summaryrefslogtreecommitdiff
path: root/emulate/emulator.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'emulate/emulator.hpp')
-rw-r--r--emulate/emulator.hpp172
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")
{}
};