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

binutils/2.18/opcodes/ia64-dis.c

    1: /* ia64-dis.c -- Disassemble ia64 instructions
    2:    Copyright 1998, 1999, 2000, 2002, 2007 Free Software Foundation, Inc.
    3:    Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
    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 file; 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 <assert.h>
   23: #include <string.h>
   24: 
   25: #include "dis-asm.h"
   26: #include "opcode/ia64.h"
   27: 
   28: #define NELEMS(a)       ((int) (sizeof (a) / sizeof (a[0])))
   29: 
   30: /* Disassemble ia64 instruction.  */
   31: 
   32: /* Return the instruction type for OPCODE found in unit UNIT. */
   33: 
   34: static enum ia64_insn_type
   35: unit_to_type (ia64_insn opcode, enum ia64_unit unit)
   36: {
   37:   enum ia64_insn_type type;
   38:   int op;
   39: 
   40:   op = IA64_OP (opcode);
   41: 
   42:   if (op >= 8 && (unit == IA64_UNIT_I || unit == IA64_UNIT_M))
   43:     {
   44:       type = IA64_TYPE_A;
   45:     }
   46:   else
   47:     {
   48:       switch (unit)
   49:         {
   50:         case IA64_UNIT_I:
   51:           type = IA64_TYPE_I; break;
   52:         case IA64_UNIT_M:
   53:           type = IA64_TYPE_M; break;
   54:         case IA64_UNIT_B:
   55:           type = IA64_TYPE_B; break;
   56:         case IA64_UNIT_F:
   57:           type = IA64_TYPE_F; break;
   58:         case IA64_UNIT_L:
   59:         case IA64_UNIT_X:
   60:           type = IA64_TYPE_X; break;
   61:         default:
   62:           type = -1;
   63:         }
   64:     }
   65:   return type;
   66: }
   67: 
   68: int
   69: print_insn_ia64 (bfd_vma memaddr, struct disassemble_info *info)
   70: {
   71:   ia64_insn t0, t1, slot[3], template, s_bit, insn;
   72:   int slotnum, j, status, need_comma, retval, slot_multiplier;
   73:   const struct ia64_operand *odesc;
   74:   const struct ia64_opcode *idesc;
   75:   const char *err, *str, *tname;
   76:   BFD_HOST_U_64_BIT value;
   77:   bfd_byte bundle[16];
   78:   enum ia64_unit unit;
   79:   char regname[16];
   80: 
   81:   if (info->bytes_per_line == 0)
   82:     info->bytes_per_line = 6;
   83:   info->display_endian = info->endian;
   84: 
   85:   slot_multiplier = info->bytes_per_line;
   86:   retval = slot_multiplier;
   87: 
   88:   slotnum = (((long) memaddr) & 0xf) / slot_multiplier;
   89:   if (slotnum > 2)
   90:     return -1;
   91: 
   92:   memaddr -= (memaddr & 0xf);
   93:   status = (*info->read_memory_func) (memaddr, bundle, sizeof (bundle), info);
   94:   if (status != 0)
   95:     {
   96:       (*info->memory_error_func) (status, memaddr, info);
   97:       return -1;
   98:     }
   99:   /* bundles are always in little-endian byte order */
  100:   t0 = bfd_getl64 (bundle);
  101:   t1 = bfd_getl64 (bundle + 8);
  102:   s_bit = t0 & 1;
  103:   template = (t0 >> 1) & 0xf;
  104:   slot[0] = (t0 >>  5) & 0x1ffffffffffLL;
  105:   slot[1] = ((t0 >> 46) & 0x3ffff) | ((t1 & 0x7fffff) << 18);
  106:   slot[2] = (t1 >> 23) & 0x1ffffffffffLL;
  107: 
  108:   tname = ia64_templ_desc[template].name;
  109:   if (slotnum == 0)
  110:     (*info->fprintf_func) (info->stream, "[%s] ", tname);
  111:   else
  112:     (*info->fprintf_func) (info->stream, "      ");
  113: 
  114:   unit = ia64_templ_desc[template].exec_unit[slotnum];
  115: 
  116:   if (template == 2 && slotnum == 1)
  117:     {
  118:       /* skip L slot in MLI template: */
  119:       slotnum = 2;
  120:       retval += slot_multiplier;
  121:     }
  122: 
  123:   insn = slot[slotnum];
  124: 
  125:   if (unit == IA64_UNIT_NIL)
  126:     goto decoding_failed;
  127: 
  128:   idesc = ia64_dis_opcode (insn, unit_to_type (insn, unit));
  129:   if (idesc == NULL)
  130:     goto decoding_failed;
  131: 
  132:   /* print predicate, if any: */
  133: 
  134:   if ((idesc->flags & IA64_OPCODE_NO_PRED)
  135:       || (insn & 0x3f) == 0)
  136:     (*info->fprintf_func) (info->stream, "      ");
  137:   else
  138:     (*info->fprintf_func) (info->stream, "(p%02d) ", (int)(insn & 0x3f));
  139: 
  140:   /* now the actual instruction: */
  141: 
  142:   (*info->fprintf_func) (info->stream, "%s", idesc->name);
  143:   if (idesc->operands[0])
  144:     (*info->fprintf_func) (info->stream, " ");
  145: 
  146:   need_comma = 0;
  147:   for (j = 0; j < NELEMS (idesc->operands) && idesc->operands[j]; ++j)
  148:     {
  149:       odesc = elf64_ia64_operands + idesc->operands[j];
  150: 
  151:       if (need_comma)
  152:         (*info->fprintf_func) (info->stream, ",");
  153: 
  154:       if (odesc - elf64_ia64_operands == IA64_OPND_IMMU64)
  155:         {
  156:           /* special case of 64 bit immediate load: */
  157:           value = ((insn >> 13) & 0x7f) | (((insn >> 27) & 0x1ff) << 7)
  158:             | (((insn >> 22) & 0x1f) << 16) | (((insn >> 21) & 0x1) << 21)
  159:             | (slot[1] << 22) | (((insn >> 36) & 0x1) << 63);
  160:         }
  161:       else if (odesc - elf64_ia64_operands == IA64_OPND_IMMU62)
  162:         {
  163:           /* 62-bit immediate for nop.x/break.x */
  164:           value = ((slot[1] & 0x1ffffffffffLL) << 21)
  165:             | (((insn >> 36) & 0x1) << 20)
  166:             | ((insn >> 6) & 0xfffff);
  167:         }
  168:       else if (odesc - elf64_ia64_operands == IA64_OPND_TGT64)
  169:         {
  170:           /* 60-bit immediate for long branches. */
  171:           value = (((insn >> 13) & 0xfffff)
  172:                    | (((insn >> 36) & 1) << 59)
  173:                    | (((slot[1] >> 2) & 0x7fffffffffLL) << 20)) << 4;
  174:         }
  175:       else
  176:         {
  177:           err = (*odesc->extract) (odesc, insn, &value);
  178:           if (err)
  179:             {
  180:               (*info->fprintf_func) (info->stream, "%s", err);
  181:               goto done;
  182:             }
  183:         }
  184: 
  185:         switch (odesc->class)
  186:           {
  187:           case IA64_OPND_CLASS_CST:
  188:             (*info->fprintf_func) (info->stream, "%s", odesc->str);
  189:             break;
  190: 
  191:           case IA64_OPND_CLASS_REG:
  192:             if (odesc->str[0] == 'a' && odesc->str[1] == 'r')
  193:               {
  194:                 switch (value)
  195:                   {
  196:                   case 0: case 1: case 2: case 3:
  197:                   case 4: case 5: case 6: case 7:
  198:                     sprintf (regname, "ar.k%u", (unsigned int) value);
  199:                     break;
  200:                   case 16:    strcpy (regname, "ar.rsc"); break;
  201:                   case 17:    strcpy (regname, "ar.bsp"); break;
  202:                   case 18:    strcpy (regname, "ar.bspstore"); break;
  203:                   case 19:    strcpy (regname, "ar.rnat"); break;
  204:                   case 32:    strcpy (regname, "ar.ccv"); break;
  205:                   case 36:    strcpy (regname, "ar.unat"); break;
  206:                   case 40:    strcpy (regname, "ar.fpsr"); break;
  207:                   case 44:    strcpy (regname, "ar.itc"); break;
  208:                   case 64:    strcpy (regname, "ar.pfs"); break;
  209:                   case 65:    strcpy (regname, "ar.lc"); break;
  210:                   case 66:    strcpy (regname, "ar.ec"); break;
  211:                   default:
  212:                     sprintf (regname, "ar%u", (unsigned int) value);
  213:                     break;
  214:                   }
  215:                 (*info->fprintf_func) (info->stream, "%s", regname);
  216:               }
  217:             else
  218:               (*info->fprintf_func) (info->stream, "%s%d", odesc->str, (int)value);
  219:             break;
  220: 
  221:           case IA64_OPND_CLASS_IND:
  222:             (*info->fprintf_func) (info->stream, "%s[r%d]", odesc->str, (int)value);
  223:             break;
  224: 
  225:           case IA64_OPND_CLASS_ABS:
  226:             str = 0;
  227:             if (odesc - elf64_ia64_operands == IA64_OPND_MBTYPE4)
  228:               switch (value)
  229:                 {
  230:                 case 0x0: str = "@brcst"; break;
  231:                 case 0x8: str = "@mix"; break;
  232:                 case 0x9: str = "@shuf"; break;
  233:                 case 0xa: str = "@alt"; break;
  234:                 case 0xb: str = "@rev"; break;
  235:                 }
  236: 
  237:             if (str)
  238:               (*info->fprintf_func) (info->stream, "%s", str);
  239:             else if (odesc->flags & IA64_OPND_FLAG_DECIMAL_SIGNED)
  240:               (*info->fprintf_func) (info->stream, "%lld", (long long) value);
  241:             else if (odesc->flags & IA64_OPND_FLAG_DECIMAL_UNSIGNED)
  242:               (*info->fprintf_func) (info->stream, "%llu", (long long) value);
  243:             else
  244:               (*info->fprintf_func) (info->stream, "0x%llx", (long long) value);
  245:             break;
  246: 
  247:           case IA64_OPND_CLASS_REL:
  248:             (*info->print_address_func) (memaddr + value, info);
  249:             break;
  250:           }
  251: 
  252:       need_comma = 1;
  253:       if (j + 1 == idesc->num_outputs)
  254:         {
  255:           (*info->fprintf_func) (info->stream, "=");
  256:           need_comma = 0;
  257:         }
  258:     }
  259:   if (slotnum + 1 == ia64_templ_desc[template].group_boundary 
  260:       || ((slotnum == 2) && s_bit))
  261:     (*info->fprintf_func) (info->stream, ";;");
  262: 
  263:  done:
  264:   ia64_free_opcode ((struct ia64_opcode *)idesc);
  265:  failed:
  266:   if (slotnum == 2)
  267:     retval += 16 - 3*slot_multiplier;
  268:   return retval;
  269: 
  270:  decoding_failed:
  271:   (*info->fprintf_func) (info->stream, "      data8 %#011llx", (long long) insn);
  272:   goto failed;
  273: }
Syntax (Markdown)