From 2f7dd0b01a55073c1038558c0255625084e937bd Mon Sep 17 00:00:00 2001
From: Thomas Harte <thomas.harte@gmail.com>
Date: Sun, 30 Jul 2023 16:26:29 -0400
Subject: [PATCH] Correct stack behaviour of PLD.

---
 Processors/65816/Implementation/65816Storage.cpp | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/Processors/65816/Implementation/65816Storage.cpp b/Processors/65816/Implementation/65816Storage.cpp
index 96aeb08ae..9854df814 100644
--- a/Processors/65816/Implementation/65816Storage.cpp
+++ b/Processors/65816/Implementation/65816Storage.cpp
@@ -656,7 +656,7 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
 		stack_exception_impl(type, is8bit, target, CycleAccessStack);
 	}
 
-	// 22b. Stack; s, PLx.
+	// 22b(i). Stack; s, PLx, respecting emulation mode. E.g. PLP.
 	static void stack_pull(AccessType, bool is8bit, const std::function<void(MicroOp)> &target) {
 		target(CycleFetchPCThrowaway);	// IO.
 		target(CycleFetchPCThrowaway);	// IO.
@@ -667,6 +667,17 @@ struct CPU::WDC65816::ProcessorStorageConstructor {
 		target(OperationPerform);
 	}
 
+	// 22b(ii). Stack; s, PLx, ignoring emulation mode. E.g. PLD.
+	static void stack_pull_no_emulation(AccessType, bool is8bit, const std::function<void(MicroOp)> &target) {
+		target(CycleFetchPCThrowaway);	// IO.
+		target(CycleFetchPCThrowaway);	// IO.
+
+		if(!is8bit) target(CyclePullNotEmulation);	// REG low.
+		target(CyclePullNotEmulation);				// REG [high].
+
+		target(OperationPerform);
+	}
+
 	// 22c. Stack; s, PHx.
 	static void stack_push(AccessType, bool is8bit, const std::function<void(MicroOp)> &target) {
 		target(CycleFetchPCThrowaway);	// IO.
@@ -852,7 +863,7 @@ ProcessorStorage::ProcessorStorage() {
 	/* 0x28 PLP s */			op(stack_pull, PLP, AccessMode::Always8Bit);
 	/* 0x29 AND # */			op(immediate, AND);
 	/* 0x2a ROL A */			op(accumulator, ROL);
-	/* 0x2b PLD s */			op(stack_pull, PLD, AccessMode::Always16Bit);
+	/* 0x2b PLD s */			op(stack_pull_no_emulation, PLD, AccessMode::Always16Bit);
 	/* 0x2c BIT a */			op(absolute, BIT);
 	/* 0x2d AND a */			op(absolute, AND);
 	/* 0x2e ROL a */			op(absolute_rmw, ROL);