diff options
-rw-r--r-- | lldb/include/lldb/Core/Disassembler.h | 7 | ||||
-rw-r--r-- | lldb/include/lldb/Core/EmulateInstruction.h | 3 | ||||
-rw-r--r-- | lldb/include/lldb/Interpreter/NamedOptionValue.h | 7 | ||||
-rw-r--r-- | lldb/source/Core/Disassembler.cpp | 237 | ||||
-rw-r--r-- | lldb/source/Interpreter/NamedOptionValue.cpp | 15 | ||||
-rw-r--r-- | lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp | 82 | ||||
-rw-r--r-- | lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h | 3 | ||||
-rw-r--r-- | lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp | 166 | ||||
-rw-r--r-- | lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h | 8 |
9 files changed, 387 insertions, 141 deletions
diff --git a/lldb/include/lldb/Core/Disassembler.h b/lldb/include/lldb/Core/Disassembler.h index 770a6a9150d..8c5a0c1a686 100644 --- a/lldb/include/lldb/Core/Disassembler.h +++ b/lldb/include/lldb/Core/Disassembler.h @@ -22,6 +22,7 @@ #include "lldb/Core/EmulateInstruction.h" #include "lldb/Core/Opcode.h" #include "lldb/Core/PluginInterface.h" +#include "lldb/Interpreter/NamedOptionValue.h" namespace lldb_private { @@ -71,6 +72,12 @@ public: virtual void SetDescription (const char *) {}; // May be overridden in sub-classes that have descriptions. + lldb::OptionValueSP + ReadArray (FILE *in_file, Stream *out_stream, OptionValue::Type data_type); + + lldb::OptionValueSP + ReadDictionary (FILE *in_file, Stream *out_stream); + bool DumpEmulation (const ArchSpec &arch); diff --git a/lldb/include/lldb/Core/EmulateInstruction.h b/lldb/include/lldb/Core/EmulateInstruction.h index 12ac147ba85..590fa18fa8e 100644 --- a/lldb/include/lldb/Core/EmulateInstruction.h +++ b/lldb/include/lldb/Core/EmulateInstruction.h @@ -16,6 +16,7 @@ #include "lldb/Core/ArchSpec.h" #include "lldb/Core/PluginInterface.h" #include "lldb/Core/Opcode.h" +#include "lldb/Interpreter/NamedOptionValue.h" //---------------------------------------------------------------------- /// @class EmulateInstruction EmulateInstruction.h "lldb/Core/EmulateInstruction.h" @@ -418,7 +419,7 @@ public: EvaluateInstruction () = 0; virtual bool - TestEmulation (Stream *out_stream, FILE *test_file, ArchSpec &arch) = 0; + TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data) = 0; bool GetAdvancePC () { return m_advance_pc; } diff --git a/lldb/include/lldb/Interpreter/NamedOptionValue.h b/lldb/include/lldb/Interpreter/NamedOptionValue.h index 3204827d387..282cc21638e 100644 --- a/lldb/include/lldb/Interpreter/NamedOptionValue.h +++ b/lldb/include/lldb/Interpreter/NamedOptionValue.h @@ -109,6 +109,12 @@ namespace lldb_private { OptionValueDictionary * GetAsDictionaryValue(); + const char * + GetStringValue (); + + uint64_t + GetUInt64Value (); + protected: bool m_value_was_set; // This can be used to see if a value has been set // by a call to SetValueFromCString(). It is often @@ -116,6 +122,7 @@ namespace lldb_private { // the command line or as a setting, versus if we // just have the default value that was already // populated in the option value. + }; diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp index a8c807dd99a..0e0ea053ef0 100644 --- a/lldb/source/Core/Disassembler.cpp +++ b/lldb/source/Core/Disassembler.cpp @@ -21,7 +21,9 @@ #include "lldb/Core/EmulateInstruction.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Core/RegularExpression.h" #include "lldb/Core/Timer.h" +#include "lldb/Interpreter/NamedOptionValue.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" @@ -502,6 +504,187 @@ Instruction::DumpEmulation (const ArchSpec &arch) return false; } +OptionValueSP +Instruction::ReadArray (FILE *in_file, Stream *out_stream, OptionValue::Type data_type) +{ + bool done = false; + char buffer[1024]; + + OptionValueSP option_value_sp (new OptionValueArray (1u << data_type)); + + int idx = 0; + while (!done) + { + if (!fgets (buffer, 1023, in_file)) + { + out_stream->Printf ("Instruction::ReadArray: Erroe reading file (fgets).\n"); + option_value_sp.reset (); + return option_value_sp; + } + + std::string line (buffer); + + int len = line.size(); + if (line[len-1] == '\n') + { + line[len-1] = '\0'; + line.resize (len-1); + } + + if ((line.size() == 1) && line[0] == ']') + { + done = true; + line.clear(); + } + + if (line.size() > 0) + { + std::string value; + RegularExpression reg_exp ("^[ \t]*([^ \t]+)[ \t]*$"); + bool reg_exp_success = reg_exp.Execute (line.c_str(), 1); + if (reg_exp_success) + reg_exp.GetMatchAtIndex (line.c_str(), 1, value); + else + value = line; + + OptionValueSP data_value_sp; + switch (data_type) + { + case OptionValue::eTypeUInt64: + data_value_sp.reset (new OptionValueUInt64 (0, 0)); + data_value_sp->SetValueFromCString (value.c_str()); + break; + // Other types can be added later as needed. + default: + data_value_sp.reset (new OptionValueString (value.c_str(), "")); + break; + } + + option_value_sp->GetAsArrayValue()->InsertValue (idx, data_value_sp); + ++idx; + } + } + + return option_value_sp; +} + +OptionValueSP +Instruction::ReadDictionary (FILE *in_file, Stream *out_stream) +{ + bool done = false; + char buffer[1024]; + + OptionValueSP option_value_sp (new OptionValueDictionary()); + static ConstString encoding_key ("data_encoding"); + OptionValue::Type data_type = OptionValue::eTypeInvalid; + + + while (!done) + { + // Read the next line in the file + if (!fgets (buffer, 1023, in_file)) + { + out_stream->Printf ("Instruction::ReadDictionary: Error reading file (fgets).\n"); + option_value_sp.reset (); + return option_value_sp; + } + + // Check to see if the line contains the end-of-dictionary marker ("}") + std::string line (buffer); + + int len = line.size(); + if (line[len-1] == '\n') + { + line[len-1] = '\0'; + line.resize (len-1); + } + + if ((line.size() == 1) && (line[0] == '}')) + { + done = true; + line.clear(); + } + + // Try to find a key-value pair in the current line and add it to the dictionary. + if (line.size() > 0) + { + RegularExpression reg_exp ("^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$"); + bool reg_exp_success = reg_exp.Execute (line.c_str(), 2); + std::string key; + std::string value; + if (reg_exp_success) + { + reg_exp.GetMatchAtIndex (line.c_str(), 1, key); + reg_exp.GetMatchAtIndex (line.c_str(), 2, value); + } + else + { + out_stream->Printf ("Instruction::ReadDictionary: Failure executing regular expression.\n"); + option_value_sp.reset(); + return option_value_sp; + } + + ConstString const_key (key.c_str()); + // Check value to see if it's the start of an array or dictionary. + + lldb::OptionValueSP value_sp; + assert (value.empty() == false); + assert (key.empty() == false); + + if (value[0] == '{') + { + assert (value.size() == 1); + // value is a dictionary + value_sp = ReadDictionary (in_file, out_stream); + if (value_sp.get() == NULL) + { + option_value_sp.reset (); + return option_value_sp; + } + } + else if (value[0] == '[') + { + assert (value.size() == 1); + // value is an array + value_sp = ReadArray (in_file, out_stream, data_type); + if (value_sp.get() == NULL) + { + option_value_sp.reset (); + return option_value_sp; + } + // We've used the data_type to read an array; re-set the type to Invalid + data_type = OptionValue::eTypeInvalid; + } + else if ((value[0] == '0') && (value[1] == 'x')) + { + value_sp.reset (new OptionValueUInt64 (0, 0)); + value_sp->SetValueFromCString (value.c_str()); + } + else + { + int len = value.size(); + if ((value[0] == '"') && (value[len-1] == '"')) + value = value.substr (1, len-2); + value_sp.reset (new OptionValueString (value.c_str(), "")); + } + + + + if (const_key == encoding_key) + { + // A 'data_encoding=..." is NOT a normal key-value pair; it is meta-data indicating the + // data type of an upcoming array (usually the next bit of data to be read in). + if (strcmp (value.c_str(), "uint32_t") == 0) + data_type = OptionValue::eTypeUInt64; + } + else + option_value_sp->GetAsDictionaryValue()->SetValueForKey (const_key, value_sp, false); + } + } + + return option_value_sp; +} + bool Instruction::TestEmulation (Stream *out_stream, const char *file_name) { @@ -521,33 +704,63 @@ Instruction::TestEmulation (Stream *out_stream, const char *file_name) return false; } - ArchSpec arch; char buffer[256]; - if (!fgets (buffer,255, test_file)) // Read/skip first line of file, which should be a comment line (description). + if (!fgets (buffer, 255, test_file)) { - out_stream->Printf ("Instruction::TestEmulation: Read comment line failed."); + out_stream->Printf ("Instruction::TestEmulation: Error reading first line of test file.\n"); fclose (test_file); return false; } - SetDescription (buffer); - - if (fscanf (test_file, "%s", buffer) != 1) // Read the arch or arch-triple from the file + + if (strncmp (buffer, "InstructionEmulationState={", 27) != 0) + { + out_stream->Printf ("Instructin::TestEmulation: Test file does not contain emulation state dictionary\n"); + fclose (test_file); + return false; + } + + // Read all the test information from the test file into an OptionValueDictionary. + + OptionValueSP data_dictionary_sp (ReadDictionary (test_file, out_stream)); + if (data_dictionary_sp.get() == NULL) { - out_stream->Printf ("Instruction::TestEmulation: Read arch failed."); + out_stream->Printf ("Instruction::TestEmulation: Error reading Dictionary Object.\n"); fclose (test_file); return false; } + + fclose (test_file); + + OptionValueDictionary *data_dictionary = data_dictionary_sp->GetAsDictionaryValue(); + static ConstString description_key ("assembly_string"); + static ConstString triple_key ("triple"); + + OptionValueSP value_sp = data_dictionary->GetValueForKey (description_key); + + if (value_sp.get() == NULL) + { + out_stream->Printf ("Instruction::TestEmulation: Test file does not contain description string.\n"); + return false; + } + + SetDescription (value_sp->GetStringValue()); + + + value_sp = data_dictionary->GetValueForKey (triple_key); + if (value_sp.get() == NULL) + { + out_stream->Printf ("Instruction::TestEmulation: Test file does not contain triple.\n"); + return false; + } - const char *cptr = buffer; - arch.SetTriple (llvm::Triple (cptr)); + ArchSpec arch; + arch.SetTriple (llvm::Triple (value_sp->GetStringValue())); bool success = false; std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, NULL)); if (insn_emulator_ap.get()) - success = insn_emulator_ap->TestEmulation (out_stream, test_file, arch); + success = insn_emulator_ap->TestEmulation (out_stream, arch, data_dictionary); - fclose (test_file); - if (success) out_stream->Printf ("Emulation test succeeded."); else diff --git a/lldb/source/Interpreter/NamedOptionValue.cpp b/lldb/source/Interpreter/NamedOptionValue.cpp index 7c1284f8067..6b5dd7e3c0b 100644 --- a/lldb/source/Interpreter/NamedOptionValue.cpp +++ b/lldb/source/Interpreter/NamedOptionValue.cpp @@ -102,6 +102,21 @@ OptionValue::GetAsDictionaryValue () return NULL; } +const char * +OptionValue::GetStringValue () +{ + if (GetType () == OptionValue::eTypeString) + return static_cast<OptionValueString *>(this)->GetCurrentValue(); + return NULL; +} + +uint64_t +OptionValue::GetUInt64Value () +{ + if (GetType () == OptionValue::eTypeUInt64) + return static_cast<OptionValueUInt64 *>(this)->GetCurrentValue(); + return 0; +} //------------------------------------------------------------------------- // OptionValueCollection diff --git a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp index c4a6cfe0ee7..702ca061da3 100644 --- a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp +++ b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp @@ -13309,25 +13309,31 @@ EmulateInstructionARM::EvaluateInstruction () } bool -EmulateInstructionARM::TestEmulation (Stream *out_stream, FILE *test_file, ArchSpec &arch) +EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data) { - if (!test_file) + if (!test_data) { - out_stream->Printf ("TestEmulation: Missing test file.\n"); + out_stream->Printf ("TestEmulation: Missing test data.\n"); return false; } + + static ConstString opcode_key ("opcode"); + static ConstString before_key ("before_state"); + static ConstString after_key ("after_state"); + + OptionValueSP value_sp = test_data->GetValueForKey (opcode_key); uint32_t test_opcode; - if (fscanf (test_file, "%x", &test_opcode) != 1) + if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeUInt64)) { - out_stream->Printf ("Test Emulation: Error reading opcode from test file.\n"); + out_stream->Printf ("TestEmulation: Error reading opcode from test file.\n"); return false; } + test_opcode = value_sp->GetUInt64Value (); - char buffer[256]; - fgets (buffer, 255, test_file); // consume the newline after reading the opcode. - - SetAdvancePC (true); + // If the instruction emulation does not directly update the PC, advance the PC to the next instruction after + // performing the emulation. + SetAdvancePC (true); if (arch.GetTriple().getArch() == llvm::Triple::arm) { @@ -13345,60 +13351,41 @@ EmulateInstructionARM::TestEmulation (Stream *out_stream, FILE *test_file, ArchS } else { - out_stream->Printf ("Test Emulation: Invalid arch.\n"); + out_stream->Printf ("TestEmulation: Invalid arch.\n"); return false; } - EmulationStateARM before_state; EmulationStateARM after_state; - // Read Memory info & load into before_state - if (!fgets (buffer, 255, test_file)) + value_sp = test_data->GetValueForKey (before_key); + if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary)) { - out_stream->Printf ("Test Emulation: Error attempting to read from test file.\n"); + out_stream->Printf ("TestEmulation: Failed to find 'before' state.\n"); return false; } - - if (strncmp (buffer, "Memory-Begin", 12) != 0) + + OptionValueDictionary *state_dictionary = value_sp->GetAsDictionaryValue (); + if (!before_state.LoadStateFromDictionary (state_dictionary)) { - out_stream->Printf ("Test Emulation: Cannot find Memory-Begin in test file.\n"); + out_stream->Printf ("TestEmulation: Failed loading 'before' state.\n"); return false; } - bool done = false; - while (!done) + value_sp = test_data->GetValueForKey (after_key); + if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary)) { - if (fgets (buffer, 255, test_file)) - { - if (strncmp (buffer, "Memory-End", 10) == 0) - done = true; - else - { - uint32_t addr; - uint32_t value; - if (sscanf (buffer, "%x %x", &addr, &value) == 2) - before_state.StoreToPseudoAddress ((addr_t) addr, (uint64_t) value, 4); - else - { - out_stream->Printf ("Test Emulation: Error attempting to sscanf address/value pair.\n"); - return false; - } - } - } - else - { - out_stream->Printf ("Test Emulation: Error attemping to read test file.\n"); - return false; - } + out_stream->Printf ("TestEmulation: Failed to find 'after' state.\n"); + return false; } - - if (!EmulationStateARM::LoadRegisterStatesFromTestFile (test_file, before_state, after_state)) + + state_dictionary = value_sp->GetAsDictionaryValue (); + if (!after_state.LoadStateFromDictionary (state_dictionary)) { - out_stream->Printf ("Test Emulation: Error occurred while attempting to load the register data.\n"); + out_stream->Printf ("TestEmulation: Failed loading 'after' state.\n"); return false; } - + SetBaton ((void *) &before_state); SetCallbacks (&EmulationStateARM::ReadPseudoMemory, &EmulationStateARM::WritePseudoMemory, @@ -13408,11 +13395,14 @@ EmulateInstructionARM::TestEmulation (Stream *out_stream, FILE *test_file, ArchS bool success = EvaluateInstruction (); if (!success) { - out_stream->Printf ("Test Emulation: EvaluateInstruction() failed.\n"); + out_stream->Printf ("TestEmulation: EvaluateInstruction() failed.\n"); return false; } success = before_state.CompareState (after_state); + if (!success) + out_stream->Printf ("TestEmulation: 'before' and 'after' states do not match.\n"); + return success; } diff --git a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h index 49ade996186..faaae730680 100644 --- a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h +++ b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h @@ -12,6 +12,7 @@ #include "lldb/Core/EmulateInstruction.h" #include "lldb/Core/Error.h" +#include "lldb/Interpreter/NamedOptionValue.h" #include "Plugins/Process/Utility/ARMDefines.h" namespace lldb_private { @@ -150,7 +151,7 @@ public: EvaluateInstruction (); virtual bool - TestEmulation (Stream *out_stream, FILE *test_file, ArchSpec &arch); + TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data); uint32_t ArchVersion(); diff --git a/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp b/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp index c3f363fb9f7..7fb65a495be 100644 --- a/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp +++ b/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.cpp @@ -315,82 +315,6 @@ EmulationStateARM::WritePseudoRegister (void *baton, } bool -EmulationStateARM::LoadState (FILE *test_file) -{ - if (!test_file) - return false; - - uint32_t num_regs; - uint32_t value32; - uint64_t value64; - - /* Load general register state */ - if (fscanf (test_file, "%d", &num_regs) != 1) - return false; - - - for (int i = 0; i < num_regs; ++i) - { - if (fscanf (test_file, "%x", &value32) == 1) - { - if (i < 17) // We only have 17 general registers, but if for some reason the file contains more - // we need to read them all, to get to the next set of register values. - m_gpr[i] = value32; - } - else - return false; - } - - /* Load d register state */ - if (fscanf (test_file, "%d", &num_regs) != 1) - return false; - - for (int i = 0; i < num_regs; ++i) - { - if (fscanf (test_file, "%x", &value64) == 1) - { - if (i < 32) - { - if (i < 16) - m_vfp_regs.sd_regs[i].d_reg = value64; - else - m_vfp_regs.d_regs[i - 16] = value64; - } - } - else - return false; - } - - /* Load s register state */ - if (fscanf (test_file, "%d", &num_regs) != 1) - return false; - - for (int i = 0; i < num_regs; ++i) - { - if (fscanf (test_file, "%x", &value32) == 1) - m_vfp_regs.sd_regs[i / 2].s_reg[i % 2] = value32; - else - return false; - } - - return true; -} - -bool -EmulationStateARM::LoadRegisterStatesFromTestFile (FILE *test_file, - EmulationStateARM &before_state, - EmulationStateARM &after_state) -{ - if (test_file) - { - if (before_state.LoadState (test_file)) - return after_state.LoadState (test_file); - } - - return false; -} - -bool EmulationStateARM::CompareState (EmulationStateARM &other_state) { bool match = true; @@ -426,3 +350,93 @@ EmulationStateARM::CompareState (EmulationStateARM &other_state) return match; } + +bool +EmulationStateARM::LoadStateFromDictionary (OptionValueDictionary *test_data) +{ + static ConstString memory_key ("memory"); + static ConstString registers_key ("registers"); + + if (!test_data) + return false; + + OptionValueSP value_sp = test_data->GetValueForKey (memory_key); + + // Load memory, if present. + + if (value_sp.get() != NULL) + { + static ConstString address_key ("address"); + static ConstString data_key ("data"); + uint64_t start_address = 0; + + OptionValueDictionary *mem_dict = value_sp->GetAsDictionaryValue(); + value_sp = mem_dict->GetValueForKey (address_key); + if (value_sp.get() == NULL) + return false; + else + start_address = value_sp->GetUInt64Value (); + + value_sp = mem_dict->GetValueForKey (data_key); + OptionValueArray *mem_array = value_sp->GetAsArrayValue(); + if (!mem_array) + return false; + + uint32_t num_elts = mem_array->GetSize(); + uint32_t address = (uint32_t) start_address; + + for (int i = 0; i < num_elts; ++i) + { + value_sp = mem_array->GetValueAtIndex (i); + if (value_sp.get() == NULL) + return false; + uint64_t value = value_sp->GetUInt64Value(); + StoreToPseudoAddress (address, value, 4); + address = address + 4; + } + } + + value_sp = test_data->GetValueForKey (registers_key); + if (value_sp.get() == NULL) + return false; + + + // Load General Registers + + OptionValueDictionary *reg_dict = value_sp->GetAsDictionaryValue (); + + StreamString sstr; + for (int i = 0; i < 16; ++i) + { + sstr.Clear(); + sstr.Printf ("r%d", i); + ConstString reg_name (sstr.GetData()); + value_sp = reg_dict->GetValueForKey (reg_name); + if (value_sp.get() == NULL) + return false; + uint64_t reg_value = value_sp->GetUInt64Value(); + StorePseudoRegisterValue (dwarf_r0 + i, reg_value); + } + + static ConstString cpsr_name ("cpsr"); + value_sp = reg_dict->GetValueForKey (cpsr_name); + if (value_sp.get() == NULL) + return false; + 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.GetData()); + value_sp = reg_dict->GetValueForKey (reg_name); + if (value_sp.get() == NULL) + return false; + uint64_t reg_value = value_sp->GetUInt64Value(); + StorePseudoRegisterValue (dwarf_s0 + i, reg_value); + } + + return true; +} + diff --git a/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h b/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h index 8ddfbed4bb4..025ff9e3d94 100644 --- a/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h +++ b/lldb/source/Plugins/Instruction/ARM/EmulationStateARM.h @@ -14,6 +14,7 @@ #include "lldb/Core/EmulateInstruction.h" #include "lldb/Core/Opcode.h" +#include "lldb/Interpreter/NamedOptionValue.h" namespace lldb_private { @@ -47,11 +48,8 @@ public: LoadPseudoRegistersFromFrame (StackFrame &frame); bool - LoadState (FILE *test_file); - - static bool - LoadRegisterStatesFromTestFile (FILE *test_file, EmulationStateARM &before_state, EmulationStateARM &after_state); - + LoadStateFromDictionary (OptionValueDictionary *test_data); + bool CompareState (EmulationStateARM &other_state); |