diff --git a/OSBindings/Mac/Clock SignalTests/68000Tests.mm b/OSBindings/Mac/Clock SignalTests/68000Tests.mm
index bfce1acf2..d902ae1cb 100644
--- a/OSBindings/Mac/Clock SignalTests/68000Tests.mm	
+++ b/OSBindings/Mac/Clock SignalTests/68000Tests.mm	
@@ -517,9 +517,15 @@ class CPU::MC68000::ProcessorStorageTests {
 //	XCTAssert(!falseInvalids.count, "%@ opcodes should be valid but aren't: %@", @(falseInvalids.count), falseInvalids.hexDump);
 }
 
-// MARK: - Tests below this line were ported from those of the Portable 68k emulator;
-// that emulator does not include a licence. It reports that all tests were verified
-// against an Amiga.
+// MARK: - Portable 68k tests
+
+// Tests below this line were ported from those of the Portable 68k package.
+// That emulator does not include a licence. It reports that all tests were
+// verified against an Amiga.
+//
+// Cf. https://sourceforge.net/projects/portable68000/
+
+// MARK: ABCD
 
 - (void)testABCD {
 	_machine->set_program({
@@ -647,4 +653,124 @@ class CPU::MC68000::ProcessorStorageTests {
 	XCTAssertEqual(*_machine->ram_at(0x3000), 0x22a2);
 }
 
+// MARK: ADD
+
+- (void)testAdd {
+	_machine->set_program({
+		0x0602, 0xff		// ADD.B #$ff, D2
+	});
+	auto state = _machine->get_processor_state();
+	state.data[2] = 0x9ae;
+	_machine->set_processor_state(state);
+	_machine->run_for_instructions(2);
+
+	state = _machine->get_processor_state();
+	XCTAssertEqual(state.status & CPU::MC68000::Flag::ConditionCodes, CPU::MC68000::Flag::Carry | CPU::MC68000::Flag::Negative | CPU::MC68000::Flag::Extend);
+	XCTAssertEqual(state.data[2], 0x9ad);
+}
+
+- (void)testAddOverflow {
+	_machine->set_program({
+		0x0602, 0x82		// ADD.B #$82, D2
+	});
+	auto state = _machine->get_processor_state();
+	state.data[2] = 0x82;
+	_machine->set_processor_state(state);
+	_machine->run_for_instructions(2);
+
+	state = _machine->get_processor_state();
+	XCTAssertEqual(state.status & CPU::MC68000::Flag::ConditionCodes, CPU::MC68000::Flag::Overflow | CPU::MC68000::Flag::Carry | CPU::MC68000::Flag::Extend);
+	XCTAssertEqual(state.data[2], 0x04);
+}
+
+- (void)testAddBxxx {
+	_machine->set_program({
+		0xd538, 0x3000		// ADD.B D2, ($3000).W
+	});
+	auto state = _machine->get_processor_state();
+	state.data[2] = 0x82;
+	*_machine->ram_at(0x3000) = 0x8200;
+	_machine->set_processor_state(state);
+	_machine->run_for_instructions(2);
+
+	state = _machine->get_processor_state();
+	XCTAssertEqual(state.status & CPU::MC68000::Flag::ConditionCodes, CPU::MC68000::Flag::Overflow | CPU::MC68000::Flag::Carry | CPU::MC68000::Flag::Extend);
+	XCTAssertEqual(state.data[2], 0x82);
+	XCTAssertEqual(*_machine->ram_at(0x3000), 0x0400);
+}
+
+- (void)testAddWDnDn {
+	_machine->set_program({
+		0xd442		// ADD.W D2, D2
+	});
+	auto state = _machine->get_processor_state();
+	state.data[2] = 0x3e8;
+	_machine->set_processor_state(state);
+	_machine->run_for_instructions(2);
+
+	state = _machine->get_processor_state();
+	XCTAssertEqual(state.data[2], 0x7D0);
+}
+
+- (void)testAddLDnPostInc {
+	_machine->set_program({
+		0xd59a		// ADD.L D2, (A2)+
+	});
+	auto state = _machine->get_processor_state();
+	state.data[2] = 0xb2d05e00;
+	state.address[2] = 0x2000;
+	*_machine->ram_at(0x2000) = 0x7735;
+	*_machine->ram_at(0x2002) = 0x9400;
+
+	_machine->set_processor_state(state);
+	_machine->run_for_instructions(2);
+
+	state = _machine->get_processor_state();
+	XCTAssertEqual(state.data[2], 0xb2d05e00);
+	XCTAssertEqual(*_machine->ram_at(0x2000), 0x2a05);
+	XCTAssertEqual(*_machine->ram_at(0x2002), 0xf200);
+	XCTAssertEqual(state.status & CPU::MC68000::Flag::ConditionCodes, CPU::MC68000::Flag::Carry | CPU::MC68000::Flag::Extend);
+}
+
+- (void)testAddWPreDec {
+	_machine->set_program({
+		0xd462		// ADD.W -(A2), D2
+	});
+	auto state = _machine->get_processor_state();
+	state.data[2] = 0xFFFF0000;
+	state.address[2] = 0x2002;
+	*_machine->ram_at(0x2000) = 0;
+	*_machine->ram_at(0x2002) = 0xffff;
+
+	_machine->set_processor_state(state);
+	_machine->run_for_instructions(2);
+
+	state = _machine->get_processor_state();
+	XCTAssertEqual(state.data[2], 0xFFFF0000);
+	XCTAssertEqual(state.address[2], 0x2000);
+	XCTAssertEqual(state.status & CPU::MC68000::Flag::ConditionCodes, CPU::MC68000::Flag::Zero);
+}
+
+/*
+	ADD.B A2, D2 test omitted; no such opcode exists on the 68000.
+	See P4-5 of the 68000PRM: An is defined for word and long only.
+*/
+
+- (void)testAddLDnDn {
+	_machine->set_program({
+		0xd481		// ADD.l D1, D2
+	});
+	auto state = _machine->get_processor_state();
+	state.data[1] = 0xfe35aab0;
+	state.data[2] = 0x012557ac;
+
+	_machine->set_processor_state(state);
+	_machine->run_for_instructions(2);
+
+	state = _machine->get_processor_state();
+	XCTAssertEqual(state.data[1], 0xfe35aab0);
+	XCTAssertEqual(state.data[2], 0xff5b025c);
+	XCTAssertEqual(state.status & CPU::MC68000::Flag::ConditionCodes, CPU::MC68000::Flag::Negative);
+}
+
 @end
diff --git a/Processors/68000/68000.hpp b/Processors/68000/68000.hpp
index 1552076a4..ad9c9793c 100644
--- a/Processors/68000/68000.hpp
+++ b/Processors/68000/68000.hpp
@@ -236,6 +236,8 @@ enum Flag: uint16_t {
 	Trace		= 0x8000,
 	Supervisor	= 0x2000,
 
+	ConditionCodes	= 0x1f,
+
 	Extend		= 0x0010,
 	Negative	= 0x0008,
 	Zero		= 0x0004,