1 /* Disassemble SH instructions.
2 Copyright 1993, 1994, 1995, 1997, 1998, 2000, 2001, 2002, 2003, 2004
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
;
405 unsigned int target_arch
;
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 #ifdef INCLUDE_SHMEDIA
420 status
= print_insn_sh64 (memaddr
, info
);
424 /* When we get here for sh64, it's because we want to disassemble
425 SHcompact, i.e. arch_sh4. */
426 target_arch
= arch_sh4
;
429 target_arch
= sh_get_arch_from_bfd_mach (info
->mach
);
432 status
= info
->read_memory_func (memaddr
, insn
, 2, info
);
436 info
->memory_error_func (status
, memaddr
, info
);
440 if (info
->endian
== BFD_ENDIAN_LITTLE
)
442 nibs
[0] = (insn
[1] >> 4) & 0xf;
443 nibs
[1] = insn
[1] & 0xf;
445 nibs
[2] = (insn
[0] >> 4) & 0xf;
446 nibs
[3] = insn
[0] & 0xf;
450 nibs
[0] = (insn
[0] >> 4) & 0xf;
451 nibs
[1] = insn
[0] & 0xf;
453 nibs
[2] = (insn
[1] >> 4) & 0xf;
454 nibs
[3] = insn
[1] & 0xf;
457 if (nibs
[0] == 0xf && (nibs
[1] & 4) == 0
458 && SH_MERGE_ARCH_SET_VALID (target_arch
, arch_sh_dsp_up
))
464 status
= info
->read_memory_func (memaddr
+ 2, insn
, 2, info
);
468 info
->memory_error_func (status
, memaddr
+ 2, info
);
472 if (info
->endian
== BFD_ENDIAN_LITTLE
)
473 field_b
= insn
[1] << 8 | insn
[0];
475 field_b
= insn
[0] << 8 | insn
[1];
477 print_insn_ppi (field_b
, info
);
478 print_insn_ddt ((nibs
[1] << 8) | (nibs
[2] << 4) | nibs
[3], info
);
481 print_insn_ddt ((nibs
[1] << 8) | (nibs
[2] << 4) | nibs
[3], info
);
484 for (op
= sh_table
; op
->name
; op
++)
492 bfd_vma disp_pc_addr
= 0;
494 if (!SH_MERGE_ARCH_SET_VALID (op
->arch
, target_arch
))
496 for (n
= 0; n
< 4; n
++)
498 int i
= op
->nibbles
[n
];
509 imm
= (nibs
[2] << 4) | (nibs
[3]);
512 imm
= ((char) imm
) * 2 + 4;
515 imm
= ((nibs
[1]) << 8) | (nibs
[2] << 4) | (nibs
[3]);
534 imm
= (nibs
[2] << 4) | nibs
[3];
537 imm
= ((nibs
[2] << 4) | nibs
[3]) << 1;
538 relmask
= ~(bfd_vma
) 1;
541 imm
= ((nibs
[2] << 4) | nibs
[3]) << 2;
542 relmask
= ~(bfd_vma
) 3;
546 imm
= ((nibs
[2] << 4) | nibs
[3]) << 1;
550 imm
= ((nibs
[2] << 4) | nibs
[3]) << 2;
553 if ((nibs
[n
] & 1) != 0)
563 if ((nibs
[n
] & 0x3) != 1 /* binary 01 */)
565 rn
= (nibs
[n
] & 0xc) >> 2;
568 rn
= (nibs
[n
] & 0xc) >> 2;
569 rm
= (nibs
[n
] & 0x3);
575 /* sh-dsp: single data transfer. */
580 rn
|= (!(rn
& 2)) << 2;
591 fprintf_fn (stream
, "%s\t", op
->name
);
593 for (n
= 0; n
< 3 && op
->arg
[n
] != A_END
; n
++)
595 if (n
&& op
->arg
[1] != A_END
)
596 fprintf_fn (stream
, ",");
600 fprintf_fn (stream
, "#%d", (char) (imm
));
603 fprintf_fn (stream
, "r0");
606 fprintf_fn (stream
, "r%d", rn
);
610 fprintf_fn (stream
, "@r%d+", rn
);
614 fprintf_fn (stream
, "@-r%d", rn
);
618 fprintf_fn (stream
, "@r%d", rn
);
621 fprintf_fn (stream
, "@(%d,r%d)", imm
, rn
);
624 fprintf_fn (stream
, "@r%d+r8", rn
);
627 fprintf_fn (stream
, "r%d", rm
);
630 fprintf_fn (stream
, "@r%d+", rm
);
633 fprintf_fn (stream
, "@-r%d", rm
);
636 fprintf_fn (stream
, "@r%d", rm
);
639 fprintf_fn (stream
, "@(%d,r%d)", imm
, rm
);
642 fprintf_fn (stream
, "r%d_bank", rb
);
646 disp_pc_addr
= imm
+ 4 + (memaddr
& relmask
);
647 (*info
->print_address_func
) (disp_pc_addr
, info
);
650 fprintf_fn (stream
, "@(r0,r%d)", rn
);
653 fprintf_fn (stream
, "@(r0,r%d)", rm
);
656 fprintf_fn (stream
, "@(%d,gbr)", imm
);
659 fprintf_fn (stream
, "@(r0,gbr)");
663 (*info
->print_address_func
) (imm
+ memaddr
, info
);
666 fprintf_fn (stream
, "sr");
669 fprintf_fn (stream
, "gbr");
672 fprintf_fn (stream
, "vbr");
675 fprintf_fn (stream
, "dsr");
678 fprintf_fn (stream
, "mod");
681 fprintf_fn (stream
, "re");
684 fprintf_fn (stream
, "rs");
687 fprintf_fn (stream
, "a0");
690 fprintf_fn (stream
, "x0");
693 fprintf_fn (stream
, "x1");
696 fprintf_fn (stream
, "y0");
699 fprintf_fn (stream
, "y1");
702 print_dsp_reg (rm
, fprintf_fn
, stream
);
705 fprintf_fn (stream
, "ssr");
708 fprintf_fn (stream
, "spc");
711 fprintf_fn (stream
, "mach");
714 fprintf_fn (stream
, "macl");
717 fprintf_fn (stream
, "pr");
720 fprintf_fn (stream
, "sgr");
723 fprintf_fn (stream
, "dbr");
726 fprintf_fn (stream
, "fr%d", rn
);
729 fprintf_fn (stream
, "fr%d", rm
);
734 fprintf_fn (stream
, "xd%d", rn
& ~1);
738 fprintf_fn (stream
, "dr%d", rn
);
743 fprintf_fn (stream
, "xd%d", rm
& ~1);
747 fprintf_fn (stream
, "dr%d", rm
);
751 fprintf_fn (stream
, "fpscr");
755 fprintf_fn (stream
, "fpul");
758 fprintf_fn (stream
, "fr0");
761 fprintf_fn (stream
, "fv%d", rn
* 4);
764 fprintf_fn (stream
, "fv%d", rm
* 4);
767 fprintf_fn (stream
, "xmtrx");
775 /* This code prints instructions in delay slots on the same line
776 as the instruction which needs the delay slots. This can be
777 confusing, since other disassembler don't work this way, and
778 it means that the instructions are not all in a line. So I
780 if (!(info
->flags
& 1)
781 && (op
->name
[0] == 'j'
782 || (op
->name
[0] == 'b'
783 && (op
->name
[1] == 'r'
784 || op
->name
[1] == 's'))
785 || (op
->name
[0] == 'r' && op
->name
[1] == 't')
786 || (op
->name
[0] == 'b' && op
->name
[2] == '.')))
789 fprintf_fn (stream
, "\t(slot ");
790 print_insn_sh (memaddr
+ 2, info
);
792 fprintf_fn (stream
, ")");
797 if (disp_pc
&& strcmp (op
->name
, "mova") != 0)
802 if (relmask
== ~(bfd_vma
) 1)
806 status
= info
->read_memory_func (disp_pc_addr
, bytes
, size
, info
);
813 if (info
->endian
== BFD_ENDIAN_LITTLE
)
814 val
= bfd_getl16 (bytes
);
816 val
= bfd_getb16 (bytes
);
820 if (info
->endian
== BFD_ENDIAN_LITTLE
)
821 val
= bfd_getl32 (bytes
);
823 val
= bfd_getb32 (bytes
);
825 if ((*info
->symbol_at_address_func
) (val
, info
))
827 fprintf_fn (stream
, "\t! 0x");
828 (*info
->print_address_func
) (val
, info
);
831 fprintf_fn (stream
, "\t! 0x%x", val
);
840 fprintf_fn (stream
, ".word 0x%x%x%x%x", nibs
[0], nibs
[1], nibs
[2], nibs
[3]);
This page took 0.048784 seconds and 4 git commands to generate.