1 /* Disassemble SH instructions.
2 Copyright 1993, 1994, 1995, 1997, 1998, 2000, 2001
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. */
27 static void print_movxy
28 PARAMS ((sh_opcode_info
*, int, int, fprintf_ftype
, void *));
29 static void print_insn_ddt
PARAMS ((int, struct disassemble_info
*));
30 static void print_dsp_reg
PARAMS ((int, fprintf_ftype
, void *));
31 static void print_insn_ppi
PARAMS ((int, struct disassemble_info
*));
34 print_movxy (op
, rn
, rm
, fprintf_fn
, stream
)
37 fprintf_ftype fprintf_fn
;
42 fprintf_fn (stream
, "%s\t", op
->name
);
43 for (n
= 0; n
< 2; n
++)
48 fprintf_fn (stream
, "@r%d", rn
);
51 fprintf_fn (stream
, "@r%d+", rn
);
54 fprintf_fn (stream
, "@r%d+r8", rn
);
57 fprintf_fn (stream
, "@r%d+r9", rn
);
60 fprintf_fn (stream
, "a%c", '0' + rm
);
63 fprintf_fn (stream
, "x%c", '0' + rm
);
66 fprintf_fn (stream
, "y%c", '0' + rm
);
72 fprintf_fn (stream
, ",");
76 /* Print a double data transfer insn. INSN is just the lower three
77 nibbles of the insn, i.e. field a and the bit that indicates if
78 a parallel processing insn follows.
79 Return nonzero if a field b of a parallel processing insns follows. */
82 print_insn_ddt (insn
, info
)
84 struct disassemble_info
*info
;
86 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
87 void *stream
= info
->stream
;
89 /* If this is just a nop, make sure to emit something. */
91 fprintf_fn (stream
, "nopx\tnopy");
93 /* If a parallel processing insn was printed before,
94 and we got a non-nop, emit a tab. */
95 if ((insn
& 0x800) && (insn
& 0x3ff))
96 fprintf_fn (stream
, "\t");
98 /* Check if either the x or y part is invalid. */
99 if (((insn
& 0xc) == 0 && (insn
& 0x2a0))
100 || ((insn
& 3) == 0 && (insn
& 0x150)))
101 fprintf_fn (stream
, ".word 0x%x", insn
);
104 static sh_opcode_info
*first_movx
, *first_movy
;
105 sh_opcode_info
*opx
, *opy
;
106 unsigned int insn_x
, insn_y
;
110 for (first_movx
= sh_table
; first_movx
->nibbles
[1] != MOVX
;)
112 for (first_movy
= first_movx
; first_movy
->nibbles
[1] != MOVY
;)
115 insn_x
= (insn
>> 2) & 0xb;
118 for (opx
= first_movx
; opx
->nibbles
[2] != insn_x
;)
120 print_movxy (opx
, ((insn
>> 9) & 1) + 4, (insn
>> 7) & 1,
123 insn_y
= (insn
& 3) | ((insn
>> 1) & 8);
127 fprintf_fn (stream
, "\t");
128 for (opy
= first_movy
; opy
->nibbles
[2] != insn_y
;)
130 print_movxy (opy
, ((insn
>> 8) & 1) + 6, (insn
>> 6) & 1,
137 print_dsp_reg (rm
, fprintf_fn
, stream
)
139 fprintf_ftype fprintf_fn
;
145 fprintf_fn (stream
, "a1");
148 fprintf_fn (stream
, "a0");
151 fprintf_fn (stream
, "x0");
154 fprintf_fn (stream
, "x1");
157 fprintf_fn (stream
, "y0");
160 fprintf_fn (stream
, "y1");
163 fprintf_fn (stream
, "m0");
166 fprintf_fn (stream
, "a1g");
169 fprintf_fn (stream
, "m1");
172 fprintf_fn (stream
, "a0g");
175 fprintf_fn (stream
, "0x%x", rm
);
181 print_insn_ppi (field_b
, info
)
183 struct disassemble_info
*info
;
185 static char *sx_tab
[] = { "x0", "x1", "a0", "a1" };
186 static char *sy_tab
[] = { "y0", "y1", "m0", "m1" };
187 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
188 void *stream
= info
->stream
;
189 unsigned int nib1
, nib2
, nib3
;
193 if ((field_b
& 0xe800) == 0)
195 fprintf_fn (stream
, "psh%c\t#%d,",
196 field_b
& 0x1000 ? 'a' : 'l',
197 (field_b
>> 4) & 127);
198 print_dsp_reg (field_b
& 0xf, fprintf_fn
, stream
);
201 if ((field_b
& 0xc000) == 0x4000 && (field_b
& 0x3000) != 0x1000)
203 static char *du_tab
[] = { "x0", "y0", "a0", "a1" };
204 static char *se_tab
[] = { "x0", "x1", "y0", "a1" };
205 static char *sf_tab
[] = { "y0", "y1", "x0", "a1" };
206 static char *sg_tab
[] = { "m0", "m1", "a0", "a1" };
208 if (field_b
& 0x2000)
210 fprintf_fn (stream
, "p%s %s,%s,%s\t",
211 (field_b
& 0x1000) ? "add" : "sub",
212 sx_tab
[(field_b
>> 6) & 3],
213 sy_tab
[(field_b
>> 4) & 3],
214 du_tab
[(field_b
>> 0) & 3]);
216 fprintf_fn (stream
, "pmuls%c%s,%s,%s",
217 field_b
& 0x2000 ? ' ' : '\t',
218 se_tab
[(field_b
>> 10) & 3],
219 sf_tab
[(field_b
>> 8) & 3],
220 sg_tab
[(field_b
>> 2) & 3]);
225 nib2
= field_b
>> 12 & 0xf;
226 nib3
= field_b
>> 8 & 0xf;
245 for (op
= sh_table
; op
->name
; op
++)
247 if (op
->nibbles
[1] == nib1
248 && op
->nibbles
[2] == nib2
249 && op
->nibbles
[3] == nib3
)
253 fprintf_fn (stream
, "%s%s\t", dc
, op
->name
);
254 for (n
= 0; n
< 3 && op
->arg
[n
] != A_END
; n
++)
256 if (n
&& op
->arg
[1] != A_END
)
257 fprintf_fn (stream
, ",");
261 print_dsp_reg (field_b
& 0xf, fprintf_fn
, stream
);
264 fprintf_fn (stream
, sx_tab
[(field_b
>> 6) & 3]);
267 fprintf_fn (stream
, sy_tab
[(field_b
>> 4) & 3]);
270 fprintf_fn (stream
, "mach");
273 fprintf_fn (stream
, "macl");
283 fprintf_fn (stream
, ".word 0x%x", field_b
);
287 print_insn_sh (memaddr
, info
)
289 struct disassemble_info
*info
;
291 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
292 void *stream
= info
->stream
;
293 unsigned char insn
[2];
294 unsigned char nibs
[4];
296 bfd_vma relmask
= ~(bfd_vma
) 0;
303 target_arch
= arch_sh1
;
304 /* SH coff object files lack information about the machine type, so
305 we end up with bfd_mach_sh unless it was set explicitly (which
306 could have happended if this is a call from gdb or the simulator.) */
307 if (bfd_asymbol_flavour(*info
->symbols
) == bfd_target_coff_flavour
)
308 target_arch
= arch_sh4
;
311 target_arch
= arch_sh2
;
313 case bfd_mach_sh_dsp
:
314 target_arch
= arch_sh_dsp
;
317 target_arch
= arch_sh3
;
319 case bfd_mach_sh3_dsp
:
320 target_arch
= arch_sh3_dsp
;
323 target_arch
= arch_sh3e
;
326 target_arch
= arch_sh4
;
329 #ifdef INCLUDE_SHMEDIA
330 status
= print_insn_sh64 (memaddr
, info
);
334 /* When we get here for sh64, it's because we want to disassemble
335 SHcompact, i.e. arch_sh4. */
336 target_arch
= arch_sh4
;
342 status
= info
->read_memory_func (memaddr
, insn
, 2, info
);
346 info
->memory_error_func (status
, memaddr
, info
);
350 if (info
->endian
== BFD_ENDIAN_LITTLE
)
352 nibs
[0] = (insn
[1] >> 4) & 0xf;
353 nibs
[1] = insn
[1] & 0xf;
355 nibs
[2] = (insn
[0] >> 4) & 0xf;
356 nibs
[3] = insn
[0] & 0xf;
360 nibs
[0] = (insn
[0] >> 4) & 0xf;
361 nibs
[1] = insn
[0] & 0xf;
363 nibs
[2] = (insn
[1] >> 4) & 0xf;
364 nibs
[3] = insn
[1] & 0xf;
367 if (nibs
[0] == 0xf && (nibs
[1] & 4) == 0 && target_arch
& arch_sh_dsp_up
)
373 status
= info
->read_memory_func (memaddr
+ 2, insn
, 2, info
);
377 info
->memory_error_func (status
, memaddr
+ 2, info
);
381 if (info
->endian
== BFD_ENDIAN_LITTLE
)
382 field_b
= insn
[1] << 8 | insn
[0];
384 field_b
= insn
[0] << 8 | insn
[1];
386 print_insn_ppi (field_b
, info
);
387 print_insn_ddt ((nibs
[1] << 8) | (nibs
[2] << 4) | nibs
[3], info
);
390 print_insn_ddt ((nibs
[1] << 8) | (nibs
[2] << 4) | nibs
[3], info
);
393 for (op
= sh_table
; op
->name
; op
++)
401 bfd_vma disp_pc_addr
= 0;
403 if ((op
->arch
& target_arch
) == 0)
405 for (n
= 0; n
< 4; n
++)
407 int i
= op
->nibbles
[n
];
418 imm
= (nibs
[2] << 4) | (nibs
[3]);
421 imm
= ((char) imm
) * 2 + 4;
424 imm
= ((nibs
[1]) << 8) | (nibs
[2] << 4) | (nibs
[3]);
443 imm
= (nibs
[2] << 4) | nibs
[3];
446 imm
= ((nibs
[2] << 4) | nibs
[3]) << 1;
447 relmask
= ~(bfd_vma
) 1;
450 imm
= ((nibs
[2] << 4) | nibs
[3]) << 2;
451 relmask
= ~(bfd_vma
) 3;
455 imm
= ((nibs
[2] << 4) | nibs
[3]) << 1;
459 imm
= ((nibs
[2] << 4) | nibs
[3]) << 2;
468 rn
= (nibs
[n
] & 0xc) >> 2;
469 rm
= (nibs
[n
] & 0x3);
475 /* sh-dsp: single data transfer. */
480 rn
|= (!(rn
& 2)) << 2;
491 fprintf_fn (stream
, "%s\t", op
->name
);
493 for (n
= 0; n
< 3 && op
->arg
[n
] != A_END
; n
++)
495 if (n
&& op
->arg
[1] != A_END
)
496 fprintf_fn (stream
, ",");
500 fprintf_fn (stream
, "#%d", (char) (imm
));
503 fprintf_fn (stream
, "r0");
506 fprintf_fn (stream
, "r%d", rn
);
509 fprintf_fn (stream
, "@r%d+", rn
);
512 fprintf_fn (stream
, "@-r%d", rn
);
515 fprintf_fn (stream
, "@r%d", rn
);
518 fprintf_fn (stream
, "@(%d,r%d)", imm
, rn
);
521 fprintf_fn (stream
, "@r%d+r8", rn
);
524 fprintf_fn (stream
, "r%d", rm
);
527 fprintf_fn (stream
, "@r%d+", rm
);
530 fprintf_fn (stream
, "@-r%d", rm
);
533 fprintf_fn (stream
, "@r%d", rm
);
536 fprintf_fn (stream
, "@(%d,r%d)", imm
, rm
);
539 fprintf_fn (stream
, "r%d_bank", rb
);
543 disp_pc_addr
= imm
+ 4 + (memaddr
& relmask
);
544 (*info
->print_address_func
) (disp_pc_addr
, info
);
547 fprintf_fn (stream
, "@(r0,r%d)", rn
);
550 fprintf_fn (stream
, "@(r0,r%d)", rm
);
553 fprintf_fn (stream
, "@(%d,gbr)", imm
);
556 fprintf_fn (stream
, "@(r0,gbr)");
560 (*info
->print_address_func
) (imm
+ memaddr
, info
);
563 fprintf_fn (stream
, "sr");
566 fprintf_fn (stream
, "gbr");
569 fprintf_fn (stream
, "vbr");
572 fprintf_fn (stream
, "dsr");
575 fprintf_fn (stream
, "mod");
578 fprintf_fn (stream
, "re");
581 fprintf_fn (stream
, "rs");
584 fprintf_fn (stream
, "a0");
587 fprintf_fn (stream
, "x0");
590 fprintf_fn (stream
, "x1");
593 fprintf_fn (stream
, "y0");
596 fprintf_fn (stream
, "y1");
599 print_dsp_reg (rm
, fprintf_fn
, stream
);
602 fprintf_fn (stream
, "ssr");
605 fprintf_fn (stream
, "spc");
608 fprintf_fn (stream
, "mach");
611 fprintf_fn (stream
, "macl");
614 fprintf_fn (stream
, "pr");
617 fprintf_fn (stream
, "sgr");
620 fprintf_fn (stream
, "dbr");
623 fprintf_fn (stream
, "fr%d", rn
);
626 fprintf_fn (stream
, "fr%d", rm
);
631 fprintf_fn (stream
, "xd%d", rn
& ~1);
635 fprintf_fn (stream
, "dr%d", rn
);
640 fprintf_fn (stream
, "xd%d", rm
& ~1);
644 fprintf_fn (stream
, "dr%d", rm
);
648 fprintf_fn (stream
, "fpscr");
652 fprintf_fn (stream
, "fpul");
655 fprintf_fn (stream
, "fr0");
658 fprintf_fn (stream
, "fv%d", rn
* 4);
661 fprintf_fn (stream
, "fv%d", rm
* 4);
664 fprintf_fn (stream
, "xmtrx");
672 /* This code prints instructions in delay slots on the same line
673 as the instruction which needs the delay slots. This can be
674 confusing, since other disassembler don't work this way, and
675 it means that the instructions are not all in a line. So I
677 if (!(info
->flags
& 1)
678 && (op
->name
[0] == 'j'
679 || (op
->name
[0] == 'b'
680 && (op
->name
[1] == 'r'
681 || op
->name
[1] == 's'))
682 || (op
->name
[0] == 'r' && op
->name
[1] == 't')
683 || (op
->name
[0] == 'b' && op
->name
[2] == '.')))
686 fprintf_fn (stream
, "\t(slot ");
687 print_insn_sh (memaddr
+ 2, info
);
689 fprintf_fn (stream
, ")");
694 if (disp_pc
&& strcmp (op
->name
, "mova") != 0)
699 if (relmask
== ~(bfd_vma
) 1)
703 status
= info
->read_memory_func (disp_pc_addr
, bytes
, size
, info
);
710 if (info
->endian
== BFD_ENDIAN_LITTLE
)
711 val
= bfd_getl16 (bytes
);
713 val
= bfd_getb16 (bytes
);
717 if (info
->endian
== BFD_ENDIAN_LITTLE
)
718 val
= bfd_getl32 (bytes
);
720 val
= bfd_getb32 (bytes
);
722 fprintf_fn (stream
, "\t! 0x%x", val
);
731 fprintf_fn (stream
, ".word 0x%x%x%x%x", nibs
[0], nibs
[1], nibs
[2], nibs
[3]);
This page took 0.044299 seconds and 5 git commands to generate.