1 /* Disassemble SH instructions.
2 Copyright 1993, 1994, 1995, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005,
3 2006, 2007 Free Software Foundation, Inc.
5 This file is part of the GNU opcodes library.
7 This library is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 It is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this file; see the file COPYING. If not, write to the
19 Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
31 #define INCLUDE_SHMEDIA
35 print_movxy (const sh_opcode_info
*op
,
38 fprintf_ftype fprintf_fn
,
43 fprintf_fn (stream
, "%s\t", op
->name
);
44 for (n
= 0; n
< 2; n
++)
53 fprintf_fn (stream
, "@r%d", rn
);
60 fprintf_fn (stream
, "@r%d+", rn
);
64 fprintf_fn (stream
, "@r%d+r8", rn
);
68 fprintf_fn (stream
, "@r%d+r9", rn
);
71 fprintf_fn (stream
, "a%c", '0' + rm
);
74 fprintf_fn (stream
, "x%c", '0' + rm
);
77 fprintf_fn (stream
, "y%c", '0' + rm
);
80 fprintf_fn (stream
, "%c%c",
82 (rm
& 2) ? '1' : '0');
85 fprintf_fn (stream
, "%c%c",
87 (rm
& 2) ? '1' : '0');
90 fprintf_fn (stream
, "%c%c",
92 (rm
& 1) ? '1' : '0');
95 fprintf_fn (stream
, "%c%c",
97 (rm
& 1) ? '1' : '0');
103 fprintf_fn (stream
, ",");
107 /* Print a double data transfer insn. INSN is just the lower three
108 nibbles of the insn, i.e. field a and the bit that indicates if
109 a parallel processing insn follows.
110 Return nonzero if a field b of a parallel processing insns follows. */
113 print_insn_ddt (int insn
, struct disassemble_info
*info
)
115 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
116 void *stream
= info
->stream
;
118 /* If this is just a nop, make sure to emit something. */
120 fprintf_fn (stream
, "nopx\tnopy");
122 /* If a parallel processing insn was printed before,
123 and we got a non-nop, emit a tab. */
124 if ((insn
& 0x800) && (insn
& 0x3ff))
125 fprintf_fn (stream
, "\t");
127 /* Check if either the x or y part is invalid. */
128 if (((insn
& 0xc) == 0 && (insn
& 0x2a0))
129 || ((insn
& 3) == 0 && (insn
& 0x150)))
130 if (info
->mach
!= bfd_mach_sh_dsp
131 && info
->mach
!= bfd_mach_sh3_dsp
)
133 static const sh_opcode_info
*first_movx
, *first_movy
;
134 const sh_opcode_info
*op
;
139 for (first_movx
= sh_table
; first_movx
->nibbles
[1] != MOVX_NOPY
;)
141 for (first_movy
= first_movx
; first_movy
->nibbles
[1] != MOVY_NOPX
;)
145 is_movy
= ((insn
& 3) != 0);
152 while (op
->nibbles
[2] != (unsigned) ((insn
>> 4) & 3)
153 || op
->nibbles
[3] != (unsigned) (insn
& 0xf))
157 (4 * ((insn
& (is_movy
? 0x200 : 0x100)) == 0)
159 + 1 * ((insn
& (is_movy
? 0x100 : 0x200)) != 0)),
164 fprintf_fn (stream
, ".word 0x%x", insn
);
167 static const sh_opcode_info
*first_movx
, *first_movy
;
168 const sh_opcode_info
*opx
, *opy
;
169 unsigned int insn_x
, insn_y
;
173 for (first_movx
= sh_table
; first_movx
->nibbles
[1] != MOVX
;)
175 for (first_movy
= first_movx
; first_movy
->nibbles
[1] != MOVY
;)
178 insn_x
= (insn
>> 2) & 0xb;
181 for (opx
= first_movx
; opx
->nibbles
[2] != insn_x
;)
183 print_movxy (opx
, ((insn
>> 9) & 1) + 4, (insn
>> 7) & 1,
186 insn_y
= (insn
& 3) | ((insn
>> 1) & 8);
190 fprintf_fn (stream
, "\t");
191 for (opy
= first_movy
; opy
->nibbles
[2] != insn_y
;)
193 print_movxy (opy
, ((insn
>> 8) & 1) + 6, (insn
>> 6) & 1,
200 print_dsp_reg (int rm
, fprintf_ftype fprintf_fn
, void *stream
)
205 fprintf_fn (stream
, "a1");
208 fprintf_fn (stream
, "a0");
211 fprintf_fn (stream
, "x0");
214 fprintf_fn (stream
, "x1");
217 fprintf_fn (stream
, "y0");
220 fprintf_fn (stream
, "y1");
223 fprintf_fn (stream
, "m0");
226 fprintf_fn (stream
, "a1g");
229 fprintf_fn (stream
, "m1");
232 fprintf_fn (stream
, "a0g");
235 fprintf_fn (stream
, "0x%x", rm
);
241 print_insn_ppi (int field_b
, struct disassemble_info
*info
)
243 static char *sx_tab
[] = { "x0", "x1", "a0", "a1" };
244 static char *sy_tab
[] = { "y0", "y1", "m0", "m1" };
245 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
246 void *stream
= info
->stream
;
247 unsigned int nib1
, nib2
, nib3
;
248 unsigned int altnib1
, nib4
;
250 const sh_opcode_info
*op
;
252 if ((field_b
& 0xe800) == 0)
254 fprintf_fn (stream
, "psh%c\t#%d,",
255 field_b
& 0x1000 ? 'a' : 'l',
256 (field_b
>> 4) & 127);
257 print_dsp_reg (field_b
& 0xf, fprintf_fn
, stream
);
260 if ((field_b
& 0xc000) == 0x4000 && (field_b
& 0x3000) != 0x1000)
262 static char *du_tab
[] = { "x0", "y0", "a0", "a1" };
263 static char *se_tab
[] = { "x0", "x1", "y0", "a1" };
264 static char *sf_tab
[] = { "y0", "y1", "x0", "a1" };
265 static char *sg_tab
[] = { "m0", "m1", "a0", "a1" };
267 if (field_b
& 0x2000)
268 fprintf_fn (stream
, "p%s %s,%s,%s\t",
269 (field_b
& 0x1000) ? "add" : "sub",
270 sx_tab
[(field_b
>> 6) & 3],
271 sy_tab
[(field_b
>> 4) & 3],
272 du_tab
[(field_b
>> 0) & 3]);
274 else if ((field_b
& 0xf0) == 0x10
275 && info
->mach
!= bfd_mach_sh_dsp
276 && info
->mach
!= bfd_mach_sh3_dsp
)
277 fprintf_fn (stream
, "pclr %s \t", du_tab
[(field_b
>> 0) & 3]);
279 else if ((field_b
& 0xf3) != 0)
280 fprintf_fn (stream
, ".word 0x%x\t", field_b
);
282 fprintf_fn (stream
, "pmuls%c%s,%s,%s",
283 field_b
& 0x2000 ? ' ' : '\t',
284 se_tab
[(field_b
>> 10) & 3],
285 sf_tab
[(field_b
>> 8) & 3],
286 sg_tab
[(field_b
>> 2) & 3]);
291 nib2
= field_b
>> 12 & 0xf;
292 nib3
= field_b
>> 8 & 0xf;
293 nib4
= field_b
>> 4 & 0xf;
316 for (op
= sh_table
; op
->name
; op
++)
318 if ((op
->nibbles
[1] == nib1
|| op
->nibbles
[1] == altnib1
)
319 && op
->nibbles
[2] == nib2
320 && op
->nibbles
[3] == nib3
)
324 switch (op
->nibbles
[4])
337 if ((nib4
& 0xc) != 0)
341 if ((nib4
& 0xc) != 4)
347 fprintf_fn (stream
, "%s%s\t", dc
, op
->name
);
348 for (n
= 0; n
< 3 && op
->arg
[n
] != A_END
; n
++)
350 if (n
&& op
->arg
[1] != A_END
)
351 fprintf_fn (stream
, ",");
355 print_dsp_reg (field_b
& 0xf, fprintf_fn
, stream
);
358 fprintf_fn (stream
, sx_tab
[(field_b
>> 6) & 3]);
361 fprintf_fn (stream
, sy_tab
[(field_b
>> 4) & 3]);
364 fprintf_fn (stream
, "mach");
367 fprintf_fn (stream
, "macl");
377 fprintf_fn (stream
, ".word 0x%x", field_b
);
380 /* FIXME mvs: movx insns print as ".word 0x%03x", insn & 0xfff
381 (ie. the upper nibble is missing). */
384 print_insn_sh (bfd_vma memaddr
, struct disassemble_info
*info
)
386 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
387 void *stream
= info
->stream
;
388 unsigned char insn
[4];
389 unsigned char nibs
[8];
391 bfd_vma relmask
= ~(bfd_vma
) 0;
392 const sh_opcode_info
*op
;
393 unsigned int target_arch
;
399 target_arch
= arch_sh1
;
400 /* SH coff object files lack information about the machine type, so
401 we end up with bfd_mach_sh unless it was set explicitly (which
402 could have happended if this is a call from gdb or the simulator.) */
404 && bfd_asymbol_flavour(*info
->symbols
) == bfd_target_coff_flavour
)
405 target_arch
= arch_sh4
;
408 #ifdef INCLUDE_SHMEDIA
409 status
= print_insn_sh64 (memaddr
, info
);
413 /* When we get here for sh64, it's because we want to disassemble
414 SHcompact, i.e. arch_sh4. */
415 target_arch
= arch_sh4
;
418 target_arch
= sh_get_arch_from_bfd_mach (info
->mach
);
421 status
= info
->read_memory_func (memaddr
, insn
, 2, info
);
425 info
->memory_error_func (status
, memaddr
, info
);
429 if (info
->endian
== BFD_ENDIAN_LITTLE
)
431 nibs
[0] = (insn
[1] >> 4) & 0xf;
432 nibs
[1] = insn
[1] & 0xf;
434 nibs
[2] = (insn
[0] >> 4) & 0xf;
435 nibs
[3] = insn
[0] & 0xf;
439 nibs
[0] = (insn
[0] >> 4) & 0xf;
440 nibs
[1] = insn
[0] & 0xf;
442 nibs
[2] = (insn
[1] >> 4) & 0xf;
443 nibs
[3] = insn
[1] & 0xf;
445 status
= info
->read_memory_func (memaddr
+ 2, insn
+ 2, 2, info
);
452 if (info
->endian
== BFD_ENDIAN_LITTLE
)
454 nibs
[4] = (insn
[3] >> 4) & 0xf;
455 nibs
[5] = insn
[3] & 0xf;
457 nibs
[6] = (insn
[2] >> 4) & 0xf;
458 nibs
[7] = insn
[2] & 0xf;
462 nibs
[4] = (insn
[2] >> 4) & 0xf;
463 nibs
[5] = insn
[2] & 0xf;
465 nibs
[6] = (insn
[3] >> 4) & 0xf;
466 nibs
[7] = insn
[3] & 0xf;
470 if (nibs
[0] == 0xf && (nibs
[1] & 4) == 0
471 && SH_MERGE_ARCH_SET_VALID (target_arch
, arch_sh_dsp_up
))
477 status
= info
->read_memory_func (memaddr
+ 2, insn
, 2, info
);
481 info
->memory_error_func (status
, memaddr
+ 2, info
);
485 if (info
->endian
== BFD_ENDIAN_LITTLE
)
486 field_b
= insn
[1] << 8 | insn
[0];
488 field_b
= insn
[0] << 8 | insn
[1];
490 print_insn_ppi (field_b
, info
);
491 print_insn_ddt ((nibs
[1] << 8) | (nibs
[2] << 4) | nibs
[3], info
);
494 print_insn_ddt ((nibs
[1] << 8) | (nibs
[2] << 4) | nibs
[3], info
);
497 for (op
= sh_table
; op
->name
; op
++)
505 bfd_vma disp_pc_addr
= 0;
508 int max_n
= SH_MERGE_ARCH_SET (op
->arch
, arch_op32
) ? 8 : 4;
511 && SH_MERGE_ARCH_SET (op
->arch
, arch_op32
))
514 if (!SH_MERGE_ARCH_SET_VALID (op
->arch
, target_arch
))
516 for (n
= 0; n
< max_n
; n
++)
518 int i
= op
->nibbles
[n
];
529 imm
= (nibs
[2] << 4) | (nibs
[3]);
532 imm
= ((char) imm
) * 2 + 4;
535 imm
= ((nibs
[1]) << 8) | (nibs
[2] << 4) | (nibs
[3]);
546 if (!(nibs
[3] & 0x8))
556 if (!(nibs
[2] & 0x8))
562 disp
= (nibs
[5] << 8) | (nibs
[6] << 4) | nibs
[7];
567 disp
= ((nibs
[5] << 8) | (nibs
[6] << 4) | nibs
[7]) << 1;
568 relmask
= ~(bfd_vma
) 1;
573 disp
= ((nibs
[5] << 8) | (nibs
[6] << 4) | nibs
[7]) << 2;
574 relmask
= ~(bfd_vma
) 3;
579 disp
= ((nibs
[5] << 8) | (nibs
[6] << 4) | nibs
[7]) << 3;
580 relmask
= ~(bfd_vma
) 7;
586 imm
= ((nibs
[2] << 16) | (nibs
[4] << 12) | (nibs
[5] << 8)
587 | (nibs
[6] << 4) | nibs
[7]);
592 imm
= ((nibs
[2] << 16) | (nibs
[4] << 12) | (nibs
[5] << 8)
593 | (nibs
[6] << 4) | nibs
[7]);
612 imm
= (nibs
[2] << 4) | nibs
[3];
619 imm
= ((nibs
[2] << 4) | nibs
[3]) << 1;
620 relmask
= ~(bfd_vma
) 1;
623 imm
= ((nibs
[2] << 4) | nibs
[3]) << 2;
624 relmask
= ~(bfd_vma
) 3;
628 imm
= ((nibs
[2] << 4) | nibs
[3]) << 1;
632 imm
= ((nibs
[2] << 4) | nibs
[3]) << 2;
635 if ((nibs
[n
] & 1) != 0)
645 if ((nibs
[n
] & 0x3) != 1 /* binary 01 */)
647 rn
= (nibs
[n
] & 0xc) >> 2;
650 rn
= (nibs
[n
] & 0xc) >> 2;
651 rm
= (nibs
[n
] & 0x3);
657 /* sh-dsp: single data transfer. */
662 rn
|= (!(rn
& 2)) << 2;
673 /* sh2a has D_REG but not X_REG. We don't know the pattern
674 doesn't match unless we check the output args to see if they
676 if (target_arch
== arch_sh2a
677 && ((op
->arg
[0] == DX_REG_M
&& (rm
& 1) != 0)
678 || (op
->arg
[1] == DX_REG_N
&& (rn
& 1) != 0)))
681 fprintf_fn (stream
, "%s\t", op
->name
);
683 for (n
= 0; n
< 3 && op
->arg
[n
] != A_END
; n
++)
685 if (n
&& op
->arg
[1] != A_END
)
686 fprintf_fn (stream
, ",");
690 fprintf_fn (stream
, "#%d", imm
);
693 fprintf_fn (stream
, "r0");
696 fprintf_fn (stream
, "r%d", rn
);
700 fprintf_fn (stream
, "@r%d+", rn
);
704 fprintf_fn (stream
, "@-r%d", rn
);
708 fprintf_fn (stream
, "@r%d", rn
);
711 fprintf_fn (stream
, "@(%d,r%d)", has_disp
?disp
:imm
, rn
);
714 fprintf_fn (stream
, "@r%d+r8", rn
);
717 fprintf_fn (stream
, "r%d", rm
);
720 fprintf_fn (stream
, "@r%d+", rm
);
723 fprintf_fn (stream
, "@-r%d", rm
);
726 fprintf_fn (stream
, "@r%d", rm
);
729 fprintf_fn (stream
, "@(%d,r%d)", has_disp
?disp
:imm
, rm
);
732 fprintf_fn (stream
, "r%d_bank", rb
);
736 disp_pc_addr
= imm
+ 4 + (memaddr
& relmask
);
737 (*info
->print_address_func
) (disp_pc_addr
, info
);
740 fprintf_fn (stream
, "@(r0,r%d)", rn
);
743 fprintf_fn (stream
, "@(r0,r%d)", rm
);
746 fprintf_fn (stream
, "@(%d,gbr)", has_disp
?disp
:imm
);
749 fprintf_fn (stream
, "tbr");
752 fprintf_fn (stream
, "@@(%d,tbr)", has_disp
?disp
:imm
);
755 fprintf_fn (stream
, "@r15+");
758 fprintf_fn (stream
, "@-r15");
761 fprintf_fn (stream
, "@(r0,gbr)");
765 (*info
->print_address_func
) (imm
+ memaddr
, info
);
768 fprintf_fn (stream
, "sr");
771 fprintf_fn (stream
, "gbr");
774 fprintf_fn (stream
, "vbr");
777 fprintf_fn (stream
, "dsr");
780 fprintf_fn (stream
, "mod");
783 fprintf_fn (stream
, "re");
786 fprintf_fn (stream
, "rs");
789 fprintf_fn (stream
, "a0");
792 fprintf_fn (stream
, "x0");
795 fprintf_fn (stream
, "x1");
798 fprintf_fn (stream
, "y0");
801 fprintf_fn (stream
, "y1");
804 print_dsp_reg (rm
, fprintf_fn
, stream
);
807 fprintf_fn (stream
, "ssr");
810 fprintf_fn (stream
, "spc");
813 fprintf_fn (stream
, "mach");
816 fprintf_fn (stream
, "macl");
819 fprintf_fn (stream
, "pr");
822 fprintf_fn (stream
, "sgr");
825 fprintf_fn (stream
, "dbr");
828 fprintf_fn (stream
, "fr%d", rn
);
831 fprintf_fn (stream
, "fr%d", rm
);
836 fprintf_fn (stream
, "xd%d", rn
& ~1);
840 fprintf_fn (stream
, "dr%d", rn
);
845 fprintf_fn (stream
, "xd%d", rm
& ~1);
849 fprintf_fn (stream
, "dr%d", rm
);
853 fprintf_fn (stream
, "fpscr");
857 fprintf_fn (stream
, "fpul");
860 fprintf_fn (stream
, "fr0");
863 fprintf_fn (stream
, "fv%d", rn
* 4);
866 fprintf_fn (stream
, "fv%d", rm
* 4);
869 fprintf_fn (stream
, "xmtrx");
877 /* This code prints instructions in delay slots on the same line
878 as the instruction which needs the delay slots. This can be
879 confusing, since other disassembler don't work this way, and
880 it means that the instructions are not all in a line. So I
882 if (!(info
->flags
& 1)
883 && (op
->name
[0] == 'j'
884 || (op
->name
[0] == 'b'
885 && (op
->name
[1] == 'r'
886 || op
->name
[1] == 's'))
887 || (op
->name
[0] == 'r' && op
->name
[1] == 't')
888 || (op
->name
[0] == 'b' && op
->name
[2] == '.')))
891 fprintf_fn (stream
, "\t(slot ");
892 print_insn_sh (memaddr
+ 2, info
);
894 fprintf_fn (stream
, ")");
899 if (disp_pc
&& strcmp (op
->name
, "mova") != 0)
904 if (relmask
== ~(bfd_vma
) 1)
908 status
= info
->read_memory_func (disp_pc_addr
, bytes
, size
, info
);
915 if (info
->endian
== BFD_ENDIAN_LITTLE
)
916 val
= bfd_getl16 (bytes
);
918 val
= bfd_getb16 (bytes
);
922 if (info
->endian
== BFD_ENDIAN_LITTLE
)
923 val
= bfd_getl32 (bytes
);
925 val
= bfd_getb32 (bytes
);
927 if ((*info
->symbol_at_address_func
) (val
, info
))
929 fprintf_fn (stream
, "\t! ");
930 (*info
->print_address_func
) (val
, info
);
933 fprintf_fn (stream
, "\t! %x", val
);
937 return SH_MERGE_ARCH_SET (op
->arch
, arch_op32
) ? 4 : 2;
942 fprintf_fn (stream
, ".word 0x%x%x%x%x", nibs
[0], nibs
[1], nibs
[2], nibs
[3]);