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

6502: Improve memset

This commit is contained in:
Karol Stasiak 2018-08-08 01:38:49 +02:00
parent 46ce602a3e
commit b01c440cf0

View File

@ -1,8 +1,9 @@
package millfork.compiler.mos package millfork.compiler.mos
import millfork.CompilationFlag
import millfork.assembly.mos.AssemblyLine import millfork.assembly.mos.AssemblyLine
import millfork.compiler.{BranchSpec, CompilationContext} import millfork.compiler.{BranchSpec, CompilationContext}
import millfork.env.{Label, NumericConstant, Type, VariableInMemory} import millfork.env.{NumericConstant, Type, VariableInMemory}
import millfork.node._ import millfork.node._
import millfork.assembly.mos.Opcode._ import millfork.assembly.mos.Opcode._
@ -32,43 +33,93 @@ object MosBulkMemoryOperations {
case Some(c) => c.quickSimplify case Some(c) => c.quickSimplify
case _ => return MosStatementCompiler.compileForStatement(ctx, f) case _ => return MosStatementCompiler.compileForStatement(ctx, f)
} }
val loadReg = MosExpressionCompiler.compile(ctx, SumExpression(List(false -> f.start, false -> target.index), decimal = false), Some(w -> reg), BranchSpec.None) val useTwoRegs = ctx.options.flag(CompilationFlag.OptimizeForSpeed) && ctx.options.zpRegisterSize >= 4
val loadReg = MosExpressionCompiler.compile(ctx, SumExpression(List(false -> f.start, false -> target.index), decimal = false), Some(w -> reg), BranchSpec.None) ++ (
if (useTwoRegs) List(AssemblyLine.zeropage(LDA, reg), AssemblyLine.zeropage(STA, reg,2), AssemblyLine.zeropage(LDA, reg,1), AssemblyLine.zeropage(STA, reg,3))
else Nil
)
val loadSource = MosExpressionCompiler.compileToA(ctx, source) val loadSource = MosExpressionCompiler.compileToA(ctx, source)
val loadAll = if (MosExpressionCompiler.changesZpreg(loadSource, 0) || MosExpressionCompiler.changesZpreg(loadSource, 1)) { val loadAll = if (MosExpressionCompiler.changesZpreg(loadSource, 0) || MosExpressionCompiler.changesZpreg(loadSource, 1)) {
loadSource ++ MosExpressionCompiler.preserveRegisterIfNeeded(ctx, MosRegister.A, loadReg) loadSource ++ MosExpressionCompiler.preserveRegisterIfNeeded(ctx, MosRegister.A, loadReg)
} else { } else {
loadReg ++ loadSource loadReg ++ loadSource
} }
val wholePageCount = size.hiByte val wholePageCount = size.hiByte.quickSimplify
val setWholePages = wholePageCount match {
case NumericConstant(0, _) => Nil def fillOnePage: List[AssemblyLine] = {
case NumericConstant(1, _) => val label = ctx.nextLabel("ms")
val label = ctx.nextLabel("ms") if (useTwoRegs) {
List( if (ctx.options.flag(CompilationFlag.OptimizeForSonicSpeed)) {
List(
AssemblyLine.immediate(LDY, 0x80),
AssemblyLine.label(label),
AssemblyLine.indexedY(STA, reg),
AssemblyLine.indexedY(STA, reg, 2),
AssemblyLine.implied(INY),
AssemblyLine.indexedY(STA, reg),
AssemblyLine.indexedY(STA, reg, 2),
AssemblyLine.implied(INY),
AssemblyLine.relative(BNE, label))
} else if (ctx.options.flag(CompilationFlag.OptimizeForSpeed)) {
List(
AssemblyLine.immediate(LDY, 0x80),
AssemblyLine.label(label),
AssemblyLine.indexedY(STA, reg),
AssemblyLine.indexedY(STA, reg, 2),
AssemblyLine.implied(INY),
AssemblyLine.relative(BNE, label))
} else ???
} else {
if (ctx.options.flag(CompilationFlag.OptimizeForSonicSpeed)) {
List(
AssemblyLine.immediate(LDY, 0),
AssemblyLine.label(label),
AssemblyLine.indexedY(STA, reg),
AssemblyLine.implied(INY),
AssemblyLine.indexedY(STA, reg),
AssemblyLine.implied(INY),
AssemblyLine.indexedY(STA, reg),
AssemblyLine.implied(INY),
AssemblyLine.indexedY(STA, reg),
AssemblyLine.implied(INY),
AssemblyLine.relative(BNE, label))
} else if (ctx.options.flag(CompilationFlag.OptimizeForSpeed)) {
List(
AssemblyLine.immediate(LDY, 0),
AssemblyLine.label(label),
AssemblyLine.indexedY(STA, reg),
AssemblyLine.implied(INY),
AssemblyLine.indexedY(STA, reg),
AssemblyLine.implied(INY),
AssemblyLine.relative(BNE, label))
} else {
List(
AssemblyLine.immediate(LDY, 0), AssemblyLine.immediate(LDY, 0),
AssemblyLine.label(label), AssemblyLine.label(label),
AssemblyLine.indexedY(STA, reg), AssemblyLine.indexedY(STA, reg),
AssemblyLine.implied(INY), AssemblyLine.implied(INY),
AssemblyLine.relative(BNE, label)) AssemblyLine.relative(BNE, label))
}
}
}
val setWholePages = wholePageCount match {
case NumericConstant(0, _) => Nil
case NumericConstant(1, _) =>
fillOnePage
case _ => case _ =>
val labelX = ctx.nextLabel("ms") val labelX = ctx.nextLabel("ms")
val labelXSkip = ctx.nextLabel("ms") val labelXSkip = ctx.nextLabel("ms")
val labelY = ctx.nextLabel("ms")
List( List(
AssemblyLine.immediate(LDX, wholePageCount), AssemblyLine.immediate(LDX, wholePageCount),
AssemblyLine.relative(BEQ, labelXSkip), AssemblyLine.relative(BEQ, labelXSkip),
AssemblyLine.label(labelX), AssemblyLine.label(labelX)) ++ fillOnePage ++ List(
AssemblyLine.immediate(LDY, 0),
AssemblyLine.label(labelY),
AssemblyLine.indexedY(STA, reg),
AssemblyLine.implied(INY),
AssemblyLine.relative(BNE, labelY),
AssemblyLine.zeropage(INC, reg, 1), AssemblyLine.zeropage(INC, reg, 1),
AssemblyLine.implied(DEX), AssemblyLine.implied(DEX),
AssemblyLine.relative(BNE, labelX), AssemblyLine.relative(BNE, labelX),
AssemblyLine.label(labelXSkip)) AssemblyLine.label(labelXSkip))
} }
val restSize = size.loByte val restSize = size.loByte.quickSimplify
val setRest = restSize match { val setRest = restSize match {
case NumericConstant(0, _) => Nil case NumericConstant(0, _) => Nil
case NumericConstant(1, _) => case NumericConstant(1, _) =>