1 /* Disassemble SPU instructions
3 Copyright (C) 2006-2017 Free Software Foundation, Inc.
5 This file is part of the GNU opcodes library.
7 This library 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 3, or (at your option)
12 It is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this file; see the file COPYING. If not, write to the
19 Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
24 #include "disassemble.h"
25 #include "opcode/spu.h"
27 /* This file provides a disassembler function which uses
28 the disassembler interface defined in dis-asm.h. */
30 extern const struct spu_opcode spu_opcodes[];
31 extern const int spu_num_opcodes;
33 static const struct spu_opcode *spu_disassemble_table[(1<<11)];
36 init_spu_disassemble (void)
40 /* If two instructions have the same opcode then we prefer the first
41 * one. In most cases it is just an alternate mnemonic. */
42 for (i = 0; i < spu_num_opcodes; i++)
44 int o = spu_opcodes[i].opcode;
47 if (spu_disassemble_table[o] == 0)
48 spu_disassemble_table[o] = &spu_opcodes[i];
52 /* Determine the instruction from the 10 least significant bits. */
53 static const struct spu_opcode *
54 get_index_for_opcode (unsigned int insn)
56 const struct spu_opcode *op_index;
57 unsigned int opcode = insn >> (32-11);
59 /* Init the table. This assumes that element 0/opcode 0 (currently
60 * NOP) is always used */
61 if (spu_disassemble_table[0] == 0)
62 init_spu_disassemble ();
64 if ((op_index = spu_disassemble_table[opcode & 0x780]) != 0
65 && op_index->insn_type == RRR)
68 if ((op_index = spu_disassemble_table[opcode & 0x7f0]) != 0
69 && (op_index->insn_type == RI18 || op_index->insn_type == LBT))
72 if ((op_index = spu_disassemble_table[opcode & 0x7f8]) != 0
73 && op_index->insn_type == RI10)
76 if ((op_index = spu_disassemble_table[opcode & 0x7fc]) != 0
77 && (op_index->insn_type == RI16))
80 if ((op_index = spu_disassemble_table[opcode & 0x7fe]) != 0
81 && (op_index->insn_type == RI8))
84 if ((op_index = spu_disassemble_table[opcode & 0x7ff]) != 0)
90 /* Print a Spu instruction. */
93 print_insn_spu (bfd_vma memaddr, struct disassemble_info *info)
100 const struct spu_opcode *op_index;
103 status = (*info->read_memory_func) (memaddr, buffer, 4, info);
106 (*info->memory_error_func) (status, memaddr, info);
110 insn = bfd_getb32 (buffer);
112 op_index = get_index_for_opcode (insn);
116 (*info->fprintf_func) (info->stream, ".long 0x%x", insn);
122 tag = (enum spu_insns)(op_index - spu_opcodes);
123 (*info->fprintf_func) (info->stream, "%s", op_index->mnemonic);
124 if (tag == M_BI || tag == M_BISL || tag == M_IRET || tag == M_BISLED
125 || tag == M_BIHNZ || tag == M_BIHZ || tag == M_BINZ || tag == M_BIZ
126 || tag == M_SYNC || tag == M_HBR)
128 int fb = (insn >> (32-18)) & 0x7f;
130 (*info->fprintf_func) (info->stream, tag == M_SYNC ? "c" : "p");
132 (*info->fprintf_func) (info->stream, "d");
134 (*info->fprintf_func) (info->stream, "e");
136 if (op_index->arg[0] != 0)
137 (*info->fprintf_func) (info->stream, "\t");
139 for (i = 1; i <= op_index->arg[0]; i++)
141 int arg = op_index->arg[i];
142 if (arg != A_P && !paren && i > 1)
143 (*info->fprintf_func) (info->stream, ",");
148 (*info->fprintf_func) (info->stream, "$%d",
149 DECODE_INSN_RT (insn));
152 (*info->fprintf_func) (info->stream, "$%d",
153 DECODE_INSN_RA (insn));
156 (*info->fprintf_func) (info->stream, "$%d",
157 DECODE_INSN_RB (insn));
160 (*info->fprintf_func) (info->stream, "$%d",
161 DECODE_INSN_RC (insn));
164 (*info->fprintf_func) (info->stream, "$sp%d",
165 DECODE_INSN_RA (insn));
168 (*info->fprintf_func) (info->stream, "$ch%d",
169 DECODE_INSN_RA (insn));
173 (*info->fprintf_func) (info->stream, "(");
176 (*info->fprintf_func) (info->stream, "%d",
177 173 - DECODE_INSN_U8 (insn));
180 (*info->fprintf_func) (info->stream, "%d",
181 155 - DECODE_INSN_U8 (insn));
191 hex_value = DECODE_INSN_I7 (insn);
192 (*info->fprintf_func) (info->stream, "%d", hex_value);
195 (*info->print_address_func) (memaddr + DECODE_INSN_I9a (insn) * 4,
199 (*info->print_address_func) (memaddr + DECODE_INSN_I9b (insn) * 4,
204 hex_value = DECODE_INSN_I10 (insn);
205 (*info->fprintf_func) (info->stream, "%d", hex_value);
208 hex_value = DECODE_INSN_I10 (insn) * 16;
209 (*info->fprintf_func) (info->stream, "%d", hex_value);
212 hex_value = DECODE_INSN_I16 (insn);
213 (*info->fprintf_func) (info->stream, "%d", hex_value);
216 hex_value = DECODE_INSN_U16 (insn);
217 (*info->fprintf_func) (info->stream, "%u", hex_value);
220 value = DECODE_INSN_I16 (insn) * 4;
222 (*info->fprintf_func) (info->stream, "%d", value);
225 hex_value = memaddr + value;
226 (*info->print_address_func) (hex_value & 0x3ffff, info);
230 value = DECODE_INSN_U16 (insn) * 4;
232 (*info->fprintf_func) (info->stream, "%d", value);
234 (*info->print_address_func) (value, info);
237 value = DECODE_INSN_U18 (insn);
238 if (value == 0 || !(*info->symbol_at_address_func)(0, info))
241 (*info->fprintf_func) (info->stream, "%u", value);
244 (*info->print_address_func) (value, info);
247 hex_value = DECODE_INSN_U14 (insn);
248 (*info->fprintf_func) (info->stream, "%u", hex_value);
251 if (arg != A_P && paren)
253 (*info->fprintf_func) (info->stream, ")");
258 (*info->fprintf_func) (info->stream, "\t# %x", hex_value);