1 /* Disassemble V850 instructions.
2 Copyright (C) 1996-2019 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)
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. */
25 #include "opcode/v850.h"
26 #include "disassemble.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
[] =
40 print_value (int flags
,
42 struct disassemble_info
*info
,
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
);
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
);
71 if (flags
& V850_OPERAND_SIGNED
)
73 info
->fprintf_func (info
->stream
, "%ld", value
);
77 info
->fprintf_func (info
->stream
, "%lu", value
);
83 get_operand_value (const struct v850_operand
*operand
,
87 struct disassemble_info
* info
,
94 if ((operand
->flags
& V850E_IMMEDIATE16
)
95 || (operand
->flags
& V850E_IMMEDIATE16HI
))
97 int status
= info
->read_memory_func (memaddr
+ bytes_read
, buffer
, 2, info
);
101 value
= bfd_getl16 (buffer
);
103 if (operand
->flags
& V850E_IMMEDIATE16HI
)
105 else if (value
& 0x8000)
106 value
|= (-1UL << 16);
112 info
->memory_error_func (status
, memaddr
+ bytes_read
, info
);
117 if (operand
->flags
& V850E_IMMEDIATE23
)
119 int status
= info
->read_memory_func (memaddr
+ 2, buffer
, 4, info
);
123 value
= bfd_getl32 (buffer
);
125 value
= (operand
->extract
) (value
, invalid
);
131 info
->memory_error_func (status
, memaddr
+ bytes_read
, info
);
136 if (operand
->flags
& V850E_IMMEDIATE32
)
138 int status
= info
->read_memory_func (memaddr
+ bytes_read
, buffer
, 4, info
);
143 value
= bfd_getl32 (buffer
);
149 info
->memory_error_func (status
, memaddr
+ bytes_read
, info
);
154 if (operand
->extract
)
155 value
= (operand
->extract
) (insn
, invalid
);
158 if (operand
->bits
== -1)
159 value
= (insn
& operand
->shift
);
161 value
= (insn
>> operand
->shift
) & ((1 << operand
->bits
) - 1);
163 if (operand
->flags
& V850_OPERAND_SIGNED
)
164 value
= ((long)(value
<< (sizeof (long)*8 - operand
->bits
))
165 >> (sizeof (long)*8 - operand
->bits
));
172 get_v850_sreg_name (unsigned int reg
)
174 static const char *const v850_sreg_names
[] =
176 "eipc/vip/mpm", "eipsw/mpc", "fepc/tid", "fepsw/ppa", "ecr/vmecr", "psw/vmtid",
177 "sr6/fpsr/vmadr/dcc", "sr7/fpepc/dc0",
178 "sr8/fpst/vpecr/dcv1", "sr9/fpcc/vptid", "sr10/fpcfg/vpadr/spal", "sr11/spau",
179 "sr12/vdecr/ipa0l", "eiic/vdtid/ipa0u", "feic/ipa1l", "dbic/ipa1u",
180 "ctpc/ipa2l", "ctpsw/ipa2u", "dbpc/ipa3l", "dbpsw/ipa3u", "ctbp/dpa0l",
181 "dir/dpa0u", "bpc/dpa0u", "asid/dpa1l",
182 "bpav/dpa1u", "bpam/dpa2l", "bpdv/dpa2u", "bpdm/dpa3l", "eiwr/dpa3u",
183 "fewr", "dbwr", "bsel"
186 if (reg
< ARRAY_SIZE (v850_sreg_names
))
187 return v850_sreg_names
[reg
];
188 return _("<invalid s-reg number>");
192 get_v850_reg_name (unsigned int reg
)
194 static const char *const v850_reg_names
[] =
196 "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7",
197 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
198 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
199 "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp"
202 if (reg
< ARRAY_SIZE (v850_reg_names
))
203 return v850_reg_names
[reg
];
204 return _("<invalid reg number>");
208 get_v850_vreg_name (unsigned int reg
)
210 static const char *const v850_vreg_names
[] =
212 "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7", "vr8", "vr9",
213 "vr10", "vr11", "vr12", "vr13", "vr14", "vr15", "vr16", "vr17", "vr18",
214 "vr19", "vr20", "vr21", "vr22", "vr23", "vr24", "vr25", "vr26", "vr27",
215 "vr28", "vr29", "vr30", "vr31"
218 if (reg
< ARRAY_SIZE (v850_vreg_names
))
219 return v850_vreg_names
[reg
];
220 return _("<invalid v-reg number>");
224 get_v850_cc_name (unsigned int reg
)
226 static const char *const v850_cc_names
[] =
228 "v", "c/l", "z", "nh", "s/n", "t", "lt", "le",
229 "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt"
232 if (reg
< ARRAY_SIZE (v850_cc_names
))
233 return v850_cc_names
[reg
];
234 return _("<invalid CC-reg number>");
238 get_v850_float_cc_name (unsigned int reg
)
240 static const char *const v850_float_cc_names
[] =
242 "f/t", "un/or", "eq/neq", "ueq/ogl", "olt/uge", "ult/oge", "ole/ugt", "ule/ogt",
243 "sf/st", "ngle/gle", "seq/sne", "ngl/gl", "lt/nlt", "nge/ge", "le/nle", "ngt/gt"
246 if (reg
< ARRAY_SIZE (v850_float_cc_names
))
247 return v850_float_cc_names
[reg
];
248 return _("<invalid float-CC-reg number>");
252 get_v850_cacheop_name (unsigned int reg
)
254 static const char *const v850_cacheop_names
[] =
256 "chbii", "cibii", "cfali", "cisti", "cildi", "chbid", "chbiwbd",
257 "chbwbd", "cibid", "cibiwbd", "cibwbd", "cfald", "cistd", "cildd"
260 if (reg
< ARRAY_SIZE (v850_cacheop_names
))
261 return v850_cacheop_names
[reg
];
262 return _("<invalid cacheop number>");
266 get_v850_prefop_name (unsigned int reg
)
268 static const char *const v850_prefop_names
[] =
269 { "prefi", "prefd" };
271 if (reg
< ARRAY_SIZE (v850_prefop_names
))
272 return v850_prefop_names
[reg
];
273 return _("<invalid prefop number>");
277 disassemble (bfd_vma memaddr
,
278 struct disassemble_info
*info
,
282 struct v850_opcode
*op
= (struct v850_opcode
*) v850_opcodes
;
283 const struct v850_operand
*operand
;
285 int target_processor
;
291 target_processor
= PROCESSOR_V850
;
295 target_processor
= PROCESSOR_V850E
;
298 case bfd_mach_v850e1
:
299 target_processor
= PROCESSOR_V850E
;
302 case bfd_mach_v850e2
:
303 target_processor
= PROCESSOR_V850E2
;
306 case bfd_mach_v850e2v3
:
307 target_processor
= PROCESSOR_V850E2V3
;
310 case bfd_mach_v850e3v5
:
311 target_processor
= PROCESSOR_V850E3V5
;
315 /* If this is a two byte insn, then mask off the high bits. */
319 /* Find the opcode. */
322 if ((op
->mask
& insn
) == op
->opcode
323 && (op
->processors
& target_processor
)
324 && !(op
->processors
& PROCESSOR_OPTION_ALIAS
))
326 /* Code check start. */
327 const unsigned char *opindex_ptr
;
331 for (opindex_ptr
= op
->operands
, opnum
= 1;
333 opindex_ptr
++, opnum
++)
338 operand
= &v850_operands
[*opindex_ptr
];
340 value
= get_operand_value (operand
, insn
, bytes_read
, memaddr
,
346 if ((operand
->flags
& V850_NOT_R0
) && value
== 0 && (op
->memop
) <=2)
349 if ((operand
->flags
& V850_NOT_SA
) && value
== 0xd)
352 if ((operand
->flags
& V850_NOT_IMM0
) && value
== 0)
356 /* Code check end. */
359 (*info
->fprintf_func
) (info
->stream
, "%s\t", op
->name
);
361 fprintf (stderr
, "match: insn: %lx, mask: %lx, opcode: %lx, name: %s\n",
362 insn
, op
->mask
, op
->opcode
, op
->name
);
366 /* Now print the operands.
368 MEMOP is the operand number at which a memory
369 address specification starts, or zero if this
370 instruction has no memory addresses.
372 A memory address is always two arguments.
374 This information allows us to determine when to
375 insert commas into the output stream as well as
376 when to insert disp[reg] expressions onto the
379 for (opindex_ptr
= op
->operands
, opnum
= 1;
381 opindex_ptr
++, opnum
++)
383 bfd_boolean square
= FALSE
;
388 operand
= &v850_operands
[*opindex_ptr
];
390 value
= get_operand_value (operand
, insn
, bytes_read
, memaddr
,
393 /* The first operand is always output without any
396 For the following arguments:
398 If memop && opnum == memop + 1, then we need '[' since
399 we're about to output the register used in a memory
402 If memop && opnum == memop + 2, then we need ']' since
403 we just finished the register in a memory reference. We
404 also need a ',' before this operand.
406 Else we just need a comma.
408 We may need to output a trailing ']' if the last operand
409 in an instruction is the register for a memory address.
411 The exception (and there's always an exception) are the
412 "jmp" insn which needs square brackets around it's only
413 register argument, and the clr1/not1/set1/tst1 insns
414 which [...] around their second register argument. */
417 if (operand
->flags
& V850_OPERAND_BANG
)
421 else if (operand
->flags
& V850_OPERAND_PERCENT
)
426 if (opnum
== 1 && opnum
== memop
)
428 info
->fprintf_func (info
->stream
, "%s[", prefix
);
431 else if ( (strcmp ("stc.w", op
->name
) == 0
432 || strcmp ("cache", op
->name
) == 0
433 || strcmp ("pref", op
->name
) == 0)
434 && opnum
== 2 && opnum
== memop
)
436 info
->fprintf_func (info
->stream
, ", [");
439 else if ( (strcmp (op
->name
, "pushsp") == 0
440 || strcmp (op
->name
, "popsp") == 0
441 || strcmp (op
->name
, "dbpush" ) == 0)
444 info
->fprintf_func (info
->stream
, "-");
447 && (v850_operands
[*(opindex_ptr
- 1)].flags
448 & V850_OPERAND_DISP
) != 0
451 info
->fprintf_func (info
->stream
, "%s[", prefix
);
455 && ( op
->opcode
== 0x00e407e0 /* clr1 */
456 || op
->opcode
== 0x00e207e0 /* not1 */
457 || op
->opcode
== 0x00e007e0 /* set1 */
458 || op
->opcode
== 0x00e607e0 /* tst1 */
461 info
->fprintf_func (info
->stream
, ", %s[", prefix
);
465 info
->fprintf_func (info
->stream
, ", %s", prefix
);
467 /* Extract the flags, ignoring ones which do not
468 effect disassembly output. */
469 flag
= operand
->flags
& (V850_OPERAND_REG
473 | V850E_OPERAND_REG_LIST
476 | V850_OPERAND_CACHEOP
477 | V850_OPERAND_PREFOP
478 | V850_OPERAND_FLOAT_CC
);
482 case V850_OPERAND_REG
:
483 info
->fprintf_func (info
->stream
, "%s", get_v850_reg_name (value
));
485 case (V850_OPERAND_REG
|V850_REG_EVEN
):
486 info
->fprintf_func (info
->stream
, "%s", get_v850_reg_name (value
* 2));
488 case V850_OPERAND_EP
:
489 info
->fprintf_func (info
->stream
, "ep");
491 case V850_OPERAND_SRG
:
492 info
->fprintf_func (info
->stream
, "%s", get_v850_sreg_name (value
));
494 case V850E_OPERAND_REG_LIST
:
496 static int list12_regs
[32] = { 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
497 0, 0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
500 unsigned long int mask
= 0;
503 switch (operand
->shift
)
505 case 0xffe00001: regs
= list12_regs
; break;
507 /* xgettext:c-format */
508 opcodes_error_handler (_("unknown operand shift: %x"),
513 for (i
= 0; i
< 32; i
++)
515 if (value
& (1 << i
))
520 mask
|= (1 << regs
[ i
]);
523 /* xgettext:c-format */
524 opcodes_error_handler (_("unknown reg: %d"), i
);
534 info
->fprintf_func (info
->stream
, "{");
543 for (bit
= 0; bit
< 32; bit
++)
544 if (mask
& (1 << bit
))
546 unsigned long int first
= bit
;
547 unsigned long int last
;
550 info
->fprintf_func (info
->stream
, ", ");
554 info
->fprintf_func (info
->stream
, "%s", get_v850_reg_name (first
));
556 for (bit
++; bit
< 32; bit
++)
557 if ((mask
& (1 << bit
)) == 0)
562 if (last
> first
+ 1)
564 info
->fprintf_func (info
->stream
, " - %s", get_v850_reg_name (last
- 1));
570 info
->fprintf_func (info
->stream
, "%sPC", mask
? ", " : "");
573 info
->fprintf_func (info
->stream
, "}");
577 case V850_OPERAND_CC
:
578 info
->fprintf_func (info
->stream
, "%s", get_v850_cc_name (value
));
581 case V850_OPERAND_FLOAT_CC
:
582 info
->fprintf_func (info
->stream
, "%s", get_v850_float_cc_name (value
));
585 case V850_OPERAND_CACHEOP
:
589 for (idx
= 0; v850_cacheop_codes
[idx
] != -1; idx
++)
591 if (value
== v850_cacheop_codes
[idx
])
593 info
->fprintf_func (info
->stream
, "%s",
594 get_v850_cacheop_name (idx
));
595 goto MATCH_CACHEOP_CODE
;
598 info
->fprintf_func (info
->stream
, "%d", (int) value
);
603 case V850_OPERAND_PREFOP
:
607 for (idx
= 0; v850_prefop_codes
[idx
] != -1; idx
++)
609 if (value
== v850_prefop_codes
[idx
])
611 info
->fprintf_func (info
->stream
, "%s",
612 get_v850_prefop_name (idx
));
613 goto MATCH_PREFOP_CODE
;
616 info
->fprintf_func (info
->stream
, "%d", (int) value
);
621 case V850_OPERAND_VREG
:
622 info
->fprintf_func (info
->stream
, "%s", get_v850_vreg_name (value
));
626 print_value (operand
->flags
, memaddr
, info
, value
);
631 (*info
->fprintf_func
) (info
->stream
, "]");
645 print_insn_v850 (bfd_vma memaddr
, struct disassemble_info
* info
)
647 int status
, status2
, match
;
649 int length
= 0, code_length
= 0;
650 unsigned long insn
= 0, insn2
= 0;
651 int target_processor
;
657 target_processor
= PROCESSOR_V850
;
661 target_processor
= PROCESSOR_V850E
;
664 case bfd_mach_v850e1
:
665 target_processor
= PROCESSOR_V850E
;
668 case bfd_mach_v850e2
:
669 target_processor
= PROCESSOR_V850E2
;
672 case bfd_mach_v850e2v3
:
673 target_processor
= PROCESSOR_V850E2V3
;
676 case bfd_mach_v850e3v5
:
677 target_processor
= PROCESSOR_V850E3V5
;
681 status
= info
->read_memory_func (memaddr
, buffer
, 2, info
);
685 info
->memory_error_func (status
, memaddr
, info
);
689 insn
= bfd_getl16 (buffer
);
691 status2
= info
->read_memory_func (memaddr
+2, buffer
, 2 , info
);
695 insn2
= bfd_getl16 (buffer
);
696 /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */
701 && ((target_processor
& PROCESSOR_V850E2_UP
) != 0))
703 if ((insn
& 0xffff) == 0x02e0 /* jr 32bit */
704 && !status2
&& (insn2
& 0x1) == 0)
709 else if ((insn
& 0xffe0) == 0x02e0 /* jarl 32bit */
710 && !status2
&& (insn2
& 0x1) == 0)
715 else if ((insn
& 0xffe0) == 0x06e0 /* jmp 32bit */
716 && !status2
&& (insn2
& 0x1) == 0)
724 && ((target_processor
& PROCESSOR_V850E3V5_UP
) != 0))
726 if ( ((insn
& 0xffe0) == 0x07a0 /* ld.dw 23bit (v850e3v5) */
727 && !status2
&& (insn2
& 0x000f) == 0x0009)
728 || ((insn
& 0xffe0) == 0x07a0 /* st.dw 23bit (v850e3v5) */
729 && !status2
&& (insn2
& 0x000f) == 0x000f))
737 && ((target_processor
& PROCESSOR_V850E2V3_UP
) != 0))
739 if (((insn
& 0xffe0) == 0x0780 /* ld.b 23bit */
740 && !status2
&& (insn2
& 0x000f) == 0x0005)
741 || ((insn
& 0xffe0) == 0x07a0 /* ld.bu 23bit */
742 && !status2
&& (insn2
& 0x000f) == 0x0005)
743 || ((insn
& 0xffe0) == 0x0780 /* ld.h 23bit */
744 && !status2
&& (insn2
& 0x000f) == 0x0007)
745 || ((insn
& 0xffe0) == 0x07a0 /* ld.hu 23bit */
746 && !status2
&& (insn2
& 0x000f) == 0x0007)
747 || ((insn
& 0xffe0) == 0x0780 /* ld.w 23bit */
748 && !status2
&& (insn2
& 0x000f) == 0x0009))
753 else if (((insn
& 0xffe0) == 0x0780 /* st.b 23bit */
754 && !status2
&& (insn2
& 0x000f) == 0x000d)
755 || ((insn
& 0xffe0) == 0x07a0 /* st.h 23bit */
756 && !status2
&& (insn2
& 0x000f) == 0x000d)
757 || ((insn
& 0xffe0) == 0x0780 /* st.w 23bit */
758 && !status2
&& (insn2
& 0x000f) == 0x000f))
766 && target_processor
!= PROCESSOR_V850
)
768 if ((insn
& 0xffe0) == 0x0620) /* 32 bit MOV */
773 else if ((insn
& 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16<<16 */
774 && !status2
&& (insn2
& 0x001f) == 0x0013)
779 else if ((insn
& 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16 */
780 && !status2
&& (insn2
& 0x001f) == 0x000b)
785 else if ((insn
& 0xffc0) == 0x0780 /* prepare {list}, imm5, imm32 */
786 && !status2
&& (insn2
& 0x001f) == 0x001b)
795 && (insn
& 0x0600) == 0x0600))
797 /* This is a 4 byte insn. */
798 status
= info
->read_memory_func (memaddr
, buffer
, 4, info
);
801 insn
= bfd_getl32 (buffer
);
804 length
= code_length
= 4;
808 if (code_length
> length
)
810 status
= info
->read_memory_func (memaddr
+ length
, buffer
, code_length
- length
, info
);
815 if (length
== 0 && !status
)
816 length
= code_length
= 2;
821 /* when the last 2 bytes of section is 0xffff, length will be 0 and cause infinitive loop */
825 match
= disassemble (memaddr
, info
, length
, insn
);
831 status
= info
->read_memory_func (memaddr
, buffer
, code_length
, info
);
833 while (l
< code_length
)
835 if (code_length
- l
== 2)
837 insn
= bfd_getl16 (buffer
+ l
) & 0xffff;
838 info
->fprintf_func (info
->stream
, ".short\t0x%04lx", insn
);
843 insn
= bfd_getl32 (buffer
+ l
);
844 info
->fprintf_func (info
->stream
, ".long\t0x%08lx", insn
);
This page took 0.060968 seconds and 4 git commands to generate.