Extend objdump's --show-all-symbols option so that it also shows the extra symbols...
[binutils-gdb.git] / opcodes / csky-dis.c
blobe9635bcf4be33d866ca0249338169030e5dbffbd
1 /* C-SKY disassembler.
2 Copyright (C) 1988-2024 Free Software Foundation, Inc.
3 Contributed by C-SKY Microsystems and Mentor Graphics.
5 This file is part of the GNU opcodes library.
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.
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.
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. */
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"
34 #define CSKY_INST_TYPE unsigned long
35 #define HAS_SUB_OPERAND (unsigned int)0xffffffff
36 #define CSKY_DEFAULT_ISA 0xffffffff
38 enum sym_type
40 CUR_TEXT,
41 CUR_DATA
44 struct csky_dis_info
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;
60 enum sym_type last_type;
61 int last_map_sym = 1;
62 bfd_vma last_map_addr = 0;
63 int using_abi = 0;
65 /* Only for objdump tool. */
66 #define INIT_MACH_FLAG 0xffffffff
67 #define BINARY_MACH_FLAG 0x0
69 static unsigned int mach_flag = INIT_MACH_FLAG;
71 static void
72 print_insn_data (bfd_vma pc ATTRIBUTE_UNUSED,
73 struct disassemble_info *info,
74 long given)
76 switch (info->bytes_per_chunk)
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 ();
92 static int
93 get_sym_code_type (struct disassemble_info *info,
94 int n,
95 enum sym_type *sym_type)
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] == '.'))
102 *sym_type = ((name[1] == 't') ? CUR_TEXT : CUR_DATA);
103 return true;
105 return false;
108 static int
109 csky_get_operand_mask (struct operand const *oprnd)
111 int mask = 0;
112 if (oprnd->mask == HAS_SUB_OPERAND)
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;
119 return oprnd->mask;
122 static int
123 csky_get_mask (struct csky_opcode_info const *pinfo)
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]);
134 mask = ~mask;
135 return mask;
138 static unsigned int
139 csky_chars_to_number (unsigned char * buf, int n)
141 int i;
142 unsigned int val = 0;
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;
153 static struct csky_opcode const *g_opcodeP;
155 static struct csky_opcode const *
156 csky_find_inst_info (struct csky_opcode_info const **pinfo,
157 CSKY_INST_TYPE inst, int length)
159 int i;
160 unsigned int mask;
161 struct csky_opcode const *p;
163 p = g_opcodeP;
164 while (p->mnemonic)
166 if (!(p->isa_flag16 & dis_info.isa)
167 && !(p->isa_flag32 & dis_info.isa))
169 p++;
170 continue;
173 /* Get the opcode mask. */
174 for (i = 0; i < OP_TABLE_NUM; i++)
175 if (length == 2)
177 mask = csky_get_mask (&p->op16[i]);
178 if (mask != 0 && (inst & mask) == p->op16[i].opcode)
180 *pinfo = &p->op16[i];
181 g_opcodeP = p;
182 return p;
185 else if (length == 4)
187 mask = csky_get_mask (&p->op32[i]);
188 if (mask != 0
189 && ((unsigned long)(inst & mask)
190 == (unsigned long)p->op32[i].opcode))
192 *pinfo = &p->op32[i];
193 g_opcodeP = p;
194 return p;
197 p++;
200 return NULL;
203 static bool
204 is_extern_symbol (struct disassemble_info *info, int addr)
206 unsigned int rel_count = 0;
208 if (info->section == NULL)
209 return 0;
210 if ((info->section->flags & SEC_RELOC) != 0) /* Fit .o file. */
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;
218 return false;
222 /* Suppress printing of mapping symbols emitted by the assembler to mark
223 the beginning of code and data sequences. */
225 bool
226 csky_symbol_is_valid (asymbol *sym,
227 struct disassemble_info *info ATTRIBUTE_UNUSED)
229 const char *name;
231 if (sym == NULL)
232 return false;
233 name = bfd_asymbol_name (sym);
234 return name && *name != '$';
237 disassembler_ftype
238 csky_get_disassembler (bfd *abfd)
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
246 mach_flag = elf_elfheader (abfd)->e_flags;
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)
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;
259 else
260 dis_info.isa = CSKY_DEFAULT_ISA;
263 return print_insn_csky;
266 /* Parse the string of disassembler options. */
267 static void
268 parse_csky_dis_options (const char *opts_in)
270 char *opts = xstrdup (opts_in);
271 char *opt = opts;
272 char *opt_end = opts;
274 for (; opt_end != NULL; opt = opt_end + 1)
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);
286 /* Get general register name. */
287 static const char *
288 get_gr_name (int regno)
290 return csky_get_general_reg_name (mach_flag, regno, using_abi);
293 /* Get control register name. */
294 static const char *
295 get_cr_name (unsigned int regno, int bank)
297 return csky_get_control_reg_name (mach_flag, bank, regno, using_abi);
300 static int
301 csky_output_operand (char *str, struct operand const *oprnd,
302 CSKY_INST_TYPE inst, int reloc ATTRIBUTE_UNUSED)
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];
312 /* Get operand value with mask. */
313 value = inst & mask;
314 for (; mask; mask >>= 1, value >>=1)
315 if (mask & 0x1)
317 result |= ((value & 0x1) << bit);
318 max |= (1 << bit);
319 bit++;
321 value = result;
323 /* Here is general instructions that have no reloc. */
324 switch (oprnd->type)
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)
337 result |= ((value & 0x1) << bit);
338 bit++;
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))
391 ret = -1;
392 break;
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)
401 ret = -1;
402 break;
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)
411 ret = -1;
412 break;
414 sprintf (buf, "%d", (int)value);
415 strcat (str, buf);
416 ret = 0;
417 break;
418 case OPRND_TYPE_IMM5b_VSH:
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;
427 case OPRND_TYPE_MSB2SIZE:
428 case OPRND_TYPE_LSB2SIZE:
430 static int size;
431 if (oprnd->type == OPRND_TYPE_MSB2SIZE)
432 size = value;
433 else
435 str[strlen (str) - 2] = '\0';
436 sprintf (buf, "%d, %d", (int)(size + value), (int)value);
437 strcat (str, buf);
439 break;
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:
460 unsigned char ibytes[4];
461 int shift = oprnd->shift;
462 int status;
463 unsigned int mem_val;
465 dis_info.info->stop_vma = 0;
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)
474 dis_info.info->memory_error_func (status, dis_info.mem,
475 dis_info.info);
476 return -1;
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)
485 dis_info.value = mem_val;
486 dis_info.need_output_symbol = 1;
488 else
490 sprintf (buf, "\t// from address pool at 0x%x",
491 (unsigned int)value);
492 strcat (str, buf);
494 break;
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:
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;
518 case OPRND_TYPE_CONSTANT:
519 case OPRND_TYPE_FCONSTANT:
521 int shift = oprnd->shift;
522 bfd_byte ibytes[8];
523 int status;
524 bfd_vma addr;
525 int nbytes;
527 dis_info.info->stop_vma = 0;
528 value <<= shift;
530 if (IS_CSKY_V1 (mach_flag))
531 addr = (dis_info.mem + 2 + value) & 0xfffffffc;
532 else
533 addr = (dis_info.mem + value) & 0xfffffffc;
535 if (oprnd->type == OPRND_TYPE_FCONSTANT
536 && dis_info.opinfo->opcode != CSKYV2_INST_FLRW)
537 nbytes = 8;
538 else
539 nbytes = 4;
541 status = dis_info.info->read_memory_func (addr, ibytes,
542 nbytes, dis_info.info);
543 if (status != 0)
544 /* Address out of bounds. -> lrw rx, [pc, 0ffset]. */
545 sprintf (buf, "[pc, %d]\t// from address pool at %x", (int)value,
546 (unsigned int)addr);
547 else if (oprnd->type == OPRND_TYPE_FCONSTANT)
549 double f;
551 if (dis_info.opinfo->opcode == CSKYV2_INST_FLRW)
552 /* flrws. */
553 floatformat_to_double ((dis_info.info->endian == BFD_ENDIAN_BIG
554 ? &floatformat_ieee_single_big
555 : &floatformat_ieee_single_little),
556 ibytes, &f);
557 else
558 floatformat_to_double ((dis_info.info->endian == BFD_ENDIAN_BIG
559 ? &floatformat_ieee_double_big
560 : &floatformat_ieee_double_little),
561 ibytes, &f);
562 sprintf (buf, "%.7g", f);
564 else
566 dis_info.value = addr;
567 dis_info.need_output_symbol = 1;
568 value = csky_chars_to_number (ibytes, 4);
569 sprintf (buf, "0x%x", (unsigned int) value);
572 strcat (str, buf);
573 break;
575 case OPRND_TYPE_ELRW_CONSTANT:
577 int shift = oprnd->shift;
578 char ibytes[4];
579 int status;
580 bfd_vma addr;
581 dis_info.info->stop_vma = 0;
583 value = 0x80 + ((~value) & 0x7f);
585 value = value << shift;
586 addr = (dis_info.mem + value) & 0xfffffffc;
588 status = dis_info.info->read_memory_func (addr, (bfd_byte *)ibytes,
589 4, dis_info.info);
590 if (status != 0)
591 /* Address out of bounds. -> lrw rx, [pc, 0ffset]. */
592 sprintf (buf, "[pc, %d]\t// from address pool at %x", (int) value,
593 (unsigned int)addr);
594 else
596 dis_info.value = addr;
597 value = csky_chars_to_number ((unsigned char *)ibytes, 4);
598 dis_info.need_output_symbol = 1;
599 sprintf (buf, "0x%x", (unsigned int)value);
602 strcat (str, buf);
603 break;
605 case OPRND_TYPE_SFLOAT:
606 case OPRND_TYPE_DFLOAT:
608 /* This is for fmovis/fmovid, which have an internal 13-bit
609 encoding that they convert to single/double precision
610 (respectively). We'll convert the 13-bit encoding to an IEEE
611 double and then to host double format to print it.
612 Sign bit: bit 20.
613 4-bit exponent: bits 19:16, biased by 11.
614 8-bit mantissa: split between 24:21 and 7:4. */
615 uint64_t imm4;
616 uint64_t imm8;
617 uint64_t dbnum;
618 unsigned char valbytes[8];
619 double fvalue;
621 imm4 = ((inst >> 16) & 0xf);
622 imm4 = (uint64_t)(1023 - (imm4 - 11)) << 52;
624 imm8 = (uint64_t)((inst >> 4) & 0xf) << 44;
625 imm8 |= (uint64_t)((inst >> 21) & 0xf) << 48;
627 dbnum = (uint64_t)((inst >> 20) & 1) << 63;
628 dbnum |= imm4 | imm8;
630 /* Do this a byte at a time so we don't have to
631 worry about the host's endianness. */
632 valbytes[0] = dbnum & 0xff;
633 valbytes[1] = (dbnum >> 8) & 0xff;
634 valbytes[2] = (dbnum >> 16) & 0xff;
635 valbytes[3] = (dbnum >> 24) & 0xff;
636 valbytes[4] = (dbnum >> 32) & 0xff;
637 valbytes[5] = (dbnum >> 40) & 0xff;
638 valbytes[6] = (dbnum >> 48) & 0xff;
639 valbytes[7] = (dbnum >> 56) & 0xff;
641 floatformat_to_double (&floatformat_ieee_double_little, valbytes,
642 &fvalue);
644 sprintf (buf, "%.7g", fvalue);
645 strcat (str, buf);
646 break;
648 case OPRND_TYPE_HFLOAT_FMOVI:
649 case OPRND_TYPE_SFLOAT_FMOVI:
651 int imm4;
652 int imm8;
653 imm4 = ((inst >> 16) & 0xf);
654 imm4 = (138 - imm4) << 23;
656 imm8 = ((inst >> 8) & 0x3);
657 imm8 |= (((inst >> 20) & 0x3f) << 2);
658 imm8 <<= 15;
660 value = ((inst >> 5) & 1) << 31;
661 value |= imm4 | imm8;
663 imm4 = 138 - (imm4 >> 23);
664 imm8 >>= 15;
665 if ((inst >> 5) & 1)
667 imm8 = 0 - imm8;
670 float f = 0;
671 memcpy (&f, &value, sizeof (float));
672 sprintf (buf, "%.7g\t// imm9:%4d, imm4:%2d", f, imm8, imm4);
673 strcat (str, buf);
675 break;
678 case OPRND_TYPE_DFLOAT_FMOVI:
680 uint64_t imm4;
681 uint64_t imm8;
682 uint64_t dvalue;
683 imm4 = ((inst >> 16) & 0xf);
684 imm4 = (1034 - imm4) << 52;
686 imm8 = ((inst >> 8) & 0x3);
687 imm8 |= (((inst >> 20) & 0x3f) << 2);
688 imm8 <<= 44;
690 dvalue = (((uint64_t)inst >> 5) & 1) << 63;
691 dvalue |= imm4 | imm8;
693 imm4 = 1034 - (imm4 >> 52);
694 imm8 >>= 44;
695 if (inst >> 5)
697 imm8 = 0 - imm8;
699 double d = 0;
700 memcpy (&d, &dvalue, sizeof (double));
701 sprintf (buf, "%.7g\t// imm9:%4ld, imm4:%2ld", d, (long) imm8, (long) imm4);
702 strcat (str, buf);
704 break;
706 case OPRND_TYPE_LABEL_WITH_BRACKET:
707 sprintf (buf, "[0x%x]", (unsigned int)value);
708 strcat (str, buf);
709 strcat (str, "\t// the offset is based on .data");
710 break;
711 case OPRND_TYPE_OIMM3b:
712 case OPRND_TYPE_OIMM4b:
713 case OPRND_TYPE_OIMM5b:
714 case OPRND_TYPE_OIMM5b_IDLY:
715 case OPRND_TYPE_OIMM8b:
716 case OPRND_TYPE_OIMM12b:
717 case OPRND_TYPE_OIMM16b:
718 case OPRND_TYPE_OIMM18b:
719 value += 1;
720 sprintf (buf, "%d", (int)value);
721 strcat (str, buf);
722 break;
723 case OPRND_TYPE_OIMM5b_BMASKI:
724 if (value > 32 || value < 16)
726 ret = -1;
727 break;
729 sprintf (buf, "%d", (int)(value + 1));
730 strcat (str, buf);
731 ret = 0;
732 break;
733 case OPRND_TYPE_FREGLIST_DASH:
734 if (IS_CSKY_V2 (mach_flag))
736 int vrx = 0;
737 int vry = 0;
738 if (dis_info.isa & CSKY_ISA_FLOAT_7E60
739 && (strstr (str, "fstm") != NULL
740 || strstr (str, "fldm") != NULL))
742 vrx = value & 0x1f;
743 vry = vrx + (value >> 5);
745 else
747 vrx = value & 0xf;
748 vry = vrx + (value >> 4);
750 sprintf (buf, "fr%d-fr%d", vrx, vry);
751 strcat (str, buf);
753 break;
754 case OPRND_TYPE_REGLIST_DASH:
755 if (IS_CSKY_V1 (mach_flag))
757 sprintf (buf, "%s-r15", get_gr_name (value));
758 strcat (str, buf);
760 else
762 if ((value & 0x1f) + (value >> 5) > 31)
764 ret = -1;
765 break;
767 strcat (str, get_gr_name ((value >> 5)));
768 strcat (str, "-");
769 strcat (str, get_gr_name ((value & 0x1f) + (value >> 5)));
771 break;
772 case OPRND_TYPE_PSR_BITS_LIST:
774 struct psrbit const *bits;
775 int first_oprnd = true;
776 int i = 0;
777 if (IS_CSKY_V1 (mach_flag))
779 if (value == 0)
781 strcat (str, "af");
782 break;
784 bits = cskyv1_psr_bits;
786 else
787 bits = cskyv2_psr_bits;
788 while (value != 0 && bits[i].name != NULL)
790 if (value & bits[i].value)
792 if (!first_oprnd)
793 strcat (str, ", ");
794 strcat (str, bits[i].name);
795 value &= ~bits[i].value;
796 first_oprnd = false;
798 i++;
800 break;
802 case OPRND_TYPE_REGbsp:
803 if (IS_CSKY_V1 (mach_flag))
804 sprintf(buf, "(%s)", get_gr_name (0));
805 else
806 sprintf(buf, "(%s)", get_gr_name (14));
807 strcat (str, buf);
808 break;
809 case OPRND_TYPE_REGsp:
810 if (IS_CSKY_V1 (mach_flag))
811 strcat (str, get_gr_name (0));
812 else
813 strcat (str, get_gr_name (14));
814 break;
815 case OPRND_TYPE_REGnr4_r7:
816 case OPRND_TYPE_AREG_WITH_BRACKET:
817 strcat (str, "(");
818 strcat (str, get_gr_name (value));
819 strcat (str, ")");
820 break;
821 case OPRND_TYPE_AREG_WITH_LSHIFT:
822 strcat (str, get_gr_name (value >> 5));
823 strcat (str, " << ");
824 if ((value & 0x1f) == 0x1)
825 strcat (str, "0");
826 else if ((value & 0x1f) == 0x2)
827 strcat (str, "1");
828 else if ((value & 0x1f) == 0x4)
829 strcat (str, "2");
830 else if ((value & 0x1f) == 0x8)
831 strcat (str, "3");
832 break;
833 case OPRND_TYPE_AREG_WITH_LSHIFT_FPU:
834 strcat (str, get_gr_name (value >> 2));
835 strcat (str, " << ");
836 if ((value & 0x3) == 0x0)
837 strcat (str, "0");
838 else if ((value & 0x3) == 0x1)
839 strcat (str, "1");
840 else if ((value & 0x3) == 0x2)
841 strcat (str, "2");
842 else if ((value & 0x3) == 0x3)
843 strcat (str, "3");
844 break;
845 case OPRND_TYPE_VREG_WITH_INDEX:
847 unsigned freg_val = value & 0xf;
848 unsigned index_val = (value >> 4) & 0xf;
849 sprintf (buf, "vr%d[%d]", freg_val, index_val);
850 strcat(str, buf);
851 break;
853 case OPRND_TYPE_FREG_WITH_INDEX:
855 unsigned freg_val = value & 0xf;
856 unsigned index_val = (value >> 4) & 0xf;
857 sprintf (buf, "fr%d[%d]", freg_val, index_val);
858 strcat(str, buf);
859 break;
861 case OPRND_TYPE_REGr4_r7:
862 if (IS_CSKY_V1 (mach_flag))
864 sprintf (buf, "%s-%s", get_gr_name (4), get_gr_name (7));
865 strcat (str, buf);
867 break;
868 case OPRND_TYPE_CONST1:
869 strcat (str, "1");
870 break;
871 case OPRND_TYPE_REG_r1a:
872 case OPRND_TYPE_REG_r1b:
873 strcat (str, get_gr_name (1));
874 break;
875 case OPRND_TYPE_REG_r28:
876 strcat (str, get_gr_name (28));
877 break;
878 case OPRND_TYPE_REGLIST_DASH_COMMA:
879 /* 16-bit reglist. */
880 if (value & 0xf)
882 strcat (str, get_gr_name (4));
883 if ((value & 0xf) > 1)
885 strcat (str, "-");
886 strcat (str, get_gr_name ((value & 0xf) + 3));
888 if (value & ~0xf)
889 strcat (str, ", ");
891 if (value & 0x10)
893 /* r15. */
894 strcat (str, get_gr_name (15));
895 if (value & ~0x1f)
896 strcat (str, ", ");
898 if (dis_info.opinfo->oprnd.oprnds[0].mask != OPRND_MASK_0_4)
900 /* 32bits reglist. */
901 value >>= 5;
902 if (value & 0x3)
904 strcat (str, get_gr_name (16));
905 if ((value & 0x7) > 1)
907 strcat (str, "-");
908 strcat (str, get_gr_name ((value & 0x7) + 15));
910 if (value & ~0x7)
911 strcat (str, ", ");
913 if (value & 0x8)
914 /* r15. */
915 strcat (str, get_gr_name (28));
917 break;
918 case OPRND_TYPE_UNCOND10b:
919 case OPRND_TYPE_UNCOND16b:
920 case OPRND_TYPE_COND10b:
921 case OPRND_TYPE_COND16b:
923 int shift = oprnd->shift;
925 if (value & ((max >> 1) + 1))
926 value |= ~max;
927 if (is_extern_symbol (dis_info.info, dis_info.mem))
928 value = 0;
929 else
930 value = dis_info.mem + (value << shift);
931 sprintf (buf, "0x%x", (unsigned int)value);
932 strcat (str, buf);
933 dis_info.need_output_symbol = 1;
934 dis_info.value = value;
936 break;
938 default:
939 ret = -1;
940 break;
942 return ret;
945 static int
946 csky_print_operand (char *str, struct operand const *oprnd,
947 CSKY_INST_TYPE inst, int reloc)
949 int ret = -1;
950 char *lc = "";
951 char *rc = "";
952 if (oprnd->mask == HAS_SUB_OPERAND)
954 struct soperand *sop = (struct soperand *)oprnd;
955 if (oprnd->type == OPRND_TYPE_BRACKET)
957 lc = "(";
958 rc = ")";
960 else if (oprnd->type == OPRND_TYPE_ABRACKET)
962 lc = "<";
963 rc = ">";
965 strcat (str, lc);
966 ret = csky_print_operand (str, &sop->subs[0], inst, reloc);
967 if (ret)
968 return ret;
969 strcat (str, ", ");
970 ret = csky_print_operand (str, &sop->subs[1], inst, reloc);
971 strcat (str, rc);
972 return ret;
974 return csky_output_operand (str, oprnd, inst, reloc);
977 static int
978 csky_print_operands (char *str, struct csky_opcode_info const *pinfo,
979 struct disassemble_info *info, CSKY_INST_TYPE inst,
980 int reloc)
982 int i = 0;
983 int ret = 0;
984 if (pinfo->operand_num)
985 strcat (str, " \t");
986 if (pinfo->operand_num == -1)
988 ret = csky_print_operand (str, &pinfo->oprnd.oprnds[i], inst, reloc);
989 if (ret)
990 return ret;
992 else
993 for (; i < pinfo->operand_num; i++)
995 if (i != 0)
996 strcat (str, ", ");
997 ret = csky_print_operand (str, &pinfo->oprnd.oprnds[i], inst, reloc);
998 if (ret)
999 return ret;
1001 info->fprintf_func (info->stream, "%s", str);
1002 if (dis_info.need_output_symbol)
1004 info->fprintf_func (info->stream, "\t// ");
1005 info->print_address_func (dis_info.value, dis_info.info);
1007 return 0;
1010 static void
1011 number_to_chars_littleendian (char *buf, CSKY_INST_TYPE val, int n)
1013 if (n <= 0)
1014 abort ();
1015 while (n--)
1017 *buf++ = val & 0xff;
1018 val >>= 8;
1022 #define CSKY_READ_DATA() \
1024 status = info->read_memory_func (memaddr, buf, 2, info); \
1025 if (status) \
1027 info->memory_error_func (status, memaddr, info); \
1028 return -1; \
1030 if (info->endian == BFD_ENDIAN_BIG) \
1031 inst |= (buf[0] << 8) | buf[1]; \
1032 else if (info->endian == BFD_ENDIAN_LITTLE) \
1033 inst |= (buf[1] << 8) | buf[0]; \
1034 else \
1035 abort(); \
1036 info->bytes_per_chunk += 2; \
1037 memaddr += 2; \
1041 print_insn_csky (bfd_vma memaddr, struct disassemble_info *info)
1043 unsigned char buf[4];
1044 CSKY_INST_TYPE inst = 0;
1045 int status;
1046 char str[256];
1047 unsigned long given;
1048 int is_data = false;
1049 void (*printer) (bfd_vma, struct disassemble_info *, long);
1050 unsigned int size = 4;
1052 memset (str, 0, sizeof (str));
1053 info->bytes_per_chunk = 0;
1054 info->bytes_per_chunk = 0;
1055 dis_info.mem = memaddr;
1056 dis_info.info = info;
1057 dis_info.need_output_symbol = 0;
1059 if (info->disassembler_options)
1061 parse_csky_dis_options (info->disassembler_options);
1062 info->disassembler_options = NULL;
1065 if (mach_flag != INIT_MACH_FLAG && mach_flag != BINARY_MACH_FLAG)
1066 info->mach = mach_flag;
1067 else if (mach_flag == INIT_MACH_FLAG)
1069 mach_flag = info->mach;
1070 dis_info.isa = CSKY_DEFAULT_ISA;
1073 if (mach_flag == BINARY_MACH_FLAG && info->endian == BFD_ENDIAN_UNKNOWN)
1075 info->endian = BFD_ENDIAN_LITTLE;
1076 dis_info.isa = CSKY_DEFAULT_ISA;
1079 /* First check the full symtab for a mapping symbol, even if there
1080 are no usable non-mapping symbols for this address. */
1081 if (info->symtab_size != 0
1082 && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour)
1084 bfd_vma addr;
1085 int n;
1086 int last_sym = -1;
1087 enum sym_type type = CUR_TEXT;
1089 if (memaddr <= last_map_addr)
1090 last_map_sym = -1;
1091 /* Start scanning at the start of the function, or wherever
1092 we finished last time. */
1093 n = 0;
1094 if (n < last_map_sym)
1095 n = last_map_sym;
1097 /* Scan up to the location being disassembled. */
1098 for (; n < info->symtab_size; n++)
1100 addr = bfd_asymbol_value (info->symtab[n]);
1101 if (addr > memaddr)
1102 break;
1103 if ((info->section == NULL
1104 || info->section == info->symtab[n]->section)
1105 && get_sym_code_type (info, n, &type))
1106 last_sym = n;
1108 last_map_sym = last_sym;
1109 last_type = type;
1110 is_data = (last_type == CUR_DATA);
1111 if (is_data)
1113 size = 4 - ( memaddr & 3);
1114 for (n = last_sym + 1; n < info->symtab_size; n++)
1116 addr = bfd_asymbol_value (info->symtab[n]);
1117 if (addr > memaddr)
1119 if (addr - memaddr < size)
1120 size = addr - memaddr;
1121 break;
1124 /* If the next symbol is after three bytes, we need to
1125 print only part of the data, so that we can use either
1126 .byte or .short. */
1127 if (size == 3)
1128 size = (memaddr & 1) ? 1 : 2;
1131 info->bytes_per_line = 4;
1133 if (is_data)
1135 int i;
1137 /* Size was already set above. */
1138 info->bytes_per_chunk = size;
1139 printer = print_insn_data;
1141 status = info->read_memory_func (memaddr, (bfd_byte *) buf, size, info);
1142 given = 0;
1143 if (info->endian == BFD_ENDIAN_LITTLE)
1144 for (i = size - 1; i >= 0; i--)
1145 given = buf[i] | (given << 8);
1146 else
1147 for (i = 0; i < (int) size; i++)
1148 given = buf[i] | (given << 8);
1150 printer (memaddr, info, given);
1151 return info->bytes_per_chunk;
1154 /* Handle instructions. */
1155 CSKY_READ_DATA();
1156 if ((inst & 0xc000) == 0xc000 && IS_CSKY_V2 (mach_flag))
1158 /* It's a 32-bit instruction. */
1159 inst <<= 16;
1160 CSKY_READ_DATA();
1161 if (info->buffer && (info->endian == BFD_ENDIAN_LITTLE))
1163 char* src = (char *)(info->buffer
1164 + ((memaddr - 4 - info->buffer_vma)
1165 * info->octets_per_byte));
1166 if (info->endian == BFD_ENDIAN_LITTLE)
1167 number_to_chars_littleendian (src, inst, 4);
1171 if (IS_CSKY_V1 (mach_flag))
1172 g_opcodeP = csky_v1_opcodes;
1173 else
1174 g_opcodeP = csky_v2_opcodes;
1178 struct csky_opcode const *op;
1179 struct csky_opcode_info const *pinfo = NULL;
1180 int reloc;
1182 memset (str, 0, sizeof (str));
1183 op = csky_find_inst_info (&pinfo, inst, info->bytes_per_chunk);
1184 if (!op)
1186 if (IS_CSKY_V1 (mach_flag))
1187 info->fprintf_func (info->stream, ".short: 0x%04x",
1188 (unsigned short)inst);
1189 else
1190 info->fprintf_func (info->stream, ".long: 0x%08x",
1191 (unsigned int)inst);
1192 return info->bytes_per_chunk;
1195 if (info->bytes_per_chunk == 2)
1196 reloc = op->reloc16;
1197 else
1198 reloc = op->reloc32;
1199 dis_info.opinfo = pinfo;
1200 strcat (str, op->mnemonic);
1202 if (csky_print_operands (str, pinfo, info, inst, reloc))
1203 g_opcodeP++;
1204 else
1205 break;
1206 } while (1);
1208 return info->bytes_per_chunk;