00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <assert.h>
00027 #include <string.h>
00028
00029 #include "dis-asm.h"
00030 #include "opcode/ia64.h"
00031
00032 #define NELEMS(a) ((int) (sizeof (a) / sizeof (a[0])))
00033
00034
00035
00036
00037
00038 static enum ia64_insn_type
00039 unit_to_type (ia64_insn opcode, enum ia64_unit unit)
00040 {
00041 enum ia64_insn_type type;
00042 int op;
00043
00044 op = IA64_OP (opcode);
00045
00046 if (op >= 8 && (unit == IA64_UNIT_I || unit == IA64_UNIT_M))
00047 {
00048 type = IA64_TYPE_A;
00049 }
00050 else
00051 {
00052 switch (unit)
00053 {
00054 case IA64_UNIT_I:
00055 type = IA64_TYPE_I; break;
00056 case IA64_UNIT_M:
00057 type = IA64_TYPE_M; break;
00058 case IA64_UNIT_B:
00059 type = IA64_TYPE_B; break;
00060 case IA64_UNIT_F:
00061 type = IA64_TYPE_F; break;
00062 case IA64_UNIT_L:
00063 case IA64_UNIT_X:
00064 type = IA64_TYPE_X; break;
00065 default:
00066 type = -1;
00067 }
00068 }
00069 return type;
00070 }
00071
00072 int
00073 print_insn_ia64 (bfd_vma memaddr, struct disassemble_info *info)
00074 {
00075 ia64_insn t0, t1, slot[3], template, s_bit, insn;
00076 int slotnum, j, status, need_comma, retval, slot_multiplier;
00077 const struct ia64_operand *odesc;
00078 const struct ia64_opcode *idesc;
00079 const char *err, *str, *tname;
00080 BFD_HOST_U_64_BIT value;
00081 bfd_byte bundle[16];
00082 enum ia64_unit unit;
00083 char regname[16];
00084
00085 if (info->bytes_per_line == 0)
00086 info->bytes_per_line = 6;
00087 info->display_endian = info->endian;
00088
00089 slot_multiplier = info->bytes_per_line;
00090 retval = slot_multiplier;
00091
00092 slotnum = (((long) memaddr) & 0xf) / slot_multiplier;
00093 if (slotnum > 2)
00094 return -1;
00095
00096 memaddr -= (memaddr & 0xf);
00097 status = (*info->read_memory_func) (memaddr, bundle, sizeof (bundle), info);
00098 if (status != 0)
00099 {
00100 (*info->memory_error_func) (status, memaddr, info);
00101 return -1;
00102 }
00103
00104 t0 = bfd_getl64 (bundle);
00105 t1 = bfd_getl64 (bundle + 8);
00106 s_bit = t0 & 1;
00107 template = (t0 >> 1) & 0xf;
00108 slot[0] = (t0 >> 5) & 0x1ffffffffffLL;
00109 slot[1] = ((t0 >> 46) & 0x3ffff) | ((t1 & 0x7fffff) << 18);
00110 slot[2] = (t1 >> 23) & 0x1ffffffffffLL;
00111
00112 tname = ia64_templ_desc[template].name;
00113 if (slotnum == 0)
00114 (*info->fprintf_func) (info->stream, "[%s] ", tname);
00115 else
00116 (*info->fprintf_func) (info->stream, " ", tname);
00117
00118 unit = ia64_templ_desc[template].exec_unit[slotnum];
00119
00120 if (template == 2 && slotnum == 1)
00121 {
00122
00123 slotnum = 2;
00124 retval += slot_multiplier;
00125 }
00126
00127 insn = slot[slotnum];
00128
00129 if (unit == IA64_UNIT_NIL)
00130 goto decoding_failed;
00131
00132 idesc = ia64_dis_opcode (insn, unit_to_type (insn, unit));
00133 if (idesc == NULL)
00134 goto decoding_failed;
00135
00136
00137
00138 if ((idesc->flags & IA64_OPCODE_NO_PRED)
00139 || (insn & 0x3f) == 0)
00140 (*info->fprintf_func) (info->stream, " ");
00141 else
00142 (*info->fprintf_func) (info->stream, "(p%02d) ", (int)(insn & 0x3f));
00143
00144
00145
00146 (*info->fprintf_func) (info->stream, "%s", idesc->name);
00147 if (idesc->operands[0])
00148 (*info->fprintf_func) (info->stream, " ");
00149
00150 need_comma = 0;
00151 for (j = 0; j < NELEMS (idesc->operands) && idesc->operands[j]; ++j)
00152 {
00153 odesc = elf64_ia64_operands + idesc->operands[j];
00154
00155 if (need_comma)
00156 (*info->fprintf_func) (info->stream, ",");
00157
00158 if (odesc - elf64_ia64_operands == IA64_OPND_IMMU64)
00159 {
00160
00161 value = ((insn >> 13) & 0x7f) | (((insn >> 27) & 0x1ff) << 7)
00162 | (((insn >> 22) & 0x1f) << 16) | (((insn >> 21) & 0x1) << 21)
00163 | (slot[1] << 22) | (((insn >> 36) & 0x1) << 63);
00164 }
00165 else if (odesc - elf64_ia64_operands == IA64_OPND_IMMU62)
00166 {
00167
00168 value = ((slot[1] & 0x1ffffffffffLL) << 21)
00169 | (((insn >> 36) & 0x1) << 20)
00170 | ((insn >> 6) & 0xfffff);
00171 }
00172 else if (odesc - elf64_ia64_operands == IA64_OPND_TGT64)
00173 {
00174
00175 value = (((insn >> 13) & 0xfffff)
00176 | (((insn >> 36) & 1) << 59)
00177 | (((slot[1] >> 2) & 0x7fffffffffLL) << 20)) << 4;
00178 }
00179 else
00180 {
00181 err = (*odesc->extract) (odesc, insn, &value);
00182 if (err)
00183 {
00184 (*info->fprintf_func) (info->stream, "%s", err);
00185 goto done;
00186 }
00187 }
00188
00189 switch (odesc->class)
00190 {
00191 case IA64_OPND_CLASS_CST:
00192 (*info->fprintf_func) (info->stream, "%s", odesc->str);
00193 break;
00194
00195 case IA64_OPND_CLASS_REG:
00196 if (odesc->str[0] == 'a' && odesc->str[1] == 'r')
00197 {
00198 switch (value)
00199 {
00200 case 0: case 1: case 2: case 3:
00201 case 4: case 5: case 6: case 7:
00202 sprintf (regname, "ar.k%u", (unsigned int) value);
00203 break;
00204 case 16: strcpy (regname, "ar.rsc"); break;
00205 case 17: strcpy (regname, "ar.bsp"); break;
00206 case 18: strcpy (regname, "ar.bspstore"); break;
00207 case 19: strcpy (regname, "ar.rnat"); break;
00208 case 32: strcpy (regname, "ar.ccv"); break;
00209 case 36: strcpy (regname, "ar.unat"); break;
00210 case 40: strcpy (regname, "ar.fpsr"); break;
00211 case 44: strcpy (regname, "ar.itc"); break;
00212 case 64: strcpy (regname, "ar.pfs"); break;
00213 case 65: strcpy (regname, "ar.lc"); break;
00214 case 66: strcpy (regname, "ar.ec"); break;
00215 default:
00216 sprintf (regname, "ar%u", (unsigned int) value);
00217 break;
00218 }
00219 (*info->fprintf_func) (info->stream, "%s", regname);
00220 }
00221 else
00222 (*info->fprintf_func) (info->stream, "%s%d", odesc->str, (int)value);
00223 break;
00224
00225 case IA64_OPND_CLASS_IND:
00226 (*info->fprintf_func) (info->stream, "%s[r%d]", odesc->str, (int)value);
00227 break;
00228
00229 case IA64_OPND_CLASS_ABS:
00230 str = 0;
00231 if (odesc - elf64_ia64_operands == IA64_OPND_MBTYPE4)
00232 switch (value)
00233 {
00234 case 0x0: str = "@brcst"; break;
00235 case 0x8: str = "@mix"; break;
00236 case 0x9: str = "@shuf"; break;
00237 case 0xa: str = "@alt"; break;
00238 case 0xb: str = "@rev"; break;
00239 }
00240
00241 if (str)
00242 (*info->fprintf_func) (info->stream, "%s", str);
00243 else if (odesc->flags & IA64_OPND_FLAG_DECIMAL_SIGNED)
00244 (*info->fprintf_func) (info->stream, "%lld", value);
00245 else if (odesc->flags & IA64_OPND_FLAG_DECIMAL_UNSIGNED)
00246 (*info->fprintf_func) (info->stream, "%llu", value);
00247 else
00248 (*info->fprintf_func) (info->stream, "0x%llx", value);
00249 break;
00250
00251 case IA64_OPND_CLASS_REL:
00252 (*info->print_address_func) (memaddr + value, info);
00253 break;
00254 }
00255
00256 need_comma = 1;
00257 if (j + 1 == idesc->num_outputs)
00258 {
00259 (*info->fprintf_func) (info->stream, "=");
00260 need_comma = 0;
00261 }
00262 }
00263 if (slotnum + 1 == ia64_templ_desc[template].group_boundary
00264 || ((slotnum == 2) && s_bit))
00265 (*info->fprintf_func) (info->stream, ";;");
00266
00267 done:
00268 ia64_free_opcode ((struct ia64_opcode *)idesc);
00269 failed:
00270 if (slotnum == 2)
00271 retval += 16 - 3*slot_multiplier;
00272 return retval;
00273
00274 decoding_failed:
00275 (*info->fprintf_func) (info->stream, " data8 %#011llx", insn);
00276 goto failed;
00277 }