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