1*3d8817e4Smiod /* Instruction printing code for the DLX Microprocessor
2*3d8817e4Smiod Copyright 2002, 2005 Free Software Foundation, Inc.
3*3d8817e4Smiod Contributed by Kuang Hwa Lin. Written by Kuang Hwa Lin, 03/2002.
4*3d8817e4Smiod
5*3d8817e4Smiod This program is free software; you can redistribute it and/or modify
6*3d8817e4Smiod it under the terms of the GNU General Public License as published by
7*3d8817e4Smiod the Free Software Foundation; either version 2 of the License, or
8*3d8817e4Smiod (at your option) any later version.
9*3d8817e4Smiod
10*3d8817e4Smiod This program is distributed in the hope that it will be useful,
11*3d8817e4Smiod but WITHOUT ANY WARRANTY; without even the implied warranty of
12*3d8817e4Smiod MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13*3d8817e4Smiod GNU General Public License for more details.
14*3d8817e4Smiod
15*3d8817e4Smiod You should have received a copy of the GNU General Public License
16*3d8817e4Smiod along with this program; if not, write to the Free Software
17*3d8817e4Smiod Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
18*3d8817e4Smiod MA 02110-1301, USA. */
19*3d8817e4Smiod
20*3d8817e4Smiod #include "sysdep.h"
21*3d8817e4Smiod #include "dis-asm.h"
22*3d8817e4Smiod #include "opcode/dlx.h"
23*3d8817e4Smiod
24*3d8817e4Smiod #define R_ERROR 0x1
25*3d8817e4Smiod #define R_TYPE 0x2
26*3d8817e4Smiod #define ILD_TYPE 0x3
27*3d8817e4Smiod #define IST_TYPE 0x4
28*3d8817e4Smiod #define IAL_TYPE 0x5
29*3d8817e4Smiod #define IBR_TYPE 0x6
30*3d8817e4Smiod #define IJ_TYPE 0x7
31*3d8817e4Smiod #define IJR_TYPE 0x8
32*3d8817e4Smiod #define NIL 0x9
33*3d8817e4Smiod
34*3d8817e4Smiod #define OPC(x) ((x >> 26) & 0x3F)
35*3d8817e4Smiod #define FUNC(x) (x & 0x7FF)
36*3d8817e4Smiod
37*3d8817e4Smiod unsigned char opc, rs1, rs2, rd;
38*3d8817e4Smiod unsigned long imm26, imm16, func, current_insn_addr;
39*3d8817e4Smiod
40*3d8817e4Smiod /* Print one instruction from MEMADDR on INFO->STREAM.
41*3d8817e4Smiod Return the size of the instruction (always 4 on dlx). */
42*3d8817e4Smiod
43*3d8817e4Smiod static unsigned char
dlx_get_opcode(unsigned long opcode)44*3d8817e4Smiod dlx_get_opcode (unsigned long opcode)
45*3d8817e4Smiod {
46*3d8817e4Smiod return (unsigned char) ((opcode >> 26) & 0x3F);
47*3d8817e4Smiod }
48*3d8817e4Smiod
49*3d8817e4Smiod static unsigned char
dlx_get_rs1(unsigned long opcode)50*3d8817e4Smiod dlx_get_rs1 (unsigned long opcode)
51*3d8817e4Smiod {
52*3d8817e4Smiod return (unsigned char) ((opcode >> 21) & 0x1F);
53*3d8817e4Smiod }
54*3d8817e4Smiod
55*3d8817e4Smiod static unsigned char
dlx_get_rs2(unsigned long opcode)56*3d8817e4Smiod dlx_get_rs2 (unsigned long opcode)
57*3d8817e4Smiod {
58*3d8817e4Smiod return (unsigned char) ((opcode >> 16) & 0x1F);
59*3d8817e4Smiod }
60*3d8817e4Smiod
61*3d8817e4Smiod static unsigned char
dlx_get_rdR(unsigned long opcode)62*3d8817e4Smiod dlx_get_rdR (unsigned long opcode)
63*3d8817e4Smiod {
64*3d8817e4Smiod return (unsigned char) ((opcode >> 11) & 0x1F);
65*3d8817e4Smiod }
66*3d8817e4Smiod
67*3d8817e4Smiod static unsigned long
dlx_get_func(unsigned long opcode)68*3d8817e4Smiod dlx_get_func (unsigned long opcode)
69*3d8817e4Smiod {
70*3d8817e4Smiod return (unsigned char) (opcode & 0x7FF);
71*3d8817e4Smiod }
72*3d8817e4Smiod
73*3d8817e4Smiod static unsigned long
dlx_get_imm16(unsigned long opcode)74*3d8817e4Smiod dlx_get_imm16 (unsigned long opcode)
75*3d8817e4Smiod {
76*3d8817e4Smiod return (unsigned long) (opcode & 0xFFFF);
77*3d8817e4Smiod }
78*3d8817e4Smiod
79*3d8817e4Smiod static unsigned long
dlx_get_imm26(unsigned long opcode)80*3d8817e4Smiod dlx_get_imm26 (unsigned long opcode)
81*3d8817e4Smiod {
82*3d8817e4Smiod return (unsigned long) (opcode & 0x03FFFFFF);
83*3d8817e4Smiod }
84*3d8817e4Smiod
85*3d8817e4Smiod /* Fill the opcode to the max length. */
86*3d8817e4Smiod
87*3d8817e4Smiod static void
operand_deliminator(struct disassemble_info * info,char * ptr)88*3d8817e4Smiod operand_deliminator (struct disassemble_info *info, char *ptr)
89*3d8817e4Smiod {
90*3d8817e4Smiod int difft = 8 - (int) strlen (ptr);
91*3d8817e4Smiod
92*3d8817e4Smiod while (difft > 0)
93*3d8817e4Smiod {
94*3d8817e4Smiod (*info->fprintf_func) (info->stream, "%c", ' ');
95*3d8817e4Smiod difft -= 1;
96*3d8817e4Smiod }
97*3d8817e4Smiod }
98*3d8817e4Smiod
99*3d8817e4Smiod /* Process the R-type opcode. */
100*3d8817e4Smiod
101*3d8817e4Smiod static unsigned char
dlx_r_type(struct disassemble_info * info)102*3d8817e4Smiod dlx_r_type (struct disassemble_info *info)
103*3d8817e4Smiod {
104*3d8817e4Smiod unsigned char r_opc[] = { OPC(ALUOP) }; /* Fix ME */
105*3d8817e4Smiod int r_opc_num = (sizeof r_opc) / (sizeof (char));
106*3d8817e4Smiod struct _r_opcode
107*3d8817e4Smiod {
108*3d8817e4Smiod unsigned long func;
109*3d8817e4Smiod char *name;
110*3d8817e4Smiod }
111*3d8817e4Smiod dlx_r_opcode[] =
112*3d8817e4Smiod {
113*3d8817e4Smiod { NOPF, "nop" }, /* NOP */
114*3d8817e4Smiod { ADDF, "add" }, /* Add */
115*3d8817e4Smiod { ADDUF, "addu" }, /* Add Unsigned */
116*3d8817e4Smiod { SUBF, "sub" }, /* SUB */
117*3d8817e4Smiod { SUBUF, "subu" }, /* Sub Unsigned */
118*3d8817e4Smiod { MULTF, "mult" }, /* MULTIPLY */
119*3d8817e4Smiod { MULTUF, "multu" }, /* MULTIPLY Unsigned */
120*3d8817e4Smiod { DIVF, "div" }, /* DIVIDE */
121*3d8817e4Smiod { DIVUF, "divu" }, /* DIVIDE Unsigned */
122*3d8817e4Smiod { ANDF, "and" }, /* AND */
123*3d8817e4Smiod { ORF, "or" }, /* OR */
124*3d8817e4Smiod { XORF, "xor" }, /* Exclusive OR */
125*3d8817e4Smiod { SLLF, "sll" }, /* SHIFT LEFT LOGICAL */
126*3d8817e4Smiod { SRAF, "sra" }, /* SHIFT RIGHT ARITHMETIC */
127*3d8817e4Smiod { SRLF, "srl" }, /* SHIFT RIGHT LOGICAL */
128*3d8817e4Smiod { SEQF, "seq" }, /* Set if equal */
129*3d8817e4Smiod { SNEF, "sne" }, /* Set if not equal */
130*3d8817e4Smiod { SLTF, "slt" }, /* Set if less */
131*3d8817e4Smiod { SGTF, "sgt" }, /* Set if greater */
132*3d8817e4Smiod { SLEF, "sle" }, /* Set if less or equal */
133*3d8817e4Smiod { SGEF, "sge" }, /* Set if greater or equal */
134*3d8817e4Smiod { SEQUF, "sequ" }, /* Set if equal */
135*3d8817e4Smiod { SNEUF, "sneu" }, /* Set if not equal */
136*3d8817e4Smiod { SLTUF, "sltu" }, /* Set if less */
137*3d8817e4Smiod { SGTUF, "sgtu" }, /* Set if greater */
138*3d8817e4Smiod { SLEUF, "sleu" }, /* Set if less or equal */
139*3d8817e4Smiod { SGEUF, "sgeu" }, /* Set if greater or equal */
140*3d8817e4Smiod { MVTSF, "mvts" }, /* Move to special register */
141*3d8817e4Smiod { MVFSF, "mvfs" }, /* Move from special register */
142*3d8817e4Smiod { BSWAPF, "bswap" }, /* Byte swap ?? */
143*3d8817e4Smiod { LUTF, "lut" } /* ????????? ?? */
144*3d8817e4Smiod };
145*3d8817e4Smiod int dlx_r_opcode_num = (sizeof dlx_r_opcode) / (sizeof dlx_r_opcode[0]);
146*3d8817e4Smiod int idx;
147*3d8817e4Smiod
148*3d8817e4Smiod for (idx = 0; idx < r_opc_num; idx++)
149*3d8817e4Smiod {
150*3d8817e4Smiod if (r_opc[idx] != opc)
151*3d8817e4Smiod continue;
152*3d8817e4Smiod else
153*3d8817e4Smiod break;
154*3d8817e4Smiod }
155*3d8817e4Smiod
156*3d8817e4Smiod if (idx == r_opc_num)
157*3d8817e4Smiod return NIL;
158*3d8817e4Smiod
159*3d8817e4Smiod for (idx = 0 ; idx < dlx_r_opcode_num; idx++)
160*3d8817e4Smiod if (dlx_r_opcode[idx].func == func)
161*3d8817e4Smiod {
162*3d8817e4Smiod (*info->fprintf_func) (info->stream, "%s", dlx_r_opcode[idx].name);
163*3d8817e4Smiod
164*3d8817e4Smiod if (func != NOPF)
165*3d8817e4Smiod {
166*3d8817e4Smiod /* This is not a nop. */
167*3d8817e4Smiod operand_deliminator (info, dlx_r_opcode[idx].name);
168*3d8817e4Smiod (*info->fprintf_func) (info->stream, "r%d,", (int)rd);
169*3d8817e4Smiod (*info->fprintf_func) (info->stream, "r%d", (int)rs1);
170*3d8817e4Smiod if (func != MVTSF && func != MVFSF)
171*3d8817e4Smiod (*info->fprintf_func) (info->stream, ",r%d", (int)rs2);
172*3d8817e4Smiod }
173*3d8817e4Smiod return (unsigned char) R_TYPE;
174*3d8817e4Smiod }
175*3d8817e4Smiod
176*3d8817e4Smiod return (unsigned char) R_ERROR;
177*3d8817e4Smiod }
178*3d8817e4Smiod
179*3d8817e4Smiod /* Process the memory read opcode. */
180*3d8817e4Smiod
181*3d8817e4Smiod static unsigned char
dlx_load_type(struct disassemble_info * info)182*3d8817e4Smiod dlx_load_type (struct disassemble_info* info)
183*3d8817e4Smiod {
184*3d8817e4Smiod struct _load_opcode
185*3d8817e4Smiod {
186*3d8817e4Smiod unsigned long opcode;
187*3d8817e4Smiod char *name;
188*3d8817e4Smiod }
189*3d8817e4Smiod dlx_load_opcode[] =
190*3d8817e4Smiod {
191*3d8817e4Smiod { OPC(LHIOP), "lhi" }, /* Load HI to register. */
192*3d8817e4Smiod { OPC(LBOP), "lb" }, /* load byte sign extended. */
193*3d8817e4Smiod { OPC(LBUOP), "lbu" }, /* load byte unsigned. */
194*3d8817e4Smiod { OPC(LSBUOP),"ldstbu"}, /* load store byte unsigned. */
195*3d8817e4Smiod { OPC(LHOP), "lh" }, /* load halfword sign extended. */
196*3d8817e4Smiod { OPC(LHUOP), "lhu" }, /* load halfword unsigned. */
197*3d8817e4Smiod { OPC(LSHUOP),"ldsthu"}, /* load store halfword unsigned. */
198*3d8817e4Smiod { OPC(LWOP), "lw" }, /* load word. */
199*3d8817e4Smiod { OPC(LSWOP), "ldstw" } /* load store word. */
200*3d8817e4Smiod };
201*3d8817e4Smiod int dlx_load_opcode_num =
202*3d8817e4Smiod (sizeof dlx_load_opcode) / (sizeof dlx_load_opcode[0]);
203*3d8817e4Smiod int idx;
204*3d8817e4Smiod
205*3d8817e4Smiod for (idx = 0 ; idx < dlx_load_opcode_num; idx++)
206*3d8817e4Smiod if (dlx_load_opcode[idx].opcode == opc)
207*3d8817e4Smiod {
208*3d8817e4Smiod if (opc == OPC (LHIOP))
209*3d8817e4Smiod {
210*3d8817e4Smiod (*info->fprintf_func) (info->stream, "%s", dlx_load_opcode[idx].name);
211*3d8817e4Smiod operand_deliminator (info, dlx_load_opcode[idx].name);
212*3d8817e4Smiod (*info->fprintf_func) (info->stream, "r%d,", (int)rs2);
213*3d8817e4Smiod (*info->fprintf_func) (info->stream, "0x%04x", (int)imm16);
214*3d8817e4Smiod }
215*3d8817e4Smiod else
216*3d8817e4Smiod {
217*3d8817e4Smiod (*info->fprintf_func) (info->stream, "%s", dlx_load_opcode[idx].name);
218*3d8817e4Smiod operand_deliminator (info, dlx_load_opcode[idx].name);
219*3d8817e4Smiod (*info->fprintf_func) (info->stream, "r%d,", (int)rs2);
220*3d8817e4Smiod (*info->fprintf_func) (info->stream, "0x%04x[r%d]", (int)imm16, (int)rs1);
221*3d8817e4Smiod }
222*3d8817e4Smiod
223*3d8817e4Smiod return (unsigned char) ILD_TYPE;
224*3d8817e4Smiod }
225*3d8817e4Smiod
226*3d8817e4Smiod return (unsigned char) NIL;
227*3d8817e4Smiod }
228*3d8817e4Smiod
229*3d8817e4Smiod /* Process the memory store opcode. */
230*3d8817e4Smiod
231*3d8817e4Smiod static unsigned char
dlx_store_type(struct disassemble_info * info)232*3d8817e4Smiod dlx_store_type (struct disassemble_info* info)
233*3d8817e4Smiod {
234*3d8817e4Smiod struct _store_opcode
235*3d8817e4Smiod {
236*3d8817e4Smiod unsigned long opcode;
237*3d8817e4Smiod char *name;
238*3d8817e4Smiod }
239*3d8817e4Smiod dlx_store_opcode[] =
240*3d8817e4Smiod {
241*3d8817e4Smiod { OPC(SBOP), "sb" }, /* Store byte. */
242*3d8817e4Smiod { OPC(SHOP), "sh" }, /* Store halfword. */
243*3d8817e4Smiod { OPC(SWOP), "sw" }, /* Store word. */
244*3d8817e4Smiod };
245*3d8817e4Smiod int dlx_store_opcode_num =
246*3d8817e4Smiod (sizeof dlx_store_opcode) / (sizeof dlx_store_opcode[0]);
247*3d8817e4Smiod int idx;
248*3d8817e4Smiod
249*3d8817e4Smiod for (idx = 0 ; idx < dlx_store_opcode_num; idx++)
250*3d8817e4Smiod if (dlx_store_opcode[idx].opcode == opc)
251*3d8817e4Smiod {
252*3d8817e4Smiod (*info->fprintf_func) (info->stream, "%s", dlx_store_opcode[idx].name);
253*3d8817e4Smiod operand_deliminator (info, dlx_store_opcode[idx].name);
254*3d8817e4Smiod (*info->fprintf_func) (info->stream, "0x%04x[r%d],", (int)imm16, (int)rs1);
255*3d8817e4Smiod (*info->fprintf_func) (info->stream, "r%d", (int)rs2);
256*3d8817e4Smiod return (unsigned char) IST_TYPE;
257*3d8817e4Smiod }
258*3d8817e4Smiod
259*3d8817e4Smiod return (unsigned char) NIL;
260*3d8817e4Smiod }
261*3d8817e4Smiod
262*3d8817e4Smiod /* Process the Arithmetic and Logical I-TYPE opcode. */
263*3d8817e4Smiod
264*3d8817e4Smiod static unsigned char
dlx_aluI_type(struct disassemble_info * info)265*3d8817e4Smiod dlx_aluI_type (struct disassemble_info* info)
266*3d8817e4Smiod {
267*3d8817e4Smiod struct _aluI_opcode
268*3d8817e4Smiod {
269*3d8817e4Smiod unsigned long opcode;
270*3d8817e4Smiod char *name;
271*3d8817e4Smiod }
272*3d8817e4Smiod dlx_aluI_opcode[] =
273*3d8817e4Smiod {
274*3d8817e4Smiod { OPC(ADDIOP), "addi" }, /* Store byte. */
275*3d8817e4Smiod { OPC(ADDUIOP), "addui" }, /* Store halfword. */
276*3d8817e4Smiod { OPC(SUBIOP), "subi" }, /* Store word. */
277*3d8817e4Smiod { OPC(SUBUIOP), "subui" }, /* Store word. */
278*3d8817e4Smiod { OPC(ANDIOP), "andi" }, /* Store word. */
279*3d8817e4Smiod { OPC(ORIOP), "ori" }, /* Store word. */
280*3d8817e4Smiod { OPC(XORIOP), "xori" }, /* Store word. */
281*3d8817e4Smiod { OPC(SLLIOP), "slli" }, /* Store word. */
282*3d8817e4Smiod { OPC(SRAIOP), "srai" }, /* Store word. */
283*3d8817e4Smiod { OPC(SRLIOP), "srli" }, /* Store word. */
284*3d8817e4Smiod { OPC(SEQIOP), "seqi" }, /* Store word. */
285*3d8817e4Smiod { OPC(SNEIOP), "snei" }, /* Store word. */
286*3d8817e4Smiod { OPC(SLTIOP), "slti" }, /* Store word. */
287*3d8817e4Smiod { OPC(SGTIOP), "sgti" }, /* Store word. */
288*3d8817e4Smiod { OPC(SLEIOP), "slei" }, /* Store word. */
289*3d8817e4Smiod { OPC(SGEIOP), "sgei" }, /* Store word. */
290*3d8817e4Smiod { OPC(SEQUIOP), "sequi" }, /* Store word. */
291*3d8817e4Smiod { OPC(SNEUIOP), "sneui" }, /* Store word. */
292*3d8817e4Smiod { OPC(SLTUIOP), "sltui" }, /* Store word. */
293*3d8817e4Smiod { OPC(SGTUIOP), "sgtui" }, /* Store word. */
294*3d8817e4Smiod { OPC(SLEUIOP), "sleui" }, /* Store word. */
295*3d8817e4Smiod { OPC(SGEUIOP), "sgeui" }, /* Store word. */
296*3d8817e4Smiod #if 0
297*3d8817e4Smiod { OPC(MVTSOP), "mvts" }, /* Store word. */
298*3d8817e4Smiod { OPC(MVFSOP), "mvfs" }, /* Store word. */
299*3d8817e4Smiod #endif
300*3d8817e4Smiod };
301*3d8817e4Smiod int dlx_aluI_opcode_num =
302*3d8817e4Smiod (sizeof dlx_aluI_opcode) / (sizeof dlx_aluI_opcode[0]);
303*3d8817e4Smiod int idx;
304*3d8817e4Smiod
305*3d8817e4Smiod for (idx = 0 ; idx < dlx_aluI_opcode_num; idx++)
306*3d8817e4Smiod if (dlx_aluI_opcode[idx].opcode == opc)
307*3d8817e4Smiod {
308*3d8817e4Smiod (*info->fprintf_func) (info->stream, "%s", dlx_aluI_opcode[idx].name);
309*3d8817e4Smiod operand_deliminator (info, dlx_aluI_opcode[idx].name);
310*3d8817e4Smiod (*info->fprintf_func) (info->stream, "r%d,", (int)rs2);
311*3d8817e4Smiod (*info->fprintf_func) (info->stream, "r%d,", (int)rs1);
312*3d8817e4Smiod (*info->fprintf_func) (info->stream, "0x%04x", (int)imm16);
313*3d8817e4Smiod
314*3d8817e4Smiod return (unsigned char) IAL_TYPE;
315*3d8817e4Smiod }
316*3d8817e4Smiod
317*3d8817e4Smiod return (unsigned char) NIL;
318*3d8817e4Smiod }
319*3d8817e4Smiod
320*3d8817e4Smiod /* Process the branch instruction. */
321*3d8817e4Smiod
322*3d8817e4Smiod static unsigned char
dlx_br_type(struct disassemble_info * info)323*3d8817e4Smiod dlx_br_type (struct disassemble_info* info)
324*3d8817e4Smiod {
325*3d8817e4Smiod struct _br_opcode
326*3d8817e4Smiod {
327*3d8817e4Smiod unsigned long opcode;
328*3d8817e4Smiod char *name;
329*3d8817e4Smiod }
330*3d8817e4Smiod dlx_br_opcode[] =
331*3d8817e4Smiod {
332*3d8817e4Smiod { OPC(BEQOP), "beqz" }, /* Store byte. */
333*3d8817e4Smiod { OPC(BNEOP), "bnez" } /* Store halfword. */
334*3d8817e4Smiod };
335*3d8817e4Smiod int dlx_br_opcode_num =
336*3d8817e4Smiod (sizeof dlx_br_opcode) / (sizeof dlx_br_opcode[0]);
337*3d8817e4Smiod int idx;
338*3d8817e4Smiod
339*3d8817e4Smiod for (idx = 0 ; idx < dlx_br_opcode_num; idx++)
340*3d8817e4Smiod if (dlx_br_opcode[idx].opcode == opc)
341*3d8817e4Smiod {
342*3d8817e4Smiod if (imm16 & 0x00008000)
343*3d8817e4Smiod imm16 |= 0xFFFF0000;
344*3d8817e4Smiod
345*3d8817e4Smiod imm16 += (current_insn_addr + 4);
346*3d8817e4Smiod (*info->fprintf_func) (info->stream, "%s", dlx_br_opcode[idx].name);
347*3d8817e4Smiod operand_deliminator (info, dlx_br_opcode[idx].name);
348*3d8817e4Smiod (*info->fprintf_func) (info->stream, "r%d,", (int) rs1);
349*3d8817e4Smiod (*info->fprintf_func) (info->stream, "0x%08x", (int) imm16);
350*3d8817e4Smiod
351*3d8817e4Smiod return (unsigned char) IBR_TYPE;
352*3d8817e4Smiod }
353*3d8817e4Smiod
354*3d8817e4Smiod return (unsigned char) NIL;
355*3d8817e4Smiod }
356*3d8817e4Smiod
357*3d8817e4Smiod /* Process the jump instruction. */
358*3d8817e4Smiod
359*3d8817e4Smiod static unsigned char
dlx_jmp_type(struct disassemble_info * info)360*3d8817e4Smiod dlx_jmp_type (struct disassemble_info* info)
361*3d8817e4Smiod {
362*3d8817e4Smiod struct _jmp_opcode
363*3d8817e4Smiod {
364*3d8817e4Smiod unsigned long opcode;
365*3d8817e4Smiod char *name;
366*3d8817e4Smiod }
367*3d8817e4Smiod dlx_jmp_opcode[] =
368*3d8817e4Smiod {
369*3d8817e4Smiod { OPC(JOP), "j" }, /* Store byte. */
370*3d8817e4Smiod { OPC(JALOP), "jal" }, /* Store halfword. */
371*3d8817e4Smiod { OPC(BREAKOP), "break" }, /* Store halfword. */
372*3d8817e4Smiod { OPC(TRAPOP), "trap" }, /* Store halfword. */
373*3d8817e4Smiod { OPC(RFEOP), "rfe" } /* Store halfword. */
374*3d8817e4Smiod };
375*3d8817e4Smiod int dlx_jmp_opcode_num =
376*3d8817e4Smiod (sizeof dlx_jmp_opcode) / (sizeof dlx_jmp_opcode[0]);
377*3d8817e4Smiod int idx;
378*3d8817e4Smiod
379*3d8817e4Smiod for (idx = 0 ; idx < dlx_jmp_opcode_num; idx++)
380*3d8817e4Smiod if (dlx_jmp_opcode[idx].opcode == opc)
381*3d8817e4Smiod {
382*3d8817e4Smiod if (imm26 & 0x02000000)
383*3d8817e4Smiod imm26 |= 0xFC000000;
384*3d8817e4Smiod
385*3d8817e4Smiod imm26 += (current_insn_addr + 4);
386*3d8817e4Smiod
387*3d8817e4Smiod (*info->fprintf_func) (info->stream, "%s", dlx_jmp_opcode[idx].name);
388*3d8817e4Smiod operand_deliminator (info, dlx_jmp_opcode[idx].name);
389*3d8817e4Smiod (*info->fprintf_func) (info->stream, "0x%08x", (int)imm26);
390*3d8817e4Smiod
391*3d8817e4Smiod return (unsigned char) IJ_TYPE;
392*3d8817e4Smiod }
393*3d8817e4Smiod
394*3d8817e4Smiod return (unsigned char) NIL;
395*3d8817e4Smiod }
396*3d8817e4Smiod
397*3d8817e4Smiod /* Process the jump register instruction. */
398*3d8817e4Smiod
399*3d8817e4Smiod static unsigned char
dlx_jr_type(struct disassemble_info * info)400*3d8817e4Smiod dlx_jr_type (struct disassemble_info* info)
401*3d8817e4Smiod {
402*3d8817e4Smiod struct _jr_opcode
403*3d8817e4Smiod {
404*3d8817e4Smiod unsigned long opcode;
405*3d8817e4Smiod char *name;
406*3d8817e4Smiod }
407*3d8817e4Smiod dlx_jr_opcode[] =
408*3d8817e4Smiod {
409*3d8817e4Smiod { OPC(JROP), "jr" }, /* Store byte. */
410*3d8817e4Smiod { OPC(JALROP), "jalr" } /* Store halfword. */
411*3d8817e4Smiod };
412*3d8817e4Smiod int dlx_jr_opcode_num =
413*3d8817e4Smiod (sizeof dlx_jr_opcode) / (sizeof dlx_jr_opcode[0]);
414*3d8817e4Smiod int idx;
415*3d8817e4Smiod
416*3d8817e4Smiod for (idx = 0 ; idx < dlx_jr_opcode_num; idx++)
417*3d8817e4Smiod if (dlx_jr_opcode[idx].opcode == opc)
418*3d8817e4Smiod {
419*3d8817e4Smiod (*info->fprintf_func) (info->stream, "%s", dlx_jr_opcode[idx].name);
420*3d8817e4Smiod operand_deliminator (info, dlx_jr_opcode[idx].name);
421*3d8817e4Smiod (*info->fprintf_func) (info->stream, "r%d", (int)rs1);
422*3d8817e4Smiod return (unsigned char) IJR_TYPE;
423*3d8817e4Smiod }
424*3d8817e4Smiod
425*3d8817e4Smiod return (unsigned char) NIL;
426*3d8817e4Smiod }
427*3d8817e4Smiod
428*3d8817e4Smiod typedef unsigned char (* dlx_insn) (struct disassemble_info *);
429*3d8817e4Smiod
430*3d8817e4Smiod /* This is the main DLX insn handling routine. */
431*3d8817e4Smiod
432*3d8817e4Smiod int
print_insn_dlx(bfd_vma memaddr,struct disassemble_info * info)433*3d8817e4Smiod print_insn_dlx (bfd_vma memaddr, struct disassemble_info* info)
434*3d8817e4Smiod {
435*3d8817e4Smiod bfd_byte buffer[4];
436*3d8817e4Smiod int insn_idx;
437*3d8817e4Smiod unsigned long insn_word;
438*3d8817e4Smiod unsigned char rtn_code;
439*3d8817e4Smiod unsigned long dlx_insn_type[] =
440*3d8817e4Smiod {
441*3d8817e4Smiod (unsigned long) dlx_r_type,
442*3d8817e4Smiod (unsigned long) dlx_load_type,
443*3d8817e4Smiod (unsigned long) dlx_store_type,
444*3d8817e4Smiod (unsigned long) dlx_aluI_type,
445*3d8817e4Smiod (unsigned long) dlx_br_type,
446*3d8817e4Smiod (unsigned long) dlx_jmp_type,
447*3d8817e4Smiod (unsigned long) dlx_jr_type,
448*3d8817e4Smiod (unsigned long) NULL
449*3d8817e4Smiod };
450*3d8817e4Smiod int dlx_insn_type_num = ((sizeof dlx_insn_type) / (sizeof (unsigned long))) - 1;
451*3d8817e4Smiod int status =
452*3d8817e4Smiod (*info->read_memory_func) (memaddr, (bfd_byte *) &buffer[0], 4, info);
453*3d8817e4Smiod
454*3d8817e4Smiod if (status != 0)
455*3d8817e4Smiod {
456*3d8817e4Smiod (*info->memory_error_func) (status, memaddr, info);
457*3d8817e4Smiod return -1;
458*3d8817e4Smiod }
459*3d8817e4Smiod
460*3d8817e4Smiod /* Now decode the insn */
461*3d8817e4Smiod insn_word = bfd_getb32 (buffer);
462*3d8817e4Smiod opc = dlx_get_opcode (insn_word);
463*3d8817e4Smiod rs1 = dlx_get_rs1 (insn_word);
464*3d8817e4Smiod rs2 = dlx_get_rs2 (insn_word);
465*3d8817e4Smiod rd = dlx_get_rdR (insn_word);
466*3d8817e4Smiod func = dlx_get_func (insn_word);
467*3d8817e4Smiod imm16= dlx_get_imm16 (insn_word);
468*3d8817e4Smiod imm26= dlx_get_imm26 (insn_word);
469*3d8817e4Smiod
470*3d8817e4Smiod #if 0
471*3d8817e4Smiod printf ("print_insn_big_dlx: opc = 0x%02x\n"
472*3d8817e4Smiod " rs1 = 0x%02x\n"
473*3d8817e4Smiod " rs2 = 0x%02x\n"
474*3d8817e4Smiod " rd = 0x%02x\n"
475*3d8817e4Smiod " func = 0x%08x\n"
476*3d8817e4Smiod " imm16 = 0x%08x\n"
477*3d8817e4Smiod " imm26 = 0x%08x\n",
478*3d8817e4Smiod opc, rs1, rs2, rd, func, imm16, imm26);
479*3d8817e4Smiod #endif
480*3d8817e4Smiod
481*3d8817e4Smiod /* Scan through all the insn type and print the insn out. */
482*3d8817e4Smiod rtn_code = 0;
483*3d8817e4Smiod current_insn_addr = (unsigned long) memaddr;
484*3d8817e4Smiod
485*3d8817e4Smiod for (insn_idx = 0; dlx_insn_type[insn_idx] != 0x0; insn_idx++)
486*3d8817e4Smiod switch (((dlx_insn) (dlx_insn_type[insn_idx])) (info))
487*3d8817e4Smiod {
488*3d8817e4Smiod /* Found the correct opcode */
489*3d8817e4Smiod case R_TYPE:
490*3d8817e4Smiod case ILD_TYPE:
491*3d8817e4Smiod case IST_TYPE:
492*3d8817e4Smiod case IAL_TYPE:
493*3d8817e4Smiod case IBR_TYPE:
494*3d8817e4Smiod case IJ_TYPE:
495*3d8817e4Smiod case IJR_TYPE:
496*3d8817e4Smiod return 4;
497*3d8817e4Smiod
498*3d8817e4Smiod /* Wrong insn type check next one. */
499*3d8817e4Smiod default:
500*3d8817e4Smiod case NIL:
501*3d8817e4Smiod continue;
502*3d8817e4Smiod
503*3d8817e4Smiod /* All rest of the return code are not recongnized, treat it as error */
504*3d8817e4Smiod /* we should never get here, I hope! */
505*3d8817e4Smiod case R_ERROR:
506*3d8817e4Smiod return -1;
507*3d8817e4Smiod }
508*3d8817e4Smiod
509*3d8817e4Smiod if (insn_idx == dlx_insn_type_num)
510*3d8817e4Smiod /* Well, does not recoganize this opcode. */
511*3d8817e4Smiod (*info->fprintf_func) (info->stream, "<%s>", "Unrecognized Opcode");
512*3d8817e4Smiod
513*3d8817e4Smiod return 4;
514*3d8817e4Smiod }
515