diff options
Diffstat (limited to 'emulate/emulator.hpp')
| -rw-r--r-- | emulate/emulator.hpp | 172 |
1 files changed, 17 insertions, 155 deletions
diff --git a/emulate/emulator.hpp b/emulate/emulator.hpp index 025c823..eb48ee8 100644 --- a/emulate/emulator.hpp +++ b/emulate/emulator.hpp @@ -82,166 +82,25 @@ public: {} }; + std::unique_ptr<RefValueType> get_first_operand(_DInst inst); + + ValueType get_second_operand(_DInst inst, RefValueType dest); + template <typename O> void handle_binary(_DInst inst) { - std::unique_ptr<RefValueType> dest; - ValueType src; - - { - _Operand dest_op = inst.ops[0]; - - switch(dest_op.type) { - case O_REG: { - dest = std::make_unique<RefValueType>(register_getters.at(dest_op.index)()); - break; - } - case O_MEM: { - throw UnhandledInstruction(); - break; - } - case O_SMEM: { - auto segment = register_getters.at(SEGMENT_GET(inst.segment))(); - auto segment_offset = ldt[boost::apply_visitor(return_visitor(), segment) >> 3].offset; - auto register_contents = register_getters.at(dest_op.index)(); - int32_t offset = boost::apply_visitor(return_visitor(), register_contents) + inst.disp; - std::cout << segment_offset << std::endl << offset << std::endl << inst.disp << std::endl; - std::cout << segment_offset + offset + inst.disp << std::endl; - auto memory_offset = segment_offset + offset + inst.disp; - switch(dest_op.size) { - case 8: { - dest = std::make_unique<RefValueType>(*reinterpret_cast<uint8_t*>(&memory[memory_offset])); - break; - } - case 16: { - dest = std::make_unique<RefValueType>(*reinterpret_cast<uint16_t*>(&memory[memory_offset])); - break; - } - case 32: { - dest = std::make_unique<RefValueType>(*reinterpret_cast<uint32_t*>(&memory[memory_offset])); - break; - } - default: { - throw UnhandledInstruction(); - } - } - - break; - } - case O_DISP: { - auto segment = register_getters.at(SEGMENT_GET(inst.segment))(); - auto segment_offset = ldt[boost::apply_visitor(return_visitor(), segment) >> 3].offset; - switch(dest_op.size) { - case 8: { - dest = std::make_unique<RefValueType>(*reinterpret_cast<uint8_t*>(&memory[segment_offset + inst.disp])); - break; - } - case 16: { - dest = std::make_unique<RefValueType>(*reinterpret_cast<uint16_t*>(&memory[segment_offset + inst.disp])); - break; - } - case 32: { - dest = std::make_unique<RefValueType>(*reinterpret_cast<uint32_t*>(&memory[segment_offset + inst.disp])); - break; - } - default: { - throw UnhandledInstruction(); - } - } - break; - } - default: { - throw UnhandledInstruction(); - } - } - } - - { - _Operand src_op = inst.ops[1]; - - switch(src_op.type) { - case O_REG: { - auto x = register_getters.at(src_op.index)(); - src = boost::apply_visitor(to_target_type(), *dest, x); - break; - } - case O_IMM: { - //Do not rely on the imm size as we need to sign extend to dest size. - src = extract_immediate_of_size(boost::apply_visitor(dest_size(), *dest), inst); - break; - } - case O_DISP: { - auto segment = register_getters.at(SEGMENT_GET(inst.segment))(); - auto segment_offset = ldt[boost::apply_visitor(return_visitor(), segment) >> 3].offset; - switch(boost::apply_visitor(dest_size(), *dest)) { - case 8: { - if(segment_offset + inst.disp > memory.size()) { - std::cerr << "Warning reading outside of memory region" << std::endl; - src = static_cast<uint8_t>(0); - } else { - src = *reinterpret_cast<uint8_t*>(&memory[segment_offset + inst.disp]); - } - break; - } - case 16: { - if(segment_offset + inst.disp + 1 > memory.size()) { - std::cerr << "Warning reading outside of memory region" << std::endl; - src = static_cast<uint16_t>(0); - } else { - src = *reinterpret_cast<uint16_t*>(&memory[segment_offset + inst.disp]); - } - break; - } - case 32: { - if(segment_offset + inst.disp + 3 > memory.size()) { - std::cerr << "Warning reading outside of memory region" << std::endl; - src = static_cast<uint32_t>(0); - } else { - src = *reinterpret_cast<uint32_t*>(&memory[segment_offset + inst.disp]); - } - break; - } - default: { - throw UnhandledInstruction(); - } - } - break; - } - case O_SMEM: { - auto segment = register_getters.at(SEGMENT_GET(inst.segment))(); - auto segment_offset = ldt[boost::apply_visitor(return_visitor(), segment) >> 3].offset; - auto register_contents = register_getters.at(src_op.index)(); - int32_t offset = boost::apply_visitor(return_visitor(), register_contents) + inst.disp; - std::cout << segment_offset << std::endl << offset << std::endl << inst.disp << std::endl; - std::cout << segment_offset + offset + inst.disp << std::endl; - auto memory_offset = segment_offset + offset + inst.disp; - switch(src_op.size) { - case 8: { - src = *reinterpret_cast<uint8_t*>(&memory[memory_offset]); - break; - } - case 16: { - src = *reinterpret_cast<uint16_t*>(&memory[memory_offset]); - break; - } - case 32: { - src = *reinterpret_cast<uint32_t*>(&memory[memory_offset]); - break; - } - default: { - throw UnhandledInstruction(); - } - } - break; - } - default: { - throw UnhandledInstruction(); - } - } - } + std::unique_ptr<RefValueType> dest = get_first_operand(inst); + ValueType src = get_second_operand(inst, *dest); boost::apply_visitor(O(cpu), *dest, src); } + template<typename O> + void handle_unary(_DInst inst) { + std::unique_ptr<RefValueType> op = get_first_operand(inst); + + boost::apply_visitor(O(cpu), *op); + } + uint32_t get_jmp_target(_DInst inst); void handle_I_JMP (_DInst inst); @@ -259,6 +118,9 @@ public: void handle_I_ADD (_DInst inst); void handle_I_PUSH(_DInst inst); void handle_I_CLD (_DInst inst); + void handle_I_SCAS(_DInst inst); + void handle_I_LEA (_DInst inst); + void handle_I_DEC (_DInst inst); void int_0x21(); void int_0x31(); @@ -277,7 +139,7 @@ public: struct UnrecognizedInstruction : public std::runtime_error { UnrecognizedInstruction() - : std::runtime_error("Encountered unhandled instruction") + : std::runtime_error("Encountered unrecognized instruction") {} }; |
