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