mirror of
https://github.com/ivanizag/izapple2.git
synced 2024-06-01 07:41:56 +00:00
Fixed JSR and BRK. Added disassemble.
This commit is contained in:
parent
ff0d3d10c9
commit
6e524093c1
160
execute.go
160
execute.go
|
@ -11,20 +11,23 @@ func step(s *state) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const modeNone = -1
|
const (
|
||||||
const modeImmediate = 0
|
modeImplicit = iota + 1
|
||||||
const modeZeroPage = 1
|
modeImplicitX
|
||||||
const modeZeroPageX = 3
|
modeImplicitY
|
||||||
const modeZeroPageY = 6
|
modeAccumulator
|
||||||
const modeAbsolute = 2
|
modeImmediate
|
||||||
const modeAbsoluteX = 4
|
modeZeroPage
|
||||||
const modeAbsoluteY = 5
|
modeZeroPageX
|
||||||
const modeIndexedIndirectX = 7
|
modeZeroPageY
|
||||||
const modeIndirectIndexedY = 8
|
modeRelative
|
||||||
const modeAccumulator = 9
|
modeAbsolute
|
||||||
const modeRegisterX = 10
|
modeAbsoluteX
|
||||||
const modeRegisterY = 11
|
modeAbsoluteY
|
||||||
const modeIndirect = 12
|
modeIndirect
|
||||||
|
modeIndexedIndirectX
|
||||||
|
modeIndirectIndexedY
|
||||||
|
)
|
||||||
|
|
||||||
// https://www.masswerk.at/6502/6502_instruction_set.html
|
// https://www.masswerk.at/6502/6502_instruction_set.html
|
||||||
// http://www.emulator101.com/reference/6502-reference.html
|
// http://www.emulator101.com/reference/6502-reference.html
|
||||||
|
@ -44,11 +47,11 @@ func resolve(s *state, line []uint8, opcode opcode) (value uint8, address uint16
|
||||||
value = s.registers.getA()
|
value = s.registers.getA()
|
||||||
hasAddress = false
|
hasAddress = false
|
||||||
register = regA
|
register = regA
|
||||||
case modeRegisterX:
|
case modeImplicitX:
|
||||||
value = s.registers.getX()
|
value = s.registers.getX()
|
||||||
hasAddress = false
|
hasAddress = false
|
||||||
register = regX
|
register = regX
|
||||||
case modeRegisterY:
|
case modeImplicitY:
|
||||||
value = s.registers.getY()
|
value = s.registers.getY()
|
||||||
hasAddress = false
|
hasAddress = false
|
||||||
register = regY
|
register = regY
|
||||||
|
@ -219,7 +222,7 @@ func opADC(s *state, line []uint8, opcode opcode) {
|
||||||
value, _, _ := resolve(s, line, opcode)
|
value, _, _ := resolve(s, line, opcode)
|
||||||
if s.registers.getFlag(flagD) {
|
if s.registers.getFlag(flagD) {
|
||||||
// TODO BCD. See http://www.6502.org/tutorials/decimal_mode.html
|
// TODO BCD. See http://www.6502.org/tutorials/decimal_mode.html
|
||||||
|
panic("BCD not supported")
|
||||||
} else {
|
} else {
|
||||||
total := uint16(s.registers.getA()) +
|
total := uint16(s.registers.getA()) +
|
||||||
uint16(value) +
|
uint16(value) +
|
||||||
|
@ -236,6 +239,7 @@ func opSBC(s *state, line []uint8, opcode opcode) {
|
||||||
value, _, _ := resolve(s, line, opcode)
|
value, _, _ := resolve(s, line, opcode)
|
||||||
if s.registers.getFlag(flagD) {
|
if s.registers.getFlag(flagD) {
|
||||||
// TODO BCD
|
// TODO BCD
|
||||||
|
panic("BCD not supported")
|
||||||
} else {
|
} else {
|
||||||
total := 0x100 + uint16(s.registers.getA()) -
|
total := 0x100 + uint16(s.registers.getA()) -
|
||||||
uint16(value) -
|
uint16(value) -
|
||||||
|
@ -300,8 +304,9 @@ func opJMP(s *state, line []uint8, opcode opcode) {
|
||||||
func opNOP(s *state, line []uint8, opcode opcode) {}
|
func opNOP(s *state, line []uint8, opcode opcode) {}
|
||||||
|
|
||||||
func opJSR(s *state, line []uint8, opcode opcode) {
|
func opJSR(s *state, line []uint8, opcode opcode) {
|
||||||
pushWord(s, s.registers.getPC())
|
pushWord(s, s.registers.getPC()-1)
|
||||||
s.registers.setPC(getWordInLine(line))
|
_, address, _ := resolve(s, line, opcode)
|
||||||
|
s.registers.setPC(address)
|
||||||
}
|
}
|
||||||
|
|
||||||
func opRTI(s *state, line []uint8, opcode opcode) {
|
func opRTI(s *state, line []uint8, opcode opcode) {
|
||||||
|
@ -310,28 +315,28 @@ func opRTI(s *state, line []uint8, opcode opcode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func opRTS(s *state, line []uint8, opcode opcode) {
|
func opRTS(s *state, line []uint8, opcode opcode) {
|
||||||
s.registers.setPC(pullWord(s) + 1) // TODO: Do we really need to add 1?
|
s.registers.setPC(pullWord(s) + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func opBRK(s *state, line []uint8, opcode opcode) {
|
func opBRK(s *state, line []uint8, opcode opcode) {
|
||||||
s.registers.setFlag(flagI)
|
pushWord(s, s.registers.getPC()+1)
|
||||||
pushWord(s, s.registers.getPC()+1) // TODO: De we have to add 1 or 2?
|
|
||||||
pushByte(s, s.registers.getP()|(flagB+flag5))
|
pushByte(s, s.registers.getP()|(flagB+flag5))
|
||||||
|
s.registers.setFlag(flagI)
|
||||||
s.registers.setPC(s.memory.getWord(0xFFFE))
|
s.registers.setPC(s.memory.getWord(0xFFFE))
|
||||||
}
|
}
|
||||||
|
|
||||||
var opcodes = [256]opcode{
|
var opcodes = [256]opcode{
|
||||||
0x00: opcode{"BRK", 1, 7, modeNone, opBRK},
|
0x00: opcode{"BRK", 1, 7, modeImplicit, opBRK},
|
||||||
0x4C: opcode{"JMP", 3, 3, modeAbsolute, opJMP},
|
0x4C: opcode{"JMP", 3, 3, modeAbsolute, opJMP},
|
||||||
0x6C: opcode{"JMP", 3, 3, modeIndirect, opJMP},
|
0x6C: opcode{"JMP", 3, 3, modeIndirect, opJMP},
|
||||||
0x20: opcode{"JSR", 3, 6, modeNone, opJSR},
|
0x20: opcode{"JSR", 3, 6, modeAbsolute, opJSR},
|
||||||
0x40: opcode{"RTI", 1, 6, modeNone, opRTI},
|
0x40: opcode{"RTI", 1, 6, modeImplicit, opRTI},
|
||||||
0x60: opcode{"RTS", 1, 6, modeNone, opRTS},
|
0x60: opcode{"RTS", 1, 6, modeImplicit, opRTS},
|
||||||
|
|
||||||
0x48: opcode{"PHA", 1, 3, modeNone, opPHA},
|
0x48: opcode{"PHA", 1, 3, modeImplicit, opPHA},
|
||||||
0x08: opcode{"PHP", 1, 3, modeNone, opPHP},
|
0x08: opcode{"PHP", 1, 3, modeImplicit, opPHP},
|
||||||
0x68: opcode{"PLA", 1, 4, modeNone, opPLA},
|
0x68: opcode{"PLA", 1, 4, modeImplicit, opPLA},
|
||||||
0x28: opcode{"PLP", 1, 4, modeNone, opPLP},
|
0x28: opcode{"PLP", 1, 4, modeImplicit, opPLP},
|
||||||
|
|
||||||
0x09: opcode{"ORA", 2, 2, modeImmediate, buildOpLogic(operationOr)},
|
0x09: opcode{"ORA", 2, 2, modeImmediate, buildOpLogic(operationOr)},
|
||||||
0x05: opcode{"ORA", 2, 3, modeZeroPage, buildOpLogic(operationOr)},
|
0x05: opcode{"ORA", 2, 3, modeZeroPage, buildOpLogic(operationOr)},
|
||||||
|
@ -379,7 +384,7 @@ var opcodes = [256]opcode{
|
||||||
0xF1: opcode{"SBC", 2, 5, modeIndirectIndexedY, opSBC}, // Extra cycles
|
0xF1: opcode{"SBC", 2, 5, modeIndirectIndexedY, opSBC}, // Extra cycles
|
||||||
|
|
||||||
0x24: opcode{"BIT", 2, 3, modeZeroPage, opBIT},
|
0x24: opcode{"BIT", 2, 3, modeZeroPage, opBIT},
|
||||||
0x2C: opcode{"BIT", 2, 3, modeAbsolute, opBIT},
|
0x2C: opcode{"BIT", 3, 3, modeAbsolute, opBIT},
|
||||||
|
|
||||||
0xC9: opcode{"CMP", 2, 2, modeImmediate, buildOpCompare(regA)},
|
0xC9: opcode{"CMP", 2, 2, modeImmediate, buildOpCompare(regA)},
|
||||||
0xC5: opcode{"CMP", 2, 3, modeZeroPage, buildOpCompare(regA)},
|
0xC5: opcode{"CMP", 2, 3, modeZeroPage, buildOpCompare(regA)},
|
||||||
|
@ -422,13 +427,13 @@ var opcodes = [256]opcode{
|
||||||
0x4E: opcode{"LSR", 3, 6, modeAbsolute, buildOpShift(false, false)},
|
0x4E: opcode{"LSR", 3, 6, modeAbsolute, buildOpShift(false, false)},
|
||||||
0x5E: opcode{"LSR", 3, 7, modeAbsoluteX, buildOpShift(false, false)},
|
0x5E: opcode{"LSR", 3, 7, modeAbsoluteX, buildOpShift(false, false)},
|
||||||
|
|
||||||
0x38: opcode{"SEC", 1, 2, modeNone, buildOpUpdateFlag(flagC, true)},
|
0x38: opcode{"SEC", 1, 2, modeImplicit, buildOpUpdateFlag(flagC, true)},
|
||||||
0xF8: opcode{"SED", 1, 2, modeNone, buildOpUpdateFlag(flagD, true)},
|
0xF8: opcode{"SED", 1, 2, modeImplicit, buildOpUpdateFlag(flagD, true)},
|
||||||
0x78: opcode{"SEI", 1, 2, modeNone, buildOpUpdateFlag(flagI, true)},
|
0x78: opcode{"SEI", 1, 2, modeImplicit, buildOpUpdateFlag(flagI, true)},
|
||||||
0x18: opcode{"CLC", 1, 2, modeNone, buildOpUpdateFlag(flagC, false)},
|
0x18: opcode{"CLC", 1, 2, modeImplicit, buildOpUpdateFlag(flagC, false)},
|
||||||
0xD8: opcode{"CLD", 1, 2, modeNone, buildOpUpdateFlag(flagD, false)},
|
0xD8: opcode{"CLD", 1, 2, modeImplicit, buildOpUpdateFlag(flagD, false)},
|
||||||
0x58: opcode{"CLI", 1, 2, modeNone, buildOpUpdateFlag(flagI, false)},
|
0x58: opcode{"CLI", 1, 2, modeImplicit, buildOpUpdateFlag(flagI, false)},
|
||||||
0xB8: opcode{"CLV", 1, 2, modeNone, buildOpUpdateFlag(flagV, false)},
|
0xB8: opcode{"CLV", 1, 2, modeImplicit, buildOpUpdateFlag(flagV, false)},
|
||||||
|
|
||||||
0xE6: opcode{"INC", 2, 5, modeZeroPage, buildOpIncDec(true)},
|
0xE6: opcode{"INC", 2, 5, modeZeroPage, buildOpIncDec(true)},
|
||||||
0xF6: opcode{"INC", 2, 6, modeZeroPageX, buildOpIncDec(true)},
|
0xF6: opcode{"INC", 2, 6, modeZeroPageX, buildOpIncDec(true)},
|
||||||
|
@ -438,17 +443,17 @@ var opcodes = [256]opcode{
|
||||||
0xD6: opcode{"DEC", 2, 6, modeZeroPageX, buildOpIncDec(false)},
|
0xD6: opcode{"DEC", 2, 6, modeZeroPageX, buildOpIncDec(false)},
|
||||||
0xCE: opcode{"DEC", 3, 6, modeAbsolute, buildOpIncDec(false)},
|
0xCE: opcode{"DEC", 3, 6, modeAbsolute, buildOpIncDec(false)},
|
||||||
0xDE: opcode{"DEC", 3, 7, modeAbsoluteX, buildOpIncDec(false)},
|
0xDE: opcode{"DEC", 3, 7, modeAbsoluteX, buildOpIncDec(false)},
|
||||||
0xE8: opcode{"INX", 1, 2, modeRegisterX, buildOpIncDec(true)},
|
0xE8: opcode{"INX", 1, 2, modeImplicitX, buildOpIncDec(true)},
|
||||||
0xC8: opcode{"INY", 1, 2, modeRegisterY, buildOpIncDec(true)},
|
0xC8: opcode{"INY", 1, 2, modeImplicitY, buildOpIncDec(true)},
|
||||||
0xCA: opcode{"DEX", 1, 2, modeRegisterX, buildOpIncDec(false)},
|
0xCA: opcode{"DEX", 1, 2, modeImplicitX, buildOpIncDec(false)},
|
||||||
0x88: opcode{"DEY", 1, 2, modeRegisterY, buildOpIncDec(false)},
|
0x88: opcode{"DEY", 1, 2, modeImplicitY, buildOpIncDec(false)},
|
||||||
|
|
||||||
0xAA: opcode{"TAX", 1, 2, modeNone, buildOpTransfer(regA, regX)},
|
0xAA: opcode{"TAX", 1, 2, modeImplicit, buildOpTransfer(regA, regX)},
|
||||||
0xA8: opcode{"TAY", 1, 2, modeNone, buildOpTransfer(regA, regY)},
|
0xA8: opcode{"TAY", 1, 2, modeImplicit, buildOpTransfer(regA, regY)},
|
||||||
0x8A: opcode{"TXA", 1, 2, modeNone, buildOpTransfer(regX, regA)},
|
0x8A: opcode{"TXA", 1, 2, modeImplicit, buildOpTransfer(regX, regA)},
|
||||||
0x98: opcode{"TYA", 1, 2, modeNone, buildOpTransfer(regY, regA)},
|
0x98: opcode{"TYA", 1, 2, modeImplicit, buildOpTransfer(regY, regA)},
|
||||||
0x9A: opcode{"TXS", 1, 2, modeNone, buildOpTransfer(regX, regSP)},
|
0x9A: opcode{"TXS", 1, 2, modeImplicit, buildOpTransfer(regX, regSP)},
|
||||||
0xBA: opcode{"TSX", 1, 2, modeNone, buildOpTransfer(regSP, regX)},
|
0xBA: opcode{"TSX", 1, 2, modeImplicit, buildOpTransfer(regSP, regX)},
|
||||||
|
|
||||||
0xA9: opcode{"LDA", 2, 2, modeImmediate, buildOpLoad(regA)},
|
0xA9: opcode{"LDA", 2, 2, modeImmediate, buildOpLoad(regA)},
|
||||||
0xA5: opcode{"LDA", 2, 3, modeZeroPage, buildOpLoad(regA)},
|
0xA5: opcode{"LDA", 2, 3, modeZeroPage, buildOpLoad(regA)},
|
||||||
|
@ -483,16 +488,16 @@ var opcodes = [256]opcode{
|
||||||
0x94: opcode{"STY", 2, 4, modeZeroPageX, buildOpStore(regY)},
|
0x94: opcode{"STY", 2, 4, modeZeroPageX, buildOpStore(regY)},
|
||||||
0x8C: opcode{"STY", 3, 4, modeAbsolute, buildOpStore(regY)},
|
0x8C: opcode{"STY", 3, 4, modeAbsolute, buildOpStore(regY)},
|
||||||
|
|
||||||
0x90: opcode{"BCC", 2, 2, modeNone, buildOpBranch(flagC, false)}, // Extra cycles
|
0x90: opcode{"BCC", 2, 2, modeRelative, buildOpBranch(flagC, false)}, // Extra cycles
|
||||||
0xB0: opcode{"BCS", 2, 2, modeNone, buildOpBranch(flagC, true)}, // Extra cycles
|
0xB0: opcode{"BCS", 2, 2, modeRelative, buildOpBranch(flagC, true)}, // Extra cycles
|
||||||
0xD0: opcode{"BNE", 2, 2, modeNone, buildOpBranch(flagZ, false)}, // Extra cycles
|
0xD0: opcode{"BNE", 2, 2, modeRelative, buildOpBranch(flagZ, false)}, // Extra cycles
|
||||||
0xF0: opcode{"BEQ", 2, 2, modeNone, buildOpBranch(flagZ, true)}, // Extra cycles
|
0xF0: opcode{"BEQ", 2, 2, modeRelative, buildOpBranch(flagZ, true)}, // Extra cycles
|
||||||
0x10: opcode{"BPL", 2, 2, modeNone, buildOpBranch(flagN, false)}, // Extra cycles
|
0x10: opcode{"BPL", 2, 2, modeRelative, buildOpBranch(flagN, false)}, // Extra cycles
|
||||||
0x30: opcode{"BMI", 2, 2, modeNone, buildOpBranch(flagN, true)}, // Extra cycles
|
0x30: opcode{"BMI", 2, 2, modeRelative, buildOpBranch(flagN, true)}, // Extra cycles
|
||||||
0x50: opcode{"BVC", 2, 2, modeNone, buildOpBranch(flagV, false)}, // Extra cycles
|
0x50: opcode{"BVC", 2, 2, modeRelative, buildOpBranch(flagV, false)}, // Extra cycles
|
||||||
0x70: opcode{"BVS", 2, 2, modeNone, buildOpBranch(flagV, true)}, // Extra cycles
|
0x70: opcode{"BVS", 2, 2, modeRelative, buildOpBranch(flagV, true)}, // Extra cycles
|
||||||
|
|
||||||
0xEA: opcode{"NOP", 1, 2, modeNone, opNOP},
|
0xEA: opcode{"NOP", 1, 2, modeImplicit, opNOP},
|
||||||
}
|
}
|
||||||
|
|
||||||
func executeLine(s *state, line []uint8) {
|
func executeLine(s *state, line []uint8) {
|
||||||
|
@ -503,10 +508,47 @@ func executeLine(s *state, line []uint8) {
|
||||||
func executeInstruction(s *state) {
|
func executeInstruction(s *state) {
|
||||||
pc := s.registers.getPC()
|
pc := s.registers.getPC()
|
||||||
opcode := opcodes[s.memory[pc]]
|
opcode := opcodes[s.memory[pc]]
|
||||||
fmt.Printf("%#04x %s: ", pc, opcode.name)
|
|
||||||
pcNext := pc + uint16(opcode.bytes)
|
pcNext := pc + uint16(opcode.bytes)
|
||||||
s.registers.setPC(pcNext)
|
s.registers.setPC(pcNext)
|
||||||
line := s.memory[pc:pcNext]
|
line := s.memory[pc:pcNext]
|
||||||
|
fmt.Printf("%#04x %-10s: ", pc, lineString(s, line, opcode))
|
||||||
opcode.action(s, line, opcode)
|
opcode.action(s, line, opcode)
|
||||||
fmt.Printf("%v, %v\n", s.registers, line)
|
fmt.Printf("%v, %x\n", s.registers, line)
|
||||||
|
}
|
||||||
|
|
||||||
|
func lineString(s *state, line []uint8, opcode opcode) string {
|
||||||
|
t := opcode.name
|
||||||
|
switch opcode.addressMode {
|
||||||
|
case modeImplicit:
|
||||||
|
case modeImplicitX:
|
||||||
|
case modeImplicitY:
|
||||||
|
//Nothing
|
||||||
|
case modeAccumulator:
|
||||||
|
t += fmt.Sprintf(" A")
|
||||||
|
case modeImmediate:
|
||||||
|
t += fmt.Sprintf(" #%02x", line[1])
|
||||||
|
case modeZeroPage:
|
||||||
|
t += fmt.Sprintf(" $%02x", line[1])
|
||||||
|
case modeZeroPageX:
|
||||||
|
t += fmt.Sprintf(" $%02x,X", line[1])
|
||||||
|
case modeZeroPageY:
|
||||||
|
t += fmt.Sprintf(" $%02x,Y", line[1])
|
||||||
|
case modeRelative:
|
||||||
|
t += fmt.Sprintf(" *%+x", int8(line[1]))
|
||||||
|
case modeAbsolute:
|
||||||
|
t += fmt.Sprintf(" $%04x", getWordInLine(line))
|
||||||
|
case modeAbsoluteX:
|
||||||
|
t += fmt.Sprintf(" $%04x,X", getWordInLine(line))
|
||||||
|
case modeAbsoluteY:
|
||||||
|
t += fmt.Sprintf(" $%04x,X", getWordInLine(line))
|
||||||
|
case modeIndirect:
|
||||||
|
t += fmt.Sprintf(" ($%04x)", getWordInLine(line))
|
||||||
|
case modeIndexedIndirectX:
|
||||||
|
t += fmt.Sprintf(" ($%02x,X)", line[1])
|
||||||
|
case modeIndirectIndexedY:
|
||||||
|
t += fmt.Sprintf(" ($%02x),Y", line[1])
|
||||||
|
default:
|
||||||
|
t += "UNKNOWN MODE"
|
||||||
|
}
|
||||||
|
return t
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user