1 1.1 christos /* TI C6X disassembler. 2 1.10 christos Copyright (C) 2010-2025 Free Software Foundation, Inc. 3 1.1 christos Contributed by Joseph Myers <joseph (at) codesourcery.com> 4 1.1 christos Bernd Schmidt <bernds (at) codesourcery.com> 5 1.1 christos 6 1.1 christos This file is part of libopcodes. 7 1.1 christos 8 1.1 christos This library is free software; you can redistribute it and/or modify 9 1.1 christos it under the terms of the GNU General Public License as published by 10 1.1 christos the Free Software Foundation; either version 3 of the License, or 11 1.1 christos (at your option) any later version. 12 1.1 christos 13 1.1 christos It is distributed in the hope that it will be useful, but WITHOUT 14 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 16 1.1 christos License for more details. 17 1.1 christos 18 1.1 christos You should have received a copy of the GNU General Public License 19 1.1 christos along with this program; if not, write to the Free Software 20 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 21 1.1 christos MA 02110-1301, USA. */ 22 1.1 christos 23 1.1 christos #include "sysdep.h" 24 1.6 christos #include "disassemble.h" 25 1.1 christos #include "opcode/tic6x.h" 26 1.1 christos #include "libiberty.h" 27 1.1 christos 28 1.1 christos /* Define the instruction format table. */ 29 1.1 christos const tic6x_insn_format tic6x_insn_format_table[tic6x_insn_format_max] = 30 1.1 christos { 31 1.1 christos #define FMT(name, num_bits, cst_bits, mask, fields) \ 32 1.1 christos { num_bits, cst_bits, mask, fields }, 33 1.1 christos #include "opcode/tic6x-insn-formats.h" 34 1.1 christos #undef FMT 35 1.1 christos }; 36 1.1 christos 37 1.1 christos /* Define the control register table. */ 38 1.1 christos const tic6x_ctrl tic6x_ctrl_table[tic6x_ctrl_max] = 39 1.1 christos { 40 1.1 christos #define CTRL(name, isa, rw, crlo, crhi_mask) \ 41 1.1 christos { \ 42 1.1 christos STRINGX(name), \ 43 1.1 christos CONCAT2(TIC6X_INSN_,isa), \ 44 1.1 christos CONCAT2(tic6x_rw_,rw), \ 45 1.1 christos crlo, \ 46 1.1 christos crhi_mask \ 47 1.1 christos }, 48 1.1 christos #include "opcode/tic6x-control-registers.h" 49 1.1 christos #undef CTRL 50 1.1 christos }; 51 1.1 christos 52 1.1 christos /* Define the opcode table. */ 53 1.1 christos const tic6x_opcode tic6x_opcode_table[tic6x_opcode_max] = 54 1.1 christos { 55 1.3 christos #define INSNU(name, func_unit, format, type, isa, flags, fixed, ops, var) \ 56 1.3 christos { \ 57 1.3 christos STRINGX(name), \ 58 1.3 christos CONCAT2(tic6x_func_unit_,func_unit), \ 59 1.3 christos CONCAT3(tic6x_insn_format,_,format), \ 60 1.3 christos CONCAT2(tic6x_pipeline_,type), \ 61 1.3 christos CONCAT2(TIC6X_INSN_,isa), \ 62 1.3 christos flags, \ 63 1.3 christos fixed, \ 64 1.3 christos ops, \ 65 1.3 christos var \ 66 1.3 christos }, 67 1.3 christos #define INSNUE(name, e, func_unit, format, type, isa, flags, fixed, ops, var) \ 68 1.3 christos { \ 69 1.3 christos STRINGX(name), \ 70 1.3 christos CONCAT2(tic6x_func_unit_,func_unit), \ 71 1.3 christos CONCAT3(tic6x_insn_format,_,format), \ 72 1.3 christos CONCAT2(tic6x_pipeline_,type), \ 73 1.3 christos CONCAT2(TIC6X_INSN_,isa), \ 74 1.3 christos flags, \ 75 1.3 christos fixed, \ 76 1.3 christos ops, \ 77 1.3 christos var \ 78 1.3 christos }, 79 1.1 christos #define INSN(name, func_unit, format, type, isa, flags, fixed, ops, var) \ 80 1.1 christos { \ 81 1.1 christos STRINGX(name), \ 82 1.1 christos CONCAT2(tic6x_func_unit_,func_unit), \ 83 1.1 christos CONCAT4(tic6x_insn_format_,func_unit,_,format), \ 84 1.1 christos CONCAT2(tic6x_pipeline_,type), \ 85 1.1 christos CONCAT2(TIC6X_INSN_,isa), \ 86 1.1 christos flags, \ 87 1.1 christos fixed, \ 88 1.1 christos ops, \ 89 1.1 christos var \ 90 1.1 christos }, 91 1.1 christos #define INSNE(name, e, func_unit, format, type, isa, flags, fixed, ops, var) \ 92 1.1 christos { \ 93 1.1 christos STRINGX(name), \ 94 1.1 christos CONCAT2(tic6x_func_unit_,func_unit), \ 95 1.1 christos CONCAT4(tic6x_insn_format_,func_unit,_,format), \ 96 1.1 christos CONCAT2(tic6x_pipeline_,type), \ 97 1.1 christos CONCAT2(TIC6X_INSN_,isa), \ 98 1.1 christos flags, \ 99 1.1 christos fixed, \ 100 1.1 christos ops, \ 101 1.1 christos var \ 102 1.1 christos }, 103 1.1 christos #include "opcode/tic6x-opcode-table.h" 104 1.1 christos #undef INSN 105 1.1 christos #undef INSNE 106 1.3 christos #undef INSNU 107 1.3 christos #undef INSNUE 108 1.1 christos }; 109 1.1 christos 110 1.1 christos /* If instruction format FMT has a field FIELD, return a pointer to 111 1.1 christos the description of that field; otherwise return NULL. */ 112 1.1 christos 113 1.1 christos const tic6x_insn_field * 114 1.1 christos tic6x_field_from_fmt (const tic6x_insn_format *fmt, tic6x_insn_field_id field) 115 1.1 christos { 116 1.1 christos unsigned int f; 117 1.1 christos 118 1.1 christos for (f = 0; f < fmt->num_fields; f++) 119 1.1 christos if (fmt->fields[f].field_id == field) 120 1.1 christos return &fmt->fields[f]; 121 1.1 christos 122 1.1 christos return NULL; 123 1.1 christos } 124 1.1 christos 125 1.3 christos /* Extract the field width. */ 126 1.3 christos 127 1.3 christos static unsigned int 128 1.3 christos tic6x_field_width (const tic6x_insn_field *field) 129 1.3 christos { 130 1.3 christos unsigned int i; 131 1.3 christos unsigned int width = 0; 132 1.3 christos 133 1.3 christos if (!field->num_bitfields) 134 1.3 christos return field->bitfields[0].width; 135 1.3 christos 136 1.3 christos for (i = 0 ; i < field->num_bitfields ; i++) 137 1.3 christos width += field->bitfields[i].width; 138 1.3 christos 139 1.3 christos return width; 140 1.3 christos } 141 1.3 christos 142 1.1 christos /* Extract the bits corresponding to FIELD from OPCODE. */ 143 1.1 christos 144 1.1 christos static unsigned int 145 1.1 christos tic6x_field_bits (unsigned int opcode, const tic6x_insn_field *field) 146 1.1 christos { 147 1.3 christos unsigned int i; 148 1.3 christos unsigned int val = 0; 149 1.3 christos 150 1.3 christos if (!field->num_bitfields) 151 1.3 christos return (opcode >> field->bitfields[0].low_pos) & ((1u << field->bitfields[0].width) - 1); 152 1.3 christos 153 1.3 christos for (i = 0 ; i < field->num_bitfields ; i++) 154 1.3 christos val |= ((opcode >> field->bitfields[i].low_pos) & ((1u << field->bitfields[i].width) - 1)) 155 1.3 christos << field->bitfields[i].pos; 156 1.3 christos 157 1.3 christos return val; 158 1.1 christos } 159 1.1 christos 160 1.1 christos /* Extract a 32-bit value read from the instruction stream. */ 161 1.1 christos 162 1.1 christos static unsigned int 163 1.1 christos tic6x_extract_32 (unsigned char *p, struct disassemble_info *info) 164 1.1 christos { 165 1.1 christos if (info->endian == BFD_ENDIAN_LITTLE) 166 1.7 christos return p[0] | (p[1] << 8) | (p[2] << 16) | ((unsigned) p[3] << 24); 167 1.1 christos else 168 1.7 christos return p[3] | (p[2] << 8) | (p[1] << 16) | ((unsigned) p[0] << 24); 169 1.1 christos } 170 1.1 christos 171 1.1 christos /* Extract a 16-bit value read from the instruction stream. */ 172 1.1 christos 173 1.1 christos static unsigned int 174 1.3 christos tic6x_extract_16 (unsigned char *p, tic6x_fetch_packet_header *header, 175 1.3 christos struct disassemble_info *info) 176 1.1 christos { 177 1.3 christos unsigned int op16; 178 1.3 christos 179 1.1 christos if (info->endian == BFD_ENDIAN_LITTLE) 180 1.3 christos op16 = (p[0]) | (p[1] << 8); 181 1.1 christos else 182 1.3 christos op16 = (p[1]) | (p[0] << 8); 183 1.3 christos op16 |= (header->sat << TIC6X_COMPACT_SAT_POS); 184 1.3 christos op16 |= (header->br << TIC6X_COMPACT_BR_POS); 185 1.3 christos op16 |= (header->dsz << TIC6X_COMPACT_DSZ_POS); 186 1.3 christos return op16; 187 1.1 christos } 188 1.1 christos 189 1.1 christos /* FP points to a fetch packet. Return whether it is header-based; if 190 1.1 christos it is, fill in HEADER. */ 191 1.1 christos 192 1.8 christos static bool 193 1.1 christos tic6x_check_fetch_packet_header (unsigned char *fp, 194 1.1 christos tic6x_fetch_packet_header *header, 195 1.1 christos struct disassemble_info *info) 196 1.1 christos { 197 1.1 christos int i; 198 1.1 christos 199 1.1 christos header->header = tic6x_extract_32 (fp + 28, info); 200 1.3 christos 201 1.1 christos if ((header->header & 0xf0000000) != 0xe0000000) 202 1.3 christos { 203 1.3 christos header->prot = 0; 204 1.3 christos header->rs = 0; 205 1.3 christos header->dsz = 0; 206 1.3 christos header->br = 0; 207 1.3 christos header->sat = 0; 208 1.3 christos for (i = 0; i < 7; i++) 209 1.8 christos header->word_compact[i] = false; 210 1.3 christos for (i = 0; i < 14; i++) 211 1.8 christos header->p_bits[i] = false; 212 1.8 christos return false; 213 1.3 christos } 214 1.1 christos 215 1.1 christos for (i = 0; i < 7; i++) 216 1.1 christos header->word_compact[i] 217 1.8 christos = (header->header & (1u << (21 + i))) != 0; 218 1.1 christos 219 1.8 christos header->prot = (header->header & (1u << 20)) != 0; 220 1.8 christos header->rs = (header->header & (1u << 19)) != 0; 221 1.1 christos header->dsz = (header->header >> 16) & 0x7; 222 1.8 christos header->br = (header->header & (1u << 15)) != 0; 223 1.8 christos header->sat = (header->header & (1u << 14)) != 0; 224 1.1 christos 225 1.1 christos for (i = 0; i < 14; i++) 226 1.8 christos header->p_bits[i] = (header->header & (1u << i)) != 0; 227 1.1 christos 228 1.8 christos return true; 229 1.1 christos } 230 1.1 christos 231 1.1 christos /* Disassemble the instruction at ADDR and print it using 232 1.1 christos INFO->FPRINTF_FUNC and INFO->STREAM, returning the number of bytes 233 1.1 christos consumed. */ 234 1.1 christos 235 1.1 christos int 236 1.1 christos print_insn_tic6x (bfd_vma addr, struct disassemble_info *info) 237 1.1 christos { 238 1.1 christos int status; 239 1.1 christos bfd_vma fp_addr; 240 1.1 christos bfd_vma fp_offset; 241 1.1 christos unsigned char fp[32]; 242 1.1 christos unsigned int opcode; 243 1.1 christos tic6x_opcode_id opcode_id; 244 1.8 christos bool fetch_packet_header_based; 245 1.1 christos tic6x_fetch_packet_header header; 246 1.1 christos unsigned int num_bits; 247 1.8 christos bool bad_offset = false; 248 1.1 christos 249 1.1 christos fp_offset = addr & 0x1f; 250 1.1 christos fp_addr = addr - fp_offset; 251 1.3 christos /* Read in a block of instructions. Since there might be a 252 1.3 christos symbol in the middle of this block, disable stop_vma. */ 253 1.3 christos info->stop_vma = 0; 254 1.1 christos status = info->read_memory_func (fp_addr, fp, 32, info); 255 1.1 christos if (status) 256 1.1 christos { 257 1.1 christos info->memory_error_func (status, addr, info); 258 1.1 christos return -1; 259 1.1 christos } 260 1.1 christos 261 1.1 christos fetch_packet_header_based 262 1.1 christos = tic6x_check_fetch_packet_header (fp, &header, info); 263 1.1 christos if (fetch_packet_header_based) 264 1.1 christos { 265 1.1 christos if (fp_offset & 0x1) 266 1.8 christos bad_offset = true; 267 1.1 christos if ((fp_offset & 0x3) && (fp_offset >= 28 268 1.1 christos || !header.word_compact[fp_offset >> 2])) 269 1.8 christos bad_offset = true; 270 1.1 christos if (fp_offset == 28) 271 1.1 christos { 272 1.1 christos info->bytes_per_chunk = 4; 273 1.1 christos info->fprintf_func (info->stream, "<fetch packet header 0x%.8x>", 274 1.1 christos header.header); 275 1.1 christos return 4; 276 1.1 christos } 277 1.1 christos num_bits = (header.word_compact[fp_offset >> 2] ? 16 : 32); 278 1.1 christos } 279 1.1 christos else 280 1.1 christos { 281 1.1 christos num_bits = 32; 282 1.1 christos if (fp_offset & 0x3) 283 1.8 christos bad_offset = true; 284 1.1 christos } 285 1.1 christos 286 1.1 christos if (bad_offset) 287 1.1 christos { 288 1.1 christos info->bytes_per_chunk = 1; 289 1.1 christos info->fprintf_func (info->stream, ".byte 0x%.2x", fp[fp_offset]); 290 1.1 christos return 1; 291 1.1 christos } 292 1.1 christos 293 1.1 christos if (num_bits == 16) 294 1.1 christos { 295 1.1 christos /* The least-significant part of a 32-bit word comes logically 296 1.1 christos before the most-significant part. For big-endian, follow the 297 1.1 christos TI assembler in showing instructions in logical order by 298 1.1 christos pretending that the two halves of the word are in opposite 299 1.1 christos locations to where they actually are. */ 300 1.1 christos if (info->endian == BFD_ENDIAN_LITTLE) 301 1.3 christos opcode = tic6x_extract_16 (fp + fp_offset, &header, info); 302 1.1 christos else 303 1.3 christos opcode = tic6x_extract_16 (fp + (fp_offset ^ 2), &header, info); 304 1.1 christos } 305 1.1 christos else 306 1.1 christos opcode = tic6x_extract_32 (fp + fp_offset, info); 307 1.1 christos 308 1.1 christos for (opcode_id = 0; opcode_id < tic6x_opcode_max; opcode_id++) 309 1.1 christos { 310 1.1 christos const tic6x_opcode *const opc = &tic6x_opcode_table[opcode_id]; 311 1.1 christos const tic6x_insn_format *const fmt 312 1.1 christos = &tic6x_insn_format_table[opc->format]; 313 1.1 christos const tic6x_insn_field *creg_field; 314 1.8 christos bool p_bit; 315 1.1 christos const char *parallel; 316 1.1 christos const char *cond = ""; 317 1.1 christos const char *func_unit; 318 1.6 christos char func_unit_buf[8]; 319 1.1 christos unsigned int func_unit_side = 0; 320 1.1 christos unsigned int func_unit_data_side = 0; 321 1.1 christos unsigned int func_unit_cross = 0; 322 1.3 christos unsigned int t_val = 0; 323 1.1 christos /* The maximum length of the text of a non-PC-relative operand 324 1.1 christos is 24 bytes (SPMASK masking all eight functional units, with 325 1.1 christos separating commas and trailing NUL). */ 326 1.1 christos char operands[TIC6X_MAX_OPERANDS][24] = { { 0 } }; 327 1.1 christos bfd_vma operands_addresses[TIC6X_MAX_OPERANDS] = { 0 }; 328 1.8 christos bool operands_text[TIC6X_MAX_OPERANDS] = { false }; 329 1.8 christos bool operands_pcrel[TIC6X_MAX_OPERANDS] = { false }; 330 1.1 christos unsigned int fix; 331 1.1 christos unsigned int num_operands; 332 1.1 christos unsigned int op_num; 333 1.8 christos bool fixed_ok; 334 1.8 christos bool operands_ok; 335 1.8 christos bool have_t = false; 336 1.1 christos 337 1.1 christos if (opc->flags & TIC6X_FLAG_MACRO) 338 1.1 christos continue; 339 1.1 christos if (fmt->num_bits != num_bits) 340 1.1 christos continue; 341 1.1 christos if ((opcode & fmt->mask) != fmt->cst_bits) 342 1.1 christos continue; 343 1.1 christos 344 1.1 christos /* If the format has a creg field, it is only a candidate for a 345 1.1 christos match if the creg and z fields have values indicating a valid 346 1.1 christos condition; reserved values indicate either an instruction 347 1.1 christos format without a creg field, or an invalid instruction. */ 348 1.1 christos creg_field = tic6x_field_from_fmt (fmt, tic6x_field_creg); 349 1.1 christos if (creg_field) 350 1.1 christos { 351 1.1 christos const tic6x_insn_field *z_field; 352 1.1 christos unsigned int creg_value, z_value; 353 1.1 christos static const char *const conds[8][2] = 354 1.1 christos { 355 1.1 christos { "", NULL }, 356 1.1 christos { "[b0] ", "[!b0] " }, 357 1.1 christos { "[b1] ", "[!b1] " }, 358 1.1 christos { "[b2] ", "[!b2] " }, 359 1.1 christos { "[a1] ", "[!a1] " }, 360 1.1 christos { "[a2] ", "[!a2] " }, 361 1.1 christos { "[a0] ", "[!a0] " }, 362 1.1 christos { NULL, NULL } 363 1.1 christos }; 364 1.1 christos 365 1.1 christos /* A creg field is not meaningful without a z field, so if 366 1.1 christos the z field is not present this is an error in the format 367 1.1 christos table. */ 368 1.1 christos z_field = tic6x_field_from_fmt (fmt, tic6x_field_z); 369 1.1 christos if (!z_field) 370 1.3 christos { 371 1.3 christos printf ("*** opcode %x: missing z field", opcode); 372 1.3 christos abort (); 373 1.3 christos } 374 1.1 christos 375 1.1 christos creg_value = tic6x_field_bits (opcode, creg_field); 376 1.1 christos z_value = tic6x_field_bits (opcode, z_field); 377 1.1 christos cond = conds[creg_value][z_value]; 378 1.1 christos if (cond == NULL) 379 1.1 christos continue; 380 1.1 christos } 381 1.1 christos 382 1.3 christos if (opc->flags & TIC6X_FLAG_INSN16_SPRED) 383 1.3 christos { 384 1.3 christos const tic6x_insn_field *cc_field; 385 1.3 christos unsigned int s_value = 0; 386 1.3 christos unsigned int z_value = 0; 387 1.8 christos bool cond_known = false; 388 1.3 christos static const char *const conds[2][2] = 389 1.3 christos { 390 1.3 christos { "[a0] ", "[!a0] " }, 391 1.3 christos { "[b0] ", "[!b0] " } 392 1.3 christos }; 393 1.3 christos 394 1.3 christos cc_field = tic6x_field_from_fmt (fmt, tic6x_field_cc); 395 1.3 christos 396 1.3 christos if (cc_field) 397 1.3 christos { 398 1.3 christos unsigned int cc_value; 399 1.3 christos 400 1.3 christos cc_value = tic6x_field_bits (opcode, cc_field); 401 1.3 christos s_value = (cc_value & 0x2) >> 1; 402 1.3 christos z_value = (cc_value & 0x1); 403 1.8 christos cond_known = true; 404 1.3 christos } 405 1.3 christos else 406 1.3 christos { 407 1.3 christos const tic6x_insn_field *z_field; 408 1.3 christos const tic6x_insn_field *s_field; 409 1.3 christos 410 1.3 christos s_field = tic6x_field_from_fmt (fmt, tic6x_field_s); 411 1.3 christos 412 1.3 christos if (!s_field) 413 1.3 christos { 414 1.3 christos printf ("opcode %x: missing compact insn predicate register field (s field)\n", 415 1.3 christos opcode); 416 1.3 christos abort (); 417 1.3 christos } 418 1.3 christos s_value = tic6x_field_bits (opcode, s_field); 419 1.3 christos z_field = tic6x_field_from_fmt (fmt, tic6x_field_z); 420 1.3 christos if (!z_field) 421 1.3 christos { 422 1.3 christos printf ("opcode %x: missing compact insn predicate z_value (z field)\n", opcode); 423 1.3 christos abort (); 424 1.3 christos } 425 1.3 christos 426 1.3 christos z_value = tic6x_field_bits (opcode, z_field); 427 1.8 christos cond_known = true; 428 1.3 christos } 429 1.3 christos 430 1.3 christos if (!cond_known) 431 1.3 christos { 432 1.3 christos printf ("opcode %x: unspecified ompact insn predicate\n", opcode); 433 1.3 christos abort (); 434 1.3 christos } 435 1.3 christos cond = conds[s_value][z_value]; 436 1.3 christos } 437 1.3 christos 438 1.1 christos /* All fixed fields must have matching values; all fields with 439 1.1 christos restricted ranges must have values within those ranges. */ 440 1.8 christos fixed_ok = true; 441 1.1 christos for (fix = 0; fix < opc->num_fixed_fields; fix++) 442 1.1 christos { 443 1.1 christos unsigned int field_bits; 444 1.1 christos const tic6x_insn_field *const field 445 1.1 christos = tic6x_field_from_fmt (fmt, opc->fixed_fields[fix].field_id); 446 1.1 christos 447 1.1 christos if (!field) 448 1.3 christos { 449 1.3 christos printf ("opcode %x: missing field #%d for FIX #%d\n", 450 1.3 christos opcode, opc->fixed_fields[fix].field_id, fix); 451 1.3 christos abort (); 452 1.3 christos } 453 1.3 christos 454 1.1 christos field_bits = tic6x_field_bits (opcode, field); 455 1.1 christos if (field_bits < opc->fixed_fields[fix].min_val 456 1.1 christos || field_bits > opc->fixed_fields[fix].max_val) 457 1.1 christos { 458 1.8 christos fixed_ok = false; 459 1.1 christos break; 460 1.1 christos } 461 1.1 christos } 462 1.1 christos if (!fixed_ok) 463 1.1 christos continue; 464 1.1 christos 465 1.1 christos /* The instruction matches. */ 466 1.1 christos 467 1.1 christos /* The p-bit indicates whether this instruction is in parallel 468 1.1 christos with the *next* instruction, whereas the parallel bars 469 1.1 christos indicate the instruction is in parallel with the *previous* 470 1.1 christos instruction. Thus, we must find the p-bit for the previous 471 1.1 christos instruction. */ 472 1.1 christos if (num_bits == 16 && (fp_offset & 0x2) == 2) 473 1.1 christos { 474 1.1 christos /* This is the logically second (most significant; second in 475 1.1 christos fp_offset terms because fp_offset relates to logical not 476 1.1 christos physical addresses) instruction of a compact pair; find 477 1.1 christos the p-bit for the first (least significant). */ 478 1.1 christos p_bit = header.p_bits[(fp_offset >> 2) << 1]; 479 1.1 christos } 480 1.1 christos else if (fp_offset >= 4) 481 1.1 christos { 482 1.1 christos /* Find the last instruction of the previous word in this 483 1.1 christos fetch packet. For compact instructions, this is the most 484 1.1 christos significant 16 bits. */ 485 1.1 christos if (fetch_packet_header_based 486 1.1 christos && header.word_compact[(fp_offset >> 2) - 1]) 487 1.1 christos p_bit = header.p_bits[(fp_offset >> 1) - 1]; 488 1.1 christos else 489 1.1 christos { 490 1.1 christos unsigned int prev_opcode 491 1.1 christos = tic6x_extract_32 (fp + (fp_offset & 0x1c) - 4, info); 492 1.8 christos p_bit = (prev_opcode & 0x1) != 0; 493 1.1 christos } 494 1.1 christos } 495 1.1 christos else 496 1.1 christos { 497 1.1 christos /* Find the last instruction of the previous fetch 498 1.1 christos packet. */ 499 1.1 christos unsigned char fp_prev[32]; 500 1.3 christos 501 1.1 christos status = info->read_memory_func (fp_addr - 32, fp_prev, 32, info); 502 1.1 christos if (status) 503 1.1 christos /* No previous instruction to be parallel with. */ 504 1.8 christos p_bit = false; 505 1.1 christos else 506 1.1 christos { 507 1.8 christos bool prev_header_based; 508 1.1 christos tic6x_fetch_packet_header prev_header; 509 1.1 christos 510 1.1 christos prev_header_based 511 1.1 christos = tic6x_check_fetch_packet_header (fp_prev, &prev_header, info); 512 1.6 christos if (prev_header_based) 513 1.6 christos { 514 1.6 christos if (prev_header.word_compact[6]) 515 1.6 christos p_bit = prev_header.p_bits[13]; 516 1.6 christos else 517 1.6 christos { 518 1.6 christos unsigned int prev_opcode = tic6x_extract_32 (fp_prev + 24, 519 1.6 christos info); 520 1.8 christos p_bit = (prev_opcode & 0x1) != 0; 521 1.6 christos } 522 1.6 christos } 523 1.1 christos else 524 1.1 christos { 525 1.1 christos unsigned int prev_opcode = tic6x_extract_32 (fp_prev + 28, 526 1.1 christos info); 527 1.8 christos p_bit = (prev_opcode & 0x1) != 0; 528 1.1 christos } 529 1.1 christos } 530 1.1 christos } 531 1.1 christos parallel = p_bit ? "|| " : ""; 532 1.1 christos 533 1.1 christos if (opc->func_unit == tic6x_func_unit_nfu) 534 1.1 christos func_unit = ""; 535 1.1 christos else 536 1.1 christos { 537 1.1 christos unsigned int fld_num; 538 1.1 christos char func_unit_char; 539 1.1 christos const char *data_str; 540 1.8 christos bool have_areg = false; 541 1.8 christos bool have_cross = false; 542 1.1 christos 543 1.1 christos func_unit_side = (opc->flags & TIC6X_FLAG_SIDE_B_ONLY) ? 2 : 0; 544 1.1 christos func_unit_cross = 0; 545 1.1 christos func_unit_data_side = (opc->flags & TIC6X_FLAG_SIDE_T2_ONLY) ? 2 : 0; 546 1.1 christos 547 1.1 christos for (fld_num = 0; fld_num < opc->num_variable_fields; fld_num++) 548 1.1 christos { 549 1.1 christos const tic6x_coding_field *const enc = &opc->variable_fields[fld_num]; 550 1.1 christos const tic6x_insn_field *field; 551 1.1 christos unsigned int fld_val; 552 1.1 christos 553 1.1 christos field = tic6x_field_from_fmt (fmt, enc->field_id); 554 1.3 christos 555 1.1 christos if (!field) 556 1.3 christos { 557 1.3 christos printf ("opcode %x: could not retrieve field (field_id:%d)\n", 558 1.3 christos opcode, fld_num); 559 1.3 christos abort (); 560 1.3 christos } 561 1.3 christos 562 1.1 christos fld_val = tic6x_field_bits (opcode, field); 563 1.3 christos 564 1.1 christos switch (enc->coding_method) 565 1.1 christos { 566 1.1 christos case tic6x_coding_fu: 567 1.1 christos /* The side must be specified exactly once. */ 568 1.1 christos if (func_unit_side) 569 1.3 christos { 570 1.3 christos printf ("opcode %x: field #%d use tic6x_coding_fu, but func_unit_side is already set!\n", 571 1.3 christos opcode, fld_num); 572 1.3 christos abort (); 573 1.3 christos } 574 1.1 christos func_unit_side = (fld_val ? 2 : 1); 575 1.1 christos break; 576 1.1 christos 577 1.1 christos case tic6x_coding_data_fu: 578 1.1 christos /* The data side must be specified exactly once. */ 579 1.1 christos if (func_unit_data_side) 580 1.3 christos { 581 1.3 christos printf ("opcode %x: field #%d use tic6x_coding_fu, but func_unit_side is already set!\n", 582 1.3 christos opcode, fld_num); 583 1.3 christos abort (); 584 1.3 christos } 585 1.1 christos func_unit_data_side = (fld_val ? 2 : 1); 586 1.1 christos break; 587 1.1 christos 588 1.1 christos case tic6x_coding_xpath: 589 1.1 christos /* Cross path use must be specified exactly 590 1.1 christos once. */ 591 1.1 christos if (have_cross) 592 1.3 christos { 593 1.3 christos printf ("opcode %x: field #%d use tic6x_coding_xpath, have_cross is already set!\n", 594 1.3 christos opcode, fld_num); 595 1.3 christos abort (); 596 1.3 christos } 597 1.8 christos have_cross = true; 598 1.1 christos func_unit_cross = fld_val; 599 1.1 christos break; 600 1.1 christos 601 1.3 christos case tic6x_coding_rside: 602 1.3 christos /* If the format has a t field, use it for src/dst register side. */ 603 1.8 christos have_t = true; 604 1.3 christos t_val = fld_val; 605 1.3 christos func_unit_data_side = (t_val ? 2 : 1); 606 1.3 christos break; 607 1.3 christos 608 1.1 christos case tic6x_coding_areg: 609 1.8 christos have_areg = true; 610 1.1 christos break; 611 1.1 christos 612 1.1 christos default: 613 1.1 christos /* Don't relate to functional units. */ 614 1.1 christos break; 615 1.1 christos } 616 1.1 christos } 617 1.1 christos 618 1.1 christos /* The side of the functional unit used must now have been 619 1.1 christos determined either from the flags or from an instruction 620 1.1 christos field. */ 621 1.1 christos if (func_unit_side != 1 && func_unit_side != 2) 622 1.3 christos { 623 1.3 christos printf ("opcode %x: func_unit_side is not encoded!\n", opcode); 624 1.3 christos abort (); 625 1.3 christos } 626 1.1 christos 627 1.1 christos /* Cross paths are not applicable when sides are specified 628 1.1 christos for both address and data paths. */ 629 1.1 christos if (func_unit_data_side && have_cross) 630 1.3 christos { 631 1.3 christos printf ("opcode %x: xpath not applicable when side are specified both for address and data!\n", 632 1.3 christos opcode); 633 1.3 christos abort (); 634 1.3 christos } 635 1.1 christos 636 1.1 christos /* Separate address and data paths are only applicable for 637 1.1 christos the D unit. */ 638 1.1 christos if (func_unit_data_side && opc->func_unit != tic6x_func_unit_d) 639 1.3 christos { 640 1.3 christos printf ("opcode %x: separate address and data paths only applicable for D unit!\n", 641 1.3 christos opcode); 642 1.3 christos abort (); 643 1.3 christos } 644 1.1 christos 645 1.1 christos /* If an address register is being used but in ADDA rather 646 1.1 christos than a load or store, it uses a cross path for side-A 647 1.1 christos instructions, and the cross path use is not specified by 648 1.1 christos an instruction field. */ 649 1.1 christos if (have_areg && !func_unit_data_side) 650 1.1 christos { 651 1.1 christos if (have_cross) 652 1.3 christos { 653 1.3 christos printf ("opcode %x: illegal cross path specifier in adda opcode!\n", opcode); 654 1.3 christos abort (); 655 1.3 christos } 656 1.8 christos func_unit_cross = func_unit_side == 1; 657 1.1 christos } 658 1.1 christos 659 1.1 christos switch (opc->func_unit) 660 1.1 christos { 661 1.1 christos case tic6x_func_unit_d: 662 1.1 christos func_unit_char = 'D'; 663 1.1 christos break; 664 1.1 christos 665 1.1 christos case tic6x_func_unit_l: 666 1.1 christos func_unit_char = 'L'; 667 1.1 christos break; 668 1.1 christos 669 1.1 christos case tic6x_func_unit_m: 670 1.1 christos func_unit_char = 'M'; 671 1.1 christos break; 672 1.1 christos 673 1.1 christos case tic6x_func_unit_s: 674 1.1 christos func_unit_char = 'S'; 675 1.1 christos break; 676 1.1 christos 677 1.1 christos default: 678 1.3 christos printf ("opcode %x: illegal func_unit specifier %d\n", opcode, opc->func_unit); 679 1.1 christos abort (); 680 1.1 christos } 681 1.1 christos 682 1.1 christos switch (func_unit_data_side) 683 1.1 christos { 684 1.1 christos case 0: 685 1.1 christos data_str = ""; 686 1.1 christos break; 687 1.1 christos 688 1.1 christos case 1: 689 1.1 christos data_str = "T1"; 690 1.1 christos break; 691 1.1 christos 692 1.1 christos case 2: 693 1.1 christos data_str = "T2"; 694 1.1 christos break; 695 1.1 christos 696 1.1 christos default: 697 1.3 christos printf ("opcode %x: illegal data func_unit specifier %d\n", 698 1.3 christos opcode, func_unit_data_side); 699 1.1 christos abort (); 700 1.1 christos } 701 1.1 christos 702 1.3 christos if (opc->flags & TIC6X_FLAG_INSN16_BSIDE && func_unit_side == 1) 703 1.3 christos func_unit_cross = 1; 704 1.3 christos 705 1.6 christos snprintf (func_unit_buf, sizeof func_unit_buf, " .%c%u%s%s", 706 1.6 christos func_unit_char, func_unit_side, 707 1.6 christos (func_unit_cross ? "X" : ""), data_str); 708 1.1 christos func_unit = func_unit_buf; 709 1.1 christos } 710 1.1 christos 711 1.1 christos /* For each operand there must be one or more fields set based 712 1.1 christos on that operand, that can together be used to derive the 713 1.1 christos operand value. */ 714 1.8 christos operands_ok = true; 715 1.1 christos num_operands = opc->num_operands; 716 1.1 christos for (op_num = 0; op_num < num_operands; op_num++) 717 1.1 christos { 718 1.1 christos unsigned int fld_num; 719 1.1 christos unsigned int mem_base_reg = 0; 720 1.8 christos bool mem_base_reg_known = false; 721 1.8 christos bool mem_base_reg_known_long = false; 722 1.1 christos unsigned int mem_offset = 0; 723 1.8 christos bool mem_offset_known = false; 724 1.8 christos bool mem_offset_known_long = false; 725 1.1 christos unsigned int mem_mode = 0; 726 1.8 christos bool mem_mode_known = false; 727 1.1 christos unsigned int mem_scaled = 0; 728 1.8 christos bool mem_scaled_known = false; 729 1.1 christos unsigned int crlo = 0; 730 1.8 christos bool crlo_known = false; 731 1.1 christos unsigned int crhi = 0; 732 1.8 christos bool crhi_known = false; 733 1.8 christos bool spmask_skip_operand = false; 734 1.1 christos unsigned int fcyc_bits = 0; 735 1.8 christos bool prev_sploop_found = false; 736 1.1 christos 737 1.1 christos switch (opc->operand_info[op_num].form) 738 1.1 christos { 739 1.3 christos case tic6x_operand_b15reg: 740 1.3 christos /* Fully determined by the functional unit. */ 741 1.8 christos operands_text[op_num] = true; 742 1.3 christos snprintf (operands[op_num], 24, "b15"); 743 1.3 christos continue; 744 1.3 christos 745 1.3 christos case tic6x_operand_zreg: 746 1.3 christos /* Fully determined by the functional unit. */ 747 1.8 christos operands_text[op_num] = true; 748 1.3 christos snprintf (operands[op_num], 24, "%c0", 749 1.3 christos (func_unit_side == 2 ? 'b' : 'a')); 750 1.3 christos continue; 751 1.3 christos 752 1.1 christos case tic6x_operand_retreg: 753 1.1 christos /* Fully determined by the functional unit. */ 754 1.8 christos operands_text[op_num] = true; 755 1.1 christos snprintf (operands[op_num], 24, "%c3", 756 1.1 christos (func_unit_side == 2 ? 'b' : 'a')); 757 1.1 christos continue; 758 1.1 christos 759 1.1 christos case tic6x_operand_irp: 760 1.8 christos operands_text[op_num] = true; 761 1.1 christos snprintf (operands[op_num], 24, "irp"); 762 1.1 christos continue; 763 1.1 christos 764 1.1 christos case tic6x_operand_nrp: 765 1.8 christos operands_text[op_num] = true; 766 1.1 christos snprintf (operands[op_num], 24, "nrp"); 767 1.1 christos continue; 768 1.1 christos 769 1.3 christos case tic6x_operand_ilc: 770 1.8 christos operands_text[op_num] = true; 771 1.3 christos snprintf (operands[op_num], 24, "ilc"); 772 1.3 christos continue; 773 1.3 christos 774 1.3 christos case tic6x_operand_hw_const_minus_1: 775 1.8 christos operands_text[op_num] = true; 776 1.3 christos snprintf (operands[op_num], 24, "-1"); 777 1.3 christos continue; 778 1.3 christos 779 1.3 christos case tic6x_operand_hw_const_0: 780 1.8 christos operands_text[op_num] = true; 781 1.3 christos snprintf (operands[op_num], 24, "0"); 782 1.3 christos continue; 783 1.3 christos 784 1.3 christos case tic6x_operand_hw_const_1: 785 1.8 christos operands_text[op_num] = true; 786 1.3 christos snprintf (operands[op_num], 24, "1"); 787 1.3 christos continue; 788 1.3 christos 789 1.3 christos case tic6x_operand_hw_const_5: 790 1.8 christos operands_text[op_num] = true; 791 1.3 christos snprintf (operands[op_num], 24, "5"); 792 1.3 christos continue; 793 1.3 christos 794 1.3 christos case tic6x_operand_hw_const_16: 795 1.8 christos operands_text[op_num] = true; 796 1.3 christos snprintf (operands[op_num], 24, "16"); 797 1.3 christos continue; 798 1.3 christos 799 1.3 christos case tic6x_operand_hw_const_24: 800 1.8 christos operands_text[op_num] = true; 801 1.3 christos snprintf (operands[op_num], 24, "24"); 802 1.3 christos continue; 803 1.3 christos 804 1.3 christos case tic6x_operand_hw_const_31: 805 1.8 christos operands_text[op_num] = true; 806 1.3 christos snprintf (operands[op_num], 24, "31"); 807 1.3 christos continue; 808 1.3 christos 809 1.1 christos default: 810 1.1 christos break; 811 1.1 christos } 812 1.1 christos 813 1.1 christos for (fld_num = 0; fld_num < opc->num_variable_fields; fld_num++) 814 1.1 christos { 815 1.1 christos const tic6x_coding_field *const enc 816 1.1 christos = &opc->variable_fields[fld_num]; 817 1.1 christos const tic6x_insn_field *field; 818 1.1 christos unsigned int fld_val; 819 1.3 christos unsigned int reg_base = 0; 820 1.1 christos signed int signed_fld_val; 821 1.3 christos char reg_side = '?'; 822 1.1 christos 823 1.1 christos if (enc->operand_num != op_num) 824 1.1 christos continue; 825 1.1 christos field = tic6x_field_from_fmt (fmt, enc->field_id); 826 1.1 christos if (!field) 827 1.3 christos { 828 1.3 christos printf ("opcode %x: missing field (field_id:%d) in format\n", opcode, enc->field_id); 829 1.3 christos abort (); 830 1.3 christos } 831 1.3 christos fld_val = tic6x_field_bits (opcode, field); 832 1.1 christos switch (enc->coding_method) 833 1.1 christos { 834 1.3 christos case tic6x_coding_cst_s3i: 835 1.3 christos (fld_val == 0x00) && (fld_val = 0x10); 836 1.3 christos (fld_val == 0x07) && (fld_val = 0x08); 837 1.3 christos /* Fall through. */ 838 1.1 christos case tic6x_coding_ucst: 839 1.1 christos case tic6x_coding_ulcst_dpr_byte: 840 1.1 christos case tic6x_coding_ulcst_dpr_half: 841 1.1 christos case tic6x_coding_ulcst_dpr_word: 842 1.1 christos case tic6x_coding_lcst_low16: 843 1.1 christos switch (opc->operand_info[op_num].form) 844 1.1 christos { 845 1.1 christos case tic6x_operand_asm_const: 846 1.1 christos case tic6x_operand_link_const: 847 1.8 christos operands_text[op_num] = true; 848 1.1 christos snprintf (operands[op_num], 24, "%u", fld_val); 849 1.1 christos break; 850 1.1 christos 851 1.1 christos case tic6x_operand_mem_long: 852 1.1 christos mem_offset = fld_val; 853 1.8 christos mem_offset_known_long = true; 854 1.1 christos break; 855 1.1 christos 856 1.1 christos default: 857 1.3 christos printf ("opcode %x: illegal operand form for operand#%d\n", opcode, op_num); 858 1.1 christos abort (); 859 1.1 christos } 860 1.1 christos break; 861 1.1 christos 862 1.1 christos case tic6x_coding_lcst_high16: 863 1.8 christos operands_text[op_num] = true; 864 1.1 christos snprintf (operands[op_num], 24, "%u", fld_val << 16); 865 1.1 christos break; 866 1.1 christos 867 1.3 christos case tic6x_coding_scst_l3i: 868 1.8 christos operands_text[op_num] = true; 869 1.3 christos if (fld_val == 0) 870 1.3 christos { 871 1.3 christos signed_fld_val = 8; 872 1.3 christos } 873 1.3 christos else 874 1.3 christos { 875 1.3 christos signed_fld_val = (signed int) fld_val; 876 1.3 christos signed_fld_val ^= (1 << (tic6x_field_width (field) - 1)); 877 1.3 christos signed_fld_val -= (1 << (tic6x_field_width (field) - 1)); 878 1.3 christos } 879 1.3 christos snprintf (operands[op_num], 24, "%d", signed_fld_val); 880 1.3 christos break; 881 1.3 christos 882 1.1 christos case tic6x_coding_scst: 883 1.8 christos operands_text[op_num] = true; 884 1.1 christos signed_fld_val = (signed int) fld_val; 885 1.3 christos signed_fld_val ^= (1 << (tic6x_field_width (field) - 1)); 886 1.3 christos signed_fld_val -= (1 << (tic6x_field_width (field) - 1)); 887 1.1 christos snprintf (operands[op_num], 24, "%d", signed_fld_val); 888 1.1 christos break; 889 1.1 christos 890 1.1 christos case tic6x_coding_ucst_minus_one: 891 1.8 christos operands_text[op_num] = true; 892 1.1 christos snprintf (operands[op_num], 24, "%u", fld_val + 1); 893 1.1 christos break; 894 1.1 christos 895 1.1 christos case tic6x_coding_pcrel: 896 1.1 christos case tic6x_coding_pcrel_half: 897 1.1 christos signed_fld_val = (signed int) fld_val; 898 1.3 christos signed_fld_val ^= (1 << (tic6x_field_width (field) - 1)); 899 1.3 christos signed_fld_val -= (1 << (tic6x_field_width (field) - 1)); 900 1.1 christos if (fetch_packet_header_based 901 1.1 christos && enc->coding_method == tic6x_coding_pcrel_half) 902 1.1 christos signed_fld_val *= 2; 903 1.1 christos else 904 1.1 christos signed_fld_val *= 4; 905 1.8 christos operands_pcrel[op_num] = true; 906 1.1 christos operands_addresses[op_num] = fp_addr + signed_fld_val; 907 1.1 christos break; 908 1.1 christos 909 1.3 christos case tic6x_coding_regpair_msb: 910 1.3 christos if (opc->operand_info[op_num].form != tic6x_operand_regpair) 911 1.3 christos abort (); 912 1.8 christos operands_text[op_num] = true; 913 1.3 christos snprintf (operands[op_num], 24, "%c%u:%c%u", 914 1.3 christos (func_unit_side == 2 ? 'b' : 'a'), (fld_val | 0x1), 915 1.3 christos (func_unit_side == 2 ? 'b' : 'a'), (fld_val | 0x1) - 1); 916 1.3 christos break; 917 1.3 christos 918 1.3 christos case tic6x_coding_pcrel_half_unsigned: 919 1.8 christos operands_pcrel[op_num] = true; 920 1.3 christos operands_addresses[op_num] = fp_addr + 2 * fld_val; 921 1.3 christos break; 922 1.3 christos 923 1.1 christos case tic6x_coding_reg_shift: 924 1.1 christos fld_val <<= 1; 925 1.1 christos /* Fall through. */ 926 1.1 christos case tic6x_coding_reg: 927 1.3 christos if (num_bits == 16 && header.rs && !(opc->flags & TIC6X_FLAG_INSN16_NORS)) 928 1.3 christos { 929 1.3 christos reg_base = 16; 930 1.3 christos } 931 1.1 christos switch (opc->operand_info[op_num].form) 932 1.1 christos { 933 1.3 christos case tic6x_operand_treg: 934 1.3 christos if (!have_t) 935 1.3 christos { 936 1.3 christos printf ("opcode %x: operand treg but missing t field\n", opcode); 937 1.3 christos abort (); 938 1.3 christos } 939 1.8 christos operands_text[op_num] = true; 940 1.3 christos reg_side = t_val ? 'b' : 'a'; 941 1.3 christos snprintf (operands[op_num], 24, "%c%u", reg_side, reg_base + fld_val); 942 1.3 christos break; 943 1.3 christos 944 1.1 christos case tic6x_operand_reg: 945 1.8 christos operands_text[op_num] = true; 946 1.3 christos reg_side = (func_unit_side == 2) ? 'b' : 'a'; 947 1.3 christos snprintf (operands[op_num], 24, "%c%u", reg_side, reg_base + fld_val); 948 1.3 christos break; 949 1.3 christos 950 1.3 christos case tic6x_operand_reg_nors: 951 1.8 christos operands_text[op_num] = true; 952 1.3 christos reg_side = (func_unit_side == 2) ? 'b' : 'a'; 953 1.3 christos snprintf (operands[op_num], 24, "%c%u", reg_side, fld_val); 954 1.3 christos break; 955 1.3 christos 956 1.3 christos case tic6x_operand_reg_bside: 957 1.8 christos operands_text[op_num] = true; 958 1.3 christos snprintf (operands[op_num], 24, "b%u", reg_base + fld_val); 959 1.3 christos break; 960 1.3 christos 961 1.3 christos case tic6x_operand_reg_bside_nors: 962 1.8 christos operands_text[op_num] = true; 963 1.3 christos snprintf (operands[op_num], 24, "b%u", fld_val); 964 1.1 christos break; 965 1.1 christos 966 1.1 christos case tic6x_operand_xreg: 967 1.8 christos operands_text[op_num] = true; 968 1.3 christos reg_side = ((func_unit_side == 2) ^ func_unit_cross) ? 'b' : 'a'; 969 1.3 christos snprintf (operands[op_num], 24, "%c%u", reg_side, reg_base + fld_val); 970 1.1 christos break; 971 1.1 christos 972 1.1 christos case tic6x_operand_dreg: 973 1.8 christos operands_text[op_num] = true; 974 1.3 christos reg_side = (func_unit_data_side == 2) ? 'b' : 'a'; 975 1.3 christos snprintf (operands[op_num], 24, "%c%u", reg_side, reg_base + fld_val); 976 1.1 christos break; 977 1.1 christos 978 1.1 christos case tic6x_operand_regpair: 979 1.8 christos operands_text[op_num] = true; 980 1.1 christos if (fld_val & 1) 981 1.8 christos operands_ok = false; 982 1.3 christos reg_side = (func_unit_side == 2) ? 'b' : 'a'; 983 1.1 christos snprintf (operands[op_num], 24, "%c%u:%c%u", 984 1.3 christos reg_side, reg_base + fld_val + 1, 985 1.3 christos reg_side, reg_base + fld_val); 986 1.1 christos break; 987 1.1 christos 988 1.1 christos case tic6x_operand_xregpair: 989 1.8 christos operands_text[op_num] = true; 990 1.1 christos if (fld_val & 1) 991 1.8 christos operands_ok = false; 992 1.3 christos reg_side = ((func_unit_side == 2) ^ func_unit_cross) ? 'b' : 'a'; 993 1.1 christos snprintf (operands[op_num], 24, "%c%u:%c%u", 994 1.3 christos reg_side, reg_base + fld_val + 1, 995 1.3 christos reg_side, reg_base + fld_val); 996 1.3 christos break; 997 1.3 christos 998 1.3 christos case tic6x_operand_tregpair: 999 1.3 christos if (!have_t) 1000 1.3 christos { 1001 1.3 christos printf ("opcode %x: operand tregpair but missing t field\n", opcode); 1002 1.3 christos abort (); 1003 1.3 christos } 1004 1.8 christos operands_text[op_num] = true; 1005 1.3 christos if (fld_val & 1) 1006 1.8 christos operands_ok = false; 1007 1.3 christos reg_side = t_val ? 'b' : 'a'; 1008 1.3 christos snprintf (operands[op_num], 24, "%c%u:%c%u", 1009 1.3 christos reg_side, reg_base + fld_val + 1, 1010 1.3 christos reg_side, reg_base + fld_val); 1011 1.1 christos break; 1012 1.1 christos 1013 1.1 christos case tic6x_operand_dregpair: 1014 1.8 christos operands_text[op_num] = true; 1015 1.1 christos if (fld_val & 1) 1016 1.8 christos operands_ok = false; 1017 1.3 christos reg_side = (func_unit_data_side) == 2 ? 'b' : 'a'; 1018 1.1 christos snprintf (operands[op_num], 24, "%c%u:%c%u", 1019 1.3 christos reg_side, reg_base + fld_val + 1, 1020 1.3 christos reg_side, reg_base + fld_val); 1021 1.1 christos break; 1022 1.1 christos 1023 1.1 christos case tic6x_operand_mem_deref: 1024 1.8 christos operands_text[op_num] = true; 1025 1.3 christos reg_side = func_unit_side == 2 ? 'b' : 'a'; 1026 1.3 christos snprintf (operands[op_num], 24, "*%c%u", reg_side, reg_base + fld_val); 1027 1.1 christos break; 1028 1.1 christos 1029 1.1 christos case tic6x_operand_mem_short: 1030 1.1 christos case tic6x_operand_mem_ndw: 1031 1.1 christos mem_base_reg = fld_val; 1032 1.8 christos mem_base_reg_known = true; 1033 1.1 christos break; 1034 1.1 christos 1035 1.1 christos default: 1036 1.3 christos printf ("opcode %x: unexpected operand form %d for operand #%d", 1037 1.3 christos opcode, opc->operand_info[op_num].form, op_num); 1038 1.3 christos abort (); 1039 1.3 christos } 1040 1.3 christos break; 1041 1.3 christos 1042 1.3 christos case tic6x_coding_reg_ptr: 1043 1.3 christos switch (opc->operand_info[op_num].form) 1044 1.3 christos { 1045 1.3 christos case tic6x_operand_mem_short: 1046 1.3 christos case tic6x_operand_mem_ndw: 1047 1.3 christos if (fld_val > 0x3u) 1048 1.3 christos { 1049 1.3 christos printf("opcode %x: illegal field value for ptr register of operand #%d (%d)", 1050 1.3 christos opcode, op_num, fld_val); 1051 1.3 christos abort (); 1052 1.3 christos } 1053 1.3 christos mem_base_reg = 0x4 | fld_val; 1054 1.8 christos mem_base_reg_known = true; 1055 1.3 christos break; 1056 1.3 christos 1057 1.3 christos default: 1058 1.3 christos printf ("opcode %x: unexpected operand form %d for operand #%d", 1059 1.3 christos opcode, opc->operand_info[op_num].form, op_num); 1060 1.1 christos abort (); 1061 1.1 christos } 1062 1.1 christos break; 1063 1.1 christos 1064 1.1 christos case tic6x_coding_areg: 1065 1.1 christos switch (opc->operand_info[op_num].form) 1066 1.1 christos { 1067 1.1 christos case tic6x_operand_areg: 1068 1.8 christos operands_text[op_num] = true; 1069 1.1 christos snprintf (operands[op_num], 24, "b%u", 1070 1.1 christos fld_val ? 15u : 14u); 1071 1.1 christos break; 1072 1.1 christos 1073 1.1 christos case tic6x_operand_mem_long: 1074 1.1 christos mem_base_reg = fld_val ? 15u : 14u; 1075 1.8 christos mem_base_reg_known_long = true; 1076 1.1 christos break; 1077 1.1 christos 1078 1.1 christos default: 1079 1.3 christos printf ("opcode %x: bad operand form\n", opcode); 1080 1.1 christos abort (); 1081 1.1 christos } 1082 1.1 christos break; 1083 1.1 christos 1084 1.3 christos case tic6x_coding_mem_offset_minus_one_noscale: 1085 1.3 christos case tic6x_coding_mem_offset_minus_one: 1086 1.3 christos fld_val += 1; 1087 1.6 christos /* Fall through. */ 1088 1.3 christos case tic6x_coding_mem_offset_noscale: 1089 1.1 christos case tic6x_coding_mem_offset: 1090 1.1 christos mem_offset = fld_val; 1091 1.8 christos mem_offset_known = true; 1092 1.3 christos if (num_bits == 16) 1093 1.3 christos { 1094 1.8 christos mem_mode_known = true; 1095 1.3 christos mem_mode = TIC6X_INSN16_MEM_MODE_VAL (opc->flags); 1096 1.8 christos mem_scaled_known = true; 1097 1.8 christos mem_scaled = true; 1098 1.3 christos if (opc->flags & TIC6X_FLAG_INSN16_B15PTR) 1099 1.3 christos { 1100 1.8 christos mem_base_reg_known = true; 1101 1.3 christos mem_base_reg = 15; 1102 1.3 christos } 1103 1.3 christos if ( enc->coding_method == tic6x_coding_mem_offset_noscale 1104 1.3 christos || enc->coding_method == tic6x_coding_mem_offset_noscale ) 1105 1.8 christos mem_scaled = false; 1106 1.3 christos } 1107 1.1 christos break; 1108 1.1 christos 1109 1.1 christos case tic6x_coding_mem_mode: 1110 1.1 christos mem_mode = fld_val; 1111 1.8 christos mem_mode_known = true; 1112 1.1 christos break; 1113 1.1 christos 1114 1.1 christos case tic6x_coding_scaled: 1115 1.1 christos mem_scaled = fld_val; 1116 1.8 christos mem_scaled_known = true; 1117 1.1 christos break; 1118 1.1 christos 1119 1.1 christos case tic6x_coding_crlo: 1120 1.1 christos crlo = fld_val; 1121 1.8 christos crlo_known = true; 1122 1.1 christos break; 1123 1.1 christos 1124 1.1 christos case tic6x_coding_crhi: 1125 1.1 christos crhi = fld_val; 1126 1.8 christos crhi_known = true; 1127 1.1 christos break; 1128 1.1 christos 1129 1.1 christos case tic6x_coding_fstg: 1130 1.1 christos case tic6x_coding_fcyc: 1131 1.1 christos if (!prev_sploop_found) 1132 1.1 christos { 1133 1.1 christos bfd_vma search_fp_addr = fp_addr; 1134 1.1 christos bfd_vma search_fp_offset = fp_offset; 1135 1.8 christos bool search_fp_header_based 1136 1.1 christos = fetch_packet_header_based; 1137 1.1 christos tic6x_fetch_packet_header search_fp_header = header; 1138 1.1 christos unsigned char search_fp[32]; 1139 1.1 christos unsigned int search_num_bits; 1140 1.1 christos unsigned int search_opcode; 1141 1.1 christos unsigned int sploop_ii = 0; 1142 1.1 christos int i; 1143 1.1 christos 1144 1.1 christos memcpy (search_fp, fp, 32); 1145 1.1 christos 1146 1.1 christos /* To interpret these bits in an SPKERNEL 1147 1.1 christos instruction, we must find the previous 1148 1.1 christos SPLOOP-family instruction. It may come up to 1149 1.1 christos 48 execute packets earlier. */ 1150 1.1 christos for (i = 0; i < 48 * 8; i++) 1151 1.1 christos { 1152 1.1 christos /* Find the previous instruction. */ 1153 1.1 christos if (search_fp_offset & 2) 1154 1.1 christos search_fp_offset -= 2; 1155 1.1 christos else if (search_fp_offset >= 4) 1156 1.1 christos { 1157 1.1 christos if (search_fp_header_based 1158 1.1 christos && (search_fp_header.word_compact 1159 1.1 christos [(search_fp_offset >> 2) - 1])) 1160 1.1 christos search_fp_offset -= 2; 1161 1.1 christos else 1162 1.1 christos search_fp_offset -= 4; 1163 1.1 christos } 1164 1.1 christos else 1165 1.1 christos { 1166 1.1 christos search_fp_addr -= 32; 1167 1.1 christos status = info->read_memory_func (search_fp_addr, 1168 1.1 christos search_fp, 1169 1.1 christos 32, info); 1170 1.1 christos if (status) 1171 1.1 christos /* No previous SPLOOP instruction. */ 1172 1.1 christos break; 1173 1.1 christos search_fp_header_based 1174 1.1 christos = (tic6x_check_fetch_packet_header 1175 1.1 christos (search_fp, &search_fp_header, info)); 1176 1.1 christos if (search_fp_header_based) 1177 1.1 christos search_fp_offset 1178 1.1 christos = search_fp_header.word_compact[6] ? 26 : 24; 1179 1.1 christos else 1180 1.1 christos search_fp_offset = 28; 1181 1.1 christos } 1182 1.1 christos 1183 1.1 christos /* Extract the previous instruction. */ 1184 1.1 christos if (search_fp_header_based) 1185 1.1 christos search_num_bits 1186 1.1 christos = (search_fp_header.word_compact[search_fp_offset 1187 1.1 christos >> 2] 1188 1.1 christos ? 16 1189 1.1 christos : 32); 1190 1.1 christos else 1191 1.1 christos search_num_bits = 32; 1192 1.1 christos if (search_num_bits == 16) 1193 1.1 christos { 1194 1.1 christos if (info->endian == BFD_ENDIAN_LITTLE) 1195 1.1 christos search_opcode 1196 1.1 christos = (tic6x_extract_16 1197 1.3 christos (search_fp + search_fp_offset, &header, info)); 1198 1.1 christos else 1199 1.1 christos search_opcode 1200 1.1 christos = (tic6x_extract_16 1201 1.3 christos (search_fp + (search_fp_offset ^ 2), &header, 1202 1.1 christos info)); 1203 1.1 christos } 1204 1.1 christos else 1205 1.1 christos search_opcode 1206 1.1 christos = tic6x_extract_32 (search_fp + search_fp_offset, 1207 1.1 christos info); 1208 1.1 christos 1209 1.1 christos /* Check whether it is an SPLOOP-family 1210 1.1 christos instruction. */ 1211 1.1 christos if (search_num_bits == 32 1212 1.1 christos && ((search_opcode & 0x003ffffe) == 0x00038000 1213 1.1 christos || (search_opcode & 0x003ffffe) == 0x0003a000 1214 1.1 christos || ((search_opcode & 0x003ffffe) 1215 1.1 christos == 0x0003e000))) 1216 1.1 christos { 1217 1.8 christos prev_sploop_found = true; 1218 1.1 christos sploop_ii = ((search_opcode >> 23) & 0x1f) + 1; 1219 1.1 christos } 1220 1.1 christos else if (search_num_bits == 16 1221 1.1 christos && (search_opcode & 0x3c7e) == 0x0c66) 1222 1.1 christos { 1223 1.8 christos prev_sploop_found = true; 1224 1.1 christos sploop_ii 1225 1.1 christos = (((search_opcode >> 7) & 0x7) 1226 1.1 christos | ((search_opcode >> 11) & 0x8)) + 1; 1227 1.1 christos } 1228 1.1 christos if (prev_sploop_found) 1229 1.1 christos { 1230 1.1 christos if (sploop_ii <= 0) 1231 1.3 christos { 1232 1.3 christos printf ("opcode %x: sloop index not found (%d)\n", opcode, sploop_ii); 1233 1.3 christos abort (); 1234 1.3 christos } 1235 1.1 christos else if (sploop_ii <= 1) 1236 1.1 christos fcyc_bits = 0; 1237 1.1 christos else if (sploop_ii <= 2) 1238 1.1 christos fcyc_bits = 1; 1239 1.1 christos else if (sploop_ii <= 4) 1240 1.1 christos fcyc_bits = 2; 1241 1.1 christos else if (sploop_ii <= 8) 1242 1.1 christos fcyc_bits = 3; 1243 1.1 christos else if (sploop_ii <= 14) 1244 1.1 christos fcyc_bits = 4; 1245 1.1 christos else 1246 1.8 christos prev_sploop_found = false; 1247 1.1 christos } 1248 1.1 christos if (prev_sploop_found) 1249 1.1 christos break; 1250 1.1 christos } 1251 1.1 christos } 1252 1.1 christos if (!prev_sploop_found) 1253 1.1 christos { 1254 1.8 christos operands_ok = false; 1255 1.8 christos operands_text[op_num] = true; 1256 1.1 christos break; 1257 1.1 christos } 1258 1.3 christos if (fcyc_bits > tic6x_field_width(field)) 1259 1.3 christos { 1260 1.3 christos printf ("opcode %x: illegal fcyc value (%d)\n", opcode, fcyc_bits); 1261 1.3 christos abort (); 1262 1.3 christos } 1263 1.1 christos if (enc->coding_method == tic6x_coding_fstg) 1264 1.1 christos { 1265 1.1 christos int i, t; 1266 1.1 christos for (t = 0, i = fcyc_bits; i < 6; i++) 1267 1.1 christos t = (t << 1) | ((fld_val >> i) & 1); 1268 1.8 christos operands_text[op_num] = true; 1269 1.1 christos snprintf (operands[op_num], 24, "%u", t); 1270 1.1 christos } 1271 1.1 christos else 1272 1.1 christos { 1273 1.8 christos operands_text[op_num] = true; 1274 1.1 christos snprintf (operands[op_num], 24, "%u", 1275 1.1 christos fld_val & ((1 << fcyc_bits) - 1)); 1276 1.1 christos } 1277 1.1 christos break; 1278 1.1 christos 1279 1.1 christos case tic6x_coding_spmask: 1280 1.1 christos if (fld_val == 0) 1281 1.8 christos spmask_skip_operand = true; 1282 1.1 christos else 1283 1.1 christos { 1284 1.1 christos char *p; 1285 1.1 christos unsigned int i; 1286 1.1 christos 1287 1.8 christos operands_text[op_num] = true; 1288 1.1 christos p = operands[op_num]; 1289 1.1 christos for (i = 0; i < 8; i++) 1290 1.1 christos if (fld_val & (1 << i)) 1291 1.1 christos { 1292 1.1 christos *p++ = "LSDM"[i/2]; 1293 1.1 christos *p++ = '1' + (i & 1); 1294 1.1 christos *p++ = ','; 1295 1.1 christos } 1296 1.1 christos p[-1] = 0; 1297 1.1 christos } 1298 1.1 christos break; 1299 1.1 christos 1300 1.1 christos case tic6x_coding_fu: 1301 1.1 christos case tic6x_coding_data_fu: 1302 1.1 christos case tic6x_coding_xpath: 1303 1.3 christos case tic6x_coding_rside: 1304 1.1 christos /* Don't relate to operands, so operand number is 1305 1.1 christos meaningless. */ 1306 1.1 christos break; 1307 1.1 christos 1308 1.1 christos default: 1309 1.3 christos printf ("opcode %x: illegal field encoding (%d)\n", opcode, enc->coding_method); 1310 1.1 christos abort (); 1311 1.1 christos } 1312 1.1 christos 1313 1.1 christos if (mem_base_reg_known_long && mem_offset_known_long) 1314 1.1 christos { 1315 1.1 christos if (operands_text[op_num] || operands_pcrel[op_num]) 1316 1.3 christos { 1317 1.3 christos printf ("opcode %x: long access but operands already known ?\n", opcode); 1318 1.3 christos abort (); 1319 1.3 christos } 1320 1.8 christos operands_text[op_num] = true; 1321 1.1 christos snprintf (operands[op_num], 24, "*+b%u(%u)", mem_base_reg, 1322 1.1 christos mem_offset * opc->operand_info[op_num].size); 1323 1.1 christos } 1324 1.1 christos 1325 1.1 christos if (mem_base_reg_known && mem_offset_known && mem_mode_known 1326 1.1 christos && (mem_scaled_known 1327 1.1 christos || (opc->operand_info[op_num].form 1328 1.1 christos != tic6x_operand_mem_ndw))) 1329 1.1 christos { 1330 1.1 christos char side; 1331 1.1 christos char base[4]; 1332 1.8 christos bool offset_is_reg; 1333 1.8 christos bool offset_scaled; 1334 1.1 christos char offset[4]; 1335 1.1 christos char offsetp[6]; 1336 1.1 christos 1337 1.1 christos if (operands_text[op_num] || operands_pcrel[op_num]) 1338 1.3 christos { 1339 1.3 christos printf ("opcode %x: mem access operands already known ?\n", opcode); 1340 1.3 christos abort (); 1341 1.3 christos } 1342 1.1 christos 1343 1.1 christos side = func_unit_side == 2 ? 'b' : 'a'; 1344 1.1 christos snprintf (base, 4, "%c%u", side, mem_base_reg); 1345 1.1 christos 1346 1.8 christos offset_is_reg = (mem_mode & 4) != 0; 1347 1.1 christos if (offset_is_reg) 1348 1.1 christos { 1349 1.3 christos 1350 1.3 christos if (num_bits == 16 && header.rs && !(opc->flags & TIC6X_FLAG_INSN16_NORS)) 1351 1.3 christos { 1352 1.3 christos reg_base = 16; 1353 1.3 christos } 1354 1.3 christos snprintf (offset, 4, "%c%u", side, reg_base + mem_offset); 1355 1.1 christos if (opc->operand_info[op_num].form 1356 1.1 christos == tic6x_operand_mem_ndw) 1357 1.8 christos offset_scaled = mem_scaled != 0; 1358 1.1 christos else 1359 1.8 christos offset_scaled = true; 1360 1.1 christos } 1361 1.1 christos else 1362 1.1 christos { 1363 1.1 christos if (opc->operand_info[op_num].form 1364 1.1 christos == tic6x_operand_mem_ndw) 1365 1.1 christos { 1366 1.8 christos offset_scaled = mem_scaled != 0; 1367 1.1 christos snprintf (offset, 4, "%u", mem_offset); 1368 1.1 christos } 1369 1.1 christos else 1370 1.1 christos { 1371 1.8 christos offset_scaled = false; 1372 1.1 christos snprintf (offset, 4, "%u", 1373 1.1 christos (mem_offset 1374 1.1 christos * opc->operand_info[op_num].size)); 1375 1.1 christos } 1376 1.1 christos } 1377 1.1 christos 1378 1.1 christos if (offset_scaled) 1379 1.1 christos snprintf (offsetp, 6, "[%s]", offset); 1380 1.1 christos else 1381 1.1 christos snprintf (offsetp, 6, "(%s)", offset); 1382 1.1 christos 1383 1.8 christos operands_text[op_num] = true; 1384 1.1 christos switch (mem_mode & ~4u) 1385 1.1 christos { 1386 1.1 christos case 0: 1387 1.1 christos snprintf (operands[op_num], 24, "*-%s%s", base, offsetp); 1388 1.1 christos break; 1389 1.1 christos 1390 1.1 christos case 1: 1391 1.1 christos snprintf (operands[op_num], 24, "*+%s%s", base, offsetp); 1392 1.1 christos break; 1393 1.1 christos 1394 1.1 christos case 2: 1395 1.1 christos case 3: 1396 1.8 christos operands_ok = false; 1397 1.1 christos break; 1398 1.1 christos 1399 1.1 christos case 8: 1400 1.1 christos snprintf (operands[op_num], 24, "*--%s%s", base, 1401 1.1 christos offsetp); 1402 1.1 christos break; 1403 1.1 christos 1404 1.1 christos case 9: 1405 1.1 christos snprintf (operands[op_num], 24, "*++%s%s", base, 1406 1.1 christos offsetp); 1407 1.1 christos break; 1408 1.1 christos 1409 1.1 christos case 10: 1410 1.1 christos snprintf (operands[op_num], 24, "*%s--%s", base, 1411 1.1 christos offsetp); 1412 1.1 christos break; 1413 1.1 christos 1414 1.1 christos case 11: 1415 1.1 christos snprintf (operands[op_num], 24, "*%s++%s", base, 1416 1.1 christos offsetp); 1417 1.1 christos break; 1418 1.1 christos 1419 1.1 christos default: 1420 1.3 christos printf ("*** unknown mem_mode : %d \n", mem_mode); 1421 1.1 christos abort (); 1422 1.1 christos } 1423 1.1 christos } 1424 1.1 christos 1425 1.1 christos if (crlo_known && crhi_known) 1426 1.1 christos { 1427 1.1 christos tic6x_rw rw; 1428 1.1 christos tic6x_ctrl_id crid; 1429 1.1 christos 1430 1.1 christos if (operands_text[op_num] || operands_pcrel[op_num]) 1431 1.3 christos { 1432 1.3 christos printf ("*** abort crlo crli\n"); 1433 1.3 christos abort (); 1434 1.3 christos } 1435 1.1 christos 1436 1.1 christos rw = opc->operand_info[op_num].rw; 1437 1.1 christos if (rw != tic6x_rw_read 1438 1.1 christos && rw != tic6x_rw_write) 1439 1.3 christos { 1440 1.3 christos printf ("*** abort rw : %d\n", rw); 1441 1.3 christos abort (); 1442 1.3 christos } 1443 1.1 christos 1444 1.1 christos for (crid = 0; crid < tic6x_ctrl_max; crid++) 1445 1.1 christos { 1446 1.1 christos if (crlo == tic6x_ctrl_table[crid].crlo 1447 1.1 christos && (crhi & tic6x_ctrl_table[crid].crhi_mask) == 0 1448 1.1 christos && (rw == tic6x_rw_read 1449 1.1 christos ? (tic6x_ctrl_table[crid].rw == tic6x_rw_read 1450 1.1 christos || (tic6x_ctrl_table[crid].rw 1451 1.1 christos == tic6x_rw_read_write)) 1452 1.1 christos : (tic6x_ctrl_table[crid].rw == tic6x_rw_write 1453 1.1 christos || (tic6x_ctrl_table[crid].rw 1454 1.1 christos == tic6x_rw_read_write)))) 1455 1.1 christos break; 1456 1.1 christos } 1457 1.1 christos if (crid == tic6x_ctrl_max) 1458 1.1 christos { 1459 1.8 christos operands_text[op_num] = true; 1460 1.8 christos operands_ok = false; 1461 1.1 christos } 1462 1.1 christos else 1463 1.1 christos { 1464 1.8 christos operands_text[op_num] = true; 1465 1.1 christos snprintf (operands[op_num], 24, "%s", 1466 1.1 christos tic6x_ctrl_table[crid].name); 1467 1.1 christos } 1468 1.1 christos } 1469 1.1 christos 1470 1.1 christos if (operands_text[op_num] || operands_pcrel[op_num] 1471 1.1 christos || spmask_skip_operand) 1472 1.1 christos break; 1473 1.1 christos } 1474 1.3 christos /* end for fld_num */ 1475 1.3 christos 1476 1.1 christos if (spmask_skip_operand) 1477 1.1 christos { 1478 1.1 christos /* SPMASK operands are only valid as the single operand 1479 1.1 christos in the opcode table. */ 1480 1.1 christos if (num_operands != 1) 1481 1.3 christos { 1482 1.3 christos printf ("opcode: %x, num_operands != 1 : %d\n", opcode, num_operands); 1483 1.3 christos abort (); 1484 1.3 christos } 1485 1.1 christos num_operands = 0; 1486 1.1 christos break; 1487 1.1 christos } 1488 1.3 christos 1489 1.1 christos /* The operand must by now have been decoded. */ 1490 1.1 christos if (!operands_text[op_num] && !operands_pcrel[op_num]) 1491 1.3 christos { 1492 1.3 christos printf ("opcode: %x, operand #%d not decoded\n", opcode, op_num); 1493 1.3 christos abort (); 1494 1.3 christos } 1495 1.3 christos } 1496 1.3 christos /* end for op_num */ 1497 1.1 christos 1498 1.1 christos if (!operands_ok) 1499 1.1 christos continue; 1500 1.1 christos 1501 1.1 christos info->bytes_per_chunk = num_bits / 8; 1502 1.3 christos info->fprintf_func (info->stream, "%s", parallel); 1503 1.3 christos info->fprintf_func (info->stream, "%s%s%s", cond, opc->name, 1504 1.3 christos func_unit); 1505 1.1 christos for (op_num = 0; op_num < num_operands; op_num++) 1506 1.1 christos { 1507 1.1 christos info->fprintf_func (info->stream, "%c", (op_num == 0 ? ' ' : ',')); 1508 1.1 christos if (operands_pcrel[op_num]) 1509 1.1 christos info->print_address_func (operands_addresses[op_num], info); 1510 1.1 christos else 1511 1.1 christos info->fprintf_func (info->stream, "%s", operands[op_num]); 1512 1.1 christos } 1513 1.1 christos if (fetch_packet_header_based && header.prot) 1514 1.1 christos info->fprintf_func (info->stream, " || nop 5"); 1515 1.1 christos 1516 1.1 christos return num_bits / 8; 1517 1.1 christos } 1518 1.1 christos 1519 1.1 christos info->bytes_per_chunk = num_bits / 8; 1520 1.1 christos info->fprintf_func (info->stream, "<undefined instruction 0x%.*x>", 1521 1.1 christos (int) num_bits / 4, opcode); 1522 1.1 christos return num_bits / 8; 1523 1.1 christos } 1524