]>
Commit | Line | Data |
---|---|---|
20135e4c | 1 | /* Disassemble moxie instructions. |
df7b86aa | 2 | Copyright 2009, 2012 |
20135e4c NC |
3 | Free Software Foundation, Inc. |
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 | ||
20135e4c | 22 | #include "sysdep.h" |
df7b86aa NC |
23 | #include <stdio.h> |
24 | ||
20135e4c NC |
25 | #define STATIC_TABLE |
26 | #define DEFINE_TABLE | |
27 | ||
28 | #include "opcode/moxie.h" | |
29 | #include "dis-asm.h" | |
30 | ||
31 | static fprintf_ftype fpr; | |
32 | static void *stream; | |
33 | ||
34 | /* Macros to extract operands from the instruction word. */ | |
35 | #define OP_A(i) ((i >> 4) & 0xf) | |
36 | #define OP_B(i) (i & 0xf) | |
f865a31d | 37 | #define INST2OFFSET(o) ((((signed short)((o & ((1<<10)-1))<<6))>>6)<<1) |
20135e4c NC |
38 | |
39 | static const char * reg_names[16] = | |
40 | { "$fp", "$sp", "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", | |
41 | "$r6", "$r7", "$r8", "$r9", "$r10", "$r11", "$r12", "$r13" }; | |
42 | ||
43 | int | |
44 | print_insn_moxie (bfd_vma addr, struct disassemble_info * info) | |
45 | { | |
46 | int length = 2; | |
47 | int status; | |
48 | stream = info->stream; | |
49 | const moxie_opc_info_t * opcode; | |
50 | bfd_byte buffer[4]; | |
51 | unsigned short iword; | |
52 | fpr = info->fprintf_func; | |
53 | ||
54 | if ((status = info->read_memory_func (addr, buffer, 2, info))) | |
55 | goto fail; | |
e202fa84 AG |
56 | |
57 | if (info->endian == BFD_ENDIAN_BIG) | |
58 | iword = bfd_getb16 (buffer); | |
59 | else | |
60 | iword = bfd_getl16 (buffer); | |
20135e4c NC |
61 | |
62 | /* Form 1 instructions have the high bit set to 0. */ | |
63 | if ((iword & (1<<15)) == 0) | |
64 | { | |
65 | /* Extract the Form 1 opcode. */ | |
66 | opcode = &moxie_form1_opc_info[iword >> 8]; | |
67 | switch (opcode->itype) | |
68 | { | |
69 | case MOXIE_F1_NARG: | |
70 | fpr (stream, "%s", opcode->name); | |
71 | break; | |
72 | case MOXIE_F1_A: | |
73 | fpr (stream, "%s\t%s", opcode->name, | |
74 | reg_names[OP_A(iword)]); | |
75 | break; | |
76 | case MOXIE_F1_AB: | |
77 | fpr (stream, "%s\t%s, %s", opcode->name, | |
78 | reg_names[OP_A(iword)], | |
79 | reg_names[OP_B(iword)]); | |
80 | break; | |
81 | case MOXIE_F1_A4: | |
82 | { | |
83 | unsigned imm; | |
84 | if ((status = info->read_memory_func (addr + 2, buffer, 4, info))) | |
85 | goto fail; | |
e202fa84 AG |
86 | if (info->endian == BFD_ENDIAN_BIG) |
87 | imm = bfd_getb32 (buffer); | |
88 | else | |
89 | imm = bfd_getl32 (buffer); | |
20135e4c NC |
90 | fpr (stream, "%s\t%s, 0x%x", opcode->name, |
91 | reg_names[OP_A(iword)], imm); | |
92 | length = 6; | |
93 | } | |
94 | break; | |
95 | case MOXIE_F1_4: | |
96 | { | |
97 | unsigned imm; | |
98 | if ((status = info->read_memory_func (addr + 2, buffer, 4, info))) | |
99 | goto fail; | |
e202fa84 AG |
100 | if (info->endian == BFD_ENDIAN_BIG) |
101 | imm = bfd_getb32 (buffer); | |
102 | else | |
103 | imm = bfd_getl32 (buffer); | |
20135e4c NC |
104 | fpr (stream, "%s\t0x%x", opcode->name, imm); |
105 | length = 6; | |
106 | } | |
107 | break; | |
0e7c7f11 AG |
108 | case MOXIE_F1_M: |
109 | { | |
110 | unsigned imm; | |
111 | if ((status = info->read_memory_func (addr + 2, buffer, 4, info))) | |
112 | goto fail; | |
e202fa84 AG |
113 | if (info->endian == BFD_ENDIAN_BIG) |
114 | imm = bfd_getb32 (buffer); | |
115 | else | |
116 | imm = bfd_getl32 (buffer); | |
0e7c7f11 AG |
117 | fpr (stream, "%s\t", opcode->name); |
118 | info->print_address_func ((bfd_vma) imm, info); | |
119 | length = 6; | |
120 | } | |
121 | break; | |
20135e4c NC |
122 | case MOXIE_F1_AiB: |
123 | fpr (stream, "%s\t(%s), %s", opcode->name, | |
124 | reg_names[OP_A(iword)], reg_names[OP_B(iword)]); | |
125 | break; | |
126 | case MOXIE_F1_ABi: | |
127 | fpr (stream, "%s\t%s, (%s)", opcode->name, | |
128 | reg_names[OP_A(iword)], reg_names[OP_B(iword)]); | |
129 | break; | |
130 | case MOXIE_F1_4A: | |
131 | { | |
132 | unsigned imm; | |
133 | if ((status = info->read_memory_func (addr + 2, buffer, 4, info))) | |
134 | goto fail; | |
e202fa84 AG |
135 | if (info->endian == BFD_ENDIAN_BIG) |
136 | imm = bfd_getb32 (buffer); | |
137 | else | |
138 | imm = bfd_getl32 (buffer); | |
20135e4c NC |
139 | fpr (stream, "%s\t0x%x, %s", |
140 | opcode->name, imm, reg_names[OP_A(iword)]); | |
141 | length = 6; | |
142 | } | |
143 | break; | |
144 | case MOXIE_F1_AiB4: | |
145 | { | |
146 | unsigned imm; | |
147 | if ((status = info->read_memory_func (addr+2, buffer, 4, info))) | |
148 | goto fail; | |
e202fa84 AG |
149 | if (info->endian == BFD_ENDIAN_BIG) |
150 | imm = bfd_getb32 (buffer); | |
151 | else | |
152 | imm = bfd_getl32 (buffer); | |
20135e4c NC |
153 | fpr (stream, "%s\t0x%x(%s), %s", opcode->name, |
154 | imm, | |
155 | reg_names[OP_A(iword)], | |
156 | reg_names[OP_B(iword)]); | |
157 | length = 6; | |
158 | } | |
159 | break; | |
160 | case MOXIE_F1_ABi4: | |
161 | { | |
162 | unsigned imm; | |
163 | if ((status = info->read_memory_func (addr+2, buffer, 4, info))) | |
164 | goto fail; | |
e202fa84 AG |
165 | if (info->endian == BFD_ENDIAN_BIG) |
166 | imm = bfd_getb32 (buffer); | |
167 | else | |
168 | imm = bfd_getl32 (buffer); | |
20135e4c NC |
169 | fpr (stream, "%s\t%s, 0x%x(%s)", |
170 | opcode->name, | |
171 | reg_names[OP_A(iword)], | |
172 | imm, | |
173 | reg_names[OP_B(iword)]); | |
174 | length = 6; | |
175 | } | |
176 | break; | |
1415a2a7 AG |
177 | case MOXIE_BAD: |
178 | fpr (stream, "bad"); | |
179 | break; | |
20135e4c | 180 | default: |
1415a2a7 | 181 | abort(); |
20135e4c NC |
182 | } |
183 | } | |
184 | else if ((iword & (1<<14)) == 0) | |
185 | { | |
186 | /* Extract the Form 2 opcode. */ | |
187 | opcode = &moxie_form2_opc_info[(iword >> 12) & 3]; | |
188 | switch (opcode->itype) | |
189 | { | |
190 | case MOXIE_F2_A8V: | |
191 | fpr (stream, "%s\t%s, 0x%x", | |
192 | opcode->name, | |
193 | reg_names[(iword >> 8) & 0xf], | |
194 | iword & ((1 << 8) - 1)); | |
195 | break; | |
196 | case MOXIE_F2_NARG: | |
197 | fpr (stream, "%s", opcode->name); | |
198 | break; | |
1415a2a7 AG |
199 | case MOXIE_BAD: |
200 | fpr (stream, "bad"); | |
201 | break; | |
20135e4c NC |
202 | default: |
203 | abort(); | |
204 | } | |
205 | } | |
206 | else | |
207 | { | |
208 | /* Extract the Form 3 opcode. */ | |
f865a31d | 209 | opcode = &moxie_form3_opc_info[(iword >> 10) & 15]; |
20135e4c NC |
210 | switch (opcode->itype) |
211 | { | |
f865a31d AG |
212 | case MOXIE_F3_PCREL: |
213 | fpr (stream, "%s\t", opcode->name); | |
1f9b75dd | 214 | info->print_address_func ((bfd_vma) (addr + INST2OFFSET(iword) + 2), |
f865a31d | 215 | info); |
20135e4c | 216 | break; |
1415a2a7 AG |
217 | case MOXIE_BAD: |
218 | fpr (stream, "bad"); | |
219 | break; | |
20135e4c NC |
220 | default: |
221 | abort(); | |
222 | } | |
223 | } | |
224 | ||
225 | return length; | |
226 | ||
227 | fail: | |
228 | info->memory_error_func (status, addr, info); | |
229 | return -1; | |
230 | } |