1 /* Disassemble h8300 instructions.
2 Copyright 1993, 1994, 1996, 1998, 2000, 2001, 2002, 2003
3 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22 #define h8_opcodes h8ops
23 #include "opcode/h8300.h"
26 #include "libiberty.h"
31 const struct h8_opcode
*opcode
;
34 struct h8_instruction
*h8_instructions
;
36 static void bfd_h8_disassemble_init
PARAMS ((void));
37 static void print_one_arg
PARAMS ((disassemble_info
*, bfd_vma
, op_type
,
38 int, int, int, int, const char **, int));
39 static unsigned int bfd_h8_disassemble
PARAMS ((bfd_vma
,
42 static void extract_immediate
PARAMS ((FILE *,
46 const struct h8_opcode
*));
48 /* Run through the opcodes and sort them into order to make them easy
52 bfd_h8_disassemble_init ()
55 unsigned int nopcodes
;
56 const struct h8_opcode
*p
;
57 struct h8_instruction
*pi
;
59 nopcodes
= sizeof (h8_opcodes
) / sizeof (struct h8_opcode
);
61 h8_instructions
= (struct h8_instruction
*)
62 xmalloc (nopcodes
* sizeof (struct h8_instruction
));
64 for (p
= h8_opcodes
, pi
= h8_instructions
; p
->name
; p
++, pi
++)
69 if ((int) p
->data
.nib
[0] < 16)
70 n1
= (int) p
->data
.nib
[0];
74 if ((int) p
->data
.nib
[1] < 16)
75 n2
= (int) p
->data
.nib
[1];
79 /* Just make sure there are an even number of nibbles in it, and
80 that the count is the same as the length. */
81 for (i
= 0; p
->data
.nib
[i
] != (op_type
) E
; i
++)
86 fprintf (stderr
, "Internal error, h8_disassemble_init.\n");
94 /* Add entry for the NULL vector terminator. */
100 extract_immediate (stream
, looking_for
, thisnib
, data
, cst
, len
, q
)
106 const struct h8_opcode
*q
;
108 switch (looking_for
& SIZE
)
114 /* DISP2 special treatment. */
115 if ((looking_for
& MODE
) == DISP
)
117 if (OP_KIND (q
->how
) == O_MOVAB
||
118 OP_KIND (q
->how
) == O_MOVAW
||
119 OP_KIND (q
->how
) == O_MOVAL
)
121 /* Handling for mova insn. */
122 switch (q
->args
.nib
[0] & MODE
) {
136 /* Handling for non-mova insn. */
137 switch (OP_SIZE (q
->how
)) {
156 *cst
= (data
[0] << 8) + data
[1];
158 if ((looking_for
& SIZE
) == L_16
)
159 *cst
= (short) *cst
; /* sign extend */
164 *cst
= (data
[0] << 24) + (data
[1] << 16) + (data
[2] << 8) + data
[3];
169 fprintf (stream
, "DISP bad size\n");
174 static const char *regnames
[] =
176 "r0h", "r1h", "r2h", "r3h", "r4h", "r5h", "r6h", "r7h",
177 "r0l", "r1l", "r2l", "r3l", "r4l", "r5l", "r6l", "r7l"
179 static const char *wregnames
[] =
181 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
182 "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7"
184 static const char *lregnames
[] =
186 "er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7",
187 "er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7"
189 static const char *cregnames
[] =
191 "ccr", "exr", "mach", "macl", "", "", "vbr", "sbr"
195 print_one_arg (info
, addr
, x
, cst
, cstlen
, rdisp_n
, rn
, pregnames
, len
)
196 disassemble_info
*info
;
199 int cst
, cstlen
, rdisp_n
, rn
;
200 const char **pregnames
;
203 void *stream
= info
->stream
;
204 fprintf_ftype outfn
= info
->fprintf_func
;
206 if ((x
& SIZE
) == L_3
||
209 outfn (stream
, "#0x%x", (unsigned) cst
);
211 else if ((x
& MODE
) == IMM
)
213 outfn (stream
, "#0x%x", (unsigned) cst
);
215 else if ((x
& MODE
) == DBIT
||
218 outfn (stream
, "#%d", (unsigned) cst
);
220 else if ((x
& MODE
) == CONST_2
)
221 outfn (stream
, "#2");
222 else if ((x
& MODE
) == CONST_4
)
223 outfn (stream
, "#4");
224 else if ((x
& MODE
) == CONST_8
)
225 outfn (stream
, "#8");
226 else if ((x
& MODE
) == CONST_16
)
227 outfn (stream
, "#16");
228 else if ((x
& MODE
) == REG
)
233 outfn (stream
, "%s", regnames
[rn
]);
237 outfn (stream
, "%s", wregnames
[rn
]);
241 outfn (stream
, "%s", lregnames
[rn
]);
245 else if ((x
& MODE
) == LOWREG
)
250 /* Always take low half of reg. */
251 outfn (stream
, "%s.b", regnames
[rn
< 8 ? rn
+ 8 : rn
]);
255 /* Always take low half of reg. */
256 outfn (stream
, "%s.w", wregnames
[rn
< 8 ? rn
: rn
- 8]);
260 outfn (stream
, "%s.l", lregnames
[rn
]);
264 else if ((x
& MODE
) == POSTINC
)
266 outfn (stream
, "@%s+", pregnames
[rn
]);
268 else if ((x
& MODE
) == POSTDEC
)
270 outfn (stream
, "@%s-", pregnames
[rn
]);
272 else if ((x
& MODE
) == PREINC
)
274 outfn (stream
, "@+%s", pregnames
[rn
]);
276 else if ((x
& MODE
) == PREDEC
)
278 outfn (stream
, "@-%s", pregnames
[rn
]);
280 else if ((x
& MODE
) == IND
)
282 outfn (stream
, "@%s", pregnames
[rn
]);
284 else if ((x
& MODE
) == ABS
|| (x
& ABSJMP
))
286 outfn (stream
, "@0x%x:%d", (unsigned) cst
, cstlen
);
288 else if ((x
& MODE
) == MEMIND
)
290 outfn (stream
, "@@%d (0x%x)", cst
, cst
);
292 else if ((x
& MODE
) == VECIND
)
294 /* FIXME Multiplier should be 2 or 4, depending on processor mode,
295 by which is meant "normal" vs. "middle", "advanced", "maximum". */
297 int offset
= (cst
+ 0x80) * 4;
298 outfn (stream
, "@@%d (0x%x)", offset
, offset
);
300 else if ((x
& MODE
) == PCREL
)
302 if ((x
& SIZE
) == L_16
||
305 outfn (stream
, ".%s%d (0x%x)",
306 (short) cst
> 0 ? "+" : "",
308 addr
+ (short) cst
+ len
);
312 outfn (stream
, ".%s%d (0x%x)",
313 (char) cst
> 0 ? "+" : "",
315 addr
+ (char) cst
+ len
);
318 else if ((x
& MODE
) == DISP
)
320 outfn (stream
, "@(0x%x:%d,%s)", cst
, cstlen
,
323 else if ((x
& MODE
) == INDEXB
)
325 /* Always take low half of reg. */
326 outfn (stream
, "@(0x%x:%d,%s.b)", cst
, cstlen
,
327 regnames
[rdisp_n
< 8 ? rdisp_n
+ 8 : rdisp_n
]);
329 else if ((x
& MODE
) == INDEXW
)
331 /* Always take low half of reg. */
332 outfn (stream
, "@(0x%x:%d,%s.w)", cst
, cstlen
,
333 wregnames
[rdisp_n
< 8 ? rdisp_n
: rdisp_n
- 8]);
335 else if ((x
& MODE
) == INDEXL
)
337 outfn (stream
, "@(0x%x:%d,%s.l)", cst
, cstlen
,
342 outfn (stream
, cregnames
[rn
]);
344 else if ((x
& MODE
) == CCR
)
346 outfn (stream
, "ccr");
348 else if ((x
& MODE
) == EXR
)
350 outfn (stream
, "exr");
352 else if ((x
& MODE
) == MACREG
)
354 outfn (stream
, "mac%c", cst
? 'l' : 'h');
357 /* xgettext:c-format */
358 outfn (stream
, _("Hmmmm 0x%x"), x
);
362 bfd_h8_disassemble (addr
, info
, mach
)
364 disassemble_info
*info
;
367 /* Find the first entry in the table for this opcode. */
368 int regno
[3] = { 0, 0, 0 };
369 int dispregno
[3] = { 0, 0, 0 };
370 int cst
[3] = { 0, 0, 0 };
371 int cstlen
[3] = { 0, 0, 0 };
372 static bfd_boolean init
= 0;
373 const struct h8_instruction
*qi
;
374 char const **pregnames
= mach
!= 0 ? lregnames
: wregnames
;
377 unsigned char data
[MAX_CODE_NIBBLES
];
378 void *stream
= info
->stream
;
379 fprintf_ftype outfn
= info
->fprintf_func
;
383 bfd_h8_disassemble_init ();
387 status
= info
->read_memory_func (addr
, data
, 2, info
);
390 info
->memory_error_func (status
, addr
, info
);
394 for (l
= 2; status
== 0 && l
< sizeof (data
) / 2; l
+= 2)
395 status
= info
->read_memory_func (addr
+ l
, data
+ l
, 2, info
);
397 /* Find the exact opcode/arg combo. */
398 for (qi
= h8_instructions
; qi
->opcode
->name
; qi
++)
400 const struct h8_opcode
*q
= qi
->opcode
;
401 op_type
*nib
= q
->data
.nib
;
402 unsigned int len
= 0;
406 op_type looking_for
= *nib
;
407 int thisnib
= data
[len
/ 2];
410 thisnib
= (len
& 1) ? (thisnib
& 0xf) : ((thisnib
/ 16) & 0xf);
411 opnr
= ((looking_for
& OP3
) == OP3
? 2
412 : (looking_for
& DST
) == DST
? 1 : 0);
414 if (looking_for
< 16 && looking_for
>= 0)
416 if (looking_for
!= thisnib
)
421 if ((int) looking_for
& (int) B31
)
423 if (!((thisnib
& 0x8) != 0))
426 looking_for
= (op_type
) ((int) looking_for
& ~(int) B31
);
429 else if ((int) looking_for
& (int) B30
)
431 if (!((thisnib
& 0x8) == 0))
434 looking_for
= (op_type
) ((int) looking_for
& ~(int) B30
);
437 if ((int) looking_for
& (int) B21
)
439 if (!((thisnib
& 0x4) != 0))
442 looking_for
= (op_type
) ((int) looking_for
& ~(int) B21
);
445 else if ((int) looking_for
& (int) B20
)
447 if (!((thisnib
& 0x4) == 0))
450 looking_for
= (op_type
) ((int) looking_for
& ~(int) B20
);
452 if ((int) looking_for
& (int) B11
)
454 if (!((thisnib
& 0x2) != 0))
457 looking_for
= (op_type
) ((int) looking_for
& ~(int) B11
);
460 else if ((int) looking_for
& (int) B10
)
462 if (!((thisnib
& 0x2) == 0))
465 looking_for
= (op_type
) ((int) looking_for
& ~(int) B10
);
468 if ((int) looking_for
& (int) B01
)
470 if (!((thisnib
& 0x1) != 0))
473 looking_for
= (op_type
) ((int) looking_for
& ~(int) B01
);
476 else if ((int) looking_for
& (int) B00
)
478 if (!((thisnib
& 0x1) == 0))
481 looking_for
= (op_type
) ((int) looking_for
& ~(int) B00
);
484 if (looking_for
& IGNORE
)
486 /* Hitachi has declared that IGNORE must be zero. */
490 else if ((looking_for
& MODE
) == DATA
)
492 ; /* Skip embedded data. */
494 else if ((looking_for
& MODE
) == DBIT
)
496 /* Exclude adds/subs by looking at bit 0 and 2, and
497 make sure the operand size, either w or l,
498 matches by looking at bit 1. */
499 if ((looking_for
& 7) != (thisnib
& 7))
502 cst
[opnr
] = (thisnib
& 0x8) ? 2 : 1;
504 else if ((looking_for
& MODE
) == DISP
||
505 (looking_for
& MODE
) == ABS
||
506 (looking_for
& MODE
) == PCREL
||
507 (looking_for
& MODE
) == INDEXB
||
508 (looking_for
& MODE
) == INDEXW
||
509 (looking_for
& MODE
) == INDEXL
)
511 extract_immediate (stream
, looking_for
, thisnib
,
512 data
+ len
/ 2, cst
+ opnr
,
514 /* Even address == bra, odd == bra/s. */
515 if (q
->how
== O (O_BRAS
, SB
))
518 else if ((looking_for
& MODE
) == REG
||
519 (looking_for
& MODE
) == LOWREG
||
520 (looking_for
& MODE
) == IND
||
521 (looking_for
& MODE
) == PREINC
||
522 (looking_for
& MODE
) == POSTINC
||
523 (looking_for
& MODE
) == PREDEC
||
524 (looking_for
& MODE
) == POSTDEC
)
526 regno
[opnr
] = thisnib
;
528 else if (looking_for
& CTRL
) /* Control Register */
531 if (((looking_for
& MODE
) == CCR
&& (thisnib
!= C_CCR
)) ||
532 ((looking_for
& MODE
) == EXR
&& (thisnib
!= C_EXR
)) ||
533 ((looking_for
& MODE
) == MACH
&& (thisnib
!= C_MACH
)) ||
534 ((looking_for
& MODE
) == MACL
&& (thisnib
!= C_MACL
)) ||
535 ((looking_for
& MODE
) == VBR
&& (thisnib
!= C_VBR
)) ||
536 ((looking_for
& MODE
) == SBR
&& (thisnib
!= C_SBR
)))
538 if (((looking_for
& MODE
) == CCR_EXR
&&
539 (thisnib
!= C_CCR
&& thisnib
!= C_EXR
)) ||
540 ((looking_for
& MODE
) == VBR_SBR
&&
541 (thisnib
!= C_VBR
&& thisnib
!= C_SBR
)) ||
542 ((looking_for
& MODE
) == MACREG
&&
543 (thisnib
!= C_MACH
&& thisnib
!= C_MACL
)))
545 if (((looking_for
& MODE
) == CC_EX_VB_SB
&&
546 (thisnib
!= C_CCR
&& thisnib
!= C_EXR
&&
547 thisnib
!= C_VBR
&& thisnib
!= C_SBR
)))
550 regno
[opnr
] = thisnib
;
552 else if ((looking_for
& SIZE
) == L_5
)
554 cst
[opnr
] = data
[len
/ 2] & 31;
557 else if ((looking_for
& SIZE
) == L_4
)
562 else if ((looking_for
& SIZE
) == L_16
||
563 (looking_for
& SIZE
) == L_16U
)
565 cst
[opnr
] = (data
[len
/ 2]) * 256 + data
[(len
+ 2) / 2];
568 else if ((looking_for
& MODE
) == MEMIND
)
572 else if ((looking_for
& MODE
) == VECIND
)
574 cst
[opnr
] = data
[1] & 0x7f;
576 else if ((looking_for
& SIZE
) == L_32
)
580 cst
[opnr
] = ((data
[i
] << 24)
581 | (data
[i
+ 1] << 16)
587 else if ((looking_for
& SIZE
) == L_24
)
592 (data
[i
] << 16) | (data
[i
+ 1] << 8) | (data
[i
+ 2]);
595 else if (looking_for
& IGNORE
)
599 else if (looking_for
& DISPREG
)
601 dispregno
[opnr
] = thisnib
& 7;
603 else if ((looking_for
& MODE
) == KBIT
)
620 else if ((looking_for
& SIZE
) == L_8
)
623 cst
[opnr
] = data
[len
/ 2];
625 else if ((looking_for
& SIZE
) == L_3
||
626 (looking_for
& SIZE
) == L_3NZ
)
628 cst
[opnr
] = thisnib
& 0x7;
629 if (cst
[opnr
] == 0 && (looking_for
& SIZE
) == L_3NZ
)
632 else if ((looking_for
& SIZE
) == L_2
)
635 cst
[opnr
] = thisnib
& 0x3;
637 else if ((looking_for
& MODE
) == MACREG
)
639 cst
[opnr
] = (thisnib
== 3);
641 else if (looking_for
== (op_type
) E
)
645 for (i
= 0; i
< qi
->length
; i
++)
646 outfn (stream
, "%02x ", data
[i
]);
651 outfn (stream
, "%s\t", q
->name
);
653 /* Gross. Disgusting. */
654 if (strcmp (q
->name
, "ldm.l") == 0)
658 count
= (data
[1] / 16) & 0x3;
661 outfn (stream
, "@sp+,er%d-er%d", high
- count
, high
);
665 if (strcmp (q
->name
, "stm.l") == 0)
669 count
= (data
[1] / 16) & 0x3;
672 outfn (stream
, "er%d-er%d,@-sp", low
, low
+ count
);
675 if (strcmp (q
->name
, "rte/l") == 0
676 || strcmp (q
->name
, "rts/l") == 0)
679 outfn (stream
, "er%d", regno
[1]);
682 outfn (stream
, "er%d-er%d", regno
[1] - regno
[0],
687 if (strncmp (q
->name
, "mova", 4) == 0)
689 op_type
*args
= q
->args
.nib
;
691 if (args
[1] == (op_type
) E
)
694 print_one_arg (info
, addr
, args
[0], cst
[0],
695 cstlen
[0], dispregno
[0], regno
[0],
696 pregnames
, qi
->length
);
697 outfn (stream
, ",er%d", dispregno
[0]);
701 outfn (stream
, "@(0x%x:%d,", cst
[0], cstlen
[0]);
702 print_one_arg (info
, addr
, args
[1], cst
[1],
703 cstlen
[1], dispregno
[1], regno
[1],
704 pregnames
, qi
->length
);
705 outfn (stream
, ".%c),",
706 (args
[0] & MODE
) == INDEXB
? 'b' : 'w');
707 print_one_arg (info
, addr
, args
[2], cst
[2],
708 cstlen
[2], dispregno
[2], regno
[2],
709 pregnames
, qi
->length
);
713 /* Fill in the args. */
715 op_type
*args
= q
->args
.nib
;
720 nargs
< 3 && args
[nargs
] != (op_type
) E
;
728 print_one_arg (info
, addr
, x
,
729 cst
[nargs
], cstlen
[nargs
],
730 dispregno
[nargs
], regno
[nargs
],
731 pregnames
, qi
->length
);
740 /* xgettext:c-format */
741 outfn (stream
, _("Don't understand 0x%x \n"), looking_for
);
752 /* Fell off the end. */
753 outfn (stream
, "%02x %02x .word\tH'%x,H'%x",
760 print_insn_h8300 (addr
, info
)
762 disassemble_info
*info
;
764 return bfd_h8_disassemble (addr
, info
, 0);
768 print_insn_h8300h (addr
, info
)
770 disassemble_info
*info
;
772 return bfd_h8_disassemble (addr
, info
, 1);
776 print_insn_h8300s (addr
, info
)
778 disassemble_info
*info
;
780 return bfd_h8_disassemble (addr
, info
, 2);