mirror of
https://github.com/irmen/prog8.git
synced 2024-08-18 23:29:32 +00:00
relaxed some type checks on certain word register assignment
preparing to optimize asmsub arg passing for complex expressions
This commit is contained in:
parent
f09c04eeac
commit
730b208617
@ -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
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
||||
|
@ -2,5 +2,9 @@
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
uword xx=$2000
|
||||
ubyte yy=30
|
||||
ubyte zz=9
|
||||
sys.memset(xx+200, yy*2, zz+yy)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user