tcg: fix size of local variables in tcg_gen_bswap64_i64
[qemu] / microblaze-dis.c
1 /* Disassemble Xilinx microblaze instructions.
2    Copyright (C) 1993, 1999, 2000 Free Software Foundation, Inc.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, see <http://www.gnu.org/licenses/>.  */
16
17 /*
18  * Copyright (c) 2001 Xilinx, Inc.  All rights reserved. 
19  *
20  * Redistribution and use in source and binary forms are permitted
21  * provided that the above copyright notice and this paragraph are
22  * duplicated in all such forms and that any documentation,
23  * advertising materials, and other materials related to such
24  * distribution and use acknowledge that the software was developed
25  * by Xilinx, Inc.  The name of the Company may not be used to endorse 
26  * or promote products derived from this software without specific prior 
27  * written permission.
28  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
29  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
30  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
31  *
32  *      Xilinx, Inc.
33  */
34
35
36 #include <stdio.h>
37 #define STATIC_TABLE
38 #define DEFINE_TABLE
39
40 #ifndef MICROBLAZE_OPC
41 #define MICROBLAZE_OPC
42 /* Assembler instructions for Xilinx's microblaze processor
43    Copyright (C) 1999, 2000 Free Software Foundation, Inc.
44
45    
46 This program is free software; you can redistribute it and/or modify
47 it under the terms of the GNU General Public License as published by
48 the Free Software Foundation; either version 2 of the License, or
49 (at your option) any later version.
50
51 This program is distributed in the hope that it will be useful,
52 but WITHOUT ANY WARRANTY; without even the implied warranty of
53 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
54 GNU General Public License for more details.
55
56 You should have received a copy of the GNU General Public License
57 along with this program; if not, see <http://www.gnu.org/licenses/>.  */
58
59 /*
60  * Copyright (c) 2001 Xilinx, Inc.  All rights reserved. 
61  *
62  * Redistribution and use in source and binary forms are permitted
63  * provided that the above copyright notice and this paragraph are
64  * duplicated in all such forms and that any documentation,
65  * advertising materials, and other materials related to such
66  * distribution and use acknowledge that the software was developed
67  * by Xilinx, Inc.  The name of the Company may not be used to endorse 
68  * or promote products derived from this software without specific prior 
69  * written permission.
70  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
71  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
72  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
73  *
74  *      Xilinx, Inc.
75  */
76
77
78 #ifndef MICROBLAZE_OPCM
79 #define MICROBLAZE_OPCM
80
81 /*
82  * Copyright (c) 2001 Xilinx, Inc.  All rights reserved. 
83  *
84  * Redistribution and use in source and binary forms are permitted
85  * provided that the above copyright notice and this paragraph are
86  * duplicated in all such forms and that any documentation,
87  * advertising materials, and other materials related to such
88  * distribution and use acknowledge that the software was developed
89  * by Xilinx, Inc.  The name of the Company may not be used to endorse 
90  * or promote products derived from this software without specific prior 
91  * written permission.
92  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
93  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
94  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
95  *
96  *      Xilinx, Inc.
97  * $Header:
98  */
99
100 enum microblaze_instr {
101    add, rsub, addc, rsubc, addk, rsubk, addkc, rsubkc, cmp, cmpu,
102    addi, rsubi, addic, rsubic, addik, rsubik, addikc, rsubikc, mul,
103    idiv, idivu, bsll, bsra, bsrl, get, put, nget, nput, cget, cput,
104    ncget, ncput, muli, bslli, bsrai, bsrli, mului, or, and, xor,
105    andn, pcmpbf, pcmpbc, pcmpeq, pcmpne, sra, src, srl, sext8, sext16, wic, wdc, mts, mfs, br, brd,
106    brld, bra, brad, brald, microblaze_brk, beq, beqd, bne, bned, blt,
107    bltd, ble, bled, bgt, bgtd, bge, bged, ori, andi, xori, andni,
108    imm, rtsd, rtid, rtbd, rted, bri, brid, brlid, brai, braid, bralid,
109    brki, beqi, beqid, bnei, bneid, blti, bltid, blei, bleid, bgti,
110    bgtid, bgei, bgeid, lbu, lhu, lw, sb, sh, sw, lbui, lhui, lwi,
111    sbi, shi, swi, msrset, msrclr, tuqula, fadd, frsub, fmul, fdiv, 
112    fcmp_lt, fcmp_eq, fcmp_le, fcmp_gt, fcmp_ne, fcmp_ge, fcmp_un, invalid_inst } ;
113
114 enum microblaze_instr_type {
115    arithmetic_inst, logical_inst, mult_inst, div_inst, branch_inst,
116    return_inst, immediate_inst, special_inst, memory_load_inst,
117    memory_store_inst, barrel_shift_inst, anyware_inst };
118
119 #define INST_WORD_SIZE 4
120
121 /* gen purpose regs go from 0 to 31 */
122 /* mask is reg num - max_reg_num, ie reg_num - 32 in this case */
123
124 #define REG_PC_MASK 0x8000
125 #define REG_MSR_MASK 0x8001
126 #define REG_EAR_MASK 0x8003
127 #define REG_ESR_MASK 0x8005
128 #define REG_FSR_MASK 0x8007
129
130 #define MIN_REGNUM 0
131 #define MAX_REGNUM 31
132
133 #define REG_PC  32 /* PC */
134 #define REG_MSR 33 /* machine status reg */
135 #define REG_EAR 35 /* Exception reg */
136 #define REG_ESR 37 /* Exception reg */
137 #define REG_FSR 39 /* FPU Status reg */
138
139 /* alternate names for gen purpose regs */
140 #define REG_SP  1 /* stack pointer */
141 #define REG_ROSDP 2 /* read-only small data pointer */
142 #define REG_RWSDP 13 /* read-write small data pointer */
143
144 /* Assembler Register - Used in Delay Slot Optimization */
145 #define REG_AS    18
146 #define REG_ZERO  0
147  
148 #define RD_LOW  21 /* low bit for RD */
149 #define RA_LOW  16 /* low bit for RA */
150 #define RB_LOW  11 /* low bit for RB */
151 #define IMM_LOW  0 /* low bit for immediate */
152
153 #define RD_MASK 0x03E00000
154 #define RA_MASK 0x001F0000
155 #define RB_MASK 0x0000F800
156 #define IMM_MASK 0x0000FFFF
157
158 // imm mask for barrel shifts
159 #define IMM5_MASK 0x0000001F
160
161
162 // imm mask for get, put instructions
163 #define  IMM12_MASK 0x00000FFF
164
165 // imm mask for msrset, msrclr instructions
166 #define  IMM14_MASK 0x00003FFF
167
168 #endif /* MICROBLAZE-OPCM */
169
170 #define INST_TYPE_RD_R1_R2 0
171 #define INST_TYPE_RD_R1_IMM 1
172 #define INST_TYPE_RD_R1_UNSIGNED_IMM 2
173 #define INST_TYPE_RD_R1 3
174 #define INST_TYPE_RD_R2 4
175 #define INST_TYPE_RD_IMM 5
176 #define INST_TYPE_R2 6
177 #define INST_TYPE_R1_R2 7
178 #define INST_TYPE_R1_IMM 8
179 #define INST_TYPE_IMM 9
180 #define INST_TYPE_SPECIAL_R1 10
181 #define INST_TYPE_RD_SPECIAL 11
182 #define INST_TYPE_R1 12
183   // new instn type for barrel shift imms
184 #define INST_TYPE_RD_R1_IMM5  13
185 #define INST_TYPE_RD_IMM12    14
186 #define INST_TYPE_R1_IMM12    15
187
188   // new insn type for insn cache
189 #define INST_TYPE_RD_R1_SPECIAL 16
190
191 // new insn type for msrclr, msrset insns.
192 #define INST_TYPE_RD_IMM14    17
193
194 // new insn type for tuqula rd - addik rd, r0, 42
195 #define INST_TYPE_RD    18
196
197 #define INST_TYPE_NONE 25
198
199
200
201 #define INST_PC_OFFSET 1 /* instructions where the label address is resolved as a PC offset (for branch label)*/
202 #define INST_NO_OFFSET 0 /* instructions where the label address is resolved as an absolute value (for data mem or abs address)*/
203
204 #define IMMVAL_MASK_NON_SPECIAL 0x0000
205 #define IMMVAL_MASK_MTS 0x4000
206 #define IMMVAL_MASK_MFS 0x0000
207
208 #define OPCODE_MASK_H   0xFC000000 /* High 6 bits only */
209 #define OPCODE_MASK_H1  0xFFE00000 /* High 11 bits */
210 #define OPCODE_MASK_H2  0xFC1F0000 /* High 6 and bits 20-16 */
211 #define OPCODE_MASK_H12 0xFFFF0000 /* High 16 */
212 #define OPCODE_MASK_H4  0xFC0007FF /* High 6 and low 11 bits */
213 #define OPCODE_MASK_H13S 0xFFE0FFF0 /* High 11 and 15:1 bits and last nibble of last byte for spr */
214 #define OPCODE_MASK_H23S 0xFC1FFFF0 /* High 6, 20-16 and 15:1 bits and last nibble of last byte for spr */
215 #define OPCODE_MASK_H34 0xFC00FFFF /* High 6 and low 16 bits */
216 #define OPCODE_MASK_H14 0xFFE007FF /* High 11 and low 11 bits */
217 #define OPCODE_MASK_H24 0xFC1F07FF /* High 6, bits 20-16 and low 11 bits */
218 #define OPCODE_MASK_H124  0xFFFF07FF /* High 16, and low 11 bits */
219 #define OPCODE_MASK_H1234 0xFFFFFFFF /* All 32 bits */
220 #define OPCODE_MASK_H3  0xFC000600 /* High 6 bits and bits 21, 22 */  
221 #define OPCODE_MASK_H32 0xFC00F000 /* High 6 bits and bit 16, 17, 18 and 19*/
222 #define OPCODE_MASK_H34B   0xFC0000FF /* High 6 bits and low 8 bits */
223
224 // New Mask for msrset, msrclr insns.
225 #define OPCODE_MASK_H23N  0xFC1FC000 /* High 6 and bits 12 - 18 */
226
227 #define DELAY_SLOT 1
228 #define NO_DELAY_SLOT 0
229
230 #define MAX_OPCODES 149
231
232 struct op_code_struct {
233   const char *name;
234   short inst_type; /* registers and immediate values involved */
235   short inst_offset_type; /* immediate vals offset from PC? (= 1 for branches) */
236   short delay_slots; /* info about delay slots needed after this instr. */
237   short immval_mask;
238   unsigned long bit_sequence; /* all the fixed bits for the op are set and all the variable bits (reg names, imm vals) are set to 0 */ 
239   unsigned long opcode_mask; /* which bits define the opcode */
240   enum microblaze_instr instr;
241   enum microblaze_instr_type instr_type;
242   /* more info about output format here */
243 } opcodes[MAX_OPCODES] = 
244
245
246   {"add",   INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x00000000, OPCODE_MASK_H4, add, arithmetic_inst },
247   {"rsub",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x04000000, OPCODE_MASK_H4, rsub, arithmetic_inst },
248   {"addc",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x08000000, OPCODE_MASK_H4, addc, arithmetic_inst },
249   {"rsubc", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x0C000000, OPCODE_MASK_H4, rsubc, arithmetic_inst },
250   {"addk",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x10000000, OPCODE_MASK_H4, addk, arithmetic_inst },
251   {"rsubk", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x14000000, OPCODE_MASK_H4, rsubk, arithmetic_inst },
252   {"cmp",   INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x14000001, OPCODE_MASK_H4, cmp, arithmetic_inst },
253   {"cmpu",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x14000003, OPCODE_MASK_H4, cmpu, arithmetic_inst },
254   {"addkc", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x18000000, OPCODE_MASK_H4, addkc, arithmetic_inst },
255   {"rsubkc",INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x1C000000, OPCODE_MASK_H4, rsubkc, arithmetic_inst },
256   {"addi",  INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x20000000, OPCODE_MASK_H, addi, arithmetic_inst },
257   {"rsubi", INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x24000000, OPCODE_MASK_H, rsubi, arithmetic_inst },
258   {"addic", INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x28000000, OPCODE_MASK_H, addic, arithmetic_inst },
259   {"rsubic",INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x2C000000, OPCODE_MASK_H, rsubic, arithmetic_inst },
260   {"addik", INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x30000000, OPCODE_MASK_H, addik, arithmetic_inst },
261   {"rsubik",INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x34000000, OPCODE_MASK_H, rsubik, arithmetic_inst },
262   {"addikc",INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x38000000, OPCODE_MASK_H, addikc, arithmetic_inst },
263   {"rsubikc",INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x3C000000, OPCODE_MASK_H, rsubikc, arithmetic_inst },
264   {"mul",   INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x40000000, OPCODE_MASK_H4, mul, mult_inst },
265   {"idiv",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x48000000, OPCODE_MASK_H4, idiv, div_inst },
266   {"idivu", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x48000002, OPCODE_MASK_H4, idivu, div_inst },
267   {"bsll",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x44000400, OPCODE_MASK_H3, bsll, barrel_shift_inst },
268   {"bsra",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x44000200, OPCODE_MASK_H3, bsra, barrel_shift_inst },
269   {"bsrl",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x44000000, OPCODE_MASK_H3, bsrl, barrel_shift_inst },
270   {"get",   INST_TYPE_RD_IMM12, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x6C000000, OPCODE_MASK_H32, get, anyware_inst },
271   {"put",   INST_TYPE_R1_IMM12, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x6C008000, OPCODE_MASK_H32, put, anyware_inst },
272   {"nget",  INST_TYPE_RD_IMM12, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x6C004000, OPCODE_MASK_H32, nget, anyware_inst },
273   {"nput",  INST_TYPE_R1_IMM12, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x6C00C000, OPCODE_MASK_H32, nput, anyware_inst },
274   {"cget",  INST_TYPE_RD_IMM12, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x6C002000, OPCODE_MASK_H32, cget, anyware_inst },
275   {"cput",  INST_TYPE_R1_IMM12, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x6C00A000, OPCODE_MASK_H32, cput, anyware_inst },
276   {"ncget", INST_TYPE_RD_IMM12, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x6C006000, OPCODE_MASK_H32, ncget, anyware_inst },
277   {"ncput", INST_TYPE_R1_IMM12, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x6C00E000, OPCODE_MASK_H32, ncput, anyware_inst },
278   {"muli",  INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x60000000, OPCODE_MASK_H, muli, mult_inst },
279   {"bslli", INST_TYPE_RD_R1_IMM5, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x64000400, OPCODE_MASK_H3, bslli, barrel_shift_inst },
280   {"bsrai", INST_TYPE_RD_R1_IMM5, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x64000200, OPCODE_MASK_H3, bsrai, barrel_shift_inst },
281   {"bsrli", INST_TYPE_RD_R1_IMM5, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x64000000, OPCODE_MASK_H3, bsrli, barrel_shift_inst },
282   {"or",    INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x80000000, OPCODE_MASK_H4, or, logical_inst },
283   {"and",   INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x84000000, OPCODE_MASK_H4, and, logical_inst },
284   {"xor",   INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x88000000, OPCODE_MASK_H4, xor, logical_inst },
285   {"andn",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x8C000000, OPCODE_MASK_H4, andn, logical_inst },
286   {"pcmpbf",INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x80000400, OPCODE_MASK_H4, pcmpbf, logical_inst },
287   {"pcmpbc",INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x84000400, OPCODE_MASK_H4, pcmpbc, logical_inst },
288   {"pcmpeq",INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x88000400, OPCODE_MASK_H4, pcmpeq, logical_inst },
289   {"pcmpne",INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x8C000400, OPCODE_MASK_H4, pcmpne, logical_inst },
290   {"sra",   INST_TYPE_RD_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000001, OPCODE_MASK_H34, sra, logical_inst },
291   {"src",   INST_TYPE_RD_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000021, OPCODE_MASK_H34, src, logical_inst },
292   {"srl",   INST_TYPE_RD_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000041, OPCODE_MASK_H34, srl, logical_inst },
293   {"sext8", INST_TYPE_RD_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000060, OPCODE_MASK_H34, sext8, logical_inst },
294   {"sext16",INST_TYPE_RD_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000061, OPCODE_MASK_H34, sext16, logical_inst },
295   {"wic",   INST_TYPE_RD_R1_SPECIAL, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000068, OPCODE_MASK_H34B, wic, special_inst },
296   {"wdc",   INST_TYPE_RD_R1_SPECIAL, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000064, OPCODE_MASK_H34B, wdc, special_inst },
297   {"mts",   INST_TYPE_SPECIAL_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_MTS, 0x9400C000, OPCODE_MASK_H13S, mts, special_inst },
298   {"mfs",   INST_TYPE_RD_SPECIAL, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_MFS, 0x94008000, OPCODE_MASK_H23S, mfs, special_inst },
299   {"br",    INST_TYPE_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x98000000, OPCODE_MASK_H124, br, branch_inst },
300   {"brd",   INST_TYPE_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x98100000, OPCODE_MASK_H124, brd, branch_inst },
301   {"brld",  INST_TYPE_RD_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x98140000, OPCODE_MASK_H24, brld, branch_inst },
302   {"bra",   INST_TYPE_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x98080000, OPCODE_MASK_H124, bra, branch_inst },
303   {"brad",  INST_TYPE_R2, INST_NO_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x98180000, OPCODE_MASK_H124, brad, branch_inst },
304   {"brald", INST_TYPE_RD_R2, INST_NO_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x981C0000, OPCODE_MASK_H24, brald, branch_inst },
305   {"brk",   INST_TYPE_RD_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x980C0000, OPCODE_MASK_H24, microblaze_brk, branch_inst },
306   {"beq",   INST_TYPE_R1_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9C000000, OPCODE_MASK_H14, beq, branch_inst },
307   {"beqd",  INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9E000000, OPCODE_MASK_H14, beqd, branch_inst },
308   {"bne",   INST_TYPE_R1_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9C200000, OPCODE_MASK_H14, bne, branch_inst },
309   {"bned",  INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9E200000, OPCODE_MASK_H14, bned, branch_inst },
310   {"blt",   INST_TYPE_R1_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9C400000, OPCODE_MASK_H14, blt, branch_inst },
311   {"bltd",  INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9E400000, OPCODE_MASK_H14, bltd, branch_inst },
312   {"ble",   INST_TYPE_R1_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9C600000, OPCODE_MASK_H14, ble, branch_inst },
313   {"bled",  INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9E600000, OPCODE_MASK_H14, bled, branch_inst },
314   {"bgt",   INST_TYPE_R1_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9C800000, OPCODE_MASK_H14, bgt, branch_inst },
315   {"bgtd",  INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9E800000, OPCODE_MASK_H14, bgtd, branch_inst },
316   {"bge",   INST_TYPE_R1_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9CA00000, OPCODE_MASK_H14, bge, branch_inst },
317   {"bged",  INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9EA00000, OPCODE_MASK_H14, bged, branch_inst },
318   {"ori",   INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xA0000000, OPCODE_MASK_H, ori, logical_inst },
319   {"andi",  INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xA4000000, OPCODE_MASK_H, andi, logical_inst },
320   {"xori",  INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xA8000000, OPCODE_MASK_H, xori, logical_inst },
321   {"andni", INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xAC000000, OPCODE_MASK_H, andni, logical_inst },
322   {"imm",   INST_TYPE_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB0000000, OPCODE_MASK_H12, imm, immediate_inst },
323   {"rtsd",  INST_TYPE_R1_IMM, INST_NO_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB6000000, OPCODE_MASK_H1, rtsd, return_inst },
324   {"rtid",  INST_TYPE_R1_IMM, INST_NO_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB6200000, OPCODE_MASK_H1, rtid, return_inst },
325   {"rtbd",  INST_TYPE_R1_IMM, INST_NO_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB6400000, OPCODE_MASK_H1, rtbd, return_inst },
326   {"rted",  INST_TYPE_R1_IMM, INST_NO_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB6800000, OPCODE_MASK_H1, rted, return_inst },
327   {"bri",   INST_TYPE_IMM, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB8000000, OPCODE_MASK_H12, bri, branch_inst },
328   {"brid",  INST_TYPE_IMM, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB8100000, OPCODE_MASK_H12, brid, branch_inst },
329   {"brlid", INST_TYPE_RD_IMM, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB8140000, OPCODE_MASK_H2, brlid, branch_inst },
330   {"brai",  INST_TYPE_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB8080000, OPCODE_MASK_H12, brai, branch_inst },
331   {"braid", INST_TYPE_IMM, INST_NO_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB8180000, OPCODE_MASK_H12, braid, branch_inst },
332   {"bralid",INST_TYPE_RD_IMM, INST_NO_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB81C0000, OPCODE_MASK_H2, bralid, branch_inst },
333   {"brki",  INST_TYPE_RD_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB80C0000, OPCODE_MASK_H2, brki, branch_inst },
334   {"beqi",  INST_TYPE_R1_IMM, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBC000000, OPCODE_MASK_H1, beqi, branch_inst },
335   {"beqid", INST_TYPE_R1_IMM, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBE000000, OPCODE_MASK_H1, beqid, branch_inst },
336   {"bnei",  INST_TYPE_R1_IMM, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBC200000, OPCODE_MASK_H1, bnei, branch_inst },
337   {"bneid", INST_TYPE_R1_IMM, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBE200000, OPCODE_MASK_H1, bneid, branch_inst },
338   {"blti",  INST_TYPE_R1_IMM, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBC400000, OPCODE_MASK_H1, blti, branch_inst },
339   {"bltid", INST_TYPE_R1_IMM, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBE400000, OPCODE_MASK_H1, bltid, branch_inst },
340   {"blei",  INST_TYPE_R1_IMM, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBC600000, OPCODE_MASK_H1, blei, branch_inst },
341   {"bleid", INST_TYPE_R1_IMM, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBE600000, OPCODE_MASK_H1, bleid, branch_inst },
342   {"bgti",  INST_TYPE_R1_IMM, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBC800000, OPCODE_MASK_H1, bgti, branch_inst },
343   {"bgtid", INST_TYPE_R1_IMM, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBE800000, OPCODE_MASK_H1, bgtid, branch_inst },
344   {"bgei",  INST_TYPE_R1_IMM, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBCA00000, OPCODE_MASK_H1, bgei, branch_inst },
345   {"bgeid", INST_TYPE_R1_IMM, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBEA00000, OPCODE_MASK_H1, bgeid, branch_inst },
346   {"lbu",   INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xC0000000, OPCODE_MASK_H4, lbu, memory_load_inst },
347   {"lhu",   INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xC4000000, OPCODE_MASK_H4, lhu, memory_load_inst },
348   {"lw",    INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xC8000000, OPCODE_MASK_H4, lw, memory_load_inst },
349   {"sb",    INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xD0000000, OPCODE_MASK_H4, sb, memory_store_inst },
350   {"sh",    INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xD4000000, OPCODE_MASK_H4, sh, memory_store_inst },
351   {"sw",    INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xD8000000, OPCODE_MASK_H4, sw, memory_store_inst },
352   {"lbui",  INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xE0000000, OPCODE_MASK_H, lbui, memory_load_inst },
353   {"lhui",  INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xE4000000, OPCODE_MASK_H, lhui, memory_load_inst },
354   {"lwi",   INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xE8000000, OPCODE_MASK_H, lwi, memory_load_inst },
355   {"sbi",   INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xF0000000, OPCODE_MASK_H, sbi, memory_store_inst },
356   {"shi",   INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xF4000000, OPCODE_MASK_H, shi, memory_store_inst },
357   {"swi",   INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xF8000000, OPCODE_MASK_H, swi, memory_store_inst },
358   {"nop",   INST_TYPE_NONE, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x80000000, OPCODE_MASK_H1234, invalid_inst, logical_inst }, /* translates to or r0, r0, r0 */
359   {"la",    INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x30000000, OPCODE_MASK_H, invalid_inst, arithmetic_inst }, /* la translates to addik */
360   {"tuqula",INST_TYPE_RD, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x3000002A, OPCODE_MASK_H, invalid_inst, arithmetic_inst }, /* tuqula rd translates to addik rd, r0, 42 */
361   {"not",   INST_TYPE_RD_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xA800FFFF, OPCODE_MASK_H34, invalid_inst, logical_inst }, /* not translates to xori rd,ra,-1 */
362   {"neg",   INST_TYPE_RD_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x04000000, OPCODE_MASK_H, invalid_inst, arithmetic_inst }, /* neg translates to rsub rd, ra, r0 */
363   {"rtb",   INST_TYPE_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB6000004, OPCODE_MASK_H1, invalid_inst, return_inst }, /* rtb translates to rts rd, 4 */
364   {"sub",   INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x04000000, OPCODE_MASK_H, invalid_inst, arithmetic_inst }, /* sub translates to rsub rd, rb, ra */
365   {"lmi",   INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xE8000000, OPCODE_MASK_H, invalid_inst, memory_load_inst },
366   {"smi",   INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xF8000000, OPCODE_MASK_H, invalid_inst, memory_store_inst },
367   {"msrset",INST_TYPE_RD_IMM14, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x94100000, OPCODE_MASK_H23N, msrset, special_inst },
368   {"msrclr",INST_TYPE_RD_IMM14, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x94110000, OPCODE_MASK_H23N, msrclr, special_inst },
369   {"fadd",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000000, OPCODE_MASK_H4, fadd, arithmetic_inst },
370   {"frsub",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000080, OPCODE_MASK_H4, frsub, arithmetic_inst },
371   {"fmul",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000100, OPCODE_MASK_H4, fmul, arithmetic_inst },
372   {"fdiv",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000180, OPCODE_MASK_H4, fdiv, arithmetic_inst },
373   {"fcmp.lt", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000210, OPCODE_MASK_H4, fcmp_lt, arithmetic_inst },
374   {"fcmp.eq", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000220, OPCODE_MASK_H4, fcmp_eq, arithmetic_inst },
375   {"fcmp.le", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000230, OPCODE_MASK_H4, fcmp_le, arithmetic_inst },
376   {"fcmp.gt", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000240, OPCODE_MASK_H4, fcmp_gt, arithmetic_inst },
377   {"fcmp.ne", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000250, OPCODE_MASK_H4, fcmp_ne, arithmetic_inst },
378   {"fcmp.ge", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000260, OPCODE_MASK_H4, fcmp_ge, arithmetic_inst },
379   {"fcmp.un", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000200, OPCODE_MASK_H4, fcmp_un, arithmetic_inst },
380   {""}
381 };
382
383 /* prefix for register names */
384 char register_prefix[] = "r";
385 char special_register_prefix[] = "spr";
386 char fsl_register_prefix[] = "rfsl";
387
388
389 /* #defines for valid immediate range */
390 #define MIN_IMM  0x80000000
391 #define MAX_IMM  0x7fffffff 
392
393 #define MIN_IMM12  0x000
394 #define MAX_IMM12  0x7ff
395
396 #define MIN_IMM14  0x0000
397 #define MAX_IMM14  0x1fff
398
399 #endif /* MICROBLAZE_OPC */
400
401 #include "dis-asm.h"
402 #include <strings.h>
403
404 #define get_field_rd(instr) get_field(instr, RD_MASK, RD_LOW)
405 #define get_field_r1(instr) get_field(instr, RA_MASK, RA_LOW)
406 #define get_field_r2(instr) get_field(instr, RB_MASK, RB_LOW)
407 #define get_int_field_imm(instr) ((instr & IMM_MASK) >> IMM_LOW)
408 #define get_int_field_r1(instr) ((instr & RA_MASK) >> RA_LOW)
409
410 static char *
411 get_field (long instr, long mask, unsigned short low) 
412 {
413   char tmpstr[25];
414   sprintf(tmpstr, "%s%d", register_prefix, (int)((instr & mask) >> low));
415   return(strdup(tmpstr));
416 }
417
418 static char *
419 get_field_imm (long instr) 
420 {
421   char tmpstr[25];
422   sprintf(tmpstr, "%d", (short)((instr & IMM_MASK) >> IMM_LOW));
423   return(strdup(tmpstr));
424 }
425
426 static char *
427 get_field_imm5 (long instr) 
428 {
429   char tmpstr[25];
430   sprintf(tmpstr, "%d", (short)((instr & IMM5_MASK) >> IMM_LOW));
431   return(strdup(tmpstr));
432 }
433
434 static char *
435 get_field_imm12 (long instr) 
436 {
437   char tmpstr[25];
438   sprintf(tmpstr, "%s%d", fsl_register_prefix, (short)((instr & IMM12_MASK) >> IMM_LOW));
439   return(strdup(tmpstr));
440 }
441
442 static char *
443 get_field_imm14 (long instr) 
444 {
445   char tmpstr[25];
446   sprintf(tmpstr, "%d", (short)((instr & IMM14_MASK) >> IMM_LOW));
447   return(strdup(tmpstr));
448 }
449
450 #if 0
451 static char *
452 get_field_unsigned_imm (long instr) 
453 {
454   char tmpstr[25];
455   sprintf(tmpstr, "%d", (int)((instr & IMM_MASK) >> IMM_LOW));
456   return(strdup(tmpstr));
457 }
458 #endif
459
460 /*
461   char *
462   get_field_special (instr) 
463   long instr;
464   {
465   char tmpstr[25];
466   
467   sprintf(tmpstr, "%s%s", register_prefix, (((instr & IMM_MASK) >> IMM_LOW) & REG_MSR_MASK) == 0 ? "pc" : "msr");
468   
469   return(strdup(tmpstr));
470   }
471 */
472
473 static char *
474 get_field_special (long instr, struct op_code_struct * op) 
475 {
476    char tmpstr[25];
477    char spr[5];
478
479    switch ( (((instr & IMM_MASK) >> IMM_LOW) ^ op->immval_mask) ) {
480    case REG_MSR_MASK :
481       strcpy(spr, "msr");
482       break;
483    case REG_PC_MASK :
484       strcpy(spr, "pc");
485       break;
486    case REG_EAR_MASK :
487       strcpy(spr, "ear");
488       break;
489    case REG_ESR_MASK :
490       strcpy(spr, "esr");
491       break;
492    case REG_FSR_MASK :
493       strcpy(spr, "fsr");
494       break;      
495    default :
496       strcpy(spr, "pc");
497       break;
498    }
499    
500    sprintf(tmpstr, "%s%s", register_prefix, spr);
501    return(strdup(tmpstr));
502 }
503
504 static unsigned long
505 read_insn_microblaze(bfd_vma memaddr, struct disassemble_info *info,
506                      struct op_code_struct ** opr)
507 {
508   unsigned char       ibytes[4];
509   int                 status;
510   struct op_code_struct * op;
511   unsigned long inst;
512
513   status = info->read_memory_func (memaddr, ibytes, 4, info);
514
515   if (status != 0) 
516     {
517       info->memory_error_func (status, memaddr, info);
518       return 0;
519     }
520
521   if (info->endian == BFD_ENDIAN_BIG)
522     inst = (ibytes[0] << 24) | (ibytes[1] << 16) | (ibytes[2] << 8) | ibytes[3];
523   else if (info->endian == BFD_ENDIAN_LITTLE)
524     inst = (ibytes[3] << 24) | (ibytes[2] << 16) | (ibytes[1] << 8) | ibytes[0];
525   else
526     abort ();
527
528   /* Just a linear search of the table.  */
529   for (op = opcodes; op->name != 0; op ++)
530     if (op->bit_sequence == (inst & op->opcode_mask))
531       break;
532
533   *opr = op;
534   return inst;
535 }
536
537
538 int 
539 print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
540 {
541   fprintf_ftype       fprintf = info->fprintf_func;
542   void *              stream = info->stream;
543   unsigned long       inst, prev_inst;
544   struct op_code_struct * op, *pop;
545   int                 immval = 0;
546   boolean             immfound = false;
547   static bfd_vma prev_insn_addr = -1; /*init the prev insn addr */
548   static int     prev_insn_vma = -1;  /*init the prev insn vma */
549   int            curr_insn_vma = info->buffer_vma;
550
551   info->bytes_per_chunk = 4;
552
553   inst = read_insn_microblaze (memaddr, info, &op);
554   if (inst == 0)
555     return -1;
556   
557   if (prev_insn_vma == curr_insn_vma) {
558   if (memaddr-(info->bytes_per_chunk) == prev_insn_addr) {
559     prev_inst = read_insn_microblaze (prev_insn_addr, info, &pop);
560     if (prev_inst == 0)
561       return -1;
562     if (pop->instr == imm) {
563       immval = (get_int_field_imm(prev_inst) << 16) & 0xffff0000;
564       immfound = true;
565     }
566     else {
567       immval = 0;
568       immfound = false;
569     }
570   }
571   }
572   /* make curr insn as prev insn */
573   prev_insn_addr = memaddr;
574   prev_insn_vma = curr_insn_vma;
575
576   if (op->name == 0)
577     fprintf (stream, ".short 0x%04x", inst);
578   else
579     {
580       fprintf (stream, "%s", op->name);
581       
582       switch (op->inst_type)
583         {
584   case INST_TYPE_RD_R1_R2:
585      fprintf(stream, "\t%s, %s, %s", get_field_rd(inst), get_field_r1(inst), get_field_r2(inst));
586      break;
587         case INST_TYPE_RD_R1_IMM:
588           fprintf(stream, "\t%s, %s, %s", get_field_rd(inst), get_field_r1(inst), get_field_imm(inst));
589           if (info->print_address_func && get_int_field_r1(inst) == 0 && info->symbol_at_address_func) {
590             if (immfound)
591               immval |= (get_int_field_imm(inst) & 0x0000ffff);
592             else {
593               immval = get_int_field_imm(inst);
594               if (immval & 0x8000)
595                 immval |= 0xFFFF0000;
596             }
597             if (immval > 0 && info->symbol_at_address_func(immval, info)) {
598               fprintf (stream, "\t// ");
599               info->print_address_func (immval, info);
600             }
601           }
602           break;
603         case INST_TYPE_RD_R1_IMM5:
604           fprintf(stream, "\t%s, %s, %s", get_field_rd(inst), get_field_r1(inst), get_field_imm5(inst));
605           break;
606         case INST_TYPE_RD_IMM12:
607           fprintf(stream, "\t%s, %s", get_field_rd(inst), get_field_imm12(inst));
608           break;
609         case INST_TYPE_R1_IMM12:
610           fprintf(stream, "\t%s, %s", get_field_r1(inst), get_field_imm12(inst));
611           break;
612         case INST_TYPE_RD_SPECIAL:
613           fprintf(stream, "\t%s, %s", get_field_rd(inst), get_field_special(inst, op));
614           break;
615         case INST_TYPE_SPECIAL_R1:
616           fprintf(stream, "\t%s, %s", get_field_special(inst, op), get_field_r1(inst));
617           break;
618         case INST_TYPE_RD_R1:
619           fprintf(stream, "\t%s, %s", get_field_rd(inst), get_field_r1(inst));
620           break;
621         case INST_TYPE_R1_R2:
622           fprintf(stream, "\t%s, %s", get_field_r1(inst), get_field_r2(inst));
623           break;
624         case INST_TYPE_R1_IMM:
625           fprintf(stream, "\t%s, %s", get_field_r1(inst), get_field_imm(inst));
626           /* The non-pc relative instructions are returns, which shouldn't 
627              have a label printed */
628           if (info->print_address_func && op->inst_offset_type == INST_PC_OFFSET && info->symbol_at_address_func) {
629             if (immfound)
630               immval |= (get_int_field_imm(inst) & 0x0000ffff);
631             else {
632               immval = get_int_field_imm(inst);
633               if (immval & 0x8000)
634                 immval |= 0xFFFF0000;
635             }
636             immval += memaddr;
637             if (immval > 0 && info->symbol_at_address_func(immval, info)) {
638               fprintf (stream, "\t// ");
639               info->print_address_func (immval, info);
640             } else {
641               fprintf (stream, "\t\t// ");
642               fprintf (stream, "%x", immval);
643             }
644           }
645           break;
646         case INST_TYPE_RD_IMM:
647           fprintf(stream, "\t%s, %s", get_field_rd(inst), get_field_imm(inst));
648           if (info->print_address_func && info->symbol_at_address_func) {
649             if (immfound)
650               immval |= (get_int_field_imm(inst) & 0x0000ffff);
651             else {
652               immval = get_int_field_imm(inst);
653               if (immval & 0x8000)
654                 immval |= 0xFFFF0000;
655             }
656             if (op->inst_offset_type == INST_PC_OFFSET)
657               immval += (int) memaddr;
658             if (info->symbol_at_address_func(immval, info)) {
659               fprintf (stream, "\t// ");
660               info->print_address_func (immval, info);
661             } 
662           }
663           break;
664         case INST_TYPE_IMM:
665           fprintf(stream, "\t%s", get_field_imm(inst));
666           if (info->print_address_func && info->symbol_at_address_func && op->instr != imm) {
667             if (immfound)
668               immval |= (get_int_field_imm(inst) & 0x0000ffff);
669             else {
670               immval = get_int_field_imm(inst);
671               if (immval & 0x8000)
672                 immval |= 0xFFFF0000;
673             }
674             if (op->inst_offset_type == INST_PC_OFFSET)
675               immval += (int) memaddr;
676             if (immval > 0 && info->symbol_at_address_func(immval, info)) {
677               fprintf (stream, "\t// ");
678               info->print_address_func (immval, info);
679             } else if (op->inst_offset_type == INST_PC_OFFSET) {
680               fprintf (stream, "\t\t// ");
681               fprintf (stream, "%x", immval);
682             }
683           }
684           break;
685         case INST_TYPE_RD_R2:
686           fprintf(stream, "\t%s, %s", get_field_rd(inst), get_field_r2(inst));
687           break;
688   case INST_TYPE_R2:
689      fprintf(stream, "\t%s", get_field_r2(inst));
690      break;
691   case INST_TYPE_R1:
692      fprintf(stream, "\t%s", get_field_r1(inst));
693      break;
694   case INST_TYPE_RD_R1_SPECIAL:
695      fprintf(stream, "\t%s, %s", get_field_rd(inst), get_field_r2(inst));
696      break;
697   case INST_TYPE_RD_IMM14:
698      fprintf(stream, "\t%s, %s", get_field_rd(inst), get_field_imm14(inst));
699      break;
700      /* For tuqula instruction */
701   case INST_TYPE_RD:
702      fprintf(stream, "\t%s", get_field_rd(inst));
703      break;
704      
705   default:
706           /* if the disassembler lags the instruction set */
707           fprintf (stream, "\tundecoded operands, inst is 0x%04x", inst);
708           break;
709         }
710     }
711   
712   /* Say how many bytes we consumed? */
713   return 4;
714 }
715
716 #if 0
717 static enum microblaze_instr
718 get_insn_microblaze (long inst, boolean *isunsignedimm,
719                      enum microblaze_instr_type *insn_type,
720                      short *delay_slots ) 
721 {
722   struct op_code_struct * op;
723   *isunsignedimm = false;
724
725   /* Just a linear search of the table.  */
726   for (op = opcodes; op->name != 0; op ++)
727     if (op->bit_sequence == (inst & op->opcode_mask))
728       break;
729
730   if (op->name == 0)
731     return invalid_inst;
732   else {
733     *isunsignedimm = (op->inst_type == INST_TYPE_RD_R1_UNSIGNED_IMM);
734     *insn_type = op->instr_type;
735     *delay_slots = op->delay_slots;
736     return op->instr;
737   }
738 }
739 #endif
740
741 #if 0
742 static short
743 get_delay_slots_microblaze ( long inst )
744 {
745   boolean isunsignedimm;
746   enum microblaze_instr_type insn_type;
747   enum microblaze_instr op;
748   short delay_slots;
749
750   op = get_insn_microblaze( inst, &isunsignedimm, &insn_type, &delay_slots);
751   if (op == invalid_inst)
752     return 0;
753   else 
754     return delay_slots;
755 }
756 #endif
757
758 #if 0
759 static enum microblaze_instr
760 microblaze_decode_insn (long insn, int *rd, int *ra, int *rb, int *imm)
761 {
762   enum microblaze_instr op;
763   boolean t1;
764   enum microblaze_instr_type t2;
765   short t3;
766
767   op = get_insn_microblaze(insn, &t1, &t2, &t3);
768   *rd = (insn & RD_MASK) >> RD_LOW;
769   *ra = (insn & RA_MASK) >> RA_LOW;
770   *rb = (insn & RB_MASK) >> RB_LOW;
771   t3 = (insn & IMM_MASK) >> IMM_LOW;
772   *imm = (int) t3;
773   return (op);
774 }
775 #endif
776
777 #if 0
778 static unsigned long
779 microblaze_get_target_address (long inst, boolean immfound, int immval,
780                                long pcval, long r1val, long r2val,
781                                boolean *targetvalid,
782                                boolean *unconditionalbranch)
783 {
784   struct op_code_struct * op;
785   long targetaddr = 0;
786
787   *unconditionalbranch = false;
788   /* Just a linear search of the table.  */
789   for (op = opcodes; op->name != 0; op ++)
790     if (op->bit_sequence == (inst & op->opcode_mask))
791       break;
792
793   if (op->name == 0) {
794     *targetvalid = false;
795   } else if (op->instr_type == branch_inst) {
796     switch (op->inst_type) {
797     case INST_TYPE_R2:
798       *unconditionalbranch = true;
799       /* fallthru */
800     case INST_TYPE_RD_R2:
801     case INST_TYPE_R1_R2:
802       targetaddr = r2val;
803       *targetvalid = true;
804       if (op->inst_offset_type == INST_PC_OFFSET)
805         targetaddr += pcval;
806       break;
807     case INST_TYPE_IMM:
808       *unconditionalbranch = true;
809       /* fallthru */
810     case INST_TYPE_RD_IMM:
811     case INST_TYPE_R1_IMM:
812       if (immfound) {
813         targetaddr = (immval << 16) & 0xffff0000;
814         targetaddr |= (get_int_field_imm(inst) & 0x0000ffff);
815       } else {
816         targetaddr = get_int_field_imm(inst);
817         if (targetaddr & 0x8000)
818           targetaddr |= 0xFFFF0000;
819       }
820       if (op->inst_offset_type == INST_PC_OFFSET)
821         targetaddr += pcval;
822       *targetvalid = true;
823       break;
824     default:
825       *targetvalid = false;
826       break;
827     }
828   } else if (op->instr_type == return_inst) {
829       if (immfound) {
830         targetaddr = (immval << 16) & 0xffff0000;
831         targetaddr |= (get_int_field_imm(inst) & 0x0000ffff);
832       } else {
833         targetaddr = get_int_field_imm(inst);
834         if (targetaddr & 0x8000)
835           targetaddr |= 0xFFFF0000;
836       }
837       targetaddr += r1val;
838       *targetvalid = true;
839   } else {
840     *targetvalid = false;
841   }
842   return targetaddr;
843 }
844 #endif