1dda28197Spatrick //===-- EmulationStateARM.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 "EmulationStateARM.h"
10061da546Spatrick
11061da546Spatrick #include "lldb/Interpreter/OptionValueArray.h"
12061da546Spatrick #include "lldb/Interpreter/OptionValueDictionary.h"
13061da546Spatrick #include "lldb/Target/RegisterContext.h"
14061da546Spatrick #include "lldb/Target/StackFrame.h"
15061da546Spatrick #include "lldb/Utility/RegisterValue.h"
16061da546Spatrick #include "lldb/Utility/Scalar.h"
17061da546Spatrick
18061da546Spatrick #include "Utility/ARM_DWARF_Registers.h"
19061da546Spatrick
20061da546Spatrick using namespace lldb;
21061da546Spatrick using namespace lldb_private;
22061da546Spatrick
EmulationStateARM()23be691f3bSpatrick EmulationStateARM::EmulationStateARM() : m_vfp_regs(), m_memory() {
24061da546Spatrick ClearPseudoRegisters();
25061da546Spatrick }
26061da546Spatrick
27be691f3bSpatrick EmulationStateARM::~EmulationStateARM() = default;
28061da546Spatrick
StorePseudoRegisterValue(uint32_t reg_num,uint64_t value)29061da546Spatrick bool EmulationStateARM::StorePseudoRegisterValue(uint32_t reg_num,
30061da546Spatrick uint64_t value) {
31061da546Spatrick if (reg_num <= dwarf_cpsr)
32061da546Spatrick m_gpr[reg_num - dwarf_r0] = (uint32_t)value;
33061da546Spatrick else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) {
34061da546Spatrick uint32_t idx = reg_num - dwarf_s0;
35061da546Spatrick m_vfp_regs.s_regs[idx] = (uint32_t)value;
36061da546Spatrick } else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31)) {
37061da546Spatrick uint32_t idx = reg_num - dwarf_d0;
38061da546Spatrick if (idx < 16) {
39061da546Spatrick m_vfp_regs.s_regs[idx * 2] = (uint32_t)value;
40061da546Spatrick m_vfp_regs.s_regs[idx * 2 + 1] = (uint32_t)(value >> 32);
41061da546Spatrick } else
42061da546Spatrick m_vfp_regs.d_regs[idx - 16] = value;
43061da546Spatrick } else
44061da546Spatrick return false;
45061da546Spatrick
46061da546Spatrick return true;
47061da546Spatrick }
48061da546Spatrick
ReadPseudoRegisterValue(uint32_t reg_num,bool & success)49061da546Spatrick uint64_t EmulationStateARM::ReadPseudoRegisterValue(uint32_t reg_num,
50061da546Spatrick bool &success) {
51061da546Spatrick uint64_t value = 0;
52061da546Spatrick success = true;
53061da546Spatrick
54061da546Spatrick if (reg_num <= dwarf_cpsr)
55061da546Spatrick value = m_gpr[reg_num - dwarf_r0];
56061da546Spatrick else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) {
57061da546Spatrick uint32_t idx = reg_num - dwarf_s0;
58*f6aab3d8Srobert value = m_vfp_regs.s_regs[idx];
59061da546Spatrick } else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31)) {
60061da546Spatrick uint32_t idx = reg_num - dwarf_d0;
61061da546Spatrick if (idx < 16)
62061da546Spatrick value = (uint64_t)m_vfp_regs.s_regs[idx * 2] |
63*f6aab3d8Srobert ((uint64_t)m_vfp_regs.s_regs[idx * 2 + 1] << 32);
64061da546Spatrick else
65061da546Spatrick value = m_vfp_regs.d_regs[idx - 16];
66061da546Spatrick } else
67061da546Spatrick success = false;
68061da546Spatrick
69061da546Spatrick return value;
70061da546Spatrick }
71061da546Spatrick
ClearPseudoRegisters()72061da546Spatrick void EmulationStateARM::ClearPseudoRegisters() {
73061da546Spatrick for (int i = 0; i < 17; ++i)
74061da546Spatrick m_gpr[i] = 0;
75061da546Spatrick
76061da546Spatrick for (int i = 0; i < 32; ++i)
77061da546Spatrick m_vfp_regs.s_regs[i] = 0;
78061da546Spatrick
79061da546Spatrick for (int i = 0; i < 16; ++i)
80061da546Spatrick m_vfp_regs.d_regs[i] = 0;
81061da546Spatrick }
82061da546Spatrick
ClearPseudoMemory()83061da546Spatrick void EmulationStateARM::ClearPseudoMemory() { m_memory.clear(); }
84061da546Spatrick
StoreToPseudoAddress(lldb::addr_t p_address,uint32_t value)85061da546Spatrick bool EmulationStateARM::StoreToPseudoAddress(lldb::addr_t p_address,
86061da546Spatrick uint32_t value) {
87061da546Spatrick m_memory[p_address] = value;
88061da546Spatrick return true;
89061da546Spatrick }
90061da546Spatrick
ReadFromPseudoAddress(lldb::addr_t p_address,bool & success)91061da546Spatrick uint32_t EmulationStateARM::ReadFromPseudoAddress(lldb::addr_t p_address,
92061da546Spatrick bool &success) {
93061da546Spatrick std::map<lldb::addr_t, uint32_t>::iterator pos;
94061da546Spatrick uint32_t ret_val = 0;
95061da546Spatrick
96061da546Spatrick success = true;
97061da546Spatrick pos = m_memory.find(p_address);
98061da546Spatrick if (pos != m_memory.end())
99061da546Spatrick ret_val = pos->second;
100061da546Spatrick else
101061da546Spatrick success = false;
102061da546Spatrick
103061da546Spatrick return ret_val;
104061da546Spatrick }
105061da546Spatrick
ReadPseudoMemory(EmulateInstruction * instruction,void * baton,const EmulateInstruction::Context & context,lldb::addr_t addr,void * dst,size_t length)106061da546Spatrick size_t EmulationStateARM::ReadPseudoMemory(
107061da546Spatrick EmulateInstruction *instruction, void *baton,
108061da546Spatrick const EmulateInstruction::Context &context, lldb::addr_t addr, void *dst,
109061da546Spatrick size_t length) {
110061da546Spatrick if (!baton)
111061da546Spatrick return 0;
112061da546Spatrick
113061da546Spatrick bool success = true;
114061da546Spatrick EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;
115061da546Spatrick if (length <= 4) {
116061da546Spatrick uint32_t value = pseudo_state->ReadFromPseudoAddress(addr, success);
117061da546Spatrick if (!success)
118061da546Spatrick return 0;
119061da546Spatrick
120061da546Spatrick if (endian::InlHostByteOrder() == lldb::eByteOrderBig)
121061da546Spatrick value = llvm::ByteSwap_32(value);
122061da546Spatrick *((uint32_t *)dst) = value;
123061da546Spatrick } else if (length == 8) {
124061da546Spatrick uint32_t value1 = pseudo_state->ReadFromPseudoAddress(addr, success);
125061da546Spatrick if (!success)
126061da546Spatrick return 0;
127061da546Spatrick
128061da546Spatrick uint32_t value2 = pseudo_state->ReadFromPseudoAddress(addr + 4, success);
129061da546Spatrick if (!success)
130061da546Spatrick return 0;
131061da546Spatrick
132061da546Spatrick if (endian::InlHostByteOrder() == lldb::eByteOrderBig) {
133061da546Spatrick value1 = llvm::ByteSwap_32(value1);
134061da546Spatrick value2 = llvm::ByteSwap_32(value2);
135061da546Spatrick }
136061da546Spatrick ((uint32_t *)dst)[0] = value1;
137061da546Spatrick ((uint32_t *)dst)[1] = value2;
138061da546Spatrick } else
139061da546Spatrick success = false;
140061da546Spatrick
141061da546Spatrick if (success)
142061da546Spatrick return length;
143061da546Spatrick
144061da546Spatrick return 0;
145061da546Spatrick }
146061da546Spatrick
WritePseudoMemory(EmulateInstruction * instruction,void * baton,const EmulateInstruction::Context & context,lldb::addr_t addr,const void * dst,size_t length)147061da546Spatrick size_t EmulationStateARM::WritePseudoMemory(
148061da546Spatrick EmulateInstruction *instruction, void *baton,
149061da546Spatrick const EmulateInstruction::Context &context, lldb::addr_t addr,
150061da546Spatrick const void *dst, size_t length) {
151061da546Spatrick if (!baton)
152061da546Spatrick return 0;
153061da546Spatrick
154061da546Spatrick EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;
155061da546Spatrick
156061da546Spatrick if (length <= 4) {
157061da546Spatrick uint32_t value;
158061da546Spatrick memcpy (&value, dst, sizeof (uint32_t));
159061da546Spatrick if (endian::InlHostByteOrder() == lldb::eByteOrderBig)
160061da546Spatrick value = llvm::ByteSwap_32(value);
161061da546Spatrick
162061da546Spatrick pseudo_state->StoreToPseudoAddress(addr, value);
163061da546Spatrick return length;
164061da546Spatrick } else if (length == 8) {
165061da546Spatrick uint32_t value1;
166061da546Spatrick uint32_t value2;
167061da546Spatrick memcpy (&value1, dst, sizeof (uint32_t));
168061da546Spatrick memcpy(&value2, static_cast<const uint8_t *>(dst) + sizeof(uint32_t),
169061da546Spatrick sizeof(uint32_t));
170061da546Spatrick if (endian::InlHostByteOrder() == lldb::eByteOrderBig) {
171061da546Spatrick value1 = llvm::ByteSwap_32(value1);
172061da546Spatrick value2 = llvm::ByteSwap_32(value2);
173061da546Spatrick }
174061da546Spatrick
175061da546Spatrick pseudo_state->StoreToPseudoAddress(addr, value1);
176061da546Spatrick pseudo_state->StoreToPseudoAddress(addr + 4, value2);
177061da546Spatrick return length;
178061da546Spatrick }
179061da546Spatrick
180061da546Spatrick return 0;
181061da546Spatrick }
182061da546Spatrick
ReadPseudoRegister(EmulateInstruction * instruction,void * baton,const lldb_private::RegisterInfo * reg_info,lldb_private::RegisterValue & reg_value)183061da546Spatrick bool EmulationStateARM::ReadPseudoRegister(
184061da546Spatrick EmulateInstruction *instruction, void *baton,
185061da546Spatrick const lldb_private::RegisterInfo *reg_info,
186061da546Spatrick lldb_private::RegisterValue ®_value) {
187061da546Spatrick if (!baton || !reg_info)
188061da546Spatrick return false;
189061da546Spatrick
190061da546Spatrick bool success = true;
191061da546Spatrick EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;
192061da546Spatrick const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF];
193061da546Spatrick assert(dwarf_reg_num != LLDB_INVALID_REGNUM);
194061da546Spatrick uint64_t reg_uval =
195061da546Spatrick pseudo_state->ReadPseudoRegisterValue(dwarf_reg_num, success);
196061da546Spatrick
197061da546Spatrick if (success)
198061da546Spatrick success = reg_value.SetUInt(reg_uval, reg_info->byte_size);
199061da546Spatrick return success;
200061da546Spatrick }
201061da546Spatrick
WritePseudoRegister(EmulateInstruction * instruction,void * baton,const EmulateInstruction::Context & context,const lldb_private::RegisterInfo * reg_info,const lldb_private::RegisterValue & reg_value)202061da546Spatrick bool EmulationStateARM::WritePseudoRegister(
203061da546Spatrick EmulateInstruction *instruction, void *baton,
204061da546Spatrick const EmulateInstruction::Context &context,
205061da546Spatrick const lldb_private::RegisterInfo *reg_info,
206061da546Spatrick const lldb_private::RegisterValue ®_value) {
207061da546Spatrick if (!baton || !reg_info)
208061da546Spatrick return false;
209061da546Spatrick
210061da546Spatrick EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;
211061da546Spatrick const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF];
212061da546Spatrick assert(dwarf_reg_num != LLDB_INVALID_REGNUM);
213061da546Spatrick return pseudo_state->StorePseudoRegisterValue(dwarf_reg_num,
214061da546Spatrick reg_value.GetAsUInt64());
215061da546Spatrick }
216061da546Spatrick
CompareState(EmulationStateARM & other_state,Stream * out_stream)217*f6aab3d8Srobert bool EmulationStateARM::CompareState(EmulationStateARM &other_state,
218*f6aab3d8Srobert Stream *out_stream) {
219061da546Spatrick bool match = true;
220061da546Spatrick
221061da546Spatrick for (int i = 0; match && i < 17; ++i) {
222*f6aab3d8Srobert if (m_gpr[i] != other_state.m_gpr[i]) {
223061da546Spatrick match = false;
224*f6aab3d8Srobert out_stream->Printf("r%d: 0x%x != 0x%x\n", i, m_gpr[i],
225*f6aab3d8Srobert other_state.m_gpr[i]);
226*f6aab3d8Srobert }
227061da546Spatrick }
228061da546Spatrick
229061da546Spatrick for (int i = 0; match && i < 32; ++i) {
230*f6aab3d8Srobert if (m_vfp_regs.s_regs[i] != other_state.m_vfp_regs.s_regs[i]) {
231061da546Spatrick match = false;
232*f6aab3d8Srobert out_stream->Printf("s%d: 0x%x != 0x%x\n", i, m_vfp_regs.s_regs[i],
233*f6aab3d8Srobert other_state.m_vfp_regs.s_regs[i]);
234*f6aab3d8Srobert }
235061da546Spatrick }
236061da546Spatrick
237061da546Spatrick for (int i = 0; match && i < 16; ++i) {
238*f6aab3d8Srobert if (m_vfp_regs.d_regs[i] != other_state.m_vfp_regs.d_regs[i]) {
239061da546Spatrick match = false;
240*f6aab3d8Srobert out_stream->Printf("d%d: 0x%" PRIx64 " != 0x%" PRIx64 "\n", i + 16,
241*f6aab3d8Srobert m_vfp_regs.d_regs[i],
242*f6aab3d8Srobert other_state.m_vfp_regs.d_regs[i]);
243*f6aab3d8Srobert }
244*f6aab3d8Srobert }
245*f6aab3d8Srobert
246*f6aab3d8Srobert // other_state is the expected state. If it has memory, check it.
247*f6aab3d8Srobert if (!other_state.m_memory.empty() && m_memory != other_state.m_memory) {
248*f6aab3d8Srobert match = false;
249*f6aab3d8Srobert out_stream->Printf("memory does not match\n");
250*f6aab3d8Srobert out_stream->Printf("got memory:\n");
251*f6aab3d8Srobert for (auto p : m_memory)
252*f6aab3d8Srobert out_stream->Printf("0x%08" PRIx64 ": 0x%08x\n", p.first, p.second);
253*f6aab3d8Srobert out_stream->Printf("expected memory:\n");
254*f6aab3d8Srobert for (auto p : other_state.m_memory)
255*f6aab3d8Srobert out_stream->Printf("0x%08" PRIx64 ": 0x%08x\n", p.first, p.second);
256061da546Spatrick }
257061da546Spatrick
258061da546Spatrick return match;
259061da546Spatrick }
260061da546Spatrick
LoadRegistersStateFromDictionary(OptionValueDictionary * reg_dict,char kind,int first_reg,int num)261*f6aab3d8Srobert bool EmulationStateARM::LoadRegistersStateFromDictionary(
262*f6aab3d8Srobert OptionValueDictionary *reg_dict, char kind, int first_reg, int num) {
263*f6aab3d8Srobert StreamString sstr;
264*f6aab3d8Srobert for (int i = 0; i < num; ++i) {
265*f6aab3d8Srobert sstr.Clear();
266*f6aab3d8Srobert sstr.Printf("%c%d", kind, i);
267*f6aab3d8Srobert OptionValueSP value_sp =
268*f6aab3d8Srobert reg_dict->GetValueForKey(ConstString(sstr.GetString()));
269*f6aab3d8Srobert if (value_sp.get() == nullptr)
270*f6aab3d8Srobert return false;
271*f6aab3d8Srobert uint64_t reg_value = value_sp->GetUInt64Value();
272*f6aab3d8Srobert StorePseudoRegisterValue(first_reg + i, reg_value);
273*f6aab3d8Srobert }
274*f6aab3d8Srobert
275*f6aab3d8Srobert return true;
276*f6aab3d8Srobert }
277*f6aab3d8Srobert
LoadStateFromDictionary(OptionValueDictionary * test_data)278061da546Spatrick bool EmulationStateARM::LoadStateFromDictionary(
279061da546Spatrick OptionValueDictionary *test_data) {
280061da546Spatrick static ConstString memory_key("memory");
281061da546Spatrick static ConstString registers_key("registers");
282061da546Spatrick
283061da546Spatrick if (!test_data)
284061da546Spatrick return false;
285061da546Spatrick
286061da546Spatrick OptionValueSP value_sp = test_data->GetValueForKey(memory_key);
287061da546Spatrick
288061da546Spatrick // Load memory, if present.
289061da546Spatrick
290061da546Spatrick if (value_sp.get() != nullptr) {
291061da546Spatrick static ConstString address_key("address");
292061da546Spatrick static ConstString data_key("data");
293061da546Spatrick uint64_t start_address = 0;
294061da546Spatrick
295061da546Spatrick OptionValueDictionary *mem_dict = value_sp->GetAsDictionary();
296061da546Spatrick value_sp = mem_dict->GetValueForKey(address_key);
297061da546Spatrick if (value_sp.get() == nullptr)
298061da546Spatrick return false;
299061da546Spatrick else
300061da546Spatrick start_address = value_sp->GetUInt64Value();
301061da546Spatrick
302061da546Spatrick value_sp = mem_dict->GetValueForKey(data_key);
303061da546Spatrick OptionValueArray *mem_array = value_sp->GetAsArray();
304061da546Spatrick if (!mem_array)
305061da546Spatrick return false;
306061da546Spatrick
307061da546Spatrick uint32_t num_elts = mem_array->GetSize();
308061da546Spatrick uint32_t address = (uint32_t)start_address;
309061da546Spatrick
310061da546Spatrick for (uint32_t i = 0; i < num_elts; ++i) {
311061da546Spatrick value_sp = mem_array->GetValueAtIndex(i);
312061da546Spatrick if (value_sp.get() == nullptr)
313061da546Spatrick return false;
314061da546Spatrick uint64_t value = value_sp->GetUInt64Value();
315061da546Spatrick StoreToPseudoAddress(address, value);
316061da546Spatrick address = address + 4;
317061da546Spatrick }
318061da546Spatrick }
319061da546Spatrick
320061da546Spatrick value_sp = test_data->GetValueForKey(registers_key);
321061da546Spatrick if (value_sp.get() == nullptr)
322061da546Spatrick return false;
323061da546Spatrick
324061da546Spatrick // Load General Registers
325061da546Spatrick
326061da546Spatrick OptionValueDictionary *reg_dict = value_sp->GetAsDictionary();
327*f6aab3d8Srobert if (!LoadRegistersStateFromDictionary(reg_dict, 'r', dwarf_r0, 16))
328061da546Spatrick return false;
329061da546Spatrick
330061da546Spatrick static ConstString cpsr_name("cpsr");
331061da546Spatrick value_sp = reg_dict->GetValueForKey(cpsr_name);
332061da546Spatrick if (value_sp.get() == nullptr)
333061da546Spatrick return false;
334061da546Spatrick StorePseudoRegisterValue(dwarf_cpsr, value_sp->GetUInt64Value());
335061da546Spatrick
336061da546Spatrick // Load s/d Registers
337*f6aab3d8Srobert // To prevent you giving both types in a state and overwriting
338*f6aab3d8Srobert // one or the other, we'll expect to get either all S registers,
339*f6aab3d8Srobert // or all D registers. Not a mix of the two.
340*f6aab3d8Srobert bool found_s_registers =
341*f6aab3d8Srobert LoadRegistersStateFromDictionary(reg_dict, 's', dwarf_s0, 32);
342*f6aab3d8Srobert bool found_d_registers =
343*f6aab3d8Srobert LoadRegistersStateFromDictionary(reg_dict, 'd', dwarf_d0, 32);
344061da546Spatrick
345*f6aab3d8Srobert return found_s_registers != found_d_registers;
346061da546Spatrick }
347