Commit 8c5b3bed authored by Derek Tu's avatar Derek Tu Committed by V8 LUCI CQ

[riscv64] Add RISC-V C-Extension Logic to macro-assembler

Lets the macro-assembler compile RISC-V C-Extension instructions
when the corresponding flag is set during runtime.

Change-Id: I443d026653b9945ac7ccff41b0ca3f7db9b65775
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3039384Reviewed-by: 's avatarBrice Dobry <brice.dobry@futurewei.com>
Reviewed-by: 's avatarJi Qiu <qiuji@iscas.ac.cn>
Commit-Queue: Ji Qiu <qiuji@iscas.ac.cn>
Cr-Commit-Position: refs/heads/master@{#76128}
parent 892af664
......@@ -275,7 +275,7 @@ void Assembler::GetCode(Isolate* isolate, CodeDesc* desc,
void Assembler::Align(int m) {
DCHECK(m >= 4 && base::bits::IsPowerOfTwo(m));
while ((pc_offset() & (m - 1)) != 0) {
nop();
NOP();
}
}
......@@ -1129,9 +1129,9 @@ void Assembler::GenInstrCB(uint8_t funct3, Opcode opcode, Register rs1,
}
void Assembler::GenInstrCBA(uint8_t funct3, uint8_t funct2, Opcode opcode,
Register rs1, uint8_t uimm6) {
DCHECK(is_uint3(funct3) && is_uint2(funct2) && is_uint6(uimm6));
ShortInstr instr = opcode | ((uimm6 & 0x1f) << 2) | ((uimm6 & 0x20) << 7) |
Register rs1, int8_t imm6) {
DCHECK(is_uint3(funct3) && is_uint2(funct2) && is_int6(imm6));
ShortInstr instr = opcode | ((imm6 & 0x1f) << 2) | ((imm6 & 0x20) << 7) |
((rs1.code() & 0x7) << kRvcRs1sShift) |
(funct3 << kRvcFunct3Shift) | (funct2 << 10);
emit(instr);
......@@ -1267,7 +1267,10 @@ uint64_t Assembler::jump_address(Label* L) {
}
}
uint64_t imm = reinterpret_cast<uint64_t>(buffer_start_) + target_pos;
DCHECK_EQ(imm & 3, 0);
if (FLAG_riscv_c_extension)
DCHECK_EQ(imm & 1, 0);
else
DCHECK_EQ(imm & 3, 0);
return imm;
}
......@@ -1295,7 +1298,10 @@ uint64_t Assembler::branch_long_offset(Label* L) {
}
}
int64_t offset = target_pos - pc_offset();
DCHECK_EQ(offset & 3, 0);
if (FLAG_riscv_c_extension)
DCHECK_EQ(offset & 1, 0);
else
DCHECK_EQ(offset & 3, 0);
return static_cast<uint64_t>(offset);
}
......@@ -2213,7 +2219,8 @@ void Assembler::c_fsdsp(FPURegister rs2, uint16_t uimm9) {
void Assembler::c_lw(Register rd, Register rs1, uint16_t uimm7) {
DCHECK(((rd.code() & 0b11000) == 0b01000) &&
((rs1.code() & 0b11000) == 0b01000) && is_uint7(uimm7));
((rs1.code() & 0b11000) == 0b01000) && is_uint7(uimm7) &&
((uimm7 & 0x3) == 0));
uint8_t uimm5 =
((uimm7 & 0x4) >> 1) | ((uimm7 & 0x40) >> 6) | ((uimm7 & 0x38) >> 1);
GenInstrCL(0b010, C0, rd, rs1, uimm5);
......@@ -2221,14 +2228,16 @@ void Assembler::c_lw(Register rd, Register rs1, uint16_t uimm7) {
void Assembler::c_ld(Register rd, Register rs1, uint16_t uimm8) {
DCHECK(((rd.code() & 0b11000) == 0b01000) &&
((rs1.code() & 0b11000) == 0b01000) && is_uint8(uimm8));
((rs1.code() & 0b11000) == 0b01000) && is_uint8(uimm8) &&
((uimm8 & 0x7) == 0));
uint8_t uimm5 = ((uimm8 & 0x38) >> 1) | ((uimm8 & 0xc0) >> 6);
GenInstrCL(0b011, C0, rd, rs1, uimm5);
}
void Assembler::c_fld(FPURegister rd, Register rs1, uint16_t uimm8) {
DCHECK(((rd.code() & 0b11000) == 0b01000) &&
((rs1.code() & 0b11000) == 0b01000) && is_uint8(uimm8));
((rs1.code() & 0b11000) == 0b01000) && is_uint8(uimm8) &&
((uimm8 & 0x7) == 0));
uint8_t uimm5 = ((uimm8 & 0x38) >> 1) | ((uimm8 & 0xc0) >> 6);
GenInstrCL(0b001, C0, rd, rs1, uimm5);
}
......@@ -2237,7 +2246,8 @@ void Assembler::c_fld(FPURegister rd, Register rs1, uint16_t uimm8) {
void Assembler::c_sw(Register rs2, Register rs1, uint16_t uimm7) {
DCHECK(((rs2.code() & 0b11000) == 0b01000) &&
((rs1.code() & 0b11000) == 0b01000) && is_uint7(uimm7));
((rs1.code() & 0b11000) == 0b01000) && is_uint7(uimm7) &&
((uimm7 & 0x3) == 0));
uint8_t uimm5 =
((uimm7 & 0x4) >> 1) | ((uimm7 & 0x40) >> 6) | ((uimm7 & 0x38) >> 1);
GenInstrCS(0b110, C0, rs2, rs1, uimm5);
......@@ -2245,14 +2255,16 @@ void Assembler::c_sw(Register rs2, Register rs1, uint16_t uimm7) {
void Assembler::c_sd(Register rs2, Register rs1, uint16_t uimm8) {
DCHECK(((rs2.code() & 0b11000) == 0b01000) &&
((rs1.code() & 0b11000) == 0b01000) && is_uint8(uimm8));
((rs1.code() & 0b11000) == 0b01000) && is_uint8(uimm8) &&
((uimm8 & 0x7) == 0));
uint8_t uimm5 = ((uimm8 & 0x38) >> 1) | ((uimm8 & 0xc0) >> 6);
GenInstrCS(0b111, C0, rs2, rs1, uimm5);
}
void Assembler::c_fsd(FPURegister rs2, Register rs1, uint16_t uimm8) {
DCHECK(((rs2.code() & 0b11000) == 0b01000) &&
((rs1.code() & 0b11000) == 0b01000) && is_uint8(uimm8));
((rs1.code() & 0b11000) == 0b01000) && is_uint8(uimm8) &&
((uimm8 & 0x7) == 0));
uint8_t uimm5 = ((uimm8 & 0x38) >> 1) | ((uimm8 & 0xc0) >> 6);
GenInstrCS(0b101, C0, rs2, rs1, uimm5);
}
......@@ -2285,19 +2297,35 @@ void Assembler::c_beqz(Register rs1, int16_t imm9) {
GenInstrCB(0b110, C1, rs1, uimm8);
}
void Assembler::c_srli(Register rs1, uint8_t uimm6) {
DCHECK(((rs1.code() & 0b11000) == 0b01000) && is_uint6(uimm6));
GenInstrCBA(0b100, 0b00, C1, rs1, uimm6);
void Assembler::c_srli(Register rs1, int8_t imm6) {
DCHECK(((rs1.code() & 0b11000) == 0b01000) && is_int6(imm6));
GenInstrCBA(0b100, 0b00, C1, rs1, imm6);
}
void Assembler::c_srai(Register rs1, int8_t imm6) {
DCHECK(((rs1.code() & 0b11000) == 0b01000) && is_int6(imm6));
GenInstrCBA(0b100, 0b01, C1, rs1, imm6);
}
void Assembler::c_srai(Register rs1, uint8_t uimm6) {
DCHECK(((rs1.code() & 0b11000) == 0b01000) && is_uint6(uimm6));
GenInstrCBA(0b100, 0b01, C1, rs1, uimm6);
void Assembler::c_andi(Register rs1, int8_t imm6) {
DCHECK(((rs1.code() & 0b11000) == 0b01000) && is_int6(imm6));
GenInstrCBA(0b100, 0b10, C1, rs1, imm6);
}
// Definitions for using compressed vs non compressed
void Assembler::NOP() {
if (FLAG_riscv_c_extension)
c_nop();
else
nop();
}
void Assembler::c_andi(Register rs1, uint8_t uimm6) {
DCHECK(((rs1.code() & 0b11000) == 0b01000) && is_uint6(uimm6));
GenInstrCBA(0b100, 0b10, C1, rs1, uimm6);
void Assembler::EBREAK() {
if (FLAG_riscv_c_extension)
c_ebreak();
else
ebreak();
}
// Privileged
......
......@@ -660,9 +660,11 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
inline void c_bnez(Register rs1, Label* L) { c_bnez(rs1, branch_offset(L)); }
void c_beqz(Register rs1, int16_t imm9);
inline void c_beqz(Register rs1, Label* L) { c_beqz(rs1, branch_offset(L)); }
void c_srli(Register rs1, uint8_t uimm6);
void c_srai(Register rs1, uint8_t uimm6);
void c_andi(Register rs1, uint8_t uimm6);
void c_srli(Register rs1, int8_t imm6);
void c_srai(Register rs1, int8_t imm6);
void c_andi(Register rs1, int8_t imm6);
void NOP();
void EBREAK();
// Privileged
void uret();
......@@ -1144,7 +1146,7 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
void GenInstrCJ(uint8_t funct3, Opcode opcode, uint16_t uint11);
void GenInstrCB(uint8_t funct3, Opcode opcode, Register rs1, uint8_t uimm8);
void GenInstrCBA(uint8_t funct3, uint8_t funct2, Opcode opcode, Register rs1,
uint8_t uimm6);
int8_t imm6);
// ----- Instruction class templates match those in LLVM's RISCVInstrInfo.td
void GenInstrBranchCC_rri(uint8_t funct3, Register rs1, Register rs2,
......
......@@ -1033,8 +1033,6 @@ class InstructionGetters : public T {
DCHECK(this->IsShortInstruction());
// | funct3 | imm[5] | rs1/rd | imm[4:0] | opcode |
// 15 12 6 2
// | funct3 | nzimm[17] | rs1/rd | nzimm[16:12] | opcode |
// 15 12 6 2
uint32_t Bits = this->InstructionBits();
int32_t imm6 = ((Bits & 0x1000) >> 7) | ((Bits & 0x7c) >> 2);
return imm6 << 26 >> 26;
......
......@@ -407,6 +407,8 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
void instr(Register rs, Register rt) { instr(rs, Operand(rt)); } \
void instr(Register rs, int32_t j) { instr(rs, Operand(j)); }
#define DEFINE_INSTRUCTION3(instr) void instr(Register rd, int64_t imm);
DEFINE_INSTRUCTION(Add32)
DEFINE_INSTRUCTION(Add64)
DEFINE_INSTRUCTION(Div32)
......@@ -457,6 +459,10 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
DEFINE_INSTRUCTION(Ror)
DEFINE_INSTRUCTION(Dror)
DEFINE_INSTRUCTION3(Li)
DEFINE_INSTRUCTION2(Mv)
#undef DEFINE_INSTRUCTION
#undef DEFINE_INSTRUCTION2
#undef DEFINE_INSTRUCTION3
......
......@@ -1271,7 +1271,7 @@ T Simulator::ReadMem(int64_t addr, Instruction* instr) {
}
#ifndef V8_COMPRESS_POINTERS // TODO(RISCV): v8:11812
// check for natural alignment
if ((addr & (sizeof(T) - 1)) != 0) {
if (!FLAG_riscv_c_extension && ((addr & (sizeof(T) - 1)) != 0)) {
PrintF("Unaligned read at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr,
reinterpret_cast<intptr_t>(instr));
DieOrDebug();
......@@ -1293,7 +1293,7 @@ void Simulator::WriteMem(int64_t addr, T value, Instruction* instr) {
}
#ifndef V8_COMPRESS_POINTERS // TODO(RISCV): v8:11812
// check for natural alignment
if ((addr & (sizeof(T) - 1)) != 0) {
if (!FLAG_riscv_c_extension && ((addr & (sizeof(T) - 1)) != 0)) {
PrintF("Unaligned write at 0x%08" PRIx64 " , pc=0x%08" V8PRIxPTR "\n", addr,
reinterpret_cast<intptr_t>(instr));
DieOrDebug();
......@@ -3316,20 +3316,22 @@ void Simulator::DecodeCLType() {
switch (instr_.RvcOpcode()) {
case RO_C_LW: {
int64_t addr = rvc_rs1s() + rvc_imm5_w();
auto val = ReadMem<int32_t>(addr, instr_.instr());
int64_t val = ReadMem<int32_t>(addr, instr_.instr());
set_rvc_rs2s(sext_xlen(val), false);
TraceMemRd(addr, val, get_register(rvc_rs2s_reg()));
break;
}
case RO_C_LD: {
int64_t addr = rvc_rs1s() + rvc_imm5_d();
auto val = ReadMem<int64_t>(addr, instr_.instr());
int64_t val = ReadMem<int64_t>(addr, instr_.instr());
set_rvc_rs2s(sext_xlen(val), false);
TraceMemRd(addr, val, get_register(rvc_rs2s_reg()));
break;
}
case RO_C_FLD: {
int64_t addr = rvc_rs1s() + rvc_imm5_d();
auto val = ReadMem<double>(addr, instr_.instr());
set_rvc_drs2s(sext_xlen(val), false);
double val = ReadMem<double>(addr, instr_.instr());
set_rvc_drs2s(val, false);
break;
}
default:
......
......@@ -522,11 +522,15 @@ class Simulator : public SimulatorBase {
set_register(rvc_rs1s_reg(), value);
if (trace) TraceRegWr(get_register(rvc_rs1s_reg()), DWORD);
}
inline void set_rvc_rs2(int64_t value, bool trace = true) {
set_register(rvc_rs2_reg(), value);
if (trace) TraceRegWr(get_register(rvc_rs2_reg()), DWORD);
}
inline void set_rvc_drd(double value, bool trace = true) {
set_fpu_register_double(rvc_rd_reg(), value);
if (trace) TraceRegWr(get_fpu_register(rvc_rd_reg()), DOUBLE);
}
inline void set_rvc_rs2s(double value, bool trace = true) {
inline void set_rvc_rs2s(int64_t value, bool trace = true) {
set_register(rvc_rs2s_reg(), value);
if (trace) TraceRegWr(get_register(rvc_rs2s_reg()), DWORD);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment