[Lldb-commits] [lldb] 05ae747 - [LLDB][RISCV] Add RV64C instruction support for EmulateInstructionRISCV

via lldb-commits lldb-commits at lists.llvm.org
Tue Oct 25 04:12:53 PDT 2022


Author: Emmmer
Date: 2022-10-25T19:12:45+08:00
New Revision: 05ae747a5353811f93f5814f24d2335e6229d78a

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

LOG: [LLDB][RISCV] Add RV64C instruction support for EmulateInstructionRISCV

Add:

- RV64C instructions sets.
- corresponding unittests.
- `c.break` code for lldb and lldb-server

Fix:
- wrong decoding of imm in `DecodeSType`

Reviewed By: DavidSpickett

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

Added: 
    lldb/source/Plugins/Instruction/RISCV/RISCVCInstructions.h

Modified: 
    lldb/source/Host/common/NativeProcessProtocol.cpp
    lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp
    lldb/source/Plugins/Instruction/RISCV/RISCVInstructions.h
    lldb/source/Target/Platform.cpp
    lldb/unittests/Instruction/RISCV/TestRISCVEmulator.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Host/common/NativeProcessProtocol.cpp b/lldb/source/Host/common/NativeProcessProtocol.cpp
index 363699344146f..cdb59842e658b 100644
--- a/lldb/source/Host/common/NativeProcessProtocol.cpp
+++ b/lldb/source/Host/common/NativeProcessProtocol.cpp
@@ -503,9 +503,10 @@ NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_t size_hint) {
   static const uint8_t g_mips64_opcode[] = {0x00, 0x00, 0x00, 0x0d};
   static const uint8_t g_mips64el_opcode[] = {0x0d, 0x00, 0x00, 0x00};
   static const uint8_t g_s390x_opcode[] = {0x00, 0x01};
-  static const uint8_t g_ppc_opcode[] = {0x7f, 0xe0, 0x00, 0x08}; // trap
+  static const uint8_t g_ppc_opcode[] = {0x7f, 0xe0, 0x00, 0x08};   // trap
   static const uint8_t g_ppcle_opcode[] = {0x08, 0x00, 0xe0, 0x7f}; // trap
   static const uint8_t g_riscv_opcode[] = {0x73, 0x00, 0x10, 0x00}; // ebreak
+  static const uint8_t g_riscv_opcode_c[] = {0x02, 0x90};           // c.ebreak
 
   switch (GetArchitecture().GetMachine()) {
   case llvm::Triple::aarch64:
@@ -535,8 +536,10 @@ NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_t size_hint) {
     return llvm::makeArrayRef(g_ppcle_opcode);
 
   case llvm::Triple::riscv32:
-  case llvm::Triple::riscv64:
-    return llvm::makeArrayRef(g_riscv_opcode);
+  case llvm::Triple::riscv64: {
+    return size_hint == 2 ? llvm::makeArrayRef(g_riscv_opcode_c)
+                          : llvm::makeArrayRef(g_riscv_opcode);
+  }
 
   default:
     return llvm::createStringError(llvm::inconvertibleErrorCode(),

diff  --git a/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp b/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp
index 8d1a4c999e8f8..1d8f3a2750277 100644
--- a/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp
+++ b/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp
@@ -6,11 +6,10 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include <cstdlib>
-
 #include "EmulateInstructionRISCV.h"
 #include "Plugins/Process/Utility/RegisterInfoPOSIX_riscv64.h"
 #include "Plugins/Process/Utility/lldb-riscv-register-enums.h"
+#include "RISCVCInstructions.h"
 #include "RISCVInstructions.h"
 
 #include "lldb/Core/Address.h"
@@ -86,8 +85,8 @@ constexpr uint32_t DecodeBImm(uint32_t inst) {
 }
 
 constexpr uint32_t DecodeSImm(uint32_t inst) {
-  return (uint64_t(int64_t(int32_t(inst & 0xFE00000)) >> 20)) // imm[11:5]
-         | ((inst & 0xF80) >> 7);                             // imm[4:0]
+  return (uint64_t(int64_t(int32_t(inst & 0xFE000000)) >> 20)) // imm[11:5]
+         | ((inst & 0xF80) >> 7);                              // imm[4:0]
 }
 
 constexpr uint32_t DecodeUImm(uint32_t inst) {
@@ -194,14 +193,14 @@ LoadStoreAddr(EmulateInstructionRISCV &emulator, I inst) {
 }
 
 // Read T from memory, then load its sign-extended value m_emu to register.
-template <typename I, typename T, typename m_emu>
+template <typename I, typename T, typename E>
 static std::enable_if_t<is_load<I>, bool>
-Load(EmulateInstructionRISCV &emulator, I inst, uint64_t (*extend)(m_emu)) {
+Load(EmulateInstructionRISCV &emulator, I inst, uint64_t (*extend)(E)) {
   auto addr = LoadStoreAddr(emulator, inst);
   if (!addr)
     return false;
   return emulator.ReadMem<T>(*addr)
-      .transform([&](T t) { return inst.rd.Write(emulator, extend(m_emu(t))); })
+      .transform([&](T t) { return inst.rd.Write(emulator, extend(E(t))); })
       .value_or(false);
 }
 
@@ -461,6 +460,38 @@ static const InstrPattern PATTERNS[] = {
     {"AMOMAX_D", 0xF800707F, 0xA000302F, DecodeRType<AMOMAX_D>},
     {"AMOMINU_D", 0xF800707F, 0xC000302F, DecodeRType<AMOMINU_D>},
     {"AMOMAXU_D", 0xF800707F, 0xE000302F, DecodeRType<AMOMAXU_D>},
+
+    // RVC (Compressed Instructions) //
+    {"C_LWSP", 0xE003, 0x4002, DecodeC_LWSP},
+    {"C_LDSP", 0xE003, 0x6002, DecodeC_LDSP},
+    {"C_SWSP", 0xE003, 0xC002, DecodeC_SWSP},
+    {"C_SDSP", 0xE003, 0xE002, DecodeC_SDSP},
+    {"C_LW", 0xE003, 0x4000, DecodeC_LW},
+    {"C_LD", 0xE003, 0x6000, DecodeC_LD},
+    {"C_SW", 0xE003, 0xC000, DecodeC_SW},
+    {"C_SD", 0xE003, 0xE000, DecodeC_SD},
+    {"C_J", 0xE003, 0xA001, DecodeC_J},
+    {"C_JR", 0xF07F, 0x8002, DecodeC_JR},
+    {"C_JALR", 0xF07F, 0x9002, DecodeC_JALR},
+    {"C_BNEZ", 0xE003, 0xE001, DecodeC_BNEZ},
+    {"C_BEQZ", 0xE003, 0xC001, DecodeC_BEQZ},
+    {"C_LI", 0xE003, 0x4001, DecodeC_LI},
+    {"C_LUI_ADDI16SP", 0xE003, 0x6001, DecodeC_LUI_ADDI16SP},
+    {"C_ADDI", 0xE003, 0x1, DecodeC_ADDI},
+    {"C_ADDIW", 0xE003, 0x2001, DecodeC_ADDIW},
+    {"C_ADDI4SPN", 0xE003, 0x0, DecodeC_ADDI4SPN},
+    {"C_SLLI", 0xE003, 0x2, DecodeC_SLLI},
+    {"C_SRLI", 0xEC03, 0x8001, DecodeC_SRLI},
+    {"C_SRAI", 0xEC03, 0x8401, DecodeC_SRAI},
+    {"C_ANDI", 0xEC03, 0x8801, DecodeC_ANDI},
+    {"C_MV", 0xF003, 0x8002, DecodeC_MV},
+    {"C_ADD", 0xF003, 0x9002, DecodeC_ADD},
+    {"C_AND", 0xFC63, 0x8C61, DecodeC_AND},
+    {"C_OR", 0xFC63, 0x8C41, DecodeC_OR},
+    {"C_XOR", 0xFC63, 0x8C21, DecodeC_XOR},
+    {"C_SUB", 0xFC63, 0x8C01, DecodeC_SUB},
+    {"C_SUBW", 0xFC63, 0x9C01, DecodeC_SUBW},
+    {"C_ADDW", 0xFC63, 0x9C21, DecodeC_ADDW},
 };
 
 llvm::Optional<DecodeResult> EmulateInstructionRISCV::Decode(uint32_t inst) {
@@ -473,9 +504,9 @@ llvm::Optional<DecodeResult> EmulateInstructionRISCV::Decode(uint32_t inst) {
 
   for (const InstrPattern &pat : PATTERNS) {
     if ((inst & pat.type_mask) == pat.eigen) {
-      LLDB_LOGF(log, "EmulateInstructionRISCV::%s: inst(%x) was decoded to %s",
-                __FUNCTION__, inst, pat.name);
-      auto decoded = pat.decode(inst);
+      LLDB_LOGF(log, "EmulateInstructionRISCV::%s: inst(%x at %lx) was decoded to %s",
+                __FUNCTION__, inst, m_addr, pat.name);
+      auto decoded = is_rvc ? pat.decode(try_rvc) : pat.decode(inst);
       return DecodeResult{decoded, inst, is_rvc, pat};
     }
   }
@@ -1017,6 +1048,11 @@ class Executor {
         m_emu, inst, 8, ZextD,
         [](uint64_t a, uint64_t b) { return std::max(a, b); });
   }
+  bool operator()(INVALID inst) { return false; }
+  bool operator()(RESERVED inst) { return false; }
+  bool operator()(EBREAK inst) { return false; }
+  bool operator()(HINT inst) { return true; }
+  bool operator()(NOP inst) { return true; }
 };
 
 bool EmulateInstructionRISCV::Execute(DecodeResult inst, bool ignore_cond) {

diff  --git a/lldb/source/Plugins/Instruction/RISCV/RISCVCInstructions.h b/lldb/source/Plugins/Instruction/RISCV/RISCVCInstructions.h
new file mode 100644
index 0000000000000..1f113167311ad
--- /dev/null
+++ b/lldb/source/Plugins/Instruction/RISCV/RISCVCInstructions.h
@@ -0,0 +1,304 @@
+//===-- RISCVCInstructions.h ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVCINSTRUCTION_H
+#define LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVCINSTRUCTION_H
+
+#include <cstdint>
+#include <variant>
+
+#include "RISCVInstructions.h"
+#include "llvm/ADT/Optional.h"
+
+namespace lldb_private {
+
+/// Unified RISC-V C register encoding.
+struct RxC {
+  uint32_t rd;
+  bool shift = true;
+  operator int() { return rd; }
+  operator Rd() { return Rd{rd + (shift ? 8 : 0)}; }
+  operator Rs() { return Rs{rd + (shift ? 8 : 0)}; }
+};
+
+// decode register for RVC
+constexpr RxC DecodeCR_RD(uint32_t inst) { return RxC{DecodeRD(inst), false}; }
+constexpr RxC DecodeCI_RD(uint32_t inst) { return RxC{DecodeRD(inst), false}; }
+constexpr RxC DecodeCR_RS1(uint32_t inst) { return RxC{DecodeRD(inst), false}; }
+constexpr RxC DecodeCI_RS1(uint32_t inst) { return RxC{DecodeRD(inst), false}; }
+constexpr RxC DecodeCR_RS2(uint32_t inst) {
+  return RxC{(inst & 0x7C) >> 2, false};
+}
+
+constexpr RxC DecodeCIW_RD(uint32_t inst) { return RxC{(inst & 0x1C) >> 2}; }
+constexpr RxC DecodeCL_RD(uint32_t inst) { return RxC{DecodeCIW_RD(inst)}; }
+constexpr RxC DecodeCA_RD(uint32_t inst) { return RxC{(inst & 0x380) >> 7}; }
+constexpr RxC DecodeCB_RD(uint32_t inst) { return RxC{DecodeCA_RD(inst)}; }
+
+constexpr RxC DecodeCL_RS1(uint32_t inst) { return RxC{DecodeCA_RD(inst)}; }
+constexpr RxC DecodeCS_RS1(uint32_t inst) { return RxC{DecodeCA_RD(inst)}; }
+constexpr RxC DecodeCA_RS1(uint32_t inst) { return RxC{DecodeCA_RD(inst)}; }
+constexpr RxC DecodeCB_RS1(uint32_t inst) { return RxC{DecodeCA_RD(inst)}; }
+
+constexpr RxC DecodeCSS_RS2(uint32_t inst) { return DecodeCR_RS2(inst); }
+constexpr RxC DecodeCS_RS2(uint32_t inst) { return RxC{DecodeCIW_RD(inst)}; }
+constexpr RxC DecodeCA_RS2(uint32_t inst) { return RxC{DecodeCIW_RD(inst)}; }
+
+RISCVInst DecodeC_LWSP(uint32_t inst) {
+  auto rd = DecodeCI_RD(inst);
+  uint16_t offset = ((inst << 4) & 0xc0)    // offset[7:6]
+                    | ((inst >> 7) & 0x20)  // offset[5]
+                    | ((inst >> 2) & 0x1c); // offset[4:2]
+  if (rd == 0)
+    return RESERVED{inst};
+  return LW{rd, Rs{gpr_sp_riscv}, uint32_t(offset)};
+}
+
+RISCVInst DecodeC_LDSP(uint32_t inst) {
+  auto rd = DecodeCI_RD(inst);
+  uint16_t offset = ((inst << 4) & 0x1c0)   // offset[8:6]
+                    | ((inst >> 7) & 0x20)  // offset[5]
+                    | ((inst >> 2) & 0x18); // offset[4:3]
+  if (rd == 0)
+    return RESERVED{inst};
+  return LD{rd, Rs{gpr_sp_riscv}, uint32_t(offset)};
+}
+
+RISCVInst DecodeC_SWSP(uint32_t inst) {
+  uint16_t offset = ((inst >> 1) & 0xc0)    // offset[7:6]
+                    | ((inst >> 7) & 0x3c); // offset[5:2]
+  return SW{Rs{gpr_sp_riscv}, DecodeCSS_RS2(inst), uint32_t(offset)};
+}
+
+RISCVInst DecodeC_SDSP(uint32_t inst) {
+  uint16_t offset = ((inst >> 1) & 0x1c0)   // offset[8:6]
+                    | ((inst >> 7) & 0x38); // offset[5:3]
+  return SD{Rs{gpr_sp_riscv}, DecodeCSS_RS2(inst), uint32_t(offset)};
+}
+
+RISCVInst DecodeC_LW(uint32_t inst) {
+  uint16_t offset = ((inst << 1) & 0x40)   // imm[6]
+                    | ((inst >> 7) & 0x38) // imm[5:3]
+                    | ((inst >> 4) & 0x4); // imm[2]
+  return LW{DecodeCL_RD(inst), DecodeCL_RS1(inst), uint32_t(offset)};
+}
+
+RISCVInst DecodeC_LD(uint32_t inst) {
+  uint16_t offset = ((inst << 1) & 0xc0)    // imm[7:6]
+                    | ((inst >> 7) & 0x38); // imm[5:3]
+  return LD{DecodeCL_RD(inst), DecodeCL_RS1(inst), uint32_t(offset)};
+}
+
+RISCVInst DecodeC_SW(uint32_t inst) {
+  uint16_t offset = ((inst << 1) & 0x40)   // imm[6]
+                    | ((inst >> 7) & 0x38) // imm[5:3]
+                    | ((inst >> 4) & 0x4); // imm[2]
+  return SW{DecodeCS_RS1(inst), DecodeCS_RS2(inst), uint32_t(offset)};
+}
+
+RISCVInst DecodeC_SD(uint32_t inst) {
+  uint16_t offset = ((inst << 1) & 0xc0)    // imm[7:6]
+                    | ((inst >> 7) & 0x38); // imm[5:3]
+  return SD{DecodeCS_RS1(inst), DecodeCS_RS2(inst), uint32_t(offset)};
+}
+
+RISCVInst DecodeC_J(uint32_t inst) {
+  uint16_t offset = ((inst >> 1) & 0x800)   // offset[11]
+                    | ((inst << 2) & 0x400) // offset[10]
+                    | ((inst >> 1) & 0x300) // offset[9:8]
+                    | ((inst << 1) & 0x80)  // offset[7]
+                    | ((inst >> 1) & 0x40)  // offset[6]
+                    | ((inst << 3) & 0x20)  // offset[5]
+                    | ((inst >> 7) & 0x10)  // offset[4]
+                    | ((inst >> 2) & 0xe);  // offset[3:1]
+  if ((offset & 0x800) == 0)
+    return JAL{Rd{0}, uint32_t(offset)};
+  return JAL{Rd{0}, uint32_t(int32_t(int16_t(offset | 0xf000)))};
+}
+
+RISCVInst DecodeC_JR(uint32_t inst) {
+  auto rs1 = DecodeCR_RS1(inst);
+  if (rs1 == 0)
+    return RESERVED{inst};
+  return JALR{Rd{0}, rs1, 0};
+}
+
+RISCVInst DecodeC_JALR(uint32_t inst) {
+  auto rs1 = DecodeCR_RS1(inst);
+  if (rs1 == 0)
+    return EBREAK{inst};
+  return JALR{Rd{1}, rs1, 0};
+}
+
+constexpr uint16_t BOffset(uint32_t inst) {
+  return ((inst >> 4) & 0x100)  // offset[8]
+         | ((inst << 1) & 0xc0) // offset[7:6]
+         | ((inst << 3) & 0x20) // offset[5]
+         | ((inst >> 7) & 0x18) // offset[4:3]
+         | ((inst >> 2) & 0x6); // offset[2:1]
+}
+
+RISCVInst DecodeC_BNEZ(uint32_t inst) {
+  auto rs1 = DecodeCB_RS1(inst);
+  uint16_t offset = BOffset(inst);
+  if ((offset & 0x100) == 0)
+    return B{rs1, Rs{0}, uint32_t(offset), 0b001};
+  return B{rs1, Rs{0}, uint32_t(int32_t(int16_t(offset | 0xfe00))), 0b001};
+}
+
+RISCVInst DecodeC_BEQZ(uint32_t inst) {
+  auto rs1 = DecodeCB_RS1(inst);
+  uint16_t offset = BOffset(inst);
+  if ((offset & 0x100) == 0)
+    return B{rs1, Rs{0}, uint32_t(offset), 0b000};
+  return B{rs1, Rs{0}, uint32_t(int32_t(int16_t(offset | 0xfe00))), 0b000};
+}
+
+RISCVInst DecodeC_LI(uint32_t inst) {
+  auto rd = DecodeCI_RD(inst);
+  uint16_t imm = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f);
+  if ((imm & 0x20) == 0)
+    return ADDI{rd, Rs{0}, uint32_t(imm)};
+  return ADDI{rd, Rs{0}, uint32_t(int32_t(int8_t(imm | 0xc0)))};
+}
+
+RISCVInst DecodeC_LUI_ADDI16SP(uint32_t inst) {
+  auto rd = DecodeCI_RD(inst);
+  if (rd == 0)
+    return HINT{inst};
+  if (rd == 2) {
+    uint16_t nzimm = ((inst >> 3) & 0x200)   // nzimm[9]
+                     | ((inst >> 2) & 0x10)  // nzimm[4]
+                     | ((inst << 1) & 0x40)  // nzimm[6]
+                     | ((inst << 4) & 0x180) // nzimm[8:7]
+                     | ((inst << 3) & 0x20); // nzimm[5]
+    if (nzimm == 0)
+      return RESERVED{inst};
+    if ((nzimm & 0x200) == 0)
+      return ADDI{Rd{gpr_sp_riscv}, Rs{gpr_sp_riscv}, uint32_t(nzimm)};
+    return ADDI{Rd{gpr_sp_riscv}, Rs{gpr_sp_riscv},
+                uint32_t(int32_t(int16_t(nzimm | 0xfc00)))};
+  }
+  uint32_t imm =
+      ((uint32_t(inst) << 5) & 0x20000) | ((uint32_t(inst) << 10) & 0x1f000);
+  if ((imm & 0x20000) == 0)
+    return LUI{rd, imm};
+  return LUI{rd, uint32_t(int32_t(imm | 0xfffc0000))};
+}
+
+RISCVInst DecodeC_ADDI(uint32_t inst) {
+  auto rd = DecodeCI_RD(inst);
+  if (rd == 0)
+    return NOP{inst};
+  uint16_t imm = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f);
+  if ((imm & 0x20) == 0)
+    return ADDI{rd, rd, uint32_t(imm)};
+  return ADDI{rd, rd, uint32_t(int32_t(int8_t(imm | 0xc0)))};
+}
+
+RISCVInst DecodeC_ADDIW(uint32_t inst) {
+  auto rd = DecodeCI_RD(inst);
+  if (rd == 0)
+    return RESERVED{inst};
+  uint16_t imm = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f);
+  if ((imm & 0x20) == 0)
+    return ADDIW{rd, rd, uint32_t(imm)};
+  return ADDIW{rd, rd, uint32_t(int32_t(int8_t(imm | 0xc0)))};
+}
+
+RISCVInst DecodeC_ADDI4SPN(uint32_t inst) {
+  auto rd = DecodeCIW_RD(inst);
+  uint16_t nzuimm = ((inst >> 1) & 0x3c0)  // nzuimm[9:6]
+                    | ((inst >> 7) & 0x30) // nzuimm[5:4]
+                    | ((inst >> 2) & 0x8)  // nzuimm[3]
+                    | ((inst >> 4) & 0x4); // nzuimm[2]
+
+  if (rd == 0 && nzuimm == 0)
+    return INVALID{inst};
+  if (nzuimm == 0)
+    return RESERVED{inst};
+  return ADDI{rd, Rs{gpr_sp_riscv}, uint32_t(nzuimm)};
+}
+
+RISCVInst DecodeC_SLLI(uint32_t inst) {
+  auto rd = DecodeCI_RD(inst);
+  uint16_t shamt = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f);
+  if (rd == 0 || shamt == 0)
+    return HINT{inst};
+  return SLLI{rd, rd, uint8_t(shamt)};
+}
+
+RISCVInst DecodeC_SRLI(uint32_t inst) {
+  auto rd = DecodeCB_RD(inst);
+  uint16_t shamt = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f);
+  if (shamt == 0)
+    return HINT{inst};
+  return SRLI{rd, rd, uint8_t(shamt)};
+}
+
+RISCVInst DecodeC_SRAI(uint32_t inst) {
+  auto rd = DecodeCB_RD(inst);
+  uint16_t shamt = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f);
+  if (shamt == 0)
+    return HINT{inst};
+  return SRAI{rd, rd, uint8_t(shamt)};
+}
+
+RISCVInst DecodeC_ANDI(uint32_t inst) {
+  auto rd = DecodeCB_RD(inst);
+  uint16_t imm = ((inst >> 7) & 0x20) | ((inst >> 2) & 0x1f);
+  if ((imm & 0x20) == 0)
+    return ANDI{rd, rd, uint32_t(imm)};
+  return ANDI{rd, rd, uint32_t(int32_t(int8_t(imm | 0xc0)))};
+}
+
+RISCVInst DecodeC_MV(uint32_t inst) {
+  auto rd = DecodeCR_RD(inst);
+  auto rs2 = DecodeCR_RS2(inst);
+  if (rd == 0)
+    return HINT{inst};
+  return ADD{rd, Rs{0}, rs2};
+}
+
+RISCVInst DecodeC_ADD(uint32_t inst) {
+  auto rd = DecodeCR_RD(inst);
+  return ADD{rd, rd, DecodeCR_RS2(inst)};
+}
+
+RISCVInst DecodeC_AND(uint32_t inst) {
+  auto rd = DecodeCA_RD(inst);
+  return AND{rd, rd, DecodeCA_RS2(inst)};
+}
+
+RISCVInst DecodeC_OR(uint32_t inst) {
+  auto rd = DecodeCA_RD(inst);
+  return OR{rd, rd, DecodeCA_RS2(inst)};
+}
+
+RISCVInst DecodeC_XOR(uint32_t inst) {
+  auto rd = DecodeCA_RD(inst);
+  return XOR{rd, rd, DecodeCA_RS2(inst)};
+}
+
+RISCVInst DecodeC_SUB(uint32_t inst) {
+  auto rd = DecodeCA_RD(inst);
+  return SUB{rd, rd, DecodeCA_RS2(inst)};
+}
+
+RISCVInst DecodeC_SUBW(uint32_t inst) {
+  auto rd = DecodeCA_RD(inst);
+  return SUBW{rd, rd, DecodeCA_RS2(inst)};
+}
+
+RISCVInst DecodeC_ADDW(uint32_t inst) {
+  auto rd = DecodeCA_RD(inst);
+  return ADDW{rd, rd, DecodeCA_RS2(inst)};
+}
+
+} // namespace lldb_private
+#endif // LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVCINSTRUCTION_H

