1//===-- EmulationStateARM.cpp -----------------------------------*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
9#include "EmulationStateARM.h"
10
11#include "lldb/Interpreter/OptionValueArray.h"
12#include "lldb/Interpreter/OptionValueDictionary.h"
13#include "lldb/Target/RegisterContext.h"
14#include "lldb/Target/StackFrame.h"
15#include "lldb/Utility/RegisterValue.h"
16#include "lldb/Utility/Scalar.h"
17
18#include "Utility/ARM_DWARF_Registers.h"
19
20using namespace lldb;
21using namespace lldb_private;
22
23EmulationStateARM::EmulationStateARM() : m_gpr(), m_vfp_regs(), m_memory() {
24  ClearPseudoRegisters();
25}
26
27EmulationStateARM::~EmulationStateARM() {}
28
29bool EmulationStateARM::LoadPseudoRegistersFromFrame(StackFrame &frame) {
30  RegisterContext *reg_ctx = frame.GetRegisterContext().get();
31  bool success = true;
32  uint32_t reg_num;
33
34  for (int i = dwarf_r0; i < dwarf_r0 + 17; ++i) {
35    reg_num =
36        reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindDWARF, i);
37    const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num);
38    RegisterValue reg_value;
39    if (reg_ctx->ReadRegister(reg_info, reg_value)) {
40      m_gpr[i - dwarf_r0] = reg_value.GetAsUInt32();
41    } else
42      success = false;
43  }
44
45  for (int i = dwarf_d0; i < dwarf_d0 + 32; ++i) {
46    reg_num =
47        reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindDWARF, i);
48    RegisterValue reg_value;
49    const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num);
50
51    if (reg_ctx->ReadRegister(reg_info, reg_value)) {
52      uint64_t value = reg_value.GetAsUInt64();
53      uint32_t idx = i - dwarf_d0;
54      if (i < 16) {
55        m_vfp_regs.s_regs[idx * 2] = (uint32_t)value;
56        m_vfp_regs.s_regs[idx * 2 + 1] = (uint32_t)(value >> 32);
57      } else
58        m_vfp_regs.d_regs[idx - 16] = value;
59    } else
60      success = false;
61  }
62
63  return success;
64}
65
66bool EmulationStateARM::StorePseudoRegisterValue(uint32_t reg_num,
67                                                 uint64_t value) {
68  if (reg_num <= dwarf_cpsr)
69    m_gpr[reg_num - dwarf_r0] = (uint32_t)value;
70  else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) {
71    uint32_t idx = reg_num - dwarf_s0;
72    m_vfp_regs.s_regs[idx] = (uint32_t)value;
73  } else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31)) {
74    uint32_t idx = reg_num - dwarf_d0;
75    if (idx < 16) {
76      m_vfp_regs.s_regs[idx * 2] = (uint32_t)value;
77      m_vfp_regs.s_regs[idx * 2 + 1] = (uint32_t)(value >> 32);
78    } else
79      m_vfp_regs.d_regs[idx - 16] = value;
80  } else
81    return false;
82
83  return true;
84}
85
86uint64_t EmulationStateARM::ReadPseudoRegisterValue(uint32_t reg_num,
87                                                    bool &success) {
88  uint64_t value = 0;
89  success = true;
90
91  if (reg_num <= dwarf_cpsr)
92    value = m_gpr[reg_num - dwarf_r0];
93  else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) {
94    uint32_t idx = reg_num - dwarf_s0;
95    value = m_vfp_regs.d_regs[idx];
96  } else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31)) {
97    uint32_t idx = reg_num - dwarf_d0;
98    if (idx < 16)
99      value = (uint64_t)m_vfp_regs.s_regs[idx * 2] |
100              ((uint64_t)m_vfp_regs.s_regs[idx * 2 + 1] >> 32);
101    else
102      value = m_vfp_regs.d_regs[idx - 16];
103  } else
104    success = false;
105
106  return value;
107}
108
109void EmulationStateARM::ClearPseudoRegisters() {
110  for (int i = 0; i < 17; ++i)
111    m_gpr[i] = 0;
112
113  for (int i = 0; i < 32; ++i)
114    m_vfp_regs.s_regs[i] = 0;
115
116  for (int i = 0; i < 16; ++i)
117    m_vfp_regs.d_regs[i] = 0;
118}
119
120void EmulationStateARM::ClearPseudoMemory() { m_memory.clear(); }
121
122bool EmulationStateARM::StoreToPseudoAddress(lldb::addr_t p_address,
123                                             uint32_t value) {
124  m_memory[p_address] = value;
125  return true;
126}
127
128uint32_t EmulationStateARM::ReadFromPseudoAddress(lldb::addr_t p_address,
129                                                  bool &success) {
130  std::map<lldb::addr_t, uint32_t>::iterator pos;
131  uint32_t ret_val = 0;
132
133  success = true;
134  pos = m_memory.find(p_address);
135  if (pos != m_memory.end())
136    ret_val = pos->second;
137  else
138    success = false;
139
140  return ret_val;
141}
142
143size_t EmulationStateARM::ReadPseudoMemory(
144    EmulateInstruction *instruction, void *baton,
145    const EmulateInstruction::Context &context, lldb::addr_t addr, void *dst,
146    size_t length) {
147  if (!baton)
148    return 0;
149
150  bool success = true;
151  EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;
152  if (length <= 4) {
153    uint32_t value = pseudo_state->ReadFromPseudoAddress(addr, success);
154    if (!success)
155      return 0;
156
157    if (endian::InlHostByteOrder() == lldb::eByteOrderBig)
158      value = llvm::ByteSwap_32(value);
159    *((uint32_t *)dst) = value;
160  } else if (length == 8) {
161    uint32_t value1 = pseudo_state->ReadFromPseudoAddress(addr, success);
162    if (!success)
163      return 0;
164
165    uint32_t value2 = pseudo_state->ReadFromPseudoAddress(addr + 4, success);
166    if (!success)
167      return 0;
168
169    if (endian::InlHostByteOrder() == lldb::eByteOrderBig) {
170      value1 = llvm::ByteSwap_32(value1);
171      value2 = llvm::ByteSwap_32(value2);
172    }
173    ((uint32_t *)dst)[0] = value1;
174    ((uint32_t *)dst)[1] = value2;
175  } else
176    success = false;
177
178  if (success)
179    return length;
180
181  return 0;
182}
183
184size_t EmulationStateARM::WritePseudoMemory(
185    EmulateInstruction *instruction, void *baton,
186    const EmulateInstruction::Context &context, lldb::addr_t addr,
187    const void *dst, size_t length) {
188  if (!baton)
189    return 0;
190
191  EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;
192
193  if (length <= 4) {
194    uint32_t value;
195    memcpy (&value, dst, sizeof (uint32_t));
196    if (endian::InlHostByteOrder() == lldb::eByteOrderBig)
197      value = llvm::ByteSwap_32(value);
198
199    pseudo_state->StoreToPseudoAddress(addr, value);
200    return length;
201  } else if (length == 8) {
202    uint32_t value1;
203    uint32_t value2;
204    memcpy (&value1, dst, sizeof (uint32_t));
205    memcpy(&value2, static_cast<const uint8_t *>(dst) + sizeof(uint32_t),
206           sizeof(uint32_t));
207    if (endian::InlHostByteOrder() == lldb::eByteOrderBig) {
208      value1 = llvm::ByteSwap_32(value1);
209      value2 = llvm::ByteSwap_32(value2);
210    }
211
212    pseudo_state->StoreToPseudoAddress(addr, value1);
213    pseudo_state->StoreToPseudoAddress(addr + 4, value2);
214    return length;
215  }
216
217  return 0;
218}
219
220bool EmulationStateARM::ReadPseudoRegister(
221    EmulateInstruction *instruction, void *baton,
222    const lldb_private::RegisterInfo *reg_info,
223    lldb_private::RegisterValue &reg_value) {
224  if (!baton || !reg_info)
225    return false;
226
227  bool success = true;
228  EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;
229  const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF];
230  assert(dwarf_reg_num != LLDB_INVALID_REGNUM);
231  uint64_t reg_uval =
232      pseudo_state->ReadPseudoRegisterValue(dwarf_reg_num, success);
233
234  if (success)
235    success = reg_value.SetUInt(reg_uval, reg_info->byte_size);
236  return success;
237}
238
239bool EmulationStateARM::WritePseudoRegister(
240    EmulateInstruction *instruction, void *baton,
241    const EmulateInstruction::Context &context,
242    const lldb_private::RegisterInfo *reg_info,
243    const lldb_private::RegisterValue &reg_value) {
244  if (!baton || !reg_info)
245    return false;
246
247  EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;
248  const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF];
249  assert(dwarf_reg_num != LLDB_INVALID_REGNUM);
250  return pseudo_state->StorePseudoRegisterValue(dwarf_reg_num,
251                                                reg_value.GetAsUInt64());
252}
253
254bool EmulationStateARM::CompareState(EmulationStateARM &other_state) {
255  bool match = true;
256
257  for (int i = 0; match && i < 17; ++i) {
258    if (m_gpr[i] != other_state.m_gpr[i])
259      match = false;
260  }
261
262  for (int i = 0; match && i < 32; ++i) {
263    if (m_vfp_regs.s_regs[i] != other_state.m_vfp_regs.s_regs[i])
264      match = false;
265  }
266
267  for (int i = 0; match && i < 16; ++i) {
268    if (m_vfp_regs.d_regs[i] != other_state.m_vfp_regs.d_regs[i])
269      match = false;
270  }
271
272  return match;
273}
274
275bool EmulationStateARM::LoadStateFromDictionary(
276    OptionValueDictionary *test_data) {
277  static ConstString memory_key("memory");
278  static ConstString registers_key("registers");
279
280  if (!test_data)
281    return false;
282
283  OptionValueSP value_sp = test_data->GetValueForKey(memory_key);
284
285  // Load memory, if present.
286
287  if (value_sp.get() != nullptr) {
288    static ConstString address_key("address");
289    static ConstString data_key("data");
290    uint64_t start_address = 0;
291
292    OptionValueDictionary *mem_dict = value_sp->GetAsDictionary();
293    value_sp = mem_dict->GetValueForKey(address_key);
294    if (value_sp.get() == nullptr)
295      return false;
296    else
297      start_address = value_sp->GetUInt64Value();
298
299    value_sp = mem_dict->GetValueForKey(data_key);
300    OptionValueArray *mem_array = value_sp->GetAsArray();
301    if (!mem_array)
302      return false;
303
304    uint32_t num_elts = mem_array->GetSize();
305    uint32_t address = (uint32_t)start_address;
306
307    for (uint32_t i = 0; i < num_elts; ++i) {
308      value_sp = mem_array->GetValueAtIndex(i);
309      if (value_sp.get() == nullptr)
310        return false;
311      uint64_t value = value_sp->GetUInt64Value();
312      StoreToPseudoAddress(address, value);
313      address = address + 4;
314    }
315  }
316
317  value_sp = test_data->GetValueForKey(registers_key);
318  if (value_sp.get() == nullptr)
319    return false;
320
321  // Load General Registers
322
323  OptionValueDictionary *reg_dict = value_sp->GetAsDictionary();
324
325  StreamString sstr;
326  for (int i = 0; i < 16; ++i) {
327    sstr.Clear();
328    sstr.Printf("r%d", i);
329    ConstString reg_name(sstr.GetString());
330    value_sp = reg_dict->GetValueForKey(reg_name);
331    if (value_sp.get() == nullptr)
332      return false;
333    uint64_t reg_value = value_sp->GetUInt64Value();
334    StorePseudoRegisterValue(dwarf_r0 + i, reg_value);
335  }
336
337  static ConstString cpsr_name("cpsr");
338  value_sp = reg_dict->GetValueForKey(cpsr_name);
339  if (value_sp.get() == nullptr)
340    return false;
341  StorePseudoRegisterValue(dwarf_cpsr, value_sp->GetUInt64Value());
342
343  // Load s/d Registers
344  for (int i = 0; i < 32; ++i) {
345    sstr.Clear();
346    sstr.Printf("s%d", i);
347    ConstString reg_name(sstr.GetString());
348    value_sp = reg_dict->GetValueForKey(reg_name);
349    if (value_sp.get() == nullptr)
350      return false;
351    uint64_t reg_value = value_sp->GetUInt64Value();
352    StorePseudoRegisterValue(dwarf_s0 + i, reg_value);
353  }
354
355  return true;
356}
357