Home | History | Annotate | Line # | Download | only in opcodes
      1      1.1  christos /* ia64-dis.c -- Disassemble ia64 instructions
      2  1.1.1.9  christos    Copyright (C) 1998-2024 Free Software Foundation, Inc.
      3      1.1  christos    Contributed by David Mosberger-Tang <davidm (at) hpl.hp.com>
      4      1.1  christos 
      5      1.1  christos    This file is part of the GNU opcodes library.
      6      1.1  christos 
      7      1.1  christos    This library is free software; you can redistribute it and/or modify
      8      1.1  christos    it under the terms of the GNU General Public License as published by
      9      1.1  christos    the Free Software Foundation; either version 3, or (at your option)
     10      1.1  christos    any later version.
     11      1.1  christos 
     12      1.1  christos    It is distributed in the hope that it will be useful, but WITHOUT
     13      1.1  christos    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     14      1.1  christos    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     15      1.1  christos    License for more details.
     16      1.1  christos 
     17      1.1  christos    You should have received a copy of the GNU General Public License
     18      1.1  christos    along with this file; see the file COPYING.  If not, write to the
     19      1.1  christos    Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
     20      1.1  christos    02110-1301, USA.  */
     21      1.1  christos 
     22  1.1.1.2  christos #include "sysdep.h"
     23      1.1  christos #include <assert.h>
     24      1.1  christos 
     25  1.1.1.6  christos #include "disassemble.h"
     26      1.1  christos #include "opcode/ia64.h"
     27      1.1  christos 
     28      1.1  christos #define NELEMS(a)	((int) (sizeof (a) / sizeof (a[0])))
     29      1.1  christos 
     30      1.1  christos /* Disassemble ia64 instruction.  */
     31      1.1  christos 
     32      1.1  christos /* Return the instruction type for OPCODE found in unit UNIT. */
     33      1.1  christos 
     34      1.1  christos static enum ia64_insn_type
     35      1.1  christos unit_to_type (ia64_insn opcode, enum ia64_unit unit)
     36      1.1  christos {
     37      1.1  christos   enum ia64_insn_type type;
     38      1.1  christos   int op;
     39      1.1  christos 
     40      1.1  christos   op = IA64_OP (opcode);
     41      1.1  christos 
     42      1.1  christos   if (op >= 8 && (unit == IA64_UNIT_I || unit == IA64_UNIT_M))
     43      1.1  christos     {
     44      1.1  christos       type = IA64_TYPE_A;
     45      1.1  christos     }
     46      1.1  christos   else
     47      1.1  christos     {
     48      1.1  christos       switch (unit)
     49      1.1  christos 	{
     50      1.1  christos 	case IA64_UNIT_I:
     51      1.1  christos 	  type = IA64_TYPE_I; break;
     52      1.1  christos 	case IA64_UNIT_M:
     53      1.1  christos 	  type = IA64_TYPE_M; break;
     54      1.1  christos 	case IA64_UNIT_B:
     55      1.1  christos 	  type = IA64_TYPE_B; break;
     56      1.1  christos 	case IA64_UNIT_F:
     57      1.1  christos 	  type = IA64_TYPE_F; break;
     58      1.1  christos         case IA64_UNIT_L:
     59      1.1  christos 	case IA64_UNIT_X:
     60      1.1  christos 	  type = IA64_TYPE_X; break;
     61      1.1  christos 	default:
     62      1.1  christos 	  type = -1;
     63      1.1  christos 	}
     64      1.1  christos     }
     65      1.1  christos   return type;
     66      1.1  christos }
     67      1.1  christos 
     68      1.1  christos int
     69      1.1  christos print_insn_ia64 (bfd_vma memaddr, struct disassemble_info *info)
     70      1.1  christos {
     71      1.1  christos   ia64_insn t0, t1, slot[3], template_val, s_bit, insn;
     72      1.1  christos   int slotnum, j, status, need_comma, retval, slot_multiplier;
     73      1.1  christos   const struct ia64_operand *odesc;
     74      1.1  christos   const struct ia64_opcode *idesc;
     75      1.1  christos   const char *err, *str, *tname;
     76  1.1.1.8  christos   uint64_t value;
     77      1.1  christos   bfd_byte bundle[16];
     78      1.1  christos   enum ia64_unit unit;
     79      1.1  christos   char regname[16];
     80      1.1  christos 
     81      1.1  christos   if (info->bytes_per_line == 0)
     82      1.1  christos     info->bytes_per_line = 6;
     83      1.1  christos   info->display_endian = info->endian;
     84      1.1  christos 
     85      1.1  christos   slot_multiplier = info->bytes_per_line;
     86      1.1  christos   retval = slot_multiplier;
     87      1.1  christos 
     88      1.1  christos   slotnum = (((long) memaddr) & 0xf) / slot_multiplier;
     89      1.1  christos   if (slotnum > 2)
     90      1.1  christos     return -1;
     91      1.1  christos 
     92      1.1  christos   memaddr -= (memaddr & 0xf);
     93      1.1  christos   status = (*info->read_memory_func) (memaddr, bundle, sizeof (bundle), info);
     94      1.1  christos   if (status != 0)
     95      1.1  christos     {
     96      1.1  christos       (*info->memory_error_func) (status, memaddr, info);
     97      1.1  christos       return -1;
     98      1.1  christos     }
     99      1.1  christos   /* bundles are always in little-endian byte order */
    100      1.1  christos   t0 = bfd_getl64 (bundle);
    101      1.1  christos   t1 = bfd_getl64 (bundle + 8);
    102      1.1  christos   s_bit = t0 & 1;
    103      1.1  christos   template_val = (t0 >> 1) & 0xf;
    104      1.1  christos   slot[0] = (t0 >>  5) & 0x1ffffffffffLL;
    105      1.1  christos   slot[1] = ((t0 >> 46) & 0x3ffff) | ((t1 & 0x7fffff) << 18);
    106      1.1  christos   slot[2] = (t1 >> 23) & 0x1ffffffffffLL;
    107      1.1  christos 
    108      1.1  christos   tname = ia64_templ_desc[template_val].name;
    109      1.1  christos   if (slotnum == 0)
    110      1.1  christos     (*info->fprintf_func) (info->stream, "[%s] ", tname);
    111      1.1  christos   else
    112      1.1  christos     (*info->fprintf_func) (info->stream, "      ");
    113      1.1  christos 
    114      1.1  christos   unit = ia64_templ_desc[template_val].exec_unit[slotnum];
    115      1.1  christos 
    116      1.1  christos   if (template_val == 2 && slotnum == 1)
    117      1.1  christos     {
    118      1.1  christos       /* skip L slot in MLI template: */
    119      1.1  christos       slotnum = 2;
    120      1.1  christos       retval += slot_multiplier;
    121      1.1  christos     }
    122      1.1  christos 
    123      1.1  christos   insn = slot[slotnum];
    124      1.1  christos 
    125      1.1  christos   if (unit == IA64_UNIT_NIL)
    126      1.1  christos     goto decoding_failed;
    127      1.1  christos 
    128      1.1  christos   idesc = ia64_dis_opcode (insn, unit_to_type (insn, unit));
    129      1.1  christos   if (idesc == NULL)
    130      1.1  christos     goto decoding_failed;
    131      1.1  christos 
    132      1.1  christos   /* print predicate, if any: */
    133      1.1  christos 
    134      1.1  christos   if ((idesc->flags & IA64_OPCODE_NO_PRED)
    135      1.1  christos       || (insn & 0x3f) == 0)
    136      1.1  christos     (*info->fprintf_func) (info->stream, "      ");
    137      1.1  christos   else
    138      1.1  christos     (*info->fprintf_func) (info->stream, "(p%02d) ", (int)(insn & 0x3f));
    139      1.1  christos 
    140      1.1  christos   /* now the actual instruction: */
    141      1.1  christos 
    142      1.1  christos   (*info->fprintf_func) (info->stream, "%s", idesc->name);
    143      1.1  christos   if (idesc->operands[0])
    144      1.1  christos     (*info->fprintf_func) (info->stream, " ");
    145      1.1  christos 
    146      1.1  christos   need_comma = 0;
    147      1.1  christos   for (j = 0; j < NELEMS (idesc->operands) && idesc->operands[j]; ++j)
    148      1.1  christos     {
    149      1.1  christos       odesc = elf64_ia64_operands + idesc->operands[j];
    150      1.1  christos 
    151      1.1  christos       if (need_comma)
    152      1.1  christos 	(*info->fprintf_func) (info->stream, ",");
    153      1.1  christos 
    154      1.1  christos       if (odesc - elf64_ia64_operands == IA64_OPND_IMMU64)
    155      1.1  christos 	{
    156      1.1  christos 	  /* special case of 64 bit immediate load: */
    157      1.1  christos 	  value = ((insn >> 13) & 0x7f) | (((insn >> 27) & 0x1ff) << 7)
    158      1.1  christos 	    | (((insn >> 22) & 0x1f) << 16) | (((insn >> 21) & 0x1) << 21)
    159      1.1  christos 	    | (slot[1] << 22) | (((insn >> 36) & 0x1) << 63);
    160      1.1  christos 	}
    161      1.1  christos       else if (odesc - elf64_ia64_operands == IA64_OPND_IMMU62)
    162      1.1  christos         {
    163      1.1  christos           /* 62-bit immediate for nop.x/break.x */
    164      1.1  christos           value = ((slot[1] & 0x1ffffffffffLL) << 21)
    165      1.1  christos             | (((insn >> 36) & 0x1) << 20)
    166      1.1  christos             | ((insn >> 6) & 0xfffff);
    167      1.1  christos         }
    168      1.1  christos       else if (odesc - elf64_ia64_operands == IA64_OPND_TGT64)
    169      1.1  christos 	{
    170      1.1  christos 	  /* 60-bit immediate for long branches. */
    171      1.1  christos 	  value = (((insn >> 13) & 0xfffff)
    172      1.1  christos 		   | (((insn >> 36) & 1) << 59)
    173      1.1  christos 		   | (((slot[1] >> 2) & 0x7fffffffffLL) << 20)) << 4;
    174      1.1  christos 	}
    175      1.1  christos       else
    176      1.1  christos 	{
    177      1.1  christos 	  err = (*odesc->extract) (odesc, insn, &value);
    178      1.1  christos 	  if (err)
    179      1.1  christos 	    {
    180      1.1  christos 	      (*info->fprintf_func) (info->stream, "%s", err);
    181      1.1  christos 	      goto done;
    182      1.1  christos 	    }
    183      1.1  christos 	}
    184      1.1  christos 
    185      1.1  christos 	switch (odesc->op_class)
    186      1.1  christos 	  {
    187      1.1  christos 	  case IA64_OPND_CLASS_CST:
    188      1.1  christos 	    (*info->fprintf_func) (info->stream, "%s", odesc->str);
    189      1.1  christos 	    break;
    190      1.1  christos 
    191      1.1  christos 	  case IA64_OPND_CLASS_REG:
    192      1.1  christos 	    if (odesc->str[0] == 'a' && odesc->str[1] == 'r')
    193      1.1  christos 	      {
    194      1.1  christos 		switch (value)
    195      1.1  christos 		  {
    196      1.1  christos 		  case 0: case 1: case 2: case 3:
    197      1.1  christos 		  case 4: case 5: case 6: case 7:
    198      1.1  christos 		    sprintf (regname, "ar.k%u", (unsigned int) value);
    199      1.1  christos 		    break;
    200      1.1  christos 		  case 16:	strcpy (regname, "ar.rsc"); break;
    201      1.1  christos 		  case 17:	strcpy (regname, "ar.bsp"); break;
    202      1.1  christos 		  case 18:	strcpy (regname, "ar.bspstore"); break;
    203      1.1  christos 		  case 19:	strcpy (regname, "ar.rnat"); break;
    204      1.1  christos 		  case 21:	strcpy (regname, "ar.fcr"); break;
    205      1.1  christos 		  case 24:	strcpy (regname, "ar.eflag"); break;
    206      1.1  christos 		  case 25:	strcpy (regname, "ar.csd"); break;
    207      1.1  christos 		  case 26:	strcpy (regname, "ar.ssd"); break;
    208      1.1  christos 		  case 27:	strcpy (regname, "ar.cflg"); break;
    209      1.1  christos 		  case 28:	strcpy (regname, "ar.fsr"); break;
    210      1.1  christos 		  case 29:	strcpy (regname, "ar.fir"); break;
    211      1.1  christos 		  case 30:	strcpy (regname, "ar.fdr"); break;
    212      1.1  christos 		  case 32:	strcpy (regname, "ar.ccv"); break;
    213      1.1  christos 		  case 36:	strcpy (regname, "ar.unat"); break;
    214      1.1  christos 		  case 40:	strcpy (regname, "ar.fpsr"); break;
    215      1.1  christos 		  case 44:	strcpy (regname, "ar.itc"); break;
    216      1.1  christos 		  case 45:	strcpy (regname, "ar.ruc"); break;
    217      1.1  christos 		  case 64:	strcpy (regname, "ar.pfs"); break;
    218      1.1  christos 		  case 65:	strcpy (regname, "ar.lc"); break;
    219      1.1  christos 		  case 66:	strcpy (regname, "ar.ec"); break;
    220      1.1  christos 		  default:
    221      1.1  christos 		    sprintf (regname, "ar%u", (unsigned int) value);
    222      1.1  christos 		    break;
    223      1.1  christos 		  }
    224      1.1  christos 		(*info->fprintf_func) (info->stream, "%s", regname);
    225      1.1  christos 	      }
    226      1.1  christos 	    else if (odesc->str[0] == 'c' && odesc->str[1] == 'r')
    227      1.1  christos 	      {
    228      1.1  christos 		switch (value)
    229      1.1  christos 		  {
    230      1.1  christos 		  case 0:       strcpy (regname, "cr.dcr"); break;
    231      1.1  christos 		  case 1:       strcpy (regname, "cr.itm"); break;
    232      1.1  christos 		  case 2:       strcpy (regname, "cr.iva"); break;
    233      1.1  christos 		  case 8:       strcpy (regname, "cr.pta"); break;
    234      1.1  christos 		  case 16:      strcpy (regname, "cr.ipsr"); break;
    235      1.1  christos 		  case 17:      strcpy (regname, "cr.isr"); break;
    236      1.1  christos 		  case 19:      strcpy (regname, "cr.iip"); break;
    237      1.1  christos 		  case 20:      strcpy (regname, "cr.ifa"); break;
    238      1.1  christos 		  case 21:      strcpy (regname, "cr.itir"); break;
    239      1.1  christos 		  case 22:      strcpy (regname, "cr.iipa"); break;
    240      1.1  christos 		  case 23:      strcpy (regname, "cr.ifs"); break;
    241      1.1  christos 		  case 24:      strcpy (regname, "cr.iim"); break;
    242      1.1  christos 		  case 25:      strcpy (regname, "cr.iha"); break;
    243      1.1  christos 		  case 26:      strcpy (regname, "cr.iib0"); break;
    244      1.1  christos 		  case 27:      strcpy (regname, "cr.iib1"); break;
    245      1.1  christos 		  case 64:      strcpy (regname, "cr.lid"); break;
    246      1.1  christos 		  case 65:      strcpy (regname, "cr.ivr"); break;
    247      1.1  christos 		  case 66:      strcpy (regname, "cr.tpr"); break;
    248      1.1  christos 		  case 67:      strcpy (regname, "cr.eoi"); break;
    249      1.1  christos 		  case 68:      strcpy (regname, "cr.irr0"); break;
    250      1.1  christos 		  case 69:      strcpy (regname, "cr.irr1"); break;
    251      1.1  christos 		  case 70:      strcpy (regname, "cr.irr2"); break;
    252      1.1  christos 		  case 71:      strcpy (regname, "cr.irr3"); break;
    253      1.1  christos 		  case 72:      strcpy (regname, "cr.itv"); break;
    254      1.1  christos 		  case 73:      strcpy (regname, "cr.pmv"); break;
    255      1.1  christos 		  case 74:      strcpy (regname, "cr.cmcv"); break;
    256      1.1  christos 		  case 80:      strcpy (regname, "cr.lrr0"); break;
    257      1.1  christos 		  case 81:      strcpy (regname, "cr.lrr1"); break;
    258      1.1  christos 		  default:
    259      1.1  christos 		    sprintf (regname, "cr%u", (unsigned int) value);
    260      1.1  christos 		    break;
    261      1.1  christos 		  }
    262      1.1  christos 		(*info->fprintf_func) (info->stream, "%s", regname);
    263      1.1  christos 	      }
    264      1.1  christos 	    else
    265      1.1  christos 	      (*info->fprintf_func) (info->stream, "%s%d", odesc->str, (int)value);
    266      1.1  christos 	    break;
    267      1.1  christos 
    268      1.1  christos 	  case IA64_OPND_CLASS_IND:
    269      1.1  christos 	    (*info->fprintf_func) (info->stream, "%s[r%d]", odesc->str, (int)value);
    270      1.1  christos 	    break;
    271      1.1  christos 
    272      1.1  christos 	  case IA64_OPND_CLASS_ABS:
    273      1.1  christos 	    str = 0;
    274      1.1  christos 	    if (odesc - elf64_ia64_operands == IA64_OPND_MBTYPE4)
    275      1.1  christos 	      switch (value)
    276      1.1  christos 		{
    277      1.1  christos 		case 0x0: str = "@brcst"; break;
    278      1.1  christos 		case 0x8: str = "@mix"; break;
    279      1.1  christos 		case 0x9: str = "@shuf"; break;
    280      1.1  christos 		case 0xa: str = "@alt"; break;
    281      1.1  christos 		case 0xb: str = "@rev"; break;
    282      1.1  christos 		}
    283      1.1  christos 
    284      1.1  christos 	    if (str)
    285      1.1  christos 	      (*info->fprintf_func) (info->stream, "%s", str);
    286      1.1  christos 	    else if (odesc->flags & IA64_OPND_FLAG_DECIMAL_SIGNED)
    287      1.1  christos 	      (*info->fprintf_func) (info->stream, "%lld", (long long) value);
    288      1.1  christos 	    else if (odesc->flags & IA64_OPND_FLAG_DECIMAL_UNSIGNED)
    289      1.1  christos 	      (*info->fprintf_func) (info->stream, "%llu", (long long) value);
    290      1.1  christos 	    else
    291      1.1  christos 	      (*info->fprintf_func) (info->stream, "0x%llx", (long long) value);
    292      1.1  christos 	    break;
    293      1.1  christos 
    294      1.1  christos 	  case IA64_OPND_CLASS_REL:
    295      1.1  christos 	    (*info->print_address_func) (memaddr + value, info);
    296      1.1  christos 	    break;
    297      1.1  christos 	  }
    298      1.1  christos 
    299      1.1  christos       need_comma = 1;
    300      1.1  christos       if (j + 1 == idesc->num_outputs)
    301      1.1  christos 	{
    302      1.1  christos 	  (*info->fprintf_func) (info->stream, "=");
    303      1.1  christos 	  need_comma = 0;
    304      1.1  christos 	}
    305      1.1  christos     }
    306  1.1.1.4  christos   if (slotnum + 1 == ia64_templ_desc[template_val].group_boundary
    307      1.1  christos       || ((slotnum == 2) && s_bit))
    308      1.1  christos     (*info->fprintf_func) (info->stream, ";;");
    309      1.1  christos 
    310      1.1  christos  done:
    311      1.1  christos   ia64_free_opcode ((struct ia64_opcode *)idesc);
    312      1.1  christos  failed:
    313      1.1  christos   if (slotnum == 2)
    314      1.1  christos     retval += 16 - 3*slot_multiplier;
    315      1.1  christos   return retval;
    316      1.1  christos 
    317      1.1  christos  decoding_failed:
    318      1.1  christos   (*info->fprintf_func) (info->stream, "      data8 %#011llx", (long long) insn);
    319      1.1  christos   goto failed;
    320      1.1  christos }
    321