From 15c649024e33a6bc3e72a67a242e8760b1b27818 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 2 Sep 2023 22:11:50 +0200 Subject: [PATCH] float problems on c64 --- docs/source/todo.rst | 2 +- floatproblem64.asm | 144 +++++++++++++++++++++++++++++++++++++++++++ floatproblem64.p8 | 51 +++++++++++---- 3 files changed, 183 insertions(+), 14 deletions(-) create mode 100644 floatproblem64.asm diff --git a/docs/source/todo.rst b/docs/source/todo.rst index aa42ffb74..8ecec31fe 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -1,7 +1,7 @@ TODO ==== - fix on c64 target: examples/cube3d-float (broken since 9.3 with the evalstack removal) it works on x16 target, oddly enough. - More detailed and simpler code for this problem in floatproblem64.p8 + More detailed and simpler code for this problem in floatproblem64.p8 / floatproblem64.asm (the minified version) - fix: search for TODO("swap operand order") - optimize: search for TODO optimize: don't use scratch var diff --git a/floatproblem64.asm b/floatproblem64.asm new file mode 100644 index 000000000..b0b3d2a2e --- /dev/null +++ b/floatproblem64.asm @@ -0,0 +1,144 @@ + +.cpu '6502' + +CHROUT = $FFD2 + +; C64 addresses for float routines: +;MOVFM = $bba2 +;CONUPK = $ba8c +;MOVAF = $bc0c +;MOVMF = $bbd4 +;FOUT = $bddd +;FADDT = $b86a +;FMULTT = $ba2b +; CX16 addresses for float routines: +MOVFM = $fe63 +CONUPK = $fe5a +MOVAF = $fe6c +MOVMF = $fe66 +FOUT = $fe06 +FADDT = $fe1b +FMULTT = $fe21 + +* = $0801 + +; 10 SYS 2062 + .word (+), 10 + .null $9e, " 2062" ++ .word 0 + +; program starts here at address 2062 + lda #$8d + jsr CHROUT + + ; calculate: value1*one + value2*one + ; (yes the multiplications with one do nothing value-wise, but they influence the routines being called...) + lda #prog8_float_const_0 + jsr MOVFM ; FAC1 = -0.8 + lda #float_const_one + jsr CONUPK ; ARG = 1.0 + jsr FMULTT ; FAC1 = -0.8*1.0 = -0.8 + jsr pushFAC1 ; save value... + lda #prog8_float_const_1 + jsr MOVFM ; FAC1 = 0.3 + lda #float_const_one + jsr CONUPK ; ARG = 1.0 + jsr FMULTT ; FAC1 = 0.3*1.0 = 0.3 + jsr MOVAF ; ARG = FAC1 = 0.3 + jsr popFAC1 ; restore value... (-0.8) + jsr FADDT ; FAC1 = -0.8 + 0.3 = -0.5 + ; ... result in FAC1 will be wrong on C64 (1.1 instead of -0.5).... + + ; print FAC1 + jsr FOUT ; fac1 to string in A/Y + sta _mod+1 + sty _mod+2 + ldy #0 +_mod lda $ffff,y ; modified + beq + + jsr CHROUT + iny + bne _mod ++ lda #$8d + jsr CHROUT + + ; print expected + ldy #0 +- lda string_1,y + beq + + jsr CHROUT + iny + bne - ++ rts + +string_1 + .text "-.5 was expected",$8d,0 + + +floats_temp_var .byte 0,0,0,0,0 ; temporary storage for a float + +pushFAC1 + ;-- push floating point in FAC onto the cpu stack + ; save return address + pla + sta returnaddr + pla + sta returnaddr+1 + ldx #floats_temp_var + jsr MOVMF + lda floats_temp_var + pha + lda floats_temp_var+1 + pha + lda floats_temp_var+2 + pha + lda floats_temp_var+3 + pha + lda floats_temp_var+4 + pha + ; re-push return address + lda returnaddr+1 + pha + lda returnaddr + pha + rts + +returnaddr .word 0 + +popFAC1 + ; -- pop floating point value from cpu stack into FAC1 + ; save return address + pla + sta returnaddr + pla + sta returnaddr+1 + pla + sta floats_temp_var+4 + pla + sta floats_temp_var+3 + pla + sta floats_temp_var+2 + pla + sta floats_temp_var+1 + pla + sta floats_temp_var + lda #floats_temp_var + jsr MOVFM + ; re-push return address + lda returnaddr+1 + pha + lda returnaddr + pha + rts + + +; global float constants +prog8_float_const_0 .byte $80, $cc, $cc, $cc, $cc ; float -0.8 +prog8_float_const_1 .byte $7f, $19, $99, $99, $99 ; float 0.3 +float_const_one .byte $81, $00, $00, $00, $00 ; float 1.0 diff --git a/floatproblem64.p8 b/floatproblem64.p8 index 746f071ab..23dc94c6a 100644 --- a/floatproblem64.p8 +++ b/floatproblem64.p8 @@ -1,32 +1,57 @@ %import textio %import floats +%import test_stack %zeropage dontuse main { sub start() { float value1 = -0.8 float value2 = 0.3 - float two = 2.0 + float one = 1.0 - float result = value1*two + value2*two ; TODO FIX: invalid result on c64, ok when the *two is removed or expression is split (it's not caused by pushFAC1/popFAC1) + float result = value1*one + value2*one ; TODO FIX: invalid result on c64, ok when the *one is removed or expression is split (it's not caused by pushFAC1/popFAC1) + ; TODO is it floats.CONUPK?? floats.print_f(result) txt.nl() - txt.print("-1 was expected\n\n") ; on C64: -1.1 is printed :( + txt.print("-.5 was expected\n\n") ; on C64: -1.1 is printed :( - result = value2*two + value1*two ; swapped operands around, now it's suddenly fine on C64... - floats.print_f(result) - txt.nl() - txt.print("-1 was expected\n\n") ; on C64: correct value is printed +; result = value2*one + value1*one ; swapped operands around, now it's suddenly fine on C64... +; floats.print_f(result) +; txt.nl() +; txt.print("-.5 was expected\n\n") ; on C64: correct value is printed - value1 = 0.8 - value2 = 0.3 - result = value1*two + value2*two - floats.print_f(result) - txt.nl() - txt.print("2.2 was expected\n\n") ; on C64: correct value is printed +; value1 = 0.8 +; value2 = 0.3 +; result = value1*one + value2*one +; floats.print_f(result) +; txt.nl() +; txt.print("1.1 was expected\n\n") ; on C64: correct value is printed +; +; printFAC1() +; printFAC1() +; printFAC1() repeat { } } + + sub printFAC1() { + ubyte[20] fac_save + sys.memcopy($60, fac_save, sizeof(fac_save)) + txt.print("fac1=") + %asm {{ + jsr floats.FOUT ; fac1 to string in A/Y + sta P8ZP_SCRATCH_W1 + sty P8ZP_SCRATCH_W1+1 + ldy #0 +- lda (P8ZP_SCRATCH_W1),y + beq + + jsr cbm.CHROUT + iny + bne - ++ }} + txt.nl() + sys.memcopy(fac_save, $60, sizeof(fac_save)) + } }