Skip to content

Commit bf737d4

Browse files
committed
Fix code relocator when indirect modification of PC via stack RTS
1 parent 114ee57 commit bf737d4

4 files changed

Lines changed: 610 additions & 29 deletions

File tree

src/Asm6502.Tests/CodeRelocatorTests.cs

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ namespace Asm6502.Tests;
1313
[TestClass]
1414
public class CodeRelocatorTests : VerifyBase
1515
{
16+
private Mos6510Cpu? _cpu;
17+
1618
[TestMethod]
1719
public async Task TestRelocationZp()
1820
{
@@ -198,8 +200,38 @@ public async Task TestJSR()
198200
.End()
199201
));
200202

203+
[TestMethod]
204+
public async Task TestJSR_ModifyPC()
205+
{
206+
await Verify(RelocToString(
207+
new Mos6510Assembler()
208+
.JSR(out var subroutine)
209+
.RTS() // Never called as we patch it
210+
.LabelForward(out var realReturn)
211+
.Label(subroutine) // Replace the return address on the stack
212+
.PLA() // We pop the JSR addressed pushed above
213+
.PLA()
214+
.LDA_Imm(realReturn.HighByte())
215+
.PHA() // We replace it with another address (below) that is at the page above
216+
.LDA_Imm(realReturn.LowByte() - 1) // Because JSR pushes PC - 1
217+
.PHA()
218+
.LDA_Imm(0x42)
219+
.RTS()
220+
.Align(256, (byte)Mos6510OpCode.NOP_Implied)
221+
.NOP()
222+
.NOP() // Padding to ensure we are at the next page (JSR PC - 1 address is pushed on the stack)
223+
.Label(realReturn)
224+
.LDA_Imm(0x43)
225+
.RTS()
226+
.End()
227+
));
228+
229+
if (_cpu is not null)
230+
{
231+
Assert.AreEqual(0x43, _cpu.A, "Invalid A Register");
232+
}
233+
}
201234

202-
203235
[TestMethod]
204236
public async Task TestLAX()
205237
=> await Verify(RelocToString(
@@ -419,7 +451,7 @@ private string RelocToString(Mos6510Assembler asm, bool expectException = false)
419451
if (relocatedBytes is not null)
420452
{
421453
relocator.PrintRelocationMap(writer);
422-
454+
_cpu = (Mos6510Cpu)relocator.Cpu;
423455
writer.WriteLine();
424456
}
425457

0 commit comments

Comments
 (0)