diff --git a/compiler/examples/test.p8 b/compiler/examples/test.p8 index 4ee4a83b1..dd94470a4 100644 --- a/compiler/examples/test.p8 +++ b/compiler/examples/test.p8 @@ -17,14 +17,29 @@ float f2 float f3 - c64scr.print_byte_decimal(-99) + + b2 = 99 + w2 = -9999 + ub2 = 100 + uw2 = 40000 + f2 = 3.141592654 + + c64.CHROUT('x') + c64scr.print_ubyte_decimal(X) c64.CHROUT('\n') - c64scr.print_byte_decimal(b1) + f1 = deg(f2) + c64flt.print_float(f1) c64.CHROUT('\n') - c64scr.print_word_decimal(-9999) + c64.CHROUT('x') + c64scr.print_ubyte_decimal(X) c64.CHROUT('\n') - c64scr.print_word_decimal(w1) + f1 = rad(f1) + c64flt.print_float(f1) c64.CHROUT('\n') + c64.CHROUT('x') + c64scr.print_ubyte_decimal(X) + c64.CHROUT('\n') + } } diff --git a/compiler/src/prog8/compiler/target/c64/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/AsmGen.kt index 875e89d9b..1241a158d 100644 --- a/compiler/src/prog8/compiler/target/c64/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/AsmGen.kt @@ -712,10 +712,10 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, bne ${ins.callLabel} """ } - Opcode.UB2FLOAT -> " jsr prog8_lib.ub2float" - Opcode.B2FLOAT -> " jsr prog8_lib.b2float" - Opcode.UW2FLOAT -> " jsr prog8_lib.uw2float" - Opcode.W2FLOAT -> " jsr prog8_lib.w2float" + Opcode.UB2FLOAT -> " jsr prog8_lib.stack_ub2float" + Opcode.B2FLOAT -> " jsr prog8_lib.stack_b2float" + Opcode.UW2FLOAT -> " jsr prog8_lib.stack_uw2float" + Opcode.W2FLOAT -> " jsr prog8_lib.stack_w2float" Opcode.B2UB -> "" // is a no-op, just carry on with the byte as-is Opcode.UB2B -> "" // is a no-op, just carry on with the byte as-is Opcode.UB2UWORD -> " lda #0 | sta ${ESTACK_HI+1},x" diff --git a/compiler/src/prog8/compiler/target/c64/Commodore64.kt b/compiler/src/prog8/compiler/target/c64/Commodore64.kt index b024214f8..c5fa506d6 100644 --- a/compiler/src/prog8/compiler/target/c64/Commodore64.kt +++ b/compiler/src/prog8/compiler/target/c64/Commodore64.kt @@ -28,14 +28,14 @@ class C64Zeropage(options: CompilationOptions) : Zeropage(options) { companion object { const val SCRATCH_B1 = 0x02 const val SCRATCH_REG = 0x03 // temp storage for a register - const val SCRATCH_REG_X = 0x50 // temp storage for register X (the evaluation stack pointer) + const val SCRATCH_REG_X = 0xfa // temp storage for register X (the evaluation stack pointer) const val SCRATCH_W1 = 0xfb // $fb/$fc const val SCRATCH_W2 = 0xfd // $fd/$fe } init { if(options.zeropage== ZeropageType.FULL) { - free.addAll(0x04 .. 0xfa) + free.addAll(0x04 .. 0xf9) free.add(0xff) free.removeAll(listOf(SCRATCH_B1, SCRATCH_REG, SCRATCH_REG_X, SCRATCH_W1, SCRATCH_W1+1, SCRATCH_W2, SCRATCH_W2+1)) free.removeAll(listOf(0xa0, 0xa1, 0xa2, 0x91, 0xc0, 0xc5, 0xcb, 0xf5, 0xf6)) // these are updated by IRQ @@ -50,8 +50,8 @@ class C64Zeropage(options: CompilationOptions) : Zeropage(options) { // add the other free Zp addresses // these are valid for the C-64 (when no RS232 I/O is performed): free.addAll(listOf(0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0d, 0x0e, - 0x51, 0x52, 0x94, 0x95, 0xa7, 0xa8, 0xa9, 0xaa, - 0xb5, 0xb6, 0xf7, 0xf8, 0xf9, 0xfa)) + 0x94, 0x95, 0xa7, 0xa8, 0xa9, 0xaa, + 0xb5, 0xb6, 0xf7, 0xf8, 0xf9)) } assert(SCRATCH_B1 !in free) assert(SCRATCH_REG !in free) diff --git a/compiler/test/UnitTests.kt b/compiler/test/UnitTests.kt index 5c4744632..0ce07131d 100644 --- a/compiler/test/UnitTests.kt +++ b/compiler/test/UnitTests.kt @@ -155,9 +155,9 @@ class TestZeropage { @Test fun testFreeSpaces() { val zp1 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true)) - assertEquals(22, zp1.available()) + assertEquals(19, zp1.available()) val zp2 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.KERNALSAFE, emptyList(), true)) - assertEquals(70, zp2.available()) + assertEquals(67, zp2.available()) val zp3 = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.FULL, emptyList(), true)) assertEquals(238, zp3.available()) } @@ -188,7 +188,7 @@ class TestZeropage { @Test fun testBasicsafeAllocation() { val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true)) - assertEquals(22, zp.available()) + assertEquals(19, zp.available()) zp.allocate(VarDecl(VarDeclType.VAR, DataType.FLOAT, null, "", null, dummypos)) assertFailsWith { @@ -219,10 +219,10 @@ class TestZeropage { val num = zp.available() / 5 val rest = zp.available() % 5 - for(i in 0..num-5) { + for(i in 0..num-4) { zp.allocate(VarDecl(VarDeclType.VAR, DataType.FLOAT, null, "", null, dummypos)) } - assertEquals(23,zp.available()) + assertEquals(18,zp.available()) assertFailsWith { // can't allocate because no more sequential bytes, only fragmented @@ -233,11 +233,9 @@ class TestZeropage { zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, null, "", null, dummypos)) } zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, null, "", null, dummypos)) - zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, null, "", null, dummypos)) - assertEquals(5, zp.available()) - zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, null, "", null, dummypos)) - zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, null, "", null, dummypos)) + assertEquals(2, zp.available()) + zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, null, "", null, dummypos)) zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, null, "", null, dummypos)) assertFailsWith { // no more space @@ -248,17 +246,16 @@ class TestZeropage { @Test fun testEfficientAllocation() { val zp = C64Zeropage(CompilationOptions(OutputType.RAW, LauncherType.NONE, ZeropageType.BASICSAFE, emptyList(), true)) - assertEquals(22, zp.available()) + assertEquals(19, zp.available()) assertEquals(0x04, zp.allocate(VarDecl(VarDeclType.VAR, DataType.FLOAT, null, "", null, dummypos))) assertEquals(0x09, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, null, "", null, dummypos))) assertEquals(0x0d, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, null, "", null, dummypos))) - assertEquals(0x51, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, null, "", null, dummypos))) assertEquals(0x94, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, null, "", null, dummypos))) assertEquals(0xa7, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, null, "", null, dummypos))) assertEquals(0xa9, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, null, "", null, dummypos))) assertEquals(0xb5, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, null, "", null, dummypos))) assertEquals(0xf7, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, null, "", null, dummypos))) - assertEquals(0xf9, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UWORD, null, "", null, dummypos))) + assertEquals(0xf9, zp.allocate(VarDecl(VarDeclType.VAR, DataType.UBYTE, null, "", null, dummypos))) assertEquals(0, zp.available()) } } diff --git a/prog8lib/c64lib.p8 b/prog8lib/c64lib.p8 index 9100b7e5f..b3a84218e 100644 --- a/prog8lib/c64lib.p8 +++ b/prog8lib/c64lib.p8 @@ -167,6 +167,7 @@ asmsub SGN () -> clobbers(A,X,Y) -> () = $bc39 ; fac1 = SGN(fac1), result of asmsub SIGN () -> clobbers() -> (ubyte @ A) = $bc2b ; SIGN(fac1) to A, $ff, $0, $1 for negative, zero, positive asmsub ABS () -> clobbers() -> () = $bc58 ; fac1 = ABS(fac1) asmsub SQR () -> clobbers(A,X,Y) -> () = $bf71 ; fac1 = SQRT(fac1) +asmsub SQRA () -> clobbers(A,X,Y) -> () = $bf74 ; fac1 = SQRT(fac2) asmsub EXP () -> clobbers(A,X,Y) -> () = $bfed ; fac1 = EXP(fac1) (e ** fac1) asmsub NEGOP () -> clobbers(A) -> () = $bfb4 ; switch the sign of fac1 asmsub RND () -> clobbers(A,X,Y) -> () = $e097 ; fac1 = RND(fac1) float random number generator diff --git a/prog8lib/prog8lib.p8 b/prog8lib/prog8lib.p8 index 49b2a4cfa..e6b597f76 100644 --- a/prog8lib/prog8lib.p8 +++ b/prog8lib/prog8lib.p8 @@ -12,7 +12,7 @@ ; note: the following ZP scratch registers must be the same as in c64lib memory ubyte SCRATCH_ZPB1 = $02 ; scratch byte 1 in ZP memory ubyte SCRATCH_ZPREG = $03 ; scratch register in ZP - memory ubyte SCRATCH_ZPREGX = $50 ; temp storage for X register (stack pointer) + memory ubyte SCRATCH_ZPREGX = $fa ; temp storage for X register (stack pointer) memory uword SCRATCH_ZPWORD1 = $fb ; scratch word in ZP ($fb/$fc) memory uword SCRATCH_ZPWORD2 = $fd ; scratch word in ZP ($fd/$fe) const uword ESTACK_LO = $ce00 @@ -84,9 +84,48 @@ w2float .proc lda SCRATCH_ZPWORD1+1 jsr c64.GIVAYF jmp ub2float._fac_to_mem - rts + .pend + +stack_b2float .proc + ; -- b2float operating on the stack + inx + lda ESTACK_LO,x + stx SCRATCH_ZPREGX + jsr c64.FREADSA + jmp push_fac1_as_result + .pend + +stack_w2float .proc + ; -- w2float operating on the stack + inx + ldy ESTACK_LO,x + lda ESTACK_HI,x + stx SCRATCH_ZPREGX + jsr c64.GIVAYF + jmp push_fac1_as_result .pend +stack_ub2float .proc + ; -- ub2float operating on the stack + inx + lda ESTACK_LO,x + stx SCRATCH_ZPREGX + tay + jsr c64.FREADUY + jmp push_fac1_as_result + .pend + +stack_uw2float .proc + ; -- uw2float operating on the stack + inx + lda ESTACK_LO,x + ldy ESTACK_HI,x + stx SCRATCH_ZPREGX + jsr c64flt.GIVUAYFAY + jmp push_fac1_as_result + .pend + + push_float .proc ; ---- push mflpt5 in A/Y onto stack ; (taking 3 stack positions = 6 bytes of which 1 is padding) @@ -172,6 +211,16 @@ pop_float .proc rts .pend +pop_float_fac1 .proc + ; -- pops float from stack into FAC1 + lda #fmath_float1 + jsr pop_float + lda #fmath_float1 + jmp c64.MOVFM + .pend + pop_float_to_indexed_var .proc ; -- pop the float on the stack, to the memory in the array at A/Y indexed by the byte on stack sta SCRATCH_ZPWORD1 @@ -270,8 +319,8 @@ push_fac1_as_result .proc div_f .proc ; -- push f1/f2 on stack - stx SCRATCH_ZPREGX jsr pop_2_floats_f2_in_fac1 + stx SCRATCH_ZPREGX lda #fmath_float1 jsr c64.FDIV @@ -280,8 +329,8 @@ div_f .proc add_f .proc ; -- push f1+f2 on stack - stx SCRATCH_ZPREGX jsr pop_2_floats_f2_in_fac1 + stx SCRATCH_ZPREGX lda #fmath_float1 jsr c64.FADD @@ -290,8 +339,8 @@ add_f .proc sub_f .proc ; -- push f1-f2 on stack - stx SCRATCH_ZPREGX jsr pop_2_floats_f2_in_fac1 + stx SCRATCH_ZPREGX lda #fmath_float1 jsr c64.FSUB @@ -300,8 +349,8 @@ sub_f .proc mul_f .proc ; -- push f1*f2 on stack - stx SCRATCH_ZPREGX jsr pop_2_floats_f2_in_fac1 + stx SCRATCH_ZPREGX lda #fmath_float1 jsr c64.FMULT @@ -310,13 +359,8 @@ mul_f .proc neg_f .proc ; -- push -flt back on stack + jsr pop_float_fac1 stx SCRATCH_ZPREGX - lda #fmath_float1 - jsr pop_float - lda #fmath_float1 - jsr c64.MOVFM jsr c64.NEGOP jmp push_fac1_as_result .pend @@ -324,7 +368,7 @@ neg_f .proc add_w .proc ; -- push word+word - .warn "addw" + .warn "addw check correctness" inx clc lda ESTACK_LO,x @@ -337,7 +381,7 @@ add_w .proc .pend add_uw .proc - .warn "add_uw" + .warn "add_uw check correctness" inx clc lda ESTACK_LO,x @@ -356,52 +400,52 @@ sub_w .proc sub_uw .proc rts ; @todo inline? - .warn "not implemented" + .warn "sub_w not implemented" .pend mul_b .proc rts - .warn "not implemented" + .warn "mul_b not implemented" .pend mul_ub .proc rts - .warn "not implemented" + .warn "mul_ub not implemented" .pend mul_w .proc rts - .warn "not implemented" + .warn "mul_w not implemented" .pend mul_uw .proc rts - .warn "not implemented" + .warn "mul_uw not implemented" .pend div_b .proc rts - .warn "not implemented" + .warn "div_b not implemented" .pend div_ub .proc rts - .warn "not implemented" + .warn "div_ub not implemented" .pend div_w .proc rts - .warn "not implemented" + .warn "div_w not implemented" .pend div_uw .proc rts - .warn "not implemented" + .warn "div_uw not implemented" .pend remainder_b .proc rts - .warn "not implemented" + .warn "remainder_b not implemented" .pend remainder_ub .proc @@ -419,12 +463,12 @@ remainder_ub .proc remainder_w .proc rts - .warn "not implemented" + .warn "remainder_w not implemented" .pend remainder_uw .proc rts - .warn "not implemented" + .warn "remainder_uw not implemented" .pend equal_w .proc @@ -707,23 +751,21 @@ greatereq_f .proc .pend compare_floats .proc - lda #<_flt2 - ldy #>_flt2 + lda #fmath_float2 jsr pop_float - lda #<_flt1 - ldy #>_flt1 + lda #fmath_float1 jsr pop_float - lda #<_flt1 - ldy #>_flt1 + lda #fmath_float1 jsr c64.MOVFM ; fac1 = flt1 - lda #<_flt2 - ldy #>_flt2 + lda #fmath_float2 stx SCRATCH_ZPREG jsr c64.FCOMP ; A = flt1 compared with flt2 (0=equal, 1=flt1>flt2, 255=flt1_pi_div_180 + jsr c64.FMULT + jmp push_fac1_as_result +_pi_div_180 .byte 123, 14, 250, 53, 18 ; pi / 180 .pend func_deg .proc - rts - .warn "not implemented" + ; -- convert radians to degrees (d * (1/ pi * 180)) + jsr pop_float_fac1 + stx SCRATCH_ZPREGX + lda #<_one_over_pi_div_180 + ldy #>_one_over_pi_div_180 + jsr c64.FMULT + jmp push_fac1_as_result +_one_over_pi_div_180 .byte 134, 101, 46, 224, 211 ; 1 / (pi * 180) .pend func_round .proc rts - .warn "not implemented" + .warn "round not implemented" .pend func_floor .proc rts - .warn "not implemented" + .warn "floor not implemented" .pend func_ceil .proc rts - .warn "not implemented" + .warn "ceil not implemented" .pend func_max .proc rts - .warn "not implemented--what does it max over???" + .warn "max not implemented--what does it max over???" .pend func_min .proc rts - .warn "not implemented--what does it min over???" + .warn "min not implemented--what does it min over???" .pend func_avg .proc rts - .warn "not implemented--what does it avg over???" + .warn "avg not implemented--what does it avg over???" .pend func_sum .proc rts - .warn "not implemented--what does it sum over???" + .warn "sum not implemented--what does it sum over???" .pend func_len .proc rts - .warn "not implemented--of what does it take len?" + .warn "len not implemented--of what does it take len?" .pend func_any .proc rts - .warn "not implemented--of what does it do any?" + .warn "any not implemented--of what does it do any?" .pend func_all .proc rts - .warn "not implemented--of what does it do all?" + .warn "all not implemented--of what does it do all?" .pend @@ -886,7 +950,7 @@ _rndf_rnum5 .fill 5 func_str2byte .proc rts - .warn "not implemented" + .warn "str2byte not implemented" .pend ; @todo python code for a str-to-ubyte function that doesn't use the basic rom: @@ -946,12 +1010,12 @@ _strlen2233 func_str2word .proc rts - .warn "not implemented" + .warn "str2word not implemented" .pend func_str2float .proc rts - .warn "not implemented" + .warn "str2float not implemented" .pend