1 // See LICENSE for license details.
14 virtual string
to_string(insn_t val
) const = 0;
18 static const char* xpr
[] = {
19 "zero", "ra", "s0", "s1", "s2", "s3", "s4", "s5",
20 "s6", "s7", "s8", "s9", "s10", "s11", "sp", "tp",
21 "v0", "v1", "a0", "a1", "a2", "a3", "a4", "a5",
22 "a6", "a7", "t0", "t1", "t2", "t3", "t4", "gp"
25 static const char* fpr
[] = {
26 "fs0", "fs1", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7",
27 "fs8", "fs9", "fs10", "fs11", "fs12", "fs13", "fs14", "fs15",
28 "fv0", "fv1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5",
29 "fa6", "fa7", "ft0", "ft1", "ft2", "ft3", "ft4", "ft5"
32 static const char* vxpr
[] = {
33 "vx0", "vx1", "vx2", "vx3", "vx4", "vx5", "vx6", "vx7",
34 "vx8", "vx9", "vx10", "vx11", "vx12", "vx13", "vx14", "vx15",
35 "vx16", "vx17", "vx18", "vx19", "vx20", "vx21", "vx22", "vx23",
36 "vx24", "vx25", "vx26", "vx27", "vx28", "vx29", "vx30", "vx31"
39 static const char* vfpr
[] = {
40 "vf0", "vf1", "vf2", "vf3", "vf4", "vf5", "vf6", "vf7",
41 "vf8", "vf9", "vf10", "vf11", "vf12", "vf13", "vf14", "vf15",
42 "vf16", "vf17", "vf18", "vf19", "vf20", "vf21", "vf22", "vf23",
43 "vf24", "vf25", "vf26", "vf27", "vf28", "vf29", "vf30", "vf31"
46 struct : public arg_t
{
47 string
to_string(insn_t insn
) const {
48 return ::to_string((int)insn
.i_imm()) + '(' + xpr
[insn
.rs1()] + ')';
52 struct : public arg_t
{
53 string
to_string(insn_t insn
) const {
54 return ::to_string((int)insn
.s_imm()) + '(' + xpr
[insn
.rs1()] + ')';
58 struct : public arg_t
{
59 string
to_string(insn_t insn
) const {
60 return string("0(") + xpr
[insn
.rs1()] + ')';
64 struct : public arg_t
{
65 std::string
to_string(insn_t insn
) const {
66 return xpr
[insn
.rd()];
70 struct : public arg_t
{
71 std::string
to_string(insn_t insn
) const {
72 return xpr
[insn
.rs1()];
76 struct : public arg_t
{
77 std::string
to_string(insn_t insn
) const {
78 return xpr
[insn
.rs2()];
82 struct : public arg_t
{
83 std::string
to_string(insn_t insn
) const {
84 return fpr
[insn
.rd()];
88 struct : public arg_t
{
89 std::string
to_string(insn_t insn
) const {
90 return fpr
[insn
.rs1()];
94 struct : public arg_t
{
95 std::string
to_string(insn_t insn
) const {
96 return fpr
[insn
.rs2()];
100 struct : public arg_t
{
101 std::string
to_string(insn_t insn
) const {
102 return fpr
[insn
.rs3()];
106 struct : public arg_t
{
107 std::string
to_string(insn_t insn
) const {
108 return vxpr
[insn
.rd()];
112 struct : public arg_t
{
113 std::string
to_string(insn_t insn
) const {
114 return vxpr
[insn
.rs1()];
118 struct : public arg_t
{
119 std::string
to_string(insn_t insn
) const {
120 return vfpr
[insn
.rd()];
124 struct : public arg_t
{
125 std::string
to_string(insn_t insn
) const {
126 return vfpr
[insn
.rs1()];
130 struct : public arg_t
{
131 std::string
to_string(insn_t insn
) const {
132 return ::to_string(insn
.i_imm() & 0x3f);
136 struct : public arg_t
{
137 std::string
to_string(insn_t insn
) const {
138 return ::to_string((insn
.i_imm() >> 6) & 0x3f);
142 struct : public arg_t
{
143 std::string
to_string(insn_t insn
) const {
144 return string("pcr") + xpr
[insn
.rs1()];
148 struct : public arg_t
{
149 std::string
to_string(insn_t insn
) const {
150 return ::to_string((int)insn
.i_imm());
154 struct : public arg_t
{
155 std::string
to_string(insn_t insn
) const {
157 s
<< std::hex
<< "0x" << ((uint32_t)insn
.u_imm() >> 12);
162 struct : public arg_t
{
163 std::string
to_string(insn_t insn
) const {
165 int32_t target
= insn
.sb_imm();
166 char sign
= target
>= 0 ? '+' : '-';
167 s
<< "pc " << sign
<< ' ' << abs(target
);
172 struct : public arg_t
{
173 std::string
to_string(insn_t insn
) const {
175 int32_t target
= insn
.sb_imm();
176 char sign
= target
>= 0 ? '+' : '-';
177 s
<< "pc " << sign
<< std::hex
<< " 0x" << abs(target
);
185 disasm_insn_t(const char* name
, uint32_t match
, uint32_t mask
,
186 const std::vector
<const arg_t
*>& args
)
187 : match(match
), mask(mask
), args(args
), name(name
) {}
189 bool operator == (insn_t insn
) const
191 return (insn
.bits() & mask
) == match
;
194 std::string
to_string(insn_t insn
) const
198 for (len
= 0; name
[len
]; len
++)
199 s
<< (name
[len
] == '_' ? '.' : name
[len
]);
203 s
<< std::string(std::max(1, 8 - len
), ' ');
204 for (size_t i
= 0; i
< args
.size()-1; i
++)
205 s
<< args
[i
]->to_string(insn
) << ", ";
206 s
<< args
[args
.size()-1]->to_string(insn
);
211 uint32_t get_match() const { return match
; }
212 uint32_t get_mask() const { return mask
; }
217 std::vector
<const arg_t
*> args
;
221 std::string
disassembler::disassemble(insn_t insn
)
223 const disasm_insn_t
* disasm_insn
= lookup(insn
);
224 return disasm_insn
? disasm_insn
->to_string(insn
) : "unknown";
227 disassembler::disassembler()
229 const uint32_t mask_rd
= 0x1fUL
<< 7;
230 const uint32_t match_rd_ra
= 1UL << 7;
231 const uint32_t mask_rs1
= 0x1fUL
<< 15;
232 const uint32_t match_rs1_ra
= 1UL << 15;
233 const uint32_t mask_rs2
= 0x1fUL
<< 15;
234 const uint32_t mask_imm
= 0xfffUL
<< 20;
236 #define DECLARE_INSN(code, match, mask) \
237 const uint32_t match_##code = match; \
238 const uint32_t mask_##code = mask;
242 // explicit per-instruction disassembly
243 #define DISASM_INSN(name, code, extra, ...) \
244 add_insn(new disasm_insn_t(name, match_##code, mask_##code | (extra), __VA_ARGS__));
245 #define DEFINE_NOARG(code) \
246 add_insn(new disasm_insn_t(#code, match_##code, mask_##code, {}));
247 #define DEFINE_DTYPE(code) DISASM_INSN(#code, code, 0, {&xrd})
248 #define DEFINE_RTYPE(code) DISASM_INSN(#code, code, 0, {&xrd, &xrs1, &xrs2})
249 #define DEFINE_ITYPE(code) DISASM_INSN(#code, code, 0, {&xrd, &xrs1, &imm})
250 #define DEFINE_I0TYPE(name, code) DISASM_INSN(name, code, mask_rs1, {&xrd, &imm})
251 #define DEFINE_I1TYPE(name, code) DISASM_INSN(name, code, mask_imm, {&xrd, &xrs1})
252 #define DEFINE_I2TYPE(name, code) DISASM_INSN(name, code, mask_rd | mask_imm, {&xrs1})
253 #define DEFINE_LTYPE(code) DISASM_INSN(#code, code, 0, {&xrd, &bigimm})
254 #define DEFINE_BTYPE(code) DISASM_INSN(#code, code, 0, {&xrs1, &xrs2, &branch_target})
255 #define DEFINE_B0TYPE(name, code) DISASM_INSN(name, code, mask_rs1 | mask_rs2, {&branch_target})
256 #define DEFINE_B1TYPE(name, code) DISASM_INSN(name, code, mask_rs2, {&xrs1, &branch_target})
257 #define DEFINE_XLOAD(code) DISASM_INSN(#code, code, 0, {&xrd, &load_address})
258 #define DEFINE_XSTORE(code) DISASM_INSN(#code, code, 0, {&xrs2, &store_address})
259 #define DEFINE_XAMO(code) DISASM_INSN(#code, code, 0, {&xrd, &xrs2, &amo_address})
260 #define DEFINE_FLOAD(code) DISASM_INSN(#code, code, 0, {&frd, &load_address})
261 #define DEFINE_FSTORE(code) DISASM_INSN(#code, code, 0, {&frs2, &store_address})
262 #define DEFINE_FRTYPE(code) DISASM_INSN(#code, code, 0, {&frd, &frs1, &frs2})
263 #define DEFINE_FR1TYPE(code) DISASM_INSN(#code, code, 0, {&frd, &frs1})
264 #define DEFINE_FR3TYPE(code) DISASM_INSN(#code, code, 0, {&frd, &frs1, &frs2, &frs3})
265 #define DEFINE_FXTYPE(code) DISASM_INSN(#code, code, 0, {&xrd, &frs1})
266 #define DEFINE_XFTYPE(code) DISASM_INSN(#code, code, 0, {&frd, &xrs1})
281 DEFINE_XAMO(amoadd_w
)
282 DEFINE_XAMO(amoswap_w
)
283 DEFINE_XAMO(amoand_w
)
285 DEFINE_XAMO(amomin_w
)
286 DEFINE_XAMO(amomax_w
)
287 DEFINE_XAMO(amominu_w
)
288 DEFINE_XAMO(amomaxu_w
)
289 DEFINE_XAMO(amoadd_d
)
290 DEFINE_XAMO(amoswap_d
)
291 DEFINE_XAMO(amoand_d
)
293 DEFINE_XAMO(amomin_d
)
294 DEFINE_XAMO(amomax_d
)
295 DEFINE_XAMO(amominu_d
)
296 DEFINE_XAMO(amomaxu_d
)
309 add_insn(new disasm_insn_t("j", match_jal
, mask_jal
| mask_rd
, {&jump_target
}));
310 add_insn(new disasm_insn_t("jal", match_jal
| match_rd_ra
, mask_jal
| mask_rd
, {&jump_target
}));
311 add_insn(new disasm_insn_t("jal", match_jal
, mask_jal
, {&xrd
, &jump_target
}));
313 DEFINE_B0TYPE("b", beq
);
314 DEFINE_B1TYPE("beqz", beq
);
315 DEFINE_B1TYPE("bnez", bne
);
316 DEFINE_B1TYPE("bltz", blt
);
317 DEFINE_B1TYPE("bgez", bge
);
328 DEFINE_I2TYPE("jr", jalr
);
329 add_insn(new disasm_insn_t("jalr", match_jalr
| match_rd_ra
, mask_jalr
| mask_rd
| mask_imm
, {&xrs1
}));
330 add_insn(new disasm_insn_t("ret", match_jalr
| match_rs1_ra
, mask_jalr
| mask_rd
| mask_rs1
| mask_imm
, {}));
333 add_insn(new disasm_insn_t("nop", match_addi
, mask_addi
| mask_rd
| mask_rs1
| mask_imm
, {}));
334 DEFINE_I0TYPE("li", addi
);
335 DEFINE_I1TYPE("move", addi
);
363 DEFINE_RTYPE(mulhsu
);
379 DEFINE_NOARG(syscall
);
382 DEFINE_NOARG(fence_i
);
384 DEFINE_DTYPE(rdcycle
);
385 DEFINE_DTYPE(rdtime
);
386 DEFINE_DTYPE(rdinstret
);
388 add_insn(new disasm_insn_t("mtpcr", match_mtpcr
, mask_mtpcr
| mask_rd
, {&xrs2
, &pcr
}));
389 add_insn(new disasm_insn_t("mtpcr", match_mtpcr
, mask_mtpcr
, {&xrd
, &xrs2
, &pcr
}));
390 add_insn(new disasm_insn_t("mfpcr", match_mfpcr
, mask_mfpcr
, {&xrd
, &pcr
}));
391 add_insn(new disasm_insn_t("setpcr", match_setpcr
, mask_setpcr
, {&xrd
, &pcr
, &imm
}));
392 add_insn(new disasm_insn_t("clearpcr", match_clearpcr
, mask_clearpcr
, {&xrd
, &pcr
, &imm
}));
395 DEFINE_FRTYPE(fadd_s
);
396 DEFINE_FRTYPE(fsub_s
);
397 DEFINE_FRTYPE(fmul_s
);
398 DEFINE_FRTYPE(fdiv_s
);
399 DEFINE_FR1TYPE(fsqrt_s
);
400 DEFINE_FRTYPE(fmin_s
);
401 DEFINE_FRTYPE(fmax_s
);
402 DEFINE_FR3TYPE(fmadd_s
);
403 DEFINE_FR3TYPE(fmsub_s
);
404 DEFINE_FR3TYPE(fnmadd_s
);
405 DEFINE_FR3TYPE(fnmsub_s
);
406 DEFINE_FRTYPE(fsgnj_s
);
407 DEFINE_FRTYPE(fsgnjn_s
);
408 DEFINE_FRTYPE(fsgnjx_s
);
409 DEFINE_FR1TYPE(fcvt_s_d
);
410 DEFINE_XFTYPE(fcvt_s_l
);
411 DEFINE_XFTYPE(fcvt_s_lu
);
412 DEFINE_XFTYPE(fcvt_s_w
);
413 DEFINE_XFTYPE(fcvt_s_wu
);
414 DEFINE_XFTYPE(fcvt_s_wu
);
415 DEFINE_XFTYPE(fmv_s_x
);
416 DEFINE_FXTYPE(fcvt_l_s
);
417 DEFINE_FXTYPE(fcvt_lu_s
);
418 DEFINE_FXTYPE(fcvt_w_s
);
419 DEFINE_FXTYPE(fcvt_wu_s
);
420 DEFINE_FXTYPE(fmv_x_s
);
421 DEFINE_FXTYPE(feq_s
);
422 DEFINE_FXTYPE(flt_s
);
423 DEFINE_FXTYPE(fle_s
);
425 DEFINE_FRTYPE(fadd_d
);
426 DEFINE_FRTYPE(fsub_d
);
427 DEFINE_FRTYPE(fmul_d
);
428 DEFINE_FRTYPE(fdiv_d
);
429 DEFINE_FR1TYPE(fsqrt_d
);
430 DEFINE_FRTYPE(fmin_d
);
431 DEFINE_FRTYPE(fmax_d
);
432 DEFINE_FR3TYPE(fmadd_d
);
433 DEFINE_FR3TYPE(fmsub_d
);
434 DEFINE_FR3TYPE(fnmadd_d
);
435 DEFINE_FR3TYPE(fnmsub_d
);
436 DEFINE_FRTYPE(fsgnj_d
);
437 DEFINE_FRTYPE(fsgnjn_d
);
438 DEFINE_FRTYPE(fsgnjx_d
);
439 DEFINE_FR1TYPE(fcvt_d_s
);
440 DEFINE_XFTYPE(fcvt_d_l
);
441 DEFINE_XFTYPE(fcvt_d_lu
);
442 DEFINE_XFTYPE(fcvt_d_w
);
443 DEFINE_XFTYPE(fcvt_d_wu
);
444 DEFINE_XFTYPE(fcvt_d_wu
);
445 DEFINE_XFTYPE(fmv_d_x
);
446 DEFINE_FXTYPE(fcvt_l_d
);
447 DEFINE_FXTYPE(fcvt_lu_d
);
448 DEFINE_FXTYPE(fcvt_w_d
);
449 DEFINE_FXTYPE(fcvt_wu_d
);
450 DEFINE_FXTYPE(fmv_x_d
);
451 DEFINE_FXTYPE(feq_d
);
452 DEFINE_FXTYPE(flt_d
);
453 DEFINE_FXTYPE(fle_d
);
455 add_insn(new disasm_insn_t("fssr", match_fssr
, mask_fssr
| mask_rd
, {&xrs1
}));
456 add_insn(new disasm_insn_t("fssr", match_fssr
, mask_fssr
, {&xrd
, &xrs1
}));
459 // provide a default disassembly for all instructions as a fallback
460 #define DECLARE_INSN(code, match, mask) \
461 add_insn(new disasm_insn_t(#code " (args unknown)", match, mask, {}));
466 const disasm_insn_t
* disassembler::lookup(insn_t insn
)
468 size_t idx
= insn
.bits() % HASH_SIZE
;
469 for (size_t j
= 0; j
< chain
[idx
].size(); j
++)
470 if(*chain
[idx
][j
] == insn
)
471 return chain
[idx
][j
];
474 for (size_t j
= 0; j
< chain
[idx
].size(); j
++)
475 if(*chain
[idx
][j
] == insn
)
476 return chain
[idx
][j
];
481 void disassembler::add_insn(disasm_insn_t
* insn
)
483 size_t idx
= HASH_SIZE
;
484 if (insn
->get_mask() % HASH_SIZE
== HASH_SIZE
- 1)
485 idx
= insn
->get_match() % HASH_SIZE
;
486 chain
[idx
].push_back(insn
);
489 disassembler::~disassembler()
491 for (size_t i
= 0; i
< HASH_SIZE
+1; i
++)
492 for (size_t j
= 0; j
< chain
[i
].size(); j
++)