more opcodes
This commit is contained in:
parent
0d6988541d
commit
9bc97a7022
|
@ -7,6 +7,7 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
2A22EBFB1F21A7A700A36A61 /* IntegerExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A22EBFA1F21A7A700A36A61 /* IntegerExtensions.swift */; };
|
||||
2AD458CE1F205EB700F05121 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458CD1F205EB700F05121 /* AppDelegate.swift */; };
|
||||
2AD458D01F205EB700F05121 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458CF1F205EB700F05121 /* ViewController.swift */; };
|
||||
2AD458D21F205EB700F05121 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2AD458D11F205EB700F05121 /* Assets.xcassets */; };
|
||||
|
@ -18,6 +19,7 @@
|
|||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
2A22EBFA1F21A7A700A36A61 /* IntegerExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegerExtensions.swift; sourceTree = "<group>"; };
|
||||
2AD458CA1F205EB700F05121 /* FruitMachine.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FruitMachine.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
2AD458CD1F205EB700F05121 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
2AD458CF1F205EB700F05121 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
||||
|
@ -79,6 +81,7 @@
|
|||
2AD458E21F20661300F05121 /* CPUInstructions.swift */,
|
||||
2AD458E41F2070DF00F05121 /* Opcodes.swift */,
|
||||
2AD458E01F2064CB00F05121 /* MemoryInterface.swift */,
|
||||
2A22EBFA1F21A7A700A36A61 /* IntegerExtensions.swift */,
|
||||
);
|
||||
path = M6502;
|
||||
sourceTree = "<group>";
|
||||
|
@ -156,6 +159,7 @@
|
|||
2AD458E31F20661300F05121 /* CPUInstructions.swift in Sources */,
|
||||
2AD458D01F205EB700F05121 /* ViewController.swift in Sources */,
|
||||
2AD458CE1F205EB700F05121 /* AppDelegate.swift in Sources */,
|
||||
2A22EBFB1F21A7A700A36A61 /* IntegerExtensions.swift in Sources */,
|
||||
2AD458E51F2070DF00F05121 /* Opcodes.swift in Sources */,
|
||||
2AD458E11F2064CB00F05121 /* MemoryInterface.swift in Sources */,
|
||||
2AD458DF1F205F4500F05121 /* CPUState.swift in Sources */,
|
||||
|
@ -329,6 +333,7 @@
|
|||
2AD458DC1F205EB700F05121 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
|
|
|
@ -41,11 +41,59 @@ class CPUInstruction: NSObject {
|
|||
}
|
||||
}
|
||||
|
||||
//indexed_indirect = LDA ($00,X)
|
||||
//indirect_indexed = LDA ($00),Y
|
||||
|
||||
let InstructionTable: [UInt8:CPUInstruction] = [
|
||||
0xA5: CPUInstruction.init(mnemonic: "LDA", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.LDA),
|
||||
|
||||
//LD instructions
|
||||
0xA9: CPUInstruction.init(mnemonic: "LDA", cycles: 2, bytes: 2, addressingMode: .immediate, action: Opcodes.LDA),
|
||||
0xAD: CPUInstruction.init(mnemonic: "LDA", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.LDA),
|
||||
0xA5: CPUInstruction.init(mnemonic: "LDA", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.LDA),
|
||||
0xB5: CPUInstruction.init(mnemonic: "LDA", cycles: 4, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.LDA),
|
||||
0xB9: CPUInstruction.init(mnemonic: "LDA", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_y, action: Opcodes.LDA),
|
||||
0xAD: CPUInstruction.init(mnemonic: "LDA", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.LDA),
|
||||
0xBD: CPUInstruction.init(mnemonic: "LDA", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.LDA),
|
||||
0xB9: CPUInstruction.init(mnemonic: "LDA", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_y, action: Opcodes.LDA),
|
||||
0xA1: CPUInstruction.init(mnemonic: "LDA", cycles: 6, bytes: 2, addressingMode: .indexed_indirect, action: Opcodes.LDA),
|
||||
0xB1: CPUInstruction.init(mnemonic: "LDA", cycles: 5, bytes: 2, addressingMode: .indirect_indexed, action: Opcodes.LDA),
|
||||
|
||||
0xA2: CPUInstruction.init(mnemonic: "LDX", cycles: 2, bytes: 2, addressingMode: .immediate, action: Opcodes.LDX),
|
||||
0xA6: CPUInstruction.init(mnemonic: "LDX", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.LDX),
|
||||
0xB6: CPUInstruction.init(mnemonic: "LDX", cycles: 4, bytes: 2, addressingMode: .zeropage_indexed_y, action: Opcodes.LDX),
|
||||
0xAE: CPUInstruction.init(mnemonic: "LDX", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.LDX),
|
||||
0xBE: CPUInstruction.init(mnemonic: "LDX", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_y, action: Opcodes.LDX),
|
||||
|
||||
0xA0: CPUInstruction.init(mnemonic: "LDY", cycles: 2, bytes: 2, addressingMode: .immediate, action: Opcodes.LDY),
|
||||
0xA4: CPUInstruction.init(mnemonic: "LDY", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.LDY),
|
||||
0xB4: CPUInstruction.init(mnemonic: "LDY", cycles: 4, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.LDY),
|
||||
0xAC: CPUInstruction.init(mnemonic: "LDY", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.LDY),
|
||||
0xBC: CPUInstruction.init(mnemonic: "LDY", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.LDY),
|
||||
|
||||
//Register functions
|
||||
0x88: CPUInstruction.init(mnemonic: "DEY", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.DEY),
|
||||
0x8A: CPUInstruction.init(mnemonic: "TXA", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.TXA),
|
||||
0x98: CPUInstruction.init(mnemonic: "TYA", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.TYA),
|
||||
0xA8: CPUInstruction.init(mnemonic: "TAY", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.TAY),
|
||||
0xAA: CPUInstruction.init(mnemonic: "TAX", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.TAX),
|
||||
0xC8: CPUInstruction.init(mnemonic: "INY", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.INY),
|
||||
0xCA: CPUInstruction.init(mnemonic: "DEX", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.DEX),
|
||||
0xE8: CPUInstruction.init(mnemonic: "INX", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.INX),
|
||||
|
||||
//Processor flag instructions
|
||||
0x18: CPUInstruction.init(mnemonic: "CLC", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.CLC),
|
||||
0x38: CPUInstruction.init(mnemonic: "SEC", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.SEC),
|
||||
0x58: CPUInstruction.init(mnemonic: "CLI", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.CLI),
|
||||
0x78: CPUInstruction.init(mnemonic: "SEI", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.SEI),
|
||||
0xB8: CPUInstruction.init(mnemonic: "CLV", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.CLV),
|
||||
0xD8: CPUInstruction.init(mnemonic: "CLD", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.CLD),
|
||||
0xF8: CPUInstruction.init(mnemonic: "SED", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.SED),
|
||||
|
||||
//Stack instructions
|
||||
0x9A: CPUInstruction.init(mnemonic: "TXS", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.TXS),
|
||||
0xBA: CPUInstruction.init(mnemonic: "TSX", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.TSX),
|
||||
0x48: CPUInstruction.init(mnemonic: "PHA", cycles: 3, bytes: 1, addressingMode: .implied, action: Opcodes.PHA),
|
||||
0x68: CPUInstruction.init(mnemonic: "PLA", cycles: 4, bytes: 1, addressingMode: .implied, action: Opcodes.PLA),
|
||||
0x08: CPUInstruction.init(mnemonic: "PHP", cycles: 3, bytes: 1, addressingMode: .implied, action: Opcodes.PHP),
|
||||
0x28: CPUInstruction.init(mnemonic: "PLP", cycles: 4, bytes: 1, addressingMode: .implied, action: Opcodes.PLP),
|
||||
|
||||
0xEA: CPUInstruction.init(mnemonic: "NOP", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.NOP),
|
||||
]
|
||||
|
|
|
@ -31,6 +31,34 @@ struct StatusRegister {
|
|||
zero = (state & 0x02 == 0x02)
|
||||
carry = (state & 0x01 == 0x01)
|
||||
}
|
||||
|
||||
func asByte() -> UInt8 {
|
||||
var val: UInt8 = 0x00
|
||||
|
||||
if(negative) {
|
||||
val |= 0x80
|
||||
}
|
||||
if(overflow) {
|
||||
val |= 0x40
|
||||
}
|
||||
if(brk) {
|
||||
val |= 0x10
|
||||
}
|
||||
if(decimal) {
|
||||
val |= 0x08
|
||||
}
|
||||
if(irq_disable) {
|
||||
val |= 0x04
|
||||
}
|
||||
if(zero) {
|
||||
val |= 0x02
|
||||
}
|
||||
if(carry) {
|
||||
val |= 0x01
|
||||
}
|
||||
|
||||
return val
|
||||
}
|
||||
}
|
||||
|
||||
class CPUState: NSObject {
|
||||
|
@ -67,6 +95,23 @@ class CPUState: NSObject {
|
|||
page_boundary_crossed = false
|
||||
}
|
||||
|
||||
func getOperandByte() -> UInt8 {
|
||||
//Returns the operand byte after the current instruction byte.
|
||||
return memoryInterface.readByte(offset: program_counter + 1)
|
||||
}
|
||||
|
||||
func getOperandWord() -> UInt16 {
|
||||
var word: UInt16
|
||||
let low = memoryInterface.readByte(offset: program_counter + 1)
|
||||
let high = memoryInterface.readByte(offset: program_counter + 2)
|
||||
|
||||
word = UInt16(high)
|
||||
word = word << 8
|
||||
word |= UInt16(low)
|
||||
|
||||
return word
|
||||
}
|
||||
|
||||
func executeNextInstruction() throws {
|
||||
instruction_register = memoryInterface.memory[Int(program_counter)]
|
||||
let operation = InstructionTable[instruction_register]
|
||||
|
@ -81,13 +126,16 @@ class CPUState: NSObject {
|
|||
self.cycles += 1
|
||||
self.page_boundary_crossed = false
|
||||
}
|
||||
|
||||
self.program_counter = UInt16(Int(self.program_counter) + operation!.bytes)
|
||||
}
|
||||
|
||||
func setNegativeFlag() {
|
||||
func updateNegativeFlag() {
|
||||
status_register.negative = (accumulator & 0x80 == 0x80)
|
||||
}
|
||||
|
||||
func setZeroFlag() {
|
||||
func updateZeroFlag() {
|
||||
status_register.zero = (accumulator == 0)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
//
|
||||
// IntegerExtensions.swift
|
||||
// FruitMachine
|
||||
//
|
||||
// Created by Christopher Rohl on 7/20/17.
|
||||
// Copyright © 2017 Christopher Rohl. All rights reserved.
|
||||
//
|
||||
|
||||
import Cocoa
|
||||
|
||||
extension UInt16 {
|
||||
static func + (left: UInt16, right: UInt8) -> UInt16 {
|
||||
return left + right
|
||||
}
|
||||
}
|
|
@ -14,4 +14,16 @@ class MemoryInterface: NSObject {
|
|||
override init() {
|
||||
memory = [UInt8](repeating: 0x00, count: 65536)
|
||||
}
|
||||
|
||||
func readByte(offset: UInt16) -> UInt8 {
|
||||
return memory[Int(offset)]
|
||||
}
|
||||
|
||||
func writeByte(offset: UInt16, value: UInt8) {
|
||||
memory[Int(offset)] = value
|
||||
}
|
||||
|
||||
func readWord(offset: UInt16) -> UInt16 {
|
||||
return UInt16(memory[Int(offset)] | (memory[Int(offset+1)] << 8))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,72 +8,188 @@
|
|||
|
||||
import Cocoa
|
||||
|
||||
/* Addressing mode helper functions */
|
||||
func PC_PLUS_1(state: CPUState) -> UInt16 {
|
||||
return state.program_counter + 1
|
||||
func getOperand(state: CPUState, mode: AddressingMode) -> UInt8 {
|
||||
switch (mode) {
|
||||
|
||||
case .immediate:
|
||||
return state.getOperandByte()
|
||||
|
||||
case .zeropage:
|
||||
return state.memoryInterface.readByte(offset: UInt16(0x0000 + state.getOperandByte()))
|
||||
case .zeropage_indexed_x:
|
||||
return state.memoryInterface.readByte(offset: UInt16(state.getOperandByte() + state.index_x) & 0x00FF)
|
||||
case .zeropage_indexed_y:
|
||||
return state.memoryInterface.readByte(offset: UInt16(state.getOperandByte() + state.index_y) & 0x00FF)
|
||||
|
||||
case .absolute:
|
||||
let word: UInt16 = state.getOperandWord()
|
||||
return state.memoryInterface.readByte(offset: word)
|
||||
case .absolute_indexed_x:
|
||||
return state.memoryInterface.readByte(offset: state.getOperandWord() + UInt16(state.index_x))
|
||||
case .absolute_indexed_y:
|
||||
return state.memoryInterface.readByte(offset: state.getOperandWord() + UInt16(state.index_y))
|
||||
|
||||
case .indexed_indirect:
|
||||
let zp: UInt8 = state.memoryInterface.readByte(offset: UInt16(state.getOperandByte() + state.index_x))
|
||||
//read from (ZP)
|
||||
let pointer: UInt16 = state.memoryInterface.readWord(offset: UInt16(zp))
|
||||
state.accumulator = state.memoryInterface.readByte(offset: pointer)
|
||||
case .indirect_indexed:
|
||||
let zp: UInt8 = state.memoryInterface.readByte(offset: UInt16(state.getOperandByte()))
|
||||
let pointer: UInt16 = state.memoryInterface.readWord(offset: UInt16(zp)) + UInt16(state.index_y)
|
||||
state.accumulator = state.memoryInterface.readByte(offset: pointer)
|
||||
|
||||
case .indirect:
|
||||
//JMP is the only instruction that does this - handle it specially since it's a UInt16
|
||||
break
|
||||
|
||||
default:
|
||||
print("Called getOperand on an instruction in addressing mode \(mode)")
|
||||
return 0
|
||||
}
|
||||
|
||||
return 0 //never gets here
|
||||
}
|
||||
|
||||
func OPERAND_IMMEDIATE(state: CPUState) -> UInt8 {
|
||||
//Operand = PC+1
|
||||
return MEMORY_READ_UINT8(state: state, address: state.program_counter + 1)
|
||||
}
|
||||
|
||||
func OPERAND_ZEROPAGE_INDEXED_X(state: CPUState) -> UInt8 {
|
||||
//Operand = (PC+1) + X
|
||||
return MEMORY_READ_UINT8(state: state, address: (state.program_counter + 1) + UInt16(state.index_x))
|
||||
}
|
||||
|
||||
func OPERAND_ZEROPAGE_INDEXED_Y(state: CPUState) -> UInt8 {
|
||||
//Operand = (PC+1) + Y
|
||||
return MEMORY_READ_UINT8(state: state, address: (state.program_counter + 1) + UInt16(state.index_y))
|
||||
}
|
||||
|
||||
func OPERAND_ABSOLUTE(state: CPUState) -> UInt16 {
|
||||
//Operand = L:(PC+1) H:(PC+2)
|
||||
let low: UInt8 = MEMORY_READ_UINT8(state: state, address: state.program_counter + 1)
|
||||
let high: UInt8 = MEMORY_READ_UINT8(state: state, address: state.program_counter + 2)
|
||||
return UInt16(high << 8 | low)
|
||||
}
|
||||
|
||||
func OPERAND_ABSOLUTE_INDEXED_X(state: CPUState) -> UInt16 {
|
||||
//Operand = L:(PC+1)+X H:(PC+2)+X
|
||||
let low: UInt8 = MEMORY_READ_UINT8(state: state, address: state.program_counter + 1 + UInt16(state.index_x))
|
||||
let high: UInt8 = MEMORY_READ_UINT8(state: state, address: state.program_counter + 2 + UInt16(state.index_x))
|
||||
return UInt16(high << 8 | low)
|
||||
}
|
||||
|
||||
func OPERAND_ABSOLUTE_INDEXED_Y(state: CPUState) -> UInt16 {
|
||||
//Operand = L:(PC+1)+Y H:(PC+2)+Y
|
||||
let low: UInt8 = MEMORY_READ_UINT8(state: state, address: state.program_counter + 1 + UInt16(state.index_y))
|
||||
let high: UInt8 = MEMORY_READ_UINT8(state: state, address: state.program_counter + 2 + UInt16(state.index_y))
|
||||
return UInt16(high << 8 | low)
|
||||
}
|
||||
|
||||
func MEMORY_READ_UINT8(state: CPUState, address: UInt16) -> UInt8 {
|
||||
return state.memoryInterface.memory[Int(address)]
|
||||
}
|
||||
/* */
|
||||
|
||||
class Opcodes: NSObject {
|
||||
|
||||
static func LDA(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
|
||||
switch addressingMode {
|
||||
case .immediate:
|
||||
state.accumulator = OPERAND_IMMEDIATE(state: state)
|
||||
case .zeropage:
|
||||
state.accumulator = OPERAND_ZEROPAGE_INDEXED_X(state: state)
|
||||
case .zeropage_indexed_x:
|
||||
state.accumulator = MEMORY_READ_UINT8(state: state, address: UInt16(0x0000 + OPERAND_ZEROPAGE_INDEXED_X(state: state)))
|
||||
case .absolute:
|
||||
state.accumulator = MEMORY_READ_UINT8(state: state, address: OPERAND_ABSOLUTE(state: state))
|
||||
case .absolute_indexed_x:
|
||||
state.accumulator = MEMORY_READ_UINT8(state: state, address: OPERAND_ABSOLUTE_INDEXED_X(state: state))
|
||||
case .absolute_indexed_y:
|
||||
state.accumulator = MEMORY_READ_UINT8(state: state, address: OPERAND_ABSOLUTE_INDEXED_Y(state: state))
|
||||
default:
|
||||
print("Unhandled addressing mode \(addressingMode) for LDA")
|
||||
}
|
||||
|
||||
state.setZeroFlag();
|
||||
state.setNegativeFlag();
|
||||
state.accumulator = getOperand(state: state, mode: addressingMode)
|
||||
|
||||
state.updateZeroFlag()
|
||||
state.updateNegativeFlag()
|
||||
}
|
||||
|
||||
static func LDX(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
state.index_x = getOperand(state: state, mode: addressingMode)
|
||||
|
||||
state.updateZeroFlag()
|
||||
state.updateNegativeFlag()
|
||||
}
|
||||
|
||||
static func LDY(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
state.index_y = getOperand(state: state, mode: addressingMode)
|
||||
|
||||
state.updateZeroFlag()
|
||||
state.updateNegativeFlag()
|
||||
}
|
||||
|
||||
//Register instructions
|
||||
static func TAX(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
state.index_x = state.accumulator
|
||||
|
||||
state.updateZeroFlag();
|
||||
state.updateNegativeFlag();
|
||||
}
|
||||
|
||||
static func TXA(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
state.accumulator = state.index_x
|
||||
|
||||
state.updateZeroFlag();
|
||||
state.updateNegativeFlag();
|
||||
}
|
||||
|
||||
static func DEX(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
state.index_x = state.index_x &- 1
|
||||
|
||||
state.updateZeroFlag();
|
||||
state.updateNegativeFlag();
|
||||
}
|
||||
|
||||
static func INX(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
state.index_x = state.index_x &+ 1
|
||||
|
||||
state.updateZeroFlag();
|
||||
state.updateNegativeFlag();
|
||||
}
|
||||
|
||||
static func TAY(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
state.index_y = state.accumulator
|
||||
|
||||
state.updateZeroFlag();
|
||||
state.updateNegativeFlag();
|
||||
}
|
||||
|
||||
static func TYA(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
state.accumulator = state.index_y
|
||||
|
||||
state.updateZeroFlag();
|
||||
state.updateNegativeFlag();
|
||||
}
|
||||
|
||||
static func DEY(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
state.index_y = state.index_x &- 1
|
||||
|
||||
state.updateZeroFlag();
|
||||
state.updateNegativeFlag();
|
||||
}
|
||||
|
||||
static func INY(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
state.index_y = state.index_x &+ 1
|
||||
|
||||
state.updateZeroFlag();
|
||||
state.updateNegativeFlag();
|
||||
}
|
||||
|
||||
//Processor flag instructions
|
||||
static func CLC(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
state.status_register.carry = false
|
||||
}
|
||||
|
||||
static func SEC(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
state.status_register.carry = true
|
||||
}
|
||||
|
||||
static func CLI(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
state.status_register.irq_disable = false
|
||||
}
|
||||
|
||||
static func SEI(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
state.status_register.irq_disable = true
|
||||
}
|
||||
|
||||
static func CLV(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
state.status_register.overflow = false
|
||||
}
|
||||
|
||||
static func CLD(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
state.status_register.decimal = false
|
||||
}
|
||||
|
||||
static func SED(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
state.status_register.carry = true
|
||||
}
|
||||
|
||||
//Stack instructions
|
||||
static func TXS(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
state.stack_pointer = state.index_x
|
||||
}
|
||||
|
||||
static func TSX(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
state.index_x = state.stack_pointer
|
||||
}
|
||||
|
||||
static func PHA(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
state.memoryInterface.writeByte(offset: 0x0100 | UInt16(state.stack_pointer), value: state.accumulator)
|
||||
state.stack_pointer = state.stack_pointer &- 1
|
||||
}
|
||||
|
||||
static func PLA(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
state.stack_pointer = state.stack_pointer &+ 1
|
||||
state.accumulator = state.memoryInterface.readByte(offset: 0x0100 | UInt16(state.stack_pointer))
|
||||
}
|
||||
|
||||
static func PHP(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
state.memoryInterface.writeByte(offset: 0x0100 | UInt16(state.stack_pointer), value: state.status_register.asByte())
|
||||
state.stack_pointer = state.stack_pointer &- 1
|
||||
}
|
||||
|
||||
static func PLP(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||
state.stack_pointer = state.stack_pointer &+ 1
|
||||
state.status_register.setState(state: state.memoryInterface.readByte(offset: 0x0100 | UInt16(state.stack_pointer)))
|
||||
}
|
||||
|
||||
static func NOP(state: CPUState, addressingMode: AddressingMode) -> Void {}
|
||||
}
|
||||
|
|
|
@ -15,11 +15,15 @@ class ViewController: NSViewController {
|
|||
super.viewDidLoad()
|
||||
|
||||
CPU.memoryInterface.memory[0] = 0xAD
|
||||
CPU.memoryInterface.memory[1] = 0x00
|
||||
CPU.memoryInterface.memory[2] = 0x00
|
||||
|
||||
|
||||
CPU.memoryInterface.memory[1] = 0x34
|
||||
CPU.memoryInterface.memory[2] = 0x12
|
||||
|
||||
CPU.memoryInterface.memory[0x1234] = 0xAA
|
||||
|
||||
do {
|
||||
try CPU.executeNextInstruction()
|
||||
try CPU.executeNextInstruction()
|
||||
} catch CPUExceptions.invalidInstruction {
|
||||
print("*** 6502 Exception: Invalid instruction 0xXX at 0xXXXX")
|
||||
} catch {
|
||||
|
|
Loading…
Reference in New Issue