diff --git a/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt index 4843633e4..2bd9f36f6 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/ExpressionsAsmGen.kt @@ -1223,6 +1223,7 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge } private fun translateExpression(expr: BinaryExpression) { + // TODO needs to use optimized assembly generation like the assignment instructions. But avoid code duplication.... rewrite all expressions into assignment form? val leftIDt = expr.left.inferType(program) val rightIDt = expr.right.inferType(program) if(!leftIDt.isKnown || !rightIDt.isKnown) @@ -1232,6 +1233,106 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge val rightDt = rightIDt.typeOrElse(DataType.STRUCT) // see if we can apply some optimized routines when(expr.operator) { + "+" -> { + if(leftDt in IntegerDatatypes && rightDt in IntegerDatatypes) { + val leftVal = expr.left.constValue(program)?.number?.toInt() + val rightVal = expr.right.constValue(program)?.number?.toInt() + if (leftVal!=null && leftVal in -4..4) { + translateExpression(expr.right) + if(rightDt in ByteDatatypes) { + val incdec = if(leftVal<0) "dec" else "inc" + repeat(leftVal.absoluteValue) { + asmgen.out(" $incdec P8ESTACK_LO,x") + } + } else { + // word + if(leftVal<0) { + repeat(leftVal.absoluteValue) { + asmgen.out(""" + lda P8ESTACK_LO+1,x + bne + + dec P8ESTACK_HI+1,x ++ dec P8ESTACK_LO+1,x""") + } + } else { + repeat(leftVal) { + asmgen.out(""" + inc P8ESTACK_LO+1,x + bne + + inc P8ESTACK_HI+1,x ++""") + } + } + } + return + } + else if (rightVal!=null && rightVal in -4..4) + { + translateExpression(expr.left) + if(leftDt in ByteDatatypes) { + val incdec = if(rightVal<0) "dec" else "inc" + repeat(rightVal.absoluteValue) { + asmgen.out(" $incdec P8ESTACK_LO,x") + } + } else { + // word + if(rightVal<0) { + repeat(rightVal.absoluteValue) { + asmgen.out(""" + lda P8ESTACK_LO+1,x + bne + + dec P8ESTACK_HI+1,x ++ dec P8ESTACK_LO+1,x""") + } + } else { + repeat(rightVal) { + asmgen.out(""" + inc P8ESTACK_LO+1,x + bne + + inc P8ESTACK_HI+1,x ++""") + } + } + } + return + } + } + } + "-" -> { + if(leftDt in IntegerDatatypes && rightDt in IntegerDatatypes) { + val rightVal = expr.right.constValue(program)?.number?.toInt() + if (rightVal!=null && rightVal in -4..4) + { + translateExpression(expr.left) + if(leftDt in ByteDatatypes) { + val incdec = if(rightVal<0) "inc" else "dec" + repeat(rightVal.absoluteValue) { + asmgen.out(" $incdec P8ESTACK_LO,x") + } + } else { + // word + if(rightVal>0) { + repeat(rightVal.absoluteValue) { + asmgen.out(""" + lda P8ESTACK_LO+1,x + bne + + dec P8ESTACK_HI+1,x ++ dec P8ESTACK_LO+1,x""") + } + } else { + repeat(rightVal) { + asmgen.out(""" + inc P8ESTACK_LO+1,x + bne + + inc P8ESTACK_HI+1,x ++""") + } + } + } + return + } + } + } ">>" -> { translateExpression(expr.left) val amount = expr.right.constValue(program)?.number?.toInt() @@ -1313,6 +1414,16 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge if(value!=null) { if(rightDt in IntegerDatatypes) { val amount = value.number.toInt() + if(amount==2) { + // optimize x*2 common case + translateExpression(expr.left) + if(leftDt in ByteDatatypes) { + asmgen.out(" asl P8ESTACK_LO,x") + } else { + asmgen.out(" asl P8ESTACK_LO,x | rol P8ESTACK_HI,x") + } + return + } when(rightDt) { DataType.UBYTE -> { if(amount in asmgen.optimizedByteMultiplications) { @@ -1357,15 +1468,31 @@ internal class ExpressionsAsmGen(private val program: Program, private val asmge } } } + "/" -> { + if(leftDt in IntegerDatatypes && rightDt in IntegerDatatypes) { + val rightVal = expr.right.constValue(program)?.number?.toInt() + if(rightVal!=null && rightVal==2) { + translateExpression(expr.left) + when(leftDt) { + DataType.UBYTE -> asmgen.out(" lsr P8ESTACK_LO+1,x") + DataType.BYTE -> asmgen.out(" asl P8ESTACK_LO+1,x | ror P8ESTACK_LO+1,x") + DataType.UWORD -> asmgen.out(" lsr P8ESTACK_HI+1,x | ror P8ESTACK_LO+1,x") + DataType.WORD -> asmgen.out(" asl P8ESTACK_HI+1,x | ror P8ESTACK_HI+1,x | ror P8ESTACK_LO+1,x") + else -> throw AssemblyError("wrong dt") + } + return + } + } + } } - // the general, non-optimized cases - translateExpression(expr.left) - translateExpression(expr.right) if((leftDt in ByteDatatypes && rightDt !in ByteDatatypes) || (leftDt in WordDatatypes && rightDt !in WordDatatypes)) throw AssemblyError("binary operator ${expr.operator} left/right dt not identical") + // the general, non-optimized cases TODO optimize more cases.... + translateExpression(expr.left) + translateExpression(expr.right) if(leftDt==DataType.STR && rightDt==DataType.STR && expr.operator in comparisonOperators) { translateCompareStrings(expr.operator) } diff --git a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt index f0c009943..073cb2939 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt @@ -668,7 +668,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, private fun inplaceModification_word_litval_to_variable(name: String, dt: DataType, operator: String, value: Int) { when (operator) { // note: ** (power) operator requires floats. - // TODO use these + and - optimizations in the expressionAsmGenerator as well. **************************************** "+" -> { when { value==0 -> {} @@ -683,6 +682,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, value==0x0100 -> asmgen.out(" inc $name+1") value==0x0200 -> asmgen.out(" inc $name+1 | inc $name+1") value==0x0300 -> asmgen.out(" inc $name+1 | inc $name+1 | inc $name+1") + value==0x0400 -> asmgen.out(" inc $name+1 | inc $name+1 | inc $name+1 | inc $name+1") value and 255==0 -> asmgen.out(" lda $name+1 | clc | adc #>$value | sta $name+1") else -> asmgen.out(""" lda $name @@ -708,6 +708,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, value==0x0100 -> asmgen.out(" dec $name+1") value==0x0200 -> asmgen.out(" dec $name+1 | dec $name+1") value==0x0300 -> asmgen.out(" dec $name+1 | dec $name+1 | dec $name+1") + value==0x0400 -> asmgen.out(" dec $name+1 | dec $name+1 | dec $name+1 | dec $name+1") value and 255==0 -> asmgen.out(" lda $name+1 | sec | sbc #>$value | sta $name+1") else -> asmgen.out(""" lda $name diff --git a/examples/test.p8 b/examples/test.p8 index d8c687334..70d714146 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -7,18 +7,24 @@ main { sub start() { - uword vv = 1111 - vv *= 23 - txt.print_uw(vv) + uword vv = $1111 + uword vv2 + vv2 = vv2+(vv/2) + vv2 = vv2+(vv - 1) + vv2 = vv2+(vv + $0200) + vv2 = vv2+(vv - $0400) + txt.print_uw(vv2) txt.chrout('\n') - word ww = -1111 - ww *= 23 - txt.print_w(ww) + word ww = -$1111 + word ww2 = 0 + ww2 = ww2 + ww + $0200 + ww2 = ww2 +ww - $0400 + txt.print_w(ww2) txt.chrout('\n') - ww = -1111 - ww *= -23 - txt.print_w(ww) + ww2= ww2 + ww + -$0200 + ww2= ww2 + ww - -$0400 + txt.print_w(ww2) txt.chrout('\n') testX()