diff --git a/InstructionSets/x86/Implementation/BCD.hpp b/InstructionSets/x86/Implementation/BCD.hpp index e8233c3eb..f8de9e6fd 100644 --- a/InstructionSets/x86/Implementation/BCD.hpp +++ b/InstructionSets/x86/Implementation/BCD.hpp @@ -16,7 +16,10 @@ namespace InstructionSet::x86::Primitive { template -void aaa(CPU::RegisterPair16 &ax, ContextT &context) { // P. 313 +void aaa( + CPU::RegisterPair16 &ax, + ContextT &context +) { // P. 313 /* IF ((AL AND 0FH) > 9) OR (AF = 1) THEN @@ -45,7 +48,11 @@ void aaa(CPU::RegisterPair16 &ax, ContextT &context) { // P. 313 } template -void aad(CPU::RegisterPair16 &ax, uint8_t imm, ContextT &context) { +void aad( + CPU::RegisterPair16 &ax, + uint8_t imm, + ContextT &context +) { /* tempAL ← AL; tempAH ← AH; @@ -62,7 +69,11 @@ void aad(CPU::RegisterPair16 &ax, uint8_t imm, ContextT &context) { } template -void aam(CPU::RegisterPair16 &ax, uint8_t imm, ContextT &context) { +void aam( + CPU::RegisterPair16 &ax, + uint8_t imm, + ContextT &context +) { /* tempAL ← AL; AH ← tempAL / imm8; (* imm8 is set to 0AH for the AAD mnemonic *) @@ -86,7 +97,10 @@ void aam(CPU::RegisterPair16 &ax, uint8_t imm, ContextT &context) { } template -void aas(CPU::RegisterPair16 &ax, ContextT &context) { +void aas( + CPU::RegisterPair16 &ax, + ContextT &context +) { /* IF ((AL AND 0FH) > 9) OR (AF = 1) THEN @@ -115,7 +129,10 @@ void aas(CPU::RegisterPair16 &ax, ContextT &context) { } template -void daa(uint8_t &al, ContextT &context) { +void daa( + uint8_t &al, + ContextT &context +) { /* (as modified by https://www.felixcloutier.com/x86/daa ...) @@ -167,7 +184,10 @@ void daa(uint8_t &al, ContextT &context) { } template -void das(uint8_t &al, ContextT &context) { +void das( + uint8_t &al, + ContextT &context +) { /* (as modified by https://www.felixcloutier.com/x86/daa ...) diff --git a/InstructionSets/x86/Implementation/PerformImplementation.hpp b/InstructionSets/x86/Implementation/PerformImplementation.hpp index 74c851a32..1090d4a17 100644 --- a/InstructionSets/x86/Implementation/PerformImplementation.hpp +++ b/InstructionSets/x86/Implementation/PerformImplementation.hpp @@ -165,13 +165,16 @@ template < // Guide to the below: // - // * use hard-coded register names where appropriate; + // * use hard-coded register names where appropriate, otherwise use the source_X() and destination_X() lambdas; // * return directly if there is definitely no possible write back to RAM; - // * otherwise use the source() and destination() lambdas, and break in order to allow a writeback if necessary. + // * break if there's a chance of writeback. switch(instruction.operation()) { default: assert(false); + case Operation::ESC: + case Operation::NOP: return; + case Operation::AAA: Primitive::aaa(context.registers.axp(), context); return; case Operation::AAD: Primitive::aad(context.registers.axp(), instruction.operand(), context); return; case Operation::AAM: Primitive::aam(context.registers.axp(), instruction.operand(), context); return; @@ -182,14 +185,15 @@ template < case Operation::CBW: Primitive::cbw(pair_low()); return; case Operation::CWD: Primitive::cwd(pair_high(), pair_low()); return; - case Operation::ESC: - case Operation::NOP: return; - case Operation::HLT: context.flow_controller.halt(); return; case Operation::WAIT: context.flow_controller.wait(); return; - case Operation::ADC: Primitive::add(destination_rmw(), source_r(), context); break; - case Operation::ADD: Primitive::add(destination_rmw(), source_r(), context); break; + case Operation::ADC: + Primitive::add(destination_rmw(), source_r(), context); + break; + case Operation::ADD: + Primitive::add(destination_rmw(), source_r(), context); + break; case Operation::SBB: Primitive::sub(destination_rmw(), source_r(), context); break; @@ -199,7 +203,9 @@ template < case Operation::CMP: Primitive::sub(destination_r(), source_r(), context); return; - case Operation::TEST: Primitive::test(destination_r(), source_r(), context); return; + case Operation::TEST: + Primitive::test(destination_r(), source_r(), context); + return; case Operation::MUL: Primitive::mul(pair_high(), pair_low(), source_r(), context); return; case Operation::IMUL_1: Primitive::imul(pair_high(), pair_low(), source_r(), context); return; @@ -238,8 +244,12 @@ template < case Operation::SAHF: Primitive::sahf(context.registers.ah(), context); return; case Operation::LAHF: Primitive::lahf(context.registers.ah(), context); return; - case Operation::LDS: if constexpr (data_size == DataSize::Word) Primitive::ld(instruction, destination_w(), context); return; - case Operation::LES: if constexpr (data_size == DataSize::Word) Primitive::ld(instruction, destination_w(), context); return; + case Operation::LDS: + if constexpr (data_size == DataSize::Word) Primitive::ld(instruction, destination_w(), context); + return; + case Operation::LES: + if constexpr (data_size == DataSize::Word) Primitive::ld(instruction, destination_w(), context); + return; case Operation::LEA: Primitive::lea(instruction, destination_w(), context); return; case Operation::MOV: Primitive::mov(destination_w(), source_r()); break; @@ -285,7 +295,8 @@ template < Primitive::setmo(destination_w(), context); break; } else { - // TODO. + // TODO: perform ENTER as of the 80186. + static_assert(int(Operation::SETMO) == int(Operation::ENTER)); } return; case Operation::SETMOC: @@ -297,12 +308,13 @@ template < } break; } else { - // TODO. + // TODO: perform BOUND as of the 80186. + static_assert(int(Operation::SETMOC) == int(Operation::BOUND)); } return; case Operation::OUT: Primitive::out(port(instruction.destination().source()), pair_low(), context); return; - case Operation::IN: Primitive::in(port(instruction.source().source()), pair_low(), context); return; + case Operation::IN: Primitive::in(port(instruction.source().source()), pair_low(), context); return; case Operation::XLAT: Primitive::xlat(instruction, context); return; @@ -372,10 +384,19 @@ template < // Write to memory if required to complete this operation. // - // TODO: can I eliminate this with some RAII magic? + // This is not currently handled via RAII because of the amount of context that would need to place onto the stack; + // instead code has been set up to make sure there is only at most one writeable target on loan for potential + // write back. I might flip-flop on this, especially if I can verify whether extra stack context is easily + // optimised out. context.memory.template write_back(); } +// +// Public function; just a trampoline into a version of perform templated on data and address size. +// +// Which, yes, means there's an outer switch leading to an inner switch, which could be reduced to one big switch. +// It'd be a substantial effort to find the most neat expression of that, I think, so it is not currently done. +// template < typename InstructionT, typename ContextT