Commit | Line | Data |
---|---|---|
529418dd JL |
1 | /* Disassemble V850 instructions. |
2 | Copyright (C) 1996 Free Software Foundation, Inc. | |
3 | ||
4 | This program is free software; you can redistribute it and/or modify | |
5 | it under the terms of the GNU General Public License as published by | |
6 | the Free Software Foundation; either version 2 of the License, or | |
7 | (at your option) any later version. | |
8 | ||
9 | This program is distributed in the hope that it will be useful, | |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | GNU General Public License for more details. | |
13 | ||
14 | You should have received a copy of the GNU General Public License | |
15 | along with this program; if not, write to the Free Software | |
16 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |
17 | ||
18 | ||
19 | #include <stdio.h> | |
20 | ||
21 | #include "ansidecl.h" | |
22 | #include "opcode/v850.h" | |
23 | #include "dis-asm.h" | |
24 | ||
502535cf JL |
25 | static const char *const v850_reg_names[] = |
26 | { "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7", | |
27 | "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", | |
28 | "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", | |
29 | "r24", "r25", "r26", "r27", "r28", "r29", "ep", "r31" }; | |
30 | ||
31 | static const char *const v850_sreg_names[] = | |
32 | { "eipc", "eipsw", "fepc", "fepsw", "ecr", "psw", "sr6", "sr7", | |
33 | "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15", | |
34 | "sr16", "sr17", "sr18", "sr19", "sr20", "sr21", "sr22", "sr23", | |
35 | "sr24", "sr25", "sr26", "sr27", "sr28", "sr29", "sr30", "sr31" }; | |
36 | ||
37 | static const char *const v850_cc_names[] = | |
38 | { "v", "c/l", "z", "nh", "s/n", "t", "lt", "le", | |
a5f2a4e5 | 39 | "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt" }; |
502535cf | 40 | |
529418dd JL |
41 | int |
42 | print_insn_v850 (memaddr, info) | |
43 | bfd_vma memaddr; | |
44 | struct disassemble_info *info; | |
45 | { | |
46 | int status; | |
47 | bfd_byte buffer[4]; | |
48 | unsigned long insn; | |
49 | ||
e05cae19 JL |
50 | /* First figure out how big the opcode is. */ |
51 | status = (*info->read_memory_func) (memaddr, buffer, 2, info); | |
529418dd JL |
52 | if (status != 0) |
53 | { | |
54 | (*info->memory_error_func) (status, memaddr, info); | |
55 | return -1; | |
56 | } | |
e05cae19 JL |
57 | insn = bfd_getl16 (buffer); |
58 | ||
59 | /* If this is a 4 byte insn, read 4 bytes of stuff. */ | |
60 | if ((insn & 0x0600) == 0x0600) | |
61 | { | |
62 | status = (*info->read_memory_func) (memaddr, buffer, 2, info); | |
63 | if (status != 0) | |
64 | { | |
65 | (*info->memory_error_func) (status, memaddr, info); | |
66 | return -1; | |
67 | } | |
68 | insn = bfd_getl32 (buffer); | |
69 | } | |
529418dd JL |
70 | |
71 | disassemble (insn, info); | |
e05cae19 JL |
72 | |
73 | /* Make sure we tell our caller how many bytes we consumed. */ | |
529418dd JL |
74 | if ((insn & 0x0600) == 0x0600) |
75 | return 4; | |
76 | else | |
77 | return 2; | |
78 | } | |
79 | ||
80 | disassemble (insn, info) | |
81 | unsigned long insn; | |
82 | struct disassemble_info *info; | |
83 | { | |
84 | struct v850_opcode *op = (struct v850_opcode *)v850_opcodes; | |
502535cf | 85 | const struct v850_operand *operand; |
529418dd JL |
86 | int match = 0; |
87 | /* If this is a two byte insn, then mask off the high bits. */ | |
88 | if ((insn & 0x0600) != 0x0600) | |
89 | insn &= 0xffff; | |
90 | ||
91 | /* Find the opcode. */ | |
92 | while (op->name) | |
93 | { | |
94 | if ((op->mask & insn) == op->opcode) | |
95 | { | |
502535cf JL |
96 | const unsigned char *opindex_ptr; |
97 | ||
529418dd JL |
98 | match = 1; |
99 | (*info->fprintf_func) (info->stream, "%s\t", op->name); | |
502535cf JL |
100 | |
101 | /* Now print the operands. */ | |
102 | for (opindex_ptr = op->operands; *opindex_ptr != 0; opindex_ptr++) | |
103 | { | |
104 | unsigned long value; | |
105 | ||
106 | operand = &v850_operands[*opindex_ptr]; | |
107 | ||
108 | if (operand->extract) | |
109 | value = (operand->extract) (insn, 0); | |
110 | else | |
111 | value = (insn >> operand->shift) & ((1 << operand->bits) - 1); | |
112 | ||
113 | if ((operand->flags & V850_OPERAND_SIGNED) != 0) | |
114 | value = ((signed long)(value << (32 - operand->bits)) | |
115 | >> (32 - operand->bits)); | |
116 | if ((operand->flags & V850_OPERAND_REG) != 0) | |
117 | (*info->fprintf_func) (info->stream, "%s", | |
118 | v850_reg_names[value]); | |
119 | else if ((operand->flags & V850_OPERAND_SRG) != 0) | |
120 | (*info->fprintf_func) (info->stream, "%s", | |
121 | v850_sreg_names[value]); | |
122 | else if ((operand->flags & V850_OPERAND_CC) != 0) | |
123 | (*info->fprintf_func) (info->stream, "%s", | |
124 | v850_cc_names[value]); | |
125 | else if ((operand->flags & V850_OPERAND_EP) != 0) | |
126 | (*info->fprintf_func) (info->stream, "ep"); | |
127 | else | |
128 | (*info->fprintf_func) (info->stream, "%d", value); | |
129 | } | |
130 | ||
131 | /* All done. */ | |
529418dd JL |
132 | break; |
133 | } | |
134 | op++; | |
135 | } | |
136 | ||
137 | if (!match) | |
138 | { | |
139 | if ((insn & 0x0600) != 0x0600) | |
140 | (*info->fprintf_func) (info->stream, ".short\t0x%04x", insn); | |
141 | else | |
142 | (*info->fprintf_func) (info->stream, ".long\t0x%08x", insn); | |
143 | } | |
144 | } |