From f083eab0116e758fcbfafe671c608ca4b7e9b358 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Tue, 10 Oct 2023 15:57:33 -0400 Subject: [PATCH] Implement INC, DEC. --- .../Implementation/PerformImplementation.hpp | 112 ++++++++++++++++++ OSBindings/Mac/Clock SignalTests/8088Tests.mm | 22 +++- 2 files changed, 129 insertions(+), 5 deletions(-) diff --git a/InstructionSets/x86/Implementation/PerformImplementation.hpp b/InstructionSets/x86/Implementation/PerformImplementation.hpp index 2f224fd4d..ba58f397d 100644 --- a/InstructionSets/x86/Implementation/PerformImplementation.hpp +++ b/InstructionSets/x86/Implementation/PerformImplementation.hpp @@ -533,6 +533,43 @@ void imul(IntT &destination_high, IntT &destination_low, IntT source, Status &st template void div(IntT &destination_high, IntT &destination_low, IntT source, FlowControllerT &flow_controller) { + /* + IF SRC = 0 + THEN #DE; (* divide error *) + FI; + IF OperandSize = 8 (* word/byte operation *) + THEN + temp ← AX / SRC; + IF temp > FFH + THEN #DE; (* divide error *) ; + ELSE + AL ← temp; + AH ← AX MOD SRC; + FI; + ELSE + IF OperandSize = 16 (* doubleword/word operation *) + THEN + temp ← DX:AX / SRC; + IF temp > FFFFH + THEN #DE; (* divide error *) ; + ELSE + AX ← temp; + DX ← DX:AX MOD SRC; + FI; + ELSE (* quadword/doubleword operation *) + temp ← EDX:EAX / SRC; + IF temp > FFFFFFFFH + THEN #DE; (* divide error *) ; + ELSE + EAX ← temp; + EDX ← EDX:EAX MOD SRC; + FI; + FI; + FI; + */ + /* + The CF, OF, SF, ZF, AF, and PF flags are undefined. + */ if(!source) { flow_controller.interrupt(Interrupt::DivideError); return; @@ -552,6 +589,43 @@ void div(IntT &destination_high, IntT &destination_low, IntT source, FlowControl template void idiv(IntT &destination_high, IntT &destination_low, IntT source, FlowControllerT &flow_controller) { + /* + IF SRC = 0 + THEN #DE; (* divide error *) + FI; + IF OperandSize = 8 (* word/byte operation *) + THEN + temp ← AX / SRC; (* signed division *) + IF (temp > 7FH) OR (temp < 80H) (* if a positive result is greater than 7FH or a negative result is less than 80H *) + THEN #DE; (* divide error *) ; + ELSE + AL ← temp; + AH ← AX MOD SRC; + FI; + ELSE + IF OperandSize = 16 (* doubleword/word operation *) + THEN + temp ← DX:AX / SRC; (* signed division *) + IF (temp > 7FFFH) OR (temp < 8000H) (* if a positive result is greater than 7FFFH or a negative result is less than 8000H *) + THEN #DE; (* divide error *) ; + ELSE + AX ← temp; + DX ← DX:AX MOD SRC; + FI; + ELSE (* quadword/doubleword operation *) + temp ← EDX:EAX / SRC; (* signed division *) + IF (temp > 7FFFFFFFH) OR (temp < 80000000H) (* if a positive result is greater than 7FFFFFFFH or a negative result is less than 80000000H *) + THEN #DE; (* divide error *) ; + ELSE + EAX ← temp; + EDX ← EDX:EAX MOD SRC; + FI; + FI; + FI; + */ + /* + The CF, OF, SF, ZF, AF, and PF flags are undefined. + */ if(!source) { flow_controller.interrupt(Interrupt::DivideError); return; @@ -570,6 +644,41 @@ void idiv(IntT &destination_high, IntT &destination_low, IntT source, FlowContro destination_high = dividend % sIntT(source); } +template +void inc(IntT &destination, Status &status) { + /* + DEST ← DEST + 1; + */ + /* + The CF flag is not affected. + The OF, SF, ZF, AF, and PF flags are set according to the result. + */ + ++destination; + + status.overflow = destination == top_bit(); + status.sign = destination & top_bit(); + status.zero = status.parity = destination; + status.auxiliary_carry = ((destination - 1) ^ destination) & 0x10; +} + +template +void dec(IntT &destination, Status &status) { + /* + DEST ← DEST - 1; + */ + /* + The CF flag is not affected. + The OF, SF, ZF, AF, and PF flags are set according to the result. + */ + status.overflow = destination == top_bit(); + + --destination; + + status.sign = destination & top_bit(); + status.zero = status.parity = destination; + status.auxiliary_carry = ((destination + 1) ^ destination) & 0x10; +} + template void and_(IntT &destination, IntT source, Status &status) { /* @@ -776,6 +885,9 @@ template < } return; + case Operation::INC: Primitive::inc(destination(), status); break; + case Operation::DEC: Primitive::dec(destination(), status); break; + case Operation::AND: Primitive::and_(destination(), source(), status); break; case Operation::CALLrel: diff --git a/OSBindings/Mac/Clock SignalTests/8088Tests.mm b/OSBindings/Mac/Clock SignalTests/8088Tests.mm index 0fdfd263c..33da0b107 100644 --- a/OSBindings/Mac/Clock SignalTests/8088Tests.mm +++ b/OSBindings/Mac/Clock SignalTests/8088Tests.mm @@ -278,7 +278,7 @@ struct FailedExecution { - (NSArray *)testFiles { NSString *path = [NSString stringWithUTF8String:TestSuiteHome]; NSSet *allowList = [NSSet setWithArray:@[ - @"37.json.gz", // AAA +/* @"37.json.gz", // AAA @"3F.json.gz", // AAS @"D4.json.gz", // AAM @"D5.json.gz", // AAD @@ -320,14 +320,25 @@ struct FailedExecution { @"F6.6.json.gz", @"F7.6.json.gz", // IDIV - @"F6.7.json.gz", @"F7.7.json.gz", + @"F6.7.json.gz", @"F7.7.json.gz",*/ + + // INC + @"40.json.gz", @"41.json.gz", @"42.json.gz", @"43.json.gz", + @"44.json.gz", @"45.json.gz", @"46.json.gz", @"47.json.gz", + @"FE.0.json.gz", + @"FF.0.json.gz", + + // DEC + @"48.json.gz", @"49.json.gz", @"4A.json.gz", @"4B.json.gz", + @"4C.json.gz", @"4D.json.gz", @"4E.json.gz", @"4F.json.gz", + @"FE.1.json.gz", + @"FF.1.json.gz", - // TODO: INC, DEC // TODO: IN, OUT // TODO: JO, JNO, JB, JNB, JZ, JNZ, JBE, JNBE, JS, JNS, JP, JNP, JL, JNL, JLE, JNLE, // CALL - @"E8.json.gz", @"FF.2.json.gz", +/* @"E8.json.gz", @"FF.2.json.gz", @"9A.json.gz", @"FF.3.json.gz", // TODO: IRET @@ -364,11 +375,12 @@ struct FailedExecution { @"FD.json.gz", // STD @"FB.json.gz", // STI @"F5.json.gz", // CMC +*/ // TODO: CMP, TEST // TODO: XCHG, XLAT // TODO: SALC, SETMO, SETMOC - + ]]; NSSet *ignoreList = nil;