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