mirror of
https://github.com/KarolS/millfork.git
synced 2025-04-06 20:37:12 +00:00
6502: fix optimizations using index registers
This commit is contained in:
parent
fca2700787
commit
cbe709a9cf
@ -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
|
||||
|
@ -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 |
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user