diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj
index 3bbf1ffda..812e56622 100644
--- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj	
+++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj	
@@ -17,6 +17,7 @@
 		4B14145E1B5887AA00E04248 /* 6502AllRAM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1414591B58879D00E04248 /* 6502AllRAM.cpp */; };
 		4B1414601B58885000E04248 /* WolfgangLorenzTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B14145F1B58885000E04248 /* WolfgangLorenzTests.swift */; };
 		4B1414621B58888700E04248 /* KlausDormannTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B1414611B58888700E04248 /* KlausDormannTests.swift */; };
+		4B1482391ECE94F30099EA63 /* Z80AllRAM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BFCA11D1ECBD9BD00AC40C1 /* Z80AllRAM.cpp */; };
 		4B1D08061E0F7A1100763741 /* TimeTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B1D08051E0F7A1100763741 /* TimeTests.mm */; };
 		4B1E85751D170228001EF87D /* Typer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B1E85731D170228001EF87D /* Typer.cpp */; };
 		4B1E85811D176468001EF87D /* 6532Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B1E85801D176468001EF87D /* 6532Tests.swift */; };
@@ -2503,6 +2504,7 @@
 				4BF8295D1D8F048B001BAE39 /* MFM.cpp in Sources */,
 				4BE77A2E1D84ADFB00BC3827 /* File.cpp in Sources */,
 				4B5FADBD1DE31D1500AEC565 /* OricMFMDSK.cpp in Sources */,
+				4B1482391ECE94F30099EA63 /* Z80AllRAM.cpp in Sources */,
 				4B77069D1EC904570053B588 /* Z80.cpp in Sources */,
 				4BAB62B51D327F7E00DF5BA0 /* G64.cpp in Sources */,
 				4BD468F71D8DF41D0084958B /* 1770.cpp in Sources */,
diff --git a/Processors/Z80/Z80.hpp b/Processors/Z80/Z80.hpp
index 8c69b226c..fd87ff0fc 100644
--- a/Processors/Z80/Z80.hpp
+++ b/Processors/Z80/Z80.hpp
@@ -67,23 +67,14 @@ enum BusOperation {
 	Input, Output,
 	Interrupt,
 //	BusRequest, BusAcknowledge,
-	None
+	Internal
 };
 
 struct MachineCycle {
 	const BusOperation operation;
+	const int length;
 	const uint16_t *address;
 	uint8_t *const value;
-
-	inline int cycle_length() const {
-		static const int cycles_by_bus_operation[6] = {
-			4,
-			3, 3,
-			3, 3,
-			3
-		};
-		return cycles_by_bus_operation[operation];
-	}
 };
 
 struct MicroOp {
@@ -129,12 +120,13 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
 		RegisterPair address_;
 
 		void decode_base_operation(uint8_t operation) {
-#define XX				{MicroOp::None}
-#define FETCH(x, y)		{MicroOp::BusOperation, nullptr, nullptr, {ReadOpcode, &y.full, &x}}
+#define XX				{MicroOp::None, 0}
+#define FETCH(x, y)		{MicroOp::BusOperation, nullptr, nullptr, {Read, 3, &y.full, &x}}
 #define FETCH16(x, y)	FETCH(x.bytes.low, y), {MicroOp::Increment16, &y.full}, FETCH(x.bytes.high, y), {MicroOp::Increment16, &y.full}
 #define FETCH16L(x, y)	FETCH(x.bytes.low, y), {MicroOp::Increment16, &y.full}, FETCH(x.bytes.high, y)
 #define FETCH_LOW()		FETCH(address_.bytes.low, pc_)
 #define FETCH_HIGH()	FETCH(address_.bytes.high, pc_)
+#define WAIT(n)			{MicroOp::BusOperation, nullptr, nullptr, {Internal, n} }
 #define Program(...)	{ __VA_ARGS__, {MicroOp::MoveToNextProgram} }
 
 			static const MicroOp base_program_table[256][10] = {
@@ -178,9 +170,8 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
 				XX,			XX,			XX,			XX,			XX,			XX,			XX,			XX,		// 0xe0
 				XX,			XX,			XX,			XX,			XX,			XX,			XX,			XX,		// 0xe8
 				XX,			XX,			XX,			XX,			XX,			XX,			XX,			XX,		// 0xf0
-				XX,
-				XX,
-//				Progam(),	/* 0xF9 LD SP, HL */
+				XX,	/* 0xf8 */
+				Program(WAIT(2), {MicroOp::Move16, &hl_.full, &sp_.full}),	/* 0xF9 LD SP, HL */
 				XX,			XX,			XX,			XX,			XX,			XX,		// 0xf8
 			};
 			if(base_program_table[operation][0].type == MicroOp::None) {
@@ -206,7 +197,7 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
 		*/
 		void run_for_cycles(int number_of_cycles) {
 			static const MicroOp fetch_decode_execute[] = {
-				{ MicroOp::BusOperation, nullptr, nullptr, {ReadOpcode, &pc_.full, &operation_}},
+				{ MicroOp::BusOperation, 4, nullptr, nullptr, {ReadOpcode, &pc_.full, &operation_}},
 				{ MicroOp::DecodeOperation },
 				{ MicroOp::MoveToNextProgram }
 			};
@@ -225,7 +216,7 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
 
 				switch(operation->type) {
 					case MicroOp::BusOperation:
-						if(number_of_cycles_ < operation->machine_cycle.cycle_length()) {
+						if(number_of_cycles_ < operation->machine_cycle.length) {
 							return;
 						}
 						static_cast<T *>(this)->perform_machine_cycle(&operation->machine_cycle);
@@ -242,6 +233,8 @@ template <class T> class Processor: public MicroOpScheduler<MicroOp> {
 					case MicroOp::Increment16:			(*((uint16_t *)operation->source))++;			break;
 					case MicroOp::Jump:					pc_ = address_;									break;
 
+					case MicroOp::Move16:				*(uint16_t *)operation->destination = *(uint16_t *)operation->source;			break;
+
 					default:
 						printf("Unhandled Z80 operation %d\n", operation->type);
 					return;