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