[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