Skip to content

Commit b7ae576

Browse files
lhloongsonSixWeining
authored andcommitted
[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
1 parent b1f4f06 commit b7ae576

File tree

3 files changed

+103
-0
lines changed

3 files changed

+103
-0
lines changed

lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ EmulateInstructionLoongArch::GetOpcodeForInstruction(uint32_t inst) {
4040
"beqz rj, offs21"},
4141
{0xfc000000, 0x44000000, &EmulateInstructionLoongArch::EmulateBNEZ,
4242
"bnez rj, offs21"},
43+
{0xfc000300, 0x48000000, &EmulateInstructionLoongArch::EmulateBCEQZ,
44+
"bceqz cj, offs21"},
45+
{0xfc000300, 0x48000100, &EmulateInstructionLoongArch::EmulateBCNEZ,
46+
"bcnez cj, offs21"},
4347
{0xfc000000, 0x4c000000, &EmulateInstructionLoongArch::EmulateJIRL,
4448
"jirl rd, rj, offs16"},
4549
{0xfc000000, 0x50000000, &EmulateInstructionLoongArch::EmulateB,
@@ -217,6 +221,14 @@ bool EmulateInstructionLoongArch::EmulateBNEZ(uint32_t inst) {
217221
return IsLoongArch64() ? EmulateBNEZ64(inst) : false;
218222
}
219223

224+
bool EmulateInstructionLoongArch::EmulateBCEQZ(uint32_t inst) {
225+
return IsLoongArch64() ? EmulateBCEQZ64(inst) : false;
226+
}
227+
228+
bool EmulateInstructionLoongArch::EmulateBCNEZ(uint32_t inst) {
229+
return IsLoongArch64() ? EmulateBCNEZ64(inst) : false;
230+
}
231+
220232
bool EmulateInstructionLoongArch::EmulateJIRL(uint32_t inst) {
221233
return IsLoongArch64() ? EmulateJIRL64(inst) : false;
222234
}
@@ -295,6 +307,50 @@ bool EmulateInstructionLoongArch::EmulateBNEZ64(uint32_t inst) {
295307
return WritePC(pc + 4);
296308
}
297309

310+
// bceqz cj, offs21
311+
// if CFR[cj] == 0:
312+
// PC = PC + SignExtend({offs21, 2'b0}, GRLEN)
313+
bool EmulateInstructionLoongArch::EmulateBCEQZ64(uint32_t inst) {
314+
bool success = false;
315+
uint32_t cj = Bits32(inst, 7, 5) + fpr_fcc0_loongarch;
316+
uint64_t pc = ReadPC(&success);
317+
if (!success)
318+
return false;
319+
uint32_t offs21 = Bits32(inst, 25, 10) + (Bits32(inst, 4, 0) << 16);
320+
uint8_t cj_val =
321+
(uint8_t)ReadRegisterUnsigned(eRegisterKindLLDB, cj, 0, &success);
322+
if (!success)
323+
return false;
324+
if (cj_val == 0) {
325+
uint64_t next_pc = pc + llvm::SignExtend64<23>(offs21 << 2);
326+
return WritePC(next_pc);
327+
} else
328+
return WritePC(pc + 4);
329+
return false;
330+
}
331+
332+
// bcnez cj, offs21
333+
// if CFR[cj] != 0:
334+
// PC = PC + SignExtend({offs21, 2'b0}, GRLEN)
335+
bool EmulateInstructionLoongArch::EmulateBCNEZ64(uint32_t inst) {
336+
bool success = false;
337+
uint32_t cj = Bits32(inst, 7, 5) + fpr_fcc0_loongarch;
338+
uint64_t pc = ReadPC(&success);
339+
if (!success)
340+
return false;
341+
uint32_t offs21 = Bits32(inst, 25, 10) + (Bits32(inst, 4, 0) << 16);
342+
uint8_t cj_val =
343+
(uint8_t)ReadRegisterUnsigned(eRegisterKindLLDB, cj, 0, &success);
344+
if (!success)
345+
return false;
346+
if (cj_val != 0) {
347+
uint64_t next_pc = pc + llvm::SignExtend64<23>(offs21 << 2);
348+
return WritePC(next_pc);
349+
} else
350+
return WritePC(pc + 4);
351+
return false;
352+
}
353+
298354
// jirl rd, rj, offs16
299355
// GR[rd] = PC + 4
300356
// PC = GR[rj] + SignExtend({offs16, 2'b0}, GRLEN)

lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ class EmulateInstructionLoongArch : public EmulateInstruction {
7575

7676
bool EmulateBEQZ(uint32_t inst);
7777
bool EmulateBNEZ(uint32_t inst);
78+
bool EmulateBCEQZ(uint32_t inst);
79+
bool EmulateBCNEZ(uint32_t inst);
7880
bool EmulateJIRL(uint32_t inst);
7981
bool EmulateB(uint32_t inst);
8082
bool EmulateBL(uint32_t inst);
@@ -88,6 +90,8 @@ class EmulateInstructionLoongArch : public EmulateInstruction {
8890

8991
bool EmulateBEQZ64(uint32_t inst);
9092
bool EmulateBNEZ64(uint32_t inst);
93+
bool EmulateBCEQZ64(uint32_t inst);
94+
bool EmulateBCNEZ64(uint32_t inst);
9195
bool EmulateJIRL64(uint32_t inst);
9296
bool EmulateB64(uint32_t inst);
9397
bool EmulateBL64(uint32_t inst);

lldb/unittests/Instruction/LoongArch/TestLoongArchEmulator.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ using namespace lldb_private;
3838
testBZcondBranch(this, name, false, rj_val_continued); \
3939
}
4040

41+
#define GEN_BCZCOND_TEST(bit, name, cj_val_branched, cj_val_continued) \
42+
TEST_F(LoongArch##bit##EmulatorTester, test##name##branched) { \
43+
testBCZcondBranch(this, name, true, cj_val_branched); \
44+
} \
45+
TEST_F(LoongArch##bit##EmulatorTester, test##name##continued) { \
46+
testBCZcondBranch(this, name, false, cj_val_continued); \
47+
}
48+
4149
struct LoongArch64EmulatorTester : public EmulateInstructionLoongArch,
4250
testing::Test {
4351
RegisterInfoPOSIX_loongarch64::GPR gpr;
@@ -136,8 +144,26 @@ static uint32_t BNEZ(uint32_t rj, int32_t offs21) {
136144
return EncodeBZcondType(0b010001, rj, uint32_t(offs21));
137145
}
138146

147+
// BCEQZ BCNEZ
148+
static uint32_t EncodeBCZcondType(uint32_t opcode, uint8_t cj,
149+
uint32_t offs21) {
150+
uint32_t offs20_16 = (offs21 & 0x001f0000) >> 16;
151+
uint32_t offs15_0 = offs21 & 0x0000ffff;
152+
return (opcode >> 2) << 26 | offs15_0 << 10 | (opcode & 0b11) << 8 | cj << 5 |
153+
offs20_16;
154+
}
155+
156+
static uint32_t BCEQZ(uint8_t cj, int32_t offs21) {
157+
return EncodeBCZcondType(0b01001000, cj, uint32_t(offs21));
158+
}
159+
160+
static uint32_t BCNEZ(uint8_t cj, int32_t offs21) {
161+
return EncodeBCZcondType(0b01001001, cj, uint32_t(offs21));
162+
}
163+
139164
using EncoderBcond = uint32_t (*)(uint32_t rj, uint32_t rd, int32_t offs16);
140165
using EncoderBZcond = uint32_t (*)(uint32_t rj, int32_t offs21);
166+
using EncoderBCZcond = uint32_t (*)(uint8_t cj, int32_t offs21);
141167

142168
TEST_F(LoongArch64EmulatorTester, testJIRL) {
143169
bool success = false;
@@ -220,6 +246,21 @@ static void testBZcondBranch(LoongArch64EmulatorTester *tester,
220246
ASSERT_EQ(pc, old_pc + (branched ? (-256 * 4) : 4));
221247
}
222248

249+
static void testBCZcondBranch(LoongArch64EmulatorTester *tester,
250+
EncoderBCZcond encoder, bool branched,
251+
uint32_t cj_val) {
252+
bool success = false;
253+
addr_t old_pc = 0x12000600;
254+
tester->WritePC(old_pc);
255+
tester->fpr.fcc = cj_val;
256+
// bc<cmp>z fcc0, 256
257+
uint32_t inst = encoder(0, 256);
258+
ASSERT_TRUE(tester->TestExecute(inst));
259+
auto pc = tester->ReadPC(&success);
260+
ASSERT_TRUE(success);
261+
ASSERT_EQ(pc, old_pc + (branched ? (256 * 4) : 4));
262+
}
263+
223264
GEN_BCOND_TEST(64, BEQ, 1, 1, 0)
224265
GEN_BCOND_TEST(64, BNE, 1, 0, 1)
225266
GEN_BCOND_TEST(64, BLT, -2, 1, -3)
@@ -228,3 +269,5 @@ GEN_BCOND_TEST(64, BLTU, -2, -1, 1)
228269
GEN_BCOND_TEST(64, BGEU, -2, 1, -1)
229270
GEN_BZCOND_TEST(64, BEQZ, 0, 1)
230271
GEN_BZCOND_TEST(64, BNEZ, 1, 0)
272+
GEN_BCZCOND_TEST(64, BCEQZ, 0, 1)
273+
GEN_BCZCOND_TEST(64, BCNEZ, 1, 0)

0 commit comments

Comments
 (0)