From b01c440cf00823fc190bc499e2d726f013d6328d Mon Sep 17 00:00:00 2001 From: Karol Stasiak Date: Wed, 8 Aug 2018 01:38:49 +0200 Subject: [PATCH] 6502: Improve memset --- .../mos/MosBulkMemoryOperations.scala | 83 +++++++++++++++---- 1 file changed, 67 insertions(+), 16 deletions(-) diff --git a/src/main/scala/millfork/compiler/mos/MosBulkMemoryOperations.scala b/src/main/scala/millfork/compiler/mos/MosBulkMemoryOperations.scala index 7aa65351..25faa178 100644 --- a/src/main/scala/millfork/compiler/mos/MosBulkMemoryOperations.scala +++ b/src/main/scala/millfork/compiler/mos/MosBulkMemoryOperations.scala @@ -1,8 +1,9 @@ package millfork.compiler.mos +import millfork.CompilationFlag import millfork.assembly.mos.AssemblyLine import millfork.compiler.{BranchSpec, CompilationContext} -import millfork.env.{Label, NumericConstant, Type, VariableInMemory} +import millfork.env.{NumericConstant, Type, VariableInMemory} import millfork.node._ import millfork.assembly.mos.Opcode._ @@ -32,43 +33,93 @@ object MosBulkMemoryOperations { case Some(c) => c.quickSimplify 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 loadAll = if (MosExpressionCompiler.changesZpreg(loadSource, 0) || MosExpressionCompiler.changesZpreg(loadSource, 1)) { loadSource ++ MosExpressionCompiler.preserveRegisterIfNeeded(ctx, MosRegister.A, loadReg) } else { loadReg ++ loadSource } - val wholePageCount = size.hiByte - val setWholePages = wholePageCount match { - case NumericConstant(0, _) => Nil - case NumericConstant(1, _) => - val label = ctx.nextLabel("ms") - List( + val wholePageCount = size.hiByte.quickSimplify + + def fillOnePage: List[AssemblyLine] = { + val label = ctx.nextLabel("ms") + if (useTwoRegs) { + 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.label(label), AssemblyLine.indexedY(STA, reg), AssemblyLine.implied(INY), AssemblyLine.relative(BNE, label)) + } + } + } + + val setWholePages = wholePageCount match { + case NumericConstant(0, _) => Nil + case NumericConstant(1, _) => + fillOnePage case _ => val labelX = ctx.nextLabel("ms") val labelXSkip = ctx.nextLabel("ms") - val labelY = ctx.nextLabel("ms") List( AssemblyLine.immediate(LDX, wholePageCount), AssemblyLine.relative(BEQ, labelXSkip), - AssemblyLine.label(labelX), - AssemblyLine.immediate(LDY, 0), - AssemblyLine.label(labelY), - AssemblyLine.indexedY(STA, reg), - AssemblyLine.implied(INY), - AssemblyLine.relative(BNE, labelY), + AssemblyLine.label(labelX)) ++ fillOnePage ++ List( AssemblyLine.zeropage(INC, reg, 1), AssemblyLine.implied(DEX), AssemblyLine.relative(BNE, labelX), AssemblyLine.label(labelXSkip)) } - val restSize = size.loByte + val restSize = size.loByte.quickSimplify val setRest = restSize match { case NumericConstant(0, _) => Nil case NumericConstant(1, _) =>