1 //===-- EmulateInstructionPPC64.cpp ------------------------------*- C++-*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "EmulateInstructionPPC64.h"
13 #include "lldb/Core/PluginManager.h"
14 #include "lldb/Symbol/UnwindPlan.h"
15 #include "lldb/Utility/ArchSpec.h"
16 #include "lldb/Utility/ConstString.h"
18 #include "Plugins/Process/Utility/lldb-ppc64le-register-enums.h"
20 #define DECLARE_REGISTER_INFOS_PPC64LE_STRUCT
21 #include "Plugins/Process/Utility/RegisterInfos_ppc64le.h"
23 #include "Plugins/Process/Utility/InstructionUtils.h"
26 using namespace lldb_private;
28 EmulateInstructionPPC64::EmulateInstructionPPC64(const ArchSpec &arch)
29 : EmulateInstruction(arch) {}
31 void EmulateInstructionPPC64::Initialize() {
32 PluginManager::RegisterPlugin(GetPluginNameStatic(),
33 GetPluginDescriptionStatic(), CreateInstance);
36 void EmulateInstructionPPC64::Terminate() {
37 PluginManager::UnregisterPlugin(CreateInstance);
40 ConstString EmulateInstructionPPC64::GetPluginNameStatic() {
41 ConstString g_plugin_name("lldb.emulate-instruction.ppc64");
45 ConstString EmulateInstructionPPC64::GetPluginName() {
46 static ConstString g_plugin_name("EmulateInstructionPPC64");
50 const char *EmulateInstructionPPC64::GetPluginDescriptionStatic() {
51 return "Emulate instructions for the PPC64 architecture.";
55 EmulateInstructionPPC64::CreateInstance(const ArchSpec &arch,
56 InstructionType inst_type) {
57 if (EmulateInstructionPPC64::SupportsEmulatingInstructionsOfTypeStatic(
59 if (arch.GetTriple().isPPC64())
60 return new EmulateInstructionPPC64(arch);
65 bool EmulateInstructionPPC64::SetTargetTriple(const ArchSpec &arch) {
66 return arch.GetTriple().isPPC64();
69 static bool LLDBTableGetRegisterInfo(uint32_t reg_num, RegisterInfo ®_info) {
70 if (reg_num >= llvm::array_lengthof(g_register_infos_ppc64le))
72 reg_info = g_register_infos_ppc64le[reg_num];
76 bool EmulateInstructionPPC64::GetRegisterInfo(RegisterKind reg_kind,
78 RegisterInfo ®_info) {
79 if (reg_kind == eRegisterKindGeneric) {
81 case LLDB_REGNUM_GENERIC_PC:
82 reg_kind = eRegisterKindLLDB;
83 reg_num = gpr_pc_ppc64le;
85 case LLDB_REGNUM_GENERIC_SP:
86 reg_kind = eRegisterKindLLDB;
87 reg_num = gpr_r1_ppc64le;
89 case LLDB_REGNUM_GENERIC_RA:
90 reg_kind = eRegisterKindLLDB;
91 reg_num = gpr_lr_ppc64le;
93 case LLDB_REGNUM_GENERIC_FLAGS:
94 reg_kind = eRegisterKindLLDB;
95 reg_num = gpr_cr_ppc64le;
103 if (reg_kind == eRegisterKindLLDB)
104 return LLDBTableGetRegisterInfo(reg_num, reg_info);
108 bool EmulateInstructionPPC64::ReadInstruction() {
109 bool success = false;
110 m_addr = ReadRegisterUnsigned(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
111 LLDB_INVALID_ADDRESS, &success);
114 ctx.type = eContextReadOpcode;
116 m_opcode.SetOpcode32(ReadMemoryUnsigned(ctx, m_addr, 4, 0, &success),
120 m_addr = LLDB_INVALID_ADDRESS;
124 bool EmulateInstructionPPC64::CreateFunctionEntryUnwind(
125 UnwindPlan &unwind_plan) {
127 unwind_plan.SetRegisterKind(eRegisterKindLLDB);
129 UnwindPlan::RowSP row(new UnwindPlan::Row);
131 // Our previous Call Frame Address is the stack pointer
132 row->GetCFAValue().SetIsRegisterPlusOffset(gpr_r1_ppc64le, 0);
134 unwind_plan.AppendRow(row);
135 unwind_plan.SetSourceName("EmulateInstructionPPC64");
136 unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
137 unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolYes);
138 unwind_plan.SetReturnAddressRegister(gpr_lr_ppc64le);
142 EmulateInstructionPPC64::Opcode *
143 EmulateInstructionPPC64::GetOpcodeForInstruction(uint32_t opcode) {
144 static EmulateInstructionPPC64::Opcode g_opcodes[] = {
145 {0xfc0007ff, 0x7c0002a6, &EmulateInstructionPPC64::EmulateMFSPR,
147 {0xfc000003, 0xf8000000, &EmulateInstructionPPC64::EmulateSTD,
149 {0xfc000003, 0xf8000001, &EmulateInstructionPPC64::EmulateSTD,
151 {0xfc0007fe, 0x7c000378, &EmulateInstructionPPC64::EmulateOR,
153 {0xfc000000, 0x38000000, &EmulateInstructionPPC64::EmulateADDI,
155 {0xfc000003, 0xe8000000, &EmulateInstructionPPC64::EmulateLD,
157 static const size_t k_num_ppc_opcodes = llvm::array_lengthof(g_opcodes);
159 for (size_t i = 0; i < k_num_ppc_opcodes; ++i) {
160 if ((g_opcodes[i].mask & opcode) == g_opcodes[i].value)
161 return &g_opcodes[i];
166 bool EmulateInstructionPPC64::EvaluateInstruction(uint32_t evaluate_options) {
167 const uint32_t opcode = m_opcode.GetOpcode32();
168 // LLDB_LOG(log, "PPC64::EvaluateInstruction: opcode={0:X+8}", opcode);
169 Opcode *opcode_data = GetOpcodeForInstruction(opcode);
173 // LLDB_LOG(log, "PPC64::EvaluateInstruction: {0}", opcode_data->name);
174 const bool auto_advance_pc =
175 evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
177 bool success = false;
179 uint32_t orig_pc_value = 0;
180 if (auto_advance_pc) {
182 ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_ppc64le, 0, &success);
187 // Call the Emulate... function.
188 success = (this->*opcode_data->callback)(opcode);
192 if (auto_advance_pc) {
193 uint32_t new_pc_value =
194 ReadRegisterUnsigned(eRegisterKindLLDB, gpr_pc_ppc64le, 0, &success);
198 if (auto_advance_pc && (new_pc_value == orig_pc_value)) {
199 EmulateInstruction::Context context;
200 context.type = eContextAdvancePC;
202 if (!WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_pc_ppc64le,
210 bool EmulateInstructionPPC64::EmulateMFSPR(uint32_t opcode) {
211 uint32_t rt = Bits32(opcode, 25, 21);
212 uint32_t spr = Bits32(opcode, 20, 11);
214 enum { SPR_LR = 0x100 };
216 // For now, we're only insterested in 'mfspr r0, lr'
217 if (rt != gpr_r0_ppc64le || spr != SPR_LR)
220 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
221 LLDB_LOG(log, "EmulateMFSPR: {0:X+8}: mfspr r0, lr", m_addr);
225 ReadRegisterUnsigned(eRegisterKindLLDB, gpr_lr_ppc64le, 0, &success);
229 context.type = eContextWriteRegisterRandomBits;
230 WriteRegisterUnsigned(context, eRegisterKindLLDB, gpr_r0_ppc64le, lr);
231 LLDB_LOG(log, "EmulateMFSPR: success!");
235 bool EmulateInstructionPPC64::EmulateLD(uint32_t opcode) {
236 uint32_t rt = Bits32(opcode, 25, 21);
237 uint32_t ra = Bits32(opcode, 20, 16);
238 uint32_t ds = Bits32(opcode, 15, 2);
240 int32_t ids = llvm::SignExtend32<16>(ds << 2);
242 // For now, tracking only loads from 0(r1) to r1 (0(r1) is the ABI defined
243 // location to save previous SP)
244 if (ra != gpr_r1_ppc64le || rt != gpr_r1_ppc64le || ids != 0)
247 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
248 LLDB_LOG(log, "EmulateLD: {0:X+8}: ld r{1}, {2}(r{3})", m_addr, rt, ids, ra);
250 RegisterInfo r1_info;
251 if (!GetRegisterInfo(eRegisterKindLLDB, gpr_r1_ppc64le, r1_info))
256 ctx.type = eContextRestoreStackPointer;
257 ctx.SetRegisterToRegisterPlusOffset(r1_info, r1_info, 0);
259 WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_r1_ppc64le, 0);
260 LLDB_LOG(log, "EmulateLD: success!");
264 bool EmulateInstructionPPC64::EmulateSTD(uint32_t opcode) {
265 uint32_t rs = Bits32(opcode, 25, 21);
266 uint32_t ra = Bits32(opcode, 20, 16);
267 uint32_t ds = Bits32(opcode, 15, 2);
268 uint32_t u = Bits32(opcode, 1, 0);
270 // For now, tracking only stores to r1
271 if (ra != gpr_r1_ppc64le)
273 // ... and only stores of SP, FP and LR (moved into r0 by a previous mfspr)
274 if (rs != gpr_r1_ppc64le && rs != gpr_r31_ppc64le && rs != gpr_r30_ppc64le &&
275 rs != gpr_r0_ppc64le)
279 uint64_t rs_val = ReadRegisterUnsigned(eRegisterKindLLDB, rs, 0, &success);
283 int32_t ids = llvm::SignExtend32<16>(ds << 2);
284 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
285 LLDB_LOG(log, "EmulateSTD: {0:X+8}: std{1} r{2}, {3}(r{4})", m_addr,
286 u ? "u" : "", rs, ids, ra);
288 // Make sure that r0 is really holding LR value (this won't catch unlikely
289 // cases, such as r0 being overwritten after mfspr)
290 uint32_t rs_num = rs;
291 if (rs == gpr_r0_ppc64le) {
293 ReadRegisterUnsigned(eRegisterKindLLDB, gpr_lr_ppc64le, 0, &success);
294 if (!success || lr != rs_val)
296 rs_num = gpr_lr_ppc64le;
300 RegisterInfo rs_info;
301 if (!GetRegisterInfo(eRegisterKindLLDB, rs_num, rs_info))
303 RegisterInfo ra_info;
304 if (!GetRegisterInfo(eRegisterKindLLDB, ra, ra_info))
308 ctx.type = eContextPushRegisterOnStack;
309 ctx.SetRegisterToRegisterPlusOffset(rs_info, ra_info, ids);
312 uint64_t ra_val = ReadRegisterUnsigned(eRegisterKindLLDB, ra, 0, &success);
316 lldb::addr_t addr = ra_val + ids;
317 WriteMemory(ctx, addr, &rs_val, sizeof(rs_val));
322 // NOTE Currently, RA will always be equal to SP(r1)
323 ctx.type = eContextAdjustStackPointer;
324 WriteRegisterUnsigned(ctx, eRegisterKindLLDB, ra, addr);
327 LLDB_LOG(log, "EmulateSTD: success!");
331 bool EmulateInstructionPPC64::EmulateOR(uint32_t opcode) {
332 uint32_t rs = Bits32(opcode, 25, 21);
333 uint32_t ra = Bits32(opcode, 20, 16);
334 uint32_t rb = Bits32(opcode, 15, 11);
336 // to be safe, process only the known 'mr r31/r30, r1' prologue instructions
337 if (m_fp != LLDB_INVALID_REGNUM || rs != rb ||
338 (ra != gpr_r30_ppc64le && ra != gpr_r31_ppc64le) || rb != gpr_r1_ppc64le)
341 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
342 LLDB_LOG(log, "EmulateOR: {0:X+8}: mr r{1}, r{2}", m_addr, ra, rb);
345 RegisterInfo ra_info;
346 if (!GetRegisterInfo(eRegisterKindLLDB, ra, ra_info))
350 ctx.type = eContextSetFramePointer;
351 ctx.SetRegister(ra_info);
355 uint64_t rb_val = ReadRegisterUnsigned(eRegisterKindLLDB, rb, 0, &success);
358 WriteRegisterUnsigned(ctx, eRegisterKindLLDB, ra, rb_val);
360 LLDB_LOG(log, "EmulateOR: success!");
364 bool EmulateInstructionPPC64::EmulateADDI(uint32_t opcode) {
365 uint32_t rt = Bits32(opcode, 25, 21);
366 uint32_t ra = Bits32(opcode, 20, 16);
367 uint32_t si = Bits32(opcode, 15, 0);
369 // handle stack adjustments only
370 // (this is a typical epilogue operation, with ra == r1. If it's
371 // something else, then we won't know the correct value of ra)
372 if (rt != gpr_r1_ppc64le || ra != gpr_r1_ppc64le)
375 int32_t si_val = llvm::SignExtend32<16>(si);
376 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
377 LLDB_LOG(log, "EmulateADDI: {0:X+8}: addi r1, r1, {1}", m_addr, si_val);
380 RegisterInfo r1_info;
381 if (!GetRegisterInfo(eRegisterKindLLDB, gpr_r1_ppc64le, r1_info))
385 ctx.type = eContextRestoreStackPointer;
386 ctx.SetRegisterToRegisterPlusOffset(r1_info, r1_info, 0);
391 ReadRegisterUnsigned(eRegisterKindLLDB, gpr_r1_ppc64le, 0, &success);
394 WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_r1_ppc64le, r1 + si_val);
395 LLDB_LOG(log, "EmulateADDI: success!");