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