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