bump version
[buildroot.git] / toolchain / gcc / 3.4.6 / 900-nios2.patch
blobbfa06a21c14dbd07c811fee3752982467d12d424
1 --- gcc-3.4.3/gcc/Makefile.in
2 +++ gcc-3.4.3-nios2/gcc/Makefile.in
3 @@ -3085,7 +3085,7 @@ install-mkheaders: stmp-int-hdrs $(STMP_
4 $(INSTALL_DATA) $(srcdir)/README-fixinc \
5 $(DESTDIR)$(itoolsdatadir)/include/README ; \
6 $(INSTALL_SCRIPT) fixinc.sh $(DESTDIR)$(itoolsdir)/fixinc.sh ; \
7 - $(INSTALL_PROGRAM) fixinc/fixincl $(DESTDIR)$(itoolsdir)/fixincl ; \
8 + $(INSTALL_PROGRAM) fixinc/fixincl$(build_exeext) $(DESTDIR)$(itoolsdir)/fixincl$(build_exeext) ; \
9 $(INSTALL_DATA) $(srcdir)/gsyslimits.h \
10 $(DESTDIR)$(itoolsdatadir)/gsyslimits.h ; \
11 else :; fi
12 --- gcc-3.4.3/gcc/combine.c
13 +++ gcc-3.4.3-nios2/gcc/combine.c
14 @@ -4380,6 +4380,14 @@ combine_simplify_rtx (rtx x, enum machin
15 mode);
18 +#ifndef __nios2__
19 +/* This screws up Nios II in this test case:
21 +if (x & 1)
22 + return 2;
23 +else
24 + return 3;
25 +*/
26 else if (STORE_FLAG_VALUE == 1
27 && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
28 && op1 == const0_rtx
29 @@ -4391,6 +4399,7 @@ combine_simplify_rtx (rtx x, enum machin
30 gen_lowpart_for_combine (mode, op0),
31 const1_rtx);
33 +#endif
35 else if (STORE_FLAG_VALUE == 1
36 && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
37 --- gcc-3.4.3/gcc/config/nios2/crti.asm
38 +++ gcc-3.4.3-nios2/gcc/config/nios2/crti.asm
39 @@ -0,0 +1,88 @@
40 +/*
41 + Copyright (C) 2003
42 + by Jonah Graham (jgraham@altera.com)
44 +This file is free software; you can redistribute it and/or modify it
45 +under the terms of the GNU General Public License as published by the
46 +Free Software Foundation; either version 2, or (at your option) any
47 +later version.
49 +In addition to the permissions in the GNU General Public License, the
50 +Free Software Foundation gives you unlimited permission to link the
51 +compiled version of this file with other programs, and to distribute
52 +those programs without any restriction coming from the use of this
53 +file. (The General Public License restrictions do apply in other
54 +respects; for example, they cover modification of the file, and
55 +distribution when not linked into another program.)
57 +This file is distributed in the hope that it will be useful, but
58 +WITHOUT ANY WARRANTY; without even the implied warranty of
59 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
60 +General Public License for more details.
62 +You should have received a copy of the GNU General Public License
63 +along with this program; see the file COPYING. If not, write to
64 +the Free Software Foundation, 59 Temple Place - Suite 330,
65 +Boston, MA 02111-1307, USA.
67 + As a special exception, if you link this library with files
68 + compiled with GCC to produce an executable, this does not cause
69 + the resulting executable to be covered by the GNU General Public License.
70 + This exception does not however invalidate any other reasons why
71 + the executable file might be covered by the GNU General Public License.
74 +This file just make a stack frame for the contents of the .fini and
75 +.init sections. Users may put any desired instructions in those
76 +sections.
79 +While technically any code can be put in the init and fini sections
80 +most stuff will not work other than stuff which obeys the call frame
81 +and ABI. All the call-preserved registers are saved, the call clobbered
82 +registers should have been saved by the code calling init and fini.
84 +See crtstuff.c for an example of code that inserts itself in the
85 +init and fini sections.
87 +See crt0.s for the code that calls init and fini.
88 +*/
90 + .file "crti.asm"
92 + .section ".init"
93 + .align 2
94 + .global _init
95 +_init:
96 + addi sp, sp, -48
97 + stw ra, 44(sp)
98 + stw r23, 40(sp)
99 + stw r22, 36(sp)
100 + stw r21, 32(sp)
101 + stw r20, 28(sp)
102 + stw r19, 24(sp)
103 + stw r18, 20(sp)
104 + stw r17, 16(sp)
105 + stw r16, 12(sp)
106 + stw fp, 8(sp)
107 + mov fp, sp
110 + .section ".fini"
111 + .align 2
112 + .global _fini
113 +_fini:
114 + addi sp, sp, -48
115 + stw ra, 44(sp)
116 + stw r23, 40(sp)
117 + stw r22, 36(sp)
118 + stw r21, 32(sp)
119 + stw r20, 28(sp)
120 + stw r19, 24(sp)
121 + stw r18, 20(sp)
122 + stw r17, 16(sp)
123 + stw r16, 12(sp)
124 + stw fp, 8(sp)
125 + mov fp, sp
128 --- gcc-3.4.3/gcc/config/nios2/crtn.asm
129 +++ gcc-3.4.3-nios2/gcc/config/nios2/crtn.asm
130 @@ -0,0 +1,70 @@
132 + Copyright (C) 2003
133 + by Jonah Graham (jgraham@altera.com)
135 +This file is free software; you can redistribute it and/or modify it
136 +under the terms of the GNU General Public License as published by the
137 +Free Software Foundation; either version 2, or (at your option) any
138 +later version.
140 +In addition to the permissions in the GNU General Public License, the
141 +Free Software Foundation gives you unlimited permission to link the
142 +compiled version of this file with other programs, and to distribute
143 +those programs without any restriction coming from the use of this
144 +file. (The General Public License restrictions do apply in other
145 +respects; for example, they cover modification of the file, and
146 +distribution when not linked into another program.)
148 +This file is distributed in the hope that it will be useful, but
149 +WITHOUT ANY WARRANTY; without even the implied warranty of
150 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
151 +General Public License for more details.
153 +You should have received a copy of the GNU General Public License
154 +along with this program; see the file COPYING. If not, write to
155 +the Free Software Foundation, 59 Temple Place - Suite 330,
156 +Boston, MA 02111-1307, USA.
158 + As a special exception, if you link this library with files
159 + compiled with GCC to produce an executable, this does not cause
160 + the resulting executable to be covered by the GNU General Public License.
161 + This exception does not however invalidate any other reasons why
162 + the executable file might be covered by the GNU General Public License.
165 +This file just makes sure that the .fini and .init sections do in
166 +fact return. Users may put any desired instructions in those sections.
167 +This file is the last thing linked into any executable.
168 +*/
169 + .file "crtn.asm"
173 + .section ".init"
174 + ldw ra, 44(sp)
175 + ldw r23, 40(sp)
176 + ldw r22, 36(sp)
177 + ldw r21, 32(sp)
178 + ldw r20, 28(sp)
179 + ldw r19, 24(sp)
180 + ldw r18, 20(sp)
181 + ldw r17, 16(sp)
182 + ldw r16, 12(sp)
183 + ldw fp, 8(sp)
184 + addi sp, sp, -48
185 + ret
187 + .section ".fini"
188 + ldw ra, 44(sp)
189 + ldw r23, 40(sp)
190 + ldw r22, 36(sp)
191 + ldw r21, 32(sp)
192 + ldw r20, 28(sp)
193 + ldw r19, 24(sp)
194 + ldw r18, 20(sp)
195 + ldw r17, 16(sp)
196 + ldw r16, 12(sp)
197 + ldw fp, 8(sp)
198 + addi sp, sp, -48
199 + ret
201 --- gcc-3.4.3/gcc/config/nios2/lib2-divmod-hi.c
202 +++ gcc-3.4.3-nios2/gcc/config/nios2/lib2-divmod-hi.c
203 @@ -0,0 +1,123 @@
205 +/* We include auto-host.h here to get HAVE_GAS_HIDDEN. This is
206 + supposedly valid even though this is a "target" file. */
207 +#include "auto-host.h"
210 +#include "tconfig.h"
211 +#include "tsystem.h"
212 +#include "coretypes.h"
213 +#include "tm.h"
216 +/* Don't use `fancy_abort' here even if config.h says to use it. */
217 +#ifdef abort
218 +#undef abort
219 +#endif
222 +#ifdef HAVE_GAS_HIDDEN
223 +#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden")))
224 +#else
225 +#define ATTRIBUTE_HIDDEN
226 +#endif
228 +#include "libgcc2.h"
230 +extern HItype __modhi3 (HItype, HItype);
231 +extern HItype __divhi3 (HItype, HItype);
232 +extern HItype __umodhi3 (HItype, HItype);
233 +extern HItype __udivhi3 (HItype, HItype);
235 +static UHItype udivmodhi4(UHItype, UHItype, word_type);
237 +static UHItype
238 +udivmodhi4(UHItype num, UHItype den, word_type modwanted)
240 + UHItype bit = 1;
241 + UHItype res = 0;
243 + while (den < num && bit && !(den & (1L<<15)))
245 + den <<=1;
246 + bit <<=1;
248 + while (bit)
250 + if (num >= den)
252 + num -= den;
253 + res |= bit;
255 + bit >>=1;
256 + den >>=1;
258 + if (modwanted) return num;
259 + return res;
263 +HItype
264 +__divhi3 (HItype a, HItype b)
266 + word_type neg = 0;
267 + HItype res;
269 + if (a < 0)
271 + a = -a;
272 + neg = !neg;
275 + if (b < 0)
277 + b = -b;
278 + neg = !neg;
281 + res = udivmodhi4 (a, b, 0);
283 + if (neg)
284 + res = -res;
286 + return res;
290 +HItype
291 +__modhi3 (HItype a, HItype b)
293 + word_type neg = 0;
294 + HItype res;
296 + if (a < 0)
298 + a = -a;
299 + neg = 1;
302 + if (b < 0)
303 + b = -b;
305 + res = udivmodhi4 (a, b, 1);
307 + if (neg)
308 + res = -res;
310 + return res;
314 +HItype
315 +__udivhi3 (HItype a, HItype b)
317 + return udivmodhi4 (a, b, 0);
321 +HItype
322 +__umodhi3 (HItype a, HItype b)
324 + return udivmodhi4 (a, b, 1);
327 --- gcc-3.4.3/gcc/config/nios2/lib2-divmod.c
328 +++ gcc-3.4.3-nios2/gcc/config/nios2/lib2-divmod.c
329 @@ -0,0 +1,126 @@
331 +/* We include auto-host.h here to get HAVE_GAS_HIDDEN. This is
332 + supposedly valid even though this is a "target" file. */
333 +#include "auto-host.h"
336 +#include "tconfig.h"
337 +#include "tsystem.h"
338 +#include "coretypes.h"
339 +#include "tm.h"
342 +/* Don't use `fancy_abort' here even if config.h says to use it. */
343 +#ifdef abort
344 +#undef abort
345 +#endif
348 +#ifdef HAVE_GAS_HIDDEN
349 +#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden")))
350 +#else
351 +#define ATTRIBUTE_HIDDEN
352 +#endif
354 +#include "libgcc2.h"
356 +extern SItype __modsi3 (SItype, SItype);
357 +extern SItype __divsi3 (SItype, SItype);
358 +extern SItype __umodsi3 (SItype, SItype);
359 +extern SItype __udivsi3 (SItype, SItype);
361 +static USItype udivmodsi4(USItype, USItype, word_type);
363 +/* 16-bit SI divide and modulo as used in NIOS */
366 +static USItype
367 +udivmodsi4(USItype num, USItype den, word_type modwanted)
369 + USItype bit = 1;
370 + USItype res = 0;
372 + while (den < num && bit && !(den & (1L<<31)))
374 + den <<=1;
375 + bit <<=1;
377 + while (bit)
379 + if (num >= den)
381 + num -= den;
382 + res |= bit;
384 + bit >>=1;
385 + den >>=1;
387 + if (modwanted) return num;
388 + return res;
392 +SItype
393 +__divsi3 (SItype a, SItype b)
395 + word_type neg = 0;
396 + SItype res;
398 + if (a < 0)
400 + a = -a;
401 + neg = !neg;
404 + if (b < 0)
406 + b = -b;
407 + neg = !neg;
410 + res = udivmodsi4 (a, b, 0);
412 + if (neg)
413 + res = -res;
415 + return res;
419 +SItype
420 +__modsi3 (SItype a, SItype b)
422 + word_type neg = 0;
423 + SItype res;
425 + if (a < 0)
427 + a = -a;
428 + neg = 1;
431 + if (b < 0)
432 + b = -b;
434 + res = udivmodsi4 (a, b, 1);
436 + if (neg)
437 + res = -res;
439 + return res;
443 +SItype
444 +__udivsi3 (SItype a, SItype b)
446 + return udivmodsi4 (a, b, 0);
450 +SItype
451 +__umodsi3 (SItype a, SItype b)
453 + return udivmodsi4 (a, b, 1);
456 --- gcc-3.4.3/gcc/config/nios2/lib2-divtable.c
457 +++ gcc-3.4.3-nios2/gcc/config/nios2/lib2-divtable.c
458 @@ -0,0 +1,46 @@
460 +/* We include auto-host.h here to get HAVE_GAS_HIDDEN. This is
461 + supposedly valid even though this is a "target" file. */
462 +#include "auto-host.h"
465 +#include "tconfig.h"
466 +#include "tsystem.h"
467 +#include "coretypes.h"
468 +#include "tm.h"
471 +/* Don't use `fancy_abort' here even if config.h says to use it. */
472 +#ifdef abort
473 +#undef abort
474 +#endif
477 +#ifdef HAVE_GAS_HIDDEN
478 +#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden")))
479 +#else
480 +#define ATTRIBUTE_HIDDEN
481 +#endif
483 +#include "libgcc2.h"
485 +UQItype __divsi3_table[] =
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
505 --- gcc-3.4.3/gcc/config/nios2/lib2-mul.c
506 +++ gcc-3.4.3-nios2/gcc/config/nios2/lib2-mul.c
507 @@ -0,0 +1,103 @@
508 +/* while we are debugging (ie compile outside of gcc build)
509 + disable gcc specific headers */
510 +#ifndef DEBUG_MULSI3
513 +/* We include auto-host.h here to get HAVE_GAS_HIDDEN. This is
514 + supposedly valid even though this is a "target" file. */
515 +#include "auto-host.h"
518 +#include "tconfig.h"
519 +#include "tsystem.h"
520 +#include "coretypes.h"
521 +#include "tm.h"
524 +/* Don't use `fancy_abort' here even if config.h says to use it. */
525 +#ifdef abort
526 +#undef abort
527 +#endif
530 +#ifdef HAVE_GAS_HIDDEN
531 +#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden")))
532 +#else
533 +#define ATTRIBUTE_HIDDEN
534 +#endif
536 +#include "libgcc2.h"
538 +#else
539 +#define SItype int
540 +#define USItype unsigned int
541 +#endif
544 +extern SItype __mulsi3 (SItype, SItype);
546 +SItype
547 +__mulsi3 (SItype a, SItype b)
549 + SItype res = 0;
550 + USItype cnt = a;
552 + while (cnt)
554 + if (cnt & 1)
556 + res += b;
558 + b <<= 1;
559 + cnt >>= 1;
562 + return res;
565 +TODO: Choose best alternative implementation.
567 +SItype
568 +__divsi3 (SItype a, SItype b)
570 + SItype res = 0;
571 + USItype cnt = 0;
573 + while (cnt < 32)
575 + if (a & (1L << cnt))
577 + res += b;
579 + b <<= 1;
580 + cnt++;
583 + return res;
588 +#ifdef DEBUG_MULSI3
590 +int
591 +main ()
593 + int i, j;
594 + int error = 0;
596 + for (i = -1000; i < 1000; i++)
597 + for (j = -1000; j < 1000; j++)
599 + int expect = i * j;
600 + int actual = A__divsi3 (i, j);
601 + if (expect != actual)
603 + printf ("error: %d * %d = %d not %d\n", i, j, expect, actual);
604 + error = 1;
608 + return error;
610 +#endif
611 --- gcc-3.4.3/gcc/config/nios2/nios2-dp-bit.c
612 +++ gcc-3.4.3-nios2/gcc/config/nios2/nios2-dp-bit.c
613 @@ -0,0 +1,1652 @@
615 +/* This is a software floating point library which can be used
616 + for targets without hardware floating point.
617 + Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004
618 + Free Software Foundation, Inc.
620 +This file is free software; you can redistribute it and/or modify it
621 +under the terms of the GNU General Public License as published by the
622 +Free Software Foundation; either version 2, or (at your option) any
623 +later version.
625 +In addition to the permissions in the GNU General Public License, the
626 +Free Software Foundation gives you unlimited permission to link the
627 +compiled version of this file with other programs, and to distribute
628 +those programs without any restriction coming from the use of this
629 +file. (The General Public License restrictions do apply in other
630 +respects; for example, they cover modification of the file, and
631 +distribution when not linked into another program.)
633 +This file is distributed in the hope that it will be useful, but
634 +WITHOUT ANY WARRANTY; without even the implied warranty of
635 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
636 +General Public License for more details.
638 +You should have received a copy of the GNU General Public License
639 +along with this program; see the file COPYING. If not, write to
640 +the Free Software Foundation, 59 Temple Place - Suite 330,
641 +Boston, MA 02111-1307, USA. */
643 +/* As a special exception, if you link this library with other files,
644 + some of which are compiled with GCC, to produce an executable,
645 + this library does not by itself cause the resulting executable
646 + to be covered by the GNU General Public License.
647 + This exception does not however invalidate any other reasons why
648 + the executable file might be covered by the GNU General Public License. */
650 +/* This implements IEEE 754 format arithmetic, but does not provide a
651 + mechanism for setting the rounding mode, or for generating or handling
652 + exceptions.
654 + The original code by Steve Chamberlain, hacked by Mark Eichin and Jim
655 + Wilson, all of Cygnus Support. */
657 +/* The intended way to use this file is to make two copies, add `#define FLOAT'
658 + to one copy, then compile both copies and add them to libgcc.a. */
660 +#include "tconfig.h"
661 +#include "coretypes.h"
662 +#include "tm.h"
663 +#include "config/fp-bit.h"
665 +/* The following macros can be defined to change the behavior of this file:
666 + FLOAT: Implement a `float', aka SFmode, fp library. If this is not
667 + defined, then this file implements a `double', aka DFmode, fp library.
668 + FLOAT_ONLY: Used with FLOAT, to implement a `float' only library, i.e.
669 + don't include float->double conversion which requires the double library.
670 + This is useful only for machines which can't support doubles, e.g. some
671 + 8-bit processors.
672 + CMPtype: Specify the type that floating point compares should return.
673 + This defaults to SItype, aka int.
674 + US_SOFTWARE_GOFAST: This makes all entry points use the same names as the
675 + US Software goFast library.
676 + _DEBUG_BITFLOAT: This makes debugging the code a little easier, by adding
677 + two integers to the FLO_union_type.
678 + NO_DENORMALS: Disable handling of denormals.
679 + NO_NANS: Disable nan and infinity handling
680 + SMALL_MACHINE: Useful when operations on QIs and HIs are faster
681 + than on an SI */
683 +/* We don't currently support extended floats (long doubles) on machines
684 + without hardware to deal with them.
686 + These stubs are just to keep the linker from complaining about unresolved
687 + references which can be pulled in from libio & libstdc++, even if the
688 + user isn't using long doubles. However, they may generate an unresolved
689 + external to abort if abort is not used by the function, and the stubs
690 + are referenced from within libc, since libgcc goes before and after the
691 + system library. */
693 +#ifdef DECLARE_LIBRARY_RENAMES
694 + DECLARE_LIBRARY_RENAMES
695 +#endif
697 +#ifdef EXTENDED_FLOAT_STUBS
698 +extern void abort (void);
699 +void __extendsfxf2 (void) { abort(); }
700 +void __extenddfxf2 (void) { abort(); }
701 +void __truncxfdf2 (void) { abort(); }
702 +void __truncxfsf2 (void) { abort(); }
703 +void __fixxfsi (void) { abort(); }
704 +void __floatsixf (void) { abort(); }
705 +void __addxf3 (void) { abort(); }
706 +void __subxf3 (void) { abort(); }
707 +void __mulxf3 (void) { abort(); }
708 +void __divxf3 (void) { abort(); }
709 +void __negxf2 (void) { abort(); }
710 +void __eqxf2 (void) { abort(); }
711 +void __nexf2 (void) { abort(); }
712 +void __gtxf2 (void) { abort(); }
713 +void __gexf2 (void) { abort(); }
714 +void __lexf2 (void) { abort(); }
715 +void __ltxf2 (void) { abort(); }
717 +void __extendsftf2 (void) { abort(); }
718 +void __extenddftf2 (void) { abort(); }
719 +void __trunctfdf2 (void) { abort(); }
720 +void __trunctfsf2 (void) { abort(); }
721 +void __fixtfsi (void) { abort(); }
722 +void __floatsitf (void) { abort(); }
723 +void __addtf3 (void) { abort(); }
724 +void __subtf3 (void) { abort(); }
725 +void __multf3 (void) { abort(); }
726 +void __divtf3 (void) { abort(); }
727 +void __negtf2 (void) { abort(); }
728 +void __eqtf2 (void) { abort(); }
729 +void __netf2 (void) { abort(); }
730 +void __gttf2 (void) { abort(); }
731 +void __getf2 (void) { abort(); }
732 +void __letf2 (void) { abort(); }
733 +void __lttf2 (void) { abort(); }
734 +#else /* !EXTENDED_FLOAT_STUBS, rest of file */
736 +/* IEEE "special" number predicates */
738 +#ifdef NO_NANS
740 +#define nan() 0
741 +#define isnan(x) 0
742 +#define isinf(x) 0
743 +#else
745 +#if defined L_thenan_sf
746 +const fp_number_type __thenan_sf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
747 +#elif defined L_thenan_df
748 +const fp_number_type __thenan_df = { CLASS_SNAN, 0, 0, {(fractype) 0} };
749 +#elif defined L_thenan_tf
750 +const fp_number_type __thenan_tf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
751 +#elif defined TFLOAT
752 +extern const fp_number_type __thenan_tf;
753 +#elif defined FLOAT
754 +extern const fp_number_type __thenan_sf;
755 +#else
756 +extern const fp_number_type __thenan_df;
757 +#endif
759 +INLINE
760 +static fp_number_type *
761 +nan (void)
763 + /* Discard the const qualifier... */
764 +#ifdef TFLOAT
765 + return (fp_number_type *) (& __thenan_tf);
766 +#elif defined FLOAT
767 + return (fp_number_type *) (& __thenan_sf);
768 +#else
769 + return (fp_number_type *) (& __thenan_df);
770 +#endif
773 +INLINE
774 +static int
775 +isnan ( fp_number_type * x)
777 + return x->class == CLASS_SNAN || x->class == CLASS_QNAN;
780 +INLINE
781 +static int
782 +isinf ( fp_number_type * x)
784 + return x->class == CLASS_INFINITY;
787 +#endif /* NO_NANS */
789 +INLINE
790 +static int
791 +iszero ( fp_number_type * x)
793 + return x->class == CLASS_ZERO;
796 +INLINE
797 +static void
798 +flip_sign ( fp_number_type * x)
800 + x->sign = !x->sign;
803 +extern FLO_type pack_d ( fp_number_type * );
805 +#if defined(L_pack_df) || defined(L_pack_sf) || defined(L_pack_tf)
806 +FLO_type
807 +pack_d ( fp_number_type * src)
809 + FLO_union_type dst;
810 + fractype fraction = src->fraction.ll; /* wasn't unsigned before? */
811 + int sign = src->sign;
812 + int exp = 0;
814 + if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && (isnan (src) || isinf (src)))
816 + /* We can't represent these values accurately. By using the
817 + largest possible magnitude, we guarantee that the conversion
818 + of infinity is at least as big as any finite number. */
819 + exp = EXPMAX;
820 + fraction = ((fractype) 1 << FRACBITS) - 1;
822 + else if (isnan (src))
824 + exp = EXPMAX;
825 + if (src->class == CLASS_QNAN || 1)
827 +#ifdef QUIET_NAN_NEGATED
828 + fraction |= QUIET_NAN - 1;
829 +#else
830 + fraction |= QUIET_NAN;
831 +#endif
834 + else if (isinf (src))
836 + exp = EXPMAX;
837 + fraction = 0;
839 + else if (iszero (src))
841 + exp = 0;
842 + fraction = 0;
844 + else if (fraction == 0)
846 + exp = 0;
848 + else
850 + if (src->normal_exp < NORMAL_EXPMIN)
852 +#ifdef NO_DENORMALS
853 + /* Go straight to a zero representation if denormals are not
854 + supported. The denormal handling would be harmless but
855 + isn't unnecessary. */
856 + exp = 0;
857 + fraction = 0;
858 +#else /* NO_DENORMALS */
859 + /* This number's exponent is too low to fit into the bits
860 + available in the number, so we'll store 0 in the exponent and
861 + shift the fraction to the right to make up for it. */
863 + int shift = NORMAL_EXPMIN - src->normal_exp;
865 + exp = 0;
867 + if (shift > FRAC_NBITS - NGARDS)
869 + /* No point shifting, since it's more that 64 out. */
870 + fraction = 0;
872 + else
874 + int lowbit = (fraction & (((fractype)1 << shift) - 1)) ? 1 : 0;
875 + fraction = (fraction >> shift) | lowbit;
877 + if ((fraction & GARDMASK) == GARDMSB)
879 + if ((fraction & (1 << NGARDS)))
880 + fraction += GARDROUND + 1;
882 + else
884 + /* Add to the guards to round up. */
885 + fraction += GARDROUND;
887 + /* Perhaps the rounding means we now need to change the
888 + exponent, because the fraction is no longer denormal. */
889 + if (fraction >= IMPLICIT_1)
891 + exp += 1;
893 + fraction >>= NGARDS;
894 +#endif /* NO_DENORMALS */
896 + else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS)
897 + && src->normal_exp > EXPBIAS)
899 + exp = EXPMAX;
900 + fraction = 0;
902 + else
904 + exp = src->normal_exp + EXPBIAS;
905 + if (!ROUND_TOWARDS_ZERO)
907 + /* IF the gard bits are the all zero, but the first, then we're
908 + half way between two numbers, choose the one which makes the
909 + lsb of the answer 0. */
910 + if ((fraction & GARDMASK) == GARDMSB)
912 + if (fraction & (1 << NGARDS))
913 + fraction += GARDROUND + 1;
915 + else
917 + /* Add a one to the guards to round up */
918 + fraction += GARDROUND;
920 + if (fraction >= IMPLICIT_2)
922 + fraction >>= 1;
923 + exp += 1;
926 + fraction >>= NGARDS;
928 + if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp > EXPMAX)
930 + /* Saturate on overflow. */
931 + exp = EXPMAX;
932 + fraction = ((fractype) 1 << FRACBITS) - 1;
937 + /* We previously used bitfields to store the number, but this doesn't
938 + handle little/big endian systems conveniently, so use shifts and
939 + masks */
940 +#ifdef FLOAT_BIT_ORDER_MISMATCH
941 + dst.bits.fraction = fraction;
942 + dst.bits.exp = exp;
943 + dst.bits.sign = sign;
944 +#else
945 +# if defined TFLOAT && defined HALFFRACBITS
947 + halffractype high, low, unity;
948 + int lowsign, lowexp;
950 + unity = (halffractype) 1 << HALFFRACBITS;
952 + /* Set HIGH to the high double's significand, masking out the implicit 1.
953 + Set LOW to the low double's full significand. */
954 + high = (fraction >> (FRACBITS - HALFFRACBITS)) & (unity - 1);
955 + low = fraction & (unity * 2 - 1);
957 + /* Get the initial sign and exponent of the low double. */
958 + lowexp = exp - HALFFRACBITS - 1;
959 + lowsign = sign;
961 + /* HIGH should be rounded like a normal double, making |LOW| <=
962 + 0.5 ULP of HIGH. Assume round-to-nearest. */
963 + if (exp < EXPMAX)
964 + if (low > unity || (low == unity && (high & 1) == 1))
966 + /* Round HIGH up and adjust LOW to match. */
967 + high++;
968 + if (high == unity)
970 + /* May make it infinite, but that's OK. */
971 + high = 0;
972 + exp++;
974 + low = unity * 2 - low;
975 + lowsign ^= 1;
978 + high |= (halffractype) exp << HALFFRACBITS;
979 + high |= (halffractype) sign << (HALFFRACBITS + EXPBITS);
981 + if (exp == EXPMAX || exp == 0 || low == 0)
982 + low = 0;
983 + else
985 + while (lowexp > 0 && low < unity)
987 + low <<= 1;
988 + lowexp--;
991 + if (lowexp <= 0)
993 + halffractype roundmsb, round;
994 + int shift;
996 + shift = 1 - lowexp;
997 + roundmsb = (1 << (shift - 1));
998 + round = low & ((roundmsb << 1) - 1);
1000 + low >>= shift;
1001 + lowexp = 0;
1003 + if (round > roundmsb || (round == roundmsb && (low & 1) == 1))
1005 + low++;
1006 + if (low == unity)
1007 + /* LOW rounds up to the smallest normal number. */
1008 + lowexp++;
1012 + low &= unity - 1;
1013 + low |= (halffractype) lowexp << HALFFRACBITS;
1014 + low |= (halffractype) lowsign << (HALFFRACBITS + EXPBITS);
1016 + dst.value_raw = ((fractype) high << HALFSHIFT) | low;
1018 +# else
1019 + dst.value_raw = fraction & ((((fractype)1) << FRACBITS) - (fractype)1);
1020 + dst.value_raw |= ((fractype) (exp & ((1 << EXPBITS) - 1))) << FRACBITS;
1021 + dst.value_raw |= ((fractype) (sign & 1)) << (FRACBITS | EXPBITS);
1022 +# endif
1023 +#endif
1025 +#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
1026 +#ifdef TFLOAT
1028 + qrtrfractype tmp1 = dst.words[0];
1029 + qrtrfractype tmp2 = dst.words[1];
1030 + dst.words[0] = dst.words[3];
1031 + dst.words[1] = dst.words[2];
1032 + dst.words[2] = tmp2;
1033 + dst.words[3] = tmp1;
1035 +#else
1037 + halffractype tmp = dst.words[0];
1038 + dst.words[0] = dst.words[1];
1039 + dst.words[1] = tmp;
1041 +#endif
1042 +#endif
1044 + return dst.value;
1046 +#endif
1048 +#if defined(L_unpack_df) || defined(L_unpack_sf) || defined(L_unpack_tf)
1049 +void
1050 +unpack_d (FLO_union_type * src, fp_number_type * dst)
1052 + /* We previously used bitfields to store the number, but this doesn't
1053 + handle little/big endian systems conveniently, so use shifts and
1054 + masks */
1055 + fractype fraction;
1056 + int exp;
1057 + int sign;
1059 +#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
1060 + FLO_union_type swapped;
1062 +#ifdef TFLOAT
1063 + swapped.words[0] = src->words[3];
1064 + swapped.words[1] = src->words[2];
1065 + swapped.words[2] = src->words[1];
1066 + swapped.words[3] = src->words[0];
1067 +#else
1068 + swapped.words[0] = src->words[1];
1069 + swapped.words[1] = src->words[0];
1070 +#endif
1071 + src = &swapped;
1072 +#endif
1074 +#ifdef FLOAT_BIT_ORDER_MISMATCH
1075 + fraction = src->bits.fraction;
1076 + exp = src->bits.exp;
1077 + sign = src->bits.sign;
1078 +#else
1079 +# if defined TFLOAT && defined HALFFRACBITS
1081 + halffractype high, low;
1083 + high = src->value_raw >> HALFSHIFT;
1084 + low = src->value_raw & (((fractype)1 << HALFSHIFT) - 1);
1086 + fraction = high & ((((fractype)1) << HALFFRACBITS) - 1);
1087 + fraction <<= FRACBITS - HALFFRACBITS;
1088 + exp = ((int)(high >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
1089 + sign = ((int)(high >> (((HALFFRACBITS + EXPBITS))))) & 1;
1091 + if (exp != EXPMAX && exp != 0 && low != 0)
1093 + int lowexp = ((int)(low >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
1094 + int lowsign = ((int)(low >> (((HALFFRACBITS + EXPBITS))))) & 1;
1095 + int shift;
1096 + fractype xlow;
1098 + xlow = low & ((((fractype)1) << HALFFRACBITS) - 1);
1099 + if (lowexp)
1100 + xlow |= (((halffractype)1) << HALFFRACBITS);
1101 + else
1102 + lowexp = 1;
1103 + shift = (FRACBITS - HALFFRACBITS) - (exp - lowexp);
1104 + if (shift > 0)
1105 + xlow <<= shift;
1106 + else if (shift < 0)
1107 + xlow >>= -shift;
1108 + if (sign == lowsign)
1109 + fraction += xlow;
1110 + else if (fraction >= xlow)
1111 + fraction -= xlow;
1112 + else
1114 + /* The high part is a power of two but the full number is lower.
1115 + This code will leave the implicit 1 in FRACTION, but we'd
1116 + have added that below anyway. */
1117 + fraction = (((fractype) 1 << FRACBITS) - xlow) << 1;
1118 + exp--;
1122 +# else
1123 + fraction = src->value_raw & ((((fractype)1) << FRACBITS) - 1);
1124 + exp = ((int)(src->value_raw >> FRACBITS)) & ((1 << EXPBITS) - 1);
1125 + sign = ((int)(src->value_raw >> (FRACBITS + EXPBITS))) & 1;
1126 +# endif
1127 +#endif
1129 + dst->sign = sign;
1130 + if (exp == 0)
1132 + /* Hmm. Looks like 0 */
1133 + if (fraction == 0
1134 +#ifdef NO_DENORMALS
1135 + || 1
1136 +#endif
1139 + /* tastes like zero */
1140 + dst->class = CLASS_ZERO;
1142 + else
1144 + /* Zero exponent with nonzero fraction - it's denormalized,
1145 + so there isn't a leading implicit one - we'll shift it so
1146 + it gets one. */
1147 + dst->normal_exp = exp - EXPBIAS + 1;
1148 + fraction <<= NGARDS;
1150 + dst->class = CLASS_NUMBER;
1151 +#if 1
1152 + while (fraction < IMPLICIT_1)
1154 + fraction <<= 1;
1155 + dst->normal_exp--;
1157 +#endif
1158 + dst->fraction.ll = fraction;
1161 + else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp == EXPMAX)
1163 + /* Huge exponent*/
1164 + if (fraction == 0)
1166 + /* Attached to a zero fraction - means infinity */
1167 + dst->class = CLASS_INFINITY;
1169 + else
1171 + /* Nonzero fraction, means nan */
1172 +#ifdef QUIET_NAN_NEGATED
1173 + if ((fraction & QUIET_NAN) == 0)
1174 +#else
1175 + if (fraction & QUIET_NAN)
1176 +#endif
1178 + dst->class = CLASS_QNAN;
1180 + else
1182 + dst->class = CLASS_SNAN;
1184 + /* Keep the fraction part as the nan number */
1185 + dst->fraction.ll = fraction;
1188 + else
1190 + /* Nothing strange about this number */
1191 + dst->normal_exp = exp - EXPBIAS;
1192 + dst->class = CLASS_NUMBER;
1193 + dst->fraction.ll = (fraction << NGARDS) | IMPLICIT_1;
1196 +#endif /* L_unpack_df || L_unpack_sf */
1198 +#if defined(L_addsub_sf) || defined(L_addsub_df) || defined(L_addsub_tf)
1199 +static fp_number_type *
1200 +_fpadd_parts (fp_number_type * a,
1201 + fp_number_type * b,
1202 + fp_number_type * tmp)
1204 + intfrac tfraction;
1206 + /* Put commonly used fields in local variables. */
1207 + int a_normal_exp;
1208 + int b_normal_exp;
1209 + fractype a_fraction;
1210 + fractype b_fraction;
1212 + if (isnan (a))
1214 + return a;
1216 + if (isnan (b))
1218 + return b;
1220 + if (isinf (a))
1222 + /* Adding infinities with opposite signs yields a NaN. */
1223 + if (isinf (b) && a->sign != b->sign)
1224 + return nan ();
1225 + return a;
1227 + if (isinf (b))
1229 + return b;
1231 + if (iszero (b))
1233 + if (iszero (a))
1235 + *tmp = *a;
1236 + tmp->sign = a->sign & b->sign;
1237 + return tmp;
1239 + return a;
1241 + if (iszero (a))
1243 + return b;
1246 + /* Got two numbers. shift the smaller and increment the exponent till
1247 + they're the same */
1249 + int diff;
1251 + a_normal_exp = a->normal_exp;
1252 + b_normal_exp = b->normal_exp;
1253 + a_fraction = a->fraction.ll;
1254 + b_fraction = b->fraction.ll;
1256 + diff = a_normal_exp - b_normal_exp;
1258 + if (diff < 0)
1259 + diff = -diff;
1260 + if (diff < FRAC_NBITS)
1262 + /* ??? This does shifts one bit at a time. Optimize. */
1263 + while (a_normal_exp > b_normal_exp)
1265 + b_normal_exp++;
1266 + LSHIFT (b_fraction);
1268 + while (b_normal_exp > a_normal_exp)
1270 + a_normal_exp++;
1271 + LSHIFT (a_fraction);
1274 + else
1276 + /* Somethings's up.. choose the biggest */
1277 + if (a_normal_exp > b_normal_exp)
1279 + b_normal_exp = a_normal_exp;
1280 + b_fraction = 0;
1282 + else
1284 + a_normal_exp = b_normal_exp;
1285 + a_fraction = 0;
1290 + if (a->sign != b->sign)
1292 + if (a->sign)
1294 + tfraction = -a_fraction + b_fraction;
1296 + else
1298 + tfraction = a_fraction - b_fraction;
1300 + if (tfraction >= 0)
1302 + tmp->sign = 0;
1303 + tmp->normal_exp = a_normal_exp;
1304 + tmp->fraction.ll = tfraction;
1306 + else
1308 + tmp->sign = 1;
1309 + tmp->normal_exp = a_normal_exp;
1310 + tmp->fraction.ll = -tfraction;
1312 + /* and renormalize it */
1314 + while (tmp->fraction.ll < IMPLICIT_1 && tmp->fraction.ll)
1316 + tmp->fraction.ll <<= 1;
1317 + tmp->normal_exp--;
1320 + else
1322 + tmp->sign = a->sign;
1323 + tmp->normal_exp = a_normal_exp;
1324 + tmp->fraction.ll = a_fraction + b_fraction;
1326 + tmp->class = CLASS_NUMBER;
1327 + /* Now the fraction is added, we have to shift down to renormalize the
1328 + number */
1330 + if (tmp->fraction.ll >= IMPLICIT_2)
1332 + LSHIFT (tmp->fraction.ll);
1333 + tmp->normal_exp++;
1335 + return tmp;
1339 +FLO_type
1340 +add (FLO_type arg_a, FLO_type arg_b)
1342 + fp_number_type a;
1343 + fp_number_type b;
1344 + fp_number_type tmp;
1345 + fp_number_type *res;
1346 + FLO_union_type au, bu;
1348 + au.value = arg_a;
1349 + bu.value = arg_b;
1351 + unpack_d (&au, &a);
1352 + unpack_d (&bu, &b);
1354 + res = _fpadd_parts (&a, &b, &tmp);
1356 + return pack_d (res);
1359 +FLO_type
1360 +sub (FLO_type arg_a, FLO_type arg_b)
1362 + fp_number_type a;
1363 + fp_number_type b;
1364 + fp_number_type tmp;
1365 + fp_number_type *res;
1366 + FLO_union_type au, bu;
1368 + au.value = arg_a;
1369 + bu.value = arg_b;
1371 + unpack_d (&au, &a);
1372 + unpack_d (&bu, &b);
1374 + b.sign ^= 1;
1376 + res = _fpadd_parts (&a, &b, &tmp);
1378 + return pack_d (res);
1380 +#endif /* L_addsub_sf || L_addsub_df */
1382 +#if defined(L_mul_sf) || defined(L_mul_df) || defined(L_mul_tf)
1383 +static inline __attribute__ ((__always_inline__)) fp_number_type *
1384 +_fpmul_parts ( fp_number_type * a,
1385 + fp_number_type * b,
1386 + fp_number_type * tmp)
1388 + fractype low = 0;
1389 + fractype high = 0;
1391 + if (isnan (a))
1393 + a->sign = a->sign != b->sign;
1394 + return a;
1396 + if (isnan (b))
1398 + b->sign = a->sign != b->sign;
1399 + return b;
1401 + if (isinf (a))
1403 + if (iszero (b))
1404 + return nan ();
1405 + a->sign = a->sign != b->sign;
1406 + return a;
1408 + if (isinf (b))
1410 + if (iszero (a))
1412 + return nan ();
1414 + b->sign = a->sign != b->sign;
1415 + return b;
1417 + if (iszero (a))
1419 + a->sign = a->sign != b->sign;
1420 + return a;
1422 + if (iszero (b))
1424 + b->sign = a->sign != b->sign;
1425 + return b;
1428 + /* Calculate the mantissa by multiplying both numbers to get a
1429 + twice-as-wide number. */
1431 +#if defined(NO_DI_MODE) || defined(TFLOAT)
1433 + fractype x = a->fraction.ll;
1434 + fractype ylow = b->fraction.ll;
1435 + fractype yhigh = 0;
1436 + int bit;
1438 + /* ??? This does multiplies one bit at a time. Optimize. */
1439 + for (bit = 0; bit < FRAC_NBITS; bit++)
1441 + int carry;
1443 + if (x & 1)
1445 + carry = (low += ylow) < ylow;
1446 + high += yhigh + carry;
1448 + yhigh <<= 1;
1449 + if (ylow & FRACHIGH)
1451 + yhigh |= 1;
1453 + ylow <<= 1;
1454 + x >>= 1;
1457 +#elif defined(FLOAT)
1458 + /* Multiplying two USIs to get a UDI, we're safe. */
1460 + UDItype answer = (UDItype)a->fraction.ll * (UDItype)b->fraction.ll;
1462 + high = answer >> BITS_PER_SI;
1463 + low = answer;
1465 +#else
1466 + /* fractype is DImode, but we need the result to be twice as wide.
1467 + Assuming a widening multiply from DImode to TImode is not
1468 + available, build one by hand. */
1470 + USItype nl = a->fraction.ll;
1471 + USItype nh = a->fraction.ll >> BITS_PER_SI;
1472 + USItype ml = b->fraction.ll;
1473 + USItype mh = b->fraction.ll >> BITS_PER_SI;
1474 + UDItype pp_ll = (UDItype) ml * nl;
1475 + UDItype pp_hl = (UDItype) mh * nl;
1476 + UDItype pp_lh = (UDItype) ml * nh;
1477 + UDItype pp_hh = (UDItype) mh * nh;
1478 + UDItype res2 = 0;
1479 + UDItype res0 = 0;
1480 + UDItype ps_hh__ = pp_hl + pp_lh;
1481 + if (ps_hh__ < pp_hl)
1482 + res2 += (UDItype)1 << BITS_PER_SI;
1483 + pp_hl = (UDItype)(USItype)ps_hh__ << BITS_PER_SI;
1484 + res0 = pp_ll + pp_hl;
1485 + if (res0 < pp_ll)
1486 + res2++;
1487 + res2 += (ps_hh__ >> BITS_PER_SI) + pp_hh;
1488 + high = res2;
1489 + low = res0;
1491 +#endif
1494 + tmp->normal_exp = a->normal_exp + b->normal_exp
1495 + + FRAC_NBITS - (FRACBITS + NGARDS);
1496 + tmp->sign = a->sign != b->sign;
1497 + while (high >= IMPLICIT_2)
1499 + tmp->normal_exp++;
1500 + if (high & 1)
1502 + low >>= 1;
1503 + low |= FRACHIGH;
1505 + high >>= 1;
1507 + while (high < IMPLICIT_1)
1509 + tmp->normal_exp--;
1511 + high <<= 1;
1512 + if (low & FRACHIGH)
1513 + high |= 1;
1514 + low <<= 1;
1516 + /* rounding is tricky. if we only round if it won't make us round later. */
1517 +#if 0
1518 + if (low & FRACHIGH2)
1520 + if (((high & GARDMASK) != GARDMSB)
1521 + && (((high + 1) & GARDMASK) == GARDMSB))
1523 + /* don't round, it gets done again later. */
1525 + else
1527 + high++;
1530 +#endif
1531 + if (!ROUND_TOWARDS_ZERO && (high & GARDMASK) == GARDMSB)
1533 + if (high & (1 << NGARDS))
1535 + /* half way, so round to even */
1536 + high += GARDROUND + 1;
1538 + else if (low)
1540 + /* but we really weren't half way */
1541 + high += GARDROUND + 1;
1544 + tmp->fraction.ll = high;
1545 + tmp->class = CLASS_NUMBER;
1546 + return tmp;
1549 +FLO_type
1550 +multiply (FLO_type arg_a, FLO_type arg_b)
1552 + fp_number_type a;
1553 + fp_number_type b;
1554 + fp_number_type tmp;
1555 + fp_number_type *res;
1556 + FLO_union_type au, bu;
1558 + au.value = arg_a;
1559 + bu.value = arg_b;
1561 + unpack_d (&au, &a);
1562 + unpack_d (&bu, &b);
1564 + res = _fpmul_parts (&a, &b, &tmp);
1566 + return pack_d (res);
1568 +#endif /* L_mul_sf || L_mul_df */
1570 +#if defined(L_div_sf) || defined(L_div_df) || defined(L_div_tf)
1571 +static inline __attribute__ ((__always_inline__)) fp_number_type *
1572 +_fpdiv_parts (fp_number_type * a,
1573 + fp_number_type * b)
1575 + fractype bit;
1576 + fractype numerator;
1577 + fractype denominator;
1578 + fractype quotient;
1580 + if (isnan (a))
1582 + return a;
1584 + if (isnan (b))
1586 + return b;
1589 + a->sign = a->sign ^ b->sign;
1591 + if (isinf (a) || iszero (a))
1593 + if (a->class == b->class)
1594 + return nan ();
1595 + return a;
1598 + if (isinf (b))
1600 + a->fraction.ll = 0;
1601 + a->normal_exp = 0;
1602 + return a;
1604 + if (iszero (b))
1606 + a->class = CLASS_INFINITY;
1607 + return a;
1610 + /* Calculate the mantissa by multiplying both 64bit numbers to get a
1611 + 128 bit number */
1613 + /* quotient =
1614 + ( numerator / denominator) * 2^(numerator exponent - denominator exponent)
1615 + */
1617 + a->normal_exp = a->normal_exp - b->normal_exp;
1618 + numerator = a->fraction.ll;
1619 + denominator = b->fraction.ll;
1621 + if (numerator < denominator)
1623 + /* Fraction will be less than 1.0 */
1624 + numerator *= 2;
1625 + a->normal_exp--;
1627 + bit = IMPLICIT_1;
1628 + quotient = 0;
1629 + /* ??? Does divide one bit at a time. Optimize. */
1630 + while (bit)
1632 + if (numerator >= denominator)
1634 + quotient |= bit;
1635 + numerator -= denominator;
1637 + bit >>= 1;
1638 + numerator *= 2;
1641 + if (!ROUND_TOWARDS_ZERO && (quotient & GARDMASK) == GARDMSB)
1643 + if (quotient & (1 << NGARDS))
1645 + /* half way, so round to even */
1646 + quotient += GARDROUND + 1;
1648 + else if (numerator)
1650 + /* but we really weren't half way, more bits exist */
1651 + quotient += GARDROUND + 1;
1655 + a->fraction.ll = quotient;
1656 + return (a);
1660 +FLO_type
1661 +divide (FLO_type arg_a, FLO_type arg_b)
1663 + fp_number_type a;
1664 + fp_number_type b;
1665 + fp_number_type *res;
1666 + FLO_union_type au, bu;
1668 + au.value = arg_a;
1669 + bu.value = arg_b;
1671 + unpack_d (&au, &a);
1672 + unpack_d (&bu, &b);
1674 + res = _fpdiv_parts (&a, &b);
1676 + return pack_d (res);
1678 +#endif /* L_div_sf || L_div_df */
1680 +#if defined(L_fpcmp_parts_sf) || defined(L_fpcmp_parts_df) \
1681 + || defined(L_fpcmp_parts_tf)
1682 +/* according to the demo, fpcmp returns a comparison with 0... thus
1683 + a<b -> -1
1684 + a==b -> 0
1685 + a>b -> +1
1686 + */
1688 +int
1689 +__fpcmp_parts (fp_number_type * a, fp_number_type * b)
1691 +#if 0
1692 + /* either nan -> unordered. Must be checked outside of this routine. */
1693 + if (isnan (a) && isnan (b))
1695 + return 1; /* still unordered! */
1697 +#endif
1699 + if (isnan (a) || isnan (b))
1701 + return 1; /* how to indicate unordered compare? */
1703 + if (isinf (a) && isinf (b))
1705 + /* +inf > -inf, but +inf != +inf */
1706 + /* b \a| +inf(0)| -inf(1)
1707 + ______\+--------+--------
1708 + +inf(0)| a==b(0)| a<b(-1)
1709 + -------+--------+--------
1710 + -inf(1)| a>b(1) | a==b(0)
1711 + -------+--------+--------
1712 + So since unordered must be nonzero, just line up the columns...
1713 + */
1714 + return b->sign - a->sign;
1716 + /* but not both... */
1717 + if (isinf (a))
1719 + return a->sign ? -1 : 1;
1721 + if (isinf (b))
1723 + return b->sign ? 1 : -1;
1725 + if (iszero (a) && iszero (b))
1727 + return 0;
1729 + if (iszero (a))
1731 + return b->sign ? 1 : -1;
1733 + if (iszero (b))
1735 + return a->sign ? -1 : 1;
1737 + /* now both are "normal". */
1738 + if (a->sign != b->sign)
1740 + /* opposite signs */
1741 + return a->sign ? -1 : 1;
1743 + /* same sign; exponents? */
1744 + if (a->normal_exp > b->normal_exp)
1746 + return a->sign ? -1 : 1;
1748 + if (a->normal_exp < b->normal_exp)
1750 + return a->sign ? 1 : -1;
1752 + /* same exponents; check size. */
1753 + if (a->fraction.ll > b->fraction.ll)
1755 + return a->sign ? -1 : 1;
1757 + if (a->fraction.ll < b->fraction.ll)
1759 + return a->sign ? 1 : -1;
1761 + /* after all that, they're equal. */
1762 + return 0;
1764 +#endif
1766 +#if defined(L_compare_sf) || defined(L_compare_df) || defined(L_compoare_tf)
1767 +CMPtype
1768 +compare (FLO_type arg_a, FLO_type arg_b)
1770 + fp_number_type a;
1771 + fp_number_type b;
1772 + FLO_union_type au, bu;
1774 + au.value = arg_a;
1775 + bu.value = arg_b;
1777 + unpack_d (&au, &a);
1778 + unpack_d (&bu, &b);
1780 + return __fpcmp_parts (&a, &b);
1782 +#endif /* L_compare_sf || L_compare_df */
1784 +#ifndef US_SOFTWARE_GOFAST
1786 +/* These should be optimized for their specific tasks someday. */
1788 +#if defined(L_eq_sf) || defined(L_eq_df) || defined(L_eq_tf)
1789 +CMPtype
1790 +_eq_f2 (FLO_type arg_a, FLO_type arg_b)
1792 + fp_number_type a;
1793 + fp_number_type b;
1794 + FLO_union_type au, bu;
1796 + au.value = arg_a;
1797 + bu.value = arg_b;
1799 + unpack_d (&au, &a);
1800 + unpack_d (&bu, &b);
1802 + if (isnan (&a) || isnan (&b))
1803 + return 1; /* false, truth == 0 */
1805 + return __fpcmp_parts (&a, &b) ;
1807 +#endif /* L_eq_sf || L_eq_df */
1809 +#if defined(L_ne_sf) || defined(L_ne_df) || defined(L_ne_tf)
1810 +CMPtype
1811 +_ne_f2 (FLO_type arg_a, FLO_type arg_b)
1813 + fp_number_type a;
1814 + fp_number_type b;
1815 + FLO_union_type au, bu;
1817 + au.value = arg_a;
1818 + bu.value = arg_b;
1820 + unpack_d (&au, &a);
1821 + unpack_d (&bu, &b);
1823 + if (isnan (&a) || isnan (&b))
1824 + return 1; /* true, truth != 0 */
1826 + return __fpcmp_parts (&a, &b) ;
1828 +#endif /* L_ne_sf || L_ne_df */
1830 +#if defined(L_gt_sf) || defined(L_gt_df) || defined(L_gt_tf)
1831 +CMPtype
1832 +_gt_f2 (FLO_type arg_a, FLO_type arg_b)
1834 + fp_number_type a;
1835 + fp_number_type b;
1836 + FLO_union_type au, bu;
1838 + au.value = arg_a;
1839 + bu.value = arg_b;
1841 + unpack_d (&au, &a);
1842 + unpack_d (&bu, &b);
1844 + if (isnan (&a) || isnan (&b))
1845 + return -1; /* false, truth > 0 */
1847 + return __fpcmp_parts (&a, &b);
1849 +#endif /* L_gt_sf || L_gt_df */
1851 +#if defined(L_ge_sf) || defined(L_ge_df) || defined(L_ge_tf)
1852 +CMPtype
1853 +_ge_f2 (FLO_type arg_a, FLO_type arg_b)
1855 + fp_number_type a;
1856 + fp_number_type b;
1857 + FLO_union_type au, bu;
1859 + au.value = arg_a;
1860 + bu.value = arg_b;
1862 + unpack_d (&au, &a);
1863 + unpack_d (&bu, &b);
1865 + if (isnan (&a) || isnan (&b))
1866 + return -1; /* false, truth >= 0 */
1867 + return __fpcmp_parts (&a, &b) ;
1869 +#endif /* L_ge_sf || L_ge_df */
1871 +#if defined(L_lt_sf) || defined(L_lt_df) || defined(L_lt_tf)
1872 +CMPtype
1873 +_lt_f2 (FLO_type arg_a, FLO_type arg_b)
1875 + fp_number_type a;
1876 + fp_number_type b;
1877 + FLO_union_type au, bu;
1879 + au.value = arg_a;
1880 + bu.value = arg_b;
1882 + unpack_d (&au, &a);
1883 + unpack_d (&bu, &b);
1885 + if (isnan (&a) || isnan (&b))
1886 + return 1; /* false, truth < 0 */
1888 + return __fpcmp_parts (&a, &b);
1890 +#endif /* L_lt_sf || L_lt_df */
1892 +#if defined(L_le_sf) || defined(L_le_df) || defined(L_le_tf)
1893 +CMPtype
1894 +_le_f2 (FLO_type arg_a, FLO_type arg_b)
1896 + fp_number_type a;
1897 + fp_number_type b;
1898 + FLO_union_type au, bu;
1900 + au.value = arg_a;
1901 + bu.value = arg_b;
1903 + unpack_d (&au, &a);
1904 + unpack_d (&bu, &b);
1906 + if (isnan (&a) || isnan (&b))
1907 + return 1; /* false, truth <= 0 */
1909 + return __fpcmp_parts (&a, &b) ;
1911 +#endif /* L_le_sf || L_le_df */
1913 +#endif /* ! US_SOFTWARE_GOFAST */
1915 +#if defined(L_unord_sf) || defined(L_unord_df) || defined(L_unord_tf)
1916 +CMPtype
1917 +_unord_f2 (FLO_type arg_a, FLO_type arg_b)
1919 + fp_number_type a;
1920 + fp_number_type b;
1921 + FLO_union_type au, bu;
1923 + au.value = arg_a;
1924 + bu.value = arg_b;
1926 + unpack_d (&au, &a);
1927 + unpack_d (&bu, &b);
1929 + return (isnan (&a) || isnan (&b));
1931 +#endif /* L_unord_sf || L_unord_df */
1933 +#if defined(L_si_to_sf) || defined(L_si_to_df) || defined(L_si_to_tf)
1934 +FLO_type
1935 +si_to_float (SItype arg_a)
1937 + fp_number_type in;
1939 + in.class = CLASS_NUMBER;
1940 + in.sign = arg_a < 0;
1941 + if (!arg_a)
1943 + in.class = CLASS_ZERO;
1945 + else
1947 + in.normal_exp = FRACBITS + NGARDS;
1948 + if (in.sign)
1950 + /* Special case for minint, since there is no +ve integer
1951 + representation for it */
1952 + if (arg_a == (- MAX_SI_INT - 1))
1954 + return (FLO_type)(- MAX_SI_INT - 1);
1956 + in.fraction.ll = (-arg_a);
1958 + else
1959 + in.fraction.ll = arg_a;
1961 + while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
1963 + in.fraction.ll <<= 1;
1964 + in.normal_exp -= 1;
1967 + return pack_d (&in);
1969 +#endif /* L_si_to_sf || L_si_to_df */
1971 +#if defined(L_usi_to_sf) || defined(L_usi_to_df) || defined(L_usi_to_tf)
1972 +FLO_type
1973 +usi_to_float (USItype arg_a)
1975 + fp_number_type in;
1977 + in.sign = 0;
1978 + if (!arg_a)
1980 + in.class = CLASS_ZERO;
1982 + else
1984 + in.class = CLASS_NUMBER;
1985 + in.normal_exp = FRACBITS + NGARDS;
1986 + in.fraction.ll = arg_a;
1988 + while (in.fraction.ll > ((fractype)1 << (FRACBITS + NGARDS)))
1990 + in.fraction.ll >>= 1;
1991 + in.normal_exp += 1;
1993 + while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
1995 + in.fraction.ll <<= 1;
1996 + in.normal_exp -= 1;
1999 + return pack_d (&in);
2001 +#endif
2003 +#if defined(L_sf_to_si) || defined(L_df_to_si) || defined(L_tf_to_si)
2004 +SItype
2005 +float_to_si (FLO_type arg_a)
2007 + fp_number_type a;
2008 + SItype tmp;
2009 + FLO_union_type au;
2011 + au.value = arg_a;
2012 + unpack_d (&au, &a);
2014 + if (iszero (&a))
2015 + return 0;
2016 + if (isnan (&a))
2017 + return 0;
2018 + /* get reasonable MAX_SI_INT... */
2019 + if (isinf (&a))
2020 + return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
2021 + /* it is a number, but a small one */
2022 + if (a.normal_exp < 0)
2023 + return 0;
2024 + if (a.normal_exp > BITS_PER_SI - 2)
2025 + return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
2026 + tmp = a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
2027 + return a.sign ? (-tmp) : (tmp);
2029 +#endif /* L_sf_to_si || L_df_to_si */
2031 +#if defined(L_sf_to_usi) || defined(L_df_to_usi) || defined(L_tf_to_usi)
2032 +#if defined US_SOFTWARE_GOFAST || defined(L_tf_to_usi)
2033 +/* While libgcc2.c defines its own __fixunssfsi and __fixunsdfsi routines,
2034 + we also define them for GOFAST because the ones in libgcc2.c have the
2035 + wrong names and I'd rather define these here and keep GOFAST CYG-LOC's
2036 + out of libgcc2.c. We can't define these here if not GOFAST because then
2037 + there'd be duplicate copies. */
2039 +USItype
2040 +float_to_usi (FLO_type arg_a)
2042 + fp_number_type a;
2043 + FLO_union_type au;
2045 + au.value = arg_a;
2046 + unpack_d (&au, &a);
2048 + if (iszero (&a))
2049 + return 0;
2050 + if (isnan (&a))
2051 + return 0;
2052 + /* it is a negative number */
2053 + if (a.sign)
2054 + return 0;
2055 + /* get reasonable MAX_USI_INT... */
2056 + if (isinf (&a))
2057 + return MAX_USI_INT;
2058 + /* it is a number, but a small one */
2059 + if (a.normal_exp < 0)
2060 + return 0;
2061 + if (a.normal_exp > BITS_PER_SI - 1)
2062 + return MAX_USI_INT;
2063 + else if (a.normal_exp > (FRACBITS + NGARDS))
2064 + return a.fraction.ll << (a.normal_exp - (FRACBITS + NGARDS));
2065 + else
2066 + return a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
2068 +#endif /* US_SOFTWARE_GOFAST */
2069 +#endif /* L_sf_to_usi || L_df_to_usi */
2071 +#if defined(L_negate_sf) || defined(L_negate_df) || defined(L_negate_tf)
2072 +FLO_type
2073 +negate (FLO_type arg_a)
2075 + fp_number_type a;
2076 + FLO_union_type au;
2078 + au.value = arg_a;
2079 + unpack_d (&au, &a);
2081 + flip_sign (&a);
2082 + return pack_d (&a);
2084 +#endif /* L_negate_sf || L_negate_df */
2086 +#ifdef FLOAT
2088 +#if defined(L_make_sf)
2089 +SFtype
2090 +__make_fp(fp_class_type class,
2091 + unsigned int sign,
2092 + int exp,
2093 + USItype frac)
2095 + fp_number_type in;
2097 + in.class = class;
2098 + in.sign = sign;
2099 + in.normal_exp = exp;
2100 + in.fraction.ll = frac;
2101 + return pack_d (&in);
2103 +#endif /* L_make_sf */
2105 +#ifndef FLOAT_ONLY
2107 +/* This enables one to build an fp library that supports float but not double.
2108 + Otherwise, we would get an undefined reference to __make_dp.
2109 + This is needed for some 8-bit ports that can't handle well values that
2110 + are 8-bytes in size, so we just don't support double for them at all. */
2112 +#if defined(L_sf_to_df)
2113 +DFtype
2114 +sf_to_df (SFtype arg_a)
2116 + fp_number_type in;
2117 + FLO_union_type au;
2119 + au.value = arg_a;
2120 + unpack_d (&au, &in);
2122 + return __make_dp (in.class, in.sign, in.normal_exp,
2123 + ((UDItype) in.fraction.ll) << F_D_BITOFF);
2125 +#endif /* L_sf_to_df */
2127 +#if defined(L_sf_to_tf) && defined(TMODES)
2128 +TFtype
2129 +sf_to_tf (SFtype arg_a)
2131 + fp_number_type in;
2132 + FLO_union_type au;
2134 + au.value = arg_a;
2135 + unpack_d (&au, &in);
2137 + return __make_tp (in.class, in.sign, in.normal_exp,
2138 + ((UTItype) in.fraction.ll) << F_T_BITOFF);
2140 +#endif /* L_sf_to_df */
2142 +#endif /* ! FLOAT_ONLY */
2143 +#endif /* FLOAT */
2145 +#ifndef FLOAT
2147 +extern SFtype __make_fp (fp_class_type, unsigned int, int, USItype);
2149 +#if defined(L_make_df)
2150 +DFtype
2151 +__make_dp (fp_class_type class, unsigned int sign, int exp, UDItype frac)
2153 + fp_number_type in;
2155 + in.class = class;
2156 + in.sign = sign;
2157 + in.normal_exp = exp;
2158 + in.fraction.ll = frac;
2159 + return pack_d (&in);
2161 +#endif /* L_make_df */
2163 +#if defined(L_df_to_sf)
2164 +SFtype
2165 +df_to_sf (DFtype arg_a)
2167 + fp_number_type in;
2168 + USItype sffrac;
2169 + FLO_union_type au;
2171 + au.value = arg_a;
2172 + unpack_d (&au, &in);
2174 + sffrac = in.fraction.ll >> F_D_BITOFF;
2176 + /* We set the lowest guard bit in SFFRAC if we discarded any non
2177 + zero bits. */
2178 + if ((in.fraction.ll & (((USItype) 1 << F_D_BITOFF) - 1)) != 0)
2179 + sffrac |= 1;
2181 + return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
2183 +#endif /* L_df_to_sf */
2185 +#if defined(L_df_to_tf) && defined(TMODES) \
2186 + && !defined(FLOAT) && !defined(TFLOAT)
2187 +TFtype
2188 +df_to_tf (DFtype arg_a)
2190 + fp_number_type in;
2191 + FLO_union_type au;
2193 + au.value = arg_a;
2194 + unpack_d (&au, &in);
2196 + return __make_tp (in.class, in.sign, in.normal_exp,
2197 + ((UTItype) in.fraction.ll) << D_T_BITOFF);
2199 +#endif /* L_sf_to_df */
2201 +#ifdef TFLOAT
2202 +#if defined(L_make_tf)
2203 +TFtype
2204 +__make_tp(fp_class_type class,
2205 + unsigned int sign,
2206 + int exp,
2207 + UTItype frac)
2209 + fp_number_type in;
2211 + in.class = class;
2212 + in.sign = sign;
2213 + in.normal_exp = exp;
2214 + in.fraction.ll = frac;
2215 + return pack_d (&in);
2217 +#endif /* L_make_tf */
2219 +#if defined(L_tf_to_df)
2220 +DFtype
2221 +tf_to_df (TFtype arg_a)
2223 + fp_number_type in;
2224 + UDItype sffrac;
2225 + FLO_union_type au;
2227 + au.value = arg_a;
2228 + unpack_d (&au, &in);
2230 + sffrac = in.fraction.ll >> D_T_BITOFF;
2232 + /* We set the lowest guard bit in SFFRAC if we discarded any non
2233 + zero bits. */
2234 + if ((in.fraction.ll & (((UTItype) 1 << D_T_BITOFF) - 1)) != 0)
2235 + sffrac |= 1;
2237 + return __make_dp (in.class, in.sign, in.normal_exp, sffrac);
2239 +#endif /* L_tf_to_df */
2241 +#if defined(L_tf_to_sf)
2242 +SFtype
2243 +tf_to_sf (TFtype arg_a)
2245 + fp_number_type in;
2246 + USItype sffrac;
2247 + FLO_union_type au;
2249 + au.value = arg_a;
2250 + unpack_d (&au, &in);
2252 + sffrac = in.fraction.ll >> F_T_BITOFF;
2254 + /* We set the lowest guard bit in SFFRAC if we discarded any non
2255 + zero bits. */
2256 + if ((in.fraction.ll & (((UTItype) 1 << F_T_BITOFF) - 1)) != 0)
2257 + sffrac |= 1;
2259 + return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
2261 +#endif /* L_tf_to_sf */
2262 +#endif /* TFLOAT */
2264 +#endif /* ! FLOAT */
2265 +#endif /* !EXTENDED_FLOAT_STUBS */
2266 --- gcc-3.4.3/gcc/config/nios2/nios2-fp-bit.c
2267 +++ gcc-3.4.3-nios2/gcc/config/nios2/nios2-fp-bit.c
2268 @@ -0,0 +1,1652 @@
2269 +#define FLOAT
2270 +/* This is a software floating point library which can be used
2271 + for targets without hardware floating point.
2272 + Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004
2273 + Free Software Foundation, Inc.
2275 +This file is free software; you can redistribute it and/or modify it
2276 +under the terms of the GNU General Public License as published by the
2277 +Free Software Foundation; either version 2, or (at your option) any
2278 +later version.
2280 +In addition to the permissions in the GNU General Public License, the
2281 +Free Software Foundation gives you unlimited permission to link the
2282 +compiled version of this file with other programs, and to distribute
2283 +those programs without any restriction coming from the use of this
2284 +file. (The General Public License restrictions do apply in other
2285 +respects; for example, they cover modification of the file, and
2286 +distribution when not linked into another program.)
2288 +This file is distributed in the hope that it will be useful, but
2289 +WITHOUT ANY WARRANTY; without even the implied warranty of
2290 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2291 +General Public License for more details.
2293 +You should have received a copy of the GNU General Public License
2294 +along with this program; see the file COPYING. If not, write to
2295 +the Free Software Foundation, 59 Temple Place - Suite 330,
2296 +Boston, MA 02111-1307, USA. */
2298 +/* As a special exception, if you link this library with other files,
2299 + some of which are compiled with GCC, to produce an executable,
2300 + this library does not by itself cause the resulting executable
2301 + to be covered by the GNU General Public License.
2302 + This exception does not however invalidate any other reasons why
2303 + the executable file might be covered by the GNU General Public License. */
2305 +/* This implements IEEE 754 format arithmetic, but does not provide a
2306 + mechanism for setting the rounding mode, or for generating or handling
2307 + exceptions.
2309 + The original code by Steve Chamberlain, hacked by Mark Eichin and Jim
2310 + Wilson, all of Cygnus Support. */
2312 +/* The intended way to use this file is to make two copies, add `#define FLOAT'
2313 + to one copy, then compile both copies and add them to libgcc.a. */
2315 +#include "tconfig.h"
2316 +#include "coretypes.h"
2317 +#include "tm.h"
2318 +#include "config/fp-bit.h"
2320 +/* The following macros can be defined to change the behavior of this file:
2321 + FLOAT: Implement a `float', aka SFmode, fp library. If this is not
2322 + defined, then this file implements a `double', aka DFmode, fp library.
2323 + FLOAT_ONLY: Used with FLOAT, to implement a `float' only library, i.e.
2324 + don't include float->double conversion which requires the double library.
2325 + This is useful only for machines which can't support doubles, e.g. some
2326 + 8-bit processors.
2327 + CMPtype: Specify the type that floating point compares should return.
2328 + This defaults to SItype, aka int.
2329 + US_SOFTWARE_GOFAST: This makes all entry points use the same names as the
2330 + US Software goFast library.
2331 + _DEBUG_BITFLOAT: This makes debugging the code a little easier, by adding
2332 + two integers to the FLO_union_type.
2333 + NO_DENORMALS: Disable handling of denormals.
2334 + NO_NANS: Disable nan and infinity handling
2335 + SMALL_MACHINE: Useful when operations on QIs and HIs are faster
2336 + than on an SI */
2338 +/* We don't currently support extended floats (long doubles) on machines
2339 + without hardware to deal with them.
2341 + These stubs are just to keep the linker from complaining about unresolved
2342 + references which can be pulled in from libio & libstdc++, even if the
2343 + user isn't using long doubles. However, they may generate an unresolved
2344 + external to abort if abort is not used by the function, and the stubs
2345 + are referenced from within libc, since libgcc goes before and after the
2346 + system library. */
2348 +#ifdef DECLARE_LIBRARY_RENAMES
2349 + DECLARE_LIBRARY_RENAMES
2350 +#endif
2352 +#ifdef EXTENDED_FLOAT_STUBS
2353 +extern void abort (void);
2354 +void __extendsfxf2 (void) { abort(); }
2355 +void __extenddfxf2 (void) { abort(); }
2356 +void __truncxfdf2 (void) { abort(); }
2357 +void __truncxfsf2 (void) { abort(); }
2358 +void __fixxfsi (void) { abort(); }
2359 +void __floatsixf (void) { abort(); }
2360 +void __addxf3 (void) { abort(); }
2361 +void __subxf3 (void) { abort(); }
2362 +void __mulxf3 (void) { abort(); }
2363 +void __divxf3 (void) { abort(); }
2364 +void __negxf2 (void) { abort(); }
2365 +void __eqxf2 (void) { abort(); }
2366 +void __nexf2 (void) { abort(); }
2367 +void __gtxf2 (void) { abort(); }
2368 +void __gexf2 (void) { abort(); }
2369 +void __lexf2 (void) { abort(); }
2370 +void __ltxf2 (void) { abort(); }
2372 +void __extendsftf2 (void) { abort(); }
2373 +void __extenddftf2 (void) { abort(); }
2374 +void __trunctfdf2 (void) { abort(); }
2375 +void __trunctfsf2 (void) { abort(); }
2376 +void __fixtfsi (void) { abort(); }
2377 +void __floatsitf (void) { abort(); }
2378 +void __addtf3 (void) { abort(); }
2379 +void __subtf3 (void) { abort(); }
2380 +void __multf3 (void) { abort(); }
2381 +void __divtf3 (void) { abort(); }
2382 +void __negtf2 (void) { abort(); }
2383 +void __eqtf2 (void) { abort(); }
2384 +void __netf2 (void) { abort(); }
2385 +void __gttf2 (void) { abort(); }
2386 +void __getf2 (void) { abort(); }
2387 +void __letf2 (void) { abort(); }
2388 +void __lttf2 (void) { abort(); }
2389 +#else /* !EXTENDED_FLOAT_STUBS, rest of file */
2391 +/* IEEE "special" number predicates */
2393 +#ifdef NO_NANS
2395 +#define nan() 0
2396 +#define isnan(x) 0
2397 +#define isinf(x) 0
2398 +#else
2400 +#if defined L_thenan_sf
2401 +const fp_number_type __thenan_sf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
2402 +#elif defined L_thenan_df
2403 +const fp_number_type __thenan_df = { CLASS_SNAN, 0, 0, {(fractype) 0} };
2404 +#elif defined L_thenan_tf
2405 +const fp_number_type __thenan_tf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
2406 +#elif defined TFLOAT
2407 +extern const fp_number_type __thenan_tf;
2408 +#elif defined FLOAT
2409 +extern const fp_number_type __thenan_sf;
2410 +#else
2411 +extern const fp_number_type __thenan_df;
2412 +#endif
2414 +INLINE
2415 +static fp_number_type *
2416 +nan (void)
2418 + /* Discard the const qualifier... */
2419 +#ifdef TFLOAT
2420 + return (fp_number_type *) (& __thenan_tf);
2421 +#elif defined FLOAT
2422 + return (fp_number_type *) (& __thenan_sf);
2423 +#else
2424 + return (fp_number_type *) (& __thenan_df);
2425 +#endif
2428 +INLINE
2429 +static int
2430 +isnan ( fp_number_type * x)
2432 + return x->class == CLASS_SNAN || x->class == CLASS_QNAN;
2435 +INLINE
2436 +static int
2437 +isinf ( fp_number_type * x)
2439 + return x->class == CLASS_INFINITY;
2442 +#endif /* NO_NANS */
2444 +INLINE
2445 +static int
2446 +iszero ( fp_number_type * x)
2448 + return x->class == CLASS_ZERO;
2451 +INLINE
2452 +static void
2453 +flip_sign ( fp_number_type * x)
2455 + x->sign = !x->sign;
2458 +extern FLO_type pack_d ( fp_number_type * );
2460 +#if defined(L_pack_df) || defined(L_pack_sf) || defined(L_pack_tf)
2461 +FLO_type
2462 +pack_d ( fp_number_type * src)
2464 + FLO_union_type dst;
2465 + fractype fraction = src->fraction.ll; /* wasn't unsigned before? */
2466 + int sign = src->sign;
2467 + int exp = 0;
2469 + if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && (isnan (src) || isinf (src)))
2471 + /* We can't represent these values accurately. By using the
2472 + largest possible magnitude, we guarantee that the conversion
2473 + of infinity is at least as big as any finite number. */
2474 + exp = EXPMAX;
2475 + fraction = ((fractype) 1 << FRACBITS) - 1;
2477 + else if (isnan (src))
2479 + exp = EXPMAX;
2480 + if (src->class == CLASS_QNAN || 1)
2482 +#ifdef QUIET_NAN_NEGATED
2483 + fraction |= QUIET_NAN - 1;
2484 +#else
2485 + fraction |= QUIET_NAN;
2486 +#endif
2489 + else if (isinf (src))
2491 + exp = EXPMAX;
2492 + fraction = 0;
2494 + else if (iszero (src))
2496 + exp = 0;
2497 + fraction = 0;
2499 + else if (fraction == 0)
2501 + exp = 0;
2503 + else
2505 + if (src->normal_exp < NORMAL_EXPMIN)
2507 +#ifdef NO_DENORMALS
2508 + /* Go straight to a zero representation if denormals are not
2509 + supported. The denormal handling would be harmless but
2510 + isn't unnecessary. */
2511 + exp = 0;
2512 + fraction = 0;
2513 +#else /* NO_DENORMALS */
2514 + /* This number's exponent is too low to fit into the bits
2515 + available in the number, so we'll store 0 in the exponent and
2516 + shift the fraction to the right to make up for it. */
2518 + int shift = NORMAL_EXPMIN - src->normal_exp;
2520 + exp = 0;
2522 + if (shift > FRAC_NBITS - NGARDS)
2524 + /* No point shifting, since it's more that 64 out. */
2525 + fraction = 0;
2527 + else
2529 + int lowbit = (fraction & (((fractype)1 << shift) - 1)) ? 1 : 0;
2530 + fraction = (fraction >> shift) | lowbit;
2532 + if ((fraction & GARDMASK) == GARDMSB)
2534 + if ((fraction & (1 << NGARDS)))
2535 + fraction += GARDROUND + 1;
2537 + else
2539 + /* Add to the guards to round up. */
2540 + fraction += GARDROUND;
2542 + /* Perhaps the rounding means we now need to change the
2543 + exponent, because the fraction is no longer denormal. */
2544 + if (fraction >= IMPLICIT_1)
2546 + exp += 1;
2548 + fraction >>= NGARDS;
2549 +#endif /* NO_DENORMALS */
2551 + else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS)
2552 + && src->normal_exp > EXPBIAS)
2554 + exp = EXPMAX;
2555 + fraction = 0;
2557 + else
2559 + exp = src->normal_exp + EXPBIAS;
2560 + if (!ROUND_TOWARDS_ZERO)
2562 + /* IF the gard bits are the all zero, but the first, then we're
2563 + half way between two numbers, choose the one which makes the
2564 + lsb of the answer 0. */
2565 + if ((fraction & GARDMASK) == GARDMSB)
2567 + if (fraction & (1 << NGARDS))
2568 + fraction += GARDROUND + 1;
2570 + else
2572 + /* Add a one to the guards to round up */
2573 + fraction += GARDROUND;
2575 + if (fraction >= IMPLICIT_2)
2577 + fraction >>= 1;
2578 + exp += 1;
2581 + fraction >>= NGARDS;
2583 + if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp > EXPMAX)
2585 + /* Saturate on overflow. */
2586 + exp = EXPMAX;
2587 + fraction = ((fractype) 1 << FRACBITS) - 1;
2592 + /* We previously used bitfields to store the number, but this doesn't
2593 + handle little/big endian systems conveniently, so use shifts and
2594 + masks */
2595 +#ifdef FLOAT_BIT_ORDER_MISMATCH
2596 + dst.bits.fraction = fraction;
2597 + dst.bits.exp = exp;
2598 + dst.bits.sign = sign;
2599 +#else
2600 +# if defined TFLOAT && defined HALFFRACBITS
2602 + halffractype high, low, unity;
2603 + int lowsign, lowexp;
2605 + unity = (halffractype) 1 << HALFFRACBITS;
2607 + /* Set HIGH to the high double's significand, masking out the implicit 1.
2608 + Set LOW to the low double's full significand. */
2609 + high = (fraction >> (FRACBITS - HALFFRACBITS)) & (unity - 1);
2610 + low = fraction & (unity * 2 - 1);
2612 + /* Get the initial sign and exponent of the low double. */
2613 + lowexp = exp - HALFFRACBITS - 1;
2614 + lowsign = sign;
2616 + /* HIGH should be rounded like a normal double, making |LOW| <=
2617 + 0.5 ULP of HIGH. Assume round-to-nearest. */
2618 + if (exp < EXPMAX)
2619 + if (low > unity || (low == unity && (high & 1) == 1))
2621 + /* Round HIGH up and adjust LOW to match. */
2622 + high++;
2623 + if (high == unity)
2625 + /* May make it infinite, but that's OK. */
2626 + high = 0;
2627 + exp++;
2629 + low = unity * 2 - low;
2630 + lowsign ^= 1;
2633 + high |= (halffractype) exp << HALFFRACBITS;
2634 + high |= (halffractype) sign << (HALFFRACBITS + EXPBITS);
2636 + if (exp == EXPMAX || exp == 0 || low == 0)
2637 + low = 0;
2638 + else
2640 + while (lowexp > 0 && low < unity)
2642 + low <<= 1;
2643 + lowexp--;
2646 + if (lowexp <= 0)
2648 + halffractype roundmsb, round;
2649 + int shift;
2651 + shift = 1 - lowexp;
2652 + roundmsb = (1 << (shift - 1));
2653 + round = low & ((roundmsb << 1) - 1);
2655 + low >>= shift;
2656 + lowexp = 0;
2658 + if (round > roundmsb || (round == roundmsb && (low & 1) == 1))
2660 + low++;
2661 + if (low == unity)
2662 + /* LOW rounds up to the smallest normal number. */
2663 + lowexp++;
2667 + low &= unity - 1;
2668 + low |= (halffractype) lowexp << HALFFRACBITS;
2669 + low |= (halffractype) lowsign << (HALFFRACBITS + EXPBITS);
2671 + dst.value_raw = ((fractype) high << HALFSHIFT) | low;
2673 +# else
2674 + dst.value_raw = fraction & ((((fractype)1) << FRACBITS) - (fractype)1);
2675 + dst.value_raw |= ((fractype) (exp & ((1 << EXPBITS) - 1))) << FRACBITS;
2676 + dst.value_raw |= ((fractype) (sign & 1)) << (FRACBITS | EXPBITS);
2677 +# endif
2678 +#endif
2680 +#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
2681 +#ifdef TFLOAT
2683 + qrtrfractype tmp1 = dst.words[0];
2684 + qrtrfractype tmp2 = dst.words[1];
2685 + dst.words[0] = dst.words[3];
2686 + dst.words[1] = dst.words[2];
2687 + dst.words[2] = tmp2;
2688 + dst.words[3] = tmp1;
2690 +#else
2692 + halffractype tmp = dst.words[0];
2693 + dst.words[0] = dst.words[1];
2694 + dst.words[1] = tmp;
2696 +#endif
2697 +#endif
2699 + return dst.value;
2701 +#endif
2703 +#if defined(L_unpack_df) || defined(L_unpack_sf) || defined(L_unpack_tf)
2704 +void
2705 +unpack_d (FLO_union_type * src, fp_number_type * dst)
2707 + /* We previously used bitfields to store the number, but this doesn't
2708 + handle little/big endian systems conveniently, so use shifts and
2709 + masks */
2710 + fractype fraction;
2711 + int exp;
2712 + int sign;
2714 +#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
2715 + FLO_union_type swapped;
2717 +#ifdef TFLOAT
2718 + swapped.words[0] = src->words[3];
2719 + swapped.words[1] = src->words[2];
2720 + swapped.words[2] = src->words[1];
2721 + swapped.words[3] = src->words[0];
2722 +#else
2723 + swapped.words[0] = src->words[1];
2724 + swapped.words[1] = src->words[0];
2725 +#endif
2726 + src = &swapped;
2727 +#endif
2729 +#ifdef FLOAT_BIT_ORDER_MISMATCH
2730 + fraction = src->bits.fraction;
2731 + exp = src->bits.exp;
2732 + sign = src->bits.sign;
2733 +#else
2734 +# if defined TFLOAT && defined HALFFRACBITS
2736 + halffractype high, low;
2738 + high = src->value_raw >> HALFSHIFT;
2739 + low = src->value_raw & (((fractype)1 << HALFSHIFT) - 1);
2741 + fraction = high & ((((fractype)1) << HALFFRACBITS) - 1);
2742 + fraction <<= FRACBITS - HALFFRACBITS;
2743 + exp = ((int)(high >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
2744 + sign = ((int)(high >> (((HALFFRACBITS + EXPBITS))))) & 1;
2746 + if (exp != EXPMAX && exp != 0 && low != 0)
2748 + int lowexp = ((int)(low >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
2749 + int lowsign = ((int)(low >> (((HALFFRACBITS + EXPBITS))))) & 1;
2750 + int shift;
2751 + fractype xlow;
2753 + xlow = low & ((((fractype)1) << HALFFRACBITS) - 1);
2754 + if (lowexp)
2755 + xlow |= (((halffractype)1) << HALFFRACBITS);
2756 + else
2757 + lowexp = 1;
2758 + shift = (FRACBITS - HALFFRACBITS) - (exp - lowexp);
2759 + if (shift > 0)
2760 + xlow <<= shift;
2761 + else if (shift < 0)
2762 + xlow >>= -shift;
2763 + if (sign == lowsign)
2764 + fraction += xlow;
2765 + else if (fraction >= xlow)
2766 + fraction -= xlow;
2767 + else
2769 + /* The high part is a power of two but the full number is lower.
2770 + This code will leave the implicit 1 in FRACTION, but we'd
2771 + have added that below anyway. */
2772 + fraction = (((fractype) 1 << FRACBITS) - xlow) << 1;
2773 + exp--;
2777 +# else
2778 + fraction = src->value_raw & ((((fractype)1) << FRACBITS) - 1);
2779 + exp = ((int)(src->value_raw >> FRACBITS)) & ((1 << EXPBITS) - 1);
2780 + sign = ((int)(src->value_raw >> (FRACBITS + EXPBITS))) & 1;
2781 +# endif
2782 +#endif
2784 + dst->sign = sign;
2785 + if (exp == 0)
2787 + /* Hmm. Looks like 0 */
2788 + if (fraction == 0
2789 +#ifdef NO_DENORMALS
2790 + || 1
2791 +#endif
2794 + /* tastes like zero */
2795 + dst->class = CLASS_ZERO;
2797 + else
2799 + /* Zero exponent with nonzero fraction - it's denormalized,
2800 + so there isn't a leading implicit one - we'll shift it so
2801 + it gets one. */
2802 + dst->normal_exp = exp - EXPBIAS + 1;
2803 + fraction <<= NGARDS;
2805 + dst->class = CLASS_NUMBER;
2806 +#if 1
2807 + while (fraction < IMPLICIT_1)
2809 + fraction <<= 1;
2810 + dst->normal_exp--;
2812 +#endif
2813 + dst->fraction.ll = fraction;
2816 + else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp == EXPMAX)
2818 + /* Huge exponent*/
2819 + if (fraction == 0)
2821 + /* Attached to a zero fraction - means infinity */
2822 + dst->class = CLASS_INFINITY;
2824 + else
2826 + /* Nonzero fraction, means nan */
2827 +#ifdef QUIET_NAN_NEGATED
2828 + if ((fraction & QUIET_NAN) == 0)
2829 +#else
2830 + if (fraction & QUIET_NAN)
2831 +#endif
2833 + dst->class = CLASS_QNAN;
2835 + else
2837 + dst->class = CLASS_SNAN;
2839 + /* Keep the fraction part as the nan number */
2840 + dst->fraction.ll = fraction;
2843 + else
2845 + /* Nothing strange about this number */
2846 + dst->normal_exp = exp - EXPBIAS;
2847 + dst->class = CLASS_NUMBER;
2848 + dst->fraction.ll = (fraction << NGARDS) | IMPLICIT_1;
2851 +#endif /* L_unpack_df || L_unpack_sf */
2853 +#if defined(L_addsub_sf) || defined(L_addsub_df) || defined(L_addsub_tf)
2854 +static fp_number_type *
2855 +_fpadd_parts (fp_number_type * a,
2856 + fp_number_type * b,
2857 + fp_number_type * tmp)
2859 + intfrac tfraction;
2861 + /* Put commonly used fields in local variables. */
2862 + int a_normal_exp;
2863 + int b_normal_exp;
2864 + fractype a_fraction;
2865 + fractype b_fraction;
2867 + if (isnan (a))
2869 + return a;
2871 + if (isnan (b))
2873 + return b;
2875 + if (isinf (a))
2877 + /* Adding infinities with opposite signs yields a NaN. */
2878 + if (isinf (b) && a->sign != b->sign)
2879 + return nan ();
2880 + return a;
2882 + if (isinf (b))
2884 + return b;
2886 + if (iszero (b))
2888 + if (iszero (a))
2890 + *tmp = *a;
2891 + tmp->sign = a->sign & b->sign;
2892 + return tmp;
2894 + return a;
2896 + if (iszero (a))
2898 + return b;
2901 + /* Got two numbers. shift the smaller and increment the exponent till
2902 + they're the same */
2904 + int diff;
2906 + a_normal_exp = a->normal_exp;
2907 + b_normal_exp = b->normal_exp;
2908 + a_fraction = a->fraction.ll;
2909 + b_fraction = b->fraction.ll;
2911 + diff = a_normal_exp - b_normal_exp;
2913 + if (diff < 0)
2914 + diff = -diff;
2915 + if (diff < FRAC_NBITS)
2917 + /* ??? This does shifts one bit at a time. Optimize. */
2918 + while (a_normal_exp > b_normal_exp)
2920 + b_normal_exp++;
2921 + LSHIFT (b_fraction);
2923 + while (b_normal_exp > a_normal_exp)
2925 + a_normal_exp++;
2926 + LSHIFT (a_fraction);
2929 + else
2931 + /* Somethings's up.. choose the biggest */
2932 + if (a_normal_exp > b_normal_exp)
2934 + b_normal_exp = a_normal_exp;
2935 + b_fraction = 0;
2937 + else
2939 + a_normal_exp = b_normal_exp;
2940 + a_fraction = 0;
2945 + if (a->sign != b->sign)
2947 + if (a->sign)
2949 + tfraction = -a_fraction + b_fraction;
2951 + else
2953 + tfraction = a_fraction - b_fraction;
2955 + if (tfraction >= 0)
2957 + tmp->sign = 0;
2958 + tmp->normal_exp = a_normal_exp;
2959 + tmp->fraction.ll = tfraction;
2961 + else
2963 + tmp->sign = 1;
2964 + tmp->normal_exp = a_normal_exp;
2965 + tmp->fraction.ll = -tfraction;
2967 + /* and renormalize it */
2969 + while (tmp->fraction.ll < IMPLICIT_1 && tmp->fraction.ll)
2971 + tmp->fraction.ll <<= 1;
2972 + tmp->normal_exp--;
2975 + else
2977 + tmp->sign = a->sign;
2978 + tmp->normal_exp = a_normal_exp;
2979 + tmp->fraction.ll = a_fraction + b_fraction;
2981 + tmp->class = CLASS_NUMBER;
2982 + /* Now the fraction is added, we have to shift down to renormalize the
2983 + number */
2985 + if (tmp->fraction.ll >= IMPLICIT_2)
2987 + LSHIFT (tmp->fraction.ll);
2988 + tmp->normal_exp++;
2990 + return tmp;
2994 +FLO_type
2995 +add (FLO_type arg_a, FLO_type arg_b)
2997 + fp_number_type a;
2998 + fp_number_type b;
2999 + fp_number_type tmp;
3000 + fp_number_type *res;
3001 + FLO_union_type au, bu;
3003 + au.value = arg_a;
3004 + bu.value = arg_b;
3006 + unpack_d (&au, &a);
3007 + unpack_d (&bu, &b);
3009 + res = _fpadd_parts (&a, &b, &tmp);
3011 + return pack_d (res);
3014 +FLO_type
3015 +sub (FLO_type arg_a, FLO_type arg_b)
3017 + fp_number_type a;
3018 + fp_number_type b;
3019 + fp_number_type tmp;
3020 + fp_number_type *res;
3021 + FLO_union_type au, bu;
3023 + au.value = arg_a;
3024 + bu.value = arg_b;
3026 + unpack_d (&au, &a);
3027 + unpack_d (&bu, &b);
3029 + b.sign ^= 1;
3031 + res = _fpadd_parts (&a, &b, &tmp);
3033 + return pack_d (res);
3035 +#endif /* L_addsub_sf || L_addsub_df */
3037 +#if defined(L_mul_sf) || defined(L_mul_df) || defined(L_mul_tf)
3038 +static inline __attribute__ ((__always_inline__)) fp_number_type *
3039 +_fpmul_parts ( fp_number_type * a,
3040 + fp_number_type * b,
3041 + fp_number_type * tmp)
3043 + fractype low = 0;
3044 + fractype high = 0;
3046 + if (isnan (a))
3048 + a->sign = a->sign != b->sign;
3049 + return a;
3051 + if (isnan (b))
3053 + b->sign = a->sign != b->sign;
3054 + return b;
3056 + if (isinf (a))
3058 + if (iszero (b))
3059 + return nan ();
3060 + a->sign = a->sign != b->sign;
3061 + return a;
3063 + if (isinf (b))
3065 + if (iszero (a))
3067 + return nan ();
3069 + b->sign = a->sign != b->sign;
3070 + return b;
3072 + if (iszero (a))
3074 + a->sign = a->sign != b->sign;
3075 + return a;
3077 + if (iszero (b))
3079 + b->sign = a->sign != b->sign;
3080 + return b;
3083 + /* Calculate the mantissa by multiplying both numbers to get a
3084 + twice-as-wide number. */
3086 +#if defined(NO_DI_MODE) || defined(TFLOAT)
3088 + fractype x = a->fraction.ll;
3089 + fractype ylow = b->fraction.ll;
3090 + fractype yhigh = 0;
3091 + int bit;
3093 + /* ??? This does multiplies one bit at a time. Optimize. */
3094 + for (bit = 0; bit < FRAC_NBITS; bit++)
3096 + int carry;
3098 + if (x & 1)
3100 + carry = (low += ylow) < ylow;
3101 + high += yhigh + carry;
3103 + yhigh <<= 1;
3104 + if (ylow & FRACHIGH)
3106 + yhigh |= 1;
3108 + ylow <<= 1;
3109 + x >>= 1;
3112 +#elif defined(FLOAT)
3113 + /* Multiplying two USIs to get a UDI, we're safe. */
3115 + UDItype answer = (UDItype)a->fraction.ll * (UDItype)b->fraction.ll;
3117 + high = answer >> BITS_PER_SI;
3118 + low = answer;
3120 +#else
3121 + /* fractype is DImode, but we need the result to be twice as wide.
3122 + Assuming a widening multiply from DImode to TImode is not
3123 + available, build one by hand. */
3125 + USItype nl = a->fraction.ll;
3126 + USItype nh = a->fraction.ll >> BITS_PER_SI;
3127 + USItype ml = b->fraction.ll;
3128 + USItype mh = b->fraction.ll >> BITS_PER_SI;
3129 + UDItype pp_ll = (UDItype) ml * nl;
3130 + UDItype pp_hl = (UDItype) mh * nl;
3131 + UDItype pp_lh = (UDItype) ml * nh;
3132 + UDItype pp_hh = (UDItype) mh * nh;
3133 + UDItype res2 = 0;
3134 + UDItype res0 = 0;
3135 + UDItype ps_hh__ = pp_hl + pp_lh;
3136 + if (ps_hh__ < pp_hl)
3137 + res2 += (UDItype)1 << BITS_PER_SI;
3138 + pp_hl = (UDItype)(USItype)ps_hh__ << BITS_PER_SI;
3139 + res0 = pp_ll + pp_hl;
3140 + if (res0 < pp_ll)
3141 + res2++;
3142 + res2 += (ps_hh__ >> BITS_PER_SI) + pp_hh;
3143 + high = res2;
3144 + low = res0;
3146 +#endif
3149 + tmp->normal_exp = a->normal_exp + b->normal_exp
3150 + + FRAC_NBITS - (FRACBITS + NGARDS);
3151 + tmp->sign = a->sign != b->sign;
3152 + while (high >= IMPLICIT_2)
3154 + tmp->normal_exp++;
3155 + if (high & 1)
3157 + low >>= 1;
3158 + low |= FRACHIGH;
3160 + high >>= 1;
3162 + while (high < IMPLICIT_1)
3164 + tmp->normal_exp--;
3166 + high <<= 1;
3167 + if (low & FRACHIGH)
3168 + high |= 1;
3169 + low <<= 1;
3171 + /* rounding is tricky. if we only round if it won't make us round later. */
3172 +#if 0
3173 + if (low & FRACHIGH2)
3175 + if (((high & GARDMASK) != GARDMSB)
3176 + && (((high + 1) & GARDMASK) == GARDMSB))
3178 + /* don't round, it gets done again later. */
3180 + else
3182 + high++;
3185 +#endif
3186 + if (!ROUND_TOWARDS_ZERO && (high & GARDMASK) == GARDMSB)
3188 + if (high & (1 << NGARDS))
3190 + /* half way, so round to even */
3191 + high += GARDROUND + 1;
3193 + else if (low)
3195 + /* but we really weren't half way */
3196 + high += GARDROUND + 1;
3199 + tmp->fraction.ll = high;
3200 + tmp->class = CLASS_NUMBER;
3201 + return tmp;
3204 +FLO_type
3205 +multiply (FLO_type arg_a, FLO_type arg_b)
3207 + fp_number_type a;
3208 + fp_number_type b;
3209 + fp_number_type tmp;
3210 + fp_number_type *res;
3211 + FLO_union_type au, bu;
3213 + au.value = arg_a;
3214 + bu.value = arg_b;
3216 + unpack_d (&au, &a);
3217 + unpack_d (&bu, &b);
3219 + res = _fpmul_parts (&a, &b, &tmp);
3221 + return pack_d (res);
3223 +#endif /* L_mul_sf || L_mul_df */
3225 +#if defined(L_div_sf) || defined(L_div_df) || defined(L_div_tf)
3226 +static inline __attribute__ ((__always_inline__)) fp_number_type *
3227 +_fpdiv_parts (fp_number_type * a,
3228 + fp_number_type * b)
3230 + fractype bit;
3231 + fractype numerator;
3232 + fractype denominator;
3233 + fractype quotient;
3235 + if (isnan (a))
3237 + return a;
3239 + if (isnan (b))
3241 + return b;
3244 + a->sign = a->sign ^ b->sign;
3246 + if (isinf (a) || iszero (a))
3248 + if (a->class == b->class)
3249 + return nan ();
3250 + return a;
3253 + if (isinf (b))
3255 + a->fraction.ll = 0;
3256 + a->normal_exp = 0;
3257 + return a;
3259 + if (iszero (b))
3261 + a->class = CLASS_INFINITY;
3262 + return a;
3265 + /* Calculate the mantissa by multiplying both 64bit numbers to get a
3266 + 128 bit number */
3268 + /* quotient =
3269 + ( numerator / denominator) * 2^(numerator exponent - denominator exponent)
3270 + */
3272 + a->normal_exp = a->normal_exp - b->normal_exp;
3273 + numerator = a->fraction.ll;
3274 + denominator = b->fraction.ll;
3276 + if (numerator < denominator)
3278 + /* Fraction will be less than 1.0 */
3279 + numerator *= 2;
3280 + a->normal_exp--;
3282 + bit = IMPLICIT_1;
3283 + quotient = 0;
3284 + /* ??? Does divide one bit at a time. Optimize. */
3285 + while (bit)
3287 + if (numerator >= denominator)
3289 + quotient |= bit;
3290 + numerator -= denominator;
3292 + bit >>= 1;
3293 + numerator *= 2;
3296 + if (!ROUND_TOWARDS_ZERO && (quotient & GARDMASK) == GARDMSB)
3298 + if (quotient & (1 << NGARDS))
3300 + /* half way, so round to even */
3301 + quotient += GARDROUND + 1;
3303 + else if (numerator)
3305 + /* but we really weren't half way, more bits exist */
3306 + quotient += GARDROUND + 1;
3310 + a->fraction.ll = quotient;
3311 + return (a);
3315 +FLO_type
3316 +divide (FLO_type arg_a, FLO_type arg_b)
3318 + fp_number_type a;
3319 + fp_number_type b;
3320 + fp_number_type *res;
3321 + FLO_union_type au, bu;
3323 + au.value = arg_a;
3324 + bu.value = arg_b;
3326 + unpack_d (&au, &a);
3327 + unpack_d (&bu, &b);
3329 + res = _fpdiv_parts (&a, &b);
3331 + return pack_d (res);
3333 +#endif /* L_div_sf || L_div_df */
3335 +#if defined(L_fpcmp_parts_sf) || defined(L_fpcmp_parts_df) \
3336 + || defined(L_fpcmp_parts_tf)
3337 +/* according to the demo, fpcmp returns a comparison with 0... thus
3338 + a<b -> -1
3339 + a==b -> 0
3340 + a>b -> +1
3341 + */
3343 +int
3344 +__fpcmp_parts (fp_number_type * a, fp_number_type * b)
3346 +#if 0
3347 + /* either nan -> unordered. Must be checked outside of this routine. */
3348 + if (isnan (a) && isnan (b))
3350 + return 1; /* still unordered! */
3352 +#endif
3354 + if (isnan (a) || isnan (b))
3356 + return 1; /* how to indicate unordered compare? */
3358 + if (isinf (a) && isinf (b))
3360 + /* +inf > -inf, but +inf != +inf */
3361 + /* b \a| +inf(0)| -inf(1)
3362 + ______\+--------+--------
3363 + +inf(0)| a==b(0)| a<b(-1)
3364 + -------+--------+--------
3365 + -inf(1)| a>b(1) | a==b(0)
3366 + -------+--------+--------
3367 + So since unordered must be nonzero, just line up the columns...
3368 + */
3369 + return b->sign - a->sign;
3371 + /* but not both... */
3372 + if (isinf (a))
3374 + return a->sign ? -1 : 1;
3376 + if (isinf (b))
3378 + return b->sign ? 1 : -1;
3380 + if (iszero (a) && iszero (b))
3382 + return 0;
3384 + if (iszero (a))
3386 + return b->sign ? 1 : -1;
3388 + if (iszero (b))
3390 + return a->sign ? -1 : 1;
3392 + /* now both are "normal". */
3393 + if (a->sign != b->sign)
3395 + /* opposite signs */
3396 + return a->sign ? -1 : 1;
3398 + /* same sign; exponents? */
3399 + if (a->normal_exp > b->normal_exp)
3401 + return a->sign ? -1 : 1;
3403 + if (a->normal_exp < b->normal_exp)
3405 + return a->sign ? 1 : -1;
3407 + /* same exponents; check size. */
3408 + if (a->fraction.ll > b->fraction.ll)
3410 + return a->sign ? -1 : 1;
3412 + if (a->fraction.ll < b->fraction.ll)
3414 + return a->sign ? 1 : -1;
3416 + /* after all that, they're equal. */
3417 + return 0;
3419 +#endif
3421 +#if defined(L_compare_sf) || defined(L_compare_df) || defined(L_compoare_tf)
3422 +CMPtype
3423 +compare (FLO_type arg_a, FLO_type arg_b)
3425 + fp_number_type a;
3426 + fp_number_type b;
3427 + FLO_union_type au, bu;
3429 + au.value = arg_a;
3430 + bu.value = arg_b;
3432 + unpack_d (&au, &a);
3433 + unpack_d (&bu, &b);
3435 + return __fpcmp_parts (&a, &b);
3437 +#endif /* L_compare_sf || L_compare_df */
3439 +#ifndef US_SOFTWARE_GOFAST
3441 +/* These should be optimized for their specific tasks someday. */
3443 +#if defined(L_eq_sf) || defined(L_eq_df) || defined(L_eq_tf)
3444 +CMPtype
3445 +_eq_f2 (FLO_type arg_a, FLO_type arg_b)
3447 + fp_number_type a;
3448 + fp_number_type b;
3449 + FLO_union_type au, bu;
3451 + au.value = arg_a;
3452 + bu.value = arg_b;
3454 + unpack_d (&au, &a);
3455 + unpack_d (&bu, &b);
3457 + if (isnan (&a) || isnan (&b))
3458 + return 1; /* false, truth == 0 */
3460 + return __fpcmp_parts (&a, &b) ;
3462 +#endif /* L_eq_sf || L_eq_df */
3464 +#if defined(L_ne_sf) || defined(L_ne_df) || defined(L_ne_tf)
3465 +CMPtype
3466 +_ne_f2 (FLO_type arg_a, FLO_type arg_b)
3468 + fp_number_type a;
3469 + fp_number_type b;
3470 + FLO_union_type au, bu;
3472 + au.value = arg_a;
3473 + bu.value = arg_b;
3475 + unpack_d (&au, &a);
3476 + unpack_d (&bu, &b);
3478 + if (isnan (&a) || isnan (&b))
3479 + return 1; /* true, truth != 0 */
3481 + return __fpcmp_parts (&a, &b) ;
3483 +#endif /* L_ne_sf || L_ne_df */
3485 +#if defined(L_gt_sf) || defined(L_gt_df) || defined(L_gt_tf)
3486 +CMPtype
3487 +_gt_f2 (FLO_type arg_a, FLO_type arg_b)
3489 + fp_number_type a;
3490 + fp_number_type b;
3491 + FLO_union_type au, bu;
3493 + au.value = arg_a;
3494 + bu.value = arg_b;
3496 + unpack_d (&au, &a);
3497 + unpack_d (&bu, &b);
3499 + if (isnan (&a) || isnan (&b))
3500 + return -1; /* false, truth > 0 */
3502 + return __fpcmp_parts (&a, &b);
3504 +#endif /* L_gt_sf || L_gt_df */
3506 +#if defined(L_ge_sf) || defined(L_ge_df) || defined(L_ge_tf)
3507 +CMPtype
3508 +_ge_f2 (FLO_type arg_a, FLO_type arg_b)
3510 + fp_number_type a;
3511 + fp_number_type b;
3512 + FLO_union_type au, bu;
3514 + au.value = arg_a;
3515 + bu.value = arg_b;
3517 + unpack_d (&au, &a);
3518 + unpack_d (&bu, &b);
3520 + if (isnan (&a) || isnan (&b))
3521 + return -1; /* false, truth >= 0 */
3522 + return __fpcmp_parts (&a, &b) ;
3524 +#endif /* L_ge_sf || L_ge_df */
3526 +#if defined(L_lt_sf) || defined(L_lt_df) || defined(L_lt_tf)
3527 +CMPtype
3528 +_lt_f2 (FLO_type arg_a, FLO_type arg_b)
3530 + fp_number_type a;
3531 + fp_number_type b;
3532 + FLO_union_type au, bu;
3534 + au.value = arg_a;
3535 + bu.value = arg_b;
3537 + unpack_d (&au, &a);
3538 + unpack_d (&bu, &b);
3540 + if (isnan (&a) || isnan (&b))
3541 + return 1; /* false, truth < 0 */
3543 + return __fpcmp_parts (&a, &b);
3545 +#endif /* L_lt_sf || L_lt_df */
3547 +#if defined(L_le_sf) || defined(L_le_df) || defined(L_le_tf)
3548 +CMPtype
3549 +_le_f2 (FLO_type arg_a, FLO_type arg_b)
3551 + fp_number_type a;
3552 + fp_number_type b;
3553 + FLO_union_type au, bu;
3555 + au.value = arg_a;
3556 + bu.value = arg_b;
3558 + unpack_d (&au, &a);
3559 + unpack_d (&bu, &b);
3561 + if (isnan (&a) || isnan (&b))
3562 + return 1; /* false, truth <= 0 */
3564 + return __fpcmp_parts (&a, &b) ;
3566 +#endif /* L_le_sf || L_le_df */
3568 +#endif /* ! US_SOFTWARE_GOFAST */
3570 +#if defined(L_unord_sf) || defined(L_unord_df) || defined(L_unord_tf)
3571 +CMPtype
3572 +_unord_f2 (FLO_type arg_a, FLO_type arg_b)
3574 + fp_number_type a;
3575 + fp_number_type b;
3576 + FLO_union_type au, bu;
3578 + au.value = arg_a;
3579 + bu.value = arg_b;
3581 + unpack_d (&au, &a);
3582 + unpack_d (&bu, &b);
3584 + return (isnan (&a) || isnan (&b));
3586 +#endif /* L_unord_sf || L_unord_df */
3588 +#if defined(L_si_to_sf) || defined(L_si_to_df) || defined(L_si_to_tf)
3589 +FLO_type
3590 +si_to_float (SItype arg_a)
3592 + fp_number_type in;
3594 + in.class = CLASS_NUMBER;
3595 + in.sign = arg_a < 0;
3596 + if (!arg_a)
3598 + in.class = CLASS_ZERO;
3600 + else
3602 + in.normal_exp = FRACBITS + NGARDS;
3603 + if (in.sign)
3605 + /* Special case for minint, since there is no +ve integer
3606 + representation for it */
3607 + if (arg_a == (- MAX_SI_INT - 1))
3609 + return (FLO_type)(- MAX_SI_INT - 1);
3611 + in.fraction.ll = (-arg_a);
3613 + else
3614 + in.fraction.ll = arg_a;
3616 + while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
3618 + in.fraction.ll <<= 1;
3619 + in.normal_exp -= 1;
3622 + return pack_d (&in);
3624 +#endif /* L_si_to_sf || L_si_to_df */
3626 +#if defined(L_usi_to_sf) || defined(L_usi_to_df) || defined(L_usi_to_tf)
3627 +FLO_type
3628 +usi_to_float (USItype arg_a)
3630 + fp_number_type in;
3632 + in.sign = 0;
3633 + if (!arg_a)
3635 + in.class = CLASS_ZERO;
3637 + else
3639 + in.class = CLASS_NUMBER;
3640 + in.normal_exp = FRACBITS + NGARDS;
3641 + in.fraction.ll = arg_a;
3643 + while (in.fraction.ll > ((fractype)1 << (FRACBITS + NGARDS)))
3645 + in.fraction.ll >>= 1;
3646 + in.normal_exp += 1;
3648 + while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
3650 + in.fraction.ll <<= 1;
3651 + in.normal_exp -= 1;
3654 + return pack_d (&in);
3656 +#endif
3658 +#if defined(L_sf_to_si) || defined(L_df_to_si) || defined(L_tf_to_si)
3659 +SItype
3660 +float_to_si (FLO_type arg_a)
3662 + fp_number_type a;
3663 + SItype tmp;
3664 + FLO_union_type au;
3666 + au.value = arg_a;
3667 + unpack_d (&au, &a);
3669 + if (iszero (&a))
3670 + return 0;
3671 + if (isnan (&a))
3672 + return 0;
3673 + /* get reasonable MAX_SI_INT... */
3674 + if (isinf (&a))
3675 + return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
3676 + /* it is a number, but a small one */
3677 + if (a.normal_exp < 0)
3678 + return 0;
3679 + if (a.normal_exp > BITS_PER_SI - 2)
3680 + return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
3681 + tmp = a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
3682 + return a.sign ? (-tmp) : (tmp);
3684 +#endif /* L_sf_to_si || L_df_to_si */
3686 +#if defined(L_sf_to_usi) || defined(L_df_to_usi) || defined(L_tf_to_usi)
3687 +#if defined US_SOFTWARE_GOFAST || defined(L_tf_to_usi)
3688 +/* While libgcc2.c defines its own __fixunssfsi and __fixunsdfsi routines,
3689 + we also define them for GOFAST because the ones in libgcc2.c have the
3690 + wrong names and I'd rather define these here and keep GOFAST CYG-LOC's
3691 + out of libgcc2.c. We can't define these here if not GOFAST because then
3692 + there'd be duplicate copies. */
3694 +USItype
3695 +float_to_usi (FLO_type arg_a)
3697 + fp_number_type a;
3698 + FLO_union_type au;
3700 + au.value = arg_a;
3701 + unpack_d (&au, &a);
3703 + if (iszero (&a))
3704 + return 0;
3705 + if (isnan (&a))
3706 + return 0;
3707 + /* it is a negative number */
3708 + if (a.sign)
3709 + return 0;
3710 + /* get reasonable MAX_USI_INT... */
3711 + if (isinf (&a))
3712 + return MAX_USI_INT;
3713 + /* it is a number, but a small one */
3714 + if (a.normal_exp < 0)
3715 + return 0;
3716 + if (a.normal_exp > BITS_PER_SI - 1)
3717 + return MAX_USI_INT;
3718 + else if (a.normal_exp > (FRACBITS + NGARDS))
3719 + return a.fraction.ll << (a.normal_exp - (FRACBITS + NGARDS));
3720 + else
3721 + return a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
3723 +#endif /* US_SOFTWARE_GOFAST */
3724 +#endif /* L_sf_to_usi || L_df_to_usi */
3726 +#if defined(L_negate_sf) || defined(L_negate_df) || defined(L_negate_tf)
3727 +FLO_type
3728 +negate (FLO_type arg_a)
3730 + fp_number_type a;
3731 + FLO_union_type au;
3733 + au.value = arg_a;
3734 + unpack_d (&au, &a);
3736 + flip_sign (&a);
3737 + return pack_d (&a);
3739 +#endif /* L_negate_sf || L_negate_df */
3741 +#ifdef FLOAT
3743 +#if defined(L_make_sf)
3744 +SFtype
3745 +__make_fp(fp_class_type class,
3746 + unsigned int sign,
3747 + int exp,
3748 + USItype frac)
3750 + fp_number_type in;
3752 + in.class = class;
3753 + in.sign = sign;
3754 + in.normal_exp = exp;
3755 + in.fraction.ll = frac;
3756 + return pack_d (&in);
3758 +#endif /* L_make_sf */
3760 +#ifndef FLOAT_ONLY
3762 +/* This enables one to build an fp library that supports float but not double.
3763 + Otherwise, we would get an undefined reference to __make_dp.
3764 + This is needed for some 8-bit ports that can't handle well values that
3765 + are 8-bytes in size, so we just don't support double for them at all. */
3767 +#if defined(L_sf_to_df)
3768 +DFtype
3769 +sf_to_df (SFtype arg_a)
3771 + fp_number_type in;
3772 + FLO_union_type au;
3774 + au.value = arg_a;
3775 + unpack_d (&au, &in);
3777 + return __make_dp (in.class, in.sign, in.normal_exp,
3778 + ((UDItype) in.fraction.ll) << F_D_BITOFF);
3780 +#endif /* L_sf_to_df */
3782 +#if defined(L_sf_to_tf) && defined(TMODES)
3783 +TFtype
3784 +sf_to_tf (SFtype arg_a)
3786 + fp_number_type in;
3787 + FLO_union_type au;
3789 + au.value = arg_a;
3790 + unpack_d (&au, &in);
3792 + return __make_tp (in.class, in.sign, in.normal_exp,
3793 + ((UTItype) in.fraction.ll) << F_T_BITOFF);
3795 +#endif /* L_sf_to_df */
3797 +#endif /* ! FLOAT_ONLY */
3798 +#endif /* FLOAT */
3800 +#ifndef FLOAT
3802 +extern SFtype __make_fp (fp_class_type, unsigned int, int, USItype);
3804 +#if defined(L_make_df)
3805 +DFtype
3806 +__make_dp (fp_class_type class, unsigned int sign, int exp, UDItype frac)
3808 + fp_number_type in;
3810 + in.class = class;
3811 + in.sign = sign;
3812 + in.normal_exp = exp;
3813 + in.fraction.ll = frac;
3814 + return pack_d (&in);
3816 +#endif /* L_make_df */
3818 +#if defined(L_df_to_sf)
3819 +SFtype
3820 +df_to_sf (DFtype arg_a)
3822 + fp_number_type in;
3823 + USItype sffrac;
3824 + FLO_union_type au;
3826 + au.value = arg_a;
3827 + unpack_d (&au, &in);
3829 + sffrac = in.fraction.ll >> F_D_BITOFF;
3831 + /* We set the lowest guard bit in SFFRAC if we discarded any non
3832 + zero bits. */
3833 + if ((in.fraction.ll & (((USItype) 1 << F_D_BITOFF) - 1)) != 0)
3834 + sffrac |= 1;
3836 + return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
3838 +#endif /* L_df_to_sf */
3840 +#if defined(L_df_to_tf) && defined(TMODES) \
3841 + && !defined(FLOAT) && !defined(TFLOAT)
3842 +TFtype
3843 +df_to_tf (DFtype arg_a)
3845 + fp_number_type in;
3846 + FLO_union_type au;
3848 + au.value = arg_a;
3849 + unpack_d (&au, &in);
3851 + return __make_tp (in.class, in.sign, in.normal_exp,
3852 + ((UTItype) in.fraction.ll) << D_T_BITOFF);
3854 +#endif /* L_sf_to_df */
3856 +#ifdef TFLOAT
3857 +#if defined(L_make_tf)
3858 +TFtype
3859 +__make_tp(fp_class_type class,
3860 + unsigned int sign,
3861 + int exp,
3862 + UTItype frac)
3864 + fp_number_type in;
3866 + in.class = class;
3867 + in.sign = sign;
3868 + in.normal_exp = exp;
3869 + in.fraction.ll = frac;
3870 + return pack_d (&in);
3872 +#endif /* L_make_tf */
3874 +#if defined(L_tf_to_df)
3875 +DFtype
3876 +tf_to_df (TFtype arg_a)
3878 + fp_number_type in;
3879 + UDItype sffrac;
3880 + FLO_union_type au;
3882 + au.value = arg_a;
3883 + unpack_d (&au, &in);
3885 + sffrac = in.fraction.ll >> D_T_BITOFF;
3887 + /* We set the lowest guard bit in SFFRAC if we discarded any non
3888 + zero bits. */
3889 + if ((in.fraction.ll & (((UTItype) 1 << D_T_BITOFF) - 1)) != 0)
3890 + sffrac |= 1;
3892 + return __make_dp (in.class, in.sign, in.normal_exp, sffrac);
3894 +#endif /* L_tf_to_df */
3896 +#if defined(L_tf_to_sf)
3897 +SFtype
3898 +tf_to_sf (TFtype arg_a)
3900 + fp_number_type in;
3901 + USItype sffrac;
3902 + FLO_union_type au;
3904 + au.value = arg_a;
3905 + unpack_d (&au, &in);
3907 + sffrac = in.fraction.ll >> F_T_BITOFF;
3909 + /* We set the lowest guard bit in SFFRAC if we discarded any non
3910 + zero bits. */
3911 + if ((in.fraction.ll & (((UTItype) 1 << F_T_BITOFF) - 1)) != 0)
3912 + sffrac |= 1;
3914 + return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
3916 +#endif /* L_tf_to_sf */
3917 +#endif /* TFLOAT */
3919 +#endif /* ! FLOAT */
3920 +#endif /* !EXTENDED_FLOAT_STUBS */
3921 --- gcc-3.4.3/gcc/config/nios2/nios2-protos.h
3922 +++ gcc-3.4.3-nios2/gcc/config/nios2/nios2-protos.h
3923 @@ -0,0 +1,70 @@
3924 +/* Subroutines for assembler code output for Altera NIOS 2G NIOS2 version.
3925 + Copyright (C) 2003 Altera
3926 + Contributed by Jonah Graham (jgraham@altera.com).
3928 +This file is part of GNU CC.
3930 +GNU CC is free software; you can redistribute it and/or modify
3931 +it under the terms of the GNU General Public License as published by
3932 +the Free Software Foundation; either version 2, or (at your option)
3933 +any later version.
3935 +GNU CC is distributed in the hope that it will be useful,
3936 +but WITHOUT ANY WARRANTY; without even the implied warranty of
3937 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3938 +GNU General Public License for more details.
3940 +You should have received a copy of the GNU General Public License
3941 +along with GNU CC; see the file COPYING. If not, write to
3942 +the Free Software Foundation, 59 Temple Place - Suite 330,
3943 +Boston, MA 02111-1307, USA. */
3945 +extern void dump_frame_size (FILE *);
3946 +extern HOST_WIDE_INT compute_frame_size (void);
3947 +extern int nios2_initial_elimination_offset (int, int);
3948 +extern void override_options (void);
3949 +extern void optimization_options (int, int);
3950 +extern int nios2_can_use_return_insn (void);
3951 +extern void expand_prologue (void);
3952 +extern void expand_epilogue (bool);
3953 +extern void function_profiler (FILE *, int);
3956 +#ifdef RTX_CODE
3957 +extern int nios2_legitimate_address (rtx, enum machine_mode, int);
3958 +extern void nios2_print_operand (FILE *, rtx, int);
3959 +extern void nios2_print_operand_address (FILE *, rtx);
3961 +extern int nios2_emit_move_sequence (rtx *, enum machine_mode);
3962 +extern int nios2_emit_expensive_div (rtx *, enum machine_mode);
3964 +extern void gen_int_relational (enum rtx_code, rtx, rtx, rtx, rtx);
3965 +extern void gen_conditional_move (rtx *, enum machine_mode);
3966 +extern const char *asm_output_opcode (FILE *, const char *);
3968 +/* predicates */
3969 +extern int arith_operand (rtx, enum machine_mode);
3970 +extern int uns_arith_operand (rtx, enum machine_mode);
3971 +extern int logical_operand (rtx, enum machine_mode);
3972 +extern int shift_operand (rtx, enum machine_mode);
3973 +extern int reg_or_0_operand (rtx, enum machine_mode);
3974 +extern int equality_op (rtx, enum machine_mode);
3975 +extern int custom_insn_opcode (rtx, enum machine_mode);
3976 +extern int rdwrctl_operand (rtx, enum machine_mode);
3978 +# ifdef HAVE_MACHINE_MODES
3979 +# if defined TREE_CODE
3980 +extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
3981 +extern rtx function_arg (const CUMULATIVE_ARGS *, enum machine_mode, tree, int);
3982 +extern int function_arg_partial_nregs (const CUMULATIVE_ARGS *, enum machine_mode, tree, int);
3983 +extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
3984 +extern int nios2_setup_incoming_varargs (const CUMULATIVE_ARGS *, enum machine_mode, tree, int);
3986 +# endif /* TREE_CODE */
3987 +# endif /* HAVE_MACHINE_MODES */
3988 +#endif
3990 +#ifdef TREE_CODE
3991 +extern int nios2_return_in_memory (tree);
3993 +#endif /* TREE_CODE */
3994 --- gcc-3.4.3/gcc/config/nios2/nios2.c
3995 +++ gcc-3.4.3-nios2/gcc/config/nios2/nios2.c
3996 @@ -0,0 +1,2853 @@
3997 +/* Subroutines for assembler code output for Altera NIOS 2G NIOS2 version.
3998 + Copyright (C) 2003 Altera
3999 + Contributed by Jonah Graham (jgraham@altera.com).
4001 +This file is part of GNU CC.
4003 +GNU CC is free software; you can redistribute it and/or modify
4004 +it under the terms of the GNU General Public License as published by
4005 +the Free Software Foundation; either version 2, or (at your option)
4006 +any later version.
4008 +GNU CC is distributed in the hope that it will be useful,
4009 +but WITHOUT ANY WARRANTY; without even the implied warranty of
4010 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4011 +GNU General Public License for more details.
4013 +You should have received a copy of the GNU General Public License
4014 +along with GNU CC; see the file COPYING. If not, write to
4015 +the Free Software Foundation, 59 Temple Place - Suite 330,
4016 +Boston, MA 02111-1307, USA. */
4019 +#include <stdio.h>
4020 +#include "config.h"
4021 +#include "system.h"
4022 +#include "coretypes.h"
4023 +#include "tm.h"
4024 +#include "rtl.h"
4025 +#include "tree.h"
4026 +#include "tm_p.h"
4027 +#include "regs.h"
4028 +#include "hard-reg-set.h"
4029 +#include "real.h"
4030 +#include "insn-config.h"
4031 +#include "conditions.h"
4032 +#include "output.h"
4033 +#include "insn-attr.h"
4034 +#include "flags.h"
4035 +#include "recog.h"
4036 +#include "expr.h"
4037 +#include "toplev.h"
4038 +#include "basic-block.h"
4039 +#include "function.h"
4040 +#include "ggc.h"
4041 +#include "reload.h"
4042 +#include "debug.h"
4043 +#include "optabs.h"
4044 +#include "target.h"
4045 +#include "target-def.h"
4047 +/* local prototypes */
4048 +static bool nios2_rtx_costs (rtx, int, int, int *);
4050 +static void nios2_asm_function_prologue (FILE *, HOST_WIDE_INT);
4051 +static int nios2_use_dfa_pipeline_interface (void);
4052 +static int nios2_issue_rate (void);
4053 +static struct machine_function *nios2_init_machine_status (void);
4054 +static bool nios2_in_small_data_p (tree);
4055 +static rtx save_reg (int, HOST_WIDE_INT, rtx);
4056 +static rtx restore_reg (int, HOST_WIDE_INT);
4057 +static unsigned int nios2_section_type_flags (tree, const char *, int);
4058 +static void nios2_init_builtins (void);
4059 +static rtx nios2_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
4060 +static bool nios2_function_ok_for_sibcall (tree, tree);
4061 +static void nios2_encode_section_info (tree, rtx, int);
4063 +/* Initialize the GCC target structure. */
4064 +#undef TARGET_ASM_FUNCTION_PROLOGUE
4065 +#define TARGET_ASM_FUNCTION_PROLOGUE nios2_asm_function_prologue
4067 +#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
4068 +#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE \
4069 + nios2_use_dfa_pipeline_interface
4070 +#undef TARGET_SCHED_ISSUE_RATE
4071 +#define TARGET_SCHED_ISSUE_RATE nios2_issue_rate
4072 +#undef TARGET_IN_SMALL_DATA_P
4073 +#define TARGET_IN_SMALL_DATA_P nios2_in_small_data_p
4074 +#undef TARGET_ENCODE_SECTION_INFO
4075 +#define TARGET_ENCODE_SECTION_INFO nios2_encode_section_info
4076 +#undef TARGET_SECTION_TYPE_FLAGS
4077 +#define TARGET_SECTION_TYPE_FLAGS nios2_section_type_flags
4079 +#undef TARGET_INIT_BUILTINS
4080 +#define TARGET_INIT_BUILTINS nios2_init_builtins
4081 +#undef TARGET_EXPAND_BUILTIN
4082 +#define TARGET_EXPAND_BUILTIN nios2_expand_builtin
4084 +#undef TARGET_FUNCTION_OK_FOR_SIBCALL
4085 +#define TARGET_FUNCTION_OK_FOR_SIBCALL nios2_function_ok_for_sibcall
4087 +#undef TARGET_RTX_COSTS
4088 +#define TARGET_RTX_COSTS nios2_rtx_costs
4091 +struct gcc_target targetm = TARGET_INITIALIZER;
4095 +/* Threshold for data being put into the small data/bss area, instead
4096 + of the normal data area (references to the small data/bss area take
4097 + 1 instruction, and use the global pointer, references to the normal
4098 + data area takes 2 instructions). */
4099 +unsigned HOST_WIDE_INT nios2_section_threshold = NIOS2_DEFAULT_GVALUE;
4102 +/* Structure to be filled in by compute_frame_size with register
4103 + save masks, and offsets for the current function. */
4105 +struct nios2_frame_info
4106 +GTY (())
4108 + long total_size; /* # bytes that the entire frame takes up */
4109 + long var_size; /* # bytes that variables take up */
4110 + long args_size; /* # bytes that outgoing arguments take up */
4111 + int save_reg_size; /* # bytes needed to store gp regs */
4112 + int save_reg_rounded; /* # bytes needed to store gp regs */
4113 + long save_regs_offset; /* offset from new sp to store gp registers */
4114 + int initialized; /* != 0 if frame size already calculated */
4115 + int num_regs; /* number of gp registers saved */
4118 +struct machine_function
4119 +GTY (())
4122 + /* Current frame information, calculated by compute_frame_size. */
4123 + struct nios2_frame_info frame;
4127 +/***************************************
4128 + * Section encodings
4129 + ***************************************/
4135 +/***************************************
4136 + * Stack Layout and Calling Conventions
4137 + ***************************************/
4140 +#define TOO_BIG_OFFSET(X) ((X) > ((1 << 15) - 1))
4141 +#define TEMP_REG_NUM 8
4143 +static void
4144 +nios2_asm_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
4146 + if (flag_verbose_asm || flag_debug_asm)
4148 + compute_frame_size ();
4149 + dump_frame_size (file);
4153 +static rtx
4154 +save_reg (int regno, HOST_WIDE_INT offset, rtx cfa_store_reg)
4156 + rtx insn, stack_slot;
4158 + stack_slot = gen_rtx_PLUS (SImode,
4159 + cfa_store_reg,
4160 + GEN_INT (offset));
4162 + insn = emit_insn (gen_rtx_SET (SImode,
4163 + gen_rtx_MEM (SImode, stack_slot),
4164 + gen_rtx_REG (SImode, regno)));
4166 + RTX_FRAME_RELATED_P (insn) = 1;
4168 + return insn;
4171 +static rtx
4172 +restore_reg (int regno, HOST_WIDE_INT offset)
4174 + rtx insn, stack_slot;
4176 + if (TOO_BIG_OFFSET (offset))
4178 + stack_slot = gen_rtx_REG (SImode, TEMP_REG_NUM);
4179 + insn = emit_insn (gen_rtx_SET (SImode,
4180 + stack_slot,
4181 + GEN_INT (offset)));
4183 + insn = emit_insn (gen_rtx_SET (SImode,
4184 + stack_slot,
4185 + gen_rtx_PLUS (SImode,
4186 + stack_slot,
4187 + stack_pointer_rtx)));
4189 + else
4191 + stack_slot = gen_rtx_PLUS (SImode,
4192 + stack_pointer_rtx,
4193 + GEN_INT (offset));
4196 + stack_slot = gen_rtx_MEM (SImode, stack_slot);
4198 + insn = emit_move_insn (gen_rtx_REG (SImode, regno), stack_slot);
4200 + return insn;
4204 +/* There are two possible paths for prologue expansion,
4205 +- the first is if the total frame size is < 2^15-1. In that
4206 +case all the immediates will fit into the 16-bit immediate
4207 +fields.
4208 +- the second is when the frame size is too big, in that
4209 +case an additional temporary register is used, first
4210 +as a cfa_temp to offset the sp, second as the cfa_store
4211 +register.
4213 +See the comment above dwarf2out_frame_debug_expr in
4214 +dwarf2out.c for more explanation of the "rules."
4217 +Case 1:
4218 +Rule # Example Insn Effect
4219 +2 addi sp, sp, -total_frame_size cfa.reg=sp, cfa.offset=total_frame_size
4220 + cfa_store.reg=sp, cfa_store.offset=total_frame_size
4221 +12 stw ra, offset(sp)
4222 +12 stw r16, offset(sp)
4223 +1 mov fp, sp
4225 +Case 2:
4226 +Rule # Example Insn Effect
4227 +6 movi r8, total_frame_size cfa_temp.reg=r8, cfa_temp.offset=total_frame_size
4228 +2 sub sp, sp, r8 cfa.reg=sp, cfa.offset=total_frame_size
4229 + cfa_store.reg=sp, cfa_store.offset=total_frame_size
4230 +5 add r8, r8, sp cfa_store.reg=r8, cfa_store.offset=0
4231 +12 stw ra, offset(r8)
4232 +12 stw r16, offset(r8)
4233 +1 mov fp, sp
4237 +void
4238 +expand_prologue ()
4240 + int i;
4241 + HOST_WIDE_INT total_frame_size;
4242 + int cfa_store_offset;
4243 + rtx insn;
4244 + rtx cfa_store_reg = 0;
4246 + total_frame_size = compute_frame_size ();
4248 + if (total_frame_size)
4251 + if (TOO_BIG_OFFSET (total_frame_size))
4253 + /* cfa_temp and cfa_store_reg are the same register,
4254 + cfa_store_reg overwrites cfa_temp */
4255 + cfa_store_reg = gen_rtx_REG (SImode, TEMP_REG_NUM);
4256 + insn = emit_insn (gen_rtx_SET (SImode,
4257 + cfa_store_reg,
4258 + GEN_INT (total_frame_size)));
4260 + RTX_FRAME_RELATED_P (insn) = 1;
4263 + insn = gen_rtx_SET (SImode,
4264 + stack_pointer_rtx,
4265 + gen_rtx_MINUS (SImode,
4266 + stack_pointer_rtx,
4267 + cfa_store_reg));
4269 + insn = emit_insn (insn);
4270 + RTX_FRAME_RELATED_P (insn) = 1;
4273 + /* if there are no registers to save, I don't need to
4274 + create a cfa_store */
4275 + if (cfun->machine->frame.save_reg_size)
4277 + insn = gen_rtx_SET (SImode,
4278 + cfa_store_reg,
4279 + gen_rtx_PLUS (SImode,
4280 + cfa_store_reg,
4281 + stack_pointer_rtx));
4283 + insn = emit_insn (insn);
4284 + RTX_FRAME_RELATED_P (insn) = 1;
4287 + cfa_store_offset
4288 + = total_frame_size
4289 + - (cfun->machine->frame.save_regs_offset
4290 + + cfun->machine->frame.save_reg_rounded);
4292 + else
4294 + insn = gen_rtx_SET (SImode,
4295 + stack_pointer_rtx,
4296 + gen_rtx_PLUS (SImode,
4297 + stack_pointer_rtx,
4298 + GEN_INT (-total_frame_size)));
4299 + insn = emit_insn (insn);
4300 + RTX_FRAME_RELATED_P (insn) = 1;
4302 + cfa_store_reg = stack_pointer_rtx;
4303 + cfa_store_offset
4304 + = cfun->machine->frame.save_regs_offset
4305 + + cfun->machine->frame.save_reg_rounded;
4309 + if (MUST_SAVE_REGISTER (RA_REGNO))
4311 + cfa_store_offset -= 4;
4312 + save_reg (RA_REGNO, cfa_store_offset, cfa_store_reg);
4314 + if (MUST_SAVE_REGISTER (FP_REGNO))
4316 + cfa_store_offset -= 4;
4317 + save_reg (FP_REGNO, cfa_store_offset, cfa_store_reg);
4320 + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4322 + if (MUST_SAVE_REGISTER (i) && i != FP_REGNO && i != RA_REGNO)
4324 + cfa_store_offset -= 4;
4325 + save_reg (i, cfa_store_offset, cfa_store_reg);
4329 + if (frame_pointer_needed)
4331 + insn = emit_insn (gen_rtx_SET (SImode,
4332 + gen_rtx_REG (SImode, FP_REGNO),
4333 + gen_rtx_REG (SImode, SP_REGNO)));
4335 + RTX_FRAME_RELATED_P (insn) = 1;
4338 + /* If we are profiling, make sure no instructions are scheduled before
4339 + the call to mcount. */
4340 + if (current_function_profile)
4341 + emit_insn (gen_blockage ());
4344 +void
4345 +expand_epilogue (bool sibcall_p)
4347 + rtx insn;
4348 + int i;
4349 + HOST_WIDE_INT total_frame_size;
4350 + int register_store_offset;
4352 + total_frame_size = compute_frame_size ();
4354 + if (!sibcall_p && nios2_can_use_return_insn ())
4356 + insn = emit_jump_insn (gen_return ());
4357 + return;
4360 + emit_insn (gen_blockage ());
4362 + register_store_offset =
4363 + cfun->machine->frame.save_regs_offset +
4364 + cfun->machine->frame.save_reg_rounded;
4366 + if (MUST_SAVE_REGISTER (RA_REGNO))
4368 + register_store_offset -= 4;
4369 + restore_reg (RA_REGNO, register_store_offset);
4372 + if (MUST_SAVE_REGISTER (FP_REGNO))
4374 + register_store_offset -= 4;
4375 + restore_reg (FP_REGNO, register_store_offset);
4378 + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
4380 + if (MUST_SAVE_REGISTER (i) && i != FP_REGNO && i != RA_REGNO)
4382 + register_store_offset -= 4;
4383 + restore_reg (i, register_store_offset);
4387 + if (total_frame_size)
4389 + rtx sp_adjust;
4391 + if (TOO_BIG_OFFSET (total_frame_size))
4393 + sp_adjust = gen_rtx_REG (SImode, TEMP_REG_NUM);
4394 + insn = emit_insn (gen_rtx_SET (SImode,
4395 + sp_adjust,
4396 + GEN_INT (total_frame_size)));
4399 + else
4401 + sp_adjust = GEN_INT (total_frame_size);
4404 + insn = gen_rtx_SET (SImode,
4405 + stack_pointer_rtx,
4406 + gen_rtx_PLUS (SImode,
4407 + stack_pointer_rtx,
4408 + sp_adjust));
4409 + insn = emit_insn (insn);
4413 + if (!sibcall_p)
4415 + insn = emit_jump_insn (gen_return_from_epilogue (gen_rtx (REG, Pmode,
4416 + RA_REGNO)));
4421 +bool
4422 +nios2_function_ok_for_sibcall (tree a ATTRIBUTE_UNUSED, tree b ATTRIBUTE_UNUSED)
4424 + return true;
4431 +/* ----------------------- *
4432 + * Profiling
4433 + * ----------------------- */
4435 +void
4436 +function_profiler (FILE *file, int labelno)
4438 + fprintf (file, "\t%s mcount begin, label: .LP%d\n",
4439 + ASM_COMMENT_START, labelno);
4440 + fprintf (file, "\tnextpc\tr8\n");
4441 + fprintf (file, "\tmov\tr9, ra\n");
4442 + fprintf (file, "\tmovhi\tr10, %%hiadj(.LP%d)\n", labelno);
4443 + fprintf (file, "\taddi\tr10, r10, %%lo(.LP%d)\n", labelno);
4444 + fprintf (file, "\tcall\tmcount\n");
4445 + fprintf (file, "\tmov\tra, r9\n");
4446 + fprintf (file, "\t%s mcount end\n", ASM_COMMENT_START);
4450 +/***************************************
4451 + * Stack Layout
4452 + ***************************************/
4455 +void
4456 +dump_frame_size (FILE *file)
4458 + fprintf (file, "\t%s Current Frame Info\n", ASM_COMMENT_START);
4460 + fprintf (file, "\t%s total_size = %ld\n", ASM_COMMENT_START,
4461 + cfun->machine->frame.total_size);
4462 + fprintf (file, "\t%s var_size = %ld\n", ASM_COMMENT_START,
4463 + cfun->machine->frame.var_size);
4464 + fprintf (file, "\t%s args_size = %ld\n", ASM_COMMENT_START,
4465 + cfun->machine->frame.args_size);
4466 + fprintf (file, "\t%s save_reg_size = %d\n", ASM_COMMENT_START,
4467 + cfun->machine->frame.save_reg_size);
4468 + fprintf (file, "\t%s save_reg_rounded = %d\n", ASM_COMMENT_START,
4469 + cfun->machine->frame.save_reg_rounded);
4470 + fprintf (file, "\t%s initialized = %d\n", ASM_COMMENT_START,
4471 + cfun->machine->frame.initialized);
4472 + fprintf (file, "\t%s num_regs = %d\n", ASM_COMMENT_START,
4473 + cfun->machine->frame.num_regs);
4474 + fprintf (file, "\t%s save_regs_offset = %ld\n", ASM_COMMENT_START,
4475 + cfun->machine->frame.save_regs_offset);
4476 + fprintf (file, "\t%s current_function_is_leaf = %d\n", ASM_COMMENT_START,
4477 + current_function_is_leaf);
4478 + fprintf (file, "\t%s frame_pointer_needed = %d\n", ASM_COMMENT_START,
4479 + frame_pointer_needed);
4480 + fprintf (file, "\t%s pretend_args_size = %d\n", ASM_COMMENT_START,
4481 + current_function_pretend_args_size);
4486 +/* Return the bytes needed to compute the frame pointer from the current
4487 + stack pointer.
4490 +HOST_WIDE_INT
4491 +compute_frame_size ()
4493 + unsigned int regno;
4494 + HOST_WIDE_INT var_size; /* # of var. bytes allocated */
4495 + HOST_WIDE_INT total_size; /* # bytes that the entire frame takes up */
4496 + HOST_WIDE_INT save_reg_size; /* # bytes needed to store callee save regs */
4497 + HOST_WIDE_INT save_reg_rounded;
4498 + /* # bytes needed to store callee save regs (rounded) */
4499 + HOST_WIDE_INT out_args_size; /* # bytes needed for outgoing args */
4501 + save_reg_size = 0;
4502 + var_size = STACK_ALIGN (get_frame_size ());
4503 + out_args_size = STACK_ALIGN (current_function_outgoing_args_size);
4505 + total_size = var_size + out_args_size;
4507 + /* Calculate space needed for gp registers. */
4508 + for (regno = 0; regno <= FIRST_PSEUDO_REGISTER; regno++)
4510 + if (MUST_SAVE_REGISTER (regno))
4512 + save_reg_size += 4;
4516 + save_reg_rounded = STACK_ALIGN (save_reg_size);
4517 + total_size += save_reg_rounded;
4519 + total_size += STACK_ALIGN (current_function_pretend_args_size);
4521 + /* Save other computed information. */
4522 + cfun->machine->frame.total_size = total_size;
4523 + cfun->machine->frame.var_size = var_size;
4524 + cfun->machine->frame.args_size = current_function_outgoing_args_size;
4525 + cfun->machine->frame.save_reg_size = save_reg_size;
4526 + cfun->machine->frame.save_reg_rounded = save_reg_rounded;
4527 + cfun->machine->frame.initialized = reload_completed;
4528 + cfun->machine->frame.num_regs = save_reg_size / UNITS_PER_WORD;
4530 + cfun->machine->frame.save_regs_offset
4531 + = save_reg_rounded ? current_function_outgoing_args_size + var_size : 0;
4533 + return total_size;
4537 +int
4538 +nios2_initial_elimination_offset (int from, int to ATTRIBUTE_UNUSED)
4540 + int offset;
4542 + /* Set OFFSET to the offset from the stack pointer. */
4543 + switch (from)
4545 + case FRAME_POINTER_REGNUM:
4546 + offset = 0;
4547 + break;
4549 + case ARG_POINTER_REGNUM:
4550 + compute_frame_size ();
4551 + offset = cfun->machine->frame.total_size;
4552 + offset -= current_function_pretend_args_size;
4553 + break;
4555 + case RETURN_ADDRESS_POINTER_REGNUM:
4556 + compute_frame_size ();
4557 + /* since the return address is always the first of the
4558 + saved registers, return the offset to the beginning
4559 + of the saved registers block */
4560 + offset = cfun->machine->frame.save_regs_offset;
4561 + break;
4563 + default:
4564 + abort ();
4567 + return offset;
4570 +/* Return nonzero if this function is known to have a null epilogue.
4571 + This allows the optimizer to omit jumps to jumps if no stack
4572 + was created. */
4573 +int
4574 +nios2_can_use_return_insn ()
4576 + if (!reload_completed)
4577 + return 0;
4579 + if (regs_ever_live[RA_REGNO] || current_function_profile)
4580 + return 0;
4582 + if (cfun->machine->frame.initialized)
4583 + return cfun->machine->frame.total_size == 0;
4585 + return compute_frame_size () == 0;
4592 +/***************************************
4594 + ***************************************/
4596 +const char *nios2_sys_nosys_string; /* for -msys=nosys */
4597 +const char *nios2_sys_lib_string; /* for -msys-lib= */
4598 +const char *nios2_sys_crt0_string; /* for -msys-crt0= */
4600 +void
4601 +override_options ()
4603 + /* Function to allocate machine-dependent function status. */
4604 + init_machine_status = &nios2_init_machine_status;
4606 + nios2_section_threshold
4607 + = g_switch_set ? g_switch_value : NIOS2_DEFAULT_GVALUE;
4609 + if (nios2_sys_nosys_string && *nios2_sys_nosys_string)
4611 + error ("invalid option '-msys=nosys%s'", nios2_sys_nosys_string);
4614 + /* If we don't have mul, we don't have mulx either! */
4615 + if (!TARGET_HAS_MUL && TARGET_HAS_MULX)
4617 + target_flags &= ~HAS_MULX_FLAG;
4622 +void
4623 +optimization_options (int level, int size)
4625 + if (level || size)
4627 + target_flags |= INLINE_MEMCPY_FLAG;
4630 + if (level >= 3 && !size)
4632 + target_flags |= FAST_SW_DIV_FLAG;
4636 +/* Allocate a chunk of memory for per-function machine-dependent data. */
4637 +static struct machine_function *
4638 +nios2_init_machine_status ()
4640 + return ((struct machine_function *)
4641 + ggc_alloc_cleared (sizeof (struct machine_function)));
4646 +/*****************
4647 + * Describing Relative Costs of Operations
4648 + *****************/
4650 +/* Compute a (partial) cost for rtx X. Return true if the complete
4651 + cost has been computed, and false if subexpressions should be
4652 + scanned. In either case, *TOTAL contains the cost result. */
4656 +static bool
4657 +nios2_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total)
4659 + switch (code)
4661 + case CONST_INT:
4662 + if (INTVAL (x) == 0)
4664 + *total = COSTS_N_INSNS (0);
4665 + return true;
4667 + else if (SMALL_INT (INTVAL (x))
4668 + || SMALL_INT_UNSIGNED (INTVAL (x))
4669 + || UPPER16_INT (INTVAL (x)))
4671 + *total = COSTS_N_INSNS (2);
4672 + return true;
4674 + else
4676 + *total = COSTS_N_INSNS (4);
4677 + return true;
4680 + case LABEL_REF:
4681 + case SYMBOL_REF:
4682 + /* ??? gp relative stuff will fit in here */
4683 + /* fall through */
4684 + case CONST:
4685 + case CONST_DOUBLE:
4687 + *total = COSTS_N_INSNS (4);
4688 + return true;
4691 + case MULT:
4693 + *total = COSTS_N_INSNS (1);
4694 + return false;
4696 + case SIGN_EXTEND:
4698 + *total = COSTS_N_INSNS (3);
4699 + return false;
4701 + case ZERO_EXTEND:
4703 + *total = COSTS_N_INSNS (1);
4704 + return false;
4707 + default:
4708 + return false;
4713 +/***************************************
4714 + * INSTRUCTION SUPPORT
4716 + * These functions are used within the Machine Description to
4717 + * handle common or complicated output and expansions from
4718 + * instructions.
4719 + ***************************************/
4721 +int
4722 +nios2_emit_move_sequence (rtx *operands, enum machine_mode mode)
4724 + rtx to = operands[0];
4725 + rtx from = operands[1];
4727 + if (!register_operand (to, mode) && !reg_or_0_operand (from, mode))
4729 + if (no_new_pseudos)
4730 + internal_error ("Trying to force_reg no_new_pseudos == 1");
4731 + from = copy_to_mode_reg (mode, from);
4734 + operands[0] = to;
4735 + operands[1] = from;
4736 + return 0;
4739 +/* Divide Support */
4742 + If -O3 is used, we want to output a table lookup for
4743 + divides between small numbers (both num and den >= 0
4744 + and < 0x10). The overhead of this method in the worse
4745 + case is 40 bytes in the text section (10 insns) and
4746 + 256 bytes in the data section. Additional divides do
4747 + not incur additional penalties in the data section.
4749 + Code speed is improved for small divides by about 5x
4750 + when using this method in the worse case (~9 cycles
4751 + vs ~45). And in the worse case divides not within the
4752 + table are penalized by about 10% (~5 cycles vs ~45).
4753 + However in the typical case the penalty is not as bad
4754 + because doing the long divide in only 45 cycles is
4755 + quite optimistic.
4757 + ??? It would be nice to have some benchmarks other
4758 + than Dhrystone to back this up.
4760 + This bit of expansion is to create this instruction
4761 + sequence as rtl.
4762 + or $8, $4, $5
4763 + slli $9, $4, 4
4764 + cmpgeui $3, $8, 16
4765 + beq $3, $0, .L3
4766 + or $10, $9, $5
4767 + add $12, $11, divide_table
4768 + ldbu $2, 0($12)
4769 + br .L1
4770 +.L3:
4771 + call slow_div
4772 +.L1:
4773 +# continue here with result in $2
4775 + ??? Ideally I would like the emit libcall block to contain
4776 + all of this code, but I don't know how to do that. What it
4777 + means is that if the divide can be eliminated, it may not
4778 + completely disappear.
4780 + ??? The __divsi3_table label should ideally be moved out
4781 + of this block and into a global. If it is placed into the
4782 + sdata section we can save even more cycles by doing things
4783 + gp relative.
4785 +int
4786 +nios2_emit_expensive_div (rtx *operands, enum machine_mode mode)
4788 + rtx or_result, shift_left_result;
4789 + rtx lookup_value;
4790 + rtx lab1, lab3;
4791 + rtx insns;
4792 + rtx libfunc;
4793 + rtx final_result;
4794 + rtx tmp;
4796 + /* it may look a little generic, but only SImode
4797 + is supported for now */
4798 + if (mode != SImode)
4799 + abort ();
4801 + libfunc = sdiv_optab->handlers[(int) SImode].libfunc;
4805 + lab1 = gen_label_rtx ();
4806 + lab3 = gen_label_rtx ();
4808 + or_result = expand_simple_binop (SImode, IOR,
4809 + operands[1], operands[2],
4810 + 0, 0, OPTAB_LIB_WIDEN);
4812 + emit_cmp_and_jump_insns (or_result, GEN_INT (15), GTU, 0,
4813 + GET_MODE (or_result), 0, lab3);
4814 + JUMP_LABEL (get_last_insn ()) = lab3;
4816 + shift_left_result = expand_simple_binop (SImode, ASHIFT,
4817 + operands[1], GEN_INT (4),
4818 + 0, 0, OPTAB_LIB_WIDEN);
4820 + lookup_value = expand_simple_binop (SImode, IOR,
4821 + shift_left_result, operands[2],
4822 + 0, 0, OPTAB_LIB_WIDEN);
4824 + convert_move (operands[0],
4825 + gen_rtx (MEM, QImode,
4826 + gen_rtx (PLUS, SImode,
4827 + lookup_value,
4828 + gen_rtx_SYMBOL_REF (SImode, "__divsi3_table"))),
4829 + 1);
4832 + tmp = emit_jump_insn (gen_jump (lab1));
4833 + JUMP_LABEL (tmp) = lab1;
4834 + emit_barrier ();
4836 + emit_label (lab3);
4837 + LABEL_NUSES (lab3) = 1;
4839 + start_sequence ();
4840 + final_result = emit_library_call_value (libfunc, NULL_RTX,
4841 + LCT_CONST, SImode, 2,
4842 + operands[1], SImode,
4843 + operands[2], SImode);
4846 + insns = get_insns ();
4847 + end_sequence ();
4848 + emit_libcall_block (insns, operands[0], final_result,
4849 + gen_rtx (DIV, SImode, operands[1], operands[2]));
4851 + emit_label (lab1);
4852 + LABEL_NUSES (lab1) = 1;
4853 + return 1;
4856 +/* Branches/Compares */
4858 +/* the way of handling branches/compares
4859 + in gcc is heavily borrowed from MIPS */
4861 +enum internal_test
4863 + ITEST_EQ,
4864 + ITEST_NE,
4865 + ITEST_GT,
4866 + ITEST_GE,
4867 + ITEST_LT,
4868 + ITEST_LE,
4869 + ITEST_GTU,
4870 + ITEST_GEU,
4871 + ITEST_LTU,
4872 + ITEST_LEU,
4873 + ITEST_MAX
4876 +static enum internal_test map_test_to_internal_test (enum rtx_code);
4878 +/* Cached operands, and operator to compare for use in set/branch/trap
4879 + on condition codes. */
4880 +rtx branch_cmp[2];
4881 +enum cmp_type branch_type;
4883 +/* Make normal rtx_code into something we can index from an array */
4885 +static enum internal_test
4886 +map_test_to_internal_test (enum rtx_code test_code)
4888 + enum internal_test test = ITEST_MAX;
4890 + switch (test_code)
4892 + case EQ:
4893 + test = ITEST_EQ;
4894 + break;
4895 + case NE:
4896 + test = ITEST_NE;
4897 + break;
4898 + case GT:
4899 + test = ITEST_GT;
4900 + break;
4901 + case GE:
4902 + test = ITEST_GE;
4903 + break;
4904 + case LT:
4905 + test = ITEST_LT;
4906 + break;
4907 + case LE:
4908 + test = ITEST_LE;
4909 + break;
4910 + case GTU:
4911 + test = ITEST_GTU;
4912 + break;
4913 + case GEU:
4914 + test = ITEST_GEU;
4915 + break;
4916 + case LTU:
4917 + test = ITEST_LTU;
4918 + break;
4919 + case LEU:
4920 + test = ITEST_LEU;
4921 + break;
4922 + default:
4923 + break;
4926 + return test;
4929 +/* Generate the code to compare (and possibly branch) two integer values
4930 + TEST_CODE is the comparison code we are trying to emulate
4931 + (or implement directly)
4932 + RESULT is where to store the result of the comparison,
4933 + or null to emit a branch
4934 + CMP0 CMP1 are the two comparison operands
4935 + DESTINATION is the destination of the branch, or null to only compare
4936 + */
4938 +void
4939 +gen_int_relational (enum rtx_code test_code, /* relational test (EQ, etc) */
4940 + rtx result, /* result to store comp. or 0 if branch */
4941 + rtx cmp0, /* first operand to compare */
4942 + rtx cmp1, /* second operand to compare */
4943 + rtx destination) /* destination of the branch, or 0 if compare */
4945 + struct cmp_info
4947 + /* for register (or 0) compares */
4948 + enum rtx_code test_code_reg; /* code to use in instruction (LT vs. LTU) */
4949 + int reverse_regs; /* reverse registers in test */
4951 + /* for immediate compares */
4952 + enum rtx_code test_code_const;
4953 + /* code to use in instruction (LT vs. LTU) */
4954 + int const_low; /* low bound of constant we can accept */
4955 + int const_high; /* high bound of constant we can accept */
4956 + int const_add; /* constant to add */
4958 + /* generic info */
4959 + int unsignedp; /* != 0 for unsigned comparisons. */
4960 + };
4962 + static const struct cmp_info info[(int) ITEST_MAX] = {
4964 + {EQ, 0, EQ, -32768, 32767, 0, 0}, /* EQ */
4965 + {NE, 0, NE, -32768, 32767, 0, 0}, /* NE */
4967 + {LT, 1, GE, -32769, 32766, 1, 0}, /* GT */
4968 + {GE, 0, GE, -32768, 32767, 0, 0}, /* GE */
4969 + {LT, 0, LT, -32768, 32767, 0, 0}, /* LT */
4970 + {GE, 1, LT, -32769, 32766, 1, 0}, /* LE */
4972 + {LTU, 1, GEU, 0, 65534, 1, 0}, /* GTU */
4973 + {GEU, 0, GEU, 0, 65535, 0, 0}, /* GEU */
4974 + {LTU, 0, LTU, 0, 65535, 0, 0}, /* LTU */
4975 + {GEU, 1, LTU, 0, 65534, 1, 0}, /* LEU */
4976 + };
4978 + enum internal_test test;
4979 + enum machine_mode mode;
4980 + const struct cmp_info *p_info;
4981 + int branch_p;
4986 + test = map_test_to_internal_test (test_code);
4987 + if (test == ITEST_MAX)
4988 + abort ();
4990 + p_info = &info[(int) test];
4992 + mode = GET_MODE (cmp0);
4993 + if (mode == VOIDmode)
4994 + mode = GET_MODE (cmp1);
4996 + branch_p = (destination != 0);
4998 + /* We can't, under any circumstances, have const_ints in cmp0
4999 + ??? Actually we could have const0 */
5000 + if (GET_CODE (cmp0) == CONST_INT)
5001 + cmp0 = force_reg (mode, cmp0);
5003 + /* if the comparison is against an int not in legal range
5004 + move it into a register */
5005 + if (GET_CODE (cmp1) == CONST_INT)
5007 + HOST_WIDE_INT value = INTVAL (cmp1);
5009 + if (value < p_info->const_low || value > p_info->const_high)
5010 + cmp1 = force_reg (mode, cmp1);
5013 + /* Comparison to constants, may involve adding 1 to change a GT into GE.
5014 + Comparison between two registers, may involve switching operands. */
5015 + if (GET_CODE (cmp1) == CONST_INT)
5017 + if (p_info->const_add != 0)
5019 + HOST_WIDE_INT new = INTVAL (cmp1) + p_info->const_add;
5021 + /* If modification of cmp1 caused overflow,
5022 + we would get the wrong answer if we follow the usual path;
5023 + thus, x > 0xffffffffU would turn into x > 0U. */
5024 + if ((p_info->unsignedp
5025 + ? (unsigned HOST_WIDE_INT) new >
5026 + (unsigned HOST_WIDE_INT) INTVAL (cmp1)
5027 + : new > INTVAL (cmp1)) != (p_info->const_add > 0))
5029 + /* ??? This case can never happen with the current numbers,
5030 + but I am paranoid and would rather an abort than
5031 + a bug I will never find */
5032 + abort ();
5034 + else
5035 + cmp1 = GEN_INT (new);
5039 + else if (p_info->reverse_regs)
5041 + rtx temp = cmp0;
5042 + cmp0 = cmp1;
5043 + cmp1 = temp;
5048 + if (branch_p)
5050 + if (register_operand (cmp0, mode) && register_operand (cmp1, mode))
5052 + rtx insn;
5053 + rtx cond = gen_rtx (p_info->test_code_reg, mode, cmp0, cmp1);
5054 + rtx label = gen_rtx_LABEL_REF (VOIDmode, destination);
5056 + insn = gen_rtx_SET (VOIDmode, pc_rtx,
5057 + gen_rtx_IF_THEN_ELSE (VOIDmode,
5058 + cond, label, pc_rtx));
5059 + emit_jump_insn (insn);
5061 + else
5063 + rtx cond, label;
5065 + result = gen_reg_rtx (mode);
5067 + emit_move_insn (result,
5068 + gen_rtx (p_info->test_code_const, mode, cmp0,
5069 + cmp1));
5071 + cond = gen_rtx (NE, mode, result, const0_rtx);
5072 + label = gen_rtx_LABEL_REF (VOIDmode, destination);
5074 + emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
5075 + gen_rtx_IF_THEN_ELSE (VOIDmode,
5076 + cond,
5077 + label, pc_rtx)));
5080 + else
5082 + if (register_operand (cmp0, mode) && register_operand (cmp1, mode))
5084 + emit_move_insn (result,
5085 + gen_rtx (p_info->test_code_reg, mode, cmp0, cmp1));
5087 + else
5089 + emit_move_insn (result,
5090 + gen_rtx (p_info->test_code_const, mode, cmp0,
5091 + cmp1));
5098 +/* ??? For now conditional moves are only supported
5099 + when the mode of the operands being compared are
5100 + the same as the ones being moved */
5102 +void
5103 +gen_conditional_move (rtx *operands, enum machine_mode mode)
5105 + rtx insn, cond;
5106 + rtx cmp_reg = gen_reg_rtx (mode);
5107 + enum rtx_code cmp_code = GET_CODE (operands[1]);
5108 + enum rtx_code move_code = EQ;
5110 + /* emit a comparison if it is not "simple".
5111 + Simple comparisons are X eq 0 and X ne 0 */
5112 + if ((cmp_code == EQ || cmp_code == NE) && branch_cmp[1] == const0_rtx)
5114 + cmp_reg = branch_cmp[0];
5115 + move_code = cmp_code;
5117 + else if ((cmp_code == EQ || cmp_code == NE) && branch_cmp[0] == const0_rtx)
5119 + cmp_reg = branch_cmp[1];
5120 + move_code = cmp_code == EQ ? NE : EQ;
5122 + else
5123 + gen_int_relational (cmp_code, cmp_reg, branch_cmp[0], branch_cmp[1],
5124 + NULL_RTX);
5126 + cond = gen_rtx (move_code, VOIDmode, cmp_reg, CONST0_RTX (mode));
5127 + insn = gen_rtx_SET (mode, operands[0],
5128 + gen_rtx_IF_THEN_ELSE (mode,
5129 + cond, operands[2], operands[3]));
5130 + emit_insn (insn);
5133 +/*******************
5134 + * Addressing Modes
5135 + *******************/
5137 +int
5138 +nios2_legitimate_address (rtx operand, enum machine_mode mode ATTRIBUTE_UNUSED,
5139 + int strict)
5141 + int ret_val = 0;
5143 + switch (GET_CODE (operand))
5145 + /* direct. */
5146 + case SYMBOL_REF:
5147 + if (SYMBOL_REF_IN_NIOS2_SMALL_DATA_P (operand))
5149 + ret_val = 1;
5150 + break;
5152 + /* else, fall through */
5153 + case LABEL_REF:
5154 + case CONST_INT:
5155 + case CONST:
5156 + case CONST_DOUBLE:
5157 + /* ??? In here I need to add gp addressing */
5158 + ret_val = 0;
5160 + break;
5162 + /* Register indirect. */
5163 + case REG:
5164 + ret_val = REG_OK_FOR_BASE_P2 (operand, strict);
5165 + break;
5167 + /* Register indirect with displacement */
5168 + case PLUS:
5170 + rtx op0 = XEXP (operand, 0);
5171 + rtx op1 = XEXP (operand, 1);
5173 + if (REG_P (op0) && REG_P (op1))
5174 + ret_val = 0;
5175 + else if (REG_P (op0) && CONSTANT_P (op1))
5176 + ret_val = REG_OK_FOR_BASE_P2 (op0, strict)
5177 + && SMALL_INT (INTVAL (op1));
5178 + else if (REG_P (op1) && CONSTANT_P (op0))
5179 + ret_val = REG_OK_FOR_BASE_P2 (op1, strict)
5180 + && SMALL_INT (INTVAL (op0));
5181 + else
5182 + ret_val = 0;
5184 + break;
5186 + default:
5187 + ret_val = 0;
5188 + break;
5191 + return ret_val;
5194 +/* Return true if EXP should be placed in the small data section. */
5196 +static bool
5197 +nios2_in_small_data_p (tree exp)
5199 + /* We want to merge strings, so we never consider them small data. */
5200 + if (TREE_CODE (exp) == STRING_CST)
5201 + return false;
5203 + if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp))
5205 + const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp));
5206 + /* ??? these string names need moving into
5207 + an array in some header file */
5208 + if (nios2_section_threshold > 0
5209 + && (strcmp (section, ".sbss") == 0
5210 + || strncmp (section, ".sbss.", 6) == 0
5211 + || strcmp (section, ".sdata") == 0
5212 + || strncmp (section, ".sdata.", 7) == 0))
5213 + return true;
5215 + else if (TREE_CODE (exp) == VAR_DECL)
5217 + HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
5219 + /* If this is an incomplete type with size 0, then we can't put it
5220 + in sdata because it might be too big when completed. */
5221 + if (size > 0 && size <= nios2_section_threshold)
5222 + return true;
5225 + return false;
5228 +static void
5229 +nios2_encode_section_info (tree decl, rtx rtl, int first)
5232 + rtx symbol;
5233 + int flags;
5235 + default_encode_section_info (decl, rtl, first);
5237 + /* Careful not to prod global register variables. */
5238 + if (GET_CODE (rtl) != MEM)
5239 + return;
5240 + symbol = XEXP (rtl, 0);
5241 + if (GET_CODE (symbol) != SYMBOL_REF)
5242 + return;
5244 + flags = SYMBOL_REF_FLAGS (symbol);
5246 + /* We don't want weak variables to be addressed with gp in case they end up with
5247 + value 0 which is not within 2^15 of $gp */
5248 + if (DECL_P (decl) && DECL_WEAK (decl))
5249 + flags |= SYMBOL_FLAG_WEAK_DECL;
5251 + SYMBOL_REF_FLAGS (symbol) = flags;
5255 +static unsigned int
5256 +nios2_section_type_flags (tree decl, const char *name, int reloc)
5258 + unsigned int flags;
5260 + flags = default_section_type_flags (decl, name, reloc);
5262 + /* ??? these string names need moving into an array in some header file */
5263 + if (strcmp (name, ".sbss") == 0
5264 + || strncmp (name, ".sbss.", 6) == 0
5265 + || strcmp (name, ".sdata") == 0
5266 + || strncmp (name, ".sdata.", 7) == 0)
5267 + flags |= SECTION_SMALL;
5269 + return flags;
5275 +/*****************************************
5276 + * Defining the Output Assembler Language
5277 + *****************************************/
5279 +/* -------------- *
5280 + * Output of Data
5281 + * -------------- */
5284 +/* -------------------------------- *
5285 + * Output of Assembler Instructions
5286 + * -------------------------------- */
5289 +/* print the operand OP to file stream
5290 + FILE modified by LETTER. LETTER
5291 + can be one of:
5292 + i: print "i" if OP is an immediate, except 0
5293 + o: print "io" if OP is volatile
5295 + z: for const0_rtx print $0 instead of 0
5296 + H: for %hiadj
5297 + L: for %lo
5298 + U: for upper half of 32 bit value
5299 + */
5301 +void
5302 +nios2_print_operand (FILE *file, rtx op, int letter)
5305 + switch (letter)
5307 + case 'i':
5308 + if (CONSTANT_P (op) && (op != const0_rtx))
5309 + fprintf (file, "i");
5310 + return;
5312 + case 'o':
5313 + if (GET_CODE (op) == MEM
5314 + && ((MEM_VOLATILE_P (op) && !TARGET_CACHE_VOLATILE)
5315 + || TARGET_BYPASS_CACHE))
5316 + fprintf (file, "io");
5317 + return;
5319 + default:
5320 + break;
5323 + if (comparison_operator (op, VOIDmode))
5325 + if (letter == 0)
5327 + fprintf (file, "%s", GET_RTX_NAME (GET_CODE (op)));
5328 + return;
5333 + switch (GET_CODE (op))
5335 + case REG:
5336 + if (letter == 0 || letter == 'z')
5338 + fprintf (file, "%s", reg_names[REGNO (op)]);
5339 + return;
5342 + case CONST_INT:
5343 + if (INTVAL (op) == 0 && letter == 'z')
5345 + fprintf (file, "zero");
5346 + return;
5348 + else if (letter == 'U')
5350 + HOST_WIDE_INT val = INTVAL (op);
5351 + rtx new_op;
5352 + val = (val / 65536) & 0xFFFF;
5353 + new_op = GEN_INT (val);
5354 + output_addr_const (file, new_op);
5355 + return;
5358 + /* else, fall through */
5359 + case CONST:
5360 + case LABEL_REF:
5361 + case SYMBOL_REF:
5362 + case CONST_DOUBLE:
5363 + if (letter == 0 || letter == 'z')
5365 + output_addr_const (file, op);
5366 + return;
5368 + else if (letter == 'H')
5370 + fprintf (file, "%%hiadj(");
5371 + output_addr_const (file, op);
5372 + fprintf (file, ")");
5373 + return;
5375 + else if (letter == 'L')
5377 + fprintf (file, "%%lo(");
5378 + output_addr_const (file, op);
5379 + fprintf (file, ")");
5380 + return;
5384 + case SUBREG:
5385 + case MEM:
5386 + if (letter == 0)
5388 + output_address (op);
5389 + return;
5392 + case CODE_LABEL:
5393 + if (letter == 0)
5395 + output_addr_const (file, op);
5396 + return;
5399 + default:
5400 + break;
5403 + fprintf (stderr, "Missing way to print (%c) ", letter);
5404 + debug_rtx (op);
5405 + abort ();
5408 +static int gprel_constant (rtx);
5410 +static int
5411 +gprel_constant (rtx op)
5413 + if (GET_CODE (op) == SYMBOL_REF
5414 + && SYMBOL_REF_IN_NIOS2_SMALL_DATA_P (op))
5416 + return 1;
5418 + else if (GET_CODE (op) == CONST
5419 + && GET_CODE (XEXP (op, 0)) == PLUS)
5421 + return gprel_constant (XEXP (XEXP (op, 0), 0));
5423 + else
5425 + return 0;
5429 +void
5430 +nios2_print_operand_address (FILE *file, rtx op)
5432 + switch (GET_CODE (op))
5434 + case CONST:
5435 + case CONST_INT:
5436 + case LABEL_REF:
5437 + case CONST_DOUBLE:
5438 + case SYMBOL_REF:
5439 + if (gprel_constant (op))
5441 + fprintf (file, "%%gprel(");
5442 + output_addr_const (file, op);
5443 + fprintf (file, ")(%s)", reg_names[GP_REGNO]);
5444 + return;
5447 + break;
5449 + case PLUS:
5451 + rtx op0 = XEXP (op, 0);
5452 + rtx op1 = XEXP (op, 1);
5454 + if (REG_P (op0) && CONSTANT_P (op1))
5456 + output_addr_const (file, op1);
5457 + fprintf (file, "(%s)", reg_names[REGNO (op0)]);
5458 + return;
5460 + else if (REG_P (op1) && CONSTANT_P (op0))
5462 + output_addr_const (file, op0);
5463 + fprintf (file, "(%s)", reg_names[REGNO (op1)]);
5464 + return;
5467 + break;
5469 + case REG:
5470 + fprintf (file, "0(%s)", reg_names[REGNO (op)]);
5471 + return;
5473 + case MEM:
5475 + rtx base = XEXP (op, 0);
5476 + PRINT_OPERAND_ADDRESS (file, base);
5477 + return;
5479 + default:
5480 + break;
5483 + fprintf (stderr, "Missing way to print address\n");
5484 + debug_rtx (op);
5485 + abort ();
5492 +/****************************
5493 + * Predicates
5494 + ****************************/
5496 +int
5497 +arith_operand (rtx op, enum machine_mode mode)
5499 + if (GET_CODE (op) == CONST_INT && SMALL_INT (INTVAL (op)))
5500 + return 1;
5502 + return register_operand (op, mode);
5505 +int
5506 +uns_arith_operand (rtx op, enum machine_mode mode)
5508 + if (GET_CODE (op) == CONST_INT && SMALL_INT_UNSIGNED (INTVAL (op)))
5509 + return 1;
5511 + return register_operand (op, mode);
5514 +int
5515 +logical_operand (rtx op, enum machine_mode mode)
5517 + if (GET_CODE (op) == CONST_INT
5518 + && (SMALL_INT_UNSIGNED (INTVAL (op)) || UPPER16_INT (INTVAL (op))))
5519 + return 1;
5521 + return register_operand (op, mode);
5524 +int
5525 +shift_operand (rtx op, enum machine_mode mode)
5527 + if (GET_CODE (op) == CONST_INT && SHIFT_INT (INTVAL (op)))
5528 + return 1;
5530 + return register_operand (op, mode);
5533 +int
5534 +rdwrctl_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
5536 + return GET_CODE (op) == CONST_INT && RDWRCTL_INT (INTVAL (op));
5539 +/* Return truth value of whether OP is a register or the constant 0. */
5541 +int
5542 +reg_or_0_operand (rtx op, enum machine_mode mode)
5544 + switch (GET_CODE (op))
5546 + case CONST_INT:
5547 + return INTVAL (op) == 0;
5549 + case CONST_DOUBLE:
5550 + return op == CONST0_RTX (mode);
5552 + default:
5553 + break;
5556 + return register_operand (op, mode);
5560 +int
5561 +equality_op (rtx op, enum machine_mode mode)
5563 + if (mode != GET_MODE (op))
5564 + return 0;
5566 + return GET_CODE (op) == EQ || GET_CODE (op) == NE;
5569 +int
5570 +custom_insn_opcode (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
5572 + return GET_CODE (op) == CONST_INT && CUSTOM_INSN_OPCODE (INTVAL (op));
5581 +/*****************************************************************************
5583 +** instruction scheduler
5585 +*****************************************************************************/
5586 +static int
5587 +nios2_use_dfa_pipeline_interface ()
5589 + return 1;
5593 +static int
5594 +nios2_issue_rate ()
5596 +#ifdef MAX_DFA_ISSUE_RATE
5597 + return MAX_DFA_ISSUE_RATE;
5598 +#else
5599 + return 1;
5600 +#endif
5604 +const char *
5605 +asm_output_opcode (FILE *file ATTRIBUTE_UNUSED,
5606 + const char *ptr ATTRIBUTE_UNUSED)
5608 + const char *p;
5610 + p = ptr;
5611 + return ptr;
5616 +/*****************************************************************************
5618 +** function arguments
5620 +*****************************************************************************/
5622 +void
5623 +init_cumulative_args (CUMULATIVE_ARGS *cum,
5624 + tree fntype ATTRIBUTE_UNUSED,
5625 + rtx libname ATTRIBUTE_UNUSED,
5626 + tree fndecl ATTRIBUTE_UNUSED,
5627 + int n_named_args ATTRIBUTE_UNUSED)
5629 + cum->regs_used = 0;
5633 +/* Update the data in CUM to advance over an argument
5634 + of mode MODE and data type TYPE.
5635 + (TYPE is null for libcalls where that information may not be available.) */
5637 +void
5638 +function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
5639 + tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED)
5641 + HOST_WIDE_INT param_size;
5643 + if (mode == BLKmode)
5645 + param_size = int_size_in_bytes (type);
5646 + if (param_size < 0)
5647 + internal_error
5648 + ("Do not know how to handle large structs or variable length types");
5650 + else
5652 + param_size = GET_MODE_SIZE (mode);
5655 + /* convert to words (round up) */
5656 + param_size = (3 + param_size) / 4;
5658 + if (cum->regs_used + param_size > NUM_ARG_REGS)
5660 + cum->regs_used = NUM_ARG_REGS;
5662 + else
5664 + cum->regs_used += param_size;
5667 + return;
5670 +/* Define where to put the arguments to a function. Value is zero to
5671 + push the argument on the stack, or a hard register in which to
5672 + store the argument.
5674 + MODE is the argument's machine mode.
5675 + TYPE is the data type of the argument (as a tree).
5676 + This is null for libcalls where that information may
5677 + not be available.
5678 + CUM is a variable of type CUMULATIVE_ARGS which gives info about
5679 + the preceding args and about the function being called.
5680 + NAMED is nonzero if this argument is a named parameter
5681 + (otherwise it is an extra parameter matching an ellipsis). */
5682 +rtx
5683 +function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
5684 + tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED)
5686 + rtx return_rtx = NULL_RTX;
5688 + if (cum->regs_used < NUM_ARG_REGS)
5690 + return_rtx = gen_rtx_REG (mode, FIRST_ARG_REGNO + cum->regs_used);
5693 + return return_rtx;
5696 +int
5697 +function_arg_partial_nregs (const CUMULATIVE_ARGS *cum,
5698 + enum machine_mode mode, tree type,
5699 + int named ATTRIBUTE_UNUSED)
5701 + HOST_WIDE_INT param_size;
5703 + if (mode == BLKmode)
5705 + param_size = int_size_in_bytes (type);
5706 + if (param_size < 0)
5707 + internal_error
5708 + ("Do not know how to handle large structs or variable length types");
5710 + else
5712 + param_size = GET_MODE_SIZE (mode);
5715 + /* convert to words (round up) */
5716 + param_size = (3 + param_size) / 4;
5718 + if (cum->regs_used < NUM_ARG_REGS
5719 + && cum->regs_used + param_size > NUM_ARG_REGS)
5721 + return NUM_ARG_REGS - cum->regs_used;
5723 + else
5725 + return 0;
5730 +int
5731 +nios2_return_in_memory (tree type)
5733 + int res = ((int_size_in_bytes (type) > (2 * UNITS_PER_WORD))
5734 + || (int_size_in_bytes (type) == -1));
5736 + return res;
5739 +/* ??? It may be possible to eliminate the copyback and implement
5740 + my own va_arg type, but that is more work for now. */
5741 +int
5742 +nios2_setup_incoming_varargs (const CUMULATIVE_ARGS *cum,
5743 + enum machine_mode mode, tree type,
5744 + int no_rtl)
5746 + CUMULATIVE_ARGS local_cum;
5747 + int regs_to_push;
5749 + local_cum = *cum;
5750 + FUNCTION_ARG_ADVANCE (local_cum, mode, type, 1);
5752 + regs_to_push = NUM_ARG_REGS - local_cum.regs_used;
5754 + if (!no_rtl)
5756 + if (regs_to_push > 0)
5758 + rtx ptr, mem;
5760 + ptr = virtual_incoming_args_rtx;
5761 + mem = gen_rtx_MEM (BLKmode, ptr);
5763 + /* va_arg is an array access in this case, which causes
5764 + it to get MEM_IN_STRUCT_P set. We must set it here
5765 + so that the insn scheduler won't assume that these
5766 + stores can't possibly overlap with the va_arg loads. */
5767 + MEM_SET_IN_STRUCT_P (mem, 1);
5769 + emit_insn (gen_blockage ());
5770 + move_block_from_reg (local_cum.regs_used + FIRST_ARG_REGNO, mem,
5771 + regs_to_push);
5772 + emit_insn (gen_blockage ());
5776 + return regs_to_push * UNITS_PER_WORD;
5782 +/*****************************************************************************
5784 +** builtins
5786 +** This method for handling builtins is from CSP where _many_ more types of
5787 +** expanders have already been written. Check there first before writing
5788 +** new ones.
5790 +*****************************************************************************/
5792 +enum nios2_builtins
5794 + NIOS2_BUILTIN_LDBIO,
5795 + NIOS2_BUILTIN_LDBUIO,
5796 + NIOS2_BUILTIN_LDHIO,
5797 + NIOS2_BUILTIN_LDHUIO,
5798 + NIOS2_BUILTIN_LDWIO,
5799 + NIOS2_BUILTIN_STBIO,
5800 + NIOS2_BUILTIN_STHIO,
5801 + NIOS2_BUILTIN_STWIO,
5802 + NIOS2_BUILTIN_SYNC,
5803 + NIOS2_BUILTIN_RDCTL,
5804 + NIOS2_BUILTIN_WRCTL,
5806 + NIOS2_BUILTIN_CUSTOM_N,
5807 + NIOS2_BUILTIN_CUSTOM_NI,
5808 + NIOS2_BUILTIN_CUSTOM_NF,
5809 + NIOS2_BUILTIN_CUSTOM_NP,
5810 + NIOS2_BUILTIN_CUSTOM_NII,
5811 + NIOS2_BUILTIN_CUSTOM_NIF,
5812 + NIOS2_BUILTIN_CUSTOM_NIP,
5813 + NIOS2_BUILTIN_CUSTOM_NFI,
5814 + NIOS2_BUILTIN_CUSTOM_NFF,
5815 + NIOS2_BUILTIN_CUSTOM_NFP,
5816 + NIOS2_BUILTIN_CUSTOM_NPI,
5817 + NIOS2_BUILTIN_CUSTOM_NPF,
5818 + NIOS2_BUILTIN_CUSTOM_NPP,
5819 + NIOS2_BUILTIN_CUSTOM_IN,
5820 + NIOS2_BUILTIN_CUSTOM_INI,
5821 + NIOS2_BUILTIN_CUSTOM_INF,
5822 + NIOS2_BUILTIN_CUSTOM_INP,
5823 + NIOS2_BUILTIN_CUSTOM_INII,
5824 + NIOS2_BUILTIN_CUSTOM_INIF,
5825 + NIOS2_BUILTIN_CUSTOM_INIP,
5826 + NIOS2_BUILTIN_CUSTOM_INFI,
5827 + NIOS2_BUILTIN_CUSTOM_INFF,
5828 + NIOS2_BUILTIN_CUSTOM_INFP,
5829 + NIOS2_BUILTIN_CUSTOM_INPI,
5830 + NIOS2_BUILTIN_CUSTOM_INPF,
5831 + NIOS2_BUILTIN_CUSTOM_INPP,
5832 + NIOS2_BUILTIN_CUSTOM_FN,
5833 + NIOS2_BUILTIN_CUSTOM_FNI,
5834 + NIOS2_BUILTIN_CUSTOM_FNF,
5835 + NIOS2_BUILTIN_CUSTOM_FNP,
5836 + NIOS2_BUILTIN_CUSTOM_FNII,
5837 + NIOS2_BUILTIN_CUSTOM_FNIF,
5838 + NIOS2_BUILTIN_CUSTOM_FNIP,
5839 + NIOS2_BUILTIN_CUSTOM_FNFI,
5840 + NIOS2_BUILTIN_CUSTOM_FNFF,
5841 + NIOS2_BUILTIN_CUSTOM_FNFP,
5842 + NIOS2_BUILTIN_CUSTOM_FNPI,
5843 + NIOS2_BUILTIN_CUSTOM_FNPF,
5844 + NIOS2_BUILTIN_CUSTOM_FNPP,
5845 + NIOS2_BUILTIN_CUSTOM_PN,
5846 + NIOS2_BUILTIN_CUSTOM_PNI,
5847 + NIOS2_BUILTIN_CUSTOM_PNF,
5848 + NIOS2_BUILTIN_CUSTOM_PNP,
5849 + NIOS2_BUILTIN_CUSTOM_PNII,
5850 + NIOS2_BUILTIN_CUSTOM_PNIF,
5851 + NIOS2_BUILTIN_CUSTOM_PNIP,
5852 + NIOS2_BUILTIN_CUSTOM_PNFI,
5853 + NIOS2_BUILTIN_CUSTOM_PNFF,
5854 + NIOS2_BUILTIN_CUSTOM_PNFP,
5855 + NIOS2_BUILTIN_CUSTOM_PNPI,
5856 + NIOS2_BUILTIN_CUSTOM_PNPF,
5857 + NIOS2_BUILTIN_CUSTOM_PNPP,
5860 + LIM_NIOS2_BUILTINS
5863 +struct builtin_description
5865 + const enum insn_code icode;
5866 + const char *const name;
5867 + const enum nios2_builtins code;
5868 + const tree *type;
5869 + rtx (* expander) PARAMS ((const struct builtin_description *,
5870 + tree, rtx, rtx, enum machine_mode, int));
5873 +static rtx nios2_expand_STXIO (const struct builtin_description *,
5874 + tree, rtx, rtx, enum machine_mode, int);
5875 +static rtx nios2_expand_LDXIO (const struct builtin_description *,
5876 + tree, rtx, rtx, enum machine_mode, int);
5877 +static rtx nios2_expand_sync (const struct builtin_description *,
5878 + tree, rtx, rtx, enum machine_mode, int);
5879 +static rtx nios2_expand_rdctl (const struct builtin_description *,
5880 + tree, rtx, rtx, enum machine_mode, int);
5881 +static rtx nios2_expand_wrctl (const struct builtin_description *,
5882 + tree, rtx, rtx, enum machine_mode, int);
5884 +static rtx nios2_expand_custom_n (const struct builtin_description *,
5885 + tree, rtx, rtx, enum machine_mode, int);
5886 +static rtx nios2_expand_custom_Xn (const struct builtin_description *,
5887 + tree, rtx, rtx, enum machine_mode, int);
5888 +static rtx nios2_expand_custom_nX (const struct builtin_description *,
5889 + tree, rtx, rtx, enum machine_mode, int);
5890 +static rtx nios2_expand_custom_XnX (const struct builtin_description *,
5891 + tree, rtx, rtx, enum machine_mode, int);
5892 +static rtx nios2_expand_custom_nXX (const struct builtin_description *,
5893 + tree, rtx, rtx, enum machine_mode, int);
5894 +static rtx nios2_expand_custom_XnXX (const struct builtin_description *,
5895 + tree, rtx, rtx, enum machine_mode, int);
5897 +static tree endlink;
5899 +/* int fn (volatile const void *)
5900 + */
5901 +static tree int_ftype_volatile_const_void_p;
5903 +/* int fn (int)
5904 + */
5905 +static tree int_ftype_int;
5907 +/* void fn (int, int)
5908 + */
5909 +static tree void_ftype_int_int;
5911 +/* void fn (volatile void *, int)
5912 + */
5913 +static tree void_ftype_volatile_void_p_int;
5915 +/* void fn (void)
5916 + */
5917 +static tree void_ftype_void;
5919 +static tree custom_n;
5920 +static tree custom_ni;
5921 +static tree custom_nf;
5922 +static tree custom_np;
5923 +static tree custom_nii;
5924 +static tree custom_nif;
5925 +static tree custom_nip;
5926 +static tree custom_nfi;
5927 +static tree custom_nff;
5928 +static tree custom_nfp;
5929 +static tree custom_npi;
5930 +static tree custom_npf;
5931 +static tree custom_npp;
5932 +static tree custom_in;
5933 +static tree custom_ini;
5934 +static tree custom_inf;
5935 +static tree custom_inp;
5936 +static tree custom_inii;
5937 +static tree custom_inif;
5938 +static tree custom_inip;
5939 +static tree custom_infi;
5940 +static tree custom_inff;
5941 +static tree custom_infp;
5942 +static tree custom_inpi;
5943 +static tree custom_inpf;
5944 +static tree custom_inpp;
5945 +static tree custom_fn;
5946 +static tree custom_fni;
5947 +static tree custom_fnf;
5948 +static tree custom_fnp;
5949 +static tree custom_fnii;
5950 +static tree custom_fnif;
5951 +static tree custom_fnip;
5952 +static tree custom_fnfi;
5953 +static tree custom_fnff;
5954 +static tree custom_fnfp;
5955 +static tree custom_fnpi;
5956 +static tree custom_fnpf;
5957 +static tree custom_fnpp;
5958 +static tree custom_pn;
5959 +static tree custom_pni;
5960 +static tree custom_pnf;
5961 +static tree custom_pnp;
5962 +static tree custom_pnii;
5963 +static tree custom_pnif;
5964 +static tree custom_pnip;
5965 +static tree custom_pnfi;
5966 +static tree custom_pnff;
5967 +static tree custom_pnfp;
5968 +static tree custom_pnpi;
5969 +static tree custom_pnpf;
5970 +static tree custom_pnpp;
5973 +static const struct builtin_description bdesc[] = {
5974 + {CODE_FOR_ldbio, "__builtin_ldbio", NIOS2_BUILTIN_LDBIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
5975 + {CODE_FOR_ldbuio, "__builtin_ldbuio", NIOS2_BUILTIN_LDBUIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
5976 + {CODE_FOR_ldhio, "__builtin_ldhio", NIOS2_BUILTIN_LDHIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
5977 + {CODE_FOR_ldhuio, "__builtin_ldhuio", NIOS2_BUILTIN_LDHUIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
5978 + {CODE_FOR_ldwio, "__builtin_ldwio", NIOS2_BUILTIN_LDWIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
5980 + {CODE_FOR_stbio, "__builtin_stbio", NIOS2_BUILTIN_STBIO, &void_ftype_volatile_void_p_int, nios2_expand_STXIO},
5981 + {CODE_FOR_sthio, "__builtin_sthio", NIOS2_BUILTIN_STHIO, &void_ftype_volatile_void_p_int, nios2_expand_STXIO},
5982 + {CODE_FOR_stwio, "__builtin_stwio", NIOS2_BUILTIN_STWIO, &void_ftype_volatile_void_p_int, nios2_expand_STXIO},
5984 + {CODE_FOR_sync, "__builtin_sync", NIOS2_BUILTIN_SYNC, &void_ftype_void, nios2_expand_sync},
5985 + {CODE_FOR_rdctl, "__builtin_rdctl", NIOS2_BUILTIN_RDCTL, &int_ftype_int, nios2_expand_rdctl},
5986 + {CODE_FOR_wrctl, "__builtin_wrctl", NIOS2_BUILTIN_WRCTL, &void_ftype_int_int, nios2_expand_wrctl},
5988 + {CODE_FOR_custom_n, "__builtin_custom_n", NIOS2_BUILTIN_CUSTOM_N, &custom_n, nios2_expand_custom_n},
5989 + {CODE_FOR_custom_ni, "__builtin_custom_ni", NIOS2_BUILTIN_CUSTOM_NI, &custom_ni, nios2_expand_custom_nX},
5990 + {CODE_FOR_custom_nf, "__builtin_custom_nf", NIOS2_BUILTIN_CUSTOM_NF, &custom_nf, nios2_expand_custom_nX},
5991 + {CODE_FOR_custom_np, "__builtin_custom_np", NIOS2_BUILTIN_CUSTOM_NP, &custom_np, nios2_expand_custom_nX},
5992 + {CODE_FOR_custom_nii, "__builtin_custom_nii", NIOS2_BUILTIN_CUSTOM_NII, &custom_nii, nios2_expand_custom_nXX},
5993 + {CODE_FOR_custom_nif, "__builtin_custom_nif", NIOS2_BUILTIN_CUSTOM_NIF, &custom_nif, nios2_expand_custom_nXX},
5994 + {CODE_FOR_custom_nip, "__builtin_custom_nip", NIOS2_BUILTIN_CUSTOM_NIP, &custom_nip, nios2_expand_custom_nXX},
5995 + {CODE_FOR_custom_nfi, "__builtin_custom_nfi", NIOS2_BUILTIN_CUSTOM_NFI, &custom_nfi, nios2_expand_custom_nXX},
5996 + {CODE_FOR_custom_nff, "__builtin_custom_nff", NIOS2_BUILTIN_CUSTOM_NFF, &custom_nff, nios2_expand_custom_nXX},
5997 + {CODE_FOR_custom_nfp, "__builtin_custom_nfp", NIOS2_BUILTIN_CUSTOM_NFP, &custom_nfp, nios2_expand_custom_nXX},
5998 + {CODE_FOR_custom_npi, "__builtin_custom_npi", NIOS2_BUILTIN_CUSTOM_NPI, &custom_npi, nios2_expand_custom_nXX},
5999 + {CODE_FOR_custom_npf, "__builtin_custom_npf", NIOS2_BUILTIN_CUSTOM_NPF, &custom_npf, nios2_expand_custom_nXX},
6000 + {CODE_FOR_custom_npp, "__builtin_custom_npp", NIOS2_BUILTIN_CUSTOM_NPP, &custom_npp, nios2_expand_custom_nXX},
6001 + {CODE_FOR_custom_in, "__builtin_custom_in", NIOS2_BUILTIN_CUSTOM_IN, &custom_in, nios2_expand_custom_Xn},
6002 + {CODE_FOR_custom_ini, "__builtin_custom_ini", NIOS2_BUILTIN_CUSTOM_INI, &custom_ini, nios2_expand_custom_XnX},
6003 + {CODE_FOR_custom_inf, "__builtin_custom_inf", NIOS2_BUILTIN_CUSTOM_INF, &custom_inf, nios2_expand_custom_XnX},
6004 + {CODE_FOR_custom_inp, "__builtin_custom_inp", NIOS2_BUILTIN_CUSTOM_INP, &custom_inp, nios2_expand_custom_XnX},
6005 + {CODE_FOR_custom_inii, "__builtin_custom_inii", NIOS2_BUILTIN_CUSTOM_INII, &custom_inii, nios2_expand_custom_XnXX},
6006 + {CODE_FOR_custom_inif, "__builtin_custom_inif", NIOS2_BUILTIN_CUSTOM_INIF, &custom_inif, nios2_expand_custom_XnXX},
6007 + {CODE_FOR_custom_inip, "__builtin_custom_inip", NIOS2_BUILTIN_CUSTOM_INIP, &custom_inip, nios2_expand_custom_XnXX},
6008 + {CODE_FOR_custom_infi, "__builtin_custom_infi", NIOS2_BUILTIN_CUSTOM_INFI, &custom_infi, nios2_expand_custom_XnXX},
6009 + {CODE_FOR_custom_inff, "__builtin_custom_inff", NIOS2_BUILTIN_CUSTOM_INFF, &custom_inff, nios2_expand_custom_XnXX},
6010 + {CODE_FOR_custom_infp, "__builtin_custom_infp", NIOS2_BUILTIN_CUSTOM_INFP, &custom_infp, nios2_expand_custom_XnXX},
6011 + {CODE_FOR_custom_inpi, "__builtin_custom_inpi", NIOS2_BUILTIN_CUSTOM_INPI, &custom_inpi, nios2_expand_custom_XnXX},
6012 + {CODE_FOR_custom_inpf, "__builtin_custom_inpf", NIOS2_BUILTIN_CUSTOM_INPF, &custom_inpf, nios2_expand_custom_XnXX},
6013 + {CODE_FOR_custom_inpp, "__builtin_custom_inpp", NIOS2_BUILTIN_CUSTOM_INPP, &custom_inpp, nios2_expand_custom_XnXX},
6014 + {CODE_FOR_custom_fn, "__builtin_custom_fn", NIOS2_BUILTIN_CUSTOM_FN, &custom_fn, nios2_expand_custom_Xn},
6015 + {CODE_FOR_custom_fni, "__builtin_custom_fni", NIOS2_BUILTIN_CUSTOM_FNI, &custom_fni, nios2_expand_custom_XnX},
6016 + {CODE_FOR_custom_fnf, "__builtin_custom_fnf", NIOS2_BUILTIN_CUSTOM_FNF, &custom_fnf, nios2_expand_custom_XnX},
6017 + {CODE_FOR_custom_fnp, "__builtin_custom_fnp", NIOS2_BUILTIN_CUSTOM_FNP, &custom_fnp, nios2_expand_custom_XnX},
6018 + {CODE_FOR_custom_fnii, "__builtin_custom_fnii", NIOS2_BUILTIN_CUSTOM_FNII, &custom_fnii, nios2_expand_custom_XnXX},
6019 + {CODE_FOR_custom_fnif, "__builtin_custom_fnif", NIOS2_BUILTIN_CUSTOM_FNIF, &custom_fnif, nios2_expand_custom_XnXX},
6020 + {CODE_FOR_custom_fnip, "__builtin_custom_fnip", NIOS2_BUILTIN_CUSTOM_FNIP, &custom_fnip, nios2_expand_custom_XnXX},
6021 + {CODE_FOR_custom_fnfi, "__builtin_custom_fnfi", NIOS2_BUILTIN_CUSTOM_FNFI, &custom_fnfi, nios2_expand_custom_XnXX},
6022 + {CODE_FOR_custom_fnff, "__builtin_custom_fnff", NIOS2_BUILTIN_CUSTOM_FNFF, &custom_fnff, nios2_expand_custom_XnXX},
6023 + {CODE_FOR_custom_fnfp, "__builtin_custom_fnfp", NIOS2_BUILTIN_CUSTOM_FNFP, &custom_fnfp, nios2_expand_custom_XnXX},
6024 + {CODE_FOR_custom_fnpi, "__builtin_custom_fnpi", NIOS2_BUILTIN_CUSTOM_FNPI, &custom_fnpi, nios2_expand_custom_XnXX},
6025 + {CODE_FOR_custom_fnpf, "__builtin_custom_fnpf", NIOS2_BUILTIN_CUSTOM_FNPF, &custom_fnpf, nios2_expand_custom_XnXX},
6026 + {CODE_FOR_custom_fnpp, "__builtin_custom_fnpp", NIOS2_BUILTIN_CUSTOM_FNPP, &custom_fnpp, nios2_expand_custom_XnXX},
6027 + {CODE_FOR_custom_pn, "__builtin_custom_pn", NIOS2_BUILTIN_CUSTOM_PN, &custom_pn, nios2_expand_custom_Xn},
6028 + {CODE_FOR_custom_pni, "__builtin_custom_pni", NIOS2_BUILTIN_CUSTOM_PNI, &custom_pni, nios2_expand_custom_XnX},
6029 + {CODE_FOR_custom_pnf, "__builtin_custom_pnf", NIOS2_BUILTIN_CUSTOM_PNF, &custom_pnf, nios2_expand_custom_XnX},
6030 + {CODE_FOR_custom_pnp, "__builtin_custom_pnp", NIOS2_BUILTIN_CUSTOM_PNP, &custom_pnp, nios2_expand_custom_XnX},
6031 + {CODE_FOR_custom_pnii, "__builtin_custom_pnii", NIOS2_BUILTIN_CUSTOM_PNII, &custom_pnii, nios2_expand_custom_XnXX},
6032 + {CODE_FOR_custom_pnif, "__builtin_custom_pnif", NIOS2_BUILTIN_CUSTOM_PNIF, &custom_pnif, nios2_expand_custom_XnXX},
6033 + {CODE_FOR_custom_pnip, "__builtin_custom_pnip", NIOS2_BUILTIN_CUSTOM_PNIP, &custom_pnip, nios2_expand_custom_XnXX},
6034 + {CODE_FOR_custom_pnfi, "__builtin_custom_pnfi", NIOS2_BUILTIN_CUSTOM_PNFI, &custom_pnfi, nios2_expand_custom_XnXX},
6035 + {CODE_FOR_custom_pnff, "__builtin_custom_pnff", NIOS2_BUILTIN_CUSTOM_PNFF, &custom_pnff, nios2_expand_custom_XnXX},
6036 + {CODE_FOR_custom_pnfp, "__builtin_custom_pnfp", NIOS2_BUILTIN_CUSTOM_PNFP, &custom_pnfp, nios2_expand_custom_XnXX},
6037 + {CODE_FOR_custom_pnpi, "__builtin_custom_pnpi", NIOS2_BUILTIN_CUSTOM_PNPI, &custom_pnpi, nios2_expand_custom_XnXX},
6038 + {CODE_FOR_custom_pnpf, "__builtin_custom_pnpf", NIOS2_BUILTIN_CUSTOM_PNPF, &custom_pnpf, nios2_expand_custom_XnXX},
6039 + {CODE_FOR_custom_pnpp, "__builtin_custom_pnpp", NIOS2_BUILTIN_CUSTOM_PNPP, &custom_pnpp, nios2_expand_custom_XnXX},
6042 + {0, 0, 0, 0, 0},
6045 +/* This does not have a closing bracket on purpose (see use) */
6046 +#define def_param(TYPE) \
6047 + tree_cons (NULL_TREE, TYPE,
6049 +static void
6050 +nios2_init_builtins ()
6052 + const struct builtin_description *d;
6055 + endlink = void_list_node;
6057 + /* Special indenting here because one of the brackets is in def_param */
6058 + /* *INDENT-OFF* */
6060 + /* int fn (volatile const void *)
6061 + */
6062 + int_ftype_volatile_const_void_p
6063 + = build_function_type (integer_type_node,
6064 + def_param (build_qualified_type (ptr_type_node,
6065 + TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE))
6066 + endlink));
6069 + /* void fn (volatile void *, int)
6070 + */
6071 + void_ftype_volatile_void_p_int
6072 + = build_function_type (void_type_node,
6073 + def_param (build_qualified_type (ptr_type_node,
6074 + TYPE_QUAL_VOLATILE))
6075 + def_param (integer_type_node)
6076 + endlink)));
6078 + /* void fn (void)
6079 + */
6080 + void_ftype_void
6081 + = build_function_type (void_type_node,
6082 + endlink);
6084 + /* int fn (int)
6085 + */
6086 + int_ftype_int
6087 + = build_function_type (integer_type_node,
6088 + def_param (integer_type_node)
6089 + endlink));
6091 + /* void fn (int, int)
6092 + */
6093 + void_ftype_int_int
6094 + = build_function_type (void_type_node,
6095 + def_param (integer_type_node)
6096 + def_param (integer_type_node)
6097 + endlink)));
6100 +#define CUSTOM_NUM def_param (integer_type_node)
6102 + custom_n
6103 + = build_function_type (void_type_node,
6104 + CUSTOM_NUM
6105 + endlink));
6106 + custom_ni
6107 + = build_function_type (void_type_node,
6108 + CUSTOM_NUM
6109 + def_param (integer_type_node)
6110 + endlink)));
6111 + custom_nf
6112 + = build_function_type (void_type_node,
6113 + CUSTOM_NUM
6114 + def_param (float_type_node)
6115 + endlink)));
6116 + custom_np
6117 + = build_function_type (void_type_node,
6118 + CUSTOM_NUM
6119 + def_param (ptr_type_node)
6120 + endlink)));
6121 + custom_nii
6122 + = build_function_type (void_type_node,
6123 + CUSTOM_NUM
6124 + def_param (integer_type_node)
6125 + def_param (integer_type_node)
6126 + endlink))));
6127 + custom_nif
6128 + = build_function_type (void_type_node,
6129 + CUSTOM_NUM
6130 + def_param (integer_type_node)
6131 + def_param (float_type_node)
6132 + endlink))));
6133 + custom_nip
6134 + = build_function_type (void_type_node,
6135 + CUSTOM_NUM
6136 + def_param (integer_type_node)
6137 + def_param (ptr_type_node)
6138 + endlink))));
6139 + custom_nfi
6140 + = build_function_type (void_type_node,
6141 + CUSTOM_NUM
6142 + def_param (float_type_node)
6143 + def_param (integer_type_node)
6144 + endlink))));
6145 + custom_nff
6146 + = build_function_type (void_type_node,
6147 + CUSTOM_NUM
6148 + def_param (float_type_node)
6149 + def_param (float_type_node)
6150 + endlink))));
6151 + custom_nfp
6152 + = build_function_type (void_type_node,
6153 + CUSTOM_NUM
6154 + def_param (float_type_node)
6155 + def_param (ptr_type_node)
6156 + endlink))));
6157 + custom_npi
6158 + = build_function_type (void_type_node,
6159 + CUSTOM_NUM
6160 + def_param (ptr_type_node)
6161 + def_param (integer_type_node)
6162 + endlink))));
6163 + custom_npf
6164 + = build_function_type (void_type_node,
6165 + CUSTOM_NUM
6166 + def_param (ptr_type_node)
6167 + def_param (float_type_node)
6168 + endlink))));
6169 + custom_npp
6170 + = build_function_type (void_type_node,
6171 + CUSTOM_NUM
6172 + def_param (ptr_type_node)
6173 + def_param (ptr_type_node)
6174 + endlink))));
6176 + custom_in
6177 + = build_function_type (integer_type_node,
6178 + CUSTOM_NUM
6179 + endlink));
6180 + custom_ini
6181 + = build_function_type (integer_type_node,
6182 + CUSTOM_NUM
6183 + def_param (integer_type_node)
6184 + endlink)));
6185 + custom_inf
6186 + = build_function_type (integer_type_node,
6187 + CUSTOM_NUM
6188 + def_param (float_type_node)
6189 + endlink)));
6190 + custom_inp
6191 + = build_function_type (integer_type_node,
6192 + CUSTOM_NUM
6193 + def_param (ptr_type_node)
6194 + endlink)));
6195 + custom_inii
6196 + = build_function_type (integer_type_node,
6197 + CUSTOM_NUM
6198 + def_param (integer_type_node)
6199 + def_param (integer_type_node)
6200 + endlink))));
6201 + custom_inif
6202 + = build_function_type (integer_type_node,
6203 + CUSTOM_NUM
6204 + def_param (integer_type_node)
6205 + def_param (float_type_node)
6206 + endlink))));
6207 + custom_inip
6208 + = build_function_type (integer_type_node,
6209 + CUSTOM_NUM
6210 + def_param (integer_type_node)
6211 + def_param (ptr_type_node)
6212 + endlink))));
6213 + custom_infi
6214 + = build_function_type (integer_type_node,
6215 + CUSTOM_NUM
6216 + def_param (float_type_node)
6217 + def_param (integer_type_node)
6218 + endlink))));
6219 + custom_inff
6220 + = build_function_type (integer_type_node,
6221 + CUSTOM_NUM
6222 + def_param (float_type_node)
6223 + def_param (float_type_node)
6224 + endlink))));
6225 + custom_infp
6226 + = build_function_type (integer_type_node,
6227 + CUSTOM_NUM
6228 + def_param (float_type_node)
6229 + def_param (ptr_type_node)
6230 + endlink))));
6231 + custom_inpi
6232 + = build_function_type (integer_type_node,
6233 + CUSTOM_NUM
6234 + def_param (ptr_type_node)
6235 + def_param (integer_type_node)
6236 + endlink))));
6237 + custom_inpf
6238 + = build_function_type (integer_type_node,
6239 + CUSTOM_NUM
6240 + def_param (ptr_type_node)
6241 + def_param (float_type_node)
6242 + endlink))));
6243 + custom_inpp
6244 + = build_function_type (integer_type_node,
6245 + CUSTOM_NUM
6246 + def_param (ptr_type_node)
6247 + def_param (ptr_type_node)
6248 + endlink))));
6250 + custom_fn
6251 + = build_function_type (float_type_node,
6252 + CUSTOM_NUM
6253 + endlink));
6254 + custom_fni
6255 + = build_function_type (float_type_node,
6256 + CUSTOM_NUM
6257 + def_param (integer_type_node)
6258 + endlink)));
6259 + custom_fnf
6260 + = build_function_type (float_type_node,
6261 + CUSTOM_NUM
6262 + def_param (float_type_node)
6263 + endlink)));
6264 + custom_fnp
6265 + = build_function_type (float_type_node,
6266 + CUSTOM_NUM
6267 + def_param (ptr_type_node)
6268 + endlink)));
6269 + custom_fnii
6270 + = build_function_type (float_type_node,
6271 + CUSTOM_NUM
6272 + def_param (integer_type_node)
6273 + def_param (integer_type_node)
6274 + endlink))));
6275 + custom_fnif
6276 + = build_function_type (float_type_node,
6277 + CUSTOM_NUM
6278 + def_param (integer_type_node)
6279 + def_param (float_type_node)
6280 + endlink))));
6281 + custom_fnip
6282 + = build_function_type (float_type_node,
6283 + CUSTOM_NUM
6284 + def_param (integer_type_node)
6285 + def_param (ptr_type_node)
6286 + endlink))));
6287 + custom_fnfi
6288 + = build_function_type (float_type_node,
6289 + CUSTOM_NUM
6290 + def_param (float_type_node)
6291 + def_param (integer_type_node)
6292 + endlink))));
6293 + custom_fnff
6294 + = build_function_type (float_type_node,
6295 + CUSTOM_NUM
6296 + def_param (float_type_node)
6297 + def_param (float_type_node)
6298 + endlink))));
6299 + custom_fnfp
6300 + = build_function_type (float_type_node,
6301 + CUSTOM_NUM
6302 + def_param (float_type_node)
6303 + def_param (ptr_type_node)
6304 + endlink))));
6305 + custom_fnpi
6306 + = build_function_type (float_type_node,
6307 + CUSTOM_NUM
6308 + def_param (ptr_type_node)
6309 + def_param (integer_type_node)
6310 + endlink))));
6311 + custom_fnpf
6312 + = build_function_type (float_type_node,
6313 + CUSTOM_NUM
6314 + def_param (ptr_type_node)
6315 + def_param (float_type_node)
6316 + endlink))));
6317 + custom_fnpp
6318 + = build_function_type (float_type_node,
6319 + CUSTOM_NUM
6320 + def_param (ptr_type_node)
6321 + def_param (ptr_type_node)
6322 + endlink))));
6325 + custom_pn
6326 + = build_function_type (ptr_type_node,
6327 + CUSTOM_NUM
6328 + endlink));
6329 + custom_pni
6330 + = build_function_type (ptr_type_node,
6331 + CUSTOM_NUM
6332 + def_param (integer_type_node)
6333 + endlink)));
6334 + custom_pnf
6335 + = build_function_type (ptr_type_node,
6336 + CUSTOM_NUM
6337 + def_param (float_type_node)
6338 + endlink)));
6339 + custom_pnp
6340 + = build_function_type (ptr_type_node,
6341 + CUSTOM_NUM
6342 + def_param (ptr_type_node)
6343 + endlink)));
6344 + custom_pnii
6345 + = build_function_type (ptr_type_node,
6346 + CUSTOM_NUM
6347 + def_param (integer_type_node)
6348 + def_param (integer_type_node)
6349 + endlink))));
6350 + custom_pnif
6351 + = build_function_type (ptr_type_node,
6352 + CUSTOM_NUM
6353 + def_param (integer_type_node)
6354 + def_param (float_type_node)
6355 + endlink))));
6356 + custom_pnip
6357 + = build_function_type (ptr_type_node,
6358 + CUSTOM_NUM
6359 + def_param (integer_type_node)
6360 + def_param (ptr_type_node)
6361 + endlink))));
6362 + custom_pnfi
6363 + = build_function_type (ptr_type_node,
6364 + CUSTOM_NUM
6365 + def_param (float_type_node)
6366 + def_param (integer_type_node)
6367 + endlink))));
6368 + custom_pnff
6369 + = build_function_type (ptr_type_node,
6370 + CUSTOM_NUM
6371 + def_param (float_type_node)
6372 + def_param (float_type_node)
6373 + endlink))));
6374 + custom_pnfp
6375 + = build_function_type (ptr_type_node,
6376 + CUSTOM_NUM
6377 + def_param (float_type_node)
6378 + def_param (ptr_type_node)
6379 + endlink))));
6380 + custom_pnpi
6381 + = build_function_type (ptr_type_node,
6382 + CUSTOM_NUM
6383 + def_param (ptr_type_node)
6384 + def_param (integer_type_node)
6385 + endlink))));
6386 + custom_pnpf
6387 + = build_function_type (ptr_type_node,
6388 + CUSTOM_NUM
6389 + def_param (ptr_type_node)
6390 + def_param (float_type_node)
6391 + endlink))));
6392 + custom_pnpp
6393 + = build_function_type (ptr_type_node,
6394 + CUSTOM_NUM
6395 + def_param (ptr_type_node)
6396 + def_param (ptr_type_node)
6397 + endlink))));
6401 + /* *INDENT-ON* */
6404 + for (d = bdesc; d->name; d++)
6406 + builtin_function (d->name, *d->type, d->code,
6407 + BUILT_IN_MD, NULL, NULL);
6411 +/* Expand an expression EXP that calls a built-in function,
6412 + with result going to TARGET if that's convenient
6413 + (and in mode MODE if that's convenient).
6414 + SUBTARGET may be used as the target for computing one of EXP's operands.
6415 + IGNORE is nonzero if the value is to be ignored. */
6417 +static rtx
6418 +nios2_expand_builtin (tree exp, rtx target, rtx subtarget,
6419 + enum machine_mode mode, int ignore)
6421 + const struct builtin_description *d;
6422 + tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
6423 + unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
6425 + for (d = bdesc; d->name; d++)
6426 + if (d->code == fcode)
6427 + return (d->expander) (d, exp, target, subtarget, mode, ignore);
6429 + /* we should have seen one of the functins we registered */
6430 + abort ();
6433 +static rtx nios2_create_target (const struct builtin_description *, rtx);
6436 +static rtx
6437 +nios2_create_target (const struct builtin_description *d, rtx target)
6439 + if (!target
6440 + || !(*insn_data[d->icode].operand[0].predicate) (target,
6441 + insn_data[d->icode].operand[0].mode))
6443 + target = gen_reg_rtx (insn_data[d->icode].operand[0].mode);
6446 + return target;
6450 +static rtx nios2_extract_opcode (const struct builtin_description *, int, tree);
6451 +static rtx nios2_extract_operand (const struct builtin_description *, int, int, tree);
6453 +static rtx
6454 +nios2_extract_opcode (const struct builtin_description *d, int op, tree arglist)
6456 + enum machine_mode mode = insn_data[d->icode].operand[op].mode;
6457 + tree arg = TREE_VALUE (arglist);
6458 + rtx opcode = expand_expr (arg, NULL_RTX, mode, 0);
6459 + opcode = protect_from_queue (opcode, 0);
6461 + if (!(*insn_data[d->icode].operand[op].predicate) (opcode, mode))
6462 + error ("Custom instruction opcode must be compile time constant in the range 0-255 for %s", d->name);
6464 + return opcode;
6467 +static rtx
6468 +nios2_extract_operand (const struct builtin_description *d, int op, int argnum, tree arglist)
6470 + enum machine_mode mode = insn_data[d->icode].operand[op].mode;
6471 + tree arg = TREE_VALUE (arglist);
6472 + rtx operand = expand_expr (arg, NULL_RTX, mode, 0);
6473 + operand = protect_from_queue (operand, 0);
6475 + if (!(*insn_data[d->icode].operand[op].predicate) (operand, mode))
6476 + operand = copy_to_mode_reg (mode, operand);
6478 + /* ??? Better errors would be nice */
6479 + if (!(*insn_data[d->icode].operand[op].predicate) (operand, mode))
6480 + error ("Invalid argument %d to %s", argnum, d->name);
6482 + return operand;
6486 +static rtx
6487 +nios2_expand_custom_n (const struct builtin_description *d, tree exp,
6488 + rtx target ATTRIBUTE_UNUSED, rtx subtarget ATTRIBUTE_UNUSED,
6489 + enum machine_mode mode ATTRIBUTE_UNUSED, int ignore ATTRIBUTE_UNUSED)
6491 + tree arglist = TREE_OPERAND (exp, 1);
6492 + rtx pat;
6493 + rtx opcode;
6495 + /* custom_n should have exactly one operand */
6496 + if (insn_data[d->icode].n_operands != 1)
6497 + abort ();
6499 + opcode = nios2_extract_opcode (d, 0, arglist);
6501 + pat = GEN_FCN (d->icode) (opcode);
6502 + if (!pat)
6503 + return 0;
6504 + emit_insn (pat);
6505 + return 0;
6508 +static rtx
6509 +nios2_expand_custom_Xn (const struct builtin_description *d, tree exp,
6510 + rtx target, rtx subtarget ATTRIBUTE_UNUSED,
6511 + enum machine_mode mode ATTRIBUTE_UNUSED,
6512 + int ignore ATTRIBUTE_UNUSED)
6514 + tree arglist = TREE_OPERAND (exp, 1);
6515 + rtx pat;
6516 + rtx opcode;
6518 + /* custom_Xn should have exactly two operands */
6519 + if (insn_data[d->icode].n_operands != 2)
6520 + abort ();
6522 + target = nios2_create_target (d, target);
6523 + opcode = nios2_extract_opcode (d, 1, arglist);
6525 + pat = GEN_FCN (d->icode) (target, opcode);
6526 + if (!pat)
6527 + return 0;
6528 + emit_insn (pat);
6529 + return target;
6532 +static rtx
6533 +nios2_expand_custom_nX (const struct builtin_description *d, tree exp,
6534 + rtx target ATTRIBUTE_UNUSED, rtx subtarget ATTRIBUTE_UNUSED,
6535 + enum machine_mode mode ATTRIBUTE_UNUSED, int ignore ATTRIBUTE_UNUSED)
6537 + tree arglist = TREE_OPERAND (exp, 1);
6538 + rtx pat;
6539 + rtx opcode;
6540 + rtx operands[1];
6541 + int i;
6544 + /* custom_nX should have exactly two operands */
6545 + if (insn_data[d->icode].n_operands != 2)
6546 + abort ();
6548 + opcode = nios2_extract_opcode (d, 0, arglist);
6549 + for (i = 0; i < 1; i++)
6551 + arglist = TREE_CHAIN (arglist);
6552 + operands[i] = nios2_extract_operand (d, i + 1, i + 1, arglist);
6555 + pat = GEN_FCN (d->icode) (opcode, operands[0]);
6556 + if (!pat)
6557 + return 0;
6558 + emit_insn (pat);
6559 + return 0;
6562 +static rtx
6563 +nios2_expand_custom_XnX (const struct builtin_description *d, tree exp, rtx target,
6564 + rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED,
6565 + int ignore ATTRIBUTE_UNUSED)
6567 + tree arglist = TREE_OPERAND (exp, 1);
6568 + rtx pat;
6569 + rtx opcode;
6570 + rtx operands[1];
6571 + int i;
6573 + /* custom_Xn should have exactly three operands */
6574 + if (insn_data[d->icode].n_operands != 3)
6575 + abort ();
6577 + target = nios2_create_target (d, target);
6578 + opcode = nios2_extract_opcode (d, 1, arglist);
6580 + for (i = 0; i < 1; i++)
6582 + arglist = TREE_CHAIN (arglist);
6583 + operands[i] = nios2_extract_operand (d, i + 2, i + 1, arglist);
6586 + pat = GEN_FCN (d->icode) (target, opcode, operands[0]);
6588 + if (!pat)
6589 + return 0;
6590 + emit_insn (pat);
6591 + return target;
6594 +static rtx
6595 +nios2_expand_custom_nXX (const struct builtin_description *d, tree exp, rtx target ATTRIBUTE_UNUSED,
6596 + rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED,
6597 + int ignore ATTRIBUTE_UNUSED)
6599 + tree arglist = TREE_OPERAND (exp, 1);
6600 + rtx pat;
6601 + rtx opcode;
6602 + rtx operands[2];
6603 + int i;
6606 + /* custom_nX should have exactly three operands */
6607 + if (insn_data[d->icode].n_operands != 3)
6608 + abort ();
6610 + opcode = nios2_extract_opcode (d, 0, arglist);
6611 + for (i = 0; i < 2; i++)
6613 + arglist = TREE_CHAIN (arglist);
6614 + operands[i] = nios2_extract_operand (d, i + 1, i + 1, arglist);
6617 + pat = GEN_FCN (d->icode) (opcode, operands[0], operands[1]);
6618 + if (!pat)
6619 + return 0;
6620 + emit_insn (pat);
6621 + return 0;
6624 +static rtx
6625 +nios2_expand_custom_XnXX (const struct builtin_description *d, tree exp, rtx target,
6626 + rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED,
6627 + int ignore ATTRIBUTE_UNUSED)
6629 + tree arglist = TREE_OPERAND (exp, 1);
6630 + rtx pat;
6631 + rtx opcode;
6632 + rtx operands[2];
6633 + int i;
6636 + /* custom_XnX should have exactly four operands */
6637 + if (insn_data[d->icode].n_operands != 4)
6638 + abort ();
6640 + target = nios2_create_target (d, target);
6641 + opcode = nios2_extract_opcode (d, 1, arglist);
6642 + for (i = 0; i < 2; i++)
6644 + arglist = TREE_CHAIN (arglist);
6645 + operands[i] = nios2_extract_operand (d, i + 2, i + 1, arglist);
6648 + pat = GEN_FCN (d->icode) (target, opcode, operands[0], operands[1]);
6650 + if (!pat)
6651 + return 0;
6652 + emit_insn (pat);
6653 + return target;
6658 +static rtx
6659 +nios2_expand_STXIO (const struct builtin_description *d, tree exp, rtx target ATTRIBUTE_UNUSED,
6660 + rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED,
6661 + int ignore ATTRIBUTE_UNUSED)
6663 + tree arglist = TREE_OPERAND (exp, 1);
6664 + rtx pat;
6665 + rtx store_dest, store_val;
6666 + enum insn_code icode = d->icode;
6668 + /* stores should have exactly two operands */
6669 + if (insn_data[icode].n_operands != 2)
6670 + abort ();
6672 + /* process the destination of the store */
6674 + enum machine_mode mode = insn_data[icode].operand[0].mode;
6675 + tree arg = TREE_VALUE (arglist);
6676 + store_dest = expand_expr (arg, NULL_RTX, VOIDmode, 0);
6677 + store_dest = protect_from_queue (store_dest, 0);
6679 + store_dest = gen_rtx_MEM (mode, copy_to_mode_reg (Pmode, store_dest));
6681 + /* ??? Better errors would be nice */
6682 + if (!(*insn_data[icode].operand[0].predicate) (store_dest, mode))
6683 + error ("Invalid argument 1 to %s", d->name);
6687 + /* process the value to store */
6689 + enum machine_mode mode = insn_data[icode].operand[1].mode;
6690 + tree arg = TREE_VALUE (TREE_CHAIN (arglist));
6691 + store_val = expand_expr (arg, NULL_RTX, mode, 0);
6692 + store_val = protect_from_queue (store_val, 0);
6694 + if (!(*insn_data[icode].operand[1].predicate) (store_val, mode))
6695 + store_val = copy_to_mode_reg (mode, store_val);
6697 + /* ??? Better errors would be nice */
6698 + if (!(*insn_data[icode].operand[1].predicate) (store_val, mode))
6699 + error ("Invalid argument 2 to %s", d->name);
6702 + pat = GEN_FCN (d->icode) (store_dest, store_val);
6703 + if (!pat)
6704 + return 0;
6705 + emit_insn (pat);
6706 + return 0;
6710 +static rtx
6711 +nios2_expand_LDXIO (const struct builtin_description * d, tree exp, rtx target,
6712 + rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED,
6713 + int ignore ATTRIBUTE_UNUSED)
6715 + tree arglist = TREE_OPERAND (exp, 1);
6716 + rtx pat;
6717 + rtx ld_src;
6718 + enum insn_code icode = d->icode;
6720 + /* loads should have exactly two operands */
6721 + if (insn_data[icode].n_operands != 2)
6722 + abort ();
6724 + target = nios2_create_target (d, target);
6727 + enum machine_mode mode = insn_data[icode].operand[1].mode;
6728 + tree arg = TREE_VALUE (arglist);
6729 + ld_src = expand_expr (arg, NULL_RTX, VOIDmode, 0);
6730 + ld_src = protect_from_queue (ld_src, 0);
6732 + ld_src = gen_rtx_MEM (mode, copy_to_mode_reg (Pmode, ld_src));
6734 + /* ??? Better errors would be nice */
6735 + if (!(*insn_data[icode].operand[1].predicate) (ld_src, mode))
6737 + error ("Invalid argument 1 to %s", d->name);
6741 + pat = GEN_FCN (d->icode) (target, ld_src);
6742 + if (!pat)
6743 + return 0;
6744 + emit_insn (pat);
6745 + return target;
6749 +static rtx
6750 +nios2_expand_sync (const struct builtin_description * d ATTRIBUTE_UNUSED,
6751 + tree exp ATTRIBUTE_UNUSED, rtx target ATTRIBUTE_UNUSED,
6752 + rtx subtarget ATTRIBUTE_UNUSED,
6753 + enum machine_mode mode ATTRIBUTE_UNUSED,
6754 + int ignore ATTRIBUTE_UNUSED)
6756 + emit_insn (gen_sync ());
6757 + return 0;
6760 +static rtx
6761 +nios2_expand_rdctl (const struct builtin_description * d ATTRIBUTE_UNUSED,
6762 + tree exp ATTRIBUTE_UNUSED, rtx target ATTRIBUTE_UNUSED,
6763 + rtx subtarget ATTRIBUTE_UNUSED,
6764 + enum machine_mode mode ATTRIBUTE_UNUSED,
6765 + int ignore ATTRIBUTE_UNUSED)
6767 + tree arglist = TREE_OPERAND (exp, 1);
6768 + rtx pat;
6769 + rtx rdctl_reg;
6770 + enum insn_code icode = d->icode;
6772 + /* rdctl should have exactly two operands */
6773 + if (insn_data[icode].n_operands != 2)
6774 + abort ();
6776 + target = nios2_create_target (d, target);
6779 + enum machine_mode mode = insn_data[icode].operand[1].mode;
6780 + tree arg = TREE_VALUE (arglist);
6781 + rdctl_reg = expand_expr (arg, NULL_RTX, VOIDmode, 0);
6782 + rdctl_reg = protect_from_queue (rdctl_reg, 0);
6784 + if (!(*insn_data[icode].operand[1].predicate) (rdctl_reg, mode))
6786 + error ("Control register number must be in range 0-31 for %s", d->name);
6790 + pat = GEN_FCN (d->icode) (target, rdctl_reg);
6791 + if (!pat)
6792 + return 0;
6793 + emit_insn (pat);
6794 + return target;
6797 +static rtx
6798 +nios2_expand_wrctl (const struct builtin_description * d ATTRIBUTE_UNUSED,
6799 + tree exp ATTRIBUTE_UNUSED, rtx target ATTRIBUTE_UNUSED,
6800 + rtx subtarget ATTRIBUTE_UNUSED,
6801 + enum machine_mode mode ATTRIBUTE_UNUSED,
6802 + int ignore ATTRIBUTE_UNUSED)
6804 + tree arglist = TREE_OPERAND (exp, 1);
6805 + rtx pat;
6806 + rtx wrctl_reg, store_val;
6807 + enum insn_code icode = d->icode;
6809 + /* stores should have exactly two operands */
6810 + if (insn_data[icode].n_operands != 2)
6811 + abort ();
6813 + /* process the destination of the store */
6815 + enum machine_mode mode = insn_data[icode].operand[0].mode;
6816 + tree arg = TREE_VALUE (arglist);
6817 + wrctl_reg = expand_expr (arg, NULL_RTX, VOIDmode, 0);
6818 + wrctl_reg = protect_from_queue (wrctl_reg, 0);
6820 + if (!(*insn_data[icode].operand[0].predicate) (wrctl_reg, mode))
6821 + error ("Control register number must be in range 0-31 for %s", d->name);
6825 + /* process the value to store */
6827 + enum machine_mode mode = insn_data[icode].operand[1].mode;
6828 + tree arg = TREE_VALUE (TREE_CHAIN (arglist));
6829 + store_val = expand_expr (arg, NULL_RTX, mode, 0);
6830 + store_val = protect_from_queue (store_val, 0);
6832 + if (!(*insn_data[icode].operand[1].predicate) (store_val, mode))
6833 + store_val = copy_to_mode_reg (mode, store_val);
6835 + /* ??? Better errors would be nice */
6836 + if (!(*insn_data[icode].operand[1].predicate) (store_val, mode))
6837 + error ("Invalid argument 2 to %s", d->name);
6840 + pat = GEN_FCN (d->icode) (wrctl_reg, store_val);
6841 + if (!pat)
6842 + return 0;
6843 + emit_insn (pat);
6844 + return 0;
6848 +#include "gt-nios2.h"
6850 --- gcc-3.4.3/gcc/config/nios2/nios2.h
6851 +++ gcc-3.4.3-nios2/gcc/config/nios2/nios2.h
6852 @@ -0,0 +1,824 @@
6853 +/* Definitions of target machine for Altera NIOS 2G NIOS2 version.
6854 + Copyright (C) 2003 Altera
6855 + Contributed by Jonah Graham (jgraham@altera.com).
6857 +This file is part of GNU CC.
6859 +GNU CC is free software; you can redistribute it and/or modify
6860 +it under the terms of the GNU General Public License as published by
6861 +the Free Software Foundation; either version 2, or (at your option)
6862 +any later version.
6864 +GNU CC is distributed in the hope that it will be useful,
6865 +but WITHOUT ANY WARRANTY; without even the implied warranty of
6866 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6867 +GNU General Public License for more details.
6869 +You should have received a copy of the GNU General Public License
6870 +along with GNU CC; see the file COPYING. If not, write to
6871 +the Free Software Foundation, 59 Temple Place - Suite 330,
6872 +Boston, MA 02111-1307, USA. */
6876 +#define TARGET_CPU_CPP_BUILTINS() \
6877 + do \
6878 + { \
6879 + builtin_define_std ("NIOS2"); \
6880 + builtin_define_std ("nios2"); \
6881 + builtin_define ("_GNU_SOURCE"); \
6882 + } \
6883 + while (0)
6884 +#define TARGET_VERSION fprintf (stderr, " (Altera Nios II)")
6890 +/*********************************
6891 + * Run-time Target Specification
6892 + *********************************/
6894 +#define HAS_DIV_FLAG 0x0001
6895 +#define HAS_MUL_FLAG 0x0002
6896 +#define HAS_MULX_FLAG 0x0004
6897 +#define FAST_SW_DIV_FLAG 0x0008
6898 +#define INLINE_MEMCPY_FLAG 0x00010
6899 +#define CACHE_VOLATILE_FLAG 0x0020
6900 +#define BYPASS_CACHE_FLAG 0x0040
6902 +extern int target_flags;
6903 +#define TARGET_HAS_DIV (target_flags & HAS_DIV_FLAG)
6904 +#define TARGET_HAS_MUL (target_flags & HAS_MUL_FLAG)
6905 +#define TARGET_HAS_MULX (target_flags & HAS_MULX_FLAG)
6906 +#define TARGET_FAST_SW_DIV (target_flags & FAST_SW_DIV_FLAG)
6907 +#define TARGET_INLINE_MEMCPY (target_flags & INLINE_MEMCPY_FLAG)
6908 +#define TARGET_CACHE_VOLATILE (target_flags & CACHE_VOLATILE_FLAG)
6909 +#define TARGET_BYPASS_CACHE (target_flags & BYPASS_CACHE_FLAG)
6911 +#define TARGET_SWITCHES \
6912 +{ \
6913 + { "hw-div", HAS_DIV_FLAG, \
6914 + N_("Enable DIV, DIVU") }, \
6915 + { "no-hw-div", -HAS_DIV_FLAG, \
6916 + N_("Disable DIV, DIVU (default)") }, \
6917 + { "hw-mul", HAS_MUL_FLAG, \
6918 + N_("Enable MUL instructions (default)") }, \
6919 + { "hw-mulx", HAS_MULX_FLAG, \
6920 + N_("Enable MULX instructions, assume fast shifter") }, \
6921 + { "no-hw-mul", -HAS_MUL_FLAG, \
6922 + N_("Disable MUL instructions") }, \
6923 + { "no-hw-mulx", -HAS_MULX_FLAG, \
6924 + N_("Disable MULX instructions, assume slow shifter (default and implied by -mno-hw-mul)") }, \
6925 + { "fast-sw-div", FAST_SW_DIV_FLAG, \
6926 + N_("Use table based fast divide (default at -O3)") }, \
6927 + { "no-fast-sw-div", -FAST_SW_DIV_FLAG, \
6928 + N_("Don't use table based fast divide ever") }, \
6929 + { "inline-memcpy", INLINE_MEMCPY_FLAG, \
6930 + N_("Inline small memcpy (default when optimizing)") }, \
6931 + { "no-inline-memcpy", -INLINE_MEMCPY_FLAG, \
6932 + N_("Don't Inline small memcpy") }, \
6933 + { "cache-volatile", CACHE_VOLATILE_FLAG, \
6934 + N_("Volatile accesses use non-io variants of instructions (default)") }, \
6935 + { "no-cache-volatile", -CACHE_VOLATILE_FLAG, \
6936 + N_("Volatile accesses use io variants of instructions") }, \
6937 + { "bypass-cache", BYPASS_CACHE_FLAG, \
6938 + N_("All ld/st instructins use io variants") }, \
6939 + { "no-bypass-cache", -BYPASS_CACHE_FLAG, \
6940 + N_("All ld/st instructins do not use io variants (default)") }, \
6941 + { "smallc", 0, \
6942 + N_("Link with a limited version of the C library") }, \
6943 + { "ctors-in-init", 0, \
6944 + "" /* undocumented: N_("Link with static constructors and destructors in init") */ }, \
6945 + { "", TARGET_DEFAULT, 0 } \
6949 +extern const char *nios2_sys_nosys_string; /* for -msys=nosys */
6950 +extern const char *nios2_sys_lib_string; /* for -msys-lib= */
6951 +extern const char *nios2_sys_crt0_string; /* for -msys-crt0= */
6953 +#define TARGET_OPTIONS \
6954 +{ \
6955 + { "sys=nosys", &nios2_sys_nosys_string, \
6956 + N_("Use stub versions of OS library calls (default)"), 0}, \
6957 + { "sys-lib=", &nios2_sys_lib_string, \
6958 + N_("Name of System Library to link against. (Converted to a -l option)"), 0}, \
6959 + { "sys-crt0=", &nios2_sys_crt0_string, \
6960 + N_("Name of the startfile. (default is a crt0 for the ISS only)"), 0}, \
6964 +/* Default target_flags if no switches specified. */
6965 +#ifndef TARGET_DEFAULT
6966 +# define TARGET_DEFAULT (HAS_MUL_FLAG | CACHE_VOLATILE_FLAG)
6967 +#endif
6969 +/* Switch Recognition by gcc.c. Add -G xx support */
6970 +#undef SWITCH_TAKES_ARG
6971 +#define SWITCH_TAKES_ARG(CHAR) \
6972 + (DEFAULT_SWITCH_TAKES_ARG (CHAR) || (CHAR) == 'G')
6974 +#define OVERRIDE_OPTIONS override_options ()
6975 +#define OPTIMIZATION_OPTIONS(LEVEL, SIZE) optimization_options (LEVEL, SIZE)
6976 +#define CAN_DEBUG_WITHOUT_FP
6978 +#define CC1_SPEC "\
6979 +%{G*}"
6981 +#undef LIB_SPEC
6982 +#define LIB_SPEC \
6983 +"--start-group %{msmallc: -lsmallc} %{!msmallc: -lc} -lgcc \
6984 + %{msys-lib=*: -l%*} \
6985 + %{!msys-lib=*: -lc } \
6986 + --end-group \
6987 + %{msys-lib=: %eYou need a library name for -msys-lib=} \
6991 +#undef STARTFILE_SPEC
6992 +#define STARTFILE_SPEC \
6993 +"%{msys-crt0=*: %*} %{!msys-crt0=*: crt1%O%s} \
6994 + %{msys-crt0=: %eYou need a C startup file for -msys-crt0=} \
6995 + %{mctors-in-init: crti%O%s crtbegin%O%s} \
6998 +#undef ENDFILE_SPEC
6999 +#define ENDFILE_SPEC \
7000 + "%{mctors-in-init: crtend%O%s crtn%O%s}"
7003 +/***********************
7004 + * Storage Layout
7005 + ***********************/
7007 +#define DEFAULT_SIGNED_CHAR 1
7008 +#define BITS_BIG_ENDIAN 0
7009 +#define BYTES_BIG_ENDIAN 0
7010 +#define WORDS_BIG_ENDIAN 0
7011 +#define BITS_PER_UNIT 8
7012 +#define BITS_PER_WORD 32
7013 +#define UNITS_PER_WORD 4
7014 +#define POINTER_SIZE 32
7015 +#define BIGGEST_ALIGNMENT 32
7016 +#define STRICT_ALIGNMENT 1
7017 +#define FUNCTION_BOUNDARY 32
7018 +#define PARM_BOUNDARY 32
7019 +#define STACK_BOUNDARY 32
7020 +#define PREFERRED_STACK_BOUNDARY 32
7021 +#define MAX_FIXED_MODE_SIZE 64
7023 +#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
7024 + ((TREE_CODE (EXP) == STRING_CST) \
7025 + && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
7028 +/**********************
7029 + * Layout of Source Language Data Types
7030 + **********************/
7032 +#define INT_TYPE_SIZE 32
7033 +#define SHORT_TYPE_SIZE 16
7034 +#define LONG_TYPE_SIZE 32
7035 +#define LONG_LONG_TYPE_SIZE 64
7036 +#define FLOAT_TYPE_SIZE 32
7037 +#define DOUBLE_TYPE_SIZE 64
7038 +#define LONG_DOUBLE_TYPE_SIZE DOUBLE_TYPE_SIZE
7041 +/*************************
7042 + * Condition Code Status
7043 + ************************/
7045 +/* comparison type */
7046 +/* ??? currently only CMP_SI is used */
7047 +enum cmp_type {
7048 + CMP_SI, /* compare four byte integers */
7049 + CMP_DI, /* compare eight byte integers */
7050 + CMP_SF, /* compare single precision floats */
7051 + CMP_DF, /* compare double precision floats */
7052 + CMP_MAX /* max comparison type */
7055 +extern GTY(()) rtx branch_cmp[2]; /* operands for compare */
7056 +extern enum cmp_type branch_type; /* what type of branch to use */
7058 +/**********************
7059 + * Register Usage
7060 + **********************/
7062 +/* ---------------------------------- *
7063 + * Basic Characteristics of Registers
7064 + * ---------------------------------- */
7067 +Register Number
7068 + Register Name
7069 + Alternate Name
7070 + Purpose
7071 +0 r0 zero always zero
7072 +1 r1 at Assembler Temporary
7073 +2-3 r2-r3 Return Location
7074 +4-7 r4-r7 Register Arguments
7075 +8-15 r8-r15 Caller Saved Registers
7076 +16-22 r16-r22 Callee Saved Registers
7077 +23 r23 sc Static Chain (Callee Saved)
7078 + ??? Does $sc want to be caller or callee
7079 + saved. If caller, 15, else 23.
7080 +24 r24 Exception Temporary
7081 +25 r25 Breakpoint Temporary
7082 +26 r26 gp Global Pointer
7083 +27 r27 sp Stack Pointer
7084 +28 r28 fp Frame Pointer
7085 +29 r29 ea Exception Return Address
7086 +30 r30 ba Breakpoint Return Address
7087 +31 r31 ra Return Address
7089 +32 ctl0 status
7090 +33 ctl1 estatus STATUS saved by exception ?
7091 +34 ctl2 bstatus STATUS saved by break ?
7092 +35 ctl3 ipri Interrupt Priority Mask ?
7093 +36 ctl4 ecause Exception Cause ?
7095 +37 pc Not an actual register
7097 +38 rap Return address pointer, this does not
7098 + actually exist and will be eliminated
7100 +39 fake_fp Fake Frame Pointer which will always be eliminated.
7101 +40 fake_ap Fake Argument Pointer which will always be eliminated.
7103 +41 First Pseudo Register
7106 +The definitions for all the hard register numbers
7107 +are located in nios2.md.
7110 +#define FIRST_PSEUDO_REGISTER 41
7111 +#define NUM_ARG_REGS (LAST_ARG_REGNO - FIRST_ARG_REGNO + 1)
7115 +/* also see CONDITIONAL_REGISTER_USAGE */
7116 +#define FIXED_REGISTERS \
7117 + { \
7118 +/* +0 1 2 3 4 5 6 7 8 9 */ \
7119 +/* 0 */ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, \
7120 +/* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
7121 +/* 20 */ 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, \
7122 +/* 30 */ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, \
7123 +/* 40 */ 1, \
7126 +/* call used is the same as caller saved
7127 + + fixed regs + args + ret vals */
7128 +#define CALL_USED_REGISTERS \
7129 + { \
7130 +/* +0 1 2 3 4 5 6 7 8 9 */ \
7131 +/* 0 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
7132 +/* 10 */ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, \
7133 +/* 20 */ 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, \
7134 +/* 30 */ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, \
7135 +/* 40 */ 1, \
7138 +#define HARD_REGNO_NREGS(REGNO, MODE) \
7139 + ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \
7140 + / UNITS_PER_WORD)
7142 +/* --------------------------- *
7143 + * How Values Fit in Registers
7144 + * --------------------------- */
7146 +#define HARD_REGNO_MODE_OK(REGNO, MODE) 1
7148 +#define MODES_TIEABLE_P(MODE1, MODE2) 1
7151 +/*************************
7152 + * Register Classes
7153 + *************************/
7155 +enum reg_class
7157 + NO_REGS,
7158 + ALL_REGS,
7159 + LIM_REG_CLASSES
7162 +#define N_REG_CLASSES (int) LIM_REG_CLASSES
7164 +#define REG_CLASS_NAMES \
7165 + {"NO_REGS", \
7166 + "ALL_REGS"}
7168 +#define GENERAL_REGS ALL_REGS
7170 +#define REG_CLASS_CONTENTS \
7171 +/* NO_REGS */ {{ 0, 0}, \
7172 +/* ALL_REGS */ {~0,~0}} \
7174 +#define REGNO_REG_CLASS(REGNO) ALL_REGS
7176 +#define BASE_REG_CLASS ALL_REGS
7177 +#define INDEX_REG_CLASS ALL_REGS
7179 +/* only one reg class, 'r', is handled automatically */
7180 +#define REG_CLASS_FROM_LETTER(CHAR) NO_REGS
7182 +#define REGNO_OK_FOR_BASE_P2(REGNO, STRICT) \
7183 + ((STRICT) \
7184 + ? (REGNO) < FIRST_PSEUDO_REGISTER \
7185 + : (REGNO) < FIRST_PSEUDO_REGISTER || (reg_renumber && reg_renumber[REGNO] < FIRST_PSEUDO_REGISTER))
7187 +#define REGNO_OK_FOR_INDEX_P2(REGNO, STRICT) \
7188 + (REGNO_OK_FOR_BASE_P2 (REGNO, STRICT))
7190 +#define REGNO_OK_FOR_BASE_P(REGNO) \
7191 + (REGNO_OK_FOR_BASE_P2 (REGNO, 1))
7193 +#define REGNO_OK_FOR_INDEX_P(REGNO) \
7194 + (REGNO_OK_FOR_INDEX_P2 (REGNO, 1))
7196 +#define REG_OK_FOR_BASE_P2(X, STRICT) \
7197 + (STRICT \
7198 + ? REGNO_OK_FOR_BASE_P2 (REGNO (X), 1) \
7199 + : REGNO_OK_FOR_BASE_P2 (REGNO (X), 1) || REGNO(X) >= FIRST_PSEUDO_REGISTER)
7201 +#define REG_OK_FOR_INDEX_P2(X, STRICT) \
7202 + (STRICT \
7203 + ? REGNO_OK_FOR_INDEX_P2 (REGNO (X), 1) \
7204 + : REGNO_OK_FOR_INDEX_P2 (REGNO (X), 1) || REGNO(X) >= FIRST_PSEUDO_REGISTER)
7206 +#define CLASS_MAX_NREGS(CLASS, MODE) \
7207 + ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \
7208 + / UNITS_PER_WORD)
7211 +#define SMALL_INT(X) ((unsigned HOST_WIDE_INT) ((X) + 0x8000) < 0x10000)
7212 +#define SMALL_INT_UNSIGNED(X) ((unsigned HOST_WIDE_INT) (X) < 0x10000)
7213 +#define UPPER16_INT(X) (((X) & 0xffff) == 0)
7214 +#define SHIFT_INT(X) ((X) >= 0 && (X) <= 31)
7215 +#define RDWRCTL_INT(X) ((X) >= 0 && (X) <= 31)
7216 +#define CUSTOM_INSN_OPCODE(X) ((X) >= 0 && (X) <= 255)
7218 +#define CONST_OK_FOR_LETTER_P(VALUE, C) \
7219 + ( \
7220 + (C) == 'I' ? SMALL_INT (VALUE) : \
7221 + (C) == 'J' ? SMALL_INT_UNSIGNED (VALUE) : \
7222 + (C) == 'K' ? UPPER16_INT (VALUE) : \
7223 + (C) == 'L' ? SHIFT_INT (VALUE) : \
7224 + (C) == 'M' ? (VALUE) == 0 : \
7225 + (C) == 'N' ? CUSTOM_INSN_OPCODE (VALUE) : \
7226 + (C) == 'O' ? RDWRCTL_INT (VALUE) : \
7227 + 0)
7229 +#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 0
7231 +#define PREFERRED_RELOAD_CLASS(X, CLASS) \
7232 + ((CLASS) == NO_REGS ? GENERAL_REGS : (CLASS))
7234 +/* 'S' matches immediates which are in small data
7235 + and therefore can be added to gp to create a
7236 + 32-bit value. */
7237 +#define EXTRA_CONSTRAINT(VALUE, C) \
7238 + ((C) == 'S' \
7239 + && (GET_CODE (VALUE) == SYMBOL_REF) \
7240 + && SYMBOL_REF_IN_NIOS2_SMALL_DATA_P (VALUE))
7245 +/* Say that the epilogue uses the return address register. Note that
7246 + in the case of sibcalls, the values "used by the epilogue" are
7247 + considered live at the start of the called function. */
7248 +#define EPILOGUE_USES(REGNO) ((REGNO) == RA_REGNO)
7251 +#define DEFAULT_MAIN_RETURN c_expand_return (integer_zero_node)
7253 +/**********************************
7254 + * Trampolines for Nested Functions
7255 + ***********************************/
7257 +#define TRAMPOLINE_TEMPLATE(FILE) \
7258 + error ("trampolines not yet implemented")
7259 +#define TRAMPOLINE_SIZE 20
7260 +#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
7261 + error ("trampolines not yet implemented")
7263 +/***************************
7264 + * Stack Layout and Calling Conventions
7265 + ***************************/
7267 +/* ------------------ *
7268 + * Basic Stack Layout
7269 + * ------------------ */
7271 +/* The downward variants are used by the compiler,
7272 + the upward ones serve as documentation */
7273 +#define STACK_GROWS_DOWNWARD
7274 +#define FRAME_GROWS_UPWARD
7275 +#define ARGS_GROW_UPWARD
7277 +#define STARTING_FRAME_OFFSET current_function_outgoing_args_size
7278 +#define FIRST_PARM_OFFSET(FUNDECL) 0
7280 +/* Before the prologue, RA lives in r31. */
7281 +#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (VOIDmode, RA_REGNO)
7283 +/* -------------------------------------- *
7284 + * Registers That Address the Stack Frame
7285 + * -------------------------------------- */
7287 +#define STACK_POINTER_REGNUM SP_REGNO
7288 +#define STATIC_CHAIN_REGNUM SC_REGNO
7289 +#define PC_REGNUM PC_REGNO
7290 +#define DWARF_FRAME_RETURN_COLUMN RA_REGNO
7292 +/* Base register for access to local variables of the function. We
7293 + pretend that the frame pointer is a non-existent hard register, and
7294 + then eliminate it to HARD_FRAME_POINTER_REGNUM. */
7295 +#define FRAME_POINTER_REGNUM FAKE_FP_REGNO
7297 +#define HARD_FRAME_POINTER_REGNUM FP_REGNO
7298 +#define RETURN_ADDRESS_POINTER_REGNUM RAP_REGNO
7299 +/* the argumnet pointer needs to always be eliminated
7300 + so it is set to a fake hard register. */
7301 +#define ARG_POINTER_REGNUM FAKE_AP_REGNO
7303 +/* ----------------------------------------- *
7304 + * Eliminating Frame Pointer and Arg Pointer
7305 + * ----------------------------------------- */
7307 +#define FRAME_POINTER_REQUIRED 0
7309 +#define ELIMINABLE_REGS \
7310 +{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
7311 + { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
7312 + { RETURN_ADDRESS_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
7313 + { RETURN_ADDRESS_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
7314 + { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
7315 + { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
7317 +#define CAN_ELIMINATE(FROM, TO) 1
7319 +#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
7320 + (OFFSET) = nios2_initial_elimination_offset ((FROM), (TO))
7322 +#define MUST_SAVE_REGISTER(regno) \
7323 + ((regs_ever_live[regno] && !call_used_regs[regno]) \
7324 + || (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed) \
7325 + || (regno == RA_REGNO && regs_ever_live[RA_REGNO]))
7327 +/* Treat LOC as a byte offset from the stack pointer and round it up
7328 + to the next fully-aligned offset. */
7329 +#define STACK_ALIGN(LOC) \
7330 + (((LOC) + ((PREFERRED_STACK_BOUNDARY / 8) - 1)) & ~((PREFERRED_STACK_BOUNDARY / 8) - 1))
7333 +/* ------------------------------ *
7334 + * Passing Arguments in Registers
7335 + * ------------------------------ */
7337 +/* see nios2.c */
7338 +#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
7339 + (function_arg (&CUM, MODE, TYPE, NAMED))
7341 +#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
7342 + (function_arg_partial_nregs (&CUM, MODE, TYPE, NAMED))
7344 +#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) 0
7346 +#define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) 0
7348 +typedef struct nios2_args
7350 + int regs_used;
7351 +} CUMULATIVE_ARGS;
7353 +/* This is to initialize the above unused CUM data type */
7354 +#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
7355 + (init_cumulative_args (&CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS))
7357 +#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
7358 + (function_arg_advance (&CUM, MODE, TYPE, NAMED))
7360 +#define FUNCTION_ARG_REGNO_P(REGNO) \
7361 + ((REGNO) >= FIRST_ARG_REGNO && (REGNO) <= LAST_ARG_REGNO)
7363 +#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \
7364 + { \
7365 + int pret_size = nios2_setup_incoming_varargs (&(CUM), (MODE), \
7366 + (TYPE), (NO_RTL)); \
7367 + if (pret_size) \
7368 + (PRETEND_SIZE) = pret_size; \
7371 +/* ----------------------------- *
7372 + * Generating Code for Profiling
7373 + * ----------------------------- */
7375 +#define PROFILE_BEFORE_PROLOGUE
7377 +#define FUNCTION_PROFILER(FILE, LABELNO) \
7378 + function_profiler ((FILE), (LABELNO))
7380 +/* --------------------------------------- *
7381 + * Passing Function Arguments on the Stack
7382 + * --------------------------------------- */
7384 +#define PROMOTE_PROTOTYPES 1
7386 +#define PUSH_ARGS 0
7387 +#define ACCUMULATE_OUTGOING_ARGS 1
7389 +#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACKSIZE) 0
7391 +/* --------------------------------------- *
7392 + * How Scalar Function Values Are Returned
7393 + * --------------------------------------- */
7395 +#define FUNCTION_VALUE(VALTYPE, FUNC) \
7396 + gen_rtx(REG, TYPE_MODE(VALTYPE), FIRST_RETVAL_REGNO)
7398 +#define LIBCALL_VALUE(MODE) \
7399 + gen_rtx(REG, MODE, FIRST_RETVAL_REGNO)
7401 +#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == FIRST_RETVAL_REGNO)
7403 +/* ----------------------------- *
7404 + * How Large Values Are Returned
7405 + * ----------------------------- */
7408 +#define RETURN_IN_MEMORY(TYPE) \
7409 + nios2_return_in_memory (TYPE)
7412 +#define STRUCT_VALUE 0
7414 +#define DEFAULT_PCC_STRUCT_RETURN 0
7416 +/*******************
7417 + * Addressing Modes
7418 + *******************/
7421 +#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)
7423 +#define CONSTANT_ADDRESS_P(X) (CONSTANT_P (X))
7425 +#define MAX_REGS_PER_ADDRESS 1
7427 +/* Go to ADDR if X is a valid address. */
7428 +#ifndef REG_OK_STRICT
7429 +#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
7430 + { \
7431 + if (nios2_legitimate_address ((X), (MODE), 0)) \
7432 + goto ADDR; \
7434 +#else
7435 +#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
7436 + { \
7437 + if (nios2_legitimate_address ((X), (MODE), 1)) \
7438 + goto ADDR; \
7440 +#endif
7442 +#ifndef REG_OK_STRICT
7443 +#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P2 (REGNO (X), 0)
7444 +#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P2 (REGNO (X), 0)
7445 +#else
7446 +#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P2 (REGNO (X), 1)
7447 +#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P2 (REGNO (X), 1)
7448 +#endif
7450 +#define LEGITIMATE_CONSTANT_P(X) 1
7452 +/* Nios II has no mode dependent addresses. */
7453 +#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)
7455 +/* Set if this has a weak declaration */
7456 +#define SYMBOL_FLAG_WEAK_DECL (1 << SYMBOL_FLAG_MACH_DEP_SHIFT)
7457 +#define SYMBOL_REF_WEAK_DECL_P(RTX) \
7458 + ((SYMBOL_REF_FLAGS (RTX) & SYMBOL_FLAG_WEAK_DECL) != 0)
7461 +/* true if a symbol is both small and not weak. In this case, gp
7462 + relative access can be used */
7463 +#define SYMBOL_REF_IN_NIOS2_SMALL_DATA_P(RTX) \
7464 + (SYMBOL_REF_SMALL_P(RTX) && !SYMBOL_REF_WEAK_DECL_P(RTX))
7466 +/*****************
7467 + * Describing Relative Costs of Operations
7468 + *****************/
7470 +#define SLOW_BYTE_ACCESS 1
7472 +/* It is as good to call a constant function address as to call an address
7473 + kept in a register.
7474 + ??? Not true anymore really. Now that call cannot address full range
7475 + of memory callr may need to be used */
7477 +#define NO_FUNCTION_CSE
7478 +#define NO_RECURSIVE_FUNCTION_CSE
7482 +/*****************************************
7483 + * Defining the Output Assembler Language
7484 + *****************************************/
7486 +/* ------------------------------------------ *
7487 + * The Overall Framework of an Assembler File
7488 + * ------------------------------------------ */
7490 +#define ASM_APP_ON "#APP\n"
7491 +#define ASM_APP_OFF "#NO_APP\n"
7493 +#define ASM_COMMENT_START "# "
7495 +/* ------------------------------- *
7496 + * Output and Generation of Labels
7497 + * ------------------------------- */
7499 +#define GLOBAL_ASM_OP "\t.global\t"
7502 +/* -------------- *
7503 + * Output of Data
7504 + * -------------- */
7506 +#define DWARF2_UNWIND_INFO 0
7509 +/* -------------------------------- *
7510 + * Assembler Commands for Alignment
7511 + * -------------------------------- */
7513 +#define ASM_OUTPUT_ALIGN(FILE, LOG) \
7514 + do { \
7515 + fprintf ((FILE), "%s%d\n", ALIGN_ASM_OP, (LOG)); \
7516 + } while (0)
7519 +/* -------------------------------- *
7520 + * Output of Assembler Instructions
7521 + * -------------------------------- */
7523 +#define REGISTER_NAMES \
7524 +{ \
7525 + "zero", \
7526 + "at", \
7527 + "r2", \
7528 + "r3", \
7529 + "r4", \
7530 + "r5", \
7531 + "r6", \
7532 + "r7", \
7533 + "r8", \
7534 + "r9", \
7535 + "r10", \
7536 + "r11", \
7537 + "r12", \
7538 + "r13", \
7539 + "r14", \
7540 + "r15", \
7541 + "r16", \
7542 + "r17", \
7543 + "r18", \
7544 + "r19", \
7545 + "r20", \
7546 + "r21", \
7547 + "r22", \
7548 + "r23", \
7549 + "r24", \
7550 + "r25", \
7551 + "gp", \
7552 + "sp", \
7553 + "fp", \
7554 + "ta", \
7555 + "ba", \
7556 + "ra", \
7557 + "status", \
7558 + "estatus", \
7559 + "bstatus", \
7560 + "ipri", \
7561 + "ecause", \
7562 + "pc", \
7563 + "rap", \
7564 + "fake_fp", \
7565 + "fake_ap", \
7568 +#define ASM_OUTPUT_OPCODE(STREAM, PTR)\
7569 + (PTR) = asm_output_opcode (STREAM, PTR)
7571 +#define PRINT_OPERAND(STREAM, X, CODE) \
7572 + nios2_print_operand (STREAM, X, CODE)
7574 +#define PRINT_OPERAND_ADDRESS(STREAM, X) \
7575 + nios2_print_operand_address (STREAM, X)
7577 +#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
7578 +do { fputs (integer_asm_op (POINTER_SIZE / BITS_PER_UNIT, TRUE), FILE); \
7579 + fprintf (FILE, ".L%u\n", (unsigned) (VALUE)); \
7580 + } while (0)
7583 +/* ------------ *
7584 + * Label Output
7585 + * ------------ */
7588 +/* ---------------------------------------------------- *
7589 + * Dividing the Output into Sections (Texts, Data, ...)
7590 + * ---------------------------------------------------- */
7592 +/* Output before read-only data. */
7593 +#define TEXT_SECTION_ASM_OP ("\t.section\t.text")
7595 +/* Output before writable data. */
7596 +#define DATA_SECTION_ASM_OP ("\t.section\t.data")
7599 +/* Default the definition of "small data" to 8 bytes. */
7600 +/* ??? How come I can't use HOST_WIDE_INT here? */
7601 +extern unsigned long nios2_section_threshold;
7602 +#define NIOS2_DEFAULT_GVALUE 8
7606 +/* This says how to output assembler code to declare an
7607 + uninitialized external linkage data object. Under SVR4,
7608 + the linker seems to want the alignment of data objects
7609 + to depend on their types. We do exactly that here. */
7611 +#undef COMMON_ASM_OP
7612 +#define COMMON_ASM_OP "\t.comm\t"
7614 +#undef ASM_OUTPUT_ALIGNED_COMMON
7615 +#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \
7616 +do \
7617 +{ \
7618 + if ((SIZE) <= nios2_section_threshold) \
7619 + { \
7620 + named_section (0, ".sbss", 0); \
7621 + (*targetm.asm_out.globalize_label) (FILE, NAME); \
7622 + ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
7623 + if (!flag_inhibit_size_directive) \
7624 + ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, SIZE); \
7625 + ASM_OUTPUT_ALIGN ((FILE), exact_log2((ALIGN) / BITS_PER_UNIT)); \
7626 + ASM_OUTPUT_LABEL(FILE, NAME); \
7627 + ASM_OUTPUT_SKIP((FILE), (SIZE) ? (SIZE) : 1); \
7628 + } \
7629 + else \
7630 + { \
7631 + fprintf ((FILE), "%s", COMMON_ASM_OP); \
7632 + assemble_name ((FILE), (NAME)); \
7633 + fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED",%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT); \
7634 + } \
7635 +} \
7636 +while (0)
7639 +/* This says how to output assembler code to declare an
7640 + uninitialized internal linkage data object. Under SVR4,
7641 + the linker seems to want the alignment of data objects
7642 + to depend on their types. We do exactly that here. */
7644 +#undef ASM_OUTPUT_ALIGNED_LOCAL
7645 +#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \
7646 +do { \
7647 + if ((SIZE) <= nios2_section_threshold) \
7648 + named_section (0, ".sbss", 0); \
7649 + else \
7650 + named_section (0, ".bss", 0); \
7651 + ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
7652 + if (!flag_inhibit_size_directive) \
7653 + ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, SIZE); \
7654 + ASM_OUTPUT_ALIGN ((FILE), exact_log2((ALIGN) / BITS_PER_UNIT)); \
7655 + ASM_OUTPUT_LABEL(FILE, NAME); \
7656 + ASM_OUTPUT_SKIP((FILE), (SIZE) ? (SIZE) : 1); \
7657 +} while (0)
7661 +/***************************
7662 + * Miscellaneous Parameters
7663 + ***************************/
7665 +#define MOVE_MAX 4
7667 +#define Pmode SImode
7668 +#define FUNCTION_MODE QImode
7670 +#define CASE_VECTOR_MODE Pmode
7672 +#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
7674 +#define LOAD_EXTEND_OP(MODE) (ZERO_EXTEND)
7676 +#define WORD_REGISTER_OPERATIONS
7677 --- gcc-3.4.3/gcc/config/nios2/nios2.md
7678 +++ gcc-3.4.3-nios2/gcc/config/nios2/nios2.md
7679 @@ -0,0 +1,2078 @@
7680 +;; Machine Description for Altera NIOS 2G NIOS2 version.
7681 +;; Copyright (C) 2003 Altera
7682 +;; Contributed by Jonah Graham (jgraham@altera.com).
7683 +;;
7684 +;; This file is part of GNU CC.
7685 +;;
7686 +;; GNU CC is free software; you can redistribute it and/or modify
7687 +;; it under the terms of the GNU General Public License as published by
7688 +;; the Free Software Foundation; either version 2, or (at your option)
7689 +;; any later version.
7690 +;;
7691 +;; GNU CC is distributed in the hope that it will be useful,
7692 +;; but WITHOUT ANY WARRANTY; without even the implied warranty of
7693 +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7694 +;; GNU General Public License for more details.
7695 +;;
7696 +;; You should have received a copy of the GNU General Public License
7697 +;; along with GNU CC; see the file COPYING. If not, write to
7698 +;; the Free Software Foundation, 59 Temple Place - Suite 330,
7699 +;; Boston, MA 02111-1307, USA. */
7703 +;*****************************************************************************
7705 +;* constants
7707 +;*****************************************************************************
7708 +(define_constants [
7709 + (GP_REGNO 26)
7710 + (SP_REGNO 27)
7711 + (FP_REGNO 28)
7712 + (RA_REGNO 31)
7713 + (RAP_REGNO 38)
7714 + (FIRST_RETVAL_REGNO 2)
7715 + (LAST_RETVAL_REGNO 3)
7716 + (FIRST_ARG_REGNO 4)
7717 + (LAST_ARG_REGNO 7)
7718 + (SC_REGNO 23)
7719 + (PC_REGNO 37)
7720 + (FAKE_FP_REGNO 39)
7721 + (FAKE_AP_REGNO 40)
7724 + (UNSPEC_BLOCKAGE 0)
7725 + (UNSPEC_LDBIO 1)
7726 + (UNSPEC_LDBUIO 2)
7727 + (UNSPEC_LDHIO 3)
7728 + (UNSPEC_LDHUIO 4)
7729 + (UNSPEC_LDWIO 5)
7730 + (UNSPEC_STBIO 6)
7731 + (UNSPEC_STHIO 7)
7732 + (UNSPEC_STWIO 8)
7733 + (UNSPEC_SYNC 9)
7734 + (UNSPEC_WRCTL 10)
7735 + (UNSPEC_RDCTL 11)
7741 +;*****************************************************************************
7743 +;* instruction scheduler
7745 +;*****************************************************************************
7747 +; No schedule info is currently available, using an assumption that no
7748 +; instruction can use the results of the previous instruction without
7749 +; incuring a stall.
7751 +; length of an instruction (in bytes)
7752 +(define_attr "length" "" (const_int 4))
7753 +(define_attr "type" "unknown,complex,control,alu,cond_alu,st,ld,shift,mul,div,custom" (const_string "complex"))
7755 +(define_asm_attributes
7756 + [(set_attr "length" "4")
7757 + (set_attr "type" "complex")])
7759 +(define_automaton "nios2")
7760 +(automata_option "v")
7761 +;(automata_option "no-minimization")
7762 +(automata_option "ndfa")
7764 +; The nios2 pipeline is fairly straightforward for the fast model.
7765 +; Every alu operation is pipelined so that an instruction can
7766 +; be issued every cycle. However, there are still potential
7767 +; stalls which this description tries to deal with.
7769 +(define_cpu_unit "cpu" "nios2")
7771 +(define_insn_reservation "complex" 1
7772 + (eq_attr "type" "complex")
7773 + "cpu")
7775 +(define_insn_reservation "control" 1
7776 + (eq_attr "type" "control")
7777 + "cpu")
7779 +(define_insn_reservation "alu" 1
7780 + (eq_attr "type" "alu")
7781 + "cpu")
7783 +(define_insn_reservation "cond_alu" 1
7784 + (eq_attr "type" "cond_alu")
7785 + "cpu")
7787 +(define_insn_reservation "st" 1
7788 + (eq_attr "type" "st")
7789 + "cpu")
7791 +(define_insn_reservation "custom" 1
7792 + (eq_attr "type" "custom")
7793 + "cpu")
7795 +; shifts, muls and lds have three cycle latency
7796 +(define_insn_reservation "ld" 3
7797 + (eq_attr "type" "ld")
7798 + "cpu")
7800 +(define_insn_reservation "shift" 3
7801 + (eq_attr "type" "shift")
7802 + "cpu")
7804 +(define_insn_reservation "mul" 3
7805 + (eq_attr "type" "mul")
7806 + "cpu")
7808 +(define_insn_reservation "div" 1
7809 + (eq_attr "type" "div")
7810 + "cpu")
7813 +;*****************************************************************************
7815 +;* MOV Instructions
7817 +;*****************************************************************************
7819 +(define_expand "movqi"
7820 + [(set (match_operand:QI 0 "nonimmediate_operand" "")
7821 + (match_operand:QI 1 "general_operand" ""))]
7822 + ""
7824 + if (nios2_emit_move_sequence (operands, QImode))
7825 + DONE;
7828 +(define_insn "movqi_internal"
7829 + [(set (match_operand:QI 0 "nonimmediate_operand" "=m, r,r, r")
7830 + (match_operand:QI 1 "general_operand" "rM,m,rM,I"))]
7831 + "(register_operand (operands[0], QImode)
7832 + || register_operand (operands[1], QImode)
7833 + || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))"
7834 + "@
7835 + stb%o0\\t%z1, %0
7836 + ldbu%o1\\t%0, %1
7837 + mov\\t%0, %z1
7838 + movi\\t%0, %1"
7839 + [(set_attr "type" "st,ld,alu,alu")])
7841 +(define_insn "ldbio"
7842 + [(set (match_operand:SI 0 "register_operand" "=r")
7843 + (unspec_volatile:SI [(const_int 0)] UNSPEC_LDBIO))
7844 + (use (match_operand:SI 1 "memory_operand" "m"))]
7845 + ""
7846 + "ldbio\\t%0, %1"
7847 + [(set_attr "type" "ld")])
7849 +(define_insn "ldbuio"
7850 + [(set (match_operand:SI 0 "register_operand" "=r")
7851 + (unspec_volatile:SI [(const_int 0)] UNSPEC_LDBUIO))
7852 + (use (match_operand:SI 1 "memory_operand" "m"))]
7853 + ""
7854 + "ldbuio\\t%0, %1"
7855 + [(set_attr "type" "ld")])
7857 +(define_insn "stbio"
7858 + [(set (match_operand:SI 0 "memory_operand" "=m")
7859 + (match_operand:SI 1 "register_operand" "r"))
7860 + (unspec_volatile:SI [(const_int 0)] UNSPEC_STBIO)]
7861 + ""
7862 + "stbio\\t%z1, %0"
7863 + [(set_attr "type" "st")])
7866 +(define_expand "movhi"
7867 + [(set (match_operand:HI 0 "nonimmediate_operand" "")
7868 + (match_operand:HI 1 "general_operand" ""))]
7869 + ""
7871 + if (nios2_emit_move_sequence (operands, HImode))
7872 + DONE;
7875 +(define_insn "movhi_internal"
7876 + [(set (match_operand:HI 0 "nonimmediate_operand" "=m, r,r, r,r")
7877 + (match_operand:HI 1 "general_operand" "rM,m,rM,I,J"))]
7878 + "(register_operand (operands[0], HImode)
7879 + || register_operand (operands[1], HImode)
7880 + || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))"
7881 + "@
7882 + sth%o0\\t%z1, %0
7883 + ldhu%o1\\t%0, %1
7884 + mov\\t%0, %z1
7885 + movi\\t%0, %1
7886 + movui\\t%0, %1"
7887 + [(set_attr "type" "st,ld,alu,alu,alu")])
7889 +(define_insn "ldhio"
7890 + [(set (match_operand:SI 0 "register_operand" "=r")
7891 + (unspec_volatile:SI [(const_int 0)] UNSPEC_LDHIO))
7892 + (use (match_operand:SI 1 "memory_operand" "m"))]
7893 + ""
7894 + "ldhio\\t%0, %1"
7895 + [(set_attr "type" "ld")])
7897 +(define_insn "ldhuio"
7898 + [(set (match_operand:SI 0 "register_operand" "=r")
7899 + (unspec_volatile:SI [(const_int 0)] UNSPEC_LDHUIO))
7900 + (use (match_operand:SI 1 "memory_operand" "m"))]
7901 + ""
7902 + "ldhuio\\t%0, %1"
7903 + [(set_attr "type" "ld")])
7905 +(define_insn "sthio"
7906 + [(set (match_operand:SI 0 "memory_operand" "=m")
7907 + (match_operand:SI 1 "register_operand" "r"))
7908 + (unspec_volatile:SI [(const_int 0)] UNSPEC_STHIO)]
7909 + ""
7910 + "sthio\\t%z1, %0"
7911 + [(set_attr "type" "st")])
7913 +(define_expand "movsi"
7914 + [(set (match_operand:SI 0 "nonimmediate_operand" "")
7915 + (match_operand:SI 1 "general_operand" ""))]
7916 + ""
7918 + if (nios2_emit_move_sequence (operands, SImode))
7919 + DONE;
7922 +(define_insn "movsi_internal"
7923 + [(set (match_operand:SI 0 "nonimmediate_operand" "=m, r,r, r,r,r,r")
7924 + (match_operand:SI 1 "general_operand" "rM,m,rM,I,J,S,i"))]
7925 + "(register_operand (operands[0], SImode)
7926 + || register_operand (operands[1], SImode)
7927 + || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))"
7928 + "@
7929 + stw%o0\\t%z1, %0
7930 + ldw%o1\\t%0, %1
7931 + mov\\t%0, %z1
7932 + movi\\t%0, %1
7933 + movui\\t%0, %1
7934 + addi\\t%0, gp, %%gprel(%1)
7935 + movhi\\t%0, %H1\;addi\\t%0, %0, %L1"
7936 + [(set_attr "type" "st,ld,alu,alu,alu,alu,alu")])
7938 +(define_insn "ldwio"
7939 + [(set (match_operand:SI 0 "register_operand" "=r")
7940 + (unspec_volatile:SI [(const_int 0)] UNSPEC_LDWIO))
7941 + (use (match_operand:SI 1 "memory_operand" "m"))]
7942 + ""
7943 + "ldwio\\t%0, %1"
7944 + [(set_attr "type" "ld")])
7946 +(define_insn "stwio"
7947 + [(set (match_operand:SI 0 "memory_operand" "=m")
7948 + (match_operand:SI 1 "register_operand" "r"))
7949 + (unspec_volatile:SI [(const_int 0)] UNSPEC_STWIO)]
7950 + ""
7951 + "stwio\\t%z1, %0"
7952 + [(set_attr "type" "st")])
7956 +;*****************************************************************************
7958 +;* zero extension
7960 +;*****************************************************************************
7963 +(define_insn "zero_extendhisi2"
7964 + [(set (match_operand:SI 0 "register_operand" "=r,r")
7965 + (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
7966 + ""
7967 + "@
7968 + andi\\t%0, %1, 0xffff
7969 + ldhu%o1\\t%0, %1"
7970 + [(set_attr "type" "alu,ld")])
7972 +(define_insn "zero_extendqihi2"
7973 + [(set (match_operand:HI 0 "register_operand" "=r,r")
7974 + (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
7975 + ""
7976 + "@
7977 + andi\\t%0, %1, 0xff
7978 + ldbu%o1\\t%0, %1"
7979 + [(set_attr "type" "alu,ld")])
7981 +(define_insn "zero_extendqisi2"
7982 + [(set (match_operand:SI 0 "register_operand" "=r,r")
7983 + (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
7984 + ""
7985 + "@
7986 + andi\\t%0, %1, 0xff
7987 + ldbu%o1\\t%0, %1"
7988 + [(set_attr "type" "alu,ld")])
7992 +;*****************************************************************************
7994 +;* sign extension
7996 +;*****************************************************************************
7998 +(define_expand "extendhisi2"
7999 + [(set (match_operand:SI 0 "register_operand" "")
8000 + (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
8001 + ""
8003 + if (optimize && GET_CODE (operands[1]) == MEM)
8004 + operands[1] = force_not_mem (operands[1]);
8006 + if (GET_CODE (operands[1]) != MEM)
8008 + rtx op1 = gen_lowpart (SImode, operands[1]);
8009 + rtx temp = gen_reg_rtx (SImode);
8010 + rtx shift = GEN_INT (16);
8012 + emit_insn (gen_ashlsi3 (temp, op1, shift));
8013 + emit_insn (gen_ashrsi3 (operands[0], temp, shift));
8014 + DONE;
8018 +(define_insn "extendhisi2_internal"
8019 + [(set (match_operand:SI 0 "register_operand" "=r")
8020 + (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
8021 + ""
8022 + "ldh%o1\\t%0, %1"
8023 + [(set_attr "type" "ld")])
8025 +(define_expand "extendqihi2"
8026 + [(set (match_operand:HI 0 "register_operand" "")
8027 + (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))]
8028 + ""
8030 + if (optimize && GET_CODE (operands[1]) == MEM)
8031 + operands[1] = force_not_mem (operands[1]);
8033 + if (GET_CODE (operands[1]) != MEM)
8035 + rtx op0 = gen_lowpart (SImode, operands[0]);
8036 + rtx op1 = gen_lowpart (SImode, operands[1]);
8037 + rtx temp = gen_reg_rtx (SImode);
8038 + rtx shift = GEN_INT (24);
8040 + emit_insn (gen_ashlsi3 (temp, op1, shift));
8041 + emit_insn (gen_ashrsi3 (op0, temp, shift));
8042 + DONE;
8046 +(define_insn "extendqihi2_internal"
8047 + [(set (match_operand:HI 0 "register_operand" "=r")
8048 + (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
8049 + ""
8050 + "ldb%o1\\t%0, %1"
8051 + [(set_attr "type" "ld")])
8054 +(define_expand "extendqisi2"
8055 + [(set (match_operand:SI 0 "register_operand" "")
8056 + (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
8057 + ""
8059 + if (optimize && GET_CODE (operands[1]) == MEM)
8060 + operands[1] = force_not_mem (operands[1]);
8062 + if (GET_CODE (operands[1]) != MEM)
8064 + rtx op1 = gen_lowpart (SImode, operands[1]);
8065 + rtx temp = gen_reg_rtx (SImode);
8066 + rtx shift = GEN_INT (24);
8068 + emit_insn (gen_ashlsi3 (temp, op1, shift));
8069 + emit_insn (gen_ashrsi3 (operands[0], temp, shift));
8070 + DONE;
8074 +(define_insn "extendqisi2_insn"
8075 + [(set (match_operand:SI 0 "register_operand" "=r")
8076 + (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
8077 + ""
8078 + "ldb%o1\\t%0, %1"
8079 + [(set_attr "type" "ld")])
8083 +;*****************************************************************************
8085 +;* Arithmetic Operations
8087 +;*****************************************************************************
8089 +(define_insn "addsi3"
8090 + [(set (match_operand:SI 0 "register_operand" "=r,r")
8091 + (plus:SI (match_operand:SI 1 "register_operand" "%r,r")
8092 + (match_operand:SI 2 "arith_operand" "r,I")))]
8093 + ""
8094 + "add%i2\\t%0, %1, %z2"
8095 + [(set_attr "type" "alu")])
8097 +(define_insn "subsi3"
8098 + [(set (match_operand:SI 0 "register_operand" "=r")
8099 + (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
8100 + (match_operand:SI 2 "register_operand" "r")))]
8101 + ""
8102 + "sub\\t%0, %z1, %2"
8103 + [(set_attr "type" "alu")])
8105 +(define_insn "mulsi3"
8106 + [(set (match_operand:SI 0 "register_operand" "=r,r")
8107 + (mult:SI (match_operand:SI 1 "register_operand" "r,r")
8108 + (match_operand:SI 2 "arith_operand" "r,I")))]
8109 + "TARGET_HAS_MUL"
8110 + "mul%i2\\t%0, %1, %z2"
8111 + [(set_attr "type" "mul")])
8113 +(define_expand "divsi3"
8114 + [(set (match_operand:SI 0 "register_operand" "=r")
8115 + (div:SI (match_operand:SI 1 "register_operand" "r")
8116 + (match_operand:SI 2 "register_operand" "r")))]
8117 + ""
8119 + if (!TARGET_HAS_DIV)
8121 + if (!TARGET_FAST_SW_DIV)
8122 + FAIL;
8123 + else
8125 + if (nios2_emit_expensive_div (operands, SImode))
8126 + DONE;
8131 +(define_insn "divsi3_insn"
8132 + [(set (match_operand:SI 0 "register_operand" "=r")
8133 + (div:SI (match_operand:SI 1 "register_operand" "r")
8134 + (match_operand:SI 2 "register_operand" "r")))]
8135 + "TARGET_HAS_DIV"
8136 + "div\\t%0, %1, %2"
8137 + [(set_attr "type" "div")])
8139 +(define_insn "udivsi3"
8140 + [(set (match_operand:SI 0 "register_operand" "=r")
8141 + (udiv:SI (match_operand:SI 1 "register_operand" "r")
8142 + (match_operand:SI 2 "register_operand" "r")))]
8143 + "TARGET_HAS_DIV"
8144 + "divu\\t%0, %1, %2"
8145 + [(set_attr "type" "div")])
8147 +(define_insn "smulsi3_highpart"
8148 + [(set (match_operand:SI 0 "register_operand" "=r")
8149 + (truncate:SI
8150 + (lshiftrt:DI
8151 + (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
8152 + (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
8153 + (const_int 32))))]
8154 + "TARGET_HAS_MULX"
8155 + "mulxss\\t%0, %1, %2"
8156 + [(set_attr "type" "mul")])
8158 +(define_insn "umulsi3_highpart"
8159 + [(set (match_operand:SI 0 "register_operand" "=r")
8160 + (truncate:SI
8161 + (lshiftrt:DI
8162 + (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
8163 + (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
8164 + (const_int 32))))]
8165 + "TARGET_HAS_MULX"
8166 + "mulxuu\\t%0, %1, %2"
8167 + [(set_attr "type" "mul")])
8170 +(define_expand "mulsidi3"
8171 + [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 0)
8172 + (mult:SI (match_operand:SI 1 "register_operand" "")
8173 + (match_operand:SI 2 "register_operand" "")))
8174 + (set (subreg:SI (match_dup 0) 4)
8175 + (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1))
8176 + (sign_extend:DI (match_dup 2)))
8177 + (const_int 32))))]
8178 + "TARGET_HAS_MULX"
8179 + "")
8181 +(define_expand "umulsidi3"
8182 + [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 0)
8183 + (mult:SI (match_operand:SI 1 "register_operand" "")
8184 + (match_operand:SI 2 "register_operand" "")))
8185 + (set (subreg:SI (match_dup 0) 4)
8186 + (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1))
8187 + (zero_extend:DI (match_dup 2)))
8188 + (const_int 32))))]
8189 + "TARGET_HAS_MULX"
8190 + "")
8194 +;*****************************************************************************
8196 +;* Negate and ones complement
8198 +;*****************************************************************************
8200 +(define_insn "negsi2"
8201 + [(set (match_operand:SI 0 "register_operand" "=r")
8202 + (neg:SI (match_operand:SI 1 "register_operand" "r")))]
8203 + ""
8205 + operands[2] = const0_rtx;
8206 + return "sub\\t%0, %z2, %1";
8208 + [(set_attr "type" "alu")])
8210 +(define_insn "one_cmplsi2"
8211 + [(set (match_operand:SI 0 "register_operand" "=r")
8212 + (not:SI (match_operand:SI 1 "register_operand" "r")))]
8213 + ""
8215 + operands[2] = const0_rtx;
8216 + return "nor\\t%0, %z2, %1";
8218 + [(set_attr "type" "alu")])
8222 +; Logical Operantions
8224 +(define_insn "andsi3"
8225 + [(set (match_operand:SI 0 "register_operand" "=r, r,r")
8226 + (and:SI (match_operand:SI 1 "register_operand" "%r, r,r")
8227 + (match_operand:SI 2 "logical_operand" "rM,J,K")))]
8228 + ""
8229 + "@
8230 + and\\t%0, %1, %z2
8231 + and%i2\\t%0, %1, %2
8232 + andh%i2\\t%0, %1, %U2"
8233 + [(set_attr "type" "alu")])
8235 +(define_insn "iorsi3"
8236 + [(set (match_operand:SI 0 "register_operand" "=r, r,r")
8237 + (ior:SI (match_operand:SI 1 "register_operand" "%r, r,r")
8238 + (match_operand:SI 2 "logical_operand" "rM,J,K")))]
8239 + ""
8240 + "@
8241 + or\\t%0, %1, %z2
8242 + or%i2\\t%0, %1, %2
8243 + orh%i2\\t%0, %1, %U2"
8244 + [(set_attr "type" "alu")])
8246 +(define_insn "*norsi3"
8247 + [(set (match_operand:SI 0 "register_operand" "=r")
8248 + (and:SI (not:SI (match_operand:SI 1 "register_operand" "%r"))
8249 + (not:SI (match_operand:SI 2 "reg_or_0_operand" "rM"))))]
8250 + ""
8251 + "nor\\t%0, %1, %z2"
8252 + [(set_attr "type" "alu")])
8254 +(define_insn "xorsi3"
8255 + [(set (match_operand:SI 0 "register_operand" "=r, r,r")
8256 + (xor:SI (match_operand:SI 1 "register_operand" "%r, r,r")
8257 + (match_operand:SI 2 "logical_operand" "rM,J,K")))]
8258 + ""
8259 + "@
8260 + xor\\t%0, %1, %z2
8261 + xor%i2\\t%0, %1, %2
8262 + xorh%i2\\t%0, %1, %U2"
8263 + [(set_attr "type" "alu")])
8267 +;*****************************************************************************
8269 +;* Shifts
8271 +;*****************************************************************************
8273 +(define_insn "ashlsi3"
8274 + [(set (match_operand:SI 0 "register_operand" "=r,r")
8275 + (ashift:SI (match_operand:SI 1 "register_operand" "r,r")
8276 + (match_operand:SI 2 "shift_operand" "r,L")))]
8277 + ""
8278 + "sll%i2\\t%0, %1, %z2"
8279 + [(set_attr "type" "shift")])
8281 +(define_insn "ashrsi3"
8282 + [(set (match_operand:SI 0 "register_operand" "=r,r")
8283 + (ashiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
8284 + (match_operand:SI 2 "shift_operand" "r,L")))]
8285 + ""
8286 + "sra%i2\\t%0, %1, %z2"
8287 + [(set_attr "type" "shift")])
8289 +(define_insn "lshrsi3"
8290 + [(set (match_operand:SI 0 "register_operand" "=r,r")
8291 + (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
8292 + (match_operand:SI 2 "shift_operand" "r,L")))]
8293 + ""
8294 + "srl%i2\\t%0, %1, %z2"
8295 + [(set_attr "type" "shift")])
8297 +(define_insn "rotlsi3"
8298 + [(set (match_operand:SI 0 "register_operand" "=r,r")
8299 + (rotate:SI (match_operand:SI 1 "register_operand" "r,r")
8300 + (match_operand:SI 2 "shift_operand" "r,L")))]
8301 + ""
8302 + "rol%i2\\t%0, %1, %z2"
8303 + [(set_attr "type" "shift")])
8305 +(define_insn "rotrsi3"
8306 + [(set (match_operand:SI 0 "register_operand" "=r,r")
8307 + (rotatert:SI (match_operand:SI 1 "register_operand" "r,r")
8308 + (match_operand:SI 2 "register_operand" "r,r")))]
8309 + ""
8310 + "ror\\t%0, %1, %2"
8311 + [(set_attr "type" "shift")])
8313 +(define_insn "*shift_mul_constants"
8314 + [(set (match_operand:SI 0 "register_operand" "=r")
8315 + (ashift:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
8316 + (match_operand:SI 2 "const_int_operand" "I"))
8317 + (match_operand:SI 3 "const_int_operand" "I")))]
8318 + "TARGET_HAS_MUL && SMALL_INT (INTVAL (operands[2]) << INTVAL (operands[3]))"
8320 + HOST_WIDE_INT mul = INTVAL (operands[2]) << INTVAL (operands[3]);
8321 + rtx ops[3];
8323 + ops[0] = operands[0];
8324 + ops[1] = operands[1];
8325 + ops[2] = GEN_INT (mul);
8327 + output_asm_insn ("muli\t%0, %1, %2", ops);
8328 + return "";
8330 + [(set_attr "type" "mul")])
8335 +;*****************************************************************************
8337 +;* Prologue, Epilogue and Return
8339 +;*****************************************************************************
8341 +(define_expand "prologue"
8342 + [(const_int 1)]
8343 + ""
8345 + expand_prologue ();
8346 + DONE;
8349 +(define_expand "epilogue"
8350 + [(return)]
8351 + ""
8353 + expand_epilogue (false);
8354 + DONE;
8357 +(define_expand "sibcall_epilogue"
8358 + [(return)]
8359 + ""
8361 + expand_epilogue (true);
8362 + DONE;
8365 +(define_insn "return"
8366 + [(return)]
8367 + "reload_completed && nios2_can_use_return_insn ()"
8368 + "ret\\t"
8371 +(define_insn "return_from_epilogue"
8372 + [(use (match_operand 0 "pmode_register_operand" ""))
8373 + (return)]
8374 + "reload_completed"
8375 + "ret\\t"
8378 +;; Block any insns from being moved before this point, since the
8379 +;; profiling call to mcount can use various registers that aren't
8380 +;; saved or used to pass arguments.
8382 +(define_insn "blockage"
8383 + [(unspec_volatile [(const_int 0)] UNSPEC_BLOCKAGE)]
8384 + ""
8385 + ""
8386 + [(set_attr "type" "unknown")
8387 + (set_attr "length" "0")])
8391 +;*****************************************************************************
8393 +;* Jumps and Calls
8395 +;*****************************************************************************
8397 +(define_insn "indirect_jump"
8398 + [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
8399 + ""
8400 + "jmp\\t%0"
8401 + [(set_attr "type" "control")])
8403 +(define_insn "jump"
8404 + [(set (pc)
8405 + (label_ref (match_operand 0 "" "")))]
8406 + ""
8407 + "br\\t%0"
8408 + [(set_attr "type" "control")])
8411 +(define_insn "indirect_call"
8412 + [(call (mem:QI (match_operand:SI 0 "register_operand" "r"))
8413 + (match_operand 1 "" ""))
8414 + (clobber (reg:SI RA_REGNO))]
8415 + ""
8416 + "callr\\t%0"
8417 + [(set_attr "type" "control")])
8419 +(define_insn "indirect_call_value"
8420 + [(set (match_operand 0 "" "")
8421 + (call (mem:QI (match_operand:SI 1 "register_operand" "r"))
8422 + (match_operand 2 "" "")))
8423 + (clobber (reg:SI RA_REGNO))]
8424 + ""
8425 + "callr\\t%1"
8428 +(define_expand "call"
8429 + [(parallel [(call (match_operand 0 "" "")
8430 + (match_operand 1 "" ""))
8431 + (clobber (reg:SI RA_REGNO))])]
8432 + ""
8433 + "")
8435 +(define_expand "call_value"
8436 + [(parallel [(set (match_operand 0 "" "")
8437 + (call (match_operand 1 "" "")
8438 + (match_operand 2 "" "")))
8439 + (clobber (reg:SI RA_REGNO))])]
8440 + ""
8441 + "")
8443 +(define_insn "*call"
8444 + [(call (mem:QI (match_operand:SI 0 "immediate_operand" "i"))
8445 + (match_operand 1 "" ""))
8446 + (clobber (match_operand:SI 2 "register_operand" "=r"))]
8447 + ""
8448 + "call\\t%0"
8449 + [(set_attr "type" "control")])
8451 +(define_insn "*call_value"
8452 + [(set (match_operand 0 "" "")
8453 + (call (mem:QI (match_operand:SI 1 "immediate_operand" "i"))
8454 + (match_operand 2 "" "")))
8455 + (clobber (match_operand:SI 3 "register_operand" "=r"))]
8456 + ""
8457 + "call\\t%1"
8458 + [(set_attr "type" "control")])
8460 +(define_expand "sibcall"
8461 + [(parallel [(call (match_operand 0 "" "")
8462 + (match_operand 1 "" ""))
8463 + (return)
8464 + (use (match_operand 2 "" ""))])]
8465 + ""
8467 + XEXP (operands[0], 0) = copy_to_mode_reg (SImode, XEXP (operands[0], 0));
8469 + if (operands[2] == NULL_RTX)
8470 + operands[2] = const0_rtx;
8474 +(define_expand "sibcall_value"
8475 + [(parallel [(set (match_operand 0 "" "")
8476 + (call (match_operand 1 "" "")
8477 + (match_operand 2 "" "")))
8478 + (return)
8479 + (use (match_operand 3 "" ""))])]
8480 + ""
8482 + XEXP (operands[1], 0) = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
8484 + if (operands[3] == NULL_RTX)
8485 + operands[3] = const0_rtx;
8489 +(define_insn "sibcall_insn"
8490 + [(call (mem:QI (match_operand:SI 0 "register_operand" "r"))
8491 + (match_operand 1 "" ""))
8492 + (return)
8493 + (use (match_operand 2 "" ""))]
8494 + ""
8495 + "jmp\\t%0"
8498 +(define_insn "sibcall_value_insn"
8499 + [(set (match_operand 0 "register_operand" "")
8500 + (call (mem:QI (match_operand:SI 1 "register_operand" "r"))
8501 + (match_operand 2 "" "")))
8502 + (return)
8503 + (use (match_operand 3 "" ""))]
8504 + ""
8505 + "jmp\\t%1"
8511 +(define_expand "tablejump"
8512 + [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
8513 + (use (label_ref (match_operand 1 "" "")))])]
8514 + ""
8515 + ""
8518 +(define_insn "*tablejump"
8519 + [(set (pc)
8520 + (match_operand:SI 0 "register_operand" "r"))
8521 + (use (label_ref (match_operand 1 "" "")))]
8522 + ""
8523 + "jmp\\t%0"
8524 + [(set_attr "type" "control")])
8528 +;*****************************************************************************
8530 +;* Comparisons
8532 +;*****************************************************************************
8533 +;; Flow here is rather complex (based on MIPS):
8535 +;; 1) The cmp{si,di,sf,df} routine is called. It deposits the
8536 +;; arguments into the branch_cmp array, and the type into
8537 +;; branch_type. No RTL is generated.
8539 +;; 2) The appropriate branch define_expand is called, which then
8540 +;; creates the appropriate RTL for the comparison and branch.
8541 +;; Different CC modes are used, based on what type of branch is
8542 +;; done, so that we can constrain things appropriately. There
8543 +;; are assumptions in the rest of GCC that break if we fold the
8544 +;; operands into the branchs for integer operations, and use cc0
8545 +;; for floating point, so we use the fp status register instead.
8546 +;; If needed, an appropriate temporary is created to hold the
8547 +;; of the integer compare.
8549 +(define_expand "cmpsi"
8550 + [(set (cc0)
8551 + (compare:CC (match_operand:SI 0 "register_operand" "")
8552 + (match_operand:SI 1 "arith_operand" "")))]
8553 + ""
8555 + branch_cmp[0] = operands[0];
8556 + branch_cmp[1] = operands[1];
8557 + branch_type = CMP_SI;
8558 + DONE;
8561 +(define_expand "tstsi"
8562 + [(set (cc0)
8563 + (match_operand:SI 0 "register_operand" ""))]
8564 + ""
8566 + branch_cmp[0] = operands[0];
8567 + branch_cmp[1] = const0_rtx;
8568 + branch_type = CMP_SI;
8569 + DONE;
8573 +;*****************************************************************************
8575 +;* setting a register from a comparison
8577 +;*****************************************************************************
8579 +(define_expand "seq"
8580 + [(set (match_operand:SI 0 "register_operand" "=r")
8581 + (eq:SI (match_dup 1)
8582 + (match_dup 2)))]
8583 + ""
8585 + if (branch_type != CMP_SI)
8586 + FAIL;
8588 + /* set up operands from compare. */
8589 + operands[1] = branch_cmp[0];
8590 + operands[2] = branch_cmp[1];
8592 + gen_int_relational (EQ, operands[0], operands[1], operands[2], NULL_RTX);
8593 + DONE;
8597 +(define_insn "*seq"
8598 + [(set (match_operand:SI 0 "register_operand" "=r")
8599 + (eq:SI (match_operand:SI 1 "reg_or_0_operand" "%rM")
8600 + (match_operand:SI 2 "arith_operand" "rI")))]
8601 + ""
8602 + "cmpeq%i2\\t%0, %z1, %z2"
8603 + [(set_attr "type" "alu")])
8606 +(define_expand "sne"
8607 + [(set (match_operand:SI 0 "register_operand" "=r")
8608 + (ne:SI (match_dup 1)
8609 + (match_dup 2)))]
8610 + ""
8612 + if (branch_type != CMP_SI)
8613 + FAIL;
8615 + /* set up operands from compare. */
8616 + operands[1] = branch_cmp[0];
8617 + operands[2] = branch_cmp[1];
8619 + gen_int_relational (NE, operands[0], operands[1], operands[2], NULL_RTX);
8620 + DONE;
8624 +(define_insn "*sne"
8625 + [(set (match_operand:SI 0 "register_operand" "=r")
8626 + (ne:SI (match_operand:SI 1 "reg_or_0_operand" "%rM")
8627 + (match_operand:SI 2 "arith_operand" "rI")))]
8628 + ""
8629 + "cmpne%i2\\t%0, %z1, %z2"
8630 + [(set_attr "type" "alu")])
8633 +(define_expand "sgt"
8634 + [(set (match_operand:SI 0 "register_operand" "=r")
8635 + (gt:SI (match_dup 1)
8636 + (match_dup 2)))]
8637 + ""
8639 + if (branch_type != CMP_SI)
8640 + FAIL;
8642 + /* set up operands from compare. */
8643 + operands[1] = branch_cmp[0];
8644 + operands[2] = branch_cmp[1];
8646 + gen_int_relational (GT, operands[0], operands[1], operands[2], NULL_RTX);
8647 + DONE;
8651 +(define_insn "*sgt"
8652 + [(set (match_operand:SI 0 "register_operand" "=r")
8653 + (gt:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
8654 + (match_operand:SI 2 "reg_or_0_operand" "rM")))]
8655 + ""
8656 + "cmplt\\t%0, %z2, %z1"
8657 + [(set_attr "type" "alu")])
8660 +(define_expand "sge"
8661 + [(set (match_operand:SI 0 "register_operand" "=r")
8662 + (ge:SI (match_dup 1)
8663 + (match_dup 2)))]
8664 + ""
8666 + if (branch_type != CMP_SI)
8667 + FAIL;
8669 + /* set up operands from compare. */
8670 + operands[1] = branch_cmp[0];
8671 + operands[2] = branch_cmp[1];
8673 + gen_int_relational (GE, operands[0], operands[1], operands[2], NULL_RTX);
8674 + DONE;
8678 +(define_insn "*sge"
8679 + [(set (match_operand:SI 0 "register_operand" "=r")
8680 + (ge:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
8681 + (match_operand:SI 2 "arith_operand" "rI")))]
8682 + ""
8683 + "cmpge%i2\\t%0, %z1, %z2"
8684 + [(set_attr "type" "alu")])
8686 +(define_expand "sle"
8687 + [(set (match_operand:SI 0 "register_operand" "=r")
8688 + (le:SI (match_dup 1)
8689 + (match_dup 2)))]
8690 + ""
8692 + if (branch_type != CMP_SI)
8693 + FAIL;
8695 + /* set up operands from compare. */
8696 + operands[1] = branch_cmp[0];
8697 + operands[2] = branch_cmp[1];
8699 + gen_int_relational (LE, operands[0], operands[1], operands[2], NULL_RTX);
8700 + DONE;
8704 +(define_insn "*sle"
8705 + [(set (match_operand:SI 0 "register_operand" "=r")
8706 + (le:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
8707 + (match_operand:SI 2 "reg_or_0_operand" "rM")))]
8708 + ""
8709 + "cmpge\\t%0, %z2, %z1"
8710 + [(set_attr "type" "alu")])
8713 +(define_expand "slt"
8714 + [(set (match_operand:SI 0 "register_operand" "=r")
8715 + (lt:SI (match_dup 1)
8716 + (match_dup 2)))]
8717 + ""
8719 + if (branch_type != CMP_SI)
8720 + FAIL;
8722 + /* set up operands from compare. */
8723 + operands[1] = branch_cmp[0];
8724 + operands[2] = branch_cmp[1];
8726 + gen_int_relational (LT, operands[0], operands[1], operands[2], NULL_RTX);
8727 + DONE;
8731 +(define_insn "*slt"
8732 + [(set (match_operand:SI 0 "register_operand" "=r")
8733 + (lt:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
8734 + (match_operand:SI 2 "arith_operand" "rI")))]
8735 + ""
8736 + "cmplt%i2\\t%0, %z1, %z2"
8737 + [(set_attr "type" "alu")])
8740 +(define_expand "sgtu"
8741 + [(set (match_operand:SI 0 "register_operand" "=r")
8742 + (gtu:SI (match_dup 1)
8743 + (match_dup 2)))]
8744 + ""
8746 + if (branch_type != CMP_SI)
8747 + FAIL;
8749 + /* set up operands from compare. */
8750 + operands[1] = branch_cmp[0];
8751 + operands[2] = branch_cmp[1];
8753 + gen_int_relational (GTU, operands[0], operands[1], operands[2], NULL_RTX);
8754 + DONE;
8758 +(define_insn "*sgtu"
8759 + [(set (match_operand:SI 0 "register_operand" "=r")
8760 + (gtu:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
8761 + (match_operand:SI 2 "reg_or_0_operand" "rM")))]
8762 + ""
8763 + "cmpltu\\t%0, %z2, %z1"
8764 + [(set_attr "type" "alu")])
8767 +(define_expand "sgeu"
8768 + [(set (match_operand:SI 0 "register_operand" "=r")
8769 + (geu:SI (match_dup 1)
8770 + (match_dup 2)))]
8771 + ""
8773 + if (branch_type != CMP_SI)
8774 + FAIL;
8776 + /* set up operands from compare. */
8777 + operands[1] = branch_cmp[0];
8778 + operands[2] = branch_cmp[1];
8780 + gen_int_relational (GEU, operands[0], operands[1], operands[2], NULL_RTX);
8781 + DONE;
8785 +(define_insn "*sgeu"
8786 + [(set (match_operand:SI 0 "register_operand" "=r")
8787 + (geu:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
8788 + (match_operand:SI 2 "uns_arith_operand" "rJ")))]
8789 + ""
8790 + "cmpgeu%i2\\t%0, %z1, %z2"
8791 + [(set_attr "type" "alu")])
8793 +(define_expand "sleu"
8794 + [(set (match_operand:SI 0 "register_operand" "=r")
8795 + (leu:SI (match_dup 1)
8796 + (match_dup 2)))]
8797 + ""
8799 + if (branch_type != CMP_SI)
8800 + FAIL;
8802 + /* set up operands from compare. */
8803 + operands[1] = branch_cmp[0];
8804 + operands[2] = branch_cmp[1];
8806 + gen_int_relational (LEU, operands[0], operands[1], operands[2], NULL_RTX);
8807 + DONE;
8811 +(define_insn "*sleu"
8812 + [(set (match_operand:SI 0 "register_operand" "=r")
8813 + (leu:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
8814 + (match_operand:SI 2 "reg_or_0_operand" "rM")))]
8815 + ""
8816 + "cmpgeu\\t%0, %z2, %z1"
8817 + [(set_attr "type" "alu")])
8820 +(define_expand "sltu"
8821 + [(set (match_operand:SI 0 "register_operand" "=r")
8822 + (ltu:SI (match_dup 1)
8823 + (match_dup 2)))]
8824 + ""
8826 + if (branch_type != CMP_SI)
8827 + FAIL;
8829 + /* set up operands from compare. */
8830 + operands[1] = branch_cmp[0];
8831 + operands[2] = branch_cmp[1];
8833 + gen_int_relational (LTU, operands[0], operands[1], operands[2], NULL_RTX);
8834 + DONE;
8838 +(define_insn "*sltu"
8839 + [(set (match_operand:SI 0 "register_operand" "=r")
8840 + (ltu:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
8841 + (match_operand:SI 2 "uns_arith_operand" "rJ")))]
8842 + ""
8843 + "cmpltu%i2\\t%0, %z1, %z2"
8844 + [(set_attr "type" "alu")])
8849 +;*****************************************************************************
8851 +;* branches
8853 +;*****************************************************************************
8855 +(define_insn "*cbranch"
8856 + [(set (pc)
8857 + (if_then_else
8858 + (match_operator:SI 0 "comparison_operator"
8859 + [(match_operand:SI 2 "reg_or_0_operand" "rM")
8860 + (match_operand:SI 3 "reg_or_0_operand" "rM")])
8861 + (label_ref (match_operand 1 "" ""))
8862 + (pc)))]
8863 + ""
8864 + "b%0\\t%z2, %z3, %l1"
8865 + [(set_attr "type" "control")])
8868 +(define_expand "beq"
8869 + [(set (pc)
8870 + (if_then_else (eq:CC (cc0)
8871 + (const_int 0))
8872 + (label_ref (match_operand 0 "" ""))
8873 + (pc)))]
8874 + ""
8876 + gen_int_relational (EQ, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
8877 + DONE;
8881 +(define_expand "bne"
8882 + [(set (pc)
8883 + (if_then_else (ne:CC (cc0)
8884 + (const_int 0))
8885 + (label_ref (match_operand 0 "" ""))
8886 + (pc)))]
8887 + ""
8889 + gen_int_relational (NE, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
8890 + DONE;
8894 +(define_expand "bgt"
8895 + [(set (pc)
8896 + (if_then_else (gt:CC (cc0)
8897 + (const_int 0))
8898 + (label_ref (match_operand 0 "" ""))
8899 + (pc)))]
8900 + ""
8902 + gen_int_relational (GT, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
8903 + DONE;
8906 +(define_expand "bge"
8907 + [(set (pc)
8908 + (if_then_else (ge:CC (cc0)
8909 + (const_int 0))
8910 + (label_ref (match_operand 0 "" ""))
8911 + (pc)))]
8912 + ""
8914 + gen_int_relational (GE, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
8915 + DONE;
8918 +(define_expand "ble"
8919 + [(set (pc)
8920 + (if_then_else (le:CC (cc0)
8921 + (const_int 0))
8922 + (label_ref (match_operand 0 "" ""))
8923 + (pc)))]
8924 + ""
8926 + gen_int_relational (LE, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
8927 + DONE;
8930 +(define_expand "blt"
8931 + [(set (pc)
8932 + (if_then_else (lt:CC (cc0)
8933 + (const_int 0))
8934 + (label_ref (match_operand 0 "" ""))
8935 + (pc)))]
8936 + ""
8938 + gen_int_relational (LT, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
8939 + DONE;
8943 +(define_expand "bgtu"
8944 + [(set (pc)
8945 + (if_then_else (gtu:CC (cc0)
8946 + (const_int 0))
8947 + (label_ref (match_operand 0 "" ""))
8948 + (pc)))]
8949 + ""
8951 + gen_int_relational (GTU, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
8952 + DONE;
8955 +(define_expand "bgeu"
8956 + [(set (pc)
8957 + (if_then_else (geu:CC (cc0)
8958 + (const_int 0))
8959 + (label_ref (match_operand 0 "" ""))
8960 + (pc)))]
8961 + ""
8963 + gen_int_relational (GEU, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
8964 + DONE;
8967 +(define_expand "bleu"
8968 + [(set (pc)
8969 + (if_then_else (leu:CC (cc0)
8970 + (const_int 0))
8971 + (label_ref (match_operand 0 "" ""))
8972 + (pc)))]
8973 + ""
8975 + gen_int_relational (LEU, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
8976 + DONE;
8979 +(define_expand "bltu"
8980 + [(set (pc)
8981 + (if_then_else (ltu:CC (cc0)
8982 + (const_int 0))
8983 + (label_ref (match_operand 0 "" ""))
8984 + (pc)))]
8985 + ""
8987 + gen_int_relational (LTU, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
8988 + DONE;
8992 +;*****************************************************************************
8994 +;* String and Block Operations
8996 +;*****************************************************************************
8998 +; ??? This is all really a hack to get Dhrystone to work as fast as possible
8999 +; things to be fixed:
9000 +; * let the compiler core handle all of this, for that to work the extra
9001 +; aliasing needs to be addressed.
9002 +; * we use three temporary registers for loading and storing to ensure no
9003 +; ld use stalls, this is excessive, because after the first ld/st only
9004 +; two are needed. Only two would be needed all the way through if
9005 +; we could schedule with other code. Consider:
9006 +; 1 ld $1, 0($src)
9007 +; 2 ld $2, 4($src)
9008 +; 3 ld $3, 8($src)
9009 +; 4 st $1, 0($dest)
9010 +; 5 ld $1, 12($src)
9011 +; 6 st $2, 4($src)
9012 +; 7 etc.
9013 +; The first store has to wait until 4. If it does not there will be one
9014 +; cycle of stalling. However, if any other instruction could be placed
9015 +; between 1 and 4, $3 would not be needed.
9016 +; * In small we probably don't want to ever do this ourself because there
9017 +; is no ld use stall.
9019 +(define_expand "movstrsi"
9020 + [(parallel [(set (match_operand:BLK 0 "general_operand" "")
9021 + (match_operand:BLK 1 "general_operand" ""))
9022 + (use (match_operand:SI 2 "const_int_operand" ""))
9023 + (use (match_operand:SI 3 "const_int_operand" ""))
9024 + (clobber (match_scratch:SI 4 "=&r"))
9025 + (clobber (match_scratch:SI 5 "=&r"))
9026 + (clobber (match_scratch:SI 6 "=&r"))])]
9027 + "TARGET_INLINE_MEMCPY"
9029 + rtx ld_addr_reg, st_addr_reg;
9031 + /* If the predicate for op2 fails in expr.c:emit_block_move_via_movstr
9032 + it trys to copy to a register, but does not re-try the predicate.
9033 + ??? Intead of fixing expr.c, I fix it here. */
9034 + if (!const_int_operand (operands[2], SImode))
9035 + FAIL;
9037 + /* ??? there are some magic numbers which need to be sorted out here.
9038 + the basis for them is not increasing code size hugely or going
9039 + out of range of offset addressing */
9040 + if (INTVAL (operands[3]) < 4)
9041 + FAIL;
9042 + if (!optimize
9043 + || (optimize_size && INTVAL (operands[2]) > 12)
9044 + || (optimize < 3 && INTVAL (operands[2]) > 100)
9045 + || INTVAL (operands[2]) > 200)
9046 + FAIL;
9048 + st_addr_reg
9049 + = replace_equiv_address (operands[0],
9050 + copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
9051 + ld_addr_reg
9052 + = replace_equiv_address (operands[1],
9053 + copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
9054 + emit_insn (gen_movstrsi_internal (st_addr_reg, ld_addr_reg,
9055 + operands[2], operands[3]));
9057 + DONE;
9061 +(define_insn "movstrsi_internal"
9062 + [(set (match_operand:BLK 0 "memory_operand" "=o")
9063 + (match_operand:BLK 1 "memory_operand" "o"))
9064 + (use (match_operand:SI 2 "const_int_operand" "i"))
9065 + (use (match_operand:SI 3 "const_int_operand" "i"))
9066 + (clobber (match_scratch:SI 4 "=&r"))
9067 + (clobber (match_scratch:SI 5 "=&r"))
9068 + (clobber (match_scratch:SI 6 "=&r"))]
9069 + "TARGET_INLINE_MEMCPY"
9071 + int ld_offset = INTVAL (operands[2]);
9072 + int ld_len = INTVAL (operands[2]);
9073 + int ld_reg = 0;
9074 + rtx ld_addr_reg = XEXP (operands[1], 0);
9075 + int st_offset = INTVAL (operands[2]);
9076 + int st_len = INTVAL (operands[2]);
9077 + int st_reg = 0;
9078 + rtx st_addr_reg = XEXP (operands[0], 0);
9079 + int delay_count = 0;
9081 + /* ops[0] is the address used by the insn
9082 + ops[1] is the register being loaded or stored */
9083 + rtx ops[2];
9085 + if (INTVAL (operands[3]) < 4)
9086 + abort ();
9088 + while (ld_offset >= 4)
9090 + /* if the load use delay has been met, I can start
9091 + storing */
9092 + if (delay_count >= 3)
9094 + ops[0] = gen_rtx (MEM, SImode,
9095 + plus_constant (st_addr_reg, st_len - st_offset));
9096 + ops[1] = operands[st_reg + 4];
9097 + output_asm_insn ("stw\t%1, %0", ops);
9099 + st_reg = (st_reg + 1) % 3;
9100 + st_offset -= 4;
9103 + ops[0] = gen_rtx (MEM, SImode,
9104 + plus_constant (ld_addr_reg, ld_len - ld_offset));
9105 + ops[1] = operands[ld_reg + 4];
9106 + output_asm_insn ("ldw\t%1, %0", ops);
9108 + ld_reg = (ld_reg + 1) % 3;
9109 + ld_offset -= 4;
9110 + delay_count++;
9113 + if (ld_offset >= 2)
9115 + /* if the load use delay has been met, I can start
9116 + storing */
9117 + if (delay_count >= 3)
9119 + ops[0] = gen_rtx (MEM, SImode,
9120 + plus_constant (st_addr_reg, st_len - st_offset));
9121 + ops[1] = operands[st_reg + 4];
9122 + output_asm_insn ("stw\t%1, %0", ops);
9124 + st_reg = (st_reg + 1) % 3;
9125 + st_offset -= 4;
9128 + ops[0] = gen_rtx (MEM, HImode,
9129 + plus_constant (ld_addr_reg, ld_len - ld_offset));
9130 + ops[1] = operands[ld_reg + 4];
9131 + output_asm_insn ("ldh\t%1, %0", ops);
9133 + ld_reg = (ld_reg + 1) % 3;
9134 + ld_offset -= 2;
9135 + delay_count++;
9138 + if (ld_offset >= 1)
9140 + /* if the load use delay has been met, I can start
9141 + storing */
9142 + if (delay_count >= 3)
9144 + ops[0] = gen_rtx (MEM, SImode,
9145 + plus_constant (st_addr_reg, st_len - st_offset));
9146 + ops[1] = operands[st_reg + 4];
9147 + output_asm_insn ("stw\t%1, %0", ops);
9149 + st_reg = (st_reg + 1) % 3;
9150 + st_offset -= 4;
9153 + ops[0] = gen_rtx (MEM, QImode,
9154 + plus_constant (ld_addr_reg, ld_len - ld_offset));
9155 + ops[1] = operands[ld_reg + 4];
9156 + output_asm_insn ("ldb\t%1, %0", ops);
9158 + ld_reg = (ld_reg + 1) % 3;
9159 + ld_offset -= 1;
9160 + delay_count++;
9163 + while (st_offset >= 4)
9165 + ops[0] = gen_rtx (MEM, SImode,
9166 + plus_constant (st_addr_reg, st_len - st_offset));
9167 + ops[1] = operands[st_reg + 4];
9168 + output_asm_insn ("stw\t%1, %0", ops);
9170 + st_reg = (st_reg + 1) % 3;
9171 + st_offset -= 4;
9174 + while (st_offset >= 2)
9176 + ops[0] = gen_rtx (MEM, HImode,
9177 + plus_constant (st_addr_reg, st_len - st_offset));
9178 + ops[1] = operands[st_reg + 4];
9179 + output_asm_insn ("sth\t%1, %0", ops);
9181 + st_reg = (st_reg + 1) % 3;
9182 + st_offset -= 2;
9185 + while (st_offset >= 1)
9187 + ops[0] = gen_rtx (MEM, QImode,
9188 + plus_constant (st_addr_reg, st_len - st_offset));
9189 + ops[1] = operands[st_reg + 4];
9190 + output_asm_insn ("stb\t%1, %0", ops);
9192 + st_reg = (st_reg + 1) % 3;
9193 + st_offset -= 1;
9196 + return "";
9198 +; ??? lengths are not being used yet, but I will probably forget
9199 +; to update this once I am using lengths, so set it to something
9200 +; definetely big enough to cover it. 400 allows for 200 bytes
9201 +; of motion.
9202 + [(set_attr "length" "400")])
9206 +;*****************************************************************************
9208 +;* Custom instructions
9210 +;*****************************************************************************
9212 +(define_constants [
9213 + (CUSTOM_N 100)
9214 + (CUSTOM_NI 101)
9215 + (CUSTOM_NF 102)
9216 + (CUSTOM_NP 103)
9217 + (CUSTOM_NII 104)
9218 + (CUSTOM_NIF 105)
9219 + (CUSTOM_NIP 106)
9220 + (CUSTOM_NFI 107)
9221 + (CUSTOM_NFF 108)
9222 + (CUSTOM_NFP 109)
9223 + (CUSTOM_NPI 110)
9224 + (CUSTOM_NPF 111)
9225 + (CUSTOM_NPP 112)
9226 + (CUSTOM_IN 113)
9227 + (CUSTOM_INI 114)
9228 + (CUSTOM_INF 115)
9229 + (CUSTOM_INP 116)
9230 + (CUSTOM_INII 117)
9231 + (CUSTOM_INIF 118)
9232 + (CUSTOM_INIP 119)
9233 + (CUSTOM_INFI 120)
9234 + (CUSTOM_INFF 121)
9235 + (CUSTOM_INFP 122)
9236 + (CUSTOM_INPI 123)
9237 + (CUSTOM_INPF 124)
9238 + (CUSTOM_INPP 125)
9239 + (CUSTOM_FN 126)
9240 + (CUSTOM_FNI 127)
9241 + (CUSTOM_FNF 128)
9242 + (CUSTOM_FNP 129)
9243 + (CUSTOM_FNII 130)
9244 + (CUSTOM_FNIF 131)
9245 + (CUSTOM_FNIP 132)
9246 + (CUSTOM_FNFI 133)
9247 + (CUSTOM_FNFF 134)
9248 + (CUSTOM_FNFP 135)
9249 + (CUSTOM_FNPI 136)
9250 + (CUSTOM_FNPF 137)
9251 + (CUSTOM_FNPP 138)
9252 + (CUSTOM_PN 139)
9253 + (CUSTOM_PNI 140)
9254 + (CUSTOM_PNF 141)
9255 + (CUSTOM_PNP 142)
9256 + (CUSTOM_PNII 143)
9257 + (CUSTOM_PNIF 144)
9258 + (CUSTOM_PNIP 145)
9259 + (CUSTOM_PNFI 146)
9260 + (CUSTOM_PNFF 147)
9261 + (CUSTOM_PNFP 148)
9262 + (CUSTOM_PNPI 149)
9263 + (CUSTOM_PNPF 150)
9264 + (CUSTOM_PNPP 151)
9268 +(define_insn "custom_n"
9269 + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")] CUSTOM_N)]
9270 + ""
9271 + "custom\\t%0, zero, zero, zero"
9272 + [(set_attr "type" "custom")])
9274 +(define_insn "custom_ni"
9275 + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
9276 + (match_operand:SI 1 "register_operand" "r")] CUSTOM_NI)]
9277 + ""
9278 + "custom\\t%0, zero, %1, zero"
9279 + [(set_attr "type" "custom")])
9281 +(define_insn "custom_nf"
9282 + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
9283 + (match_operand:SF 1 "register_operand" "r")] CUSTOM_NF)]
9284 + ""
9285 + "custom\\t%0, zero, %1, zero"
9286 + [(set_attr "type" "custom")])
9288 +(define_insn "custom_np"
9289 + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
9290 + (match_operand:SI 1 "register_operand" "r")] CUSTOM_NP)]
9291 + ""
9292 + "custom\\t%0, zero, %1, zero"
9293 + [(set_attr "type" "custom")])
9295 +(define_insn "custom_nii"
9296 + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
9297 + (match_operand:SI 1 "register_operand" "r")
9298 + (match_operand:SI 2 "register_operand" "r")] CUSTOM_NII)]
9299 + ""
9300 + "custom\\t%0, zero, %1, %2"
9301 + [(set_attr "type" "custom")])
9303 +(define_insn "custom_nif"
9304 + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
9305 + (match_operand:SI 1 "register_operand" "r")
9306 + (match_operand:SF 2 "register_operand" "r")] CUSTOM_NIF)]
9307 + ""
9308 + "custom\\t%0, zero, %1, %2"
9309 + [(set_attr "type" "custom")])
9311 +(define_insn "custom_nip"
9312 + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
9313 + (match_operand:SI 1 "register_operand" "r")
9314 + (match_operand:SI 2 "register_operand" "r")] CUSTOM_NIP)]
9315 + ""
9316 + "custom\\t%0, zero, %1, %2"
9317 + [(set_attr "type" "custom")])
9319 +(define_insn "custom_nfi"
9320 + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
9321 + (match_operand:SF 1 "register_operand" "r")
9322 + (match_operand:SI 2 "register_operand" "r")] CUSTOM_NFI)]
9323 + ""
9324 + "custom\\t%0, zero, %1, %2"
9325 + [(set_attr "type" "custom")])
9327 +(define_insn "custom_nff"
9328 + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
9329 + (match_operand:SF 1 "register_operand" "r")
9330 + (match_operand:SF 2 "register_operand" "r")] CUSTOM_NFF)]
9331 + ""
9332 + "custom\\t%0, zero, %1, %2"
9333 + [(set_attr "type" "custom")])
9335 +(define_insn "custom_nfp"
9336 + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
9337 + (match_operand:SF 1 "register_operand" "r")
9338 + (match_operand:SI 2 "register_operand" "r")] CUSTOM_NFP)]
9339 + ""
9340 + "custom\\t%0, zero, %1, %2"
9341 + [(set_attr "type" "custom")])
9343 +(define_insn "custom_npi"
9344 + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
9345 + (match_operand:SI 1 "register_operand" "r")
9346 + (match_operand:SI 2 "register_operand" "r")] CUSTOM_NPI)]
9347 + ""
9348 + "custom\\t%0, zero, %1, %2"
9349 + [(set_attr "type" "custom")])
9351 +(define_insn "custom_npf"
9352 + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
9353 + (match_operand:SI 1 "register_operand" "r")
9354 + (match_operand:SF 2 "register_operand" "r")] CUSTOM_NPF)]
9355 + ""
9356 + "custom\\t%0, zero, %1, %2"
9357 + [(set_attr "type" "custom")])
9359 +(define_insn "custom_npp"
9360 + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
9361 + (match_operand:SI 1 "register_operand" "r")
9362 + (match_operand:SI 2 "register_operand" "r")] CUSTOM_NPP)]
9363 + ""
9364 + "custom\\t%0, zero, %1, %2"
9365 + [(set_attr "type" "custom")])
9369 +(define_insn "custom_in"
9370 + [(set (match_operand:SI 0 "register_operand" "=r")
9371 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")] CUSTOM_IN))]
9372 + ""
9373 + "custom\\t%1, %0, zero, zero"
9374 + [(set_attr "type" "custom")])
9376 +(define_insn "custom_ini"
9377 + [(set (match_operand:SI 0 "register_operand" "=r")
9378 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
9379 + (match_operand:SI 2 "register_operand" "r")] CUSTOM_INI))]
9380 + ""
9381 + "custom\\t%1, %0, %2, zero"
9382 + [(set_attr "type" "custom")])
9384 +(define_insn "custom_inf"
9385 + [(set (match_operand:SI 0 "register_operand" "=r")
9386 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
9387 + (match_operand:SF 2 "register_operand" "r")] CUSTOM_INF))]
9388 + ""
9389 + "custom\\t%1, %0, %2, zero"
9390 + [(set_attr "type" "custom")])
9392 +(define_insn "custom_inp"
9393 + [(set (match_operand:SI 0 "register_operand" "=r")
9394 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
9395 + (match_operand:SI 2 "register_operand" "r")] CUSTOM_INP))]
9396 + ""
9397 + "custom\\t%1, %0, %2, zero"
9398 + [(set_attr "type" "custom")])
9400 +(define_insn "custom_inii"
9401 + [(set (match_operand:SI 0 "register_operand" "=r")
9402 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
9403 + (match_operand:SI 2 "register_operand" "r")
9404 + (match_operand:SI 3 "register_operand" "r")] CUSTOM_INII))]
9405 + ""
9406 + "custom\\t%1, %0, %2, %3"
9407 + [(set_attr "type" "custom")])
9409 +(define_insn "custom_inif"
9410 + [(set (match_operand:SI 0 "register_operand" "=r")
9411 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
9412 + (match_operand:SI 2 "register_operand" "r")
9413 + (match_operand:SF 3 "register_operand" "r")] CUSTOM_INIF))]
9414 + ""
9415 + "custom\\t%1, %0, %2, %3"
9416 + [(set_attr "type" "custom")])
9418 +(define_insn "custom_inip"
9419 + [(set (match_operand:SI 0 "register_operand" "=r")
9420 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
9421 + (match_operand:SI 2 "register_operand" "r")
9422 + (match_operand:SI 3 "register_operand" "r")] CUSTOM_INIP))]
9423 + ""
9424 + "custom\\t%1, %0, %2, %3"
9425 + [(set_attr "type" "custom")])
9427 +(define_insn "custom_infi"
9428 + [(set (match_operand:SI 0 "register_operand" "=r")
9429 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
9430 + (match_operand:SF 2 "register_operand" "r")
9431 + (match_operand:SI 3 "register_operand" "r")] CUSTOM_INFI))]
9432 + ""
9433 + "custom\\t%1, %0, %2, %3"
9434 + [(set_attr "type" "custom")])
9436 +(define_insn "custom_inff"
9437 + [(set (match_operand:SI 0 "register_operand" "=r")
9438 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
9439 + (match_operand:SF 2 "register_operand" "r")
9440 + (match_operand:SF 3 "register_operand" "r")] CUSTOM_INFF))]
9441 + ""
9442 + "custom\\t%1, %0, %2, %3"
9443 + [(set_attr "type" "custom")])
9445 +(define_insn "custom_infp"
9446 + [(set (match_operand:SI 0 "register_operand" "=r")
9447 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
9448 + (match_operand:SF 2 "register_operand" "r")
9449 + (match_operand:SI 3 "register_operand" "r")] CUSTOM_INFP))]
9450 + ""
9451 + "custom\\t%1, %0, %2, %3"
9452 + [(set_attr "type" "custom")])
9454 +(define_insn "custom_inpi"
9455 + [(set (match_operand:SI 0 "register_operand" "=r")
9456 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
9457 + (match_operand:SI 2 "register_operand" "r")
9458 + (match_operand:SI 3 "register_operand" "r")] CUSTOM_INPI))]
9459 + ""
9460 + "custom\\t%1, %0, %2, %3"
9461 + [(set_attr "type" "custom")])
9463 +(define_insn "custom_inpf"
9464 + [(set (match_operand:SI 0 "register_operand" "=r")
9465 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
9466 + (match_operand:SI 2 "register_operand" "r")
9467 + (match_operand:SF 3 "register_operand" "r")] CUSTOM_INPF))]
9468 + ""
9469 + "custom\\t%1, %0, %2, %3"
9470 + [(set_attr "type" "custom")])
9472 +(define_insn "custom_inpp"
9473 + [(set (match_operand:SI 0 "register_operand" "=r")
9474 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
9475 + (match_operand:SI 2 "register_operand" "r")
9476 + (match_operand:SI 3 "register_operand" "r")] CUSTOM_INPP))]
9477 + ""
9478 + "custom\\t%1, %0, %2, %3"
9479 + [(set_attr "type" "custom")])
9485 +(define_insn "custom_fn"
9486 + [(set (match_operand:SF 0 "register_operand" "=r")
9487 + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")] CUSTOM_FN))]
9488 + ""
9489 + "custom\\t%1, %0, zero, zero"
9490 + [(set_attr "type" "custom")])
9492 +(define_insn "custom_fni"
9493 + [(set (match_operand:SF 0 "register_operand" "=r")
9494 + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
9495 + (match_operand:SI 2 "register_operand" "r")] CUSTOM_FNI))]
9496 + ""
9497 + "custom\\t%1, %0, %2, zero"
9498 + [(set_attr "type" "custom")])
9500 +(define_insn "custom_fnf"
9501 + [(set (match_operand:SF 0 "register_operand" "=r")
9502 + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
9503 + (match_operand:SF 2 "register_operand" "r")] CUSTOM_FNF))]
9504 + ""
9505 + "custom\\t%1, %0, %2, zero"
9506 + [(set_attr "type" "custom")])
9508 +(define_insn "custom_fnp"
9509 + [(set (match_operand:SF 0 "register_operand" "=r")
9510 + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
9511 + (match_operand:SI 2 "register_operand" "r")] CUSTOM_FNP))]
9512 + ""
9513 + "custom\\t%1, %0, %2, zero"
9514 + [(set_attr "type" "custom")])
9516 +(define_insn "custom_fnii"
9517 + [(set (match_operand:SF 0 "register_operand" "=r")
9518 + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
9519 + (match_operand:SI 2 "register_operand" "r")
9520 + (match_operand:SI 3 "register_operand" "r")] CUSTOM_FNII))]
9521 + ""
9522 + "custom\\t%1, %0, %2, %3"
9523 + [(set_attr "type" "custom")])
9525 +(define_insn "custom_fnif"
9526 + [(set (match_operand:SF 0 "register_operand" "=r")
9527 + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
9528 + (match_operand:SI 2 "register_operand" "r")
9529 + (match_operand:SF 3 "register_operand" "r")] CUSTOM_FNIF))]
9530 + ""
9531 + "custom\\t%1, %0, %2, %3"
9532 + [(set_attr "type" "custom")])
9534 +(define_insn "custom_fnip"
9535 + [(set (match_operand:SF 0 "register_operand" "=r")
9536 + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
9537 + (match_operand:SI 2 "register_operand" "r")
9538 + (match_operand:SI 3 "register_operand" "r")] CUSTOM_FNIP))]
9539 + ""
9540 + "custom\\t%1, %0, %2, %3"
9541 + [(set_attr "type" "custom")])
9543 +(define_insn "custom_fnfi"
9544 + [(set (match_operand:SF 0 "register_operand" "=r")
9545 + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
9546 + (match_operand:SF 2 "register_operand" "r")
9547 + (match_operand:SI 3 "register_operand" "r")] CUSTOM_FNFI))]
9548 + ""
9549 + "custom\\t%1, %0, %2, %3"
9550 + [(set_attr "type" "custom")])
9552 +(define_insn "custom_fnff"
9553 + [(set (match_operand:SF 0 "register_operand" "=r")
9554 + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
9555 + (match_operand:SF 2 "register_operand" "r")
9556 + (match_operand:SF 3 "register_operand" "r")] CUSTOM_FNFF))]
9557 + ""
9558 + "custom\\t%1, %0, %2, %3"
9559 + [(set_attr "type" "custom")])
9561 +(define_insn "custom_fnfp"
9562 + [(set (match_operand:SF 0 "register_operand" "=r")
9563 + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
9564 + (match_operand:SF 2 "register_operand" "r")
9565 + (match_operand:SI 3 "register_operand" "r")] CUSTOM_FNFP))]
9566 + ""
9567 + "custom\\t%1, %0, %2, %3"
9568 + [(set_attr "type" "custom")])
9570 +(define_insn "custom_fnpi"
9571 + [(set (match_operand:SF 0 "register_operand" "=r")
9572 + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
9573 + (match_operand:SI 2 "register_operand" "r")
9574 + (match_operand:SI 3 "register_operand" "r")] CUSTOM_FNPI))]
9575 + ""
9576 + "custom\\t%1, %0, %2, %3"
9577 + [(set_attr "type" "custom")])
9579 +(define_insn "custom_fnpf"
9580 + [(set (match_operand:SF 0 "register_operand" "=r")
9581 + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
9582 + (match_operand:SI 2 "register_operand" "r")
9583 + (match_operand:SF 3 "register_operand" "r")] CUSTOM_FNPF))]
9584 + ""
9585 + "custom\\t%1, %0, %2, %3"
9586 + [(set_attr "type" "custom")])
9588 +(define_insn "custom_fnpp"
9589 + [(set (match_operand:SF 0 "register_operand" "=r")
9590 + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
9591 + (match_operand:SI 2 "register_operand" "r")
9592 + (match_operand:SI 3 "register_operand" "r")] CUSTOM_FNPP))]
9593 + ""
9594 + "custom\\t%1, %0, %2, %3"
9595 + [(set_attr "type" "custom")])
9599 +(define_insn "custom_pn"
9600 + [(set (match_operand:SI 0 "register_operand" "=r")
9601 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")] CUSTOM_PN))]
9602 + ""
9603 + "custom\\t%1, %0, zero, zero"
9604 + [(set_attr "type" "custom")])
9606 +(define_insn "custom_pni"
9607 + [(set (match_operand:SI 0 "register_operand" "=r")
9608 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
9609 + (match_operand:SI 2 "register_operand" "r")] CUSTOM_PNI))]
9610 + ""
9611 + "custom\\t%1, %0, %2, zero"
9612 + [(set_attr "type" "custom")])
9614 +(define_insn "custom_pnf"
9615 + [(set (match_operand:SI 0 "register_operand" "=r")
9616 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
9617 + (match_operand:SF 2 "register_operand" "r")] CUSTOM_PNF))]
9618 + ""
9619 + "custom\\t%1, %0, %2, zero"
9620 + [(set_attr "type" "custom")])
9622 +(define_insn "custom_pnp"
9623 + [(set (match_operand:SI 0 "register_operand" "=r")
9624 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
9625 + (match_operand:SI 2 "register_operand" "r")] CUSTOM_PNP))]
9626 + ""
9627 + "custom\\t%1, %0, %2, zero"
9628 + [(set_attr "type" "custom")])
9630 +(define_insn "custom_pnii"
9631 + [(set (match_operand:SI 0 "register_operand" "=r")
9632 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
9633 + (match_operand:SI 2 "register_operand" "r")
9634 + (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNII))]
9635 + ""
9636 + "custom\\t%1, %0, %2, %3"
9637 + [(set_attr "type" "custom")])
9639 +(define_insn "custom_pnif"
9640 + [(set (match_operand:SI 0 "register_operand" "=r")
9641 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
9642 + (match_operand:SI 2 "register_operand" "r")
9643 + (match_operand:SF 3 "register_operand" "r")] CUSTOM_PNIF))]
9644 + ""
9645 + "custom\\t%1, %0, %2, %3"
9646 + [(set_attr "type" "custom")])
9648 +(define_insn "custom_pnip"
9649 + [(set (match_operand:SI 0 "register_operand" "=r")
9650 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
9651 + (match_operand:SI 2 "register_operand" "r")
9652 + (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNIP))]
9653 + ""
9654 + "custom\\t%1, %0, %2, %3"
9655 + [(set_attr "type" "custom")])
9657 +(define_insn "custom_pnfi"
9658 + [(set (match_operand:SI 0 "register_operand" "=r")
9659 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
9660 + (match_operand:SF 2 "register_operand" "r")
9661 + (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNFI))]
9662 + ""
9663 + "custom\\t%1, %0, %2, %3"
9664 + [(set_attr "type" "custom")])
9666 +(define_insn "custom_pnff"
9667 + [(set (match_operand:SI 0 "register_operand" "=r")
9668 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
9669 + (match_operand:SF 2 "register_operand" "r")
9670 + (match_operand:SF 3 "register_operand" "r")] CUSTOM_PNFF))]
9671 + ""
9672 + "custom\\t%1, %0, %2, %3"
9673 + [(set_attr "type" "custom")])
9675 +(define_insn "custom_pnfp"
9676 + [(set (match_operand:SI 0 "register_operand" "=r")
9677 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
9678 + (match_operand:SF 2 "register_operand" "r")
9679 + (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNFP))]
9680 + ""
9681 + "custom\\t%1, %0, %2, %3"
9682 + [(set_attr "type" "custom")])
9684 +(define_insn "custom_pnpi"
9685 + [(set (match_operand:SI 0 "register_operand" "=r")
9686 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
9687 + (match_operand:SI 2 "register_operand" "r")
9688 + (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNPI))]
9689 + ""
9690 + "custom\\t%1, %0, %2, %3"
9691 + [(set_attr "type" "custom")])
9693 +(define_insn "custom_pnpf"
9694 + [(set (match_operand:SI 0 "register_operand" "=r")
9695 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
9696 + (match_operand:SI 2 "register_operand" "r")
9697 + (match_operand:SF 3 "register_operand" "r")] CUSTOM_PNPF))]
9698 + ""
9699 + "custom\\t%1, %0, %2, %3"
9700 + [(set_attr "type" "custom")])
9702 +(define_insn "custom_pnpp"
9703 + [(set (match_operand:SI 0 "register_operand" "=r")
9704 + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
9705 + (match_operand:SI 2 "register_operand" "r")
9706 + (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNPP))]
9707 + ""
9708 + "custom\\t%1, %0, %2, %3"
9709 + [(set_attr "type" "custom")])
9716 +;*****************************************************************************
9718 +;* Misc
9720 +;*****************************************************************************
9722 +(define_insn "nop"
9723 + [(const_int 0)]
9724 + ""
9725 + "nop\\t"
9726 + [(set_attr "type" "alu")])
9728 +(define_insn "sync"
9729 + [(unspec_volatile [(const_int 0)] UNSPEC_SYNC)]
9730 + ""
9731 + "sync\\t"
9732 + [(set_attr "type" "control")])
9735 +(define_insn "rdctl"
9736 + [(set (match_operand:SI 0 "register_operand" "=r")
9737 + (unspec_volatile:SI [(match_operand:SI 1 "rdwrctl_operand" "O")] UNSPEC_RDCTL))]
9738 + ""
9739 + "rdctl\\t%0, ctl%1"
9740 + [(set_attr "type" "control")])
9742 +(define_insn "wrctl"
9743 + [(unspec_volatile:SI [(match_operand:SI 0 "rdwrctl_operand" "O")
9744 + (match_operand:SI 1 "register_operand" "r")] UNSPEC_WRCTL)]
9745 + ""
9746 + "wrctl\\tctl%0, %1"
9747 + [(set_attr "type" "control")])
9751 +;*****************************************************************************
9753 +;* Peepholes
9755 +;*****************************************************************************
9758 --- gcc-3.4.3/gcc/config/nios2/t-nios2
9759 +++ gcc-3.4.3-nios2/gcc/config/nios2/t-nios2
9760 @@ -0,0 +1,123 @@
9762 +## Compiler flags to use when compiling libgcc2.c.
9764 +## LIB2FUNCS_EXTRA
9765 +## A list of source file names to be compiled or assembled and inserted into libgcc.a.
9767 +LIB2FUNCS_EXTRA=$(srcdir)/config/nios2/lib2-divmod.c \
9768 + $(srcdir)/config/nios2/lib2-divmod-hi.c \
9769 + $(srcdir)/config/nios2/lib2-divtable.c \
9770 + $(srcdir)/config/nios2/lib2-mul.c
9773 +## Floating Point Emulation
9774 +## To have GCC include software floating point libraries in libgcc.a define FPBIT
9775 +## and DPBIT along with a few rules as follows:
9777 +## # We want fine grained libraries, so use the new code
9778 +## # to build the floating point emulation libraries.
9779 +FPBIT=$(srcdir)/config/nios2/nios2-fp-bit.c
9780 +DPBIT=$(srcdir)/config/nios2/nios2-dp-bit.c
9782 +TARGET_LIBGCC2_CFLAGS = -O2
9784 +# FLOAT_ONLY - no doubles
9785 +# SMALL_MACHINE - QI/HI is faster than SI
9786 +# Actually SMALL_MACHINE uses chars and shorts instead of ints
9787 +# since ints (16-bit ones as they are today) are at least as fast
9788 +# as chars and shorts, don't define SMALL_MACHINE
9789 +# CMPtype - type returned by FP compare, i.e. INT (hard coded in fp-bit - see code )
9791 +$(FPBIT): $(srcdir)/config/fp-bit.c Makefile
9792 + echo '#define FLOAT' > ${FPBIT}
9793 + cat $(srcdir)/config/fp-bit.c >> ${FPBIT}
9795 +$(DPBIT): $(srcdir)/config/fp-bit.c Makefile
9796 + echo '' > ${DPBIT}
9797 + cat $(srcdir)/config/fp-bit.c >> ${DPBIT}
9799 +EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
9801 +# Assemble startup files.
9802 +$(T)crti.o: $(srcdir)/config/nios2/crti.asm $(GCC_PASSES)
9803 + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
9804 + -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/nios2/crti.asm
9806 +$(T)crtn.o: $(srcdir)/config/nios2/crtn.asm $(GCC_PASSES)
9807 + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
9808 + -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/nios2/crtn.asm
9811 +## You may need to provide additional #defines at the beginning of
9812 +## fp-bit.c and dp-bit.c to control target endianness and other options
9814 +## CRTSTUFF_T_CFLAGS
9815 +## Special flags used when compiling crtstuff.c. See Initialization.
9817 +## CRTSTUFF_T_CFLAGS_S
9818 +## Special flags used when compiling crtstuff.c for shared linking. Used
9819 +## if you use crtbeginS.o and crtendS.o in EXTRA-PARTS. See Initialization.
9821 +## MULTILIB_OPTIONS
9822 +## For some targets, invoking GCC in different ways produces objects that
9823 +## can not be linked together. For example, for some targets GCC produces
9824 +## both big and little endian code. For these targets, you must arrange
9825 +## for multiple versions of libgcc.a to be compiled, one for each set of
9826 +## incompatible options. When GCC invokes the linker, it arranges to link
9827 +## in the right version of libgcc.a, based on the command line options
9828 +## used.
9829 +## The MULTILIB_OPTIONS macro lists the set of options for which special
9830 +## versions of libgcc.a must be built. Write options that are mutually
9831 +## incompatible side by side, separated by a slash. Write options that may
9832 +## be used together separated by a space. The build procedure will build
9833 +## all combinations of compatible options.
9835 +## For example, if you set MULTILIB_OPTIONS to m68000/m68020 msoft-float,
9836 +## Makefile will build special versions of libgcc.a using the following
9837 +## sets of options: -m68000, -m68020, -msoft-float, -m68000 -msoft-float,
9838 +## and -m68020 -msoft-float.
9840 +MULTILIB_OPTIONS = mno-hw-mul mhw-mulx
9842 +## MULTILIB_DIRNAMES
9843 +## If MULTILIB_OPTIONS is used, this variable specifies the directory names
9844 +## that should be used to hold the various libraries. Write one element in
9845 +## MULTILIB_DIRNAMES for each element in MULTILIB_OPTIONS. If
9846 +## MULTILIB_DIRNAMES is not used, the default value will be
9847 +## MULTILIB_OPTIONS, with all slashes treated as spaces.
9848 +## For example, if MULTILIB_OPTIONS is set to m68000/m68020 msoft-float,
9849 +## then the default value of MULTILIB_DIRNAMES is m68000 m68020
9850 +## msoft-float. You may specify a different value if you desire a
9851 +## different set of directory names.
9853 +# MULTILIB_DIRNAMES =
9855 +## MULTILIB_MATCHES
9856 +## Sometimes the same option may be written in two different ways. If an
9857 +## option is listed in MULTILIB_OPTIONS, GCC needs to know about any
9858 +## synonyms. In that case, set MULTILIB_MATCHES to a list of items of the
9859 +## form option=option to describe all relevant synonyms. For example,
9860 +## m68000=mc68000 m68020=mc68020.
9862 +## MULTILIB_EXCEPTIONS
9863 +## Sometimes when there are multiple sets of MULTILIB_OPTIONS being
9864 +## specified, there are combinations that should not be built. In that
9865 +## case, set MULTILIB_EXCEPTIONS to be all of the switch exceptions in
9866 +## shell case syntax that should not be built.
9867 +## For example, in the PowerPC embedded ABI support, it is not desirable to
9868 +## build libraries compiled with the -mcall-aix option and either of the
9869 +## -fleading-underscore or -mlittle options at the same time. Therefore
9870 +## MULTILIB_EXCEPTIONS is set to
9872 +## *mcall-aix/*fleading-underscore* *mlittle/*mcall-aix*
9875 +MULTILIB_EXCEPTIONS = *mno-hw-mul/*mhw-mulx*
9878 +## MULTILIB_EXTRA_OPTS Sometimes it is desirable that when building
9879 +## multiple versions of libgcc.a certain options should always be passed on
9880 +## to the compiler. In that case, set MULTILIB_EXTRA_OPTS to be the list
9881 +## of options to be used for all builds.
9884 --- gcc-3.4.3/gcc/config.gcc
9885 +++ gcc-3.4.3-nios2/gcc/config.gcc
9886 @@ -1321,6 +1321,10 @@ m32rle-*-linux*)
9887 thread_file='posix'
9890 +# JBG
9891 +nios2-*-* | nios2-*-*)
9892 + tm_file="elfos.h ${tm_file}"
9893 + ;;
9894 # m68hc11 and m68hc12 share the same machine description.
9895 m68hc11-*-*|m6811-*-*)
9896 tm_file="dbxelf.h elfos.h m68hc11/m68hc11.h"
9897 --- gcc-3.4.3/gcc/cse.c
9898 +++ gcc-3.4.3-nios2/gcc/cse.c
9899 @@ -3134,6 +3134,10 @@ find_comparison_args (enum rtx_code code
9900 #ifdef FLOAT_STORE_FLAG_VALUE
9901 REAL_VALUE_TYPE fsfv;
9902 #endif
9903 +#ifdef __nios2__
9904 + if (p->is_const)
9905 + break;
9906 +#endif
9908 /* If the entry isn't valid, skip it. */
9909 if (! exp_equiv_p (p->exp, p->exp, 1, 0))
9910 --- gcc-3.4.3/gcc/doc/extend.texi
9911 +++ gcc-3.4.3-nios2/gcc/doc/extend.texi
9912 @@ -5636,12 +5636,118 @@ to those machines. Generally these gene
9913 instructions, but allow the compiler to schedule those calls.
9915 @menu
9916 +* Altera Nios II Built-in Functions::
9917 * Alpha Built-in Functions::
9918 * ARM Built-in Functions::
9919 * X86 Built-in Functions::
9920 * PowerPC AltiVec Built-in Functions::
9921 @end menu
9923 +@node Altera Nios II Built-in Functions
9924 +@subsection Altera Nios II Built-in Functions
9926 +These built-in functions are available for the Altera Nios II
9927 +family of processors.
9929 +The following built-in functions are always available. They
9930 +all generate the machine instruction that is part of the name.
9932 +@example
9933 +int __builtin_ldbio (volatile const void *)
9934 +int __builtin_ldbuio (volatile const void *)
9935 +int __builtin_ldhio (volatile const void *)
9936 +int __builtin_ldhuio (volatile const void *)
9937 +int __builtin_ldwio (volatile const void *)
9938 +void __builtin_stbio (volatile void *, int)
9939 +void __builtin_sthio (volatile void *, int)
9940 +void __builtin_stwio (volatile void *, int)
9941 +void __builtin_sync (void)
9942 +int __builtin_rdctl (int)
9943 +void __builtin_wrctl (int, int)
9944 +@end example
9946 +The following built-in functions are always available. They
9947 +all generate a Nios II Custom Instruction. The name of the
9948 +function represents the types that the function takes and
9949 +returns. The letter before the @code{n} is the return type
9950 +or void if absent. The @code{n} represnts the first parameter
9951 +to all the custom instructions, the custom instruction number.
9952 +The two letters after the @code{n} represent the up to two
9953 +parameters to the function.
9955 +The letters reprsent the following data types:
9956 +@table @code
9957 +@item <no letter>
9958 +@code{void} for return type and no parameter for parameter types.
9960 +@item i
9961 +@code{int} for return type and parameter type
9963 +@item f
9964 +@code{float} for return type and parameter type
9966 +@item p
9967 +@code{void *} for return type and parameter type
9969 +@end table
9971 +And the function names are:
9972 +@example
9973 +void __builtin_custom_n (void)
9974 +void __builtin_custom_ni (int)
9975 +void __builtin_custom_nf (float)
9976 +void __builtin_custom_np (void *)
9977 +void __builtin_custom_nii (int, int)
9978 +void __builtin_custom_nif (int, float)
9979 +void __builtin_custom_nip (int, void *)
9980 +void __builtin_custom_nfi (float, int)
9981 +void __builtin_custom_nff (float, float)
9982 +void __builtin_custom_nfp (float, void *)
9983 +void __builtin_custom_npi (void *, int)
9984 +void __builtin_custom_npf (void *, float)
9985 +void __builtin_custom_npp (void *, void *)
9986 +int __builtin_custom_in (void)
9987 +int __builtin_custom_ini (int)
9988 +int __builtin_custom_inf (float)
9989 +int __builtin_custom_inp (void *)
9990 +int __builtin_custom_inii (int, int)
9991 +int __builtin_custom_inif (int, float)
9992 +int __builtin_custom_inip (int, void *)
9993 +int __builtin_custom_infi (float, int)
9994 +int __builtin_custom_inff (float, float)
9995 +int __builtin_custom_infp (float, void *)
9996 +int __builtin_custom_inpi (void *, int)
9997 +int __builtin_custom_inpf (void *, float)
9998 +int __builtin_custom_inpp (void *, void *)
9999 +float __builtin_custom_fn (void)
10000 +float __builtin_custom_fni (int)
10001 +float __builtin_custom_fnf (float)
10002 +float __builtin_custom_fnp (void *)
10003 +float __builtin_custom_fnii (int, int)
10004 +float __builtin_custom_fnif (int, float)
10005 +float __builtin_custom_fnip (int, void *)
10006 +float __builtin_custom_fnfi (float, int)
10007 +float __builtin_custom_fnff (float, float)
10008 +float __builtin_custom_fnfp (float, void *)
10009 +float __builtin_custom_fnpi (void *, int)
10010 +float __builtin_custom_fnpf (void *, float)
10011 +float __builtin_custom_fnpp (void *, void *)
10012 +void * __builtin_custom_pn (void)
10013 +void * __builtin_custom_pni (int)
10014 +void * __builtin_custom_pnf (float)
10015 +void * __builtin_custom_pnp (void *)
10016 +void * __builtin_custom_pnii (int, int)
10017 +void * __builtin_custom_pnif (int, float)
10018 +void * __builtin_custom_pnip (int, void *)
10019 +void * __builtin_custom_pnfi (float, int)
10020 +void * __builtin_custom_pnff (float, float)
10021 +void * __builtin_custom_pnfp (float, void *)
10022 +void * __builtin_custom_pnpi (void *, int)
10023 +void * __builtin_custom_pnpf (void *, float)
10024 +void * __builtin_custom_pnpp (void *, void *)
10025 +@end example
10028 @node Alpha Built-in Functions
10029 @subsection Alpha Built-in Functions
10031 --- gcc-3.4.3/gcc/doc/invoke.texi
10032 +++ gcc-3.4.3-nios2/gcc/doc/invoke.texi
10033 @@ -337,6 +337,14 @@ in the following sections.
10034 @item Machine Dependent Options
10035 @xref{Submodel Options,,Hardware Models and Configurations}.
10037 +@emph{Altera Nios II Options}
10038 +@gccoptlist{-msmallc -mno-bypass-cache -mbypass-cache @gol
10039 +-mno-cache-volatile -mcache-volatile -mno-inline-memcpy @gol
10040 +-minline-memcpy -mno-fast-sw-div -mfast-sw-div @gol
10041 +-mhw-mul -mno-hw-mul -mhw-mulx -mno-hw-mulx @gol
10042 +-mno-hw-div -mhw-div @gol
10043 +-msys-crt0= -msys-lib= -msys=nosys }
10045 @emph{M680x0 Options}
10046 @gccoptlist{-m68000 -m68020 -m68020-40 -m68020-60 -m68030 -m68040 @gol
10047 -m68060 -mcpu32 -m5200 -m68881 -mbitfield -mc68000 -mc68020 @gol
10048 @@ -5836,6 +5844,7 @@ machine description. The default for th
10049 that macro, which enables you to change the defaults.
10051 @menu
10052 +* Altera Nios II Options::
10053 * M680x0 Options::
10054 * M68hc1x Options::
10055 * VAX Options::
10056 @@ -5871,6 +5880,103 @@ that macro, which enables you to change
10057 * FRV Options::
10058 @end menu
10061 +@node Altera Nios II Options
10062 +@subsection Altera Nios II Options
10063 +@cindex Altera Nios II options
10065 +These are the @samp{-m} options defined for the Altera Nios II
10066 +processor.
10068 +@table @gcctabopt
10070 +@item -msmallc
10071 +@opindex msmallc
10073 +Link with a limited version of the C library, -lsmallc. For more
10074 +information see the C Library Documentation.
10077 +@item -mbypass-cache
10078 +@itemx -mno-bypass-cache
10079 +@opindex mno-bypass-cache
10080 +@opindex mbypass-cache
10082 +Force all load and store instructions to always bypass cache by
10083 +using io variants of the instructions. The default is to not
10084 +bypass the cache.
10086 +@item -mno-cache-volatile
10087 +@itemx -mcache-volatile
10088 +@opindex mcache-volatile
10089 +@opindex mno-cache-volatile
10091 +Volatile memory access bypass the cache using the io variants of
10092 +the ld and st instructions. The default is to cache volatile
10093 +accesses.
10095 +-mno-cache-volatile is deprecated and will be deleted in a
10096 +future GCC release.
10099 +@item -mno-inline-memcpy
10100 +@itemx -minline-memcpy
10101 +@opindex mno-inline-memcpy
10102 +@opindex minline-memcpy
10104 +Do not inline memcpy. The default is to inline when -O is on.
10107 +@item -mno-fast-sw-div
10108 +@itemx -mfast-sw-div
10109 +@opindex mno-fast-sw-div
10110 +@opindex mfast-sw-div
10112 +Do no use table based fast divide for small numbers. The default
10113 +is to use the fast divide at -O3 and above.
10116 +@item -mno-hw-mul
10117 +@itemx -mhw-mul
10118 +@itemx -mno-hw-mulx
10119 +@itemx -mhw-mulx
10120 +@itemx -mno-hw-div
10121 +@itemx -mhw-div
10122 +@opindex mno-hw-mul
10123 +@opindex mhw-mul
10124 +@opindex mno-hw-mulx
10125 +@opindex mhw-mulx
10126 +@opindex mno-hw-div
10127 +@opindex mhw-div
10129 +Enable or disable emitting @code{mul}, @code{mulx} and @code{div} family of
10130 +instructions by the compiler. The default is to emit @code{mul}
10131 +and not emit @code{div} and @code{mulx}.
10133 +The different combinations of @code{mul} and @code{mulx} instructions
10134 +generate a different multilib options.
10137 +@item -msys-crt0=@var{startfile}
10138 +@opindex msys-crt0
10140 +@var{startfile} is the file name of the startfile (crt0) to use
10141 +when linking. The default is crt0.o that comes with libgloss
10142 +and is only suitable for use with the instruction set
10143 +simulator.
10145 +@item -msys-lib=@var{systemlib}
10146 +@itemx -msys-lib=nosys
10147 +@opindex msys-lib
10149 +@var{systemlib} is the library name of the library which provides
10150 +the system calls required by the C library, e.g. @code{read}, @code{write}
10151 +etc. The default is to use nosys, this library provides
10152 +stub implementations of the calls and is part of libgloss.
10154 +@end table
10157 @node M680x0 Options
10158 @subsection M680x0 Options
10159 @cindex M680x0 options
10160 --- gcc-3.4.3/gcc/doc/md.texi
10161 +++ gcc-3.4.3-nios2/gcc/doc/md.texi
10162 @@ -1335,6 +1335,49 @@ However, here is a summary of the machin
10163 available on some particular machines.
10165 @table @emph
10167 +@item Altera Nios II family---@file{nios2.h}
10168 +@table @code
10170 +@item I
10171 +Integer that is valid as an immediate operand in an
10172 +instruction taking a signed 16-bit number. Range
10173 +@minus{}32768 to 32767.
10175 +@item J
10176 +Integer that is valid as an immediate operand in an
10177 +instruction taking an unsigned 16-bit number. Range
10178 +0 to 65535.
10180 +@item K
10181 +Integer that is valid as an immediate operand in an
10182 +instruction taking only the upper 16-bits of a
10183 +32-bit number. Range 32-bit numbers with the lower
10184 +16-bits being 0.
10186 +@item L
10187 +Integer that is valid as an immediate operand for a
10188 +shift instruction. Range 0 to 31.
10191 +@item M
10192 +Integer that is valid as an immediate operand for
10193 +only the value 0. Can be used in conjunction with
10194 +the format modifier @code{z} to use @code{r0}
10195 +instead of @code{0} in the assembly output.
10197 +@item N
10198 +Integer that is valid as an immediate operand for
10199 +a custom instruction opcode. Range 0 to 255.
10201 +@item S
10202 +Matches immediates which are addresses in the small
10203 +data section and therefore can be added to @code{gp}
10204 +as a 16-bit immediate to re-create their 32-bit value.
10206 +@end table
10209 @item ARM family---@file{arm.h}
10210 @table @code
10211 @item f