Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
disassembler_riscv.cc
Go to the documentation of this file.
1// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/globals.h" // Needed here to get TARGET_ARCH_RISCV.
6#if defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
7
9
10#include "platform/assert.h"
11#include "vm/instructions.h"
12
13namespace dart {
14
15#if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
16
17// We deviate from objdump in two places:
18// - branches display displacements instead of targets so our output is
19// position independent for tests.
20// - auipc/lui display the decoded value instead of the encoded value
21class RISCVDisassembler {
22 public:
23 explicit RISCVDisassembler(char* buffer,
24 size_t buffer_size,
25 ExtensionSet extensions)
26 : extensions_(extensions),
27 buffer_(buffer),
28 buffer_size_(buffer_size),
29 buffer_pos_(0) {}
30
31 bool Supports(Extension extension) const {
32 return extensions_.Includes(extension);
33 }
34 bool Supports(ExtensionSet extensions) const {
35 return extensions_.IncludesAll(extensions);
36 }
37
38 intptr_t Disassemble(uword pc) {
39 uint16_t parcel = *reinterpret_cast<uint16_t*>(pc);
40 if (Supports(RV_C) && IsCInstruction(parcel)) {
41 CInstr instr(parcel);
42 DisassembleInstruction(instr);
43 return instr.length();
44 } else {
45 uint32_t parcel = LoadUnaligned(reinterpret_cast<uint32_t*>(pc));
46 Instr instr(parcel);
47 DisassembleInstruction(instr);
48 return instr.length();
49 }
50 }
51
52 private:
53 void DisassembleInstruction(Instr instr);
54 void DisassembleInstruction(CInstr instr);
55 void DisassembleLUI(Instr instr);
56 void DisassembleAUIPC(Instr instr);
57 void DisassembleJAL(Instr instr);
58 void DisassembleJALR(Instr instr);
59 void DisassembleBRANCH(Instr instr);
60 void DisassembleLOAD(Instr instr);
61 void DisassembleSTORE(Instr instr);
62 void DisassembleOPIMM(Instr instr);
63 void DisassembleOPIMM32(Instr instr);
64 void DisassembleOP(Instr instr);
65 void DisassembleOP_0(Instr instr);
66 void DisassembleOP_SUB(Instr instr);
67 void DisassembleOP_MULDIV(Instr instr);
68 void DisassembleOP_SHADD(Instr instr);
69 void DisassembleOP_MINMAXCLMUL(Instr instr);
70 void DisassembleOP_ROTATE(Instr instr);
71 void DisassembleOP_BCLRBEXT(Instr instr);
72 void DisassembleOP32(Instr instr);
73 void DisassembleOP32_0(Instr instr);
74 void DisassembleOP32_SUB(Instr instr);
75 void DisassembleOP32_MULDIV(Instr instr);
76 void DisassembleOP32_SHADD(Instr instr);
77 void DisassembleOP32_ADDUW(Instr instr);
78 void DisassembleOP32_ROTATE(Instr instr);
79 void DisassembleMISCMEM(Instr instr);
80 void DisassembleSYSTEM(Instr instr);
81 void DisassembleAMO(Instr instr);
82 void DisassembleAMO32(Instr instr);
83 void DisassembleAMO64(Instr instr);
84 void DisassembleLOADFP(Instr instr);
85 void DisassembleSTOREFP(Instr instr);
86 void DisassembleFMADD(Instr instr);
87 void DisassembleFMSUB(Instr instr);
88 void DisassembleFNMADD(Instr instr);
89 void DisassembleFNMSUB(Instr instr);
90 void DisassembleOPFP(Instr instr);
91
92 void UnknownInstruction(Instr instr);
93 void UnknownInstruction(CInstr instr);
94
95 void Print(const char* format, Instr instr, ExtensionSet extension);
96 void Print(const char* format, CInstr instr, ExtensionSet extension);
97 const char* PrintOption(const char* format, Instr instr);
98 const char* PrintOption(const char* format, CInstr instr);
99
100 void Printf(const char* format, ...) PRINTF_ATTRIBUTE(2, 3) {
101 va_list args;
103 intptr_t len = Utils::VSNPrint(buffer_ + buffer_pos_,
104 buffer_size_ - buffer_pos_, format, args);
105 va_end(args);
106 buffer_pos_ += len;
107 buffer_[buffer_pos_] = '\0';
108 }
109
110 const ExtensionSet extensions_;
111 char* buffer_; // Decode instructions into this buffer.
112 size_t buffer_size_; // The size of the character buffer.
113 size_t buffer_pos_; // Current character position in buffer.
114};
115
116void RISCVDisassembler::DisassembleInstruction(Instr instr) {
117 switch (instr.opcode()) {
118 case LUI:
119 DisassembleLUI(instr);
120 break;
121 case AUIPC:
122 DisassembleAUIPC(instr);
123 break;
124 case JAL:
125 DisassembleJAL(instr);
126 break;
127 case JALR:
128 DisassembleJALR(instr);
129 break;
130 case BRANCH:
131 DisassembleBRANCH(instr);
132 break;
133 case LOAD:
134 DisassembleLOAD(instr);
135 break;
136 case STORE:
137 DisassembleSTORE(instr);
138 break;
139 case OPIMM:
140 DisassembleOPIMM(instr);
141 break;
142 case OPIMM32:
143 DisassembleOPIMM32(instr);
144 break;
145 case OP:
146 DisassembleOP(instr);
147 break;
148 case OP32:
149 DisassembleOP32(instr);
150 break;
151 case MISCMEM:
152 DisassembleMISCMEM(instr);
153 break;
154 case SYSTEM:
155 DisassembleSYSTEM(instr);
156 break;
157 case AMO:
158 DisassembleAMO(instr);
159 break;
160 case LOADFP:
161 DisassembleLOADFP(instr);
162 break;
163 case STOREFP:
164 DisassembleSTOREFP(instr);
165 break;
166 case FMADD:
167 DisassembleFMADD(instr);
168 break;
169 case FMSUB:
170 DisassembleFMSUB(instr);
171 break;
172 case FNMADD:
173 DisassembleFNMADD(instr);
174 break;
175 case FNMSUB:
176 DisassembleFNMSUB(instr);
177 break;
178 case OPFP:
179 DisassembleOPFP(instr);
180 break;
181 default:
182 if ((instr.encoding() == 0) ||
183 (instr.encoding() == static_cast<uint32_t>(-1))) {
184 Print("trap", instr, RV_I);
185 break;
186 }
187 UnknownInstruction(instr);
188 }
189}
190
191void RISCVDisassembler::DisassembleInstruction(CInstr instr) {
192 switch (instr.opcode()) {
193 case C_LWSP:
194 Print("lw 'rd, 'spload4imm(sp)", instr, RV_C);
195 break;
196#if XLEN == 32
197 case C_FLWSP:
198 Print("flw 'frd, 'spload4imm(sp)", instr, RV_C | RV_F);
199 break;
200#else
201 case C_LDSP:
202 Print("ld 'rd, 'spload8imm(sp)", instr, RV_C);
203 break;
204#endif
205 case C_FLDSP:
206 Print("fld 'frd, 'spload8imm(sp)", instr, RV_C | RV_D);
207 break;
208 case C_SWSP:
209 Print("sw 'rs2, 'spstore4imm(sp)", instr, RV_C);
210 break;
211#if XLEN == 32
212 case C_FSWSP:
213 Print("fsw 'frs2, 'spstore4imm(sp)", instr, RV_C | RV_F);
214 break;
215#else
216 case C_SDSP:
217 Print("sd 'rs2, 'spstore8imm(sp)", instr, RV_C);
218 break;
219#endif
220 case C_FSDSP:
221 Print("fsd 'frs2, 'spstore8imm(sp)", instr, RV_C | RV_D);
222 break;
223 case C_LW:
224 Print("lw 'rdp, 'mem4imm('rs1p)", instr, RV_C);
225 break;
226#if XLEN == 32
227 case C_FLW:
228 Print("flw 'frdp, 'mem4imm('rs1p)", instr, RV_C | RV_F);
229 break;
230#else
231 case C_LD:
232 Print("ld 'rdp, 'mem8imm('rs1p)", instr, RV_C);
233 break;
234#endif
235 case C_FLD:
236 Print("fld 'frdp, 'mem8imm('rs1p)", instr, RV_C | RV_D);
237 break;
238 case C_SW:
239 Print("sw 'rs2p, 'mem4imm('rs1p)", instr, RV_C);
240 break;
241#if XLEN == 32
242 case C_FSW:
243 Print("fsw 'frs2p, 'mem4imm('rs1p)", instr, RV_C | RV_F);
244 break;
245#else
246 case C_SD:
247 Print("sd 'rs2p, 'mem8imm('rs1p)", instr, RV_C);
248 break;
249#endif
250 case C_FSD:
251 Print("fsd 'frs2p, 'mem8imm('rs1p)", instr, RV_C | RV_F);
252 break;
253 case C_J:
254 Print("j 'jimm", instr, RV_C);
255 break;
256#if XLEN == 32
257 case C_JAL:
258 Print("jal 'jimm", instr, RV_C);
259 break;
260#endif
261 case C_JR:
262 if ((instr.encoding() & (C_JALR ^ C_JR)) != 0) {
263 if ((instr.rs1() == ZR) && (instr.rs2() == ZR)) {
264 Print("ebreak", instr, RV_C);
265 } else if (instr.rs2() == ZR) {
266 Print("jalr 'rs1", instr, RV_C);
267 } else {
268 Print("add 'rd, 'rs1, 'rs2", instr, RV_C);
269 }
270 } else {
271 if (instr.rd() != ZR && instr.rs2() != ZR) {
272 Print("mv 'rd, 'rs2", instr, RV_C);
273 } else if (instr.rs2() != ZR) {
274 UnknownInstruction(instr);
275 } else if (instr.rs1() == RA) {
276 Print("ret", instr, RV_C);
277 } else {
278 Print("jr 'rs1", instr, RV_C);
279 }
280 }
281 break;
282 case C_BEQZ:
283 Print("beqz 'rs1p, 'bimm", instr, RV_C);
284 break;
285 case C_BNEZ:
286 Print("bnez 'rs1p, 'bimm", instr, RV_C);
287 break;
288 case C_LI:
289 Print("li 'rd, 'iimm", instr, RV_C);
290 break;
291 case C_LUI:
292 if (instr.rd() == SP) {
293 Print("addi 'rd, 'rs1, 'i16imm", instr, RV_C);
294 } else {
295 Print("lui 'rd, 'uimm", instr, RV_C);
296 }
297 break;
298 case C_ADDI:
299 if ((instr.rd() == ZR) && (instr.rs1() == ZR) && (instr.i_imm() == 0)) {
300 Print("nop", instr, RV_C);
301 } else {
302 Print("addi 'rd, 'rs1, 'iimm", instr, RV_C);
303 }
304 break;
305#if XLEN >= 64
306 case C_ADDIW:
307 if (instr.i_imm() == 0) {
308 Print("sext.w 'rd, 'rs1", instr, RV_C);
309 } else {
310 Print("addiw 'rd, 'rs1, 'iimm", instr, RV_C);
311 }
312 break;
313#endif
314 case C_ADDI4SPN:
315 if (instr.i4spn_imm() == 0) {
316 UnknownInstruction(instr);
317 } else {
318 Print("addi 'rdp, sp, 'i4spnimm", instr, RV_C);
319 }
320 break;
321 case C_SLLI:
322 if (instr.i_imm() == 0) {
323 UnknownInstruction(instr);
324 } else {
325 Print("slli 'rd, 'rs1, 'iimm", instr, RV_C);
326 }
327 break;
328 case C_MISCALU:
329 switch (instr.encoding() & C_MISCALU_MASK) {
330 case C_SRLI:
331 if (instr.i_imm() == 0) {
332 UnknownInstruction(instr);
333 } else {
334 Print("srli 'rs1p, 'rs1p, 'iimm", instr, RV_C);
335 }
336 break;
337 case C_SRAI:
338 if (instr.i_imm() == 0) {
339 UnknownInstruction(instr);
340 } else {
341 Print("srai 'rs1p, 'rs1p, 'iimm", instr, RV_C);
342 }
343 break;
344 case C_ANDI:
345 Print("andi 'rs1p, 'rs1p, 'iimm", instr, RV_C);
346 break;
347 case C_RR:
348 switch (instr.encoding() & C_RR_MASK) {
349 case C_AND:
350 Print("and 'rs1p, 'rs1p, 'rs2p", instr, RV_C);
351 break;
352 case C_OR:
353 Print("or 'rs1p, 'rs1p, 'rs2p", instr, RV_C);
354 break;
355 case C_XOR:
356 Print("xor 'rs1p, 'rs1p, 'rs2p", instr, RV_C);
357 break;
358 case C_SUB:
359 Print("sub 'rs1p, 'rs1p, 'rs2p", instr, RV_C);
360 break;
361#if XLEN >= 64
362 case C_ADDW:
363 Print("addw 'rs1p, 'rs1p, 'rs2p", instr, RV_C);
364 break;
365 case C_SUBW:
366 Print("subw 'rs1p, 'rs1p, 'rs2p", instr, RV_C);
367 break;
368#endif
369 default:
370 UnknownInstruction(instr);
371 }
372 break;
373 default:
374 UnknownInstruction(instr);
375 }
376 break;
377 default:
378 if ((instr.encoding() == 0) ||
379 (instr.encoding() == static_cast<uint16_t>(-1))) {
380 Print("trap", instr, RV_C);
381 break;
382 }
383 UnknownInstruction(instr);
384 }
385}
386
387void RISCVDisassembler::DisassembleLUI(Instr instr) {
388 Print("lui 'rd, 'uimm", instr, RV_I);
389}
390
391void RISCVDisassembler::DisassembleAUIPC(Instr instr) {
392 Print("auipc 'rd, 'uimm", instr, RV_I);
393}
394
395void RISCVDisassembler::DisassembleJAL(Instr instr) {
396 if (instr.rd() == ZR) {
397 Print("j 'jimm", instr, RV_I);
398 } else if (instr.rd() == RA) {
399 Print("jal 'jimm", instr, RV_I);
400 } else {
401 Print("jal 'rd, 'jimm", instr, RV_I);
402 }
403}
404
405void RISCVDisassembler::DisassembleJALR(Instr instr) {
406 if (instr.rd() == ZR) {
407 if ((instr.rs1() == RA) && (instr.itype_imm() == 0)) {
408 Print("ret", instr, RV_I);
409 } else if (instr.itype_imm() == 0) {
410 Print("jr 'rs1", instr, RV_I);
411 } else {
412 Print("jr 'iimm('rs1)", instr, RV_I);
413 }
414 } else if (instr.rd() == RA) {
415 if (instr.itype_imm() == 0) {
416 Print("jalr 'rs1", instr, RV_I);
417 } else {
418 Print("jalr 'iimm('rs1)", instr, RV_I);
419 }
420 } else {
421 if (instr.itype_imm() == 0) {
422 Print("jalr 'rd, 'rs1", instr, RV_I);
423 } else {
424 Print("jalr 'rd, 'iimm('rs1)", instr, RV_I);
425 }
426 }
427}
428
429void RISCVDisassembler::DisassembleBRANCH(Instr instr) {
430 switch (instr.funct3()) {
431 case BEQ:
432 if (instr.rs2() == ZR) {
433 Print("beqz 'rs1, 'bimm", instr, RV_I);
434 } else {
435 Print("beq 'rs1, 'rs2, 'bimm", instr, RV_I);
436 }
437 break;
438 case BNE:
439 if (instr.rs2() == ZR) {
440 Print("bnez 'rs1, 'bimm", instr, RV_I);
441 } else {
442 Print("bne 'rs1, 'rs2, 'bimm", instr, RV_I);
443 }
444 break;
445 case BLT:
446 if (instr.rs2() == ZR) {
447 Print("bltz 'rs1, 'bimm", instr, RV_I);
448 } else if (instr.rs1() == ZR) {
449 Print("bgtz 'rs2, 'bimm", instr, RV_I);
450 } else {
451 Print("blt 'rs1, 'rs2, 'bimm", instr, RV_I);
452 }
453 break;
454 case BGE:
455 if (instr.rs2() == ZR) {
456 Print("bgez 'rs1, 'bimm", instr, RV_I);
457 } else if (instr.rs1() == ZR) {
458 Print("blez 'rs2, 'bimm", instr, RV_I);
459 } else {
460 Print("ble 'rs2, 'rs1, 'bimm", instr, RV_I);
461 }
462 break;
463 case BLTU:
464 Print("bltu 'rs1, 'rs2, 'bimm", instr, RV_I);
465 break;
466 case BGEU:
467 Print("bleu 'rs2, 'rs1, 'bimm", instr, RV_I);
468 break;
469 default:
470 UnknownInstruction(instr);
471 }
472}
473
474void RISCVDisassembler::DisassembleLOAD(Instr instr) {
475 switch (instr.funct3()) {
476 case LB:
477 Print("lb 'rd, 'iimm('rs1)", instr, RV_I);
478 break;
479 case LH:
480 Print("lh 'rd, 'iimm('rs1)", instr, RV_I);
481 break;
482 case LW:
483 Print("lw 'rd, 'iimm('rs1)", instr, RV_I);
484 break;
485 case LBU:
486 Print("lbu 'rd, 'iimm('rs1)", instr, RV_I);
487 break;
488 case LHU:
489 Print("lhu 'rd, 'iimm('rs1)", instr, RV_I);
490 break;
491#if XLEN >= 64
492 case LWU:
493 Print("lwu 'rd, 'iimm('rs1)", instr, RV_I);
494 break;
495 case LD:
496 Print("ld 'rd, 'iimm('rs1)", instr, RV_I);
497 break;
498#endif
499 default:
500 UnknownInstruction(instr);
501 }
502}
503
504void RISCVDisassembler::DisassembleLOADFP(Instr instr) {
505 switch (instr.funct3()) {
506 case S:
507 Print("flw 'frd, 'iimm('rs1)", instr, RV_F);
508 break;
509 case D:
510 Print("fld 'frd, 'iimm('rs1)", instr, RV_D);
511 break;
512 default:
513 UnknownInstruction(instr);
514 }
515}
516
517void RISCVDisassembler::DisassembleSTORE(Instr instr) {
518 switch (instr.funct3()) {
519 case SB:
520 Print("sb 'rs2, 'simm('rs1)", instr, RV_I);
521 break;
522 case SH:
523 Print("sh 'rs2, 'simm('rs1)", instr, RV_I);
524 break;
525 case SW:
526 Print("sw 'rs2, 'simm('rs1)", instr, RV_I);
527 break;
528#if XLEN >= 64
529 case SD:
530 Print("sd 'rs2, 'simm('rs1)", instr, RV_I);
531 break;
532#endif
533 default:
534 UnknownInstruction(instr);
535 }
536}
537
538void RISCVDisassembler::DisassembleSTOREFP(Instr instr) {
539 switch (instr.funct3()) {
540 case S:
541 Print("fsw 'frs2, 'simm('rs1)", instr, RV_F);
542 break;
543 case D:
544 Print("fsd 'frs2, 'simm('rs1)", instr, RV_D);
545 break;
546 default:
547 UnknownInstruction(instr);
548 }
549}
550
551void RISCVDisassembler::DisassembleOPIMM(Instr instr) {
552 switch (instr.funct3()) {
553 case ADDI:
554 if ((instr.rd() == ZR) && (instr.rs1() == ZR) &&
555 (instr.itype_imm() == 0)) {
556 Print("nop", instr, RV_I); // The canonical nop.
557 } else if (instr.itype_imm() == 0) {
558 Print("mv 'rd, 'rs1", instr, RV_I);
559 } else if (instr.rs1() == ZR) {
560 Print("li 'rd, 'iimm", instr, RV_I);
561 } else {
562 Print("addi 'rd, 'rs1, 'iimm", instr, RV_I);
563 }
564 break;
565 case SLTI:
566 Print("slti 'rd, 'rs1, 'iimm", instr, RV_I);
567 break;
568 case SLTIU:
569 if (instr.itype_imm() == 1) {
570 Print("seqz 'rd, 'rs1", instr, RV_I);
571 } else {
572 Print("sltiu 'rd, 'rs1, 'iimm", instr, RV_I);
573 }
574 break;
575 case XORI:
576 if (instr.itype_imm() == -1) {
577 Print("not 'rd, 'rs1", instr, RV_I);
578 } else {
579 Print("xori 'rd, 'rs1, 'iimm", instr, RV_I);
580 }
581 break;
582 case ORI:
583 Print("ori 'rd, 'rs1, 'iimm", instr, RV_I);
584 break;
585 case ANDI:
586 Print("andi 'rd, 'rs1, 'iimm", instr, RV_I);
587 break;
588 case SLLI:
589 if (instr.funct7() == COUNT) {
590 if (instr.shamt() == 0b00000) {
591 Print("clz 'rd, 'rs1", instr, RV_Zbb);
592 } else if (instr.shamt() == 0b00001) {
593 Print("ctz 'rd, 'rs1", instr, RV_Zbb);
594 } else if (instr.shamt() == 0b00010) {
595 Print("cpop 'rd, 'rs1", instr, RV_Zbb);
596 } else if (instr.shamt() == 0b00100) {
597 Print("sext.b 'rd, 'rs1", instr, RV_Zbb);
598 } else if (instr.shamt() == 0b00101) {
599 Print("sext.h 'rd, 'rs1", instr, RV_Zbb);
600 } else {
601 UnknownInstruction(instr);
602 }
603 } else if ((instr.funct7() & 0b1111110) == BCLRBEXT) {
604 Print("bclri 'rd, 'rs1, 'shamt", instr, RV_Zbs);
605 } else if ((instr.funct7() & 0b1111110) == BINV) {
606 Print("binvi 'rd, 'rs1, 'shamt", instr, RV_Zbs);
607 } else if ((instr.funct7() & 0b1111110) == BSET) {
608 Print("bseti 'rd, 'rs1, 'shamt", instr, RV_Zbs);
609 } else {
610 Print("slli 'rd, 'rs1, 'shamt", instr, RV_I);
611 }
612 break;
613 case SRI:
614 if ((instr.funct7() & 0b1111110) == SRA) {
615 Print("srai 'rd, 'rs1, 'shamt", instr, RV_I);
616 } else if ((instr.funct7() & 0b1111110) == ROTATE) {
617 Print("rori 'rd, 'rs1, 'shamt", instr, RV_Zbb);
618 } else if (instr.funct7() == 0b0010100) {
619 Print("orc.b 'rd, 'rs1", instr, RV_Zbb);
620#if XLEN == 32
621 } else if (instr.funct7() == 0b0110100) {
622 Print("rev8 'rd, 'rs1", instr, RV_Zbb);
623#else
624 } else if (instr.funct7() == 0b0110101) {
625 Print("rev8 'rd, 'rs1", instr, RV_Zbb);
626#endif
627 } else if ((instr.funct7() & 0b1111110) == BCLRBEXT) {
628 Print("bexti 'rd, 'rs1, 'shamt", instr, RV_Zbs);
629 } else {
630 Print("srli 'rd, 'rs1, 'shamt", instr, RV_I);
631 }
632 break;
633 default:
634 UnknownInstruction(instr);
635 }
636}
637
638void RISCVDisassembler::DisassembleOPIMM32(Instr instr) {
639 switch (instr.funct3()) {
640#if XLEN >= 64
641 case ADDI:
642 if (instr.itype_imm() == 0) {
643 Print("sext.w 'rd, 'rs1", instr, RV_I);
644 } else {
645 Print("addiw 'rd, 'rs1, 'iimm", instr, RV_I);
646 }
647 break;
648 case SLLI:
649 if (instr.funct7() == SLLIUW) {
650 Print("slli.uw 'rd, 'rs1, 'shamt", instr, RV_Zba);
651 } else if (instr.funct7() == COUNT) {
652 if (instr.shamt() == 0b00000) {
653 Print("clzw 'rd, 'rs1", instr, RV_Zbb);
654 } else if (instr.shamt() == 0b00001) {
655 Print("ctzw 'rd, 'rs1", instr, RV_Zbb);
656 } else if (instr.shamt() == 0b00010) {
657 Print("cpopw 'rd, 'rs1", instr, RV_Zbb);
658 } else {
659 UnknownInstruction(instr);
660 }
661 } else {
662 Print("slliw 'rd, 'rs1, 'shamt", instr, RV_I);
663 }
664 break;
665 case SRI:
666 if (instr.funct7() == SRA) {
667 Print("sraiw 'rd, 'rs1, 'shamt", instr, RV_I);
668 } else if (instr.funct7() == ROTATE) {
669 Print("roriw 'rd, 'rs1, 'shamt", instr, RV_Zbb);
670 } else {
671 Print("srliw 'rd, 'rs1, 'shamt", instr, RV_I);
672 }
673 break;
674#endif
675 default:
676 UnknownInstruction(instr);
677 }
678}
679
680void RISCVDisassembler::DisassembleOP(Instr instr) {
681 switch (instr.funct7()) {
682 case 0:
683 DisassembleOP_0(instr);
684 break;
685 case SUB:
686 DisassembleOP_SUB(instr);
687 break;
688 case MULDIV:
689 DisassembleOP_MULDIV(instr);
690 break;
691 case SHADD:
692 DisassembleOP_SHADD(instr);
693 break;
694 case MINMAXCLMUL:
695 DisassembleOP_MINMAXCLMUL(instr);
696 break;
697 case ROTATE:
698 DisassembleOP_ROTATE(instr);
699 break;
700 case BCLRBEXT:
701 DisassembleOP_BCLRBEXT(instr);
702 break;
703 case BINV:
704 Print("binv 'rd, 'rs1, 'rs2", instr, RV_Zbs);
705 break;
706 case BSET:
707 Print("bset 'rd, 'rs1, 'rs2", instr, RV_Zbs);
708 break;
709#if XLEN == 32
710 case 0b0000100:
711 Print("zext.h 'rd, 'rs1", instr, RV_Zbb);
712 break;
713#endif
714 default:
715 UnknownInstruction(instr);
716 }
717}
718
719void RISCVDisassembler::DisassembleOP_0(Instr instr) {
720 switch (instr.funct3()) {
721 case ADD:
722 Print("add 'rd, 'rs1, 'rs2", instr, RV_I);
723 break;
724 case SLL:
725 Print("sll 'rd, 'rs1, 'rs2", instr, RV_I);
726 break;
727 case SLT:
728 if (instr.rs2() == ZR) {
729 Print("sltz 'rd, 'rs1", instr, RV_I);
730 } else if (instr.rs1() == ZR) {
731 Print("sgtz 'rd, 'rs2", instr, RV_I);
732 } else {
733 Print("slt 'rd, 'rs1, 'rs2", instr, RV_I);
734 }
735 break;
736 case SLTU:
737 if (instr.rs1() == ZR) {
738 Print("snez 'rd, 'rs2", instr, RV_I);
739 } else {
740 Print("sltu 'rd, 'rs1, 'rs2", instr, RV_I);
741 }
742 break;
743 case XOR:
744 Print("xor 'rd, 'rs1, 'rs2", instr, RV_I);
745 break;
746 case SR:
747 Print("srl 'rd, 'rs1, 'rs2", instr, RV_I);
748 break;
749 case OR:
750 Print("or 'rd, 'rs1, 'rs2", instr, RV_I);
751 break;
752 case AND:
753 Print("and 'rd, 'rs1, 'rs2", instr, RV_I);
754 break;
755 default:
756 UnknownInstruction(instr);
757 }
758}
759
760void RISCVDisassembler::DisassembleOP_SUB(Instr instr) {
761 switch (instr.funct3()) {
762 case ADD:
763 if (instr.rs1() == ZR) {
764 Print("neg 'rd, 'rs2", instr, RV_I);
765 } else {
766 Print("sub 'rd, 'rs1, 'rs2", instr, RV_I);
767 }
768 break;
769 case SR:
770 Print("sra 'rd, 'rs1, 'rs2", instr, RV_I);
771 break;
772 case AND:
773 Print("andn 'rd, 'rs1, 'rs2", instr, RV_Zbb);
774 break;
775 case OR:
776 Print("orn 'rd, 'rs1, 'rs2", instr, RV_Zbb);
777 break;
778 case XOR:
779 Print("xnor 'rd, 'rs1, 'rs2", instr, RV_Zbb);
780 break;
781 default:
782 UnknownInstruction(instr);
783 }
784}
785
786void RISCVDisassembler::DisassembleOP_MULDIV(Instr instr) {
787 switch (instr.funct3()) {
788 case MUL:
789 Print("mul 'rd, 'rs1, 'rs2", instr, RV_M);
790 break;
791 case MULH:
792 Print("mulh 'rd, 'rs1, 'rs2", instr, RV_M);
793 break;
794 case MULHSU:
795 Print("mulhsu 'rd, 'rs1, 'rs2", instr, RV_M);
796 break;
797 case MULHU:
798 Print("mulhu 'rd, 'rs1, 'rs2", instr, RV_M);
799 break;
800 case DIV:
801 Print("div 'rd, 'rs1, 'rs2", instr, RV_M);
802 break;
803 case DIVU:
804 Print("divu 'rd, 'rs1, 'rs2", instr, RV_M);
805 break;
806 case REM:
807 Print("rem 'rd, 'rs1, 'rs2", instr, RV_M);
808 break;
809 case REMU:
810 Print("remu 'rd, 'rs1, 'rs2", instr, RV_M);
811 break;
812 default:
813 UnknownInstruction(instr);
814 }
815}
816
817void RISCVDisassembler::DisassembleOP_SHADD(Instr instr) {
818 switch (instr.funct3()) {
819 case SH1ADD:
820 Print("sh1add 'rd, 'rs1, 'rs2", instr, RV_Zba);
821 break;
822 case SH2ADD:
823 Print("sh2add 'rd, 'rs1, 'rs2", instr, RV_Zba);
824 break;
825 case SH3ADD:
826 Print("sh3add 'rd, 'rs1, 'rs2", instr, RV_Zba);
827 break;
828 default:
829 UnknownInstruction(instr);
830 }
831}
832
833void RISCVDisassembler::DisassembleOP_MINMAXCLMUL(Instr instr) {
834 switch (instr.funct3()) {
835 case MAX:
836 Print("max 'rd, 'rs1, 'rs2", instr, RV_Zbb);
837 break;
838 case MAXU:
839 Print("maxu 'rd, 'rs1, 'rs2", instr, RV_Zbb);
840 break;
841 case MIN:
842 Print("min 'rd, 'rs1, 'rs2", instr, RV_Zbb);
843 break;
844 case MINU:
845 Print("minu 'rd, 'rs1, 'rs2", instr, RV_Zbb);
846 break;
847 case CLMUL:
848 Print("clmul 'rd, 'rs1, 'rs2", instr, RV_Zbc);
849 break;
850 case CLMULH:
851 Print("clmulh 'rd, 'rs1, 'rs2", instr, RV_Zbc);
852 break;
853 case CLMULR:
854 Print("clmulr 'rd, 'rs1, 'rs2", instr, RV_Zbc);
855 break;
856 default:
857 UnknownInstruction(instr);
858 }
859}
860
861void RISCVDisassembler::DisassembleOP_ROTATE(Instr instr) {
862 switch (instr.funct3()) {
863 case ROR:
864 Print("ror 'rd, 'rs1, 'rs2", instr, RV_Zbb);
865 break;
866 case ROL:
867 Print("rol 'rd, 'rs1, 'rs2", instr, RV_Zbb);
868 break;
869 default:
870 UnknownInstruction(instr);
871 }
872}
873
874void RISCVDisassembler::DisassembleOP_BCLRBEXT(Instr instr) {
875 switch (instr.funct3()) {
876 case BCLR:
877 Print("bclr 'rd, 'rs1, 'rs2", instr, RV_Zbs);
878 break;
879 case BEXT:
880 Print("bext 'rd, 'rs1, 'rs2", instr, RV_Zbs);
881 break;
882 default:
883 UnknownInstruction(instr);
884 }
885}
886
887void RISCVDisassembler::DisassembleOP32(Instr instr) {
888 switch (instr.funct7()) {
889 case 0:
890 DisassembleOP32_0(instr);
891 break;
892 case SUB:
893 DisassembleOP32_SUB(instr);
894 break;
895 case MULDIV:
896 DisassembleOP32_MULDIV(instr);
897 break;
898 case SHADD:
899 DisassembleOP32_SHADD(instr);
900 break;
901 case ADDUW:
902 DisassembleOP32_ADDUW(instr);
903 break;
904 case ROTATE:
905 DisassembleOP32_ROTATE(instr);
906 break;
907 default:
908 UnknownInstruction(instr);
909 }
910}
911
912void RISCVDisassembler::DisassembleOP32_0(Instr instr) {
913 switch (instr.funct3()) {
914#if XLEN >= 64
915 case ADD:
916 Print("addw 'rd, 'rs1, 'rs2", instr, RV_I);
917 break;
918 case SLL:
919 Print("sllw 'rd, 'rs1, 'rs2", instr, RV_I);
920 break;
921 case SR: {
922 Print("srlw 'rd, 'rs1, 'rs2", instr, RV_I);
923 break;
924 }
925#endif
926 default:
927 UnknownInstruction(instr);
928 }
929}
930
931void RISCVDisassembler::DisassembleOP32_SUB(Instr instr) {
932 switch (instr.funct3()) {
933#if XLEN >= 64
934 case ADD:
935 if (instr.rs1() == ZR) {
936 Print("negw 'rd, 'rs2", instr, RV_I);
937 } else {
938 Print("subw 'rd, 'rs1, 'rs2", instr, RV_I);
939 }
940 break;
941 case SR:
942 Print("sraw 'rd, 'rs1, 'rs2", instr, RV_I);
943 break;
944#endif
945 default:
946 UnknownInstruction(instr);
947 }
948}
949
950void RISCVDisassembler::DisassembleOP32_MULDIV(Instr instr) {
951 switch (instr.funct3()) {
952#if XLEN >= 64
953 case MULW:
954 Print("mulw 'rd, 'rs1, 'rs2", instr, RV_M);
955 break;
956 case DIVW:
957 Print("divw 'rd, 'rs1, 'rs2", instr, RV_M);
958 break;
959 case DIVUW:
960 Print("divuw 'rd, 'rs1, 'rs2", instr, RV_M);
961 break;
962 case REMW:
963 Print("remw 'rd, 'rs1, 'rs2", instr, RV_M);
964 break;
965 case REMUW:
966 Print("remuw 'rd, 'rs1, 'rs2", instr, RV_M);
967 break;
968#endif
969 default:
970 UnknownInstruction(instr);
971 }
972}
973
974void RISCVDisassembler::DisassembleOP32_SHADD(Instr instr) {
975 switch (instr.funct3()) {
976 case SH1ADD:
977 Print("sh1add.uw 'rd, 'rs1, 'rs2", instr, RV_Zba);
978 break;
979 case SH2ADD:
980 Print("sh2add.uw 'rd, 'rs1, 'rs2", instr, RV_Zba);
981 break;
982 case SH3ADD:
983 Print("sh3add.uw 'rd, 'rs1, 'rs2", instr, RV_Zba);
984 break;
985 default:
986 UnknownInstruction(instr);
987 }
988}
989
990void RISCVDisassembler::DisassembleOP32_ADDUW(Instr instr) {
991 switch (instr.funct3()) {
992#if XLEN >= 64
993 case F3_0:
994 Print("add.uw 'rd, 'rs1, 'rs2", instr, RV_Zba);
995 break;
996 case ZEXT:
997 Print("zext.h 'rd, 'rs1", instr, RV_Zbb);
998 break;
999#endif
1000 default:
1001 UnknownInstruction(instr);
1002 }
1003}
1004
1005void RISCVDisassembler::DisassembleOP32_ROTATE(Instr instr) {
1006 switch (instr.funct3()) {
1007 case ROR:
1008 Print("rorw 'rd, 'rs1, 'rs2", instr, RV_Zbb);
1009 break;
1010 case ROL:
1011 Print("rolw 'rd, 'rs1, 'rs2", instr, RV_Zbb);
1012 break;
1013 default:
1014 UnknownInstruction(instr);
1015 }
1016}
1017
1018void RISCVDisassembler::DisassembleMISCMEM(Instr instr) {
1019 switch (instr.funct3()) {
1020 case FENCE:
1021 Print("fence'predsucc", instr, RV_I);
1022 break;
1023 case FENCEI:
1024 Print("fence.i", instr, RV_I);
1025 break;
1026 default:
1027 UnknownInstruction(instr);
1028 }
1029}
1030
1031void RISCVDisassembler::DisassembleSYSTEM(Instr instr) {
1032 switch (instr.funct3()) {
1033 case 0:
1034 switch (instr.funct12()) {
1035 case ECALL:
1036 if (instr.rs1() == ZR) {
1037 Print("ecall", instr, RV_I);
1038 } else {
1039 Print("SimulatorPrintObject 'rs1", instr, RV_I);
1040 }
1041 break;
1042 case EBREAK:
1043 Print("ebreak", instr, RV_I);
1044 break;
1045 default:
1046 UnknownInstruction(instr);
1047 }
1048 break;
1049 case CSRRW:
1050 if (instr.rd() == ZR) {
1051 Print("csrw 'csr, 'rs1", instr, RV_I);
1052 } else {
1053 Print("csrrw 'rd, 'csr, 'rs1", instr, RV_I);
1054 }
1055 break;
1056 case CSRRS:
1057 if (instr.rs1() == ZR) {
1058 Print("csrr 'rd, 'csr", instr, RV_I);
1059 } else if (instr.rd() == ZR) {
1060 Print("csrs 'csr, 'rs1", instr, RV_I);
1061 } else {
1062 Print("csrrs 'rd, 'csr, 'rs1", instr, RV_I);
1063 }
1064 break;
1065 case CSRRC:
1066 if (instr.rd() == ZR) {
1067 Print("csrc 'csr, 'rs1", instr, RV_I);
1068 } else {
1069 Print("csrrc 'rd, 'csr, 'rs1", instr, RV_I);
1070 }
1071 break;
1072 case CSRRWI:
1073 if (instr.rd() == ZR) {
1074 Print("csrwi 'csr, 'zimm", instr, RV_I);
1075 } else {
1076 Print("csrrwi 'rd, 'csr, 'zimm", instr, RV_I);
1077 }
1078 break;
1079 case CSRRSI:
1080 if (instr.rd() == ZR) {
1081 Print("csrsi 'csr, 'zimm", instr, RV_I);
1082 } else {
1083 Print("csrrsi 'rd, 'csr, 'zimm", instr, RV_I);
1084 }
1085 break;
1086 case CSRRCI:
1087 if (instr.rd() == ZR) {
1088 Print("csrci 'csr, 'zimm", instr, RV_I);
1089 } else {
1090 Print("csrrci 'rd, 'csr, 'zimm", instr, RV_I);
1091 }
1092 break;
1093 default:
1094 UnknownInstruction(instr);
1095 }
1096}
1097
1098void RISCVDisassembler::DisassembleAMO(Instr instr) {
1099 switch (instr.funct3()) {
1100 case WIDTH32:
1101 DisassembleAMO32(instr);
1102 break;
1103 case WIDTH64:
1104 DisassembleAMO64(instr);
1105 break;
1106 default:
1107 UnknownInstruction(instr);
1108 }
1109}
1110
1111void RISCVDisassembler::DisassembleAMO32(Instr instr) {
1112 switch (instr.funct5()) {
1113 case LR:
1114 Print("lr.w'order 'rd, ('rs1)", instr, RV_A);
1115 break;
1116 case SC:
1117 Print("sc.w'order 'rd, 'rs2, ('rs1)", instr, RV_A);
1118 break;
1119 case AMOSWAP:
1120 Print("amoswap.w'order 'rd, 'rs2, ('rs1)", instr, RV_A);
1121 break;
1122 case AMOADD:
1123 Print("amoadd.w'order 'rd, 'rs2, ('rs1)", instr, RV_A);
1124 break;
1125 case AMOXOR:
1126 Print("amoxor.w'order 'rd, 'rs2, ('rs1)", instr, RV_A);
1127 break;
1128 case AMOAND:
1129 Print("amoand.w'order 'rd, 'rs2, ('rs1)", instr, RV_A);
1130 break;
1131 case AMOOR:
1132 Print("amoor.w'order 'rd, 'rs2, ('rs1)", instr, RV_A);
1133 break;
1134 case AMOMIN:
1135 Print("amomin.w'order 'rd, 'rs2, ('rs1)", instr, RV_A);
1136 break;
1137 case AMOMAX:
1138 Print("amomax.w'order 'rd, 'rs2, ('rs1)", instr, RV_A);
1139 break;
1140 case AMOMINU:
1141 Print("amominu.w'order 'rd, 'rs2, ('rs1)", instr, RV_A);
1142 break;
1143 case AMOMAXU:
1144 Print("amomaxu.w'order 'rd, 'rs2, ('rs1)", instr, RV_A);
1145 break;
1146 default:
1147 UnknownInstruction(instr);
1148 }
1149}
1150
1151void RISCVDisassembler::DisassembleAMO64(Instr instr) {
1152 switch (instr.funct5()) {
1153#if XLEN >= 64
1154 case LR:
1155 Print("lr.d'order 'rd, ('rs1)", instr, RV_A);
1156 break;
1157 case SC:
1158 Print("sc.d'order 'rd, 'rs2, ('rs1)", instr, RV_A);
1159 break;
1160 case AMOSWAP:
1161 Print("amoswap.d'order 'rd, 'rs2, ('rs1)", instr, RV_A);
1162 break;
1163 case AMOADD:
1164 Print("amoadd.d'order 'rd, 'rs2, ('rs1)", instr, RV_A);
1165 break;
1166 case AMOXOR:
1167 Print("amoxor.d'order 'rd, 'rs2, ('rs1)", instr, RV_A);
1168 break;
1169 case AMOAND:
1170 Print("amoand.d'order 'rd, 'rs2, ('rs1)", instr, RV_A);
1171 break;
1172 case AMOOR:
1173 Print("amoor.d'order 'rd, 'rs2, ('rs1)", instr, RV_A);
1174 break;
1175 case AMOMIN:
1176 Print("amomin.d'order 'rd, 'rs2, ('rs1)", instr, RV_A);
1177 break;
1178 case AMOMAX:
1179 Print("amomax.d'order 'rd, 'rs2, ('rs1)", instr, RV_A);
1180 break;
1181 case AMOMINU:
1182 Print("amominu.d'order 'rd, 'rs2, ('rs1)", instr, RV_A);
1183 break;
1184 case AMOMAXU:
1185 Print("amomaxu.d'order 'rd, 'rs2, ('rs1)", instr, RV_A);
1186 break;
1187#endif
1188 default:
1189 UnknownInstruction(instr);
1190 }
1191}
1192
1193void RISCVDisassembler::DisassembleFMADD(Instr instr) {
1194 switch (instr.funct2()) {
1195 case F2_S:
1196 Print("fmadd.s 'frd, 'frs1, 'frs2, 'frs3'round", instr, RV_F);
1197 break;
1198 case F2_D:
1199 Print("fmadd.d 'frd, 'frs1, 'frs2, 'frs3'round", instr, RV_D);
1200 break;
1201 default:
1202 UnknownInstruction(instr);
1203 }
1204}
1205
1206void RISCVDisassembler::DisassembleFMSUB(Instr instr) {
1207 switch (instr.funct2()) {
1208 case F2_S:
1209 Print("fmsub.s 'frd, 'frs1, 'frs2, 'frs3'round", instr, RV_F);
1210 break;
1211 case F2_D:
1212 Print("fmsub.d 'frd, 'frs1, 'frs2, 'frs3'round", instr, RV_D);
1213 break;
1214 default:
1215 UnknownInstruction(instr);
1216 }
1217}
1218
1219void RISCVDisassembler::DisassembleFNMADD(Instr instr) {
1220 switch (instr.funct2()) {
1221 case F2_S:
1222 Print("fnmadd.s 'frd, 'frs1, 'frs2, 'frs3'round", instr, RV_F);
1223 break;
1224 case F2_D:
1225 Print("fnmadd.d 'frd, 'frs1, 'frs2, 'frs3'round", instr, RV_D);
1226 break;
1227 default:
1228 UnknownInstruction(instr);
1229 }
1230}
1231
1232void RISCVDisassembler::DisassembleFNMSUB(Instr instr) {
1233 switch (instr.funct2()) {
1234 case F2_S:
1235 Print("fnmsub.s 'frd, 'frs1, 'frs2, 'frs3'round", instr, RV_F);
1236 break;
1237 case F2_D:
1238 Print("fnmsub.d 'frd, 'frs1, 'frs2, 'frs3'round", instr, RV_D);
1239 break;
1240 default:
1241 UnknownInstruction(instr);
1242 }
1243}
1244
1245void RISCVDisassembler::DisassembleOPFP(Instr instr) {
1246 switch (instr.funct7()) {
1247 case FADDS:
1248 Print("fadd.s 'frd, 'frs1, 'frs2'round", instr, RV_F);
1249 break;
1250 case FSUBS:
1251 Print("fsub.s 'frd, 'frs1, 'frs2'round", instr, RV_F);
1252 break;
1253 case FMULS:
1254 Print("fmul.s 'frd, 'frs1, 'frs2'round", instr, RV_F);
1255 break;
1256 case FDIVS:
1257 Print("fdiv.s 'frd, 'frs1, 'frs2'round", instr, RV_F);
1258 break;
1259 case FSQRTS:
1260 Print("fsqrt.s 'frd, 'frs1'round", instr, RV_F);
1261 break;
1262 case FSGNJS: {
1263 switch (instr.funct3()) {
1264 case J:
1265 if (instr.frs1() == instr.frs2()) {
1266 Print("fmv.s 'frd, 'frs1", instr, RV_F);
1267 } else {
1268 Print("fsgnj.s 'frd, 'frs1, 'frs2", instr, RV_F);
1269 }
1270 break;
1271 case JN:
1272 if (instr.frs1() == instr.frs2()) {
1273 Print("fneg.s 'frd, 'frs1", instr, RV_F);
1274 } else {
1275 Print("fsgnjn.s 'frd, 'frs1, 'frs2", instr, RV_F);
1276 }
1277 break;
1278 case JX:
1279 if (instr.frs1() == instr.frs2()) {
1280 Print("fabs.s 'frd, 'frs1", instr, RV_F);
1281 } else {
1282 Print("fsgnjx.s 'frd, 'frs1, 'frs2", instr, RV_F);
1283 }
1284 break;
1285 default:
1286 UnknownInstruction(instr);
1287 }
1288 break;
1289 }
1290 case FMINMAXS: {
1291 switch (instr.funct3()) {
1292 case FMIN:
1293 Print("fmin.s 'frd, 'frs1, 'frs2", instr, RV_F);
1294 break;
1295 case FMAX:
1296 Print("fmax.s 'frd, 'frs1, 'frs2", instr, RV_F);
1297 break;
1298 default:
1299 UnknownInstruction(instr);
1300 }
1301 break;
1302 }
1303 case FCMPS: {
1304 switch (instr.funct3()) {
1305 case FEQ:
1306 Print("feq.s 'rd, 'frs1, 'frs2", instr, RV_F);
1307 break;
1308 case FLT:
1309 Print("flt.s 'rd, 'frs1, 'frs2", instr, RV_F);
1310 break;
1311 case FLE:
1312 Print("fle.s 'rd, 'frs1, 'frs2", instr, RV_F);
1313 break;
1314 default:
1315 UnknownInstruction(instr);
1316 }
1317 break;
1318 }
1319 case FCLASSS: // = FMVXW
1320 switch (instr.funct3()) {
1321 case 1:
1322 Print("fclass.s 'rd, 'frs1", instr, RV_F);
1323 break;
1324 case 0:
1325 Print("fmv.x.w 'rd, 'frs1", instr, RV_F);
1326 break;
1327 default:
1328 UnknownInstruction(instr);
1329 }
1330 break;
1331 case FCVTintS:
1332 switch (static_cast<FcvtRs2>(instr.rs2())) {
1333 case W:
1334 Print("fcvt.w.s 'rd, 'frs1'round", instr, RV_F);
1335 break;
1336 case WU:
1337 Print("fcvt.wu.s 'rd, 'frs1'round", instr, RV_F);
1338 break;
1339#if XLEN >= 64
1340 case L:
1341 Print("fcvt.l.s 'rd, 'frs1'round", instr, RV_F);
1342 break;
1343 case LU:
1344 Print("fcvt.lu.s 'rd, 'frs1'round", instr, RV_F);
1345 break;
1346#endif
1347 default:
1348 UnknownInstruction(instr);
1349 }
1350 break;
1351 case FCVTSint:
1352 switch (static_cast<FcvtRs2>(instr.rs2())) {
1353 case W:
1354 Print("fcvt.s.w 'frd, 'rs1'round", instr, RV_F);
1355 break;
1356 case WU:
1357 Print("fcvt.s.wu 'frd, 'rs1'round", instr, RV_F);
1358 break;
1359#if XLEN >= 64
1360 case L:
1361 Print("fcvt.s.l 'frd, 'rs1'round", instr, RV_F);
1362 break;
1363 case LU:
1364 Print("fcvt.s.lu 'frd, 'rs1'round", instr, RV_F);
1365 break;
1366#endif
1367 default:
1368 UnknownInstruction(instr);
1369 }
1370 break;
1371 case FMVWX:
1372 Print("fmv.w.x 'frd, 'rs1", instr, RV_F);
1373 break;
1374 case FADDD:
1375 Print("fadd.d 'frd, 'frs1, 'frs2'round", instr, RV_D);
1376 break;
1377 case FSUBD:
1378 Print("fsub.d 'frd, 'frs1, 'frs2'round", instr, RV_D);
1379 break;
1380 case FMULD:
1381 Print("fmul.d 'frd, 'frs1, 'frs2'round", instr, RV_D);
1382 break;
1383 case FDIVD:
1384 Print("fdiv.d 'frd, 'frs1, 'frs2'round", instr, RV_D);
1385 break;
1386 case FSQRTD:
1387 Print("fsqrt.d 'frd, 'frs1'round", instr, RV_D);
1388 break;
1389 case FSGNJD: {
1390 switch (instr.funct3()) {
1391 case J:
1392 if (instr.frs1() == instr.frs2()) {
1393 Print("fmv.d 'frd, 'frs1", instr, RV_D);
1394 } else {
1395 Print("fsgnj.d 'frd, 'frs1, 'frs2", instr, RV_D);
1396 }
1397 break;
1398 case JN:
1399 if (instr.frs1() == instr.frs2()) {
1400 Print("fneg.d 'frd, 'frs1", instr, RV_D);
1401 } else {
1402 Print("fsgnjn.d 'frd, 'frs1, 'frs2", instr, RV_D);
1403 }
1404 break;
1405 case JX:
1406 if (instr.frs1() == instr.frs2()) {
1407 Print("fabs.d 'frd, 'frs1", instr, RV_D);
1408 } else {
1409 Print("fsgnjx.d 'frd, 'frs1, 'frs2", instr, RV_D);
1410 }
1411 break;
1412 default:
1413 UnknownInstruction(instr);
1414 }
1415 break;
1416 }
1417 case FMINMAXD: {
1418 switch (instr.funct3()) {
1419 case FMIN:
1420 Print("fmin.d 'frd, 'frs1, 'frs2", instr, RV_D);
1421 break;
1422 case FMAX:
1423 Print("fmax.d 'frd, 'frs1, 'frs2", instr, RV_D);
1424 break;
1425 default:
1426 UnknownInstruction(instr);
1427 }
1428 break;
1429 }
1430 case FCVTS: {
1431 switch (instr.rs2()) {
1432 case 1:
1433 Print("fcvt.s.d 'frd, 'frs1'round", instr, RV_D);
1434 break;
1435 default:
1436 UnknownInstruction(instr);
1437 }
1438 break;
1439 }
1440 case FCVTD: {
1441 switch (instr.rs2()) {
1442 case 0:
1443 Print("fcvt.d.s 'frd, 'frs1'round", instr, RV_D);
1444 break;
1445 default:
1446 UnknownInstruction(instr);
1447 }
1448 break;
1449 }
1450 case FCMPD: {
1451 switch (instr.funct3()) {
1452 case FEQ:
1453 Print("feq.d 'rd, 'frs1, 'frs2", instr, RV_D);
1454 break;
1455 case FLT:
1456 Print("flt.d 'rd, 'frs1, 'frs2", instr, RV_D);
1457 break;
1458 case FLE:
1459 Print("fle.d 'rd, 'frs1, 'frs2", instr, RV_D);
1460 break;
1461 default:
1462 UnknownInstruction(instr);
1463 }
1464 break;
1465 }
1466 case FCLASSD: // = FMVXD
1467 switch (instr.funct3()) {
1468 case 1:
1469 Print("fclass.d 'rd, 'frs1", instr, RV_D);
1470 break;
1471#if XLEN >= 64
1472 case 0:
1473 Print("fmv.x.d 'rd, 'frs1", instr, RV_D);
1474 break;
1475#endif
1476 default:
1477 UnknownInstruction(instr);
1478 }
1479 break;
1480 case FCVTintD:
1481 switch (static_cast<FcvtRs2>(instr.rs2())) {
1482 case W:
1483 Print("fcvt.w.d 'rd, 'frs1'round", instr, RV_D);
1484 break;
1485 case WU:
1486 Print("fcvt.wu.d 'rd, 'frs1'round", instr, RV_D);
1487 break;
1488#if XLEN >= 64
1489 case L:
1490 Print("fcvt.l.d 'rd, 'frs1'round", instr, RV_D);
1491 break;
1492 case LU:
1493 Print("fcvt.lu.d 'rd, 'frs1'round", instr, RV_D);
1494 break;
1495#endif
1496 default:
1497 UnknownInstruction(instr);
1498 }
1499 break;
1500 case FCVTDint:
1501 switch (static_cast<FcvtRs2>(instr.rs2())) {
1502 case W:
1503 Print("fcvt.d.w 'frd, 'rs1'round", instr, RV_D);
1504 break;
1505 case WU:
1506 Print("fcvt.d.wu 'frd, 'rs1'round", instr, RV_D);
1507 break;
1508#if XLEN >= 64
1509 case L:
1510 Print("fcvt.d.l 'frd, 'rs1'round", instr, RV_D);
1511 break;
1512 case LU:
1513 Print("fcvt.d.lu 'frd, 'rs1'round", instr, RV_D);
1514 break;
1515#endif
1516 default:
1517 UnknownInstruction(instr);
1518 }
1519 break;
1520#if XLEN >= 64
1521 case FMVDX:
1522 Print("fmv.d.x 'frd, 'rs1", instr, RV_D);
1523 break;
1524#endif
1525 default:
1526 UnknownInstruction(instr);
1527 }
1528}
1529
1530void RISCVDisassembler::UnknownInstruction(Instr instr) {
1531 if (instr.encoding() == 0) {
1532 Print("trap", instr, RV_I);
1533 } else {
1534 Print("unknown", instr, ExtensionSet::Empty());
1535 }
1536}
1537
1538void RISCVDisassembler::UnknownInstruction(CInstr instr) {
1539 if (instr.encoding() == 0) {
1540 Print("trap", instr, RV_I);
1541 } else {
1542 Print("unknown", instr, ExtensionSet::Empty());
1543 }
1544}
1545
1546void RISCVDisassembler::Print(const char* format,
1547 Instr instr,
1548 ExtensionSet ex) {
1549 // Printf(" %08x ", instr.encoding());
1550
1551 while (format[0] != '\0') {
1552 if (format[0] == '\'') {
1553 format = PrintOption(format + 1, instr);
1554 } else {
1555 Printf("%c", format[0]);
1556 format++;
1557 }
1558 }
1559
1560 // Printf("\n");
1561}
1562
1563void RISCVDisassembler::Print(const char* format,
1564 CInstr instr,
1565 ExtensionSet ex) {
1566 // Printf(" %04x ", instr.encoding());
1567
1568 while (format[0] != '\0') {
1569 if (format[0] == '\'') {
1570 format = PrintOption(format + 1, instr);
1571 } else {
1572 Printf("%c", format[0]);
1573 format++;
1574 }
1575 }
1576
1577 // Printf("\n");
1578}
1579
1580#define STRING_STARTS_WITH(string, compare_string) \
1581 (strncmp(string, compare_string, strlen(compare_string)) == 0)
1582
1583const char* RISCVDisassembler::PrintOption(const char* format, Instr instr) {
1584 if (STRING_STARTS_WITH(format, "rd")) {
1585 Printf("%s", cpu_reg_names[instr.rd()]);
1586 return format + 2;
1587 } else if (STRING_STARTS_WITH(format, "rs1")) {
1588 Printf("%s", cpu_reg_names[instr.rs1()]);
1589 return format + 3;
1590 } else if (STRING_STARTS_WITH(format, "rs2")) {
1591 Printf("%s", cpu_reg_names[instr.rs2()]);
1592 return format + 3;
1593 } else if (STRING_STARTS_WITH(format, "shamt")) {
1594 Printf("0x%x", instr.shamt());
1595 return format + 5;
1596 } else if (STRING_STARTS_WITH(format, "jimm")) {
1597 Printf("%+" Pd, static_cast<intptr_t>(instr.jtype_imm()));
1598 return format + 4;
1599 } else if (STRING_STARTS_WITH(format, "uimm")) {
1600 // objdump instead displays (imm >> 12) as hex.
1601 Printf("%" Pd, static_cast<intptr_t>(instr.utype_imm()));
1602 return format + 4;
1603 } else if (STRING_STARTS_WITH(format, "iimm")) {
1604 Printf("%" Pd, static_cast<intptr_t>(instr.itype_imm()));
1605 return format + 4;
1606 } else if (STRING_STARTS_WITH(format, "simm")) {
1607 Printf("%" Pd, static_cast<intptr_t>(instr.stype_imm()));
1608 return format + 4;
1609 } else if (STRING_STARTS_WITH(format, "bimm")) {
1610 Printf("%+" Pd, static_cast<intptr_t>(instr.btype_imm()));
1611 return format + 4;
1612 } else if (STRING_STARTS_WITH(format, "zimm")) {
1613 Printf("%" Pd, static_cast<intptr_t>(instr.zimm()));
1614 return format + 4;
1615 } else if (STRING_STARTS_WITH(format, "csr")) {
1616 Printf("0x%" Px, static_cast<intptr_t>(instr.csr()));
1617 return format + 3;
1618 } else if (STRING_STARTS_WITH(format, "order")) {
1619 switch (instr.memory_order()) {
1620 case std::memory_order_relaxed:
1621 break;
1622 case std::memory_order_acquire:
1623 Printf(".aq");
1624 break;
1625 case std::memory_order_release:
1626 Printf(".rl");
1627 break;
1628 case std::memory_order_acq_rel:
1629 Printf(".aqrl");
1630 break;
1631 default:
1632 UNREACHABLE();
1633 }
1634 return format + 5;
1635 } else if (STRING_STARTS_WITH(format, "round")) {
1636 switch (instr.rounding()) {
1637 case RNE:
1638 // Printf(", rne");
1639 break;
1640 case RTZ:
1641 Printf(", rtz");
1642 break;
1643 case RDN:
1644 Printf(", rdn");
1645 break;
1646 case RUP:
1647 Printf(", rup");
1648 break;
1649 case RMM:
1650 Printf(", rmm");
1651 break;
1652 case DYN:
1653 Printf(", dyn");
1654 break;
1655 default:
1656 Printf("<invalid rounding mode>");
1657 }
1658 return format + 5;
1659 } else if (STRING_STARTS_WITH(format, "predsucc")) {
1660 HartEffects pred = static_cast<HartEffects>((instr.itype_imm() >> 4) & 0xF);
1661 HartEffects succ = static_cast<HartEffects>((instr.itype_imm() >> 0) & 0xF);
1662 if ((pred != HartEffects::kAll) || (succ != HartEffects::kAll)) {
1663 Printf(" ");
1664 if ((pred & HartEffects::kInput) != 0) Printf("i");
1665 if ((pred & HartEffects::kOutput) != 0) Printf("o");
1666 if ((pred & HartEffects::kRead) != 0) Printf("r");
1667 if ((pred & HartEffects::kWrite) != 0) Printf("w");
1668 Printf(",");
1669 if ((succ & HartEffects::kInput) != 0) Printf("i");
1670 if ((succ & HartEffects::kOutput) != 0) Printf("o");
1671 if ((succ & HartEffects::kRead) != 0) Printf("r");
1672 if ((succ & HartEffects::kWrite) != 0) Printf("w");
1673 }
1674 return format + 8;
1675 } else if (STRING_STARTS_WITH(format, "frd")) {
1676 Printf("%s", fpu_reg_names[instr.frd()]);
1677 return format + 3;
1678 } else if (STRING_STARTS_WITH(format, "frs1")) {
1679 Printf("%s", fpu_reg_names[instr.frs1()]);
1680 return format + 4;
1681 } else if (STRING_STARTS_WITH(format, "frs2")) {
1682 Printf("%s", fpu_reg_names[instr.frs2()]);
1683 return format + 4;
1684 } else if (STRING_STARTS_WITH(format, "frs3")) {
1685 Printf("%s", fpu_reg_names[instr.frs3()]);
1686 return format + 4;
1687 }
1688
1689 FATAL("Bad format %s\n", format);
1690 return nullptr;
1691}
1692
1693const char* RISCVDisassembler::PrintOption(const char* format, CInstr instr) {
1694 if (STRING_STARTS_WITH(format, "rdp")) {
1695 Printf("%s", cpu_reg_names[instr.rdp()]);
1696 return format + 3;
1697 } else if (STRING_STARTS_WITH(format, "rs1p")) {
1698 Printf("%s", cpu_reg_names[instr.rs1p()]);
1699 return format + 4;
1700 } else if (STRING_STARTS_WITH(format, "rs2p")) {
1701 Printf("%s", cpu_reg_names[instr.rs2p()]);
1702 return format + 4;
1703 } else if (STRING_STARTS_WITH(format, "rd")) {
1704 Printf("%s", cpu_reg_names[instr.rd()]);
1705 return format + 2;
1706 } else if (STRING_STARTS_WITH(format, "rs1")) {
1707 Printf("%s", cpu_reg_names[instr.rs1()]);
1708 return format + 3;
1709 } else if (STRING_STARTS_WITH(format, "rs2")) {
1710 Printf("%s", cpu_reg_names[instr.rs2()]);
1711 return format + 3;
1712 } else if (STRING_STARTS_WITH(format, "frdp")) {
1713 Printf("%s", fpu_reg_names[instr.frdp()]);
1714 return format + 4;
1715 } else if (STRING_STARTS_WITH(format, "frs1p")) {
1716 Printf("%s", fpu_reg_names[instr.frs1p()]);
1717 return format + 5;
1718 } else if (STRING_STARTS_WITH(format, "frs2p")) {
1719 Printf("%s", fpu_reg_names[instr.frs2p()]);
1720 return format + 5;
1721 } else if (STRING_STARTS_WITH(format, "frd")) {
1722 Printf("%s", fpu_reg_names[instr.frd()]);
1723 return format + 3;
1724 } else if (STRING_STARTS_WITH(format, "frs1")) {
1725 Printf("%s", fpu_reg_names[instr.frs1()]);
1726 return format + 4;
1727 } else if (STRING_STARTS_WITH(format, "frs2")) {
1728 Printf("%s", fpu_reg_names[instr.frs2()]);
1729 return format + 4;
1730 } else if (STRING_STARTS_WITH(format, "spload4imm")) {
1731 Printf("%" Pd, static_cast<intptr_t>(instr.spload4_imm()));
1732 return format + 10;
1733 } else if (STRING_STARTS_WITH(format, "spload8imm")) {
1734 Printf("%" Pd, static_cast<intptr_t>(instr.spload8_imm()));
1735 return format + 10;
1736 } else if (STRING_STARTS_WITH(format, "spstore4imm")) {
1737 Printf("%" Pd, static_cast<intptr_t>(instr.spstore4_imm()));
1738 return format + 11;
1739 } else if (STRING_STARTS_WITH(format, "spstore8imm")) {
1740 Printf("%" Pd, static_cast<intptr_t>(instr.spstore8_imm()));
1741 return format + 11;
1742 } else if (STRING_STARTS_WITH(format, "mem4imm")) {
1743 Printf("%" Pd, static_cast<intptr_t>(instr.mem4_imm()));
1744 return format + 7;
1745 } else if (STRING_STARTS_WITH(format, "mem8imm")) {
1746 Printf("%" Pd, static_cast<intptr_t>(instr.mem8_imm()));
1747 return format + 7;
1748 } else if (STRING_STARTS_WITH(format, "jimm")) {
1749 Printf("%+" Pd, static_cast<intptr_t>(instr.j_imm()));
1750 return format + 4;
1751 } else if (STRING_STARTS_WITH(format, "bimm")) {
1752 Printf("%+" Pd, static_cast<intptr_t>(instr.b_imm()));
1753 return format + 4;
1754 } else if (STRING_STARTS_WITH(format, "iimm")) {
1755 Printf("%" Pd, static_cast<intptr_t>(instr.i_imm()));
1756 return format + 4;
1757 } else if (STRING_STARTS_WITH(format, "uimm")) {
1758 // objdump instead displays (imm >> 12) as hex.
1759 Printf("%" Pd, static_cast<intptr_t>(instr.u_imm()));
1760 return format + 4;
1761 } else if (STRING_STARTS_WITH(format, "i16imm")) {
1762 Printf("%" Pd, static_cast<intptr_t>(instr.i16_imm()));
1763 return format + 6;
1764 } else if (STRING_STARTS_WITH(format, "i4spnimm")) {
1765 Printf("%" Pd, static_cast<intptr_t>(instr.i4spn_imm()));
1766 return format + 8;
1767 }
1768
1769 FATAL("Bad format %s\n", format);
1770 return nullptr;
1771}
1772
1773void Disassembler::DecodeInstruction(char* hex_buffer,
1774 intptr_t hex_size,
1775 char* human_buffer,
1776 intptr_t human_size,
1777 int* out_instr_size,
1778 const Code& code,
1779 Object** object,
1780 uword pc) {
1781 RISCVDisassembler decoder(human_buffer, human_size,
1782 FLAG_use_compressed_instructions ? RV_GC : RV_G);
1783 int instr_size = decoder.Disassemble(pc);
1784 if (instr_size == 2) {
1785 Utils::SNPrint(hex_buffer, hex_size, " %04x",
1786 *reinterpret_cast<uint16_t*>(pc));
1787 } else if (instr_size == 4) {
1788 Utils::SNPrint(hex_buffer, hex_size, "%08x",
1789 LoadUnaligned(reinterpret_cast<uint32_t*>(pc)));
1790 }
1791 if (out_instr_size != nullptr) {
1792 *out_instr_size = instr_size;
1793 }
1794
1795 *object = nullptr;
1796 if (!code.IsNull()) {
1797 *object = &Object::Handle();
1798 if (!DecodeLoadObjectFromPoolOrThread(pc, code, *object)) {
1799 *object = nullptr;
1800 }
1801 }
1802}
1803
1804#endif // !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
1805
1806} // namespace dart
1807
1808#endif // defined(TARGET_ARCH_RISCV)
static uint32_t buffer_size(uint32_t offset, uint32_t maxAlignment)
#define UNREACHABLE()
Definition assert.h:248
static void DecodeInstruction(char *hex_buffer, intptr_t hex_size, char *human_buffer, intptr_t human_size, int *out_instr_len, const Code &code, Object **object, uword pc)
static Object & Handle()
Definition object.h:407
static int SNPrint(char *str, size_t size, const char *format,...) PRINTF_ATTRIBUTE(3
#define FATAL(error)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
static const uint8_t buffer[]
uint32_t uint32_t * format
va_start(args, format)
va_end(args)
static constexpr Extension RV_F(3)
bool IsCInstruction(uint16_t parcel)
static constexpr Extension RV_Zbs(9)
static constexpr ExtensionSet RV_GC
const char *const fpu_reg_names[kNumberOfFpuRegisters]
static constexpr Extension RV_Zbc(8)
uintptr_t uword
Definition globals.h:501
bool DecodeLoadObjectFromPoolOrThread(uword pc, const Code &code, Object *obj)
static T LoadUnaligned(const T *ptr)
Definition unaligned.h:14
static constexpr Extension RV_A(2)
const char *const cpu_reg_names[kNumberOfCpuRegisters]
static constexpr Extension RV_Zba(6)
static constexpr Extension RV_M(1)
static constexpr Extension RV_C(5)
static constexpr ExtensionSet RV_G
static constexpr Extension RV_D(4)
static constexpr Extension RV_I(0)
static constexpr Extension RV_Zbb(7)
#define Px
Definition globals.h:410
#define Pd
Definition globals.h:408
#define PRINTF_ATTRIBUTE(string_index, first_to_check)
Definition globals.h:697