[Lldb-commits] [lldb] b7ae576 - [LLDB][LoongArch] Add FP branch instructions for EmulateInstructionLoongArch
Weining Lu via lldb-commits
lldb-commits at lists.llvm.org
Fri Jan 13 17:24:31 PST 2023
Author: Hui Li
Date: 2023-01-14T09:22:18+08:00
New Revision: b7ae5762a110ee7c28b218b4ed4e3e24b2b3c64d
URL: https://github.com/llvm/llvm-project/commit/b7ae5762a110ee7c28b218b4ed4e3e24b2b3c64d
DIFF: https://github.com/llvm/llvm-project/commit/b7ae5762a110ee7c28b218b4ed4e3e24b2b3c64d.diff
LOG: [LLDB][LoongArch] Add FP branch instructions for EmulateInstructionLoongArch
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
```
Reviewed By: SixWeining, MaskRay, DavidSpickett
Differential Revision: https://reviews.llvm.org/D140759
Added:
Modified:
lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.cpp
lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.h
lldb/unittests/Instruction/LoongArch/TestLoongArchEmulator.cpp
Removed:
################################################################################
diff --git a/lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.cpp b/lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.cpp
index c17da8b25aa31..adfd57dff07c0 100644
--- a/lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.cpp
+++ b/lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.cpp
@@ -40,6 +40,10 @@ EmulateInstructionLoongArch::GetOpcodeForInstruction(uint32_t inst) {
"beqz rj, offs21"},
{0xfc000000, 0x44000000, &EmulateInstructionLoongArch::EmulateBNEZ,
"bnez rj, offs21"},
+ {0xfc000300, 0x48000000, &EmulateInstructionLoongArch::EmulateBCEQZ,
+ "bceqz cj, offs21"},
+ {0xfc000300, 0x48000100, &EmulateInstructionLoongArch::EmulateBCNEZ,
+ "bcnez cj, offs21"},
{0xfc000000, 0x4c000000, &EmulateInstructionLoongArch::EmulateJIRL,
"jirl rd, rj, offs16"},
{0xfc000000, 0x50000000, &EmulateInstructionLoongArch::EmulateB,
@@ -217,6 +221,14 @@ bool EmulateInstructionLoongArch::EmulateBNEZ(uint32_t inst) {
return IsLoongArch64() ? EmulateBNEZ64(inst) : false;
}
+bool EmulateInstructionLoongArch::EmulateBCEQZ(uint32_t inst) {
+ return IsLoongArch64() ? EmulateBCEQZ64(inst) : false;
+}
+
+bool EmulateInstructionLoongArch::EmulateBCNEZ(uint32_t inst) {
+ return IsLoongArch64() ? EmulateBCNEZ64(inst) : false;
+}
+
bool EmulateInstructionLoongArch::EmulateJIRL(uint32_t inst) {
return IsLoongArch64() ? EmulateJIRL64(inst) : false;
}
@@ -295,6 +307,50 @@ bool EmulateInstructionLoongArch::EmulateBNEZ64(uint32_t inst) {
return WritePC(pc + 4);
}
+// bceqz cj, offs21
+// if CFR[cj] == 0:
+// PC = PC + SignExtend({offs21, 2'b0}, GRLEN)
+bool EmulateInstructionLoongArch::EmulateBCEQZ64(uint32_t inst) {
+ bool success = false;
+ uint32_t cj = Bits32(inst, 7, 5) + fpr_fcc0_loongarch;
+ 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 (cj_val == 0) {
+ uint64_t next_pc = pc + llvm::SignExtend64<23>(offs21 << 2);
+ return WritePC(next_pc);
+ } else
+ return WritePC(pc + 4);
+ return false;
+}
+
+// bcnez cj, offs21
+// if CFR[cj] != 0:
+// PC = PC + SignExtend({offs21, 2'b0}, GRLEN)
+bool EmulateInstructionLoongArch::EmulateBCNEZ64(uint32_t inst) {
+ bool success = false;
+ uint32_t cj = Bits32(inst, 7, 5) + fpr_fcc0_loongarch;
+ 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 (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)
diff --git a/lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.h b/lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.h
index 15da499261b05..e03356244b476 100644
--- a/lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.h
+++ b/lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.h
@@ -75,6 +75,8 @@ class EmulateInstructionLoongArch : public EmulateInstruction {
bool EmulateBEQZ(uint32_t inst);
bool EmulateBNEZ(uint32_t inst);
+ bool EmulateBCEQZ(uint32_t inst);
+ bool EmulateBCNEZ(uint32_t inst);
bool EmulateJIRL(uint32_t inst);
bool EmulateB(uint32_t inst);
bool EmulateBL(uint32_t inst);
@@ -88,6 +90,8 @@ class EmulateInstructionLoongArch : public EmulateInstruction {
bool EmulateBEQZ64(uint32_t inst);
bool EmulateBNEZ64(uint32_t inst);
+ bool EmulateBCEQZ64(uint32_t inst);
+ bool EmulateBCNEZ64(uint32_t inst);
bool EmulateJIRL64(uint32_t inst);
bool EmulateB64(uint32_t inst);
bool EmulateBL64(uint32_t inst);
diff --git a/lldb/unittests/Instruction/LoongArch/TestLoongArchEmulator.cpp b/lldb/unittests/Instruction/LoongArch/TestLoongArchEmulator.cpp
index af16559161507..376af1f015905 100644
--- a/lldb/unittests/Instruction/LoongArch/TestLoongArchEmulator.cpp
+++ b/lldb/unittests/Instruction/LoongArch/TestLoongArchEmulator.cpp
@@ -38,6 +38,14 @@ using namespace lldb_private;
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 @@ static uint32_t BNEZ(uint32_t rj, int32_t offs21) {
return EncodeBZcondType(0b010001, rj, uint32_t(offs21));
}
+// BCEQZ BCNEZ
+static uint32_t EncodeBCZcondType(uint32_t opcode, uint8_t cj,
+ uint32_t offs21) {
+ uint32_t offs20_16 = (offs21 & 0x001f0000) >> 16;
+ uint32_t offs15_0 = offs21 & 0x0000ffff;
+ return (opcode >> 2) << 26 | offs15_0 << 10 | (opcode & 0b11) << 8 | cj << 5 |
+ offs20_16;
+}
+
+static uint32_t BCEQZ(uint8_t cj, int32_t offs21) {
+ return EncodeBCZcondType(0b01001000, cj, uint32_t(offs21));
+}
+
+static uint32_t BCNEZ(uint8_t cj, int32_t offs21) {
+ return EncodeBCZcondType(0b01001001, cj, 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 @@ static void testBZcondBranch(LoongArch64EmulatorTester *tester,
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, BLTU, -2, -1, 1)
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)
More information about the lldb-commits
mailing list