xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1dda28197Spatrick //===-- EmulateInstructionPPC64.cpp ---------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "EmulateInstructionPPC64.h"
10061da546Spatrick 
11be691f3bSpatrick #include <cstdlib>
12*f6aab3d8Srobert #include <optional>
13061da546Spatrick 
14*f6aab3d8Srobert #include "Plugins/Process/Utility/lldb-ppc64le-register-enums.h"
15061da546Spatrick #include "lldb/Core/PluginManager.h"
16061da546Spatrick #include "lldb/Symbol/UnwindPlan.h"
17061da546Spatrick #include "lldb/Utility/ArchSpec.h"
18061da546Spatrick #include "lldb/Utility/ConstString.h"
19*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
20061da546Spatrick 
21061da546Spatrick #define DECLARE_REGISTER_INFOS_PPC64LE_STRUCT
22061da546Spatrick #include "Plugins/Process/Utility/RegisterInfos_ppc64le.h"
23061da546Spatrick 
24061da546Spatrick #include "Plugins/Process/Utility/InstructionUtils.h"
25061da546Spatrick 
26061da546Spatrick using namespace lldb;
27061da546Spatrick using namespace lldb_private;
28061da546Spatrick 
LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionPPC64,InstructionPPC64)29dda28197Spatrick LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionPPC64, InstructionPPC64)
30dda28197Spatrick 
31061da546Spatrick EmulateInstructionPPC64::EmulateInstructionPPC64(const ArchSpec &arch)
32061da546Spatrick     : EmulateInstruction(arch) {}
33061da546Spatrick 
Initialize()34061da546Spatrick void EmulateInstructionPPC64::Initialize() {
35061da546Spatrick   PluginManager::RegisterPlugin(GetPluginNameStatic(),
36061da546Spatrick                                 GetPluginDescriptionStatic(), CreateInstance);
37061da546Spatrick }
38061da546Spatrick 
Terminate()39061da546Spatrick void EmulateInstructionPPC64::Terminate() {
40061da546Spatrick   PluginManager::UnregisterPlugin(CreateInstance);
41061da546Spatrick }
42061da546Spatrick 
GetPluginDescriptionStatic()43*f6aab3d8Srobert llvm::StringRef EmulateInstructionPPC64::GetPluginDescriptionStatic() {
44061da546Spatrick   return "Emulate instructions for the PPC64 architecture.";
45061da546Spatrick }
46061da546Spatrick 
47061da546Spatrick EmulateInstruction *
CreateInstance(const ArchSpec & arch,InstructionType inst_type)48061da546Spatrick EmulateInstructionPPC64::CreateInstance(const ArchSpec &arch,
49061da546Spatrick                                         InstructionType inst_type) {
50061da546Spatrick   if (EmulateInstructionPPC64::SupportsEmulatingInstructionsOfTypeStatic(
51061da546Spatrick           inst_type))
52061da546Spatrick     if (arch.GetTriple().isPPC64())
53061da546Spatrick       return new EmulateInstructionPPC64(arch);
54061da546Spatrick 
55061da546Spatrick   return nullptr;
56061da546Spatrick }
57061da546Spatrick 
SetTargetTriple(const ArchSpec & arch)58061da546Spatrick bool EmulateInstructionPPC64::SetTargetTriple(const ArchSpec &arch) {
59061da546Spatrick   return arch.GetTriple().isPPC64();
60061da546Spatrick }
61061da546Spatrick 
LLDBTableGetRegisterInfo(uint32_t reg_num)62*f6aab3d8Srobert static std::optional<RegisterInfo> LLDBTableGetRegisterInfo(uint32_t reg_num) {
63*f6aab3d8Srobert   if (reg_num >= std::size(g_register_infos_ppc64le))
64*f6aab3d8Srobert     return {};
65*f6aab3d8Srobert   return g_register_infos_ppc64le[reg_num];
66061da546Spatrick }
67061da546Spatrick 
68*f6aab3d8Srobert std::optional<RegisterInfo>
GetRegisterInfo(RegisterKind reg_kind,uint32_t reg_num)69*f6aab3d8Srobert EmulateInstructionPPC64::GetRegisterInfo(RegisterKind reg_kind,
70*f6aab3d8Srobert                                          uint32_t reg_num) {
71061da546Spatrick   if (reg_kind == eRegisterKindGeneric) {
72061da546Spatrick     switch (reg_num) {
73061da546Spatrick     case LLDB_REGNUM_GENERIC_PC:
74061da546Spatrick       reg_kind = eRegisterKindLLDB;
75061da546Spatrick       reg_num = gpr_pc_ppc64le;
76061da546Spatrick       break;
77061da546Spatrick     case LLDB_REGNUM_GENERIC_SP:
78061da546Spatrick       reg_kind = eRegisterKindLLDB;
79061da546Spatrick       reg_num = gpr_r1_ppc64le;
80061da546Spatrick       break;
81061da546Spatrick     case LLDB_REGNUM_GENERIC_RA:
82061da546Spatrick       reg_kind = eRegisterKindLLDB;
83061da546Spatrick       reg_num = gpr_lr_ppc64le;
84061da546Spatrick       break;
85061da546Spatrick     case LLDB_REGNUM_GENERIC_FLAGS:
86061da546Spatrick       reg_kind = eRegisterKindLLDB;
87061da546Spatrick       reg_num = gpr_cr_ppc64le;
88061da546Spatrick       break;
89061da546Spatrick 
90061da546Spatrick     default:
91*f6aab3d8Srobert       return {};
92061da546Spatrick     }
93061da546Spatrick   }
94061da546Spatrick 
95061da546Spatrick   if (reg_kind == eRegisterKindLLDB)
96*f6aab3d8Srobert     return LLDBTableGetRegisterInfo(reg_num);
97*f6aab3d8Srobert   return {};
98061da546Spatrick }
99061da546Spatrick 
ReadInstruction()100061da546Spatrick bool EmulateInstructionPPC64::ReadInstruction() {
101061da546Spatrick   bool success = false;
102061da546Spatrick   m_addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
103061da546Spatrick                                 LLDB_INVALID_ADDRESS, &success);
104061da546Spatrick   if (success) {
105061da546Spatrick     Context ctx;
106061da546Spatrick     ctx.type = eContextReadOpcode;
107061da546Spatrick     ctx.SetNoArgs();
108061da546Spatrick     m_opcode.SetOpcode32(ReadMemoryUnsigned(ctx, m_addr, 4, 0, &success),
109061da546Spatrick                          GetByteOrder());
110061da546Spatrick   }
111061da546Spatrick   if (!success)
112061da546Spatrick     m_addr = LLDB_INVALID_ADDRESS;
113061da546Spatrick   return success;
114061da546Spatrick }
115061da546Spatrick 
CreateFunctionEntryUnwind(UnwindPlan & unwind_plan)116061da546Spatrick bool EmulateInstructionPPC64::CreateFunctionEntryUnwind(
117061da546Spatrick     UnwindPlan &unwind_plan) {
118061da546Spatrick   unwind_plan.Clear();
119061da546Spatrick   unwind_plan.SetRegisterKind(eRegisterKindLLDB);
120061da546Spatrick 
121061da546Spatrick   UnwindPlan::RowSP row(new UnwindPlan::Row);
122061da546Spatrick 
123061da546Spatrick   // Our previous Call Frame Address is the stack pointer
124061da546Spatrick   row->GetCFAValue().SetIsRegisterPlusOffset(gpr_r1_ppc64le, 0);
125061da546Spatrick 
126061da546Spatrick   unwind_plan.AppendRow(row);
127061da546Spatrick   unwind_plan.SetSourceName("EmulateInstructionPPC64");
128061da546Spatrick   unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
129061da546Spatrick   unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
130061da546Spatrick   unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
131061da546Spatrick   unwind_plan.SetReturnAddressRegister(gpr_lr_ppc64le);
132061da546Spatrick   return true;
133061da546Spatrick }
134061da546Spatrick 
135061da546Spatrick EmulateInstructionPPC64::Opcode *
GetOpcodeForInstruction(uint32_t opcode)136061da546Spatrick EmulateInstructionPPC64::GetOpcodeForInstruction(uint32_t opcode) {
137061da546Spatrick   static EmulateInstructionPPC64::Opcode g_opcodes[] = {
138061da546Spatrick       {0xfc0007ff, 0x7c0002a6, &EmulateInstructionPPC64::EmulateMFSPR,
139061da546Spatrick        "mfspr RT, SPR"},
140061da546Spatrick       {0xfc000003, 0xf8000000, &EmulateInstructionPPC64::EmulateSTD,
141061da546Spatrick        "std RS, DS(RA)"},
142061da546Spatrick       {0xfc000003, 0xf8000001, &EmulateInstructionPPC64::EmulateSTD,
143061da546Spatrick        "stdu RS, DS(RA)"},
144061da546Spatrick       {0xfc0007fe, 0x7c000378, &EmulateInstructionPPC64::EmulateOR,
145061da546Spatrick        "or RA, RS, RB"},
146061da546Spatrick       {0xfc000000, 0x38000000, &EmulateInstructionPPC64::EmulateADDI,
147061da546Spatrick        "addi RT, RA, SI"},
148061da546Spatrick       {0xfc000003, 0xe8000000, &EmulateInstructionPPC64::EmulateLD,
149061da546Spatrick        "ld RT, DS(RA)"}};
150*f6aab3d8Srobert   static const size_t k_num_ppc_opcodes = std::size(g_opcodes);
151061da546Spatrick 
152061da546Spatrick   for (size_t i = 0; i < k_num_ppc_opcodes; ++i) {
153061da546Spatrick     if ((g_opcodes[i].mask & opcode) == g_opcodes[i].value)
154061da546Spatrick       return &g_opcodes[i];
155061da546Spatrick   }
156061da546Spatrick   return nullptr;
157061da546Spatrick }
158061da546Spatrick 
EvaluateInstruction(uint32_t evaluate_options)159061da546Spatrick bool EmulateInstructionPPC64::EvaluateInstruction(uint32_t evaluate_options) {
160061da546Spatrick   const uint32_t opcode = m_opcode.GetOpcode32();
161061da546Spatrick   // LLDB_LOG(log, "PPC64::EvaluateInstruction: opcode={0:X+8}", opcode);
162061da546Spatrick   Opcode *opcode_data = GetOpcodeForInstruction(opcode);
163061da546Spatrick   if (!opcode_data)
164061da546Spatrick     return false;
165061da546Spatrick 
166061da546Spatrick   // LLDB_LOG(log, "PPC64::EvaluateInstruction: {0}", opcode_data->name);
167061da546Spatrick   const bool auto_advance_pc =
168061da546Spatrick       evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
169061da546Spatrick 
170061da546Spatrick   bool success = false;
171061da546Spatrick 
172061da546Spatrick   uint32_t orig_pc_value = 0;
173061da546Spatrick   if (auto_advance_pc) {
174061da546Spatrick     orig_pc_value =
175061da546Spatrick         ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_ppc64le, 0, &success);
176061da546Spatrick     if (!success)
177061da546Spatrick       return false;
178061da546Spatrick   }
179061da546Spatrick 
180061da546Spatrick   // Call the Emulate... function.
181061da546Spatrick   success = (this->*opcode_data->callback)(opcode);
182061da546Spatrick   if (!success)
183061da546Spatrick     return false;
184061da546Spatrick 
185061da546Spatrick   if (auto_advance_pc) {
186061da546Spatrick     uint32_t new_pc_value =
187061da546Spatrick         ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_ppc64le, 0, &success);
188061da546Spatrick     if (!success)
189061da546Spatrick       return false;
190061da546Spatrick 
191dda28197Spatrick     if (new_pc_value == orig_pc_value) {
192061da546Spatrick       EmulateInstruction::Context context;
193061da546Spatrick       context.type = eContextAdvancePC;
194061da546Spatrick       context.SetNoArgs();
195061da546Spatrick       if (!WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_pc_ppc64le,
196061da546Spatrick                                  orig_pc_value + 4))
197061da546Spatrick         return false;
198061da546Spatrick     }
199061da546Spatrick   }
200061da546Spatrick   return true;
201061da546Spatrick }
202061da546Spatrick 
EmulateMFSPR(uint32_t opcode)203061da546Spatrick bool EmulateInstructionPPC64::EmulateMFSPR(uint32_t opcode) {
204061da546Spatrick   uint32_t rt = Bits32(opcode, 25, 21);
205061da546Spatrick   uint32_t spr = Bits32(opcode, 20, 11);
206061da546Spatrick 
207061da546Spatrick   enum { SPR_LR = 0x100 };
208061da546Spatrick 
209061da546Spatrick   // For now, we're only insterested in 'mfspr r0, lr'
210061da546Spatrick   if (rt != gpr_r0_ppc64le || spr != SPR_LR)
211061da546Spatrick     return false;
212061da546Spatrick 
213*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Unwind);
214061da546Spatrick   LLDB_LOG(log, "EmulateMFSPR: {0:X+8}: mfspr r0, lr", m_addr);
215061da546Spatrick 
216061da546Spatrick   bool success;
217061da546Spatrick   uint64_t lr =
218061da546Spatrick       ReadRegisterUnsigned(eRegisterKindLLDB, gpr_lr_ppc64le, 0, &success);
219061da546Spatrick   if (!success)
220061da546Spatrick     return false;
221061da546Spatrick   Context context;
222061da546Spatrick   context.type = eContextWriteRegisterRandomBits;
223061da546Spatrick   WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_r0_ppc64le, lr);
224061da546Spatrick   LLDB_LOG(log, "EmulateMFSPR: success!");
225061da546Spatrick   return true;
226061da546Spatrick }
227061da546Spatrick 
EmulateLD(uint32_t opcode)228061da546Spatrick bool EmulateInstructionPPC64::EmulateLD(uint32_t opcode) {
229061da546Spatrick   uint32_t rt = Bits32(opcode, 25, 21);
230061da546Spatrick   uint32_t ra = Bits32(opcode, 20, 16);
231061da546Spatrick   uint32_t ds = Bits32(opcode, 15, 2);
232061da546Spatrick 
233061da546Spatrick   int32_t ids = llvm::SignExtend32<16>(ds << 2);
234061da546Spatrick 
235061da546Spatrick   // For now, tracking only loads from 0(r1) to r1 (0(r1) is the ABI defined
236061da546Spatrick   // location to save previous SP)
237061da546Spatrick   if (ra != gpr_r1_ppc64le || rt != gpr_r1_ppc64le || ids != 0)
238061da546Spatrick     return false;
239061da546Spatrick 
240*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Unwind);
241061da546Spatrick   LLDB_LOG(log, "EmulateLD: {0:X+8}: ld r{1}, {2}(r{3})", m_addr, rt, ids, ra);
242061da546Spatrick 
243*f6aab3d8Srobert   std::optional<RegisterInfo> r1_info =
244*f6aab3d8Srobert       GetRegisterInfo(eRegisterKindLLDB, gpr_r1_ppc64le);
245*f6aab3d8Srobert   if (!r1_info)
246061da546Spatrick     return false;
247061da546Spatrick 
248061da546Spatrick   // restore SP
249061da546Spatrick   Context ctx;
250061da546Spatrick   ctx.type = eContextRestoreStackPointer;
251*f6aab3d8Srobert   ctx.SetRegisterToRegisterPlusOffset(*r1_info, *r1_info, 0);
252061da546Spatrick 
253061da546Spatrick   WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_r1_ppc64le, 0);
254061da546Spatrick   LLDB_LOG(log, "EmulateLD: success!");
255061da546Spatrick   return true;
256061da546Spatrick }
257061da546Spatrick 
EmulateSTD(uint32_t opcode)258061da546Spatrick bool EmulateInstructionPPC64::EmulateSTD(uint32_t opcode) {
259061da546Spatrick   uint32_t rs = Bits32(opcode, 25, 21);
260061da546Spatrick   uint32_t ra = Bits32(opcode, 20, 16);
261061da546Spatrick   uint32_t ds = Bits32(opcode, 15, 2);
262061da546Spatrick   uint32_t u = Bits32(opcode, 1, 0);
263061da546Spatrick 
264061da546Spatrick   // For now, tracking only stores to r1
265061da546Spatrick   if (ra != gpr_r1_ppc64le)
266061da546Spatrick     return false;
267061da546Spatrick   // ... and only stores of SP, FP and LR (moved into r0 by a previous mfspr)
268061da546Spatrick   if (rs != gpr_r1_ppc64le && rs != gpr_r31_ppc64le && rs != gpr_r30_ppc64le &&
269061da546Spatrick       rs != gpr_r0_ppc64le)
270061da546Spatrick     return false;
271061da546Spatrick 
272061da546Spatrick   bool success;
273061da546Spatrick   uint64_t rs_val = ReadRegisterUnsigned(eRegisterKindLLDB, rs, 0, &success);
274061da546Spatrick   if (!success)
275061da546Spatrick     return false;
276061da546Spatrick 
277061da546Spatrick   int32_t ids = llvm::SignExtend32<16>(ds << 2);
278*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Unwind);
279061da546Spatrick   LLDB_LOG(log, "EmulateSTD: {0:X+8}: std{1} r{2}, {3}(r{4})", m_addr,
280061da546Spatrick            u ? "u" : "", rs, ids, ra);
281061da546Spatrick 
282061da546Spatrick   // Make sure that r0 is really holding LR value (this won't catch unlikely
283061da546Spatrick   // cases, such as r0 being overwritten after mfspr)
284061da546Spatrick   uint32_t rs_num = rs;
285061da546Spatrick   if (rs == gpr_r0_ppc64le) {
286061da546Spatrick     uint64_t lr =
287061da546Spatrick         ReadRegisterUnsigned(eRegisterKindLLDB, gpr_lr_ppc64le, 0, &success);
288061da546Spatrick     if (!success || lr != rs_val)
289061da546Spatrick       return false;
290061da546Spatrick     rs_num = gpr_lr_ppc64le;
291061da546Spatrick   }
292061da546Spatrick 
293061da546Spatrick   // set context
294*f6aab3d8Srobert   std::optional<RegisterInfo> rs_info =
295*f6aab3d8Srobert       GetRegisterInfo(eRegisterKindLLDB, rs_num);
296*f6aab3d8Srobert   if (!rs_info)
297061da546Spatrick     return false;
298*f6aab3d8Srobert   std::optional<RegisterInfo> ra_info = GetRegisterInfo(eRegisterKindLLDB, ra);
299*f6aab3d8Srobert   if (!ra_info)
300061da546Spatrick     return false;
301061da546Spatrick 
302061da546Spatrick   Context ctx;
303061da546Spatrick   ctx.type = eContextPushRegisterOnStack;
304*f6aab3d8Srobert   ctx.SetRegisterToRegisterPlusOffset(*rs_info, *ra_info, ids);
305061da546Spatrick 
306061da546Spatrick   // store
307061da546Spatrick   uint64_t ra_val = ReadRegisterUnsigned(eRegisterKindLLDB, ra, 0, &success);
308061da546Spatrick   if (!success)
309061da546Spatrick     return false;
310061da546Spatrick 
311061da546Spatrick   lldb::addr_t addr = ra_val + ids;
312061da546Spatrick   WriteMemory(ctx, addr, &rs_val, sizeof(rs_val));
313061da546Spatrick 
314061da546Spatrick   // update RA?
315061da546Spatrick   if (u) {
316061da546Spatrick     Context ctx;
317061da546Spatrick     // NOTE Currently, RA will always be equal to SP(r1)
318061da546Spatrick     ctx.type = eContextAdjustStackPointer;
319061da546Spatrick     WriteRegisterUnsigned(ctx, eRegisterKindLLDB, ra, addr);
320061da546Spatrick   }
321061da546Spatrick 
322061da546Spatrick   LLDB_LOG(log, "EmulateSTD: success!");
323061da546Spatrick   return true;
324061da546Spatrick }
325061da546Spatrick 
EmulateOR(uint32_t opcode)326061da546Spatrick bool EmulateInstructionPPC64::EmulateOR(uint32_t opcode) {
327061da546Spatrick   uint32_t rs = Bits32(opcode, 25, 21);
328061da546Spatrick   uint32_t ra = Bits32(opcode, 20, 16);
329061da546Spatrick   uint32_t rb = Bits32(opcode, 15, 11);
330061da546Spatrick 
331061da546Spatrick   // to be safe, process only the known 'mr r31/r30, r1' prologue instructions
332061da546Spatrick   if (m_fp != LLDB_INVALID_REGNUM || rs != rb ||
333061da546Spatrick       (ra != gpr_r30_ppc64le && ra != gpr_r31_ppc64le) || rb != gpr_r1_ppc64le)
334061da546Spatrick     return false;
335061da546Spatrick 
336*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Unwind);
337061da546Spatrick   LLDB_LOG(log, "EmulateOR: {0:X+8}: mr r{1}, r{2}", m_addr, ra, rb);
338061da546Spatrick 
339061da546Spatrick   // set context
340*f6aab3d8Srobert   std::optional<RegisterInfo> ra_info = GetRegisterInfo(eRegisterKindLLDB, ra);
341*f6aab3d8Srobert   if (!ra_info)
342061da546Spatrick     return false;
343061da546Spatrick 
344061da546Spatrick   Context ctx;
345061da546Spatrick   ctx.type = eContextSetFramePointer;
346*f6aab3d8Srobert   ctx.SetRegister(*ra_info);
347061da546Spatrick 
348061da546Spatrick   // move
349061da546Spatrick   bool success;
350061da546Spatrick   uint64_t rb_val = ReadRegisterUnsigned(eRegisterKindLLDB, rb, 0, &success);
351061da546Spatrick   if (!success)
352061da546Spatrick     return false;
353061da546Spatrick   WriteRegisterUnsigned(ctx, eRegisterKindLLDB, ra, rb_val);
354061da546Spatrick   m_fp = ra;
355061da546Spatrick   LLDB_LOG(log, "EmulateOR: success!");
356061da546Spatrick   return true;
357061da546Spatrick }
358061da546Spatrick 
EmulateADDI(uint32_t opcode)359061da546Spatrick bool EmulateInstructionPPC64::EmulateADDI(uint32_t opcode) {
360061da546Spatrick   uint32_t rt = Bits32(opcode, 25, 21);
361061da546Spatrick   uint32_t ra = Bits32(opcode, 20, 16);
362061da546Spatrick   uint32_t si = Bits32(opcode, 15, 0);
363061da546Spatrick 
364061da546Spatrick   // handle stack adjustments only
365061da546Spatrick   // (this is a typical epilogue operation, with ra == r1. If it's
366061da546Spatrick   //  something else, then we won't know the correct value of ra)
367061da546Spatrick   if (rt != gpr_r1_ppc64le || ra != gpr_r1_ppc64le)
368061da546Spatrick     return false;
369061da546Spatrick 
370061da546Spatrick   int32_t si_val = llvm::SignExtend32<16>(si);
371*f6aab3d8Srobert   Log *log = GetLog(LLDBLog::Unwind);
372061da546Spatrick   LLDB_LOG(log, "EmulateADDI: {0:X+8}: addi r1, r1, {1}", m_addr, si_val);
373061da546Spatrick 
374061da546Spatrick   // set context
375*f6aab3d8Srobert   std::optional<RegisterInfo> r1_info =
376*f6aab3d8Srobert       GetRegisterInfo(eRegisterKindLLDB, gpr_r1_ppc64le);
377*f6aab3d8Srobert   if (!r1_info)
378061da546Spatrick     return false;
379061da546Spatrick 
380061da546Spatrick   Context ctx;
381061da546Spatrick   ctx.type = eContextRestoreStackPointer;
382*f6aab3d8Srobert   ctx.SetRegisterToRegisterPlusOffset(*r1_info, *r1_info, 0);
383061da546Spatrick 
384061da546Spatrick   // adjust SP
385061da546Spatrick   bool success;
386061da546Spatrick   uint64_t r1 =
387061da546Spatrick       ReadRegisterUnsigned(eRegisterKindLLDB, gpr_r1_ppc64le, 0, &success);
388061da546Spatrick   if (!success)
389061da546Spatrick     return false;
390061da546Spatrick   WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_r1_ppc64le, r1 + si_val);
391061da546Spatrick   LLDB_LOG(log, "EmulateADDI: success!");
392061da546Spatrick   return true;
393061da546Spatrick }
394