changeset 82:9a4e2364a966

Fix logic in int32_mul and overflow integer multiply to floating point It seems logical to allow integer multiplication to overflow to floating point. If this turns out to be unfortunate, it can be changed. In this update, 32 bit integer multiplication will overflow to floating point.
author William Astle <lost@l-w.ca>
date Sat, 07 Oct 2023 13:39:25 -0600
parents fbc14509955a
children a492441bfc56
files src/fps.s src/int.s
diffstat 2 files changed, 40 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/src/fps.s	Sat Oct 07 12:59:43 2023 -0600
+++ b/src/fps.s	Sat Oct 07 13:39:25 2023 -0600
@@ -42,6 +42,35 @@
                 clr fpa0extra                   ; clear extra precision
                 jmp fps_add10                   ; go normalize the result and return
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Convert 64 bit unsigned value at (X) to single precision floating point in value accumulator at (Y)
+;
+; Cases:
+; * byte 0 is first nonzero - exponent at 64 bits right, use upper 0 to 4
+; * byte 1 is first nonzero - exponent at 56 bits right, use bytes 1 to 5
+; * byte 2 is first nonzero - exponent at 48 bits right, use bytes 2 to 6
+; * otherwise - exponent at 40 bits right, use bytes 3 to 7
+fps_fromuint64  clra                            ; set sign to positive
+fps_fromuint64s sta fpa0+fps.sign               ; save sign of result
+                ldb #0xc0                       ; exponent if binary point is 64 bits to the right
+                lda ,x+                         ; is the first byte zero?
+                bne fps_fromuint64a             ; brif not
+                subb #8                         ; lose a byte off exponent
+                lda ,x+                         ; is the second byte zero?
+                bne fps_fromuint64a             ; brif not
+                subb #8                         ; lose another byte off exponent
+                lda ,x+                         ; is third byte zero?
+                bne fps_fromuint64a             ; brif not
+                subb #8                         ; lose another byte
+                lda ,x+                         ; get first byte to copy
+fps_fromuint64a stb fpa0+fps.exp                ; save exponent
+                sta fpa0+fps.sig                ; save high byte of significand
+                ldd ,x                          ; copy next two bytes to significand
+                std fpa0+fps.sig+1
+                ldd 2,x                         ; and the final byte and extra precision
+                sta fpa0+fps.sig+3
+                stb fpa0extra
+                jmp fps_add10                   ; go normalize the result and return
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ; Unary negation - negate (X) to (Y)
 fps_neg         ldd 2,x                         ; copy to output and keep exponent in A
                 std 2,y
--- a/src/int.s	Sat Oct 07 12:59:43 2023 -0600
+++ b/src/int.s	Sat Oct 07 13:39:25 2023 -0600
@@ -68,18 +68,18 @@
                 orb fpa0extra1
                 orb fpa0extra2
                 orb fpa0extra3
-                bne OVERROR2                    ; brif not - overflowed
+                bne int32_mul4                  ; brif not - overflow to floating point
                 ldb fpa0extra4                  ; is bit 31 set?
                 bpl int32_mul2                  ; brif not - no overflow
                 lda ,s                          ; negative result wanted?
-                bpl OVERROR2                    ; brif not - we overflowed
+                bpl int32_mul4                  ; brif not - overflow to floating point
                 andb #0x7f                      ; lose extra sign bit
-                orb fpa0extra5                  ; "or" in other bytes to see if all but bit 31 are zero
+                orb fpa0extra2                  ; "or" in other bytes to see if all but bit 31 are zero
                 orb fpa0extra6
                 orb fpa0extra7
-                bne OVERROR2                    ; brif any nonzero bits - we overflowed maximum negative number
-                ldb ,s+                         ; do we want a negative result?
-                bpl int32_mul2                  ; brif not
+                bne int32_mul4                  ; brif any nonzero bits - we overflowed maximum negative number
+int32_mul2      ldb ,s+                         ; do we want a negative result?
+                bpl int32_mul3                  ; brif not - don't negate result
                 ldd zero                        ; negate result
                 subd fpa0extra6
                 std fpa0extra6
@@ -87,11 +87,15 @@
                 sbcb fpa0extra5
                 sbca fpa0extra4
                 std fpa0extra4
-int32_mul2      ldd fpa0extra4                  ; copy result to destination
+int32_mul3      ldd fpa0extra4                  ; copy result to destination
                 std val.int,y
                 ldd fpa0extra6
                 std val.int+2,y
                 rts
+int32_mul4      puls b                          ; get back desired sign
+                sex                             ; set proper sign for floating point result
+                ldx #fpa0extra                  ; point to 64 bit unsigned result
+                jmp fps_fromuint64s             ; go convert to floating point using the sign in A
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ; 32 bit multiply.
 ;