1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-07-07 21:28:59 +00:00

6502: fix optimizations using index registers

This commit is contained in:
Karol Stasiak 2018-12-29 20:01:17 +01:00
parent fca2700787
commit cbe709a9cf
3 changed files with 58 additions and 5 deletions

View File

@ -100,6 +100,11 @@ class ChangeIndexRegisterOptimization(preferX2Y: Boolean) extends AssemblyOptimi
//noinspection OptionEqualsSome
private def canOptimize(code: List[AssemblyLine], dir: IndexDirection, loaded: Option[IndexReg]): Boolean = code match {
case AssemblyLine0(INC | DEC | ASL | ROL | ROR | LSR | STZ | LDZ | BIT, AbsoluteX | ZeroPageX, _) :: xs if dir == X2Y => false
case AssemblyLine0(LDY | STY, AbsoluteX | ZeroPageX, _) :: xs => false
case AssemblyLine0(LDX | STX, AbsoluteY | ZeroPageY, _) :: xs => false
case AssemblyLine0(_, AbsoluteY, _) :: xs if loaded != Some(Y) => false
case AssemblyLine0(_, ZeroPageY, _) :: xs if loaded != Some(Y) => false
case AssemblyLine0(_, IndexedY, _) :: xs if dir == Y2X || loaded != Some(Y) => false
@ -118,18 +123,15 @@ class ChangeIndexRegisterOptimization(preferX2Y: Boolean) extends AssemblyOptimi
canOptimize(xs, dir, None)
case AssemblyLine0(LDX | TAX, _, _) :: AssemblyLine0(_, IndexedX, _) :: xs if dir == X2Y =>
canOptimize(xs, dir, None)
case AssemblyLine0(LDX | TAX, _, _) :: AssemblyLine0(INC | DEC | ASL | ROL | ROR | LSR | LDY | STY | STZ, AbsoluteX | ZeroPageX, _) :: xs if dir == X2Y =>
case AssemblyLine0(LDX | TAX, _, _) :: AssemblyLine0(INC | DEC | ASL | ROL | ROR | LSR | STZ, AbsoluteX | ZeroPageX, _) :: xs if dir == X2Y =>
canOptimize(xs, dir, None)
case AssemblyLine0(LDY | TAY, _, _) :: AssemblyLine0(INY | DEY, _, _) :: AssemblyLine0(_, IndexedY, _) :: xs if dir == Y2X =>
canOptimize(xs, dir, None)
case AssemblyLine0(LDX | TAX, _, _) :: AssemblyLine0(INX | DEX, _, _) :: AssemblyLine0(_, IndexedX, _) :: xs if dir == X2Y =>
canOptimize(xs, dir, None)
case AssemblyLine0(LDX | TAX, _, _) :: AssemblyLine0(INX | DEX, _, _) :: AssemblyLine0(INC | DEC | ASL | ROL | ROR | LSR | LDY | STY | STZ, AbsoluteX | ZeroPageX, _) :: xs if dir == X2Y =>
case AssemblyLine0(LDX | TAX, _, _) :: AssemblyLine0(INX | DEX, _, _) :: AssemblyLine0(INC | DEC | ASL | ROL | ROR | LSR | STZ, AbsoluteX | ZeroPageX, _) :: xs if dir == X2Y =>
canOptimize(xs, dir, None)
case AssemblyLine0(INC | DEC | ASL | ROL | ROR | LSR | STZ | LDZ | LDY | STY | BIT, AbsoluteX | ZeroPageX, _) :: xs if dir == X2Y => false
case AssemblyLine0(LDX | STX, AbsoluteY | ZeroPageY, _) :: xs if dir == Y2X => false
case AssemblyLine0(LAX, _, _) :: xs => false
case AssemblyLine0(JSR | BSR, _, _) :: xs => false // TODO
case AssemblyLine0(JMP, Absolute, _) :: xs => canOptimize(xs, dir, None) // TODO

View File

@ -379,11 +379,25 @@ object VariableToRegisterOptimization extends AssemblyOptimization[AssemblyLine]
val vy = yCandidate.getOrElse("-")
val vz = zCandidate.getOrElse("-")
lines match {
case (AssemblyLine0(_, Immediate, MemoryAddressConstant(th)), _) :: xs
if th.name == vx || th.name == vy || th.name == vz =>
// if an address of a variable is used, then that variable cannot be assigned to a register
None
case (AssemblyLine0(_, Immediate, SubbyteConstant(MemoryAddressConstant(th), _)), _) :: xs
if th.name == vx || th.name == vy || th.name == vz =>
// if an address of a variable is used, then that variable cannot be assigned to a register
None
case (AssemblyLine0(LDX | STX, AbsoluteY | ZeroPageY | IndexedY | IndexedSY | IndexedZ, _), _) :: xs if xCandidate.isDefined =>
None
case (AssemblyLine0(LDY | STY, AbsoluteX | ZeroPageX | IndexedX | LongAbsoluteX | IndexedZ, _), _) :: xs if yCandidate.isDefined =>
None
case (AssemblyLine0(LDZ | STZ, AbsoluteX | ZeroPageX | IndexedX | LongAbsoluteX | AbsoluteY | ZeroPageY | IndexedY | IndexedSY, _), _) :: xs if zCandidate.isDefined =>
None
case (AssemblyLine0(_, AbsoluteX | AbsoluteY | LongAbsoluteX |
ZeroPageX | ZeroPageY |
IndexedY | IndexedX | IndexedZ |

View File

@ -66,4 +66,41 @@ class SecondAssemblyOptimizationSuite extends FunSuite with Matchers {
| }
""".stripMargin) { m => m.readByte(0xc000) should equal(4) }
}
test("Index register usage") {
EmuBenchmarkRun(
"""
| array palette = [0, 2, 8, 7, 1]
| array reverse_palette [16] @$c000
| array __screen[1000]
| array c64_color_ram[1000]
| void main () {
| byte i
| for i,0,paralleluntil,palette.length {
| reverse_palette[palette[i]] = i
| }
| for i,0,paralleluntil,250 {
| __screen[000+i] = 160
| __screen[250+i] = 160
| __screen[500+i] = 160
| __screen[750+i] = 160
| }
| for i,0,paralleluntil,250 {
| c64_color_ram[000+i] = 0
| c64_color_ram[250+i] = 0
| c64_color_ram[500+i] = 0
| c64_color_ram[750+i] = 0
| }
| for i,0,paralleluntil,40 {
| c64_color_ram[960+i] = 1
| }
| }
""".stripMargin) { m =>
m.readByte(0xc000) should equal(0)
m.readByte(0xc002) should equal(1)
m.readByte(0xc008) should equal(2)
m.readByte(0xc007) should equal(3)
m.readByte(0xc001) should equal(4)
}
}
}