izapple2/core6502/addressing.go

104 lines
2.5 KiB
Go

package core6502
const (
modeImplicit = iota + 1
modeImplicitX
modeImplicitY
modeAccumulator
modeImmediate
modeZeroPage
modeZeroPageX
modeZeroPageY
modeRelative
modeAbsolute
modeAbsoluteX
modeAbsoluteY
modeIndirect
modeIndexedIndirectX
modeIndirectIndexedY
)
func getWordInLine(line []uint8) uint16 {
return uint16(line[1]) + 0x100*uint16(line[2])
}
func resolveValue(s *State, line []uint8, opcode opcode) uint8 {
getValue, _, _ := resolve(s, line, opcode)
return getValue()
}
func resolveGetSetValue(s *State, line []uint8, opcode opcode) (value uint8, setValue func(uint8)) {
getValue, setValue, _ := resolve(s, line, opcode)
value = getValue()
return
}
func resolveSetValue(s *State, line []uint8, opcode opcode) func(uint8) {
_, setValue, _ := resolve(s, line, opcode)
return setValue
}
func resolveAddress(s *State, line []uint8, opcode opcode) uint16 {
_, _, address := resolve(s, line, opcode)
return address
}
func resolve(s *State, line []uint8, opcode opcode) (getValue func() uint8, setValue func(uint8), address uint16) {
hasAddress := true
register := regNone
switch opcode.addressMode {
case modeAccumulator:
getValue = func() uint8 { return s.reg.getA() }
hasAddress = false
register = regA
case modeImplicitX:
getValue = func() uint8 { return s.reg.getX() }
hasAddress = false
register = regX
case modeImplicitY:
getValue = func() uint8 { return s.reg.getY() }
hasAddress = false
register = regY
case modeImmediate:
getValue = func() uint8 { return line[1] }
hasAddress = false
case modeZeroPage:
address = uint16(line[1])
case modeZeroPageX:
address = uint16(line[1] + s.reg.getX())
case modeZeroPageY:
address = uint16(line[1] + s.reg.getY())
case modeAbsolute:
address = getWordInLine(line)
case modeAbsoluteX:
address = getWordInLine(line) + uint16(s.reg.getX())
case modeAbsoluteY:
address = getWordInLine(line) + uint16(s.reg.getY())
case modeIndexedIndirectX:
addressAddress := uint8(line[1] + s.reg.getX())
address = getZeroPageWord(s.mem, addressAddress)
case modeIndirect:
addressAddress := getWordInLine(line)
address = getWord(s.mem, addressAddress)
case modeIndirectIndexedY:
address = getZeroPageWord(s.mem, line[1]) +
uint16(s.reg.getY())
}
if hasAddress {
getValue = func() uint8 { return s.mem.Peek(address) }
}
setValue = func(value uint8) {
if hasAddress {
s.mem.Poke(address, value)
} else if register != regNone {
s.reg.setRegister(register, value)
} else {
// Todo: assert impossible
}
}
return
}