diff src/int.s @ 83:a492441bfc56

Add utility multiply and divide by 10 routines Add a fast multiply by 10 routine for both integer and floating point (shift left twice, add original, shift left). Also add a simple call to divide by 10 for both though there is no fast shortcut for that.
author William Astle <lost@l-w.ca>
date Sat, 07 Oct 2023 15:17:44 -0600
parents 9a4e2364a966
children 663d8e77b579
line wrap: on
line diff
--- a/src/int.s	Sat Oct 07 13:39:25 2023 -0600
+++ b/src/int.s	Sat Oct 07 15:17:44 2023 -0600
@@ -35,6 +35,38 @@
                 bvs OVERROR2                    ; raise overflow if needed
 int32_add0      rts
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Fast multiply 32 bit at (X) by 10
+;
+; This will work for signed because the left shift will double it even if it is negative and V is set correctly after
+; left shifts. The add will have the same sign so the magnitude will still increase, not decrease.
+uint32_mul10    ldd val.int,x                   ; make copy of original
+                ldu val.int+2,x
+                pshs d,u                        ; save original
+                lsl val.int+3,x                 ; shift left (times 2)
+                rol val.int+2,x
+                rol val.int+1,x
+                rol val.int,x
+                bvs OVERROR2                    ; brif overflow
+                lsl val.int+3,x                 ; shift left (times 4)
+                rol val.int+2,x
+                rol val.int+1,x
+                rol val.int,x
+                bvs OVERROR2                    ; brif overflow
+                ldd val.int+2,x                 ; add original (times 5)
+                addd 2,s
+                std val.int+2,x
+                puls d,u                        ; (get upper word and clean stack)
+                adcb val.int+1,x
+                adca val.int,x
+                std val.int,x
+                bvs OVERROR2                    ; brif overflow
+                lsl val.int+3,x                 ; shift left again (times 10)
+                rol val.int+2,x
+                rol val.int+1,x
+                rol val.int,x
+                bvs OVERROR2                    ; brif overflow
+                rts
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ; Signed 32 bit integer multiply (X) * (U) -> (Y), overflow if exceeds signed 32 bit range                
 int32_mul       ldd val.int+2,x                 ; copy left operand to temporary
                 std fpa0+fps.sig+2
@@ -227,6 +259,12 @@
                 stb fpa0extra
                 rts
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Integer divide (X) by 10 *in place*
+int32_const10   fqb 10                          ; integer constant 10
+int32_div10     ldu #int32_const10              ; point to integer constant 10
+                leay ,x                         ; point to output location
+                ; fall through to integer division
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ; 32 bit division, integer only, truncate fraction without rounding. Note that there is exactly one case where integer
 ; division can overflow: dividing -0x80000000 by -1 which yields 0x80000000. All other cases reduce the magnitude.
 int32_div       ldd val.int+2,x                 ; copy left operand to temporary