19990502 sourceware import
[deliverable/binutils-gdb.git] / opcodes / m10300-dis.c
CommitLineData
252b5132
RH
1/* Disassemble MN10300 instructions.
2 Copyright (C) 1996, 1997, 1998 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"
22#include "opcode/mn10300.h"
23#include "dis-asm.h"
24#include "opintl.h"
25
26static void disassemble PARAMS ((bfd_vma, struct disassemble_info *,
27 unsigned long insn, unsigned int));
28
29int
30print_insn_mn10300 (memaddr, info)
31 bfd_vma memaddr;
32 struct disassemble_info *info;
33{
34 int status;
35 bfd_byte buffer[4];
36 unsigned long insn;
37 unsigned int consume;
38
39 /* First figure out how big the opcode is. */
40 status = (*info->read_memory_func) (memaddr, buffer, 1, info);
41 if (status != 0)
42 {
43 (*info->memory_error_func) (status, memaddr, info);
44 return -1;
45 }
46 insn = *(unsigned char *) buffer;
47
48 /* These are one byte insns. */
49 if ((insn & 0xf3) == 0x00
50 || (insn & 0xf0) == 0x10
51 || (insn & 0xfc) == 0x3c
52 || (insn & 0xf3) == 0x41
53 || (insn & 0xf3) == 0x40
54 || (insn & 0xfc) == 0x50
55 || (insn & 0xfc) == 0x54
56 || (insn & 0xf0) == 0x60
57 || (insn & 0xf0) == 0x70
58 || ((insn & 0xf0) == 0x80
59 && (insn & 0x0c) >> 2 != (insn & 0x03))
60 || ((insn & 0xf0) == 0x90
61 && (insn & 0x0c) >> 2 != (insn & 0x03))
62 || ((insn & 0xf0) == 0xa0
63 && (insn & 0x0c) >> 2 != (insn & 0x03))
64 || ((insn & 0xf0) == 0xb0
65 && (insn & 0x0c) >> 2 != (insn & 0x03))
66 || (insn & 0xff) == 0xcb
67 || (insn & 0xfc) == 0xd0
68 || (insn & 0xfc) == 0xd4
69 || (insn & 0xfc) == 0xd8
70 || (insn & 0xf0) == 0xe0
71 || (insn & 0xff) == 0xff)
72 {
73 consume = 1;
74 }
75
76 /* These are two byte insns. */
77 else if ((insn & 0xf0) == 0x80
78 || (insn & 0xf0) == 0x90
79 || (insn & 0xf0) == 0xa0
80 || (insn & 0xf0) == 0xb0
81 || (insn & 0xfc) == 0x20
82 || (insn & 0xfc) == 0x28
83 || (insn & 0xf3) == 0x43
84 || (insn & 0xf3) == 0x42
85 || (insn & 0xfc) == 0x58
86 || (insn & 0xfc) == 0x5c
87 || ((insn & 0xf0) == 0xc0
88 && (insn & 0xff) != 0xcb
89 && (insn & 0xff) != 0xcc
90 && (insn & 0xff) != 0xcd)
91 || (insn & 0xff) == 0xf0
92 || (insn & 0xff) == 0xf1
93 || (insn & 0xff) == 0xf2
94 || (insn & 0xff) == 0xf3
95 || (insn & 0xff) == 0xf4
96 || (insn & 0xff) == 0xf5
97 || (insn & 0xff) == 0xf6)
98 {
99 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
100 if (status != 0)
101 {
102 (*info->memory_error_func) (status, memaddr, info);
103 return -1;
104 }
105 insn = bfd_getb16 (buffer);
106 consume = 2;
107 }
108
109 /* These are three byte insns. */
110 else if ((insn & 0xff) == 0xf8
111 || (insn & 0xff) == 0xcc
112 || (insn & 0xff) == 0xf9
113 || (insn & 0xf3) == 0x01
114 || (insn & 0xf3) == 0x02
115 || (insn & 0xf3) == 0x03
116 || (insn & 0xfc) == 0x24
117 || (insn & 0xfc) == 0x2c
118 || (insn & 0xfc) == 0x30
119 || (insn & 0xfc) == 0x34
120 || (insn & 0xfc) == 0x38
121 || (insn & 0xff) == 0xde
122 || (insn & 0xff) == 0xdf
123 || (insn & 0xff) == 0xcc)
124 {
125 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
126 if (status != 0)
127 {
128 (*info->memory_error_func) (status, memaddr, info);
129 return -1;
130 }
131 insn = bfd_getb16 (buffer);
132 insn <<= 8;
133 status = (*info->read_memory_func) (memaddr + 2, buffer, 1, info);
134 if (status != 0)
135 {
136 (*info->memory_error_func) (status, memaddr, info);
137 return -1;
138 }
139 insn |= *(unsigned char *)buffer;
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 consume = 4;
155 }
156
157 /* These are five byte insns. */
158 else if ((insn & 0xff) == 0xcd
159 || (insn & 0xff) == 0xdc)
160 {
161 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
162 if (status != 0)
163 {
164 (*info->memory_error_func) (status, memaddr, info);
165 return -1;
166 }
167 insn = bfd_getb32 (buffer);
168 consume = 5;
169 }
170
171 /* These are six byte insns. */
172 else if ((insn & 0xff) == 0xfd
173 || (insn & 0xff) == 0xfc)
174 {
175 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
176 if (status != 0)
177 {
178 (*info->memory_error_func) (status, memaddr, info);
179 return -1;
180 }
181
182 insn = bfd_getb32 (buffer);
183 consume = 6;
184 }
185
186 /* Else its a seven byte insns (in theory). */
187 else
188 {
189 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
190 if (status != 0)
191 {
192 (*info->memory_error_func) (status, memaddr, info);
193 return -1;
194 }
195
196 insn = bfd_getb32 (buffer);
197 consume = 7;
198 }
199
200 disassemble (memaddr, info, insn, consume);
201
202 return consume;
203}
204
205static void
206disassemble (memaddr, info, insn, size)
207 bfd_vma memaddr;
208 struct disassemble_info *info;
209 unsigned long insn;
210 unsigned int size;
211{
212 struct mn10300_opcode *op = (struct mn10300_opcode *)mn10300_opcodes;
213 const struct mn10300_operand *operand;
214 bfd_byte buffer[4];
215 unsigned long extension = 0;
216 int status, match = 0;
217
218 /* Find the opcode. */
219 while (op->name)
220 {
221 int mysize, extra_shift;
222
223 if (op->format == FMT_S0)
224 mysize = 1;
225 else if (op->format == FMT_S1
226 || op->format == FMT_D0)
227 mysize = 2;
228 else if (op->format == FMT_S2
229 || op->format == FMT_D1)
230 mysize = 3;
231 else if (op->format == FMT_S4)
232 mysize = 5;
233 else if (op->format == FMT_D2)
234 mysize = 4;
235 else if (op->format == FMT_D4)
236 mysize = 6;
237 else
238 mysize = 7;
239
240 if ((op->mask & insn) == op->opcode
241 && size == (unsigned int) mysize
242 && (op->machine == 0
243 || op->machine == info->mach))
244 {
245 const unsigned char *opindex_ptr;
246 unsigned int nocomma;
247 int paren = 0;
248
249 if (op->format == FMT_D1 || op->format == FMT_S1)
250 extra_shift = 8;
251 else if (op->format == FMT_D2 || op->format == FMT_D4
252 || op->format == FMT_S2 || op->format == FMT_S4
253 || op->format == FMT_S6 || op->format == FMT_D5)
254 extra_shift = 16;
255 else
256 extra_shift = 0;
257
258 if (size == 1 || size == 2)
259 {
260 extension = 0;
261 }
262 else if (size == 3
263 && (op->format == FMT_D1
264 || op->opcode == 0xdf0000
265 || op->opcode == 0xde0000))
266 {
267 extension = 0;
268 }
269 else if (size == 3)
270 {
271 insn &= 0xff0000;
272 status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
273 if (status != 0)
274 {
275 (*info->memory_error_func) (status, memaddr, info);
276 return;
277 }
278
279 insn |= bfd_getl16 (buffer);
280 extension = 0;
281 }
282 else if (size == 4
283 && (op->opcode == 0xfaf80000
284 || op->opcode == 0xfaf00000
285 || op->opcode == 0xfaf40000))
286 {
287 extension = 0;
288 }
289 else if (size == 4)
290 {
291 insn &= 0xffff0000;
292 status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
293 if (status != 0)
294 {
295 (*info->memory_error_func) (status, memaddr, info);
296 return;
297 }
298
299 insn |= bfd_getl16 (buffer);
300 extension = 0;
301 }
302 else if (size == 5 && op->opcode == 0xdc000000)
303 {
304 unsigned long temp = 0;
305 status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
306 if (status != 0)
307 {
308 (*info->memory_error_func) (status, memaddr, info);
309 return;
310 }
311 temp |= bfd_getl32 (buffer);
312
313 insn &= 0xff000000;
314 insn |= (temp & 0xffffff00) >> 8;
315 extension = temp & 0xff;
316 }
317 else if (size == 5)
318 {
319 unsigned long temp = 0;
320 status = (*info->read_memory_func) (memaddr + 1, buffer, 2, info);
321 if (status != 0)
322 {
323 (*info->memory_error_func) (status, memaddr, info);
324 return;
325 }
326 temp |= bfd_getl16 (buffer);
327
328 insn &= 0xff0000ff;
329 insn |= temp << 8;
330
331 status = (*info->read_memory_func) (memaddr + 4, buffer, 1, info);
332 if (status != 0)
333 {
334 (*info->memory_error_func) (status, memaddr, info);
335 return;
336 }
337 extension = *(unsigned char *)buffer;
338 }
339 else if (size == 6)
340 {
341 unsigned long temp = 0;
342 status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
343 if (status != 0)
344 {
345 (*info->memory_error_func) (status, memaddr, info);
346 return;
347 }
348 temp |= bfd_getl32 (buffer);
349
350 insn &= 0xffff0000;
351 insn |= (temp >> 16) & 0xffff;
352 extension = temp & 0xffff;
353 }
354 else if (size == 7 && op->opcode == 0xdd000000)
355 {
356 unsigned long temp = 0;
357 status = (*info->read_memory_func) (memaddr + 1, buffer, 4, info);
358 if (status != 0)
359 {
360 (*info->memory_error_func) (status, memaddr, info);
361 return;
362 }
363 temp |= bfd_getl32 (buffer);
364
365 insn &= 0xff000000;
366 insn |= (temp >> 8) & 0xffffff;
367 extension = (temp & 0xff) << 16;
368
369 status = (*info->read_memory_func) (memaddr + 5, buffer, 2, info);
370 if (status != 0)
371 {
372 (*info->memory_error_func) (status, memaddr, info);
373 return;
374 }
375 extension |= bfd_getb16 (buffer);
376 }
377 else if (size == 7)
378 {
379 unsigned long temp = 0;
380 status = (*info->read_memory_func) (memaddr + 2, buffer, 4, info);
381 if (status != 0)
382 {
383 (*info->memory_error_func) (status, memaddr, info);
384 return;
385 }
386 temp |= bfd_getl32 (buffer);
387
388 insn &= 0xffff0000;
389 insn |= (temp >> 16) & 0xffff;
390 extension = (temp & 0xffff) << 8;
391
392 status = (*info->read_memory_func) (memaddr + 6, buffer, 1, info);
393 if (status != 0)
394 {
395 (*info->memory_error_func) (status, memaddr, info);
396 return;
397 }
398 extension |= *(unsigned char *)buffer;
399 }
400
401 match = 1;
402 (*info->fprintf_func) (info->stream, "%s\t", op->name);
403
404 /* Now print the operands. */
405 for (opindex_ptr = op->operands, nocomma = 1;
406 *opindex_ptr != 0;
407 opindex_ptr++)
408 {
409 unsigned long value;
410
411 operand = &mn10300_operands[*opindex_ptr];
412
413
414 if ((operand->flags & MN10300_OPERAND_SPLIT) != 0)
415 {
416 unsigned long temp;
417 value = insn & ((1 << operand->bits) - 1);
418 value <<= (32 - operand->bits);
419 temp = extension >> operand->shift;
420 temp &= ((1 << (32 - operand->bits)) - 1);
421 value |= temp;
422 }
423 else if ((operand->flags & MN10300_OPERAND_EXTENDED) != 0)
424 {
425 value = ((extension >> (operand->shift))
426 & ((1 << operand->bits) - 1));
427 }
428 else
429 {
430 value = ((insn >> (operand->shift))
431 & ((1 << operand->bits) - 1));
432 }
433
434 if ((operand->flags & MN10300_OPERAND_SIGNED) != 0
435 )
436 value = ((long)(value << (32 - operand->bits))
437 >> (32 - operand->bits));
438
439 if (!nocomma
440 && (!paren
441 || ((operand->flags & MN10300_OPERAND_PAREN) == 0)))
442 (*info->fprintf_func) (info->stream, ",");
443
444 nocomma = 0;
445
446 if ((operand->flags & MN10300_OPERAND_DREG) != 0)
447 {
448 value = ((insn >> (operand->shift + extra_shift))
449 & ((1 << operand->bits) - 1));
450 (*info->fprintf_func) (info->stream, "d%d", value);
451 }
452
453 else if ((operand->flags & MN10300_OPERAND_AREG) != 0)
454 {
455 value = ((insn >> (operand->shift + extra_shift))
456 & ((1 << operand->bits) - 1));
457 (*info->fprintf_func) (info->stream, "a%d", value);
458 }
459
460 else if ((operand->flags & MN10300_OPERAND_SP) != 0)
461 (*info->fprintf_func) (info->stream, "sp");
462
463 else if ((operand->flags & MN10300_OPERAND_PSW) != 0)
464 (*info->fprintf_func) (info->stream, "psw");
465
466 else if ((operand->flags & MN10300_OPERAND_MDR) != 0)
467 (*info->fprintf_func) (info->stream, "mdr");
468
469
470 else if ((operand->flags & MN10300_OPERAND_PAREN) != 0)
471 {
472 if (paren)
473 (*info->fprintf_func) (info->stream, ")");
474 else
475 {
476 (*info->fprintf_func) (info->stream, "(");
477 nocomma = 1;
478 }
479 paren = !paren;
480 }
481
482 else if ((operand->flags & MN10300_OPERAND_PCREL) != 0)
483 (*info->print_address_func) ((long) value + memaddr, info);
484
485 else if ((operand->flags & MN10300_OPERAND_MEMADDR) != 0)
486 (*info->print_address_func) (value, info);
487
488 else if ((operand->flags & MN10300_OPERAND_REG_LIST) != 0)
489 {
490 int comma = 0;
491
492 (*info->fprintf_func) (info->stream, "[");
493 if (value & 0x80)
494 {
495 (*info->fprintf_func) (info->stream, "d2");
496 comma = 1;
497 }
498
499 if (value & 0x40)
500 {
501 if (comma)
502 (*info->fprintf_func) (info->stream, ",");
503 (*info->fprintf_func) (info->stream, "d3");
504 comma = 1;
505 }
506
507 if (value & 0x20)
508 {
509 if (comma)
510 (*info->fprintf_func) (info->stream, ",");
511 (*info->fprintf_func) (info->stream, "a2");
512 comma = 1;
513 }
514
515 if (value & 0x10)
516 {
517 if (comma)
518 (*info->fprintf_func) (info->stream, ",");
519 (*info->fprintf_func) (info->stream, "a3");
520 comma = 1;
521 }
522
523 if (value & 0x08)
524 {
525 if (comma)
526 (*info->fprintf_func) (info->stream, ",");
527 (*info->fprintf_func) (info->stream, "other");
528 comma = 1;
529 }
530
531 (*info->fprintf_func) (info->stream, "]");
532 }
533
534 else
535 (*info->fprintf_func) (info->stream, "%d", value);
536 }
537 /* All done. */
538 break;
539 }
540 op++;
541 }
542
543 if (!match)
544 {
545 /* xgettext:c-format */
546 (*info->fprintf_func) (info->stream, _("unknown\t0x%04x"), insn);
547 }
548}
This page took 0.045542 seconds and 4 git commands to generate.