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

binutils/2.18/opcodes/cr16-dis.c

    1: /* Disassembler code for CR16.
    2:    Copyright 2007 Free Software Foundation, Inc.
    3:    Contributed by M R Swami Reddy (MR.Swami.Reddy@nsc.com).
    4: 
    5:    This file is part of GAS, GDB and the GNU binutils.
    6: 
    7:    This program is free software; you can redistribute it and/or modify it
    8:    under the terms of the GNU General Public License as published by the
    9:    Free Software Foundation; either version 3, or (at your option)
   10:    any later version.
   11: 
   12:    This program is distributed in the hope that it will be useful, but WITHOUT
   13:    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14:    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   15:    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 Foundation,
   19:    Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
   20: 
   21: #include "dis-asm.h"
   22: #include "sysdep.h"
   23: #include "opcode/cr16.h"
   24: #include "libiberty.h"
   25: 
   26: /* String to print when opcode was not matched.  */
   27: #define ILLEGAL  "illegal"
   28:   /* Escape to 16-bit immediate.  */
   29: #define ESCAPE_16_BIT  0xB
   30: 
   31: /* Extract 'n_bits' from 'a' starting from offset 'offs'.  */
   32: #define EXTRACT(a, offs, n_bits)                    \
   33:   (n_bits == 32 ? (((a) >> (offs)) & 0xffffffffL)   \
   34:   : (((a) >> (offs)) & ((1 << (n_bits)) -1)))
   35: 
   36: /* Set Bit Mask - a mask to set all bits starting from offset 'offs'.  */
   37: #define SBM(offs)  ((((1 << (32 - offs)) -1) << (offs)))
   38: 
   39: typedef unsigned long dwordU;
   40: typedef unsigned short wordU;
   41: 
   42: typedef struct
   43: {
   44:   dwordU val;
   45:   int nbits;
   46: } parameter;
   47: 
   48: /* Structure to map valid 'cinv' instruction options.  */
   49: 
   50: typedef struct
   51:   {
   52:     /* Cinv printed string.  */
   53:     char *istr;
   54:     /* Value corresponding to the string.  */
   55:     char *ostr;
   56:   }
   57: cinv_entry;
   58: 
   59: /* CR16 'cinv' options mapping.  */
   60: const cinv_entry cr16_cinvs[] =
   61: {
   62:   {"cinv[i]",     "cinv    [i]"},
   63:   {"cinv[i,u]",   "cinv    [i,u]"},
   64:   {"cinv[d]",     "cinv    [d]"},
   65:   {"cinv[d,u]",   "cinv    [d,u]"},
   66:   {"cinv[d,i]",   "cinv    [d,i]"},
   67:   {"cinv[d,i,u]", "cinv    [d,i,u]"}
   68: };
   69: 
   70: /* Number of valid 'cinv' instruction options.  */
   71: static int NUMCINVS = ARRAY_SIZE (cr16_cinvs);
   72: 
   73: /* Enum to distinguish different registers argument types.  */
   74: typedef enum REG_ARG_TYPE
   75:   {
   76:     /* General purpose register (r<N>).  */
   77:     REG_ARG = 0,
   78:     /*Processor register   */
   79:     P_ARG,
   80:   }
   81: REG_ARG_TYPE;
   82: 
   83: /* Current opcode table entry we're disassembling.  */
   84: const inst *instruction;
   85: /* Current instruction we're disassembling.  */
   86: ins currInsn;
   87: /* The current instruction is read into 3 consecutive words.  */
   88: wordU words[3];
   89: /* Contains all words in appropriate order.  */
   90: ULONGLONG allWords;
   91: /* Holds the current processed argument number.  */
   92: int processing_argument_number;
   93: /* Nonzero means a IMM4 instruction.  */
   94: int imm4flag;
   95: /* Nonzero means the instruction's original size is
   96:    incremented (escape sequence is used).  */
   97: int size_changed;
   98: 
   99: 
  100: /* Print the constant expression length.  */
  101: 
  102: static char *
  103: print_exp_len (int size)
  104: {
  105:   switch (size)
  106:     {
  107:     case 4:
  108:     case 5:
  109:     case 6:
  110:     case 8:
  111:     case 14:
  112:     case 16:
  113:       return ":s";
  114:     case 20:
  115:     case 24:
  116:     case 32:
  117:       return ":m";
  118:     case 48:
  119:       return ":l";
  120:     default:
  121:       return "";
  122:     }
  123: }
  124: 
  125: 
  126: /* Retrieve the number of operands for the current assembled instruction.  */
  127: 
  128: static int
  129: get_number_of_operands (void)
  130: {
  131:   int i;
  132: 
  133:   for (i = 0; instruction->operands[i].op_type && i < MAX_OPERANDS; i++)
  134:     ;
  135: 
  136:   return i;
  137: }
  138: 
  139: /* Return the bit size for a given operand.  */
  140: 
  141: static int
  142: getbits (operand_type op)
  143: {
  144:   if (op < MAX_OPRD)
  145:     return cr16_optab[op].bit_size;
  146: 
  147:   return 0;
  148: }
  149: 
  150: /* Return the argument type of a given operand.  */
  151: 
  152: static argtype
  153: getargtype (operand_type op)
  154: {
  155:   if (op < MAX_OPRD)
  156:     return cr16_optab[op].arg_type;
  157: 
  158:   return nullargs;
  159: }
  160: 
  161: /* Given a 'CC' instruction constant operand, return its corresponding
  162:    string. This routine is used when disassembling the 'CC' instruction.  */
  163: 
  164: static char *
  165: getccstring (unsigned cc)
  166: {
  167:   return (char *) cr16_b_cond_tab[cc];
  168: }
  169: 
  170: 
  171: /* Given a 'cinv' instruction constant operand, return its corresponding
  172:    string. This routine is used when disassembling the 'cinv' instruction. */
  173: 
  174: static char *
  175: getcinvstring (const char *str)
  176: {
  177:   const cinv_entry *cinv;
  178: 
  179:   for (cinv = cr16_cinvs; cinv < (cr16_cinvs + NUMCINVS); cinv++)
  180:     if (strcmp (cinv->istr, str) == 0)
  181:       return cinv->ostr;
  182: 
  183:   return ILLEGAL;
  184: }
  185: 
  186: /* Given the trap index in dispatch table, return its name.
  187:    This routine is used when disassembling the 'excp' instruction.  */
  188: 
  189: static char *
  190: gettrapstring (unsigned int index)
  191: {
  192:   const trap_entry *trap;
  193: 
  194:   for (trap = cr16_traps; trap < cr16_traps + NUMTRAPS; trap++)
  195:     if (trap->entry == index)
  196:       return trap->name;
  197: 
  198:   return ILLEGAL;
  199: }
  200: 
  201: /* Given a register enum value, retrieve its name.  */
  202: 
  203: static char *
  204: getregname (reg r)
  205: {
  206:   const reg_entry *reg = cr16_regtab + r;
  207: 
  208:   if (reg->type != CR16_R_REGTYPE)
  209:     return ILLEGAL;
  210: 
  211:   return reg->name;
  212: }
  213: 
  214: /* Given a register pair enum value, retrieve its name.  */
  215: 
  216: static char *
  217: getregpname (reg r)
  218: {
  219:   const reg_entry *reg = cr16_regptab + r;
  220: 
  221:   if (reg->type != CR16_RP_REGTYPE)
  222:     return ILLEGAL;
  223: 
  224:   return reg->name;
  225: }
  226: 
  227: /* Given a index register pair enum value, retrieve its name.  */
  228: 
  229: static char *
  230: getidxregpname (reg r)
  231: {
  232:   const reg_entry *reg;
  233: 
  234:   switch (r)
  235:    {
  236:    case 0: r = 0; break;
  237:    case 1: r = 2; break;
  238:    case 2: r = 4; break;
  239:    case 3: r = 6; break;
  240:    case 4: r = 8; break;
  241:    case 5: r = 10; break;
  242:    case 6: r = 3; break;
  243:    case 7: r = 5; break;
  244:    default:
  245:      break;
  246:    }
  247: 
  248:   reg = cr16_regptab + r;
  249: 
  250:   if (reg->type != CR16_RP_REGTYPE)
  251:     return ILLEGAL;
  252: 
  253:   return reg->name;
  254: }
  255: 
  256: /* Getting a processor register name.  */
  257: 
  258: static char *
  259: getprocregname (int index)
  260: {
  261:   const reg_entry *r;
  262: 
  263:   for (r = cr16_pregtab; r < cr16_pregtab + NUMPREGS; r++)
  264:     if (r->image == index)
  265:       return r->name;
  266: 
  267:   return "ILLEGAL REGISTER";
  268: }
  269: 
  270: /* Getting a processor register name - 32 bit size.  */
  271: 
  272: static char *
  273: getprocpregname (int index)
  274: {
  275:   const reg_entry *r;
  276: 
  277:   for (r = cr16_pregptab; r < cr16_pregptab + NUMPREGPS; r++)
  278:     if (r->image == index)
  279:       return r->name;
  280: 
  281:   return "ILLEGAL REGISTER";
  282: }
  283: 
  284: /* START and END are relating 'allWords' struct, which is 48 bits size.
  285: 
  286:                           START|--------|END
  287:              +---------+---------+---------+---------+
  288:              |         |   V    |     A    |   L     |
  289:              +---------+---------+---------+---------+
  290:                        0         16        32        48
  291:     words                  [0]       [1]       [2]      */
  292: 
  293: static parameter
  294: makelongparameter (ULONGLONG val, int start, int end)
  295: {
  296:   parameter p;
  297: 
  298:   p.val = (dwordU) EXTRACT (val, 48 - end, end - start);
  299:   p.nbits = end - start;
  300:   return p;
  301: }
  302: 
  303: /* Build a mask of the instruction's 'constant' opcode,
  304:    based on the instruction's printing flags.  */
  305: 
  306: static unsigned long
  307: build_mask (void)
  308: {
  309:   unsigned long mask = SBM (instruction->match_bits);
  310:   return mask;
  311: }
  312: 
  313: /* Search for a matching opcode. Return 1 for success, 0 for failure.  */
  314: 
  315: static int
  316: match_opcode (void)
  317: {
  318:   unsigned long mask;
  319:   /* The instruction 'constant' opcode doewsn't exceed 32 bits.  */
  320:   unsigned long doubleWord = words[1] + (words[0] << 16);
  321: 
  322:   /* Start searching from end of instruction table.  */
  323:   instruction = &cr16_instruction[NUMOPCODES - 2];
  324: 
  325:   /* Loop over instruction table until a full match is found.  */
  326:   while (instruction >= cr16_instruction)
  327:     {
  328:       mask = build_mask ();
  329:       if ((doubleWord & mask) == BIN (instruction->match,
  330:                                       instruction->match_bits))
  331:         return 1;
  332:       else
  333:         instruction--;
  334:     }
  335:   return 0;
  336: }
  337: 
  338: /* Set the proper parameter value for different type of arguments.  */
  339: 
  340: static void
  341: make_argument (argument * a, int start_bits)
  342: {
  343:   int inst_bit_size;
  344:   parameter p;
  345: 
  346:   if ((instruction->size == 3) && a->size >= 16)
  347:     inst_bit_size = 48;
  348:   else
  349:     inst_bit_size = 32;
  350: 
  351:   switch (a->type)
  352:     {
  353:     case arg_r:
  354:       p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
  355:                              inst_bit_size - start_bits);
  356:       a->r = p.val;
  357:       break;
  358: 
  359:     case arg_rp:
  360:       p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
  361:                              inst_bit_size - start_bits);
  362:       a->rp = p.val;
  363:       break;
  364: 
  365:     case arg_pr:
  366:       p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
  367:                              inst_bit_size - start_bits);
  368:       a->pr = p.val;
  369:       break;
  370: 
  371:     case arg_prp:
  372:       p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
  373:                              inst_bit_size - start_bits);
  374:       a->prp = p.val;
  375:       break;
  376: 
  377:     case arg_ic:
  378:       p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
  379:                              inst_bit_size - start_bits);
  380:       a->constant = p.val;
  381:       break;
  382: 
  383:     case arg_cc:
  384:       p = makelongparameter (allWords, inst_bit_size - (start_bits + a->size),
  385:                              inst_bit_size - start_bits);
  386: 
  387:       a->cc = p.val;
  388:       break;
  389: 
  390:     case arg_idxr:
  391:       if ((IS_INSN_MNEMONIC ("cbitb"))
  392:           || (IS_INSN_MNEMONIC ("sbitb"))
  393:           || (IS_INSN_MNEMONIC ("tbitb")))
  394:         p = makelongparameter (allWords, 8, 9);
  395:       else
  396:         p = makelongparameter (allWords, 9, 10);
  397:       a->i_r = p.val;
  398:       p = makelongparameter (allWords, inst_bit_size - a->size, inst_bit_size);
  399:       a->constant = p.val;
  400:       break;
  401: 
  402:     case arg_idxrp:
  403:       p = makelongparameter (allWords, start_bits + 12, start_bits + 13);
  404:       a->i_r = p.val;
  405:       p = makelongparameter (allWords, start_bits + 13, start_bits + 16);
  406:       a->rp = p.val;
  407:       if (inst_bit_size > 32)
  408:         {
  409:           p = makelongparameter (allWords, inst_bit_size - start_bits - 12,
  410:                                  inst_bit_size);
  411:           a->constant = ((p.val & 0xffff) | (p.val >> 8 & 0xf0000));
  412:         }
  413:       else if (instruction->size == 2)
  414:         {
  415:           p = makelongparameter (allWords, inst_bit_size - 22, inst_bit_size);
  416:           a->constant = (p.val & 0xf) | (((p.val >>20) & 0x3) << 4)
  417:             | ((p.val >>14 & 0x3) << 6) | (((p.val >>7) & 0x1f) <<7);
  418:         }
  419:       else if (instruction->size == 1 && a->size == 0)
  420:         a->constant = 0;
  421: 
  422:       break;
  423: 
  424:     case arg_rbase:
  425:       p = makelongparameter (allWords, inst_bit_size, inst_bit_size);
  426:       a->constant = p.val;
  427:       p = makelongparameter (allWords, inst_bit_size - (start_bits + 4),
  428:                              inst_bit_size - start_bits);
  429:       a->r = p.val;
  430:       break;
  431: 
  432:     case arg_cr:
  433:       p = makelongparameter (allWords, start_bits + 12, start_bits + 16);
  434:       a->r = p.val;
  435:       p = makelongparameter (allWords, inst_bit_size - 16, inst_bit_size);
  436:       a->constant = p.val;
  437:       break;
  438: 
  439:     case arg_crp:
  440:       if (instruction->size == 1)
  441:         p = makelongparameter (allWords, 12, 16);
  442:       else
  443:         p = makelongparameter (allWords, start_bits + 12, start_bits + 16);
  444:       a->rp = p.val;
  445: 
  446:       if (inst_bit_size > 32)
  447:         {
  448:           p = makelongparameter (allWords, inst_bit_size - start_bits - 12,
  449:                                  inst_bit_size);
  450:           a->constant = ((p.val & 0xffff) | (p.val >> 8 & 0xf0000));
  451:         }
  452:       else if (instruction->size == 2)
  453:         {
  454:           p = makelongparameter (allWords, inst_bit_size - 16, inst_bit_size);
  455:           a->constant = p.val;
  456:         }
  457:       else if (instruction->size == 1 && a->size != 0)
  458:         {
  459:           p = makelongparameter (allWords, 4, 8);
  460:           if (IS_INSN_MNEMONIC ("loadw")
  461:               || IS_INSN_MNEMONIC ("loadd")
  462:               || IS_INSN_MNEMONIC ("storw")
  463:               || IS_INSN_MNEMONIC ("stord"))
  464:             a->constant = (p.val * 2);
  465:           else
  466:             a->constant = p.val;
  467:         }
  468:       else /* below case for 0x0(reg pair) */
  469:         a->constant = 0;
  470: 
  471:       break;
  472: 
  473:     case arg_c:
  474: 
  475:       if ((IS_INSN_TYPE (BRANCH_INS))
  476:           || (IS_INSN_MNEMONIC ("bal"))
  477:           || (IS_INSN_TYPE (CSTBIT_INS))
  478:           || (IS_INSN_TYPE (LD_STOR_INS)))
  479:         {
  480:           switch (a->size)
  481:             {
  482:             case 8 :
  483:               p = makelongparameter (allWords, 0, start_bits);
  484:               a->constant = ((((p.val&0xf00)>>4)) | (p.val&0xf));
  485:               break;
  486: 
  487:             case 24:
  488:               if (instruction->size == 3)
  489:                 {
  490:                   p = makelongparameter (allWords, 16, inst_bit_size);
  491:                   a->constant = ((((p.val>>16)&0xf) << 20)
  492:                                  | (((p.val>>24)&0xf) << 16)
  493:                                  | (p.val & 0xffff));
  494:                 }
  495:               else if (instruction->size == 2)
  496:                 {
  497:                   p = makelongparameter (allWords, 8, inst_bit_size);
  498:                   a->constant = p.val;
  499:                 }
  500:               break;
  501: 
  502:             default:
  503:               p = makelongparameter (allWords, inst_bit_size - (start_bits +
  504:                                                                 a->size), inst_bit_size - start_bits);
  505:               a->constant = p.val;
  506:               break;
  507:             }
  508:         }
  509:       else
  510:         {
  511:           p = makelongparameter (allWords, inst_bit_size -
  512:                                  (start_bits + a->size),
  513:                                  inst_bit_size - start_bits);
  514:           a->constant = p.val;
  515:         }
  516:       break;
  517: 
  518:     default:
  519:       break;
  520:     }
  521: }
  522: 
  523: /*  Print a single argument.  */
  524: 
  525: static void
  526: print_arg (argument *a, bfd_vma memaddr, struct disassemble_info *info)
  527: {
  528:   LONGLONG longdisp, mask;
  529:   int sign_flag = 0;
  530:   int relative = 0;
  531:   bfd_vma number;
  532:   PTR stream = info->stream;
  533:   fprintf_ftype func = info->fprintf_func;
  534: 
  535:   switch (a->type)
  536:     {
  537:     case arg_r:
  538:       func (stream, "%s", getregname (a->r));
  539:       break;
  540: 
  541:     case arg_rp:
  542:       func (stream, "%s", getregpname (a->rp));
  543:       break;
  544: 
  545:     case arg_pr:
  546:       func (stream, "%s", getprocregname (a->pr));
  547:       break;
  548: 
  549:     case arg_prp:
  550:       func (stream, "%s", getprocpregname (a->prp));
  551:       break;
  552: 
  553:     case arg_cc:
  554:       func (stream, "%s", getccstring (a->cc));
  555:       func (stream, "%s", "\t");
  556:       break;
  557: 
  558:     case arg_ic:
  559:       if (IS_INSN_MNEMONIC ("excp"))
  560:         {
  561:           func (stream, "%s", gettrapstring (a->constant));
  562:           break;
  563:         }
  564:       else if ((IS_INSN_TYPE (ARITH_INS) || IS_INSN_TYPE (ARITH_BYTE_INS))
  565:                && ((instruction->size == 1) && (a->constant == 9)))
  566:         func (stream, "$%d", -1);
  567:       else if (INST_HAS_REG_LIST)
  568:         func (stream, "$0x%lx", a->constant +1);
  569:       else if (IS_INSN_TYPE (SHIFT_INS))
  570:         {
  571:           longdisp = a->constant;
  572:           mask = ((LONGLONG)1 << a->size) - 1;
  573:           if (longdisp & ((LONGLONG)1 << (a->size -1)))
  574:             {
  575:               sign_flag = 1;
  576:               longdisp = ~(longdisp) + 1;
  577:             }
  578:           a->constant = (unsigned long int) (longdisp & mask);
  579:           func (stream, "$%d", ((int)(sign_flag ? -a->constant :
  580:                                       a->constant)));
  581:         }
  582:       else
  583: