]> git.proxmox.com Git - qemu.git/blob - microblaze-dis.c
ARM back-end: Fix encode_imm
[qemu.git] / 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