@@ -230,10 +230,36 @@ Load(EmulateInstructionRISCV &emulator, I inst, uint64_t (*extend)(E)) {
230230 auto addr = LoadStoreAddr (emulator, inst);
231231 if (!addr)
232232 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 );
233+
234+ // Set up context for the load operation, similar to ARM64
235+ EmulateInstructionRISCV::Context context;
236+
237+ // Get register info for base register
238+ uint32_t rs1_lldb = GPREncodingToLLDB (inst.rs1 .rs );
239+ std::optional<RegisterInfo> reg_info_rs1 =
240+ emulator.GetRegisterInfo (eRegisterKindLLDB, rs1_lldb);
241+
242+ if (!reg_info_rs1)
243+ return false ;
244+
245+ // Set context type based on whether this is a stack-based load
246+ if (inst.rs1 .rs == 2 ) { // x2 is the stack pointer in RISC-V
247+ context.type = EmulateInstruction::eContextPopRegisterOffStack;
248+ } else {
249+ context.type = EmulateInstruction::eContextRegisterLoad;
250+ }
251+
252+ // Set the context address information
253+ context.SetAddress (*addr);
254+
255+ // Read from memory with context and write to register
256+ bool success = false ;
257+ uint64_t value =
258+ emulator.ReadMemoryUnsigned (context, *addr, sizeof (T), 0 , &success);
259+ if (!success)
260+ return false ;
261+
262+ return inst.rd .Write (emulator, extend (E (T (value))));
237263}
238264
239265template <typename I, typename T>
@@ -242,9 +268,38 @@ Store(EmulateInstructionRISCV &emulator, I inst) {
242268 auto addr = LoadStoreAddr (emulator, inst);
243269 if (!addr)
244270 return false ;
245- return transformOptional (
246- inst.rs2 .Read (emulator),
247- [&](uint64_t rs2) { return emulator.WriteMem <T>(*addr, rs2); })
271+
272+ // Set up context for the store operation, similar to ARM64
273+ EmulateInstructionRISCV::Context context;
274+
275+ // Get register info for source and base registers
276+ uint32_t rs1_lldb = GPREncodingToLLDB (inst.rs1 .rs );
277+ uint32_t rs2_lldb = GPREncodingToLLDB (inst.rs2 .rs );
278+ std::optional<RegisterInfo> reg_info_rs1 =
279+ emulator.GetRegisterInfo (eRegisterKindLLDB, rs1_lldb);
280+ std::optional<RegisterInfo> reg_info_rs2 =
281+ emulator.GetRegisterInfo (eRegisterKindLLDB, rs2_lldb);
282+
283+ if (!reg_info_rs1 || !reg_info_rs2)
284+ return false ;
285+
286+ // Set context type based on whether this is a stack-based store
287+ if (inst.rs1 .rs == 2 ) { // x2 is the stack pointer in RISC-V
288+ context.type = EmulateInstruction::eContextPushRegisterOnStack;
289+ } else {
290+ context.type = EmulateInstruction::eContextRegisterStore;
291+ }
292+
293+ // Set the context to show which register is being stored to which base
294+ // register + offset
295+ context.SetRegisterToRegisterPlusOffset (*reg_info_rs2, *reg_info_rs1,
296+ SignExt (inst.imm ));
297+
298+ return transformOptional (inst.rs2 .Read (emulator),
299+ [&](uint64_t rs2) {
300+ return emulator.WriteMemoryUnsigned (
301+ context, *addr, rs2, sizeof (T));
302+ })
248303 .value_or (false );
249304}
250305
@@ -737,11 +792,42 @@ class Executor {
737792 bool operator ()(SH inst) { return Store<SH, uint16_t >(m_emu, inst); }
738793 bool operator ()(SW inst) { return Store<SW, uint32_t >(m_emu, inst); }
739794 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- })
795+ return transformOptional (
796+ inst.rs1 .ReadI64 (m_emu),
797+ [&](int64_t rs1) {
798+ int64_t result = rs1 + int64_t (SignExt (inst.imm ));
799+ // Check if this is a stack pointer adjustment
800+ if (inst.rd .rd == 2 && inst.rs1 .rs == 2 ) { // rd=sp, rs1=sp
801+ EmulateInstruction::Context context;
802+ context.type =
803+ EmulateInstruction::eContextAdjustStackPointer;
804+ context.SetImmediateSigned (SignExt (inst.imm ));
805+ uint32_t sp_lldb_reg = GPREncodingToLLDB (2 );
806+ RegisterValue registerValue;
807+ registerValue.SetUInt64 (result);
808+ return m_emu.WriteRegister (context, eRegisterKindLLDB,
809+ sp_lldb_reg, registerValue);
810+ }
811+ // Check if this is setting up the frame pointer
812+ // addi fp, sp, imm -> fp = sp + imm (frame pointer setup)
813+ if (inst.rd .rd == 8 && inst.rs1 .rs == 2 ) { // rd=fp, rs1=sp
814+ EmulateInstruction::Context context;
815+ context.type = EmulateInstruction::eContextSetFramePointer;
816+ auto sp_reg_info = m_emu.GetRegisterInfo (
817+ eRegisterKindLLDB, GPREncodingToLLDB (2 ));
818+ if (sp_reg_info) {
819+ context.SetRegisterPlusOffset (*sp_reg_info,
820+ SignExt (inst.imm ));
821+ }
822+ uint32_t fp_lldb_reg = GPREncodingToLLDB (8 );
823+ RegisterValue registerValue;
824+ registerValue.SetUInt64 (result);
825+ return m_emu.WriteRegister (context, eRegisterKindLLDB,
826+ fp_lldb_reg, registerValue);
827+ }
828+ // Regular ADDI instruction
829+ return inst.rd .Write (m_emu, result);
830+ })
745831 .value_or (false );
746832 }
747833 bool operator ()(SLTI inst) {
@@ -1745,6 +1831,61 @@ EmulateInstructionRISCV::GetRegisterInfo(RegisterKind reg_kind,
17451831 return array[reg_index];
17461832}
17471833
1834+ bool EmulateInstructionRISCV::SetInstruction (const Opcode &opcode,
1835+ const Address &inst_addr,
1836+ Target *target) {
1837+ // Call the base class implementation
1838+ if (!EmulateInstruction::SetInstruction (opcode, inst_addr, target))
1839+ return false ;
1840+
1841+ // Extract instruction data from the opcode
1842+ uint32_t inst_data = 0 ;
1843+ const void *opcode_data = m_opcode.GetOpcodeBytes ();
1844+ if (!opcode_data)
1845+ return false ;
1846+
1847+ if (m_opcode.GetByteSize () == 2 ) {
1848+ // 16-bit compressed instruction
1849+ const uint16_t *data = static_cast <const uint16_t *>(opcode_data);
1850+ inst_data = *data;
1851+ } else if (m_opcode.GetByteSize () == 4 ) {
1852+ // 32-bit instruction
1853+ const uint32_t *data = static_cast <const uint32_t *>(opcode_data);
1854+ inst_data = *data;
1855+ } else {
1856+ return false ;
1857+ }
1858+
1859+ // Decode the instruction
1860+ auto decoded_inst = Decode (inst_data);
1861+ if (!decoded_inst)
1862+ return false ;
1863+
1864+ // Store the decoded result
1865+ m_decoded = *decoded_inst;
1866+ return true ;
1867+ }
1868+
1869+ bool EmulateInstructionRISCV::CreateFunctionEntryUnwind (
1870+ UnwindPlan &unwind_plan) {
1871+ unwind_plan.Clear ();
1872+ unwind_plan.SetRegisterKind (eRegisterKindLLDB);
1873+
1874+ UnwindPlan::Row row;
1875+
1876+ row.GetCFAValue ().SetIsRegisterPlusOffset (gpr_sp_riscv, 0 );
1877+ row.SetRegisterLocationToSame (gpr_ra_riscv, /* must_replace=*/ false );
1878+ row.SetRegisterLocationToSame (gpr_fp_riscv, /* must_replace=*/ false );
1879+
1880+ unwind_plan.AppendRow (std::move (row));
1881+ unwind_plan.SetSourceName (" EmulateInstructionRISCV" );
1882+ unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
1883+ unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes);
1884+ unwind_plan.SetUnwindPlanForSignalTrap (eLazyBoolNo);
1885+ unwind_plan.SetReturnAddressRegister (gpr_ra_riscv);
1886+ return true ;
1887+ }
1888+
17481889bool EmulateInstructionRISCV::SetTargetTriple (const ArchSpec &arch) {
17491890 return SupportsThisArch (arch);
17501891}
0 commit comments