2 * Simple LatticeMico32 disassembler.
4 * Copyright (c) 2012 Michael Walle <michael@walle.cc>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include "qemu/osdep.h"
22 #include "disas/dis-asm.h"
25 LM32_OP_SRUI
= 0, LM32_OP_NORI
, LM32_OP_MULI
, LM32_OP_SH
, LM32_OP_LB
,
26 LM32_OP_SRI
, LM32_OP_XORI
, LM32_OP_LH
, LM32_OP_ANDI
, LM32_OP_XNORI
,
27 LM32_OP_LW
, LM32_OP_LHU
, LM32_OP_SB
, LM32_OP_ADDI
, LM32_OP_ORI
,
28 LM32_OP_SLI
, LM32_OP_LBU
, LM32_OP_BE
, LM32_OP_BG
, LM32_OP_BGE
,
29 LM32_OP_BGEU
, LM32_OP_BGU
, LM32_OP_SW
, LM32_OP_BNE
, LM32_OP_ANDHI
,
30 LM32_OP_CMPEI
, LM32_OP_CMPGI
, LM32_OP_CMPGEI
, LM32_OP_CMPGEUI
,
31 LM32_OP_CMPGUI
, LM32_OP_ORHI
, LM32_OP_CMPNEI
, LM32_OP_SRU
, LM32_OP_NOR
,
32 LM32_OP_MUL
, LM32_OP_DIVU
, LM32_OP_RCSR
, LM32_OP_SR
, LM32_OP_XOR
,
33 LM32_OP_ILL0
, LM32_OP_AND
, LM32_OP_XNOR
, LM32_OP_ILL1
, LM32_OP_SCALL
,
34 LM32_OP_SEXTB
, LM32_OP_ADD
, LM32_OP_OR
, LM32_OP_SL
, LM32_OP_B
,
35 LM32_OP_MODU
, LM32_OP_SUB
, LM32_OP_ILL2
, LM32_OP_WCSR
, LM32_OP_ILL3
,
36 LM32_OP_CALL
, LM32_OP_SEXTH
, LM32_OP_BI
, LM32_OP_CMPE
, LM32_OP_CMPG
,
37 LM32_OP_CMPGE
, LM32_OP_CMPGEU
, LM32_OP_CMPGU
, LM32_OP_CALLI
, LM32_OP_CMPNE
,
41 FMT_INVALID
= 0, FMT_RRI5
, FMT_RRI16
, FMT_IMM26
, FMT_LOAD
, FMT_STORE
,
42 FMT_RRR
, FMT_R
, FMT_RNR
, FMT_CRN
, FMT_CNR
, FMT_BREAK
,
46 LM32_CSR_IE
= 0, LM32_CSR_IM
, LM32_CSR_IP
, LM32_CSR_ICC
, LM32_CSR_DCC
,
47 LM32_CSR_CC
, LM32_CSR_CFG
, LM32_CSR_EBA
, LM32_CSR_DC
, LM32_CSR_DEBA
,
48 LM32_CSR_CFG2
, LM32_CSR_JTX
= 0xe, LM32_CSR_JRX
, LM32_CSR_BP0
,
49 LM32_CSR_BP1
, LM32_CSR_BP2
, LM32_CSR_BP3
, LM32_CSR_WP0
= 0x18,
50 LM32_CSR_WP1
, LM32_CSR_WP2
, LM32_CSR_WP3
,
58 static const Lm32CsrInfo lm32_csr_info
[] = {
59 {LM32_CSR_IE
, "ie", },
60 {LM32_CSR_IM
, "im", },
61 {LM32_CSR_IP
, "ip", },
62 {LM32_CSR_ICC
, "icc", },
63 {LM32_CSR_DCC
, "dcc", },
64 {LM32_CSR_CC
, "cc", },
65 {LM32_CSR_CFG
, "cfg", },
66 {LM32_CSR_EBA
, "eba", },
67 {LM32_CSR_DC
, "dc", },
68 {LM32_CSR_DEBA
, "deba", },
69 {LM32_CSR_CFG2
, "cfg2", },
70 {LM32_CSR_JTX
, "jtx", },
71 {LM32_CSR_JRX
, "jrx", },
72 {LM32_CSR_BP0
, "bp0", },
73 {LM32_CSR_BP1
, "bp1", },
74 {LM32_CSR_BP2
, "bp2", },
75 {LM32_CSR_BP3
, "bp3", },
76 {LM32_CSR_WP0
, "wp0", },
77 {LM32_CSR_WP1
, "wp1", },
78 {LM32_CSR_WP2
, "wp2", },
79 {LM32_CSR_WP3
, "wp3", },
82 static const Lm32CsrInfo
*find_csr_info(int csr
)
84 const Lm32CsrInfo
*info
;
87 for (i
= 0; i
< ARRAY_SIZE(lm32_csr_info
); i
++) {
88 info
= &lm32_csr_info
[i
];
89 if (csr
== info
->csr
) {
103 LM32_REG_R0
= 0, LM32_REG_R1
, LM32_REG_R2
, LM32_REG_R3
, LM32_REG_R4
,
104 LM32_REG_R5
, LM32_REG_R6
, LM32_REG_R7
, LM32_REG_R8
, LM32_REG_R9
,
105 LM32_REG_R10
, LM32_REG_R11
, LM32_REG_R12
, LM32_REG_R13
, LM32_REG_R14
,
106 LM32_REG_R15
, LM32_REG_R16
, LM32_REG_R17
, LM32_REG_R18
, LM32_REG_R19
,
107 LM32_REG_R20
, LM32_REG_R21
, LM32_REG_R22
, LM32_REG_R23
, LM32_REG_R24
,
108 LM32_REG_R25
, LM32_REG_GP
, LM32_REG_FP
, LM32_REG_SP
, LM32_REG_RA
,
109 LM32_REG_EA
, LM32_REG_BA
,
112 static const Lm32RegInfo lm32_reg_info
[] = {
113 {LM32_REG_R0
, "r0", },
114 {LM32_REG_R1
, "r1", },
115 {LM32_REG_R2
, "r2", },
116 {LM32_REG_R3
, "r3", },
117 {LM32_REG_R4
, "r4", },
118 {LM32_REG_R5
, "r5", },
119 {LM32_REG_R6
, "r6", },
120 {LM32_REG_R7
, "r7", },
121 {LM32_REG_R8
, "r8", },
122 {LM32_REG_R9
, "r9", },
123 {LM32_REG_R10
, "r10", },
124 {LM32_REG_R11
, "r11", },
125 {LM32_REG_R12
, "r12", },
126 {LM32_REG_R13
, "r13", },
127 {LM32_REG_R14
, "r14", },
128 {LM32_REG_R15
, "r15", },
129 {LM32_REG_R16
, "r16", },
130 {LM32_REG_R17
, "r17", },
131 {LM32_REG_R18
, "r18", },
132 {LM32_REG_R19
, "r19", },
133 {LM32_REG_R20
, "r20", },
134 {LM32_REG_R21
, "r21", },
135 {LM32_REG_R22
, "r22", },
136 {LM32_REG_R23
, "r23", },
137 {LM32_REG_R24
, "r24", },
138 {LM32_REG_R25
, "r25", },
139 {LM32_REG_GP
, "gp", },
140 {LM32_REG_FP
, "fp", },
141 {LM32_REG_SP
, "sp", },
142 {LM32_REG_RA
, "ra", },
143 {LM32_REG_EA
, "ea", },
144 {LM32_REG_BA
, "ba", },
147 static const Lm32RegInfo
*find_reg_info(int reg
)
149 assert(ARRAY_SIZE(lm32_reg_info
) == 32);
150 return &lm32_reg_info
[reg
& 0x1f];
159 const char *args_fmt
;
162 static const Lm32OpcodeInfo lm32_opcode_info
[] = {
163 /* pseudo instructions */
164 {{0x34000000, 0xffffffff}, "nop", NULL
},
165 {{0xac000002, 0xffffffff}, "break", NULL
},
166 {{0xac000003, 0xffffffff}, "scall", NULL
},
167 {{0xc3e00000, 0xffffffff}, "bret", NULL
},
168 {{0xc3c00000, 0xffffffff}, "eret", NULL
},
169 {{0xc3a00000, 0xffffffff}, "ret", NULL
},
170 {{0xa4000000, 0xfc1f07ff}, "not", "%2, %0"},
171 {{0xb8000000, 0xfc1f07ff}, "mv", "%2, %0"},
172 {{0x71e00000, 0xffe00000}, "mvhi", "%1, %u"},
173 {{0x34000000, 0xffe00000}, "mvi", "%1, %s"},
175 #define _O(op) {op << 26, 0x3f << 26}
176 /* regular opcodes */
177 {_O(LM32_OP_ADD
), "add", "%2, %0, %1" },
178 {_O(LM32_OP_ADDI
), "addi", "%1, %0, %s" },
179 {_O(LM32_OP_AND
), "and", "%2, %0, %1" },
180 {_O(LM32_OP_ANDHI
), "andhi", "%1, %0, %u" },
181 {_O(LM32_OP_ANDI
), "andi", "%1, %0, %u" },
182 {_O(LM32_OP_B
), "b", "%0", },
183 {_O(LM32_OP_BE
), "be", "%1, %0, %r" },
184 {_O(LM32_OP_BG
), "bg", "%1, %0, %r" },
185 {_O(LM32_OP_BGE
), "bge", "%1, %0, %r" },
186 {_O(LM32_OP_BGEU
), "bgeu", "%1, %0, %r" },
187 {_O(LM32_OP_BGU
), "bgu", "%1, %0, %r" },
188 {_O(LM32_OP_BI
), "bi", "%R", },
189 {_O(LM32_OP_BNE
), "bne", "%1, %0, %r" },
190 {_O(LM32_OP_CALL
), "call", "%0", },
191 {_O(LM32_OP_CALLI
), "calli", "%R", },
192 {_O(LM32_OP_CMPE
), "cmpe", "%2, %0, %1" },
193 {_O(LM32_OP_CMPEI
), "cmpei", "%1, %0, %s" },
194 {_O(LM32_OP_CMPG
), "cmpg", "%2, %0, %1" },
195 {_O(LM32_OP_CMPGE
), "cmpge", "%2, %0, %1" },
196 {_O(LM32_OP_CMPGEI
), "cmpgei", "%1, %0, %s" },
197 {_O(LM32_OP_CMPGEU
), "cmpgeu", "%2, %0, %1" },
198 {_O(LM32_OP_CMPGEUI
), "cmpgeui", "%1, %0, %s" },
199 {_O(LM32_OP_CMPGI
), "cmpgi", "%1, %0, %s" },
200 {_O(LM32_OP_CMPGU
), "cmpgu", "%2, %0, %1" },
201 {_O(LM32_OP_CMPGUI
), "cmpgui", "%1, %0, %s" },
202 {_O(LM32_OP_CMPNE
), "cmpne", "%2, %0, %1" },
203 {_O(LM32_OP_CMPNEI
), "cmpnei", "%1, %0, %s" },
204 {_O(LM32_OP_DIVU
), "divu", "%2, %0, %1" },
205 {_O(LM32_OP_LB
), "lb", "%1, (%0+%s)" },
206 {_O(LM32_OP_LBU
), "lbu", "%1, (%0+%s)" },
207 {_O(LM32_OP_LH
), "lh", "%1, (%0+%s)" },
208 {_O(LM32_OP_LHU
), "lhu", "%1, (%0+%s)" },
209 {_O(LM32_OP_LW
), "lw", "%1, (%0+%s)" },
210 {_O(LM32_OP_MODU
), "modu", "%2, %0, %1" },
211 {_O(LM32_OP_MULI
), "muli", "%1, %0, %s" },
212 {_O(LM32_OP_MUL
), "mul", "%2, %0, %1" },
213 {_O(LM32_OP_NORI
), "nori", "%1, %0, %u" },
214 {_O(LM32_OP_NOR
), "nor", "%2, %0, %1" },
215 {_O(LM32_OP_ORHI
), "orhi", "%1, %0, %u" },
216 {_O(LM32_OP_ORI
), "ori", "%1, %0, %u" },
217 {_O(LM32_OP_OR
), "or", "%2, %0, %1" },
218 {_O(LM32_OP_RCSR
), "rcsr", "%2, %c", },
219 {_O(LM32_OP_SB
), "sb", "(%0+%s), %1" },
220 {_O(LM32_OP_SEXTB
), "sextb", "%2, %0", },
221 {_O(LM32_OP_SEXTH
), "sexth", "%2, %0", },
222 {_O(LM32_OP_SH
), "sh", "(%0+%s), %1" },
223 {_O(LM32_OP_SLI
), "sli", "%1, %0, %h" },
224 {_O(LM32_OP_SL
), "sl", "%2, %0, %1" },
225 {_O(LM32_OP_SRI
), "sri", "%1, %0, %h" },
226 {_O(LM32_OP_SR
), "sr", "%2, %0, %1" },
227 {_O(LM32_OP_SRUI
), "srui", "%1, %0, %d" },
228 {_O(LM32_OP_SRU
), "sru", "%2, %0, %s" },
229 {_O(LM32_OP_SUB
), "sub", "%2, %0, %s" },
230 {_O(LM32_OP_SW
), "sw", "(%0+%s), %1" },
231 {_O(LM32_OP_WCSR
), "wcsr", "%c, %1", },
232 {_O(LM32_OP_XNORI
), "xnori", "%1, %0, %u" },
233 {_O(LM32_OP_XNOR
), "xnor", "%2, %0, %1" },
234 {_O(LM32_OP_XORI
), "xori", "%1, %0, %u" },
235 {_O(LM32_OP_XOR
), "xor", "%2, %0, %1" },
239 static const Lm32OpcodeInfo
*find_opcode_info(uint32_t opcode
)
241 const Lm32OpcodeInfo
*info
;
243 for (i
= 0; i
< ARRAY_SIZE(lm32_opcode_info
); i
++) {
244 info
= &lm32_opcode_info
[i
];
245 if ((opcode
& info
->op
.mask
) == info
->op
.code
) {
253 int print_insn_lm32(bfd_vma memaddr
, struct disassemble_info
*info
)
255 fprintf_function fprintf_fn
= info
->fprintf_func
;
256 void *stream
= info
->stream
;
259 const Lm32OpcodeInfo
*opc_info
;
261 const char *args_fmt
;
263 rc
= info
->read_memory_func(memaddr
, insn
, 4, info
);
265 info
->memory_error_func(rc
, memaddr
, info
);
269 fprintf_fn(stream
, "%02x %02x %02x %02x ",
270 insn
[0], insn
[1], insn
[2], insn
[3]);
272 op
= bfd_getb32(insn
);
273 opc_info
= find_opcode_info(op
);
275 fprintf_fn(stream
, "%-8s ", opc_info
->name
);
276 args_fmt
= opc_info
->args_fmt
;
277 while (args_fmt
&& *args_fmt
) {
278 if (*args_fmt
== '%') {
279 switch (*(++args_fmt
)) {
283 r0
= (op
>> 21) & 0x1f;
284 r0_name
= find_reg_info(r0
)->name
;
285 fprintf_fn(stream
, "%s", r0_name
);
291 r1
= (op
>> 16) & 0x1f;
292 r1_name
= find_reg_info(r1
)->name
;
293 fprintf_fn(stream
, "%s", r1_name
);
299 r2
= (op
>> 11) & 0x1f;
300 r2_name
= find_reg_info(r2
)->name
;
301 fprintf_fn(stream
, "%s", r2_name
);
306 const Lm32CsrInfo
*info
;
307 csr
= (op
>> 21) & 0x1f;
308 info
= find_csr_info(csr
);
310 fprintf_fn(stream
, "%s", info
->name
);
312 fprintf_fn(stream
, "0x%x", csr
);
319 fprintf_fn(stream
, "0x%x", u16
);
324 s16
= (int16_t)(op
& 0xffff);
325 fprintf_fn(stream
, "%d", s16
);
330 rela
= memaddr
+ (((int16_t)(op
& 0xffff)) << 2);
331 fprintf_fn(stream
, "%x", rela
);
337 imm26
= (int32_t)((op
& 0x3ffffff) << 6) >> 4;
338 rela
= memaddr
+ imm26
;
339 fprintf_fn(stream
, "%x", rela
);
345 fprintf_fn(stream
, "%d", u5
);
352 fprintf_fn(stream
, "%c", *args_fmt
);
357 fprintf_fn(stream
, ".word 0x%x", op
);