Add support for the .gnu.sgstubs section to the linker for ARM/ELF based targets.
[binutils-gdb.git] / opcodes / v850-dis.c
blobd132da493e9844048e7250fa27dea5201d605bcd
1 /* Disassemble V850 instructions.
2 Copyright (C) 1996-2023 Free Software Foundation, Inc.
4 This file is part of the GNU opcodes library.
6 This library is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
11 It is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
22 #include "sysdep.h"
23 #include <stdio.h>
24 #include <string.h>
25 #include "opcode/v850.h"
26 #include "disassemble.h"
27 #include "opintl.h"
28 #include "libiberty.h"
30 static const int v850_cacheop_codes[] =
32 0x00, 0x20, 0x40, 0x60, 0x61, 0x04, 0x06,
33 0x07, 0x24, 0x26, 0x27, 0x44, 0x64, 0x65, -1
36 static const int v850_prefop_codes[] =
37 { 0x00, 0x04, -1};
39 static void
40 print_value (int flags,
41 bfd_vma memaddr,
42 struct disassemble_info *info,
43 long value)
45 if (flags & V850_PCREL)
47 bfd_vma addr = value + memaddr;
49 if (flags & V850_INVERSE_PCREL)
50 addr = memaddr - value;
51 info->print_address_func (addr, info);
53 else if (flags & V850_OPERAND_DISP)
55 if (flags & V850_OPERAND_SIGNED)
57 info->fprintf_func (info->stream, "%ld", value);
59 else
61 info->fprintf_func (info->stream, "%lu", value);
64 else if ((flags & V850E_IMMEDIATE32)
65 || (flags & V850E_IMMEDIATE16HI))
67 info->fprintf_func (info->stream, "0x%lx", value);
69 else
71 if (flags & V850_OPERAND_SIGNED)
73 info->fprintf_func (info->stream, "%ld", value);
75 else
77 info->fprintf_func (info->stream, "%lu", value);
82 static long
83 get_operand_value (const struct v850_operand *operand,
84 unsigned long insn,
85 int bytes_read,
86 bfd_vma memaddr,
87 struct disassemble_info * info,
88 bool noerror,
89 int *invalid)
91 unsigned long value;
92 bfd_byte buffer[4];
94 if ((operand->flags & V850E_IMMEDIATE16)
95 || (operand->flags & V850E_IMMEDIATE16HI))
97 int status = info->read_memory_func (memaddr + bytes_read, buffer, 2, info);
99 if (status == 0)
101 value = bfd_getl16 (buffer);
103 if (operand->flags & V850E_IMMEDIATE16HI)
104 value <<= 16;
105 else if (value & 0x8000)
106 value |= (-1UL << 16);
108 return value;
111 if (!noerror)
112 info->memory_error_func (status, memaddr + bytes_read, info);
114 return 0;
117 if (operand->flags & V850E_IMMEDIATE23)
119 int status = info->read_memory_func (memaddr + 2, buffer, 4, info);
121 if (status == 0)
123 value = bfd_getl32 (buffer);
125 value = (operand->extract) (value, invalid);
127 return value;
130 if (!noerror)
131 info->memory_error_func (status, memaddr + bytes_read, info);
133 return 0;
136 if (operand->flags & V850E_IMMEDIATE32)
138 int status = info->read_memory_func (memaddr + bytes_read, buffer, 4, info);
140 if (status == 0)
142 bytes_read += 4;
143 value = bfd_getl32 (buffer);
145 return value;
148 if (!noerror)
149 info->memory_error_func (status, memaddr + bytes_read, info);
151 return 0;
154 if (operand->extract)
155 value = (operand->extract) (insn, invalid);
156 else
158 if (operand->bits == -1)
159 value = (insn & operand->shift);
160 else
161 value = (insn >> operand->shift) & ((1ul << operand->bits) - 1);
163 if (operand->flags & V850_OPERAND_SIGNED)
165 unsigned long sign = 1ul << (operand->bits - 1);
166 value = (value ^ sign) - sign;
170 return value;
173 static const char *
174 get_v850_sreg_name (unsigned int reg)
176 static const char *const v850_sreg_names[] =
178 "eipc/vip/mpm", "eipsw/mpc", "fepc/tid", "fepsw/ppa", "ecr/vmecr", "psw/vmtid",
179 "sr6/fpsr/vmadr/dcc", "sr7/fpepc/dc0",
180 "sr8/fpst/vpecr/dcv1", "sr9/fpcc/vptid", "sr10/fpcfg/vpadr/spal", "sr11/spau",
181 "sr12/vdecr/ipa0l", "eiic/vdtid/ipa0u", "feic/ipa1l", "dbic/ipa1u",
182 "ctpc/ipa2l", "ctpsw/ipa2u", "dbpc/ipa3l", "dbpsw/ipa3u", "ctbp/dpa0l",
183 "dir/dpa0u", "bpc/dpa0u", "asid/dpa1l",
184 "bpav/dpa1u", "bpam/dpa2l", "bpdv/dpa2u", "bpdm/dpa3l", "eiwr/dpa3u",
185 "fewr", "dbwr", "bsel"
188 if (reg < ARRAY_SIZE (v850_sreg_names))
189 return v850_sreg_names[reg];
190 return _("<invalid s-reg number>");
193 static const char *
194 get_v850_reg_name (unsigned int reg)
196 static const char *const v850_reg_names[] =
198 "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7",
199 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
200 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
201 "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp"
204 if (reg < ARRAY_SIZE (v850_reg_names))
205 return v850_reg_names[reg];
206 return _("<invalid reg number>");
209 static const char *
210 get_v850_vreg_name (unsigned int reg)
212 static const char *const v850_vreg_names[] =
214 "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7", "vr8", "vr9",
215 "vr10", "vr11", "vr12", "vr13", "vr14", "vr15", "vr16", "vr17", "vr18",
216 "vr19", "vr20", "vr21", "vr22", "vr23", "vr24", "vr25", "vr26", "vr27",
217 "vr28", "vr29", "vr30", "vr31"
220 if (reg < ARRAY_SIZE (v850_vreg_names))
221 return v850_vreg_names[reg];
222 return _("<invalid v-reg number>");
225 static const char *
226 get_v850_cc_name (unsigned int reg)
228 static const char *const v850_cc_names[] =
230 "v", "c/l", "z", "nh", "s/n", "t", "lt", "le",
231 "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt"
234 if (reg < ARRAY_SIZE (v850_cc_names))
235 return v850_cc_names[reg];
236 return _("<invalid CC-reg number>");
239 static const char *
240 get_v850_float_cc_name (unsigned int reg)
242 static const char *const v850_float_cc_names[] =
244 "f/t", "un/or", "eq/neq", "ueq/ogl", "olt/uge", "ult/oge", "ole/ugt", "ule/ogt",
245 "sf/st", "ngle/gle", "seq/sne", "ngl/gl", "lt/nlt", "nge/ge", "le/nle", "ngt/gt"
248 if (reg < ARRAY_SIZE (v850_float_cc_names))
249 return v850_float_cc_names[reg];
250 return _("<invalid float-CC-reg number>");
253 static const char *
254 get_v850_cacheop_name (unsigned int reg)
256 static const char *const v850_cacheop_names[] =
258 "chbii", "cibii", "cfali", "cisti", "cildi", "chbid", "chbiwbd",
259 "chbwbd", "cibid", "cibiwbd", "cibwbd", "cfald", "cistd", "cildd"
262 if (reg < ARRAY_SIZE (v850_cacheop_names))
263 return v850_cacheop_names[reg];
264 return _("<invalid cacheop number>");
267 static const char *
268 get_v850_prefop_name (unsigned int reg)
270 static const char *const v850_prefop_names[] =
271 { "prefi", "prefd" };
273 if (reg < ARRAY_SIZE (v850_prefop_names))
274 return v850_prefop_names[reg];
275 return _("<invalid prefop number>");
278 static int
279 disassemble (bfd_vma memaddr,
280 struct disassemble_info *info,
281 int bytes_read,
282 unsigned long insn)
284 struct v850_opcode *op = (struct v850_opcode *) v850_opcodes;
285 const struct v850_operand *operand;
286 int match = 0;
287 int target_processor;
289 switch (info->mach)
291 case 0:
292 default:
293 target_processor = PROCESSOR_V850;
294 break;
296 case bfd_mach_v850e:
297 target_processor = PROCESSOR_V850E;
298 break;
300 case bfd_mach_v850e1:
301 target_processor = PROCESSOR_V850E;
302 break;
304 case bfd_mach_v850e2:
305 target_processor = PROCESSOR_V850E2;
306 break;
308 case bfd_mach_v850e2v3:
309 target_processor = PROCESSOR_V850E2V3;
310 break;
312 case bfd_mach_v850e3v5:
313 target_processor = PROCESSOR_V850E3V5;
314 break;
317 /* If this is a two byte insn, then mask off the high bits. */
318 if (bytes_read == 2)
319 insn &= 0xffff;
321 /* Find the opcode. */
322 while (op->name)
324 if ((op->mask & insn) == op->opcode
325 && (op->processors & target_processor)
326 && !(op->processors & PROCESSOR_OPTION_ALIAS))
328 /* Code check start. */
329 const unsigned char *opindex_ptr;
330 unsigned int opnum;
331 unsigned int memop;
333 for (opindex_ptr = op->operands, opnum = 1;
334 *opindex_ptr != 0;
335 opindex_ptr++, opnum++)
337 int invalid = 0;
338 long value;
340 operand = &v850_operands[*opindex_ptr];
342 value = get_operand_value (operand, insn, bytes_read, memaddr,
343 info, 1, &invalid);
345 if (invalid)
346 goto next_opcode;
348 if ((operand->flags & V850_NOT_R0) && value == 0 && (op->memop) <=2)
349 goto next_opcode;
351 if ((operand->flags & V850_NOT_SA) && value == 0xd)
352 goto next_opcode;
354 if ((operand->flags & V850_NOT_IMM0) && value == 0)
355 goto next_opcode;
358 /* Code check end. */
360 match = 1;
361 (*info->fprintf_func) (info->stream, "%s\t", op->name);
362 #if 0
363 fprintf (stderr, "match: insn: %lx, mask: %lx, opcode: %lx, name: %s\n",
364 insn, op->mask, op->opcode, op->name );
365 #endif
367 memop = op->memop;
368 /* Now print the operands.
370 MEMOP is the operand number at which a memory
371 address specification starts, or zero if this
372 instruction has no memory addresses.
374 A memory address is always two arguments.
376 This information allows us to determine when to
377 insert commas into the output stream as well as
378 when to insert disp[reg] expressions onto the
379 output stream. */
381 for (opindex_ptr = op->operands, opnum = 1;
382 *opindex_ptr != 0;
383 opindex_ptr++, opnum++)
385 bool square = false;
386 long value;
387 int flag;
388 char *prefix;
390 operand = &v850_operands[*opindex_ptr];
392 value = get_operand_value (operand, insn, bytes_read, memaddr,
393 info, 0, 0);
395 /* The first operand is always output without any
396 special handling.
398 For the following arguments:
400 If memop && opnum == memop + 1, then we need '[' since
401 we're about to output the register used in a memory
402 reference.
404 If memop && opnum == memop + 2, then we need ']' since
405 we just finished the register in a memory reference. We
406 also need a ',' before this operand.
408 Else we just need a comma.
410 We may need to output a trailing ']' if the last operand
411 in an instruction is the register for a memory address.
413 The exception (and there's always an exception) are the
414 "jmp" insn which needs square brackets around it's only
415 register argument, and the clr1/not1/set1/tst1 insns
416 which [...] around their second register argument. */
418 prefix = "";
419 if (operand->flags & V850_OPERAND_BANG)
421 prefix = "!";
423 else if (operand->flags & V850_OPERAND_PERCENT)
425 prefix = "%";
428 if (opnum == 1 && opnum == memop)
430 info->fprintf_func (info->stream, "%s[", prefix);
431 square = true;
433 else if ( (strcmp ("stc.w", op->name) == 0
434 || strcmp ("cache", op->name) == 0
435 || strcmp ("pref", op->name) == 0)
436 && opnum == 2 && opnum == memop)
438 info->fprintf_func (info->stream, ", [");
439 square = true;
441 else if ( (strcmp (op->name, "pushsp") == 0
442 || strcmp (op->name, "popsp") == 0
443 || strcmp (op->name, "dbpush" ) == 0)
444 && opnum == 2)
446 info->fprintf_func (info->stream, "-");
448 else if (opnum > 1
449 && (v850_operands[*(opindex_ptr - 1)].flags
450 & V850_OPERAND_DISP) != 0
451 && opnum == memop)
453 info->fprintf_func (info->stream, "%s[", prefix);
454 square = true;
456 else if (opnum == 2
457 && ( op->opcode == 0x00e407e0 /* clr1 */
458 || op->opcode == 0x00e207e0 /* not1 */
459 || op->opcode == 0x00e007e0 /* set1 */
460 || op->opcode == 0x00e607e0 /* tst1 */
463 info->fprintf_func (info->stream, ", %s[", prefix);
464 square = true;
466 else if (opnum > 1)
467 info->fprintf_func (info->stream, ", %s", prefix);
469 /* Extract the flags, ignoring ones which do not
470 effect disassembly output. */
471 flag = operand->flags & (V850_OPERAND_REG
472 | V850_REG_EVEN
473 | V850_OPERAND_EP
474 | V850_OPERAND_SRG
475 | V850E_OPERAND_REG_LIST
476 | V850_OPERAND_CC
477 | V850_OPERAND_VREG
478 | V850_OPERAND_CACHEOP
479 | V850_OPERAND_PREFOP
480 | V850_OPERAND_FLOAT_CC);
482 switch (flag)
484 case V850_OPERAND_REG:
485 info->fprintf_func (info->stream, "%s", get_v850_reg_name (value));
486 break;
487 case (V850_OPERAND_REG|V850_REG_EVEN):
488 info->fprintf_func (info->stream, "%s", get_v850_reg_name (value * 2));
489 break;
490 case V850_OPERAND_EP:
491 info->fprintf_func (info->stream, "ep");
492 break;
493 case V850_OPERAND_SRG:
494 info->fprintf_func (info->stream, "%s", get_v850_sreg_name (value));
495 break;
496 case V850E_OPERAND_REG_LIST:
498 static int list12_regs[32] = { 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
499 0, 0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
500 int *regs;
501 int i;
502 unsigned int mask = 0;
503 int pc = 0;
505 switch (operand->shift)
507 case 0xffe00001: regs = list12_regs; break;
508 default:
509 /* xgettext:c-format */
510 opcodes_error_handler (_("unknown operand shift: %x"),
511 operand->shift);
512 abort ();
515 for (i = 0; i < 32; i++)
517 if (value & (1u << i))
519 switch (regs[ i ])
521 default:
522 mask |= (1u << regs[ i ]);
523 break;
524 case 0:
525 /* xgettext:c-format */
526 opcodes_error_handler (_("unknown reg: %d"), i);
527 abort ();
528 break;
529 case -1:
530 pc = 1;
531 break;
536 info->fprintf_func (info->stream, "{");
538 if (mask || pc)
540 if (mask)
542 unsigned int bit;
543 int shown_one = 0;
545 for (bit = 0; bit < 32; bit++)
546 if (mask & (1u << bit))
548 unsigned int first = bit;
549 unsigned int last;
551 if (shown_one)
552 info->fprintf_func (info->stream, ", ");
553 else
554 shown_one = 1;
556 info->fprintf_func (info->stream, "%s", get_v850_reg_name (first));
558 for (bit++; bit < 32; bit++)
559 if ((mask & (1u << bit)) == 0)
560 break;
562 last = bit;
564 if (last > first + 1)
566 info->fprintf_func (info->stream, " - %s", get_v850_reg_name (last - 1));
571 if (pc)
572 info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
575 info->fprintf_func (info->stream, "}");
577 break;
579 case V850_OPERAND_CC:
580 info->fprintf_func (info->stream, "%s", get_v850_cc_name (value));
581 break;
583 case V850_OPERAND_FLOAT_CC:
584 info->fprintf_func (info->stream, "%s", get_v850_float_cc_name (value));
585 break;
587 case V850_OPERAND_CACHEOP:
589 int idx;
591 for (idx = 0; v850_cacheop_codes[idx] != -1; idx++)
593 if (value == v850_cacheop_codes[idx])
595 info->fprintf_func (info->stream, "%s",
596 get_v850_cacheop_name (idx));
597 goto MATCH_CACHEOP_CODE;
600 info->fprintf_func (info->stream, "%d", (int) value);
602 MATCH_CACHEOP_CODE:
603 break;
605 case V850_OPERAND_PREFOP:
607 int idx;
609 for (idx = 0; v850_prefop_codes[idx] != -1; idx++)
611 if (value == v850_prefop_codes[idx])
613 info->fprintf_func (info->stream, "%s",
614 get_v850_prefop_name (idx));
615 goto MATCH_PREFOP_CODE;
618 info->fprintf_func (info->stream, "%d", (int) value);
620 MATCH_PREFOP_CODE:
621 break;
623 case V850_OPERAND_VREG:
624 info->fprintf_func (info->stream, "%s", get_v850_vreg_name (value));
625 break;
627 default:
628 print_value (operand->flags, memaddr, info, value);
629 break;
632 if (square)
633 (*info->fprintf_func) (info->stream, "]");
636 /* All done. */
637 break;
639 next_opcode:
640 op++;
643 return match;
647 print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info)
649 int status, status2, match;
650 bfd_byte buffer[8];
651 int length = 0, code_length = 0;
652 unsigned long insn = 0, insn2 = 0;
653 int target_processor;
655 switch (info->mach)
657 case 0:
658 default:
659 target_processor = PROCESSOR_V850;
660 break;
662 case bfd_mach_v850e:
663 target_processor = PROCESSOR_V850E;
664 break;
666 case bfd_mach_v850e1:
667 target_processor = PROCESSOR_V850E;
668 break;
670 case bfd_mach_v850e2:
671 target_processor = PROCESSOR_V850E2;
672 break;
674 case bfd_mach_v850e2v3:
675 target_processor = PROCESSOR_V850E2V3;
676 break;
678 case bfd_mach_v850e3v5:
679 target_processor = PROCESSOR_V850E3V5;
680 break;
683 status = info->read_memory_func (memaddr, buffer, 2, info);
685 if (status)
687 info->memory_error_func (status, memaddr, info);
688 return -1;
691 insn = bfd_getl16 (buffer);
693 status2 = info->read_memory_func (memaddr+2, buffer, 2 , info);
695 if (!status2)
697 insn2 = bfd_getl16 (buffer);
698 /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */
701 /* Special case. */
702 if (length == 0
703 && ((target_processor & PROCESSOR_V850E2_UP) != 0))
705 if ((insn & 0xffff) == 0x02e0 /* jr 32bit */
706 && !status2 && (insn2 & 0x1) == 0)
708 length = 2;
709 code_length = 6;
711 else if ((insn & 0xffe0) == 0x02e0 /* jarl 32bit */
712 && !status2 && (insn2 & 0x1) == 0)
714 length = 2;
715 code_length = 6;
717 else if ((insn & 0xffe0) == 0x06e0 /* jmp 32bit */
718 && !status2 && (insn2 & 0x1) == 0)
720 length = 2;
721 code_length = 6;
725 if (length == 0
726 && ((target_processor & PROCESSOR_V850E3V5_UP) != 0))
728 if ( ((insn & 0xffe0) == 0x07a0 /* ld.dw 23bit (v850e3v5) */
729 && !status2 && (insn2 & 0x000f) == 0x0009)
730 || ((insn & 0xffe0) == 0x07a0 /* st.dw 23bit (v850e3v5) */
731 && !status2 && (insn2 & 0x000f) == 0x000f))
733 length = 4;
734 code_length = 6;
738 if (length == 0
739 && ((target_processor & PROCESSOR_V850E2V3_UP) != 0))
741 if (((insn & 0xffe0) == 0x0780 /* ld.b 23bit */
742 && !status2 && (insn2 & 0x000f) == 0x0005)
743 || ((insn & 0xffe0) == 0x07a0 /* ld.bu 23bit */
744 && !status2 && (insn2 & 0x000f) == 0x0005)
745 || ((insn & 0xffe0) == 0x0780 /* ld.h 23bit */
746 && !status2 && (insn2 & 0x000f) == 0x0007)
747 || ((insn & 0xffe0) == 0x07a0 /* ld.hu 23bit */
748 && !status2 && (insn2 & 0x000f) == 0x0007)
749 || ((insn & 0xffe0) == 0x0780 /* ld.w 23bit */
750 && !status2 && (insn2 & 0x000f) == 0x0009))
752 length = 4;
753 code_length = 6;
755 else if (((insn & 0xffe0) == 0x0780 /* st.b 23bit */
756 && !status2 && (insn2 & 0x000f) == 0x000d)
757 || ((insn & 0xffe0) == 0x07a0 /* st.h 23bit */
758 && !status2 && (insn2 & 0x000f) == 0x000d)
759 || ((insn & 0xffe0) == 0x0780 /* st.w 23bit */
760 && !status2 && (insn2 & 0x000f) == 0x000f))
762 length = 4;
763 code_length = 6;
767 if (length == 0
768 && target_processor != PROCESSOR_V850)
770 if ((insn & 0xffe0) == 0x0620) /* 32 bit MOV */
772 length = 2;
773 code_length = 6;
775 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16<<16 */
776 && !status2 && (insn2 & 0x001f) == 0x0013)
778 length = 4;
779 code_length = 6;
781 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16 */
782 && !status2 && (insn2 & 0x001f) == 0x000b)
784 length = 4;
785 code_length = 6;
787 else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm32 */
788 && !status2 && (insn2 & 0x001f) == 0x001b)
790 length = 4;
791 code_length = 8;
795 if (length == 4
796 || (length == 0
797 && (insn & 0x0600) == 0x0600))
799 /* This is a 4 byte insn. */
800 status = info->read_memory_func (memaddr, buffer, 4, info);
801 if (!status)
803 insn = bfd_getl32 (buffer);
805 if (!length)
806 length = code_length = 4;
810 if (code_length > length)
812 status = info->read_memory_func (memaddr + length, buffer, code_length - length, info);
813 if (status)
814 length = 0;
817 if (length == 0 && !status)
818 length = code_length = 2;
820 if (length == 2)
821 insn &= 0xffff;
823 /* when the last 2 bytes of section is 0xffff, length will be 0 and cause infinitive loop */
824 if (length == 0)
825 return -1;
827 match = disassemble (memaddr, info, length, insn);
829 if (!match)
831 int l = 0;
833 status = info->read_memory_func (memaddr, buffer, code_length, info);
835 while (l < code_length)
837 if (code_length - l == 2)
839 insn = bfd_getl16 (buffer + l) & 0xffff;
840 info->fprintf_func (info->stream, ".short\t0x%04lx", insn);
841 l += 2;
843 else
845 insn = bfd_getl32 (buffer + l);
846 info->fprintf_func (info->stream, ".long\t0x%08lx", insn);
847 l += 4;
852 return code_length;