fixed c64 float problem

This commit is contained in:
Irmen de Jong 2023-09-03 16:40:10 +02:00
parent 48bd51e1a5
commit c3fbdf34ca
6 changed files with 36 additions and 151 deletions

View File

@ -3031,7 +3031,11 @@ $repeatLabel""")
}
internal fun popFAC1() {
out(" jsr floats.popFAC1")
out(" clc | jsr floats.popFAC")
}
internal fun popFAC2() {
out(" sec | jsr floats.popFAC")
}
internal fun needAsaveForExpr(arg: PtExpression): Boolean =

View File

@ -3,6 +3,8 @@ package prog8.codegen.cpu6502.assignment
import prog8.code.ast.PtBinaryExpression
import prog8.code.ast.PtExpression
import prog8.code.core.*
import prog8.code.target.C64Target
import prog8.code.target.Cx16Target
import prog8.codegen.cpu6502.AsmGen6502Internal
//
@ -245,11 +247,28 @@ internal class AnyExprAsmGen(
}
private fun assignFloatOperandsToFACandARG(left: PtExpression, right: PtExpression) {
asmgen.assignExpressionToRegister(left, RegisterOrPair.FAC1, true)
if(!right.isSimple()) asmgen.pushFAC1()
asmgen.assignExpressionToRegister(right, RegisterOrPair.FAC2, true)
if(!right.isSimple()) asmgen.popFAC1()
// TODO: always make sure FAC2 is loaded last (done using CONUPK) otherwise the result will be corrupt on C64
when(asmgen.options.compTarget.name) {
C64Target.NAME -> {
// c64 has a quirk: always make sure FAC2 is loaded last (done using CONUPK) otherwise the result will be corrupt on C64
// this requires some more forced copying around of float values in certain cases
if (right.isSimple()) {
asmgen.assignExpressionToRegister(left, RegisterOrPair.FAC1, true)
asmgen.assignExpressionToRegister(right, RegisterOrPair.FAC2, true)
} else {
asmgen.assignExpressionToRegister(right, RegisterOrPair.FAC1, true)
asmgen.pushFAC1()
asmgen.assignExpressionToRegister(left, RegisterOrPair.FAC1, true)
asmgen.popFAC2()
}
}
Cx16Target.NAME -> {
asmgen.assignExpressionToRegister(left, RegisterOrPair.FAC1, true)
if (!right.isSimple()) asmgen.pushFAC1()
asmgen.assignExpressionToRegister(right, RegisterOrPair.FAC2, true)
if (!right.isSimple()) asmgen.popFAC1()
}
else -> TODO("don't know how to evaluate float expression for selected compilation target")
}
}
private fun setupFloatComparisonFAC1vsVarAY(expr: PtBinaryExpression) {

View File

@ -418,8 +418,9 @@ pushFAC1 .proc
rts
.pend
popFAC1 .proc
; -- pop floating point value from cpu stack into FAC1
popFAC .proc
; -- pop floating point value from cpu stack into FAC1 or FAC2 (
; carry flag clear=FAC1, carry set=FAC2
; save return address
pla
sta P8ZP_SCRATCH_W2
@ -437,8 +438,11 @@ popFAC1 .proc
sta floats.floats_temp_var
lda #<floats.floats_temp_var
ldy #>floats.floats_temp_var
bcs +
jsr floats.MOVFM
; re-push return address
jmp ++
+ jsr floats.CONUPK
+ ; re-push return address
lda P8ZP_SCRATCH_W2+1
pha
lda P8ZP_SCRATCH_W2

View File

@ -1,10 +1,5 @@
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 floatproblem.p8 / floatproblem64-small.asm (the minified version)
Seems like MOVFM (loading FAC) corrupts the sign of ARG, so CONUPK (loading ARG) needs to be done AFTER MOVFM (loading FAC)...?
See assignFloatOperandsToFACandARG()
- prefix prog8 subroutines with p8s_ instead of p8_ to not let them clash with variables in the asm?
- allow 'chained' array indexing for expressions: value = ptrarray[0][0]
- allow 'chained' array indexing for assign targets: ptrarray[0][0] = 42 this is just evaluating the lhs as a uword pointer expression

View File

@ -1,80 +0,0 @@
.cpu '6502'
CHROUT = $FFD2
; C64 addresses for float routines:
MOVFM = $bba2
CONUPK = $ba8c
MOVAF = $bc0c
MOVEF = $bc0f
MOVMF = $bbd4
FOUT = $bddd
FADDT = $b86a
FMULTT = $ba2b
; CX16 addresses for float routines:
;MOVFM = $fe63
;CONUPK = $fe5a
;MOVAF = $fe6c
;MOVEF = $fe81
;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
ldx #0
stx $6f
lda #<prog8_float_const_1 ; 0.3
ldy #>prog8_float_const_1
jsr CONUPK ; ARG = 0.3
lda #<prog8_float_const_0 ; -0.8
ldy #>prog8_float_const_0
jsr MOVFM ; FAC1 = -0.8 ; On C64 this also seems to corrupt the value in ARG!!! (or at least, the sign of that)
jsr FADDT ; FAC1 = -0.8 + 0.3 = -0.5
; ... result in FAC1 will be wrong on C64 (1.1 instead of -0.5)....
; Seems like MOVFM (loading FAC) corrupts the sign of ARG, so CONUPK (loading ARG) needs to be done AFTER MOVFM (loading FAC)...?
; 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 -
+
loop jmp loop
string_1
.text "-.5 was expected",$8d,0
; 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

View File

@ -1,57 +0,0 @@
%import textio
%import floats
%import test_stack
%zeropage dontuse
main {
sub start() {
float value1 = -0.8
float value2 = 0.3
float one = 1.0
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("-.5 was expected\n\n") ; on C64: -1.1 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*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))
}
}