diff --git a/src/main/scala/millfork/compiler/mos/MosExpressionCompiler.scala b/src/main/scala/millfork/compiler/mos/MosExpressionCompiler.scala index 7cd19ff9..0a1283ee 100644 --- a/src/main/scala/millfork/compiler/mos/MosExpressionCompiler.scala +++ b/src/main/scala/millfork/compiler/mos/MosExpressionCompiler.scala @@ -9,6 +9,7 @@ import millfork.compiler._ import millfork.env._ import millfork.error.ConsoleLogger import millfork.node.{MosRegister, _} +import millfork.output.NoAlignment /** * @author Karol Stasiak */ @@ -180,7 +181,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] { val reg = ctx.env.get[VariableInMemory]("__reg") val compileIndex = compile(ctx, indexExpression, Some(MosExpressionCompiler.getExpressionType(ctx, indexExpression) -> RegisterVariable(MosRegister.YA, w)), BranchSpec.None) val prepareRegister = pointy match { - case ConstantPointy(addr, _, _, _, _) => + case ConstantPointy(addr, _, _, _, _, _) => List( AssemblyLine.implied(CLC), AssemblyLine.immediate(ADC, addr.hiByte), @@ -295,7 +296,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] { wrapWordIndexingStorage(prepareWordIndexing(ctx, p, indexExpr)) case (p: ConstantPointy, Some(v), 2, _) => val w = env.get[VariableType]("word") - wrapWordIndexingStorage(prepareWordIndexing(ctx, ConstantPointy(p.value + constIndex, None, if (constIndex.isProvablyZero) p.size else None, w, p.elementType), v)) + wrapWordIndexingStorage(prepareWordIndexing(ctx, ConstantPointy(p.value + constIndex, None, if (constIndex.isProvablyZero) p.size else None, w, p.elementType, NoAlignment), v)) case (p: ConstantPointy, Some(v), 1, _) => storeToArrayAtUnknownIndex(v, p.value) //TODO: should there be a type check or a zeropage check? @@ -614,7 +615,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] { None, if (constantIndex.isProvablyZero) a.size else None, env.get[VariableType]("word"), - a.elementType), v) ++ loadFromReg() + a.elementType, NoAlignment), v) ++ loadFromReg() case (a: VariablePointy, _, 2, _) => prepareWordIndexing(ctx, a, indexExpr) ++ loadFromReg() case (p:VariablePointy, None, 0 | 1, _) => diff --git a/src/main/scala/millfork/compiler/z80/Z80ExpressionCompiler.scala b/src/main/scala/millfork/compiler/z80/Z80ExpressionCompiler.scala index 0ba6bb9e..16268d48 100644 --- a/src/main/scala/millfork/compiler/z80/Z80ExpressionCompiler.scala +++ b/src/main/scala/millfork/compiler/z80/Z80ExpressionCompiler.scala @@ -7,6 +7,7 @@ import millfork.env._ import millfork.node.{ZRegister, _} import millfork.assembly.z80.ZOpcode._ import millfork.error.ConsoleLogger +import millfork.output.{NoAlignment, WithinPageAlignment} /** * @author Karol Stasiak @@ -940,13 +941,21 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] { val pointy = env.getPointy(i.name) AbstractExpressionCompiler.checkIndexType(ctx, pointy, i.index) pointy match { - case ConstantPointy(baseAddr, _, _, _, _) => + case ConstantPointy(baseAddr, _, size, _, _, alignment) => env.evalVariableAndConstantSubParts(i.index) match { case (None, offset) => List(ZLine.ldImm16(ZRegister.HL, (baseAddr + offset).quickSimplify)) case (Some(index), offset) => - List(ZLine.ldImm16(ZRegister.BC, (baseAddr + offset).quickSimplify)) ++ - stashBCIfChanged(ctx, compileToHL(ctx, index)) ++ - List(ZLine.registers(ADD_16, ZRegister.HL, ZRegister.BC)) + val constantPart = (baseAddr + offset).quickSimplify + if (getExpressionType(ctx, i.index).size == 1 && size.exists(_ < 256) && alignment == WithinPageAlignment) { + compileToA(ctx, i.index) ++ List( + ZLine.imm8(ADD, constantPart.loByte), + ZLine.ld8(ZRegister.L, ZRegister.A), + ZLine.ldImm8(ZRegister.H, constantPart.hiByte)) + } else { + List(ZLine.ldImm16(ZRegister.BC, constantPart)) ++ + stashBCIfChanged(ctx, compileToHL(ctx, index)) ++ + List(ZLine.registers(ADD_16, ZRegister.HL, ZRegister.BC)) + } } case VariablePointy(varAddr, _, _) => env.eval(i.index) match { diff --git a/src/main/scala/millfork/env/Environment.scala b/src/main/scala/millfork/env/Environment.scala index b456f8b6..b9a660ec 100644 --- a/src/main/scala/millfork/env/Environment.scala +++ b/src/main/scala/millfork/env/Environment.scala @@ -294,13 +294,13 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa InitializedMemoryVariable UninitializedMemoryVariable getArrayOrPointer(name) match { - case th@InitializedArray(_, _, cs, _, i, e, _) => ConstantPointy(th.toAddress, Some(name), Some(cs.length), i, e) - case th@UninitializedArray(_, size, _, i, e, _) => ConstantPointy(th.toAddress, Some(name), Some(size), i, e) - case th@RelativeArray(_, _, size, _, i, e) => ConstantPointy(th.toAddress, Some(name), Some(size), i, e) + case th@InitializedArray(_, _, cs, _, i, e, _) => ConstantPointy(th.toAddress, Some(name), Some(cs.length), i, e, th.alignment) + case th@UninitializedArray(_, size, _, i, e, _) => ConstantPointy(th.toAddress, Some(name), Some(size), i, e, th.alignment) + case th@RelativeArray(_, _, size, _, i, e) => ConstantPointy(th.toAddress, Some(name), Some(size), i, e, NoAlignment) case ConstantThing(_, value, typ) if typ.size <= 2 && typ.isPointy => val b = get[VariableType]("byte") val w = get[VariableType]("word") - ConstantPointy(value, None, None, w, b) + ConstantPointy(value, None, None, w, b, NoAlignment) case th:VariableInMemory if th.typ.isPointy=> val b = get[VariableType]("byte") val w = get[VariableType]("word") @@ -309,7 +309,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa log.error(s"$name is not a valid pointer or array") val b = get[VariableType]("byte") val w = get[VariableType]("word") - ConstantPointy(Constant.Zero, None, None, w, b) + ConstantPointy(Constant.Zero, None, None, w, b, NoAlignment) } } @@ -872,9 +872,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa } private def defaultArrayAlignment(options: CompilationOptions, size: Long): MemoryAlignment = { - if (options.platform.cpuFamily == CpuFamily.M6502 && - options.flag(CompilationFlag.OptimizeForSpeed) && - size <= 256) WithinPageAlignment + if (options.flag(CompilationFlag.OptimizeForSpeed) && size <= 256 && size != 0) WithinPageAlignment else NoAlignment } diff --git a/src/main/scala/millfork/env/Pointy.scala b/src/main/scala/millfork/env/Pointy.scala index 154f0871..d5e2681d 100644 --- a/src/main/scala/millfork/env/Pointy.scala +++ b/src/main/scala/millfork/env/Pointy.scala @@ -1,5 +1,7 @@ package millfork.env +import millfork.output.MemoryAlignment + trait Pointy { def name: Option[String] def indexType: VariableType @@ -10,4 +12,4 @@ case class VariablePointy(addr: Constant, indexType: VariableType, elementType: override def name: Option[String] = None } -case class ConstantPointy(value: Constant, name: Option[String], size: Option[Int], indexType: VariableType, elementType: VariableType) extends Pointy +case class ConstantPointy(value: Constant, name: Option[String], size: Option[Int], indexType: VariableType, elementType: VariableType, alignment: MemoryAlignment) extends Pointy