diff --git a/src/main/scala/millfork/env/Constant.scala b/src/main/scala/millfork/env/Constant.scala index a64643bd..515b9675 100644 --- a/src/main/scala/millfork/env/Constant.scala +++ b/src/main/scala/millfork/env/Constant.scala @@ -201,7 +201,11 @@ case class MemoryAddressConstant(var thing: ThingInMemory) extends Constant { } override def isProvablyDivisibleBy256: Boolean = thing match { - case t:PreallocableThing => t.alignment match { + case t: PreallocableThing => t.alignment match { + case DivisibleAlignment(divisor) => divisor.&(0xff) == 0 + case _ => false + } + case t: UninitializedMemory => t.alignment match { case DivisibleAlignment(divisor) => divisor.&(0xff) == 0 case _ => false } @@ -228,7 +232,9 @@ case class SubbyteConstant(base: Constant, index: Int) extends Constant { } else { NumericConstant((x >> (index * 8)) & 0xff, 1) } - case _ => SubbyteConstant(simplified, index) + case _ => + if (index == 0 && simplified.isProvablyDivisibleBy256) Constant.Zero + else SubbyteConstant(simplified, index) } } diff --git a/src/main/scala/millfork/env/Environment.scala b/src/main/scala/millfork/env/Environment.scala index 003d4987..b5e90037 100644 --- a/src/main/scala/millfork/env/Environment.scala +++ b/src/main/scala/millfork/env/Environment.scala @@ -1002,6 +1002,9 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa } def registerArray(stmt: ArrayDeclarationStatement, options: CompilationOptions): Unit = { + if (options.flag(CompilationFlag.LUnixRelocatableCode) && stmt.alignment.exists(_.isMultiplePages)) { + log.error("Invalid alignment for LUnix code", stmt.position) + } val b = get[VariableType]("byte") val w = get[VariableType]("word") val p = get[Type]("pointer") @@ -1036,7 +1039,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa declaredBank = stmt.bank, indexType, b) } addThing(array, stmt.position) - registerAddressConstant(UninitializedMemoryVariable(stmt.name, p, VariableAllocationMethod.None, stmt.bank, NoAlignment, isVolatile = false), stmt.position, options) + registerAddressConstant(UninitializedMemoryVariable(stmt.name, p, VariableAllocationMethod.None, stmt.bank, alignment, isVolatile = false), stmt.position, options) val a = address match { case None => array.toAddress case Some(aa) => aa diff --git a/src/main/scala/millfork/output/MemoryAlignment.scala b/src/main/scala/millfork/output/MemoryAlignment.scala index 0caa7f4d..d082fc89 100644 --- a/src/main/scala/millfork/output/MemoryAlignment.scala +++ b/src/main/scala/millfork/output/MemoryAlignment.scala @@ -3,8 +3,18 @@ package millfork.output /** * @author Karol Stasiak */ -sealed trait MemoryAlignment +sealed trait MemoryAlignment { + def isMultiplePages: Boolean +} -case object NoAlignment extends MemoryAlignment -case object WithinPageAlignment extends MemoryAlignment -case class DivisibleAlignment(divisor: Int) extends MemoryAlignment +case object NoAlignment extends MemoryAlignment { + override def isMultiplePages: Boolean = false +} + +case object WithinPageAlignment extends MemoryAlignment { + override def isMultiplePages: Boolean = false +} + +case class DivisibleAlignment(divisor: Int) extends MemoryAlignment { + override def isMultiplePages: Boolean = divisor > 256 +}