1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-09-10 11:54:30 +00:00

Z80: Faster array indexing

This commit is contained in:
Karol Stasiak 2018-08-08 17:50:27 +02:00
parent 8b09941cef
commit 019547aae8
4 changed files with 26 additions and 16 deletions

View File

@ -9,6 +9,7 @@ import millfork.compiler._
import millfork.env._ import millfork.env._
import millfork.error.ConsoleLogger import millfork.error.ConsoleLogger
import millfork.node.{MosRegister, _} import millfork.node.{MosRegister, _}
import millfork.output.NoAlignment
/** /**
* @author Karol Stasiak * @author Karol Stasiak
*/ */
@ -180,7 +181,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
val reg = ctx.env.get[VariableInMemory]("__reg") val reg = ctx.env.get[VariableInMemory]("__reg")
val compileIndex = compile(ctx, indexExpression, Some(MosExpressionCompiler.getExpressionType(ctx, indexExpression) -> RegisterVariable(MosRegister.YA, w)), BranchSpec.None) val compileIndex = compile(ctx, indexExpression, Some(MosExpressionCompiler.getExpressionType(ctx, indexExpression) -> RegisterVariable(MosRegister.YA, w)), BranchSpec.None)
val prepareRegister = pointy match { val prepareRegister = pointy match {
case ConstantPointy(addr, _, _, _, _) => case ConstantPointy(addr, _, _, _, _, _) =>
List( List(
AssemblyLine.implied(CLC), AssemblyLine.implied(CLC),
AssemblyLine.immediate(ADC, addr.hiByte), AssemblyLine.immediate(ADC, addr.hiByte),
@ -295,7 +296,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
wrapWordIndexingStorage(prepareWordIndexing(ctx, p, indexExpr)) wrapWordIndexingStorage(prepareWordIndexing(ctx, p, indexExpr))
case (p: ConstantPointy, Some(v), 2, _) => case (p: ConstantPointy, Some(v), 2, _) =>
val w = env.get[VariableType]("word") 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, _) => case (p: ConstantPointy, Some(v), 1, _) =>
storeToArrayAtUnknownIndex(v, p.value) storeToArrayAtUnknownIndex(v, p.value)
//TODO: should there be a type check or a zeropage check? //TODO: should there be a type check or a zeropage check?
@ -614,7 +615,7 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
None, None,
if (constantIndex.isProvablyZero) a.size else None, if (constantIndex.isProvablyZero) a.size else None,
env.get[VariableType]("word"), env.get[VariableType]("word"),
a.elementType), v) ++ loadFromReg() a.elementType, NoAlignment), v) ++ loadFromReg()
case (a: VariablePointy, _, 2, _) => case (a: VariablePointy, _, 2, _) =>
prepareWordIndexing(ctx, a, indexExpr) ++ loadFromReg() prepareWordIndexing(ctx, a, indexExpr) ++ loadFromReg()
case (p:VariablePointy, None, 0 | 1, _) => case (p:VariablePointy, None, 0 | 1, _) =>

View File

@ -7,6 +7,7 @@ import millfork.env._
import millfork.node.{ZRegister, _} import millfork.node.{ZRegister, _}
import millfork.assembly.z80.ZOpcode._ import millfork.assembly.z80.ZOpcode._
import millfork.error.ConsoleLogger import millfork.error.ConsoleLogger
import millfork.output.{NoAlignment, WithinPageAlignment}
/** /**
* @author Karol Stasiak * @author Karol Stasiak
@ -940,13 +941,21 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
val pointy = env.getPointy(i.name) val pointy = env.getPointy(i.name)
AbstractExpressionCompiler.checkIndexType(ctx, pointy, i.index) AbstractExpressionCompiler.checkIndexType(ctx, pointy, i.index)
pointy match { pointy match {
case ConstantPointy(baseAddr, _, _, _, _) => case ConstantPointy(baseAddr, _, size, _, _, alignment) =>
env.evalVariableAndConstantSubParts(i.index) match { env.evalVariableAndConstantSubParts(i.index) match {
case (None, offset) => List(ZLine.ldImm16(ZRegister.HL, (baseAddr + offset).quickSimplify)) case (None, offset) => List(ZLine.ldImm16(ZRegister.HL, (baseAddr + offset).quickSimplify))
case (Some(index), offset) => case (Some(index), offset) =>
List(ZLine.ldImm16(ZRegister.BC, (baseAddr + offset).quickSimplify)) ++ val constantPart = (baseAddr + offset).quickSimplify
stashBCIfChanged(ctx, compileToHL(ctx, index)) ++ if (getExpressionType(ctx, i.index).size == 1 && size.exists(_ < 256) && alignment == WithinPageAlignment) {
List(ZLine.registers(ADD_16, ZRegister.HL, ZRegister.BC)) 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, _, _) => case VariablePointy(varAddr, _, _) =>
env.eval(i.index) match { env.eval(i.index) match {

View File

@ -294,13 +294,13 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
InitializedMemoryVariable InitializedMemoryVariable
UninitializedMemoryVariable UninitializedMemoryVariable
getArrayOrPointer(name) match { getArrayOrPointer(name) match {
case th@InitializedArray(_, _, cs, _, i, e, _) => ConstantPointy(th.toAddress, Some(name), Some(cs.length), 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) 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) 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 => case ConstantThing(_, value, typ) if typ.size <= 2 && typ.isPointy =>
val b = get[VariableType]("byte") val b = get[VariableType]("byte")
val w = get[VariableType]("word") 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=> case th:VariableInMemory if th.typ.isPointy=>
val b = get[VariableType]("byte") val b = get[VariableType]("byte")
val w = get[VariableType]("word") 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") log.error(s"$name is not a valid pointer or array")
val b = get[VariableType]("byte") val b = get[VariableType]("byte")
val w = get[VariableType]("word") 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 = { private def defaultArrayAlignment(options: CompilationOptions, size: Long): MemoryAlignment = {
if (options.platform.cpuFamily == CpuFamily.M6502 && if (options.flag(CompilationFlag.OptimizeForSpeed) && size <= 256 && size != 0) WithinPageAlignment
options.flag(CompilationFlag.OptimizeForSpeed) &&
size <= 256) WithinPageAlignment
else NoAlignment else NoAlignment
} }

View File

@ -1,5 +1,7 @@
package millfork.env package millfork.env
import millfork.output.MemoryAlignment
trait Pointy { trait Pointy {
def name: Option[String] def name: Option[String]
def indexType: VariableType def indexType: VariableType
@ -10,4 +12,4 @@ case class VariablePointy(addr: Constant, indexType: VariableType, elementType:
override def name: Option[String] = None 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