diff options
Diffstat (limited to 'arch/parisc/lib/milli/divU.S')
-rw-r--r-- | arch/parisc/lib/milli/divU.S | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/arch/parisc/lib/milli/divU.S b/arch/parisc/lib/milli/divU.S new file mode 100644 index 000000000000..9287fe2546fa --- /dev/null +++ b/arch/parisc/lib/milli/divU.S | |||
@@ -0,0 +1,235 @@ | |||
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 | ||