diff --git a/InstructionSets/x86/Implementation/PerformImplementation.hpp b/InstructionSets/x86/Implementation/PerformImplementation.hpp index dafe8b821..b66369c8e 100644 --- a/InstructionSets/x86/Implementation/PerformImplementation.hpp +++ b/InstructionSets/x86/Implementation/PerformImplementation.hpp @@ -923,7 +923,7 @@ void setmoc(IntT &destination, uint8_t cl, Status &status) { if(cl) setmo(destination, status); } -template +template inline void rcl(IntT &destination, uint8_t count, Status &status) { /* (* RCL and RCR instructions *) @@ -954,7 +954,7 @@ inline void rcl(IntT &destination, uint8_t count, Status &status) { 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 temp_count = count % (Numeric::bit_size() + 1); + const auto temp_count = count % (Numeric::bit_size() + 1); auto carry = status.carry_bit(); switch(temp_count) { case 0: break; @@ -979,6 +979,49 @@ inline void rcl(IntT &destination, uint8_t count, Status &status) { ); } +template +inline void rcr(IntT &destination, uint8_t count, Status &status) { + /* + (* RCR instruction operation *) + IF COUNT = 1 + THEN OF ← MSB(DEST) XOR CF; + ELSE OF is undefined; + FI; + WHILE (tempCOUNT ≠ 0) + DO + tempCF ← LSB(SRC); + DEST ← (DEST / 2) + (CF * 2SIZE); + CF ← tempCF; + tempCOUNT ← tempCOUNT – 1; + OD; + */ + auto carry = status.carry_bit(); + status.set_from( + ((destination >> (Numeric::bit_size() - 1)) & 1) ^ carry + ); + + const auto temp_count = count % (Numeric::bit_size() + 1); + switch(temp_count) { + case 0: break; + case Numeric::bit_size(): { + const IntT temp_carry = destination & Numeric::top_bit(); + destination = (destination << 1) | carry; + carry = temp_carry; + } break; + default: { + const IntT temp_carry = destination & (1 << (temp_count - 1)); + destination = + (destination >> temp_count) | + (destination << (Numeric::bit_size() + 1 - temp_count)) | + (carry << (Numeric::bit_size() - temp_count)); + carry = temp_carry; + } break; + } + + status.set_from(carry); +} + + } template < @@ -1140,7 +1183,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::RCL: Primitive::rcl(destination(), shift_count(), status); break; + case Operation::RCR: Primitive::rcr(destination(), shift_count(), status); break; case Operation::CLC: Primitive::clc(status); return; case Operation::CLD: Primitive::cld(status); return; diff --git a/OSBindings/Mac/Clock SignalTests/8088Tests.mm b/OSBindings/Mac/Clock SignalTests/8088Tests.mm index 58e8db2d1..0d78ca6aa 100644 --- a/OSBindings/Mac/Clock SignalTests/8088Tests.mm +++ b/OSBindings/Mac/Clock SignalTests/8088Tests.mm @@ -418,11 +418,15 @@ struct FailedExecution { */ // TODO: POP, POPF, PUSH, PUSHF - // TODO: RCR, ROL, ROR, SAL, SAR, SHR + // TODO: ROL, ROR, SAL, SAR, SHR // RCL - @"D0.2.json.gz", @"D2.2.json.gz", - @"D1.2.json.gz", @"D3.2.json.gz", +// @"D0.2.json.gz", @"D2.2.json.gz", +// @"D1.2.json.gz", @"D3.2.json.gz", + + // RCR + @"D0.3.json.gz", @"D2.3.json.gz", + @"D1.3.json.gz", @"D3.3.json.gz", /* @"F8.json.gz", // CLC