implement mod32, divmod32, etc.

This commit is contained in:
~d6 2021-12-29 16:17:01 -05:00
parent 13d852eae1
commit 5938805c2d
3 changed files with 45 additions and 23 deletions

View File

@ -24,7 +24,9 @@
( sub32 x** y** -> z** x - y )
( mul16 x* y* -> z** x * y )
( mul32 x** y** -> z** x * y )
( div32 x** y** -> z** x / y )
( div32 x** y** -> q** x / y )
( mod32 x** y** -> r** x % y )
( divmod32 x** y** -> q** r** x / y, x % y )
( negate32 x** -> z** -x )
( lshift32 x** n^ -> z** x<<n )
( rshift32 x** n^ -> z** x>>n )
@ -49,7 +51,7 @@
( )
( - shared memory, 16 bytes )
( - mul32 memory, 12 bytes )
( - div32 memory, 16 bytes )
( - _divmod32 memory, 16 bytes )
%DEBUG { #ff #0e DEO }
%RTN { JMP2r }
@ -331,7 +333,6 @@
,&x1 STR2 ,&x0 STR2 ( save xlo, xhi )
,&y1 LDR2 ,&x1 LDR2 ;mul16 JSR2 ( [x1*y1] )
,&z1 STR2 ,&z0 STR2 ( sum = x1*y1, save zlo, zhi )
,&y1 LDR2 ,&x0 LDR2 MUL2 ( [x0*y1]<<16 )
,&y0 LDR2 ,&x1 LDR2 MUL2 ( [x1*y0]<<16 )
( [x0*y0]<<32 will completely overflow )
@ -342,43 +343,66 @@
&y0 $2 &y1 $2
&z0 $2 &z1 $2 ]
( x / y )
@div32 ( x** y** -> q** )
;_divmod32 JSR2
;_divmod32/quo0 LDA2 ;_divmod32/quo1 LDA2
RTN
@mod32 ( x** y** -> r** )
;_divmod32 JSR2
;_divmod32/rem0 LDA2 ;_divmod32/rem1 LDA2
RTN
@divmod32 ( x** y** -> q** r** )
;_divmod32 JSR2
;_divmod32/quo0 LDA2 ;_divmod32/quo1 LDA2
;_divmod32/rem0 LDA2 ;_divmod32/rem1 LDA2
RTN
( calculate and store x / y and x % y )
@_divmod32 ( x** y** -> )
( store y and x for repeated use )
;div32/div1 STA2 ;div32/div0 STA2 ( y -> div )
;div32/rem1 STA2 ;div32/rem0 STA2 ( x -> rem )
,&div1 STR2 ,&div0 STR2 ( y -> div )
,&rem1 STR2 ,&rem0 STR2 ( x -> rem )
( if x < y then the answer is 0 )
;div32/rem0 LDA2 ;div32/rem1 LDA2
;div32/div0 LDA2 ;div32/div1 LDA2
,&rem0 LDR2 ,&rem1 LDR2
,&div0 LDR2 ,&div1 LDR2
;lt32 JSR2 ,&is-zero JCN ,&not-zero JMP
&is-zero
#0000 #0000 RTN
#0000 ,&quo0 STR2 #0000 ,&quo1 STR2 RTN
( x >= y so the answer is >= 1 )
&not-zero
#0000 ;div32/quo0 STA2 #0000 ;div32/quo1 STA2 ( 0 -> quo )
#0000 ,&quo0 STR2 #0000 ,&quo1 STR2 ( 0 -> quo )
( bitcount[x] - bitcount[y] determines the largest multiple of y to try )
;div32/rem0 LDA2 ;div32/rem1 LDA2 ;bitcount32 JSR2 ( rbits^ )
;div32/div0 LDA2 ;div32/div1 LDA2 ;bitcount32 JSR2 ( rbits^ dbits^ )
,&rem0 LDR2 ,&rem1 LDR2 ;bitcount32 JSR2 ( rbits^ )
,&div0 LDR2 ,&div1 LDR2 ;bitcount32 JSR2 ( rbits^ dbits^ )
SUB ( shift=rbits-dits )
#00 DUP2 ( shift 0 shift 0 )
( 1<<shift -> cur )
#0000 #0001 ROT2 POP
;lshift32 JSR2 ;div32/cur1 STA2 ;div32/cur0 STA2
;lshift32 JSR2 ,&cur1 STR2 ,&cur0 STR2
( div<<shift -> div )
;div32/div0 LDA2 ;div32/div1 LDA2 ROT2 POP
;lshift32 JSR2 ;div32/div1 STA2 ;div32/div0 STA2
,&div0 LDR2 ,&div1 LDR2 ROT2 POP
;lshift32 JSR2 ,&div1 STR2 ,&div0 STR2
&loop
,&loop JMP
[ &div0 $2 &div1 $2
&rem0 $2 &rem1 $2
&quo0 $2 &quo1 $2
&cur0 $2 &cur1 $2 ]
&loop
( if rem >= the current divisor, we can subtract it and add to quotient )
,&rem0 LDR2 ,&rem1 LDR2 ,&div0 LDR2 ,&div1 LDR2 ;lt32 JSR2 ( rem<div? )
,&rem0 LDR2 ,&rem1 LDR2 ,&div0 LDR2 ,&div1 LDR2 ;lt32 JSR2 ( is rem < div? )
,&rem-lt JCN ( if rem < div skip this iteration )
( if rem >= div, then we have found a multiple of y that divides x )
( since rem >= div, we have found a multiple of y that divides x )
,&rem0 LDR2 ,&rem1 LDR2 ,&div0 LDR2 ,&div1 LDR2 ;sub32 JSR2 ,&rem1 STR2 ,&rem0 STR2 ( rem -= div )
,&quo0 LDR2 ,&quo1 LDR2 ,&cur0 LDR2 ,&cur1 LDR2 ;add32 JSR2 ,&quo1 STR2 ,&quo0 STR2 ( quo += cur )
@ -386,9 +410,4 @@
,&div0 LDR2 ,&div1 LDR2 #01 ;rshift32 JSR2 ,&div1 STR2 ,&div0 STR2 ( div >>= 1 )
,&cur0 LDR2 ,&cur1 LDR2 #01 ;rshift32 JSR2 ,&cur1 STR2 ,&cur0 STR2 ( cur >>= 1 )
,&cur0 LDR2 ,&cur1 LDR2 ;non-zero32 JSR2 ,&loop JCN ( if cur>0, loop. else we're done )
,&quo0 LDR2 ,&quo1 LDR2 ( TODO: consider making this divmod32 )
RTN
[ &div0 $2 &div1 $2
&rem0 $2 &rem1 $2
&quo0 $2 &quo1 $2
&cur0 $2 &cur1 $2 ]

View File

@ -52,6 +52,7 @@ RTN
;buf LDA LIT '* EQU ;test-mul32 JCN2
;buf LDA LIT '- EQU ;test-sub32 JCN2
;buf LDA LIT '/ EQU ;test-div32 JCN2
;buf LDA LIT '% EQU ;test-mod32 JCN2
;buf LDA LIT 'L EQU ;test-lshift32 JCN2
;buf LDA LIT 'R EQU ;test-rshift32 JCN2
;buf LDA LIT 'B EQU ;test-bitcount32 JCN2
@ -123,6 +124,7 @@ RTN
@test-mul32 ;mul32 ;binary-32-test JMP2
@test-sub32 ;sub32 ;binary-32-test JMP2
@test-div32 ;div32 ;binary-32-test JMP2
@test-mod32 ;mod32 ;binary-32-test JMP2
@test-lshift32 ;lshift32 ;binary-32-8-32-test JMP2
@test-rshift32 ;rshift32 ;binary-32-8-32-test JMP2
@test-bitcount32 ;bitcount32 ;unary-32-8-test JMP2

View File

@ -63,6 +63,7 @@ def main():
test(p, trials, b'-', [('x', u32), ('y', u32)], u32, lambda x, y: x - y)
test(p, trials, b'*', [('x', u32), ('y', u32)], u32, lambda x, y: x * y)
test(p, trials, b'/', [('x', u32), ('y', u32)], u32, lambda x, y: x // y)
test(p, trials, b'%', [('x', u32), ('y', u32)], u32, lambda x, y: x % y)
test(p, trials, b'L', [('x', u32), ('y', u5)], u32, lambda x, y: x << y)
test(p, trials, b'R', [('x', u32), ('y', u5)], u32, lambda x, y: x >> y)
test(p, trials, b'B', [('x', u32)], u8, bitcount)