From 8d24c00df2f71b62f74dd749f4710df97ea59bee Mon Sep 17 00:00:00 2001
From: Thomas Harte <thomas.harte@gmail.com>
Date: Sat, 30 Apr 2022 09:00:47 -0400
Subject: [PATCH] Include decoded condition in Preinstruction.

---
 InstructionSets/M68k/Decoder.cpp     | 45 ++++++++++++++++++++++------
 InstructionSets/M68k/Decoder.hpp     |  3 +-
 InstructionSets/M68k/Instruction.hpp | 25 ++++++++++++++--
 3 files changed, 60 insertions(+), 13 deletions(-)

diff --git a/InstructionSets/M68k/Decoder.cpp b/InstructionSets/M68k/Decoder.cpp
index 414b9768d..49b190846 100644
--- a/InstructionSets/M68k/Decoder.cpp
+++ b/InstructionSets/M68k/Decoder.cpp
@@ -479,7 +479,8 @@ template <uint8_t op> uint32_t Predecoder<model>::invalid_operands() {
 template <Model model>
 template <uint8_t op, bool validate> Preinstruction Predecoder<model>::validated(
 	AddressingMode op1_mode, int op1_reg,
-	AddressingMode op2_mode, int op2_reg
+	AddressingMode op2_mode, int op2_reg,
+	Condition condition
 ) {
 	constexpr auto operation = Predecoder<model>::operation(op);
 
@@ -489,7 +490,8 @@ template <uint8_t op, bool validate> Preinstruction Predecoder<model>::validated
 			op1_mode, op1_reg,
 			op2_mode, op2_reg,
 			requires_supervisor<model>(operation),
-			size(operation));
+			size(operation),
+			condition);
 	}
 
 	const auto invalid = invalid_operands<op>();
@@ -501,7 +503,8 @@ template <uint8_t op, bool validate> Preinstruction Predecoder<model>::validated
 			op1_mode, op1_reg,
 			op2_mode, op2_reg,
 			requires_supervisor<model>(operation),
-			size(operation));
+			size(operation),
+			condition);
 }
 
 /// Decodes the fields within an instruction and constructs a `Preinstruction`, given that the operation has already been
@@ -601,18 +604,29 @@ template <uint8_t op, bool validate> Preinstruction Predecoder<model>::decode(ui
 				combined_mode(ea_mode, ea_register), ea_register);
 
 		//
-		// MARK: STOP, ANDItoCCR, ANDItoSR, EORItoCCR, EORItoSR, ORItoCCR, ORItoSR, Bccl, Bccw, BSRl, BSRw
+		// MARK: STOP, ANDItoCCR, ANDItoSR, EORItoCCR, EORItoSR, ORItoCCR, ORItoSR, BSRl, BSRw
 		//
-		// Operand is an immedate; destination/source (if any) is implied by the operation.
+		// Operand is an immedate; destination/source (if any) is implied by the operation,
+		// e.g. ORItoSR has a destination of SR.
 		//
 		case OpT(Operation::STOP):
-		case OpT(Operation::Bccl):		case OpT(Operation::Bccw):
 		case OpT(Operation::BSRl):		case OpT(Operation::BSRw):
 		case OpT(Operation::ORItoSR):	case OpT(Operation::ORItoCCR):
 		case OpT(Operation::ANDItoSR):	case OpT(Operation::ANDItoCCR):
 		case OpT(Operation::EORItoSR):	case OpT(Operation::EORItoCCR):
 			return validated<op, validate>(AddressingMode::ImmediateData);
 
+		//
+		// MARK: Bccl, Bccw
+		//
+		// Operand is an immedate; b8–b11 are a condition code.
+		//
+		case OpT(Operation::Bccl):		case OpT(Operation::Bccw):
+			return validated<op, validate>(
+				AddressingMode::ImmediateData, 0,
+				AddressingMode::None, 0,
+				Condition((instruction >> 8) & 0xf));
+
 		//
 		// MARK: CHK
 		//
