Skip to content

Commit

Permalink
Add Zicond.
Browse files Browse the repository at this point in the history
  • Loading branch information
rmacnak committed Nov 2, 2024
1 parent d1590bb commit 1ae50ac
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 0 deletions.
10 changes: 10 additions & 0 deletions vm/assembler_riscv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1539,6 +1539,16 @@ void Assembler::bseti(Register rd, Register rs1, intx_t shamt) {
EmitRType(BSET, shamt, rs1, F3_BSET, rd, OPIMM);
}

void Assembler::czeroeqz(Register rd, Register rs1, Register rs2) {
ASSERT(Supports(RV_Zicond));
EmitRType(CZERO, rs2, rs1, CZEROEQZ, rd, OP);
}

void Assembler::czeronez(Register rd, Register rs1, Register rs2) {
ASSERT(Supports(RV_Zicond));
EmitRType(CZERO, rs2, rs1, CZERONEZ, rd, OP);
}

void Assembler::c_lwsp(Register rd, Address addr) {
ASSERT(rd != ZERO);
ASSERT(addr.base() == SP);
Expand Down
6 changes: 6 additions & 0 deletions vm/assembler_riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,12 @@ class Assembler {
void bset(Register rd, Register rs1, Register rs2);
void bseti(Register rd, Register rs1, intx_t shamt);

// ==== Zicond: Integer conditional operations ====
// rd := rs2 == 0 ? 0 : rs1
void czeroeqz(Register rd, Register rs1, Register rs2);
// rd := rs2 != 0 ? 0 : rs1
void czeronez(Register rd, Register rs1, Register rs2);

private:
// ==== RV32/64C ====
void c_lwsp(Register rd, Address addr);
Expand Down
6 changes: 6 additions & 0 deletions vm/constants_riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,9 @@ enum Funct3 {
BEXT = 0b101,
F3_BINV = 0b001,
F3_BSET = 0b001,

CZEROEQZ = 0b101,
CZERONEZ = 0b111,
};

enum Funct7 {
Expand Down Expand Up @@ -412,6 +415,8 @@ enum Funct7 {
BCLRBEXT = 0b0100100,
BINV = 0b0110100,
BSET = 0b0010100,

CZERO = 0b0000111,
};

enum Funct5 {
Expand Down Expand Up @@ -1056,6 +1061,7 @@ static constexpr Extension RV_Zbs(8); // Single-bit instructions
static constexpr ExtensionSet RV_B = RV_Zba | RV_Zbb | RV_Zbs;
static constexpr ExtensionSet RV_GCB = RV_GC | RV_B;
static constexpr Extension RV_Zbc(9); // Carry-less multiplication
static constexpr Extension RV_Zicond(10); // Integer conditional operations

} // namespace psoup

Expand Down
16 changes: 16 additions & 0 deletions vm/disassembler_riscv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,9 @@ void Disassembler::DisassembleOP(Instruction instr) {
Print("zext.h 'rd, 'rs1", instr, RV_Zbb);
break;
#endif
case CZERO:
DisassembleOP_CZERO(instr);
break;
default:
UnknownInstruction(instr);
}
Expand Down Expand Up @@ -842,6 +845,19 @@ void Disassembler::DisassembleOP_BCLRBEXT(Instruction instr) {
}
}

void Disassembler::DisassembleOP_CZERO(Instruction instr) {
switch (instr.funct3()) {
case CZEROEQZ:
Print("czero.eqz 'rd, 'rs1, 'rs2", instr, RV_Zicond);
break;
case CZERONEZ:
Print("czero.nez 'rd, 'rs1, 'rs2", instr, RV_Zicond);
break;
default:
UnknownInstruction(instr);
}
}

void Disassembler::DisassembleOP32(Instruction instr) {
switch (instr.funct7()) {
case 0:
Expand Down
1 change: 1 addition & 0 deletions vm/disassembler_riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class Disassembler {
void DisassembleOP_MINMAXCLMUL(Instruction instr);
void DisassembleOP_ROTATE(Instruction instr);
void DisassembleOP_BCLRBEXT(Instruction instr);
void DisassembleOP_CZERO(Instruction instr);
void DisassembleOP32(Instruction instr);
void DisassembleOP32_0(Instruction instr);
void DisassembleOP32_SUB(Instruction instr);
Expand Down
19 changes: 19 additions & 0 deletions vm/simulator_riscv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,9 @@ void Simulator::InterpretOP(Instruction instr) {
pc_ += instr.length();
break;
#endif
case CZERO:
InterpretOP_CZERO(instr);
break;
default:
IllegalInstruction(instr);
}
Expand Down Expand Up @@ -1303,6 +1306,22 @@ void Simulator::InterpretOP_BCLRBEXT(Instruction instr) {
pc_ += instr.length();
}

void Simulator::InterpretOP_CZERO(Instruction instr) {
switch (instr.funct3()) {
case CZEROEQZ:
set_xreg(instr.rd(), get_xreg(instr.rs2()) == 0 ? 0
: get_xreg(instr.rs1()));
break;
case CZERONEZ:
set_xreg(instr.rd(), get_xreg(instr.rs2()) != 0 ? 0
: get_xreg(instr.rs1()));
break;
default:
IllegalInstruction(instr);
}
pc_ += instr.length();
}

void Simulator::InterpretOP32(Instruction instr) {
switch (instr.funct7()) {
#if XLEN >= 64
Expand Down
1 change: 1 addition & 0 deletions vm/simulator_riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ class Simulator {
void InterpretOP_MINMAXCLMUL(Instruction instr);
void InterpretOP_ROTATE(Instruction instr);
void InterpretOP_BCLRBEXT(Instruction instr);
void InterpretOP_CZERO(Instruction instr);
void InterpretOP32(Instruction instr);
void InterpretOP32_0(Instruction instr);
void InterpretOP32_SUB(Instruction instr);
Expand Down
44 changes: 44 additions & 0 deletions vm/test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9310,6 +9310,50 @@ UNIT_TEST(BitSetImmediate2) {
EXPECT_EQ(-1, simulator.Call(buffer, -1));
}

UNIT_TEST(ConditionalZeroIfEqualsZero) {
Assembler assembler(RV_GC | RV_Zicond);
__ czeroeqz(A0, A0, A1);
__ ret();

void* buffer = assembler.buffer();
size_t size = assembler.size();

Disassembler disassembler(RV_GC | RV_Zicond);
char* disassembly = disassembler.Disassemble(buffer, size);
EXPECT_STREQ(
" 0eb55533 czero.eqz a0, a0, a1\n"
" 8082 ret\n",
disassembly);
free(disassembly);

Simulator simulator;
EXPECT_EQ(0, simulator.Call(buffer, 42, 0));
EXPECT_EQ(42, simulator.Call(buffer, 42, 1));
EXPECT_EQ(42, simulator.Call(buffer, 42, -1));
}

UNIT_TEST(ConditionalZeroIfNotEqualsZero) {
Assembler assembler(RV_GC | RV_Zicond);
__ czeronez(A0, A0, A1);
__ ret();

void* buffer = assembler.buffer();
size_t size = assembler.size();

Disassembler disassembler(RV_GC | RV_Zicond);
char* disassembly = disassembler.Disassemble(buffer, size);
EXPECT_STREQ(
" 0eb57533 czero.nez a0, a0, a1\n"
" 8082 ret\n",
disassembly);
free(disassembly);

Simulator simulator;
EXPECT_EQ(42, simulator.Call(buffer, 42, 0));
EXPECT_EQ(0, simulator.Call(buffer, 42, 1));
EXPECT_EQ(0, simulator.Call(buffer, 42, -1));
}

UNIT_TEST(MacroLoadImmediate_LoadImmediates) {
for (intptr_t base = -8; base < 7; base++) {
for (intptr_t shift = 0; shift < XLEN; shift++) {
Expand Down

0 comments on commit 1ae50ac

Please sign in to comment.