From da828a5d36722c3464d6d314c588a322ac6d3874 Mon Sep 17 00:00:00 2001 From: Luigi Thirty Date: Sun, 23 Jul 2017 01:29:09 -0400 Subject: [PATCH] some more opcodes and refactoring --- FruitMachine.xcodeproj/project.pbxproj | 4 + FruitMachine/M6502/AddressConversions.swift | 15 ++ FruitMachine/M6502/CPUInstructions.swift | 158 ++++++++++++-------- FruitMachine/M6502/Opcodes.swift | 74 ++++++--- 4 files changed, 170 insertions(+), 81 deletions(-) create mode 100644 FruitMachine/M6502/AddressConversions.swift diff --git a/FruitMachine.xcodeproj/project.pbxproj b/FruitMachine.xcodeproj/project.pbxproj index 199bf20..19396ed 100644 --- a/FruitMachine.xcodeproj/project.pbxproj +++ b/FruitMachine.xcodeproj/project.pbxproj @@ -17,6 +17,7 @@ 2AD458E31F20661300F05121 /* CPUInstructions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458E21F20661300F05121 /* CPUInstructions.swift */; }; 2AD458E51F2070DF00F05121 /* Opcodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AD458E41F2070DF00F05121 /* Opcodes.swift */; }; 2AE5BA041F23DE4400FAA343 /* Disassembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE5BA031F23DE4400FAA343 /* Disassembly.swift */; }; + 2AE5BA061F2469EB00FAA343 /* AddressConversions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2AE5BA051F2469EB00FAA343 /* AddressConversions.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -33,6 +34,7 @@ 2AD458E21F20661300F05121 /* CPUInstructions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CPUInstructions.swift; sourceTree = ""; }; 2AD458E41F2070DF00F05121 /* Opcodes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Opcodes.swift; sourceTree = ""; }; 2AE5BA031F23DE4400FAA343 /* Disassembly.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Disassembly.swift; sourceTree = ""; }; + 2AE5BA051F2469EB00FAA343 /* AddressConversions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressConversions.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -83,6 +85,7 @@ 2AD458E21F20661300F05121 /* CPUInstructions.swift */, 2AE5BA031F23DE4400FAA343 /* Disassembly.swift */, 2AD458E41F2070DF00F05121 /* Opcodes.swift */, + 2AE5BA051F2469EB00FAA343 /* AddressConversions.swift */, 2AD458E01F2064CB00F05121 /* MemoryInterface.swift */, 2A22EBFA1F21A7A700A36A61 /* IntegerExtensions.swift */, ); @@ -165,6 +168,7 @@ 2A22EBFB1F21A7A700A36A61 /* IntegerExtensions.swift in Sources */, 2AE5BA041F23DE4400FAA343 /* Disassembly.swift in Sources */, 2AD458E51F2070DF00F05121 /* Opcodes.swift in Sources */, + 2AE5BA061F2469EB00FAA343 /* AddressConversions.swift in Sources */, 2AD458E11F2064CB00F05121 /* MemoryInterface.swift in Sources */, 2AD458DF1F205F4500F05121 /* CPUState.swift in Sources */, ); diff --git a/FruitMachine/M6502/AddressConversions.swift b/FruitMachine/M6502/AddressConversions.swift new file mode 100644 index 0000000..81f97ce --- /dev/null +++ b/FruitMachine/M6502/AddressConversions.swift @@ -0,0 +1,15 @@ +// +// Conversions.swift +// FruitMachine +// +// Created by Christopher Rohl on 7/23/17. +// Copyright © 2017 Christopher Rohl. All rights reserved. +// + +import Cocoa + +class AddressConversions: NSObject { + static func zeroPageAsUInt16(address: UInt8) -> UInt16 { + return 0x0000 | UInt16(address) + } +} diff --git a/FruitMachine/M6502/CPUInstructions.swift b/FruitMachine/M6502/CPUInstructions.swift index 39d54b0..069c231 100644 --- a/FruitMachine/M6502/CPUInstructions.swift +++ b/FruitMachine/M6502/CPUInstructions.swift @@ -46,86 +46,116 @@ class CPUInstruction: NSObject { let InstructionTable: [UInt8:CPUInstruction] = [ - //INC/DEC - 0xC6: CPUInstruction(mnemonic: "DEC", cycles: 5, bytes: 2, addressingMode: .zeropage, action: Opcodes.DEC), - 0xD6: CPUInstruction(mnemonic: "DEC", cycles: 6, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.DEC), - 0xCE: CPUInstruction(mnemonic: "DEC", cycles: 6, bytes: 3, addressingMode: .absolute, action: Opcodes.DEC), - 0xDE: CPUInstruction(mnemonic: "DEC", cycles: 7, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.DEC), + //Boolean operators + 0x09: CPUInstruction(mnemonic: "ORA", cycles: 2, bytes: 2, addressingMode: .immediate, action: Opcodes.ORA), + 0x05: CPUInstruction(mnemonic: "ORA", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.ORA), + 0x15: CPUInstruction(mnemonic: "ORA", cycles: 4, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.ORA), + 0x0D: CPUInstruction(mnemonic: "ORA", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.ORA), + 0x1D: CPUInstruction(mnemonic: "ORA", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.ORA), + 0x19: CPUInstruction(mnemonic: "ORA", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_y, action: Opcodes.ORA), + 0x01: CPUInstruction(mnemonic: "ORA", cycles: 6, bytes: 2, addressingMode: .indexed_indirect, action: Opcodes.ORA), + 0x11: CPUInstruction(mnemonic: "ORA", cycles: 5, bytes: 2, addressingMode: .indirect_indexed, action: Opcodes.ORA), - 0xE6: CPUInstruction(mnemonic: "INC", cycles: 5, bytes: 2, addressingMode: .zeropage, action: Opcodes.INC), - 0xF6: CPUInstruction(mnemonic: "INC", cycles: 6, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.INC), - 0xEE: CPUInstruction(mnemonic: "INC", cycles: 6, bytes: 3, addressingMode: .absolute, action: Opcodes.INC), - 0xFE: CPUInstruction(mnemonic: "INC", cycles: 7, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.INC), + 0x49: CPUInstruction(mnemonic: "EOR", cycles: 2, bytes: 2, addressingMode: .immediate, action: Opcodes.EOR), + 0x45: CPUInstruction(mnemonic: "EOR", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.EOR), + 0x55: CPUInstruction(mnemonic: "EOR", cycles: 4, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.EOR), + 0x4D: CPUInstruction(mnemonic: "EOR", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.EOR), + 0x5D: CPUInstruction(mnemonic: "EOR", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.EOR), + 0x59: CPUInstruction(mnemonic: "EOR", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_y, action: Opcodes.EOR), + 0x41: CPUInstruction(mnemonic: "EOR", cycles: 6, bytes: 2, addressingMode: .indexed_indirect, action: Opcodes.EOR), + 0x51: CPUInstruction(mnemonic: "EOR", cycles: 5, bytes: 2, addressingMode: .indirect_indexed, action: Opcodes.EOR), + + 0x29: CPUInstruction(mnemonic: "AND", cycles: 2, bytes: 2, addressingMode: .immediate, action: Opcodes.AND), + 0x25: CPUInstruction(mnemonic: "AND", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.AND), + 0x35: CPUInstruction(mnemonic: "AND", cycles: 4, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.AND), + 0x2D: CPUInstruction(mnemonic: "AND", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.AND), + 0x3D: CPUInstruction(mnemonic: "AND", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.AND), + 0x39: CPUInstruction(mnemonic: "AND", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_y, action: Opcodes.AND), + 0x21: CPUInstruction(mnemonic: "AND", cycles: 6, bytes: 2, addressingMode: .indexed_indirect, action: Opcodes.AND), + 0x31: CPUInstruction(mnemonic: "AND", cycles: 5, bytes: 2, addressingMode: .indirect_indexed, action: Opcodes.AND), + + //INC/DEC + 0xC6: CPUInstruction(mnemonic: "DEC", cycles: 5, bytes: 2, addressingMode: .zeropage, action: Opcodes.DEC), + 0xD6: CPUInstruction(mnemonic: "DEC", cycles: 6, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.DEC), + 0xCE: CPUInstruction(mnemonic: "DEC", cycles: 6, bytes: 3, addressingMode: .absolute, action: Opcodes.DEC), + 0xDE: CPUInstruction(mnemonic: "DEC", cycles: 7, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.DEC), + + 0xE6: CPUInstruction(mnemonic: "INC", cycles: 5, bytes: 2, addressingMode: .zeropage, action: Opcodes.INC), + 0xF6: CPUInstruction(mnemonic: "INC", cycles: 6, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.INC), + 0xEE: CPUInstruction(mnemonic: "INC", cycles: 6, bytes: 3, addressingMode: .absolute, action: Opcodes.INC), + 0xFE: CPUInstruction(mnemonic: "INC", cycles: 7, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.INC), //JMP - 0x4C: CPUInstruction(mnemonic: "JMP", cycles: 3, bytes: 3, addressingMode: .absolute, action: Opcodes.JMP), - 0x6C: CPUInstruction(mnemonic: "JMP", cycles: 5, bytes: 3, addressingMode: .indirect, action: Opcodes.JMP), + 0x4C: CPUInstruction(mnemonic: "JMP", cycles: 3, bytes: 3, addressingMode: .absolute, action: Opcodes.JMP), + 0x6C: CPUInstruction(mnemonic: "JMP", cycles: 5, bytes: 3, addressingMode: .indirect, action: Opcodes.JMP), //LD instructions - 0xA9: CPUInstruction(mnemonic: "LDA", cycles: 2, bytes: 2, addressingMode: .immediate, action: Opcodes.LDA), - 0xA5: CPUInstruction(mnemonic: "LDA", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.LDA), - 0xB5: CPUInstruction(mnemonic: "LDA", cycles: 4, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.LDA), - 0xAD: CPUInstruction(mnemonic: "LDA", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.LDA), - 0xBD: CPUInstruction(mnemonic: "LDA", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.LDA), - 0xB9: CPUInstruction(mnemonic: "LDA", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_y, action: Opcodes.LDA), - 0xA1: CPUInstruction(mnemonic: "LDA", cycles: 6, bytes: 2, addressingMode: .indexed_indirect, action: Opcodes.LDA), - 0xB1: CPUInstruction(mnemonic: "LDA", cycles: 5, bytes: 2, addressingMode: .indirect_indexed, action: Opcodes.LDA), + 0xA9: CPUInstruction(mnemonic: "LDA", cycles: 2, bytes: 2, addressingMode: .immediate, action: Opcodes.LDA), + 0xA5: CPUInstruction(mnemonic: "LDA", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.LDA), + 0xB5: CPUInstruction(mnemonic: "LDA", cycles: 4, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.LDA), + 0xAD: CPUInstruction(mnemonic: "LDA", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.LDA), + 0xBD: CPUInstruction(mnemonic: "LDA", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.LDA), + 0xB9: CPUInstruction(mnemonic: "LDA", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_y, action: Opcodes.LDA), + 0xA1: CPUInstruction(mnemonic: "LDA", cycles: 6, bytes: 2, addressingMode: .indexed_indirect, action: Opcodes.LDA), + 0xB1: CPUInstruction(mnemonic: "LDA", cycles: 5, bytes: 2, addressingMode: .indirect_indexed, action: Opcodes.LDA), - 0xA2: CPUInstruction(mnemonic: "LDX", cycles: 2, bytes: 2, addressingMode: .immediate, action: Opcodes.LDX), - 0xA6: CPUInstruction(mnemonic: "LDX", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.LDX), - 0xB6: CPUInstruction(mnemonic: "LDX", cycles: 4, bytes: 2, addressingMode: .zeropage_indexed_y, action: Opcodes.LDX), - 0xAE: CPUInstruction(mnemonic: "LDX", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.LDX), - 0xBE: CPUInstruction(mnemonic: "LDX", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_y, action: Opcodes.LDX), + 0xA2: CPUInstruction(mnemonic: "LDX", cycles: 2, bytes: 2, addressingMode: .immediate, action: Opcodes.LDX), + 0xA6: CPUInstruction(mnemonic: "LDX", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.LDX), + 0xB6: CPUInstruction(mnemonic: "LDX", cycles: 4, bytes: 2, addressingMode: .zeropage_indexed_y, action: Opcodes.LDX), + 0xAE: CPUInstruction(mnemonic: "LDX", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.LDX), + 0xBE: CPUInstruction(mnemonic: "LDX", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_y, action: Opcodes.LDX), - 0xA0: CPUInstruction(mnemonic: "LDY", cycles: 2, bytes: 2, addressingMode: .immediate, action: Opcodes.LDY), - 0xA4: CPUInstruction(mnemonic: "LDY", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.LDY), - 0xB4: CPUInstruction(mnemonic: "LDY", cycles: 4, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.LDY), - 0xAC: CPUInstruction(mnemonic: "LDY", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.LDY), - 0xBC: CPUInstruction(mnemonic: "LDY", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.LDY), + 0xA0: CPUInstruction(mnemonic: "LDY", cycles: 2, bytes: 2, addressingMode: .immediate, action: Opcodes.LDY), + 0xA4: CPUInstruction(mnemonic: "LDY", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.LDY), + 0xB4: CPUInstruction(mnemonic: "LDY", cycles: 4, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.LDY), + 0xAC: CPUInstruction(mnemonic: "LDY", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.LDY), + 0xBC: CPUInstruction(mnemonic: "LDY", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.LDY), //ST functions - 0x85: CPUInstruction(mnemonic: "STA", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.STA), - 0x95: CPUInstruction(mnemonic: "STA", cycles: 4, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.STA), - 0x8D: CPUInstruction(mnemonic: "STA", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.STA), - 0x9D: CPUInstruction(mnemonic: "STA", cycles: 5, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.STA), - 0x99: CPUInstruction(mnemonic: "STA", cycles: 5, bytes: 3, addressingMode: .absolute_indexed_y, action: Opcodes.STA), - 0x81: CPUInstruction(mnemonic: "STA", cycles: 6, bytes: 2, addressingMode: .indexed_indirect, action: Opcodes.STA), - 0x91: CPUInstruction(mnemonic: "STA", cycles: 6, bytes: 2, addressingMode: .indirect_indexed, action: Opcodes.STA), + 0x85: CPUInstruction(mnemonic: "STA", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.STA), + 0x95: CPUInstruction(mnemonic: "STA", cycles: 4, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.STA), + 0x8D: CPUInstruction(mnemonic: "STA", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.STA), + 0x9D: CPUInstruction(mnemonic: "STA", cycles: 5, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.STA), + 0x99: CPUInstruction(mnemonic: "STA", cycles: 5, bytes: 3, addressingMode: .absolute_indexed_y, action: Opcodes.STA), + 0x81: CPUInstruction(mnemonic: "STA", cycles: 6, bytes: 2, addressingMode: .indexed_indirect, action: Opcodes.STA), + 0x91: CPUInstruction(mnemonic: "STA", cycles: 6, bytes: 2, addressingMode: .indirect_indexed, action: Opcodes.STA), - 0x86: CPUInstruction(mnemonic: "STX", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.STX), - 0x96: CPUInstruction(mnemonic: "STX", cycles: 4, bytes: 2, addressingMode: .zeropage_indexed_y, action: Opcodes.STX), - 0x8E: CPUInstruction(mnemonic: "STX", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.STX), + 0x86: CPUInstruction(mnemonic: "STX", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.STX), + 0x96: CPUInstruction(mnemonic: "STX", cycles: 4, bytes: 2, addressingMode: .zeropage_indexed_y, action: Opcodes.STX), + 0x8E: CPUInstruction(mnemonic: "STX", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.STX), - 0x84: CPUInstruction(mnemonic: "STY", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.STY), - 0x94: CPUInstruction(mnemonic: "STY", cycles: 4, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.STY), - 0x8C: CPUInstruction(mnemonic: "STY", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.STY), + 0x84: CPUInstruction(mnemonic: "STY", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.STY), + 0x94: CPUInstruction(mnemonic: "STY", cycles: 4, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.STY), + 0x8C: CPUInstruction(mnemonic: "STY", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.STY), //Register functions - 0x88: CPUInstruction(mnemonic: "DEY", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.DEY), - 0x8A: CPUInstruction(mnemonic: "TXA", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.TXA), - 0x98: CPUInstruction(mnemonic: "TYA", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.TYA), - 0xA8: CPUInstruction(mnemonic: "TAY", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.TAY), - 0xAA: CPUInstruction(mnemonic: "TAX", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.TAX), - 0xC8: CPUInstruction(mnemonic: "INY", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.INY), - 0xCA: CPUInstruction(mnemonic: "DEX", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.DEX), - 0xE8: CPUInstruction(mnemonic: "INX", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.INX), + 0x88: CPUInstruction(mnemonic: "DEY", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.DEY), + 0x8A: CPUInstruction(mnemonic: "TXA", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.TXA), + 0x98: CPUInstruction(mnemonic: "TYA", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.TYA), + 0xA8: CPUInstruction(mnemonic: "TAY", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.TAY), + 0xAA: CPUInstruction(mnemonic: "TAX", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.TAX), + 0xC8: CPUInstruction(mnemonic: "INY", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.INY), + 0xCA: CPUInstruction(mnemonic: "DEX", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.DEX), + 0xE8: CPUInstruction(mnemonic: "INX", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.INX), //Processor flag instructions - 0x18: CPUInstruction(mnemonic: "CLC", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.CLC), - 0x38: CPUInstruction(mnemonic: "SEC", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.SEC), - 0x58: CPUInstruction(mnemonic: "CLI", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.CLI), - 0x78: CPUInstruction(mnemonic: "SEI", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.SEI), - 0xB8: CPUInstruction(mnemonic: "CLV", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.CLV), - 0xD8: CPUInstruction(mnemonic: "CLD", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.CLD), - 0xF8: CPUInstruction(mnemonic: "SED", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.SED), + 0x18: CPUInstruction(mnemonic: "CLC", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.CLC), + 0x38: CPUInstruction(mnemonic: "SEC", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.SEC), + 0x58: CPUInstruction(mnemonic: "CLI", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.CLI), + 0x78: CPUInstruction(mnemonic: "SEI", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.SEI), + 0xB8: CPUInstruction(mnemonic: "CLV", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.CLV), + 0xD8: CPUInstruction(mnemonic: "CLD", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.CLD), + 0xF8: CPUInstruction(mnemonic: "SED", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.SED), //Stack instructions - 0x9A: CPUInstruction(mnemonic: "TXS", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.TXS), - 0xBA: CPUInstruction(mnemonic: "TSX", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.TSX), - 0x48: CPUInstruction(mnemonic: "PHA", cycles: 3, bytes: 1, addressingMode: .implied, action: Opcodes.PHA), - 0x68: CPUInstruction(mnemonic: "PLA", cycles: 4, bytes: 1, addressingMode: .implied, action: Opcodes.PLA), - 0x08: CPUInstruction(mnemonic: "PHP", cycles: 3, bytes: 1, addressingMode: .implied, action: Opcodes.PHP), - 0x28: CPUInstruction(mnemonic: "PLP", cycles: 4, bytes: 1, addressingMode: .implied, action: Opcodes.PLP), + 0x9A: CPUInstruction(mnemonic: "TXS", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.TXS), + 0xBA: CPUInstruction(mnemonic: "TSX", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.TSX), + 0x48: CPUInstruction(mnemonic: "PHA", cycles: 3, bytes: 1, addressingMode: .implied, action: Opcodes.PHA), + 0x68: CPUInstruction(mnemonic: "PLA", cycles: 4, bytes: 1, addressingMode: .implied, action: Opcodes.PLA), + 0x08: CPUInstruction(mnemonic: "PHP", cycles: 3, bytes: 1, addressingMode: .implied, action: Opcodes.PHP), + 0x28: CPUInstruction(mnemonic: "PLP", cycles: 4, bytes: 1, addressingMode: .implied, action: Opcodes.PLP), - 0xEA: CPUInstruction(mnemonic: "NOP", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.NOP), + 0x20: CPUInstruction(mnemonic: "JSR", cycles: 6, bytes: 3, addressingMode: .absolute, action: Opcodes.JSR), + + 0xEA: CPUInstruction(mnemonic: "NOP", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.NOP), ] diff --git a/FruitMachine/M6502/Opcodes.swift b/FruitMachine/M6502/Opcodes.swift index a365c01..bf27792 100644 --- a/FruitMachine/M6502/Opcodes.swift +++ b/FruitMachine/M6502/Opcodes.swift @@ -8,12 +8,25 @@ import Cocoa -func stackPointerAsUInt16(state: CPUState) -> UInt16 { - return 0x0100 | UInt16(state.stack_pointer); -} +extension CPUState { -func zpAsUInt16(address: UInt8) -> UInt16 { - return 0x0000 | UInt16(address) + func pushByte(data: UInt8) -> Void { + memoryInterface.writeByte(offset: stackPointerAsUInt16(), value: data) + stack_pointer = stack_pointer &- 1 + } + + func pushWord(data: UInt16) -> Void { + let low = UInt8(data & 0x00FF) + let high = UInt8(data & 0xFF00) + + pushByte(data: low) + pushByte(data: high) + } + + func stackPointerAsUInt16() -> UInt16 { + return 0x0100 | UInt16(stack_pointer); + } + } func getOperandByteForAddressingMode(state: CPUState, mode: AddressingMode) -> UInt8 { @@ -110,7 +123,7 @@ class Opcodes: NSObject { let address: UInt16 if(addressingMode == .zeropage || addressingMode == .zeropage_indexed_x) { - address = zpAsUInt16(address: state.getOperandByte()) + address = AddressConversions.zeroPageAsUInt16(address: state.getOperandByte()) state.memoryInterface.writeByte(offset: address, value: state.accumulator) } @@ -128,7 +141,7 @@ class Opcodes: NSObject { let address: UInt16 if(addressingMode == .zeropage || addressingMode == .zeropage_indexed_y) { - address = zpAsUInt16(address: state.getOperandByte()) + address = AddressConversions.zeroPageAsUInt16(address: state.getOperandByte()) state.memoryInterface.writeByte(offset: address, value: state.index_x) } @@ -146,7 +159,7 @@ class Opcodes: NSObject { let address: UInt16 if(addressingMode == .zeropage || addressingMode == .zeropage_indexed_x) { - address = zpAsUInt16(address: state.getOperandByte()) + address = AddressConversions.zeroPageAsUInt16(address: state.getOperandByte()) state.memoryInterface.writeByte(offset: address, value: state.index_y) } @@ -222,7 +235,7 @@ class Opcodes: NSObject { var val: UInt8 if(addressingMode == .zeropage || addressingMode == .zeropage_indexed_x) { - address = zpAsUInt16(address: state.getOperandByte()) + address = AddressConversions.zeroPageAsUInt16(address: state.getOperandByte()) val = state.memoryInterface.readByte(offset: address) } @@ -247,7 +260,7 @@ class Opcodes: NSObject { var val: UInt8 if(addressingMode == .zeropage || addressingMode == .zeropage_indexed_x) { - address = zpAsUInt16(address: state.getOperandByte()) + address = AddressConversions.zeroPageAsUInt16(address: state.getOperandByte()) val = state.memoryInterface.readByte(offset: address) } @@ -273,7 +286,7 @@ class Opcodes: NSObject { state.updateZeroFlag(value: data) state.updateNegativeFlag(value: data) - state.status_register.carry = !state.status_register.negative //? check this + state.status_register.carry = (data >= 0) } static func CPX(state: CPUState, addressingMode: AddressingMode) -> Void { @@ -281,7 +294,7 @@ class Opcodes: NSObject { state.updateZeroFlag(value: data) state.updateNegativeFlag(value: data) - state.status_register.carry = !state.status_register.negative //? check this + state.status_register.carry = (data >= 0) } static func CPY(state: CPUState, addressingMode: AddressingMode) -> Void { @@ -289,7 +302,29 @@ class Opcodes: NSObject { state.updateZeroFlag(value: data) state.updateNegativeFlag(value: data) - state.status_register.carry = !state.status_register.negative //? check this + state.status_register.carry = (data >= 0) + } + + //Boolean operators + static func EOR(state: CPUState, addressingMode: AddressingMode) -> Void { + state.accumulator = state.accumulator ^ getOperandByteForAddressingMode(state: state, mode: addressingMode) + + state.updateZeroFlag(value: state.accumulator) + state.updateNegativeFlag(value: state.accumulator) + } + + static func AND(state: CPUState, addressingMode: AddressingMode) -> Void { + state.accumulator = state.accumulator & getOperandByteForAddressingMode(state: state, mode: addressingMode) + + state.updateZeroFlag(value: state.accumulator) + state.updateNegativeFlag(value: state.accumulator) + } + + static func ORA(state: CPUState, addressingMode: AddressingMode) -> Void { + state.accumulator = state.accumulator | getOperandByteForAddressingMode(state: state, mode: addressingMode) + + state.updateZeroFlag(value: state.accumulator) + state.updateNegativeFlag(value: state.accumulator) } //Processor flag instructions @@ -334,26 +369,26 @@ class Opcodes: NSObject { } static func PHA(state: CPUState, addressingMode: AddressingMode) -> Void { - state.memoryInterface.writeByte(offset: stackPointerAsUInt16(state: state), value: state.accumulator) + state.memoryInterface.writeByte(offset: state.stackPointerAsUInt16(), 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: stackPointerAsUInt16(state: state)) + state.accumulator = state.memoryInterface.readByte(offset: state.stackPointerAsUInt16()) state.updateZeroFlag(value: state.accumulator); state.updateNegativeFlag(value: state.accumulator); } static func PHP(state: CPUState, addressingMode: AddressingMode) -> Void { - state.memoryInterface.writeByte(offset: stackPointerAsUInt16(state: state), value: state.status_register.asByte()) + state.memoryInterface.writeByte(offset: state.stackPointerAsUInt16(), 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.fromByte(state: state.memoryInterface.readByte(offset: stackPointerAsUInt16(state: state))) + state.status_register.fromByte(state: state.memoryInterface.readByte(offset: state.stackPointerAsUInt16())) } //Misc @@ -361,6 +396,11 @@ class Opcodes: NSObject { state.program_counter = getOperandWordForAddressingMode(state: state, mode: addressingMode) } + static func JSR(state: CPUState, addressingMode: AddressingMode) -> Void { + //JSR pushes the address-1 of the next operation on to the stack before transferring program control to the following address + state.pushWord(data: state.program_counter + 3) + state.program_counter = state.getOperandWord() + } static func NOP(state: CPUState, addressingMode: AddressingMode) -> Void {} }