// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "jit/riscv64/extension/base-riscv-i.h"
#include "jit/riscv64/constant/Constant-riscv64.h"
#include "jit/riscv64/Assembler-riscv64.h"
#include "jit/riscv64/Architecture-riscv64.h"
namespace js {
namespace jit {
void AssemblerRISCVI::lui(Register rd, int32_t imm20) {
GenInstrU(LUI, rd, imm20);
}
void AssemblerRISCVI::auipc(Register rd, int32_t imm20) {
GenInstrU(AUIPC, rd, imm20);
}
// Jumps
void AssemblerRISCVI::jal(Register rd, int32_t imm21) {
GenInstrJ(JAL, rd, imm21);
}
void AssemblerRISCVI::jalr(Register rd, Register rs1, int16_t imm12) {
GenInstrI(0 b000, JALR, rd, rs1, imm12);
}
// Branches
void AssemblerRISCVI::beq(Register rs1, Register rs2, int16_t imm13) {
GenInstrBranchCC_rri(0 b000, rs1, rs2, imm13);
}
void AssemblerRISCVI::bne(Register rs1, Register rs2, int16_t imm13) {
GenInstrBranchCC_rri(0 b001, rs1, rs2, imm13);
}
void AssemblerRISCVI::blt(Register rs1, Register rs2, int16_t imm13) {
GenInstrBranchCC_rri(0 b100, rs1, rs2, imm13);
}
void AssemblerRISCVI::bge(Register rs1, Register rs2, int16_t imm13) {
GenInstrBranchCC_rri(0 b101, rs1, rs2, imm13);
}
void AssemblerRISCVI::bltu(Register rs1, Register rs2, int16_t imm13) {
GenInstrBranchCC_rri(0 b110, rs1, rs2, imm13);
}
void AssemblerRISCVI::bgeu(Register rs1, Register rs2, int16_t imm13) {
GenInstrBranchCC_rri(0 b111, rs1, rs2, imm13);
}
// Loads
void AssemblerRISCVI::lb(Register rd, Register rs1, int16_t imm12) {
GenInstrLoad_ri(0 b000, rd, rs1, imm12);
}
void AssemblerRISCVI::lh(Register rd, Register rs1, int16_t imm12) {
GenInstrLoad_ri(0 b001, rd, rs1, imm12);
}
void AssemblerRISCVI::lw(Register rd, Register rs1, int16_t imm12) {
GenInstrLoad_ri(0 b010, rd, rs1, imm12);
}
void AssemblerRISCVI::lbu(Register rd, Register rs1, int16_t imm12) {
GenInstrLoad_ri(0 b100, rd, rs1, imm12);
}
void AssemblerRISCVI::lhu(Register rd, Register rs1, int16_t imm12) {
GenInstrLoad_ri(0 b101, rd, rs1, imm12);
}
// Stores
void AssemblerRISCVI::sb(Register source, Register base, int16_t imm12) {
GenInstrStore_rri(0 b000, base, source, imm12);
}
void AssemblerRISCVI::sh(Register source, Register base, int16_t imm12) {
GenInstrStore_rri(0 b001, base, source, imm12);
}
void AssemblerRISCVI::sw(Register source, Register base, int16_t imm12) {
GenInstrStore_rri(0 b010, base, source, imm12);
}
// Arithmetic with immediate
void AssemblerRISCVI::addi(Register rd, Register rs1, int16_t imm12) {
GenInstrALU_ri(0 b000, rd, rs1, imm12);
}
void AssemblerRISCVI::slti(Register rd, Register rs1, int16_t imm12) {
GenInstrALU_ri(0 b010, rd, rs1, imm12);
}
void AssemblerRISCVI::sltiu(Register rd, Register rs1, int16_t imm12) {
GenInstrALU_ri(0 b011, rd, rs1, imm12);
}
void AssemblerRISCVI::xori(Register rd, Register rs1, int16_t imm12) {
GenInstrALU_ri(0 b100, rd, rs1, imm12);
}
void AssemblerRISCVI::ori(Register rd, Register rs1, int16_t imm12) {
GenInstrALU_ri(0 b110, rd, rs1, imm12);
}
void AssemblerRISCVI::andi(Register rd, Register rs1, int16_t imm12) {
GenInstrALU_ri(0 b111, rd, rs1, imm12);
}
void AssemblerRISCVI::slli(Register rd, Register rs1, uint8_t shamt) {
GenInstrShift_ri(0 , 0 b001, rd, rs1, shamt & 0 x3f);
}
void AssemblerRISCVI::srli(Register rd, Register rs1, uint8_t shamt) {
GenInstrShift_ri(0 , 0 b101, rd, rs1, shamt & 0 x3f);
}
void AssemblerRISCVI::srai(Register rd, Register rs1, uint8_t shamt) {
GenInstrShift_ri(1 , 0 b101, rd, rs1, shamt & 0 x3f);
}
// Arithmetic
void AssemblerRISCVI::add(Register rd, Register rs1, Register rs2) {
GenInstrALU_rr(0 b0000000, 0 b000, rd, rs1, rs2);
}
void AssemblerRISCVI::sub(Register rd, Register rs1, Register rs2) {
GenInstrALU_rr(0 b0100000, 0 b000, rd, rs1, rs2);
}
void AssemblerRISCVI::sll(Register rd, Register rs1, Register rs2) {
GenInstrALU_rr(0 b0000000, 0 b001, rd, rs1, rs2);
}
void AssemblerRISCVI::slt(Register rd, Register rs1, Register rs2) {
GenInstrALU_rr(0 b0000000, 0 b010, rd, rs1, rs2);
}
void AssemblerRISCVI::sltu(Register rd, Register rs1, Register rs2) {
GenInstrALU_rr(0 b0000000, 0 b011, rd, rs1, rs2);
}
void AssemblerRISCVI::xor_(Register rd, Register rs1, Register rs2) {
GenInstrALU_rr(0 b0000000, 0 b100, rd, rs1, rs2);
}
void AssemblerRISCVI::srl(Register rd, Register rs1, Register rs2) {
GenInstrALU_rr(0 b0000000, 0 b101, rd, rs1, rs2);
}
void AssemblerRISCVI::sra(Register rd, Register rs1, Register rs2) {
GenInstrALU_rr(0 b0100000, 0 b101, rd, rs1, rs2);
}
void AssemblerRISCVI::or_(Register rd, Register rs1, Register rs2) {
GenInstrALU_rr(0 b0000000, 0 b110, rd, rs1, rs2);
}
void AssemblerRISCVI::and_(Register rd, Register rs1, Register rs2) {
GenInstrALU_rr(0 b0000000, 0 b111, rd, rs1, rs2);
}
// Memory fences
void AssemblerRISCVI::fence(uint8_t pred, uint8_t succ) {
MOZ_ASSERT(is_uint4(pred) && is_uint4(succ));
uint16_t imm12 = succ | (pred << 4 ) | (0 b0000 << 8 );
GenInstrI(0 b000, MISC_MEM, ToRegister(0 UL), ToRegister(0 UL), imm12);
}
void AssemblerRISCVI::fence_tso() {
uint16_t imm12 = (0 b0011) | (0 b0011 << 4 ) | (0 b1000 << 8 );
GenInstrI(0 b000, MISC_MEM, ToRegister(0 UL), ToRegister(0 UL), imm12);
}
// Environment call / break
void AssemblerRISCVI::ecall() {
GenInstrI(0 b000, SYSTEM, ToRegister(0 UL), ToRegister(0 UL), 0 );
}
void AssemblerRISCVI::ebreak() {
GenInstrI(0 b000, SYSTEM, ToRegister(0 UL), ToRegister(0 UL), 1 );
}
// This is a de facto standard (as set by GNU binutils) 32-bit unimplemented
// instruction (i.e., it should always trap, if your implementation has invalid
// instruction traps).
void AssemblerRISCVI::unimp() {
GenInstrI(0 b001, SYSTEM, ToRegister(0 ), ToRegister(0 ), 0 b110000000000);
}
bool AssemblerRISCVI::IsBranch(Instr instr) {
return (instr & kBaseOpcodeMask) == BRANCH;
}
bool AssemblerRISCVI::IsJump(Instr instr) {
int Op = instr & kBaseOpcodeMask;
return Op == JAL || Op == JALR;
}
bool AssemblerRISCVI::IsNop(Instr instr) { return instr == kNopByte; }
bool AssemblerRISCVI::IsJal(Instr instr) {
return (instr & kBaseOpcodeMask) == JAL;
}
bool AssemblerRISCVI::IsJalr(Instr instr) {
return (instr & kBaseOpcodeMask) == JALR;
}
bool AssemblerRISCVI::IsLui(Instr instr) {
return (instr & kBaseOpcodeMask) == LUI;
}
bool AssemblerRISCVI::IsAuipc(Instr instr) {
return (instr & kBaseOpcodeMask) == AUIPC;
}
bool AssemblerRISCVI::IsAddi(Instr instr) {
return (instr & (kBaseOpcodeMask | kFunct3Mask)) == RO_ADDI;
}
bool AssemblerRISCVI::IsOri(Instr instr) {
return (instr & (kBaseOpcodeMask | kFunct3Mask)) == RO_ORI;
}
bool AssemblerRISCVI::IsSlli(Instr instr) {
return (instr & (kBaseOpcodeMask | kFunct3Mask)) == RO_SLLI;
}
int AssemblerRISCVI::JumpOffset(Instr instr) {
int32_t imm21 = ((instr & 0 x7fe00000) >> 20 ) | ((instr & 0 x100000) >> 9 ) |
(instr & 0 xff000) | ((instr & 0 x80000000) >> 11 );
imm21 = imm21 << 11 >> 11 ;
return imm21;
}
int AssemblerRISCVI::JalrOffset(Instr instr) {
MOZ_ASSERT(IsJalr(instr));
int32_t imm12 = static_cast <int32_t>(instr & kImm12Mask) >> 20 ;
return imm12;
}
int AssemblerRISCVI::AuipcOffset(Instr instr) {
MOZ_ASSERT(IsAuipc(instr));
int32_t imm20 = static_cast <int32_t>(instr & kImm20Mask);
return imm20;
}
bool AssemblerRISCVI::IsLw(Instr instr) {
return (instr & (kBaseOpcodeMask | kFunct3Mask)) == RO_LW;
}
int AssemblerRISCVI::LoadOffset(Instr instr) {
#if JS_CODEGEN_RISCV64
MOZ_ASSERT(IsLd(instr));
#elif V8_TARGET_ARCH_RISCV32
MOZ_ASSERT(IsLw(instr));
#endif
int32_t imm12 = static_cast <int32_t>(instr & kImm12Mask) >> 20 ;
return imm12;
}
#ifdef JS_CODEGEN_RISCV64
bool AssemblerRISCVI::IsAddiw(Instr instr) {
return (instr & (kBaseOpcodeMask | kFunct3Mask)) == RO_ADDIW;
}
bool AssemblerRISCVI::IsLd(Instr instr) {
return (instr & (kBaseOpcodeMask | kFunct3Mask)) == RO_LD;
}
void AssemblerRISCVI::lwu(Register rd, Register rs1, int16_t imm12) {
GenInstrLoad_ri(0 b110, rd, rs1, imm12);
}
void AssemblerRISCVI::ld(Register rd, Register rs1, int16_t imm12) {
GenInstrLoad_ri(0 b011, rd, rs1, imm12);
}
void AssemblerRISCVI::sd(Register source, Register base, int16_t imm12) {
GenInstrStore_rri(0 b011, base, source, imm12);
}
void AssemblerRISCVI::addiw(Register rd, Register rs1, int16_t imm12) {
GenInstrI(0 b000, OP_IMM_32, rd, rs1, imm12);
}
void AssemblerRISCVI::slliw(Register rd, Register rs1, uint8_t shamt) {
GenInstrShiftW_ri(0 , 0 b001, rd, rs1, shamt & 0 x1f);
}
void AssemblerRISCVI::srliw(Register rd, Register rs1, uint8_t shamt) {
GenInstrShiftW_ri(0 , 0 b101, rd, rs1, shamt & 0 x1f);
}
void AssemblerRISCVI::sraiw(Register rd, Register rs1, uint8_t shamt) {
GenInstrShiftW_ri(1 , 0 b101, rd, rs1, shamt & 0 x1f);
}
void AssemblerRISCVI::addw(Register rd, Register rs1, Register rs2) {
GenInstrALUW_rr(0 b0000000, 0 b000, rd, rs1, rs2);
}
void AssemblerRISCVI::subw(Register rd, Register rs1, Register rs2) {
GenInstrALUW_rr(0 b0100000, 0 b000, rd, rs1, rs2);
}
void AssemblerRISCVI::sllw(Register rd, Register rs1, Register rs2) {
GenInstrALUW_rr(0 b0000000, 0 b001, rd, rs1, rs2);
}
void AssemblerRISCVI::srlw(Register rd, Register rs1, Register rs2) {
GenInstrALUW_rr(0 b0000000, 0 b101, rd, rs1, rs2);
}
void AssemblerRISCVI::sraw(Register rd, Register rs1, Register rs2) {
GenInstrALUW_rr(0 b0100000, 0 b101, rd, rs1, rs2);
}
#endif
int AssemblerRISCVI::BranchOffset(Instr instr) {
// | imm[12] | imm[10:5] | rs2 | rs1 | funct3 | imm[4:1|11] | opcode |
// 31 25 11 7
int32_t imm13 = ((instr & 0 xf00) >> 7 ) | ((instr & 0 x7e000000) >> 20 ) |
((instr & 0 x80) << 4 ) | ((instr & 0 x80000000) >> 19 );
imm13 = imm13 << 19 >> 19 ;
return imm13;
}
int AssemblerRISCVI::BrachlongOffset(Instr auipc, Instr instr_I) {
MOZ_ASSERT(reinterpret_cast <Instruction*>(&instr_I)->InstructionType() ==
InstructionBase::kIType);
MOZ_ASSERT(IsAuipc(auipc));
MOZ_ASSERT(((auipc & kRdFieldMask) >> kRdShift) ==
((instr_I & kRs1FieldMask) >> kRs1Shift));
int32_t imm_auipc = AuipcOffset(auipc);
int32_t imm12 = static_cast <int32_t>(instr_I & kImm12Mask) >> 20 ;
int32_t offset = imm12 + imm_auipc;
return offset;
}
} // namespace jit
} // namespace js
Messung V0.5 in Prozent C=95 H=100 G=97
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-06-04)
¤
*© Formatika GbR, Deutschland