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.) */
308 && bfd_asymbol_flavour(*info
->symbols
) == bfd_target_coff_flavour
)
309 target_arch
= arch_sh4
;
312 target_arch
= arch_sh2
;
314 case bfd_mach_sh_dsp
:
315 target_arch
= arch_sh_dsp
;
318 target_arch
= arch_sh3
;
320 case bfd_mach_sh3_dsp
:
321 target_arch
= arch_sh3_dsp
;
324 target_arch
= arch_sh3e
;
327 target_arch
= arch_sh4
;
330 #ifdef INCLUDE_SHMEDIA
331 status
= print_insn_sh64 (memaddr
, info
);
335 /* When we get here for sh64, it's because we want to disassemble
336 SHcompact, i.e. arch_sh4. */
337 target_arch
= arch_sh4
;
343 status
= info
->read_memory_func (memaddr
, insn
, 2, info
);
347 info
->memory_error_func (status
, memaddr
, info
);
351 if (info
->endian
== BFD_ENDIAN_LITTLE
)
353 nibs
[0] = (insn
[1] >> 4) & 0xf;
354 nibs
[1] = insn
[1] & 0xf;
356 nibs
[2] = (insn
[0] >> 4) & 0xf;
357 nibs
[3] = insn
[0] & 0xf;
361 nibs
[0] = (insn
[0] >> 4) & 0xf;
362 nibs
[1] = insn
[0] & 0xf;
364 nibs
[2] = (insn
[1] >> 4) & 0xf;
365 nibs
[3] = insn
[1] & 0xf;
368 if (nibs
[0] == 0xf && (nibs
[1] & 4) == 0 && target_arch
& arch_sh_dsp_up
)
374 status
= info
->read_memory_func (memaddr
+ 2, insn
, 2, info
);
378 info
->memory_error_func (status
, memaddr
+ 2, info
);
382 if (info
->endian
== BFD_ENDIAN_LITTLE
)
383 field_b
= insn
[1] << 8 | insn
[0];
385 field_b
= insn
[0] << 8 | insn
[1];
387 print_insn_ppi (field_b
, info
);
388 print_insn_ddt ((nibs
[1] << 8) | (nibs
[2] << 4) | nibs
[3], info
);
391 print_insn_ddt ((nibs
[1] << 8) | (nibs
[2] << 4) | nibs
[3], info
);
394 for (op
= sh_table
; op
->name
; op
++)
402 bfd_vma disp_pc_addr
= 0;
404 if ((op
->arch
& target_arch
) == 0)
406 for (n
= 0; n
< 4; n
++)
408 int i
= op
->nibbles
[n
];
419 imm
= (nibs
[2] << 4) | (nibs
[3]);
422 imm
= ((char) imm
) * 2 + 4;
425 imm
= ((nibs
[1]) << 8) | (nibs
[2] << 4) | (nibs
[3]);
444 imm
= (nibs
[2] << 4) | nibs
[3];
447 imm
= ((nibs
[2] << 4) | nibs
[3]) << 1;
448 relmask
= ~(bfd_vma
) 1;
451 imm
= ((nibs
[2] << 4) | nibs
[3]) << 2;
452 relmask
= ~(bfd_vma
) 3;
456 imm
= ((nibs
[2] << 4) | nibs
[3]) << 1;
460 imm
= ((nibs
[2] << 4) | nibs
[3]) << 2;
469 rn
= (nibs
[n
] & 0xc) >> 2;
470 rm
= (nibs
[n
] & 0x3);
476 /* sh-dsp: single data transfer. */
481 rn
|= (!(rn
& 2)) << 2;
492 fprintf_fn (stream
, "%s\t", op
->name
);
494 for (n
= 0; n
< 3 && op
->arg
[n
] != A_END
; n
++)
496 if (n
&& op
->arg
[1] != A_END
)
497 fprintf_fn (stream
, ",");
501 fprintf_fn (stream
, "#%d", (char) (imm
));
504 fprintf_fn (stream
, "r0");
507 fprintf_fn (stream
, "r%d", rn
);
510 fprintf_fn (stream
, "@r%d+", rn
);
513 fprintf_fn (stream
, "@-r%d", rn
);
516 fprintf_fn (stream
, "@r%d", rn
);
519 fprintf_fn (stream
, "@(%d,r%d)", imm
, rn
);
522 fprintf_fn (stream
, "@r%d+r8", rn
);
525 fprintf_fn (stream
, "r%d", rm
);
528 fprintf_fn (stream
, "@r%d+", rm
);
531 fprintf_fn (stream
, "@-r%d", rm
);
534 fprintf_fn (stream
, "@r%d", rm
);
537 fprintf_fn (stream
, "@(%d,r%d)", imm
, rm
);
540 fprintf_fn (stream
, "r%d_bank", rb
);
544 disp_pc_addr
= imm
+ 4 + (memaddr
& relmask
);
545 (*info
->print_address_func
) (disp_pc_addr
, info
);
548 fprintf_fn (stream
, "@(r0,r%d)", rn
);
551 fprintf_fn (stream
, "@(r0,r%d)", rm
);
554 fprintf_fn (stream
, "@(%d,gbr)", imm
);
557 fprintf_fn (stream
, "@(r0,gbr)");
561 (*info
->print_address_func
) (imm
+ memaddr
, info
);
564 fprintf_fn (stream
, "sr");
567 fprintf_fn (stream
, "gbr");
570 fprintf_fn (stream
, "vbr");
573 fprintf_fn (stream
, "dsr");
576 fprintf_fn (stream
, "mod");
579 fprintf_fn (stream
, "re");
582 fprintf_fn (stream
, "rs");
585 fprintf_fn (stream
, "a0");
588 fprintf_fn (stream
, "x0");
591 fprintf_fn (stream
, "x1");
594 fprintf_fn (stream
, "y0");
597 fprintf_fn (stream
, "y1");
600 print_dsp_reg (rm
, fprintf_fn
, stream
);
603 fprintf_fn (stream
, "ssr");
606 fprintf_fn (stream
, "spc");
609 fprintf_fn (stream
, "mach");
612 fprintf_fn (stream
, "macl");
615 fprintf_fn (stream
, "pr");
618 fprintf_fn (stream
, "sgr");
621 fprintf_fn (stream
, "dbr");
624 fprintf_fn (stream
, "fr%d", rn
);
627 fprintf_fn (stream
, "fr%d", rm
);
632 fprintf_fn (stream
, "xd%d", rn
& ~1);
636 fprintf_fn (stream
, "dr%d", rn
);
641 fprintf_fn (stream
, "xd%d", rm
& ~1);
645 fprintf_fn (stream
, "dr%d", rm
);
649 fprintf_fn (stream
, "fpscr");
653 fprintf_fn (stream
, "fpul");
656 fprintf_fn (stream
, "fr0");
659 fprintf_fn (stream
, "fv%d", rn
* 4);
662 fprintf_fn (stream
, "fv%d", rm
* 4);
665 fprintf_fn (stream
, "xmtrx");
673 /* This code prints instructions in delay slots on the same line
674 as the instruction which needs the delay slots. This can be
675 confusing, since other disassembler don't work this way, and
676 it means that the instructions are not all in a line. So I
678 if (!(info
->flags
& 1)
679 && (op
->name
[0] == 'j'
680 || (op
->name
[0] == 'b'
681 && (op
->name
[1] == 'r'
682 || op
->name
[1] == 's'))
683 || (op
->name
[0] == 'r' && op
->name
[1] == 't')
684 || (op
->name
[0] == 'b' && op
->name
[2] == '.')))
687 fprintf_fn (stream
, "\t(slot ");
688 print_insn_sh (memaddr
+ 2, info
);
690 fprintf_fn (stream
, ")");
695 if (disp_pc
&& strcmp (op
->name
, "mova") != 0)
700 if (relmask
== ~(bfd_vma
) 1)
704 status
= info
->read_memory_func (disp_pc_addr
, bytes
, size
, info
);
711 if (info
->endian
== BFD_ENDIAN_LITTLE
)
712 val
= bfd_getl16 (bytes
);
714 val
= bfd_getb16 (bytes
);
718 if (info
->endian
== BFD_ENDIAN_LITTLE
)
719 val
= bfd_getl32 (bytes
);
721 val
= bfd_getb32 (bytes
);
723 fprintf_fn (stream
, "\t! 0x%x", val
);
732 fprintf_fn (stream
, ".word 0x%x%x%x%x", nibs
[0], nibs
[1], nibs
[2], nibs
[3]);
This page took 0.043946 seconds and 4 git commands to generate.