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:
parent
8b09941cef
commit
019547aae8
@ -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, _) =>
|
||||||
|
@ -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 {
|
||||||
|
14
src/main/scala/millfork/env/Environment.scala
vendored
14
src/main/scala/millfork/env/Environment.scala
vendored
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
src/main/scala/millfork/env/Pointy.scala
vendored
4
src/main/scala/millfork/env/Pointy.scala
vendored
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user