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