mirror of
https://github.com/KarolS/millfork.git
synced 2024-10-12 09:23:45 +00:00
Fix memset
This commit is contained in:
parent
0ded460840
commit
59afc24db6
@ -1,7 +1,7 @@
|
|||||||
package millfork.compiler.mos
|
package millfork.compiler.mos
|
||||||
|
|
||||||
import millfork.CompilationFlag
|
import millfork.CompilationFlag
|
||||||
import millfork.assembly.mos.AssemblyLine
|
import millfork.assembly.mos.{AssemblyLine, AssemblyLine0}
|
||||||
import millfork.compiler.{BranchSpec, CompilationContext}
|
import millfork.compiler.{BranchSpec, CompilationContext}
|
||||||
import millfork.env.{NumericConstant, Type, VariableInMemory}
|
import millfork.env.{NumericConstant, Type, VariableInMemory}
|
||||||
import millfork.node._
|
import millfork.node._
|
||||||
@ -34,10 +34,31 @@ object MosBulkMemoryOperations {
|
|||||||
case _ => return MosStatementCompiler.compileForStatement(ctx, f)._1
|
case _ => return MosStatementCompiler.compileForStatement(ctx, f)._1
|
||||||
}
|
}
|
||||||
val useTwoRegs = ctx.options.flag(CompilationFlag.OptimizeForSpeed) && ctx.options.zpRegisterSize >= 4
|
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) ++ (
|
val loadReg =
|
||||||
if (useTwoRegs) List(AssemblyLine.zeropage(LDA, reg), AssemblyLine.zeropage(STA, reg,2), AssemblyLine.zeropage(LDA, reg,1), AssemblyLine.zeropage(STA, reg,3))
|
if (useTwoRegs) {
|
||||||
else Nil
|
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 loadSource = MosExpressionCompiler.compileToA(ctx, source)
|
||||||
val loadAll = if (MosExpressionCompiler.changesZpreg(loadSource, 0) || MosExpressionCompiler.changesZpreg(loadSource, 1)) {
|
val loadAll = if (MosExpressionCompiler.changesZpreg(loadSource, 0) || MosExpressionCompiler.changesZpreg(loadSource, 1)) {
|
||||||
loadSource ++ MosExpressionCompiler.preserveRegisterIfNeeded(ctx, MosRegister.A, loadReg)
|
loadSource ++ MosExpressionCompiler.preserveRegisterIfNeeded(ctx, MosRegister.A, loadReg)
|
||||||
@ -53,20 +74,20 @@ object MosBulkMemoryOperations {
|
|||||||
List(
|
List(
|
||||||
AssemblyLine.immediate(LDY, 0x80),
|
AssemblyLine.immediate(LDY, 0x80),
|
||||||
AssemblyLine.label(label),
|
AssemblyLine.label(label),
|
||||||
|
AssemblyLine.implied(DEY),
|
||||||
AssemblyLine.indexedY(STA, reg),
|
AssemblyLine.indexedY(STA, reg),
|
||||||
AssemblyLine.indexedY(STA, reg, 2),
|
AssemblyLine.indexedY(STA, reg, 2),
|
||||||
AssemblyLine.implied(INY),
|
AssemblyLine.implied(DEY),
|
||||||
AssemblyLine.indexedY(STA, reg),
|
AssemblyLine.indexedY(STA, reg),
|
||||||
AssemblyLine.indexedY(STA, reg, 2),
|
AssemblyLine.indexedY(STA, reg, 2),
|
||||||
AssemblyLine.implied(INY),
|
|
||||||
AssemblyLine.relative(BNE, label))
|
AssemblyLine.relative(BNE, label))
|
||||||
} else if (ctx.options.flag(CompilationFlag.OptimizeForSpeed)) {
|
} else if (ctx.options.flag(CompilationFlag.OptimizeForSpeed)) {
|
||||||
List(
|
List(
|
||||||
AssemblyLine.immediate(LDY, 0x80),
|
AssemblyLine.immediate(LDY, 0x80),
|
||||||
AssemblyLine.label(label),
|
AssemblyLine.label(label),
|
||||||
|
AssemblyLine.implied(DEY),
|
||||||
AssemblyLine.indexedY(STA, reg),
|
AssemblyLine.indexedY(STA, reg),
|
||||||
AssemblyLine.indexedY(STA, reg, 2),
|
AssemblyLine.indexedY(STA, reg, 2),
|
||||||
AssemblyLine.implied(INY),
|
|
||||||
AssemblyLine.relative(BNE, label))
|
AssemblyLine.relative(BNE, label))
|
||||||
} else ???
|
} else ???
|
||||||
} else {
|
} else {
|
||||||
@ -113,7 +134,8 @@ object MosBulkMemoryOperations {
|
|||||||
List(
|
List(
|
||||||
AssemblyLine.immediate(LDX, wholePageCount),
|
AssemblyLine.immediate(LDX, wholePageCount),
|
||||||
AssemblyLine.relative(BEQ, labelXSkip),
|
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.zeropage(INC, reg, 1),
|
||||||
AssemblyLine.implied(DEX),
|
AssemblyLine.implied(DEX),
|
||||||
AssemblyLine.relative(BNE, labelX),
|
AssemblyLine.relative(BNE, labelX),
|
||||||
|
@ -54,11 +54,11 @@ object Z80BulkMemoryOperations {
|
|||||||
val calculateAddress = Z80ExpressionCompiler.calculateAddressToHL(ctx, IndexedExpression(array, targetIndexExpression))
|
val calculateAddress = Z80ExpressionCompiler.calculateAddressToHL(ctx, IndexedExpression(array, targetIndexExpression))
|
||||||
val calculateSize = f.direction match {
|
val calculateSize = f.direction match {
|
||||||
case ForDirection.DownTo =>
|
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 =>
|
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)))
|
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 {
|
val (incOp, ldOp) = f.direction match {
|
||||||
case ForDirection.DownTo => DEC_16 -> LDDR
|
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…
Reference in New Issue
Block a user