]>
Commit | Line | Data |
---|---|---|
99dee823 | 1 | ;; Copyright (C) 2001-2021 Free Software Foundation, Inc. |
ad41bd84 JM |
2 | ;; |
3 | ;; This file is part of GCC. | |
4 | ;; | |
5 | ;; GCC is free software; you can redistribute it and/or modify it under | |
6 | ;; the terms of the GNU General Public License as published by the Free | |
7 | ;; Software Foundation; either version 3, or (at your option) any later | |
8 | ;; version. | |
9 | ;; | |
10 | ;; GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
11 | ;; WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
12 | ;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
13 | ;; for more details. | |
14 | ;; | |
15 | ;; Under Section 7 of GPL version 3, you are granted additional | |
16 | ;; permissions described in the GCC Runtime Library Exception, version | |
17 | ;; 3.1, as published by the Free Software Foundation. | |
18 | ;; | |
19 | ;; You should have received a copy of the GNU General Public License and | |
20 | ;; a copy of the GCC Runtime Library Exception along with this program; | |
21 | ;; see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
22 | ;; <http://www.gnu.org/licenses/>. | |
23 | ;; | |
0b85d816 HPN |
24 | ;; This code used to be expanded through interesting expansions in |
25 | ;; the machine description, compiled from this code: | |
26 | ;; | |
27 | ;; #ifdef L_mulsi3 | |
28 | ;; long __Mul (unsigned long a, unsigned long b) __attribute__ ((__const__)); | |
29 | ;; | |
30 | ;; /* This must be compiled with the -mexpand-mul flag, to synthesize the | |
31 | ;; multiplication from the mstep instructions. The check for | |
32 | ;; smaller-size multiplication pays off in the order of .5-10%; | |
33 | ;; estimated median 1%, depending on application. | |
34 | ;; FIXME: It can be further optimized if we go to assembler code, as | |
35 | ;; gcc 2.7.2 adds a few unnecessary instructions and does not put the | |
36 | ;; basic blocks in optimal order. */ | |
37 | ;; long | |
38 | ;; __Mul (unsigned long a, unsigned long b) | |
39 | ;; { | |
40 | ;; #if defined (__CRIS_arch_version) && __CRIS_arch_version >= 10 | |
41 | ;; /* In case other code is compiled without -march=v10, they will | |
42 | ;; contain calls to __Mul, regardless of flags at link-time. The | |
43 | ;; "else"-code below will work, but is unnecessarily slow. This | |
44 | ;; sometimes cuts a few minutes off from simulation time by just | |
45 | ;; returning a "mulu.d". */ | |
46 | ;; return a * b; | |
47 | ;; #else | |
48 | ;; unsigned long min; | |
49 | ;; | |
50 | ;; /* Get minimum via the bound insn. */ | |
51 | ;; min = a < b ? a : b; | |
52 | ;; | |
53 | ;; /* Can we omit computation of the high part? */ | |
54 | ;; if (min > 65535) | |
55 | ;; /* No. Perform full multiplication. */ | |
56 | ;; return a * b; | |
57 | ;; else | |
58 | ;; { | |
59 | ;; /* Check if both operands are within 16 bits. */ | |
60 | ;; unsigned long max; | |
61 | ;; | |
62 | ;; /* Get maximum, by knowing the minimum. | |
63 | ;; This will partition a and b into max and min. | |
64 | ;; This is not currently something GCC understands, | |
65 | ;; so do this trick by asm. */ | |
66 | ;; __asm__ ("xor %1,%0\n\txor %2,%0" | |
67 | ;; : "=r" (max) | |
68 | ;; : "r" (b), "r" (a), "0" (min)); | |
69 | ;; | |
70 | ;; if (max > 65535) | |
71 | ;; /* Make GCC understand that only the low part of "min" will be | |
72 | ;; used. */ | |
73 | ;; return max * (unsigned short) min; | |
74 | ;; else | |
75 | ;; /* Only the low parts of both operands are necessary. */ | |
76 | ;; return ((unsigned short) max) * (unsigned short) min; | |
77 | ;; } | |
78 | ;; #endif /* not __CRIS_arch_version >= 10 */ | |
79 | ;; } | |
80 | ;; #endif /* L_mulsi3 */ | |
81 | ;; | |
82 | ;; That approach was abandoned since the caveats outweighted the | |
83 | ;; benefits. The expand-multiplication machinery is also removed, so you | |
84 | ;; can't do this anymore. | |
85 | ;; | |
86 | ;; For doubters of there being any benefits, some where: insensitivity to: | |
87 | ;; - ABI changes (mostly for experimentation) | |
88 | ;; - assembler syntax differences (mostly debug format). | |
89 | ;; - insn scheduling issues. | |
90 | ;; Most ABI experiments will presumably happen with arches with mul insns, | |
91 | ;; so that argument doesn't really hold anymore, and it's unlikely there | |
92 | ;; being new arch variants needing insn scheduling and not having mul | |
93 | ;; insns. | |
94 | ||
95 | ;; ELF and a.out have different syntax for local labels: the "wrong" | |
96 | ;; one may not be omitted from the object. | |
97 | #undef L | |
98 | #ifdef __AOUT__ | |
99 | # define L(x) x | |
100 | #else | |
101 | # define L(x) .x | |
102 | #endif | |
103 | ||
104 | .global ___Mul | |
105 | .type ___Mul,@function | |
106 | ___Mul: | |
107 | #if defined (__CRIS_arch_version) && __CRIS_arch_version >= 10 | |
86da66b5 HPN |
108 | ;; Can't have the mulu.d last on a cache-line (in the delay-slot of the |
109 | ;; "ret"), due to hardware bug. See documentation for -mmul-bug-workaround. | |
110 | ;; Not worthwhile to conditionalize here. | |
111 | .p2alignw 2,0x050f | |
0b85d816 | 112 | mulu.d $r11,$r10 |
86da66b5 HPN |
113 | ret |
114 | nop | |
0b85d816 | 115 | #else |
0e499e75 HPN |
116 | ;; See if we can avoid multiplying some of the parts, knowing |
117 | ;; they're zero. | |
118 | ||
0b85d816 | 119 | move.d $r11,$r9 |
0e499e75 | 120 | bound.d $r10,$r9 |
0b85d816 HPN |
121 | cmpu.w 65535,$r9 |
122 | bls L(L3) | |
0e499e75 | 123 | move.d $r10,$r12 |
0b85d816 | 124 | |
0e499e75 HPN |
125 | ;; Nope, have to do all the parts of a 32-bit multiplication. |
126 | ;; See head comment in optabs.c:expand_doubleword_mult. | |
127 | ||
128 | move.d $r10,$r13 | |
129 | movu.w $r11,$r9 ; ab*cd = (a*d + b*c)<<16 + b*d | |
0b85d816 | 130 | lslq 16,$r13 |
0e499e75 | 131 | mstep $r9,$r13 ; d*b |
0b85d816 HPN |
132 | mstep $r9,$r13 |
133 | mstep $r9,$r13 | |
134 | mstep $r9,$r13 | |
135 | mstep $r9,$r13 | |
136 | mstep $r9,$r13 | |
137 | mstep $r9,$r13 | |
138 | mstep $r9,$r13 | |
139 | mstep $r9,$r13 | |
140 | mstep $r9,$r13 | |
141 | mstep $r9,$r13 | |
142 | mstep $r9,$r13 | |
143 | mstep $r9,$r13 | |
144 | mstep $r9,$r13 | |
145 | mstep $r9,$r13 | |
146 | mstep $r9,$r13 | |
147 | clear.w $r10 | |
148 | test.d $r10 | |
0e499e75 | 149 | mstep $r9,$r10 ; d*a |
0b85d816 HPN |
150 | mstep $r9,$r10 |
151 | mstep $r9,$r10 | |
152 | mstep $r9,$r10 | |
153 | mstep $r9,$r10 | |
154 | mstep $r9,$r10 | |
155 | mstep $r9,$r10 | |
156 | mstep $r9,$r10 | |
157 | mstep $r9,$r10 | |
158 | mstep $r9,$r10 | |
159 | mstep $r9,$r10 | |
160 | mstep $r9,$r10 | |
161 | mstep $r9,$r10 | |
162 | mstep $r9,$r10 | |
163 | mstep $r9,$r10 | |
164 | mstep $r9,$r10 | |
165 | movu.w $r12,$r12 | |
0e499e75 HPN |
166 | clear.w $r11 |
167 | move.d $r11,$r9 ; Doubles as a "test.d" preparing for the mstep. | |
168 | mstep $r12,$r9 ; b*c | |
0b85d816 HPN |
169 | mstep $r12,$r9 |
170 | mstep $r12,$r9 | |
171 | mstep $r12,$r9 | |
172 | mstep $r12,$r9 | |
173 | mstep $r12,$r9 | |
174 | mstep $r12,$r9 | |
175 | mstep $r12,$r9 | |
176 | mstep $r12,$r9 | |
177 | mstep $r12,$r9 | |
178 | mstep $r12,$r9 | |
179 | mstep $r12,$r9 | |
180 | mstep $r12,$r9 | |
181 | mstep $r12,$r9 | |
182 | mstep $r12,$r9 | |
183 | mstep $r12,$r9 | |
184 | add.w $r9,$r10 | |
185 | lslq 16,$r10 | |
186 | ret | |
187 | add.d $r13,$r10 | |
188 | ||
189 | L(L3): | |
0e499e75 HPN |
190 | ;; Form the maximum in $r10, by knowing the minimum, $r9. |
191 | ;; (We don't know which one of $r10 or $r11 it is.) | |
192 | ;; Check if the largest operand is still just 16 bits. | |
193 | ||
194 | xor $r9,$r10 | |
0b85d816 | 195 | xor $r11,$r10 |
0b85d816 HPN |
196 | cmpu.w 65535,$r10 |
197 | bls L(L5) | |
198 | movu.w $r9,$r13 | |
199 | ||
0e499e75 HPN |
200 | ;; We have ab*cd = (a*c)<<32 + (a*d + b*c)<<16 + b*d, but c==0 |
201 | ;; so we only need (a*d)<<16 + b*d with d = $r13, ab = $r10. | |
202 | ;; We drop the upper part of (a*d)<<16 as we're only doing a | |
203 | ;; 32-bit-result multiplication. | |
204 | ||
0b85d816 HPN |
205 | move.d $r10,$r9 |
206 | lslq 16,$r9 | |
0e499e75 | 207 | mstep $r13,$r9 ; b*d |
0b85d816 HPN |
208 | mstep $r13,$r9 |
209 | mstep $r13,$r9 | |
210 | mstep $r13,$r9 | |
211 | mstep $r13,$r9 | |
212 | mstep $r13,$r9 | |
213 | mstep $r13,$r9 | |
214 | mstep $r13,$r9 | |
215 | mstep $r13,$r9 | |
216 | mstep $r13,$r9 | |
217 | mstep $r13,$r9 | |
218 | mstep $r13,$r9 | |
219 | mstep $r13,$r9 | |
220 | mstep $r13,$r9 | |
221 | mstep $r13,$r9 | |
222 | mstep $r13,$r9 | |
223 | clear.w $r10 | |
224 | test.d $r10 | |
0e499e75 | 225 | mstep $r13,$r10 ; a*d |
0b85d816 HPN |
226 | mstep $r13,$r10 |
227 | mstep $r13,$r10 | |
228 | mstep $r13,$r10 | |
229 | mstep $r13,$r10 | |
230 | mstep $r13,$r10 | |
231 | mstep $r13,$r10 | |
232 | mstep $r13,$r10 | |
233 | mstep $r13,$r10 | |
234 | mstep $r13,$r10 | |
235 | mstep $r13,$r10 | |
236 | mstep $r13,$r10 | |
237 | mstep $r13,$r10 | |
238 | mstep $r13,$r10 | |
239 | mstep $r13,$r10 | |
240 | mstep $r13,$r10 | |
241 | lslq 16,$r10 | |
242 | ret | |
243 | add.d $r9,$r10 | |
244 | ||
245 | L(L5): | |
0e499e75 HPN |
246 | ;; We have ab*cd = (a*c)<<32 + (a*d + b*c)<<16 + b*d, but a and c==0 |
247 | ;; so b*d (with b=$r13, a=$r10) it is. | |
248 | ||
0b85d816 | 249 | lslq 16,$r10 |
0e499e75 HPN |
250 | mstep $r13,$r10 |
251 | mstep $r13,$r10 | |
252 | mstep $r13,$r10 | |
253 | mstep $r13,$r10 | |
254 | mstep $r13,$r10 | |
255 | mstep $r13,$r10 | |
256 | mstep $r13,$r10 | |
257 | mstep $r13,$r10 | |
258 | mstep $r13,$r10 | |
259 | mstep $r13,$r10 | |
260 | mstep $r13,$r10 | |
261 | mstep $r13,$r10 | |
262 | mstep $r13,$r10 | |
263 | mstep $r13,$r10 | |
264 | mstep $r13,$r10 | |
0b85d816 | 265 | ret |
0e499e75 | 266 | mstep $r13,$r10 |
0b85d816 HPN |
267 | #endif |
268 | L(Lfe1): | |
269 | .size ___Mul,L(Lfe1)-___Mul |