From 59521f9d380ae39293e7113cec03f216419f2943 Mon Sep 17 00:00:00 2001
From: Thomas Harte <thomas.harte@gmail.com>
Date: Mon, 9 Oct 2023 11:59:38 -0400
Subject: [PATCH] Implement CBW, CLC, CLD, CLI, CMC.

---
 .../Implementation/PerformImplementation.hpp  | 24 +++++++++++++++----
 OSBindings/Mac/Clock SignalTests/8088Tests.mm |  5 ++++
 2 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/InstructionSets/x86/Implementation/PerformImplementation.hpp b/InstructionSets/x86/Implementation/PerformImplementation.hpp
index f3ce62489..ba665a3bf 100644
--- a/InstructionSets/x86/Implementation/PerformImplementation.hpp
+++ b/InstructionSets/x86/Implementation/PerformImplementation.hpp
@@ -358,7 +358,7 @@ inline void call_absolute(IntT target, FlowControllerT &flow_controller) {
 }
 
 template <Model model, typename InstructionT, typename FlowControllerT, typename RegistersT, typename MemoryT>
-inline void call_far(InstructionT &instruction,
+void call_far(InstructionT &instruction,
 	FlowControllerT &flow_controller,
 	RegistersT &registers,
 	MemoryT &memory) {
@@ -389,6 +389,15 @@ inline void call_far(InstructionT &instruction,
 	flow_controller.call(segment, offset);
 }
 
+inline void cbw(CPU::RegisterPair16 &ax) {
+	ax.halves.high = (ax.halves.low & 0x80) ? 0xff : 0x00;
+}
+
+inline void clc(Status &status) {	status.carry = 0;				}
+inline void cld(Status &status) {	status.direction = 0;			}
+inline void cli(Status &status) {	status.interrupt = 0;			}	// TODO: quite a bit more in protected mode.
+inline void cmc(Status &status) {	status.carry = !status.carry;	}
+
 }
 
 template <
@@ -447,10 +456,9 @@ template <
 		case Operation::AAM:	Primitive::aam(registers.axp(), instruction.operand(), status, flow_controller);	return;
 		case Operation::AAS:	Primitive::aas(registers.axp(), status);											return;
 
-		case Operation::ADC:	Primitive::adc(destination(), source(), status);									break;
-		case Operation::ADD:	Primitive::add(destination(), source(), status);									break;
-
-		case Operation::AND:	Primitive::and_(destination(), source(), status);									break;
+		case Operation::ADC:	Primitive::adc(destination(), source(), status);		break;
+		case Operation::ADD:	Primitive::add(destination(), source(), status);		break;
+		case Operation::AND:	Primitive::and_(destination(), source(), status);		break;
 
 		case Operation::CALLrel:
 			Primitive::call_relative(instruction.displacement(), registers, flow_controller);
@@ -461,6 +469,12 @@ template <
 		case Operation::CALLfar:
 			Primitive::call_far<model>(instruction, flow_controller, registers, memory);
 		return;
+
+		case Operation::CBW:	Primitive::cbw(registers.axp());	return;
+		case Operation::CLC:	Primitive::clc(status);				return;
+		case Operation::CLD:	Primitive::cld(status);				return;
+		case Operation::CLI:	Primitive::cli(status);				return;
+		case Operation::CMC:	Primitive::cmc(status);				return;
 	}
 
 	// Write to memory if required to complete this operation.
diff --git a/OSBindings/Mac/Clock SignalTests/8088Tests.mm b/OSBindings/Mac/Clock SignalTests/8088Tests.mm
index 9a412f39c..ef484181d 100644
--- a/OSBindings/Mac/Clock SignalTests/8088Tests.mm	
+++ b/OSBindings/Mac/Clock SignalTests/8088Tests.mm	
@@ -295,6 +295,11 @@ struct FailedExecution {
 		@"3F.json.gz",	// AAS
 		@"D4.json.gz",	// AAM
 		@"D5.json.gz",	// AAD
+		@"98.json.gz",	// CBW
+		@"F8.json.gz",	// CLC
+		@"FC.json.gz",	// CLD
+		@"FA.json.gz",	// CLI
+		@"F5.json.gz",	// CMC
 	]];
 
 	NSSet *ignoreList = nil;