mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 01:59:38 +00:00
Import "Add the ratified portions of the B extension: Zba, Zbb, Zbc, Zbs."
TEST=ci Change-Id: I7676dabc67762c0c2e4a1a9975100c59edcda769 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/271441 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Alexander Aprelev <aam@google.com>
This commit is contained in:
parent
38ac261884
commit
b166d909c3
|
@ -1086,12 +1086,12 @@ void MicroAssembler::fsgnjxs(FRegister rd, FRegister rs1, FRegister rs2) {
|
|||
|
||||
void MicroAssembler::fmins(FRegister rd, FRegister rs1, FRegister rs2) {
|
||||
ASSERT(Supports(RV_F));
|
||||
EmitRType(FMINMAXS, rs2, rs1, MIN, rd, OPFP);
|
||||
EmitRType(FMINMAXS, rs2, rs1, FMIN, rd, OPFP);
|
||||
}
|
||||
|
||||
void MicroAssembler::fmaxs(FRegister rd, FRegister rs1, FRegister rs2) {
|
||||
ASSERT(Supports(RV_F));
|
||||
EmitRType(FMINMAXS, rs2, rs1, MAX, rd, OPFP);
|
||||
EmitRType(FMINMAXS, rs2, rs1, FMAX, rd, OPFP);
|
||||
}
|
||||
|
||||
void MicroAssembler::feqs(Register rd, FRegister rs1, FRegister rs2) {
|
||||
|
@ -1296,12 +1296,12 @@ void MicroAssembler::fsgnjxd(FRegister rd, FRegister rs1, FRegister rs2) {
|
|||
|
||||
void MicroAssembler::fmind(FRegister rd, FRegister rs1, FRegister rs2) {
|
||||
ASSERT(Supports(RV_D));
|
||||
EmitRType(FMINMAXD, rs2, rs1, MIN, rd, OPFP);
|
||||
EmitRType(FMINMAXD, rs2, rs1, FMIN, rd, OPFP);
|
||||
}
|
||||
|
||||
void MicroAssembler::fmaxd(FRegister rd, FRegister rs1, FRegister rs2) {
|
||||
ASSERT(Supports(RV_D));
|
||||
EmitRType(FMINMAXD, rs2, rs1, MAX, rd, OPFP);
|
||||
EmitRType(FMINMAXD, rs2, rs1, FMAX, rd, OPFP);
|
||||
}
|
||||
|
||||
void MicroAssembler::fcvtsd(FRegister rd,
|
||||
|
@ -1398,6 +1398,242 @@ void MicroAssembler::fmvdx(FRegister rd, Register rs1) {
|
|||
}
|
||||
#endif // XLEN >= 64
|
||||
|
||||
#if XLEN >= 64
|
||||
void MicroAssembler::adduw(Register rd, Register rs1, Register rs2) {
|
||||
ASSERT(Supports(RV_Zba));
|
||||
EmitRType(ADDUW, rs2, rs1, F3_0, rd, OP32);
|
||||
}
|
||||
#endif
|
||||
|
||||
void MicroAssembler::sh1add(Register rd, Register rs1, Register rs2) {
|
||||
ASSERT(Supports(RV_Zba));
|
||||
EmitRType(SHADD, rs2, rs1, SH1ADD, rd, OP);
|
||||
}
|
||||
|
||||
#if XLEN >= 64
|
||||
void MicroAssembler::sh1adduw(Register rd, Register rs1, Register rs2) {
|
||||
ASSERT(Supports(RV_Zba));
|
||||
EmitRType(SHADD, rs2, rs1, SH1ADD, rd, OP32);
|
||||
}
|
||||
#endif
|
||||
|
||||
void MicroAssembler::sh2add(Register rd, Register rs1, Register rs2) {
|
||||
ASSERT(Supports(RV_Zba));
|
||||
EmitRType(SHADD, rs2, rs1, SH2ADD, rd, OP);
|
||||
}
|
||||
|
||||
#if XLEN >= 64
|
||||
void MicroAssembler::sh2adduw(Register rd, Register rs1, Register rs2) {
|
||||
ASSERT(Supports(RV_Zba));
|
||||
EmitRType(SHADD, rs2, rs1, SH2ADD, rd, OP32);
|
||||
}
|
||||
#endif
|
||||
|
||||
void MicroAssembler::sh3add(Register rd, Register rs1, Register rs2) {
|
||||
ASSERT(Supports(RV_Zba));
|
||||
EmitRType(SHADD, rs2, rs1, SH3ADD, rd, OP);
|
||||
}
|
||||
|
||||
#if XLEN >= 64
|
||||
void MicroAssembler::sh3adduw(Register rd, Register rs1, Register rs2) {
|
||||
ASSERT(Supports(RV_Zba));
|
||||
EmitRType(SHADD, rs2, rs1, SH3ADD, rd, OP32);
|
||||
}
|
||||
|
||||
void MicroAssembler::slliuw(Register rd, Register rs1, intx_t shamt) {
|
||||
ASSERT((shamt > 0) && (shamt < 32));
|
||||
ASSERT(Supports(RV_Zba));
|
||||
EmitRType(SLLIUW, shamt, rs1, SLLI, rd, OPIMM32);
|
||||
}
|
||||
#endif
|
||||
|
||||
void MicroAssembler::andn(Register rd, Register rs1, Register rs2) {
|
||||
ASSERT(Supports(RV_Zbb));
|
||||
EmitRType(SUB, rs2, rs1, AND, rd, OP);
|
||||
}
|
||||
|
||||
void MicroAssembler::orn(Register rd, Register rs1, Register rs2) {
|
||||
ASSERT(Supports(RV_Zbb));
|
||||
EmitRType(SUB, rs2, rs1, OR, rd, OP);
|
||||
}
|
||||
|
||||
void MicroAssembler::xnor(Register rd, Register rs1, Register rs2) {
|
||||
ASSERT(Supports(RV_Zbb));
|
||||
EmitRType(SUB, rs2, rs1, XOR, rd, OP);
|
||||
}
|
||||
|
||||
void MicroAssembler::clz(Register rd, Register rs1) {
|
||||
ASSERT(Supports(RV_Zbb));
|
||||
EmitRType(COUNT, 0b00000, rs1, F3_COUNT, rd, OPIMM);
|
||||
}
|
||||
|
||||
void MicroAssembler::clzw(Register rd, Register rs1) {
|
||||
ASSERT(Supports(RV_Zbb));
|
||||
EmitRType(COUNT, 0b00000, rs1, F3_COUNT, rd, OPIMM32);
|
||||
}
|
||||
|
||||
void MicroAssembler::ctz(Register rd, Register rs1) {
|
||||
ASSERT(Supports(RV_Zbb));
|
||||
EmitRType(COUNT, 0b00001, rs1, F3_COUNT, rd, OPIMM);
|
||||
}
|
||||
|
||||
void MicroAssembler::ctzw(Register rd, Register rs1) {
|
||||
ASSERT(Supports(RV_Zbb));
|
||||
EmitRType(COUNT, 0b00001, rs1, F3_COUNT, rd, OPIMM32);
|
||||
}
|
||||
|
||||
void MicroAssembler::cpop(Register rd, Register rs1) {
|
||||
ASSERT(Supports(RV_Zbb));
|
||||
EmitRType(COUNT, 0b00010, rs1, F3_COUNT, rd, OPIMM);
|
||||
}
|
||||
|
||||
void MicroAssembler::cpopw(Register rd, Register rs1) {
|
||||
ASSERT(Supports(RV_Zbb));
|
||||
EmitRType(COUNT, 0b00010, rs1, F3_COUNT, rd, OPIMM32);
|
||||
}
|
||||
|
||||
void MicroAssembler::max(Register rd, Register rs1, Register rs2) {
|
||||
ASSERT(Supports(RV_Zbb));
|
||||
EmitRType(MINMAXCLMUL, rs2, rs1, MAX, rd, OP);
|
||||
}
|
||||
|
||||
void MicroAssembler::maxu(Register rd, Register rs1, Register rs2) {
|
||||
ASSERT(Supports(RV_Zbb));
|
||||
EmitRType(MINMAXCLMUL, rs2, rs1, MAXU, rd, OP);
|
||||
}
|
||||
|
||||
void MicroAssembler::min(Register rd, Register rs1, Register rs2) {
|
||||
ASSERT(Supports(RV_Zbb));
|
||||
EmitRType(MINMAXCLMUL, rs2, rs1, MIN, rd, OP);
|
||||
}
|
||||
|
||||
void MicroAssembler::minu(Register rd, Register rs1, Register rs2) {
|
||||
ASSERT(Supports(RV_Zbb));
|
||||
EmitRType(MINMAXCLMUL, rs2, rs1, MINU, rd, OP);
|
||||
}
|
||||
|
||||
void MicroAssembler::sextb(Register rd, Register rs1) {
|
||||
ASSERT(Supports(RV_Zbb));
|
||||
EmitRType((Funct7)0b0110000, 0b00100, rs1, SEXT, rd, OPIMM);
|
||||
}
|
||||
|
||||
void MicroAssembler::sexth(Register rd, Register rs1) {
|
||||
ASSERT(Supports(RV_Zbb));
|
||||
EmitRType((Funct7)0b0110000, 0b00101, rs1, SEXT, rd, OPIMM);
|
||||
}
|
||||
|
||||
void MicroAssembler::zexth(Register rd, Register rs1) {
|
||||
ASSERT(Supports(RV_Zbb));
|
||||
#if XLEN == 32
|
||||
EmitRType((Funct7)0b0000100, 0b00000, rs1, ZEXT, rd, OP);
|
||||
#elif XLEN == 64
|
||||
EmitRType((Funct7)0b0000100, 0b00000, rs1, ZEXT, rd, OP32);
|
||||
#else
|
||||
UNIMPLEMENTED();
|
||||
#endif
|
||||
}
|
||||
|
||||
void MicroAssembler::rol(Register rd, Register rs1, Register rs2) {
|
||||
ASSERT(Supports(RV_Zbb));
|
||||
EmitRType(ROTATE, rs2, rs1, ROL, rd, OP);
|
||||
}
|
||||
|
||||
void MicroAssembler::rolw(Register rd, Register rs1, Register rs2) {
|
||||
ASSERT(Supports(RV_Zbb));
|
||||
EmitRType(ROTATE, rs2, rs1, ROL, rd, OP32);
|
||||
}
|
||||
|
||||
void MicroAssembler::ror(Register rd, Register rs1, Register rs2) {
|
||||
ASSERT(Supports(RV_Zbb));
|
||||
EmitRType(ROTATE, rs2, rs1, ROR, rd, OP);
|
||||
}
|
||||
|
||||
void MicroAssembler::rori(Register rd, Register rs1, intx_t shamt) {
|
||||
ASSERT(Supports(RV_Zbb));
|
||||
EmitRType(ROTATE, shamt, rs1, ROR, rd, OPIMM);
|
||||
}
|
||||
|
||||
void MicroAssembler::roriw(Register rd, Register rs1, intx_t shamt) {
|
||||
ASSERT(Supports(RV_Zbb));
|
||||
EmitRType(ROTATE, shamt, rs1, ROR, rd, OPIMM32);
|
||||
}
|
||||
|
||||
void MicroAssembler::rorw(Register rd, Register rs1, Register rs2) {
|
||||
ASSERT(Supports(RV_Zbb));
|
||||
EmitRType(ROTATE, rs2, rs1, ROR, rd, OP32);
|
||||
}
|
||||
|
||||
void MicroAssembler::orcb(Register rd, Register rs1) {
|
||||
ASSERT(Supports(RV_Zbb));
|
||||
EmitRType((Funct7)0b0010100, 0b00111, rs1, (Funct3)0b101, rd, OPIMM);
|
||||
}
|
||||
|
||||
void MicroAssembler::rev8(Register rd, Register rs1) {
|
||||
ASSERT(Supports(RV_Zbb));
|
||||
#if XLEN == 32
|
||||
EmitRType((Funct7)0b0110100, 0b11000, rs1, (Funct3)0b101, rd, OPIMM);
|
||||
#elif XLEN == 64
|
||||
EmitRType((Funct7)0b0110101, 0b11000, rs1, (Funct3)0b101, rd, OPIMM);
|
||||
#else
|
||||
UNIMPLEMENTED();
|
||||
#endif
|
||||
}
|
||||
|
||||
void MicroAssembler::clmul(Register rd, Register rs1, Register rs2) {
|
||||
ASSERT(Supports(RV_Zbc));
|
||||
EmitRType(MINMAXCLMUL, rs2, rs1, CLMUL, rd, OP);
|
||||
}
|
||||
|
||||
void MicroAssembler::clmulh(Register rd, Register rs1, Register rs2) {
|
||||
ASSERT(Supports(RV_Zbc));
|
||||
EmitRType(MINMAXCLMUL, rs2, rs1, CLMULH, rd, OP);
|
||||
}
|
||||
|
||||
void MicroAssembler::clmulr(Register rd, Register rs1, Register rs2) {
|
||||
ASSERT(Supports(RV_Zbc));
|
||||
EmitRType(MINMAXCLMUL, rs2, rs1, CLMULR, rd, OP);
|
||||
}
|
||||
|
||||
void MicroAssembler::bclr(Register rd, Register rs1, Register rs2) {
|
||||
ASSERT(Supports(RV_Zbs));
|
||||
EmitRType(BCLRBEXT, rs2, rs1, BCLR, rd, OP);
|
||||
}
|
||||
|
||||
void MicroAssembler::bclri(Register rd, Register rs1, intx_t shamt) {
|
||||
ASSERT(Supports(RV_Zbs));
|
||||
EmitRType(BCLRBEXT, shamt, rs1, BCLR, rd, OPIMM);
|
||||
}
|
||||
|
||||
void MicroAssembler::bext(Register rd, Register rs1, Register rs2) {
|
||||
ASSERT(Supports(RV_Zbs));
|
||||
EmitRType(BCLRBEXT, rs2, rs1, BEXT, rd, OP);
|
||||
}
|
||||
|
||||
void MicroAssembler::bexti(Register rd, Register rs1, intx_t shamt) {
|
||||
ASSERT(Supports(RV_Zbs));
|
||||
EmitRType(BCLRBEXT, shamt, rs1, BEXT, rd, OPIMM);
|
||||
}
|
||||
|
||||
void MicroAssembler::binv(Register rd, Register rs1, Register rs2) {
|
||||
ASSERT(Supports(RV_Zbs));
|
||||
EmitRType(BINV, rs2, rs1, F3_BINV, rd, OP);
|
||||
}
|
||||
|
||||
void MicroAssembler::binvi(Register rd, Register rs1, intx_t shamt) {
|
||||
ASSERT(Supports(RV_Zbs));
|
||||
EmitRType(BINV, shamt, rs1, F3_BINV, rd, OPIMM);
|
||||
}
|
||||
|
||||
void MicroAssembler::bset(Register rd, Register rs1, Register rs2) {
|
||||
ASSERT(Supports(RV_Zbs));
|
||||
EmitRType(BSET, rs2, rs1, F3_BSET, rd, OP);
|
||||
}
|
||||
|
||||
void MicroAssembler::bseti(Register rd, Register rs1, intx_t shamt) {
|
||||
ASSERT(Supports(RV_Zbs));
|
||||
EmitRType(BSET, shamt, rs1, F3_BSET, rd, OPIMM);
|
||||
}
|
||||
|
||||
void MicroAssembler::c_lwsp(Register rd, Address addr) {
|
||||
ASSERT(rd != ZR);
|
||||
ASSERT(addr.base() == SP);
|
||||
|
|
|
@ -547,6 +547,57 @@ class MicroAssembler : public AssemblerBase {
|
|||
void fmvdx(FRegister rd, Register rs1);
|
||||
#endif // XLEN >= 64
|
||||
|
||||
// ==== Zba: Address generation ====
|
||||
void adduw(Register rd, Register rs1, Register rs2);
|
||||
void sh1add(Register rd, Register rs1, Register rs2);
|
||||
void sh1adduw(Register rd, Register rs1, Register rs2);
|
||||
void sh2add(Register rd, Register rs1, Register rs2);
|
||||
void sh2adduw(Register rd, Register rs1, Register rs2);
|
||||
void sh3add(Register rd, Register rs1, Register rs2);
|
||||
void sh3adduw(Register rd, Register rs1, Register rs2);
|
||||
void slliuw(Register rd, Register rs1, intx_t imm);
|
||||
|
||||
// ==== Zbb: Basic bit-manipulation ====
|
||||
void andn(Register rd, Register rs1, Register rs2);
|
||||
void orn(Register rd, Register rs1, Register rs2);
|
||||
void xnor(Register rd, Register rs1, Register rs2);
|
||||
void clz(Register rd, Register rs);
|
||||
void clzw(Register rd, Register rs);
|
||||
void ctz(Register rd, Register rs);
|
||||
void ctzw(Register rd, Register rs);
|
||||
void cpop(Register rd, Register rs);
|
||||
void cpopw(Register rd, Register rs);
|
||||
void max(Register rd, Register rs1, Register rs2);
|
||||
void maxu(Register rd, Register rs1, Register rs2);
|
||||
void min(Register rd, Register rs1, Register rs2);
|
||||
void minu(Register rd, Register rs1, Register rs2);
|
||||
void sextb(Register rd, Register rs);
|
||||
void sexth(Register rd, Register rs);
|
||||
void zexth(Register rd, Register rs);
|
||||
void rol(Register rd, Register rs1, Register rs2);
|
||||
void rolw(Register rd, Register rs1, Register rs2);
|
||||
void ror(Register rd, Register rs1, Register rs2);
|
||||
void rori(Register rd, Register rs1, intx_t imm);
|
||||
void roriw(Register rd, Register rs1, intx_t imm);
|
||||
void rorw(Register rd, Register rs1, Register rs2);
|
||||
void orcb(Register rd, Register rs);
|
||||
void rev8(Register rd, Register rs);
|
||||
|
||||
// ==== Zbc: Carry-less multiplication ====
|
||||
void clmul(Register rd, Register rs1, Register rs2);
|
||||
void clmulh(Register rd, Register rs1, Register rs2);
|
||||
void clmulr(Register rd, Register rs1, Register rs2);
|
||||
|
||||
// ==== Zbs: Single-bit instructions ====
|
||||
void bclr(Register rd, Register rs1, Register rs2);
|
||||
void bclri(Register rd, Register rs1, intx_t shamt);
|
||||
void bext(Register rd, Register rs1, Register rs2);
|
||||
void bexti(Register rd, Register rs1, intx_t shamt);
|
||||
void binv(Register rd, Register rs1, Register rs2);
|
||||
void binvi(Register rd, Register rs1, intx_t shamt);
|
||||
void bset(Register rd, Register rs1, Register rs2);
|
||||
void bseti(Register rd, Register rs1, intx_t shamt);
|
||||
|
||||
// ==== Dart Simulator Debugging ====
|
||||
void SimulatorPrintObject(Register rs1);
|
||||
|
||||
|
|
|
@ -6165,6 +6165,952 @@ ASSEMBLER_TEST_RUN(CompressedEnvironmentBreak, test) {
|
|||
// Not running: would trap.
|
||||
}
|
||||
|
||||
#if XLEN >= 64
|
||||
ASSEMBLER_TEST_GENERATE(AddUnsignedWord, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ adduw(A0, A0, A1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(AddUnsignedWord, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"08b5053b add.uw a0, a0, a1\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(0x200000001, Call(test->entry(), 0x1, 0x200000000));
|
||||
EXPECT_EQ(0x200000001, Call(test->entry(), 0x100000001, 0x200000000));
|
||||
EXPECT_EQ(0x2FFFFFFFF, Call(test->entry(), -0x1, 0x200000000));
|
||||
}
|
||||
#endif
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(Shift1Add, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ sh1add(A0, A0, A1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(Shift1Add, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"20b52533 sh1add a0, a0, a1\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(1002, Call(test->entry(), 1, 1000));
|
||||
EXPECT_EQ(1000, Call(test->entry(), 0, 1000));
|
||||
EXPECT_EQ(998, Call(test->entry(), -1, 1000));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(Shift2Add, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ sh2add(A0, A0, A1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(Shift2Add, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"20b54533 sh2add a0, a0, a1\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(1004, Call(test->entry(), 1, 1000));
|
||||
EXPECT_EQ(1000, Call(test->entry(), 0, 1000));
|
||||
EXPECT_EQ(996, Call(test->entry(), -1, 1000));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(Shift3Add, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ sh3add(A0, A0, A1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(Shift3Add, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"20b56533 sh3add a0, a0, a1\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(1008, Call(test->entry(), 1, 1000));
|
||||
EXPECT_EQ(1000, Call(test->entry(), 0, 1000));
|
||||
EXPECT_EQ(992, Call(test->entry(), -1, 1000));
|
||||
}
|
||||
|
||||
#if XLEN >= 64
|
||||
ASSEMBLER_TEST_GENERATE(Shift1AddUnsignedWord, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ sh1adduw(A0, A0, A1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(Shift1AddUnsignedWord, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"20b5253b sh1add.uw a0, a0, a1\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(1002, Call(test->entry(), 1, 1000));
|
||||
EXPECT_EQ(1002, Call(test->entry(), 0x100000001, 1000));
|
||||
EXPECT_EQ(1000, Call(test->entry(), 0, 1000));
|
||||
EXPECT_EQ(8589935590, Call(test->entry(), -1, 1000));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(Shift2AddUnsignedWord, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ sh2adduw(A0, A0, A1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(Shift2AddUnsignedWord, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"20b5453b sh2add.uw a0, a0, a1\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(1004, Call(test->entry(), 1, 1000));
|
||||
EXPECT_EQ(1004, Call(test->entry(), 0x100000001, 1000));
|
||||
EXPECT_EQ(1000, Call(test->entry(), 0, 1000));
|
||||
EXPECT_EQ(17179870180, Call(test->entry(), -1, 1000));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(Shift3AddUnsignedWord, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ sh3adduw(A0, A0, A1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(Shift3AddUnsignedWord, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"20b5653b sh3add.uw a0, a0, a1\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(1008, Call(test->entry(), 1, 1000));
|
||||
EXPECT_EQ(1008, Call(test->entry(), 0x100000001, 1000));
|
||||
EXPECT_EQ(1000, Call(test->entry(), 0, 1000));
|
||||
EXPECT_EQ(34359739360, Call(test->entry(), -1, 1000));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(ShiftLeftLogicalImmediateUnsignedWord, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ slliuw(A0, A0, 8);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(ShiftLeftLogicalImmediateUnsignedWord, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"0885151b slli.uw a0, a0, 0x8\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(0x100, Call(test->entry(), 0x1));
|
||||
EXPECT_EQ(0x1000000000, Call(test->entry(), 0x10000000));
|
||||
EXPECT_EQ(0, Call(test->entry(), 0x100000000));
|
||||
EXPECT_EQ(0x100, Call(test->entry(), 0x100000001));
|
||||
}
|
||||
#endif
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(AndNot, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ andn(A0, A0, A1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(AndNot, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"40b57533 andn a0, a0, a1\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(6, Call(test->entry(), 7, 17));
|
||||
EXPECT_EQ(0, Call(test->entry(), 7, -17));
|
||||
EXPECT_EQ(-24, Call(test->entry(), -7, 17));
|
||||
EXPECT_EQ(16, Call(test->entry(), -7, -17));
|
||||
EXPECT_EQ(16, Call(test->entry(), 17, 7));
|
||||
EXPECT_EQ(0, Call(test->entry(), 17, -7));
|
||||
EXPECT_EQ(-24, Call(test->entry(), -17, 7));
|
||||
EXPECT_EQ(6, Call(test->entry(), -17, -7));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(OrNot, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ orn(A0, A0, A1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(OrNot, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"40b56533 orn a0, a0, a1\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(-17, Call(test->entry(), 7, 17));
|
||||
EXPECT_EQ(23, Call(test->entry(), 7, -17));
|
||||
EXPECT_EQ(-1, Call(test->entry(), -7, 17));
|
||||
EXPECT_EQ(-7, Call(test->entry(), -7, -17));
|
||||
EXPECT_EQ(-7, Call(test->entry(), 17, 7));
|
||||
EXPECT_EQ(23, Call(test->entry(), 17, -7));
|
||||
EXPECT_EQ(-1, Call(test->entry(), -17, 7));
|
||||
EXPECT_EQ(-17, Call(test->entry(), -17, -7));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(XorNot, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ xnor(A0, A0, A1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(XorNot, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"40b54533 xnor a0, a0, a1\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(-23, Call(test->entry(), 7, 17));
|
||||
EXPECT_EQ(23, Call(test->entry(), 7, -17));
|
||||
EXPECT_EQ(23, Call(test->entry(), -7, 17));
|
||||
EXPECT_EQ(-23, Call(test->entry(), -7, -17));
|
||||
EXPECT_EQ(-23, Call(test->entry(), 17, 7));
|
||||
EXPECT_EQ(23, Call(test->entry(), 17, -7));
|
||||
EXPECT_EQ(23, Call(test->entry(), -17, 7));
|
||||
EXPECT_EQ(-23, Call(test->entry(), -17, -7));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(CountLeadingZeroes, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ clz(A0, A0);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(CountLeadingZeroes, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"60051513 clz a0, a0\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(XLEN, Call(test->entry(), 0));
|
||||
EXPECT_EQ(XLEN - 1, Call(test->entry(), 1));
|
||||
EXPECT_EQ(XLEN - 2, Call(test->entry(), 2));
|
||||
EXPECT_EQ(XLEN - 3, Call(test->entry(), 4));
|
||||
EXPECT_EQ(XLEN - 8, Call(test->entry(), 240));
|
||||
EXPECT_EQ(0, Call(test->entry(), -1));
|
||||
EXPECT_EQ(0, Call(test->entry(), -2));
|
||||
EXPECT_EQ(0, Call(test->entry(), -4));
|
||||
EXPECT_EQ(0, Call(test->entry(), -240));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(CountTrailingZeroes, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ ctz(A0, A0);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(CountTrailingZeroes, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"60151513 ctz a0, a0\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(XLEN, Call(test->entry(), 0));
|
||||
EXPECT_EQ(0, Call(test->entry(), 1));
|
||||
EXPECT_EQ(1, Call(test->entry(), 2));
|
||||
EXPECT_EQ(2, Call(test->entry(), 4));
|
||||
EXPECT_EQ(4, Call(test->entry(), 240));
|
||||
EXPECT_EQ(0, Call(test->entry(), -1));
|
||||
EXPECT_EQ(1, Call(test->entry(), -2));
|
||||
EXPECT_EQ(2, Call(test->entry(), -4));
|
||||
EXPECT_EQ(4, Call(test->entry(), -240));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(CountPopulation, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ cpop(A0, A0);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(CountPopulation, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"60251513 cpop a0, a0\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(0, Call(test->entry(), 0));
|
||||
EXPECT_EQ(1, Call(test->entry(), 1));
|
||||
EXPECT_EQ(3, Call(test->entry(), 7));
|
||||
EXPECT_EQ(4, Call(test->entry(), 30));
|
||||
EXPECT_EQ(XLEN, Call(test->entry(), -1));
|
||||
EXPECT_EQ(XLEN - 2, Call(test->entry(), -7));
|
||||
EXPECT_EQ(XLEN - 4, Call(test->entry(), -30));
|
||||
}
|
||||
|
||||
#if XLEN >= 64
|
||||
ASSEMBLER_TEST_GENERATE(CountLeadingZeroesWord, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ clzw(A0, A0);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(CountLeadingZeroesWord, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"6005151b clzw a0, a0\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(32, Call(test->entry(), 0));
|
||||
EXPECT_EQ(31, Call(test->entry(), 1));
|
||||
EXPECT_EQ(30, Call(test->entry(), 2));
|
||||
EXPECT_EQ(29, Call(test->entry(), 4));
|
||||
EXPECT_EQ(24, Call(test->entry(), 240));
|
||||
EXPECT_EQ(0, Call(test->entry(), -1));
|
||||
EXPECT_EQ(0, Call(test->entry(), -2));
|
||||
EXPECT_EQ(0, Call(test->entry(), -4));
|
||||
EXPECT_EQ(0, Call(test->entry(), -240));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(CountTrailingZeroesWord, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ ctzw(A0, A0);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(CountTrailingZeroesWord, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"6015151b ctzw a0, a0\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(32, Call(test->entry(), 0));
|
||||
EXPECT_EQ(0, Call(test->entry(), 1));
|
||||
EXPECT_EQ(1, Call(test->entry(), 2));
|
||||
EXPECT_EQ(2, Call(test->entry(), 4));
|
||||
EXPECT_EQ(4, Call(test->entry(), 240));
|
||||
EXPECT_EQ(0, Call(test->entry(), -1));
|
||||
EXPECT_EQ(1, Call(test->entry(), -2));
|
||||
EXPECT_EQ(2, Call(test->entry(), -4));
|
||||
EXPECT_EQ(4, Call(test->entry(), -240));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(CountPopulationWord, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ cpopw(A0, A0);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(CountPopulationWord, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"6025151b cpopw a0, a0\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(0, Call(test->entry(), 0));
|
||||
EXPECT_EQ(1, Call(test->entry(), 1));
|
||||
EXPECT_EQ(3, Call(test->entry(), 7));
|
||||
EXPECT_EQ(4, Call(test->entry(), 30));
|
||||
EXPECT_EQ(32, Call(test->entry(), -1));
|
||||
EXPECT_EQ(30, Call(test->entry(), -7));
|
||||
EXPECT_EQ(28, Call(test->entry(), -30));
|
||||
EXPECT_EQ(0, Call(test->entry(), 0x7FFFFFFF00000000));
|
||||
}
|
||||
#endif
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(Max, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ max(A0, A0, A1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(Max, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"0ab56533 max a0, a0, a1\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(17, Call(test->entry(), 7, 17));
|
||||
EXPECT_EQ(17, Call(test->entry(), -7, 17));
|
||||
EXPECT_EQ(7, Call(test->entry(), 7, -17));
|
||||
EXPECT_EQ(-7, Call(test->entry(), -7, -17));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(MaxUnsigned, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ maxu(A0, A0, A1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(MaxUnsigned, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"0ab57533 maxu a0, a0, a1\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(17, Call(test->entry(), 7, 17));
|
||||
EXPECT_EQ(-7, Call(test->entry(), -7, 17));
|
||||
EXPECT_EQ(-17, Call(test->entry(), 7, -17));
|
||||
EXPECT_EQ(-7, Call(test->entry(), -7, -17));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(Min, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ min(A0, A0, A1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(Min, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"0ab54533 min a0, a0, a1\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(7, Call(test->entry(), 7, 17));
|
||||
EXPECT_EQ(-7, Call(test->entry(), -7, 17));
|
||||
EXPECT_EQ(-17, Call(test->entry(), 7, -17));
|
||||
EXPECT_EQ(-17, Call(test->entry(), -7, -17));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(MinUnsigned, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ minu(A0, A0, A1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(MinUnsigned, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"0ab55533 minu a0, a0, a1\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(7, Call(test->entry(), 7, 17));
|
||||
EXPECT_EQ(17, Call(test->entry(), -7, 17));
|
||||
EXPECT_EQ(7, Call(test->entry(), 7, -17));
|
||||
EXPECT_EQ(-17, Call(test->entry(), -7, -17));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(SignExtendByte, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ sextb(A0, A0);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(SignExtendByte, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"60451513 sext.b a0, a0\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(1, Call(test->entry(), 1));
|
||||
EXPECT_EQ(127, Call(test->entry(), 127));
|
||||
EXPECT_EQ(-128, Call(test->entry(), 128));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(SignExtendHalfWord, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ sexth(A0, A0);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(SignExtendHalfWord, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"60551513 sext.h a0, a0\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(0, Call(test->entry(), 0));
|
||||
EXPECT_EQ(0x7BCD, Call(test->entry(), 0x12347BCD));
|
||||
EXPECT_EQ(-1, Call(test->entry(), 0xFFFF));
|
||||
EXPECT_EQ(-1, Call(test->entry(), -1));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(ZeroExtendHalfWord, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ zexth(A0, A0);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(ZeroExtendHalfWord, test) {
|
||||
#if XLEN == 32
|
||||
EXPECT_DISASSEMBLY(
|
||||
"08054533 zext.h a0, a0\n"
|
||||
" 8082 ret\n");
|
||||
#else
|
||||
EXPECT_DISASSEMBLY(
|
||||
"0805453b zext.h a0, a0\n"
|
||||
" 8082 ret\n");
|
||||
#endif
|
||||
|
||||
EXPECT_EQ(0, Call(test->entry(), 0));
|
||||
EXPECT_EQ(0xABCD, Call(test->entry(), 0x1234ABCD));
|
||||
EXPECT_EQ(0xFFFF, Call(test->entry(), 0xFFFF));
|
||||
EXPECT_EQ(0xFFFF, Call(test->entry(), -1));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(RotateRight, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ ror(A0, A0, A1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(RotateRight, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"60b55533 ror a0, a0, a1\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
#if XLEN == 32
|
||||
EXPECT_EQ(static_cast<intx_t>(0x12345678),
|
||||
Call(test->entry(), 0x12345678, 0));
|
||||
EXPECT_EQ(static_cast<intx_t>(0x81234567),
|
||||
Call(test->entry(), 0x12345678, 4));
|
||||
EXPECT_EQ(static_cast<intx_t>(0x23456781),
|
||||
Call(test->entry(), 0x12345678, 28));
|
||||
EXPECT_EQ(static_cast<intx_t>(0x81234567),
|
||||
Call(test->entry(), 0x12345678, 36));
|
||||
#else
|
||||
EXPECT_EQ(static_cast<intx_t>(0x0123456789ABCDEF),
|
||||
Call(test->entry(), 0x0123456789ABCDEF, 0));
|
||||
EXPECT_EQ(static_cast<intx_t>(0xF0123456789ABCDE),
|
||||
Call(test->entry(), 0x0123456789ABCDEF, 4));
|
||||
EXPECT_EQ(static_cast<intx_t>(0x123456789ABCDEF0),
|
||||
Call(test->entry(), 0x0123456789ABCDEF, 60));
|
||||
EXPECT_EQ(static_cast<intx_t>(0xF0123456789ABCDE),
|
||||
Call(test->entry(), 0x0123456789ABCDEF, 68));
|
||||
#endif
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(RotateLeft, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ rol(A0, A0, A1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(RotateLeft, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"60b51533 rol a0, a0, a1\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
#if XLEN == 32
|
||||
EXPECT_EQ(static_cast<intx_t>(0x12345678),
|
||||
Call(test->entry(), 0x12345678, 0));
|
||||
EXPECT_EQ(static_cast<intx_t>(0x23456781),
|
||||
Call(test->entry(), 0x12345678, 4));
|
||||
EXPECT_EQ(static_cast<intx_t>(0x81234567),
|
||||
Call(test->entry(), 0x12345678, 28));
|
||||
EXPECT_EQ(static_cast<intx_t>(0x23456781),
|
||||
Call(test->entry(), 0x12345678, 36));
|
||||
#else
|
||||
EXPECT_EQ(static_cast<intx_t>(0x0123456789ABCDEF),
|
||||
Call(test->entry(), 0x0123456789ABCDEF, 0));
|
||||
EXPECT_EQ(static_cast<intx_t>(0x123456789ABCDEF0),
|
||||
Call(test->entry(), 0x0123456789ABCDEF, 4));
|
||||
EXPECT_EQ(static_cast<intx_t>(0xF0123456789ABCDE),
|
||||
Call(test->entry(), 0x0123456789ABCDEF, 60));
|
||||
EXPECT_EQ(static_cast<intx_t>(0x123456789ABCDEF0),
|
||||
Call(test->entry(), 0x0123456789ABCDEF, 68));
|
||||
#endif
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(RotateRightImmediate, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ rori(A0, A0, 4);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(RotateRightImmediate, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"60455513 rori a0, a0, 0x4\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
#if XLEN == 32
|
||||
EXPECT_EQ(static_cast<intx_t>(0x81234567), Call(test->entry(), 0x12345678));
|
||||
#else
|
||||
EXPECT_EQ(static_cast<intx_t>(0xF0123456789ABCDE),
|
||||
Call(test->entry(), 0x0123456789ABCDEF));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if XLEN >= 64
|
||||
ASSEMBLER_TEST_GENERATE(RotateRightWord, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ rorw(A0, A0, A1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(RotateRightWord, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"60b5553b rorw a0, a0, a1\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(sign_extend(0x12345678), Call(test->entry(), 0x12345678, 0));
|
||||
EXPECT_EQ(sign_extend(0x81234567), Call(test->entry(), 0x12345678, 4));
|
||||
EXPECT_EQ(sign_extend(0x23456781), Call(test->entry(), 0x12345678, 28));
|
||||
EXPECT_EQ(sign_extend(0x81234567), Call(test->entry(), 0x12345678, 36));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(RotateLeftWord, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ rolw(A0, A0, A1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(RotateLeftWord, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"60b5153b rolw a0, a0, a1\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(sign_extend(0x12345678), Call(test->entry(), 0x12345678, 0));
|
||||
EXPECT_EQ(sign_extend(0x23456781), Call(test->entry(), 0x12345678, 4));
|
||||
EXPECT_EQ(sign_extend(0x81234567), Call(test->entry(), 0x12345678, 28));
|
||||
EXPECT_EQ(sign_extend(0x23456781), Call(test->entry(), 0x12345678, 36));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(RotateRightImmediateWord, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ roriw(A0, A0, 4);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(RotateRightImmediateWord, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"6045551b roriw a0, a0, 0x4\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(sign_extend(0x81234567), Call(test->entry(), 0x12345678));
|
||||
}
|
||||
#endif
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(OrCombineBytes, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ orcb(A0, A0);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(OrCombineBytes, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"28755513 orc.b a0, a0\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(0, Call(test->entry(), 0));
|
||||
EXPECT_EQ(-1, Call(test->entry(), -1));
|
||||
EXPECT_EQ(0x00FF00FF, Call(test->entry(), 0x00010001));
|
||||
#if XLEN >= 64
|
||||
EXPECT_EQ(0x00FF00FF00FF00FF, Call(test->entry(), 0x0001000100010001));
|
||||
#endif
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(ByteReverse, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ rev8(A0, A0);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(ByteReverse, test) {
|
||||
#if XLEN == 32
|
||||
EXPECT_DISASSEMBLY(
|
||||
"69855513 rev8 a0, a0\n"
|
||||
" 8082 ret\n");
|
||||
#else
|
||||
EXPECT_DISASSEMBLY(
|
||||
"6b855513 rev8 a0, a0\n"
|
||||
" 8082 ret\n");
|
||||
#endif
|
||||
|
||||
EXPECT_EQ(0, Call(test->entry(), 0));
|
||||
EXPECT_EQ(-1, Call(test->entry(), -1));
|
||||
#if XLEN == 32
|
||||
EXPECT_EQ(0x11223344, Call(test->entry(), 0x44332211));
|
||||
#elif XLEN == 64
|
||||
EXPECT_EQ(0x1122334455667788, Call(test->entry(), 0x8877665544332211));
|
||||
#endif
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(CarrylessMultiply, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ clmul(A0, A0, A1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(CarrylessMultiply, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"0ab51533 clmul a0, a0, a1\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
#if XLEN == 32
|
||||
EXPECT_EQ(0x55555555, Call(test->entry(), -1, -1));
|
||||
#else
|
||||
EXPECT_EQ(0x5555555555555555, Call(test->entry(), -1, -1));
|
||||
#endif
|
||||
EXPECT_EQ(0, Call(test->entry(), -1, 0));
|
||||
EXPECT_EQ(-1, Call(test->entry(), -1, 1));
|
||||
EXPECT_EQ(0, Call(test->entry(), 0, -1));
|
||||
EXPECT_EQ(0, Call(test->entry(), 0, 0));
|
||||
EXPECT_EQ(0, Call(test->entry(), 0, 1));
|
||||
EXPECT_EQ(-1, Call(test->entry(), 1, -1));
|
||||
EXPECT_EQ(0, Call(test->entry(), 1, 0));
|
||||
EXPECT_EQ(1, Call(test->entry(), 1, 1));
|
||||
|
||||
EXPECT_EQ(4, Call(test->entry(), 2, 2));
|
||||
EXPECT_EQ(5, Call(test->entry(), 3, 3));
|
||||
EXPECT_EQ(16, Call(test->entry(), 4, 4));
|
||||
EXPECT_EQ(20, Call(test->entry(), 6, 6));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(CarrylessMultiplyHigh, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ clmulh(A0, A0, A1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(CarrylessMultiplyHigh, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"0ab53533 clmulh a0, a0, a1\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
#if XLEN == 32
|
||||
EXPECT_EQ(0x55555555, Call(test->entry(), -1, -1));
|
||||
#else
|
||||
EXPECT_EQ(0x5555555555555555, Call(test->entry(), -1, -1));
|
||||
#endif
|
||||
EXPECT_EQ(0, Call(test->entry(), -1, 0));
|
||||
EXPECT_EQ(0, Call(test->entry(), -1, 1));
|
||||
EXPECT_EQ(0, Call(test->entry(), 0, -1));
|
||||
EXPECT_EQ(0, Call(test->entry(), 0, 0));
|
||||
EXPECT_EQ(0, Call(test->entry(), 0, 1));
|
||||
EXPECT_EQ(0, Call(test->entry(), 1, -1));
|
||||
EXPECT_EQ(0, Call(test->entry(), 1, 0));
|
||||
EXPECT_EQ(0, Call(test->entry(), 1, 1));
|
||||
|
||||
EXPECT_EQ(0, Call(test->entry(), 2, 2));
|
||||
EXPECT_EQ(0, Call(test->entry(), 3, 3));
|
||||
EXPECT_EQ(0, Call(test->entry(), 4, 4));
|
||||
EXPECT_EQ(0, Call(test->entry(), 6, 6));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(CarrylessMultiplyReversed, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ clmulr(A0, A0, A1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(CarrylessMultiplyReversed, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"0ab52533 clmulr a0, a0, a1\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
#if XLEN == 32
|
||||
EXPECT_EQ(-0x55555556, Call(test->entry(), -1, -1));
|
||||
#else
|
||||
EXPECT_EQ(-0x5555555555555556, Call(test->entry(), -1, -1));
|
||||
#endif
|
||||
EXPECT_EQ(0, Call(test->entry(), -1, 0));
|
||||
EXPECT_EQ(1, Call(test->entry(), -1, 1));
|
||||
EXPECT_EQ(0, Call(test->entry(), 0, -1));
|
||||
EXPECT_EQ(0, Call(test->entry(), 0, 0));
|
||||
EXPECT_EQ(0, Call(test->entry(), 0, 1));
|
||||
EXPECT_EQ(1, Call(test->entry(), 1, -1));
|
||||
EXPECT_EQ(0, Call(test->entry(), 1, 0));
|
||||
EXPECT_EQ(0, Call(test->entry(), 1, 1));
|
||||
|
||||
EXPECT_EQ(0, Call(test->entry(), 2, 2));
|
||||
EXPECT_EQ(0, Call(test->entry(), 3, 3));
|
||||
EXPECT_EQ(0, Call(test->entry(), 4, 4));
|
||||
EXPECT_EQ(0, Call(test->entry(), 6, 6));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(BitClear, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ bclr(A0, A0, A1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(BitClear, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"48b51533 bclr a0, a0, a1\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(42, Call(test->entry(), 42, 0));
|
||||
EXPECT_EQ(40, Call(test->entry(), 42, 1));
|
||||
EXPECT_EQ(42, Call(test->entry(), 42, 2));
|
||||
EXPECT_EQ(34, Call(test->entry(), 42, 3));
|
||||
EXPECT_EQ(42, Call(test->entry(), 42, 4));
|
||||
EXPECT_EQ(10, Call(test->entry(), 42, 5));
|
||||
EXPECT_EQ(42, Call(test->entry(), 42, 6));
|
||||
EXPECT_EQ(42, Call(test->entry(), 42, 7));
|
||||
EXPECT_EQ(42, Call(test->entry(), 42, 8));
|
||||
|
||||
EXPECT_EQ(42, Call(test->entry(), 42, 64));
|
||||
EXPECT_EQ(40, Call(test->entry(), 42, 65));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(BitClearImmediate, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ bclri(A0, A0, 3);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(BitClearImmediate, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"48351513 bclri a0, a0, 0x3\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(0, Call(test->entry(), 0));
|
||||
EXPECT_EQ(7, Call(test->entry(), 7));
|
||||
EXPECT_EQ(0, Call(test->entry(), 8));
|
||||
EXPECT_EQ(1, Call(test->entry(), 9));
|
||||
EXPECT_EQ(-15, Call(test->entry(), -7));
|
||||
EXPECT_EQ(-16, Call(test->entry(), -8));
|
||||
EXPECT_EQ(-9, Call(test->entry(), -9));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(BitClearImmediate2, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ bclri(A0, A0, XLEN - 1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(BitClearImmediate2, test) {
|
||||
#if XLEN == 32
|
||||
EXPECT_DISASSEMBLY(
|
||||
"49f51513 bclri a0, a0, 0x1f\n"
|
||||
" 8082 ret\n");
|
||||
#elif XLEN == 64
|
||||
EXPECT_DISASSEMBLY(
|
||||
"4bf51513 bclri a0, a0, 0x3f\n"
|
||||
" 8082 ret\n");
|
||||
#endif
|
||||
|
||||
EXPECT_EQ(0, Call(test->entry(), 0));
|
||||
EXPECT_EQ(1, Call(test->entry(), 1));
|
||||
EXPECT_EQ(kMaxIntX, Call(test->entry(), -1));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(BitExtract, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ bext(A0, A0, A1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(BitExtract, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"48b55533 bext a0, a0, a1\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(0, Call(test->entry(), 42, 0));
|
||||
EXPECT_EQ(1, Call(test->entry(), 42, 1));
|
||||
EXPECT_EQ(0, Call(test->entry(), 42, 2));
|
||||
EXPECT_EQ(1, Call(test->entry(), 42, 3));
|
||||
EXPECT_EQ(0, Call(test->entry(), 42, 4));
|
||||
EXPECT_EQ(1, Call(test->entry(), 42, 5));
|
||||
EXPECT_EQ(0, Call(test->entry(), 42, 6));
|
||||
EXPECT_EQ(0, Call(test->entry(), 42, 7));
|
||||
EXPECT_EQ(0, Call(test->entry(), 42, 8));
|
||||
|
||||
EXPECT_EQ(0, Call(test->entry(), 42, 64));
|
||||
EXPECT_EQ(1, Call(test->entry(), 42, 65));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(BitExtractImmediate, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ bexti(A0, A0, 3);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(BitExtractImmediate, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"48355513 bexti a0, a0, 0x3\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(0, Call(test->entry(), 0));
|
||||
EXPECT_EQ(0, Call(test->entry(), 7));
|
||||
EXPECT_EQ(1, Call(test->entry(), 8));
|
||||
EXPECT_EQ(1, Call(test->entry(), 9));
|
||||
EXPECT_EQ(1, Call(test->entry(), -7));
|
||||
EXPECT_EQ(1, Call(test->entry(), -8));
|
||||
EXPECT_EQ(0, Call(test->entry(), -9));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(BitExtractImmediate2, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ bexti(A0, A0, XLEN - 1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(BitExtractImmediate2, test) {
|
||||
#if XLEN == 32
|
||||
EXPECT_DISASSEMBLY(
|
||||
"49f55513 bexti a0, a0, 0x1f\n"
|
||||
" 8082 ret\n");
|
||||
#elif XLEN == 64
|
||||
EXPECT_DISASSEMBLY(
|
||||
"4bf55513 bexti a0, a0, 0x3f\n"
|
||||
" 8082 ret\n");
|
||||
#endif
|
||||
|
||||
EXPECT_EQ(0, Call(test->entry(), 0));
|
||||
EXPECT_EQ(0, Call(test->entry(), 1));
|
||||
EXPECT_EQ(1, Call(test->entry(), -1));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(BitInvert, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ binv(A0, A0, A1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(BitInvert, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"68b51533 binv a0, a0, a1\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(43, Call(test->entry(), 42, 0));
|
||||
EXPECT_EQ(40, Call(test->entry(), 42, 1));
|
||||
EXPECT_EQ(46, Call(test->entry(), 42, 2));
|
||||
EXPECT_EQ(34, Call(test->entry(), 42, 3));
|
||||
EXPECT_EQ(58, Call(test->entry(), 42, 4));
|
||||
EXPECT_EQ(10, Call(test->entry(), 42, 5));
|
||||
EXPECT_EQ(106, Call(test->entry(), 42, 6));
|
||||
EXPECT_EQ(170, Call(test->entry(), 42, 7));
|
||||
EXPECT_EQ(298, Call(test->entry(), 42, 8));
|
||||
|
||||
EXPECT_EQ(43, Call(test->entry(), 42, 64));
|
||||
EXPECT_EQ(40, Call(test->entry(), 42, 65));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(BitInvertImmediate, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ binvi(A0, A0, 3);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(BitInvertImmediate, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"68351513 binvi a0, a0, 0x3\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(8, Call(test->entry(), 0));
|
||||
EXPECT_EQ(15, Call(test->entry(), 7));
|
||||
EXPECT_EQ(0, Call(test->entry(), 8));
|
||||
EXPECT_EQ(1, Call(test->entry(), 9));
|
||||
EXPECT_EQ(-15, Call(test->entry(), -7));
|
||||
EXPECT_EQ(-16, Call(test->entry(), -8));
|
||||
EXPECT_EQ(-1, Call(test->entry(), -9));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(BitInvertImmediate2, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ binvi(A0, A0, XLEN - 1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(BitInvertImmediate2, test) {
|
||||
#if XLEN == 32
|
||||
EXPECT_DISASSEMBLY(
|
||||
"69f51513 binvi a0, a0, 0x1f\n"
|
||||
" 8082 ret\n");
|
||||
#elif XLEN == 64
|
||||
EXPECT_DISASSEMBLY(
|
||||
"6bf51513 binvi a0, a0, 0x3f\n"
|
||||
" 8082 ret\n");
|
||||
#endif
|
||||
|
||||
EXPECT_EQ(kMinIntX, Call(test->entry(), 0));
|
||||
EXPECT_EQ(kMinIntX + 1, Call(test->entry(), 1));
|
||||
EXPECT_EQ(kMaxIntX, Call(test->entry(), -1));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(BitSet, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ bset(A0, A0, A1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(BitSet, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"28b51533 bset a0, a0, a1\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(43, Call(test->entry(), 42, 0));
|
||||
EXPECT_EQ(42, Call(test->entry(), 42, 1));
|
||||
EXPECT_EQ(46, Call(test->entry(), 42, 2));
|
||||
EXPECT_EQ(42, Call(test->entry(), 42, 3));
|
||||
EXPECT_EQ(58, Call(test->entry(), 42, 4));
|
||||
EXPECT_EQ(42, Call(test->entry(), 42, 5));
|
||||
EXPECT_EQ(106, Call(test->entry(), 42, 6));
|
||||
EXPECT_EQ(170, Call(test->entry(), 42, 7));
|
||||
EXPECT_EQ(298, Call(test->entry(), 42, 8));
|
||||
|
||||
EXPECT_EQ(43, Call(test->entry(), 42, 64));
|
||||
EXPECT_EQ(42, Call(test->entry(), 42, 65));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(BitSetImmediate, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ bseti(A0, A0, 3);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(BitSetImmediate, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"28351513 bseti a0, a0, 0x3\n"
|
||||
" 8082 ret\n");
|
||||
|
||||
EXPECT_EQ(8, Call(test->entry(), 0));
|
||||
EXPECT_EQ(15, Call(test->entry(), 7));
|
||||
EXPECT_EQ(8, Call(test->entry(), 8));
|
||||
EXPECT_EQ(9, Call(test->entry(), 9));
|
||||
EXPECT_EQ(-7, Call(test->entry(), -7));
|
||||
EXPECT_EQ(-8, Call(test->entry(), -8));
|
||||
EXPECT_EQ(-1, Call(test->entry(), -9));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(BitSetImmediate2, assembler) {
|
||||
__ SetExtensions(RV_GCB);
|
||||
__ bseti(A0, A0, XLEN - 1);
|
||||
__ ret();
|
||||
}
|
||||
ASSEMBLER_TEST_RUN(BitSetImmediate2, test) {
|
||||
#if XLEN == 32
|
||||
EXPECT_DISASSEMBLY(
|
||||
"29f51513 bseti a0, a0, 0x1f\n"
|
||||
" 8082 ret\n");
|
||||
#elif XLEN == 64
|
||||
EXPECT_DISASSEMBLY(
|
||||
"2bf51513 bseti a0, a0, 0x3f\n"
|
||||
" 8082 ret\n");
|
||||
#endif
|
||||
|
||||
EXPECT_EQ(kMinIntX, Call(test->entry(), 0));
|
||||
EXPECT_EQ(kMinIntX + 1, Call(test->entry(), 1));
|
||||
EXPECT_EQ(-1, Call(test->entry(), -1));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(LoadImmediate_MaxInt32, assembler) {
|
||||
FLAG_use_compressed_instructions = true;
|
||||
__ SetExtensions(RV_GC);
|
||||
|
@ -6346,6 +7292,7 @@ ASSEMBLER_TEST_RUN(AddBranchOverflow_NonDestructive, test) {
|
|||
EXPECT_EQ(kMinIntX + 1, Call(test->entry(), 42, kMinIntX, 1));
|
||||
EXPECT_EQ(kMinIntX, Call(test->entry(), 42, kMinIntX, 0));
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_GENERATE(AddBranchOverflow_Destructive, assembler) {
|
||||
FLAG_use_compressed_instructions = true;
|
||||
__ SetExtensions(RV_GC);
|
||||
|
@ -6357,7 +7304,6 @@ ASSEMBLER_TEST_GENERATE(AddBranchOverflow_Destructive, assembler) {
|
|||
__ li(A0, 0);
|
||||
__ ret();
|
||||
}
|
||||
|
||||
ASSEMBLER_TEST_RUN(AddBranchOverflow_Destructive, test) {
|
||||
EXPECT_DISASSEMBLY(
|
||||
"00052693 slti tmp, a0, 0\n"
|
||||
|
|
|
@ -65,10 +65,17 @@ class RISCVDisassembler {
|
|||
void DisassembleOP_0(Instr instr);
|
||||
void DisassembleOP_SUB(Instr instr);
|
||||
void DisassembleOP_MULDIV(Instr instr);
|
||||
void DisassembleOP_SHADD(Instr instr);
|
||||
void DisassembleOP_MINMAXCLMUL(Instr instr);
|
||||
void DisassembleOP_ROTATE(Instr instr);
|
||||
void DisassembleOP_BCLRBEXT(Instr instr);
|
||||
void DisassembleOP32(Instr instr);
|
||||
void DisassembleOP32_0(Instr instr);
|
||||
void DisassembleOP32_SUB(Instr instr);
|
||||
void DisassembleOP32_MULDIV(Instr instr);
|
||||
void DisassembleOP32_SHADD(Instr instr);
|
||||
void DisassembleOP32_ADDUW(Instr instr);
|
||||
void DisassembleOP32_ROTATE(Instr instr);
|
||||
void DisassembleMISCMEM(Instr instr);
|
||||
void DisassembleSYSTEM(Instr instr);
|
||||
void DisassembleAMO(Instr instr);
|
||||
|
@ -579,11 +586,46 @@ void RISCVDisassembler::DisassembleOPIMM(Instr instr) {
|
|||
Print("andi 'rd, 'rs1, 'iimm", instr, RV_I);
|
||||
break;
|
||||
case SLLI:
|
||||
Print("slli 'rd, 'rs1, 'shamt", instr, RV_I);
|
||||
if (instr.funct7() == COUNT) {
|
||||
if (instr.shamt() == 0b00000) {
|
||||
Print("clz 'rd, 'rs1", instr, RV_Zbb);
|
||||
} else if (instr.shamt() == 0b00001) {
|
||||
Print("ctz 'rd, 'rs1", instr, RV_Zbb);
|
||||
} else if (instr.shamt() == 0b00010) {
|
||||
Print("cpop 'rd, 'rs1", instr, RV_Zbb);
|
||||
} else if (instr.shamt() == 0b00100) {
|
||||
Print("sext.b 'rd, 'rs1", instr, RV_Zbb);
|
||||
} else if (instr.shamt() == 0b00101) {
|
||||
Print("sext.h 'rd, 'rs1", instr, RV_Zbb);
|
||||
} else {
|
||||
UnknownInstruction(instr);
|
||||
}
|
||||
} else if ((instr.funct7() & 0b1111110) == BCLRBEXT) {
|
||||
Print("bclri 'rd, 'rs1, 'shamt", instr, RV_Zbs);
|
||||
} else if ((instr.funct7() & 0b1111110) == BINV) {
|
||||
Print("binvi 'rd, 'rs1, 'shamt", instr, RV_Zbs);
|
||||
} else if ((instr.funct7() & 0b1111110) == BSET) {
|
||||
Print("bseti 'rd, 'rs1, 'shamt", instr, RV_Zbs);
|
||||
} else {
|
||||
Print("slli 'rd, 'rs1, 'shamt", instr, RV_I);
|
||||
}
|
||||
break;
|
||||
case SRI:
|
||||
if ((instr.funct7() & 0b1111110) == SRA) {
|
||||
Print("srai 'rd, 'rs1, 'shamt", instr, RV_I);
|
||||
} else if ((instr.funct7() & 0b1111110) == ROTATE) {
|
||||
Print("rori 'rd, 'rs1, 'shamt", instr, RV_Zbb);
|
||||
} else if (instr.funct7() == 0b0010100) {
|
||||
Print("orc.b 'rd, 'rs1", instr, RV_Zbb);
|
||||
#if XLEN == 32
|
||||
} else if (instr.funct7() == 0b0110100) {
|
||||
Print("rev8 'rd, 'rs1", instr, RV_Zbb);
|
||||
#else
|
||||
} else if (instr.funct7() == 0b0110101) {
|
||||
Print("rev8 'rd, 'rs1", instr, RV_Zbb);
|
||||
#endif
|
||||
} else if ((instr.funct7() & 0b1111110) == BCLRBEXT) {
|
||||
Print("bexti 'rd, 'rs1, 'shamt", instr, RV_Zbs);
|
||||
} else {
|
||||
Print("srli 'rd, 'rs1, 'shamt", instr, RV_I);
|
||||
}
|
||||
|
@ -604,11 +646,27 @@ void RISCVDisassembler::DisassembleOPIMM32(Instr instr) {
|
|||
}
|
||||
break;
|
||||
case SLLI:
|
||||
Print("slliw 'rd, 'rs1, 'shamt", instr, RV_I);
|
||||
if (instr.funct7() == SLLIUW) {
|
||||
Print("slli.uw 'rd, 'rs1, 'shamt", instr, RV_Zba);
|
||||
} else if (instr.funct7() == COUNT) {
|
||||
if (instr.shamt() == 0b00000) {
|
||||
Print("clzw 'rd, 'rs1", instr, RV_Zbb);
|
||||
} else if (instr.shamt() == 0b00001) {
|
||||
Print("ctzw 'rd, 'rs1", instr, RV_Zbb);
|
||||
} else if (instr.shamt() == 0b00010) {
|
||||
Print("cpopw 'rd, 'rs1", instr, RV_Zbb);
|
||||
} else {
|
||||
UnknownInstruction(instr);
|
||||
}
|
||||
} else {
|
||||
Print("slliw 'rd, 'rs1, 'shamt", instr, RV_I);
|
||||
}
|
||||
break;
|
||||
case SRI:
|
||||
if (instr.funct7() == SRA) {
|
||||
Print("sraiw 'rd, 'rs1, 'shamt", instr, RV_I);
|
||||
} else if (instr.funct7() == ROTATE) {
|
||||
Print("roriw 'rd, 'rs1, 'shamt", instr, RV_Zbb);
|
||||
} else {
|
||||
Print("srliw 'rd, 'rs1, 'shamt", instr, RV_I);
|
||||
}
|
||||
|
@ -630,6 +688,29 @@ void RISCVDisassembler::DisassembleOP(Instr instr) {
|
|||
case MULDIV:
|
||||
DisassembleOP_MULDIV(instr);
|
||||
break;
|
||||
case SHADD:
|
||||
DisassembleOP_SHADD(instr);
|
||||
break;
|
||||
case MINMAXCLMUL:
|
||||
DisassembleOP_MINMAXCLMUL(instr);
|
||||
break;
|
||||
case ROTATE:
|
||||
DisassembleOP_ROTATE(instr);
|
||||
break;
|
||||
case BCLRBEXT:
|
||||
DisassembleOP_BCLRBEXT(instr);
|
||||
break;
|
||||
case BINV:
|
||||
Print("binv 'rd, 'rs1, 'rs2", instr, RV_Zbs);
|
||||
break;
|
||||
case BSET:
|
||||
Print("bset 'rd, 'rs1, 'rs2", instr, RV_Zbs);
|
||||
break;
|
||||
#if XLEN == 32
|
||||
case 0b0000100:
|
||||
Print("zext.h 'rd, 'rs1", instr, RV_Zbb);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
UnknownInstruction(instr);
|
||||
}
|
||||
|
@ -688,6 +769,15 @@ void RISCVDisassembler::DisassembleOP_SUB(Instr instr) {
|
|||
case SR:
|
||||
Print("sra 'rd, 'rs1, 'rs2", instr, RV_I);
|
||||
break;
|
||||
case AND:
|
||||
Print("andn 'rd, 'rs1, 'rs2", instr, RV_Zbb);
|
||||
break;
|
||||
case OR:
|
||||
Print("orn 'rd, 'rs1, 'rs2", instr, RV_Zbb);
|
||||
break;
|
||||
case XOR:
|
||||
Print("xnor 'rd, 'rs1, 'rs2", instr, RV_Zbb);
|
||||
break;
|
||||
default:
|
||||
UnknownInstruction(instr);
|
||||
}
|
||||
|
@ -724,6 +814,76 @@ void RISCVDisassembler::DisassembleOP_MULDIV(Instr instr) {
|
|||
}
|
||||
}
|
||||
|
||||
void RISCVDisassembler::DisassembleOP_SHADD(Instr instr) {
|
||||
switch (instr.funct3()) {
|
||||
case SH1ADD:
|
||||
Print("sh1add 'rd, 'rs1, 'rs2", instr, RV_Zba);
|
||||
break;
|
||||
case SH2ADD:
|
||||
Print("sh2add 'rd, 'rs1, 'rs2", instr, RV_Zba);
|
||||
break;
|
||||
case SH3ADD:
|
||||
Print("sh3add 'rd, 'rs1, 'rs2", instr, RV_Zba);
|
||||
break;
|
||||
default:
|
||||
UnknownInstruction(instr);
|
||||
}
|
||||
}
|
||||
|
||||
void RISCVDisassembler::DisassembleOP_MINMAXCLMUL(Instr instr) {
|
||||
switch (instr.funct3()) {
|
||||
case MAX:
|
||||
Print("max 'rd, 'rs1, 'rs2", instr, RV_Zbb);
|
||||
break;
|
||||
case MAXU:
|
||||
Print("maxu 'rd, 'rs1, 'rs2", instr, RV_Zbb);
|
||||
break;
|
||||
case MIN:
|
||||
Print("min 'rd, 'rs1, 'rs2", instr, RV_Zbb);
|
||||
break;
|
||||
case MINU:
|
||||
Print("minu 'rd, 'rs1, 'rs2", instr, RV_Zbb);
|
||||
break;
|
||||
case CLMUL:
|
||||
Print("clmul 'rd, 'rs1, 'rs2", instr, RV_Zbc);
|
||||
break;
|
||||
case CLMULH:
|
||||
Print("clmulh 'rd, 'rs1, 'rs2", instr, RV_Zbc);
|
||||
break;
|
||||
case CLMULR:
|
||||
Print("clmulr 'rd, 'rs1, 'rs2", instr, RV_Zbc);
|
||||
break;
|
||||
default:
|
||||
UnknownInstruction(instr);
|
||||
}
|
||||
}
|
||||
|
||||
void RISCVDisassembler::DisassembleOP_ROTATE(Instr instr) {
|
||||
switch (instr.funct3()) {
|
||||
case ROR:
|
||||
Print("ror 'rd, 'rs1, 'rs2", instr, RV_Zbb);
|
||||
break;
|
||||
case ROL:
|
||||
Print("rol 'rd, 'rs1, 'rs2", instr, RV_Zbb);
|
||||
break;
|
||||
default:
|
||||
UnknownInstruction(instr);
|
||||
}
|
||||
}
|
||||
|
||||
void RISCVDisassembler::DisassembleOP_BCLRBEXT(Instr instr) {
|
||||
switch (instr.funct3()) {
|
||||
case BCLR:
|
||||
Print("bclr 'rd, 'rs1, 'rs2", instr, RV_Zbs);
|
||||
break;
|
||||
case BEXT:
|
||||
Print("bext 'rd, 'rs1, 'rs2", instr, RV_Zbs);
|
||||
break;
|
||||
default:
|
||||
UnknownInstruction(instr);
|
||||
}
|
||||
}
|
||||
|
||||
void RISCVDisassembler::DisassembleOP32(Instr instr) {
|
||||
switch (instr.funct7()) {
|
||||
case 0:
|
||||
|
@ -735,6 +895,15 @@ void RISCVDisassembler::DisassembleOP32(Instr instr) {
|
|||
case MULDIV:
|
||||
DisassembleOP32_MULDIV(instr);
|
||||
break;
|
||||
case SHADD:
|
||||
DisassembleOP32_SHADD(instr);
|
||||
break;
|
||||
case ADDUW:
|
||||
DisassembleOP32_ADDUW(instr);
|
||||
break;
|
||||
case ROTATE:
|
||||
DisassembleOP32_ROTATE(instr);
|
||||
break;
|
||||
default:
|
||||
UnknownInstruction(instr);
|
||||
}
|
||||
|
@ -802,6 +971,50 @@ void RISCVDisassembler::DisassembleOP32_MULDIV(Instr instr) {
|
|||
}
|
||||
}
|
||||
|
||||
void RISCVDisassembler::DisassembleOP32_SHADD(Instr instr) {
|
||||
switch (instr.funct3()) {
|
||||
case SH1ADD:
|
||||
Print("sh1add.uw 'rd, 'rs1, 'rs2", instr, RV_Zba);
|
||||
break;
|
||||
case SH2ADD:
|
||||
Print("sh2add.uw 'rd, 'rs1, 'rs2", instr, RV_Zba);
|
||||
break;
|
||||
case SH3ADD:
|
||||
Print("sh3add.uw 'rd, 'rs1, 'rs2", instr, RV_Zba);
|
||||
break;
|
||||
default:
|
||||
UnknownInstruction(instr);
|
||||
}
|
||||
}
|
||||
|
||||
void RISCVDisassembler::DisassembleOP32_ADDUW(Instr instr) {
|
||||
switch (instr.funct3()) {
|
||||
#if XLEN >= 64
|
||||
case F3_0:
|
||||
Print("add.uw 'rd, 'rs1, 'rs2", instr, RV_Zba);
|
||||
break;
|
||||
case ZEXT:
|
||||
Print("zext.h 'rd, 'rs1", instr, RV_Zbb);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
UnknownInstruction(instr);
|
||||
}
|
||||
}
|
||||
|
||||
void RISCVDisassembler::DisassembleOP32_ROTATE(Instr instr) {
|
||||
switch (instr.funct3()) {
|
||||
case ROR:
|
||||
Print("rorw 'rd, 'rs1, 'rs2", instr, RV_Zbb);
|
||||
break;
|
||||
case ROL:
|
||||
Print("rolw 'rd, 'rs1, 'rs2", instr, RV_Zbb);
|
||||
break;
|
||||
default:
|
||||
UnknownInstruction(instr);
|
||||
}
|
||||
}
|
||||
|
||||
void RISCVDisassembler::DisassembleMISCMEM(Instr instr) {
|
||||
switch (instr.funct3()) {
|
||||
case FENCE:
|
||||
|
@ -1076,10 +1289,10 @@ void RISCVDisassembler::DisassembleOPFP(Instr instr) {
|
|||
}
|
||||
case FMINMAXS: {
|
||||
switch (instr.funct3()) {
|
||||
case MIN:
|
||||
case FMIN:
|
||||
Print("fmin.s 'frd, 'frs1, 'frs2", instr, RV_F);
|
||||
break;
|
||||
case MAX:
|
||||
case FMAX:
|
||||
Print("fmax.s 'frd, 'frs1, 'frs2", instr, RV_F);
|
||||
break;
|
||||
default:
|
||||
|
@ -1203,10 +1416,10 @@ void RISCVDisassembler::DisassembleOPFP(Instr instr) {
|
|||
}
|
||||
case FMINMAXD: {
|
||||
switch (instr.funct3()) {
|
||||
case MIN:
|
||||
case FMIN:
|
||||
Print("fmin.d 'frd, 'frs1, 'frs2", instr, RV_D);
|
||||
break;
|
||||
case MAX:
|
||||
case FMAX:
|
||||
Print("fmax.d 'frd, 'frs1, 'frs2", instr, RV_D);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -780,11 +780,36 @@ enum Funct3 {
|
|||
J = 0b000,
|
||||
JN = 0b001,
|
||||
JX = 0b010,
|
||||
MIN = 0b000,
|
||||
MAX = 0b001,
|
||||
FMIN = 0b000,
|
||||
FMAX = 0b001,
|
||||
FEQ = 0b010,
|
||||
FLT = 0b001,
|
||||
FLE = 0b000,
|
||||
|
||||
SH1ADD = 0b010,
|
||||
SH2ADD = 0b100,
|
||||
SH3ADD = 0b110,
|
||||
|
||||
F3_COUNT = 0b001,
|
||||
|
||||
MAX = 0b110,
|
||||
MAXU = 0b111,
|
||||
MIN = 0b100,
|
||||
MINU = 0b101,
|
||||
CLMUL = 0b001,
|
||||
CLMULH = 0b011,
|
||||
CLMULR = 0b010,
|
||||
|
||||
SEXT = 0b001,
|
||||
ZEXT = 0b100,
|
||||
|
||||
ROL = 0b001,
|
||||
ROR = 0b101,
|
||||
|
||||
BCLR = 0b001,
|
||||
BEXT = 0b101,
|
||||
F3_BINV = 0b001,
|
||||
F3_BSET = 0b001,
|
||||
};
|
||||
|
||||
enum Funct7 {
|
||||
|
@ -822,6 +847,16 @@ enum Funct7 {
|
|||
FCVTDint = 0b1101001,
|
||||
FMVXD = 0b1110001,
|
||||
FMVDX = 0b1111001,
|
||||
|
||||
ADDUW = 0b0000100,
|
||||
SHADD = 0b0010000,
|
||||
SLLIUW = 0b0000100,
|
||||
COUNT = 0b0110000,
|
||||
MINMAXCLMUL = 0b0000101,
|
||||
ROTATE = 0b0110000,
|
||||
BCLRBEXT = 0b0100100,
|
||||
BINV = 0b0110100,
|
||||
BSET = 0b0010100,
|
||||
};
|
||||
|
||||
enum Funct5 {
|
||||
|
@ -1515,6 +1550,12 @@ static constexpr Extension RV_D(4); // Double-precision floating point
|
|||
static constexpr Extension RV_C(5); // Compressed instructions
|
||||
static constexpr ExtensionSet RV_G = RV_I | RV_M | RV_A | RV_F | RV_D;
|
||||
static constexpr ExtensionSet RV_GC = RV_G | RV_C;
|
||||
static constexpr Extension RV_Zba(6); // Address generation
|
||||
static constexpr Extension RV_Zbb(7); // Basic bit-manipulation
|
||||
static constexpr Extension RV_Zbc(8); // Carry-less multiplicatio
|
||||
static constexpr Extension RV_Zbs(9); // Single-bit instructions
|
||||
static constexpr ExtensionSet RV_B = RV_Zba | RV_Zbb | RV_Zbc | RV_Zbs;
|
||||
static constexpr ExtensionSet RV_GCB = RV_GC | RV_B;
|
||||
|
||||
#undef R
|
||||
|
||||
|
|
|
@ -1007,6 +1007,162 @@ void Simulator::InterpretSTOREFP(Instr instr) {
|
|||
pc_ += instr.length();
|
||||
}
|
||||
|
||||
static uintx_t clz(uintx_t a) {
|
||||
for (int bit = XLEN - 1; bit >= 0; bit--) {
|
||||
if ((a & (static_cast<uintx_t>(1) << bit)) != 0) {
|
||||
return XLEN - bit - 1;
|
||||
}
|
||||
}
|
||||
return XLEN;
|
||||
}
|
||||
|
||||
static uintx_t ctz(uintx_t a) {
|
||||
for (int bit = 0; bit < XLEN; bit++) {
|
||||
if ((a & (static_cast<uintx_t>(1) << bit)) != 0) {
|
||||
return bit;
|
||||
}
|
||||
}
|
||||
return XLEN;
|
||||
}
|
||||
|
||||
static uintx_t cpop(uintx_t a) {
|
||||
uintx_t count = 0;
|
||||
for (int bit = 0; bit < XLEN; bit++) {
|
||||
if ((a & (static_cast<uintx_t>(1) << bit)) != 0) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static uintx_t clzw(uint32_t a) {
|
||||
for (int bit = 32 - 1; bit >= 0; bit--) {
|
||||
if ((a & (static_cast<uint32_t>(1) << bit)) != 0) {
|
||||
return 32 - bit - 1;
|
||||
}
|
||||
}
|
||||
return 32;
|
||||
}
|
||||
|
||||
static uintx_t ctzw(uint32_t a) {
|
||||
for (int bit = 0; bit < 32; bit++) {
|
||||
if ((a & (static_cast<uint32_t>(1) << bit)) != 0) {
|
||||
return bit;
|
||||
}
|
||||
}
|
||||
return 32;
|
||||
}
|
||||
|
||||
static uintx_t cpopw(uint32_t a) {
|
||||
uintx_t count = 0;
|
||||
for (int bit = 0; bit < 32; bit++) {
|
||||
if ((a & (static_cast<uint32_t>(1) << bit)) != 0) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static intx_t max(intx_t a, intx_t b) {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
static uintx_t maxu(uintx_t a, uintx_t b) {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
static intx_t min(intx_t a, intx_t b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
static uintx_t minu(uintx_t a, uintx_t b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
static uintx_t clmul(uintx_t a, uintx_t b) {
|
||||
uintx_t result = 0;
|
||||
for (int bit = 0; bit < XLEN; bit++) {
|
||||
if (((b >> bit) & 1) != 0) {
|
||||
result ^= a << bit;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
static uintx_t clmulh(uintx_t a, uintx_t b) {
|
||||
uintx_t result = 0;
|
||||
for (int bit = 1; bit < XLEN; bit++) {
|
||||
if (((b >> bit) & 1) != 0) {
|
||||
result ^= a >> (XLEN - bit);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
static uintx_t clmulr(uintx_t a, uintx_t b) {
|
||||
uintx_t result = 0;
|
||||
for (int bit = 0; bit < XLEN; bit++) {
|
||||
if (((b >> bit) & 1) != 0) {
|
||||
result ^= a >> (XLEN - bit - 1);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
static uintx_t sextb(uintx_t a) {
|
||||
return static_cast<intx_t>(a << (XLEN - 8)) >> (XLEN - 8);
|
||||
}
|
||||
static uintx_t sexth(uintx_t a) {
|
||||
return static_cast<intx_t>(a << (XLEN - 16)) >> (XLEN - 16);
|
||||
}
|
||||
static uintx_t zexth(uintx_t a) {
|
||||
return a << (XLEN - 16) >> (XLEN - 16);
|
||||
}
|
||||
static uintx_t ror(uintx_t a, uintx_t b) {
|
||||
uintx_t r = b & (XLEN - 1);
|
||||
uintx_t l = (XLEN - r) & (XLEN - 1);
|
||||
return (a << l) | (a >> r);
|
||||
}
|
||||
static uintx_t rol(uintx_t a, uintx_t b) {
|
||||
uintx_t l = b & (XLEN - 1);
|
||||
uintx_t r = (XLEN - l) & (XLEN - 1);
|
||||
return (a << l) | (a >> r);
|
||||
}
|
||||
static uintx_t rorw(uintx_t a, uintx_t b) {
|
||||
uint32_t r = b & (XLEN - 1);
|
||||
uint32_t l = (XLEN - r) & (XLEN - 1);
|
||||
uint32_t x = a;
|
||||
return sign_extend((x << l) | (x >> r));
|
||||
}
|
||||
static uintx_t rolw(uintx_t a, uintx_t b) {
|
||||
uint32_t l = b & (XLEN - 1);
|
||||
uint32_t r = (XLEN - l) & (XLEN - 1);
|
||||
uint32_t x = a;
|
||||
return sign_extend((x << l) | (x >> r));
|
||||
}
|
||||
static uintx_t orcb(uintx_t a) {
|
||||
uintx_t result = 0;
|
||||
for (int shift = 0; shift < XLEN; shift += 8) {
|
||||
if (((a >> shift) & 0xFF) != 0) {
|
||||
result |= static_cast<uintx_t>(0xFF) << shift;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
static uintx_t rev8(uintx_t a) {
|
||||
uintx_t result = 0;
|
||||
for (int shift = 0; shift < XLEN; shift += 8) {
|
||||
result <<= 8;
|
||||
result |= (a >> shift) & 0xFF;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
static uintx_t bclr(uintx_t a, uintx_t b) {
|
||||
return a & ~(static_cast<uintx_t>(1) << (b & (XLEN - 1)));
|
||||
}
|
||||
static uintx_t bext(uintx_t a, uintx_t b) {
|
||||
return (a >> (b & (XLEN - 1))) & 1;
|
||||
}
|
||||
static uintx_t binv(uintx_t a, uintx_t b) {
|
||||
return a ^ (static_cast<uintx_t>(1) << (b & (XLEN - 1)));
|
||||
}
|
||||
static uintx_t bset(uintx_t a, uintx_t b) {
|
||||
return a | (static_cast<uintx_t>(1) << (b & (XLEN - 1)));
|
||||
}
|
||||
|
||||
DART_FORCE_INLINE
|
||||
void Simulator::InterpretOPIMM(Instr instr) {
|
||||
switch (instr.funct3()) {
|
||||
|
@ -1034,15 +1190,48 @@ void Simulator::InterpretOPIMM(Instr instr) {
|
|||
break;
|
||||
case ANDI:
|
||||
set_xreg(instr.rd(), get_xreg(instr.rs1()) & instr.itype_imm());
|
||||
|
||||
break;
|
||||
case SLLI:
|
||||
set_xreg(instr.rd(), get_xreg(instr.rs1()) << instr.shamt());
|
||||
if (instr.funct7() == COUNT) {
|
||||
if (instr.shamt() == 0b00000) {
|
||||
set_xreg(instr.rd(), clz(get_xreg(instr.rs1())));
|
||||
} else if (instr.shamt() == 0b00001) {
|
||||
set_xreg(instr.rd(), ctz(get_xreg(instr.rs1())));
|
||||
} else if (instr.shamt() == 0b00010) {
|
||||
set_xreg(instr.rd(), cpop(get_xreg(instr.rs1())));
|
||||
} else if (instr.shamt() == 0b00100) {
|
||||
set_xreg(instr.rd(), sextb(get_xreg(instr.rs1())));
|
||||
} else if (instr.shamt() == 0b00101) {
|
||||
set_xreg(instr.rd(), sexth(get_xreg(instr.rs1())));
|
||||
} else {
|
||||
IllegalInstruction(instr);
|
||||
}
|
||||
} else if ((instr.funct7() & 0b1111110) == BCLRBEXT) {
|
||||
set_xreg(instr.rd(), bclr(get_xreg(instr.rs1()), instr.shamt()));
|
||||
} else if ((instr.funct7() & 0b1111110) == BINV) {
|
||||
set_xreg(instr.rd(), binv(get_xreg(instr.rs1()), instr.shamt()));
|
||||
} else if ((instr.funct7() & 0b1111110) == BSET) {
|
||||
set_xreg(instr.rd(), bset(get_xreg(instr.rs1()), instr.shamt()));
|
||||
} else {
|
||||
set_xreg(instr.rd(), get_xreg(instr.rs1()) << instr.shamt());
|
||||
}
|
||||
break;
|
||||
case SRI:
|
||||
if ((instr.funct7() & 0b1111110) == SRA) {
|
||||
set_xreg(instr.rd(),
|
||||
static_cast<intx_t>(get_xreg(instr.rs1())) >> instr.shamt());
|
||||
} else if ((instr.funct7() & 0b1111110) == ROTATE) {
|
||||
set_xreg(instr.rd(), ror(get_xreg(instr.rs1()), instr.shamt()));
|
||||
} else if (instr.funct7() == 0b0010100) {
|
||||
set_xreg(instr.rd(), orcb(get_xreg(instr.rs1())));
|
||||
#if XLEN == 32
|
||||
} else if (instr.funct7() == 0b0110100) {
|
||||
#else
|
||||
} else if (instr.funct7() == 0b0110101) {
|
||||
#endif
|
||||
set_xreg(instr.rd(), rev8(get_xreg(instr.rs1())));
|
||||
} else if ((instr.funct7() & 0b1111110) == BCLRBEXT) {
|
||||
set_xreg(instr.rd(), bext(get_xreg(instr.rs1()), instr.shamt()));
|
||||
} else {
|
||||
set_xreg(instr.rd(),
|
||||
static_cast<uintx_t>(get_xreg(instr.rs1())) >> instr.shamt());
|
||||
|
@ -1064,9 +1253,25 @@ void Simulator::InterpretOPIMM32(Instr instr) {
|
|||
break;
|
||||
}
|
||||
case SLLI: {
|
||||
uint32_t a = get_xreg(instr.rs1());
|
||||
uint32_t b = instr.shamt();
|
||||
set_xreg(instr.rd(), sign_extend(a << b));
|
||||
if (instr.funct7() == SLLIUW) {
|
||||
uintx_t a = static_cast<uint32_t>(get_xreg(instr.rs1()));
|
||||
uintx_t b = instr.shamt();
|
||||
set_xreg(instr.rd(), a << b);
|
||||
} else if (instr.funct7() == COUNT) {
|
||||
if (instr.shamt() == 0b00000) {
|
||||
set_xreg(instr.rd(), clzw(get_xreg(instr.rs1())));
|
||||
} else if (instr.shamt() == 0b00001) {
|
||||
set_xreg(instr.rd(), ctzw(get_xreg(instr.rs1())));
|
||||
} else if (instr.shamt() == 0b00010) {
|
||||
set_xreg(instr.rd(), cpopw(get_xreg(instr.rs1())));
|
||||
} else {
|
||||
IllegalInstruction(instr);
|
||||
}
|
||||
} else {
|
||||
uint32_t a = get_xreg(instr.rs1());
|
||||
uint32_t b = instr.shamt();
|
||||
set_xreg(instr.rd(), sign_extend(a << b));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SRI:
|
||||
|
@ -1074,6 +1279,8 @@ void Simulator::InterpretOPIMM32(Instr instr) {
|
|||
int32_t a = get_xreg(instr.rs1());
|
||||
int32_t b = instr.shamt();
|
||||
set_xreg(instr.rd(), sign_extend(a >> b));
|
||||
} else if (instr.funct7() == ROTATE) {
|
||||
set_xreg(instr.rd(), rorw(get_xreg(instr.rs1()), instr.shamt()));
|
||||
} else {
|
||||
uint32_t a = get_xreg(instr.rs1());
|
||||
uint32_t b = instr.shamt();
|
||||
|
@ -1098,6 +1305,32 @@ void Simulator::InterpretOP(Instr instr) {
|
|||
case MULDIV:
|
||||
InterpretOP_MULDIV(instr);
|
||||
break;
|
||||
case SHADD:
|
||||
InterpretOP_SHADD(instr);
|
||||
break;
|
||||
case MINMAXCLMUL:
|
||||
InterpretOP_MINMAXCLMUL(instr);
|
||||
break;
|
||||
case ROTATE:
|
||||
InterpretOP_ROTATE(instr);
|
||||
break;
|
||||
case BCLRBEXT:
|
||||
InterpretOP_BCLRBEXT(instr);
|
||||
break;
|
||||
case BINV:
|
||||
set_xreg(instr.rd(), binv(get_xreg(instr.rs1()), get_xreg(instr.rs2())));
|
||||
pc_ += instr.length();
|
||||
break;
|
||||
case BSET:
|
||||
set_xreg(instr.rd(), bset(get_xreg(instr.rs1()), get_xreg(instr.rs2())));
|
||||
pc_ += instr.length();
|
||||
break;
|
||||
#if XLEN == 32
|
||||
case 0b0000100:
|
||||
set_xreg(instr.rd(), zexth(get_xreg(instr.rs1())));
|
||||
pc_ += instr.length();
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
IllegalInstruction(instr);
|
||||
}
|
||||
|
@ -1331,6 +1564,98 @@ void Simulator::InterpretOP_SUB(Instr instr) {
|
|||
set_xreg(instr.rd(), static_cast<intx_t>(get_xreg(instr.rs1())) >> shamt);
|
||||
break;
|
||||
}
|
||||
case AND:
|
||||
set_xreg(instr.rd(), get_xreg(instr.rs1()) & ~get_xreg(instr.rs2()));
|
||||
break;
|
||||
case OR:
|
||||
set_xreg(instr.rd(), get_xreg(instr.rs1()) | ~get_xreg(instr.rs2()));
|
||||
break;
|
||||
case XOR:
|
||||
set_xreg(instr.rd(), get_xreg(instr.rs1()) ^ ~get_xreg(instr.rs2()));
|
||||
break;
|
||||
default:
|
||||
IllegalInstruction(instr);
|
||||
}
|
||||
pc_ += instr.length();
|
||||
}
|
||||
|
||||
DART_FORCE_INLINE
|
||||
void Simulator::InterpretOP_SHADD(Instr instr) {
|
||||
switch (instr.funct3()) {
|
||||
case SH1ADD:
|
||||
set_xreg(instr.rd(),
|
||||
(get_xreg(instr.rs1()) << 1) + get_xreg(instr.rs2()));
|
||||
break;
|
||||
case SH2ADD:
|
||||
set_xreg(instr.rd(),
|
||||
(get_xreg(instr.rs1()) << 2) + get_xreg(instr.rs2()));
|
||||
break;
|
||||
case SH3ADD:
|
||||
set_xreg(instr.rd(),
|
||||
(get_xreg(instr.rs1()) << 3) + get_xreg(instr.rs2()));
|
||||
break;
|
||||
default:
|
||||
IllegalInstruction(instr);
|
||||
}
|
||||
pc_ += instr.length();
|
||||
}
|
||||
|
||||
DART_FORCE_INLINE
|
||||
void Simulator::InterpretOP_MINMAXCLMUL(Instr instr) {
|
||||
switch (instr.funct3()) {
|
||||
case MAX:
|
||||
set_xreg(instr.rd(), max(get_xreg(instr.rs1()), get_xreg(instr.rs2())));
|
||||
break;
|
||||
case MAXU:
|
||||
set_xreg(instr.rd(), maxu(get_xreg(instr.rs1()), get_xreg(instr.rs2())));
|
||||
break;
|
||||
case MIN:
|
||||
set_xreg(instr.rd(), min(get_xreg(instr.rs1()), get_xreg(instr.rs2())));
|
||||
break;
|
||||
case MINU:
|
||||
set_xreg(instr.rd(), minu(get_xreg(instr.rs1()), get_xreg(instr.rs2())));
|
||||
break;
|
||||
case CLMUL:
|
||||
set_xreg(instr.rd(), clmul(get_xreg(instr.rs1()), get_xreg(instr.rs2())));
|
||||
break;
|
||||
case CLMULH:
|
||||
set_xreg(instr.rd(),
|
||||
clmulh(get_xreg(instr.rs1()), get_xreg(instr.rs2())));
|
||||
break;
|
||||
case CLMULR:
|
||||
set_xreg(instr.rd(),
|
||||
clmulr(get_xreg(instr.rs1()), get_xreg(instr.rs2())));
|
||||
break;
|
||||
default:
|
||||
IllegalInstruction(instr);
|
||||
}
|
||||
pc_ += instr.length();
|
||||
}
|
||||
|
||||
DART_FORCE_INLINE
|
||||
void Simulator::InterpretOP_ROTATE(Instr instr) {
|
||||
switch (instr.funct3()) {
|
||||
case ROR:
|
||||
set_xreg(instr.rd(), ror(get_xreg(instr.rs1()), get_xreg(instr.rs2())));
|
||||
break;
|
||||
case ROL:
|
||||
set_xreg(instr.rd(), rol(get_xreg(instr.rs1()), get_xreg(instr.rs2())));
|
||||
break;
|
||||
default:
|
||||
IllegalInstruction(instr);
|
||||
}
|
||||
pc_ += instr.length();
|
||||
}
|
||||
|
||||
DART_FORCE_INLINE
|
||||
void Simulator::InterpretOP_BCLRBEXT(Instr instr) {
|
||||
switch (instr.funct3()) {
|
||||
case BCLR:
|
||||
set_xreg(instr.rd(), bclr(get_xreg(instr.rs1()), get_xreg(instr.rs2())));
|
||||
break;
|
||||
case BEXT:
|
||||
set_xreg(instr.rd(), bext(get_xreg(instr.rs1()), get_xreg(instr.rs2())));
|
||||
break;
|
||||
default:
|
||||
IllegalInstruction(instr);
|
||||
}
|
||||
|
@ -1350,6 +1675,15 @@ void Simulator::InterpretOP32(Instr instr) {
|
|||
case MULDIV:
|
||||
InterpretOP32_MULDIV(instr);
|
||||
break;
|
||||
case SHADD:
|
||||
InterpretOP32_SHADD(instr);
|
||||
break;
|
||||
case ADDUW:
|
||||
InterpretOP32_ADDUW(instr);
|
||||
break;
|
||||
case ROTATE:
|
||||
InterpretOP32_ROTATE(instr);
|
||||
break;
|
||||
#endif // XLEN >= 64
|
||||
default:
|
||||
IllegalInstruction(instr);
|
||||
|
@ -1439,6 +1773,68 @@ void Simulator::InterpretOP32_MULDIV(Instr instr) {
|
|||
pc_ += instr.length();
|
||||
}
|
||||
|
||||
DART_FORCE_INLINE
|
||||
void Simulator::InterpretOP32_SHADD(Instr instr) {
|
||||
switch (instr.funct3()) {
|
||||
case SH1ADD: {
|
||||
uintx_t a = static_cast<uint32_t>(get_xreg(instr.rs1()));
|
||||
uintx_t b = get_xreg(instr.rs2());
|
||||
set_xreg(instr.rd(), (a << 1) + b);
|
||||
break;
|
||||
}
|
||||
case SH2ADD: {
|
||||
uintx_t a = static_cast<uint32_t>(get_xreg(instr.rs1()));
|
||||
uintx_t b = get_xreg(instr.rs2());
|
||||
set_xreg(instr.rd(), (a << 2) + b);
|
||||
break;
|
||||
}
|
||||
case SH3ADD: {
|
||||
uintx_t a = static_cast<uint32_t>(get_xreg(instr.rs1()));
|
||||
uintx_t b = get_xreg(instr.rs2());
|
||||
set_xreg(instr.rd(), (a << 3) + b);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
IllegalInstruction(instr);
|
||||
}
|
||||
pc_ += instr.length();
|
||||
}
|
||||
|
||||
DART_FORCE_INLINE
|
||||
void Simulator::InterpretOP32_ADDUW(Instr instr) {
|
||||
switch (instr.funct3()) {
|
||||
#if XLEN >= 64
|
||||
case F3_0: {
|
||||
uintx_t a = static_cast<uint32_t>(get_xreg(instr.rs1()));
|
||||
uintx_t b = get_xreg(instr.rs2());
|
||||
set_xreg(instr.rd(), a + b);
|
||||
break;
|
||||
}
|
||||
case ZEXT:
|
||||
set_xreg(instr.rd(), zexth(get_xreg(instr.rs1())));
|
||||
break;
|
||||
#endif // XLEN >= 64
|
||||
default:
|
||||
IllegalInstruction(instr);
|
||||
}
|
||||
pc_ += instr.length();
|
||||
}
|
||||
|
||||
DART_FORCE_INLINE
|
||||
void Simulator::InterpretOP32_ROTATE(Instr instr) {
|
||||
switch (instr.funct3()) {
|
||||
case ROR:
|
||||
set_xreg(instr.rd(), rorw(get_xreg(instr.rs1()), get_xreg(instr.rs2())));
|
||||
break;
|
||||
case ROL:
|
||||
set_xreg(instr.rd(), rolw(get_xreg(instr.rs1()), get_xreg(instr.rs2())));
|
||||
break;
|
||||
default:
|
||||
IllegalInstruction(instr);
|
||||
}
|
||||
pc_ += instr.length();
|
||||
}
|
||||
|
||||
void Simulator::InterpretMISCMEM(Instr instr) {
|
||||
switch (instr.funct3()) {
|
||||
case FENCE:
|
||||
|
@ -2295,10 +2691,10 @@ void Simulator::InterpretOPFP(Instr instr) {
|
|||
float rs1 = get_fregs(instr.frs1());
|
||||
float rs2 = get_fregs(instr.frs2());
|
||||
switch (instr.funct3()) {
|
||||
case MIN:
|
||||
case FMIN:
|
||||
set_fregs(instr.frd(), rv_fminf(rs1, rs2));
|
||||
break;
|
||||
case MAX:
|
||||
case FMAX:
|
||||
set_fregs(instr.frd(), rv_fmaxf(rs1, rs2));
|
||||
break;
|
||||
default:
|
||||
|
@ -2449,10 +2845,10 @@ void Simulator::InterpretOPFP(Instr instr) {
|
|||
double rs1 = get_fregd(instr.frs1());
|
||||
double rs2 = get_fregd(instr.frs2());
|
||||
switch (instr.funct3()) {
|
||||
case MIN:
|
||||
case FMIN:
|
||||
set_fregd(instr.frd(), rv_fmin(rs1, rs2));
|
||||
break;
|
||||
case MAX:
|
||||
case FMAX:
|
||||
set_fregd(instr.frd(), rv_fmax(rs1, rs2));
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -208,10 +208,17 @@ class Simulator {
|
|||
void InterpretOP_0(Instr instr);
|
||||
void InterpretOP_SUB(Instr instr);
|
||||
void InterpretOP_MULDIV(Instr instr);
|
||||
void InterpretOP_SHADD(Instr instr);
|
||||
void InterpretOP_MINMAXCLMUL(Instr instr);
|
||||
void InterpretOP_ROTATE(Instr instr);
|
||||
void InterpretOP_BCLRBEXT(Instr instr);
|
||||
void InterpretOP32(Instr instr);
|
||||
void InterpretOP32_0(Instr instr);
|
||||
void InterpretOP32_SUB(Instr instr);
|
||||
void InterpretOP32_MULDIV(Instr instr);
|
||||
void InterpretOP32_SHADD(Instr instr);
|
||||
void InterpretOP32_ADDUW(Instr instr);
|
||||
void InterpretOP32_ROTATE(Instr instr);
|
||||
void InterpretMISCMEM(Instr instr);
|
||||
void InterpretSYSTEM(Instr instr);
|
||||
void InterpretECALL(Instr instr);
|
||||
|
|
Loading…
Reference in a new issue