From ef7744dbdaa6f264c171e68473fa020632a3b1d1 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Fri, 21 Aug 2020 04:02:10 +0200 Subject: [PATCH] asm fix --- compiler/res/prog8lib/math.asm | 1 + compiler/res/prog8lib/prog8lib.asm | 4 +- .../target/c64/codegen/AssignmentAsmGen.kt | 64 ++--- .../codegen/AugmentableAssignmentAsmGen.kt | 243 +++++++++++------- examples/test.p8 | 77 +----- 5 files changed, 198 insertions(+), 191 deletions(-) diff --git a/compiler/res/prog8lib/math.asm b/compiler/res/prog8lib/math.asm index 5c6a1382d..34237e5a9 100644 --- a/compiler/res/prog8lib/math.asm +++ b/compiler/res/prog8lib/math.asm @@ -52,6 +52,7 @@ multiply_words .proc ; -- multiply two 16-bit words into a 32-bit result (signed and unsigned) ; input: A/Y = first 16-bit number, c64.SCRATCH_ZPWORD1 in ZP = second 16-bit number ; output: multiply_words.result 4-bytes/32-bits product, LSB order (low-to-high) + ; clobbers: A sta c64.SCRATCH_ZPWORD2 sty c64.SCRATCH_ZPWORD2+1 diff --git a/compiler/res/prog8lib/prog8lib.asm b/compiler/res/prog8lib/prog8lib.asm index 22f0c3895..b3c60545a 100644 --- a/compiler/res/prog8lib/prog8lib.asm +++ b/compiler/res/prog8lib/prog8lib.asm @@ -55,7 +55,7 @@ write_byte_to_address_on_stack .proc ldy c64.ESTACK_HI+1,x sty c64.SCRATCH_ZPWORD2+1 ldy #0 - lda (c64.SCRATCH_ZPWORD2),y + sta (c64.SCRATCH_ZPWORD2),y rts .pend @@ -343,9 +343,7 @@ mul_word .proc sta c64.SCRATCH_ZPWORD1+1 lda c64.ESTACK_LO+1,x ldy c64.ESTACK_HI+1,x - stx c64.SCRATCH_ZPREGX jsr math.multiply_words - ldx c64.SCRATCH_ZPREGX lda math.multiply_words.result sta c64.ESTACK_LO+1,x lda math.multiply_words.result+1 diff --git a/compiler/src/prog8/compiler/target/c64/codegen/AssignmentAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/AssignmentAsmGen.kt index bddda813a..33e26498f 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/AssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/AssignmentAsmGen.kt @@ -371,29 +371,31 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen val addressExpr = memoryAddress.addressExpression val addressLv = addressExpr as? NumericLiteralValue when { - addressLv != null -> asmgen.out(" lda $ldaInstructionArg | sta ${addressLv.number.toHex()}") + addressLv != null -> { + asmgen.out(" lda $ldaInstructionArg | sta ${addressLv.number.toHex()}") + } addressExpr is IdentifierReference -> { val pointerVarName = asmgen.asmIdentifierName(addressExpr) asmgen.out(""" - lda $pointerVarName - sta ${C64Zeropage.SCRATCH_W2} - lda $pointerVarName+1 - sta ${C64Zeropage.SCRATCH_W2+1} - lda $ldaInstructionArg - ldy #0 - sta (${C64Zeropage.SCRATCH_W2}),y""") + lda $pointerVarName + sta ${C64Zeropage.SCRATCH_W2} + lda $pointerVarName+1 + sta ${C64Zeropage.SCRATCH_W2+1} + lda $ldaInstructionArg + ldy #0 + sta (${C64Zeropage.SCRATCH_W2}),y""") } else -> { asmgen.translateExpression(addressExpr) asmgen.out(""" - inx - lda $ESTACK_LO_HEX,x - sta ${C64Zeropage.SCRATCH_W2} - lda $ESTACK_HI_HEX,x - sta ${C64Zeropage.SCRATCH_W2+1} - lda $ldaInstructionArg - ldy #0 - sta (${C64Zeropage.SCRATCH_W2}),y""") + inx + lda $ESTACK_LO_HEX,x + sta ${C64Zeropage.SCRATCH_W2} + lda $ESTACK_HI_HEX,x + sta ${C64Zeropage.SCRATCH_W2+1} + lda $ldaInstructionArg + ldy #0 + sta (${C64Zeropage.SCRATCH_W2}),y""") } } } @@ -404,7 +406,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen val addressLv = addressExpr as? NumericLiteralValue val registerName = register.name.toLowerCase() when { - addressLv != null -> asmgen.out(" st$registerName ${addressLv.number.toHex()}") + addressLv != null -> { + asmgen.out(" st$registerName ${addressLv.number.toHex()}") + } addressExpr is IdentifierReference -> { val targetName = asmgen.asmIdentifierName(addressExpr) when (register) { @@ -413,25 +417,25 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen CpuRegister.Y -> asmgen.out(" tya") } asmgen.out(""" - ldy $targetName - sty ${C64Zeropage.SCRATCH_W1} - ldy $targetName+1 - sty ${C64Zeropage.SCRATCH_W1+1} - ldy #0 - sta (${C64Zeropage.SCRATCH_W1}),y""") + ldy $targetName + sty ${C64Zeropage.SCRATCH_W1} + ldy $targetName+1 + sty ${C64Zeropage.SCRATCH_W1+1} + ldy #0 + sta (${C64Zeropage.SCRATCH_W1}),y""") } else -> { asmgen.saveRegister(register) asmgen.translateExpression(addressExpr) asmgen.restoreRegister(CpuRegister.A) asmgen.out(""" - inx - ldy $ESTACK_LO_HEX,x - sty ${C64Zeropage.SCRATCH_W1} - ldy $ESTACK_HI_HEX,x - sty ${C64Zeropage.SCRATCH_W1+1} - ldy #0 - sta (${C64Zeropage.SCRATCH_W1}),y""") + inx + ldy $ESTACK_LO_HEX,x + sty ${C64Zeropage.SCRATCH_W1} + ldy $ESTACK_HI_HEX,x + sty ${C64Zeropage.SCRATCH_W1+1} + ldy #0 + sta (${C64Zeropage.SCRATCH_W1}),y""") } } } diff --git a/compiler/src/prog8/compiler/target/c64/codegen/AugmentableAssignmentAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/AugmentableAssignmentAsmGen.kt index d2ea5f98b..96b635334 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/AugmentableAssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/AugmentableAssignmentAsmGen.kt @@ -12,8 +12,8 @@ import prog8.compiler.target.c64.C64MachineDefinition.ESTACK_LO_PLUS1_HEX import prog8.compiler.toHex internal class AugmentableAssignmentAsmGen(private val program: Program, - private val assignmentAsmGen: AssignmentAsmGen, - private val asmgen: AsmGen) { + private val assignmentAsmGen: AssignmentAsmGen, + private val asmgen: AsmGen) { fun translate(assign: Assignment) { require(assign.isAugmentable) @@ -22,8 +22,9 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, // A = -A , A = +A, A = ~A val px = assign.value as PrefixExpression val type = px.inferType(program).typeOrElse(DataType.STRUCT) - when(px.operator) { - "+" -> {} + when (px.operator) { + "+" -> { + } "-" -> inplaceNegate(assign.target, type) "~" -> inplaceInvert(assign.target, type) "not" -> inplaceBooleanNot(assign.target, type) @@ -43,10 +44,9 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, return inplaceModification(target, binExpr.operator, binExpr.right, assign) } - if (binExpr.operator in associativeOperators) - { + if (binExpr.operator in associativeOperators) { val leftBinExpr = binExpr.left as? BinaryExpression - if (leftBinExpr!=null && binExpr.right isSameAs target) { + if (leftBinExpr != null && binExpr.right isSameAs target) { // A = 5 A return inplaceModification(target, binExpr.operator, binExpr.left, assign) } @@ -110,30 +110,30 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, val ident = value as? IdentifierReference when { - identifier!=null -> { + identifier != null -> { val name = asmgen.asmIdentifierName(identifier) val dt = identifier.inferType(program).typeOrElse(DataType.STRUCT) when (dt) { in ByteDatatypes -> { when { - valueLv!=null -> inplaceModification_byte_litval_to_variable(name, operator, valueLv) - ident!=null -> inplaceModification_byte_variable_to_variable(name, operator, ident) + valueLv != null -> inplaceModification_byte_litval_to_variable(name, dt, operator, valueLv) + ident != null -> inplaceModification_byte_variable_to_variable(name, dt, operator, ident) // TODO more specialized code for types such as memory read etc. - else -> inplaceModification_byte_value_to_variable(name, operator, value) + else -> inplaceModification_byte_value_to_variable(name, dt, operator, value) } } in WordDatatypes -> { when { - valueLv!=null -> inplaceModification_word_litval_to_variable(name, operator, valueLv) - ident!=null -> inplaceModification_word_variable_to_variable(name, operator, ident) + valueLv != null -> inplaceModification_word_litval_to_variable(name, operator, valueLv) + ident != null -> inplaceModification_word_variable_to_variable(name, operator, ident) // TODO more specialized code for types such as memory read etc. else -> inplaceModification_word_value_to_variable(name, operator, value) } } DataType.FLOAT -> { when { - valueLv!=null -> inplaceModification_float_litval_to_variable(name, operator, valueLv) - ident!=null -> inplaceModification_float_variable_to_variable(name, operator, ident) + valueLv != null -> inplaceModification_float_litval_to_variable(name, operator, valueLv) + ident != null -> inplaceModification_float_variable_to_variable(name, operator, ident) // TODO more specialized code for types such as memory read etc. else -> inplaceModification_float_value_to_variable(name, operator, value) } @@ -144,23 +144,23 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, } } } - memory!=null -> { + memory != null -> { when (memory.addressExpression) { is NumericLiteralValue -> { val addr = (memory.addressExpression as NumericLiteralValue).number.toInt() // re-use code to assign a variable, instead this time, use a direct memory address when { - valueLv!=null -> inplaceModification_byte_litval_to_variable(addr.toHex(), operator, valueLv) - ident!=null -> inplaceModification_byte_variable_to_variable(addr.toHex(), operator, ident) + valueLv != null -> inplaceModification_byte_litval_to_variable(addr.toHex(), DataType.UBYTE, operator, valueLv) + ident != null -> inplaceModification_byte_variable_to_variable(addr.toHex(), DataType.UBYTE, operator, ident) // TODO more specialized code for types such as memory read etc. - else -> inplaceModification_byte_value_to_variable(addr.toHex(), operator, value) + else -> inplaceModification_byte_value_to_variable(addr.toHex(), DataType.UBYTE, operator, value) } } is IdentifierReference -> { val name = asmgen.asmIdentifierName(memory.addressExpression as IdentifierReference) when { - valueLv!=null -> inplaceModification_byte_litval_to_memory(name, operator, valueLv) - ident!=null -> inplaceModification_byte_variable_to_memory(name, operator, ident) + valueLv != null -> inplaceModification_byte_litval_to_memory(name, operator, valueLv) + ident != null -> inplaceModification_byte_variable_to_memory(name, operator, ident) // TODO more specialized code for types such as memory read etc. else -> inplaceModification_byte_value_to_memory(name, operator, value, origAssign) } @@ -170,16 +170,16 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, asmgen.out(" jsr prog8_lib.read_byte_from_address_on_stack | sta ${C64Zeropage.SCRATCH_B1}") // the original memory byte's value is now in the scratch B1 location. when { - valueLv!=null -> inplaceModification_byte_litval_to_variable(C64Zeropage.SCRATCH_B1.toHex(), operator, valueLv) - ident!=null -> inplaceModification_byte_variable_to_variable(C64Zeropage.SCRATCH_B1.toHex(), operator, ident) + valueLv != null -> inplaceModification_byte_litval_to_variable(C64Zeropage.SCRATCH_B1.toHex(), DataType.UBYTE, operator, valueLv) + ident != null -> inplaceModification_byte_variable_to_variable(C64Zeropage.SCRATCH_B1.toHex(), DataType.UBYTE, operator, ident) // TODO more specialized code for types such as memory read etc. - else -> inplaceModification_byte_value_to_variable(C64Zeropage.SCRATCH_B1.toHex(), operator, value) + else -> inplaceModification_byte_value_to_variable(C64Zeropage.SCRATCH_B1.toHex(), DataType.UBYTE, operator, value) } asmgen.out(" lda ${C64Zeropage.SCRATCH_B1} | jsr prog8_lib.write_byte_to_address_on_stack | inx") } } } - arrayIdx!=null -> { + arrayIdx != null -> { println("TODO 3 optimize simple inplace array assignment $arrayIdx $operator= $value") assignmentAsmGen.translateOtherAssignment(origAssign) // TODO get rid of this fallback } @@ -190,7 +190,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, // this should be the last resort for code generation for this, // because the value is evaluated onto the eval stack (=slow). asmgen.translateExpression(value) - when(operator) { + when (operator) { "**" -> TODO("pow") "+" -> { asmgen.out(""" @@ -207,7 +207,18 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, """) } "-" -> { - TODO("-") + asmgen.out(""" + jsr c64flt.pop_float_fac1 + stx ${C64Zeropage.SCRATCH_REG_X} + lda #<$name + ldy #>$name + jsr c64flt.CONUPK + jsr c64flt.FSUBT + ldx #<$name + ldy #>$name + jsr c64flt.MOVMF + ldx ${C64Zeropage.SCRATCH_REG_X} + """) } "*" -> TODO()// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier "/" -> { @@ -231,10 +242,10 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, private fun inplaceModification_float_litval_to_variable(name: String, operator: String, value: Double) { val constValueName = asmgen.getFloatConst(value) - when(operator) { + when (operator) { "**" -> TODO("pow") "+" -> { - if(value==0.0) + if (value == 0.0) return asmgen.out(""" stx ${C64Zeropage.SCRATCH_REG_X} @@ -252,13 +263,26 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, """) } "-" -> { - if(value==0.0) + if (value == 0.0) return - TODO("-") + asmgen.out(""" + stx ${C64Zeropage.SCRATCH_REG_X} + lda #<$constValueName + ldy #>$constValueName + jsr c64flt.MOVFM + lda #<$name + ldy #>$name + jsr c64flt.CONUPK + jsr c64flt.FSUBT + ldx #<$name + ldy #>$name + jsr c64flt.MOVMF + ldx ${C64Zeropage.SCRATCH_REG_X} + """) } "*" -> TODO()// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier "/" -> { - if(value==0.0) + if (value == 0.0) throw AssemblyError("division by zero") TODO() // asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b") @@ -275,7 +299,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, private fun inplaceModification_byte_value_to_memory(pointername: String, operator: String, value: Expression, origAssign: Assignment) { assignmentAsmGen.translateOtherAssignment(origAssign) // TODO get rid of this fallback - TODO("Not yet implemented") + TODO("inplaceModification_byte_value_to_memory") } private fun inplaceModification_byte_variable_to_memory(pointername: String, operator: String, ident: IdentifierReference) { @@ -285,11 +309,11 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, lda $pointername ldy $pointername+1 sta ${C64Zeropage.SCRATCH_W1} - sty ${C64Zeropage.SCRATCH_W1+1} + sty ${C64Zeropage.SCRATCH_W1 + 1} ldy #0 lda (${C64Zeropage.SCRATCH_W1}),y""") } - when(operator) { + when (operator) { // note: ** (power) operator requires floats. "+" -> { loadByteFromPointerInA() @@ -331,11 +355,11 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, lda $pointername ldy $pointername+1 sta ${C64Zeropage.SCRATCH_W1} - sty ${C64Zeropage.SCRATCH_W1+1} + sty ${C64Zeropage.SCRATCH_W1 + 1} ldy #0 lda (${C64Zeropage.SCRATCH_W1}),y""") } - when(operator) { + when (operator) { // note: ** (power) operator requires floats. "+" -> { loadByteFromPointerInA() @@ -354,14 +378,14 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, // asmgen.out(" jsr prog8_lib.remainder_ub") } "<<" -> { - if(value>1) { + if (value > 1) { loadByteFromPointerInA() repeat(value.toInt()) { asmgen.out(" asl a") } asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y") } } ">>" -> { - if(value>1) { + if (value > 1) { loadByteFromPointerInA() repeat(value.toInt()) { asmgen.out(" lsr a") } asmgen.out(" sta (${C64Zeropage.SCRATCH_W1}),y") @@ -384,27 +408,41 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, } private fun inplaceModification_word_litval_to_variable(name: String, operator: String, value: Double) { - when(operator) { + when (operator) { // note: ** (power) operator requires floats. "+" -> asmgen.out(" lda $name | clc | adc #<$value | sta $name | lda $name+1 | adc #>$value | sta $name+1") "-" -> asmgen.out(" lda $name | sec | sbc #<$value | sta $name | lda $name+1 | sbc #>$value | sta $name+1") - "*" -> TODO()// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier - "/" -> TODO()// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b") + "*" -> { + // TODO what about the optimized routines? + asmgen.out(""" + lda $name + sta c64.SCRATCH_ZPWORD1 + lda $name+1 + sta c64.SCRATCH_ZPWORD1+1 + lda #<$value + ldy #>$value + jsr math.multiply_words + lda math.multiply_words.result + sta $name + lda math.multiply_words.result+1 + sta $name+1,x""") + } + "/" -> TODO("word $name /= $value")// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b") "%" -> { - TODO("word remainder") + TODO("word remainder $value") // if(types==DataType.BYTE) // throw AssemblyError("remainder of signed integers is not properly defined/implemented, use unsigned instead") // asmgen.out(" jsr prog8_lib.remainder_ub") } "<<" -> { - if(value>1) { + if (value > 1) { asmgen.out(" lda $name") TODO("word asl") asmgen.out(" sta $name") } } ">>" -> { - if(value>1) { + if (value > 1) { asmgen.out(" lda $name") TODO("word lsr") asmgen.out(" sta $name") @@ -419,7 +457,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, private fun inplaceModification_word_variable_to_variable(name: String, operator: String, ident: IdentifierReference) { val otherName = asmgen.asmIdentifierName(ident) - when(operator) { + when (operator) { // note: ** (power) operator requires floats. "+" -> asmgen.out(" lda $name | clc | adc $otherName | sta $name | lda $name+1 | adc $otherName+1 | sta $name+1") "-" -> asmgen.out(" lda $name | sec | sbc $otherName | sta $name | lda $name+1 | sbc $otherName+1 | sta $name+1") @@ -444,7 +482,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, // this should be the last resort for code generation for this, // because the value is evaluated onto the eval stack (=slow). asmgen.translateExpression(value) - when(operator) { + when (operator) { // note: ** (power) operator requires floats. "+" -> asmgen.out(" lda $name | clc | adc $ESTACK_LO_PLUS1_HEX,x | sta $name | lda $name+1 | adc $ESTACK_HI_PLUS1_HEX,x | sta $name+1") "-" -> asmgen.out(" lda $name | sec | sbc $ESTACK_LO_PLUS1_HEX,x | sta $name | lda $name+1 | sbc $ESTACK_HI_PLUS1_HEX,x | sta $name+1") @@ -466,11 +504,11 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, asmgen.out(" inx") } - private fun inplaceModification_byte_value_to_variable(name: String, operator: String, value: Expression) { + private fun inplaceModification_byte_value_to_variable(name: String, dt: DataType, operator: String, value: Expression) { // this should be the last resort for code generation for this, // because the value is evaluated onto the eval stack (=slow). asmgen.translateExpression(value) - when(operator) { + when (operator) { // note: ** (power) operator requires floats. "+" -> asmgen.out(" lda $name | clc | adc $ESTACK_LO_PLUS1_HEX,x | sta $name") "-" -> asmgen.out(" lda $name | sec | sbc $ESTACK_LO_PLUS1_HEX,x | sta $name") @@ -492,9 +530,9 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, asmgen.out(" inx") } - private fun inplaceModification_byte_variable_to_variable(name: String, operator: String, ident: IdentifierReference) { + private fun inplaceModification_byte_variable_to_variable(name: String, dt: DataType, operator: String, ident: IdentifierReference) { val otherName = asmgen.asmIdentifierName(ident) - when(operator) { + when (operator) { // note: ** (power) operator requires floats. "+" -> asmgen.out(" lda $name | clc | adc $otherName | sta $name") "-" -> asmgen.out(" lda $name | sec | sbc $otherName | sta $name") @@ -515,28 +553,45 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, } } - private fun inplaceModification_byte_litval_to_variable(name: String, operator: String, value: Double) { - when(operator) { + private fun inplaceModification_byte_litval_to_variable(name: String, dt: DataType, operator: String, value: Double) { + when (operator) { // note: ** (power) operator requires floats. "+" -> asmgen.out(" lda $name | clc | adc #$value | sta $name") "-" -> asmgen.out(" lda $name | sec | sbc #$value | sta $name") - "*" -> TODO()// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier - "/" -> TODO()// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b") + "*" -> { + // TODO what about the optimized routines? + TODO("$dt mul $name *= $value") + // asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier + } + "/" -> { + if (dt == DataType.UBYTE) { + asmgen.out(""" + lda $name + ldy #$value + jsr math.divmod_ub + sty $name + """) + } else { + // BYTE + // requires to use unsigned division and fix sign afterwards, see idiv_b in prog8lib + TODO("BYTE div $name /= $value") + } + } "%" -> { - TODO("byte remainder") + TODO("$dt remainder") // if(types==DataType.BYTE) // throw AssemblyError("remainder of signed integers is not properly defined/implemented, use unsigned instead") // asmgen.out(" jsr prog8_lib.remainder_ub") } "<<" -> { - if(value>1) { + if (value > 1) { asmgen.out(" lda $name") repeat(value.toInt()) { asmgen.out(" asl a") } asmgen.out(" sta $name") } } ">>" -> { - if(value>1) { + if (value > 1) { asmgen.out(" lda $name") repeat(value.toInt()) { asmgen.out(" lsr a") } asmgen.out(" sta $name") @@ -554,26 +609,28 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, val outerCastDt = cast.type val innerCastDt = (cast.expression as? TypecastExpression)?.type - if(innerCastDt==null) { + if (innerCastDt == null) { // simple typecast where the value is the target - when(targetDt) { - DataType.UBYTE, DataType.BYTE -> { /* byte target can't be casted to anything else at all */ } + when (targetDt) { + DataType.UBYTE, DataType.BYTE -> { /* byte target can't be casted to anything else at all */ + } DataType.UWORD, DataType.WORD -> { - when(outerCastDt) { + when (outerCastDt) { DataType.UBYTE, DataType.BYTE -> { - if(target.identifier!=null) { + if (target.identifier != null) { val name = asmgen.asmIdentifierName(target.identifier!!) asmgen.out(" lda #0 | sta $name+1") } else throw AssemblyError("weird value") } - DataType.UWORD, DataType.WORD, in IterableDatatypes -> {} + DataType.UWORD, DataType.WORD, in IterableDatatypes -> { + } DataType.FLOAT -> throw AssemblyError("incompatible cast type") else -> throw AssemblyError("weird cast type") } } DataType.FLOAT -> { - if(outerCastDt!=DataType.FLOAT) + if (outerCastDt != DataType.FLOAT) throw AssemblyError("in-place cast of a float makes no sense") } else -> throw AssemblyError("invalid cast target type") @@ -581,19 +638,19 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, } else { // typecast with nested typecast, that has the target as a value // calculate singular cast that is required - val castDt = if(outerCastDt largerThan innerCastDt) innerCastDt else outerCastDt + val castDt = if (outerCastDt largerThan innerCastDt) innerCastDt else outerCastDt val value = (cast.expression as TypecastExpression).expression val resultingCast = TypecastExpression(value, castDt, false, assign.position) inplaceCast(target, resultingCast, assign) } } - private fun inplaceBooleanNot(target: AssignTarget, dt: DataType) { + private fun inplaceBooleanNot(target: AssignTarget, dt: DataType) { val arrayIdx = target.arrayindexed val identifier = target.identifier val memory = target.memoryAddress - when(dt) { + when (dt) { DataType.UBYTE -> { when { identifier != null -> { @@ -631,7 +688,14 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, sta (${C64Zeropage.SCRATCH_W1}),y""") } else -> { - TODO("$memory") + asmgen.translateExpression(memory.addressExpression) + asmgen.out(""" + jsr prog8_lib.read_byte_from_address_on_stack + beq + + lda #1 ++ eor #1 + jsr prog8_lib.write_byte_to_address_on_stack + inx""") } } } @@ -642,7 +706,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, } DataType.UWORD -> { when { - identifier!=null -> { + identifier != null -> { val name = asmgen.asmIdentifierName(identifier) asmgen.out(""" lda $name @@ -654,8 +718,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, lsr a sta $name+1""") } - arrayIdx!=null -> TODO("in-place not of uword array") - memory!=null -> throw AssemblyError("no asm gen for uword-memory not") + arrayIdx != null -> TODO("in-place not of uword array") + memory != null -> throw AssemblyError("no asm gen for uword-memory not") } } else -> throw AssemblyError("boolean-not of invalid type") @@ -667,7 +731,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, val identifier = target.identifier val memory = target.memoryAddress - when(dt) { + when (dt) { DataType.UBYTE -> { when { identifier != null -> { @@ -699,7 +763,12 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, sta (${C64Zeropage.SCRATCH_W1}),y""") } else -> { - TODO("$memory") + asmgen.translateExpression(memory.addressExpression) + asmgen.out(""" + jsr prog8_lib.read_byte_from_address_on_stack + eor #255 + jsr prog8_lib.write_byte_to_address_on_stack + inx""") } } } @@ -710,7 +779,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, } DataType.UWORD -> { when { - identifier!=null -> { + identifier != null -> { val name = asmgen.asmIdentifierName(identifier) asmgen.out(""" lda $name @@ -720,8 +789,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, eor #255 sta $name+1""") } - arrayIdx!=null -> TODO("in-place invert uword array") - memory!=null -> throw AssemblyError("no asm gen for uword-memory invert") + arrayIdx != null -> TODO("in-place invert uword array") + memory != null -> throw AssemblyError("no asm gen for uword-memory invert") } } else -> throw AssemblyError("invert of invalid type") @@ -733,10 +802,10 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, val identifier = target.identifier val memory = target.memoryAddress - when(dt) { + when (dt) { DataType.BYTE -> { when { - identifier!=null -> { + identifier != null -> { val name = asmgen.asmIdentifierName(identifier) asmgen.out(""" lda #0 @@ -744,13 +813,13 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, sbc $name sta $name""") } - memory!=null -> throw AssemblyError("can't in-place negate memory ubyte") - arrayIdx!=null -> TODO("in-place negate byte array") + memory != null -> throw AssemblyError("can't in-place negate memory ubyte") + arrayIdx != null -> TODO("in-place negate byte array") } } DataType.WORD -> { when { - identifier!=null -> { + identifier != null -> { val name = asmgen.asmIdentifierName(identifier) asmgen.out(""" lda #0 @@ -761,13 +830,13 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, sbc $name+1 sta $name+1""") } - arrayIdx!=null -> TODO("in-place negate word array") - memory!=null -> throw AssemblyError("no asm gen for word memory negate") + arrayIdx != null -> TODO("in-place negate word array") + memory != null -> throw AssemblyError("no asm gen for word memory negate") } } DataType.FLOAT -> { when { - identifier!=null -> { + identifier != null -> { val name = asmgen.asmIdentifierName(identifier) asmgen.out(""" stx ${C64Zeropage.SCRATCH_REG_X} @@ -781,8 +850,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, ldx ${C64Zeropage.SCRATCH_REG_X} """) } - arrayIdx!=null -> TODO("in-place negate float array") - memory!=null -> throw AssemblyError("no asm gen for float memory negate") + arrayIdx != null -> TODO("in-place negate float array") + memory != null -> throw AssemblyError("no asm gen for float memory negate") } } else -> throw AssemblyError("negate of invalid type") diff --git a/examples/test.p8 b/examples/test.p8 index 5cfef7ac8..ef0c5e7a2 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -7,79 +7,14 @@ main { sub start() { - ;ubyte @(addr)=0 - uword addr = $02 - uword addr2 = $03 - ubyte B = 22 - ; all optimized: - @(addr) = B - c64scr.print_ub(@(addr)) - c64.CHROUT('\n') - @(addr2-1) = @(addr2-1) +33 - c64scr.print_ub(@(addr)) - c64.CHROUT('\n') + uword addr = $c002 - @(addr) = 11 - c64scr.print_ub(@(addr)) + @(addr-2) = $f8 + @(addr-2) = not @(addr-2) + c64scr.print_ubhex(@($c000), true) c64.CHROUT('\n') - @(addr) = 33 + @(addr) - c64scr.print_ub(@(addr)) - c64.CHROUT('\n') - - @(addr) = 11 - c64scr.print_ub(@(addr)) - c64.CHROUT('\n') - @(addr) = (@(addr) + 33) + B - c64scr.print_ub(@(addr)) - c64.CHROUT('\n') - - @(addr) = 11 - c64scr.print_ub(@(addr)) - c64.CHROUT('\n') - @(addr) = (33 + @(addr)) + B - c64scr.print_ub(@(addr)) - c64.CHROUT('\n') - - @(addr) = 11 - c64scr.print_ub(@(addr)) - c64.CHROUT('\n') - @(addr) = (@(addr) + B) + 33 - c64scr.print_ub(@(addr)) - c64.CHROUT('\n') - - @(addr) = 11 - c64scr.print_ub(@(addr)) - c64.CHROUT('\n') - @(addr) = (B + @(addr)) + 33 - c64scr.print_ub(@(addr)) - c64.CHROUT('\n') - - @(addr) = 11 - c64scr.print_ub(@(addr)) - c64.CHROUT('\n') - @(addr) = B+ (@(addr) + 33) - c64scr.print_ub(@(addr)) - c64.CHROUT('\n') - - @(addr) = 11 - c64scr.print_ub(@(addr)) - c64.CHROUT('\n') - @(addr) = B+(33 + @(addr)) - c64scr.print_ub(@(addr)) - c64.CHROUT('\n') - - @(addr) = 11 - c64scr.print_ub(@(addr)) - c64.CHROUT('\n') - @(addr) = 33+(@(addr) + B) - c64scr.print_ub(@(addr)) - c64.CHROUT('\n') - - @(addr) = 11 - c64scr.print_ub(@(addr)) - c64.CHROUT('\n') - @(addr) = 33+(B + @(addr)) - c64scr.print_ub(@(addr)) + @(addr-2) = not @(addr-2) + c64scr.print_ubhex(@($c000), true) c64.CHROUT('\n') } }