aboutsummaryrefslogtreecommitdiffstats
path: root/arch/parisc/lib/milli/divI.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/parisc/lib/milli/divI.S')
-rw-r--r--arch/parisc/lib/milli/divI.S254
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
63RDEFINE(temp,r1)
64RDEFINE(retreg,ret1) /* r29 */
65RDEFINE(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
85GSYM($$divoI)
86 comib,=,n -1,arg1,LREF(negative1) /* when divisor == -1 */
87GSYM($$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)
92LSYM(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
110LSYM(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
124LSYM(regular_seq)
125 comib,>>=,n 15,arg1,LREF(small_divisor)
126 add,>= 0,arg0,retreg /* move dividend, if retreg < 0, */
127LSYM(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
203LSYM(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
247LSYM(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