1 /* Disassemble SH instructions.
2 Copyright 1993, 1994, 1995, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005
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., 51 Franklin Street - Fifth Floor, Boston,
18 MA 02110-1301, USA. */
29 #define INCLUDE_SHMEDIA
33 print_movxy (const sh_opcode_info
*op
,
36 fprintf_ftype fprintf_fn
,
41 fprintf_fn (stream
, "%s\t", op
->name
);
42 for (n
= 0; n
< 2; n
++)
51 fprintf_fn (stream
, "@r%d", rn
);
58 fprintf_fn (stream
, "@r%d+", rn
);
62 fprintf_fn (stream
, "@r%d+r8", rn
);
66 fprintf_fn (stream
, "@r%d+r9", rn
);
69 fprintf_fn (stream
, "a%c", '0' + rm
);
72 fprintf_fn (stream
, "x%c", '0' + rm
);
75 fprintf_fn (stream
, "y%c", '0' + rm
);
78 fprintf_fn (stream
, "%c%c",
80 (rm
& 2) ? '1' : '0');
83 fprintf_fn (stream
, "%c%c",
85 (rm
& 2) ? '1' : '0');
88 fprintf_fn (stream
, "%c%c",
90 (rm
& 1) ? '1' : '0');
93 fprintf_fn (stream
, "%c%c",
95 (rm
& 1) ? '1' : '0');
101 fprintf_fn (stream
, ",");
105 /* Print a double data transfer insn. INSN is just the lower three
106 nibbles of the insn, i.e. field a and the bit that indicates if
107 a parallel processing insn follows.
108 Return nonzero if a field b of a parallel processing insns follows. */
111 print_insn_ddt (int insn
, struct disassemble_info
*info
)
113 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
114 void *stream
= info
->stream
;
116 /* If this is just a nop, make sure to emit something. */
118 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
& 0xc) == 0 && (insn
& 0x2a0))
127 || ((insn
& 3) == 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
);
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,
198 print_dsp_reg (int rm
, fprintf_ftype fprintf_fn
, void *stream
)
203 fprintf_fn (stream
, "a1");
206 fprintf_fn (stream
, "a0");
209 fprintf_fn (stream
, "x0");
212 fprintf_fn (stream
, "x1");
215 fprintf_fn (stream
, "y0");
218 fprintf_fn (stream
, "y1");
221 fprintf_fn (stream
, "m0");
224 fprintf_fn (stream
, "a1g");
227 fprintf_fn (stream
, "m1");
230 fprintf_fn (stream
, "a0g");
233 fprintf_fn (stream
, "0x%x", rm
);
239 print_insn_ppi (int field_b
, struct disassemble_info
*info
)
241 static char *sx_tab
[] = { "x0", "x1", "a0", "a1" };
242 static char *sy_tab
[] = { "y0", "y1", "m0", "m1" };
243 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
244 void *stream
= info
->stream
;
245 unsigned int nib1
, nib2
, nib3
;
246 unsigned int altnib1
, nib4
;
248 const sh_opcode_info
*op
;
250 if ((field_b
& 0xe800) == 0)
252 fprintf_fn (stream
, "psh%c\t#%d,",
253 field_b
& 0x1000 ? 'a' : 'l',
254 (field_b
>> 4) & 127);
255 print_dsp_reg (field_b
& 0xf, fprintf_fn
, stream
);
258 if ((field_b
& 0xc000) == 0x4000 && (field_b
& 0x3000) != 0x1000)
260 static char *du_tab
[] = { "x0", "y0", "a0", "a1" };
261 static char *se_tab
[] = { "x0", "x1", "y0", "a1" };
262 static char *sf_tab
[] = { "y0", "y1", "x0", "a1" };
263 static char *sg_tab
[] = { "m0", "m1", "a0", "a1" };
265 if (field_b
& 0x2000)
266 fprintf_fn (stream
, "p%s %s,%s,%s\t",
267 (field_b
& 0x1000) ? "add" : "sub",
268 sx_tab
[(field_b
>> 6) & 3],
269 sy_tab
[(field_b
>> 4) & 3],
270 du_tab
[(field_b
>> 0) & 3]);
272 else if ((field_b
& 0xf0) == 0x10
273 && info
->mach
!= bfd_mach_sh_dsp
274 && info
->mach
!= bfd_mach_sh3_dsp
)
275 fprintf_fn (stream
, "pclr %s \t", du_tab
[(field_b
>> 0) & 3]);
277 else if ((field_b
& 0xf3) != 0)
278 fprintf_fn (stream
, ".word 0x%x\t", field_b
);
280 fprintf_fn (stream
, "pmuls%c%s,%s,%s",
281 field_b
& 0x2000 ? ' ' : '\t',
282 se_tab
[(field_b
>> 10) & 3],
283 sf_tab
[(field_b
>> 8) & 3],
284 sg_tab
[(field_b
>> 2) & 3]);
289 nib2
= field_b
>> 12 & 0xf;
290 nib3
= field_b
>> 8 & 0xf;
291 nib4
= field_b
>> 4 & 0xf;
314 for (op
= sh_table
; op
->name
; op
++)
316 if ((op
->nibbles
[1] == nib1
|| op
->nibbles
[1] == altnib1
)
317 && op
->nibbles
[2] == nib2
318 && op
->nibbles
[3] == nib3
)
322 switch (op
->nibbles
[4])
335 if ((nib4
& 0xc) != 0)
339 if ((nib4
& 0xc) != 4)
345 fprintf_fn (stream
, "%s%s\t", dc
, op
->name
);
346 for (n
= 0; n
< 3 && op
->arg
[n
] != A_END
; n
++)
348 if (n
&& op
->arg
[1] != A_END
)
349 fprintf_fn (stream
, ",");
353 print_dsp_reg (field_b
& 0xf, fprintf_fn
, stream
);
356 fprintf_fn (stream
, sx_tab
[(field_b
>> 6) & 3]);
359 fprintf_fn (stream
, sy_tab
[(field_b
>> 4) & 3]);
362 fprintf_fn (stream
, "mach");
365 fprintf_fn (stream
, "macl");
375 fprintf_fn (stream
, ".word 0x%x", field_b
);
378 /* FIXME mvs: movx insns print as ".word 0x%03x", insn & 0xfff
379 (ie. the upper nibble is missing). */
382 print_insn_sh (bfd_vma memaddr
, struct disassemble_info
*info
)
384 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
385 void *stream
= info
->stream
;
386 unsigned char insn
[4];
387 unsigned char nibs
[8];
389 bfd_vma relmask
= ~(bfd_vma
) 0;
390 const sh_opcode_info
*op
;
391 unsigned int target_arch
;
397 target_arch
= arch_sh1
;
398 /* SH coff object files lack information about the machine type, so
399 we end up with bfd_mach_sh unless it was set explicitly (which
400 could have happended if this is a call from gdb or the simulator.) */
402 && bfd_asymbol_flavour(*info
->symbols
) == bfd_target_coff_flavour
)
403 target_arch
= arch_sh4
;
406 #ifdef INCLUDE_SHMEDIA
407 status
= print_insn_sh64 (memaddr
, info
);
411 /* When we get here for sh64, it's because we want to disassemble
412 SHcompact, i.e. arch_sh4. */
413 target_arch
= arch_sh4
;
416 target_arch
= sh_get_arch_from_bfd_mach (info
->mach
);
419 status
= info
->read_memory_func (memaddr
, insn
, 2, info
);
423 info
->memory_error_func (status
, memaddr
, info
);
427 if (info
->endian
== BFD_ENDIAN_LITTLE
)
429 nibs
[0] = (insn
[1] >> 4) & 0xf;
430 nibs
[1] = insn
[1] & 0xf;
432 nibs
[2] = (insn
[0] >> 4) & 0xf;
433 nibs
[3] = insn
[0] & 0xf;
437 nibs
[0] = (insn
[0] >> 4) & 0xf;
438 nibs
[1] = insn
[0] & 0xf;
440 nibs
[2] = (insn
[1] >> 4) & 0xf;
441 nibs
[3] = insn
[1] & 0xf;
443 status
= info
->read_memory_func (memaddr
+ 2, insn
+ 2, 2, info
);
450 if (info
->endian
== BFD_ENDIAN_LITTLE
)
452 nibs
[4] = (insn
[3] >> 4) & 0xf;
453 nibs
[5] = insn
[3] & 0xf;
455 nibs
[6] = (insn
[2] >> 4) & 0xf;
456 nibs
[7] = insn
[2] & 0xf;
460 nibs
[4] = (insn
[2] >> 4) & 0xf;
461 nibs
[5] = insn
[2] & 0xf;
463 nibs
[6] = (insn
[3] >> 4) & 0xf;
464 nibs
[7] = insn
[3] & 0xf;
468 if (nibs
[0] == 0xf && (nibs
[1] & 4) == 0
469 && SH_MERGE_ARCH_SET_VALID (target_arch
, arch_sh_dsp_up
))
475 status
= info
->read_memory_func (memaddr
+ 2, insn
, 2, info
);
479 info
->memory_error_func (status
, memaddr
+ 2, info
);
483 if (info
->endian
== BFD_ENDIAN_LITTLE
)
484 field_b
= insn
[1] << 8 | insn
[0];
486 field_b
= insn
[0] << 8 | insn
[1];
488 print_insn_ppi (field_b
, info
);
489 print_insn_ddt ((nibs
[1] << 8) | (nibs
[2] << 4) | nibs
[3], info
);
492 print_insn_ddt ((nibs
[1] << 8) | (nibs
[2] << 4) | nibs
[3], info
);
495 for (op
= sh_table
; op
->name
; op
++)
503 bfd_vma disp_pc_addr
= 0;
506 int max_n
= SH_MERGE_ARCH_SET (op
->arch
, arch_op32
) ? 8 : 4;
509 && SH_MERGE_ARCH_SET (op
->arch
, arch_op32
))
512 if (!SH_MERGE_ARCH_SET_VALID (op
->arch
, target_arch
))
514 for (n
= 0; n
< max_n
; n
++)
516 int i
= op
->nibbles
[n
];
527 imm
= (nibs
[2] << 4) | (nibs
[3]);
530 imm
= ((char) imm
) * 2 + 4;
533 imm
= ((nibs
[1]) << 8) | (nibs
[2] << 4) | (nibs
[3]);
544 if (!(nibs
[3] & 0x8))
554 if (!(nibs
[2] & 0x8))
560 disp
= (nibs
[5] << 8) | (nibs
[6] << 4) | nibs
[7];
565 disp
= ((nibs
[5] << 8) | (nibs
[6] << 4) | nibs
[7]) << 1;
566 relmask
= ~(bfd_vma
) 1;
571 disp
= ((nibs
[5] << 8) | (nibs
[6] << 4) | nibs
[7]) << 2;
572 relmask
= ~(bfd_vma
) 3;
577 disp
= ((nibs
[5] << 8) | (nibs
[6] << 4) | nibs
[7]) << 3;
578 relmask
= ~(bfd_vma
) 7;
584 imm
= ((nibs
[2] << 16) | (nibs
[4] << 12) | (nibs
[5] << 8)
585 | (nibs
[6] << 4) | nibs
[7]);
590 imm
= ((nibs
[2] << 16) | (nibs
[4] << 12) | (nibs
[5] << 8)
591 | (nibs
[6] << 4) | nibs
[7]);
610 imm
= (nibs
[2] << 4) | nibs
[3];
617 imm
= ((nibs
[2] << 4) | nibs
[3]) << 1;
618 relmask
= ~(bfd_vma
) 1;
621 imm
= ((nibs
[2] << 4) | nibs
[3]) << 2;
622 relmask
= ~(bfd_vma
) 3;
626 imm
= ((nibs
[2] << 4) | nibs
[3]) << 1;
630 imm
= ((nibs
[2] << 4) | nibs
[3]) << 2;
633 if ((nibs
[n
] & 1) != 0)
643 if ((nibs
[n
] & 0x3) != 1 /* binary 01 */)
645 rn
= (nibs
[n
] & 0xc) >> 2;
648 rn
= (nibs
[n
] & 0xc) >> 2;
649 rm
= (nibs
[n
] & 0x3);
655 /* sh-dsp: single data transfer. */
660 rn
|= (!(rn
& 2)) << 2;
671 /* sh2a has D_REG but not X_REG. We don't know the pattern
672 doesn't match unless we check the output args to see if they
674 if (target_arch
== arch_sh2a
675 && ((op
->arg
[0] == DX_REG_M
&& (rm
& 1) != 0)
676 || (op
->arg
[1] == DX_REG_N
&& (rn
& 1) != 0)))
679 fprintf_fn (stream
, "%s\t", op
->name
);
681 for (n
= 0; n
< 3 && op
->arg
[n
] != A_END
; n
++)
683 if (n
&& op
->arg
[1] != A_END
)
684 fprintf_fn (stream
, ",");
688 fprintf_fn (stream
, "#%d", imm
);
691 fprintf_fn (stream
, "r0");
694 fprintf_fn (stream
, "r%d", rn
);
698 fprintf_fn (stream
, "@r%d+", rn
);
702 fprintf_fn (stream
, "@-r%d", rn
);
706 fprintf_fn (stream
, "@r%d", rn
);
709 fprintf_fn (stream
, "@(%d,r%d)", has_disp
?disp
:imm
, rn
);
712 fprintf_fn (stream
, "@r%d+r8", rn
);
715 fprintf_fn (stream
, "r%d", rm
);
718 fprintf_fn (stream
, "@r%d+", rm
);
721 fprintf_fn (stream
, "@-r%d", rm
);
724 fprintf_fn (stream
, "@r%d", rm
);
727 fprintf_fn (stream
, "@(%d,r%d)", has_disp
?disp
:imm
, rm
);
730 fprintf_fn (stream
, "r%d_bank", rb
);
734 disp_pc_addr
= imm
+ 4 + (memaddr
& relmask
);
735 (*info
->print_address_func
) (disp_pc_addr
, info
);
738 fprintf_fn (stream
, "@(r0,r%d)", rn
);
741 fprintf_fn (stream
, "@(r0,r%d)", rm
);
744 fprintf_fn (stream
, "@(%d,gbr)", has_disp
?disp
:imm
);
747 fprintf_fn (stream
, "tbr");
750 fprintf_fn (stream
, "@@(%d,tbr)", has_disp
?disp
:imm
);
753 fprintf_fn (stream
, "@r15+");
756 fprintf_fn (stream
, "@-r15");
759 fprintf_fn (stream
, "@(r0,gbr)");
763 (*info
->print_address_func
) (imm
+ memaddr
, info
);
766 fprintf_fn (stream
, "sr");
769 fprintf_fn (stream
, "gbr");
772 fprintf_fn (stream
, "vbr");
775 fprintf_fn (stream
, "dsr");
778 fprintf_fn (stream
, "mod");
781 fprintf_fn (stream
, "re");
784 fprintf_fn (stream
, "rs");
787 fprintf_fn (stream
, "a0");
790 fprintf_fn (stream
, "x0");
793 fprintf_fn (stream
, "x1");
796 fprintf_fn (stream
, "y0");
799 fprintf_fn (stream
, "y1");
802 print_dsp_reg (rm
, fprintf_fn
, stream
);
805 fprintf_fn (stream
, "ssr");
808 fprintf_fn (stream
, "spc");
811 fprintf_fn (stream
, "mach");
814 fprintf_fn (stream
, "macl");
817 fprintf_fn (stream
, "pr");
820 fprintf_fn (stream
, "sgr");
823 fprintf_fn (stream
, "dbr");
826 fprintf_fn (stream
, "fr%d", rn
);
829 fprintf_fn (stream
, "fr%d", rm
);
834 fprintf_fn (stream
, "xd%d", rn
& ~1);
838 fprintf_fn (stream
, "dr%d", rn
);
843 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 status
= info
->read_memory_func (disp_pc_addr
, bytes
, size
, info
);
913 if (info
->endian
== BFD_ENDIAN_LITTLE
)
914 val
= bfd_getl16 (bytes
);
916 val
= bfd_getb16 (bytes
);
920 if (info
->endian
== BFD_ENDIAN_LITTLE
)
921 val
= bfd_getl32 (bytes
);
923 val
= bfd_getb32 (bytes
);
925 if ((*info
->symbol_at_address_func
) (val
, info
))
927 fprintf_fn (stream
, "\t! 0x");
928 (*info
->print_address_func
) (val
, info
);
931 fprintf_fn (stream
, "\t! 0x%x", val
);
935 return SH_MERGE_ARCH_SET (op
->arch
, arch_op32
) ? 4 : 2;
940 fprintf_fn (stream
, ".word 0x%x%x%x%x", nibs
[0], nibs
[1], nibs
[2], nibs
[3]);
This page took 0.047819 seconds and 4 git commands to generate.