1 /* Disassemble SH instructions.
2 Copyright (C) 1993-2024 Free Software Foundation, Inc.
4 This file is part of the GNU opcodes library.
6 This library is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 It is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this file; see the file COPYING. If not, write to the
18 Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
28 #include "disassemble.h"
31 print_movxy (const sh_opcode_info
*op
,
34 fprintf_ftype fprintf_fn
,
39 fprintf_fn (stream
, "%s\t", op
->name
);
40 for (n
= 0; n
< 2; n
++)
49 fprintf_fn (stream
, "@r%d", rn
);
56 fprintf_fn (stream
, "@r%d+", rn
);
60 fprintf_fn (stream
, "@r%d+r8", rn
);
64 fprintf_fn (stream
, "@r%d+r9", rn
);
67 fprintf_fn (stream
, "a%c", '0' + rm
);
70 fprintf_fn (stream
, "x%c", '0' + rm
);
73 fprintf_fn (stream
, "y%c", '0' + rm
);
76 fprintf_fn (stream
, "%c%c",
78 (rm
& 2) ? '1' : '0');
81 fprintf_fn (stream
, "%c%c",
83 (rm
& 2) ? '1' : '0');
86 fprintf_fn (stream
, "%c%c",
88 (rm
& 1) ? '1' : '0');
91 fprintf_fn (stream
, "%c%c",
93 (rm
& 1) ? '1' : '0');
99 fprintf_fn (stream
, ",");
103 /* Print a double data transfer insn. INSN is just the lower three
104 nibbles of the insn, i.e. field a and the bit that indicates if
105 a parallel processing insn follows. */
108 print_insn_ddt (int insn
, struct disassemble_info
*info
)
110 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
111 void *stream
= info
->stream
;
113 /* If this is just a nop, make sure to emit something. */
116 fprintf_fn (stream
, "nopx\tnopy");
120 /* If a parallel processing insn was printed before,
121 and we got a non-nop, emit a tab. */
122 if ((insn
& 0x800) && (insn
& 0x3ff))
123 fprintf_fn (stream
, "\t");
125 /* Check if either the x or y part is invalid. */
126 if (((insn
& 3) != 0 && (insn
& 0xc) == 0 && (insn
& 0x2a0))
127 || ((insn
& 3) == 0 && (insn
& 0xc) != 0 && (insn
& 0x150)))
128 if (info
->mach
!= bfd_mach_sh_dsp
129 && info
->mach
!= bfd_mach_sh3_dsp
)
131 static const sh_opcode_info
*first_movx
, *first_movy
;
132 const sh_opcode_info
*op
;
137 for (first_movx
= sh_table
; first_movx
->nibbles
[1] != MOVX_NOPY
;)
139 for (first_movy
= first_movx
; first_movy
->nibbles
[1] != MOVY_NOPX
;)
143 is_movy
= ((insn
& 3) != 0);
150 while (op
->nibbles
[2] != (unsigned) ((insn
>> 4) & 3)
151 || op
->nibbles
[3] != (unsigned) (insn
& 0xf))
155 (4 * ((insn
& (is_movy
? 0x200 : 0x100)) == 0)
157 + 1 * ((insn
& (is_movy
? 0x100 : 0x200)) != 0)),
162 fprintf_fn (stream
, ".word 0x%x", insn
| 0xf000);
165 static const sh_opcode_info
*first_movx
, *first_movy
;
166 const sh_opcode_info
*opx
, *opy
;
167 unsigned int insn_x
, insn_y
;
171 for (first_movx
= sh_table
; first_movx
->nibbles
[1] != MOVX
;)
173 for (first_movy
= first_movx
; first_movy
->nibbles
[1] != MOVY
;)
176 insn_x
= (insn
>> 2) & 0xb;
179 for (opx
= first_movx
; opx
->nibbles
[2] != insn_x
;)
181 print_movxy (opx
, ((insn
>> 9) & 1) + 4, (insn
>> 7) & 1,
184 insn_y
= (insn
& 3) | ((insn
>> 1) & 8);
188 fprintf_fn (stream
, "\t");
189 for (opy
= first_movy
; opy
->nibbles
[2] != insn_y
;)
191 print_movxy (opy
, ((insn
>> 8) & 1) + 6, (insn
>> 6) & 1,
194 if (!insn_x
&& !insn_y
&& ((insn
& 0x3ff) != 0 || (insn
& 0x800) == 0))
195 fprintf_fn (stream
, ".word 0x%x", insn
| 0xf000);
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
, "%s", sx_tab
[(field_b
>> 6) & 3]);
361 fprintf_fn (stream
, "%s", 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 target_arch
= sh_get_arch_from_bfd_mach (info
->mach
);
411 status
= info
->read_memory_func (memaddr
, insn
, 2, info
);
415 info
->memory_error_func (status
, memaddr
, info
);
419 if (info
->endian
== BFD_ENDIAN_LITTLE
)
421 nibs
[0] = (insn
[1] >> 4) & 0xf;
422 nibs
[1] = insn
[1] & 0xf;
424 nibs
[2] = (insn
[0] >> 4) & 0xf;
425 nibs
[3] = insn
[0] & 0xf;
429 nibs
[0] = (insn
[0] >> 4) & 0xf;
430 nibs
[1] = insn
[0] & 0xf;
432 nibs
[2] = (insn
[1] >> 4) & 0xf;
433 nibs
[3] = insn
[1] & 0xf;
435 status
= info
->read_memory_func (memaddr
+ 2, insn
+ 2, 2, info
);
442 if (info
->endian
== BFD_ENDIAN_LITTLE
)
444 nibs
[4] = (insn
[3] >> 4) & 0xf;
445 nibs
[5] = insn
[3] & 0xf;
447 nibs
[6] = (insn
[2] >> 4) & 0xf;
448 nibs
[7] = insn
[2] & 0xf;
452 nibs
[4] = (insn
[2] >> 4) & 0xf;
453 nibs
[5] = insn
[2] & 0xf;
455 nibs
[6] = (insn
[3] >> 4) & 0xf;
456 nibs
[7] = insn
[3] & 0xf;
460 if (nibs
[0] == 0xf && (nibs
[1] & 4) == 0
461 && SH_MERGE_ARCH_SET_VALID (target_arch
, arch_sh_dsp_up
))
467 status
= info
->read_memory_func (memaddr
+ 2, insn
, 2, info
);
471 info
->memory_error_func (status
, memaddr
+ 2, info
);
475 if (info
->endian
== BFD_ENDIAN_LITTLE
)
476 field_b
= insn
[1] << 8 | insn
[0];
478 field_b
= insn
[0] << 8 | insn
[1];
480 print_insn_ppi (field_b
, info
);
481 print_insn_ddt ((nibs
[1] << 8) | (nibs
[2] << 4) | nibs
[3], info
);
484 print_insn_ddt ((nibs
[1] << 8) | (nibs
[2] << 4) | nibs
[3], info
);
487 for (op
= sh_table
; op
->name
; op
++)
495 bfd_vma disp_pc_addr
= 0;
498 int max_n
= SH_MERGE_ARCH_SET (op
->arch
, arch_op32
) ? 8 : 4;
501 && SH_MERGE_ARCH_SET (op
->arch
, arch_op32
))
504 if (!SH_MERGE_ARCH_SET_VALID (op
->arch
, target_arch
))
506 for (n
= 0; n
< max_n
; n
++)
508 int i
= op
->nibbles
[n
];
519 imm
= (nibs
[2] << 4) | (nibs
[3]);
522 imm
= ((char) imm
) * 2 + 4;
525 imm
= ((nibs
[1]) << 8) | (nibs
[2] << 4) | (nibs
[3]);
536 if (!(nibs
[3] & 0x8))
546 if (!(nibs
[2] & 0x8))
552 disp
= (nibs
[5] << 8) | (nibs
[6] << 4) | nibs
[7];
557 disp
= ((nibs
[5] << 8) | (nibs
[6] << 4) | nibs
[7]) << 1;
558 relmask
= ~(bfd_vma
) 1;
563 disp
= ((nibs
[5] << 8) | (nibs
[6] << 4) | nibs
[7]) << 2;
564 relmask
= ~(bfd_vma
) 3;
569 disp
= ((nibs
[5] << 8) | (nibs
[6] << 4) | nibs
[7]) << 3;
570 relmask
= ~(bfd_vma
) 7;
576 imm
= ((nibs
[2] << 16) | (nibs
[4] << 12) | (nibs
[5] << 8)
577 | (nibs
[6] << 4) | nibs
[7]);
582 imm
= ((nibs
[2] << 16) | (nibs
[4] << 12) | (nibs
[5] << 8)
583 | (nibs
[6] << 4) | nibs
[7]);
602 imm
= (nibs
[2] << 4) | nibs
[3];
609 disp
= imm
= (nibs
[2] << 4) | nibs
[3];
613 imm
= ((nibs
[2] << 4) | nibs
[3]) << 1;
614 relmask
= ~(bfd_vma
) 1;
617 imm
= ((nibs
[2] << 4) | nibs
[3]) << 2;
618 relmask
= ~(bfd_vma
) 3;
622 imm
= ((nibs
[2] << 4) | nibs
[3]) << 1;
626 imm
= ((nibs
[2] << 4) | nibs
[3]) << 2;
629 if ((nibs
[n
] & 1) != 0)
639 if ((nibs
[n
] & 0x3) != 1 /* binary 01 */)
641 rn
= (nibs
[n
] & 0xc) >> 2;
644 rn
= (nibs
[n
] & 0xc) >> 2;
645 rm
= (nibs
[n
] & 0x3);
648 if (!(nibs
[n
] & 0x08)) /* Must always be 1. */
653 /* sh-dsp: single data transfer. */
658 rn
|= (!(rn
& 2)) << 2;
669 /* sh2a has D_REG but not X_REG. We don't know the pattern
670 doesn't match unless we check the output args to see if they
672 if (target_arch
== arch_sh2a
673 && ((op
->arg
[0] == DX_REG_M
&& (rm
& 1) != 0)
674 || (op
->arg
[1] == DX_REG_N
&& (rn
& 1) != 0)))
677 fprintf_fn (stream
, "%s\t", op
->name
);
679 for (n
= 0; n
< 3 && op
->arg
[n
] != A_END
; n
++)
681 if (n
&& op
->arg
[1] != A_END
)
682 fprintf_fn (stream
, ",");
686 fprintf_fn (stream
, "#%d", imm
);
689 fprintf_fn (stream
, "r0");
692 fprintf_fn (stream
, "r%d", rn
);
696 fprintf_fn (stream
, "@r%d+", rn
);
700 fprintf_fn (stream
, "@-r%d", rn
);
704 fprintf_fn (stream
, "@r%d", rn
);
707 fprintf_fn (stream
, "@(%d,r%d)", has_disp
?disp
:imm
, rn
);
710 fprintf_fn (stream
, "@r%d+r8", rn
);
713 fprintf_fn (stream
, "r%d", rm
);
716 fprintf_fn (stream
, "@r%d+", rm
);
719 fprintf_fn (stream
, "@-r%d", rm
);
722 fprintf_fn (stream
, "@r%d", rm
);
725 fprintf_fn (stream
, "@(%d,r%d)", has_disp
?disp
:imm
, rm
);
728 fprintf_fn (stream
, "r%d_bank", rb
);
732 disp_pc_addr
= imm
+ 4 + (memaddr
& relmask
);
733 (*info
->print_address_func
) (disp_pc_addr
, info
);
736 fprintf_fn (stream
, "@(r0,r%d)", rn
);
739 fprintf_fn (stream
, "@(r0,r%d)", rm
);
742 fprintf_fn (stream
, "@(%d,gbr)", has_disp
?disp
:imm
);
745 fprintf_fn (stream
, "tbr");
748 fprintf_fn (stream
, "@@(%d,tbr)", has_disp
?disp
:imm
);
751 fprintf_fn (stream
, "@r15+");
754 fprintf_fn (stream
, "@-r15");
757 fprintf_fn (stream
, "@(r0,gbr)");
761 (*info
->print_address_func
) (imm
+ memaddr
, info
);
764 fprintf_fn (stream
, "sr");
767 fprintf_fn (stream
, "gbr");
770 fprintf_fn (stream
, "vbr");
773 fprintf_fn (stream
, "dsr");
776 fprintf_fn (stream
, "mod");
779 fprintf_fn (stream
, "re");
782 fprintf_fn (stream
, "rs");
785 fprintf_fn (stream
, "a0");
788 fprintf_fn (stream
, "x0");
791 fprintf_fn (stream
, "x1");
794 fprintf_fn (stream
, "y0");
797 fprintf_fn (stream
, "y1");
800 print_dsp_reg (rm
, fprintf_fn
, stream
);
803 fprintf_fn (stream
, "ssr");
806 fprintf_fn (stream
, "spc");
809 fprintf_fn (stream
, "mach");
812 fprintf_fn (stream
, "macl");
815 fprintf_fn (stream
, "pr");
818 fprintf_fn (stream
, "sgr");
821 fprintf_fn (stream
, "dbr");
824 fprintf_fn (stream
, "fr%d", rn
);
827 fprintf_fn (stream
, "fr%d", rm
);
832 fprintf_fn (stream
, "xd%d", rn
& ~1);
837 fprintf_fn (stream
, "dr%d", rn
);
842 fprintf_fn (stream
, "xd%d", rm
& ~1);
847 fprintf_fn (stream
, "dr%d", rm
);
851 fprintf_fn (stream
, "fpscr");
855 fprintf_fn (stream
, "fpul");
858 fprintf_fn (stream
, "fr0");
861 fprintf_fn (stream
, "fv%d", rn
* 4);
864 fprintf_fn (stream
, "fv%d", rm
* 4);
867 fprintf_fn (stream
, "xmtrx");
875 /* This code prints instructions in delay slots on the same line
876 as the instruction which needs the delay slots. This can be
877 confusing, since other disassembler don't work this way, and
878 it means that the instructions are not all in a line. So I
880 if (!(info
->flags
& 1)
881 && (op
->name
[0] == 'j'
882 || (op
->name
[0] == 'b'
883 && (op
->name
[1] == 'r'
884 || op
->name
[1] == 's'))
885 || (op
->name
[0] == 'r' && op
->name
[1] == 't')
886 || (op
->name
[0] == 'b' && op
->name
[2] == '.')))
889 fprintf_fn (stream
, "\t(slot ");
890 print_insn_sh (memaddr
+ 2, info
);
892 fprintf_fn (stream
, ")");
897 if (disp_pc
&& strcmp (op
->name
, "mova") != 0)
902 if (relmask
== ~(bfd_vma
) 1)
906 /* Not reading an instruction - disable stop_vma. */
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]);