[Lldb-commits] [lldb] eafe2d4 - [LLDB][LoongArch] Add branch instructions for EmulateInstructionLoongArch

Weining Lu via lldb-commits lldb-commits at lists.llvm.org
Fri Dec 16 01:49:27 PST 2022


Author: Hui Li
Date: 2022-12-16T17:48:37+08:00
New Revision: eafe2d4cf17b7448db5750aff79ee3bb0158f945

URL: https://github.com/llvm/llvm-project/commit/eafe2d4cf17b7448db5750aff79ee3bb0158f945
DIFF: https://github.com/llvm/llvm-project/commit/eafe2d4cf17b7448db5750aff79ee3bb0158f945.diff

LOG: [LLDB][LoongArch] Add branch instructions for EmulateInstructionLoongArch

Add conditional and unconditional branch instructions for loongarch64.
Note that this does not include floating-point branch instructions, that will come in a later patch.

Reviewed By: SixWeining, DavidSpickett

Differential Revision: https://reviews.llvm.org/D139833

Added: 
    

Modified: 
    lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.cpp
    lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.h

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.cpp b/lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.cpp
index 14ac993d9ac0..b37bb860254e 100644
--- a/lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.cpp
+++ b/lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.cpp
@@ -33,8 +33,30 @@ namespace lldb_private {
 
 EmulateInstructionLoongArch::Opcode *
 EmulateInstructionLoongArch::GetOpcodeForInstruction(uint32_t inst) {
-  // TODO: Add the mask of jump instruction.
+  // TODO: Add the mask for other instruction.
   static EmulateInstructionLoongArch::Opcode g_opcodes[] = {
+      {0xfc000000, 0x40000000, &EmulateInstructionLoongArch::EmulateBEQZ,
+       "beqz rj, offs21"},
+      {0xfc000000, 0x44000000, &EmulateInstructionLoongArch::EmulateBNEZ,
+       "bnez rj, offs21"},
+      {0xfc000000, 0x4c000000, &EmulateInstructionLoongArch::EmulateJIRL,
+       "jirl rd, rj, offs16"},
+      {0xfc000000, 0x50000000, &EmulateInstructionLoongArch::EmulateB,
+       " b  offs26"},
+      {0xfc000000, 0x54000000, &EmulateInstructionLoongArch::EmulateBL,
+       "bl  offs26"},
+      {0xfc000000, 0x58000000, &EmulateInstructionLoongArch::EmulateBEQ,
+       "beq  rj, rd, offs16"},
+      {0xfc000000, 0x5c000000, &EmulateInstructionLoongArch::EmulateBNE,
+       "bne  rj, rd, offs16"},
+      {0xfc000000, 0x60000000, &EmulateInstructionLoongArch::EmulateBLT,
+       "blt  rj, rd, offs16"},
+      {0xfc000000, 0x64000000, &EmulateInstructionLoongArch::EmulateBGE,
+       "bge  rj, rd, offs16"},
+      {0xfc000000, 0x68000000, &EmulateInstructionLoongArch::EmulateBLTU,
+       "bltu rj, rd, offs16"},
+      {0xfc000000, 0x6c000000, &EmulateInstructionLoongArch::EmulateBGEU,
+       "bgeu rj, rd, offs16"},
       {0x00000000, 0x00000000, &EmulateInstructionLoongArch::EmulateNonJMP,
        "NonJMP"}};
   static const size_t num_loongarch_opcodes = std::size(g_opcodes);
@@ -176,6 +198,339 @@ bool EmulateInstructionLoongArch::SupportsThisArch(const ArchSpec &arch) {
   return arch.GetTriple().isLoongArch();
 }
 
+bool EmulateInstructionLoongArch::EmulateBEQZ(uint32_t inst) {
+  if (IsLoongArch64())
+    return EmulateBEQZ64(inst);
+  else
+    return false;
+}
+
+bool EmulateInstructionLoongArch::EmulateBNEZ(uint32_t inst) {
+  if (IsLoongArch64())
+    return EmulateBNEZ64(inst);
+  else
+    return false;
+}
+
+bool EmulateInstructionLoongArch::EmulateJIRL(uint32_t inst) {
+  if (IsLoongArch64())
+    return EmulateJIRL64(inst);
+  else
+    return false;
+}
+
+bool EmulateInstructionLoongArch::EmulateB(uint32_t inst) {
+  if (IsLoongArch64())
+    return EmulateB64(inst);
+  else
+    return false;
+}
+
+bool EmulateInstructionLoongArch::EmulateBL(uint32_t inst) {
+  if (IsLoongArch64())
+    return EmulateBL64(inst);
+  else
+    return false;
+}
+
+bool EmulateInstructionLoongArch::EmulateBEQ(uint32_t inst) {
+  if (IsLoongArch64())
+    return EmulateBEQ64(inst);
+  else
+    return false;
+}
+
+bool EmulateInstructionLoongArch::EmulateBNE(uint32_t inst) {
+  if (IsLoongArch64())
+    return EmulateJIRL64(inst);
+  else
+    return false;
+}
+
+bool EmulateInstructionLoongArch::EmulateBLT(uint32_t inst) {
+  if (IsLoongArch64())
+    return EmulateBLT64(inst);
+  else
+    return false;
+}
+
+bool EmulateInstructionLoongArch::EmulateBGE(uint32_t inst) {
+  if (IsLoongArch64())
+    return EmulateBGE64(inst);
+  else
+    return false;
+}
+
+bool EmulateInstructionLoongArch::EmulateBLTU(uint32_t inst) {
+  if (IsLoongArch64())
+    return EmulateBLTU64(inst);
+  else
+    return false;
+}
+
+bool EmulateInstructionLoongArch::EmulateBGEU(uint32_t inst) {
+  if (IsLoongArch64())
+    return EmulateBGEU64(inst);
+  else
+    return false;
+}
+
 bool EmulateInstructionLoongArch::EmulateNonJMP(uint32_t inst) { return false; }
 
+// beqz rj, offs21
+// if GR[rj] == 0:
+//   PC = PC + SignExtend({offs21, 2'b0}, GRLEN)
+bool EmulateInstructionLoongArch::EmulateBEQZ64(uint32_t inst) {
+  uint64_t next_pc, imm_sign_extend;
+  bool success = false;
+  uint32_t rj = Bits32(inst, 9, 5);
+  uint64_t rj_val;
+  uint64_t pc = ReadPC(&success);
+  if (!success)
+    return false;
+  uint32_t offs21 = Bits32(inst, 25, 10) + (Bits32(inst, 4, 0) << 16);
+  rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success);
+  if (!success)
+    return false;
+  if (rj_val == 0) {
+    imm_sign_extend = llvm::SignExtend64<23>(offs21 << 2);
+    next_pc = pc + imm_sign_extend;
+    return WritePC(next_pc);
+  } else
+    return WritePC(pc + 4);
+}
+
+// bnez rj, offs21
+// if GR[rj] != 0:
+//   PC = PC + SignExtend({offs21, 2'b0}, GRLEN)
+bool EmulateInstructionLoongArch::EmulateBNEZ64(uint32_t inst) {
+  uint64_t next_pc, imm_sign_extend;
+  bool success = false;
+  uint32_t rj = Bits32(inst, 9, 5);
+  uint64_t rj_val;
+  uint64_t pc = ReadPC(&success);
+  if (!success)
+    return false;
+  uint32_t offs21 = Bits32(inst, 25, 10) + (Bits32(inst, 4, 0) << 16);
+  rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success);
+  if (!success)
+    return false;
+  if (rj_val != 0) {
+    imm_sign_extend = llvm::SignExtend64<23>(offs21 << 2);
+    next_pc = pc + imm_sign_extend;
+    return WritePC(next_pc);
+  } else
+    return WritePC(pc + 4);
+}
+
+// jirl rd, rj, offs16
+// GR[rd] = PC + 4
+// PC = GR[rj] + SignExtend({offs16, 2'b0}, GRLEN)
+bool EmulateInstructionLoongArch::EmulateJIRL64(uint32_t inst) {
+  uint64_t next_pc, imm_sign_extend;
+  RegisterValue value;
+  uint32_t rj = Bits32(inst, 9, 5);
+  uint32_t rd = Bits32(inst, 4, 0);
+  bool success = false;
+  uint64_t pc = ReadPC(&success);
+  if (!success)
+    return false;
+  EmulateInstruction::Context ctx;
+  if (!WriteRegisterUnsigned(ctx, eRegisterKindLLDB, rd, pc + 4))
+    return false;
+  if (!ReadRegister(eRegisterKindLLDB, rj, value))
+    return false;
+  imm_sign_extend = llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2);
+  next_pc = value.GetAsUInt64() + imm_sign_extend;
+  return WritePC(next_pc);
+}
+
+// b offs26
+// PC = PC + SignExtend({offs26, 2' b0}, GRLEN)
+bool EmulateInstructionLoongArch::EmulateB64(uint32_t inst) {
+  uint64_t next_pc, imm_sign_extend;
+  bool success = false;
+  uint64_t pc = ReadPC(&success);
+  if (!success)
+    return false;
+  uint32_t offs26 = Bits32(inst, 25, 10) + (Bits32(inst, 9, 0) << 16);
+  imm_sign_extend = llvm::SignExtend64<28>(offs26 << 2);
+  next_pc = pc + imm_sign_extend;
+  return WritePC(next_pc);
+}
+
+// bl offs26
+// GR[1] = PC + 4
+// PC = PC + SignExtend({offs26, 2'b0}, GRLEN)
+bool EmulateInstructionLoongArch::EmulateBL64(uint32_t inst) {
+  uint64_t next_pc, imm_sign_extend;
+  bool success = false;
+  uint64_t pc = ReadPC(&success);
+  if (!success)
+    return false;
+  EmulateInstruction::Context ctx;
+  if (!WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_r1_loongarch, pc + 4))
+    return false;
+  uint32_t offs26 = Bits32(inst, 25, 10) + (Bits32(inst, 9, 0) << 16);
+  imm_sign_extend = llvm::SignExtend64<28>(offs26 << 2);
+  next_pc = pc + imm_sign_extend;
+  return WritePC(next_pc);
+}
+
+// beq rj, rd, offs16
+// if GR[rj] == GR[rd]:
+//   PC = PC + SignExtend({offs16, 2'b0}, GRLEN)
+bool EmulateInstructionLoongArch::EmulateBEQ64(uint32_t inst) {
+  uint64_t next_pc, imm_sign_extend;
+  bool success = false;
+  uint32_t rj = Bits32(inst, 9, 5);
+  uint32_t rd = Bits32(inst, 4, 0);
+  uint64_t rj_val, rd_val;
+  uint64_t pc = ReadPC(&success);
+  if (!success)
+    return false;
+  rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success);
+  if (!success)
+    return false;
+  rd_val = ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success);
+  if (!success)
+    return false;
+  if (rj_val == rd_val) {
+    imm_sign_extend = llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2);
+    next_pc = pc + imm_sign_extend;
+    return WritePC(next_pc);
+  } else
+    return WritePC(pc + 4);
+}
+
+// bne rj, rd, offs16
+// if GR[rj] != GR[rd]:
+//   PC = PC + SignExtend({offs16, 2'b0}, GRLEN)
+bool EmulateInstructionLoongArch::EmulateBNE64(uint32_t inst) {
+  uint64_t next_pc, imm_sign_extend;
+  bool success = false;
+  uint32_t rj = Bits32(inst, 9, 5);
+  uint32_t rd = Bits32(inst, 4, 0);
+  uint64_t rj_val, rd_val;
+  uint64_t pc = ReadPC(&success);
+  if (!success)
+    return false;
+  rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success);
+  if (!success)
+    return false;
+  rd_val = ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success);
+  if (!success)
+    return false;
+  if (rj_val != rd_val) {
+    imm_sign_extend = llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2);
+    next_pc = pc + imm_sign_extend;
+    return WritePC(next_pc);
+  } else
+    return WritePC(pc + 4);
+}
+
+// blt rj, rd, offs16
+// if signed(GR[rj]) < signed(GR[rd]):
+//   PC = PC + SignExtend({offs16, 2'b0}, GRLEN)
+bool EmulateInstructionLoongArch::EmulateBLT64(uint32_t inst) {
+  uint64_t next_pc, imm_sign_extend;
+  bool success = false;
+  uint32_t rj = Bits32(inst, 9, 5);
+  uint32_t rd = Bits32(inst, 4, 0);
+  int64_t rj_val, rd_val;
+  uint64_t pc = ReadPC(&success);
+  if (!success)
+    return false;
+  rj_val = (int64_t)ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success);
+  if (!success)
+    return false;
+  rd_val = (int64_t)ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success);
+  if (!success)
+    return false;
+  if (rj_val < rd_val) {
+    imm_sign_extend = llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2);
+    next_pc = pc + imm_sign_extend;
+    return WritePC(next_pc);
+  } else
+    return WritePC(pc + 4);
+}
+
+// bge rj, rd, offs16
+// if signed(GR[rj]) >= signed(GR[rd]):
+//   PC = PC + SignExtend({offs16, 2'b0}, GRLEN)
+bool EmulateInstructionLoongArch::EmulateBGE64(uint32_t inst) {
+  uint64_t next_pc, imm_sign_extend;
+  bool success = false;
+  uint32_t rj = Bits32(inst, 9, 5);
+  uint32_t rd = Bits32(inst, 4, 0);
+  int64_t rj_val, rd_val;
+  uint64_t pc = ReadPC(&success);
+  if (!success)
+    return false;
+  rj_val = (int64_t)ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success);
+  if (!success)
+    return false;
+  rd_val = (int64_t)ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success);
+  if (!success)
+    return false;
+  if (rj_val >= rd_val) {
+    imm_sign_extend = llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2);
+    next_pc = pc + imm_sign_extend;
+    return WritePC(next_pc);
+  } else
+    return WritePC(pc + 4);
+}
+
+// bltu rj, rd, offs16
+// if unsigned(GR[rj]) < unsigned(GR[rd]):
+//   PC = PC + SignExtend({offs16, 2'b0}, GRLEN)
+bool EmulateInstructionLoongArch::EmulateBLTU64(uint32_t inst) {
+  uint64_t next_pc, imm_sign_extend;
+  bool success = false;
+  uint32_t rj = Bits32(inst, 9, 5);
+  uint32_t rd = Bits32(inst, 4, 0);
+  uint64_t rj_val, rd_val;
+  uint64_t pc = ReadPC(&success);
+  if (!success)
+    return false;
+  rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success);
+  if (!success)
+    return false;
+  rd_val = ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success);
+  if (!success)
+    return false;
+  if (rj_val < rd_val) {
+    imm_sign_extend = llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2);
+    next_pc = pc + imm_sign_extend;
+    return WritePC(next_pc);
+  } else
+    return WritePC(pc + 4);
+}
+
+// bgeu rj, rd, offs16
+// if unsigned(GR[rj]) >= unsigned(GR[rd]):
+//   PC = PC + SignExtend({offs16, 2'b0}, GRLEN)
+bool EmulateInstructionLoongArch::EmulateBGEU64(uint32_t inst) {
+  uint64_t next_pc, imm_sign_extend;
+  bool success = false;
+  uint32_t rj = Bits32(inst, 9, 5);
+  uint32_t rd = Bits32(inst, 4, 0);
+  uint64_t rj_val, rd_val;
+  uint64_t pc = ReadPC(&success);
+  if (!success)
+    return false;
+  rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success);
+  if (!success)
+    return false;
+  rd_val = ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success);
+  if (!success)
+    return false;
+  if (rj_val >= rd_val) {
+    imm_sign_extend = llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2);
+    next_pc = pc + imm_sign_extend;
+    return WritePC(next_pc);
+  } else
+    return WritePC(pc + 4);
+}
+
 } // namespace lldb_private

