mirror of
https://github.com/Luigi30/FruitMachine-Swift.git
synced 2025-02-16 23:31:01 +00:00
more instructions, just need ADC/SBC and the shift instructions now
This commit is contained in:
parent
da828a5d36
commit
eb9f02758b
@ -155,7 +155,20 @@ let InstructionTable: [UInt8:CPUInstruction] = [
|
|||||||
0x08: CPUInstruction(mnemonic: "PHP", cycles: 3, bytes: 1, addressingMode: .implied, action: Opcodes.PHP),
|
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),
|
0x28: CPUInstruction(mnemonic: "PLP", cycles: 4, bytes: 1, addressingMode: .implied, action: Opcodes.PLP),
|
||||||
|
|
||||||
|
//Branch instructions
|
||||||
|
0x10: CPUInstruction(mnemonic: "BPL", cycles: 2, bytes: 2, addressingMode: .relative, action: Opcodes.BPL),
|
||||||
|
0x30: CPUInstruction(mnemonic: "BMI", cycles: 2, bytes: 2, addressingMode: .relative, action: Opcodes.BMI),
|
||||||
|
0x50: CPUInstruction(mnemonic: "BVC", cycles: 2, bytes: 2, addressingMode: .relative, action: Opcodes.BVC),
|
||||||
|
0x70: CPUInstruction(mnemonic: "BVS", cycles: 2, bytes: 2, addressingMode: .relative, action: Opcodes.BVS),
|
||||||
|
0x90: CPUInstruction(mnemonic: "BCC", cycles: 2, bytes: 2, addressingMode: .relative, action: Opcodes.BCC),
|
||||||
|
0xB0: CPUInstruction(mnemonic: "BCS", cycles: 2, bytes: 2, addressingMode: .relative, action: Opcodes.BCS),
|
||||||
|
0xD0: CPUInstruction(mnemonic: "BNE", cycles: 2, bytes: 2, addressingMode: .relative, action: Opcodes.BNE),
|
||||||
|
0xF0: CPUInstruction(mnemonic: "BEQ", cycles: 2, bytes: 2, addressingMode: .relative, action: Opcodes.BEQ),
|
||||||
|
|
||||||
0x20: CPUInstruction(mnemonic: "JSR", cycles: 6, bytes: 3, addressingMode: .absolute, action: Opcodes.JSR),
|
0x20: CPUInstruction(mnemonic: "JSR", cycles: 6, bytes: 3, addressingMode: .absolute, action: Opcodes.JSR),
|
||||||
|
0x60: CPUInstruction(mnemonic: "RTS", cycles: 6, bytes: 1, addressingMode: .implied, action: Opcodes.RTS),
|
||||||
|
|
||||||
|
0x00: CPUInstruction(mnemonic: "BRK", cycles: 7, bytes: 1, addressingMode: .implied, action: Opcodes.BRK),
|
||||||
|
|
||||||
0xEA: CPUInstruction(mnemonic: "NOP", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.NOP),
|
0xEA: CPUInstruction(mnemonic: "NOP", cycles: 2, bytes: 1, addressingMode: .implied, action: Opcodes.NOP),
|
||||||
]
|
]
|
||||||
|
@ -123,6 +123,8 @@ class CPUState: NSObject {
|
|||||||
|
|
||||||
var memoryInterface: MemoryInterface
|
var memoryInterface: MemoryInterface
|
||||||
|
|
||||||
|
var branch_was_taken: Bool
|
||||||
|
|
||||||
override init() {
|
override init() {
|
||||||
cycles = 0
|
cycles = 0
|
||||||
|
|
||||||
@ -136,7 +138,11 @@ class CPUState: NSObject {
|
|||||||
status_register = StatusRegister(negative: false, overflow: false, brk: false, decimal: false, irq_disable: false, zero: false, carry: false)
|
status_register = StatusRegister(negative: false, overflow: false, brk: false, decimal: false, irq_disable: false, zero: false, carry: false)
|
||||||
memoryInterface = MemoryInterface()
|
memoryInterface = MemoryInterface()
|
||||||
|
|
||||||
|
//Some instructions incur a 1-cycle penalty if crossing a page boundary.
|
||||||
page_boundary_crossed = false
|
page_boundary_crossed = false
|
||||||
|
//Branches incur a 1-cycle penalty if taken plus the page boundary penalty if necessary.
|
||||||
|
branch_was_taken = false
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func disassemble(fromAddress: UInt16, length: UInt16) -> [Disassembly] {
|
func disassemble(fromAddress: UInt16, length: UInt16) -> [Disassembly] {
|
||||||
@ -212,6 +218,10 @@ class CPUState: NSObject {
|
|||||||
self.cycles += 1
|
self.cycles += 1
|
||||||
self.page_boundary_crossed = false
|
self.page_boundary_crossed = false
|
||||||
}
|
}
|
||||||
|
if(self.branch_was_taken) {
|
||||||
|
self.cycles += 1
|
||||||
|
self.branch_was_taken = false
|
||||||
|
}
|
||||||
|
|
||||||
if(operation!.mnemonic != "JMP") {
|
if(operation!.mnemonic != "JMP") {
|
||||||
self.program_counter = UInt16(Int(self.program_counter) + operation!.bytes)
|
self.program_counter = UInt16(Int(self.program_counter) + operation!.bytes)
|
||||||
|
@ -10,6 +10,18 @@ import Cocoa
|
|||||||
|
|
||||||
extension CPUState {
|
extension CPUState {
|
||||||
|
|
||||||
|
func popByte() -> UInt8 {
|
||||||
|
stack_pointer = stack_pointer &+ 1
|
||||||
|
return memoryInterface.readByte(offset: stackPointerAsUInt16())
|
||||||
|
}
|
||||||
|
|
||||||
|
func popWord() -> UInt16 {
|
||||||
|
let low = popByte()
|
||||||
|
let high = popByte()
|
||||||
|
|
||||||
|
return (UInt16(high) << 8) | UInt16(low)
|
||||||
|
}
|
||||||
|
|
||||||
func pushByte(data: UInt8) -> Void {
|
func pushByte(data: UInt8) -> Void {
|
||||||
memoryInterface.writeByte(offset: stackPointerAsUInt16(), value: data)
|
memoryInterface.writeByte(offset: stackPointerAsUInt16(), value: data)
|
||||||
stack_pointer = stack_pointer &- 1
|
stack_pointer = stack_pointer &- 1
|
||||||
@ -27,6 +39,15 @@ extension CPUState {
|
|||||||
return 0x0100 | UInt16(stack_pointer);
|
return 0x0100 | UInt16(stack_pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func doBranch() {
|
||||||
|
let distance = getOperandByte()
|
||||||
|
|
||||||
|
if(((program_counter & 0x00FF) + distance) > 0x0100) {
|
||||||
|
page_boundary_crossed = true
|
||||||
|
}
|
||||||
|
program_counter = program_counter + distance
|
||||||
|
branch_was_taken = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getOperandByteForAddressingMode(state: CPUState, mode: AddressingMode) -> UInt8 {
|
func getOperandByteForAddressingMode(state: CPUState, mode: AddressingMode) -> UInt8 {
|
||||||
@ -391,16 +412,74 @@ class Opcodes: NSObject {
|
|||||||
state.status_register.fromByte(state: state.memoryInterface.readByte(offset: state.stackPointerAsUInt16()))
|
state.status_register.fromByte(state: state.memoryInterface.readByte(offset: state.stackPointerAsUInt16()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static func BPL(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||||
|
if(!state.status_register.negative) {
|
||||||
|
state.doBranch()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func BMI(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||||
|
if(state.status_register.negative) {
|
||||||
|
state.doBranch()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func BVC(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||||
|
if(!state.status_register.overflow) {
|
||||||
|
state.doBranch()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func BVS(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||||
|
if(state.status_register.overflow) {
|
||||||
|
state.doBranch()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func BCC(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||||
|
if(!state.status_register.carry) {
|
||||||
|
state.doBranch()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func BCS(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||||
|
if(state.status_register.carry) {
|
||||||
|
state.doBranch()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func BNE(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||||
|
if(!state.status_register.zero) {
|
||||||
|
state.doBranch()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func BEQ(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||||
|
if(state.status_register.zero) {
|
||||||
|
state.doBranch()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Misc
|
//Misc
|
||||||
static func JMP(state: CPUState, addressingMode: AddressingMode) -> Void {
|
static func JMP(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||||
state.program_counter = getOperandWordForAddressingMode(state: state, mode: addressingMode)
|
state.program_counter = getOperandWordForAddressingMode(state: state, mode: addressingMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
static func JSR(state: CPUState, addressingMode: AddressingMode) -> Void {
|
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 - 1)
|
||||||
state.pushWord(data: state.program_counter + 3)
|
|
||||||
state.program_counter = state.getOperandWord()
|
state.program_counter = state.getOperandWord()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static func RTS(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||||
|
state.program_counter = state.popWord() + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
static func BRK(state: CPUState, addressingMode: AddressingMode) -> Void {
|
||||||
|
state.status_register.brk = true
|
||||||
|
state.pushWord(data: state.program_counter)
|
||||||
|
state.pushByte(data: state.status_register.asByte())
|
||||||
|
state.program_counter = state.memoryInterface.readWord(offset: 0xFFFE)
|
||||||
|
}
|
||||||
|
|
||||||
static func NOP(state: CPUState, addressingMode: AddressingMode) -> Void {}
|
static func NOP(state: CPUState, addressingMode: AddressingMode) -> Void {}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user