mirror of
https://github.com/KarolS/millfork.git
synced 2025-01-01 06:29:53 +00:00
Fix volatile
This commit is contained in:
parent
70256e9d46
commit
49816d18fe
@ -547,6 +547,8 @@ object AssemblyLine0 {
|
||||
|
||||
case class AssemblyLine(opcode: Opcode.Value, addrMode: AddrMode.Value, var parameter: Constant, elidability: Elidability.Value = Elidability.Elidable, source: Option[SourceLine] = None) extends AbstractCode {
|
||||
|
||||
def applyVolatile(v: Boolean): AssemblyLine = if (v) copy(elidability = Elidability.Volatile) else this
|
||||
|
||||
def pos(s: Option[SourceLine]): AssemblyLine = if (s.isEmpty || s == source) this else this.copy(source = s)
|
||||
|
||||
def pos(s1: Option[SourceLine], s2: Option[SourceLine]): AssemblyLine = pos(Seq(s1, s2))
|
||||
|
@ -89,7 +89,7 @@ object ZLine {
|
||||
import ZOpcode._
|
||||
import ZRegister._
|
||||
|
||||
private def elidability(source: ThingInMemory): Elidability.Value = {
|
||||
def elidability(source: ThingInMemory): Elidability.Value = {
|
||||
if (source.isVolatile) Elidability.Volatile else Elidability.Elidable
|
||||
}
|
||||
|
||||
|
@ -140,11 +140,12 @@ object ByteVariableToRegisterOptimization extends AssemblyOptimization[ZLine] {
|
||||
val newCode = inlineVars(v, register, addressInHl = false, addressInBc = false, addressInDe = false, oldCode.map(_._2))
|
||||
reportOptimizedBlock(oldCode, newCode)
|
||||
if (vs.paramVariables(v)) {
|
||||
val addr = vs.localVariables.find(_.name.==(v)).get.asInstanceOf[MemoryVariable].toAddress
|
||||
val variable = vs.localVariables.find(_.name.==(v)).get.asInstanceOf[MemoryVariable]
|
||||
val addr = variable.toAddress
|
||||
if (register == ZRegister.A) {
|
||||
output += ZLine.ldAbs8(ZRegister.A, addr)
|
||||
output += ZLine.ldAbs8(ZRegister.A, addr, elidability = ZLine.elidability(variable))
|
||||
} else {
|
||||
output += ZLine.ldAbs8(ZRegister.A, addr)
|
||||
output += ZLine.ldAbs8(ZRegister.A, addr, elidability = ZLine.elidability(variable))
|
||||
output += ZLine.ld8(register, ZRegister.A)
|
||||
}
|
||||
}
|
||||
|
@ -224,19 +224,19 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
||||
AssemblyLine.zeropage(STA, reg, 1),
|
||||
AssemblyLine.immediate(LDA, p.value.loByte),
|
||||
AssemblyLine.zeropage(STA, reg))
|
||||
case VariablePointy(addr, _, _, true) =>
|
||||
case VariablePointy(addr, _, _, true, v) =>
|
||||
List(
|
||||
AssemblyLine.implied(CLC),
|
||||
AssemblyLine.zeropage(ADC, addr + 1),
|
||||
AssemblyLine.zeropage(ADC, addr + 1).applyVolatile(v),
|
||||
AssemblyLine.zeropage(STA, reg, 1),
|
||||
AssemblyLine.zeropage(LDA, addr),
|
||||
AssemblyLine.zeropage(LDA, addr).applyVolatile(v),
|
||||
AssemblyLine.zeropage(STA, reg))
|
||||
case VariablePointy(addr, _, _, false) =>
|
||||
case VariablePointy(addr, _, _, false, v) =>
|
||||
List(
|
||||
AssemblyLine.implied(CLC),
|
||||
AssemblyLine.absolute(ADC, addr + 1),
|
||||
AssemblyLine.absolute(ADC, addr + 1).applyVolatile(v),
|
||||
AssemblyLine.zeropage(STA, reg, 1),
|
||||
AssemblyLine.absolute(LDA, addr),
|
||||
AssemblyLine.absolute(LDA, addr).applyVolatile(v),
|
||||
AssemblyLine.zeropage(STA, reg))
|
||||
case StackVariablePointy(offset, _, _) =>
|
||||
if (ctx.options.flag(CompilationFlag.EmitEmulation65816Opcodes)) {
|
||||
@ -370,25 +370,25 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
|
||||
}
|
||||
storeToArrayAtUnknownIndex(v, p.value)
|
||||
//TODO: should there be a type check or a zeropage check?
|
||||
case (pointerVariable@VariablePointy(varAddr, _, _, true), None, _, 0 | 1) =>
|
||||
case (pointerVariable@VariablePointy(varAddr, _, _, true, volatile), None, _, 0 | 1) =>
|
||||
register match {
|
||||
case MosRegister.A =>
|
||||
List(AssemblyLine.immediate(LDY, constIndex), AssemblyLine.indexedY(STA, pointerVariable.addr))
|
||||
List(AssemblyLine.immediate(LDY, constIndex), AssemblyLine.indexedY(STA, pointerVariable.addr).applyVolatile(volatile))
|
||||
case MosRegister.Y =>
|
||||
List(AssemblyLine.implied(TYA), AssemblyLine.immediate(LDY, constIndex), AssemblyLine.indexedY(STA, pointerVariable.addr), AssemblyLine.implied(TAY))
|
||||
List(AssemblyLine.implied(TYA), AssemblyLine.immediate(LDY, constIndex), AssemblyLine.indexedY(STA, pointerVariable.addr).applyVolatile(volatile), AssemblyLine.implied(TAY))
|
||||
case MosRegister.X =>
|
||||
List(AssemblyLine.immediate(LDY, constIndex), AssemblyLine.implied(TXA), AssemblyLine.indexedY(STA, pointerVariable.addr))
|
||||
List(AssemblyLine.immediate(LDY, constIndex), AssemblyLine.implied(TXA), AssemblyLine.indexedY(STA, pointerVariable.addr).applyVolatile(volatile))
|
||||
case _ =>
|
||||
ctx.log.error("Cannot store a word in an array", target.position)
|
||||
Nil
|
||||
}
|
||||
case (p@VariablePointy(varAddr, _, _, true), Some(_), _, 0 | 1) =>
|
||||
case (p@VariablePointy(varAddr, _, _, true, volatile), Some(_), _, 0 | 1) =>
|
||||
val calculatingIndex = compile(ctx, indexExpr, Some(b, RegisterVariable(MosRegister.Y, b)), NoBranching)
|
||||
register match {
|
||||
case MosRegister.A =>
|
||||
preserveRegisterIfNeeded(ctx, MosRegister.A, calculatingIndex) :+ AssemblyLine.indexedY(STA, varAddr)
|
||||
preserveRegisterIfNeeded(ctx, MosRegister.A, calculatingIndex) :+ AssemblyLine.indexedY(STA, varAddr).applyVolatile(volatile)
|
||||
case MosRegister.X =>
|
||||
preserveRegisterIfNeeded(ctx, MosRegister.X, calculatingIndex) ++ List(AssemblyLine.implied(TXA), AssemblyLine.indexedY(STA, varAddr))
|
||||
preserveRegisterIfNeeded(ctx, MosRegister.X, calculatingIndex) ++ List(AssemblyLine.implied(TXA), AssemblyLine.indexedY(STA, varAddr).applyVolatile(volatile))
|
||||
case MosRegister.Y =>
|
||||
AssemblyLine.implied(TYA) :: preserveRegisterIfNeeded(ctx, MosRegister.A, calculatingIndex) ++ List(
|
||||
AssemblyLine.indexedY(STA, varAddr), AssemblyLine.implied(TAY)
|
||||
|
@ -432,10 +432,10 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
case ZExpressionTarget.DEHL =>
|
||||
// TODO: signed int24s
|
||||
if (ctx.options.flag(CompilationFlag.EmitZ80Opcodes)) {
|
||||
List(ZLine.ldAbs16(HL, v), ZLine.ldAbs16(DE, v.toAddress + 2))
|
||||
List(ZLine.ldAbs16(HL, v), ZLine.ldAbs16(DE, v.toAddress + 2, ZLine.elidability(v)))
|
||||
} else if (ctx.options.flag(CompilationFlag.EmitIntel8080Opcodes)) {
|
||||
// The optimizer might spit out an EX DE,HL
|
||||
List(ZLine.ldAbs16(HL, v.toAddress + 2), ZLine.ld8(D,H), ZLine.ld8(E,L),ZLine.ldAbs16(HL, v))
|
||||
List(ZLine.ldAbs16(HL, v.toAddress + 2, ZLine.elidability(v)), ZLine.ld8(D,H), ZLine.ld8(E,L),ZLine.ldAbs16(HL, v))
|
||||
} else {
|
||||
// TODO: is it optimal?
|
||||
List(
|
||||
@ -1102,7 +1102,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
case 1 =>
|
||||
calculateAddressToAppropriatePointer(ctx, l, forWriting = true) match {
|
||||
case Some((LocalVariableAddressViaHL, List(ZLine0(LD_16, TwoRegisters(ZRegister.HL, ZRegister.IMM_16), addr)))) =>
|
||||
Z80Multiply.compileUnsignedByteDivision(ctx, Right(l), r, f.functionName == "%%=") :+ ZLine.ldAbs8(addr, ZRegister.A)
|
||||
Z80Multiply.compileUnsignedByteDivision(ctx, Right(l), r, f.functionName == "%%=") :+ ZLine.ldAbs8(addr, ZRegister.A, Elidability.Elidable)
|
||||
case Some((LocalVariableAddressViaHL, code)) =>
|
||||
code ++ (stashHLIfChanged(ctx, Z80Multiply.compileUnsignedByteDivision(ctx, Left(LocalVariableAddressViaHL), r, f.functionName == "%%=")) :+ ZLine.ld8(ZRegister.MEM_HL, ZRegister.A))
|
||||
case Some((lvo, code)) =>
|
||||
@ -1118,9 +1118,9 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
calculateAddressToAppropriatePointer(ctx, l, forWriting = true) match {
|
||||
case Some((LocalVariableAddressViaHL, List(ZLine0(LD_16, TwoRegisters(ZRegister.HL, ZRegister.IMM_16), addr)))) =>
|
||||
Z80Multiply.compileUnsignedWordDivision(ctx, Right(l), r, modulo = true, rhsWord = false) ++ List(
|
||||
ZLine.ldAbs8(addr, ZRegister.A),
|
||||
ZLine.ldAbs8(addr, ZRegister.A, Elidability.Elidable),
|
||||
ZLine.register(XOR, ZRegister.A),
|
||||
ZLine.ldAbs8(addr+1, ZRegister.A)
|
||||
ZLine.ldAbs8(addr+1, ZRegister.A, Elidability.Elidable)
|
||||
)
|
||||
case Some((lvo@LocalVariableAddressViaHL, code)) =>
|
||||
code ++ stashHLIfChanged(ctx, Z80Multiply.compileUnsignedWordDivision(ctx, Left(lvo), r, modulo = true, rhsWord = false)) ++ List(
|
||||
@ -1448,31 +1448,31 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
List(ZLine.registers(ADD_16, ZRegister.HL, ZRegister.BC))
|
||||
}
|
||||
}
|
||||
case VariablePointy(varAddr, _, _, _) =>
|
||||
case vp@VariablePointy(varAddr, _, _, _, _) =>
|
||||
env.eval(i.index) match {
|
||||
case Some(NumericConstant(0, _)) if extraOffset == 0 =>
|
||||
if (ctx.options.flag(CompilationFlag.EmitIntel8080Opcodes)) {
|
||||
List(ZLine.ldAbs16(ZRegister.HL, varAddr))
|
||||
List(ZLine.ldAbs16(ZRegister.HL, varAddr, vp.elidability))
|
||||
} else {
|
||||
// TODO: is this reasonable?
|
||||
List(
|
||||
ZLine.ldAbs8(ZRegister.A, varAddr),
|
||||
ZLine.ldAbs8(ZRegister.A, varAddr, vp.elidability),
|
||||
ZLine.ld8(ZRegister.L, ZRegister.A),
|
||||
ZLine.ldAbs8(ZRegister.A, varAddr + 1),
|
||||
ZLine.ldAbs8(ZRegister.A, varAddr + 1, vp.elidability),
|
||||
ZLine.ld8(ZRegister.H, ZRegister.A))
|
||||
}
|
||||
case _ =>
|
||||
if (ctx.options.flag(CompilationFlag.EmitIntel8080Opcodes)) {
|
||||
compileToBC(ctx, i.index #*# elementSize #+# extraOffset) ++
|
||||
List(ZLine.ldAbs16(ZRegister.HL, varAddr)) ++
|
||||
List(ZLine.ldAbs16(ZRegister.HL, varAddr, vp.elidability)) ++
|
||||
List.fill(elementSize)(ZLine.registers(ADD_16, ZRegister.HL, ZRegister.BC))
|
||||
} else {
|
||||
// TODO: is this reasonable?
|
||||
compileToBC(ctx, i.index #*# elementSize #+# extraOffset) ++
|
||||
List(
|
||||
ZLine.ldAbs8(ZRegister.A, varAddr),
|
||||
ZLine.ldAbs8(ZRegister.A, varAddr, vp.elidability),
|
||||
ZLine.ld8(ZRegister.L, ZRegister.A),
|
||||
ZLine.ldAbs8(ZRegister.A, varAddr + 1),
|
||||
ZLine.ldAbs8(ZRegister.A, varAddr + 1, vp.elidability),
|
||||
ZLine.ld8(ZRegister.H, ZRegister.A)) ++
|
||||
List.fill(elementSize)(ZLine.registers(ADD_16, ZRegister.HL, ZRegister.BC))
|
||||
}
|
||||
@ -1570,14 +1570,15 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
}
|
||||
}
|
||||
|
||||
def signExtend(ctx: CompilationContext, targetAddr: Constant, hiRegister: ZRegister.Value, bytes: Int, signedSource: Boolean): List[ZLine] = {
|
||||
def signExtend(ctx: CompilationContext, targetAddr: Constant, hiRegister: ZRegister.Value, bytes: Int, signedSource: Boolean, volatile: Boolean): List[ZLine] = {
|
||||
val elidability = if (volatile) Elidability.Volatile else Elidability.Elidable
|
||||
if (bytes <= 0) return Nil
|
||||
val prepareA = if (signedSource) {
|
||||
signExtendHighestByte(ctx, hiRegister)
|
||||
} else {
|
||||
List(ZLine.ldImm8(ZRegister.A, 0))
|
||||
}
|
||||
val fillUpperBytes = List.tabulate(bytes)(i => ZLine.ldAbs8((targetAddr + i).quickSimplify, ZRegister.A))
|
||||
val fillUpperBytes = List.tabulate(bytes)(i => ZLine.ldAbs8((targetAddr + i).quickSimplify, ZRegister.A, elidability))
|
||||
prepareA ++ fillUpperBytes
|
||||
}
|
||||
|
||||
@ -1639,11 +1640,12 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
prepareA ++ fillUpperBytes
|
||||
}
|
||||
|
||||
def storeA(ctx: CompilationContext, targetAddr: Constant, targetSize: Int, signedSource: Boolean): List[ZLine] = {
|
||||
def storeA(ctx: CompilationContext, targetAddr: Constant, targetSize: Int, signedSource: Boolean, volatile: Boolean): List[ZLine] = {
|
||||
val elidability = if (volatile) Elidability.Volatile else Elidability.Elidable
|
||||
targetSize match {
|
||||
case 0 => Nil
|
||||
case 1 => List(ZLine.ldAbs8(targetAddr, ZRegister.A))
|
||||
case n => ZLine.ldAbs8(targetAddr, ZRegister.A) :: signExtend(ctx, targetAddr + 1, ZRegister.A, n - 1, signedSource)
|
||||
case 1 => List(ZLine.ldAbs8(targetAddr, ZRegister.A, elidability))
|
||||
case n => ZLine.ldAbs8(targetAddr, ZRegister.A, elidability) :: signExtend(ctx, targetAddr + 1, ZRegister.A, n - 1, signedSource, volatile)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1671,103 +1673,106 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
}
|
||||
}
|
||||
|
||||
def storeHL(ctx: CompilationContext, targetAddr: Constant, targetSize: Int, signedSource: Boolean): List[ZLine] = {
|
||||
def storeHL(ctx: CompilationContext, targetAddr: Constant, targetSize: Int, signedSource: Boolean, volatile: Boolean): List[ZLine] = {
|
||||
// TODO: LD (nnnn),HL compatibility?
|
||||
val elidability = if (volatile) Elidability.Volatile else Elidability.Elidable
|
||||
targetSize match {
|
||||
case 0 => Nil
|
||||
case 1 => List(ZLine.ld8(ZRegister.A, ZRegister.L), ZLine.ldAbs8(targetAddr, ZRegister.A))
|
||||
case 1 => List(ZLine.ld8(ZRegister.A, ZRegister.L), ZLine.ldAbs8(targetAddr, ZRegister.A, elidability))
|
||||
case n =>
|
||||
if (ctx.options.flag(CompilationFlag.EmitIntel8080Opcodes)){
|
||||
ZLine.ldAbs16(targetAddr, ZRegister.HL) :: signExtend(ctx, targetAddr + 2, ZRegister.H, n - 2, signedSource)
|
||||
ZLine.ldAbs16(targetAddr, ZRegister.HL, elidability) :: signExtend(ctx, targetAddr + 2, ZRegister.H, n - 2, signedSource, volatile)
|
||||
} else {
|
||||
List(
|
||||
ZLine.ld8(ZRegister.A, ZRegister.L),
|
||||
ZLine.ldAbs8(targetAddr, ZRegister.A),
|
||||
ZLine.ldAbs8(targetAddr, ZRegister.A, elidability),
|
||||
ZLine.ld8(ZRegister.A, ZRegister.H),
|
||||
ZLine.ldAbs8(targetAddr + 1, ZRegister.A)) ++ signExtend(ctx, targetAddr + 2, ZRegister.H, n - 2, signedSource)
|
||||
ZLine.ldAbs8(targetAddr + 1, ZRegister.A, elidability)) ++ signExtend(ctx, targetAddr + 2, ZRegister.H, n - 2, signedSource, volatile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def storeEHL(ctx: CompilationContext, targetAddr: Constant, targetSize: Int, signedSource: Boolean): List[ZLine] = {
|
||||
def storeEHL(ctx: CompilationContext, targetAddr: Constant, targetSize: Int, signedSource: Boolean, volatile: Boolean): List[ZLine] = {
|
||||
val elidability = if (volatile) Elidability.Volatile else Elidability.Elidable
|
||||
targetSize match {
|
||||
case 0 => Nil
|
||||
case 1 => List(ZLine.ld8(ZRegister.A, ZRegister.L), ZLine.ldAbs8(targetAddr, ZRegister.A))
|
||||
case 1 => List(ZLine.ld8(ZRegister.A, ZRegister.L), ZLine.ldAbs8(targetAddr, ZRegister.A, elidability))
|
||||
case 2 =>
|
||||
if (ctx.options.flag(CompilationFlag.EmitIntel8080Opcodes)){
|
||||
List(ZLine.ldAbs16(targetAddr, ZRegister.HL))
|
||||
List(ZLine.ldAbs16(targetAddr, ZRegister.HL, elidability))
|
||||
} else {
|
||||
List(
|
||||
ZLine.ld8(ZRegister.A, ZRegister.L),
|
||||
ZLine.ldAbs8(targetAddr, ZRegister.A),
|
||||
ZLine.ldAbs8(targetAddr, ZRegister.A, elidability),
|
||||
ZLine.ld8(ZRegister.A, ZRegister.H),
|
||||
ZLine.ldAbs8(targetAddr + 1, ZRegister.A))
|
||||
ZLine.ldAbs8(targetAddr + 1, ZRegister.A, elidability))
|
||||
}
|
||||
case n =>
|
||||
if (ctx.options.flag(CompilationFlag.EmitIntel8080Opcodes)){
|
||||
List(
|
||||
ZLine.ldAbs16(targetAddr, ZRegister.HL),
|
||||
ZLine.ldAbs16(targetAddr, ZRegister.HL, elidability),
|
||||
ZLine.ld8(ZRegister.A, ZRegister.E),
|
||||
ZLine.ldAbs8(targetAddr + 2, ZRegister.A)) ++ signExtend(ctx, targetAddr + 3, ZRegister.E, n - 3, signedSource)
|
||||
ZLine.ldAbs8(targetAddr + 2, ZRegister.A, elidability)) ++ signExtend(ctx, targetAddr + 3, ZRegister.E, n - 3, signedSource, volatile)
|
||||
} else {
|
||||
List(
|
||||
ZLine.ld8(ZRegister.A, ZRegister.L),
|
||||
ZLine.ldAbs8(targetAddr, ZRegister.A),
|
||||
ZLine.ldAbs8(targetAddr, ZRegister.A, elidability),
|
||||
ZLine.ld8(ZRegister.A, ZRegister.H),
|
||||
ZLine.ldAbs8(targetAddr + 1, ZRegister.A),
|
||||
ZLine.ldAbs8(targetAddr + 1, ZRegister.A, elidability),
|
||||
ZLine.ld8(ZRegister.A, ZRegister.E),
|
||||
ZLine.ldAbs8(targetAddr + 2, ZRegister.A)) ++ signExtend(ctx, targetAddr + 3, ZRegister.E, n - 3, signedSource)
|
||||
ZLine.ldAbs8(targetAddr + 2, ZRegister.A, elidability)) ++ signExtend(ctx, targetAddr + 3, ZRegister.E, n - 3, signedSource, volatile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def storeDEHL(ctx: CompilationContext, targetAddr: Constant, targetSize: Int, signedSource: Boolean): List[ZLine] = {
|
||||
def storeDEHL(ctx: CompilationContext, targetAddr: Constant, targetSize: Int, signedSource: Boolean, volatile: Boolean): List[ZLine] = {
|
||||
val elidability = if (volatile) Elidability.Volatile else Elidability.Elidable
|
||||
targetSize match {
|
||||
case 0 => Nil
|
||||
case 1 => List(ZLine.ld8(ZRegister.A, ZRegister.L), ZLine.ldAbs8(targetAddr, ZRegister.A))
|
||||
case 1 => List(ZLine.ld8(ZRegister.A, ZRegister.L), ZLine.ldAbs8(targetAddr, ZRegister.A, elidability))
|
||||
case 2 =>
|
||||
if (ctx.options.flag(CompilationFlag.EmitIntel8080Opcodes)){
|
||||
List(ZLine.ldAbs16(targetAddr, ZRegister.HL))
|
||||
List(ZLine.ldAbs16(targetAddr, ZRegister.HL, elidability))
|
||||
} else {
|
||||
List(
|
||||
ZLine.ld8(ZRegister.A, ZRegister.L),
|
||||
ZLine.ldAbs8(targetAddr, ZRegister.A),
|
||||
ZLine.ldAbs8(targetAddr, ZRegister.A, elidability),
|
||||
ZLine.ld8(ZRegister.A, ZRegister.H),
|
||||
ZLine.ldAbs8(targetAddr + 1, ZRegister.A))
|
||||
ZLine.ldAbs8(targetAddr + 1, ZRegister.A, elidability))
|
||||
}
|
||||
case 3 =>
|
||||
if (ctx.options.flag(CompilationFlag.EmitIntel8080Opcodes)) {
|
||||
List(
|
||||
ZLine.ldAbs16(targetAddr, ZRegister.HL),
|
||||
ZLine.ldAbs16(targetAddr, ZRegister.HL, elidability),
|
||||
ZLine.ld8(ZRegister.A, ZRegister.E),
|
||||
ZLine.ldAbs8(targetAddr + 2, ZRegister.A))
|
||||
ZLine.ldAbs8(targetAddr + 2, ZRegister.A, elidability))
|
||||
} else {
|
||||
List(
|
||||
ZLine.ld8(ZRegister.A, ZRegister.L),
|
||||
ZLine.ldAbs8(targetAddr, ZRegister.A),
|
||||
ZLine.ldAbs8(targetAddr, ZRegister.A, elidability),
|
||||
ZLine.ld8(ZRegister.A, ZRegister.H),
|
||||
ZLine.ldAbs8(targetAddr + 1, ZRegister.A),
|
||||
ZLine.ldAbs8(targetAddr + 1, ZRegister.A, elidability),
|
||||
ZLine.ld8(ZRegister.A, ZRegister.E),
|
||||
ZLine.ldAbs8(targetAddr + 2, ZRegister.A))
|
||||
ZLine.ldAbs8(targetAddr + 2, ZRegister.A, elidability))
|
||||
}
|
||||
case n =>
|
||||
if (ctx.options.flag(CompilationFlag.EmitIntel8080Opcodes)){
|
||||
List(
|
||||
ZLine.ldAbs16(targetAddr, ZRegister.HL),
|
||||
ZLine.ldAbs16(targetAddr, ZRegister.HL, elidability),
|
||||
ZLine.ld8(ZRegister.A, ZRegister.E),
|
||||
ZLine.ldAbs8(targetAddr + 2, ZRegister.A),
|
||||
ZLine.ldAbs8(targetAddr + 2, ZRegister.A, elidability),
|
||||
ZLine.ld8(ZRegister.A, ZRegister.D),
|
||||
ZLine.ldAbs8(targetAddr + 3, ZRegister.A)) ++ signExtend(ctx, targetAddr + 4, ZRegister.D, n - 4, signedSource)
|
||||
ZLine.ldAbs8(targetAddr + 3, ZRegister.A, elidability)) ++ signExtend(ctx, targetAddr + 4, ZRegister.D, n - 4, signedSource, volatile)
|
||||
} else {
|
||||
List(
|
||||
ZLine.ld8(ZRegister.A, ZRegister.L),
|
||||
ZLine.ldAbs8(targetAddr, ZRegister.A),
|
||||
ZLine.ldAbs8(targetAddr, ZRegister.A, elidability),
|
||||
ZLine.ld8(ZRegister.A, ZRegister.H),
|
||||
ZLine.ldAbs8(targetAddr + 1, ZRegister.A),
|
||||
ZLine.ldAbs8(targetAddr + 1, ZRegister.A, elidability),
|
||||
ZLine.ld8(ZRegister.A, ZRegister.E),
|
||||
ZLine.ldAbs8(targetAddr + 2, ZRegister.A),
|
||||
ZLine.ldAbs8(targetAddr + 2, ZRegister.A, elidability),
|
||||
ZLine.ld8(ZRegister.A, ZRegister.D),
|
||||
ZLine.ldAbs8(targetAddr + 3, ZRegister.A)) ++ signExtend(ctx, targetAddr + 4, ZRegister.D, n - 4, signedSource)
|
||||
ZLine.ldAbs8(targetAddr + 3, ZRegister.A, elidability)) ++ signExtend(ctx, targetAddr + 4, ZRegister.D, n - 4, signedSource, volatile)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1837,7 +1842,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
target match {
|
||||
case VariableExpression(vname) =>
|
||||
env.get[Variable](vname) match {
|
||||
case v: VariableInMemory => storeA(ctx, v.toAddress, v.typ.size, signedSource)
|
||||
case v: VariableInMemory => storeA(ctx, v.toAddress, v.typ.size, signedSource, v.isVolatile)
|
||||
case v: StackVariable =>
|
||||
if (ctx.options.flag(CompilationFlag.UseIxForStack)){
|
||||
storeAViaIX(ctx, v.baseOffset, v.typ.size, signedSource)
|
||||
@ -1849,7 +1854,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
}
|
||||
case i:IndexedExpression =>
|
||||
calculateAddressToHL(ctx, i, forWriting = true) match {
|
||||
case List(ZLine0(LD_16, TwoRegisters(ZRegister.HL, ZRegister.IMM_16), addr)) => storeA(ctx, addr, 1, signedSource)
|
||||
case List(ZLine0(LD_16, TwoRegisters(ZRegister.HL, ZRegister.IMM_16), addr)) => storeA(ctx, addr, 1, signedSource, volatile = false)
|
||||
case code => if (code.exists(changesA)) {
|
||||
List(ZLine.ld8(ZRegister.E, ZRegister.A)) ++ stashDEIfChanged(ctx, code) :+ ZLine.ld8(ZRegister.MEM_HL, ZRegister.E)
|
||||
} else code :+ ZLine.ld8(ZRegister.MEM_HL, ZRegister.A)
|
||||
@ -1888,7 +1893,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
target match {
|
||||
case VariableExpression(vname) =>
|
||||
env.get[Variable](vname) match {
|
||||
case v: VariableInMemory => storeHL(ctx, v.toAddress, v.typ.size, signedSource)
|
||||
case v: VariableInMemory => storeHL(ctx, v.toAddress, v.typ.size, signedSource, v.isVolatile)
|
||||
case v: StackVariable =>
|
||||
if (ctx.options.flag(CompilationFlag.UseIxForStack)){
|
||||
storeHLViaIX(ctx, v.baseOffset, v.typ.size, signedSource)
|
||||
@ -1935,7 +1940,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
env.getPointy(pointyName) match {
|
||||
case p: ConstantPointy =>
|
||||
env.evalVariableAndConstantSubParts(indexExpr) match {
|
||||
case (None, offset) => ZLine.ld8(ZRegister.A, ZRegister.L) :: storeA(ctx, (p.value + offset).quickSimplify, 1, signedSource)
|
||||
case (None, offset) => ZLine.ld8(ZRegister.A, ZRegister.L) :: storeA(ctx, (p.value + offset).quickSimplify, 1, signedSource, volatile = false)
|
||||
}
|
||||
case _ => ctx.log.fatal("Whee!") // the statement preprocessor should have removed all of those
|
||||
}
|
||||
@ -1983,7 +1988,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
val preparePointer = target match {
|
||||
case VariableExpression(vname) =>
|
||||
env.get[Variable](vname) match {
|
||||
case v: VariableInMemory => return storeEHL(ctx, v.toAddress, v.typ.size, signedSource)
|
||||
case v: VariableInMemory => return storeEHL(ctx, v.toAddress, v.typ.size, signedSource, v.isVolatile)
|
||||
case v: StackVariable =>
|
||||
if (ctx.options.flag(CompilationFlag.UseIxForStack)){
|
||||
return storeEHLViaIX(ctx, v.baseOffset, v.typ.size, signedSource)
|
||||
@ -2015,7 +2020,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
val preparePointer = target match {
|
||||
case VariableExpression(vname) =>
|
||||
env.get[Variable](vname) match {
|
||||
case v: VariableInMemory => return storeDEHL(ctx, v.toAddress, v.typ.size, signedSource)
|
||||
case v: VariableInMemory => return storeDEHL(ctx, v.toAddress, v.typ.size, signedSource, v.isVolatile)
|
||||
case v: StackVariable =>
|
||||
if (ctx.options.flag(CompilationFlag.UseIxForStack)){
|
||||
return storeDEHLViaIX(ctx, v.baseOffset, v.typ.size, signedSource)
|
||||
@ -2166,9 +2171,9 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
case v: VariableInMemory =>
|
||||
List.tabulate(size) { i =>
|
||||
if (i < v.typ.size) {
|
||||
List(ZLine.ldAbs8(ZRegister.A, v.toAddress + i))
|
||||
List(ZLine.ldAbs8(ZRegister.A, v.toAddress + i, ZLine.elidability(v)))
|
||||
} else if (v.typ.isSigned) {
|
||||
ZLine.ldAbs8(ZRegister.A, v.toAddress + v.typ.size - 1) :: signExtendHighestByte(ctx, ZRegister.A)
|
||||
ZLine.ldAbs8(ZRegister.A, v.toAddress + v.typ.size - 1, Elidability.Elidable) :: signExtendHighestByte(ctx, ZRegister.A)
|
||||
} else {
|
||||
List(ZLine.ldImm8(ZRegister.A, 0))
|
||||
}
|
||||
@ -2279,7 +2284,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
val result = env.get[VariableInMemory](function.name + ".return")
|
||||
List.tabulate(size) {
|
||||
case 0 => compile(ctx, rhs, ZExpressionTarget.NOTHING, BranchSpec.None) :+ ZLine.ldAbs8(ZRegister.A, result)
|
||||
case i if i < typ.size => List(ZLine.ldAbs8(ZRegister.A, result.toAddress + i))
|
||||
case i if i < typ.size => List(ZLine.ldAbs8(ZRegister.A, result.toAddress + i, Elidability.Elidable))
|
||||
case _ => List(ZLine.ldImm8(ZRegister.A, 0)) // TODO: signed large types?
|
||||
}
|
||||
}
|
||||
@ -2316,7 +2321,7 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
}
|
||||
List.tabulate(size) { i =>
|
||||
if (i < size) {
|
||||
List(ZLine.ldAbs8(v.toAddress + i, ZRegister.A))
|
||||
List(ZLine.ldAbs8(v.toAddress + i, ZRegister.A, ZLine.elidability(v)))
|
||||
} else {
|
||||
Nil
|
||||
}
|
||||
|
@ -397,7 +397,7 @@ class Environment(val parent: Option[Environment], val prefix: String, val cpuFa
|
||||
case th:VariableInMemory if th.typ.isPointy=>
|
||||
val e = get[VariableType](th.typ.pointerTargetName)
|
||||
val w = get[VariableType]("word")
|
||||
VariablePointy(th.toAddress, w, e, th.zeropage)
|
||||
VariablePointy(th.toAddress, w, e, th.zeropage, th.isVolatile)
|
||||
case th:StackVariable if th.typ.isPointy =>
|
||||
val e = get[VariableType](th.typ.pointerTargetName)
|
||||
val w = get[VariableType]("word")
|
||||
|
4
src/main/scala/millfork/env/Pointy.scala
vendored
4
src/main/scala/millfork/env/Pointy.scala
vendored
@ -1,5 +1,6 @@
|
||||
package millfork.env
|
||||
|
||||
import millfork.assembly.Elidability
|
||||
import millfork.output.MemoryAlignment
|
||||
|
||||
trait Pointy {
|
||||
@ -16,10 +17,11 @@ case class StackVariablePointy(offset: Int, indexType: VariableType, elementType
|
||||
override def isArray: Boolean = false
|
||||
}
|
||||
|
||||
case class VariablePointy(addr: Constant, indexType: VariableType, elementType: VariableType, zeropage: Boolean) extends Pointy {
|
||||
case class VariablePointy(addr: Constant, indexType: VariableType, elementType: VariableType, zeropage: Boolean, volatile: Boolean) extends Pointy {
|
||||
override def name: Option[String] = None
|
||||
override def readOnly: Boolean = false
|
||||
override def isArray: Boolean = false
|
||||
def elidability: Elidability.Value = if (volatile) Elidability.Volatile else Elidability.Elidable
|
||||
}
|
||||
|
||||
case class ConstantPointy(value: Constant,
|
||||
|
@ -37,8 +37,8 @@ class ZLineSizeSuite extends FunSuite with Matchers {
|
||||
runCase(ZLine.ldViaIx(0, A))
|
||||
runCase(ZLine.ld8(B, C))
|
||||
runCase(ZLine.ldImm8(B, 9))
|
||||
runCase(ZLine.ldAbs8(A, Zero))
|
||||
runCase(ZLine.ldAbs16(HL, Zero))
|
||||
runCase(ZLine.ldAbs8(A, Zero, elidability = Elidability.Elidable))
|
||||
runCase(ZLine.ldAbs16(HL, Zero, elidability = Elidability.Elidable))
|
||||
runCase(ZLine.ldImm16(HL, Zero))
|
||||
runCase(ZLine.register(SLA, E))
|
||||
runCase(ZLine.register(BIT0, E))
|
||||
|
Loading…
Reference in New Issue
Block a user