1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-08-13 02:28:59 +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
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, _) =>