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

Zeropage variable optimizations

This commit is contained in:
Karol Stasiak 2018-01-29 11:55:15 +01:00
parent 50d4823e0a
commit 17920cee26
2 changed files with 43 additions and 69 deletions

View File

@ -184,6 +184,7 @@ object AddrMode extends Enumeration {
case IndexedX | AbsoluteIndexedX => "(" + argument + ", X)" case IndexedX | AbsoluteIndexedX => "(" + argument + ", X)"
case IndexedY => "(" + argument + "), Y" case IndexedY => "(" + argument + "), Y"
case Indirect | ZeroPageIndirect => "(" + argument + ")" case Indirect | ZeroPageIndirect => "(" + argument + ")"
case ZeroPage => argument // + "\t;zp"
case _ => argument; case _ => argument;
} }
} }

View File

@ -282,21 +282,15 @@ object MfCompiler {
case 0 => ??? case 0 => ???
case 1 => case 1 =>
v match { v match {
case mv: VariableInMemory => AssemblyLine.absolute(store, mv) :: Nil case mv: VariableInMemory => AssemblyLine.variable(ctx, store, mv)
case sv@StackVariable(_, _, offset) => AssemblyLine.implied(transferToA) :: AssemblyLine.implied(TSX) :: AssemblyLine.absoluteX(STA, offset + ctx.extraStackOffset) :: Nil case sv@StackVariable(_, _, offset) => AssemblyLine.implied(transferToA) :: AssemblyLine.implied(TSX) :: AssemblyLine.absoluteX(STA, offset + ctx.extraStackOffset) :: Nil
} }
case s if s > 1 => case s if s > 1 =>
v match { v match {
case mv: VariableInMemory => case mv: VariableInMemory =>
if (mv.zeropage) { AssemblyLine.variable(ctx, store, mv) ++
AssemblyLine.zeropage(store, mv) :: List(AssemblyLine.immediate(LDA, 0)) ++
AssemblyLine.immediate(LDA, 0) :: List.tabulate(s - 1)(i => AssemblyLine.variable(ctx, STA, mv, i + 1)).flatten
List.tabulate(s - 1)(i => AssemblyLine.zeropage(STA, mv.toAddress + (i + 1)))
} else {
AssemblyLine.absolute(store, mv) ::
AssemblyLine.immediate(LDA, 0) ::
List.tabulate(s - 1)(i => AssemblyLine.absolute(STA, mv.toAddress + (i + 1)))
}
case sv@StackVariable(_, _, offset) => case sv@StackVariable(_, _, offset) =>
AssemblyLine.implied(transferToA) :: AssemblyLine.implied(transferToA) ::
AssemblyLine.implied(TSX) :: AssemblyLine.implied(TSX) ::
@ -465,15 +459,14 @@ object MfCompiler {
env.get[TypedThing](name) match { env.get[TypedThing](name) match {
case source: VariableInMemory => case source: VariableInMemory =>
target match { target match {
case RegisterVariable(Register.A, _) => List(AssemblyLine.absolute(LDA, source)) case RegisterVariable(Register.A, _) => AssemblyLine.variable(ctx, LDA, source)
case RegisterVariable(Register.X, _) => List(AssemblyLine.absolute(LDX, source)) case RegisterVariable(Register.X, _) => AssemblyLine.variable(ctx, LDX, source)
case RegisterVariable(Register.Y, _) => List(AssemblyLine.absolute(LDY, source)) case RegisterVariable(Register.Y, _) => AssemblyLine.variable(ctx, LDY, source)
case RegisterVariable(Register.AX, _) => case RegisterVariable(Register.AX, _) =>
exprType.size match { exprType.size match {
case 1 => if (exprType.isSigned) { case 1 => if (exprType.isSigned) {
val label = nextLabel("sx") val label = nextLabel("sx")
List( AssemblyLine.variable(ctx, LDA, source) ++ List(
AssemblyLine.absolute(LDA, source),
AssemblyLine.implied(PHA), AssemblyLine.implied(PHA),
AssemblyLine.immediate(ORA, 0x7F), AssemblyLine.immediate(ORA, 0x7F),
AssemblyLine.relative(BMI, label), AssemblyLine.relative(BMI, label),
@ -481,19 +474,15 @@ object MfCompiler {
AssemblyLine.label(label), AssemblyLine.label(label),
AssemblyLine.implied(TAX), AssemblyLine.implied(TAX),
AssemblyLine.implied(PLA)) AssemblyLine.implied(PLA))
} else List( } else AssemblyLine.variable(ctx, LDA, source) :+ AssemblyLine.immediate(LDX, 0)
AssemblyLine.absolute(LDA, source), case 2 =>
AssemblyLine.immediate(LDX, 0)) AssemblyLine.variable(ctx, LDA, source) ++ AssemblyLine.variable(ctx, LDX, source, 1)
case 2 => List(
AssemblyLine.absolute(LDA, source),
AssemblyLine.absolute(LDX, source, 1))
} }
case RegisterVariable(Register.AY, _) => case RegisterVariable(Register.AY, _) =>
exprType.size match { exprType.size match {
case 1 => if (exprType.isSigned) { case 1 => if (exprType.isSigned) {
val label = nextLabel("sx") val label = nextLabel("sx")
List( AssemblyLine.variable(ctx, LDA, source) ++ List(
AssemblyLine.absolute(LDA, source),
AssemblyLine.implied(PHA), AssemblyLine.implied(PHA),
AssemblyLine.immediate(ORA, 0x7F), AssemblyLine.immediate(ORA, 0x7F),
AssemblyLine.relative(BMI, label), AssemblyLine.relative(BMI, label),
@ -502,56 +491,47 @@ object MfCompiler {
AssemblyLine.implied(TAY), AssemblyLine.implied(TAY),
AssemblyLine.implied(PLA)) AssemblyLine.implied(PLA))
} else { } else {
List( AssemblyLine.variable(ctx, LDA, source) :+ AssemblyLine.immediate(LDY, 0)
AssemblyLine.absolute(LDA, source),
AssemblyLine.immediate(LDY, 0))
} }
case 2 => List( case 2 =>
AssemblyLine.absolute(LDA, source), AssemblyLine.variable(ctx, LDA, source) ++ AssemblyLine.variable(ctx, LDY, source, 1)
AssemblyLine.absolute(LDY, source, 1))
} }
case RegisterVariable(Register.XA, _) => case RegisterVariable(Register.XA, _) =>
exprType.size match { exprType.size match {
case 1 => if (exprType.isSigned) { case 1 => if (exprType.isSigned) {
val label = nextLabel("sx") val label = nextLabel("sx")
List( AssemblyLine.variable(ctx, LDX, source) ++ List(
AssemblyLine.absolute(LDX, source),
AssemblyLine.implied(TXA), AssemblyLine.implied(TXA),
AssemblyLine.immediate(ORA, 0x7F), AssemblyLine.immediate(ORA, 0x7F),
AssemblyLine.relative(BMI, label), AssemblyLine.relative(BMI, label),
AssemblyLine.immediate(LDA, 0), AssemblyLine.immediate(LDA, 0),
AssemblyLine.label(label)) AssemblyLine.label(label))
} else List( } else
AssemblyLine.absolute(LDX, source), AssemblyLine.variable(ctx, LDX, source) :+ AssemblyLine.immediate(LDA, 0)
AssemblyLine.immediate(LDA, 0)) case 2 =>
case 2 => List( AssemblyLine.variable(ctx, LDX, source) ++ AssemblyLine.variable(ctx,LDA, source, 1)
AssemblyLine.absolute(LDX, source),
AssemblyLine.absolute(LDA, source, 1))
} }
case RegisterVariable(Register.YA, _) => case RegisterVariable(Register.YA, _) =>
exprType.size match { exprType.size match {
case 1 => if (exprType.isSigned) { case 1 => if (exprType.isSigned) {
val label = nextLabel("sx") val label = nextLabel("sx")
List( AssemblyLine.variable(ctx, LDY, source) ++ List(
AssemblyLine.absolute(LDY, source),
AssemblyLine.implied(TYA), AssemblyLine.implied(TYA),
AssemblyLine.immediate(ORA, 0x7F), AssemblyLine.immediate(ORA, 0x7F),
AssemblyLine.relative(BMI, label), AssemblyLine.relative(BMI, label),
AssemblyLine.immediate(LDA, 0), AssemblyLine.immediate(LDA, 0),
AssemblyLine.label(label)) AssemblyLine.label(label))
} else List( } else
AssemblyLine.absolute(LDY, source), AssemblyLine.variable(ctx, LDY, source) :+ AssemblyLine.immediate(LDA, 0)
AssemblyLine.immediate(LDA, 0)) case 2 =>
case 2 => List( AssemblyLine.variable(ctx, LDY, source) ++ AssemblyLine.variable(ctx, LDA, source, 1)
AssemblyLine.absolute(LDY, source),
AssemblyLine.absolute(LDA, source, 1))
} }
case target: VariableInMemory => case target: VariableInMemory =>
if (exprType.size > target.typ.size) { if (exprType.size > target.typ.size) {
ErrorReporting.error(s"Variable `$target.name` is too small", expr.position) ErrorReporting.error(s"Variable `$target.name` is too small", expr.position)
Nil Nil
} else { } else {
val copy = List.tabulate(exprType.size)(i => List(AssemblyLine.absolute(LDA, source, i), AssemblyLine.absolute(STA, target, i))) val copy = List.tabulate(exprType.size)(i => AssemblyLine.variable(ctx, LDA, source, i) ++ AssemblyLine.variable(ctx, STA, target, i))
val extend = if (exprType.size == target.typ.size) Nil else if (exprType.isSigned) { val extend = if (exprType.size == target.typ.size) Nil else if (exprType.isSigned) {
val label = nextLabel("sx") val label = nextLabel("sx")
List( List(
@ -559,10 +539,10 @@ object MfCompiler {
AssemblyLine.relative(BMI, label), AssemblyLine.relative(BMI, label),
AssemblyLine.immediate(LDA, 0), AssemblyLine.immediate(LDA, 0),
AssemblyLine.label(label)) ++ AssemblyLine.label(label)) ++
List.tabulate(target.typ.size - exprType.size)(i => AssemblyLine.absolute(STA, target, i + exprType.size)) List.tabulate(target.typ.size - exprType.size)(i => AssemblyLine.variable(ctx, STA, target, i + exprType.size)).flatten
} else { } else {
AssemblyLine.immediate(LDA, 0) :: AssemblyLine.immediate(LDA, 0) ::
List.tabulate(target.typ.size - exprType.size)(i => AssemblyLine.absolute(STA, target, i + exprType.size)) List.tabulate(target.typ.size - exprType.size)(i => AssemblyLine.variable(ctx, STA, target, i + exprType.size)).flatten
} }
copy.flatten ++ extend copy.flatten ++ extend
} }
@ -571,7 +551,7 @@ object MfCompiler {
ErrorReporting.error(s"Variable `$target.name` is too small", expr.position) ErrorReporting.error(s"Variable `$target.name` is too small", expr.position)
Nil Nil
} else { } else {
val copy = List.tabulate(exprType.size)(i => List(AssemblyLine.absolute(LDA, source, i), AssemblyLine.absoluteX(STA, target.baseOffset + ctx.extraStackOffset + i))) val copy = List.tabulate(exprType.size)(i => AssemblyLine.variable(ctx, LDA, source, i) :+ AssemblyLine.absoluteX(STA, target.baseOffset + ctx.extraStackOffset + i))
val extend = if (exprType.size == target.typ.size) Nil else if (exprType.isSigned) { val extend = if (exprType.size == target.typ.size) Nil else if (exprType.isSigned) {
val label = nextLabel("sx") val label = nextLabel("sx")
List( List(
@ -657,7 +637,7 @@ object MfCompiler {
ErrorReporting.error(s"Variable `$target.name` is too small", expr.position) ErrorReporting.error(s"Variable `$target.name` is too small", expr.position)
Nil Nil
} else { } else {
val copy = List.tabulate(exprType.size)(i => List(AssemblyLine.absoluteX(LDA, offset + ctx.extraStackOffset + i), AssemblyLine.absolute(STA, target, i))) val copy = List.tabulate(exprType.size)(i => AssemblyLine.absoluteX(LDA, offset + ctx.extraStackOffset + i) :: AssemblyLine.variable(ctx, STA, target, i))
val extend = if (exprType.size == target.typ.size) Nil else if (exprType.isSigned) { val extend = if (exprType.size == target.typ.size) Nil else if (exprType.isSigned) {
val label = nextLabel("sx") val label = nextLabel("sx")
List( List(
@ -665,10 +645,10 @@ object MfCompiler {
AssemblyLine.relative(BMI, label), AssemblyLine.relative(BMI, label),
AssemblyLine.immediate(LDA, 0), AssemblyLine.immediate(LDA, 0),
AssemblyLine.label(label)) ++ AssemblyLine.label(label)) ++
List.tabulate(target.typ.size - exprType.size)(i => AssemblyLine.absolute(STA, target, i + exprType.size)) List.tabulate(target.typ.size - exprType.size)(i => AssemblyLine.variable(ctx, STA, target, i + exprType.size)).flatten
} else { } else {
AssemblyLine.immediate(LDA, 0) :: AssemblyLine.immediate(LDA, 0) ::
List.tabulate(target.typ.size - exprType.size)(i => AssemblyLine.absolute(STA, target, i + exprType.size)) List.tabulate(target.typ.size - exprType.size)(i => AssemblyLine.variable(ctx, STA, target, i + exprType.size)).flatten
} }
AssemblyLine.implied(TSX) :: (copy.flatten ++ extend) AssemblyLine.implied(TSX) :: (copy.flatten ++ extend)
} }
@ -1249,21 +1229,18 @@ object MfCompiler {
case (t, v: VariableInMemory) => t.size match { case (t, v: VariableInMemory) => t.size match {
case 1 => v.typ.size match { case 1 => v.typ.size match {
case 1 => case 1 =>
List(AssemblyLine.absolute(STA, v)) AssemblyLine.variable(ctx, STA, v)
case s if s > 1 => case s if s > 1 =>
if (t.isSigned) { if (t.isSigned) {
val label = nextLabel("sx") val label = nextLabel("sx")
List( AssemblyLine.variable(ctx, STA, v)++List(
AssemblyLine.absolute(STA, v),
AssemblyLine.immediate(ORA, 0x7f), AssemblyLine.immediate(ORA, 0x7f),
AssemblyLine.relative(BMI, label), AssemblyLine.relative(BMI, label),
AssemblyLine.immediate(LDA, 0), AssemblyLine.immediate(LDA, 0),
AssemblyLine.label(label)) ++ List.tabulate(s - 1)(i => AssemblyLine.absolute(STA, v, i + 1)) AssemblyLine.label(label)) ++ List.tabulate(s - 1)(i => AssemblyLine.variable(ctx, STA, v, i + 1)).flatten
} else { } else {
List( AssemblyLine.variable(ctx, STA, v) ++ List(AssemblyLine.immediate(LDA, 0)) ++
AssemblyLine.absolute(STA, v), List.tabulate(s - 1)(i => AssemblyLine.variable(ctx, STA, v, i + 1)).flatten
AssemblyLine.immediate(LDA, 0)) ++
List.tabulate(s - 1)(i => AssemblyLine.absolute(STA, v, i + 1))
} }
} }
case 2 => v.typ.size match { case 2 => v.typ.size match {
@ -1271,24 +1248,20 @@ object MfCompiler {
ErrorReporting.error(s"Variable `${v.name}` cannot hold a word", position) ErrorReporting.error(s"Variable `${v.name}` cannot hold a word", position)
Nil Nil
case 2 => case 2 =>
List(AssemblyLine.absolute(STA, v), AssemblyLine.absolute(STX, v, 1)) AssemblyLine.variable(ctx, STA, v) ++ AssemblyLine.variable(ctx, STX, v, 1)
case s if s > 2 => case s if s > 2 =>
if (t.isSigned) { if (t.isSigned) {
val label = nextLabel("sx") val label = nextLabel("sx")
List( AssemblyLine.variable(ctx, STA, v) ++ AssemblyLine.variable(ctx, STX, v, 1) ++ List(
AssemblyLine.absolute(STA, v),
AssemblyLine.absolute(STX, v, 1),
AssemblyLine.implied(TXA), AssemblyLine.implied(TXA),
AssemblyLine.immediate(ORA, 0x7f), AssemblyLine.immediate(ORA, 0x7f),
AssemblyLine.relative(BMI, label), AssemblyLine.relative(BMI, label),
AssemblyLine.immediate(LDA, 0), AssemblyLine.immediate(LDA, 0),
AssemblyLine.label(label)) ++ List.tabulate(s - 2)(i => AssemblyLine.absolute(STA, v, i + 2)) AssemblyLine.label(label)) ++ List.tabulate(s - 2)(i => AssemblyLine.variable(ctx, STA, v, i + 2)).flatten
} else { } else {
List( AssemblyLine.variable(ctx, STA, v) ++ AssemblyLine.variable(ctx, STX, v, 1) ++ List(
AssemblyLine.absolute(STA, v),
AssemblyLine.absolute(STX, v, 1),
AssemblyLine.immediate(LDA, 0)) ++ AssemblyLine.immediate(LDA, 0)) ++
List.tabulate(s - 2)(i => AssemblyLine.absolute(STA, v, i + 2)) List.tabulate(s - 2)(i => AssemblyLine.variable(ctx, STA, v, i + 2)).flatten
} }
} }
} }