Mercurial > hg > index.cgi
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