(linenum→info "unix/slp.c:2238")

binutils/2.18/opcodes/d10v-dis.c

    1: /* Disassemble D10V instructions.
    2:    Copyright 1996, 1997, 1998, 2000, 2001, 2005, 2007
    3:    Free Software Foundation, Inc.
    4: 
    5:    This file is part of the GNU opcodes library.
    6: 
    7:    This library is free software; you can redistribute it and/or modify
    8:    it under the terms of the GNU General Public License as published by
    9:    the Free Software Foundation; either version 3, or (at your option)
   10:    any later version.
   11: 
   12:    It is distributed in the hope that it will be useful, but WITHOUT
   13:    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   14:    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
   15:    License for more details.
   16: 
   17:    You should have received a copy of the GNU General Public License
   18:    along with this program; if not, write to the Free Software
   19:    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
   20:    MA 02110-1301, USA.  */
   21: 
   22: #include <stdio.h>
   23: 
   24: #include "sysdep.h"
   25: #include "opcode/d10v.h"
   26: #include "dis-asm.h"
   27: 
   28: /* The PC wraps at 18 bits, except for the segment number,
   29:    so use this mask to keep the parts we want.  */
   30: #define PC_MASK 0x0303FFFF
   31: 
   32: static void
   33: print_operand (struct d10v_operand *oper,
   34:                unsigned long insn,
   35:                struct d10v_opcode *op,
   36:                bfd_vma memaddr,
   37:                struct disassemble_info *info)
   38: {
   39:   int num, shift;
   40: 
   41:   if (oper->flags == OPERAND_ATMINUS)
   42:     {
   43:       (*info->fprintf_func) (info->stream, "@-");
   44:       return;
   45:     }
   46:   if (oper->flags == OPERAND_MINUS)
   47:     {
   48:       (*info->fprintf_func) (info->stream, "-");
   49:       return;
   50:     }
   51:   if (oper->flags == OPERAND_PLUS)
   52:     {
   53:       (*info->fprintf_func) (info->stream, "+");
   54:       return;
   55:     }
   56:   if (oper->flags == OPERAND_ATSIGN)
   57:     {
   58:       (*info->fprintf_func) (info->stream, "@");
   59:       return;
   60:     }
   61:   if (oper->flags == OPERAND_ATPAR)
   62:     {
   63:       (*info->fprintf_func) (info->stream, "@(");
   64:       return;
   65:     }
   66: 
   67:   shift = oper->shift;
   68: 
   69:   /* The LONG_L format shifts registers over by 15.  */
   70:   if (op->format == LONG_L && (oper->flags & OPERAND_REG))
   71:     shift += 15;
   72: 
   73:   num = (insn >> shift) & (0x7FFFFFFF >> (31 - oper->bits));
   74: 
   75:   if (oper->flags & OPERAND_REG)
   76:     {
   77:       int i;
   78:       int match = 0;
   79: 
   80:       num += (oper->flags
   81:               & (OPERAND_GPR | OPERAND_FFLAG | OPERAND_CFLAG | OPERAND_CONTROL));
   82:       if (oper->flags & (OPERAND_ACC0 | OPERAND_ACC1))
   83:         num += num ? OPERAND_ACC1 : OPERAND_ACC0;
   84:       for (i = 0; i < d10v_reg_name_cnt (); i++)
   85:         {
   86:           if (num == (d10v_predefined_registers[i].value & ~ OPERAND_SP))
   87:             {
   88:               if (d10v_predefined_registers[i].pname)
   89:                 (*info->fprintf_func) (info->stream, "%s",
   90:                                        d10v_predefined_registers[i].pname);
   91:               else
   92:                 (*info->fprintf_func) (info->stream, "%s",
   93:                                        d10v_predefined_registers[i].name);
   94:               match = 1;
   95:               break;
   96:             }
   97:         }
   98:       if (match == 0)
   99:         {
  100:           /* This would only get executed if a register was not in the
  101:              register table.  */
  102:           if (oper->flags & (OPERAND_ACC0 | OPERAND_ACC1))
  103:             (*info->fprintf_func) (info->stream, "a");
  104:           else if (oper->flags & OPERAND_CONTROL)
  105:             (*info->fprintf_func) (info->stream, "cr");
  106:           else if (oper->flags & OPERAND_REG)
  107:             (*info->fprintf_func) (info->stream, "r");
  108:           (*info->fprintf_func) (info->stream, "%d", num & REGISTER_MASK);
  109:         }
  110:     }
  111:   else
  112:     {
  113:       /* Addresses are right-shifted by 2.  */
  114:       if (oper->flags & OPERAND_ADDR)
  115:         {
  116:           long max;
  117:           int neg = 0;
  118: 
  119:           max = (1 << (oper->bits - 1));
  120:           if (num & max)
  121:             {
  122:               num = -num & ((1 << oper->bits) - 1);
  123:               neg = 1;
  124:             }
  125:           num = num << 2;
  126:           if (info->flags & INSN_HAS_RELOC)
  127:             (*info->print_address_func) (num & PC_MASK, info);
  128:           else
  129:             {
  130:               if (neg)
  131:                 (*info->print_address_func) ((memaddr - num) & PC_MASK, info);
  132:               else
  133:                 (*info->print_address_func) ((memaddr + num) & PC_MASK, info);
  134:             }
  135:         }
  136:       else
  137:         {
  138:           if (oper->flags & OPERAND_SIGNED)
  139:             {
  140:               int max = (1 << (oper->bits - 1));
  141:               if (num & max)
  142:                 {
  143:                   num = -num & ((1 << oper->bits) - 1);
  144:                   (*info->fprintf_func) (info->stream, "-");
  145:                 }
  146:             }
  147:           (*info->fprintf_func) (info->stream, "0x%x", num);
  148:         }
  149:     }
  150: }
  151: 
  152: static void
  153: dis_long (unsigned long insn,
  154:           bfd_vma memaddr,
  155:           struct disassemble_info *info)
  156: {
  157:   int i;
  158:   struct d10v_opcode *op = (struct d10v_opcode *) d10v_opcodes;
  159:   struct d10v_operand *oper;
  160:   int need_paren = 0;
  161:   int match = 0;
  162: 
  163:   while (op->name)
  164:     {
  165:       if ((op->format & LONG_OPCODE)
  166:           && ((op->mask & insn) == (unsigned long) op->opcode))
  167:         {
  168:           match = 1;
  169:           (*info->fprintf_func) (info->stream, "%s\t", op->name);
  170: 
  171:           for (i = 0; op->operands[i]; i++)
  172:             {
  173:               oper = (struct d10v_operand *) &d10v_operands[op->operands[i]];
  174:               if (oper->flags == OPERAND_ATPAR)
  175:                 need_paren = 1;
  176:               print_operand (oper, insn, op, memaddr, info);
  177:               if (op->operands[i + 1] && oper->bits
  178:                   && d10v_operands[op->operands[i + 1]].flags != OPERAND_PLUS
  179:                   && d10v_operands[op->operands[i + 1]].flags != OPERAND_MINUS)
  180:                 (*info->fprintf_func) (info->stream, ", ");
  181:             }
  182:           break;
  183:         }
  184:       op++;
  185:     }
  186: 
  187:   if (!match)
  188:     (*info->fprintf_func) (info->stream, ".long\t0x%08lx", insn);
  189: 
  190:   if (need_paren)
  191:     (*info->fprintf_func) (info->stream, ")");
  192: }
  193: 
  194: static void
  195: dis_2_short (unsigned long insn,
  196:              bfd_vma memaddr,
  197:              struct disassemble_info *info,
  198:              int order)
  199: {
  200:   int i, j;
  201:   unsigned int ins[2];
  202:   struct d10v_opcode *op;
  203:   int match, num_match = 0;
  204:   struct d10v_operand *oper;
  205:   int need_paren = 0;
  206: 
  207:   ins[0] = (insn & 0x3FFFFFFF) >> 15;
  208:   ins[1] = insn & 0x00007FFF;
  209: 
  210:   for (j = 0; j < 2; j++)
  211:     {
  212:       op = (struct d10v_opcode *) d10v_opcodes;
  213:       match = 0;
  214:       while (op->name)
  215:         {
  216:           if ((op->format & SHORT_OPCODE)
  217:               && ((((unsigned int) op->mask) & ins[j])
  218:                   == (unsigned int) op->opcode))
  219:             {
  220:               (*info->fprintf_func) (info->stream, "%s\t", op->name);
  221:               for (i = 0; op->operands[i]; i++)
  222:                 {
  223:                   oper = (struct d10v_operand *) &d10v_operands[op->operands[i]];
  224:                   if (oper->flags == OPERAND_ATPAR)
  225:                     need_paren = 1;
  226:                   print_operand (oper, ins[j], op, memaddr, info);
  227:                   if (op->operands[i + 1] && oper->bits
  228:                       && d10v_operands[op->operands[i + 1]].flags != OPERAND_PLUS
  229:                       && d10v_operands[op->operands[i + 1]].flags != OPERAND_MINUS)
  230:                     (*info->fprintf_func) (info->stream, ", ");
  231:                 }
  232:               match = 1;
  233:               num_match++;
  234:               break;
  235:             }
  236:           op++;
  237:         }
  238:       if (!match)
  239:         (*info->fprintf_func) (info->stream, "unknown");
  240: 
  241:       switch (order)
  242:         {
  243:         case 0:
  244:           (*info->fprintf_func) (info->stream, "\t->\t");
  245:           order = -1;
  246:           break;
  247:         case 1:
  248:           (*info->fprintf_func) (info->stream, "\t<-\t");
  249:           order = -1;
  250:           break;
  251:         case 2:
  252:           (*info->fprintf_func) (info->stream, "\t||\t");
  253:           order = -1;
  254:           break;
  255:         default:
  256:           break;
  257:         }
  258:     }
  259: 
  260:   if (num_match == 0)
  261:     (*info->fprintf_func) (info->stream, ".long\t0x%08lx", insn);
  262: 
  263:   if (need_paren)
  264:     (*info->fprintf_func) (info->stream, ")");
  265: }
  266: 
  267: int
  268: print_insn_d10v (bfd_vma memaddr, struct disassemble_info *info)
  269: {
  270:   int status;
  271:   bfd_byte buffer[4];
  272:   unsigned long insn;
  273: 
  274:   status = (*info->read_memory_func) (memaddr, buffer, 4, info);
  275:   if (status != 0)
  276:     {
  277:       (*info->memory_error_func) (status, memaddr, info);
  278:       return -1;
  279:     }
  280:   insn = bfd_getb32 (buffer);
  281: 
  282:   status = insn & FM11;
  283:   switch (status)
  284:     {
  285:     case 0:
  286:       dis_2_short (insn, memaddr, info, 2);
  287:       break;
  288:     case FM01:
  289:       dis_2_short (insn, memaddr, info, 0);
  290:       break;
  291:     case FM10:
  292:       dis_2_short (insn, memaddr, info, 1);
  293:       break;
  294:     case FM11:
  295:       dis_long (insn, memaddr, info);
  296:       break;
  297:     }
  298:   return 4;
  299: }
Syntax (Markdown)