@@ -724,9 +738,20 @@ template <uint8_t op, bool validate> Preinstruction Predecoder<model>::decode(ui
 		case OpT(Operation::PEA):
 		case OpT(Operation::TAS):
 		case OpT(Operation::TSTb):		case OpT(Operation::TSTw):		case OpT(Operation::TSTl):
-		case OpT(Operation::Scc):
 			return validated<op, validate>(combined_mode(ea_mode, ea_register), ea_register);
 
+		//
+		// MARK: Scc
+		//
+		// b0–b2 and b3–b5:		effective address;
+		// b8–b11:				a condition.
+		//
+		case OpT(Operation::Scc):
+			return validated<op, validate>(
+				combined_mode(ea_mode, ea_register), ea_register,
+				AddressingMode::None, 0,
+				Condition((instruction >> 8) & 0xf));
+
 		//
 		// MARK: UNLINK, MOVEtoUSP, MOVEfromUSP
 		//
@@ -739,13 +764,15 @@ template <uint8_t op, bool validate> Preinstruction Predecoder<model>::decode(ui
 		//
 		// MARK: DBcc
 		//
-		// b0–b2:		a data register.
+		// b0–b2:		a data register;
+		// b8–b11:		a condition.
 		// Followed by an immediate value.
 		//
 		case OpT(Operation::DBcc):
 			return validated<op, validate>(
 				AddressingMode::DataRegisterDirect, ea_register,
-				AddressingMode::ImmediateData, 0);
+				AddressingMode::ImmediateData, 0,
+				Condition((instruction >> 8) & 0xf));
 
 		//
 		// MARK: SWAP, EXTbtow, EXTwtol
diff --git a/InstructionSets/M68k/Decoder.hpp b/InstructionSets/M68k/Decoder.hpp
index 14903755d..59bae5cce 100644
--- a/InstructionSets/M68k/Decoder.hpp
+++ b/InstructionSets/M68k/Decoder.hpp
@@ -56,7 +56,8 @@ template <Model model> class Predecoder {
 		template <OpT operation, bool validate = true> Preinstruction decode(uint16_t instruction);
 		template <OpT operation, bool validate> Preinstruction validated(
 			AddressingMode op1_mode = AddressingMode::None, int op1_reg = 0,
-			AddressingMode op2_mode = AddressingMode::None, int op2_reg = 0
+			AddressingMode op2_mode = AddressingMode::None, int op2_reg = 0,
+			Condition condition = Condition::True
 		);
 		template <uint8_t op> uint32_t invalid_operands();
 
diff --git a/InstructionSets/M68k/Instruction.hpp b/InstructionSets/M68k/Instruction.hpp
index 3ae2e7006..252fb5e77 100644
--- a/InstructionSets/M68k/Instruction.hpp
+++ b/InstructionSets/M68k/Instruction.hpp
@@ -252,6 +252,17 @@ constexpr uint32_t quick(Operation op, uint16_t instruction) {
 	}
 }
 
+enum class Condition {
+	True = 0x00,					False = 0x01,
+	High = 0x02,					LowOrSame = 0x03,
+	CarryClear = 0x04,				CarrySet = 0x05,
+	NotEqual = 0x06,				Equal = 0x07,
+	OverflowClear = 0x08,			OverflowSet = 0x09,
+	Positive = 0x0a,				Negative = 0x0b,
+	GreaterThanOrEqual = 0x0c,		LessThan = 0x0d,
+	GreaterThan = 0x0e,				LessThanOrEqual = 0x0f,
+};
+
 /// Indicates the addressing mode applicable to an operand.
 ///
 /// Implementation notes:
@@ -363,7 +374,10 @@ class Preinstruction {
 			return flags_ & 0x80;
 		}
 		DataSize size() {
-			return DataSize(flags_ & 0x7f);
+			return DataSize(flags_ & 0x03);
+		}
+		Condition condition() {
+			return Condition((flags_ >> 2) & 0x0f);
 		}
 
 	private:
@@ -376,11 +390,16 @@ class Preinstruction {
 			AddressingMode op1_mode,	int op1_reg,
 			AddressingMode op2_mode,	int op2_reg,
 			bool is_supervisor,
-			DataSize size) : operation(operation)
+			DataSize size,
+			Condition condition) : operation(operation)
 		{
 			operands_[0] = uint8_t(op1_mode) | uint8_t(op1_reg << 5);
 			operands_[1] = uint8_t(op2_mode) | uint8_t(op2_reg << 5);
-			flags_ = (is_supervisor ? 0x80 : 0x00) | uint8_t(size);
+			flags_ = uint8_t(
+				(is_supervisor ? 0x80 : 0x00) |
+				(int(condition) << 2) |
+				int(size)
+			);
 		}
 
 		Preinstruction() {}