mirror of
https://github.com/KarolS/millfork.git
synced 2024-10-12 09:23:45 +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
|
//noinspection OptionEqualsSome
|
||||||
private def canOptimize(code: List[AssemblyLine], dir: IndexDirection, loaded: Option[IndexReg]): Boolean = code match {
|
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(_, AbsoluteY, _) :: xs if loaded != Some(Y) => false
|
||||||
case AssemblyLine0(_, ZeroPageY, _) :: 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
|
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)
|
canOptimize(xs, dir, None)
|
||||||
case AssemblyLine0(LDX | TAX, _, _) :: AssemblyLine0(_, IndexedX, _) :: xs if dir == X2Y =>
|
case AssemblyLine0(LDX | TAX, _, _) :: AssemblyLine0(_, IndexedX, _) :: xs if dir == X2Y =>
|
||||||
canOptimize(xs, dir, None)
|
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)
|
canOptimize(xs, dir, None)
|
||||||
case AssemblyLine0(LDY | TAY, _, _) :: AssemblyLine0(INY | DEY, _, _) :: AssemblyLine0(_, IndexedY, _) :: xs if dir == Y2X =>
|
case AssemblyLine0(LDY | TAY, _, _) :: AssemblyLine0(INY | DEY, _, _) :: AssemblyLine0(_, IndexedY, _) :: xs if dir == Y2X =>
|
||||||
canOptimize(xs, dir, None)
|
canOptimize(xs, dir, None)
|
||||||
case AssemblyLine0(LDX | TAX, _, _) :: AssemblyLine0(INX | DEX, _, _) :: AssemblyLine0(_, IndexedX, _) :: xs if dir == X2Y =>
|
case AssemblyLine0(LDX | TAX, _, _) :: AssemblyLine0(INX | DEX, _, _) :: AssemblyLine0(_, IndexedX, _) :: xs if dir == X2Y =>
|
||||||
canOptimize(xs, dir, None)
|
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)
|
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(LAX, _, _) :: xs => false
|
||||||
case AssemblyLine0(JSR | BSR, _, _) :: xs => false // TODO
|
case AssemblyLine0(JSR | BSR, _, _) :: xs => false // TODO
|
||||||
case AssemblyLine0(JMP, Absolute, _) :: xs => canOptimize(xs, dir, None) // 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 vy = yCandidate.getOrElse("-")
|
||||||
val vz = zCandidate.getOrElse("-")
|
val vz = zCandidate.getOrElse("-")
|
||||||
lines match {
|
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
|
case (AssemblyLine0(_, Immediate, SubbyteConstant(MemoryAddressConstant(th), _)), _) :: xs
|
||||||
if th.name == vx || th.name == vy || th.name == vz =>
|
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
|
// if an address of a variable is used, then that variable cannot be assigned to a register
|
||||||
None
|
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 |
|
case (AssemblyLine0(_, AbsoluteX | AbsoluteY | LongAbsoluteX |
|
||||||
ZeroPageX | ZeroPageY |
|
ZeroPageX | ZeroPageY |
|
||||||
IndexedY | IndexedX | IndexedZ |
|
IndexedY | IndexedX | IndexedZ |
|
||||||
|
@ -66,4 +66,41 @@ class SecondAssemblyOptimizationSuite extends FunSuite with Matchers {
|
|||||||
| }
|
| }
|
||||||
""".stripMargin) { m => m.readByte(0xc000) should equal(4) }
|
""".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…
Reference in New Issue
Block a user