]>
Commit | Line | Data |
---|---|---|
e90e390c EI |
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 | |
8167ee88 | 15 | along with this program; if not, see <http://www.gnu.org/licenses/>. */ |
e90e390c EI |
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 | |
8167ee88 | 57 | along with this program; if not, see <http://www.gnu.org/licenses/>. */ |
e90e390c EI |
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 |