Pull cpuidle into release branch
[pandora-kernel.git] / arch / parisc / lib / milli / divU.S
1 /* 32 and 64-bit millicode, original author Hewlett-Packard
2    adapted for gcc by Paul Bame <bame@debian.org>
3    and Alan Modra <alan@linuxcare.com.au>.
4
5    Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
6
7    This file is part of GCC and is released under the terms of
8    of the GNU General Public License as published by the Free Software
9    Foundation; either version 2, or (at your option) any later version.
10    See the file COPYING in the top-level GCC source directory for a copy
11    of the license.  */
12
13 #include "milli.h"
14
15 #ifdef L_divU
16 /* ROUTINE:     $$divU
17    .
18    .    Single precision divide for unsigned integers.
19    .
20    .    Quotient is truncated towards zero.
21    .    Traps on divide by zero.
22
23    INPUT REGISTERS:
24    .    arg0 == dividend
25    .    arg1 == divisor
26    .    mrp  == return pc
27    .    sr0  == return space when called externally
28
29    OUTPUT REGISTERS:
30    .    arg0 =  undefined
31    .    arg1 =  undefined
32    .    ret1 =  quotient
33
34    OTHER REGISTERS AFFECTED:
35    .    r1   =  undefined
36
37    SIDE EFFECTS:
38    .    Causes a trap under the following conditions:
39    .            divisor is zero
40    .    Changes memory at the following places:
41    .            NONE
42
43    PERMISSIBLE CONTEXT:
44    .    Unwindable.
45    .    Does not create a stack frame.
46    .    Suitable for internal or external millicode.
47    .    Assumes the special millicode register conventions.
48
49    DISCUSSION:
50    .    Branchs to other millicode routines using BE:
51    .            $$divU_# for 3,5,6,7,9,10,12,14,15
52    .
53    .    For selected small divisors calls the special divide by constant
54    .    routines written by Karl Pettis.  These are: 3,5,6,7,9,10,12,14,15.  */
55
56 RDEFINE(temp,r1)
57 RDEFINE(retreg,ret1)    /* r29 */
58 RDEFINE(temp1,arg0)
59         SUBSPA_MILLI_DIV
60         ATTR_MILLI
61         .export $$divU,millicode
62         .import $$divU_3,millicode
63         .import $$divU_5,millicode
64         .import $$divU_6,millicode
65         .import $$divU_7,millicode
66         .import $$divU_9,millicode
67         .import $$divU_10,millicode
68         .import $$divU_12,millicode
69         .import $$divU_14,millicode
70         .import $$divU_15,millicode
71         .proc
72         .callinfo       millicode
73         .entry
74 GSYM($$divU)
75 /* The subtract is not nullified since it does no harm and can be used
76    by the two cases that branch back to "normal".  */
77         ldo     -1(arg1),temp           /* is there at most one bit set ? */
78         and,=   arg1,temp,r0            /* if so, denominator is power of 2 */
79         b       LREF(regular_seq)
80         addit,= 0,arg1,0                /* trap for zero dvr */
81         copy    arg0,retreg
82         extru,= arg1,15,16,temp         /* test denominator with 0xffff0000 */
83         extru   retreg,15,16,retreg     /* retreg = retreg >> 16 */
84         or      arg1,temp,arg1          /* arg1 = arg1 | (arg1 >> 16) */
85         ldi     0xcc,temp1              /* setup 0xcc in temp1 */
86         extru,= arg1,23,8,temp          /* test denominator with 0xff00 */
87         extru   retreg,23,24,retreg     /* retreg = retreg >> 8 */
88         or      arg1,temp,arg1          /* arg1 = arg1 | (arg1 >> 8) */
89         ldi     0xaa,temp               /* setup 0xaa in temp */
90         extru,= arg1,27,4,r0            /* test denominator with 0xf0 */
91         extru   retreg,27,28,retreg     /* retreg = retreg >> 4 */
92         and,=   arg1,temp1,r0           /* test denominator with 0xcc */
93         extru   retreg,29,30,retreg     /* retreg = retreg >> 2 */
94         and,=   arg1,temp,r0            /* test denominator with 0xaa */
95         extru   retreg,30,31,retreg     /* retreg = retreg >> 1 */
96         MILLIRETN
97         nop     
98 LSYM(regular_seq)
99         comib,>=  15,arg1,LREF(special_divisor)
100         subi    0,arg1,temp             /* clear carry, negate the divisor */
101         ds      r0,temp,r0              /* set V-bit to 1 */
102 LSYM(normal)
103         add     arg0,arg0,retreg        /* shift msb bit into carry */
104         ds      r0,arg1,temp            /* 1st divide step, if no carry */
105         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
106         ds      temp,arg1,temp          /* 2nd divide step */
107         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
108         ds      temp,arg1,temp          /* 3rd divide step */
109         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
110         ds      temp,arg1,temp          /* 4th divide step */
111         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
112         ds      temp,arg1,temp          /* 5th divide step */
113         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
114         ds      temp,arg1,temp          /* 6th divide step */
115         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
116         ds      temp,arg1,temp          /* 7th divide step */
117         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
118         ds      temp,arg1,temp          /* 8th divide step */
119         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
120         ds      temp,arg1,temp          /* 9th divide step */
121         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
122         ds      temp,arg1,temp          /* 10th divide step */
123         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
124         ds      temp,arg1,temp          /* 11th divide step */
125         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
126         ds      temp,arg1,temp          /* 12th divide step */
127         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
128         ds      temp,arg1,temp          /* 13th divide step */
129         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
130         ds      temp,arg1,temp          /* 14th divide step */
131         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
132         ds      temp,arg1,temp          /* 15th divide step */
133         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
134         ds      temp,arg1,temp          /* 16th divide step */
135         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
136         ds      temp,arg1,temp          /* 17th divide step */
137         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
138         ds      temp,arg1,temp          /* 18th divide step */
139         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
140         ds      temp,arg1,temp          /* 19th divide step */
141         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
142         ds      temp,arg1,temp          /* 20th divide step */
143         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
144         ds      temp,arg1,temp          /* 21st divide step */
145         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
146         ds      temp,arg1,temp          /* 22nd divide step */
147         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
148         ds      temp,arg1,temp          /* 23rd divide step */
149         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
150         ds      temp,arg1,temp          /* 24th divide step */
151         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
152         ds      temp,arg1,temp          /* 25th divide step */
153         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
154         ds      temp,arg1,temp          /* 26th divide step */
155         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
156         ds      temp,arg1,temp          /* 27th divide step */
157         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
158         ds      temp,arg1,temp          /* 28th divide step */
159         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
160         ds      temp,arg1,temp          /* 29th divide step */
161         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
162         ds      temp,arg1,temp          /* 30th divide step */
163         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
164         ds      temp,arg1,temp          /* 31st divide step */
165         addc    retreg,retreg,retreg    /* shift retreg with/into carry */
166         ds      temp,arg1,temp          /* 32nd divide step, */
167         MILLIRET
168         addc    retreg,retreg,retreg    /* shift last retreg bit into retreg */
169
170 /* Handle the cases where divisor is a small constant or has high bit on.  */
171 LSYM(special_divisor)
172 /*      blr     arg1,r0 */
173 /*      comib,>,n  0,arg1,LREF(big_divisor) ; nullify previous instruction */
174
175 /* Pratap 8/13/90. The 815 Stirling chip set has a bug that prevents us from
176    generating such a blr, comib sequence. A problem in nullification. So I
177    rewrote this code.  */
178
179 #if defined(CONFIG_64BIT)
180 /* Clear the upper 32 bits of the arg1 register.  We are working with
181    small divisors (and 32-bit unsigned integers)   We must not be mislead
182    by "1" bits left in the upper 32 bits.  */
183         depd %r0,31,32,%r25
184 #endif
185         comib,> 0,arg1,LREF(big_divisor)
186         nop
187         blr     arg1,r0
188         nop
189
190 LSYM(zero_divisor)      /* this label is here to provide external visibility */
191         addit,= 0,arg1,0                /* trap for zero dvr */
192         nop
193         MILLIRET                        /* divisor == 1 */
194         copy    arg0,retreg
195         MILLIRET                        /* divisor == 2 */
196         extru   arg0,30,31,retreg
197         MILLI_BEN($$divU_3)             /* divisor == 3 */
198         nop
199         MILLIRET                        /* divisor == 4 */
200         extru   arg0,29,30,retreg
201         MILLI_BEN($$divU_5)             /* divisor == 5 */
202         nop
203         MILLI_BEN($$divU_6)             /* divisor == 6 */
204         nop
205         MILLI_BEN($$divU_7)             /* divisor == 7 */
206         nop
207         MILLIRET                        /* divisor == 8 */
208         extru   arg0,28,29,retreg
209         MILLI_BEN($$divU_9)             /* divisor == 9 */
210         nop
211         MILLI_BEN($$divU_10)            /* divisor == 10 */
212         nop
213         b       LREF(normal)            /* divisor == 11 */
214         ds      r0,temp,r0              /* set V-bit to 1 */
215         MILLI_BEN($$divU_12)            /* divisor == 12 */
216         nop
217         b       LREF(normal)            /* divisor == 13 */
218         ds      r0,temp,r0              /* set V-bit to 1 */
219         MILLI_BEN($$divU_14)            /* divisor == 14 */
220         nop
221         MILLI_BEN($$divU_15)            /* divisor == 15 */
222         nop
223
224 /* Handle the case where the high bit is on in the divisor.
225    Compute:     if( dividend>=divisor) quotient=1; else quotient=0;
226    Note:        dividend>==divisor iff dividend-divisor does not borrow
227    and          not borrow iff carry.  */
228 LSYM(big_divisor)
229         sub     arg0,arg1,r0
230         MILLIRET
231         addc    r0,r0,retreg
232         .exit
233         .procend
234         .end
235 #endif