yann@1
|
1 |
--- gcc-3.4.3/gcc/Makefile.in
|
yann@1
|
2 |
+++ gcc-3.4.3-nios2/gcc/Makefile.in
|
yann@1
|
3 |
@@ -3085,7 +3085,7 @@ install-mkheaders: stmp-int-hdrs $(STMP_
|
yann@1
|
4 |
$(INSTALL_DATA) $(srcdir)/README-fixinc \
|
yann@1
|
5 |
$(DESTDIR)$(itoolsdatadir)/include/README ; \
|
yann@1
|
6 |
$(INSTALL_SCRIPT) fixinc.sh $(DESTDIR)$(itoolsdir)/fixinc.sh ; \
|
yann@1
|
7 |
- $(INSTALL_PROGRAM) fixinc/fixincl $(DESTDIR)$(itoolsdir)/fixincl ; \
|
yann@1
|
8 |
+ $(INSTALL_PROGRAM) fixinc/fixincl$(build_exeext) $(DESTDIR)$(itoolsdir)/fixincl$(build_exeext) ; \
|
yann@1
|
9 |
$(INSTALL_DATA) $(srcdir)/gsyslimits.h \
|
yann@1
|
10 |
$(DESTDIR)$(itoolsdatadir)/gsyslimits.h ; \
|
yann@1
|
11 |
else :; fi
|
yann@1
|
12 |
--- gcc-3.4.3/gcc/combine.c
|
yann@1
|
13 |
+++ gcc-3.4.3-nios2/gcc/combine.c
|
yann@1
|
14 |
@@ -4380,6 +4380,14 @@ combine_simplify_rtx (rtx x, enum machin
|
yann@1
|
15 |
mode);
|
yann@1
|
16 |
}
|
yann@1
|
17 |
|
yann@1
|
18 |
+#ifndef __nios2__
|
yann@1
|
19 |
+/* This screws up Nios II in this test case:
|
yann@1
|
20 |
+
|
yann@1
|
21 |
+if (x & 1)
|
yann@1
|
22 |
+ return 2;
|
yann@1
|
23 |
+else
|
yann@1
|
24 |
+ return 3;
|
yann@1
|
25 |
+*/
|
yann@1
|
26 |
else if (STORE_FLAG_VALUE == 1
|
yann@1
|
27 |
&& new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
|
yann@1
|
28 |
&& op1 == const0_rtx
|
yann@1
|
29 |
@@ -4391,6 +4399,7 @@ combine_simplify_rtx (rtx x, enum machin
|
yann@1
|
30 |
gen_lowpart_for_combine (mode, op0),
|
yann@1
|
31 |
const1_rtx);
|
yann@1
|
32 |
}
|
yann@1
|
33 |
+#endif
|
yann@1
|
34 |
|
yann@1
|
35 |
else if (STORE_FLAG_VALUE == 1
|
yann@1
|
36 |
&& new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
|
yann@1
|
37 |
--- gcc-3.4.3/gcc/config/nios2/crti.asm
|
yann@1
|
38 |
+++ gcc-3.4.3-nios2/gcc/config/nios2/crti.asm
|
yann@1
|
39 |
@@ -0,0 +1,88 @@
|
yann@1
|
40 |
+/*
|
yann@1
|
41 |
+ Copyright (C) 2003
|
yann@1
|
42 |
+ by Jonah Graham (jgraham@altera.com)
|
yann@1
|
43 |
+
|
yann@1
|
44 |
+This file is free software; you can redistribute it and/or modify it
|
yann@1
|
45 |
+under the terms of the GNU General Public License as published by the
|
yann@1
|
46 |
+Free Software Foundation; either version 2, or (at your option) any
|
yann@1
|
47 |
+later version.
|
yann@1
|
48 |
+
|
yann@1
|
49 |
+In addition to the permissions in the GNU General Public License, the
|
yann@1
|
50 |
+Free Software Foundation gives you unlimited permission to link the
|
yann@1
|
51 |
+compiled version of this file with other programs, and to distribute
|
yann@1
|
52 |
+those programs without any restriction coming from the use of this
|
yann@1
|
53 |
+file. (The General Public License restrictions do apply in other
|
yann@1
|
54 |
+respects; for example, they cover modification of the file, and
|
yann@1
|
55 |
+distribution when not linked into another program.)
|
yann@1
|
56 |
+
|
yann@1
|
57 |
+This file is distributed in the hope that it will be useful, but
|
yann@1
|
58 |
+WITHOUT ANY WARRANTY; without even the implied warranty of
|
yann@1
|
59 |
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
yann@1
|
60 |
+General Public License for more details.
|
yann@1
|
61 |
+
|
yann@1
|
62 |
+You should have received a copy of the GNU General Public License
|
yann@1
|
63 |
+along with this program; see the file COPYING. If not, write to
|
yann@1
|
64 |
+the Free Software Foundation, 59 Temple Place - Suite 330,
|
yann@1
|
65 |
+Boston, MA 02111-1307, USA.
|
yann@1
|
66 |
+
|
yann@1
|
67 |
+ As a special exception, if you link this library with files
|
yann@1
|
68 |
+ compiled with GCC to produce an executable, this does not cause
|
yann@1
|
69 |
+ the resulting executable to be covered by the GNU General Public License.
|
yann@1
|
70 |
+ This exception does not however invalidate any other reasons why
|
yann@1
|
71 |
+ the executable file might be covered by the GNU General Public License.
|
yann@1
|
72 |
+
|
yann@1
|
73 |
+
|
yann@1
|
74 |
+This file just make a stack frame for the contents of the .fini and
|
yann@1
|
75 |
+.init sections. Users may put any desired instructions in those
|
yann@1
|
76 |
+sections.
|
yann@1
|
77 |
+
|
yann@1
|
78 |
+
|
yann@1
|
79 |
+While technically any code can be put in the init and fini sections
|
yann@1
|
80 |
+most stuff will not work other than stuff which obeys the call frame
|
yann@1
|
81 |
+and ABI. All the call-preserved registers are saved, the call clobbered
|
yann@1
|
82 |
+registers should have been saved by the code calling init and fini.
|
yann@1
|
83 |
+
|
yann@1
|
84 |
+See crtstuff.c for an example of code that inserts itself in the
|
yann@1
|
85 |
+init and fini sections.
|
yann@1
|
86 |
+
|
yann@1
|
87 |
+See crt0.s for the code that calls init and fini.
|
yann@1
|
88 |
+*/
|
yann@1
|
89 |
+
|
yann@1
|
90 |
+ .file "crti.asm"
|
yann@1
|
91 |
+
|
yann@1
|
92 |
+ .section ".init"
|
yann@1
|
93 |
+ .align 2
|
yann@1
|
94 |
+ .global _init
|
yann@1
|
95 |
+_init:
|
yann@1
|
96 |
+ addi sp, sp, -48
|
yann@1
|
97 |
+ stw ra, 44(sp)
|
yann@1
|
98 |
+ stw r23, 40(sp)
|
yann@1
|
99 |
+ stw r22, 36(sp)
|
yann@1
|
100 |
+ stw r21, 32(sp)
|
yann@1
|
101 |
+ stw r20, 28(sp)
|
yann@1
|
102 |
+ stw r19, 24(sp)
|
yann@1
|
103 |
+ stw r18, 20(sp)
|
yann@1
|
104 |
+ stw r17, 16(sp)
|
yann@1
|
105 |
+ stw r16, 12(sp)
|
yann@1
|
106 |
+ stw fp, 8(sp)
|
yann@1
|
107 |
+ mov fp, sp
|
yann@1
|
108 |
+
|
yann@1
|
109 |
+
|
yann@1
|
110 |
+ .section ".fini"
|
yann@1
|
111 |
+ .align 2
|
yann@1
|
112 |
+ .global _fini
|
yann@1
|
113 |
+_fini:
|
yann@1
|
114 |
+ addi sp, sp, -48
|
yann@1
|
115 |
+ stw ra, 44(sp)
|
yann@1
|
116 |
+ stw r23, 40(sp)
|
yann@1
|
117 |
+ stw r22, 36(sp)
|
yann@1
|
118 |
+ stw r21, 32(sp)
|
yann@1
|
119 |
+ stw r20, 28(sp)
|
yann@1
|
120 |
+ stw r19, 24(sp)
|
yann@1
|
121 |
+ stw r18, 20(sp)
|
yann@1
|
122 |
+ stw r17, 16(sp)
|
yann@1
|
123 |
+ stw r16, 12(sp)
|
yann@1
|
124 |
+ stw fp, 8(sp)
|
yann@1
|
125 |
+ mov fp, sp
|
yann@1
|
126 |
+
|
yann@1
|
127 |
+
|
yann@1
|
128 |
--- gcc-3.4.3/gcc/config/nios2/crtn.asm
|
yann@1
|
129 |
+++ gcc-3.4.3-nios2/gcc/config/nios2/crtn.asm
|
yann@1
|
130 |
@@ -0,0 +1,70 @@
|
yann@1
|
131 |
+/*
|
yann@1
|
132 |
+ Copyright (C) 2003
|
yann@1
|
133 |
+ by Jonah Graham (jgraham@altera.com)
|
yann@1
|
134 |
+
|
yann@1
|
135 |
+This file is free software; you can redistribute it and/or modify it
|
yann@1
|
136 |
+under the terms of the GNU General Public License as published by the
|
yann@1
|
137 |
+Free Software Foundation; either version 2, or (at your option) any
|
yann@1
|
138 |
+later version.
|
yann@1
|
139 |
+
|
yann@1
|
140 |
+In addition to the permissions in the GNU General Public License, the
|
yann@1
|
141 |
+Free Software Foundation gives you unlimited permission to link the
|
yann@1
|
142 |
+compiled version of this file with other programs, and to distribute
|
yann@1
|
143 |
+those programs without any restriction coming from the use of this
|
yann@1
|
144 |
+file. (The General Public License restrictions do apply in other
|
yann@1
|
145 |
+respects; for example, they cover modification of the file, and
|
yann@1
|
146 |
+distribution when not linked into another program.)
|
yann@1
|
147 |
+
|
yann@1
|
148 |
+This file is distributed in the hope that it will be useful, but
|
yann@1
|
149 |
+WITHOUT ANY WARRANTY; without even the implied warranty of
|
yann@1
|
150 |
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
yann@1
|
151 |
+General Public License for more details.
|
yann@1
|
152 |
+
|
yann@1
|
153 |
+You should have received a copy of the GNU General Public License
|
yann@1
|
154 |
+along with this program; see the file COPYING. If not, write to
|
yann@1
|
155 |
+the Free Software Foundation, 59 Temple Place - Suite 330,
|
yann@1
|
156 |
+Boston, MA 02111-1307, USA.
|
yann@1
|
157 |
+
|
yann@1
|
158 |
+ As a special exception, if you link this library with files
|
yann@1
|
159 |
+ compiled with GCC to produce an executable, this does not cause
|
yann@1
|
160 |
+ the resulting executable to be covered by the GNU General Public License.
|
yann@1
|
161 |
+ This exception does not however invalidate any other reasons why
|
yann@1
|
162 |
+ the executable file might be covered by the GNU General Public License.
|
yann@1
|
163 |
+
|
yann@1
|
164 |
+
|
yann@1
|
165 |
+This file just makes sure that the .fini and .init sections do in
|
yann@1
|
166 |
+fact return. Users may put any desired instructions in those sections.
|
yann@1
|
167 |
+This file is the last thing linked into any executable.
|
yann@1
|
168 |
+*/
|
yann@1
|
169 |
+ .file "crtn.asm"
|
yann@1
|
170 |
+
|
yann@1
|
171 |
+
|
yann@1
|
172 |
+
|
yann@1
|
173 |
+ .section ".init"
|
yann@1
|
174 |
+ ldw ra, 44(sp)
|
yann@1
|
175 |
+ ldw r23, 40(sp)
|
yann@1
|
176 |
+ ldw r22, 36(sp)
|
yann@1
|
177 |
+ ldw r21, 32(sp)
|
yann@1
|
178 |
+ ldw r20, 28(sp)
|
yann@1
|
179 |
+ ldw r19, 24(sp)
|
yann@1
|
180 |
+ ldw r18, 20(sp)
|
yann@1
|
181 |
+ ldw r17, 16(sp)
|
yann@1
|
182 |
+ ldw r16, 12(sp)
|
yann@1
|
183 |
+ ldw fp, 8(sp)
|
yann@1
|
184 |
+ addi sp, sp, -48
|
yann@1
|
185 |
+ ret
|
yann@1
|
186 |
+
|
yann@1
|
187 |
+ .section ".fini"
|
yann@1
|
188 |
+ ldw ra, 44(sp)
|
yann@1
|
189 |
+ ldw r23, 40(sp)
|
yann@1
|
190 |
+ ldw r22, 36(sp)
|
yann@1
|
191 |
+ ldw r21, 32(sp)
|
yann@1
|
192 |
+ ldw r20, 28(sp)
|
yann@1
|
193 |
+ ldw r19, 24(sp)
|
yann@1
|
194 |
+ ldw r18, 20(sp)
|
yann@1
|
195 |
+ ldw r17, 16(sp)
|
yann@1
|
196 |
+ ldw r16, 12(sp)
|
yann@1
|
197 |
+ ldw fp, 8(sp)
|
yann@1
|
198 |
+ addi sp, sp, -48
|
yann@1
|
199 |
+ ret
|
yann@1
|
200 |
+
|
yann@1
|
201 |
--- gcc-3.4.3/gcc/config/nios2/lib2-divmod-hi.c
|
yann@1
|
202 |
+++ gcc-3.4.3-nios2/gcc/config/nios2/lib2-divmod-hi.c
|
yann@1
|
203 |
@@ -0,0 +1,123 @@
|
yann@1
|
204 |
+
|
yann@1
|
205 |
+/* We include auto-host.h here to get HAVE_GAS_HIDDEN. This is
|
yann@1
|
206 |
+ supposedly valid even though this is a "target" file. */
|
yann@1
|
207 |
+#include "auto-host.h"
|
yann@1
|
208 |
+
|
yann@1
|
209 |
+
|
yann@1
|
210 |
+#include "tconfig.h"
|
yann@1
|
211 |
+#include "tsystem.h"
|
yann@1
|
212 |
+#include "coretypes.h"
|
yann@1
|
213 |
+#include "tm.h"
|
yann@1
|
214 |
+
|
yann@1
|
215 |
+
|
yann@1
|
216 |
+/* Don't use `fancy_abort' here even if config.h says to use it. */
|
yann@1
|
217 |
+#ifdef abort
|
yann@1
|
218 |
+#undef abort
|
yann@1
|
219 |
+#endif
|
yann@1
|
220 |
+
|
yann@1
|
221 |
+
|
yann@1
|
222 |
+#ifdef HAVE_GAS_HIDDEN
|
yann@1
|
223 |
+#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden")))
|
yann@1
|
224 |
+#else
|
yann@1
|
225 |
+#define ATTRIBUTE_HIDDEN
|
yann@1
|
226 |
+#endif
|
yann@1
|
227 |
+
|
yann@1
|
228 |
+#include "libgcc2.h"
|
yann@1
|
229 |
+
|
yann@1
|
230 |
+extern HItype __modhi3 (HItype, HItype);
|
yann@1
|
231 |
+extern HItype __divhi3 (HItype, HItype);
|
yann@1
|
232 |
+extern HItype __umodhi3 (HItype, HItype);
|
yann@1
|
233 |
+extern HItype __udivhi3 (HItype, HItype);
|
yann@1
|
234 |
+
|
yann@1
|
235 |
+static UHItype udivmodhi4(UHItype, UHItype, word_type);
|
yann@1
|
236 |
+
|
yann@1
|
237 |
+static UHItype
|
yann@1
|
238 |
+udivmodhi4(UHItype num, UHItype den, word_type modwanted)
|
yann@1
|
239 |
+{
|
yann@1
|
240 |
+ UHItype bit = 1;
|
yann@1
|
241 |
+ UHItype res = 0;
|
yann@1
|
242 |
+
|
yann@1
|
243 |
+ while (den < num && bit && !(den & (1L<<15)))
|
yann@1
|
244 |
+ {
|
yann@1
|
245 |
+ den <<=1;
|
yann@1
|
246 |
+ bit <<=1;
|
yann@1
|
247 |
+ }
|
yann@1
|
248 |
+ while (bit)
|
yann@1
|
249 |
+ {
|
yann@1
|
250 |
+ if (num >= den)
|
yann@1
|
251 |
+ {
|
yann@1
|
252 |
+ num -= den;
|
yann@1
|
253 |
+ res |= bit;
|
yann@1
|
254 |
+ }
|
yann@1
|
255 |
+ bit >>=1;
|
yann@1
|
256 |
+ den >>=1;
|
yann@1
|
257 |
+ }
|
yann@1
|
258 |
+ if (modwanted) return num;
|
yann@1
|
259 |
+ return res;
|
yann@1
|
260 |
+}
|
yann@1
|
261 |
+
|
yann@1
|
262 |
+
|
yann@1
|
263 |
+HItype
|
yann@1
|
264 |
+__divhi3 (HItype a, HItype b)
|
yann@1
|
265 |
+{
|
yann@1
|
266 |
+ word_type neg = 0;
|
yann@1
|
267 |
+ HItype res;
|
yann@1
|
268 |
+
|
yann@1
|
269 |
+ if (a < 0)
|
yann@1
|
270 |
+ {
|
yann@1
|
271 |
+ a = -a;
|
yann@1
|
272 |
+ neg = !neg;
|
yann@1
|
273 |
+ }
|
yann@1
|
274 |
+
|
yann@1
|
275 |
+ if (b < 0)
|
yann@1
|
276 |
+ {
|
yann@1
|
277 |
+ b = -b;
|
yann@1
|
278 |
+ neg = !neg;
|
yann@1
|
279 |
+ }
|
yann@1
|
280 |
+
|
yann@1
|
281 |
+ res = udivmodhi4 (a, b, 0);
|
yann@1
|
282 |
+
|
yann@1
|
283 |
+ if (neg)
|
yann@1
|
284 |
+ res = -res;
|
yann@1
|
285 |
+
|
yann@1
|
286 |
+ return res;
|
yann@1
|
287 |
+}
|
yann@1
|
288 |
+
|
yann@1
|
289 |
+
|
yann@1
|
290 |
+HItype
|
yann@1
|
291 |
+__modhi3 (HItype a, HItype b)
|
yann@1
|
292 |
+{
|
yann@1
|
293 |
+ word_type neg = 0;
|
yann@1
|
294 |
+ HItype res;
|
yann@1
|
295 |
+
|
yann@1
|
296 |
+ if (a < 0)
|
yann@1
|
297 |
+ {
|
yann@1
|
298 |
+ a = -a;
|
yann@1
|
299 |
+ neg = 1;
|
yann@1
|
300 |
+ }
|
yann@1
|
301 |
+
|
yann@1
|
302 |
+ if (b < 0)
|
yann@1
|
303 |
+ b = -b;
|
yann@1
|
304 |
+
|
yann@1
|
305 |
+ res = udivmodhi4 (a, b, 1);
|
yann@1
|
306 |
+
|
yann@1
|
307 |
+ if (neg)
|
yann@1
|
308 |
+ res = -res;
|
yann@1
|
309 |
+
|
yann@1
|
310 |
+ return res;
|
yann@1
|
311 |
+}
|
yann@1
|
312 |
+
|
yann@1
|
313 |
+
|
yann@1
|
314 |
+HItype
|
yann@1
|
315 |
+__udivhi3 (HItype a, HItype b)
|
yann@1
|
316 |
+{
|
yann@1
|
317 |
+ return udivmodhi4 (a, b, 0);
|
yann@1
|
318 |
+}
|
yann@1
|
319 |
+
|
yann@1
|
320 |
+
|
yann@1
|
321 |
+HItype
|
yann@1
|
322 |
+__umodhi3 (HItype a, HItype b)
|
yann@1
|
323 |
+{
|
yann@1
|
324 |
+ return udivmodhi4 (a, b, 1);
|
yann@1
|
325 |
+}
|
yann@1
|
326 |
+
|
yann@1
|
327 |
--- gcc-3.4.3/gcc/config/nios2/lib2-divmod.c
|
yann@1
|
328 |
+++ gcc-3.4.3-nios2/gcc/config/nios2/lib2-divmod.c
|
yann@1
|
329 |
@@ -0,0 +1,126 @@
|
yann@1
|
330 |
+
|
yann@1
|
331 |
+/* We include auto-host.h here to get HAVE_GAS_HIDDEN. This is
|
yann@1
|
332 |
+ supposedly valid even though this is a "target" file. */
|
yann@1
|
333 |
+#include "auto-host.h"
|
yann@1
|
334 |
+
|
yann@1
|
335 |
+
|
yann@1
|
336 |
+#include "tconfig.h"
|
yann@1
|
337 |
+#include "tsystem.h"
|
yann@1
|
338 |
+#include "coretypes.h"
|
yann@1
|
339 |
+#include "tm.h"
|
yann@1
|
340 |
+
|
yann@1
|
341 |
+
|
yann@1
|
342 |
+/* Don't use `fancy_abort' here even if config.h says to use it. */
|
yann@1
|
343 |
+#ifdef abort
|
yann@1
|
344 |
+#undef abort
|
yann@1
|
345 |
+#endif
|
yann@1
|
346 |
+
|
yann@1
|
347 |
+
|
yann@1
|
348 |
+#ifdef HAVE_GAS_HIDDEN
|
yann@1
|
349 |
+#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden")))
|
yann@1
|
350 |
+#else
|
yann@1
|
351 |
+#define ATTRIBUTE_HIDDEN
|
yann@1
|
352 |
+#endif
|
yann@1
|
353 |
+
|
yann@1
|
354 |
+#include "libgcc2.h"
|
yann@1
|
355 |
+
|
yann@1
|
356 |
+extern SItype __modsi3 (SItype, SItype);
|
yann@1
|
357 |
+extern SItype __divsi3 (SItype, SItype);
|
yann@1
|
358 |
+extern SItype __umodsi3 (SItype, SItype);
|
yann@1
|
359 |
+extern SItype __udivsi3 (SItype, SItype);
|
yann@1
|
360 |
+
|
yann@1
|
361 |
+static USItype udivmodsi4(USItype, USItype, word_type);
|
yann@1
|
362 |
+
|
yann@1
|
363 |
+/* 16-bit SI divide and modulo as used in NIOS */
|
yann@1
|
364 |
+
|
yann@1
|
365 |
+
|
yann@1
|
366 |
+static USItype
|
yann@1
|
367 |
+udivmodsi4(USItype num, USItype den, word_type modwanted)
|
yann@1
|
368 |
+{
|
yann@1
|
369 |
+ USItype bit = 1;
|
yann@1
|
370 |
+ USItype res = 0;
|
yann@1
|
371 |
+
|
yann@1
|
372 |
+ while (den < num && bit && !(den & (1L<<31)))
|
yann@1
|
373 |
+ {
|
yann@1
|
374 |
+ den <<=1;
|
yann@1
|
375 |
+ bit <<=1;
|
yann@1
|
376 |
+ }
|
yann@1
|
377 |
+ while (bit)
|
yann@1
|
378 |
+ {
|
yann@1
|
379 |
+ if (num >= den)
|
yann@1
|
380 |
+ {
|
yann@1
|
381 |
+ num -= den;
|
yann@1
|
382 |
+ res |= bit;
|
yann@1
|
383 |
+ }
|
yann@1
|
384 |
+ bit >>=1;
|
yann@1
|
385 |
+ den >>=1;
|
yann@1
|
386 |
+ }
|
yann@1
|
387 |
+ if (modwanted) return num;
|
yann@1
|
388 |
+ return res;
|
yann@1
|
389 |
+}
|
yann@1
|
390 |
+
|
yann@1
|
391 |
+
|
yann@1
|
392 |
+SItype
|
yann@1
|
393 |
+__divsi3 (SItype a, SItype b)
|
yann@1
|
394 |
+{
|
yann@1
|
395 |
+ word_type neg = 0;
|
yann@1
|
396 |
+ SItype res;
|
yann@1
|
397 |
+
|
yann@1
|
398 |
+ if (a < 0)
|
yann@1
|
399 |
+ {
|
yann@1
|
400 |
+ a = -a;
|
yann@1
|
401 |
+ neg = !neg;
|
yann@1
|
402 |
+ }
|
yann@1
|
403 |
+
|
yann@1
|
404 |
+ if (b < 0)
|
yann@1
|
405 |
+ {
|
yann@1
|
406 |
+ b = -b;
|
yann@1
|
407 |
+ neg = !neg;
|
yann@1
|
408 |
+ }
|
yann@1
|
409 |
+
|
yann@1
|
410 |
+ res = udivmodsi4 (a, b, 0);
|
yann@1
|
411 |
+
|
yann@1
|
412 |
+ if (neg)
|
yann@1
|
413 |
+ res = -res;
|
yann@1
|
414 |
+
|
yann@1
|
415 |
+ return res;
|
yann@1
|
416 |
+}
|
yann@1
|
417 |
+
|
yann@1
|
418 |
+
|
yann@1
|
419 |
+SItype
|
yann@1
|
420 |
+__modsi3 (SItype a, SItype b)
|
yann@1
|
421 |
+{
|
yann@1
|
422 |
+ word_type neg = 0;
|
yann@1
|
423 |
+ SItype res;
|
yann@1
|
424 |
+
|
yann@1
|
425 |
+ if (a < 0)
|
yann@1
|
426 |
+ {
|
yann@1
|
427 |
+ a = -a;
|
yann@1
|
428 |
+ neg = 1;
|
yann@1
|
429 |
+ }
|
yann@1
|
430 |
+
|
yann@1
|
431 |
+ if (b < 0)
|
yann@1
|
432 |
+ b = -b;
|
yann@1
|
433 |
+
|
yann@1
|
434 |
+ res = udivmodsi4 (a, b, 1);
|
yann@1
|
435 |
+
|
yann@1
|
436 |
+ if (neg)
|
yann@1
|
437 |
+ res = -res;
|
yann@1
|
438 |
+
|
yann@1
|
439 |
+ return res;
|
yann@1
|
440 |
+}
|
yann@1
|
441 |
+
|
yann@1
|
442 |
+
|
yann@1
|
443 |
+SItype
|
yann@1
|
444 |
+__udivsi3 (SItype a, SItype b)
|
yann@1
|
445 |
+{
|
yann@1
|
446 |
+ return udivmodsi4 (a, b, 0);
|
yann@1
|
447 |
+}
|
yann@1
|
448 |
+
|
yann@1
|
449 |
+
|
yann@1
|
450 |
+SItype
|
yann@1
|
451 |
+__umodsi3 (SItype a, SItype b)
|
yann@1
|
452 |
+{
|
yann@1
|
453 |
+ return udivmodsi4 (a, b, 1);
|
yann@1
|
454 |
+}
|
yann@1
|
455 |
+
|
yann@1
|
456 |
--- gcc-3.4.3/gcc/config/nios2/lib2-divtable.c
|
yann@1
|
457 |
+++ gcc-3.4.3-nios2/gcc/config/nios2/lib2-divtable.c
|
yann@1
|
458 |
@@ -0,0 +1,46 @@
|
yann@1
|
459 |
+
|
yann@1
|
460 |
+/* We include auto-host.h here to get HAVE_GAS_HIDDEN. This is
|
yann@1
|
461 |
+ supposedly valid even though this is a "target" file. */
|
yann@1
|
462 |
+#include "auto-host.h"
|
yann@1
|
463 |
+
|
yann@1
|
464 |
+
|
yann@1
|
465 |
+#include "tconfig.h"
|
yann@1
|
466 |
+#include "tsystem.h"
|
yann@1
|
467 |
+#include "coretypes.h"
|
yann@1
|
468 |
+#include "tm.h"
|
yann@1
|
469 |
+
|
yann@1
|
470 |
+
|
yann@1
|
471 |
+/* Don't use `fancy_abort' here even if config.h says to use it. */
|
yann@1
|
472 |
+#ifdef abort
|
yann@1
|
473 |
+#undef abort
|
yann@1
|
474 |
+#endif
|
yann@1
|
475 |
+
|
yann@1
|
476 |
+
|
yann@1
|
477 |
+#ifdef HAVE_GAS_HIDDEN
|
yann@1
|
478 |
+#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden")))
|
yann@1
|
479 |
+#else
|
yann@1
|
480 |
+#define ATTRIBUTE_HIDDEN
|
yann@1
|
481 |
+#endif
|
yann@1
|
482 |
+
|
yann@1
|
483 |
+#include "libgcc2.h"
|
yann@1
|
484 |
+
|
yann@1
|
485 |
+UQItype __divsi3_table[] =
|
yann@1
|
486 |
+{
|
yann@1
|
487 |
+ 0, 0/1, 0/2, 0/3, 0/4, 0/5, 0/6, 0/7, 0/8, 0/9, 0/10, 0/11, 0/12, 0/13, 0/14, 0/15,
|
yann@1
|
488 |
+ 0, 1/1, 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9, 1/10, 1/11, 1/12, 1/13, 1/14, 1/15,
|
yann@1
|
489 |
+ 0, 2/1, 2/2, 2/3, 2/4, 2/5, 2/6, 2/7, 2/8, 2/9, 2/10, 2/11, 2/12, 2/13, 2/14, 2/15,
|
yann@1
|
490 |
+ 0, 3/1, 3/2, 3/3, 3/4, 3/5, 3/6, 3/7, 3/8, 3/9, 3/10, 3/11, 3/12, 3/13, 3/14, 3/15,
|
yann@1
|
491 |
+ 0, 4/1, 4/2, 4/3, 4/4, 4/5, 4/6, 4/7, 4/8, 4/9, 4/10, 4/11, 4/12, 4/13, 4/14, 4/15,
|
yann@1
|
492 |
+ 0, 5/1, 5/2, 5/3, 5/4, 5/5, 5/6, 5/7, 5/8, 5/9, 5/10, 5/11, 5/12, 5/13, 5/14, 5/15,
|
yann@1
|
493 |
+ 0, 6/1, 6/2, 6/3, 6/4, 6/5, 6/6, 6/7, 6/8, 6/9, 6/10, 6/11, 6/12, 6/13, 6/14, 6/15,
|
yann@1
|
494 |
+ 0, 7/1, 7/2, 7/3, 7/4, 7/5, 7/6, 7/7, 7/8, 7/9, 7/10, 7/11, 7/12, 7/13, 7/14, 7/15,
|
yann@1
|
495 |
+ 0, 8/1, 8/2, 8/3, 8/4, 8/5, 8/6, 8/7, 8/8, 8/9, 8/10, 8/11, 8/12, 8/13, 8/14, 8/15,
|
yann@1
|
496 |
+ 0, 9/1, 9/2, 9/3, 9/4, 9/5, 9/6, 9/7, 9/8, 9/9, 9/10, 9/11, 9/12, 9/13, 9/14, 9/15,
|
yann@1
|
497 |
+ 0, 10/1, 10/2, 10/3, 10/4, 10/5, 10/6, 10/7, 10/8, 10/9, 10/10, 10/11, 10/12, 10/13, 10/14, 10/15,
|
yann@1
|
498 |
+ 0, 11/1, 11/2, 11/3, 11/4, 11/5, 11/6, 11/7, 11/8, 11/9, 11/10, 11/11, 11/12, 11/13, 11/14, 11/15,
|
yann@1
|
499 |
+ 0, 12/1, 12/2, 12/3, 12/4, 12/5, 12/6, 12/7, 12/8, 12/9, 12/10, 12/11, 12/12, 12/13, 12/14, 12/15,
|
yann@1
|
500 |
+ 0, 13/1, 13/2, 13/3, 13/4, 13/5, 13/6, 13/7, 13/8, 13/9, 13/10, 13/11, 13/12, 13/13, 13/14, 13/15,
|
yann@1
|
501 |
+ 0, 14/1, 14/2, 14/3, 14/4, 14/5, 14/6, 14/7, 14/8, 14/9, 14/10, 14/11, 14/12, 14/13, 14/14, 14/15,
|
yann@1
|
502 |
+ 0, 15/1, 15/2, 15/3, 15/4, 15/5, 15/6, 15/7, 15/8, 15/9, 15/10, 15/11, 15/12, 15/13, 15/14, 15/15,
|
yann@1
|
503 |
+};
|
yann@1
|
504 |
+
|
yann@1
|
505 |
--- gcc-3.4.3/gcc/config/nios2/lib2-mul.c
|
yann@1
|
506 |
+++ gcc-3.4.3-nios2/gcc/config/nios2/lib2-mul.c
|
yann@1
|
507 |
@@ -0,0 +1,103 @@
|
yann@1
|
508 |
+/* while we are debugging (ie compile outside of gcc build)
|
yann@1
|
509 |
+ disable gcc specific headers */
|
yann@1
|
510 |
+#ifndef DEBUG_MULSI3
|
yann@1
|
511 |
+
|
yann@1
|
512 |
+
|
yann@1
|
513 |
+/* We include auto-host.h here to get HAVE_GAS_HIDDEN. This is
|
yann@1
|
514 |
+ supposedly valid even though this is a "target" file. */
|
yann@1
|
515 |
+#include "auto-host.h"
|
yann@1
|
516 |
+
|
yann@1
|
517 |
+
|
yann@1
|
518 |
+#include "tconfig.h"
|
yann@1
|
519 |
+#include "tsystem.h"
|
yann@1
|
520 |
+#include "coretypes.h"
|
yann@1
|
521 |
+#include "tm.h"
|
yann@1
|
522 |
+
|
yann@1
|
523 |
+
|
yann@1
|
524 |
+/* Don't use `fancy_abort' here even if config.h says to use it. */
|
yann@1
|
525 |
+#ifdef abort
|
yann@1
|
526 |
+#undef abort
|
yann@1
|
527 |
+#endif
|
yann@1
|
528 |
+
|
yann@1
|
529 |
+
|
yann@1
|
530 |
+#ifdef HAVE_GAS_HIDDEN
|
yann@1
|
531 |
+#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden")))
|
yann@1
|
532 |
+#else
|
yann@1
|
533 |
+#define ATTRIBUTE_HIDDEN
|
yann@1
|
534 |
+#endif
|
yann@1
|
535 |
+
|
yann@1
|
536 |
+#include "libgcc2.h"
|
yann@1
|
537 |
+
|
yann@1
|
538 |
+#else
|
yann@1
|
539 |
+#define SItype int
|
yann@1
|
540 |
+#define USItype unsigned int
|
yann@1
|
541 |
+#endif
|
yann@1
|
542 |
+
|
yann@1
|
543 |
+
|
yann@1
|
544 |
+extern SItype __mulsi3 (SItype, SItype);
|
yann@1
|
545 |
+
|
yann@1
|
546 |
+SItype
|
yann@1
|
547 |
+__mulsi3 (SItype a, SItype b)
|
yann@1
|
548 |
+{
|
yann@1
|
549 |
+ SItype res = 0;
|
yann@1
|
550 |
+ USItype cnt = a;
|
yann@1
|
551 |
+
|
yann@1
|
552 |
+ while (cnt)
|
yann@1
|
553 |
+ {
|
yann@1
|
554 |
+ if (cnt & 1)
|
yann@1
|
555 |
+ {
|
yann@1
|
556 |
+ res += b;
|
yann@1
|
557 |
+ }
|
yann@1
|
558 |
+ b <<= 1;
|
yann@1
|
559 |
+ cnt >>= 1;
|
yann@1
|
560 |
+ }
|
yann@1
|
561 |
+
|
yann@1
|
562 |
+ return res;
|
yann@1
|
563 |
+}
|
yann@1
|
564 |
+/*
|
yann@1
|
565 |
+TODO: Choose best alternative implementation.
|
yann@1
|
566 |
+
|
yann@1
|
567 |
+SItype
|
yann@1
|
568 |
+__divsi3 (SItype a, SItype b)
|
yann@1
|
569 |
+{
|
yann@1
|
570 |
+ SItype res = 0;
|
yann@1
|
571 |
+ USItype cnt = 0;
|
yann@1
|
572 |
+
|
yann@1
|
573 |
+ while (cnt < 32)
|
yann@1
|
574 |
+ {
|
yann@1
|
575 |
+ if (a & (1L << cnt))
|
yann@1
|
576 |
+ {
|
yann@1
|
577 |
+ res += b;
|
yann@1
|
578 |
+ }
|
yann@1
|
579 |
+ b <<= 1;
|
yann@1
|
580 |
+ cnt++;
|
yann@1
|
581 |
+ }
|
yann@1
|
582 |
+
|
yann@1
|
583 |
+ return res;
|
yann@1
|
584 |
+}
|
yann@1
|
585 |
+*/
|
yann@1
|
586 |
+
|
yann@1
|
587 |
+
|
yann@1
|
588 |
+#ifdef DEBUG_MULSI3
|
yann@1
|
589 |
+
|
yann@1
|
590 |
+int
|
yann@1
|
591 |
+main ()
|
yann@1
|
592 |
+{
|
yann@1
|
593 |
+ int i, j;
|
yann@1
|
594 |
+ int error = 0;
|
yann@1
|
595 |
+
|
yann@1
|
596 |
+ for (i = -1000; i < 1000; i++)
|
yann@1
|
597 |
+ for (j = -1000; j < 1000; j++)
|
yann@1
|
598 |
+ {
|
yann@1
|
599 |
+ int expect = i * j;
|
yann@1
|
600 |
+ int actual = A__divsi3 (i, j);
|
yann@1
|
601 |
+ if (expect != actual)
|
yann@1
|
602 |
+ {
|
yann@1
|
603 |
+ printf ("error: %d * %d = %d not %d\n", i, j, expect, actual);
|
yann@1
|
604 |
+ error = 1;
|
yann@1
|
605 |
+ }
|
yann@1
|
606 |
+ }
|
yann@1
|
607 |
+
|
yann@1
|
608 |
+ return error;
|
yann@1
|
609 |
+}
|
yann@1
|
610 |
+#endif
|
yann@1
|
611 |
--- gcc-3.4.3/gcc/config/nios2/nios2-dp-bit.c
|
yann@1
|
612 |
+++ gcc-3.4.3-nios2/gcc/config/nios2/nios2-dp-bit.c
|
yann@1
|
613 |
@@ -0,0 +1,1652 @@
|
yann@1
|
614 |
+
|
yann@1
|
615 |
+/* This is a software floating point library which can be used
|
yann@1
|
616 |
+ for targets without hardware floating point.
|
yann@1
|
617 |
+ Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004
|
yann@1
|
618 |
+ Free Software Foundation, Inc.
|
yann@1
|
619 |
+
|
yann@1
|
620 |
+This file is free software; you can redistribute it and/or modify it
|
yann@1
|
621 |
+under the terms of the GNU General Public License as published by the
|
yann@1
|
622 |
+Free Software Foundation; either version 2, or (at your option) any
|
yann@1
|
623 |
+later version.
|
yann@1
|
624 |
+
|
yann@1
|
625 |
+In addition to the permissions in the GNU General Public License, the
|
yann@1
|
626 |
+Free Software Foundation gives you unlimited permission to link the
|
yann@1
|
627 |
+compiled version of this file with other programs, and to distribute
|
yann@1
|
628 |
+those programs without any restriction coming from the use of this
|
yann@1
|
629 |
+file. (The General Public License restrictions do apply in other
|
yann@1
|
630 |
+respects; for example, they cover modification of the file, and
|
yann@1
|
631 |
+distribution when not linked into another program.)
|
yann@1
|
632 |
+
|
yann@1
|
633 |
+This file is distributed in the hope that it will be useful, but
|
yann@1
|
634 |
+WITHOUT ANY WARRANTY; without even the implied warranty of
|
yann@1
|
635 |
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
yann@1
|
636 |
+General Public License for more details.
|
yann@1
|
637 |
+
|
yann@1
|
638 |
+You should have received a copy of the GNU General Public License
|
yann@1
|
639 |
+along with this program; see the file COPYING. If not, write to
|
yann@1
|
640 |
+the Free Software Foundation, 59 Temple Place - Suite 330,
|
yann@1
|
641 |
+Boston, MA 02111-1307, USA. */
|
yann@1
|
642 |
+
|
yann@1
|
643 |
+/* As a special exception, if you link this library with other files,
|
yann@1
|
644 |
+ some of which are compiled with GCC, to produce an executable,
|
yann@1
|
645 |
+ this library does not by itself cause the resulting executable
|
yann@1
|
646 |
+ to be covered by the GNU General Public License.
|
yann@1
|
647 |
+ This exception does not however invalidate any other reasons why
|
yann@1
|
648 |
+ the executable file might be covered by the GNU General Public License. */
|
yann@1
|
649 |
+
|
yann@1
|
650 |
+/* This implements IEEE 754 format arithmetic, but does not provide a
|
yann@1
|
651 |
+ mechanism for setting the rounding mode, or for generating or handling
|
yann@1
|
652 |
+ exceptions.
|
yann@1
|
653 |
+
|
yann@1
|
654 |
+ The original code by Steve Chamberlain, hacked by Mark Eichin and Jim
|
yann@1
|
655 |
+ Wilson, all of Cygnus Support. */
|
yann@1
|
656 |
+
|
yann@1
|
657 |
+/* The intended way to use this file is to make two copies, add `#define FLOAT'
|
yann@1
|
658 |
+ to one copy, then compile both copies and add them to libgcc.a. */
|
yann@1
|
659 |
+
|
yann@1
|
660 |
+#include "tconfig.h"
|
yann@1
|
661 |
+#include "coretypes.h"
|
yann@1
|
662 |
+#include "tm.h"
|
yann@1
|
663 |
+#include "config/fp-bit.h"
|
yann@1
|
664 |
+
|
yann@1
|
665 |
+/* The following macros can be defined to change the behavior of this file:
|
yann@1
|
666 |
+ FLOAT: Implement a `float', aka SFmode, fp library. If this is not
|
yann@1
|
667 |
+ defined, then this file implements a `double', aka DFmode, fp library.
|
yann@1
|
668 |
+ FLOAT_ONLY: Used with FLOAT, to implement a `float' only library, i.e.
|
yann@1
|
669 |
+ don't include float->double conversion which requires the double library.
|
yann@1
|
670 |
+ This is useful only for machines which can't support doubles, e.g. some
|
yann@1
|
671 |
+ 8-bit processors.
|
yann@1
|
672 |
+ CMPtype: Specify the type that floating point compares should return.
|
yann@1
|
673 |
+ This defaults to SItype, aka int.
|
yann@1
|
674 |
+ US_SOFTWARE_GOFAST: This makes all entry points use the same names as the
|
yann@1
|
675 |
+ US Software goFast library.
|
yann@1
|
676 |
+ _DEBUG_BITFLOAT: This makes debugging the code a little easier, by adding
|
yann@1
|
677 |
+ two integers to the FLO_union_type.
|
yann@1
|
678 |
+ NO_DENORMALS: Disable handling of denormals.
|
yann@1
|
679 |
+ NO_NANS: Disable nan and infinity handling
|
yann@1
|
680 |
+ SMALL_MACHINE: Useful when operations on QIs and HIs are faster
|
yann@1
|
681 |
+ than on an SI */
|
yann@1
|
682 |
+
|
yann@1
|
683 |
+/* We don't currently support extended floats (long doubles) on machines
|
yann@1
|
684 |
+ without hardware to deal with them.
|
yann@1
|
685 |
+
|
yann@1
|
686 |
+ These stubs are just to keep the linker from complaining about unresolved
|
yann@1
|
687 |
+ references which can be pulled in from libio & libstdc++, even if the
|
yann@1
|
688 |
+ user isn't using long doubles. However, they may generate an unresolved
|
yann@1
|
689 |
+ external to abort if abort is not used by the function, and the stubs
|
yann@1
|
690 |
+ are referenced from within libc, since libgcc goes before and after the
|
yann@1
|
691 |
+ system library. */
|
yann@1
|
692 |
+
|
yann@1
|
693 |
+#ifdef DECLARE_LIBRARY_RENAMES
|
yann@1
|
694 |
+ DECLARE_LIBRARY_RENAMES
|
yann@1
|
695 |
+#endif
|
yann@1
|
696 |
+
|
yann@1
|
697 |
+#ifdef EXTENDED_FLOAT_STUBS
|
yann@1
|
698 |
+extern void abort (void);
|
yann@1
|
699 |
+void __extendsfxf2 (void) { abort(); }
|
yann@1
|
700 |
+void __extenddfxf2 (void) { abort(); }
|
yann@1
|
701 |
+void __truncxfdf2 (void) { abort(); }
|
yann@1
|
702 |
+void __truncxfsf2 (void) { abort(); }
|
yann@1
|
703 |
+void __fixxfsi (void) { abort(); }
|
yann@1
|
704 |
+void __floatsixf (void) { abort(); }
|
yann@1
|
705 |
+void __addxf3 (void) { abort(); }
|
yann@1
|
706 |
+void __subxf3 (void) { abort(); }
|
yann@1
|
707 |
+void __mulxf3 (void) { abort(); }
|
yann@1
|
708 |
+void __divxf3 (void) { abort(); }
|
yann@1
|
709 |
+void __negxf2 (void) { abort(); }
|
yann@1
|
710 |
+void __eqxf2 (void) { abort(); }
|
yann@1
|
711 |
+void __nexf2 (void) { abort(); }
|
yann@1
|
712 |
+void __gtxf2 (void) { abort(); }
|
yann@1
|
713 |
+void __gexf2 (void) { abort(); }
|
yann@1
|
714 |
+void __lexf2 (void) { abort(); }
|
yann@1
|
715 |
+void __ltxf2 (void) { abort(); }
|
yann@1
|
716 |
+
|
yann@1
|
717 |
+void __extendsftf2 (void) { abort(); }
|
yann@1
|
718 |
+void __extenddftf2 (void) { abort(); }
|
yann@1
|
719 |
+void __trunctfdf2 (void) { abort(); }
|
yann@1
|
720 |
+void __trunctfsf2 (void) { abort(); }
|
yann@1
|
721 |
+void __fixtfsi (void) { abort(); }
|
yann@1
|
722 |
+void __floatsitf (void) { abort(); }
|
yann@1
|
723 |
+void __addtf3 (void) { abort(); }
|
yann@1
|
724 |
+void __subtf3 (void) { abort(); }
|
yann@1
|
725 |
+void __multf3 (void) { abort(); }
|
yann@1
|
726 |
+void __divtf3 (void) { abort(); }
|
yann@1
|
727 |
+void __negtf2 (void) { abort(); }
|
yann@1
|
728 |
+void __eqtf2 (void) { abort(); }
|
yann@1
|
729 |
+void __netf2 (void) { abort(); }
|
yann@1
|
730 |
+void __gttf2 (void) { abort(); }
|
yann@1
|
731 |
+void __getf2 (void) { abort(); }
|
yann@1
|
732 |
+void __letf2 (void) { abort(); }
|
yann@1
|
733 |
+void __lttf2 (void) { abort(); }
|
yann@1
|
734 |
+#else /* !EXTENDED_FLOAT_STUBS, rest of file */
|
yann@1
|
735 |
+
|
yann@1
|
736 |
+/* IEEE "special" number predicates */
|
yann@1
|
737 |
+
|
yann@1
|
738 |
+#ifdef NO_NANS
|
yann@1
|
739 |
+
|
yann@1
|
740 |
+#define nan() 0
|
yann@1
|
741 |
+#define isnan(x) 0
|
yann@1
|
742 |
+#define isinf(x) 0
|
yann@1
|
743 |
+#else
|
yann@1
|
744 |
+
|
yann@1
|
745 |
+#if defined L_thenan_sf
|
yann@1
|
746 |
+const fp_number_type __thenan_sf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
|
yann@1
|
747 |
+#elif defined L_thenan_df
|
yann@1
|
748 |
+const fp_number_type __thenan_df = { CLASS_SNAN, 0, 0, {(fractype) 0} };
|
yann@1
|
749 |
+#elif defined L_thenan_tf
|
yann@1
|
750 |
+const fp_number_type __thenan_tf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
|
yann@1
|
751 |
+#elif defined TFLOAT
|
yann@1
|
752 |
+extern const fp_number_type __thenan_tf;
|
yann@1
|
753 |
+#elif defined FLOAT
|
yann@1
|
754 |
+extern const fp_number_type __thenan_sf;
|
yann@1
|
755 |
+#else
|
yann@1
|
756 |
+extern const fp_number_type __thenan_df;
|
yann@1
|
757 |
+#endif
|
yann@1
|
758 |
+
|
yann@1
|
759 |
+INLINE
|
yann@1
|
760 |
+static fp_number_type *
|
yann@1
|
761 |
+nan (void)
|
yann@1
|
762 |
+{
|
yann@1
|
763 |
+ /* Discard the const qualifier... */
|
yann@1
|
764 |
+#ifdef TFLOAT
|
yann@1
|
765 |
+ return (fp_number_type *) (& __thenan_tf);
|
yann@1
|
766 |
+#elif defined FLOAT
|
yann@1
|
767 |
+ return (fp_number_type *) (& __thenan_sf);
|
yann@1
|
768 |
+#else
|
yann@1
|
769 |
+ return (fp_number_type *) (& __thenan_df);
|
yann@1
|
770 |
+#endif
|
yann@1
|
771 |
+}
|
yann@1
|
772 |
+
|
yann@1
|
773 |
+INLINE
|
yann@1
|
774 |
+static int
|
yann@1
|
775 |
+isnan ( fp_number_type * x)
|
yann@1
|
776 |
+{
|
yann@1
|
777 |
+ return x->class == CLASS_SNAN || x->class == CLASS_QNAN;
|
yann@1
|
778 |
+}
|
yann@1
|
779 |
+
|
yann@1
|
780 |
+INLINE
|
yann@1
|
781 |
+static int
|
yann@1
|
782 |
+isinf ( fp_number_type * x)
|
yann@1
|
783 |
+{
|
yann@1
|
784 |
+ return x->class == CLASS_INFINITY;
|
yann@1
|
785 |
+}
|
yann@1
|
786 |
+
|
yann@1
|
787 |
+#endif /* NO_NANS */
|
yann@1
|
788 |
+
|
yann@1
|
789 |
+INLINE
|
yann@1
|
790 |
+static int
|
yann@1
|
791 |
+iszero ( fp_number_type * x)
|
yann@1
|
792 |
+{
|
yann@1
|
793 |
+ return x->class == CLASS_ZERO;
|
yann@1
|
794 |
+}
|
yann@1
|
795 |
+
|
yann@1
|
796 |
+INLINE
|
yann@1
|
797 |
+static void
|
yann@1
|
798 |
+flip_sign ( fp_number_type * x)
|
yann@1
|
799 |
+{
|
yann@1
|
800 |
+ x->sign = !x->sign;
|
yann@1
|
801 |
+}
|
yann@1
|
802 |
+
|
yann@1
|
803 |
+extern FLO_type pack_d ( fp_number_type * );
|
yann@1
|
804 |
+
|
yann@1
|
805 |
+#if defined(L_pack_df) || defined(L_pack_sf) || defined(L_pack_tf)
|
yann@1
|
806 |
+FLO_type
|
yann@1
|
807 |
+pack_d ( fp_number_type * src)
|
yann@1
|
808 |
+{
|
yann@1
|
809 |
+ FLO_union_type dst;
|
yann@1
|
810 |
+ fractype fraction = src->fraction.ll; /* wasn't unsigned before? */
|
yann@1
|
811 |
+ int sign = src->sign;
|
yann@1
|
812 |
+ int exp = 0;
|
yann@1
|
813 |
+
|
yann@1
|
814 |
+ if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && (isnan (src) || isinf (src)))
|
yann@1
|
815 |
+ {
|
yann@1
|
816 |
+ /* We can't represent these values accurately. By using the
|
yann@1
|
817 |
+ largest possible magnitude, we guarantee that the conversion
|
yann@1
|
818 |
+ of infinity is at least as big as any finite number. */
|
yann@1
|
819 |
+ exp = EXPMAX;
|
yann@1
|
820 |
+ fraction = ((fractype) 1 << FRACBITS) - 1;
|
yann@1
|
821 |
+ }
|
yann@1
|
822 |
+ else if (isnan (src))
|
yann@1
|
823 |
+ {
|
yann@1
|
824 |
+ exp = EXPMAX;
|
yann@1
|
825 |
+ if (src->class == CLASS_QNAN || 1)
|
yann@1
|
826 |
+ {
|
yann@1
|
827 |
+#ifdef QUIET_NAN_NEGATED
|
yann@1
|
828 |
+ fraction |= QUIET_NAN - 1;
|
yann@1
|
829 |
+#else
|
yann@1
|
830 |
+ fraction |= QUIET_NAN;
|
yann@1
|
831 |
+#endif
|
yann@1
|
832 |
+ }
|
yann@1
|
833 |
+ }
|
yann@1
|
834 |
+ else if (isinf (src))
|
yann@1
|
835 |
+ {
|
yann@1
|
836 |
+ exp = EXPMAX;
|
yann@1
|
837 |
+ fraction = 0;
|
yann@1
|
838 |
+ }
|
yann@1
|
839 |
+ else if (iszero (src))
|
yann@1
|
840 |
+ {
|
yann@1
|
841 |
+ exp = 0;
|
yann@1
|
842 |
+ fraction = 0;
|
yann@1
|
843 |
+ }
|
yann@1
|
844 |
+ else if (fraction == 0)
|
yann@1
|
845 |
+ {
|
yann@1
|
846 |
+ exp = 0;
|
yann@1
|
847 |
+ }
|
yann@1
|
848 |
+ else
|
yann@1
|
849 |
+ {
|
yann@1
|
850 |
+ if (src->normal_exp < NORMAL_EXPMIN)
|
yann@1
|
851 |
+ {
|
yann@1
|
852 |
+#ifdef NO_DENORMALS
|
yann@1
|
853 |
+ /* Go straight to a zero representation if denormals are not
|
yann@1
|
854 |
+ supported. The denormal handling would be harmless but
|
yann@1
|
855 |
+ isn't unnecessary. */
|
yann@1
|
856 |
+ exp = 0;
|
yann@1
|
857 |
+ fraction = 0;
|
yann@1
|
858 |
+#else /* NO_DENORMALS */
|
yann@1
|
859 |
+ /* This number's exponent is too low to fit into the bits
|
yann@1
|
860 |
+ available in the number, so we'll store 0 in the exponent and
|
yann@1
|
861 |
+ shift the fraction to the right to make up for it. */
|
yann@1
|
862 |
+
|
yann@1
|
863 |
+ int shift = NORMAL_EXPMIN - src->normal_exp;
|
yann@1
|
864 |
+
|
yann@1
|
865 |
+ exp = 0;
|
yann@1
|
866 |
+
|
yann@1
|
867 |
+ if (shift > FRAC_NBITS - NGARDS)
|
yann@1
|
868 |
+ {
|
yann@1
|
869 |
+ /* No point shifting, since it's more that 64 out. */
|
yann@1
|
870 |
+ fraction = 0;
|
yann@1
|
871 |
+ }
|
yann@1
|
872 |
+ else
|
yann@1
|
873 |
+ {
|
yann@1
|
874 |
+ int lowbit = (fraction & (((fractype)1 << shift) - 1)) ? 1 : 0;
|
yann@1
|
875 |
+ fraction = (fraction >> shift) | lowbit;
|
yann@1
|
876 |
+ }
|
yann@1
|
877 |
+ if ((fraction & GARDMASK) == GARDMSB)
|
yann@1
|
878 |
+ {
|
yann@1
|
879 |
+ if ((fraction & (1 << NGARDS)))
|
yann@1
|
880 |
+ fraction += GARDROUND + 1;
|
yann@1
|
881 |
+ }
|
yann@1
|
882 |
+ else
|
yann@1
|
883 |
+ {
|
yann@1
|
884 |
+ /* Add to the guards to round up. */
|
yann@1
|
885 |
+ fraction += GARDROUND;
|
yann@1
|
886 |
+ }
|
yann@1
|
887 |
+ /* Perhaps the rounding means we now need to change the
|
yann@1
|
888 |
+ exponent, because the fraction is no longer denormal. */
|
yann@1
|
889 |
+ if (fraction >= IMPLICIT_1)
|
yann@1
|
890 |
+ {
|
yann@1
|
891 |
+ exp += 1;
|
yann@1
|
892 |
+ }
|
yann@1
|
893 |
+ fraction >>= NGARDS;
|
yann@1
|
894 |
+#endif /* NO_DENORMALS */
|
yann@1
|
895 |
+ }
|
yann@1
|
896 |
+ else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS)
|
yann@1
|
897 |
+ && src->normal_exp > EXPBIAS)
|
yann@1
|
898 |
+ {
|
yann@1
|
899 |
+ exp = EXPMAX;
|
yann@1
|
900 |
+ fraction = 0;
|
yann@1
|
901 |
+ }
|
yann@1
|
902 |
+ else
|
yann@1
|
903 |
+ {
|
yann@1
|
904 |
+ exp = src->normal_exp + EXPBIAS;
|
yann@1
|
905 |
+ if (!ROUND_TOWARDS_ZERO)
|
yann@1
|
906 |
+ {
|
yann@1
|
907 |
+ /* IF the gard bits are the all zero, but the first, then we're
|
yann@1
|
908 |
+ half way between two numbers, choose the one which makes the
|
yann@1
|
909 |
+ lsb of the answer 0. */
|
yann@1
|
910 |
+ if ((fraction & GARDMASK) == GARDMSB)
|
yann@1
|
911 |
+ {
|
yann@1
|
912 |
+ if (fraction & (1 << NGARDS))
|
yann@1
|
913 |
+ fraction += GARDROUND + 1;
|
yann@1
|
914 |
+ }
|
yann@1
|
915 |
+ else
|
yann@1
|
916 |
+ {
|
yann@1
|
917 |
+ /* Add a one to the guards to round up */
|
yann@1
|
918 |
+ fraction += GARDROUND;
|
yann@1
|
919 |
+ }
|
yann@1
|
920 |
+ if (fraction >= IMPLICIT_2)
|
yann@1
|
921 |
+ {
|
yann@1
|
922 |
+ fraction >>= 1;
|
yann@1
|
923 |
+ exp += 1;
|
yann@1
|
924 |
+ }
|
yann@1
|
925 |
+ }
|
yann@1
|
926 |
+ fraction >>= NGARDS;
|
yann@1
|
927 |
+
|
yann@1
|
928 |
+ if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp > EXPMAX)
|
yann@1
|
929 |
+ {
|
yann@1
|
930 |
+ /* Saturate on overflow. */
|
yann@1
|
931 |
+ exp = EXPMAX;
|
yann@1
|
932 |
+ fraction = ((fractype) 1 << FRACBITS) - 1;
|
yann@1
|
933 |
+ }
|
yann@1
|
934 |
+ }
|
yann@1
|
935 |
+ }
|
yann@1
|
936 |
+
|
yann@1
|
937 |
+ /* We previously used bitfields to store the number, but this doesn't
|
yann@1
|
938 |
+ handle little/big endian systems conveniently, so use shifts and
|
yann@1
|
939 |
+ masks */
|
yann@1
|
940 |
+#ifdef FLOAT_BIT_ORDER_MISMATCH
|
yann@1
|
941 |
+ dst.bits.fraction = fraction;
|
yann@1
|
942 |
+ dst.bits.exp = exp;
|
yann@1
|
943 |
+ dst.bits.sign = sign;
|
yann@1
|
944 |
+#else
|
yann@1
|
945 |
+# if defined TFLOAT && defined HALFFRACBITS
|
yann@1
|
946 |
+ {
|
yann@1
|
947 |
+ halffractype high, low, unity;
|
yann@1
|
948 |
+ int lowsign, lowexp;
|
yann@1
|
949 |
+
|
yann@1
|
950 |
+ unity = (halffractype) 1 << HALFFRACBITS;
|
yann@1
|
951 |
+
|
yann@1
|
952 |
+ /* Set HIGH to the high double's significand, masking out the implicit 1.
|
yann@1
|
953 |
+ Set LOW to the low double's full significand. */
|
yann@1
|
954 |
+ high = (fraction >> (FRACBITS - HALFFRACBITS)) & (unity - 1);
|
yann@1
|
955 |
+ low = fraction & (unity * 2 - 1);
|
yann@1
|
956 |
+
|
yann@1
|
957 |
+ /* Get the initial sign and exponent of the low double. */
|
yann@1
|
958 |
+ lowexp = exp - HALFFRACBITS - 1;
|
yann@1
|
959 |
+ lowsign = sign;
|
yann@1
|
960 |
+
|
yann@1
|
961 |
+ /* HIGH should be rounded like a normal double, making |LOW| <=
|
yann@1
|
962 |
+ 0.5 ULP of HIGH. Assume round-to-nearest. */
|
yann@1
|
963 |
+ if (exp < EXPMAX)
|
yann@1
|
964 |
+ if (low > unity || (low == unity && (high & 1) == 1))
|
yann@1
|
965 |
+ {
|
yann@1
|
966 |
+ /* Round HIGH up and adjust LOW to match. */
|
yann@1
|
967 |
+ high++;
|
yann@1
|
968 |
+ if (high == unity)
|
yann@1
|
969 |
+ {
|
yann@1
|
970 |
+ /* May make it infinite, but that's OK. */
|
yann@1
|
971 |
+ high = 0;
|
yann@1
|
972 |
+ exp++;
|
yann@1
|
973 |
+ }
|
yann@1
|
974 |
+ low = unity * 2 - low;
|
yann@1
|
975 |
+ lowsign ^= 1;
|
yann@1
|
976 |
+ }
|
yann@1
|
977 |
+
|
yann@1
|
978 |
+ high |= (halffractype) exp << HALFFRACBITS;
|
yann@1
|
979 |
+ high |= (halffractype) sign << (HALFFRACBITS + EXPBITS);
|
yann@1
|
980 |
+
|
yann@1
|
981 |
+ if (exp == EXPMAX || exp == 0 || low == 0)
|
yann@1
|
982 |
+ low = 0;
|
yann@1
|
983 |
+ else
|
yann@1
|
984 |
+ {
|
yann@1
|
985 |
+ while (lowexp > 0 && low < unity)
|
yann@1
|
986 |
+ {
|
yann@1
|
987 |
+ low <<= 1;
|
yann@1
|
988 |
+ lowexp--;
|
yann@1
|
989 |
+ }
|
yann@1
|
990 |
+
|
yann@1
|
991 |
+ if (lowexp <= 0)
|
yann@1
|
992 |
+ {
|
yann@1
|
993 |
+ halffractype roundmsb, round;
|
yann@1
|
994 |
+ int shift;
|
yann@1
|
995 |
+
|
yann@1
|
996 |
+ shift = 1 - lowexp;
|
yann@1
|
997 |
+ roundmsb = (1 << (shift - 1));
|
yann@1
|
998 |
+ round = low & ((roundmsb << 1) - 1);
|
yann@1
|
999 |
+
|
yann@1
|
1000 |
+ low >>= shift;
|
yann@1
|
1001 |
+ lowexp = 0;
|
yann@1
|
1002 |
+
|
yann@1
|
1003 |
+ if (round > roundmsb || (round == roundmsb && (low & 1) == 1))
|
yann@1
|
1004 |
+ {
|
yann@1
|
1005 |
+ low++;
|
yann@1
|
1006 |
+ if (low == unity)
|
yann@1
|
1007 |
+ /* LOW rounds up to the smallest normal number. */
|
yann@1
|
1008 |
+ lowexp++;
|
yann@1
|
1009 |
+ }
|
yann@1
|
1010 |
+ }
|
yann@1
|
1011 |
+
|
yann@1
|
1012 |
+ low &= unity - 1;
|
yann@1
|
1013 |
+ low |= (halffractype) lowexp << HALFFRACBITS;
|
yann@1
|
1014 |
+ low |= (halffractype) lowsign << (HALFFRACBITS + EXPBITS);
|
yann@1
|
1015 |
+ }
|
yann@1
|
1016 |
+ dst.value_raw = ((fractype) high << HALFSHIFT) | low;
|
yann@1
|
1017 |
+ }
|
yann@1
|
1018 |
+# else
|
yann@1
|
1019 |
+ dst.value_raw = fraction & ((((fractype)1) << FRACBITS) - (fractype)1);
|
yann@1
|
1020 |
+ dst.value_raw |= ((fractype) (exp & ((1 << EXPBITS) - 1))) << FRACBITS;
|
yann@1
|
1021 |
+ dst.value_raw |= ((fractype) (sign & 1)) << (FRACBITS | EXPBITS);
|
yann@1
|
1022 |
+# endif
|
yann@1
|
1023 |
+#endif
|
yann@1
|
1024 |
+
|
yann@1
|
1025 |
+#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
|
yann@1
|
1026 |
+#ifdef TFLOAT
|
yann@1
|
1027 |
+ {
|
yann@1
|
1028 |
+ qrtrfractype tmp1 = dst.words[0];
|
yann@1
|
1029 |
+ qrtrfractype tmp2 = dst.words[1];
|
yann@1
|
1030 |
+ dst.words[0] = dst.words[3];
|
yann@1
|
1031 |
+ dst.words[1] = dst.words[2];
|
yann@1
|
1032 |
+ dst.words[2] = tmp2;
|
yann@1
|
1033 |
+ dst.words[3] = tmp1;
|
yann@1
|
1034 |
+ }
|
yann@1
|
1035 |
+#else
|
yann@1
|
1036 |
+ {
|
yann@1
|
1037 |
+ halffractype tmp = dst.words[0];
|
yann@1
|
1038 |
+ dst.words[0] = dst.words[1];
|
yann@1
|
1039 |
+ dst.words[1] = tmp;
|
yann@1
|
1040 |
+ }
|
yann@1
|
1041 |
+#endif
|
yann@1
|
1042 |
+#endif
|
yann@1
|
1043 |
+
|
yann@1
|
1044 |
+ return dst.value;
|
yann@1
|
1045 |
+}
|
yann@1
|
1046 |
+#endif
|
yann@1
|
1047 |
+
|
yann@1
|
1048 |
+#if defined(L_unpack_df) || defined(L_unpack_sf) || defined(L_unpack_tf)
|
yann@1
|
1049 |
+void
|
yann@1
|
1050 |
+unpack_d (FLO_union_type * src, fp_number_type * dst)
|
yann@1
|
1051 |
+{
|
yann@1
|
1052 |
+ /* We previously used bitfields to store the number, but this doesn't
|
yann@1
|
1053 |
+ handle little/big endian systems conveniently, so use shifts and
|
yann@1
|
1054 |
+ masks */
|
yann@1
|
1055 |
+ fractype fraction;
|
yann@1
|
1056 |
+ int exp;
|
yann@1
|
1057 |
+ int sign;
|
yann@1
|
1058 |
+
|
yann@1
|
1059 |
+#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
|
yann@1
|
1060 |
+ FLO_union_type swapped;
|
yann@1
|
1061 |
+
|
yann@1
|
1062 |
+#ifdef TFLOAT
|
yann@1
|
1063 |
+ swapped.words[0] = src->words[3];
|
yann@1
|
1064 |
+ swapped.words[1] = src->words[2];
|
yann@1
|
1065 |
+ swapped.words[2] = src->words[1];
|
yann@1
|
1066 |
+ swapped.words[3] = src->words[0];
|
yann@1
|
1067 |
+#else
|
yann@1
|
1068 |
+ swapped.words[0] = src->words[1];
|
yann@1
|
1069 |
+ swapped.words[1] = src->words[0];
|
yann@1
|
1070 |
+#endif
|
yann@1
|
1071 |
+ src = &swapped;
|
yann@1
|
1072 |
+#endif
|
yann@1
|
1073 |
+
|
yann@1
|
1074 |
+#ifdef FLOAT_BIT_ORDER_MISMATCH
|
yann@1
|
1075 |
+ fraction = src->bits.fraction;
|
yann@1
|
1076 |
+ exp = src->bits.exp;
|
yann@1
|
1077 |
+ sign = src->bits.sign;
|
yann@1
|
1078 |
+#else
|
yann@1
|
1079 |
+# if defined TFLOAT && defined HALFFRACBITS
|
yann@1
|
1080 |
+ {
|
yann@1
|
1081 |
+ halffractype high, low;
|
yann@1
|
1082 |
+
|
yann@1
|
1083 |
+ high = src->value_raw >> HALFSHIFT;
|
yann@1
|
1084 |
+ low = src->value_raw & (((fractype)1 << HALFSHIFT) - 1);
|
yann@1
|
1085 |
+
|
yann@1
|
1086 |
+ fraction = high & ((((fractype)1) << HALFFRACBITS) - 1);
|
yann@1
|
1087 |
+ fraction <<= FRACBITS - HALFFRACBITS;
|
yann@1
|
1088 |
+ exp = ((int)(high >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
|
yann@1
|
1089 |
+ sign = ((int)(high >> (((HALFFRACBITS + EXPBITS))))) & 1;
|
yann@1
|
1090 |
+
|
yann@1
|
1091 |
+ if (exp != EXPMAX && exp != 0 && low != 0)
|
yann@1
|
1092 |
+ {
|
yann@1
|
1093 |
+ int lowexp = ((int)(low >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
|
yann@1
|
1094 |
+ int lowsign = ((int)(low >> (((HALFFRACBITS + EXPBITS))))) & 1;
|
yann@1
|
1095 |
+ int shift;
|
yann@1
|
1096 |
+ fractype xlow;
|
yann@1
|
1097 |
+
|
yann@1
|
1098 |
+ xlow = low & ((((fractype)1) << HALFFRACBITS) - 1);
|
yann@1
|
1099 |
+ if (lowexp)
|
yann@1
|
1100 |
+ xlow |= (((halffractype)1) << HALFFRACBITS);
|
yann@1
|
1101 |
+ else
|
yann@1
|
1102 |
+ lowexp = 1;
|
yann@1
|
1103 |
+ shift = (FRACBITS - HALFFRACBITS) - (exp - lowexp);
|
yann@1
|
1104 |
+ if (shift > 0)
|
yann@1
|
1105 |
+ xlow <<= shift;
|
yann@1
|
1106 |
+ else if (shift < 0)
|
yann@1
|
1107 |
+ xlow >>= -shift;
|
yann@1
|
1108 |
+ if (sign == lowsign)
|
yann@1
|
1109 |
+ fraction += xlow;
|
yann@1
|
1110 |
+ else if (fraction >= xlow)
|
yann@1
|
1111 |
+ fraction -= xlow;
|
yann@1
|
1112 |
+ else
|
yann@1
|
1113 |
+ {
|
yann@1
|
1114 |
+ /* The high part is a power of two but the full number is lower.
|
yann@1
|
1115 |
+ This code will leave the implicit 1 in FRACTION, but we'd
|
yann@1
|
1116 |
+ have added that below anyway. */
|
yann@1
|
1117 |
+ fraction = (((fractype) 1 << FRACBITS) - xlow) << 1;
|
yann@1
|
1118 |
+ exp--;
|
yann@1
|
1119 |
+ }
|
yann@1
|
1120 |
+ }
|
yann@1
|
1121 |
+ }
|
yann@1
|
1122 |
+# else
|
yann@1
|
1123 |
+ fraction = src->value_raw & ((((fractype)1) << FRACBITS) - 1);
|
yann@1
|
1124 |
+ exp = ((int)(src->value_raw >> FRACBITS)) & ((1 << EXPBITS) - 1);
|
yann@1
|
1125 |
+ sign = ((int)(src->value_raw >> (FRACBITS + EXPBITS))) & 1;
|
yann@1
|
1126 |
+# endif
|
yann@1
|
1127 |
+#endif
|
yann@1
|
1128 |
+
|
yann@1
|
1129 |
+ dst->sign = sign;
|
yann@1
|
1130 |
+ if (exp == 0)
|
yann@1
|
1131 |
+ {
|
yann@1
|
1132 |
+ /* Hmm. Looks like 0 */
|
yann@1
|
1133 |
+ if (fraction == 0
|
yann@1
|
1134 |
+#ifdef NO_DENORMALS
|
yann@1
|
1135 |
+ || 1
|
yann@1
|
1136 |
+#endif
|
yann@1
|
1137 |
+ )
|
yann@1
|
1138 |
+ {
|
yann@1
|
1139 |
+ /* tastes like zero */
|
yann@1
|
1140 |
+ dst->class = CLASS_ZERO;
|
yann@1
|
1141 |
+ }
|
yann@1
|
1142 |
+ else
|
yann@1
|
1143 |
+ {
|
yann@1
|
1144 |
+ /* Zero exponent with nonzero fraction - it's denormalized,
|
yann@1
|
1145 |
+ so there isn't a leading implicit one - we'll shift it so
|
yann@1
|
1146 |
+ it gets one. */
|
yann@1
|
1147 |
+ dst->normal_exp = exp - EXPBIAS + 1;
|
yann@1
|
1148 |
+ fraction <<= NGARDS;
|
yann@1
|
1149 |
+
|
yann@1
|
1150 |
+ dst->class = CLASS_NUMBER;
|
yann@1
|
1151 |
+#if 1
|
yann@1
|
1152 |
+ while (fraction < IMPLICIT_1)
|
yann@1
|
1153 |
+ {
|
yann@1
|
1154 |
+ fraction <<= 1;
|
yann@1
|
1155 |
+ dst->normal_exp--;
|
yann@1
|
1156 |
+ }
|
yann@1
|
1157 |
+#endif
|
yann@1
|
1158 |
+ dst->fraction.ll = fraction;
|
yann@1
|
1159 |
+ }
|
yann@1
|
1160 |
+ }
|
yann@1
|
1161 |
+ else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp == EXPMAX)
|
yann@1
|
1162 |
+ {
|
yann@1
|
1163 |
+ /* Huge exponent*/
|
yann@1
|
1164 |
+ if (fraction == 0)
|
yann@1
|
1165 |
+ {
|
yann@1
|
1166 |
+ /* Attached to a zero fraction - means infinity */
|
yann@1
|
1167 |
+ dst->class = CLASS_INFINITY;
|
yann@1
|
1168 |
+ }
|
yann@1
|
1169 |
+ else
|
yann@1
|
1170 |
+ {
|
yann@1
|
1171 |
+ /* Nonzero fraction, means nan */
|
yann@1
|
1172 |
+#ifdef QUIET_NAN_NEGATED
|
yann@1
|
1173 |
+ if ((fraction & QUIET_NAN) == 0)
|
yann@1
|
1174 |
+#else
|
yann@1
|
1175 |
+ if (fraction & QUIET_NAN)
|
yann@1
|
1176 |
+#endif
|
yann@1
|
1177 |
+ {
|
yann@1
|
1178 |
+ dst->class = CLASS_QNAN;
|
yann@1
|
1179 |
+ }
|
yann@1
|
1180 |
+ else
|
yann@1
|
1181 |
+ {
|
yann@1
|
1182 |
+ dst->class = CLASS_SNAN;
|
yann@1
|
1183 |
+ }
|
yann@1
|
1184 |
+ /* Keep the fraction part as the nan number */
|
yann@1
|
1185 |
+ dst->fraction.ll = fraction;
|
yann@1
|
1186 |
+ }
|
yann@1
|
1187 |
+ }
|
yann@1
|
1188 |
+ else
|
yann@1
|
1189 |
+ {
|
yann@1
|
1190 |
+ /* Nothing strange about this number */
|
yann@1
|
1191 |
+ dst->normal_exp = exp - EXPBIAS;
|
yann@1
|
1192 |
+ dst->class = CLASS_NUMBER;
|
yann@1
|
1193 |
+ dst->fraction.ll = (fraction << NGARDS) | IMPLICIT_1;
|
yann@1
|
1194 |
+ }
|
yann@1
|
1195 |
+}
|
yann@1
|
1196 |
+#endif /* L_unpack_df || L_unpack_sf */
|
yann@1
|
1197 |
+
|
yann@1
|
1198 |
+#if defined(L_addsub_sf) || defined(L_addsub_df) || defined(L_addsub_tf)
|
yann@1
|
1199 |
+static fp_number_type *
|
yann@1
|
1200 |
+_fpadd_parts (fp_number_type * a,
|
yann@1
|
1201 |
+ fp_number_type * b,
|
yann@1
|
1202 |
+ fp_number_type * tmp)
|
yann@1
|
1203 |
+{
|
yann@1
|
1204 |
+ intfrac tfraction;
|
yann@1
|
1205 |
+
|
yann@1
|
1206 |
+ /* Put commonly used fields in local variables. */
|
yann@1
|
1207 |
+ int a_normal_exp;
|
yann@1
|
1208 |
+ int b_normal_exp;
|
yann@1
|
1209 |
+ fractype a_fraction;
|
yann@1
|
1210 |
+ fractype b_fraction;
|
yann@1
|
1211 |
+
|
yann@1
|
1212 |
+ if (isnan (a))
|
yann@1
|
1213 |
+ {
|
yann@1
|
1214 |
+ return a;
|
yann@1
|
1215 |
+ }
|
yann@1
|
1216 |
+ if (isnan (b))
|
yann@1
|
1217 |
+ {
|
yann@1
|
1218 |
+ return b;
|
yann@1
|
1219 |
+ }
|
yann@1
|
1220 |
+ if (isinf (a))
|
yann@1
|
1221 |
+ {
|
yann@1
|
1222 |
+ /* Adding infinities with opposite signs yields a NaN. */
|
yann@1
|
1223 |
+ if (isinf (b) && a->sign != b->sign)
|
yann@1
|
1224 |
+ return nan ();
|
yann@1
|
1225 |
+ return a;
|
yann@1
|
1226 |
+ }
|
yann@1
|
1227 |
+ if (isinf (b))
|
yann@1
|
1228 |
+ {
|
yann@1
|
1229 |
+ return b;
|
yann@1
|
1230 |
+ }
|
yann@1
|
1231 |
+ if (iszero (b))
|
yann@1
|
1232 |
+ {
|
yann@1
|
1233 |
+ if (iszero (a))
|
yann@1
|
1234 |
+ {
|
yann@1
|
1235 |
+ *tmp = *a;
|
yann@1
|
1236 |
+ tmp->sign = a->sign & b->sign;
|
yann@1
|
1237 |
+ return tmp;
|
yann@1
|
1238 |
+ }
|
yann@1
|
1239 |
+ return a;
|
yann@1
|
1240 |
+ }
|
yann@1
|
1241 |
+ if (iszero (a))
|
yann@1
|
1242 |
+ {
|
yann@1
|
1243 |
+ return b;
|
yann@1
|
1244 |
+ }
|
yann@1
|
1245 |
+
|
yann@1
|
1246 |
+ /* Got two numbers. shift the smaller and increment the exponent till
|
yann@1
|
1247 |
+ they're the same */
|
yann@1
|
1248 |
+ {
|
yann@1
|
1249 |
+ int diff;
|
yann@1
|
1250 |
+
|
yann@1
|
1251 |
+ a_normal_exp = a->normal_exp;
|
yann@1
|
1252 |
+ b_normal_exp = b->normal_exp;
|
yann@1
|
1253 |
+ a_fraction = a->fraction.ll;
|
yann@1
|
1254 |
+ b_fraction = b->fraction.ll;
|
yann@1
|
1255 |
+
|
yann@1
|
1256 |
+ diff = a_normal_exp - b_normal_exp;
|
yann@1
|
1257 |
+
|
yann@1
|
1258 |
+ if (diff < 0)
|
yann@1
|
1259 |
+ diff = -diff;
|
yann@1
|
1260 |
+ if (diff < FRAC_NBITS)
|
yann@1
|
1261 |
+ {
|
yann@1
|
1262 |
+ /* ??? This does shifts one bit at a time. Optimize. */
|
yann@1
|
1263 |
+ while (a_normal_exp > b_normal_exp)
|
yann@1
|
1264 |
+ {
|
yann@1
|
1265 |
+ b_normal_exp++;
|
yann@1
|
1266 |
+ LSHIFT (b_fraction);
|
yann@1
|
1267 |
+ }
|
yann@1
|
1268 |
+ while (b_normal_exp > a_normal_exp)
|
yann@1
|
1269 |
+ {
|
yann@1
|
1270 |
+ a_normal_exp++;
|
yann@1
|
1271 |
+ LSHIFT (a_fraction);
|
yann@1
|
1272 |
+ }
|
yann@1
|
1273 |
+ }
|
yann@1
|
1274 |
+ else
|
yann@1
|
1275 |
+ {
|
yann@1
|
1276 |
+ /* Somethings's up.. choose the biggest */
|
yann@1
|
1277 |
+ if (a_normal_exp > b_normal_exp)
|
yann@1
|
1278 |
+ {
|
yann@1
|
1279 |
+ b_normal_exp = a_normal_exp;
|
yann@1
|
1280 |
+ b_fraction = 0;
|
yann@1
|
1281 |
+ }
|
yann@1
|
1282 |
+ else
|
yann@1
|
1283 |
+ {
|
yann@1
|
1284 |
+ a_normal_exp = b_normal_exp;
|
yann@1
|
1285 |
+ a_fraction = 0;
|
yann@1
|
1286 |
+ }
|
yann@1
|
1287 |
+ }
|
yann@1
|
1288 |
+ }
|
yann@1
|
1289 |
+
|
yann@1
|
1290 |
+ if (a->sign != b->sign)
|
yann@1
|
1291 |
+ {
|
yann@1
|
1292 |
+ if (a->sign)
|
yann@1
|
1293 |
+ {
|
yann@1
|
1294 |
+ tfraction = -a_fraction + b_fraction;
|
yann@1
|
1295 |
+ }
|
yann@1
|
1296 |
+ else
|
yann@1
|
1297 |
+ {
|
yann@1
|
1298 |
+ tfraction = a_fraction - b_fraction;
|
yann@1
|
1299 |
+ }
|
yann@1
|
1300 |
+ if (tfraction >= 0)
|
yann@1
|
1301 |
+ {
|
yann@1
|
1302 |
+ tmp->sign = 0;
|
yann@1
|
1303 |
+ tmp->normal_exp = a_normal_exp;
|
yann@1
|
1304 |
+ tmp->fraction.ll = tfraction;
|
yann@1
|
1305 |
+ }
|
yann@1
|
1306 |
+ else
|
yann@1
|
1307 |
+ {
|
yann@1
|
1308 |
+ tmp->sign = 1;
|
yann@1
|
1309 |
+ tmp->normal_exp = a_normal_exp;
|
yann@1
|
1310 |
+ tmp->fraction.ll = -tfraction;
|
yann@1
|
1311 |
+ }
|
yann@1
|
1312 |
+ /* and renormalize it */
|
yann@1
|
1313 |
+
|
yann@1
|
1314 |
+ while (tmp->fraction.ll < IMPLICIT_1 && tmp->fraction.ll)
|
yann@1
|
1315 |
+ {
|
yann@1
|
1316 |
+ tmp->fraction.ll <<= 1;
|
yann@1
|
1317 |
+ tmp->normal_exp--;
|
yann@1
|
1318 |
+ }
|
yann@1
|
1319 |
+ }
|
yann@1
|
1320 |
+ else
|
yann@1
|
1321 |
+ {
|
yann@1
|
1322 |
+ tmp->sign = a->sign;
|
yann@1
|
1323 |
+ tmp->normal_exp = a_normal_exp;
|
yann@1
|
1324 |
+ tmp->fraction.ll = a_fraction + b_fraction;
|
yann@1
|
1325 |
+ }
|
yann@1
|
1326 |
+ tmp->class = CLASS_NUMBER;
|
yann@1
|
1327 |
+ /* Now the fraction is added, we have to shift down to renormalize the
|
yann@1
|
1328 |
+ number */
|
yann@1
|
1329 |
+
|
yann@1
|
1330 |
+ if (tmp->fraction.ll >= IMPLICIT_2)
|
yann@1
|
1331 |
+ {
|
yann@1
|
1332 |
+ LSHIFT (tmp->fraction.ll);
|
yann@1
|
1333 |
+ tmp->normal_exp++;
|
yann@1
|
1334 |
+ }
|
yann@1
|
1335 |
+ return tmp;
|
yann@1
|
1336 |
+
|
yann@1
|
1337 |
+}
|
yann@1
|
1338 |
+
|
yann@1
|
1339 |
+FLO_type
|
yann@1
|
1340 |
+add (FLO_type arg_a, FLO_type arg_b)
|
yann@1
|
1341 |
+{
|
yann@1
|
1342 |
+ fp_number_type a;
|
yann@1
|
1343 |
+ fp_number_type b;
|
yann@1
|
1344 |
+ fp_number_type tmp;
|
yann@1
|
1345 |
+ fp_number_type *res;
|
yann@1
|
1346 |
+ FLO_union_type au, bu;
|
yann@1
|
1347 |
+
|
yann@1
|
1348 |
+ au.value = arg_a;
|
yann@1
|
1349 |
+ bu.value = arg_b;
|
yann@1
|
1350 |
+
|
yann@1
|
1351 |
+ unpack_d (&au, &a);
|
yann@1
|
1352 |
+ unpack_d (&bu, &b);
|
yann@1
|
1353 |
+
|
yann@1
|
1354 |
+ res = _fpadd_parts (&a, &b, &tmp);
|
yann@1
|
1355 |
+
|
yann@1
|
1356 |
+ return pack_d (res);
|
yann@1
|
1357 |
+}
|
yann@1
|
1358 |
+
|
yann@1
|
1359 |
+FLO_type
|
yann@1
|
1360 |
+sub (FLO_type arg_a, FLO_type arg_b)
|
yann@1
|
1361 |
+{
|
yann@1
|
1362 |
+ fp_number_type a;
|
yann@1
|
1363 |
+ fp_number_type b;
|
yann@1
|
1364 |
+ fp_number_type tmp;
|
yann@1
|
1365 |
+ fp_number_type *res;
|
yann@1
|
1366 |
+ FLO_union_type au, bu;
|
yann@1
|
1367 |
+
|
yann@1
|
1368 |
+ au.value = arg_a;
|
yann@1
|
1369 |
+ bu.value = arg_b;
|
yann@1
|
1370 |
+
|
yann@1
|
1371 |
+ unpack_d (&au, &a);
|
yann@1
|
1372 |
+ unpack_d (&bu, &b);
|
yann@1
|
1373 |
+
|
yann@1
|
1374 |
+ b.sign ^= 1;
|
yann@1
|
1375 |
+
|
yann@1
|
1376 |
+ res = _fpadd_parts (&a, &b, &tmp);
|
yann@1
|
1377 |
+
|
yann@1
|
1378 |
+ return pack_d (res);
|
yann@1
|
1379 |
+}
|
yann@1
|
1380 |
+#endif /* L_addsub_sf || L_addsub_df */
|
yann@1
|
1381 |
+
|
yann@1
|
1382 |
+#if defined(L_mul_sf) || defined(L_mul_df) || defined(L_mul_tf)
|
yann@1
|
1383 |
+static inline __attribute__ ((__always_inline__)) fp_number_type *
|
yann@1
|
1384 |
+_fpmul_parts ( fp_number_type * a,
|
yann@1
|
1385 |
+ fp_number_type * b,
|
yann@1
|
1386 |
+ fp_number_type * tmp)
|
yann@1
|
1387 |
+{
|
yann@1
|
1388 |
+ fractype low = 0;
|
yann@1
|
1389 |
+ fractype high = 0;
|
yann@1
|
1390 |
+
|
yann@1
|
1391 |
+ if (isnan (a))
|
yann@1
|
1392 |
+ {
|
yann@1
|
1393 |
+ a->sign = a->sign != b->sign;
|
yann@1
|
1394 |
+ return a;
|
yann@1
|
1395 |
+ }
|
yann@1
|
1396 |
+ if (isnan (b))
|
yann@1
|
1397 |
+ {
|
yann@1
|
1398 |
+ b->sign = a->sign != b->sign;
|
yann@1
|
1399 |
+ return b;
|
yann@1
|
1400 |
+ }
|
yann@1
|
1401 |
+ if (isinf (a))
|
yann@1
|
1402 |
+ {
|
yann@1
|
1403 |
+ if (iszero (b))
|
yann@1
|
1404 |
+ return nan ();
|
yann@1
|
1405 |
+ a->sign = a->sign != b->sign;
|
yann@1
|
1406 |
+ return a;
|
yann@1
|
1407 |
+ }
|
yann@1
|
1408 |
+ if (isinf (b))
|
yann@1
|
1409 |
+ {
|
yann@1
|
1410 |
+ if (iszero (a))
|
yann@1
|
1411 |
+ {
|
yann@1
|
1412 |
+ return nan ();
|
yann@1
|
1413 |
+ }
|
yann@1
|
1414 |
+ b->sign = a->sign != b->sign;
|
yann@1
|
1415 |
+ return b;
|
yann@1
|
1416 |
+ }
|
yann@1
|
1417 |
+ if (iszero (a))
|
yann@1
|
1418 |
+ {
|
yann@1
|
1419 |
+ a->sign = a->sign != b->sign;
|
yann@1
|
1420 |
+ return a;
|
yann@1
|
1421 |
+ }
|
yann@1
|
1422 |
+ if (iszero (b))
|
yann@1
|
1423 |
+ {
|
yann@1
|
1424 |
+ b->sign = a->sign != b->sign;
|
yann@1
|
1425 |
+ return b;
|
yann@1
|
1426 |
+ }
|
yann@1
|
1427 |
+
|
yann@1
|
1428 |
+ /* Calculate the mantissa by multiplying both numbers to get a
|
yann@1
|
1429 |
+ twice-as-wide number. */
|
yann@1
|
1430 |
+ {
|
yann@1
|
1431 |
+#if defined(NO_DI_MODE) || defined(TFLOAT)
|
yann@1
|
1432 |
+ {
|
yann@1
|
1433 |
+ fractype x = a->fraction.ll;
|
yann@1
|
1434 |
+ fractype ylow = b->fraction.ll;
|
yann@1
|
1435 |
+ fractype yhigh = 0;
|
yann@1
|
1436 |
+ int bit;
|
yann@1
|
1437 |
+
|
yann@1
|
1438 |
+ /* ??? This does multiplies one bit at a time. Optimize. */
|
yann@1
|
1439 |
+ for (bit = 0; bit < FRAC_NBITS; bit++)
|
yann@1
|
1440 |
+ {
|
yann@1
|
1441 |
+ int carry;
|
yann@1
|
1442 |
+
|
yann@1
|
1443 |
+ if (x & 1)
|
yann@1
|
1444 |
+ {
|
yann@1
|
1445 |
+ carry = (low += ylow) < ylow;
|
yann@1
|
1446 |
+ high += yhigh + carry;
|
yann@1
|
1447 |
+ }
|
yann@1
|
1448 |
+ yhigh <<= 1;
|
yann@1
|
1449 |
+ if (ylow & FRACHIGH)
|
yann@1
|
1450 |
+ {
|
yann@1
|
1451 |
+ yhigh |= 1;
|
yann@1
|
1452 |
+ }
|
yann@1
|
1453 |
+ ylow <<= 1;
|
yann@1
|
1454 |
+ x >>= 1;
|
yann@1
|
1455 |
+ }
|
yann@1
|
1456 |
+ }
|
yann@1
|
1457 |
+#elif defined(FLOAT)
|
yann@1
|
1458 |
+ /* Multiplying two USIs to get a UDI, we're safe. */
|
yann@1
|
1459 |
+ {
|
yann@1
|
1460 |
+ UDItype answer = (UDItype)a->fraction.ll * (UDItype)b->fraction.ll;
|
yann@1
|
1461 |
+
|
yann@1
|
1462 |
+ high = answer >> BITS_PER_SI;
|
yann@1
|
1463 |
+ low = answer;
|
yann@1
|
1464 |
+ }
|
yann@1
|
1465 |
+#else
|
yann@1
|
1466 |
+ /* fractype is DImode, but we need the result to be twice as wide.
|
yann@1
|
1467 |
+ Assuming a widening multiply from DImode to TImode is not
|
yann@1
|
1468 |
+ available, build one by hand. */
|
yann@1
|
1469 |
+ {
|
yann@1
|
1470 |
+ USItype nl = a->fraction.ll;
|
yann@1
|
1471 |
+ USItype nh = a->fraction.ll >> BITS_PER_SI;
|
yann@1
|
1472 |
+ USItype ml = b->fraction.ll;
|
yann@1
|
1473 |
+ USItype mh = b->fraction.ll >> BITS_PER_SI;
|
yann@1
|
1474 |
+ UDItype pp_ll = (UDItype) ml * nl;
|
yann@1
|
1475 |
+ UDItype pp_hl = (UDItype) mh * nl;
|
yann@1
|
1476 |
+ UDItype pp_lh = (UDItype) ml * nh;
|
yann@1
|
1477 |
+ UDItype pp_hh = (UDItype) mh * nh;
|
yann@1
|
1478 |
+ UDItype res2 = 0;
|
yann@1
|
1479 |
+ UDItype res0 = 0;
|
yann@1
|
1480 |
+ UDItype ps_hh__ = pp_hl + pp_lh;
|
yann@1
|
1481 |
+ if (ps_hh__ < pp_hl)
|
yann@1
|
1482 |
+ res2 += (UDItype)1 << BITS_PER_SI;
|
yann@1
|
1483 |
+ pp_hl = (UDItype)(USItype)ps_hh__ << BITS_PER_SI;
|
yann@1
|
1484 |
+ res0 = pp_ll + pp_hl;
|
yann@1
|
1485 |
+ if (res0 < pp_ll)
|
yann@1
|
1486 |
+ res2++;
|
yann@1
|
1487 |
+ res2 += (ps_hh__ >> BITS_PER_SI) + pp_hh;
|
yann@1
|
1488 |
+ high = res2;
|
yann@1
|
1489 |
+ low = res0;
|
yann@1
|
1490 |
+ }
|
yann@1
|
1491 |
+#endif
|
yann@1
|
1492 |
+ }
|
yann@1
|
1493 |
+
|
yann@1
|
1494 |
+ tmp->normal_exp = a->normal_exp + b->normal_exp
|
yann@1
|
1495 |
+ + FRAC_NBITS - (FRACBITS + NGARDS);
|
yann@1
|
1496 |
+ tmp->sign = a->sign != b->sign;
|
yann@1
|
1497 |
+ while (high >= IMPLICIT_2)
|
yann@1
|
1498 |
+ {
|
yann@1
|
1499 |
+ tmp->normal_exp++;
|
yann@1
|
1500 |
+ if (high & 1)
|
yann@1
|
1501 |
+ {
|
yann@1
|
1502 |
+ low >>= 1;
|
yann@1
|
1503 |
+ low |= FRACHIGH;
|
yann@1
|
1504 |
+ }
|
yann@1
|
1505 |
+ high >>= 1;
|
yann@1
|
1506 |
+ }
|
yann@1
|
1507 |
+ while (high < IMPLICIT_1)
|
yann@1
|
1508 |
+ {
|
yann@1
|
1509 |
+ tmp->normal_exp--;
|
yann@1
|
1510 |
+
|
yann@1
|
1511 |
+ high <<= 1;
|
yann@1
|
1512 |
+ if (low & FRACHIGH)
|
yann@1
|
1513 |
+ high |= 1;
|
yann@1
|
1514 |
+ low <<= 1;
|
yann@1
|
1515 |
+ }
|
yann@1
|
1516 |
+ /* rounding is tricky. if we only round if it won't make us round later. */
|
yann@1
|
1517 |
+#if 0
|
yann@1
|
1518 |
+ if (low & FRACHIGH2)
|
yann@1
|
1519 |
+ {
|
yann@1
|
1520 |
+ if (((high & GARDMASK) != GARDMSB)
|
yann@1
|
1521 |
+ && (((high + 1) & GARDMASK) == GARDMSB))
|
yann@1
|
1522 |
+ {
|
yann@1
|
1523 |
+ /* don't round, it gets done again later. */
|
yann@1
|
1524 |
+ }
|
yann@1
|
1525 |
+ else
|
yann@1
|
1526 |
+ {
|
yann@1
|
1527 |
+ high++;
|
yann@1
|
1528 |
+ }
|
yann@1
|
1529 |
+ }
|
yann@1
|
1530 |
+#endif
|
yann@1
|
1531 |
+ if (!ROUND_TOWARDS_ZERO && (high & GARDMASK) == GARDMSB)
|
yann@1
|
1532 |
+ {
|
yann@1
|
1533 |
+ if (high & (1 << NGARDS))
|
yann@1
|
1534 |
+ {
|
yann@1
|
1535 |
+ /* half way, so round to even */
|
yann@1
|
1536 |
+ high += GARDROUND + 1;
|
yann@1
|
1537 |
+ }
|
yann@1
|
1538 |
+ else if (low)
|
yann@1
|
1539 |
+ {
|
yann@1
|
1540 |
+ /* but we really weren't half way */
|
yann@1
|
1541 |
+ high += GARDROUND + 1;
|
yann@1
|
1542 |
+ }
|
yann@1
|
1543 |
+ }
|
yann@1
|
1544 |
+ tmp->fraction.ll = high;
|
yann@1
|
1545 |
+ tmp->class = CLASS_NUMBER;
|
yann@1
|
1546 |
+ return tmp;
|
yann@1
|
1547 |
+}
|
yann@1
|
1548 |
+
|
yann@1
|
1549 |
+FLO_type
|
yann@1
|
1550 |
+multiply (FLO_type arg_a, FLO_type arg_b)
|
yann@1
|
1551 |
+{
|
yann@1
|
1552 |
+ fp_number_type a;
|
yann@1
|
1553 |
+ fp_number_type b;
|
yann@1
|
1554 |
+ fp_number_type tmp;
|
yann@1
|
1555 |
+ fp_number_type *res;
|
yann@1
|
1556 |
+ FLO_union_type au, bu;
|
yann@1
|
1557 |
+
|
yann@1
|
1558 |
+ au.value = arg_a;
|
yann@1
|
1559 |
+ bu.value = arg_b;
|
yann@1
|
1560 |
+
|
yann@1
|
1561 |
+ unpack_d (&au, &a);
|
yann@1
|
1562 |
+ unpack_d (&bu, &b);
|
yann@1
|
1563 |
+
|
yann@1
|
1564 |
+ res = _fpmul_parts (&a, &b, &tmp);
|
yann@1
|
1565 |
+
|
yann@1
|
1566 |
+ return pack_d (res);
|
yann@1
|
1567 |
+}
|
yann@1
|
1568 |
+#endif /* L_mul_sf || L_mul_df */
|
yann@1
|
1569 |
+
|
yann@1
|
1570 |
+#if defined(L_div_sf) || defined(L_div_df) || defined(L_div_tf)
|
yann@1
|
1571 |
+static inline __attribute__ ((__always_inline__)) fp_number_type *
|
yann@1
|
1572 |
+_fpdiv_parts (fp_number_type * a,
|
yann@1
|
1573 |
+ fp_number_type * b)
|
yann@1
|
1574 |
+{
|
yann@1
|
1575 |
+ fractype bit;
|
yann@1
|
1576 |
+ fractype numerator;
|
yann@1
|
1577 |
+ fractype denominator;
|
yann@1
|
1578 |
+ fractype quotient;
|
yann@1
|
1579 |
+
|
yann@1
|
1580 |
+ if (isnan (a))
|
yann@1
|
1581 |
+ {
|
yann@1
|
1582 |
+ return a;
|
yann@1
|
1583 |
+ }
|
yann@1
|
1584 |
+ if (isnan (b))
|
yann@1
|
1585 |
+ {
|
yann@1
|
1586 |
+ return b;
|
yann@1
|
1587 |
+ }
|
yann@1
|
1588 |
+
|
yann@1
|
1589 |
+ a->sign = a->sign ^ b->sign;
|
yann@1
|
1590 |
+
|
yann@1
|
1591 |
+ if (isinf (a) || iszero (a))
|
yann@1
|
1592 |
+ {
|
yann@1
|
1593 |
+ if (a->class == b->class)
|
yann@1
|
1594 |
+ return nan ();
|
yann@1
|
1595 |
+ return a;
|
yann@1
|
1596 |
+ }
|
yann@1
|
1597 |
+
|
yann@1
|
1598 |
+ if (isinf (b))
|
yann@1
|
1599 |
+ {
|
yann@1
|
1600 |
+ a->fraction.ll = 0;
|
yann@1
|
1601 |
+ a->normal_exp = 0;
|
yann@1
|
1602 |
+ return a;
|
yann@1
|
1603 |
+ }
|
yann@1
|
1604 |
+ if (iszero (b))
|
yann@1
|
1605 |
+ {
|
yann@1
|
1606 |
+ a->class = CLASS_INFINITY;
|
yann@1
|
1607 |
+ return a;
|
yann@1
|
1608 |
+ }
|
yann@1
|
1609 |
+
|
yann@1
|
1610 |
+ /* Calculate the mantissa by multiplying both 64bit numbers to get a
|
yann@1
|
1611 |
+ 128 bit number */
|
yann@1
|
1612 |
+ {
|
yann@1
|
1613 |
+ /* quotient =
|
yann@1
|
1614 |
+ ( numerator / denominator) * 2^(numerator exponent - denominator exponent)
|
yann@1
|
1615 |
+ */
|
yann@1
|
1616 |
+
|
yann@1
|
1617 |
+ a->normal_exp = a->normal_exp - b->normal_exp;
|
yann@1
|
1618 |
+ numerator = a->fraction.ll;
|
yann@1
|
1619 |
+ denominator = b->fraction.ll;
|
yann@1
|
1620 |
+
|
yann@1
|
1621 |
+ if (numerator < denominator)
|
yann@1
|
1622 |
+ {
|
yann@1
|
1623 |
+ /* Fraction will be less than 1.0 */
|
yann@1
|
1624 |
+ numerator *= 2;
|
yann@1
|
1625 |
+ a->normal_exp--;
|
yann@1
|
1626 |
+ }
|
yann@1
|
1627 |
+ bit = IMPLICIT_1;
|
yann@1
|
1628 |
+ quotient = 0;
|
yann@1
|
1629 |
+ /* ??? Does divide one bit at a time. Optimize. */
|
yann@1
|
1630 |
+ while (bit)
|
yann@1
|
1631 |
+ {
|
yann@1
|
1632 |
+ if (numerator >= denominator)
|
yann@1
|
1633 |
+ {
|
yann@1
|
1634 |
+ quotient |= bit;
|
yann@1
|
1635 |
+ numerator -= denominator;
|
yann@1
|
1636 |
+ }
|
yann@1
|
1637 |
+ bit >>= 1;
|
yann@1
|
1638 |
+ numerator *= 2;
|
yann@1
|
1639 |
+ }
|
yann@1
|
1640 |
+
|
yann@1
|
1641 |
+ if (!ROUND_TOWARDS_ZERO && (quotient & GARDMASK) == GARDMSB)
|
yann@1
|
1642 |
+ {
|
yann@1
|
1643 |
+ if (quotient & (1 << NGARDS))
|
yann@1
|
1644 |
+ {
|
yann@1
|
1645 |
+ /* half way, so round to even */
|
yann@1
|
1646 |
+ quotient += GARDROUND + 1;
|
yann@1
|
1647 |
+ }
|
yann@1
|
1648 |
+ else if (numerator)
|
yann@1
|
1649 |
+ {
|
yann@1
|
1650 |
+ /* but we really weren't half way, more bits exist */
|
yann@1
|
1651 |
+ quotient += GARDROUND + 1;
|
yann@1
|
1652 |
+ }
|
yann@1
|
1653 |
+ }
|
yann@1
|
1654 |
+
|
yann@1
|
1655 |
+ a->fraction.ll = quotient;
|
yann@1
|
1656 |
+ return (a);
|
yann@1
|
1657 |
+ }
|
yann@1
|
1658 |
+}
|
yann@1
|
1659 |
+
|
yann@1
|
1660 |
+FLO_type
|
yann@1
|
1661 |
+divide (FLO_type arg_a, FLO_type arg_b)
|
yann@1
|
1662 |
+{
|
yann@1
|
1663 |
+ fp_number_type a;
|
yann@1
|
1664 |
+ fp_number_type b;
|
yann@1
|
1665 |
+ fp_number_type *res;
|
yann@1
|
1666 |
+ FLO_union_type au, bu;
|
yann@1
|
1667 |
+
|
yann@1
|
1668 |
+ au.value = arg_a;
|
yann@1
|
1669 |
+ bu.value = arg_b;
|
yann@1
|
1670 |
+
|
yann@1
|
1671 |
+ unpack_d (&au, &a);
|
yann@1
|
1672 |
+ unpack_d (&bu, &b);
|
yann@1
|
1673 |
+
|
yann@1
|
1674 |
+ res = _fpdiv_parts (&a, &b);
|
yann@1
|
1675 |
+
|
yann@1
|
1676 |
+ return pack_d (res);
|
yann@1
|
1677 |
+}
|
yann@1
|
1678 |
+#endif /* L_div_sf || L_div_df */
|
yann@1
|
1679 |
+
|
yann@1
|
1680 |
+#if defined(L_fpcmp_parts_sf) || defined(L_fpcmp_parts_df) \
|
yann@1
|
1681 |
+ || defined(L_fpcmp_parts_tf)
|
yann@1
|
1682 |
+/* according to the demo, fpcmp returns a comparison with 0... thus
|
yann@1
|
1683 |
+ a<b -> -1
|
yann@1
|
1684 |
+ a==b -> 0
|
yann@1
|
1685 |
+ a>b -> +1
|
yann@1
|
1686 |
+ */
|
yann@1
|
1687 |
+
|
yann@1
|
1688 |
+int
|
yann@1
|
1689 |
+__fpcmp_parts (fp_number_type * a, fp_number_type * b)
|
yann@1
|
1690 |
+{
|
yann@1
|
1691 |
+#if 0
|
yann@1
|
1692 |
+ /* either nan -> unordered. Must be checked outside of this routine. */
|
yann@1
|
1693 |
+ if (isnan (a) && isnan (b))
|
yann@1
|
1694 |
+ {
|
yann@1
|
1695 |
+ return 1; /* still unordered! */
|
yann@1
|
1696 |
+ }
|
yann@1
|
1697 |
+#endif
|
yann@1
|
1698 |
+
|
yann@1
|
1699 |
+ if (isnan (a) || isnan (b))
|
yann@1
|
1700 |
+ {
|
yann@1
|
1701 |
+ return 1; /* how to indicate unordered compare? */
|
yann@1
|
1702 |
+ }
|
yann@1
|
1703 |
+ if (isinf (a) && isinf (b))
|
yann@1
|
1704 |
+ {
|
yann@1
|
1705 |
+ /* +inf > -inf, but +inf != +inf */
|
yann@1
|
1706 |
+ /* b \a| +inf(0)| -inf(1)
|
yann@1
|
1707 |
+ ______\+--------+--------
|
yann@1
|
1708 |
+ +inf(0)| a==b(0)| a<b(-1)
|
yann@1
|
1709 |
+ -------+--------+--------
|
yann@1
|
1710 |
+ -inf(1)| a>b(1) | a==b(0)
|
yann@1
|
1711 |
+ -------+--------+--------
|
yann@1
|
1712 |
+ So since unordered must be nonzero, just line up the columns...
|
yann@1
|
1713 |
+ */
|
yann@1
|
1714 |
+ return b->sign - a->sign;
|
yann@1
|
1715 |
+ }
|
yann@1
|
1716 |
+ /* but not both... */
|
yann@1
|
1717 |
+ if (isinf (a))
|
yann@1
|
1718 |
+ {
|
yann@1
|
1719 |
+ return a->sign ? -1 : 1;
|
yann@1
|
1720 |
+ }
|
yann@1
|
1721 |
+ if (isinf (b))
|
yann@1
|
1722 |
+ {
|
yann@1
|
1723 |
+ return b->sign ? 1 : -1;
|
yann@1
|
1724 |
+ }
|
yann@1
|
1725 |
+ if (iszero (a) && iszero (b))
|
yann@1
|
1726 |
+ {
|
yann@1
|
1727 |
+ return 0;
|
yann@1
|
1728 |
+ }
|
yann@1
|
1729 |
+ if (iszero (a))
|
yann@1
|
1730 |
+ {
|
yann@1
|
1731 |
+ return b->sign ? 1 : -1;
|
yann@1
|
1732 |
+ }
|
yann@1
|
1733 |
+ if (iszero (b))
|
yann@1
|
1734 |
+ {
|
yann@1
|
1735 |
+ return a->sign ? -1 : 1;
|
yann@1
|
1736 |
+ }
|
yann@1
|
1737 |
+ /* now both are "normal". */
|
yann@1
|
1738 |
+ if (a->sign != b->sign)
|
yann@1
|
1739 |
+ {
|
yann@1
|
1740 |
+ /* opposite signs */
|
yann@1
|
1741 |
+ return a->sign ? -1 : 1;
|
yann@1
|
1742 |
+ }
|
yann@1
|
1743 |
+ /* same sign; exponents? */
|
yann@1
|
1744 |
+ if (a->normal_exp > b->normal_exp)
|
yann@1
|
1745 |
+ {
|
yann@1
|
1746 |
+ return a->sign ? -1 : 1;
|
yann@1
|
1747 |
+ }
|
yann@1
|
1748 |
+ if (a->normal_exp < b->normal_exp)
|
yann@1
|
1749 |
+ {
|
yann@1
|
1750 |
+ return a->sign ? 1 : -1;
|
yann@1
|
1751 |
+ }
|
yann@1
|
1752 |
+ /* same exponents; check size. */
|
yann@1
|
1753 |
+ if (a->fraction.ll > b->fraction.ll)
|
yann@1
|
1754 |
+ {
|
yann@1
|
1755 |
+ return a->sign ? -1 : 1;
|
yann@1
|
1756 |
+ }
|
yann@1
|
1757 |
+ if (a->fraction.ll < b->fraction.ll)
|
yann@1
|
1758 |
+ {
|
yann@1
|
1759 |
+ return a->sign ? 1 : -1;
|
yann@1
|
1760 |
+ }
|
yann@1
|
1761 |
+ /* after all that, they're equal. */
|
yann@1
|
1762 |
+ return 0;
|
yann@1
|
1763 |
+}
|
yann@1
|
1764 |
+#endif
|
yann@1
|
1765 |
+
|
yann@1
|
1766 |
+#if defined(L_compare_sf) || defined(L_compare_df) || defined(L_compoare_tf)
|
yann@1
|
1767 |
+CMPtype
|
yann@1
|
1768 |
+compare (FLO_type arg_a, FLO_type arg_b)
|
yann@1
|
1769 |
+{
|
yann@1
|
1770 |
+ fp_number_type a;
|
yann@1
|
1771 |
+ fp_number_type b;
|
yann@1
|
1772 |
+ FLO_union_type au, bu;
|
yann@1
|
1773 |
+
|
yann@1
|
1774 |
+ au.value = arg_a;
|
yann@1
|
1775 |
+ bu.value = arg_b;
|
yann@1
|
1776 |
+
|
yann@1
|
1777 |
+ unpack_d (&au, &a);
|
yann@1
|
1778 |
+ unpack_d (&bu, &b);
|
yann@1
|
1779 |
+
|
yann@1
|
1780 |
+ return __fpcmp_parts (&a, &b);
|
yann@1
|
1781 |
+}
|
yann@1
|
1782 |
+#endif /* L_compare_sf || L_compare_df */
|
yann@1
|
1783 |
+
|
yann@1
|
1784 |
+#ifndef US_SOFTWARE_GOFAST
|
yann@1
|
1785 |
+
|
yann@1
|
1786 |
+/* These should be optimized for their specific tasks someday. */
|
yann@1
|
1787 |
+
|
yann@1
|
1788 |
+#if defined(L_eq_sf) || defined(L_eq_df) || defined(L_eq_tf)
|
yann@1
|
1789 |
+CMPtype
|
yann@1
|
1790 |
+_eq_f2 (FLO_type arg_a, FLO_type arg_b)
|
yann@1
|
1791 |
+{
|
yann@1
|
1792 |
+ fp_number_type a;
|
yann@1
|
1793 |
+ fp_number_type b;
|
yann@1
|
1794 |
+ FLO_union_type au, bu;
|
yann@1
|
1795 |
+
|
yann@1
|
1796 |
+ au.value = arg_a;
|
yann@1
|
1797 |
+ bu.value = arg_b;
|
yann@1
|
1798 |
+
|
yann@1
|
1799 |
+ unpack_d (&au, &a);
|
yann@1
|
1800 |
+ unpack_d (&bu, &b);
|
yann@1
|
1801 |
+
|
yann@1
|
1802 |
+ if (isnan (&a) || isnan (&b))
|
yann@1
|
1803 |
+ return 1; /* false, truth == 0 */
|
yann@1
|
1804 |
+
|
yann@1
|
1805 |
+ return __fpcmp_parts (&a, &b) ;
|
yann@1
|
1806 |
+}
|
yann@1
|
1807 |
+#endif /* L_eq_sf || L_eq_df */
|
yann@1
|
1808 |
+
|
yann@1
|
1809 |
+#if defined(L_ne_sf) || defined(L_ne_df) || defined(L_ne_tf)
|
yann@1
|
1810 |
+CMPtype
|
yann@1
|
1811 |
+_ne_f2 (FLO_type arg_a, FLO_type arg_b)
|
yann@1
|
1812 |
+{
|
yann@1
|
1813 |
+ fp_number_type a;
|
yann@1
|
1814 |
+ fp_number_type b;
|
yann@1
|
1815 |
+ FLO_union_type au, bu;
|
yann@1
|
1816 |
+
|
yann@1
|
1817 |
+ au.value = arg_a;
|
yann@1
|
1818 |
+ bu.value = arg_b;
|
yann@1
|
1819 |
+
|
yann@1
|
1820 |
+ unpack_d (&au, &a);
|
yann@1
|
1821 |
+ unpack_d (&bu, &b);
|
yann@1
|
1822 |
+
|
yann@1
|
1823 |
+ if (isnan (&a) || isnan (&b))
|
yann@1
|
1824 |
+ return 1; /* true, truth != 0 */
|
yann@1
|
1825 |
+
|
yann@1
|
1826 |
+ return __fpcmp_parts (&a, &b) ;
|
yann@1
|
1827 |
+}
|
yann@1
|
1828 |
+#endif /* L_ne_sf || L_ne_df */
|
yann@1
|
1829 |
+
|
yann@1
|
1830 |
+#if defined(L_gt_sf) || defined(L_gt_df) || defined(L_gt_tf)
|
yann@1
|
1831 |
+CMPtype
|
yann@1
|
1832 |
+_gt_f2 (FLO_type arg_a, FLO_type arg_b)
|
yann@1
|
1833 |
+{
|
yann@1
|
1834 |
+ fp_number_type a;
|
yann@1
|
1835 |
+ fp_number_type b;
|
yann@1
|
1836 |
+ FLO_union_type au, bu;
|
yann@1
|
1837 |
+
|
yann@1
|
1838 |
+ au.value = arg_a;
|
yann@1
|
1839 |
+ bu.value = arg_b;
|
yann@1
|
1840 |
+
|
yann@1
|
1841 |
+ unpack_d (&au, &a);
|
yann@1
|
1842 |
+ unpack_d (&bu, &b);
|
yann@1
|
1843 |
+
|
yann@1
|
1844 |
+ if (isnan (&a) || isnan (&b))
|
yann@1
|
1845 |
+ return -1; /* false, truth > 0 */
|
yann@1
|
1846 |
+
|
yann@1
|
1847 |
+ return __fpcmp_parts (&a, &b);
|
yann@1
|
1848 |
+}
|
yann@1
|
1849 |
+#endif /* L_gt_sf || L_gt_df */
|
yann@1
|
1850 |
+
|
yann@1
|
1851 |
+#if defined(L_ge_sf) || defined(L_ge_df) || defined(L_ge_tf)
|
yann@1
|
1852 |
+CMPtype
|
yann@1
|
1853 |
+_ge_f2 (FLO_type arg_a, FLO_type arg_b)
|
yann@1
|
1854 |
+{
|
yann@1
|
1855 |
+ fp_number_type a;
|
yann@1
|
1856 |
+ fp_number_type b;
|
yann@1
|
1857 |
+ FLO_union_type au, bu;
|
yann@1
|
1858 |
+
|
yann@1
|
1859 |
+ au.value = arg_a;
|
yann@1
|
1860 |
+ bu.value = arg_b;
|
yann@1
|
1861 |
+
|
yann@1
|
1862 |
+ unpack_d (&au, &a);
|
yann@1
|
1863 |
+ unpack_d (&bu, &b);
|
yann@1
|
1864 |
+
|
yann@1
|
1865 |
+ if (isnan (&a) || isnan (&b))
|
yann@1
|
1866 |
+ return -1; /* false, truth >= 0 */
|
yann@1
|
1867 |
+ return __fpcmp_parts (&a, &b) ;
|
yann@1
|
1868 |
+}
|
yann@1
|
1869 |
+#endif /* L_ge_sf || L_ge_df */
|
yann@1
|
1870 |
+
|
yann@1
|
1871 |
+#if defined(L_lt_sf) || defined(L_lt_df) || defined(L_lt_tf)
|
yann@1
|
1872 |
+CMPtype
|
yann@1
|
1873 |
+_lt_f2 (FLO_type arg_a, FLO_type arg_b)
|
yann@1
|
1874 |
+{
|
yann@1
|
1875 |
+ fp_number_type a;
|
yann@1
|
1876 |
+ fp_number_type b;
|
yann@1
|
1877 |
+ FLO_union_type au, bu;
|
yann@1
|
1878 |
+
|
yann@1
|
1879 |
+ au.value = arg_a;
|
yann@1
|
1880 |
+ bu.value = arg_b;
|
yann@1
|
1881 |
+
|
yann@1
|
1882 |
+ unpack_d (&au, &a);
|
yann@1
|
1883 |
+ unpack_d (&bu, &b);
|
yann@1
|
1884 |
+
|
yann@1
|
1885 |
+ if (isnan (&a) || isnan (&b))
|
yann@1
|
1886 |
+ return 1; /* false, truth < 0 */
|
yann@1
|
1887 |
+
|
yann@1
|
1888 |
+ return __fpcmp_parts (&a, &b);
|
yann@1
|
1889 |
+}
|
yann@1
|
1890 |
+#endif /* L_lt_sf || L_lt_df */
|
yann@1
|
1891 |
+
|
yann@1
|
1892 |
+#if defined(L_le_sf) || defined(L_le_df) || defined(L_le_tf)
|
yann@1
|
1893 |
+CMPtype
|
yann@1
|
1894 |
+_le_f2 (FLO_type arg_a, FLO_type arg_b)
|
yann@1
|
1895 |
+{
|
yann@1
|
1896 |
+ fp_number_type a;
|
yann@1
|
1897 |
+ fp_number_type b;
|
yann@1
|
1898 |
+ FLO_union_type au, bu;
|
yann@1
|
1899 |
+
|
yann@1
|
1900 |
+ au.value = arg_a;
|
yann@1
|
1901 |
+ bu.value = arg_b;
|
yann@1
|
1902 |
+
|
yann@1
|
1903 |
+ unpack_d (&au, &a);
|
yann@1
|
1904 |
+ unpack_d (&bu, &b);
|
yann@1
|
1905 |
+
|
yann@1
|
1906 |
+ if (isnan (&a) || isnan (&b))
|
yann@1
|
1907 |
+ return 1; /* false, truth <= 0 */
|
yann@1
|
1908 |
+
|
yann@1
|
1909 |
+ return __fpcmp_parts (&a, &b) ;
|
yann@1
|
1910 |
+}
|
yann@1
|
1911 |
+#endif /* L_le_sf || L_le_df */
|
yann@1
|
1912 |
+
|
yann@1
|
1913 |
+#endif /* ! US_SOFTWARE_GOFAST */
|
yann@1
|
1914 |
+
|
yann@1
|
1915 |
+#if defined(L_unord_sf) || defined(L_unord_df) || defined(L_unord_tf)
|
yann@1
|
1916 |
+CMPtype
|
yann@1
|
1917 |
+_unord_f2 (FLO_type arg_a, FLO_type arg_b)
|
yann@1
|
1918 |
+{
|
yann@1
|
1919 |
+ fp_number_type a;
|
yann@1
|
1920 |
+ fp_number_type b;
|
yann@1
|
1921 |
+ FLO_union_type au, bu;
|
yann@1
|
1922 |
+
|
yann@1
|
1923 |
+ au.value = arg_a;
|
yann@1
|
1924 |
+ bu.value = arg_b;
|
yann@1
|
1925 |
+
|
yann@1
|
1926 |
+ unpack_d (&au, &a);
|
yann@1
|
1927 |
+ unpack_d (&bu, &b);
|
yann@1
|
1928 |
+
|
yann@1
|
1929 |
+ return (isnan (&a) || isnan (&b));
|
yann@1
|
1930 |
+}
|
yann@1
|
1931 |
+#endif /* L_unord_sf || L_unord_df */
|
yann@1
|
1932 |
+
|
yann@1
|
1933 |
+#if defined(L_si_to_sf) || defined(L_si_to_df) || defined(L_si_to_tf)
|
yann@1
|
1934 |
+FLO_type
|
yann@1
|
1935 |
+si_to_float (SItype arg_a)
|
yann@1
|
1936 |
+{
|
yann@1
|
1937 |
+ fp_number_type in;
|
yann@1
|
1938 |
+
|
yann@1
|
1939 |
+ in.class = CLASS_NUMBER;
|
yann@1
|
1940 |
+ in.sign = arg_a < 0;
|
yann@1
|
1941 |
+ if (!arg_a)
|
yann@1
|
1942 |
+ {
|
yann@1
|
1943 |
+ in.class = CLASS_ZERO;
|
yann@1
|
1944 |
+ }
|
yann@1
|
1945 |
+ else
|
yann@1
|
1946 |
+ {
|
yann@1
|
1947 |
+ in.normal_exp = FRACBITS + NGARDS;
|
yann@1
|
1948 |
+ if (in.sign)
|
yann@1
|
1949 |
+ {
|
yann@1
|
1950 |
+ /* Special case for minint, since there is no +ve integer
|
yann@1
|
1951 |
+ representation for it */
|
yann@1
|
1952 |
+ if (arg_a == (- MAX_SI_INT - 1))
|
yann@1
|
1953 |
+ {
|
yann@1
|
1954 |
+ return (FLO_type)(- MAX_SI_INT - 1);
|
yann@1
|
1955 |
+ }
|
yann@1
|
1956 |
+ in.fraction.ll = (-arg_a);
|
yann@1
|
1957 |
+ }
|
yann@1
|
1958 |
+ else
|
yann@1
|
1959 |
+ in.fraction.ll = arg_a;
|
yann@1
|
1960 |
+
|
yann@1
|
1961 |
+ while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
|
yann@1
|
1962 |
+ {
|
yann@1
|
1963 |
+ in.fraction.ll <<= 1;
|
yann@1
|
1964 |
+ in.normal_exp -= 1;
|
yann@1
|
1965 |
+ }
|
yann@1
|
1966 |
+ }
|
yann@1
|
1967 |
+ return pack_d (&in);
|
yann@1
|
1968 |
+}
|
yann@1
|
1969 |
+#endif /* L_si_to_sf || L_si_to_df */
|
yann@1
|
1970 |
+
|
yann@1
|
1971 |
+#if defined(L_usi_to_sf) || defined(L_usi_to_df) || defined(L_usi_to_tf)
|
yann@1
|
1972 |
+FLO_type
|
yann@1
|
1973 |
+usi_to_float (USItype arg_a)
|
yann@1
|
1974 |
+{
|
yann@1
|
1975 |
+ fp_number_type in;
|
yann@1
|
1976 |
+
|
yann@1
|
1977 |
+ in.sign = 0;
|
yann@1
|
1978 |
+ if (!arg_a)
|
yann@1
|
1979 |
+ {
|
yann@1
|
1980 |
+ in.class = CLASS_ZERO;
|
yann@1
|
1981 |
+ }
|
yann@1
|
1982 |
+ else
|
yann@1
|
1983 |
+ {
|
yann@1
|
1984 |
+ in.class = CLASS_NUMBER;
|
yann@1
|
1985 |
+ in.normal_exp = FRACBITS + NGARDS;
|
yann@1
|
1986 |
+ in.fraction.ll = arg_a;
|
yann@1
|
1987 |
+
|
yann@1
|
1988 |
+ while (in.fraction.ll > ((fractype)1 << (FRACBITS + NGARDS)))
|
yann@1
|
1989 |
+ {
|
yann@1
|
1990 |
+ in.fraction.ll >>= 1;
|
yann@1
|
1991 |
+ in.normal_exp += 1;
|
yann@1
|
1992 |
+ }
|
yann@1
|
1993 |
+ while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
|
yann@1
|
1994 |
+ {
|
yann@1
|
1995 |
+ in.fraction.ll <<= 1;
|
yann@1
|
1996 |
+ in.normal_exp -= 1;
|
yann@1
|
1997 |
+ }
|
yann@1
|
1998 |
+ }
|
yann@1
|
1999 |
+ return pack_d (&in);
|
yann@1
|
2000 |
+}
|
yann@1
|
2001 |
+#endif
|
yann@1
|
2002 |
+
|
yann@1
|
2003 |
+#if defined(L_sf_to_si) || defined(L_df_to_si) || defined(L_tf_to_si)
|
yann@1
|
2004 |
+SItype
|
yann@1
|
2005 |
+float_to_si (FLO_type arg_a)
|
yann@1
|
2006 |
+{
|
yann@1
|
2007 |
+ fp_number_type a;
|
yann@1
|
2008 |
+ SItype tmp;
|
yann@1
|
2009 |
+ FLO_union_type au;
|
yann@1
|
2010 |
+
|
yann@1
|
2011 |
+ au.value = arg_a;
|
yann@1
|
2012 |
+ unpack_d (&au, &a);
|
yann@1
|
2013 |
+
|
yann@1
|
2014 |
+ if (iszero (&a))
|
yann@1
|
2015 |
+ return 0;
|
yann@1
|
2016 |
+ if (isnan (&a))
|
yann@1
|
2017 |
+ return 0;
|
yann@1
|
2018 |
+ /* get reasonable MAX_SI_INT... */
|
yann@1
|
2019 |
+ if (isinf (&a))
|
yann@1
|
2020 |
+ return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
|
yann@1
|
2021 |
+ /* it is a number, but a small one */
|
yann@1
|
2022 |
+ if (a.normal_exp < 0)
|
yann@1
|
2023 |
+ return 0;
|
yann@1
|
2024 |
+ if (a.normal_exp > BITS_PER_SI - 2)
|
yann@1
|
2025 |
+ return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
|
yann@1
|
2026 |
+ tmp = a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
|
yann@1
|
2027 |
+ return a.sign ? (-tmp) : (tmp);
|
yann@1
|
2028 |
+}
|
yann@1
|
2029 |
+#endif /* L_sf_to_si || L_df_to_si */
|
yann@1
|
2030 |
+
|
yann@1
|
2031 |
+#if defined(L_sf_to_usi) || defined(L_df_to_usi) || defined(L_tf_to_usi)
|
yann@1
|
2032 |
+#if defined US_SOFTWARE_GOFAST || defined(L_tf_to_usi)
|
yann@1
|
2033 |
+/* While libgcc2.c defines its own __fixunssfsi and __fixunsdfsi routines,
|
yann@1
|
2034 |
+ we also define them for GOFAST because the ones in libgcc2.c have the
|
yann@1
|
2035 |
+ wrong names and I'd rather define these here and keep GOFAST CYG-LOC's
|
yann@1
|
2036 |
+ out of libgcc2.c. We can't define these here if not GOFAST because then
|
yann@1
|
2037 |
+ there'd be duplicate copies. */
|
yann@1
|
2038 |
+
|
yann@1
|
2039 |
+USItype
|
yann@1
|
2040 |
+float_to_usi (FLO_type arg_a)
|
yann@1
|
2041 |
+{
|
yann@1
|
2042 |
+ fp_number_type a;
|
yann@1
|
2043 |
+ FLO_union_type au;
|
yann@1
|
2044 |
+
|
yann@1
|
2045 |
+ au.value = arg_a;
|
yann@1
|
2046 |
+ unpack_d (&au, &a);
|
yann@1
|
2047 |
+
|
yann@1
|
2048 |
+ if (iszero (&a))
|
yann@1
|
2049 |
+ return 0;
|
yann@1
|
2050 |
+ if (isnan (&a))
|
yann@1
|
2051 |
+ return 0;
|
yann@1
|
2052 |
+ /* it is a negative number */
|
yann@1
|
2053 |
+ if (a.sign)
|
yann@1
|
2054 |
+ return 0;
|
yann@1
|
2055 |
+ /* get reasonable MAX_USI_INT... */
|
yann@1
|
2056 |
+ if (isinf (&a))
|
yann@1
|
2057 |
+ return MAX_USI_INT;
|
yann@1
|
2058 |
+ /* it is a number, but a small one */
|
yann@1
|
2059 |
+ if (a.normal_exp < 0)
|
yann@1
|
2060 |
+ return 0;
|
yann@1
|
2061 |
+ if (a.normal_exp > BITS_PER_SI - 1)
|
yann@1
|
2062 |
+ return MAX_USI_INT;
|
yann@1
|
2063 |
+ else if (a.normal_exp > (FRACBITS + NGARDS))
|
yann@1
|
2064 |
+ return a.fraction.ll << (a.normal_exp - (FRACBITS + NGARDS));
|
yann@1
|
2065 |
+ else
|
yann@1
|
2066 |
+ return a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
|
yann@1
|
2067 |
+}
|
yann@1
|
2068 |
+#endif /* US_SOFTWARE_GOFAST */
|
yann@1
|
2069 |
+#endif /* L_sf_to_usi || L_df_to_usi */
|
yann@1
|
2070 |
+
|
yann@1
|
2071 |
+#if defined(L_negate_sf) || defined(L_negate_df) || defined(L_negate_tf)
|
yann@1
|
2072 |
+FLO_type
|
yann@1
|
2073 |
+negate (FLO_type arg_a)
|
yann@1
|
2074 |
+{
|
yann@1
|
2075 |
+ fp_number_type a;
|
yann@1
|
2076 |
+ FLO_union_type au;
|
yann@1
|
2077 |
+
|
yann@1
|
2078 |
+ au.value = arg_a;
|
yann@1
|
2079 |
+ unpack_d (&au, &a);
|
yann@1
|
2080 |
+
|
yann@1
|
2081 |
+ flip_sign (&a);
|
yann@1
|
2082 |
+ return pack_d (&a);
|
yann@1
|
2083 |
+}
|
yann@1
|
2084 |
+#endif /* L_negate_sf || L_negate_df */
|
yann@1
|
2085 |
+
|
yann@1
|
2086 |
+#ifdef FLOAT
|
yann@1
|
2087 |
+
|
yann@1
|
2088 |
+#if defined(L_make_sf)
|
yann@1
|
2089 |
+SFtype
|
yann@1
|
2090 |
+__make_fp(fp_class_type class,
|
yann@1
|
2091 |
+ unsigned int sign,
|
yann@1
|
2092 |
+ int exp,
|
yann@1
|
2093 |
+ USItype frac)
|
yann@1
|
2094 |
+{
|
yann@1
|
2095 |
+ fp_number_type in;
|
yann@1
|
2096 |
+
|
yann@1
|
2097 |
+ in.class = class;
|
yann@1
|
2098 |
+ in.sign = sign;
|
yann@1
|
2099 |
+ in.normal_exp = exp;
|
yann@1
|
2100 |
+ in.fraction.ll = frac;
|
yann@1
|
2101 |
+ return pack_d (&in);
|
yann@1
|
2102 |
+}
|
yann@1
|
2103 |
+#endif /* L_make_sf */
|
yann@1
|
2104 |
+
|
yann@1
|
2105 |
+#ifndef FLOAT_ONLY
|
yann@1
|
2106 |
+
|
yann@1
|
2107 |
+/* This enables one to build an fp library that supports float but not double.
|
yann@1
|
2108 |
+ Otherwise, we would get an undefined reference to __make_dp.
|
yann@1
|
2109 |
+ This is needed for some 8-bit ports that can't handle well values that
|
yann@1
|
2110 |
+ are 8-bytes in size, so we just don't support double for them at all. */
|
yann@1
|
2111 |
+
|
yann@1
|
2112 |
+#if defined(L_sf_to_df)
|
yann@1
|
2113 |
+DFtype
|
yann@1
|
2114 |
+sf_to_df (SFtype arg_a)
|
yann@1
|
2115 |
+{
|
yann@1
|
2116 |
+ fp_number_type in;
|
yann@1
|
2117 |
+ FLO_union_type au;
|
yann@1
|
2118 |
+
|
yann@1
|
2119 |
+ au.value = arg_a;
|
yann@1
|
2120 |
+ unpack_d (&au, &in);
|
yann@1
|
2121 |
+
|
yann@1
|
2122 |
+ return __make_dp (in.class, in.sign, in.normal_exp,
|
yann@1
|
2123 |
+ ((UDItype) in.fraction.ll) << F_D_BITOFF);
|
yann@1
|
2124 |
+}
|
yann@1
|
2125 |
+#endif /* L_sf_to_df */
|
yann@1
|
2126 |
+
|
yann@1
|
2127 |
+#if defined(L_sf_to_tf) && defined(TMODES)
|
yann@1
|
2128 |
+TFtype
|
yann@1
|
2129 |
+sf_to_tf (SFtype arg_a)
|
yann@1
|
2130 |
+{
|
yann@1
|
2131 |
+ fp_number_type in;
|
yann@1
|
2132 |
+ FLO_union_type au;
|
yann@1
|
2133 |
+
|
yann@1
|
2134 |
+ au.value = arg_a;
|
yann@1
|
2135 |
+ unpack_d (&au, &in);
|
yann@1
|
2136 |
+
|
yann@1
|
2137 |
+ return __make_tp (in.class, in.sign, in.normal_exp,
|
yann@1
|
2138 |
+ ((UTItype) in.fraction.ll) << F_T_BITOFF);
|
yann@1
|
2139 |
+}
|
yann@1
|
2140 |
+#endif /* L_sf_to_df */
|
yann@1
|
2141 |
+
|
yann@1
|
2142 |
+#endif /* ! FLOAT_ONLY */
|
yann@1
|
2143 |
+#endif /* FLOAT */
|
yann@1
|
2144 |
+
|
yann@1
|
2145 |
+#ifndef FLOAT
|
yann@1
|
2146 |
+
|
yann@1
|
2147 |
+extern SFtype __make_fp (fp_class_type, unsigned int, int, USItype);
|
yann@1
|
2148 |
+
|
yann@1
|
2149 |
+#if defined(L_make_df)
|
yann@1
|
2150 |
+DFtype
|
yann@1
|
2151 |
+__make_dp (fp_class_type class, unsigned int sign, int exp, UDItype frac)
|
yann@1
|
2152 |
+{
|
yann@1
|
2153 |
+ fp_number_type in;
|
yann@1
|
2154 |
+
|
yann@1
|
2155 |
+ in.class = class;
|
yann@1
|
2156 |
+ in.sign = sign;
|
yann@1
|
2157 |
+ in.normal_exp = exp;
|
yann@1
|
2158 |
+ in.fraction.ll = frac;
|
yann@1
|
2159 |
+ return pack_d (&in);
|
yann@1
|
2160 |
+}
|
yann@1
|
2161 |
+#endif /* L_make_df */
|
yann@1
|
2162 |
+
|
yann@1
|
2163 |
+#if defined(L_df_to_sf)
|
yann@1
|
2164 |
+SFtype
|
yann@1
|
2165 |
+df_to_sf (DFtype arg_a)
|
yann@1
|
2166 |
+{
|
yann@1
|
2167 |
+ fp_number_type in;
|
yann@1
|
2168 |
+ USItype sffrac;
|
yann@1
|
2169 |
+ FLO_union_type au;
|
yann@1
|
2170 |
+
|
yann@1
|
2171 |
+ au.value = arg_a;
|
yann@1
|
2172 |
+ unpack_d (&au, &in);
|
yann@1
|
2173 |
+
|
yann@1
|
2174 |
+ sffrac = in.fraction.ll >> F_D_BITOFF;
|
yann@1
|
2175 |
+
|
yann@1
|
2176 |
+ /* We set the lowest guard bit in SFFRAC if we discarded any non
|
yann@1
|
2177 |
+ zero bits. */
|
yann@1
|
2178 |
+ if ((in.fraction.ll & (((USItype) 1 << F_D_BITOFF) - 1)) != 0)
|
yann@1
|
2179 |
+ sffrac |= 1;
|
yann@1
|
2180 |
+
|
yann@1
|
2181 |
+ return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
|
yann@1
|
2182 |
+}
|
yann@1
|
2183 |
+#endif /* L_df_to_sf */
|
yann@1
|
2184 |
+
|
yann@1
|
2185 |
+#if defined(L_df_to_tf) && defined(TMODES) \
|
yann@1
|
2186 |
+ && !defined(FLOAT) && !defined(TFLOAT)
|
yann@1
|
2187 |
+TFtype
|
yann@1
|
2188 |
+df_to_tf (DFtype arg_a)
|
yann@1
|
2189 |
+{
|
yann@1
|
2190 |
+ fp_number_type in;
|
yann@1
|
2191 |
+ FLO_union_type au;
|
yann@1
|
2192 |
+
|
yann@1
|
2193 |
+ au.value = arg_a;
|
yann@1
|
2194 |
+ unpack_d (&au, &in);
|
yann@1
|
2195 |
+
|
yann@1
|
2196 |
+ return __make_tp (in.class, in.sign, in.normal_exp,
|
yann@1
|
2197 |
+ ((UTItype) in.fraction.ll) << D_T_BITOFF);
|
yann@1
|
2198 |
+}
|
yann@1
|
2199 |
+#endif /* L_sf_to_df */
|
yann@1
|
2200 |
+
|
yann@1
|
2201 |
+#ifdef TFLOAT
|
yann@1
|
2202 |
+#if defined(L_make_tf)
|
yann@1
|
2203 |
+TFtype
|
yann@1
|
2204 |
+__make_tp(fp_class_type class,
|
yann@1
|
2205 |
+ unsigned int sign,
|
yann@1
|
2206 |
+ int exp,
|
yann@1
|
2207 |
+ UTItype frac)
|
yann@1
|
2208 |
+{
|
yann@1
|
2209 |
+ fp_number_type in;
|
yann@1
|
2210 |
+
|
yann@1
|
2211 |
+ in.class = class;
|
yann@1
|
2212 |
+ in.sign = sign;
|
yann@1
|
2213 |
+ in.normal_exp = exp;
|
yann@1
|
2214 |
+ in.fraction.ll = frac;
|
yann@1
|
2215 |
+ return pack_d (&in);
|
yann@1
|
2216 |
+}
|
yann@1
|
2217 |
+#endif /* L_make_tf */
|
yann@1
|
2218 |
+
|
yann@1
|
2219 |
+#if defined(L_tf_to_df)
|
yann@1
|
2220 |
+DFtype
|
yann@1
|
2221 |
+tf_to_df (TFtype arg_a)
|
yann@1
|
2222 |
+{
|
yann@1
|
2223 |
+ fp_number_type in;
|
yann@1
|
2224 |
+ UDItype sffrac;
|
yann@1
|
2225 |
+ FLO_union_type au;
|
yann@1
|
2226 |
+
|
yann@1
|
2227 |
+ au.value = arg_a;
|
yann@1
|
2228 |
+ unpack_d (&au, &in);
|
yann@1
|
2229 |
+
|
yann@1
|
2230 |
+ sffrac = in.fraction.ll >> D_T_BITOFF;
|
yann@1
|
2231 |
+
|
yann@1
|
2232 |
+ /* We set the lowest guard bit in SFFRAC if we discarded any non
|
yann@1
|
2233 |
+ zero bits. */
|
yann@1
|
2234 |
+ if ((in.fraction.ll & (((UTItype) 1 << D_T_BITOFF) - 1)) != 0)
|
yann@1
|
2235 |
+ sffrac |= 1;
|
yann@1
|
2236 |
+
|
yann@1
|
2237 |
+ return __make_dp (in.class, in.sign, in.normal_exp, sffrac);
|
yann@1
|
2238 |
+}
|
yann@1
|
2239 |
+#endif /* L_tf_to_df */
|
yann@1
|
2240 |
+
|
yann@1
|
2241 |
+#if defined(L_tf_to_sf)
|
yann@1
|
2242 |
+SFtype
|
yann@1
|
2243 |
+tf_to_sf (TFtype arg_a)
|
yann@1
|
2244 |
+{
|
yann@1
|
2245 |
+ fp_number_type in;
|
yann@1
|
2246 |
+ USItype sffrac;
|
yann@1
|
2247 |
+ FLO_union_type au;
|
yann@1
|
2248 |
+
|
yann@1
|
2249 |
+ au.value = arg_a;
|
yann@1
|
2250 |
+ unpack_d (&au, &in);
|
yann@1
|
2251 |
+
|
yann@1
|
2252 |
+ sffrac = in.fraction.ll >> F_T_BITOFF;
|
yann@1
|
2253 |
+
|
yann@1
|
2254 |
+ /* We set the lowest guard bit in SFFRAC if we discarded any non
|
yann@1
|
2255 |
+ zero bits. */
|
yann@1
|
2256 |
+ if ((in.fraction.ll & (((UTItype) 1 << F_T_BITOFF) - 1)) != 0)
|
yann@1
|
2257 |
+ sffrac |= 1;
|
yann@1
|
2258 |
+
|
yann@1
|
2259 |
+ return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
|
yann@1
|
2260 |
+}
|
yann@1
|
2261 |
+#endif /* L_tf_to_sf */
|
yann@1
|
2262 |
+#endif /* TFLOAT */
|
yann@1
|
2263 |
+
|
yann@1
|
2264 |
+#endif /* ! FLOAT */
|
yann@1
|
2265 |
+#endif /* !EXTENDED_FLOAT_STUBS */
|
yann@1
|
2266 |
--- gcc-3.4.3/gcc/config/nios2/nios2-fp-bit.c
|
yann@1
|
2267 |
+++ gcc-3.4.3-nios2/gcc/config/nios2/nios2-fp-bit.c
|
yann@1
|
2268 |
@@ -0,0 +1,1652 @@
|
yann@1
|
2269 |
+#define FLOAT
|
yann@1
|
2270 |
+/* This is a software floating point library which can be used
|
yann@1
|
2271 |
+ for targets without hardware floating point.
|
yann@1
|
2272 |
+ Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004
|
yann@1
|
2273 |
+ Free Software Foundation, Inc.
|
yann@1
|
2274 |
+
|
yann@1
|
2275 |
+This file is free software; you can redistribute it and/or modify it
|
yann@1
|
2276 |
+under the terms of the GNU General Public License as published by the
|
yann@1
|
2277 |
+Free Software Foundation; either version 2, or (at your option) any
|
yann@1
|
2278 |
+later version.
|
yann@1
|
2279 |
+
|
yann@1
|
2280 |
+In addition to the permissions in the GNU General Public License, the
|
yann@1
|
2281 |
+Free Software Foundation gives you unlimited permission to link the
|
yann@1
|
2282 |
+compiled version of this file with other programs, and to distribute
|
yann@1
|
2283 |
+those programs without any restriction coming from the use of this
|
yann@1
|
2284 |
+file. (The General Public License restrictions do apply in other
|
yann@1
|
2285 |
+respects; for example, they cover modification of the file, and
|
yann@1
|
2286 |
+distribution when not linked into another program.)
|
yann@1
|
2287 |
+
|
yann@1
|
2288 |
+This file is distributed in the hope that it will be useful, but
|
yann@1
|
2289 |
+WITHOUT ANY WARRANTY; without even the implied warranty of
|
yann@1
|
2290 |
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
yann@1
|
2291 |
+General Public License for more details.
|
yann@1
|
2292 |
+
|
yann@1
|
2293 |
+You should have received a copy of the GNU General Public License
|
yann@1
|
2294 |
+along with this program; see the file COPYING. If not, write to
|
yann@1
|
2295 |
+the Free Software Foundation, 59 Temple Place - Suite 330,
|
yann@1
|
2296 |
+Boston, MA 02111-1307, USA. */
|
yann@1
|
2297 |
+
|
yann@1
|
2298 |
+/* As a special exception, if you link this library with other files,
|
yann@1
|
2299 |
+ some of which are compiled with GCC, to produce an executable,
|
yann@1
|
2300 |
+ this library does not by itself cause the resulting executable
|
yann@1
|
2301 |
+ to be covered by the GNU General Public License.
|
yann@1
|
2302 |
+ This exception does not however invalidate any other reasons why
|
yann@1
|
2303 |
+ the executable file might be covered by the GNU General Public License. */
|
yann@1
|
2304 |
+
|
yann@1
|
2305 |
+/* This implements IEEE 754 format arithmetic, but does not provide a
|
yann@1
|
2306 |
+ mechanism for setting the rounding mode, or for generating or handling
|
yann@1
|
2307 |
+ exceptions.
|
yann@1
|
2308 |
+
|
yann@1
|
2309 |
+ The original code by Steve Chamberlain, hacked by Mark Eichin and Jim
|
yann@1
|
2310 |
+ Wilson, all of Cygnus Support. */
|
yann@1
|
2311 |
+
|
yann@1
|
2312 |
+/* The intended way to use this file is to make two copies, add `#define FLOAT'
|
yann@1
|
2313 |
+ to one copy, then compile both copies and add them to libgcc.a. */
|
yann@1
|
2314 |
+
|
yann@1
|
2315 |
+#include "tconfig.h"
|
yann@1
|
2316 |
+#include "coretypes.h"
|
yann@1
|
2317 |
+#include "tm.h"
|
yann@1
|
2318 |
+#include "config/fp-bit.h"
|
yann@1
|
2319 |
+
|
yann@1
|
2320 |
+/* The following macros can be defined to change the behavior of this file:
|
yann@1
|
2321 |
+ FLOAT: Implement a `float', aka SFmode, fp library. If this is not
|
yann@1
|
2322 |
+ defined, then this file implements a `double', aka DFmode, fp library.
|
yann@1
|
2323 |
+ FLOAT_ONLY: Used with FLOAT, to implement a `float' only library, i.e.
|
yann@1
|
2324 |
+ don't include float->double conversion which requires the double library.
|
yann@1
|
2325 |
+ This is useful only for machines which can't support doubles, e.g. some
|
yann@1
|
2326 |
+ 8-bit processors.
|
yann@1
|
2327 |
+ CMPtype: Specify the type that floating point compares should return.
|
yann@1
|
2328 |
+ This defaults to SItype, aka int.
|
yann@1
|
2329 |
+ US_SOFTWARE_GOFAST: This makes all entry points use the same names as the
|
yann@1
|
2330 |
+ US Software goFast library.
|
yann@1
|
2331 |
+ _DEBUG_BITFLOAT: This makes debugging the code a little easier, by adding
|
yann@1
|
2332 |
+ two integers to the FLO_union_type.
|
yann@1
|
2333 |
+ NO_DENORMALS: Disable handling of denormals.
|
yann@1
|
2334 |
+ NO_NANS: Disable nan and infinity handling
|
yann@1
|
2335 |
+ SMALL_MACHINE: Useful when operations on QIs and HIs are faster
|
yann@1
|
2336 |
+ than on an SI */
|
yann@1
|
2337 |
+
|
yann@1
|
2338 |
+/* We don't currently support extended floats (long doubles) on machines
|
yann@1
|
2339 |
+ without hardware to deal with them.
|
yann@1
|
2340 |
+
|
yann@1
|
2341 |
+ These stubs are just to keep the linker from complaining about unresolved
|
yann@1
|
2342 |
+ references which can be pulled in from libio & libstdc++, even if the
|
yann@1
|
2343 |
+ user isn't using long doubles. However, they may generate an unresolved
|
yann@1
|
2344 |
+ external to abort if abort is not used by the function, and the stubs
|
yann@1
|
2345 |
+ are referenced from within libc, since libgcc goes before and after the
|
yann@1
|
2346 |
+ system library. */
|
yann@1
|
2347 |
+
|
yann@1
|
2348 |
+#ifdef DECLARE_LIBRARY_RENAMES
|
yann@1
|
2349 |
+ DECLARE_LIBRARY_RENAMES
|
yann@1
|
2350 |
+#endif
|
yann@1
|
2351 |
+
|
yann@1
|
2352 |
+#ifdef EXTENDED_FLOAT_STUBS
|
yann@1
|
2353 |
+extern void abort (void);
|
yann@1
|
2354 |
+void __extendsfxf2 (void) { abort(); }
|
yann@1
|
2355 |
+void __extenddfxf2 (void) { abort(); }
|
yann@1
|
2356 |
+void __truncxfdf2 (void) { abort(); }
|
yann@1
|
2357 |
+void __truncxfsf2 (void) { abort(); }
|
yann@1
|
2358 |
+void __fixxfsi (void) { abort(); }
|
yann@1
|
2359 |
+void __floatsixf (void) { abort(); }
|
yann@1
|
2360 |
+void __addxf3 (void) { abort(); }
|
yann@1
|
2361 |
+void __subxf3 (void) { abort(); }
|
yann@1
|
2362 |
+void __mulxf3 (void) { abort(); }
|
yann@1
|
2363 |
+void __divxf3 (void) { abort(); }
|
yann@1
|
2364 |
+void __negxf2 (void) { abort(); }
|
yann@1
|
2365 |
+void __eqxf2 (void) { abort(); }
|
yann@1
|
2366 |
+void __nexf2 (void) { abort(); }
|
yann@1
|
2367 |
+void __gtxf2 (void) { abort(); }
|
yann@1
|
2368 |
+void __gexf2 (void) { abort(); }
|
yann@1
|
2369 |
+void __lexf2 (void) { abort(); }
|
yann@1
|
2370 |
+void __ltxf2 (void) { abort(); }
|
yann@1
|
2371 |
+
|
yann@1
|
2372 |
+void __extendsftf2 (void) { abort(); }
|
yann@1
|
2373 |
+void __extenddftf2 (void) { abort(); }
|
yann@1
|
2374 |
+void __trunctfdf2 (void) { abort(); }
|
yann@1
|
2375 |
+void __trunctfsf2 (void) { abort(); }
|
yann@1
|
2376 |
+void __fixtfsi (void) { abort(); }
|
yann@1
|
2377 |
+void __floatsitf (void) { abort(); }
|
yann@1
|
2378 |
+void __addtf3 (void) { abort(); }
|
yann@1
|
2379 |
+void __subtf3 (void) { abort(); }
|
yann@1
|
2380 |
+void __multf3 (void) { abort(); }
|
yann@1
|
2381 |
+void __divtf3 (void) { abort(); }
|
yann@1
|
2382 |
+void __negtf2 (void) { abort(); }
|
yann@1
|
2383 |
+void __eqtf2 (void) { abort(); }
|
yann@1
|
2384 |
+void __netf2 (void) { abort(); }
|
yann@1
|
2385 |
+void __gttf2 (void) { abort(); }
|
yann@1
|
2386 |
+void __getf2 (void) { abort(); }
|
yann@1
|
2387 |
+void __letf2 (void) { abort(); }
|
yann@1
|
2388 |
+void __lttf2 (void) { abort(); }
|
yann@1
|
2389 |
+#else /* !EXTENDED_FLOAT_STUBS, rest of file */
|
yann@1
|
2390 |
+
|
yann@1
|
2391 |
+/* IEEE "special" number predicates */
|
yann@1
|
2392 |
+
|
yann@1
|
2393 |
+#ifdef NO_NANS
|
yann@1
|
2394 |
+
|
yann@1
|
2395 |
+#define nan() 0
|
yann@1
|
2396 |
+#define isnan(x) 0
|
yann@1
|
2397 |
+#define isinf(x) 0
|
yann@1
|
2398 |
+#else
|
yann@1
|
2399 |
+
|
yann@1
|
2400 |
+#if defined L_thenan_sf
|
yann@1
|
2401 |
+const fp_number_type __thenan_sf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
|
yann@1
|
2402 |
+#elif defined L_thenan_df
|
yann@1
|
2403 |
+const fp_number_type __thenan_df = { CLASS_SNAN, 0, 0, {(fractype) 0} };
|
yann@1
|
2404 |
+#elif defined L_thenan_tf
|
yann@1
|
2405 |
+const fp_number_type __thenan_tf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
|
yann@1
|
2406 |
+#elif defined TFLOAT
|
yann@1
|
2407 |
+extern const fp_number_type __thenan_tf;
|
yann@1
|
2408 |
+#elif defined FLOAT
|
yann@1
|
2409 |
+extern const fp_number_type __thenan_sf;
|
yann@1
|
2410 |
+#else
|
yann@1
|
2411 |
+extern const fp_number_type __thenan_df;
|
yann@1
|
2412 |
+#endif
|
yann@1
|
2413 |
+
|
yann@1
|
2414 |
+INLINE
|
yann@1
|
2415 |
+static fp_number_type *
|
yann@1
|
2416 |
+nan (void)
|
yann@1
|
2417 |
+{
|
yann@1
|
2418 |
+ /* Discard the const qualifier... */
|
yann@1
|
2419 |
+#ifdef TFLOAT
|
yann@1
|
2420 |
+ return (fp_number_type *) (& __thenan_tf);
|
yann@1
|
2421 |
+#elif defined FLOAT
|
yann@1
|
2422 |
+ return (fp_number_type *) (& __thenan_sf);
|
yann@1
|
2423 |
+#else
|
yann@1
|
2424 |
+ return (fp_number_type *) (& __thenan_df);
|
yann@1
|
2425 |
+#endif
|
yann@1
|
2426 |
+}
|
yann@1
|
2427 |
+
|
yann@1
|
2428 |
+INLINE
|
yann@1
|
2429 |
+static int
|
yann@1
|
2430 |
+isnan ( fp_number_type * x)
|
yann@1
|
2431 |
+{
|
yann@1
|
2432 |
+ return x->class == CLASS_SNAN || x->class == CLASS_QNAN;
|
yann@1
|
2433 |
+}
|
yann@1
|
2434 |
+
|
yann@1
|
2435 |
+INLINE
|
yann@1
|
2436 |
+static int
|
yann@1
|
2437 |
+isinf ( fp_number_type * x)
|
yann@1
|
2438 |
+{
|
yann@1
|
2439 |
+ return x->class == CLASS_INFINITY;
|
yann@1
|
2440 |
+}
|
yann@1
|
2441 |
+
|
yann@1
|
2442 |
+#endif /* NO_NANS */
|
yann@1
|
2443 |
+
|
yann@1
|
2444 |
+INLINE
|
yann@1
|
2445 |
+static int
|
yann@1
|
2446 |
+iszero ( fp_number_type * x)
|
yann@1
|
2447 |
+{
|
yann@1
|
2448 |
+ return x->class == CLASS_ZERO;
|
yann@1
|
2449 |
+}
|
yann@1
|
2450 |
+
|
yann@1
|
2451 |
+INLINE
|
yann@1
|
2452 |
+static void
|
yann@1
|
2453 |
+flip_sign ( fp_number_type * x)
|
yann@1
|
2454 |
+{
|
yann@1
|
2455 |
+ x->sign = !x->sign;
|
yann@1
|
2456 |
+}
|
yann@1
|
2457 |
+
|
yann@1
|
2458 |
+extern FLO_type pack_d ( fp_number_type * );
|
yann@1
|
2459 |
+
|
yann@1
|
2460 |
+#if defined(L_pack_df) || defined(L_pack_sf) || defined(L_pack_tf)
|
yann@1
|
2461 |
+FLO_type
|
yann@1
|
2462 |
+pack_d ( fp_number_type * src)
|
yann@1
|
2463 |
+{
|
yann@1
|
2464 |
+ FLO_union_type dst;
|
yann@1
|
2465 |
+ fractype fraction = src->fraction.ll; /* wasn't unsigned before? */
|
yann@1
|
2466 |
+ int sign = src->sign;
|
yann@1
|
2467 |
+ int exp = 0;
|
yann@1
|
2468 |
+
|
yann@1
|
2469 |
+ if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && (isnan (src) || isinf (src)))
|
yann@1
|
2470 |
+ {
|
yann@1
|
2471 |
+ /* We can't represent these values accurately. By using the
|
yann@1
|
2472 |
+ largest possible magnitude, we guarantee that the conversion
|
yann@1
|
2473 |
+ of infinity is at least as big as any finite number. */
|
yann@1
|
2474 |
+ exp = EXPMAX;
|
yann@1
|
2475 |
+ fraction = ((fractype) 1 << FRACBITS) - 1;
|
yann@1
|
2476 |
+ }
|
yann@1
|
2477 |
+ else if (isnan (src))
|
yann@1
|
2478 |
+ {
|
yann@1
|
2479 |
+ exp = EXPMAX;
|
yann@1
|
2480 |
+ if (src->class == CLASS_QNAN || 1)
|
yann@1
|
2481 |
+ {
|
yann@1
|
2482 |
+#ifdef QUIET_NAN_NEGATED
|
yann@1
|
2483 |
+ fraction |= QUIET_NAN - 1;
|
yann@1
|
2484 |
+#else
|
yann@1
|
2485 |
+ fraction |= QUIET_NAN;
|
yann@1
|
2486 |
+#endif
|
yann@1
|
2487 |
+ }
|
yann@1
|
2488 |
+ }
|
yann@1
|
2489 |
+ else if (isinf (src))
|
yann@1
|
2490 |
+ {
|
yann@1
|
2491 |
+ exp = EXPMAX;
|
yann@1
|
2492 |
+ fraction = 0;
|
yann@1
|
2493 |
+ }
|
yann@1
|
2494 |
+ else if (iszero (src))
|
yann@1
|
2495 |
+ {
|
yann@1
|
2496 |
+ exp = 0;
|
yann@1
|
2497 |
+ fraction = 0;
|
yann@1
|
2498 |
+ }
|
yann@1
|
2499 |
+ else if (fraction == 0)
|
yann@1
|
2500 |
+ {
|
yann@1
|
2501 |
+ exp = 0;
|
yann@1
|
2502 |
+ }
|
yann@1
|
2503 |
+ else
|
yann@1
|
2504 |
+ {
|
yann@1
|
2505 |
+ if (src->normal_exp < NORMAL_EXPMIN)
|
yann@1
|
2506 |
+ {
|
yann@1
|
2507 |
+#ifdef NO_DENORMALS
|
yann@1
|
2508 |
+ /* Go straight to a zero representation if denormals are not
|
yann@1
|
2509 |
+ supported. The denormal handling would be harmless but
|
yann@1
|
2510 |
+ isn't unnecessary. */
|
yann@1
|
2511 |
+ exp = 0;
|
yann@1
|
2512 |
+ fraction = 0;
|
yann@1
|
2513 |
+#else /* NO_DENORMALS */
|
yann@1
|
2514 |
+ /* This number's exponent is too low to fit into the bits
|
yann@1
|
2515 |
+ available in the number, so we'll store 0 in the exponent and
|
yann@1
|
2516 |
+ shift the fraction to the right to make up for it. */
|
yann@1
|
2517 |
+
|
yann@1
|
2518 |
+ int shift = NORMAL_EXPMIN - src->normal_exp;
|
yann@1
|
2519 |
+
|
yann@1
|
2520 |
+ exp = 0;
|
yann@1
|
2521 |
+
|
yann@1
|
2522 |
+ if (shift > FRAC_NBITS - NGARDS)
|
yann@1
|
2523 |
+ {
|
yann@1
|
2524 |
+ /* No point shifting, since it's more that 64 out. */
|
yann@1
|
2525 |
+ fraction = 0;
|
yann@1
|
2526 |
+ }
|
yann@1
|
2527 |
+ else
|
yann@1
|
2528 |
+ {
|
yann@1
|
2529 |
+ int lowbit = (fraction & (((fractype)1 << shift) - 1)) ? 1 : 0;
|
yann@1
|
2530 |
+ fraction = (fraction >> shift) | lowbit;
|
yann@1
|
2531 |
+ }
|
yann@1
|
2532 |
+ if ((fraction & GARDMASK) == GARDMSB)
|
yann@1
|
2533 |
+ {
|
yann@1
|
2534 |
+ if ((fraction & (1 << NGARDS)))
|
yann@1
|
2535 |
+ fraction += GARDROUND + 1;
|
yann@1
|
2536 |
+ }
|
yann@1
|
2537 |
+ else
|
yann@1
|
2538 |
+ {
|
yann@1
|
2539 |
+ /* Add to the guards to round up. */
|
yann@1
|
2540 |
+ fraction += GARDROUND;
|
yann@1
|
2541 |
+ }
|
yann@1
|
2542 |
+ /* Perhaps the rounding means we now need to change the
|
yann@1
|
2543 |
+ exponent, because the fraction is no longer denormal. */
|
yann@1
|
2544 |
+ if (fraction >= IMPLICIT_1)
|
yann@1
|
2545 |
+ {
|
yann@1
|
2546 |
+ exp += 1;
|
yann@1
|
2547 |
+ }
|
yann@1
|
2548 |
+ fraction >>= NGARDS;
|
yann@1
|
2549 |
+#endif /* NO_DENORMALS */
|
yann@1
|
2550 |
+ }
|
yann@1
|
2551 |
+ else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS)
|
yann@1
|
2552 |
+ && src->normal_exp > EXPBIAS)
|
yann@1
|
2553 |
+ {
|
yann@1
|
2554 |
+ exp = EXPMAX;
|
yann@1
|
2555 |
+ fraction = 0;
|
yann@1
|
2556 |
+ }
|
yann@1
|
2557 |
+ else
|
yann@1
|
2558 |
+ {
|
yann@1
|
2559 |
+ exp = src->normal_exp + EXPBIAS;
|
yann@1
|
2560 |
+ if (!ROUND_TOWARDS_ZERO)
|
yann@1
|
2561 |
+ {
|
yann@1
|
2562 |
+ /* IF the gard bits are the all zero, but the first, then we're
|
yann@1
|
2563 |
+ half way between two numbers, choose the one which makes the
|
yann@1
|
2564 |
+ lsb of the answer 0. */
|
yann@1
|
2565 |
+ if ((fraction & GARDMASK) == GARDMSB)
|
yann@1
|
2566 |
+ {
|
yann@1
|
2567 |
+ if (fraction & (1 << NGARDS))
|
yann@1
|
2568 |
+ fraction += GARDROUND + 1;
|
yann@1
|
2569 |
+ }
|
yann@1
|
2570 |
+ else
|
yann@1
|
2571 |
+ {
|
yann@1
|
2572 |
+ /* Add a one to the guards to round up */
|
yann@1
|
2573 |
+ fraction += GARDROUND;
|
yann@1
|
2574 |
+ }
|
yann@1
|
2575 |
+ if (fraction >= IMPLICIT_2)
|
yann@1
|
2576 |
+ {
|
yann@1
|
2577 |
+ fraction >>= 1;
|
yann@1
|
2578 |
+ exp += 1;
|
yann@1
|
2579 |
+ }
|
yann@1
|
2580 |
+ }
|
yann@1
|
2581 |
+ fraction >>= NGARDS;
|
yann@1
|
2582 |
+
|
yann@1
|
2583 |
+ if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp > EXPMAX)
|
yann@1
|
2584 |
+ {
|
yann@1
|
2585 |
+ /* Saturate on overflow. */
|
yann@1
|
2586 |
+ exp = EXPMAX;
|
yann@1
|
2587 |
+ fraction = ((fractype) 1 << FRACBITS) - 1;
|
yann@1
|
2588 |
+ }
|
yann@1
|
2589 |
+ }
|
yann@1
|
2590 |
+ }
|
yann@1
|
2591 |
+
|
yann@1
|
2592 |
+ /* We previously used bitfields to store the number, but this doesn't
|
yann@1
|
2593 |
+ handle little/big endian systems conveniently, so use shifts and
|
yann@1
|
2594 |
+ masks */
|
yann@1
|
2595 |
+#ifdef FLOAT_BIT_ORDER_MISMATCH
|
yann@1
|
2596 |
+ dst.bits.fraction = fraction;
|
yann@1
|
2597 |
+ dst.bits.exp = exp;
|
yann@1
|
2598 |
+ dst.bits.sign = sign;
|
yann@1
|
2599 |
+#else
|
yann@1
|
2600 |
+# if defined TFLOAT && defined HALFFRACBITS
|
yann@1
|
2601 |
+ {
|
yann@1
|
2602 |
+ halffractype high, low, unity;
|
yann@1
|
2603 |
+ int lowsign, lowexp;
|
yann@1
|
2604 |
+
|
yann@1
|
2605 |
+ unity = (halffractype) 1 << HALFFRACBITS;
|
yann@1
|
2606 |
+
|
yann@1
|
2607 |
+ /* Set HIGH to the high double's significand, masking out the implicit 1.
|
yann@1
|
2608 |
+ Set LOW to the low double's full significand. */
|
yann@1
|
2609 |
+ high = (fraction >> (FRACBITS - HALFFRACBITS)) & (unity - 1);
|
yann@1
|
2610 |
+ low = fraction & (unity * 2 - 1);
|
yann@1
|
2611 |
+
|
yann@1
|
2612 |
+ /* Get the initial sign and exponent of the low double. */
|
yann@1
|
2613 |
+ lowexp = exp - HALFFRACBITS - 1;
|
yann@1
|
2614 |
+ lowsign = sign;
|
yann@1
|
2615 |
+
|
yann@1
|
2616 |
+ /* HIGH should be rounded like a normal double, making |LOW| <=
|
yann@1
|
2617 |
+ 0.5 ULP of HIGH. Assume round-to-nearest. */
|
yann@1
|
2618 |
+ if (exp < EXPMAX)
|
yann@1
|
2619 |
+ if (low > unity || (low == unity && (high & 1) == 1))
|
yann@1
|
2620 |
+ {
|
yann@1
|
2621 |
+ /* Round HIGH up and adjust LOW to match. */
|
yann@1
|
2622 |
+ high++;
|
yann@1
|
2623 |
+ if (high == unity)
|
yann@1
|
2624 |
+ {
|
yann@1
|
2625 |
+ /* May make it infinite, but that's OK. */
|
yann@1
|
2626 |
+ high = 0;
|
yann@1
|
2627 |
+ exp++;
|
yann@1
|
2628 |
+ }
|
yann@1
|
2629 |
+ low = unity * 2 - low;
|
yann@1
|
2630 |
+ lowsign ^= 1;
|
yann@1
|
2631 |
+ }
|
yann@1
|
2632 |
+
|
yann@1
|
2633 |
+ high |= (halffractype) exp << HALFFRACBITS;
|
yann@1
|
2634 |
+ high |= (halffractype) sign << (HALFFRACBITS + EXPBITS);
|
yann@1
|
2635 |
+
|
yann@1
|
2636 |
+ if (exp == EXPMAX || exp == 0 || low == 0)
|
yann@1
|
2637 |
+ low = 0;
|
yann@1
|
2638 |
+ else
|
yann@1
|
2639 |
+ {
|
yann@1
|
2640 |
+ while (lowexp > 0 && low < unity)
|
yann@1
|
2641 |
+ {
|
yann@1
|
2642 |
+ low <<= 1;
|
yann@1
|
2643 |
+ lowexp--;
|
yann@1
|
2644 |
+ }
|
yann@1
|
2645 |
+
|
yann@1
|
2646 |
+ if (lowexp <= 0)
|
yann@1
|
2647 |
+ {
|
yann@1
|
2648 |
+ halffractype roundmsb, round;
|
yann@1
|
2649 |
+ int shift;
|
yann@1
|
2650 |
+
|
yann@1
|
2651 |
+ shift = 1 - lowexp;
|
yann@1
|
2652 |
+ roundmsb = (1 << (shift - 1));
|
yann@1
|
2653 |
+ round = low & ((roundmsb << 1) - 1);
|
yann@1
|
2654 |
+
|
yann@1
|
2655 |
+ low >>= shift;
|
yann@1
|
2656 |
+ lowexp = 0;
|
yann@1
|
2657 |
+
|
yann@1
|
2658 |
+ if (round > roundmsb || (round == roundmsb && (low & 1) == 1))
|
yann@1
|
2659 |
+ {
|
yann@1
|
2660 |
+ low++;
|
yann@1
|
2661 |
+ if (low == unity)
|
yann@1
|
2662 |
+ /* LOW rounds up to the smallest normal number. */
|
yann@1
|
2663 |
+ lowexp++;
|
yann@1
|
2664 |
+ }
|
yann@1
|
2665 |
+ }
|
yann@1
|
2666 |
+
|
yann@1
|
2667 |
+ low &= unity - 1;
|
yann@1
|
2668 |
+ low |= (halffractype) lowexp << HALFFRACBITS;
|
yann@1
|
2669 |
+ low |= (halffractype) lowsign << (HALFFRACBITS + EXPBITS);
|
yann@1
|
2670 |
+ }
|
yann@1
|
2671 |
+ dst.value_raw = ((fractype) high << HALFSHIFT) | low;
|
yann@1
|
2672 |
+ }
|
yann@1
|
2673 |
+# else
|
yann@1
|
2674 |
+ dst.value_raw = fraction & ((((fractype)1) << FRACBITS) - (fractype)1);
|
yann@1
|
2675 |
+ dst.value_raw |= ((fractype) (exp & ((1 << EXPBITS) - 1))) << FRACBITS;
|
yann@1
|
2676 |
+ dst.value_raw |= ((fractype) (sign & 1)) << (FRACBITS | EXPBITS);
|
yann@1
|
2677 |
+# endif
|
yann@1
|
2678 |
+#endif
|
yann@1
|
2679 |
+
|
yann@1
|
2680 |
+#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
|
yann@1
|
2681 |
+#ifdef TFLOAT
|
yann@1
|
2682 |
+ {
|
yann@1
|
2683 |
+ qrtrfractype tmp1 = dst.words[0];
|
yann@1
|
2684 |
+ qrtrfractype tmp2 = dst.words[1];
|
yann@1
|
2685 |
+ dst.words[0] = dst.words[3];
|
yann@1
|
2686 |
+ dst.words[1] = dst.words[2];
|
yann@1
|
2687 |
+ dst.words[2] = tmp2;
|
yann@1
|
2688 |
+ dst.words[3] = tmp1;
|
yann@1
|
2689 |
+ }
|
yann@1
|
2690 |
+#else
|
yann@1
|
2691 |
+ {
|
yann@1
|
2692 |
+ halffractype tmp = dst.words[0];
|
yann@1
|
2693 |
+ dst.words[0] = dst.words[1];
|
yann@1
|
2694 |
+ dst.words[1] = tmp;
|
yann@1
|
2695 |
+ }
|
yann@1
|
2696 |
+#endif
|
yann@1
|
2697 |
+#endif
|
yann@1
|
2698 |
+
|
yann@1
|
2699 |
+ return dst.value;
|
yann@1
|
2700 |
+}
|
yann@1
|
2701 |
+#endif
|
yann@1
|
2702 |
+
|
yann@1
|
2703 |
+#if defined(L_unpack_df) || defined(L_unpack_sf) || defined(L_unpack_tf)
|
yann@1
|
2704 |
+void
|
yann@1
|
2705 |
+unpack_d (FLO_union_type * src, fp_number_type * dst)
|
yann@1
|
2706 |
+{
|
yann@1
|
2707 |
+ /* We previously used bitfields to store the number, but this doesn't
|
yann@1
|
2708 |
+ handle little/big endian systems conveniently, so use shifts and
|
yann@1
|
2709 |
+ masks */
|
yann@1
|
2710 |
+ fractype fraction;
|
yann@1
|
2711 |
+ int exp;
|
yann@1
|
2712 |
+ int sign;
|
yann@1
|
2713 |
+
|
yann@1
|
2714 |
+#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
|
yann@1
|
2715 |
+ FLO_union_type swapped;
|
yann@1
|
2716 |
+
|
yann@1
|
2717 |
+#ifdef TFLOAT
|
yann@1
|
2718 |
+ swapped.words[0] = src->words[3];
|
yann@1
|
2719 |
+ swapped.words[1] = src->words[2];
|
yann@1
|
2720 |
+ swapped.words[2] = src->words[1];
|
yann@1
|
2721 |
+ swapped.words[3] = src->words[0];
|
yann@1
|
2722 |
+#else
|
yann@1
|
2723 |
+ swapped.words[0] = src->words[1];
|
yann@1
|
2724 |
+ swapped.words[1] = src->words[0];
|
yann@1
|
2725 |
+#endif
|
yann@1
|
2726 |
+ src = &swapped;
|
yann@1
|
2727 |
+#endif
|
yann@1
|
2728 |
+
|
yann@1
|
2729 |
+#ifdef FLOAT_BIT_ORDER_MISMATCH
|
yann@1
|
2730 |
+ fraction = src->bits.fraction;
|
yann@1
|
2731 |
+ exp = src->bits.exp;
|
yann@1
|
2732 |
+ sign = src->bits.sign;
|
yann@1
|
2733 |
+#else
|
yann@1
|
2734 |
+# if defined TFLOAT && defined HALFFRACBITS
|
yann@1
|
2735 |
+ {
|
yann@1
|
2736 |
+ halffractype high, low;
|
yann@1
|
2737 |
+
|
yann@1
|
2738 |
+ high = src->value_raw >> HALFSHIFT;
|
yann@1
|
2739 |
+ low = src->value_raw & (((fractype)1 << HALFSHIFT) - 1);
|
yann@1
|
2740 |
+
|
yann@1
|
2741 |
+ fraction = high & ((((fractype)1) << HALFFRACBITS) - 1);
|
yann@1
|
2742 |
+ fraction <<= FRACBITS - HALFFRACBITS;
|
yann@1
|
2743 |
+ exp = ((int)(high >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
|
yann@1
|
2744 |
+ sign = ((int)(high >> (((HALFFRACBITS + EXPBITS))))) & 1;
|
yann@1
|
2745 |
+
|
yann@1
|
2746 |
+ if (exp != EXPMAX && exp != 0 && low != 0)
|
yann@1
|
2747 |
+ {
|
yann@1
|
2748 |
+ int lowexp = ((int)(low >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
|
yann@1
|
2749 |
+ int lowsign = ((int)(low >> (((HALFFRACBITS + EXPBITS))))) & 1;
|
yann@1
|
2750 |
+ int shift;
|
yann@1
|
2751 |
+ fractype xlow;
|
yann@1
|
2752 |
+
|
yann@1
|
2753 |
+ xlow = low & ((((fractype)1) << HALFFRACBITS) - 1);
|
yann@1
|
2754 |
+ if (lowexp)
|
yann@1
|
2755 |
+ xlow |= (((halffractype)1) << HALFFRACBITS);
|
yann@1
|
2756 |
+ else
|
yann@1
|
2757 |
+ lowexp = 1;
|
yann@1
|
2758 |
+ shift = (FRACBITS - HALFFRACBITS) - (exp - lowexp);
|
yann@1
|
2759 |
+ if (shift > 0)
|
yann@1
|
2760 |
+ xlow <<= shift;
|
yann@1
|
2761 |
+ else if (shift < 0)
|
yann@1
|
2762 |
+ xlow >>= -shift;
|
yann@1
|
2763 |
+ if (sign == lowsign)
|
yann@1
|
2764 |
+ fraction += xlow;
|
yann@1
|
2765 |
+ else if (fraction >= xlow)
|
yann@1
|
2766 |
+ fraction -= xlow;
|
yann@1
|
2767 |
+ else
|
yann@1
|
2768 |
+ {
|
yann@1
|
2769 |
+ /* The high part is a power of two but the full number is lower.
|
yann@1
|
2770 |
+ This code will leave the implicit 1 in FRACTION, but we'd
|
yann@1
|
2771 |
+ have added that below anyway. */
|
yann@1
|
2772 |
+ fraction = (((fractype) 1 << FRACBITS) - xlow) << 1;
|
yann@1
|
2773 |
+ exp--;
|
yann@1
|
2774 |
+ }
|
yann@1
|
2775 |
+ }
|
yann@1
|
2776 |
+ }
|
yann@1
|
2777 |
+# else
|
yann@1
|
2778 |
+ fraction = src->value_raw & ((((fractype)1) << FRACBITS) - 1);
|
yann@1
|
2779 |
+ exp = ((int)(src->value_raw >> FRACBITS)) & ((1 << EXPBITS) - 1);
|
yann@1
|
2780 |
+ sign = ((int)(src->value_raw >> (FRACBITS + EXPBITS))) & 1;
|
yann@1
|
2781 |
+# endif
|
yann@1
|
2782 |
+#endif
|
yann@1
|
2783 |
+
|
yann@1
|
2784 |
+ dst->sign = sign;
|
yann@1
|
2785 |
+ if (exp == 0)
|
yann@1
|
2786 |
+ {
|
yann@1
|
2787 |
+ /* Hmm. Looks like 0 */
|
yann@1
|
2788 |
+ if (fraction == 0
|
yann@1
|
2789 |
+#ifdef NO_DENORMALS
|
yann@1
|
2790 |
+ || 1
|
yann@1
|
2791 |
+#endif
|
yann@1
|
2792 |
+ )
|
yann@1
|
2793 |
+ {
|
yann@1
|
2794 |
+ /* tastes like zero */
|
yann@1
|
2795 |
+ dst->class = CLASS_ZERO;
|
yann@1
|
2796 |
+ }
|
yann@1
|
2797 |
+ else
|
yann@1
|
2798 |
+ {
|
yann@1
|
2799 |
+ /* Zero exponent with nonzero fraction - it's denormalized,
|
yann@1
|
2800 |
+ so there isn't a leading implicit one - we'll shift it so
|
yann@1
|
2801 |
+ it gets one. */
|
yann@1
|
2802 |
+ dst->normal_exp = exp - EXPBIAS + 1;
|
yann@1
|
2803 |
+ fraction <<= NGARDS;
|
yann@1
|
2804 |
+
|
yann@1
|
2805 |
+ dst->class = CLASS_NUMBER;
|
yann@1
|
2806 |
+#if 1
|
yann@1
|
2807 |
+ while (fraction < IMPLICIT_1)
|
yann@1
|
2808 |
+ {
|
yann@1
|
2809 |
+ fraction <<= 1;
|
yann@1
|
2810 |
+ dst->normal_exp--;
|
yann@1
|
2811 |
+ }
|
yann@1
|
2812 |
+#endif
|
yann@1
|
2813 |
+ dst->fraction.ll = fraction;
|
yann@1
|
2814 |
+ }
|
yann@1
|
2815 |
+ }
|
yann@1
|
2816 |
+ else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp == EXPMAX)
|
yann@1
|
2817 |
+ {
|
yann@1
|
2818 |
+ /* Huge exponent*/
|
yann@1
|
2819 |
+ if (fraction == 0)
|
yann@1
|
2820 |
+ {
|
yann@1
|
2821 |
+ /* Attached to a zero fraction - means infinity */
|
yann@1
|
2822 |
+ dst->class = CLASS_INFINITY;
|
yann@1
|
2823 |
+ }
|
yann@1
|
2824 |
+ else
|
yann@1
|
2825 |
+ {
|
yann@1
|
2826 |
+ /* Nonzero fraction, means nan */
|
yann@1
|
2827 |
+#ifdef QUIET_NAN_NEGATED
|
yann@1
|
2828 |
+ if ((fraction & QUIET_NAN) == 0)
|
yann@1
|
2829 |
+#else
|
yann@1
|
2830 |
+ if (fraction & QUIET_NAN)
|
yann@1
|
2831 |
+#endif
|
yann@1
|
2832 |
+ {
|
yann@1
|
2833 |
+ dst->class = CLASS_QNAN;
|
yann@1
|
2834 |
+ }
|
yann@1
|
2835 |
+ else
|
yann@1
|
2836 |
+ {
|
yann@1
|
2837 |
+ dst->class = CLASS_SNAN;
|
yann@1
|
2838 |
+ }
|
yann@1
|
2839 |
+ /* Keep the fraction part as the nan number */
|
yann@1
|
2840 |
+ dst->fraction.ll = fraction;
|
yann@1
|
2841 |
+ }
|
yann@1
|
2842 |
+ }
|
yann@1
|
2843 |
+ else
|
yann@1
|
2844 |
+ {
|
yann@1
|
2845 |
+ /* Nothing strange about this number */
|
yann@1
|
2846 |
+ dst->normal_exp = exp - EXPBIAS;
|
yann@1
|
2847 |
+ dst->class = CLASS_NUMBER;
|
yann@1
|
2848 |
+ dst->fraction.ll = (fraction << NGARDS) | IMPLICIT_1;
|
yann@1
|
2849 |
+ }
|
yann@1
|
2850 |
+}
|
yann@1
|
2851 |
+#endif /* L_unpack_df || L_unpack_sf */
|
yann@1
|
2852 |
+
|
yann@1
|
2853 |
+#if defined(L_addsub_sf) || defined(L_addsub_df) || defined(L_addsub_tf)
|
yann@1
|
2854 |
+static fp_number_type *
|
yann@1
|
2855 |
+_fpadd_parts (fp_number_type * a,
|
yann@1
|
2856 |
+ fp_number_type * b,
|
yann@1
|
2857 |
+ fp_number_type * tmp)
|
yann@1
|
2858 |
+{
|
yann@1
|
2859 |
+ intfrac tfraction;
|
yann@1
|
2860 |
+
|
yann@1
|
2861 |
+ /* Put commonly used fields in local variables. */
|
yann@1
|
2862 |
+ int a_normal_exp;
|
yann@1
|
2863 |
+ int b_normal_exp;
|
yann@1
|
2864 |
+ fractype a_fraction;
|
yann@1
|
2865 |
+ fractype b_fraction;
|
yann@1
|
2866 |
+
|
yann@1
|
2867 |
+ if (isnan (a))
|
yann@1
|
2868 |
+ {
|
yann@1
|
2869 |
+ return a;
|
yann@1
|
2870 |
+ }
|
yann@1
|
2871 |
+ if (isnan (b))
|
yann@1
|
2872 |
+ {
|
yann@1
|
2873 |
+ return b;
|
yann@1
|
2874 |
+ }
|
yann@1
|
2875 |
+ if (isinf (a))
|
yann@1
|
2876 |
+ {
|
yann@1
|
2877 |
+ /* Adding infinities with opposite signs yields a NaN. */
|
yann@1
|
2878 |
+ if (isinf (b) && a->sign != b->sign)
|
yann@1
|
2879 |
+ return nan ();
|
yann@1
|
2880 |
+ return a;
|
yann@1
|
2881 |
+ }
|
yann@1
|
2882 |
+ if (isinf (b))
|
yann@1
|
2883 |
+ {
|
yann@1
|
2884 |
+ return b;
|
yann@1
|
2885 |
+ }
|
yann@1
|
2886 |
+ if (iszero (b))
|
yann@1
|
2887 |
+ {
|
yann@1
|
2888 |
+ if (iszero (a))
|
yann@1
|
2889 |
+ {
|
yann@1
|
2890 |
+ *tmp = *a;
|
yann@1
|
2891 |
+ tmp->sign = a->sign & b->sign;
|
yann@1
|
2892 |
+ return tmp;
|
yann@1
|
2893 |
+ }
|
yann@1
|
2894 |
+ return a;
|
yann@1
|
2895 |
+ }
|
yann@1
|
2896 |
+ if (iszero (a))
|
yann@1
|
2897 |
+ {
|
yann@1
|
2898 |
+ return b;
|
yann@1
|
2899 |
+ }
|
yann@1
|
2900 |
+
|
yann@1
|
2901 |
+ /* Got two numbers. shift the smaller and increment the exponent till
|
yann@1
|
2902 |
+ they're the same */
|
yann@1
|
2903 |
+ {
|
yann@1
|
2904 |
+ int diff;
|
yann@1
|
2905 |
+
|
yann@1
|
2906 |
+ a_normal_exp = a->normal_exp;
|
yann@1
|
2907 |
+ b_normal_exp = b->normal_exp;
|
yann@1
|
2908 |
+ a_fraction = a->fraction.ll;
|
yann@1
|
2909 |
+ b_fraction = b->fraction.ll;
|
yann@1
|
2910 |
+
|
yann@1
|
2911 |
+ diff = a_normal_exp - b_normal_exp;
|
yann@1
|
2912 |
+
|
yann@1
|
2913 |
+ if (diff < 0)
|
yann@1
|
2914 |
+ diff = -diff;
|
yann@1
|
2915 |
+ if (diff < FRAC_NBITS)
|
yann@1
|
2916 |
+ {
|
yann@1
|
2917 |
+ /* ??? This does shifts one bit at a time. Optimize. */
|
yann@1
|
2918 |
+ while (a_normal_exp > b_normal_exp)
|
yann@1
|
2919 |
+ {
|
yann@1
|
2920 |
+ b_normal_exp++;
|
yann@1
|
2921 |
+ LSHIFT (b_fraction);
|
yann@1
|
2922 |
+ }
|
yann@1
|
2923 |
+ while (b_normal_exp > a_normal_exp)
|
yann@1
|
2924 |
+ {
|
yann@1
|
2925 |
+ a_normal_exp++;
|
yann@1
|
2926 |
+ LSHIFT (a_fraction);
|
yann@1
|
2927 |
+ }
|
yann@1
|
2928 |
+ }
|
yann@1
|
2929 |
+ else
|
yann@1
|
2930 |
+ {
|
yann@1
|
2931 |
+ /* Somethings's up.. choose the biggest */
|
yann@1
|
2932 |
+ if (a_normal_exp > b_normal_exp)
|
yann@1
|
2933 |
+ {
|
yann@1
|
2934 |
+ b_normal_exp = a_normal_exp;
|
yann@1
|
2935 |
+ b_fraction = 0;
|
yann@1
|
2936 |
+ }
|
yann@1
|
2937 |
+ else
|
yann@1
|
2938 |
+ {
|
yann@1
|
2939 |
+ a_normal_exp = b_normal_exp;
|
yann@1
|
2940 |
+ a_fraction = 0;
|
yann@1
|
2941 |
+ }
|
yann@1
|
2942 |
+ }
|
yann@1
|
2943 |
+ }
|
yann@1
|
2944 |
+
|
yann@1
|
2945 |
+ if (a->sign != b->sign)
|
yann@1
|
2946 |
+ {
|
yann@1
|
2947 |
+ if (a->sign)
|
yann@1
|
2948 |
+ {
|
yann@1
|
2949 |
+ tfraction = -a_fraction + b_fraction;
|
yann@1
|
2950 |
+ }
|
yann@1
|
2951 |
+ else
|
yann@1
|
2952 |
+ {
|
yann@1
|
2953 |
+ tfraction = a_fraction - b_fraction;
|
yann@1
|
2954 |
+ }
|
yann@1
|
2955 |
+ if (tfraction >= 0)
|
yann@1
|
2956 |
+ {
|
yann@1
|
2957 |
+ tmp->sign = 0;
|
yann@1
|
2958 |
+ tmp->normal_exp = a_normal_exp;
|
yann@1
|
2959 |
+ tmp->fraction.ll = tfraction;
|
yann@1
|
2960 |
+ }
|
yann@1
|
2961 |
+ else
|
yann@1
|
2962 |
+ {
|
yann@1
|
2963 |
+ tmp->sign = 1;
|
yann@1
|
2964 |
+ tmp->normal_exp = a_normal_exp;
|
yann@1
|
2965 |
+ tmp->fraction.ll = -tfraction;
|
yann@1
|
2966 |
+ }
|
yann@1
|
2967 |
+ /* and renormalize it */
|
yann@1
|
2968 |
+
|
yann@1
|
2969 |
+ while (tmp->fraction.ll < IMPLICIT_1 && tmp->fraction.ll)
|
yann@1
|
2970 |
+ {
|
yann@1
|
2971 |
+ tmp->fraction.ll <<= 1;
|
yann@1
|
2972 |
+ tmp->normal_exp--;
|
yann@1
|
2973 |
+ }
|
yann@1
|
2974 |
+ }
|
yann@1
|
2975 |
+ else
|
yann@1
|
2976 |
+ {
|
yann@1
|
2977 |
+ tmp->sign = a->sign;
|
yann@1
|
2978 |
+ tmp->normal_exp = a_normal_exp;
|
yann@1
|
2979 |
+ tmp->fraction.ll = a_fraction + b_fraction;
|
yann@1
|
2980 |
+ }
|
yann@1
|
2981 |
+ tmp->class = CLASS_NUMBER;
|
yann@1
|
2982 |
+ /* Now the fraction is added, we have to shift down to renormalize the
|
yann@1
|
2983 |
+ number */
|
yann@1
|
2984 |
+
|
yann@1
|
2985 |
+ if (tmp->fraction.ll >= IMPLICIT_2)
|
yann@1
|
2986 |
+ {
|
yann@1
|
2987 |
+ LSHIFT (tmp->fraction.ll);
|
yann@1
|
2988 |
+ tmp->normal_exp++;
|
yann@1
|
2989 |
+ }
|
yann@1
|
2990 |
+ return tmp;
|
yann@1
|
2991 |
+
|
yann@1
|
2992 |
+}
|
yann@1
|
2993 |
+
|
yann@1
|
2994 |
+FLO_type
|
yann@1
|
2995 |
+add (FLO_type arg_a, FLO_type arg_b)
|
yann@1
|
2996 |
+{
|
yann@1
|
2997 |
+ fp_number_type a;
|
yann@1
|
2998 |
+ fp_number_type b;
|
yann@1
|
2999 |
+ fp_number_type tmp;
|
yann@1
|
3000 |
+ fp_number_type *res;
|
yann@1
|
3001 |
+ FLO_union_type au, bu;
|
yann@1
|
3002 |
+
|
yann@1
|
3003 |
+ au.value = arg_a;
|
yann@1
|
3004 |
+ bu.value = arg_b;
|
yann@1
|
3005 |
+
|
yann@1
|
3006 |
+ unpack_d (&au, &a);
|
yann@1
|
3007 |
+ unpack_d (&bu, &b);
|
yann@1
|
3008 |
+
|
yann@1
|
3009 |
+ res = _fpadd_parts (&a, &b, &tmp);
|
yann@1
|
3010 |
+
|
yann@1
|
3011 |
+ return pack_d (res);
|
yann@1
|
3012 |
+}
|
yann@1
|
3013 |
+
|
yann@1
|
3014 |
+FLO_type
|
yann@1
|
3015 |
+sub (FLO_type arg_a, FLO_type arg_b)
|
yann@1
|
3016 |
+{
|
yann@1
|
3017 |
+ fp_number_type a;
|
yann@1
|
3018 |
+ fp_number_type b;
|
yann@1
|
3019 |
+ fp_number_type tmp;
|
yann@1
|
3020 |
+ fp_number_type *res;
|
yann@1
|
3021 |
+ FLO_union_type au, bu;
|
yann@1
|
3022 |
+
|
yann@1
|
3023 |
+ au.value = arg_a;
|
yann@1
|
3024 |
+ bu.value = arg_b;
|
yann@1
|
3025 |
+
|
yann@1
|
3026 |
+ unpack_d (&au, &a);
|
yann@1
|
3027 |
+ unpack_d (&bu, &b);
|
yann@1
|
3028 |
+
|
yann@1
|
3029 |
+ b.sign ^= 1;
|
yann@1
|
3030 |
+
|
yann@1
|
3031 |
+ res = _fpadd_parts (&a, &b, &tmp);
|
yann@1
|
3032 |
+
|
yann@1
|
3033 |
+ return pack_d (res);
|
yann@1
|
3034 |
+}
|
yann@1
|
3035 |
+#endif /* L_addsub_sf || L_addsub_df */
|
yann@1
|
3036 |
+
|
yann@1
|
3037 |
+#if defined(L_mul_sf) || defined(L_mul_df) || defined(L_mul_tf)
|
yann@1
|
3038 |
+static inline __attribute__ ((__always_inline__)) fp_number_type *
|
yann@1
|
3039 |
+_fpmul_parts ( fp_number_type * a,
|
yann@1
|
3040 |
+ fp_number_type * b,
|
yann@1
|
3041 |
+ fp_number_type * tmp)
|
yann@1
|
3042 |
+{
|
yann@1
|
3043 |
+ fractype low = 0;
|
yann@1
|
3044 |
+ fractype high = 0;
|
yann@1
|
3045 |
+
|
yann@1
|
3046 |
+ if (isnan (a))
|
yann@1
|
3047 |
+ {
|
yann@1
|
3048 |
+ a->sign = a->sign != b->sign;
|
yann@1
|
3049 |
+ return a;
|
yann@1
|
3050 |
+ }
|
yann@1
|
3051 |
+ if (isnan (b))
|
yann@1
|
3052 |
+ {
|
yann@1
|
3053 |
+ b->sign = a->sign != b->sign;
|
yann@1
|
3054 |
+ return b;
|
yann@1
|
3055 |
+ }
|
yann@1
|
3056 |
+ if (isinf (a))
|
yann@1
|
3057 |
+ {
|
yann@1
|
3058 |
+ if (iszero (b))
|
yann@1
|
3059 |
+ return nan ();
|
yann@1
|
3060 |
+ a->sign = a->sign != b->sign;
|
yann@1
|
3061 |
+ return a;
|
yann@1
|
3062 |
+ }
|
yann@1
|
3063 |
+ if (isinf (b))
|
yann@1
|
3064 |
+ {
|
yann@1
|
3065 |
+ if (iszero (a))
|
yann@1
|
3066 |
+ {
|
yann@1
|
3067 |
+ return nan ();
|
yann@1
|
3068 |
+ }
|
yann@1
|
3069 |
+ b->sign = a->sign != b->sign;
|
yann@1
|
3070 |
+ return b;
|
yann@1
|
3071 |
+ }
|
yann@1
|
3072 |
+ if (iszero (a))
|
yann@1
|
3073 |
+ {
|
yann@1
|
3074 |
+ a->sign = a->sign != b->sign;
|
yann@1
|
3075 |
+ return a;
|
yann@1
|
3076 |
+ }
|
yann@1
|
3077 |
+ if (iszero (b))
|
yann@1
|
3078 |
+ {
|
yann@1
|
3079 |
+ b->sign = a->sign != b->sign;
|
yann@1
|
3080 |
+ return b;
|
yann@1
|
3081 |
+ }
|
yann@1
|
3082 |
+
|
yann@1
|
3083 |
+ /* Calculate the mantissa by multiplying both numbers to get a
|
yann@1
|
3084 |
+ twice-as-wide number. */
|
yann@1
|
3085 |
+ {
|
yann@1
|
3086 |
+#if defined(NO_DI_MODE) || defined(TFLOAT)
|
yann@1
|
3087 |
+ {
|
yann@1
|
3088 |
+ fractype x = a->fraction.ll;
|
yann@1
|
3089 |
+ fractype ylow = b->fraction.ll;
|
yann@1
|
3090 |
+ fractype yhigh = 0;
|
yann@1
|
3091 |
+ int bit;
|
yann@1
|
3092 |
+
|
yann@1
|
3093 |
+ /* ??? This does multiplies one bit at a time. Optimize. */
|
yann@1
|
3094 |
+ for (bit = 0; bit < FRAC_NBITS; bit++)
|
yann@1
|
3095 |
+ {
|
yann@1
|
3096 |
+ int carry;
|
yann@1
|
3097 |
+
|
yann@1
|
3098 |
+ if (x & 1)
|
yann@1
|
3099 |
+ {
|
yann@1
|
3100 |
+ carry = (low += ylow) < ylow;
|
yann@1
|
3101 |
+ high += yhigh + carry;
|
yann@1
|
3102 |
+ }
|
yann@1
|
3103 |
+ yhigh <<= 1;
|
yann@1
|
3104 |
+ if (ylow & FRACHIGH)
|
yann@1
|
3105 |
+ {
|
yann@1
|
3106 |
+ yhigh |= 1;
|
yann@1
|
3107 |
+ }
|
yann@1
|
3108 |
+ ylow <<= 1;
|
yann@1
|
3109 |
+ x >>= 1;
|
yann@1
|
3110 |
+ }
|
yann@1
|
3111 |
+ }
|
yann@1
|
3112 |
+#elif defined(FLOAT)
|
yann@1
|
3113 |
+ /* Multiplying two USIs to get a UDI, we're safe. */
|
yann@1
|
3114 |
+ {
|
yann@1
|
3115 |
+ UDItype answer = (UDItype)a->fraction.ll * (UDItype)b->fraction.ll;
|
yann@1
|
3116 |
+
|
yann@1
|
3117 |
+ high = answer >> BITS_PER_SI;
|
yann@1
|
3118 |
+ low = answer;
|
yann@1
|
3119 |
+ }
|
yann@1
|
3120 |
+#else
|
yann@1
|
3121 |
+ /* fractype is DImode, but we need the result to be twice as wide.
|
yann@1
|
3122 |
+ Assuming a widening multiply from DImode to TImode is not
|
yann@1
|
3123 |
+ available, build one by hand. */
|
yann@1
|
3124 |
+ {
|
yann@1
|
3125 |
+ USItype nl = a->fraction.ll;
|
yann@1
|
3126 |
+ USItype nh = a->fraction.ll >> BITS_PER_SI;
|
yann@1
|
3127 |
+ USItype ml = b->fraction.ll;
|
yann@1
|
3128 |
+ USItype mh = b->fraction.ll >> BITS_PER_SI;
|
yann@1
|
3129 |
+ UDItype pp_ll = (UDItype) ml * nl;
|
yann@1
|
3130 |
+ UDItype pp_hl = (UDItype) mh * nl;
|
yann@1
|
3131 |
+ UDItype pp_lh = (UDItype) ml * nh;
|
yann@1
|
3132 |
+ UDItype pp_hh = (UDItype) mh * nh;
|
yann@1
|
3133 |
+ UDItype res2 = 0;
|
yann@1
|
3134 |
+ UDItype res0 = 0;
|
yann@1
|
3135 |
+ UDItype ps_hh__ = pp_hl + pp_lh;
|
yann@1
|
3136 |
+ if (ps_hh__ < pp_hl)
|
yann@1
|
3137 |
+ res2 += (UDItype)1 << BITS_PER_SI;
|
yann@1
|
3138 |
+ pp_hl = (UDItype)(USItype)ps_hh__ << BITS_PER_SI;
|
yann@1
|
3139 |
+ res0 = pp_ll + pp_hl;
|
yann@1
|
3140 |
+ if (res0 < pp_ll)
|
yann@1
|
3141 |
+ res2++;
|
yann@1
|
3142 |
+ res2 += (ps_hh__ >> BITS_PER_SI) + pp_hh;
|
yann@1
|
3143 |
+ high = res2;
|
yann@1
|
3144 |
+ low = res0;
|
yann@1
|
3145 |
+ }
|
yann@1
|
3146 |
+#endif
|
yann@1
|
3147 |
+ }
|
yann@1
|
3148 |
+
|
yann@1
|
3149 |
+ tmp->normal_exp = a->normal_exp + b->normal_exp
|
yann@1
|
3150 |
+ + FRAC_NBITS - (FRACBITS + NGARDS);
|
yann@1
|
3151 |
+ tmp->sign = a->sign != b->sign;
|
yann@1
|
3152 |
+ while (high >= IMPLICIT_2)
|
yann@1
|
3153 |
+ {
|
yann@1
|
3154 |
+ tmp->normal_exp++;
|
yann@1
|
3155 |
+ if (high & 1)
|
yann@1
|
3156 |
+ {
|
yann@1
|
3157 |
+ low >>= 1;
|
yann@1
|
3158 |
+ low |= FRACHIGH;
|
yann@1
|
3159 |
+ }
|
yann@1
|
3160 |
+ high >>= 1;
|
yann@1
|
3161 |
+ }
|
yann@1
|
3162 |
+ while (high < IMPLICIT_1)
|
yann@1
|
3163 |
+ {
|
yann@1
|
3164 |
+ tmp->normal_exp--;
|
yann@1
|
3165 |
+
|
yann@1
|
3166 |
+ high <<= 1;
|
yann@1
|
3167 |
+ if (low & FRACHIGH)
|
yann@1
|
3168 |
+ high |= 1;
|
yann@1
|
3169 |
+ low <<= 1;
|
yann@1
|
3170 |
+ }
|
yann@1
|
3171 |
+ /* rounding is tricky. if we only round if it won't make us round later. */
|
yann@1
|
3172 |
+#if 0
|
yann@1
|
3173 |
+ if (low & FRACHIGH2)
|
yann@1
|
3174 |
+ {
|
yann@1
|
3175 |
+ if (((high & GARDMASK) != GARDMSB)
|
yann@1
|
3176 |
+ && (((high + 1) & GARDMASK) == GARDMSB))
|
yann@1
|
3177 |
+ {
|
yann@1
|
3178 |
+ /* don't round, it gets done again later. */
|
yann@1
|
3179 |
+ }
|
yann@1
|
3180 |
+ else
|
yann@1
|
3181 |
+ {
|
yann@1
|
3182 |
+ high++;
|
yann@1
|
3183 |
+ }
|
yann@1
|
3184 |
+ }
|
yann@1
|
3185 |
+#endif
|
yann@1
|
3186 |
+ if (!ROUND_TOWARDS_ZERO && (high & GARDMASK) == GARDMSB)
|
yann@1
|
3187 |
+ {
|
yann@1
|
3188 |
+ if (high & (1 << NGARDS))
|
yann@1
|
3189 |
+ {
|
yann@1
|
3190 |
+ /* half way, so round to even */
|
yann@1
|
3191 |
+ high += GARDROUND + 1;
|
yann@1
|
3192 |
+ }
|
yann@1
|
3193 |
+ else if (low)
|
yann@1
|
3194 |
+ {
|
yann@1
|
3195 |
+ /* but we really weren't half way */
|
yann@1
|
3196 |
+ high += GARDROUND + 1;
|
yann@1
|
3197 |
+ }
|
yann@1
|
3198 |
+ }
|
yann@1
|
3199 |
+ tmp->fraction.ll = high;
|
yann@1
|
3200 |
+ tmp->class = CLASS_NUMBER;
|
yann@1
|
3201 |
+ return tmp;
|
yann@1
|
3202 |
+}
|
yann@1
|
3203 |
+
|
yann@1
|
3204 |
+FLO_type
|
yann@1
|
3205 |
+multiply (FLO_type arg_a, FLO_type arg_b)
|
yann@1
|
3206 |
+{
|
yann@1
|
3207 |
+ fp_number_type a;
|
yann@1
|
3208 |
+ fp_number_type b;
|
yann@1
|
3209 |
+ fp_number_type tmp;
|
yann@1
|
3210 |
+ fp_number_type *res;
|
yann@1
|
3211 |
+ FLO_union_type au, bu;
|
yann@1
|
3212 |
+
|
yann@1
|
3213 |
+ au.value = arg_a;
|
yann@1
|
3214 |
+ bu.value = arg_b;
|
yann@1
|
3215 |
+
|
yann@1
|
3216 |
+ unpack_d (&au, &a);
|
yann@1
|
3217 |
+ unpack_d (&bu, &b);
|
yann@1
|
3218 |
+
|
yann@1
|
3219 |
+ res = _fpmul_parts (&a, &b, &tmp);
|
yann@1
|
3220 |
+
|
yann@1
|
3221 |
+ return pack_d (res);
|
yann@1
|
3222 |
+}
|
yann@1
|
3223 |
+#endif /* L_mul_sf || L_mul_df */
|
yann@1
|
3224 |
+
|
yann@1
|
3225 |
+#if defined(L_div_sf) || defined(L_div_df) || defined(L_div_tf)
|
yann@1
|
3226 |
+static inline __attribute__ ((__always_inline__)) fp_number_type *
|
yann@1
|
3227 |
+_fpdiv_parts (fp_number_type * a,
|
yann@1
|
3228 |
+ fp_number_type * b)
|
yann@1
|
3229 |
+{
|
yann@1
|
3230 |
+ fractype bit;
|
yann@1
|
3231 |
+ fractype numerator;
|
yann@1
|
3232 |
+ fractype denominator;
|
yann@1
|
3233 |
+ fractype quotient;
|
yann@1
|
3234 |
+
|
yann@1
|
3235 |
+ if (isnan (a))
|
yann@1
|
3236 |
+ {
|
yann@1
|
3237 |
+ return a;
|
yann@1
|
3238 |
+ }
|
yann@1
|
3239 |
+ if (isnan (b))
|
yann@1
|
3240 |
+ {
|
yann@1
|
3241 |
+ return b;
|
yann@1
|
3242 |
+ }
|
yann@1
|
3243 |
+
|
yann@1
|
3244 |
+ a->sign = a->sign ^ b->sign;
|
yann@1
|
3245 |
+
|
yann@1
|
3246 |
+ if (isinf (a) || iszero (a))
|
yann@1
|
3247 |
+ {
|
yann@1
|
3248 |
+ if (a->class == b->class)
|
yann@1
|
3249 |
+ return nan ();
|
yann@1
|
3250 |
+ return a;
|
yann@1
|
3251 |
+ }
|
yann@1
|
3252 |
+
|
yann@1
|
3253 |
+ if (isinf (b))
|
yann@1
|
3254 |
+ {
|
yann@1
|
3255 |
+ a->fraction.ll = 0;
|
yann@1
|
3256 |
+ a->normal_exp = 0;
|
yann@1
|
3257 |
+ return a;
|
yann@1
|
3258 |
+ }
|
yann@1
|
3259 |
+ if (iszero (b))
|
yann@1
|
3260 |
+ {
|
yann@1
|
3261 |
+ a->class = CLASS_INFINITY;
|
yann@1
|
3262 |
+ return a;
|
yann@1
|
3263 |
+ }
|
yann@1
|
3264 |
+
|
yann@1
|
3265 |
+ /* Calculate the mantissa by multiplying both 64bit numbers to get a
|
yann@1
|
3266 |
+ 128 bit number */
|
yann@1
|
3267 |
+ {
|
yann@1
|
3268 |
+ /* quotient =
|
yann@1
|
3269 |
+ ( numerator / denominator) * 2^(numerator exponent - denominator exponent)
|
yann@1
|
3270 |
+ */
|
yann@1
|
3271 |
+
|
yann@1
|
3272 |
+ a->normal_exp = a->normal_exp - b->normal_exp;
|
yann@1
|
3273 |
+ numerator = a->fraction.ll;
|
yann@1
|
3274 |
+ denominator = b->fraction.ll;
|
yann@1
|
3275 |
+
|
yann@1
|
3276 |
+ if (numerator < denominator)
|
yann@1
|
3277 |
+ {
|
yann@1
|
3278 |
+ /* Fraction will be less than 1.0 */
|
yann@1
|
3279 |
+ numerator *= 2;
|
yann@1
|
3280 |
+ a->normal_exp--;
|
yann@1
|
3281 |
+ }
|
yann@1
|
3282 |
+ bit = IMPLICIT_1;
|
yann@1
|
3283 |
+ quotient = 0;
|
yann@1
|
3284 |
+ /* ??? Does divide one bit at a time. Optimize. */
|
yann@1
|
3285 |
+ while (bit)
|
yann@1
|
3286 |
+ {
|
yann@1
|
3287 |
+ if (numerator >= denominator)
|
yann@1
|
3288 |
+ {
|
yann@1
|
3289 |
+ quotient |= bit;
|
yann@1
|
3290 |
+ numerator -= denominator;
|
yann@1
|
3291 |
+ }
|
yann@1
|
3292 |
+ bit >>= 1;
|
yann@1
|
3293 |
+ numerator *= 2;
|
yann@1
|
3294 |
+ }
|
yann@1
|
3295 |
+
|
yann@1
|
3296 |
+ if (!ROUND_TOWARDS_ZERO && (quotient & GARDMASK) == GARDMSB)
|
yann@1
|
3297 |
+ {
|
yann@1
|
3298 |
+ if (quotient & (1 << NGARDS))
|
yann@1
|
3299 |
+ {
|
yann@1
|
3300 |
+ /* half way, so round to even */
|
yann@1
|
3301 |
+ quotient += GARDROUND + 1;
|
yann@1
|
3302 |
+ }
|
yann@1
|
3303 |
+ else if (numerator)
|
yann@1
|
3304 |
+ {
|
yann@1
|
3305 |
+ /* but we really weren't half way, more bits exist */
|
yann@1
|
3306 |
+ quotient += GARDROUND + 1;
|
yann@1
|
3307 |
+ }
|
yann@1
|
3308 |
+ }
|
yann@1
|
3309 |
+
|
yann@1
|
3310 |
+ a->fraction.ll = quotient;
|
yann@1
|
3311 |
+ return (a);
|
yann@1
|
3312 |
+ }
|
yann@1
|
3313 |
+}
|
yann@1
|
3314 |
+
|
yann@1
|
3315 |
+FLO_type
|
yann@1
|
3316 |
+divide (FLO_type arg_a, FLO_type arg_b)
|
yann@1
|
3317 |
+{
|
yann@1
|
3318 |
+ fp_number_type a;
|
yann@1
|
3319 |
+ fp_number_type b;
|
yann@1
|
3320 |
+ fp_number_type *res;
|
yann@1
|
3321 |
+ FLO_union_type au, bu;
|
yann@1
|
3322 |
+
|
yann@1
|
3323 |
+ au.value = arg_a;
|
yann@1
|
3324 |
+ bu.value = arg_b;
|
yann@1
|
3325 |
+
|
yann@1
|
3326 |
+ unpack_d (&au, &a);
|
yann@1
|
3327 |
+ unpack_d (&bu, &b);
|
yann@1
|
3328 |
+
|
yann@1
|
3329 |
+ res = _fpdiv_parts (&a, &b);
|
yann@1
|
3330 |
+
|
yann@1
|
3331 |
+ return pack_d (res);
|
yann@1
|
3332 |
+}
|
yann@1
|
3333 |
+#endif /* L_div_sf || L_div_df */
|
yann@1
|
3334 |
+
|
yann@1
|
3335 |
+#if defined(L_fpcmp_parts_sf) || defined(L_fpcmp_parts_df) \
|
yann@1
|
3336 |
+ || defined(L_fpcmp_parts_tf)
|
yann@1
|
3337 |
+/* according to the demo, fpcmp returns a comparison with 0... thus
|
yann@1
|
3338 |
+ a<b -> -1
|
yann@1
|
3339 |
+ a==b -> 0
|
yann@1
|
3340 |
+ a>b -> +1
|
yann@1
|
3341 |
+ */
|
yann@1
|
3342 |
+
|
yann@1
|
3343 |
+int
|
yann@1
|
3344 |
+__fpcmp_parts (fp_number_type * a, fp_number_type * b)
|
yann@1
|
3345 |
+{
|
yann@1
|
3346 |
+#if 0
|
yann@1
|
3347 |
+ /* either nan -> unordered. Must be checked outside of this routine. */
|
yann@1
|
3348 |
+ if (isnan (a) && isnan (b))
|
yann@1
|
3349 |
+ {
|
yann@1
|
3350 |
+ return 1; /* still unordered! */
|
yann@1
|
3351 |
+ }
|
yann@1
|
3352 |
+#endif
|
yann@1
|
3353 |
+
|
yann@1
|
3354 |
+ if (isnan (a) || isnan (b))
|
yann@1
|
3355 |
+ {
|
yann@1
|
3356 |
+ return 1; /* how to indicate unordered compare? */
|
yann@1
|
3357 |
+ }
|
yann@1
|
3358 |
+ if (isinf (a) && isinf (b))
|
yann@1
|
3359 |
+ {
|
yann@1
|
3360 |
+ /* +inf > -inf, but +inf != +inf */
|
yann@1
|
3361 |
+ /* b \a| +inf(0)| -inf(1)
|
yann@1
|
3362 |
+ ______\+--------+--------
|
yann@1
|
3363 |
+ +inf(0)| a==b(0)| a<b(-1)
|
yann@1
|
3364 |
+ -------+--------+--------
|
yann@1
|
3365 |
+ -inf(1)| a>b(1) | a==b(0)
|
yann@1
|
3366 |
+ -------+--------+--------
|
yann@1
|
3367 |
+ So since unordered must be nonzero, just line up the columns...
|
yann@1
|
3368 |
+ */
|
yann@1
|
3369 |
+ return b->sign - a->sign;
|
yann@1
|
3370 |
+ }
|
yann@1
|
3371 |
+ /* but not both... */
|
yann@1
|
3372 |
+ if (isinf (a))
|
yann@1
|
3373 |
+ {
|
yann@1
|
3374 |
+ return a->sign ? -1 : 1;
|
yann@1
|
3375 |
+ }
|
yann@1
|
3376 |
+ if (isinf (b))
|
yann@1
|
3377 |
+ {
|
yann@1
|
3378 |
+ return b->sign ? 1 : -1;
|
yann@1
|
3379 |
+ }
|
yann@1
|
3380 |
+ if (iszero (a) && iszero (b))
|
yann@1
|
3381 |
+ {
|
yann@1
|
3382 |
+ return 0;
|
yann@1
|
3383 |
+ }
|
yann@1
|
3384 |
+ if (iszero (a))
|
yann@1
|
3385 |
+ {
|
yann@1
|
3386 |
+ return b->sign ? 1 : -1;
|
yann@1
|
3387 |
+ }
|
yann@1
|
3388 |
+ if (iszero (b))
|
yann@1
|
3389 |
+ {
|
yann@1
|
3390 |
+ return a->sign ? -1 : 1;
|
yann@1
|
3391 |
+ }
|
yann@1
|
3392 |
+ /* now both are "normal". */
|
yann@1
|
3393 |
+ if (a->sign != b->sign)
|
yann@1
|
3394 |
+ {
|
yann@1
|
3395 |
+ /* opposite signs */
|
yann@1
|
3396 |
+ return a->sign ? -1 : 1;
|
yann@1
|
3397 |
+ }
|
yann@1
|
3398 |
+ /* same sign; exponents? */
|
yann@1
|
3399 |
+ if (a->normal_exp > b->normal_exp)
|
yann@1
|
3400 |
+ {
|
yann@1
|
3401 |
+ return a->sign ? -1 : 1;
|
yann@1
|
3402 |
+ }
|
yann@1
|
3403 |
+ if (a->normal_exp < b->normal_exp)
|
yann@1
|
3404 |
+ {
|
yann@1
|
3405 |
+ return a->sign ? 1 : -1;
|
yann@1
|
3406 |
+ }
|
yann@1
|
3407 |
+ /* same exponents; check size. */
|
yann@1
|
3408 |
+ if (a->fraction.ll > b->fraction.ll)
|
yann@1
|
3409 |
+ {
|
yann@1
|
3410 |
+ return a->sign ? -1 : 1;
|
yann@1
|
3411 |
+ }
|
yann@1
|
3412 |
+ if (a->fraction.ll < b->fraction.ll)
|
yann@1
|
3413 |
+ {
|
yann@1
|
3414 |
+ return a->sign ? 1 : -1;
|
yann@1
|
3415 |
+ }
|
yann@1
|
3416 |
+ /* after all that, they're equal. */
|
yann@1
|
3417 |
+ return 0;
|
yann@1
|
3418 |
+}
|
yann@1
|
3419 |
+#endif
|
yann@1
|
3420 |
+
|
yann@1
|
3421 |
+#if defined(L_compare_sf) || defined(L_compare_df) || defined(L_compoare_tf)
|
yann@1
|
3422 |
+CMPtype
|
yann@1
|
3423 |
+compare (FLO_type arg_a, FLO_type arg_b)
|
yann@1
|
3424 |
+{
|
yann@1
|
3425 |
+ fp_number_type a;
|
yann@1
|
3426 |
+ fp_number_type b;
|
yann@1
|
3427 |
+ FLO_union_type au, bu;
|
yann@1
|
3428 |
+
|
yann@1
|
3429 |
+ au.value = arg_a;
|
yann@1
|
3430 |
+ bu.value = arg_b;
|
yann@1
|
3431 |
+
|
yann@1
|
3432 |
+ unpack_d (&au, &a);
|
yann@1
|
3433 |
+ unpack_d (&bu, &b);
|
yann@1
|
3434 |
+
|
yann@1
|
3435 |
+ return __fpcmp_parts (&a, &b);
|
yann@1
|
3436 |
+}
|
yann@1
|
3437 |
+#endif /* L_compare_sf || L_compare_df */
|
yann@1
|
3438 |
+
|
yann@1
|
3439 |
+#ifndef US_SOFTWARE_GOFAST
|
yann@1
|
3440 |
+
|
yann@1
|
3441 |
+/* These should be optimized for their specific tasks someday. */
|
yann@1
|
3442 |
+
|
yann@1
|
3443 |
+#if defined(L_eq_sf) || defined(L_eq_df) || defined(L_eq_tf)
|
yann@1
|
3444 |
+CMPtype
|
yann@1
|
3445 |
+_eq_f2 (FLO_type arg_a, FLO_type arg_b)
|
yann@1
|
3446 |
+{
|
yann@1
|
3447 |
+ fp_number_type a;
|
yann@1
|
3448 |
+ fp_number_type b;
|
yann@1
|
3449 |
+ FLO_union_type au, bu;
|
yann@1
|
3450 |
+
|
yann@1
|
3451 |
+ au.value = arg_a;
|
yann@1
|
3452 |
+ bu.value = arg_b;
|
yann@1
|
3453 |
+
|
yann@1
|
3454 |
+ unpack_d (&au, &a);
|
yann@1
|
3455 |
+ unpack_d (&bu, &b);
|
yann@1
|
3456 |
+
|
yann@1
|
3457 |
+ if (isnan (&a) || isnan (&b))
|
yann@1
|
3458 |
+ return 1; /* false, truth == 0 */
|
yann@1
|
3459 |
+
|
yann@1
|
3460 |
+ return __fpcmp_parts (&a, &b) ;
|
yann@1
|
3461 |
+}
|
yann@1
|
3462 |
+#endif /* L_eq_sf || L_eq_df */
|
yann@1
|
3463 |
+
|
yann@1
|
3464 |
+#if defined(L_ne_sf) || defined(L_ne_df) || defined(L_ne_tf)
|
yann@1
|
3465 |
+CMPtype
|
yann@1
|
3466 |
+_ne_f2 (FLO_type arg_a, FLO_type arg_b)
|
yann@1
|
3467 |
+{
|
yann@1
|
3468 |
+ fp_number_type a;
|
yann@1
|
3469 |
+ fp_number_type b;
|
yann@1
|
3470 |
+ FLO_union_type au, bu;
|
yann@1
|
3471 |
+
|
yann@1
|
3472 |
+ au.value = arg_a;
|
yann@1
|
3473 |
+ bu.value = arg_b;
|
yann@1
|
3474 |
+
|
yann@1
|
3475 |
+ unpack_d (&au, &a);
|
yann@1
|
3476 |
+ unpack_d (&bu, &b);
|
yann@1
|
3477 |
+
|
yann@1
|
3478 |
+ if (isnan (&a) || isnan (&b))
|
yann@1
|
3479 |
+ return 1; /* true, truth != 0 */
|
yann@1
|
3480 |
+
|
yann@1
|
3481 |
+ return __fpcmp_parts (&a, &b) ;
|
yann@1
|
3482 |
+}
|
yann@1
|
3483 |
+#endif /* L_ne_sf || L_ne_df */
|
yann@1
|
3484 |
+
|
yann@1
|
3485 |
+#if defined(L_gt_sf) || defined(L_gt_df) || defined(L_gt_tf)
|
yann@1
|
3486 |
+CMPtype
|
yann@1
|
3487 |
+_gt_f2 (FLO_type arg_a, FLO_type arg_b)
|
yann@1
|
3488 |
+{
|
yann@1
|
3489 |
+ fp_number_type a;
|
yann@1
|
3490 |
+ fp_number_type b;
|
yann@1
|
3491 |
+ FLO_union_type au, bu;
|
yann@1
|
3492 |
+
|
yann@1
|
3493 |
+ au.value = arg_a;
|
yann@1
|
3494 |
+ bu.value = arg_b;
|
yann@1
|
3495 |
+
|
yann@1
|
3496 |
+ unpack_d (&au, &a);
|
yann@1
|
3497 |
+ unpack_d (&bu, &b);
|
yann@1
|
3498 |
+
|
yann@1
|
3499 |
+ if (isnan (&a) || isnan (&b))
|
yann@1
|
3500 |
+ return -1; /* false, truth > 0 */
|
yann@1
|
3501 |
+
|
yann@1
|
3502 |
+ return __fpcmp_parts (&a, &b);
|
yann@1
|
3503 |
+}
|
yann@1
|
3504 |
+#endif /* L_gt_sf || L_gt_df */
|
yann@1
|
3505 |
+
|
yann@1
|
3506 |
+#if defined(L_ge_sf) || defined(L_ge_df) || defined(L_ge_tf)
|
yann@1
|
3507 |
+CMPtype
|
yann@1
|
3508 |
+_ge_f2 (FLO_type arg_a, FLO_type arg_b)
|
yann@1
|
3509 |
+{
|
yann@1
|
3510 |
+ fp_number_type a;
|
yann@1
|
3511 |
+ fp_number_type b;
|
yann@1
|
3512 |
+ FLO_union_type au, bu;
|
yann@1
|
3513 |
+
|
yann@1
|
3514 |
+ au.value = arg_a;
|
yann@1
|
3515 |
+ bu.value = arg_b;
|
yann@1
|
3516 |
+
|
yann@1
|
3517 |
+ unpack_d (&au, &a);
|
yann@1
|
3518 |
+ unpack_d (&bu, &b);
|
yann@1
|
3519 |
+
|
yann@1
|
3520 |
+ if (isnan (&a) || isnan (&b))
|
yann@1
|
3521 |
+ return -1; /* false, truth >= 0 */
|
yann@1
|
3522 |
+ return __fpcmp_parts (&a, &b) ;
|
yann@1
|
3523 |
+}
|
yann@1
|
3524 |
+#endif /* L_ge_sf || L_ge_df */
|
yann@1
|
3525 |
+
|
yann@1
|
3526 |
+#if defined(L_lt_sf) || defined(L_lt_df) || defined(L_lt_tf)
|
yann@1
|
3527 |
+CMPtype
|
yann@1
|
3528 |
+_lt_f2 (FLO_type arg_a, FLO_type arg_b)
|
yann@1
|
3529 |
+{
|
yann@1
|
3530 |
+ fp_number_type a;
|
yann@1
|
3531 |
+ fp_number_type b;
|
yann@1
|
3532 |
+ FLO_union_type au, bu;
|
yann@1
|
3533 |
+
|
yann@1
|
3534 |
+ au.value = arg_a;
|
yann@1
|
3535 |
+ bu.value = arg_b;
|
yann@1
|
3536 |
+
|
yann@1
|
3537 |
+ unpack_d (&au, &a);
|
yann@1
|
3538 |
+ unpack_d (&bu, &b);
|
yann@1
|
3539 |
+
|
yann@1
|
3540 |
+ if (isnan (&a) || isnan (&b))
|
yann@1
|
3541 |
+ return 1; /* false, truth < 0 */
|
yann@1
|
3542 |
+
|
yann@1
|
3543 |
+ return __fpcmp_parts (&a, &b);
|
yann@1
|
3544 |
+}
|
yann@1
|
3545 |
+#endif /* L_lt_sf || L_lt_df */
|
yann@1
|
3546 |
+
|
yann@1
|
3547 |
+#if defined(L_le_sf) || defined(L_le_df) || defined(L_le_tf)
|
yann@1
|
3548 |
+CMPtype
|
yann@1
|
3549 |
+_le_f2 (FLO_type arg_a, FLO_type arg_b)
|
yann@1
|
3550 |
+{
|
yann@1
|
3551 |
+ fp_number_type a;
|
yann@1
|
3552 |
+ fp_number_type b;
|
yann@1
|
3553 |
+ FLO_union_type au, bu;
|
yann@1
|
3554 |
+
|
yann@1
|
3555 |
+ au.value = arg_a;
|
yann@1
|
3556 |
+ bu.value = arg_b;
|
yann@1
|
3557 |
+
|
yann@1
|
3558 |
+ unpack_d (&au, &a);
|
yann@1
|
3559 |
+ unpack_d (&bu, &b);
|
yann@1
|
3560 |
+
|
yann@1
|
3561 |
+ if (isnan (&a) || isnan (&b))
|
yann@1
|
3562 |
+ return 1; /* false, truth <= 0 */
|
yann@1
|
3563 |
+
|
yann@1
|
3564 |
+ return __fpcmp_parts (&a, &b) ;
|
yann@1
|
3565 |
+}
|
yann@1
|
3566 |
+#endif /* L_le_sf || L_le_df */
|
yann@1
|
3567 |
+
|
yann@1
|
3568 |
+#endif /* ! US_SOFTWARE_GOFAST */
|
yann@1
|
3569 |
+
|
yann@1
|
3570 |
+#if defined(L_unord_sf) || defined(L_unord_df) || defined(L_unord_tf)
|
yann@1
|
3571 |
+CMPtype
|
yann@1
|
3572 |
+_unord_f2 (FLO_type arg_a, FLO_type arg_b)
|
yann@1
|
3573 |
+{
|
yann@1
|
3574 |
+ fp_number_type a;
|
yann@1
|
3575 |
+ fp_number_type b;
|
yann@1
|
3576 |
+ FLO_union_type au, bu;
|
yann@1
|
3577 |
+
|
yann@1
|
3578 |
+ au.value = arg_a;
|
yann@1
|
3579 |
+ bu.value = arg_b;
|
yann@1
|
3580 |
+
|
yann@1
|
3581 |
+ unpack_d (&au, &a);
|
yann@1
|
3582 |
+ unpack_d (&bu, &b);
|
yann@1
|
3583 |
+
|
yann@1
|
3584 |
+ return (isnan (&a) || isnan (&b));
|
yann@1
|
3585 |
+}
|
yann@1
|
3586 |
+#endif /* L_unord_sf || L_unord_df */
|
yann@1
|
3587 |
+
|
yann@1
|
3588 |
+#if defined(L_si_to_sf) || defined(L_si_to_df) || defined(L_si_to_tf)
|
yann@1
|
3589 |
+FLO_type
|
yann@1
|
3590 |
+si_to_float (SItype arg_a)
|
yann@1
|
3591 |
+{
|
yann@1
|
3592 |
+ fp_number_type in;
|
yann@1
|
3593 |
+
|
yann@1
|
3594 |
+ in.class = CLASS_NUMBER;
|
yann@1
|
3595 |
+ in.sign = arg_a < 0;
|
yann@1
|
3596 |
+ if (!arg_a)
|
yann@1
|
3597 |
+ {
|
yann@1
|
3598 |
+ in.class = CLASS_ZERO;
|
yann@1
|
3599 |
+ }
|
yann@1
|
3600 |
+ else
|
yann@1
|
3601 |
+ {
|
yann@1
|
3602 |
+ in.normal_exp = FRACBITS + NGARDS;
|
yann@1
|
3603 |
+ if (in.sign)
|
yann@1
|
3604 |
+ {
|
yann@1
|
3605 |
+ /* Special case for minint, since there is no +ve integer
|
yann@1
|
3606 |
+ representation for it */
|
yann@1
|
3607 |
+ if (arg_a == (- MAX_SI_INT - 1))
|
yann@1
|
3608 |
+ {
|
yann@1
|
3609 |
+ return (FLO_type)(- MAX_SI_INT - 1);
|
yann@1
|
3610 |
+ }
|
yann@1
|
3611 |
+ in.fraction.ll = (-arg_a);
|
yann@1
|
3612 |
+ }
|
yann@1
|
3613 |
+ else
|
yann@1
|
3614 |
+ in.fraction.ll = arg_a;
|
yann@1
|
3615 |
+
|
yann@1
|
3616 |
+ while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
|
yann@1
|
3617 |
+ {
|
yann@1
|
3618 |
+ in.fraction.ll <<= 1;
|
yann@1
|
3619 |
+ in.normal_exp -= 1;
|
yann@1
|
3620 |
+ }
|
yann@1
|
3621 |
+ }
|
yann@1
|
3622 |
+ return pack_d (&in);
|
yann@1
|
3623 |
+}
|
yann@1
|
3624 |
+#endif /* L_si_to_sf || L_si_to_df */
|
yann@1
|
3625 |
+
|
yann@1
|
3626 |
+#if defined(L_usi_to_sf) || defined(L_usi_to_df) || defined(L_usi_to_tf)
|
yann@1
|
3627 |
+FLO_type
|
yann@1
|
3628 |
+usi_to_float (USItype arg_a)
|
yann@1
|
3629 |
+{
|
yann@1
|
3630 |
+ fp_number_type in;
|
yann@1
|
3631 |
+
|
yann@1
|
3632 |
+ in.sign = 0;
|
yann@1
|
3633 |
+ if (!arg_a)
|
yann@1
|
3634 |
+ {
|
yann@1
|
3635 |
+ in.class = CLASS_ZERO;
|
yann@1
|
3636 |
+ }
|
yann@1
|
3637 |
+ else
|
yann@1
|
3638 |
+ {
|
yann@1
|
3639 |
+ in.class = CLASS_NUMBER;
|
yann@1
|
3640 |
+ in.normal_exp = FRACBITS + NGARDS;
|
yann@1
|
3641 |
+ in.fraction.ll = arg_a;
|
yann@1
|
3642 |
+
|
yann@1
|
3643 |
+ while (in.fraction.ll > ((fractype)1 << (FRACBITS + NGARDS)))
|
yann@1
|
3644 |
+ {
|
yann@1
|
3645 |
+ in.fraction.ll >>= 1;
|
yann@1
|
3646 |
+ in.normal_exp += 1;
|
yann@1
|
3647 |
+ }
|
yann@1
|
3648 |
+ while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
|
yann@1
|
3649 |
+ {
|
yann@1
|
3650 |
+ in.fraction.ll <<= 1;
|
yann@1
|
3651 |
+ in.normal_exp -= 1;
|
yann@1
|
3652 |
+ }
|
yann@1
|
3653 |
+ }
|
yann@1
|
3654 |
+ return pack_d (&in);
|
yann@1
|
3655 |
+}
|
yann@1
|
3656 |
+#endif
|
yann@1
|
3657 |
+
|
yann@1
|
3658 |
+#if defined(L_sf_to_si) || defined(L_df_to_si) || defined(L_tf_to_si)
|
yann@1
|
3659 |
+SItype
|
yann@1
|
3660 |
+float_to_si (FLO_type arg_a)
|
yann@1
|
3661 |
+{
|
yann@1
|
3662 |
+ fp_number_type a;
|
yann@1
|
3663 |
+ SItype tmp;
|
yann@1
|
3664 |
+ FLO_union_type au;
|
yann@1
|
3665 |
+
|
yann@1
|
3666 |
+ au.value = arg_a;
|
yann@1
|
3667 |
+ unpack_d (&au, &a);
|
yann@1
|
3668 |
+
|
yann@1
|
3669 |
+ if (iszero (&a))
|
yann@1
|
3670 |
+ return 0;
|
yann@1
|
3671 |
+ if (isnan (&a))
|
yann@1
|
3672 |
+ return 0;
|
yann@1
|
3673 |
+ /* get reasonable MAX_SI_INT... */
|
yann@1
|
3674 |
+ if (isinf (&a))
|
yann@1
|
3675 |
+ return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
|
yann@1
|
3676 |
+ /* it is a number, but a small one */
|
yann@1
|
3677 |
+ if (a.normal_exp < 0)
|
yann@1
|
3678 |
+ return 0;
|
yann@1
|
3679 |
+ if (a.normal_exp > BITS_PER_SI - 2)
|
yann@1
|
3680 |
+ return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
|
yann@1
|
3681 |
+ tmp = a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
|
yann@1
|
3682 |
+ return a.sign ? (-tmp) : (tmp);
|
yann@1
|
3683 |
+}
|
yann@1
|
3684 |
+#endif /* L_sf_to_si || L_df_to_si */
|
yann@1
|
3685 |
+
|
yann@1
|
3686 |
+#if defined(L_sf_to_usi) || defined(L_df_to_usi) || defined(L_tf_to_usi)
|
yann@1
|
3687 |
+#if defined US_SOFTWARE_GOFAST || defined(L_tf_to_usi)
|
yann@1
|
3688 |
+/* While libgcc2.c defines its own __fixunssfsi and __fixunsdfsi routines,
|
yann@1
|
3689 |
+ we also define them for GOFAST because the ones in libgcc2.c have the
|
yann@1
|
3690 |
+ wrong names and I'd rather define these here and keep GOFAST CYG-LOC's
|
yann@1
|
3691 |
+ out of libgcc2.c. We can't define these here if not GOFAST because then
|
yann@1
|
3692 |
+ there'd be duplicate copies. */
|
yann@1
|
3693 |
+
|
yann@1
|
3694 |
+USItype
|
yann@1
|
3695 |
+float_to_usi (FLO_type arg_a)
|
yann@1
|
3696 |
+{
|
yann@1
|
3697 |
+ fp_number_type a;
|
yann@1
|
3698 |
+ FLO_union_type au;
|
yann@1
|
3699 |
+
|
yann@1
|
3700 |
+ au.value = arg_a;
|
yann@1
|
3701 |
+ unpack_d (&au, &a);
|
yann@1
|
3702 |
+
|
yann@1
|
3703 |
+ if (iszero (&a))
|
yann@1
|
3704 |
+ return 0;
|
yann@1
|
3705 |
+ if (isnan (&a))
|
yann@1
|
3706 |
+ return 0;
|
yann@1
|
3707 |
+ /* it is a negative number */
|
yann@1
|
3708 |
+ if (a.sign)
|
yann@1
|
3709 |
+ return 0;
|
yann@1
|
3710 |
+ /* get reasonable MAX_USI_INT... */
|
yann@1
|
3711 |
+ if (isinf (&a))
|
yann@1
|
3712 |
+ return MAX_USI_INT;
|
yann@1
|
3713 |
+ /* it is a number, but a small one */
|
yann@1
|
3714 |
+ if (a.normal_exp < 0)
|
yann@1
|
3715 |
+ return 0;
|
yann@1
|
3716 |
+ if (a.normal_exp > BITS_PER_SI - 1)
|
yann@1
|
3717 |
+ return MAX_USI_INT;
|
yann@1
|
3718 |
+ else if (a.normal_exp > (FRACBITS + NGARDS))
|
yann@1
|
3719 |
+ return a.fraction.ll << (a.normal_exp - (FRACBITS + NGARDS));
|
yann@1
|
3720 |
+ else
|
yann@1
|
3721 |
+ return a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
|
yann@1
|
3722 |
+}
|
yann@1
|
3723 |
+#endif /* US_SOFTWARE_GOFAST */
|
yann@1
|
3724 |
+#endif /* L_sf_to_usi || L_df_to_usi */
|
yann@1
|
3725 |
+
|
yann@1
|
3726 |
+#if defined(L_negate_sf) || defined(L_negate_df) || defined(L_negate_tf)
|
yann@1
|
3727 |
+FLO_type
|
yann@1
|
3728 |
+negate (FLO_type arg_a)
|
yann@1
|
3729 |
+{
|
yann@1
|
3730 |
+ fp_number_type a;
|
yann@1
|
3731 |
+ FLO_union_type au;
|
yann@1
|
3732 |
+
|
yann@1
|
3733 |
+ au.value = arg_a;
|
yann@1
|
3734 |
+ unpack_d (&au, &a);
|
yann@1
|
3735 |
+
|
yann@1
|
3736 |
+ flip_sign (&a);
|
yann@1
|
3737 |
+ return pack_d (&a);
|
yann@1
|
3738 |
+}
|
yann@1
|
3739 |
+#endif /* L_negate_sf || L_negate_df */
|
yann@1
|
3740 |
+
|
yann@1
|
3741 |
+#ifdef FLOAT
|
yann@1
|
3742 |
+
|
yann@1
|
3743 |
+#if defined(L_make_sf)
|
yann@1
|
3744 |
+SFtype
|
yann@1
|
3745 |
+__make_fp(fp_class_type class,
|
yann@1
|
3746 |
+ unsigned int sign,
|
yann@1
|
3747 |
+ int exp,
|
yann@1
|
3748 |
+ USItype frac)
|
yann@1
|
3749 |
+{
|
yann@1
|
3750 |
+ fp_number_type in;
|
yann@1
|
3751 |
+
|
yann@1
|
3752 |
+ in.class = class;
|
yann@1
|
3753 |
+ in.sign = sign;
|
yann@1
|
3754 |
+ in.normal_exp = exp;
|
yann@1
|
3755 |
+ in.fraction.ll = frac;
|
yann@1
|
3756 |
+ return pack_d (&in);
|
yann@1
|
3757 |
+}
|
yann@1
|
3758 |
+#endif /* L_make_sf */
|
yann@1
|
3759 |
+
|
yann@1
|
3760 |
+#ifndef FLOAT_ONLY
|
yann@1
|
3761 |
+
|
yann@1
|
3762 |
+/* This enables one to build an fp library that supports float but not double.
|
yann@1
|
3763 |
+ Otherwise, we would get an undefined reference to __make_dp.
|
yann@1
|
3764 |
+ This is needed for some 8-bit ports that can't handle well values that
|
yann@1
|
3765 |
+ are 8-bytes in size, so we just don't support double for them at all. */
|
yann@1
|
3766 |
+
|
yann@1
|
3767 |
+#if defined(L_sf_to_df)
|
yann@1
|
3768 |
+DFtype
|
yann@1
|
3769 |
+sf_to_df (SFtype arg_a)
|
yann@1
|
3770 |
+{
|
yann@1
|
3771 |
+ fp_number_type in;
|
yann@1
|
3772 |
+ FLO_union_type au;
|
yann@1
|
3773 |
+
|
yann@1
|
3774 |
+ au.value = arg_a;
|
yann@1
|
3775 |
+ unpack_d (&au, &in);
|
yann@1
|
3776 |
+
|
yann@1
|
3777 |
+ return __make_dp (in.class, in.sign, in.normal_exp,
|
yann@1
|
3778 |
+ ((UDItype) in.fraction.ll) << F_D_BITOFF);
|
yann@1
|
3779 |
+}
|
yann@1
|
3780 |
+#endif /* L_sf_to_df */
|
yann@1
|
3781 |
+
|
yann@1
|
3782 |
+#if defined(L_sf_to_tf) && defined(TMODES)
|
yann@1
|
3783 |
+TFtype
|
yann@1
|
3784 |
+sf_to_tf (SFtype arg_a)
|
yann@1
|
3785 |
+{
|
yann@1
|
3786 |
+ fp_number_type in;
|
yann@1
|
3787 |
+ FLO_union_type au;
|
yann@1
|
3788 |
+
|
yann@1
|
3789 |
+ au.value = arg_a;
|
yann@1
|
3790 |
+ unpack_d (&au, &in);
|
yann@1
|
3791 |
+
|
yann@1
|
3792 |
+ return __make_tp (in.class, in.sign, in.normal_exp,
|
yann@1
|
3793 |
+ ((UTItype) in.fraction.ll) << F_T_BITOFF);
|
yann@1
|
3794 |
+}
|
yann@1
|
3795 |
+#endif /* L_sf_to_df */
|
yann@1
|
3796 |
+
|
yann@1
|
3797 |
+#endif /* ! FLOAT_ONLY */
|
yann@1
|
3798 |
+#endif /* FLOAT */
|
yann@1
|
3799 |
+
|
yann@1
|
3800 |
+#ifndef FLOAT
|
yann@1
|
3801 |
+
|
yann@1
|
3802 |
+extern SFtype __make_fp (fp_class_type, unsigned int, int, USItype);
|
yann@1
|
3803 |
+
|
yann@1
|
3804 |
+#if defined(L_make_df)
|
yann@1
|
3805 |
+DFtype
|
yann@1
|
3806 |
+__make_dp (fp_class_type class, unsigned int sign, int exp, UDItype frac)
|
yann@1
|
3807 |
+{
|
yann@1
|
3808 |
+ fp_number_type in;
|
yann@1
|
3809 |
+
|
yann@1
|
3810 |
+ in.class = class;
|
yann@1
|
3811 |
+ in.sign = sign;
|
yann@1
|
3812 |
+ in.normal_exp = exp;
|
yann@1
|
3813 |
+ in.fraction.ll = frac;
|
yann@1
|
3814 |
+ return pack_d (&in);
|
yann@1
|
3815 |
+}
|
yann@1
|
3816 |
+#endif /* L_make_df */
|
yann@1
|
3817 |
+
|
yann@1
|
3818 |
+#if defined(L_df_to_sf)
|
yann@1
|
3819 |
+SFtype
|
yann@1
|
3820 |
+df_to_sf (DFtype arg_a)
|
yann@1
|
3821 |
+{
|
yann@1
|
3822 |
+ fp_number_type in;
|
yann@1
|
3823 |
+ USItype sffrac;
|
yann@1
|
3824 |
+ FLO_union_type au;
|
yann@1
|
3825 |
+
|
yann@1
|
3826 |
+ au.value = arg_a;
|
yann@1
|
3827 |
+ unpack_d (&au, &in);
|
yann@1
|
3828 |
+
|
yann@1
|
3829 |
+ sffrac = in.fraction.ll >> F_D_BITOFF;
|
yann@1
|
3830 |
+
|
yann@1
|
3831 |
+ /* We set the lowest guard bit in SFFRAC if we discarded any non
|
yann@1
|
3832 |
+ zero bits. */
|
yann@1
|
3833 |
+ if ((in.fraction.ll & (((USItype) 1 << F_D_BITOFF) - 1)) != 0)
|
yann@1
|
3834 |
+ sffrac |= 1;
|
yann@1
|
3835 |
+
|
yann@1
|
3836 |
+ return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
|
yann@1
|
3837 |
+}
|
yann@1
|
3838 |
+#endif /* L_df_to_sf */
|
yann@1
|
3839 |
+
|
yann@1
|
3840 |
+#if defined(L_df_to_tf) && defined(TMODES) \
|
yann@1
|
3841 |
+ && !defined(FLOAT) && !defined(TFLOAT)
|
yann@1
|
3842 |
+TFtype
|
yann@1
|
3843 |
+df_to_tf (DFtype arg_a)
|
yann@1
|
3844 |
+{
|
yann@1
|
3845 |
+ fp_number_type in;
|
yann@1
|
3846 |
+ FLO_union_type au;
|
yann@1
|
3847 |
+
|
yann@1
|
3848 |
+ au.value = arg_a;
|
yann@1
|
3849 |
+ unpack_d (&au, &in);
|
yann@1
|
3850 |
+
|
yann@1
|
3851 |
+ return __make_tp (in.class, in.sign, in.normal_exp,
|
yann@1
|
3852 |
+ ((UTItype) in.fraction.ll) << D_T_BITOFF);
|
yann@1
|
3853 |
+}
|
yann@1
|
3854 |
+#endif /* L_sf_to_df */
|
yann@1
|
3855 |
+
|
yann@1
|
3856 |
+#ifdef TFLOAT
|
yann@1
|
3857 |
+#if defined(L_make_tf)
|
yann@1
|
3858 |
+TFtype
|
yann@1
|
3859 |
+__make_tp(fp_class_type class,
|
yann@1
|
3860 |
+ unsigned int sign,
|
yann@1
|
3861 |
+ int exp,
|
yann@1
|
3862 |
+ UTItype frac)
|
yann@1
|
3863 |
+{
|
yann@1
|
3864 |
+ fp_number_type in;
|
yann@1
|
3865 |
+
|
yann@1
|
3866 |
+ in.class = class;
|
yann@1
|
3867 |
+ in.sign = sign;
|
yann@1
|
3868 |
+ in.normal_exp = exp;
|
yann@1
|
3869 |
+ in.fraction.ll = frac;
|
yann@1
|
3870 |
+ return pack_d (&in);
|
yann@1
|
3871 |
+}
|
yann@1
|
3872 |
+#endif /* L_make_tf */
|
yann@1
|
3873 |
+
|
yann@1
|
3874 |
+#if defined(L_tf_to_df)
|
yann@1
|
3875 |
+DFtype
|
yann@1
|
3876 |
+tf_to_df (TFtype arg_a)
|
yann@1
|
3877 |
+{
|
yann@1
|
3878 |
+ fp_number_type in;
|
yann@1
|
3879 |
+ UDItype sffrac;
|
yann@1
|
3880 |
+ FLO_union_type au;
|
yann@1
|
3881 |
+
|
yann@1
|
3882 |
+ au.value = arg_a;
|
yann@1
|
3883 |
+ unpack_d (&au, &in);
|
yann@1
|
3884 |
+
|
yann@1
|
3885 |
+ sffrac = in.fraction.ll >> D_T_BITOFF;
|
yann@1
|
3886 |
+
|
yann@1
|
3887 |
+ /* We set the lowest guard bit in SFFRAC if we discarded any non
|
yann@1
|
3888 |
+ zero bits. */
|
yann@1
|
3889 |
+ if ((in.fraction.ll & (((UTItype) 1 << D_T_BITOFF) - 1)) != 0)
|
yann@1
|
3890 |
+ sffrac |= 1;
|
yann@1
|
3891 |
+
|
yann@1
|
3892 |
+ return __make_dp (in.class, in.sign, in.normal_exp, sffrac);
|
yann@1
|
3893 |
+}
|
yann@1
|
3894 |
+#endif /* L_tf_to_df */
|
yann@1
|
3895 |
+
|
yann@1
|
3896 |
+#if defined(L_tf_to_sf)
|
yann@1
|
3897 |
+SFtype
|
yann@1
|
3898 |
+tf_to_sf (TFtype arg_a)
|
yann@1
|
3899 |
+{
|
yann@1
|
3900 |
+ fp_number_type in;
|
yann@1
|
3901 |
+ USItype sffrac;
|
yann@1
|
3902 |
+ FLO_union_type au;
|
yann@1
|
3903 |
+
|
yann@1
|
3904 |
+ au.value = arg_a;
|
yann@1
|
3905 |
+ unpack_d (&au, &in);
|
yann@1
|
3906 |
+
|
yann@1
|
3907 |
+ sffrac = in.fraction.ll >> F_T_BITOFF;
|
yann@1
|
3908 |
+
|
yann@1
|
3909 |
+ /* We set the lowest guard bit in SFFRAC if we discarded any non
|
yann@1
|
3910 |
+ zero bits. */
|
yann@1
|
3911 |
+ if ((in.fraction.ll & (((UTItype) 1 << F_T_BITOFF) - 1)) != 0)
|
yann@1
|
3912 |
+ sffrac |= 1;
|
yann@1
|
3913 |
+
|
yann@1
|
3914 |
+ return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
|
yann@1
|
3915 |
+}
|
yann@1
|
3916 |
+#endif /* L_tf_to_sf */
|
yann@1
|
3917 |
+#endif /* TFLOAT */
|
yann@1
|
3918 |
+
|
yann@1
|
3919 |
+#endif /* ! FLOAT */
|
yann@1
|
3920 |
+#endif /* !EXTENDED_FLOAT_STUBS */
|
yann@1
|
3921 |
--- gcc-3.4.3/gcc/config/nios2/nios2-protos.h
|
yann@1
|
3922 |
+++ gcc-3.4.3-nios2/gcc/config/nios2/nios2-protos.h
|
yann@1
|
3923 |
@@ -0,0 +1,70 @@
|
yann@1
|
3924 |
+/* Subroutines for assembler code output for Altera NIOS 2G NIOS2 version.
|
yann@1
|
3925 |
+ Copyright (C) 2003 Altera
|
yann@1
|
3926 |
+ Contributed by Jonah Graham (jgraham@altera.com).
|
yann@1
|
3927 |
+
|
yann@1
|
3928 |
+This file is part of GNU CC.
|
yann@1
|
3929 |
+
|
yann@1
|
3930 |
+GNU CC is free software; you can redistribute it and/or modify
|
yann@1
|
3931 |
+it under the terms of the GNU General Public License as published by
|
yann@1
|
3932 |
+the Free Software Foundation; either version 2, or (at your option)
|
yann@1
|
3933 |
+any later version.
|
yann@1
|
3934 |
+
|
yann@1
|
3935 |
+GNU CC is distributed in the hope that it will be useful,
|
yann@1
|
3936 |
+but WITHOUT ANY WARRANTY; without even the implied warranty of
|
yann@1
|
3937 |
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
yann@1
|
3938 |
+GNU General Public License for more details.
|
yann@1
|
3939 |
+
|
yann@1
|
3940 |
+You should have received a copy of the GNU General Public License
|
yann@1
|
3941 |
+along with GNU CC; see the file COPYING. If not, write to
|
yann@1
|
3942 |
+the Free Software Foundation, 59 Temple Place - Suite 330,
|
yann@1
|
3943 |
+Boston, MA 02111-1307, USA. */
|
yann@1
|
3944 |
+
|
yann@1
|
3945 |
+extern void dump_frame_size (FILE *);
|
yann@1
|
3946 |
+extern HOST_WIDE_INT compute_frame_size (void);
|
yann@1
|
3947 |
+extern int nios2_initial_elimination_offset (int, int);
|
yann@1
|
3948 |
+extern void override_options (void);
|
yann@1
|
3949 |
+extern void optimization_options (int, int);
|
yann@1
|
3950 |
+extern int nios2_can_use_return_insn (void);
|
yann@1
|
3951 |
+extern void expand_prologue (void);
|
yann@1
|
3952 |
+extern void expand_epilogue (bool);
|
yann@1
|
3953 |
+extern void function_profiler (FILE *, int);
|
yann@1
|
3954 |
+
|
yann@1
|
3955 |
+
|
yann@1
|
3956 |
+#ifdef RTX_CODE
|
yann@1
|
3957 |
+extern int nios2_legitimate_address (rtx, enum machine_mode, int);
|
yann@1
|
3958 |
+extern void nios2_print_operand (FILE *, rtx, int);
|
yann@1
|
3959 |
+extern void nios2_print_operand_address (FILE *, rtx);
|
yann@1
|
3960 |
+
|
yann@1
|
3961 |
+extern int nios2_emit_move_sequence (rtx *, enum machine_mode);
|
yann@1
|
3962 |
+extern int nios2_emit_expensive_div (rtx *, enum machine_mode);
|
yann@1
|
3963 |
+
|
yann@1
|
3964 |
+extern void gen_int_relational (enum rtx_code, rtx, rtx, rtx, rtx);
|
yann@1
|
3965 |
+extern void gen_conditional_move (rtx *, enum machine_mode);
|
yann@1
|
3966 |
+extern const char *asm_output_opcode (FILE *, const char *);
|
yann@1
|
3967 |
+
|
yann@1
|
3968 |
+/* predicates */
|
yann@1
|
3969 |
+extern int arith_operand (rtx, enum machine_mode);
|
yann@1
|
3970 |
+extern int uns_arith_operand (rtx, enum machine_mode);
|
yann@1
|
3971 |
+extern int logical_operand (rtx, enum machine_mode);
|
yann@1
|
3972 |
+extern int shift_operand (rtx, enum machine_mode);
|
yann@1
|
3973 |
+extern int reg_or_0_operand (rtx, enum machine_mode);
|
yann@1
|
3974 |
+extern int equality_op (rtx, enum machine_mode);
|
yann@1
|
3975 |
+extern int custom_insn_opcode (rtx, enum machine_mode);
|
yann@1
|
3976 |
+extern int rdwrctl_operand (rtx, enum machine_mode);
|
yann@1
|
3977 |
+
|
yann@1
|
3978 |
+# ifdef HAVE_MACHINE_MODES
|
yann@1
|
3979 |
+# if defined TREE_CODE
|
yann@1
|
3980 |
+extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
|
yann@1
|
3981 |
+extern rtx function_arg (const CUMULATIVE_ARGS *, enum machine_mode, tree, int);
|
yann@1
|
3982 |
+extern int function_arg_partial_nregs (const CUMULATIVE_ARGS *, enum machine_mode, tree, int);
|
yann@1
|
3983 |
+extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
|
yann@1
|
3984 |
+extern int nios2_setup_incoming_varargs (const CUMULATIVE_ARGS *, enum machine_mode, tree, int);
|
yann@1
|
3985 |
+
|
yann@1
|
3986 |
+# endif /* TREE_CODE */
|
yann@1
|
3987 |
+# endif /* HAVE_MACHINE_MODES */
|
yann@1
|
3988 |
+#endif
|
yann@1
|
3989 |
+
|
yann@1
|
3990 |
+#ifdef TREE_CODE
|
yann@1
|
3991 |
+extern int nios2_return_in_memory (tree);
|
yann@1
|
3992 |
+
|
yann@1
|
3993 |
+#endif /* TREE_CODE */
|
yann@1
|
3994 |
--- gcc-3.4.3/gcc/config/nios2/nios2.c
|
yann@1
|
3995 |
+++ gcc-3.4.3-nios2/gcc/config/nios2/nios2.c
|
yann@1
|
3996 |
@@ -0,0 +1,2853 @@
|
yann@1
|
3997 |
+/* Subroutines for assembler code output for Altera NIOS 2G NIOS2 version.
|
yann@1
|
3998 |
+ Copyright (C) 2003 Altera
|
yann@1
|
3999 |
+ Contributed by Jonah Graham (jgraham@altera.com).
|
yann@1
|
4000 |
+
|
yann@1
|
4001 |
+This file is part of GNU CC.
|
yann@1
|
4002 |
+
|
yann@1
|
4003 |
+GNU CC is free software; you can redistribute it and/or modify
|
yann@1
|
4004 |
+it under the terms of the GNU General Public License as published by
|
yann@1
|
4005 |
+the Free Software Foundation; either version 2, or (at your option)
|
yann@1
|
4006 |
+any later version.
|
yann@1
|
4007 |
+
|
yann@1
|
4008 |
+GNU CC is distributed in the hope that it will be useful,
|
yann@1
|
4009 |
+but WITHOUT ANY WARRANTY; without even the implied warranty of
|
yann@1
|
4010 |
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
yann@1
|
4011 |
+GNU General Public License for more details.
|
yann@1
|
4012 |
+
|
yann@1
|
4013 |
+You should have received a copy of the GNU General Public License
|
yann@1
|
4014 |
+along with GNU CC; see the file COPYING. If not, write to
|
yann@1
|
4015 |
+the Free Software Foundation, 59 Temple Place - Suite 330,
|
yann@1
|
4016 |
+Boston, MA 02111-1307, USA. */
|
yann@1
|
4017 |
+
|
yann@1
|
4018 |
+
|
yann@1
|
4019 |
+#include <stdio.h>
|
yann@1
|
4020 |
+#include "config.h"
|
yann@1
|
4021 |
+#include "system.h"
|
yann@1
|
4022 |
+#include "coretypes.h"
|
yann@1
|
4023 |
+#include "tm.h"
|
yann@1
|
4024 |
+#include "rtl.h"
|
yann@1
|
4025 |
+#include "tree.h"
|
yann@1
|
4026 |
+#include "tm_p.h"
|
yann@1
|
4027 |
+#include "regs.h"
|
yann@1
|
4028 |
+#include "hard-reg-set.h"
|
yann@1
|
4029 |
+#include "real.h"
|
yann@1
|
4030 |
+#include "insn-config.h"
|
yann@1
|
4031 |
+#include "conditions.h"
|
yann@1
|
4032 |
+#include "output.h"
|
yann@1
|
4033 |
+#include "insn-attr.h"
|
yann@1
|
4034 |
+#include "flags.h"
|
yann@1
|
4035 |
+#include "recog.h"
|
yann@1
|
4036 |
+#include "expr.h"
|
yann@1
|
4037 |
+#include "toplev.h"
|
yann@1
|
4038 |
+#include "basic-block.h"
|
yann@1
|
4039 |
+#include "function.h"
|
yann@1
|
4040 |
+#include "ggc.h"
|
yann@1
|
4041 |
+#include "reload.h"
|
yann@1
|
4042 |
+#include "debug.h"
|
yann@1
|
4043 |
+#include "optabs.h"
|
yann@1
|
4044 |
+#include "target.h"
|
yann@1
|
4045 |
+#include "target-def.h"
|
yann@1
|
4046 |
+
|
yann@1
|
4047 |
+/* local prototypes */
|
yann@1
|
4048 |
+static bool nios2_rtx_costs (rtx, int, int, int *);
|
yann@1
|
4049 |
+
|
yann@1
|
4050 |
+static void nios2_asm_function_prologue (FILE *, HOST_WIDE_INT);
|
yann@1
|
4051 |
+static int nios2_use_dfa_pipeline_interface (void);
|
yann@1
|
4052 |
+static int nios2_issue_rate (void);
|
yann@1
|
4053 |
+static struct machine_function *nios2_init_machine_status (void);
|
yann@1
|
4054 |
+static bool nios2_in_small_data_p (tree);
|
yann@1
|
4055 |
+static rtx save_reg (int, HOST_WIDE_INT, rtx);
|
yann@1
|
4056 |
+static rtx restore_reg (int, HOST_WIDE_INT);
|
yann@1
|
4057 |
+static unsigned int nios2_section_type_flags (tree, const char *, int);
|
yann@1
|
4058 |
+static void nios2_init_builtins (void);
|
yann@1
|
4059 |
+static rtx nios2_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
|
yann@1
|
4060 |
+static bool nios2_function_ok_for_sibcall (tree, tree);
|
yann@1
|
4061 |
+static void nios2_encode_section_info (tree, rtx, int);
|
yann@1
|
4062 |
+
|
yann@1
|
4063 |
+/* Initialize the GCC target structure. */
|
yann@1
|
4064 |
+#undef TARGET_ASM_FUNCTION_PROLOGUE
|
yann@1
|
4065 |
+#define TARGET_ASM_FUNCTION_PROLOGUE nios2_asm_function_prologue
|
yann@1
|
4066 |
+
|
yann@1
|
4067 |
+#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
|
yann@1
|
4068 |
+#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE \
|
yann@1
|
4069 |
+ nios2_use_dfa_pipeline_interface
|
yann@1
|
4070 |
+#undef TARGET_SCHED_ISSUE_RATE
|
yann@1
|
4071 |
+#define TARGET_SCHED_ISSUE_RATE nios2_issue_rate
|
yann@1
|
4072 |
+#undef TARGET_IN_SMALL_DATA_P
|
yann@1
|
4073 |
+#define TARGET_IN_SMALL_DATA_P nios2_in_small_data_p
|
yann@1
|
4074 |
+#undef TARGET_ENCODE_SECTION_INFO
|
yann@1
|
4075 |
+#define TARGET_ENCODE_SECTION_INFO nios2_encode_section_info
|
yann@1
|
4076 |
+#undef TARGET_SECTION_TYPE_FLAGS
|
yann@1
|
4077 |
+#define TARGET_SECTION_TYPE_FLAGS nios2_section_type_flags
|
yann@1
|
4078 |
+
|
yann@1
|
4079 |
+#undef TARGET_INIT_BUILTINS
|
yann@1
|
4080 |
+#define TARGET_INIT_BUILTINS nios2_init_builtins
|
yann@1
|
4081 |
+#undef TARGET_EXPAND_BUILTIN
|
yann@1
|
4082 |
+#define TARGET_EXPAND_BUILTIN nios2_expand_builtin
|
yann@1
|
4083 |
+
|
yann@1
|
4084 |
+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
|
yann@1
|
4085 |
+#define TARGET_FUNCTION_OK_FOR_SIBCALL nios2_function_ok_for_sibcall
|
yann@1
|
4086 |
+
|
yann@1
|
4087 |
+#undef TARGET_RTX_COSTS
|
yann@1
|
4088 |
+#define TARGET_RTX_COSTS nios2_rtx_costs
|
yann@1
|
4089 |
+
|
yann@1
|
4090 |
+
|
yann@1
|
4091 |
+struct gcc_target targetm = TARGET_INITIALIZER;
|
yann@1
|
4092 |
+
|
yann@1
|
4093 |
+
|
yann@1
|
4094 |
+
|
yann@1
|
4095 |
+/* Threshold for data being put into the small data/bss area, instead
|
yann@1
|
4096 |
+ of the normal data area (references to the small data/bss area take
|
yann@1
|
4097 |
+ 1 instruction, and use the global pointer, references to the normal
|
yann@1
|
4098 |
+ data area takes 2 instructions). */
|
yann@1
|
4099 |
+unsigned HOST_WIDE_INT nios2_section_threshold = NIOS2_DEFAULT_GVALUE;
|
yann@1
|
4100 |
+
|
yann@1
|
4101 |
+
|
yann@1
|
4102 |
+/* Structure to be filled in by compute_frame_size with register
|
yann@1
|
4103 |
+ save masks, and offsets for the current function. */
|
yann@1
|
4104 |
+
|
yann@1
|
4105 |
+struct nios2_frame_info
|
yann@1
|
4106 |
+GTY (())
|
yann@1
|
4107 |
+{
|
yann@1
|
4108 |
+ long total_size; /* # bytes that the entire frame takes up */
|
yann@1
|
4109 |
+ long var_size; /* # bytes that variables take up */
|
yann@1
|
4110 |
+ long args_size; /* # bytes that outgoing arguments take up */
|
yann@1
|
4111 |
+ int save_reg_size; /* # bytes needed to store gp regs */
|
yann@1
|
4112 |
+ int save_reg_rounded; /* # bytes needed to store gp regs */
|
yann@1
|
4113 |
+ long save_regs_offset; /* offset from new sp to store gp registers */
|
yann@1
|
4114 |
+ int initialized; /* != 0 if frame size already calculated */
|
yann@1
|
4115 |
+ int num_regs; /* number of gp registers saved */
|
yann@1
|
4116 |
+};
|
yann@1
|
4117 |
+
|
yann@1
|
4118 |
+struct machine_function
|
yann@1
|
4119 |
+GTY (())
|
yann@1
|
4120 |
+{
|
yann@1
|
4121 |
+
|
yann@1
|
4122 |
+ /* Current frame information, calculated by compute_frame_size. */
|
yann@1
|
4123 |
+ struct nios2_frame_info frame;
|
yann@1
|
4124 |
+};
|
yann@1
|
4125 |
+
|
yann@1
|
4126 |
+
|
yann@1
|
4127 |
+/***************************************
|
yann@1
|
4128 |
+ * Section encodings
|
yann@1
|
4129 |
+ ***************************************/
|
yann@1
|
4130 |
+
|
yann@1
|
4131 |
+
|
yann@1
|
4132 |
+
|
yann@1
|
4133 |
+
|
yann@1
|
4134 |
+
|
yann@1
|
4135 |
+/***************************************
|
yann@1
|
4136 |
+ * Stack Layout and Calling Conventions
|
yann@1
|
4137 |
+ ***************************************/
|
yann@1
|
4138 |
+
|
yann@1
|
4139 |
+
|
yann@1
|
4140 |
+#define TOO_BIG_OFFSET(X) ((X) > ((1 << 15) - 1))
|
yann@1
|
4141 |
+#define TEMP_REG_NUM 8
|
yann@1
|
4142 |
+
|
yann@1
|
4143 |
+static void
|
yann@1
|
4144 |
+nios2_asm_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
|
yann@1
|
4145 |
+{
|
yann@1
|
4146 |
+ if (flag_verbose_asm || flag_debug_asm)
|
yann@1
|
4147 |
+ {
|
yann@1
|
4148 |
+ compute_frame_size ();
|
yann@1
|
4149 |
+ dump_frame_size (file);
|
yann@1
|
4150 |
+ }
|
yann@1
|
4151 |
+}
|
yann@1
|
4152 |
+
|
yann@1
|
4153 |
+static rtx
|
yann@1
|
4154 |
+save_reg (int regno, HOST_WIDE_INT offset, rtx cfa_store_reg)
|
yann@1
|
4155 |
+{
|
yann@1
|
4156 |
+ rtx insn, stack_slot;
|
yann@1
|
4157 |
+
|
yann@1
|
4158 |
+ stack_slot = gen_rtx_PLUS (SImode,
|
yann@1
|
4159 |
+ cfa_store_reg,
|
yann@1
|
4160 |
+ GEN_INT (offset));
|
yann@1
|
4161 |
+
|
yann@1
|
4162 |
+ insn = emit_insn (gen_rtx_SET (SImode,
|
yann@1
|
4163 |
+ gen_rtx_MEM (SImode, stack_slot),
|
yann@1
|
4164 |
+ gen_rtx_REG (SImode, regno)));
|
yann@1
|
4165 |
+
|
yann@1
|
4166 |
+ RTX_FRAME_RELATED_P (insn) = 1;
|
yann@1
|
4167 |
+
|
yann@1
|
4168 |
+ return insn;
|
yann@1
|
4169 |
+}
|
yann@1
|
4170 |
+
|
yann@1
|
4171 |
+static rtx
|
yann@1
|
4172 |
+restore_reg (int regno, HOST_WIDE_INT offset)
|
yann@1
|
4173 |
+{
|
yann@1
|
4174 |
+ rtx insn, stack_slot;
|
yann@1
|
4175 |
+
|
yann@1
|
4176 |
+ if (TOO_BIG_OFFSET (offset))
|
yann@1
|
4177 |
+ {
|
yann@1
|
4178 |
+ stack_slot = gen_rtx_REG (SImode, TEMP_REG_NUM);
|
yann@1
|
4179 |
+ insn = emit_insn (gen_rtx_SET (SImode,
|
yann@1
|
4180 |
+ stack_slot,
|
yann@1
|
4181 |
+ GEN_INT (offset)));
|
yann@1
|
4182 |
+
|
yann@1
|
4183 |
+ insn = emit_insn (gen_rtx_SET (SImode,
|
yann@1
|
4184 |
+ stack_slot,
|
yann@1
|
4185 |
+ gen_rtx_PLUS (SImode,
|
yann@1
|
4186 |
+ stack_slot,
|
yann@1
|
4187 |
+ stack_pointer_rtx)));
|
yann@1
|
4188 |
+ }
|
yann@1
|
4189 |
+ else
|
yann@1
|
4190 |
+ {
|
yann@1
|
4191 |
+ stack_slot = gen_rtx_PLUS (SImode,
|
yann@1
|
4192 |
+ stack_pointer_rtx,
|
yann@1
|
4193 |
+ GEN_INT (offset));
|
yann@1
|
4194 |
+ }
|
yann@1
|
4195 |
+
|
yann@1
|
4196 |
+ stack_slot = gen_rtx_MEM (SImode, stack_slot);
|
yann@1
|
4197 |
+
|
yann@1
|
4198 |
+ insn = emit_move_insn (gen_rtx_REG (SImode, regno), stack_slot);
|
yann@1
|
4199 |
+
|
yann@1
|
4200 |
+ return insn;
|
yann@1
|
4201 |
+}
|
yann@1
|
4202 |
+
|
yann@1
|
4203 |
+
|
yann@1
|
4204 |
+/* There are two possible paths for prologue expansion,
|
yann@1
|
4205 |
+- the first is if the total frame size is < 2^15-1. In that
|
yann@1
|
4206 |
+case all the immediates will fit into the 16-bit immediate
|
yann@1
|
4207 |
+fields.
|
yann@1
|
4208 |
+- the second is when the frame size is too big, in that
|
yann@1
|
4209 |
+case an additional temporary register is used, first
|
yann@1
|
4210 |
+as a cfa_temp to offset the sp, second as the cfa_store
|
yann@1
|
4211 |
+register.
|
yann@1
|
4212 |
+
|
yann@1
|
4213 |
+See the comment above dwarf2out_frame_debug_expr in
|
yann@1
|
4214 |
+dwarf2out.c for more explanation of the "rules."
|
yann@1
|
4215 |
+
|
yann@1
|
4216 |
+
|
yann@1
|
4217 |
+Case 1:
|
yann@1
|
4218 |
+Rule # Example Insn Effect
|
yann@1
|
4219 |
+2 addi sp, sp, -total_frame_size cfa.reg=sp, cfa.offset=total_frame_size
|
yann@1
|
4220 |
+ cfa_store.reg=sp, cfa_store.offset=total_frame_size
|
yann@1
|
4221 |
+12 stw ra, offset(sp)
|
yann@1
|
4222 |
+12 stw r16, offset(sp)
|
yann@1
|
4223 |
+1 mov fp, sp
|
yann@1
|
4224 |
+
|
yann@1
|
4225 |
+Case 2:
|
yann@1
|
4226 |
+Rule # Example Insn Effect
|
yann@1
|
4227 |
+6 movi r8, total_frame_size cfa_temp.reg=r8, cfa_temp.offset=total_frame_size
|
yann@1
|
4228 |
+2 sub sp, sp, r8 cfa.reg=sp, cfa.offset=total_frame_size
|
yann@1
|
4229 |
+ cfa_store.reg=sp, cfa_store.offset=total_frame_size
|
yann@1
|
4230 |
+5 add r8, r8, sp cfa_store.reg=r8, cfa_store.offset=0
|
yann@1
|
4231 |
+12 stw ra, offset(r8)
|
yann@1
|
4232 |
+12 stw r16, offset(r8)
|
yann@1
|
4233 |
+1 mov fp, sp
|
yann@1
|
4234 |
+
|
yann@1
|
4235 |
+*/
|
yann@1
|
4236 |
+
|
yann@1
|
4237 |
+void
|
yann@1
|
4238 |
+expand_prologue ()
|
yann@1
|
4239 |
+{
|
yann@1
|
4240 |
+ int i;
|
yann@1
|
4241 |
+ HOST_WIDE_INT total_frame_size;
|
yann@1
|
4242 |
+ int cfa_store_offset;
|
yann@1
|
4243 |
+ rtx insn;
|
yann@1
|
4244 |
+ rtx cfa_store_reg = 0;
|
yann@1
|
4245 |
+
|
yann@1
|
4246 |
+ total_frame_size = compute_frame_size ();
|
yann@1
|
4247 |
+
|
yann@1
|
4248 |
+ if (total_frame_size)
|
yann@1
|
4249 |
+ {
|
yann@1
|
4250 |
+
|
yann@1
|
4251 |
+ if (TOO_BIG_OFFSET (total_frame_size))
|
yann@1
|
4252 |
+ {
|
yann@1
|
4253 |
+ /* cfa_temp and cfa_store_reg are the same register,
|
yann@1
|
4254 |
+ cfa_store_reg overwrites cfa_temp */
|
yann@1
|
4255 |
+ cfa_store_reg = gen_rtx_REG (SImode, TEMP_REG_NUM);
|
yann@1
|
4256 |
+ insn = emit_insn (gen_rtx_SET (SImode,
|
yann@1
|
4257 |
+ cfa_store_reg,
|
yann@1
|
4258 |
+ GEN_INT (total_frame_size)));
|
yann@1
|
4259 |
+
|
yann@1
|
4260 |
+ RTX_FRAME_RELATED_P (insn) = 1;
|
yann@1
|
4261 |
+
|
yann@1
|
4262 |
+
|
yann@1
|
4263 |
+ insn = gen_rtx_SET (SImode,
|
yann@1
|
4264 |
+ stack_pointer_rtx,
|
yann@1
|
4265 |
+ gen_rtx_MINUS (SImode,
|
yann@1
|
4266 |
+ stack_pointer_rtx,
|
yann@1
|
4267 |
+ cfa_store_reg));
|
yann@1
|
4268 |
+
|
yann@1
|
4269 |
+ insn = emit_insn (insn);
|
yann@1
|
4270 |
+ RTX_FRAME_RELATED_P (insn) = 1;
|
yann@1
|
4271 |
+
|
yann@1
|
4272 |
+
|
yann@1
|
4273 |
+ /* if there are no registers to save, I don't need to
|
yann@1
|
4274 |
+ create a cfa_store */
|
yann@1
|
4275 |
+ if (cfun->machine->frame.save_reg_size)
|
yann@1
|
4276 |
+ {
|
yann@1
|
4277 |
+ insn = gen_rtx_SET (SImode,
|
yann@1
|
4278 |
+ cfa_store_reg,
|
yann@1
|
4279 |
+ gen_rtx_PLUS (SImode,
|
yann@1
|
4280 |
+ cfa_store_reg,
|
yann@1
|
4281 |
+ stack_pointer_rtx));
|
yann@1
|
4282 |
+
|
yann@1
|
4283 |
+ insn = emit_insn (insn);
|
yann@1
|
4284 |
+ RTX_FRAME_RELATED_P (insn) = 1;
|
yann@1
|
4285 |
+ }
|
yann@1
|
4286 |
+
|
yann@1
|
4287 |
+ cfa_store_offset
|
yann@1
|
4288 |
+ = total_frame_size
|
yann@1
|
4289 |
+ - (cfun->machine->frame.save_regs_offset
|
yann@1
|
4290 |
+ + cfun->machine->frame.save_reg_rounded);
|
yann@1
|
4291 |
+ }
|
yann@1
|
4292 |
+ else
|
yann@1
|
4293 |
+ {
|
yann@1
|
4294 |
+ insn = gen_rtx_SET (SImode,
|
yann@1
|
4295 |
+ stack_pointer_rtx,
|
yann@1
|
4296 |
+ gen_rtx_PLUS (SImode,
|
yann@1
|
4297 |
+ stack_pointer_rtx,
|
yann@1
|
4298 |
+ GEN_INT (-total_frame_size)));
|
yann@1
|
4299 |
+ insn = emit_insn (insn);
|
yann@1
|
4300 |
+ RTX_FRAME_RELATED_P (insn) = 1;
|
yann@1
|
4301 |
+
|
yann@1
|
4302 |
+ cfa_store_reg = stack_pointer_rtx;
|
yann@1
|
4303 |
+ cfa_store_offset
|
yann@1
|
4304 |
+ = cfun->machine->frame.save_regs_offset
|
yann@1
|
4305 |
+ + cfun->machine->frame.save_reg_rounded;
|
yann@1
|
4306 |
+ }
|
yann@1
|
4307 |
+ }
|
yann@1
|
4308 |
+
|
yann@1
|
4309 |
+ if (MUST_SAVE_REGISTER (RA_REGNO))
|
yann@1
|
4310 |
+ {
|
yann@1
|
4311 |
+ cfa_store_offset -= 4;
|
yann@1
|
4312 |
+ save_reg (RA_REGNO, cfa_store_offset, cfa_store_reg);
|
yann@1
|
4313 |
+ }
|
yann@1
|
4314 |
+ if (MUST_SAVE_REGISTER (FP_REGNO))
|
yann@1
|
4315 |
+ {
|
yann@1
|
4316 |
+ cfa_store_offset -= 4;
|
yann@1
|
4317 |
+ save_reg (FP_REGNO, cfa_store_offset, cfa_store_reg);
|
yann@1
|
4318 |
+ }
|
yann@1
|
4319 |
+
|
yann@1
|
4320 |
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
yann@1
|
4321 |
+ {
|
yann@1
|
4322 |
+ if (MUST_SAVE_REGISTER (i) && i != FP_REGNO && i != RA_REGNO)
|
yann@1
|
4323 |
+ {
|
yann@1
|
4324 |
+ cfa_store_offset -= 4;
|
yann@1
|
4325 |
+ save_reg (i, cfa_store_offset, cfa_store_reg);
|
yann@1
|
4326 |
+ }
|
yann@1
|
4327 |
+ }
|
yann@1
|
4328 |
+
|
yann@1
|
4329 |
+ if (frame_pointer_needed)
|
yann@1
|
4330 |
+ {
|
yann@1
|
4331 |
+ insn = emit_insn (gen_rtx_SET (SImode,
|
yann@1
|
4332 |
+ gen_rtx_REG (SImode, FP_REGNO),
|
yann@1
|
4333 |
+ gen_rtx_REG (SImode, SP_REGNO)));
|
yann@1
|
4334 |
+
|
yann@1
|
4335 |
+ RTX_FRAME_RELATED_P (insn) = 1;
|
yann@1
|
4336 |
+ }
|
yann@1
|
4337 |
+
|
yann@1
|
4338 |
+ /* If we are profiling, make sure no instructions are scheduled before
|
yann@1
|
4339 |
+ the call to mcount. */
|
yann@1
|
4340 |
+ if (current_function_profile)
|
yann@1
|
4341 |
+ emit_insn (gen_blockage ());
|
yann@1
|
4342 |
+}
|
yann@1
|
4343 |
+
|
yann@1
|
4344 |
+void
|
yann@1
|
4345 |
+expand_epilogue (bool sibcall_p)
|
yann@1
|
4346 |
+{
|
yann@1
|
4347 |
+ rtx insn;
|
yann@1
|
4348 |
+ int i;
|
yann@1
|
4349 |
+ HOST_WIDE_INT total_frame_size;
|
yann@1
|
4350 |
+ int register_store_offset;
|
yann@1
|
4351 |
+
|
yann@1
|
4352 |
+ total_frame_size = compute_frame_size ();
|
yann@1
|
4353 |
+
|
yann@1
|
4354 |
+ if (!sibcall_p && nios2_can_use_return_insn ())
|
yann@1
|
4355 |
+ {
|
yann@1
|
4356 |
+ insn = emit_jump_insn (gen_return ());
|
yann@1
|
4357 |
+ return;
|
yann@1
|
4358 |
+ }
|
yann@1
|
4359 |
+
|
yann@1
|
4360 |
+ emit_insn (gen_blockage ());
|
yann@1
|
4361 |
+
|
yann@1
|
4362 |
+ register_store_offset =
|
yann@1
|
4363 |
+ cfun->machine->frame.save_regs_offset +
|
yann@1
|
4364 |
+ cfun->machine->frame.save_reg_rounded;
|
yann@1
|
4365 |
+
|
yann@1
|
4366 |
+ if (MUST_SAVE_REGISTER (RA_REGNO))
|
yann@1
|
4367 |
+ {
|
yann@1
|
4368 |
+ register_store_offset -= 4;
|
yann@1
|
4369 |
+ restore_reg (RA_REGNO, register_store_offset);
|
yann@1
|
4370 |
+ }
|
yann@1
|
4371 |
+
|
yann@1
|
4372 |
+ if (MUST_SAVE_REGISTER (FP_REGNO))
|
yann@1
|
4373 |
+ {
|
yann@1
|
4374 |
+ register_store_offset -= 4;
|
yann@1
|
4375 |
+ restore_reg (FP_REGNO, register_store_offset);
|
yann@1
|
4376 |
+ }
|
yann@1
|
4377 |
+
|
yann@1
|
4378 |
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
yann@1
|
4379 |
+ {
|
yann@1
|
4380 |
+ if (MUST_SAVE_REGISTER (i) && i != FP_REGNO && i != RA_REGNO)
|
yann@1
|
4381 |
+ {
|
yann@1
|
4382 |
+ register_store_offset -= 4;
|
yann@1
|
4383 |
+ restore_reg (i, register_store_offset);
|
yann@1
|
4384 |
+ }
|
yann@1
|
4385 |
+ }
|
yann@1
|
4386 |
+
|
yann@1
|
4387 |
+ if (total_frame_size)
|
yann@1
|
4388 |
+ {
|
yann@1
|
4389 |
+ rtx sp_adjust;
|
yann@1
|
4390 |
+
|
yann@1
|
4391 |
+ if (TOO_BIG_OFFSET (total_frame_size))
|
yann@1
|
4392 |
+ {
|
yann@1
|
4393 |
+ sp_adjust = gen_rtx_REG (SImode, TEMP_REG_NUM);
|
yann@1
|
4394 |
+ insn = emit_insn (gen_rtx_SET (SImode,
|
yann@1
|
4395 |
+ sp_adjust,
|
yann@1
|
4396 |
+ GEN_INT (total_frame_size)));
|
yann@1
|
4397 |
+
|
yann@1
|
4398 |
+ }
|
yann@1
|
4399 |
+ else
|
yann@1
|
4400 |
+ {
|
yann@1
|
4401 |
+ sp_adjust = GEN_INT (total_frame_size);
|
yann@1
|
4402 |
+ }
|
yann@1
|
4403 |
+
|
yann@1
|
4404 |
+ insn = gen_rtx_SET (SImode,
|
yann@1
|
4405 |
+ stack_pointer_rtx,
|
yann@1
|
4406 |
+ gen_rtx_PLUS (SImode,
|
yann@1
|
4407 |
+ stack_pointer_rtx,
|
yann@1
|
4408 |
+ sp_adjust));
|
yann@1
|
4409 |
+ insn = emit_insn (insn);
|
yann@1
|
4410 |
+ }
|
yann@1
|
4411 |
+
|
yann@1
|
4412 |
+
|
yann@1
|
4413 |
+ if (!sibcall_p)
|
yann@1
|
4414 |
+ {
|
yann@1
|
4415 |
+ insn = emit_jump_insn (gen_return_from_epilogue (gen_rtx (REG, Pmode,
|
yann@1
|
4416 |
+ RA_REGNO)));
|
yann@1
|
4417 |
+ }
|
yann@1
|
4418 |
+}
|
yann@1
|
4419 |
+
|
yann@1
|
4420 |
+
|
yann@1
|
4421 |
+bool
|
yann@1
|
4422 |
+nios2_function_ok_for_sibcall (tree a ATTRIBUTE_UNUSED, tree b ATTRIBUTE_UNUSED)
|
yann@1
|
4423 |
+{
|
yann@1
|
4424 |
+ return true;
|
yann@1
|
4425 |
+}
|
yann@1
|
4426 |
+
|
yann@1
|
4427 |
+
|
yann@1
|
4428 |
+
|
yann@1
|
4429 |
+
|
yann@1
|
4430 |
+
|
yann@1
|
4431 |
+/* ----------------------- *
|
yann@1
|
4432 |
+ * Profiling
|
yann@1
|
4433 |
+ * ----------------------- */
|
yann@1
|
4434 |
+
|
yann@1
|
4435 |
+void
|
yann@1
|
4436 |
+function_profiler (FILE *file, int labelno)
|
yann@1
|
4437 |
+{
|
yann@1
|
4438 |
+ fprintf (file, "\t%s mcount begin, label: .LP%d\n",
|
yann@1
|
4439 |
+ ASM_COMMENT_START, labelno);
|
yann@1
|
4440 |
+ fprintf (file, "\tnextpc\tr8\n");
|
yann@1
|
4441 |
+ fprintf (file, "\tmov\tr9, ra\n");
|
yann@1
|
4442 |
+ fprintf (file, "\tmovhi\tr10, %%hiadj(.LP%d)\n", labelno);
|
yann@1
|
4443 |
+ fprintf (file, "\taddi\tr10, r10, %%lo(.LP%d)\n", labelno);
|
yann@1
|
4444 |
+ fprintf (file, "\tcall\tmcount\n");
|
yann@1
|
4445 |
+ fprintf (file, "\tmov\tra, r9\n");
|
yann@1
|
4446 |
+ fprintf (file, "\t%s mcount end\n", ASM_COMMENT_START);
|
yann@1
|
4447 |
+}
|
yann@1
|
4448 |
+
|
yann@1
|
4449 |
+
|
yann@1
|
4450 |
+/***************************************
|
yann@1
|
4451 |
+ * Stack Layout
|
yann@1
|
4452 |
+ ***************************************/
|
yann@1
|
4453 |
+
|
yann@1
|
4454 |
+
|
yann@1
|
4455 |
+void
|
yann@1
|
4456 |
+dump_frame_size (FILE *file)
|
yann@1
|
4457 |
+{
|
yann@1
|
4458 |
+ fprintf (file, "\t%s Current Frame Info\n", ASM_COMMENT_START);
|
yann@1
|
4459 |
+
|
yann@1
|
4460 |
+ fprintf (file, "\t%s total_size = %ld\n", ASM_COMMENT_START,
|
yann@1
|
4461 |
+ cfun->machine->frame.total_size);
|
yann@1
|
4462 |
+ fprintf (file, "\t%s var_size = %ld\n", ASM_COMMENT_START,
|
yann@1
|
4463 |
+ cfun->machine->frame.var_size);
|
yann@1
|
4464 |
+ fprintf (file, "\t%s args_size = %ld\n", ASM_COMMENT_START,
|
yann@1
|
4465 |
+ cfun->machine->frame.args_size);
|
yann@1
|
4466 |
+ fprintf (file, "\t%s save_reg_size = %d\n", ASM_COMMENT_START,
|
yann@1
|
4467 |
+ cfun->machine->frame.save_reg_size);
|
yann@1
|
4468 |
+ fprintf (file, "\t%s save_reg_rounded = %d\n", ASM_COMMENT_START,
|
yann@1
|
4469 |
+ cfun->machine->frame.save_reg_rounded);
|
yann@1
|
4470 |
+ fprintf (file, "\t%s initialized = %d\n", ASM_COMMENT_START,
|
yann@1
|
4471 |
+ cfun->machine->frame.initialized);
|
yann@1
|
4472 |
+ fprintf (file, "\t%s num_regs = %d\n", ASM_COMMENT_START,
|
yann@1
|
4473 |
+ cfun->machine->frame.num_regs);
|
yann@1
|
4474 |
+ fprintf (file, "\t%s save_regs_offset = %ld\n", ASM_COMMENT_START,
|
yann@1
|
4475 |
+ cfun->machine->frame.save_regs_offset);
|
yann@1
|
4476 |
+ fprintf (file, "\t%s current_function_is_leaf = %d\n", ASM_COMMENT_START,
|
yann@1
|
4477 |
+ current_function_is_leaf);
|
yann@1
|
4478 |
+ fprintf (file, "\t%s frame_pointer_needed = %d\n", ASM_COMMENT_START,
|
yann@1
|
4479 |
+ frame_pointer_needed);
|
yann@1
|
4480 |
+ fprintf (file, "\t%s pretend_args_size = %d\n", ASM_COMMENT_START,
|
yann@1
|
4481 |
+ current_function_pretend_args_size);
|
yann@1
|
4482 |
+
|
yann@1
|
4483 |
+}
|
yann@1
|
4484 |
+
|
yann@1
|
4485 |
+
|
yann@1
|
4486 |
+/* Return the bytes needed to compute the frame pointer from the current
|
yann@1
|
4487 |
+ stack pointer.
|
yann@1
|
4488 |
+*/
|
yann@1
|
4489 |
+
|
yann@1
|
4490 |
+HOST_WIDE_INT
|
yann@1
|
4491 |
+compute_frame_size ()
|
yann@1
|
4492 |
+{
|
yann@1
|
4493 |
+ unsigned int regno;
|
yann@1
|
4494 |
+ HOST_WIDE_INT var_size; /* # of var. bytes allocated */
|
yann@1
|
4495 |
+ HOST_WIDE_INT total_size; /* # bytes that the entire frame takes up */
|
yann@1
|
4496 |
+ HOST_WIDE_INT save_reg_size; /* # bytes needed to store callee save regs */
|
yann@1
|
4497 |
+ HOST_WIDE_INT save_reg_rounded;
|
yann@1
|
4498 |
+ /* # bytes needed to store callee save regs (rounded) */
|
yann@1
|
4499 |
+ HOST_WIDE_INT out_args_size; /* # bytes needed for outgoing args */
|
yann@1
|
4500 |
+
|
yann@1
|
4501 |
+ save_reg_size = 0;
|
yann@1
|
4502 |
+ var_size = STACK_ALIGN (get_frame_size ());
|
yann@1
|
4503 |
+ out_args_size = STACK_ALIGN (current_function_outgoing_args_size);
|
yann@1
|
4504 |
+
|
yann@1
|
4505 |
+ total_size = var_size + out_args_size;
|
yann@1
|
4506 |
+
|
yann@1
|
4507 |
+ /* Calculate space needed for gp registers. */
|
yann@1
|
4508 |
+ for (regno = 0; regno <= FIRST_PSEUDO_REGISTER; regno++)
|
yann@1
|
4509 |
+ {
|
yann@1
|
4510 |
+ if (MUST_SAVE_REGISTER (regno))
|
yann@1
|
4511 |
+ {
|
yann@1
|
4512 |
+ save_reg_size += 4;
|
yann@1
|
4513 |
+ }
|
yann@1
|
4514 |
+ }
|
yann@1
|
4515 |
+
|
yann@1
|
4516 |
+ save_reg_rounded = STACK_ALIGN (save_reg_size);
|
yann@1
|
4517 |
+ total_size += save_reg_rounded;
|
yann@1
|
4518 |
+
|
yann@1
|
4519 |
+ total_size += STACK_ALIGN (current_function_pretend_args_size);
|
yann@1
|
4520 |
+
|
yann@1
|
4521 |
+ /* Save other computed information. */
|
yann@1
|
4522 |
+ cfun->machine->frame.total_size = total_size;
|
yann@1
|
4523 |
+ cfun->machine->frame.var_size = var_size;
|
yann@1
|
4524 |
+ cfun->machine->frame.args_size = current_function_outgoing_args_size;
|
yann@1
|
4525 |
+ cfun->machine->frame.save_reg_size = save_reg_size;
|
yann@1
|
4526 |
+ cfun->machine->frame.save_reg_rounded = save_reg_rounded;
|
yann@1
|
4527 |
+ cfun->machine->frame.initialized = reload_completed;
|
yann@1
|
4528 |
+ cfun->machine->frame.num_regs = save_reg_size / UNITS_PER_WORD;
|
yann@1
|
4529 |
+
|
yann@1
|
4530 |
+ cfun->machine->frame.save_regs_offset
|
yann@1
|
4531 |
+ = save_reg_rounded ? current_function_outgoing_args_size + var_size : 0;
|
yann@1
|
4532 |
+
|
yann@1
|
4533 |
+ return total_size;
|
yann@1
|
4534 |
+}
|
yann@1
|
4535 |
+
|
yann@1
|
4536 |
+
|
yann@1
|
4537 |
+int
|
yann@1
|
4538 |
+nios2_initial_elimination_offset (int from, int to ATTRIBUTE_UNUSED)
|
yann@1
|
4539 |
+{
|
yann@1
|
4540 |
+ int offset;
|
yann@1
|
4541 |
+
|
yann@1
|
4542 |
+ /* Set OFFSET to the offset from the stack pointer. */
|
yann@1
|
4543 |
+ switch (from)
|
yann@1
|
4544 |
+ {
|
yann@1
|
4545 |
+ case FRAME_POINTER_REGNUM:
|
yann@1
|
4546 |
+ offset = 0;
|
yann@1
|
4547 |
+ break;
|
yann@1
|
4548 |
+
|
yann@1
|
4549 |
+ case ARG_POINTER_REGNUM:
|
yann@1
|
4550 |
+ compute_frame_size ();
|
yann@1
|
4551 |
+ offset = cfun->machine->frame.total_size;
|
yann@1
|
4552 |
+ offset -= current_function_pretend_args_size;
|
yann@1
|
4553 |
+ break;
|
yann@1
|
4554 |
+
|
yann@1
|
4555 |
+ case RETURN_ADDRESS_POINTER_REGNUM:
|
yann@1
|
4556 |
+ compute_frame_size ();
|
yann@1
|
4557 |
+ /* since the return address is always the first of the
|
yann@1
|
4558 |
+ saved registers, return the offset to the beginning
|
yann@1
|
4559 |
+ of the saved registers block */
|
yann@1
|
4560 |
+ offset = cfun->machine->frame.save_regs_offset;
|
yann@1
|
4561 |
+ break;
|
yann@1
|
4562 |
+
|
yann@1
|
4563 |
+ default:
|
yann@1
|
4564 |
+ abort ();
|
yann@1
|
4565 |
+ }
|
yann@1
|
4566 |
+
|
yann@1
|
4567 |
+ return offset;
|
yann@1
|
4568 |
+}
|
yann@1
|
4569 |
+
|
yann@1
|
4570 |
+/* Return nonzero if this function is known to have a null epilogue.
|
yann@1
|
4571 |
+ This allows the optimizer to omit jumps to jumps if no stack
|
yann@1
|
4572 |
+ was created. */
|
yann@1
|
4573 |
+int
|
yann@1
|
4574 |
+nios2_can_use_return_insn ()
|
yann@1
|
4575 |
+{
|
yann@1
|
4576 |
+ if (!reload_completed)
|
yann@1
|
4577 |
+ return 0;
|
yann@1
|
4578 |
+
|
yann@1
|
4579 |
+ if (regs_ever_live[RA_REGNO] || current_function_profile)
|
yann@1
|
4580 |
+ return 0;
|
yann@1
|
4581 |
+
|
yann@1
|
4582 |
+ if (cfun->machine->frame.initialized)
|
yann@1
|
4583 |
+ return cfun->machine->frame.total_size == 0;
|
yann@1
|
4584 |
+
|
yann@1
|
4585 |
+ return compute_frame_size () == 0;
|
yann@1
|
4586 |
+}
|
yann@1
|
4587 |
+
|
yann@1
|
4588 |
+
|
yann@1
|
4589 |
+
|
yann@1
|
4590 |
+
|
yann@1
|
4591 |
+
|
yann@1
|
4592 |
+/***************************************
|
yann@1
|
4593 |
+ *
|
yann@1
|
4594 |
+ ***************************************/
|
yann@1
|
4595 |
+
|
yann@1
|
4596 |
+const char *nios2_sys_nosys_string; /* for -msys=nosys */
|
yann@1
|
4597 |
+const char *nios2_sys_lib_string; /* for -msys-lib= */
|
yann@1
|
4598 |
+const char *nios2_sys_crt0_string; /* for -msys-crt0= */
|
yann@1
|
4599 |
+
|
yann@1
|
4600 |
+void
|
yann@1
|
4601 |
+override_options ()
|
yann@1
|
4602 |
+{
|
yann@1
|
4603 |
+ /* Function to allocate machine-dependent function status. */
|
yann@1
|
4604 |
+ init_machine_status = &nios2_init_machine_status;
|
yann@1
|
4605 |
+
|
yann@1
|
4606 |
+ nios2_section_threshold
|
yann@1
|
4607 |
+ = g_switch_set ? g_switch_value : NIOS2_DEFAULT_GVALUE;
|
yann@1
|
4608 |
+
|
yann@1
|
4609 |
+ if (nios2_sys_nosys_string && *nios2_sys_nosys_string)
|
yann@1
|
4610 |
+ {
|
yann@1
|
4611 |
+ error ("invalid option '-msys=nosys%s'", nios2_sys_nosys_string);
|
yann@1
|
4612 |
+ }
|
yann@1
|
4613 |
+
|
yann@1
|
4614 |
+ /* If we don't have mul, we don't have mulx either! */
|
yann@1
|
4615 |
+ if (!TARGET_HAS_MUL && TARGET_HAS_MULX)
|
yann@1
|
4616 |
+ {
|
yann@1
|
4617 |
+ target_flags &= ~HAS_MULX_FLAG;
|
yann@1
|
4618 |
+ }
|
yann@1
|
4619 |
+
|
yann@1
|
4620 |
+}
|
yann@1
|
4621 |
+
|
yann@1
|
4622 |
+void
|
yann@1
|
4623 |
+optimization_options (int level, int size)
|
yann@1
|
4624 |
+{
|
yann@1
|
4625 |
+ if (level || size)
|
yann@1
|
4626 |
+ {
|
yann@1
|
4627 |
+ target_flags |= INLINE_MEMCPY_FLAG;
|
yann@1
|
4628 |
+ }
|
yann@1
|
4629 |
+
|
yann@1
|
4630 |
+ if (level >= 3 && !size)
|
yann@1
|
4631 |
+ {
|
yann@1
|
4632 |
+ target_flags |= FAST_SW_DIV_FLAG;
|
yann@1
|
4633 |
+ }
|
yann@1
|
4634 |
+}
|
yann@1
|
4635 |
+
|
yann@1
|
4636 |
+/* Allocate a chunk of memory for per-function machine-dependent data. */
|
yann@1
|
4637 |
+static struct machine_function *
|
yann@1
|
4638 |
+nios2_init_machine_status ()
|
yann@1
|
4639 |
+{
|
yann@1
|
4640 |
+ return ((struct machine_function *)
|
yann@1
|
4641 |
+ ggc_alloc_cleared (sizeof (struct machine_function)));
|
yann@1
|
4642 |
+}
|
yann@1
|
4643 |
+
|
yann@1
|
4644 |
+
|
yann@1
|
4645 |
+
|
yann@1
|
4646 |
+/*****************
|
yann@1
|
4647 |
+ * Describing Relative Costs of Operations
|
yann@1
|
4648 |
+ *****************/
|
yann@1
|
4649 |
+
|
yann@1
|
4650 |
+/* Compute a (partial) cost for rtx X. Return true if the complete
|
yann@1
|
4651 |
+ cost has been computed, and false if subexpressions should be
|
yann@1
|
4652 |
+ scanned. In either case, *TOTAL contains the cost result. */
|
yann@1
|
4653 |
+
|
yann@1
|
4654 |
+
|
yann@1
|
4655 |
+
|
yann@1
|
4656 |
+static bool
|
yann@1
|
4657 |
+nios2_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total)
|
yann@1
|
4658 |
+{
|
yann@1
|
4659 |
+ switch (code)
|
yann@1
|
4660 |
+ {
|
yann@1
|
4661 |
+ case CONST_INT:
|
yann@1
|
4662 |
+ if (INTVAL (x) == 0)
|
yann@1
|
4663 |
+ {
|
yann@1
|
4664 |
+ *total = COSTS_N_INSNS (0);
|
yann@1
|
4665 |
+ return true;
|
yann@1
|
4666 |
+ }
|
yann@1
|
4667 |
+ else if (SMALL_INT (INTVAL (x))
|
yann@1
|
4668 |
+ || SMALL_INT_UNSIGNED (INTVAL (x))
|
yann@1
|
4669 |
+ || UPPER16_INT (INTVAL (x)))
|
yann@1
|
4670 |
+ {
|
yann@1
|
4671 |
+ *total = COSTS_N_INSNS (2);
|
yann@1
|
4672 |
+ return true;
|
yann@1
|
4673 |
+ }
|
yann@1
|
4674 |
+ else
|
yann@1
|
4675 |
+ {
|
yann@1
|
4676 |
+ *total = COSTS_N_INSNS (4);
|
yann@1
|
4677 |
+ return true;
|
yann@1
|
4678 |
+ }
|
yann@1
|
4679 |
+
|
yann@1
|
4680 |
+ case LABEL_REF:
|
yann@1
|
4681 |
+ case SYMBOL_REF:
|
yann@1
|
4682 |
+ /* ??? gp relative stuff will fit in here */
|
yann@1
|
4683 |
+ /* fall through */
|
yann@1
|
4684 |
+ case CONST:
|
yann@1
|
4685 |
+ case CONST_DOUBLE:
|
yann@1
|
4686 |
+ {
|
yann@1
|
4687 |
+ *total = COSTS_N_INSNS (4);
|
yann@1
|
4688 |
+ return true;
|
yann@1
|
4689 |
+ }
|
yann@1
|
4690 |
+
|
yann@1
|
4691 |
+ case MULT:
|
yann@1
|
4692 |
+ {
|
yann@1
|
4693 |
+ *total = COSTS_N_INSNS (1);
|
yann@1
|
4694 |
+ return false;
|
yann@1
|
4695 |
+ }
|
yann@1
|
4696 |
+ case SIGN_EXTEND:
|
yann@1
|
4697 |
+ {
|
yann@1
|
4698 |
+ *total = COSTS_N_INSNS (3);
|
yann@1
|
4699 |
+ return false;
|
yann@1
|
4700 |
+ }
|
yann@1
|
4701 |
+ case ZERO_EXTEND:
|
yann@1
|
4702 |
+ {
|
yann@1
|
4703 |
+ *total = COSTS_N_INSNS (1);
|
yann@1
|
4704 |
+ return false;
|
yann@1
|
4705 |
+ }
|
yann@1
|
4706 |
+
|
yann@1
|
4707 |
+ default:
|
yann@1
|
4708 |
+ return false;
|
yann@1
|
4709 |
+ }
|
yann@1
|
4710 |
+}
|
yann@1
|
4711 |
+
|
yann@1
|
4712 |
+
|
yann@1
|
4713 |
+/***************************************
|
yann@1
|
4714 |
+ * INSTRUCTION SUPPORT
|
yann@1
|
4715 |
+ *
|
yann@1
|
4716 |
+ * These functions are used within the Machine Description to
|
yann@1
|
4717 |
+ * handle common or complicated output and expansions from
|
yann@1
|
4718 |
+ * instructions.
|
yann@1
|
4719 |
+ ***************************************/
|
yann@1
|
4720 |
+
|
yann@1
|
4721 |
+int
|
yann@1
|
4722 |
+nios2_emit_move_sequence (rtx *operands, enum machine_mode mode)
|
yann@1
|
4723 |
+{
|
yann@1
|
4724 |
+ rtx to = operands[0];
|
yann@1
|
4725 |
+ rtx from = operands[1];
|
yann@1
|
4726 |
+
|
yann@1
|
4727 |
+ if (!register_operand (to, mode) && !reg_or_0_operand (from, mode))
|
yann@1
|
4728 |
+ {
|
yann@1
|
4729 |
+ if (no_new_pseudos)
|
yann@1
|
4730 |
+ internal_error ("Trying to force_reg no_new_pseudos == 1");
|
yann@1
|
4731 |
+ from = copy_to_mode_reg (mode, from);
|
yann@1
|
4732 |
+ }
|
yann@1
|
4733 |
+
|
yann@1
|
4734 |
+ operands[0] = to;
|
yann@1
|
4735 |
+ operands[1] = from;
|
yann@1
|
4736 |
+ return 0;
|
yann@1
|
4737 |
+}
|
yann@1
|
4738 |
+
|
yann@1
|
4739 |
+/* Divide Support */
|
yann@1
|
4740 |
+
|
yann@1
|
4741 |
+/*
|
yann@1
|
4742 |
+ If -O3 is used, we want to output a table lookup for
|
yann@1
|
4743 |
+ divides between small numbers (both num and den >= 0
|
yann@1
|
4744 |
+ and < 0x10). The overhead of this method in the worse
|
yann@1
|
4745 |
+ case is 40 bytes in the text section (10 insns) and
|
yann@1
|
4746 |
+ 256 bytes in the data section. Additional divides do
|
yann@1
|
4747 |
+ not incur additional penalties in the data section.
|
yann@1
|
4748 |
+
|
yann@1
|
4749 |
+ Code speed is improved for small divides by about 5x
|
yann@1
|
4750 |
+ when using this method in the worse case (~9 cycles
|
yann@1
|
4751 |
+ vs ~45). And in the worse case divides not within the
|
yann@1
|
4752 |
+ table are penalized by about 10% (~5 cycles vs ~45).
|
yann@1
|
4753 |
+ However in the typical case the penalty is not as bad
|
yann@1
|
4754 |
+ because doing the long divide in only 45 cycles is
|
yann@1
|
4755 |
+ quite optimistic.
|
yann@1
|
4756 |
+
|
yann@1
|
4757 |
+ ??? It would be nice to have some benchmarks other
|
yann@1
|
4758 |
+ than Dhrystone to back this up.
|
yann@1
|
4759 |
+
|
yann@1
|
4760 |
+ This bit of expansion is to create this instruction
|
yann@1
|
4761 |
+ sequence as rtl.
|
yann@1
|
4762 |
+ or $8, $4, $5
|
yann@1
|
4763 |
+ slli $9, $4, 4
|
yann@1
|
4764 |
+ cmpgeui $3, $8, 16
|
yann@1
|
4765 |
+ beq $3, $0, .L3
|
yann@1
|
4766 |
+ or $10, $9, $5
|
yann@1
|
4767 |
+ add $12, $11, divide_table
|
yann@1
|
4768 |
+ ldbu $2, 0($12)
|
yann@1
|
4769 |
+ br .L1
|
yann@1
|
4770 |
+.L3:
|
yann@1
|
4771 |
+ call slow_div
|
yann@1
|
4772 |
+.L1:
|
yann@1
|
4773 |
+# continue here with result in $2
|
yann@1
|
4774 |
+
|
yann@1
|
4775 |
+ ??? Ideally I would like the emit libcall block to contain
|
yann@1
|
4776 |
+ all of this code, but I don't know how to do that. What it
|
yann@1
|
4777 |
+ means is that if the divide can be eliminated, it may not
|
yann@1
|
4778 |
+ completely disappear.
|
yann@1
|
4779 |
+
|
yann@1
|
4780 |
+ ??? The __divsi3_table label should ideally be moved out
|
yann@1
|
4781 |
+ of this block and into a global. If it is placed into the
|
yann@1
|
4782 |
+ sdata section we can save even more cycles by doing things
|
yann@1
|
4783 |
+ gp relative.
|
yann@1
|
4784 |
+*/
|
yann@1
|
4785 |
+int
|
yann@1
|
4786 |
+nios2_emit_expensive_div (rtx *operands, enum machine_mode mode)
|
yann@1
|
4787 |
+{
|
yann@1
|
4788 |
+ rtx or_result, shift_left_result;
|
yann@1
|
4789 |
+ rtx lookup_value;
|
yann@1
|
4790 |
+ rtx lab1, lab3;
|
yann@1
|
4791 |
+ rtx insns;
|
yann@1
|
4792 |
+ rtx libfunc;
|
yann@1
|
4793 |
+ rtx final_result;
|
yann@1
|
4794 |
+ rtx tmp;
|
yann@1
|
4795 |
+
|
yann@1
|
4796 |
+ /* it may look a little generic, but only SImode
|
yann@1
|
4797 |
+ is supported for now */
|
yann@1
|
4798 |
+ if (mode != SImode)
|
yann@1
|
4799 |
+ abort ();
|
yann@1
|
4800 |
+
|
yann@1
|
4801 |
+ libfunc = sdiv_optab->handlers[(int) SImode].libfunc;
|
yann@1
|
4802 |
+
|
yann@1
|
4803 |
+
|
yann@1
|
4804 |
+
|
yann@1
|
4805 |
+ lab1 = gen_label_rtx ();
|
yann@1
|
4806 |
+ lab3 = gen_label_rtx ();
|
yann@1
|
4807 |
+
|
yann@1
|
4808 |
+ or_result = expand_simple_binop (SImode, IOR,
|
yann@1
|
4809 |
+ operands[1], operands[2],
|
yann@1
|
4810 |
+ 0, 0, OPTAB_LIB_WIDEN);
|
yann@1
|
4811 |
+
|
yann@1
|
4812 |
+ emit_cmp_and_jump_insns (or_result, GEN_INT (15), GTU, 0,
|
yann@1
|
4813 |
+ GET_MODE (or_result), 0, lab3);
|
yann@1
|
4814 |
+ JUMP_LABEL (get_last_insn ()) = lab3;
|
yann@1
|
4815 |
+
|
yann@1
|
4816 |
+ shift_left_result = expand_simple_binop (SImode, ASHIFT,
|
yann@1
|
4817 |
+ operands[1], GEN_INT (4),
|
yann@1
|
4818 |
+ 0, 0, OPTAB_LIB_WIDEN);
|
yann@1
|
4819 |
+
|
yann@1
|
4820 |
+ lookup_value = expand_simple_binop (SImode, IOR,
|
yann@1
|
4821 |
+ shift_left_result, operands[2],
|
yann@1
|
4822 |
+ 0, 0, OPTAB_LIB_WIDEN);
|
yann@1
|
4823 |
+
|
yann@1
|
4824 |
+ convert_move (operands[0],
|
yann@1
|
4825 |
+ gen_rtx (MEM, QImode,
|
yann@1
|
4826 |
+ gen_rtx (PLUS, SImode,
|
yann@1
|
4827 |
+ lookup_value,
|
yann@1
|
4828 |
+ gen_rtx_SYMBOL_REF (SImode, "__divsi3_table"))),
|
yann@1
|
4829 |
+ 1);
|
yann@1
|
4830 |
+
|
yann@1
|
4831 |
+
|
yann@1
|
4832 |
+ tmp = emit_jump_insn (gen_jump (lab1));
|
yann@1
|
4833 |
+ JUMP_LABEL (tmp) = lab1;
|
yann@1
|
4834 |
+ emit_barrier ();
|
yann@1
|
4835 |
+
|
yann@1
|
4836 |
+ emit_label (lab3);
|
yann@1
|
4837 |
+ LABEL_NUSES (lab3) = 1;
|
yann@1
|
4838 |
+
|
yann@1
|
4839 |
+ start_sequence ();
|
yann@1
|
4840 |
+ final_result = emit_library_call_value (libfunc, NULL_RTX,
|
yann@1
|
4841 |
+ LCT_CONST, SImode, 2,
|
yann@1
|
4842 |
+ operands[1], SImode,
|
yann@1
|
4843 |
+ operands[2], SImode);
|
yann@1
|
4844 |
+
|
yann@1
|
4845 |
+
|
yann@1
|
4846 |
+ insns = get_insns ();
|
yann@1
|
4847 |
+ end_sequence ();
|
yann@1
|
4848 |
+ emit_libcall_block (insns, operands[0], final_result,
|
yann@1
|
4849 |
+ gen_rtx (DIV, SImode, operands[1], operands[2]));
|
yann@1
|
4850 |
+
|
yann@1
|
4851 |
+ emit_label (lab1);
|
yann@1
|
4852 |
+ LABEL_NUSES (lab1) = 1;
|
yann@1
|
4853 |
+ return 1;
|
yann@1
|
4854 |
+}
|
yann@1
|
4855 |
+
|
yann@1
|
4856 |
+/* Branches/Compares */
|
yann@1
|
4857 |
+
|
yann@1
|
4858 |
+/* the way of handling branches/compares
|
yann@1
|
4859 |
+ in gcc is heavily borrowed from MIPS */
|
yann@1
|
4860 |
+
|
yann@1
|
4861 |
+enum internal_test
|
yann@1
|
4862 |
+{
|
yann@1
|
4863 |
+ ITEST_EQ,
|
yann@1
|
4864 |
+ ITEST_NE,
|
yann@1
|
4865 |
+ ITEST_GT,
|
yann@1
|
4866 |
+ ITEST_GE,
|
yann@1
|
4867 |
+ ITEST_LT,
|
yann@1
|
4868 |
+ ITEST_LE,
|
yann@1
|
4869 |
+ ITEST_GTU,
|
yann@1
|
4870 |
+ ITEST_GEU,
|
yann@1
|
4871 |
+ ITEST_LTU,
|
yann@1
|
4872 |
+ ITEST_LEU,
|
yann@1
|
4873 |
+ ITEST_MAX
|
yann@1
|
4874 |
+};
|
yann@1
|
4875 |
+
|
yann@1
|
4876 |
+static enum internal_test map_test_to_internal_test (enum rtx_code);
|
yann@1
|
4877 |
+
|
yann@1
|
4878 |
+/* Cached operands, and operator to compare for use in set/branch/trap
|
yann@1
|
4879 |
+ on condition codes. */
|
yann@1
|
4880 |
+rtx branch_cmp[2];
|
yann@1
|
4881 |
+enum cmp_type branch_type;
|
yann@1
|
4882 |
+
|
yann@1
|
4883 |
+/* Make normal rtx_code into something we can index from an array */
|
yann@1
|
4884 |
+
|
yann@1
|
4885 |
+static enum internal_test
|
yann@1
|
4886 |
+map_test_to_internal_test (enum rtx_code test_code)
|
yann@1
|
4887 |
+{
|
yann@1
|
4888 |
+ enum internal_test test = ITEST_MAX;
|
yann@1
|
4889 |
+
|
yann@1
|
4890 |
+ switch (test_code)
|
yann@1
|
4891 |
+ {
|
yann@1
|
4892 |
+ case EQ:
|
yann@1
|
4893 |
+ test = ITEST_EQ;
|
yann@1
|
4894 |
+ break;
|
yann@1
|
4895 |
+ case NE:
|
yann@1
|
4896 |
+ test = ITEST_NE;
|
yann@1
|
4897 |
+ break;
|
yann@1
|
4898 |
+ case GT:
|
yann@1
|
4899 |
+ test = ITEST_GT;
|
yann@1
|
4900 |
+ break;
|
yann@1
|
4901 |
+ case GE:
|
yann@1
|
4902 |
+ test = ITEST_GE;
|
yann@1
|
4903 |
+ break;
|
yann@1
|
4904 |
+ case LT:
|
yann@1
|
4905 |
+ test = ITEST_LT;
|
yann@1
|
4906 |
+ break;
|
yann@1
|
4907 |
+ case LE:
|
yann@1
|
4908 |
+ test = ITEST_LE;
|
yann@1
|
4909 |
+ break;
|
yann@1
|
4910 |
+ case GTU:
|
yann@1
|
4911 |
+ test = ITEST_GTU;
|
yann@1
|
4912 |
+ break;
|
yann@1
|
4913 |
+ case GEU:
|
yann@1
|
4914 |
+ test = ITEST_GEU;
|
yann@1
|
4915 |
+ break;
|
yann@1
|
4916 |
+ case LTU:
|
yann@1
|
4917 |
+ test = ITEST_LTU;
|
yann@1
|
4918 |
+ break;
|
yann@1
|
4919 |
+ case LEU:
|
yann@1
|
4920 |
+ test = ITEST_LEU;
|
yann@1
|
4921 |
+ break;
|
yann@1
|
4922 |
+ default:
|
yann@1
|
4923 |
+ break;
|
yann@1
|
4924 |
+ }
|
yann@1
|
4925 |
+
|
yann@1
|
4926 |
+ return test;
|
yann@1
|
4927 |
+}
|
yann@1
|
4928 |
+
|
yann@1
|
4929 |
+/* Generate the code to compare (and possibly branch) two integer values
|
yann@1
|
4930 |
+ TEST_CODE is the comparison code we are trying to emulate
|
yann@1
|
4931 |
+ (or implement directly)
|
yann@1
|
4932 |
+ RESULT is where to store the result of the comparison,
|
yann@1
|
4933 |
+ or null to emit a branch
|
yann@1
|
4934 |
+ CMP0 CMP1 are the two comparison operands
|
yann@1
|
4935 |
+ DESTINATION is the destination of the branch, or null to only compare
|
yann@1
|
4936 |
+ */
|
yann@1
|
4937 |
+
|
yann@1
|
4938 |
+void
|
yann@1
|
4939 |
+gen_int_relational (enum rtx_code test_code, /* relational test (EQ, etc) */
|
yann@1
|
4940 |
+ rtx result, /* result to store comp. or 0 if branch */
|
yann@1
|
4941 |
+ rtx cmp0, /* first operand to compare */
|
yann@1
|
4942 |
+ rtx cmp1, /* second operand to compare */
|
yann@1
|
4943 |
+ rtx destination) /* destination of the branch, or 0 if compare */
|
yann@1
|
4944 |
+{
|
yann@1
|
4945 |
+ struct cmp_info
|
yann@1
|
4946 |
+ {
|
yann@1
|
4947 |
+ /* for register (or 0) compares */
|
yann@1
|
4948 |
+ enum rtx_code test_code_reg; /* code to use in instruction (LT vs. LTU) */
|
yann@1
|
4949 |
+ int reverse_regs; /* reverse registers in test */
|
yann@1
|
4950 |
+
|
yann@1
|
4951 |
+ /* for immediate compares */
|
yann@1
|
4952 |
+ enum rtx_code test_code_const;
|
yann@1
|
4953 |
+ /* code to use in instruction (LT vs. LTU) */
|
yann@1
|
4954 |
+ int const_low; /* low bound of constant we can accept */
|
yann@1
|
4955 |
+ int const_high; /* high bound of constant we can accept */
|
yann@1
|
4956 |
+ int const_add; /* constant to add */
|
yann@1
|
4957 |
+
|
yann@1
|
4958 |
+ /* generic info */
|
yann@1
|
4959 |
+ int unsignedp; /* != 0 for unsigned comparisons. */
|
yann@1
|
4960 |
+ };
|
yann@1
|
4961 |
+
|
yann@1
|
4962 |
+ static const struct cmp_info info[(int) ITEST_MAX] = {
|
yann@1
|
4963 |
+
|
yann@1
|
4964 |
+ {EQ, 0, EQ, -32768, 32767, 0, 0}, /* EQ */
|
yann@1
|
4965 |
+ {NE, 0, NE, -32768, 32767, 0, 0}, /* NE */
|
yann@1
|
4966 |
+
|
yann@1
|
4967 |
+ {LT, 1, GE, -32769, 32766, 1, 0}, /* GT */
|
yann@1
|
4968 |
+ {GE, 0, GE, -32768, 32767, 0, 0}, /* GE */
|
yann@1
|
4969 |
+ {LT, 0, LT, -32768, 32767, 0, 0}, /* LT */
|
yann@1
|
4970 |
+ {GE, 1, LT, -32769, 32766, 1, 0}, /* LE */
|
yann@1
|
4971 |
+
|
yann@1
|
4972 |
+ {LTU, 1, GEU, 0, 65534, 1, 0}, /* GTU */
|
yann@1
|
4973 |
+ {GEU, 0, GEU, 0, 65535, 0, 0}, /* GEU */
|
yann@1
|
4974 |
+ {LTU, 0, LTU, 0, 65535, 0, 0}, /* LTU */
|
yann@1
|
4975 |
+ {GEU, 1, LTU, 0, 65534, 1, 0}, /* LEU */
|
yann@1
|
4976 |
+ };
|
yann@1
|
4977 |
+
|
yann@1
|
4978 |
+ enum internal_test test;
|
yann@1
|
4979 |
+ enum machine_mode mode;
|
yann@1
|
4980 |
+ const struct cmp_info *p_info;
|
yann@1
|
4981 |
+ int branch_p;
|
yann@1
|
4982 |
+
|
yann@1
|
4983 |
+
|
yann@1
|
4984 |
+
|
yann@1
|
4985 |
+
|
yann@1
|
4986 |
+ test = map_test_to_internal_test (test_code);
|
yann@1
|
4987 |
+ if (test == ITEST_MAX)
|
yann@1
|
4988 |
+ abort ();
|
yann@1
|
4989 |
+
|
yann@1
|
4990 |
+ p_info = &info[(int) test];
|
yann@1
|
4991 |
+
|
yann@1
|
4992 |
+ mode = GET_MODE (cmp0);
|
yann@1
|
4993 |
+ if (mode == VOIDmode)
|
yann@1
|
4994 |
+ mode = GET_MODE (cmp1);
|
yann@1
|
4995 |
+
|
yann@1
|
4996 |
+ branch_p = (destination != 0);
|
yann@1
|
4997 |
+
|
yann@1
|
4998 |
+ /* We can't, under any circumstances, have const_ints in cmp0
|
yann@1
|
4999 |
+ ??? Actually we could have const0 */
|
yann@1
|
5000 |
+ if (GET_CODE (cmp0) == CONST_INT)
|
yann@1
|
5001 |
+ cmp0 = force_reg (mode, cmp0);
|
yann@1
|
5002 |
+
|
yann@1
|
5003 |
+ /* if the comparison is against an int not in legal range
|
yann@1
|
5004 |
+ move it into a register */
|
yann@1
|
5005 |
+ if (GET_CODE (cmp1) == CONST_INT)
|
yann@1
|
5006 |
+ {
|
yann@1
|
5007 |
+ HOST_WIDE_INT value = INTVAL (cmp1);
|
yann@1
|
5008 |
+
|
yann@1
|
5009 |
+ if (value < p_info->const_low || value > p_info->const_high)
|
yann@1
|
5010 |
+ cmp1 = force_reg (mode, cmp1);
|
yann@1
|
5011 |
+ }
|
yann@1
|
5012 |
+
|
yann@1
|
5013 |
+ /* Comparison to constants, may involve adding 1 to change a GT into GE.
|
yann@1
|
5014 |
+ Comparison between two registers, may involve switching operands. */
|
yann@1
|
5015 |
+ if (GET_CODE (cmp1) == CONST_INT)
|
yann@1
|
5016 |
+ {
|
yann@1
|
5017 |
+ if (p_info->const_add != 0)
|
yann@1
|
5018 |
+ {
|
yann@1
|
5019 |
+ HOST_WIDE_INT new = INTVAL (cmp1) + p_info->const_add;
|
yann@1
|
5020 |
+
|
yann@1
|
5021 |
+ /* If modification of cmp1 caused overflow,
|
yann@1
|
5022 |
+ we would get the wrong answer if we follow the usual path;
|
yann@1
|
5023 |
+ thus, x > 0xffffffffU would turn into x > 0U. */
|
yann@1
|
5024 |
+ if ((p_info->unsignedp
|
yann@1
|
5025 |
+ ? (unsigned HOST_WIDE_INT) new >
|
yann@1
|
5026 |
+ (unsigned HOST_WIDE_INT) INTVAL (cmp1)
|
yann@1
|
5027 |
+ : new > INTVAL (cmp1)) != (p_info->const_add > 0))
|
yann@1
|
5028 |
+ {
|
yann@1
|
5029 |
+ /* ??? This case can never happen with the current numbers,
|
yann@1
|
5030 |
+ but I am paranoid and would rather an abort than
|
yann@1
|
5031 |
+ a bug I will never find */
|
yann@1
|
5032 |
+ abort ();
|
yann@1
|
5033 |
+ }
|
yann@1
|
5034 |
+ else
|
yann@1
|
5035 |
+ cmp1 = GEN_INT (new);
|
yann@1
|
5036 |
+ }
|
yann@1
|
5037 |
+ }
|
yann@1
|
5038 |
+
|
yann@1
|
5039 |
+ else if (p_info->reverse_regs)
|
yann@1
|
5040 |
+ {
|
yann@1
|
5041 |
+ rtx temp = cmp0;
|
yann@1
|
5042 |
+ cmp0 = cmp1;
|
yann@1
|
5043 |
+ cmp1 = temp;
|
yann@1
|
5044 |
+ }
|
yann@1
|
5045 |
+
|
yann@1
|
5046 |
+
|
yann@1
|
5047 |
+
|
yann@1
|
5048 |
+ if (branch_p)
|
yann@1
|
5049 |
+ {
|
yann@1
|
5050 |
+ if (register_operand (cmp0, mode) && register_operand (cmp1, mode))
|
yann@1
|
5051 |
+ {
|
yann@1
|
5052 |
+ rtx insn;
|
yann@1
|
5053 |
+ rtx cond = gen_rtx (p_info->test_code_reg, mode, cmp0, cmp1);
|
yann@1
|
5054 |
+ rtx label = gen_rtx_LABEL_REF (VOIDmode, destination);
|
yann@1
|
5055 |
+
|
yann@1
|
5056 |
+ insn = gen_rtx_SET (VOIDmode, pc_rtx,
|
yann@1
|
5057 |
+ gen_rtx_IF_THEN_ELSE (VOIDmode,
|
yann@1
|
5058 |
+ cond, label, pc_rtx));
|
yann@1
|
5059 |
+ emit_jump_insn (insn);
|
yann@1
|
5060 |
+ }
|
yann@1
|
5061 |
+ else
|
yann@1
|
5062 |
+ {
|
yann@1
|
5063 |
+ rtx cond, label;
|
yann@1
|
5064 |
+
|
yann@1
|
5065 |
+ result = gen_reg_rtx (mode);
|
yann@1
|
5066 |
+
|
yann@1
|
5067 |
+ emit_move_insn (result,
|
yann@1
|
5068 |
+ gen_rtx (p_info->test_code_const, mode, cmp0,
|
yann@1
|
5069 |
+ cmp1));
|
yann@1
|
5070 |
+
|
yann@1
|
5071 |
+ cond = gen_rtx (NE, mode, result, const0_rtx);
|
yann@1
|
5072 |
+ label = gen_rtx_LABEL_REF (VOIDmode, destination);
|
yann@1
|
5073 |
+
|
yann@1
|
5074 |
+ emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
|
yann@1
|
5075 |
+ gen_rtx_IF_THEN_ELSE (VOIDmode,
|
yann@1
|
5076 |
+ cond,
|
yann@1
|
5077 |
+ label, pc_rtx)));
|
yann@1
|
5078 |
+ }
|
yann@1
|
5079 |
+ }
|
yann@1
|
5080 |
+ else
|
yann@1
|
5081 |
+ {
|
yann@1
|
5082 |
+ if (register_operand (cmp0, mode) && register_operand (cmp1, mode))
|
yann@1
|
5083 |
+ {
|
yann@1
|
5084 |
+ emit_move_insn (result,
|
yann@1
|
5085 |
+ gen_rtx (p_info->test_code_reg, mode, cmp0, cmp1));
|
yann@1
|
5086 |
+ }
|
yann@1
|
5087 |
+ else
|
yann@1
|
5088 |
+ {
|
yann@1
|
5089 |
+ emit_move_insn (result,
|
yann@1
|
5090 |
+ gen_rtx (p_info->test_code_const, mode, cmp0,
|
yann@1
|
5091 |
+ cmp1));
|
yann@1
|
5092 |
+ }
|
yann@1
|
5093 |
+ }
|
yann@1
|
5094 |
+
|
yann@1
|
5095 |
+}
|
yann@1
|
5096 |
+
|
yann@1
|
5097 |
+
|
yann@1
|
5098 |
+/* ??? For now conditional moves are only supported
|
yann@1
|
5099 |
+ when the mode of the operands being compared are
|
yann@1
|
5100 |
+ the same as the ones being moved */
|
yann@1
|
5101 |
+
|
yann@1
|
5102 |
+void
|
yann@1
|
5103 |
+gen_conditional_move (rtx *operands, enum machine_mode mode)
|
yann@1
|
5104 |
+{
|
yann@1
|
5105 |
+ rtx insn, cond;
|
yann@1
|
5106 |
+ rtx cmp_reg = gen_reg_rtx (mode);
|
yann@1
|
5107 |
+ enum rtx_code cmp_code = GET_CODE (operands[1]);
|
yann@1
|
5108 |
+ enum rtx_code move_code = EQ;
|
yann@1
|
5109 |
+
|
yann@1
|
5110 |
+ /* emit a comparison if it is not "simple".
|
yann@1
|
5111 |
+ Simple comparisons are X eq 0 and X ne 0 */
|
yann@1
|
5112 |
+ if ((cmp_code == EQ || cmp_code == NE) && branch_cmp[1] == const0_rtx)
|
yann@1
|
5113 |
+ {
|
yann@1
|
5114 |
+ cmp_reg = branch_cmp[0];
|
yann@1
|
5115 |
+ move_code = cmp_code;
|
yann@1
|
5116 |
+ }
|
yann@1
|
5117 |
+ else if ((cmp_code == EQ || cmp_code == NE) && branch_cmp[0] == const0_rtx)
|
yann@1
|
5118 |
+ {
|
yann@1
|
5119 |
+ cmp_reg = branch_cmp[1];
|
yann@1
|
5120 |
+ move_code = cmp_code == EQ ? NE : EQ;
|
yann@1
|
5121 |
+ }
|
yann@1
|
5122 |
+ else
|
yann@1
|
5123 |
+ gen_int_relational (cmp_code, cmp_reg, branch_cmp[0], branch_cmp[1],
|
yann@1
|
5124 |
+ NULL_RTX);
|
yann@1
|
5125 |
+
|
yann@1
|
5126 |
+ cond = gen_rtx (move_code, VOIDmode, cmp_reg, CONST0_RTX (mode));
|
yann@1
|
5127 |
+ insn = gen_rtx_SET (mode, operands[0],
|
yann@1
|
5128 |
+ gen_rtx_IF_THEN_ELSE (mode,
|
yann@1
|
5129 |
+ cond, operands[2], operands[3]));
|
yann@1
|
5130 |
+ emit_insn (insn);
|
yann@1
|
5131 |
+}
|
yann@1
|
5132 |
+
|
yann@1
|
5133 |
+/*******************
|
yann@1
|
5134 |
+ * Addressing Modes
|
yann@1
|
5135 |
+ *******************/
|
yann@1
|
5136 |
+
|
yann@1
|
5137 |
+int
|
yann@1
|
5138 |
+nios2_legitimate_address (rtx operand, enum machine_mode mode ATTRIBUTE_UNUSED,
|
yann@1
|
5139 |
+ int strict)
|
yann@1
|
5140 |
+{
|
yann@1
|
5141 |
+ int ret_val = 0;
|
yann@1
|
5142 |
+
|
yann@1
|
5143 |
+ switch (GET_CODE (operand))
|
yann@1
|
5144 |
+ {
|
yann@1
|
5145 |
+ /* direct. */
|
yann@1
|
5146 |
+ case SYMBOL_REF:
|
yann@1
|
5147 |
+ if (SYMBOL_REF_IN_NIOS2_SMALL_DATA_P (operand))
|
yann@1
|
5148 |
+ {
|
yann@1
|
5149 |
+ ret_val = 1;
|
yann@1
|
5150 |
+ break;
|
yann@1
|
5151 |
+ }
|
yann@1
|
5152 |
+ /* else, fall through */
|
yann@1
|
5153 |
+ case LABEL_REF:
|
yann@1
|
5154 |
+ case CONST_INT:
|
yann@1
|
5155 |
+ case CONST:
|
yann@1
|
5156 |
+ case CONST_DOUBLE:
|
yann@1
|
5157 |
+ /* ??? In here I need to add gp addressing */
|
yann@1
|
5158 |
+ ret_val = 0;
|
yann@1
|
5159 |
+
|
yann@1
|
5160 |
+ break;
|
yann@1
|
5161 |
+
|
yann@1
|
5162 |
+ /* Register indirect. */
|
yann@1
|
5163 |
+ case REG:
|
yann@1
|
5164 |
+ ret_val = REG_OK_FOR_BASE_P2 (operand, strict);
|
yann@1
|
5165 |
+ break;
|
yann@1
|
5166 |
+
|
yann@1
|
5167 |
+ /* Register indirect with displacement */
|
yann@1
|
5168 |
+ case PLUS:
|
yann@1
|
5169 |
+ {
|
yann@1
|
5170 |
+ rtx op0 = XEXP (operand, 0);
|
yann@1
|
5171 |
+ rtx op1 = XEXP (operand, 1);
|
yann@1
|
5172 |
+
|
yann@1
|
5173 |
+ if (REG_P (op0) && REG_P (op1))
|
yann@1
|
5174 |
+ ret_val = 0;
|
yann@1
|
5175 |
+ else if (REG_P (op0) && CONSTANT_P (op1))
|
yann@1
|
5176 |
+ ret_val = REG_OK_FOR_BASE_P2 (op0, strict)
|
yann@1
|
5177 |
+ && SMALL_INT (INTVAL (op1));
|
yann@1
|
5178 |
+ else if (REG_P (op1) && CONSTANT_P (op0))
|
yann@1
|
5179 |
+ ret_val = REG_OK_FOR_BASE_P2 (op1, strict)
|
yann@1
|
5180 |
+ && SMALL_INT (INTVAL (op0));
|
yann@1
|
5181 |
+ else
|
yann@1
|
5182 |
+ ret_val = 0;
|
yann@1
|
5183 |
+ }
|
yann@1
|
5184 |
+ break;
|
yann@1
|
5185 |
+
|
yann@1
|
5186 |
+ default:
|
yann@1
|
5187 |
+ ret_val = 0;
|
yann@1
|
5188 |
+ break;
|
yann@1
|
5189 |
+ }
|
yann@1
|
5190 |
+
|
yann@1
|
5191 |
+ return ret_val;
|
yann@1
|
5192 |
+}
|
yann@1
|
5193 |
+
|
yann@1
|
5194 |
+/* Return true if EXP should be placed in the small data section. */
|
yann@1
|
5195 |
+
|
yann@1
|
5196 |
+static bool
|
yann@1
|
5197 |
+nios2_in_small_data_p (tree exp)
|
yann@1
|
5198 |
+{
|
yann@1
|
5199 |
+ /* We want to merge strings, so we never consider them small data. */
|
yann@1
|
5200 |
+ if (TREE_CODE (exp) == STRING_CST)
|
yann@1
|
5201 |
+ return false;
|
yann@1
|
5202 |
+
|
yann@1
|
5203 |
+ if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp))
|
yann@1
|
5204 |
+ {
|
yann@1
|
5205 |
+ const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp));
|
yann@1
|
5206 |
+ /* ??? these string names need moving into
|
yann@1
|
5207 |
+ an array in some header file */
|
yann@1
|
5208 |
+ if (nios2_section_threshold > 0
|
yann@1
|
5209 |
+ && (strcmp (section, ".sbss") == 0
|
yann@1
|
5210 |
+ || strncmp (section, ".sbss.", 6) == 0
|
yann@1
|
5211 |
+ || strcmp (section, ".sdata") == 0
|
yann@1
|
5212 |
+ || strncmp (section, ".sdata.", 7) == 0))
|
yann@1
|
5213 |
+ return true;
|
yann@1
|
5214 |
+ }
|
yann@1
|
5215 |
+ else if (TREE_CODE (exp) == VAR_DECL)
|
yann@1
|
5216 |
+ {
|
yann@1
|
5217 |
+ HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
|
yann@1
|
5218 |
+
|
yann@1
|
5219 |
+ /* If this is an incomplete type with size 0, then we can't put it
|
yann@1
|
5220 |
+ in sdata because it might be too big when completed. */
|
yann@1
|
5221 |
+ if (size > 0 && size <= nios2_section_threshold)
|
yann@1
|
5222 |
+ return true;
|
yann@1
|
5223 |
+ }
|
yann@1
|
5224 |
+
|
yann@1
|
5225 |
+ return false;
|
yann@1
|
5226 |
+}
|
yann@1
|
5227 |
+
|
yann@1
|
5228 |
+static void
|
yann@1
|
5229 |
+nios2_encode_section_info (tree decl, rtx rtl, int first)
|
yann@1
|
5230 |
+{
|
yann@1
|
5231 |
+
|
yann@1
|
5232 |
+ rtx symbol;
|
yann@1
|
5233 |
+ int flags;
|
yann@1
|
5234 |
+
|
yann@1
|
5235 |
+ default_encode_section_info (decl, rtl, first);
|
yann@1
|
5236 |
+
|
yann@1
|
5237 |
+ /* Careful not to prod global register variables. */
|
yann@1
|
5238 |
+ if (GET_CODE (rtl) != MEM)
|
yann@1
|
5239 |
+ return;
|
yann@1
|
5240 |
+ symbol = XEXP (rtl, 0);
|
yann@1
|
5241 |
+ if (GET_CODE (symbol) != SYMBOL_REF)
|
yann@1
|
5242 |
+ return;
|
yann@1
|
5243 |
+
|
yann@1
|
5244 |
+ flags = SYMBOL_REF_FLAGS (symbol);
|
yann@1
|
5245 |
+
|
yann@1
|
5246 |
+ /* We don't want weak variables to be addressed with gp in case they end up with
|
yann@1
|
5247 |
+ value 0 which is not within 2^15 of $gp */
|
yann@1
|
5248 |
+ if (DECL_P (decl) && DECL_WEAK (decl))
|
yann@1
|
5249 |
+ flags |= SYMBOL_FLAG_WEAK_DECL;
|
yann@1
|
5250 |
+
|
yann@1
|
5251 |
+ SYMBOL_REF_FLAGS (symbol) = flags;
|
yann@1
|
5252 |
+}
|
yann@1
|
5253 |
+
|
yann@1
|
5254 |
+
|
yann@1
|
5255 |
+static unsigned int
|
yann@1
|
5256 |
+nios2_section_type_flags (tree decl, const char *name, int reloc)
|
yann@1
|
5257 |
+{
|
yann@1
|
5258 |
+ unsigned int flags;
|
yann@1
|
5259 |
+
|
yann@1
|
5260 |
+ flags = default_section_type_flags (decl, name, reloc);
|
yann@1
|
5261 |
+
|
yann@1
|
5262 |
+ /* ??? these string names need moving into an array in some header file */
|
yann@1
|
5263 |
+ if (strcmp (name, ".sbss") == 0
|
yann@1
|
5264 |
+ || strncmp (name, ".sbss.", 6) == 0
|
yann@1
|
5265 |
+ || strcmp (name, ".sdata") == 0
|
yann@1
|
5266 |
+ || strncmp (name, ".sdata.", 7) == 0)
|
yann@1
|
5267 |
+ flags |= SECTION_SMALL;
|
yann@1
|
5268 |
+
|
yann@1
|
5269 |
+ return flags;
|
yann@1
|
5270 |
+}
|
yann@1
|
5271 |
+
|
yann@1
|
5272 |
+
|
yann@1
|
5273 |
+
|
yann@1
|
5274 |
+
|
yann@1
|
5275 |
+/*****************************************
|
yann@1
|
5276 |
+ * Defining the Output Assembler Language
|
yann@1
|
5277 |
+ *****************************************/
|
yann@1
|
5278 |
+
|
yann@1
|
5279 |
+/* -------------- *
|
yann@1
|
5280 |
+ * Output of Data
|
yann@1
|
5281 |
+ * -------------- */
|
yann@1
|
5282 |
+
|
yann@1
|
5283 |
+
|
yann@1
|
5284 |
+/* -------------------------------- *
|
yann@1
|
5285 |
+ * Output of Assembler Instructions
|
yann@1
|
5286 |
+ * -------------------------------- */
|
yann@1
|
5287 |
+
|
yann@1
|
5288 |
+
|
yann@1
|
5289 |
+/* print the operand OP to file stream
|
yann@1
|
5290 |
+ FILE modified by LETTER. LETTER
|
yann@1
|
5291 |
+ can be one of:
|
yann@1
|
5292 |
+ i: print "i" if OP is an immediate, except 0
|
yann@1
|
5293 |
+ o: print "io" if OP is volatile
|
yann@1
|
5294 |
+
|
yann@1
|
5295 |
+ z: for const0_rtx print $0 instead of 0
|
yann@1
|
5296 |
+ H: for %hiadj
|
yann@1
|
5297 |
+ L: for %lo
|
yann@1
|
5298 |
+ U: for upper half of 32 bit value
|
yann@1
|
5299 |
+ */
|
yann@1
|
5300 |
+
|
yann@1
|
5301 |
+void
|
yann@1
|
5302 |
+nios2_print_operand (FILE *file, rtx op, int letter)
|
yann@1
|
5303 |
+{
|
yann@1
|
5304 |
+
|
yann@1
|
5305 |
+ switch (letter)
|
yann@1
|
5306 |
+ {
|
yann@1
|
5307 |
+ case 'i':
|
yann@1
|
5308 |
+ if (CONSTANT_P (op) && (op != const0_rtx))
|
yann@1
|
5309 |
+ fprintf (file, "i");
|
yann@1
|
5310 |
+ return;
|
yann@1
|
5311 |
+
|
yann@1
|
5312 |
+ case 'o':
|
yann@1
|
5313 |
+ if (GET_CODE (op) == MEM
|
yann@1
|
5314 |
+ && ((MEM_VOLATILE_P (op) && !TARGET_CACHE_VOLATILE)
|
yann@1
|
5315 |
+ || TARGET_BYPASS_CACHE))
|
yann@1
|
5316 |
+ fprintf (file, "io");
|
yann@1
|
5317 |
+ return;
|
yann@1
|
5318 |
+
|
yann@1
|
5319 |
+ default:
|
yann@1
|
5320 |
+ break;
|
yann@1
|
5321 |
+ }
|
yann@1
|
5322 |
+
|
yann@1
|
5323 |
+ if (comparison_operator (op, VOIDmode))
|
yann@1
|
5324 |
+ {
|
yann@1
|
5325 |
+ if (letter == 0)
|
yann@1
|
5326 |
+ {
|
yann@1
|
5327 |
+ fprintf (file, "%s", GET_RTX_NAME (GET_CODE (op)));
|
yann@1
|
5328 |
+ return;
|
yann@1
|
5329 |
+ }
|
yann@1
|
5330 |
+ }
|
yann@1
|
5331 |
+
|
yann@1
|
5332 |
+
|
yann@1
|
5333 |
+ switch (GET_CODE (op))
|
yann@1
|
5334 |
+ {
|
yann@1
|
5335 |
+ case REG:
|
yann@1
|
5336 |
+ if (letter == 0 || letter == 'z')
|
yann@1
|
5337 |
+ {
|
yann@1
|
5338 |
+ fprintf (file, "%s", reg_names[REGNO (op)]);
|
yann@1
|
5339 |
+ return;
|
yann@1
|
5340 |
+ }
|
yann@1
|
5341 |
+
|
yann@1
|
5342 |
+ case CONST_INT:
|
yann@1
|
5343 |
+ if (INTVAL (op) == 0 && letter == 'z')
|
yann@1
|
5344 |
+ {
|
yann@1
|
5345 |
+ fprintf (file, "zero");
|
yann@1
|
5346 |
+ return;
|
yann@1
|
5347 |
+ }
|
yann@1
|
5348 |
+ else if (letter == 'U')
|
yann@1
|
5349 |
+ {
|
yann@1
|
5350 |
+ HOST_WIDE_INT val = INTVAL (op);
|
yann@1
|
5351 |
+ rtx new_op;
|
yann@1
|
5352 |
+ val = (val / 65536) & 0xFFFF;
|
yann@1
|
5353 |
+ new_op = GEN_INT (val);
|
yann@1
|
5354 |
+ output_addr_const (file, new_op);
|
yann@1
|
5355 |
+ return;
|
yann@1
|
5356 |
+ }
|
yann@1
|
5357 |
+
|
yann@1
|
5358 |
+ /* else, fall through */
|
yann@1
|
5359 |
+ case CONST:
|
yann@1
|
5360 |
+ case LABEL_REF:
|
yann@1
|
5361 |
+ case SYMBOL_REF:
|
yann@1
|
5362 |
+ case CONST_DOUBLE:
|
yann@1
|
5363 |
+ if (letter == 0 || letter == 'z')
|
yann@1
|
5364 |
+ {
|
yann@1
|
5365 |
+ output_addr_const (file, op);
|
yann@1
|
5366 |
+ return;
|
yann@1
|
5367 |
+ }
|
yann@1
|
5368 |
+ else if (letter == 'H')
|
yann@1
|
5369 |
+ {
|
yann@1
|
5370 |
+ fprintf (file, "%%hiadj(");
|
yann@1
|
5371 |
+ output_addr_const (file, op);
|
yann@1
|
5372 |
+ fprintf (file, ")");
|
yann@1
|
5373 |
+ return;
|
yann@1
|
5374 |
+ }
|
yann@1
|
5375 |
+ else if (letter == 'L')
|
yann@1
|
5376 |
+ {
|
yann@1
|
5377 |
+ fprintf (file, "%%lo(");
|
yann@1
|
5378 |
+ output_addr_const (file, op);
|
yann@1
|
5379 |
+ fprintf (file, ")");
|
yann@1
|
5380 |
+ return;
|
yann@1
|
5381 |
+ }
|
yann@1
|
5382 |
+
|
yann@1
|
5383 |
+
|
yann@1
|
5384 |
+ case SUBREG:
|
yann@1
|
5385 |
+ case MEM:
|
yann@1
|
5386 |
+ if (letter == 0)
|
yann@1
|
5387 |
+ {
|
yann@1
|
5388 |
+ output_address (op);
|
yann@1
|
5389 |
+ return;
|
yann@1
|
5390 |
+ }
|
yann@1
|
5391 |
+
|
yann@1
|
5392 |
+ case CODE_LABEL:
|
yann@1
|
5393 |
+ if (letter == 0)
|
yann@1
|
5394 |
+ {
|
yann@1
|
5395 |
+ output_addr_const (file, op);
|
yann@1
|
5396 |
+ return;
|
yann@1
|
5397 |
+ }
|
yann@1
|
5398 |
+
|
yann@1
|
5399 |
+ default:
|
yann@1
|
5400 |
+ break;
|
yann@1
|
5401 |
+ }
|
yann@1
|
5402 |
+
|
yann@1
|
5403 |
+ fprintf (stderr, "Missing way to print (%c) ", letter);
|
yann@1
|
5404 |
+ debug_rtx (op);
|
yann@1
|
5405 |
+ abort ();
|
yann@1
|
5406 |
+}
|
yann@1
|
5407 |
+
|
yann@1
|
5408 |
+static int gprel_constant (rtx);
|
yann@1
|
5409 |
+
|
yann@1
|
5410 |
+static int
|
yann@1
|
5411 |
+gprel_constant (rtx op)
|
yann@1
|
5412 |
+{
|
yann@1
|
5413 |
+ if (GET_CODE (op) == SYMBOL_REF
|
yann@1
|
5414 |
+ && SYMBOL_REF_IN_NIOS2_SMALL_DATA_P (op))
|
yann@1
|
5415 |
+ {
|
yann@1
|
5416 |
+ return 1;
|
yann@1
|
5417 |
+ }
|
yann@1
|
5418 |
+ else if (GET_CODE (op) == CONST
|
yann@1
|
5419 |
+ && GET_CODE (XEXP (op, 0)) == PLUS)
|
yann@1
|
5420 |
+ {
|
yann@1
|
5421 |
+ return gprel_constant (XEXP (XEXP (op, 0), 0));
|
yann@1
|
5422 |
+ }
|
yann@1
|
5423 |
+ else
|
yann@1
|
5424 |
+ {
|
yann@1
|
5425 |
+ return 0;
|
yann@1
|
5426 |
+ }
|
yann@1
|
5427 |
+}
|
yann@1
|
5428 |
+
|
yann@1
|
5429 |
+void
|
yann@1
|
5430 |
+nios2_print_operand_address (FILE *file, rtx op)
|
yann@1
|
5431 |
+{
|
yann@1
|
5432 |
+ switch (GET_CODE (op))
|
yann@1
|
5433 |
+ {
|
yann@1
|
5434 |
+ case CONST:
|
yann@1
|
5435 |
+ case CONST_INT:
|
yann@1
|
5436 |
+ case LABEL_REF:
|
yann@1
|
5437 |
+ case CONST_DOUBLE:
|
yann@1
|
5438 |
+ case SYMBOL_REF:
|
yann@1
|
5439 |
+ if (gprel_constant (op))
|
yann@1
|
5440 |
+ {
|
yann@1
|
5441 |
+ fprintf (file, "%%gprel(");
|
yann@1
|
5442 |
+ output_addr_const (file, op);
|
yann@1
|
5443 |
+ fprintf (file, ")(%s)", reg_names[GP_REGNO]);
|
yann@1
|
5444 |
+ return;
|
yann@1
|
5445 |
+ }
|
yann@1
|
5446 |
+
|
yann@1
|
5447 |
+ break;
|
yann@1
|
5448 |
+
|
yann@1
|
5449 |
+ case PLUS:
|
yann@1
|
5450 |
+ {
|
yann@1
|
5451 |
+ rtx op0 = XEXP (op, 0);
|
yann@1
|
5452 |
+ rtx op1 = XEXP (op, 1);
|
yann@1
|
5453 |
+
|
yann@1
|
5454 |
+ if (REG_P (op0) && CONSTANT_P (op1))
|
yann@1
|
5455 |
+ {
|
yann@1
|
5456 |
+ output_addr_const (file, op1);
|
yann@1
|
5457 |
+ fprintf (file, "(%s)", reg_names[REGNO (op0)]);
|
yann@1
|
5458 |
+ return;
|
yann@1
|
5459 |
+ }
|
yann@1
|
5460 |
+ else if (REG_P (op1) && CONSTANT_P (op0))
|
yann@1
|
5461 |
+ {
|
yann@1
|
5462 |
+ output_addr_const (file, op0);
|
yann@1
|
5463 |
+ fprintf (file, "(%s)", reg_names[REGNO (op1)]);
|
yann@1
|
5464 |
+ return;
|
yann@1
|
5465 |
+ }
|
yann@1
|
5466 |
+ }
|
yann@1
|
5467 |
+ break;
|
yann@1
|
5468 |
+
|
yann@1
|
5469 |
+ case REG:
|
yann@1
|
5470 |
+ fprintf (file, "0(%s)", reg_names[REGNO (op)]);
|
yann@1
|
5471 |
+ return;
|
yann@1
|
5472 |
+
|
yann@1
|
5473 |
+ case MEM:
|
yann@1
|
5474 |
+ {
|
yann@1
|
5475 |
+ rtx base = XEXP (op, 0);
|
yann@1
|
5476 |
+ PRINT_OPERAND_ADDRESS (file, base);
|
yann@1
|
5477 |
+ return;
|
yann@1
|
5478 |
+ }
|
yann@1
|
5479 |
+ default:
|
yann@1
|
5480 |
+ break;
|
yann@1
|
5481 |
+ }
|
yann@1
|
5482 |
+
|
yann@1
|
5483 |
+ fprintf (stderr, "Missing way to print address\n");
|
yann@1
|
5484 |
+ debug_rtx (op);
|
yann@1
|
5485 |
+ abort ();
|
yann@1
|
5486 |
+}
|
yann@1
|
5487 |
+
|
yann@1
|
5488 |
+
|
yann@1
|
5489 |
+
|
yann@1
|
5490 |
+
|
yann@1
|
5491 |
+
|
yann@1
|
5492 |
+/****************************
|
yann@1
|
5493 |
+ * Predicates
|
yann@1
|
5494 |
+ ****************************/
|
yann@1
|
5495 |
+
|
yann@1
|
5496 |
+int
|
yann@1
|
5497 |
+arith_operand (rtx op, enum machine_mode mode)
|
yann@1
|
5498 |
+{
|
yann@1
|
5499 |
+ if (GET_CODE (op) == CONST_INT && SMALL_INT (INTVAL (op)))
|
yann@1
|
5500 |
+ return 1;
|
yann@1
|
5501 |
+
|
yann@1
|
5502 |
+ return register_operand (op, mode);
|
yann@1
|
5503 |
+}
|
yann@1
|
5504 |
+
|
yann@1
|
5505 |
+int
|
yann@1
|
5506 |
+uns_arith_operand (rtx op, enum machine_mode mode)
|
yann@1
|
5507 |
+{
|
yann@1
|
5508 |
+ if (GET_CODE (op) == CONST_INT && SMALL_INT_UNSIGNED (INTVAL (op)))
|
yann@1
|
5509 |
+ return 1;
|
yann@1
|
5510 |
+
|
yann@1
|
5511 |
+ return register_operand (op, mode);
|
yann@1
|
5512 |
+}
|
yann@1
|
5513 |
+
|
yann@1
|
5514 |
+int
|
yann@1
|
5515 |
+logical_operand (rtx op, enum machine_mode mode)
|
yann@1
|
5516 |
+{
|
yann@1
|
5517 |
+ if (GET_CODE (op) == CONST_INT
|
yann@1
|
5518 |
+ && (SMALL_INT_UNSIGNED (INTVAL (op)) || UPPER16_INT (INTVAL (op))))
|
yann@1
|
5519 |
+ return 1;
|
yann@1
|
5520 |
+
|
yann@1
|
5521 |
+ return register_operand (op, mode);
|
yann@1
|
5522 |
+}
|
yann@1
|
5523 |
+
|
yann@1
|
5524 |
+int
|
yann@1
|
5525 |
+shift_operand (rtx op, enum machine_mode mode)
|
yann@1
|
5526 |
+{
|
yann@1
|
5527 |
+ if (GET_CODE (op) == CONST_INT && SHIFT_INT (INTVAL (op)))
|
yann@1
|
5528 |
+ return 1;
|
yann@1
|
5529 |
+
|
yann@1
|
5530 |
+ return register_operand (op, mode);
|
yann@1
|
5531 |
+}
|
yann@1
|
5532 |
+
|
yann@1
|
5533 |
+int
|
yann@1
|
5534 |
+rdwrctl_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
|
yann@1
|
5535 |
+{
|
yann@1
|
5536 |
+ return GET_CODE (op) == CONST_INT && RDWRCTL_INT (INTVAL (op));
|
yann@1
|
5537 |
+}
|
yann@1
|
5538 |
+
|
yann@1
|
5539 |
+/* Return truth value of whether OP is a register or the constant 0. */
|
yann@1
|
5540 |
+
|
yann@1
|
5541 |
+int
|
yann@1
|
5542 |
+reg_or_0_operand (rtx op, enum machine_mode mode)
|
yann@1
|
5543 |
+{
|
yann@1
|
5544 |
+ switch (GET_CODE (op))
|
yann@1
|
5545 |
+ {
|
yann@1
|
5546 |
+ case CONST_INT:
|
yann@1
|
5547 |
+ return INTVAL (op) == 0;
|
yann@1
|
5548 |
+
|
yann@1
|
5549 |
+ case CONST_DOUBLE:
|
yann@1
|
5550 |
+ return op == CONST0_RTX (mode);
|
yann@1
|
5551 |
+
|
yann@1
|
5552 |
+ default:
|
yann@1
|
5553 |
+ break;
|
yann@1
|
5554 |
+ }
|
yann@1
|
5555 |
+
|
yann@1
|
5556 |
+ return register_operand (op, mode);
|
yann@1
|
5557 |
+}
|
yann@1
|
5558 |
+
|
yann@1
|
5559 |
+
|
yann@1
|
5560 |
+int
|
yann@1
|
5561 |
+equality_op (rtx op, enum machine_mode mode)
|
yann@1
|
5562 |
+{
|
yann@1
|
5563 |
+ if (mode != GET_MODE (op))
|
yann@1
|
5564 |
+ return 0;
|
yann@1
|
5565 |
+
|
yann@1
|
5566 |
+ return GET_CODE (op) == EQ || GET_CODE (op) == NE;
|
yann@1
|
5567 |
+}
|
yann@1
|
5568 |
+
|
yann@1
|
5569 |
+int
|
yann@1
|
5570 |
+custom_insn_opcode (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
|
yann@1
|
5571 |
+{
|
yann@1
|
5572 |
+ return GET_CODE (op) == CONST_INT && CUSTOM_INSN_OPCODE (INTVAL (op));
|
yann@1
|
5573 |
+}
|
yann@1
|
5574 |
+
|
yann@1
|
5575 |
+
|
yann@1
|
5576 |
+
|
yann@1
|
5577 |
+
|
yann@1
|
5578 |
+
|
yann@1
|
5579 |
+
|
yann@1
|
5580 |
+
|
yann@1
|
5581 |
+/*****************************************************************************
|
yann@1
|
5582 |
+**
|
yann@1
|
5583 |
+** instruction scheduler
|
yann@1
|
5584 |
+**
|
yann@1
|
5585 |
+*****************************************************************************/
|
yann@1
|
5586 |
+static int
|
yann@1
|
5587 |
+nios2_use_dfa_pipeline_interface ()
|
yann@1
|
5588 |
+{
|
yann@1
|
5589 |
+ return 1;
|
yann@1
|
5590 |
+}
|
yann@1
|
5591 |
+
|
yann@1
|
5592 |
+
|
yann@1
|
5593 |
+static int
|
yann@1
|
5594 |
+nios2_issue_rate ()
|
yann@1
|
5595 |
+{
|
yann@1
|
5596 |
+#ifdef MAX_DFA_ISSUE_RATE
|
yann@1
|
5597 |
+ return MAX_DFA_ISSUE_RATE;
|
yann@1
|
5598 |
+#else
|
yann@1
|
5599 |
+ return 1;
|
yann@1
|
5600 |
+#endif
|
yann@1
|
5601 |
+}
|
yann@1
|
5602 |
+
|
yann@1
|
5603 |
+
|
yann@1
|
5604 |
+const char *
|
yann@1
|
5605 |
+asm_output_opcode (FILE *file ATTRIBUTE_UNUSED,
|
yann@1
|
5606 |
+ const char *ptr ATTRIBUTE_UNUSED)
|
yann@1
|
5607 |
+{
|
yann@1
|
5608 |
+ const char *p;
|
yann@1
|
5609 |
+
|
yann@1
|
5610 |
+ p = ptr;
|
yann@1
|
5611 |
+ return ptr;
|
yann@1
|
5612 |
+}
|
yann@1
|
5613 |
+
|
yann@1
|
5614 |
+
|
yann@1
|
5615 |
+
|
yann@1
|
5616 |
+/*****************************************************************************
|
yann@1
|
5617 |
+**
|
yann@1
|
5618 |
+** function arguments
|
yann@1
|
5619 |
+**
|
yann@1
|
5620 |
+*****************************************************************************/
|
yann@1
|
5621 |
+
|
yann@1
|
5622 |
+void
|
yann@1
|
5623 |
+init_cumulative_args (CUMULATIVE_ARGS *cum,
|
yann@1
|
5624 |
+ tree fntype ATTRIBUTE_UNUSED,
|
yann@1
|
5625 |
+ rtx libname ATTRIBUTE_UNUSED,
|
yann@1
|
5626 |
+ tree fndecl ATTRIBUTE_UNUSED,
|
yann@1
|
5627 |
+ int n_named_args ATTRIBUTE_UNUSED)
|
yann@1
|
5628 |
+{
|
yann@1
|
5629 |
+ cum->regs_used = 0;
|
yann@1
|
5630 |
+}
|
yann@1
|
5631 |
+
|
yann@1
|
5632 |
+
|
yann@1
|
5633 |
+/* Update the data in CUM to advance over an argument
|
yann@1
|
5634 |
+ of mode MODE and data type TYPE.
|
yann@1
|
5635 |
+ (TYPE is null for libcalls where that information may not be available.) */
|
yann@1
|
5636 |
+
|
yann@1
|
5637 |
+void
|
yann@1
|
5638 |
+function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
yann@1
|
5639 |
+ tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED)
|
yann@1
|
5640 |
+{
|
yann@1
|
5641 |
+ HOST_WIDE_INT param_size;
|
yann@1
|
5642 |
+
|
yann@1
|
5643 |
+ if (mode == BLKmode)
|
yann@1
|
5644 |
+ {
|
yann@1
|
5645 |
+ param_size = int_size_in_bytes (type);
|
yann@1
|
5646 |
+ if (param_size < 0)
|
yann@1
|
5647 |
+ internal_error
|
yann@1
|
5648 |
+ ("Do not know how to handle large structs or variable length types");
|
yann@1
|
5649 |
+ }
|
yann@1
|
5650 |
+ else
|
yann@1
|
5651 |
+ {
|
yann@1
|
5652 |
+ param_size = GET_MODE_SIZE (mode);
|
yann@1
|
5653 |
+ }
|
yann@1
|
5654 |
+
|
yann@1
|
5655 |
+ /* convert to words (round up) */
|
yann@1
|
5656 |
+ param_size = (3 + param_size) / 4;
|
yann@1
|
5657 |
+
|
yann@1
|
5658 |
+ if (cum->regs_used + param_size > NUM_ARG_REGS)
|
yann@1
|
5659 |
+ {
|
yann@1
|
5660 |
+ cum->regs_used = NUM_ARG_REGS;
|
yann@1
|
5661 |
+ }
|
yann@1
|
5662 |
+ else
|
yann@1
|
5663 |
+ {
|
yann@1
|
5664 |
+ cum->regs_used += param_size;
|
yann@1
|
5665 |
+ }
|
yann@1
|
5666 |
+
|
yann@1
|
5667 |
+ return;
|
yann@1
|
5668 |
+}
|
yann@1
|
5669 |
+
|
yann@1
|
5670 |
+/* Define where to put the arguments to a function. Value is zero to
|
yann@1
|
5671 |
+ push the argument on the stack, or a hard register in which to
|
yann@1
|
5672 |
+ store the argument.
|
yann@1
|
5673 |
+
|
yann@1
|
5674 |
+ MODE is the argument's machine mode.
|
yann@1
|
5675 |
+ TYPE is the data type of the argument (as a tree).
|
yann@1
|
5676 |
+ This is null for libcalls where that information may
|
yann@1
|
5677 |
+ not be available.
|
yann@1
|
5678 |
+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
|
yann@1
|
5679 |
+ the preceding args and about the function being called.
|
yann@1
|
5680 |
+ NAMED is nonzero if this argument is a named parameter
|
yann@1
|
5681 |
+ (otherwise it is an extra parameter matching an ellipsis). */
|
yann@1
|
5682 |
+rtx
|
yann@1
|
5683 |
+function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
|
yann@1
|
5684 |
+ tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED)
|
yann@1
|
5685 |
+{
|
yann@1
|
5686 |
+ rtx return_rtx = NULL_RTX;
|
yann@1
|
5687 |
+
|
yann@1
|
5688 |
+ if (cum->regs_used < NUM_ARG_REGS)
|
yann@1
|
5689 |
+ {
|
yann@1
|
5690 |
+ return_rtx = gen_rtx_REG (mode, FIRST_ARG_REGNO + cum->regs_used);
|
yann@1
|
5691 |
+ }
|
yann@1
|
5692 |
+
|
yann@1
|
5693 |
+ return return_rtx;
|
yann@1
|
5694 |
+}
|
yann@1
|
5695 |
+
|
yann@1
|
5696 |
+int
|
yann@1
|
5697 |
+function_arg_partial_nregs (const CUMULATIVE_ARGS *cum,
|
yann@1
|
5698 |
+ enum machine_mode mode, tree type,
|
yann@1
|
5699 |
+ int named ATTRIBUTE_UNUSED)
|
yann@1
|
5700 |
+{
|
yann@1
|
5701 |
+ HOST_WIDE_INT param_size;
|
yann@1
|
5702 |
+
|
yann@1
|
5703 |
+ if (mode == BLKmode)
|
yann@1
|
5704 |
+ {
|
yann@1
|
5705 |
+ param_size = int_size_in_bytes (type);
|
yann@1
|
5706 |
+ if (param_size < 0)
|
yann@1
|
5707 |
+ internal_error
|
yann@1
|
5708 |
+ ("Do not know how to handle large structs or variable length types");
|
yann@1
|
5709 |
+ }
|
yann@1
|
5710 |
+ else
|
yann@1
|
5711 |
+ {
|
yann@1
|
5712 |
+ param_size = GET_MODE_SIZE (mode);
|
yann@1
|
5713 |
+ }
|
yann@1
|
5714 |
+
|
yann@1
|
5715 |
+ /* convert to words (round up) */
|
yann@1
|
5716 |
+ param_size = (3 + param_size) / 4;
|
yann@1
|
5717 |
+
|
yann@1
|
5718 |
+ if (cum->regs_used < NUM_ARG_REGS
|
yann@1
|
5719 |
+ && cum->regs_used + param_size > NUM_ARG_REGS)
|
yann@1
|
5720 |
+ {
|
yann@1
|
5721 |
+ return NUM_ARG_REGS - cum->regs_used;
|
yann@1
|
5722 |
+ }
|
yann@1
|
5723 |
+ else
|
yann@1
|
5724 |
+ {
|
yann@1
|
5725 |
+ return 0;
|
yann@1
|
5726 |
+ }
|
yann@1
|
5727 |
+}
|
yann@1
|
5728 |
+
|
yann@1
|
5729 |
+
|
yann@1
|
5730 |
+int
|
yann@1
|
5731 |
+nios2_return_in_memory (tree type)
|
yann@1
|
5732 |
+{
|
yann@1
|
5733 |
+ int res = ((int_size_in_bytes (type) > (2 * UNITS_PER_WORD))
|
yann@1
|
5734 |
+ || (int_size_in_bytes (type) == -1));
|
yann@1
|
5735 |
+
|
yann@1
|
5736 |
+ return res;
|
yann@1
|
5737 |
+}
|
yann@1
|
5738 |
+
|
yann@1
|
5739 |
+/* ??? It may be possible to eliminate the copyback and implement
|
yann@1
|
5740 |
+ my own va_arg type, but that is more work for now. */
|
yann@1
|
5741 |
+int
|
yann@1
|
5742 |
+nios2_setup_incoming_varargs (const CUMULATIVE_ARGS *cum,
|
yann@1
|
5743 |
+ enum machine_mode mode, tree type,
|
yann@1
|
5744 |
+ int no_rtl)
|
yann@1
|
5745 |
+{
|
yann@1
|
5746 |
+ CUMULATIVE_ARGS local_cum;
|
yann@1
|
5747 |
+ int regs_to_push;
|
yann@1
|
5748 |
+
|
yann@1
|
5749 |
+ local_cum = *cum;
|
yann@1
|
5750 |
+ FUNCTION_ARG_ADVANCE (local_cum, mode, type, 1);
|
yann@1
|
5751 |
+
|
yann@1
|
5752 |
+ regs_to_push = NUM_ARG_REGS - local_cum.regs_used;
|
yann@1
|
5753 |
+
|
yann@1
|
5754 |
+ if (!no_rtl)
|
yann@1
|
5755 |
+ {
|
yann@1
|
5756 |
+ if (regs_to_push > 0)
|
yann@1
|
5757 |
+ {
|
yann@1
|
5758 |
+ rtx ptr, mem;
|
yann@1
|
5759 |
+
|
yann@1
|
5760 |
+ ptr = virtual_incoming_args_rtx;
|
yann@1
|
5761 |
+ mem = gen_rtx_MEM (BLKmode, ptr);
|
yann@1
|
5762 |
+
|
yann@1
|
5763 |
+ /* va_arg is an array access in this case, which causes
|
yann@1
|
5764 |
+ it to get MEM_IN_STRUCT_P set. We must set it here
|
yann@1
|
5765 |
+ so that the insn scheduler won't assume that these
|
yann@1
|
5766 |
+ stores can't possibly overlap with the va_arg loads. */
|
yann@1
|
5767 |
+ MEM_SET_IN_STRUCT_P (mem, 1);
|
yann@1
|
5768 |
+
|
yann@1
|
5769 |
+ emit_insn (gen_blockage ());
|
yann@1
|
5770 |
+ move_block_from_reg (local_cum.regs_used + FIRST_ARG_REGNO, mem,
|
yann@1
|
5771 |
+ regs_to_push);
|
yann@1
|
5772 |
+ emit_insn (gen_blockage ());
|
yann@1
|
5773 |
+ }
|
yann@1
|
5774 |
+ }
|
yann@1
|
5775 |
+
|
yann@1
|
5776 |
+ return regs_to_push * UNITS_PER_WORD;
|
yann@1
|
5777 |
+
|
yann@1
|
5778 |
+}
|
yann@1
|
5779 |
+
|
yann@1
|
5780 |
+
|
yann@1
|
5781 |
+
|
yann@1
|
5782 |
+/*****************************************************************************
|
yann@1
|
5783 |
+**
|
yann@1
|
5784 |
+** builtins
|
yann@1
|
5785 |
+**
|
yann@1
|
5786 |
+** This method for handling builtins is from CSP where _many_ more types of
|
yann@1
|
5787 |
+** expanders have already been written. Check there first before writing
|
yann@1
|
5788 |
+** new ones.
|
yann@1
|
5789 |
+**
|
yann@1
|
5790 |
+*****************************************************************************/
|
yann@1
|
5791 |
+
|
yann@1
|
5792 |
+enum nios2_builtins
|
yann@1
|
5793 |
+{
|
yann@1
|
5794 |
+ NIOS2_BUILTIN_LDBIO,
|
yann@1
|
5795 |
+ NIOS2_BUILTIN_LDBUIO,
|
yann@1
|
5796 |
+ NIOS2_BUILTIN_LDHIO,
|
yann@1
|
5797 |
+ NIOS2_BUILTIN_LDHUIO,
|
yann@1
|
5798 |
+ NIOS2_BUILTIN_LDWIO,
|
yann@1
|
5799 |
+ NIOS2_BUILTIN_STBIO,
|
yann@1
|
5800 |
+ NIOS2_BUILTIN_STHIO,
|
yann@1
|
5801 |
+ NIOS2_BUILTIN_STWIO,
|
yann@1
|
5802 |
+ NIOS2_BUILTIN_SYNC,
|
yann@1
|
5803 |
+ NIOS2_BUILTIN_RDCTL,
|
yann@1
|
5804 |
+ NIOS2_BUILTIN_WRCTL,
|
yann@1
|
5805 |
+
|
yann@1
|
5806 |
+ NIOS2_BUILTIN_CUSTOM_N,
|
yann@1
|
5807 |
+ NIOS2_BUILTIN_CUSTOM_NI,
|
yann@1
|
5808 |
+ NIOS2_BUILTIN_CUSTOM_NF,
|
yann@1
|
5809 |
+ NIOS2_BUILTIN_CUSTOM_NP,
|
yann@1
|
5810 |
+ NIOS2_BUILTIN_CUSTOM_NII,
|
yann@1
|
5811 |
+ NIOS2_BUILTIN_CUSTOM_NIF,
|
yann@1
|
5812 |
+ NIOS2_BUILTIN_CUSTOM_NIP,
|
yann@1
|
5813 |
+ NIOS2_BUILTIN_CUSTOM_NFI,
|
yann@1
|
5814 |
+ NIOS2_BUILTIN_CUSTOM_NFF,
|
yann@1
|
5815 |
+ NIOS2_BUILTIN_CUSTOM_NFP,
|
yann@1
|
5816 |
+ NIOS2_BUILTIN_CUSTOM_NPI,
|
yann@1
|
5817 |
+ NIOS2_BUILTIN_CUSTOM_NPF,
|
yann@1
|
5818 |
+ NIOS2_BUILTIN_CUSTOM_NPP,
|
yann@1
|
5819 |
+ NIOS2_BUILTIN_CUSTOM_IN,
|
yann@1
|
5820 |
+ NIOS2_BUILTIN_CUSTOM_INI,
|
yann@1
|
5821 |
+ NIOS2_BUILTIN_CUSTOM_INF,
|
yann@1
|
5822 |
+ NIOS2_BUILTIN_CUSTOM_INP,
|
yann@1
|
5823 |
+ NIOS2_BUILTIN_CUSTOM_INII,
|
yann@1
|
5824 |
+ NIOS2_BUILTIN_CUSTOM_INIF,
|
yann@1
|
5825 |
+ NIOS2_BUILTIN_CUSTOM_INIP,
|
yann@1
|
5826 |
+ NIOS2_BUILTIN_CUSTOM_INFI,
|
yann@1
|
5827 |
+ NIOS2_BUILTIN_CUSTOM_INFF,
|
yann@1
|
5828 |
+ NIOS2_BUILTIN_CUSTOM_INFP,
|
yann@1
|
5829 |
+ NIOS2_BUILTIN_CUSTOM_INPI,
|
yann@1
|
5830 |
+ NIOS2_BUILTIN_CUSTOM_INPF,
|
yann@1
|
5831 |
+ NIOS2_BUILTIN_CUSTOM_INPP,
|
yann@1
|
5832 |
+ NIOS2_BUILTIN_CUSTOM_FN,
|
yann@1
|
5833 |
+ NIOS2_BUILTIN_CUSTOM_FNI,
|
yann@1
|
5834 |
+ NIOS2_BUILTIN_CUSTOM_FNF,
|
yann@1
|
5835 |
+ NIOS2_BUILTIN_CUSTOM_FNP,
|
yann@1
|
5836 |
+ NIOS2_BUILTIN_CUSTOM_FNII,
|
yann@1
|
5837 |
+ NIOS2_BUILTIN_CUSTOM_FNIF,
|
yann@1
|
5838 |
+ NIOS2_BUILTIN_CUSTOM_FNIP,
|
yann@1
|
5839 |
+ NIOS2_BUILTIN_CUSTOM_FNFI,
|
yann@1
|
5840 |
+ NIOS2_BUILTIN_CUSTOM_FNFF,
|
yann@1
|
5841 |
+ NIOS2_BUILTIN_CUSTOM_FNFP,
|
yann@1
|
5842 |
+ NIOS2_BUILTIN_CUSTOM_FNPI,
|
yann@1
|
5843 |
+ NIOS2_BUILTIN_CUSTOM_FNPF,
|
yann@1
|
5844 |
+ NIOS2_BUILTIN_CUSTOM_FNPP,
|
yann@1
|
5845 |
+ NIOS2_BUILTIN_CUSTOM_PN,
|
yann@1
|
5846 |
+ NIOS2_BUILTIN_CUSTOM_PNI,
|
yann@1
|
5847 |
+ NIOS2_BUILTIN_CUSTOM_PNF,
|
yann@1
|
5848 |
+ NIOS2_BUILTIN_CUSTOM_PNP,
|
yann@1
|
5849 |
+ NIOS2_BUILTIN_CUSTOM_PNII,
|
yann@1
|
5850 |
+ NIOS2_BUILTIN_CUSTOM_PNIF,
|
yann@1
|
5851 |
+ NIOS2_BUILTIN_CUSTOM_PNIP,
|
yann@1
|
5852 |
+ NIOS2_BUILTIN_CUSTOM_PNFI,
|
yann@1
|
5853 |
+ NIOS2_BUILTIN_CUSTOM_PNFF,
|
yann@1
|
5854 |
+ NIOS2_BUILTIN_CUSTOM_PNFP,
|
yann@1
|
5855 |
+ NIOS2_BUILTIN_CUSTOM_PNPI,
|
yann@1
|
5856 |
+ NIOS2_BUILTIN_CUSTOM_PNPF,
|
yann@1
|
5857 |
+ NIOS2_BUILTIN_CUSTOM_PNPP,
|
yann@1
|
5858 |
+
|
yann@1
|
5859 |
+
|
yann@1
|
5860 |
+ LIM_NIOS2_BUILTINS
|
yann@1
|
5861 |
+};
|
yann@1
|
5862 |
+
|
yann@1
|
5863 |
+struct builtin_description
|
yann@1
|
5864 |
+{
|
yann@1
|
5865 |
+ const enum insn_code icode;
|
yann@1
|
5866 |
+ const char *const name;
|
yann@1
|
5867 |
+ const enum nios2_builtins code;
|
yann@1
|
5868 |
+ const tree *type;
|
yann@1
|
5869 |
+ rtx (* expander) PARAMS ((const struct builtin_description *,
|
yann@1
|
5870 |
+ tree, rtx, rtx, enum machine_mode, int));
|
yann@1
|
5871 |
+};
|
yann@1
|
5872 |
+
|
yann@1
|
5873 |
+static rtx nios2_expand_STXIO (const struct builtin_description *,
|
yann@1
|
5874 |
+ tree, rtx, rtx, enum machine_mode, int);
|
yann@1
|
5875 |
+static rtx nios2_expand_LDXIO (const struct builtin_description *,
|
yann@1
|
5876 |
+ tree, rtx, rtx, enum machine_mode, int);
|
yann@1
|
5877 |
+static rtx nios2_expand_sync (const struct builtin_description *,
|
yann@1
|
5878 |
+ tree, rtx, rtx, enum machine_mode, int);
|
yann@1
|
5879 |
+static rtx nios2_expand_rdctl (const struct builtin_description *,
|
yann@1
|
5880 |
+ tree, rtx, rtx, enum machine_mode, int);
|
yann@1
|
5881 |
+static rtx nios2_expand_wrctl (const struct builtin_description *,
|
yann@1
|
5882 |
+ tree, rtx, rtx, enum machine_mode, int);
|
yann@1
|
5883 |
+
|
yann@1
|
5884 |
+static rtx nios2_expand_custom_n (const struct builtin_description *,
|
yann@1
|
5885 |
+ tree, rtx, rtx, enum machine_mode, int);
|
yann@1
|
5886 |
+static rtx nios2_expand_custom_Xn (const struct builtin_description *,
|
yann@1
|
5887 |
+ tree, rtx, rtx, enum machine_mode, int);
|
yann@1
|
5888 |
+static rtx nios2_expand_custom_nX (const struct builtin_description *,
|
yann@1
|
5889 |
+ tree, rtx, rtx, enum machine_mode, int);
|
yann@1
|
5890 |
+static rtx nios2_expand_custom_XnX (const struct builtin_description *,
|
yann@1
|
5891 |
+ tree, rtx, rtx, enum machine_mode, int);
|
yann@1
|
5892 |
+static rtx nios2_expand_custom_nXX (const struct builtin_description *,
|
yann@1
|
5893 |
+ tree, rtx, rtx, enum machine_mode, int);
|
yann@1
|
5894 |
+static rtx nios2_expand_custom_XnXX (const struct builtin_description *,
|
yann@1
|
5895 |
+ tree, rtx, rtx, enum machine_mode, int);
|
yann@1
|
5896 |
+
|
yann@1
|
5897 |
+static tree endlink;
|
yann@1
|
5898 |
+
|
yann@1
|
5899 |
+/* int fn (volatile const void *)
|
yann@1
|
5900 |
+ */
|
yann@1
|
5901 |
+static tree int_ftype_volatile_const_void_p;
|
yann@1
|
5902 |
+
|
yann@1
|
5903 |
+/* int fn (int)
|
yann@1
|
5904 |
+ */
|
yann@1
|
5905 |
+static tree int_ftype_int;
|
yann@1
|
5906 |
+
|
yann@1
|
5907 |
+/* void fn (int, int)
|
yann@1
|
5908 |
+ */
|
yann@1
|
5909 |
+static tree void_ftype_int_int;
|
yann@1
|
5910 |
+
|
yann@1
|
5911 |
+/* void fn (volatile void *, int)
|
yann@1
|
5912 |
+ */
|
yann@1
|
5913 |
+static tree void_ftype_volatile_void_p_int;
|
yann@1
|
5914 |
+
|
yann@1
|
5915 |
+/* void fn (void)
|
yann@1
|
5916 |
+ */
|
yann@1
|
5917 |
+static tree void_ftype_void;
|
yann@1
|
5918 |
+
|
yann@1
|
5919 |
+static tree custom_n;
|
yann@1
|
5920 |
+static tree custom_ni;
|
yann@1
|
5921 |
+static tree custom_nf;
|
yann@1
|
5922 |
+static tree custom_np;
|
yann@1
|
5923 |
+static tree custom_nii;
|
yann@1
|
5924 |
+static tree custom_nif;
|
yann@1
|
5925 |
+static tree custom_nip;
|
yann@1
|
5926 |
+static tree custom_nfi;
|
yann@1
|
5927 |
+static tree custom_nff;
|
yann@1
|
5928 |
+static tree custom_nfp;
|
yann@1
|
5929 |
+static tree custom_npi;
|
yann@1
|
5930 |
+static tree custom_npf;
|
yann@1
|
5931 |
+static tree custom_npp;
|
yann@1
|
5932 |
+static tree custom_in;
|
yann@1
|
5933 |
+static tree custom_ini;
|
yann@1
|
5934 |
+static tree custom_inf;
|
yann@1
|
5935 |
+static tree custom_inp;
|
yann@1
|
5936 |
+static tree custom_inii;
|
yann@1
|
5937 |
+static tree custom_inif;
|
yann@1
|
5938 |
+static tree custom_inip;
|
yann@1
|
5939 |
+static tree custom_infi;
|
yann@1
|
5940 |
+static tree custom_inff;
|
yann@1
|
5941 |
+static tree custom_infp;
|
yann@1
|
5942 |
+static tree custom_inpi;
|
yann@1
|
5943 |
+static tree custom_inpf;
|
yann@1
|
5944 |
+static tree custom_inpp;
|
yann@1
|
5945 |
+static tree custom_fn;
|
yann@1
|
5946 |
+static tree custom_fni;
|
yann@1
|
5947 |
+static tree custom_fnf;
|
yann@1
|
5948 |
+static tree custom_fnp;
|
yann@1
|
5949 |
+static tree custom_fnii;
|
yann@1
|
5950 |
+static tree custom_fnif;
|
yann@1
|
5951 |
+static tree custom_fnip;
|
yann@1
|
5952 |
+static tree custom_fnfi;
|
yann@1
|
5953 |
+static tree custom_fnff;
|
yann@1
|
5954 |
+static tree custom_fnfp;
|
yann@1
|
5955 |
+static tree custom_fnpi;
|
yann@1
|
5956 |
+static tree custom_fnpf;
|
yann@1
|
5957 |
+static tree custom_fnpp;
|
yann@1
|
5958 |
+static tree custom_pn;
|
yann@1
|
5959 |
+static tree custom_pni;
|
yann@1
|
5960 |
+static tree custom_pnf;
|
yann@1
|
5961 |
+static tree custom_pnp;
|
yann@1
|
5962 |
+static tree custom_pnii;
|
yann@1
|
5963 |
+static tree custom_pnif;
|
yann@1
|
5964 |
+static tree custom_pnip;
|
yann@1
|
5965 |
+static tree custom_pnfi;
|
yann@1
|
5966 |
+static tree custom_pnff;
|
yann@1
|
5967 |
+static tree custom_pnfp;
|
yann@1
|
5968 |
+static tree custom_pnpi;
|
yann@1
|
5969 |
+static tree custom_pnpf;
|
yann@1
|
5970 |
+static tree custom_pnpp;
|
yann@1
|
5971 |
+
|
yann@1
|
5972 |
+
|
yann@1
|
5973 |
+static const struct builtin_description bdesc[] = {
|
yann@1
|
5974 |
+ {CODE_FOR_ldbio, "__builtin_ldbio", NIOS2_BUILTIN_LDBIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
|
yann@1
|
5975 |
+ {CODE_FOR_ldbuio, "__builtin_ldbuio", NIOS2_BUILTIN_LDBUIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
|
yann@1
|
5976 |
+ {CODE_FOR_ldhio, "__builtin_ldhio", NIOS2_BUILTIN_LDHIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
|
yann@1
|
5977 |
+ {CODE_FOR_ldhuio, "__builtin_ldhuio", NIOS2_BUILTIN_LDHUIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
|
yann@1
|
5978 |
+ {CODE_FOR_ldwio, "__builtin_ldwio", NIOS2_BUILTIN_LDWIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
|
yann@1
|
5979 |
+
|
yann@1
|
5980 |
+ {CODE_FOR_stbio, "__builtin_stbio", NIOS2_BUILTIN_STBIO, &void_ftype_volatile_void_p_int, nios2_expand_STXIO},
|
yann@1
|
5981 |
+ {CODE_FOR_sthio, "__builtin_sthio", NIOS2_BUILTIN_STHIO, &void_ftype_volatile_void_p_int, nios2_expand_STXIO},
|
yann@1
|
5982 |
+ {CODE_FOR_stwio, "__builtin_stwio", NIOS2_BUILTIN_STWIO, &void_ftype_volatile_void_p_int, nios2_expand_STXIO},
|
yann@1
|
5983 |
+
|
yann@1
|
5984 |
+ {CODE_FOR_sync, "__builtin_sync", NIOS2_BUILTIN_SYNC, &void_ftype_void, nios2_expand_sync},
|
yann@1
|
5985 |
+ {CODE_FOR_rdctl, "__builtin_rdctl", NIOS2_BUILTIN_RDCTL, &int_ftype_int, nios2_expand_rdctl},
|
yann@1
|
5986 |
+ {CODE_FOR_wrctl, "__builtin_wrctl", NIOS2_BUILTIN_WRCTL, &void_ftype_int_int, nios2_expand_wrctl},
|
yann@1
|
5987 |
+
|
yann@1
|
5988 |
+ {CODE_FOR_custom_n, "__builtin_custom_n", NIOS2_BUILTIN_CUSTOM_N, &custom_n, nios2_expand_custom_n},
|
yann@1
|
5989 |
+ {CODE_FOR_custom_ni, "__builtin_custom_ni", NIOS2_BUILTIN_CUSTOM_NI, &custom_ni, nios2_expand_custom_nX},
|
yann@1
|
5990 |
+ {CODE_FOR_custom_nf, "__builtin_custom_nf", NIOS2_BUILTIN_CUSTOM_NF, &custom_nf, nios2_expand_custom_nX},
|
yann@1
|
5991 |
+ {CODE_FOR_custom_np, "__builtin_custom_np", NIOS2_BUILTIN_CUSTOM_NP, &custom_np, nios2_expand_custom_nX},
|
yann@1
|
5992 |
+ {CODE_FOR_custom_nii, "__builtin_custom_nii", NIOS2_BUILTIN_CUSTOM_NII, &custom_nii, nios2_expand_custom_nXX},
|
yann@1
|
5993 |
+ {CODE_FOR_custom_nif, "__builtin_custom_nif", NIOS2_BUILTIN_CUSTOM_NIF, &custom_nif, nios2_expand_custom_nXX},
|
yann@1
|
5994 |
+ {CODE_FOR_custom_nip, "__builtin_custom_nip", NIOS2_BUILTIN_CUSTOM_NIP, &custom_nip, nios2_expand_custom_nXX},
|
yann@1
|
5995 |
+ {CODE_FOR_custom_nfi, "__builtin_custom_nfi", NIOS2_BUILTIN_CUSTOM_NFI, &custom_nfi, nios2_expand_custom_nXX},
|
yann@1
|
5996 |
+ {CODE_FOR_custom_nff, "__builtin_custom_nff", NIOS2_BUILTIN_CUSTOM_NFF, &custom_nff, nios2_expand_custom_nXX},
|
yann@1
|
5997 |
+ {CODE_FOR_custom_nfp, "__builtin_custom_nfp", NIOS2_BUILTIN_CUSTOM_NFP, &custom_nfp, nios2_expand_custom_nXX},
|
yann@1
|
5998 |
+ {CODE_FOR_custom_npi, "__builtin_custom_npi", NIOS2_BUILTIN_CUSTOM_NPI, &custom_npi, nios2_expand_custom_nXX},
|
yann@1
|
5999 |
+ {CODE_FOR_custom_npf, "__builtin_custom_npf", NIOS2_BUILTIN_CUSTOM_NPF, &custom_npf, nios2_expand_custom_nXX},
|
yann@1
|
6000 |
+ {CODE_FOR_custom_npp, "__builtin_custom_npp", NIOS2_BUILTIN_CUSTOM_NPP, &custom_npp, nios2_expand_custom_nXX},
|
yann@1
|
6001 |
+ {CODE_FOR_custom_in, "__builtin_custom_in", NIOS2_BUILTIN_CUSTOM_IN, &custom_in, nios2_expand_custom_Xn},
|
yann@1
|
6002 |
+ {CODE_FOR_custom_ini, "__builtin_custom_ini", NIOS2_BUILTIN_CUSTOM_INI, &custom_ini, nios2_expand_custom_XnX},
|
yann@1
|
6003 |
+ {CODE_FOR_custom_inf, "__builtin_custom_inf", NIOS2_BUILTIN_CUSTOM_INF, &custom_inf, nios2_expand_custom_XnX},
|
yann@1
|
6004 |
+ {CODE_FOR_custom_inp, "__builtin_custom_inp", NIOS2_BUILTIN_CUSTOM_INP, &custom_inp, nios2_expand_custom_XnX},
|
yann@1
|
6005 |
+ {CODE_FOR_custom_inii, "__builtin_custom_inii", NIOS2_BUILTIN_CUSTOM_INII, &custom_inii, nios2_expand_custom_XnXX},
|
yann@1
|
6006 |
+ {CODE_FOR_custom_inif, "__builtin_custom_inif", NIOS2_BUILTIN_CUSTOM_INIF, &custom_inif, nios2_expand_custom_XnXX},
|
yann@1
|
6007 |
+ {CODE_FOR_custom_inip, "__builtin_custom_inip", NIOS2_BUILTIN_CUSTOM_INIP, &custom_inip, nios2_expand_custom_XnXX},
|
yann@1
|
6008 |
+ {CODE_FOR_custom_infi, "__builtin_custom_infi", NIOS2_BUILTIN_CUSTOM_INFI, &custom_infi, nios2_expand_custom_XnXX},
|
yann@1
|
6009 |
+ {CODE_FOR_custom_inff, "__builtin_custom_inff", NIOS2_BUILTIN_CUSTOM_INFF, &custom_inff, nios2_expand_custom_XnXX},
|
yann@1
|
6010 |
+ {CODE_FOR_custom_infp, "__builtin_custom_infp", NIOS2_BUILTIN_CUSTOM_INFP, &custom_infp, nios2_expand_custom_XnXX},
|
yann@1
|
6011 |
+ {CODE_FOR_custom_inpi, "__builtin_custom_inpi", NIOS2_BUILTIN_CUSTOM_INPI, &custom_inpi, nios2_expand_custom_XnXX},
|
yann@1
|
6012 |
+ {CODE_FOR_custom_inpf, "__builtin_custom_inpf", NIOS2_BUILTIN_CUSTOM_INPF, &custom_inpf, nios2_expand_custom_XnXX},
|
yann@1
|
6013 |
+ {CODE_FOR_custom_inpp, "__builtin_custom_inpp", NIOS2_BUILTIN_CUSTOM_INPP, &custom_inpp, nios2_expand_custom_XnXX},
|
yann@1
|
6014 |
+ {CODE_FOR_custom_fn, "__builtin_custom_fn", NIOS2_BUILTIN_CUSTOM_FN, &custom_fn, nios2_expand_custom_Xn},
|
yann@1
|
6015 |
+ {CODE_FOR_custom_fni, "__builtin_custom_fni", NIOS2_BUILTIN_CUSTOM_FNI, &custom_fni, nios2_expand_custom_XnX},
|
yann@1
|
6016 |
+ {CODE_FOR_custom_fnf, "__builtin_custom_fnf", NIOS2_BUILTIN_CUSTOM_FNF, &custom_fnf, nios2_expand_custom_XnX},
|
yann@1
|
6017 |
+ {CODE_FOR_custom_fnp, "__builtin_custom_fnp", NIOS2_BUILTIN_CUSTOM_FNP, &custom_fnp, nios2_expand_custom_XnX},
|
yann@1
|
6018 |
+ {CODE_FOR_custom_fnii, "__builtin_custom_fnii", NIOS2_BUILTIN_CUSTOM_FNII, &custom_fnii, nios2_expand_custom_XnXX},
|
yann@1
|
6019 |
+ {CODE_FOR_custom_fnif, "__builtin_custom_fnif", NIOS2_BUILTIN_CUSTOM_FNIF, &custom_fnif, nios2_expand_custom_XnXX},
|
yann@1
|
6020 |
+ {CODE_FOR_custom_fnip, "__builtin_custom_fnip", NIOS2_BUILTIN_CUSTOM_FNIP, &custom_fnip, nios2_expand_custom_XnXX},
|
yann@1
|
6021 |
+ {CODE_FOR_custom_fnfi, "__builtin_custom_fnfi", NIOS2_BUILTIN_CUSTOM_FNFI, &custom_fnfi, nios2_expand_custom_XnXX},
|
yann@1
|
6022 |
+ {CODE_FOR_custom_fnff, "__builtin_custom_fnff", NIOS2_BUILTIN_CUSTOM_FNFF, &custom_fnff, nios2_expand_custom_XnXX},
|
yann@1
|
6023 |
+ {CODE_FOR_custom_fnfp, "__builtin_custom_fnfp", NIOS2_BUILTIN_CUSTOM_FNFP, &custom_fnfp, nios2_expand_custom_XnXX},
|
yann@1
|
6024 |
+ {CODE_FOR_custom_fnpi, "__builtin_custom_fnpi", NIOS2_BUILTIN_CUSTOM_FNPI, &custom_fnpi, nios2_expand_custom_XnXX},
|
yann@1
|
6025 |
+ {CODE_FOR_custom_fnpf, "__builtin_custom_fnpf", NIOS2_BUILTIN_CUSTOM_FNPF, &custom_fnpf, nios2_expand_custom_XnXX},
|
yann@1
|
6026 |
+ {CODE_FOR_custom_fnpp, "__builtin_custom_fnpp", NIOS2_BUILTIN_CUSTOM_FNPP, &custom_fnpp, nios2_expand_custom_XnXX},
|
yann@1
|
6027 |
+ {CODE_FOR_custom_pn, "__builtin_custom_pn", NIOS2_BUILTIN_CUSTOM_PN, &custom_pn, nios2_expand_custom_Xn},
|
yann@1
|
6028 |
+ {CODE_FOR_custom_pni, "__builtin_custom_pni", NIOS2_BUILTIN_CUSTOM_PNI, &custom_pni, nios2_expand_custom_XnX},
|
yann@1
|
6029 |
+ {CODE_FOR_custom_pnf, "__builtin_custom_pnf", NIOS2_BUILTIN_CUSTOM_PNF, &custom_pnf, nios2_expand_custom_XnX},
|
yann@1
|
6030 |
+ {CODE_FOR_custom_pnp, "__builtin_custom_pnp", NIOS2_BUILTIN_CUSTOM_PNP, &custom_pnp, nios2_expand_custom_XnX},
|
yann@1
|
6031 |
+ {CODE_FOR_custom_pnii, "__builtin_custom_pnii", NIOS2_BUILTIN_CUSTOM_PNII, &custom_pnii, nios2_expand_custom_XnXX},
|
yann@1
|
6032 |
+ {CODE_FOR_custom_pnif, "__builtin_custom_pnif", NIOS2_BUILTIN_CUSTOM_PNIF, &custom_pnif, nios2_expand_custom_XnXX},
|
yann@1
|
6033 |
+ {CODE_FOR_custom_pnip, "__builtin_custom_pnip", NIOS2_BUILTIN_CUSTOM_PNIP, &custom_pnip, nios2_expand_custom_XnXX},
|
yann@1
|
6034 |
+ {CODE_FOR_custom_pnfi, "__builtin_custom_pnfi", NIOS2_BUILTIN_CUSTOM_PNFI, &custom_pnfi, nios2_expand_custom_XnXX},
|
yann@1
|
6035 |
+ {CODE_FOR_custom_pnff, "__builtin_custom_pnff", NIOS2_BUILTIN_CUSTOM_PNFF, &custom_pnff, nios2_expand_custom_XnXX},
|
yann@1
|
6036 |
+ {CODE_FOR_custom_pnfp, "__builtin_custom_pnfp", NIOS2_BUILTIN_CUSTOM_PNFP, &custom_pnfp, nios2_expand_custom_XnXX},
|
yann@1
|
6037 |
+ {CODE_FOR_custom_pnpi, "__builtin_custom_pnpi", NIOS2_BUILTIN_CUSTOM_PNPI, &custom_pnpi, nios2_expand_custom_XnXX},
|
yann@1
|
6038 |
+ {CODE_FOR_custom_pnpf, "__builtin_custom_pnpf", NIOS2_BUILTIN_CUSTOM_PNPF, &custom_pnpf, nios2_expand_custom_XnXX},
|
yann@1
|
6039 |
+ {CODE_FOR_custom_pnpp, "__builtin_custom_pnpp", NIOS2_BUILTIN_CUSTOM_PNPP, &custom_pnpp, nios2_expand_custom_XnXX},
|
yann@1
|
6040 |
+
|
yann@1
|
6041 |
+
|
yann@1
|
6042 |
+ {0, 0, 0, 0, 0},
|
yann@1
|
6043 |
+};
|
yann@1
|
6044 |
+
|
yann@1
|
6045 |
+/* This does not have a closing bracket on purpose (see use) */
|
yann@1
|
6046 |
+#define def_param(TYPE) \
|
yann@1
|
6047 |
+ tree_cons (NULL_TREE, TYPE,
|
yann@1
|
6048 |
+
|
yann@1
|
6049 |
+static void
|
yann@1
|
6050 |
+nios2_init_builtins ()
|
yann@1
|
6051 |
+{
|
yann@1
|
6052 |
+ const struct builtin_description *d;
|
yann@1
|
6053 |
+
|
yann@1
|
6054 |
+
|
yann@1
|
6055 |
+ endlink = void_list_node;
|
yann@1
|
6056 |
+
|
yann@1
|
6057 |
+ /* Special indenting here because one of the brackets is in def_param */
|
yann@1
|
6058 |
+ /* *INDENT-OFF* */
|
yann@1
|
6059 |
+
|
yann@1
|
6060 |
+ /* int fn (volatile const void *)
|
yann@1
|
6061 |
+ */
|
yann@1
|
6062 |
+ int_ftype_volatile_const_void_p
|
yann@1
|
6063 |
+ = build_function_type (integer_type_node,
|
yann@1
|
6064 |
+ def_param (build_qualified_type (ptr_type_node,
|
yann@1
|
6065 |
+ TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE))
|
yann@1
|
6066 |
+ endlink));
|
yann@1
|
6067 |
+
|
yann@1
|
6068 |
+
|
yann@1
|
6069 |
+ /* void fn (volatile void *, int)
|
yann@1
|
6070 |
+ */
|
yann@1
|
6071 |
+ void_ftype_volatile_void_p_int
|
yann@1
|
6072 |
+ = build_function_type (void_type_node,
|
yann@1
|
6073 |
+ def_param (build_qualified_type (ptr_type_node,
|
yann@1
|
6074 |
+ TYPE_QUAL_VOLATILE))
|
yann@1
|
6075 |
+ def_param (integer_type_node)
|
yann@1
|
6076 |
+ endlink)));
|
yann@1
|
6077 |
+
|
yann@1
|
6078 |
+ /* void fn (void)
|
yann@1
|
6079 |
+ */
|
yann@1
|
6080 |
+ void_ftype_void
|
yann@1
|
6081 |
+ = build_function_type (void_type_node,
|
yann@1
|
6082 |
+ endlink);
|
yann@1
|
6083 |
+
|
yann@1
|
6084 |
+ /* int fn (int)
|
yann@1
|
6085 |
+ */
|
yann@1
|
6086 |
+ int_ftype_int
|
yann@1
|
6087 |
+ = build_function_type (integer_type_node,
|
yann@1
|
6088 |
+ def_param (integer_type_node)
|
yann@1
|
6089 |
+ endlink));
|
yann@1
|
6090 |
+
|
yann@1
|
6091 |
+ /* void fn (int, int)
|
yann@1
|
6092 |
+ */
|
yann@1
|
6093 |
+ void_ftype_int_int
|
yann@1
|
6094 |
+ = build_function_type (void_type_node,
|
yann@1
|
6095 |
+ def_param (integer_type_node)
|
yann@1
|
6096 |
+ def_param (integer_type_node)
|
yann@1
|
6097 |
+ endlink)));
|
yann@1
|
6098 |
+
|
yann@1
|
6099 |
+
|
yann@1
|
6100 |
+#define CUSTOM_NUM def_param (integer_type_node)
|
yann@1
|
6101 |
+
|
yann@1
|
6102 |
+ custom_n
|
yann@1
|
6103 |
+ = build_function_type (void_type_node,
|
yann@1
|
6104 |
+ CUSTOM_NUM
|
yann@1
|
6105 |
+ endlink));
|
yann@1
|
6106 |
+ custom_ni
|
yann@1
|
6107 |
+ = build_function_type (void_type_node,
|
yann@1
|
6108 |
+ CUSTOM_NUM
|
yann@1
|
6109 |
+ def_param (integer_type_node)
|
yann@1
|
6110 |
+ endlink)));
|
yann@1
|
6111 |
+ custom_nf
|
yann@1
|
6112 |
+ = build_function_type (void_type_node,
|
yann@1
|
6113 |
+ CUSTOM_NUM
|
yann@1
|
6114 |
+ def_param (float_type_node)
|
yann@1
|
6115 |
+ endlink)));
|
yann@1
|
6116 |
+ custom_np
|
yann@1
|
6117 |
+ = build_function_type (void_type_node,
|
yann@1
|
6118 |
+ CUSTOM_NUM
|
yann@1
|
6119 |
+ def_param (ptr_type_node)
|
yann@1
|
6120 |
+ endlink)));
|
yann@1
|
6121 |
+ custom_nii
|
yann@1
|
6122 |
+ = build_function_type (void_type_node,
|
yann@1
|
6123 |
+ CUSTOM_NUM
|
yann@1
|
6124 |
+ def_param (integer_type_node)
|
yann@1
|
6125 |
+ def_param (integer_type_node)
|
yann@1
|
6126 |
+ endlink))));
|
yann@1
|
6127 |
+ custom_nif
|
yann@1
|
6128 |
+ = build_function_type (void_type_node,
|
yann@1
|
6129 |
+ CUSTOM_NUM
|
yann@1
|
6130 |
+ def_param (integer_type_node)
|
yann@1
|
6131 |
+ def_param (float_type_node)
|
yann@1
|
6132 |
+ endlink))));
|
yann@1
|
6133 |
+ custom_nip
|
yann@1
|
6134 |
+ = build_function_type (void_type_node,
|
yann@1
|
6135 |
+ CUSTOM_NUM
|
yann@1
|
6136 |
+ def_param (integer_type_node)
|
yann@1
|
6137 |
+ def_param (ptr_type_node)
|
yann@1
|
6138 |
+ endlink))));
|
yann@1
|
6139 |
+ custom_nfi
|
yann@1
|
6140 |
+ = build_function_type (void_type_node,
|
yann@1
|
6141 |
+ CUSTOM_NUM
|
yann@1
|
6142 |
+ def_param (float_type_node)
|
yann@1
|
6143 |
+ def_param (integer_type_node)
|
yann@1
|
6144 |
+ endlink))));
|
yann@1
|
6145 |
+ custom_nff
|
yann@1
|
6146 |
+ = build_function_type (void_type_node,
|
yann@1
|
6147 |
+ CUSTOM_NUM
|
yann@1
|
6148 |
+ def_param (float_type_node)
|
yann@1
|
6149 |
+ def_param (float_type_node)
|
yann@1
|
6150 |
+ endlink))));
|
yann@1
|
6151 |
+ custom_nfp
|
yann@1
|
6152 |
+ = build_function_type (void_type_node,
|
yann@1
|
6153 |
+ CUSTOM_NUM
|
yann@1
|
6154 |
+ def_param (float_type_node)
|
yann@1
|
6155 |
+ def_param (ptr_type_node)
|
yann@1
|
6156 |
+ endlink))));
|
yann@1
|
6157 |
+ custom_npi
|
yann@1
|
6158 |
+ = build_function_type (void_type_node,
|
yann@1
|
6159 |
+ CUSTOM_NUM
|
yann@1
|
6160 |
+ def_param (ptr_type_node)
|
yann@1
|
6161 |
+ def_param (integer_type_node)
|
yann@1
|
6162 |
+ endlink))));
|
yann@1
|
6163 |
+ custom_npf
|
yann@1
|
6164 |
+ = build_function_type (void_type_node,
|
yann@1
|
6165 |
+ CUSTOM_NUM
|
yann@1
|
6166 |
+ def_param (ptr_type_node)
|
yann@1
|
6167 |
+ def_param (float_type_node)
|
yann@1
|
6168 |
+ endlink))));
|
yann@1
|
6169 |
+ custom_npp
|
yann@1
|
6170 |
+ = build_function_type (void_type_node,
|
yann@1
|
6171 |
+ CUSTOM_NUM
|
yann@1
|
6172 |
+ def_param (ptr_type_node)
|
yann@1
|
6173 |
+ def_param (ptr_type_node)
|
yann@1
|
6174 |
+ endlink))));
|
yann@1
|
6175 |
+
|
yann@1
|
6176 |
+ custom_in
|
yann@1
|
6177 |
+ = build_function_type (integer_type_node,
|
yann@1
|
6178 |
+ CUSTOM_NUM
|
yann@1
|
6179 |
+ endlink));
|
yann@1
|
6180 |
+ custom_ini
|
yann@1
|
6181 |
+ = build_function_type (integer_type_node,
|
yann@1
|
6182 |
+ CUSTOM_NUM
|
yann@1
|
6183 |
+ def_param (integer_type_node)
|
yann@1
|
6184 |
+ endlink)));
|
yann@1
|
6185 |
+ custom_inf
|
yann@1
|
6186 |
+ = build_function_type (integer_type_node,
|
yann@1
|
6187 |
+ CUSTOM_NUM
|
yann@1
|
6188 |
+ def_param (float_type_node)
|
yann@1
|
6189 |
+ endlink)));
|
yann@1
|
6190 |
+ custom_inp
|
yann@1
|
6191 |
+ = build_function_type (integer_type_node,
|
yann@1
|
6192 |
+ CUSTOM_NUM
|
yann@1
|
6193 |
+ def_param (ptr_type_node)
|
yann@1
|
6194 |
+ endlink)));
|
yann@1
|
6195 |
+ custom_inii
|
yann@1
|
6196 |
+ = build_function_type (integer_type_node,
|
yann@1
|
6197 |
+ CUSTOM_NUM
|
yann@1
|
6198 |
+ def_param (integer_type_node)
|
yann@1
|
6199 |
+ def_param (integer_type_node)
|
yann@1
|
6200 |
+ endlink))));
|
yann@1
|
6201 |
+ custom_inif
|
yann@1
|
6202 |
+ = build_function_type (integer_type_node,
|
yann@1
|
6203 |
+ CUSTOM_NUM
|
yann@1
|
6204 |
+ def_param (integer_type_node)
|
yann@1
|
6205 |
+ def_param (float_type_node)
|
yann@1
|
6206 |
+ endlink))));
|
yann@1
|
6207 |
+ custom_inip
|
yann@1
|
6208 |
+ = build_function_type (integer_type_node,
|
yann@1
|
6209 |
+ CUSTOM_NUM
|
yann@1
|
6210 |
+ def_param (integer_type_node)
|
yann@1
|
6211 |
+ def_param (ptr_type_node)
|
yann@1
|
6212 |
+ endlink))));
|
yann@1
|
6213 |
+ custom_infi
|
yann@1
|
6214 |
+ = build_function_type (integer_type_node,
|
yann@1
|
6215 |
+ CUSTOM_NUM
|
yann@1
|
6216 |
+ def_param (float_type_node)
|
yann@1
|
6217 |
+ def_param (integer_type_node)
|
yann@1
|
6218 |
+ endlink))));
|
yann@1
|
6219 |
+ custom_inff
|
yann@1
|
6220 |
+ = build_function_type (integer_type_node,
|
yann@1
|
6221 |
+ CUSTOM_NUM
|
yann@1
|
6222 |
+ def_param (float_type_node)
|
yann@1
|
6223 |
+ def_param (float_type_node)
|
yann@1
|
6224 |
+ endlink))));
|
yann@1
|
6225 |
+ custom_infp
|
yann@1
|
6226 |
+ = build_function_type (integer_type_node,
|
yann@1
|
6227 |
+ CUSTOM_NUM
|
yann@1
|
6228 |
+ def_param (float_type_node)
|
yann@1
|
6229 |
+ def_param (ptr_type_node)
|
yann@1
|
6230 |
+ endlink))));
|
yann@1
|
6231 |
+ custom_inpi
|
yann@1
|
6232 |
+ = build_function_type (integer_type_node,
|
yann@1
|
6233 |
+ CUSTOM_NUM
|
yann@1
|
6234 |
+ def_param (ptr_type_node)
|
yann@1
|
6235 |
+ def_param (integer_type_node)
|
yann@1
|
6236 |
+ endlink))));
|
yann@1
|
6237 |
+ custom_inpf
|
yann@1
|
6238 |
+ = build_function_type (integer_type_node,
|
yann@1
|
6239 |
+ CUSTOM_NUM
|
yann@1
|
6240 |
+ def_param (ptr_type_node)
|
yann@1
|
6241 |
+ def_param (float_type_node)
|
yann@1
|
6242 |
+ endlink))));
|
yann@1
|
6243 |
+ custom_inpp
|
yann@1
|
6244 |
+ = build_function_type (integer_type_node,
|
yann@1
|
6245 |
+ CUSTOM_NUM
|
yann@1
|
6246 |
+ def_param (ptr_type_node)
|
yann@1
|
6247 |
+ def_param (ptr_type_node)
|
yann@1
|
6248 |
+ endlink))));
|
yann@1
|
6249 |
+
|
yann@1
|
6250 |
+ custom_fn
|
yann@1
|
6251 |
+ = build_function_type (float_type_node,
|
yann@1
|
6252 |
+ CUSTOM_NUM
|
yann@1
|
6253 |
+ endlink));
|
yann@1
|
6254 |
+ custom_fni
|
yann@1
|
6255 |
+ = build_function_type (float_type_node,
|
yann@1
|
6256 |
+ CUSTOM_NUM
|
yann@1
|
6257 |
+ def_param (integer_type_node)
|
yann@1
|
6258 |
+ endlink)));
|
yann@1
|
6259 |
+ custom_fnf
|
yann@1
|
6260 |
+ = build_function_type (float_type_node,
|
yann@1
|
6261 |
+ CUSTOM_NUM
|
yann@1
|
6262 |
+ def_param (float_type_node)
|
yann@1
|
6263 |
+ endlink)));
|
yann@1
|
6264 |
+ custom_fnp
|
yann@1
|
6265 |
+ = build_function_type (float_type_node,
|
yann@1
|
6266 |
+ CUSTOM_NUM
|
yann@1
|
6267 |
+ def_param (ptr_type_node)
|
yann@1
|
6268 |
+ endlink)));
|
yann@1
|
6269 |
+ custom_fnii
|
yann@1
|
6270 |
+ = build_function_type (float_type_node,
|
yann@1
|
6271 |
+ CUSTOM_NUM
|
yann@1
|
6272 |
+ def_param (integer_type_node)
|
yann@1
|
6273 |
+ def_param (integer_type_node)
|
yann@1
|
6274 |
+ endlink))));
|
yann@1
|
6275 |
+ custom_fnif
|
yann@1
|
6276 |
+ = build_function_type (float_type_node,
|
yann@1
|
6277 |
+ CUSTOM_NUM
|
yann@1
|
6278 |
+ def_param (integer_type_node)
|
yann@1
|
6279 |
+ def_param (float_type_node)
|
yann@1
|
6280 |
+ endlink))));
|
yann@1
|
6281 |
+ custom_fnip
|
yann@1
|
6282 |
+ = build_function_type (float_type_node,
|
yann@1
|
6283 |
+ CUSTOM_NUM
|
yann@1
|
6284 |
+ def_param (integer_type_node)
|
yann@1
|
6285 |
+ def_param (ptr_type_node)
|
yann@1
|
6286 |
+ endlink))));
|
yann@1
|
6287 |
+ custom_fnfi
|
yann@1
|
6288 |
+ = build_function_type (float_type_node,
|
yann@1
|
6289 |
+ CUSTOM_NUM
|
yann@1
|
6290 |
+ def_param (float_type_node)
|
yann@1
|
6291 |
+ def_param (integer_type_node)
|
yann@1
|
6292 |
+ endlink))));
|
yann@1
|
6293 |
+ custom_fnff
|
yann@1
|
6294 |
+ = build_function_type (float_type_node,
|
yann@1
|
6295 |
+ CUSTOM_NUM
|
yann@1
|
6296 |
+ def_param (float_type_node)
|
yann@1
|
6297 |
+ def_param (float_type_node)
|
yann@1
|
6298 |
+ endlink))));
|
yann@1
|
6299 |
+ custom_fnfp
|
yann@1
|
6300 |
+ = build_function_type (float_type_node,
|
yann@1
|
6301 |
+ CUSTOM_NUM
|
yann@1
|
6302 |
+ def_param (float_type_node)
|
yann@1
|
6303 |
+ def_param (ptr_type_node)
|
yann@1
|
6304 |
+ endlink))));
|
yann@1
|
6305 |
+ custom_fnpi
|
yann@1
|
6306 |
+ = build_function_type (float_type_node,
|
yann@1
|
6307 |
+ CUSTOM_NUM
|
yann@1
|
6308 |
+ def_param (ptr_type_node)
|
yann@1
|
6309 |
+ def_param (integer_type_node)
|
yann@1
|
6310 |
+ endlink))));
|
yann@1
|
6311 |
+ custom_fnpf
|
yann@1
|
6312 |
+ = build_function_type (float_type_node,
|
yann@1
|
6313 |
+ CUSTOM_NUM
|
yann@1
|
6314 |
+ def_param (ptr_type_node)
|
yann@1
|
6315 |
+ def_param (float_type_node)
|
yann@1
|
6316 |
+ endlink))));
|
yann@1
|
6317 |
+ custom_fnpp
|
yann@1
|
6318 |
+ = build_function_type (float_type_node,
|
yann@1
|
6319 |
+ CUSTOM_NUM
|
yann@1
|
6320 |
+ def_param (ptr_type_node)
|
yann@1
|
6321 |
+ def_param (ptr_type_node)
|
yann@1
|
6322 |
+ endlink))));
|
yann@1
|
6323 |
+
|
yann@1
|
6324 |
+
|
yann@1
|
6325 |
+ custom_pn
|
yann@1
|
6326 |
+ = build_function_type (ptr_type_node,
|
yann@1
|
6327 |
+ CUSTOM_NUM
|
yann@1
|
6328 |
+ endlink));
|
yann@1
|
6329 |
+ custom_pni
|
yann@1
|
6330 |
+ = build_function_type (ptr_type_node,
|
yann@1
|
6331 |
+ CUSTOM_NUM
|
yann@1
|
6332 |
+ def_param (integer_type_node)
|
yann@1
|
6333 |
+ endlink)));
|
yann@1
|
6334 |
+ custom_pnf
|
yann@1
|
6335 |
+ = build_function_type (ptr_type_node,
|
yann@1
|
6336 |
+ CUSTOM_NUM
|
yann@1
|
6337 |
+ def_param (float_type_node)
|
yann@1
|
6338 |
+ endlink)));
|
yann@1
|
6339 |
+ custom_pnp
|
yann@1
|
6340 |
+ = build_function_type (ptr_type_node,
|
yann@1
|
6341 |
+ CUSTOM_NUM
|
yann@1
|
6342 |
+ def_param (ptr_type_node)
|
yann@1
|
6343 |
+ endlink)));
|
yann@1
|
6344 |
+ custom_pnii
|
yann@1
|
6345 |
+ = build_function_type (ptr_type_node,
|
yann@1
|
6346 |
+ CUSTOM_NUM
|
yann@1
|
6347 |
+ def_param (integer_type_node)
|
yann@1
|
6348 |
+ def_param (integer_type_node)
|
yann@1
|
6349 |
+ endlink))));
|
yann@1
|
6350 |
+ custom_pnif
|
yann@1
|
6351 |
+ = build_function_type (ptr_type_node,
|
yann@1
|
6352 |
+ CUSTOM_NUM
|
yann@1
|
6353 |
+ def_param (integer_type_node)
|
yann@1
|
6354 |
+ def_param (float_type_node)
|
yann@1
|
6355 |
+ endlink))));
|
yann@1
|
6356 |
+ custom_pnip
|
yann@1
|
6357 |
+ = build_function_type (ptr_type_node,
|
yann@1
|
6358 |
+ CUSTOM_NUM
|
yann@1
|
6359 |
+ def_param (integer_type_node)
|
yann@1
|
6360 |
+ def_param (ptr_type_node)
|
yann@1
|
6361 |
+ endlink))));
|
yann@1
|
6362 |
+ custom_pnfi
|
yann@1
|
6363 |
+ = build_function_type (ptr_type_node,
|
yann@1
|
6364 |
+ CUSTOM_NUM
|
yann@1
|
6365 |
+ def_param (float_type_node)
|
yann@1
|
6366 |
+ def_param (integer_type_node)
|
yann@1
|
6367 |
+ endlink))));
|
yann@1
|
6368 |
+ custom_pnff
|
yann@1
|
6369 |
+ = build_function_type (ptr_type_node,
|
yann@1
|
6370 |
+ CUSTOM_NUM
|
yann@1
|
6371 |
+ def_param (float_type_node)
|
yann@1
|
6372 |
+ def_param (float_type_node)
|
yann@1
|
6373 |
+ endlink))));
|
yann@1
|
6374 |
+ custom_pnfp
|
yann@1
|
6375 |
+ = build_function_type (ptr_type_node,
|
yann@1
|
6376 |
+ CUSTOM_NUM
|
yann@1
|
6377 |
+ def_param (float_type_node)
|
yann@1
|
6378 |
+ def_param (ptr_type_node)
|
yann@1
|
6379 |
+ endlink))));
|
yann@1
|
6380 |
+ custom_pnpi
|
yann@1
|
6381 |
+ = build_function_type (ptr_type_node,
|
yann@1
|
6382 |
+ CUSTOM_NUM
|
yann@1
|
6383 |
+ def_param (ptr_type_node)
|
yann@1
|
6384 |
+ def_param (integer_type_node)
|
yann@1
|
6385 |
+ endlink))));
|
yann@1
|
6386 |
+ custom_pnpf
|
yann@1
|
6387 |
+ = build_function_type (ptr_type_node,
|
yann@1
|
6388 |
+ CUSTOM_NUM
|
yann@1
|
6389 |
+ def_param (ptr_type_node)
|
yann@1
|
6390 |
+ def_param (float_type_node)
|
yann@1
|
6391 |
+ endlink))));
|
yann@1
|
6392 |
+ custom_pnpp
|
yann@1
|
6393 |
+ = build_function_type (ptr_type_node,
|
yann@1
|
6394 |
+ CUSTOM_NUM
|
yann@1
|
6395 |
+ def_param (ptr_type_node)
|
yann@1
|
6396 |
+ def_param (ptr_type_node)
|
yann@1
|
6397 |
+ endlink))));
|
yann@1
|
6398 |
+
|
yann@1
|
6399 |
+
|
yann@1
|
6400 |
+
|
yann@1
|
6401 |
+ /* *INDENT-ON* */
|
yann@1
|
6402 |
+
|
yann@1
|
6403 |
+
|
yann@1
|
6404 |
+ for (d = bdesc; d->name; d++)
|
yann@1
|
6405 |
+ {
|
yann@1
|
6406 |
+ builtin_function (d->name, *d->type, d->code,
|
yann@1
|
6407 |
+ BUILT_IN_MD, NULL, NULL);
|
yann@1
|
6408 |
+ }
|
yann@1
|
6409 |
+}
|
yann@1
|
6410 |
+
|
yann@1
|
6411 |
+/* Expand an expression EXP that calls a built-in function,
|
yann@1
|
6412 |
+ with result going to TARGET if that's convenient
|
yann@1
|
6413 |
+ (and in mode MODE if that's convenient).
|
yann@1
|
6414 |
+ SUBTARGET may be used as the target for computing one of EXP's operands.
|
yann@1
|
6415 |
+ IGNORE is nonzero if the value is to be ignored. */
|
yann@1
|
6416 |
+
|
yann@1
|
6417 |
+static rtx
|
yann@1
|
6418 |
+nios2_expand_builtin (tree exp, rtx target, rtx subtarget,
|
yann@1
|
6419 |
+ enum machine_mode mode, int ignore)
|
yann@1
|
6420 |
+{
|
yann@1
|
6421 |
+ const struct builtin_description *d;
|
yann@1
|
6422 |
+ tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
|
yann@1
|
6423 |
+ unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
|
yann@1
|
6424 |
+
|
yann@1
|
6425 |
+ for (d = bdesc; d->name; d++)
|
yann@1
|
6426 |
+ if (d->code == fcode)
|
yann@1
|
6427 |
+ return (d->expander) (d, exp, target, subtarget, mode, ignore);
|
yann@1
|
6428 |
+
|
yann@1
|
6429 |
+ /* we should have seen one of the functins we registered */
|
yann@1
|
6430 |
+ abort ();
|
yann@1
|
6431 |
+}
|
yann@1
|
6432 |
+
|
yann@1
|
6433 |
+static rtx nios2_create_target (const struct builtin_description *, rtx);
|
yann@1
|
6434 |
+
|
yann@1
|
6435 |
+
|
yann@1
|
6436 |
+static rtx
|
yann@1
|
6437 |
+nios2_create_target (const struct builtin_description *d, rtx target)
|
yann@1
|
6438 |
+{
|
yann@1
|
6439 |
+ if (!target
|
yann@1
|
6440 |
+ || !(*insn_data[d->icode].operand[0].predicate) (target,
|
yann@1
|
6441 |
+ insn_data[d->icode].operand[0].mode))
|
yann@1
|
6442 |
+ {
|
yann@1
|
6443 |
+ target = gen_reg_rtx (insn_data[d->icode].operand[0].mode);
|
yann@1
|
6444 |
+ }
|
yann@1
|
6445 |
+
|
yann@1
|
6446 |
+ return target;
|
yann@1
|
6447 |
+}
|
yann@1
|
6448 |
+
|
yann@1
|
6449 |
+
|
yann@1
|
6450 |
+static rtx nios2_extract_opcode (const struct builtin_description *, int, tree);
|
yann@1
|
6451 |
+static rtx nios2_extract_operand (const struct builtin_description *, int, int, tree);
|
yann@1
|
6452 |
+
|
yann@1
|
6453 |
+static rtx
|
yann@1
|
6454 |
+nios2_extract_opcode (const struct builtin_description *d, int op, tree arglist)
|
yann@1
|
6455 |
+{
|
yann@1
|
6456 |
+ enum machine_mode mode = insn_data[d->icode].operand[op].mode;
|
yann@1
|
6457 |
+ tree arg = TREE_VALUE (arglist);
|
yann@1
|
6458 |
+ rtx opcode = expand_expr (arg, NULL_RTX, mode, 0);
|
yann@1
|
6459 |
+ opcode = protect_from_queue (opcode, 0);
|
yann@1
|
6460 |
+
|
yann@1
|
6461 |
+ if (!(*insn_data[d->icode].operand[op].predicate) (opcode, mode))
|
yann@1
|
6462 |
+ error ("Custom instruction opcode must be compile time constant in the range 0-255 for %s", d->name);
|
yann@1
|
6463 |
+
|
yann@1
|
6464 |
+ return opcode;
|
yann@1
|
6465 |
+}
|
yann@1
|
6466 |
+
|
yann@1
|
6467 |
+static rtx
|
yann@1
|
6468 |
+nios2_extract_operand (const struct builtin_description *d, int op, int argnum, tree arglist)
|
yann@1
|
6469 |
+{
|
yann@1
|
6470 |
+ enum machine_mode mode = insn_data[d->icode].operand[op].mode;
|
yann@1
|
6471 |
+ tree arg = TREE_VALUE (arglist);
|
yann@1
|
6472 |
+ rtx operand = expand_expr (arg, NULL_RTX, mode, 0);
|
yann@1
|
6473 |
+ operand = protect_from_queue (operand, 0);
|
yann@1
|
6474 |
+
|
yann@1
|
6475 |
+ if (!(*insn_data[d->icode].operand[op].predicate) (operand, mode))
|
yann@1
|
6476 |
+ operand = copy_to_mode_reg (mode, operand);
|
yann@1
|
6477 |
+
|
yann@1
|
6478 |
+ /* ??? Better errors would be nice */
|
yann@1
|
6479 |
+ if (!(*insn_data[d->icode].operand[op].predicate) (operand, mode))
|
yann@1
|
6480 |
+ error ("Invalid argument %d to %s", argnum, d->name);
|
yann@1
|
6481 |
+
|
yann@1
|
6482 |
+ return operand;
|
yann@1
|
6483 |
+}
|
yann@1
|
6484 |
+
|
yann@1
|
6485 |
+
|
yann@1
|
6486 |
+static rtx
|
yann@1
|
6487 |
+nios2_expand_custom_n (const struct builtin_description *d, tree exp,
|
yann@1
|
6488 |
+ rtx target ATTRIBUTE_UNUSED, rtx subtarget ATTRIBUTE_UNUSED,
|
yann@1
|
6489 |
+ enum machine_mode mode ATTRIBUTE_UNUSED, int ignore ATTRIBUTE_UNUSED)
|
yann@1
|
6490 |
+{
|
yann@1
|
6491 |
+ tree arglist = TREE_OPERAND (exp, 1);
|
yann@1
|
6492 |
+ rtx pat;
|
yann@1
|
6493 |
+ rtx opcode;
|
yann@1
|
6494 |
+
|
yann@1
|
6495 |
+ /* custom_n should have exactly one operand */
|
yann@1
|
6496 |
+ if (insn_data[d->icode].n_operands != 1)
|
yann@1
|
6497 |
+ abort ();
|
yann@1
|
6498 |
+
|
yann@1
|
6499 |
+ opcode = nios2_extract_opcode (d, 0, arglist);
|
yann@1
|
6500 |
+
|
yann@1
|
6501 |
+ pat = GEN_FCN (d->icode) (opcode);
|
yann@1
|
6502 |
+ if (!pat)
|
yann@1
|
6503 |
+ return 0;
|
yann@1
|
6504 |
+ emit_insn (pat);
|
yann@1
|
6505 |
+ return 0;
|
yann@1
|
6506 |
+}
|
yann@1
|
6507 |
+
|
yann@1
|
6508 |
+static rtx
|
yann@1
|
6509 |
+nios2_expand_custom_Xn (const struct builtin_description *d, tree exp,
|
yann@1
|
6510 |
+ rtx target, rtx subtarget ATTRIBUTE_UNUSED,
|
yann@1
|
6511 |
+ enum machine_mode mode ATTRIBUTE_UNUSED,
|
yann@1
|
6512 |
+ int ignore ATTRIBUTE_UNUSED)
|
yann@1
|
6513 |
+{
|
yann@1
|
6514 |
+ tree arglist = TREE_OPERAND (exp, 1);
|
yann@1
|
6515 |
+ rtx pat;
|
yann@1
|
6516 |
+ rtx opcode;
|
yann@1
|
6517 |
+
|
yann@1
|
6518 |
+ /* custom_Xn should have exactly two operands */
|
yann@1
|
6519 |
+ if (insn_data[d->icode].n_operands != 2)
|
yann@1
|
6520 |
+ abort ();
|
yann@1
|
6521 |
+
|
yann@1
|
6522 |
+ target = nios2_create_target (d, target);
|
yann@1
|
6523 |
+ opcode = nios2_extract_opcode (d, 1, arglist);
|
yann@1
|
6524 |
+
|
yann@1
|
6525 |
+ pat = GEN_FCN (d->icode) (target, opcode);
|
yann@1
|
6526 |
+ if (!pat)
|
yann@1
|
6527 |
+ return 0;
|
yann@1
|
6528 |
+ emit_insn (pat);
|
yann@1
|
6529 |
+ return target;
|
yann@1
|
6530 |
+}
|
yann@1
|
6531 |
+
|
yann@1
|
6532 |
+static rtx
|
yann@1
|
6533 |
+nios2_expand_custom_nX (const struct builtin_description *d, tree exp,
|
yann@1
|
6534 |
+ rtx target ATTRIBUTE_UNUSED, rtx subtarget ATTRIBUTE_UNUSED,
|
yann@1
|
6535 |
+ enum machine_mode mode ATTRIBUTE_UNUSED, int ignore ATTRIBUTE_UNUSED)
|
yann@1
|
6536 |
+{
|
yann@1
|
6537 |
+ tree arglist = TREE_OPERAND (exp, 1);
|
yann@1
|
6538 |
+ rtx pat;
|
yann@1
|
6539 |
+ rtx opcode;
|
yann@1
|
6540 |
+ rtx operands[1];
|
yann@1
|
6541 |
+ int i;
|
yann@1
|
6542 |
+
|
yann@1
|
6543 |
+
|
yann@1
|
6544 |
+ /* custom_nX should have exactly two operands */
|
yann@1
|
6545 |
+ if (insn_data[d->icode].n_operands != 2)
|
yann@1
|
6546 |
+ abort ();
|
yann@1
|
6547 |
+
|
yann@1
|
6548 |
+ opcode = nios2_extract_opcode (d, 0, arglist);
|
yann@1
|
6549 |
+ for (i = 0; i < 1; i++)
|
yann@1
|
6550 |
+ {
|
yann@1
|
6551 |
+ arglist = TREE_CHAIN (arglist);
|
yann@1
|
6552 |
+ operands[i] = nios2_extract_operand (d, i + 1, i + 1, arglist);
|
yann@1
|
6553 |
+ }
|
yann@1
|
6554 |
+
|
yann@1
|
6555 |
+ pat = GEN_FCN (d->icode) (opcode, operands[0]);
|
yann@1
|
6556 |
+ if (!pat)
|
yann@1
|
6557 |
+ return 0;
|
yann@1
|
6558 |
+ emit_insn (pat);
|
yann@1
|
6559 |
+ return 0;
|
yann@1
|
6560 |
+}
|
yann@1
|
6561 |
+
|
yann@1
|
6562 |
+static rtx
|
yann@1
|
6563 |
+nios2_expand_custom_XnX (const struct builtin_description *d, tree exp, rtx target,
|
yann@1
|
6564 |
+ rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED,
|
yann@1
|
6565 |
+ int ignore ATTRIBUTE_UNUSED)
|
yann@1
|
6566 |
+{
|
yann@1
|
6567 |
+ tree arglist = TREE_OPERAND (exp, 1);
|
yann@1
|
6568 |
+ rtx pat;
|
yann@1
|
6569 |
+ rtx opcode;
|
yann@1
|
6570 |
+ rtx operands[1];
|
yann@1
|
6571 |
+ int i;
|
yann@1
|
6572 |
+
|
yann@1
|
6573 |
+ /* custom_Xn should have exactly three operands */
|
yann@1
|
6574 |
+ if (insn_data[d->icode].n_operands != 3)
|
yann@1
|
6575 |
+ abort ();
|
yann@1
|
6576 |
+
|
yann@1
|
6577 |
+ target = nios2_create_target (d, target);
|
yann@1
|
6578 |
+ opcode = nios2_extract_opcode (d, 1, arglist);
|
yann@1
|
6579 |
+
|
yann@1
|
6580 |
+ for (i = 0; i < 1; i++)
|
yann@1
|
6581 |
+ {
|
yann@1
|
6582 |
+ arglist = TREE_CHAIN (arglist);
|
yann@1
|
6583 |
+ operands[i] = nios2_extract_operand (d, i + 2, i + 1, arglist);
|
yann@1
|
6584 |
+ }
|
yann@1
|
6585 |
+
|
yann@1
|
6586 |
+ pat = GEN_FCN (d->icode) (target, opcode, operands[0]);
|
yann@1
|
6587 |
+
|
yann@1
|
6588 |
+ if (!pat)
|
yann@1
|
6589 |
+ return 0;
|
yann@1
|
6590 |
+ emit_insn (pat);
|
yann@1
|
6591 |
+ return target;
|
yann@1
|
6592 |
+}
|
yann@1
|
6593 |
+
|
yann@1
|
6594 |
+static rtx
|
yann@1
|
6595 |
+nios2_expand_custom_nXX (const struct builtin_description *d, tree exp, rtx target ATTRIBUTE_UNUSED,
|
yann@1
|
6596 |
+ rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED,
|
yann@1
|
6597 |
+ int ignore ATTRIBUTE_UNUSED)
|
yann@1
|
6598 |
+{
|
yann@1
|
6599 |
+ tree arglist = TREE_OPERAND (exp, 1);
|
yann@1
|
6600 |
+ rtx pat;
|
yann@1
|
6601 |
+ rtx opcode;
|
yann@1
|
6602 |
+ rtx operands[2];
|
yann@1
|
6603 |
+ int i;
|
yann@1
|
6604 |
+
|
yann@1
|
6605 |
+
|
yann@1
|
6606 |
+ /* custom_nX should have exactly three operands */
|
yann@1
|
6607 |
+ if (insn_data[d->icode].n_operands != 3)
|
yann@1
|
6608 |
+ abort ();
|
yann@1
|
6609 |
+
|
yann@1
|
6610 |
+ opcode = nios2_extract_opcode (d, 0, arglist);
|
yann@1
|
6611 |
+ for (i = 0; i < 2; i++)
|
yann@1
|
6612 |
+ {
|
yann@1
|
6613 |
+ arglist = TREE_CHAIN (arglist);
|
yann@1
|
6614 |
+ operands[i] = nios2_extract_operand (d, i + 1, i + 1, arglist);
|
yann@1
|
6615 |
+ }
|
yann@1
|
6616 |
+
|
yann@1
|
6617 |
+ pat = GEN_FCN (d->icode) (opcode, operands[0], operands[1]);
|
yann@1
|
6618 |
+ if (!pat)
|
yann@1
|
6619 |
+ return 0;
|
yann@1
|
6620 |
+ emit_insn (pat);
|
yann@1
|
6621 |
+ return 0;
|
yann@1
|
6622 |
+}
|
yann@1
|
6623 |
+
|
yann@1
|
6624 |
+static rtx
|
yann@1
|
6625 |
+nios2_expand_custom_XnXX (const struct builtin_description *d, tree exp, rtx target,
|
yann@1
|
6626 |
+ rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED,
|
yann@1
|
6627 |
+ int ignore ATTRIBUTE_UNUSED)
|
yann@1
|
6628 |
+{
|
yann@1
|
6629 |
+ tree arglist = TREE_OPERAND (exp, 1);
|
yann@1
|
6630 |
+ rtx pat;
|
yann@1
|
6631 |
+ rtx opcode;
|
yann@1
|
6632 |
+ rtx operands[2];
|
yann@1
|
6633 |
+ int i;
|
yann@1
|
6634 |
+
|
yann@1
|
6635 |
+
|
yann@1
|
6636 |
+ /* custom_XnX should have exactly four operands */
|
yann@1
|
6637 |
+ if (insn_data[d->icode].n_operands != 4)
|
yann@1
|
6638 |
+ abort ();
|
yann@1
|
6639 |
+
|
yann@1
|
6640 |
+ target = nios2_create_target (d, target);
|
yann@1
|
6641 |
+ opcode = nios2_extract_opcode (d, 1, arglist);
|
yann@1
|
6642 |
+ for (i = 0; i < 2; i++)
|
yann@1
|
6643 |
+ {
|
yann@1
|
6644 |
+ arglist = TREE_CHAIN (arglist);
|
yann@1
|
6645 |
+ operands[i] = nios2_extract_operand (d, i + 2, i + 1, arglist);
|
yann@1
|
6646 |
+ }
|
yann@1
|
6647 |
+
|
yann@1
|
6648 |
+ pat = GEN_FCN (d->icode) (target, opcode, operands[0], operands[1]);
|
yann@1
|
6649 |
+
|
yann@1
|
6650 |
+ if (!pat)
|
yann@1
|
6651 |
+ return 0;
|
yann@1
|
6652 |
+ emit_insn (pat);
|
yann@1
|
6653 |
+ return target;
|
yann@1
|
6654 |
+}
|
yann@1
|
6655 |
+
|
yann@1
|
6656 |
+
|
yann@1
|
6657 |
+
|
yann@1
|
6658 |
+static rtx
|
yann@1
|
6659 |
+nios2_expand_STXIO (const struct builtin_description *d, tree exp, rtx target ATTRIBUTE_UNUSED,
|
yann@1
|
6660 |
+ rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED,
|
yann@1
|
6661 |
+ int ignore ATTRIBUTE_UNUSED)
|
yann@1
|
6662 |
+{
|
yann@1
|
6663 |
+ tree arglist = TREE_OPERAND (exp, 1);
|
yann@1
|
6664 |
+ rtx pat;
|
yann@1
|
6665 |
+ rtx store_dest, store_val;
|
yann@1
|
6666 |
+ enum insn_code icode = d->icode;
|
yann@1
|
6667 |
+
|
yann@1
|
6668 |
+ /* stores should have exactly two operands */
|
yann@1
|
6669 |
+ if (insn_data[icode].n_operands != 2)
|
yann@1
|
6670 |
+ abort ();
|
yann@1
|
6671 |
+
|
yann@1
|
6672 |
+ /* process the destination of the store */
|
yann@1
|
6673 |
+ {
|
yann@1
|
6674 |
+ enum machine_mode mode = insn_data[icode].operand[0].mode;
|
yann@1
|
6675 |
+ tree arg = TREE_VALUE (arglist);
|
yann@1
|
6676 |
+ store_dest = expand_expr (arg, NULL_RTX, VOIDmode, 0);
|
yann@1
|
6677 |
+ store_dest = protect_from_queue (store_dest, 0);
|
yann@1
|
6678 |
+
|
yann@1
|
6679 |
+ store_dest = gen_rtx_MEM (mode, copy_to_mode_reg (Pmode, store_dest));
|
yann@1
|
6680 |
+
|
yann@1
|
6681 |
+ /* ??? Better errors would be nice */
|
yann@1
|
6682 |
+ if (!(*insn_data[icode].operand[0].predicate) (store_dest, mode))
|
yann@1
|
6683 |
+ error ("Invalid argument 1 to %s", d->name);
|
yann@1
|
6684 |
+ }
|
yann@1
|
6685 |
+
|
yann@1
|
6686 |
+
|
yann@1
|
6687 |
+ /* process the value to store */
|
yann@1
|
6688 |
+ {
|
yann@1
|
6689 |
+ enum machine_mode mode = insn_data[icode].operand[1].mode;
|
yann@1
|
6690 |
+ tree arg = TREE_VALUE (TREE_CHAIN (arglist));
|
yann@1
|
6691 |
+ store_val = expand_expr (arg, NULL_RTX, mode, 0);
|
yann@1
|
6692 |
+ store_val = protect_from_queue (store_val, 0);
|
yann@1
|
6693 |
+
|
yann@1
|
6694 |
+ if (!(*insn_data[icode].operand[1].predicate) (store_val, mode))
|
yann@1
|
6695 |
+ store_val = copy_to_mode_reg (mode, store_val);
|
yann@1
|
6696 |
+
|
yann@1
|
6697 |
+ /* ??? Better errors would be nice */
|
yann@1
|
6698 |
+ if (!(*insn_data[icode].operand[1].predicate) (store_val, mode))
|
yann@1
|
6699 |
+ error ("Invalid argument 2 to %s", d->name);
|
yann@1
|
6700 |
+ }
|
yann@1
|
6701 |
+
|
yann@1
|
6702 |
+ pat = GEN_FCN (d->icode) (store_dest, store_val);
|
yann@1
|
6703 |
+ if (!pat)
|
yann@1
|
6704 |
+ return 0;
|
yann@1
|
6705 |
+ emit_insn (pat);
|
yann@1
|
6706 |
+ return 0;
|
yann@1
|
6707 |
+}
|
yann@1
|
6708 |
+
|
yann@1
|
6709 |
+
|
yann@1
|
6710 |
+static rtx
|
yann@1
|
6711 |
+nios2_expand_LDXIO (const struct builtin_description * d, tree exp, rtx target,
|
yann@1
|
6712 |
+ rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED,
|
yann@1
|
6713 |
+ int ignore ATTRIBUTE_UNUSED)
|
yann@1
|
6714 |
+{
|
yann@1
|
6715 |
+ tree arglist = TREE_OPERAND (exp, 1);
|
yann@1
|
6716 |
+ rtx pat;
|
yann@1
|
6717 |
+ rtx ld_src;
|
yann@1
|
6718 |
+ enum insn_code icode = d->icode;
|
yann@1
|
6719 |
+
|
yann@1
|
6720 |
+ /* loads should have exactly two operands */
|
yann@1
|
6721 |
+ if (insn_data[icode].n_operands != 2)
|
yann@1
|
6722 |
+ abort ();
|
yann@1
|
6723 |
+
|
yann@1
|
6724 |
+ target = nios2_create_target (d, target);
|
yann@1
|
6725 |
+
|
yann@1
|
6726 |
+ {
|
yann@1
|
6727 |
+ enum machine_mode mode = insn_data[icode].operand[1].mode;
|
yann@1
|
6728 |
+ tree arg = TREE_VALUE (arglist);
|
yann@1
|
6729 |
+ ld_src = expand_expr (arg, NULL_RTX, VOIDmode, 0);
|
yann@1
|
6730 |
+ ld_src = protect_from_queue (ld_src, 0);
|
yann@1
|
6731 |
+
|
yann@1
|
6732 |
+ ld_src = gen_rtx_MEM (mode, copy_to_mode_reg (Pmode, ld_src));
|
yann@1
|
6733 |
+
|
yann@1
|
6734 |
+ /* ??? Better errors would be nice */
|
yann@1
|
6735 |
+ if (!(*insn_data[icode].operand[1].predicate) (ld_src, mode))
|
yann@1
|
6736 |
+ {
|
yann@1
|
6737 |
+ error ("Invalid argument 1 to %s", d->name);
|
yann@1
|
6738 |
+ }
|
yann@1
|
6739 |
+ }
|
yann@1
|
6740 |
+
|
yann@1
|
6741 |
+ pat = GEN_FCN (d->icode) (target, ld_src);
|
yann@1
|
6742 |
+ if (!pat)
|
yann@1
|
6743 |
+ return 0;
|
yann@1
|
6744 |
+ emit_insn (pat);
|
yann@1
|
6745 |
+ return target;
|
yann@1
|
6746 |
+}
|
yann@1
|
6747 |
+
|
yann@1
|
6748 |
+
|
yann@1
|
6749 |
+static rtx
|
yann@1
|
6750 |
+nios2_expand_sync (const struct builtin_description * d ATTRIBUTE_UNUSED,
|
yann@1
|
6751 |
+ tree exp ATTRIBUTE_UNUSED, rtx target ATTRIBUTE_UNUSED,
|
yann@1
|
6752 |
+ rtx subtarget ATTRIBUTE_UNUSED,
|
yann@1
|
6753 |
+ enum machine_mode mode ATTRIBUTE_UNUSED,
|
yann@1
|
6754 |
+ int ignore ATTRIBUTE_UNUSED)
|
yann@1
|
6755 |
+{
|
yann@1
|
6756 |
+ emit_insn (gen_sync ());
|
yann@1
|
6757 |
+ return 0;
|
yann@1
|
6758 |
+}
|
yann@1
|
6759 |
+
|
yann@1
|
6760 |
+static rtx
|
yann@1
|
6761 |
+nios2_expand_rdctl (const struct builtin_description * d ATTRIBUTE_UNUSED,
|
yann@1
|
6762 |
+ tree exp ATTRIBUTE_UNUSED, rtx target ATTRIBUTE_UNUSED,
|
yann@1
|
6763 |
+ rtx subtarget ATTRIBUTE_UNUSED,
|
yann@1
|
6764 |
+ enum machine_mode mode ATTRIBUTE_UNUSED,
|
yann@1
|
6765 |
+ int ignore ATTRIBUTE_UNUSED)
|
yann@1
|
6766 |
+{
|
yann@1
|
6767 |
+ tree arglist = TREE_OPERAND (exp, 1);
|
yann@1
|
6768 |
+ rtx pat;
|
yann@1
|
6769 |
+ rtx rdctl_reg;
|
yann@1
|
6770 |
+ enum insn_code icode = d->icode;
|
yann@1
|
6771 |
+
|
yann@1
|
6772 |
+ /* rdctl should have exactly two operands */
|
yann@1
|
6773 |
+ if (insn_data[icode].n_operands != 2)
|
yann@1
|
6774 |
+ abort ();
|
yann@1
|
6775 |
+
|
yann@1
|
6776 |
+ target = nios2_create_target (d, target);
|
yann@1
|
6777 |
+
|
yann@1
|
6778 |
+ {
|
yann@1
|
6779 |
+ enum machine_mode mode = insn_data[icode].operand[1].mode;
|
yann@1
|
6780 |
+ tree arg = TREE_VALUE (arglist);
|
yann@1
|
6781 |
+ rdctl_reg = expand_expr (arg, NULL_RTX, VOIDmode, 0);
|
yann@1
|
6782 |
+ rdctl_reg = protect_from_queue (rdctl_reg, 0);
|
yann@1
|
6783 |
+
|
yann@1
|
6784 |
+ if (!(*insn_data[icode].operand[1].predicate) (rdctl_reg, mode))
|
yann@1
|
6785 |
+ {
|
yann@1
|
6786 |
+ error ("Control register number must be in range 0-31 for %s", d->name);
|
yann@1
|
6787 |
+ }
|
yann@1
|
6788 |
+ }
|
yann@1
|
6789 |
+
|
yann@1
|
6790 |
+ pat = GEN_FCN (d->icode) (target, rdctl_reg);
|
yann@1
|
6791 |
+ if (!pat)
|
yann@1
|
6792 |
+ return 0;
|
yann@1
|
6793 |
+ emit_insn (pat);
|
yann@1
|
6794 |
+ return target;
|
yann@1
|
6795 |
+}
|
yann@1
|
6796 |
+
|
yann@1
|
6797 |
+static rtx
|
yann@1
|
6798 |
+nios2_expand_wrctl (const struct builtin_description * d ATTRIBUTE_UNUSED,
|
yann@1
|
6799 |
+ tree exp ATTRIBUTE_UNUSED, rtx target ATTRIBUTE_UNUSED,
|
yann@1
|
6800 |
+ rtx subtarget ATTRIBUTE_UNUSED,
|
yann@1
|
6801 |
+ enum machine_mode mode ATTRIBUTE_UNUSED,
|
yann@1
|
6802 |
+ int ignore ATTRIBUTE_UNUSED)
|
yann@1
|
6803 |
+{
|
yann@1
|
6804 |
+ tree arglist = TREE_OPERAND (exp, 1);
|
yann@1
|
6805 |
+ rtx pat;
|
yann@1
|
6806 |
+ rtx wrctl_reg, store_val;
|
yann@1
|
6807 |
+ enum insn_code icode = d->icode;
|
yann@1
|
6808 |
+
|
yann@1
|
6809 |
+ /* stores should have exactly two operands */
|
yann@1
|
6810 |
+ if (insn_data[icode].n_operands != 2)
|
yann@1
|
6811 |
+ abort ();
|
yann@1
|
6812 |
+
|
yann@1
|
6813 |
+ /* process the destination of the store */
|
yann@1
|
6814 |
+ {
|
yann@1
|
6815 |
+ enum machine_mode mode = insn_data[icode].operand[0].mode;
|
yann@1
|
6816 |
+ tree arg = TREE_VALUE (arglist);
|
yann@1
|
6817 |
+ wrctl_reg = expand_expr (arg, NULL_RTX, VOIDmode, 0);
|
yann@1
|
6818 |
+ wrctl_reg = protect_from_queue (wrctl_reg, 0);
|
yann@1
|
6819 |
+
|
yann@1
|
6820 |
+ if (!(*insn_data[icode].operand[0].predicate) (wrctl_reg, mode))
|
yann@1
|
6821 |
+ error ("Control register number must be in range 0-31 for %s", d->name);
|
yann@1
|
6822 |
+ }
|
yann@1
|
6823 |
+
|
yann@1
|
6824 |
+
|
yann@1
|
6825 |
+ /* process the value to store */
|
yann@1
|
6826 |
+ {
|
yann@1
|
6827 |
+ enum machine_mode mode = insn_data[icode].operand[1].mode;
|
yann@1
|
6828 |
+ tree arg = TREE_VALUE (TREE_CHAIN (arglist));
|
yann@1
|
6829 |
+ store_val = expand_expr (arg, NULL_RTX, mode, 0);
|
yann@1
|
6830 |
+ store_val = protect_from_queue (store_val, 0);
|
yann@1
|
6831 |
+
|
yann@1
|
6832 |
+ if (!(*insn_data[icode].operand[1].predicate) (store_val, mode))
|
yann@1
|
6833 |
+ store_val = copy_to_mode_reg (mode, store_val);
|
yann@1
|
6834 |
+
|
yann@1
|
6835 |
+ /* ??? Better errors would be nice */
|
yann@1
|
6836 |
+ if (!(*insn_data[icode].operand[1].predicate) (store_val, mode))
|
yann@1
|
6837 |
+ error ("Invalid argument 2 to %s", d->name);
|
yann@1
|
6838 |
+ }
|
yann@1
|
6839 |
+
|
yann@1
|
6840 |
+ pat = GEN_FCN (d->icode) (wrctl_reg, store_val);
|
yann@1
|
6841 |
+ if (!pat)
|
yann@1
|
6842 |
+ return 0;
|
yann@1
|
6843 |
+ emit_insn (pat);
|
yann@1
|
6844 |
+ return 0;
|
yann@1
|
6845 |
+}
|
yann@1
|
6846 |
+
|
yann@1
|
6847 |
+
|
yann@1
|
6848 |
+#include "gt-nios2.h"
|
yann@1
|
6849 |
+
|
yann@1
|
6850 |
--- gcc-3.4.3/gcc/config/nios2/nios2.h
|
yann@1
|
6851 |
+++ gcc-3.4.3-nios2/gcc/config/nios2/nios2.h
|
yann@1
|
6852 |
@@ -0,0 +1,824 @@
|
yann@1
|
6853 |
+/* Definitions of target machine for Altera NIOS 2G NIOS2 version.
|
yann@1
|
6854 |
+ Copyright (C) 2003 Altera
|
yann@1
|
6855 |
+ Contributed by Jonah Graham (jgraham@altera.com).
|
yann@1
|
6856 |
+
|
yann@1
|
6857 |
+This file is part of GNU CC.
|
yann@1
|
6858 |
+
|
yann@1
|
6859 |
+GNU CC is free software; you can redistribute it and/or modify
|
yann@1
|
6860 |
+it under the terms of the GNU General Public License as published by
|
yann@1
|
6861 |
+the Free Software Foundation; either version 2, or (at your option)
|
yann@1
|
6862 |
+any later version.
|
yann@1
|
6863 |
+
|
yann@1
|
6864 |
+GNU CC is distributed in the hope that it will be useful,
|
yann@1
|
6865 |
+but WITHOUT ANY WARRANTY; without even the implied warranty of
|
yann@1
|
6866 |
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
yann@1
|
6867 |
+GNU General Public License for more details.
|
yann@1
|
6868 |
+
|
yann@1
|
6869 |
+You should have received a copy of the GNU General Public License
|
yann@1
|
6870 |
+along with GNU CC; see the file COPYING. If not, write to
|
yann@1
|
6871 |
+the Free Software Foundation, 59 Temple Place - Suite 330,
|
yann@1
|
6872 |
+Boston, MA 02111-1307, USA. */
|
yann@1
|
6873 |
+
|
yann@1
|
6874 |
+
|
yann@1
|
6875 |
+
|
yann@1
|
6876 |
+#define TARGET_CPU_CPP_BUILTINS() \
|
yann@1
|
6877 |
+ do \
|
yann@1
|
6878 |
+ { \
|
yann@1
|
6879 |
+ builtin_define_std ("NIOS2"); \
|
yann@1
|
6880 |
+ builtin_define_std ("nios2"); \
|
yann@1
|
6881 |
+ builtin_define ("_GNU_SOURCE"); \
|
yann@1
|
6882 |
+ } \
|
yann@1
|
6883 |
+ while (0)
|
yann@1
|
6884 |
+#define TARGET_VERSION fprintf (stderr, " (Altera Nios II)")
|
yann@1
|
6885 |
+
|
yann@1
|
6886 |
+
|
yann@1
|
6887 |
+
|
yann@1
|
6888 |
+
|
yann@1
|
6889 |
+
|
yann@1
|
6890 |
+/*********************************
|
yann@1
|
6891 |
+ * Run-time Target Specification
|
yann@1
|
6892 |
+ *********************************/
|
yann@1
|
6893 |
+
|
yann@1
|
6894 |
+#define HAS_DIV_FLAG 0x0001
|
yann@1
|
6895 |
+#define HAS_MUL_FLAG 0x0002
|
yann@1
|
6896 |
+#define HAS_MULX_FLAG 0x0004
|
yann@1
|
6897 |
+#define FAST_SW_DIV_FLAG 0x0008
|
yann@1
|
6898 |
+#define INLINE_MEMCPY_FLAG 0x00010
|
yann@1
|
6899 |
+#define CACHE_VOLATILE_FLAG 0x0020
|
yann@1
|
6900 |
+#define BYPASS_CACHE_FLAG 0x0040
|
yann@1
|
6901 |
+
|
yann@1
|
6902 |
+extern int target_flags;
|
yann@1
|
6903 |
+#define TARGET_HAS_DIV (target_flags & HAS_DIV_FLAG)
|
yann@1
|
6904 |
+#define TARGET_HAS_MUL (target_flags & HAS_MUL_FLAG)
|
yann@1
|
6905 |
+#define TARGET_HAS_MULX (target_flags & HAS_MULX_FLAG)
|
yann@1
|
6906 |
+#define TARGET_FAST_SW_DIV (target_flags & FAST_SW_DIV_FLAG)
|
yann@1
|
6907 |
+#define TARGET_INLINE_MEMCPY (target_flags & INLINE_MEMCPY_FLAG)
|
yann@1
|
6908 |
+#define TARGET_CACHE_VOLATILE (target_flags & CACHE_VOLATILE_FLAG)
|
yann@1
|
6909 |
+#define TARGET_BYPASS_CACHE (target_flags & BYPASS_CACHE_FLAG)
|
yann@1
|
6910 |
+
|
yann@1
|
6911 |
+#define TARGET_SWITCHES \
|
yann@1
|
6912 |
+{ \
|
yann@1
|
6913 |
+ { "hw-div", HAS_DIV_FLAG, \
|
yann@1
|
6914 |
+ N_("Enable DIV, DIVU") }, \
|
yann@1
|
6915 |
+ { "no-hw-div", -HAS_DIV_FLAG, \
|
yann@1
|
6916 |
+ N_("Disable DIV, DIVU (default)") }, \
|
yann@1
|
6917 |
+ { "hw-mul", HAS_MUL_FLAG, \
|
yann@1
|
6918 |
+ N_("Enable MUL instructions (default)") }, \
|
yann@1
|
6919 |
+ { "hw-mulx", HAS_MULX_FLAG, \
|
yann@1
|
6920 |
+ N_("Enable MULX instructions, assume fast shifter") }, \
|
yann@1
|
6921 |
+ { "no-hw-mul", -HAS_MUL_FLAG, \
|
yann@1
|
6922 |
+ N_("Disable MUL instructions") }, \
|
yann@1
|
6923 |
+ { "no-hw-mulx", -HAS_MULX_FLAG, \
|
yann@1
|
6924 |
+ N_("Disable MULX instructions, assume slow shifter (default and implied by -mno-hw-mul)") }, \
|
yann@1
|
6925 |
+ { "fast-sw-div", FAST_SW_DIV_FLAG, \
|
yann@1
|
6926 |
+ N_("Use table based fast divide (default at -O3)") }, \
|
yann@1
|
6927 |
+ { "no-fast-sw-div", -FAST_SW_DIV_FLAG, \
|
yann@1
|
6928 |
+ N_("Don't use table based fast divide ever") }, \
|
yann@1
|
6929 |
+ { "inline-memcpy", INLINE_MEMCPY_FLAG, \
|
yann@1
|
6930 |
+ N_("Inline small memcpy (default when optimizing)") }, \
|
yann@1
|
6931 |
+ { "no-inline-memcpy", -INLINE_MEMCPY_FLAG, \
|
yann@1
|
6932 |
+ N_("Don't Inline small memcpy") }, \
|
yann@1
|
6933 |
+ { "cache-volatile", CACHE_VOLATILE_FLAG, \
|
yann@1
|
6934 |
+ N_("Volatile accesses use non-io variants of instructions (default)") }, \
|
yann@1
|
6935 |
+ { "no-cache-volatile", -CACHE_VOLATILE_FLAG, \
|
yann@1
|
6936 |
+ N_("Volatile accesses use io variants of instructions") }, \
|
yann@1
|
6937 |
+ { "bypass-cache", BYPASS_CACHE_FLAG, \
|
yann@1
|
6938 |
+ N_("All ld/st instructins use io variants") }, \
|
yann@1
|
6939 |
+ { "no-bypass-cache", -BYPASS_CACHE_FLAG, \
|
yann@1
|
6940 |
+ N_("All ld/st instructins do not use io variants (default)") }, \
|
yann@1
|
6941 |
+ { "smallc", 0, \
|
yann@1
|
6942 |
+ N_("Link with a limited version of the C library") }, \
|
yann@1
|
6943 |
+ { "ctors-in-init", 0, \
|
yann@1
|
6944 |
+ "" /* undocumented: N_("Link with static constructors and destructors in init") */ }, \
|
yann@1
|
6945 |
+ { "", TARGET_DEFAULT, 0 } \
|
yann@1
|
6946 |
+}
|
yann@1
|
6947 |
+
|
yann@1
|
6948 |
+
|
yann@1
|
6949 |
+extern const char *nios2_sys_nosys_string; /* for -msys=nosys */
|
yann@1
|
6950 |
+extern const char *nios2_sys_lib_string; /* for -msys-lib= */
|
yann@1
|
6951 |
+extern const char *nios2_sys_crt0_string; /* for -msys-crt0= */
|
yann@1
|
6952 |
+
|
yann@1
|
6953 |
+#define TARGET_OPTIONS \
|
yann@1
|
6954 |
+{ \
|
yann@1
|
6955 |
+ { "sys=nosys", &nios2_sys_nosys_string, \
|
yann@1
|
6956 |
+ N_("Use stub versions of OS library calls (default)"), 0}, \
|
yann@1
|
6957 |
+ { "sys-lib=", &nios2_sys_lib_string, \
|
yann@1
|
6958 |
+ N_("Name of System Library to link against. (Converted to a -l option)"), 0}, \
|
yann@1
|
6959 |
+ { "sys-crt0=", &nios2_sys_crt0_string, \
|
yann@1
|
6960 |
+ N_("Name of the startfile. (default is a crt0 for the ISS only)"), 0}, \
|
yann@1
|
6961 |
+}
|
yann@1
|
6962 |
+
|
yann@1
|
6963 |
+
|
yann@1
|
6964 |
+/* Default target_flags if no switches specified. */
|
yann@1
|
6965 |
+#ifndef TARGET_DEFAULT
|
yann@1
|
6966 |
+# define TARGET_DEFAULT (HAS_MUL_FLAG | CACHE_VOLATILE_FLAG)
|
yann@1
|
6967 |
+#endif
|
yann@1
|
6968 |
+
|
yann@1
|
6969 |
+/* Switch Recognition by gcc.c. Add -G xx support */
|
yann@1
|
6970 |
+#undef SWITCH_TAKES_ARG
|
yann@1
|
6971 |
+#define SWITCH_TAKES_ARG(CHAR) \
|
yann@1
|
6972 |
+ (DEFAULT_SWITCH_TAKES_ARG (CHAR) || (CHAR) == 'G')
|
yann@1
|
6973 |
+
|
yann@1
|
6974 |
+#define OVERRIDE_OPTIONS override_options ()
|
yann@1
|
6975 |
+#define OPTIMIZATION_OPTIONS(LEVEL, SIZE) optimization_options (LEVEL, SIZE)
|
yann@1
|
6976 |
+#define CAN_DEBUG_WITHOUT_FP
|
yann@1
|
6977 |
+
|
yann@1
|
6978 |
+#define CC1_SPEC "\
|
yann@1
|
6979 |
+%{G*}"
|
yann@1
|
6980 |
+
|
yann@1
|
6981 |
+#undef LIB_SPEC
|
yann@1
|
6982 |
+#define LIB_SPEC \
|
yann@1
|
6983 |
+"--start-group %{msmallc: -lsmallc} %{!msmallc: -lc} -lgcc \
|
yann@1
|
6984 |
+ %{msys-lib=*: -l%*} \
|
yann@1
|
6985 |
+ %{!msys-lib=*: -lc } \
|
yann@1
|
6986 |
+ --end-group \
|
yann@1
|
6987 |
+ %{msys-lib=: %eYou need a library name for -msys-lib=} \
|
yann@1
|
6988 |
+"
|
yann@1
|
6989 |
+
|
yann@1
|
6990 |
+
|
yann@1
|
6991 |
+#undef STARTFILE_SPEC
|
yann@1
|
6992 |
+#define STARTFILE_SPEC \
|
yann@1
|
6993 |
+"%{msys-crt0=*: %*} %{!msys-crt0=*: crt1%O%s} \
|
yann@1
|
6994 |
+ %{msys-crt0=: %eYou need a C startup file for -msys-crt0=} \
|
yann@1
|
6995 |
+ %{mctors-in-init: crti%O%s crtbegin%O%s} \
|
yann@1
|
6996 |
+"
|
yann@1
|
6997 |
+
|
yann@1
|
6998 |
+#undef ENDFILE_SPEC
|
yann@1
|
6999 |
+#define ENDFILE_SPEC \
|
yann@1
|
7000 |
+ "%{mctors-in-init: crtend%O%s crtn%O%s}"
|
yann@1
|
7001 |
+
|
yann@1
|
7002 |
+
|
yann@1
|
7003 |
+/***********************
|
yann@1
|
7004 |
+ * Storage Layout
|
yann@1
|
7005 |
+ ***********************/
|
yann@1
|
7006 |
+
|
yann@1
|
7007 |
+#define DEFAULT_SIGNED_CHAR 1
|
yann@1
|
7008 |
+#define BITS_BIG_ENDIAN 0
|
yann@1
|
7009 |
+#define BYTES_BIG_ENDIAN 0
|
yann@1
|
7010 |
+#define WORDS_BIG_ENDIAN 0
|
yann@1
|
7011 |
+#define BITS_PER_UNIT 8
|
yann@1
|
7012 |
+#define BITS_PER_WORD 32
|
yann@1
|
7013 |
+#define UNITS_PER_WORD 4
|
yann@1
|
7014 |
+#define POINTER_SIZE 32
|
yann@1
|
7015 |
+#define BIGGEST_ALIGNMENT 32
|
yann@1
|
7016 |
+#define STRICT_ALIGNMENT 1
|
yann@1
|
7017 |
+#define FUNCTION_BOUNDARY 32
|
yann@1
|
7018 |
+#define PARM_BOUNDARY 32
|
yann@1
|
7019 |
+#define STACK_BOUNDARY 32
|
yann@1
|
7020 |
+#define PREFERRED_STACK_BOUNDARY 32
|
yann@1
|
7021 |
+#define MAX_FIXED_MODE_SIZE 64
|
yann@1
|
7022 |
+
|
yann@1
|
7023 |
+#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
|
yann@1
|
7024 |
+ ((TREE_CODE (EXP) == STRING_CST) \
|
yann@1
|
7025 |
+ && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
|
yann@1
|
7026 |
+
|
yann@1
|
7027 |
+
|
yann@1
|
7028 |
+/**********************
|
yann@1
|
7029 |
+ * Layout of Source Language Data Types
|
yann@1
|
7030 |
+ **********************/
|
yann@1
|
7031 |
+
|
yann@1
|
7032 |
+#define INT_TYPE_SIZE 32
|
yann@1
|
7033 |
+#define SHORT_TYPE_SIZE 16
|
yann@1
|
7034 |
+#define LONG_TYPE_SIZE 32
|
yann@1
|
7035 |
+#define LONG_LONG_TYPE_SIZE 64
|
yann@1
|
7036 |
+#define FLOAT_TYPE_SIZE 32
|
yann@1
|
7037 |
+#define DOUBLE_TYPE_SIZE 64
|
yann@1
|
7038 |
+#define LONG_DOUBLE_TYPE_SIZE DOUBLE_TYPE_SIZE
|
yann@1
|
7039 |
+
|
yann@1
|
7040 |
+
|
yann@1
|
7041 |
+/*************************
|
yann@1
|
7042 |
+ * Condition Code Status
|
yann@1
|
7043 |
+ ************************/
|
yann@1
|
7044 |
+
|
yann@1
|
7045 |
+/* comparison type */
|
yann@1
|
7046 |
+/* ??? currently only CMP_SI is used */
|
yann@1
|
7047 |
+enum cmp_type {
|
yann@1
|
7048 |
+ CMP_SI, /* compare four byte integers */
|
yann@1
|
7049 |
+ CMP_DI, /* compare eight byte integers */
|
yann@1
|
7050 |
+ CMP_SF, /* compare single precision floats */
|
yann@1
|
7051 |
+ CMP_DF, /* compare double precision floats */
|
yann@1
|
7052 |
+ CMP_MAX /* max comparison type */
|
yann@1
|
7053 |
+};
|
yann@1
|
7054 |
+
|
yann@1
|
7055 |
+extern GTY(()) rtx branch_cmp[2]; /* operands for compare */
|
yann@1
|
7056 |
+extern enum cmp_type branch_type; /* what type of branch to use */
|
yann@1
|
7057 |
+
|
yann@1
|
7058 |
+/**********************
|
yann@1
|
7059 |
+ * Register Usage
|
yann@1
|
7060 |
+ **********************/
|
yann@1
|
7061 |
+
|
yann@1
|
7062 |
+/* ---------------------------------- *
|
yann@1
|
7063 |
+ * Basic Characteristics of Registers
|
yann@1
|
7064 |
+ * ---------------------------------- */
|
yann@1
|
7065 |
+
|
yann@1
|
7066 |
+/*
|
yann@1
|
7067 |
+Register Number
|
yann@1
|
7068 |
+ Register Name
|
yann@1
|
7069 |
+ Alternate Name
|
yann@1
|
7070 |
+ Purpose
|
yann@1
|
7071 |
+0 r0 zero always zero
|
yann@1
|
7072 |
+1 r1 at Assembler Temporary
|
yann@1
|
7073 |
+2-3 r2-r3 Return Location
|
yann@1
|
7074 |
+4-7 r4-r7 Register Arguments
|
yann@1
|
7075 |
+8-15 r8-r15 Caller Saved Registers
|
yann@1
|
7076 |
+16-22 r16-r22 Callee Saved Registers
|
yann@1
|
7077 |
+23 r23 sc Static Chain (Callee Saved)
|
yann@1
|
7078 |
+ ??? Does $sc want to be caller or callee
|
yann@1
|
7079 |
+ saved. If caller, 15, else 23.
|
yann@1
|
7080 |
+24 r24 Exception Temporary
|
yann@1
|
7081 |
+25 r25 Breakpoint Temporary
|
yann@1
|
7082 |
+26 r26 gp Global Pointer
|
yann@1
|
7083 |
+27 r27 sp Stack Pointer
|
yann@1
|
7084 |
+28 r28 fp Frame Pointer
|
yann@1
|
7085 |
+29 r29 ea Exception Return Address
|
yann@1
|
7086 |
+30 r30 ba Breakpoint Return Address
|
yann@1
|
7087 |
+31 r31 ra Return Address
|
yann@1
|
7088 |
+
|
yann@1
|
7089 |
+32 ctl0 status
|
yann@1
|
7090 |
+33 ctl1 estatus STATUS saved by exception ?
|
yann@1
|
7091 |
+34 ctl2 bstatus STATUS saved by break ?
|
yann@1
|
7092 |
+35 ctl3 ipri Interrupt Priority Mask ?
|
yann@1
|
7093 |
+36 ctl4 ecause Exception Cause ?
|
yann@1
|
7094 |
+
|
yann@1
|
7095 |
+37 pc Not an actual register
|
yann@1
|
7096 |
+
|
yann@1
|
7097 |
+38 rap Return address pointer, this does not
|
yann@1
|
7098 |
+ actually exist and will be eliminated
|
yann@1
|
7099 |
+
|
yann@1
|
7100 |
+39 fake_fp Fake Frame Pointer which will always be eliminated.
|
yann@1
|
7101 |
+40 fake_ap Fake Argument Pointer which will always be eliminated.
|
yann@1
|
7102 |
+
|
yann@1
|
7103 |
+41 First Pseudo Register
|
yann@1
|
7104 |
+
|
yann@1
|
7105 |
+
|
yann@1
|
7106 |
+The definitions for all the hard register numbers
|
yann@1
|
7107 |
+are located in nios2.md.
|
yann@1
|
7108 |
+*/
|
yann@1
|
7109 |
+
|
yann@1
|
7110 |
+#define FIRST_PSEUDO_REGISTER 41
|
yann@1
|
7111 |
+#define NUM_ARG_REGS (LAST_ARG_REGNO - FIRST_ARG_REGNO + 1)
|
yann@1
|
7112 |
+
|
yann@1
|
7113 |
+
|
yann@1
|
7114 |
+
|
yann@1
|
7115 |
+/* also see CONDITIONAL_REGISTER_USAGE */
|
yann@1
|
7116 |
+#define FIXED_REGISTERS \
|
yann@1
|
7117 |
+ { \
|
yann@1
|
7118 |
+/* +0 1 2 3 4 5 6 7 8 9 */ \
|
yann@1
|
7119 |
+/* 0 */ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, \
|
yann@1
|
7120 |
+/* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
yann@1
|
7121 |
+/* 20 */ 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, \
|
yann@1
|
7122 |
+/* 30 */ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, \
|
yann@1
|
7123 |
+/* 40 */ 1, \
|
yann@1
|
7124 |
+ }
|
yann@1
|
7125 |
+
|
yann@1
|
7126 |
+/* call used is the same as caller saved
|
yann@1
|
7127 |
+ + fixed regs + args + ret vals */
|
yann@1
|
7128 |
+#define CALL_USED_REGISTERS \
|
yann@1
|
7129 |
+ { \
|
yann@1
|
7130 |
+/* +0 1 2 3 4 5 6 7 8 9 */ \
|
yann@1
|
7131 |
+/* 0 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
yann@1
|
7132 |
+/* 10 */ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, \
|
yann@1
|
7133 |
+/* 20 */ 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, \
|
yann@1
|
7134 |
+/* 30 */ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, \
|
yann@1
|
7135 |
+/* 40 */ 1, \
|
yann@1
|
7136 |
+ }
|
yann@1
|
7137 |
+
|
yann@1
|
7138 |
+#define HARD_REGNO_NREGS(REGNO, MODE) \
|
yann@1
|
7139 |
+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \
|
yann@1
|
7140 |
+ / UNITS_PER_WORD)
|
yann@1
|
7141 |
+
|
yann@1
|
7142 |
+/* --------------------------- *
|
yann@1
|
7143 |
+ * How Values Fit in Registers
|
yann@1
|
7144 |
+ * --------------------------- */
|
yann@1
|
7145 |
+
|
yann@1
|
7146 |
+#define HARD_REGNO_MODE_OK(REGNO, MODE) 1
|
yann@1
|
7147 |
+
|
yann@1
|
7148 |
+#define MODES_TIEABLE_P(MODE1, MODE2) 1
|
yann@1
|
7149 |
+
|
yann@1
|
7150 |
+
|
yann@1
|
7151 |
+/*************************
|
yann@1
|
7152 |
+ * Register Classes
|
yann@1
|
7153 |
+ *************************/
|
yann@1
|
7154 |
+
|
yann@1
|
7155 |
+enum reg_class
|
yann@1
|
7156 |
+{
|
yann@1
|
7157 |
+ NO_REGS,
|
yann@1
|
7158 |
+ ALL_REGS,
|
yann@1
|
7159 |
+ LIM_REG_CLASSES
|
yann@1
|
7160 |
+};
|
yann@1
|
7161 |
+
|
yann@1
|
7162 |
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
|
yann@1
|
7163 |
+
|
yann@1
|
7164 |
+#define REG_CLASS_NAMES \
|
yann@1
|
7165 |
+ {"NO_REGS", \
|
yann@1
|
7166 |
+ "ALL_REGS"}
|
yann@1
|
7167 |
+
|
yann@1
|
7168 |
+#define GENERAL_REGS ALL_REGS
|
yann@1
|
7169 |
+
|
yann@1
|
7170 |
+#define REG_CLASS_CONTENTS \
|
yann@1
|
7171 |
+/* NO_REGS */ {{ 0, 0}, \
|
yann@1
|
7172 |
+/* ALL_REGS */ {~0,~0}} \
|
yann@1
|
7173 |
+
|
yann@1
|
7174 |
+#define REGNO_REG_CLASS(REGNO) ALL_REGS
|
yann@1
|
7175 |
+
|
yann@1
|
7176 |
+#define BASE_REG_CLASS ALL_REGS
|
yann@1
|
7177 |
+#define INDEX_REG_CLASS ALL_REGS
|
yann@1
|
7178 |
+
|
yann@1
|
7179 |
+/* only one reg class, 'r', is handled automatically */
|
yann@1
|
7180 |
+#define REG_CLASS_FROM_LETTER(CHAR) NO_REGS
|
yann@1
|
7181 |
+
|
yann@1
|
7182 |
+#define REGNO_OK_FOR_BASE_P2(REGNO, STRICT) \
|
yann@1
|
7183 |
+ ((STRICT) \
|
yann@1
|
7184 |
+ ? (REGNO) < FIRST_PSEUDO_REGISTER \
|
yann@1
|
7185 |
+ : (REGNO) < FIRST_PSEUDO_REGISTER || (reg_renumber && reg_renumber[REGNO] < FIRST_PSEUDO_REGISTER))
|
yann@1
|
7186 |
+
|
yann@1
|
7187 |
+#define REGNO_OK_FOR_INDEX_P2(REGNO, STRICT) \
|
yann@1
|
7188 |
+ (REGNO_OK_FOR_BASE_P2 (REGNO, STRICT))
|
yann@1
|
7189 |
+
|
yann@1
|
7190 |
+#define REGNO_OK_FOR_BASE_P(REGNO) \
|
yann@1
|
7191 |
+ (REGNO_OK_FOR_BASE_P2 (REGNO, 1))
|
yann@1
|
7192 |
+
|
yann@1
|
7193 |
+#define REGNO_OK_FOR_INDEX_P(REGNO) \
|
yann@1
|
7194 |
+ (REGNO_OK_FOR_INDEX_P2 (REGNO, 1))
|
yann@1
|
7195 |
+
|
yann@1
|
7196 |
+#define REG_OK_FOR_BASE_P2(X, STRICT) \
|
yann@1
|
7197 |
+ (STRICT \
|
yann@1
|
7198 |
+ ? REGNO_OK_FOR_BASE_P2 (REGNO (X), 1) \
|
yann@1
|
7199 |
+ : REGNO_OK_FOR_BASE_P2 (REGNO (X), 1) || REGNO(X) >= FIRST_PSEUDO_REGISTER)
|
yann@1
|
7200 |
+
|
yann@1
|
7201 |
+#define REG_OK_FOR_INDEX_P2(X, STRICT) \
|
yann@1
|
7202 |
+ (STRICT \
|
yann@1
|
7203 |
+ ? REGNO_OK_FOR_INDEX_P2 (REGNO (X), 1) \
|
yann@1
|
7204 |
+ : REGNO_OK_FOR_INDEX_P2 (REGNO (X), 1) || REGNO(X) >= FIRST_PSEUDO_REGISTER)
|
yann@1
|
7205 |
+
|
yann@1
|
7206 |
+#define CLASS_MAX_NREGS(CLASS, MODE) \
|
yann@1
|
7207 |
+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \
|
yann@1
|
7208 |
+ / UNITS_PER_WORD)
|
yann@1
|
7209 |
+
|
yann@1
|
7210 |
+
|
yann@1
|
7211 |
+#define SMALL_INT(X) ((unsigned HOST_WIDE_INT) ((X) + 0x8000) < 0x10000)
|
yann@1
|
7212 |
+#define SMALL_INT_UNSIGNED(X) ((unsigned HOST_WIDE_INT) (X) < 0x10000)
|
yann@1
|
7213 |
+#define UPPER16_INT(X) (((X) & 0xffff) == 0)
|
yann@1
|
7214 |
+#define SHIFT_INT(X) ((X) >= 0 && (X) <= 31)
|
yann@1
|
7215 |
+#define RDWRCTL_INT(X) ((X) >= 0 && (X) <= 31)
|
yann@1
|
7216 |
+#define CUSTOM_INSN_OPCODE(X) ((X) >= 0 && (X) <= 255)
|
yann@1
|
7217 |
+
|
yann@1
|
7218 |
+#define CONST_OK_FOR_LETTER_P(VALUE, C) \
|
yann@1
|
7219 |
+ ( \
|
yann@1
|
7220 |
+ (C) == 'I' ? SMALL_INT (VALUE) : \
|
yann@1
|
7221 |
+ (C) == 'J' ? SMALL_INT_UNSIGNED (VALUE) : \
|
yann@1
|
7222 |
+ (C) == 'K' ? UPPER16_INT (VALUE) : \
|
yann@1
|
7223 |
+ (C) == 'L' ? SHIFT_INT (VALUE) : \
|
yann@1
|
7224 |
+ (C) == 'M' ? (VALUE) == 0 : \
|
yann@1
|
7225 |
+ (C) == 'N' ? CUSTOM_INSN_OPCODE (VALUE) : \
|
yann@1
|
7226 |
+ (C) == 'O' ? RDWRCTL_INT (VALUE) : \
|
yann@1
|
7227 |
+ 0)
|
yann@1
|
7228 |
+
|
yann@1
|
7229 |
+#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 0
|
yann@1
|
7230 |
+
|
yann@1
|
7231 |
+#define PREFERRED_RELOAD_CLASS(X, CLASS) \
|
yann@1
|
7232 |
+ ((CLASS) == NO_REGS ? GENERAL_REGS : (CLASS))
|
yann@1
|
7233 |
+
|
yann@1
|
7234 |
+/* 'S' matches immediates which are in small data
|
yann@1
|
7235 |
+ and therefore can be added to gp to create a
|
yann@1
|
7236 |
+ 32-bit value. */
|
yann@1
|
7237 |
+#define EXTRA_CONSTRAINT(VALUE, C) \
|
yann@1
|
7238 |
+ ((C) == 'S' \
|
yann@1
|
7239 |
+ && (GET_CODE (VALUE) == SYMBOL_REF) \
|
yann@1
|
7240 |
+ && SYMBOL_REF_IN_NIOS2_SMALL_DATA_P (VALUE))
|
yann@1
|
7241 |
+
|
yann@1
|
7242 |
+
|
yann@1
|
7243 |
+
|
yann@1
|
7244 |
+
|
yann@1
|
7245 |
+/* Say that the epilogue uses the return address register. Note that
|
yann@1
|
7246 |
+ in the case of sibcalls, the values "used by the epilogue" are
|
yann@1
|
7247 |
+ considered live at the start of the called function. */
|
yann@1
|
7248 |
+#define EPILOGUE_USES(REGNO) ((REGNO) == RA_REGNO)
|
yann@1
|
7249 |
+
|
yann@1
|
7250 |
+
|
yann@1
|
7251 |
+#define DEFAULT_MAIN_RETURN c_expand_return (integer_zero_node)
|
yann@1
|
7252 |
+
|
yann@1
|
7253 |
+/**********************************
|
yann@1
|
7254 |
+ * Trampolines for Nested Functions
|
yann@1
|
7255 |
+ ***********************************/
|
yann@1
|
7256 |
+
|
yann@1
|
7257 |
+#define TRAMPOLINE_TEMPLATE(FILE) \
|
yann@1
|
7258 |
+ error ("trampolines not yet implemented")
|
yann@1
|
7259 |
+#define TRAMPOLINE_SIZE 20
|
yann@1
|
7260 |
+#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
|
yann@1
|
7261 |
+ error ("trampolines not yet implemented")
|
yann@1
|
7262 |
+
|
yann@1
|
7263 |
+/***************************
|
yann@1
|
7264 |
+ * Stack Layout and Calling Conventions
|
yann@1
|
7265 |
+ ***************************/
|
yann@1
|
7266 |
+
|
yann@1
|
7267 |
+/* ------------------ *
|
yann@1
|
7268 |
+ * Basic Stack Layout
|
yann@1
|
7269 |
+ * ------------------ */
|
yann@1
|
7270 |
+
|
yann@1
|
7271 |
+/* The downward variants are used by the compiler,
|
yann@1
|
7272 |
+ the upward ones serve as documentation */
|
yann@1
|
7273 |
+#define STACK_GROWS_DOWNWARD
|
yann@1
|
7274 |
+#define FRAME_GROWS_UPWARD
|
yann@1
|
7275 |
+#define ARGS_GROW_UPWARD
|
yann@1
|
7276 |
+
|
yann@1
|
7277 |
+#define STARTING_FRAME_OFFSET current_function_outgoing_args_size
|
yann@1
|
7278 |
+#define FIRST_PARM_OFFSET(FUNDECL) 0
|
yann@1
|
7279 |
+
|
yann@1
|
7280 |
+/* Before the prologue, RA lives in r31. */
|
yann@1
|
7281 |
+#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (VOIDmode, RA_REGNO)
|
yann@1
|
7282 |
+
|
yann@1
|
7283 |
+/* -------------------------------------- *
|
yann@1
|
7284 |
+ * Registers That Address the Stack Frame
|
yann@1
|
7285 |
+ * -------------------------------------- */
|
yann@1
|
7286 |
+
|
yann@1
|
7287 |
+#define STACK_POINTER_REGNUM SP_REGNO
|
yann@1
|
7288 |
+#define STATIC_CHAIN_REGNUM SC_REGNO
|
yann@1
|
7289 |
+#define PC_REGNUM PC_REGNO
|
yann@1
|
7290 |
+#define DWARF_FRAME_RETURN_COLUMN RA_REGNO
|
yann@1
|
7291 |
+
|
yann@1
|
7292 |
+/* Base register for access to local variables of the function. We
|
yann@1
|
7293 |
+ pretend that the frame pointer is a non-existent hard register, and
|
yann@1
|
7294 |
+ then eliminate it to HARD_FRAME_POINTER_REGNUM. */
|
yann@1
|
7295 |
+#define FRAME_POINTER_REGNUM FAKE_FP_REGNO
|
yann@1
|
7296 |
+
|
yann@1
|
7297 |
+#define HARD_FRAME_POINTER_REGNUM FP_REGNO
|
yann@1
|
7298 |
+#define RETURN_ADDRESS_POINTER_REGNUM RAP_REGNO
|
yann@1
|
7299 |
+/* the argumnet pointer needs to always be eliminated
|
yann@1
|
7300 |
+ so it is set to a fake hard register. */
|
yann@1
|
7301 |
+#define ARG_POINTER_REGNUM FAKE_AP_REGNO
|
yann@1
|
7302 |
+
|
yann@1
|
7303 |
+/* ----------------------------------------- *
|
yann@1
|
7304 |
+ * Eliminating Frame Pointer and Arg Pointer
|
yann@1
|
7305 |
+ * ----------------------------------------- */
|
yann@1
|
7306 |
+
|
yann@1
|
7307 |
+#define FRAME_POINTER_REQUIRED 0
|
yann@1
|
7308 |
+
|
yann@1
|
7309 |
+#define ELIMINABLE_REGS \
|
yann@1
|
7310 |
+{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
|
yann@1
|
7311 |
+ { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
|
yann@1
|
7312 |
+ { RETURN_ADDRESS_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
|
yann@1
|
7313 |
+ { RETURN_ADDRESS_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
|
yann@1
|
7314 |
+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
|
yann@1
|
7315 |
+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
|
yann@1
|
7316 |
+
|
yann@1
|
7317 |
+#define CAN_ELIMINATE(FROM, TO) 1
|
yann@1
|
7318 |
+
|
yann@1
|
7319 |
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
|
yann@1
|
7320 |
+ (OFFSET) = nios2_initial_elimination_offset ((FROM), (TO))
|
yann@1
|
7321 |
+
|
yann@1
|
7322 |
+#define MUST_SAVE_REGISTER(regno) \
|
yann@1
|
7323 |
+ ((regs_ever_live[regno] && !call_used_regs[regno]) \
|
yann@1
|
7324 |
+ || (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed) \
|
yann@1
|
7325 |
+ || (regno == RA_REGNO && regs_ever_live[RA_REGNO]))
|
yann@1
|
7326 |
+
|
yann@1
|
7327 |
+/* Treat LOC as a byte offset from the stack pointer and round it up
|
yann@1
|
7328 |
+ to the next fully-aligned offset. */
|
yann@1
|
7329 |
+#define STACK_ALIGN(LOC) \
|
yann@1
|
7330 |
+ (((LOC) + ((PREFERRED_STACK_BOUNDARY / 8) - 1)) & ~((PREFERRED_STACK_BOUNDARY / 8) - 1))
|
yann@1
|
7331 |
+
|
yann@1
|
7332 |
+
|
yann@1
|
7333 |
+/* ------------------------------ *
|
yann@1
|
7334 |
+ * Passing Arguments in Registers
|
yann@1
|
7335 |
+ * ------------------------------ */
|
yann@1
|
7336 |
+
|
yann@1
|
7337 |
+/* see nios2.c */
|
yann@1
|
7338 |
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
|
yann@1
|
7339 |
+ (function_arg (&CUM, MODE, TYPE, NAMED))
|
yann@1
|
7340 |
+
|
yann@1
|
7341 |
+#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
|
yann@1
|
7342 |
+ (function_arg_partial_nregs (&CUM, MODE, TYPE, NAMED))
|
yann@1
|
7343 |
+
|
yann@1
|
7344 |
+#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) 0
|
yann@1
|
7345 |
+
|
yann@1
|
7346 |
+#define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) 0
|
yann@1
|
7347 |
+
|
yann@1
|
7348 |
+typedef struct nios2_args
|
yann@1
|
7349 |
+{
|
yann@1
|
7350 |
+ int regs_used;
|
yann@1
|
7351 |
+} CUMULATIVE_ARGS;
|
yann@1
|
7352 |
+
|
yann@1
|
7353 |
+/* This is to initialize the above unused CUM data type */
|
yann@1
|
7354 |
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
|
yann@1
|
7355 |
+ (init_cumulative_args (&CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS))
|
yann@1
|
7356 |
+
|
yann@1
|
7357 |
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
|
yann@1
|
7358 |
+ (function_arg_advance (&CUM, MODE, TYPE, NAMED))
|
yann@1
|
7359 |
+
|
yann@1
|
7360 |
+#define FUNCTION_ARG_REGNO_P(REGNO) \
|
yann@1
|
7361 |
+ ((REGNO) >= FIRST_ARG_REGNO && (REGNO) <= LAST_ARG_REGNO)
|
yann@1
|
7362 |
+
|
yann@1
|
7363 |
+#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \
|
yann@1
|
7364 |
+ { \
|
yann@1
|
7365 |
+ int pret_size = nios2_setup_incoming_varargs (&(CUM), (MODE), \
|
yann@1
|
7366 |
+ (TYPE), (NO_RTL)); \
|
yann@1
|
7367 |
+ if (pret_size) \
|
yann@1
|
7368 |
+ (PRETEND_SIZE) = pret_size; \
|
yann@1
|
7369 |
+ }
|
yann@1
|
7370 |
+
|
yann@1
|
7371 |
+/* ----------------------------- *
|
yann@1
|
7372 |
+ * Generating Code for Profiling
|
yann@1
|
7373 |
+ * ----------------------------- */
|
yann@1
|
7374 |
+
|
yann@1
|
7375 |
+#define PROFILE_BEFORE_PROLOGUE
|
yann@1
|
7376 |
+
|
yann@1
|
7377 |
+#define FUNCTION_PROFILER(FILE, LABELNO) \
|
yann@1
|
7378 |
+ function_profiler ((FILE), (LABELNO))
|
yann@1
|
7379 |
+
|
yann@1
|
7380 |
+/* --------------------------------------- *
|
yann@1
|
7381 |
+ * Passing Function Arguments on the Stack
|
yann@1
|
7382 |
+ * --------------------------------------- */
|
yann@1
|
7383 |
+
|
yann@1
|
7384 |
+#define PROMOTE_PROTOTYPES 1
|
yann@1
|
7385 |
+
|
yann@1
|
7386 |
+#define PUSH_ARGS 0
|
yann@1
|
7387 |
+#define ACCUMULATE_OUTGOING_ARGS 1
|
yann@1
|
7388 |
+
|
yann@1
|
7389 |
+#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACKSIZE) 0
|
yann@1
|
7390 |
+
|
yann@1
|
7391 |
+/* --------------------------------------- *
|
yann@1
|
7392 |
+ * How Scalar Function Values Are Returned
|
yann@1
|
7393 |
+ * --------------------------------------- */
|
yann@1
|
7394 |
+
|
yann@1
|
7395 |
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
|
yann@1
|
7396 |
+ gen_rtx(REG, TYPE_MODE(VALTYPE), FIRST_RETVAL_REGNO)
|
yann@1
|
7397 |
+
|
yann@1
|
7398 |
+#define LIBCALL_VALUE(MODE) \
|
yann@1
|
7399 |
+ gen_rtx(REG, MODE, FIRST_RETVAL_REGNO)
|
yann@1
|
7400 |
+
|
yann@1
|
7401 |
+#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == FIRST_RETVAL_REGNO)
|
yann@1
|
7402 |
+
|
yann@1
|
7403 |
+/* ----------------------------- *
|
yann@1
|
7404 |
+ * How Large Values Are Returned
|
yann@1
|
7405 |
+ * ----------------------------- */
|
yann@1
|
7406 |
+
|
yann@1
|
7407 |
+
|
yann@1
|
7408 |
+#define RETURN_IN_MEMORY(TYPE) \
|
yann@1
|
7409 |
+ nios2_return_in_memory (TYPE)
|
yann@1
|
7410 |
+
|
yann@1
|
7411 |
+
|
yann@1
|
7412 |
+#define STRUCT_VALUE 0
|
yann@1
|
7413 |
+
|
yann@1
|
7414 |
+#define DEFAULT_PCC_STRUCT_RETURN 0
|
yann@1
|
7415 |
+
|
yann@1
|
7416 |
+/*******************
|
yann@1
|
7417 |
+ * Addressing Modes
|
yann@1
|
7418 |
+ *******************/
|
yann@1
|
7419 |
+
|
yann@1
|
7420 |
+
|
yann@1
|
7421 |
+#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)
|
yann@1
|
7422 |
+
|
yann@1
|
7423 |
+#define CONSTANT_ADDRESS_P(X) (CONSTANT_P (X))
|
yann@1
|
7424 |
+
|
yann@1
|
7425 |
+#define MAX_REGS_PER_ADDRESS 1
|
yann@1
|
7426 |
+
|
yann@1
|
7427 |
+/* Go to ADDR if X is a valid address. */
|
yann@1
|
7428 |
+#ifndef REG_OK_STRICT
|
yann@1
|
7429 |
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
|
yann@1
|
7430 |
+ { \
|
yann@1
|
7431 |
+ if (nios2_legitimate_address ((X), (MODE), 0)) \
|
yann@1
|
7432 |
+ goto ADDR; \
|
yann@1
|
7433 |
+ }
|
yann@1
|
7434 |
+#else
|
yann@1
|
7435 |
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
|
yann@1
|
7436 |
+ { \
|
yann@1
|
7437 |
+ if (nios2_legitimate_address ((X), (MODE), 1)) \
|
yann@1
|
7438 |
+ goto ADDR; \
|
yann@1
|
7439 |
+ }
|
yann@1
|
7440 |
+#endif
|
yann@1
|
7441 |
+
|
yann@1
|
7442 |
+#ifndef REG_OK_STRICT
|
yann@1
|
7443 |
+#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P2 (REGNO (X), 0)
|
yann@1
|
7444 |
+#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P2 (REGNO (X), 0)
|
yann@1
|
7445 |
+#else
|
yann@1
|
7446 |
+#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P2 (REGNO (X), 1)
|
yann@1
|
7447 |
+#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P2 (REGNO (X), 1)
|
yann@1
|
7448 |
+#endif
|
yann@1
|
7449 |
+
|
yann@1
|
7450 |
+#define LEGITIMATE_CONSTANT_P(X) 1
|
yann@1
|
7451 |
+
|
yann@1
|
7452 |
+/* Nios II has no mode dependent addresses. */
|
yann@1
|
7453 |
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)
|
yann@1
|
7454 |
+
|
yann@1
|
7455 |
+/* Set if this has a weak declaration */
|
yann@1
|
7456 |
+#define SYMBOL_FLAG_WEAK_DECL (1 << SYMBOL_FLAG_MACH_DEP_SHIFT)
|
yann@1
|
7457 |
+#define SYMBOL_REF_WEAK_DECL_P(RTX) \
|
yann@1
|
7458 |
+ ((SYMBOL_REF_FLAGS (RTX) & SYMBOL_FLAG_WEAK_DECL) != 0)
|
yann@1
|
7459 |
+
|
yann@1
|
7460 |
+
|
yann@1
|
7461 |
+/* true if a symbol is both small and not weak. In this case, gp
|
yann@1
|
7462 |
+ relative access can be used */
|
yann@1
|
7463 |
+#define SYMBOL_REF_IN_NIOS2_SMALL_DATA_P(RTX) \
|
yann@1
|
7464 |
+ (SYMBOL_REF_SMALL_P(RTX) && !SYMBOL_REF_WEAK_DECL_P(RTX))
|
yann@1
|
7465 |
+
|
yann@1
|
7466 |
+/*****************
|
yann@1
|
7467 |
+ * Describing Relative Costs of Operations
|
yann@1
|
7468 |
+ *****************/
|
yann@1
|
7469 |
+
|
yann@1
|
7470 |
+#define SLOW_BYTE_ACCESS 1
|
yann@1
|
7471 |
+
|
yann@1
|
7472 |
+/* It is as good to call a constant function address as to call an address
|
yann@1
|
7473 |
+ kept in a register.
|
yann@1
|
7474 |
+ ??? Not true anymore really. Now that call cannot address full range
|
yann@1
|
7475 |
+ of memory callr may need to be used */
|
yann@1
|
7476 |
+
|
yann@1
|
7477 |
+#define NO_FUNCTION_CSE
|
yann@1
|
7478 |
+#define NO_RECURSIVE_FUNCTION_CSE
|
yann@1
|
7479 |
+
|
yann@1
|
7480 |
+
|
yann@1
|
7481 |
+
|
yann@1
|
7482 |
+/*****************************************
|
yann@1
|
7483 |
+ * Defining the Output Assembler Language
|
yann@1
|
7484 |
+ *****************************************/
|
yann@1
|
7485 |
+
|
yann@1
|
7486 |
+/* ------------------------------------------ *
|
yann@1
|
7487 |
+ * The Overall Framework of an Assembler File
|
yann@1
|
7488 |
+ * ------------------------------------------ */
|
yann@1
|
7489 |
+
|
yann@1
|
7490 |
+#define ASM_APP_ON "#APP\n"
|
yann@1
|
7491 |
+#define ASM_APP_OFF "#NO_APP\n"
|
yann@1
|
7492 |
+
|
yann@1
|
7493 |
+#define ASM_COMMENT_START "# "
|
yann@1
|
7494 |
+
|
yann@1
|
7495 |
+/* ------------------------------- *
|
yann@1
|
7496 |
+ * Output and Generation of Labels
|
yann@1
|
7497 |
+ * ------------------------------- */
|
yann@1
|
7498 |
+
|
yann@1
|
7499 |
+#define GLOBAL_ASM_OP "\t.global\t"
|
yann@1
|
7500 |
+
|
yann@1
|
7501 |
+
|
yann@1
|
7502 |
+/* -------------- *
|
yann@1
|
7503 |
+ * Output of Data
|
yann@1
|
7504 |
+ * -------------- */
|
yann@1
|
7505 |
+
|
yann@1
|
7506 |
+#define DWARF2_UNWIND_INFO 0
|
yann@1
|
7507 |
+
|
yann@1
|
7508 |
+
|
yann@1
|
7509 |
+/* -------------------------------- *
|
yann@1
|
7510 |
+ * Assembler Commands for Alignment
|
yann@1
|
7511 |
+ * -------------------------------- */
|
yann@1
|
7512 |
+
|
yann@1
|
7513 |
+#define ASM_OUTPUT_ALIGN(FILE, LOG) \
|
yann@1
|
7514 |
+ do { \
|
yann@1
|
7515 |
+ fprintf ((FILE), "%s%d\n", ALIGN_ASM_OP, (LOG)); \
|
yann@1
|
7516 |
+ } while (0)
|
yann@1
|
7517 |
+
|
yann@1
|
7518 |
+
|
yann@1
|
7519 |
+/* -------------------------------- *
|
yann@1
|
7520 |
+ * Output of Assembler Instructions
|
yann@1
|
7521 |
+ * -------------------------------- */
|
yann@1
|
7522 |
+
|
yann@1
|
7523 |
+#define REGISTER_NAMES \
|
yann@1
|
7524 |
+{ \
|
yann@1
|
7525 |
+ "zero", \
|
yann@1
|
7526 |
+ "at", \
|
yann@1
|
7527 |
+ "r2", \
|
yann@1
|
7528 |
+ "r3", \
|
yann@1
|
7529 |
+ "r4", \
|
yann@1
|
7530 |
+ "r5", \
|
yann@1
|
7531 |
+ "r6", \
|
yann@1
|
7532 |
+ "r7", \
|
yann@1
|
7533 |
+ "r8", \
|
yann@1
|
7534 |
+ "r9", \
|
yann@1
|
7535 |
+ "r10", \
|
yann@1
|
7536 |
+ "r11", \
|
yann@1
|
7537 |
+ "r12", \
|
yann@1
|
7538 |
+ "r13", \
|
yann@1
|
7539 |
+ "r14", \
|
yann@1
|
7540 |
+ "r15", \
|
yann@1
|
7541 |
+ "r16", \
|
yann@1
|
7542 |
+ "r17", \
|
yann@1
|
7543 |
+ "r18", \
|
yann@1
|
7544 |
+ "r19", \
|
yann@1
|
7545 |
+ "r20", \
|
yann@1
|
7546 |
+ "r21", \
|
yann@1
|
7547 |
+ "r22", \
|
yann@1
|
7548 |
+ "r23", \
|
yann@1
|
7549 |
+ "r24", \
|
yann@1
|
7550 |
+ "r25", \
|
yann@1
|
7551 |
+ "gp", \
|
yann@1
|
7552 |
+ "sp", \
|
yann@1
|
7553 |
+ "fp", \
|
yann@1
|
7554 |
+ "ta", \
|
yann@1
|
7555 |
+ "ba", \
|
yann@1
|
7556 |
+ "ra", \
|
yann@1
|
7557 |
+ "status", \
|
yann@1
|
7558 |
+ "estatus", \
|
yann@1
|
7559 |
+ "bstatus", \
|
yann@1
|
7560 |
+ "ipri", \
|
yann@1
|
7561 |
+ "ecause", \
|
yann@1
|
7562 |
+ "pc", \
|
yann@1
|
7563 |
+ "rap", \
|
yann@1
|
7564 |
+ "fake_fp", \
|
yann@1
|
7565 |
+ "fake_ap", \
|
yann@1
|
7566 |
+}
|
yann@1
|
7567 |
+
|
yann@1
|
7568 |
+#define ASM_OUTPUT_OPCODE(STREAM, PTR)\
|
yann@1
|
7569 |
+ (PTR) = asm_output_opcode (STREAM, PTR)
|
yann@1
|
7570 |
+
|
yann@1
|
7571 |
+#define PRINT_OPERAND(STREAM, X, CODE) \
|
yann@1
|
7572 |
+ nios2_print_operand (STREAM, X, CODE)
|
yann@1
|
7573 |
+
|
yann@1
|
7574 |
+#define PRINT_OPERAND_ADDRESS(STREAM, X) \
|
yann@1
|
7575 |
+ nios2_print_operand_address (STREAM, X)
|
yann@1
|
7576 |
+
|
yann@1
|
7577 |
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
|
yann@1
|
7578 |
+do { fputs (integer_asm_op (POINTER_SIZE / BITS_PER_UNIT, TRUE), FILE); \
|
yann@1
|
7579 |
+ fprintf (FILE, ".L%u\n", (unsigned) (VALUE)); \
|
yann@1
|
7580 |
+ } while (0)
|
yann@1
|
7581 |
+
|
yann@1
|
7582 |
+
|
yann@1
|
7583 |
+/* ------------ *
|
yann@1
|
7584 |
+ * Label Output
|
yann@1
|
7585 |
+ * ------------ */
|
yann@1
|
7586 |
+
|
yann@1
|
7587 |
+
|
yann@1
|
7588 |
+/* ---------------------------------------------------- *
|
yann@1
|
7589 |
+ * Dividing the Output into Sections (Texts, Data, ...)
|
yann@1
|
7590 |
+ * ---------------------------------------------------- */
|
yann@1
|
7591 |
+
|
yann@1
|
7592 |
+/* Output before read-only data. */
|
yann@1
|
7593 |
+#define TEXT_SECTION_ASM_OP ("\t.section\t.text")
|
yann@1
|
7594 |
+
|
yann@1
|
7595 |
+/* Output before writable data. */
|
yann@1
|
7596 |
+#define DATA_SECTION_ASM_OP ("\t.section\t.data")
|
yann@1
|
7597 |
+
|
yann@1
|
7598 |
+
|
yann@1
|
7599 |
+/* Default the definition of "small data" to 8 bytes. */
|
yann@1
|
7600 |
+/* ??? How come I can't use HOST_WIDE_INT here? */
|
yann@1
|
7601 |
+extern unsigned long nios2_section_threshold;
|
yann@1
|
7602 |
+#define NIOS2_DEFAULT_GVALUE 8
|
yann@1
|
7603 |
+
|
yann@1
|
7604 |
+
|
yann@1
|
7605 |
+
|
yann@1
|
7606 |
+/* This says how to output assembler code to declare an
|
yann@1
|
7607 |
+ uninitialized external linkage data object. Under SVR4,
|
yann@1
|
7608 |
+ the linker seems to want the alignment of data objects
|
yann@1
|
7609 |
+ to depend on their types. We do exactly that here. */
|
yann@1
|
7610 |
+
|
yann@1
|
7611 |
+#undef COMMON_ASM_OP
|
yann@1
|
7612 |
+#define COMMON_ASM_OP "\t.comm\t"
|
yann@1
|
7613 |
+
|
yann@1
|
7614 |
+#undef ASM_OUTPUT_ALIGNED_COMMON
|
yann@1
|
7615 |
+#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \
|
yann@1
|
7616 |
+do \
|
yann@1
|
7617 |
+{ \
|
yann@1
|
7618 |
+ if ((SIZE) <= nios2_section_threshold) \
|
yann@1
|
7619 |
+ { \
|
yann@1
|
7620 |
+ named_section (0, ".sbss", 0); \
|
yann@1
|
7621 |
+ (*targetm.asm_out.globalize_label) (FILE, NAME); \
|
yann@1
|
7622 |
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
|
yann@1
|
7623 |
+ if (!flag_inhibit_size_directive) \
|
yann@1
|
7624 |
+ ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, SIZE); \
|
yann@1
|
7625 |
+ ASM_OUTPUT_ALIGN ((FILE), exact_log2((ALIGN) / BITS_PER_UNIT)); \
|
yann@1
|
7626 |
+ ASM_OUTPUT_LABEL(FILE, NAME); \
|
yann@1
|
7627 |
+ ASM_OUTPUT_SKIP((FILE), (SIZE) ? (SIZE) : 1); \
|
yann@1
|
7628 |
+ } \
|
yann@1
|
7629 |
+ else \
|
yann@1
|
7630 |
+ { \
|
yann@1
|
7631 |
+ fprintf ((FILE), "%s", COMMON_ASM_OP); \
|
yann@1
|
7632 |
+ assemble_name ((FILE), (NAME)); \
|
yann@1
|
7633 |
+ fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED",%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT); \
|
yann@1
|
7634 |
+ } \
|
yann@1
|
7635 |
+} \
|
yann@1
|
7636 |
+while (0)
|
yann@1
|
7637 |
+
|
yann@1
|
7638 |
+
|
yann@1
|
7639 |
+/* This says how to output assembler code to declare an
|
yann@1
|
7640 |
+ uninitialized internal linkage data object. Under SVR4,
|
yann@1
|
7641 |
+ the linker seems to want the alignment of data objects
|
yann@1
|
7642 |
+ to depend on their types. We do exactly that here. */
|
yann@1
|
7643 |
+
|
yann@1
|
7644 |
+#undef ASM_OUTPUT_ALIGNED_LOCAL
|
yann@1
|
7645 |
+#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \
|
yann@1
|
7646 |
+do { \
|
yann@1
|
7647 |
+ if ((SIZE) <= nios2_section_threshold) \
|
yann@1
|
7648 |
+ named_section (0, ".sbss", 0); \
|
yann@1
|
7649 |
+ else \
|
yann@1
|
7650 |
+ named_section (0, ".bss", 0); \
|
yann@1
|
7651 |
+ ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
|
yann@1
|
7652 |
+ if (!flag_inhibit_size_directive) \
|
yann@1
|
7653 |
+ ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, SIZE); \
|
yann@1
|
7654 |
+ ASM_OUTPUT_ALIGN ((FILE), exact_log2((ALIGN) / BITS_PER_UNIT)); \
|
yann@1
|
7655 |
+ ASM_OUTPUT_LABEL(FILE, NAME); \
|
yann@1
|
7656 |
+ ASM_OUTPUT_SKIP((FILE), (SIZE) ? (SIZE) : 1); \
|
yann@1
|
7657 |
+} while (0)
|
yann@1
|
7658 |
+
|
yann@1
|
7659 |
+
|
yann@1
|
7660 |
+
|
yann@1
|
7661 |
+/***************************
|
yann@1
|
7662 |
+ * Miscellaneous Parameters
|
yann@1
|
7663 |
+ ***************************/
|
yann@1
|
7664 |
+
|
yann@1
|
7665 |
+#define MOVE_MAX 4
|
yann@1
|
7666 |
+
|
yann@1
|
7667 |
+#define Pmode SImode
|
yann@1
|
7668 |
+#define FUNCTION_MODE QImode
|
yann@1
|
7669 |
+
|
yann@1
|
7670 |
+#define CASE_VECTOR_MODE Pmode
|
yann@1
|
7671 |
+
|
yann@1
|
7672 |
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
|
yann@1
|
7673 |
+
|
yann@1
|
7674 |
+#define LOAD_EXTEND_OP(MODE) (ZERO_EXTEND)
|
yann@1
|
7675 |
+
|
yann@1
|
7676 |
+#define WORD_REGISTER_OPERATIONS
|
yann@1
|
7677 |
--- gcc-3.4.3/gcc/config/nios2/nios2.md
|
yann@1
|
7678 |
+++ gcc-3.4.3-nios2/gcc/config/nios2/nios2.md
|
yann@1
|
7679 |
@@ -0,0 +1,2078 @@
|
yann@1
|
7680 |
+;; Machine Description for Altera NIOS 2G NIOS2 version.
|
yann@1
|
7681 |
+;; Copyright (C) 2003 Altera
|
yann@1
|
7682 |
+;; Contributed by Jonah Graham (jgraham@altera.com).
|
yann@1
|
7683 |
+;;
|
yann@1
|
7684 |
+;; This file is part of GNU CC.
|
yann@1
|
7685 |
+;;
|
yann@1
|
7686 |
+;; GNU CC is free software; you can redistribute it and/or modify
|
yann@1
|
7687 |
+;; it under the terms of the GNU General Public License as published by
|
yann@1
|
7688 |
+;; the Free Software Foundation; either version 2, or (at your option)
|
yann@1
|
7689 |
+;; any later version.
|
yann@1
|
7690 |
+;;
|
yann@1
|
7691 |
+;; GNU CC is distributed in the hope that it will be useful,
|
yann@1
|
7692 |
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
yann@1
|
7693 |
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
yann@1
|
7694 |
+;; GNU General Public License for more details.
|
yann@1
|
7695 |
+;;
|
yann@1
|
7696 |
+;; You should have received a copy of the GNU General Public License
|
yann@1
|
7697 |
+;; along with GNU CC; see the file COPYING. If not, write to
|
yann@1
|
7698 |
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
|
yann@1
|
7699 |
+;; Boston, MA 02111-1307, USA. */
|
yann@1
|
7700 |
+
|
yann@1
|
7701 |
+
|
yann@1
|
7702 |
+
|
yann@1
|
7703 |
+;*****************************************************************************
|
yann@1
|
7704 |
+;*
|
yann@1
|
7705 |
+;* constants
|
yann@1
|
7706 |
+;*
|
yann@1
|
7707 |
+;*****************************************************************************
|
yann@1
|
7708 |
+(define_constants [
|
yann@1
|
7709 |
+ (GP_REGNO 26)
|
yann@1
|
7710 |
+ (SP_REGNO 27)
|
yann@1
|
7711 |
+ (FP_REGNO 28)
|
yann@1
|
7712 |
+ (RA_REGNO 31)
|
yann@1
|
7713 |
+ (RAP_REGNO 38)
|
yann@1
|
7714 |
+ (FIRST_RETVAL_REGNO 2)
|
yann@1
|
7715 |
+ (LAST_RETVAL_REGNO 3)
|
yann@1
|
7716 |
+ (FIRST_ARG_REGNO 4)
|
yann@1
|
7717 |
+ (LAST_ARG_REGNO 7)
|
yann@1
|
7718 |
+ (SC_REGNO 23)
|
yann@1
|
7719 |
+ (PC_REGNO 37)
|
yann@1
|
7720 |
+ (FAKE_FP_REGNO 39)
|
yann@1
|
7721 |
+ (FAKE_AP_REGNO 40)
|
yann@1
|
7722 |
+
|
yann@1
|
7723 |
+
|
yann@1
|
7724 |
+ (UNSPEC_BLOCKAGE 0)
|
yann@1
|
7725 |
+ (UNSPEC_LDBIO 1)
|
yann@1
|
7726 |
+ (UNSPEC_LDBUIO 2)
|
yann@1
|
7727 |
+ (UNSPEC_LDHIO 3)
|
yann@1
|
7728 |
+ (UNSPEC_LDHUIO 4)
|
yann@1
|
7729 |
+ (UNSPEC_LDWIO 5)
|
yann@1
|
7730 |
+ (UNSPEC_STBIO 6)
|
yann@1
|
7731 |
+ (UNSPEC_STHIO 7)
|
yann@1
|
7732 |
+ (UNSPEC_STWIO 8)
|
yann@1
|
7733 |
+ (UNSPEC_SYNC 9)
|
yann@1
|
7734 |
+ (UNSPEC_WRCTL 10)
|
yann@1
|
7735 |
+ (UNSPEC_RDCTL 11)
|
yann@1
|
7736 |
+
|
yann@1
|
7737 |
+])
|
yann@1
|
7738 |
+
|
yann@1
|
7739 |
+
|
yann@1
|
7740 |
+
|
yann@1
|
7741 |
+;*****************************************************************************
|
yann@1
|
7742 |
+;*
|
yann@1
|
7743 |
+;* instruction scheduler
|
yann@1
|
7744 |
+;*
|
yann@1
|
7745 |
+;*****************************************************************************
|
yann@1
|
7746 |
+
|
yann@1
|
7747 |
+; No schedule info is currently available, using an assumption that no
|
yann@1
|
7748 |
+; instruction can use the results of the previous instruction without
|
yann@1
|
7749 |
+; incuring a stall.
|
yann@1
|
7750 |
+
|
yann@1
|
7751 |
+; length of an instruction (in bytes)
|
yann@1
|
7752 |
+(define_attr "length" "" (const_int 4))
|
yann@1
|
7753 |
+(define_attr "type" "unknown,complex,control,alu,cond_alu,st,ld,shift,mul,div,custom" (const_string "complex"))
|
yann@1
|
7754 |
+
|
yann@1
|
7755 |
+(define_asm_attributes
|
yann@1
|
7756 |
+ [(set_attr "length" "4")
|
yann@1
|
7757 |
+ (set_attr "type" "complex")])
|
yann@1
|
7758 |
+
|
yann@1
|
7759 |
+(define_automaton "nios2")
|
yann@1
|
7760 |
+(automata_option "v")
|
yann@1
|
7761 |
+;(automata_option "no-minimization")
|
yann@1
|
7762 |
+(automata_option "ndfa")
|
yann@1
|
7763 |
+
|
yann@1
|
7764 |
+; The nios2 pipeline is fairly straightforward for the fast model.
|
yann@1
|
7765 |
+; Every alu operation is pipelined so that an instruction can
|
yann@1
|
7766 |
+; be issued every cycle. However, there are still potential
|
yann@1
|
7767 |
+; stalls which this description tries to deal with.
|
yann@1
|
7768 |
+
|
yann@1
|
7769 |
+(define_cpu_unit "cpu" "nios2")
|
yann@1
|
7770 |
+
|
yann@1
|
7771 |
+(define_insn_reservation "complex" 1
|
yann@1
|
7772 |
+ (eq_attr "type" "complex")
|
yann@1
|
7773 |
+ "cpu")
|
yann@1
|
7774 |
+
|
yann@1
|
7775 |
+(define_insn_reservation "control" 1
|
yann@1
|
7776 |
+ (eq_attr "type" "control")
|
yann@1
|
7777 |
+ "cpu")
|
yann@1
|
7778 |
+
|
yann@1
|
7779 |
+(define_insn_reservation "alu" 1
|
yann@1
|
7780 |
+ (eq_attr "type" "alu")
|
yann@1
|
7781 |
+ "cpu")
|
yann@1
|
7782 |
+
|
yann@1
|
7783 |
+(define_insn_reservation "cond_alu" 1
|
yann@1
|
7784 |
+ (eq_attr "type" "cond_alu")
|
yann@1
|
7785 |
+ "cpu")
|
yann@1
|
7786 |
+
|
yann@1
|
7787 |
+(define_insn_reservation "st" 1
|
yann@1
|
7788 |
+ (eq_attr "type" "st")
|
yann@1
|
7789 |
+ "cpu")
|
yann@1
|
7790 |
+
|
yann@1
|
7791 |
+(define_insn_reservation "custom" 1
|
yann@1
|
7792 |
+ (eq_attr "type" "custom")
|
yann@1
|
7793 |
+ "cpu")
|
yann@1
|
7794 |
+
|
yann@1
|
7795 |
+; shifts, muls and lds have three cycle latency
|
yann@1
|
7796 |
+(define_insn_reservation "ld" 3
|
yann@1
|
7797 |
+ (eq_attr "type" "ld")
|
yann@1
|
7798 |
+ "cpu")
|
yann@1
|
7799 |
+
|
yann@1
|
7800 |
+(define_insn_reservation "shift" 3
|
yann@1
|
7801 |
+ (eq_attr "type" "shift")
|
yann@1
|
7802 |
+ "cpu")
|
yann@1
|
7803 |
+
|
yann@1
|
7804 |
+(define_insn_reservation "mul" 3
|
yann@1
|
7805 |
+ (eq_attr "type" "mul")
|
yann@1
|
7806 |
+ "cpu")
|
yann@1
|
7807 |
+
|
yann@1
|
7808 |
+(define_insn_reservation "div" 1
|
yann@1
|
7809 |
+ (eq_attr "type" "div")
|
yann@1
|
7810 |
+ "cpu")
|
yann@1
|
7811 |
+
|
yann@1
|
7812 |
+
|
yann@1
|
7813 |
+;*****************************************************************************
|
yann@1
|
7814 |
+;*
|
yann@1
|
7815 |
+;* MOV Instructions
|
yann@1
|
7816 |
+;*
|
yann@1
|
7817 |
+;*****************************************************************************
|
yann@1
|
7818 |
+
|
yann@1
|
7819 |
+(define_expand "movqi"
|
yann@1
|
7820 |
+ [(set (match_operand:QI 0 "nonimmediate_operand" "")
|
yann@1
|
7821 |
+ (match_operand:QI 1 "general_operand" ""))]
|
yann@1
|
7822 |
+ ""
|
yann@1
|
7823 |
+{
|
yann@1
|
7824 |
+ if (nios2_emit_move_sequence (operands, QImode))
|
yann@1
|
7825 |
+ DONE;
|
yann@1
|
7826 |
+})
|
yann@1
|
7827 |
+
|
yann@1
|
7828 |
+(define_insn "movqi_internal"
|
yann@1
|
7829 |
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=m, r,r, r")
|
yann@1
|
7830 |
+ (match_operand:QI 1 "general_operand" "rM,m,rM,I"))]
|
yann@1
|
7831 |
+ "(register_operand (operands[0], QImode)
|
yann@1
|
7832 |
+ || register_operand (operands[1], QImode)
|
yann@1
|
7833 |
+ || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))"
|
yann@1
|
7834 |
+ "@
|
yann@1
|
7835 |
+ stb%o0\\t%z1, %0
|
yann@1
|
7836 |
+ ldbu%o1\\t%0, %1
|
yann@1
|
7837 |
+ mov\\t%0, %z1
|
yann@1
|
7838 |
+ movi\\t%0, %1"
|
yann@1
|
7839 |
+ [(set_attr "type" "st,ld,alu,alu")])
|
yann@1
|
7840 |
+
|
yann@1
|
7841 |
+(define_insn "ldbio"
|
yann@1
|
7842 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
7843 |
+ (unspec_volatile:SI [(const_int 0)] UNSPEC_LDBIO))
|
yann@1
|
7844 |
+ (use (match_operand:SI 1 "memory_operand" "m"))]
|
yann@1
|
7845 |
+ ""
|
yann@1
|
7846 |
+ "ldbio\\t%0, %1"
|
yann@1
|
7847 |
+ [(set_attr "type" "ld")])
|
yann@1
|
7848 |
+
|
yann@1
|
7849 |
+(define_insn "ldbuio"
|
yann@1
|
7850 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
7851 |
+ (unspec_volatile:SI [(const_int 0)] UNSPEC_LDBUIO))
|
yann@1
|
7852 |
+ (use (match_operand:SI 1 "memory_operand" "m"))]
|
yann@1
|
7853 |
+ ""
|
yann@1
|
7854 |
+ "ldbuio\\t%0, %1"
|
yann@1
|
7855 |
+ [(set_attr "type" "ld")])
|
yann@1
|
7856 |
+
|
yann@1
|
7857 |
+(define_insn "stbio"
|
yann@1
|
7858 |
+ [(set (match_operand:SI 0 "memory_operand" "=m")
|
yann@1
|
7859 |
+ (match_operand:SI 1 "register_operand" "r"))
|
yann@1
|
7860 |
+ (unspec_volatile:SI [(const_int 0)] UNSPEC_STBIO)]
|
yann@1
|
7861 |
+ ""
|
yann@1
|
7862 |
+ "stbio\\t%z1, %0"
|
yann@1
|
7863 |
+ [(set_attr "type" "st")])
|
yann@1
|
7864 |
+
|
yann@1
|
7865 |
+
|
yann@1
|
7866 |
+(define_expand "movhi"
|
yann@1
|
7867 |
+ [(set (match_operand:HI 0 "nonimmediate_operand" "")
|
yann@1
|
7868 |
+ (match_operand:HI 1 "general_operand" ""))]
|
yann@1
|
7869 |
+ ""
|
yann@1
|
7870 |
+{
|
yann@1
|
7871 |
+ if (nios2_emit_move_sequence (operands, HImode))
|
yann@1
|
7872 |
+ DONE;
|
yann@1
|
7873 |
+})
|
yann@1
|
7874 |
+
|
yann@1
|
7875 |
+(define_insn "movhi_internal"
|
yann@1
|
7876 |
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=m, r,r, r,r")
|
yann@1
|
7877 |
+ (match_operand:HI 1 "general_operand" "rM,m,rM,I,J"))]
|
yann@1
|
7878 |
+ "(register_operand (operands[0], HImode)
|
yann@1
|
7879 |
+ || register_operand (operands[1], HImode)
|
yann@1
|
7880 |
+ || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))"
|
yann@1
|
7881 |
+ "@
|
yann@1
|
7882 |
+ sth%o0\\t%z1, %0
|
yann@1
|
7883 |
+ ldhu%o1\\t%0, %1
|
yann@1
|
7884 |
+ mov\\t%0, %z1
|
yann@1
|
7885 |
+ movi\\t%0, %1
|
yann@1
|
7886 |
+ movui\\t%0, %1"
|
yann@1
|
7887 |
+ [(set_attr "type" "st,ld,alu,alu,alu")])
|
yann@1
|
7888 |
+
|
yann@1
|
7889 |
+(define_insn "ldhio"
|
yann@1
|
7890 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
7891 |
+ (unspec_volatile:SI [(const_int 0)] UNSPEC_LDHIO))
|
yann@1
|
7892 |
+ (use (match_operand:SI 1 "memory_operand" "m"))]
|
yann@1
|
7893 |
+ ""
|
yann@1
|
7894 |
+ "ldhio\\t%0, %1"
|
yann@1
|
7895 |
+ [(set_attr "type" "ld")])
|
yann@1
|
7896 |
+
|
yann@1
|
7897 |
+(define_insn "ldhuio"
|
yann@1
|
7898 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
7899 |
+ (unspec_volatile:SI [(const_int 0)] UNSPEC_LDHUIO))
|
yann@1
|
7900 |
+ (use (match_operand:SI 1 "memory_operand" "m"))]
|
yann@1
|
7901 |
+ ""
|
yann@1
|
7902 |
+ "ldhuio\\t%0, %1"
|
yann@1
|
7903 |
+ [(set_attr "type" "ld")])
|
yann@1
|
7904 |
+
|
yann@1
|
7905 |
+(define_insn "sthio"
|
yann@1
|
7906 |
+ [(set (match_operand:SI 0 "memory_operand" "=m")
|
yann@1
|
7907 |
+ (match_operand:SI 1 "register_operand" "r"))
|
yann@1
|
7908 |
+ (unspec_volatile:SI [(const_int 0)] UNSPEC_STHIO)]
|
yann@1
|
7909 |
+ ""
|
yann@1
|
7910 |
+ "sthio\\t%z1, %0"
|
yann@1
|
7911 |
+ [(set_attr "type" "st")])
|
yann@1
|
7912 |
+
|
yann@1
|
7913 |
+(define_expand "movsi"
|
yann@1
|
7914 |
+ [(set (match_operand:SI 0 "nonimmediate_operand" "")
|
yann@1
|
7915 |
+ (match_operand:SI 1 "general_operand" ""))]
|
yann@1
|
7916 |
+ ""
|
yann@1
|
7917 |
+{
|
yann@1
|
7918 |
+ if (nios2_emit_move_sequence (operands, SImode))
|
yann@1
|
7919 |
+ DONE;
|
yann@1
|
7920 |
+})
|
yann@1
|
7921 |
+
|
yann@1
|
7922 |
+(define_insn "movsi_internal"
|
yann@1
|
7923 |
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=m, r,r, r,r,r,r")
|
yann@1
|
7924 |
+ (match_operand:SI 1 "general_operand" "rM,m,rM,I,J,S,i"))]
|
yann@1
|
7925 |
+ "(register_operand (operands[0], SImode)
|
yann@1
|
7926 |
+ || register_operand (operands[1], SImode)
|
yann@1
|
7927 |
+ || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))"
|
yann@1
|
7928 |
+ "@
|
yann@1
|
7929 |
+ stw%o0\\t%z1, %0
|
yann@1
|
7930 |
+ ldw%o1\\t%0, %1
|
yann@1
|
7931 |
+ mov\\t%0, %z1
|
yann@1
|
7932 |
+ movi\\t%0, %1
|
yann@1
|
7933 |
+ movui\\t%0, %1
|
yann@1
|
7934 |
+ addi\\t%0, gp, %%gprel(%1)
|
yann@1
|
7935 |
+ movhi\\t%0, %H1\;addi\\t%0, %0, %L1"
|
yann@1
|
7936 |
+ [(set_attr "type" "st,ld,alu,alu,alu,alu,alu")])
|
yann@1
|
7937 |
+
|
yann@1
|
7938 |
+(define_insn "ldwio"
|
yann@1
|
7939 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
7940 |
+ (unspec_volatile:SI [(const_int 0)] UNSPEC_LDWIO))
|
yann@1
|
7941 |
+ (use (match_operand:SI 1 "memory_operand" "m"))]
|
yann@1
|
7942 |
+ ""
|
yann@1
|
7943 |
+ "ldwio\\t%0, %1"
|
yann@1
|
7944 |
+ [(set_attr "type" "ld")])
|
yann@1
|
7945 |
+
|
yann@1
|
7946 |
+(define_insn "stwio"
|
yann@1
|
7947 |
+ [(set (match_operand:SI 0 "memory_operand" "=m")
|
yann@1
|
7948 |
+ (match_operand:SI 1 "register_operand" "r"))
|
yann@1
|
7949 |
+ (unspec_volatile:SI [(const_int 0)] UNSPEC_STWIO)]
|
yann@1
|
7950 |
+ ""
|
yann@1
|
7951 |
+ "stwio\\t%z1, %0"
|
yann@1
|
7952 |
+ [(set_attr "type" "st")])
|
yann@1
|
7953 |
+
|
yann@1
|
7954 |
+
|
yann@1
|
7955 |
+
|
yann@1
|
7956 |
+;*****************************************************************************
|
yann@1
|
7957 |
+;*
|
yann@1
|
7958 |
+;* zero extension
|
yann@1
|
7959 |
+;*
|
yann@1
|
7960 |
+;*****************************************************************************
|
yann@1
|
7961 |
+
|
yann@1
|
7962 |
+
|
yann@1
|
7963 |
+(define_insn "zero_extendhisi2"
|
yann@1
|
7964 |
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
|
yann@1
|
7965 |
+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
|
yann@1
|
7966 |
+ ""
|
yann@1
|
7967 |
+ "@
|
yann@1
|
7968 |
+ andi\\t%0, %1, 0xffff
|
yann@1
|
7969 |
+ ldhu%o1\\t%0, %1"
|
yann@1
|
7970 |
+ [(set_attr "type" "alu,ld")])
|
yann@1
|
7971 |
+
|
yann@1
|
7972 |
+(define_insn "zero_extendqihi2"
|
yann@1
|
7973 |
+ [(set (match_operand:HI 0 "register_operand" "=r,r")
|
yann@1
|
7974 |
+ (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
|
yann@1
|
7975 |
+ ""
|
yann@1
|
7976 |
+ "@
|
yann@1
|
7977 |
+ andi\\t%0, %1, 0xff
|
yann@1
|
7978 |
+ ldbu%o1\\t%0, %1"
|
yann@1
|
7979 |
+ [(set_attr "type" "alu,ld")])
|
yann@1
|
7980 |
+
|
yann@1
|
7981 |
+(define_insn "zero_extendqisi2"
|
yann@1
|
7982 |
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
|
yann@1
|
7983 |
+ (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
|
yann@1
|
7984 |
+ ""
|
yann@1
|
7985 |
+ "@
|
yann@1
|
7986 |
+ andi\\t%0, %1, 0xff
|
yann@1
|
7987 |
+ ldbu%o1\\t%0, %1"
|
yann@1
|
7988 |
+ [(set_attr "type" "alu,ld")])
|
yann@1
|
7989 |
+
|
yann@1
|
7990 |
+
|
yann@1
|
7991 |
+
|
yann@1
|
7992 |
+;*****************************************************************************
|
yann@1
|
7993 |
+;*
|
yann@1
|
7994 |
+;* sign extension
|
yann@1
|
7995 |
+;*
|
yann@1
|
7996 |
+;*****************************************************************************
|
yann@1
|
7997 |
+
|
yann@1
|
7998 |
+(define_expand "extendhisi2"
|
yann@1
|
7999 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
yann@1
|
8000 |
+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
|
yann@1
|
8001 |
+ ""
|
yann@1
|
8002 |
+{
|
yann@1
|
8003 |
+ if (optimize && GET_CODE (operands[1]) == MEM)
|
yann@1
|
8004 |
+ operands[1] = force_not_mem (operands[1]);
|
yann@1
|
8005 |
+
|
yann@1
|
8006 |
+ if (GET_CODE (operands[1]) != MEM)
|
yann@1
|
8007 |
+ {
|
yann@1
|
8008 |
+ rtx op1 = gen_lowpart (SImode, operands[1]);
|
yann@1
|
8009 |
+ rtx temp = gen_reg_rtx (SImode);
|
yann@1
|
8010 |
+ rtx shift = GEN_INT (16);
|
yann@1
|
8011 |
+
|
yann@1
|
8012 |
+ emit_insn (gen_ashlsi3 (temp, op1, shift));
|
yann@1
|
8013 |
+ emit_insn (gen_ashrsi3 (operands[0], temp, shift));
|
yann@1
|
8014 |
+ DONE;
|
yann@1
|
8015 |
+ }
|
yann@1
|
8016 |
+})
|
yann@1
|
8017 |
+
|
yann@1
|
8018 |
+(define_insn "extendhisi2_internal"
|
yann@1
|
8019 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8020 |
+ (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
|
yann@1
|
8021 |
+ ""
|
yann@1
|
8022 |
+ "ldh%o1\\t%0, %1"
|
yann@1
|
8023 |
+ [(set_attr "type" "ld")])
|
yann@1
|
8024 |
+
|
yann@1
|
8025 |
+(define_expand "extendqihi2"
|
yann@1
|
8026 |
+ [(set (match_operand:HI 0 "register_operand" "")
|
yann@1
|
8027 |
+ (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))]
|
yann@1
|
8028 |
+ ""
|
yann@1
|
8029 |
+{
|
yann@1
|
8030 |
+ if (optimize && GET_CODE (operands[1]) == MEM)
|
yann@1
|
8031 |
+ operands[1] = force_not_mem (operands[1]);
|
yann@1
|
8032 |
+
|
yann@1
|
8033 |
+ if (GET_CODE (operands[1]) != MEM)
|
yann@1
|
8034 |
+ {
|
yann@1
|
8035 |
+ rtx op0 = gen_lowpart (SImode, operands[0]);
|
yann@1
|
8036 |
+ rtx op1 = gen_lowpart (SImode, operands[1]);
|
yann@1
|
8037 |
+ rtx temp = gen_reg_rtx (SImode);
|
yann@1
|
8038 |
+ rtx shift = GEN_INT (24);
|
yann@1
|
8039 |
+
|
yann@1
|
8040 |
+ emit_insn (gen_ashlsi3 (temp, op1, shift));
|
yann@1
|
8041 |
+ emit_insn (gen_ashrsi3 (op0, temp, shift));
|
yann@1
|
8042 |
+ DONE;
|
yann@1
|
8043 |
+ }
|
yann@1
|
8044 |
+})
|
yann@1
|
8045 |
+
|
yann@1
|
8046 |
+(define_insn "extendqihi2_internal"
|
yann@1
|
8047 |
+ [(set (match_operand:HI 0 "register_operand" "=r")
|
yann@1
|
8048 |
+ (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
|
yann@1
|
8049 |
+ ""
|
yann@1
|
8050 |
+ "ldb%o1\\t%0, %1"
|
yann@1
|
8051 |
+ [(set_attr "type" "ld")])
|
yann@1
|
8052 |
+
|
yann@1
|
8053 |
+
|
yann@1
|
8054 |
+(define_expand "extendqisi2"
|
yann@1
|
8055 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
yann@1
|
8056 |
+ (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
|
yann@1
|
8057 |
+ ""
|
yann@1
|
8058 |
+{
|
yann@1
|
8059 |
+ if (optimize && GET_CODE (operands[1]) == MEM)
|
yann@1
|
8060 |
+ operands[1] = force_not_mem (operands[1]);
|
yann@1
|
8061 |
+
|
yann@1
|
8062 |
+ if (GET_CODE (operands[1]) != MEM)
|
yann@1
|
8063 |
+ {
|
yann@1
|
8064 |
+ rtx op1 = gen_lowpart (SImode, operands[1]);
|
yann@1
|
8065 |
+ rtx temp = gen_reg_rtx (SImode);
|
yann@1
|
8066 |
+ rtx shift = GEN_INT (24);
|
yann@1
|
8067 |
+
|
yann@1
|
8068 |
+ emit_insn (gen_ashlsi3 (temp, op1, shift));
|
yann@1
|
8069 |
+ emit_insn (gen_ashrsi3 (operands[0], temp, shift));
|
yann@1
|
8070 |
+ DONE;
|
yann@1
|
8071 |
+ }
|
yann@1
|
8072 |
+})
|
yann@1
|
8073 |
+
|
yann@1
|
8074 |
+(define_insn "extendqisi2_insn"
|
yann@1
|
8075 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8076 |
+ (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
|
yann@1
|
8077 |
+ ""
|
yann@1
|
8078 |
+ "ldb%o1\\t%0, %1"
|
yann@1
|
8079 |
+ [(set_attr "type" "ld")])
|
yann@1
|
8080 |
+
|
yann@1
|
8081 |
+
|
yann@1
|
8082 |
+
|
yann@1
|
8083 |
+;*****************************************************************************
|
yann@1
|
8084 |
+;*
|
yann@1
|
8085 |
+;* Arithmetic Operations
|
yann@1
|
8086 |
+;*
|
yann@1
|
8087 |
+;*****************************************************************************
|
yann@1
|
8088 |
+
|
yann@1
|
8089 |
+(define_insn "addsi3"
|
yann@1
|
8090 |
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
|
yann@1
|
8091 |
+ (plus:SI (match_operand:SI 1 "register_operand" "%r,r")
|
yann@1
|
8092 |
+ (match_operand:SI 2 "arith_operand" "r,I")))]
|
yann@1
|
8093 |
+ ""
|
yann@1
|
8094 |
+ "add%i2\\t%0, %1, %z2"
|
yann@1
|
8095 |
+ [(set_attr "type" "alu")])
|
yann@1
|
8096 |
+
|
yann@1
|
8097 |
+(define_insn "subsi3"
|
yann@1
|
8098 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8099 |
+ (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
|
yann@1
|
8100 |
+ (match_operand:SI 2 "register_operand" "r")))]
|
yann@1
|
8101 |
+ ""
|
yann@1
|
8102 |
+ "sub\\t%0, %z1, %2"
|
yann@1
|
8103 |
+ [(set_attr "type" "alu")])
|
yann@1
|
8104 |
+
|
yann@1
|
8105 |
+(define_insn "mulsi3"
|
yann@1
|
8106 |
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
|
yann@1
|
8107 |
+ (mult:SI (match_operand:SI 1 "register_operand" "r,r")
|
yann@1
|
8108 |
+ (match_operand:SI 2 "arith_operand" "r,I")))]
|
yann@1
|
8109 |
+ "TARGET_HAS_MUL"
|
yann@1
|
8110 |
+ "mul%i2\\t%0, %1, %z2"
|
yann@1
|
8111 |
+ [(set_attr "type" "mul")])
|
yann@1
|
8112 |
+
|
yann@1
|
8113 |
+(define_expand "divsi3"
|
yann@1
|
8114 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8115 |
+ (div:SI (match_operand:SI 1 "register_operand" "r")
|
yann@1
|
8116 |
+ (match_operand:SI 2 "register_operand" "r")))]
|
yann@1
|
8117 |
+ ""
|
yann@1
|
8118 |
+{
|
yann@1
|
8119 |
+ if (!TARGET_HAS_DIV)
|
yann@1
|
8120 |
+ {
|
yann@1
|
8121 |
+ if (!TARGET_FAST_SW_DIV)
|
yann@1
|
8122 |
+ FAIL;
|
yann@1
|
8123 |
+ else
|
yann@1
|
8124 |
+ {
|
yann@1
|
8125 |
+ if (nios2_emit_expensive_div (operands, SImode))
|
yann@1
|
8126 |
+ DONE;
|
yann@1
|
8127 |
+ }
|
yann@1
|
8128 |
+ }
|
yann@1
|
8129 |
+})
|
yann@1
|
8130 |
+
|
yann@1
|
8131 |
+(define_insn "divsi3_insn"
|
yann@1
|
8132 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8133 |
+ (div:SI (match_operand:SI 1 "register_operand" "r")
|
yann@1
|
8134 |
+ (match_operand:SI 2 "register_operand" "r")))]
|
yann@1
|
8135 |
+ "TARGET_HAS_DIV"
|
yann@1
|
8136 |
+ "div\\t%0, %1, %2"
|
yann@1
|
8137 |
+ [(set_attr "type" "div")])
|
yann@1
|
8138 |
+
|
yann@1
|
8139 |
+(define_insn "udivsi3"
|
yann@1
|
8140 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8141 |
+ (udiv:SI (match_operand:SI 1 "register_operand" "r")
|
yann@1
|
8142 |
+ (match_operand:SI 2 "register_operand" "r")))]
|
yann@1
|
8143 |
+ "TARGET_HAS_DIV"
|
yann@1
|
8144 |
+ "divu\\t%0, %1, %2"
|
yann@1
|
8145 |
+ [(set_attr "type" "div")])
|
yann@1
|
8146 |
+
|
yann@1
|
8147 |
+(define_insn "smulsi3_highpart"
|
yann@1
|
8148 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8149 |
+ (truncate:SI
|
yann@1
|
8150 |
+ (lshiftrt:DI
|
yann@1
|
8151 |
+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
|
yann@1
|
8152 |
+ (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
|
yann@1
|
8153 |
+ (const_int 32))))]
|
yann@1
|
8154 |
+ "TARGET_HAS_MULX"
|
yann@1
|
8155 |
+ "mulxss\\t%0, %1, %2"
|
yann@1
|
8156 |
+ [(set_attr "type" "mul")])
|
yann@1
|
8157 |
+
|
yann@1
|
8158 |
+(define_insn "umulsi3_highpart"
|
yann@1
|
8159 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8160 |
+ (truncate:SI
|
yann@1
|
8161 |
+ (lshiftrt:DI
|
yann@1
|
8162 |
+ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
|
yann@1
|
8163 |
+ (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
|
yann@1
|
8164 |
+ (const_int 32))))]
|
yann@1
|
8165 |
+ "TARGET_HAS_MULX"
|
yann@1
|
8166 |
+ "mulxuu\\t%0, %1, %2"
|
yann@1
|
8167 |
+ [(set_attr "type" "mul")])
|
yann@1
|
8168 |
+
|
yann@1
|
8169 |
+
|
yann@1
|
8170 |
+(define_expand "mulsidi3"
|
yann@1
|
8171 |
+ [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 0)
|
yann@1
|
8172 |
+ (mult:SI (match_operand:SI 1 "register_operand" "")
|
yann@1
|
8173 |
+ (match_operand:SI 2 "register_operand" "")))
|
yann@1
|
8174 |
+ (set (subreg:SI (match_dup 0) 4)
|
yann@1
|
8175 |
+ (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1))
|
yann@1
|
8176 |
+ (sign_extend:DI (match_dup 2)))
|
yann@1
|
8177 |
+ (const_int 32))))]
|
yann@1
|
8178 |
+ "TARGET_HAS_MULX"
|
yann@1
|
8179 |
+ "")
|
yann@1
|
8180 |
+
|
yann@1
|
8181 |
+(define_expand "umulsidi3"
|
yann@1
|
8182 |
+ [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 0)
|
yann@1
|
8183 |
+ (mult:SI (match_operand:SI 1 "register_operand" "")
|
yann@1
|
8184 |
+ (match_operand:SI 2 "register_operand" "")))
|
yann@1
|
8185 |
+ (set (subreg:SI (match_dup 0) 4)
|
yann@1
|
8186 |
+ (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1))
|
yann@1
|
8187 |
+ (zero_extend:DI (match_dup 2)))
|
yann@1
|
8188 |
+ (const_int 32))))]
|
yann@1
|
8189 |
+ "TARGET_HAS_MULX"
|
yann@1
|
8190 |
+ "")
|
yann@1
|
8191 |
+
|
yann@1
|
8192 |
+
|
yann@1
|
8193 |
+
|
yann@1
|
8194 |
+;*****************************************************************************
|
yann@1
|
8195 |
+;*
|
yann@1
|
8196 |
+;* Negate and ones complement
|
yann@1
|
8197 |
+;*
|
yann@1
|
8198 |
+;*****************************************************************************
|
yann@1
|
8199 |
+
|
yann@1
|
8200 |
+(define_insn "negsi2"
|
yann@1
|
8201 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8202 |
+ (neg:SI (match_operand:SI 1 "register_operand" "r")))]
|
yann@1
|
8203 |
+ ""
|
yann@1
|
8204 |
+{
|
yann@1
|
8205 |
+ operands[2] = const0_rtx;
|
yann@1
|
8206 |
+ return "sub\\t%0, %z2, %1";
|
yann@1
|
8207 |
+}
|
yann@1
|
8208 |
+ [(set_attr "type" "alu")])
|
yann@1
|
8209 |
+
|
yann@1
|
8210 |
+(define_insn "one_cmplsi2"
|
yann@1
|
8211 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8212 |
+ (not:SI (match_operand:SI 1 "register_operand" "r")))]
|
yann@1
|
8213 |
+ ""
|
yann@1
|
8214 |
+{
|
yann@1
|
8215 |
+ operands[2] = const0_rtx;
|
yann@1
|
8216 |
+ return "nor\\t%0, %z2, %1";
|
yann@1
|
8217 |
+}
|
yann@1
|
8218 |
+ [(set_attr "type" "alu")])
|
yann@1
|
8219 |
+
|
yann@1
|
8220 |
+
|
yann@1
|
8221 |
+
|
yann@1
|
8222 |
+; Logical Operantions
|
yann@1
|
8223 |
+
|
yann@1
|
8224 |
+(define_insn "andsi3"
|
yann@1
|
8225 |
+ [(set (match_operand:SI 0 "register_operand" "=r, r,r")
|
yann@1
|
8226 |
+ (and:SI (match_operand:SI 1 "register_operand" "%r, r,r")
|
yann@1
|
8227 |
+ (match_operand:SI 2 "logical_operand" "rM,J,K")))]
|
yann@1
|
8228 |
+ ""
|
yann@1
|
8229 |
+ "@
|
yann@1
|
8230 |
+ and\\t%0, %1, %z2
|
yann@1
|
8231 |
+ and%i2\\t%0, %1, %2
|
yann@1
|
8232 |
+ andh%i2\\t%0, %1, %U2"
|
yann@1
|
8233 |
+ [(set_attr "type" "alu")])
|
yann@1
|
8234 |
+
|
yann@1
|
8235 |
+(define_insn "iorsi3"
|
yann@1
|
8236 |
+ [(set (match_operand:SI 0 "register_operand" "=r, r,r")
|
yann@1
|
8237 |
+ (ior:SI (match_operand:SI 1 "register_operand" "%r, r,r")
|
yann@1
|
8238 |
+ (match_operand:SI 2 "logical_operand" "rM,J,K")))]
|
yann@1
|
8239 |
+ ""
|
yann@1
|
8240 |
+ "@
|
yann@1
|
8241 |
+ or\\t%0, %1, %z2
|
yann@1
|
8242 |
+ or%i2\\t%0, %1, %2
|
yann@1
|
8243 |
+ orh%i2\\t%0, %1, %U2"
|
yann@1
|
8244 |
+ [(set_attr "type" "alu")])
|
yann@1
|
8245 |
+
|
yann@1
|
8246 |
+(define_insn "*norsi3"
|
yann@1
|
8247 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8248 |
+ (and:SI (not:SI (match_operand:SI 1 "register_operand" "%r"))
|
yann@1
|
8249 |
+ (not:SI (match_operand:SI 2 "reg_or_0_operand" "rM"))))]
|
yann@1
|
8250 |
+ ""
|
yann@1
|
8251 |
+ "nor\\t%0, %1, %z2"
|
yann@1
|
8252 |
+ [(set_attr "type" "alu")])
|
yann@1
|
8253 |
+
|
yann@1
|
8254 |
+(define_insn "xorsi3"
|
yann@1
|
8255 |
+ [(set (match_operand:SI 0 "register_operand" "=r, r,r")
|
yann@1
|
8256 |
+ (xor:SI (match_operand:SI 1 "register_operand" "%r, r,r")
|
yann@1
|
8257 |
+ (match_operand:SI 2 "logical_operand" "rM,J,K")))]
|
yann@1
|
8258 |
+ ""
|
yann@1
|
8259 |
+ "@
|
yann@1
|
8260 |
+ xor\\t%0, %1, %z2
|
yann@1
|
8261 |
+ xor%i2\\t%0, %1, %2
|
yann@1
|
8262 |
+ xorh%i2\\t%0, %1, %U2"
|
yann@1
|
8263 |
+ [(set_attr "type" "alu")])
|
yann@1
|
8264 |
+
|
yann@1
|
8265 |
+
|
yann@1
|
8266 |
+
|
yann@1
|
8267 |
+;*****************************************************************************
|
yann@1
|
8268 |
+;*
|
yann@1
|
8269 |
+;* Shifts
|
yann@1
|
8270 |
+;*
|
yann@1
|
8271 |
+;*****************************************************************************
|
yann@1
|
8272 |
+
|
yann@1
|
8273 |
+(define_insn "ashlsi3"
|
yann@1
|
8274 |
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
|
yann@1
|
8275 |
+ (ashift:SI (match_operand:SI 1 "register_operand" "r,r")
|
yann@1
|
8276 |
+ (match_operand:SI 2 "shift_operand" "r,L")))]
|
yann@1
|
8277 |
+ ""
|
yann@1
|
8278 |
+ "sll%i2\\t%0, %1, %z2"
|
yann@1
|
8279 |
+ [(set_attr "type" "shift")])
|
yann@1
|
8280 |
+
|
yann@1
|
8281 |
+(define_insn "ashrsi3"
|
yann@1
|
8282 |
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
|
yann@1
|
8283 |
+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
|
yann@1
|
8284 |
+ (match_operand:SI 2 "shift_operand" "r,L")))]
|
yann@1
|
8285 |
+ ""
|
yann@1
|
8286 |
+ "sra%i2\\t%0, %1, %z2"
|
yann@1
|
8287 |
+ [(set_attr "type" "shift")])
|
yann@1
|
8288 |
+
|
yann@1
|
8289 |
+(define_insn "lshrsi3"
|
yann@1
|
8290 |
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
|
yann@1
|
8291 |
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
|
yann@1
|
8292 |
+ (match_operand:SI 2 "shift_operand" "r,L")))]
|
yann@1
|
8293 |
+ ""
|
yann@1
|
8294 |
+ "srl%i2\\t%0, %1, %z2"
|
yann@1
|
8295 |
+ [(set_attr "type" "shift")])
|
yann@1
|
8296 |
+
|
yann@1
|
8297 |
+(define_insn "rotlsi3"
|
yann@1
|
8298 |
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
|
yann@1
|
8299 |
+ (rotate:SI (match_operand:SI 1 "register_operand" "r,r")
|
yann@1
|
8300 |
+ (match_operand:SI 2 "shift_operand" "r,L")))]
|
yann@1
|
8301 |
+ ""
|
yann@1
|
8302 |
+ "rol%i2\\t%0, %1, %z2"
|
yann@1
|
8303 |
+ [(set_attr "type" "shift")])
|
yann@1
|
8304 |
+
|
yann@1
|
8305 |
+(define_insn "rotrsi3"
|
yann@1
|
8306 |
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
|
yann@1
|
8307 |
+ (rotatert:SI (match_operand:SI 1 "register_operand" "r,r")
|
yann@1
|
8308 |
+ (match_operand:SI 2 "register_operand" "r,r")))]
|
yann@1
|
8309 |
+ ""
|
yann@1
|
8310 |
+ "ror\\t%0, %1, %2"
|
yann@1
|
8311 |
+ [(set_attr "type" "shift")])
|
yann@1
|
8312 |
+
|
yann@1
|
8313 |
+(define_insn "*shift_mul_constants"
|
yann@1
|
8314 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8315 |
+ (ashift:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
|
yann@1
|
8316 |
+ (match_operand:SI 2 "const_int_operand" "I"))
|
yann@1
|
8317 |
+ (match_operand:SI 3 "const_int_operand" "I")))]
|
yann@1
|
8318 |
+ "TARGET_HAS_MUL && SMALL_INT (INTVAL (operands[2]) << INTVAL (operands[3]))"
|
yann@1
|
8319 |
+{
|
yann@1
|
8320 |
+ HOST_WIDE_INT mul = INTVAL (operands[2]) << INTVAL (operands[3]);
|
yann@1
|
8321 |
+ rtx ops[3];
|
yann@1
|
8322 |
+
|
yann@1
|
8323 |
+ ops[0] = operands[0];
|
yann@1
|
8324 |
+ ops[1] = operands[1];
|
yann@1
|
8325 |
+ ops[2] = GEN_INT (mul);
|
yann@1
|
8326 |
+
|
yann@1
|
8327 |
+ output_asm_insn ("muli\t%0, %1, %2", ops);
|
yann@1
|
8328 |
+ return "";
|
yann@1
|
8329 |
+}
|
yann@1
|
8330 |
+ [(set_attr "type" "mul")])
|
yann@1
|
8331 |
+
|
yann@1
|
8332 |
+
|
yann@1
|
8333 |
+
|
yann@1
|
8334 |
+
|
yann@1
|
8335 |
+;*****************************************************************************
|
yann@1
|
8336 |
+;*
|
yann@1
|
8337 |
+;* Prologue, Epilogue and Return
|
yann@1
|
8338 |
+;*
|
yann@1
|
8339 |
+;*****************************************************************************
|
yann@1
|
8340 |
+
|
yann@1
|
8341 |
+(define_expand "prologue"
|
yann@1
|
8342 |
+ [(const_int 1)]
|
yann@1
|
8343 |
+ ""
|
yann@1
|
8344 |
+{
|
yann@1
|
8345 |
+ expand_prologue ();
|
yann@1
|
8346 |
+ DONE;
|
yann@1
|
8347 |
+})
|
yann@1
|
8348 |
+
|
yann@1
|
8349 |
+(define_expand "epilogue"
|
yann@1
|
8350 |
+ [(return)]
|
yann@1
|
8351 |
+ ""
|
yann@1
|
8352 |
+{
|
yann@1
|
8353 |
+ expand_epilogue (false);
|
yann@1
|
8354 |
+ DONE;
|
yann@1
|
8355 |
+})
|
yann@1
|
8356 |
+
|
yann@1
|
8357 |
+(define_expand "sibcall_epilogue"
|
yann@1
|
8358 |
+ [(return)]
|
yann@1
|
8359 |
+ ""
|
yann@1
|
8360 |
+{
|
yann@1
|
8361 |
+ expand_epilogue (true);
|
yann@1
|
8362 |
+ DONE;
|
yann@1
|
8363 |
+})
|
yann@1
|
8364 |
+
|
yann@1
|
8365 |
+(define_insn "return"
|
yann@1
|
8366 |
+ [(return)]
|
yann@1
|
8367 |
+ "reload_completed && nios2_can_use_return_insn ()"
|
yann@1
|
8368 |
+ "ret\\t"
|
yann@1
|
8369 |
+)
|
yann@1
|
8370 |
+
|
yann@1
|
8371 |
+(define_insn "return_from_epilogue"
|
yann@1
|
8372 |
+ [(use (match_operand 0 "pmode_register_operand" ""))
|
yann@1
|
8373 |
+ (return)]
|
yann@1
|
8374 |
+ "reload_completed"
|
yann@1
|
8375 |
+ "ret\\t"
|
yann@1
|
8376 |
+)
|
yann@1
|
8377 |
+
|
yann@1
|
8378 |
+;; Block any insns from being moved before this point, since the
|
yann@1
|
8379 |
+;; profiling call to mcount can use various registers that aren't
|
yann@1
|
8380 |
+;; saved or used to pass arguments.
|
yann@1
|
8381 |
+
|
yann@1
|
8382 |
+(define_insn "blockage"
|
yann@1
|
8383 |
+ [(unspec_volatile [(const_int 0)] UNSPEC_BLOCKAGE)]
|
yann@1
|
8384 |
+ ""
|
yann@1
|
8385 |
+ ""
|
yann@1
|
8386 |
+ [(set_attr "type" "unknown")
|
yann@1
|
8387 |
+ (set_attr "length" "0")])
|
yann@1
|
8388 |
+
|
yann@1
|
8389 |
+
|
yann@1
|
8390 |
+
|
yann@1
|
8391 |
+;*****************************************************************************
|
yann@1
|
8392 |
+;*
|
yann@1
|
8393 |
+;* Jumps and Calls
|
yann@1
|
8394 |
+;*
|
yann@1
|
8395 |
+;*****************************************************************************
|
yann@1
|
8396 |
+
|
yann@1
|
8397 |
+(define_insn "indirect_jump"
|
yann@1
|
8398 |
+ [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
|
yann@1
|
8399 |
+ ""
|
yann@1
|
8400 |
+ "jmp\\t%0"
|
yann@1
|
8401 |
+ [(set_attr "type" "control")])
|
yann@1
|
8402 |
+
|
yann@1
|
8403 |
+(define_insn "jump"
|
yann@1
|
8404 |
+ [(set (pc)
|
yann@1
|
8405 |
+ (label_ref (match_operand 0 "" "")))]
|
yann@1
|
8406 |
+ ""
|
yann@1
|
8407 |
+ "br\\t%0"
|
yann@1
|
8408 |
+ [(set_attr "type" "control")])
|
yann@1
|
8409 |
+
|
yann@1
|
8410 |
+
|
yann@1
|
8411 |
+(define_insn "indirect_call"
|
yann@1
|
8412 |
+ [(call (mem:QI (match_operand:SI 0 "register_operand" "r"))
|
yann@1
|
8413 |
+ (match_operand 1 "" ""))
|
yann@1
|
8414 |
+ (clobber (reg:SI RA_REGNO))]
|
yann@1
|
8415 |
+ ""
|
yann@1
|
8416 |
+ "callr\\t%0"
|
yann@1
|
8417 |
+ [(set_attr "type" "control")])
|
yann@1
|
8418 |
+
|
yann@1
|
8419 |
+(define_insn "indirect_call_value"
|
yann@1
|
8420 |
+ [(set (match_operand 0 "" "")
|
yann@1
|
8421 |
+ (call (mem:QI (match_operand:SI 1 "register_operand" "r"))
|
yann@1
|
8422 |
+ (match_operand 2 "" "")))
|
yann@1
|
8423 |
+ (clobber (reg:SI RA_REGNO))]
|
yann@1
|
8424 |
+ ""
|
yann@1
|
8425 |
+ "callr\\t%1"
|
yann@1
|
8426 |
+)
|
yann@1
|
8427 |
+
|
yann@1
|
8428 |
+(define_expand "call"
|
yann@1
|
8429 |
+ [(parallel [(call (match_operand 0 "" "")
|
yann@1
|
8430 |
+ (match_operand 1 "" ""))
|
yann@1
|
8431 |
+ (clobber (reg:SI RA_REGNO))])]
|
yann@1
|
8432 |
+ ""
|
yann@1
|
8433 |
+ "")
|
yann@1
|
8434 |
+
|
yann@1
|
8435 |
+(define_expand "call_value"
|
yann@1
|
8436 |
+ [(parallel [(set (match_operand 0 "" "")
|
yann@1
|
8437 |
+ (call (match_operand 1 "" "")
|
yann@1
|
8438 |
+ (match_operand 2 "" "")))
|
yann@1
|
8439 |
+ (clobber (reg:SI RA_REGNO))])]
|
yann@1
|
8440 |
+ ""
|
yann@1
|
8441 |
+ "")
|
yann@1
|
8442 |
+
|
yann@1
|
8443 |
+(define_insn "*call"
|
yann@1
|
8444 |
+ [(call (mem:QI (match_operand:SI 0 "immediate_operand" "i"))
|
yann@1
|
8445 |
+ (match_operand 1 "" ""))
|
yann@1
|
8446 |
+ (clobber (match_operand:SI 2 "register_operand" "=r"))]
|
yann@1
|
8447 |
+ ""
|
yann@1
|
8448 |
+ "call\\t%0"
|
yann@1
|
8449 |
+ [(set_attr "type" "control")])
|
yann@1
|
8450 |
+
|
yann@1
|
8451 |
+(define_insn "*call_value"
|
yann@1
|
8452 |
+ [(set (match_operand 0 "" "")
|
yann@1
|
8453 |
+ (call (mem:QI (match_operand:SI 1 "immediate_operand" "i"))
|
yann@1
|
8454 |
+ (match_operand 2 "" "")))
|
yann@1
|
8455 |
+ (clobber (match_operand:SI 3 "register_operand" "=r"))]
|
yann@1
|
8456 |
+ ""
|
yann@1
|
8457 |
+ "call\\t%1"
|
yann@1
|
8458 |
+ [(set_attr "type" "control")])
|
yann@1
|
8459 |
+
|
yann@1
|
8460 |
+(define_expand "sibcall"
|
yann@1
|
8461 |
+ [(parallel [(call (match_operand 0 "" "")
|
yann@1
|
8462 |
+ (match_operand 1 "" ""))
|
yann@1
|
8463 |
+ (return)
|
yann@1
|
8464 |
+ (use (match_operand 2 "" ""))])]
|
yann@1
|
8465 |
+ ""
|
yann@1
|
8466 |
+ {
|
yann@1
|
8467 |
+ XEXP (operands[0], 0) = copy_to_mode_reg (SImode, XEXP (operands[0], 0));
|
yann@1
|
8468 |
+
|
yann@1
|
8469 |
+ if (operands[2] == NULL_RTX)
|
yann@1
|
8470 |
+ operands[2] = const0_rtx;
|
yann@1
|
8471 |
+ }
|
yann@1
|
8472 |
+)
|
yann@1
|
8473 |
+
|
yann@1
|
8474 |
+(define_expand "sibcall_value"
|
yann@1
|
8475 |
+ [(parallel [(set (match_operand 0 "" "")
|
yann@1
|
8476 |
+ (call (match_operand 1 "" "")
|
yann@1
|
8477 |
+ (match_operand 2 "" "")))
|
yann@1
|
8478 |
+ (return)
|
yann@1
|
8479 |
+ (use (match_operand 3 "" ""))])]
|
yann@1
|
8480 |
+ ""
|
yann@1
|
8481 |
+ {
|
yann@1
|
8482 |
+ XEXP (operands[1], 0) = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
|
yann@1
|
8483 |
+
|
yann@1
|
8484 |
+ if (operands[3] == NULL_RTX)
|
yann@1
|
8485 |
+ operands[3] = const0_rtx;
|
yann@1
|
8486 |
+ }
|
yann@1
|
8487 |
+)
|
yann@1
|
8488 |
+
|
yann@1
|
8489 |
+(define_insn "sibcall_insn"
|
yann@1
|
8490 |
+ [(call (mem:QI (match_operand:SI 0 "register_operand" "r"))
|
yann@1
|
8491 |
+ (match_operand 1 "" ""))
|
yann@1
|
8492 |
+ (return)
|
yann@1
|
8493 |
+ (use (match_operand 2 "" ""))]
|
yann@1
|
8494 |
+ ""
|
yann@1
|
8495 |
+ "jmp\\t%0"
|
yann@1
|
8496 |
+)
|
yann@1
|
8497 |
+
|
yann@1
|
8498 |
+(define_insn "sibcall_value_insn"
|
yann@1
|
8499 |
+ [(set (match_operand 0 "register_operand" "")
|
yann@1
|
8500 |
+ (call (mem:QI (match_operand:SI 1 "register_operand" "r"))
|
yann@1
|
8501 |
+ (match_operand 2 "" "")))
|
yann@1
|
8502 |
+ (return)
|
yann@1
|
8503 |
+ (use (match_operand 3 "" ""))]
|
yann@1
|
8504 |
+ ""
|
yann@1
|
8505 |
+ "jmp\\t%1"
|
yann@1
|
8506 |
+)
|
yann@1
|
8507 |
+
|
yann@1
|
8508 |
+
|
yann@1
|
8509 |
+
|
yann@1
|
8510 |
+
|
yann@1
|
8511 |
+(define_expand "tablejump"
|
yann@1
|
8512 |
+ [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
|
yann@1
|
8513 |
+ (use (label_ref (match_operand 1 "" "")))])]
|
yann@1
|
8514 |
+ ""
|
yann@1
|
8515 |
+ ""
|
yann@1
|
8516 |
+)
|
yann@1
|
8517 |
+
|
yann@1
|
8518 |
+(define_insn "*tablejump"
|
yann@1
|
8519 |
+ [(set (pc)
|
yann@1
|
8520 |
+ (match_operand:SI 0 "register_operand" "r"))
|
yann@1
|
8521 |
+ (use (label_ref (match_operand 1 "" "")))]
|
yann@1
|
8522 |
+ ""
|
yann@1
|
8523 |
+ "jmp\\t%0"
|
yann@1
|
8524 |
+ [(set_attr "type" "control")])
|
yann@1
|
8525 |
+
|
yann@1
|
8526 |
+
|
yann@1
|
8527 |
+
|
yann@1
|
8528 |
+;*****************************************************************************
|
yann@1
|
8529 |
+;*
|
yann@1
|
8530 |
+;* Comparisons
|
yann@1
|
8531 |
+;*
|
yann@1
|
8532 |
+;*****************************************************************************
|
yann@1
|
8533 |
+;; Flow here is rather complex (based on MIPS):
|
yann@1
|
8534 |
+;;
|
yann@1
|
8535 |
+;; 1) The cmp{si,di,sf,df} routine is called. It deposits the
|
yann@1
|
8536 |
+;; arguments into the branch_cmp array, and the type into
|
yann@1
|
8537 |
+;; branch_type. No RTL is generated.
|
yann@1
|
8538 |
+;;
|
yann@1
|
8539 |
+;; 2) The appropriate branch define_expand is called, which then
|
yann@1
|
8540 |
+;; creates the appropriate RTL for the comparison and branch.
|
yann@1
|
8541 |
+;; Different CC modes are used, based on what type of branch is
|
yann@1
|
8542 |
+;; done, so that we can constrain things appropriately. There
|
yann@1
|
8543 |
+;; are assumptions in the rest of GCC that break if we fold the
|
yann@1
|
8544 |
+;; operands into the branchs for integer operations, and use cc0
|
yann@1
|
8545 |
+;; for floating point, so we use the fp status register instead.
|
yann@1
|
8546 |
+;; If needed, an appropriate temporary is created to hold the
|
yann@1
|
8547 |
+;; of the integer compare.
|
yann@1
|
8548 |
+
|
yann@1
|
8549 |
+(define_expand "cmpsi"
|
yann@1
|
8550 |
+ [(set (cc0)
|
yann@1
|
8551 |
+ (compare:CC (match_operand:SI 0 "register_operand" "")
|
yann@1
|
8552 |
+ (match_operand:SI 1 "arith_operand" "")))]
|
yann@1
|
8553 |
+ ""
|
yann@1
|
8554 |
+{
|
yann@1
|
8555 |
+ branch_cmp[0] = operands[0];
|
yann@1
|
8556 |
+ branch_cmp[1] = operands[1];
|
yann@1
|
8557 |
+ branch_type = CMP_SI;
|
yann@1
|
8558 |
+ DONE;
|
yann@1
|
8559 |
+})
|
yann@1
|
8560 |
+
|
yann@1
|
8561 |
+(define_expand "tstsi"
|
yann@1
|
8562 |
+ [(set (cc0)
|
yann@1
|
8563 |
+ (match_operand:SI 0 "register_operand" ""))]
|
yann@1
|
8564 |
+ ""
|
yann@1
|
8565 |
+{
|
yann@1
|
8566 |
+ branch_cmp[0] = operands[0];
|
yann@1
|
8567 |
+ branch_cmp[1] = const0_rtx;
|
yann@1
|
8568 |
+ branch_type = CMP_SI;
|
yann@1
|
8569 |
+ DONE;
|
yann@1
|
8570 |
+})
|
yann@1
|
8571 |
+
|
yann@1
|
8572 |
+
|
yann@1
|
8573 |
+;*****************************************************************************
|
yann@1
|
8574 |
+;*
|
yann@1
|
8575 |
+;* setting a register from a comparison
|
yann@1
|
8576 |
+;*
|
yann@1
|
8577 |
+;*****************************************************************************
|
yann@1
|
8578 |
+
|
yann@1
|
8579 |
+(define_expand "seq"
|
yann@1
|
8580 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8581 |
+ (eq:SI (match_dup 1)
|
yann@1
|
8582 |
+ (match_dup 2)))]
|
yann@1
|
8583 |
+ ""
|
yann@1
|
8584 |
+{
|
yann@1
|
8585 |
+ if (branch_type != CMP_SI)
|
yann@1
|
8586 |
+ FAIL;
|
yann@1
|
8587 |
+
|
yann@1
|
8588 |
+ /* set up operands from compare. */
|
yann@1
|
8589 |
+ operands[1] = branch_cmp[0];
|
yann@1
|
8590 |
+ operands[2] = branch_cmp[1];
|
yann@1
|
8591 |
+
|
yann@1
|
8592 |
+ gen_int_relational (EQ, operands[0], operands[1], operands[2], NULL_RTX);
|
yann@1
|
8593 |
+ DONE;
|
yann@1
|
8594 |
+})
|
yann@1
|
8595 |
+
|
yann@1
|
8596 |
+
|
yann@1
|
8597 |
+(define_insn "*seq"
|
yann@1
|
8598 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8599 |
+ (eq:SI (match_operand:SI 1 "reg_or_0_operand" "%rM")
|
yann@1
|
8600 |
+ (match_operand:SI 2 "arith_operand" "rI")))]
|
yann@1
|
8601 |
+ ""
|
yann@1
|
8602 |
+ "cmpeq%i2\\t%0, %z1, %z2"
|
yann@1
|
8603 |
+ [(set_attr "type" "alu")])
|
yann@1
|
8604 |
+
|
yann@1
|
8605 |
+
|
yann@1
|
8606 |
+(define_expand "sne"
|
yann@1
|
8607 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8608 |
+ (ne:SI (match_dup 1)
|
yann@1
|
8609 |
+ (match_dup 2)))]
|
yann@1
|
8610 |
+ ""
|
yann@1
|
8611 |
+{
|
yann@1
|
8612 |
+ if (branch_type != CMP_SI)
|
yann@1
|
8613 |
+ FAIL;
|
yann@1
|
8614 |
+
|
yann@1
|
8615 |
+ /* set up operands from compare. */
|
yann@1
|
8616 |
+ operands[1] = branch_cmp[0];
|
yann@1
|
8617 |
+ operands[2] = branch_cmp[1];
|
yann@1
|
8618 |
+
|
yann@1
|
8619 |
+ gen_int_relational (NE, operands[0], operands[1], operands[2], NULL_RTX);
|
yann@1
|
8620 |
+ DONE;
|
yann@1
|
8621 |
+})
|
yann@1
|
8622 |
+
|
yann@1
|
8623 |
+
|
yann@1
|
8624 |
+(define_insn "*sne"
|
yann@1
|
8625 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8626 |
+ (ne:SI (match_operand:SI 1 "reg_or_0_operand" "%rM")
|
yann@1
|
8627 |
+ (match_operand:SI 2 "arith_operand" "rI")))]
|
yann@1
|
8628 |
+ ""
|
yann@1
|
8629 |
+ "cmpne%i2\\t%0, %z1, %z2"
|
yann@1
|
8630 |
+ [(set_attr "type" "alu")])
|
yann@1
|
8631 |
+
|
yann@1
|
8632 |
+
|
yann@1
|
8633 |
+(define_expand "sgt"
|
yann@1
|
8634 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8635 |
+ (gt:SI (match_dup 1)
|
yann@1
|
8636 |
+ (match_dup 2)))]
|
yann@1
|
8637 |
+ ""
|
yann@1
|
8638 |
+{
|
yann@1
|
8639 |
+ if (branch_type != CMP_SI)
|
yann@1
|
8640 |
+ FAIL;
|
yann@1
|
8641 |
+
|
yann@1
|
8642 |
+ /* set up operands from compare. */
|
yann@1
|
8643 |
+ operands[1] = branch_cmp[0];
|
yann@1
|
8644 |
+ operands[2] = branch_cmp[1];
|
yann@1
|
8645 |
+
|
yann@1
|
8646 |
+ gen_int_relational (GT, operands[0], operands[1], operands[2], NULL_RTX);
|
yann@1
|
8647 |
+ DONE;
|
yann@1
|
8648 |
+})
|
yann@1
|
8649 |
+
|
yann@1
|
8650 |
+
|
yann@1
|
8651 |
+(define_insn "*sgt"
|
yann@1
|
8652 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8653 |
+ (gt:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
|
yann@1
|
8654 |
+ (match_operand:SI 2 "reg_or_0_operand" "rM")))]
|
yann@1
|
8655 |
+ ""
|
yann@1
|
8656 |
+ "cmplt\\t%0, %z2, %z1"
|
yann@1
|
8657 |
+ [(set_attr "type" "alu")])
|
yann@1
|
8658 |
+
|
yann@1
|
8659 |
+
|
yann@1
|
8660 |
+(define_expand "sge"
|
yann@1
|
8661 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8662 |
+ (ge:SI (match_dup 1)
|
yann@1
|
8663 |
+ (match_dup 2)))]
|
yann@1
|
8664 |
+ ""
|
yann@1
|
8665 |
+{
|
yann@1
|
8666 |
+ if (branch_type != CMP_SI)
|
yann@1
|
8667 |
+ FAIL;
|
yann@1
|
8668 |
+
|
yann@1
|
8669 |
+ /* set up operands from compare. */
|
yann@1
|
8670 |
+ operands[1] = branch_cmp[0];
|
yann@1
|
8671 |
+ operands[2] = branch_cmp[1];
|
yann@1
|
8672 |
+
|
yann@1
|
8673 |
+ gen_int_relational (GE, operands[0], operands[1], operands[2], NULL_RTX);
|
yann@1
|
8674 |
+ DONE;
|
yann@1
|
8675 |
+})
|
yann@1
|
8676 |
+
|
yann@1
|
8677 |
+
|
yann@1
|
8678 |
+(define_insn "*sge"
|
yann@1
|
8679 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8680 |
+ (ge:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
|
yann@1
|
8681 |
+ (match_operand:SI 2 "arith_operand" "rI")))]
|
yann@1
|
8682 |
+ ""
|
yann@1
|
8683 |
+ "cmpge%i2\\t%0, %z1, %z2"
|
yann@1
|
8684 |
+ [(set_attr "type" "alu")])
|
yann@1
|
8685 |
+
|
yann@1
|
8686 |
+(define_expand "sle"
|
yann@1
|
8687 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8688 |
+ (le:SI (match_dup 1)
|
yann@1
|
8689 |
+ (match_dup 2)))]
|
yann@1
|
8690 |
+ ""
|
yann@1
|
8691 |
+{
|
yann@1
|
8692 |
+ if (branch_type != CMP_SI)
|
yann@1
|
8693 |
+ FAIL;
|
yann@1
|
8694 |
+
|
yann@1
|
8695 |
+ /* set up operands from compare. */
|
yann@1
|
8696 |
+ operands[1] = branch_cmp[0];
|
yann@1
|
8697 |
+ operands[2] = branch_cmp[1];
|
yann@1
|
8698 |
+
|
yann@1
|
8699 |
+ gen_int_relational (LE, operands[0], operands[1], operands[2], NULL_RTX);
|
yann@1
|
8700 |
+ DONE;
|
yann@1
|
8701 |
+})
|
yann@1
|
8702 |
+
|
yann@1
|
8703 |
+
|
yann@1
|
8704 |
+(define_insn "*sle"
|
yann@1
|
8705 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8706 |
+ (le:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
|
yann@1
|
8707 |
+ (match_operand:SI 2 "reg_or_0_operand" "rM")))]
|
yann@1
|
8708 |
+ ""
|
yann@1
|
8709 |
+ "cmpge\\t%0, %z2, %z1"
|
yann@1
|
8710 |
+ [(set_attr "type" "alu")])
|
yann@1
|
8711 |
+
|
yann@1
|
8712 |
+
|
yann@1
|
8713 |
+(define_expand "slt"
|
yann@1
|
8714 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8715 |
+ (lt:SI (match_dup 1)
|
yann@1
|
8716 |
+ (match_dup 2)))]
|
yann@1
|
8717 |
+ ""
|
yann@1
|
8718 |
+{
|
yann@1
|
8719 |
+ if (branch_type != CMP_SI)
|
yann@1
|
8720 |
+ FAIL;
|
yann@1
|
8721 |
+
|
yann@1
|
8722 |
+ /* set up operands from compare. */
|
yann@1
|
8723 |
+ operands[1] = branch_cmp[0];
|
yann@1
|
8724 |
+ operands[2] = branch_cmp[1];
|
yann@1
|
8725 |
+
|
yann@1
|
8726 |
+ gen_int_relational (LT, operands[0], operands[1], operands[2], NULL_RTX);
|
yann@1
|
8727 |
+ DONE;
|
yann@1
|
8728 |
+})
|
yann@1
|
8729 |
+
|
yann@1
|
8730 |
+
|
yann@1
|
8731 |
+(define_insn "*slt"
|
yann@1
|
8732 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8733 |
+ (lt:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
|
yann@1
|
8734 |
+ (match_operand:SI 2 "arith_operand" "rI")))]
|
yann@1
|
8735 |
+ ""
|
yann@1
|
8736 |
+ "cmplt%i2\\t%0, %z1, %z2"
|
yann@1
|
8737 |
+ [(set_attr "type" "alu")])
|
yann@1
|
8738 |
+
|
yann@1
|
8739 |
+
|
yann@1
|
8740 |
+(define_expand "sgtu"
|
yann@1
|
8741 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8742 |
+ (gtu:SI (match_dup 1)
|
yann@1
|
8743 |
+ (match_dup 2)))]
|
yann@1
|
8744 |
+ ""
|
yann@1
|
8745 |
+{
|
yann@1
|
8746 |
+ if (branch_type != CMP_SI)
|
yann@1
|
8747 |
+ FAIL;
|
yann@1
|
8748 |
+
|
yann@1
|
8749 |
+ /* set up operands from compare. */
|
yann@1
|
8750 |
+ operands[1] = branch_cmp[0];
|
yann@1
|
8751 |
+ operands[2] = branch_cmp[1];
|
yann@1
|
8752 |
+
|
yann@1
|
8753 |
+ gen_int_relational (GTU, operands[0], operands[1], operands[2], NULL_RTX);
|
yann@1
|
8754 |
+ DONE;
|
yann@1
|
8755 |
+})
|
yann@1
|
8756 |
+
|
yann@1
|
8757 |
+
|
yann@1
|
8758 |
+(define_insn "*sgtu"
|
yann@1
|
8759 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8760 |
+ (gtu:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
|
yann@1
|
8761 |
+ (match_operand:SI 2 "reg_or_0_operand" "rM")))]
|
yann@1
|
8762 |
+ ""
|
yann@1
|
8763 |
+ "cmpltu\\t%0, %z2, %z1"
|
yann@1
|
8764 |
+ [(set_attr "type" "alu")])
|
yann@1
|
8765 |
+
|
yann@1
|
8766 |
+
|
yann@1
|
8767 |
+(define_expand "sgeu"
|
yann@1
|
8768 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8769 |
+ (geu:SI (match_dup 1)
|
yann@1
|
8770 |
+ (match_dup 2)))]
|
yann@1
|
8771 |
+ ""
|
yann@1
|
8772 |
+{
|
yann@1
|
8773 |
+ if (branch_type != CMP_SI)
|
yann@1
|
8774 |
+ FAIL;
|
yann@1
|
8775 |
+
|
yann@1
|
8776 |
+ /* set up operands from compare. */
|
yann@1
|
8777 |
+ operands[1] = branch_cmp[0];
|
yann@1
|
8778 |
+ operands[2] = branch_cmp[1];
|
yann@1
|
8779 |
+
|
yann@1
|
8780 |
+ gen_int_relational (GEU, operands[0], operands[1], operands[2], NULL_RTX);
|
yann@1
|
8781 |
+ DONE;
|
yann@1
|
8782 |
+})
|
yann@1
|
8783 |
+
|
yann@1
|
8784 |
+
|
yann@1
|
8785 |
+(define_insn "*sgeu"
|
yann@1
|
8786 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8787 |
+ (geu:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
|
yann@1
|
8788 |
+ (match_operand:SI 2 "uns_arith_operand" "rJ")))]
|
yann@1
|
8789 |
+ ""
|
yann@1
|
8790 |
+ "cmpgeu%i2\\t%0, %z1, %z2"
|
yann@1
|
8791 |
+ [(set_attr "type" "alu")])
|
yann@1
|
8792 |
+
|
yann@1
|
8793 |
+(define_expand "sleu"
|
yann@1
|
8794 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8795 |
+ (leu:SI (match_dup 1)
|
yann@1
|
8796 |
+ (match_dup 2)))]
|
yann@1
|
8797 |
+ ""
|
yann@1
|
8798 |
+{
|
yann@1
|
8799 |
+ if (branch_type != CMP_SI)
|
yann@1
|
8800 |
+ FAIL;
|
yann@1
|
8801 |
+
|
yann@1
|
8802 |
+ /* set up operands from compare. */
|
yann@1
|
8803 |
+ operands[1] = branch_cmp[0];
|
yann@1
|
8804 |
+ operands[2] = branch_cmp[1];
|
yann@1
|
8805 |
+
|
yann@1
|
8806 |
+ gen_int_relational (LEU, operands[0], operands[1], operands[2], NULL_RTX);
|
yann@1
|
8807 |
+ DONE;
|
yann@1
|
8808 |
+})
|
yann@1
|
8809 |
+
|
yann@1
|
8810 |
+
|
yann@1
|
8811 |
+(define_insn "*sleu"
|
yann@1
|
8812 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8813 |
+ (leu:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
|
yann@1
|
8814 |
+ (match_operand:SI 2 "reg_or_0_operand" "rM")))]
|
yann@1
|
8815 |
+ ""
|
yann@1
|
8816 |
+ "cmpgeu\\t%0, %z2, %z1"
|
yann@1
|
8817 |
+ [(set_attr "type" "alu")])
|
yann@1
|
8818 |
+
|
yann@1
|
8819 |
+
|
yann@1
|
8820 |
+(define_expand "sltu"
|
yann@1
|
8821 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8822 |
+ (ltu:SI (match_dup 1)
|
yann@1
|
8823 |
+ (match_dup 2)))]
|
yann@1
|
8824 |
+ ""
|
yann@1
|
8825 |
+{
|
yann@1
|
8826 |
+ if (branch_type != CMP_SI)
|
yann@1
|
8827 |
+ FAIL;
|
yann@1
|
8828 |
+
|
yann@1
|
8829 |
+ /* set up operands from compare. */
|
yann@1
|
8830 |
+ operands[1] = branch_cmp[0];
|
yann@1
|
8831 |
+ operands[2] = branch_cmp[1];
|
yann@1
|
8832 |
+
|
yann@1
|
8833 |
+ gen_int_relational (LTU, operands[0], operands[1], operands[2], NULL_RTX);
|
yann@1
|
8834 |
+ DONE;
|
yann@1
|
8835 |
+})
|
yann@1
|
8836 |
+
|
yann@1
|
8837 |
+
|
yann@1
|
8838 |
+(define_insn "*sltu"
|
yann@1
|
8839 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
8840 |
+ (ltu:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
|
yann@1
|
8841 |
+ (match_operand:SI 2 "uns_arith_operand" "rJ")))]
|
yann@1
|
8842 |
+ ""
|
yann@1
|
8843 |
+ "cmpltu%i2\\t%0, %z1, %z2"
|
yann@1
|
8844 |
+ [(set_attr "type" "alu")])
|
yann@1
|
8845 |
+
|
yann@1
|
8846 |
+
|
yann@1
|
8847 |
+
|
yann@1
|
8848 |
+
|
yann@1
|
8849 |
+;*****************************************************************************
|
yann@1
|
8850 |
+;*
|
yann@1
|
8851 |
+;* branches
|
yann@1
|
8852 |
+;*
|
yann@1
|
8853 |
+;*****************************************************************************
|
yann@1
|
8854 |
+
|
yann@1
|
8855 |
+(define_insn "*cbranch"
|
yann@1
|
8856 |
+ [(set (pc)
|
yann@1
|
8857 |
+ (if_then_else
|
yann@1
|
8858 |
+ (match_operator:SI 0 "comparison_operator"
|
yann@1
|
8859 |
+ [(match_operand:SI 2 "reg_or_0_operand" "rM")
|
yann@1
|
8860 |
+ (match_operand:SI 3 "reg_or_0_operand" "rM")])
|
yann@1
|
8861 |
+ (label_ref (match_operand 1 "" ""))
|
yann@1
|
8862 |
+ (pc)))]
|
yann@1
|
8863 |
+ ""
|
yann@1
|
8864 |
+ "b%0\\t%z2, %z3, %l1"
|
yann@1
|
8865 |
+ [(set_attr "type" "control")])
|
yann@1
|
8866 |
+
|
yann@1
|
8867 |
+
|
yann@1
|
8868 |
+(define_expand "beq"
|
yann@1
|
8869 |
+ [(set (pc)
|
yann@1
|
8870 |
+ (if_then_else (eq:CC (cc0)
|
yann@1
|
8871 |
+ (const_int 0))
|
yann@1
|
8872 |
+ (label_ref (match_operand 0 "" ""))
|
yann@1
|
8873 |
+ (pc)))]
|
yann@1
|
8874 |
+ ""
|
yann@1
|
8875 |
+{
|
yann@1
|
8876 |
+ gen_int_relational (EQ, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
|
yann@1
|
8877 |
+ DONE;
|
yann@1
|
8878 |
+})
|
yann@1
|
8879 |
+
|
yann@1
|
8880 |
+
|
yann@1
|
8881 |
+(define_expand "bne"
|
yann@1
|
8882 |
+ [(set (pc)
|
yann@1
|
8883 |
+ (if_then_else (ne:CC (cc0)
|
yann@1
|
8884 |
+ (const_int 0))
|
yann@1
|
8885 |
+ (label_ref (match_operand 0 "" ""))
|
yann@1
|
8886 |
+ (pc)))]
|
yann@1
|
8887 |
+ ""
|
yann@1
|
8888 |
+{
|
yann@1
|
8889 |
+ gen_int_relational (NE, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
|
yann@1
|
8890 |
+ DONE;
|
yann@1
|
8891 |
+})
|
yann@1
|
8892 |
+
|
yann@1
|
8893 |
+
|
yann@1
|
8894 |
+(define_expand "bgt"
|
yann@1
|
8895 |
+ [(set (pc)
|
yann@1
|
8896 |
+ (if_then_else (gt:CC (cc0)
|
yann@1
|
8897 |
+ (const_int 0))
|
yann@1
|
8898 |
+ (label_ref (match_operand 0 "" ""))
|
yann@1
|
8899 |
+ (pc)))]
|
yann@1
|
8900 |
+ ""
|
yann@1
|
8901 |
+{
|
yann@1
|
8902 |
+ gen_int_relational (GT, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
|
yann@1
|
8903 |
+ DONE;
|
yann@1
|
8904 |
+})
|
yann@1
|
8905 |
+
|
yann@1
|
8906 |
+(define_expand "bge"
|
yann@1
|
8907 |
+ [(set (pc)
|
yann@1
|
8908 |
+ (if_then_else (ge:CC (cc0)
|
yann@1
|
8909 |
+ (const_int 0))
|
yann@1
|
8910 |
+ (label_ref (match_operand 0 "" ""))
|
yann@1
|
8911 |
+ (pc)))]
|
yann@1
|
8912 |
+ ""
|
yann@1
|
8913 |
+{
|
yann@1
|
8914 |
+ gen_int_relational (GE, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
|
yann@1
|
8915 |
+ DONE;
|
yann@1
|
8916 |
+})
|
yann@1
|
8917 |
+
|
yann@1
|
8918 |
+(define_expand "ble"
|
yann@1
|
8919 |
+ [(set (pc)
|
yann@1
|
8920 |
+ (if_then_else (le:CC (cc0)
|
yann@1
|
8921 |
+ (const_int 0))
|
yann@1
|
8922 |
+ (label_ref (match_operand 0 "" ""))
|
yann@1
|
8923 |
+ (pc)))]
|
yann@1
|
8924 |
+ ""
|
yann@1
|
8925 |
+{
|
yann@1
|
8926 |
+ gen_int_relational (LE, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
|
yann@1
|
8927 |
+ DONE;
|
yann@1
|
8928 |
+})
|
yann@1
|
8929 |
+
|
yann@1
|
8930 |
+(define_expand "blt"
|
yann@1
|
8931 |
+ [(set (pc)
|
yann@1
|
8932 |
+ (if_then_else (lt:CC (cc0)
|
yann@1
|
8933 |
+ (const_int 0))
|
yann@1
|
8934 |
+ (label_ref (match_operand 0 "" ""))
|
yann@1
|
8935 |
+ (pc)))]
|
yann@1
|
8936 |
+ ""
|
yann@1
|
8937 |
+{
|
yann@1
|
8938 |
+ gen_int_relational (LT, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
|
yann@1
|
8939 |
+ DONE;
|
yann@1
|
8940 |
+})
|
yann@1
|
8941 |
+
|
yann@1
|
8942 |
+
|
yann@1
|
8943 |
+(define_expand "bgtu"
|
yann@1
|
8944 |
+ [(set (pc)
|
yann@1
|
8945 |
+ (if_then_else (gtu:CC (cc0)
|
yann@1
|
8946 |
+ (const_int 0))
|
yann@1
|
8947 |
+ (label_ref (match_operand 0 "" ""))
|
yann@1
|
8948 |
+ (pc)))]
|
yann@1
|
8949 |
+ ""
|
yann@1
|
8950 |
+{
|
yann@1
|
8951 |
+ gen_int_relational (GTU, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
|
yann@1
|
8952 |
+ DONE;
|
yann@1
|
8953 |
+})
|
yann@1
|
8954 |
+
|
yann@1
|
8955 |
+(define_expand "bgeu"
|
yann@1
|
8956 |
+ [(set (pc)
|
yann@1
|
8957 |
+ (if_then_else (geu:CC (cc0)
|
yann@1
|
8958 |
+ (const_int 0))
|
yann@1
|
8959 |
+ (label_ref (match_operand 0 "" ""))
|
yann@1
|
8960 |
+ (pc)))]
|
yann@1
|
8961 |
+ ""
|
yann@1
|
8962 |
+{
|
yann@1
|
8963 |
+ gen_int_relational (GEU, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
|
yann@1
|
8964 |
+ DONE;
|
yann@1
|
8965 |
+})
|
yann@1
|
8966 |
+
|
yann@1
|
8967 |
+(define_expand "bleu"
|
yann@1
|
8968 |
+ [(set (pc)
|
yann@1
|
8969 |
+ (if_then_else (leu:CC (cc0)
|
yann@1
|
8970 |
+ (const_int 0))
|
yann@1
|
8971 |
+ (label_ref (match_operand 0 "" ""))
|
yann@1
|
8972 |
+ (pc)))]
|
yann@1
|
8973 |
+ ""
|
yann@1
|
8974 |
+{
|
yann@1
|
8975 |
+ gen_int_relational (LEU, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
|
yann@1
|
8976 |
+ DONE;
|
yann@1
|
8977 |
+})
|
yann@1
|
8978 |
+
|
yann@1
|
8979 |
+(define_expand "bltu"
|
yann@1
|
8980 |
+ [(set (pc)
|
yann@1
|
8981 |
+ (if_then_else (ltu:CC (cc0)
|
yann@1
|
8982 |
+ (const_int 0))
|
yann@1
|
8983 |
+ (label_ref (match_operand 0 "" ""))
|
yann@1
|
8984 |
+ (pc)))]
|
yann@1
|
8985 |
+ ""
|
yann@1
|
8986 |
+{
|
yann@1
|
8987 |
+ gen_int_relational (LTU, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
|
yann@1
|
8988 |
+ DONE;
|
yann@1
|
8989 |
+})
|
yann@1
|
8990 |
+
|
yann@1
|
8991 |
+
|
yann@1
|
8992 |
+;*****************************************************************************
|
yann@1
|
8993 |
+;*
|
yann@1
|
8994 |
+;* String and Block Operations
|
yann@1
|
8995 |
+;*
|
yann@1
|
8996 |
+;*****************************************************************************
|
yann@1
|
8997 |
+
|
yann@1
|
8998 |
+; ??? This is all really a hack to get Dhrystone to work as fast as possible
|
yann@1
|
8999 |
+; things to be fixed:
|
yann@1
|
9000 |
+; * let the compiler core handle all of this, for that to work the extra
|
yann@1
|
9001 |
+; aliasing needs to be addressed.
|
yann@1
|
9002 |
+; * we use three temporary registers for loading and storing to ensure no
|
yann@1
|
9003 |
+; ld use stalls, this is excessive, because after the first ld/st only
|
yann@1
|
9004 |
+; two are needed. Only two would be needed all the way through if
|
yann@1
|
9005 |
+; we could schedule with other code. Consider:
|
yann@1
|
9006 |
+; 1 ld $1, 0($src)
|
yann@1
|
9007 |
+; 2 ld $2, 4($src)
|
yann@1
|
9008 |
+; 3 ld $3, 8($src)
|
yann@1
|
9009 |
+; 4 st $1, 0($dest)
|
yann@1
|
9010 |
+; 5 ld $1, 12($src)
|
yann@1
|
9011 |
+; 6 st $2, 4($src)
|
yann@1
|
9012 |
+; 7 etc.
|
yann@1
|
9013 |
+; The first store has to wait until 4. If it does not there will be one
|
yann@1
|
9014 |
+; cycle of stalling. However, if any other instruction could be placed
|
yann@1
|
9015 |
+; between 1 and 4, $3 would not be needed.
|
yann@1
|
9016 |
+; * In small we probably don't want to ever do this ourself because there
|
yann@1
|
9017 |
+; is no ld use stall.
|
yann@1
|
9018 |
+
|
yann@1
|
9019 |
+(define_expand "movstrsi"
|
yann@1
|
9020 |
+ [(parallel [(set (match_operand:BLK 0 "general_operand" "")
|
yann@1
|
9021 |
+ (match_operand:BLK 1 "general_operand" ""))
|
yann@1
|
9022 |
+ (use (match_operand:SI 2 "const_int_operand" ""))
|
yann@1
|
9023 |
+ (use (match_operand:SI 3 "const_int_operand" ""))
|
yann@1
|
9024 |
+ (clobber (match_scratch:SI 4 "=&r"))
|
yann@1
|
9025 |
+ (clobber (match_scratch:SI 5 "=&r"))
|
yann@1
|
9026 |
+ (clobber (match_scratch:SI 6 "=&r"))])]
|
yann@1
|
9027 |
+ "TARGET_INLINE_MEMCPY"
|
yann@1
|
9028 |
+{
|
yann@1
|
9029 |
+ rtx ld_addr_reg, st_addr_reg;
|
yann@1
|
9030 |
+
|
yann@1
|
9031 |
+ /* If the predicate for op2 fails in expr.c:emit_block_move_via_movstr
|
yann@1
|
9032 |
+ it trys to copy to a register, but does not re-try the predicate.
|
yann@1
|
9033 |
+ ??? Intead of fixing expr.c, I fix it here. */
|
yann@1
|
9034 |
+ if (!const_int_operand (operands[2], SImode))
|
yann@1
|
9035 |
+ FAIL;
|
yann@1
|
9036 |
+
|
yann@1
|
9037 |
+ /* ??? there are some magic numbers which need to be sorted out here.
|
yann@1
|
9038 |
+ the basis for them is not increasing code size hugely or going
|
yann@1
|
9039 |
+ out of range of offset addressing */
|
yann@1
|
9040 |
+ if (INTVAL (operands[3]) < 4)
|
yann@1
|
9041 |
+ FAIL;
|
yann@1
|
9042 |
+ if (!optimize
|
yann@1
|
9043 |
+ || (optimize_size && INTVAL (operands[2]) > 12)
|
yann@1
|
9044 |
+ || (optimize < 3 && INTVAL (operands[2]) > 100)
|
yann@1
|
9045 |
+ || INTVAL (operands[2]) > 200)
|
yann@1
|
9046 |
+ FAIL;
|
yann@1
|
9047 |
+
|
yann@1
|
9048 |
+ st_addr_reg
|
yann@1
|
9049 |
+ = replace_equiv_address (operands[0],
|
yann@1
|
9050 |
+ copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
|
yann@1
|
9051 |
+ ld_addr_reg
|
yann@1
|
9052 |
+ = replace_equiv_address (operands[1],
|
yann@1
|
9053 |
+ copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
|
yann@1
|
9054 |
+ emit_insn (gen_movstrsi_internal (st_addr_reg, ld_addr_reg,
|
yann@1
|
9055 |
+ operands[2], operands[3]));
|
yann@1
|
9056 |
+
|
yann@1
|
9057 |
+ DONE;
|
yann@1
|
9058 |
+})
|
yann@1
|
9059 |
+
|
yann@1
|
9060 |
+
|
yann@1
|
9061 |
+(define_insn "movstrsi_internal"
|
yann@1
|
9062 |
+ [(set (match_operand:BLK 0 "memory_operand" "=o")
|
yann@1
|
9063 |
+ (match_operand:BLK 1 "memory_operand" "o"))
|
yann@1
|
9064 |
+ (use (match_operand:SI 2 "const_int_operand" "i"))
|
yann@1
|
9065 |
+ (use (match_operand:SI 3 "const_int_operand" "i"))
|
yann@1
|
9066 |
+ (clobber (match_scratch:SI 4 "=&r"))
|
yann@1
|
9067 |
+ (clobber (match_scratch:SI 5 "=&r"))
|
yann@1
|
9068 |
+ (clobber (match_scratch:SI 6 "=&r"))]
|
yann@1
|
9069 |
+ "TARGET_INLINE_MEMCPY"
|
yann@1
|
9070 |
+{
|
yann@1
|
9071 |
+ int ld_offset = INTVAL (operands[2]);
|
yann@1
|
9072 |
+ int ld_len = INTVAL (operands[2]);
|
yann@1
|
9073 |
+ int ld_reg = 0;
|
yann@1
|
9074 |
+ rtx ld_addr_reg = XEXP (operands[1], 0);
|
yann@1
|
9075 |
+ int st_offset = INTVAL (operands[2]);
|
yann@1
|
9076 |
+ int st_len = INTVAL (operands[2]);
|
yann@1
|
9077 |
+ int st_reg = 0;
|
yann@1
|
9078 |
+ rtx st_addr_reg = XEXP (operands[0], 0);
|
yann@1
|
9079 |
+ int delay_count = 0;
|
yann@1
|
9080 |
+
|
yann@1
|
9081 |
+ /* ops[0] is the address used by the insn
|
yann@1
|
9082 |
+ ops[1] is the register being loaded or stored */
|
yann@1
|
9083 |
+ rtx ops[2];
|
yann@1
|
9084 |
+
|
yann@1
|
9085 |
+ if (INTVAL (operands[3]) < 4)
|
yann@1
|
9086 |
+ abort ();
|
yann@1
|
9087 |
+
|
yann@1
|
9088 |
+ while (ld_offset >= 4)
|
yann@1
|
9089 |
+ {
|
yann@1
|
9090 |
+ /* if the load use delay has been met, I can start
|
yann@1
|
9091 |
+ storing */
|
yann@1
|
9092 |
+ if (delay_count >= 3)
|
yann@1
|
9093 |
+ {
|
yann@1
|
9094 |
+ ops[0] = gen_rtx (MEM, SImode,
|
yann@1
|
9095 |
+ plus_constant (st_addr_reg, st_len - st_offset));
|
yann@1
|
9096 |
+ ops[1] = operands[st_reg + 4];
|
yann@1
|
9097 |
+ output_asm_insn ("stw\t%1, %0", ops);
|
yann@1
|
9098 |
+
|
yann@1
|
9099 |
+ st_reg = (st_reg + 1) % 3;
|
yann@1
|
9100 |
+ st_offset -= 4;
|
yann@1
|
9101 |
+ }
|
yann@1
|
9102 |
+
|
yann@1
|
9103 |
+ ops[0] = gen_rtx (MEM, SImode,
|
yann@1
|
9104 |
+ plus_constant (ld_addr_reg, ld_len - ld_offset));
|
yann@1
|
9105 |
+ ops[1] = operands[ld_reg + 4];
|
yann@1
|
9106 |
+ output_asm_insn ("ldw\t%1, %0", ops);
|
yann@1
|
9107 |
+
|
yann@1
|
9108 |
+ ld_reg = (ld_reg + 1) % 3;
|
yann@1
|
9109 |
+ ld_offset -= 4;
|
yann@1
|
9110 |
+ delay_count++;
|
yann@1
|
9111 |
+ }
|
yann@1
|
9112 |
+
|
yann@1
|
9113 |
+ if (ld_offset >= 2)
|
yann@1
|
9114 |
+ {
|
yann@1
|
9115 |
+ /* if the load use delay has been met, I can start
|
yann@1
|
9116 |
+ storing */
|
yann@1
|
9117 |
+ if (delay_count >= 3)
|
yann@1
|
9118 |
+ {
|
yann@1
|
9119 |
+ ops[0] = gen_rtx (MEM, SImode,
|
yann@1
|
9120 |
+ plus_constant (st_addr_reg, st_len - st_offset));
|
yann@1
|
9121 |
+ ops[1] = operands[st_reg + 4];
|
yann@1
|
9122 |
+ output_asm_insn ("stw\t%1, %0", ops);
|
yann@1
|
9123 |
+
|
yann@1
|
9124 |
+ st_reg = (st_reg + 1) % 3;
|
yann@1
|
9125 |
+ st_offset -= 4;
|
yann@1
|
9126 |
+ }
|
yann@1
|
9127 |
+
|
yann@1
|
9128 |
+ ops[0] = gen_rtx (MEM, HImode,
|
yann@1
|
9129 |
+ plus_constant (ld_addr_reg, ld_len - ld_offset));
|
yann@1
|
9130 |
+ ops[1] = operands[ld_reg + 4];
|
yann@1
|
9131 |
+ output_asm_insn ("ldh\t%1, %0", ops);
|
yann@1
|
9132 |
+
|
yann@1
|
9133 |
+ ld_reg = (ld_reg + 1) % 3;
|
yann@1
|
9134 |
+ ld_offset -= 2;
|
yann@1
|
9135 |
+ delay_count++;
|
yann@1
|
9136 |
+ }
|
yann@1
|
9137 |
+
|
yann@1
|
9138 |
+ if (ld_offset >= 1)
|
yann@1
|
9139 |
+ {
|
yann@1
|
9140 |
+ /* if the load use delay has been met, I can start
|
yann@1
|
9141 |
+ storing */
|
yann@1
|
9142 |
+ if (delay_count >= 3)
|
yann@1
|
9143 |
+ {
|
yann@1
|
9144 |
+ ops[0] = gen_rtx (MEM, SImode,
|
yann@1
|
9145 |
+ plus_constant (st_addr_reg, st_len - st_offset));
|
yann@1
|
9146 |
+ ops[1] = operands[st_reg + 4];
|
yann@1
|
9147 |
+ output_asm_insn ("stw\t%1, %0", ops);
|
yann@1
|
9148 |
+
|
yann@1
|
9149 |
+ st_reg = (st_reg + 1) % 3;
|
yann@1
|
9150 |
+ st_offset -= 4;
|
yann@1
|
9151 |
+ }
|
yann@1
|
9152 |
+
|
yann@1
|
9153 |
+ ops[0] = gen_rtx (MEM, QImode,
|
yann@1
|
9154 |
+ plus_constant (ld_addr_reg, ld_len - ld_offset));
|
yann@1
|
9155 |
+ ops[1] = operands[ld_reg + 4];
|
yann@1
|
9156 |
+ output_asm_insn ("ldb\t%1, %0", ops);
|
yann@1
|
9157 |
+
|
yann@1
|
9158 |
+ ld_reg = (ld_reg + 1) % 3;
|
yann@1
|
9159 |
+ ld_offset -= 1;
|
yann@1
|
9160 |
+ delay_count++;
|
yann@1
|
9161 |
+ }
|
yann@1
|
9162 |
+
|
yann@1
|
9163 |
+ while (st_offset >= 4)
|
yann@1
|
9164 |
+ {
|
yann@1
|
9165 |
+ ops[0] = gen_rtx (MEM, SImode,
|
yann@1
|
9166 |
+ plus_constant (st_addr_reg, st_len - st_offset));
|
yann@1
|
9167 |
+ ops[1] = operands[st_reg + 4];
|
yann@1
|
9168 |
+ output_asm_insn ("stw\t%1, %0", ops);
|
yann@1
|
9169 |
+
|
yann@1
|
9170 |
+ st_reg = (st_reg + 1) % 3;
|
yann@1
|
9171 |
+ st_offset -= 4;
|
yann@1
|
9172 |
+ }
|
yann@1
|
9173 |
+
|
yann@1
|
9174 |
+ while (st_offset >= 2)
|
yann@1
|
9175 |
+ {
|
yann@1
|
9176 |
+ ops[0] = gen_rtx (MEM, HImode,
|
yann@1
|
9177 |
+ plus_constant (st_addr_reg, st_len - st_offset));
|
yann@1
|
9178 |
+ ops[1] = operands[st_reg + 4];
|
yann@1
|
9179 |
+ output_asm_insn ("sth\t%1, %0", ops);
|
yann@1
|
9180 |
+
|
yann@1
|
9181 |
+ st_reg = (st_reg + 1) % 3;
|
yann@1
|
9182 |
+ st_offset -= 2;
|
yann@1
|
9183 |
+ }
|
yann@1
|
9184 |
+
|
yann@1
|
9185 |
+ while (st_offset >= 1)
|
yann@1
|
9186 |
+ {
|
yann@1
|
9187 |
+ ops[0] = gen_rtx (MEM, QImode,
|
yann@1
|
9188 |
+ plus_constant (st_addr_reg, st_len - st_offset));
|
yann@1
|
9189 |
+ ops[1] = operands[st_reg + 4];
|
yann@1
|
9190 |
+ output_asm_insn ("stb\t%1, %0", ops);
|
yann@1
|
9191 |
+
|
yann@1
|
9192 |
+ st_reg = (st_reg + 1) % 3;
|
yann@1
|
9193 |
+ st_offset -= 1;
|
yann@1
|
9194 |
+ }
|
yann@1
|
9195 |
+
|
yann@1
|
9196 |
+ return "";
|
yann@1
|
9197 |
+}
|
yann@1
|
9198 |
+; ??? lengths are not being used yet, but I will probably forget
|
yann@1
|
9199 |
+; to update this once I am using lengths, so set it to something
|
yann@1
|
9200 |
+; definetely big enough to cover it. 400 allows for 200 bytes
|
yann@1
|
9201 |
+; of motion.
|
yann@1
|
9202 |
+ [(set_attr "length" "400")])
|
yann@1
|
9203 |
+
|
yann@1
|
9204 |
+
|
yann@1
|
9205 |
+
|
yann@1
|
9206 |
+;*****************************************************************************
|
yann@1
|
9207 |
+;*
|
yann@1
|
9208 |
+;* Custom instructions
|
yann@1
|
9209 |
+;*
|
yann@1
|
9210 |
+;*****************************************************************************
|
yann@1
|
9211 |
+
|
yann@1
|
9212 |
+(define_constants [
|
yann@1
|
9213 |
+ (CUSTOM_N 100)
|
yann@1
|
9214 |
+ (CUSTOM_NI 101)
|
yann@1
|
9215 |
+ (CUSTOM_NF 102)
|
yann@1
|
9216 |
+ (CUSTOM_NP 103)
|
yann@1
|
9217 |
+ (CUSTOM_NII 104)
|
yann@1
|
9218 |
+ (CUSTOM_NIF 105)
|
yann@1
|
9219 |
+ (CUSTOM_NIP 106)
|
yann@1
|
9220 |
+ (CUSTOM_NFI 107)
|
yann@1
|
9221 |
+ (CUSTOM_NFF 108)
|
yann@1
|
9222 |
+ (CUSTOM_NFP 109)
|
yann@1
|
9223 |
+ (CUSTOM_NPI 110)
|
yann@1
|
9224 |
+ (CUSTOM_NPF 111)
|
yann@1
|
9225 |
+ (CUSTOM_NPP 112)
|
yann@1
|
9226 |
+ (CUSTOM_IN 113)
|
yann@1
|
9227 |
+ (CUSTOM_INI 114)
|
yann@1
|
9228 |
+ (CUSTOM_INF 115)
|
yann@1
|
9229 |
+ (CUSTOM_INP 116)
|
yann@1
|
9230 |
+ (CUSTOM_INII 117)
|
yann@1
|
9231 |
+ (CUSTOM_INIF 118)
|
yann@1
|
9232 |
+ (CUSTOM_INIP 119)
|
yann@1
|
9233 |
+ (CUSTOM_INFI 120)
|
yann@1
|
9234 |
+ (CUSTOM_INFF 121)
|
yann@1
|
9235 |
+ (CUSTOM_INFP 122)
|
yann@1
|
9236 |
+ (CUSTOM_INPI 123)
|
yann@1
|
9237 |
+ (CUSTOM_INPF 124)
|
yann@1
|
9238 |
+ (CUSTOM_INPP 125)
|
yann@1
|
9239 |
+ (CUSTOM_FN 126)
|
yann@1
|
9240 |
+ (CUSTOM_FNI 127)
|
yann@1
|
9241 |
+ (CUSTOM_FNF 128)
|
yann@1
|
9242 |
+ (CUSTOM_FNP 129)
|
yann@1
|
9243 |
+ (CUSTOM_FNII 130)
|
yann@1
|
9244 |
+ (CUSTOM_FNIF 131)
|
yann@1
|
9245 |
+ (CUSTOM_FNIP 132)
|
yann@1
|
9246 |
+ (CUSTOM_FNFI 133)
|
yann@1
|
9247 |
+ (CUSTOM_FNFF 134)
|
yann@1
|
9248 |
+ (CUSTOM_FNFP 135)
|
yann@1
|
9249 |
+ (CUSTOM_FNPI 136)
|
yann@1
|
9250 |
+ (CUSTOM_FNPF 137)
|
yann@1
|
9251 |
+ (CUSTOM_FNPP 138)
|
yann@1
|
9252 |
+ (CUSTOM_PN 139)
|
yann@1
|
9253 |
+ (CUSTOM_PNI 140)
|
yann@1
|
9254 |
+ (CUSTOM_PNF 141)
|
yann@1
|
9255 |
+ (CUSTOM_PNP 142)
|
yann@1
|
9256 |
+ (CUSTOM_PNII 143)
|
yann@1
|
9257 |
+ (CUSTOM_PNIF 144)
|
yann@1
|
9258 |
+ (CUSTOM_PNIP 145)
|
yann@1
|
9259 |
+ (CUSTOM_PNFI 146)
|
yann@1
|
9260 |
+ (CUSTOM_PNFF 147)
|
yann@1
|
9261 |
+ (CUSTOM_PNFP 148)
|
yann@1
|
9262 |
+ (CUSTOM_PNPI 149)
|
yann@1
|
9263 |
+ (CUSTOM_PNPF 150)
|
yann@1
|
9264 |
+ (CUSTOM_PNPP 151)
|
yann@1
|
9265 |
+])
|
yann@1
|
9266 |
+
|
yann@1
|
9267 |
+
|
yann@1
|
9268 |
+(define_insn "custom_n"
|
yann@1
|
9269 |
+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")] CUSTOM_N)]
|
yann@1
|
9270 |
+ ""
|
yann@1
|
9271 |
+ "custom\\t%0, zero, zero, zero"
|
yann@1
|
9272 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9273 |
+
|
yann@1
|
9274 |
+(define_insn "custom_ni"
|
yann@1
|
9275 |
+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
|
yann@1
|
9276 |
+ (match_operand:SI 1 "register_operand" "r")] CUSTOM_NI)]
|
yann@1
|
9277 |
+ ""
|
yann@1
|
9278 |
+ "custom\\t%0, zero, %1, zero"
|
yann@1
|
9279 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9280 |
+
|
yann@1
|
9281 |
+(define_insn "custom_nf"
|
yann@1
|
9282 |
+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
|
yann@1
|
9283 |
+ (match_operand:SF 1 "register_operand" "r")] CUSTOM_NF)]
|
yann@1
|
9284 |
+ ""
|
yann@1
|
9285 |
+ "custom\\t%0, zero, %1, zero"
|
yann@1
|
9286 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9287 |
+
|
yann@1
|
9288 |
+(define_insn "custom_np"
|
yann@1
|
9289 |
+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
|
yann@1
|
9290 |
+ (match_operand:SI 1 "register_operand" "r")] CUSTOM_NP)]
|
yann@1
|
9291 |
+ ""
|
yann@1
|
9292 |
+ "custom\\t%0, zero, %1, zero"
|
yann@1
|
9293 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9294 |
+
|
yann@1
|
9295 |
+(define_insn "custom_nii"
|
yann@1
|
9296 |
+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
|
yann@1
|
9297 |
+ (match_operand:SI 1 "register_operand" "r")
|
yann@1
|
9298 |
+ (match_operand:SI 2 "register_operand" "r")] CUSTOM_NII)]
|
yann@1
|
9299 |
+ ""
|
yann@1
|
9300 |
+ "custom\\t%0, zero, %1, %2"
|
yann@1
|
9301 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9302 |
+
|
yann@1
|
9303 |
+(define_insn "custom_nif"
|
yann@1
|
9304 |
+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
|
yann@1
|
9305 |
+ (match_operand:SI 1 "register_operand" "r")
|
yann@1
|
9306 |
+ (match_operand:SF 2 "register_operand" "r")] CUSTOM_NIF)]
|
yann@1
|
9307 |
+ ""
|
yann@1
|
9308 |
+ "custom\\t%0, zero, %1, %2"
|
yann@1
|
9309 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9310 |
+
|
yann@1
|
9311 |
+(define_insn "custom_nip"
|
yann@1
|
9312 |
+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
|
yann@1
|
9313 |
+ (match_operand:SI 1 "register_operand" "r")
|
yann@1
|
9314 |
+ (match_operand:SI 2 "register_operand" "r")] CUSTOM_NIP)]
|
yann@1
|
9315 |
+ ""
|
yann@1
|
9316 |
+ "custom\\t%0, zero, %1, %2"
|
yann@1
|
9317 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9318 |
+
|
yann@1
|
9319 |
+(define_insn "custom_nfi"
|
yann@1
|
9320 |
+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
|
yann@1
|
9321 |
+ (match_operand:SF 1 "register_operand" "r")
|
yann@1
|
9322 |
+ (match_operand:SI 2 "register_operand" "r")] CUSTOM_NFI)]
|
yann@1
|
9323 |
+ ""
|
yann@1
|
9324 |
+ "custom\\t%0, zero, %1, %2"
|
yann@1
|
9325 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9326 |
+
|
yann@1
|
9327 |
+(define_insn "custom_nff"
|
yann@1
|
9328 |
+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
|
yann@1
|
9329 |
+ (match_operand:SF 1 "register_operand" "r")
|
yann@1
|
9330 |
+ (match_operand:SF 2 "register_operand" "r")] CUSTOM_NFF)]
|
yann@1
|
9331 |
+ ""
|
yann@1
|
9332 |
+ "custom\\t%0, zero, %1, %2"
|
yann@1
|
9333 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9334 |
+
|
yann@1
|
9335 |
+(define_insn "custom_nfp"
|
yann@1
|
9336 |
+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
|
yann@1
|
9337 |
+ (match_operand:SF 1 "register_operand" "r")
|
yann@1
|
9338 |
+ (match_operand:SI 2 "register_operand" "r")] CUSTOM_NFP)]
|
yann@1
|
9339 |
+ ""
|
yann@1
|
9340 |
+ "custom\\t%0, zero, %1, %2"
|
yann@1
|
9341 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9342 |
+
|
yann@1
|
9343 |
+(define_insn "custom_npi"
|
yann@1
|
9344 |
+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
|
yann@1
|
9345 |
+ (match_operand:SI 1 "register_operand" "r")
|
yann@1
|
9346 |
+ (match_operand:SI 2 "register_operand" "r")] CUSTOM_NPI)]
|
yann@1
|
9347 |
+ ""
|
yann@1
|
9348 |
+ "custom\\t%0, zero, %1, %2"
|
yann@1
|
9349 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9350 |
+
|
yann@1
|
9351 |
+(define_insn "custom_npf"
|
yann@1
|
9352 |
+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
|
yann@1
|
9353 |
+ (match_operand:SI 1 "register_operand" "r")
|
yann@1
|
9354 |
+ (match_operand:SF 2 "register_operand" "r")] CUSTOM_NPF)]
|
yann@1
|
9355 |
+ ""
|
yann@1
|
9356 |
+ "custom\\t%0, zero, %1, %2"
|
yann@1
|
9357 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9358 |
+
|
yann@1
|
9359 |
+(define_insn "custom_npp"
|
yann@1
|
9360 |
+ [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
|
yann@1
|
9361 |
+ (match_operand:SI 1 "register_operand" "r")
|
yann@1
|
9362 |
+ (match_operand:SI 2 "register_operand" "r")] CUSTOM_NPP)]
|
yann@1
|
9363 |
+ ""
|
yann@1
|
9364 |
+ "custom\\t%0, zero, %1, %2"
|
yann@1
|
9365 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9366 |
+
|
yann@1
|
9367 |
+
|
yann@1
|
9368 |
+
|
yann@1
|
9369 |
+(define_insn "custom_in"
|
yann@1
|
9370 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9371 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")] CUSTOM_IN))]
|
yann@1
|
9372 |
+ ""
|
yann@1
|
9373 |
+ "custom\\t%1, %0, zero, zero"
|
yann@1
|
9374 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9375 |
+
|
yann@1
|
9376 |
+(define_insn "custom_ini"
|
yann@1
|
9377 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9378 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9379 |
+ (match_operand:SI 2 "register_operand" "r")] CUSTOM_INI))]
|
yann@1
|
9380 |
+ ""
|
yann@1
|
9381 |
+ "custom\\t%1, %0, %2, zero"
|
yann@1
|
9382 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9383 |
+
|
yann@1
|
9384 |
+(define_insn "custom_inf"
|
yann@1
|
9385 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9386 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9387 |
+ (match_operand:SF 2 "register_operand" "r")] CUSTOM_INF))]
|
yann@1
|
9388 |
+ ""
|
yann@1
|
9389 |
+ "custom\\t%1, %0, %2, zero"
|
yann@1
|
9390 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9391 |
+
|
yann@1
|
9392 |
+(define_insn "custom_inp"
|
yann@1
|
9393 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9394 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9395 |
+ (match_operand:SI 2 "register_operand" "r")] CUSTOM_INP))]
|
yann@1
|
9396 |
+ ""
|
yann@1
|
9397 |
+ "custom\\t%1, %0, %2, zero"
|
yann@1
|
9398 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9399 |
+
|
yann@1
|
9400 |
+(define_insn "custom_inii"
|
yann@1
|
9401 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9402 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9403 |
+ (match_operand:SI 2 "register_operand" "r")
|
yann@1
|
9404 |
+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_INII))]
|
yann@1
|
9405 |
+ ""
|
yann@1
|
9406 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9407 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9408 |
+
|
yann@1
|
9409 |
+(define_insn "custom_inif"
|
yann@1
|
9410 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9411 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9412 |
+ (match_operand:SI 2 "register_operand" "r")
|
yann@1
|
9413 |
+ (match_operand:SF 3 "register_operand" "r")] CUSTOM_INIF))]
|
yann@1
|
9414 |
+ ""
|
yann@1
|
9415 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9416 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9417 |
+
|
yann@1
|
9418 |
+(define_insn "custom_inip"
|
yann@1
|
9419 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9420 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9421 |
+ (match_operand:SI 2 "register_operand" "r")
|
yann@1
|
9422 |
+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_INIP))]
|
yann@1
|
9423 |
+ ""
|
yann@1
|
9424 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9425 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9426 |
+
|
yann@1
|
9427 |
+(define_insn "custom_infi"
|
yann@1
|
9428 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9429 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9430 |
+ (match_operand:SF 2 "register_operand" "r")
|
yann@1
|
9431 |
+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_INFI))]
|
yann@1
|
9432 |
+ ""
|
yann@1
|
9433 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9434 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9435 |
+
|
yann@1
|
9436 |
+(define_insn "custom_inff"
|
yann@1
|
9437 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9438 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9439 |
+ (match_operand:SF 2 "register_operand" "r")
|
yann@1
|
9440 |
+ (match_operand:SF 3 "register_operand" "r")] CUSTOM_INFF))]
|
yann@1
|
9441 |
+ ""
|
yann@1
|
9442 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9443 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9444 |
+
|
yann@1
|
9445 |
+(define_insn "custom_infp"
|
yann@1
|
9446 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9447 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9448 |
+ (match_operand:SF 2 "register_operand" "r")
|
yann@1
|
9449 |
+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_INFP))]
|
yann@1
|
9450 |
+ ""
|
yann@1
|
9451 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9452 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9453 |
+
|
yann@1
|
9454 |
+(define_insn "custom_inpi"
|
yann@1
|
9455 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9456 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9457 |
+ (match_operand:SI 2 "register_operand" "r")
|
yann@1
|
9458 |
+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_INPI))]
|
yann@1
|
9459 |
+ ""
|
yann@1
|
9460 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9461 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9462 |
+
|
yann@1
|
9463 |
+(define_insn "custom_inpf"
|
yann@1
|
9464 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9465 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9466 |
+ (match_operand:SI 2 "register_operand" "r")
|
yann@1
|
9467 |
+ (match_operand:SF 3 "register_operand" "r")] CUSTOM_INPF))]
|
yann@1
|
9468 |
+ ""
|
yann@1
|
9469 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9470 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9471 |
+
|
yann@1
|
9472 |
+(define_insn "custom_inpp"
|
yann@1
|
9473 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9474 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9475 |
+ (match_operand:SI 2 "register_operand" "r")
|
yann@1
|
9476 |
+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_INPP))]
|
yann@1
|
9477 |
+ ""
|
yann@1
|
9478 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9479 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9480 |
+
|
yann@1
|
9481 |
+
|
yann@1
|
9482 |
+
|
yann@1
|
9483 |
+
|
yann@1
|
9484 |
+
|
yann@1
|
9485 |
+(define_insn "custom_fn"
|
yann@1
|
9486 |
+ [(set (match_operand:SF 0 "register_operand" "=r")
|
yann@1
|
9487 |
+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")] CUSTOM_FN))]
|
yann@1
|
9488 |
+ ""
|
yann@1
|
9489 |
+ "custom\\t%1, %0, zero, zero"
|
yann@1
|
9490 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9491 |
+
|
yann@1
|
9492 |
+(define_insn "custom_fni"
|
yann@1
|
9493 |
+ [(set (match_operand:SF 0 "register_operand" "=r")
|
yann@1
|
9494 |
+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9495 |
+ (match_operand:SI 2 "register_operand" "r")] CUSTOM_FNI))]
|
yann@1
|
9496 |
+ ""
|
yann@1
|
9497 |
+ "custom\\t%1, %0, %2, zero"
|
yann@1
|
9498 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9499 |
+
|
yann@1
|
9500 |
+(define_insn "custom_fnf"
|
yann@1
|
9501 |
+ [(set (match_operand:SF 0 "register_operand" "=r")
|
yann@1
|
9502 |
+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9503 |
+ (match_operand:SF 2 "register_operand" "r")] CUSTOM_FNF))]
|
yann@1
|
9504 |
+ ""
|
yann@1
|
9505 |
+ "custom\\t%1, %0, %2, zero"
|
yann@1
|
9506 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9507 |
+
|
yann@1
|
9508 |
+(define_insn "custom_fnp"
|
yann@1
|
9509 |
+ [(set (match_operand:SF 0 "register_operand" "=r")
|
yann@1
|
9510 |
+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9511 |
+ (match_operand:SI 2 "register_operand" "r")] CUSTOM_FNP))]
|
yann@1
|
9512 |
+ ""
|
yann@1
|
9513 |
+ "custom\\t%1, %0, %2, zero"
|
yann@1
|
9514 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9515 |
+
|
yann@1
|
9516 |
+(define_insn "custom_fnii"
|
yann@1
|
9517 |
+ [(set (match_operand:SF 0 "register_operand" "=r")
|
yann@1
|
9518 |
+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9519 |
+ (match_operand:SI 2 "register_operand" "r")
|
yann@1
|
9520 |
+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_FNII))]
|
yann@1
|
9521 |
+ ""
|
yann@1
|
9522 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9523 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9524 |
+
|
yann@1
|
9525 |
+(define_insn "custom_fnif"
|
yann@1
|
9526 |
+ [(set (match_operand:SF 0 "register_operand" "=r")
|
yann@1
|
9527 |
+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9528 |
+ (match_operand:SI 2 "register_operand" "r")
|
yann@1
|
9529 |
+ (match_operand:SF 3 "register_operand" "r")] CUSTOM_FNIF))]
|
yann@1
|
9530 |
+ ""
|
yann@1
|
9531 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9532 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9533 |
+
|
yann@1
|
9534 |
+(define_insn "custom_fnip"
|
yann@1
|
9535 |
+ [(set (match_operand:SF 0 "register_operand" "=r")
|
yann@1
|
9536 |
+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9537 |
+ (match_operand:SI 2 "register_operand" "r")
|
yann@1
|
9538 |
+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_FNIP))]
|
yann@1
|
9539 |
+ ""
|
yann@1
|
9540 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9541 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9542 |
+
|
yann@1
|
9543 |
+(define_insn "custom_fnfi"
|
yann@1
|
9544 |
+ [(set (match_operand:SF 0 "register_operand" "=r")
|
yann@1
|
9545 |
+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9546 |
+ (match_operand:SF 2 "register_operand" "r")
|
yann@1
|
9547 |
+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_FNFI))]
|
yann@1
|
9548 |
+ ""
|
yann@1
|
9549 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9550 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9551 |
+
|
yann@1
|
9552 |
+(define_insn "custom_fnff"
|
yann@1
|
9553 |
+ [(set (match_operand:SF 0 "register_operand" "=r")
|
yann@1
|
9554 |
+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9555 |
+ (match_operand:SF 2 "register_operand" "r")
|
yann@1
|
9556 |
+ (match_operand:SF 3 "register_operand" "r")] CUSTOM_FNFF))]
|
yann@1
|
9557 |
+ ""
|
yann@1
|
9558 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9559 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9560 |
+
|
yann@1
|
9561 |
+(define_insn "custom_fnfp"
|
yann@1
|
9562 |
+ [(set (match_operand:SF 0 "register_operand" "=r")
|
yann@1
|
9563 |
+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9564 |
+ (match_operand:SF 2 "register_operand" "r")
|
yann@1
|
9565 |
+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_FNFP))]
|
yann@1
|
9566 |
+ ""
|
yann@1
|
9567 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9568 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9569 |
+
|
yann@1
|
9570 |
+(define_insn "custom_fnpi"
|
yann@1
|
9571 |
+ [(set (match_operand:SF 0 "register_operand" "=r")
|
yann@1
|
9572 |
+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9573 |
+ (match_operand:SI 2 "register_operand" "r")
|
yann@1
|
9574 |
+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_FNPI))]
|
yann@1
|
9575 |
+ ""
|
yann@1
|
9576 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9577 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9578 |
+
|
yann@1
|
9579 |
+(define_insn "custom_fnpf"
|
yann@1
|
9580 |
+ [(set (match_operand:SF 0 "register_operand" "=r")
|
yann@1
|
9581 |
+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9582 |
+ (match_operand:SI 2 "register_operand" "r")
|
yann@1
|
9583 |
+ (match_operand:SF 3 "register_operand" "r")] CUSTOM_FNPF))]
|
yann@1
|
9584 |
+ ""
|
yann@1
|
9585 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9586 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9587 |
+
|
yann@1
|
9588 |
+(define_insn "custom_fnpp"
|
yann@1
|
9589 |
+ [(set (match_operand:SF 0 "register_operand" "=r")
|
yann@1
|
9590 |
+ (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9591 |
+ (match_operand:SI 2 "register_operand" "r")
|
yann@1
|
9592 |
+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_FNPP))]
|
yann@1
|
9593 |
+ ""
|
yann@1
|
9594 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9595 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9596 |
+
|
yann@1
|
9597 |
+
|
yann@1
|
9598 |
+
|
yann@1
|
9599 |
+(define_insn "custom_pn"
|
yann@1
|
9600 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9601 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")] CUSTOM_PN))]
|
yann@1
|
9602 |
+ ""
|
yann@1
|
9603 |
+ "custom\\t%1, %0, zero, zero"
|
yann@1
|
9604 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9605 |
+
|
yann@1
|
9606 |
+(define_insn "custom_pni"
|
yann@1
|
9607 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9608 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9609 |
+ (match_operand:SI 2 "register_operand" "r")] CUSTOM_PNI))]
|
yann@1
|
9610 |
+ ""
|
yann@1
|
9611 |
+ "custom\\t%1, %0, %2, zero"
|
yann@1
|
9612 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9613 |
+
|
yann@1
|
9614 |
+(define_insn "custom_pnf"
|
yann@1
|
9615 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9616 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9617 |
+ (match_operand:SF 2 "register_operand" "r")] CUSTOM_PNF))]
|
yann@1
|
9618 |
+ ""
|
yann@1
|
9619 |
+ "custom\\t%1, %0, %2, zero"
|
yann@1
|
9620 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9621 |
+
|
yann@1
|
9622 |
+(define_insn "custom_pnp"
|
yann@1
|
9623 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9624 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9625 |
+ (match_operand:SI 2 "register_operand" "r")] CUSTOM_PNP))]
|
yann@1
|
9626 |
+ ""
|
yann@1
|
9627 |
+ "custom\\t%1, %0, %2, zero"
|
yann@1
|
9628 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9629 |
+
|
yann@1
|
9630 |
+(define_insn "custom_pnii"
|
yann@1
|
9631 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9632 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9633 |
+ (match_operand:SI 2 "register_operand" "r")
|
yann@1
|
9634 |
+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNII))]
|
yann@1
|
9635 |
+ ""
|
yann@1
|
9636 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9637 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9638 |
+
|
yann@1
|
9639 |
+(define_insn "custom_pnif"
|
yann@1
|
9640 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9641 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9642 |
+ (match_operand:SI 2 "register_operand" "r")
|
yann@1
|
9643 |
+ (match_operand:SF 3 "register_operand" "r")] CUSTOM_PNIF))]
|
yann@1
|
9644 |
+ ""
|
yann@1
|
9645 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9646 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9647 |
+
|
yann@1
|
9648 |
+(define_insn "custom_pnip"
|
yann@1
|
9649 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9650 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9651 |
+ (match_operand:SI 2 "register_operand" "r")
|
yann@1
|
9652 |
+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNIP))]
|
yann@1
|
9653 |
+ ""
|
yann@1
|
9654 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9655 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9656 |
+
|
yann@1
|
9657 |
+(define_insn "custom_pnfi"
|
yann@1
|
9658 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9659 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9660 |
+ (match_operand:SF 2 "register_operand" "r")
|
yann@1
|
9661 |
+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNFI))]
|
yann@1
|
9662 |
+ ""
|
yann@1
|
9663 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9664 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9665 |
+
|
yann@1
|
9666 |
+(define_insn "custom_pnff"
|
yann@1
|
9667 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9668 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9669 |
+ (match_operand:SF 2 "register_operand" "r")
|
yann@1
|
9670 |
+ (match_operand:SF 3 "register_operand" "r")] CUSTOM_PNFF))]
|
yann@1
|
9671 |
+ ""
|
yann@1
|
9672 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9673 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9674 |
+
|
yann@1
|
9675 |
+(define_insn "custom_pnfp"
|
yann@1
|
9676 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9677 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9678 |
+ (match_operand:SF 2 "register_operand" "r")
|
yann@1
|
9679 |
+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNFP))]
|
yann@1
|
9680 |
+ ""
|
yann@1
|
9681 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9682 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9683 |
+
|
yann@1
|
9684 |
+(define_insn "custom_pnpi"
|
yann@1
|
9685 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9686 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9687 |
+ (match_operand:SI 2 "register_operand" "r")
|
yann@1
|
9688 |
+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNPI))]
|
yann@1
|
9689 |
+ ""
|
yann@1
|
9690 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9691 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9692 |
+
|
yann@1
|
9693 |
+(define_insn "custom_pnpf"
|
yann@1
|
9694 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9695 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9696 |
+ (match_operand:SI 2 "register_operand" "r")
|
yann@1
|
9697 |
+ (match_operand:SF 3 "register_operand" "r")] CUSTOM_PNPF))]
|
yann@1
|
9698 |
+ ""
|
yann@1
|
9699 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9700 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9701 |
+
|
yann@1
|
9702 |
+(define_insn "custom_pnpp"
|
yann@1
|
9703 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9704 |
+ (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
|
yann@1
|
9705 |
+ (match_operand:SI 2 "register_operand" "r")
|
yann@1
|
9706 |
+ (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNPP))]
|
yann@1
|
9707 |
+ ""
|
yann@1
|
9708 |
+ "custom\\t%1, %0, %2, %3"
|
yann@1
|
9709 |
+ [(set_attr "type" "custom")])
|
yann@1
|
9710 |
+
|
yann@1
|
9711 |
+
|
yann@1
|
9712 |
+
|
yann@1
|
9713 |
+
|
yann@1
|
9714 |
+
|
yann@1
|
9715 |
+
|
yann@1
|
9716 |
+;*****************************************************************************
|
yann@1
|
9717 |
+;*
|
yann@1
|
9718 |
+;* Misc
|
yann@1
|
9719 |
+;*
|
yann@1
|
9720 |
+;*****************************************************************************
|
yann@1
|
9721 |
+
|
yann@1
|
9722 |
+(define_insn "nop"
|
yann@1
|
9723 |
+ [(const_int 0)]
|
yann@1
|
9724 |
+ ""
|
yann@1
|
9725 |
+ "nop\\t"
|
yann@1
|
9726 |
+ [(set_attr "type" "alu")])
|
yann@1
|
9727 |
+
|
yann@1
|
9728 |
+(define_insn "sync"
|
yann@1
|
9729 |
+ [(unspec_volatile [(const_int 0)] UNSPEC_SYNC)]
|
yann@1
|
9730 |
+ ""
|
yann@1
|
9731 |
+ "sync\\t"
|
yann@1
|
9732 |
+ [(set_attr "type" "control")])
|
yann@1
|
9733 |
+
|
yann@1
|
9734 |
+
|
yann@1
|
9735 |
+(define_insn "rdctl"
|
yann@1
|
9736 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
yann@1
|
9737 |
+ (unspec_volatile:SI [(match_operand:SI 1 "rdwrctl_operand" "O")] UNSPEC_RDCTL))]
|
yann@1
|
9738 |
+ ""
|
yann@1
|
9739 |
+ "rdctl\\t%0, ctl%1"
|
yann@1
|
9740 |
+ [(set_attr "type" "control")])
|
yann@1
|
9741 |
+
|
yann@1
|
9742 |
+(define_insn "wrctl"
|
yann@1
|
9743 |
+ [(unspec_volatile:SI [(match_operand:SI 0 "rdwrctl_operand" "O")
|
yann@1
|
9744 |
+ (match_operand:SI 1 "register_operand" "r")] UNSPEC_WRCTL)]
|
yann@1
|
9745 |
+ ""
|
yann@1
|
9746 |
+ "wrctl\\tctl%0, %1"
|
yann@1
|
9747 |
+ [(set_attr "type" "control")])
|
yann@1
|
9748 |
+
|
yann@1
|
9749 |
+
|
yann@1
|
9750 |
+
|
yann@1
|
9751 |
+;*****************************************************************************
|
yann@1
|
9752 |
+;*
|
yann@1
|
9753 |
+;* Peepholes
|
yann@1
|
9754 |
+;*
|
yann@1
|
9755 |
+;*****************************************************************************
|
yann@1
|
9756 |
+
|
yann@1
|
9757 |
+
|
yann@1
|
9758 |
--- gcc-3.4.3/gcc/config/nios2/t-nios2
|
yann@1
|
9759 |
+++ gcc-3.4.3-nios2/gcc/config/nios2/t-nios2
|
yann@1
|
9760 |
@@ -0,0 +1,123 @@
|
yann@1
|
9761 |
+##
|
yann@1
|
9762 |
+## Compiler flags to use when compiling libgcc2.c.
|
yann@1
|
9763 |
+##
|
yann@1
|
9764 |
+## LIB2FUNCS_EXTRA
|
yann@1
|
9765 |
+## A list of source file names to be compiled or assembled and inserted into libgcc.a.
|
yann@1
|
9766 |
+
|
yann@1
|
9767 |
+LIB2FUNCS_EXTRA=$(srcdir)/config/nios2/lib2-divmod.c \
|
yann@1
|
9768 |
+ $(srcdir)/config/nios2/lib2-divmod-hi.c \
|
yann@1
|
9769 |
+ $(srcdir)/config/nios2/lib2-divtable.c \
|
yann@1
|
9770 |
+ $(srcdir)/config/nios2/lib2-mul.c
|
yann@1
|
9771 |
+
|
yann@1
|
9772 |
+##
|
yann@1
|
9773 |
+## Floating Point Emulation
|
yann@1
|
9774 |
+## To have GCC include software floating point libraries in libgcc.a define FPBIT
|
yann@1
|
9775 |
+## and DPBIT along with a few rules as follows:
|
yann@1
|
9776 |
+##
|
yann@1
|
9777 |
+## # We want fine grained libraries, so use the new code
|
yann@1
|
9778 |
+## # to build the floating point emulation libraries.
|
yann@1
|
9779 |
+FPBIT=$(srcdir)/config/nios2/nios2-fp-bit.c
|
yann@1
|
9780 |
+DPBIT=$(srcdir)/config/nios2/nios2-dp-bit.c
|
yann@1
|
9781 |
+
|
yann@1
|
9782 |
+TARGET_LIBGCC2_CFLAGS = -O2
|
yann@1
|
9783 |
+
|
yann@1
|
9784 |
+# FLOAT_ONLY - no doubles
|
yann@1
|
9785 |
+# SMALL_MACHINE - QI/HI is faster than SI
|
yann@1
|
9786 |
+# Actually SMALL_MACHINE uses chars and shorts instead of ints
|
yann@1
|
9787 |
+# since ints (16-bit ones as they are today) are at least as fast
|
yann@1
|
9788 |
+# as chars and shorts, don't define SMALL_MACHINE
|
yann@1
|
9789 |
+# CMPtype - type returned by FP compare, i.e. INT (hard coded in fp-bit - see code )
|
yann@1
|
9790 |
+
|
yann@1
|
9791 |
+$(FPBIT): $(srcdir)/config/fp-bit.c Makefile
|
yann@1
|
9792 |
+ echo '#define FLOAT' > ${FPBIT}
|
yann@1
|
9793 |
+ cat $(srcdir)/config/fp-bit.c >> ${FPBIT}
|
yann@1
|
9794 |
+
|
yann@1
|
9795 |
+$(DPBIT): $(srcdir)/config/fp-bit.c Makefile
|
yann@1
|
9796 |
+ echo '' > ${DPBIT}
|
yann@1
|
9797 |
+ cat $(srcdir)/config/fp-bit.c >> ${DPBIT}
|
yann@1
|
9798 |
+
|
yann@1
|
9799 |
+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
|
yann@1
|
9800 |
+
|
yann@1
|
9801 |
+# Assemble startup files.
|
yann@1
|
9802 |
+$(T)crti.o: $(srcdir)/config/nios2/crti.asm $(GCC_PASSES)
|
yann@1
|
9803 |
+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
|
yann@1
|
9804 |
+ -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/nios2/crti.asm
|
yann@1
|
9805 |
+
|
yann@1
|
9806 |
+$(T)crtn.o: $(srcdir)/config/nios2/crtn.asm $(GCC_PASSES)
|
yann@1
|
9807 |
+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
|
yann@1
|
9808 |
+ -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/nios2/crtn.asm
|
yann@1
|
9809 |
+
|
yann@1
|
9810 |
+
|
yann@1
|
9811 |
+## You may need to provide additional #defines at the beginning of
|
yann@1
|
9812 |
+## fp-bit.c and dp-bit.c to control target endianness and other options
|
yann@1
|
9813 |
+##
|
yann@1
|
9814 |
+## CRTSTUFF_T_CFLAGS
|
yann@1
|
9815 |
+## Special flags used when compiling crtstuff.c. See Initialization.
|
yann@1
|
9816 |
+##
|
yann@1
|
9817 |
+## CRTSTUFF_T_CFLAGS_S
|
yann@1
|
9818 |
+## Special flags used when compiling crtstuff.c for shared linking. Used
|
yann@1
|
9819 |
+## if you use crtbeginS.o and crtendS.o in EXTRA-PARTS. See Initialization.
|
yann@1
|
9820 |
+##
|
yann@1
|
9821 |
+## MULTILIB_OPTIONS
|
yann@1
|
9822 |
+## For some targets, invoking GCC in different ways produces objects that
|
yann@1
|
9823 |
+## can not be linked together. For example, for some targets GCC produces
|
yann@1
|
9824 |
+## both big and little endian code. For these targets, you must arrange
|
yann@1
|
9825 |
+## for multiple versions of libgcc.a to be compiled, one for each set of
|
yann@1
|
9826 |
+## incompatible options. When GCC invokes the linker, it arranges to link
|
yann@1
|
9827 |
+## in the right version of libgcc.a, based on the command line options
|
yann@1
|
9828 |
+## used.
|
yann@1
|
9829 |
+## The MULTILIB_OPTIONS macro lists the set of options for which special
|
yann@1
|
9830 |
+## versions of libgcc.a must be built. Write options that are mutually
|
yann@1
|
9831 |
+## incompatible side by side, separated by a slash. Write options that may
|
yann@1
|
9832 |
+## be used together separated by a space. The build procedure will build
|
yann@1
|
9833 |
+## all combinations of compatible options.
|
yann@1
|
9834 |
+##
|
yann@1
|
9835 |
+## For example, if you set MULTILIB_OPTIONS to m68000/m68020 msoft-float,
|
yann@1
|
9836 |
+## Makefile will build special versions of libgcc.a using the following
|
yann@1
|
9837 |
+## sets of options: -m68000, -m68020, -msoft-float, -m68000 -msoft-float,
|
yann@1
|
9838 |
+## and -m68020 -msoft-float.
|
yann@1
|
9839 |
+
|
yann@1
|
9840 |
+MULTILIB_OPTIONS = mno-hw-mul mhw-mulx
|
yann@1
|
9841 |
+
|
yann@1
|
9842 |
+## MULTILIB_DIRNAMES
|
yann@1
|
9843 |
+## If MULTILIB_OPTIONS is used, this variable specifies the directory names
|
yann@1
|
9844 |
+## that should be used to hold the various libraries. Write one element in
|
yann@1
|
9845 |
+## MULTILIB_DIRNAMES for each element in MULTILIB_OPTIONS. If
|
yann@1
|
9846 |
+## MULTILIB_DIRNAMES is not used, the default value will be
|
yann@1
|
9847 |
+## MULTILIB_OPTIONS, with all slashes treated as spaces.
|
yann@1
|
9848 |
+## For example, if MULTILIB_OPTIONS is set to m68000/m68020 msoft-float,
|
yann@1
|
9849 |
+## then the default value of MULTILIB_DIRNAMES is m68000 m68020
|
yann@1
|
9850 |
+## msoft-float. You may specify a different value if you desire a
|
yann@1
|
9851 |
+## different set of directory names.
|
yann@1
|
9852 |
+
|
yann@1
|
9853 |
+# MULTILIB_DIRNAMES =
|
yann@1
|
9854 |
+
|
yann@1
|
9855 |
+## MULTILIB_MATCHES
|
yann@1
|
9856 |
+## Sometimes the same option may be written in two different ways. If an
|
yann@1
|
9857 |
+## option is listed in MULTILIB_OPTIONS, GCC needs to know about any
|
yann@1
|
9858 |
+## synonyms. In that case, set MULTILIB_MATCHES to a list of items of the
|
yann@1
|
9859 |
+## form option=option to describe all relevant synonyms. For example,
|
yann@1
|
9860 |
+## m68000=mc68000 m68020=mc68020.
|
yann@1
|
9861 |
+##
|
yann@1
|
9862 |
+## MULTILIB_EXCEPTIONS
|
yann@1
|
9863 |
+## Sometimes when there are multiple sets of MULTILIB_OPTIONS being
|
yann@1
|
9864 |
+## specified, there are combinations that should not be built. In that
|
yann@1
|
9865 |
+## case, set MULTILIB_EXCEPTIONS to be all of the switch exceptions in
|
yann@1
|
9866 |
+## shell case syntax that should not be built.
|
yann@1
|
9867 |
+## For example, in the PowerPC embedded ABI support, it is not desirable to
|
yann@1
|
9868 |
+## build libraries compiled with the -mcall-aix option and either of the
|
yann@1
|
9869 |
+## -fleading-underscore or -mlittle options at the same time. Therefore
|
yann@1
|
9870 |
+## MULTILIB_EXCEPTIONS is set to
|
yann@1
|
9871 |
+##
|
yann@1
|
9872 |
+## *mcall-aix/*fleading-underscore* *mlittle/*mcall-aix*
|
yann@1
|
9873 |
+##
|
yann@1
|
9874 |
+
|
yann@1
|
9875 |
+MULTILIB_EXCEPTIONS = *mno-hw-mul/*mhw-mulx*
|
yann@1
|
9876 |
+
|
yann@1
|
9877 |
+##
|
yann@1
|
9878 |
+## MULTILIB_EXTRA_OPTS Sometimes it is desirable that when building
|
yann@1
|
9879 |
+## multiple versions of libgcc.a certain options should always be passed on
|
yann@1
|
9880 |
+## to the compiler. In that case, set MULTILIB_EXTRA_OPTS to be the list
|
yann@1
|
9881 |
+## of options to be used for all builds.
|
yann@1
|
9882 |
+##
|
yann@1
|
9883 |
+
|
yann@1
|
9884 |
--- gcc-3.4.3/gcc/config.gcc
|
yann@1
|
9885 |
+++ gcc-3.4.3-nios2/gcc/config.gcc
|
yann@1
|
9886 |
@@ -1321,6 +1321,10 @@ m32rle-*-linux*)
|
yann@1
|
9887 |
thread_file='posix'
|
yann@1
|
9888 |
fi
|
yann@1
|
9889 |
;;
|
yann@1
|
9890 |
+# JBG
|
yann@1
|
9891 |
+nios2-*-* | nios2-*-*)
|
yann@1
|
9892 |
+ tm_file="elfos.h ${tm_file}"
|
yann@1
|
9893 |
+ ;;
|
yann@1
|
9894 |
# m68hc11 and m68hc12 share the same machine description.
|
yann@1
|
9895 |
m68hc11-*-*|m6811-*-*)
|
yann@1
|
9896 |
tm_file="dbxelf.h elfos.h m68hc11/m68hc11.h"
|
yann@1
|
9897 |
--- gcc-3.4.3/gcc/cse.c
|
yann@1
|
9898 |
+++ gcc-3.4.3-nios2/gcc/cse.c
|
yann@1
|
9899 |
@@ -3134,6 +3134,10 @@ find_comparison_args (enum rtx_code code
|
yann@1
|
9900 |
#ifdef FLOAT_STORE_FLAG_VALUE
|
yann@1
|
9901 |
REAL_VALUE_TYPE fsfv;
|
yann@1
|
9902 |
#endif
|
yann@1
|
9903 |
+#ifdef __nios2__
|
yann@1
|
9904 |
+ if (p->is_const)
|
yann@1
|
9905 |
+ break;
|
yann@1
|
9906 |
+#endif
|
yann@1
|
9907 |
|
yann@1
|
9908 |
/* If the entry isn't valid, skip it. */
|
yann@1
|
9909 |
if (! exp_equiv_p (p->exp, p->exp, 1, 0))
|
yann@1
|
9910 |
--- gcc-3.4.3/gcc/doc/extend.texi
|
yann@1
|
9911 |
+++ gcc-3.4.3-nios2/gcc/doc/extend.texi
|
yann@1
|
9912 |
@@ -5636,12 +5636,118 @@ to those machines. Generally these gene
|
yann@1
|
9913 |
instructions, but allow the compiler to schedule those calls.
|
yann@1
|
9914 |
|
yann@1
|
9915 |
@menu
|
yann@1
|
9916 |
+* Altera Nios II Built-in Functions::
|
yann@1
|
9917 |
* Alpha Built-in Functions::
|
yann@1
|
9918 |
* ARM Built-in Functions::
|
yann@1
|
9919 |
* X86 Built-in Functions::
|
yann@1
|
9920 |
* PowerPC AltiVec Built-in Functions::
|
yann@1
|
9921 |
@end menu
|
yann@1
|
9922 |
|
yann@1
|
9923 |
+@node Altera Nios II Built-in Functions
|
yann@1
|
9924 |
+@subsection Altera Nios II Built-in Functions
|
yann@1
|
9925 |
+
|
yann@1
|
9926 |
+These built-in functions are available for the Altera Nios II
|
yann@1
|
9927 |
+family of processors.
|
yann@1
|
9928 |
+
|
yann@1
|
9929 |
+The following built-in functions are always available. They
|
yann@1
|
9930 |
+all generate the machine instruction that is part of the name.
|
yann@1
|
9931 |
+
|
yann@1
|
9932 |
+@example
|
yann@1
|
9933 |
+int __builtin_ldbio (volatile const void *)
|
yann@1
|
9934 |
+int __builtin_ldbuio (volatile const void *)
|
yann@1
|
9935 |
+int __builtin_ldhio (volatile const void *)
|
yann@1
|
9936 |
+int __builtin_ldhuio (volatile const void *)
|
yann@1
|
9937 |
+int __builtin_ldwio (volatile const void *)
|
yann@1
|
9938 |
+void __builtin_stbio (volatile void *, int)
|
yann@1
|
9939 |
+void __builtin_sthio (volatile void *, int)
|
yann@1
|
9940 |
+void __builtin_stwio (volatile void *, int)
|
yann@1
|
9941 |
+void __builtin_sync (void)
|
yann@1
|
9942 |
+int __builtin_rdctl (int)
|
yann@1
|
9943 |
+void __builtin_wrctl (int, int)
|
yann@1
|
9944 |
+@end example
|
yann@1
|
9945 |
+
|
yann@1
|
9946 |
+The following built-in functions are always available. They
|
yann@1
|
9947 |
+all generate a Nios II Custom Instruction. The name of the
|
yann@1
|
9948 |
+function represents the types that the function takes and
|
yann@1
|
9949 |
+returns. The letter before the @code{n} is the return type
|
yann@1
|
9950 |
+or void if absent. The @code{n} represnts the first parameter
|
yann@1
|
9951 |
+to all the custom instructions, the custom instruction number.
|
yann@1
|
9952 |
+The two letters after the @code{n} represent the up to two
|
yann@1
|
9953 |
+parameters to the function.
|
yann@1
|
9954 |
+
|
yann@1
|
9955 |
+The letters reprsent the following data types:
|
yann@1
|
9956 |
+@table @code
|
yann@1
|
9957 |
+@item <no letter>
|
yann@1
|
9958 |
+@code{void} for return type and no parameter for parameter types.
|
yann@1
|
9959 |
+
|
yann@1
|
9960 |
+@item i
|
yann@1
|
9961 |
+@code{int} for return type and parameter type
|
yann@1
|
9962 |
+
|
yann@1
|
9963 |
+@item f
|
yann@1
|
9964 |
+@code{float} for return type and parameter type
|
yann@1
|
9965 |
+
|
yann@1
|
9966 |
+@item p
|
yann@1
|
9967 |
+@code{void *} for return type and parameter type
|
yann@1
|
9968 |
+
|
yann@1
|
9969 |
+@end table
|
yann@1
|
9970 |
+
|
yann@1
|
9971 |
+And the function names are:
|
yann@1
|
9972 |
+@example
|
yann@1
|
9973 |
+void __builtin_custom_n (void)
|
yann@1
|
9974 |
+void __builtin_custom_ni (int)
|
yann@1
|
9975 |
+void __builtin_custom_nf (float)
|
yann@1
|
9976 |
+void __builtin_custom_np (void *)
|
yann@1
|
9977 |
+void __builtin_custom_nii (int, int)
|
yann@1
|
9978 |
+void __builtin_custom_nif (int, float)
|
yann@1
|
9979 |
+void __builtin_custom_nip (int, void *)
|
yann@1
|
9980 |
+void __builtin_custom_nfi (float, int)
|
yann@1
|
9981 |
+void __builtin_custom_nff (float, float)
|
yann@1
|
9982 |
+void __builtin_custom_nfp (float, void *)
|
yann@1
|
9983 |
+void __builtin_custom_npi (void *, int)
|
yann@1
|
9984 |
+void __builtin_custom_npf (void *, float)
|
yann@1
|
9985 |
+void __builtin_custom_npp (void *, void *)
|
yann@1
|
9986 |
+int __builtin_custom_in (void)
|
yann@1
|
9987 |
+int __builtin_custom_ini (int)
|
yann@1
|
9988 |
+int __builtin_custom_inf (float)
|
yann@1
|
9989 |
+int __builtin_custom_inp (void *)
|
yann@1
|
9990 |
+int __builtin_custom_inii (int, int)
|
yann@1
|
9991 |
+int __builtin_custom_inif (int, float)
|
yann@1
|
9992 |
+int __builtin_custom_inip (int, void *)
|
yann@1
|
9993 |
+int __builtin_custom_infi (float, int)
|
yann@1
|
9994 |
+int __builtin_custom_inff (float, float)
|
yann@1
|
9995 |
+int __builtin_custom_infp (float, void *)
|
yann@1
|
9996 |
+int __builtin_custom_inpi (void *, int)
|
yann@1
|
9997 |
+int __builtin_custom_inpf (void *, float)
|
yann@1
|
9998 |
+int __builtin_custom_inpp (void *, void *)
|
yann@1
|
9999 |
+float __builtin_custom_fn (void)
|
yann@1
|
10000 |
+float __builtin_custom_fni (int)
|
yann@1
|
10001 |
+float __builtin_custom_fnf (float)
|
yann@1
|
10002 |
+float __builtin_custom_fnp (void *)
|
yann@1
|
10003 |
+float __builtin_custom_fnii (int, int)
|
yann@1
|
10004 |
+float __builtin_custom_fnif (int, float)
|
yann@1
|
10005 |
+float __builtin_custom_fnip (int, void *)
|
yann@1
|
10006 |
+float __builtin_custom_fnfi (float, int)
|
yann@1
|
10007 |
+float __builtin_custom_fnff (float, float)
|
yann@1
|
10008 |
+float __builtin_custom_fnfp (float, void *)
|
yann@1
|
10009 |
+float __builtin_custom_fnpi (void *, int)
|
yann@1
|
10010 |
+float __builtin_custom_fnpf (void *, float)
|
yann@1
|
10011 |
+float __builtin_custom_fnpp (void *, void *)
|
yann@1
|
10012 |
+void * __builtin_custom_pn (void)
|
yann@1
|
10013 |
+void * __builtin_custom_pni (int)
|
yann@1
|
10014 |
+void * __builtin_custom_pnf (float)
|
yann@1
|
10015 |
+void * __builtin_custom_pnp (void *)
|
yann@1
|
10016 |
+void * __builtin_custom_pnii (int, int)
|
yann@1
|
10017 |
+void * __builtin_custom_pnif (int, float)
|
yann@1
|
10018 |
+void * __builtin_custom_pnip (int, void *)
|
yann@1
|
10019 |
+void * __builtin_custom_pnfi (float, int)
|
yann@1
|
10020 |
+void * __builtin_custom_pnff (float, float)
|
yann@1
|
10021 |
+void * __builtin_custom_pnfp (float, void *)
|
yann@1
|
10022 |
+void * __builtin_custom_pnpi (void *, int)
|
yann@1
|
10023 |
+void * __builtin_custom_pnpf (void *, float)
|
yann@1
|
10024 |
+void * __builtin_custom_pnpp (void *, void *)
|
yann@1
|
10025 |
+@end example
|
yann@1
|
10026 |
+
|
yann@1
|
10027 |
+
|
yann@1
|
10028 |
@node Alpha Built-in Functions
|
yann@1
|
10029 |
@subsection Alpha Built-in Functions
|
yann@1
|
10030 |
|
yann@1
|
10031 |
--- gcc-3.4.3/gcc/doc/invoke.texi
|
yann@1
|
10032 |
+++ gcc-3.4.3-nios2/gcc/doc/invoke.texi
|
yann@1
|
10033 |
@@ -337,6 +337,14 @@ in the following sections.
|
yann@1
|
10034 |
@item Machine Dependent Options
|
yann@1
|
10035 |
@xref{Submodel Options,,Hardware Models and Configurations}.
|
yann@1
|
10036 |
|
yann@1
|
10037 |
+@emph{Altera Nios II Options}
|
yann@1
|
10038 |
+@gccoptlist{-msmallc -mno-bypass-cache -mbypass-cache @gol
|
yann@1
|
10039 |
+-mno-cache-volatile -mcache-volatile -mno-inline-memcpy @gol
|
yann@1
|
10040 |
+-minline-memcpy -mno-fast-sw-div -mfast-sw-div @gol
|
yann@1
|
10041 |
+-mhw-mul -mno-hw-mul -mhw-mulx -mno-hw-mulx @gol
|
yann@1
|
10042 |
+-mno-hw-div -mhw-div @gol
|
yann@1
|
10043 |
+-msys-crt0= -msys-lib= -msys=nosys }
|
yann@1
|
10044 |
+
|
yann@1
|
10045 |
@emph{M680x0 Options}
|
yann@1
|
10046 |
@gccoptlist{-m68000 -m68020 -m68020-40 -m68020-60 -m68030 -m68040 @gol
|
yann@1
|
10047 |
-m68060 -mcpu32 -m5200 -m68881 -mbitfield -mc68000 -mc68020 @gol
|
yann@1
|
10048 |
@@ -5836,6 +5844,7 @@ machine description. The default for th
|
yann@1
|
10049 |
that macro, which enables you to change the defaults.
|
yann@1
|
10050 |
|
yann@1
|
10051 |
@menu
|
yann@1
|
10052 |
+* Altera Nios II Options::
|
yann@1
|
10053 |
* M680x0 Options::
|
yann@1
|
10054 |
* M68hc1x Options::
|
yann@1
|
10055 |
* VAX Options::
|
yann@1
|
10056 |
@@ -5871,6 +5880,103 @@ that macro, which enables you to change
|
yann@1
|
10057 |
* FRV Options::
|
yann@1
|
10058 |
@end menu
|
yann@1
|
10059 |
|
yann@1
|
10060 |
+
|
yann@1
|
10061 |
+@node Altera Nios II Options
|
yann@1
|
10062 |
+@subsection Altera Nios II Options
|
yann@1
|
10063 |
+@cindex Altera Nios II options
|
yann@1
|
10064 |
+
|
yann@1
|
10065 |
+These are the @samp{-m} options defined for the Altera Nios II
|
yann@1
|
10066 |
+processor.
|
yann@1
|
10067 |
+
|
yann@1
|
10068 |
+@table @gcctabopt
|
yann@1
|
10069 |
+
|
yann@1
|
10070 |
+@item -msmallc
|
yann@1
|
10071 |
+@opindex msmallc
|
yann@1
|
10072 |
+
|
yann@1
|
10073 |
+Link with a limited version of the C library, -lsmallc. For more
|
yann@1
|
10074 |
+information see the C Library Documentation.
|
yann@1
|
10075 |
+
|
yann@1
|
10076 |
+
|
yann@1
|
10077 |
+@item -mbypass-cache
|
yann@1
|
10078 |
+@itemx -mno-bypass-cache
|
yann@1
|
10079 |
+@opindex mno-bypass-cache
|
yann@1
|
10080 |
+@opindex mbypass-cache
|
yann@1
|
10081 |
+
|
yann@1
|
10082 |
+Force all load and store instructions to always bypass cache by
|
yann@1
|
10083 |
+using io variants of the instructions. The default is to not
|
yann@1
|
10084 |
+bypass the cache.
|
yann@1
|
10085 |
+
|
yann@1
|
10086 |
+@item -mno-cache-volatile
|
yann@1
|
10087 |
+@itemx -mcache-volatile
|
yann@1
|
10088 |
+@opindex mcache-volatile
|
yann@1
|
10089 |
+@opindex mno-cache-volatile
|
yann@1
|
10090 |
+
|
yann@1
|
10091 |
+Volatile memory access bypass the cache using the io variants of
|
yann@1
|
10092 |
+the ld and st instructions. The default is to cache volatile
|
yann@1
|
10093 |
+accesses.
|
yann@1
|
10094 |
+
|
yann@1
|
10095 |
+-mno-cache-volatile is deprecated and will be deleted in a
|
yann@1
|
10096 |
+future GCC release.
|
yann@1
|
10097 |
+
|
yann@1
|
10098 |
+
|
yann@1
|
10099 |
+@item -mno-inline-memcpy
|
yann@1
|
10100 |
+@itemx -minline-memcpy
|
yann@1
|
10101 |
+@opindex mno-inline-memcpy
|
yann@1
|
10102 |
+@opindex minline-memcpy
|
yann@1
|
10103 |
+
|
yann@1
|
10104 |
+Do not inline memcpy. The default is to inline when -O is on.
|
yann@1
|
10105 |
+
|
yann@1
|
10106 |
+
|
yann@1
|
10107 |
+@item -mno-fast-sw-div
|
yann@1
|
10108 |
+@itemx -mfast-sw-div
|
yann@1
|
10109 |
+@opindex mno-fast-sw-div
|
yann@1
|
10110 |
+@opindex mfast-sw-div
|
yann@1
|
10111 |
+
|
yann@1
|
10112 |
+Do no use table based fast divide for small numbers. The default
|
yann@1
|
10113 |
+is to use the fast divide at -O3 and above.
|
yann@1
|
10114 |
+
|
yann@1
|
10115 |
+
|
yann@1
|
10116 |
+@item -mno-hw-mul
|
yann@1
|
10117 |
+@itemx -mhw-mul
|
yann@1
|
10118 |
+@itemx -mno-hw-mulx
|
yann@1
|
10119 |
+@itemx -mhw-mulx
|
yann@1
|
10120 |
+@itemx -mno-hw-div
|
yann@1
|
10121 |
+@itemx -mhw-div
|
yann@1
|
10122 |
+@opindex mno-hw-mul
|
yann@1
|
10123 |
+@opindex mhw-mul
|
yann@1
|
10124 |
+@opindex mno-hw-mulx
|
yann@1
|
10125 |
+@opindex mhw-mulx
|
yann@1
|
10126 |
+@opindex mno-hw-div
|
yann@1
|
10127 |
+@opindex mhw-div
|
yann@1
|
10128 |
+
|
yann@1
|
10129 |
+Enable or disable emitting @code{mul}, @code{mulx} and @code{div} family of
|
yann@1
|
10130 |
+instructions by the compiler. The default is to emit @code{mul}
|
yann@1
|
10131 |
+and not emit @code{div} and @code{mulx}.
|
yann@1
|
10132 |
+
|
yann@1
|
10133 |
+The different combinations of @code{mul} and @code{mulx} instructions
|
yann@1
|
10134 |
+generate a different multilib options.
|
yann@1
|
10135 |
+
|
yann@1
|
10136 |
+
|
yann@1
|
10137 |
+@item -msys-crt0=@var{startfile}
|
yann@1
|
10138 |
+@opindex msys-crt0
|
yann@1
|
10139 |
+
|
yann@1
|
10140 |
+@var{startfile} is the file name of the startfile (crt0) to use
|
yann@1
|
10141 |
+when linking. The default is crt0.o that comes with libgloss
|
yann@1
|
10142 |
+and is only suitable for use with the instruction set
|
yann@1
|
10143 |
+simulator.
|
yann@1
|
10144 |
+
|
yann@1
|
10145 |
+@item -msys-lib=@var{systemlib}
|
yann@1
|
10146 |
+@itemx -msys-lib=nosys
|
yann@1
|
10147 |
+@opindex msys-lib
|
yann@1
|
10148 |
+
|
yann@1
|
10149 |
+@var{systemlib} is the library name of the library which provides
|
yann@1
|
10150 |
+the system calls required by the C library, e.g. @code{read}, @code{write}
|
yann@1
|
10151 |
+etc. The default is to use nosys, this library provides
|
yann@1
|
10152 |
+stub implementations of the calls and is part of libgloss.
|
yann@1
|
10153 |
+
|
yann@1
|
10154 |
+@end table
|
yann@1
|
10155 |
+
|
yann@1
|
10156 |
+
|
yann@1
|
10157 |
@node M680x0 Options
|
yann@1
|
10158 |
@subsection M680x0 Options
|
yann@1
|
10159 |
@cindex M680x0 options
|
yann@1
|
10160 |
--- gcc-3.4.3/gcc/doc/md.texi
|
yann@1
|
10161 |
+++ gcc-3.4.3-nios2/gcc/doc/md.texi
|
yann@1
|
10162 |
@@ -1335,6 +1335,49 @@ However, here is a summary of the machin
|
yann@1
|
10163 |
available on some particular machines.
|
yann@1
|
10164 |
|
yann@1
|
10165 |
@table @emph
|
yann@1
|
10166 |
+
|
yann@1
|
10167 |
+@item Altera Nios II family---@file{nios2.h}
|
yann@1
|
10168 |
+@table @code
|
yann@1
|
10169 |
+
|
yann@1
|
10170 |
+@item I
|
yann@1
|
10171 |
+Integer that is valid as an immediate operand in an
|
yann@1
|
10172 |
+instruction taking a signed 16-bit number. Range
|
yann@1
|
10173 |
+@minus{}32768 to 32767.
|
yann@1
|
10174 |
+
|
yann@1
|
10175 |
+@item J
|
yann@1
|
10176 |
+Integer that is valid as an immediate operand in an
|
yann@1
|
10177 |
+instruction taking an unsigned 16-bit number. Range
|
yann@1
|
10178 |
+0 to 65535.
|
yann@1
|
10179 |
+
|
yann@1
|
10180 |
+@item K
|
yann@1
|
10181 |
+Integer that is valid as an immediate operand in an
|
yann@1
|
10182 |
+instruction taking only the upper 16-bits of a
|
yann@1
|
10183 |
+32-bit number. Range 32-bit numbers with the lower
|
yann@1
|
10184 |
+16-bits being 0.
|
yann@1
|
10185 |
+
|
yann@1
|
10186 |
+@item L
|
yann@1
|
10187 |
+Integer that is valid as an immediate operand for a
|
yann@1
|
10188 |
+shift instruction. Range 0 to 31.
|
yann@1
|
10189 |
+
|
yann@1
|
10190 |
+
|
yann@1
|
10191 |
+@item M
|
yann@1
|
10192 |
+Integer that is valid as an immediate operand for
|
yann@1
|
10193 |
+only the value 0. Can be used in conjunction with
|
yann@1
|
10194 |
+the format modifier @code{z} to use @code{r0}
|
yann@1
|
10195 |
+instead of @code{0} in the assembly output.
|
yann@1
|
10196 |
+
|
yann@1
|
10197 |
+@item N
|
yann@1
|
10198 |
+Integer that is valid as an immediate operand for
|
yann@1
|
10199 |
+a custom instruction opcode. Range 0 to 255.
|
yann@1
|
10200 |
+
|
yann@1
|
10201 |
+@item S
|
yann@1
|
10202 |
+Matches immediates which are addresses in the small
|
yann@1
|
10203 |
+data section and therefore can be added to @code{gp}
|
yann@1
|
10204 |
+as a 16-bit immediate to re-create their 32-bit value.
|
yann@1
|
10205 |
+
|
yann@1
|
10206 |
+@end table
|
yann@1
|
10207 |
+
|
yann@1
|
10208 |
+
|
yann@1
|
10209 |
@item ARM family---@file{arm.h}
|
yann@1
|
10210 |
@table @code
|
yann@1
|
10211 |
@item f
|