This commit is contained in:
Irmen de Jong 2021-11-06 14:47:11 +01:00
parent 1605791f1b
commit 62dc824bc0
7 changed files with 100 additions and 55 deletions

View File

@ -833,6 +833,7 @@ class AsmGen(private val program: Program,
} }
} }
@Deprecated("avoid calling this as it generates slow evalstack based code")
internal fun translateExpression(expression: Expression) = internal fun translateExpression(expression: Expression) =
expressionsAsmGen.translateExpression(expression) expressionsAsmGen.translateExpression(expression)

View File

@ -14,6 +14,7 @@ import kotlin.math.absoluteValue
internal class ExpressionsAsmGen(private val program: Program, private val asmgen: AsmGen) { internal class ExpressionsAsmGen(private val program: Program, private val asmgen: AsmGen) {
@Deprecated("avoid calling this as it generates slow evalstack based code")
internal fun translateExpression(expression:Expression) { internal fun translateExpression(expression:Expression) {
if (this.asmgen.options.slowCodegenWarnings) { if (this.asmgen.options.slowCodegenWarnings) {
asmgen.errors.warn("slow stack evaluation used for expression $expression", expression.position) asmgen.errors.warn("slow stack evaluation used for expression $expression", expression.position)

View File

@ -143,18 +143,16 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
// 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()) { for (arg in stmt.args.reversed())
if(arg.isSimple) { // TODO FOR ALL ARG TYPES? asmgen.translateExpression(arg)
// 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... // TODO here's an alternative to the above, but for now generates bigger code due to intermediate register steps:
// println("*** ALT PARAM PASSING FOR ASMSUB $stmt $arg") // TODO DEBUG // for (arg in stmt.args.reversed()) {
val dt = arg.inferType(program).getOr(DataType.UNDEFINED) // // note this stuff below is needed to (eventually) avoid calling asmgen.translateExpression()
val target = AsmAssignTarget(TargetStorageKind.STACK, program, asmgen, dt, sub) // // TODO also This STILL requires the translateNormalAssignment() to be fixed to avoid stack eval for expressions...
asmgen.assignExpressionTo(arg, target) // val dt = arg.inferType(program).getOr(DataType.UNDEFINED)
} else { // asmgen.assignExpressionTo(arg, AsmAssignTarget(TargetStorageKind.STACK, program, asmgen, dt, sub))
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

View File

@ -33,6 +33,11 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
} }
fun translateNormalAssignment(assign: AsmAssignment) { fun translateNormalAssignment(assign: AsmAssignment) {
if(assign.isAugmentable) {
augmentableAsmGen.translate(assign)
return
}
when(assign.source.kind) { when(assign.source.kind) {
SourceStorageKind.LITERALNUMBER -> { SourceStorageKind.LITERALNUMBER -> {
// simple case: assign a constant number // simple case: assign a constant number
@ -249,6 +254,22 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
} }
} }
} }
// TODO OPTIMIZE PREFIX EXPRESSION:
// is PrefixExpression -> {
// // first assign the value to the target then apply the operator in place on the target.
// translateNormalAssignment(AsmAssignment(
// AsmAssignSource.fromAstSource(value.expression, program, asmgen),
// assign.target,
// false, program.memsizer, assign.position
// ))
// when(value.operator) {
// "+" -> {}
// "-" -> augmentableAsmGen.inplaceNegate(assign.target, assign.target.datatype)
// "~" -> augmentableAsmGen.inplaceInvert(assign.target, assign.target.datatype)
// "not" -> augmentableAsmGen.inplaceBooleanNot(assign.target, assign.target.datatype)
// else -> throw AssemblyError("invalid prefix operator")
// }
// }
else -> { else -> {
// Everything else just evaluate via the stack. // Everything else just evaluate via the stack.
// (we can't use the assignment helper functions (assignExpressionTo...) to do it via registers here, // (we can't use the assignment helper functions (assignExpressionTo...) to do it via registers here,
@ -257,7 +278,8 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
asmgen.translateExpression(value) asmgen.translateExpression(value)
if (assign.target.datatype in WordDatatypes && assign.source.datatype in ByteDatatypes) if (assign.target.datatype in WordDatatypes && assign.source.datatype in ByteDatatypes)
asmgen.signExtendStackLsb(assign.source.datatype) asmgen.signExtendStackLsb(assign.source.datatype)
assignStackValue(assign.target) if(assign.target.kind!=TargetStorageKind.STACK || assign.target.datatype != assign.source.datatype)
assignStackValue(assign.target)
} }
} }
} }
@ -265,7 +287,8 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
asmgen.assignRegister(assign.source.register!!, assign.target) asmgen.assignRegister(assign.source.register!!, assign.target)
} }
SourceStorageKind.STACK -> { SourceStorageKind.STACK -> {
assignStackValue(assign.target) if(assign.target.kind!=TargetStorageKind.STACK || assign.target.datatype != assign.source.datatype)
assignStackValue(assign.target)
} }
} }
} }

View File

@ -1724,7 +1724,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
} }
} }
private fun inplaceBooleanNot(target: AsmAssignTarget, dt: DataType) { internal fun inplaceBooleanNot(target: AsmAssignTarget, dt: DataType) {
when (dt) { when (dt) {
DataType.UBYTE -> { DataType.UBYTE -> {
when (target.kind) { when (target.kind) {
@ -1768,9 +1768,9 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
} }
} }
} }
TargetStorageKind.ARRAY -> throw AssemblyError("missing codegen for in-place not of ubyte array") TargetStorageKind.REGISTER -> TODO("missing codegen for byte reg not")
TargetStorageKind.REGISTER -> throw AssemblyError("missing codegen for reg not") TargetStorageKind.STACK -> TODO("missing codegen for byte stack not")
TargetStorageKind.STACK -> throw AssemblyError("missing codegen for stack not") else -> throw AssemblyError("missing codegen for in-place not of ubyte ${target.kind}")
} }
} }
DataType.UWORD -> { DataType.UWORD -> {
@ -1786,17 +1786,17 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
lsr a lsr a
sta ${target.asmVarname}+1""") sta ${target.asmVarname}+1""")
} }
TargetStorageKind.MEMORY -> throw AssemblyError("no asm gen for uword-memory not") TargetStorageKind.MEMORY -> TODO("no asm gen for uword-memory not")
TargetStorageKind.ARRAY -> throw AssemblyError("missing codegen for in-place not of uword array") TargetStorageKind.REGISTER -> TODO("missing codegen for word reg not")
TargetStorageKind.REGISTER -> throw AssemblyError("missing codegen for reg not") TargetStorageKind.STACK -> TODO("missing codegen for word stack not")
TargetStorageKind.STACK -> throw AssemblyError("missing codegen for stack not") else -> throw AssemblyError("missing codegen for in-place not of uword for ${target.kind}")
} }
} }
else -> throw AssemblyError("boolean-not of invalid type") else -> throw AssemblyError("boolean-not of invalid type")
} }
} }
private fun inplaceInvert(target: AsmAssignTarget, dt: DataType) { internal fun inplaceInvert(target: AsmAssignTarget, dt: DataType) {
when (dt) { when (dt) {
DataType.UBYTE -> { DataType.UBYTE -> {
when (target.kind) { when (target.kind) {
@ -1831,9 +1831,16 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
} }
} }
} }
TargetStorageKind.ARRAY -> throw AssemblyError("missing codegen for in-place invert ubyte array") TargetStorageKind.REGISTER -> {
TargetStorageKind.REGISTER -> throw AssemblyError("missing codegen for reg invert") when(target.register!!) {
TargetStorageKind.STACK -> throw AssemblyError("missing codegen for stack invert") RegisterOrPair.A -> asmgen.out(" eor #255")
RegisterOrPair.X -> asmgen.out(" txa | eor #255 | tax")
RegisterOrPair.Y -> asmgen.out(" tya | eor #255 | tay")
else -> throw AssemblyError("invalid reg dt for byte invert")
}
}
TargetStorageKind.STACK -> TODO("missing codegen for byte stack invert")
else -> throw AssemblyError("missing codegen for in-place invert ubyte for ${target.kind}")
} }
} }
DataType.UWORD -> { DataType.UWORD -> {
@ -1847,17 +1854,27 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
eor #255 eor #255
sta ${target.asmVarname}+1""") sta ${target.asmVarname}+1""")
} }
TargetStorageKind.MEMORY -> throw AssemblyError("no asm gen for uword-memory invert") TargetStorageKind.REGISTER -> {
TargetStorageKind.ARRAY -> throw AssemblyError("missing codegen for in-place invert uword array") when(target.register!!) {
TargetStorageKind.REGISTER -> throw AssemblyError("missing codegen for reg invert") RegisterOrPair.AX -> asmgen.out(" pha | txa | eor #255 | tax | pla | eor #255")
TargetStorageKind.STACK -> throw AssemblyError("missing codegen for stack invert") RegisterOrPair.AY -> asmgen.out(" pha | tya | eor #255 | tay | pla | eor #255")
RegisterOrPair.XY -> asmgen.out(" txa | eor #255 | tax | tya | eor #255 | tay")
in Cx16VirtualRegisters -> {
TODO("codegen for cx16 word register invert")
}
else -> throw AssemblyError("invalid reg dt for word invert")
}
}
TargetStorageKind.MEMORY -> TODO("no asm gen for uword-memory invert")
TargetStorageKind.STACK -> TODO("missing codegen for word stack invert")
else -> throw AssemblyError("missing codegen for in-place invert uword for ${target.kind}")
} }
} }
else -> throw AssemblyError("invert of invalid type") else -> throw AssemblyError("invert of invalid type")
} }
} }
private fun inplaceNegate(target: AsmAssignTarget, dt: DataType) { internal fun inplaceNegate(target: AsmAssignTarget, dt: DataType) {
when (dt) { when (dt) {
DataType.BYTE -> { DataType.BYTE -> {
when (target.kind) { when (target.kind) {
@ -1868,10 +1885,10 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
sbc ${target.asmVarname} sbc ${target.asmVarname}
sta ${target.asmVarname}""") sta ${target.asmVarname}""")
} }
TargetStorageKind.MEMORY -> throw AssemblyError("can't in-place negate memory ubyte") TargetStorageKind.REGISTER -> TODO("missing codegen for byte reg negate")
TargetStorageKind.ARRAY -> throw AssemblyError("missing codegen for in-place negate byte array") TargetStorageKind.MEMORY -> TODO("can't in-place negate memory ubyte")
TargetStorageKind.REGISTER -> throw AssemblyError("missing codegen for reg negate") TargetStorageKind.STACK -> TODO("missing codegen for byte stack negate")
TargetStorageKind.STACK -> throw AssemblyError("missing codegen for stack negate") else -> throw AssemblyError("missing codegen for in-place negate byte array")
} }
} }
DataType.WORD -> { DataType.WORD -> {
@ -1886,10 +1903,10 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
sbc ${target.asmVarname}+1 sbc ${target.asmVarname}+1
sta ${target.asmVarname}+1""") sta ${target.asmVarname}+1""")
} }
TargetStorageKind.ARRAY -> throw AssemblyError("missing codegen for in-place negate word array") TargetStorageKind.REGISTER -> TODO("missing codegen for word reg negate")
TargetStorageKind.MEMORY -> throw AssemblyError("no asm gen for word memory negate") TargetStorageKind.MEMORY -> TODO("no asm gen for word memory negate")
TargetStorageKind.REGISTER -> throw AssemblyError("missing codegen for reg negate") TargetStorageKind.STACK -> TODO("missing codegen for word stack negate")
TargetStorageKind.STACK -> throw AssemblyError("missing codegen for stack negate") else -> throw AssemblyError("missing codegen for in-place negate word array")
} }
} }
DataType.FLOAT -> { DataType.FLOAT -> {
@ -1902,9 +1919,10 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
sta ${target.asmVarname}+1 sta ${target.asmVarname}+1
""") """)
} }
TargetStorageKind.ARRAY -> throw AssemblyError("missing codegen for in-place negate float array") TargetStorageKind.REGISTER -> TODO("missing codegen for float reg negate")
TargetStorageKind.STACK -> throw AssemblyError("missing codegen for stack float negate") TargetStorageKind.MEMORY -> TODO("missing codegen for float memory negate")
else -> throw AssemblyError("weird target kind for float") TargetStorageKind.STACK -> TODO("missing codegen for stack float negate")
else -> throw AssemblyError("weird target kind for inplace negate float ${target.kind}")
} }
} }
else -> throw AssemblyError("negate of invalid type") else -> throw AssemblyError("negate of invalid type")

