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 e865e2586..6f728b120 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/assignment/AugmentableAssignmentAsmGen.kt @@ -642,14 +642,15 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, // TODO use these + and - optimizations in the expressionAsmGenerator as well. "+" -> { when { - value<0x0100 -> asmgen.out(""" + value==0 -> {} + value in 1..0xff -> asmgen.out(""" lda $name clc adc #$value sta $name bcc + inc $name+1 -+ """) ++""") 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") @@ -666,14 +667,15 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, } "-" -> { when { - value<0x0100 -> asmgen.out(""" + value==0 -> {} + value in 1..0xff -> asmgen.out(""" lda $name sec sbc #$value sta $name bcs + dec $name+1 -+ """) ++""") 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") @@ -841,32 +843,52 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, when (operator) { // note: ** (power) operator requires floats. "+" -> { - asmgen.out(""" - ldy #0 - lda $otherName - bpl + - dey ; sign extend -+ clc - adc $name - sta $name - tya - adc $name+1 - sta $name+1""") + if(valueDt==DataType.UBYTE) + asmgen.out(""" + lda $name + clc + adc $otherName + sta $name + bcc + + inc $name+1 ++""") + else + asmgen.out(""" + ldy #0 + lda $otherName + bpl + + dey ; sign extend ++ clc + adc $name + sta $name + tya + adc $name+1 + sta $name+1""") } "-" -> { - asmgen.out(""" - ldy #0 - lda $otherName - bpl + - dey ; sign extend -+ sty P8ZP_SCRATCH_B1 - lda $name - sec - sbc $otherName - sta $name - lda $name+1 - sbc P8ZP_SCRATCH_B1 - sta $name+1""") + if(valueDt==DataType.UBYTE) + asmgen.out(""" + lda $name + sec + sbc $otherName + sta $name + bcc + + dec $name+1 ++""") + else + asmgen.out(""" + ldy #0 + lda $otherName + bpl + + dey ; sign extend ++ sty P8ZP_SCRATCH_B1 + lda $name + sec + sbc $otherName + sta $name + lda $name+1 + sbc P8ZP_SCRATCH_B1 + sta $name+1""") } "*" -> { asmgen.out(""" @@ -882,8 +904,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, lda math.multiply_words.result+1 sta $name+1""") } - "/" -> TODO("div wordvar/bytevar") - "%" -> TODO("word remainder bytevar") + "/" -> TODO("div (u)wordvar/bytevar") + "%" -> TODO("(u)word remainder bytevar") "<<" -> { asmgen.out(""" ldy $otherName @@ -911,9 +933,9 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, bne -""") } } - "&" -> TODO("bitand wordvar bytevar") - "^" -> TODO("bitxor wordvar bytevar") - "|" -> TODO("bitor wordvar bytevar") + "&" -> TODO("bitand (u)wordvar bytevar") + "^" -> TODO("bitxor (u)wordvar bytevar") + "|" -> TODO("bitor (u)wordvar bytevar") else -> throw AssemblyError("invalid operator for in-place modification $operator") } } @@ -1009,36 +1031,56 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, when (operator) { // note: ** (power) operator requires floats. "+" -> { - asmgen.out(""" - ldy #0 - lda P8ESTACK_LO+1,x - bpl + - dey ; sign extend -+ clc - adc $name - sta $name - tya - adc $name+1 - sta $name+1""") + if(valueDt==DataType.UBYTE) + asmgen.out(""" + lda $name + clc + adc P8ESTACK_LO+1,x + sta $name + bcc + + inc $name+1 ++""") + else + asmgen.out(""" + ldy #0 + lda P8ESTACK_LO+1,x + bpl + + dey ; sign extend ++ clc + adc $name + sta $name + tya + adc $name+1 + sta $name+1""") } "-" -> { - asmgen.out(""" - ldy #0 - lda P8ESTACK_LO+1,x - bpl + - dey ; sign extend -+ sty P8ZP_SCRATCH_B1 - lda $name - sec - sbc P8ESTACK_LO+1,x - sta $name - lda $name+1 - sbc P8ZP_SCRATCH_B1 - sta $name+1""") + if(valueDt==DataType.UBYTE) + asmgen.out(""" + lda $name + sec + sbc P8ESTACK_LO+1,x + sta $name + bcc + + dec $name+1 ++""") + else + asmgen.out(""" + ldy #0 + lda P8ESTACK_LO+1,x + bpl + + dey ; sign extend ++ sty P8ZP_SCRATCH_B1 + lda $name + sec + sbc P8ESTACK_LO+1,x + sta $name + lda $name+1 + sbc P8ZP_SCRATCH_B1 + sta $name+1""") } - "*" -> TODO("mul word byte") - "/" -> TODO("div word byte") - "%" -> TODO("word remainder byte") + "*" -> TODO("mul (u)word (u)byte") + "/" -> TODO("div (u)word (u)byte") + "%" -> TODO("(u)word remainder (u)byte") "<<" -> { asmgen.translateExpression(value) asmgen.out(""" @@ -1077,9 +1119,9 @@ internal class AugmentableAssignmentAsmGen(private val program: Program, +""") } } - "&" -> TODO("bitand word byte") - "^" -> TODO("bitxor word byte") - "|" -> TODO("bitor word byte") + "&" -> TODO("bitand (u)word (u)byte") + "^" -> TODO("bitxor (u)word (u)byte") + "|" -> TODO("bitor (u)word (u)byte") else -> throw AssemblyError("invalid operator for in-place modification $operator") } } diff --git a/examples/arithmetic/wordbyte.p8 b/examples/arithmetic/wordbyte.p8 new file mode 100644 index 000000000..f43d4bd20 --- /dev/null +++ b/examples/arithmetic/wordbyte.p8 @@ -0,0 +1,315 @@ +%import textio +%import syslib +%zeropage basicsafe + + +main { + sub start() { + repeat 25 { + txt.chrout('\n') + } + + ubyte ub + byte bb + uword uwsum + word wsum + + uwsum = 50000 + ub=50 + uwsum += ub + ub=250 + uwsum += ub + + if uwsum==50300 + txt.print("1 ok\n") + else { + txt.print("1 fail:") + txt.print_uw(uwsum) + txt.chrout('\n') + } + + wsum = -30000 + bb = 100 + wsum += bb + bb = -50 + wsum += bb + + if wsum==-29950 + txt.print("2 ok\n") + else { + txt.print("2 fail:") + txt.print_w(wsum) + txt.chrout('\n') + } + + uwsum = 50000 + ub=50 + uwsum -= ub + ub=250 + uwsum -= ub + + if uwsum==49700 + txt.print("3 ok\n") + else { + txt.print("3 fail:") + txt.print_uw(uwsum) + txt.chrout('\n') + } + wsum = -30000 + bb = 100 + wsum -= bb + bb = -50 + wsum -= bb + + if wsum==-30050 + txt.print("4 ok\n") + else + txt.print("4 fail\n") + + + + uwsum = 50000 + bb=50 + uwsum += bb as uword + bb=-100 + uwsum += bb as uword + + if uwsum==49950 + txt.print("5 ok\n") + else + txt.print("5 fail\n") + + uwsum = 50000 + bb=50 + uwsum -= bb as uword + bb=100 + uwsum -= bb as uword + + if uwsum==49850 + txt.print("6 ok\n") + else { + txt.print("6 fail:") + txt.print_uw(uwsum) + txt.chrout('\n') + } + + wsum = -30000 + ub = 50 + wsum += ub + ub = 250 + wsum += ub + + if wsum==-29700 + txt.print("7 ok\n") + else { + txt.print("7 fail:") + txt.print_w(wsum) + txt.chrout('\n') + } + + wsum = -30000 + ub = 50 + wsum -= ub + ub = 250 + wsum -= ub + + if wsum==-30300 + txt.print("8 ok\n") + else { + txt.print("8 fail:") + txt.print_w(wsum) + txt.chrout('\n') + } + + txt.chrout('\n') + + + + uwsum = 50000 + ub=0 + uwsum += (50+ub) + uwsum += (250+ub) + + if uwsum==50300 + txt.print("1b ok\n") + else { + txt.print("1b fail:") + txt.print_uw(uwsum) + txt.chrout('\n') + } + + bb = 0 + wsum = -30000 + wsum += (100+bb) + wsum += (-50+bb) + + if wsum==-29950 + txt.print("2b ok\n") + else { + txt.print("2b fail:") + txt.print_w(wsum) + txt.chrout('\n') + } + + uwsum = 50000 + uwsum -= (50+ub) + uwsum -= (250+ub) + + if uwsum==49700 + txt.print("3b ok\n") + else { + txt.print("3b fail:") + txt.print_uw(uwsum) + txt.chrout('\n') + } + wsum = -30000 + wsum -= (100+bb) + wsum -= (-50+bb) + + if wsum==-30050 + txt.print("4b ok\n") + else + txt.print("4b fail\n") + + + uwsum = 50000 + uwsum += (50+bb) as uword + uwsum += (-100+bb) as uword + + if uwsum==49950 + txt.print("5b ok\n") + else + txt.print("5b fail\n") + + uwsum = 50000 + uwsum -= (50+bb) as uword + uwsum -= (100+bb) as uword + + if uwsum==49850 + txt.print("6b ok\n") + else { + txt.print("6b fail:") + txt.print_uw(uwsum) + txt.chrout('\n') + } + + wsum = -30000 + wsum += (50+ub) + wsum += (250+ub) + + if wsum==-29700 + txt.print("7b ok\n") + else { + txt.print("7b fail:") + txt.print_w(wsum) + txt.chrout('\n') + } + + wsum = -30000 + wsum -= (50+ub) + wsum -= (250+ub) + + if wsum==-30300 + txt.print("8b ok\n") + else { + txt.print("8b fail:") + txt.print_w(wsum) + txt.chrout('\n') + } + + txt.chrout('\n') + + + + uwsum = 50000 + uwsum += 50 + uwsum += 250 + + if uwsum==50300 + txt.print("1c ok\n") + else { + txt.print("1c fail:") + txt.print_uw(uwsum) + txt.chrout('\n') + } + + wsum = -30000 + wsum += 100 + wsum += -50 + + if wsum==-29950 + txt.print("2c ok\n") + else { + txt.print("2c fail:") + txt.print_w(wsum) + txt.chrout('\n') + } + + uwsum = 50000 + uwsum -= 50 + uwsum -= 250 + + if uwsum==49700 + txt.print("3c ok\n") + else { + txt.print("3c fail:") + txt.print_uw(uwsum) + txt.chrout('\n') + } + wsum = -30000 + wsum -= 100 + wsum -= -50 + + if wsum==-30050 + txt.print("4c ok\n") + else + txt.print("4c fail\n") + + + uwsum = 50000 + uwsum += 50 as uword + uwsum += -100 as uword + + if uwsum==49950 + txt.print("5c ok\n") + else + txt.print("5c fail\n") + + uwsum = 50000 + uwsum -= 50 as uword + uwsum -= 100 as uword + + if uwsum==49850 + txt.print("6c ok\n") + else { + txt.print("6c fail:") + txt.print_uw(uwsum) + txt.chrout('\n') + } + + wsum = -30000 + wsum += 50 + wsum += 250 + + if wsum==-29700 + txt.print("7c ok\n") + else { + txt.print("7c fail:") + txt.print_w(wsum) + txt.chrout('\n') + } + + wsum = -30000 + wsum -= 50 + wsum -= 250 + + if wsum==-30300 + txt.print("8c ok\n") + else { + txt.print("8c fail:") + txt.print_w(wsum) + txt.chrout('\n') + } + } + +} diff --git a/examples/test.p8 b/examples/test.p8 index c9006fe99..e3eb61773 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -6,22 +6,7 @@ main { sub start() { - withX(1) - withX(2) - withX(3) - withY(6) - withY(7) - withY(8) + } - asmsub withX(ubyte foo @X) { - %asm {{ - rts - }} - } - asmsub withY(ubyte foo @Y) { - %asm {{ - rts - }} - } }