Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
            }
        }
Beispiel #3
0
        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);
                    }
                }
            }
        }