mirror of
https://github.com/KarolS/millfork.git
synced 2025-01-03 19:31:02 +00:00
6809: tons of improvements:
* stack variables * large comparisons * pointer optimizations * fixed constant evaluation
This commit is contained in:
parent
b9bf433308
commit
a22571f60b
@ -187,6 +187,14 @@ Allow using the IY register for other purposes.
|
|||||||
Compiling to 8086 is based on translating from a mix of 8085 and Z80 instructions to 8086.
|
Compiling to 8086 is based on translating from a mix of 8085 and Z80 instructions to 8086.
|
||||||
See [the 8086 support disclaimer](./../lang/x86disclaimer.md).
|
See [the 8086 support disclaimer](./../lang/x86disclaimer.md).
|
||||||
|
|
||||||
|
#### 6809-related
|
||||||
|
|
||||||
|
* `-fuse-u-for-stack`, `-fuse-y-for-stack`
|
||||||
|
Which of Z80 index registers should be used as the base pointer for accessing stack variables, if any.
|
||||||
|
`.ini` equivalent: `u_stack` and `y_stack`. Default: none.
|
||||||
|
**Warning: Currently, picking one of those two options is required!**
|
||||||
|
The compiler doesn't support accessing the stack variables via the S stack pointer register yet.
|
||||||
|
|
||||||
## Optimization options
|
## Optimization options
|
||||||
|
|
||||||
* `-O0` – Disable all optimizations except unused global symbol removal.
|
* `-O0` – Disable all optimizations except unused global symbol removal.
|
||||||
|
@ -114,6 +114,13 @@ This list cannot contain module template instantiations.
|
|||||||
|
|
||||||
* `iy_scratch` – allow using the IY register for other purposes, default is `false`
|
* `iy_scratch` – allow using the IY register for other purposes, default is `false`
|
||||||
|
|
||||||
|
* `u_stack` – use the U register to access stack variables, default is `false`. Applicable only to 6809-based targets.
|
||||||
|
|
||||||
|
* `y_stack` – use the Y register to access stack variables, default is `false`. Applicable only to 6809-based targets.
|
||||||
|
**Warning: Currently, picking either `u_stack` or `y_stack` is required,
|
||||||
|
unless you want to always specify this option in the compiler's command line!**
|
||||||
|
The compiler doesn't support accessing the stack variables via the S stack pointer register yet.
|
||||||
|
|
||||||
* `software_stack` – use software stack for stack variables, default is `false`. Applicable only to 6502-based targets.
|
* `software_stack` – use software stack for stack variables, default is `false`. Applicable only to 6502-based targets.
|
||||||
|
|
||||||
* `output_intel_syntax` – use Intel syntax instead of Zilog syntax, default is `true` for Intel 8080/8085 and `false` otherwise
|
* `output_intel_syntax` – use Intel syntax instead of Zilog syntax, default is `true` for Intel 8080/8085 and `false` otherwise
|
||||||
|
@ -190,6 +190,9 @@ case class CompilationOptions(platform: Platform,
|
|||||||
if (flags(UseUForStack) && flags(UseYForStack)) {
|
if (flags(UseUForStack) && flags(UseYForStack)) {
|
||||||
log.error("Cannot use both U and Y registers for stack variables simultaneously")
|
log.error("Cannot use both U and Y registers for stack variables simultaneously")
|
||||||
}
|
}
|
||||||
|
if (!flags(UseUForStack) && !flags(UseYForStack)) {
|
||||||
|
log.error("You need to use either the U register or the Y register as the base pointer. This might be relaxed in the future.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -651,10 +651,10 @@ object Main {
|
|||||||
c.changeFlag(CompilationFlag.UseIyForStack, true).changeFlag(CompilationFlag.UseIxForStack, false)
|
c.changeFlag(CompilationFlag.UseIyForStack, true).changeFlag(CompilationFlag.UseIxForStack, false)
|
||||||
}.description("Use IY as base pointer for stack variables (Z80 only)")
|
}.description("Use IY as base pointer for stack variables (Z80 only)")
|
||||||
flag("-fuse-u-for-stack").action { c =>
|
flag("-fuse-u-for-stack").action { c =>
|
||||||
c.changeFlag(CompilationFlag.UseIxForStack, true).changeFlag(CompilationFlag.UseUForStack, false)
|
c.changeFlag(CompilationFlag.UseUForStack, true).changeFlag(CompilationFlag.UseYForStack, false)
|
||||||
}.description("Use U as base pointer for stack variables (6809 only)").hidden()
|
}.description("Use U as base pointer for stack variables (6809 only)").hidden()
|
||||||
flag("-fuse-y-for-stack").action { c =>
|
flag("-fuse-y-for-stack").action { c =>
|
||||||
c.changeFlag(CompilationFlag.UseIyForStack, true).changeFlag(CompilationFlag.UseYForStack, false)
|
c.changeFlag(CompilationFlag.UseYForStack, true).changeFlag(CompilationFlag.UseUForStack, false)
|
||||||
}.description("Use Y as base pointer for stack variables (6809 only)").hidden()
|
}.description("Use Y as base pointer for stack variables (6809 only)").hidden()
|
||||||
boolean("-fuse-ix-for-scratch", "-fno-use-ix-for-scratch").action { (c, v) =>
|
boolean("-fuse-ix-for-scratch", "-fno-use-ix-for-scratch").action { (c, v) =>
|
||||||
if (v) {
|
if (v) {
|
||||||
|
@ -9,26 +9,41 @@ sealed trait MAddrMode {
|
|||||||
def changesRegister(reg: M6809Register.Value): Boolean = false
|
def changesRegister(reg: M6809Register.Value): Boolean = false
|
||||||
|
|
||||||
def makeIndirect(position: Position): MAddrMode
|
def makeIndirect(position: Position): MAddrMode
|
||||||
|
|
||||||
|
def isDeferenceable: Boolean
|
||||||
|
def dereference(): MAddrMode
|
||||||
}
|
}
|
||||||
|
|
||||||
case object Inherent extends MAddrMode {
|
case object Inherent extends MAddrMode {
|
||||||
def makeIndirect(position: Position): MAddrMode = ???
|
def makeIndirect(position: Position): MAddrMode = ???
|
||||||
|
|
||||||
|
def isDeferenceable: Boolean = false
|
||||||
|
def dereference(): MAddrMode = ???
|
||||||
}
|
}
|
||||||
|
|
||||||
case object InherentA extends MAddrMode {
|
case object InherentA extends MAddrMode {
|
||||||
override def changesRegister(reg: M6809Register.Value): Boolean = reg == M6809Register.A || reg == M6809Register.D
|
override def changesRegister(reg: M6809Register.Value): Boolean = reg == M6809Register.A || reg == M6809Register.D
|
||||||
|
|
||||||
def makeIndirect(position: Position): MAddrMode = ???
|
def makeIndirect(position: Position): MAddrMode = ???
|
||||||
|
|
||||||
|
def isDeferenceable: Boolean = false
|
||||||
|
def dereference(): MAddrMode = ???
|
||||||
}
|
}
|
||||||
|
|
||||||
case object InherentB extends MAddrMode {
|
case object InherentB extends MAddrMode {
|
||||||
override def changesRegister(reg: M6809Register.Value): Boolean = reg == M6809Register.B || reg == M6809Register.D
|
override def changesRegister(reg: M6809Register.Value): Boolean = reg == M6809Register.B || reg == M6809Register.D
|
||||||
|
|
||||||
def makeIndirect(position: Position): MAddrMode = ???
|
def makeIndirect(position: Position): MAddrMode = ???
|
||||||
|
|
||||||
|
def isDeferenceable: Boolean = false
|
||||||
|
def dereference(): MAddrMode = ???
|
||||||
}
|
}
|
||||||
|
|
||||||
case class TwoRegisters(source: M6809Register.Value, target: M6809Register.Value) extends MAddrMode {
|
case class TwoRegisters(source: M6809Register.Value, target: M6809Register.Value) extends MAddrMode {
|
||||||
def makeIndirect(position: Position): MAddrMode = ???
|
def makeIndirect(position: Position): MAddrMode = ???
|
||||||
|
|
||||||
|
def isDeferenceable: Boolean = false
|
||||||
|
def dereference(): MAddrMode = ???
|
||||||
}
|
}
|
||||||
|
|
||||||
case class RegisterSet(registers: Set[M6809Register.Value]) extends MAddrMode {
|
case class RegisterSet(registers: Set[M6809Register.Value]) extends MAddrMode {
|
||||||
@ -42,6 +57,9 @@ case class RegisterSet(registers: Set[M6809Register.Value]) extends MAddrMode {
|
|||||||
case _ => registers(register)
|
case _ => registers(register)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def isDeferenceable: Boolean = false
|
||||||
|
def dereference(): MAddrMode = ???
|
||||||
}
|
}
|
||||||
|
|
||||||
object RegisterSet {
|
object RegisterSet {
|
||||||
@ -57,56 +75,88 @@ object RegisterSet {
|
|||||||
|
|
||||||
case class Absolute(indirect: Boolean) extends MAddrMode {
|
case class Absolute(indirect: Boolean) extends MAddrMode {
|
||||||
def makeIndirect(position: Position): MAddrMode = copy(indirect = true)
|
def makeIndirect(position: Position): MAddrMode = copy(indirect = true)
|
||||||
|
|
||||||
|
def isDeferenceable: Boolean = !indirect
|
||||||
|
def dereference(): MAddrMode = copy(indirect = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
case class Indexed(base: M6809Register.Value, indirect: Boolean) extends MAddrMode {
|
case class Indexed(base: M6809Register.Value, indirect: Boolean) extends MAddrMode {
|
||||||
def makeIndirect(position: Position): MAddrMode = copy(indirect = true)
|
def makeIndirect(position: Position): MAddrMode = copy(indirect = true)
|
||||||
|
|
||||||
|
def isDeferenceable: Boolean = !indirect
|
||||||
|
def dereference(): MAddrMode = copy(indirect = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
case class AAccumulatorIndexed(base: M6809Register.Value, indirect: Boolean) extends MAddrMode {
|
case class AAccumulatorIndexed(base: M6809Register.Value, indirect: Boolean) extends MAddrMode {
|
||||||
def makeIndirect(position: Position): MAddrMode = copy(indirect = true)
|
def makeIndirect(position: Position): MAddrMode = copy(indirect = true)
|
||||||
|
|
||||||
|
def isDeferenceable: Boolean = !indirect
|
||||||
|
def dereference(): MAddrMode = copy(indirect = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
case class BAccumulatorIndexed(base: M6809Register.Value, indirect: Boolean) extends MAddrMode {
|
case class BAccumulatorIndexed(base: M6809Register.Value, indirect: Boolean) extends MAddrMode {
|
||||||
def makeIndirect(position: Position): MAddrMode = copy(indirect = true)
|
def makeIndirect(position: Position): MAddrMode = copy(indirect = true)
|
||||||
|
|
||||||
|
def isDeferenceable: Boolean = !indirect
|
||||||
|
def dereference(): MAddrMode = copy(indirect = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
case class DAccumulatorIndexed(base: M6809Register.Value, indirect: Boolean) extends MAddrMode {
|
case class DAccumulatorIndexed(base: M6809Register.Value, indirect: Boolean) extends MAddrMode {
|
||||||
def makeIndirect(position: Position): MAddrMode = copy(indirect = true)
|
def makeIndirect(position: Position): MAddrMode = copy(indirect = true)
|
||||||
|
|
||||||
|
def isDeferenceable: Boolean = !indirect
|
||||||
|
def dereference(): MAddrMode = copy(indirect = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
case class PostIncremented(base: M6809Register.Value, amount: Int, indirect: Boolean) extends MAddrMode {
|
case class PostIncremented(base: M6809Register.Value, amount: Int, indirect: Boolean) extends MAddrMode {
|
||||||
override def changesRegister(reg: M6809Register.Value): Boolean = reg == base
|
override def changesRegister(reg: M6809Register.Value): Boolean = reg == base
|
||||||
|
|
||||||
def makeIndirect(position: Position): MAddrMode = copy(indirect = true)
|
def makeIndirect(position: Position): MAddrMode = copy(indirect = true)
|
||||||
|
def isDeferenceable: Boolean = false
|
||||||
|
def dereference(): MAddrMode = ???
|
||||||
}
|
}
|
||||||
|
|
||||||
case class PreDecremented(base: M6809Register.Value, amount: Int, indirect: Boolean) extends MAddrMode {
|
case class PreDecremented(base: M6809Register.Value, amount: Int, indirect: Boolean) extends MAddrMode {
|
||||||
override def changesRegister(reg: M6809Register.Value): Boolean = reg == base
|
override def changesRegister(reg: M6809Register.Value): Boolean = reg == base
|
||||||
|
|
||||||
def makeIndirect(position: Position): MAddrMode = copy(indirect = true)
|
def makeIndirect(position: Position): MAddrMode = copy(indirect = true)
|
||||||
|
def isDeferenceable: Boolean = false
|
||||||
|
def dereference(): MAddrMode = ???
|
||||||
}
|
}
|
||||||
|
|
||||||
case object Relative extends MAddrMode {
|
case object Relative extends MAddrMode {
|
||||||
def makeIndirect(position: Position): MAddrMode = ???
|
def makeIndirect(position: Position): MAddrMode = ???
|
||||||
|
def isDeferenceable: Boolean = false
|
||||||
|
def dereference(): MAddrMode = ???
|
||||||
}
|
}
|
||||||
|
|
||||||
case object LongRelative extends MAddrMode {
|
case object LongRelative extends MAddrMode {
|
||||||
def makeIndirect(position: Position): MAddrMode = ???
|
def makeIndirect(position: Position): MAddrMode = ???
|
||||||
|
def isDeferenceable: Boolean = false
|
||||||
|
def dereference(): MAddrMode = ???
|
||||||
}
|
}
|
||||||
|
|
||||||
case object Immediate extends MAddrMode {
|
case object Immediate extends MAddrMode {
|
||||||
def makeIndirect(position: Position): MAddrMode = ???
|
def makeIndirect(position: Position): MAddrMode = ???
|
||||||
|
|
||||||
|
def isDeferenceable: Boolean = true
|
||||||
|
def dereference(): MAddrMode = Absolute(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
case object DirectPage extends MAddrMode {
|
case object DirectPage extends MAddrMode {
|
||||||
def makeIndirect(position: Position): MAddrMode = ???
|
def makeIndirect(position: Position): MAddrMode = ???
|
||||||
|
def isDeferenceable: Boolean = false
|
||||||
|
def dereference(): MAddrMode = ???
|
||||||
}
|
}
|
||||||
|
|
||||||
case object NonExistent extends MAddrMode {
|
case object NonExistent extends MAddrMode {
|
||||||
def makeIndirect(position: Position): MAddrMode = ???
|
def makeIndirect(position: Position): MAddrMode = ???
|
||||||
|
def isDeferenceable: Boolean = false
|
||||||
|
def dereference(): MAddrMode = ???
|
||||||
}
|
}
|
||||||
|
|
||||||
case object RawByte extends MAddrMode {
|
case object RawByte extends MAddrMode {
|
||||||
def makeIndirect(position: Position): MAddrMode = ???
|
def makeIndirect(position: Position): MAddrMode = ???
|
||||||
|
def isDeferenceable: Boolean = false
|
||||||
|
def dereference(): MAddrMode = ???
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,12 @@ object MLine {
|
|||||||
def indexedX(opcode: MOpcode.Value, offset: Int): MLine =
|
def indexedX(opcode: MOpcode.Value, offset: Int): MLine =
|
||||||
MLine(opcode, Indexed(M6809Register.X, indirect = false), Constant(offset))
|
MLine(opcode, Indexed(M6809Register.X, indirect = false), Constant(offset))
|
||||||
|
|
||||||
|
def indexedU(opcode: MOpcode.Value, offset: Int): MLine =
|
||||||
|
MLine(opcode, Indexed(M6809Register.U, indirect = false), Constant(offset))
|
||||||
|
|
||||||
|
def indexedY(opcode: MOpcode.Value, offset: Int): MLine =
|
||||||
|
MLine(opcode, Indexed(M6809Register.Y, indirect = false), Constant(offset))
|
||||||
|
|
||||||
def accessAndPullS(opcode: MOpcode.Value): MLine =
|
def accessAndPullS(opcode: MOpcode.Value): MLine =
|
||||||
MLine(opcode, PostIncremented(M6809Register.S, 1, indirect = false), Constant.Zero)
|
MLine(opcode, PostIncremented(M6809Register.S, 1, indirect = false), Constant.Zero)
|
||||||
|
|
||||||
|
@ -49,8 +49,7 @@ object M6809Buitins {
|
|||||||
// TODO: preserve X?
|
// TODO: preserve X?
|
||||||
rc ++ List(MLine.pp(PSHS, M6809Register.D)) ++ lc ++ List(MLine.accessAndPullSTwice(opcode), lc.last.copy(opcode = STD))
|
rc ++ List(MLine.pp(PSHS, M6809Register.D)) ++ lc ++ List(MLine.accessAndPullSTwice(opcode), lc.last.copy(opcode = STD))
|
||||||
case _ =>
|
case _ =>
|
||||||
println(lc)
|
rc ++ List(MLine.pp(PSHS, M6809Register.D)) ++ lc ++ List(MLine.accessAndPullSTwice(opcode)) ++ M6809ExpressionCompiler.storeD(ctx, l)
|
||||||
???
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package millfork.compiler.m6809
|
package millfork.compiler.m6809
|
||||||
|
|
||||||
|
import millfork.CompilationFlag
|
||||||
import millfork.assembly.Elidability
|
import millfork.assembly.Elidability
|
||||||
import millfork.assembly.m6809.{Inherent, MLine, MOpcode, NonExistent}
|
import millfork.assembly.m6809.{Inherent, MLine, MOpcode, NonExistent}
|
||||||
import millfork.compiler.{AbstractCompiler, CompilationContext}
|
import millfork.compiler.{AbstractCompiler, CompilationContext}
|
||||||
@ -10,8 +11,26 @@ import millfork.env.{Constant, Label, MemoryAddressConstant, NormalParamSignatur
|
|||||||
*/
|
*/
|
||||||
object M6809Compiler extends AbstractCompiler[MLine] {
|
object M6809Compiler extends AbstractCompiler[MLine] {
|
||||||
override def compile(ctx: CompilationContext): List[MLine] = {
|
override def compile(ctx: CompilationContext): List[MLine] = {
|
||||||
ctx.env.nameCheck(ctx.function.code)
|
|
||||||
import MOpcode._
|
import MOpcode._
|
||||||
|
|
||||||
|
val prologue = if (ctx.function.stackVariablesSize == 0) Nil else {
|
||||||
|
import millfork.node.M6809Register.{U, S, Y}
|
||||||
|
if (ctx.options.flag(CompilationFlag.UseUForStack)) {
|
||||||
|
List(
|
||||||
|
MLine.pp(PSHS, U),
|
||||||
|
MLine.indexedS(LEAS, -ctx.function.stackVariablesSize),
|
||||||
|
MLine.tfr(S, U))
|
||||||
|
} else if (ctx.options.flag(CompilationFlag.UseYForStack)) {
|
||||||
|
List(
|
||||||
|
MLine.pp(PSHS, Y),
|
||||||
|
MLine.indexedS(LEAS, -ctx.function.stackVariablesSize),
|
||||||
|
MLine.tfr(S, Y))
|
||||||
|
} else {
|
||||||
|
List(MLine.indexedS(LEAS, -ctx.function.stackVariablesSize))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.env.nameCheck(ctx.function.code)
|
||||||
val storeParamsFromRegisters = ctx.function.params match {
|
val storeParamsFromRegisters = ctx.function.params match {
|
||||||
case NormalParamSignature(List(param)) if param.typ.size == 1 =>
|
case NormalParamSignature(List(param)) if param.typ.size == 1 =>
|
||||||
List(MLine.absolute(STB, param.toAddress))
|
List(MLine.absolute(STB, param.toAddress))
|
||||||
@ -22,6 +41,6 @@ object M6809Compiler extends AbstractCompiler[MLine] {
|
|||||||
val label = MLine.label(Label(ctx.function.name)).copy(elidability = Elidability.Fixed)
|
val label = MLine.label(Label(ctx.function.name)).copy(elidability = Elidability.Fixed)
|
||||||
val chunk = packHalves(M6809StatementCompiler.compile(ctx, new M6809StatementPreprocessor(ctx, ctx.function.code)()))
|
val chunk = packHalves(M6809StatementCompiler.compile(ctx, new M6809StatementPreprocessor(ctx, ctx.function.code)()))
|
||||||
// TODO: stackframe etc.
|
// TODO: stackframe etc.
|
||||||
label :: (storeParamsFromRegisters ++ chunk)
|
label :: (storeParamsFromRegisters ++ prologue ++ chunk)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import millfork.assembly.m6809.{DAccumulatorIndexed, Immediate, Indexed, Inheren
|
|||||||
import millfork.compiler.{AbstractExpressionCompiler, BranchIfFalse, BranchIfTrue, BranchSpec, ComparisonType, CompilationContext, NoBranching}
|
import millfork.compiler.{AbstractExpressionCompiler, BranchIfFalse, BranchIfTrue, BranchSpec, ComparisonType, CompilationContext, NoBranching}
|
||||||
import millfork.node.{DerefExpression, Expression, FunctionCallExpression, GeneratedConstantExpression, IndexedExpression, LhsExpression, LiteralExpression, M6809Register, SeparateBytesExpression, SumExpression, VariableExpression}
|
import millfork.node.{DerefExpression, Expression, FunctionCallExpression, GeneratedConstantExpression, IndexedExpression, LhsExpression, LiteralExpression, M6809Register, SeparateBytesExpression, SumExpression, VariableExpression}
|
||||||
import millfork.assembly.m6809.MOpcode._
|
import millfork.assembly.m6809.MOpcode._
|
||||||
import millfork.env.{AssemblyOrMacroParamSignature, BuiltInBooleanType, Constant, ConstantBooleanType, ConstantPointy, ExternFunction, FatBooleanType, FlagBooleanType, FunctionInMemory, FunctionPointerType, Label, M6809RegisterVariable, MacroFunction, MathOperator, MemoryAddressConstant, MemoryVariable, NonFatalCompilationException, NormalFunction, NormalParamSignature, NumericConstant, StackVariablePointy, StructureConstant, ThingInMemory, Type, Variable, VariableInMemory, VariablePointy}
|
import millfork.env.{AssemblyOrMacroParamSignature, BuiltInBooleanType, Constant, ConstantBooleanType, ConstantPointy, ExternFunction, FatBooleanType, FlagBooleanType, FunctionInMemory, FunctionPointerType, Label, M6809RegisterVariable, MacroFunction, MathOperator, MemoryAddressConstant, MemoryVariable, NonFatalCompilationException, NormalFunction, NormalParamSignature, NumericConstant, StackOffsetThing, StackVariable, StackVariablePointy, StructureConstant, Thing, ThingInMemory, Type, Variable, VariableInMemory, VariableLikeThing, VariablePointy}
|
||||||
|
|
||||||
import scala.collection.GenTraversableOnce
|
import scala.collection.GenTraversableOnce
|
||||||
|
|
||||||
@ -73,18 +73,29 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
|||||||
}
|
}
|
||||||
expr match {
|
expr match {
|
||||||
case VariableExpression(name) =>
|
case VariableExpression(name) =>
|
||||||
val variable = env.get[Variable](name)
|
env.get[VariableLikeThing](name) match {
|
||||||
exprType.size match {
|
case variable: Variable =>
|
||||||
case 1 =>
|
exprType.size match {
|
||||||
targetSize match {
|
case 1 =>
|
||||||
case 0 => Nil
|
targetSize match {
|
||||||
case 1 => List(MLine.variable(ctx, toLd(target), variable))
|
case 0 => Nil
|
||||||
case 2 => List(MLine.variable(ctx, LDB, variable)) ++ zeroextendB(ctx, target, exprType.isSigned)
|
case 1 => List(MLine.variable(ctx, toLd(target), variable))
|
||||||
|
case 2 => List(MLine.variable(ctx, LDB, variable)) ++ zeroextendB(ctx, target, exprType.isSigned)
|
||||||
|
}
|
||||||
|
case 2 =>
|
||||||
|
targetSize match {
|
||||||
|
case 0 => Nil
|
||||||
|
case 2 => List(MLine.variable(ctx, toLd(target), variable))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case 2 =>
|
case sot: StackOffsetThing =>
|
||||||
targetSize match {
|
sot.subbyte match {
|
||||||
case 0 => Nil
|
case None =>
|
||||||
case 2 => List(MLine.variable(ctx, toLd(target), variable))
|
if (target == MExpressionTarget.X) calculateStackAddressToX(ctx, sot.offset)
|
||||||
|
else calculateStackAddressToD(ctx, sot.offset) ++ targetifyD(ctx, target)
|
||||||
|
case Some(0) => calculateStackAddressToD(ctx, sot.offset) ++ targetifyB(ctx, target, isSigned = false)
|
||||||
|
case Some(1) => calculateStackAddressToD(ctx, sot.offset) ++ targetifyA(ctx, target, isSigned = false)
|
||||||
|
case _ => throw new IllegalArgumentException
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case LiteralExpression(c, _) =>
|
case LiteralExpression(c, _) =>
|
||||||
@ -93,7 +104,12 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
|||||||
case _ => List(MLine.immediate(MExpressionTarget.toLd(target), NumericConstant(c, MExpressionTarget.size(target))))
|
case _ => List(MLine.immediate(MExpressionTarget.toLd(target), NumericConstant(c, MExpressionTarget.size(target))))
|
||||||
}
|
}
|
||||||
case DerefExpression(inner, offset, _) =>
|
case DerefExpression(inner, offset, _) =>
|
||||||
compileToX(ctx, inner) :+ MLine(toLd(target), Indexed(M6809Register.X, indirect = false), NumericConstant(offset, 2))
|
compileToX(ctx, inner) match {
|
||||||
|
case List(l@MLine0(LDX, addrMode, _)) if addrMode.isDeferenceable =>
|
||||||
|
List(l.copy(opcode = toLd(target), addrMode = addrMode.dereference()))
|
||||||
|
case _ =>
|
||||||
|
compileToX(ctx, inner) :+ MLine(toLd(target), Indexed(M6809Register.X, indirect = false), NumericConstant(offset, 2))
|
||||||
|
}
|
||||||
case IndexedExpression(name, index) =>
|
case IndexedExpression(name, index) =>
|
||||||
env.getPointy(name) match {
|
env.getPointy(name) match {
|
||||||
case c: ConstantPointy =>
|
case c: ConstantPointy =>
|
||||||
@ -101,12 +117,18 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
|||||||
val constantOffset = (c.value + constIndex).quickSimplify
|
val constantOffset = (c.value + constIndex).quickSimplify
|
||||||
variableIndex match {
|
variableIndex match {
|
||||||
case (Some(ix)) =>
|
case (Some(ix)) =>
|
||||||
compileToX(ctx, ix) ++ (
|
val prepareIndex = compileToX(ctx, ix)
|
||||||
targetSize match {
|
targetSize match {
|
||||||
case 0 => Nil
|
case 0 => prepareIndex
|
||||||
case 1 => List(MLine.indexedX(toLd(target), constantOffset))
|
case 1 =>
|
||||||
case 2 => List(MLine.indexedX(LDB, constantOffset)) ++ zeroextendB(ctx, target, exprType.isSigned)
|
prepareIndex match {
|
||||||
})
|
case List(l@MLine0(LDX, addrMode, _)) if addrMode.isDeferenceable && constantOffset.isProvablyZero =>
|
||||||
|
List(l.copy(opcode = toLd(target), addrMode = addrMode.dereference()))
|
||||||
|
case _ =>
|
||||||
|
prepareIndex ++ List(MLine.indexedX(toLd(target), constantOffset))
|
||||||
|
}
|
||||||
|
case 2 => prepareIndex ++ List(MLine.indexedX(LDB, constantOffset)) ++ zeroextendB(ctx, target, exprType.isSigned)++targetifyD(ctx, target)
|
||||||
|
}
|
||||||
case None =>
|
case None =>
|
||||||
targetSize match {
|
targetSize match {
|
||||||
case 0 => Nil
|
case 0 => Nil
|
||||||
@ -126,11 +148,19 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
|||||||
)) -> Constant.Zero
|
)) -> Constant.Zero
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prepareIndex ++ (targetSize match {
|
targetSize match {
|
||||||
case 0 => Nil
|
case 0 => prepareIndex
|
||||||
case 1 => List(MLine.indexedX(toLd(target), offset))
|
case 1 =>
|
||||||
case 2 => List(MLine.indexedX(LDB, offset)) ++ zeroextendB(ctx, target, exprType.isSigned)
|
prepareIndex match {
|
||||||
})
|
case List(l@MLine0(LDX, addrMode, _)) if addrMode.isDeferenceable && offset.isProvablyZero =>
|
||||||
|
List(l.copy(opcode = toLd(target), addrMode = addrMode.dereference()))
|
||||||
|
case _ =>
|
||||||
|
prepareIndex :+ MLine.indexedX(toLd(target), offset)
|
||||||
|
}
|
||||||
|
case 2 =>
|
||||||
|
val toD = prepareIndex ++ List(MLine.indexedX(LDB, offset)) ++ zeroextendB(ctx, target, exprType.isSigned)
|
||||||
|
toD ++ targetifyD(ctx, target)
|
||||||
|
}
|
||||||
case v:StackVariablePointy =>
|
case v:StackVariablePointy =>
|
||||||
ctx.env.eval(index) match {
|
ctx.env.eval(index) match {
|
||||||
case Some(ix) => List(MLine.variablestack(ctx, LDX, v.offset), MLine.indexedX(LDB, ix * v.elementType.size))
|
case Some(ix) => List(MLine.variablestack(ctx, LDX, v.offset), MLine.indexedX(LDB, ix * v.elementType.size))
|
||||||
@ -280,7 +310,7 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
|||||||
size match {
|
size match {
|
||||||
case 1 => M6809Comparisons.compile8BitComparison(ctx, ComparisonType.Equal, l, r, branches)
|
case 1 => M6809Comparisons.compile8BitComparison(ctx, ComparisonType.Equal, l, r, branches)
|
||||||
case 2 => M6809Comparisons.compile16BitComparison(ctx, ComparisonType.Equal, l, r, branches)
|
case 2 => M6809Comparisons.compile16BitComparison(ctx, ComparisonType.Equal, l, r, branches)
|
||||||
case _ => ???
|
case _ => M6809LargeBuiltins.compileComparison(ctx, ComparisonType.Equal, l, r, branches)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "!=" =>
|
case "!=" =>
|
||||||
@ -289,7 +319,7 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
|||||||
size match {
|
size match {
|
||||||
case 1 => M6809Comparisons.compile8BitComparison(ctx, ComparisonType.NotEqual, l, r, branches)
|
case 1 => M6809Comparisons.compile8BitComparison(ctx, ComparisonType.NotEqual, l, r, branches)
|
||||||
case 2 => M6809Comparisons.compile16BitComparison(ctx, ComparisonType.NotEqual, l, r, branches)
|
case 2 => M6809Comparisons.compile16BitComparison(ctx, ComparisonType.NotEqual, l, r, branches)
|
||||||
case _ => ???
|
case _ => M6809LargeBuiltins.compileComparison(ctx, ComparisonType.NotEqual, l, r, branches)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "<" =>
|
case "<" =>
|
||||||
@ -298,7 +328,7 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
|||||||
size match {
|
size match {
|
||||||
case 1 => M6809Comparisons.compile8BitComparison(ctx, if (signed) ComparisonType.LessSigned else ComparisonType.LessUnsigned, l, r, branches)
|
case 1 => M6809Comparisons.compile8BitComparison(ctx, if (signed) ComparisonType.LessSigned else ComparisonType.LessUnsigned, l, r, branches)
|
||||||
case 2 => M6809Comparisons.compile16BitComparison(ctx, if (signed) ComparisonType.LessSigned else ComparisonType.LessUnsigned, l, r, branches)
|
case 2 => M6809Comparisons.compile16BitComparison(ctx, if (signed) ComparisonType.LessSigned else ComparisonType.LessUnsigned, l, r, branches)
|
||||||
case _ => ???
|
case _ => M6809LargeBuiltins.compileComparison(ctx, if (signed) ComparisonType.LessSigned else ComparisonType.LessUnsigned, l, r, branches)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case ">" =>
|
case ">" =>
|
||||||
@ -307,7 +337,7 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
|||||||
size match {
|
size match {
|
||||||
case 1 => M6809Comparisons.compile8BitComparison(ctx, if (signed) ComparisonType.GreaterSigned else ComparisonType.GreaterUnsigned, l, r, branches)
|
case 1 => M6809Comparisons.compile8BitComparison(ctx, if (signed) ComparisonType.GreaterSigned else ComparisonType.GreaterUnsigned, l, r, branches)
|
||||||
case 2 => M6809Comparisons.compile16BitComparison(ctx, if (signed) ComparisonType.GreaterSigned else ComparisonType.GreaterUnsigned, l, r, branches)
|
case 2 => M6809Comparisons.compile16BitComparison(ctx, if (signed) ComparisonType.GreaterSigned else ComparisonType.GreaterUnsigned, l, r, branches)
|
||||||
case _ => ???
|
case _ => M6809LargeBuiltins.compileComparison(ctx, if (signed) ComparisonType.GreaterSigned else ComparisonType.GreaterUnsigned, l, r, branches)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "<=" =>
|
case "<=" =>
|
||||||
@ -316,7 +346,7 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
|||||||
size match {
|
size match {
|
||||||
case 1 => M6809Comparisons.compile8BitComparison(ctx, if (signed) ComparisonType.LessOrEqualSigned else ComparisonType.LessOrEqualUnsigned, l, r, branches)
|
case 1 => M6809Comparisons.compile8BitComparison(ctx, if (signed) ComparisonType.LessOrEqualSigned else ComparisonType.LessOrEqualUnsigned, l, r, branches)
|
||||||
case 2 => M6809Comparisons.compile16BitComparison(ctx, if (signed) ComparisonType.LessOrEqualSigned else ComparisonType.LessOrEqualUnsigned, l, r, branches)
|
case 2 => M6809Comparisons.compile16BitComparison(ctx, if (signed) ComparisonType.LessOrEqualSigned else ComparisonType.LessOrEqualUnsigned, l, r, branches)
|
||||||
case _ => ???
|
case _ => M6809LargeBuiltins.compileComparison(ctx, if (signed) ComparisonType.LessOrEqualSigned else ComparisonType.LessOrEqualUnsigned, l, r, branches)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case ">=" =>
|
case ">=" =>
|
||||||
@ -325,7 +355,7 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
|||||||
size match {
|
size match {
|
||||||
case 1 => M6809Comparisons.compile8BitComparison(ctx, if (signed) ComparisonType.GreaterOrEqualSigned else ComparisonType.GreaterOrEqualUnsigned, l, r, branches)
|
case 1 => M6809Comparisons.compile8BitComparison(ctx, if (signed) ComparisonType.GreaterOrEqualSigned else ComparisonType.GreaterOrEqualUnsigned, l, r, branches)
|
||||||
case 2 => M6809Comparisons.compile16BitComparison(ctx, if (signed) ComparisonType.GreaterOrEqualSigned else ComparisonType.GreaterOrEqualUnsigned, l, r, branches)
|
case 2 => M6809Comparisons.compile16BitComparison(ctx, if (signed) ComparisonType.GreaterOrEqualSigned else ComparisonType.GreaterOrEqualUnsigned, l, r, branches)
|
||||||
case _ => ???
|
case _ => M6809LargeBuiltins.compileComparison(ctx, if (signed) ComparisonType.GreaterOrEqualSigned else ComparisonType.GreaterOrEqualUnsigned, l, r, branches)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "<<" =>
|
case "<<" =>
|
||||||
@ -766,8 +796,13 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
|||||||
def compileAddressToX(ctx: CompilationContext, expr: LhsExpression): List[MLine] = {
|
def compileAddressToX(ctx: CompilationContext, expr: LhsExpression): List[MLine] = {
|
||||||
expr match {
|
expr match {
|
||||||
case VariableExpression(name) =>
|
case VariableExpression(name) =>
|
||||||
val variable = ctx.env.get[VariableInMemory](name)
|
ctx.env.get[Thing](name) match {
|
||||||
List(MLine.immediate(MOpcode.LDX, variable.toAddress))
|
case variable: VariableInMemory =>
|
||||||
|
List(MLine.immediate(MOpcode.LDX, variable.toAddress))
|
||||||
|
case variable: StackVariable =>
|
||||||
|
List(MLine.variable(ctx, LEAX, variable))
|
||||||
|
}
|
||||||
|
|
||||||
case DerefExpression(inner, offset, _) =>
|
case DerefExpression(inner, offset, _) =>
|
||||||
compileToX(ctx, inner) :+ MLine.indexedX(MOpcode.LEAX, Constant(offset))
|
compileToX(ctx, inner) :+ MLine.indexedX(MOpcode.LEAX, Constant(offset))
|
||||||
case IndexedExpression(aname, index) =>
|
case IndexedExpression(aname, index) =>
|
||||||
@ -913,8 +948,12 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
|||||||
case GeneratedConstantExpression(const, _) =>
|
case GeneratedConstantExpression(const, _) =>
|
||||||
List.tabulate(targetSize)(i => List(MLine.immediate(LDB, const.subbyteBe(targetSize - 1 - i, targetSize))))
|
List.tabulate(targetSize)(i => List(MLine.immediate(LDB, const.subbyteBe(targetSize - 1 - i, targetSize))))
|
||||||
case VariableExpression(name) =>
|
case VariableExpression(name) =>
|
||||||
val v = ctx.env.get[Variable](name)
|
ctx.env.get[VariableLikeThing](name) match {
|
||||||
List.tabulate(targetSize)(i => List(if (i < v.typ.size) MLine.variable(ctx, LDB, v, v.typ.size - 1 - i) else MLine.immediate(LDB, 0)))
|
case v: Variable =>
|
||||||
|
List.tabulate(targetSize)(i => List(if (i < v.typ.size) MLine.variable(ctx, LDB, v, v.typ.size - 1 - i) else MLine.immediate(LDB, 0)))
|
||||||
|
case sot: StackOffsetThing =>
|
||||||
|
List(calculateStackAddressToD(ctx, sot.offset), List(MLine.tfr(M6809Register.A, M6809Register.B)))
|
||||||
|
}
|
||||||
case e:FunctionCallExpression =>
|
case e:FunctionCallExpression =>
|
||||||
ctx.env.maybeGet[NormalFunction](e.functionName) match {
|
ctx.env.maybeGet[NormalFunction](e.functionName) match {
|
||||||
case Some(function) =>
|
case Some(function) =>
|
||||||
@ -930,4 +969,26 @@ object M6809ExpressionCompiler extends AbstractExpressionCompiler[MLine] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def calculateStackAddressToD(ctx: CompilationContext, baseOffset: Int): List[MLine] = {
|
||||||
|
import M6809Register._
|
||||||
|
if (ctx.options.flag(CompilationFlag.UseUForStack)) {
|
||||||
|
List(MLine.tfr(U, D), MLine.immediate(ADDD, baseOffset))
|
||||||
|
} else if (ctx.options.flag(CompilationFlag.UseYForStack)) {
|
||||||
|
List(MLine.tfr(Y, D), MLine.immediate(ADDD, baseOffset))
|
||||||
|
} else {
|
||||||
|
List(MLine.tfr(S, D), MLine.immediate(ADDD, baseOffset + ctx.extraStackOffset))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def calculateStackAddressToX(ctx: CompilationContext, baseOffset: Int): List[MLine] = {
|
||||||
|
import M6809Register._
|
||||||
|
if (ctx.options.flag(CompilationFlag.UseUForStack)) {
|
||||||
|
List(MLine.indexedU(LEAX, baseOffset))
|
||||||
|
} else if (ctx.options.flag(CompilationFlag.UseYForStack)) {
|
||||||
|
List(MLine.indexedY(LEAX, baseOffset))
|
||||||
|
} else {
|
||||||
|
List(MLine.indexedS(LEAX, baseOffset + ctx.extraStackOffset))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package millfork.compiler.m6809
|
package millfork.compiler.m6809
|
||||||
|
|
||||||
import millfork.assembly.m6809.{Immediate, MLine, MLine0, MOpcode, TwoRegisters}
|
import millfork.assembly.m6809.{Immediate, MLine, MLine0, MOpcode, TwoRegisters}
|
||||||
import millfork.compiler.{AbstractExpressionCompiler, CompilationContext}
|
import millfork.compiler.{AbstractExpressionCompiler, BranchIfFalse, BranchIfTrue, BranchSpec, ComparisonType, CompilationContext, NoBranching}
|
||||||
import millfork.node.{Expression, LhsExpression, M6809Register}
|
import millfork.node.{Expression, LhsExpression, M6809Register}
|
||||||
import millfork.assembly.m6809.MOpcode._
|
import millfork.assembly.m6809.MOpcode._
|
||||||
import millfork.env.{Constant, NumericConstant}
|
import millfork.env.{Constant, NumericConstant}
|
||||||
@ -83,6 +83,13 @@ object M6809LargeBuiltins {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def isSingleLdb(code: List[MLine]): Boolean = code.length == 1 && code.head.opcode == LDB
|
||||||
|
|
||||||
|
def replaceLdb(code: List[MLine], op: MOpcode.Value): List[MLine] = {
|
||||||
|
if (code.last.opcode != LDB) ???
|
||||||
|
code.init :+ code.last.copy(opcode = op)
|
||||||
|
}
|
||||||
|
|
||||||
def compileInc(ctx: CompilationContext, target: LhsExpression): List[MLine] = {
|
def compileInc(ctx: CompilationContext, target: LhsExpression): List[MLine] = {
|
||||||
val sizeInBytes = AbstractExpressionCompiler.getExpressionType(ctx, target).size
|
val sizeInBytes = AbstractExpressionCompiler.getExpressionType(ctx, target).size
|
||||||
val result = new ListBuffer[MLine]()
|
val result = new ListBuffer[MLine]()
|
||||||
@ -120,6 +127,7 @@ object M6809LargeBuiltins {
|
|||||||
val result = new ListBuffer[MLine]()
|
val result = new ListBuffer[MLine]()
|
||||||
val targetAddr: Option[Constant] = M6809ExpressionCompiler.compileAddressToX(ctx, target) match {
|
val targetAddr: Option[Constant] = M6809ExpressionCompiler.compileAddressToX(ctx, target) match {
|
||||||
case List(MLine(LDX, Immediate, addr, _, _)) => Some(addr)
|
case List(MLine(LDX, Immediate, addr, _, _)) => Some(addr)
|
||||||
|
case List(MLine(LEAX, _, _, _, _)) => None
|
||||||
case xs =>
|
case xs =>
|
||||||
result ++= xs
|
result ++= xs
|
||||||
ctx.log.error("Invalid left-hand-side expression", target.position)
|
ctx.log.error("Invalid left-hand-side expression", target.position)
|
||||||
@ -273,4 +281,91 @@ object M6809LargeBuiltins {
|
|||||||
result.toList
|
result.toList
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def compileComparison(ctx: CompilationContext, typ: ComparisonType.Value, l: Expression, r: Expression, branches: BranchSpec): List[MLine] = {
|
||||||
|
typ match {
|
||||||
|
case ComparisonType.GreaterSigned | ComparisonType.GreaterUnsigned | ComparisonType.LessOrEqualSigned | ComparisonType.LessOrEqualUnsigned =>
|
||||||
|
return compileComparison(ctx, ComparisonType.flip(typ), r, l, branches)
|
||||||
|
case _ =>
|
||||||
|
}
|
||||||
|
val targetLabel = branches match {
|
||||||
|
case BranchIfTrue(label) => Some(label)
|
||||||
|
case BranchIfFalse(label) => return compileComparison(ctx, ComparisonType.negate(typ), l, r, BranchIfTrue(label))
|
||||||
|
case NoBranching => None
|
||||||
|
}
|
||||||
|
val ltype = AbstractExpressionCompiler.getExpressionType(ctx, l)
|
||||||
|
val rtype = AbstractExpressionCompiler.getExpressionType(ctx, r)
|
||||||
|
val size = ltype.size max rtype.size
|
||||||
|
val lReads = M6809ExpressionCompiler.compileToByteReads(ctx, l, size)
|
||||||
|
val rReads = M6809ExpressionCompiler.compileToByteReads(ctx, r, size)
|
||||||
|
if (!lReads.forall(isSingleLdb) && !rReads.forall(isSingleLdb)) {
|
||||||
|
ctx.log.error("Too complex comparison", l.position.orElse(r.position))
|
||||||
|
return Nil
|
||||||
|
}
|
||||||
|
val result = ListBuffer[MLine]()
|
||||||
|
typ match {
|
||||||
|
case ComparisonType.Equal =>
|
||||||
|
val skipLabel = ctx.nextLabel("co")
|
||||||
|
for(i <- 0 until size) {
|
||||||
|
(lReads(i), rReads(i)) match {
|
||||||
|
case (List(MLine0(LDB, Immediate, NumericConstant(a, _))), List(MLine0(LDB, Immediate, NumericConstant(b, _)))) if a == b =>
|
||||||
|
if (a != b) {
|
||||||
|
targetLabel.foreach(l => result += MLine.shortBranch(BRA, skipLabel))
|
||||||
|
}
|
||||||
|
case (l, r) =>
|
||||||
|
if (isSingleLdb(l)) {
|
||||||
|
result ++= r ++ replaceLdb(l, CMPB)
|
||||||
|
} else if (isSingleLdb(r)) {
|
||||||
|
result ++= l ++ replaceLdb(r, CMPB)
|
||||||
|
} else ???
|
||||||
|
}
|
||||||
|
if (i != size - 1) {
|
||||||
|
targetLabel.foreach(l => result += MLine.longBranch(BNE, skipLabel))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
targetLabel.foreach(l => result += MLine.longBranch(BEQ, l))
|
||||||
|
result += MLine.label(skipLabel)
|
||||||
|
case ComparisonType.NotEqual =>
|
||||||
|
for(i <- 0 until size) {
|
||||||
|
(lReads(i), rReads(i)) match {
|
||||||
|
case (List(MLine0(LDB, Immediate, NumericConstant(a, _))), List(MLine0(LDB, Immediate, NumericConstant(b, _)))) =>
|
||||||
|
if (a != b) {
|
||||||
|
targetLabel.foreach(l => result += MLine.longBranch(BRA, l))
|
||||||
|
}
|
||||||
|
case (l, r) =>
|
||||||
|
if (isSingleLdb(l)) {
|
||||||
|
result ++= r ++ replaceLdb(l, CMPB)
|
||||||
|
} else if (isSingleLdb(r)) {
|
||||||
|
result ++= l ++ replaceLdb(r, CMPB)
|
||||||
|
} else ???
|
||||||
|
}
|
||||||
|
if (result.nonEmpty) {
|
||||||
|
targetLabel.foreach(l => result += MLine.longBranch(BNE, l))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case _ =>
|
||||||
|
for(i <- 0 until size) {
|
||||||
|
val l = lReads(i)
|
||||||
|
val r = rReads(i)
|
||||||
|
if (isSingleLdb(r)) {
|
||||||
|
result ++= M6809ExpressionCompiler.stashCarryIfNeeded(ctx, l)
|
||||||
|
result ++= replaceLdb(r, if (i == 0) SUBB else SBCB)
|
||||||
|
} else {
|
||||||
|
result ++= M6809ExpressionCompiler.stashCarryIfNeeded(ctx, r)
|
||||||
|
result += MLine.pp(PSHS, M6809Register.B)
|
||||||
|
result ++= M6809ExpressionCompiler.stashCarryIfNeeded(ctx, l)
|
||||||
|
result += MLine.accessAndPullS(if (i == 0) SUBB else SBCB)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val j = typ match {
|
||||||
|
case ComparisonType.GreaterOrEqualSigned => MOpcode.BGE
|
||||||
|
case ComparisonType.GreaterOrEqualUnsigned => MOpcode.BCC
|
||||||
|
case ComparisonType.LessSigned => MOpcode.BLT
|
||||||
|
case ComparisonType.LessUnsigned => MOpcode.BCS
|
||||||
|
}
|
||||||
|
targetLabel.foreach(l => result += MLine.longBranch(j, l))
|
||||||
|
}
|
||||||
|
result.toList
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
package millfork.compiler.m6809
|
package millfork.compiler.m6809
|
||||||
|
|
||||||
|
import millfork.{CompilationFlag, CompilationOptions}
|
||||||
import millfork.assembly.{BranchingOpcodeMapping, Elidability}
|
import millfork.assembly.{BranchingOpcodeMapping, Elidability}
|
||||||
import millfork.assembly.m6809.{Inherent, MLine, MOpcode, NonExistent}
|
import millfork.assembly.m6809.{Inherent, MLine, MOpcode, NonExistent}
|
||||||
import millfork.compiler.{AbstractCompiler, AbstractExpressionCompiler, AbstractStatementCompiler, BranchSpec, CompilationContext}
|
import millfork.compiler.{AbstractCompiler, AbstractExpressionCompiler, AbstractStatementCompiler, BranchSpec, CompilationContext}
|
||||||
import millfork.node.{Assignment, BlackHoleExpression, BreakStatement, ContinueStatement, DoWhileStatement, ExecutableStatement, Expression, ExpressionStatement, ForEachStatement, ForStatement, FunctionCallExpression, GotoStatement, IfStatement, LabelStatement, LiteralExpression, M6809AssemblyStatement, MemsetStatement, ReturnDispatchStatement, ReturnStatement, VariableExpression, WhileStatement}
|
import millfork.node.{Assignment, BlackHoleExpression, BreakStatement, ContinueStatement, DoWhileStatement, EmptyStatement, ExecutableStatement, Expression, ExpressionStatement, ForEachStatement, ForStatement, FunctionCallExpression, GotoStatement, IfStatement, LabelStatement, LiteralExpression, M6809AssemblyStatement, MemsetStatement, ReturnDispatchStatement, ReturnStatement, VariableExpression, WhileStatement}
|
||||||
import millfork.assembly.m6809.MOpcode._
|
import millfork.assembly.m6809.MOpcode._
|
||||||
import millfork.env.{BooleanType, ConstantBooleanType, FatBooleanType, Label, MemoryAddressConstant, StructureConstant, ThingInMemory}
|
import millfork.env.{BooleanType, ConstantBooleanType, FatBooleanType, Label, MemoryAddressConstant, StructureConstant, ThingInMemory}
|
||||||
|
|
||||||
@ -13,11 +14,25 @@ import millfork.env.{BooleanType, ConstantBooleanType, FatBooleanType, Label, Me
|
|||||||
object M6809StatementCompiler extends AbstractStatementCompiler[MLine] {
|
object M6809StatementCompiler extends AbstractStatementCompiler[MLine] {
|
||||||
def compile(ctx: CompilationContext, statement: ExecutableStatement): (List[MLine], List[MLine]) = {
|
def compile(ctx: CompilationContext, statement: ExecutableStatement): (List[MLine], List[MLine]) = {
|
||||||
val env = ctx.env
|
val env = ctx.env
|
||||||
|
val epilogue = if (ctx.function.stackVariablesSize == 0) Nil else {
|
||||||
|
import millfork.node.M6809Register.{U, Y}
|
||||||
|
if (ctx.options.flag(CompilationFlag.UseUForStack)) {
|
||||||
|
List(
|
||||||
|
MLine.indexedS(LEAS, ctx.function.stackVariablesSize),
|
||||||
|
MLine.pp(PULS, U))
|
||||||
|
} else if (ctx.options.flag(CompilationFlag.UseYForStack)) {
|
||||||
|
List(
|
||||||
|
MLine.indexedS(LEAS, ctx.function.stackVariablesSize),
|
||||||
|
MLine.pp(PULS, Y))
|
||||||
|
} else {
|
||||||
|
List(MLine.indexedS(LEAS, ctx.function.stackVariablesSize))
|
||||||
|
}
|
||||||
|
}
|
||||||
val code: (List[MLine], List[MLine]) = statement match {
|
val code: (List[MLine], List[MLine]) = statement match {
|
||||||
case ReturnStatement(None) =>
|
case ReturnStatement(None) =>
|
||||||
// TODO: clean stack
|
// TODO: clean stack
|
||||||
// TODO: RTI
|
// TODO: RTI
|
||||||
List(MLine.inherent(RTS)) -> Nil
|
(epilogue :+ MLine.inherent(RTS)) -> Nil
|
||||||
case ReturnStatement(Some(e)) =>
|
case ReturnStatement(Some(e)) =>
|
||||||
// TODO: clean stack
|
// TODO: clean stack
|
||||||
// TODO: RTI
|
// TODO: RTI
|
||||||
@ -41,7 +56,7 @@ object M6809StatementCompiler extends AbstractStatementCompiler[MLine] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(eval ++ rts) -> Nil
|
(eval ++ epilogue ++ rts) -> Nil
|
||||||
case M6809AssemblyStatement(opcode, addrMode, expression, elidability) =>
|
case M6809AssemblyStatement(opcode, addrMode, expression, elidability) =>
|
||||||
ctx.env.evalForAsm(expression, opcode) match {
|
ctx.env.evalForAsm(expression, opcode) match {
|
||||||
case Some(e) => List(MLine(opcode, addrMode, e, elidability)) -> Nil
|
case Some(e) => List(MLine(opcode, addrMode, e, elidability)) -> Nil
|
||||||
@ -109,6 +124,8 @@ object M6809StatementCompiler extends AbstractStatementCompiler[MLine] {
|
|||||||
}
|
}
|
||||||
case s: ReturnDispatchStatement =>
|
case s: ReturnDispatchStatement =>
|
||||||
M6809ReturnDispatch.compile(ctx, s) -> Nil
|
M6809ReturnDispatch.compile(ctx, s) -> Nil
|
||||||
|
case EmptyStatement(_) =>
|
||||||
|
Nil -> Nil
|
||||||
case _ =>
|
case _ =>
|
||||||
println(statement)
|
println(statement)
|
||||||
ctx.log.error("Not implemented yet", statement.position)
|
ctx.log.error("Not implemented yet", statement.position)
|
||||||
|
13
src/main/scala/millfork/env/Constant.scala
vendored
13
src/main/scala/millfork/env/Constant.scala
vendored
@ -1,5 +1,6 @@
|
|||||||
package millfork.env
|
package millfork.env
|
||||||
|
|
||||||
|
import millfork.CompilationOptions
|
||||||
import millfork.DecimalUtils._
|
import millfork.DecimalUtils._
|
||||||
import millfork.node.{ResolvedFieldDesc, SumExpression}
|
import millfork.node.{ResolvedFieldDesc, SumExpression}
|
||||||
import millfork.output.DivisibleAlignment
|
import millfork.output.DivisibleAlignment
|
||||||
@ -95,13 +96,23 @@ sealed trait Constant {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def subconstant(offset: Int, length: Int): Constant = {
|
def subconstant(options: CompilationOptions, offset: Int, length: Int): Constant = {
|
||||||
if (offset == 0 && length == requiredSize) {
|
if (offset == 0 && length == requiredSize) {
|
||||||
this
|
this
|
||||||
|
} else if (options.platform.isBigEndian && length == 1) {
|
||||||
|
// TODO: is this ok?
|
||||||
|
subbyteBe(offset, requiredSize)
|
||||||
} else if (length == 1) {
|
} else if (length == 1) {
|
||||||
subbyte(offset)
|
subbyte(offset)
|
||||||
} else if (offset >= requiredSize) {
|
} else if (offset >= requiredSize) {
|
||||||
Constant.Zero
|
Constant.Zero
|
||||||
|
} else if (options.platform.isBigEndian) {
|
||||||
|
// TODO: is this ok?
|
||||||
|
(0 until length).map { i =>
|
||||||
|
val index = i + offset
|
||||||
|
val shift = 8 * (length - i)
|
||||||
|
CompoundConstant(MathOperator.Shl, subbyteBe(index, requiredSize), NumericConstant(shift, 1)).quickSimplify
|
||||||
|
}.reduceLeft((l, r) => CompoundConstant(MathOperator.Or, l, r).quickSimplify).quickSimplify
|
||||||
} else {
|
} else {
|
||||||
((length - 1) to 0 by (-1)).map { i =>
|
((length - 1) to 0 by (-1)).map { i =>
|
||||||
val index = i + offset
|
val index = i + offset
|
||||||
|
@ -1844,7 +1844,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
|||||||
addThing(ConstantThing(prefix + name, constantValue, typ), stmt.position)
|
addThing(ConstantThing(prefix + name, constantValue, typ), stmt.position)
|
||||||
for(Subvariable(suffix, offset, t, arraySize) <- getSubvariables(typ)) {
|
for(Subvariable(suffix, offset, t, arraySize) <- getSubvariables(typ)) {
|
||||||
if (arraySize.isDefined) ??? // TODO
|
if (arraySize.isDefined) ??? // TODO
|
||||||
addThing(ConstantThing(prefix + name + suffix, constantValue.subconstant(offset, t.size), t), stmt.position)
|
addThing(ConstantThing(prefix + name + suffix, constantValue.subconstant(options, offset, t.size), t), stmt.position)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (stmt.stack && stmt.global) log.error(s"`$name` is static or global and cannot be on stack", position)
|
if (stmt.stack && stmt.global) log.error(s"`$name` is static or global and cannot be on stack", position)
|
||||||
|
@ -32,6 +32,7 @@ object EmuM6809Run {
|
|||||||
TestErrorReporting.log.info(s"Loading $filename for $cpu")
|
TestErrorReporting.log.info(s"Loading $filename for $cpu")
|
||||||
val source = Files.readAllLines(Paths.get(filename), StandardCharsets.US_ASCII).asScala.mkString("\n")
|
val source = Files.readAllLines(Paths.get(filename), StandardCharsets.US_ASCII).asScala.mkString("\n")
|
||||||
val options = CompilationOptions(EmuPlatform.get(cpu), Map(
|
val options = CompilationOptions(EmuPlatform.get(cpu), Map(
|
||||||
|
CompilationFlag.UseUForStack -> true,
|
||||||
CompilationFlag.LenientTextEncoding -> true
|
CompilationFlag.LenientTextEncoding -> true
|
||||||
), None, 0, Map(), EmuPlatform.textCodecRepository, JobContext(TestErrorReporting.log, new LabelGenerator))
|
), None, 0, Map(), EmuPlatform.textCodecRepository, JobContext(TestErrorReporting.log, new LabelGenerator))
|
||||||
val PreprocessingResult(preprocessedSource, features, _) = Preprocessor.preprocessForTest(options, source)
|
val PreprocessingResult(preprocessedSource, features, _) = Preprocessor.preprocessForTest(options, source)
|
||||||
@ -90,6 +91,7 @@ class EmuM6809Run(cpu: millfork.Cpu.Value, nodeOptimizations: List[NodeOptimizat
|
|||||||
CompilationFlag.EmitIllegals -> this.emitIllegals,
|
CompilationFlag.EmitIllegals -> this.emitIllegals,
|
||||||
CompilationFlag.InlineFunctions -> this.inline,
|
CompilationFlag.InlineFunctions -> this.inline,
|
||||||
CompilationFlag.OptimizeStdlib -> this.inline,
|
CompilationFlag.OptimizeStdlib -> this.inline,
|
||||||
|
CompilationFlag.UseUForStack -> true,
|
||||||
CompilationFlag.InterproceduralOptimization -> true,
|
CompilationFlag.InterproceduralOptimization -> true,
|
||||||
CompilationFlag.CompactReturnDispatchParams -> true,
|
CompilationFlag.CompactReturnDispatchParams -> true,
|
||||||
CompilationFlag.SubroutineExtraction -> optimizeForSize,
|
CompilationFlag.SubroutineExtraction -> optimizeForSize,
|
||||||
|
Loading…
Reference in New Issue
Block a user