lh03061238 updated this revision to Diff 485680.
lh03061238 added a comment.

1、Modify BCEQZ/BCNEZ instruction opcode and mask
2、Separate BCEQZ and BCNEZ
3、Use "Bits32(inst, 7, 5) + fpr_fcc0_loongarch" to calculate cj


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D140759/new/

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,27 @@
   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;
+  uint32_t bcxxz = opcode & 0b11;
+  opcode = opcode >> 2;
+  return opcode << 26 | offs15_0 << 10 | bcxxz << 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 +247,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 +270,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,8 @@
 
   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);
@@ -87,6 +89,8 @@
 
   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);
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,10 @@
        "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,
@@ -216,6 +220,14 @@
   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;
 }
@@ -294,6 +306,50 @@
     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)
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to