1 /* Disassemble V850 instructions. 2 Copyright (C) 1996-2024 Free Software Foundation, Inc. 3 4 This file is part of the GNU opcodes library. 5 6 This library is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3, or (at your option) 9 any later version. 10 11 It is distributed in the hope that it will be useful, but WITHOUT 12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 14 License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 19 MA 02110-1301, USA. */ 20 21 22 #include "sysdep.h" 23 #include <stdio.h> 24 #include <string.h> 25 #include "opcode/v850.h" 26 #include "disassemble.h" 27 #include "opintl.h" 28 #include "libiberty.h" 29 30 static const int v850_cacheop_codes[] = 31 { 32 0x00, 0x20, 0x40, 0x60, 0x61, 0x04, 0x06, 33 0x07, 0x24, 0x26, 0x27, 0x44, 0x64, 0x65, -1 34 }; 35 36 static const int v850_prefop_codes[] = 37 { 0x00, 0x04, -1}; 38 39 static void 40 print_value (int flags, 41 bfd_vma memaddr, 42 struct disassemble_info *info, 43 long value) 44 { 45 if (flags & V850_PCREL) 46 { 47 bfd_vma addr = value + memaddr; 48 49 if (flags & V850_INVERSE_PCREL) 50 addr = memaddr - value; 51 info->print_address_func (addr, info); 52 } 53 else if (flags & V850_OPERAND_DISP) 54 { 55 if (flags & V850_OPERAND_SIGNED) 56 { 57 info->fprintf_func (info->stream, "%ld", value); 58 } 59 else 60 { 61 info->fprintf_func (info->stream, "%lu", value); 62 } 63 } 64 else if ((flags & V850E_IMMEDIATE32) 65 || (flags & V850E_IMMEDIATE16HI)) 66 { 67 info->fprintf_func (info->stream, "0x%lx", value); 68 } 69 else 70 { 71 if (flags & V850_OPERAND_SIGNED) 72 { 73 info->fprintf_func (info->stream, "%ld", value); 74 } 75 else 76 { 77 info->fprintf_func (info->stream, "%lu", value); 78 } 79 } 80 } 81 82 static long 83 get_operand_value (const struct v850_operand *operand, 84 unsigned long insn, 85 int bytes_read, 86 bfd_vma memaddr, 87 struct disassemble_info * info, 88 bool noerror, 89 int *invalid) 90 { 91 unsigned long value; 92 bfd_byte buffer[4]; 93 94 if ((operand->flags & V850E_IMMEDIATE16) 95 || (operand->flags & V850E_IMMEDIATE16HI)) 96 { 97 int status = info->read_memory_func (memaddr + bytes_read, buffer, 2, info); 98 99 if (status == 0) 100 { 101 value = bfd_getl16 (buffer); 102 103 if (operand->flags & V850E_IMMEDIATE16HI) 104 value <<= 16; 105 else if (value & 0x8000) 106 value |= (-1UL << 16); 107 108 return value; 109 } 110 111 if (!noerror) 112 info->memory_error_func (status, memaddr + bytes_read, info); 113 114 return 0; 115 } 116 117 if (operand->flags & V850E_IMMEDIATE23) 118 { 119 int status = info->read_memory_func (memaddr + 2, buffer, 4, info); 120 121 if (status == 0) 122 { 123 value = bfd_getl32 (buffer); 124 125 value = (operand->extract) (value, invalid); 126 127 return value; 128 } 129 130 if (!noerror) 131 info->memory_error_func (status, memaddr + bytes_read, info); 132 133 return 0; 134 } 135 136 if (operand->flags & V850E_IMMEDIATE32) 137 { 138 int status = info->read_memory_func (memaddr + bytes_read, buffer, 4, info); 139 140 if (status == 0) 141 { 142 bytes_read += 4; 143 value = bfd_getl32 (buffer); 144 145 return value; 146 } 147 148 if (!noerror) 149 info->memory_error_func (status, memaddr + bytes_read, info); 150 151 return 0; 152 } 153 154 if (operand->extract) 155 value = (operand->extract) (insn, invalid); 156 else 157 { 158 if (operand->bits == -1) 159 value = (insn & operand->shift); 160 else 161 value = (insn >> operand->shift) & ((1ul << operand->bits) - 1); 162 163 if (operand->flags & V850_OPERAND_SIGNED) 164 { 165 unsigned long sign = 1ul << (operand->bits - 1); 166 value = (value ^ sign) - sign; 167 } 168 } 169 170 return value; 171 } 172 173 static const char * 174 get_v850_sreg_name (unsigned int reg) 175 { 176 static const char *const v850_sreg_names[] = 177 { 178 "eipc/vip/mpm", "eipsw/mpc", "fepc/tid", "fepsw/ppa", "ecr/vmecr", "psw/vmtid", 179 "sr6/fpsr/vmadr/dcc", "sr7/fpepc/dc0", 180 "sr8/fpst/vpecr/dcv1", "sr9/fpcc/vptid", "sr10/fpcfg/vpadr/spal", "sr11/spau", 181 "sr12/vdecr/ipa0l", "eiic/vdtid/ipa0u", "feic/ipa1l", "dbic/ipa1u", 182 "ctpc/ipa2l", "ctpsw/ipa2u", "dbpc/ipa3l", "dbpsw/ipa3u", "ctbp/dpa0l", 183 "dir/dpa0u", "bpc/dpa0u", "asid/dpa1l", 184 "bpav/dpa1u", "bpam/dpa2l", "bpdv/dpa2u", "bpdm/dpa3l", "eiwr/dpa3u", 185 "fewr", "dbwr", "bsel" 186 }; 187 188 if (reg < ARRAY_SIZE (v850_sreg_names)) 189 return v850_sreg_names[reg]; 190 return _("<invalid s-reg number>"); 191 } 192 193 static const char * 194 get_v850_reg_name (unsigned int reg) 195 { 196 static const char *const v850_reg_names[] = 197 { 198 "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7", 199 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 200 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", 201 "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp" 202 }; 203 204 if (reg < ARRAY_SIZE (v850_reg_names)) 205 return v850_reg_names[reg]; 206 return _("<invalid reg number>"); 207 } 208 209 static const char * 210 get_v850_vreg_name (unsigned int reg) 211 { 212 static const char *const v850_vreg_names[] = 213 { 214 "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7", "vr8", "vr9", 215 "vr10", "vr11", "vr12", "vr13", "vr14", "vr15", "vr16", "vr17", "vr18", 216 "vr19", "vr20", "vr21", "vr22", "vr23", "vr24", "vr25", "vr26", "vr27", 217 "vr28", "vr29", "vr30", "vr31" 218 }; 219 220 if (reg < ARRAY_SIZE (v850_vreg_names)) 221 return v850_vreg_names[reg]; 222 return _("<invalid v-reg number>"); 223 } 224 225 static const char * 226 get_v850_cc_name (unsigned int reg) 227 { 228 static const char *const v850_cc_names[] = 229 { 230 "v", "c/l", "z", "nh", "s/n", "t", "lt", "le", 231 "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt" 232 }; 233 234 if (reg < ARRAY_SIZE (v850_cc_names)) 235 return v850_cc_names[reg]; 236 return _("<invalid CC-reg number>"); 237 } 238 239 static const char * 240 get_v850_float_cc_name (unsigned int reg) 241 { 242 static const char *const v850_float_cc_names[] = 243 { 244 "f/t", "un/or", "eq/neq", "ueq/ogl", "olt/uge", "ult/oge", "ole/ugt", "ule/ogt", 245 "sf/st", "ngle/gle", "seq/sne", "ngl/gl", "lt/nlt", "nge/ge", "le/nle", "ngt/gt" 246 }; 247 248 if (reg < ARRAY_SIZE (v850_float_cc_names)) 249 return v850_float_cc_names[reg]; 250 return _("<invalid float-CC-reg number>"); 251 } 252 253 static const char * 254 get_v850_cacheop_name (unsigned int reg) 255 { 256 static const char *const v850_cacheop_names[] = 257 { 258 "chbii", "cibii", "cfali", "cisti", "cildi", "chbid", "chbiwbd", 259 "chbwbd", "cibid", "cibiwbd", "cibwbd", "cfald", "cistd", "cildd" 260 }; 261 262 if (reg < ARRAY_SIZE (v850_cacheop_names)) 263 return v850_cacheop_names[reg]; 264 return _("<invalid cacheop number>"); 265 } 266 267 static const char * 268 get_v850_prefop_name (unsigned int reg) 269 { 270 static const char *const v850_prefop_names[] = 271 { "prefi", "prefd" }; 272 273 if (reg < ARRAY_SIZE (v850_prefop_names)) 274 return v850_prefop_names[reg]; 275 return _("<invalid prefop number>"); 276 } 277 278 static int 279 disassemble (bfd_vma memaddr, 280 struct disassemble_info *info, 281 int bytes_read, 282 unsigned long insn) 283 { 284 struct v850_opcode *op = (struct v850_opcode *) v850_opcodes; 285 const struct v850_operand *operand; 286 int match = 0; 287 int target_processor; 288 289 switch (info->mach) 290 { 291 case 0: 292 default: 293 target_processor = PROCESSOR_V850; 294 break; 295 296 case bfd_mach_v850e: 297 target_processor = PROCESSOR_V850E; 298 break; 299 300 case bfd_mach_v850e1: 301 target_processor = PROCESSOR_V850E; 302 break; 303 304 case bfd_mach_v850e2: 305 target_processor = PROCESSOR_V850E2; 306 break; 307 308 case bfd_mach_v850e2v3: 309 target_processor = PROCESSOR_V850E2V3; 310 break; 311 312 case bfd_mach_v850e3v5: 313 target_processor = PROCESSOR_V850E3V5; 314 break; 315 } 316 317 /* If this is a two byte insn, then mask off the high bits. */ 318 if (bytes_read == 2) 319 insn &= 0xffff; 320 321 /* Find the opcode. */ 322 while (op->name) 323 { 324 if ((op->mask & insn) == op->opcode 325 && (op->processors & target_processor) 326 && !(op->processors & PROCESSOR_OPTION_ALIAS)) 327 { 328 /* Code check start. */ 329 const unsigned char *opindex_ptr; 330 unsigned int opnum; 331 unsigned int memop; 332 333 for (opindex_ptr = op->operands, opnum = 1; 334 *opindex_ptr != 0; 335 opindex_ptr++, opnum++) 336 { 337 int invalid = 0; 338 long value; 339 340 operand = &v850_operands[*opindex_ptr]; 341 342 value = get_operand_value (operand, insn, bytes_read, memaddr, 343 info, 1, &invalid); 344 345 if (invalid) 346 goto next_opcode; 347 348 if ((operand->flags & V850_NOT_R0) && value == 0 && (op->memop) <=2) 349 goto next_opcode; 350 351 if ((operand->flags & V850_NOT_SA) && value == 0xd) 352 goto next_opcode; 353 354 if ((operand->flags & V850_NOT_IMM0) && value == 0) 355 goto next_opcode; 356 } 357 358 /* Code check end. */ 359 360 match = 1; 361 (*info->fprintf_func) (info->stream, "%s\t", op->name); 362 #if 0 363 fprintf (stderr, "match: insn: %lx, mask: %lx, opcode: %lx, name: %s\n", 364 insn, op->mask, op->opcode, op->name ); 365 #endif 366 367 memop = op->memop; 368 /* Now print the operands. 369 370 MEMOP is the operand number at which a memory 371 address specification starts, or zero if this 372 instruction has no memory addresses. 373 374 A memory address is always two arguments. 375 376 This information allows us to determine when to 377 insert commas into the output stream as well as 378 when to insert disp[reg] expressions onto the 379 output stream. */ 380 381 for (opindex_ptr = op->operands, opnum = 1; 382 *opindex_ptr != 0; 383 opindex_ptr++, opnum++) 384 { 385 bool square = false; 386 long value; 387 int flag; 388 char *prefix; 389 390 operand = &v850_operands[*opindex_ptr]; 391 392 value = get_operand_value (operand, insn, bytes_read, memaddr, 393 info, 0, 0); 394 395 /* The first operand is always output without any 396 special handling. 397 398 For the following arguments: 399 400 If memop && opnum == memop + 1, then we need '[' since 401 we're about to output the register used in a memory 402 reference. 403 404 If memop && opnum == memop + 2, then we need ']' since 405 we just finished the register in a memory reference. We 406 also need a ',' before this operand. 407 408 Else we just need a comma. 409 410 We may need to output a trailing ']' if the last operand 411 in an instruction is the register for a memory address. 412 413 The exception (and there's always an exception) are the 414 "jmp" insn which needs square brackets around it's only 415 register argument, and the clr1/not1/set1/tst1 insns 416 which [...] around their second register argument. */ 417 418 prefix = ""; 419 if (operand->flags & V850_OPERAND_BANG) 420 { 421 prefix = "!"; 422 } 423 else if (operand->flags & V850_OPERAND_PERCENT) 424 { 425 prefix = "%"; 426 } 427 428 if (opnum == 1 && opnum == memop) 429 { 430 info->fprintf_func (info->stream, "%s[", prefix); 431 square = true; 432 } 433 else if ( (strcmp ("stc.w", op->name) == 0 434 || strcmp ("cache", op->name) == 0 435 || strcmp ("pref", op->name) == 0) 436 && opnum == 2 && opnum == memop) 437 { 438 info->fprintf_func (info->stream, ", ["); 439 square = true; 440 } 441 else if ( (strcmp (op->name, "pushsp") == 0 442 || strcmp (op->name, "popsp") == 0 443 || strcmp (op->name, "dbpush" ) == 0) 444 && opnum == 2) 445 { 446 info->fprintf_func (info->stream, "-"); 447 } 448 else if (opnum > 1 449 && (v850_operands[*(opindex_ptr - 1)].flags 450 & V850_OPERAND_DISP) != 0 451 && opnum == memop) 452 { 453 info->fprintf_func (info->stream, "%s[", prefix); 454 square = true; 455 } 456 else if (opnum == 2 457 && ( op->opcode == 0x00e407e0 /* clr1 */ 458 || op->opcode == 0x00e207e0 /* not1 */ 459 || op->opcode == 0x00e007e0 /* set1 */ 460 || op->opcode == 0x00e607e0 /* tst1 */ 461 )) 462 { 463 info->fprintf_func (info->stream, ", %s[", prefix); 464 square = true; 465 } 466 else if (opnum > 1) 467 info->fprintf_func (info->stream, ", %s", prefix); 468 469 /* Extract the flags, ignoring ones which do not 470 effect disassembly output. */ 471 flag = operand->flags & (V850_OPERAND_REG 472 | V850_REG_EVEN 473 | V850_OPERAND_EP 474 | V850_OPERAND_SRG 475 | V850E_OPERAND_REG_LIST 476 | V850_OPERAND_CC 477 | V850_OPERAND_VREG 478 | V850_OPERAND_CACHEOP 479 | V850_OPERAND_PREFOP 480 | V850_OPERAND_FLOAT_CC); 481 482 switch (flag) 483 { 484 case V850_OPERAND_REG: 485 info->fprintf_func (info->stream, "%s", get_v850_reg_name (value)); 486 break; 487 case (V850_OPERAND_REG|V850_REG_EVEN): 488 info->fprintf_func (info->stream, "%s", get_v850_reg_name (value * 2)); 489 break; 490 case V850_OPERAND_EP: 491 info->fprintf_func (info->stream, "ep"); 492 break; 493 case V850_OPERAND_SRG: 494 info->fprintf_func (info->stream, "%s", get_v850_sreg_name (value)); 495 break; 496 case V850E_OPERAND_REG_LIST: 497 { 498 static int list12_regs[32] = { 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 499 0, 0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 }; 500 int *regs; 501 int i; 502 unsigned int mask = 0; 503 int pc = 0; 504 505 switch (operand->shift) 506 { 507 case 0xffe00001: regs = list12_regs; break; 508 default: 509 /* xgettext:c-format */ 510 opcodes_error_handler (_("unknown operand shift: %x"), 511 operand->shift); 512 abort (); 513 } 514 515 for (i = 0; i < 32; i++) 516 { 517 if (value & (1u << i)) 518 { 519 switch (regs[ i ]) 520 { 521 default: 522 mask |= (1u << regs[ i ]); 523 break; 524 case 0: 525 /* xgettext:c-format */ 526 opcodes_error_handler (_("unknown reg: %d"), i); 527 abort (); 528 break; 529 case -1: 530 pc = 1; 531 break; 532 } 533 } 534 } 535 536 info->fprintf_func (info->stream, "{"); 537 538 if (mask || pc) 539 { 540 if (mask) 541 { 542 unsigned int bit; 543 int shown_one = 0; 544 545 for (bit = 0; bit < 32; bit++) 546 if (mask & (1u << bit)) 547 { 548 unsigned int first = bit; 549 unsigned int last; 550 551 if (shown_one) 552 info->fprintf_func (info->stream, ", "); 553 else 554 shown_one = 1; 555 556 info->fprintf_func (info->stream, "%s", get_v850_reg_name (first)); 557 558 for (bit++; bit < 32; bit++) 559 if ((mask & (1u << bit)) == 0) 560 break; 561 562 last = bit; 563 564 if (last > first + 1) 565 { 566 info->fprintf_func (info->stream, " - %s", get_v850_reg_name (last - 1)); 567 } 568 } 569 } 570 571 if (pc) 572 info->fprintf_func (info->stream, "%sPC", mask ? ", " : ""); 573 } 574 575 info->fprintf_func (info->stream, "}"); 576 } 577 break; 578 579 case V850_OPERAND_CC: 580 info->fprintf_func (info->stream, "%s", get_v850_cc_name (value)); 581 break; 582 583 case V850_OPERAND_FLOAT_CC: 584 info->fprintf_func (info->stream, "%s", get_v850_float_cc_name (value)); 585 break; 586 587 case V850_OPERAND_CACHEOP: 588 { 589 int idx; 590 591 for (idx = 0; v850_cacheop_codes[idx] != -1; idx++) 592 { 593 if (value == v850_cacheop_codes[idx]) 594 { 595 info->fprintf_func (info->stream, "%s", 596 get_v850_cacheop_name (idx)); 597 goto MATCH_CACHEOP_CODE; 598 } 599 } 600 info->fprintf_func (info->stream, "%d", (int) value); 601 } 602 MATCH_CACHEOP_CODE: 603 break; 604 605 case V850_OPERAND_PREFOP: 606 { 607 int idx; 608 609 for (idx = 0; v850_prefop_codes[idx] != -1; idx++) 610 { 611 if (value == v850_prefop_codes[idx]) 612 { 613 info->fprintf_func (info->stream, "%s", 614 get_v850_prefop_name (idx)); 615 goto MATCH_PREFOP_CODE; 616 } 617 } 618 info->fprintf_func (info->stream, "%d", (int) value); 619 } 620 MATCH_PREFOP_CODE: 621 break; 622 623 case V850_OPERAND_VREG: 624 info->fprintf_func (info->stream, "%s", get_v850_vreg_name (value)); 625 break; 626 627 default: 628 print_value (operand->flags, memaddr, info, value); 629 break; 630 } 631 632 if (square) 633 (*info->fprintf_func) (info->stream, "]"); 634 } 635 636 /* All done. */ 637 break; 638 } 639 next_opcode: 640 op++; 641 } 642 643 return match; 644 } 645 646 int 647 print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info) 648 { 649 int status, status2, match; 650 bfd_byte buffer[8]; 651 int length = 0, code_length = 0; 652 unsigned long insn = 0, insn2 = 0; 653 int target_processor; 654 655 switch (info->mach) 656 { 657 case 0: 658 default: 659 target_processor = PROCESSOR_V850; 660 break; 661 662 case bfd_mach_v850e: 663 target_processor = PROCESSOR_V850E; 664 break; 665 666 case bfd_mach_v850e1: 667 target_processor = PROCESSOR_V850E; 668 break; 669 670 case bfd_mach_v850e2: 671 target_processor = PROCESSOR_V850E2; 672 break; 673 674 case bfd_mach_v850e2v3: 675 target_processor = PROCESSOR_V850E2V3; 676 break; 677 678 case bfd_mach_v850e3v5: 679 target_processor = PROCESSOR_V850E3V5; 680 break; 681 } 682 683 status = info->read_memory_func (memaddr, buffer, 2, info); 684 685 if (status) 686 { 687 info->memory_error_func (status, memaddr, info); 688 return -1; 689 } 690 691 insn = bfd_getl16 (buffer); 692 693 status2 = info->read_memory_func (memaddr+2, buffer, 2 , info); 694 695 if (!status2) 696 { 697 insn2 = bfd_getl16 (buffer); 698 /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */ 699 } 700 701 /* Special case. */ 702 if (length == 0 703 && ((target_processor & PROCESSOR_V850E2_UP) != 0)) 704 { 705 if ((insn & 0xffff) == 0x02e0 /* jr 32bit */ 706 && !status2 && (insn2 & 0x1) == 0) 707 { 708 length = 2; 709 code_length = 6; 710 } 711 else if ((insn & 0xffe0) == 0x02e0 /* jarl 32bit */ 712 && !status2 && (insn2 & 0x1) == 0) 713 { 714 length = 2; 715 code_length = 6; 716 } 717 else if ((insn & 0xffe0) == 0x06e0 /* jmp 32bit */ 718 && !status2 && (insn2 & 0x1) == 0) 719 { 720 length = 2; 721 code_length = 6; 722 } 723 } 724 725 if (length == 0 726 && ((target_processor & PROCESSOR_V850E3V5_UP) != 0)) 727 { 728 if ( ((insn & 0xffe0) == 0x07a0 /* ld.dw 23bit (v850e3v5) */ 729 && !status2 && (insn2 & 0x000f) == 0x0009) 730 || ((insn & 0xffe0) == 0x07a0 /* st.dw 23bit (v850e3v5) */ 731 && !status2 && (insn2 & 0x000f) == 0x000f)) 732 { 733 length = 4; 734 code_length = 6; 735 } 736 } 737 738 if (length == 0 739 && ((target_processor & PROCESSOR_V850E2V3_UP) != 0)) 740 { 741 if (((insn & 0xffe0) == 0x0780 /* ld.b 23bit */ 742 && !status2 && (insn2 & 0x000f) == 0x0005) 743 || ((insn & 0xffe0) == 0x07a0 /* ld.bu 23bit */ 744 && !status2 && (insn2 & 0x000f) == 0x0005) 745 || ((insn & 0xffe0) == 0x0780 /* ld.h 23bit */ 746 && !status2 && (insn2 & 0x000f) == 0x0007) 747 || ((insn & 0xffe0) == 0x07a0 /* ld.hu 23bit */ 748 && !status2 && (insn2 & 0x000f) == 0x0007) 749 || ((insn & 0xffe0) == 0x0780 /* ld.w 23bit */ 750 && !status2 && (insn2 & 0x000f) == 0x0009)) 751 { 752 length = 4; 753 code_length = 6; 754 } 755 else if (((insn & 0xffe0) == 0x0780 /* st.b 23bit */ 756 && !status2 && (insn2 & 0x000f) == 0x000d) 757 || ((insn & 0xffe0) == 0x07a0 /* st.h 23bit */ 758 && !status2 && (insn2 & 0x000f) == 0x000d) 759 || ((insn & 0xffe0) == 0x0780 /* st.w 23bit */ 760 && !status2 && (insn2 & 0x000f) == 0x000f)) 761 { 762 length = 4; 763 code_length = 6; 764 } 765 } 766 767 if (length == 0 768 && target_processor != PROCESSOR_V850) 769 { 770 if ((insn & 0xffe0) == 0x0620) /* 32 bit MOV */ 771 { 772 length = 2; 773 code_length = 6; 774 } 775 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16<<16 */ 776 && !status2 && (insn2 & 0x001f) == 0x0013) 777 { 778 length = 4; 779 code_length = 6; 780 } 781 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16 */ 782 && !status2 && (insn2 & 0x001f) == 0x000b) 783 { 784 length = 4; 785 code_length = 6; 786 } 787 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm32 */ 788 && !status2 && (insn2 & 0x001f) == 0x001b) 789 { 790 length = 4; 791 code_length = 8; 792 } 793 } 794 795 if (length == 4 796 || (length == 0 797 && (insn & 0x0600) == 0x0600)) 798 { 799 /* This is a 4 byte insn. */ 800 status = info->read_memory_func (memaddr, buffer, 4, info); 801 if (!status) 802 { 803 insn = bfd_getl32 (buffer); 804 805 if (!length) 806 length = code_length = 4; 807 } 808 } 809 810 if (code_length > length) 811 { 812 status = info->read_memory_func (memaddr + length, buffer, code_length - length, info); 813 if (status) 814 length = 0; 815 } 816 817 if (length == 0 && !status) 818 length = code_length = 2; 819 820 if (length == 2) 821 insn &= 0xffff; 822 823 /* when the last 2 bytes of section is 0xffff, length will be 0 and cause infinitive loop */ 824 if (length == 0) 825 return -1; 826 827 match = disassemble (memaddr, info, length, insn); 828 829 if (!match) 830 { 831 int l = 0; 832 833 status = info->read_memory_func (memaddr, buffer, code_length, info); 834 835 while (l < code_length) 836 { 837 if (code_length - l == 2) 838 { 839 insn = bfd_getl16 (buffer + l) & 0xffff; 840 info->fprintf_func (info->stream, ".short\t0x%04lx", insn); 841 l += 2; 842 } 843 else 844 { 845 insn = bfd_getl32 (buffer + l); 846 info->fprintf_func (info->stream, ".long\t0x%08lx", insn); 847 l += 4; 848 } 849 } 850 } 851 852 return code_length; 853 } 854