1
0
mirror of https://github.com/KarolS/millfork.git synced 2024-07-14 07:28:54 +00:00

6502: Better passing of register parameters

This commit is contained in:
Karol Stasiak 2019-01-04 12:59:43 +01:00
parent 25ca2cd6b8
commit 19c0668002

View File

@ -426,6 +426,15 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
case 2 => case 2 =>
AssemblyLine.variable(ctx, LDX, source) ++ AssemblyLine.variable(ctx,LDA, source, 1) AssemblyLine.variable(ctx, LDX, source) ++ AssemblyLine.variable(ctx,LDA, source, 1)
} }
case RegisterVariable(MosRegister.XY, _) =>
exprType.size match {
case 1 => if (exprType.isSigned) {
AssemblyLine.variable(ctx, LDX, source) ++ List(AssemblyLine.implied(TXA)) ++ signExtendA(ctx) ++ List(AssemblyLine.implied(TAY))
} else
AssemblyLine.variable(ctx, LDX, source) :+ AssemblyLine.immediate(LDY, 0)
case 2 =>
AssemblyLine.variable(ctx, LDX, source) ++ AssemblyLine.variable(ctx, LDY, source, 1)
}
case RegisterVariable(MosRegister.YA, _) => case RegisterVariable(MosRegister.YA, _) =>
exprType.size match { exprType.size match {
case 1 => if (exprType.isSigned) { case 1 => if (exprType.isSigned) {
@ -435,6 +444,15 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
case 2 => case 2 =>
AssemblyLine.variable(ctx, LDY, source) ++ AssemblyLine.variable(ctx, LDA, source, 1) AssemblyLine.variable(ctx, LDY, source) ++ AssemblyLine.variable(ctx, LDA, source, 1)
} }
case RegisterVariable(MosRegister.YX, _) =>
exprType.size match {
case 1 => if (exprType.isSigned) {
AssemblyLine.variable(ctx, LDY, source) ++ List(AssemblyLine.implied(TYA)) ++ signExtendA(ctx) ++ List(AssemblyLine.implied(TAX))
} else
AssemblyLine.variable(ctx, LDY, source) :+ AssemblyLine.immediate(LDX, 0)
case 2 =>
AssemblyLine.variable(ctx, LDY, source) ++ AssemblyLine.variable(ctx, LDX, source, 1)
}
case target: VariableInMemory => case target: VariableInMemory =>
if (exprType.size > target.typ.size) { if (exprType.size > target.typ.size) {
ctx.log.error(s"Variable `$target.name` is too small", expr.position) ctx.log.error(s"Variable `$target.name` is too small", expr.position)
@ -497,8 +515,11 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
case RegisterVariable(MosRegister.AY, _) => case RegisterVariable(MosRegister.AY, _) =>
AssemblyLine.tsx(ctx) ++ (exprType.size match { AssemblyLine.tsx(ctx) ++ (exprType.size match {
case 1 => if (exprType.isSigned) { case 1 => if (exprType.isSigned) {
val label = ctx.nextLabel("sx") List(
??? // TODO AssemblyLine.dataStackX(ctx, LDA, offset),
AssemblyLine.implied(PHA)) ++
signExtendA(ctx) ++
List(AssemblyLine.implied(PLA))
} else { } else {
List( List(
AssemblyLine.dataStackX(ctx, LDA, offset), AssemblyLine.dataStackX(ctx, LDA, offset),
@ -509,12 +530,30 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
AssemblyLine.dataStackX(ctx, LDY, offset + 1)) AssemblyLine.dataStackX(ctx, LDY, offset + 1))
}) })
case RegisterVariable(MosRegister.XA, _) => case RegisterVariable(MosRegister.XA, _) =>
??? // TODO AssemblyLine.tsx(ctx) ++ (exprType.size match {
case 1 => if (exprType.isSigned) {
List(
AssemblyLine.dataStackX(ctx, LDA, offset),
AssemblyLine.implied(TAX)) ++
signExtendA(ctx)
} else {
List(
AssemblyLine.dataStackX(ctx, LDA, offset),
AssemblyLine.implied(TAX),
AssemblyLine.immediate(LDA, 0))
}
case 2 => List(
AssemblyLine.dataStackX(ctx, LDA, offset),
AssemblyLine.dataStackX(ctx, LDY, offset + 1),
AssemblyLine.implied(TAX),
AssemblyLine.implied(TYA))
})
case RegisterVariable(MosRegister.YA, _) => case RegisterVariable(MosRegister.YA, _) =>
AssemblyLine.tsx(ctx) ++ (exprType.size match { AssemblyLine.tsx(ctx) ++ (exprType.size match {
case 1 => if (exprType.isSigned) { case 1 => if (exprType.isSigned) {
val label = ctx.nextLabel("sx") List(
??? // TODO AssemblyLine.dataStackX(ctx, LDA, offset),
AssemblyLine.implied(TAY)) ++ signExtendA(ctx)
} else { } else {
List( List(
AssemblyLine.dataStackX(ctx, LDY, offset), AssemblyLine.dataStackX(ctx, LDY, offset),
@ -524,6 +563,43 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
AssemblyLine.dataStackX(ctx, LDY, offset), AssemblyLine.dataStackX(ctx, LDY, offset),
AssemblyLine.dataStackX(ctx, LDA, offset + 1)) AssemblyLine.dataStackX(ctx, LDA, offset + 1))
}) })
case RegisterVariable(MosRegister.YX, _) =>
AssemblyLine.tsx(ctx) ++ (exprType.size match {
case 1 => if (exprType.isSigned) {
List(
AssemblyLine.dataStackX(ctx, LDA, offset),
AssemblyLine.implied(TAY)) ++
signExtendA(ctx) ++
List(AssemblyLine.implied(TAX))
} else {
List(
AssemblyLine.dataStackX(ctx, LDY, offset),
AssemblyLine.immediate(LDX, 0))
}
case 2 => List(
AssemblyLine.dataStackX(ctx, LDY, offset),
AssemblyLine.dataStackX(ctx, LDA, offset + 1),
AssemblyLine.implied(TAX))
})
case RegisterVariable(MosRegister.XY, _) =>
AssemblyLine.tsx(ctx) ++ (exprType.size match {
case 1 => if (exprType.isSigned) {
List(
AssemblyLine.dataStackX(ctx, LDA, offset),
AssemblyLine.implied(TAX)) ++
signExtendA(ctx) ++
List(AssemblyLine.implied(TAY))
} else {
List(
AssemblyLine.dataStackX(ctx, LDA, offset),
AssemblyLine.implied(TAX),
AssemblyLine.immediate(LDY, 0))
}
case 2 => List(
AssemblyLine.dataStackX(ctx, LDA, offset),
AssemblyLine.dataStackX(ctx, LDY, offset + 1),
AssemblyLine.implied(TAX))
})
case target: VariableInMemory => case target: VariableInMemory =>
if (exprType.size > target.typ.size) { if (exprType.size > target.typ.size) {
ctx.log.error(s"Variable `$target.name` is too small", expr.position) ctx.log.error(s"Variable `$target.name` is too small", expr.position)
@ -714,11 +790,17 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
compile(ctx, l, Some(b -> RegisterVariable(MosRegister.A, b)), branches) ++ compile(ctx, l, Some(b -> RegisterVariable(MosRegister.A, b)), branches) ++
preserveRegisterIfNeeded(ctx, MosRegister.A, compile(ctx, h, Some(b -> RegisterVariable(MosRegister.Y, b)), branches)) preserveRegisterIfNeeded(ctx, MosRegister.A, compile(ctx, h, Some(b -> RegisterVariable(MosRegister.Y, b)), branches))
case RegisterVariable(MosRegister.XA, _) => case RegisterVariable(MosRegister.XA, _) =>
compile(ctx, l, Some(b -> RegisterVariable(MosRegister.X, b)), branches) ++ compile(ctx, h, Some(b -> RegisterVariable(MosRegister.A, b)), branches) ++
compile(ctx, h, Some(b -> RegisterVariable(MosRegister.A, b)), branches) preserveRegisterIfNeeded(ctx, MosRegister.A, compile(ctx, l, Some(b -> RegisterVariable(MosRegister.X, b)), branches))
case RegisterVariable(MosRegister.YA, _) => case RegisterVariable(MosRegister.YA, _) =>
compile(ctx, h, Some(b -> RegisterVariable(MosRegister.A, b)), branches) ++
preserveRegisterIfNeeded(ctx, MosRegister.A, compile(ctx, l, Some(b -> RegisterVariable(MosRegister.Y, b)), branches))
case RegisterVariable(MosRegister.XY, _) =>
compile(ctx, l, Some(b -> RegisterVariable(MosRegister.X, b)), branches) ++
preserveRegisterIfNeeded(ctx, MosRegister.X, compile(ctx, h, Some(b -> RegisterVariable(MosRegister.Y, b)), branches))
case RegisterVariable(MosRegister.YX, _) =>
compile(ctx, l, Some(b -> RegisterVariable(MosRegister.Y, b)), branches) ++ compile(ctx, l, Some(b -> RegisterVariable(MosRegister.Y, b)), branches) ++
compile(ctx, h, Some(b -> RegisterVariable(MosRegister.A, b)), branches) preserveRegisterIfNeeded(ctx, MosRegister.Y, compile(ctx, h, Some(b -> RegisterVariable(MosRegister.X, b)), branches))
case target: VariableInMemory => case target: VariableInMemory =>
target.typ.size match { target.typ.size match {
case 1 => case 1 =>
@ -1172,10 +1254,14 @@ object MosExpressionCompiler extends AbstractExpressionCompiler[AssemblyLine] {
} }
val thirdViaRegisters = pairs.flatMap { val thirdViaRegisters = pairs.flatMap {
case (paramExpr, AssemblyParam(typ, paramVar@RegisterVariable(register, _), AssemblyParameterPassingBehaviour.Copy)) => case (paramExpr, AssemblyParam(typ, paramVar@RegisterVariable(register, _), AssemblyParameterPassingBehaviour.Copy)) =>
compile(ctx, paramExpr, Some(typ -> paramVar), NoBranching) Some(register -> compile(ctx, paramExpr, Some(typ -> paramVar), NoBranching))
// TODO: fix
case _ => Nil case _ => Nil
} match {
case Seq() => Nil
case Seq((_, param)) => param
case Seq((MosRegister.A, pa), (_, pxy)) => pa ++ preserveRegisterIfNeeded(ctx, MosRegister.A, pxy)
case Seq((_, pxy), (MosRegister.A, pa)) => pa ++ preserveRegisterIfNeeded(ctx, MosRegister.A, pxy)
case other => other.flatMap(_._2) // TODO : make sure all registers are passed in correctly
} }
secondViaMemory ++ thirdViaRegisters :+ AssemblyLine.absoluteOrLongAbsolute(JSR, function, ctx.options) secondViaMemory ++ thirdViaRegisters :+ AssemblyLine.absoluteOrLongAbsolute(JSR, function, ctx.options)
case NormalParamSignature(List(MemoryVariable(_, typ, _))) if typ.size == 1 => case NormalParamSignature(List(MemoryVariable(_, typ, _))) if typ.size == 1 =>