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 ®_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 ®_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