1
0
mirror of https://github.com/cc65/cc65.git synced 2025-04-08 19:38:55 +00:00

Merge pull request #2567 from sidneycadot/fix-jsr

sim65: fix memory access order of the JSR instruction.
This commit is contained in:
Sidney Cadot 2024-12-22 17:59:19 +01:00 committed by GitHub
commit 3c4d9660ed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1456,13 +1456,37 @@ static void OPC_6502_1F (void)
static void OPC_6502_20 (void)
/* Opcode $20: JSR */
{
unsigned Addr;
/* The obvious way to implement JSR for the 6502 is to (a) read the target address,
* and then (b) push the return address minus one. Or do (b) first, then (a).
*
* However, there is a non-obvious case where this conflicts with the actual order
* of operations that the 6502 does, which is:
*
* (a) Load the LSB of the target address.
* (b) Push the MSB of the return address, minus one.
* (c) Push the LSB of the return address, minus one.
* (d) Load the MSB of the target address.
*
* This can make a difference in a pretty esoteric case, if the JSR target is located,
* wholly or in part, inside the stack page (!). This won't happen in normal code
* but it can happen in specifically constructed examples.
*
* To deal with this, we load the LSB and MSB of the target address separately,
* with the pushing of the return address sandwiched in between, to mimic
* the order of the bus operations on a real 6502.
*/
unsigned AddrLo, AddrHi;
Cycles = 6;
Addr = MemReadWord (Regs.PC+1);
Regs.PC += 2;
Regs.PC += 1;
AddrLo = MemReadByte(Regs.PC);
Regs.PC += 1;
PUSH (PCH);
PUSH (PCL);
Regs.PC = Addr;
AddrHi = MemReadByte(Regs.PC);
Regs.PC = AddrLo + (AddrHi << 8);
ParaVirtHooks (&Regs);
}