Revert "Bias the placement of kernel pages at lower PFNs"
[linux-2.6] / arch / parisc / lib / milli / divI.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_divI
16 /* ROUTINES:    $$divI, $$divoI
17
18    Single precision divide for signed binary integers.
19
20    The quotient is truncated towards zero.
21    The sign of the quotient is the XOR of the signs of the dividend and
22    divisor.
23    Divide by zero is trapped.
24    Divide of -2**31 by -1 is trapped for $$divoI but not for $$divI.
25
26    INPUT REGISTERS:
27    .    arg0 == dividend
28    .    arg1 == divisor
29    .    mrp  == return pc
30    .    sr0  == return space when called externally
31
32    OUTPUT REGISTERS:
33    .    arg0 =  undefined
34    .    arg1 =  undefined
35    .    ret1 =  quotient
36
37    OTHER REGISTERS AFFECTED:
38    .    r1   =  undefined
39
40    SIDE EFFECTS:
41    .    Causes a trap under the following conditions:
42    .            divisor is zero  (traps with ADDIT,=  0,25,0)
43    .            dividend==-2**31  and divisor==-1 and routine is $$divoI
44    .                             (traps with ADDO  26,25,0)
45    .    Changes memory at the following places:
46    .            NONE
47
48    PERMISSIBLE CONTEXT:
49    .    Unwindable.
50    .    Suitable for internal or external millicode.
51    .    Assumes the special millicode register conventions.
52
53    DISCUSSION:
54    .    Branchs to other millicode routines using BE
55    .            $$div_# for # being 2,3,4,5,6,7,8,9,10,12,14,15
56    .
57    .    For selected divisors, calls a divide by constant routine written by
58    .    Karl Pettis.  Eligible divisors are 1..15 excluding 11 and 13.
59    .
60    .    The only overflow case is -2**31 divided by -1.
61    .    Both routines return -2**31 but only $$divoI traps.  */
62
63 RDEFINE(temp,r1)
64 RDEFINE(retreg,ret1)    /*  r29 */
65 RDEFINE(temp1,arg0)
66         SUBSPA_MILLI_DIV
67         ATTR_MILLI
68         .import $$divI_2,millicode
69         .import $$divI_3,millicode
70         .import $$divI_4,millicode
71         .import $$divI_5,millicode
72         .import $$divI_6,millicode
73         .import $$divI_7,millicode
74         .import $$divI_8,millicode
75         .import $$divI_9,millicode
76         .import $$divI_10,millicode
77         .import $$divI_12,millicode
78         .import $$divI_14,millicode
79         .import $$divI_15,millicode
80         .export $$divI,millicode
81         .export $$divoI,millicode
82         .proc
83         .callinfo       millicode
84         .entry
85 GSYM($$divoI)
86         comib,=,n  -1,arg1,LREF(negative1)      /*  when divisor == -1 */
87 GSYM($$divI)
88         ldo     -1(arg1),temp           /*  is there at most one bit set ? */
89         and,<>  arg1,temp,r0            /*  if not, don't use power of 2 divide */
90         addi,>  0,arg1,r0               /*  if divisor > 0, use power of 2 divide */
91         b,n     LREF(neg_denom)
92 LSYM(pow2)
93         addi,>= 0,arg0,retreg           /*  if numerator is negative, add the */
94         add     arg0,temp,retreg        /*  (denominaotr -1) to correct for shifts */
95         extru,= arg1,15,16,temp         /*  test denominator with 0xffff0000 */
96         extrs   retreg,15,16,retreg     /*  retreg = retreg >> 16 */
97         or      arg1,temp,arg1          /*  arg1 = arg1 | (arg1 >> 16) */
98         ldi     0xcc,temp1              /*  setup 0xcc in temp1 */
99         extru,= arg1,23,8,temp          /*  test denominator with 0xff00 */
100         extrs   retreg,23,24,retreg     /*  retreg = retreg >> 8 */
101         or      arg1,temp,arg1          /*  arg1 = arg1 | (arg1 >> 8) */
102         ldi     0xaa,temp               /*  setup 0xaa in temp */
103         extru,= arg1,27,4,r0            /*  test denominator with 0xf0 */
104         extrs   retreg,27,28,retreg     /*  retreg = retreg >> 4 */
105         and,=   arg1,temp1,r0           /*  test denominator with 0xcc */
106         extrs   retreg,29,30,retreg     /*  retreg = retreg >> 2 */
107         and,=   arg1,temp,r0            /*  test denominator with 0xaa */
108         extrs   retreg,30,31,retreg     /*  retreg = retreg >> 1 */
109         MILLIRETN
110 LSYM(neg_denom)
111         addi,<  0,arg1,r0               /*  if arg1 >= 0, it's not power of 2 */
112         b,n     LREF(regular_seq)
113         sub     r0,arg1,temp            /*  make denominator positive */
114         comb,=,n  arg1,temp,LREF(regular_seq)   /*  test against 0x80000000 and 0 */
115         ldo     -1(temp),retreg         /*  is there at most one bit set ? */
116         and,=   temp,retreg,r0          /*  if so, the denominator is power of 2 */
117         b,n     LREF(regular_seq)
118         sub     r0,arg0,retreg          /*  negate numerator */
119         comb,=,n arg0,retreg,LREF(regular_seq) /*  test against 0x80000000 */
120         copy    retreg,arg0             /*  set up arg0, arg1 and temp  */
121         copy    temp,arg1               /*  before branching to pow2 */
122         b       LREF(pow2)
123         ldo     -1(arg1),temp
124 LSYM(regular_seq)
125         comib,>>=,n 15,arg1,LREF(small_divisor)
126         add,>=  0,arg0,retreg           /*  move dividend, if retreg < 0, */
127 LSYM(normal)
128         subi    0,retreg,retreg         /*    make it positive */
129         sub     0,arg1,temp             /*  clear carry,  */
130                                         /*    negate the divisor */
131         ds      0,temp,0                /*  set V-bit to the comple- */
132                                         /*    ment of the divisor sign */
133         add     retreg,retreg,retreg    /*  shift msb bit into carry */
134         ds      r0,arg1,temp            /*  1st divide step, if no carry */
135         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
136         ds      temp,arg1,temp          /*  2nd divide step */
137         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
138         ds      temp,arg1,temp          /*  3rd divide step */
139         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
140         ds      temp,arg1,temp          /*  4th divide step */
141         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
142         ds      temp,arg1,temp          /*  5th divide step */
143         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
144         ds      temp,arg1,temp          /*  6th divide step */
145         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
146         ds      temp,arg1,temp          /*  7th divide step */
147         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
148         ds      temp,arg1,temp          /*  8th divide step */
149         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
150         ds      temp,arg1,temp          /*  9th divide step */
151         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
152         ds      temp,arg1,temp          /*  10th divide step */
153         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
154         ds      temp,arg1,temp          /*  11th divide step */
155         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
156         ds      temp,arg1,temp          /*  12th divide step */
157         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
158         ds      temp,arg1,temp          /*  13th divide step */
159         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
160         ds      temp,arg1,temp          /*  14th divide step */
161         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
162         ds      temp,arg1,temp          /*  15th divide step */
163         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
164         ds      temp,arg1,temp          /*  16th divide step */
165         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
166         ds      temp,arg1,temp          /*  17th divide step */
167         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
168         ds      temp,arg1,temp          /*  18th divide step */
169         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
170         ds      temp,arg1,temp          /*  19th divide step */
171         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
172         ds      temp,arg1,temp          /*  20th divide step */
173         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
174         ds      temp,arg1,temp          /*  21st divide step */
175         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
176         ds      temp,arg1,temp          /*  22nd divide step */
177         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
178         ds      temp,arg1,temp          /*  23rd divide step */
179         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
180         ds      temp,arg1,temp          /*  24th divide step */
181         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
182         ds      temp,arg1,temp          /*  25th divide step */
183         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
184         ds      temp,arg1,temp          /*  26th divide step */
185         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
186         ds      temp,arg1,temp          /*  27th divide step */
187         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
188         ds      temp,arg1,temp          /*  28th divide step */
189         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
190         ds      temp,arg1,temp          /*  29th divide step */
191         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
192         ds      temp,arg1,temp          /*  30th divide step */
193         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
194         ds      temp,arg1,temp          /*  31st divide step */
195         addc    retreg,retreg,retreg    /*  shift retreg with/into carry */
196         ds      temp,arg1,temp          /*  32nd divide step, */
197         addc    retreg,retreg,retreg    /*  shift last retreg bit into retreg */
198         xor,>=  arg0,arg1,0             /*  get correct sign of quotient */
199           sub   0,retreg,retreg         /*    based on operand signs */
200         MILLIRETN
201         nop
202
203 LSYM(small_divisor)
204
205 #if defined(CONFIG_64BIT)
206 /*  Clear the upper 32 bits of the arg1 register.  We are working with  */
207 /*  small divisors (and 32-bit integers)   We must not be mislead  */
208 /*  by "1" bits left in the upper 32 bits.  */
209         depd %r0,31,32,%r25
210 #endif
211         blr,n   arg1,r0
212         nop
213 /*  table for divisor == 0,1, ... ,15 */
214         addit,= 0,arg1,r0       /*  trap if divisor == 0 */
215         nop
216         MILLIRET                /*  divisor == 1 */
217         copy    arg0,retreg
218         MILLI_BEN($$divI_2)     /*  divisor == 2 */
219         nop
220         MILLI_BEN($$divI_3)     /*  divisor == 3 */
221         nop
222         MILLI_BEN($$divI_4)     /*  divisor == 4 */
223         nop
224         MILLI_BEN($$divI_5)     /*  divisor == 5 */
225         nop
226         MILLI_BEN($$divI_6)     /*  divisor == 6 */
227         nop
228         MILLI_BEN($$divI_7)     /*  divisor == 7 */
229         nop
230         MILLI_BEN($$divI_8)     /*  divisor == 8 */
231         nop
232         MILLI_BEN($$divI_9)     /*  divisor == 9 */
233         nop
234         MILLI_BEN($$divI_10)    /*  divisor == 10 */
235         nop
236         b       LREF(normal)            /*  divisor == 11 */
237         add,>=  0,arg0,retreg
238         MILLI_BEN($$divI_12)    /*  divisor == 12 */
239         nop
240         b       LREF(normal)            /*  divisor == 13 */
241         add,>=  0,arg0,retreg
242         MILLI_BEN($$divI_14)    /*  divisor == 14 */
243         nop
244         MILLI_BEN($$divI_15)    /*  divisor == 15 */
245         nop
246
247 LSYM(negative1)
248         sub     0,arg0,retreg   /*  result is negation of dividend */
249         MILLIRET
250         addo    arg0,arg1,r0    /*  trap iff dividend==0x80000000 && divisor==-1 */
251         .exit
252         .procend
253         .end
254 #endif