From d0a9b5cb81db93cb0d36710dab7d9bbdf1d52e8b Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Tue, 10 Oct 2023 22:09:10 -0400 Subject: [PATCH] Implement NEG, NOT. --- .../Implementation/PerformImplementation.hpp | 36 +++++++++++++++++++ InstructionSets/x86/Instruction.hpp | 4 +-- OSBindings/Mac/Clock SignalTests/8088Tests.mm | 10 ++++-- 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/InstructionSets/x86/Implementation/PerformImplementation.hpp b/InstructionSets/x86/Implementation/PerformImplementation.hpp index dfee72060..55f5582b5 100644 --- a/InstructionSets/x86/Implementation/PerformImplementation.hpp +++ b/InstructionSets/x86/Implementation/PerformImplementation.hpp @@ -749,6 +749,40 @@ void xor_(IntT &destination, IntT source, Status &status) { status.zero = status.parity = destination; } +template +void neg(IntT &destination, Status &status) { + /* + IF DEST = 0 + THEN CF ← 0 + ELSE CF ← 1; + FI; + DEST ← –(DEST) + */ + /* + The CF flag cleared to 0 if the source operand is 0; otherwise it is set to 1. + The OF, SF, ZF, AF, and PF flags are set according to the result. + */ + status.auxiliary_carry = Numeric::carried_in<4>(IntT(0), destination, IntT(-destination)); + + destination = -destination; + + status.carry = destination; + status.overflow = destination == top_bit(); + status.sign = destination & top_bit(); + status.zero = status.parity = destination; +} + +template +void not_(IntT &destination) { + /* + DEST ← NOT DEST; + */ + /* + Flags affected: none. + */ + destination = ~destination; +} + template inline void call_relative(IntT offset, RegistersT ®isters, FlowControllerT &flow_controller) { flow_controller.call(registers.ip() + offset); @@ -944,6 +978,8 @@ template < 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::CALLrel: Primitive::call_relative(instruction.displacement(), registers, flow_controller); diff --git a/InstructionSets/x86/Instruction.hpp b/InstructionSets/x86/Instruction.hpp index 9bbc80dc4..3cd6f756f 100644 --- a/InstructionSets/x86/Instruction.hpp +++ b/InstructionSets/x86/Instruction.hpp @@ -144,9 +144,9 @@ enum class Operation: uint8_t { /// Loads the destination with the source. MOV, - /// Negatives; source and destination point to the same thing, to negative. + /// Negatives; source indicates what to negative. NEG, - /// Logical NOT; source and destination point to the same thing, to negative. + /// Logical NOT; source indicates what to negative. NOT, /// Logical AND; source, destination, operand and displacement will be populated appropriately. AND, diff --git a/OSBindings/Mac/Clock SignalTests/8088Tests.mm b/OSBindings/Mac/Clock SignalTests/8088Tests.mm index 6c166c4fb..a14a11adb 100644 --- a/OSBindings/Mac/Clock SignalTests/8088Tests.mm +++ b/OSBindings/Mac/Clock SignalTests/8088Tests.mm @@ -376,12 +376,11 @@ struct FailedExecution { // TODO: LOOP, LOOPE, LOOPNE // TODO: MOV - // TODO: NEG, NOT // AND @"20.json.gz", @"21.json.gz", @"22.json.gz", @"23.json.gz", @"24.json.gz", @"25.json.gz", @"80.4.json.gz", @"81.4.json.gz", @"83.4.json.gz", -*/ + // OR @"08.json.gz", @"09.json.gz", @"0A.json.gz", @"0B.json.gz", @"0C.json.gz", @"0D.json.gz", @"80.1.json.gz", @"81.1.json.gz", @"83.1.json.gz", @@ -389,6 +388,13 @@ struct FailedExecution { // XOR @"30.json.gz", @"31.json.gz", @"32.json.gz", @"33.json.gz", @"34.json.gz", @"35.json.gz", @"80.6.json.gz", @"81.6.json.gz", @"83.6.json.gz", +*/ + + // NEG + @"F6.3.json.gz", @"F7.3.json.gz", + + // NOT + @"F6.2.json.gz", @"F7.2.json.gz", /* // NOP