Add support for mips16 (16 bit MIPS implementation):
[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
e7c50cef 29int
ae1b99e4 30print_insn_mn10300 (memaddr, info)
e7c50cef
JL
31 bfd_vma memaddr;
32 struct disassemble_info *info;
33{
4aa92185
JL
34 int status;
35 bfd_byte buffer[4];
36 unsigned long insn;
37 unsigned long extension;
38 unsigned int consume;
39
40 /* First figure out how big the opcode is. */
41 status = (*info->read_memory_func) (memaddr, buffer, 1, info);
42 if (status != 0)
43 {
44 (*info->memory_error_func) (status, memaddr, info);
45 return -1;
46 }
47 insn = *(unsigned char *) buffer;
48
d91028d2 49 /* These are one byte insns. */
4aa92185
JL
50 if ((insn & 0xf3) == 0x00
51 || (insn & 0xf0) == 0x10
52 || (insn & 0xfc) == 0x3c
53 || (insn & 0xf3) == 0x41
54 || (insn & 0xf3) == 0x40
55 || (insn & 0xfc) == 0x50
56 || (insn & 0xfc) == 0x54
57 || (insn & 0xf0) == 0x60
58 || (insn & 0xf0) == 0x70
59 || ((insn & 0xf0) == 0x80
60 && (insn & 0x0c) >> 2 != (insn & 0x03))
61 || ((insn & 0xf0) == 0x90
62 && (insn & 0x0c) >> 2 != (insn & 0x03))
63 || ((insn & 0xf0) == 0xa0
64 && (insn & 0x0c) >> 2 != (insn & 0x03))
65 || ((insn & 0xf0) == 0xb0
66 && (insn & 0x0c) >> 2 != (insn & 0x03))
67 || (insn & 0xff) == 0xcb
68 || (insn & 0xfc) == 0xd0
69 || (insn & 0xfc) == 0xd4
70 || (insn & 0xfc) == 0xd8
71 || (insn & 0xf0) == 0xe0)
72 {
73 extension = 0;
74 consume = 1;
75 }
76
77 /* These are two byte insns. */
78 else if ((insn & 0xf0) == 0x80
79 || (insn & 0xf0) == 0x90
80 || (insn & 0xf0) == 0xa0
81 || (insn & 0xf0) == 0xb0
82 || (insn & 0xfc) == 0x20
83 || (insn & 0xfc) == 0x28
84 || (insn & 0xf3) == 0x43
85 || (insn & 0xf3) == 0x42
86 || (insn & 0xfc) == 0x58
87 || (insn & 0xfc) == 0x5c
88 || ((insn & 0xf0) == 0xc0
89 && (insn & 0xff) != 0xcb
90 && (insn & 0xff) != 0xcc
91 && (insn & 0xff) != 0xcd)
92 || (insn & 0xff) == 0xf0
93 || (insn & 0xff) == 0xf1
94 || (insn & 0xff) == 0xf2
95 || (insn & 0xff) == 0xf3
96 || (insn & 0xff) == 0xf4
97 || (insn & 0xff) == 0xf5
98 || (insn & 0xff) == 0xf6)
99 {
100 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
101 if (status != 0)
102 {
103 (*info->memory_error_func) (status, memaddr, info);
104 return -1;
105 }
106 insn = bfd_getb16 (buffer);
107 extension = 0;
108 consume = 2;
109 }
110
111 /* These are three byte insns. */
112 else if ((insn & 0xff) == 0xf8
113 || (insn & 0xff) == 0xcc
114 || (insn & 0xff) == 0xf9
115 || (insn & 0xf3) == 0x01
116 || (insn & 0xf3) == 0x02
117 || (insn & 0xf3) == 0x03
118 || (insn & 0xfc) == 0x24
119 || (insn & 0xfc) == 0x2c
120 || (insn & 0xfc) == 0x30
121 || (insn & 0xfc) == 0x34
122 || (insn & 0xfc) == 0x38
123 || (insn & 0xff) == 0xde
124 || (insn & 0xff) == 0xdf
125 || (insn & 0xff) == 0xcc)
126 {
127 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
128 if (status != 0)
129 {
130 (*info->memory_error_func) (status, memaddr, info);
131 return -1;
132 }
133 insn = bfd_getb16 (buffer);
134 insn <<= 8;
d91028d2
JL
135 status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info);
136 if (status != 0)
137 {
138 (*info->memory_error_func) (status, memaddr, info);
139 return -1;
140 }
141 insn |= *(unsigned char *)buffer;
4aa92185
JL
142 extension = 0;
143 consume = 3;
144 }
145
146 /* These are four byte insns. */
147 else if ((insn & 0xff) == 0xfa
148 || (insn & 0xff) == 0xfb)
149 {
150 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
151 if (status != 0)
152 {
153 (*info->memory_error_func) (status, memaddr, info);
154 return -1;
155 }
156 insn = bfd_getb32 (buffer);
157 extension = 0;
158 consume = 4;
159 }
160
161 /* These are five byte insns. */
162 else if ((insn & 0xff) == 0xcd
163 || (insn & 0xff) == 0xdc)
164 {
165 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
166 if (status != 0)
167 {
168 (*info->memory_error_func) (status, memaddr, info);
169 return -1;
170 }
171 insn = bfd_getb32 (buffer);
172
d91028d2 173 status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
4aa92185
JL
174 if (status != 0)
175 {
d91028d2 176 (*info->memory_error_func) (status, memaddr + 4, info);
4aa92185
JL
177 return -1;
178 }
d91028d2 179 extension = *(unsigned char *) buffer;
4aa92185
JL
180 consume = 5;
181 }
182
183 /* These are six byte insns. */
184 else if ((insn & 0xff) == 0xfd
185 || (insn & 0xff) == 0xfc)
186 {
187 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
188 if (status != 0)
189 {
190 (*info->memory_error_func) (status, memaddr, info);
191 return -1;
192 }
193
194 insn = bfd_getb32 (buffer);
d91028d2 195 status = (*info->read_memory_func) (memaddr + 4, buffer, 2, info);
4aa92185
JL
196 if (status != 0)
197 {
d91028d2 198 (*info->memory_error_func) (status, memaddr + 4, info);
4aa92185
JL
199 return -1;
200 }
d91028d2 201 extension = bfd_getb16 (buffer);
4aa92185
JL
202 consume = 6;
203 }
204
205 /* Else its a seven byte insns (in theory). */
206 else
207 {
208 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
209 if (status != 0)
210 {
211 (*info->memory_error_func) (status, memaddr, info);
212 return -1;
213 }
214
215 insn = bfd_getb32 (buffer);
d91028d2 216 status = (*info->read_memory_func) (memaddr + 4, buffer, 2, info);
4aa92185
JL
217 if (status != 0)
218 {
d91028d2 219 (*info->memory_error_func) (status, memaddr + 4, info);
4aa92185
JL
220 return -1;
221 }
222 extension = bfd_getb16 (buffer);
223 extension <<= 8;
f497f3ae 224 status = (*info->read_memory_func) (memaddr + 6, buffer, 1, info);
d91028d2
JL
225 if (status != 0)
226 {
f497f3ae 227 (*info->memory_error_func) (status, memaddr + 6, info);
d91028d2
JL
228 return -1;
229 }
230 extension |= *(unsigned char *)buffer;
4aa92185
JL
231 consume = 7;
232 }
233
234 disassemble (memaddr, info, insn, extension, consume);
235
236 return consume;
237}
238
239static void
240disassemble (memaddr, info, insn, extension, size)
241 bfd_vma memaddr;
242 struct disassemble_info *info;
243 unsigned long insn;
244 unsigned long extension;
245 unsigned int size;
246{
247 struct mn10300_opcode *op = (struct mn10300_opcode *)mn10300_opcodes;
248 const struct mn10300_operand *operand;
249 int match = 0;
250
251 /* Find the opcode. */
252 while (op->name)
253 {
d91028d2 254 int mysize, extra_shift;
4aa92185
JL
255
256 if (op->format == FMT_S0)
257 mysize = 1;
258 else if (op->format == FMT_S1
259 || op->format == FMT_D0)
260 mysize = 2;
261 else if (op->format == FMT_S2
262 || op->format == FMT_D1)
263 mysize = 3;
264 else if (op->format == FMT_S4)
265 mysize = 5;
266 else if (op->format == FMT_D2)
267 mysize = 4;
268 else if (op->format == FMT_D4)
269 mysize = 6;
270 else
271 mysize = 7;
272
d91028d2
JL
273 if (op->format == FMT_D1 || op->format == FMT_S1)
274 extra_shift = 8;
275 else if (op->format == FMT_D2 || op->format == FMT_D4
276 || op->format == FMT_S2 || op->format == FMT_S4
277 || op->format == FMT_S6 || op->format == FMT_D5)
278 extra_shift = 16;
279 else
280 extra_shift = 0;
281
4aa92185
JL
282 if ((op->mask & insn) == op->opcode
283 && size == mysize)
284 {
285 const unsigned char *opindex_ptr;
d91028d2
JL
286 unsigned int nocomma, memop;
287 int paren = 0;
4aa92185
JL
288
289 match = 1;
290 (*info->fprintf_func) (info->stream, "%s\t", op->name);
291
292 /* Now print the operands. */
d91028d2 293 for (opindex_ptr = op->operands, nocomma = 1;
4aa92185 294 *opindex_ptr != 0;
d91028d2 295 opindex_ptr++)
4aa92185
JL
296 {
297 unsigned long value;
298
299 operand = &mn10300_operands[*opindex_ptr];
300
f497f3ae
JL
301 if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
302 {
303 unsigned long temp;
304 value = insn & ((1 << operand->bits) - 1);
305 value <<= (32 - operand->bits);
306 temp = extension >> operand->shift;
307 temp &= ((1 << 32 - operand->bits) - 1);
308 value |= temp;
309 }
310 else if ((operand->flags & MN10300_OPERAND_EXTENDED) != 0)
311 {
312 value = ((extension >> (operand->shift))
313 & ((1 << operand->bits) - 1));
314 }
315 else
316 {
317 value = ((insn >> (operand->shift))
318 & ((1 << operand->bits) - 1));
319 }
4aa92185
JL
320
321 if ((operand->flags & MN10300_OPERAND_SIGNED) != 0)
322 value = ((long)(value << (32 - operand->bits))
323 >> (32 - operand->bits));
324
d91028d2
JL
325 if (!nocomma
326 && (!paren
327 || ((operand->flags & MN10300_OPERAND_PAREN) == 0)))
328 (*info->fprintf_func) (info->stream, ",");
329
330 nocomma = 0;
331
332 if ((operand->flags & MN10300_OPERAND_DREG) != 0)
333 {
334 value = ((insn >> (operand->shift + extra_shift))
335 & ((1 << operand->bits) - 1));
76783aa3 336 (*info->fprintf_func) (info->stream, "$d%d", value);
d91028d2
JL
337 }
338
339 else if ((operand->flags & MN10300_OPERAND_AREG) != 0)
340 {
341 value = ((insn >> (operand->shift + extra_shift))
342 & ((1 << operand->bits) - 1));
76783aa3 343 (*info->fprintf_func) (info->stream, "$a%d", value);
d91028d2
JL
344 }
345
346 else if ((operand->flags & MN10300_OPERAND_SP) != 0)
76783aa3 347 (*info->fprintf_func) (info->stream, "$sp");
d91028d2
JL
348
349 else if ((operand->flags & MN10300_OPERAND_PSW) != 0)
76783aa3 350 (*info->fprintf_func) (info->stream, "$psw");
d91028d2
JL
351
352 else if ((operand->flags & MN10300_OPERAND_MDR) != 0)
76783aa3 353 (*info->fprintf_func) (info->stream, "$mdr");
d91028d2
JL
354
355 else if ((operand->flags & MN10300_OPERAND_PAREN) != 0)
356 {
357 if (paren)
358 (*info->fprintf_func) (info->stream, ")");
359 else
360 {
361 (*info->fprintf_func) (info->stream, "(");
362 nocomma = 1;
363 }
364 paren = !paren;
365 }
366
aa9c04cd
JL
367 else if ((operand->flags & MN10300_OPERAND_PCREL) != 0)
368 (*info->print_address_func) (value + memaddr, info);
369
370 else if ((operand->flags & MN10300_OPERAND_MEMADDR) != 0)
371 (*info->print_address_func) (value, info);
372
f0e98103
JL
373 else if ((operand->flags & MN10300_OPERAND_REG_LIST) != 0)
374 {
375 int comma = 0;
376
377 (*info->fprintf_func) (info->stream, "[");
378 if (value & 0x80)
379 {
11cd057a 380 (*info->fprintf_func) (info->stream, "%d2");
f0e98103
JL
381 comma = 1;
382 }
383
384 if (value & 0x40)
385 {
386 if (comma)
387 (*info->fprintf_func) (info->stream, ",");
11cd057a 388 (*info->fprintf_func) (info->stream, "%d3");
f0e98103
JL
389 comma = 1;
390 }
391
392 if (value & 0x20)
393 {
394 if (comma)
395 (*info->fprintf_func) (info->stream, ",");
11cd057a 396 (*info->fprintf_func) (info->stream, "%a2");
f0e98103
JL
397 comma = 1;
398 }
399
400 if (value & 0x10)
401 {
402 if (comma)
403 (*info->fprintf_func) (info->stream, ",");
11cd057a 404 (*info->fprintf_func) (info->stream, "%a3");
f0e98103
JL
405 comma = 1;
406 }
407
408 if (value & 0x08)
409 {
410 if (comma)
411 (*info->fprintf_func) (info->stream, ",");
11cd057a 412 (*info->fprintf_func) (info->stream, "%other");
f0e98103
JL
413 comma = 1;
414 }
415 (*info->fprintf_func) (info->stream, "]");
416 }
417
d91028d2
JL
418 else
419 (*info->fprintf_func) (info->stream, "%d", value);
420 }
4aa92185
JL
421 /* All done. */
422 break;
423 }
424 op++;
425 }
426
427 if (!match)
428 {
429 (*info->fprintf_func) (info->stream, "unknown\t0x%04x", insn);
430 }
e7c50cef 431}
This page took 0.04496 seconds and 4 git commands to generate.