mirror of
https://github.com/irmen/prog8.git
synced 2024-07-09 17:29:46 +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.Cx16Target
|
||||||
import prog8.compiler.target.cbm.AssemblyProgram
|
import prog8.compiler.target.cbm.AssemblyProgram
|
||||||
import prog8.compiler.target.cbm.loadAsmIncludeFile
|
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.AsmAssignment
|
||||||
import prog8.compiler.target.cpu6502.codegen.assignment.AssignmentAsmGen
|
import prog8.compiler.target.cpu6502.codegen.assignment.AssignmentAsmGen
|
||||||
import prog8.compilerinterface.*
|
import prog8.compilerinterface.*
|
||||||
@ -856,6 +857,21 @@ class AsmGen(private val program: Program,
|
|||||||
internal fun assignVariableToRegister(asmVarName: String, register: RegisterOrPair) =
|
internal fun assignVariableToRegister(asmVarName: String, register: RegisterOrPair) =
|
||||||
assignmentAsmGen.assignVariableToRegister(asmVarName, register)
|
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) {
|
private fun translateSubroutine(sub: Subroutine) {
|
||||||
var onlyVariables = false
|
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.AsmAssignSource
|
||||||
import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignTarget
|
import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignTarget
|
||||||
import prog8.compiler.target.cpu6502.codegen.assignment.AsmAssignment
|
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.compiler.target.cpu6502.codegen.assignment.TargetStorageKind
|
||||||
import prog8.compilerinterface.CpuType
|
import prog8.compilerinterface.CpuType
|
||||||
|
|
||||||
@ -104,7 +105,6 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
|
|||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
// Risk of clobbering due to complex expression args. Evaluate first, then assign registers.
|
// 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)
|
registerArgsViaStackEvaluation(stmt, sub)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,13 +136,43 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
|
|||||||
private fun registerArgsViaStackEvaluation(stmt: IFunctionCall, sub: Subroutine) {
|
private fun registerArgsViaStackEvaluation(stmt: IFunctionCall, sub: Subroutine) {
|
||||||
// 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.
|
||||||
|
// TODO find another way to prepare the arguments, without using the eval stack
|
||||||
|
|
||||||
if(sub.parameters.isEmpty())
|
if(sub.parameters.isEmpty())
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
// 1. load all arguments reversed onto the stack: first arg goes last (is on top).
|
// 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 argForCarry: IndexedValue<Pair<Expression, RegisterOrStatusflag>>? = null
|
||||||
var argForXregister: 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 -> {
|
SourceStorageKind.REGISTER -> {
|
||||||
when(assign.source.datatype) {
|
when(assign.source.datatype) {
|
||||||
DataType.UBYTE -> assignRegisterByte(assign.target, assign.source.register!!.asCpuRegister())
|
DataType.UBYTE, DataType.BYTE -> assignRegisterByte(assign.target, assign.source.register!!.asCpuRegister())
|
||||||
DataType.UWORD -> assignRegisterpairWord(assign.target, assign.source.register!!)
|
DataType.UWORD, DataType.WORD, in PassByReferenceDatatypes -> assignRegisterpairWord(assign.target, assign.source.register!!)
|
||||||
else -> throw AssemblyError("invalid register dt")
|
else -> throw AssemblyError("invalid register dt ${assign.source.datatype}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SourceStorageKind.STACK -> {
|
SourceStorageKind.STACK -> {
|
||||||
@ -1455,7 +1455,7 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun assignRegisterpairWord(target: AsmAssignTarget, regs: RegisterOrPair) {
|
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)
|
if(target.datatype==DataType.FLOAT)
|
||||||
throw AssemblyError("float value should be from FAC1 not from registerpair memory pointer")
|
throw AssemblyError("float value should be from FAC1 not from registerpair memory pointer")
|
||||||
|
|
||||||
|
@ -2,5 +2,9 @@
|
|||||||
|
|
||||||
main {
|
main {
|
||||||
sub start() {
|
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