xref: /openbsd-src/gnu/usr.bin/binutils-2.17/opcodes/dlx-dis.c (revision 3d8817e467ea46cf4772788d6804dd293abfb01a)
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