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) _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits