diff --git a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt index 28cdbf59d..acd5043bc 100644 --- a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt +++ b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/AsmGen.kt @@ -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) = expressionsAsmGen.translateExpression(expression) diff --git a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/ExpressionsAsmGen.kt b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/ExpressionsAsmGen.kt index 2d2d4e329..189db373a 100644 --- a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/ExpressionsAsmGen.kt +++ b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/ExpressionsAsmGen.kt @@ -14,6 +14,7 @@ import kotlin.math.absoluteValue 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) { if (this.asmgen.options.slowCodegenWarnings) { asmgen.errors.warn("slow stack evaluation used for expression $expression", expression.position) diff --git a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/FunctionCallAsmGen.kt b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/FunctionCallAsmGen.kt index 75ec7b42d..8d86c7676 100644 --- a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/FunctionCallAsmGen.kt +++ b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/FunctionCallAsmGen.kt @@ -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). - 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... - // println("*** ALT PARAM PASSING FOR ASMSUB $stmt $arg") // TODO DEBUG - val dt = arg.inferType(program).getOr(DataType.UNDEFINED) - val target = AsmAssignTarget(TargetStorageKind.STACK, program, asmgen, dt, sub) - asmgen.assignExpressionTo(arg, target) - } else { - asmgen.translateExpression(arg) // TODO GET RID OF THIS, if the above actually produces compact code - } - } + for (arg in stmt.args.reversed()) + asmgen.translateExpression(arg) + + // TODO here's an alternative to the above, but for now generates bigger code due to intermediate register steps: +// for (arg in stmt.args.reversed()) { +// // note this stuff below is needed to (eventually) avoid calling asmgen.translateExpression() +// // TODO also This STILL requires the translateNormalAssignment() to be fixed to avoid stack eval for expressions... +// val dt = arg.inferType(program).getOr(DataType.UNDEFINED) +// asmgen.assignExpressionTo(arg, AsmAssignTarget(TargetStorageKind.STACK, program, asmgen, dt, sub)) +// } var argForCarry: IndexedValue>? = null var argForXregister: IndexedValue>? = null diff --git a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt index 9783f4625..b0956ba83 100644 --- a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt +++ b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AssignmentAsmGen.kt @@ -33,6 +33,11 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen } fun translateNormalAssignment(assign: AsmAssignment) { + if(assign.isAugmentable) { + augmentableAsmGen.translate(assign) + return + } + when(assign.source.kind) { SourceStorageKind.LITERALNUMBER -> { // 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 -> { // Everything else just evaluate via the stack. // (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) if (assign.target.datatype in WordDatatypes && assign.source.datatype in ByteDatatypes) 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) } SourceStorageKind.STACK -> { - assignStackValue(assign.target) + if(assign.target.kind!=TargetStorageKind.STACK || assign.target.datatype != assign.source.datatype) + assignStackValue(assign.target) } } } diff --git a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt index 99b35ca94..ab8e5718d 100644 --- a/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt +++ b/codeGeneration/src/prog8/compiler/target/cpu6502/codegen/assignment/AugmentableAssignmentAsmGen.kt @@ -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) { DataType.UBYTE -> { 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 -> throw AssemblyError("missing codegen for reg not") - TargetStorageKind.STACK -> throw AssemblyError("missing codegen for stack not") + TargetStorageKind.REGISTER -> TODO("missing codegen for byte reg not") + TargetStorageKind.STACK -> TODO("missing codegen for byte stack not") + else -> throw AssemblyError("missing codegen for in-place not of ubyte ${target.kind}") } } DataType.UWORD -> { @@ -1786,17 +1786,17 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, lsr a sta ${target.asmVarname}+1""") } - TargetStorageKind.MEMORY -> throw AssemblyError("no asm gen for uword-memory not") - TargetStorageKind.ARRAY -> throw AssemblyError("missing codegen for in-place not of uword array") - TargetStorageKind.REGISTER -> throw AssemblyError("missing codegen for reg not") - TargetStorageKind.STACK -> throw AssemblyError("missing codegen for stack not") + TargetStorageKind.MEMORY -> TODO("no asm gen for uword-memory not") + TargetStorageKind.REGISTER -> TODO("missing codegen for word reg not") + TargetStorageKind.STACK -> TODO("missing codegen for word stack not") + else -> throw AssemblyError("missing codegen for in-place not of uword for ${target.kind}") } } else -> throw AssemblyError("boolean-not of invalid type") } } - private fun inplaceInvert(target: AsmAssignTarget, dt: DataType) { + internal fun inplaceInvert(target: AsmAssignTarget, dt: DataType) { when (dt) { DataType.UBYTE -> { 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 -> throw AssemblyError("missing codegen for reg invert") - TargetStorageKind.STACK -> throw AssemblyError("missing codegen for stack invert") + TargetStorageKind.REGISTER -> { + when(target.register!!) { + 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 -> { @@ -1847,17 +1854,27 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, eor #255 sta ${target.asmVarname}+1""") } - TargetStorageKind.MEMORY -> throw AssemblyError("no asm gen for uword-memory invert") - TargetStorageKind.ARRAY -> throw AssemblyError("missing codegen for in-place invert uword array") - TargetStorageKind.REGISTER -> throw AssemblyError("missing codegen for reg invert") - TargetStorageKind.STACK -> throw AssemblyError("missing codegen for stack invert") + TargetStorageKind.REGISTER -> { + when(target.register!!) { + RegisterOrPair.AX -> asmgen.out(" pha | txa | eor #255 | tax | pla | eor #255") + 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") } } - private fun inplaceNegate(target: AsmAssignTarget, dt: DataType) { + internal fun inplaceNegate(target: AsmAssignTarget, dt: DataType) { when (dt) { DataType.BYTE -> { when (target.kind) { @@ -1868,10 +1885,10 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, sbc ${target.asmVarname} sta ${target.asmVarname}""") } - TargetStorageKind.MEMORY -> throw AssemblyError("can't in-place negate memory ubyte") - TargetStorageKind.ARRAY -> throw AssemblyError("missing codegen for in-place negate byte array") - TargetStorageKind.REGISTER -> throw AssemblyError("missing codegen for reg negate") - TargetStorageKind.STACK -> throw AssemblyError("missing codegen for stack negate") + TargetStorageKind.REGISTER -> TODO("missing codegen for byte reg negate") + TargetStorageKind.MEMORY -> TODO("can't in-place negate memory ubyte") + TargetStorageKind.STACK -> TODO("missing codegen for byte stack negate") + else -> throw AssemblyError("missing codegen for in-place negate byte array") } } DataType.WORD -> { @@ -1886,10 +1903,10 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, sbc ${target.asmVarname}+1 sta ${target.asmVarname}+1""") } - TargetStorageKind.ARRAY -> throw AssemblyError("missing codegen for in-place negate word array") - TargetStorageKind.MEMORY -> throw AssemblyError("no asm gen for word memory negate") - TargetStorageKind.REGISTER -> throw AssemblyError("missing codegen for reg negate") - TargetStorageKind.STACK -> throw AssemblyError("missing codegen for stack negate") + TargetStorageKind.REGISTER -> TODO("missing codegen for word reg negate") + TargetStorageKind.MEMORY -> TODO("no asm gen for word memory negate") + TargetStorageKind.STACK -> TODO("missing codegen for word stack negate") + else -> throw AssemblyError("missing codegen for in-place negate word array") } } DataType.FLOAT -> { @@ -1902,9 +1919,10 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, sta ${target.asmVarname}+1 """) } - TargetStorageKind.ARRAY -> throw AssemblyError("missing codegen for in-place negate float array") - TargetStorageKind.STACK -> throw AssemblyError("missing codegen for stack float negate") - else -> throw AssemblyError("weird target kind for float") + TargetStorageKind.REGISTER -> TODO("missing codegen for float reg negate") + TargetStorageKind.MEMORY -> TODO("missing codegen for float memory negate") + 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") diff --git a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt index 840e6327b..1feda02f3 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt @@ -244,8 +244,8 @@ internal class AstChecker(private val program: Program, if(subroutine.name in BuiltinFunctions) err("cannot redefine a built-in function") - if(subroutine.parameters.size>16) - err("subroutines are limited to 16 parameters") + if(subroutine.parameters.size>6 && !subroutine.isAsmSubroutine) + 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() if(uniqueNames.size!=subroutine.parameters.size) diff --git a/examples/test.p8 b/examples/test.p8 index 25383b5cc..b7eeb5840 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -4,22 +4,26 @@ main { sub start() { -; uword xx=$2000 + uword xx=$2000 + + @(~xx) *= 2 + ; ubyte yy=$30 ; ubyte zz=9 -; ; sys.memset(xx+200, yy*2, zz+yy) +; sys.memset(xx+200, yy*2, ~yy) ; ; @($c030) = 10 -; @($c000+yy) *= 2 +; @(~xx) *= 2 ; 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]) } }