mirror of
https://github.com/KarolS/millfork.git
synced 2025-01-12 03:30:09 +00:00
Fix memset
This commit is contained in:
parent
0ded460840
commit
59afc24db6
@ -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),
|
||||
|
@ -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
|
||||
|
51
src/test/scala/millfork/test/MemsetSuite.scala
Normal file
51
src/test/scala/millfork/test/MemsetSuite.scala
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user