more instructions work

This commit is contained in:
Luigi Thirty 2017-07-23 20:40:48 -04:00
parent eb9f02758b
commit dc0d454a12
5 changed files with 223 additions and 8 deletions

View File

@ -21,6 +21,16 @@ class DebuggerViewController: NSViewController {
let CPU = CPUState.sharedInstance
var disassembly: [Disassembly] = [Disassembly]()
func highlightCurrentInstruction() -> Bool {
for (index, instruction) in disassembly.enumerated() {
if(instruction.address == CPU.program_counter) {
debuggerTableView.selectRowIndexes(NSIndexSet(index: index) as IndexSet, byExtendingSelection: false)
return true //instruction found
}
}
return false //instruction not found
}
func updateCPUStatusFields() {
text_CPU_A.stringValue = String(format:"%02X", CPU.accumulator)
text_CPU_X.stringValue = String(format:"%02X", CPU.index_x)
@ -28,6 +38,11 @@ class DebuggerViewController: NSViewController {
text_CPU_IP.stringValue = String(format:"%04X", CPU.program_counter)
text_CPU_SR.stringValue = String(format:"%02X", CPU.stack_pointer)
text_CPU_Flags.stringValue = String(CPU.status_register.asString())
if(!highlightCurrentInstruction()) {
disassembly = CPU.disassemble(fromAddress: CPU.program_counter, length: 256)
highlightCurrentInstruction()
}
}
override func viewDidLoad() {
@ -37,8 +52,10 @@ class DebuggerViewController: NSViewController {
debuggerTableView.dataSource = self
CPU.memoryInterface.loadBinary(path: "/Users/luigi/6502/test.bin")
CPU.performReset()
CPU.program_counter = 0x400 //entry point for the test program
updateCPUStatusFields()
disassembly = CPU.disassemble(fromAddress: 0x0000, length: 16)
disassembly = CPU.disassemble(fromAddress: CPU.program_counter, length: 10000)
debuggerTableView.reloadData()
// Do any additional setup after loading the view.

View File

@ -46,6 +46,16 @@ class CPUInstruction: NSObject {
let InstructionTable: [UInt8:CPUInstruction] = [
//ADC/SBC
0x69: CPUInstruction(mnemonic: "ADC", cycles: 2, bytes: 2, addressingMode: .immediate, action: Opcodes.ADC),
0x65: CPUInstruction(mnemonic: "ADC", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.ADC),
0x75: CPUInstruction(mnemonic: "ADC", cycles: 4, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.ADC),
0x6D: CPUInstruction(mnemonic: "ADC", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.ADC),
0x7D: CPUInstruction(mnemonic: "ADC", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.ADC),
0x79: CPUInstruction(mnemonic: "ADC", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_y, action: Opcodes.ADC),
0x61: CPUInstruction(mnemonic: "ADC", cycles: 6, bytes: 2, addressingMode: .indexed_indirect, action: Opcodes.ADC),
0x71: CPUInstruction(mnemonic: "ADC", cycles: 5, bytes: 2, addressingMode: .indirect_indexed, action: Opcodes.ADC),
//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),
@ -74,6 +84,34 @@ let InstructionTable: [UInt8:CPUInstruction] = [
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),
//Bitwise operations
0x24: CPUInstruction(mnemonic: "BIT", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.BIT),
0x2C: CPUInstruction(mnemonic: "BIT", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.BIT),
0x0A: CPUInstruction(mnemonic: "ASL", cycles: 2, bytes: 1, addressingMode: .accumulator, action: Opcodes.ASL),
0x06: CPUInstruction(mnemonic: "ASL", cycles: 5, bytes: 2, addressingMode: .zeropage, action: Opcodes.ASL),
0x16: CPUInstruction(mnemonic: "ASL", cycles: 6, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.ASL),
0x0E: CPUInstruction(mnemonic: "ASL", cycles: 6, bytes: 3, addressingMode: .absolute, action: Opcodes.ASL),
0x1E: CPUInstruction(mnemonic: "ASL", cycles: 7, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.ASL),
0x4A: CPUInstruction(mnemonic: "LSR", cycles: 2, bytes: 1, addressingMode: .accumulator, action: Opcodes.LSR),
0x46: CPUInstruction(mnemonic: "LSR", cycles: 5, bytes: 2, addressingMode: .zeropage, action: Opcodes.LSR),
0x56: CPUInstruction(mnemonic: "LSR", cycles: 6, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.LSR),
0x4E: CPUInstruction(mnemonic: "LSR", cycles: 6, bytes: 3, addressingMode: .absolute, action: Opcodes.LSR),
0x5E: CPUInstruction(mnemonic: "LSR", cycles: 7, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.LSR),
0x2A: CPUInstruction(mnemonic: "ROL", cycles: 2, bytes: 1, addressingMode: .accumulator, action: Opcodes.ROL),
0x26: CPUInstruction(mnemonic: "ROL", cycles: 5, bytes: 2, addressingMode: .zeropage, action: Opcodes.ROL),
0x36: CPUInstruction(mnemonic: "ROL", cycles: 6, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.ROL),
0x2E: CPUInstruction(mnemonic: "ROL", cycles: 6, bytes: 3, addressingMode: .absolute, action: Opcodes.ROL),
0x3E: CPUInstruction(mnemonic: "ROL", cycles: 7, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.ROL),
0x6A: CPUInstruction(mnemonic: "ROL", cycles: 2, bytes: 1, addressingMode: .accumulator, action: Opcodes.ROR),
0x66: CPUInstruction(mnemonic: "ROL", cycles: 5, bytes: 2, addressingMode: .zeropage, action: Opcodes.ROR),
0x76: CPUInstruction(mnemonic: "ROL", cycles: 6, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.ROR),
0x6E: CPUInstruction(mnemonic: "ROL", cycles: 6, bytes: 3, addressingMode: .absolute, action: Opcodes.ROR),
0x7E: CPUInstruction(mnemonic: "ROL", cycles: 7, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.ROR),
//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),
@ -128,6 +166,24 @@ let InstructionTable: [UInt8:CPUInstruction] = [
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),
//Compare functions
0xC9: CPUInstruction(mnemonic: "CMP", cycles: 2, bytes: 2, addressingMode: .immediate, action: Opcodes.CMP),
0xC5: CPUInstruction(mnemonic: "CMP", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.CMP),
0xD5: CPUInstruction(mnemonic: "CMP", cycles: 4, bytes: 2, addressingMode: .zeropage_indexed_x, action: Opcodes.CMP),
0xCD: CPUInstruction(mnemonic: "CMP", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.CMP),
0xDD: CPUInstruction(mnemonic: "CMP", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_x, action: Opcodes.CMP),
0xD9: CPUInstruction(mnemonic: "CMP", cycles: 4, bytes: 3, addressingMode: .absolute_indexed_y, action: Opcodes.CMP),
0xC1: CPUInstruction(mnemonic: "CMP", cycles: 6, bytes: 2, addressingMode: .indexed_indirect, action: Opcodes.CMP),
0xD1: CPUInstruction(mnemonic: "CMP", cycles: 5, bytes: 2, addressingMode: .indirect_indexed, action: Opcodes.CMP),
0xE0: CPUInstruction(mnemonic: "CPX", cycles: 2, bytes: 2, addressingMode: .immediate, action: Opcodes.CPX),
0xE4: CPUInstruction(mnemonic: "CPX", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.CPX),
0xEC: CPUInstruction(mnemonic: "CPX", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.CPX),
0xC0: CPUInstruction(mnemonic: "CPY", cycles: 2, bytes: 2, addressingMode: .immediate, action: Opcodes.CPY),
0xC4: CPUInstruction(mnemonic: "CPY", cycles: 3, bytes: 2, addressingMode: .zeropage, action: Opcodes.CPY),
0xCC: CPUInstruction(mnemonic: "CPY", cycles: 4, bytes: 3, addressingMode: .absolute, action: Opcodes.CPY),
//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),

View File

@ -77,7 +77,7 @@ struct StatusRegister {
}
func asByte() -> UInt8 {
var val: UInt8 = 0x00
var val: UInt8 = 0x20 //unused bit is hardwired to 1
if(negative) {
val |= 0x80
@ -106,6 +106,10 @@ struct StatusRegister {
}
class CPUState: NSObject {
let NMI_VECTOR: UInt16 = 0xFFFA
let RESET_VECTOR: UInt16 = 0xFFFC
let IRQ_VECTOR: UInt16 = 0xFFFE
static var sharedInstance = CPUState()
var cycles: Int
@ -228,6 +232,12 @@ class CPUState: NSObject {
}
}
func performReset() {
program_counter = memoryInterface.readWord(offset: RESET_VECTOR)
stack_pointer = 0xFF
status_register.irq_disable = true
}
func updateNegativeFlag(value: UInt8) {
status_register.negative = (value & 0x80 == 0x80)
}

View File

@ -10,6 +10,6 @@ import Cocoa
extension UInt16 {
static func + (left: UInt16, right: UInt8) -> UInt16 {
return left + right
return left + UInt16(right)
}
}

View File

@ -40,12 +40,19 @@ extension CPUState {
}
func doBranch() {
let distance = getOperandByte()
let distance = Int8(bitPattern: getOperandByte())
if(((program_counter & 0x00FF) + distance) > 0x0100) {
page_boundary_crossed = true
if(distance < 0) {
if((program_counter & 0x00FF) - UInt16(abs(Int16(distance))) > 0x8000) {
page_boundary_crossed = true
}
} else {
if((program_counter & 0x00FF) + UInt16(abs(Int16(distance)))ß > 0x0100) {
page_boundary_crossed = true
}
}
program_counter = program_counter + distance
program_counter = UInt16(Int(program_counter) + Int(distance))
branch_was_taken = true
}
}
@ -115,10 +122,35 @@ func getOperandWordForAddressingMode(state: CPUState, mode: AddressingMode) -> U
}
func hex2bcd(hex: UInt8) -> UInt8 {
var y: UInt8 = (hex / 10) << 4
y = y | (hex % 10)
return y
}
/* */
class Opcodes: NSObject {
static func ADC(state: CPUState, addressingMode: AddressingMode) -> Void {
let operand = UInt8(getOperandByteForAddressingMode(state: state, mode: addressingMode))
var t16: UInt16 = UInt16(state.accumulator &+ operand) + UInt16((state.status_register.carry ? UInt8(1) : UInt8(0)))
let t8: UInt8 = UInt8(t16 & 0xFF)
state.status_register.overflow = (~(state.accumulator ^ operand) & (state.accumulator ^ t8) & 0x80) == 0x80
state.status_register.zero = (t8 == 0)
state.status_register.negative = (t8 & 0x80) == 0x80
if(state.status_register.decimal) {
t16 = UInt16(hex2bcd(hex: state.accumulator) + hex2bcd(hex: operand) + (state.status_register.carry ? UInt8(1) : UInt8(0)))
} else {
state.status_register.carry = (t16 > 255)
}
state.accumulator = (UInt8(t16 & 0xFF))
}
static func LDA(state: CPUState, addressingMode: AddressingMode) -> Void {
state.accumulator = getOperandByteForAddressingMode(state: state, mode: addressingMode)
@ -323,7 +355,7 @@ class Opcodes: NSObject {
state.updateZeroFlag(value: data)
state.updateNegativeFlag(value: data)
state.status_register.carry = (data >= 0)
state.status_register.carry = (data >= 0)
}
//Boolean operators
@ -348,6 +380,106 @@ class Opcodes: NSObject {
state.updateNegativeFlag(value: state.accumulator)
}
//Bitwise operators
static func BIT(state: CPUState, addressingMode: AddressingMode) -> Void {
let operand = getOperandByteForAddressingMode(state: state, mode: addressingMode)
let data = state.accumulator & operand
state.updateZeroFlag(value: data)
state.updateNegativeFlag(value: operand)
state.status_register.overflow = (state.accumulator & UInt8(0x40)) == 0x40
}
static func ASL(state: CPUState, addressingMode: AddressingMode) -> Void {
let operand: UInt8
if(addressingMode == .implied) {
operand = state.accumulator
state.status_register.carry = ((operand & 0x80) == 0x80)
state.accumulator = (state.accumulator &<< 1) & 0xFE
state.updateZeroFlag(value: state.accumulator)
state.updateNegativeFlag(value: state.accumulator)
} else {
let address = getOperandWordForAddressingMode(state: state, mode: addressingMode)
var data = state.memoryInterface.readByte(offset: address)
state.status_register.carry = (data & 0x80) == 0x80
data = (data &<< 1) & 0xFE
state.memoryInterface.writeByte(offset: address, value: data)
state.updateZeroFlag(value: data)
state.updateNegativeFlag(value: data)
}
}
static func LSR(state: CPUState, addressingMode: AddressingMode) -> Void {
let operand: UInt8
if(addressingMode == .implied) {
operand = state.accumulator
state.status_register.carry = ((operand & 0x01) == 0x01)
state.accumulator = (state.accumulator &>> 1) & 0x7F
state.updateZeroFlag(value: state.accumulator)
state.status_register.negative = false
} else {
let address = getOperandWordForAddressingMode(state: state, mode: addressingMode)
var data = state.memoryInterface.readByte(offset: address)
state.status_register.carry = (data & 0x01) == 0x01
data = (data &>> 1) & 0x7F
state.memoryInterface.writeByte(offset: address, value: data)
state.updateZeroFlag(value: data)
state.updateNegativeFlag(value: data)
}
}
static func ROL(state: CPUState, addressingMode: AddressingMode) -> Void {
let operand: UInt8
if(addressingMode == .implied) {
operand = state.accumulator
state.accumulator = (state.accumulator &<< 1) & 0xFE
state.accumulator = state.accumulator | (state.status_register.carry ? 0x01 : 0x00)
state.status_register.carry = ((operand & 0x80) == 0x80)
state.updateZeroFlag(value: state.accumulator)
state.status_register.negative = (state.accumulator & 0x80) == 0x80
} else {
let address = getOperandWordForAddressingMode(state: state, mode: addressingMode)
var data = state.memoryInterface.readByte(offset: address)
data = (data &<< 1) & 0xFE
data = data | (state.status_register.carry ? 0x01 : 0x00)
state.memoryInterface.writeByte(offset: address, value: data)
state.status_register.carry = (data & 0x80) == 0x80
state.updateZeroFlag(value: data)
state.status_register.negative = (data & 0x80) == 0x80
}
}
static func ROR(state: CPUState, addressingMode: AddressingMode) -> Void {
let operand: UInt8
if(addressingMode == .implied) {
operand = state.accumulator
state.status_register.carry = ((operand & 0x01) == 0x01)
state.accumulator = (state.accumulator &>> 1) & 0x7F
state.accumulator = state.accumulator | (state.status_register.carry ? 0x80 : 0x00)
state.updateZeroFlag(value: state.accumulator)
state.status_register.negative = (state.accumulator & 0x80) == 0x80
} else {
let address = getOperandWordForAddressingMode(state: state, mode: addressingMode)
var data = state.memoryInterface.readByte(offset: address)
state.status_register.carry = (data & 0x01) == 0x01
data = (data &>> 1) & 0x7F
data = data | (state.status_register.carry ? 0x80 : 0x00)
state.memoryInterface.writeByte(offset: address, value: data)
state.updateZeroFlag(value: data)
state.status_register.negative = (data & 0x80) == 0x80
}
}
//Processor flag instructions
static func CLC(state: CPUState, addressingMode: AddressingMode) -> Void {
state.status_register.carry = false