* mn10300-dis.c: Start working on disassembler support.
[deliverable/binutils-gdb.git] / opcodes / mn10300-dis.c
CommitLineData
ae1b99e4 1/* Disassemble MN10300 instructions.
e7c50cef
JL
2 Copyright (C) 1996 Free Software Foundation, Inc.
3
4This program is free software; you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation; either version 2 of the License, or
7(at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17
18
19#include <stdio.h>
20
21#include "ansidecl.h"
ae1b99e4 22#include "opcode/mn10300.h"
e7c50cef
JL
23#include "dis-asm.h"
24
4aa92185
JL
25static void disassemble PARAMS ((bfd_vma, struct disassemble_info *,
26 unsigned long insn, unsigned long,
27 unsigned int));
28
29static const char *const mn10300_reg_names[] =
30{ "d0", "d1", "d2", "d3", "a0", "a1", "a2", "a3", };
e7c50cef
JL
31
32int
ae1b99e4 33print_insn_mn10300 (memaddr, info)
e7c50cef
JL
34 bfd_vma memaddr;
35 struct disassemble_info *info;
36{
4aa92185
JL
37 int status;
38 bfd_byte buffer[4];
39 unsigned long insn;
40 unsigned long extension;
41 unsigned int consume;
42
43 /* First figure out how big the opcode is. */
44 status = (*info->read_memory_func) (memaddr, buffer, 1, info);
45 if (status != 0)
46 {
47 (*info->memory_error_func) (status, memaddr, info);
48 return -1;
49 }
50 insn = *(unsigned char *) buffer;
51
52 /* These are one byte insns XXX imm8 versions of mov, cmp. */
53 if ((insn & 0xf3) == 0x00
54 || (insn & 0xf0) == 0x10
55 || (insn & 0xfc) == 0x3c
56 || (insn & 0xf3) == 0x41
57 || (insn & 0xf3) == 0x40
58 || (insn & 0xfc) == 0x50
59 || (insn & 0xfc) == 0x54
60 || (insn & 0xf0) == 0x60
61 || (insn & 0xf0) == 0x70
62 || ((insn & 0xf0) == 0x80
63 && (insn & 0x0c) >> 2 != (insn & 0x03))
64 || ((insn & 0xf0) == 0x90
65 && (insn & 0x0c) >> 2 != (insn & 0x03))
66 || ((insn & 0xf0) == 0xa0
67 && (insn & 0x0c) >> 2 != (insn & 0x03))
68 || ((insn & 0xf0) == 0xb0
69 && (insn & 0x0c) >> 2 != (insn & 0x03))
70 || (insn & 0xff) == 0xcb
71 || (insn & 0xfc) == 0xd0
72 || (insn & 0xfc) == 0xd4
73 || (insn & 0xfc) == 0xd8
74 || (insn & 0xf0) == 0xe0)
75 {
76 extension = 0;
77 consume = 1;
78 }
79
80 /* These are two byte insns. */
81 else if ((insn & 0xf0) == 0x80
82 || (insn & 0xf0) == 0x90
83 || (insn & 0xf0) == 0xa0
84 || (insn & 0xf0) == 0xb0
85 || (insn & 0xfc) == 0x20
86 || (insn & 0xfc) == 0x28
87 || (insn & 0xf3) == 0x43
88 || (insn & 0xf3) == 0x42
89 || (insn & 0xfc) == 0x58
90 || (insn & 0xfc) == 0x5c
91 || ((insn & 0xf0) == 0xc0
92 && (insn & 0xff) != 0xcb
93 && (insn & 0xff) != 0xcc
94 && (insn & 0xff) != 0xcd)
95 || (insn & 0xff) == 0xf0
96 || (insn & 0xff) == 0xf1
97 || (insn & 0xff) == 0xf2
98 || (insn & 0xff) == 0xf3
99 || (insn & 0xff) == 0xf4
100 || (insn & 0xff) == 0xf5
101 || (insn & 0xff) == 0xf6)
102 {
103 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
104 if (status != 0)
105 {
106 (*info->memory_error_func) (status, memaddr, info);
107 return -1;
108 }
109 insn = bfd_getb16 (buffer);
110 extension = 0;
111 consume = 2;
112 }
113
114 /* These are three byte insns. */
115 else if ((insn & 0xff) == 0xf8
116 || (insn & 0xff) == 0xcc
117 || (insn & 0xff) == 0xf9
118 || (insn & 0xf3) == 0x01
119 || (insn & 0xf3) == 0x02
120 || (insn & 0xf3) == 0x03
121 || (insn & 0xfc) == 0x24
122 || (insn & 0xfc) == 0x2c
123 || (insn & 0xfc) == 0x30
124 || (insn & 0xfc) == 0x34
125 || (insn & 0xfc) == 0x38
126 || (insn & 0xff) == 0xde
127 || (insn & 0xff) == 0xdf
128 || (insn & 0xff) == 0xcc)
129 {
130 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
131 if (status != 0)
132 {
133 (*info->memory_error_func) (status, memaddr, info);
134 return -1;
135 }
136 insn = bfd_getb16 (buffer);
137 insn <<= 8;
138 insn |= *(unsigned char *)buffer + 2;
139 extension = 0;
140 consume = 3;
141 }
142
143 /* These are four byte insns. */
144 else if ((insn & 0xff) == 0xfa
145 || (insn & 0xff) == 0xfb)
146 {
147 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
148 if (status != 0)
149 {
150 (*info->memory_error_func) (status, memaddr, info);
151 return -1;
152 }
153 insn = bfd_getb32 (buffer);
154 extension = 0;
155 consume = 4;
156 }
157
158 /* These are five byte insns. */
159 else if ((insn & 0xff) == 0xcd
160 || (insn & 0xff) == 0xdc)
161 {
162 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
163 if (status != 0)
164 {
165 (*info->memory_error_func) (status, memaddr, info);
166 return -1;
167 }
168 insn = bfd_getb32 (buffer);
169
170 status = (*info->read_memory_func) (memaddr, buffer, 1, info);
171 if (status != 0)
172 {
173 (*info->memory_error_func) (status, memaddr, info);
174 return -1;
175 }
176 extension = *(unsigned char *) buffer + 4;
177 consume = 5;
178 }
179
180 /* These are six byte insns. */
181 else if ((insn & 0xff) == 0xfd
182 || (insn & 0xff) == 0xfc)
183 {
184 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
185 if (status != 0)
186 {
187 (*info->memory_error_func) (status, memaddr, info);
188 return -1;
189 }
190
191 insn = bfd_getb32 (buffer);
192 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
193 if (status != 0)
194 {
195 (*info->memory_error_func) (status, memaddr, info);
196 return -1;
197 }
198 extension = bfd_getb16 (buffer + 4);
199 consume = 6;
200 }
201
202 /* Else its a seven byte insns (in theory). */
203 else
204 {
205 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
206 if (status != 0)
207 {
208 (*info->memory_error_func) (status, memaddr, info);
209 return -1;
210 }
211
212 insn = bfd_getb32 (buffer);
213 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
214 if (status != 0)
215 {
216 (*info->memory_error_func) (status, memaddr, info);
217 return -1;
218 }
219 extension = bfd_getb16 (buffer);
220 extension <<= 8;
221 extension |= *(unsigned char *)buffer + 2;
222 consume = 7;
223 }
224
225 disassemble (memaddr, info, insn, extension, consume);
226
227 return consume;
228}
229
230static void
231disassemble (memaddr, info, insn, extension, size)
232 bfd_vma memaddr;
233 struct disassemble_info *info;
234 unsigned long insn;
235 unsigned long extension;
236 unsigned int size;
237{
238 struct mn10300_opcode *op = (struct mn10300_opcode *)mn10300_opcodes;
239 const struct mn10300_operand *operand;
240 int match = 0;
241
242 /* Find the opcode. */
243 while (op->name)
244 {
245 int mysize;
246
247 if (op->format == FMT_S0)
248 mysize = 1;
249 else if (op->format == FMT_S1
250 || op->format == FMT_D0)
251 mysize = 2;
252 else if (op->format == FMT_S2
253 || op->format == FMT_D1)
254 mysize = 3;
255 else if (op->format == FMT_S4)
256 mysize = 5;
257 else if (op->format == FMT_D2)
258 mysize = 4;
259 else if (op->format == FMT_D4)
260 mysize = 6;
261 else
262 mysize = 7;
263
264 if ((op->mask & insn) == op->opcode
265 && size == mysize)
266 {
267 const unsigned char *opindex_ptr;
268 unsigned int opnum, memop;
269
270 match = 1;
271 (*info->fprintf_func) (info->stream, "%s\t", op->name);
272
273 /* Now print the operands. */
274 for (opindex_ptr = op->operands, opnum = 1;
275 *opindex_ptr != 0;
276 opindex_ptr++, opnum++)
277 {
278 unsigned long value;
279
280 operand = &mn10300_operands[*opindex_ptr];
281
282 value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
283
284 if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
285 value = ((long)(value << (32 - operand->bits))
286 >> (32 - operand->bits));
287
288 /* All done. */
289 break;
290 }
291 op++;
292 }
293
294 if (!match)
295 {
296 (*info->fprintf_func) (info->stream, "unknown\t0x%04x", insn);
297 }
e7c50cef 298}
This page took 0.038452 seconds and 4 git commands to generate.