@@ -33,6 +33,10 @@ LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionRISCV, InstructionRISCV)
3333
3434namespace lldb_private {
3535
36+ // RISC-V General Purpose Register numbers
37+ static constexpr uint32_t RISCV_GPR_SP = 2 ; // x2 is the stack pointer
38+ static constexpr uint32_t RISCV_GPR_FP = 8 ; // x8 is the frame pointer
39+
3640// / Returns all values wrapped in Optional, or std::nullopt if any of the values
3741// / is std::nullopt.
3842template <typename ... Ts>
@@ -108,6 +112,16 @@ static uint32_t FPREncodingToLLDB(uint32_t reg_encode) {
108112 return LLDB_INVALID_REGNUM;
109113}
110114
115+ // Helper function to get register info from GPR encoding
116+ static std::optional<RegisterInfo>
117+ GPREncodingToRegisterInfo (EmulateInstructionRISCV &emulator,
118+ uint32_t reg_encode) {
119+ uint32_t lldb_reg = GPREncodingToLLDB (reg_encode);
120+ if (lldb_reg == LLDB_INVALID_REGNUM)
121+ return std::nullopt ;
122+ return emulator.GetRegisterInfo (eRegisterKindLLDB, lldb_reg);
123+ }
124+
111125bool Rd::Write (EmulateInstructionRISCV &emulator, uint64_t value) {
112126 uint32_t lldb_reg = GPREncodingToLLDB (rd);
113127 EmulateInstruction::Context ctx;
@@ -230,10 +244,34 @@ Load(EmulateInstructionRISCV &emulator, I inst, uint64_t (*extend)(E)) {
230244 auto addr = LoadStoreAddr (emulator, inst);
231245 if (!addr)
232246 return false ;
233- return transformOptional (
234- emulator.ReadMem <T>(*addr),
235- [&](T t) { return inst.rd .Write (emulator, extend (E (t))); })
236- .value_or (false );
247+
248+ // Set up context for the load operation, similar to ARM64.
249+ EmulateInstructionRISCV::Context context;
250+
251+ // Get register info for base register
252+ std::optional<RegisterInfo> reg_info_rs1 =
253+ GPREncodingToRegisterInfo (emulator, inst.rs1 .rs );
254+
255+ if (!reg_info_rs1)
256+ return false ;
257+
258+ // Set context type based on whether this is a stack-based load.
259+ if (inst.rs1 .rs == RISCV_GPR_SP)
260+ context.type = EmulateInstruction::eContextPopRegisterOffStack;
261+ else
262+ context.type = EmulateInstruction::eContextRegisterLoad;
263+
264+ // Set the context address information
265+ context.SetAddress (*addr);
266+
267+ // Read from memory with context and write to register.
268+ bool success = false ;
269+ uint64_t value =
270+ emulator.ReadMemoryUnsigned (context, *addr, sizeof (T), 0 , &success);
271+ if (!success)
272+ return false ;
273+
274+ return inst.rd .Write (emulator, extend (E (T (value))));
237275}
238276
239277template <typename I, typename T>
@@ -242,9 +280,35 @@ Store(EmulateInstructionRISCV &emulator, I inst) {
242280 auto addr = LoadStoreAddr (emulator, inst);
243281 if (!addr)
244282 return false ;
245- return transformOptional (
246- inst.rs2 .Read (emulator),
247- [&](uint64_t rs2) { return emulator.WriteMem <T>(*addr, rs2); })
283+
284+ // Set up context for the store operation, similar to ARM64.
285+ EmulateInstructionRISCV::Context context;
286+
287+ // Get register info for source and base registers.
288+ std::optional<RegisterInfo> reg_info_rs1 =
289+ GPREncodingToRegisterInfo (emulator, inst.rs1 .rs );
290+ std::optional<RegisterInfo> reg_info_rs2 =
291+ GPREncodingToRegisterInfo (emulator, inst.rs2 .rs );
292+
293+ if (!reg_info_rs1 || !reg_info_rs2)
294+ return false ;
295+
296+ // Set context type based on whether this is a stack-based store.
297+ if (inst.rs1 .rs == RISCV_GPR_SP)
298+ context.type = EmulateInstruction::eContextPushRegisterOnStack;
299+ else
300+ context.type = EmulateInstruction::eContextRegisterStore;
301+
302+ // Set the context to show which register is being stored to which base
303+ // register + offset.
304+ context.SetRegisterToRegisterPlusOffset (*reg_info_rs2, *reg_info_rs1,
305+ SignExt (inst.imm ));
306+
307+ return transformOptional (inst.rs2 .Read (emulator),
308+ [&](uint64_t rs2) {
309+ return emulator.WriteMemoryUnsigned (
310+ context, *addr, rs2, sizeof (T));
311+ })
248312 .value_or (false );
249313}
250314
@@ -737,11 +801,44 @@ class Executor {
737801 bool operator ()(SH inst) { return Store<SH, uint16_t >(m_emu, inst); }
738802 bool operator ()(SW inst) { return Store<SW, uint32_t >(m_emu, inst); }
739803 bool operator ()(ADDI inst) {
740- return transformOptional (inst.rs1 .ReadI64 (m_emu),
741- [&](int64_t rs1) {
742- return inst.rd .Write (
743- m_emu, rs1 + int64_t (SignExt (inst.imm )));
744- })
804+ return transformOptional (
805+ inst.rs1 .ReadI64 (m_emu),
806+ [&](int64_t rs1) {
807+ int64_t result = rs1 + int64_t (SignExt (inst.imm ));
808+ // Check if this is a stack pointer adjustment.
809+ if (inst.rd .rd == RISCV_GPR_SP &&
810+ inst.rs1 .rs == RISCV_GPR_SP) {
811+ EmulateInstruction::Context context;
812+ context.type =
813+ EmulateInstruction::eContextAdjustStackPointer;
814+ context.SetImmediateSigned (SignExt (inst.imm ));
815+ uint32_t sp_lldb_reg = GPREncodingToLLDB (RISCV_GPR_SP);
816+ RegisterValue registerValue;
817+ registerValue.SetUInt64 (result);
818+ return m_emu.WriteRegister (context, eRegisterKindLLDB,
819+ sp_lldb_reg, registerValue);
820+ }
821+ // Check if this is setting up the frame pointer.
822+ // addi fp, sp, imm -> fp = sp + imm (frame pointer setup).
823+ if (inst.rd .rd == RISCV_GPR_FP &&
824+ inst.rs1 .rs == RISCV_GPR_SP) {
825+ EmulateInstruction::Context context;
826+ context.type = EmulateInstruction::eContextSetFramePointer;
827+ auto sp_reg_info = m_emu.GetRegisterInfo (
828+ eRegisterKindLLDB, GPREncodingToLLDB (RISCV_GPR_SP));
829+ if (sp_reg_info) {
830+ context.SetRegisterPlusOffset (*sp_reg_info,
831+ SignExt (inst.imm ));
832+ }
833+ uint32_t fp_lldb_reg = GPREncodingToLLDB (RISCV_GPR_FP);
834+ RegisterValue registerValue;
835+ registerValue.SetUInt64 (result);
836+ return m_emu.WriteRegister (context, eRegisterKindLLDB,
837+ fp_lldb_reg, registerValue);
838+ }
839+ // Regular ADDI instruction.
840+ return inst.rd .Write (m_emu, result);
841+ })
745842 .value_or (false );
746843 }
747844 bool operator ()(SLTI inst) {
@@ -1745,6 +1842,61 @@ EmulateInstructionRISCV::GetRegisterInfo(RegisterKind reg_kind,
17451842 return array[reg_index];
17461843}
17471844
1845+ bool EmulateInstructionRISCV::SetInstruction (const Opcode &opcode,
1846+ const Address &inst_addr,
1847+ Target *target) {
1848+ // Call the base class implementation.
1849+ if (!EmulateInstruction::SetInstruction (opcode, inst_addr, target))
1850+ return false ;
1851+
1852+ // Extract instruction data from the opcode.
1853+ uint32_t inst_data = 0 ;
1854+ const void *opcode_data = m_opcode.GetOpcodeBytes ();
1855+ if (!opcode_data)
1856+ return false ;
1857+
1858+ if (m_opcode.GetByteSize () == 2 ) {
1859+ // 16-bit compressed instruction.
1860+ const uint16_t *data = static_cast <const uint16_t *>(opcode_data);
1861+ inst_data = *data;
1862+ } else if (m_opcode.GetByteSize () == 4 ) {
1863+ // 32-bit instruction.
1864+ const uint32_t *data = static_cast <const uint32_t *>(opcode_data);
1865+ inst_data = *data;
1866+ } else {
1867+ return false ;
1868+ }
1869+
1870+ // Decode the instruction.
1871+ auto decoded_inst = Decode (inst_data);
1872+ if (!decoded_inst)
1873+ return false ;
1874+
1875+ // Store the decoded result.
1876+ m_decoded = *decoded_inst;
1877+ return true ;
1878+ }
1879+
1880+ bool EmulateInstructionRISCV::CreateFunctionEntryUnwind (
1881+ UnwindPlan &unwind_plan) {
1882+ unwind_plan.Clear ();
1883+ unwind_plan.SetRegisterKind (eRegisterKindLLDB);
1884+
1885+ UnwindPlan::Row row;
1886+
1887+ row.GetCFAValue ().SetIsRegisterPlusOffset (gpr_sp_riscv, 0 );
1888+ row.SetRegisterLocationToSame (gpr_ra_riscv, /* must_replace=*/ false );
1889+ row.SetRegisterLocationToSame (gpr_fp_riscv, /* must_replace=*/ false );
1890+
1891+ unwind_plan.AppendRow (std::move (row));
1892+ unwind_plan.SetSourceName (" EmulateInstructionRISCV" );
1893+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
1894+ unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes);
1895+ unwind_plan.SetUnwindPlanForSignalTrap (eLazyBoolNo);
1896+ unwind_plan.SetReturnAddressRegister (gpr_ra_riscv);
1897+ return true ;
1898+ }
1899+
17481900bool EmulateInstructionRISCV::SetTargetTriple (const ArchSpec &arch) {
17491901 return SupportsThisArch (arch);
17501902}
0 commit comments