1 /* Disassemble SH instructions.
2 Copyright 1993, 1994, 1995, 1997, 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. */
28 #define INCLUDE_SHMEDIA
31 static void print_movxy
32 PARAMS ((const sh_opcode_info
*, int, int, fprintf_ftype
, void *));
33 static void print_insn_ddt
PARAMS ((int, struct disassemble_info
*));
34 static void print_dsp_reg
PARAMS ((int, fprintf_ftype
, void *));
35 static void print_insn_ppi
PARAMS ((int, struct disassemble_info
*));
38 print_movxy (op
, rn
, rm
, fprintf_fn
, stream
)
39 const sh_opcode_info
*op
;
41 fprintf_ftype fprintf_fn
;
46 fprintf_fn (stream
, "%s\t", op
->name
);
47 for (n
= 0; n
< 2; n
++)
56 fprintf_fn (stream
, "@r%d", rn
);
63 fprintf_fn (stream
, "@r%d+", rn
);
67 fprintf_fn (stream
, "@r%d+r8", rn
);
71 fprintf_fn (stream
, "@r%d+r9", rn
);
74 fprintf_fn (stream
, "a%c", '0' + rm
);
77 fprintf_fn (stream
, "x%c", '0' + rm
);
80 fprintf_fn (stream
, "y%c", '0' + rm
);
83 fprintf_fn (stream
, "%c%c",
85 (rm
& 2) ? '1' : '0');
88 fprintf_fn (stream
, "%c%c",
90 (rm
& 2) ? '1' : '0');
93 fprintf_fn (stream
, "%c%c",
95 (rm
& 1) ? '1' : '0');
98 fprintf_fn (stream
, "%c%c",
100 (rm
& 1) ? '1' : '0');
106 fprintf_fn (stream
, ",");
110 /* Print a double data transfer insn. INSN is just the lower three
111 nibbles of the insn, i.e. field a and the bit that indicates if
112 a parallel processing insn follows.
113 Return nonzero if a field b of a parallel processing insns follows. */
116 print_insn_ddt (insn
, info
)
118 struct disassemble_info
*info
;
120 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
121 void *stream
= info
->stream
;
123 /* If this is just a nop, make sure to emit something. */
125 fprintf_fn (stream
, "nopx\tnopy");
127 /* If a parallel processing insn was printed before,
128 and we got a non-nop, emit a tab. */
129 if ((insn
& 0x800) && (insn
& 0x3ff))
130 fprintf_fn (stream
, "\t");
132 /* Check if either the x or y part is invalid. */
133 if (((insn
& 0xc) == 0 && (insn
& 0x2a0))
134 || ((insn
& 3) == 0 && (insn
& 0x150)))
135 if (info
->mach
!= bfd_mach_sh_dsp
136 && info
->mach
!= bfd_mach_sh3_dsp
)
138 static const sh_opcode_info
*first_movx
, *first_movy
;
139 const sh_opcode_info
*op
;
144 for (first_movx
= sh_table
; first_movx
->nibbles
[1] != MOVX_NOPY
;)
146 for (first_movy
= first_movx
; first_movy
->nibbles
[1] != MOVY_NOPX
;)
150 is_movy
= ((insn
& 3) != 0);
157 while (op
->nibbles
[2] != (unsigned) ((insn
>> 4) & 3)
158 || op
->nibbles
[3] != (unsigned) (insn
& 0xf))
162 (4 * ((insn
& (is_movy
? 0x200 : 0x100)) == 0)
164 + 1 * ((insn
& (is_movy
? 0x100 : 0x200)) != 0)),
169 fprintf_fn (stream
, ".word 0x%x", insn
);
172 static const sh_opcode_info
*first_movx
, *first_movy
;
173 const sh_opcode_info
*opx
, *opy
;
174 unsigned int insn_x
, insn_y
;
178 for (first_movx
= sh_table
; first_movx
->nibbles
[1] != MOVX
;)
180 for (first_movy
= first_movx
; first_movy
->nibbles
[1] != MOVY
;)
183 insn_x
= (insn
>> 2) & 0xb;
186 for (opx
= first_movx
; opx
->nibbles
[2] != insn_x
;)
188 print_movxy (opx
, ((insn
>> 9) & 1) + 4, (insn
>> 7) & 1,
191 insn_y
= (insn
& 3) | ((insn
>> 1) & 8);
195 fprintf_fn (stream
, "\t");
196 for (opy
= first_movy
; opy
->nibbles
[2] != insn_y
;)
198 print_movxy (opy
, ((insn
>> 8) & 1) + 6, (insn
>> 6) & 1,
205 print_dsp_reg (rm
, fprintf_fn
, stream
)
207 fprintf_ftype fprintf_fn
;
213 fprintf_fn (stream
, "a1");
216 fprintf_fn (stream
, "a0");
219 fprintf_fn (stream
, "x0");
222 fprintf_fn (stream
, "x1");
225 fprintf_fn (stream
, "y0");
228 fprintf_fn (stream
, "y1");
231 fprintf_fn (stream
, "m0");
234 fprintf_fn (stream
, "a1g");
237 fprintf_fn (stream
, "m1");
240 fprintf_fn (stream
, "a0g");
243 fprintf_fn (stream
, "0x%x", rm
);
249 print_insn_ppi (field_b
, info
)
251 struct disassemble_info
*info
;
253 static char *sx_tab
[] = { "x0", "x1", "a0", "a1" };
254 static char *sy_tab
[] = { "y0", "y1", "m0", "m1" };
255 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
256 void *stream
= info
->stream
;
257 unsigned int nib1
, nib2
, nib3
;
258 unsigned int altnib1
, nib4
;
260 const sh_opcode_info
*op
;
262 if ((field_b
& 0xe800) == 0)
264 fprintf_fn (stream
, "psh%c\t#%d,",
265 field_b
& 0x1000 ? 'a' : 'l',
266 (field_b
>> 4) & 127);
267 print_dsp_reg (field_b
& 0xf, fprintf_fn
, stream
);
270 if ((field_b
& 0xc000) == 0x4000 && (field_b
& 0x3000) != 0x1000)
272 static char *du_tab
[] = { "x0", "y0", "a0", "a1" };
273 static char *se_tab
[] = { "x0", "x1", "y0", "a1" };
274 static char *sf_tab
[] = { "y0", "y1", "x0", "a1" };
275 static char *sg_tab
[] = { "m0", "m1", "a0", "a1" };
277 if (field_b
& 0x2000)
279 fprintf_fn (stream
, "p%s %s,%s,%s\t",
280 (field_b
& 0x1000) ? "add" : "sub",
281 sx_tab
[(field_b
>> 6) & 3],
282 sy_tab
[(field_b
>> 4) & 3],
283 du_tab
[(field_b
>> 0) & 3]);
285 else if ((field_b
& 0xf0) == 0x10
286 && info
->mach
!= bfd_mach_sh_dsp
287 && info
->mach
!= bfd_mach_sh3_dsp
)
289 fprintf_fn (stream
, "pclr %s \t", du_tab
[(field_b
>> 0) & 3]);
291 else if ((field_b
& 0xf3) != 0)
293 fprintf_fn (stream
, ".word 0x%x\t", field_b
);
295 fprintf_fn (stream
, "pmuls%c%s,%s,%s",
296 field_b
& 0x2000 ? ' ' : '\t',
297 se_tab
[(field_b
>> 10) & 3],
298 sf_tab
[(field_b
>> 8) & 3],
299 sg_tab
[(field_b
>> 2) & 3]);
304 nib2
= field_b
>> 12 & 0xf;
305 nib3
= field_b
>> 8 & 0xf;
306 nib4
= field_b
>> 4 & 0xf;
329 for (op
= sh_table
; op
->name
; op
++)
331 if ((op
->nibbles
[1] == nib1
|| op
->nibbles
[1] == altnib1
)
332 && op
->nibbles
[2] == nib2
333 && op
->nibbles
[3] == nib3
)
337 switch (op
->nibbles
[4])
350 if ((nib4
& 0xc) != 0)
354 if ((nib4
& 0xc) != 4)
360 fprintf_fn (stream
, "%s%s\t", dc
, op
->name
);
361 for (n
= 0; n
< 3 && op
->arg
[n
] != A_END
; n
++)
363 if (n
&& op
->arg
[1] != A_END
)
364 fprintf_fn (stream
, ",");
368 print_dsp_reg (field_b
& 0xf, fprintf_fn
, stream
);
371 fprintf_fn (stream
, sx_tab
[(field_b
>> 6) & 3]);
374 fprintf_fn (stream
, sy_tab
[(field_b
>> 4) & 3]);
377 fprintf_fn (stream
, "mach");
380 fprintf_fn (stream
, "macl");
390 fprintf_fn (stream
, ".word 0x%x", field_b
);
394 print_insn_sh (memaddr
, info
)
396 struct disassemble_info
*info
;
398 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
399 void *stream
= info
->stream
;
400 unsigned char insn
[4];
401 unsigned char nibs
[4];
403 bfd_vma relmask
= ~(bfd_vma
) 0;
404 const sh_opcode_info
*op
;
410 target_arch
= arch_sh1
;
411 /* SH coff object files lack information about the machine type, so
412 we end up with bfd_mach_sh unless it was set explicitly (which
413 could have happended if this is a call from gdb or the simulator.) */
415 && bfd_asymbol_flavour(*info
->symbols
) == bfd_target_coff_flavour
)
416 target_arch
= arch_sh4
;
419 target_arch
= arch_sh2
;
422 target_arch
= arch_sh2e
;
424 case bfd_mach_sh_dsp
:
425 target_arch
= arch_sh_dsp
;
428 target_arch
= arch_sh3
;
430 case bfd_mach_sh3_dsp
:
431 target_arch
= arch_sh3_dsp
;
434 target_arch
= arch_sh3e
;
437 case bfd_mach_sh4_nofpu
:
438 target_arch
= arch_sh4
;
441 case bfd_mach_sh4a_nofpu
:
442 target_arch
= arch_sh4a
;
444 case bfd_mach_sh4al_dsp
:
445 target_arch
= arch_sh4al_dsp
;
448 #ifdef INCLUDE_SHMEDIA
449 status
= print_insn_sh64 (memaddr
, info
);
453 /* When we get here for sh64, it's because we want to disassemble
454 SHcompact, i.e. arch_sh4. */
455 target_arch
= arch_sh4
;
461 status
= info
->read_memory_func (memaddr
, insn
, 2, info
);
465 info
->memory_error_func (status
, memaddr
, info
);
469 if (info
->endian
== BFD_ENDIAN_LITTLE
)
471 nibs
[0] = (insn
[1] >> 4) & 0xf;
472 nibs
[1] = insn
[1] & 0xf;
474 nibs
[2] = (insn
[0] >> 4) & 0xf;
475 nibs
[3] = insn
[0] & 0xf;
479 nibs
[0] = (insn
[0] >> 4) & 0xf;
480 nibs
[1] = insn
[0] & 0xf;
482 nibs
[2] = (insn
[1] >> 4) & 0xf;
483 nibs
[3] = insn
[1] & 0xf;
486 if (nibs
[0] == 0xf && (nibs
[1] & 4) == 0 && target_arch
& arch_sh_dsp_up
)
492 status
= info
->read_memory_func (memaddr
+ 2, insn
, 2, info
);
496 info
->memory_error_func (status
, memaddr
+ 2, info
);
500 if (info
->endian
== BFD_ENDIAN_LITTLE
)
501 field_b
= insn
[1] << 8 | insn
[0];
503 field_b
= insn
[0] << 8 | insn
[1];
505 print_insn_ppi (field_b
, info
);
506 print_insn_ddt ((nibs
[1] << 8) | (nibs
[2] << 4) | nibs
[3], info
);
509 print_insn_ddt ((nibs
[1] << 8) | (nibs
[2] << 4) | nibs
[3], info
);
512 for (op
= sh_table
; op
->name
; op
++)
520 bfd_vma disp_pc_addr
= 0;
522 if ((op
->arch
& target_arch
) == 0)
524 for (n
= 0; n
< 4; n
++)
526 int i
= op
->nibbles
[n
];
537 imm
= (nibs
[2] << 4) | (nibs
[3]);
540 imm
= ((char) imm
) * 2 + 4;
543 imm
= ((nibs
[1]) << 8) | (nibs
[2] << 4) | (nibs
[3]);
562 imm
= (nibs
[2] << 4) | nibs
[3];
565 imm
= ((nibs
[2] << 4) | nibs
[3]) << 1;
566 relmask
= ~(bfd_vma
) 1;
569 imm
= ((nibs
[2] << 4) | nibs
[3]) << 2;
570 relmask
= ~(bfd_vma
) 3;
574 imm
= ((nibs
[2] << 4) | nibs
[3]) << 1;
578 imm
= ((nibs
[2] << 4) | nibs
[3]) << 2;
581 if ((nibs
[n
] & 1) != 0)
591 if ((nibs
[n
] & 0x3) != 1 /* binary 01 */)
593 rn
= (nibs
[n
] & 0xc) >> 2;
596 rn
= (nibs
[n
] & 0xc) >> 2;
597 rm
= (nibs
[n
] & 0x3);
603 /* sh-dsp: single data transfer. */
608 rn
|= (!(rn
& 2)) << 2;
619 fprintf_fn (stream
, "%s\t", op
->name
);
621 for (n
= 0; n
< 3 && op
->arg
[n
] != A_END
; n
++)
623 if (n
&& op
->arg
[1] != A_END
)
624 fprintf_fn (stream
, ",");
628 fprintf_fn (stream
, "#%d", (char) (imm
));
631 fprintf_fn (stream
, "r0");
634 fprintf_fn (stream
, "r%d", rn
);
638 fprintf_fn (stream
, "@r%d+", rn
);
642 fprintf_fn (stream
, "@-r%d", rn
);
646 fprintf_fn (stream
, "@r%d", rn
);
649 fprintf_fn (stream
, "@(%d,r%d)", imm
, rn
);
652 fprintf_fn (stream
, "@r%d+r8", rn
);
655 fprintf_fn (stream
, "r%d", rm
);
658 fprintf_fn (stream
, "@r%d+", rm
);
661 fprintf_fn (stream
, "@-r%d", rm
);
664 fprintf_fn (stream
, "@r%d", rm
);
667 fprintf_fn (stream
, "@(%d,r%d)", imm
, rm
);
670 fprintf_fn (stream
, "r%d_bank", rb
);
674 disp_pc_addr
= imm
+ 4 + (memaddr
& relmask
);
675 (*info
->print_address_func
) (disp_pc_addr
, info
);
678 fprintf_fn (stream
, "@(r0,r%d)", rn
);
681 fprintf_fn (stream
, "@(r0,r%d)", rm
);
684 fprintf_fn (stream
, "@(%d,gbr)", imm
);
687 fprintf_fn (stream
, "@(r0,gbr)");
691 (*info
->print_address_func
) (imm
+ memaddr
, info
);
694 fprintf_fn (stream
, "sr");
697 fprintf_fn (stream
, "gbr");
700 fprintf_fn (stream
, "vbr");
703 fprintf_fn (stream
, "dsr");
706 fprintf_fn (stream
, "mod");
709 fprintf_fn (stream
, "re");
712 fprintf_fn (stream
, "rs");
715 fprintf_fn (stream
, "a0");
718 fprintf_fn (stream
, "x0");
721 fprintf_fn (stream
, "x1");
724 fprintf_fn (stream
, "y0");
727 fprintf_fn (stream
, "y1");
730 print_dsp_reg (rm
, fprintf_fn
, stream
);
733 fprintf_fn (stream
, "ssr");
736 fprintf_fn (stream
, "spc");
739 fprintf_fn (stream
, "mach");
742 fprintf_fn (stream
, "macl");
745 fprintf_fn (stream
, "pr");
748 fprintf_fn (stream
, "sgr");
751 fprintf_fn (stream
, "dbr");
754 fprintf_fn (stream
, "fr%d", rn
);
757 fprintf_fn (stream
, "fr%d", rm
);
762 fprintf_fn (stream
, "xd%d", rn
& ~1);
766 fprintf_fn (stream
, "dr%d", rn
);
771 fprintf_fn (stream
, "xd%d", rm
& ~1);
775 fprintf_fn (stream
, "dr%d", rm
);
779 fprintf_fn (stream
, "fpscr");
783 fprintf_fn (stream
, "fpul");
786 fprintf_fn (stream
, "fr0");
789 fprintf_fn (stream
, "fv%d", rn
* 4);
792 fprintf_fn (stream
, "fv%d", rm
* 4);
795 fprintf_fn (stream
, "xmtrx");
803 /* This code prints instructions in delay slots on the same line
804 as the instruction which needs the delay slots. This can be
805 confusing, since other disassembler don't work this way, and
806 it means that the instructions are not all in a line. So I
808 if (!(info
->flags
& 1)
809 && (op
->name
[0] == 'j'
810 || (op
->name
[0] == 'b'
811 && (op
->name
[1] == 'r'
812 || op
->name
[1] == 's'))
813 || (op
->name
[0] == 'r' && op
->name
[1] == 't')
814 || (op
->name
[0] == 'b' && op
->name
[2] == '.')))
817 fprintf_fn (stream
, "\t(slot ");
818 print_insn_sh (memaddr
+ 2, info
);
820 fprintf_fn (stream
, ")");
825 if (disp_pc
&& strcmp (op
->name
, "mova") != 0)
830 if (relmask
== ~(bfd_vma
) 1)
834 status
= info
->read_memory_func (disp_pc_addr
, bytes
, size
, info
);
841 if (info
->endian
== BFD_ENDIAN_LITTLE
)
842 val
= bfd_getl16 (bytes
);
844 val
= bfd_getb16 (bytes
);
848 if (info
->endian
== BFD_ENDIAN_LITTLE
)
849 val
= bfd_getl32 (bytes
);
851 val
= bfd_getb32 (bytes
);
853 fprintf_fn (stream
, "\t! 0x%x", val
);
862 fprintf_fn (stream
, ".word 0x%x%x%x%x", nibs
[0], nibs
[1], nibs
[2], nibs
[3]);