mirror of
https://github.com/KarolS/millfork.git
synced 2025-01-26 20:33:02 +00:00
6502: Two fixes:
– fix writing constants to volatile variables – fix optimizing variables to registers yet again
This commit is contained in:
parent
2f63eafc3a
commit
fb42e77e6e
@ -12,6 +12,8 @@
|
||||
|
||||
* 6502: Fixed optimizations using index registers.
|
||||
|
||||
* Fixed volatile-related bugs.
|
||||
|
||||
* Fixed optimizations removing jumps to jumps.
|
||||
|
||||
* Fixed optimizations removing pointless stores to local variables.
|
||||
|
@ -987,21 +987,6 @@ object VariableToRegisterOptimization extends AssemblyOptimization[AssemblyLine]
|
||||
// these TAY's may get optimized away by a different optimization
|
||||
tailcall(inlineVars(xCandidate, yCandidate, zCandidate, aCandidate, features, xs)).map(AssemblyLine.implied(TAY) :: _)
|
||||
|
||||
case (AssemblyLine(LDA, am, param, Elidability.Elidable, s1), _) :: (AssemblyLine(STA, Absolute | ZeroPage, MemoryAddressConstant(th), Elidability.Elidable, s2), _) :: xs
|
||||
if th.name == vx && LdxAddrModes(am) =>
|
||||
// these TXA's may get optimized away by a different optimization
|
||||
tailcall(inlineVars(xCandidate, yCandidate, zCandidate, aCandidate, features, xs)).map(AssemblyLine(LDX, am, param).pos(s1, s2) :: AssemblyLine.implied(TXA).pos(s1, s2) :: _)
|
||||
|
||||
case (AssemblyLine(LDA, am, param, Elidability.Elidable, s1), _) :: (AssemblyLine(STA, Absolute | ZeroPage, MemoryAddressConstant(th), Elidability.Elidable, s2), _) :: xs
|
||||
if th.name == vy && LdyAddrModes(am) =>
|
||||
// these TYA's may get optimized away by a different optimization
|
||||
tailcall(inlineVars(xCandidate, yCandidate, zCandidate, aCandidate, features, xs)).map(AssemblyLine(LDY, am, param).pos(s1, s2) :: AssemblyLine.implied(TYA).pos(s1, s2) :: _)
|
||||
|
||||
case (AssemblyLine(LDA, am, param, Elidability.Elidable, s1), _) :: (AssemblyLine(STA, Absolute | ZeroPage, MemoryAddressConstant(th), Elidability.Elidable, s2), _) :: xs
|
||||
if th.name == vz && LdzAddrModes(am) =>
|
||||
// these TZA's may get optimized away by a different optimization
|
||||
tailcall(inlineVars(xCandidate, yCandidate, zCandidate, aCandidate, features, xs)).map(AssemblyLine(LDZ, am, param).pos(s1, s2) :: AssemblyLine.implied(TZA).pos(s1, s2) :: _)
|
||||
|
||||
case (AssemblyLine(LDA, Absolute | ZeroPage, MemoryAddressConstant(th), _, s1), _) :: (AssemblyLine(CMP, am, param, Elidability.Elidable, s2), _) :: xs
|
||||
if th.name == vx && CpxyzAddrModes(am) && isNot(vx, param) =>
|
||||
// ditto
|
||||
@ -1045,6 +1030,21 @@ object VariableToRegisterOptimization extends AssemblyOptimization[AssemblyLine]
|
||||
if th.name == va =>
|
||||
tailcall(inlineVars(xCandidate, yCandidate, zCandidate, aCandidate, features, xs)).map(AssemblyLine.implied(TAY).pos(s) :: _)
|
||||
|
||||
case (AssemblyLine(LDA, am, param, Elidability.Elidable, s1), _) :: (AssemblyLine(STA, Absolute | ZeroPage, MemoryAddressConstant(th), Elidability.Elidable, s2), _) :: xs
|
||||
if th.name == vx && LdxAddrModes(am) =>
|
||||
// these TXA's may get optimized away by a different optimization
|
||||
tailcall(inlineVars(xCandidate, yCandidate, zCandidate, aCandidate, features, xs)).map(AssemblyLine(LDX, am, param).pos(s1, s2) :: AssemblyLine.implied(TXA).pos(s1, s2) :: _)
|
||||
|
||||
case (AssemblyLine(LDA, am, param, Elidability.Elidable, s1), _) :: (AssemblyLine(STA, Absolute | ZeroPage, MemoryAddressConstant(th), Elidability.Elidable, s2), _) :: xs
|
||||
if th.name == vy && LdyAddrModes(am) =>
|
||||
// these TYA's may get optimized away by a different optimization
|
||||
tailcall(inlineVars(xCandidate, yCandidate, zCandidate, aCandidate, features, xs)).map(AssemblyLine(LDY, am, param).pos(s1, s2) :: AssemblyLine.implied(TYA).pos(s1, s2) :: _)
|
||||
|
||||
case (AssemblyLine(LDA, am, param, Elidability.Elidable, s1), _) :: (AssemblyLine(STA, Absolute | ZeroPage, MemoryAddressConstant(th), Elidability.Elidable, s2), _) :: xs
|
||||
if th.name == vz && LdzAddrModes(am) =>
|
||||
// these TZA's may get optimized away by a different optimization
|
||||
tailcall(inlineVars(xCandidate, yCandidate, zCandidate, aCandidate, features, xs)).map(AssemblyLine(LDZ, am, param).pos(s1, s2) :: AssemblyLine.implied(TZA).pos(s1, s2) :: _)
|
||||
|
||||
case (AssemblyLine(STA, Absolute | ZeroPage, MemoryAddressConstant(th), _, s), _) :: xs
|
||||
if th.name == vx =>
|
||||
tailcall(inlineVars(xCandidate, yCandidate, zCandidate, aCandidate, features, xs)).map(AssemblyLine.implied(TAX).pos(s) :: _)
|
||||
|
@ -1,6 +1,7 @@
|
||||
package millfork.compiler.mos
|
||||
|
||||
import millfork.CompilationFlag
|
||||
import millfork.assembly.Elidability
|
||||
import millfork.assembly.mos.AddrMode._
|
||||
import millfork.assembly.mos.Opcode._
|
||||
import millfork.assembly.mos._
|
||||
@ -38,23 +39,24 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
||||
AssemblyLine(LDA, Immediate, expr.hiByte),
|
||||
AssemblyLine(LDY, Immediate, expr.loByte))
|
||||
case m: VariableInMemory =>
|
||||
val elidability = if (m.isVolatile) Elidability.Volatile else Elidability.Elidable
|
||||
val addrMode = if (m.zeropage) ZeroPage else Absolute
|
||||
val addr = m.toAddress
|
||||
m.typ.size match {
|
||||
case 0 => Nil
|
||||
case 1 => List(
|
||||
AssemblyLine(LDA, Immediate, expr.loByte),
|
||||
AssemblyLine(STA, addrMode, addr))
|
||||
AssemblyLine(STA, addrMode, addr, elidability = elidability))
|
||||
case 2 => if (ctx.options.flag(CompilationFlag.EmitNative65816Opcodes)) {
|
||||
AssemblyLine.accu16 :: AssemblyLine(LDA_W, WordImmediate, expr) ::(AssemblyLine.variable(ctx, STA_W, m) :+ AssemblyLine.accu8)
|
||||
} else List(
|
||||
AssemblyLine(LDA, Immediate, expr.loByte),
|
||||
AssemblyLine(STA, addrMode, addr),
|
||||
AssemblyLine(STA, addrMode, addr, elidability = elidability),
|
||||
AssemblyLine(LDA, Immediate, expr.hiByte),
|
||||
AssemblyLine(STA, addrMode, addr + 1))
|
||||
AssemblyLine(STA, addrMode, addr + 1, elidability = elidability))
|
||||
case s => List.tabulate(s)(i => List(
|
||||
AssemblyLine(LDA, Immediate, expr.subbyte(i)),
|
||||
AssemblyLine(STA, addrMode, addr + i))).flatten
|
||||
AssemblyLine(STA, addrMode, addr + i, elidability = elidability))).flatten
|
||||
}
|
||||
case m@StackVariable(_, t, offset) =>
|
||||
t.size match {
|
||||
|
37
src/test/scala/millfork/test/VolatileSuite.scala
Normal file
37
src/test/scala/millfork/test/VolatileSuite.scala
Normal file
@ -0,0 +1,37 @@
|
||||
package millfork.test
|
||||
|
||||
import millfork.Cpu
|
||||
import millfork.test.emu.{EmuBenchmarkRun, EmuCrossPlatformBenchmarkRun, EmuSuperOptimizedRun, EmuUltraBenchmarkRun}
|
||||
import org.scalatest.{FunSuite, Matchers}
|
||||
|
||||
/**
|
||||
* @author Karol Stasiak
|
||||
*/
|
||||
class VolatileSuite extends FunSuite with Matchers {
|
||||
|
||||
test("Basic volatile test") {
|
||||
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Z80)(
|
||||
"""
|
||||
| word addr @$c000
|
||||
| volatile byte output @$c0ea
|
||||
| byte thing
|
||||
| void main () {
|
||||
| f(55)
|
||||
| addr = f.addr
|
||||
| }
|
||||
| noinline void f(byte x) {
|
||||
| output = 5
|
||||
| thing = x
|
||||
| output = x
|
||||
| }
|
||||
""".stripMargin) { m =>
|
||||
m.readByte(0xc0ea) should equal(55)
|
||||
var f = m.readWord(0xc000)
|
||||
var count = 0
|
||||
do {
|
||||
if (m.readWord(f) == 0xc0ea) count +=1
|
||||
f += 1
|
||||
} while (count < 2)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user