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
++)
52 fprintf_fn (stream
, "@r%d", rn
);
55 fprintf_fn (stream
, "@r%d+", rn
);
58 fprintf_fn (stream
, "@r%d+r8", rn
);
61 fprintf_fn (stream
, "@r%d+r9", rn
);
64 fprintf_fn (stream
, "a%c", '0' + rm
);
67 fprintf_fn (stream
, "x%c", '0' + rm
);
70 fprintf_fn (stream
, "y%c", '0' + rm
);
76 fprintf_fn (stream
, ",");
80 /* Print a double data transfer insn. INSN is just the lower three
81 nibbles of the insn, i.e. field a and the bit that indicates if
82 a parallel processing insn follows.
83 Return nonzero if a field b of a parallel processing insns follows. */
86 print_insn_ddt (insn
, info
)
88 struct disassemble_info
*info
;
90 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
91 void *stream
= info
->stream
;
93 /* If this is just a nop, make sure to emit something. */
95 fprintf_fn (stream
, "nopx\tnopy");
97 /* If a parallel processing insn was printed before,
98 and we got a non-nop, emit a tab. */
99 if ((insn
& 0x800) && (insn
& 0x3ff))
100 fprintf_fn (stream
, "\t");
102 /* Check if either the x or y part is invalid. */
103 if (((insn
& 0xc) == 0 && (insn
& 0x2a0))
104 || ((insn
& 3) == 0 && (insn
& 0x150)))
105 fprintf_fn (stream
, ".word 0x%x", insn
);
108 static const sh_opcode_info
*first_movx
, *first_movy
;
109 const sh_opcode_info
*opx
, *opy
;
110 unsigned int insn_x
, insn_y
;
114 for (first_movx
= sh_table
; first_movx
->nibbles
[1] != MOVX
;)
116 for (first_movy
= first_movx
; first_movy
->nibbles
[1] != MOVY
;)
119 insn_x
= (insn
>> 2) & 0xb;
122 for (opx
= first_movx
; opx
->nibbles
[2] != insn_x
;)
124 print_movxy (opx
, ((insn
>> 9) & 1) + 4, (insn
>> 7) & 1,
127 insn_y
= (insn
& 3) | ((insn
>> 1) & 8);
131 fprintf_fn (stream
, "\t");
132 for (opy
= first_movy
; opy
->nibbles
[2] != insn_y
;)
134 print_movxy (opy
, ((insn
>> 8) & 1) + 6, (insn
>> 6) & 1,
141 print_dsp_reg (rm
, fprintf_fn
, stream
)
143 fprintf_ftype fprintf_fn
;
149 fprintf_fn (stream
, "a1");
152 fprintf_fn (stream
, "a0");
155 fprintf_fn (stream
, "x0");
158 fprintf_fn (stream
, "x1");
161 fprintf_fn (stream
, "y0");
164 fprintf_fn (stream
, "y1");
167 fprintf_fn (stream
, "m0");
170 fprintf_fn (stream
, "a1g");
173 fprintf_fn (stream
, "m1");
176 fprintf_fn (stream
, "a0g");
179 fprintf_fn (stream
, "0x%x", rm
);
185 print_insn_ppi (field_b
, info
)
187 struct disassemble_info
*info
;
189 static char *sx_tab
[] = { "x0", "x1", "a0", "a1" };
190 static char *sy_tab
[] = { "y0", "y1", "m0", "m1" };
191 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
192 void *stream
= info
->stream
;
193 unsigned int nib1
, nib2
, nib3
;
195 const sh_opcode_info
*op
;
197 if ((field_b
& 0xe800) == 0)
199 fprintf_fn (stream
, "psh%c\t#%d,",
200 field_b
& 0x1000 ? 'a' : 'l',
201 (field_b
>> 4) & 127);
202 print_dsp_reg (field_b
& 0xf, fprintf_fn
, stream
);
205 if ((field_b
& 0xc000) == 0x4000 && (field_b
& 0x3000) != 0x1000)
207 static char *du_tab
[] = { "x0", "y0", "a0", "a1" };
208 static char *se_tab
[] = { "x0", "x1", "y0", "a1" };
209 static char *sf_tab
[] = { "y0", "y1", "x0", "a1" };
210 static char *sg_tab
[] = { "m0", "m1", "a0", "a1" };
212 if (field_b
& 0x2000)
214 fprintf_fn (stream
, "p%s %s,%s,%s\t",
215 (field_b
& 0x1000) ? "add" : "sub",
216 sx_tab
[(field_b
>> 6) & 3],
217 sy_tab
[(field_b
>> 4) & 3],
218 du_tab
[(field_b
>> 0) & 3]);
220 fprintf_fn (stream
, "pmuls%c%s,%s,%s",
221 field_b
& 0x2000 ? ' ' : '\t',
222 se_tab
[(field_b
>> 10) & 3],
223 sf_tab
[(field_b
>> 8) & 3],
224 sg_tab
[(field_b
>> 2) & 3]);
229 nib2
= field_b
>> 12 & 0xf;
230 nib3
= field_b
>> 8 & 0xf;
249 for (op
= sh_table
; op
->name
; op
++)
251 if (op
->nibbles
[1] == nib1
252 && op
->nibbles
[2] == nib2
253 && op
->nibbles
[3] == nib3
)
257 fprintf_fn (stream
, "%s%s\t", dc
, op
->name
);
258 for (n
= 0; n
< 3 && op
->arg
[n
] != A_END
; n
++)
260 if (n
&& op
->arg
[1] != A_END
)
261 fprintf_fn (stream
, ",");
265 print_dsp_reg (field_b
& 0xf, fprintf_fn
, stream
);
268 fprintf_fn (stream
, sx_tab
[(field_b
>> 6) & 3]);
271 fprintf_fn (stream
, sy_tab
[(field_b
>> 4) & 3]);
274 fprintf_fn (stream
, "mach");
277 fprintf_fn (stream
, "macl");
287 fprintf_fn (stream
, ".word 0x%x", field_b
);
291 print_insn_sh (memaddr
, info
)
293 struct disassemble_info
*info
;
295 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
296 void *stream
= info
->stream
;
297 unsigned char insn
[2];
298 unsigned char nibs
[4];
300 bfd_vma relmask
= ~(bfd_vma
) 0;
301 const sh_opcode_info
*op
;
307 target_arch
= arch_sh1
;
308 /* SH coff object files lack information about the machine type, so
309 we end up with bfd_mach_sh unless it was set explicitly (which
310 could have happended if this is a call from gdb or the simulator.) */
312 && bfd_asymbol_flavour(*info
->symbols
) == bfd_target_coff_flavour
)
313 target_arch
= arch_sh4
;
316 target_arch
= arch_sh2
;
319 target_arch
= arch_sh2e
;
321 case bfd_mach_sh_dsp
:
322 target_arch
= arch_sh_dsp
;
325 target_arch
= arch_sh3
;
327 case bfd_mach_sh3_dsp
:
328 target_arch
= arch_sh3_dsp
;
331 target_arch
= arch_sh3e
;
334 target_arch
= arch_sh4
;
337 #ifdef INCLUDE_SHMEDIA
338 status
= print_insn_sh64 (memaddr
, info
);
342 /* When we get here for sh64, it's because we want to disassemble
343 SHcompact, i.e. arch_sh4. */
344 target_arch
= arch_sh4
;
350 status
= info
->read_memory_func (memaddr
, insn
, 2, info
);
354 info
->memory_error_func (status
, memaddr
, info
);
358 if (info
->endian
== BFD_ENDIAN_LITTLE
)
360 nibs
[0] = (insn
[1] >> 4) & 0xf;
361 nibs
[1] = insn
[1] & 0xf;
363 nibs
[2] = (insn
[0] >> 4) & 0xf;
364 nibs
[3] = insn
[0] & 0xf;
368 nibs
[0] = (insn
[0] >> 4) & 0xf;
369 nibs
[1] = insn
[0] & 0xf;
371 nibs
[2] = (insn
[1] >> 4) & 0xf;
372 nibs
[3] = insn
[1] & 0xf;
375 if (nibs
[0] == 0xf && (nibs
[1] & 4) == 0 && target_arch
& arch_sh_dsp_up
)
381 status
= info
->read_memory_func (memaddr
+ 2, insn
, 2, info
);
385 info
->memory_error_func (status
, memaddr
+ 2, info
);
389 if (info
->endian
== BFD_ENDIAN_LITTLE
)
390 field_b
= insn
[1] << 8 | insn
[0];
392 field_b
= insn
[0] << 8 | insn
[1];
394 print_insn_ppi (field_b
, info
);
395 print_insn_ddt ((nibs
[1] << 8) | (nibs
[2] << 4) | nibs
[3], info
);
398 print_insn_ddt ((nibs
[1] << 8) | (nibs
[2] << 4) | nibs
[3], info
);
401 for (op
= sh_table
; op
->name
; op
++)
409 bfd_vma disp_pc_addr
= 0;
411 if ((op
->arch
& target_arch
) == 0)
413 for (n
= 0; n
< 4; n
++)
415 int i
= op
->nibbles
[n
];
426 imm
= (nibs
[2] << 4) | (nibs
[3]);
429 imm
= ((char) imm
) * 2 + 4;
432 imm
= ((nibs
[1]) << 8) | (nibs
[2] << 4) | (nibs
[3]);
451 imm
= (nibs
[2] << 4) | nibs
[3];
454 imm
= ((nibs
[2] << 4) | nibs
[3]) << 1;
455 relmask
= ~(bfd_vma
) 1;
458 imm
= ((nibs
[2] << 4) | nibs
[3]) << 2;
459 relmask
= ~(bfd_vma
) 3;
463 imm
= ((nibs
[2] << 4) | nibs
[3]) << 1;
467 imm
= ((nibs
[2] << 4) | nibs
[3]) << 2;
476 rn
= (nibs
[n
] & 0xc) >> 2;
477 rm
= (nibs
[n
] & 0x3);
483 /* sh-dsp: single data transfer. */
488 rn
|= (!(rn
& 2)) << 2;
499 fprintf_fn (stream
, "%s\t", op
->name
);
501 for (n
= 0; n
< 3 && op
->arg
[n
] != A_END
; n
++)
503 if (n
&& op
->arg
[1] != A_END
)
504 fprintf_fn (stream
, ",");
508 fprintf_fn (stream
, "#%d", (char) (imm
));
511 fprintf_fn (stream
, "r0");
514 fprintf_fn (stream
, "r%d", rn
);
517 fprintf_fn (stream
, "@r%d+", rn
);
520 fprintf_fn (stream
, "@-r%d", rn
);
523 fprintf_fn (stream
, "@r%d", rn
);
526 fprintf_fn (stream
, "@(%d,r%d)", imm
, rn
);
529 fprintf_fn (stream
, "@r%d+r8", rn
);
532 fprintf_fn (stream
, "r%d", rm
);
535 fprintf_fn (stream
, "@r%d+", rm
);
538 fprintf_fn (stream
, "@-r%d", rm
);
541 fprintf_fn (stream
, "@r%d", rm
);
544 fprintf_fn (stream
, "@(%d,r%d)", imm
, rm
);
547 fprintf_fn (stream
, "r%d_bank", rb
);
551 disp_pc_addr
= imm
+ 4 + (memaddr
& relmask
);
552 (*info
->print_address_func
) (disp_pc_addr
, info
);
555 fprintf_fn (stream
, "@(r0,r%d)", rn
);
558 fprintf_fn (stream
, "@(r0,r%d)", rm
);
561 fprintf_fn (stream
, "@(%d,gbr)", imm
);
564 fprintf_fn (stream
, "@(r0,gbr)");
568 (*info
->print_address_func
) (imm
+ memaddr
, info
);
571 fprintf_fn (stream
, "sr");
574 fprintf_fn (stream
, "gbr");
577 fprintf_fn (stream
, "vbr");
580 fprintf_fn (stream
, "dsr");
583 fprintf_fn (stream
, "mod");
586 fprintf_fn (stream
, "re");
589 fprintf_fn (stream
, "rs");
592 fprintf_fn (stream
, "a0");
595 fprintf_fn (stream
, "x0");
598 fprintf_fn (stream
, "x1");
601 fprintf_fn (stream
, "y0");
604 fprintf_fn (stream
, "y1");
607 print_dsp_reg (rm
, fprintf_fn
, stream
);
610 fprintf_fn (stream
, "ssr");
613 fprintf_fn (stream
, "spc");
616 fprintf_fn (stream
, "mach");
619 fprintf_fn (stream
, "macl");
622 fprintf_fn (stream
, "pr");
625 fprintf_fn (stream
, "sgr");
628 fprintf_fn (stream
, "dbr");
631 fprintf_fn (stream
, "fr%d", rn
);
634 fprintf_fn (stream
, "fr%d", rm
);
639 fprintf_fn (stream
, "xd%d", rn
& ~1);
643 fprintf_fn (stream
, "dr%d", rn
);
648 fprintf_fn (stream
, "xd%d", rm
& ~1);
652 fprintf_fn (stream
, "dr%d", rm
);
656 fprintf_fn (stream
, "fpscr");
660 fprintf_fn (stream
, "fpul");
663 fprintf_fn (stream
, "fr0");
666 fprintf_fn (stream
, "fv%d", rn
* 4);
669 fprintf_fn (stream
, "fv%d", rm
* 4);
672 fprintf_fn (stream
, "xmtrx");
680 /* This code prints instructions in delay slots on the same line
681 as the instruction which needs the delay slots. This can be
682 confusing, since other disassembler don't work this way, and
683 it means that the instructions are not all in a line. So I
685 if (!(info
->flags
& 1)
686 && (op
->name
[0] == 'j'
687 || (op
->name
[0] == 'b'
688 && (op
->name
[1] == 'r'
689 || op
->name
[1] == 's'))
690 || (op
->name
[0] == 'r' && op
->name
[1] == 't')
691 || (op
->name
[0] == 'b' && op
->name
[2] == '.')))
694 fprintf_fn (stream
, "\t(slot ");
695 print_insn_sh (memaddr
+ 2, info
);
697 fprintf_fn (stream
, ")");
702 if (disp_pc
&& strcmp (op
->name
, "mova") != 0)
707 if (relmask
== ~(bfd_vma
) 1)
711 status
= info
->read_memory_func (disp_pc_addr
, bytes
, size
, info
);
718 if (info
->endian
== BFD_ENDIAN_LITTLE
)
719 val
= bfd_getl16 (bytes
);
721 val
= bfd_getb16 (bytes
);
725 if (info
->endian
== BFD_ENDIAN_LITTLE
)
726 val
= bfd_getl32 (bytes
);
728 val
= bfd_getb32 (bytes
);
730 fprintf_fn (stream
, "\t! 0x%x", val
);
739 fprintf_fn (stream
, ".word 0x%x%x%x%x", nibs
[0], nibs
[1], nibs
[2], nibs
[3]);
This page took 0.046089 seconds and 4 git commands to generate.