mirror of
https://github.com/irmen/prog8.git
synced 2024-10-01 22:56:10 +00:00
improve register arg passing again
This commit is contained in:
parent
90c4a26d52
commit
137d506e42
@ -65,44 +65,77 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
|
|||||||
// this is called when one or more of the arguments are 'complex' and
|
// this is called when one or more of the arguments are 'complex' and
|
||||||
// cannot be assigned to a register easily or risk clobbering other registers.
|
// cannot be assigned to a register easily or risk clobbering other registers.
|
||||||
|
|
||||||
// make sure the X register is loaded last so we can "safely" destroy the estack pointer
|
if(sub.parameters.isEmpty())
|
||||||
val argsOrig = stmt.args.zip(sub.asmParameterRegisters)
|
return
|
||||||
val args = mutableListOf<Pair<Expression, RegisterOrStatusflag>>()
|
|
||||||
for(argOrig in argsOrig) {
|
|
||||||
if(argOrig.second.registerOrPair in setOf(RegisterOrPair.X, RegisterOrPair.AX, RegisterOrPair.XY))
|
|
||||||
args.add(argOrig)
|
|
||||||
else
|
|
||||||
args.add(0, argOrig)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (arg in args.reversed())
|
// 1. load all arguments reversed onto the stack: first arg goes last (is on top).
|
||||||
asmgen.translateExpression(arg.first)
|
for (arg in stmt.args.reversed())
|
||||||
for (arg in args) {
|
asmgen.translateExpression(arg)
|
||||||
val regparam = arg.second
|
|
||||||
|
var argForCarry: IndexedValue<Pair<Expression, RegisterOrStatusflag>>? = null
|
||||||
|
var argForXregister: IndexedValue<Pair<Expression, RegisterOrStatusflag>>? = null
|
||||||
|
var argForAregister: IndexedValue<Pair<Expression, RegisterOrStatusflag>>? = null
|
||||||
|
|
||||||
|
asmgen.out(" inx") // align estack pointer
|
||||||
|
|
||||||
|
for(argi in stmt.args.zip(sub.asmParameterRegisters).withIndex()) {
|
||||||
when {
|
when {
|
||||||
regparam.statusflag==Statusflag.Pc -> {
|
argi.value.second.stack -> TODO("asmsub @stack parameter")
|
||||||
asmgen.out("""
|
argi.value.second.statusflag == Statusflag.Pc -> {
|
||||||
inx
|
require(argForCarry == null)
|
||||||
pha
|
argForCarry = argi
|
||||||
lda P8ESTACK_LO,x
|
|
||||||
beq +
|
|
||||||
sec
|
|
||||||
bcs ++
|
|
||||||
+ clc
|
|
||||||
+ pla""")
|
|
||||||
}
|
}
|
||||||
regparam.statusflag!=null -> {
|
argi.value.second.statusflag != null -> throw AssemblyError("can only use Carry as status flag parameter")
|
||||||
throw AssemblyError("can only use Carry as status flag parameter")
|
argi.value.second.registerOrPair in setOf(RegisterOrPair.X, RegisterOrPair.AX, RegisterOrPair.XY) -> {
|
||||||
|
require(argForXregister==null)
|
||||||
|
argForXregister = argi
|
||||||
}
|
}
|
||||||
regparam.registerOrPair!=null -> {
|
argi.value.second.registerOrPair in setOf(RegisterOrPair.A, RegisterOrPair.AY) -> {
|
||||||
val tgt = AsmAssignTarget.fromRegisters(regparam.registerOrPair, program, asmgen)
|
require(argForAregister == null)
|
||||||
val source = AsmAssignSource(SourceStorageKind.STACK, program, tgt.datatype)
|
argForAregister = argi
|
||||||
val asgn = AsmAssignment(source, tgt, false, Position.DUMMY)
|
|
||||||
asmgen.translateNormalAssignment(asgn)
|
|
||||||
}
|
}
|
||||||
else -> {}
|
argi.value.second.registerOrPair == RegisterOrPair.Y -> {
|
||||||
|
asmgen.out(" ldy P8ESTACK_LO+${argi.index},x")
|
||||||
|
}
|
||||||
|
else -> throw AssemblyError("weird argument")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(argForCarry!=null) {
|
||||||
|
asmgen.out("""
|
||||||
|
lda P8ESTACK_LO+${argForCarry.index},x
|
||||||
|
beq +
|
||||||
|
sec
|
||||||
|
bcs ++
|
||||||
|
+ clc
|
||||||
|
+ php""") // push the status flags
|
||||||
|
}
|
||||||
|
|
||||||
|
if(argForAregister!=null) {
|
||||||
|
when(argForAregister.value.second.registerOrPair) {
|
||||||
|
RegisterOrPair.A -> asmgen.out(" lda P8ESTACK_LO+${argForAregister.index},x")
|
||||||
|
RegisterOrPair.AY -> asmgen.out(" lda P8ESTACK_LO+${argForAregister.index},x | ldy P8ESTACK_HI+${argForAregister.index},x")
|
||||||
|
else -> throw AssemblyError("weird arg")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(argForXregister!=null) {
|
||||||
|
if(argForAregister!=null)
|
||||||
|
asmgen.out(" pha")
|
||||||
|
when(argForXregister.value.second.registerOrPair) {
|
||||||
|
RegisterOrPair.X -> asmgen.out(" lda P8ESTACK_LO+${argForXregister.index},x | tax")
|
||||||
|
RegisterOrPair.AX -> asmgen.out(" ldy P8ESTACK_LO+${argForXregister.index},x | lda P8ESTACK_HI+${argForXregister.index},x | tax | tya")
|
||||||
|
RegisterOrPair.XY -> asmgen.out(" ldy P8ESTACK_HI+${argForXregister.index},x | lda P8ESTACK_LO+${argForXregister.index},x | tax")
|
||||||
|
else -> throw AssemblyError("weird arg")
|
||||||
|
}
|
||||||
|
if(argForAregister!=null)
|
||||||
|
asmgen.out(" pla")
|
||||||
|
} else {
|
||||||
|
repeat(sub.parameters.size - 1) { asmgen.out(" inx") } // unwind stack
|
||||||
|
}
|
||||||
|
|
||||||
|
if(argForCarry!=null)
|
||||||
|
asmgen.out(" plp") // set the carry flag back to correct value
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun argumentViaVariable(sub: Subroutine, parameter: IndexedValue<SubroutineParameter>, value: Expression) {
|
private fun argumentViaVariable(sub: Subroutine, parameter: IndexedValue<SubroutineParameter>, value: Expression) {
|
||||||
|
@ -260,16 +260,16 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
DataType.UBYTE, DataType.BYTE -> {
|
DataType.UBYTE, DataType.BYTE -> {
|
||||||
when(target.register!!) {
|
when(target.register!!) {
|
||||||
RegisterOrPair.A -> asmgen.out(" inx | lda P8ESTACK_LO,x")
|
RegisterOrPair.A -> asmgen.out(" inx | lda P8ESTACK_LO,x")
|
||||||
RegisterOrPair.X -> asmgen.out(" inx | lda P8ESTACK_LO,x | tax")
|
RegisterOrPair.X -> throw AssemblyError("can't load X from stack here - use intermediary var? ${target.origAstTarget?.position}")
|
||||||
RegisterOrPair.Y -> asmgen.out(" inx | ldy P8ESTACK_LO,x")
|
RegisterOrPair.Y -> asmgen.out(" inx | ldy P8ESTACK_LO,x")
|
||||||
else -> throw AssemblyError("can't assign byte to register pair word")
|
else -> throw AssemblyError("can't assign byte to register pair word")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DataType.UWORD, DataType.WORD, in PassByReferenceDatatypes -> {
|
DataType.UWORD, DataType.WORD, in PassByReferenceDatatypes -> {
|
||||||
when(target.register!!) {
|
when(target.register!!) {
|
||||||
RegisterOrPair.AX -> asmgen.out(" inx | lda P8ESTACK_LO,x | pha | lda P8ESTACK_HI,x | tax | pla")
|
RegisterOrPair.AX -> throw AssemblyError("can't load X from stack here - use intermediary var? ${target.origAstTarget?.position}")
|
||||||
RegisterOrPair.AY-> asmgen.out(" inx | lda P8ESTACK_LO,x | ldy P8ESTACK_HI,x")
|
RegisterOrPair.AY-> asmgen.out(" inx | lda P8ESTACK_LO,x | ldy P8ESTACK_HI,x")
|
||||||
RegisterOrPair.XY-> asmgen.out(" inx | lda P8ESTACK_LO,x | ldy P8ESTACK_HI,x | tax")
|
RegisterOrPair.XY-> throw AssemblyError("can't load X from stack here - use intermediary var? ${target.origAstTarget?.position}")
|
||||||
else -> throw AssemblyError("can't assign word to single byte register")
|
else -> throw AssemblyError("can't assign word to single byte register")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -590,7 +590,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
TargetStorageKind.STACK -> {
|
TargetStorageKind.STACK -> {
|
||||||
when(register) {
|
when(register) {
|
||||||
CpuRegister.A -> asmgen.out(" sta P8ESTACK_LO,x | dex")
|
CpuRegister.A -> asmgen.out(" sta P8ESTACK_LO,x | dex")
|
||||||
CpuRegister.X -> throw AssemblyError("can't store X itself on eval stack")
|
CpuRegister.X -> throw AssemblyError("can't use X here")
|
||||||
CpuRegister.Y -> asmgen.out(" tya | sta P8ESTACK_LO,x | dex")
|
CpuRegister.Y -> asmgen.out(" tya | sta P8ESTACK_LO,x | dex")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user