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:
parent
46ce602a3e
commit
b01c440cf0
@ -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, _) =>
|
||||
|
Loading…
Reference in New Issue
Block a user