EmulationStateARM.cpp revision 061b79dbf1fefaf157d414747e98a463a0f32eda
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
19using namespace lldb;
20using namespace lldb_private;
21
22EmulationStateARM::EmulationStateARM () :
23    m_gpr (),
24    m_vfp_regs (),
25    m_memory ()
26{
27    ClearPseudoRegisters();
28}
29
30EmulationStateARM::~EmulationStateARM ()
31{
32}
33
34bool
35EmulationStateARM::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
75bool
76EmulationStateARM::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
100uint64_t
101EmulationStateARM::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
126void
127EmulationStateARM::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
139void
140EmulationStateARM::ClearPseudoMemory ()
141{
142    m_memory.clear();
143}
144
145bool
146EmulationStateARM::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
161uint32_t
162EmulationStateARM::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
177size_t
178EmulationStateARM::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
221size_t
222EmulationStateARM::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
242bool
243EmulationStateARM::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
263bool
264EmulationStateARM::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
279bool
280EmulationStateARM::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
316bool
317EmulationStateARM::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