1 /* C-SKY disassembler. 2 Copyright (C) 1988-2024 Free Software Foundation, Inc. 3 Contributed by C-SKY Microsystems and Mentor Graphics. 4 5 This file is part of the GNU opcodes library. 6 7 This library is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3, or (at your option) 10 any later version. 11 12 It is distributed in the hope that it will be useful, but WITHOUT 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 15 License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 20 MA 02110-1301, USA. */ 21 22 #include "sysdep.h" 23 #include "config.h" 24 #include <stdio.h> 25 #include <stdint.h> 26 #include <elf/csky.h> 27 #include "disassemble.h" 28 #include "elf-bfd.h" 29 #include "opcode/csky.h" 30 #include "libiberty.h" 31 #include "csky-opc.h" 32 #include "floatformat.h" 33 34 #define CSKY_INST_TYPE unsigned long 35 #define HAS_SUB_OPERAND (unsigned int)0xffffffff 36 #define CSKY_DEFAULT_ISA 0xffffffff 37 38 enum sym_type 39 { 40 CUR_TEXT, 41 CUR_DATA 42 }; 43 44 struct csky_dis_info 45 { 46 /* Mem to disassemble. */ 47 bfd_vma mem; 48 /* Disassemble info. */ 49 disassemble_info *info; 50 /* Opcode information. */ 51 struct csky_opcode_info const *opinfo; 52 uint64_t isa; 53 /* The value of operand to show. */ 54 int value; 55 /* Whether to look up/print a symbol name. */ 56 int need_output_symbol; 57 } dis_info; 58 59 60 enum sym_type last_type; 61 int last_map_sym = 1; 62 bfd_vma last_map_addr = 0; 63 int using_abi = 0; 64 65 /* Only for objdump tool. */ 66 #define INIT_MACH_FLAG 0xffffffff 67 #define BINARY_MACH_FLAG 0x0 68 69 static unsigned int mach_flag = INIT_MACH_FLAG; 70 71 static void 72 print_insn_data (bfd_vma pc ATTRIBUTE_UNUSED, 73 struct disassemble_info *info, 74 long given) 75 { 76 switch (info->bytes_per_chunk) 77 { 78 case 1: 79 info->fprintf_func (info->stream, ".byte\t0x%02lx", given); 80 break; 81 case 2: 82 info->fprintf_func (info->stream, ".short\t0x%04lx", given); 83 break; 84 case 4: 85 info->fprintf_func (info->stream, ".long\t0x%08lx", given); 86 break; 87 default: 88 abort (); 89 } 90 } 91 92 static int 93 get_sym_code_type (struct disassemble_info *info, 94 int n, 95 enum sym_type *sym_type) 96 { 97 const char *name; 98 name = bfd_asymbol_name (info->symtab[n]); 99 if (name[0] == '$' && (name[1] == 't' || name[1] == 'd') 100 && (name[2] == 0 || name[2] == '.')) 101 { 102 *sym_type = ((name[1] == 't') ? CUR_TEXT : CUR_DATA); 103 return true; 104 } 105 return false; 106 } 107 108 static int 109 csky_get_operand_mask (struct operand const *oprnd) 110 { 111 int mask = 0; 112 if (oprnd->mask == HAS_SUB_OPERAND) 113 { 114 struct soperand *sop = (struct soperand *)oprnd; 115 mask |= csky_get_operand_mask (&sop->subs[0]); 116 mask |= csky_get_operand_mask (&sop->subs[1]); 117 return mask; 118 } 119 return oprnd->mask; 120 } 121 122 static int 123 csky_get_mask (struct csky_opcode_info const *pinfo) 124 { 125 int i = 0; 126 int mask = 0; 127 /* List type. */ 128 if (pinfo->operand_num == -1) 129 mask |= csky_get_operand_mask (&pinfo->oprnd.oprnds[i]); 130 else 131 for (; i < pinfo->operand_num; i++) 132 mask |= csky_get_operand_mask (&pinfo->oprnd.oprnds[i]); 133 134 mask = ~mask; 135 return mask; 136 } 137 138 static unsigned int 139 csky_chars_to_number (unsigned char * buf, int n) 140 { 141 int i; 142 unsigned int val = 0; 143 144 if (dis_info.info->endian == BFD_ENDIAN_BIG) 145 for (i = 0; i < n; i++) 146 val = val << 8 | buf[i]; 147 else 148 for (i = n - 1; i >= 0; i--) 149 val = val << 8 | buf[i]; 150 return val; 151 } 152 153 static struct csky_opcode const *g_opcodeP; 154 155 static struct csky_opcode const * 156 csky_find_inst_info (struct csky_opcode_info const **pinfo, 157 CSKY_INST_TYPE inst, int length) 158 { 159 int i; 160 unsigned int mask; 161 struct csky_opcode const *p; 162 163 p = g_opcodeP; 164 while (p->mnemonic) 165 { 166 if (!(p->isa_flag16 & dis_info.isa) 167 && !(p->isa_flag32 & dis_info.isa)) 168 { 169 p++; 170 continue; 171 } 172 173 /* Get the opcode mask. */ 174 for (i = 0; i < OP_TABLE_NUM; i++) 175 if (length == 2) 176 { 177 mask = csky_get_mask (&p->op16[i]); 178 if (mask != 0 && (inst & mask) == p->op16[i].opcode) 179 { 180 *pinfo = &p->op16[i]; 181 g_opcodeP = p; 182 return p; 183 } 184 } 185 else if (length == 4) 186 { 187 mask = csky_get_mask (&p->op32[i]); 188 if (mask != 0 189 && ((unsigned long)(inst & mask) 190 == (unsigned long)p->op32[i].opcode)) 191 { 192 *pinfo = &p->op32[i]; 193 g_opcodeP = p; 194 return p; 195 } 196 } 197 p++; 198 } 199 200 return NULL; 201 } 202 203 static bool 204 is_extern_symbol (struct disassemble_info *info, int addr) 205 { 206 unsigned int rel_count = 0; 207 208 if (info->section == NULL) 209 return 0; 210 if ((info->section->flags & SEC_RELOC) != 0) /* Fit .o file. */ 211 { 212 struct reloc_cache_entry *pt = info->section->relocation; 213 for (; rel_count < info->section->reloc_count; rel_count++, pt++) 214 if ((long unsigned int)addr == pt->address) 215 return true; 216 return false; 217 } 218 return false; 219 } 220 221 222 /* Suppress printing of mapping symbols emitted by the assembler to mark 223 the beginning of code and data sequences. */ 224 225 bool 226 csky_symbol_is_valid (asymbol *sym, 227 struct disassemble_info *info ATTRIBUTE_UNUSED) 228 { 229 const char *name; 230 231 if (sym == NULL) 232 return false; 233 name = bfd_asymbol_name (sym); 234 return name && *name != '$'; 235 } 236 237 disassembler_ftype 238 csky_get_disassembler (bfd *abfd) 239 { 240 obj_attribute *attr; 241 const char *sec_name = NULL; 242 if (!abfd || bfd_get_flavour (abfd) != bfd_target_elf_flavour) 243 dis_info.isa = CSKY_DEFAULT_ISA; 244 else 245 { 246 mach_flag = elf_elfheader (abfd)->e_flags; 247 248 sec_name = get_elf_backend_data (abfd)->obj_attrs_section; 249 /* Skip any input that hasn't attribute section. 250 This enables to link object files without attribute section with 251 any others. */ 252 if (bfd_get_section_by_name (abfd, sec_name) != NULL) 253 { 254 attr = elf_known_obj_attributes_proc (abfd); 255 dis_info.isa = attr[Tag_CSKY_ISA_EXT_FLAGS].i; 256 dis_info.isa <<= 32; 257 dis_info.isa |= attr[Tag_CSKY_ISA_FLAGS].i; 258 } 259 else 260 dis_info.isa = CSKY_DEFAULT_ISA; 261 } 262 263 return print_insn_csky; 264 } 265 266 /* Parse the string of disassembler options. */ 267 static void 268 parse_csky_dis_options (const char *opts_in) 269 { 270 char *opts = xstrdup (opts_in); 271 char *opt = opts; 272 char *opt_end = opts; 273 274 for (; opt_end != NULL; opt = opt_end + 1) 275 { 276 if ((opt_end = strchr (opt, ',')) != NULL) 277 *opt_end = 0; 278 if (strcmp (opt, "abi-names") == 0) 279 using_abi = 1; 280 else 281 fprintf (stderr, 282 "unrecognized disassembler option: %s", opt); 283 } 284 } 285 286 /* Get general register name. */ 287 static const char * 288 get_gr_name (int regno) 289 { 290 return csky_get_general_reg_name (mach_flag, regno, using_abi); 291 } 292 293 /* Get control register name. */ 294 static const char * 295 get_cr_name (unsigned int regno, int bank) 296 { 297 return csky_get_control_reg_name (mach_flag, bank, regno, using_abi); 298 } 299 300 static int 301 csky_output_operand (char *str, struct operand const *oprnd, 302 CSKY_INST_TYPE inst, int reloc ATTRIBUTE_UNUSED) 303 { 304 int ret = 0;; 305 int bit = 0; 306 int result = 0; 307 bfd_vma value; 308 int mask = oprnd->mask; 309 int max = 0; 310 char buf[128]; 311 312 /* Get operand value with mask. */ 313 value = inst & mask; 314 for (; mask; mask >>= 1, value >>=1) 315 if (mask & 0x1) 316 { 317 result |= ((value & 0x1) << bit); 318 max |= (1 << bit); 319 bit++; 320 } 321 value = result; 322 323 /* Here is general instructions that have no reloc. */ 324 switch (oprnd->type) 325 { 326 case OPRND_TYPE_CTRLREG: 327 if (IS_CSKY_V1(mach_flag) && ((value & 0x1f) == 0x1f)) 328 return -1; 329 strcat (str, get_cr_name((value & 0x1f), (value >> 5))); 330 break; 331 case OPRND_TYPE_DUMMY_REG: 332 mask = dis_info.opinfo->oprnd.oprnds[0].mask; 333 value = inst & mask; 334 for (; mask; mask >>= 1, value >>=1) 335 if (mask & 0x1) 336 { 337 result |= ((value & 0x1) << bit); 338 bit++; 339 } 340 value = result; 341 strcat (str, get_gr_name (value)); 342 break; 343 case OPRND_TYPE_GREG0_7: 344 case OPRND_TYPE_GREG0_15: 345 case OPRND_TYPE_GREG16_31: 346 case OPRND_TYPE_REGnsplr: 347 case OPRND_TYPE_AREG: 348 strcat (str, get_gr_name (value)); 349 break; 350 case OPRND_TYPE_CPREG: 351 sprintf (buf, "cpr%d", (int)value); 352 strcat (str, buf); 353 break; 354 case OPRND_TYPE_FREG: 355 sprintf (buf, "fr%d", (int)value); 356 strcat (str, buf); 357 break; 358 case OPRND_TYPE_VREG: 359 dis_info.value = value; 360 sprintf (buf, "vr%d", (int)value); 361 strcat (str, buf); 362 break; 363 case OPRND_TYPE_CPCREG: 364 sprintf (buf, "cpcr%d", (int)value); 365 strcat (str, buf); 366 break; 367 case OPRND_TYPE_CPIDX: 368 sprintf (buf, "cp%d", (int)value); 369 strcat (str, buf); 370 break; 371 case OPRND_TYPE_IMM2b_JMPIX: 372 value = (value + 2) << 3; 373 sprintf (buf, "%d", (int)value); 374 strcat (str, buf); 375 break; 376 case OPRND_TYPE_IMM_LDST: 377 case OPRND_TYPE_IMM_FLDST: 378 value <<= oprnd->shift; 379 sprintf (buf, "0x%x", (unsigned int)value); 380 strcat (str, buf); 381 break; 382 case OPRND_TYPE_IMM7b_LS2: 383 case OPRND_TYPE_IMM8b_LS2: 384 sprintf (buf, "%d", (int)(value << 2)); 385 strcat (str, buf); 386 ret = 0; 387 break; 388 case OPRND_TYPE_IMM5b_BMASKI: 389 if ((value != 0) && (value > 31 || value < 8)) 390 { 391 ret = -1; 392 break; 393 } 394 sprintf (buf, "%d", (int)value); 395 strcat (str, buf); 396 ret = 0; 397 break; 398 case OPRND_TYPE_IMM5b_1_31: 399 if (value > 31 || value < 1) 400 { 401 ret = -1; 402 break; 403 } 404 sprintf (buf, "%d", (int)value); 405 strcat (str, buf); 406 ret = 0; 407 break; 408 case OPRND_TYPE_IMM5b_7_31: 409 if (value > 31 || value < 7) 410 { 411 ret = -1; 412 break; 413 } 414 sprintf (buf, "%d", (int)value); 415 strcat (str, buf); 416 ret = 0; 417 break; 418 case OPRND_TYPE_IMM5b_VSH: 419 { 420 char num[128]; 421 value = ((value & 0x1) << 4) | (value >> 1); 422 sprintf (num, "%d", (int)value); 423 strcat (str, num); 424 ret = 0; 425 break; 426 } 427 case OPRND_TYPE_MSB2SIZE: 428 case OPRND_TYPE_LSB2SIZE: 429 { 430 static int size; 431 if (oprnd->type == OPRND_TYPE_MSB2SIZE) 432 size = value; 433 else 434 { 435 str[strlen (str) - 2] = '\0'; 436 sprintf (buf, "%d, %d", (int)(size + value), (int)value); 437 strcat (str, buf); 438 } 439 break; 440 } 441 case OPRND_TYPE_IMM1b: 442 case OPRND_TYPE_IMM2b: 443 case OPRND_TYPE_IMM4b: 444 case OPRND_TYPE_IMM5b: 445 case OPRND_TYPE_IMM5b_LS: 446 case OPRND_TYPE_IMM7b: 447 case OPRND_TYPE_IMM8b: 448 case OPRND_TYPE_IMM12b: 449 case OPRND_TYPE_IMM15b: 450 case OPRND_TYPE_IMM16b: 451 case OPRND_TYPE_IMM16b_MOVIH: 452 case OPRND_TYPE_IMM16b_ORI: 453 sprintf (buf, "%d", (int)value); 454 strcat (str, buf); 455 ret = 0; 456 break; 457 case OPRND_TYPE_OFF8b: 458 case OPRND_TYPE_OFF16b: 459 { 460 unsigned char ibytes[4]; 461 int shift = oprnd->shift; 462 int status; 463 unsigned int mem_val; 464 465 dis_info.info->stop_vma = 0; 466 467 value = ((dis_info.mem + (value << shift) 468 + ((IS_CSKY_V1 (mach_flag)) ? 2 : 0)) 469 & 0xfffffffc); 470 status = dis_info.info->read_memory_func (value, ibytes, 4, 471 dis_info.info); 472 if (status != 0) 473 { 474 dis_info.info->memory_error_func (status, dis_info.mem, 475 dis_info.info); 476 return -1; 477 } 478 mem_val = csky_chars_to_number (ibytes, 4); 479 /* Remove [] around literal value to match ABI syntax. */ 480 sprintf (buf, "0x%X", mem_val); 481 strcat (str, buf); 482 /* For jmpi/jsri, we'll try to get a symbol for the target. */ 483 if (dis_info.info->print_address_func && mem_val != 0) 484 { 485 dis_info.value = mem_val; 486 dis_info.need_output_symbol = 1; 487 } 488 else 489 { 490 sprintf (buf, "\t// from address pool at 0x%x", 491 (unsigned int)value); 492 strcat (str, buf); 493 } 494 break; 495 } 496 case OPRND_TYPE_BLOOP_OFF4b: 497 case OPRND_TYPE_BLOOP_OFF12b: 498 case OPRND_TYPE_OFF11b: 499 case OPRND_TYPE_OFF16b_LSL1: 500 case OPRND_TYPE_IMM_OFF18b: 501 case OPRND_TYPE_OFF26b: 502 { 503 int shift = oprnd->shift; 504 if (value & ((max >> 1) + 1)) 505 value |= ~max; 506 if (is_extern_symbol (dis_info.info, dis_info.mem)) 507 value = 0; 508 else if (IS_CSKY_V1 (mach_flag)) 509 value = dis_info.mem + 2 + (value << shift); 510 else 511 value = dis_info.mem + (value << shift); 512 dis_info.need_output_symbol = 1; 513 dis_info.value= value; 514 sprintf (buf, "0x%x", (unsigned int)value); 515 strcat (str, buf); 516 break; 517 } 518 case OPRND_TYPE_CONSTANT: 519 case OPRND_TYPE_FCONSTANT: 520 { 521 int shift = oprnd->shift; 522 bfd_byte ibytes[8]; 523 int status; 524 bfd_vma addr; 525 int nbytes; 526 527 dis_info.info->stop_vma = 0; 528 value <<= shift; 529 530 if (IS_CSKY_V1 (mach_flag)) 531 addr = (dis_info.mem + 2 + value) & 0xfffffffc; 532 else 533 addr = (dis_info.mem + value) & 0xfffffffc; 534 535 if (oprnd->type == OPRND_TYPE_FCONSTANT 536 && dis_info.opinfo->opcode != CSKYV2_INST_FLRW) 537 nbytes = 8; 538 else 539 nbytes = 4; 540 541 status = dis_info.info->read_memory_func (addr, ibytes, 542 nbytes, dis_info.info); 543 if (status != 0) 544 /* Address out of bounds. -> lrw rx, [pc, 0ffset]. */ 545 sprintf (buf, "[pc, %d]\t// from address pool at %x", (int)value, 546 (unsigned int)addr); 547 else if (oprnd->type == OPRND_TYPE_FCONSTANT) 548 { 549 double f; 550 551 if (dis_info.opinfo->opcode == CSKYV2_INST_FLRW) 552 /* flrws. */ 553 floatformat_to_double ((dis_info.info->endian == BFD_ENDIAN_BIG 554 ? &floatformat_ieee_single_big 555 : &floatformat_ieee_single_little), 556 ibytes, &f); 557 else 558 floatformat_to_double ((dis_info.info->endian == BFD_ENDIAN_BIG 559 ? &floatformat_ieee_double_big 560 : &floatformat_ieee_double_little), 561 ibytes, &f); 562 sprintf (buf, "%.7g", f); 563 } 564 else 565 { 566 dis_info.value = addr; 567 dis_info.need_output_symbol = 1; 568 value = csky_chars_to_number (ibytes, 4); 569 sprintf (buf, "0x%x", (unsigned int) value); 570 } 571 572 strcat (str, buf); 573 break; 574 } 575 case OPRND_TYPE_ELRW_CONSTANT: 576 { 577 int shift = oprnd->shift; 578 char ibytes[4]; 579 int status; 580 bfd_vma addr; 581 dis_info.info->stop_vma = 0; 582 583 value = 0x80 + ((~value) & 0x7f); 584 585 value = value << shift; 586 addr = (dis_info.mem + value) & 0xfffffffc; 587 588 status = dis_info.info->read_memory_func (addr, (bfd_byte *)ibytes, 589 4, dis_info.info); 590 if (status != 0) 591 /* Address out of bounds. -> lrw rx, [pc, 0ffset]. */ 592 sprintf (buf, "[pc, %d]\t// from address pool at %x", (int) value, 593 (unsigned int)addr); 594 else 595 { 596 dis_info.value = addr; 597 value = csky_chars_to_number ((unsigned char *)ibytes, 4); 598 dis_info.need_output_symbol = 1; 599 sprintf (buf, "0x%x", (unsigned int)value); 600 } 601 602 strcat (str, buf); 603 break; 604 } 605 case OPRND_TYPE_SFLOAT: 606 case OPRND_TYPE_DFLOAT: 607 { 608 /* This is for fmovis/fmovid, which have an internal 13-bit 609 encoding that they convert to single/double precision 610 (respectively). We'll convert the 13-bit encoding to an IEEE 611 double and then to host double format to print it. 612 Sign bit: bit 20. 613 4-bit exponent: bits 19:16, biased by 11. 614 8-bit mantissa: split between 24:21 and 7:4. */ 615 uint64_t imm4; 616 uint64_t imm8; 617 uint64_t dbnum; 618 unsigned char valbytes[8]; 619 double fvalue; 620 621 imm4 = ((inst >> 16) & 0xf); 622 imm4 = (uint64_t)(1023 - (imm4 - 11)) << 52; 623 624 imm8 = (uint64_t)((inst >> 4) & 0xf) << 44; 625 imm8 |= (uint64_t)((inst >> 21) & 0xf) << 48; 626 627 dbnum = (uint64_t)((inst >> 20) & 1) << 63; 628 dbnum |= imm4 | imm8; 629 630 /* Do this a byte at a time so we don't have to 631 worry about the host's endianness. */ 632 valbytes[0] = dbnum & 0xff; 633 valbytes[1] = (dbnum >> 8) & 0xff; 634 valbytes[2] = (dbnum >> 16) & 0xff; 635 valbytes[3] = (dbnum >> 24) & 0xff; 636 valbytes[4] = (dbnum >> 32) & 0xff; 637 valbytes[5] = (dbnum >> 40) & 0xff; 638 valbytes[6] = (dbnum >> 48) & 0xff; 639 valbytes[7] = (dbnum >> 56) & 0xff; 640 641 floatformat_to_double (&floatformat_ieee_double_little, valbytes, 642 &fvalue); 643 644 sprintf (buf, "%.7g", fvalue); 645 strcat (str, buf); 646 break; 647 } 648 case OPRND_TYPE_HFLOAT_FMOVI: 649 case OPRND_TYPE_SFLOAT_FMOVI: 650 { 651 int imm4; 652 int imm8; 653 imm4 = ((inst >> 16) & 0xf); 654 imm4 = (138 - imm4) << 23; 655 656 imm8 = ((inst >> 8) & 0x3); 657 imm8 |= (((inst >> 20) & 0x3f) << 2); 658 imm8 <<= 15; 659 660 value = ((inst >> 5) & 1) << 31; 661 value |= imm4 | imm8; 662 663 imm4 = 138 - (imm4 >> 23); 664 imm8 >>= 15; 665 if ((inst >> 5) & 1) 666 { 667 imm8 = 0 - imm8; 668 } 669 670 float f = 0; 671 memcpy (&f, &value, sizeof (float)); 672 sprintf (buf, "%.7g\t// imm9:%4d, imm4:%2d", f, imm8, imm4); 673 strcat (str, buf); 674 675 break; 676 } 677 678 case OPRND_TYPE_DFLOAT_FMOVI: 679 { 680 uint64_t imm4; 681 uint64_t imm8; 682 uint64_t dvalue; 683 imm4 = ((inst >> 16) & 0xf); 684 imm4 = (1034 - imm4) << 52; 685 686 imm8 = ((inst >> 8) & 0x3); 687 imm8 |= (((inst >> 20) & 0x3f) << 2); 688 imm8 <<= 44; 689 690 dvalue = (((uint64_t)inst >> 5) & 1) << 63; 691 dvalue |= imm4 | imm8; 692 693 imm4 = 1034 - (imm4 >> 52); 694 imm8 >>= 44; 695 if (inst >> 5) 696 { 697 imm8 = 0 - imm8; 698 } 699 double d = 0; 700 memcpy (&d, &dvalue, sizeof (double)); 701 sprintf (buf, "%.7g\t// imm9:%4ld, imm4:%2ld", d, (long) imm8, (long) imm4); 702 strcat (str, buf); 703 704 break; 705 } 706 case OPRND_TYPE_LABEL_WITH_BRACKET: 707 sprintf (buf, "[0x%x]", (unsigned int)value); 708 strcat (str, buf); 709 strcat (str, "\t// the offset is based on .data"); 710 break; 711 case OPRND_TYPE_OIMM3b: 712 case OPRND_TYPE_OIMM4b: 713 case OPRND_TYPE_OIMM5b: 714 case OPRND_TYPE_OIMM5b_IDLY: 715 case OPRND_TYPE_OIMM8b: 716 case OPRND_TYPE_OIMM12b: 717 case OPRND_TYPE_OIMM16b: 718 case OPRND_TYPE_OIMM18b: 719 value += 1; 720 sprintf (buf, "%d", (int)value); 721 strcat (str, buf); 722 break; 723 case OPRND_TYPE_OIMM5b_BMASKI: 724 if (value > 32 || value < 16) 725 { 726 ret = -1; 727 break; 728 } 729 sprintf (buf, "%d", (int)(value + 1)); 730 strcat (str, buf); 731 ret = 0; 732 break; 733 case OPRND_TYPE_FREGLIST_DASH: 734 if (IS_CSKY_V2 (mach_flag)) 735 { 736 int vrx = 0; 737 int vry = 0; 738 if (dis_info.isa & CSKY_ISA_FLOAT_7E60 739 && (strstr (str, "fstm") != NULL 740 || strstr (str, "fldm") != NULL)) 741 { 742 vrx = value & 0x1f; 743 vry = vrx + (value >> 5); 744 } 745 else 746 { 747 vrx = value & 0xf; 748 vry = vrx + (value >> 4); 749 } 750 sprintf (buf, "fr%d-fr%d", vrx, vry); 751 strcat (str, buf); 752 } 753 break; 754 case OPRND_TYPE_REGLIST_DASH: 755 if (IS_CSKY_V1 (mach_flag)) 756 { 757 sprintf (buf, "%s-r15", get_gr_name (value)); 758 strcat (str, buf); 759 } 760 else 761 { 762 if ((value & 0x1f) + (value >> 5) > 31) 763 { 764 ret = -1; 765 break; 766 } 767 strcat (str, get_gr_name ((value >> 5))); 768 strcat (str, "-"); 769 strcat (str, get_gr_name ((value & 0x1f) + (value >> 5))); 770 } 771 break; 772 case OPRND_TYPE_PSR_BITS_LIST: 773 { 774 struct psrbit const *bits; 775 int first_oprnd = true; 776 int i = 0; 777 if (IS_CSKY_V1 (mach_flag)) 778 { 779 if (value == 0) 780 { 781 strcat (str, "af"); 782 break; 783 } 784 bits = cskyv1_psr_bits; 785 } 786 else 787 bits = cskyv2_psr_bits; 788 while (value != 0 && bits[i].name != NULL) 789 { 790 if (value & bits[i].value) 791 { 792 if (!first_oprnd) 793 strcat (str, ", "); 794 strcat (str, bits[i].name); 795 value &= ~bits[i].value; 796 first_oprnd = false; 797 } 798 i++; 799 } 800 break; 801 } 802 case OPRND_TYPE_REGbsp: 803 if (IS_CSKY_V1 (mach_flag)) 804 sprintf(buf, "(%s)", get_gr_name (0)); 805 else 806 sprintf(buf, "(%s)", get_gr_name (14)); 807 strcat (str, buf); 808 break; 809 case OPRND_TYPE_REGsp: 810 if (IS_CSKY_V1 (mach_flag)) 811 strcat (str, get_gr_name (0)); 812 else 813 strcat (str, get_gr_name (14)); 814 break; 815 case OPRND_TYPE_REGnr4_r7: 816 case OPRND_TYPE_AREG_WITH_BRACKET: 817 strcat (str, "("); 818 strcat (str, get_gr_name (value)); 819 strcat (str, ")"); 820 break; 821 case OPRND_TYPE_AREG_WITH_LSHIFT: 822 strcat (str, get_gr_name (value >> 5)); 823 strcat (str, " << "); 824 if ((value & 0x1f) == 0x1) 825 strcat (str, "0"); 826 else if ((value & 0x1f) == 0x2) 827 strcat (str, "1"); 828 else if ((value & 0x1f) == 0x4) 829 strcat (str, "2"); 830 else if ((value & 0x1f) == 0x8) 831 strcat (str, "3"); 832 break; 833 case OPRND_TYPE_AREG_WITH_LSHIFT_FPU: 834 strcat (str, get_gr_name (value >> 2)); 835 strcat (str, " << "); 836 if ((value & 0x3) == 0x0) 837 strcat (str, "0"); 838 else if ((value & 0x3) == 0x1) 839 strcat (str, "1"); 840 else if ((value & 0x3) == 0x2) 841 strcat (str, "2"); 842 else if ((value & 0x3) == 0x3) 843 strcat (str, "3"); 844 break; 845 case OPRND_TYPE_VREG_WITH_INDEX: 846 { 847 unsigned freg_val = value & 0xf; 848 unsigned index_val = (value >> 4) & 0xf; 849 sprintf (buf, "vr%d[%d]", freg_val, index_val); 850 strcat(str, buf); 851 break; 852 } 853 case OPRND_TYPE_FREG_WITH_INDEX: 854 { 855 unsigned freg_val = value & 0xf; 856 unsigned index_val = (value >> 4) & 0xf; 857 sprintf (buf, "fr%d[%d]", freg_val, index_val); 858 strcat(str, buf); 859 break; 860 } 861 case OPRND_TYPE_REGr4_r7: 862 if (IS_CSKY_V1 (mach_flag)) 863 { 864 sprintf (buf, "%s-%s", get_gr_name (4), get_gr_name (7)); 865 strcat (str, buf); 866 } 867 break; 868 case OPRND_TYPE_CONST1: 869 strcat (str, "1"); 870 break; 871 case OPRND_TYPE_REG_r1a: 872 case OPRND_TYPE_REG_r1b: 873 strcat (str, get_gr_name (1)); 874 break; 875 case OPRND_TYPE_REG_r28: 876 strcat (str, get_gr_name (28)); 877 break; 878 case OPRND_TYPE_REGLIST_DASH_COMMA: 879 /* 16-bit reglist. */ 880 if (value & 0xf) 881 { 882 strcat (str, get_gr_name (4)); 883 if ((value & 0xf) > 1) 884 { 885 strcat (str, "-"); 886 strcat (str, get_gr_name ((value & 0xf) + 3)); 887 } 888 if (value & ~0xf) 889 strcat (str, ", "); 890 } 891 if (value & 0x10) 892 { 893 /* r15. */ 894 strcat (str, get_gr_name (15)); 895 if (value & ~0x1f) 896 strcat (str, ", "); 897 } 898 if (dis_info.opinfo->oprnd.oprnds[0].mask != OPRND_MASK_0_4) 899 { 900 /* 32bits reglist. */ 901 value >>= 5; 902 if (value & 0x3) 903 { 904 strcat (str, get_gr_name (16)); 905 if ((value & 0x7) > 1) 906 { 907 strcat (str, "-"); 908 strcat (str, get_gr_name ((value & 0x7) + 15)); 909 } 910 if (value & ~0x7) 911 strcat (str, ", "); 912 } 913 if (value & 0x8) 914 /* r15. */ 915 strcat (str, get_gr_name (28)); 916 } 917 break; 918 case OPRND_TYPE_UNCOND10b: 919 case OPRND_TYPE_UNCOND16b: 920 case OPRND_TYPE_COND10b: 921 case OPRND_TYPE_COND16b: 922 { 923 int shift = oprnd->shift; 924 925 if (value & ((max >> 1) + 1)) 926 value |= ~max; 927 if (is_extern_symbol (dis_info.info, dis_info.mem)) 928 value = 0; 929 else 930 value = dis_info.mem + (value << shift); 931 sprintf (buf, "0x%x", (unsigned int)value); 932 strcat (str, buf); 933 dis_info.need_output_symbol = 1; 934 dis_info.value = value; 935 } 936 break; 937 938 default: 939 ret = -1; 940 break; 941 } 942 return ret; 943 } 944 945 static int 946 csky_print_operand (char *str, struct operand const *oprnd, 947 CSKY_INST_TYPE inst, int reloc) 948 { 949 int ret = -1; 950 char *lc = ""; 951 char *rc = ""; 952 if (oprnd->mask == HAS_SUB_OPERAND) 953 { 954 struct soperand *sop = (struct soperand *)oprnd; 955 if (oprnd->type == OPRND_TYPE_BRACKET) 956 { 957 lc = "("; 958 rc = ")"; 959 } 960 else if (oprnd->type == OPRND_TYPE_ABRACKET) 961 { 962 lc = "<"; 963 rc = ">"; 964 } 965 strcat (str, lc); 966 ret = csky_print_operand (str, &sop->subs[0], inst, reloc); 967 if (ret) 968 return ret; 969 strcat (str, ", "); 970 ret = csky_print_operand (str, &sop->subs[1], inst, reloc); 971 strcat (str, rc); 972 return ret; 973 } 974 return csky_output_operand (str, oprnd, inst, reloc); 975 } 976 977 static int 978 csky_print_operands (char *str, struct csky_opcode_info const *pinfo, 979 struct disassemble_info *info, CSKY_INST_TYPE inst, 980 int reloc) 981 { 982 int i = 0; 983 int ret = 0; 984 if (pinfo->operand_num) 985 strcat (str, " \t"); 986 if (pinfo->operand_num == -1) 987 { 988 ret = csky_print_operand (str, &pinfo->oprnd.oprnds[i], inst, reloc); 989 if (ret) 990 return ret; 991 } 992 else 993 for (; i < pinfo->operand_num; i++) 994 { 995 if (i != 0) 996 strcat (str, ", "); 997 ret = csky_print_operand (str, &pinfo->oprnd.oprnds[i], inst, reloc); 998 if (ret) 999 return ret; 1000 } 1001 info->fprintf_func (info->stream, "%s", str); 1002 if (dis_info.need_output_symbol) 1003 { 1004 info->fprintf_func (info->stream, "\t// "); 1005 info->print_address_func (dis_info.value, dis_info.info); 1006 } 1007 return 0; 1008 } 1009 1010 static void 1011 number_to_chars_littleendian (char *buf, CSKY_INST_TYPE val, int n) 1012 { 1013 if (n <= 0) 1014 abort (); 1015 while (n--) 1016 { 1017 *buf++ = val & 0xff; 1018 val >>= 8; 1019 } 1020 } 1021 1022 #define CSKY_READ_DATA() \ 1023 { \ 1024 status = info->read_memory_func (memaddr, buf, 2, info); \ 1025 if (status) \ 1026 { \ 1027 info->memory_error_func (status, memaddr, info); \ 1028 return -1; \ 1029 } \ 1030 if (info->endian == BFD_ENDIAN_BIG) \ 1031 inst |= (buf[0] << 8) | buf[1]; \ 1032 else if (info->endian == BFD_ENDIAN_LITTLE) \ 1033 inst |= (buf[1] << 8) | buf[0]; \ 1034 else \ 1035 abort(); \ 1036 info->bytes_per_chunk += 2; \ 1037 memaddr += 2; \ 1038 } 1039 1040 int 1041 print_insn_csky (bfd_vma memaddr, struct disassemble_info *info) 1042 { 1043 unsigned char buf[4]; 1044 CSKY_INST_TYPE inst = 0; 1045 int status; 1046 char str[256]; 1047 unsigned long given; 1048 int is_data = false; 1049 void (*printer) (bfd_vma, struct disassemble_info *, long); 1050 unsigned int size = 4; 1051 1052 memset (str, 0, sizeof (str)); 1053 info->bytes_per_chunk = 0; 1054 info->bytes_per_chunk = 0; 1055 dis_info.mem = memaddr; 1056 dis_info.info = info; 1057 dis_info.need_output_symbol = 0; 1058 1059 if (info->disassembler_options) 1060 { 1061 parse_csky_dis_options (info->disassembler_options); 1062 info->disassembler_options = NULL; 1063 } 1064 1065 if (mach_flag != INIT_MACH_FLAG && mach_flag != BINARY_MACH_FLAG) 1066 info->mach = mach_flag; 1067 else if (mach_flag == INIT_MACH_FLAG) 1068 { 1069 mach_flag = info->mach; 1070 dis_info.isa = CSKY_DEFAULT_ISA; 1071 } 1072 1073 if (mach_flag == BINARY_MACH_FLAG && info->endian == BFD_ENDIAN_UNKNOWN) 1074 { 1075 info->endian = BFD_ENDIAN_LITTLE; 1076 dis_info.isa = CSKY_DEFAULT_ISA; 1077 } 1078 1079 /* First check the full symtab for a mapping symbol, even if there 1080 are no usable non-mapping symbols for this address. */ 1081 if (info->symtab_size != 0 1082 && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour) 1083 { 1084 bfd_vma addr; 1085 int n; 1086 int last_sym = -1; 1087 enum sym_type type = CUR_TEXT; 1088 1089 if (memaddr <= last_map_addr) 1090 last_map_sym = -1; 1091 /* Start scanning at the start of the function, or wherever 1092 we finished last time. */ 1093 n = 0; 1094 if (n < last_map_sym) 1095 n = last_map_sym; 1096 1097 /* Scan up to the location being disassembled. */ 1098 for (; n < info->symtab_size; n++) 1099 { 1100 addr = bfd_asymbol_value (info->symtab[n]); 1101 if (addr > memaddr) 1102 break; 1103 if ((info->section == NULL 1104 || info->section == info->symtab[n]->section) 1105 && get_sym_code_type (info, n, &type)) 1106 last_sym = n; 1107 } 1108 last_map_sym = last_sym; 1109 last_type = type; 1110 is_data = (last_type == CUR_DATA); 1111 if (is_data) 1112 { 1113 size = 4 - ( memaddr & 3); 1114 for (n = last_sym + 1; n < info->symtab_size; n++) 1115 { 1116 addr = bfd_asymbol_value (info->symtab[n]); 1117 if (addr > memaddr) 1118 { 1119 if (addr - memaddr < size) 1120 size = addr - memaddr; 1121 break; 1122 } 1123 } 1124 /* If the next symbol is after three bytes, we need to 1125 print only part of the data, so that we can use either 1126 .byte or .short. */ 1127 if (size == 3) 1128 size = (memaddr & 1) ? 1 : 2; 1129 } 1130 } 1131 info->bytes_per_line = 4; 1132 1133 if (is_data) 1134 { 1135 int i; 1136 1137 /* Size was already set above. */ 1138 info->bytes_per_chunk = size; 1139 printer = print_insn_data; 1140 1141 status = info->read_memory_func (memaddr, (bfd_byte *) buf, size, info); 1142 given = 0; 1143 if (info->endian == BFD_ENDIAN_LITTLE) 1144 for (i = size - 1; i >= 0; i--) 1145 given = buf[i] | (given << 8); 1146 else 1147 for (i = 0; i < (int) size; i++) 1148 given = buf[i] | (given << 8); 1149 1150 printer (memaddr, info, given); 1151 return info->bytes_per_chunk; 1152 } 1153 1154 /* Handle instructions. */ 1155 CSKY_READ_DATA(); 1156 if ((inst & 0xc000) == 0xc000 && IS_CSKY_V2 (mach_flag)) 1157 { 1158 /* It's a 32-bit instruction. */ 1159 inst <<= 16; 1160 CSKY_READ_DATA(); 1161 if (info->buffer && (info->endian == BFD_ENDIAN_LITTLE)) 1162 { 1163 char* src = (char *)(info->buffer 1164 + ((memaddr - 4 - info->buffer_vma) 1165 * info->octets_per_byte)); 1166 if (info->endian == BFD_ENDIAN_LITTLE) 1167 number_to_chars_littleendian (src, inst, 4); 1168 } 1169 } 1170 1171 if (IS_CSKY_V1 (mach_flag)) 1172 g_opcodeP = csky_v1_opcodes; 1173 else 1174 g_opcodeP = csky_v2_opcodes; 1175 1176 do 1177 { 1178 struct csky_opcode const *op; 1179 struct csky_opcode_info const *pinfo = NULL; 1180 int reloc; 1181 1182 memset (str, 0, sizeof (str)); 1183 op = csky_find_inst_info (&pinfo, inst, info->bytes_per_chunk); 1184 if (!op) 1185 { 1186 if (IS_CSKY_V1 (mach_flag)) 1187 info->fprintf_func (info->stream, ".short: 0x%04x", 1188 (unsigned short)inst); 1189 else 1190 info->fprintf_func (info->stream, ".long: 0x%08x", 1191 (unsigned int)inst); 1192 return info->bytes_per_chunk; 1193 } 1194 1195 if (info->bytes_per_chunk == 2) 1196 reloc = op->reloc16; 1197 else 1198 reloc = op->reloc32; 1199 dis_info.opinfo = pinfo; 1200 strcat (str, op->mnemonic); 1201 1202 if (csky_print_operands (str, pinfo, info, inst, reloc)) 1203 g_opcodeP++; 1204 else 1205 break; 1206 } while (1); 1207 1208 return info->bytes_per_chunk; 1209 } 1210