diff  --git a/lldb/source/Plugins/Instruction/RISCV/RISCVInstructions.h b/lldb/source/Plugins/Instruction/RISCV/RISCVInstructions.h
index 380dcefeecfd2..5b29fce4ec5bf 100644
--- a/lldb/source/Plugins/Instruction/RISCV/RISCVInstructions.h
+++ b/lldb/source/Plugins/Instruction/RISCV/RISCVInstructions.h
@@ -68,6 +68,11 @@ struct Rs {
     Rd rd;                                                                     \
     Rs rs1;                                                                    \
   }
+/// The `inst` fields are used for debugging.
+#define INVALID_INST(NAME)                                                     \
+  struct NAME {                                                                \
+    uint32_t inst;                                                             \
+  }
 
 // RV32I instructions (The base integer ISA)
 struct B {
@@ -165,16 +170,22 @@ R_TYPE_INST(AMOMAX_D);
 R_TYPE_INST(AMOMINU_D);
 R_TYPE_INST(AMOMAXU_D);
 
-using RISCVInst =
-    std::variant<LUI, AUIPC, JAL, JALR, B, LB, LH, LW, LBU, LHU, SB, SH, SW,
-                 ADDI, SLTI, SLTIU, XORI, ORI, ANDI, ADD, SUB, SLL, SLT, SLTU,
-                 XOR, SRL, SRA, OR, AND, LWU, LD, SD, SLLI, SRLI, SRAI, ADDIW,
-                 SLLIW, SRLIW, SRAIW, ADDW, SUBW, SLLW, SRLW, SRAW, MUL, MULH,
-                 MULHSU, MULHU, DIV, DIVU, REM, REMU, MULW, DIVW, DIVUW, REMW,
-                 REMUW, LR_W, SC_W, AMOSWAP_W, AMOADD_W, AMOXOR_W, AMOAND_W,
-                 AMOOR_W, AMOMIN_W, AMOMAX_W, AMOMINU_W, AMOMAXU_W, LR_D, SC_D,
-                 AMOSWAP_D, AMOADD_D, AMOXOR_D, AMOAND_D, AMOOR_D, AMOMIN_D,
-                 AMOMAX_D, AMOMINU_D, AMOMAXU_D>;
+/// Invalid and reserved instructions, the `inst` fields are used for debugging.
+INVALID_INST(INVALID);
+INVALID_INST(RESERVED);
+INVALID_INST(EBREAK);
+INVALID_INST(HINT);
+INVALID_INST(NOP);
+
+using RISCVInst = std::variant<
+    LUI, AUIPC, JAL, JALR, B, LB, LH, LW, LBU, LHU, SB, SH, SW, ADDI, SLTI,
+    SLTIU, XORI, ORI, ANDI, ADD, SUB, SLL, SLT, SLTU, XOR, SRL, SRA, OR, AND,
+    LWU, LD, SD, SLLI, SRLI, SRAI, ADDIW, SLLIW, SRLIW, SRAIW, ADDW, SUBW, SLLW,
+    SRLW, SRAW, MUL, MULH, MULHSU, MULHU, DIV, DIVU, REM, REMU, MULW, DIVW,
+    DIVUW, REMW, REMUW, LR_W, SC_W, AMOSWAP_W, AMOADD_W, AMOXOR_W, AMOAND_W,
+    AMOOR_W, AMOMIN_W, AMOMAX_W, AMOMINU_W, AMOMAXU_W, LR_D, SC_D, AMOSWAP_D,
+    AMOADD_D, AMOXOR_D, AMOAND_D, AMOOR_D, AMOMIN_D, AMOMAX_D, AMOMINU_D,
+    AMOMAXU_D, INVALID, EBREAK, RESERVED, HINT, NOP>;
 
 struct InstrPattern {
   const char *name;
@@ -196,25 +207,5 @@ constexpr uint32_t DecodeRD(uint32_t inst) { return (inst & 0xF80) >> 7; }
 constexpr uint32_t DecodeRS1(uint32_t inst) { return (inst & 0xF8000) >> 15; }
 constexpr uint32_t DecodeRS2(uint32_t inst) { return (inst & 0x1F00000) >> 20; }
 
-// decode register for RVC
-constexpr uint16_t DecodeCR_RD(uint16_t inst) { return DecodeRD(inst); }
-constexpr uint16_t DecodeCI_RD(uint16_t inst) { return DecodeRD(inst); }
-constexpr uint16_t DecodeCIW_RD(uint16_t inst) { return (inst & 0x1C) >> 2; }
-constexpr uint16_t DecodeCL_RD(uint16_t inst) { return DecodeCIW_RD(inst); }
-constexpr uint16_t DecodeCA_RD(uint16_t inst) { return (inst & 0x380) >> 7; }
-constexpr uint16_t DecodeCB_RD(uint16_t inst) { return DecodeCA_RD(inst); }
-
-constexpr uint16_t DecodeCR_RS1(uint16_t inst) { return DecodeRD(inst); }
-constexpr uint16_t DecodeCI_RS1(uint16_t inst) { return DecodeRD(inst); }
-constexpr uint16_t DecodeCL_RS1(uint16_t inst) { return DecodeCA_RD(inst); }
-constexpr uint16_t DecodeCS_RS1(uint16_t inst) { return DecodeCA_RD(inst); }
-constexpr uint16_t DecodeCA_RS1(uint16_t inst) { return DecodeCA_RD(inst); }
-constexpr uint16_t DecodeCB_RS1(uint16_t inst) { return DecodeCA_RD(inst); }
-
-constexpr uint16_t DecodeCR_RS2(uint16_t inst) { return (inst & 0x7C) >> 2; }
-constexpr uint16_t DecodeCSS_RS2(uint16_t inst) { return DecodeCR_RS2(inst); }
-constexpr uint16_t DecodeCS_RS2(uint16_t inst) { return DecodeCIW_RD(inst); }
-constexpr uint16_t DecodeCA_RS2(uint16_t inst) { return DecodeCIW_RD(inst); }
-
 } // namespace lldb_private
 #endif // LLDB_SOURCE_PLUGINS_INSTRUCTION_RISCV_RISCVINSTRUCTION_H

diff  --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp
index 4e09a6cf35627..306ee99be5952 100644
--- a/lldb/source/Target/Platform.cpp
+++ b/lldb/source/Target/Platform.cpp
@@ -1929,8 +1929,14 @@ size_t Platform::GetSoftwareBreakpointTrapOpcode(Target &target,
   case llvm::Triple::riscv32:
   case llvm::Triple::riscv64: {
     static const uint8_t g_riscv_opcode[] = {0x73, 0x00, 0x10, 0x00}; // ebreak
-    trap_opcode = g_riscv_opcode;
-    trap_opcode_size = sizeof(g_riscv_opcode);
+    static const uint8_t g_riscv_opcode_c[] = {0x02, 0x90}; // c.ebreak
+    if (arch.GetFlags() & ArchSpec::eRISCV_rvc) {
+      trap_opcode = g_riscv_opcode_c;
+      trap_opcode_size = sizeof(g_riscv_opcode_c);
+    } else {
+      trap_opcode = g_riscv_opcode;
+      trap_opcode_size = sizeof(g_riscv_opcode);
+    }
   } break;
 
   default:

diff  --git a/lldb/unittests/Instruction/RISCV/TestRISCVEmulator.cpp b/lldb/unittests/Instruction/RISCV/TestRISCVEmulator.cpp
index 5645bae8016bb..9d58983b6532b 100644
--- a/lldb/unittests/Instruction/RISCV/TestRISCVEmulator.cpp
+++ b/lldb/unittests/Instruction/RISCV/TestRISCVEmulator.cpp
@@ -256,6 +256,88 @@ TEST_F(RISCVEmulatorTester, TestAtomicSequence) {
   ASSERT_EQ(this->gpr.gpr[0], uint64_t(16));
 }
 
+struct TestDecode {
+  uint32_t inst;
+  RISCVInst inst_type;
+};
+
+bool compareInst(const RISCVInst &lhs, const RISCVInst &rhs) {
+  if (lhs.index() != rhs.index())
+    return false;
+  return std::visit(
+      [&](auto &&L) {
+        return std::visit(
+            [&](auto &&R) {
+              // guaranteed by
+              // 1. lhs.index() == rhs.index()
+              // (they are the same instruction type)
+              // 2. all instruction representations are plain data objects
+              // consisting of primitive types.
+              return std::memcmp(&L, &R, sizeof(L)) == 0;
+            },
+            rhs);
+      },
+      lhs);
+}
+
+TEST_F(RISCVEmulatorTester, TestCDecode) {
+  std::vector<TestDecode> tests = {
+      {0x0000, INVALID{0x0000}},
+      {0x0010, RESERVED{0x0010}},
+      // ADDI4SPN here, decode as ADDI
+      {0x0024, ADDI{Rd{9}, Rs{2}, 8}},
+      {0x4488, LW{Rd{10}, Rs{9}, 8}},
+      {0x6488, LD{Rd{10}, Rs{9}, 8}},
+      {0xC488, SW{Rs{9}, Rs{10}, 8}},
+      {0xE488, SD{Rs{9}, Rs{10}, 8}},
+      {0x1001, NOP{0x1001}},
+      {0x1085, ADDI{Rd{1}, Rs{1}, uint32_t(-31)}},
+      {0x2081, ADDIW{Rd{1}, Rs{1}, 0}},
+      // ADDI16SP here, decode as ADDI
+      {0x7101, ADDI{Rd{2}, Rs{2}, uint32_t(-512)}},
+      {0x4081, ADDI{Rd{1}, Rs{0}, 0}},
+      {0x7081, LUI{Rd{1}, uint32_t(-131072)}},
+      {0x8085, SRLI{Rd{9}, Rs{9}, 1}},
+      {0x8485, SRAI{Rd{9}, Rs{9}, 1}},
+      {0x8881, ANDI{Rd{9}, Rs{9}, 0}},
+      {0x8C85, SUB{Rd{9}, Rs{9}, Rs{9}}},
+      {0x8CA5, XOR{Rd{9}, Rs{9}, Rs{9}}},
+      {0x8CC5, OR{Rd{9}, Rs{9}, Rs{9}}},
+      {0x8CE5, AND{Rd{9}, Rs{9}, Rs{9}}},
+      {0x9C85, SUBW{Rd{9}, Rs{9}, Rs{9}}},
+      {0x9CA5, ADDW{Rd{9}, Rs{9}, Rs{9}}},
+      // C.J here, decoded as JAL
+      {0xA001, JAL{Rd{0}, 0}},
+      {0xC081, B{Rs{9}, Rs{0}, 0, 0b000}},
+      {0xE081, B{Rs{9}, Rs{0}, 0, 0b001}},
+      {0x1082, SLLI{Rd{1}, Rs{1}, 32}},
+      {0x1002, HINT{0x1002}},
+      // SLLI64 here, decoded as HINT if not in RV128
+      {0x0082, HINT{0x0082}},
+      // LWSP here, decoded as LW
+      {0x4082, LW{Rd{1}, Rs{2}, 0}},
+      // LDSP here, decoded as LD
+      {0x6082, LD{Rd{1}, Rs{2}, 0}},
+      // C.JR here, decoded as JALR
+      {0x8082, JALR{Rd{0}, Rs{1}, 0}},
+      // C.MV here, decoded as ADD
+      {0x8086, ADD{Rd{1}, Rs{0}, Rs{1}}},
+      {0x9002, EBREAK{0x9002}},
+      {0x9082, JALR{Rd{1}, Rs{1}, 0}},
+      {0x9086, ADD{Rd{1}, Rs{1}, Rs{1}}},
+      // C.SWSP here, decoded as SW
+      {0xC006, SW{Rs{2}, Rs{1}, 0}},
+      // C.SDSP here, decoded as SD
+      {0xE006, SD{Rs{2}, Rs{1}, 0}},
+  };
+
+  for (auto i : tests) {
+    auto decode = this->Decode(i.inst);
+    ASSERT_TRUE(decode.has_value());
+    ASSERT_TRUE(compareInst(decode->decoded, i.inst_type));
+  }
+}
+
 // GEN_BRANCH_TEST(opcode, imm1, imm2, imm3):
 // It should branch for instruction `opcode imm1, imm2`
 // It should do nothing for instruction `opcode imm1, imm3`
@@ -274,7 +356,6 @@ struct TestData {
 };
 
 TEST_F(RISCVEmulatorTester, TestDecodeAndExcute) {
-
   std::vector<TestData> tests = {
       // RV32I & RV64I Tests
       {0x00010113, "ADDI", false, [](RS1 rs1, RS2, PC) { return rs1 + 0; }},


        


More information about the lldb-commits mailing list