From 1cd1bbd26c0a2eaa75fbbff065cd1ee09b3089ab Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 29 Oct 2023 16:19:10 -0400 Subject: [PATCH] Make a first pass of access types. --- .../Implementation/PerformImplementation.hpp | 93 ++++++++++++------- 1 file changed, 60 insertions(+), 33 deletions(-) diff --git a/InstructionSets/x86/Implementation/PerformImplementation.hpp b/InstructionSets/x86/Implementation/PerformImplementation.hpp index ae1458497..464eccfbb 100644 --- a/InstructionSets/x86/Implementation/PerformImplementation.hpp +++ b/InstructionSets/x86/Implementation/PerformImplementation.hpp @@ -1526,7 +1526,7 @@ template < // Establish source() and destination() shorthand to fetch data if necessary. IntT immediate; const auto source = [&]() -> IntT& { - return *resolve( + return *resolve( instruction, instruction.source().source(), instruction.source(), @@ -1535,8 +1535,33 @@ template < nullptr, &immediate); }; - const auto destination = [&]() -> IntT& { - return *resolve( + + // C++17, which this project targets at the time of writing, does not provide templatised lambdas. + // So the following division is in part a necessity. + // + // (though GCC offers C++20 syntax as an extension, and Clang seems to follow along, so maybe I'm overthinking) + const auto destination_r = [&]() -> IntT& { + return *resolve( + instruction, + instruction.destination().source(), + instruction.destination(), + registers, + memory, + nullptr, + &immediate); + }; + const auto destination_w = [&]() -> IntT& { + return *resolve( + instruction, + instruction.destination().source(), + instruction.destination(), + registers, + memory, + nullptr, + &immediate); + }; + const auto destination_rmw = [&]() -> IntT& { + return *resolve( instruction, instruction.destination().source(), instruction.destination(), @@ -1636,39 +1661,39 @@ template < case Operation::HLT: flow_controller.halt(); return; case Operation::WAIT: flow_controller.wait(); return; - case Operation::ADC: Primitive::add(destination(), source(), status); break; - case Operation::ADD: Primitive::add(destination(), source(), status); break; - case Operation::SBB: Primitive::sub(destination(), source(), status); break; - case Operation::SUB: Primitive::sub(destination(), source(), status); break; - case Operation::CMP: Primitive::sub(destination(), source(), status); break; - case Operation::TEST: Primitive::test(destination(), source(), status); break; + case Operation::ADC: Primitive::add(destination_rmw(), source(), status); break; + case Operation::ADD: Primitive::add(destination_rmw(), source(), status); break; + case Operation::SBB: Primitive::sub(destination_rmw(), source(), status); break; + case Operation::SUB: Primitive::sub(destination_rmw(), source(), status); break; + case Operation::CMP: Primitive::sub(destination_rmw(), source(), status); break; + case Operation::TEST: Primitive::test(destination_r(), source(), status); return; case Operation::MUL: Primitive::mul(pair_high(), pair_low(), source(), status); return; case Operation::IMUL_1: Primitive::imul(pair_high(), pair_low(), source(), status); return; case Operation::DIV: Primitive::div(pair_high(), pair_low(), source(), flow_controller); return; case Operation::IDIV: Primitive::idiv(pair_high(), pair_low(), source(), flow_controller); return; - case Operation::INC: Primitive::inc(destination(), status); break; - case Operation::DEC: Primitive::dec(destination(), status); break; + case Operation::INC: Primitive::inc(destination_rmw(), status); break; + case Operation::DEC: Primitive::dec(destination_rmw(), status); break; - case Operation::AND: Primitive::and_(destination(), source(), status); break; - case Operation::OR: Primitive::or_(destination(), source(), status); break; - case Operation::XOR: Primitive::xor_(destination(), source(), status); break; - case Operation::NEG: Primitive::neg(source(), status); break; - case Operation::NOT: Primitive::not_(source()); break; + case Operation::AND: Primitive::and_(destination_rmw(), source(), status); break; + case Operation::OR: Primitive::or_(destination_rmw(), source(), status); break; + case Operation::XOR: Primitive::xor_(destination_rmw(), source(), status); break; + case Operation::NEG: Primitive::neg(source(), status); break; // TODO: should be a destination. + case Operation::NOT: Primitive::not_(source()); break; // TODO: should be a destination. case Operation::CALLrel: Primitive::call_relative(instruction.displacement(), registers, flow_controller); return; case Operation::CALLabs: - Primitive::call_absolute(destination(), flow_controller); + Primitive::call_absolute(destination_r(), flow_controller); return; case Operation::CALLfar: Primitive::call_far(instruction, flow_controller, registers, memory); return; case Operation::JMPrel: jcc(true); return; - case Operation::JMPabs: Primitive::jump_absolute(destination(), flow_controller); return; + case Operation::JMPabs: Primitive::jump_absolute(destination_r(), flow_controller); return; case Operation::JMPfar: Primitive::jump_far(instruction, flow_controller, registers, memory); return; case Operation::JCXZ: jcc(!eCX()); return; @@ -1686,11 +1711,11 @@ template < case Operation::SAHF: Primitive::sahf(registers.ah(), status); return; case Operation::LAHF: Primitive::lahf(registers.ah(), status); return; - case Operation::LDS: if constexpr (data_size == DataSize::Word) Primitive::ld(instruction, destination(), memory, registers); return; - case Operation::LES: if constexpr (data_size == DataSize::Word) Primitive::ld(instruction, destination(), memory, registers); return; + case Operation::LDS: if constexpr (data_size == DataSize::Word) Primitive::ld(instruction, destination_w(), memory, registers); return; + case Operation::LES: if constexpr (data_size == DataSize::Word) Primitive::ld(instruction, destination_w(), memory, registers); return; - case Operation::LEA: Primitive::lea(instruction, destination(), memory, registers); return; - case Operation::MOV: Primitive::mov(destination(), source()); return; + case Operation::LEA: Primitive::lea(instruction, destination_w(), memory, registers); return; + case Operation::MOV: Primitive::mov(destination_w(), source()); break; case Operation::JO: jcc(status.condition()); return; case Operation::JNO: jcc(!status.condition()); return; @@ -1709,13 +1734,13 @@ template < case Operation::JLE: jcc(status.condition()); return; case Operation::JNLE: jcc(!status.condition()); return; - case Operation::RCL: Primitive::rcl(destination(), shift_count(), status); break; - case Operation::RCR: Primitive::rcr(destination(), shift_count(), status); break; - case Operation::ROL: Primitive::rol(destination(), shift_count(), status); break; - case Operation::ROR: Primitive::ror(destination(), shift_count(), status); break; - case Operation::SAL: Primitive::sal(destination(), shift_count(), status); break; - case Operation::SAR: Primitive::sar(destination(), shift_count(), status); break; - case Operation::SHR: Primitive::shr(destination(), shift_count(), status); break; + case Operation::RCL: Primitive::rcl(destination_rmw(), shift_count(), status); break; + case Operation::RCR: Primitive::rcr(destination_rmw(), shift_count(), status); break; + case Operation::ROL: Primitive::rol(destination_rmw(), shift_count(), status); break; + case Operation::ROR: Primitive::ror(destination_rmw(), shift_count(), status); break; + case Operation::SAL: Primitive::sal(destination_rmw(), shift_count(), status); break; + case Operation::SAR: Primitive::sar(destination_rmw(), shift_count(), status); break; + case Operation::SHR: Primitive::shr(destination_rmw(), shift_count(), status); break; case Operation::CLC: Primitive::clc(status); return; case Operation::CLD: Primitive::cld(status); return; @@ -1725,19 +1750,21 @@ template < case Operation::STI: Primitive::sti(status); return; case Operation::CMC: Primitive::cmc(status); return; - case Operation::XCHG: Primitive::xchg(destination(), source()); return; + case Operation::XCHG: Primitive::xchg(destination_rmw(), source()); break; - case Operation::SALC: Primitive::salc(registers.al(), status); return; + case Operation::SALC: Primitive::salc(registers.al(), status); return; case Operation::SETMO: if constexpr (model == Model::i8086) { - Primitive::setmo(destination(), status); + Primitive::setmo(destination_w(), status); + break; } else { // TODO. } return; case Operation::SETMOC: if constexpr (model == Model::i8086) { - Primitive::setmoc(destination(), registers.cl(), status); + Primitive::setmoc(destination_w(), registers.cl(), status); + break; } else { // TODO. }