lh03061238 created this revision.
lh03061238 added reviewers: SixWeining, wangleiat, xen0n, xry111, MaskRay,
seehearfeel, DavidSpickett.
Herald added a subscriber: StephenFan.
Herald added a project: All.
lh03061238 requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.
Add floating-point branch Instructions for EmulateInstructionLoongArch and
add relevant unit tests.
Without this patch:
$ ninja check-lldb-unit
[0/1] Running lldb unit test suite
Testing Time: 10.45s
Passed: 1044
With this patch:
$ ninja check-lldb-unit
[0/1] Running lldb unit test suite
Testing Time: 10.20s
Passed: 1048
Depends on D140615 <https://reviews.llvm.org/D140615> and D140386
<https://reviews.llvm.org/D140386>
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D140759
Files:
lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.cpp
lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.h
lldb/unittests/Instruction/LoongArch/TestLoongArchEmulator.cpp
Index: lldb/unittests/Instruction/LoongArch/TestLoongArchEmulator.cpp
===================================================================
--- lldb/unittests/Instruction/LoongArch/TestLoongArchEmulator.cpp
+++ lldb/unittests/Instruction/LoongArch/TestLoongArchEmulator.cpp
@@ -38,6 +38,14 @@
testBZcondBranch(this, name, false, rj_val_continued); \
}
+#define GEN_BCZCOND_TEST(bit, name, cj_val_branched, cj_val_continued) \
+ TEST_F(LoongArch##bit##EmulatorTester, test##name##branched) { \
+ testBCZcondBranch(this, name, true, cj_val_branched); \
+ } \
+ TEST_F(LoongArch##bit##EmulatorTester, test##name##continued) { \
+ testBCZcondBranch(this, name, false, cj_val_continued); \
+ }
+
struct LoongArch64EmulatorTester : public EmulateInstructionLoongArch,
testing::Test {
RegisterInfoPOSIX_loongarch64::GPR gpr;
@@ -136,8 +144,26 @@
return EncodeBZcondType(0b010001, rj, uint32_t(offs21));
}
+// BCEQZ BCNEZ
+static uint32_t EncodeBCZcondType(uint32_t opcode, uint8_t cj, uint8_t bcxxz,
+ uint32_t offs21) {
+ uint32_t offs20_16 = (offs21 & 0x001f0000) >> 16;
+ uint32_t offs15_0 = offs21 & 0x0000ffff;
+ bcxxz = bcxxz & 0b00000011;
+ return opcode << 26 | offs15_0 << 10 | bcxxz << 8 | cj << 5 | offs20_16;
+}
+
+static uint32_t BCEQZ(uint8_t cj, int32_t offs21) {
+ return EncodeBCZcondType(0b010010, cj, 0b00, uint32_t(offs21));
+}
+
+static uint32_t BCNEZ(uint8_t cj, int32_t offs21) {
+ return EncodeBCZcondType(0b010010, cj, 0b01, uint32_t(offs21));
+}
+
using EncoderBcond = uint32_t (*)(uint32_t rj, uint32_t rd, int32_t offs16);
using EncoderBZcond = uint32_t (*)(uint32_t rj, int32_t offs21);
+using EncoderBCZcond = uint32_t (*)(uint8_t cj, int32_t offs21);
TEST_F(LoongArch64EmulatorTester, testJIRL) {
bool success = false;
@@ -220,6 +246,21 @@
ASSERT_EQ(pc, old_pc + (branched ? (-256 * 4) : 4));
}
+static void testBCZcondBranch(LoongArch64EmulatorTester *tester,
+ EncoderBCZcond encoder, bool branched,
+ uint32_t cj_val) {
+ bool success = false;
+ addr_t old_pc = 0x12000600;
+ tester->WritePC(old_pc);
+ tester->fpr.fcc = cj_val;
+ // bc<cmp>z fcc0, (256)
+ uint32_t inst = encoder(0, 256);
+ ASSERT_TRUE(tester->TestExecute(inst));
+ auto pc = tester->ReadPC(&success);
+ ASSERT_TRUE(success);
+ ASSERT_EQ(pc, old_pc + (branched ? (256 * 4) : 4));
+}
+
GEN_BCOND_TEST(64, BEQ, 1, 1, 0)
GEN_BCOND_TEST(64, BNE, 1, 0, 1)
GEN_BCOND_TEST(64, BLT, -2, 1, -3)
@@ -228,3 +269,5 @@
GEN_BCOND_TEST(64, BGEU, -2, 1, -1)
GEN_BZCOND_TEST(64, BEQZ, 0, 1)
GEN_BZCOND_TEST(64, BNEZ, 1, 0)
+GEN_BCZCOND_TEST(64, BCEQZ, 0, 1)
+GEN_BCZCOND_TEST(64, BCNEZ, 1, 0)
Index: lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.h
===================================================================
--- lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.h
+++ lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.h
@@ -74,6 +74,7 @@
bool EmulateBEQZ(uint32_t inst);
bool EmulateBNEZ(uint32_t inst);
+ bool EmulateBCXXZ(uint32_t inst);
bool EmulateJIRL(uint32_t inst);
bool EmulateB(uint32_t inst);
bool EmulateBL(uint32_t inst);
@@ -87,6 +88,7 @@
bool EmulateBEQZ64(uint32_t inst);
bool EmulateBNEZ64(uint32_t inst);
+ bool EmulateBCXXZ64(uint32_t inst);
bool EmulateJIRL64(uint32_t inst);
bool EmulateB64(uint32_t inst);
bool EmulateBL64(uint32_t inst);
Index: lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.cpp
===================================================================
--- lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.cpp
+++ lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.cpp
@@ -39,6 +39,8 @@
"beqz rj, offs21"},
{0xfc000000, 0x44000000, &EmulateInstructionLoongArch::EmulateBNEZ,
"bnez rj, offs21"},
+ {0xfc000000, 0x48000000, &EmulateInstructionLoongArch::EmulateBCXXZ,
+ "bceqz/bcnez cj, offs21"},
{0xfc000000, 0x4c000000, &EmulateInstructionLoongArch::EmulateJIRL,
"jirl rd, rj, offs16"},
{0xfc000000, 0x50000000, &EmulateInstructionLoongArch::EmulateB,
@@ -216,6 +218,10 @@
return IsLoongArch64() ? EmulateBNEZ64(inst) : false;
}
+bool EmulateInstructionLoongArch::EmulateBCXXZ(uint32_t inst) {
+ return IsLoongArch64() ? EmulateBCXXZ64(inst) : false;
+}
+
bool EmulateInstructionLoongArch::EmulateJIRL(uint32_t inst) {
return IsLoongArch64() ? EmulateJIRL64(inst) : false;
}
@@ -294,6 +300,42 @@
return WritePC(pc + 4);
}
+// bceqz cj, offs21
+// if CFR[cj] == 0:
+// PC = PC + SignExtend({offs21, 2'b0}, GRLEN)
+// bcnez cj, offs21
+// if CFR[cj] != 0:
+// PC = PC + SignExtend({offs21, 2'b0}, GRLEN)
+bool EmulateInstructionLoongArch::EmulateBCXXZ64(uint32_t inst) {
+ bool success = false;
+ uint32_t bcxxz = (inst >> 8) & 0b11;
+ uint32_t cj = Bits32(inst, 7, 5) + fpr_first_loongarch + 32;
+ uint64_t pc = ReadPC(&success);
+ if (!success)
+ return false;
+ uint32_t offs21 = Bits32(inst, 25, 10) + (Bits32(inst, 4, 0) << 16);
+ uint8_t cj_val =
+ (uint8_t)ReadRegisterUnsigned(eRegisterKindLLDB, cj, 0, &success);
+ if (!success)
+ return false;
+ if (bcxxz == 0b00) {
+ // BCEQZ
+ if (cj_val == 0) {
+ uint64_t next_pc = pc + llvm::SignExtend64<23>(offs21 << 2);
+ return WritePC(next_pc);
+ } else
+ return WritePC(pc + 4);
+ } else if (bcxxz == 0b01) {
+ // BCNEZ
+ if (cj_val != 0) {
+ uint64_t next_pc = pc + llvm::SignExtend64<23>(offs21 << 2);
+ return WritePC(next_pc);
+ } else
+ return WritePC(pc + 4);
+ }
+ return false;
+}
+
// jirl rd, rj, offs16
// GR[rd] = PC + 4
// PC = GR[rj] + SignExtend({offs16, 2'b0}, GRLEN)
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits