relaxed some type checks on certain word register assignment

preparing to optimize asmsub arg passing for complex expressions
This commit is contained in:
Irmen de Jong 2021-11-04 23:57:25 +01:00
parent f09c04eeac
commit 730b208617
4 changed files with 57 additions and 7 deletions

View File

@ -11,6 +11,7 @@ import prog8.compiler.target.C64Target
import prog8.compiler.target.Cx16Target
import prog8.compiler.target.cbm.AssemblyProgram
import prog8.compiler.target.cbm.loadAsmIncludeFile
import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignTarget
import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignment
import prog8.compiler.target.cpu6502.codegen.assignment.AssignmentAsmGen
import prog8.compilerinterface.*
@ -856,6 +857,21 @@ class AsmGen(private val program: Program,
internal fun assignVariableToRegister(asmVarName: String, register: RegisterOrPair) =
assignmentAsmGen.assignVariableToRegister(asmVarName, register)
internal fun assignRegister(reg: RegisterOrPair, target: AsmAssignTarget) {
when(reg) {
RegisterOrPair.A,
RegisterOrPair.X,
RegisterOrPair.Y -> assignmentAsmGen.assignRegisterByte(target, reg.asCpuRegister())
RegisterOrPair.AX,
RegisterOrPair.AY,
RegisterOrPair.XY,
in Cx16VirtualRegisters -> assignmentAsmGen.assignRegisterpairWord(target, reg)
RegisterOrPair.FAC1 -> assignmentAsmGen.assignFAC1float(target)
RegisterOrPair.FAC2 -> throw AssemblyError("no support yet to assign FAC2 directly to something")
else -> throw AssemblyError("invalid register")
}
}
private fun translateSubroutine(sub: Subroutine) {
var onlyVariables = false

View File

@ -13,6 +13,7 @@ import prog8.compiler.target.AssemblyError
import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignSource
import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignTarget
import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignment
import prog8.compiler.target.cpu6502.codegen.assignment.SourceStorageKind
import prog8.compiler.target.cpu6502.codegen.assignment.TargetStorageKind
import prog8.compilerinterface.CpuType
@ -104,7 +105,6 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
}
else -> {
// Risk of clobbering due to complex expression args. Evaluate first, then assign registers.
// TODO find another way to prepare the arguments, without using the eval stack
registerArgsViaStackEvaluation(stmt, sub)
}
}
@ -136,13 +136,43 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
private fun registerArgsViaStackEvaluation(stmt: IFunctionCall, sub: Subroutine) {
// 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.
// TODO find another way to prepare the arguments, without using the eval stack
if(sub.parameters.isEmpty())
return
// 1. load all arguments reversed onto the stack: first arg goes last (is on top).
for (arg in stmt.args.reversed())
asmgen.translateExpression(arg)
for (arg in stmt.args.reversed()) {
if(arg.isSimple) { // TODO FOR ALL ARG TYPES?
// note this stuff below is needed to (eventually) avoid calling asmgen.translateExpression()
// TODO but This STILL requires the translateNormalAssignment() to be fixed to avoid stack eval for expressions...
when (val dt = arg.inferType(program).getOr(DataType.UNDEFINED)) {
in ByteDatatypes -> {
asmgen.assignExpressionToRegister(arg, RegisterOrPair.A)
asmgen.assignRegister(RegisterOrPair.A, AsmAssignTarget(TargetStorageKind.STACK, program, asmgen, dt, sub))
}
in WordDatatypes, in PassByReferenceDatatypes -> {
asmgen.assignExpressionToRegister(arg, RegisterOrPair.AY)
asmgen.translateNormalAssignment(
AsmAssignment(
AsmAssignSource(SourceStorageKind.REGISTER, program, asmgen, dt, register=RegisterOrPair.AY),
AsmAssignTarget(TargetStorageKind.STACK, program, asmgen, dt, sub),
false, program.memsizer, arg.position
)
)
}
DataType.FLOAT -> {
asmgen.assignExpressionToRegister(arg, RegisterOrPair.FAC1)
asmgen.assignRegister(RegisterOrPair.FAC1, AsmAssignTarget(TargetStorageKind.STACK, program, asmgen, dt, sub))
}
else -> throw AssemblyError("weird dt $dt")
}
} else {
asmgen.translateExpression(arg) // TODO GET RID OF THIS, if the above actually produces compact code
}
}
var argForCarry: IndexedValue<Pair<Expression, RegisterOrStatusflag>>? = null
var argForXregister: IndexedValue<Pair<Expression, RegisterOrStatusflag>>? = null

View File

@ -263,9 +263,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
}
SourceStorageKind.REGISTER -> {
when(assign.source.datatype) {
DataType.UBYTE -> assignRegisterByte(assign.target, assign.source.register!!.asCpuRegister())
DataType.UWORD -> assignRegisterpairWord(assign.target, assign.source.register!!)
else -> throw AssemblyError("invalid register dt")
DataType.UBYTE, DataType.BYTE -> assignRegisterByte(assign.target, assign.source.register!!.asCpuRegister())
DataType.UWORD, DataType.WORD, in PassByReferenceDatatypes -> assignRegisterpairWord(assign.target, assign.source.register!!)
else -> throw AssemblyError("invalid register dt ${assign.source.datatype}")
}
}
SourceStorageKind.STACK -> {
@ -1455,7 +1455,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
}
internal fun assignRegisterpairWord(target: AsmAssignTarget, regs: RegisterOrPair) {
require(target.datatype in NumericDatatypes)
require(target.datatype in NumericDatatypes || target.datatype in PassByReferenceDatatypes)
if(target.datatype==DataType.FLOAT)
throw AssemblyError("float value should be from FAC1 not from registerpair memory pointer")

View File

@ -2,5 +2,9 @@
main {
sub start() {
uword xx=$2000
ubyte yy=30
ubyte zz=9
sys.memset(xx+200, yy*2, zz+yy)
}
}