From 1a0f848b21c5518e22bd18c7aa20c4abea8fd4b1 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Fri, 13 Oct 2023 14:44:22 -0400 Subject: [PATCH] Implement RCL. --- .../Implementation/PerformImplementation.hpp | 61 +++++++++++++++++++ OSBindings/Mac/Clock SignalTests/8088Tests.mm | 14 +++-- 2 files changed, 70 insertions(+), 5 deletions(-) diff --git a/InstructionSets/x86/Implementation/PerformImplementation.hpp b/InstructionSets/x86/Implementation/PerformImplementation.hpp index 74df69705..88d129436 100644 --- a/InstructionSets/x86/Implementation/PerformImplementation.hpp +++ b/InstructionSets/x86/Implementation/PerformImplementation.hpp @@ -923,6 +923,54 @@ void setmoc(IntT &destination, uint8_t cl, Status &status) { if(cl) setmo(destination, status); } +template +inline void rcl(IntT &destination, uint8_t count, Status &status) { + /* + (* RCL and RCR instructions *) + SIZE ← OperandSize + CASE (determine count) OF + SIZE = 8: tempCOUNT ← (COUNT AND 1FH) MOD 9; + SIZE = 16: tempCOUNT ← (COUNT AND 1FH) MOD 17; + SIZE = 32: tempCOUNT ← COUNT AND 1FH; + ESAC; + */ + if constexpr (model != Model::i8086) { + count &= 0x1f; + } + auto temp_count = count % (Numeric::bit_size() + 1); + + /* + (* RCL instruction operation *) + WHILE (tempCOUNT ≠ 0) + DO + tempCF ← MSB(DEST); + DEST ← (DEST * 2) + CF; + CF ← tempCF; + tempCOUNT ← tempCOUNT – 1; + OD; + ELIHW; + IF COUNT = 1 + THEN OF ← MSB(DEST) XOR CF; + ELSE OF is undefined; + FI; + */ + /* + The CF flag contains the value of the bit shifted into it. + The OF flag is affected only for single- bit rotates (see “Description” above); + it is undefined for multi-bit rotates. The SF, ZF, AF, and PF flags are not affected. + */ + auto carry = status.carry_bit(); + while(temp_count--) { + const IntT temp_carry = (destination >> (Numeric::bit_size() - 1)) & 1; + destination = (destination << 1) | carry; + carry = temp_carry; + } + status.set_from(carry); + status.set_from( + ((destination >> (Numeric::bit_size() - 1)) & 1) ^ carry + ); +} + } template < @@ -976,6 +1024,14 @@ template < flow_controller); }; + const auto shift_count = [&]() -> uint8_t { + switch(instruction.source().template source()) { + case Source::None: return 1; + case Source::Immediate: return uint8_t(instruction.operand()); + default: return registers.cl(); + } + }; + // Some instructions use a pair of registers as an extended accumulator — DX:AX or EDX:EAX. // The two following return the high and low parts of that pair; they also work in Byte mode to return AH:AL, // i.e. AX split into high and low parts. @@ -1075,6 +1131,8 @@ 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::CLC: Primitive::clc(status); return; case Operation::CLD: Primitive::cld(status); return; case Operation::CLI: Primitive::cli(status); return; @@ -1126,6 +1184,9 @@ template < // Dispatch to a function just like this that is specialised on data size. // Fetching will occur in that specialised function, per the overlapping // meaning of register names. + + // TODO: incorporate and propagate address size. + switch(instruction.operation_size()) { case DataSize::Byte: perform(instruction, status, flow_controller, registers, memory, io); diff --git a/OSBindings/Mac/Clock SignalTests/8088Tests.mm b/OSBindings/Mac/Clock SignalTests/8088Tests.mm index bc61250b5..58e8db2d1 100644 --- a/OSBindings/Mac/Clock SignalTests/8088Tests.mm +++ b/OSBindings/Mac/Clock SignalTests/8088Tests.mm @@ -415,10 +415,16 @@ struct FailedExecution { // NOP @"90.json.gz", +*/ // TODO: POP, POPF, PUSH, PUSHF - // TODO: RCL, RCR, ROL, ROR, SAL, SAR, SHR + // TODO: RCR, ROL, ROR, SAL, SAR, SHR + // RCL + @"D0.2.json.gz", @"D2.2.json.gz", + @"D1.2.json.gz", @"D3.2.json.gz", + +/* @"F8.json.gz", // CLC @"FC.json.gz", // CLD @"FA.json.gz", // CLI @@ -441,11 +447,9 @@ struct FailedExecution { @"86.json.gz", @"87.json.gz", @"91.json.gz", @"92.json.gz", @"93.json.gz", @"94.json.gz", @"95.json.gz", @"96.json.gz", @"97.json.gz", -*/ - @"D7.json.gz", // XLAT -/* - @"D6.json.gz", // SALC + @"D7.json.gz", // XLAT + @"D6.json.gz", // SALC @"D0.6.json.gz", @"D1.6.json.gz", // SETMO @"D2.6.json.gz", @"D3.6.json.gz", // SETMOC */