xref: /netbsd-src/external/gpl3/gcc.old/dist/libgcc/config/cris/mulsi3.S (revision b83ebeba7f767758d2778bb0f9d7a76534253621)
1;; Copyright (C) 2001-2013 Free Software Foundation, Inc.
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;;
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
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
112	mulu.d $r11,$r10
113	ret
114	nop
115#else
116	move.d $r10,$r12
117	move.d $r11,$r9
118	bound.d $r12,$r9
119	cmpu.w 65535,$r9
120	bls L(L3)
121	move.d $r12,$r13
122
123	movu.w $r11,$r9
124	lslq 16,$r13
125	mstep $r9,$r13
126	mstep $r9,$r13
127	mstep $r9,$r13
128	mstep $r9,$r13
129	mstep $r9,$r13
130	mstep $r9,$r13
131	mstep $r9,$r13
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	clear.w $r10
142	test.d $r10
143	mstep $r9,$r10
144	mstep $r9,$r10
145	mstep $r9,$r10
146	mstep $r9,$r10
147	mstep $r9,$r10
148	mstep $r9,$r10
149	mstep $r9,$r10
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	movu.w $r12,$r12
160	move.d $r11,$r9
161	clear.w $r9
162	test.d $r9
163	mstep $r12,$r9
164	mstep $r12,$r9
165	mstep $r12,$r9
166	mstep $r12,$r9
167	mstep $r12,$r9
168	mstep $r12,$r9
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	add.w $r9,$r10
180	lslq 16,$r10
181	ret
182	add.d $r13,$r10
183
184L(L3):
185	move.d $r9,$r10
186	xor $r11,$r10
187	xor $r12,$r10
188	cmpu.w 65535,$r10
189	bls L(L5)
190	movu.w $r9,$r13
191
192	movu.w $r13,$r13
193	move.d $r10,$r9
194	lslq 16,$r9
195	mstep $r13,$r9
196	mstep $r13,$r9
197	mstep $r13,$r9
198	mstep $r13,$r9
199	mstep $r13,$r9
200	mstep $r13,$r9
201	mstep $r13,$r9
202	mstep $r13,$r9
203	mstep $r13,$r9
204	mstep $r13,$r9
205	mstep $r13,$r9
206	mstep $r13,$r9
207	mstep $r13,$r9
208	mstep $r13,$r9
209	mstep $r13,$r9
210	mstep $r13,$r9
211	clear.w $r10
212	test.d $r10
213	mstep $r13,$r10
214	mstep $r13,$r10
215	mstep $r13,$r10
216	mstep $r13,$r10
217	mstep $r13,$r10
218	mstep $r13,$r10
219	mstep $r13,$r10
220	mstep $r13,$r10
221	mstep $r13,$r10
222	mstep $r13,$r10
223	mstep $r13,$r10
224	mstep $r13,$r10
225	mstep $r13,$r10
226	mstep $r13,$r10
227	mstep $r13,$r10
228	mstep $r13,$r10
229	lslq 16,$r10
230	ret
231	add.d $r9,$r10
232
233L(L5):
234	movu.w $r9,$r9
235	lslq 16,$r10
236	mstep $r9,$r10
237	mstep $r9,$r10
238	mstep $r9,$r10
239	mstep $r9,$r10
240	mstep $r9,$r10
241	mstep $r9,$r10
242	mstep $r9,$r10
243	mstep $r9,$r10
244	mstep $r9,$r10
245	mstep $r9,$r10
246	mstep $r9,$r10
247	mstep $r9,$r10
248	mstep $r9,$r10
249	mstep $r9,$r10
250	mstep $r9,$r10
251	ret
252	mstep $r9,$r10
253#endif
254L(Lfe1):
255	.size	___Mul,L(Lfe1)-___Mul
256