1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-06-12 06:29:34 +00:00

6502: Two fixes:

– fix writing constants to volatile variables
– fix optimizing variables to registers yet again
This commit is contained in:
Karol Stasiak 2018-12-31 13:18:11 +01:00
parent 2f63eafc3a
commit fb42e77e6e
4 changed files with 60 additions and 19 deletions

View File

@ -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.

View File

@ -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) :: _)

View File

@ -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 {

View 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)
}
}
}