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 {
getValue, _, _ := resolve(s, line, opcode)
return getValue()
switch opcode.addressMode {
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)) {
getValue, setValue, _ := resolve(s, line, opcode)
value = getValue()
return
}
func resolveSetValue(s *State, line []uint8, opcode opcode, value uint8) {
switch opcode.addressMode {
case modeAccumulator:
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) {
_, setValue, _ := resolve(s, line, opcode)
return setValue
// The value is in memory
address := resolveAddress(s, line, opcode)
s.mem.Poke(address, value)
}
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
var address uint16
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:
@ -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,
// placed one byte after the zeropage reference
address = s.reg.getPC() + uint16(int8(line[2])) // Note: line[2] is signed
default:
panic("Assert failed. Missing addressing mode")
}
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
return address
}
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 {
return func(s *State, line []uint8, opcode opcode) {
value, setValue := resolveGetSetValue(s, line, opcode)
value := resolveValue(s, line, opcode)
if inc {
value++
} else {
value--
}
s.reg.updateFlagZN(value)
setValue(value)
resolveSetValue(s, line, opcode, value)
}
}
func buildOpShift(isLeft bool, isRotate bool) opFunc {
return func(s *State, line []uint8, opcode opcode) {
value, setValue := resolveGetSetValue(s, line, opcode)
value := resolveValue(s, line, opcode)
oldCarry := s.reg.getFlagBit(flagC)
var carry bool
@ -44,7 +44,7 @@ func buildOpShift(isLeft bool, isRotate bool) opFunc {
}
s.reg.updateFlag(flagC, carry)
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 {
return func(s *State, line []uint8, opcode opcode) {
setValue := resolveSetValue(s, line, opcode)
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 {
return func(s *State, line []uint8, opcode opcode) {
value, setValue := resolveGetSetValue(s, line, opcode)
value := resolveValue(s, line, opcode)
if set {
setValue(value | (1 << bit))
value = value | (1 << bit)
} 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) {
value, setValue := resolveGetSetValue(s, line, opcode)
value := resolveValue(s, line, opcode)
a := s.reg.getA()
s.reg.updateFlag(flagZ, (value&a) == 0)
setValue(value &^ a)
resolveSetValue(s, line, opcode, value&^a)
}
func opTSB(s *State, line []uint8, opcode opcode) {
value, setValue := resolveGetSetValue(s, line, opcode)
value := resolveValue(s, line, opcode)
a := s.reg.getA()
s.reg.updateFlag(flagZ, (value&a) == 0)
setValue(value | a)
resolveSetValue(s, line, opcode, value|a)
}
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) {
setValue := resolveSetValue(s, line, opcode)
setValue(0)
resolveSetValue(s, line, opcode, 0)
}