Much faster resolution avoiding a single getSet with callbacks.

This commit is contained in:
Ivan Izaguirre 2020-01-11 17:15:42 +01:00
parent b2b009037e
commit 6387e93f06
2 changed files with 45 additions and 63 deletions

View File

@ -29,46 +29,44 @@ func getWordInLine(line []uint8) uint16 {
} }
func resolveValue(s *State, line []uint8, opcode opcode) uint8 { func resolveValue(s *State, line []uint8, opcode opcode) uint8 {
getValue, _, _ := resolve(s, line, opcode) switch opcode.addressMode {
return getValue() case modeAccumulator:
return s.reg.getA()
case modeImplicitX:
return s.reg.getX()
case modeImplicitY:
return s.reg.getY()
case modeImmediate:
return line[1]
}
// The value is in memory
address := resolveAddress(s, line, opcode)
return s.mem.Peek(address)
} }
func resolveGetSetValue(s *State, line []uint8, opcode opcode) (value uint8, setValue func(uint8)) { func resolveSetValue(s *State, line []uint8, opcode opcode, value uint8) {
getValue, setValue, _ := resolve(s, line, opcode) switch opcode.addressMode {
value = getValue() case modeAccumulator:
return s.reg.setA(value)
} return
case modeImplicitX:
s.reg.setX(value)
return
case modeImplicitY:
s.reg.setY(value)
return
}
func resolveSetValue(s *State, line []uint8, opcode opcode) func(uint8) { // The value is in memory
_, setValue, _ := resolve(s, line, opcode) address := resolveAddress(s, line, opcode)
return setValue s.mem.Poke(address, value)
} }
func resolveAddress(s *State, line []uint8, opcode opcode) uint16 { func resolveAddress(s *State, line []uint8, opcode opcode) uint16 {
_, _, address := resolve(s, line, opcode) var address uint16
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 { 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: case modeZeroPage:
address = uint16(line[1]) address = uint16(line[1])
case modeZeroPageX: case modeZeroPageX:
@ -103,25 +101,10 @@ func resolve(s *State, line []uint8, opcode opcode) (getValue func() uint8, setV
// Two addressing modes combined. We refer to the second one, relative, // Two addressing modes combined. We refer to the second one, relative,
// placed one byte after the zeropage reference // placed one byte after the zeropage reference
address = s.reg.getPC() + uint16(int8(line[2])) // Note: line[2] is signed address = s.reg.getPC() + uint16(int8(line[2])) // Note: line[2] is signed
default: default:
panic("Assert failed. Missing addressing mode") panic("Assert failed. Missing addressing mode")
} }
return address
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 {
panic("Assert failed. Should never happen")
}
}
return
} }
func lineString(line []uint8, opcode opcode) string { func lineString(line []uint8, opcode opcode) string {

View File

@ -12,20 +12,20 @@ func buildOpTransfer(regSrc int, regDst int) opFunc {
func buildOpIncDec(inc bool) opFunc { func buildOpIncDec(inc bool) opFunc {
return func(s *State, line []uint8, opcode opcode) { return func(s *State, line []uint8, opcode opcode) {
value, setValue := resolveGetSetValue(s, line, opcode) value := resolveValue(s, line, opcode)
if inc { if inc {
value++ value++
} else { } else {
value-- value--
} }
s.reg.updateFlagZN(value) s.reg.updateFlagZN(value)
setValue(value) resolveSetValue(s, line, opcode, value)
} }
} }
func buildOpShift(isLeft bool, isRotate bool) opFunc { func buildOpShift(isLeft bool, isRotate bool) opFunc {
return func(s *State, line []uint8, opcode opcode) { return func(s *State, line []uint8, opcode opcode) {
value, setValue := resolveGetSetValue(s, line, opcode) value := resolveValue(s, line, opcode)
oldCarry := s.reg.getFlagBit(flagC) oldCarry := s.reg.getFlagBit(flagC)
var carry bool var carry bool
@ -44,7 +44,7 @@ func buildOpShift(isLeft bool, isRotate bool) opFunc {
} }
s.reg.updateFlag(flagC, carry) s.reg.updateFlag(flagC, carry)
s.reg.updateFlagZN(value) s.reg.updateFlagZN(value)
setValue(value) resolveSetValue(s, line, opcode, value)
} }
} }
@ -58,9 +58,8 @@ func buildOpLoad(regDst int) opFunc {
func buildOpStore(regSrc int) opFunc { func buildOpStore(regSrc int) opFunc {
return func(s *State, line []uint8, opcode opcode) { return func(s *State, line []uint8, opcode opcode) {
setValue := resolveSetValue(s, line, opcode)
value := s.reg.getRegister(regSrc) value := s.reg.getRegister(regSrc)
setValue(value) resolveSetValue(s, line, opcode, value)
} }
} }
@ -96,12 +95,13 @@ func buildOpBranchOnBit(bit uint8, test bool) opFunc {
func buildOpSetBit(bit uint8, set bool) opFunc { func buildOpSetBit(bit uint8, set bool) opFunc {
return func(s *State, line []uint8, opcode opcode) { return func(s *State, line []uint8, opcode opcode) {
value, setValue := resolveGetSetValue(s, line, opcode) value := resolveValue(s, line, opcode)
if set { if set {
setValue(value | (1 << bit)) value = value | (1 << bit)
} else { } else {
setValue(value &^ (1 << bit)) value = value &^ (1 << bit)
} }
resolveSetValue(s, line, opcode, value)
} }
} }
@ -117,17 +117,17 @@ func opBIT(s *State, line []uint8, opcode opcode) {
} }
func opTRB(s *State, line []uint8, opcode opcode) { func opTRB(s *State, line []uint8, opcode opcode) {
value, setValue := resolveGetSetValue(s, line, opcode) value := resolveValue(s, line, opcode)
a := s.reg.getA() a := s.reg.getA()
s.reg.updateFlag(flagZ, (value&a) == 0) s.reg.updateFlag(flagZ, (value&a) == 0)
setValue(value &^ a) resolveSetValue(s, line, opcode, value&^a)
} }
func opTSB(s *State, line []uint8, opcode opcode) { func opTSB(s *State, line []uint8, opcode opcode) {
value, setValue := resolveGetSetValue(s, line, opcode) value := resolveValue(s, line, opcode)
a := s.reg.getA() a := s.reg.getA()
s.reg.updateFlag(flagZ, (value&a) == 0) s.reg.updateFlag(flagZ, (value&a) == 0)
setValue(value | a) resolveSetValue(s, line, opcode, value|a)
} }
func buildOpCompare(reg int) opFunc { func buildOpCompare(reg int) opFunc {
@ -305,6 +305,5 @@ func opBRKAlt(s *State, line []uint8, opcode opcode) {
} }
func opSTZ(s *State, line []uint8, opcode opcode) { func opSTZ(s *State, line []uint8, opcode opcode) {
setValue := resolveSetValue(s, line, opcode) resolveSetValue(s, line, opcode, 0)
setValue(0)
} }