Base-constant-riscv.h (35482B)
1 // Copyright 2022 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 #ifndef jit_riscv64_constant_Base_constant_riscv__h_ 5 #define jit_riscv64_constant_Base_constant_riscv__h_ 6 7 #include "mozilla/Assertions.h" 8 9 namespace js { 10 namespace jit { 11 12 // On RISC-V Simulator breakpoints can have different codes: 13 // - Breaks between 0 and kMaxWatchpointCode are treated as simple watchpoints, 14 // the simulator will run through them and print the registers. 15 // - Breaks between kMaxWatchpointCode and kMaxStopCode are treated as stop() 16 // instructions (see Assembler::stop()). 17 // - Breaks larger than kMaxStopCode are simple breaks, dropping you into the 18 // debugger. 19 const uint32_t kMaxTracepointCode = 63; 20 const uint32_t kMaxWatchpointCode = 31; 21 const uint32_t kMaxStopCode = 127; 22 const uint32_t kWasmTrapCode = 6; 23 static_assert(kMaxWatchpointCode < kMaxStopCode); 24 static_assert(kMaxTracepointCode < kMaxStopCode); 25 26 // Debug parameters. 27 // 28 // For example: 29 // 30 // __ Debug(TRACE_ENABLE | LOG_TRACE); 31 // starts tracing: set v8_flags.trace-sim is true. 32 // __ Debug(TRACE_ENABLE | LOG_REGS); 33 // PrintAllregs. 34 // __ Debug(TRACE_DISABLE | LOG_TRACE); 35 // stops tracing: set v8_flags.trace-sim is false. 36 const uint32_t kDebuggerTracingDirectivesMask = 0b111 << 3; 37 enum DebugParameters : uint32_t { 38 NO_PARAM = 1 << 5, 39 BREAK = 1 << 0, 40 LOG_TRACE = 1 << 1, 41 LOG_REGS = 1 << 2, 42 LOG_ALL = LOG_TRACE, 43 // Trace control. 44 TRACE_ENABLE = 1 << 3 | NO_PARAM, 45 TRACE_DISABLE = 1 << 4 | NO_PARAM, 46 }; 47 // On RISCV all instructions are 32 bits, except for RVC. 48 using Instr = int32_t; 49 using ShortInstr = int16_t; 50 typedef unsigned char byte; 51 // ----- Fields offset and length. 52 // RISCV constants 53 const int kBaseOpcodeShift = 0; 54 const int kBaseOpcodeBits = 7; 55 const int kFunct6Shift = 26; 56 const int kFunct6Bits = 6; 57 const int kFunct7Shift = 25; 58 const int kFunct7Bits = 7; 59 const int kFunct5Shift = 27; 60 const int kFunct5Bits = 5; 61 const int kFunct3Shift = 12; 62 const int kFunct3Bits = 3; 63 const int kFunct2Shift = 25; 64 const int kFunct2Bits = 2; 65 const int kRs1Shift = 15; 66 const int kRs1Bits = 5; 67 const int kVs1Shift = 15; 68 const int kVs1Bits = 5; 69 const int kVs2Shift = 20; 70 const int kVs2Bits = 5; 71 const int kVdShift = 7; 72 const int kVdBits = 5; 73 const int kRs2Shift = 20; 74 const int kRs2Bits = 5; 75 const int kRs3Shift = 27; 76 const int kRs3Bits = 5; 77 const int kRdShift = 7; 78 const int kRdBits = 5; 79 const int kRlShift = 25; 80 const int kAqShift = 26; 81 const int kImm12Shift = 20; 82 const int kImm12Bits = 12; 83 const int kImm11Shift = 2; 84 const int kImm11Bits = 11; 85 const int kShamtShift = 20; 86 const int kShamtBits = 5; 87 const uint32_t kShamtMask = (((1 << kShamtBits) - 1) << kShamtShift); 88 const int kShamtWShift = 20; 89 // FIXME: remove this once we have a proper way to handle the wide shift amount 90 const int kShamtWBits = 6; 91 const int kArithShiftShift = 30; 92 const int kImm20Shift = 12; 93 const int kImm20Bits = 20; 94 const int kCsrShift = 20; 95 const int kCsrBits = 12; 96 const int kMemOrderBits = 4; 97 const int kPredOrderShift = 24; 98 const int kSuccOrderShift = 20; 99 100 // for C extension 101 const int kRvcFunct4Shift = 12; 102 const int kRvcFunct4Bits = 4; 103 const int kRvcFunct3Shift = 13; 104 const int kRvcFunct3Bits = 3; 105 const int kRvcRs1Shift = 7; 106 const int kRvcRs1Bits = 5; 107 const int kRvcRs2Shift = 2; 108 const int kRvcRs2Bits = 5; 109 const int kRvcRdShift = 7; 110 const int kRvcRdBits = 5; 111 const int kRvcRs1sShift = 7; 112 const int kRvcRs1sBits = 3; 113 const int kRvcRs2sShift = 2; 114 const int kRvcRs2sBits = 3; 115 const int kRvcFunct2Shift = 5; 116 const int kRvcFunct2BShift = 10; 117 const int kRvcFunct2Bits = 2; 118 const int kRvcFunct6Shift = 10; 119 const int kRvcFunct6Bits = 6; 120 121 const uint32_t kRvcOpcodeMask = 122 0b11 | (((1 << kRvcFunct3Bits) - 1) << kRvcFunct3Shift); 123 const uint32_t kRvcFunct3Mask = 124 (((1 << kRvcFunct3Bits) - 1) << kRvcFunct3Shift); 125 const uint32_t kRvcFunct4Mask = 126 (((1 << kRvcFunct4Bits) - 1) << kRvcFunct4Shift); 127 const uint32_t kRvcFunct6Mask = 128 (((1 << kRvcFunct6Bits) - 1) << kRvcFunct6Shift); 129 const uint32_t kRvcFunct2Mask = 130 (((1 << kRvcFunct2Bits) - 1) << kRvcFunct2Shift); 131 const uint32_t kRvcFunct2BMask = 132 (((1 << kRvcFunct2Bits) - 1) << kRvcFunct2BShift); 133 const uint32_t kCRTypeMask = kRvcOpcodeMask | kRvcFunct4Mask; 134 const uint32_t kCSTypeMask = kRvcOpcodeMask | kRvcFunct6Mask; 135 const uint32_t kCATypeMask = kRvcOpcodeMask | kRvcFunct6Mask | kRvcFunct2Mask; 136 const uint32_t kRvcBImm8Mask = (((1 << 5) - 1) << 2) | (((1 << 3) - 1) << 10); 137 138 // RISCV Instruction bit masks 139 const uint32_t kBaseOpcodeMask = ((1 << kBaseOpcodeBits) - 1) 140 << kBaseOpcodeShift; 141 const uint32_t kFunct3Mask = ((1 << kFunct3Bits) - 1) << kFunct3Shift; 142 const uint32_t kFunct5Mask = ((1 << kFunct5Bits) - 1) << kFunct5Shift; 143 const uint32_t kFunct6Mask = ((1 << kFunct6Bits) - 1) << kFunct6Shift; 144 const uint32_t kFunct7Mask = ((1 << kFunct7Bits) - 1) << kFunct7Shift; 145 const uint32_t kFunct2Mask = 0b11 << kFunct7Shift; 146 const uint32_t kRTypeMask = kBaseOpcodeMask | kFunct3Mask | kFunct7Mask; 147 const uint32_t kRATypeMask = kBaseOpcodeMask | kFunct3Mask | kFunct5Mask; 148 const uint32_t kRFPTypeMask = kBaseOpcodeMask | kFunct7Mask; 149 const uint32_t kR4TypeMask = kBaseOpcodeMask | kFunct3Mask | kFunct2Mask; 150 const uint32_t kITypeMask = kBaseOpcodeMask | kFunct3Mask; 151 const uint32_t kSTypeMask = kBaseOpcodeMask | kFunct3Mask; 152 const uint32_t kBTypeMask = kBaseOpcodeMask | kFunct3Mask; 153 const uint32_t kUTypeMask = kBaseOpcodeMask; 154 const uint32_t kJTypeMask = kBaseOpcodeMask; 155 const uint32_t kRs1FieldMask = ((1 << kRs1Bits) - 1) << kRs1Shift; 156 const uint32_t kRs2FieldMask = ((1 << kRs2Bits) - 1) << kRs2Shift; 157 const uint32_t kRs3FieldMask = ((1 << kRs3Bits) - 1) << kRs3Shift; 158 const uint32_t kRdFieldMask = ((1 << kRdBits) - 1) << kRdShift; 159 const uint32_t kBImm12Mask = kFunct7Mask | kRdFieldMask; 160 const uint32_t kImm20Mask = ((1 << kImm20Bits) - 1) << kImm20Shift; 161 const uint32_t kImm12Mask = ((1 << kImm12Bits) - 1) << kImm12Shift; 162 const uint32_t kImm11Mask = ((1 << kImm11Bits) - 1) << kImm11Shift; 163 const uint32_t kImm31_12Mask = ((1 << 20) - 1) << 12; 164 const uint32_t kImm19_0Mask = ((1 << 20) - 1); 165 166 // for RVV extension 167 #define RVV_LMUL(V) \ 168 V(m1) \ 169 V(m2) \ 170 V(m4) \ 171 V(m8) \ 172 V(RESERVERD) \ 173 V(mf8) \ 174 V(mf4) \ 175 V(mf2) 176 177 enum Vlmul { 178 #define DEFINE_FLAG(name) name, 179 RVV_LMUL(DEFINE_FLAG) 180 #undef DEFINE_FLAG 181 }; 182 183 #define RVV_SEW(V) \ 184 V(E8) \ 185 V(E16) \ 186 V(E32) \ 187 V(E64) 188 189 #define DEFINE_FLAG(name) name, 190 enum VSew { 191 RVV_SEW(DEFINE_FLAG) 192 #undef DEFINE_FLAG 193 }; 194 195 constexpr int kRvvELEN = 64; 196 constexpr int kRvvVLEN = 128; 197 constexpr int kRvvSLEN = kRvvVLEN; 198 const int kRvvFunct6Shift = 26; 199 const int kRvvFunct6Bits = 6; 200 const uint32_t kRvvFunct6Mask = 201 (((1 << kRvvFunct6Bits) - 1) << kRvvFunct6Shift); 202 203 const int kRvvVmBits = 1; 204 const int kRvvVmShift = 25; 205 const uint32_t kRvvVmMask = (((1 << kRvvVmBits) - 1) << kRvvVmShift); 206 207 const int kRvvVs2Bits = 5; 208 const int kRvvVs2Shift = 20; 209 const uint32_t kRvvVs2Mask = (((1 << kRvvVs2Bits) - 1) << kRvvVs2Shift); 210 211 const int kRvvVs1Bits = 5; 212 const int kRvvVs1Shift = 15; 213 const uint32_t kRvvVs1Mask = (((1 << kRvvVs1Bits) - 1) << kRvvVs1Shift); 214 215 const int kRvvRs1Bits = kRvvVs1Bits; 216 const int kRvvRs1Shift = kRvvVs1Shift; 217 const uint32_t kRvvRs1Mask = (((1 << kRvvRs1Bits) - 1) << kRvvRs1Shift); 218 219 const int kRvvRs2Bits = 5; 220 const int kRvvRs2Shift = 20; 221 const uint32_t kRvvRs2Mask = (((1 << kRvvRs2Bits) - 1) << kRvvRs2Shift); 222 223 const int kRvvImm5Bits = kRvvVs1Bits; 224 const int kRvvImm5Shift = kRvvVs1Shift; 225 const uint32_t kRvvImm5Mask = (((1 << kRvvImm5Bits) - 1) << kRvvImm5Shift); 226 227 const int kRvvVdBits = 5; 228 const int kRvvVdShift = 7; 229 const uint32_t kRvvVdMask = (((1 << kRvvVdBits) - 1) << kRvvVdShift); 230 231 const int kRvvRdBits = kRvvVdBits; 232 const int kRvvRdShift = kRvvVdShift; 233 const uint32_t kRvvRdMask = (((1 << kRvvRdBits) - 1) << kRvvRdShift); 234 235 const int kRvvZimmBits = 11; 236 const int kRvvZimmShift = 20; 237 const uint32_t kRvvZimmMask = (((1 << kRvvZimmBits) - 1) << kRvvZimmShift); 238 239 const int kRvvUimmShift = kRvvRs1Shift; 240 const int kRvvUimmBits = kRvvRs1Bits; 241 const uint32_t kRvvUimmMask = (((1 << kRvvUimmBits) - 1) << kRvvUimmShift); 242 243 const int kRvvWidthBits = 3; 244 const int kRvvWidthShift = 12; 245 const uint32_t kRvvWidthMask = (((1 << kRvvWidthBits) - 1) << kRvvWidthShift); 246 247 const int kRvvMopBits = 2; 248 const int kRvvMopShift = 26; 249 const uint32_t kRvvMopMask = (((1 << kRvvMopBits) - 1) << kRvvMopShift); 250 251 const int kRvvMewBits = 1; 252 const int kRvvMewShift = 28; 253 const uint32_t kRvvMewMask = (((1 << kRvvMewBits) - 1) << kRvvMewShift); 254 255 const int kRvvNfBits = 3; 256 const int kRvvNfShift = 29; 257 const uint32_t kRvvNfMask = (((1 << kRvvNfBits) - 1) << kRvvNfShift); 258 259 const int kNopByte = 0x00000013; 260 261 enum BaseOpcode : uint32_t { 262 LOAD = 0b0000011, // I form: LB LH LW LBU LHU 263 LOAD_FP = 0b0000111, // I form: FLW FLD FLQ 264 MISC_MEM = 0b0001111, // I special form: FENCE FENCE.I 265 OP_IMM = 0b0010011, // I form: ADDI SLTI SLTIU XORI ORI ANDI 266 AUIPC = 0b0010111, // U form: AUIPC 267 OP_IMM_32 = 0b0011011, // I form: ADDIW SLLIW SRLIW SRAIW 268 // Note: SRLIW SRAIW I form first, then func3 101 special shift encoding 269 STORE = 0b0100011, // S form: SB SH SW SD 270 STORE_FP = 0b0100111, // S form: FSW FSD FSQ 271 AMO = 0b0101111, // R form: All A instructions 272 OP = 0b0110011, // R: ADD SUB SLL SLT SLTU XOR SRL SRA OR AND and 32M set 273 LUI = 0b0110111, // U form: LUI 274 OP_32 = 0b0111011, // R: ADDW SUBW SLLW SRLW SRAW MULW DIVW DIVUW REMW REMUW 275 MADD = 0b1000011, // R4 type: FMADD.S FMADD.D FMADD.Q 276 MSUB = 0b1000111, // R4 type: FMSUB.S FMSUB.D FMSUB.Q 277 NMSUB = 0b1001011, // R4 type: FNMSUB.S FNMSUB.D FNMSUB.Q 278 NMADD = 0b1001111, // R4 type: FNMADD.S FNMADD.D FNMADD.Q 279 OP_FP = 0b1010011, // R type: Q ext 280 BRANCH = 0b1100011, // B form: BEQ BNE, BLT, BGE, BLTU BGEU 281 JALR = 0b1100111, // I form: JALR 282 JAL = 0b1101111, // J form: JAL 283 SYSTEM = 0b1110011, // I form: ECALL EBREAK Zicsr ext 284 OP_V = 0b1010111, // V form: RVV 285 286 // C extension 287 C0 = 0b00, 288 C1 = 0b01, 289 C2 = 0b10, 290 FUNCT2_0 = 0b00, 291 FUNCT2_1 = 0b01, 292 FUNCT2_2 = 0b10, 293 FUNCT2_3 = 0b11, 294 }; 295 296 // ----- Emulated conditions. 297 // On RISC-V we use this enum to abstract from conditional branch instructions. 298 // The 'U' prefix is used to specify unsigned comparisons. 299 // Opposite conditions must be paired as odd/even numbers 300 // because 'NegateCondition' function flips LSB to negate condition. 301 enum RiscvCondition { // Any value < 0 is considered no_condition. 302 overflow = 0, 303 no_overflow = 1, 304 Uless = 2, 305 Ugreater_equal = 3, 306 Uless_equal = 4, 307 Ugreater = 5, 308 equal = 6, 309 not_equal = 7, // Unordered or Not Equal. 310 less = 8, 311 greater_equal = 9, 312 less_equal = 10, 313 greater = 11, 314 cc_always = 12, 315 316 // Aliases. 317 eq = equal, 318 ne = not_equal, 319 ge = greater_equal, 320 lt = less, 321 gt = greater, 322 le = less_equal, 323 al = cc_always, 324 ult = Uless, 325 uge = Ugreater_equal, 326 ule = Uless_equal, 327 ugt = Ugreater, 328 }; 329 330 // ----- Coprocessor conditions. 331 enum FPUCondition { 332 kNoFPUCondition = -1, 333 EQ = 0x02, // Ordered and Equal 334 NE = 0x03, // Unordered or Not Equal 335 LT = 0x04, // Ordered and Less Than 336 GE = 0x05, // Ordered and Greater Than or Equal 337 LE = 0x06, // Ordered and Less Than or Equal 338 GT = 0x07, // Ordered and Greater Than 339 }; 340 341 enum CheckForInexactConversion { 342 kCheckForInexactConversion, 343 kDontCheckForInexactConversion 344 }; 345 346 enum class MaxMinKind : int { kMin = 0, kMax = 1 }; 347 348 // ---------------------------------------------------------------------------- 349 // RISCV flags 350 351 enum ControlStatusReg { 352 csr_fflags = 0x001, // Floating-Point Accrued Exceptions (RW) 353 csr_frm = 0x002, // Floating-Point Dynamic Rounding Mode (RW) 354 csr_fcsr = 0x003, // Floating-Point Control and Status Register (RW) 355 csr_cycle = 0xc00, // Cycle counter for RDCYCLE instruction (RO) 356 csr_time = 0xc01, // Timer for RDTIME instruction (RO) 357 csr_instret = 0xc02, // Insns-retired counter for RDINSTRET instruction (RO) 358 csr_cycleh = 0xc80, // Upper 32 bits of cycle, RV32I only (RO) 359 csr_timeh = 0xc81, // Upper 32 bits of time, RV32I only (RO) 360 csr_instreth = 0xc82 // Upper 32 bits of instret, RV32I only (RO) 361 }; 362 363 enum FFlagsMask { 364 kInvalidOperation = 0b10000, // NV: Invalid 365 kDivideByZero = 0b1000, // DZ: Divide by Zero 366 kOverflow = 0b100, // OF: Overflow 367 kUnderflow = 0b10, // UF: Underflow 368 kInexact = 0b1 // NX: Inexact 369 }; 370 371 enum FPURoundingMode { 372 RNE = 0b000, // Round to Nearest, ties to Even 373 RTZ = 0b001, // Round towards Zero 374 RDN = 0b010, // Round Down (towards -infinity) 375 RUP = 0b011, // Round Up (towards +infinity) 376 RMM = 0b100, // Round to Nearest, tiest to Max Magnitude 377 DYN = 0b111 // In instruction's rm field, selects dynamic rounding mode; 378 // In Rounding Mode register, Invalid 379 }; 380 381 enum MemoryOdering { 382 PSI = 0b1000, // PI or SI 383 PSO = 0b0100, // PO or SO 384 PSR = 0b0010, // PR or SR 385 PSW = 0b0001, // PW or SW 386 PSIORW = PSI | PSO | PSR | PSW 387 }; 388 389 const int kFloat32ExponentBias = 127; 390 const int kFloat32MantissaBits = 23; 391 const int kFloat32ExponentBits = 8; 392 const int kFloat64ExponentBias = 1023; 393 const int kFloat64MantissaBits = 52; 394 const int kFloat64ExponentBits = 11; 395 396 enum FClassFlag { 397 kNegativeInfinity = 1, 398 kNegativeNormalNumber = 1 << 1, 399 kNegativeSubnormalNumber = 1 << 2, 400 kNegativeZero = 1 << 3, 401 kPositiveZero = 1 << 4, 402 kPositiveSubnormalNumber = 1 << 5, 403 kPositiveNormalNumber = 1 << 6, 404 kPositiveInfinity = 1 << 7, 405 kSignalingNaN = 1 << 8, 406 kQuietNaN = 1 << 9 407 }; 408 409 enum OffsetSize : uint32_t { 410 kOffset21 = 21, // RISCV jal 411 kOffset12 = 12, // RISCV imm12 412 kOffset20 = 20, // RISCV imm20 413 kOffset13 = 13, // RISCV branch 414 kOffset32 = 32, // RISCV auipc + instr_I 415 kOffset11 = 11, // RISCV C_J 416 kOffset9 = 9, // RISCV compressed branch 417 }; 418 419 // The classes of immediate branch ranges, in order of increasing range. 420 // Note that CondBranchType and CompareBranchType have the same range. 421 enum ImmBranchRangeType { 422 CondBranchRangeType, // 423 UncondBranchRangeType, // 424 UnknownBranchRangeType, 425 426 // Number of 'short-range' branch range types. 427 // We don't consider unconditional branches 'short-range'. 428 NumShortBranchRangeTypes = UnknownBranchRangeType 429 }; 430 431 inline ImmBranchRangeType OffsetSizeToImmBranchRangeType(OffsetSize bits) { 432 switch (bits) { 433 case kOffset21: 434 return UncondBranchRangeType; 435 case kOffset13: 436 return CondBranchRangeType; 437 default: 438 MOZ_CRASH("Unimplement"); 439 } 440 } 441 442 inline OffsetSize ImmBranchRangeTypeToOffsetSize(ImmBranchRangeType type) { 443 switch (type) { 444 case CondBranchRangeType: 445 return kOffset13; 446 case UncondBranchRangeType: 447 return kOffset21; 448 default: 449 MOZ_CRASH("Unimplement"); 450 } 451 } 452 453 int32_t ImmBranchMaxForwardOffset(OffsetSize bits); 454 455 inline int32_t ImmBranchMaxForwardOffset(ImmBranchRangeType type) { 456 return ImmBranchMaxForwardOffset(ImmBranchRangeTypeToOffsetSize(type)); 457 } 458 // ----------------------------------------------------------------------------- 459 // Specific instructions, constants, and masks. 460 // These constants are declared in assembler-riscv64.cc, as they use named 461 // registers and other constants. 462 463 // An Illegal instruction 464 const Instr kIllegalInstr = 0; // All other bits are 0s (i.e., ecall) 465 // An ECALL instruction, used for redirected real time call 466 const Instr rtCallRedirInstr = SYSTEM; // All other bits are 0s (i.e., ecall) 467 // An EBreak instruction, used for debugging and semi-hosting 468 const Instr kBreakInstr = SYSTEM | 1 << kImm12Shift; // ebreak 469 470 constexpr uint8_t kInstrSize = 4; 471 constexpr uint8_t kShortInstrSize = 2; 472 constexpr uint8_t kInstrSizeLog2 = 2; 473 474 class InstructionBase { 475 public: 476 enum { 477 // On RISC-V, PC cannot actually be directly accessed. We behave as if PC 478 // was always the value of the current instruction being executed. 479 kPCReadOffset = 0 480 }; 481 482 // Instruction type. 483 enum Type { 484 kRType, 485 kR4Type, // Special R4 for Q extension 486 kIType, 487 kSType, 488 kBType, 489 kUType, 490 kJType, 491 // C extension 492 kCRType, 493 kCIType, 494 kCSSType, 495 kCIWType, 496 kCLType, 497 kCSType, 498 kCAType, 499 kCBType, 500 kCJType, 501 // V extension 502 kVType, 503 kVLType, 504 kVSType, 505 kVAMOType, 506 kVIVVType, 507 kVFVVType, 508 kVMVVType, 509 kVIVIType, 510 kVIVXType, 511 kVFVFType, 512 kVMVXType, 513 kVSETType, 514 kUnsupported = -1 515 }; 516 517 inline bool IsIllegalInstruction() const { 518 uint16_t FirstHalfWord = *reinterpret_cast<const uint16_t*>(this); 519 return FirstHalfWord == 0; 520 } 521 522 bool IsShortInstruction() const; 523 524 inline uint8_t InstructionSize() const { 525 return (this->IsShortInstruction()) ? kShortInstrSize : kInstrSize; 526 } 527 528 // Get the raw instruction bits. 529 inline Instr InstructionBits() const { 530 if (this->IsShortInstruction()) { 531 return 0x0000FFFF & (*reinterpret_cast<const ShortInstr*>(this)); 532 } 533 return *reinterpret_cast<const Instr*>(this); 534 } 535 536 // Set the raw instruction bits to value. 537 inline void SetInstructionBits(Instr value) { 538 *reinterpret_cast<Instr*>(this) = value; 539 } 540 541 // Read one particular bit out of the instruction bits. 542 inline int Bit(int nr) const { return (InstructionBits() >> nr) & 1; } 543 544 // Read a bit field out of the instruction bits. 545 inline int Bits(int hi, int lo) const { 546 return (InstructionBits() >> lo) & ((2U << (hi - lo)) - 1); 547 } 548 549 // Accessors for the different named fields used in the RISC-V encoding. 550 inline BaseOpcode BaseOpcodeValue() const { 551 return static_cast<BaseOpcode>( 552 Bits(kBaseOpcodeShift + kBaseOpcodeBits - 1, kBaseOpcodeShift)); 553 } 554 555 // Return the fields at their original place in the instruction encoding. 556 inline BaseOpcode BaseOpcodeFieldRaw() const { 557 return static_cast<BaseOpcode>(InstructionBits() & kBaseOpcodeMask); 558 } 559 560 // Safe to call within R-type instructions 561 inline int Funct7FieldRaw() const { return InstructionBits() & kFunct7Mask; } 562 563 // Safe to call within R-type instructions 564 inline int Funct6FieldRaw() const { return InstructionBits() & kFunct6Mask; } 565 566 // Safe to call within R-, I-, S-, or B-type instructions 567 inline int Funct3FieldRaw() const { return InstructionBits() & kFunct3Mask; } 568 569 // Safe to call within R-, I-, S-, or B-type instructions 570 inline int Rs1FieldRawNoAssert() const { 571 return InstructionBits() & kRs1FieldMask; 572 } 573 574 // Safe to call within R-, S-, or B-type instructions 575 inline int Rs2FieldRawNoAssert() const { 576 return InstructionBits() & kRs2FieldMask; 577 } 578 579 // Safe to call within R4-type instructions 580 inline int Rs3FieldRawNoAssert() const { 581 return InstructionBits() & kRs3FieldMask; 582 } 583 584 inline int32_t ITypeBits() const { return InstructionBits() & kITypeMask; } 585 586 inline int32_t InstructionOpcodeType() const { 587 if (IsShortInstruction()) { 588 return InstructionBits() & kRvcOpcodeMask; 589 } else { 590 return InstructionBits() & kBaseOpcodeMask; 591 } 592 } 593 594 // Get the encoding type of the instruction. 595 Type InstructionType() const; 596 OffsetSize GetOffsetSize() const; 597 inline ImmBranchRangeType GetImmBranchRangeType() const { 598 return OffsetSizeToImmBranchRangeType(GetOffsetSize()); 599 } 600 601 protected: 602 InstructionBase() {} 603 }; 604 605 template <class T> 606 class InstructionGetters : public T { 607 public: 608 // Say if the instruction is a break or a trap. 609 bool IsTrap() const; 610 611 inline int BaseOpcode() const { 612 return this->InstructionBits() & kBaseOpcodeMask; 613 } 614 615 inline int RvcOpcode() const { 616 MOZ_ASSERT(this->IsShortInstruction()); 617 return this->InstructionBits() & kRvcOpcodeMask; 618 } 619 620 inline int Rs1Value() const { 621 MOZ_ASSERT(this->InstructionType() == InstructionBase::kRType || 622 this->InstructionType() == InstructionBase::kR4Type || 623 this->InstructionType() == InstructionBase::kIType || 624 this->InstructionType() == InstructionBase::kSType || 625 this->InstructionType() == InstructionBase::kBType || 626 this->InstructionType() == InstructionBase::kIType || 627 this->InstructionType() == InstructionBase::kVType); 628 return this->Bits(kRs1Shift + kRs1Bits - 1, kRs1Shift); 629 } 630 631 inline int Rs2Value() const { 632 MOZ_ASSERT(this->InstructionType() == InstructionBase::kRType || 633 this->InstructionType() == InstructionBase::kR4Type || 634 this->InstructionType() == InstructionBase::kSType || 635 this->InstructionType() == InstructionBase::kBType || 636 this->InstructionType() == InstructionBase::kIType || 637 this->InstructionType() == InstructionBase::kVType); 638 return this->Bits(kRs2Shift + kRs2Bits - 1, kRs2Shift); 639 } 640 641 inline int Rs3Value() const { 642 MOZ_ASSERT(this->InstructionType() == InstructionBase::kR4Type); 643 return this->Bits(kRs3Shift + kRs3Bits - 1, kRs3Shift); 644 } 645 646 inline int Vs1Value() const { 647 MOZ_ASSERT(this->InstructionType() == InstructionBase::kVType || 648 this->InstructionType() == InstructionBase::kIType || 649 this->InstructionType() == InstructionBase::kSType); 650 return this->Bits(kVs1Shift + kVs1Bits - 1, kVs1Shift); 651 } 652 653 inline int Vs2Value() const { 654 MOZ_ASSERT(this->InstructionType() == InstructionBase::kVType || 655 this->InstructionType() == InstructionBase::kIType || 656 this->InstructionType() == InstructionBase::kSType); 657 return this->Bits(kVs2Shift + kVs2Bits - 1, kVs2Shift); 658 } 659 660 inline int VdValue() const { 661 MOZ_ASSERT(this->InstructionType() == InstructionBase::kVType || 662 this->InstructionType() == InstructionBase::kIType || 663 this->InstructionType() == InstructionBase::kSType); 664 return this->Bits(kVdShift + kVdBits - 1, kVdShift); 665 } 666 667 inline int RdValue() const { 668 MOZ_ASSERT(this->InstructionType() == InstructionBase::kRType || 669 this->InstructionType() == InstructionBase::kR4Type || 670 this->InstructionType() == InstructionBase::kIType || 671 this->InstructionType() == InstructionBase::kSType || 672 this->InstructionType() == InstructionBase::kUType || 673 this->InstructionType() == InstructionBase::kJType || 674 this->InstructionType() == InstructionBase::kVType); 675 return this->Bits(kRdShift + kRdBits - 1, kRdShift); 676 } 677 678 inline int RvcRs1Value() const { return this->RvcRdValue(); } 679 680 int RvcRdValue() const; 681 682 int RvcRs2Value() const; 683 684 int RvcRs1sValue() const; 685 686 int RvcRs2sValue() const; 687 688 int Funct7Value() const; 689 690 inline int Funct3Value() const { 691 MOZ_ASSERT(this->InstructionType() == InstructionBase::kRType || 692 this->InstructionType() == InstructionBase::kIType || 693 this->InstructionType() == InstructionBase::kSType || 694 this->InstructionType() == InstructionBase::kBType); 695 return this->Bits(kFunct3Shift + kFunct3Bits - 1, kFunct3Shift); 696 } 697 698 inline int Funct5Value() const { 699 MOZ_ASSERT(this->InstructionType() == InstructionBase::kRType && 700 this->BaseOpcode() == OP_FP); 701 return this->Bits(kFunct5Shift + kFunct5Bits - 1, kFunct5Shift); 702 } 703 704 int RvcFunct6Value() const; 705 706 int RvcFunct4Value() const; 707 708 int RvcFunct3Value() const; 709 710 int RvcFunct2Value() const; 711 712 int RvcFunct2BValue() const; 713 714 inline int CsrValue() const { 715 MOZ_ASSERT(this->InstructionType() == InstructionBase::kIType && 716 this->BaseOpcode() == SYSTEM); 717 return (this->Bits(kCsrShift + kCsrBits - 1, kCsrShift)); 718 } 719 720 inline int RoundMode() const { 721 MOZ_ASSERT((this->InstructionType() == InstructionBase::kRType || 722 this->InstructionType() == InstructionBase::kR4Type) && 723 this->BaseOpcode() == OP_FP); 724 return this->Bits(kFunct3Shift + kFunct3Bits - 1, kFunct3Shift); 725 } 726 727 inline int MemoryOrder(bool is_pred) const { 728 MOZ_ASSERT((this->InstructionType() == InstructionBase::kIType && 729 this->BaseOpcode() == MISC_MEM)); 730 if (is_pred) { 731 return this->Bits(kPredOrderShift + kMemOrderBits - 1, kPredOrderShift); 732 } else { 733 return this->Bits(kSuccOrderShift + kMemOrderBits - 1, kSuccOrderShift); 734 } 735 } 736 737 inline int Imm12Value() const { 738 MOZ_ASSERT(this->InstructionType() == InstructionBase::kIType); 739 int Value = this->Bits(kImm12Shift + kImm12Bits - 1, kImm12Shift); 740 return Value << 20 >> 20; 741 } 742 743 inline int32_t Imm12SExtValue() const { 744 int32_t Value = this->Imm12Value() << 20 >> 20; 745 return Value; 746 } 747 748 inline int BranchOffset() const { 749 MOZ_ASSERT(this->InstructionType() == InstructionBase::kBType); 750 // | imm[12|10:5] | rs2 | rs1 | funct3 | imm[4:1|11] | opcode | 751 // 31 25 11 7 752 uint32_t Bits = this->InstructionBits(); 753 int16_t imm13 = ((Bits & 0xf00) >> 7) | ((Bits & 0x7e000000) >> 20) | 754 ((Bits & 0x80) << 4) | ((Bits & 0x80000000) >> 19); 755 return imm13 << 19 >> 19; 756 } 757 758 inline int StoreOffset() const { 759 MOZ_ASSERT(this->InstructionType() == InstructionBase::kSType); 760 // | imm[11:5] | rs2 | rs1 | funct3 | imm[4:0] | opcode | 761 // 31 25 11 7 762 uint32_t Bits = this->InstructionBits(); 763 int16_t imm12 = ((Bits & 0xf80) >> 7) | ((Bits & 0xfe000000) >> 20); 764 return imm12 << 20 >> 20; 765 } 766 767 inline int Imm20UValue() const { 768 MOZ_ASSERT(this->InstructionType() == InstructionBase::kUType); 769 // | imm[31:12] | rd | opcode | 770 // 31 12 771 int32_t Bits = this->InstructionBits(); 772 return Bits >> 12; 773 } 774 775 inline int Imm20JValue() const { 776 MOZ_ASSERT(this->InstructionType() == InstructionBase::kJType); 777 // | imm[20|10:1|11|19:12] | rd | opcode | 778 // 31 12 779 uint32_t Bits = this->InstructionBits(); 780 int32_t imm20 = ((Bits & 0x7fe00000) >> 20) | ((Bits & 0x100000) >> 9) | 781 (Bits & 0xff000) | ((Bits & 0x80000000) >> 11); 782 return imm20 << 11 >> 11; 783 } 784 785 inline bool IsArithShift() const { 786 // Valid only for right shift operations 787 MOZ_ASSERT((this->BaseOpcode() == OP || this->BaseOpcode() == OP_32 || 788 this->BaseOpcode() == OP_IMM || 789 this->BaseOpcode() == OP_IMM_32) && 790 this->Funct3Value() == 0b101); 791 return this->InstructionBits() & 0x40000000; 792 } 793 794 inline int Shamt() const { 795 // Valid only for shift instructions (SLLI, SRLI, SRAI) 796 MOZ_ASSERT(((this->InstructionBits() & kBaseOpcodeMask) == OP_IMM || 797 (this->InstructionBits() & kBaseOpcodeMask) == OP_IMM_32) && 798 (this->Funct3Value() == 0b001 || this->Funct3Value() == 0b101)); 799 // | 0A0000 | shamt | rs1 | funct3 | rd | opcode | 800 // 31 25 20 801 return this->Bits(kImm12Shift + 5, kImm12Shift); 802 } 803 804 inline int Shamt32() const { 805 // Valid only for shift instructions (SLLIW, SRLIW, SRAIW) 806 MOZ_ASSERT((this->InstructionBits() & kBaseOpcodeMask) == OP_IMM_32 && 807 (this->Funct3Value() == 0b001 || this->Funct3Value() == 0b101)); 808 // | 0A00000 | shamt | rs1 | funct3 | rd | opcode | 809 // 31 24 20 810 return this->Bits(kImm12Shift + 4, kImm12Shift); 811 } 812 813 inline int RvcImm6Value() const { 814 MOZ_ASSERT(this->IsShortInstruction()); 815 // | funct3 | imm[5] | rs1/rd | imm[4:0] | opcode | 816 // 15 12 6 2 817 uint32_t Bits = this->InstructionBits(); 818 int32_t imm6 = ((Bits & 0x1000) >> 7) | ((Bits & 0x7c) >> 2); 819 return imm6 << 26 >> 26; 820 } 821 822 inline int RvcImm6Addi16spValue() const { 823 MOZ_ASSERT(this->IsShortInstruction()); 824 // | funct3 | nzimm[9] | 2 | nzimm[4|6|8:7|5] | opcode | 825 // 15 12 6 2 826 uint32_t Bits = this->InstructionBits(); 827 int32_t imm10 = ((Bits & 0x1000) >> 3) | ((Bits & 0x40) >> 2) | 828 ((Bits & 0x20) << 1) | ((Bits & 0x18) << 4) | 829 ((Bits & 0x4) << 3); 830 MOZ_ASSERT(imm10 != 0); 831 return imm10 << 22 >> 22; 832 } 833 834 inline int RvcImm8Addi4spnValue() const { 835 MOZ_ASSERT(this->IsShortInstruction()); 836 // | funct3 | nzimm[11] | rd' | opcode | 837 // 15 13 5 2 838 uint32_t Bits = this->InstructionBits(); 839 int32_t uimm10 = ((Bits & 0x20) >> 2) | ((Bits & 0x40) >> 4) | 840 ((Bits & 0x780) >> 1) | ((Bits & 0x1800) >> 7); 841 MOZ_ASSERT(uimm10 != 0); 842 return uimm10; 843 } 844 845 inline int RvcShamt6() const { 846 MOZ_ASSERT(this->IsShortInstruction()); 847 // | funct3 | nzuimm[5] | rs1/rd | nzuimm[4:0] | opcode | 848 // 15 12 6 2 849 int32_t imm6 = this->RvcImm6Value(); 850 return imm6 & 0x3f; 851 } 852 853 inline int RvcImm6LwspValue() const { 854 MOZ_ASSERT(this->IsShortInstruction()); 855 // | funct3 | uimm[5] | rs1 | uimm[4:2|7:6] | opcode | 856 // 15 12 6 2 857 uint32_t Bits = this->InstructionBits(); 858 int32_t imm8 = 859 ((Bits & 0x1000) >> 7) | ((Bits & 0x70) >> 2) | ((Bits & 0xc) << 4); 860 return imm8; 861 } 862 863 inline int RvcImm6LdspValue() const { 864 MOZ_ASSERT(this->IsShortInstruction()); 865 // | funct3 | uimm[5] | rs1 | uimm[4:3|8:6] | opcode | 866 // 15 12 6 2 867 uint32_t Bits = this->InstructionBits(); 868 int32_t imm9 = 869 ((Bits & 0x1000) >> 7) | ((Bits & 0x60) >> 2) | ((Bits & 0x1c) << 4); 870 return imm9; 871 } 872 873 inline int RvcImm6SwspValue() const { 874 MOZ_ASSERT(this->IsShortInstruction()); 875 // | funct3 | uimm[5:2|7:6] | rs2 | opcode | 876 // 15 12 7 877 uint32_t Bits = this->InstructionBits(); 878 int32_t imm8 = ((Bits & 0x1e00) >> 7) | ((Bits & 0x180) >> 1); 879 return imm8; 880 } 881 882 inline int RvcImm6SdspValue() const { 883 MOZ_ASSERT(this->IsShortInstruction()); 884 // | funct3 | uimm[5:3|8:6] | rs2 | opcode | 885 // 15 12 7 886 uint32_t Bits = this->InstructionBits(); 887 int32_t imm9 = ((Bits & 0x1c00) >> 7) | ((Bits & 0x380) >> 1); 888 return imm9; 889 } 890 891 inline int RvcImm5WValue() const { 892 MOZ_ASSERT(this->IsShortInstruction()); 893 // | funct3 | imm[5:3] | rs1 | imm[2|6] | rd | opcode | 894 // 15 12 10 6 4 2 895 uint32_t Bits = this->InstructionBits(); 896 int32_t imm7 = 897 ((Bits & 0x1c00) >> 7) | ((Bits & 0x40) >> 4) | ((Bits & 0x20) << 1); 898 return imm7; 899 } 900 901 inline int RvcImm5DValue() const { 902 MOZ_ASSERT(this->IsShortInstruction()); 903 // | funct3 | imm[5:3] | rs1 | imm[7:6] | rd | opcode | 904 // 15 12 10 6 4 2 905 uint32_t Bits = this->InstructionBits(); 906 int32_t imm8 = ((Bits & 0x1c00) >> 7) | ((Bits & 0x60) << 1); 907 return imm8; 908 } 909 910 inline int RvcImm11CJValue() const { 911 MOZ_ASSERT(this->IsShortInstruction()); 912 // | funct3 | [11|4|9:8|10|6|7|3:1|5] | opcode | 913 // 15 12 2 914 uint32_t Bits = this->InstructionBits(); 915 int32_t imm12 = ((Bits & 0x4) << 3) | ((Bits & 0x38) >> 2) | 916 ((Bits & 0x40) << 1) | ((Bits & 0x80) >> 1) | 917 ((Bits & 0x100) << 2) | ((Bits & 0x600) >> 1) | 918 ((Bits & 0x800) >> 7) | ((Bits & 0x1000) >> 1); 919 return imm12 << 20 >> 20; 920 } 921 922 inline int RvcImm8BValue() const { 923 MOZ_ASSERT(this->IsShortInstruction()); 924 // | funct3 | imm[8|4:3] | rs1` | imm[7:6|2:1|5] | opcode | 925 // 15 12 10 7 2 926 uint32_t Bits = this->InstructionBits(); 927 int32_t imm9 = ((Bits & 0x4) << 3) | ((Bits & 0x18) >> 2) | 928 ((Bits & 0x60) << 1) | ((Bits & 0xc00) >> 7) | 929 ((Bits & 0x1000) >> 4); 930 return imm9 << 23 >> 23; 931 } 932 933 inline int vl_vs_width() { 934 int width = 0; 935 if ((this->InstructionBits() & kBaseOpcodeMask) != LOAD_FP && 936 (this->InstructionBits() & kBaseOpcodeMask) != STORE_FP) 937 return -1; 938 switch (this->InstructionBits() & (kRvvWidthMask | kRvvMewMask)) { 939 case 0x0: 940 width = 8; 941 break; 942 case 0x00005000: 943 width = 16; 944 break; 945 case 0x00006000: 946 width = 32; 947 break; 948 case 0x00007000: 949 width = 64; 950 break; 951 case 0x10000000: 952 width = 128; 953 break; 954 case 0x10005000: 955 width = 256; 956 break; 957 case 0x10006000: 958 width = 512; 959 break; 960 case 0x10007000: 961 width = 1024; 962 break; 963 default: 964 width = -1; 965 break; 966 } 967 return width; 968 } 969 970 uint32_t Rvvzimm() const; 971 972 uint32_t Rvvuimm() const; 973 974 inline uint32_t RvvVsew() const { 975 uint32_t zimm = this->Rvvzimm(); 976 uint32_t vsew = (zimm >> 3) & 0x7; 977 return vsew; 978 } 979 980 inline uint32_t RvvVlmul() const { 981 uint32_t zimm = this->Rvvzimm(); 982 uint32_t vlmul = zimm & 0x7; 983 return vlmul; 984 } 985 986 inline uint8_t RvvVM() const { 987 MOZ_ASSERT(this->InstructionType() == InstructionBase::kVType || 988 this->InstructionType() == InstructionBase::kIType || 989 this->InstructionType() == InstructionBase::kSType); 990 return this->Bits(kRvvVmShift + kRvvVmBits - 1, kRvvVmShift); 991 } 992 993 inline const char* RvvSEW() const { 994 uint32_t vsew = this->RvvVsew(); 995 switch (vsew) { 996 #define CAST_VSEW(name) \ 997 case name: \ 998 return #name; 999 RVV_SEW(CAST_VSEW) 1000 default: 1001 return "unknown"; 1002 #undef CAST_VSEW 1003 } 1004 } 1005 1006 inline const char* RvvLMUL() const { 1007 uint32_t vlmul = this->RvvVlmul(); 1008 switch (vlmul) { 1009 #define CAST_VLMUL(name) \ 1010 case name: \ 1011 return #name; 1012 RVV_LMUL(CAST_VLMUL) 1013 default: 1014 return "unknown"; 1015 #undef CAST_VLMUL 1016 } 1017 } 1018 1019 #define sext(x, len) (((int32_t)(x) << (32 - len)) >> (32 - len)) 1020 #define zext(x, len) (((uint32_t)(x) << (32 - len)) >> (32 - len)) 1021 1022 inline int32_t RvvSimm5() const { 1023 MOZ_ASSERT(this->InstructionType() == InstructionBase::kVType); 1024 return sext(this->Bits(kRvvImm5Shift + kRvvImm5Bits - 1, kRvvImm5Shift), 1025 kRvvImm5Bits); 1026 } 1027 1028 inline uint32_t RvvUimm5() const { 1029 MOZ_ASSERT(this->InstructionType() == InstructionBase::kVType); 1030 uint32_t imm = this->Bits(kRvvImm5Shift + kRvvImm5Bits - 1, kRvvImm5Shift); 1031 return zext(imm, kRvvImm5Bits); 1032 } 1033 #undef sext 1034 #undef zext 1035 inline bool AqValue() const { return this->Bits(kAqShift, kAqShift); } 1036 1037 inline bool RlValue() const { return this->Bits(kRlShift, kRlShift); } 1038 }; 1039 1040 class Instruction : public InstructionGetters<InstructionBase> { 1041 public: 1042 // Instructions are read of out a code stream. The only way to get a 1043 // reference to an instruction is to convert a pointer. There is no way 1044 // to allocate or create instances of class Instruction. 1045 // Use the At(pc) function to create references to Instruction. 1046 static Instruction* At(byte* pc) { 1047 return reinterpret_cast<Instruction*>(pc); 1048 } 1049 1050 private: 1051 // We need to prevent the creation of instances of class Instruction. 1052 Instruction() = delete; 1053 Instruction(const Instruction&) = delete; 1054 Instruction& operator=(const Instruction&) = delete; 1055 }; 1056 1057 // ----------------------------------------------------------------------------- 1058 // Instructions. 1059 1060 template <class P> 1061 bool InstructionGetters<P>::IsTrap() const { 1062 return (this->InstructionBits() == kBreakInstr); 1063 } 1064 1065 } // namespace jit 1066 } // namespace js 1067 #endif // jit_riscv64_constant_Base_constant_riscv__h_