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