Home | History | Annotate | Download | only in ARM
      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             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 
     77 bool
     78 EmulationStateARM::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 
    102 uint64_t
    103 EmulationStateARM::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 
    128 void
    129 EmulationStateARM::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 
    141 void
    142 EmulationStateARM::ClearPseudoMemory ()
    143 {
    144     m_memory.clear();
    145 }
    146 
    147 bool
    148 EmulationStateARM::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 
    163 uint32_t
    164 EmulationStateARM::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 
    179 size_t
    180 EmulationStateARM::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 
    223 size_t
    224 EmulationStateARM::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 
    244 bool
    245 EmulationStateARM::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 
    265 bool
    266 EmulationStateARM::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 
    281 bool
    282 EmulationStateARM::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 
    318 bool
    319 EmulationStateARM::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