more instructions, just need ADC/SBC and the shift instructions now

This commit is contained in:
Luigi Thirty 2017-07-23 14:50:46 -04:00
parent da828a5d36
commit eb9f02758b
3 changed files with 104 additions and 2 deletions

View File

@ -155,7 +155,20 @@ let InstructionTable: [UInt8:CPUInstruction] = [
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),
//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),
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),
]

View File

@ -123,6 +123,8 @@ class CPUState: NSObject {
var memoryInterface: MemoryInterface
var branch_was_taken: Bool
override init() {
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)
memoryInterface = MemoryInterface()
//Some instructions incur a 1-cycle penalty if crossing a page boundary.
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] {
@ -212,6 +218,10 @@ class CPUState: NSObject {
self.cycles += 1
self.page_boundary_crossed = false
}
if(self.branch_was_taken) {
self.cycles += 1
self.branch_was_taken = false
}
if(operation!.mnemonic != "JMP") {
self.program_counter = UInt16(Int(self.program_counter) + operation!.bytes)

View File

@ -10,6 +10,18 @@ import Cocoa
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 {
memoryInterface.writeByte(offset: stackPointerAsUInt16(), value: data)
stack_pointer = stack_pointer &- 1
@ -27,6 +39,15 @@ extension CPUState {
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 {
@ -391,16 +412,74 @@ class Opcodes: NSObject {
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
static func JMP(state: CPUState, addressingMode: AddressingMode) -> Void {
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.pushWord(data: state.program_counter - 1)
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 {}
}