1252a386801444fa88a918608315640af5b7d0a1
[riscv-isa-sim.git] / riscv / disasm.cc
1 #include "disasm.h"
2 #include <string>
3 #include <vector>
4 #include <cstdarg>
5 #include <sstream>
6 #include <stdlib.h>
7
8 class arg_t
9 {
10 public:
11 virtual std::string to_string(insn_t val) const = 0;
12 virtual ~arg_t() {}
13 };
14
15 static const char* xpr_to_string[] = {
16 "zero", "ra", "v0", "v1", "a0", "a1", "a2", "a3",
17 "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
18 "t4", "t5", "t6", "t7", "s0", "s1", "s2", "s3",
19 "s4", "s5", "s6", "s7", "s8", "s9", "sp", "tp"
20 };
21
22 static const char* fpr_to_string[] = {
23 "ft0", "ft1", "fv0", "fv1", "fa0", "fa1", "fa2", "fa3",
24 "fa4", "fa5", "fa6", "fa7", "ft2", "ft3", "ft4", "ft5",
25 "ft6", "ft7", "ft8", "ft9", "fs0", "fs1", "fs2", "fs3",
26 "fs4", "fs5", "fs6", "fs7", "fs8", "fs9", "ft10", "ft11"
27 };
28
29 static const char* vxpr_to_string[] = {
30 "vx0", "vx1", "vx2", "vx3", "vx4", "vx5", "vx6", "vx7",
31 "vx8", "vx9", "vx10", "vx11", "vx12", "vx13", "vx14", "vx15",
32 "vx16", "vx17", "vx18", "vx19", "vx20", "vx21", "vx22", "vx23",
33 "vx24", "vx25", "vx26", "vx27", "vx28", "vx29", "vx30", "vx31"
34 };
35
36 static const char* vfpr_to_string[] = {
37 "vf0", "vf1", "vf2", "vf3", "vf4", "vf5", "vf6", "vf7",
38 "vf8", "vf9", "vf10", "vf11", "vf12", "vf13", "vf14", "vf15",
39 "vf16", "vf17", "vf18", "vf19", "vf20", "vf21", "vf22", "vf23",
40 "vf24", "vf25", "vf26", "vf27", "vf28", "vf29", "vf30", "vf31"
41 };
42
43 class load_address_t : public arg_t
44 {
45 public:
46 load_address_t() {}
47 virtual std::string to_string(insn_t insn) const
48 {
49 std::stringstream s;
50 s << insn.itype.imm12 << '(' << xpr_to_string[insn.itype.rs1] << ')';
51 return s.str();
52 }
53 };
54
55 class store_address_t : public arg_t
56 {
57 public:
58 store_address_t() {}
59 virtual std::string to_string(insn_t insn) const
60 {
61 std::stringstream s;
62 int32_t imm = (int32_t)insn.btype.immlo;
63 imm |= insn.btype.immhi << IMMLO_BITS;
64 s << imm << '(' << xpr_to_string[insn.itype.rs1] << ')';
65 return s.str();
66 }
67 };
68
69 class amo_address_t : public arg_t
70 {
71 public:
72 amo_address_t() {}
73 virtual std::string to_string(insn_t insn) const
74 {
75 std::stringstream s;
76 s << "0(" << xpr_to_string[insn.itype.rs1] << ')';
77 return s.str();
78 }
79 };
80
81 class xrd_reg_t : public arg_t
82 {
83 public:
84 xrd_reg_t() {}
85 virtual std::string to_string(insn_t insn) const
86 {
87 return xpr_to_string[insn.itype.rd];
88 }
89 };
90
91 class xrs1_reg_t : public arg_t
92 {
93 public:
94 xrs1_reg_t() {}
95 virtual std::string to_string(insn_t insn) const
96 {
97 return xpr_to_string[insn.itype.rs1];
98 }
99 };
100
101 class xrs2_reg_t : public arg_t
102 {
103 public:
104 xrs2_reg_t() {}
105 virtual std::string to_string(insn_t insn) const
106 {
107 return xpr_to_string[insn.rtype.rs2];
108 }
109 };
110
111 class frd_reg_t : public arg_t
112 {
113 public:
114 frd_reg_t() {}
115 virtual std::string to_string(insn_t insn) const
116 {
117 return fpr_to_string[insn.ftype.rd];
118 }
119 };
120
121 class frs1_reg_t : public arg_t
122 {
123 public:
124 frs1_reg_t() {}
125 virtual std::string to_string(insn_t insn) const
126 {
127 return fpr_to_string[insn.ftype.rs1];
128 }
129 };
130
131 class frs2_reg_t : public arg_t
132 {
133 public:
134 frs2_reg_t() {}
135 virtual std::string to_string(insn_t insn) const
136 {
137 return fpr_to_string[insn.ftype.rs2];
138 }
139 };
140
141 class frs3_reg_t : public arg_t
142 {
143 public:
144 frs3_reg_t() {}
145 virtual std::string to_string(insn_t insn) const
146 {
147 return fpr_to_string[insn.ftype.rs3];
148 }
149 };
150
151 class vxrd_reg_t : public arg_t
152 {
153 public:
154 vxrd_reg_t() {}
155 virtual std::string to_string(insn_t insn) const
156 {
157 return vxpr_to_string[insn.itype.rd];
158 }
159 };
160
161 class vxrs1_reg_t : public arg_t
162 {
163 public:
164 vxrs1_reg_t() {}
165 virtual std::string to_string(insn_t insn) const
166 {
167 return vxpr_to_string[insn.itype.rs1];
168 }
169 };
170
171 class vfrd_reg_t : public arg_t
172 {
173 public:
174 vfrd_reg_t() {}
175 virtual std::string to_string(insn_t insn) const
176 {
177 return vfpr_to_string[insn.itype.rd];
178 }
179 };
180
181 class vfrs1_reg_t : public arg_t
182 {
183 public:
184 vfrs1_reg_t() {}
185 virtual std::string to_string(insn_t insn) const
186 {
187 return vfpr_to_string[insn.itype.rs1];
188 }
189 };
190
191 class nxregs_reg_t : public arg_t
192 {
193 public:
194 nxregs_reg_t() {}
195 virtual std::string to_string(insn_t insn) const
196 {
197 std::stringstream s;
198 s << (insn.itype.imm12 & 0x3f);
199 return s.str();
200 }
201 };
202
203 class nfregs_reg_t : public arg_t
204 {
205 public:
206 nfregs_reg_t() {}
207 virtual std::string to_string(insn_t insn) const
208 {
209 std::stringstream s;
210 s << ((insn.itype.imm12 >> 6) & 0x3f);
211 return s.str();
212 }
213 };
214
215 class pcr_reg_t : public arg_t
216 {
217 public:
218 pcr_reg_t() {}
219 virtual std::string to_string(insn_t insn) const
220 {
221 std::stringstream s;
222 s << "pcr" << insn.rtype.rs1;
223 return s.str();
224 }
225 };
226
227 class imm_t : public arg_t
228 {
229 public:
230 imm_t() {}
231 virtual std::string to_string(insn_t insn) const
232 {
233 std::stringstream s;
234 s << insn.itype.imm12;
235 return s.str();
236 }
237 };
238
239 class bigimm_t : public arg_t
240 {
241 public:
242 bigimm_t() {}
243 virtual std::string to_string(insn_t insn) const
244 {
245 std::stringstream s;
246 s << std::hex << "0x" << insn.ltype.bigimm;
247 return s.str();
248 }
249 };
250
251 class branch_target_t : public arg_t
252 {
253 public:
254 branch_target_t() {}
255 virtual std::string to_string(insn_t insn) const
256 {
257 std::stringstream s;
258 int32_t target = (int32_t)insn.btype.immlo;
259 target |= insn.btype.immhi << IMMLO_BITS;
260 target <<= BRANCH_ALIGN_BITS;
261 char sign = target >= 0 ? '+' : '-';
262 s << "pc " << sign << std::hex << " 0x" << abs(target);
263 return s.str();
264 }
265 };
266
267 class jump_target_t : public arg_t
268 {
269 public:
270 jump_target_t() {}
271 virtual std::string to_string(insn_t insn) const
272 {
273 std::stringstream s;
274 int32_t target = (int32_t)insn.jtype.target;
275 target <<= JUMP_ALIGN_BITS;
276 char sign = target >= 0 ? '+' : '-';
277 s << "pc " << sign << std::hex << " 0x" << abs(target);
278 return s.str();
279 }
280 };
281
282 // workaround for lack of initializer_list in gcc-4.1
283 class disasm_insn_t
284 {
285 public:
286 disasm_insn_t(const char* name, uint32_t match, uint32_t mask)
287 {
288 init(name, match, mask, 0);
289 }
290 disasm_insn_t(const char* name, uint32_t match, uint32_t mask,
291 const arg_t* a0)
292 {
293 init(name, match, mask, 1, a0);
294 }
295 disasm_insn_t(const char* name, uint32_t match, uint32_t mask,
296 const arg_t* a0, const arg_t* a1)
297 {
298 init(name, match, mask, 2, a0, a1);
299 }
300 disasm_insn_t(const char* name, uint32_t match, uint32_t mask,
301 const arg_t* a0, const arg_t* a1, const arg_t* a2)
302 {
303 init(name, match, mask, 3, a0, a1, a2);
304 }
305 disasm_insn_t(const char* name, uint32_t match, uint32_t mask,
306 const arg_t* a0, const arg_t* a1, const arg_t* a2,
307 const arg_t* a3)
308 {
309 init(name, match, mask, 4, a0, a1, a2, a3);
310 }
311 disasm_insn_t(const char* name, uint32_t match, uint32_t mask,
312 const arg_t* a0, const arg_t* a1, const arg_t* a2,
313 const arg_t* a3, const arg_t* a4)
314 {
315 init(name, match, mask, 5, a0, a1, a2, a3, a4);
316 }
317
318 bool operator == (insn_t insn) const
319 {
320 return (insn.bits & mask) == match;
321 }
322
323 std::string to_string(insn_t insn) const
324 {
325 std::stringstream s;
326 int len;
327 for (len = 0; name[len]; len++)
328 s << (name[len] == '_' ? '.' : name[len]);
329
330 if (args.size())
331 {
332 s << std::string(std::max(1, 8 - len), ' ');
333 for (size_t i = 0; i < args.size()-1; i++)
334 s << args[i]->to_string(insn) << ", ";
335 s << args[args.size()-1]->to_string(insn);
336 }
337 return s.str();
338 }
339
340 uint32_t get_match() const { return match; }
341 uint32_t get_mask() const { return mask; }
342
343 private:
344 uint32_t match;
345 uint32_t mask;
346 std::vector<const arg_t*> args;
347 const char* name;
348
349 void init(const char* name, uint32_t match, uint32_t mask, int n, ...)
350 {
351 va_list vl;
352 va_start(vl, n);
353 for (int i = 0; i < n; i++)
354 args.push_back(va_arg(vl, const arg_t*));
355 va_end(vl);
356 this->match = match;
357 this->mask = mask;
358 this->name = name;
359 }
360 };
361
362 std::string disassembler::disassemble(insn_t insn)
363 {
364 const disasm_insn_t* disasm_insn = lookup(insn);
365 return disasm_insn ? disasm_insn->to_string(insn) : "unknown";
366 }
367
368 disassembler::disassembler()
369 {
370 static const xrd_reg_t _xrd_reg, *xrd_reg = &_xrd_reg;
371 static const xrs1_reg_t _xrs1_reg, *xrs1_reg = &_xrs1_reg;
372 static const load_address_t _load_address, *load_address = &_load_address;
373 static const store_address_t _store_address, *store_address = &_store_address;
374 static const amo_address_t _amo_address, *amo_address = &_amo_address;
375 static const xrs2_reg_t _xrs2_reg, *xrs2_reg = &_xrs2_reg;
376 static const frd_reg_t _frd_reg, *frd_reg = &_frd_reg;
377 static const frs1_reg_t _frs1_reg, *frs1_reg = &_frs1_reg;
378 static const frs2_reg_t _frs2_reg, *frs2_reg = &_frs2_reg;
379 static const frs3_reg_t _frs3_reg, *frs3_reg = &_frs3_reg;
380 static const pcr_reg_t _pcr_reg, *pcr_reg = &_pcr_reg;
381 static const imm_t _imm, *imm = &_imm;
382 static const bigimm_t _bigimm, *bigimm = &_bigimm;
383 static const branch_target_t _branch_target, *branch_target = &_branch_target;
384 static const jump_target_t _jump_target, *jump_target = &_jump_target;
385 static const vxrd_reg_t _vxrd_reg, *vxrd_reg = &_vxrd_reg;
386 static const vxrs1_reg_t _vxrs1_reg, *vxrs1_reg = &_vxrs1_reg;
387 static const vfrd_reg_t _vfrd_reg, *vfrd_reg = &_vfrd_reg;
388 static const vfrs1_reg_t _vfrs1_reg, *vfrs1_reg = &_vfrs1_reg;
389 static const nxregs_reg_t _nxregs_reg, *nxregs_reg = &_nxregs_reg;
390 static const nfregs_reg_t _nfregs_reg, *nfregs_reg = &_nfregs_reg;
391
392 insn_t dummy;
393 dummy.bits = -1, dummy.rtype.rs1 = 0;
394 uint32_t mask_rs1 = ~dummy.bits;
395 dummy.bits = -1, dummy.rtype.rs2 = 0;
396 uint32_t mask_rs2 = ~dummy.bits;
397 dummy.bits = -1, dummy.rtype.rd = 0;
398 uint32_t mask_rd = ~dummy.bits;
399 dummy.bits = -1, dummy.itype.imm12 = 0;
400 uint32_t mask_imm = ~dummy.bits;
401 dummy.bits = 0, dummy.itype.rd = 1;
402 uint32_t match_rd_ra = dummy.bits;
403 dummy.bits = 0, dummy.itype.rs1 = 1;
404 uint32_t match_rs1_ra = dummy.bits;
405
406 #define DECLARE_INSN(code, match, mask) \
407 const uint32_t __attribute__((unused)) match_##code = match; \
408 const uint32_t __attribute__((unused)) mask_##code = mask;
409 #include "opcodes.h"
410 #undef DECLARE_INSN
411
412 // explicit per-instruction disassembly
413 #define DISASM_INSN(name, code, extra, ...) \
414 add_insn(new disasm_insn_t(name, match_##code, mask_##code | (extra), __VA_ARGS__));
415 #define DEFINE_NOARG(code) \
416 add_insn(new disasm_insn_t(#code, match_##code, mask_##code));
417 #define DEFINE_DTYPE(code) DISASM_INSN(#code, code, 0, xrd_reg)
418 #define DEFINE_RTYPE(code) DISASM_INSN(#code, code, 0, xrd_reg, xrs1_reg, xrs2_reg)
419 #define DEFINE_ITYPE(code) DISASM_INSN(#code, code, 0, xrd_reg, xrs1_reg, imm)
420 #define DEFINE_I0TYPE(name, code) DISASM_INSN(name, code, mask_rs1, xrd_reg, imm)
421 #define DEFINE_I1TYPE(name, code) DISASM_INSN(name, code, mask_imm, xrd_reg, xrs1_reg)
422 #define DEFINE_I2TYPE(name, code) DISASM_INSN(name, code, mask_rd | mask_imm, xrs1_reg)
423 #define DEFINE_LTYPE(code) DISASM_INSN(#code, code, 0, xrd_reg, bigimm)
424 #define DEFINE_BTYPE(code) DISASM_INSN(#code, code, 0, xrs1_reg, xrs2_reg, branch_target)
425 #define DEFINE_B0TYPE(name, code) DISASM_INSN(name, code, mask_rs1 | mask_rs2, branch_target)
426 #define DEFINE_B1TYPE(name, code) DISASM_INSN(name, code, mask_rs2, xrs1_reg, branch_target)
427 #define DEFINE_JTYPE(code) DISASM_INSN(#code, code, 0, jump_target)
428 #define DEFINE_XLOAD(code) DISASM_INSN(#code, code, 0, xrd_reg, load_address)
429 #define DEFINE_XSTORE(code) DISASM_INSN(#code, code, 0, xrs2_reg, store_address)
430 #define DEFINE_XAMO(code) DISASM_INSN(#code, code, 0, xrd_reg, xrs2_reg, amo_address)
431 #define DEFINE_FLOAD(code) DISASM_INSN(#code, code, 0, frd_reg, load_address)
432 #define DEFINE_FSTORE(code) DISASM_INSN(#code, code, 0, frs2_reg, store_address)
433 #define DEFINE_FRTYPE(code) DISASM_INSN(#code, code, 0, frd_reg, frs1_reg, frs2_reg)
434 #define DEFINE_FR1TYPE(code) DISASM_INSN(#code, code, 0, frd_reg, frs1_reg)
435 #define DEFINE_FR3TYPE(code) DISASM_INSN(#code, code, 0, frd_reg, frs1_reg, frs2_reg, frs3_reg)
436 #define DEFINE_FXTYPE(code) DISASM_INSN(#code, code, 0, xrd_reg, frs1_reg)
437 #define DEFINE_XFTYPE(code) DISASM_INSN(#code, code, 0, frd_reg, xrs1_reg)
438
439 #define DEFINE_RS1(code) DISASM_INSN(#code, code, 0, xrs1_reg)
440 #define DEFINE_RS1_RS2(code) DISASM_INSN(#code, code, 0, xrs1_reg, xrs2_reg)
441 #define DEFINE_VEC_XMEM(code) DISASM_INSN(#code, code, 0, vxrd_reg, xrs1_reg)
442 #define DEFINE_VEC_XMEMST(code) DISASM_INSN(#code, code, 0, vxrd_reg, xrs1_reg, xrs2_reg)
443 #define DEFINE_VEC_FMEM(code) DISASM_INSN(#code, code, 0, vfrd_reg, xrs1_reg)
444 #define DEFINE_VEC_FMEMST(code) DISASM_INSN(#code, code, 0, vfrd_reg, xrs1_reg, xrs2_reg)
445
446 DEFINE_XLOAD(lb)
447 DEFINE_XLOAD(lbu)
448 DEFINE_XLOAD(lh)
449 DEFINE_XLOAD(lhu)
450 DEFINE_XLOAD(lw)
451 DEFINE_XLOAD(lwu)
452 DEFINE_XLOAD(ld)
453
454 DEFINE_XSTORE(sb)
455 DEFINE_XSTORE(sh)
456 DEFINE_XSTORE(sw)
457 DEFINE_XSTORE(sd)
458
459 DEFINE_XAMO(amoadd_w)
460 DEFINE_XAMO(amoswap_w)
461 DEFINE_XAMO(amoand_w)
462 DEFINE_XAMO(amoor_w)
463 DEFINE_XAMO(amomin_w)
464 DEFINE_XAMO(amomax_w)
465 DEFINE_XAMO(amominu_w)
466 DEFINE_XAMO(amomaxu_w)
467 DEFINE_XAMO(amoadd_d)
468 DEFINE_XAMO(amoswap_d)
469 DEFINE_XAMO(amoand_d)
470 DEFINE_XAMO(amoor_d)
471 DEFINE_XAMO(amomin_d)
472 DEFINE_XAMO(amomax_d)
473 DEFINE_XAMO(amominu_d)
474 DEFINE_XAMO(amomaxu_d)
475
476 DEFINE_FLOAD(flw)
477 DEFINE_FLOAD(fld)
478
479 DEFINE_FSTORE(fsw)
480 DEFINE_FSTORE(fsd)
481
482 DEFINE_JTYPE(j);
483 DEFINE_JTYPE(jal);
484
485 DEFINE_B0TYPE("b", beq);
486 DEFINE_B1TYPE("beqz", beq);
487 DEFINE_B1TYPE("bnez", bne);
488 DEFINE_B1TYPE("bltz", blt);
489 DEFINE_B1TYPE("bgez", bge);
490 DEFINE_BTYPE(beq)
491 DEFINE_BTYPE(bne)
492 DEFINE_BTYPE(blt)
493 DEFINE_BTYPE(bge)
494 DEFINE_BTYPE(bltu)
495 DEFINE_BTYPE(bgeu)
496
497 DEFINE_LTYPE(lui);
498
499 DEFINE_I2TYPE("jr", jalr_j);
500 add_insn(new disasm_insn_t("jalr", match_jalr_c | match_rd_ra, mask_jalr_c | mask_rd | mask_imm, xrs1_reg));
501 add_insn(new disasm_insn_t("ret", match_jalr_r | match_rs1_ra, mask_jalr_r | mask_rd | mask_rs1 | mask_imm));
502 DEFINE_DTYPE(rdnpc);
503 DEFINE_ITYPE(jalr_c);
504 DEFINE_ITYPE(jalr_r);
505 DEFINE_ITYPE(jalr_j);
506
507 add_insn(new disasm_insn_t("nop", match_addi, mask_addi | mask_rd | mask_rs1 | mask_imm));
508 DEFINE_I0TYPE("li", addi);
509 DEFINE_I1TYPE("move", addi);
510 DEFINE_ITYPE(addi);
511 DEFINE_ITYPE(slli);
512 DEFINE_ITYPE(slti);
513 DEFINE_ITYPE(sltiu);
514 DEFINE_ITYPE(xori);
515 DEFINE_ITYPE(srli);
516 DEFINE_ITYPE(srai);
517 DEFINE_ITYPE(ori);
518 DEFINE_ITYPE(andi);
519 DEFINE_ITYPE(addiw);
520 DEFINE_ITYPE(slliw);
521 DEFINE_ITYPE(srliw);
522 DEFINE_ITYPE(sraiw);
523
524 DEFINE_RTYPE(add);
525 DEFINE_RTYPE(sub);
526 DEFINE_RTYPE(sll);
527 DEFINE_RTYPE(slt);
528 DEFINE_RTYPE(sltu);
529 DEFINE_RTYPE(xor);
530 DEFINE_RTYPE(srl);
531 DEFINE_RTYPE(sra);
532 DEFINE_RTYPE(or);
533 DEFINE_RTYPE(and);
534 DEFINE_RTYPE(mul);
535 DEFINE_RTYPE(mulh);
536 DEFINE_RTYPE(mulhu);
537 DEFINE_RTYPE(mulhsu);
538 DEFINE_RTYPE(div);
539 DEFINE_RTYPE(divu);
540 DEFINE_RTYPE(rem);
541 DEFINE_RTYPE(remu);
542 DEFINE_RTYPE(addw);
543 DEFINE_RTYPE(subw);
544 DEFINE_RTYPE(sllw);
545 DEFINE_RTYPE(srlw);
546 DEFINE_RTYPE(sraw);
547 DEFINE_RTYPE(mulw);
548 DEFINE_RTYPE(divw);
549 DEFINE_RTYPE(divuw);
550 DEFINE_RTYPE(remw);
551 DEFINE_RTYPE(remuw);
552
553 DEFINE_NOARG(syscall);
554 DEFINE_NOARG(break);
555 DEFINE_NOARG(fence);
556 DEFINE_NOARG(fence_i);
557
558 DEFINE_DTYPE(rdcycle);
559 DEFINE_DTYPE(rdtime);
560 DEFINE_DTYPE(rdinstret);
561
562 add_insn(new disasm_insn_t("mtpcr", match_mtpcr, mask_mtpcr | mask_rd, xrs2_reg, pcr_reg));
563 add_insn(new disasm_insn_t("mtpcr", match_mtpcr, mask_mtpcr, xrd_reg, xrs2_reg, pcr_reg));
564 add_insn(new disasm_insn_t("mfpcr", match_mfpcr, mask_mfpcr, xrd_reg, pcr_reg));
565 add_insn(new disasm_insn_t("setpcr", match_setpcr, mask_setpcr, xrd_reg, pcr_reg, imm));
566 add_insn(new disasm_insn_t("clearpcr", match_clearpcr, mask_clearpcr, xrd_reg, pcr_reg, imm));
567 DEFINE_NOARG(eret)
568 DEFINE_NOARG(cflush)
569
570 DEFINE_RS1(vxcptsave);
571 DEFINE_RS1(vxcptrestore);
572 DEFINE_NOARG(vxcptkill);
573
574 DEFINE_RS1(vxcptevac);
575 DEFINE_NOARG(vxcpthold);
576 DEFINE_RS1_RS2(venqcmd);
577 DEFINE_RS1_RS2(venqimm1);
578 DEFINE_RS1_RS2(venqimm2);
579 DEFINE_RS1_RS2(venqcnt);
580
581 DEFINE_FRTYPE(fadd_s);
582 DEFINE_FRTYPE(fsub_s);
583 DEFINE_FRTYPE(fmul_s);
584 DEFINE_FRTYPE(fdiv_s);
585 DEFINE_FR1TYPE(fsqrt_s);
586 DEFINE_FRTYPE(fmin_s);
587 DEFINE_FRTYPE(fmax_s);
588 DEFINE_FR3TYPE(fmadd_s);
589 DEFINE_FR3TYPE(fmsub_s);
590 DEFINE_FR3TYPE(fnmadd_s);
591 DEFINE_FR3TYPE(fnmsub_s);
592 DEFINE_FRTYPE(fsgnj_s);
593 DEFINE_FRTYPE(fsgnjn_s);
594 DEFINE_FRTYPE(fsgnjx_s);
595 DEFINE_FR1TYPE(fcvt_s_d);
596 DEFINE_XFTYPE(fcvt_s_l);
597 DEFINE_XFTYPE(fcvt_s_lu);
598 DEFINE_XFTYPE(fcvt_s_w);
599 DEFINE_XFTYPE(fcvt_s_wu);
600 DEFINE_XFTYPE(fcvt_s_wu);
601 DEFINE_XFTYPE(mxtf_s);
602 DEFINE_FXTYPE(fcvt_l_s);
603 DEFINE_FXTYPE(fcvt_lu_s);
604 DEFINE_FXTYPE(fcvt_w_s);
605 DEFINE_FXTYPE(fcvt_wu_s);
606 DEFINE_FXTYPE(mftx_s);
607 DEFINE_FXTYPE(feq_s);
608 DEFINE_FXTYPE(flt_s);
609 DEFINE_FXTYPE(fle_s);
610
611 DEFINE_FRTYPE(fadd_d);
612 DEFINE_FRTYPE(fsub_d);
613 DEFINE_FRTYPE(fmul_d);
614 DEFINE_FRTYPE(fdiv_d);
615 DEFINE_FR1TYPE(fsqrt_d);
616 DEFINE_FRTYPE(fmin_d);
617 DEFINE_FRTYPE(fmax_d);
618 DEFINE_FR3TYPE(fmadd_d);
619 DEFINE_FR3TYPE(fmsub_d);
620 DEFINE_FR3TYPE(fnmadd_d);
621 DEFINE_FR3TYPE(fnmsub_d);
622 DEFINE_FRTYPE(fsgnj_d);
623 DEFINE_FRTYPE(fsgnjn_d);
624 DEFINE_FRTYPE(fsgnjx_d);
625 DEFINE_FR1TYPE(fcvt_d_s);
626 DEFINE_XFTYPE(fcvt_d_l);
627 DEFINE_XFTYPE(fcvt_d_lu);
628 DEFINE_XFTYPE(fcvt_d_w);
629 DEFINE_XFTYPE(fcvt_d_wu);
630 DEFINE_XFTYPE(fcvt_d_wu);
631 DEFINE_XFTYPE(mxtf_d);
632 DEFINE_FXTYPE(fcvt_l_d);
633 DEFINE_FXTYPE(fcvt_lu_d);
634 DEFINE_FXTYPE(fcvt_w_d);
635 DEFINE_FXTYPE(fcvt_wu_d);
636 DEFINE_FXTYPE(mftx_d);
637 DEFINE_FXTYPE(feq_d);
638 DEFINE_FXTYPE(flt_d);
639 DEFINE_FXTYPE(fle_d);
640
641 add_insn(new disasm_insn_t("mtfsr", match_mtfsr, mask_mtfsr | mask_rd, xrs1_reg));
642 add_insn(new disasm_insn_t("mtfsr", match_mtfsr, mask_mtfsr, xrd_reg, xrs1_reg));
643 DEFINE_DTYPE(mffsr);
644
645 DEFINE_VEC_XMEM(vld);
646 DEFINE_VEC_XMEM(vlw);
647 DEFINE_VEC_XMEM(vlwu);
648 DEFINE_VEC_XMEM(vlh);
649 DEFINE_VEC_XMEM(vlhu);
650 DEFINE_VEC_XMEM(vlb);
651 DEFINE_VEC_XMEM(vlbu);
652 DEFINE_VEC_FMEM(vfld);
653 DEFINE_VEC_FMEM(vflw);
654 DEFINE_VEC_XMEMST(vlstd);
655 DEFINE_VEC_XMEMST(vlstw);
656 DEFINE_VEC_XMEMST(vlstwu);
657 DEFINE_VEC_XMEMST(vlsth);
658 DEFINE_VEC_XMEMST(vlsthu);
659 DEFINE_VEC_XMEMST(vlstb);
660 DEFINE_VEC_XMEMST(vlstbu);
661 DEFINE_VEC_FMEMST(vflstd);
662 DEFINE_VEC_FMEMST(vflstw);
663
664 DEFINE_VEC_XMEM(vsd);
665 DEFINE_VEC_XMEM(vsw);
666 DEFINE_VEC_XMEM(vsh);
667 DEFINE_VEC_XMEM(vsb);
668 DEFINE_VEC_FMEM(vfsd);
669 DEFINE_VEC_FMEM(vfsw);
670 DEFINE_VEC_XMEMST(vsstd);
671 DEFINE_VEC_XMEMST(vsstw);
672 DEFINE_VEC_XMEMST(vssth);
673 DEFINE_VEC_XMEMST(vsstb);
674 DEFINE_VEC_FMEMST(vfsstd);
675 DEFINE_VEC_FMEMST(vfsstw);
676
677 DISASM_INSN("vmvv", vmvv, 0, vxrd_reg, vxrs1_reg);
678 DISASM_INSN("vmsv", vmsv, 0, vxrd_reg, xrs1_reg);
679 DISASM_INSN("vmst", vmst, 0, vxrd_reg, xrs1_reg, xrs2_reg);
680 DISASM_INSN("vmts", vmts, 0, xrd_reg, vxrs1_reg, xrs2_reg);
681 DISASM_INSN("vfmvv", vfmvv, 0, vfrd_reg, vfrs1_reg);
682 DISASM_INSN("vfmsv", vfmsv, 0, vfrd_reg, frs1_reg);
683 DISASM_INSN("vfmst", vfmst, 0, vfrd_reg, frs1_reg, frs2_reg);
684 DISASM_INSN("vfmts", vfmts, 0, frd_reg, vfrs1_reg, frs2_reg);
685
686 DEFINE_RS1_RS2(vvcfg);
687 DEFINE_RS1_RS2(vtcfg);
688
689 DISASM_INSN("vvcfgivl", vvcfgivl, 0, xrd_reg, xrs1_reg, nxregs_reg, nfregs_reg);
690 DISASM_INSN("vtcfgivl", vtcfgivl, 0, xrd_reg, xrs1_reg, nxregs_reg, nfregs_reg);
691 DISASM_INSN("vsetvl", vsetvl, 0, xrd_reg, xrs1_reg);
692 DISASM_INSN("vf", vf, 0, xrs1_reg, imm);
693
694 DEFINE_NOARG(fence_v_l);
695 DEFINE_NOARG(fence_v_g);
696
697 // provide a default disassembly for all instructions as a fallback
698 #define DECLARE_INSN(code, match, mask) \
699 add_insn(new disasm_insn_t(#code " (args unknown)", match, mask));
700 #include "opcodes.h"
701 #undef DECLARE_INSN
702 }
703
704 const disasm_insn_t* disassembler::lookup(insn_t insn)
705 {
706 size_t idx = insn.bits % HASH_SIZE;
707 for (size_t j = 0; j < chain[idx].size(); j++)
708 if(*chain[idx][j] == insn)
709 return chain[idx][j];
710
711 idx = HASH_SIZE;
712 for (size_t j = 0; j < chain[idx].size(); j++)
713 if(*chain[idx][j] == insn)
714 return chain[idx][j];
715
716 return NULL;
717 }
718
719 void disassembler::add_insn(disasm_insn_t* insn)
720 {
721 size_t idx = HASH_SIZE;
722 if (insn->get_mask() % HASH_SIZE == HASH_SIZE - 1)
723 idx = insn->get_match() % HASH_SIZE;
724 chain[idx].push_back(insn);
725 }
726
727 disassembler::~disassembler()
728 {
729 for (size_t i = 0; i < HASH_SIZE+1; i++)
730 for (size_t j = 0; j < chain[i].size(); j++)
731 delete chain[i][j];
732 }