mirror of
https://github.com/KarolS/millfork.git
synced 2025-02-08 00:30:38 +00:00
Allow putting pointer variables anywhere
This commit is contained in:
parent
194f79f907
commit
4cd1db0e0f
@ -198,13 +198,37 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
|||||||
AssemblyLine.zeropage(STA, reg, 1),
|
AssemblyLine.zeropage(STA, reg, 1),
|
||||||
AssemblyLine.immediate(LDA, addr.loByte),
|
AssemblyLine.immediate(LDA, addr.loByte),
|
||||||
AssemblyLine.zeropage(STA, reg))
|
AssemblyLine.zeropage(STA, reg))
|
||||||
case VariablePointy(addr, _, _) =>
|
case VariablePointy(addr, _, _, true) =>
|
||||||
List(
|
List(
|
||||||
AssemblyLine.implied(CLC),
|
AssemblyLine.implied(CLC),
|
||||||
AssemblyLine.zeropage(ADC, addr + 1),
|
AssemblyLine.zeropage(ADC, addr + 1),
|
||||||
AssemblyLine.zeropage(STA, reg, 1),
|
AssemblyLine.zeropage(STA, reg, 1),
|
||||||
AssemblyLine.zeropage(LDA, addr),
|
AssemblyLine.zeropage(LDA, addr),
|
||||||
AssemblyLine.zeropage(STA, reg))
|
AssemblyLine.zeropage(STA, reg))
|
||||||
|
case VariablePointy(addr, _, _, false) =>
|
||||||
|
List(
|
||||||
|
AssemblyLine.implied(CLC),
|
||||||
|
AssemblyLine.absolute(ADC, addr + 1),
|
||||||
|
AssemblyLine.zeropage(STA, reg, 1),
|
||||||
|
AssemblyLine.absolute(LDA, addr),
|
||||||
|
AssemblyLine.zeropage(STA, reg))
|
||||||
|
case StackVariablePointy(offset, _, _) =>
|
||||||
|
if (ctx.options.flag(CompilationFlag.EmitEmulation65816Opcodes)) {
|
||||||
|
List(
|
||||||
|
AssemblyLine.implied(CLC),
|
||||||
|
AssemblyLine.stackRelative(ADC, offset + 1 + ctx.extraStackOffset),
|
||||||
|
AssemblyLine.zeropage(STA, reg, 1),
|
||||||
|
AssemblyLine.stackRelative(LDA, offset + ctx.extraStackOffset),
|
||||||
|
AssemblyLine.zeropage(STA, reg))
|
||||||
|
} else {
|
||||||
|
List(
|
||||||
|
AssemblyLine.implied(CLC),
|
||||||
|
AssemblyLine.implied(TSX),
|
||||||
|
AssemblyLine.absoluteX(ADC, offset + 1 + ctx.extraStackOffset),
|
||||||
|
AssemblyLine.zeropage(STA, reg, 1),
|
||||||
|
AssemblyLine.absoluteX(LDA, offset + ctx.extraStackOffset),
|
||||||
|
AssemblyLine.zeropage(STA, reg))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
compileIndex ++ prepareRegister
|
compileIndex ++ prepareRegister
|
||||||
}
|
}
|
||||||
@ -279,21 +303,21 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
|||||||
val cmos = ctx.options.flag(CompilationFlag.EmitCmosOpcodes)
|
val cmos = ctx.options.flag(CompilationFlag.EmitCmosOpcodes)
|
||||||
register match {
|
register match {
|
||||||
case MosRegister.A =>
|
case MosRegister.A =>
|
||||||
List(AssemblyLine.implied(PHA)) ++ code ++ List(AssemblyLine.implied(PLA), AssemblyLine.indexedY(STA, reg))
|
List(AssemblyLine.implied(PHA)) ++ fixTsx(code) ++ List(AssemblyLine.implied(PLA), AssemblyLine.indexedY(STA, reg))
|
||||||
case MosRegister.X =>
|
case MosRegister.X =>
|
||||||
if (code.exists(l => OpcodeClasses.ChangesX(l.opcode))) {
|
if (code.exists(l => OpcodeClasses.ChangesX(l.opcode))) {
|
||||||
if (cmos)
|
if (cmos)
|
||||||
List(AssemblyLine.implied(PHX)) ++ code ++ List(AssemblyLine.implied(PLA), AssemblyLine.indexedY(STA, reg))
|
List(AssemblyLine.implied(PHX)) ++ fixTsx(code) ++ List(AssemblyLine.implied(PLA), AssemblyLine.indexedY(STA, reg))
|
||||||
else
|
else
|
||||||
List(AssemblyLine.implied(TXA), AssemblyLine.implied(PHA)) ++ code ++ List(AssemblyLine.implied(PLA), AssemblyLine.indexedY(STA, reg))
|
List(AssemblyLine.implied(TXA), AssemblyLine.implied(PHA)) ++ fixTsx(code) ++ List(AssemblyLine.implied(PLA), AssemblyLine.indexedY(STA, reg))
|
||||||
} else {
|
} else {
|
||||||
code ++ List(AssemblyLine.implied(TXA), AssemblyLine.indexedY(STA, reg))
|
code ++ List(AssemblyLine.implied(TXA), AssemblyLine.indexedY(STA, reg))
|
||||||
}
|
}
|
||||||
case MosRegister.Y =>
|
case MosRegister.Y =>
|
||||||
if (cmos)
|
if (cmos)
|
||||||
List(AssemblyLine.implied(PHY)) ++ code ++ List(AssemblyLine.implied(PLA), AssemblyLine.indexedY(STA, reg))
|
List(AssemblyLine.implied(PHY)) ++ fixTsx(code) ++ List(AssemblyLine.implied(PLA), AssemblyLine.indexedY(STA, reg))
|
||||||
else
|
else
|
||||||
List(AssemblyLine.implied(TYA), AssemblyLine.implied(PHA)) ++ code ++ List(AssemblyLine.implied(PLA), AssemblyLine.indexedY(STA, reg))
|
List(AssemblyLine.implied(TYA), AssemblyLine.implied(PHA)) ++ fixTsx(code) ++ List(AssemblyLine.implied(PLA), AssemblyLine.indexedY(STA, reg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,13 +326,16 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
|||||||
List(AssemblyLine.absolute(store, env.genRelativeVariable(p.value + constIndex, b, zeropage = false)))
|
List(AssemblyLine.absolute(store, env.genRelativeVariable(p.value + constIndex, b, zeropage = false)))
|
||||||
case (p: VariablePointy, _, _, 2) =>
|
case (p: VariablePointy, _, _, 2) =>
|
||||||
wrapWordIndexingStorage(prepareWordIndexing(ctx, p, indexExpr))
|
wrapWordIndexingStorage(prepareWordIndexing(ctx, p, indexExpr))
|
||||||
|
case (p: VariablePointy, _, 0 | 1, _) if !p.zeropage =>
|
||||||
|
// TODO: optimize?
|
||||||
|
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, NoAlignment), 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?
|
||||||
case (pointerVariable:VariablePointy, None, _, 0 | 1) =>
|
case (pointerVariable@VariablePointy(varAddr, _, _, true), None, _, 0 | 1) =>
|
||||||
register match {
|
register match {
|
||||||
case MosRegister.A =>
|
case MosRegister.A =>
|
||||||
List(AssemblyLine.immediate(LDY, constIndex), AssemblyLine.indexedY(STA, pointerVariable.addr))
|
List(AssemblyLine.immediate(LDY, constIndex), AssemblyLine.indexedY(STA, pointerVariable.addr))
|
||||||
@ -320,21 +347,51 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
|||||||
ctx.log.error("Cannot store a word in an array", target.position)
|
ctx.log.error("Cannot store a word in an array", target.position)
|
||||||
Nil
|
Nil
|
||||||
}
|
}
|
||||||
case (pointerVariable:VariablePointy, Some(_), _, 0 | 1) =>
|
case (p@VariablePointy(varAddr, _, _, true), Some(_), _, 0 | 1) =>
|
||||||
val calculatingIndex = compile(ctx, indexExpr, Some(b, RegisterVariable(MosRegister.Y, b)), NoBranching)
|
val calculatingIndex = compile(ctx, indexExpr, Some(b, RegisterVariable(MosRegister.Y, b)), NoBranching)
|
||||||
register match {
|
register match {
|
||||||
case MosRegister.A =>
|
case MosRegister.A =>
|
||||||
preserveRegisterIfNeeded(ctx, MosRegister.A, calculatingIndex) :+ AssemblyLine.indexedY(STA, pointerVariable.addr)
|
preserveRegisterIfNeeded(ctx, MosRegister.A, calculatingIndex) :+ AssemblyLine.indexedY(STA, varAddr)
|
||||||
case MosRegister.X =>
|
case MosRegister.X =>
|
||||||
preserveRegisterIfNeeded(ctx, MosRegister.X, calculatingIndex) ++ List(AssemblyLine.implied(TXA), AssemblyLine.indexedY(STA, pointerVariable.addr))
|
preserveRegisterIfNeeded(ctx, MosRegister.X, calculatingIndex) ++ List(AssemblyLine.implied(TXA), AssemblyLine.indexedY(STA, varAddr))
|
||||||
case MosRegister.Y =>
|
case MosRegister.Y =>
|
||||||
AssemblyLine.implied(TYA) :: preserveRegisterIfNeeded(ctx, MosRegister.A, calculatingIndex) ++ List(
|
AssemblyLine.implied(TYA) :: preserveRegisterIfNeeded(ctx, MosRegister.A, calculatingIndex) ++ List(
|
||||||
AssemblyLine.indexedY(STA, pointerVariable.addr), AssemblyLine.implied(TAY)
|
AssemblyLine.indexedY(STA, varAddr), AssemblyLine.implied(TAY)
|
||||||
)
|
)
|
||||||
case _ =>
|
case _ =>
|
||||||
ctx.log.error("Cannot store a word in an array", target.position)
|
ctx.log.error("Cannot store a word in an array", target.position)
|
||||||
Nil
|
Nil
|
||||||
}
|
}
|
||||||
|
case (StackVariablePointy(offset, _, _), None, _, 0 | 1) if ctx.options.flag(CompilationFlag.EmitEmulation65816Opcodes) =>
|
||||||
|
register match {
|
||||||
|
case MosRegister.A =>
|
||||||
|
List(AssemblyLine.immediate(LDY, constIndex), AssemblyLine.indexedSY(STA, offset))
|
||||||
|
case MosRegister.Y =>
|
||||||
|
List(AssemblyLine.implied(TYA), AssemblyLine.immediate(LDY, constIndex), AssemblyLine.indexedSY(STA, offset), AssemblyLine.implied(TAY))
|
||||||
|
case MosRegister.X =>
|
||||||
|
List(AssemblyLine.immediate(LDY, constIndex), AssemblyLine.implied(TXA), AssemblyLine.indexedSY(STA, offset))
|
||||||
|
case _ =>
|
||||||
|
ctx.log.error("Cannot store a word in an array", target.position)
|
||||||
|
Nil
|
||||||
|
}
|
||||||
|
case (p@StackVariablePointy(offset, _, _), Some(_), _, 0 | 1) if ctx.options.flag(CompilationFlag.EmitEmulation65816Opcodes) =>
|
||||||
|
val calculatingIndex = compile(ctx, indexExpr, Some(b, RegisterVariable(MosRegister.Y, b)), NoBranching)
|
||||||
|
register match {
|
||||||
|
case MosRegister.A =>
|
||||||
|
preserveRegisterIfNeeded(ctx, MosRegister.A, calculatingIndex) :+ AssemblyLine.indexedSY(STA, offset)
|
||||||
|
case MosRegister.X =>
|
||||||
|
preserveRegisterIfNeeded(ctx, MosRegister.X, calculatingIndex) ++ List(AssemblyLine.implied(TXA), AssemblyLine.indexedSY(STA, offset))
|
||||||
|
case MosRegister.Y =>
|
||||||
|
AssemblyLine.implied(TYA) :: preserveRegisterIfNeeded(ctx, MosRegister.A, calculatingIndex) ++ List(
|
||||||
|
AssemblyLine.indexedSY(STA, offset), AssemblyLine.implied(TAY)
|
||||||
|
)
|
||||||
|
case _ =>
|
||||||
|
ctx.log.error("Cannot store a word in an array", target.position)
|
||||||
|
Nil
|
||||||
|
}
|
||||||
|
case (p: StackVariablePointy, _, _, _) =>
|
||||||
|
// TODO: optimize?
|
||||||
|
wrapWordIndexingStorage(prepareWordIndexing(ctx, p, indexExpr))
|
||||||
case _ =>
|
case _ =>
|
||||||
ctx.log.error("Invalid index for writing", indexExpr.position)
|
ctx.log.error("Invalid index for writing", indexExpr.position)
|
||||||
Nil
|
Nil
|
||||||
@ -716,6 +773,8 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
|||||||
a.elementType, NoAlignment), 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, _, 0 | 1, _) if !p.zeropage =>
|
||||||
|
prepareWordIndexing(ctx, p, indexExpr) ++ loadFromReg()
|
||||||
case (p:VariablePointy, None, 0 | 1, _) =>
|
case (p:VariablePointy, None, 0 | 1, _) =>
|
||||||
register match {
|
register match {
|
||||||
case MosRegister.A =>
|
case MosRegister.A =>
|
||||||
@ -735,6 +794,17 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
|||||||
case MosRegister.Y =>
|
case MosRegister.Y =>
|
||||||
calculatingIndex ++ List(AssemblyLine.indexedY(LDA, p.addr), AssemblyLine.implied(TAY))
|
calculatingIndex ++ List(AssemblyLine.indexedY(LDA, p.addr), AssemblyLine.implied(TAY))
|
||||||
}
|
}
|
||||||
|
case (p: StackVariablePointy, _, 0 | 1, _) if ctx.options.flag(CompilationFlag.EmitEmulation65816Opcodes) =>
|
||||||
|
register match {
|
||||||
|
case MosRegister.A =>
|
||||||
|
List(AssemblyLine.immediate(LDY, constantIndex), AssemblyLine.indexedSY(LDA, p.offset))
|
||||||
|
case MosRegister.Y =>
|
||||||
|
List(AssemblyLine.immediate(LDY, constantIndex), AssemblyLine.indexedSY(LDA, p.offset), AssemblyLine.implied(TAY))
|
||||||
|
case MosRegister.X =>
|
||||||
|
List(AssemblyLine.immediate(LDY, constantIndex), AssemblyLine.indexedSY(LDA, p.offset), AssemblyLine.implied(TAX))
|
||||||
|
}
|
||||||
|
case (p: StackVariablePointy, _, _, _) =>
|
||||||
|
prepareWordIndexing(ctx, p, indexExpr) ++ loadFromReg()
|
||||||
case _ =>
|
case _ =>
|
||||||
ctx.log.error("Invalid index for reading", indexExpr.position)
|
ctx.log.error("Invalid index for reading", indexExpr.position)
|
||||||
Nil
|
Nil
|
||||||
|
@ -1004,7 +1004,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
|||||||
List(ZLine.registers(ADD_16, ZRegister.HL, ZRegister.BC))
|
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 {
|
||||||
case Some(NumericConstant(0, _)) =>
|
case Some(NumericConstant(0, _)) =>
|
||||||
if (ctx.options.flag(CompilationFlag.EmitIntel8080Opcodes)) {
|
if (ctx.options.flag(CompilationFlag.EmitIntel8080Opcodes)) {
|
||||||
@ -1034,6 +1034,10 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
|||||||
ZLine.registers(ADD_16, ZRegister.HL, ZRegister.BC))
|
ZLine.registers(ADD_16, ZRegister.HL, ZRegister.BC))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case _: StackVariablePointy =>
|
||||||
|
compileToHL(ctx, VariableExpression(i.name).pos(i.position)) ++
|
||||||
|
stashHLIfChanged(ctx, compileToBC(ctx, i.index)) ++
|
||||||
|
List(ZLine.registers(ADD_16, ZRegister.HL, ZRegister.BC))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
src/main/scala/millfork/env/Constant.scala
vendored
2
src/main/scala/millfork/env/Constant.scala
vendored
@ -215,6 +215,8 @@ case class MemoryAddressConstant(var thing: ThingInMemory) extends Constant {
|
|||||||
case _ => false
|
case _ => false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override def fitsProvablyIntoByte: Boolean = thing.zeropage
|
||||||
|
|
||||||
override def requiredSize = 2
|
override def requiredSize = 2
|
||||||
|
|
||||||
override def toString: String = thing.name
|
override def toString: String = thing.name
|
||||||
|
25
src/main/scala/millfork/env/Environment.scala
vendored
25
src/main/scala/millfork/env/Environment.scala
vendored
@ -294,7 +294,8 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
|||||||
}
|
}
|
||||||
|
|
||||||
def getArrayOrPointer(arrayName: String): Thing = {
|
def getArrayOrPointer(arrayName: String): Thing = {
|
||||||
maybeGet[ThingInMemory](arrayName).
|
maybeGet[StackVariable](arrayName).
|
||||||
|
orElse(maybeGet[ThingInMemory](arrayName)).
|
||||||
orElse(maybeGet[ThingInMemory](arrayName + ".array")).
|
orElse(maybeGet[ThingInMemory](arrayName + ".array")).
|
||||||
orElse(maybeGet[ConstantThing](arrayName)).
|
orElse(maybeGet[ConstantThing](arrayName)).
|
||||||
getOrElse(log.fatal(s"`$arrayName` is not an array or a pointer"))
|
getOrElse(log.fatal(s"`$arrayName` is not an array or a pointer"))
|
||||||
@ -314,7 +315,11 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
|||||||
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")
|
||||||
VariablePointy(th.toAddress, w, b)
|
VariablePointy(th.toAddress, w, b, th.zeropage)
|
||||||
|
case th:StackVariable if th.typ.isPointy =>
|
||||||
|
val b = get[VariableType]("byte")
|
||||||
|
val w = get[VariableType]("word")
|
||||||
|
StackVariablePointy(th.baseOffset, w, b)
|
||||||
case _ =>
|
case _ =>
|
||||||
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")
|
||||||
@ -1148,17 +1153,6 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
|||||||
val b = get[Type]("byte")
|
val b = get[Type]("byte")
|
||||||
val w = get[Type]("word")
|
val w = get[Type]("word")
|
||||||
val typ = get[VariableType](stmt.typ)
|
val typ = get[VariableType](stmt.typ)
|
||||||
if (stmt.typ == "pointer" || stmt.typ == "farpointer") {
|
|
||||||
// if (stmt.constant) {
|
|
||||||
// log.error(s"Pointer `${stmt.name}` cannot be constant")
|
|
||||||
// }
|
|
||||||
stmt.address.flatMap(eval) match {
|
|
||||||
case Some(NumericConstant(a, _)) =>
|
|
||||||
if ((a & 0xff00) != 0)
|
|
||||||
log.error(s"Pointer `${stmt.name}` cannot be located outside the zero page")
|
|
||||||
case _ => ()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val alignment = stmt.alignment.getOrElse(defaultVariableAlignment(options, typ.size))
|
val alignment = stmt.alignment.getOrElse(defaultVariableAlignment(options, typ.size))
|
||||||
if (stmt.constant) {
|
if (stmt.constant) {
|
||||||
if (stmt.stack) log.error(s"`$name` is a constant and cannot be on stack", position)
|
if (stmt.stack) log.error(s"`$name` is a constant and cannot be on stack", position)
|
||||||
@ -1191,7 +1185,8 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
|||||||
} else {
|
} else {
|
||||||
val (v, addr) = stmt.address.fold[(VariableInMemory, Constant)]({
|
val (v, addr) = stmt.address.fold[(VariableInMemory, Constant)]({
|
||||||
val alloc =
|
val alloc =
|
||||||
if (isPointy || typ.name == "__reg$type") VariableAllocationMethod.Zeropage
|
if (isPointy && stmt.bank.isEmpty) VariableAllocationMethod.Zeropage
|
||||||
|
else if (typ.name == "__reg$type") VariableAllocationMethod.Zeropage
|
||||||
else if (stmt.global) VariableAllocationMethod.Static
|
else if (stmt.global) VariableAllocationMethod.Static
|
||||||
else if (stmt.register) VariableAllocationMethod.Register
|
else if (stmt.register) VariableAllocationMethod.Register
|
||||||
else VariableAllocationMethod.Auto
|
else VariableAllocationMethod.Auto
|
||||||
@ -1257,7 +1252,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
|||||||
(".b1", 1, b),
|
(".b1", 1, b),
|
||||||
(".b2", 2, b),
|
(".b2", 2, b),
|
||||||
(".b3", 3, b))
|
(".b3", 3, b))
|
||||||
case sz if sz > 4 => List.tabulate(sz){ i => (".b" + i, i, b) }
|
case sz if sz > 4 => (".lo", 0, b) :: (".loword", 0, w) :: List.tabulate(sz){ i => (".b" + i, i, b) }
|
||||||
case _ => Nil
|
case _ => Nil
|
||||||
}
|
}
|
||||||
case _ => Nil
|
case _ => Nil
|
||||||
|
6
src/main/scala/millfork/env/Pointy.scala
vendored
6
src/main/scala/millfork/env/Pointy.scala
vendored
@ -8,7 +8,11 @@ trait Pointy {
|
|||||||
def elementType: VariableType
|
def elementType: VariableType
|
||||||
}
|
}
|
||||||
|
|
||||||
case class VariablePointy(addr: Constant, indexType: VariableType, elementType: VariableType) extends Pointy {
|
case class StackVariablePointy(offset: Int, indexType: VariableType, elementType: VariableType) extends Pointy {
|
||||||
|
override def name: Option[String] = None
|
||||||
|
}
|
||||||
|
|
||||||
|
case class VariablePointy(addr: Constant, indexType: VariableType, elementType: VariableType, zeropage: Boolean) extends Pointy {
|
||||||
override def name: Option[String] = None
|
override def name: Option[String] = None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
src/main/scala/millfork/env/Thing.scala
vendored
2
src/main/scala/millfork/env/Thing.scala
vendored
@ -175,7 +175,7 @@ object VariableAllocationMethod extends Enumeration {
|
|||||||
val Auto, Register, Static, Zeropage, None = Value
|
val Auto, Register, Static, Zeropage, None = Value
|
||||||
}
|
}
|
||||||
|
|
||||||
case class StackVariable(name: String, typ: Type, baseOffset: Int) extends Variable {
|
case class StackVariable(name: String, typ: Type, baseOffset: Int) extends Variable with IndexableThing {
|
||||||
def sizeInBytes: Int = typ.size
|
def sizeInBytes: Int = typ.size
|
||||||
override def isVolatile: Boolean = false
|
override def isVolatile: Boolean = false
|
||||||
}
|
}
|
||||||
|
42
src/test/scala/millfork/test/PointerSuite.scala
Normal file
42
src/test/scala/millfork/test/PointerSuite.scala
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package millfork.test
|
||||||
|
|
||||||
|
import millfork.Cpu
|
||||||
|
import millfork.test.emu.EmuCrossPlatformBenchmarkRun
|
||||||
|
import org.scalatest.{FunSuite, Matchers}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karol Stasiak
|
||||||
|
*/
|
||||||
|
class PointerSuite extends FunSuite with Matchers {
|
||||||
|
|
||||||
|
test("Pointers outside zeropage") {
|
||||||
|
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Sixteen, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp)(
|
||||||
|
"""
|
||||||
|
| pointer p @$c004
|
||||||
|
| array output[2] @$c000
|
||||||
|
| void main() {
|
||||||
|
| p = output.addr
|
||||||
|
| output[0] = 45
|
||||||
|
| p[1] = p[0]
|
||||||
|
| }
|
||||||
|
""".stripMargin) { m =>
|
||||||
|
m.readByte(0xc001) should equal(45)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test("Pointers on stack") {
|
||||||
|
EmuCrossPlatformBenchmarkRun(Cpu.Mos, Cpu.Sixteen, Cpu.Z80, Cpu.Intel8080, Cpu.Sharp)(
|
||||||
|
"""
|
||||||
|
| array output[2] @$c000
|
||||||
|
| void main() {
|
||||||
|
| stack pointer p
|
||||||
|
| p = output.addr
|
||||||
|
| output[0] = 45
|
||||||
|
| p[1] = p[0]
|
||||||
|
| }
|
||||||
|
""".stripMargin) { m =>
|
||||||
|
m.readByte(0xc001) should equal(45)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user