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