mirror of
https://github.com/irmen/prog8.git
synced 2024-07-06 13:29:00 +00:00
c64 float problem
This commit is contained in:
parent
10d0b03a90
commit
48bd51e1a5
@ -1,6 +1,7 @@
|
|||||||
package prog8.codegen.cpu6502.assignment
|
package prog8.codegen.cpu6502.assignment
|
||||||
|
|
||||||
import prog8.code.ast.PtBinaryExpression
|
import prog8.code.ast.PtBinaryExpression
|
||||||
|
import prog8.code.ast.PtExpression
|
||||||
import prog8.code.core.*
|
import prog8.code.core.*
|
||||||
import prog8.codegen.cpu6502.AsmGen6502Internal
|
import prog8.codegen.cpu6502.AsmGen6502Internal
|
||||||
|
|
||||||
@ -180,37 +181,25 @@ internal class AnyExprAsmGen(
|
|||||||
private fun assignFloatBinExpr(expr: PtBinaryExpression, assign: AsmAssignment): Boolean {
|
private fun assignFloatBinExpr(expr: PtBinaryExpression, assign: AsmAssignment): Boolean {
|
||||||
when(expr.operator) {
|
when(expr.operator) {
|
||||||
"+" -> {
|
"+" -> {
|
||||||
asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.FAC1, true)
|
assignFloatOperandsToFACandARG(expr.left, expr.right)
|
||||||
if(!expr.right.isSimple()) asmgen.pushFAC1()
|
|
||||||
asmgen.assignExpressionToRegister(expr.right, RegisterOrPair.FAC2, true)
|
|
||||||
if(!expr.right.isSimple()) asmgen.popFAC1()
|
|
||||||
asmgen.out(" jsr floats.FADDT")
|
asmgen.out(" jsr floats.FADDT")
|
||||||
asmgen.assignRegister(RegisterOrPair.FAC1, assign.target)
|
asmgen.assignRegister(RegisterOrPair.FAC1, assign.target)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
"-" -> {
|
"-" -> {
|
||||||
asmgen.assignExpressionToRegister(expr.right, RegisterOrPair.FAC1, true)
|
assignFloatOperandsToFACandARG(expr.right, expr.left)
|
||||||
if(!expr.left.isSimple()) asmgen.pushFAC1()
|
|
||||||
asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.FAC2, true)
|
|
||||||
if(!expr.left.isSimple()) asmgen.popFAC1()
|
|
||||||
asmgen.out(" jsr floats.FSUBT")
|
asmgen.out(" jsr floats.FSUBT")
|
||||||
asmgen.assignRegister(RegisterOrPair.FAC1, assign.target)
|
asmgen.assignRegister(RegisterOrPair.FAC1, assign.target)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
"*" -> {
|
"*" -> {
|
||||||
asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.FAC1, true)
|
assignFloatOperandsToFACandARG(expr.left, expr.right)
|
||||||
if(!expr.right.isSimple()) asmgen.pushFAC1()
|
|
||||||
asmgen.assignExpressionToRegister(expr.right, RegisterOrPair.FAC2, true)
|
|
||||||
if(!expr.right.isSimple()) asmgen.popFAC1()
|
|
||||||
asmgen.out(" jsr floats.FMULTT")
|
asmgen.out(" jsr floats.FMULTT")
|
||||||
asmgen.assignRegister(RegisterOrPair.FAC1, assign.target)
|
asmgen.assignRegister(RegisterOrPair.FAC1, assign.target)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
"/" -> {
|
"/" -> {
|
||||||
asmgen.assignExpressionToRegister(expr.right, RegisterOrPair.FAC1, true)
|
assignFloatOperandsToFACandARG(expr.right, expr.left)
|
||||||
if(!expr.left.isSimple()) asmgen.pushFAC1()
|
|
||||||
asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.FAC2, true)
|
|
||||||
if(!expr.left.isSimple()) asmgen.popFAC1()
|
|
||||||
asmgen.out(" jsr floats.FDIVT")
|
asmgen.out(" jsr floats.FDIVT")
|
||||||
asmgen.assignRegister(RegisterOrPair.FAC1, assign.target)
|
asmgen.assignRegister(RegisterOrPair.FAC1, assign.target)
|
||||||
return true
|
return true
|
||||||
@ -255,6 +244,14 @@ 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
|
||||||
|
}
|
||||||
|
|
||||||
private fun setupFloatComparisonFAC1vsVarAY(expr: PtBinaryExpression) {
|
private fun setupFloatComparisonFAC1vsVarAY(expr: PtBinaryExpression) {
|
||||||
asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.FAC1, true)
|
asmgen.assignExpressionToRegister(expr.left, RegisterOrPair.FAC1, true)
|
||||||
if(!expr.right.isSimple()) asmgen.pushFAC1()
|
if(!expr.right.isSimple()) asmgen.pushFAC1()
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
- fix on c64 target: examples/cube3d-float (broken since 9.3 with the evalstack removal) it works on x16 target, oddly enough.
|
- 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 / floatproblem64.asm (the minified version)
|
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?
|
- 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 expressions: value = ptrarray[0][0]
|
||||||
|
80
floatproblem64-small.asm
Normal file
80
floatproblem64-small.asm
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
|
||||||
|
.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
|
@ -1,144 +0,0 @@
|
|||||||
|
|
||||||
.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 ; -0.8
|
|
||||||
ldy #>prog8_float_const_0
|
|
||||||
jsr MOVFM ; FAC1 = -0.8
|
|
||||||
lda #<float_const_one ; 1.0
|
|
||||||
ldy #>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 ; 0.3
|
|
||||||
ldy #>prog8_float_const_1
|
|
||||||
jsr MOVFM ; FAC1 = 0.3
|
|
||||||
lda #<float_const_one ; 1.0
|
|
||||||
ldy #>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
|
|
||||||
ldy #>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
|
|
||||||
ldy #>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
|
|
Loading…
Reference in New Issue
Block a user