From 90c2782d0b78d64a19e7236c7dd6d8cc7a2e8396 Mon Sep 17 00:00:00 2001 From: Dennis Brentjes Date: Sat, 16 Jun 2018 19:26:59 +0200 Subject: Rewrites the binary operation function to have code reuse between unary and binary operations. --- emulate/emulator.hpp | 172 +++++---------------------------------------------- 1 file changed, 17 insertions(+), 155 deletions(-) (limited to 'emulate/emulator.hpp') 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 get_first_operand(_DInst inst); + + ValueType get_second_operand(_DInst inst, RefValueType dest); + template void handle_binary(_DInst inst) { - std::unique_ptr dest; - ValueType src; - - { - _Operand dest_op = inst.ops[0]; - - switch(dest_op.type) { - case O_REG: { - dest = std::make_unique(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(*reinterpret_cast(&memory[memory_offset])); - break; - } - case 16: { - dest = std::make_unique(*reinterpret_cast(&memory[memory_offset])); - break; - } - case 32: { - dest = std::make_unique(*reinterpret_cast(&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(*reinterpret_cast(&memory[segment_offset + inst.disp])); - break; - } - case 16: { - dest = std::make_unique(*reinterpret_cast(&memory[segment_offset + inst.disp])); - break; - } - case 32: { - dest = std::make_unique(*reinterpret_cast(&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(0); - } else { - src = *reinterpret_cast(&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(0); - } else { - src = *reinterpret_cast(&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(0); - } else { - src = *reinterpret_cast(&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(&memory[memory_offset]); - break; - } - case 16: { - src = *reinterpret_cast(&memory[memory_offset]); - break; - } - case 32: { - src = *reinterpret_cast(&memory[memory_offset]); - break; - } - default: { - throw UnhandledInstruction(); - } - } - break; - } - default: { - throw UnhandledInstruction(); - } - } - } + std::unique_ptr dest = get_first_operand(inst); + ValueType src = get_second_operand(inst, *dest); boost::apply_visitor(O(cpu), *dest, src); } + template + void handle_unary(_DInst inst) { + std::unique_ptr 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") {} }; -- cgit v1.2.3-70-g09d2