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

binutils/2.18/opcodes/i960-dis.c

    1: /* Disassemble i80960 instructions.
    2:    Copyright 1990, 1991, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2003,
    3:    2007  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; see the file COPYING.  If not, write to the
   19:    Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
   20:    02110-1301, USA.  */
   21: 
   22: #include "sysdep.h"
   23: #include "dis-asm.h"
   24: 
   25: static const char *const reg_names[] = {
   26: /*  0 */        "pfp", "sp",  "rip", "r3",  "r4",  "r5",  "r6",  "r7",
   27: /*  8 */        "r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
   28: /* 16 */        "g0",  "g1",  "g2",  "g3",  "g4",  "g5",  "g6",  "g7",
   29: /* 24 */        "g8",  "g9",  "g10", "g11", "g12", "g13", "g14", "fp",
   30: /* 32 */        "pc",  "ac",  "ip",  "tc",  "fp0", "fp1", "fp2", "fp3"
   31: };
   32: 
   33: 
   34: static FILE *stream;            /* Output goes here */
   35: static struct disassemble_info *info;
   36: static void print_addr (bfd_vma);
   37: static void ctrl (bfd_vma, unsigned long, unsigned long);
   38: static void cobr (bfd_vma, unsigned long, unsigned long);
   39: static void reg (unsigned long);
   40: static int mem (bfd_vma, unsigned long, unsigned long, int);
   41: static void ea (bfd_vma, int, const char *, const char *, int, unsigned int);
   42: static void dstop (int, int, int);
   43: static void regop (int, int, int, int);
   44: static void invalid (int);
   45: static int pinsn (bfd_vma, unsigned long, unsigned long);
   46: static void put_abs (unsigned long, unsigned long);
   47: 
   48: 
   49: /* Print the i960 instruction at address 'memaddr' in debugged memory,
   50:    on INFO->STREAM.  Returns length of the instruction, in bytes.  */
   51: 
   52: int
   53: print_insn_i960 (bfd_vma memaddr, struct disassemble_info *info_arg)
   54: {
   55:   unsigned int word1, word2 = 0xdeadbeef;
   56:   bfd_byte buffer[8];
   57:   int status;
   58: 
   59:   info = info_arg;
   60:   stream = info->stream;
   61: 
   62:   /* Read word1.  Only read word2 if the instruction
   63:      needs it, to prevent reading past the end of a section.  */
   64: 
   65:   status = (*info->read_memory_func) (memaddr, (bfd_byte *) buffer, 4, info);
   66:   if (status != 0)
   67:     {
   68:       (*info->memory_error_func) (status, memaddr, info);
   69:       return -1;
   70:     }
   71: 
   72:   word1 = bfd_getl32 (buffer);
   73: 
   74:   /* Divide instruction set into classes based on high 4 bits of opcode.  */
   75:   switch ( (word1 >> 28) & 0xf )
   76:     {
   77:     default:
   78:       break;
   79:     case 0x8:
   80:     case 0x9:
   81:     case 0xa:
   82:     case 0xb:
   83:     case 0xc:
   84:       /* Read word2.  */
   85:       status = (*info->read_memory_func)
   86:         (memaddr + 4, (bfd_byte *) (buffer + 4), 4, info);
   87:       if (status != 0)
   88:         {
   89:           (*info->memory_error_func) (status, memaddr, info);
   90:           return -1;
   91:         }
   92:       word2 = bfd_getl32 (buffer + 4);
   93:       break;
   94:     }
   95: 
   96:   return pinsn( memaddr, word1, word2 );
   97: }
   98: ^L
   99: #define IN_GDB
  100: 
  101: /*****************************************************************************
  102:  *      All code below this point should be identical with that of
  103:  *      the disassembler in gdmp960.
  104: 
  105:  A noble sentiment, but at least in cosmetic ways (info->fprintf_func), it
  106:  just ain't so. -kingdon, 31 Mar 93
  107:  *****************************************************************************/
  108: 
  109: struct tabent {
  110:   char *name;
  111:   short numops;
  112: };
  113: 
  114: struct sparse_tabent {
  115:   int opcode;
  116:   char *name;
  117:   short numops;
  118: };
  119: 
  120: static int
  121: pinsn (bfd_vma memaddr, unsigned long word1, unsigned long word2)
  122: {
  123:   int instr_len;
  124: 
  125:   instr_len = 4;
  126:   put_abs (word1, word2);
  127: 
  128:   /* Divide instruction set into classes based on high 4 bits of opcode.  */
  129:   switch ((word1 >> 28) & 0xf)
  130:     {
  131:     case 0x0:
  132:     case 0x1:
  133:       ctrl (memaddr, word1, word2);
  134:       break;
  135:     case 0x2:
  136:     case 0x3:
  137:       cobr (memaddr, word1, word2);
  138:       break;
  139:     case 0x5:
  140:     case 0x6:
  141:     case 0x7:
  142:       reg (word1);
  143:       break;
  144:     case 0x8:
  145:     case 0x9:
  146:     case 0xa:
  147:     case 0xb:
  148:     case 0xc:
  149:       instr_len = mem (memaddr, word1, word2, 0);
  150:       break;
  151:     default:
  152:       /* Invalid instruction, print as data word.  */
  153:       invalid (word1);
  154:       break;
  155:     }
  156:   return instr_len;
  157: }
  158: 
  159: /* CTRL format.. */
  160: 
  161: static void
  162: ctrl (bfd_vma memaddr, unsigned long word1, unsigned long word2 ATTRIBUTE_UNUSED)
  163: {
  164:   int i;
  165:   static const struct tabent ctrl_tab[] = {
  166:     { NULL,             0, },      /* 0x00 */
  167:     { NULL,             0, },      /* 0x01 */
  168:     { NULL,             0, },      /* 0x02 */
  169:     { NULL,             0, },      /* 0x03 */
  170:     { NULL,             0, },      /* 0x04 */
  171:     { NULL,             0, },      /* 0x05 */
  172:     { NULL,             0, },      /* 0x06 */
  173:     { NULL,             0, },      /* 0x07 */
  174:     { "b",              1, },       /* 0x08 */
  175:     { "call",           1, },    /* 0x09 */
  176:     { "ret",            0, },     /* 0x0a */
  177:     { "bal",            1, },     /* 0x0b */
  178:     { NULL,             0, },      /* 0x0c */
  179:     { NULL,             0, },      /* 0x0d */
  180:     { NULL,             0, },      /* 0x0e */
  181:     { NULL,             0, },      /* 0x0f */
  182:     { "bno",            1, },     /* 0x10 */
  183:     { "bg",             1, },      /* 0x11 */
  184:     { "be",             1, },      /* 0x12 */
  185:     { "bge",            1, },     /* 0x13 */
  186:     { "bl",             1, },      /* 0x14 */
  187:     { "bne",            1, },     /* 0x15 */
  188:     { "ble",            1, },     /* 0x16 */
  189:     { "bo",             1, },      /* 0x17 */
  190:     { "faultno",        0, },  /* 0x18 */
  191:     { "faultg",         0, },  /* 0x19 */
  192:     { "faulte",         0, },  /* 0x1a */
  193:     { "faultge",        0, },  /* 0x1b */
  194:     { "faultl",         0, },  /* 0x1c */
  195:     { "faultne",        0, },  /* 0x1d */
  196:     { "faultle",        0, },  /* 0x1e */
  197:     { "faulto",         0, },  /* 0x1f */
  198:   };
  199: 
  200:   i = (word1 >> 24) & 0xff;
  201:   if ((ctrl_tab[i].name == NULL) || ((word1 & 1) != 0))
  202:     {
  203:       invalid (word1);
  204:       return;
  205:     }
  206: 
  207:   (*info->fprintf_func) (stream, ctrl_tab[i].name);
  208:   if (word1 & 2)
  209:     /* Predicts branch not taken.  */
  210:     (*info->fprintf_func) (stream, ".f");
  211: 
  212:   if (ctrl_tab[i].numops == 1)
  213:     {
  214:       /* Extract displacement and convert to address.  */
  215:       word1 &= 0x00ffffff;
  216: 
  217:       if (word1 & 0x00800000)
  218:         {
  219:           /* Sign bit is set.  */
  220:           word1 |= (-1 & ~0xffffff);   /* Sign extend.  */
  221:         }
  222: 
  223:       (*info->fprintf_func) (stream, "\t");
  224:       print_addr (word1 + memaddr);
  225:     }
  226: }
  227: 
  228: /* COBR format.  */
  229: 
  230: static void
  231: cobr (bfd_vma memaddr, unsigned long word1, unsigned long word2 ATTRIBUTE_UNUSED)
  232: {
  233:   int src1;
  234:   int src2;
  235:   int i;
  236: 
  237:   static const struct tabent cobr_tab[] = {
  238:     { "testno", 1, },   /* 0x20 */
  239:     { "testg",  1, },    /* 0x21 */
  240:     { "teste",  1, },    /* 0x22 */
  241:     { "testge", 1, },   /* 0x23 */
  242:     { "testl",  1, },    /* 0x24 */
  243:     { "testne", 1, },   /* 0x25 */
  244:     { "testle", 1, },   /* 0x26 */
  245:     { "testo",  1, },    /* 0x27 */
  246:     { NULL,     0, },       /* 0x28 */
  247:     { NULL,     0, },       /* 0x29 */
  248:     { NULL,     0, },       /* 0x2a */
  249:     { NULL,     0, },       /* 0x2b */
  250:     { NULL,     0, },       /* 0x2c */
  251:     { NULL,     0, },       /* 0x2d */
  252:     { NULL,     0, },       /* 0x2e */
  253:     { NULL,     0, },       /* 0x2f */
  254:     { "bbc",    3, },      /* 0x30 */
  255:     { "cmpobg", 3, },   /* 0x31 */
  256:     { "cmpobe", 3, },   /* 0x32 */
  257:     { "cmpobge",3, },   /* 0x33 */
  258:     { "cmpobl", 3, },   /* 0x34 */
  259:     { "cmpobne",3, },   /* 0x35 */
  260:     { "cmpoble",3, },   /* 0x36 */
  261:     { "bbs",    3, },      /* 0x37 */
  262:     { "cmpibno",3, },   /* 0x38 */
  263:     { "cmpibg", 3, },   /* 0x39 */
  264:     { "cmpibe", 3, },   /* 0x3a */
  265:     { "cmpibge",3, },   /* 0x3b */
  266:     { "cmpibl", 3, },   /* 0x3c */
  267:     { "cmpibne",3, },   /* 0x3d */
  268:     { "cmpible",3, },   /* 0x3e */
  269:     { "cmpibo", 3, },   /* 0x3f */
  270:   };
  271: 
  272:   i = ((word1 >> 24) & 0xff) - 0x20;
  273:   if (cobr_tab[i].name == NULL)
  274:     {
  275:       invalid (word1);
  276:       return;
  277:     }
  278: 
  279:   (*info->fprintf_func) (stream, cobr_tab[i].name);
  280: 
  281:   /* Predicts branch not taken.  */
  282:   if (word1 & 2)
  283:     (*info->fprintf_func) (stream, ".f");
  284: 
  285:   (*info->fprintf_func) (stream, "\t");
  286: 
  287:   src1 = (word1 >> 19) & 0x1f;
  288:   src2 = (word1 >> 14) & 0x1f;
  289: 
  290:   if (word1 & 0x02000)
  291:     /* M1 is 1 */
  292:     (*info->fprintf_func) (stream, "%d", src1);
  293:   else
  294:     (*info->fprintf_func) (stream, reg_names[src1]);
  295: 
  296:   if (cobr_tab[i].numops > 1)
  297:     {
  298:       if (word1 & 1)
  299:         /* S2 is 1.  */
  300:         (*info->fprintf_func) (stream, ",sf%d,", src2);
  301:       else
  302:         /* S1 is 0.  */
  303:         (*info->fprintf_func) (stream, ",%s,", reg_names[src2]);
  304: 
  305:       /* Extract displacement and convert to address.  */
  306:       word1 &= 0x00001ffc;
  307:       if (word1 & 0x00001000)
  308:         /* Negative displacement.  */
  309:         word1 |= (-1 & ~0x1fff);       /* Sign extend.  */
  310: 
  311:       print_addr (memaddr + word1);
  312:     }
  313: }
  314: 
  315: /* MEM format.  */
  316: /* Returns instruction length: 4 or 8.  */
  317: 
  318: static int
  319: mem (bfd_vma memaddr, unsigned long word1, unsigned long word2, int noprint)
  320: {
  321:   int i, j;
  322:   int len;
  323:   int mode;
  324:   int offset;
  325:   const char *reg1, *reg2, *reg3;
  326: 
  327:   /* This lookup table is too sparse to make it worth typing in, but not
  328:      so large as to make a sparse array necessary.  We create the table
  329:      at runtime.  */
  330: 
  331:   /* NOTE: In this table, the meaning of 'numops' is:
  332:       1: single operand
  333:       2: 2 operands, load instruction
  334:      -2: 2 operands, store instruction.  */
  335:   static struct tabent *mem_tab;
  336:   /* Opcodes of 0x8X, 9X, aX, bX, and cX must be in the table.  */
  337: #define MEM_MIN 0x80
  338: #define MEM_MAX 0xcf
  339: #define MEM_SIZ ( * sizeof(struct tabent))
  340: 
  341:   static const struct sparse_tabent mem_init[] = {
  342:     { 0x80,     "ldob",      2 },
  343:     { 0x82,     "stob",     -2 },
  344:     { 0x84,     "bx",        1 },
  345:     { 0x85,     "balx",      2 },
  346:     { 0x86,     "callx", 1 },
  347:     { 0x88,     "ldos",      2 },
  348:     { 0x8a,     "stos",     -2 },
  349:     { 0x8c,     "lda",       2 },
  350:     { 0x90,     "ld",        2 },
  351:     { 0x92,     "st",       -2 },
  352:     { 0x98,     "ldl",       2 },
  353:     { 0x9a,     "stl",      -2 },
  354:     { 0xa0,     "ldt",       2 },
  355:     { 0xa2,     "stt",      -2 },
  356:     { 0xac,     "dcinva", 1 },
  357:     { 0xb0,     "ldq",       2 },
  358:     { 0xb2,     "stq",      -2 },
  359:     { 0xc0,     "ldib",      2 },
  360:     { 0xc2,     "stib",     -2 },
  361:     { 0xc8,     "ldis",      2 },
  362:     { 0xca,     "stis",     -2 },
  363:     { 0,        NULL,  0 }
  364:   };
  365:   static struct tabent mem_tab_buf[MEM_MAX - MEM_MIN + 1];
  366: 
  367:   if (mem_tab == NULL)
  368:     {
  369:       mem_tab = mem_tab_buf;
  370: 
  371:       for (i = 0; mem_init[i].opcode != 0; i++)
  372:         {
  373:           j = mem_init[i].opcode - MEM_MIN;
  374:           mem_tab[j].name = mem_init[i].name;
  375:           mem_tab[j].numops = mem_init[i].numops;
  376:         }
  377:     }
  378: 
  379:   i = ((word1 >> 24) & 0xff) - MEM_MIN;
  380:   mode = (word1 >> 10) & 0xf;
  381: 
  382:   if ((mem_tab[i].name != NULL)         /* Valid instruction */
  383:       && ((mode == 5) || (mode >= 12)))
  384:     /* With 32-bit displacement.  */
  385:     len = 8;
  386:   else
  387:     len = 4;
  388: 
  389:   if (noprint)
  390:     return len;
  391: 
  392:   if ((mem_tab[i].name == NULL) || (mode == 6))
  393:     {
  394:       invalid (word1);
  395:       return len;
  396:     }
  397: 
  398:   (*info->fprintf_func) (stream, "%s\t", mem_tab[i].name);
  399: 
  400:   reg1 = reg_names[ (word1 >> 19) & 0x1f ];     /* MEMB only */
  401:   reg2 = reg_names[ (word1 >> 14) & 0x1f ];
  402:   reg3 = reg_names[ word1 & 0x1f ];             /* MEMB only */
  403:   offset = word1 & 0xfff;                               /* MEMA only  */
  404: 
  405:   switch (mem_tab[i].numops)
  406:     {
  407:     case 2: /* LOAD INSTRUCTION */
  408:       if (mode & 4)
  409:         {                      /* MEMB FORMAT */
  410:           ea (memaddr, mode, reg2, reg3, word1, word2);
  411:           (*info->fprintf_func) (stream, ",%s", reg1);
  412:         }
  413:       else
  414:         {                              /* MEMA FORMAT */
  415:           (*info->fprintf_func) (stream, "0x%x", (unsigned) offset);
  416: 
  417:           if (mode & 8)
  418:             (*info->fprintf_func) (stream, "(%s)", reg2);
  419: 
  420:           (*info->fprintf_func)(stream, ",%s", reg1);
  421:         }
  422:       break;
  423: 
  424:     case -2: /* STORE INSTRUCTION */
  425:       if (mode & 4)
  426:         {
  427:           /* MEMB FORMAT */
  428:           (*info->fprintf_func) (stream, "%s,", reg1);
  429:           ea (memaddr, mode, reg2, reg3, word1, word2);
  430:         }
  431:       else
  432:         {
  433:           /* MEMA FORMAT */
  434:           (*info->fprintf_func) (stream, "%s,0x%x", reg1, (unsigned) offset);
  435: 
  436:           if (mode & 8)
  437:             (*info->fprintf_func) (stream, "(%s)", reg2);
  438:         }
  439:       break;
  440: 
  441:     case 1: /* BX/CALLX INSTRUCTION */
  442:       if (mode & 4)
  443:         {
  444:           /* MEMB FORMAT */
  445:           ea (memaddr, mode, reg2, reg3, word1, word2);
  446:         }
  447:       else
  448:         {
  449:           /* MEMA FORMAT */
  450:           (*info->fprintf_func) (stream, "0x%x", (unsigned) offset);
  451:           if (mode & 8)
  452:             (*info->fprintf_func) (stream, "(%s)", reg2);
  453:         }
  454:       break;
  455:     }
  456: 
  457:   return len;
  458: }
  459: 
  460: /* REG format.  */
  461: 
  462: static void
  463: reg (unsigned long word1)
  464: {
  465:   int i, j;
  466:   int opcode;
  467:   int fp;
  468:   int m1, m2, m3;
  469:   int s1, s2;
  470:   int src, src2, dst;
  471:   char *mnemp;
  472: 
  473:   /* This lookup table is too sparse to make it worth typing in, but not
  474:      so large as to make a sparse array necessary.  We create the table
  475:      at runtime.  */
  476: 
  477:   /* NOTE: In this table, the meaning of 'numops' is:
  478:          1: single operand, which is NOT a destination.
  479:         -1: single operand, which IS a destination.
  480:          2: 2 operands, the 2nd of which is NOT a destination.
  481:         -2: 2 operands, the 2nd of which IS a destination.
  482:          3: 3 operands
  483: 
  484:         If an opcode mnemonic begins with "F", it is a floating-point
  485:         opcode (the "F" is not printed).  */
  486: 
  487:   static struct tabent *reg_tab;
  488:   static const struct sparse_tabent reg_init[] =
  489:   {
  490: #define REG_MIN 0x580
  491:     { 0x580,    "notbit",  3 },
  492:     { 0x581,    "and",             3 },
  493:     { 0x582,    "andnot",  3 },
  494:     { 0x583,    "setbit",  3 },
  495:     { 0x584,    "notand",  3 },
  496:     { 0x586,    "xor",             3 },
  497:     { 0x587,    "or",              3 },
  498:     { 0x588,    "nor",             3 },
  499:     { 0x589,    "xnor",            3 },
  500:     { 0x58a,    "not",             -2 },
  501:     { 0x58b,    "ornot",   3 },
  502:     { 0x58c,    "clrbit",  3 },
  503:     { 0x58d,    "notor",   3 },
  504:     { 0x58e,    "nand",            3 },
  505:     { 0x58f,    "alterbit",        3 },
  506:     { 0x590,    "addo",            3 },
  507:     { 0x591,    "addi",            3 },
  508:     { 0x592,    "subo",            3 },
  509:     { 0x593,    "subi",            3 },
  510:     { 0x594,    "cmpob",   2 },
  511:     { 0x595,    "cmpib",   2 },
  512:     { 0x596,    "cmpos",   2 },
  513:     { 0x597,    "cmpis",   2 },
  514:     { 0x598,    "shro",            3 },
  515:     { 0x59a,    "shrdi",   3 },
  516:     { 0x59b,    "shri",            3 },
  517:     { 0x59c,    "shlo",            3 },
  518:     { 0x59d,    "rotate",  3 },
  519:     { 0x59e,    "shli",            3 },
  520:     { 0x5a0,    "cmpo",            2 },
  521:     { 0x5a1,    "cmpi",            2 },
  522:     { 0x5a2,    "concmpo", 2 },
  523:     { 0x5a3,    "concmpi", 2 },
  524:     { 0x5a4,    "cmpinco", 3 },
  525:     { 0x5a5,    "cmpinci", 3 },
  526:     { 0x5a6,    "cmpdeco", 3 },
  527:     { 0x5a7,    "cmpdeci", 3 },
  528:     { 0x5ac,    "scanbyte",        2 },
  529:     { 0x5ad,    "bswap",   -2 },
  530:     { 0x5ae,    "chkbit",  2 },
  531:     { 0x5b0,    "addc",            3 },
  532:     { 0x5b2,    "subc",            3 },
  533:     { 0x5b4,    "intdis",  0 },
  534:     { 0x5b5,    "inten",   0 },
  535:     { 0x5cc,    "mov",             -2 },
  536:     { 0x5d8,    "eshro",   3 },
  537:     { 0x5dc,    "movl",            -2 },
  538:     { 0x5ec,    "movt",            -2 },
  539:     { 0x5fc,    "movq",            -2 },
  540:     { 0x600,    "synmov",  2 },
  541:     { 0x601,    "synmovl", 2 },
  542:     { 0x602,    "synmovq", 2 },
  543:     { 0x603,    "cmpstr",  3 },
  544:     { 0x604,    "movqstr", 3 },
  545:     { 0x605,    "movstr",  3 },
  546:     { 0x610,    "atmod",   3 },
  547:     { 0x612,    "atadd",   3 },
  548:     { 0x613,    "inspacc", -2 },
  549:     { 0x614,    "ldphy",   -2 },
  550:     { 0x615,    "synld",   -2 },
  551:     { 0x617,    "fill",            3 },
  552: