public void ExecuteJumpReturn(byte instruction, AddressModes addressMode, int signature) { RegisterBankNumber fakeBank = new RegisterBankNumber { Value = cpu.PC >> 16 }; int addr = GetAddress(addressMode, signature, fakeBank); switch (instruction) { case OpcodeList.JSR_Absolute: case OpcodeList.JSR_AbsoluteIndexedIndirectWithX: cpu.Push(cpu.PC - 1, 2); cpu.JumpLong(addr); return; case OpcodeList.JSR_AbsoluteLong: cpu.Push(cpu.PC - 1, 3); cpu.JumpLong(addr); return; case OpcodeList.JMP_Absolute: case OpcodeList.JMP_AbsoluteLong: case OpcodeList.JMP_AbsoluteIndirect: case OpcodeList.JMP_AbsoluteIndexedIndirectWithX: case OpcodeList.JMP_AbsoluteIndirectLong: cpu.JumpLong(addr); return; // RTS, RTL, RTI case OpcodeList.RTI_StackImplied: cpu.Flags.SetFlags(cpu.Pull(1)); cpu.SyncFlags(); if (cpu.Flags.Emulation) { cpu.JumpShort(cpu.Pull(2)); } else { cpu.JumpLong(cpu.Pull(3)); } return; case OpcodeList.RTS_StackImplied: cpu.JumpShort(cpu.Pull(2) + 1); return; case OpcodeList.RTL_StackImplied: addr = cpu.Pull(3); cpu.JumpLong(addr + 1); return; default: throw new NotImplementedException("ExecuteJumpReturn() opcode not implemented: " + instruction.ToString("X2")); } }
private int GetAddress(AddressModes addressMode, int SignatureBytes, RegisterBankNumber Bank) { int addr = 0; int ptr = 0; switch (addressMode) { // The address will not be used in Immediate or Implied mode, but case AddressModes.Immediate: return(ADDRESS_IMMEDIATE); case AddressModes.Implied: return(ADDRESS_IMPLIED); case AddressModes.Absolute: return(Bank.GetLongAddress(SignatureBytes)); case AddressModes.AbsoluteLong: return(SignatureBytes); case AddressModes.AbsoluteIndexedWithX: return(Bank.GetLongAddress(SignatureBytes + cpu.X.Value)); case AddressModes.AbsoluteLongIndexedWithX: return(SignatureBytes + cpu.X.Value); case AddressModes.AbsoluteIndexedWithY: return(Bank.GetLongAddress(SignatureBytes + cpu.Y.Value)); case AddressModes.AbsoluteLongIndexedWithY: return(Bank.GetLongAddress(SignatureBytes + cpu.X.Value)); case AddressModes.DirectPage: return(cpu.DirectPage.GetLongAddress(SignatureBytes)); case AddressModes.DirectPageIndexedWithX: return(cpu.DirectPage.GetLongAddress(SignatureBytes + cpu.X.Value)); case AddressModes.DirectPageIndexedWithY: return(cpu.DirectPage.GetLongAddress(SignatureBytes + cpu.Y.Value)); case AddressModes.DirectPageIndexedIndirectWithX: addr = cpu.DirectPage.GetLongAddress(SignatureBytes) + cpu.X.Value; ptr = cpu.MemMgr.ReadWord(addr); //return cpu.ProgramBank.GetLongAddress(ptr); return((cpu.PC & 0xFF_0000) + ptr); case AddressModes.DirectPageIndirect: addr = cpu.DirectPage.GetLongAddress(SignatureBytes); ptr = cpu.MemMgr.ReadWord(addr); return(cpu.DataBank.GetLongAddress(ptr)); case AddressModes.DirectPageIndirectIndexedWithY: addr = cpu.DirectPage.GetLongAddress(SignatureBytes); ptr = cpu.MemMgr.ReadWord(addr) + cpu.Y.Value; //return cpu.ProgramBank.GetLongAddress(ptr); return((cpu.PC & 0xFF_0000) + ptr); case AddressModes.DirectPageIndirectLong: addr = cpu.DirectPage.GetLongAddress(SignatureBytes); ptr = cpu.MemMgr.ReadLong(addr); return(ptr); case AddressModes.DirectPageIndirectLongIndexedWithY: addr = cpu.DirectPage.GetLongAddress(SignatureBytes); ptr = cpu.MemMgr.ReadLong(addr) + cpu.Y.Value; return(ptr); case AddressModes.ProgramCounterRelative: ptr = MakeSignedByte((byte)SignatureBytes); addr = cpu.PC + ptr; return(addr); case AddressModes.ProgramCounterRelativeLong: ptr = MakeSignedInt((UInt16)SignatureBytes); addr = cpu.PC + ptr; return(addr); case AddressModes.StackImplied: //case AddressModes.StackAbsolute: return(0); case AddressModes.StackDirectPageIndirect: return(cpu.DirectPage.GetLongAddress(SignatureBytes)); case AddressModes.StackRelative: return(cpu.Stack.Value + SignatureBytes); case AddressModes.StackRelativeIndirectIndexedWithY: int bankOffset = Bank.Value << 16; addr = bankOffset + (cpu.Stack.Value + SignatureBytes); return(bankOffset + cpu.MemMgr.ReadWord(addr) + cpu.Y.Value); case AddressModes.StackProgramCounterRelativeLong: return(SignatureBytes); // Jump and JSR indirect references vectors located in Bank 0 case AddressModes.JmpAbsoluteIndirect: addr = SignatureBytes; ptr = cpu.MemMgr.ReadWord(addr); //return cpu.ProgramBank.GetLongAddress(ptr); return((cpu.PC & 0xFF_0000) + ptr); case AddressModes.JmpAbsoluteIndirectLong: addr = SignatureBytes; ptr = cpu.MemMgr.ReadLong(addr); return(ptr); case AddressModes.JmpAbsoluteIndexedIndirectWithX: addr = SignatureBytes + cpu.X.Value; //ptr = cpu.Memory.ReadWord(cpu.ProgramBank.GetLongAddress(addr)); ptr = cpu.MemMgr.ReadWord((cpu.PC & 0xFF_0000) + addr); //return cpu.ProgramBank.GetLongAddress(ptr); return((cpu.PC & 0xFF_0000) + ptr); case AddressModes.Accumulator: return(0); default: throw new NotImplementedException("GetAddress() Address mode not implemented: " + addressMode.ToString()); } }