diff --git a/execute.go b/execute.go index d7d9287..e2d792d 100644 --- a/execute.go +++ b/execute.go @@ -14,53 +14,15 @@ const modeImmediate = 0 const modeZeroPage = 1 const modeZeroPageX = 3 const modeAbsolute = 2 +const modeAbsoluteX = 4 +const modeAbsoluteY = 5 // https://www.masswerk.at/6502/6502_instruction_set.html -func opLDAimm(s *state, line []uint8) { - opLDR(s, line, regA, modeImmediate) -} - -func opLDAzpg(s *state, line []uint8) { - opLDR(s, line, regA, modeZeroPage) -} - -func opLDYimm(s *state, line []uint8) { - opLDR(s, line, regY, modeImmediate) -} - -func opLDAzpgX(s *state, line []uint8) { - opLDR(s, line, regA, modeZeroPageX) -} - -func opLDAabs(s *state, line []uint8) { - opLDR(s, line, regA, modeAbsolute) -} - func getWordInLine(line []uint8) uint16 { return uint16(line[1]) + 0x100*uint16(line[2]) } -func opLDR(s *state, line []uint8, reg int, mode int) { - var value uint8 - switch mode { - case modeImmediate: - value = line[1] - case modeZeroPage: - address := line[1] - value = s.memory[address] - case modeZeroPageX: - address := line[1] + s.registers.getRegister(regX) - value = s.memory[address] - case modeAbsolute: - address := getWordInLine(line) - value = s.memory[address] - } - - s.registers.setRegister(reg, value) -} - -type opFunc func(s *state, line []uint8, opcode opcode) type opcode struct { name string bytes int @@ -70,18 +32,44 @@ type opcode struct { action opFunc } +type opFunc func(s *state, line []uint8, opcode opcode) + func opNOP(s *state, line []uint8, opcode opcode) {} -func opLDRex(s *state, line []uint8, opcode opcode) { - opLDR(s, line, opcode.reg, opcode.mode) + +func opLDR(s *state, line []uint8, opcode opcode) { + var value uint8 + switch opcode.mode { + case modeImmediate: + value = line[1] + case modeZeroPage: + address := line[1] + value = s.memory[address] + case modeZeroPageX: + address := line[1] + s.registers.getX() + value = s.memory[address] + case modeAbsolute: + address := getWordInLine(line) + value = s.memory[address] + case modeAbsoluteX: + address := getWordInLine(line) + uint16(s.registers.getX()) + value = s.memory[address] + case modeAbsoluteY: + address := getWordInLine(line) + uint16(s.registers.getY()) + value = s.memory[address] + } + + s.registers.setRegister(opcode.reg, value) } var opcodes = [256]opcode{ 0x00: opcode{"BRK", 1, 7, modeImmediate, regNone, opNOP}, - 0xA0: opcode{"LDY", -1, -1, modeImmediate, regY, opLDRex}, - 0xA5: opcode{"LDA", 2, 3, modeZeroPage, regA, opLDRex}, - 0xB5: opcode{"LDA", 2, 4, modeZeroPageX, regA, opLDRex}, - 0xA9: opcode{"LDA", 2, 2, modeImmediate, regA, opLDRex}, - 0xAD: opcode{"LDA", 3, 4, modeAbsolute, regA, opLDRex}, + 0xA0: opcode{"LDY", 2, 2, modeImmediate, regY, opLDR}, + 0xA5: opcode{"LDA", 2, 3, modeZeroPage, regA, opLDR}, + 0xB5: opcode{"LDA", 2, 4, modeZeroPageX, regA, opLDR}, + 0xA9: opcode{"LDA", 2, 2, modeImmediate, regA, opLDR}, + 0xAD: opcode{"LDA", 3, 4, modeAbsolute, regA, opLDR}, + 0xB9: opcode{"LDA", 3, 4, modeAbsoluteY, regA, opLDR}, // Extra cycles + 0xBD: opcode{"LDA", 3, 4, modeAbsoluteX, regA, opLDR}, // Extra cycles } func executeLine(s *state, line []uint8) { diff --git a/execute_test.go b/execute_test.go index e76d1a5..7a4a64a 100644 --- a/execute_test.go +++ b/execute_test.go @@ -7,47 +7,6 @@ import ( func TestLDA(t *testing.T) { var s state - opLDAimm(&s, []uint8{0xA9, 0x42}) - if s.registers.getA() != 0x42 { - t.Error("Error in LDA #") - } - - opLDYimm(&s, []uint8{0xA0, 0xFE}) - if s.registers.getY() != 0xFE { - t.Error("Error in LDY #") - } - - s.memory[0x38] = 0x87 - opLDAzpg(&s, []uint8{0xA5, 0x38}) - if s.registers.getA() != 0x87 { - t.Error("Error in LDA zpg") - } - - s.memory[0x57] = 0x90 - s.registers.setX(0x10) - opLDAzpgX(&s, []uint8{0xB5, 0x47}) - if s.registers.getA() != 0x90 { - t.Error("Error in LDA zpgX") - } - - s.memory[0x38] = 0x12 - s.registers.setX(0x89) - opLDAzpgX(&s, []uint8{0xB5, 0xAF}) - if s.registers.getA() != 0x12 { - t.Error("Error in LDA zpgX with sero page overflow") - } - - s.memory[0x1234] = 0x67 - opLDAabs(&s, []uint8{0xAD, 0x34, 0x12}) - if s.registers.getA() != 0x67 { - t.Error("Error in LDA abs") - } - -} - -func TestLDA2(t *testing.T) { - var s state - executeLine(&s, []uint8{0xA9, 0x42}) if s.registers.getA() != 0x42 { t.Error("Error in LDA #") @@ -68,7 +27,7 @@ func TestLDA2(t *testing.T) { s.registers.setX(0x10) executeLine(&s, []uint8{0xB5, 0x47}) if s.registers.getA() != 0x90 { - t.Error("Error in LDA zpgX") + t.Error("Error in LDA zpg, X") } s.memory[0x38] = 0x12 @@ -84,4 +43,18 @@ func TestLDA2(t *testing.T) { t.Error("Error in LDA abs") } + s.memory[0xC057] = 0x7E + s.registers.setX(0x57) + executeLine(&s, []uint8{0xBD, 0x00, 0xC0}) + if s.registers.getA() != 0x7E { + t.Error("Error in LDA abs, X") + } + + s.memory[0xD059] = 0x7A + s.registers.setY(0x59) + executeLine(&s, []uint8{0xB9, 0x00, 0xD0}) + if s.registers.getA() != 0x7A { + t.Error("Error in LDA abs, Y") + } + }