diff  --git a/lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.h b/lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.h
index 06abc99d1ee9..cee87053dd6b 100644
--- a/lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.h
+++ b/lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.h
@@ -38,8 +38,9 @@ class EmulateInstructionLoongArch : public EmulateInstruction {
   static void Terminate();
 
 public:
-  EmulateInstructionLoongArch(const ArchSpec &arch)
-      : EmulateInstruction(arch) {}
+  EmulateInstructionLoongArch(const ArchSpec &arch) : EmulateInstruction(arch) {
+    m_arch_subtype = arch.GetMachine();
+  }
 
   llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
 
@@ -57,6 +58,7 @@ class EmulateInstructionLoongArch : public EmulateInstruction {
                                                uint32_t reg_num) override;
   lldb::addr_t ReadPC(bool *success);
   bool WritePC(lldb::addr_t pc);
+  bool IsLoongArch64() { return m_arch_subtype == llvm::Triple::loongarch64; }
 
 private:
   struct Opcode {
@@ -66,9 +68,33 @@ class EmulateInstructionLoongArch : public EmulateInstruction {
     const char *name;
   };
 
+  llvm::Triple::ArchType m_arch_subtype;
   Opcode *GetOpcodeForInstruction(uint32_t inst);
 
+  bool EmulateBEQZ(uint32_t inst);
+  bool EmulateBNEZ(uint32_t inst);
+  bool EmulateJIRL(uint32_t inst);
+  bool EmulateB(uint32_t inst);
+  bool EmulateBL(uint32_t inst);
+  bool EmulateBEQ(uint32_t inst);
+  bool EmulateBNE(uint32_t inst);
+  bool EmulateBLT(uint32_t inst);
+  bool EmulateBGE(uint32_t inst);
+  bool EmulateBLTU(uint32_t inst);
+  bool EmulateBGEU(uint32_t inst);
   bool EmulateNonJMP(uint32_t inst);
+
+  bool EmulateBEQZ64(uint32_t inst);
+  bool EmulateBNEZ64(uint32_t inst);
+  bool EmulateJIRL64(uint32_t inst);
+  bool EmulateB64(uint32_t inst);
+  bool EmulateBL64(uint32_t inst);
+  bool EmulateBEQ64(uint32_t inst);
+  bool EmulateBNE64(uint32_t inst);
+  bool EmulateBLT64(uint32_t inst);
+  bool EmulateBGE64(uint32_t inst);
+  bool EmulateBLTU64(uint32_t inst);
+  bool EmulateBGEU64(uint32_t inst);
 };
 
 } // namespace lldb_private


        


More information about the lldb-commits mailing list