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