View File

@ -244,8 +244,8 @@ internal class AstChecker(private val program: Program,
if(subroutine.name in BuiltinFunctions) if(subroutine.name in BuiltinFunctions)
err("cannot redefine a built-in function") err("cannot redefine a built-in function")
if(subroutine.parameters.size>16) if(subroutine.parameters.size>6 && !subroutine.isAsmSubroutine)
err("subroutines are limited to 16 parameters") errors.warn("subroutine has a large number of parameters, this slows down code execution a lot", subroutine.position)
val uniqueNames = subroutine.parameters.asSequence().map { it.name }.toSet() val uniqueNames = subroutine.parameters.asSequence().map { it.name }.toSet()
if(uniqueNames.size!=subroutine.parameters.size) if(uniqueNames.size!=subroutine.parameters.size)

View File

@ -4,22 +4,26 @@
main { main {
sub start() { sub start() {
; uword xx=$2000 uword xx=$2000
@(~xx) *= 2
; ubyte yy=$30 ; ubyte yy=$30
; ubyte zz=9 ; ubyte zz=9
; ; sys.memset(xx+200, yy*2, zz+yy) ; sys.memset(xx+200, yy*2, ~yy)
; ;
; @($c030) = 10 ; @($c030) = 10
; @($c000+yy) *= 2 ; @(~xx) *= 2
; txt.print_ub(@($c030)) ; txt.print_ub(@($c030))
;
; float f1 = 1111.11
; float f2 = 2222.22
; float[] fa = [2222.22, 3333.33]
;
; swap(f1, fa[1])
; floats.print_f(f1)
; txt.nl()
; floats.print_f(fa[1])
float f1 = 1111.11
float f2 = 2222.22
float[] fa = [2222.22, 3333.33]
swap(f1, fa[1])
floats.print_f(f1)
txt.nl()
floats.print_f(fa[1])
} }
} }