From 290c4bc7be45a29d98ea2e8460ef50f4924a1c4b Mon Sep 17 00:00:00 2001 From: David Spickett Date: Fri, 22 Jul 2022 14:13:32 +0000 Subject: [PATCH] [LLDB][ARM] Generalise adding register state in emulation tests and add D registers Since some s and d registers overlap we will error if we find both. This prevents you overwriting one with the other in a test case. Reviewed By: clayborg Differential Revision: https://reviews.llvm.org/D130462 --- .../Plugins/Instruction/ARM/EmulationStateARM.cpp | 52 ++++++++++++---------- .../Plugins/Instruction/ARM/EmulationStateARM.h | 4 ++ 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp b/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp index 32430cd..bc5a7f4 100644 --- a/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp +++ b/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp @@ -272,6 +272,23 @@ bool EmulationStateARM::CompareState(EmulationStateARM &other_state) { return match; } +bool EmulationStateARM::LoadRegistersStateFromDictionary( + OptionValueDictionary *reg_dict, char kind, int first_reg, int num) { + StreamString sstr; + for (int i = 0; i < num; ++i) { + sstr.Clear(); + sstr.Printf("%c%d", kind, i); + OptionValueSP value_sp = + reg_dict->GetValueForKey(ConstString(sstr.GetString())); + if (value_sp.get() == nullptr) + return false; + uint64_t reg_value = value_sp->GetUInt64Value(); + StorePseudoRegisterValue(first_reg + i, reg_value); + } + + return true; +} + bool EmulationStateARM::LoadStateFromDictionary( OptionValueDictionary *test_data) { static ConstString memory_key("memory"); @@ -321,18 +338,8 @@ bool EmulationStateARM::LoadStateFromDictionary( // Load General Registers OptionValueDictionary *reg_dict = value_sp->GetAsDictionary(); - - StreamString sstr; - for (int i = 0; i < 16; ++i) { - sstr.Clear(); - sstr.Printf("r%d", i); - ConstString reg_name(sstr.GetString()); - value_sp = reg_dict->GetValueForKey(reg_name); - if (value_sp.get() == nullptr) - return false; - uint64_t reg_value = value_sp->GetUInt64Value(); - StorePseudoRegisterValue(dwarf_r0 + i, reg_value); - } + if (!LoadRegistersStateFromDictionary(reg_dict, 'r', dwarf_r0, 16)) + return false; static ConstString cpsr_name("cpsr"); value_sp = reg_dict->GetValueForKey(cpsr_name); @@ -341,16 +348,13 @@ bool EmulationStateARM::LoadStateFromDictionary( StorePseudoRegisterValue(dwarf_cpsr, value_sp->GetUInt64Value()); // Load s/d Registers - for (int i = 0; i < 32; ++i) { - sstr.Clear(); - sstr.Printf("s%d", i); - ConstString reg_name(sstr.GetString()); - value_sp = reg_dict->GetValueForKey(reg_name); - if (value_sp.get() == nullptr) - return false; - uint64_t reg_value = value_sp->GetUInt64Value(); - StorePseudoRegisterValue(dwarf_s0 + i, reg_value); - } - - return true; + // To prevent you giving both types in a state and overwriting + // one or the other, we'll expect to get either all S registers, + // or all D registers. Not a mix of the two. + bool found_s_registers = + LoadRegistersStateFromDictionary(reg_dict, 's', dwarf_s0, 32); + bool found_d_registers = + LoadRegistersStateFromDictionary(reg_dict, 'd', dwarf_d0, 32); + + return found_s_registers != found_d_registers; } diff --git a/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h b/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h index 28bc5d9..b240fbb 100644 --- a/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h +++ b/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h @@ -61,6 +61,10 @@ public: const lldb_private::RegisterValue ®_value); private: + bool LoadRegistersStateFromDictionary( + lldb_private::OptionValueDictionary *reg_dict, char kind, int first_reg, + int num); + uint32_t m_gpr[17] = {0}; struct _sd_regs { uint32_t s_regs[32]; // sregs 0 - 31 & dregs 0 - 15 -- 2.7.4