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