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