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
18 . Single precision divide for unsigned integers.
20 . Quotient is truncated towards zero.
21 . Traps on divide by zero.
27 . sr0 == return space when called externally
34 OTHER REGISTERS AFFECTED:
38 . Causes a trap under the following conditions:
40 . Changes memory at the following places:
45 . Does not create a stack frame.
46 . Suitable for internal or external millicode.
47 . Assumes the special millicode register conventions.
50 . Branchs to other millicode routines using BE:
51 . $$divU_# for 3,5,6,7,9,10,12,14,15
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. */
57 RDEFINE(retreg,ret1) /* r29 */
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
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 */
80 addit,= 0,arg1,0 /* trap for zero dvr */
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 */
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 */
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, */
168 addc retreg,retreg,retreg /* shift last retreg bit into retreg */
170 /* Handle the cases where divisor is a small constant or has high bit on. */
171 LSYM(special_divisor)
173 /* comib,>,n 0,arg1,LREF(big_divisor) ; nullify previous instruction */
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. */
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. */
185 comib,> 0,arg1,LREF(big_divisor)
190 LSYM(zero_divisor) /* this label is here to provide external visibility */
191 addit,= 0,arg1,0 /* trap for zero dvr */
193 MILLIRET /* divisor == 1 */
195 MILLIRET /* divisor == 2 */
196 extru arg0,30,31,retreg
197 MILLI_BEN($$divU_3) /* divisor == 3 */
199 MILLIRET /* divisor == 4 */
200 extru arg0,29,30,retreg
201 MILLI_BEN($$divU_5) /* divisor == 5 */
203 MILLI_BEN($$divU_6) /* divisor == 6 */
205 MILLI_BEN($$divU_7) /* divisor == 7 */
207 MILLIRET /* divisor == 8 */
208 extru arg0,28,29,retreg
209 MILLI_BEN($$divU_9) /* divisor == 9 */
211 MILLI_BEN($$divU_10) /* divisor == 10 */
213 b LREF(normal) /* divisor == 11 */
214 ds r0,temp,r0 /* set V-bit to 1 */
215 MILLI_BEN($$divU_12) /* divisor == 12 */
217 b LREF(normal) /* divisor == 13 */
218 ds r0,temp,r0 /* set V-bit to 1 */
219 MILLI_BEN($$divU_14) /* divisor == 14 */
221 MILLI_BEN($$divU_15) /* divisor == 15 */
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. */