mirror of
https://github.com/KarolS/millfork.git
synced 2026-04-19 10:42:10 +00:00
Z80: Compile 8-bit values directly into registers other than A
This commit is contained in:
@@ -126,8 +126,15 @@ Non-macro functions can only have their parameters passed via registers:
|
||||
* `word hl`, `word bc`, `word de`: a 2-byte word byte passed via given 16-bit register
|
||||
|
||||
**Work in progress**:
|
||||
Currently, only 3 parameter signatures are supported for non-macro assembly functions:
|
||||
`()`, `(byte a)` and `(word hl)`. More parameters or parameters passed via other registers do not work yet.
|
||||
Currently, only few parameter signatures are supported for non-macro assembly functions:
|
||||
|
||||
* `()`
|
||||
|
||||
* `(byte a)`, `(byte b)`, `(byte c)`, `(byte d)`, `(byte e)`, `(byte h)`, `(byte l)` ("byte" may be any other 2-byte type)
|
||||
|
||||
* `(word hl)`, `(word bc)`, `(word de)` ("word" may be any other 2-byte type)
|
||||
|
||||
More parameters or parameters passed via other registers do not work yet.
|
||||
|
||||
Macro assembly functions cannot have any parameter passed via registers.
|
||||
|
||||
|
||||
@@ -159,11 +159,11 @@ object Z80BulkMemoryOperations {
|
||||
val loopRegister = if (useC) ZRegister.C else ZRegister.B
|
||||
val countDown = f.direction == ForDirection.ParallelTo || f.direction == ForDirection.ParallelUntil || f.direction == ForDirection.DownTo
|
||||
val countDownDespiteSyntax = f.direction == ForDirection.ParallelTo || f.direction == ForDirection.ParallelUntil
|
||||
val initC = if (useC) Z80ExpressionCompiler.compileToA(ctx, f.direction match {
|
||||
val initC = if (useC) Z80ExpressionCompiler.compile8BitTo(ctx, f.direction match {
|
||||
case ForDirection.ParallelTo => f.end
|
||||
case ForDirection.ParallelUntil => SumExpression(List(false -> f.end, true -> LiteralExpression(1, 1)), decimal = false)
|
||||
case _ => f.start
|
||||
}) :+ ZLine.ld8(ZRegister.C, ZRegister.A) else Nil
|
||||
}, ZRegister.C) else Nil
|
||||
val nextC = if (useC) List(ZLine.register(if (countDown) DEC else INC, ZRegister.C)) else Nil
|
||||
ExtraLoopRegister(loopRegister, initC, nextC, countDownDespiteSyntax)
|
||||
}
|
||||
@@ -369,8 +369,7 @@ object Z80BulkMemoryOperations {
|
||||
val ldr = z80Bulk(decreasing)
|
||||
val smallCount = indexVariableSize == 1 && (ldr.isEmpty || !ctx.options.flag(CompilationFlag.EmitZ80Opcodes))
|
||||
val calculateByteCount = if (smallCount) {
|
||||
Z80ExpressionCompiler.compileToA(ctx, byteCountExpression) ++
|
||||
List(ZLine.ld8(ZRegister.B, ZRegister.A))
|
||||
Z80ExpressionCompiler.compile8BitTo(ctx, byteCountExpression, ZRegister.B)
|
||||
} else {
|
||||
Z80ExpressionCompiler.compileToHL(ctx, byteCountExpression) ++
|
||||
List(ZLine.ld8(ZRegister.B, ZRegister.H), ZLine.ld8(ZRegister.C, ZRegister.L))
|
||||
|
||||
@@ -19,6 +19,26 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
|
||||
def compileToA(ctx: CompilationContext, expression: Expression): List[ZLine] = compile(ctx, expression, ZExpressionTarget.A)
|
||||
|
||||
def compile8BitTo(ctx: CompilationContext, expression: Expression, register: ZRegister.Value): List[ZLine] = {
|
||||
if (ZRegister.A == register) compileToA(ctx, expression) else {
|
||||
val toA = compileToA(ctx, expression)
|
||||
if (toA.isEmpty) Nil else {
|
||||
toA.last match {
|
||||
case ZLine(ZOpcode.LD, TwoRegisters(ZRegister.A, source), _, _) if source == register =>
|
||||
toA.init
|
||||
case ZLine(ZOpcode.LD, TwoRegisters(ZRegister.A, source@(ZRegister.B | ZRegister.C | ZRegister.D | ZRegister.E | ZRegister.MEM_HL)), _, _) =>
|
||||
toA.init :+ ZLine.ld8(register, source)
|
||||
case ZLine(ZOpcode.LD, TwoRegistersOffset(ZRegister.A, ZRegister.MEM_IX_D, offset), _, _) =>
|
||||
toA.init :+ ZLine.ldViaIx(register, offset)
|
||||
case ZLine(ZOpcode.LD, TwoRegistersOffset(ZRegister.A, ZRegister.MEM_IY_D, offset), _, _) =>
|
||||
toA.init :+ ZLine.ldViaIy(register, offset)
|
||||
case _ =>
|
||||
toA :+ ZLine.ld8(register, ZRegister.A)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def compileToHL(ctx: CompilationContext, expression: Expression): List[ZLine] = compile(ctx, expression, ZExpressionTarget.HL)
|
||||
|
||||
def compileToEHL(ctx: CompilationContext, expression: Expression): List[ZLine] = compile(ctx, expression, ZExpressionTarget.EHL)
|
||||
@@ -786,9 +806,20 @@ object Z80ExpressionCompiler extends AbstractExpressionCompiler[ZLine] {
|
||||
case AssemblyParamSignature(List(AssemblyParam(typ1, ZRegisterVariable(ZRegister.A, typ2), AssemblyParameterPassingBehaviour.Copy)))
|
||||
if typ1.size == 1 && typ2.size == 1 =>
|
||||
compileToA(ctx, params.head) :+ ZLine(CALL, NoRegisters, function.toAddress)
|
||||
case AssemblyParamSignature(List(AssemblyParam(typ1, ZRegisterVariable(
|
||||
register@(ZRegister.B | ZRegister.C | ZRegister.D | ZRegister.E | ZRegister.H | ZRegister.L),
|
||||
typ2), AssemblyParameterPassingBehaviour.Copy)))
|
||||
if typ1.size == 1 && typ2.size == 1 =>
|
||||
compile8BitTo(ctx, params.head, register) :+ ZLine(CALL, NoRegisters, function.toAddress)
|
||||
case AssemblyParamSignature(List(AssemblyParam(typ1, ZRegisterVariable(ZRegister.HL, typ2), AssemblyParameterPassingBehaviour.Copy)))
|
||||
if typ1.size == 2 && typ2.size == 2 =>
|
||||
compileToHL(ctx, params.head) :+ ZLine(CALL, NoRegisters, function.toAddress)
|
||||
case AssemblyParamSignature(List(AssemblyParam(typ1, ZRegisterVariable(ZRegister.DE, typ2), AssemblyParameterPassingBehaviour.Copy)))
|
||||
if typ1.size == 2 && typ2.size == 2 =>
|
||||
compileToDE(ctx, params.head) :+ ZLine(CALL, NoRegisters, function.toAddress)
|
||||
case AssemblyParamSignature(List(AssemblyParam(typ1, ZRegisterVariable(ZRegister.BC, typ2), AssemblyParameterPassingBehaviour.Copy)))
|
||||
if typ1.size == 2 && typ2.size == 2 =>
|
||||
compileToBC(ctx, params.head) :+ ZLine(CALL, NoRegisters, function.toAddress)
|
||||
case AssemblyParamSignature(Nil) =>
|
||||
List(ZLine(CALL, NoRegisters, function.toAddress))
|
||||
case AssemblyParamSignature(paramConvs) =>
|
||||
|
||||
@@ -48,7 +48,8 @@ object Z80MacroExpander extends MacroExpander[ZLine] {
|
||||
hadRegisterParam = true
|
||||
paramPreparation = (register, typ.size) match {
|
||||
case (ZRegister.A, 1) => Z80ExpressionCompiler.compileToA(ctx, actualParam)
|
||||
case (r@(ZRegister.B | ZRegister.C | ZRegister.D | ZRegister.E | ZRegister.H | ZRegister.L), 1) => Z80ExpressionCompiler.compileToA(ctx, actualParam) :+ ZLine.ld8(r, ZRegister.A)
|
||||
case (r@(ZRegister.B | ZRegister.C | ZRegister.D | ZRegister.E | ZRegister.H | ZRegister.L), 1) =>
|
||||
Z80ExpressionCompiler.compile8BitTo(ctx, actualParam, r)
|
||||
case (ZRegister.HL, 2) => Z80ExpressionCompiler.compileToHL(ctx, actualParam)
|
||||
case (ZRegister.BC, 2) => Z80ExpressionCompiler.compileToBC(ctx, actualParam)
|
||||
case (ZRegister.DE, 2) => Z80ExpressionCompiler.compileToDE(ctx, actualParam)
|
||||
|
||||
@@ -41,7 +41,7 @@ object Z80Shifting {
|
||||
l ++ List.tabulate(i.toInt)(_ => op) ++ fixAfterShiftIfNeeded(extendedOps, left, i)
|
||||
}
|
||||
case _ =>
|
||||
val calcCount = Z80ExpressionCompiler.compileToA(ctx, rhs) :+ ZLine.ld8(ZRegister.B, ZRegister.A)
|
||||
val calcCount = Z80ExpressionCompiler.compile8BitTo(ctx, rhs, ZRegister.B)
|
||||
val l = Z80ExpressionCompiler.stashBCIfChanged(ctx, Z80ExpressionCompiler.compileToA(ctx, lhs))
|
||||
val loopBody = op :: fixAfterShiftIfNeeded(extendedOps, left, 1)
|
||||
val label = Z80Compiler.nextLabel("sh")
|
||||
@@ -117,7 +117,7 @@ object Z80Shifting {
|
||||
}
|
||||
}
|
||||
case _ =>
|
||||
val calcCount = Z80ExpressionCompiler.compileToA(ctx, rhs) :+ ZLine.ld8(ZRegister.B, ZRegister.A)
|
||||
val calcCount = Z80ExpressionCompiler.compile8BitTo(ctx, rhs, ZRegister.B)
|
||||
val l = Z80ExpressionCompiler.stashBCIfChanged(ctx, Z80ExpressionCompiler.compileToA(ctx, lhs))
|
||||
val loopBody = ZLine.register(op, ZRegister.A) :: fixAfterShiftIfNeeded(extendedOps, left, 1)
|
||||
val label = Z80Compiler.nextLabel("sh")
|
||||
@@ -168,7 +168,7 @@ object Z80Shifting {
|
||||
}
|
||||
}
|
||||
case _ =>
|
||||
val calcCount = Z80ExpressionCompiler.compileToA(ctx, rhs) :+ ZLine.ld8(ZRegister.B, ZRegister.A)
|
||||
val calcCount = Z80ExpressionCompiler.compile8BitTo(ctx, rhs, ZRegister.B)
|
||||
val loopBody =
|
||||
if (extendedOps) {
|
||||
if (left) {
|
||||
@@ -271,7 +271,7 @@ object Z80Shifting {
|
||||
List.fill(n.toInt)(shiftOne).flatten
|
||||
case _ =>
|
||||
val label = Z80Compiler.nextLabel("sh")
|
||||
val calcCount = Z80ExpressionCompiler.compileToA(ctx, rhs) :+ ZLine.ld8(ZRegister.B, ZRegister.A)
|
||||
val calcCount = Z80ExpressionCompiler.compile8BitTo(ctx, rhs, ZRegister.B)
|
||||
calcCount ++ List(ZLine.label(label)) ++ shiftOne ++ ZLine.djnz(ctx, label)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user