1 | long division
and modulus routines
3 | written by Kai-Uwe Bloem
(I5110401@dbstu1.bitnet
).
6 | Revision
1.1, kub
03-90
7 | first version
, replaces the appropriate routine from fixnum.s.
8 | Should
be faster in more common cases. Division is done by
68000 divu
9 | operations if divisor is only
16 bits wide. Otherwise the normal division
10 | algorithm as described in various papers takes place. The division routine
11 | delivers the quotient in d0
and the remainder in
%d1
, thus the implementation
12 | of the modulo operation is trivial. We gain some extra speed by inlining
13 | the division code here instead of calling _udivsi3.
21 movel
%d2
,%a0 | save registers
23 clrw
%sp@
- | sign flag
24 clrl
%d0 | prepare result
25 movel
%sp@
(10),%d2 | get divisor
26 beq L_9 | divisor
= 0 causes
a division
trap
27 bpl L_00 | divisor
< 0 ?
29 notw
%sp@ | remember sign
30 L_00
: movel
%sp@
(6),%d1 | get dividend
31 bpl L_01 | dividend
< 0 ?
33 notw
%sp@ | remember sign
35 |
== case
1) divident
< divisor
36 cmpl %d2
,%d1 | is divident smaller then divisor ?
37 bcs L_8 | yes
, return immediately
38 |
== case
2) divisor has
<= 16 significant bits
40 bne L_2 | divisor has only
16 bits
41 movew
%d1
,%d3 | save dividend
42 clrw
%d1 | divide dvd.h by dvs
44 beq L_02 |
(no division necessary if dividend zero
)
46 L_02
: movew
%d1
,%d0 | save quotient.h
48 movew
%d3
,%d1 |
(%d0.h
= remainder of prev divu
)
49 divu
%d2
,%d1 | divide dvd.
l by dvs
50 movew
%d1
,%d0 | save quotient.
l
51 clrw
%d1 | get remainder
54 |
== case
3) divisor
> 16 bits
(corollary is dividend
> 16 bits
, see case
1)
56 moveq
#31,%d3 | loop count
58 addl
%d1
,%d1 | shift divident
...
59 addxl
%d0
,%d0 |
... into %d0
60 cmpl %d2
,%d0 | compare with divisor
62 subl
%d2
,%d0 | big enough
, subtract
63 addw
#1,%d1 | and note bit into result
66 exg
%d0
,%d1 | put quotient
and remainder in their registers
68 tstw
%sp@
(6) | must the remainder
be corrected ?
70 negl
%d1 | yes
, apply sign
71 | the following line would
be correct if modulus is defined as in algebra
72 | addl
%sp@
(6),%d1 | algebraic correction
: modulus can only
be >= 0
73 L_04
: tstw
%sp@
+ | result should
be negative ?
75 negl
%d0 | yes
, negate it
81 divu
%d2
,%d1 | cause division
trap
82 bra L_8 | back to user
86 movel
%sp@
(8),%sp@
- | push divisor
87 movel
%sp@
(8),%sp@
- | push dividend
90 movel
%d1
,%d0 | return the remainder in
%d0