1/* C-SKY disassembler. 2 Copyright (C) 1988-2022 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 38enum sym_type 39{ 40 CUR_TEXT, 41 CUR_DATA 42}; 43 44struct 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 60enum sym_type last_type; 61int last_map_sym = 1; 62bfd_vma last_map_addr = 0; 63int using_abi = 0; 64 65/* Only for objdump tool. */ 66#define INIT_MACH_FLAG 0xffffffff 67#define BINARY_MACH_FLAG 0x0 68 69static unsigned int mach_flag = INIT_MACH_FLAG; 70 71static void 72print_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 92static int 93get_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 108static int 109csky_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 122static int 123csky_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 138static unsigned int 139csky_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 153static struct csky_opcode const *g_opcodeP; 154 155static struct csky_opcode const * 156csky_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 203static bool 204is_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 225bool 226csky_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 237disassembler_ftype 238csky_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. */ 267static void 268parse_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. */ 287static const char * 288get_gr_name (int regno) 289{ 290 return csky_get_general_reg_name (mach_flag, regno, using_abi); 291} 292 293/* Get control register name. */ 294static const char * 295get_cr_name (unsigned int regno, int bank) 296{ 297 return csky_get_control_reg_name (mach_flag, bank, regno, using_abi); 298} 299 300static int 301csky_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 char 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, (bfd_byte *)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 548 { 549 dis_info.value = addr; 550 value = csky_chars_to_number ((unsigned char *)ibytes, 4); 551 } 552 553 if (oprnd->type == OPRND_TYPE_FCONSTANT) 554 { 555 double f; 556 557 if (dis_info.opinfo->opcode == CSKYV2_INST_FLRW) 558 /* flrws. */ 559 floatformat_to_double ((dis_info.info->endian == BFD_ENDIAN_BIG 560 ? &floatformat_ieee_single_big 561 : &floatformat_ieee_single_little), 562 ibytes, &f); 563 else 564 floatformat_to_double ((dis_info.info->endian == BFD_ENDIAN_BIG 565 ? &floatformat_ieee_double_big 566 : &floatformat_ieee_double_little), 567 ibytes, &f); 568 sprintf (buf, "%.7g", f); 569 } 570 else 571 { 572 dis_info.need_output_symbol = 1; 573 sprintf (buf, "0x%x", (unsigned int)value); 574 } 575 576 strcat (str, buf); 577 break; 578 } 579 case OPRND_TYPE_ELRW_CONSTANT: 580 { 581 int shift = oprnd->shift; 582 char ibytes[4]; 583 int status; 584 bfd_vma addr; 585 dis_info.info->stop_vma = 0; 586 587 value = 0x80 + ((~value) & 0x7f); 588 589 value = value << shift; 590 addr = (dis_info.mem + value) & 0xfffffffc; 591 592 status = dis_info.info->read_memory_func (addr, (bfd_byte *)ibytes, 593 4, dis_info.info); 594 if (status != 0) 595 /* Address out of bounds. -> lrw rx, [pc, 0ffset]. */ 596 sprintf (buf, "[pc, %d]\t// from address pool at %x", (int) value, 597 (unsigned int)addr); 598 else 599 { 600 dis_info.value = addr; 601 value = csky_chars_to_number ((unsigned char *)ibytes, 4); 602 dis_info.need_output_symbol = 1; 603 sprintf (buf, "0x%x", (unsigned int)value); 604 } 605 606 strcat (str, buf); 607 break; 608 } 609 case OPRND_TYPE_SFLOAT: 610 case OPRND_TYPE_DFLOAT: 611 { 612 /* This is for fmovis/fmovid, which have an internal 13-bit 613 encoding that they convert to single/double precision 614 (respectively). We'll convert the 13-bit encoding to an IEEE 615 double and then to host double format to print it. 616 Sign bit: bit 20. 617 4-bit exponent: bits 19:16, biased by 11. 618 8-bit mantissa: split between 24:21 and 7:4. */ 619 uint64_t imm4; 620 uint64_t imm8; 621 uint64_t dbnum; 622 unsigned char valbytes[8]; 623 double fvalue; 624 625 imm4 = ((inst >> 16) & 0xf); 626 imm4 = (uint64_t)(1023 - (imm4 - 11)) << 52; 627 628 imm8 = (uint64_t)((inst >> 4) & 0xf) << 44; 629 imm8 |= (uint64_t)((inst >> 21) & 0xf) << 48; 630 631 dbnum = (uint64_t)((inst >> 20) & 1) << 63; 632 dbnum |= imm4 | imm8; 633 634 /* Do this a byte at a time so we don't have to 635 worry about the host's endianness. */ 636 valbytes[0] = dbnum & 0xff; 637 valbytes[1] = (dbnum >> 8) & 0xff; 638 valbytes[2] = (dbnum >> 16) & 0xff; 639 valbytes[3] = (dbnum >> 24) & 0xff; 640 valbytes[4] = (dbnum >> 32) & 0xff; 641 valbytes[5] = (dbnum >> 40) & 0xff; 642 valbytes[6] = (dbnum >> 48) & 0xff; 643 valbytes[7] = (dbnum >> 56) & 0xff; 644 645 floatformat_to_double (&floatformat_ieee_double_little, valbytes, 646 &fvalue); 647 648 sprintf (buf, "%.7g", fvalue); 649 strcat (str, buf); 650 break; 651 } 652 case OPRND_TYPE_HFLOAT_FMOVI: 653 case OPRND_TYPE_SFLOAT_FMOVI: 654 { 655 int imm4; 656 int imm8; 657 imm4 = ((inst >> 16) & 0xf); 658 imm4 = (138 - imm4) << 23; 659 660 imm8 = ((inst >> 8) & 0x3); 661 imm8 |= (((inst >> 20) & 0x3f) << 2); 662 imm8 <<= 15; 663 664 value = ((inst >> 5) & 1) << 31; 665 value |= imm4 | imm8; 666 667 imm4 = 138 - (imm4 >> 23); 668 imm8 >>= 15; 669 if ((inst >> 5) & 1) 670 { 671 imm8 = 0 - imm8; 672 } 673 674 float f = 0; 675 memcpy (&f, &value, sizeof (float)); 676 sprintf (buf, "%.7g\t// imm9:%4d, imm4:%2d", f, imm8, imm4); 677 strcat (str, buf); 678 679 break; 680 } 681 682 case OPRND_TYPE_DFLOAT_FMOVI: 683 { 684 uint64_t imm4; 685 uint64_t imm8; 686 uint64_t dvalue; 687 imm4 = ((inst >> 16) & 0xf); 688 imm4 = (1034 - imm4) << 52; 689 690 imm8 = ((inst >> 8) & 0x3); 691 imm8 |= (((inst >> 20) & 0x3f) << 2); 692 imm8 <<= 44; 693 694 dvalue = (((uint64_t)inst >> 5) & 1) << 63; 695 dvalue |= imm4 | imm8; 696 697 imm4 = 1034 - (imm4 >> 52); 698 imm8 >>= 44; 699 if (inst >> 5) 700 { 701 imm8 = 0 - imm8; 702 } 703 double d = 0; 704 memcpy (&d, &dvalue, sizeof (double)); 705 sprintf (buf, "%.7g\t// imm9:%4ld, imm4:%2ld", d, (long) imm8, (long) imm4); 706 strcat (str, buf); 707 708 break; 709 } 710 case OPRND_TYPE_LABEL_WITH_BRACKET: 711 sprintf (buf, "[0x%x]", (unsigned int)value); 712 strcat (str, buf); 713 strcat (str, "\t// the offset is based on .data"); 714 break; 715 case OPRND_TYPE_OIMM3b: 716 case OPRND_TYPE_OIMM4b: 717 case OPRND_TYPE_OIMM5b: 718 case OPRND_TYPE_OIMM5b_IDLY: 719 case OPRND_TYPE_OIMM8b: 720 case OPRND_TYPE_OIMM12b: 721 case OPRND_TYPE_OIMM16b: 722 case OPRND_TYPE_OIMM18b: 723 value += 1; 724 sprintf (buf, "%d", (int)value); 725 strcat (str, buf); 726 break; 727 case OPRND_TYPE_OIMM5b_BMASKI: 728 if (value > 32 || value < 16) 729 { 730 ret = -1; 731 break; 732 } 733 sprintf (buf, "%d", (int)(value + 1)); 734 strcat (str, buf); 735 ret = 0; 736 break; 737 case OPRND_TYPE_FREGLIST_DASH: 738 if (IS_CSKY_V2 (mach_flag)) 739 { 740 int vrx = 0; 741 int vry = 0; 742 if (dis_info.isa & CSKY_ISA_FLOAT_7E60 743 && (strstr (str, "fstm") != NULL 744 || strstr (str, "fldm") != NULL)) 745 { 746 vrx = value & 0x1f; 747 vry = vrx + (value >> 5); 748 } 749 else 750 { 751 vrx = value & 0xf; 752 vry = vrx + (value >> 4); 753 } 754 sprintf (buf, "fr%d-fr%d", vrx, vry); 755 strcat (str, buf); 756 } 757 break; 758 case OPRND_TYPE_REGLIST_DASH: 759 if (IS_CSKY_V1 (mach_flag)) 760 { 761 sprintf (buf, "%s-r15", get_gr_name (value)); 762 strcat (str, buf); 763 } 764 else 765 { 766 if ((value & 0x1f) + (value >> 5) > 31) 767 { 768 ret = -1; 769 break; 770 } 771 strcat (str, get_gr_name ((value >> 5))); 772 strcat (str, "-"); 773 strcat (str, get_gr_name ((value & 0x1f) + (value >> 5))); 774 } 775 break; 776 case OPRND_TYPE_PSR_BITS_LIST: 777 { 778 struct psrbit const *bits; 779 int first_oprnd = true; 780 int i = 0; 781 if (IS_CSKY_V1 (mach_flag)) 782 { 783 if (value == 0) 784 { 785 strcat (str, "af"); 786 break; 787 } 788 bits = cskyv1_psr_bits; 789 } 790 else 791 bits = cskyv2_psr_bits; 792 while (value != 0 && bits[i].name != NULL) 793 { 794 if (value & bits[i].value) 795 { 796 if (!first_oprnd) 797 strcat (str, ", "); 798 strcat (str, bits[i].name); 799 value &= ~bits[i].value; 800 first_oprnd = false; 801 } 802 i++; 803 } 804 break; 805 } 806 case OPRND_TYPE_REGbsp: 807 if (IS_CSKY_V1 (mach_flag)) 808 sprintf(buf, "(%s)", get_gr_name (0)); 809 else 810 sprintf(buf, "(%s)", get_gr_name (14)); 811 strcat (str, buf); 812 break; 813 case OPRND_TYPE_REGsp: 814 if (IS_CSKY_V1 (mach_flag)) 815 strcat (str, get_gr_name (0)); 816 else 817 strcat (str, get_gr_name (14)); 818 break; 819 case OPRND_TYPE_REGnr4_r7: 820 case OPRND_TYPE_AREG_WITH_BRACKET: 821 strcat (str, "("); 822 strcat (str, get_gr_name (value)); 823 strcat (str, ")"); 824 break; 825 case OPRND_TYPE_AREG_WITH_LSHIFT: 826 strcat (str, get_gr_name (value >> 5)); 827 strcat (str, " << "); 828 if ((value & 0x1f) == 0x1) 829 strcat (str, "0"); 830 else if ((value & 0x1f) == 0x2) 831 strcat (str, "1"); 832 else if ((value & 0x1f) == 0x4) 833 strcat (str, "2"); 834 else if ((value & 0x1f) == 0x8) 835 strcat (str, "3"); 836 break; 837 case OPRND_TYPE_AREG_WITH_LSHIFT_FPU: 838 strcat (str, get_gr_name (value >> 2)); 839 strcat (str, " << "); 840 if ((value & 0x3) == 0x0) 841 strcat (str, "0"); 842 else if ((value & 0x3) == 0x1) 843 strcat (str, "1"); 844 else if ((value & 0x3) == 0x2) 845 strcat (str, "2"); 846 else if ((value & 0x3) == 0x3) 847 strcat (str, "3"); 848 break; 849 case OPRND_TYPE_VREG_WITH_INDEX: 850 { 851 unsigned freg_val = value & 0xf; 852 unsigned index_val = (value >> 4) & 0xf; 853 sprintf (buf, "vr%d[%d]", freg_val, index_val); 854 strcat(str, buf); 855 break; 856 } 857 case OPRND_TYPE_FREG_WITH_INDEX: 858 { 859 unsigned freg_val = value & 0xf; 860 unsigned index_val = (value >> 4) & 0xf; 861 sprintf (buf, "fr%d[%d]", freg_val, index_val); 862 strcat(str, buf); 863 break; 864 } 865 case OPRND_TYPE_REGr4_r7: 866 if (IS_CSKY_V1 (mach_flag)) 867 { 868 sprintf (buf, "%s-%s", get_gr_name (4), get_gr_name (7)); 869 strcat (str, buf); 870 } 871 break; 872 case OPRND_TYPE_CONST1: 873 strcat (str, "1"); 874 break; 875 case OPRND_TYPE_REG_r1a: 876 case OPRND_TYPE_REG_r1b: 877 strcat (str, get_gr_name (1)); 878 break; 879 case OPRND_TYPE_REG_r28: 880 strcat (str, get_gr_name (28)); 881 break; 882 case OPRND_TYPE_REGLIST_DASH_COMMA: 883 /* 16-bit reglist. */ 884 if (value & 0xf) 885 { 886 strcat (str, get_gr_name (4)); 887 if ((value & 0xf) > 1) 888 { 889 strcat (str, "-"); 890 strcat (str, get_gr_name ((value & 0xf) + 3)); 891 } 892 if (value & ~0xf) 893 strcat (str, ", "); 894 } 895 if (value & 0x10) 896 { 897 /* r15. */ 898 strcat (str, get_gr_name (15)); 899 if (value & ~0x1f) 900 strcat (str, ", "); 901 } 902 if (dis_info.opinfo->oprnd.oprnds[0].mask != OPRND_MASK_0_4) 903 { 904 /* 32bits reglist. */ 905 value >>= 5; 906 if (value & 0x3) 907 { 908 strcat (str, get_gr_name (16)); 909 if ((value & 0x7) > 1) 910 { 911 strcat (str, "-"); 912 strcat (str, get_gr_name ((value & 0x7) + 15)); 913 } 914 if (value & ~0x7) 915 strcat (str, ", "); 916 } 917 if (value & 0x8) 918 /* r15. */ 919 strcat (str, get_gr_name (28)); 920 } 921 break; 922 case OPRND_TYPE_UNCOND10b: 923 case OPRND_TYPE_UNCOND16b: 924 case OPRND_TYPE_COND10b: 925 case OPRND_TYPE_COND16b: 926 { 927 int shift = oprnd->shift; 928 929 if (value & ((max >> 1) + 1)) 930 value |= ~max; 931 if (is_extern_symbol (dis_info.info, dis_info.mem)) 932 value = 0; 933 else 934 value = dis_info.mem + (value << shift); 935 sprintf (buf, "0x%x", (unsigned int)value); 936 strcat (str, buf); 937 dis_info.need_output_symbol = 1; 938 dis_info.value = value; 939 } 940 break; 941 942 default: 943 ret = -1; 944 break; 945 } 946 return ret; 947} 948 949static int 950csky_print_operand (char *str, struct operand const *oprnd, 951 CSKY_INST_TYPE inst, int reloc) 952{ 953 int ret = -1; 954 char *lc = ""; 955 char *rc = ""; 956 if (oprnd->mask == HAS_SUB_OPERAND) 957 { 958 struct soperand *sop = (struct soperand *)oprnd; 959 if (oprnd->type == OPRND_TYPE_BRACKET) 960 { 961 lc = "("; 962 rc = ")"; 963 } 964 else if (oprnd->type == OPRND_TYPE_ABRACKET) 965 { 966 lc = "<"; 967 rc = ">"; 968 } 969 strcat (str, lc); 970 ret = csky_print_operand (str, &sop->subs[0], inst, reloc); 971 if (ret) 972 return ret; 973 strcat (str, ", "); 974 ret = csky_print_operand (str, &sop->subs[1], inst, reloc); 975 strcat (str, rc); 976 return ret; 977 } 978 return csky_output_operand (str, oprnd, inst, reloc); 979} 980 981static int 982csky_print_operands (char *str, struct csky_opcode_info const *pinfo, 983 struct disassemble_info *info, CSKY_INST_TYPE inst, 984 int reloc) 985{ 986 int i = 0; 987 int ret = 0; 988 if (pinfo->operand_num) 989 strcat (str, " \t"); 990 if (pinfo->operand_num == -1) 991 { 992 ret = csky_print_operand (str, &pinfo->oprnd.oprnds[i], inst, reloc); 993 if (ret) 994 return ret; 995 } 996 else 997 for (; i < pinfo->operand_num; i++) 998 { 999 if (i != 0) 1000 strcat (str, ", "); 1001 ret = csky_print_operand (str, &pinfo->oprnd.oprnds[i], inst, reloc); 1002 if (ret) 1003 return ret; 1004 } 1005 info->fprintf_func (info->stream, "%s", str); 1006 if (dis_info.need_output_symbol) 1007 { 1008 info->fprintf_func (info->stream, "\t// "); 1009 info->print_address_func (dis_info.value, dis_info.info); 1010 } 1011 return 0; 1012} 1013 1014static void 1015number_to_chars_littleendian (char *buf, CSKY_INST_TYPE val, int n) 1016{ 1017 if (n <= 0) 1018 abort (); 1019 while (n--) 1020 { 1021 *buf++ = val & 0xff; 1022 val >>= 8; 1023 } 1024} 1025 1026#define CSKY_READ_DATA() \ 1027{ \ 1028 status = info->read_memory_func (memaddr, buf, 2, info); \ 1029 if (status) \ 1030 { \ 1031 info->memory_error_func (status, memaddr, info); \ 1032 return -1; \ 1033 } \ 1034 if (info->endian == BFD_ENDIAN_BIG) \ 1035 inst |= (buf[0] << 8) | buf[1]; \ 1036 else if (info->endian == BFD_ENDIAN_LITTLE) \ 1037 inst |= (buf[1] << 8) | buf[0]; \ 1038 else \ 1039 abort(); \ 1040 info->bytes_per_chunk += 2; \ 1041 memaddr += 2; \ 1042} 1043 1044int 1045print_insn_csky (bfd_vma memaddr, struct disassemble_info *info) 1046{ 1047 unsigned char buf[4]; 1048 CSKY_INST_TYPE inst = 0; 1049 int status; 1050 char str[256]; 1051 unsigned long given; 1052 int is_data = false; 1053 void (*printer) (bfd_vma, struct disassemble_info *, long); 1054 unsigned int size = 4; 1055 1056 memset (str, 0, sizeof (str)); 1057 info->bytes_per_chunk = 0; 1058 info->bytes_per_chunk = 0; 1059 dis_info.mem = memaddr; 1060 dis_info.info = info; 1061 dis_info.need_output_symbol = 0; 1062 1063 if (info->disassembler_options) 1064 { 1065 parse_csky_dis_options (info->disassembler_options); 1066 info->disassembler_options = NULL; 1067 } 1068 1069 if (mach_flag != INIT_MACH_FLAG && mach_flag != BINARY_MACH_FLAG) 1070 info->mach = mach_flag; 1071 else if (mach_flag == INIT_MACH_FLAG) 1072 { 1073 mach_flag = info->mach; 1074 dis_info.isa = CSKY_DEFAULT_ISA; 1075 } 1076 1077 if (mach_flag == BINARY_MACH_FLAG && info->endian == BFD_ENDIAN_UNKNOWN) 1078 { 1079 info->endian = BFD_ENDIAN_LITTLE; 1080 dis_info.isa = CSKY_DEFAULT_ISA; 1081 } 1082 1083 /* First check the full symtab for a mapping symbol, even if there 1084 are no usable non-mapping symbols for this address. */ 1085 if (info->symtab_size != 0 1086 && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour) 1087 { 1088 bfd_vma addr; 1089 int n; 1090 int last_sym = -1; 1091 enum sym_type type = CUR_TEXT; 1092 1093 if (memaddr <= last_map_addr) 1094 last_map_sym = -1; 1095 /* Start scanning at the start of the function, or wherever 1096 we finished last time. */ 1097 n = 0; 1098 if (n < last_map_sym) 1099 n = last_map_sym; 1100 1101 /* Scan up to the location being disassembled. */ 1102 for (; n < info->symtab_size; n++) 1103 { 1104 addr = bfd_asymbol_value (info->symtab[n]); 1105 if (addr > memaddr) 1106 break; 1107 if ((info->section == NULL 1108 || info->section == info->symtab[n]->section) 1109 && get_sym_code_type (info, n, &type)) 1110 last_sym = n; 1111 } 1112 last_map_sym = last_sym; 1113 last_type = type; 1114 is_data = (last_type == CUR_DATA); 1115 if (is_data) 1116 { 1117 size = 4 - ( memaddr & 3); 1118 for (n = last_sym + 1; n < info->symtab_size; n++) 1119 { 1120 addr = bfd_asymbol_value (info->symtab[n]); 1121 if (addr > memaddr) 1122 { 1123 if (addr - memaddr < size) 1124 size = addr - memaddr; 1125 break; 1126 } 1127 } 1128 /* If the next symbol is after three bytes, we need to 1129 print only part of the data, so that we can use either 1130 .byte or .short. */ 1131 if (size == 3) 1132 size = (memaddr & 1) ? 1 : 2; 1133 } 1134 } 1135 info->bytes_per_line = 4; 1136 1137 if (is_data) 1138 { 1139 int i; 1140 1141 /* Size was already set above. */ 1142 info->bytes_per_chunk = size; 1143 printer = print_insn_data; 1144 1145 status = info->read_memory_func (memaddr, (bfd_byte *) buf, size, info); 1146 given = 0; 1147 if (info->endian == BFD_ENDIAN_LITTLE) 1148 for (i = size - 1; i >= 0; i--) 1149 given = buf[i] | (given << 8); 1150 else 1151 for (i = 0; i < (int) size; i++) 1152 given = buf[i] | (given << 8); 1153 1154 printer (memaddr, info, given); 1155 return info->bytes_per_chunk; 1156 } 1157 1158 /* Handle instructions. */ 1159 CSKY_READ_DATA(); 1160 if ((inst & 0xc000) == 0xc000 && IS_CSKY_V2 (mach_flag)) 1161 { 1162 /* It's a 32-bit instruction. */ 1163 inst <<= 16; 1164 CSKY_READ_DATA(); 1165 if (info->buffer && (info->endian == BFD_ENDIAN_LITTLE)) 1166 { 1167 char* src = (char *)(info->buffer 1168 + ((memaddr - 4 - info->buffer_vma) 1169 * info->octets_per_byte)); 1170 if (info->endian == BFD_ENDIAN_LITTLE) 1171 number_to_chars_littleendian (src, inst, 4); 1172 } 1173 } 1174 1175 if (IS_CSKY_V1 (mach_flag)) 1176 g_opcodeP = csky_v1_opcodes; 1177 else 1178 g_opcodeP = csky_v2_opcodes; 1179 1180 do 1181 { 1182 struct csky_opcode const *op; 1183 struct csky_opcode_info const *pinfo = NULL; 1184 int reloc; 1185 1186 memset (str, 0, sizeof (str)); 1187 op = csky_find_inst_info (&pinfo, inst, info->bytes_per_chunk); 1188 if (!op) 1189 { 1190 if (IS_CSKY_V1 (mach_flag)) 1191 info->fprintf_func (info->stream, ".short: 0x%04x", 1192 (unsigned short)inst); 1193 else 1194 info->fprintf_func (info->stream, ".long: 0x%08x", 1195 (unsigned int)inst); 1196 return info->bytes_per_chunk; 1197 } 1198 1199 if (info->bytes_per_chunk == 2) 1200 reloc = op->reloc16; 1201 else 1202 reloc = op->reloc32; 1203 dis_info.opinfo = pinfo; 1204 strcat (str, op->mnemonic); 1205 1206 if (csky_print_operands (str, pinfo, info, inst, reloc)) 1207 g_opcodeP++; 1208 else 1209 break; 1210 } while (1); 1211 1212 return info->bytes_per_chunk; 1213} 1214