1 /* Disassemble SPU instructions
3 Copyright 2006 Free Software Foundation, Inc.
5 This file is part of GDB, GAS, and the GNU binutils.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
24 #include "opcode/spu.h"
26 /* This file provides a disassembler function which uses
27 the disassembler interface defined in dis-asm.h. */
29 extern const struct spu_opcode spu_opcodes
[];
30 extern const int spu_num_opcodes
;
32 static const struct spu_opcode
*spu_disassemble_table
[(1<<11)];
35 init_spu_disassemble (void)
39 /* If two instructions have the same opcode then we prefer the first
40 * one. In most cases it is just an alternate mnemonic. */
41 for (i
= 0; i
< spu_num_opcodes
; i
++)
43 int o
= spu_opcodes
[i
].opcode
;
46 if (spu_disassemble_table
[o
] == 0)
47 spu_disassemble_table
[o
] = &spu_opcodes
[i
];
51 /* Determine the instruction from the 10 least significant bits. */
52 static const struct spu_opcode
*
53 get_index_for_opcode (unsigned int insn
)
55 const struct spu_opcode
*index
;
56 unsigned int opcode
= insn
>> (32-11);
58 /* Init the table. This assumes that element 0/opcode 0 (currently
59 * NOP) is always used */
60 if (spu_disassemble_table
[0] == 0)
61 init_spu_disassemble ();
63 if ((index
= spu_disassemble_table
[opcode
& 0x780]) != 0
64 && index
->insn_type
== RRR
)
67 if ((index
= spu_disassemble_table
[opcode
& 0x7f0]) != 0
68 && (index
->insn_type
== RI18
|| index
->insn_type
== LBT
))
71 if ((index
= spu_disassemble_table
[opcode
& 0x7f8]) != 0
72 && index
->insn_type
== RI10
)
75 if ((index
= spu_disassemble_table
[opcode
& 0x7fc]) != 0
76 && (index
->insn_type
== RI16
))
79 if ((index
= spu_disassemble_table
[opcode
& 0x7fe]) != 0
80 && (index
->insn_type
== RI8
))
83 if ((index
= spu_disassemble_table
[opcode
& 0x7ff]) != 0)
89 /* Print a Spu instruction. */
92 print_insn_spu (bfd_vma memaddr
, struct disassemble_info
*info
)
99 const struct spu_opcode
*index
;
102 status
= (*info
->read_memory_func
) (memaddr
, buffer
, 4, info
);
105 (*info
->memory_error_func
) (status
, memaddr
, info
);
109 insn
= bfd_getb32 (buffer
);
111 index
= get_index_for_opcode (insn
);
115 (*info
->fprintf_func
) (info
->stream
, ".long 0x%x", insn
);
121 tag
= (enum spu_insns
)(index
- spu_opcodes
);
122 (*info
->fprintf_func
) (info
->stream
, "%s", index
->mnemonic
);
123 if (tag
== M_BI
|| tag
== M_BISL
|| tag
== M_IRET
|| tag
== M_BISLED
124 || tag
== M_BIHNZ
|| tag
== M_BIHZ
|| tag
== M_BINZ
|| tag
== M_BIZ
125 || tag
== M_SYNC
|| tag
== M_HBR
)
127 int fb
= (insn
>> (32-18)) & 0x7f;
129 (*info
->fprintf_func
) (info
->stream
, tag
== M_SYNC
? "c" : "p");
131 (*info
->fprintf_func
) (info
->stream
, "d");
133 (*info
->fprintf_func
) (info
->stream
, "e");
135 if (index
->arg
[0] != 0)
136 (*info
->fprintf_func
) (info
->stream
, "\t");
138 for (i
= 1; i
<= index
->arg
[0]; i
++)
140 int arg
= index
->arg
[i
];
141 if (arg
!= A_P
&& !paren
&& i
> 1)
142 (*info
->fprintf_func
) (info
->stream
, ",");
147 (*info
->fprintf_func
) (info
->stream
, "$%d",
148 DECODE_INSN_RT (insn
));
151 (*info
->fprintf_func
) (info
->stream
, "$%d",
152 DECODE_INSN_RA (insn
));
155 (*info
->fprintf_func
) (info
->stream
, "$%d",
156 DECODE_INSN_RB (insn
));
159 (*info
->fprintf_func
) (info
->stream
, "$%d",
160 DECODE_INSN_RC (insn
));
163 (*info
->fprintf_func
) (info
->stream
, "$sp%d",
164 DECODE_INSN_RA (insn
));
167 (*info
->fprintf_func
) (info
->stream
, "$ch%d",
168 DECODE_INSN_RA (insn
));
172 (*info
->fprintf_func
) (info
->stream
, "(");
175 (*info
->fprintf_func
) (info
->stream
, "%d",
176 173 - DECODE_INSN_U8 (insn
));
179 (*info
->fprintf_func
) (info
->stream
, "%d",
180 155 - DECODE_INSN_U8 (insn
));
190 hex_value
= DECODE_INSN_I7 (insn
);
191 (*info
->fprintf_func
) (info
->stream
, "%d", hex_value
);
194 (*info
->print_address_func
) (memaddr
+ DECODE_INSN_I9a (insn
) * 4,
198 (*info
->print_address_func
) (memaddr
+ DECODE_INSN_I9b (insn
) * 4,
203 hex_value
= DECODE_INSN_I10 (insn
);
204 (*info
->fprintf_func
) (info
->stream
, "%d", hex_value
);
207 hex_value
= DECODE_INSN_I10 (insn
) * 16;
208 (*info
->fprintf_func
) (info
->stream
, "%d", hex_value
);
211 hex_value
= DECODE_INSN_I16 (insn
);
212 (*info
->fprintf_func
) (info
->stream
, "%d", hex_value
);
215 hex_value
= DECODE_INSN_U16 (insn
);
216 (*info
->fprintf_func
) (info
->stream
, "%u", hex_value
);
219 value
= DECODE_INSN_I16 (insn
) * 4;
221 (*info
->fprintf_func
) (info
->stream
, "%d", value
);
224 hex_value
= memaddr
+ value
;
225 (*info
->print_address_func
) (hex_value
& 0x3ffff, info
);
229 value
= DECODE_INSN_U16 (insn
) * 4;
231 (*info
->fprintf_func
) (info
->stream
, "%d", value
);
233 (*info
->print_address_func
) (value
, info
);
236 value
= DECODE_INSN_U18 (insn
);
237 if (value
== 0 || !(*info
->symbol_at_address_func
)(0, info
))
240 (*info
->fprintf_func
) (info
->stream
, "%u", value
);
243 (*info
->print_address_func
) (value
, info
);
246 hex_value
= DECODE_INSN_U14 (insn
);
247 (*info
->fprintf_func
) (info
->stream
, "%u", hex_value
);
250 if (arg
!= A_P
&& paren
)
252 (*info
->fprintf_func
) (info
->stream
, ")");
257 (*info
->fprintf_func
) (info
->stream
, "\t# %x", hex_value
);