Back to index

cell-binutils  2.17cvs20070401
ia64-dis.c
Go to the documentation of this file.
00001 /* ia64-dis.c -- Disassemble ia64 instructions
00002    Copyright 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
00003    Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
00004 
00005    This file is part of GDB, GAS, and the GNU binutils.
00006 
00007    GDB, GAS, and the GNU binutils are free software; you can redistribute
00008    them and/or modify them under the terms of the GNU General Public
00009    License as published by the Free Software Foundation; either version
00010    2, or (at your option) any later version.
00011 
00012    GDB, GAS, and the GNU binutils are distributed in the hope that they
00013    will be useful, but WITHOUT ANY WARRANTY; without even the implied
00014    warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
00015    the GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this file; see the file COPYING.  If not, write to the
00019    Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
00020    02110-1301, USA.  */
00021 
00022 #include <assert.h>
00023 #include <string.h>
00024 
00025 #include "dis-asm.h"
00026 #include "opcode/ia64.h"
00027 
00028 #define NELEMS(a)    ((int) (sizeof (a) / sizeof (a[0])))
00029 
00030 /* Disassemble ia64 instruction.  */
00031 
00032 /* Return the instruction type for OPCODE found in unit UNIT. */
00033 
00034 static enum ia64_insn_type
00035 unit_to_type (ia64_insn opcode, enum ia64_unit unit)
00036 {
00037   enum ia64_insn_type type;
00038   int op;
00039 
00040   op = IA64_OP (opcode);
00041 
00042   if (op >= 8 && (unit == IA64_UNIT_I || unit == IA64_UNIT_M))
00043     {
00044       type = IA64_TYPE_A;
00045     }
00046   else
00047     {
00048       switch (unit)
00049        {
00050        case IA64_UNIT_I:
00051          type = IA64_TYPE_I; break;
00052        case IA64_UNIT_M:
00053          type = IA64_TYPE_M; break;
00054        case IA64_UNIT_B:
00055          type = IA64_TYPE_B; break;
00056        case IA64_UNIT_F:
00057          type = IA64_TYPE_F; break;
00058         case IA64_UNIT_L:
00059        case IA64_UNIT_X:
00060          type = IA64_TYPE_X; break;
00061        default:
00062          type = -1;
00063        }
00064     }
00065   return type;
00066 }
00067 
00068 int
00069 print_insn_ia64 (bfd_vma memaddr, struct disassemble_info *info)
00070 {
00071   ia64_insn t0, t1, slot[3], template, s_bit, insn;
00072   int slotnum, j, status, need_comma, retval, slot_multiplier;
00073   const struct ia64_operand *odesc;
00074   const struct ia64_opcode *idesc;
00075   const char *err, *str, *tname;
00076   BFD_HOST_U_64_BIT value;
00077   bfd_byte bundle[16];
00078   enum ia64_unit unit;
00079   char regname[16];
00080 
00081   if (info->bytes_per_line == 0)
00082     info->bytes_per_line = 6;
00083   info->display_endian = info->endian;
00084 
00085   slot_multiplier = info->bytes_per_line;
00086   retval = slot_multiplier;
00087 
00088   slotnum = (((long) memaddr) & 0xf) / slot_multiplier;
00089   if (slotnum > 2)
00090     return -1;
00091 
00092   memaddr -= (memaddr & 0xf);
00093   status = (*info->read_memory_func) (memaddr, bundle, sizeof (bundle), info);
00094   if (status != 0)
00095     {
00096       (*info->memory_error_func) (status, memaddr, info);
00097       return -1;
00098     }
00099   /* bundles are always in little-endian byte order */
00100   t0 = bfd_getl64 (bundle);
00101   t1 = bfd_getl64 (bundle + 8);
00102   s_bit = t0 & 1;
00103   template = (t0 >> 1) & 0xf;
00104   slot[0] = (t0 >>  5) & 0x1ffffffffffLL;
00105   slot[1] = ((t0 >> 46) & 0x3ffff) | ((t1 & 0x7fffff) << 18);
00106   slot[2] = (t1 >> 23) & 0x1ffffffffffLL;
00107 
00108   tname = ia64_templ_desc[template].name;
00109   if (slotnum == 0)
00110     (*info->fprintf_func) (info->stream, "[%s] ", tname);
00111   else
00112     (*info->fprintf_func) (info->stream, "      ");
00113 
00114   unit = ia64_templ_desc[template].exec_unit[slotnum];
00115 
00116   if (template == 2 && slotnum == 1)
00117     {
00118       /* skip L slot in MLI template: */
00119       slotnum = 2;
00120       retval += slot_multiplier;
00121     }
00122 
00123   insn = slot[slotnum];
00124 
00125   if (unit == IA64_UNIT_NIL)
00126     goto decoding_failed;
00127 
00128   idesc = ia64_dis_opcode (insn, unit_to_type (insn, unit));
00129   if (idesc == NULL)
00130     goto decoding_failed;
00131 
00132   /* print predicate, if any: */
00133 
00134   if ((idesc->flags & IA64_OPCODE_NO_PRED)
00135       || (insn & 0x3f) == 0)
00136     (*info->fprintf_func) (info->stream, "      ");
00137   else
00138     (*info->fprintf_func) (info->stream, "(p%02d) ", (int)(insn & 0x3f));
00139 
00140   /* now the actual instruction: */
00141 
00142   (*info->fprintf_func) (info->stream, "%s", idesc->name);
00143   if (idesc->operands[0])
00144     (*info->fprintf_func) (info->stream, " ");
00145 
00146   need_comma = 0;
00147   for (j = 0; j < NELEMS (idesc->operands) && idesc->operands[j]; ++j)
00148     {
00149       odesc = elf64_ia64_operands + idesc->operands[j];
00150 
00151       if (need_comma)
00152        (*info->fprintf_func) (info->stream, ",");
00153 
00154       if (odesc - elf64_ia64_operands == IA64_OPND_IMMU64)
00155        {
00156          /* special case of 64 bit immediate load: */
00157          value = ((insn >> 13) & 0x7f) | (((insn >> 27) & 0x1ff) << 7)
00158            | (((insn >> 22) & 0x1f) << 16) | (((insn >> 21) & 0x1) << 21)
00159            | (slot[1] << 22) | (((insn >> 36) & 0x1) << 63);
00160        }
00161       else if (odesc - elf64_ia64_operands == IA64_OPND_IMMU62)
00162         {
00163           /* 62-bit immediate for nop.x/break.x */
00164           value = ((slot[1] & 0x1ffffffffffLL) << 21)
00165             | (((insn >> 36) & 0x1) << 20)
00166             | ((insn >> 6) & 0xfffff);
00167         }
00168       else if (odesc - elf64_ia64_operands == IA64_OPND_TGT64)
00169        {
00170          /* 60-bit immediate for long branches. */
00171          value = (((insn >> 13) & 0xfffff)
00172                  | (((insn >> 36) & 1) << 59)
00173                  | (((slot[1] >> 2) & 0x7fffffffffLL) << 20)) << 4;
00174        }
00175       else
00176        {
00177          err = (*odesc->extract) (odesc, insn, &value);
00178          if (err)
00179            {
00180              (*info->fprintf_func) (info->stream, "%s", err);
00181              goto done;
00182            }
00183        }
00184 
00185        switch (odesc->class)
00186          {
00187          case IA64_OPND_CLASS_CST:
00188            (*info->fprintf_func) (info->stream, "%s", odesc->str);
00189            break;
00190 
00191          case IA64_OPND_CLASS_REG:
00192            if (odesc->str[0] == 'a' && odesc->str[1] == 'r')
00193              {
00194               switch (value)
00195                 {
00196                 case 0: case 1: case 2: case 3:
00197                 case 4: case 5: case 6: case 7:
00198                   sprintf (regname, "ar.k%u", (unsigned int) value);
00199                   break;
00200                 case 16:    strcpy (regname, "ar.rsc"); break;
00201                 case 17:    strcpy (regname, "ar.bsp"); break;
00202                 case 18:    strcpy (regname, "ar.bspstore"); break;
00203                 case 19:    strcpy (regname, "ar.rnat"); break;
00204                 case 32:    strcpy (regname, "ar.ccv"); break;
00205                 case 36:    strcpy (regname, "ar.unat"); break;
00206                 case 40:    strcpy (regname, "ar.fpsr"); break;
00207                 case 44:    strcpy (regname, "ar.itc"); break;
00208                 case 64:    strcpy (regname, "ar.pfs"); break;
00209                 case 65:    strcpy (regname, "ar.lc"); break;
00210                 case 66:    strcpy (regname, "ar.ec"); break;
00211                 default:
00212                   sprintf (regname, "ar%u", (unsigned int) value);
00213                   break;
00214                 }
00215               (*info->fprintf_func) (info->stream, "%s", regname);
00216              }
00217            else
00218              (*info->fprintf_func) (info->stream, "%s%d", odesc->str, (int)value);
00219            break;
00220 
00221          case IA64_OPND_CLASS_IND:
00222            (*info->fprintf_func) (info->stream, "%s[r%d]", odesc->str, (int)value);
00223            break;
00224 
00225          case IA64_OPND_CLASS_ABS:
00226            str = 0;
00227            if (odesc - elf64_ia64_operands == IA64_OPND_MBTYPE4)
00228              switch (value)
00229               {
00230               case 0x0: str = "@brcst"; break;
00231               case 0x8: str = "@mix"; break;
00232               case 0x9: str = "@shuf"; break;
00233               case 0xa: str = "@alt"; break;
00234               case 0xb: str = "@rev"; break;
00235               }
00236 
00237            if (str)
00238              (*info->fprintf_func) (info->stream, "%s", str);
00239            else if (odesc->flags & IA64_OPND_FLAG_DECIMAL_SIGNED)
00240              (*info->fprintf_func) (info->stream, "%lld", (long long) value);
00241            else if (odesc->flags & IA64_OPND_FLAG_DECIMAL_UNSIGNED)
00242              (*info->fprintf_func) (info->stream, "%llu", (long long) value);
00243            else
00244              (*info->fprintf_func) (info->stream, "0x%llx", (long long) value);
00245            break;
00246 
00247          case IA64_OPND_CLASS_REL:
00248            (*info->print_address_func) (memaddr + value, info);
00249            break;
00250          }
00251 
00252       need_comma = 1;
00253       if (j + 1 == idesc->num_outputs)
00254        {
00255          (*info->fprintf_func) (info->stream, "=");
00256          need_comma = 0;
00257        }
00258     }
00259   if (slotnum + 1 == ia64_templ_desc[template].group_boundary 
00260       || ((slotnum == 2) && s_bit))
00261     (*info->fprintf_func) (info->stream, ";;");
00262 
00263  done:
00264   ia64_free_opcode ((struct ia64_opcode *)idesc);
00265  failed:
00266   if (slotnum == 2)
00267     retval += 16 - 3*slot_multiplier;
00268   return retval;
00269 
00270  decoding_failed:
00271   (*info->fprintf_func) (info->stream, "      data8 %#011llx", (long long) insn);
00272   goto failed;
00273 }