diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/IfElseAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/IfElseAsmGen.kt index c4b7d4e48..3a875ce20 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/IfElseAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/IfElseAsmGen.kt @@ -1019,6 +1019,14 @@ _jump jmp ($asmLabel) val varname = asmgen.asmVariableName(value) asmgen.out(" lda $varname+1") } + is PtAddressOf -> { + if(value.isFromArrayElement) { + asmgen.assignExpressionToRegister(value, RegisterOrPair.AY, true) + asmgen.out(" cpy #0") + } else { + asmgen.out(" lda #>${asmgen.asmVariableName(value.identifier)}") + } + } else -> { asmgen.assignExpressionToRegister(value, RegisterOrPair.AY, true) asmgen.out(" cpy #0") @@ -1217,22 +1225,22 @@ _jump jmp ($asmLabel) // special case for (u)word == X and (u)word != X - fun translateLoadFromVarNotEquals(varname: String) { + fun translateNotEquals(valueLsb: String, valueMsb: String) { if(jump!=null) { val (asmLabel, indirect) = asmgen.getJumpTarget(jump) if(indirect) { asmgen.out(""" - cmp $varname + cmp $valueLsb bne + - cpy $varname+1 + cpy $valueMsb beq ++ + jmp ($asmLabel) +""") } else { asmgen.out(""" - cmp $varname + cmp $valueLsb bne $asmLabel - cpy $varname+1 + cpy $valueMsb bne $asmLabel""") } asmgen.translate(stmt.elseScope) @@ -1242,9 +1250,9 @@ _jump jmp ($asmLabel) // if and else blocks val elseLabel = asmgen.makeLabel("else") asmgen.out(""" - cmp $varname + cmp $valueLsb bne + - cpy $varname+1 + cpy $valueMsb beq $elseLabel +""") asmgen.translate(stmt.ifScope) @@ -1254,9 +1262,9 @@ _jump jmp ($asmLabel) } else { // no else block asmgen.out(""" - cmp $varname + cmp $valueLsb bne + - cpy $varname+1 + cpy $valueMsb beq $afterIfLabel +""") asmgen.translate(stmt.ifScope) @@ -1265,22 +1273,22 @@ _jump jmp ($asmLabel) } } - fun translateLoadFromVarEquals(varname: String) { + fun translateEquals(valueLsb: String, valueMsb: String) { return if(jump!=null) { val (asmLabel, indirect) = asmgen.getJumpTarget(jump) if(indirect) { asmgen.out(""" - cmp $varname + cmp $valueLsb bne + - cpy $varname+1 + cpy $valueMsb bne + jmp ($asmLabel) +""") } else { asmgen.out(""" - cmp $varname + cmp $valueLsb bne + - cpy $varname+1 + cpy $valueMsb beq $asmLabel +""") } @@ -1291,9 +1299,9 @@ _jump jmp ($asmLabel) // if and else blocks val elseLabel = asmgen.makeLabel("else") asmgen.out(""" - cmp $varname + cmp $valueLsb bne $elseLabel - cpy $varname+1 + cpy $valueMsb bne $elseLabel""") asmgen.translate(stmt.ifScope) asmgen.jmp(afterIfLabel, false) @@ -1302,9 +1310,9 @@ _jump jmp ($asmLabel) } else { // no else block asmgen.out(""" - cmp $varname + cmp $valueLsb bne $afterIfLabel - cpy $varname+1 + cpy $valueMsb bne $afterIfLabel""") asmgen.translate(stmt.ifScope) } @@ -1321,14 +1329,28 @@ _jump jmp ($asmLabel) val offset = constIndex * program.memsizer.memorySize(left.type) if(offset<256) { val varName = asmgen.asmVariableName(left.variable) - return translateLoadFromVarNotEquals("$varName+$offset") + return translateNotEquals("$varName+$offset", "$varName+$offset+1") } } fallbackTranslate(stmt, false) } is PtIdentifier -> { asmgen.assignExpressionToRegister(right, RegisterOrPair.AY, signed) - return translateLoadFromVarNotEquals(asmgen.asmVariableName(left)) + val varname = asmgen.asmVariableName(left) + return translateNotEquals(varname, varname+"+1") + } + is PtAddressOf -> { + if(left.isFromArrayElement) + fallbackTranslate(stmt, false) + else { + if(left.isFromArrayElement) + fallbackTranslate(stmt, false) + else { + asmgen.assignExpressionToRegister(right, RegisterOrPair.AY, signed) + val varname = asmgen.asmVariableName(left.identifier) + return translateNotEquals("#<$varname", "#>$varname") + } + } } else -> fallbackTranslate(stmt, false) } @@ -1341,14 +1363,24 @@ _jump jmp ($asmLabel) val offset = constIndex * program.memsizer.memorySize(left.type) if(offset<256) { val varName = asmgen.asmVariableName(left.variable) - return translateLoadFromVarEquals("$varName+$offset") + return translateEquals("$varName+$offset", "$varName+$offset+1") } } fallbackTranslate(stmt, false) } is PtIdentifier -> { asmgen.assignExpressionToRegister(right, RegisterOrPair.AY, signed) - return translateLoadFromVarEquals(asmgen.asmVariableName(left)) + val varname = asmgen.asmVariableName(left) + return translateEquals(varname, varname+"+1") + } + is PtAddressOf -> { + if(left.isFromArrayElement) + fallbackTranslate(stmt, false) + else { + asmgen.assignExpressionToRegister(right, RegisterOrPair.AY, signed) + val varname = asmgen.asmVariableName(left.identifier) + return translateEquals("#<$varname", "#>$varname") + } } else -> fallbackTranslate(stmt, false) } diff --git a/compiler/src/prog8/compiler/astprocessing/BeforeAsmAstChanger.kt b/compiler/src/prog8/compiler/astprocessing/BeforeAsmAstChanger.kt index 1a574cafb..b090a0845 100644 --- a/compiler/src/prog8/compiler/astprocessing/BeforeAsmAstChanger.kt +++ b/compiler/src/prog8/compiler/astprocessing/BeforeAsmAstChanger.kt @@ -131,4 +131,37 @@ internal class BeforeAsmAstChanger(val program: Program, private val options: Co return noModifications } + + override fun after(expr: BinaryExpression, parent: Node): Iterable { + if(options.compTarget.name!=VMTarget.NAME) { + val rightNum = expr.right.constValue(program) + if(rightNum!=null && rightNum.type in IntegerDatatypes) { + //val signed = expr.left.inferType(program).getOr(DataType.UNDEFINED) in SignedDatatypes + when(expr.operator) { + ">" -> { + // X>N -> X>=N+1, easier to do in 6502 + // TODO check if useful for words as well + val maximum = if(rightNum.type in ByteDatatypes) 255 else 65535 + if(rightNum.number=", NumericLiteral(rightNum.type, numPlusOne.toDouble(), rightNum.position), expr.position) + return listOf(IAstModification.ReplaceNode(expr, newExpr, parent)) + } + } + "<=" -> { + // X<=N -> X X<=N-1 -X > N --> X>=N+1 etc etc some yield shorter code!! - +optimize signed word wordGreaterValue, wordLessEqualsValue (can it be without scratch vars?) +optimize signed word wordGreaterZero, wordLessEqualsZero (by comparing msb/lsb separately?) verify ifelse codegens to be shortest code: (some are using too many scratch vars?) uword >= @@ -18,9 +14,11 @@ word > word <= word < +explore possible optimizations for words when comparing to a constant number (BeforeAsmAstChanger) + floatparse is a bit larger -testgfx2 is a bit larger +testgfx2 is a quite a bit larger amiga is a bit larger halloween is 1 byte larger rockrunner is bigger than on 10.1 diff --git a/examples/test.p8 b/examples/test.p8 index 5769b5384..a3e0d6deb 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -5,34 +5,14 @@ main { sub start() { - uword @shared wptr - str buffer=" " - - ; TODO: these generate LARGE code - while wptr!=&buffer - cx16.r0L++ - while wptr==&buffer - cx16.r0L++ - - ; ... these are fine: - while wptr!=cx16.r0 - cx16.r0L++ - while wptr==cx16.r0 - cx16.r0L++ - - - if ub() > 5 - cx16.r0L++ - - if ub() < 5 - cx16.r0L++ - - if sb() > 5 - cx16.r0L++ - - if sb() < 5 - cx16.r0L++ - + if cx16.r0sL > 10 + cx16.r1L++ + if cx16.r0sL >= 10 + cx16.r1L++ + if cx16.r0sL < 10 + cx16.r1L++ + if cx16.r0sL <= 10 + cx16.r1L++ } sub ub() -> ubyte {