Disasm-riscv64.cpp (67788B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 */ 4 // Copyright 2011 the V8 project authors. All rights reserved. 5 // Use of this source code is governed by a BSD-style license that can be 6 // found in the LICENSE file. 7 8 // A Disassembler object is used to disassemble a block of code instruction by 9 // instruction. The default implementation of the NameConverter object can be 10 // overriden to modify register names or to do symbol lookup on addresses. 11 // 12 // The example below will disassemble a block of code and print it to stdout. 13 // 14 // disasm::NameConverter converter; 15 // disasm::Disassembler d(converter); 16 // for (uint8_t* pc = begin; pc < end;) { 17 // disasm::EmbeddedVector<char, disasm::ReasonableBufferSize> buffer; 18 // uint8_t* prev_pc = pc; 19 // pc += d.InstructionDecode(buffer, pc); 20 // printf("%p %08x %s\n", 21 // prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer); 22 // } 23 // 24 // The Disassembler class also has a convenience method to disassemble a block 25 // of code into a FILE*, meaning that the above functionality could also be 26 // achieved by just calling Disassembler::Disassemble(stdout, begin, end); 27 28 #include "jit/riscv64/disasm/Disasm-riscv64.h" 29 30 #include <stdio.h> 31 #include <string.h> 32 #include <string_view> 33 34 #include "jit/riscv64/Assembler-riscv64.h" 35 36 namespace js { 37 namespace jit { 38 namespace disasm { 39 40 #define UNSUPPORTED_RISCV() printf("Unsupported instruction %d.\n", __LINE__) 41 //------------------------------------------------------------------------------ 42 43 // Decoder decodes and disassembles instructions into an output buffer. 44 // It uses the converter to convert register names and call destinations into 45 // more informative description. 46 class Decoder { 47 public: 48 Decoder(const disasm::NameConverter& converter, V8Vector<char> out_buffer) 49 : converter_(converter), out_buffer_(out_buffer), out_buffer_pos_(0) { 50 out_buffer_[out_buffer_pos_] = '\0'; 51 } 52 53 ~Decoder() {} 54 55 // Writes one disassembled instruction into 'buffer' (0-terminated). 56 // Returns the length of the disassembled machine instruction in bytes. 57 int InstructionDecode(uint8_t* instruction); 58 59 static bool IsConstantPoolAt(uint8_t* instr_ptr); 60 static int ConstantPoolSizeAt(uint8_t* instr_ptr); 61 62 private: 63 // Bottleneck functions to print into the out_buffer. 64 void PrintChar(const char ch); 65 void Print(const char* str); 66 67 // Printing of common values. 68 void PrintRegister(int reg); 69 void PrintFPURegister(int freg); 70 void PrintVRegister(int reg); 71 void PrintFPUStatusRegister(int freg); 72 void PrintRs1(Instruction* instr); 73 void PrintRs2(Instruction* instr); 74 void PrintRd(Instruction* instr); 75 void PrintUimm(Instruction* instr); 76 void PrintVs1(Instruction* instr); 77 void PrintVs2(Instruction* instr); 78 void PrintVd(Instruction* instr); 79 void PrintFRs1(Instruction* instr); 80 void PrintFRs2(Instruction* instr); 81 void PrintFRs3(Instruction* instr); 82 void PrintFRd(Instruction* instr); 83 void PrintImm12(Instruction* instr); 84 void PrintImm12X(Instruction* instr); 85 void PrintImm20U(Instruction* instr); 86 void PrintImm20J(Instruction* instr); 87 void PrintShamt(Instruction* instr); 88 void PrintShamt32(Instruction* instr); 89 void PrintRvcImm6(Instruction* instr); 90 void PrintRvcImm6U(Instruction* instr); 91 void PrintRvcImm6Addi16sp(Instruction* instr); 92 void PrintRvcShamt(Instruction* instr); 93 void PrintRvcImm6Ldsp(Instruction* instr); 94 void PrintRvcImm6Lwsp(Instruction* instr); 95 void PrintRvcImm6Sdsp(Instruction* instr); 96 void PrintRvcImm6Swsp(Instruction* instr); 97 void PrintRvcImm5W(Instruction* instr); 98 void PrintRvcImm5D(Instruction* instr); 99 void PrintRvcImm8Addi4spn(Instruction* instr); 100 void PrintRvcImm11CJ(Instruction* instr); 101 void PrintRvcImm8B(Instruction* instr); 102 void PrintRvvVm(Instruction* instr); 103 void PrintAcquireRelease(Instruction* instr); 104 void PrintBranchOffset(Instruction* instr); 105 void PrintStoreOffset(Instruction* instr); 106 void PrintCSRReg(Instruction* instr); 107 void PrintRvvSEW(Instruction* instr); 108 void PrintRvvLMUL(Instruction* instr); 109 void PrintRvvSimm5(Instruction* instr); 110 void PrintRvvUimm5(Instruction* instr); 111 void PrintRoundingMode(Instruction* instr); 112 void PrintMemoryOrder(Instruction* instr, bool is_pred); 113 114 // Each of these functions decodes one particular instruction type. 115 void DecodeRType(Instruction* instr); 116 void DecodeR4Type(Instruction* instr); 117 void DecodeRAType(Instruction* instr); 118 void DecodeRFPType(Instruction* instr); 119 void DecodeIType(Instruction* instr); 120 void DecodeSType(Instruction* instr); 121 void DecodeBType(Instruction* instr); 122 void DecodeUType(Instruction* instr); 123 void DecodeJType(Instruction* instr); 124 void DecodeCRType(Instruction* instr); 125 void DecodeCAType(Instruction* instr); 126 void DecodeCIType(Instruction* instr); 127 void DecodeCIWType(Instruction* instr); 128 void DecodeCSSType(Instruction* instr); 129 void DecodeCLType(Instruction* instr); 130 void DecodeCSType(Instruction* instr); 131 void DecodeCJType(Instruction* instr); 132 void DecodeCBType(Instruction* instr); 133 134 // Printing of instruction name. 135 void PrintInstructionName(Instruction* instr); 136 void PrintTarget(Instruction* instr); 137 138 // Handle formatting of instructions and their options. 139 int FormatRegister(Instruction* instr, const char* option); 140 int FormatFPURegisterOrRoundMode(Instruction* instr, const char* option); 141 int FormatRvcRegister(Instruction* instr, const char* option); 142 int FormatRvcImm(Instruction* instr, const char* option); 143 int FormatOption(Instruction* instr, const char* option); 144 void Format(Instruction* instr, const char* format); 145 void Unknown(Instruction* instr); 146 147 int switch_sew(Instruction* instr); 148 int switch_nf(Instruction* instr); 149 150 const disasm::NameConverter& converter_; 151 V8Vector<char> out_buffer_; 152 int out_buffer_pos_; 153 154 // Disallow copy and assign. 155 Decoder(const Decoder&) = delete; 156 void operator=(const Decoder&) = delete; 157 }; 158 159 // Support for assertions in the Decoder formatting functions. 160 #define STRING_STARTS_WITH(string, compare_string) \ 161 (strncmp(string, compare_string, strlen(compare_string)) == 0) 162 163 // Append the ch to the output buffer. 164 void Decoder::PrintChar(const char ch) { out_buffer_[out_buffer_pos_++] = ch; } 165 166 // Append the str to the output buffer. 167 void Decoder::Print(const char* str) { 168 char cur = *str++; 169 while (cur != '\0' && (out_buffer_pos_ < int(out_buffer_.length() - 1))) { 170 PrintChar(cur); 171 cur = *str++; 172 } 173 out_buffer_[out_buffer_pos_] = 0; 174 } 175 176 int Decoder::switch_nf(Instruction* instr) { 177 int nf = 0; 178 switch (instr->InstructionBits() & kRvvNfMask) { 179 case 0x20000000: 180 nf = 2; 181 break; 182 case 0x40000000: 183 nf = 3; 184 break; 185 case 0x60000000: 186 nf = 4; 187 break; 188 case 0x80000000: 189 nf = 5; 190 break; 191 case 0xa0000000: 192 nf = 6; 193 break; 194 case 0xc0000000: 195 nf = 7; 196 break; 197 case 0xe0000000: 198 nf = 8; 199 break; 200 } 201 return nf; 202 } 203 204 int Decoder::switch_sew(Instruction* instr) { 205 int width = 0; 206 if ((instr->InstructionBits() & kBaseOpcodeMask) != LOAD_FP && 207 (instr->InstructionBits() & kBaseOpcodeMask) != STORE_FP) 208 return -1; 209 switch (instr->InstructionBits() & (kRvvWidthMask | kRvvMewMask)) { 210 case 0x0: 211 width = 8; 212 break; 213 case 0x00005000: 214 width = 16; 215 break; 216 case 0x00006000: 217 width = 32; 218 break; 219 case 0x00007000: 220 width = 64; 221 break; 222 case 0x10000000: 223 width = 128; 224 break; 225 case 0x10005000: 226 width = 256; 227 break; 228 case 0x10006000: 229 width = 512; 230 break; 231 case 0x10007000: 232 width = 1024; 233 break; 234 default: 235 width = -1; 236 break; 237 } 238 return width; 239 } 240 241 // Handle all register based formatting in this function to reduce the 242 // complexity of FormatOption. 243 int Decoder::FormatRegister(Instruction* instr, const char* format) { 244 MOZ_ASSERT(format[0] == 'r'); 245 if (format[1] == 's') { // 'rs[12]: Rs register. 246 if (format[2] == '1') { 247 int reg = instr->Rs1Value(); 248 PrintRegister(reg); 249 return 3; 250 } else if (format[2] == '2') { 251 int reg = instr->Rs2Value(); 252 PrintRegister(reg); 253 return 3; 254 } 255 MOZ_CRASH(); 256 } else if (format[1] == 'd') { // 'rd: rd register. 257 int reg = instr->RdValue(); 258 PrintRegister(reg); 259 return 2; 260 } 261 MOZ_CRASH(); 262 } 263 264 // Handle all FPUregister based formatting in this function to reduce the 265 // complexity of FormatOption. 266 int Decoder::FormatFPURegisterOrRoundMode(Instruction* instr, 267 const char* format) { 268 MOZ_ASSERT(format[0] == 'f'); 269 if (format[1] == 's') { // 'fs[1-3]: Rs register. 270 if (format[2] == '1') { 271 int reg = instr->Rs1Value(); 272 PrintFPURegister(reg); 273 return 3; 274 } else if (format[2] == '2') { 275 int reg = instr->Rs2Value(); 276 PrintFPURegister(reg); 277 return 3; 278 } else if (format[2] == '3') { 279 int reg = instr->Rs3Value(); 280 PrintFPURegister(reg); 281 return 3; 282 } 283 MOZ_CRASH(); 284 } else if (format[1] == 'd') { // 'fd: fd register. 285 int reg = instr->RdValue(); 286 PrintFPURegister(reg); 287 return 2; 288 } else if (format[1] == 'r') { // 'frm 289 MOZ_ASSERT(STRING_STARTS_WITH(format, "frm")); 290 PrintRoundingMode(instr); 291 return 3; 292 } 293 MOZ_CRASH(); 294 } 295 296 // Handle all C extension register based formatting in this function to reduce 297 // the complexity of FormatOption. 298 int Decoder::FormatRvcRegister(Instruction* instr, const char* format) { 299 MOZ_ASSERT(format[0] == 'C'); 300 MOZ_ASSERT(format[1] == 'r' || format[1] == 'f'); 301 if (format[2] == 's') { // 'Crs[12]: Rs register. 302 if (format[3] == '1') { 303 if (format[4] == 's') { // 'Crs1s: 3-bits register 304 int reg = instr->RvcRs1sValue(); 305 if (format[1] == 'r') { 306 PrintRegister(reg); 307 } else if (format[1] == 'f') { 308 PrintFPURegister(reg); 309 } 310 return 5; 311 } 312 int reg = instr->RvcRs1Value(); 313 if (format[1] == 'r') { 314 PrintRegister(reg); 315 } else if (format[1] == 'f') { 316 PrintFPURegister(reg); 317 } 318 return 4; 319 } else if (format[3] == '2') { 320 if (format[4] == 's') { // 'Crs2s: 3-bits register 321 int reg = instr->RvcRs2sValue(); 322 if (format[1] == 'r') { 323 PrintRegister(reg); 324 } else if (format[1] == 'f') { 325 PrintFPURegister(reg); 326 } 327 return 5; 328 } 329 int reg = instr->RvcRs2Value(); 330 if (format[1] == 'r') { 331 PrintRegister(reg); 332 } else if (format[1] == 'f') { 333 PrintFPURegister(reg); 334 } 335 return 4; 336 } 337 MOZ_CRASH(); 338 } else if (format[2] == 'd') { // 'Crd: rd register. 339 int reg = instr->RvcRdValue(); 340 if (format[1] == 'r') { 341 PrintRegister(reg); 342 } else if (format[1] == 'f') { 343 PrintFPURegister(reg); 344 } 345 return 3; 346 } 347 MOZ_CRASH(); 348 } 349 350 // Handle all C extension immediates based formatting in this function to reduce 351 // the complexity of FormatOption. 352 int Decoder::FormatRvcImm(Instruction* instr, const char* format) { 353 // TODO(riscv): add other rvc imm format 354 MOZ_ASSERT(STRING_STARTS_WITH(format, "Cimm")); 355 if (format[4] == '6') { 356 if (format[5] == 'U') { 357 MOZ_ASSERT(STRING_STARTS_WITH(format, "Cimm6U")); 358 PrintRvcImm6U(instr); 359 return 6; 360 } else if (format[5] == 'A') { 361 if (format[9] == '1' && format[10] == '6') { 362 MOZ_ASSERT(STRING_STARTS_WITH(format, "Cimm6Addi16sp")); 363 PrintRvcImm6Addi16sp(instr); 364 return 13; 365 } 366 MOZ_CRASH(); 367 } else if (format[5] == 'L') { 368 if (format[6] == 'd') { 369 if (format[7] == 's') { 370 MOZ_ASSERT(STRING_STARTS_WITH(format, "Cimm6Ldsp")); 371 PrintRvcImm6Ldsp(instr); 372 return 9; 373 } 374 } else if (format[6] == 'w') { 375 if (format[7] == 's') { 376 MOZ_ASSERT(STRING_STARTS_WITH(format, "Cimm6Lwsp")); 377 PrintRvcImm6Lwsp(instr); 378 return 9; 379 } 380 } 381 MOZ_CRASH(); 382 } else if (format[5] == 'S') { 383 if (format[6] == 'w') { 384 MOZ_ASSERT(STRING_STARTS_WITH(format, "Cimm6Swsp")); 385 PrintRvcImm6Swsp(instr); 386 return 9; 387 } else if (format[6] == 'd') { 388 MOZ_ASSERT(STRING_STARTS_WITH(format, "Cimm6Sdsp")); 389 PrintRvcImm6Sdsp(instr); 390 return 9; 391 } 392 MOZ_CRASH(); 393 } 394 PrintRvcImm6(instr); 395 return 5; 396 } else if (format[4] == '5') { 397 MOZ_ASSERT(STRING_STARTS_WITH(format, "Cimm5")); 398 if (format[5] == 'W') { 399 MOZ_ASSERT(STRING_STARTS_WITH(format, "Cimm5W")); 400 PrintRvcImm5W(instr); 401 return 6; 402 } else if (format[5] == 'D') { 403 MOZ_ASSERT(STRING_STARTS_WITH(format, "Cimm5D")); 404 PrintRvcImm5D(instr); 405 return 6; 406 } 407 MOZ_CRASH(); 408 } else if (format[4] == '8') { 409 MOZ_ASSERT(STRING_STARTS_WITH(format, "Cimm8")); 410 if (format[5] == 'A') { 411 MOZ_ASSERT(STRING_STARTS_WITH(format, "Cimm8Addi4spn")); 412 PrintRvcImm8Addi4spn(instr); 413 return 13; 414 } else if (format[5] == 'B') { 415 MOZ_ASSERT(STRING_STARTS_WITH(format, "Cimm8B")); 416 PrintRvcImm8B(instr); 417 return 6; 418 } 419 MOZ_CRASH(); 420 } else if (format[4] == '1') { 421 MOZ_ASSERT(STRING_STARTS_WITH(format, "Cimm1")); 422 if (format[5] == '1') { 423 MOZ_ASSERT(STRING_STARTS_WITH(format, "Cimm11CJ")); 424 PrintRvcImm11CJ(instr); 425 return 8; 426 } 427 MOZ_CRASH(); 428 } 429 MOZ_CRASH(); 430 } 431 432 // FormatOption takes a formatting string and interprets it based on 433 // the current instructions. The format string points to the first 434 // character of the option string (the option escape has already been 435 // consumed by the caller.) FormatOption returns the number of 436 // characters that were consumed from the formatting string. 437 int Decoder::FormatOption(Instruction* instr, const char* format) { 438 switch (format[0]) { 439 case 'C': { // `C extension 440 if (format[1] == 'r' || format[1] == 'f') { 441 return FormatRvcRegister(instr, format); 442 } else if (format[1] == 'i') { 443 return FormatRvcImm(instr, format); 444 } else if (format[1] == 's') { 445 MOZ_ASSERT(STRING_STARTS_WITH(format, "Cshamt")); 446 PrintRvcShamt(instr); 447 return 6; 448 } 449 MOZ_CRASH(); 450 } 451 case 'c': { // `csr: CSR registers 452 if (format[1] == 's') { 453 if (format[2] == 'r') { 454 PrintCSRReg(instr); 455 return 3; 456 } 457 } 458 MOZ_CRASH(); 459 } 460 case 'i': { // 'imm12, 'imm12x, 'imm20U, or 'imm20J: Immediates. 461 if (format[3] == '1') { 462 if (format[4] == '2') { 463 MOZ_ASSERT(STRING_STARTS_WITH(format, "imm12")); 464 if (format[5] == 'x') { 465 PrintImm12X(instr); 466 return 6; 467 } 468 PrintImm12(instr); 469 return 5; 470 } 471 } else if (format[3] == '2' && format[4] == '0') { 472 MOZ_ASSERT(STRING_STARTS_WITH(format, "imm20")); 473 switch (format[5]) { 474 case 'U': 475 MOZ_ASSERT(STRING_STARTS_WITH(format, "imm20U")); 476 PrintImm20U(instr); 477 break; 478 case 'J': 479 MOZ_ASSERT(STRING_STARTS_WITH(format, "imm20J")); 480 PrintImm20J(instr); 481 break; 482 } 483 return 6; 484 } 485 MOZ_CRASH(); 486 } 487 case 'o': { // 'offB or 'offS: Offsets. 488 if (format[3] == 'B') { 489 MOZ_ASSERT(STRING_STARTS_WITH(format, "offB")); 490 PrintBranchOffset(instr); 491 return 4; 492 } else if (format[3] == 'S') { 493 MOZ_ASSERT(STRING_STARTS_WITH(format, "offS")); 494 PrintStoreOffset(instr); 495 return 4; 496 } 497 MOZ_CRASH(); 498 } 499 case 'r': { // 'r: registers. 500 return FormatRegister(instr, format); 501 } 502 case 'f': { // 'f: FPUregisters or `frm 503 return FormatFPURegisterOrRoundMode(instr, format); 504 } 505 case 'a': { // 'a: Atomic acquire and release. 506 PrintAcquireRelease(instr); 507 return 1; 508 } 509 case 'p': { // `pre 510 MOZ_ASSERT(STRING_STARTS_WITH(format, "pre")); 511 PrintMemoryOrder(instr, true); 512 return 3; 513 } 514 case 's': { // 's32 or 's64: Shift amount. 515 if (format[1] == '3') { 516 MOZ_ASSERT(STRING_STARTS_WITH(format, "s32")); 517 PrintShamt32(instr); 518 return 3; 519 } else if (format[1] == '6') { 520 MOZ_ASSERT(STRING_STARTS_WITH(format, "s64")); 521 PrintShamt(instr); 522 return 3; 523 } else if (format[1] == 'u') { 524 MOZ_ASSERT(STRING_STARTS_WITH(format, "suc")); 525 PrintMemoryOrder(instr, false); 526 return 3; 527 } else if (format[1] == 'e') { 528 MOZ_ASSERT(STRING_STARTS_WITH(format, "sew")); 529 PrintRvvSEW(instr); 530 return 3; 531 } else if (format[1] == 'i') { 532 MOZ_ASSERT(STRING_STARTS_WITH(format, "simm5")); 533 PrintRvvSimm5(instr); 534 return 5; 535 } 536 MOZ_CRASH(); 537 } 538 case 'v': { 539 if (format[1] == 'd') { 540 MOZ_ASSERT(STRING_STARTS_WITH(format, "vd")); 541 PrintVd(instr); 542 return 2; 543 } else if (format[2] == '1') { 544 MOZ_ASSERT(STRING_STARTS_WITH(format, "vs1")); 545 PrintVs1(instr); 546 return 3; 547 } else if (format[2] == '2') { 548 MOZ_ASSERT(STRING_STARTS_WITH(format, "vs2")); 549 PrintVs2(instr); 550 return 3; 551 } else { 552 MOZ_ASSERT(STRING_STARTS_WITH(format, "vm")); 553 PrintRvvVm(instr); 554 return 2; 555 } 556 } 557 case 'l': { 558 MOZ_ASSERT(STRING_STARTS_WITH(format, "lmul")); 559 PrintRvvLMUL(instr); 560 return 4; 561 } 562 case 'u': { 563 if (STRING_STARTS_WITH(format, "uimm5")) { 564 PrintRvvUimm5(instr); 565 return 5; 566 } else { 567 MOZ_ASSERT(STRING_STARTS_WITH(format, "uimm")); 568 PrintUimm(instr); 569 return 4; 570 } 571 } 572 case 't': { // 'target: target of branch instructions' 573 MOZ_ASSERT(STRING_STARTS_WITH(format, "target")); 574 PrintTarget(instr); 575 return 6; 576 } 577 } 578 MOZ_CRASH(); 579 } 580 581 // Format takes a formatting string for a whole instruction and prints it into 582 // the output buffer. All escaped options are handed to FormatOption to be 583 // parsed further. 584 void Decoder::Format(Instruction* instr, const char* format) { 585 char cur = *format++; 586 while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) { 587 if (cur == '\'') { // Single quote is used as the formatting escape. 588 format += FormatOption(instr, format); 589 } else { 590 out_buffer_[out_buffer_pos_++] = cur; 591 } 592 cur = *format++; 593 } 594 out_buffer_[out_buffer_pos_] = '\0'; 595 } 596 597 // The disassembler may end up decoding data inlined in the code. We do not want 598 // it to crash if the data does not ressemble any known instruction. 599 #define VERIFY(condition) \ 600 if (!(condition)) { \ 601 Unknown(instr); \ 602 return; \ 603 } 604 605 // For currently unimplemented decodings the disassembler calls Unknown(instr) 606 // which will just print "unknown" of the instruction bits. 607 void Decoder::Unknown(Instruction* instr) { Format(instr, "unknown"); } 608 609 // Print the register name according to the active name converter. 610 void Decoder::PrintRegister(int reg) { 611 Print(converter_.NameOfCPURegister(reg)); 612 } 613 614 void Decoder::PrintVRegister(int reg) { UNSUPPORTED_RISCV(); } 615 616 void Decoder::PrintRs1(Instruction* instr) { 617 int reg = instr->Rs1Value(); 618 PrintRegister(reg); 619 } 620 621 void Decoder::PrintRs2(Instruction* instr) { 622 int reg = instr->Rs2Value(); 623 PrintRegister(reg); 624 } 625 626 void Decoder::PrintRd(Instruction* instr) { 627 int reg = instr->RdValue(); 628 PrintRegister(reg); 629 } 630 631 void Decoder::PrintUimm(Instruction* instr) { 632 int val = instr->Rs1Value(); 633 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", val); 634 } 635 636 void Decoder::PrintVs1(Instruction* instr) { 637 int reg = instr->Vs1Value(); 638 PrintVRegister(reg); 639 } 640 641 void Decoder::PrintVs2(Instruction* instr) { 642 int reg = instr->Vs2Value(); 643 PrintVRegister(reg); 644 } 645 646 void Decoder::PrintVd(Instruction* instr) { 647 int reg = instr->VdValue(); 648 PrintVRegister(reg); 649 } 650 651 // Print the FPUregister name according to the active name converter. 652 void Decoder::PrintFPURegister(int freg) { 653 Print(converter_.NameOfXMMRegister(freg)); 654 } 655 656 void Decoder::PrintFRs1(Instruction* instr) { 657 int reg = instr->Rs1Value(); 658 PrintFPURegister(reg); 659 } 660 661 void Decoder::PrintFRs2(Instruction* instr) { 662 int reg = instr->Rs2Value(); 663 PrintFPURegister(reg); 664 } 665 666 void Decoder::PrintFRs3(Instruction* instr) { 667 int reg = instr->Rs3Value(); 668 PrintFPURegister(reg); 669 } 670 671 void Decoder::PrintFRd(Instruction* instr) { 672 int reg = instr->RdValue(); 673 PrintFPURegister(reg); 674 } 675 676 void Decoder::PrintImm12X(Instruction* instr) { 677 int32_t imm = instr->Imm12Value(); 678 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); 679 } 680 681 void Decoder::PrintImm12(Instruction* instr) { 682 int32_t imm = instr->Imm12Value(); 683 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm); 684 } 685 686 void Decoder::PrintTarget(Instruction* instr) { 687 // if (Assembler::IsJalr(instr->InstructionBits())) { 688 // if (Assembler::IsAuipc((instr - 4)->InstructionBits()) && 689 // (instr - 4)->RdValue() == instr->Rs1Value()) { 690 // int32_t imm = Assembler::BrachlongOffset((instr - 691 // 4)->InstructionBits(), 692 // instr->InstructionBits()); 693 // const char* target = 694 // converter_.NameOfAddress(reinterpret_cast<byte*>(instr - 4) + imm); 695 // out_buffer_pos_ += 696 // SNPrintF(out_buffer_ + out_buffer_pos_, " -> %s", target); 697 // return; 698 // } 699 // } 700 } 701 702 void Decoder::PrintBranchOffset(Instruction* instr) { 703 int32_t imm = instr->BranchOffset(); 704 const char* target = 705 converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + imm); 706 out_buffer_pos_ += 707 SNPrintF(out_buffer_ + out_buffer_pos_, "%d -> %s", imm, target); 708 } 709 710 void Decoder::PrintStoreOffset(Instruction* instr) { 711 int32_t imm = instr->StoreOffset(); 712 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm); 713 } 714 715 void Decoder::PrintRvvSEW(Instruction* instr) { 716 const char* sew = instr->RvvSEW(); 717 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%s", sew); 718 } 719 720 void Decoder::PrintRvvLMUL(Instruction* instr) { 721 const char* lmul = instr->RvvLMUL(); 722 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%s", lmul); 723 } 724 725 void Decoder::PrintRvvSimm5(Instruction* instr) { 726 const int simm5 = instr->RvvSimm5(); 727 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", simm5); 728 } 729 730 void Decoder::PrintRvvUimm5(Instruction* instr) { 731 const uint32_t uimm5 = instr->RvvUimm5(); 732 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%u", uimm5); 733 } 734 735 void Decoder::PrintImm20U(Instruction* instr) { 736 int32_t imm = instr->Imm20UValue(); 737 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); 738 } 739 740 void Decoder::PrintImm20J(Instruction* instr) { 741 int32_t imm = instr->Imm20JValue(); 742 const char* target = 743 converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + imm); 744 out_buffer_pos_ += 745 SNPrintF(out_buffer_ + out_buffer_pos_, "%d -> %s", imm, target); 746 } 747 748 void Decoder::PrintShamt(Instruction* instr) { 749 int32_t imm = instr->Shamt(); 750 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm); 751 } 752 753 void Decoder::PrintShamt32(Instruction* instr) { 754 int32_t imm = instr->Shamt32(); 755 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm); 756 } 757 758 void Decoder::PrintRvcImm6(Instruction* instr) { 759 int32_t imm = instr->RvcImm6Value(); 760 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm); 761 } 762 763 void Decoder::PrintRvcImm6U(Instruction* instr) { 764 int32_t imm = instr->RvcImm6Value() & 0xFFFFF; 765 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); 766 } 767 768 void Decoder::PrintRvcImm6Addi16sp(Instruction* instr) { 769 int32_t imm = instr->RvcImm6Addi16spValue(); 770 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm); 771 } 772 773 void Decoder::PrintRvcShamt(Instruction* instr) { 774 int32_t imm = instr->RvcShamt6(); 775 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm); 776 } 777 778 void Decoder::PrintRvcImm6Ldsp(Instruction* instr) { 779 int32_t imm = instr->RvcImm6LdspValue(); 780 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm); 781 } 782 783 void Decoder::PrintRvcImm6Lwsp(Instruction* instr) { 784 int32_t imm = instr->RvcImm6LwspValue(); 785 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm); 786 } 787 788 void Decoder::PrintRvcImm6Swsp(Instruction* instr) { 789 int32_t imm = instr->RvcImm6SwspValue(); 790 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm); 791 } 792 793 void Decoder::PrintRvcImm6Sdsp(Instruction* instr) { 794 int32_t imm = instr->RvcImm6SdspValue(); 795 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm); 796 } 797 798 void Decoder::PrintRvcImm5W(Instruction* instr) { 799 int32_t imm = instr->RvcImm5WValue(); 800 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm); 801 } 802 803 void Decoder::PrintRvcImm5D(Instruction* instr) { 804 int32_t imm = instr->RvcImm5DValue(); 805 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm); 806 } 807 808 void Decoder::PrintRvcImm8Addi4spn(Instruction* instr) { 809 int32_t imm = instr->RvcImm8Addi4spnValue(); 810 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm); 811 } 812 813 void Decoder::PrintRvcImm11CJ(Instruction* instr) { 814 int32_t imm = instr->RvcImm11CJValue(); 815 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm); 816 } 817 818 void Decoder::PrintRvcImm8B(Instruction* instr) { 819 int32_t imm = instr->RvcImm8BValue(); 820 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm); 821 } 822 823 void Decoder::PrintRvvVm(Instruction* instr) { 824 uint8_t imm = instr->RvvVM(); 825 if (imm == 0) { 826 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, " v0.t"); 827 } 828 } 829 830 void Decoder::PrintAcquireRelease(Instruction* instr) { 831 bool aq = instr->AqValue(); 832 bool rl = instr->RlValue(); 833 if (aq || rl) { 834 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "."); 835 } 836 if (aq) { 837 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "aq"); 838 } 839 if (rl) { 840 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "rl"); 841 } 842 } 843 844 void Decoder::PrintCSRReg(Instruction* instr) { 845 int32_t csr_reg = instr->CsrValue(); 846 std::string_view s; 847 switch (csr_reg) { 848 case csr_fflags: // Floating-Point Accrued Exceptions (RW) 849 s = "csr_fflags"; 850 break; 851 case csr_frm: // Floating-Point Dynamic Rounding Mode (RW) 852 s = "csr_frm"; 853 break; 854 case csr_fcsr: // Floating-Point Control and Status Register (RW) 855 s = "csr_fcsr"; 856 break; 857 case csr_cycle: 858 s = "csr_cycle"; 859 break; 860 case csr_time: 861 s = "csr_time"; 862 break; 863 case csr_instret: 864 s = "csr_instret"; 865 break; 866 case csr_cycleh: 867 s = "csr_cycleh"; 868 break; 869 case csr_timeh: 870 s = "csr_timeh"; 871 break; 872 case csr_instreth: 873 s = "csr_instreth"; 874 break; 875 default: 876 MOZ_CRASH(); 877 } 878 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%s", s.data()); 879 } 880 881 void Decoder::PrintRoundingMode(Instruction* instr) { 882 int frm = instr->RoundMode(); 883 std::string_view s; 884 switch (frm) { 885 case RNE: 886 s = "RNE"; 887 break; 888 case RTZ: 889 s = "RTZ"; 890 break; 891 case RDN: 892 s = "RDN"; 893 break; 894 case RUP: 895 s = "RUP"; 896 break; 897 case RMM: 898 s = "RMM"; 899 break; 900 case DYN: 901 s = "DYN"; 902 break; 903 default: 904 MOZ_CRASH(); 905 } 906 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%s", s.data()); 907 } 908 909 void Decoder::PrintMemoryOrder(Instruction* instr, bool is_pred) { 910 int memOrder = instr->MemoryOrder(is_pred); 911 char s[5] = {}; 912 char* ps = s; 913 if ((memOrder & PSI) == PSI) { 914 *ps++ = 'i'; 915 } 916 if ((memOrder & PSO) == PSO) { 917 *ps++ = 'o'; 918 } 919 if ((memOrder & PSR) == PSR) { 920 *ps++ = 'r'; 921 } 922 if ((memOrder & PSW) == PSW) { 923 *ps++ = 'w'; 924 } 925 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%s", s); 926 } 927 928 // Printing of instruction name. 929 void Decoder::PrintInstructionName(Instruction* instr) {} 930 931 // RISCV Instruction Decode Routine 932 void Decoder::DecodeRType(Instruction* instr) { 933 switch (instr->InstructionBits() & kRTypeMask) { 934 case RO_ADD: 935 Format(instr, "add 'rd, 'rs1, 'rs2"); 936 break; 937 case RO_SUB: 938 if (instr->Rs1Value() == zero.code()) 939 Format(instr, "neg 'rd, 'rs2"); 940 else 941 Format(instr, "sub 'rd, 'rs1, 'rs2"); 942 break; 943 case RO_SLL: 944 Format(instr, "sll 'rd, 'rs1, 'rs2"); 945 break; 946 case RO_SLT: 947 if (instr->Rs2Value() == zero.code()) 948 Format(instr, "sltz 'rd, 'rs1"); 949 else if (instr->Rs1Value() == zero.code()) 950 Format(instr, "sgtz 'rd, 'rs2"); 951 else 952 Format(instr, "slt 'rd, 'rs1, 'rs2"); 953 break; 954 case RO_SLTU: 955 if (instr->Rs1Value() == zero.code()) 956 Format(instr, "snez 'rd, 'rs2"); 957 else 958 Format(instr, "sltu 'rd, 'rs1, 'rs2"); 959 break; 960 case RO_XOR: 961 Format(instr, "xor 'rd, 'rs1, 'rs2"); 962 break; 963 case RO_SRL: 964 Format(instr, "srl 'rd, 'rs1, 'rs2"); 965 break; 966 case RO_SRA: 967 Format(instr, "sra 'rd, 'rs1, 'rs2"); 968 break; 969 case RO_OR: 970 Format(instr, "or 'rd, 'rs1, 'rs2"); 971 break; 972 case RO_AND: 973 Format(instr, "and 'rd, 'rs1, 'rs2"); 974 break; 975 case RO_ANDN: 976 Format(instr, "andn 'rd, 'rs1, 'rs2"); 977 break; 978 case RO_ORN: 979 Format(instr, "orn 'rd, 'rs1, 'rs2"); 980 break; 981 case RO_XNOR: 982 Format(instr, "xnor 'rd, 'rs1, 'rs2"); 983 break; 984 #ifdef JS_CODEGEN_RISCV64 985 case RO_ADDW: 986 Format(instr, "addw 'rd, 'rs1, 'rs2"); 987 break; 988 case RO_ADDUW: 989 if (instr->Rs2Value() == zero_reg.code()) { 990 Format(instr, "zext.w 'rd, 'rs1"); 991 } else { 992 Format(instr, "add.uw 'rd, 'rs1, 'rs2"); 993 } 994 break; 995 case RO_SUBW: 996 if (instr->Rs1Value() == zero.code()) 997 Format(instr, "negw 'rd, 'rs2"); 998 else 999 Format(instr, "subw 'rd, 'rs1, 'rs2"); 1000 break; 1001 case RO_SLLW: 1002 Format(instr, "sllw 'rd, 'rs1, 'rs2"); 1003 break; 1004 case RO_SRLW: 1005 Format(instr, "srlw 'rd, 'rs1, 'rs2"); 1006 break; 1007 case RO_SRAW: 1008 Format(instr, "sraw 'rd, 'rs1, 'rs2"); 1009 break; 1010 #endif /* JS_CODEGEN_RISCV64 */ 1011 // TODO(riscv): Add RISCV M extension macro 1012 case RO_MUL: 1013 Format(instr, "mul 'rd, 'rs1, 'rs2"); 1014 break; 1015 case RO_MULH: 1016 Format(instr, "mulh 'rd, 'rs1, 'rs2"); 1017 break; 1018 case RO_MULHSU: 1019 Format(instr, "mulhsu 'rd, 'rs1, 'rs2"); 1020 break; 1021 case RO_MULHU: 1022 Format(instr, "mulhu 'rd, 'rs1, 'rs2"); 1023 break; 1024 case RO_DIV: 1025 Format(instr, "div 'rd, 'rs1, 'rs2"); 1026 break; 1027 case RO_DIVU: 1028 Format(instr, "divu 'rd, 'rs1, 'rs2"); 1029 break; 1030 case RO_REM: 1031 Format(instr, "rem 'rd, 'rs1, 'rs2"); 1032 break; 1033 case RO_REMU: 1034 Format(instr, "remu 'rd, 'rs1, 'rs2"); 1035 break; 1036 #ifdef JS_CODEGEN_RISCV64 1037 case RO_MULW: 1038 Format(instr, "mulw 'rd, 'rs1, 'rs2"); 1039 break; 1040 case RO_DIVW: 1041 Format(instr, "divw 'rd, 'rs1, 'rs2"); 1042 break; 1043 case RO_DIVUW: 1044 Format(instr, "divuw 'rd, 'rs1, 'rs2"); 1045 break; 1046 case RO_REMW: 1047 Format(instr, "remw 'rd, 'rs1, 'rs2"); 1048 break; 1049 case RO_REMUW: 1050 Format(instr, "remuw 'rd, 'rs1, 'rs2"); 1051 break; 1052 case RO_SH1ADDUW: 1053 Format(instr, "sh1add.uw 'rd, 'rs1, 'rs2"); 1054 break; 1055 case RO_SH2ADDUW: 1056 Format(instr, "sh2add.uw 'rd, 'rs1, 'rs2"); 1057 break; 1058 case RO_SH3ADDUW: 1059 Format(instr, "sh3add.uw 'rd, 'rs1, 'rs2"); 1060 break; 1061 case RO_ROLW: 1062 Format(instr, "rolw 'rd, 'rs1, 'rs2"); 1063 break; 1064 case RO_RORW: 1065 Format(instr, "rorw 'rd, 'rs1, 'rs2"); 1066 break; 1067 #endif /*JS_CODEGEN_RISCV64*/ 1068 case RO_SH1ADD: 1069 Format(instr, "sh1add 'rd, 'rs1, 'rs2"); 1070 break; 1071 case RO_SH2ADD: 1072 Format(instr, "sh2add 'rd, 'rs1, 'rs2"); 1073 break; 1074 case RO_SH3ADD: 1075 Format(instr, "sh3add 'rd, 'rs1, 'rs2"); 1076 break; 1077 case RO_MAX: 1078 Format(instr, "max 'rd, 'rs1, 'rs2"); 1079 break; 1080 case RO_MAXU: 1081 Format(instr, "maxu 'rd, 'rs1, 'rs2"); 1082 break; 1083 case RO_MIN: 1084 Format(instr, "min 'rd, 'rs1, 'rs2"); 1085 break; 1086 case RO_MINU: 1087 Format(instr, "minu 'rd, 'rs1, 'rs2"); 1088 break; 1089 case RO_ZEXTH: 1090 Format(instr, "zext.h 'rd, 'rs1"); 1091 break; 1092 case RO_ROL: 1093 Format(instr, "rol 'rd, 'rs1, 'rs2"); 1094 break; 1095 case RO_ROR: 1096 Format(instr, "ror 'rd, 'rs1, 'rs2"); 1097 break; 1098 case RO_BCLR: 1099 Format(instr, "bclr 'rd, 'rs1, 'rs2"); 1100 break; 1101 case RO_BEXT: 1102 Format(instr, "bext 'rd, 'rs1, 'rs2"); 1103 break; 1104 case RO_BINV: 1105 Format(instr, "binv 'rd, 'rs1, 'rs2"); 1106 break; 1107 case RO_BSET: 1108 Format(instr, "bset 'rd, 'rs1, 'rs2"); 1109 break; 1110 // TODO(riscv): End Add RISCV M extension macro 1111 default: { 1112 switch (instr->BaseOpcode()) { 1113 case AMO: 1114 DecodeRAType(instr); 1115 break; 1116 case OP_FP: 1117 DecodeRFPType(instr); 1118 break; 1119 default: 1120 UNSUPPORTED_RISCV(); 1121 } 1122 } 1123 } 1124 } 1125 1126 void Decoder::DecodeRAType(Instruction* instr) { 1127 // TODO(riscv): Add macro for RISCV A extension 1128 // Special handling for A extension instructions because it uses func5 1129 // For all A extension instruction, V8 simulator is pure sequential. No 1130 // Memory address lock or other synchronizaiton behaviors. 1131 switch (instr->InstructionBits() & kRATypeMask) { 1132 case RO_LR_W: 1133 Format(instr, "lr.w'a 'rd, ('rs1)"); 1134 break; 1135 case RO_SC_W: 1136 Format(instr, "sc.w'a 'rd, 'rs2, ('rs1)"); 1137 break; 1138 case RO_AMOSWAP_W: 1139 Format(instr, "amoswap.w'a 'rd, 'rs2, ('rs1)"); 1140 break; 1141 case RO_AMOADD_W: 1142 Format(instr, "amoadd.w'a 'rd, 'rs2, ('rs1)"); 1143 break; 1144 case RO_AMOXOR_W: 1145 Format(instr, "amoxor.w'a 'rd, 'rs2, ('rs1)"); 1146 break; 1147 case RO_AMOAND_W: 1148 Format(instr, "amoand.w'a 'rd, 'rs2, ('rs1)"); 1149 break; 1150 case RO_AMOOR_W: 1151 Format(instr, "amoor.w'a 'rd, 'rs2, ('rs1)"); 1152 break; 1153 case RO_AMOMIN_W: 1154 Format(instr, "amomin.w'a 'rd, 'rs2, ('rs1)"); 1155 break; 1156 case RO_AMOMAX_W: 1157 Format(instr, "amomax.w'a 'rd, 'rs2, ('rs1)"); 1158 break; 1159 case RO_AMOMINU_W: 1160 Format(instr, "amominu.w'a 'rd, 'rs2, ('rs1)"); 1161 break; 1162 case RO_AMOMAXU_W: 1163 Format(instr, "amomaxu.w'a 'rd, 'rs2, ('rs1)"); 1164 break; 1165 #ifdef JS_CODEGEN_RISCV64 1166 case RO_LR_D: 1167 Format(instr, "lr.d'a 'rd, ('rs1)"); 1168 break; 1169 case RO_SC_D: 1170 Format(instr, "sc.d'a 'rd, 'rs2, ('rs1)"); 1171 break; 1172 case RO_AMOSWAP_D: 1173 Format(instr, "amoswap.d'a 'rd, 'rs2, ('rs1)"); 1174 break; 1175 case RO_AMOADD_D: 1176 Format(instr, "amoadd.d'a 'rd, 'rs2, ('rs1)"); 1177 break; 1178 case RO_AMOXOR_D: 1179 Format(instr, "amoxor.d'a 'rd, 'rs2, ('rs1)"); 1180 break; 1181 case RO_AMOAND_D: 1182 Format(instr, "amoand.d'a 'rd, 'rs2, ('rs1)"); 1183 break; 1184 case RO_AMOOR_D: 1185 Format(instr, "amoor.d'a 'rd, 'rs2, ('rs1)"); 1186 break; 1187 case RO_AMOMIN_D: 1188 Format(instr, "amomin.d'a 'rd, 'rs2, ('rs1)"); 1189 break; 1190 case RO_AMOMAX_D: 1191 Format(instr, "amoswap.d'a 'rd, 'rs2, ('rs1)"); 1192 break; 1193 case RO_AMOMINU_D: 1194 Format(instr, "amominu.d'a 'rd, 'rs2, ('rs1)"); 1195 break; 1196 case RO_AMOMAXU_D: 1197 Format(instr, "amomaxu.d'a 'rd, 'rs2, ('rs1)"); 1198 break; 1199 #endif /*JS_CODEGEN_RISCV64*/ 1200 // TODO(riscv): End Add macro for RISCV A extension 1201 default: { 1202 UNSUPPORTED_RISCV(); 1203 } 1204 } 1205 } 1206 1207 void Decoder::DecodeRFPType(Instruction* instr) { 1208 // OP_FP instructions (F/D) uses func7 first. Some further uses fun3 and rs2() 1209 1210 // kRATypeMask is only for func7 1211 switch (instr->InstructionBits() & kRFPTypeMask) { 1212 // TODO(riscv): Add macro for RISCV F extension 1213 case RO_FADD_S: 1214 Format(instr, "fadd.s 'fd, 'fs1, 'fs2"); 1215 break; 1216 case RO_FSUB_S: 1217 Format(instr, "fsub.s 'fd, 'fs1, 'fs2"); 1218 break; 1219 case RO_FMUL_S: 1220 Format(instr, "fmul.s 'fd, 'fs1, 'fs2"); 1221 break; 1222 case RO_FDIV_S: 1223 Format(instr, "fdiv.s 'fd, 'fs1, 'fs2"); 1224 break; 1225 case RO_FSQRT_S: 1226 Format(instr, "fsqrt.s 'fd, 'fs1"); 1227 break; 1228 case RO_FSGNJ_S: { // RO_FSGNJN_S RO_FSGNJX_S 1229 switch (instr->Funct3Value()) { 1230 case 0b000: // RO_FSGNJ_S 1231 if (instr->Rs1Value() == instr->Rs2Value()) 1232 Format(instr, "fmv.s 'fd, 'fs1"); 1233 else 1234 Format(instr, "fsgnj.s 'fd, 'fs1, 'fs2"); 1235 break; 1236 case 0b001: // RO_FSGNJN_S 1237 if (instr->Rs1Value() == instr->Rs2Value()) 1238 Format(instr, "fneg.s 'fd, 'fs1"); 1239 else 1240 Format(instr, "fsgnjn.s 'fd, 'fs1, 'fs2"); 1241 break; 1242 case 0b010: // RO_FSGNJX_S 1243 if (instr->Rs1Value() == instr->Rs2Value()) 1244 Format(instr, "fabs.s 'fd, 'fs1"); 1245 else 1246 Format(instr, "fsgnjx.s 'fd, 'fs1, 'fs2"); 1247 break; 1248 default: 1249 UNSUPPORTED_RISCV(); 1250 } 1251 break; 1252 } 1253 case RO_FMIN_S: { // RO_FMAX_S 1254 switch (instr->Funct3Value()) { 1255 case 0b000: // RO_FMIN_S 1256 Format(instr, "fmin.s 'fd, 'fs1, 'fs2"); 1257 break; 1258 case 0b001: // RO_FMAX_S 1259 Format(instr, "fmax.s 'fd, 'fs1, 'fs2"); 1260 break; 1261 default: 1262 UNSUPPORTED_RISCV(); 1263 } 1264 break; 1265 } 1266 case RO_FCVT_W_S: { // RO_FCVT_WU_S , 64F RO_FCVT_L_S RO_FCVT_LU_S 1267 switch (instr->Rs2Value()) { 1268 case 0b00000: // RO_FCVT_W_S 1269 Format(instr, "fcvt.w.s ['frm] 'rd, 'fs1"); 1270 break; 1271 case 0b00001: // RO_FCVT_WU_S 1272 Format(instr, "fcvt.wu.s ['frm] 'rd, 'fs1"); 1273 break; 1274 #ifdef JS_CODEGEN_RISCV64 1275 case 0b00010: // RO_FCVT_L_S 1276 Format(instr, "fcvt.l.s ['frm] 'rd, 'fs1"); 1277 break; 1278 case 0b00011: // RO_FCVT_LU_S 1279 Format(instr, "fcvt.lu.s ['frm] 'rd, 'fs1"); 1280 break; 1281 #endif /* JS_CODEGEN_RISCV64 */ 1282 default: 1283 UNSUPPORTED_RISCV(); 1284 } 1285 break; 1286 } 1287 case RO_FMV: { // RO_FCLASS_S 1288 if (instr->Rs2Value() != 0b00000) { 1289 UNSUPPORTED_RISCV(); 1290 } 1291 switch (instr->Funct3Value()) { 1292 case 0b000: // RO_FMV_X_W 1293 Format(instr, "fmv.x.w 'rd, 'fs1"); 1294 break; 1295 case 0b001: // RO_FCLASS_S 1296 Format(instr, "fclass.s 'rd, 'fs1"); 1297 break; 1298 default: 1299 UNSUPPORTED_RISCV(); 1300 } 1301 break; 1302 } 1303 case RO_FLE_S: { // RO_FEQ_S RO_FLT_S RO_FLE_S 1304 switch (instr->Funct3Value()) { 1305 case 0b010: // RO_FEQ_S 1306 Format(instr, "feq.s 'rd, 'fs1, 'fs2"); 1307 break; 1308 case 0b001: // RO_FLT_S 1309 Format(instr, "flt.s 'rd, 'fs1, 'fs2"); 1310 break; 1311 case 0b000: // RO_FLE_S 1312 Format(instr, "fle.s 'rd, 'fs1, 'fs2"); 1313 break; 1314 default: 1315 UNSUPPORTED_RISCV(); 1316 } 1317 break; 1318 } 1319 case RO_FCVT_S_W: { // RO_FCVT_S_WU , 64F RO_FCVT_S_L RO_FCVT_S_LU 1320 switch (instr->Rs2Value()) { 1321 case 0b00000: // RO_FCVT_S_W 1322 Format(instr, "fcvt.s.w 'fd, 'rs1"); 1323 break; 1324 case 0b00001: // RO_FCVT_S_WU 1325 Format(instr, "fcvt.s.wu 'fd, 'rs1"); 1326 break; 1327 #ifdef JS_CODEGEN_RISCV64 1328 case 0b00010: // RO_FCVT_S_L 1329 Format(instr, "fcvt.s.l 'fd, 'rs1"); 1330 break; 1331 case 0b00011: // RO_FCVT_S_LU 1332 Format(instr, "fcvt.s.lu 'fd, 'rs1"); 1333 break; 1334 #endif /* JS_CODEGEN_RISCV64 */ 1335 default: { 1336 UNSUPPORTED_RISCV(); 1337 } 1338 } 1339 break; 1340 } 1341 case RO_FMV_W_X: { 1342 if (instr->Funct3Value() == 0b000) { 1343 Format(instr, "fmv.w.x 'fd, 'rs1"); 1344 } else { 1345 UNSUPPORTED_RISCV(); 1346 } 1347 break; 1348 } 1349 // TODO(riscv): Add macro for RISCV D extension 1350 case RO_FADD_D: 1351 Format(instr, "fadd.d 'fd, 'fs1, 'fs2"); 1352 break; 1353 case RO_FSUB_D: 1354 Format(instr, "fsub.d 'fd, 'fs1, 'fs2"); 1355 break; 1356 case RO_FMUL_D: 1357 Format(instr, "fmul.d 'fd, 'fs1, 'fs2"); 1358 break; 1359 case RO_FDIV_D: 1360 Format(instr, "fdiv.d 'fd, 'fs1, 'fs2"); 1361 break; 1362 case RO_FSQRT_D: { 1363 if (instr->Rs2Value() == 0b00000) { 1364 Format(instr, "fsqrt.d 'fd, 'fs1"); 1365 } else { 1366 UNSUPPORTED_RISCV(); 1367 } 1368 break; 1369 } 1370 case RO_FSGNJ_D: { // RO_FSGNJN_D RO_FSGNJX_D 1371 switch (instr->Funct3Value()) { 1372 case 0b000: // RO_FSGNJ_D 1373 if (instr->Rs1Value() == instr->Rs2Value()) 1374 Format(instr, "fmv.d 'fd, 'fs1"); 1375 else 1376 Format(instr, "fsgnj.d 'fd, 'fs1, 'fs2"); 1377 break; 1378 case 0b001: // RO_FSGNJN_D 1379 if (instr->Rs1Value() == instr->Rs2Value()) 1380 Format(instr, "fneg.d 'fd, 'fs1"); 1381 else 1382 Format(instr, "fsgnjn.d 'fd, 'fs1, 'fs2"); 1383 break; 1384 case 0b010: // RO_FSGNJX_D 1385 if (instr->Rs1Value() == instr->Rs2Value()) 1386 Format(instr, "fabs.d 'fd, 'fs1"); 1387 else 1388 Format(instr, "fsgnjx.d 'fd, 'fs1, 'fs2"); 1389 break; 1390 default: 1391 UNSUPPORTED_RISCV(); 1392 } 1393 break; 1394 } 1395 case RO_FMIN_D: { // RO_FMAX_D 1396 switch (instr->Funct3Value()) { 1397 case 0b000: // RO_FMIN_D 1398 Format(instr, "fmin.d 'fd, 'fs1, 'fs2"); 1399 break; 1400 case 0b001: // RO_FMAX_D 1401 Format(instr, "fmax.d 'fd, 'fs1, 'fs2"); 1402 break; 1403 default: 1404 UNSUPPORTED_RISCV(); 1405 } 1406 break; 1407 } 1408 case (RO_FCVT_S_D & kRFPTypeMask): { 1409 if (instr->Rs2Value() == 0b00001) { 1410 Format(instr, "fcvt.s.d ['frm] 'fd, 'fs1"); 1411 } else { 1412 UNSUPPORTED_RISCV(); 1413 } 1414 break; 1415 } 1416 case RO_FCVT_D_S: { 1417 if (instr->Rs2Value() == 0b00000) { 1418 Format(instr, "fcvt.d.s 'fd, 'fs1"); 1419 } else { 1420 UNSUPPORTED_RISCV(); 1421 } 1422 break; 1423 } 1424 case RO_FLE_D: { // RO_FEQ_D RO_FLT_D RO_FLE_D 1425 switch (instr->Funct3Value()) { 1426 case 0b010: // RO_FEQ_S 1427 Format(instr, "feq.d 'rd, 'fs1, 'fs2"); 1428 break; 1429 case 0b001: // RO_FLT_D 1430 Format(instr, "flt.d 'rd, 'fs1, 'fs2"); 1431 break; 1432 case 0b000: // RO_FLE_D 1433 Format(instr, "fle.d 'rd, 'fs1, 'fs2"); 1434 break; 1435 default: 1436 UNSUPPORTED_RISCV(); 1437 } 1438 break; 1439 } 1440 case (RO_FCLASS_D & kRFPTypeMask): { // RO_FCLASS_D , 64D RO_FMV_X_D 1441 if (instr->Rs2Value() != 0b00000) { 1442 UNSUPPORTED_RISCV(); 1443 break; 1444 } 1445 switch (instr->Funct3Value()) { 1446 case 0b001: // RO_FCLASS_D 1447 Format(instr, "fclass.d 'rd, 'fs1"); 1448 break; 1449 #ifdef JS_CODEGEN_RISCV64 1450 case 0b000: // RO_FMV_X_D 1451 Format(instr, "fmv.x.d 'rd, 'fs1"); 1452 break; 1453 #endif /* JS_CODEGEN_RISCV64 */ 1454 default: 1455 UNSUPPORTED_RISCV(); 1456 } 1457 break; 1458 } 1459 case RO_FCVT_W_D: { // RO_FCVT_WU_D , 64F RO_FCVT_L_D RO_FCVT_LU_D 1460 switch (instr->Rs2Value()) { 1461 case 0b00000: // RO_FCVT_W_D 1462 Format(instr, "fcvt.w.d ['frm] 'rd, 'fs1"); 1463 break; 1464 case 0b00001: // RO_FCVT_WU_D 1465 Format(instr, "fcvt.wu.d ['frm] 'rd, 'fs1"); 1466 break; 1467 #ifdef JS_CODEGEN_RISCV64 1468 case 0b00010: // RO_FCVT_L_D 1469 Format(instr, "fcvt.l.d ['frm] 'rd, 'fs1"); 1470 break; 1471 case 0b00011: // RO_FCVT_LU_D 1472 Format(instr, "fcvt.lu.d ['frm] 'rd, 'fs1"); 1473 break; 1474 #endif /* JS_CODEGEN_RISCV64 */ 1475 default: 1476 UNSUPPORTED_RISCV(); 1477 } 1478 break; 1479 } 1480 case RO_FCVT_D_W: { // RO_FCVT_D_WU , 64F RO_FCVT_D_L RO_FCVT_D_LU 1481 switch (instr->Rs2Value()) { 1482 case 0b00000: // RO_FCVT_D_W 1483 Format(instr, "fcvt.d.w 'fd, 'rs1"); 1484 break; 1485 case 0b00001: // RO_FCVT_D_WU 1486 Format(instr, "fcvt.d.wu 'fd, 'rs1"); 1487 break; 1488 #ifdef JS_CODEGEN_RISCV64 1489 case 0b00010: // RO_FCVT_D_L 1490 Format(instr, "fcvt.d.l 'fd, 'rs1"); 1491 break; 1492 case 0b00011: // RO_FCVT_D_LU 1493 Format(instr, "fcvt.d.lu 'fd, 'rs1"); 1494 break; 1495 #endif /* JS_CODEGEN_RISCV64 */ 1496 default: 1497 UNSUPPORTED_RISCV(); 1498 } 1499 break; 1500 } 1501 #ifdef JS_CODEGEN_RISCV64 1502 case RO_FMV_D_X: { 1503 if (instr->Funct3Value() == 0b000 && instr->Rs2Value() == 0b00000) { 1504 Format(instr, "fmv.d.x 'fd, 'rs1"); 1505 } else { 1506 UNSUPPORTED_RISCV(); 1507 } 1508 break; 1509 } 1510 #endif /* JS_CODEGEN_RISCV64 */ 1511 default: { 1512 UNSUPPORTED_RISCV(); 1513 } 1514 } 1515 } 1516 1517 void Decoder::DecodeR4Type(Instruction* instr) { 1518 switch (instr->InstructionBits() & kR4TypeMask) { 1519 // TODO(riscv): use F Extension macro block 1520 case RO_FMADD_S: 1521 Format(instr, "fmadd.s 'fd, 'fs1, 'fs2, 'fs3"); 1522 break; 1523 case RO_FMSUB_S: 1524 Format(instr, "fmsub.s 'fd, 'fs1, 'fs2, 'fs3"); 1525 break; 1526 case RO_FNMSUB_S: 1527 Format(instr, "fnmsub.s 'fd, 'fs1, 'fs2, 'fs3"); 1528 break; 1529 case RO_FNMADD_S: 1530 Format(instr, "fnmadd.s 'fd, 'fs1, 'fs2, 'fs3"); 1531 break; 1532 // TODO(riscv): use F Extension macro block 1533 case RO_FMADD_D: 1534 Format(instr, "fmadd.d 'fd, 'fs1, 'fs2, 'fs3"); 1535 break; 1536 case RO_FMSUB_D: 1537 Format(instr, "fmsub.d 'fd, 'fs1, 'fs2, 'fs3"); 1538 break; 1539 case RO_FNMSUB_D: 1540 Format(instr, "fnmsub.d 'fd, 'fs1, 'fs2, 'fs3"); 1541 break; 1542 case RO_FNMADD_D: 1543 Format(instr, "fnmadd.d 'fd, 'fs1, 'fs2, 'fs3"); 1544 break; 1545 default: 1546 UNSUPPORTED_RISCV(); 1547 } 1548 } 1549 1550 void Decoder::DecodeIType(Instruction* instr) { 1551 switch (instr->InstructionBits() & kITypeMask) { 1552 case RO_JALR: 1553 if (instr->RdValue() == zero.code() && instr->Rs1Value() == ra.code() && 1554 instr->Imm12Value() == 0) 1555 Format(instr, "ret"); 1556 else if (instr->RdValue() == zero.code() && instr->Imm12Value() == 0) 1557 Format(instr, "jr 'rs1"); 1558 else if (instr->RdValue() == ra.code() && instr->Imm12Value() == 0) 1559 Format(instr, "jalr 'rs1"); 1560 else 1561 Format(instr, "jalr 'rd, 'imm12('rs1)"); 1562 break; 1563 case RO_LB: 1564 Format(instr, "lb 'rd, 'imm12('rs1)"); 1565 break; 1566 case RO_LH: 1567 Format(instr, "lh 'rd, 'imm12('rs1)"); 1568 break; 1569 case RO_LW: 1570 Format(instr, "lw 'rd, 'imm12('rs1)"); 1571 break; 1572 case RO_LBU: 1573 Format(instr, "lbu 'rd, 'imm12('rs1)"); 1574 break; 1575 case RO_LHU: 1576 Format(instr, "lhu 'rd, 'imm12('rs1)"); 1577 break; 1578 #ifdef JS_CODEGEN_RISCV64 1579 case RO_LWU: 1580 Format(instr, "lwu 'rd, 'imm12('rs1)"); 1581 break; 1582 case RO_LD: 1583 Format(instr, "ld 'rd, 'imm12('rs1)"); 1584 break; 1585 #endif /*JS_CODEGEN_RISCV64*/ 1586 case RO_ADDI: 1587 if (instr->Imm12Value() == 0) { 1588 if (instr->RdValue() == zero.code() && instr->Rs1Value() == zero.code()) 1589 Format(instr, "nop"); 1590 else 1591 Format(instr, "mv 'rd, 'rs1"); 1592 } else if (instr->Rs1Value() == zero.code()) { 1593 Format(instr, "li 'rd, 'imm12"); 1594 } else { 1595 Format(instr, "addi 'rd, 'rs1, 'imm12"); 1596 } 1597 break; 1598 case RO_SLTI: 1599 Format(instr, "slti 'rd, 'rs1, 'imm12"); 1600 break; 1601 case RO_SLTIU: 1602 if (instr->Imm12Value() == 1) 1603 Format(instr, "seqz 'rd, 'rs1"); 1604 else 1605 Format(instr, "sltiu 'rd, 'rs1, 'imm12"); 1606 break; 1607 case RO_XORI: 1608 if (instr->Imm12Value() == -1) 1609 Format(instr, "not 'rd, 'rs1"); 1610 else 1611 Format(instr, "xori 'rd, 'rs1, 'imm12x"); 1612 break; 1613 case RO_ORI: 1614 Format(instr, "ori 'rd, 'rs1, 'imm12x"); 1615 break; 1616 case RO_ANDI: 1617 Format(instr, "andi 'rd, 'rs1, 'imm12x"); 1618 break; 1619 case OP_SHL: 1620 switch (instr->Funct6FieldRaw() | OP_SHL) { 1621 case RO_SLLI: 1622 Format(instr, "slli 'rd, 'rs1, 's64"); 1623 break; 1624 case RO_BCLRI: 1625 Format(instr, "bclri 'rd, 'rs1, 's64"); 1626 break; 1627 case RO_BINVI: 1628 Format(instr, "binvi 'rd, 'rs1, 's64"); 1629 break; 1630 case RO_BSETI: 1631 Format(instr, "bseti 'rd, 'rs1, 's64"); 1632 break; 1633 case OP_COUNT: 1634 switch (instr->Shamt()) { 1635 case 0: 1636 Format(instr, "clz 'rd, 'rs1"); 1637 break; 1638 case 1: 1639 Format(instr, "ctz 'rd, 'rs1"); 1640 break; 1641 case 2: 1642 Format(instr, "cpop 'rd, 'rs1"); 1643 break; 1644 case 4: 1645 Format(instr, "sext.b 'rd, 'rs1"); 1646 break; 1647 case 5: 1648 Format(instr, "sext.h 'rd, 'rs1"); 1649 break; 1650 default: 1651 UNSUPPORTED_RISCV(); 1652 } 1653 break; 1654 default: 1655 UNSUPPORTED_RISCV(); 1656 } 1657 break; 1658 case OP_SHR: { // RO_SRAI 1659 switch (instr->Funct6FieldRaw() | OP_SHR) { 1660 case RO_SRLI: 1661 Format(instr, "srli 'rd, 'rs1, 's64"); 1662 break; 1663 case RO_SRAI: 1664 Format(instr, "srai 'rd, 'rs1, 's64"); 1665 break; 1666 case RO_BEXTI: 1667 Format(instr, "bexti 'rd, 'rs1, 's64"); 1668 break; 1669 case RO_ORCB&(kFunct6Mask | OP_SHR): 1670 Format(instr, "orc.b 'rd, 'rs1"); 1671 break; 1672 case RO_RORI: 1673 #ifdef JS_CODEGEN_RISCV64 1674 Format(instr, "rori 'rd, 'rs1, 's64"); 1675 break; 1676 #else 1677 Format(instr, "rori 'rd, 'rs1, 's32"); 1678 break; 1679 #endif 1680 case RO_REV8: { 1681 if (instr->Imm12Value() == RO_REV8_IMM12) { 1682 Format(instr, "rev8 'rd, 'rs1"); 1683 break; 1684 } 1685 UNSUPPORTED_RISCV(); 1686 break; 1687 } 1688 default: 1689 UNSUPPORTED_RISCV(); 1690 } 1691 break; 1692 } 1693 #ifdef JS_CODEGEN_RISCV64 1694 case RO_ADDIW: 1695 if (instr->Imm12Value() == 0) 1696 Format(instr, "sext.w 'rd, 'rs1"); 1697 else 1698 Format(instr, "addiw 'rd, 'rs1, 'imm12"); 1699 break; 1700 case OP_SHLW: 1701 switch (instr->Funct7FieldRaw() | OP_SHLW) { 1702 case RO_SLLIW: 1703 Format(instr, "slliw 'rd, 'rs1, 's32"); 1704 break; 1705 case RO_SLLIUW: 1706 Format(instr, "slli.uw 'rd, 'rs1, 's32"); 1707 break; 1708 case OP_COUNTW: { 1709 switch (instr->Shamt()) { 1710 case 0: 1711 Format(instr, "clzw 'rd, 'rs1"); 1712 break; 1713 case 1: 1714 Format(instr, "ctzw 'rd, 'rs1"); 1715 break; 1716 case 2: 1717 Format(instr, "cpopw 'rd, 'rs1"); 1718 break; 1719 default: 1720 UNSUPPORTED_RISCV(); 1721 } 1722 break; 1723 } 1724 default: 1725 UNSUPPORTED_RISCV(); 1726 } 1727 break; 1728 case OP_SHRW: { // RO_SRAI 1729 switch (instr->Funct7FieldRaw() | OP_SHRW) { 1730 case RO_SRLIW: 1731 Format(instr, "srliw 'rd, 'rs1, 's32"); 1732 break; 1733 case RO_SRAIW: 1734 Format(instr, "sraiw 'rd, 'rs1, 's32"); 1735 break; 1736 case RO_RORIW: 1737 Format(instr, "roriw 'rd, 'rs1, 's32"); 1738 break; 1739 default: 1740 UNSUPPORTED_RISCV(); 1741 } 1742 break; 1743 } 1744 #endif /*JS_CODEGEN_RISCV64*/ 1745 case RO_FENCE: 1746 if (instr->MemoryOrder(true) == PSIORW && 1747 instr->MemoryOrder(false) == PSIORW) 1748 Format(instr, "fence"); 1749 else 1750 Format(instr, "fence 'pre, 'suc"); 1751 break; 1752 case RO_ECALL: { // RO_EBREAK 1753 if (instr->Imm12Value() == 0) { // ECALL 1754 Format(instr, "ecall"); 1755 } else if (instr->Imm12Value() == 1) { // EBREAK 1756 Format(instr, "ebreak"); 1757 } else { 1758 UNSUPPORTED_RISCV(); 1759 } 1760 break; 1761 } 1762 // TODO(riscv): use Zifencei Standard Extension macro block 1763 case RO_FENCE_I: 1764 Format(instr, "fence.i"); 1765 break; 1766 // TODO(riscv): use Zicsr Standard Extension macro block 1767 // FIXME(RISC-V): Add special formatting for CSR registers 1768 case RO_CSRRW: 1769 if (instr->CsrValue() == csr_fcsr) { 1770 if (instr->RdValue() == zero.code()) 1771 Format(instr, "fscsr 'rs1"); 1772 else 1773 Format(instr, "fscsr 'rd, 'rs1"); 1774 } else if (instr->CsrValue() == csr_frm) { 1775 if (instr->RdValue() == zero.code()) 1776 Format(instr, "fsrm 'rs1"); 1777 else 1778 Format(instr, "fsrm 'rd, 'rs1"); 1779 } else if (instr->CsrValue() == csr_fflags) { 1780 if (instr->RdValue() == zero.code()) 1781 Format(instr, "fsflags 'rs1"); 1782 else 1783 Format(instr, "fsflags 'rd, 'rs1"); 1784 } else if (instr->RdValue() == zero.code()) { 1785 Format(instr, "csrw 'csr, 'rs1"); 1786 } else { 1787 Format(instr, "csrrw 'rd, 'csr, 'rs1"); 1788 } 1789 break; 1790 case RO_CSRRS: 1791 if (instr->Rs1Value() == zero.code()) { 1792 switch (instr->CsrValue()) { 1793 case csr_instret: 1794 Format(instr, "rdinstret 'rd"); 1795 break; 1796 case csr_instreth: 1797 Format(instr, "rdinstreth 'rd"); 1798 break; 1799 case csr_time: 1800 Format(instr, "rdtime 'rd"); 1801 break; 1802 case csr_timeh: 1803 Format(instr, "rdtimeh 'rd"); 1804 break; 1805 case csr_cycle: 1806 Format(instr, "rdcycle 'rd"); 1807 break; 1808 case csr_cycleh: 1809 Format(instr, "rdcycleh 'rd"); 1810 break; 1811 case csr_fflags: 1812 Format(instr, "frflags 'rd"); 1813 break; 1814 case csr_frm: 1815 Format(instr, "frrm 'rd"); 1816 break; 1817 case csr_fcsr: 1818 Format(instr, "frcsr 'rd"); 1819 break; 1820 default: 1821 MOZ_CRASH(); 1822 } 1823 } else if (instr->Rs1Value() == zero.code()) { 1824 Format(instr, "csrr 'rd, 'csr"); 1825 } else if (instr->RdValue() == zero.code()) { 1826 Format(instr, "csrs 'csr, 'rs1"); 1827 } else { 1828 Format(instr, "csrrs 'rd, 'csr, 'rs1"); 1829 } 1830 break; 1831 case RO_CSRRC: 1832 if (instr->RdValue() == zero.code()) 1833 Format(instr, "csrc 'csr, 'rs1"); 1834 else 1835 Format(instr, "csrrc 'rd, 'csr, 'rs1"); 1836 break; 1837 case RO_CSRRWI: 1838 if (instr->RdValue() == zero.code()) 1839 Format(instr, "csrwi 'csr, 'uimm"); 1840 else 1841 Format(instr, "csrrwi 'rd, 'csr, 'uimm"); 1842 break; 1843 case RO_CSRRSI: 1844 if (instr->RdValue() == zero.code()) 1845 Format(instr, "csrsi 'csr, 'uimm"); 1846 else 1847 Format(instr, "csrrsi 'rd, 'csr, 'uimm"); 1848 break; 1849 case RO_CSRRCI: 1850 if (instr->RdValue() == zero.code()) 1851 Format(instr, "csrci 'csr, 'uimm"); 1852 else 1853 Format(instr, "csrrci 'rd, 'csr, 'uimm"); 1854 break; 1855 // TODO(riscv): use F Extension macro block 1856 case RO_FLW: 1857 Format(instr, "flw 'fd, 'imm12('rs1)"); 1858 break; 1859 // TODO(riscv): use D Extension macro block 1860 case RO_FLD: 1861 Format(instr, "fld 'fd, 'imm12('rs1)"); 1862 break; 1863 default: 1864 #ifdef CAN_USE_RVV_INSTRUCTIONS 1865 if (instr->vl_vs_width() != -1) { 1866 DecodeRvvVL(instr); 1867 } else { 1868 UNSUPPORTED_RISCV(); 1869 } 1870 break; 1871 #else 1872 UNSUPPORTED_RISCV(); 1873 #endif 1874 } 1875 } 1876 1877 void Decoder::DecodeSType(Instruction* instr) { 1878 switch (instr->InstructionBits() & kSTypeMask) { 1879 case RO_SB: 1880 Format(instr, "sb 'rs2, 'offS('rs1)"); 1881 break; 1882 case RO_SH: 1883 Format(instr, "sh 'rs2, 'offS('rs1)"); 1884 break; 1885 case RO_SW: 1886 Format(instr, "sw 'rs2, 'offS('rs1)"); 1887 break; 1888 #ifdef JS_CODEGEN_RISCV64 1889 case RO_SD: 1890 Format(instr, "sd 'rs2, 'offS('rs1)"); 1891 break; 1892 #endif /*JS_CODEGEN_RISCV64*/ 1893 // TODO(riscv): use F Extension macro block 1894 case RO_FSW: 1895 Format(instr, "fsw 'fs2, 'offS('rs1)"); 1896 break; 1897 // TODO(riscv): use D Extension macro block 1898 case RO_FSD: 1899 Format(instr, "fsd 'fs2, 'offS('rs1)"); 1900 break; 1901 default: 1902 #ifdef CAN_USE_RVV_INSTRUCTIONS 1903 if (instr->vl_vs_width() != -1) { 1904 DecodeRvvVS(instr); 1905 } else { 1906 UNSUPPORTED_RISCV(); 1907 } 1908 break; 1909 #else 1910 UNSUPPORTED_RISCV(); 1911 #endif 1912 } 1913 } 1914 1915 void Decoder::DecodeBType(Instruction* instr) { 1916 switch (instr->InstructionBits() & kBTypeMask) { 1917 case RO_BEQ: 1918 Format(instr, "beq 'rs1, 'rs2, 'offB"); 1919 break; 1920 case RO_BNE: 1921 Format(instr, "bne 'rs1, 'rs2, 'offB"); 1922 break; 1923 case RO_BLT: 1924 Format(instr, "blt 'rs1, 'rs2, 'offB"); 1925 break; 1926 case RO_BGE: 1927 Format(instr, "bge 'rs1, 'rs2, 'offB"); 1928 break; 1929 case RO_BLTU: 1930 Format(instr, "bltu 'rs1, 'rs2, 'offB"); 1931 break; 1932 case RO_BGEU: 1933 Format(instr, "bgeu 'rs1, 'rs2, 'offB"); 1934 break; 1935 default: 1936 UNSUPPORTED_RISCV(); 1937 } 1938 } 1939 void Decoder::DecodeUType(Instruction* instr) { 1940 // U Type doesn't have additional mask 1941 switch (instr->BaseOpcodeFieldRaw()) { 1942 case LUI: 1943 Format(instr, "lui 'rd, 'imm20U"); 1944 break; 1945 case AUIPC: 1946 Format(instr, "auipc 'rd, 'imm20U"); 1947 break; 1948 default: 1949 UNSUPPORTED_RISCV(); 1950 } 1951 } 1952 // namespace jit 1953 void Decoder::DecodeJType(Instruction* instr) { 1954 // J Type doesn't have additional mask 1955 switch (instr->BaseOpcodeValue()) { 1956 case JAL: 1957 if (instr->RdValue() == zero.code()) 1958 Format(instr, "j 'imm20J"); 1959 else if (instr->RdValue() == ra.code()) 1960 Format(instr, "jal 'imm20J"); 1961 else 1962 Format(instr, "jal 'rd, 'imm20J"); 1963 break; 1964 default: 1965 UNSUPPORTED_RISCV(); 1966 } 1967 } 1968 1969 void Decoder::DecodeCRType(Instruction* instr) { 1970 switch (instr->RvcFunct4Value()) { 1971 case 0b1000: 1972 if (instr->RvcRs1Value() != 0 && instr->RvcRs2Value() == 0) 1973 Format(instr, "jr 'Crs1"); 1974 else if (instr->RvcRdValue() != 0 && instr->RvcRs2Value() != 0) 1975 Format(instr, "mv 'Crd, 'Crs2"); 1976 else 1977 UNSUPPORTED_RISCV(); 1978 break; 1979 case 0b1001: 1980 if (instr->RvcRs1Value() == 0 && instr->RvcRs2Value() == 0) 1981 Format(instr, "ebreak"); 1982 else if (instr->RvcRdValue() != 0 && instr->RvcRs2Value() == 0) 1983 Format(instr, "jalr 'Crs1"); 1984 else if (instr->RvcRdValue() != 0 && instr->RvcRs2Value() != 0) 1985 Format(instr, "add 'Crd, 'Crd, 'Crs2"); 1986 else 1987 UNSUPPORTED_RISCV(); 1988 break; 1989 default: 1990 UNSUPPORTED_RISCV(); 1991 } 1992 } 1993 1994 void Decoder::DecodeCAType(Instruction* instr) { 1995 switch (instr->InstructionBits() & kCATypeMask) { 1996 case RO_C_SUB: 1997 Format(instr, "sub 'Crs1s, 'Crs1s, 'Crs2s"); 1998 break; 1999 case RO_C_XOR: 2000 Format(instr, "xor 'Crs1s, 'Crs1s, 'Crs2s"); 2001 break; 2002 case RO_C_OR: 2003 Format(instr, "or 'Crs1s, 'Crs1s, 'Crs2s"); 2004 break; 2005 case RO_C_AND: 2006 Format(instr, "and 'Crs1s, 'Crs1s, 'Crs2s"); 2007 break; 2008 #ifdef JS_CODEGEN_RISCV64 2009 case RO_C_SUBW: 2010 Format(instr, "subw 'Crs1s, 'Crs1s, 'Crs2s"); 2011 break; 2012 case RO_C_ADDW: 2013 Format(instr, "addw 'Crs1s, 'Crs1s, 'Crs2s"); 2014 break; 2015 #endif 2016 default: 2017 UNSUPPORTED_RISCV(); 2018 } 2019 } 2020 2021 void Decoder::DecodeCIType(Instruction* instr) { 2022 switch (instr->RvcOpcode()) { 2023 case RO_C_NOP_ADDI: 2024 if (instr->RvcRdValue() == 0) 2025 Format(instr, "nop"); 2026 else 2027 Format(instr, "addi 'Crd, 'Crd, 'Cimm6"); 2028 break; 2029 #ifdef JS_CODEGEN_RISCV64 2030 case RO_C_ADDIW: 2031 Format(instr, "addiw 'Crd, 'Crd, 'Cimm6"); 2032 break; 2033 #endif 2034 case RO_C_LI: 2035 Format(instr, "li 'Crd, 'Cimm6"); 2036 break; 2037 case RO_C_LUI_ADD: 2038 if (instr->RvcRdValue() == 2) 2039 Format(instr, "addi sp, sp, 'Cimm6Addi16sp"); 2040 else if (instr->RvcRdValue() != 0 && instr->RvcRdValue() != 2) 2041 Format(instr, "lui 'Crd, 'Cimm6U"); 2042 else 2043 UNSUPPORTED_RISCV(); 2044 break; 2045 case RO_C_SLLI: 2046 Format(instr, "slli 'Crd, 'Crd, 'Cshamt"); 2047 break; 2048 case RO_C_FLDSP: 2049 Format(instr, "fld 'Cfd, 'Cimm6Ldsp(sp)"); 2050 break; 2051 case RO_C_LWSP: 2052 Format(instr, "lw 'Crd, 'Cimm6Lwsp(sp)"); 2053 break; 2054 #ifdef JS_CODEGEN_RISCV64 2055 case RO_C_LDSP: 2056 Format(instr, "ld 'Crd, 'Cimm6Ldsp(sp)"); 2057 break; 2058 #elif defined(JS_CODEGEN_RISCV32) 2059 case RO_C_FLWSP: 2060 Format(instr, "flw 'Cfd, 'Cimm6Ldsp(sp)"); 2061 break; 2062 #endif 2063 default: 2064 UNSUPPORTED_RISCV(); 2065 } 2066 } 2067 2068 void Decoder::DecodeCIWType(Instruction* instr) { 2069 switch (instr->RvcOpcode()) { 2070 case RO_C_ADDI4SPN: 2071 Format(instr, "addi 'Crs2s, sp, 'Cimm8Addi4spn"); 2072 break; 2073 default: 2074 UNSUPPORTED_RISCV(); 2075 } 2076 } 2077 2078 void Decoder::DecodeCSSType(Instruction* instr) { 2079 switch (instr->RvcOpcode()) { 2080 case RO_C_SWSP: 2081 Format(instr, "sw 'Crs2, 'Cimm6Swsp(sp)"); 2082 break; 2083 #ifdef JS_CODEGEN_RISCV64 2084 case RO_C_SDSP: 2085 Format(instr, "sd 'Crs2, 'Cimm6Sdsp(sp)"); 2086 break; 2087 #elif defined(JS_CODEGEN_RISCV32) 2088 case RO_C_FSWSP: 2089 Format(instr, "fsw 'Cfs2, 'Cimm6Sdsp(sp)"); 2090 break; 2091 #endif 2092 case RO_C_FSDSP: 2093 Format(instr, "fsd 'Cfs2, 'Cimm6Sdsp(sp)"); 2094 break; 2095 default: 2096 UNSUPPORTED_RISCV(); 2097 } 2098 } 2099 2100 void Decoder::DecodeCLType(Instruction* instr) { 2101 switch (instr->RvcOpcode()) { 2102 case RO_C_FLD: 2103 Format(instr, "fld 'Cfs2s, 'Cimm5D('Crs1s)"); 2104 break; 2105 case RO_C_LW: 2106 Format(instr, "lw 'Crs2s, 'Cimm5W('Crs1s)"); 2107 break; 2108 #ifdef JS_CODEGEN_RISCV64 2109 case RO_C_LD: 2110 Format(instr, "ld 'Crs2s, 'Cimm5D('Crs1s)"); 2111 break; 2112 #elif defined(JS_CODEGEN_RISCV32) 2113 case RO_C_FLW: 2114 Format(instr, "fld 'Cfs2s, 'Cimm5D('Crs1s)"); 2115 break; 2116 #endif 2117 2118 default: 2119 UNSUPPORTED_RISCV(); 2120 } 2121 } 2122 2123 void Decoder::DecodeCSType(Instruction* instr) { 2124 switch (instr->RvcOpcode()) { 2125 case RO_C_FSD: 2126 Format(instr, "fsd 'Cfs2s, 'Cimm5D('Crs1s)"); 2127 break; 2128 case RO_C_SW: 2129 Format(instr, "sw 'Crs2s, 'Cimm5W('Crs1s)"); 2130 break; 2131 #ifdef JS_CODEGEN_RISCV64 2132 case RO_C_SD: 2133 Format(instr, "sd 'Crs2s, 'Cimm5D('Crs1s)"); 2134 break; 2135 #elif defined(JS_CODEGEN_RISCV32) 2136 case RO_C_FSW: 2137 Format(instr, "fsw 'Cfs2s, 'Cimm5D('Crs1s)"); 2138 break; 2139 #endif 2140 default: 2141 UNSUPPORTED_RISCV(); 2142 } 2143 } 2144 2145 void Decoder::DecodeCJType(Instruction* instr) { 2146 switch (instr->RvcOpcode()) { 2147 case RO_C_J: 2148 Format(instr, "j 'Cimm11CJ"); 2149 break; 2150 default: 2151 UNSUPPORTED_RISCV(); 2152 } 2153 } 2154 2155 void Decoder::DecodeCBType(Instruction* instr) { 2156 switch (instr->RvcOpcode()) { 2157 case RO_C_BNEZ: 2158 Format(instr, "bnez 'Crs1s, x0, 'Cimm8B"); 2159 break; 2160 case RO_C_BEQZ: 2161 Format(instr, "beqz 'Crs1s, x0, 'Cimm8B"); 2162 break; 2163 case RO_C_MISC_ALU: 2164 if (instr->RvcFunct2BValue() == 0b00) 2165 Format(instr, "srli 'Crs1s, 'Crs1s, 'Cshamt"); 2166 else if (instr->RvcFunct2BValue() == 0b01) 2167 Format(instr, "srai 'Crs1s, 'Crs1s, 'Cshamt"); 2168 else if (instr->RvcFunct2BValue() == 0b10) 2169 Format(instr, "andi 'Crs1s, 'Crs1s, 'Cimm6"); 2170 else 2171 UNSUPPORTED_RISCV(); 2172 break; 2173 default: 2174 UNSUPPORTED_RISCV(); 2175 } 2176 } 2177 2178 #undef VERIFIY 2179 2180 bool Decoder::IsConstantPoolAt(uint8_t* instr_ptr) { 2181 UNSUPPORTED_RISCV(); 2182 MOZ_CRASH(); 2183 } 2184 2185 int Decoder::ConstantPoolSizeAt(uint8_t* instr_ptr) { 2186 UNSUPPORTED_RISCV(); 2187 MOZ_CRASH(); 2188 } 2189 2190 // Disassemble the instruction at *instr_ptr into the output buffer. 2191 int Decoder::InstructionDecode(byte* instr_ptr) { 2192 Instruction* instr = Instruction::At(instr_ptr); 2193 // Print raw instruction bytes. 2194 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%08x ", 2195 instr->InstructionBits()); 2196 switch (instr->InstructionType()) { 2197 case Instruction::kRType: 2198 DecodeRType(instr); 2199 break; 2200 case Instruction::kR4Type: 2201 DecodeR4Type(instr); 2202 break; 2203 case Instruction::kIType: 2204 DecodeIType(instr); 2205 break; 2206 case Instruction::kSType: 2207 DecodeSType(instr); 2208 break; 2209 case Instruction::kBType: 2210 DecodeBType(instr); 2211 break; 2212 case Instruction::kUType: 2213 DecodeUType(instr); 2214 break; 2215 case Instruction::kJType: 2216 DecodeJType(instr); 2217 break; 2218 case Instruction::kCRType: 2219 DecodeCRType(instr); 2220 break; 2221 case Instruction::kCAType: 2222 DecodeCAType(instr); 2223 break; 2224 case Instruction::kCJType: 2225 DecodeCJType(instr); 2226 break; 2227 case Instruction::kCIType: 2228 DecodeCIType(instr); 2229 break; 2230 case Instruction::kCIWType: 2231 DecodeCIWType(instr); 2232 break; 2233 case Instruction::kCSSType: 2234 DecodeCSSType(instr); 2235 break; 2236 case Instruction::kCLType: 2237 DecodeCLType(instr); 2238 break; 2239 case Instruction::kCSType: 2240 DecodeCSType(instr); 2241 break; 2242 case Instruction::kCBType: 2243 DecodeCBType(instr); 2244 break; 2245 #ifdef CAN_USE_RVV_INSTRUCTIONS 2246 case Instruction::kVType: 2247 DecodeVType(instr); 2248 break; 2249 #endif 2250 default: 2251 Format(instr, "UNSUPPORTED"); 2252 UNSUPPORTED_RISCV(); 2253 } 2254 return instr->InstructionSize(); 2255 } 2256 2257 } // namespace disasm 2258 2259 #undef STRING_STARTS_WITH 2260 #undef VERIFY 2261 2262 //------------------------------------------------------------------------------ 2263 2264 namespace disasm { 2265 2266 const char* NameConverter::NameOfAddress(uint8_t* addr) const { 2267 SNPrintF(tmp_buffer_, "%p", addr); 2268 return tmp_buffer_.start(); 2269 } 2270 2271 const char* NameConverter::NameOfConstant(uint8_t* addr) const { 2272 return NameOfAddress(addr); 2273 } 2274 2275 const char* NameConverter::NameOfCPURegister(int reg) const { 2276 return Registers::GetName(reg); 2277 } 2278 2279 const char* NameConverter::NameOfByteCPURegister(int reg) const { 2280 MOZ_CRASH(" RISC-V does not have the concept of a byte register."); 2281 } 2282 2283 const char* NameConverter::NameOfXMMRegister(int reg) const { 2284 return FloatRegisters::GetName(reg); 2285 } 2286 2287 const char* NameConverter::NameInCode(uint8_t* addr) const { 2288 // The default name converter is called for unknown code. So we will not try 2289 // to access any memory. 2290 return ""; 2291 } 2292 2293 //------------------------------------------------------------------------------ 2294 2295 Disassembler::Disassembler(const NameConverter& converter) 2296 : converter_(converter) {} 2297 2298 Disassembler::~Disassembler() {} 2299 2300 int Disassembler::InstructionDecode(V8Vector<char> buffer, 2301 uint8_t* instruction) { 2302 Decoder d(converter_, buffer); 2303 return d.InstructionDecode(instruction); 2304 } 2305 2306 int Disassembler::ConstantPoolSizeAt(uint8_t* instruction) { 2307 return Decoder::ConstantPoolSizeAt(instruction); 2308 } 2309 2310 void Disassembler::Disassemble(FILE* f, uint8_t* begin, uint8_t* end) { 2311 NameConverter converter; 2312 Disassembler d(converter); 2313 for (uint8_t* pc = begin; pc < end;) { 2314 EmbeddedVector<char, ReasonableBufferSize> buffer; 2315 buffer[0] = '\0'; 2316 uint8_t* prev_pc = pc; 2317 pc += d.InstructionDecode(buffer, pc); 2318 fprintf(f, "%p %08x %s\n", prev_pc, 2319 *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); 2320 } 2321 } 2322 2323 } // namespace disasm 2324 } // namespace jit 2325 } // namespace js