1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-07-07 21:28:59 +00:00

Fix memset

This commit is contained in:
Karol Stasiak 2018-12-27 14:19:04 +01:00
parent 0ded460840
commit 59afc24db6
3 changed files with 85 additions and 12 deletions

View File

@ -1,7 +1,7 @@
package millfork.compiler.mos
import millfork.CompilationFlag
import millfork.assembly.mos.AssemblyLine
import millfork.assembly.mos.{AssemblyLine, AssemblyLine0}
import millfork.compiler.{BranchSpec, CompilationContext}
import millfork.env.{NumericConstant, Type, VariableInMemory}
import millfork.node._
@ -34,10 +34,31 @@ object MosBulkMemoryOperations {
case _ => return MosStatementCompiler.compileForStatement(ctx, f)._1
}
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 loadReg =
if (useTwoRegs) {
import millfork.assembly.mos.AddrMode._
val first = MosExpressionCompiler.compile(ctx, SumExpression(List(false -> f.start, false -> target.index), decimal = false), Some(w -> reg), BranchSpec.None)
first ++ (first match {
case List(AssemblyLine0(LDA, Immediate, l), AssemblyLine0(LDA, ZeroPage, r0), AssemblyLine0(LDA, Immediate, h), AssemblyLine0(LDA, ZeroPage, r1))
if (r1-r0).quickSimplify.isProvably(1) =>
val c = (h.asl(8) + l+ 0x80).quickSimplify
List(
AssemblyLine.immediate(LDA, c.loByte),
AssemblyLine.zeropage(STA, reg, 2),
AssemblyLine.immediate(LDA, c.subbyte(1)),
AssemblyLine.zeropage(STA, reg, 3))
case _ =>
List(
AssemblyLine.zeropage(LDA, reg),
AssemblyLine.implied(CLC),
AssemblyLine.immediate(ADC, 0x80),
AssemblyLine.zeropage(STA, reg, 2),
AssemblyLine.zeropage(LDA, reg, 1),
AssemblyLine.immediate(ADC, 0),
AssemblyLine.zeropage(STA, reg, 3))
})
}else MosExpressionCompiler.compile(ctx, SumExpression(List(false -> f.start, false -> target.index), decimal = false), Some(w -> reg), BranchSpec.None)
val loadSource = MosExpressionCompiler.compileToA(ctx, source)
val loadAll = if (MosExpressionCompiler.changesZpreg(loadSource, 0) || MosExpressionCompiler.changesZpreg(loadSource, 1)) {
loadSource ++ MosExpressionCompiler.preserveRegisterIfNeeded(ctx, MosRegister.A, loadReg)
@ -53,20 +74,20 @@ object MosBulkMemoryOperations {
List(
AssemblyLine.immediate(LDY, 0x80),
AssemblyLine.label(label),
AssemblyLine.implied(DEY),
AssemblyLine.indexedY(STA, reg),
AssemblyLine.indexedY(STA, reg, 2),
AssemblyLine.implied(INY),
AssemblyLine.implied(DEY),
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.implied(DEY),
AssemblyLine.indexedY(STA, reg),
AssemblyLine.indexedY(STA, reg, 2),
AssemblyLine.implied(INY),
AssemblyLine.relative(BNE, label))
} else ???
} else {
@ -113,7 +134,8 @@ object MosBulkMemoryOperations {
List(
AssemblyLine.immediate(LDX, wholePageCount),
AssemblyLine.relative(BEQ, labelXSkip),
AssemblyLine.label(labelX)) ++ fillOnePage ++ List(
AssemblyLine.label(labelX)) ++ fillOnePage ++
(if (useTwoRegs) List(AssemblyLine.zeropage(INC, reg, 3)) else Nil) ++ List(
AssemblyLine.zeropage(INC, reg, 1),
AssemblyLine.implied(DEX),
AssemblyLine.relative(BNE, labelX),

View File

@ -54,11 +54,11 @@ object Z80BulkMemoryOperations {
val calculateAddress = Z80ExpressionCompiler.calculateAddressToHL(ctx, IndexedExpression(array, targetIndexExpression))
val calculateSize = f.direction match {
case ForDirection.DownTo =>
Z80ExpressionCompiler.stashHLIfChanged(ctx, Z80ExpressionCompiler.compileToBC(ctx, SumExpression(List(false -> f.start, true -> f.end, false -> LiteralExpression(1, 1)), decimal = false)))
Z80ExpressionCompiler.stashHLIfChanged(ctx, Z80ExpressionCompiler.compileToBC(ctx, SumExpression(List(false -> f.start, true -> f.end), decimal = false)))
case ForDirection.To | ForDirection.ParallelTo =>
Z80ExpressionCompiler.stashHLIfChanged(ctx, Z80ExpressionCompiler.compileToBC(ctx, SumExpression(List(false -> f.end, true -> f.start, false -> LiteralExpression(1, 1)), decimal = false)))
case ForDirection.Until | ForDirection.ParallelUntil =>
Z80ExpressionCompiler.stashHLIfChanged(ctx, Z80ExpressionCompiler.compileToBC(ctx, SumExpression(List(false -> f.end, true -> f.start), decimal = false)))
case ForDirection.Until | ForDirection.ParallelUntil =>
Z80ExpressionCompiler.stashHLIfChanged(ctx, Z80ExpressionCompiler.compileToBC(ctx, SumExpression(List(false -> f.end, true -> f.start, true -> LiteralExpression(1, 1)), decimal = false)))
}
val (incOp, ldOp) = f.direction match {
case ForDirection.DownTo => DEC_16 -> LDDR

View File

@ -0,0 +1,51 @@
package millfork.test
import millfork.Cpu
import millfork.test.emu.EmuCrossPlatformBenchmarkRun
import org.scalatest.{AppendedClues, FunSuite, Matchers}
/**
* @author Karol Stasiak
*/
class MemsetSuite extends FunSuite with Matchers with AppendedClues {
test("memset $1000") {
memsetCase(0x1000)
}
test("memset $40") {
memsetCase(0x40)
}
test("memset $80") {
memsetCase(0x80)
}
test("memset $100") {
memsetCase(0x100)
}
test("memset $200") {
memsetCase(0x200)
}
test("memset $fff") {
memsetCase(0xfff)
}
def memsetCase(size: Int): Unit = {
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Intel8080, Cpu.Z80)(
"const word SIZE = " + size + """
| array output [SIZE] @$c000
| void main () {
| pointer p
| for p,output.addr,paralleluntil,output.addr+SIZE {
| p[0] = 42
| }
| }
""".stripMargin) { m =>
for(addr <- 0 until 0x1000) {
if (addr < size) {
m.readByte(addr + 0xc000) should equal(42) withClue f"$$$addr%04x"
} else {
m.readByte(addr + 0xc000) should equal(0) withClue f"$$$addr%04x"
}
}
}
}
}