mirror of
https://github.com/irmen/prog8.git
synced 2026-04-26 20:17:57 +00:00
avoid unnecessary word extension when assigning a register byte to a byte target
This commit is contained in:
@@ -727,7 +727,7 @@ class AsmGen6502Internal (
|
||||
}
|
||||
|
||||
assignExpressionToRegister(value, RegisterOrPair.A)
|
||||
assignRegister(RegisterOrPair.A, target)
|
||||
assignmentAsmGen.assignRegisterByte(target, CpuRegister.A, target.datatype.isSigned, false)
|
||||
}
|
||||
target.datatype.isWord || target.datatype.isPassByRef -> {
|
||||
assignExpressionToRegister(value, RegisterOrPair.AY)
|
||||
@@ -1063,26 +1063,39 @@ $repeatLabel""")
|
||||
|
||||
private fun translate(ret: PtReturn) {
|
||||
val returnvalue = ret.children.singleOrNull()
|
||||
val sub = ret.definingSub()!!
|
||||
val returnRegs = sub.returnsWhatWhere()
|
||||
|
||||
if(returnvalue!=null) {
|
||||
val sub = ret.definingSub()!!
|
||||
val returnReg = sub.returnsWhatWhere().single()
|
||||
if (sub.returns.single().isNumericOrBool==true) {
|
||||
assignExpressionToRegister(returnvalue as PtExpression, returnReg.first.registerOrPair!!)
|
||||
assignExpressionToRegister(returnvalue as PtExpression, returnRegs.single().first.registerOrPair!!)
|
||||
}
|
||||
else {
|
||||
// all else take its address and assign that also to AY register pair
|
||||
val addrofValue = PtAddressOf(returnvalue.position)
|
||||
addrofValue.add(returnvalue as PtIdentifier)
|
||||
addrofValue.parent = ret.parent
|
||||
assignmentAsmGen.assignExpressionToRegister(addrofValue, returnReg.first.registerOrPair!!, false)
|
||||
assignmentAsmGen.assignExpressionToRegister(addrofValue, returnRegs.single().first.registerOrPair!!, false)
|
||||
}
|
||||
}
|
||||
else if(ret.children.size>1) {
|
||||
// multi-value returns are passed throug cx16.R15 down to R0 (allows unencumbered use of many Rx registers if you don't return that many values)
|
||||
val registersReverseOrder = Cx16VirtualRegisters.reversed()
|
||||
ret.children.zip(registersReverseOrder).forEach { (value, register) ->
|
||||
assignExpressionToRegister(value as PtExpression, register)
|
||||
val assigns = ret.children.zip(returnRegs).map { it.first to it.second }
|
||||
assigns.forEach {
|
||||
val tgt = AsmAssignTarget(TargetStorageKind.REGISTER, this, it.second.second, null, it.first.position, register = it.second.first.registerOrPair!!)
|
||||
assignExpressionTo(it.first as PtExpression, tgt)
|
||||
}
|
||||
|
||||
// TODO: note: multi-value returns are passed throug cx16.R15 down to R0 (allows unencumbered use of many Rx registers if you don't return that many values)
|
||||
// TODO: to avoid register clobbering, assign the first return value last in row.
|
||||
/*
|
||||
assigns.drop(1).forEach {
|
||||
val tgt = AsmAssignTarget(TargetStorageKind.REGISTER, this, it.second.second, null, it.first.position, register = it.second.first.registerOrPair!!)
|
||||
assignExpressionTo(it.first as PtExpression, tgt)
|
||||
}
|
||||
assigns.first().also {
|
||||
assignExpressionToRegister(it.first as PtExpression, it.second.first.registerOrPair!!)
|
||||
}
|
||||
*/
|
||||
}
|
||||
out(" rts")
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package prog8.codegen.cpu6502
|
||||
import prog8.code.ast.IPtSubroutine
|
||||
import prog8.code.ast.PtAsmSub
|
||||
import prog8.code.ast.PtSub
|
||||
import prog8.code.core.AssemblyError
|
||||
import prog8.code.core.Cx16VirtualRegisters
|
||||
import prog8.code.core.DataType
|
||||
import prog8.code.core.RegisterOrPair
|
||||
import prog8.code.core.RegisterOrStatusflag
|
||||
@@ -17,21 +17,31 @@ internal fun IPtSubroutine.returnsWhatWhere(): List<Pair<RegisterOrStatusflag, D
|
||||
is PtSub -> {
|
||||
// for non-asm subroutines, determine the return registers based on the type of the return values
|
||||
|
||||
fun cpuRegisterFor(returntype: DataType): RegisterOrStatusflag = when {
|
||||
returntype.isByteOrBool -> RegisterOrStatusflag(RegisterOrPair.A, null)
|
||||
returntype.isWord -> RegisterOrStatusflag(RegisterOrPair.AY, null)
|
||||
returntype.isFloat -> RegisterOrStatusflag(RegisterOrPair.FAC1, null)
|
||||
else -> RegisterOrStatusflag(RegisterOrPair.AY, null)
|
||||
}
|
||||
|
||||
when(returns.size) {
|
||||
0 -> return emptyList()
|
||||
1 -> {
|
||||
val returntype = returns.single()
|
||||
val register = when {
|
||||
returntype.isByteOrBool -> RegisterOrStatusflag(RegisterOrPair.A, null)
|
||||
returntype.isWord -> RegisterOrStatusflag(RegisterOrPair.AY, null)
|
||||
returntype.isFloat -> RegisterOrStatusflag(RegisterOrPair.FAC1, null)
|
||||
else -> RegisterOrStatusflag(RegisterOrPair.AY, null)
|
||||
}
|
||||
val register = cpuRegisterFor(returntype)
|
||||
return listOf(Pair(register, returntype))
|
||||
}
|
||||
else -> {
|
||||
// TODO for multi-value results, put the first one in register(s) and only the rest in the virtual registers?
|
||||
throw AssemblyError("multi-value returns from a normal subroutine are not put into registers, this routine shouldn't have been called in this scenario")
|
||||
val others = returns.zip(Cx16VirtualRegisters.reversed())
|
||||
.map { (type, reg) -> RegisterOrStatusflag(reg, null) to type }
|
||||
return others
|
||||
|
||||
// TODO for multi-value results, put the first one in A or AY cpu register(s) and the rest in the virtual registers starting from R15 and counting down
|
||||
// val first = cpuRegisterFor(returns.first()) to returns.first()
|
||||
// val others = returns.drop(1)
|
||||
// .zip(Cx16VirtualRegisters.reversed())
|
||||
// .map { (type, reg) -> RegisterOrStatusflag(reg, null) to type }
|
||||
// return listOf(first) + others
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+69
-3
@@ -1,12 +1,78 @@
|
||||
%import textio
|
||||
%zeropage basicsafe
|
||||
%option no_sysinit
|
||||
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
const uword MAX_CAVE_WIDTH = 440 ; word here to avoid having to cast to word all the time
|
||||
cx16.r5 = one()
|
||||
txt.print_uw(cx16.r5)
|
||||
txt.nl()
|
||||
|
||||
if cx16.r0L > MAX_CAVE_WIDTH
|
||||
return
|
||||
cx16.r5, cx16.r6 = two()
|
||||
txt.print_uw(cx16.r5)
|
||||
txt.spc()
|
||||
txt.print_uw(cx16.r6)
|
||||
txt.nl()
|
||||
|
||||
cx16.r5, cx16.r6, cx16.r7 = three()
|
||||
txt.print_uw(cx16.r5)
|
||||
txt.spc()
|
||||
txt.print_uw(cx16.r6)
|
||||
txt.spc()
|
||||
txt.print_uw(cx16.r7)
|
||||
txt.nl()
|
||||
|
||||
; bytes
|
||||
cx16.r5L = oneb()
|
||||
txt.print_ub(cx16.r5L)
|
||||
txt.nl()
|
||||
|
||||
cx16.r5L, cx16.r6L = twob()
|
||||
txt.print_ub(cx16.r5L)
|
||||
txt.spc()
|
||||
txt.print_ub(cx16.r6L)
|
||||
txt.nl()
|
||||
|
||||
cx16.r5L, cx16.r6L, cx16.r7L = threeb()
|
||||
txt.print_ub(cx16.r5L)
|
||||
txt.spc()
|
||||
txt.print_ub(cx16.r6L)
|
||||
txt.spc()
|
||||
txt.print_ub(cx16.r7L)
|
||||
txt.nl()
|
||||
}
|
||||
|
||||
uword @shared w1=1111
|
||||
uword @shared w2=2222
|
||||
uword @shared w3=3333
|
||||
ubyte @shared b1=11
|
||||
ubyte @shared b2=22
|
||||
ubyte @shared b3=33
|
||||
|
||||
sub one() -> uword {
|
||||
cx16.r0L++
|
||||
return w1
|
||||
}
|
||||
|
||||
sub two() -> uword, uword { ; TODO no P8SRC generated in IR?
|
||||
return w1, w2
|
||||
}
|
||||
|
||||
sub three() -> uword, uword, uword { ; TODO no P8SRC generated in IR?
|
||||
return w1, w2, w3
|
||||
}
|
||||
|
||||
sub oneb() -> ubyte {
|
||||
cx16.r0L++
|
||||
return b1
|
||||
}
|
||||
|
||||
sub twob() -> ubyte,ubyte { ; TODO no P8SRC generated in IR?
|
||||
return b1, b2
|
||||
}
|
||||
|
||||
sub threeb() -> ubyte, ubyte, ubyte { ; TODO no P8SRC generated in IR?
|
||||
return b1, b2, b3
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user