180814287SRaphael Isemann //===-- EmulationStateARM.cpp ---------------------------------------------===//
23ac6711aSCaroline Tice //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63ac6711aSCaroline Tice //
73ac6711aSCaroline Tice //===----------------------------------------------------------------------===//
83ac6711aSCaroline Tice 
93ac6711aSCaroline Tice #include "EmulationStateARM.h"
103ac6711aSCaroline Tice 
1167cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueArray.h"
1267cc0636SGreg Clayton #include "lldb/Interpreter/OptionValueDictionary.h"
133ac6711aSCaroline Tice #include "lldb/Target/RegisterContext.h"
14b9c1b51eSKate Stone #include "lldb/Target/StackFrame.h"
15d821c997SPavel Labath #include "lldb/Utility/RegisterValue.h"
16d821c997SPavel Labath #include "lldb/Utility/Scalar.h"
173ac6711aSCaroline Tice 
183ac6711aSCaroline Tice #include "Utility/ARM_DWARF_Registers.h"
193ac6711aSCaroline Tice 
203ac6711aSCaroline Tice using namespace lldb;
213ac6711aSCaroline Tice using namespace lldb_private;
223ac6711aSCaroline Tice 
EmulationStateARM()239494c510SJonas Devlieghere EmulationStateARM::EmulationStateARM() : m_vfp_regs(), m_memory() {
243ac6711aSCaroline Tice   ClearPseudoRegisters();
253ac6711aSCaroline Tice }
263ac6711aSCaroline Tice 
27fd2433e1SJonas Devlieghere EmulationStateARM::~EmulationStateARM() = default;
283ac6711aSCaroline Tice 
LoadPseudoRegistersFromFrame(StackFrame & frame)29b9c1b51eSKate Stone bool EmulationStateARM::LoadPseudoRegistersFromFrame(StackFrame &frame) {
307349bd90SGreg Clayton   RegisterContext *reg_ctx = frame.GetRegisterContext().get();
313ac6711aSCaroline Tice   bool success = true;
327349bd90SGreg Clayton   uint32_t reg_num;
333ac6711aSCaroline Tice 
34b9c1b51eSKate Stone   for (int i = dwarf_r0; i < dwarf_r0 + 17; ++i) {
35b9c1b51eSKate Stone     reg_num =
36b9c1b51eSKate Stone         reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindDWARF, i);
377349bd90SGreg Clayton     const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num);
387349bd90SGreg Clayton     RegisterValue reg_value;
39b9c1b51eSKate Stone     if (reg_ctx->ReadRegister(reg_info, reg_value)) {
407349bd90SGreg Clayton       m_gpr[i - dwarf_r0] = reg_value.GetAsUInt32();
41b9c1b51eSKate Stone     } else
423ac6711aSCaroline Tice       success = false;
433ac6711aSCaroline Tice   }
443ac6711aSCaroline Tice 
45b9c1b51eSKate Stone   for (int i = dwarf_d0; i < dwarf_d0 + 32; ++i) {
46b9c1b51eSKate Stone     reg_num =
47b9c1b51eSKate Stone         reg_ctx->ConvertRegisterKindToRegisterNumber(eRegisterKindDWARF, i);
487349bd90SGreg Clayton     RegisterValue reg_value;
497349bd90SGreg Clayton     const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num);
507349bd90SGreg Clayton 
51b9c1b51eSKate Stone     if (reg_ctx->ReadRegister(reg_info, reg_value)) {
5291a2ad18SUlrich Weigand       uint64_t value = reg_value.GetAsUInt64();
533ac6711aSCaroline Tice       uint32_t idx = i - dwarf_d0;
54b9c1b51eSKate Stone       if (i < 16) {
5591a2ad18SUlrich Weigand         m_vfp_regs.s_regs[idx * 2] = (uint32_t)value;
5691a2ad18SUlrich Weigand         m_vfp_regs.s_regs[idx * 2 + 1] = (uint32_t)(value >> 32);
57b9c1b51eSKate Stone       } else
5891a2ad18SUlrich Weigand         m_vfp_regs.d_regs[idx - 16] = value;
59b9c1b51eSKate Stone     } else
603ac6711aSCaroline Tice       success = false;
613ac6711aSCaroline Tice   }
623ac6711aSCaroline Tice 
633ac6711aSCaroline Tice   return success;
643ac6711aSCaroline Tice }
653ac6711aSCaroline Tice 
StorePseudoRegisterValue(uint32_t reg_num,uint64_t value)66b9c1b51eSKate Stone bool EmulationStateARM::StorePseudoRegisterValue(uint32_t reg_num,
67b9c1b51eSKate Stone                                                  uint64_t value) {
6849a28fdaSDavide Italiano   if (reg_num <= dwarf_cpsr)
693ac6711aSCaroline Tice     m_gpr[reg_num - dwarf_r0] = (uint32_t)value;
70b9c1b51eSKate Stone   else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) {
713ac6711aSCaroline Tice     uint32_t idx = reg_num - dwarf_s0;
7291a2ad18SUlrich Weigand     m_vfp_regs.s_regs[idx] = (uint32_t)value;
73b9c1b51eSKate Stone   } else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31)) {
7491a2ad18SUlrich Weigand     uint32_t idx = reg_num - dwarf_d0;
75b9c1b51eSKate Stone     if (idx < 16) {
7691a2ad18SUlrich Weigand       m_vfp_regs.s_regs[idx * 2] = (uint32_t)value;
7791a2ad18SUlrich Weigand       m_vfp_regs.s_regs[idx * 2 + 1] = (uint32_t)(value >> 32);
78b9c1b51eSKate Stone     } else
7991a2ad18SUlrich Weigand       m_vfp_regs.d_regs[idx - 16] = value;
80b9c1b51eSKate Stone   } else
813ac6711aSCaroline Tice     return false;
823ac6711aSCaroline Tice 
833ac6711aSCaroline Tice   return true;
843ac6711aSCaroline Tice }
853ac6711aSCaroline Tice 
ReadPseudoRegisterValue(uint32_t reg_num,bool & success)86b9c1b51eSKate Stone uint64_t EmulationStateARM::ReadPseudoRegisterValue(uint32_t reg_num,
87b9c1b51eSKate Stone                                                     bool &success) {
883ac6711aSCaroline Tice   uint64_t value = 0;
893ac6711aSCaroline Tice   success = true;
903ac6711aSCaroline Tice 
9149a28fdaSDavide Italiano   if (reg_num <= dwarf_cpsr)
923ac6711aSCaroline Tice     value = m_gpr[reg_num - dwarf_r0];
93b9c1b51eSKate Stone   else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31)) {
943ac6711aSCaroline Tice     uint32_t idx = reg_num - dwarf_s0;
9591a2ad18SUlrich Weigand     value = m_vfp_regs.d_regs[idx];
96b9c1b51eSKate Stone   } else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31)) {
9791a2ad18SUlrich Weigand     uint32_t idx = reg_num - dwarf_d0;
9891a2ad18SUlrich Weigand     if (idx < 16)
99b9c1b51eSKate Stone       value = (uint64_t)m_vfp_regs.s_regs[idx * 2] |
100e80dbfddSSlava Gurevich               ((uint64_t)m_vfp_regs.s_regs[idx * 2 + 1] << 32);
1013ac6711aSCaroline Tice     else
10291a2ad18SUlrich Weigand       value = m_vfp_regs.d_regs[idx - 16];
103b9c1b51eSKate Stone   } else
1043ac6711aSCaroline Tice     success = false;
1053ac6711aSCaroline Tice 
1063ac6711aSCaroline Tice   return value;
1073ac6711aSCaroline Tice }
1083ac6711aSCaroline Tice 
ClearPseudoRegisters()109b9c1b51eSKate Stone void EmulationStateARM::ClearPseudoRegisters() {
1103ac6711aSCaroline Tice   for (int i = 0; i < 17; ++i)
1113ac6711aSCaroline Tice     m_gpr[i] = 0;
1123ac6711aSCaroline Tice 
11391a2ad18SUlrich Weigand   for (int i = 0; i < 32; ++i)
11491a2ad18SUlrich Weigand     m_vfp_regs.s_regs[i] = 0;
1153ac6711aSCaroline Tice 
1163ac6711aSCaroline Tice   for (int i = 0; i < 16; ++i)
1173ac6711aSCaroline Tice     m_vfp_regs.d_regs[i] = 0;
1183ac6711aSCaroline Tice }
1193ac6711aSCaroline Tice 
ClearPseudoMemory()120b9c1b51eSKate Stone void EmulationStateARM::ClearPseudoMemory() { m_memory.clear(); }
1213ac6711aSCaroline Tice 
StoreToPseudoAddress(lldb::addr_t p_address,uint32_t value)122b9c1b51eSKate Stone bool EmulationStateARM::StoreToPseudoAddress(lldb::addr_t p_address,
123b9c1b51eSKate Stone                                              uint32_t value) {
1243ac6711aSCaroline Tice   m_memory[p_address] = value;
1253ac6711aSCaroline Tice   return true;
1263ac6711aSCaroline Tice }
1273ac6711aSCaroline Tice 
ReadFromPseudoAddress(lldb::addr_t p_address,bool & success)128b9c1b51eSKate Stone uint32_t EmulationStateARM::ReadFromPseudoAddress(lldb::addr_t p_address,
129b9c1b51eSKate Stone                                                   bool &success) {
1303ac6711aSCaroline Tice   std::map<lldb::addr_t, uint32_t>::iterator pos;
1313ac6711aSCaroline Tice   uint32_t ret_val = 0;
1323ac6711aSCaroline Tice 
1333ac6711aSCaroline Tice   success = true;
1343ac6711aSCaroline Tice   pos = m_memory.find(p_address);
1353ac6711aSCaroline Tice   if (pos != m_memory.end())
1363ac6711aSCaroline Tice     ret_val = pos->second;
1373ac6711aSCaroline Tice   else
1383ac6711aSCaroline Tice     success = false;
1393ac6711aSCaroline Tice 
1403ac6711aSCaroline Tice   return ret_val;
1413ac6711aSCaroline Tice }
1423ac6711aSCaroline Tice 
ReadPseudoMemory(EmulateInstruction * instruction,void * baton,const EmulateInstruction::Context & context,lldb::addr_t addr,void * dst,size_t length)143b9c1b51eSKate Stone size_t EmulationStateARM::ReadPseudoMemory(
144b9c1b51eSKate Stone     EmulateInstruction *instruction, void *baton,
145b9c1b51eSKate Stone     const EmulateInstruction::Context &context, lldb::addr_t addr, void *dst,
146b9c1b51eSKate Stone     size_t length) {
1473ac6711aSCaroline Tice   if (!baton)
1483ac6711aSCaroline Tice     return 0;
1493ac6711aSCaroline Tice 
1503ac6711aSCaroline Tice   bool success = true;
1513ac6711aSCaroline Tice   EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;
152b9c1b51eSKate Stone   if (length <= 4) {
15391a2ad18SUlrich Weigand     uint32_t value = pseudo_state->ReadFromPseudoAddress(addr, success);
1543ac6711aSCaroline Tice     if (!success)
1553ac6711aSCaroline Tice       return 0;
1563ac6711aSCaroline Tice 
15791a2ad18SUlrich Weigand     if (endian::InlHostByteOrder() == lldb::eByteOrderBig)
15891a2ad18SUlrich Weigand       value = llvm::ByteSwap_32(value);
1593ac6711aSCaroline Tice     *((uint32_t *)dst) = value;
160b9c1b51eSKate Stone   } else if (length == 8) {
16191a2ad18SUlrich Weigand     uint32_t value1 = pseudo_state->ReadFromPseudoAddress(addr, success);
1623ac6711aSCaroline Tice     if (!success)
1633ac6711aSCaroline Tice       return 0;
1643ac6711aSCaroline Tice 
16591a2ad18SUlrich Weigand     uint32_t value2 = pseudo_state->ReadFromPseudoAddress(addr + 4, success);
1663ac6711aSCaroline Tice     if (!success)
1673ac6711aSCaroline Tice       return 0;
1683ac6711aSCaroline Tice 
169b9c1b51eSKate Stone     if (endian::InlHostByteOrder() == lldb::eByteOrderBig) {
17091a2ad18SUlrich Weigand       value1 = llvm::ByteSwap_32(value1);
17191a2ad18SUlrich Weigand       value2 = llvm::ByteSwap_32(value2);
17291a2ad18SUlrich Weigand     }
17391a2ad18SUlrich Weigand     ((uint32_t *)dst)[0] = value1;
17491a2ad18SUlrich Weigand     ((uint32_t *)dst)[1] = value2;
175b9c1b51eSKate Stone   } else
1763ac6711aSCaroline Tice     success = false;
1773ac6711aSCaroline Tice 
1783ac6711aSCaroline Tice   if (success)
1793ac6711aSCaroline Tice     return length;
1803ac6711aSCaroline Tice 
1813ac6711aSCaroline Tice   return 0;
1823ac6711aSCaroline Tice }
1833ac6711aSCaroline Tice 
WritePseudoMemory(EmulateInstruction * instruction,void * baton,const EmulateInstruction::Context & context,lldb::addr_t addr,const void * dst,size_t length)184b9c1b51eSKate Stone size_t EmulationStateARM::WritePseudoMemory(
185b9c1b51eSKate Stone     EmulateInstruction *instruction, void *baton,
186b9c1b51eSKate Stone     const EmulateInstruction::Context &context, lldb::addr_t addr,
187b9c1b51eSKate Stone     const void *dst, size_t length) {
1883ac6711aSCaroline Tice   if (!baton)
1893ac6711aSCaroline Tice     return 0;
1903ac6711aSCaroline Tice 
1913ac6711aSCaroline Tice   EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;
19291a2ad18SUlrich Weigand 
193b9c1b51eSKate Stone   if (length <= 4) {
1943724ae4eSJason Molenda     uint32_t value;
1953724ae4eSJason Molenda     memcpy (&value, dst, sizeof (uint32_t));
19691a2ad18SUlrich Weigand     if (endian::InlHostByteOrder() == lldb::eByteOrderBig)
19791a2ad18SUlrich Weigand       value = llvm::ByteSwap_32(value);
19891a2ad18SUlrich Weigand 
19991a2ad18SUlrich Weigand     pseudo_state->StoreToPseudoAddress(addr, value);
2003ac6711aSCaroline Tice     return length;
201b9c1b51eSKate Stone   } else if (length == 8) {
2023724ae4eSJason Molenda     uint32_t value1;
2033724ae4eSJason Molenda     uint32_t value2;
2043724ae4eSJason Molenda     memcpy (&value1, dst, sizeof (uint32_t));
205f76e099cSSaleem Abdulrasool     memcpy(&value2, static_cast<const uint8_t *>(dst) + sizeof(uint32_t),
206f76e099cSSaleem Abdulrasool            sizeof(uint32_t));
207b9c1b51eSKate Stone     if (endian::InlHostByteOrder() == lldb::eByteOrderBig) {
20891a2ad18SUlrich Weigand       value1 = llvm::ByteSwap_32(value1);
20991a2ad18SUlrich Weigand       value2 = llvm::ByteSwap_32(value2);
21091a2ad18SUlrich Weigand     }
21191a2ad18SUlrich Weigand 
21291a2ad18SUlrich Weigand     pseudo_state->StoreToPseudoAddress(addr, value1);
21391a2ad18SUlrich Weigand     pseudo_state->StoreToPseudoAddress(addr + 4, value2);
21491a2ad18SUlrich Weigand     return length;
21591a2ad18SUlrich Weigand   }
2163ac6711aSCaroline Tice 
2173ac6711aSCaroline Tice   return 0;
2183ac6711aSCaroline Tice }
2193ac6711aSCaroline Tice 
ReadPseudoRegister(EmulateInstruction * instruction,void * baton,const lldb_private::RegisterInfo * reg_info,lldb_private::RegisterValue & reg_value)220b9c1b51eSKate Stone bool EmulationStateARM::ReadPseudoRegister(
221b9c1b51eSKate Stone     EmulateInstruction *instruction, void *baton,
2227349bd90SGreg Clayton     const lldb_private::RegisterInfo *reg_info,
223b9c1b51eSKate Stone     lldb_private::RegisterValue &reg_value) {
2247349bd90SGreg Clayton   if (!baton || !reg_info)
2253ac6711aSCaroline Tice     return false;
2263ac6711aSCaroline Tice 
2273ac6711aSCaroline Tice   bool success = true;
2283ac6711aSCaroline Tice   EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;
2297349bd90SGreg Clayton   const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF];
2307349bd90SGreg Clayton   assert(dwarf_reg_num != LLDB_INVALID_REGNUM);
231b9c1b51eSKate Stone   uint64_t reg_uval =
232b9c1b51eSKate Stone       pseudo_state->ReadPseudoRegisterValue(dwarf_reg_num, success);
2333ac6711aSCaroline Tice 
2347349bd90SGreg Clayton   if (success)
2357349bd90SGreg Clayton     success = reg_value.SetUInt(reg_uval, reg_info->byte_size);
2363ac6711aSCaroline Tice   return success;
2373ac6711aSCaroline Tice }
2383ac6711aSCaroline Tice 
WritePseudoRegister(EmulateInstruction * instruction,void * baton,const EmulateInstruction::Context & context,const lldb_private::RegisterInfo * reg_info,const lldb_private::RegisterValue & reg_value)239b9c1b51eSKate Stone bool EmulationStateARM::WritePseudoRegister(
240b9c1b51eSKate Stone     EmulateInstruction *instruction, void *baton,
2413ac6711aSCaroline Tice     const EmulateInstruction::Context &context,
2427349bd90SGreg Clayton     const lldb_private::RegisterInfo *reg_info,
243b9c1b51eSKate Stone     const lldb_private::RegisterValue &reg_value) {
2447349bd90SGreg Clayton   if (!baton || !reg_info)
2453ac6711aSCaroline Tice     return false;
2463ac6711aSCaroline Tice 
2473ac6711aSCaroline Tice   EmulationStateARM *pseudo_state = (EmulationStateARM *)baton;
2487349bd90SGreg Clayton   const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF];
2497349bd90SGreg Clayton   assert(dwarf_reg_num != LLDB_INVALID_REGNUM);
250b9c1b51eSKate Stone   return pseudo_state->StorePseudoRegisterValue(dwarf_reg_num,
251b9c1b51eSKate Stone                                                 reg_value.GetAsUInt64());
2523ac6711aSCaroline Tice }
2533ac6711aSCaroline Tice 
CompareState(EmulationStateARM & other_state,Stream * out_stream)2543ebd5419SDavid Spickett bool EmulationStateARM::CompareState(EmulationStateARM &other_state,
2553ebd5419SDavid Spickett                                      Stream *out_stream) {
2563ac6711aSCaroline Tice   bool match = true;
2573ac6711aSCaroline Tice 
258b9c1b51eSKate Stone   for (int i = 0; match && i < 17; ++i) {
2593ebd5419SDavid Spickett     if (m_gpr[i] != other_state.m_gpr[i]) {
2603ac6711aSCaroline Tice       match = false;
2613ebd5419SDavid Spickett       out_stream->Printf("r%d: 0x%x != 0x%x\n", i, m_gpr[i],
2623ebd5419SDavid Spickett                          other_state.m_gpr[i]);
2633ebd5419SDavid Spickett     }
2643ac6711aSCaroline Tice   }
2653ac6711aSCaroline Tice 
266b9c1b51eSKate Stone   for (int i = 0; match && i < 32; ++i) {
2673ebd5419SDavid Spickett     if (m_vfp_regs.s_regs[i] != other_state.m_vfp_regs.s_regs[i]) {
2683ac6711aSCaroline Tice       match = false;
2693ebd5419SDavid Spickett       out_stream->Printf("s%d: 0x%x != 0x%x\n", i, m_vfp_regs.s_regs[i],
2703ebd5419SDavid Spickett                          other_state.m_vfp_regs.s_regs[i]);
2713ebd5419SDavid Spickett     }
2723ac6711aSCaroline Tice   }
27391a2ad18SUlrich Weigand 
274b9c1b51eSKate Stone   for (int i = 0; match && i < 16; ++i) {
2753ebd5419SDavid Spickett     if (m_vfp_regs.d_regs[i] != other_state.m_vfp_regs.d_regs[i]) {
2763ac6711aSCaroline Tice       match = false;
277*d0479cb2SDavid Spickett       out_stream->Printf("d%d: 0x%" PRIx64 " != 0x%" PRIx64 "\n", i + 16,
278*d0479cb2SDavid Spickett                          m_vfp_regs.d_regs[i],
2793ebd5419SDavid Spickett                          other_state.m_vfp_regs.d_regs[i]);
2803ebd5419SDavid Spickett     }
2813ac6711aSCaroline Tice   }
2823ac6711aSCaroline Tice 
28310c2bab5SDavid Spickett   // other_state is the expected state. If it has memory, check it.
28410c2bab5SDavid Spickett   if (!other_state.m_memory.empty() && m_memory != other_state.m_memory) {
28510c2bab5SDavid Spickett     match = false;
28610c2bab5SDavid Spickett     out_stream->Printf("memory does not match\n");
28710c2bab5SDavid Spickett     out_stream->Printf("got memory:\n");
28810c2bab5SDavid Spickett     for (auto p : m_memory)
289*d0479cb2SDavid Spickett       out_stream->Printf("0x%08" PRIx64 ": 0x%08x\n", p.first, p.second);
29010c2bab5SDavid Spickett     out_stream->Printf("expected memory:\n");
29110c2bab5SDavid Spickett     for (auto p : other_state.m_memory)
292*d0479cb2SDavid Spickett       out_stream->Printf("0x%08" PRIx64 ": 0x%08x\n", p.first, p.second);
29310c2bab5SDavid Spickett   }
29410c2bab5SDavid Spickett 
2953ac6711aSCaroline Tice   return match;
2963ac6711aSCaroline Tice }
297de2fb9cfSCaroline Tice 
LoadRegistersStateFromDictionary(OptionValueDictionary * reg_dict,char kind,int first_reg,int num)298290c4bc7SDavid Spickett bool EmulationStateARM::LoadRegistersStateFromDictionary(
299290c4bc7SDavid Spickett     OptionValueDictionary *reg_dict, char kind, int first_reg, int num) {
300290c4bc7SDavid Spickett   StreamString sstr;
301290c4bc7SDavid Spickett   for (int i = 0; i < num; ++i) {
302290c4bc7SDavid Spickett     sstr.Clear();
303290c4bc7SDavid Spickett     sstr.Printf("%c%d", kind, i);
304290c4bc7SDavid Spickett     OptionValueSP value_sp =
305290c4bc7SDavid Spickett         reg_dict->GetValueForKey(ConstString(sstr.GetString()));
306290c4bc7SDavid Spickett     if (value_sp.get() == nullptr)
307290c4bc7SDavid Spickett       return false;
308290c4bc7SDavid Spickett     uint64_t reg_value = value_sp->GetUInt64Value();
309290c4bc7SDavid Spickett     StorePseudoRegisterValue(first_reg + i, reg_value);
310290c4bc7SDavid Spickett   }
311290c4bc7SDavid Spickett 
312290c4bc7SDavid Spickett   return true;
313290c4bc7SDavid Spickett }
314290c4bc7SDavid Spickett 
LoadStateFromDictionary(OptionValueDictionary * test_data)315b9c1b51eSKate Stone bool EmulationStateARM::LoadStateFromDictionary(
316b9c1b51eSKate Stone     OptionValueDictionary *test_data) {
317de2fb9cfSCaroline Tice   static ConstString memory_key("memory");
318de2fb9cfSCaroline Tice   static ConstString registers_key("registers");
319de2fb9cfSCaroline Tice 
320de2fb9cfSCaroline Tice   if (!test_data)
321de2fb9cfSCaroline Tice     return false;
322de2fb9cfSCaroline Tice 
323de2fb9cfSCaroline Tice   OptionValueSP value_sp = test_data->GetValueForKey(memory_key);
324de2fb9cfSCaroline Tice 
325de2fb9cfSCaroline Tice   // Load memory, if present.
326de2fb9cfSCaroline Tice 
327248a1305SKonrad Kleine   if (value_sp.get() != nullptr) {
328de2fb9cfSCaroline Tice     static ConstString address_key("address");
329de2fb9cfSCaroline Tice     static ConstString data_key("data");
330de2fb9cfSCaroline Tice     uint64_t start_address = 0;
331de2fb9cfSCaroline Tice 
33284c39663SGreg Clayton     OptionValueDictionary *mem_dict = value_sp->GetAsDictionary();
333de2fb9cfSCaroline Tice     value_sp = mem_dict->GetValueForKey(address_key);
334248a1305SKonrad Kleine     if (value_sp.get() == nullptr)
335de2fb9cfSCaroline Tice       return false;
336de2fb9cfSCaroline Tice     else
337de2fb9cfSCaroline Tice       start_address = value_sp->GetUInt64Value();
338de2fb9cfSCaroline Tice 
339de2fb9cfSCaroline Tice     value_sp = mem_dict->GetValueForKey(data_key);
34084c39663SGreg Clayton     OptionValueArray *mem_array = value_sp->GetAsArray();
341de2fb9cfSCaroline Tice     if (!mem_array)
342de2fb9cfSCaroline Tice       return false;
343de2fb9cfSCaroline Tice 
344de2fb9cfSCaroline Tice     uint32_t num_elts = mem_array->GetSize();
345de2fb9cfSCaroline Tice     uint32_t address = (uint32_t)start_address;
346de2fb9cfSCaroline Tice 
347b9c1b51eSKate Stone     for (uint32_t i = 0; i < num_elts; ++i) {
348de2fb9cfSCaroline Tice       value_sp = mem_array->GetValueAtIndex(i);
349248a1305SKonrad Kleine       if (value_sp.get() == nullptr)
350de2fb9cfSCaroline Tice         return false;
351de2fb9cfSCaroline Tice       uint64_t value = value_sp->GetUInt64Value();
35291a2ad18SUlrich Weigand       StoreToPseudoAddress(address, value);
353de2fb9cfSCaroline Tice       address = address + 4;
354de2fb9cfSCaroline Tice     }
355de2fb9cfSCaroline Tice   }
356de2fb9cfSCaroline Tice 
357de2fb9cfSCaroline Tice   value_sp = test_data->GetValueForKey(registers_key);
358248a1305SKonrad Kleine   if (value_sp.get() == nullptr)
359de2fb9cfSCaroline Tice     return false;
360de2fb9cfSCaroline Tice 
361de2fb9cfSCaroline Tice   // Load General Registers
362de2fb9cfSCaroline Tice 
36384c39663SGreg Clayton   OptionValueDictionary *reg_dict = value_sp->GetAsDictionary();
364290c4bc7SDavid Spickett   if (!LoadRegistersStateFromDictionary(reg_dict, 'r', dwarf_r0, 16))
365de2fb9cfSCaroline Tice     return false;
366de2fb9cfSCaroline Tice 
367de2fb9cfSCaroline Tice   static ConstString cpsr_name("cpsr");
368de2fb9cfSCaroline Tice   value_sp = reg_dict->GetValueForKey(cpsr_name);
369248a1305SKonrad Kleine   if (value_sp.get() == nullptr)
370de2fb9cfSCaroline Tice     return false;
371de2fb9cfSCaroline Tice   StorePseudoRegisterValue(dwarf_cpsr, value_sp->GetUInt64Value());
372de2fb9cfSCaroline Tice 
373de2fb9cfSCaroline Tice   // Load s/d Registers
374290c4bc7SDavid Spickett   // To prevent you giving both types in a state and overwriting
375290c4bc7SDavid Spickett   // one or the other, we'll expect to get either all S registers,
376290c4bc7SDavid Spickett   // or all D registers. Not a mix of the two.
377290c4bc7SDavid Spickett   bool found_s_registers =
378290c4bc7SDavid Spickett       LoadRegistersStateFromDictionary(reg_dict, 's', dwarf_s0, 32);
379290c4bc7SDavid Spickett   bool found_d_registers =
380290c4bc7SDavid Spickett       LoadRegistersStateFromDictionary(reg_dict, 'd', dwarf_d0, 32);
381de2fb9cfSCaroline Tice 
382290c4bc7SDavid Spickett   return found_s_registers != found_d_registers;
383de2fb9cfSCaroline Tice }
384