Added missing properties.
[tangerine.git] / arch / m68k-mac / libgcc1 / _divmodsi3.s
blobe8dc91d28ce2bd50eccc3efa39cebf0939328787
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.
15 .text
16 .even
17 .globl __divsi3
18 .globl __modsi3
20 __divsi3:
21 movel %d2,%a0 | save registers
22 movel %d3,%a1
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 ?
28 negl %d2 | negate it
29 notw %sp@ | remember sign
30 L_00: movel %sp@(6),%d1 | get dividend
31 bpl L_01 | dividend < 0 ?
32 negl %d1 | negate it
33 notw %sp@ | remember sign
34 L_01:
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
39 tstw %sp@(10)
40 bne L_2 | divisor has only 16 bits
41 movew %d1,%d3 | save dividend
42 clrw %d1 | divide dvd.h by dvs
43 swap %d1
44 beq L_02 | (no division necessary if dividend zero)
45 divu %d2,%d1
46 L_02: movew %d1,%d0 | save quotient.h
47 swap %d0
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
52 swap %d1
53 bra L_8 | and return
54 |== case 3) divisor > 16 bits (corollary is dividend > 16 bits, see case 1)
55 L_2:
56 moveq #31,%d3 | loop count
57 L_3:
58 addl %d1,%d1 | shift divident ...
59 addxl %d0,%d0 | ... into %d0
60 cmpl %d2,%d0 | compare with divisor
61 bcs L_03
62 subl %d2,%d0 | big enough, subtract
63 addw #1,%d1 | and note bit into result
64 L_03:
65 dbra %d3,L_3
66 exg %d0,%d1 | put quotient and remainder in their registers
67 L_8:
68 tstw %sp@(6) | must the remainder be corrected ?
69 bpl L_04
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 ?
74 bpl L_05
75 negl %d0 | yes, negate it
76 L_05:
77 movel %a1,%d3
78 movel %a0,%d2
79 rts
80 L_9:
81 divu %d2,%d1 | cause division trap
82 bra L_8 | back to user
85 __modsi3:
86 movel %sp@(8),%sp@- | push divisor
87 movel %sp@(8),%sp@- | push dividend
88 jbsr __divsi3
89 addql #8,%sp
90 movel %d1,%d0 | return the remainder in %d0
91 rts