@@ -33,6 +33,10 @@ LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionRISCV, InstructionRISCV)
33
33
34
34
namespace lldb_private {
35
35
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
+
36
40
// / Returns all values wrapped in Optional, or std::nullopt if any of the values
37
41
// / is std::nullopt.
38
42
template <typename ... Ts>
@@ -108,6 +112,16 @@ static uint32_t FPREncodingToLLDB(uint32_t reg_encode) {
108
112
return LLDB_INVALID_REGNUM;
109
113
}
110
114
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
+
111
125
bool Rd::Write (EmulateInstructionRISCV &emulator, uint64_t value) {
112
126
uint32_t lldb_reg = GPREncodingToLLDB (rd);
113
127
EmulateInstruction::Context ctx;
@@ -230,10 +244,34 @@ Load(EmulateInstructionRISCV &emulator, I inst, uint64_t (*extend)(E)) {
230
244
auto addr = LoadStoreAddr (emulator, inst);
231
245
if (!addr)
232
246
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))));
237
275
}
238
276
239
277
template <typename I, typename T>
@@ -242,9 +280,35 @@ Store(EmulateInstructionRISCV &emulator, I inst) {
242
280
auto addr = LoadStoreAddr (emulator, inst);
243
281
if (!addr)
244
282
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
+ })
248
312
.value_or (false );
249
313
}
250
314
@@ -737,11 +801,44 @@ class Executor {
737
801
bool operator ()(SH inst) { return Store<SH, uint16_t >(m_emu, inst); }
738
802
bool operator ()(SW inst) { return Store<SW, uint32_t >(m_emu, inst); }
739
803
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
+ })
745
842
.value_or (false );
746
843
}
747
844
bool operator ()(SLTI inst) {
@@ -1745,6 +1842,61 @@ EmulateInstructionRISCV::GetRegisterInfo(RegisterKind reg_kind,
1745
1842
return array[reg_index];
1746
1843
}
1747
1844
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
+
1748
1900
bool EmulateInstructionRISCV::SetTargetTriple (const ArchSpec &arch) {
1749
1901
return SupportsThisArch (arch);
1750
1902
}
0 commit comments