mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
removed @stack in subroutine args and returnvalues, can only use variables or registers now
This commit is contained in:
parent
3efa8da8e0
commit
3ab641aa21
@ -143,7 +143,6 @@ class AstToSourceCode(val output: (text: String) -> Unit, val program: Program):
|
||||
for(param in subroutine.parameters.zip(subroutine.asmParameterRegisters)) {
|
||||
val reg =
|
||||
when {
|
||||
param.second.stack -> "stack"
|
||||
param.second.registerOrPair!=null -> param.second.registerOrPair.toString()
|
||||
param.second.statusflag!=null -> param.second.statusflag.toString()
|
||||
else -> "?????"
|
||||
|
@ -254,8 +254,8 @@ private fun prog8Parser.Asmsub_declContext.toAst(): AsmsubDecl {
|
||||
val clobbers = asmsub_clobbers()?.clobber()?.toAst() ?: emptySet()
|
||||
val normalParameters = params.map { SubroutineParameter(it.name, it.type, it.position) }
|
||||
val normalReturntypes = returns.map { it.type }
|
||||
val paramRegisters = params.map { RegisterOrStatusflag(it.registerOrPair, it.statusflag, false) }
|
||||
val returnRegisters = returns.map { RegisterOrStatusflag(it.registerOrPair, it.statusflag, it.stack) }
|
||||
val paramRegisters = params.map { RegisterOrStatusflag(it.registerOrPair, it.statusflag) }
|
||||
val returnRegisters = returns.map { RegisterOrStatusflag(it.registerOrPair, it.statusflag) }
|
||||
return AsmsubDecl(name, normalParameters, normalReturntypes, paramRegisters, returnRegisters, clobbers)
|
||||
}
|
||||
|
||||
@ -268,7 +268,6 @@ private class AsmSubroutineParameter(name: String,
|
||||
private class AsmSubroutineReturn(val type: DataType,
|
||||
val registerOrPair: RegisterOrPair?,
|
||||
val statusflag: Statusflag?,
|
||||
val stack: Boolean,
|
||||
val position: Position)
|
||||
|
||||
private fun prog8Parser.Asmsub_returnsContext.toAst(): List<AsmSubroutineReturn>
|
||||
@ -287,7 +286,7 @@ private fun prog8Parser.Asmsub_returnsContext.toAst(): List<AsmSubroutineReturn>
|
||||
it.datatype().toAst(),
|
||||
registerorpair,
|
||||
statusregister,
|
||||
!it.stack?.text.isNullOrEmpty(), toPosition())
|
||||
toPosition())
|
||||
}
|
||||
|
||||
private fun prog8Parser.Asmsub_paramsContext.toAst(): List<AsmSubroutineParameter>
|
||||
|
@ -44,7 +44,7 @@ class BuiltinFunctionStatementPlaceholder(val name: String, override val positio
|
||||
}
|
||||
}
|
||||
|
||||
data class RegisterOrStatusflag(val registerOrPair: RegisterOrPair?, val statusflag: Statusflag?, val stack: Boolean) // TODO get rid of stack?
|
||||
data class RegisterOrStatusflag(val registerOrPair: RegisterOrPair?, val statusflag: Statusflag?)
|
||||
|
||||
class Block(override val name: String,
|
||||
val address: Int?,
|
||||
@ -697,11 +697,11 @@ class Subroutine(override val name: String,
|
||||
private fun determineReturnRegisters(returntypes: List<DataType>): List<RegisterOrStatusflag> {
|
||||
// for non-asm subroutines, determine the return registers based on the type of the return value
|
||||
return when(returntypes.singleOrNull()) {
|
||||
in ByteDatatypes -> listOf(RegisterOrStatusflag(RegisterOrPair.A, null, false))
|
||||
in WordDatatypes -> listOf(RegisterOrStatusflag(RegisterOrPair.AY, null, false))
|
||||
DataType.FLOAT -> listOf(RegisterOrStatusflag(RegisterOrPair.AY, null, false))
|
||||
in ByteDatatypes -> listOf(RegisterOrStatusflag(RegisterOrPair.A, null))
|
||||
in WordDatatypes -> listOf(RegisterOrStatusflag(RegisterOrPair.AY, null))
|
||||
DataType.FLOAT -> listOf(RegisterOrStatusflag(RegisterOrPair.AY, null))
|
||||
null -> emptyList()
|
||||
else -> listOf(RegisterOrStatusflag(RegisterOrPair.AY, null, false))
|
||||
else -> listOf(RegisterOrStatusflag(RegisterOrPair.AY, null))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1155,7 +1155,6 @@ $counterVar .byte 0""")
|
||||
val returnValueTarget =
|
||||
when {
|
||||
returnReg.registerOrPair!=null -> AsmAssignTarget.fromRegisters(returnReg.registerOrPair, sub, program, this)
|
||||
returnReg.stack -> AsmAssignTarget(TargetStorageKind.STACK, program, this, returnType, sub)
|
||||
else -> throw AssemblyError("normal subroutines can't return value in status register directly")
|
||||
}
|
||||
|
||||
|
@ -1055,41 +1055,41 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge
|
||||
asmgen.translateFunctionCall(expression, preserveStatusRegisterAfterCall)
|
||||
val returns = sub.returntypes.zip(sub.asmReturnvaluesRegisters)
|
||||
for ((_, reg) in returns) {
|
||||
if (!reg.stack) {
|
||||
// result value in cpu or status registers, put it on the stack
|
||||
if (reg.registerOrPair != null) {
|
||||
when (reg.registerOrPair) {
|
||||
RegisterOrPair.A -> asmgen.out(" sta P8ESTACK_LO,x | dex")
|
||||
RegisterOrPair.Y -> asmgen.out(" tya | sta P8ESTACK_LO,x | dex")
|
||||
RegisterOrPair.AY -> asmgen.out(" sta P8ESTACK_LO,x | tya | sta P8ESTACK_HI,x | dex")
|
||||
RegisterOrPair.X -> {
|
||||
// return value in X register has been discarded, just push a zero
|
||||
if(CompilationTarget.instance.machine.cpu==CpuType.CPU65c02)
|
||||
asmgen.out(" stz P8ESTACK_LO,x")
|
||||
else
|
||||
asmgen.out(" lda #0 | sta P8ESTACK_LO,x")
|
||||
asmgen.out(" dex")
|
||||
}
|
||||
RegisterOrPair.AX -> {
|
||||
// return value in X register has been discarded, just push a zero in this place
|
||||
asmgen.out(" sta P8ESTACK_LO,x")
|
||||
if(CompilationTarget.instance.machine.cpu==CpuType.CPU65c02)
|
||||
asmgen.out(" stz P8ESTACK_HI,x")
|
||||
else
|
||||
asmgen.out(" lda #0 | sta P8ESTACK_HI,x")
|
||||
asmgen.out(" dex")
|
||||
}
|
||||
RegisterOrPair.XY -> {
|
||||
// return value in X register has been discarded, just push a zero in this place
|
||||
if(CompilationTarget.instance.machine.cpu==CpuType.CPU65c02)
|
||||
asmgen.out(" stz P8ESTACK_LO,x")
|
||||
else
|
||||
asmgen.out(" lda #0 | sta P8ESTACK_LO,x")
|
||||
asmgen.out(" tya | sta P8ESTACK_HI,x | dex")
|
||||
}
|
||||
// result value in cpu or status registers, put it on the stack
|
||||
if (reg.registerOrPair != null) {
|
||||
when (reg.registerOrPair) {
|
||||
RegisterOrPair.A -> asmgen.out(" sta P8ESTACK_LO,x | dex")
|
||||
RegisterOrPair.Y -> asmgen.out(" tya | sta P8ESTACK_LO,x | dex")
|
||||
RegisterOrPair.AY -> asmgen.out(" sta P8ESTACK_LO,x | tya | sta P8ESTACK_HI,x | dex")
|
||||
RegisterOrPair.X -> {
|
||||
// return value in X register has been discarded, just push a zero
|
||||
if(CompilationTarget.instance.machine.cpu==CpuType.CPU65c02)
|
||||
asmgen.out(" stz P8ESTACK_LO,x")
|
||||
else
|
||||
asmgen.out(" lda #0 | sta P8ESTACK_LO,x")
|
||||
asmgen.out(" dex")
|
||||
}
|
||||
RegisterOrPair.AX -> {
|
||||
// return value in X register has been discarded, just push a zero in this place
|
||||
asmgen.out(" sta P8ESTACK_LO,x")
|
||||
if(CompilationTarget.instance.machine.cpu==CpuType.CPU65c02)
|
||||
asmgen.out(" stz P8ESTACK_HI,x")
|
||||
else
|
||||
asmgen.out(" lda #0 | sta P8ESTACK_HI,x")
|
||||
asmgen.out(" dex")
|
||||
}
|
||||
RegisterOrPair.XY -> {
|
||||
// return value in X register has been discarded, just push a zero in this place
|
||||
if(CompilationTarget.instance.machine.cpu==CpuType.CPU65c02)
|
||||
asmgen.out(" stz P8ESTACK_LO,x")
|
||||
else
|
||||
asmgen.out(" lda #0 | sta P8ESTACK_LO,x")
|
||||
asmgen.out(" tya | sta P8ESTACK_HI,x | dex")
|
||||
}
|
||||
}
|
||||
// return value from a statusregister is not put on the stack, it should be acted on via a conditional branch such as if_cc
|
||||
}
|
||||
else if(reg.statusflag!=null) {
|
||||
TODO("statusflag result onto stack")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,14 +18,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
|
||||
val sub = stmt.target.targetSubroutine(program.namespace)!!
|
||||
val preserveStatusRegisterAfterCall = sub.asmReturnvaluesRegisters.any {it.statusflag!=null}
|
||||
translateFunctionCall(stmt, preserveStatusRegisterAfterCall)
|
||||
// discard resultvalues that might be on the stack:
|
||||
val returns = sub.returntypes.zip(sub.asmReturnvaluesRegisters)
|
||||
for ((t, reg) in returns) {
|
||||
if (reg.stack) {
|
||||
if (t in IntegerDatatypes || t in PassByReferenceDatatypes) asmgen.out(" inx")
|
||||
else if (t == DataType.FLOAT) asmgen.out(" inx | inx | inx")
|
||||
}
|
||||
}
|
||||
// functioncalls no longer return results on the stack, so simply ignore the results in the registers
|
||||
if(preserveStatusRegisterAfterCall)
|
||||
asmgen.out(" plp\t; restore status flags from call")
|
||||
}
|
||||
@ -104,7 +97,6 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
|
||||
|
||||
for(argi in stmt.args.zip(sub.asmParameterRegisters).withIndex()) {
|
||||
when {
|
||||
argi.value.second.stack -> TODO("asmsub @stack parameter")
|
||||
argi.value.second.statusflag == Statusflag.Pc -> {
|
||||
require(argForCarry == null)
|
||||
argForCarry = argi
|
||||
@ -191,20 +183,12 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
|
||||
val paramRegister = sub.asmParameterRegisters[parameter.index]
|
||||
val statusflag = paramRegister.statusflag
|
||||
val register = paramRegister.registerOrPair
|
||||
val stack = paramRegister.stack
|
||||
val requiredDt = parameter.value.type
|
||||
if(requiredDt!=valueDt) {
|
||||
if(valueDt largerThan requiredDt)
|
||||
throw AssemblyError("can only convert byte values to word param types")
|
||||
}
|
||||
when {
|
||||
stack -> {
|
||||
// push arg onto the stack
|
||||
// note: argument order is reversed (first argument will be deepest on the stack)
|
||||
asmgen.translateExpression(value)
|
||||
if(requiredDt!=valueDt)
|
||||
asmgen.signExtendStackLsb(valueDt)
|
||||
}
|
||||
statusflag!=null -> {
|
||||
if(requiredDt!=valueDt)
|
||||
throw AssemblyError("for statusflag, byte value is required")
|
||||
|
@ -6,7 +6,6 @@ TODO
|
||||
- make memset(w) and memcopy able to work with >256 bytes
|
||||
- make memset and memcopy use the ROM routines on the CX16
|
||||
- calling convention for builtin functions no longer via stack but via statically allocated vars inside the subroutine proc (just as normal subroutines)
|
||||
- get rid of @stack in asmsub (syntax, ast) altogether (because all subroutines are no longer using this calling convention anymore)
|
||||
- make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as '_'
|
||||
- option to load the built-in library files from a directory instead of the embedded ones (for easier library development/debugging)
|
||||
- see if we can group some errors together for instance the (now single) errors about unidentified symbols
|
||||
|
@ -271,7 +271,7 @@ asmsub_decl : identifier '(' asmsub_params? ')' asmsub_clobbers? asmsub_returns?
|
||||
|
||||
asmsub_params : asmsub_param (',' EOL? asmsub_param)* ;
|
||||
|
||||
asmsub_param : vardecl '@' identifier ; // A,X,Y,AX,AY,XY,Pc,Pz,Pn,Pv allowed. TODO implement stack='stack'
|
||||
asmsub_param : vardecl '@' identifier ; // A,X,Y,AX,AY,XY,Pc,Pz,Pn,Pv allowed.
|
||||
|
||||
asmsub_clobbers : 'clobbers' '(' clobber? ')' ;
|
||||
|
||||
@ -279,7 +279,7 @@ clobber : identifier (',' identifier)* ; // A,X,Y allowed
|
||||
|
||||
asmsub_returns : '->' asmsub_return (',' EOL? asmsub_return)* ;
|
||||
|
||||
asmsub_return : datatype '@' (identifier | stack='stack') ; // A,X,Y,AX,AY,XY,Pc,Pz,Pn,Pv allowed
|
||||
asmsub_return : datatype '@' identifier ; // A,X,Y,AX,AY,XY,Pc,Pz,Pn,Pv allowed
|
||||
|
||||
|
||||
if_stmt : 'if' expression EOL? (statement | statement_block) EOL? else_part? ; // statement is constrained later
|
||||
|
Loading…
x
Reference in New Issue
Block a user