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