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