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