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>.
5 Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
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
16 /* ROUTINES: $$divI, $$divoI
18 Single precision divide for signed binary integers.
20 The quotient is truncated towards zero.
21 The sign of the quotient is the XOR of the signs of the dividend and
23 Divide by zero is trapped.
24 Divide of -2**31 by -1 is trapped for $$divoI but not for $$divI.
30 . sr0 == return space when called externally
37 OTHER REGISTERS AFFECTED:
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:
50 . Suitable for internal or external millicode.
51 . Assumes the special millicode register conventions.
54 . Branchs to other millicode routines using BE
55 . $$div_# for # being 2,3,4,5,6,7,8,9,10,12,14,15
57 . For selected divisors, calls a divide by constant routine written by
58 . Karl Pettis. Eligible divisors are 1..15 excluding 11 and 13.
60 . The only overflow case is -2**31 divided by -1.
61 . Both routines return -2**31 but only $$divoI traps. */
64 RDEFINE(retreg,ret1) /* r29 */
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
86 comib,=,n -1,arg1,LREF(negative1) /* when divisor == -1 */
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 */
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 */
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 */
125 comib,>>=,n 15,arg1,LREF(small_divisor)
126 add,>= 0,arg0,retreg /* move dividend, if retreg < 0, */
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 */
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. */
213 /* table for divisor == 0,1, ... ,15 */
214 addit,= 0,arg1,r0 /* trap if divisor == 0 */
216 MILLIRET /* divisor == 1 */
218 MILLI_BEN($$divI_2) /* divisor == 2 */
220 MILLI_BEN($$divI_3) /* divisor == 3 */
222 MILLI_BEN($$divI_4) /* divisor == 4 */
224 MILLI_BEN($$divI_5) /* divisor == 5 */
226 MILLI_BEN($$divI_6) /* divisor == 6 */
228 MILLI_BEN($$divI_7) /* divisor == 7 */
230 MILLI_BEN($$divI_8) /* divisor == 8 */
232 MILLI_BEN($$divI_9) /* divisor == 9 */
234 MILLI_BEN($$divI_10) /* divisor == 10 */
236 b LREF(normal) /* divisor == 11 */
238 MILLI_BEN($$divI_12) /* divisor == 12 */
240 b LREF(normal) /* divisor == 13 */
242 MILLI_BEN($$divI_14) /* divisor == 14 */
244 MILLI_BEN($$divI_15) /* divisor == 15 */
248 sub 0,arg0,retreg /* result is negation of dividend */
250 addo arg0,arg1,r0 /* trap iff dividend==0x80000000 && divisor==-1 */