public void cpu_OnJSR(Cpu cpu) { Debug.Assert(cpu.OpCode == 0x20); // JSR // 6502 JSR semantics StackByte jsrReturnAddrH = _stackBytes[StackPtr + 2]; StackByte jsrReturnAddrL = _stackBytes[StackPtr + 1]; JsrInfo info = new JsrInfo { JsrOpcodeAddr = cpu.OpcodeRPC, JsrTargetAddr = cpu.RPC, StackPtrAfterJsr = StackPtr, CyclesAfterJsr = cpu.Cycles, JsrReturnAddrH = jsrReturnAddrH, JsrReturnAddrL = jsrReturnAddrL, CallDepthAtJsr = CallDepth, }; // check integrity of JsrInfo (ReturnAddrOnStack is calculated property) Debug.Assert((jsrReturnAddrL.Value | jsrReturnAddrH.Value << 8) == info.ReturnAddrOnStack); _jsrInfoStack.Push(info); jsrReturnAddrH.NotifyNewJsrInfo(info, AddressPart.High, cpu.Cycles); jsrReturnAddrL.NotifyNewJsrInfo(info, AddressPart.Low, cpu.Cycles); OnJSR?.Invoke(info); }
public StackWrapper(MachineOperator mo) { _cpu = mo.Machine.Cpu; _memory = mo.Machine.Memory; for (int stackPtr = 0xff; stackPtr >= 0; stackPtr--) { _stackBytes[stackPtr] = new StackByte(_memory, stackPtr); } }
public void cpu_OnRTS(Cpu cpu) { Debug.Assert(cpu.OpCode == 0x60); // RTS // RTS adds 1 to RPC, so return address needs to be one byte less than target RPC // this how RTS is defined, so we can safely assert (6502 semantics, not StackWrapper semantics) StackByte highRtsPart = _stackBytes[StackPtr]; StackByte lowRtsPart = _stackBytes[StackPtr - 1]; Debug.Assert(lowRtsPart.Value + (highRtsPart.Value << 8) + 1 == cpu.RPC); if (StackPtr == TopStackPtrH) { // StackPtr is at the level where the matching JSR happened JsrInfo info = PopJsrInfo(i => { // TraceLine( $"<- RTS /{CallDepth} {cpu.RPC.ToHex()}" + (i.Retired ? $" (retired {i.JsrOpcodeAddr.ToHex()})" : "" ) ); }); AddRtsInfo(info); OnRTS?.Invoke(info); } else { Debug.Assert(false, "UNTESTED"); if (StackPtr < TopStackPtrH) { // probably a RTS jump table // nothing to do for us here // we could probably assert that StackPtr is 2 below exectedStackPtr, but maybe caller wants to pass sth on the stack? } else { // probably an "exception", i.e. returning not to the caller but to the caller's caller Debug.Assert(StackPtr > TopStackPtrH); while (_jsrInfoStack.Count > 0 && StackPtr > TopStackPtrH) { JsrInfo info = PopJsrInfo(i => { // TraceLine( $"<- ignored RTS /{CallDepth} {cpu.RPC.ToHex()}" + (i.Retired ? $" (retired {i.JsrOpcodeAddr.ToHex()})" : "") ); }); info.Ignored = true; AddRtsInfo(info); OnRTS?.Invoke(info); } } } }