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. */
29 static void print_movxy
30 PARAMS ((sh_opcode_info
*, int, int, fprintf_ftype
, void *));
31 static void print_insn_ddt
PARAMS ((int, struct disassemble_info
*));
32 static void print_dsp_reg
PARAMS ((int, fprintf_ftype
, void *));
33 static void print_insn_ppi
PARAMS ((int, struct disassemble_info
*));
34 static int print_insn_shx
PARAMS ((bfd_vma
, struct disassemble_info
*));
37 print_movxy (op
, rn
, rm
, fprintf_fn
, stream
)
40 fprintf_ftype fprintf_fn
;
45 fprintf_fn (stream
, "%s\t", op
->name
);
46 for (n
= 0; n
< 2; n
++)
51 fprintf_fn (stream
, "@r%d", rn
);
54 fprintf_fn (stream
, "@r%d+", rn
);
57 fprintf_fn (stream
, "@r%d+r8", rn
);
60 fprintf_fn (stream
, "@r%d+r9", rn
);
63 fprintf_fn (stream
, "a%c", '0' + rm
);
66 fprintf_fn (stream
, "x%c", '0' + rm
);
69 fprintf_fn (stream
, "y%c", '0' + rm
);
75 fprintf_fn (stream
, ",");
79 /* Print a double data transfer insn. INSN is just the lower three
80 nibbles of the insn, i.e. field a and the bit that indicates if
81 a parallel processing insn follows.
82 Return nonzero if a field b of a parallel processing insns follows. */
85 print_insn_ddt (insn
, info
)
87 struct disassemble_info
*info
;
89 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
90 void *stream
= info
->stream
;
92 /* If this is just a nop, make sure to emit something. */
94 fprintf_fn (stream
, "nopx\tnopy");
96 /* If a parallel processing insn was printed before,
97 and we got a non-nop, emit a tab. */
98 if ((insn
& 0x800) && (insn
& 0x3ff))
99 fprintf_fn (stream
, "\t");
101 /* Check if either the x or y part is invalid. */
102 if (((insn
& 0xc) == 0 && (insn
& 0x2a0))
103 || ((insn
& 3) == 0 && (insn
& 0x150)))
104 fprintf_fn (stream
, ".word 0x%x", insn
);
107 static sh_opcode_info
*first_movx
, *first_movy
;
108 sh_opcode_info
*opx
, *opy
;
109 unsigned int insn_x
, insn_y
;
113 for (first_movx
= sh_table
; first_movx
->nibbles
[1] != MOVX
;)
115 for (first_movy
= first_movx
; first_movy
->nibbles
[1] != MOVY
;)
118 insn_x
= (insn
>> 2) & 0xb;
121 for (opx
= first_movx
; opx
->nibbles
[2] != insn_x
;)
123 print_movxy (opx
, ((insn
>> 9) & 1) + 4, (insn
>> 7) & 1,
126 insn_y
= (insn
& 3) | ((insn
>> 1) & 8);
130 fprintf_fn (stream
, "\t");
131 for (opy
= first_movy
; opy
->nibbles
[2] != insn_y
;)
133 print_movxy (opy
, ((insn
>> 8) & 1) + 6, (insn
>> 6) & 1,
140 print_dsp_reg (rm
, fprintf_fn
, stream
)
142 fprintf_ftype fprintf_fn
;
148 fprintf_fn (stream
, "a1");
151 fprintf_fn (stream
, "a0");
154 fprintf_fn (stream
, "x0");
157 fprintf_fn (stream
, "x1");
160 fprintf_fn (stream
, "y0");
163 fprintf_fn (stream
, "y1");
166 fprintf_fn (stream
, "m0");
169 fprintf_fn (stream
, "a1g");
172 fprintf_fn (stream
, "m1");
175 fprintf_fn (stream
, "a0g");
178 fprintf_fn (stream
, "0x%x", rm
);
184 print_insn_ppi (field_b
, info
)
186 struct disassemble_info
*info
;
188 static char *sx_tab
[] = { "x0", "x1", "a0", "a1" };
189 static char *sy_tab
[] = { "y0", "y1", "m0", "m1" };
190 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
191 void *stream
= info
->stream
;
192 unsigned int nib1
, nib2
, nib3
;
196 if ((field_b
& 0xe800) == 0)
198 fprintf_fn (stream
, "psh%c\t#%d,",
199 field_b
& 0x1000 ? 'a' : 'l',
200 (field_b
>> 4) & 127);
201 print_dsp_reg (field_b
& 0xf, fprintf_fn
, stream
);
204 if ((field_b
& 0xc000) == 0x4000 && (field_b
& 0x3000) != 0x1000)
206 static char *du_tab
[] = { "x0", "y0", "a0", "a1" };
207 static char *se_tab
[] = { "x0", "x1", "y0", "a1" };
208 static char *sf_tab
[] = { "y0", "y1", "x0", "a1" };
209 static char *sg_tab
[] = { "m0", "m1", "a0", "a1" };
211 if (field_b
& 0x2000)
213 fprintf_fn (stream
, "p%s %s,%s,%s\t",
214 (field_b
& 0x1000) ? "add" : "sub",
215 sx_tab
[(field_b
>> 6) & 3],
216 sy_tab
[(field_b
>> 4) & 3],
217 du_tab
[(field_b
>> 0) & 3]);
219 fprintf_fn (stream
, "pmuls%c%s,%s,%s",
220 field_b
& 0x2000 ? ' ' : '\t',
221 se_tab
[(field_b
>> 10) & 3],
222 sf_tab
[(field_b
>> 8) & 3],
223 sg_tab
[(field_b
>> 2) & 3]);
228 nib2
= field_b
>> 12 & 0xf;
229 nib3
= field_b
>> 8 & 0xf;
248 for (op
= sh_table
; op
->name
; op
++)
250 if (op
->nibbles
[1] == nib1
251 && op
->nibbles
[2] == nib2
252 && op
->nibbles
[3] == nib3
)
256 fprintf_fn (stream
, "%s%s\t", dc
, op
->name
);
257 for (n
= 0; n
< 3 && op
->arg
[n
] != A_END
; n
++)
259 if (n
&& op
->arg
[1] != A_END
)
260 fprintf_fn (stream
, ",");
264 print_dsp_reg (field_b
& 0xf, fprintf_fn
, stream
);
267 fprintf_fn (stream
, sx_tab
[(field_b
>> 6) & 3]);
270 fprintf_fn (stream
, sy_tab
[(field_b
>> 4) & 3]);
273 fprintf_fn (stream
, "mach");
276 fprintf_fn (stream
, "macl");
286 fprintf_fn (stream
, ".word 0x%x", field_b
);
290 print_insn_shx (memaddr
, info
)
292 struct disassemble_info
*info
;
294 fprintf_ftype fprintf_fn
= info
->fprintf_func
;
295 void *stream
= info
->stream
;
296 unsigned char insn
[2];
297 unsigned char nibs
[4];
299 bfd_vma relmask
= ~(bfd_vma
) 0;
306 target_arch
= arch_sh1
;
309 target_arch
= arch_sh2
;
311 case bfd_mach_sh_dsp
:
312 target_arch
= arch_sh_dsp
;
315 target_arch
= arch_sh3
;
317 case bfd_mach_sh3_dsp
:
318 target_arch
= arch_sh3_dsp
;
321 target_arch
= arch_sh3e
;
324 target_arch
= arch_sh4
;
327 /* When we get here for sh64, it's because we want to disassemble
328 SHcompact, i.e. arch_sh4. */
329 target_arch
= arch_sh4
;
335 status
= info
->read_memory_func (memaddr
, insn
, 2, info
);
339 info
->memory_error_func (status
, memaddr
, info
);
343 if (info
->flags
& LITTLE_BIT
)
345 nibs
[0] = (insn
[1] >> 4) & 0xf;
346 nibs
[1] = insn
[1] & 0xf;
348 nibs
[2] = (insn
[0] >> 4) & 0xf;
349 nibs
[3] = insn
[0] & 0xf;
353 nibs
[0] = (insn
[0] >> 4) & 0xf;
354 nibs
[1] = insn
[0] & 0xf;
356 nibs
[2] = (insn
[1] >> 4) & 0xf;
357 nibs
[3] = insn
[1] & 0xf;
360 if (nibs
[0] == 0xf && (nibs
[1] & 4) == 0 && target_arch
& arch_sh_dsp_up
)
366 status
= info
->read_memory_func (memaddr
+ 2, insn
, 2, info
);
370 info
->memory_error_func (status
, memaddr
+ 2, info
);
374 if (info
->flags
& LITTLE_BIT
)
375 field_b
= insn
[1] << 8 | insn
[0];
377 field_b
= insn
[0] << 8 | insn
[1];
379 print_insn_ppi (field_b
, info
);
380 print_insn_ddt ((nibs
[1] << 8) | (nibs
[2] << 4) | nibs
[3], info
);
383 print_insn_ddt ((nibs
[1] << 8) | (nibs
[2] << 4) | nibs
[3], info
);
386 for (op
= sh_table
; op
->name
; op
++)
394 bfd_vma disp_pc_addr
= 0;
396 if ((op
->arch
& target_arch
) == 0)
398 for (n
= 0; n
< 4; n
++)
400 int i
= op
->nibbles
[n
];
411 imm
= (nibs
[2] << 4) | (nibs
[3]);
414 imm
= ((char) imm
) * 2 + 4;
417 imm
= ((nibs
[1]) << 8) | (nibs
[2] << 4) | (nibs
[3]);
436 imm
= (nibs
[2] << 4) | nibs
[3];
439 imm
= ((nibs
[2] << 4) | nibs
[3]) << 1;
440 relmask
= ~(bfd_vma
) 1;
443 imm
= ((nibs
[2] << 4) | nibs
[3]) << 2;
444 relmask
= ~(bfd_vma
) 3;
448 imm
= ((nibs
[2] << 4) | nibs
[3]) << 1;
452 imm
= ((nibs
[2] << 4) | nibs
[3]) << 2;
461 rn
= (nibs
[n
] & 0xc) >> 2;
462 rm
= (nibs
[n
] & 0x3);
468 /* sh-dsp: single data transfer. */
473 rn
|= (!(rn
& 2)) << 2;
484 fprintf_fn (stream
, "%s\t", op
->name
);
486 for (n
= 0; n
< 3 && op
->arg
[n
] != A_END
; n
++)
488 if (n
&& op
->arg
[1] != A_END
)
489 fprintf_fn (stream
, ",");
493 fprintf_fn (stream
, "#%d", (char) (imm
));
496 fprintf_fn (stream
, "r0");
499 fprintf_fn (stream
, "r%d", rn
);
502 fprintf_fn (stream
, "@r%d+", rn
);
505 fprintf_fn (stream
, "@-r%d", rn
);
508 fprintf_fn (stream
, "@r%d", rn
);
511 fprintf_fn (stream
, "@(%d,r%d)", imm
, rn
);
514 fprintf_fn (stream
, "@r%d+r8", rn
);
517 fprintf_fn (stream
, "r%d", rm
);
520 fprintf_fn (stream
, "@r%d+", rm
);
523 fprintf_fn (stream
, "@-r%d", rm
);
526 fprintf_fn (stream
, "@r%d", rm
);
529 fprintf_fn (stream
, "@(%d,r%d)", imm
, rm
);
532 fprintf_fn (stream
, "r%d_bank", rb
);
536 disp_pc_addr
= imm
+ 4 + (memaddr
& relmask
);
537 (*info
->print_address_func
) (disp_pc_addr
, info
);
540 fprintf_fn (stream
, "@(r0,r%d)", rn
);
543 fprintf_fn (stream
, "@(r0,r%d)", rm
);
546 fprintf_fn (stream
, "@(%d,gbr)", imm
);
549 fprintf_fn (stream
, "@(r0,gbr)");
553 (*info
->print_address_func
) (imm
+ memaddr
, info
);
556 fprintf_fn (stream
, "sr");
559 fprintf_fn (stream
, "gbr");
562 fprintf_fn (stream
, "vbr");
565 fprintf_fn (stream
, "dsr");
568 fprintf_fn (stream
, "mod");
571 fprintf_fn (stream
, "re");
574 fprintf_fn (stream
, "rs");
577 fprintf_fn (stream
, "a0");
580 fprintf_fn (stream
, "x0");
583 fprintf_fn (stream
, "x1");
586 fprintf_fn (stream
, "y0");
589 fprintf_fn (stream
, "y1");
592 print_dsp_reg (rm
, fprintf_fn
, stream
);
595 fprintf_fn (stream
, "ssr");
598 fprintf_fn (stream
, "spc");
601 fprintf_fn (stream
, "mach");
604 fprintf_fn (stream
, "macl");
607 fprintf_fn (stream
, "pr");
610 fprintf_fn (stream
, "sgr");
613 fprintf_fn (stream
, "dbr");
616 fprintf_fn (stream
, "fr%d", rn
);
619 fprintf_fn (stream
, "fr%d", rm
);
624 fprintf_fn (stream
, "xd%d", rn
& ~1);
628 fprintf_fn (stream
, "dr%d", rn
);
633 fprintf_fn (stream
, "xd%d", rm
& ~1);
637 fprintf_fn (stream
, "dr%d", rm
);
641 fprintf_fn (stream
, "fpscr");
645 fprintf_fn (stream
, "fpul");
648 fprintf_fn (stream
, "fr0");
651 fprintf_fn (stream
, "fv%d", rn
* 4);
654 fprintf_fn (stream
, "fv%d", rm
* 4);
657 fprintf_fn (stream
, "xmtrx");
665 /* This code prints instructions in delay slots on the same line
666 as the instruction which needs the delay slots. This can be
667 confusing, since other disassembler don't work this way, and
668 it means that the instructions are not all in a line. So I
670 if (!(info
->flags
& 1)
671 && (op
->name
[0] == 'j'
672 || (op
->name
[0] == 'b'
673 && (op
->name
[1] == 'r'
674 || op
->name
[1] == 's'))
675 || (op
->name
[0] == 'r' && op
->name
[1] == 't')
676 || (op
->name
[0] == 'b' && op
->name
[2] == '.')))
679 fprintf_fn (stream
, "\t(slot ");
680 print_insn_shx (memaddr
+ 2, info
);
682 fprintf_fn (stream
, ")");
687 if (disp_pc
&& strcmp (op
->name
, "mova") != 0)
692 if (relmask
== ~(bfd_vma
) 1)
696 status
= info
->read_memory_func (disp_pc_addr
, bytes
, size
, info
);
703 if ((info
->flags
& LITTLE_BIT
) != 0)
704 val
= bfd_getl16 (bytes
);
706 val
= bfd_getb16 (bytes
);
710 if ((info
->flags
& LITTLE_BIT
) != 0)
711 val
= bfd_getl32 (bytes
);
713 val
= bfd_getb32 (bytes
);
715 fprintf_fn (stream
, "\t! 0x%x", val
);
724 fprintf_fn (stream
, ".word 0x%x%x%x%x", nibs
[0], nibs
[1], nibs
[2], nibs
[3]);
729 print_insn_shl (memaddr
, info
)
731 struct disassemble_info
*info
;
735 info
->flags
= LITTLE_BIT
;
736 r
= print_insn_shx (memaddr
, info
);
741 print_insn_sh (memaddr
, info
)
743 struct disassemble_info
*info
;
748 r
= print_insn_shx (memaddr
, info
);
This page took 0.044618 seconds and 4 git commands to generate.