mgl@1371
|
1 |
--- a/configure.in
|
mgl@1371
|
2 |
+++ b/configure.in
|
mgl@1371
|
3 |
@@ -503,6 +503,9 @@ case "${target}" in
|
mgl@1371
|
4 |
arm-*-riscix*)
|
mgl@1371
|
5 |
noconfigdirs="$noconfigdirs ld target-libgloss ${libgcj}"
|
mgl@1371
|
6 |
;;
|
mgl@1371
|
7 |
+ avr32-*-*)
|
mgl@1371
|
8 |
+ noconfigdirs="$noconfigdirs target-libiberty target-libmudflap target-libffi ${libgcj}"
|
mgl@1371
|
9 |
+ ;;
|
mgl@1371
|
10 |
avr-*-*)
|
mgl@1371
|
11 |
noconfigdirs="$noconfigdirs target-libiberty target-libstdc++-v3 ${libgcj}"
|
mgl@1371
|
12 |
;;
|
mgl@1371
|
13 |
--- a/gcc/builtins.c
|
mgl@1371
|
14 |
+++ b/gcc/builtins.c
|
mgl@1371
|
15 |
@@ -9223,7 +9223,7 @@ validate_arglist (tree arglist, ...)
|
mgl@1371
|
16 |
|
mgl@1371
|
17 |
do
|
mgl@1371
|
18 |
{
|
mgl@1371
|
19 |
- code = va_arg (ap, enum tree_code);
|
mgl@1371
|
20 |
+ code = va_arg (ap, int);
|
mgl@1371
|
21 |
switch (code)
|
mgl@1371
|
22 |
{
|
mgl@1371
|
23 |
case 0:
|
mgl@1371
|
24 |
--- a/gcc/calls.c
|
mgl@1371
|
25 |
+++ b/gcc/calls.c
|
mgl@1371
|
26 |
@@ -3447,7 +3447,7 @@ emit_library_call_value_1 (int retval, r
|
mgl@1371
|
27 |
for (; count < nargs; count++)
|
mgl@1371
|
28 |
{
|
mgl@1371
|
29 |
rtx val = va_arg (p, rtx);
|
mgl@1371
|
30 |
- enum machine_mode mode = va_arg (p, enum machine_mode);
|
mgl@1371
|
31 |
+ enum machine_mode mode = va_arg (p, int);
|
mgl@1371
|
32 |
|
mgl@1371
|
33 |
/* We cannot convert the arg value to the mode the library wants here;
|
mgl@1371
|
34 |
must do it earlier where we know the signedness of the arg. */
|
mgl@1371
|
35 |
--- a/gcc/c-incpath.c
|
mgl@1371
|
36 |
+++ b/gcc/c-incpath.c
|
mgl@1371
|
37 |
@@ -347,6 +347,18 @@ add_path (char *path, int chain, int cxx
|
mgl@1371
|
38 |
char* c;
|
mgl@1371
|
39 |
for (c = path; *c; c++)
|
mgl@1371
|
40 |
if (*c == '\\') *c = '/';
|
mgl@1371
|
41 |
+ /* Remove unnecessary trailing slashes. On some versions of MS
|
mgl@1371
|
42 |
+ Windows, trailing _forward_ slashes cause no problems for stat().
|
mgl@1371
|
43 |
+ On newer versions, stat() does not recognise a directory that ends
|
mgl@1371
|
44 |
+ in a '\\' or '/', unless it is a drive root dir, such as "c:/",
|
mgl@1371
|
45 |
+ where it is obligatory. */
|
mgl@1371
|
46 |
+ int pathlen = strlen (path);
|
mgl@1371
|
47 |
+ char* end = path + pathlen - 1;
|
mgl@1371
|
48 |
+ /* Preserve the lead '/' or lead "c:/". */
|
mgl@1371
|
49 |
+ char* start = path + (pathlen > 2 && path[1] == ':' ? 3 : 1);
|
mgl@1371
|
50 |
+
|
mgl@1371
|
51 |
+ for (; end > start && IS_DIR_SEPARATOR (*end); end--)
|
mgl@1371
|
52 |
+ *end = 0;
|
mgl@1371
|
53 |
#endif
|
mgl@1371
|
54 |
|
mgl@1371
|
55 |
p = XNEW (cpp_dir);
|
mgl@1371
|
56 |
--- /dev/null
|
mgl@1371
|
57 |
+++ b/gcc/config/avr32/avr32.c
|
mgl@1371
|
58 |
@@ -0,0 +1,7915 @@
|
mgl@1371
|
59 |
+/*
|
mgl@1371
|
60 |
+ Target hooks and helper functions for AVR32.
|
mgl@1371
|
61 |
+ Copyright 2003-2006 Atmel Corporation.
|
mgl@1371
|
62 |
+
|
mgl@1371
|
63 |
+ Written by Ronny Pedersen, Atmel Norway, <rpedersen@atmel.com>
|
mgl@1371
|
64 |
+ Initial porting by Anders �dland.
|
mgl@1371
|
65 |
+
|
mgl@1371
|
66 |
+ This file is part of GCC.
|
mgl@1371
|
67 |
+
|
mgl@1371
|
68 |
+ This program is free software; you can redistribute it and/or modify
|
mgl@1371
|
69 |
+ it under the terms of the GNU General Public License as published by
|
mgl@1371
|
70 |
+ the Free Software Foundation; either version 2 of the License, or
|
mgl@1371
|
71 |
+ (at your option) any later version.
|
mgl@1371
|
72 |
+
|
mgl@1371
|
73 |
+ This program is distributed in the hope that it will be useful,
|
mgl@1371
|
74 |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
mgl@1371
|
75 |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
mgl@1371
|
76 |
+ GNU General Public License for more details.
|
mgl@1371
|
77 |
+
|
mgl@1371
|
78 |
+ You should have received a copy of the GNU General Public License
|
mgl@1371
|
79 |
+ along with this program; if not, write to the Free Software
|
mgl@1371
|
80 |
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
mgl@1371
|
81 |
+
|
mgl@1371
|
82 |
+#include "config.h"
|
mgl@1371
|
83 |
+#include "system.h"
|
mgl@1371
|
84 |
+#include "coretypes.h"
|
mgl@1371
|
85 |
+#include "tm.h"
|
mgl@1371
|
86 |
+#include "rtl.h"
|
mgl@1371
|
87 |
+#include "tree.h"
|
mgl@1371
|
88 |
+#include "obstack.h"
|
mgl@1371
|
89 |
+#include "regs.h"
|
mgl@1371
|
90 |
+#include "hard-reg-set.h"
|
mgl@1371
|
91 |
+#include "real.h"
|
mgl@1371
|
92 |
+#include "insn-config.h"
|
mgl@1371
|
93 |
+#include "conditions.h"
|
mgl@1371
|
94 |
+#include "output.h"
|
mgl@1371
|
95 |
+#include "insn-attr.h"
|
mgl@1371
|
96 |
+#include "flags.h"
|
mgl@1371
|
97 |
+#include "reload.h"
|
mgl@1371
|
98 |
+#include "function.h"
|
mgl@1371
|
99 |
+#include "expr.h"
|
mgl@1371
|
100 |
+#include "optabs.h"
|
mgl@1371
|
101 |
+#include "toplev.h"
|
mgl@1371
|
102 |
+#include "recog.h"
|
mgl@1371
|
103 |
+#include "ggc.h"
|
mgl@1371
|
104 |
+#include "except.h"
|
mgl@1371
|
105 |
+#include "c-pragma.h"
|
mgl@1371
|
106 |
+#include "integrate.h"
|
mgl@1371
|
107 |
+#include "tm_p.h"
|
mgl@1371
|
108 |
+#include "langhooks.h"
|
mgl@1371
|
109 |
+
|
mgl@1371
|
110 |
+#include "target.h"
|
mgl@1371
|
111 |
+#include "target-def.h"
|
mgl@1371
|
112 |
+
|
mgl@1371
|
113 |
+#include <ctype.h>
|
mgl@1371
|
114 |
+
|
mgl@1371
|
115 |
+/* Forward definitions of types. */
|
mgl@1371
|
116 |
+typedef struct minipool_node Mnode;
|
mgl@1371
|
117 |
+typedef struct minipool_fixup Mfix;
|
mgl@1371
|
118 |
+
|
mgl@1371
|
119 |
+/* Obstack for minipool constant handling. */
|
mgl@1371
|
120 |
+static struct obstack minipool_obstack;
|
mgl@1371
|
121 |
+static char *minipool_startobj;
|
mgl@1371
|
122 |
+static rtx minipool_vector_label;
|
mgl@1371
|
123 |
+
|
mgl@1371
|
124 |
+/* True if we are currently building a constant table. */
|
mgl@1371
|
125 |
+int making_const_table;
|
mgl@1371
|
126 |
+
|
mgl@1371
|
127 |
+/* Some forward function declarations */
|
mgl@1371
|
128 |
+static unsigned long avr32_isr_value (tree);
|
mgl@1371
|
129 |
+static unsigned long avr32_compute_func_type (void);
|
mgl@1371
|
130 |
+static tree avr32_handle_isr_attribute (tree *, tree, tree, int, bool *);
|
mgl@1371
|
131 |
+static tree avr32_handle_acall_attribute (tree *, tree, tree, int, bool *);
|
mgl@1371
|
132 |
+static tree avr32_handle_fndecl_attribute (tree * node, tree name, tree args,
|
mgl@1371
|
133 |
+ int flags, bool * no_add_attrs);
|
mgl@1371
|
134 |
+static void avr32_reorg (void);
|
mgl@1371
|
135 |
+bool avr32_return_in_msb (tree type);
|
mgl@1371
|
136 |
+bool avr32_vector_mode_supported (enum machine_mode mode);
|
mgl@1371
|
137 |
+static void avr32_init_libfuncs (void);
|
mgl@1371
|
138 |
+
|
mgl@1371
|
139 |
+
|
mgl@1371
|
140 |
+static void
|
mgl@1371
|
141 |
+avr32_add_gc_roots (void)
|
mgl@1371
|
142 |
+{
|
mgl@1371
|
143 |
+ gcc_obstack_init (&minipool_obstack);
|
mgl@1371
|
144 |
+ minipool_startobj = (char *) obstack_alloc (&minipool_obstack, 0);
|
mgl@1371
|
145 |
+}
|
mgl@1371
|
146 |
+
|
mgl@1371
|
147 |
+
|
mgl@1371
|
148 |
+/* List of all known AVR32 parts */
|
mgl@1371
|
149 |
+static const struct part_type_s avr32_part_types[] = {
|
mgl@1371
|
150 |
+ /* name, part_type, architecture type, macro */
|
mgl@1371
|
151 |
+ {"none", PART_TYPE_AVR32_NONE, ARCH_TYPE_AVR32_AP, "__AVR32__"},
|
mgl@1371
|
152 |
+ {"ap7000", PART_TYPE_AVR32_AP7000, ARCH_TYPE_AVR32_AP, "__AVR32_AP7000__"},
|
mgl@1371
|
153 |
+ {"ap7001", PART_TYPE_AVR32_AP7001, ARCH_TYPE_AVR32_AP, "__AVR32_AP7001__"},
|
mgl@1371
|
154 |
+ {"ap7002", PART_TYPE_AVR32_AP7002, ARCH_TYPE_AVR32_AP, "__AVR32_AP7002__"},
|
mgl@1371
|
155 |
+ {"ap7200", PART_TYPE_AVR32_AP7200, ARCH_TYPE_AVR32_AP, "__AVR32_AP7200__"},
|
mgl@1371
|
156 |
+ {"uc3a0128", PART_TYPE_AVR32_UC3A0128, ARCH_TYPE_AVR32_UCR2,
|
mgl@1371
|
157 |
+ "__AVR32_UC3A0128__"},
|
mgl@1371
|
158 |
+ {"uc3a0256", PART_TYPE_AVR32_UC3A0256, ARCH_TYPE_AVR32_UCR2,
|
mgl@1371
|
159 |
+ "__AVR32_UC3A0256__"},
|
mgl@1371
|
160 |
+ {"uc3a0512", PART_TYPE_AVR32_UC3A0512, ARCH_TYPE_AVR32_UCR2,
|
mgl@1371
|
161 |
+ "__AVR32_UC3A0512__"},
|
mgl@1371
|
162 |
+ {"uc3a0512es", PART_TYPE_AVR32_UC3A0512ES, ARCH_TYPE_AVR32_UCR1,
|
mgl@1371
|
163 |
+ "__AVR32_UC3A0512ES__"},
|
mgl@1371
|
164 |
+ {"uc3a1128", PART_TYPE_AVR32_UC3A1128, ARCH_TYPE_AVR32_UCR2,
|
mgl@1371
|
165 |
+ "__AVR32_UC3A1128__"},
|
mgl@1371
|
166 |
+ {"uc3a1256", PART_TYPE_AVR32_UC3A1256, ARCH_TYPE_AVR32_UCR2,
|
mgl@1371
|
167 |
+ "__AVR32_UC3A1256__"},
|
mgl@1371
|
168 |
+ {"uc3a1512", PART_TYPE_AVR32_UC3A1512, ARCH_TYPE_AVR32_UCR2,
|
mgl@1371
|
169 |
+ "__AVR32_UC3A1512__"},
|
mgl@1371
|
170 |
+ {"uc3a1512es", PART_TYPE_AVR32_UC3A1512ES, ARCH_TYPE_AVR32_UCR1,
|
mgl@1371
|
171 |
+ "__AVR32_UC3A1512ES__"},
|
mgl@1371
|
172 |
+ {"uc3a3revd", PART_TYPE_AVR32_UC3A3REVD, ARCH_TYPE_AVR32_UCR2NOMUL,
|
mgl@1371
|
173 |
+ "__AVR32_UC3A3256S__"},
|
mgl@1371
|
174 |
+ {"uc3a364", PART_TYPE_AVR32_UC3A364, ARCH_TYPE_AVR32_UCR2,
|
mgl@1371
|
175 |
+ "__AVR32_UC3A364__"},
|
mgl@1371
|
176 |
+ {"uc3a364s", PART_TYPE_AVR32_UC3A364S, ARCH_TYPE_AVR32_UCR2,
|
mgl@1371
|
177 |
+ "__AVR32_UC3A364S__"},
|
mgl@1371
|
178 |
+ {"uc3a3128", PART_TYPE_AVR32_UC3A3128, ARCH_TYPE_AVR32_UCR2,
|
mgl@1371
|
179 |
+ "__AVR32_UC3A3128__"},
|
mgl@1371
|
180 |
+ {"uc3a3128s", PART_TYPE_AVR32_UC3A3128S, ARCH_TYPE_AVR32_UCR2,
|
mgl@1371
|
181 |
+ "__AVR32_UC3A3128S__"},
|
mgl@1371
|
182 |
+ {"uc3a3256", PART_TYPE_AVR32_UC3A3256, ARCH_TYPE_AVR32_UCR2,
|
mgl@1371
|
183 |
+ "__AVR32_UC3A3256__"},
|
mgl@1371
|
184 |
+ {"uc3a3256s", PART_TYPE_AVR32_UC3A3256S, ARCH_TYPE_AVR32_UCR2,
|
mgl@1371
|
185 |
+ "__AVR32_UC3A3256S__"},
|
mgl@1371
|
186 |
+ {"uc3b064", PART_TYPE_AVR32_UC3B064, ARCH_TYPE_AVR32_UCR1,
|
mgl@1371
|
187 |
+ "__AVR32_UC3B064__"},
|
mgl@1371
|
188 |
+ {"uc3b0128", PART_TYPE_AVR32_UC3B0128, ARCH_TYPE_AVR32_UCR1,
|
mgl@1371
|
189 |
+ "__AVR32_UC3B0128__"},
|
mgl@1371
|
190 |
+ {"uc3b0256", PART_TYPE_AVR32_UC3B0256, ARCH_TYPE_AVR32_UCR1,
|
mgl@1371
|
191 |
+ "__AVR32_UC3B0256__"},
|
mgl@1371
|
192 |
+ {"uc3b0256es", PART_TYPE_AVR32_UC3B0256ES, ARCH_TYPE_AVR32_UCR1,
|
mgl@1371
|
193 |
+ "__AVR32_UC3B0256ES__"},
|
mgl@1371
|
194 |
+ {"uc3b164", PART_TYPE_AVR32_UC3B164, ARCH_TYPE_AVR32_UCR1,
|
mgl@1371
|
195 |
+ "__AVR32_UC3B164__"},
|
mgl@1371
|
196 |
+ {"uc3b1128", PART_TYPE_AVR32_UC3B1128, ARCH_TYPE_AVR32_UCR1,
|
mgl@1371
|
197 |
+ "__AVR32_UC3B1128__"},
|
mgl@1371
|
198 |
+ {"uc3b1256", PART_TYPE_AVR32_UC3B1256, ARCH_TYPE_AVR32_UCR1,
|
mgl@1371
|
199 |
+ "__AVR32_UC3B1256__"},
|
mgl@1371
|
200 |
+ {"uc3b1256es", PART_TYPE_AVR32_UC3B1256ES, ARCH_TYPE_AVR32_UCR1,
|
mgl@1371
|
201 |
+ "__AVR32_UC3B1256ES__"},
|
mgl@1371
|
202 |
+ {NULL, 0, 0, NULL}
|
mgl@1371
|
203 |
+};
|
mgl@1371
|
204 |
+
|
mgl@1371
|
205 |
+/* List of all known AVR32 architectures */
|
mgl@1371
|
206 |
+static const struct arch_type_s avr32_arch_types[] = {
|
mgl@1371
|
207 |
+ /* name, architecture type, microarchitecture type, feature flags, macro */
|
mgl@1371
|
208 |
+ {"ap", ARCH_TYPE_AVR32_AP, UARCH_TYPE_AVR32B,
|
mgl@1371
|
209 |
+ (FLAG_AVR32_HAS_DSP
|
mgl@1371
|
210 |
+ | FLAG_AVR32_HAS_SIMD
|
mgl@1371
|
211 |
+ | FLAG_AVR32_HAS_UNALIGNED_WORD
|
mgl@1371
|
212 |
+ | FLAG_AVR32_HAS_BRANCH_PRED | FLAG_AVR32_HAS_RETURN_STACK
|
mgl@1371
|
213 |
+ | FLAG_AVR32_HAS_CACHES),
|
mgl@1371
|
214 |
+ "__AVR32_AP__"},
|
mgl@1371
|
215 |
+ {"ucr1", ARCH_TYPE_AVR32_UCR1, UARCH_TYPE_AVR32A,
|
mgl@1371
|
216 |
+ (FLAG_AVR32_HAS_DSP | FLAG_AVR32_HAS_RMW),
|
mgl@1371
|
217 |
+ "__AVR32_UC__=1"},
|
mgl@1371
|
218 |
+ {"ucr2", ARCH_TYPE_AVR32_UCR2, UARCH_TYPE_AVR32A,
|
mgl@1371
|
219 |
+ (FLAG_AVR32_HAS_DSP | FLAG_AVR32_HAS_RMW
|
mgl@1371
|
220 |
+ | FLAG_AVR32_HAS_V2_INSNS),
|
mgl@1371
|
221 |
+ "__AVR32_UC__=2"},
|
mgl@1371
|
222 |
+ {"ucr2nomul", ARCH_TYPE_AVR32_UCR2NOMUL, UARCH_TYPE_AVR32A,
|
mgl@1371
|
223 |
+ (FLAG_AVR32_HAS_DSP | FLAG_AVR32_HAS_RMW
|
mgl@1371
|
224 |
+ | FLAG_AVR32_HAS_V2_INSNS | FLAG_AVR32_HAS_NO_MUL_INSNS),
|
mgl@1371
|
225 |
+ "__AVR32_UC__=3"},
|
mgl@1371
|
226 |
+ {NULL, 0, 0, 0, NULL}
|
mgl@1371
|
227 |
+};
|
mgl@1371
|
228 |
+
|
mgl@1371
|
229 |
+/* Default arch name */
|
mgl@1371
|
230 |
+const char *avr32_arch_name = "none";
|
mgl@1371
|
231 |
+const char *avr32_part_name = "none";
|
mgl@1371
|
232 |
+
|
mgl@1371
|
233 |
+const struct part_type_s *avr32_part;
|
mgl@1371
|
234 |
+const struct arch_type_s *avr32_arch;
|
mgl@1371
|
235 |
+
|
mgl@1371
|
236 |
+
|
mgl@1371
|
237 |
+/* Set default target_flags. */
|
mgl@1371
|
238 |
+#undef TARGET_DEFAULT_TARGET_FLAGS
|
mgl@1371
|
239 |
+#define TARGET_DEFAULT_TARGET_FLAGS \
|
mgl@1371
|
240 |
+ (MASK_HAS_ASM_ADDR_PSEUDOS | MASK_MD_REORG_OPTIMIZATION | MASK_COND_EXEC_BEFORE_RELOAD)
|
mgl@1371
|
241 |
+
|
mgl@1371
|
242 |
+void
|
mgl@1371
|
243 |
+avr32_optimization_options (int level,
|
mgl@1371
|
244 |
+ int size){
|
mgl@1371
|
245 |
+ if (AVR32_ALWAYS_PIC)
|
mgl@1371
|
246 |
+ flag_pic = 1;
|
mgl@1371
|
247 |
+
|
mgl@1371
|
248 |
+ /* Enable section anchors if optimization is enabled. */
|
mgl@1371
|
249 |
+ if (level > 0 || size)
|
mgl@1371
|
250 |
+ flag_section_anchors = 1;
|
mgl@1371
|
251 |
+}
|
mgl@1371
|
252 |
+
|
mgl@1371
|
253 |
+/* Override command line options */
|
mgl@1371
|
254 |
+void
|
mgl@1371
|
255 |
+avr32_override_options (void)
|
mgl@1371
|
256 |
+{
|
mgl@1371
|
257 |
+ const struct part_type_s *part;
|
mgl@1371
|
258 |
+ const struct arch_type_s *arch;
|
mgl@1371
|
259 |
+
|
mgl@1371
|
260 |
+ /*Add backward compability*/
|
mgl@1371
|
261 |
+ if (strcmp ("uc", avr32_arch_name)== 0)
|
mgl@1371
|
262 |
+ {
|
mgl@1371
|
263 |
+ fprintf (stderr, "Warning: Deprecated arch `%s' specified. "
|
mgl@1371
|
264 |
+ "Please use '-march=ucr1' instead. "
|
mgl@1371
|
265 |
+ "Converting to arch 'ucr1'\n",
|
mgl@1371
|
266 |
+ avr32_arch_name);
|
mgl@1371
|
267 |
+ avr32_arch_name="ucr1";
|
mgl@1371
|
268 |
+ }
|
mgl@1371
|
269 |
+
|
mgl@1371
|
270 |
+ /* Check if arch type is set. */
|
mgl@1371
|
271 |
+ for (arch = avr32_arch_types; arch->name; arch++)
|
mgl@1371
|
272 |
+ {
|
mgl@1371
|
273 |
+ if (strcmp (arch->name, avr32_arch_name) == 0)
|
mgl@1371
|
274 |
+ break;
|
mgl@1371
|
275 |
+ }
|
mgl@1371
|
276 |
+ avr32_arch = arch;
|
mgl@1371
|
277 |
+
|
mgl@1371
|
278 |
+ if (!arch->name && strcmp("none", avr32_arch_name) != 0)
|
mgl@1371
|
279 |
+ {
|
mgl@1371
|
280 |
+ fprintf (stderr, "Unknown arch `%s' specified\n"
|
mgl@1371
|
281 |
+ "Known arch names:\n"
|
mgl@1371
|
282 |
+ "\tuc (deprecated)\n",
|
mgl@1371
|
283 |
+ avr32_arch_name);
|
mgl@1371
|
284 |
+ for (arch = avr32_arch_types; arch->name; arch++)
|
mgl@1371
|
285 |
+ fprintf (stderr, "\t%s\n", arch->name);
|
mgl@1371
|
286 |
+ avr32_arch = &avr32_arch_types[ARCH_TYPE_AVR32_AP];
|
mgl@1371
|
287 |
+ }
|
mgl@1371
|
288 |
+
|
mgl@1371
|
289 |
+ /* Check if part type is set. */
|
mgl@1371
|
290 |
+ for (part = avr32_part_types; part->name; part++)
|
mgl@1371
|
291 |
+ if (strcmp (part->name, avr32_part_name) == 0)
|
mgl@1371
|
292 |
+ break;
|
mgl@1371
|
293 |
+
|
mgl@1371
|
294 |
+ avr32_part = part;
|
mgl@1371
|
295 |
+ if (!part->name)
|
mgl@1371
|
296 |
+ {
|
mgl@1371
|
297 |
+ fprintf (stderr, "Unknown part `%s' specified\nKnown part names:\n",
|
mgl@1371
|
298 |
+ avr32_part_name);
|
mgl@1371
|
299 |
+ for (part = avr32_part_types; part->name; part++)
|
mgl@1371
|
300 |
+ {
|
mgl@1371
|
301 |
+ if (strcmp("none", part->name) != 0)
|
mgl@1371
|
302 |
+ fprintf (stderr, "\t%s\n", part->name);
|
mgl@1371
|
303 |
+ }
|
mgl@1371
|
304 |
+ /* Set default to NONE*/
|
mgl@1371
|
305 |
+ avr32_part = &avr32_part_types[PART_TYPE_AVR32_NONE];
|
mgl@1371
|
306 |
+ }
|
mgl@1371
|
307 |
+
|
mgl@1371
|
308 |
+ /* NB! option -march= overrides option -mpart
|
mgl@1371
|
309 |
+ * if both are used at the same time */
|
mgl@1371
|
310 |
+ if (!arch->name)
|
mgl@1371
|
311 |
+ avr32_arch = &avr32_arch_types[avr32_part->arch_type];
|
mgl@1371
|
312 |
+
|
mgl@1371
|
313 |
+ /* If optimization level is two or greater, then align start of loops to a
|
mgl@1371
|
314 |
+ word boundary since this will allow folding the first insn of the loop.
|
mgl@1371
|
315 |
+ Do this only for targets supporting branch prediction. */
|
mgl@1371
|
316 |
+ if (optimize >= 2 && TARGET_BRANCH_PRED)
|
mgl@1371
|
317 |
+ align_loops = 2;
|
mgl@1371
|
318 |
+
|
mgl@1371
|
319 |
+
|
mgl@1371
|
320 |
+ /* Enable fast-float library if unsafe math optimizations
|
mgl@1371
|
321 |
+ are used. */
|
mgl@1371
|
322 |
+ if (flag_unsafe_math_optimizations)
|
mgl@1371
|
323 |
+ target_flags |= MASK_FAST_FLOAT;
|
mgl@1371
|
324 |
+
|
mgl@1371
|
325 |
+ /* Check if we should set avr32_imm_in_const_pool
|
mgl@1371
|
326 |
+ based on if caches are present or not. */
|
mgl@1371
|
327 |
+ if ( avr32_imm_in_const_pool == -1 )
|
mgl@1371
|
328 |
+ {
|
mgl@1371
|
329 |
+ if ( TARGET_CACHES )
|
mgl@1371
|
330 |
+ avr32_imm_in_const_pool = 1;
|
mgl@1371
|
331 |
+ else
|
mgl@1371
|
332 |
+ avr32_imm_in_const_pool = 0;
|
mgl@1371
|
333 |
+ }
|
mgl@1371
|
334 |
+
|
mgl@1371
|
335 |
+ if (TARGET_NO_PIC)
|
mgl@1371
|
336 |
+ flag_pic = 0;
|
mgl@1371
|
337 |
+
|
mgl@1371
|
338 |
+ avr32_add_gc_roots ();
|
mgl@1371
|
339 |
+}
|
mgl@1371
|
340 |
+
|
mgl@1371
|
341 |
+
|
mgl@1371
|
342 |
+/*
|
mgl@1371
|
343 |
+If defined, a function that outputs the assembler code for entry to a
|
mgl@1371
|
344 |
+function. The prologue is responsible for setting up the stack frame,
|
mgl@1371
|
345 |
+initializing the frame pointer register, saving registers that must be
|
mgl@1371
|
346 |
+saved, and allocating size additional bytes of storage for the
|
mgl@1371
|
347 |
+local variables. size is an integer. file is a stdio
|
mgl@1371
|
348 |
+stream to which the assembler code should be output.
|
mgl@1371
|
349 |
+
|
mgl@1371
|
350 |
+The label for the beginning of the function need not be output by this
|
mgl@1371
|
351 |
+macro. That has already been done when the macro is run.
|
mgl@1371
|
352 |
+
|
mgl@1371
|
353 |
+To determine which registers to save, the macro can refer to the array
|
mgl@1371
|
354 |
+regs_ever_live: element r is nonzero if hard register
|
mgl@1371
|
355 |
+r is used anywhere within the function. This implies the function
|
mgl@1371
|
356 |
+prologue should save register r, provided it is not one of the
|
mgl@1371
|
357 |
+call-used registers. (TARGET_ASM_FUNCTION_EPILOGUE must likewise use
|
mgl@1371
|
358 |
+regs_ever_live.)
|
mgl@1371
|
359 |
+
|
mgl@1371
|
360 |
+On machines that have ``register windows'', the function entry code does
|
mgl@1371
|
361 |
+not save on the stack the registers that are in the windows, even if
|
mgl@1371
|
362 |
+they are supposed to be preserved by function calls; instead it takes
|
mgl@1371
|
363 |
+appropriate steps to ``push'' the register stack, if any non-call-used
|
mgl@1371
|
364 |
+registers are used in the function.
|
mgl@1371
|
365 |
+
|
mgl@1371
|
366 |
+On machines where functions may or may not have frame-pointers, the
|
mgl@1371
|
367 |
+function entry code must vary accordingly; it must set up the frame
|
mgl@1371
|
368 |
+pointer if one is wanted, and not otherwise. To determine whether a
|
mgl@1371
|
369 |
+frame pointer is in wanted, the macro can refer to the variable
|
mgl@1371
|
370 |
+frame_pointer_needed. The variable's value will be 1 at run
|
mgl@1371
|
371 |
+time in a function that needs a frame pointer. (see Elimination).
|
mgl@1371
|
372 |
+
|
mgl@1371
|
373 |
+The function entry code is responsible for allocating any stack space
|
mgl@1371
|
374 |
+required for the function. This stack space consists of the regions
|
mgl@1371
|
375 |
+listed below. In most cases, these regions are allocated in the
|
mgl@1371
|
376 |
+order listed, with the last listed region closest to the top of the
|
mgl@1371
|
377 |
+stack (the lowest address if STACK_GROWS_DOWNWARD is defined, and
|
mgl@1371
|
378 |
+the highest address if it is not defined). You can use a different order
|
mgl@1371
|
379 |
+for a machine if doing so is more convenient or required for
|
mgl@1371
|
380 |
+compatibility reasons. Except in cases where required by standard
|
mgl@1371
|
381 |
+or by a debugger, there is no reason why the stack layout used by GCC
|
mgl@1371
|
382 |
+need agree with that used by other compilers for a machine.
|
mgl@1371
|
383 |
+*/
|
mgl@1371
|
384 |
+
|
mgl@1371
|
385 |
+#undef TARGET_ASM_FUNCTION_PROLOGUE
|
mgl@1371
|
386 |
+#define TARGET_ASM_FUNCTION_PROLOGUE avr32_target_asm_function_prologue
|
mgl@1371
|
387 |
+
|
mgl@1371
|
388 |
+
|
mgl@1371
|
389 |
+#undef TARGET_DEFAULT_SHORT_ENUMS
|
mgl@1371
|
390 |
+#define TARGET_DEFAULT_SHORT_ENUMS hook_bool_void_false
|
mgl@1371
|
391 |
+
|
mgl@1371
|
392 |
+#undef TARGET_PROMOTE_FUNCTION_ARGS
|
mgl@1371
|
393 |
+#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
|
mgl@1371
|
394 |
+
|
mgl@1371
|
395 |
+#undef TARGET_PROMOTE_FUNCTION_RETURN
|
mgl@1371
|
396 |
+#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
|
mgl@1371
|
397 |
+
|
mgl@1371
|
398 |
+#undef TARGET_PROMOTE_PROTOTYPES
|
mgl@1371
|
399 |
+#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
|
mgl@1371
|
400 |
+
|
mgl@1371
|
401 |
+#undef TARGET_MUST_PASS_IN_STACK
|
mgl@1371
|
402 |
+#define TARGET_MUST_PASS_IN_STACK avr32_must_pass_in_stack
|
mgl@1371
|
403 |
+
|
mgl@1371
|
404 |
+#undef TARGET_PASS_BY_REFERENCE
|
mgl@1371
|
405 |
+#define TARGET_PASS_BY_REFERENCE avr32_pass_by_reference
|
mgl@1371
|
406 |
+
|
mgl@1371
|
407 |
+#undef TARGET_STRICT_ARGUMENT_NAMING
|
mgl@1371
|
408 |
+#define TARGET_STRICT_ARGUMENT_NAMING avr32_strict_argument_naming
|
mgl@1371
|
409 |
+
|
mgl@1371
|
410 |
+#undef TARGET_VECTOR_MODE_SUPPORTED_P
|
mgl@1371
|
411 |
+#define TARGET_VECTOR_MODE_SUPPORTED_P avr32_vector_mode_supported
|
mgl@1371
|
412 |
+
|
mgl@1371
|
413 |
+#undef TARGET_RETURN_IN_MEMORY
|
mgl@1371
|
414 |
+#define TARGET_RETURN_IN_MEMORY avr32_return_in_memory
|
mgl@1371
|
415 |
+
|
mgl@1371
|
416 |
+#undef TARGET_RETURN_IN_MSB
|
mgl@1371
|
417 |
+#define TARGET_RETURN_IN_MSB avr32_return_in_msb
|
mgl@1371
|
418 |
+
|
mgl@1371
|
419 |
+#undef TARGET_ENCODE_SECTION_INFO
|
mgl@1371
|
420 |
+#define TARGET_ENCODE_SECTION_INFO avr32_encode_section_info
|
mgl@1371
|
421 |
+
|
mgl@1371
|
422 |
+#undef TARGET_ARG_PARTIAL_BYTES
|
mgl@1371
|
423 |
+#define TARGET_ARG_PARTIAL_BYTES avr32_arg_partial_bytes
|
mgl@1371
|
424 |
+
|
mgl@1371
|
425 |
+#undef TARGET_STRIP_NAME_ENCODING
|
mgl@1371
|
426 |
+#define TARGET_STRIP_NAME_ENCODING avr32_strip_name_encoding
|
mgl@1371
|
427 |
+
|
mgl@1371
|
428 |
+#define streq(string1, string2) (strcmp (string1, string2) == 0)
|
mgl@1371
|
429 |
+
|
mgl@1371
|
430 |
+#undef TARGET_NARROW_VOLATILE_BITFIELD
|
mgl@1371
|
431 |
+#define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
|
mgl@1371
|
432 |
+
|
mgl@1371
|
433 |
+#undef TARGET_ATTRIBUTE_TABLE
|
mgl@1371
|
434 |
+#define TARGET_ATTRIBUTE_TABLE avr32_attribute_table
|
mgl@1371
|
435 |
+
|
mgl@1371
|
436 |
+#undef TARGET_COMP_TYPE_ATTRIBUTES
|
mgl@1371
|
437 |
+#define TARGET_COMP_TYPE_ATTRIBUTES avr32_comp_type_attributes
|
mgl@1371
|
438 |
+
|
mgl@1371
|
439 |
+
|
mgl@1371
|
440 |
+#undef TARGET_RTX_COSTS
|
mgl@1371
|
441 |
+#define TARGET_RTX_COSTS avr32_rtx_costs
|
mgl@1371
|
442 |
+
|
mgl@1371
|
443 |
+#undef TARGET_CANNOT_FORCE_CONST_MEM
|
mgl@1371
|
444 |
+#define TARGET_CANNOT_FORCE_CONST_MEM avr32_cannot_force_const_mem
|
mgl@1371
|
445 |
+
|
mgl@1371
|
446 |
+#undef TARGET_ASM_INTEGER
|
mgl@1371
|
447 |
+#define TARGET_ASM_INTEGER avr32_assemble_integer
|
mgl@1371
|
448 |
+
|
mgl@1371
|
449 |
+#undef TARGET_FUNCTION_VALUE
|
mgl@1371
|
450 |
+#define TARGET_FUNCTION_VALUE avr32_function_value
|
mgl@1371
|
451 |
+
|
mgl@1371
|
452 |
+#undef TARGET_MIN_ANCHOR_OFFSET
|
mgl@1371
|
453 |
+#define TARGET_MIN_ANCHOR_OFFSET (0)
|
mgl@1371
|
454 |
+
|
mgl@1371
|
455 |
+#undef TARGET_MAX_ANCHOR_OFFSET
|
mgl@1371
|
456 |
+#define TARGET_MAX_ANCHOR_OFFSET ((1 << 15) - 1)
|
mgl@1371
|
457 |
+
|
mgl@1371
|
458 |
+#undef TARGET_SECONDARY_RELOAD
|
mgl@1371
|
459 |
+#define TARGET_SECONDARY_RELOAD avr32_secondary_reload
|
mgl@1371
|
460 |
+
|
mgl@1371
|
461 |
+enum reg_class
|
mgl@1371
|
462 |
+avr32_secondary_reload (bool in_p, rtx x, enum reg_class class ATTRIBUTE_UNUSED,
|
mgl@1371
|
463 |
+ enum machine_mode mode, secondary_reload_info *sri)
|
mgl@1371
|
464 |
+{
|
mgl@1371
|
465 |
+
|
mgl@1371
|
466 |
+ if ( avr32_rmw_memory_operand (x, mode) )
|
mgl@1371
|
467 |
+ {
|
mgl@1371
|
468 |
+ if (!in_p)
|
mgl@1371
|
469 |
+ sri->icode = CODE_FOR_reload_out_rmw_memory_operand;
|
mgl@1371
|
470 |
+ else
|
mgl@1371
|
471 |
+ sri->icode = CODE_FOR_reload_in_rmw_memory_operand;
|
mgl@1371
|
472 |
+ }
|
mgl@1371
|
473 |
+ return NO_REGS;
|
mgl@1371
|
474 |
+
|
mgl@1371
|
475 |
+}
|
mgl@1371
|
476 |
+
|
mgl@1371
|
477 |
+/*
|
mgl@1371
|
478 |
+ * Switches to the appropriate section for output of constant pool
|
mgl@1371
|
479 |
+ * entry x in mode. You can assume that x is some kind of constant in
|
mgl@1371
|
480 |
+ * RTL. The argument mode is redundant except in the case of a
|
mgl@1371
|
481 |
+ * const_int rtx. Select the section by calling readonly_data_ section
|
mgl@1371
|
482 |
+ * or one of the alternatives for other sections. align is the
|
mgl@1371
|
483 |
+ * constant alignment in bits.
|
mgl@1371
|
484 |
+ *
|
mgl@1371
|
485 |
+ * The default version of this function takes care of putting symbolic
|
mgl@1371
|
486 |
+ * constants in flag_ pic mode in data_section and everything else in
|
mgl@1371
|
487 |
+ * readonly_data_section.
|
mgl@1371
|
488 |
+ */
|
mgl@1371
|
489 |
+//#undef TARGET_ASM_SELECT_RTX_SECTION
|
mgl@1371
|
490 |
+//#define TARGET_ASM_SELECT_RTX_SECTION avr32_select_rtx_section
|
mgl@1371
|
491 |
+
|
mgl@1371
|
492 |
+
|
mgl@1371
|
493 |
+/*
|
mgl@1371
|
494 |
+ * If non-null, this hook performs a target-specific pass over the
|
mgl@1371
|
495 |
+ * instruction stream. The compiler will run it at all optimization
|
mgl@1371
|
496 |
+ * levels, just before the point at which it normally does
|
mgl@1371
|
497 |
+ * delayed-branch scheduling.
|
mgl@1371
|
498 |
+ *
|
mgl@1371
|
499 |
+ * The exact purpose of the hook varies from target to target. Some
|
mgl@1371
|
500 |
+ * use it to do transformations that are necessary for correctness,
|
mgl@1371
|
501 |
+ * such as laying out in-function constant pools or avoiding hardware
|
mgl@1371
|
502 |
+ * hazards. Others use it as an opportunity to do some
|
mgl@1371
|
503 |
+ * machine-dependent optimizations.
|
mgl@1371
|
504 |
+ *
|
mgl@1371
|
505 |
+ * You need not implement the hook if it has nothing to do. The
|
mgl@1371
|
506 |
+ * default definition is null.
|
mgl@1371
|
507 |
+ */
|
mgl@1371
|
508 |
+#undef TARGET_MACHINE_DEPENDENT_REORG
|
mgl@1371
|
509 |
+#define TARGET_MACHINE_DEPENDENT_REORG avr32_reorg
|
mgl@1371
|
510 |
+
|
mgl@1371
|
511 |
+/* Target hook for assembling integer objects.
|
mgl@1371
|
512 |
+ Need to handle integer vectors */
|
mgl@1371
|
513 |
+static bool
|
mgl@1371
|
514 |
+avr32_assemble_integer (rtx x, unsigned int size, int aligned_p)
|
mgl@1371
|
515 |
+{
|
mgl@1371
|
516 |
+ if (avr32_vector_mode_supported (GET_MODE (x)))
|
mgl@1371
|
517 |
+ {
|
mgl@1371
|
518 |
+ int i, units;
|
mgl@1371
|
519 |
+
|
mgl@1371
|
520 |
+ if (GET_CODE (x) != CONST_VECTOR)
|
mgl@1371
|
521 |
+ abort ();
|
mgl@1371
|
522 |
+
|
mgl@1371
|
523 |
+ units = CONST_VECTOR_NUNITS (x);
|
mgl@1371
|
524 |
+
|
mgl@1371
|
525 |
+ switch (GET_MODE (x))
|
mgl@1371
|
526 |
+ {
|
mgl@1371
|
527 |
+ case V2HImode:
|
mgl@1371
|
528 |
+ size = 2;
|
mgl@1371
|
529 |
+ break;
|
mgl@1371
|
530 |
+ case V4QImode:
|
mgl@1371
|
531 |
+ size = 1;
|
mgl@1371
|
532 |
+ break;
|
mgl@1371
|
533 |
+ default:
|
mgl@1371
|
534 |
+ abort ();
|
mgl@1371
|
535 |
+ }
|
mgl@1371
|
536 |
+
|
mgl@1371
|
537 |
+ for (i = 0; i < units; i++)
|
mgl@1371
|
538 |
+ {
|
mgl@1371
|
539 |
+ rtx elt;
|
mgl@1371
|
540 |
+
|
mgl@1371
|
541 |
+ elt = CONST_VECTOR_ELT (x, i);
|
mgl@1371
|
542 |
+ assemble_integer (elt, size, i == 0 ? 32 : size * BITS_PER_UNIT, 1);
|
mgl@1371
|
543 |
+ }
|
mgl@1371
|
544 |
+
|
mgl@1371
|
545 |
+ return true;
|
mgl@1371
|
546 |
+ }
|
mgl@1371
|
547 |
+
|
mgl@1371
|
548 |
+ return default_assemble_integer (x, size, aligned_p);
|
mgl@1371
|
549 |
+}
|
mgl@1371
|
550 |
+
|
mgl@1371
|
551 |
+/*
|
mgl@1371
|
552 |
+ * This target hook describes the relative costs of RTL expressions.
|
mgl@1371
|
553 |
+ *
|
mgl@1371
|
554 |
+ * The cost may depend on the precise form of the expression, which is
|
mgl@1371
|
555 |
+ * available for examination in x, and the rtx code of the expression
|
mgl@1371
|
556 |
+ * in which it is contained, found in outer_code. code is the
|
mgl@1371
|
557 |
+ * expression code--redundant, since it can be obtained with GET_CODE
|
mgl@1371
|
558 |
+ * (x).
|
mgl@1371
|
559 |
+ *
|
mgl@1371
|
560 |
+ * In implementing this hook, you can use the construct COSTS_N_INSNS
|
mgl@1371
|
561 |
+ * (n) to specify a cost equal to n fast instructions.
|
mgl@1371
|
562 |
+ *
|
mgl@1371
|
563 |
+ * On entry to the hook, *total contains a default estimate for the
|
mgl@1371
|
564 |
+ * cost of the expression. The hook should modify this value as
|
mgl@1371
|
565 |
+ * necessary. Traditionally, the default costs are COSTS_N_INSNS (5)
|
mgl@1371
|
566 |
+ * for multiplications, COSTS_N_INSNS (7) for division and modulus
|
mgl@1371
|
567 |
+ * operations, and COSTS_N_INSNS (1) for all other operations.
|
mgl@1371
|
568 |
+ *
|
mgl@1371
|
569 |
+ * When optimizing for code size, i.e. when optimize_size is non-zero,
|
mgl@1371
|
570 |
+ * this target hook should be used to estimate the relative size cost
|
mgl@1371
|
571 |
+ * of an expression, again relative to COSTS_N_INSNS.
|
mgl@1371
|
572 |
+ *
|
mgl@1371
|
573 |
+ * The hook returns true when all subexpressions of x have been
|
mgl@1371
|
574 |
+ * processed, and false when rtx_cost should recurse.
|
mgl@1371
|
575 |
+ */
|
mgl@1371
|
576 |
+
|
mgl@1371
|
577 |
+/* Worker routine for avr32_rtx_costs. */
|
mgl@1371
|
578 |
+static inline int
|
mgl@1371
|
579 |
+avr32_rtx_costs_1 (rtx x, enum rtx_code code ATTRIBUTE_UNUSED,
|
mgl@1371
|
580 |
+ enum rtx_code outer ATTRIBUTE_UNUSED)
|
mgl@1371
|
581 |
+{
|
mgl@1371
|
582 |
+ enum machine_mode mode = GET_MODE (x);
|
mgl@1371
|
583 |
+
|
mgl@1371
|
584 |
+ switch (GET_CODE (x))
|
mgl@1371
|
585 |
+ {
|
mgl@1371
|
586 |
+ case MEM:
|
mgl@1371
|
587 |
+ /* Using pre decrement / post increment memory operations on the
|
mgl@1371
|
588 |
+ avr32_uc architecture means that two writebacks must be performed
|
mgl@1371
|
589 |
+ and hence two cycles are needed. */
|
mgl@1371
|
590 |
+ if (!optimize_size
|
mgl@1371
|
591 |
+ && GET_MODE_SIZE (mode) <= 2 * UNITS_PER_WORD
|
mgl@1371
|
592 |
+ && TARGET_ARCH_UC
|
mgl@1371
|
593 |
+ && (GET_CODE (XEXP (x, 0)) == PRE_DEC
|
mgl@1371
|
594 |
+ || GET_CODE (XEXP (x, 0)) == POST_INC))
|
mgl@1371
|
595 |
+ return COSTS_N_INSNS (5);
|
mgl@1371
|
596 |
+
|
mgl@1371
|
597 |
+ /* Memory costs quite a lot for the first word, but subsequent words
|
mgl@1371
|
598 |
+ load at the equivalent of a single insn each. */
|
mgl@1371
|
599 |
+ if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
|
mgl@1371
|
600 |
+ return COSTS_N_INSNS (3 + (GET_MODE_SIZE (mode) / UNITS_PER_WORD));
|
mgl@1371
|
601 |
+
|
mgl@1371
|
602 |
+ return COSTS_N_INSNS (4);
|
mgl@1371
|
603 |
+ case SYMBOL_REF:
|
mgl@1371
|
604 |
+ case CONST:
|
mgl@1371
|
605 |
+ /* These are valid for the pseudo insns: lda.w and call which operates
|
mgl@1371
|
606 |
+ on direct addresses. We assume that the cost of a lda.w is the same
|
mgl@1371
|
607 |
+ as the cost of a ld.w insn. */
|
mgl@1371
|
608 |
+ return (outer == SET) ? COSTS_N_INSNS (4) : COSTS_N_INSNS (1);
|
mgl@1371
|
609 |
+ case DIV:
|
mgl@1371
|
610 |
+ case MOD:
|
mgl@1371
|
611 |
+ case UDIV:
|
mgl@1371
|
612 |
+ case UMOD:
|
mgl@1371
|
613 |
+ return optimize_size ? COSTS_N_INSNS (1) : COSTS_N_INSNS (16);
|
mgl@1371
|
614 |
+
|
mgl@1371
|
615 |
+ case ROTATE:
|
mgl@1371
|
616 |
+ case ROTATERT:
|
mgl@1371
|
617 |
+ if (mode == TImode)
|
mgl@1371
|
618 |
+ return COSTS_N_INSNS (100);
|
mgl@1371
|
619 |
+
|
mgl@1371
|
620 |
+ if (mode == DImode)
|
mgl@1371
|
621 |
+ return COSTS_N_INSNS (10);
|
mgl@1371
|
622 |
+ return COSTS_N_INSNS (4);
|
mgl@1371
|
623 |
+ case ASHIFT:
|
mgl@1371
|
624 |
+ case LSHIFTRT:
|
mgl@1371
|
625 |
+ case ASHIFTRT:
|
mgl@1371
|
626 |
+ case NOT:
|
mgl@1371
|
627 |
+ if (mode == TImode)
|
mgl@1371
|
628 |
+ return COSTS_N_INSNS (10);
|
mgl@1371
|
629 |
+
|
mgl@1371
|
630 |
+ if (mode == DImode)
|
mgl@1371
|
631 |
+ return COSTS_N_INSNS (4);
|
mgl@1371
|
632 |
+ return COSTS_N_INSNS (1);
|
mgl@1371
|
633 |
+ case PLUS:
|
mgl@1371
|
634 |
+ case MINUS:
|
mgl@1371
|
635 |
+ case NEG:
|
mgl@1371
|
636 |
+ case COMPARE:
|
mgl@1371
|
637 |
+ case ABS:
|
mgl@1371
|
638 |
+ if (GET_MODE_CLASS (mode) == MODE_FLOAT)
|
mgl@1371
|
639 |
+ return COSTS_N_INSNS (100);
|
mgl@1371
|
640 |
+
|
mgl@1371
|
641 |
+ if (mode == TImode)
|
mgl@1371
|
642 |
+ return COSTS_N_INSNS (50);
|
mgl@1371
|
643 |
+
|
mgl@1371
|
644 |
+ if (mode == DImode)
|
mgl@1371
|
645 |
+ return COSTS_N_INSNS (2);
|
mgl@1371
|
646 |
+ return COSTS_N_INSNS (1);
|
mgl@1371
|
647 |
+
|
mgl@1371
|
648 |
+ case MULT:
|
mgl@1371
|
649 |
+ {
|
mgl@1371
|
650 |
+ if (GET_MODE_CLASS (mode) == MODE_FLOAT)
|
mgl@1371
|
651 |
+ return COSTS_N_INSNS (300);
|
mgl@1371
|
652 |
+
|
mgl@1371
|
653 |
+ if (mode == TImode)
|
mgl@1371
|
654 |
+ return COSTS_N_INSNS (16);
|
mgl@1371
|
655 |
+
|
mgl@1371
|
656 |
+ if (mode == DImode)
|
mgl@1371
|
657 |
+ return COSTS_N_INSNS (4);
|
mgl@1371
|
658 |
+
|
mgl@1371
|
659 |
+ if (mode == HImode)
|
mgl@1371
|
660 |
+ return COSTS_N_INSNS (2);
|
mgl@1371
|
661 |
+
|
mgl@1371
|
662 |
+ return COSTS_N_INSNS (3);
|
mgl@1371
|
663 |
+ }
|
mgl@1371
|
664 |
+ case IF_THEN_ELSE:
|
mgl@1371
|
665 |
+ if (GET_CODE (XEXP (x, 1)) == PC || GET_CODE (XEXP (x, 2)) == PC)
|
mgl@1371
|
666 |
+ return COSTS_N_INSNS (4);
|
mgl@1371
|
667 |
+ return COSTS_N_INSNS (1);
|
mgl@1371
|
668 |
+ case SIGN_EXTEND:
|
mgl@1371
|
669 |
+ case ZERO_EXTEND:
|
mgl@1371
|
670 |
+ /* Sign/Zero extensions of registers cost quite much since these
|
mgl@1371
|
671 |
+ instrcutions only take one register operand which means that gcc
|
mgl@1371
|
672 |
+ often must insert some move instrcutions */
|
mgl@1371
|
673 |
+ if (mode == QImode || mode == HImode)
|
mgl@1371
|
674 |
+ return (COSTS_N_INSNS (GET_CODE (XEXP (x, 0)) == MEM ? 0 : 1));
|
mgl@1371
|
675 |
+ return COSTS_N_INSNS (4);
|
mgl@1371
|
676 |
+ case UNSPEC:
|
mgl@1371
|
677 |
+ /* divmod operations */
|
mgl@1371
|
678 |
+ if (XINT (x, 1) == UNSPEC_UDIVMODSI4_INTERNAL
|
mgl@1371
|
679 |
+ || XINT (x, 1) == UNSPEC_DIVMODSI4_INTERNAL)
|
mgl@1371
|
680 |
+ {
|
mgl@1371
|
681 |
+ return optimize_size ? COSTS_N_INSNS (1) : COSTS_N_INSNS (16);
|
mgl@1371
|
682 |
+ }
|
mgl@1371
|
683 |
+ /* Fallthrough */
|
mgl@1371
|
684 |
+ default:
|
mgl@1371
|
685 |
+ return COSTS_N_INSNS (1);
|
mgl@1371
|
686 |
+ }
|
mgl@1371
|
687 |
+}
|
mgl@1371
|
688 |
+
|
mgl@1371
|
689 |
+static bool
|
mgl@1371
|
690 |
+avr32_rtx_costs (rtx x, int code, int outer_code, int *total)
|
mgl@1371
|
691 |
+{
|
mgl@1371
|
692 |
+ *total = avr32_rtx_costs_1 (x, code, outer_code);
|
mgl@1371
|
693 |
+ return true;
|
mgl@1371
|
694 |
+}
|
mgl@1371
|
695 |
+
|
mgl@1371
|
696 |
+
|
mgl@1371
|
697 |
+bool
|
mgl@1371
|
698 |
+avr32_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
|
mgl@1371
|
699 |
+{
|
mgl@1371
|
700 |
+ /* Do not want symbols in the constant pool when compiling pic or if using
|
mgl@1371
|
701 |
+ address pseudo instructions. */
|
mgl@1371
|
702 |
+ return ((flag_pic || TARGET_HAS_ASM_ADDR_PSEUDOS)
|
mgl@1371
|
703 |
+ && avr32_find_symbol (x) != NULL_RTX);
|
mgl@1371
|
704 |
+}
|
mgl@1371
|
705 |
+
|
mgl@1371
|
706 |
+
|
mgl@1371
|
707 |
+/* Table of machine attributes. */
|
mgl@1371
|
708 |
+const struct attribute_spec avr32_attribute_table[] = {
|
mgl@1371
|
709 |
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
|
mgl@1371
|
710 |
+ /* Interrupt Service Routines have special prologue and epilogue
|
mgl@1371
|
711 |
+ requirements. */
|
mgl@1371
|
712 |
+ {"isr", 0, 1, false, false, false, avr32_handle_isr_attribute},
|
mgl@1371
|
713 |
+ {"interrupt", 0, 1, false, false, false, avr32_handle_isr_attribute},
|
mgl@1371
|
714 |
+ {"acall", 0, 1, false, true, true, avr32_handle_acall_attribute},
|
mgl@1371
|
715 |
+ {"naked", 0, 0, true, false, false, avr32_handle_fndecl_attribute},
|
mgl@1371
|
716 |
+ {"rmw_addressable", 0, 0, true, false, false, NULL},
|
mgl@1371
|
717 |
+ {NULL, 0, 0, false, false, false, NULL}
|
mgl@1371
|
718 |
+};
|
mgl@1371
|
719 |
+
|
mgl@1371
|
720 |
+
|
mgl@1371
|
721 |
+typedef struct
|
mgl@1371
|
722 |
+{
|
mgl@1371
|
723 |
+ const char *const arg;
|
mgl@1371
|
724 |
+ const unsigned long return_value;
|
mgl@1371
|
725 |
+}
|
mgl@1371
|
726 |
+isr_attribute_arg;
|
mgl@1371
|
727 |
+
|
mgl@1371
|
728 |
+static const isr_attribute_arg isr_attribute_args[] = {
|
mgl@1371
|
729 |
+ {"FULL", AVR32_FT_ISR_FULL},
|
mgl@1371
|
730 |
+ {"full", AVR32_FT_ISR_FULL},
|
mgl@1371
|
731 |
+ {"HALF", AVR32_FT_ISR_HALF},
|
mgl@1371
|
732 |
+ {"half", AVR32_FT_ISR_HALF},
|
mgl@1371
|
733 |
+ {"NONE", AVR32_FT_ISR_NONE},
|
mgl@1371
|
734 |
+ {"none", AVR32_FT_ISR_NONE},
|
mgl@1371
|
735 |
+ {"UNDEF", AVR32_FT_ISR_NONE},
|
mgl@1371
|
736 |
+ {"undef", AVR32_FT_ISR_NONE},
|
mgl@1371
|
737 |
+ {"SWI", AVR32_FT_ISR_NONE},
|
mgl@1371
|
738 |
+ {"swi", AVR32_FT_ISR_NONE},
|
mgl@1371
|
739 |
+ {NULL, AVR32_FT_ISR_NONE}
|
mgl@1371
|
740 |
+};
|
mgl@1371
|
741 |
+
|
mgl@1371
|
742 |
+/* Returns the (interrupt) function type of the current
|
mgl@1371
|
743 |
+ function, or AVR32_FT_UNKNOWN if the type cannot be determined. */
|
mgl@1371
|
744 |
+
|
mgl@1371
|
745 |
+static unsigned long
|
mgl@1371
|
746 |
+avr32_isr_value (tree argument)
|
mgl@1371
|
747 |
+{
|
mgl@1371
|
748 |
+ const isr_attribute_arg *ptr;
|
mgl@1371
|
749 |
+ const char *arg;
|
mgl@1371
|
750 |
+
|
mgl@1371
|
751 |
+ /* No argument - default to ISR_NONE. */
|
mgl@1371
|
752 |
+ if (argument == NULL_TREE)
|
mgl@1371
|
753 |
+ return AVR32_FT_ISR_NONE;
|
mgl@1371
|
754 |
+
|
mgl@1371
|
755 |
+ /* Get the value of the argument. */
|
mgl@1371
|
756 |
+ if (TREE_VALUE (argument) == NULL_TREE
|
mgl@1371
|
757 |
+ || TREE_CODE (TREE_VALUE (argument)) != STRING_CST)
|
mgl@1371
|
758 |
+ return AVR32_FT_UNKNOWN;
|
mgl@1371
|
759 |
+
|
mgl@1371
|
760 |
+ arg = TREE_STRING_POINTER (TREE_VALUE (argument));
|
mgl@1371
|
761 |
+
|
mgl@1371
|
762 |
+ /* Check it against the list of known arguments. */
|
mgl@1371
|
763 |
+ for (ptr = isr_attribute_args; ptr->arg != NULL; ptr++)
|
mgl@1371
|
764 |
+ if (streq (arg, ptr->arg))
|
mgl@1371
|
765 |
+ return ptr->return_value;
|
mgl@1371
|
766 |
+
|
mgl@1371
|
767 |
+ /* An unrecognized interrupt type. */
|
mgl@1371
|
768 |
+ return AVR32_FT_UNKNOWN;
|
mgl@1371
|
769 |
+}
|
mgl@1371
|
770 |
+
|
mgl@1371
|
771 |
+
|
mgl@1371
|
772 |
+
|
mgl@1371
|
773 |
+/*
|
mgl@1371
|
774 |
+These hooks specify assembly directives for creating certain kinds
|
mgl@1371
|
775 |
+of integer object. The TARGET_ASM_BYTE_OP directive creates a
|
mgl@1371
|
776 |
+byte-sized object, the TARGET_ASM_ALIGNED_HI_OP one creates an
|
mgl@1371
|
777 |
+aligned two-byte object, and so on. Any of the hooks may be
|
mgl@1371
|
778 |
+NULL, indicating that no suitable directive is available.
|
mgl@1371
|
779 |
+
|
mgl@1371
|
780 |
+The compiler will print these strings at the start of a new line,
|
mgl@1371
|
781 |
+followed immediately by the object's initial value. In most cases,
|
mgl@1371
|
782 |
+the string should contain a tab, a pseudo-op, and then another tab.
|
mgl@1371
|
783 |
+*/
|
mgl@1371
|
784 |
+#undef TARGET_ASM_BYTE_OP
|
mgl@1371
|
785 |
+#define TARGET_ASM_BYTE_OP "\t.byte\t"
|
mgl@1371
|
786 |
+#undef TARGET_ASM_ALIGNED_HI_OP
|
mgl@1371
|
787 |
+#define TARGET_ASM_ALIGNED_HI_OP "\t.align 1\n\t.short\t"
|
mgl@1371
|
788 |
+#undef TARGET_ASM_ALIGNED_SI_OP
|
mgl@1371
|
789 |
+#define TARGET_ASM_ALIGNED_SI_OP "\t.align 2\n\t.int\t"
|
mgl@1371
|
790 |
+#undef TARGET_ASM_ALIGNED_DI_OP
|
mgl@1371
|
791 |
+#define TARGET_ASM_ALIGNED_DI_OP NULL
|
mgl@1371
|
792 |
+#undef TARGET_ASM_ALIGNED_TI_OP
|
mgl@1371
|
793 |
+#define TARGET_ASM_ALIGNED_TI_OP NULL
|
mgl@1371
|
794 |
+#undef TARGET_ASM_UNALIGNED_HI_OP
|
mgl@1371
|
795 |
+#define TARGET_ASM_UNALIGNED_HI_OP "\t.short\t"
|
mgl@1371
|
796 |
+#undef TARGET_ASM_UNALIGNED_SI_OP
|
mgl@1371
|
797 |
+#define TARGET_ASM_UNALIGNED_SI_OP "\t.int\t"
|
mgl@1371
|
798 |
+#undef TARGET_ASM_UNALIGNED_DI_OP
|
mgl@1371
|
799 |
+#define TARGET_ASM_UNALIGNED_DI_OP NULL
|
mgl@1371
|
800 |
+#undef TARGET_ASM_UNALIGNED_TI_OP
|
mgl@1371
|
801 |
+#define TARGET_ASM_UNALIGNED_TI_OP NULL
|
mgl@1371
|
802 |
+
|
mgl@1371
|
803 |
+#undef TARGET_ASM_OUTPUT_MI_THUNK
|
mgl@1371
|
804 |
+#define TARGET_ASM_OUTPUT_MI_THUNK avr32_output_mi_thunk
|
mgl@1371
|
805 |
+
|
mgl@1371
|
806 |
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
|
mgl@1371
|
807 |
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
|
mgl@1371
|
808 |
+
|
mgl@1371
|
809 |
+static void
|
mgl@1371
|
810 |
+avr32_output_mi_thunk (FILE * file,
|
mgl@1371
|
811 |
+ tree thunk ATTRIBUTE_UNUSED,
|
mgl@1371
|
812 |
+ HOST_WIDE_INT delta,
|
mgl@1371
|
813 |
+ HOST_WIDE_INT vcall_offset, tree function)
|
mgl@1371
|
814 |
+ {
|
mgl@1371
|
815 |
+ int mi_delta = delta;
|
mgl@1371
|
816 |
+ int this_regno =
|
mgl@1371
|
817 |
+ (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function) ?
|
mgl@1371
|
818 |
+ INTERNAL_REGNUM (11) : INTERNAL_REGNUM (12));
|
mgl@1371
|
819 |
+
|
mgl@1371
|
820 |
+
|
mgl@1371
|
821 |
+ if (!avr32_const_ok_for_constraint_p (mi_delta, 'I', "Is21")
|
mgl@1371
|
822 |
+ || vcall_offset)
|
mgl@1371
|
823 |
+ {
|
mgl@1371
|
824 |
+ fputs ("\tpushm\tlr\n", file);
|
mgl@1371
|
825 |
+ }
|
mgl@1371
|
826 |
+
|
mgl@1371
|
827 |
+
|
mgl@1371
|
828 |
+ if (mi_delta != 0)
|
mgl@1371
|
829 |
+ {
|
mgl@1371
|
830 |
+ if (avr32_const_ok_for_constraint_p (mi_delta, 'I', "Is21"))
|
mgl@1371
|
831 |
+ {
|
mgl@1371
|
832 |
+ fprintf (file, "\tsub\t%s, %d\n", reg_names[this_regno], -mi_delta);
|
mgl@1371
|
833 |
+ }
|
mgl@1371
|
834 |
+ else
|
mgl@1371
|
835 |
+ {
|
mgl@1371
|
836 |
+ /* Immediate is larger than k21 we must make us a temp register by
|
mgl@1371
|
837 |
+ pushing a register to the stack. */
|
mgl@1371
|
838 |
+ fprintf (file, "\tmov\tlr, lo(%d)\n", mi_delta);
|
mgl@1371
|
839 |
+ fprintf (file, "\torh\tlr, hi(%d)\n", mi_delta);
|
mgl@1371
|
840 |
+ fprintf (file, "\tadd\t%s, lr\n", reg_names[this_regno]);
|
mgl@1371
|
841 |
+ }
|
mgl@1371
|
842 |
+ }
|
mgl@1371
|
843 |
+
|
mgl@1371
|
844 |
+
|
mgl@1371
|
845 |
+ if (vcall_offset != 0)
|
mgl@1371
|
846 |
+ {
|
mgl@1371
|
847 |
+ fprintf (file, "\tld.w\tlr, %s[0]\n", reg_names[this_regno]);
|
mgl@1371
|
848 |
+ fprintf (file, "\tld.w\tlr, lr[%i]\n", (int) vcall_offset);
|
mgl@1371
|
849 |
+ fprintf (file, "\tadd\t%s, lr\n", reg_names[this_regno]);
|
mgl@1371
|
850 |
+ }
|
mgl@1371
|
851 |
+
|
mgl@1371
|
852 |
+
|
mgl@1371
|
853 |
+ if (!avr32_const_ok_for_constraint_p (mi_delta, 'I', "Is21")
|
mgl@1371
|
854 |
+ || vcall_offset)
|
mgl@1371
|
855 |
+ {
|
mgl@1371
|
856 |
+ fputs ("\tpopm\tlr\n", file);
|
mgl@1371
|
857 |
+ }
|
mgl@1371
|
858 |
+
|
mgl@1371
|
859 |
+ /* Jump to the function. We assume that we can use an rjmp since the
|
mgl@1371
|
860 |
+ function to jump to is local and probably not too far away from
|
mgl@1371
|
861 |
+ the thunk. If this assumption proves to be wrong we could implement
|
mgl@1371
|
862 |
+ this jump by calculating the offset between the jump source and destination
|
mgl@1371
|
863 |
+ and put this in the constant pool and then perform an add to pc.
|
mgl@1371
|
864 |
+ This would also be legitimate PIC code. But for now we hope that an rjmp
|
mgl@1371
|
865 |
+ will be sufficient...
|
mgl@1371
|
866 |
+ */
|
mgl@1371
|
867 |
+ fputs ("\trjmp\t", file);
|
mgl@1371
|
868 |
+ assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
|
mgl@1371
|
869 |
+ fputc ('\n', file);
|
mgl@1371
|
870 |
+ }
|
mgl@1371
|
871 |
+
|
mgl@1371
|
872 |
+
|
mgl@1371
|
873 |
+/* Implements target hook vector_mode_supported. */
|
mgl@1371
|
874 |
+bool
|
mgl@1371
|
875 |
+avr32_vector_mode_supported (enum machine_mode mode)
|
mgl@1371
|
876 |
+{
|
mgl@1371
|
877 |
+ if ((mode == V2HImode) || (mode == V4QImode))
|
mgl@1371
|
878 |
+ return true;
|
mgl@1371
|
879 |
+
|
mgl@1371
|
880 |
+ return false;
|
mgl@1371
|
881 |
+}
|
mgl@1371
|
882 |
+
|
mgl@1371
|
883 |
+
|
mgl@1371
|
884 |
+#undef TARGET_INIT_LIBFUNCS
|
mgl@1371
|
885 |
+#define TARGET_INIT_LIBFUNCS avr32_init_libfuncs
|
mgl@1371
|
886 |
+
|
mgl@1371
|
887 |
+#undef TARGET_INIT_BUILTINS
|
mgl@1371
|
888 |
+#define TARGET_INIT_BUILTINS avr32_init_builtins
|
mgl@1371
|
889 |
+
|
mgl@1371
|
890 |
+#undef TARGET_EXPAND_BUILTIN
|
mgl@1371
|
891 |
+#define TARGET_EXPAND_BUILTIN avr32_expand_builtin
|
mgl@1371
|
892 |
+
|
mgl@1371
|
893 |
+tree int_ftype_int, int_ftype_void, short_ftype_short, void_ftype_int_int,
|
mgl@1371
|
894 |
+ void_ftype_ptr_int;
|
mgl@1371
|
895 |
+tree void_ftype_int, void_ftype_void, int_ftype_ptr_int;
|
mgl@1371
|
896 |
+tree short_ftype_short, int_ftype_int_short, int_ftype_short_short,
|
mgl@1371
|
897 |
+ short_ftype_short_short;
|
mgl@1371
|
898 |
+tree int_ftype_int_int, longlong_ftype_int_short, longlong_ftype_short_short;
|
mgl@1371
|
899 |
+tree void_ftype_int_int_int_int_int, void_ftype_int_int_int;
|
mgl@1371
|
900 |
+tree longlong_ftype_int_int, void_ftype_int_int_longlong;
|
mgl@1371
|
901 |
+tree int_ftype_int_int_int, longlong_ftype_longlong_int_short;
|
mgl@1371
|
902 |
+tree longlong_ftype_longlong_short_short, int_ftype_int_short_short;
|
mgl@1371
|
903 |
+
|
mgl@1371
|
904 |
+#define def_builtin(NAME, TYPE, CODE) \
|
mgl@1371
|
905 |
+ lang_hooks.builtin_function ((NAME), (TYPE), (CODE), \
|
mgl@1371
|
906 |
+ BUILT_IN_MD, NULL, NULL_TREE)
|
mgl@1371
|
907 |
+
|
mgl@1371
|
908 |
+#define def_mbuiltin(MASK, NAME, TYPE, CODE) \
|
mgl@1371
|
909 |
+ do \
|
mgl@1371
|
910 |
+ { \
|
mgl@1371
|
911 |
+ if ((MASK)) \
|
mgl@1371
|
912 |
+ lang_hooks.builtin_function ((NAME), (TYPE), (CODE), \
|
mgl@1371
|
913 |
+ BUILT_IN_MD, NULL, NULL_TREE); \
|
mgl@1371
|
914 |
+ } \
|
mgl@1371
|
915 |
+ while (0)
|
mgl@1371
|
916 |
+
|
mgl@1371
|
917 |
+struct builtin_description
|
mgl@1371
|
918 |
+{
|
mgl@1371
|
919 |
+ const unsigned int mask;
|
mgl@1371
|
920 |
+ const enum insn_code icode;
|
mgl@1371
|
921 |
+ const char *const name;
|
mgl@1371
|
922 |
+ const int code;
|
mgl@1371
|
923 |
+ const enum rtx_code comparison;
|
mgl@1371
|
924 |
+ const unsigned int flag;
|
mgl@1371
|
925 |
+ const tree *ftype;
|
mgl@1371
|
926 |
+};
|
mgl@1371
|
927 |
+
|
mgl@1371
|
928 |
+static const struct builtin_description bdesc_2arg[] = {
|
mgl@1371
|
929 |
+#define DSP_BUILTIN(code, builtin, ftype) \
|
mgl@1371
|
930 |
+ { 1, CODE_FOR_##code, "__builtin_" #code , \
|
mgl@1371
|
931 |
+ AVR32_BUILTIN_##builtin, 0, 0, ftype }
|
mgl@1371
|
932 |
+
|
mgl@1371
|
933 |
+ DSP_BUILTIN (mulsathh_h, MULSATHH_H, &short_ftype_short_short),
|
mgl@1371
|
934 |
+ DSP_BUILTIN (mulsathh_w, MULSATHH_W, &int_ftype_short_short),
|
mgl@1371
|
935 |
+ DSP_BUILTIN (mulsatrndhh_h, MULSATRNDHH_H, &short_ftype_short_short),
|
mgl@1371
|
936 |
+ DSP_BUILTIN (mulsatrndwh_w, MULSATRNDWH_W, &int_ftype_int_short),
|
mgl@1371
|
937 |
+ DSP_BUILTIN (mulsatwh_w, MULSATWH_W, &int_ftype_int_short),
|
mgl@1371
|
938 |
+ DSP_BUILTIN (satadd_h, SATADD_H, &short_ftype_short_short),
|
mgl@1371
|
939 |
+ DSP_BUILTIN (satsub_h, SATSUB_H, &short_ftype_short_short),
|
mgl@1371
|
940 |
+ DSP_BUILTIN (satadd_w, SATADD_W, &int_ftype_int_int),
|
mgl@1371
|
941 |
+ DSP_BUILTIN (satsub_w, SATSUB_W, &int_ftype_int_int),
|
mgl@1371
|
942 |
+ DSP_BUILTIN (mulwh_d, MULWH_D, &longlong_ftype_int_short),
|
mgl@1371
|
943 |
+ DSP_BUILTIN (mulnwh_d, MULNWH_D, &longlong_ftype_int_short)
|
mgl@1371
|
944 |
+};
|
mgl@1371
|
945 |
+
|
mgl@1371
|
946 |
+
|
mgl@1371
|
947 |
+void
|
mgl@1371
|
948 |
+avr32_init_builtins (void)
|
mgl@1371
|
949 |
+{
|
mgl@1371
|
950 |
+ unsigned int i;
|
mgl@1371
|
951 |
+ const struct builtin_description *d;
|
mgl@1371
|
952 |
+ tree endlink = void_list_node;
|
mgl@1371
|
953 |
+ tree int_endlink = tree_cons (NULL_TREE, integer_type_node, endlink);
|
mgl@1371
|
954 |
+ tree longlong_endlink =
|
mgl@1371
|
955 |
+ tree_cons (NULL_TREE, long_long_integer_type_node, endlink);
|
mgl@1371
|
956 |
+ tree short_endlink =
|
mgl@1371
|
957 |
+ tree_cons (NULL_TREE, short_integer_type_node, endlink);
|
mgl@1371
|
958 |
+ tree void_endlink = tree_cons (NULL_TREE, void_type_node, endlink);
|
mgl@1371
|
959 |
+
|
mgl@1371
|
960 |
+ /* int func (int) */
|
mgl@1371
|
961 |
+ int_ftype_int = build_function_type (integer_type_node, int_endlink);
|
mgl@1371
|
962 |
+
|
mgl@1371
|
963 |
+ /* short func (short) */
|
mgl@1371
|
964 |
+ short_ftype_short
|
mgl@1371
|
965 |
+ = build_function_type (short_integer_type_node, short_endlink);
|
mgl@1371
|
966 |
+
|
mgl@1371
|
967 |
+ /* short func (short, short) */
|
mgl@1371
|
968 |
+ short_ftype_short_short
|
mgl@1371
|
969 |
+ = build_function_type (short_integer_type_node,
|
mgl@1371
|
970 |
+ tree_cons (NULL_TREE, short_integer_type_node,
|
mgl@1371
|
971 |
+ short_endlink));
|
mgl@1371
|
972 |
+
|
mgl@1371
|
973 |
+ /* long long func (long long, short, short) */
|
mgl@1371
|
974 |
+ longlong_ftype_longlong_short_short
|
mgl@1371
|
975 |
+ = build_function_type (long_long_integer_type_node,
|
mgl@1371
|
976 |
+ tree_cons (NULL_TREE, long_long_integer_type_node,
|
mgl@1371
|
977 |
+ tree_cons (NULL_TREE,
|
mgl@1371
|
978 |
+ short_integer_type_node,
|
mgl@1371
|
979 |
+ short_endlink)));
|
mgl@1371
|
980 |
+
|
mgl@1371
|
981 |
+ /* long long func (short, short) */
|
mgl@1371
|
982 |
+ longlong_ftype_short_short
|
mgl@1371
|
983 |
+ = build_function_type (long_long_integer_type_node,
|
mgl@1371
|
984 |
+ tree_cons (NULL_TREE, short_integer_type_node,
|
mgl@1371
|
985 |
+ short_endlink));
|
mgl@1371
|
986 |
+
|
mgl@1371
|
987 |
+ /* int func (int, int) */
|
mgl@1371
|
988 |
+ int_ftype_int_int
|
mgl@1371
|
989 |
+ = build_function_type (integer_type_node,
|
mgl@1371
|
990 |
+ tree_cons (NULL_TREE, integer_type_node,
|
mgl@1371
|
991 |
+ int_endlink));
|
mgl@1371
|
992 |
+
|
mgl@1371
|
993 |
+ /* long long func (int, int) */
|
mgl@1371
|
994 |
+ longlong_ftype_int_int
|
mgl@1371
|
995 |
+ = build_function_type (long_long_integer_type_node,
|
mgl@1371
|
996 |
+ tree_cons (NULL_TREE, integer_type_node,
|
mgl@1371
|
997 |
+ int_endlink));
|
mgl@1371
|
998 |
+
|
mgl@1371
|
999 |
+ /* long long int func (long long, int, short) */
|
mgl@1371
|
1000 |
+ longlong_ftype_longlong_int_short
|
mgl@1371
|
1001 |
+ = build_function_type (long_long_integer_type_node,
|
mgl@1371
|
1002 |
+ tree_cons (NULL_TREE, long_long_integer_type_node,
|
mgl@1371
|
1003 |
+ tree_cons (NULL_TREE, integer_type_node,
|
mgl@1371
|
1004 |
+ short_endlink)));
|
mgl@1371
|
1005 |
+
|
mgl@1371
|
1006 |
+ /* long long int func (int, short) */
|
mgl@1371
|
1007 |
+ longlong_ftype_int_short
|
mgl@1371
|
1008 |
+ = build_function_type (long_long_integer_type_node,
|
mgl@1371
|
1009 |
+ tree_cons (NULL_TREE, integer_type_node,
|
mgl@1371
|
1010 |
+ short_endlink));
|
mgl@1371
|
1011 |
+
|
mgl@1371
|
1012 |
+ /* int func (int, short, short) */
|
mgl@1371
|
1013 |
+ int_ftype_int_short_short
|
mgl@1371
|
1014 |
+ = build_function_type (integer_type_node,
|
mgl@1371
|
1015 |
+ tree_cons (NULL_TREE, integer_type_node,
|
mgl@1371
|
1016 |
+ tree_cons (NULL_TREE,
|
mgl@1371
|
1017 |
+ short_integer_type_node,
|
mgl@1371
|
1018 |
+ short_endlink)));
|
mgl@1371
|
1019 |
+
|
mgl@1371
|
1020 |
+ /* int func (short, short) */
|
mgl@1371
|
1021 |
+ int_ftype_short_short
|
mgl@1371
|
1022 |
+ = build_function_type (integer_type_node,
|
mgl@1371
|
1023 |
+ tree_cons (NULL_TREE, short_integer_type_node,
|
mgl@1371
|
1024 |
+ short_endlink));
|
mgl@1371
|
1025 |
+
|
mgl@1371
|
1026 |
+ /* int func (int, short) */
|
mgl@1371
|
1027 |
+ int_ftype_int_short
|
mgl@1371
|
1028 |
+ = build_function_type (integer_type_node,
|
mgl@1371
|
1029 |
+ tree_cons (NULL_TREE, integer_type_node,
|
mgl@1371
|
1030 |
+ short_endlink));
|
mgl@1371
|
1031 |
+
|
mgl@1371
|
1032 |
+ /* void func (int, int) */
|
mgl@1371
|
1033 |
+ void_ftype_int_int
|
mgl@1371
|
1034 |
+ = build_function_type (void_type_node,
|
mgl@1371
|
1035 |
+ tree_cons (NULL_TREE, integer_type_node,
|
mgl@1371
|
1036 |
+ int_endlink));
|
mgl@1371
|
1037 |
+
|
mgl@1371
|
1038 |
+ /* void func (int, int, int) */
|
mgl@1371
|
1039 |
+ void_ftype_int_int_int
|
mgl@1371
|
1040 |
+ = build_function_type (void_type_node,
|
mgl@1371
|
1041 |
+ tree_cons (NULL_TREE, integer_type_node,
|
mgl@1371
|
1042 |
+ tree_cons (NULL_TREE, integer_type_node,
|
mgl@1371
|
1043 |
+ int_endlink)));
|
mgl@1371
|
1044 |
+
|
mgl@1371
|
1045 |
+ /* void func (int, int, long long) */
|
mgl@1371
|
1046 |
+ void_ftype_int_int_longlong
|
mgl@1371
|
1047 |
+ = build_function_type (void_type_node,
|
mgl@1371
|
1048 |
+ tree_cons (NULL_TREE, integer_type_node,
|
mgl@1371
|
1049 |
+ tree_cons (NULL_TREE, integer_type_node,
|
mgl@1371
|
1050 |
+ longlong_endlink)));
|
mgl@1371
|
1051 |
+
|
mgl@1371
|
1052 |
+ /* void func (int, int, int, int, int) */
|
mgl@1371
|
1053 |
+ void_ftype_int_int_int_int_int
|
mgl@1371
|
1054 |
+ = build_function_type (void_type_node,
|
mgl@1371
|
1055 |
+ tree_cons (NULL_TREE, integer_type_node,
|
mgl@1371
|
1056 |
+ tree_cons (NULL_TREE, integer_type_node,
|
mgl@1371
|
1057 |
+ tree_cons (NULL_TREE,
|
mgl@1371
|
1058 |
+ integer_type_node,
|
mgl@1371
|
1059 |
+ tree_cons
|
mgl@1371
|
1060 |
+ (NULL_TREE,
|
mgl@1371
|
1061 |
+ integer_type_node,
|
mgl@1371
|
1062 |
+ int_endlink)))));
|
mgl@1371
|
1063 |
+
|
mgl@1371
|
1064 |
+ /* void func (void *, int) */
|
mgl@1371
|
1065 |
+ void_ftype_ptr_int
|
mgl@1371
|
1066 |
+ = build_function_type (void_type_node,
|
mgl@1371
|
1067 |
+ tree_cons (NULL_TREE, ptr_type_node, int_endlink));
|
mgl@1371
|
1068 |
+
|
mgl@1371
|
1069 |
+ /* void func (int) */
|
mgl@1371
|
1070 |
+ void_ftype_int = build_function_type (void_type_node, int_endlink);
|
mgl@1371
|
1071 |
+
|
mgl@1371
|
1072 |
+ /* void func (void) */
|
mgl@1371
|
1073 |
+ void_ftype_void = build_function_type (void_type_node, void_endlink);
|
mgl@1371
|
1074 |
+
|
mgl@1371
|
1075 |
+ /* int func (void) */
|
mgl@1371
|
1076 |
+ int_ftype_void = build_function_type (integer_type_node, void_endlink);
|
mgl@1371
|
1077 |
+
|
mgl@1371
|
1078 |
+ /* int func (void *, int) */
|
mgl@1371
|
1079 |
+ int_ftype_ptr_int
|
mgl@1371
|
1080 |
+ = build_function_type (integer_type_node,
|
mgl@1371
|
1081 |
+ tree_cons (NULL_TREE, ptr_type_node, int_endlink));
|
mgl@1371
|
1082 |
+
|
mgl@1371
|
1083 |
+ /* int func (int, int, int) */
|
mgl@1371
|
1084 |
+ int_ftype_int_int_int
|
mgl@1371
|
1085 |
+ = build_function_type (integer_type_node,
|
mgl@1371
|
1086 |
+ tree_cons (NULL_TREE, integer_type_node,
|
mgl@1371
|
1087 |
+ tree_cons (NULL_TREE, integer_type_node,
|
mgl@1371
|
1088 |
+ int_endlink)));
|
mgl@1371
|
1089 |
+
|
mgl@1371
|
1090 |
+ /* Initialize avr32 builtins. */
|
mgl@1371
|
1091 |
+ def_builtin ("__builtin_mfsr", int_ftype_int, AVR32_BUILTIN_MFSR);
|
mgl@1371
|
1092 |
+ def_builtin ("__builtin_mtsr", void_ftype_int_int, AVR32_BUILTIN_MTSR);
|
mgl@1371
|
1093 |
+ def_builtin ("__builtin_mfdr", int_ftype_int, AVR32_BUILTIN_MFDR);
|
mgl@1371
|
1094 |
+ def_builtin ("__builtin_mtdr", void_ftype_int_int, AVR32_BUILTIN_MTDR);
|
mgl@1371
|
1095 |
+ def_builtin ("__builtin_cache", void_ftype_ptr_int, AVR32_BUILTIN_CACHE);
|
mgl@1371
|
1096 |
+ def_builtin ("__builtin_sync", void_ftype_int, AVR32_BUILTIN_SYNC);
|
mgl@1371
|
1097 |
+ def_builtin ("__builtin_ssrf", void_ftype_int, AVR32_BUILTIN_SSRF);
|
mgl@1371
|
1098 |
+ def_builtin ("__builtin_csrf", void_ftype_int, AVR32_BUILTIN_CSRF);
|
mgl@1371
|
1099 |
+ def_builtin ("__builtin_tlbr", void_ftype_void, AVR32_BUILTIN_TLBR);
|
mgl@1371
|
1100 |
+ def_builtin ("__builtin_tlbs", void_ftype_void, AVR32_BUILTIN_TLBS);
|
mgl@1371
|
1101 |
+ def_builtin ("__builtin_tlbw", void_ftype_void, AVR32_BUILTIN_TLBW);
|
mgl@1371
|
1102 |
+ def_builtin ("__builtin_breakpoint", void_ftype_void,
|
mgl@1371
|
1103 |
+ AVR32_BUILTIN_BREAKPOINT);
|
mgl@1371
|
1104 |
+ def_builtin ("__builtin_xchg", int_ftype_ptr_int, AVR32_BUILTIN_XCHG);
|
mgl@1371
|
1105 |
+ def_builtin ("__builtin_ldxi", int_ftype_ptr_int, AVR32_BUILTIN_LDXI);
|
mgl@1371
|
1106 |
+ def_builtin ("__builtin_bswap_16", short_ftype_short,
|
mgl@1371
|
1107 |
+ AVR32_BUILTIN_BSWAP16);
|
mgl@1371
|
1108 |
+ def_builtin ("__builtin_bswap_32", int_ftype_int, AVR32_BUILTIN_BSWAP32);
|
mgl@1371
|
1109 |
+ def_builtin ("__builtin_cop", void_ftype_int_int_int_int_int,
|
mgl@1371
|
1110 |
+ AVR32_BUILTIN_COP);
|
mgl@1371
|
1111 |
+ def_builtin ("__builtin_mvcr_w", int_ftype_int_int, AVR32_BUILTIN_MVCR_W);
|
mgl@1371
|
1112 |
+ def_builtin ("__builtin_mvrc_w", void_ftype_int_int_int,
|
mgl@1371
|
1113 |
+ AVR32_BUILTIN_MVRC_W);
|
mgl@1371
|
1114 |
+ def_builtin ("__builtin_mvcr_d", longlong_ftype_int_int,
|
mgl@1371
|
1115 |
+ AVR32_BUILTIN_MVCR_D);
|
mgl@1371
|
1116 |
+ def_builtin ("__builtin_mvrc_d", void_ftype_int_int_longlong,
|
mgl@1371
|
1117 |
+ AVR32_BUILTIN_MVRC_D);
|
mgl@1371
|
1118 |
+ def_builtin ("__builtin_sats", int_ftype_int_int_int, AVR32_BUILTIN_SATS);
|
mgl@1371
|
1119 |
+ def_builtin ("__builtin_satu", int_ftype_int_int_int, AVR32_BUILTIN_SATU);
|
mgl@1371
|
1120 |
+ def_builtin ("__builtin_satrnds", int_ftype_int_int_int,
|
mgl@1371
|
1121 |
+ AVR32_BUILTIN_SATRNDS);
|
mgl@1371
|
1122 |
+ def_builtin ("__builtin_satrndu", int_ftype_int_int_int,
|
mgl@1371
|
1123 |
+ AVR32_BUILTIN_SATRNDU);
|
mgl@1371
|
1124 |
+ def_builtin ("__builtin_musfr", void_ftype_int, AVR32_BUILTIN_MUSFR);
|
mgl@1371
|
1125 |
+ def_builtin ("__builtin_mustr", int_ftype_void, AVR32_BUILTIN_MUSTR);
|
mgl@1371
|
1126 |
+ def_builtin ("__builtin_macsathh_w", int_ftype_int_short_short,
|
mgl@1371
|
1127 |
+ AVR32_BUILTIN_MACSATHH_W);
|
mgl@1371
|
1128 |
+ def_builtin ("__builtin_macwh_d", longlong_ftype_longlong_int_short,
|
mgl@1371
|
1129 |
+ AVR32_BUILTIN_MACWH_D);
|
mgl@1371
|
1130 |
+ def_builtin ("__builtin_machh_d", longlong_ftype_longlong_short_short,
|
mgl@1371
|
1131 |
+ AVR32_BUILTIN_MACHH_D);
|
mgl@1371
|
1132 |
+ def_builtin ("__builtin_mems", void_ftype_ptr_int, AVR32_BUILTIN_MEMS);
|
mgl@1371
|
1133 |
+ def_builtin ("__builtin_memt", void_ftype_ptr_int, AVR32_BUILTIN_MEMT);
|
mgl@1371
|
1134 |
+ def_builtin ("__builtin_memc", void_ftype_ptr_int, AVR32_BUILTIN_MEMC);
|
mgl@1371
|
1135 |
+
|
mgl@1371
|
1136 |
+ /* Add all builtins that are more or less simple operations on two
|
mgl@1371
|
1137 |
+ operands. */
|
mgl@1371
|
1138 |
+ for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
|
mgl@1371
|
1139 |
+ {
|
mgl@1371
|
1140 |
+ /* Use one of the operands; the target can have a different mode for
|
mgl@1371
|
1141 |
+ mask-generating compares. */
|
mgl@1371
|
1142 |
+
|
mgl@1371
|
1143 |
+ if (d->name == 0)
|
mgl@1371
|
1144 |
+ continue;
|
mgl@1371
|
1145 |
+
|
mgl@1371
|
1146 |
+ def_mbuiltin (d->mask, d->name, *(d->ftype), d->code);
|
mgl@1371
|
1147 |
+ }
|
mgl@1371
|
1148 |
+}
|
mgl@1371
|
1149 |
+
|
mgl@1371
|
1150 |
+
|
mgl@1371
|
1151 |
+/* Subroutine of avr32_expand_builtin to take care of binop insns. */
|
mgl@1371
|
1152 |
+
|
mgl@1371
|
1153 |
+static rtx
|
mgl@1371
|
1154 |
+avr32_expand_binop_builtin (enum insn_code icode, tree arglist, rtx target)
|
mgl@1371
|
1155 |
+{
|
mgl@1371
|
1156 |
+ rtx pat;
|
mgl@1371
|
1157 |
+ tree arg0 = TREE_VALUE (arglist);
|
mgl@1371
|
1158 |
+ tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
|
mgl@1371
|
1159 |
+ rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1160 |
+ rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1161 |
+ enum machine_mode tmode = insn_data[icode].operand[0].mode;
|
mgl@1371
|
1162 |
+ enum machine_mode mode0 = insn_data[icode].operand[1].mode;
|
mgl@1371
|
1163 |
+ enum machine_mode mode1 = insn_data[icode].operand[2].mode;
|
mgl@1371
|
1164 |
+
|
mgl@1371
|
1165 |
+ if (!target
|
mgl@1371
|
1166 |
+ || GET_MODE (target) != tmode
|
mgl@1371
|
1167 |
+ || !(*insn_data[icode].operand[0].predicate) (target, tmode))
|
mgl@1371
|
1168 |
+ target = gen_reg_rtx (tmode);
|
mgl@1371
|
1169 |
+
|
mgl@1371
|
1170 |
+ /* In case the insn wants input operands in modes different from the
|
mgl@1371
|
1171 |
+ result, abort. */
|
mgl@1371
|
1172 |
+ if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
|
mgl@1371
|
1173 |
+ {
|
mgl@1371
|
1174 |
+ /* If op0 is already a reg we must cast it to the correct mode. */
|
mgl@1371
|
1175 |
+ if (REG_P (op0))
|
mgl@1371
|
1176 |
+ op0 = convert_to_mode (mode0, op0, 1);
|
mgl@1371
|
1177 |
+ else
|
mgl@1371
|
1178 |
+ op0 = copy_to_mode_reg (mode0, op0);
|
mgl@1371
|
1179 |
+ }
|
mgl@1371
|
1180 |
+ if (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
|
mgl@1371
|
1181 |
+ {
|
mgl@1371
|
1182 |
+ /* If op1 is already a reg we must cast it to the correct mode. */
|
mgl@1371
|
1183 |
+ if (REG_P (op1))
|
mgl@1371
|
1184 |
+ op1 = convert_to_mode (mode1, op1, 1);
|
mgl@1371
|
1185 |
+ else
|
mgl@1371
|
1186 |
+ op1 = copy_to_mode_reg (mode1, op1);
|
mgl@1371
|
1187 |
+ }
|
mgl@1371
|
1188 |
+ pat = GEN_FCN (icode) (target, op0, op1);
|
mgl@1371
|
1189 |
+ if (!pat)
|
mgl@1371
|
1190 |
+ return 0;
|
mgl@1371
|
1191 |
+ emit_insn (pat);
|
mgl@1371
|
1192 |
+ return target;
|
mgl@1371
|
1193 |
+}
|
mgl@1371
|
1194 |
+
|
mgl@1371
|
1195 |
+/* Expand an expression EXP that calls a built-in function,
|
mgl@1371
|
1196 |
+ with result going to TARGET if that's convenient
|
mgl@1371
|
1197 |
+ (and in mode MODE if that's convenient).
|
mgl@1371
|
1198 |
+ SUBTARGET may be used as the target for computing one of EXP's operands.
|
mgl@1371
|
1199 |
+ IGNORE is nonzero if the value is to be ignored. */
|
mgl@1371
|
1200 |
+
|
mgl@1371
|
1201 |
+rtx
|
mgl@1371
|
1202 |
+avr32_expand_builtin (tree exp,
|
mgl@1371
|
1203 |
+ rtx target,
|
mgl@1371
|
1204 |
+ rtx subtarget ATTRIBUTE_UNUSED,
|
mgl@1371
|
1205 |
+ enum machine_mode mode ATTRIBUTE_UNUSED,
|
mgl@1371
|
1206 |
+ int ignore ATTRIBUTE_UNUSED)
|
mgl@1371
|
1207 |
+{
|
mgl@1371
|
1208 |
+ const struct builtin_description *d;
|
mgl@1371
|
1209 |
+ unsigned int i;
|
mgl@1371
|
1210 |
+ enum insn_code icode = 0;
|
mgl@1371
|
1211 |
+ tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
|
mgl@1371
|
1212 |
+ tree arglist = TREE_OPERAND (exp, 1);
|
mgl@1371
|
1213 |
+ tree arg0, arg1, arg2;
|
mgl@1371
|
1214 |
+ rtx op0, op1, op2, pat;
|
mgl@1371
|
1215 |
+ enum machine_mode tmode, mode0, mode1;
|
mgl@1371
|
1216 |
+ enum machine_mode arg0_mode;
|
mgl@1371
|
1217 |
+ int fcode = DECL_FUNCTION_CODE (fndecl);
|
mgl@1371
|
1218 |
+
|
mgl@1371
|
1219 |
+ switch (fcode)
|
mgl@1371
|
1220 |
+ {
|
mgl@1371
|
1221 |
+ default:
|
mgl@1371
|
1222 |
+ break;
|
mgl@1371
|
1223 |
+
|
mgl@1371
|
1224 |
+ case AVR32_BUILTIN_SATS:
|
mgl@1371
|
1225 |
+ case AVR32_BUILTIN_SATU:
|
mgl@1371
|
1226 |
+ case AVR32_BUILTIN_SATRNDS:
|
mgl@1371
|
1227 |
+ case AVR32_BUILTIN_SATRNDU:
|
mgl@1371
|
1228 |
+ {
|
mgl@1371
|
1229 |
+ const char *fname;
|
mgl@1371
|
1230 |
+ switch (fcode)
|
mgl@1371
|
1231 |
+ {
|
mgl@1371
|
1232 |
+ default:
|
mgl@1371
|
1233 |
+ case AVR32_BUILTIN_SATS:
|
mgl@1371
|
1234 |
+ icode = CODE_FOR_sats;
|
mgl@1371
|
1235 |
+ fname = "sats";
|
mgl@1371
|
1236 |
+ break;
|
mgl@1371
|
1237 |
+ case AVR32_BUILTIN_SATU:
|
mgl@1371
|
1238 |
+ icode = CODE_FOR_satu;
|
mgl@1371
|
1239 |
+ fname = "satu";
|
mgl@1371
|
1240 |
+ break;
|
mgl@1371
|
1241 |
+ case AVR32_BUILTIN_SATRNDS:
|
mgl@1371
|
1242 |
+ icode = CODE_FOR_satrnds;
|
mgl@1371
|
1243 |
+ fname = "satrnds";
|
mgl@1371
|
1244 |
+ break;
|
mgl@1371
|
1245 |
+ case AVR32_BUILTIN_SATRNDU:
|
mgl@1371
|
1246 |
+ icode = CODE_FOR_satrndu;
|
mgl@1371
|
1247 |
+ fname = "satrndu";
|
mgl@1371
|
1248 |
+ break;
|
mgl@1371
|
1249 |
+ }
|
mgl@1371
|
1250 |
+
|
mgl@1371
|
1251 |
+ arg0 = TREE_VALUE (arglist);
|
mgl@1371
|
1252 |
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
|
mgl@1371
|
1253 |
+ arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
|
mgl@1371
|
1254 |
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1255 |
+ op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1256 |
+ op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1257 |
+
|
mgl@1371
|
1258 |
+ tmode = insn_data[icode].operand[0].mode;
|
mgl@1371
|
1259 |
+
|
mgl@1371
|
1260 |
+
|
mgl@1371
|
1261 |
+ if (target == 0
|
mgl@1371
|
1262 |
+ || GET_MODE (target) != tmode
|
mgl@1371
|
1263 |
+ || !(*insn_data[icode].operand[0].predicate) (target, tmode))
|
mgl@1371
|
1264 |
+ target = gen_reg_rtx (tmode);
|
mgl@1371
|
1265 |
+
|
mgl@1371
|
1266 |
+
|
mgl@1371
|
1267 |
+ if (!(*insn_data[icode].operand[0].predicate) (op0, GET_MODE (op0)))
|
mgl@1371
|
1268 |
+ {
|
mgl@1371
|
1269 |
+ op0 = copy_to_mode_reg (insn_data[icode].operand[0].mode, op0);
|
mgl@1371
|
1270 |
+ }
|
mgl@1371
|
1271 |
+
|
mgl@1371
|
1272 |
+ if (!(*insn_data[icode].operand[1].predicate) (op1, SImode))
|
mgl@1371
|
1273 |
+ {
|
mgl@1371
|
1274 |
+ error ("Parameter 2 to __builtin_%s should be a constant number.",
|
mgl@1371
|
1275 |
+ fname);
|
mgl@1371
|
1276 |
+ return NULL_RTX;
|
mgl@1371
|
1277 |
+ }
|
mgl@1371
|
1278 |
+
|
mgl@1371
|
1279 |
+ if (!(*insn_data[icode].operand[1].predicate) (op2, SImode))
|
mgl@1371
|
1280 |
+ {
|
mgl@1371
|
1281 |
+ error ("Parameter 3 to __builtin_%s should be a constant number.",
|
mgl@1371
|
1282 |
+ fname);
|
mgl@1371
|
1283 |
+ return NULL_RTX;
|
mgl@1371
|
1284 |
+ }
|
mgl@1371
|
1285 |
+
|
mgl@1371
|
1286 |
+ emit_move_insn (target, op0);
|
mgl@1371
|
1287 |
+ pat = GEN_FCN (icode) (target, op1, op2);
|
mgl@1371
|
1288 |
+ if (!pat)
|
mgl@1371
|
1289 |
+ return 0;
|
mgl@1371
|
1290 |
+ emit_insn (pat);
|
mgl@1371
|
1291 |
+
|
mgl@1371
|
1292 |
+ return target;
|
mgl@1371
|
1293 |
+ }
|
mgl@1371
|
1294 |
+ case AVR32_BUILTIN_MUSTR:
|
mgl@1371
|
1295 |
+ icode = CODE_FOR_mustr;
|
mgl@1371
|
1296 |
+ tmode = insn_data[icode].operand[0].mode;
|
mgl@1371
|
1297 |
+
|
mgl@1371
|
1298 |
+ if (target == 0
|
mgl@1371
|
1299 |
+ || GET_MODE (target) != tmode
|
mgl@1371
|
1300 |
+ || !(*insn_data[icode].operand[0].predicate) (target, tmode))
|
mgl@1371
|
1301 |
+ target = gen_reg_rtx (tmode);
|
mgl@1371
|
1302 |
+ pat = GEN_FCN (icode) (target);
|
mgl@1371
|
1303 |
+ if (!pat)
|
mgl@1371
|
1304 |
+ return 0;
|
mgl@1371
|
1305 |
+ emit_insn (pat);
|
mgl@1371
|
1306 |
+ return target;
|
mgl@1371
|
1307 |
+
|
mgl@1371
|
1308 |
+ case AVR32_BUILTIN_MFSR:
|
mgl@1371
|
1309 |
+ icode = CODE_FOR_mfsr;
|
mgl@1371
|
1310 |
+ arg0 = TREE_VALUE (arglist);
|
mgl@1371
|
1311 |
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1312 |
+ tmode = insn_data[icode].operand[0].mode;
|
mgl@1371
|
1313 |
+ mode0 = insn_data[icode].operand[1].mode;
|
mgl@1371
|
1314 |
+
|
mgl@1371
|
1315 |
+ if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
|
mgl@1371
|
1316 |
+ {
|
mgl@1371
|
1317 |
+ error ("Parameter 1 to __builtin_mfsr must be a constant number");
|
mgl@1371
|
1318 |
+ }
|
mgl@1371
|
1319 |
+
|
mgl@1371
|
1320 |
+ if (target == 0
|
mgl@1371
|
1321 |
+ || GET_MODE (target) != tmode
|
mgl@1371
|
1322 |
+ || !(*insn_data[icode].operand[0].predicate) (target, tmode))
|
mgl@1371
|
1323 |
+ target = gen_reg_rtx (tmode);
|
mgl@1371
|
1324 |
+ pat = GEN_FCN (icode) (target, op0);
|
mgl@1371
|
1325 |
+ if (!pat)
|
mgl@1371
|
1326 |
+ return 0;
|
mgl@1371
|
1327 |
+ emit_insn (pat);
|
mgl@1371
|
1328 |
+ return target;
|
mgl@1371
|
1329 |
+ case AVR32_BUILTIN_MTSR:
|
mgl@1371
|
1330 |
+ icode = CODE_FOR_mtsr;
|
mgl@1371
|
1331 |
+ arg0 = TREE_VALUE (arglist);
|
mgl@1371
|
1332 |
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
|
mgl@1371
|
1333 |
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1334 |
+ op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1335 |
+ mode0 = insn_data[icode].operand[0].mode;
|
mgl@1371
|
1336 |
+ mode1 = insn_data[icode].operand[1].mode;
|
mgl@1371
|
1337 |
+
|
mgl@1371
|
1338 |
+ if (!(*insn_data[icode].operand[0].predicate) (op0, mode0))
|
mgl@1371
|
1339 |
+ {
|
mgl@1371
|
1340 |
+ error ("Parameter 1 to __builtin_mtsr must be a constant number");
|
mgl@1371
|
1341 |
+ return gen_reg_rtx (mode0);
|
mgl@1371
|
1342 |
+ }
|
mgl@1371
|
1343 |
+ if (!(*insn_data[icode].operand[1].predicate) (op1, mode1))
|
mgl@1371
|
1344 |
+ op1 = copy_to_mode_reg (mode1, op1);
|
mgl@1371
|
1345 |
+ pat = GEN_FCN (icode) (op0, op1);
|
mgl@1371
|
1346 |
+ if (!pat)
|
mgl@1371
|
1347 |
+ return 0;
|
mgl@1371
|
1348 |
+ emit_insn (pat);
|
mgl@1371
|
1349 |
+ return NULL_RTX;
|
mgl@1371
|
1350 |
+ case AVR32_BUILTIN_MFDR:
|
mgl@1371
|
1351 |
+ icode = CODE_FOR_mfdr;
|
mgl@1371
|
1352 |
+ arg0 = TREE_VALUE (arglist);
|
mgl@1371
|
1353 |
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1354 |
+ tmode = insn_data[icode].operand[0].mode;
|
mgl@1371
|
1355 |
+ mode0 = insn_data[icode].operand[1].mode;
|
mgl@1371
|
1356 |
+
|
mgl@1371
|
1357 |
+ if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
|
mgl@1371
|
1358 |
+ {
|
mgl@1371
|
1359 |
+ error ("Parameter 1 to __builtin_mfdr must be a constant number");
|
mgl@1371
|
1360 |
+ }
|
mgl@1371
|
1361 |
+
|
mgl@1371
|
1362 |
+ if (target == 0
|
mgl@1371
|
1363 |
+ || GET_MODE (target) != tmode
|
mgl@1371
|
1364 |
+ || !(*insn_data[icode].operand[0].predicate) (target, tmode))
|
mgl@1371
|
1365 |
+ target = gen_reg_rtx (tmode);
|
mgl@1371
|
1366 |
+ pat = GEN_FCN (icode) (target, op0);
|
mgl@1371
|
1367 |
+ if (!pat)
|
mgl@1371
|
1368 |
+ return 0;
|
mgl@1371
|
1369 |
+ emit_insn (pat);
|
mgl@1371
|
1370 |
+ return target;
|
mgl@1371
|
1371 |
+ case AVR32_BUILTIN_MTDR:
|
mgl@1371
|
1372 |
+ icode = CODE_FOR_mtdr;
|
mgl@1371
|
1373 |
+ arg0 = TREE_VALUE (arglist);
|
mgl@1371
|
1374 |
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
|
mgl@1371
|
1375 |
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1376 |
+ op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1377 |
+ mode0 = insn_data[icode].operand[0].mode;
|
mgl@1371
|
1378 |
+ mode1 = insn_data[icode].operand[1].mode;
|
mgl@1371
|
1379 |
+
|
mgl@1371
|
1380 |
+ if (!(*insn_data[icode].operand[0].predicate) (op0, mode0))
|
mgl@1371
|
1381 |
+ {
|
mgl@1371
|
1382 |
+ error ("Parameter 1 to __builtin_mtdr must be a constant number");
|
mgl@1371
|
1383 |
+ return gen_reg_rtx (mode0);
|
mgl@1371
|
1384 |
+ }
|
mgl@1371
|
1385 |
+ if (!(*insn_data[icode].operand[1].predicate) (op1, mode1))
|
mgl@1371
|
1386 |
+ op1 = copy_to_mode_reg (mode1, op1);
|
mgl@1371
|
1387 |
+ pat = GEN_FCN (icode) (op0, op1);
|
mgl@1371
|
1388 |
+ if (!pat)
|
mgl@1371
|
1389 |
+ return 0;
|
mgl@1371
|
1390 |
+ emit_insn (pat);
|
mgl@1371
|
1391 |
+ return NULL_RTX;
|
mgl@1371
|
1392 |
+ case AVR32_BUILTIN_CACHE:
|
mgl@1371
|
1393 |
+ icode = CODE_FOR_cache;
|
mgl@1371
|
1394 |
+ arg0 = TREE_VALUE (arglist);
|
mgl@1371
|
1395 |
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
|
mgl@1371
|
1396 |
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1397 |
+ op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1398 |
+ mode0 = insn_data[icode].operand[0].mode;
|
mgl@1371
|
1399 |
+ mode1 = insn_data[icode].operand[1].mode;
|
mgl@1371
|
1400 |
+
|
mgl@1371
|
1401 |
+ if (!(*insn_data[icode].operand[1].predicate) (op1, mode1))
|
mgl@1371
|
1402 |
+ {
|
mgl@1371
|
1403 |
+ error ("Parameter 2 to __builtin_cache must be a constant number");
|
mgl@1371
|
1404 |
+ return gen_reg_rtx (mode1);
|
mgl@1371
|
1405 |
+ }
|
mgl@1371
|
1406 |
+
|
mgl@1371
|
1407 |
+ if (!(*insn_data[icode].operand[0].predicate) (op0, mode0))
|
mgl@1371
|
1408 |
+ op0 = copy_to_mode_reg (mode0, op0);
|
mgl@1371
|
1409 |
+
|
mgl@1371
|
1410 |
+ pat = GEN_FCN (icode) (op0, op1);
|
mgl@1371
|
1411 |
+ if (!pat)
|
mgl@1371
|
1412 |
+ return 0;
|
mgl@1371
|
1413 |
+ emit_insn (pat);
|
mgl@1371
|
1414 |
+ return NULL_RTX;
|
mgl@1371
|
1415 |
+ case AVR32_BUILTIN_SYNC:
|
mgl@1371
|
1416 |
+ case AVR32_BUILTIN_MUSFR:
|
mgl@1371
|
1417 |
+ case AVR32_BUILTIN_SSRF:
|
mgl@1371
|
1418 |
+ case AVR32_BUILTIN_CSRF:
|
mgl@1371
|
1419 |
+ {
|
mgl@1371
|
1420 |
+ const char *fname;
|
mgl@1371
|
1421 |
+ switch (fcode)
|
mgl@1371
|
1422 |
+ {
|
mgl@1371
|
1423 |
+ default:
|
mgl@1371
|
1424 |
+ case AVR32_BUILTIN_SYNC:
|
mgl@1371
|
1425 |
+ icode = CODE_FOR_sync;
|
mgl@1371
|
1426 |
+ fname = "sync";
|
mgl@1371
|
1427 |
+ break;
|
mgl@1371
|
1428 |
+ case AVR32_BUILTIN_MUSFR:
|
mgl@1371
|
1429 |
+ icode = CODE_FOR_musfr;
|
mgl@1371
|
1430 |
+ fname = "musfr";
|
mgl@1371
|
1431 |
+ break;
|
mgl@1371
|
1432 |
+ case AVR32_BUILTIN_SSRF:
|
mgl@1371
|
1433 |
+ icode = CODE_FOR_ssrf;
|
mgl@1371
|
1434 |
+ fname = "ssrf";
|
mgl@1371
|
1435 |
+ break;
|
mgl@1371
|
1436 |
+ case AVR32_BUILTIN_CSRF:
|
mgl@1371
|
1437 |
+ icode = CODE_FOR_csrf;
|
mgl@1371
|
1438 |
+ fname = "csrf";
|
mgl@1371
|
1439 |
+ break;
|
mgl@1371
|
1440 |
+ }
|
mgl@1371
|
1441 |
+
|
mgl@1371
|
1442 |
+ arg0 = TREE_VALUE (arglist);
|
mgl@1371
|
1443 |
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1444 |
+ mode0 = insn_data[icode].operand[0].mode;
|
mgl@1371
|
1445 |
+
|
mgl@1371
|
1446 |
+ if (!(*insn_data[icode].operand[0].predicate) (op0, mode0))
|
mgl@1371
|
1447 |
+ {
|
mgl@1371
|
1448 |
+ if (icode == CODE_FOR_musfr)
|
mgl@1371
|
1449 |
+ op0 = copy_to_mode_reg (mode0, op0);
|
mgl@1371
|
1450 |
+ else
|
mgl@1371
|
1451 |
+ {
|
mgl@1371
|
1452 |
+ error ("Parameter to __builtin_%s is illegal.", fname);
|
mgl@1371
|
1453 |
+ return gen_reg_rtx (mode0);
|
mgl@1371
|
1454 |
+ }
|
mgl@1371
|
1455 |
+ }
|
mgl@1371
|
1456 |
+ pat = GEN_FCN (icode) (op0);
|
mgl@1371
|
1457 |
+ if (!pat)
|
mgl@1371
|
1458 |
+ return 0;
|
mgl@1371
|
1459 |
+ emit_insn (pat);
|
mgl@1371
|
1460 |
+ return NULL_RTX;
|
mgl@1371
|
1461 |
+ }
|
mgl@1371
|
1462 |
+ case AVR32_BUILTIN_TLBR:
|
mgl@1371
|
1463 |
+ icode = CODE_FOR_tlbr;
|
mgl@1371
|
1464 |
+ pat = GEN_FCN (icode) (NULL_RTX);
|
mgl@1371
|
1465 |
+ if (!pat)
|
mgl@1371
|
1466 |
+ return 0;
|
mgl@1371
|
1467 |
+ emit_insn (pat);
|
mgl@1371
|
1468 |
+ return NULL_RTX;
|
mgl@1371
|
1469 |
+ case AVR32_BUILTIN_TLBS:
|
mgl@1371
|
1470 |
+ icode = CODE_FOR_tlbs;
|
mgl@1371
|
1471 |
+ pat = GEN_FCN (icode) (NULL_RTX);
|
mgl@1371
|
1472 |
+ if (!pat)
|
mgl@1371
|
1473 |
+ return 0;
|
mgl@1371
|
1474 |
+ emit_insn (pat);
|
mgl@1371
|
1475 |
+ return NULL_RTX;
|
mgl@1371
|
1476 |
+ case AVR32_BUILTIN_TLBW:
|
mgl@1371
|
1477 |
+ icode = CODE_FOR_tlbw;
|
mgl@1371
|
1478 |
+ pat = GEN_FCN (icode) (NULL_RTX);
|
mgl@1371
|
1479 |
+ if (!pat)
|
mgl@1371
|
1480 |
+ return 0;
|
mgl@1371
|
1481 |
+ emit_insn (pat);
|
mgl@1371
|
1482 |
+ return NULL_RTX;
|
mgl@1371
|
1483 |
+ case AVR32_BUILTIN_BREAKPOINT:
|
mgl@1371
|
1484 |
+ icode = CODE_FOR_breakpoint;
|
mgl@1371
|
1485 |
+ pat = GEN_FCN (icode) (NULL_RTX);
|
mgl@1371
|
1486 |
+ if (!pat)
|
mgl@1371
|
1487 |
+ return 0;
|
mgl@1371
|
1488 |
+ emit_insn (pat);
|
mgl@1371
|
1489 |
+ return NULL_RTX;
|
mgl@1371
|
1490 |
+ case AVR32_BUILTIN_XCHG:
|
mgl@1371
|
1491 |
+ icode = CODE_FOR_sync_lock_test_and_setsi;
|
mgl@1371
|
1492 |
+ arg0 = TREE_VALUE (arglist);
|
mgl@1371
|
1493 |
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
|
mgl@1371
|
1494 |
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1495 |
+ op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1496 |
+ tmode = insn_data[icode].operand[0].mode;
|
mgl@1371
|
1497 |
+ mode0 = insn_data[icode].operand[1].mode;
|
mgl@1371
|
1498 |
+ mode1 = insn_data[icode].operand[2].mode;
|
mgl@1371
|
1499 |
+
|
mgl@1371
|
1500 |
+ if (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
|
mgl@1371
|
1501 |
+ {
|
mgl@1371
|
1502 |
+ op1 = copy_to_mode_reg (mode1, op1);
|
mgl@1371
|
1503 |
+ }
|
mgl@1371
|
1504 |
+
|
mgl@1371
|
1505 |
+ op0 = force_reg (GET_MODE (op0), op0);
|
mgl@1371
|
1506 |
+ op0 = gen_rtx_MEM (GET_MODE (op0), op0);
|
mgl@1371
|
1507 |
+ if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
|
mgl@1371
|
1508 |
+ {
|
mgl@1371
|
1509 |
+ error
|
mgl@1371
|
1510 |
+ ("Parameter 1 to __builtin_xchg must be a pointer to an integer.");
|
mgl@1371
|
1511 |
+ }
|
mgl@1371
|
1512 |
+
|
mgl@1371
|
1513 |
+ if (target == 0
|
mgl@1371
|
1514 |
+ || GET_MODE (target) != tmode
|
mgl@1371
|
1515 |
+ || !(*insn_data[icode].operand[0].predicate) (target, tmode))
|
mgl@1371
|
1516 |
+ target = gen_reg_rtx (tmode);
|
mgl@1371
|
1517 |
+ pat = GEN_FCN (icode) (target, op0, op1);
|
mgl@1371
|
1518 |
+ if (!pat)
|
mgl@1371
|
1519 |
+ return 0;
|
mgl@1371
|
1520 |
+ emit_insn (pat);
|
mgl@1371
|
1521 |
+ return target;
|
mgl@1371
|
1522 |
+ case AVR32_BUILTIN_LDXI:
|
mgl@1371
|
1523 |
+ icode = CODE_FOR_ldxi;
|
mgl@1371
|
1524 |
+ arg0 = TREE_VALUE (arglist);
|
mgl@1371
|
1525 |
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
|
mgl@1371
|
1526 |
+ arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
|
mgl@1371
|
1527 |
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1528 |
+ op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1529 |
+ op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1530 |
+ tmode = insn_data[icode].operand[0].mode;
|
mgl@1371
|
1531 |
+ mode0 = insn_data[icode].operand[1].mode;
|
mgl@1371
|
1532 |
+ mode1 = insn_data[icode].operand[2].mode;
|
mgl@1371
|
1533 |
+
|
mgl@1371
|
1534 |
+ if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
|
mgl@1371
|
1535 |
+ {
|
mgl@1371
|
1536 |
+ op0 = copy_to_mode_reg (mode0, op0);
|
mgl@1371
|
1537 |
+ }
|
mgl@1371
|
1538 |
+
|
mgl@1371
|
1539 |
+ if (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
|
mgl@1371
|
1540 |
+ {
|
mgl@1371
|
1541 |
+ op1 = copy_to_mode_reg (mode1, op1);
|
mgl@1371
|
1542 |
+ }
|
mgl@1371
|
1543 |
+
|
mgl@1371
|
1544 |
+ if (!(*insn_data[icode].operand[3].predicate) (op2, SImode))
|
mgl@1371
|
1545 |
+ {
|
mgl@1371
|
1546 |
+ error
|
mgl@1371
|
1547 |
+ ("Parameter 3 to __builtin_ldxi must be a valid extract shift operand: (0|8|16|24)");
|
mgl@1371
|
1548 |
+ return gen_reg_rtx (mode0);
|
mgl@1371
|
1549 |
+ }
|
mgl@1371
|
1550 |
+
|
mgl@1371
|
1551 |
+ if (target == 0
|
mgl@1371
|
1552 |
+ || GET_MODE (target) != tmode
|
mgl@1371
|
1553 |
+ || !(*insn_data[icode].operand[0].predicate) (target, tmode))
|
mgl@1371
|
1554 |
+ target = gen_reg_rtx (tmode);
|
mgl@1371
|
1555 |
+ pat = GEN_FCN (icode) (target, op0, op1, op2);
|
mgl@1371
|
1556 |
+ if (!pat)
|
mgl@1371
|
1557 |
+ return 0;
|
mgl@1371
|
1558 |
+ emit_insn (pat);
|
mgl@1371
|
1559 |
+ return target;
|
mgl@1371
|
1560 |
+ case AVR32_BUILTIN_BSWAP16:
|
mgl@1371
|
1561 |
+ {
|
mgl@1371
|
1562 |
+ icode = CODE_FOR_bswap_16;
|
mgl@1371
|
1563 |
+ arg0 = TREE_VALUE (arglist);
|
mgl@1371
|
1564 |
+ arg0_mode = TYPE_MODE (TREE_TYPE (arg0));
|
mgl@1371
|
1565 |
+ mode0 = insn_data[icode].operand[1].mode;
|
mgl@1371
|
1566 |
+ if (arg0_mode != mode0)
|
mgl@1371
|
1567 |
+ arg0 = build1 (NOP_EXPR,
|
mgl@1371
|
1568 |
+ (*lang_hooks.types.type_for_mode) (mode0, 0), arg0);
|
mgl@1371
|
1569 |
+
|
mgl@1371
|
1570 |
+ op0 = expand_expr (arg0, NULL_RTX, HImode, 0);
|
mgl@1371
|
1571 |
+ tmode = insn_data[icode].operand[0].mode;
|
mgl@1371
|
1572 |
+
|
mgl@1371
|
1573 |
+
|
mgl@1371
|
1574 |
+ if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
|
mgl@1371
|
1575 |
+ {
|
mgl@1371
|
1576 |
+ if ( CONST_INT_P (op0) )
|
mgl@1371
|
1577 |
+ {
|
mgl@1371
|
1578 |
+ HOST_WIDE_INT val = ( ((INTVAL (op0)&0x00ff) << 8) |
|
mgl@1371
|
1579 |
+ ((INTVAL (op0)&0xff00) >> 8) );
|
mgl@1371
|
1580 |
+ /* Sign extend 16-bit value to host wide int */
|
mgl@1371
|
1581 |
+ val <<= (HOST_BITS_PER_WIDE_INT - 16);
|
mgl@1371
|
1582 |
+ val >>= (HOST_BITS_PER_WIDE_INT - 16);
|
mgl@1371
|
1583 |
+ op0 = GEN_INT(val);
|
mgl@1371
|
1584 |
+ if (target == 0
|
mgl@1371
|
1585 |
+ || GET_MODE (target) != tmode
|
mgl@1371
|
1586 |
+ || !(*insn_data[icode].operand[0].predicate) (target, tmode))
|
mgl@1371
|
1587 |
+ target = gen_reg_rtx (tmode);
|
mgl@1371
|
1588 |
+ emit_move_insn(target, op0);
|
mgl@1371
|
1589 |
+ return target;
|
mgl@1371
|
1590 |
+ }
|
mgl@1371
|
1591 |
+ else
|
mgl@1371
|
1592 |
+ op0 = copy_to_mode_reg (mode0, op0);
|
mgl@1371
|
1593 |
+ }
|
mgl@1371
|
1594 |
+
|
mgl@1371
|
1595 |
+ if (target == 0
|
mgl@1371
|
1596 |
+ || GET_MODE (target) != tmode
|
mgl@1371
|
1597 |
+ || !(*insn_data[icode].operand[0].predicate) (target, tmode))
|
mgl@1371
|
1598 |
+ {
|
mgl@1371
|
1599 |
+ target = gen_reg_rtx (tmode);
|
mgl@1371
|
1600 |
+ }
|
mgl@1371
|
1601 |
+
|
mgl@1371
|
1602 |
+
|
mgl@1371
|
1603 |
+ pat = GEN_FCN (icode) (target, op0);
|
mgl@1371
|
1604 |
+ if (!pat)
|
mgl@1371
|
1605 |
+ return 0;
|
mgl@1371
|
1606 |
+ emit_insn (pat);
|
mgl@1371
|
1607 |
+
|
mgl@1371
|
1608 |
+ return target;
|
mgl@1371
|
1609 |
+ }
|
mgl@1371
|
1610 |
+ case AVR32_BUILTIN_BSWAP32:
|
mgl@1371
|
1611 |
+ {
|
mgl@1371
|
1612 |
+ icode = CODE_FOR_bswap_32;
|
mgl@1371
|
1613 |
+ arg0 = TREE_VALUE (arglist);
|
mgl@1371
|
1614 |
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1615 |
+ tmode = insn_data[icode].operand[0].mode;
|
mgl@1371
|
1616 |
+ mode0 = insn_data[icode].operand[1].mode;
|
mgl@1371
|
1617 |
+
|
mgl@1371
|
1618 |
+ if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
|
mgl@1371
|
1619 |
+ {
|
mgl@1371
|
1620 |
+ if ( CONST_INT_P (op0) )
|
mgl@1371
|
1621 |
+ {
|
mgl@1371
|
1622 |
+ HOST_WIDE_INT val = ( ((INTVAL (op0)&0x000000ff) << 24) |
|
mgl@1371
|
1623 |
+ ((INTVAL (op0)&0x0000ff00) << 8) |
|
mgl@1371
|
1624 |
+ ((INTVAL (op0)&0x00ff0000) >> 8) |
|
mgl@1371
|
1625 |
+ ((INTVAL (op0)&0xff000000) >> 24) );
|
mgl@1371
|
1626 |
+ /* Sign extend 32-bit value to host wide int */
|
mgl@1371
|
1627 |
+ val <<= (HOST_BITS_PER_WIDE_INT - 32);
|
mgl@1371
|
1628 |
+ val >>= (HOST_BITS_PER_WIDE_INT - 32);
|
mgl@1371
|
1629 |
+ op0 = GEN_INT(val);
|
mgl@1371
|
1630 |
+ if (target == 0
|
mgl@1371
|
1631 |
+ || GET_MODE (target) != tmode
|
mgl@1371
|
1632 |
+ || !(*insn_data[icode].operand[0].predicate) (target, tmode))
|
mgl@1371
|
1633 |
+ target = gen_reg_rtx (tmode);
|
mgl@1371
|
1634 |
+ emit_move_insn(target, op0);
|
mgl@1371
|
1635 |
+ return target;
|
mgl@1371
|
1636 |
+ }
|
mgl@1371
|
1637 |
+ else
|
mgl@1371
|
1638 |
+ op0 = copy_to_mode_reg (mode0, op0);
|
mgl@1371
|
1639 |
+ }
|
mgl@1371
|
1640 |
+
|
mgl@1371
|
1641 |
+ if (target == 0
|
mgl@1371
|
1642 |
+ || GET_MODE (target) != tmode
|
mgl@1371
|
1643 |
+ || !(*insn_data[icode].operand[0].predicate) (target, tmode))
|
mgl@1371
|
1644 |
+ target = gen_reg_rtx (tmode);
|
mgl@1371
|
1645 |
+
|
mgl@1371
|
1646 |
+
|
mgl@1371
|
1647 |
+ pat = GEN_FCN (icode) (target, op0);
|
mgl@1371
|
1648 |
+ if (!pat)
|
mgl@1371
|
1649 |
+ return 0;
|
mgl@1371
|
1650 |
+ emit_insn (pat);
|
mgl@1371
|
1651 |
+
|
mgl@1371
|
1652 |
+ return target;
|
mgl@1371
|
1653 |
+ }
|
mgl@1371
|
1654 |
+ case AVR32_BUILTIN_MVCR_W:
|
mgl@1371
|
1655 |
+ case AVR32_BUILTIN_MVCR_D:
|
mgl@1371
|
1656 |
+ {
|
mgl@1371
|
1657 |
+ arg0 = TREE_VALUE (arglist);
|
mgl@1371
|
1658 |
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
|
mgl@1371
|
1659 |
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1660 |
+ op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1661 |
+
|
mgl@1371
|
1662 |
+ if (fcode == AVR32_BUILTIN_MVCR_W)
|
mgl@1371
|
1663 |
+ icode = CODE_FOR_mvcrsi;
|
mgl@1371
|
1664 |
+ else
|
mgl@1371
|
1665 |
+ icode = CODE_FOR_mvcrdi;
|
mgl@1371
|
1666 |
+
|
mgl@1371
|
1667 |
+ tmode = insn_data[icode].operand[0].mode;
|
mgl@1371
|
1668 |
+
|
mgl@1371
|
1669 |
+ if (target == 0
|
mgl@1371
|
1670 |
+ || GET_MODE (target) != tmode
|
mgl@1371
|
1671 |
+ || !(*insn_data[icode].operand[0].predicate) (target, tmode))
|
mgl@1371
|
1672 |
+ target = gen_reg_rtx (tmode);
|
mgl@1371
|
1673 |
+
|
mgl@1371
|
1674 |
+ if (!(*insn_data[icode].operand[1].predicate) (op0, SImode))
|
mgl@1371
|
1675 |
+ {
|
mgl@1371
|
1676 |
+ error
|
mgl@1371
|
1677 |
+ ("Parameter 1 to __builtin_cop is not a valid coprocessor number.");
|
mgl@1371
|
1678 |
+ error ("Number should be between 0 and 7.");
|
mgl@1371
|
1679 |
+ return NULL_RTX;
|
mgl@1371
|
1680 |
+ }
|
mgl@1371
|
1681 |
+
|
mgl@1371
|
1682 |
+ if (!(*insn_data[icode].operand[2].predicate) (op1, SImode))
|
mgl@1371
|
1683 |
+ {
|
mgl@1371
|
1684 |
+ error
|
mgl@1371
|
1685 |
+ ("Parameter 2 to __builtin_cop is not a valid coprocessor register number.");
|
mgl@1371
|
1686 |
+ error ("Number should be between 0 and 15.");
|
mgl@1371
|
1687 |
+ return NULL_RTX;
|
mgl@1371
|
1688 |
+ }
|
mgl@1371
|
1689 |
+
|
mgl@1371
|
1690 |
+ pat = GEN_FCN (icode) (target, op0, op1);
|
mgl@1371
|
1691 |
+ if (!pat)
|
mgl@1371
|
1692 |
+ return 0;
|
mgl@1371
|
1693 |
+ emit_insn (pat);
|
mgl@1371
|
1694 |
+
|
mgl@1371
|
1695 |
+ return target;
|
mgl@1371
|
1696 |
+ }
|
mgl@1371
|
1697 |
+ case AVR32_BUILTIN_MACSATHH_W:
|
mgl@1371
|
1698 |
+ case AVR32_BUILTIN_MACWH_D:
|
mgl@1371
|
1699 |
+ case AVR32_BUILTIN_MACHH_D:
|
mgl@1371
|
1700 |
+ {
|
mgl@1371
|
1701 |
+ arg0 = TREE_VALUE (arglist);
|
mgl@1371
|
1702 |
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
|
mgl@1371
|
1703 |
+ arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
|
mgl@1371
|
1704 |
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1705 |
+ op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1706 |
+ op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1707 |
+
|
mgl@1371
|
1708 |
+ icode = ((fcode == AVR32_BUILTIN_MACSATHH_W) ? CODE_FOR_macsathh_w :
|
mgl@1371
|
1709 |
+ (fcode == AVR32_BUILTIN_MACWH_D) ? CODE_FOR_macwh_d :
|
mgl@1371
|
1710 |
+ CODE_FOR_machh_d);
|
mgl@1371
|
1711 |
+
|
mgl@1371
|
1712 |
+ tmode = insn_data[icode].operand[0].mode;
|
mgl@1371
|
1713 |
+ mode0 = insn_data[icode].operand[1].mode;
|
mgl@1371
|
1714 |
+ mode1 = insn_data[icode].operand[2].mode;
|
mgl@1371
|
1715 |
+
|
mgl@1371
|
1716 |
+
|
mgl@1371
|
1717 |
+ if (!target
|
mgl@1371
|
1718 |
+ || GET_MODE (target) != tmode
|
mgl@1371
|
1719 |
+ || !(*insn_data[icode].operand[0].predicate) (target, tmode))
|
mgl@1371
|
1720 |
+ target = gen_reg_rtx (tmode);
|
mgl@1371
|
1721 |
+
|
mgl@1371
|
1722 |
+ if (!(*insn_data[icode].operand[0].predicate) (op0, tmode))
|
mgl@1371
|
1723 |
+ {
|
mgl@1371
|
1724 |
+ /* If op0 is already a reg we must cast it to the correct mode. */
|
mgl@1371
|
1725 |
+ if (REG_P (op0))
|
mgl@1371
|
1726 |
+ op0 = convert_to_mode (tmode, op0, 1);
|
mgl@1371
|
1727 |
+ else
|
mgl@1371
|
1728 |
+ op0 = copy_to_mode_reg (tmode, op0);
|
mgl@1371
|
1729 |
+ }
|
mgl@1371
|
1730 |
+
|
mgl@1371
|
1731 |
+ if (!(*insn_data[icode].operand[1].predicate) (op1, mode0))
|
mgl@1371
|
1732 |
+ {
|
mgl@1371
|
1733 |
+ /* If op1 is already a reg we must cast it to the correct mode. */
|
mgl@1371
|
1734 |
+ if (REG_P (op1))
|
mgl@1371
|
1735 |
+ op1 = convert_to_mode (mode0, op1, 1);
|
mgl@1371
|
1736 |
+ else
|
mgl@1371
|
1737 |
+ op1 = copy_to_mode_reg (mode0, op1);
|
mgl@1371
|
1738 |
+ }
|
mgl@1371
|
1739 |
+
|
mgl@1371
|
1740 |
+ if (!(*insn_data[icode].operand[2].predicate) (op2, mode1))
|
mgl@1371
|
1741 |
+ {
|
mgl@1371
|
1742 |
+ /* If op1 is already a reg we must cast it to the correct mode. */
|
mgl@1371
|
1743 |
+ if (REG_P (op2))
|
mgl@1371
|
1744 |
+ op2 = convert_to_mode (mode1, op2, 1);
|
mgl@1371
|
1745 |
+ else
|
mgl@1371
|
1746 |
+ op2 = copy_to_mode_reg (mode1, op2);
|
mgl@1371
|
1747 |
+ }
|
mgl@1371
|
1748 |
+
|
mgl@1371
|
1749 |
+ emit_move_insn (target, op0);
|
mgl@1371
|
1750 |
+
|
mgl@1371
|
1751 |
+ pat = GEN_FCN (icode) (target, op1, op2);
|
mgl@1371
|
1752 |
+ if (!pat)
|
mgl@1371
|
1753 |
+ return 0;
|
mgl@1371
|
1754 |
+ emit_insn (pat);
|
mgl@1371
|
1755 |
+ return target;
|
mgl@1371
|
1756 |
+ }
|
mgl@1371
|
1757 |
+ case AVR32_BUILTIN_MVRC_W:
|
mgl@1371
|
1758 |
+ case AVR32_BUILTIN_MVRC_D:
|
mgl@1371
|
1759 |
+ {
|
mgl@1371
|
1760 |
+ arg0 = TREE_VALUE (arglist);
|
mgl@1371
|
1761 |
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
|
mgl@1371
|
1762 |
+ arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
|
mgl@1371
|
1763 |
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1764 |
+ op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1765 |
+ op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1766 |
+
|
mgl@1371
|
1767 |
+ if (fcode == AVR32_BUILTIN_MVRC_W)
|
mgl@1371
|
1768 |
+ icode = CODE_FOR_mvrcsi;
|
mgl@1371
|
1769 |
+ else
|
mgl@1371
|
1770 |
+ icode = CODE_FOR_mvrcdi;
|
mgl@1371
|
1771 |
+
|
mgl@1371
|
1772 |
+ if (!(*insn_data[icode].operand[0].predicate) (op0, SImode))
|
mgl@1371
|
1773 |
+ {
|
mgl@1371
|
1774 |
+ error ("Parameter 1 is not a valid coprocessor number.");
|
mgl@1371
|
1775 |
+ error ("Number should be between 0 and 7.");
|
mgl@1371
|
1776 |
+ return NULL_RTX;
|
mgl@1371
|
1777 |
+ }
|
mgl@1371
|
1778 |
+
|
mgl@1371
|
1779 |
+ if (!(*insn_data[icode].operand[1].predicate) (op1, SImode))
|
mgl@1371
|
1780 |
+ {
|
mgl@1371
|
1781 |
+ error ("Parameter 2 is not a valid coprocessor register number.");
|
mgl@1371
|
1782 |
+ error ("Number should be between 0 and 15.");
|
mgl@1371
|
1783 |
+ return NULL_RTX;
|
mgl@1371
|
1784 |
+ }
|
mgl@1371
|
1785 |
+
|
mgl@1371
|
1786 |
+ if (GET_CODE (op2) == CONST_INT
|
mgl@1371
|
1787 |
+ || GET_CODE (op2) == CONST
|
mgl@1371
|
1788 |
+ || GET_CODE (op2) == SYMBOL_REF || GET_CODE (op2) == LABEL_REF)
|
mgl@1371
|
1789 |
+ {
|
mgl@1371
|
1790 |
+ op2 = force_const_mem (insn_data[icode].operand[2].mode, op2);
|
mgl@1371
|
1791 |
+ }
|
mgl@1371
|
1792 |
+
|
mgl@1371
|
1793 |
+ if (!(*insn_data[icode].operand[2].predicate) (op2, GET_MODE (op2)))
|
mgl@1371
|
1794 |
+ op2 = copy_to_mode_reg (insn_data[icode].operand[2].mode, op2);
|
mgl@1371
|
1795 |
+
|
mgl@1371
|
1796 |
+
|
mgl@1371
|
1797 |
+ pat = GEN_FCN (icode) (op0, op1, op2);
|
mgl@1371
|
1798 |
+ if (!pat)
|
mgl@1371
|
1799 |
+ return 0;
|
mgl@1371
|
1800 |
+ emit_insn (pat);
|
mgl@1371
|
1801 |
+
|
mgl@1371
|
1802 |
+ return NULL_RTX;
|
mgl@1371
|
1803 |
+ }
|
mgl@1371
|
1804 |
+ case AVR32_BUILTIN_COP:
|
mgl@1371
|
1805 |
+ {
|
mgl@1371
|
1806 |
+ rtx op3, op4;
|
mgl@1371
|
1807 |
+ tree arg3, arg4;
|
mgl@1371
|
1808 |
+ icode = CODE_FOR_cop;
|
mgl@1371
|
1809 |
+ arg0 = TREE_VALUE (arglist);
|
mgl@1371
|
1810 |
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
|
mgl@1371
|
1811 |
+ arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
|
mgl@1371
|
1812 |
+ arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
|
mgl@1371
|
1813 |
+ arg4 =
|
mgl@1371
|
1814 |
+ TREE_VALUE (TREE_CHAIN
|
mgl@1371
|
1815 |
+ (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist)))));
|
mgl@1371
|
1816 |
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1817 |
+ op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1818 |
+ op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1819 |
+ op3 = expand_expr (arg3, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1820 |
+ op4 = expand_expr (arg4, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1821 |
+
|
mgl@1371
|
1822 |
+ if (!(*insn_data[icode].operand[0].predicate) (op0, SImode))
|
mgl@1371
|
1823 |
+ {
|
mgl@1371
|
1824 |
+ error
|
mgl@1371
|
1825 |
+ ("Parameter 1 to __builtin_cop is not a valid coprocessor number.");
|
mgl@1371
|
1826 |
+ error ("Number should be between 0 and 7.");
|
mgl@1371
|
1827 |
+ return NULL_RTX;
|
mgl@1371
|
1828 |
+ }
|
mgl@1371
|
1829 |
+
|
mgl@1371
|
1830 |
+ if (!(*insn_data[icode].operand[1].predicate) (op1, SImode))
|
mgl@1371
|
1831 |
+ {
|
mgl@1371
|
1832 |
+ error
|
mgl@1371
|
1833 |
+ ("Parameter 2 to __builtin_cop is not a valid coprocessor register number.");
|
mgl@1371
|
1834 |
+ error ("Number should be between 0 and 15.");
|
mgl@1371
|
1835 |
+ return NULL_RTX;
|
mgl@1371
|
1836 |
+ }
|
mgl@1371
|
1837 |
+
|
mgl@1371
|
1838 |
+ if (!(*insn_data[icode].operand[2].predicate) (op2, SImode))
|
mgl@1371
|
1839 |
+ {
|
mgl@1371
|
1840 |
+ error
|
mgl@1371
|
1841 |
+ ("Parameter 3 to __builtin_cop is not a valid coprocessor register number.");
|
mgl@1371
|
1842 |
+ error ("Number should be between 0 and 15.");
|
mgl@1371
|
1843 |
+ return NULL_RTX;
|
mgl@1371
|
1844 |
+ }
|
mgl@1371
|
1845 |
+
|
mgl@1371
|
1846 |
+ if (!(*insn_data[icode].operand[3].predicate) (op3, SImode))
|
mgl@1371
|
1847 |
+ {
|
mgl@1371
|
1848 |
+ error
|
mgl@1371
|
1849 |
+ ("Parameter 4 to __builtin_cop is not a valid coprocessor register number.");
|
mgl@1371
|
1850 |
+ error ("Number should be between 0 and 15.");
|
mgl@1371
|
1851 |
+ return NULL_RTX;
|
mgl@1371
|
1852 |
+ }
|
mgl@1371
|
1853 |
+
|
mgl@1371
|
1854 |
+ if (!(*insn_data[icode].operand[4].predicate) (op4, SImode))
|
mgl@1371
|
1855 |
+ {
|
mgl@1371
|
1856 |
+ error
|
mgl@1371
|
1857 |
+ ("Parameter 5 to __builtin_cop is not a valid coprocessor operation.");
|
mgl@1371
|
1858 |
+ error ("Number should be between 0 and 127.");
|
mgl@1371
|
1859 |
+ return NULL_RTX;
|
mgl@1371
|
1860 |
+ }
|
mgl@1371
|
1861 |
+
|
mgl@1371
|
1862 |
+ pat = GEN_FCN (icode) (op0, op1, op2, op3, op4);
|
mgl@1371
|
1863 |
+ if (!pat)
|
mgl@1371
|
1864 |
+ return 0;
|
mgl@1371
|
1865 |
+ emit_insn (pat);
|
mgl@1371
|
1866 |
+
|
mgl@1371
|
1867 |
+ return target;
|
mgl@1371
|
1868 |
+ }
|
mgl@1371
|
1869 |
+ case AVR32_BUILTIN_MEMS:
|
mgl@1371
|
1870 |
+ case AVR32_BUILTIN_MEMC:
|
mgl@1371
|
1871 |
+ case AVR32_BUILTIN_MEMT:
|
mgl@1371
|
1872 |
+ {
|
mgl@1371
|
1873 |
+ if (!TARGET_RMW)
|
mgl@1371
|
1874 |
+ error ("Trying to use __builtin_mem(s/c/t) when target does not support RMW insns.");
|
mgl@1371
|
1875 |
+
|
mgl@1371
|
1876 |
+ switch (fcode) {
|
mgl@1371
|
1877 |
+ case AVR32_BUILTIN_MEMS:
|
mgl@1371
|
1878 |
+ icode = CODE_FOR_iorsi3;
|
mgl@1371
|
1879 |
+ break;
|
mgl@1371
|
1880 |
+ case AVR32_BUILTIN_MEMC:
|
mgl@1371
|
1881 |
+ icode = CODE_FOR_andsi3;
|
mgl@1371
|
1882 |
+ break;
|
mgl@1371
|
1883 |
+ case AVR32_BUILTIN_MEMT:
|
mgl@1371
|
1884 |
+ icode = CODE_FOR_xorsi3;
|
mgl@1371
|
1885 |
+ break;
|
mgl@1371
|
1886 |
+ }
|
mgl@1371
|
1887 |
+
|
mgl@1371
|
1888 |
+ arg0 = TREE_VALUE (arglist);
|
mgl@1371
|
1889 |
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
|
mgl@1371
|
1890 |
+ op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1891 |
+ if ( GET_CODE (op0) == SYMBOL_REF )
|
mgl@1371
|
1892 |
+ // This symbol must be RMW addressable
|
mgl@1371
|
1893 |
+ SYMBOL_REF_FLAGS (op0) |= (1 << SYMBOL_FLAG_RMW_ADDR_SHIFT);
|
mgl@1371
|
1894 |
+ op0 = gen_rtx_MEM(SImode, op0);
|
mgl@1371
|
1895 |
+ op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
|
mgl@1371
|
1896 |
+ mode0 = insn_data[icode].operand[1].mode;
|
mgl@1371
|
1897 |
+
|
mgl@1371
|
1898 |
+
|
mgl@1371
|
1899 |
+ if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
|
mgl@1371
|
1900 |
+ {
|
mgl@1371
|
1901 |
+ error ("Parameter 1 to __builtin_mem(s/c/t) must be a Ks15<<2 address or a rmw addressable symbol.");
|
mgl@1371
|
1902 |
+ }
|
mgl@1371
|
1903 |
+
|
mgl@1371
|
1904 |
+ if ( !CONST_INT_P (op1)
|
mgl@1371
|
1905 |
+ || INTVAL (op1) > 31
|
mgl@1371
|
1906 |
+ || INTVAL (op1) < 0 )
|
mgl@1371
|
1907 |
+ error ("Parameter 2 to __builtin_mem(s/c/t) must be a constant between 0 and 31.");
|
mgl@1371
|
1908 |
+
|
mgl@1371
|
1909 |
+ if ( fcode == AVR32_BUILTIN_MEMC )
|
mgl@1371
|
1910 |
+ op1 = GEN_INT((~(1 << INTVAL(op1)))&0xffffffff);
|
mgl@1371
|
1911 |
+ else
|
mgl@1371
|
1912 |
+ op1 = GEN_INT((1 << INTVAL(op1))&0xffffffff);
|
mgl@1371
|
1913 |
+ pat = GEN_FCN (icode) (op0, op0, op1);
|
mgl@1371
|
1914 |
+ if (!pat)
|
mgl@1371
|
1915 |
+ return 0;
|
mgl@1371
|
1916 |
+ emit_insn (pat);
|
mgl@1371
|
1917 |
+ return op0;
|
mgl@1371
|
1918 |
+ }
|
mgl@1371
|
1919 |
+
|
mgl@1371
|
1920 |
+ }
|
mgl@1371
|
1921 |
+
|
mgl@1371
|
1922 |
+ for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
|
mgl@1371
|
1923 |
+ if (d->code == fcode)
|
mgl@1371
|
1924 |
+ return avr32_expand_binop_builtin (d->icode, arglist, target);
|
mgl@1371
|
1925 |
+
|
mgl@1371
|
1926 |
+
|
mgl@1371
|
1927 |
+ /* @@@ Should really do something sensible here. */
|
mgl@1371
|
1928 |
+ return NULL_RTX;
|
mgl@1371
|
1929 |
+}
|
mgl@1371
|
1930 |
+
|
mgl@1371
|
1931 |
+
|
mgl@1371
|
1932 |
+/* Handle an "interrupt" or "isr" attribute;
|
mgl@1371
|
1933 |
+ arguments as in struct attribute_spec.handler. */
|
mgl@1371
|
1934 |
+
|
mgl@1371
|
1935 |
+static tree
|
mgl@1371
|
1936 |
+avr32_handle_isr_attribute (tree * node, tree name, tree args,
|
mgl@1371
|
1937 |
+ int flags, bool * no_add_attrs)
|
mgl@1371
|
1938 |
+{
|
mgl@1371
|
1939 |
+ if (DECL_P (*node))
|
mgl@1371
|
1940 |
+ {
|
mgl@1371
|
1941 |
+ if (TREE_CODE (*node) != FUNCTION_DECL)
|
mgl@1371
|
1942 |
+ {
|
mgl@1371
|
1943 |
+ warning (OPT_Wattributes,"`%s' attribute only applies to functions",
|
mgl@1371
|
1944 |
+ IDENTIFIER_POINTER (name));
|
mgl@1371
|
1945 |
+ *no_add_attrs = true;
|
mgl@1371
|
1946 |
+ }
|
mgl@1371
|
1947 |
+ /* FIXME: the argument if any is checked for type attributes; should it
|
mgl@1371
|
1948 |
+ be checked for decl ones? */
|
mgl@1371
|
1949 |
+ }
|
mgl@1371
|
1950 |
+ else
|
mgl@1371
|
1951 |
+ {
|
mgl@1371
|
1952 |
+ if (TREE_CODE (*node) == FUNCTION_TYPE
|
mgl@1371
|
1953 |
+ || TREE_CODE (*node) == METHOD_TYPE)
|
mgl@1371
|
1954 |
+ {
|
mgl@1371
|
1955 |
+ if (avr32_isr_value (args) == AVR32_FT_UNKNOWN)
|
mgl@1371
|
1956 |
+ {
|
mgl@1371
|
1957 |
+ warning (OPT_Wattributes,"`%s' attribute ignored", IDENTIFIER_POINTER (name));
|
mgl@1371
|
1958 |
+ *no_add_attrs = true;
|
mgl@1371
|
1959 |
+ }
|
mgl@1371
|
1960 |
+ }
|
mgl@1371
|
1961 |
+ else if (TREE_CODE (*node) == POINTER_TYPE
|
mgl@1371
|
1962 |
+ && (TREE_CODE (TREE_TYPE (*node)) == FUNCTION_TYPE
|
mgl@1371
|
1963 |
+ || TREE_CODE (TREE_TYPE (*node)) == METHOD_TYPE)
|
mgl@1371
|
1964 |
+ && avr32_isr_value (args) != AVR32_FT_UNKNOWN)
|
mgl@1371
|
1965 |
+ {
|
mgl@1371
|
1966 |
+ *node = build_variant_type_copy (*node);
|
mgl@1371
|
1967 |
+ TREE_TYPE (*node) = build_type_attribute_variant
|
mgl@1371
|
1968 |
+ (TREE_TYPE (*node),
|
mgl@1371
|
1969 |
+ tree_cons (name, args, TYPE_ATTRIBUTES (TREE_TYPE (*node))));
|
mgl@1371
|
1970 |
+ *no_add_attrs = true;
|
mgl@1371
|
1971 |
+ }
|
mgl@1371
|
1972 |
+ else
|
mgl@1371
|
1973 |
+ {
|
mgl@1371
|
1974 |
+ /* Possibly pass this attribute on from the type to a decl. */
|
mgl@1371
|
1975 |
+ if (flags & ((int) ATTR_FLAG_DECL_NEXT
|
mgl@1371
|
1976 |
+ | (int) ATTR_FLAG_FUNCTION_NEXT
|
mgl@1371
|
1977 |
+ | (int) ATTR_FLAG_ARRAY_NEXT))
|
mgl@1371
|
1978 |
+ {
|
mgl@1371
|
1979 |
+ *no_add_attrs = true;
|
mgl@1371
|
1980 |
+ return tree_cons (name, args, NULL_TREE);
|
mgl@1371
|
1981 |
+ }
|
mgl@1371
|
1982 |
+ else
|
mgl@1371
|
1983 |
+ {
|
mgl@1371
|
1984 |
+ warning (OPT_Wattributes,"`%s' attribute ignored", IDENTIFIER_POINTER (name));
|
mgl@1371
|
1985 |
+ }
|
mgl@1371
|
1986 |
+ }
|
mgl@1371
|
1987 |
+ }
|
mgl@1371
|
1988 |
+
|
mgl@1371
|
1989 |
+ return NULL_TREE;
|
mgl@1371
|
1990 |
+}
|
mgl@1371
|
1991 |
+
|
mgl@1371
|
1992 |
+/* Handle an attribute requiring a FUNCTION_DECL;
|
mgl@1371
|
1993 |
+ arguments as in struct attribute_spec.handler. */
|
mgl@1371
|
1994 |
+static tree
|
mgl@1371
|
1995 |
+avr32_handle_fndecl_attribute (tree * node, tree name,
|
mgl@1371
|
1996 |
+ tree args ATTRIBUTE_UNUSED,
|
mgl@1371
|
1997 |
+ int flags ATTRIBUTE_UNUSED,
|
mgl@1371
|
1998 |
+ bool * no_add_attrs)
|
mgl@1371
|
1999 |
+{
|
mgl@1371
|
2000 |
+ if (TREE_CODE (*node) != FUNCTION_DECL)
|
mgl@1371
|
2001 |
+ {
|
mgl@1371
|
2002 |
+ warning (OPT_Wattributes,"%qs attribute only applies to functions",
|
mgl@1371
|
2003 |
+ IDENTIFIER_POINTER (name));
|
mgl@1371
|
2004 |
+ *no_add_attrs = true;
|
mgl@1371
|
2005 |
+ }
|
mgl@1371
|
2006 |
+
|
mgl@1371
|
2007 |
+ return NULL_TREE;
|
mgl@1371
|
2008 |
+}
|
mgl@1371
|
2009 |
+
|
mgl@1371
|
2010 |
+
|
mgl@1371
|
2011 |
+/* Handle an acall attribute;
|
mgl@1371
|
2012 |
+ arguments as in struct attribute_spec.handler. */
|
mgl@1371
|
2013 |
+
|
mgl@1371
|
2014 |
+static tree
|
mgl@1371
|
2015 |
+avr32_handle_acall_attribute (tree * node, tree name,
|
mgl@1371
|
2016 |
+ tree args ATTRIBUTE_UNUSED,
|
mgl@1371
|
2017 |
+ int flags ATTRIBUTE_UNUSED, bool * no_add_attrs)
|
mgl@1371
|
2018 |
+{
|
mgl@1371
|
2019 |
+ if (TREE_CODE (*node) == FUNCTION_TYPE || TREE_CODE (*node) == METHOD_TYPE)
|
mgl@1371
|
2020 |
+ {
|
mgl@1371
|
2021 |
+ warning (OPT_Wattributes,"`%s' attribute not yet supported...",
|
mgl@1371
|
2022 |
+ IDENTIFIER_POINTER (name));
|
mgl@1371
|
2023 |
+ *no_add_attrs = true;
|
mgl@1371
|
2024 |
+ return NULL_TREE;
|
mgl@1371
|
2025 |
+ }
|
mgl@1371
|
2026 |
+
|
mgl@1371
|
2027 |
+ warning (OPT_Wattributes,"`%s' attribute only applies to functions",
|
mgl@1371
|
2028 |
+ IDENTIFIER_POINTER (name));
|
mgl@1371
|
2029 |
+ *no_add_attrs = true;
|
mgl@1371
|
2030 |
+ return NULL_TREE;
|
mgl@1371
|
2031 |
+}
|
mgl@1371
|
2032 |
+
|
mgl@1371
|
2033 |
+
|
mgl@1371
|
2034 |
+/* Return 0 if the attributes for two types are incompatible, 1 if they
|
mgl@1371
|
2035 |
+ are compatible, and 2 if they are nearly compatible (which causes a
|
mgl@1371
|
2036 |
+ warning to be generated). */
|
mgl@1371
|
2037 |
+
|
mgl@1371
|
2038 |
+static int
|
mgl@1371
|
2039 |
+avr32_comp_type_attributes (tree type1, tree type2)
|
mgl@1371
|
2040 |
+{
|
mgl@1371
|
2041 |
+ int acall1, acall2, isr1, isr2, naked1, naked2;
|
mgl@1371
|
2042 |
+
|
mgl@1371
|
2043 |
+ /* Check for mismatch of non-default calling convention. */
|
mgl@1371
|
2044 |
+ if (TREE_CODE (type1) != FUNCTION_TYPE)
|
mgl@1371
|
2045 |
+ return 1;
|
mgl@1371
|
2046 |
+
|
mgl@1371
|
2047 |
+ /* Check for mismatched call attributes. */
|
mgl@1371
|
2048 |
+ acall1 = lookup_attribute ("acall", TYPE_ATTRIBUTES (type1)) != NULL;
|
mgl@1371
|
2049 |
+ acall2 = lookup_attribute ("acall", TYPE_ATTRIBUTES (type2)) != NULL;
|
mgl@1371
|
2050 |
+ naked1 = lookup_attribute ("naked", TYPE_ATTRIBUTES (type1)) != NULL;
|
mgl@1371
|
2051 |
+ naked2 = lookup_attribute ("naked", TYPE_ATTRIBUTES (type2)) != NULL;
|
mgl@1371
|
2052 |
+ isr1 = lookup_attribute ("isr", TYPE_ATTRIBUTES (type1)) != NULL;
|
mgl@1371
|
2053 |
+ if (!isr1)
|
mgl@1371
|
2054 |
+ isr1 = lookup_attribute ("interrupt", TYPE_ATTRIBUTES (type1)) != NULL;
|
mgl@1371
|
2055 |
+
|
mgl@1371
|
2056 |
+ isr2 = lookup_attribute ("isr", TYPE_ATTRIBUTES (type2)) != NULL;
|
mgl@1371
|
2057 |
+ if (!isr2)
|
mgl@1371
|
2058 |
+ isr2 = lookup_attribute ("interrupt", TYPE_ATTRIBUTES (type2)) != NULL;
|
mgl@1371
|
2059 |
+
|
mgl@1371
|
2060 |
+ if ((acall1 && isr2)
|
mgl@1371
|
2061 |
+ || (acall2 && isr1) || (naked1 && isr2) || (naked2 && isr1))
|
mgl@1371
|
2062 |
+ return 0;
|
mgl@1371
|
2063 |
+
|
mgl@1371
|
2064 |
+ return 1;
|
mgl@1371
|
2065 |
+}
|
mgl@1371
|
2066 |
+
|
mgl@1371
|
2067 |
+
|
mgl@1371
|
2068 |
+/* Computes the type of the current function. */
|
mgl@1371
|
2069 |
+
|
mgl@1371
|
2070 |
+static unsigned long
|
mgl@1371
|
2071 |
+avr32_compute_func_type (void)
|
mgl@1371
|
2072 |
+{
|
mgl@1371
|
2073 |
+ unsigned long type = AVR32_FT_UNKNOWN;
|
mgl@1371
|
2074 |
+ tree a;
|
mgl@1371
|
2075 |
+ tree attr;
|
mgl@1371
|
2076 |
+
|
mgl@1371
|
2077 |
+ if (TREE_CODE (current_function_decl) != FUNCTION_DECL)
|
mgl@1371
|
2078 |
+ abort ();
|
mgl@1371
|
2079 |
+
|
mgl@1371
|
2080 |
+ /* Decide if the current function is volatile. Such functions never
|
mgl@1371
|
2081 |
+ return, and many memory cycles can be saved by not storing register
|
mgl@1371
|
2082 |
+ values that will never be needed again. This optimization was added to
|
mgl@1371
|
2083 |
+ speed up context switching in a kernel application. */
|
mgl@1371
|
2084 |
+ if (optimize > 0
|
mgl@1371
|
2085 |
+ && TREE_NOTHROW (current_function_decl)
|
mgl@1371
|
2086 |
+ && TREE_THIS_VOLATILE (current_function_decl))
|
mgl@1371
|
2087 |
+ type |= AVR32_FT_VOLATILE;
|
mgl@1371
|
2088 |
+
|
mgl@1371
|
2089 |
+ if (cfun->static_chain_decl != NULL)
|
mgl@1371
|
2090 |
+ type |= AVR32_FT_NESTED;
|
mgl@1371
|
2091 |
+
|
mgl@1371
|
2092 |
+ attr = DECL_ATTRIBUTES (current_function_decl);
|
mgl@1371
|
2093 |
+
|
mgl@1371
|
2094 |
+ a = lookup_attribute ("isr", attr);
|
mgl@1371
|
2095 |
+ if (a == NULL_TREE)
|
mgl@1371
|
2096 |
+ a = lookup_attribute ("interrupt", attr);
|
mgl@1371
|
2097 |
+
|
mgl@1371
|
2098 |
+ if (a == NULL_TREE)
|
mgl@1371
|
2099 |
+ type |= AVR32_FT_NORMAL;
|
mgl@1371
|
2100 |
+ else
|
mgl@1371
|
2101 |
+ type |= avr32_isr_value (TREE_VALUE (a));
|
mgl@1371
|
2102 |
+
|
mgl@1371
|
2103 |
+
|
mgl@1371
|
2104 |
+ a = lookup_attribute ("acall", attr);
|
mgl@1371
|
2105 |
+ if (a != NULL_TREE)
|
mgl@1371
|
2106 |
+ type |= AVR32_FT_ACALL;
|
mgl@1371
|
2107 |
+
|
mgl@1371
|
2108 |
+ a = lookup_attribute ("naked", attr);
|
mgl@1371
|
2109 |
+ if (a != NULL_TREE)
|
mgl@1371
|
2110 |
+ type |= AVR32_FT_NAKED;
|
mgl@1371
|
2111 |
+
|
mgl@1371
|
2112 |
+ return type;
|
mgl@1371
|
2113 |
+}
|
mgl@1371
|
2114 |
+
|
mgl@1371
|
2115 |
+/* Returns the type of the current function. */
|
mgl@1371
|
2116 |
+
|
mgl@1371
|
2117 |
+static unsigned long
|
mgl@1371
|
2118 |
+avr32_current_func_type (void)
|
mgl@1371
|
2119 |
+{
|
mgl@1371
|
2120 |
+ if (AVR32_FUNC_TYPE (cfun->machine->func_type) == AVR32_FT_UNKNOWN)
|
mgl@1371
|
2121 |
+ cfun->machine->func_type = avr32_compute_func_type ();
|
mgl@1371
|
2122 |
+
|
mgl@1371
|
2123 |
+ return cfun->machine->func_type;
|
mgl@1371
|
2124 |
+}
|
mgl@1371
|
2125 |
+
|
mgl@1371
|
2126 |
+/*
|
mgl@1371
|
2127 |
+ This target hook should return true if we should not pass type solely
|
mgl@1371
|
2128 |
+ in registers. The file expr.h defines a definition that is usually appropriate,
|
mgl@1371
|
2129 |
+ refer to expr.h for additional documentation.
|
mgl@1371
|
2130 |
+*/
|
mgl@1371
|
2131 |
+bool
|
mgl@1371
|
2132 |
+avr32_must_pass_in_stack (enum machine_mode mode ATTRIBUTE_UNUSED, tree type)
|
mgl@1371
|
2133 |
+{
|
mgl@1371
|
2134 |
+ if (type && AGGREGATE_TYPE_P (type)
|
mgl@1371
|
2135 |
+ /* If the alignment is less than the size then pass in the struct on
|
mgl@1371
|
2136 |
+ the stack. */
|
mgl@1371
|
2137 |
+ && ((unsigned int) TYPE_ALIGN_UNIT (type) <
|
mgl@1371
|
2138 |
+ (unsigned int) int_size_in_bytes (type))
|
mgl@1371
|
2139 |
+ /* If we support unaligned word accesses then structs of size 4 and 8
|
mgl@1371
|
2140 |
+ can have any alignment and still be passed in registers. */
|
mgl@1371
|
2141 |
+ && !(TARGET_UNALIGNED_WORD
|
mgl@1371
|
2142 |
+ && (int_size_in_bytes (type) == 4
|
mgl@1371
|
2143 |
+ || int_size_in_bytes (type) == 8))
|
mgl@1371
|
2144 |
+ /* Double word structs need only a word alignment. */
|
mgl@1371
|
2145 |
+ && !(int_size_in_bytes (type) == 8 && TYPE_ALIGN_UNIT (type) >= 4))
|
mgl@1371
|
2146 |
+ return true;
|
mgl@1371
|
2147 |
+
|
mgl@1371
|
2148 |
+ if (type && AGGREGATE_TYPE_P (type)
|
mgl@1371
|
2149 |
+ /* Structs of size 3,5,6,7 are always passed in registers. */
|
mgl@1371
|
2150 |
+ && (int_size_in_bytes (type) == 3
|
mgl@1371
|
2151 |
+ || int_size_in_bytes (type) == 5
|
mgl@1371
|
2152 |
+ || int_size_in_bytes (type) == 6 || int_size_in_bytes (type) == 7))
|
mgl@1371
|
2153 |
+ return true;
|
mgl@1371
|
2154 |
+
|
mgl@1371
|
2155 |
+
|
mgl@1371
|
2156 |
+ return (type && TREE_ADDRESSABLE (type));
|
mgl@1371
|
2157 |
+}
|
mgl@1371
|
2158 |
+
|
mgl@1371
|
2159 |
+
|
mgl@1371
|
2160 |
+bool
|
mgl@1371
|
2161 |
+avr32_strict_argument_naming (CUMULATIVE_ARGS * ca ATTRIBUTE_UNUSED)
|
mgl@1371
|
2162 |
+{
|
mgl@1371
|
2163 |
+ return true;
|
mgl@1371
|
2164 |
+}
|
mgl@1371
|
2165 |
+
|
mgl@1371
|
2166 |
+/*
|
mgl@1371
|
2167 |
+ This target hook should return true if an argument at the position indicated
|
mgl@1371
|
2168 |
+ by cum should be passed by reference. This predicate is queried after target
|
mgl@1371
|
2169 |
+ independent reasons for being passed by reference, such as TREE_ADDRESSABLE (type).
|
mgl@1371
|
2170 |
+
|
mgl@1371
|
2171 |
+ If the hook returns true, a copy of that argument is made in memory and a
|
mgl@1371
|
2172 |
+ pointer to the argument is passed instead of the argument itself. The pointer
|
mgl@1371
|
2173 |
+ is passed in whatever way is appropriate for passing a pointer to that type.
|
mgl@1371
|
2174 |
+*/
|
mgl@1371
|
2175 |
+bool
|
mgl@1371
|
2176 |
+avr32_pass_by_reference (CUMULATIVE_ARGS * cum ATTRIBUTE_UNUSED,
|
mgl@1371
|
2177 |
+ enum machine_mode mode ATTRIBUTE_UNUSED,
|
mgl@1371
|
2178 |
+ tree type, bool named ATTRIBUTE_UNUSED)
|
mgl@1371
|
2179 |
+{
|
mgl@1371
|
2180 |
+ return (type && (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST));
|
mgl@1371
|
2181 |
+}
|
mgl@1371
|
2182 |
+
|
mgl@1371
|
2183 |
+static int
|
mgl@1371
|
2184 |
+avr32_arg_partial_bytes (CUMULATIVE_ARGS * pcum ATTRIBUTE_UNUSED,
|
mgl@1371
|
2185 |
+ enum machine_mode mode ATTRIBUTE_UNUSED,
|
mgl@1371
|
2186 |
+ tree type ATTRIBUTE_UNUSED,
|
mgl@1371
|
2187 |
+ bool named ATTRIBUTE_UNUSED)
|
mgl@1371
|
2188 |
+{
|
mgl@1371
|
2189 |
+ return 0;
|
mgl@1371
|
2190 |
+}
|
mgl@1371
|
2191 |
+
|
mgl@1371
|
2192 |
+
|
mgl@1371
|
2193 |
+struct gcc_target targetm = TARGET_INITIALIZER;
|
mgl@1371
|
2194 |
+
|
mgl@1371
|
2195 |
+/*
|
mgl@1371
|
2196 |
+ Table used to convert from register number in the assembler instructions and
|
mgl@1371
|
2197 |
+ the register numbers used in gcc.
|
mgl@1371
|
2198 |
+*/
|
mgl@1371
|
2199 |
+const int avr32_function_arg_reglist[] = {
|
mgl@1371
|
2200 |
+ INTERNAL_REGNUM (12),
|
mgl@1371
|
2201 |
+ INTERNAL_REGNUM (11),
|
mgl@1371
|
2202 |
+ INTERNAL_REGNUM (10),
|
mgl@1371
|
2203 |
+ INTERNAL_REGNUM (9),
|
mgl@1371
|
2204 |
+ INTERNAL_REGNUM (8)
|
mgl@1371
|
2205 |
+};
|
mgl@1371
|
2206 |
+
|
mgl@1371
|
2207 |
+rtx avr32_compare_op0 = NULL_RTX;
|
mgl@1371
|
2208 |
+rtx avr32_compare_op1 = NULL_RTX;
|
mgl@1371
|
2209 |
+rtx avr32_compare_operator = NULL_RTX;
|
mgl@1371
|
2210 |
+rtx avr32_acc_cache = NULL_RTX;
|
mgl@1371
|
2211 |
+
|
mgl@1371
|
2212 |
+/*
|
mgl@1371
|
2213 |
+ Returns nonzero if it is allowed to store a value of mode mode in hard
|
mgl@1371
|
2214 |
+ register number regno.
|
mgl@1371
|
2215 |
+*/
|
mgl@1371
|
2216 |
+int
|
mgl@1371
|
2217 |
+avr32_hard_regno_mode_ok (int regnr, enum machine_mode mode)
|
mgl@1371
|
2218 |
+{
|
mgl@1371
|
2219 |
+ /* We allow only float modes in the fp-registers */
|
mgl@1371
|
2220 |
+ if (regnr >= FIRST_FP_REGNUM
|
mgl@1371
|
2221 |
+ && regnr <= LAST_FP_REGNUM && GET_MODE_CLASS (mode) != MODE_FLOAT)
|
mgl@1371
|
2222 |
+ {
|
mgl@1371
|
2223 |
+ return 0;
|
mgl@1371
|
2224 |
+ }
|
mgl@1371
|
2225 |
+
|
mgl@1371
|
2226 |
+ switch (mode)
|
mgl@1371
|
2227 |
+ {
|
mgl@1371
|
2228 |
+ case DImode: /* long long */
|
mgl@1371
|
2229 |
+ case DFmode: /* double */
|
mgl@1371
|
2230 |
+ case SCmode: /* __complex__ float */
|
mgl@1371
|
2231 |
+ case CSImode: /* __complex__ int */
|
mgl@1371
|
2232 |
+ if (regnr < 4)
|
mgl@1371
|
2233 |
+ { /* long long int not supported in r12, sp, lr
|
mgl@1371
|
2234 |
+ or pc. */
|
mgl@1371
|
2235 |
+ return 0;
|
mgl@1371
|
2236 |
+ }
|
mgl@1371
|
2237 |
+ else
|
mgl@1371
|
2238 |
+ {
|
mgl@1371
|
2239 |
+ if (regnr % 2) /* long long int has to be refered in even
|
mgl@1371
|
2240 |
+ registers. */
|
mgl@1371
|
2241 |
+ return 0;
|
mgl@1371
|
2242 |
+ else
|
mgl@1371
|
2243 |
+ return 1;
|
mgl@1371
|
2244 |
+ }
|
mgl@1371
|
2245 |
+ case CDImode: /* __complex__ long long */
|
mgl@1371
|
2246 |
+ case DCmode: /* __complex__ double */
|
mgl@1371
|
2247 |
+ case TImode: /* 16 bytes */
|
mgl@1371
|
2248 |
+ if (regnr < 7)
|
mgl@1371
|
2249 |
+ return 0;
|
mgl@1371
|
2250 |
+ else if (regnr % 2)
|
mgl@1371
|
2251 |
+ return 0;
|
mgl@1371
|
2252 |
+ else
|
mgl@1371
|
2253 |
+ return 1;
|
mgl@1371
|
2254 |
+ default:
|
mgl@1371
|
2255 |
+ return 1;
|
mgl@1371
|
2256 |
+ }
|
mgl@1371
|
2257 |
+}
|
mgl@1371
|
2258 |
+
|
mgl@1371
|
2259 |
+
|
mgl@1371
|
2260 |
+int
|
mgl@1371
|
2261 |
+avr32_rnd_operands (rtx add, rtx shift)
|
mgl@1371
|
2262 |
+{
|
mgl@1371
|
2263 |
+ if (GET_CODE (shift) == CONST_INT &&
|
mgl@1371
|
2264 |
+ GET_CODE (add) == CONST_INT && INTVAL (shift) > 0)
|
mgl@1371
|
2265 |
+ {
|
mgl@1371
|
2266 |
+ if ((1 << (INTVAL (shift) - 1)) == INTVAL (add))
|
mgl@1371
|
2267 |
+ return TRUE;
|
mgl@1371
|
2268 |
+ }
|
mgl@1371
|
2269 |
+
|
mgl@1371
|
2270 |
+ return FALSE;
|
mgl@1371
|
2271 |
+}
|
mgl@1371
|
2272 |
+
|
mgl@1371
|
2273 |
+
|
mgl@1371
|
2274 |
+
|
mgl@1371
|
2275 |
+int
|
mgl@1371
|
2276 |
+avr32_const_ok_for_constraint_p (HOST_WIDE_INT value, char c, const char *str)
|
mgl@1371
|
2277 |
+{
|
mgl@1371
|
2278 |
+ switch (c)
|
mgl@1371
|
2279 |
+ {
|
mgl@1371
|
2280 |
+ case 'K':
|
mgl@1371
|
2281 |
+ case 'I':
|
mgl@1371
|
2282 |
+ {
|
mgl@1371
|
2283 |
+ HOST_WIDE_INT min_value = 0, max_value = 0;
|
mgl@1371
|
2284 |
+ char size_str[3];
|
mgl@1371
|
2285 |
+ int const_size;
|
mgl@1371
|
2286 |
+
|
mgl@1371
|
2287 |
+ size_str[0] = str[2];
|
mgl@1371
|
2288 |
+ size_str[1] = str[3];
|
mgl@1371
|
2289 |
+ size_str[2] = '\0';
|
mgl@1371
|
2290 |
+ const_size = atoi (size_str);
|
mgl@1371
|
2291 |
+
|
mgl@1371
|
2292 |
+ if (toupper (str[1]) == 'U')
|
mgl@1371
|
2293 |
+ {
|
mgl@1371
|
2294 |
+ min_value = 0;
|
mgl@1371
|
2295 |
+ max_value = (1 << const_size) - 1;
|
mgl@1371
|
2296 |
+ }
|
mgl@1371
|
2297 |
+ else if (toupper (str[1]) == 'S')
|
mgl@1371
|
2298 |
+ {
|
mgl@1371
|
2299 |
+ min_value = -(1 << (const_size - 1));
|
mgl@1371
|
2300 |
+ max_value = (1 << (const_size - 1)) - 1;
|
mgl@1371
|
2301 |
+ }
|
mgl@1371
|
2302 |
+
|
mgl@1371
|
2303 |
+ if (c == 'I')
|
mgl@1371
|
2304 |
+ {
|
mgl@1371
|
2305 |
+ value = -value;
|
mgl@1371
|
2306 |
+ }
|
mgl@1371
|
2307 |
+
|
mgl@1371
|
2308 |
+ if (value >= min_value && value <= max_value)
|
mgl@1371
|
2309 |
+ {
|
mgl@1371
|
2310 |
+ return 1;
|
mgl@1371
|
2311 |
+ }
|
mgl@1371
|
2312 |
+ break;
|
mgl@1371
|
2313 |
+ }
|
mgl@1371
|
2314 |
+ case 'M':
|
mgl@1371
|
2315 |
+ return avr32_mask_upper_bits_operand (GEN_INT (value), VOIDmode);
|
mgl@1371
|
2316 |
+ case 'J':
|
mgl@1371
|
2317 |
+ return avr32_hi16_immediate_operand (GEN_INT (value), VOIDmode);
|
mgl@1371
|
2318 |
+ case 'O':
|
mgl@1371
|
2319 |
+ return one_bit_set_operand (GEN_INT (value), VOIDmode);
|
mgl@1371
|
2320 |
+ case 'N':
|
mgl@1371
|
2321 |
+ return one_bit_cleared_operand (GEN_INT (value), VOIDmode);
|
mgl@1371
|
2322 |
+ case 'L':
|
mgl@1371
|
2323 |
+ /* The lower 16-bits are set. */
|
mgl@1371
|
2324 |
+ return ((value & 0xffff) == 0xffff) ;
|
mgl@1371
|
2325 |
+ }
|
mgl@1371
|
2326 |
+
|
mgl@1371
|
2327 |
+ return 0;
|
mgl@1371
|
2328 |
+}
|
mgl@1371
|
2329 |
+
|
mgl@1371
|
2330 |
+
|
mgl@1371
|
2331 |
+/*Compute mask of which floating-point registers needs saving upon
|
mgl@1371
|
2332 |
+ entry to this function*/
|
mgl@1371
|
2333 |
+static unsigned long
|
mgl@1371
|
2334 |
+avr32_compute_save_fp_reg_mask (void)
|
mgl@1371
|
2335 |
+{
|
mgl@1371
|
2336 |
+ unsigned long func_type = avr32_current_func_type ();
|
mgl@1371
|
2337 |
+ unsigned int save_reg_mask = 0;
|
mgl@1371
|
2338 |
+ unsigned int reg;
|
mgl@1371
|
2339 |
+ unsigned int max_reg = 7;
|
mgl@1371
|
2340 |
+ int save_all_call_used_regs = FALSE;
|
mgl@1371
|
2341 |
+
|
mgl@1371
|
2342 |
+ /* This only applies for hardware floating-point implementation. */
|
mgl@1371
|
2343 |
+ if (!TARGET_HARD_FLOAT)
|
mgl@1371
|
2344 |
+ return 0;
|
mgl@1371
|
2345 |
+
|
mgl@1371
|
2346 |
+ if (IS_INTERRUPT (func_type))
|
mgl@1371
|
2347 |
+ {
|
mgl@1371
|
2348 |
+
|
mgl@1371
|
2349 |
+ /* Interrupt functions must not corrupt any registers, even call
|
mgl@1371
|
2350 |
+ clobbered ones. If this is a leaf function we can just examine the
|
mgl@1371
|
2351 |
+ registers used by the RTL, but otherwise we have to assume that
|
mgl@1371
|
2352 |
+ whatever function is called might clobber anything, and so we have
|
mgl@1371
|
2353 |
+ to save all the call-clobbered registers as well. */
|
mgl@1371
|
2354 |
+ max_reg = 13;
|
mgl@1371
|
2355 |
+ save_all_call_used_regs = !current_function_is_leaf;
|
mgl@1371
|
2356 |
+ }
|
mgl@1371
|
2357 |
+
|
mgl@1371
|
2358 |
+ /* All used registers used must be saved */
|
mgl@1371
|
2359 |
+ for (reg = 0; reg <= max_reg; reg++)
|
mgl@1371
|
2360 |
+ if (regs_ever_live[INTERNAL_FP_REGNUM (reg)]
|
mgl@1371
|
2361 |
+ || (save_all_call_used_regs
|
mgl@1371
|
2362 |
+ && call_used_regs[INTERNAL_FP_REGNUM (reg)]))
|
mgl@1371
|
2363 |
+ save_reg_mask |= (1 << reg);
|
mgl@1371
|
2364 |
+
|
mgl@1371
|
2365 |
+ return save_reg_mask;
|
mgl@1371
|
2366 |
+}
|
mgl@1371
|
2367 |
+
|
mgl@1371
|
2368 |
+/*Compute mask of registers which needs saving upon function entry */
|
mgl@1371
|
2369 |
+static unsigned long
|
mgl@1371
|
2370 |
+avr32_compute_save_reg_mask (int push)
|
mgl@1371
|
2371 |
+{
|
mgl@1371
|
2372 |
+ unsigned long func_type;
|
mgl@1371
|
2373 |
+ unsigned int save_reg_mask = 0;
|
mgl@1371
|
2374 |
+ unsigned int reg;
|
mgl@1371
|
2375 |
+
|
mgl@1371
|
2376 |
+ func_type = avr32_current_func_type ();
|
mgl@1371
|
2377 |
+
|
mgl@1371
|
2378 |
+ if (IS_INTERRUPT (func_type))
|
mgl@1371
|
2379 |
+ {
|
mgl@1371
|
2380 |
+ unsigned int max_reg = 12;
|
mgl@1371
|
2381 |
+
|
mgl@1371
|
2382 |
+
|
mgl@1371
|
2383 |
+ /* Get the banking scheme for the interrupt */
|
mgl@1371
|
2384 |
+ switch (func_type)
|
mgl@1371
|
2385 |
+ {
|
mgl@1371
|
2386 |
+ case AVR32_FT_ISR_FULL:
|
mgl@1371
|
2387 |
+ max_reg = 0;
|
mgl@1371
|
2388 |
+ break;
|
mgl@1371
|
2389 |
+ case AVR32_FT_ISR_HALF:
|
mgl@1371
|
2390 |
+ max_reg = 7;
|
mgl@1371
|
2391 |
+ break;
|
mgl@1371
|
2392 |
+ case AVR32_FT_ISR_NONE:
|
mgl@1371
|
2393 |
+ max_reg = 12;
|
mgl@1371
|
2394 |
+ break;
|
mgl@1371
|
2395 |
+ }
|
mgl@1371
|
2396 |
+
|
mgl@1371
|
2397 |
+ /* Interrupt functions must not corrupt any registers, even call
|
mgl@1371
|
2398 |
+ clobbered ones. If this is a leaf function we can just examine the
|
mgl@1371
|
2399 |
+ registers used by the RTL, but otherwise we have to assume that
|
mgl@1371
|
2400 |
+ whatever function is called might clobber anything, and so we have
|
mgl@1371
|
2401 |
+ to save all the call-clobbered registers as well. */
|
mgl@1371
|
2402 |
+
|
mgl@1371
|
2403 |
+ /* Need not push the registers r8-r12 for AVR32A architectures, as this
|
mgl@1371
|
2404 |
+ is automatially done in hardware. We also do not have any shadow
|
mgl@1371
|
2405 |
+ registers. */
|
mgl@1371
|
2406 |
+ if (TARGET_UARCH_AVR32A)
|
mgl@1371
|
2407 |
+ {
|
mgl@1371
|
2408 |
+ max_reg = 7;
|
mgl@1371
|
2409 |
+ func_type = AVR32_FT_ISR_NONE;
|
mgl@1371
|
2410 |
+ }
|
mgl@1371
|
2411 |
+
|
mgl@1371
|
2412 |
+ /* All registers which are used and is not shadowed must be saved */
|
mgl@1371
|
2413 |
+ for (reg = 0; reg <= max_reg; reg++)
|
mgl@1371
|
2414 |
+ if (regs_ever_live[INTERNAL_REGNUM (reg)]
|
mgl@1371
|
2415 |
+ || (!current_function_is_leaf
|
mgl@1371
|
2416 |
+ && call_used_regs[INTERNAL_REGNUM (reg)]))
|
mgl@1371
|
2417 |
+ save_reg_mask |= (1 << reg);
|
mgl@1371
|
2418 |
+
|
mgl@1371
|
2419 |
+ /* Check LR */
|
mgl@1371
|
2420 |
+ if ((regs_ever_live[LR_REGNUM]
|
mgl@1371
|
2421 |
+ || !current_function_is_leaf || frame_pointer_needed)
|
mgl@1371
|
2422 |
+ /* Only non-shadowed register models */
|
mgl@1371
|
2423 |
+ && (func_type == AVR32_FT_ISR_NONE))
|
mgl@1371
|
2424 |
+ save_reg_mask |= (1 << ASM_REGNUM (LR_REGNUM));
|
mgl@1371
|
2425 |
+
|
mgl@1371
|
2426 |
+ /* Make sure that the GOT register is pushed. */
|
mgl@1371
|
2427 |
+ if (max_reg >= ASM_REGNUM (PIC_OFFSET_TABLE_REGNUM)
|
mgl@1371
|
2428 |
+ && current_function_uses_pic_offset_table)
|
mgl@1371
|
2429 |
+ save_reg_mask |= (1 << ASM_REGNUM (PIC_OFFSET_TABLE_REGNUM));
|
mgl@1371
|
2430 |
+
|
mgl@1371
|
2431 |
+ }
|
mgl@1371
|
2432 |
+ else
|
mgl@1371
|
2433 |
+ {
|
mgl@1371
|
2434 |
+ int use_pushm = optimize_size;
|
mgl@1371
|
2435 |
+
|
mgl@1371
|
2436 |
+ /* In the normal case we only need to save those registers which are
|
mgl@1371
|
2437 |
+ call saved and which are used by this function. */
|
mgl@1371
|
2438 |
+ for (reg = 0; reg <= 7; reg++)
|
mgl@1371
|
2439 |
+ if (regs_ever_live[INTERNAL_REGNUM (reg)]
|
mgl@1371
|
2440 |
+ && !call_used_regs[INTERNAL_REGNUM (reg)])
|
mgl@1371
|
2441 |
+ save_reg_mask |= (1 << reg);
|
mgl@1371
|
2442 |
+
|
mgl@1371
|
2443 |
+ /* Make sure that the GOT register is pushed. */
|
mgl@1371
|
2444 |
+ if (current_function_uses_pic_offset_table)
|
mgl@1371
|
2445 |
+ save_reg_mask |= (1 << ASM_REGNUM (PIC_OFFSET_TABLE_REGNUM));
|
mgl@1371
|
2446 |
+
|
mgl@1371
|
2447 |
+
|
mgl@1371
|
2448 |
+ /* If we optimize for size and do not have anonymous arguments: use
|
mgl@1371
|
2449 |
+ popm/pushm always */
|
mgl@1371
|
2450 |
+ if (use_pushm)
|
mgl@1371
|
2451 |
+ {
|
mgl@1371
|
2452 |
+ if ((save_reg_mask & (1 << 0))
|
mgl@1371
|
2453 |
+ || (save_reg_mask & (1 << 1))
|
mgl@1371
|
2454 |
+ || (save_reg_mask & (1 << 2)) || (save_reg_mask & (1 << 3)))
|
mgl@1371
|
2455 |
+ save_reg_mask |= 0xf;
|
mgl@1371
|
2456 |
+
|
mgl@1371
|
2457 |
+ if ((save_reg_mask & (1 << 4))
|
mgl@1371
|
2458 |
+ || (save_reg_mask & (1 << 5))
|
mgl@1371
|
2459 |
+ || (save_reg_mask & (1 << 6)) || (save_reg_mask & (1 << 7)))
|
mgl@1371
|
2460 |
+ save_reg_mask |= 0xf0;
|
mgl@1371
|
2461 |
+
|
mgl@1371
|
2462 |
+ if ((save_reg_mask & (1 << 8)) || (save_reg_mask & (1 << 9)))
|
mgl@1371
|
2463 |
+ save_reg_mask |= 0x300;
|
mgl@1371
|
2464 |
+ }
|
mgl@1371
|
2465 |
+
|
mgl@1371
|
2466 |
+
|
mgl@1371
|
2467 |
+ /* Check LR */
|
mgl@1371
|
2468 |
+ if ((regs_ever_live[LR_REGNUM]
|
mgl@1371
|
2469 |
+ || !current_function_is_leaf
|
mgl@1371
|
2470 |
+ || (optimize_size
|
mgl@1371
|
2471 |
+ && save_reg_mask
|
mgl@1371
|
2472 |
+ && !current_function_calls_eh_return) || frame_pointer_needed))
|
mgl@1371
|
2473 |
+ {
|
mgl@1371
|
2474 |
+ if (push
|
mgl@1371
|
2475 |
+ /* Never pop LR into PC for functions which
|
mgl@1371
|
2476 |
+ calls __builtin_eh_return, since we need to
|
mgl@1371
|
2477 |
+ fix the SP after the restoring of the registers
|
mgl@1371
|
2478 |
+ and before returning. */
|
mgl@1371
|
2479 |
+ || current_function_calls_eh_return)
|
mgl@1371
|
2480 |
+ {
|
mgl@1371
|
2481 |
+ /* Push/Pop LR */
|
mgl@1371
|
2482 |
+ save_reg_mask |= (1 << ASM_REGNUM (LR_REGNUM));
|
mgl@1371
|
2483 |
+ }
|
mgl@1371
|
2484 |
+ else
|
mgl@1371
|
2485 |
+ {
|
mgl@1371
|
2486 |
+ /* Pop PC */
|
mgl@1371
|
2487 |
+ save_reg_mask |= (1 << ASM_REGNUM (PC_REGNUM));
|
mgl@1371
|
2488 |
+ }
|
mgl@1371
|
2489 |
+ }
|
mgl@1371
|
2490 |
+ }
|
mgl@1371
|
2491 |
+
|
mgl@1371
|
2492 |
+
|
mgl@1371
|
2493 |
+ /* Save registers so the exception handler can modify them. */
|
mgl@1371
|
2494 |
+ if (current_function_calls_eh_return)
|
mgl@1371
|
2495 |
+ {
|
mgl@1371
|
2496 |
+ unsigned int i;
|
mgl@1371
|
2497 |
+
|
mgl@1371
|
2498 |
+ for (i = 0;; i++)
|
mgl@1371
|
2499 |
+ {
|
mgl@1371
|
2500 |
+ reg = EH_RETURN_DATA_REGNO (i);
|
mgl@1371
|
2501 |
+ if (reg == INVALID_REGNUM)
|
mgl@1371
|
2502 |
+ break;
|
mgl@1371
|
2503 |
+ save_reg_mask |= 1 << ASM_REGNUM (reg);
|
mgl@1371
|
2504 |
+ }
|
mgl@1371
|
2505 |
+ }
|
mgl@1371
|
2506 |
+
|
mgl@1371
|
2507 |
+ return save_reg_mask;
|
mgl@1371
|
2508 |
+}
|
mgl@1371
|
2509 |
+
|
mgl@1371
|
2510 |
+/*Compute total size in bytes of all saved registers */
|
mgl@1371
|
2511 |
+static int
|
mgl@1371
|
2512 |
+avr32_get_reg_mask_size (int reg_mask)
|
mgl@1371
|
2513 |
+{
|
mgl@1371
|
2514 |
+ int reg, size;
|
mgl@1371
|
2515 |
+ size = 0;
|
mgl@1371
|
2516 |
+
|
mgl@1371
|
2517 |
+ for (reg = 0; reg <= 15; reg++)
|
mgl@1371
|
2518 |
+ if (reg_mask & (1 << reg))
|
mgl@1371
|
2519 |
+ size += 4;
|
mgl@1371
|
2520 |
+
|
mgl@1371
|
2521 |
+ return size;
|
mgl@1371
|
2522 |
+}
|
mgl@1371
|
2523 |
+
|
mgl@1371
|
2524 |
+/*Get a register from one of the registers which are saved onto the stack
|
mgl@1371
|
2525 |
+ upon function entry */
|
mgl@1371
|
2526 |
+
|
mgl@1371
|
2527 |
+static int
|
mgl@1371
|
2528 |
+avr32_get_saved_reg (int save_reg_mask)
|
mgl@1371
|
2529 |
+{
|
mgl@1371
|
2530 |
+ unsigned int reg;
|
mgl@1371
|
2531 |
+
|
mgl@1371
|
2532 |
+ /* Find the first register which is saved in the saved_reg_mask */
|
mgl@1371
|
2533 |
+ for (reg = 0; reg <= 15; reg++)
|
mgl@1371
|
2534 |
+ if (save_reg_mask & (1 << reg))
|
mgl@1371
|
2535 |
+ return reg;
|
mgl@1371
|
2536 |
+
|
mgl@1371
|
2537 |
+ return -1;
|
mgl@1371
|
2538 |
+}
|
mgl@1371
|
2539 |
+
|
mgl@1371
|
2540 |
+/* Return 1 if it is possible to return using a single instruction. */
|
mgl@1371
|
2541 |
+int
|
mgl@1371
|
2542 |
+avr32_use_return_insn (int iscond)
|
mgl@1371
|
2543 |
+{
|
mgl@1371
|
2544 |
+ unsigned int func_type = avr32_current_func_type ();
|
mgl@1371
|
2545 |
+ unsigned long saved_int_regs;
|
mgl@1371
|
2546 |
+ unsigned long saved_fp_regs;
|
mgl@1371
|
2547 |
+
|
mgl@1371
|
2548 |
+ /* Never use a return instruction before reload has run. */
|
mgl@1371
|
2549 |
+ if (!reload_completed)
|
mgl@1371
|
2550 |
+ return 0;
|
mgl@1371
|
2551 |
+
|
mgl@1371
|
2552 |
+ /* Must adjust the stack for vararg functions. */
|
mgl@1371
|
2553 |
+ if (current_function_args_info.uses_anonymous_args)
|
mgl@1371
|
2554 |
+ return 0;
|
mgl@1371
|
2555 |
+
|
mgl@1371
|
2556 |
+ /* If there a stack adjstment. */
|
mgl@1371
|
2557 |
+ if (get_frame_size ())
|
mgl@1371
|
2558 |
+ return 0;
|
mgl@1371
|
2559 |
+
|
mgl@1371
|
2560 |
+ saved_int_regs = avr32_compute_save_reg_mask (TRUE);
|
mgl@1371
|
2561 |
+ saved_fp_regs = avr32_compute_save_fp_reg_mask ();
|
mgl@1371
|
2562 |
+
|
mgl@1371
|
2563 |
+ /* Functions which have saved fp-regs on the stack can not be performed in
|
mgl@1371
|
2564 |
+ one instruction */
|
mgl@1371
|
2565 |
+ if (saved_fp_regs)
|
mgl@1371
|
2566 |
+ return 0;
|
mgl@1371
|
2567 |
+
|
mgl@1371
|
2568 |
+ /* Conditional returns can not be performed in one instruction if we need
|
mgl@1371
|
2569 |
+ to restore registers from the stack */
|
mgl@1371
|
2570 |
+ if (iscond && saved_int_regs)
|
mgl@1371
|
2571 |
+ return 0;
|
mgl@1371
|
2572 |
+
|
mgl@1371
|
2573 |
+ /* Conditional return can not be used for interrupt handlers. */
|
mgl@1371
|
2574 |
+ if (iscond && IS_INTERRUPT (func_type))
|
mgl@1371
|
2575 |
+ return 0;
|
mgl@1371
|
2576 |
+
|
mgl@1371
|
2577 |
+ /* For interrupt handlers which needs to pop registers */
|
mgl@1371
|
2578 |
+ if (saved_int_regs && IS_INTERRUPT (func_type))
|
mgl@1371
|
2579 |
+ return 0;
|
mgl@1371
|
2580 |
+
|
mgl@1371
|
2581 |
+
|
mgl@1371
|
2582 |
+ /* If there are saved registers but the LR isn't saved, then we need two
|
mgl@1371
|
2583 |
+ instructions for the return. */
|
mgl@1371
|
2584 |
+ if (saved_int_regs && !(saved_int_regs & (1 << ASM_REGNUM (LR_REGNUM))))
|
mgl@1371
|
2585 |
+ return 0;
|
mgl@1371
|
2586 |
+
|
mgl@1371
|
2587 |
+
|
mgl@1371
|
2588 |
+ return 1;
|
mgl@1371
|
2589 |
+}
|
mgl@1371
|
2590 |
+
|
mgl@1371
|
2591 |
+
|
mgl@1371
|
2592 |
+/*Generate some function prologue info in the assembly file*/
|
mgl@1371
|
2593 |
+
|
mgl@1371
|
2594 |
+void
|
mgl@1371
|
2595 |
+avr32_target_asm_function_prologue (FILE * f, HOST_WIDE_INT frame_size)
|
mgl@1371
|
2596 |
+{
|
mgl@1371
|
2597 |
+ if (IS_NAKED (avr32_current_func_type ()))
|
mgl@1371
|
2598 |
+ fprintf (f,
|
mgl@1371
|
2599 |
+ "\t# Function is naked: Prologue and epilogue provided by programmer\n");
|
mgl@1371
|
2600 |
+
|
mgl@1371
|
2601 |
+ if (IS_INTERRUPT (avr32_current_func_type ()))
|
mgl@1371
|
2602 |
+ {
|
mgl@1371
|
2603 |
+ switch (avr32_current_func_type ())
|
mgl@1371
|
2604 |
+ {
|
mgl@1371
|
2605 |
+ case AVR32_FT_ISR_FULL:
|
mgl@1371
|
2606 |
+ fprintf (f,
|
mgl@1371
|
2607 |
+ "\t# Interrupt Function: Fully shadowed register file\n");
|
mgl@1371
|
2608 |
+ break;
|
mgl@1371
|
2609 |
+ case AVR32_FT_ISR_HALF:
|
mgl@1371
|
2610 |
+ fprintf (f,
|
mgl@1371
|
2611 |
+ "\t# Interrupt Function: Half shadowed register file\n");
|
mgl@1371
|
2612 |
+ break;
|
mgl@1371
|
2613 |
+ default:
|
mgl@1371
|
2614 |
+ case AVR32_FT_ISR_NONE:
|
mgl@1371
|
2615 |
+ fprintf (f, "\t# Interrupt Function: No shadowed register file\n");
|
mgl@1371
|
2616 |
+ break;
|
mgl@1371
|
2617 |
+ }
|
mgl@1371
|
2618 |
+ }
|
mgl@1371
|
2619 |
+
|
mgl@1371
|
2620 |
+
|
mgl@1371
|
2621 |
+ fprintf (f, "\t# args = %i, frame = %li, pretend = %i\n",
|
mgl@1371
|
2622 |
+ current_function_args_size, frame_size,
|
mgl@1371
|
2623 |
+ current_function_pretend_args_size);
|
mgl@1371
|
2624 |
+
|
mgl@1371
|
2625 |
+ fprintf (f, "\t# frame_needed = %i, leaf_function = %i\n",
|
mgl@1371
|
2626 |
+ frame_pointer_needed, current_function_is_leaf);
|
mgl@1371
|
2627 |
+
|
mgl@1371
|
2628 |
+ fprintf (f, "\t# uses_anonymous_args = %i\n",
|
mgl@1371
|
2629 |
+ current_function_args_info.uses_anonymous_args);
|
mgl@1371
|
2630 |
+ if (current_function_calls_eh_return)
|
mgl@1371
|
2631 |
+ fprintf (f, "\t# Calls __builtin_eh_return.\n");
|
mgl@1371
|
2632 |
+
|
mgl@1371
|
2633 |
+}
|
mgl@1371
|
2634 |
+
|
mgl@1371
|
2635 |
+
|
mgl@1371
|
2636 |
+/* Generate and emit an insn that we will recognize as a pushm or stm.
|
mgl@1371
|
2637 |
+ Unfortunately, since this insn does not reflect very well the actual
|
mgl@1371
|
2638 |
+ semantics of the operation, we need to annotate the insn for the benefit
|
mgl@1371
|
2639 |
+ of DWARF2 frame unwind information. */
|
mgl@1371
|
2640 |
+
|
mgl@1371
|
2641 |
+int avr32_convert_to_reglist16 (int reglist8_vect);
|
mgl@1371
|
2642 |
+
|
mgl@1371
|
2643 |
+static rtx
|
mgl@1371
|
2644 |
+emit_multi_reg_push (int reglist, int usePUSHM)
|
mgl@1371
|
2645 |
+{
|
mgl@1371
|
2646 |
+ rtx insn;
|
mgl@1371
|
2647 |
+ rtx dwarf;
|
mgl@1371
|
2648 |
+ rtx tmp;
|
mgl@1371
|
2649 |
+ rtx reg;
|
mgl@1371
|
2650 |
+ int i;
|
mgl@1371
|
2651 |
+ int nr_regs;
|
mgl@1371
|
2652 |
+ int index = 0;
|
mgl@1371
|
2653 |
+
|
mgl@1371
|
2654 |
+ if (usePUSHM)
|
mgl@1371
|
2655 |
+ {
|
mgl@1371
|
2656 |
+ insn = emit_insn (gen_pushm (gen_rtx_CONST_INT (SImode, reglist)));
|
mgl@1371
|
2657 |
+ reglist = avr32_convert_to_reglist16 (reglist);
|
mgl@1371
|
2658 |
+ }
|
mgl@1371
|
2659 |
+ else
|
mgl@1371
|
2660 |
+ {
|
mgl@1371
|
2661 |
+ insn = emit_insn (gen_stm (stack_pointer_rtx,
|
mgl@1371
|
2662 |
+ gen_rtx_CONST_INT (SImode, reglist),
|
mgl@1371
|
2663 |
+ gen_rtx_CONST_INT (SImode, 1)));
|
mgl@1371
|
2664 |
+ }
|
mgl@1371
|
2665 |
+
|
mgl@1371
|
2666 |
+ nr_regs = avr32_get_reg_mask_size (reglist) / 4;
|
mgl@1371
|
2667 |
+ dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (nr_regs + 1));
|
mgl@1371
|
2668 |
+
|
mgl@1371
|
2669 |
+ for (i = 15; i >= 0; i--)
|
mgl@1371
|
2670 |
+ {
|
mgl@1371
|
2671 |
+ if (reglist & (1 << i))
|
mgl@1371
|
2672 |
+ {
|
mgl@1371
|
2673 |
+ reg = gen_rtx_REG (SImode, INTERNAL_REGNUM (i));
|
mgl@1371
|
2674 |
+ tmp = gen_rtx_SET (VOIDmode,
|
mgl@1371
|
2675 |
+ gen_rtx_MEM (SImode,
|
mgl@1371
|
2676 |
+ plus_constant (stack_pointer_rtx,
|
mgl@1371
|
2677 |
+ 4 * index)), reg);
|
mgl@1371
|
2678 |
+ RTX_FRAME_RELATED_P (tmp) = 1;
|
mgl@1371
|
2679 |
+ XVECEXP (dwarf, 0, 1 + index++) = tmp;
|
mgl@1371
|
2680 |
+ }
|
mgl@1371
|
2681 |
+ }
|
mgl@1371
|
2682 |
+
|
mgl@1371
|
2683 |
+ tmp = gen_rtx_SET (SImode,
|
mgl@1371
|
2684 |
+ stack_pointer_rtx,
|
mgl@1371
|
2685 |
+ gen_rtx_PLUS (SImode,
|
mgl@1371
|
2686 |
+ stack_pointer_rtx,
|
mgl@1371
|
2687 |
+ GEN_INT (-4 * nr_regs)));
|
mgl@1371
|
2688 |
+ RTX_FRAME_RELATED_P (tmp) = 1;
|
mgl@1371
|
2689 |
+ XVECEXP (dwarf, 0, 0) = tmp;
|
mgl@1371
|
2690 |
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
|
mgl@1371
|
2691 |
+ REG_NOTES (insn));
|
mgl@1371
|
2692 |
+ return insn;
|
mgl@1371
|
2693 |
+}
|
mgl@1371
|
2694 |
+
|
mgl@1371
|
2695 |
+
|
mgl@1371
|
2696 |
+static rtx
|
mgl@1371
|
2697 |
+emit_multi_fp_reg_push (int reglist)
|
mgl@1371
|
2698 |
+{
|
mgl@1371
|
2699 |
+ rtx insn;
|
mgl@1371
|
2700 |
+ rtx dwarf;
|
mgl@1371
|
2701 |
+ rtx tmp;
|
mgl@1371
|
2702 |
+ rtx reg;
|
mgl@1371
|
2703 |
+ int i;
|
mgl@1371
|
2704 |
+ int nr_regs;
|
mgl@1371
|
2705 |
+ int index = 0;
|
mgl@1371
|
2706 |
+
|
mgl@1371
|
2707 |
+ insn = emit_insn (gen_stm_fp (stack_pointer_rtx,
|
mgl@1371
|
2708 |
+ gen_rtx_CONST_INT (SImode, reglist),
|
mgl@1371
|
2709 |
+ gen_rtx_CONST_INT (SImode, 1)));
|
mgl@1371
|
2710 |
+
|
mgl@1371
|
2711 |
+ nr_regs = avr32_get_reg_mask_size (reglist) / 4;
|
mgl@1371
|
2712 |
+ dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (nr_regs + 1));
|
mgl@1371
|
2713 |
+
|
mgl@1371
|
2714 |
+ for (i = 15; i >= 0; i--)
|
mgl@1371
|
2715 |
+ {
|
mgl@1371
|
2716 |
+ if (reglist & (1 << i))
|
mgl@1371
|
2717 |
+ {
|
mgl@1371
|
2718 |
+ reg = gen_rtx_REG (SImode, INTERNAL_FP_REGNUM (i));
|
mgl@1371
|
2719 |
+ tmp = gen_rtx_SET (VOIDmode,
|
mgl@1371
|
2720 |
+ gen_rtx_MEM (SImode,
|
mgl@1371
|
2721 |
+ plus_constant (stack_pointer_rtx,
|
mgl@1371
|
2722 |
+ 4 * index)), reg);
|
mgl@1371
|
2723 |
+ RTX_FRAME_RELATED_P (tmp) = 1;
|
mgl@1371
|
2724 |
+ XVECEXP (dwarf, 0, 1 + index++) = tmp;
|
mgl@1371
|
2725 |
+ }
|
mgl@1371
|
2726 |
+ }
|
mgl@1371
|
2727 |
+
|
mgl@1371
|
2728 |
+ tmp = gen_rtx_SET (SImode,
|
mgl@1371
|
2729 |
+ stack_pointer_rtx,
|
mgl@1371
|
2730 |
+ gen_rtx_PLUS (SImode,
|
mgl@1371
|
2731 |
+ stack_pointer_rtx,
|
mgl@1371
|
2732 |
+ GEN_INT (-4 * nr_regs)));
|
mgl@1371
|
2733 |
+ RTX_FRAME_RELATED_P (tmp) = 1;
|
mgl@1371
|
2734 |
+ XVECEXP (dwarf, 0, 0) = tmp;
|
mgl@1371
|
2735 |
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
|
mgl@1371
|
2736 |
+ REG_NOTES (insn));
|
mgl@1371
|
2737 |
+ return insn;
|
mgl@1371
|
2738 |
+}
|
mgl@1371
|
2739 |
+
|
mgl@1371
|
2740 |
+rtx
|
mgl@1371
|
2741 |
+avr32_gen_load_multiple (rtx * regs, int count, rtx from,
|
mgl@1371
|
2742 |
+ int write_back, int in_struct_p, int scalar_p)
|
mgl@1371
|
2743 |
+{
|
mgl@1371
|
2744 |
+
|
mgl@1371
|
2745 |
+ rtx result;
|
mgl@1371
|
2746 |
+ int i = 0, j;
|
mgl@1371
|
2747 |
+
|
mgl@1371
|
2748 |
+ result =
|
mgl@1371
|
2749 |
+ gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count + (write_back ? 1 : 0)));
|
mgl@1371
|
2750 |
+
|
mgl@1371
|
2751 |
+ if (write_back)
|
mgl@1371
|
2752 |
+ {
|
mgl@1371
|
2753 |
+ XVECEXP (result, 0, 0)
|
mgl@1371
|
2754 |
+ = gen_rtx_SET (GET_MODE (from), from,
|
mgl@1371
|
2755 |
+ plus_constant (from, count * 4));
|
mgl@1371
|
2756 |
+ i = 1;
|
mgl@1371
|
2757 |
+ count++;
|
mgl@1371
|
2758 |
+ }
|
mgl@1371
|
2759 |
+
|
mgl@1371
|
2760 |
+
|
mgl@1371
|
2761 |
+ for (j = 0; i < count; i++, j++)
|
mgl@1371
|
2762 |
+ {
|
mgl@1371
|
2763 |
+ rtx unspec;
|
mgl@1371
|
2764 |
+ rtx mem = gen_rtx_MEM (SImode, plus_constant (from, j * 4));
|
mgl@1371
|
2765 |
+ MEM_IN_STRUCT_P (mem) = in_struct_p;
|
mgl@1371
|
2766 |
+ MEM_SCALAR_P (mem) = scalar_p;
|
mgl@1371
|
2767 |
+ unspec = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, mem), UNSPEC_LDM);
|
mgl@1371
|
2768 |
+ XVECEXP (result, 0, i) = gen_rtx_SET (VOIDmode, regs[j], unspec);
|
mgl@1371
|
2769 |
+ }
|
mgl@1371
|
2770 |
+
|
mgl@1371
|
2771 |
+ return result;
|
mgl@1371
|
2772 |
+}
|
mgl@1371
|
2773 |
+
|
mgl@1371
|
2774 |
+
|
mgl@1371
|
2775 |
+rtx
|
mgl@1371
|
2776 |
+avr32_gen_store_multiple (rtx * regs, int count, rtx to,
|
mgl@1371
|
2777 |
+ int in_struct_p, int scalar_p)
|
mgl@1371
|
2778 |
+{
|
mgl@1371
|
2779 |
+ rtx result;
|
mgl@1371
|
2780 |
+ int i = 0, j;
|
mgl@1371
|
2781 |
+
|
mgl@1371
|
2782 |
+ result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
|
mgl@1371
|
2783 |
+
|
mgl@1371
|
2784 |
+ for (j = 0; i < count; i++, j++)
|
mgl@1371
|
2785 |
+ {
|
mgl@1371
|
2786 |
+ rtx mem = gen_rtx_MEM (SImode, plus_constant (to, j * 4));
|
mgl@1371
|
2787 |
+ MEM_IN_STRUCT_P (mem) = in_struct_p;
|
mgl@1371
|
2788 |
+ MEM_SCALAR_P (mem) = scalar_p;
|
mgl@1371
|
2789 |
+ XVECEXP (result, 0, i)
|
mgl@1371
|
2790 |
+ = gen_rtx_SET (VOIDmode, mem,
|
mgl@1371
|
2791 |
+ gen_rtx_UNSPEC (VOIDmode,
|
mgl@1371
|
2792 |
+ gen_rtvec (1, regs[j]),
|
mgl@1371
|
2793 |
+ UNSPEC_STORE_MULTIPLE));
|
mgl@1371
|
2794 |
+ }
|
mgl@1371
|
2795 |
+
|
mgl@1371
|
2796 |
+ return result;
|
mgl@1371
|
2797 |
+}
|
mgl@1371
|
2798 |
+
|
mgl@1371
|
2799 |
+
|
mgl@1371
|
2800 |
+/* Move a block of memory if it is word aligned or we support unaligned
|
mgl@1371
|
2801 |
+ word memory accesses. The size must be maximum 64 bytes. */
|
mgl@1371
|
2802 |
+
|
mgl@1371
|
2803 |
+int
|
mgl@1371
|
2804 |
+avr32_gen_movmemsi (rtx * operands)
|
mgl@1371
|
2805 |
+{
|
mgl@1371
|
2806 |
+ HOST_WIDE_INT bytes_to_go;
|
mgl@1371
|
2807 |
+ rtx src, dst;
|
mgl@1371
|
2808 |
+ rtx st_src, st_dst;
|
mgl@1371
|
2809 |
+ int src_offset = 0, dst_offset = 0;
|
mgl@1371
|
2810 |
+ int block_size;
|
mgl@1371
|
2811 |
+ int dst_in_struct_p, src_in_struct_p;
|
mgl@1371
|
2812 |
+ int dst_scalar_p, src_scalar_p;
|
mgl@1371
|
2813 |
+ int unaligned;
|
mgl@1371
|
2814 |
+
|
mgl@1371
|
2815 |
+ if (GET_CODE (operands[2]) != CONST_INT
|
mgl@1371
|
2816 |
+ || GET_CODE (operands[3]) != CONST_INT
|
mgl@1371
|
2817 |
+ || INTVAL (operands[2]) > 64
|
mgl@1371
|
2818 |
+ || ((INTVAL (operands[3]) & 3) && !TARGET_UNALIGNED_WORD))
|
mgl@1371
|
2819 |
+ return 0;
|
mgl@1371
|
2820 |
+
|
mgl@1371
|
2821 |
+ unaligned = (INTVAL (operands[3]) & 3) != 0;
|
mgl@1371
|
2822 |
+
|
mgl@1371
|
2823 |
+ block_size = 4;
|
mgl@1371
|
2824 |
+
|
mgl@1371
|
2825 |
+ st_dst = XEXP (operands[0], 0);
|
mgl@1371
|
2826 |
+ st_src = XEXP (operands[1], 0);
|
mgl@1371
|
2827 |
+
|
mgl@1371
|
2828 |
+ dst_in_struct_p = MEM_IN_STRUCT_P (operands[0]);
|
mgl@1371
|
2829 |
+ dst_scalar_p = MEM_SCALAR_P (operands[0]);
|
mgl@1371
|
2830 |
+ src_in_struct_p = MEM_IN_STRUCT_P (operands[1]);
|
mgl@1371
|
2831 |
+ src_scalar_p = MEM_SCALAR_P (operands[1]);
|
mgl@1371
|
2832 |
+
|
mgl@1371
|
2833 |
+ dst = copy_to_mode_reg (SImode, st_dst);
|
mgl@1371
|
2834 |
+ src = copy_to_mode_reg (SImode, st_src);
|
mgl@1371
|
2835 |
+
|
mgl@1371
|
2836 |
+ bytes_to_go = INTVAL (operands[2]);
|
mgl@1371
|
2837 |
+
|
mgl@1371
|
2838 |
+ while (bytes_to_go)
|
mgl@1371
|
2839 |
+ {
|
mgl@1371
|
2840 |
+ enum machine_mode move_mode;
|
mgl@1371
|
2841 |
+ /* (Seems to be a problem with reloads for the movti pattern so this is
|
mgl@1371
|
2842 |
+ disabled until that problem is resolved)
|
mgl@1371
|
2843 |
+ UPDATE: Problem seems to be solved now.... */
|
mgl@1371
|
2844 |
+ if (bytes_to_go >= GET_MODE_SIZE (TImode) && !unaligned
|
mgl@1371
|
2845 |
+ /* Do not emit ldm/stm for UC3 as ld.d/st.d is more optimal. */
|
mgl@1371
|
2846 |
+ && !TARGET_ARCH_UC)
|
mgl@1371
|
2847 |
+ move_mode = TImode;
|
mgl@1371
|
2848 |
+ else if ((bytes_to_go >= GET_MODE_SIZE (DImode)) && !unaligned)
|
mgl@1371
|
2849 |
+ move_mode = DImode;
|
mgl@1371
|
2850 |
+ else if (bytes_to_go >= GET_MODE_SIZE (SImode))
|
mgl@1371
|
2851 |
+ move_mode = SImode;
|
mgl@1371
|
2852 |
+ else
|
mgl@1371
|
2853 |
+ move_mode = QImode;
|
mgl@1371
|
2854 |
+
|
mgl@1371
|
2855 |
+ {
|
mgl@1371
|
2856 |
+ rtx src_mem;
|
mgl@1371
|
2857 |
+ rtx dst_mem = gen_rtx_MEM (move_mode,
|
mgl@1371
|
2858 |
+ gen_rtx_PLUS (SImode, dst,
|
mgl@1371
|
2859 |
+ GEN_INT (dst_offset)));
|
mgl@1371
|
2860 |
+ dst_offset += GET_MODE_SIZE (move_mode);
|
mgl@1371
|
2861 |
+ if ( 0 /* This causes an error in GCC. Think there is
|
mgl@1371
|
2862 |
+ something wrong in the gcse pass which causes REQ_EQUIV notes
|
mgl@1371
|
2863 |
+ to be wrong so disabling it for now. */
|
mgl@1371
|
2864 |
+ && move_mode == TImode
|
mgl@1371
|
2865 |
+ && INTVAL (operands[2]) > GET_MODE_SIZE (TImode) )
|
mgl@1371
|
2866 |
+ {
|
mgl@1371
|
2867 |
+ src_mem = gen_rtx_MEM (move_mode,
|
mgl@1371
|
2868 |
+ gen_rtx_POST_INC (SImode, src));
|
mgl@1371
|
2869 |
+ }
|
mgl@1371
|
2870 |
+ else
|
mgl@1371
|
2871 |
+ {
|
mgl@1371
|
2872 |
+ src_mem = gen_rtx_MEM (move_mode,
|
mgl@1371
|
2873 |
+ gen_rtx_PLUS (SImode, src,
|
mgl@1371
|
2874 |
+ GEN_INT (src_offset)));
|
mgl@1371
|
2875 |
+ src_offset += GET_MODE_SIZE (move_mode);
|
mgl@1371
|
2876 |
+ }
|
mgl@1371
|
2877 |
+
|
mgl@1371
|
2878 |
+ bytes_to_go -= GET_MODE_SIZE (move_mode);
|
mgl@1371
|
2879 |
+
|
mgl@1371
|
2880 |
+ MEM_IN_STRUCT_P (dst_mem) = dst_in_struct_p;
|
mgl@1371
|
2881 |
+ MEM_SCALAR_P (dst_mem) = dst_scalar_p;
|
mgl@1371
|
2882 |
+
|
mgl@1371
|
2883 |
+ MEM_IN_STRUCT_P (src_mem) = src_in_struct_p;
|
mgl@1371
|
2884 |
+ MEM_SCALAR_P (src_mem) = src_scalar_p;
|
mgl@1371
|
2885 |
+ emit_move_insn (dst_mem, src_mem);
|
mgl@1371
|
2886 |
+
|
mgl@1371
|
2887 |
+ }
|
mgl@1371
|
2888 |
+ }
|
mgl@1371
|
2889 |
+
|
mgl@1371
|
2890 |
+ return 1;
|
mgl@1371
|
2891 |
+}
|
mgl@1371
|
2892 |
+
|
mgl@1371
|
2893 |
+
|
mgl@1371
|
2894 |
+
|
mgl@1371
|
2895 |
+/*Expand the prologue instruction*/
|
mgl@1371
|
2896 |
+void
|
mgl@1371
|
2897 |
+avr32_expand_prologue (void)
|
mgl@1371
|
2898 |
+{
|
mgl@1371
|
2899 |
+ rtx insn, dwarf;
|
mgl@1371
|
2900 |
+ unsigned long saved_reg_mask, saved_fp_reg_mask;
|
mgl@1371
|
2901 |
+ int reglist8 = 0;
|
mgl@1371
|
2902 |
+
|
mgl@1371
|
2903 |
+ /* Naked functions does not have a prologue */
|
mgl@1371
|
2904 |
+ if (IS_NAKED (avr32_current_func_type ()))
|
mgl@1371
|
2905 |
+ return;
|
mgl@1371
|
2906 |
+
|
mgl@1371
|
2907 |
+ saved_reg_mask = avr32_compute_save_reg_mask (TRUE);
|
mgl@1371
|
2908 |
+
|
mgl@1371
|
2909 |
+ if (saved_reg_mask)
|
mgl@1371
|
2910 |
+ {
|
mgl@1371
|
2911 |
+ /* Must push used registers */
|
mgl@1371
|
2912 |
+
|
mgl@1371
|
2913 |
+ /* Should we use POPM or LDM? */
|
mgl@1371
|
2914 |
+ int usePUSHM = TRUE;
|
mgl@1371
|
2915 |
+ reglist8 = 0;
|
mgl@1371
|
2916 |
+ if (((saved_reg_mask & (1 << 0)) ||
|
mgl@1371
|
2917 |
+ (saved_reg_mask & (1 << 1)) ||
|
mgl@1371
|
2918 |
+ (saved_reg_mask & (1 << 2)) || (saved_reg_mask & (1 << 3))))
|
mgl@1371
|
2919 |
+ {
|
mgl@1371
|
2920 |
+ /* One of R0-R3 should at least be pushed */
|
mgl@1371
|
2921 |
+ if (((saved_reg_mask & (1 << 0)) &&
|
mgl@1371
|
2922 |
+ (saved_reg_mask & (1 << 1)) &&
|
mgl@1371
|
2923 |
+ (saved_reg_mask & (1 << 2)) && (saved_reg_mask & (1 << 3))))
|
mgl@1371
|
2924 |
+ {
|
mgl@1371
|
2925 |
+ /* All should be pushed */
|
mgl@1371
|
2926 |
+ reglist8 |= 0x01;
|
mgl@1371
|
2927 |
+ }
|
mgl@1371
|
2928 |
+ else
|
mgl@1371
|
2929 |
+ {
|
mgl@1371
|
2930 |
+ usePUSHM = FALSE;
|
mgl@1371
|
2931 |
+ }
|
mgl@1371
|
2932 |
+ }
|
mgl@1371
|
2933 |
+
|
mgl@1371
|
2934 |
+ if (((saved_reg_mask & (1 << 4)) ||
|
mgl@1371
|
2935 |
+ (saved_reg_mask & (1 << 5)) ||
|
mgl@1371
|
2936 |
+ (saved_reg_mask & (1 << 6)) || (saved_reg_mask & (1 << 7))))
|
mgl@1371
|
2937 |
+ {
|
mgl@1371
|
2938 |
+ /* One of R4-R7 should at least be pushed */
|
mgl@1371
|
2939 |
+ if (((saved_reg_mask & (1 << 4)) &&
|
mgl@1371
|
2940 |
+ (saved_reg_mask & (1 << 5)) &&
|
mgl@1371
|
2941 |
+ (saved_reg_mask & (1 << 6)) && (saved_reg_mask & (1 << 7))))
|
mgl@1371
|
2942 |
+ {
|
mgl@1371
|
2943 |
+ if (usePUSHM)
|
mgl@1371
|
2944 |
+ /* All should be pushed */
|
mgl@1371
|
2945 |
+ reglist8 |= 0x02;
|
mgl@1371
|
2946 |
+ }
|
mgl@1371
|
2947 |
+ else
|
mgl@1371
|
2948 |
+ {
|
mgl@1371
|
2949 |
+ usePUSHM = FALSE;
|
mgl@1371
|
2950 |
+ }
|
mgl@1371
|
2951 |
+ }
|
mgl@1371
|
2952 |
+
|
mgl@1371
|
2953 |
+ if (((saved_reg_mask & (1 << 8)) || (saved_reg_mask & (1 << 9))))
|
mgl@1371
|
2954 |
+ {
|
mgl@1371
|
2955 |
+ /* One of R8-R9 should at least be pushed */
|
mgl@1371
|
2956 |
+ if (((saved_reg_mask & (1 << 8)) && (saved_reg_mask & (1 << 9))))
|
mgl@1371
|
2957 |
+ {
|
mgl@1371
|
2958 |
+ if (usePUSHM)
|
mgl@1371
|
2959 |
+ /* All should be pushed */
|
mgl@1371
|
2960 |
+ reglist8 |= 0x04;
|
mgl@1371
|
2961 |
+ }
|
mgl@1371
|
2962 |
+ else
|
mgl@1371
|
2963 |
+ {
|
mgl@1371
|
2964 |
+ usePUSHM = FALSE;
|
mgl@1371
|
2965 |
+ }
|
mgl@1371
|
2966 |
+ }
|
mgl@1371
|
2967 |
+
|
mgl@1371
|
2968 |
+ if (saved_reg_mask & (1 << 10))
|
mgl@1371
|
2969 |
+ reglist8 |= 0x08;
|
mgl@1371
|
2970 |
+
|
mgl@1371
|
2971 |
+ if (saved_reg_mask & (1 << 11))
|
mgl@1371
|
2972 |
+ reglist8 |= 0x10;
|
mgl@1371
|
2973 |
+
|
mgl@1371
|
2974 |
+ if (saved_reg_mask & (1 << 12))
|
mgl@1371
|
2975 |
+ reglist8 |= 0x20;
|
mgl@1371
|
2976 |
+
|
mgl@1371
|
2977 |
+ if (saved_reg_mask & (1 << ASM_REGNUM (LR_REGNUM)))
|
mgl@1371
|
2978 |
+ {
|
mgl@1371
|
2979 |
+ /* Push LR */
|
mgl@1371
|
2980 |
+ reglist8 |= 0x40;
|
mgl@1371
|
2981 |
+ }
|
mgl@1371
|
2982 |
+
|
mgl@1371
|
2983 |
+ if (usePUSHM)
|
mgl@1371
|
2984 |
+ {
|
mgl@1371
|
2985 |
+ insn = emit_multi_reg_push (reglist8, TRUE);
|
mgl@1371
|
2986 |
+ }
|
mgl@1371
|
2987 |
+ else
|
mgl@1371
|
2988 |
+ {
|
mgl@1371
|
2989 |
+ insn = emit_multi_reg_push (saved_reg_mask, FALSE);
|
mgl@1371
|
2990 |
+ }
|
mgl@1371
|
2991 |
+ RTX_FRAME_RELATED_P (insn) = 1;
|
mgl@1371
|
2992 |
+
|
mgl@1371
|
2993 |
+ /* Prevent this instruction from being scheduled after any other
|
mgl@1371
|
2994 |
+ instructions. */
|
mgl@1371
|
2995 |
+ emit_insn (gen_blockage ());
|
mgl@1371
|
2996 |
+ }
|
mgl@1371
|
2997 |
+
|
mgl@1371
|
2998 |
+ saved_fp_reg_mask = avr32_compute_save_fp_reg_mask ();
|
mgl@1371
|
2999 |
+ if (saved_fp_reg_mask)
|
mgl@1371
|
3000 |
+ {
|
mgl@1371
|
3001 |
+ insn = emit_multi_fp_reg_push (saved_fp_reg_mask);
|
mgl@1371
|
3002 |
+ RTX_FRAME_RELATED_P (insn) = 1;
|
mgl@1371
|
3003 |
+
|
mgl@1371
|
3004 |
+ /* Prevent this instruction from being scheduled after any other
|
mgl@1371
|
3005 |
+ instructions. */
|
mgl@1371
|
3006 |
+ emit_insn (gen_blockage ());
|
mgl@1371
|
3007 |
+ }
|
mgl@1371
|
3008 |
+
|
mgl@1371
|
3009 |
+ /* Set frame pointer */
|
mgl@1371
|
3010 |
+ if (frame_pointer_needed)
|
mgl@1371
|
3011 |
+ {
|
mgl@1371
|
3012 |
+ insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
|
mgl@1371
|
3013 |
+ RTX_FRAME_RELATED_P (insn) = 1;
|
mgl@1371
|
3014 |
+ }
|
mgl@1371
|
3015 |
+
|
mgl@1371
|
3016 |
+ if (get_frame_size () > 0)
|
mgl@1371
|
3017 |
+ {
|
mgl@1371
|
3018 |
+ if (avr32_const_ok_for_constraint_p (get_frame_size (), 'K', "Ks21"))
|
mgl@1371
|
3019 |
+ {
|
mgl@1371
|
3020 |
+ insn = emit_insn (gen_rtx_SET (SImode,
|
mgl@1371
|
3021 |
+ stack_pointer_rtx,
|
mgl@1371
|
3022 |
+ gen_rtx_PLUS (SImode,
|
mgl@1371
|
3023 |
+ stack_pointer_rtx,
|
mgl@1371
|
3024 |
+ gen_rtx_CONST_INT
|
mgl@1371
|
3025 |
+ (SImode,
|
mgl@1371
|
3026 |
+ -get_frame_size
|
mgl@1371
|
3027 |
+ ()))));
|
mgl@1371
|
3028 |
+ RTX_FRAME_RELATED_P (insn) = 1;
|
mgl@1371
|
3029 |
+ }
|
mgl@1371
|
3030 |
+ else
|
mgl@1371
|
3031 |
+ {
|
mgl@1371
|
3032 |
+ /* Immediate is larger than k21 We must either check if we can use
|
mgl@1371
|
3033 |
+ one of the pushed reegisters as temporary storage or we must
|
mgl@1371
|
3034 |
+ make us a temp register by pushing a register to the stack. */
|
mgl@1371
|
3035 |
+ rtx temp_reg, const_pool_entry, insn;
|
mgl@1371
|
3036 |
+ if (saved_reg_mask)
|
mgl@1371
|
3037 |
+ {
|
mgl@1371
|
3038 |
+ temp_reg =
|
mgl@1371
|
3039 |
+ gen_rtx_REG (SImode,
|
mgl@1371
|
3040 |
+ INTERNAL_REGNUM (avr32_get_saved_reg
|
mgl@1371
|
3041 |
+ (saved_reg_mask)));
|
mgl@1371
|
3042 |
+ }
|
mgl@1371
|
3043 |
+ else
|
mgl@1371
|
3044 |
+ {
|
mgl@1371
|
3045 |
+ temp_reg = gen_rtx_REG (SImode, INTERNAL_REGNUM (7));
|
mgl@1371
|
3046 |
+ emit_move_insn (gen_rtx_MEM
|
mgl@1371
|
3047 |
+ (SImode,
|
mgl@1371
|
3048 |
+ gen_rtx_PRE_DEC (SImode, stack_pointer_rtx)),
|
mgl@1371
|
3049 |
+ temp_reg);
|
mgl@1371
|
3050 |
+ }
|
mgl@1371
|
3051 |
+
|
mgl@1371
|
3052 |
+ const_pool_entry =
|
mgl@1371
|
3053 |
+ force_const_mem (SImode,
|
mgl@1371
|
3054 |
+ gen_rtx_CONST_INT (SImode, get_frame_size ()));
|
mgl@1371
|
3055 |
+ emit_move_insn (temp_reg, const_pool_entry);
|
mgl@1371
|
3056 |
+
|
mgl@1371
|
3057 |
+ insn = emit_insn (gen_rtx_SET (SImode,
|
mgl@1371
|
3058 |
+ stack_pointer_rtx,
|
mgl@1371
|
3059 |
+ gen_rtx_MINUS (SImode,
|
mgl@1371
|
3060 |
+ stack_pointer_rtx,
|
mgl@1371
|
3061 |
+ temp_reg)));
|
mgl@1371
|
3062 |
+
|
mgl@1371
|
3063 |
+ dwarf = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
|
mgl@1371
|
3064 |
+ gen_rtx_PLUS (SImode, stack_pointer_rtx,
|
mgl@1371
|
3065 |
+ GEN_INT (-get_frame_size ())));
|
mgl@1371
|
3066 |
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
|
mgl@1371
|
3067 |
+ dwarf, REG_NOTES (insn));
|
mgl@1371
|
3068 |
+ RTX_FRAME_RELATED_P (insn) = 1;
|
mgl@1371
|
3069 |
+
|
mgl@1371
|
3070 |
+ if (!saved_reg_mask)
|
mgl@1371
|
3071 |
+ {
|
mgl@1371
|
3072 |
+ insn =
|
mgl@1371
|
3073 |
+ emit_move_insn (temp_reg,
|
mgl@1371
|
3074 |
+ gen_rtx_MEM (SImode,
|
mgl@1371
|
3075 |
+ gen_rtx_POST_INC (SImode,
|
mgl@1371
|
3076 |
+ gen_rtx_REG
|
mgl@1371
|
3077 |
+ (SImode,
|
mgl@1371
|
3078 |
+ 13))));
|
mgl@1371
|
3079 |
+ }
|
mgl@1371
|
3080 |
+
|
mgl@1371
|
3081 |
+ /* Mark the temp register as dead */
|
mgl@1371
|
3082 |
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_DEAD, temp_reg,
|
mgl@1371
|
3083 |
+ REG_NOTES (insn));
|
mgl@1371
|
3084 |
+
|
mgl@1371
|
3085 |
+
|
mgl@1371
|
3086 |
+ }
|
mgl@1371
|
3087 |
+
|
mgl@1371
|
3088 |
+ /* Prevent the the stack adjustment to be scheduled after any
|
mgl@1371
|
3089 |
+ instructions using the frame pointer. */
|
mgl@1371
|
3090 |
+ emit_insn (gen_blockage ());
|
mgl@1371
|
3091 |
+ }
|
mgl@1371
|
3092 |
+
|
mgl@1371
|
3093 |
+ /* Load GOT */
|
mgl@1371
|
3094 |
+ if (flag_pic)
|
mgl@1371
|
3095 |
+ {
|
mgl@1371
|
3096 |
+ avr32_load_pic_register ();
|
mgl@1371
|
3097 |
+
|
mgl@1371
|
3098 |
+ /* gcc does not know that load or call instructions might use the pic
|
mgl@1371
|
3099 |
+ register so it might schedule these instructions before the loading
|
mgl@1371
|
3100 |
+ of the pic register. To avoid this emit a barrier for now. TODO!
|
mgl@1371
|
3101 |
+ Find out a better way to let gcc know which instructions might use
|
mgl@1371
|
3102 |
+ the pic register. */
|
mgl@1371
|
3103 |
+ emit_insn (gen_blockage ());
|
mgl@1371
|
3104 |
+ }
|
mgl@1371
|
3105 |
+ return;
|
mgl@1371
|
3106 |
+}
|
mgl@1371
|
3107 |
+
|
mgl@1371
|
3108 |
+void
|
mgl@1371
|
3109 |
+avr32_set_return_address (rtx source, rtx scratch)
|
mgl@1371
|
3110 |
+{
|
mgl@1371
|
3111 |
+ rtx addr;
|
mgl@1371
|
3112 |
+ unsigned long saved_regs;
|
mgl@1371
|
3113 |
+
|
mgl@1371
|
3114 |
+ saved_regs = avr32_compute_save_reg_mask (TRUE);
|
mgl@1371
|
3115 |
+
|
mgl@1371
|
3116 |
+ if (!(saved_regs & (1 << ASM_REGNUM (LR_REGNUM))))
|
mgl@1371
|
3117 |
+ emit_move_insn (gen_rtx_REG (Pmode, LR_REGNUM), source);
|
mgl@1371
|
3118 |
+ else
|
mgl@1371
|
3119 |
+ {
|
mgl@1371
|
3120 |
+ if (frame_pointer_needed)
|
mgl@1371
|
3121 |
+ addr = gen_rtx_REG (Pmode, FRAME_POINTER_REGNUM);
|
mgl@1371
|
3122 |
+ else
|
mgl@1371
|
3123 |
+ if (avr32_const_ok_for_constraint_p (get_frame_size (), 'K', "Ks16"))
|
mgl@1371
|
3124 |
+ {
|
mgl@1371
|
3125 |
+ addr = plus_constant (stack_pointer_rtx, get_frame_size ());
|
mgl@1371
|
3126 |
+ }
|
mgl@1371
|
3127 |
+ else
|
mgl@1371
|
3128 |
+ {
|
mgl@1371
|
3129 |
+ emit_insn (gen_movsi (scratch, GEN_INT (get_frame_size ())));
|
mgl@1371
|
3130 |
+ addr = scratch;
|
mgl@1371
|
3131 |
+ }
|
mgl@1371
|
3132 |
+ emit_move_insn (gen_rtx_MEM (Pmode, addr), source);
|
mgl@1371
|
3133 |
+ }
|
mgl@1371
|
3134 |
+}
|
mgl@1371
|
3135 |
+
|
mgl@1371
|
3136 |
+
|
mgl@1371
|
3137 |
+
|
mgl@1371
|
3138 |
+/* Return the length of INSN. LENGTH is the initial length computed by
|
mgl@1371
|
3139 |
+ attributes in the machine-description file. */
|
mgl@1371
|
3140 |
+
|
mgl@1371
|
3141 |
+int
|
mgl@1371
|
3142 |
+avr32_adjust_insn_length (rtx insn ATTRIBUTE_UNUSED,
|
mgl@1371
|
3143 |
+ int length ATTRIBUTE_UNUSED)
|
mgl@1371
|
3144 |
+{
|
mgl@1371
|
3145 |
+ return length;
|
mgl@1371
|
3146 |
+}
|
mgl@1371
|
3147 |
+
|
mgl@1371
|
3148 |
+void
|
mgl@1371
|
3149 |
+avr32_output_return_instruction (int single_ret_inst ATTRIBUTE_UNUSED,
|
mgl@1371
|
3150 |
+ int iscond ATTRIBUTE_UNUSED,
|
mgl@1371
|
3151 |
+ rtx cond ATTRIBUTE_UNUSED, rtx r12_imm)
|
mgl@1371
|
3152 |
+{
|
mgl@1371
|
3153 |
+
|
mgl@1371
|
3154 |
+ unsigned long saved_reg_mask, saved_fp_reg_mask;
|
mgl@1371
|
3155 |
+ int insert_ret = TRUE;
|
mgl@1371
|
3156 |
+ int reglist8 = 0;
|
mgl@1371
|
3157 |
+ int stack_adjustment = get_frame_size ();
|
mgl@1371
|
3158 |
+ unsigned int func_type = avr32_current_func_type ();
|
mgl@1371
|
3159 |
+ FILE *f = asm_out_file;
|
mgl@1371
|
3160 |
+
|
mgl@1371
|
3161 |
+ /* Naked functions does not have an epilogue */
|
mgl@1371
|
3162 |
+ if (IS_NAKED (func_type))
|
mgl@1371
|
3163 |
+ return;
|
mgl@1371
|
3164 |
+
|
mgl@1371
|
3165 |
+ saved_fp_reg_mask = avr32_compute_save_fp_reg_mask ();
|
mgl@1371
|
3166 |
+
|
mgl@1371
|
3167 |
+ saved_reg_mask = avr32_compute_save_reg_mask (FALSE);
|
mgl@1371
|
3168 |
+
|
mgl@1371
|
3169 |
+ /* Reset frame pointer */
|
mgl@1371
|
3170 |
+ if (stack_adjustment > 0)
|
mgl@1371
|
3171 |
+ {
|
mgl@1371
|
3172 |
+ if (avr32_const_ok_for_constraint_p (stack_adjustment, 'I', "Is21"))
|
mgl@1371
|
3173 |
+ {
|
mgl@1371
|
3174 |
+ fprintf (f, "\tsub\tsp, %i # Reset Frame Pointer\n",
|
mgl@1371
|
3175 |
+ -stack_adjustment);
|
mgl@1371
|
3176 |
+ }
|
mgl@1371
|
3177 |
+ else
|
mgl@1371
|
3178 |
+ {
|
mgl@1371
|
3179 |
+ /* TODO! Is it safe to use r8 as scratch?? */
|
mgl@1371
|
3180 |
+ fprintf (f, "\tmov\tr8, lo(%i) # Reset Frame Pointer\n",
|
mgl@1371
|
3181 |
+ -stack_adjustment);
|
mgl@1371
|
3182 |
+ fprintf (f, "\torh\tr8, hi(%i) # Reset Frame Pointer\n",
|
mgl@1371
|
3183 |
+ -stack_adjustment);
|
mgl@1371
|
3184 |
+ fprintf (f, "\tadd\tsp, r8 # Reset Frame Pointer\n");
|
mgl@1371
|
3185 |
+ }
|
mgl@1371
|
3186 |
+ }
|
mgl@1371
|
3187 |
+
|
mgl@1371
|
3188 |
+ if (saved_fp_reg_mask)
|
mgl@1371
|
3189 |
+ {
|
mgl@1371
|
3190 |
+ char reglist[64]; /* 64 bytes should be enough... */
|
mgl@1371
|
3191 |
+ avr32_make_fp_reglist_w (saved_fp_reg_mask, (char *) reglist);
|
mgl@1371
|
3192 |
+ fprintf (f, "\tldcm.w\tcp0, sp++, %s\n", reglist);
|
mgl@1371
|
3193 |
+ if (saved_fp_reg_mask & ~0xff)
|
mgl@1371
|
3194 |
+ {
|
mgl@1371
|
3195 |
+ saved_fp_reg_mask &= ~0xff;
|
mgl@1371
|
3196 |
+ avr32_make_fp_reglist_d (saved_fp_reg_mask, (char *) reglist);
|
mgl@1371
|
3197 |
+ fprintf (f, "\tldcm.d\tcp0, sp++, %s\n", reglist);
|
mgl@1371
|
3198 |
+ }
|
mgl@1371
|
3199 |
+ }
|
mgl@1371
|
3200 |
+
|
mgl@1371
|
3201 |
+ if (saved_reg_mask)
|
mgl@1371
|
3202 |
+ {
|
mgl@1371
|
3203 |
+ /* Must pop used registers */
|
mgl@1371
|
3204 |
+
|
mgl@1371
|
3205 |
+ /* Should we use POPM or LDM? */
|
mgl@1371
|
3206 |
+ int usePOPM = TRUE;
|
mgl@1371
|
3207 |
+ if (((saved_reg_mask & (1 << 0)) ||
|
mgl@1371
|
3208 |
+ (saved_reg_mask & (1 << 1)) ||
|
mgl@1371
|
3209 |
+ (saved_reg_mask & (1 << 2)) || (saved_reg_mask & (1 << 3))))
|
mgl@1371
|
3210 |
+ {
|
mgl@1371
|
3211 |
+ /* One of R0-R3 should at least be popped */
|
mgl@1371
|
3212 |
+ if (((saved_reg_mask & (1 << 0)) &&
|
mgl@1371
|
3213 |
+ (saved_reg_mask & (1 << 1)) &&
|
mgl@1371
|
3214 |
+ (saved_reg_mask & (1 << 2)) && (saved_reg_mask & (1 << 3))))
|
mgl@1371
|
3215 |
+ {
|
mgl@1371
|
3216 |
+ /* All should be popped */
|
mgl@1371
|
3217 |
+ reglist8 |= 0x01;
|
mgl@1371
|
3218 |
+ }
|
mgl@1371
|
3219 |
+ else
|
mgl@1371
|
3220 |
+ {
|
mgl@1371
|
3221 |
+ usePOPM = FALSE;
|
mgl@1371
|
3222 |
+ }
|
mgl@1371
|
3223 |
+ }
|
mgl@1371
|
3224 |
+
|
mgl@1371
|
3225 |
+ if (((saved_reg_mask & (1 << 4)) ||
|
mgl@1371
|
3226 |
+ (saved_reg_mask & (1 << 5)) ||
|
mgl@1371
|
3227 |
+ (saved_reg_mask & (1 << 6)) || (saved_reg_mask & (1 << 7))))
|
mgl@1371
|
3228 |
+ {
|
mgl@1371
|
3229 |
+ /* One of R0-R3 should at least be popped */
|
mgl@1371
|
3230 |
+ if (((saved_reg_mask & (1 << 4)) &&
|
mgl@1371
|
3231 |
+ (saved_reg_mask & (1 << 5)) &&
|
mgl@1371
|
3232 |
+ (saved_reg_mask & (1 << 6)) && (saved_reg_mask & (1 << 7))))
|
mgl@1371
|
3233 |
+ {
|
mgl@1371
|
3234 |
+ if (usePOPM)
|
mgl@1371
|
3235 |
+ /* All should be popped */
|
mgl@1371
|
3236 |
+ reglist8 |= 0x02;
|
mgl@1371
|
3237 |
+ }
|
mgl@1371
|
3238 |
+ else
|
mgl@1371
|
3239 |
+ {
|
mgl@1371
|
3240 |
+ usePOPM = FALSE;
|
mgl@1371
|
3241 |
+ }
|
mgl@1371
|
3242 |
+ }
|
mgl@1371
|
3243 |
+
|
mgl@1371
|
3244 |
+ if (((saved_reg_mask & (1 << 8)) || (saved_reg_mask & (1 << 9))))
|
mgl@1371
|
3245 |
+ {
|
mgl@1371
|
3246 |
+ /* One of R8-R9 should at least be pushed */
|
mgl@1371
|
3247 |
+ if (((saved_reg_mask & (1 << 8)) && (saved_reg_mask & (1 << 9))))
|
mgl@1371
|
3248 |
+ {
|
mgl@1371
|
3249 |
+ if (usePOPM)
|
mgl@1371
|
3250 |
+ /* All should be pushed */
|
mgl@1371
|
3251 |
+ reglist8 |= 0x04;
|
mgl@1371
|
3252 |
+ }
|
mgl@1371
|
3253 |
+ else
|
mgl@1371
|
3254 |
+ {
|
mgl@1371
|
3255 |
+ usePOPM = FALSE;
|
mgl@1371
|
3256 |
+ }
|
mgl@1371
|
3257 |
+ }
|
mgl@1371
|
3258 |
+
|
mgl@1371
|
3259 |
+ if (saved_reg_mask & (1 << 10))
|
mgl@1371
|
3260 |
+ reglist8 |= 0x08;
|
mgl@1371
|
3261 |
+
|
mgl@1371
|
3262 |
+ if (saved_reg_mask & (1 << 11))
|
mgl@1371
|
3263 |
+ reglist8 |= 0x10;
|
mgl@1371
|
3264 |
+
|
mgl@1371
|
3265 |
+ if (saved_reg_mask & (1 << 12))
|
mgl@1371
|
3266 |
+ reglist8 |= 0x20;
|
mgl@1371
|
3267 |
+
|
mgl@1371
|
3268 |
+ if (saved_reg_mask & (1 << ASM_REGNUM (LR_REGNUM)))
|
mgl@1371
|
3269 |
+ /* Pop LR */
|
mgl@1371
|
3270 |
+ reglist8 |= 0x40;
|
mgl@1371
|
3271 |
+
|
mgl@1371
|
3272 |
+ if (saved_reg_mask & (1 << ASM_REGNUM (PC_REGNUM)))
|
mgl@1371
|
3273 |
+ /* Pop LR into PC. */
|
mgl@1371
|
3274 |
+ reglist8 |= 0x80;
|
mgl@1371
|
3275 |
+
|
mgl@1371
|
3276 |
+ if (usePOPM)
|
mgl@1371
|
3277 |
+ {
|
mgl@1371
|
3278 |
+ char reglist[64]; /* 64 bytes should be enough... */
|
mgl@1371
|
3279 |
+ avr32_make_reglist8 (reglist8, (char *) reglist);
|
mgl@1371
|
3280 |
+
|
mgl@1371
|
3281 |
+ if (reglist8 & 0x80)
|
mgl@1371
|
3282 |
+ /* This instruction is also a return */
|
mgl@1371
|
3283 |
+ insert_ret = FALSE;
|
mgl@1371
|
3284 |
+
|
mgl@1371
|
3285 |
+ if (r12_imm && !insert_ret)
|
mgl@1371
|
3286 |
+ fprintf (f, "\tpopm\t%s, r12=%li\n", reglist, INTVAL (r12_imm));
|
mgl@1371
|
3287 |
+ else
|
mgl@1371
|
3288 |
+ fprintf (f, "\tpopm\t%s\n", reglist);
|
mgl@1371
|
3289 |
+
|
mgl@1371
|
3290 |
+ }
|
mgl@1371
|
3291 |
+ else
|
mgl@1371
|
3292 |
+ {
|
mgl@1371
|
3293 |
+ char reglist[64]; /* 64 bytes should be enough... */
|
mgl@1371
|
3294 |
+ avr32_make_reglist16 (saved_reg_mask, (char *) reglist);
|
mgl@1371
|
3295 |
+ if (saved_reg_mask & (1 << ASM_REGNUM (PC_REGNUM)))
|
mgl@1371
|
3296 |
+ /* This instruction is also a return */
|
mgl@1371
|
3297 |
+ insert_ret = FALSE;
|
mgl@1371
|
3298 |
+
|
mgl@1371
|
3299 |
+ if (r12_imm && !insert_ret)
|
mgl@1371
|
3300 |
+ fprintf (f, "\tldm\tsp++, %s, r12=%li\n", reglist,
|
mgl@1371
|
3301 |
+ INTVAL (r12_imm));
|
mgl@1371
|
3302 |
+ else
|
mgl@1371
|
3303 |
+ fprintf (f, "\tldm\tsp++, %s\n", reglist);
|
mgl@1371
|
3304 |
+
|
mgl@1371
|
3305 |
+ }
|
mgl@1371
|
3306 |
+
|
mgl@1371
|
3307 |
+ }
|
mgl@1371
|
3308 |
+
|
mgl@1371
|
3309 |
+ /* Stack adjustment for exception handler. */
|
mgl@1371
|
3310 |
+ if (current_function_calls_eh_return)
|
mgl@1371
|
3311 |
+ fprintf (f, "\tadd\tsp, r%d\n", ASM_REGNUM (EH_RETURN_STACKADJ_REGNO));
|
mgl@1371
|
3312 |
+
|
mgl@1371
|
3313 |
+
|
mgl@1371
|
3314 |
+ if (IS_INTERRUPT (func_type))
|
mgl@1371
|
3315 |
+ {
|
mgl@1371
|
3316 |
+ fprintf (f, "\trete\n");
|
mgl@1371
|
3317 |
+ }
|
mgl@1371
|
3318 |
+ else if (insert_ret)
|
mgl@1371
|
3319 |
+ {
|
mgl@1371
|
3320 |
+ if (r12_imm)
|
mgl@1371
|
3321 |
+ fprintf (f, "\tretal\t%li\n", INTVAL (r12_imm));
|
mgl@1371
|
3322 |
+ else
|
mgl@1371
|
3323 |
+ fprintf (f, "\tretal\tr12\n");
|
mgl@1371
|
3324 |
+ }
|
mgl@1371
|
3325 |
+}
|
mgl@1371
|
3326 |
+
|
mgl@1371
|
3327 |
+/* Function for converting a fp-register mask to a
|
mgl@1371
|
3328 |
+ reglistCPD8 register list string. */
|
mgl@1371
|
3329 |
+void
|
mgl@1371
|
3330 |
+avr32_make_fp_reglist_d (int reglist_mask, char *reglist_string)
|
mgl@1371
|
3331 |
+{
|
mgl@1371
|
3332 |
+ int i;
|
mgl@1371
|
3333 |
+
|
mgl@1371
|
3334 |
+ /* Make sure reglist_string is empty */
|
mgl@1371
|
3335 |
+ reglist_string[0] = '\0';
|
mgl@1371
|
3336 |
+
|
mgl@1371
|
3337 |
+ for (i = 0; i < NUM_FP_REGS; i += 2)
|
mgl@1371
|
3338 |
+ {
|
mgl@1371
|
3339 |
+ if (reglist_mask & (1 << i))
|
mgl@1371
|
3340 |
+ {
|
mgl@1371
|
3341 |
+ strlen (reglist_string) ?
|
mgl@1371
|
3342 |
+ sprintf (reglist_string, "%s, %s-%s", reglist_string,
|
mgl@1371
|
3343 |
+ reg_names[INTERNAL_FP_REGNUM (i)],
|
mgl@1371
|
3344 |
+ reg_names[INTERNAL_FP_REGNUM (i + 1)]) :
|
mgl@1371
|
3345 |
+ sprintf (reglist_string, "%s-%s",
|
mgl@1371
|
3346 |
+ reg_names[INTERNAL_FP_REGNUM (i)],
|
mgl@1371
|
3347 |
+ reg_names[INTERNAL_FP_REGNUM (i + 1)]);
|
mgl@1371
|
3348 |
+ }
|
mgl@1371
|
3349 |
+ }
|
mgl@1371
|
3350 |
+}
|
mgl@1371
|
3351 |
+
|
mgl@1371
|
3352 |
+/* Function for converting a fp-register mask to a
|
mgl@1371
|
3353 |
+ reglistCP8 register list string. */
|
mgl@1371
|
3354 |
+void
|
mgl@1371
|
3355 |
+avr32_make_fp_reglist_w (int reglist_mask, char *reglist_string)
|
mgl@1371
|
3356 |
+{
|
mgl@1371
|
3357 |
+ int i;
|
mgl@1371
|
3358 |
+
|
mgl@1371
|
3359 |
+ /* Make sure reglist_string is empty */
|
mgl@1371
|
3360 |
+ reglist_string[0] = '\0';
|
mgl@1371
|
3361 |
+
|
mgl@1371
|
3362 |
+ for (i = 0; i < NUM_FP_REGS; ++i)
|
mgl@1371
|
3363 |
+ {
|
mgl@1371
|
3364 |
+ if (reglist_mask & (1 << i))
|
mgl@1371
|
3365 |
+ {
|
mgl@1371
|
3366 |
+ strlen (reglist_string) ?
|
mgl@1371
|
3367 |
+ sprintf (reglist_string, "%s, %s", reglist_string,
|
mgl@1371
|
3368 |
+ reg_names[INTERNAL_FP_REGNUM (i)]) :
|
mgl@1371
|
3369 |
+ sprintf (reglist_string, "%s", reg_names[INTERNAL_FP_REGNUM (i)]);
|
mgl@1371
|
3370 |
+ }
|
mgl@1371
|
3371 |
+ }
|
mgl@1371
|
3372 |
+}
|
mgl@1371
|
3373 |
+
|
mgl@1371
|
3374 |
+void
|
mgl@1371
|
3375 |
+avr32_make_reglist16 (int reglist16_vect, char *reglist16_string)
|
mgl@1371
|
3376 |
+{
|
mgl@1371
|
3377 |
+ int i;
|
mgl@1371
|
3378 |
+
|
mgl@1371
|
3379 |
+ /* Make sure reglist16_string is empty */
|
mgl@1371
|
3380 |
+ reglist16_string[0] = '\0';
|
mgl@1371
|
3381 |
+
|
mgl@1371
|
3382 |
+ for (i = 0; i < 16; ++i)
|
mgl@1371
|
3383 |
+ {
|
mgl@1371
|
3384 |
+ if (reglist16_vect & (1 << i))
|
mgl@1371
|
3385 |
+ {
|
mgl@1371
|
3386 |
+ strlen (reglist16_string) ?
|
mgl@1371
|
3387 |
+ sprintf (reglist16_string, "%s, %s", reglist16_string,
|
mgl@1371
|
3388 |
+ reg_names[INTERNAL_REGNUM (i)]) :
|
mgl@1371
|
3389 |
+ sprintf (reglist16_string, "%s", reg_names[INTERNAL_REGNUM (i)]);
|
mgl@1371
|
3390 |
+ }
|
mgl@1371
|
3391 |
+ }
|
mgl@1371
|
3392 |
+}
|
mgl@1371
|
3393 |
+
|
mgl@1371
|
3394 |
+int
|
mgl@1371
|
3395 |
+avr32_convert_to_reglist16 (int reglist8_vect)
|
mgl@1371
|
3396 |
+{
|
mgl@1371
|
3397 |
+ int reglist16_vect = 0;
|
mgl@1371
|
3398 |
+ if (reglist8_vect & 0x1)
|
mgl@1371
|
3399 |
+ reglist16_vect |= 0xF;
|
mgl@1371
|
3400 |
+ if (reglist8_vect & 0x2)
|
mgl@1371
|
3401 |
+ reglist16_vect |= 0xF0;
|
mgl@1371
|
3402 |
+ if (reglist8_vect & 0x4)
|
mgl@1371
|
3403 |
+ reglist16_vect |= 0x300;
|
mgl@1371
|
3404 |
+ if (reglist8_vect & 0x8)
|
mgl@1371
|
3405 |
+ reglist16_vect |= 0x400;
|
mgl@1371
|
3406 |
+ if (reglist8_vect & 0x10)
|
mgl@1371
|
3407 |
+ reglist16_vect |= 0x800;
|
mgl@1371
|
3408 |
+ if (reglist8_vect & 0x20)
|
mgl@1371
|
3409 |
+ reglist16_vect |= 0x1000;
|
mgl@1371
|
3410 |
+ if (reglist8_vect & 0x40)
|
mgl@1371
|
3411 |
+ reglist16_vect |= 0x4000;
|
mgl@1371
|
3412 |
+ if (reglist8_vect & 0x80)
|
mgl@1371
|
3413 |
+ reglist16_vect |= 0x8000;
|
mgl@1371
|
3414 |
+
|
mgl@1371
|
3415 |
+ return reglist16_vect;
|
mgl@1371
|
3416 |
+}
|
mgl@1371
|
3417 |
+
|
mgl@1371
|
3418 |
+void
|
mgl@1371
|
3419 |
+avr32_make_reglist8 (int reglist8_vect, char *reglist8_string)
|
mgl@1371
|
3420 |
+{
|
mgl@1371
|
3421 |
+ /* Make sure reglist8_string is empty */
|
mgl@1371
|
3422 |
+ reglist8_string[0] = '\0';
|
mgl@1371
|
3423 |
+
|
mgl@1371
|
3424 |
+ if (reglist8_vect & 0x1)
|
mgl@1371
|
3425 |
+ sprintf (reglist8_string, "r0-r3");
|
mgl@1371
|
3426 |
+ if (reglist8_vect & 0x2)
|
mgl@1371
|
3427 |
+ strlen (reglist8_string) ? sprintf (reglist8_string, "%s, r4-r7",
|
mgl@1371
|
3428 |
+ reglist8_string) :
|
mgl@1371
|
3429 |
+ sprintf (reglist8_string, "r4-r7");
|
mgl@1371
|
3430 |
+ if (reglist8_vect & 0x4)
|
mgl@1371
|
3431 |
+ strlen (reglist8_string) ? sprintf (reglist8_string, "%s, r8-r9",
|
mgl@1371
|
3432 |
+ reglist8_string) :
|
mgl@1371
|
3433 |
+ sprintf (reglist8_string, "r8-r9");
|
mgl@1371
|
3434 |
+ if (reglist8_vect & 0x8)
|
mgl@1371
|
3435 |
+ strlen (reglist8_string) ? sprintf (reglist8_string, "%s, r10",
|
mgl@1371
|
3436 |
+ reglist8_string) :
|
mgl@1371
|
3437 |
+ sprintf (reglist8_string, "r10");
|
mgl@1371
|
3438 |
+ if (reglist8_vect & 0x10)
|
mgl@1371
|
3439 |
+ strlen (reglist8_string) ? sprintf (reglist8_string, "%s, r11",
|
mgl@1371
|
3440 |
+ reglist8_string) :
|
mgl@1371
|
3441 |
+ sprintf (reglist8_string, "r11");
|
mgl@1371
|
3442 |
+ if (reglist8_vect & 0x20)
|
mgl@1371
|
3443 |
+ strlen (reglist8_string) ? sprintf (reglist8_string, "%s, r12",
|
mgl@1371
|
3444 |
+ reglist8_string) :
|
mgl@1371
|
3445 |
+ sprintf (reglist8_string, "r12");
|
mgl@1371
|
3446 |
+ if (reglist8_vect & 0x40)
|
mgl@1371
|
3447 |
+ strlen (reglist8_string) ? sprintf (reglist8_string, "%s, lr",
|
mgl@1371
|
3448 |
+ reglist8_string) :
|
mgl@1371
|
3449 |
+ sprintf (reglist8_string, "lr");
|
mgl@1371
|
3450 |
+ if (reglist8_vect & 0x80)
|
mgl@1371
|
3451 |
+ strlen (reglist8_string) ? sprintf (reglist8_string, "%s, pc",
|
mgl@1371
|
3452 |
+ reglist8_string) :
|
mgl@1371
|
3453 |
+ sprintf (reglist8_string, "pc");
|
mgl@1371
|
3454 |
+}
|
mgl@1371
|
3455 |
+
|
mgl@1371
|
3456 |
+int
|
mgl@1371
|
3457 |
+avr32_eh_return_data_regno (int n)
|
mgl@1371
|
3458 |
+{
|
mgl@1371
|
3459 |
+ if (n >= 0 && n <= 3)
|
mgl@1371
|
3460 |
+ return 8 + n;
|
mgl@1371
|
3461 |
+ else
|
mgl@1371
|
3462 |
+ return INVALID_REGNUM;
|
mgl@1371
|
3463 |
+}
|
mgl@1371
|
3464 |
+
|
mgl@1371
|
3465 |
+/* Compute the distance from register FROM to register TO.
|
mgl@1371
|
3466 |
+ These can be the arg pointer, the frame pointer or
|
mgl@1371
|
3467 |
+ the stack pointer.
|
mgl@1371
|
3468 |
+ Typical stack layout looks like this:
|
mgl@1371
|
3469 |
+
|
mgl@1371
|
3470 |
+ old stack pointer -> | |
|
mgl@1371
|
3471 |
+ ----
|
mgl@1371
|
3472 |
+ | | \
|
mgl@1371
|
3473 |
+ | | saved arguments for
|
mgl@1371
|
3474 |
+ | | vararg functions
|
mgl@1371
|
3475 |
+ arg_pointer -> | | /
|
mgl@1371
|
3476 |
+ --
|
mgl@1371
|
3477 |
+ | | \
|
mgl@1371
|
3478 |
+ | | call saved
|
mgl@1371
|
3479 |
+ | | registers
|
mgl@1371
|
3480 |
+ | | /
|
mgl@1371
|
3481 |
+ frame ptr -> --
|
mgl@1371
|
3482 |
+ | | \
|
mgl@1371
|
3483 |
+ | | local
|
mgl@1371
|
3484 |
+ | | variables
|
mgl@1371
|
3485 |
+ stack ptr --> | | /
|
mgl@1371
|
3486 |
+ --
|
mgl@1371
|
3487 |
+ | | \
|
mgl@1371
|
3488 |
+ | | outgoing
|
mgl@1371
|
3489 |
+ | | arguments
|
mgl@1371
|
3490 |
+ | | /
|
mgl@1371
|
3491 |
+ --
|
mgl@1371
|
3492 |
+
|
mgl@1371
|
3493 |
+ For a given funciton some or all of these stack compomnents
|
mgl@1371
|
3494 |
+ may not be needed, giving rise to the possibility of
|
mgl@1371
|
3495 |
+ eliminating some of the registers.
|
mgl@1371
|
3496 |
+
|
mgl@1371
|
3497 |
+ The values returned by this function must reflect the behaviour
|
mgl@1371
|
3498 |
+ of avr32_expand_prologue() and avr32_compute_save_reg_mask().
|
mgl@1371
|
3499 |
+
|
mgl@1371
|
3500 |
+ The sign of the number returned reflects the direction of stack
|
mgl@1371
|
3501 |
+ growth, so the values are positive for all eliminations except
|
mgl@1371
|
3502 |
+ from the soft frame pointer to the hard frame pointer. */
|
mgl@1371
|
3503 |
+
|
mgl@1371
|
3504 |
+
|
mgl@1371
|
3505 |
+int
|
mgl@1371
|
3506 |
+avr32_initial_elimination_offset (int from, int to)
|
mgl@1371
|
3507 |
+{
|
mgl@1371
|
3508 |
+ int i;
|
mgl@1371
|
3509 |
+ int call_saved_regs = 0;
|
mgl@1371
|
3510 |
+ unsigned long saved_reg_mask, saved_fp_reg_mask;
|
mgl@1371
|
3511 |
+ unsigned int local_vars = get_frame_size ();
|
mgl@1371
|
3512 |
+
|
mgl@1371
|
3513 |
+ saved_reg_mask = avr32_compute_save_reg_mask (TRUE);
|
mgl@1371
|
3514 |
+ saved_fp_reg_mask = avr32_compute_save_fp_reg_mask ();
|
mgl@1371
|
3515 |
+
|
mgl@1371
|
3516 |
+ for (i = 0; i < 16; ++i)
|
mgl@1371
|
3517 |
+ {
|
mgl@1371
|
3518 |
+ if (saved_reg_mask & (1 << i))
|
mgl@1371
|
3519 |
+ call_saved_regs += 4;
|
mgl@1371
|
3520 |
+ }
|
mgl@1371
|
3521 |
+
|
mgl@1371
|
3522 |
+ for (i = 0; i < NUM_FP_REGS; ++i)
|
mgl@1371
|
3523 |
+ {
|
mgl@1371
|
3524 |
+ if (saved_fp_reg_mask & (1 << i))
|
mgl@1371
|
3525 |
+ call_saved_regs += 4;
|
mgl@1371
|
3526 |
+ }
|
mgl@1371
|
3527 |
+
|
mgl@1371
|
3528 |
+ switch (from)
|
mgl@1371
|
3529 |
+ {
|
mgl@1371
|
3530 |
+ case ARG_POINTER_REGNUM:
|
mgl@1371
|
3531 |
+ switch (to)
|
mgl@1371
|
3532 |
+ {
|
mgl@1371
|
3533 |
+ case STACK_POINTER_REGNUM:
|
mgl@1371
|
3534 |
+ return call_saved_regs + local_vars;
|
mgl@1371
|
3535 |
+ case FRAME_POINTER_REGNUM:
|
mgl@1371
|
3536 |
+ return call_saved_regs;
|
mgl@1371
|
3537 |
+ default:
|
mgl@1371
|
3538 |
+ abort ();
|
mgl@1371
|
3539 |
+ }
|
mgl@1371
|
3540 |
+ case FRAME_POINTER_REGNUM:
|
mgl@1371
|
3541 |
+ switch (to)
|
mgl@1371
|
3542 |
+ {
|
mgl@1371
|
3543 |
+ case STACK_POINTER_REGNUM:
|
mgl@1371
|
3544 |
+ return local_vars;
|
mgl@1371
|
3545 |
+ default:
|
mgl@1371
|
3546 |
+ abort ();
|
mgl@1371
|
3547 |
+ }
|
mgl@1371
|
3548 |
+ default:
|
mgl@1371
|
3549 |
+ abort ();
|
mgl@1371
|
3550 |
+ }
|
mgl@1371
|
3551 |
+}
|
mgl@1371
|
3552 |
+
|
mgl@1371
|
3553 |
+
|
mgl@1371
|
3554 |
+/*
|
mgl@1371
|
3555 |
+ Returns a rtx used when passing the next argument to a function.
|
mgl@1371
|
3556 |
+ avr32_init_cumulative_args() and avr32_function_arg_advance() sets witch
|
mgl@1371
|
3557 |
+ register to use.
|
mgl@1371
|
3558 |
+*/
|
mgl@1371
|
3559 |
+rtx
|
mgl@1371
|
3560 |
+avr32_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode,
|
mgl@1371
|
3561 |
+ tree type, int named)
|
mgl@1371
|
3562 |
+{
|
mgl@1371
|
3563 |
+ int index = -1;
|
mgl@1371
|
3564 |
+
|
mgl@1371
|
3565 |
+ HOST_WIDE_INT arg_size, arg_rsize;
|
mgl@1371
|
3566 |
+ if (type)
|
mgl@1371
|
3567 |
+ {
|
mgl@1371
|
3568 |
+ arg_size = int_size_in_bytes (type);
|
mgl@1371
|
3569 |
+ }
|
mgl@1371
|
3570 |
+ else
|
mgl@1371
|
3571 |
+ {
|
mgl@1371
|
3572 |
+ arg_size = GET_MODE_SIZE (mode);
|
mgl@1371
|
3573 |
+ }
|
mgl@1371
|
3574 |
+ arg_rsize = PUSH_ROUNDING (arg_size);
|
mgl@1371
|
3575 |
+
|
mgl@1371
|
3576 |
+ /*
|
mgl@1371
|
3577 |
+ The last time this macro is called, it is called with mode == VOIDmode,
|
mgl@1371
|
3578 |
+ and its result is passed to the call or call_value pattern as operands 2
|
mgl@1371
|
3579 |
+ and 3 respectively. */
|
mgl@1371
|
3580 |
+ if (mode == VOIDmode)
|
mgl@1371
|
3581 |
+ {
|
mgl@1371
|
3582 |
+ return gen_rtx_CONST_INT (SImode, 22); /* ToDo: fixme. */
|
mgl@1371
|
3583 |
+ }
|
mgl@1371
|
3584 |
+
|
mgl@1371
|
3585 |
+ if ((*targetm.calls.must_pass_in_stack) (mode, type) || !named)
|
mgl@1371
|
3586 |
+ {
|
mgl@1371
|
3587 |
+ return NULL_RTX;
|
mgl@1371
|
3588 |
+ }
|
mgl@1371
|
3589 |
+
|
mgl@1371
|
3590 |
+ if (arg_rsize == 8)
|
mgl@1371
|
3591 |
+ {
|
mgl@1371
|
3592 |
+ /* use r11:r10 or r9:r8. */
|
mgl@1371
|
3593 |
+ if (!(GET_USED_INDEX (cum, 1) || GET_USED_INDEX (cum, 2)))
|
mgl@1371
|
3594 |
+ index = 1;
|
mgl@1371
|
3595 |
+ else if (!(GET_USED_INDEX (cum, 3) || GET_USED_INDEX (cum, 4)))
|
mgl@1371
|
3596 |
+ index = 3;
|
mgl@1371
|
3597 |
+ else
|
mgl@1371
|
3598 |
+ index = -1;
|
mgl@1371
|
3599 |
+ }
|
mgl@1371
|
3600 |
+ else if (arg_rsize == 4)
|
mgl@1371
|
3601 |
+ { /* Use first available register */
|
mgl@1371
|
3602 |
+ index = 0;
|
mgl@1371
|
3603 |
+ while (index <= LAST_CUM_REG_INDEX && GET_USED_INDEX (cum, index))
|
mgl@1371
|
3604 |
+ index++;
|
mgl@1371
|
3605 |
+ if (index > LAST_CUM_REG_INDEX)
|
mgl@1371
|
3606 |
+ index = -1;
|
mgl@1371
|
3607 |
+ }
|
mgl@1371
|
3608 |
+
|
mgl@1371
|
3609 |
+ SET_REG_INDEX (cum, index);
|
mgl@1371
|
3610 |
+
|
mgl@1371
|
3611 |
+ if (GET_REG_INDEX (cum) >= 0)
|
mgl@1371
|
3612 |
+ return gen_rtx_REG (mode,
|
mgl@1371
|
3613 |
+ avr32_function_arg_reglist[GET_REG_INDEX (cum)]);
|
mgl@1371
|
3614 |
+
|
mgl@1371
|
3615 |
+ return NULL_RTX;
|
mgl@1371
|
3616 |
+}
|
mgl@1371
|
3617 |
+
|
mgl@1371
|
3618 |
+/*
|
mgl@1371
|
3619 |
+ Set the register used for passing the first argument to a function.
|
mgl@1371
|
3620 |
+*/
|
mgl@1371
|
3621 |
+void
|
mgl@1371
|
3622 |
+avr32_init_cumulative_args (CUMULATIVE_ARGS * cum,
|
mgl@1371
|
3623 |
+ tree fntype ATTRIBUTE_UNUSED,
|
mgl@1371
|
3624 |
+ rtx libname ATTRIBUTE_UNUSED,
|
mgl@1371
|
3625 |
+ tree fndecl ATTRIBUTE_UNUSED)
|
mgl@1371
|
3626 |
+ {
|
mgl@1371
|
3627 |
+ /* Set all registers as unused. */
|
mgl@1371
|
3628 |
+ SET_INDEXES_UNUSED (cum);
|
mgl@1371
|
3629 |
+
|
mgl@1371
|
3630 |
+ /* Reset uses_anonymous_args */
|
mgl@1371
|
3631 |
+ cum->uses_anonymous_args = 0;
|
mgl@1371
|
3632 |
+
|
mgl@1371
|
3633 |
+ /* Reset size of stack pushed arguments */
|
mgl@1371
|
3634 |
+ cum->stack_pushed_args_size = 0;
|
mgl@1371
|
3635 |
+ }
|
mgl@1371
|
3636 |
+
|
mgl@1371
|
3637 |
+/*
|
mgl@1371
|
3638 |
+ Set register used for passing the next argument to a function. Only the
|
mgl@1371
|
3639 |
+ Scratch Registers are used.
|
mgl@1371
|
3640 |
+
|
mgl@1371
|
3641 |
+ number name
|
mgl@1371
|
3642 |
+ 15 r15 PC
|
mgl@1371
|
3643 |
+ 14 r14 LR
|
mgl@1371
|
3644 |
+ 13 r13 _SP_________
|
mgl@1371
|
3645 |
+ FIRST_CUM_REG 12 r12 _||_
|
mgl@1371
|
3646 |
+ 10 r11 ||
|
mgl@1371
|
3647 |
+ 11 r10 _||_ Scratch Registers
|
mgl@1371
|
3648 |
+ 8 r9 ||
|
mgl@1371
|
3649 |
+ LAST_SCRATCH_REG 9 r8 _\/_________
|
mgl@1371
|
3650 |
+ 6 r7 /\
|
mgl@1371
|
3651 |
+ 7 r6 ||
|
mgl@1371
|
3652 |
+ 4 r5 ||
|
mgl@1371
|
3653 |
+ 5 r4 ||
|
mgl@1371
|
3654 |
+ 2 r3 ||
|
mgl@1371
|
3655 |
+ 3 r2 ||
|
mgl@1371
|
3656 |
+ 0 r1 ||
|
mgl@1371
|
3657 |
+ 1 r0 _||_________
|
mgl@1371
|
3658 |
+
|
mgl@1371
|
3659 |
+*/
|
mgl@1371
|
3660 |
+void
|
mgl@1371
|
3661 |
+avr32_function_arg_advance (CUMULATIVE_ARGS * cum, enum machine_mode mode,
|
mgl@1371
|
3662 |
+ tree type, int named ATTRIBUTE_UNUSED)
|
mgl@1371
|
3663 |
+{
|
mgl@1371
|
3664 |
+ HOST_WIDE_INT arg_size, arg_rsize;
|
mgl@1371
|
3665 |
+
|
mgl@1371
|
3666 |
+ if (type)
|
mgl@1371
|
3667 |
+ {
|
mgl@1371
|
3668 |
+ arg_size = int_size_in_bytes (type);
|
mgl@1371
|
3669 |
+ }
|
mgl@1371
|
3670 |
+ else
|
mgl@1371
|
3671 |
+ {
|
mgl@1371
|
3672 |
+ arg_size = GET_MODE_SIZE (mode);
|
mgl@1371
|
3673 |
+ }
|
mgl@1371
|
3674 |
+ arg_rsize = PUSH_ROUNDING (arg_size);
|
mgl@1371
|
3675 |
+
|
mgl@1371
|
3676 |
+ /* It the argument had to be passed in stack, no register is used. */
|
mgl@1371
|
3677 |
+ if ((*targetm.calls.must_pass_in_stack) (mode, type))
|
mgl@1371
|
3678 |
+ {
|
mgl@1371
|
3679 |
+ cum->stack_pushed_args_size += PUSH_ROUNDING (int_size_in_bytes (type));
|
mgl@1371
|
3680 |
+ return;
|
mgl@1371
|
3681 |
+ }
|
mgl@1371
|
3682 |
+
|
mgl@1371
|
3683 |
+ /* Mark the used registers as "used". */
|
mgl@1371
|
3684 |
+ if (GET_REG_INDEX (cum) >= 0)
|
mgl@1371
|
3685 |
+ {
|
mgl@1371
|
3686 |
+ SET_USED_INDEX (cum, GET_REG_INDEX (cum));
|
mgl@1371
|
3687 |
+ if (arg_rsize == 8)
|
mgl@1371
|
3688 |
+ {
|
mgl@1371
|
3689 |
+ SET_USED_INDEX (cum, (GET_REG_INDEX (cum) + 1));
|
mgl@1371
|
3690 |
+ }
|
mgl@1371
|
3691 |
+ }
|
mgl@1371
|
3692 |
+ else
|
mgl@1371
|
3693 |
+ {
|
mgl@1371
|
3694 |
+ /* Had to use stack */
|
mgl@1371
|
3695 |
+ cum->stack_pushed_args_size += arg_rsize;
|
mgl@1371
|
3696 |
+ }
|
mgl@1371
|
3697 |
+}
|
mgl@1371
|
3698 |
+
|
mgl@1371
|
3699 |
+/*
|
mgl@1371
|
3700 |
+ Defines witch direction to go to find the next register to use if the
|
mgl@1371
|
3701 |
+ argument is larger then one register or for arguments shorter than an
|
mgl@1371
|
3702 |
+ int which is not promoted, such as the last part of structures with
|
mgl@1371
|
3703 |
+ size not a multiple of 4. */
|
mgl@1371
|
3704 |
+enum direction
|
mgl@1371
|
3705 |
+avr32_function_arg_padding (enum machine_mode mode ATTRIBUTE_UNUSED,
|
mgl@1371
|
3706 |
+ tree type)
|
mgl@1371
|
3707 |
+{
|
mgl@1371
|
3708 |
+ /* Pad upward for all aggregates except byte and halfword sized aggregates
|
mgl@1371
|
3709 |
+ which can be passed in registers. */
|
mgl@1371
|
3710 |
+ if (type
|
mgl@1371
|
3711 |
+ && AGGREGATE_TYPE_P (type)
|
mgl@1371
|
3712 |
+ && (int_size_in_bytes (type) != 1)
|
mgl@1371
|
3713 |
+ && !((int_size_in_bytes (type) == 2)
|
mgl@1371
|
3714 |
+ && TYPE_ALIGN_UNIT (type) >= 2)
|
mgl@1371
|
3715 |
+ && (int_size_in_bytes (type) & 0x3))
|
mgl@1371
|
3716 |
+ {
|
mgl@1371
|
3717 |
+ return upward;
|
mgl@1371
|
3718 |
+ }
|
mgl@1371
|
3719 |
+
|
mgl@1371
|
3720 |
+ return downward;
|
mgl@1371
|
3721 |
+}
|
mgl@1371
|
3722 |
+
|
mgl@1371
|
3723 |
+/*
|
mgl@1371
|
3724 |
+ Return a rtx used for the return value from a function call.
|
mgl@1371
|
3725 |
+*/
|
mgl@1371
|
3726 |
+rtx
|
mgl@1371
|
3727 |
+avr32_function_value (tree type, tree func, bool outgoing ATTRIBUTE_UNUSED)
|
mgl@1371
|
3728 |
+{
|
mgl@1371
|
3729 |
+ if (avr32_return_in_memory (type, func))
|
mgl@1371
|
3730 |
+ return NULL_RTX;
|
mgl@1371
|
3731 |
+
|
mgl@1371
|
3732 |
+ if (int_size_in_bytes (type) <= 4)
|
mgl@1371
|
3733 |
+ if (avr32_return_in_msb (type))
|
mgl@1371
|
3734 |
+ /* Aggregates of size less than a word which does align the data in the
|
mgl@1371
|
3735 |
+ MSB must use SImode for r12. */
|
mgl@1371
|
3736 |
+ return gen_rtx_REG (SImode, RET_REGISTER);
|
mgl@1371
|
3737 |
+ else
|
mgl@1371
|
3738 |
+ return gen_rtx_REG (TYPE_MODE (type), RET_REGISTER);
|
mgl@1371
|
3739 |
+ else if (int_size_in_bytes (type) <= 8)
|
mgl@1371
|
3740 |
+ return gen_rtx_REG (TYPE_MODE (type), INTERNAL_REGNUM (11));
|
mgl@1371
|
3741 |
+
|
mgl@1371
|
3742 |
+ return NULL_RTX;
|
mgl@1371
|
3743 |
+}
|
mgl@1371
|
3744 |
+
|
mgl@1371
|
3745 |
+/*
|
mgl@1371
|
3746 |
+ Return a rtx used for the return value from a library function call.
|
mgl@1371
|
3747 |
+*/
|
mgl@1371
|
3748 |
+rtx
|
mgl@1371
|
3749 |
+avr32_libcall_value (enum machine_mode mode)
|
mgl@1371
|
3750 |
+{
|
mgl@1371
|
3751 |
+
|
mgl@1371
|
3752 |
+ if (GET_MODE_SIZE (mode) <= 4)
|
mgl@1371
|
3753 |
+ return gen_rtx_REG (mode, RET_REGISTER);
|
mgl@1371
|
3754 |
+ else if (GET_MODE_SIZE (mode) <= 8)
|
mgl@1371
|
3755 |
+ return gen_rtx_REG (mode, INTERNAL_REGNUM (11));
|
mgl@1371
|
3756 |
+ else
|
mgl@1371
|
3757 |
+ return NULL_RTX;
|
mgl@1371
|
3758 |
+}
|
mgl@1371
|
3759 |
+
|
mgl@1371
|
3760 |
+/* Return TRUE if X references a SYMBOL_REF. */
|
mgl@1371
|
3761 |
+int
|
mgl@1371
|
3762 |
+symbol_mentioned_p (rtx x)
|
mgl@1371
|
3763 |
+{
|
mgl@1371
|
3764 |
+ const char *fmt;
|
mgl@1371
|
3765 |
+ int i;
|
mgl@1371
|
3766 |
+
|
mgl@1371
|
3767 |
+ if (GET_CODE (x) == SYMBOL_REF)
|
mgl@1371
|
3768 |
+ return 1;
|
mgl@1371
|
3769 |
+
|
mgl@1371
|
3770 |
+ fmt = GET_RTX_FORMAT (GET_CODE (x));
|
mgl@1371
|
3771 |
+
|
mgl@1371
|
3772 |
+ for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
|
mgl@1371
|
3773 |
+ {
|
mgl@1371
|
3774 |
+ if (fmt[i] == 'E')
|
mgl@1371
|
3775 |
+ {
|
mgl@1371
|
3776 |
+ int j;
|
mgl@1371
|
3777 |
+
|
mgl@1371
|
3778 |
+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
|
mgl@1371
|
3779 |
+ if (symbol_mentioned_p (XVECEXP (x, i, j)))
|
mgl@1371
|
3780 |
+ return 1;
|
mgl@1371
|
3781 |
+ }
|
mgl@1371
|
3782 |
+ else if (fmt[i] == 'e' && symbol_mentioned_p (XEXP (x, i)))
|
mgl@1371
|
3783 |
+ return 1;
|
mgl@1371
|
3784 |
+ }
|
mgl@1371
|
3785 |
+
|
mgl@1371
|
3786 |
+ return 0;
|
mgl@1371
|
3787 |
+}
|
mgl@1371
|
3788 |
+
|
mgl@1371
|
3789 |
+/* Return TRUE if X references a LABEL_REF. */
|
mgl@1371
|
3790 |
+int
|
mgl@1371
|
3791 |
+label_mentioned_p (rtx x)
|
mgl@1371
|
3792 |
+{
|
mgl@1371
|
3793 |
+ const char *fmt;
|
mgl@1371
|
3794 |
+ int i;
|
mgl@1371
|
3795 |
+
|
mgl@1371
|
3796 |
+ if (GET_CODE (x) == LABEL_REF)
|
mgl@1371
|
3797 |
+ return 1;
|
mgl@1371
|
3798 |
+
|
mgl@1371
|
3799 |
+ fmt = GET_RTX_FORMAT (GET_CODE (x));
|
mgl@1371
|
3800 |
+ for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
|
mgl@1371
|
3801 |
+ {
|
mgl@1371
|
3802 |
+ if (fmt[i] == 'E')
|
mgl@1371
|
3803 |
+ {
|
mgl@1371
|
3804 |
+ int j;
|
mgl@1371
|
3805 |
+
|
mgl@1371
|
3806 |
+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
|
mgl@1371
|
3807 |
+ if (label_mentioned_p (XVECEXP (x, i, j)))
|
mgl@1371
|
3808 |
+ return 1;
|
mgl@1371
|
3809 |
+ }
|
mgl@1371
|
3810 |
+ else if (fmt[i] == 'e' && label_mentioned_p (XEXP (x, i)))
|
mgl@1371
|
3811 |
+ return 1;
|
mgl@1371
|
3812 |
+ }
|
mgl@1371
|
3813 |
+
|
mgl@1371
|
3814 |
+ return 0;
|
mgl@1371
|
3815 |
+}
|
mgl@1371
|
3816 |
+
|
mgl@1371
|
3817 |
+/* Return TRUE if X contains a MEM expression. */
|
mgl@1371
|
3818 |
+int
|
mgl@1371
|
3819 |
+mem_mentioned_p (rtx x)
|
mgl@1371
|
3820 |
+{
|
mgl@1371
|
3821 |
+ const char *fmt;
|
mgl@1371
|
3822 |
+ int i;
|
mgl@1371
|
3823 |
+
|
mgl@1371
|
3824 |
+ if (MEM_P (x))
|
mgl@1371
|
3825 |
+ return 1;
|
mgl@1371
|
3826 |
+
|
mgl@1371
|
3827 |
+ fmt = GET_RTX_FORMAT (GET_CODE (x));
|
mgl@1371
|
3828 |
+ for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
|
mgl@1371
|
3829 |
+ {
|
mgl@1371
|
3830 |
+ if (fmt[i] == 'E')
|
mgl@1371
|
3831 |
+ {
|
mgl@1371
|
3832 |
+ int j;
|
mgl@1371
|
3833 |
+
|
mgl@1371
|
3834 |
+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
|
mgl@1371
|
3835 |
+ if (mem_mentioned_p (XVECEXP (x, i, j)))
|
mgl@1371
|
3836 |
+ return 1;
|
mgl@1371
|
3837 |
+ }
|
mgl@1371
|
3838 |
+ else if (fmt[i] == 'e' && mem_mentioned_p (XEXP (x, i)))
|
mgl@1371
|
3839 |
+ return 1;
|
mgl@1371
|
3840 |
+ }
|
mgl@1371
|
3841 |
+
|
mgl@1371
|
3842 |
+ return 0;
|
mgl@1371
|
3843 |
+}
|
mgl@1371
|
3844 |
+
|
mgl@1371
|
3845 |
+int
|
mgl@1371
|
3846 |
+avr32_legitimate_pic_operand_p (rtx x)
|
mgl@1371
|
3847 |
+{
|
mgl@1371
|
3848 |
+
|
mgl@1371
|
3849 |
+ /* We can't have const, this must be broken down to a symbol. */
|
mgl@1371
|
3850 |
+ if (GET_CODE (x) == CONST)
|
mgl@1371
|
3851 |
+ return FALSE;
|
mgl@1371
|
3852 |
+
|
mgl@1371
|
3853 |
+ /* Can't access symbols or labels via the constant pool either */
|
mgl@1371
|
3854 |
+ if ((GET_CODE (x) == SYMBOL_REF
|
mgl@1371
|
3855 |
+ && CONSTANT_POOL_ADDRESS_P (x)
|
mgl@1371
|
3856 |
+ && (symbol_mentioned_p (get_pool_constant (x))
|
mgl@1371
|
3857 |
+ || label_mentioned_p (get_pool_constant (x)))))
|
mgl@1371
|
3858 |
+ return FALSE;
|
mgl@1371
|
3859 |
+
|
mgl@1371
|
3860 |
+ return TRUE;
|
mgl@1371
|
3861 |
+}
|
mgl@1371
|
3862 |
+
|
mgl@1371
|
3863 |
+
|
mgl@1371
|
3864 |
+rtx
|
mgl@1371
|
3865 |
+legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
|
mgl@1371
|
3866 |
+ rtx reg)
|
mgl@1371
|
3867 |
+{
|
mgl@1371
|
3868 |
+
|
mgl@1371
|
3869 |
+ if (GET_CODE (orig) == SYMBOL_REF || GET_CODE (orig) == LABEL_REF)
|
mgl@1371
|
3870 |
+ {
|
mgl@1371
|
3871 |
+ int subregs = 0;
|
mgl@1371
|
3872 |
+
|
mgl@1371
|
3873 |
+ if (reg == 0)
|
mgl@1371
|
3874 |
+ {
|
mgl@1371
|
3875 |
+ if (no_new_pseudos)
|
mgl@1371
|
3876 |
+ abort ();
|
mgl@1371
|
3877 |
+ else
|
mgl@1371
|
3878 |
+ reg = gen_reg_rtx (Pmode);
|
mgl@1371
|
3879 |
+
|
mgl@1371
|
3880 |
+ subregs = 1;
|
mgl@1371
|
3881 |
+ }
|
mgl@1371
|
3882 |
+
|
mgl@1371
|
3883 |
+ emit_move_insn (reg, orig);
|
mgl@1371
|
3884 |
+
|
mgl@1371
|
3885 |
+ /* Only set current function as using pic offset table if flag_pic is
|
mgl@1371
|
3886 |
+ set. This is because this function is also used if
|
mgl@1371
|
3887 |
+ TARGET_HAS_ASM_ADDR_PSEUDOS is set. */
|
mgl@1371
|
3888 |
+ if (flag_pic)
|
mgl@1371
|
3889 |
+ current_function_uses_pic_offset_table = 1;
|
mgl@1371
|
3890 |
+
|
mgl@1371
|
3891 |
+ /* Put a REG_EQUAL note on this insn, so that it can be optimized by
|
mgl@1371
|
3892 |
+ loop. */
|
mgl@1371
|
3893 |
+ return reg;
|
mgl@1371
|
3894 |
+ }
|
mgl@1371
|
3895 |
+ else if (GET_CODE (orig) == CONST)
|
mgl@1371
|
3896 |
+ {
|
mgl@1371
|
3897 |
+ rtx base, offset;
|
mgl@1371
|
3898 |
+
|
mgl@1371
|
3899 |
+ if (flag_pic
|
mgl@1371
|
3900 |
+ && GET_CODE (XEXP (orig, 0)) == PLUS
|
mgl@1371
|
3901 |
+ && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
|
mgl@1371
|
3902 |
+ return orig;
|
mgl@1371
|
3903 |
+
|
mgl@1371
|
3904 |
+ if (reg == 0)
|
mgl@1371
|
3905 |
+ {
|
mgl@1371
|
3906 |
+ if (no_new_pseudos)
|
mgl@1371
|
3907 |
+ abort ();
|
mgl@1371
|
3908 |
+ else
|
mgl@1371
|
3909 |
+ reg = gen_reg_rtx (Pmode);
|
mgl@1371
|
3910 |
+ }
|
mgl@1371
|
3911 |
+
|
mgl@1371
|
3912 |
+ if (GET_CODE (XEXP (orig, 0)) == PLUS)
|
mgl@1371
|
3913 |
+ {
|
mgl@1371
|
3914 |
+ base =
|
mgl@1371
|
3915 |
+ legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
|
mgl@1371
|
3916 |
+ offset =
|
mgl@1371
|
3917 |
+ legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
|
mgl@1371
|
3918 |
+ base == reg ? 0 : reg);
|
mgl@1371
|
3919 |
+ }
|
mgl@1371
|
3920 |
+ else
|
mgl@1371
|
3921 |
+ abort ();
|
mgl@1371
|
3922 |
+
|
mgl@1371
|
3923 |
+ if (GET_CODE (offset) == CONST_INT)
|
mgl@1371
|
3924 |
+ {
|
mgl@1371
|
3925 |
+ /* The base register doesn't really matter, we only want to test
|
mgl@1371
|
3926 |
+ the index for the appropriate mode. */
|
mgl@1371
|
3927 |
+ if (!avr32_const_ok_for_constraint_p (INTVAL (offset), 'I', "Is21"))
|
mgl@1371
|
3928 |
+ {
|
mgl@1371
|
3929 |
+ if (!no_new_pseudos)
|
mgl@1371
|
3930 |
+ offset = force_reg (Pmode, offset);
|
mgl@1371
|
3931 |
+ else
|
mgl@1371
|
3932 |
+ abort ();
|
mgl@1371
|
3933 |
+ }
|
mgl@1371
|
3934 |
+
|
mgl@1371
|
3935 |
+ if (GET_CODE (offset) == CONST_INT)
|
mgl@1371
|
3936 |
+ return plus_constant (base, INTVAL (offset));
|
mgl@1371
|
3937 |
+ }
|
mgl@1371
|
3938 |
+
|
mgl@1371
|
3939 |
+ return gen_rtx_PLUS (Pmode, base, offset);
|
mgl@1371
|
3940 |
+ }
|
mgl@1371
|
3941 |
+
|
mgl@1371
|
3942 |
+ return orig;
|
mgl@1371
|
3943 |
+}
|
mgl@1371
|
3944 |
+
|
mgl@1371
|
3945 |
+/* Generate code to load the PIC register. */
|
mgl@1371
|
3946 |
+void
|
mgl@1371
|
3947 |
+avr32_load_pic_register (void)
|
mgl@1371
|
3948 |
+{
|
mgl@1371
|
3949 |
+ rtx l1, pic_tmp;
|
mgl@1371
|
3950 |
+ rtx global_offset_table;
|
mgl@1371
|
3951 |
+
|
mgl@1371
|
3952 |
+ if ((current_function_uses_pic_offset_table == 0) || TARGET_NO_INIT_GOT)
|
mgl@1371
|
3953 |
+ return;
|
mgl@1371
|
3954 |
+
|
mgl@1371
|
3955 |
+ if (!flag_pic)
|
mgl@1371
|
3956 |
+ abort ();
|
mgl@1371
|
3957 |
+
|
mgl@1371
|
3958 |
+ l1 = gen_label_rtx ();
|
mgl@1371
|
3959 |
+
|
mgl@1371
|
3960 |
+ global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
|
mgl@1371
|
3961 |
+ pic_tmp =
|
mgl@1371
|
3962 |
+ gen_rtx_CONST (Pmode,
|
mgl@1371
|
3963 |
+ gen_rtx_MINUS (SImode, gen_rtx_LABEL_REF (Pmode, l1),
|
mgl@1371
|
3964 |
+ global_offset_table));
|
mgl@1371
|
3965 |
+ emit_insn (gen_pic_load_addr
|
mgl@1371
|
3966 |
+ (pic_offset_table_rtx, force_const_mem (SImode, pic_tmp)));
|
mgl@1371
|
3967 |
+ emit_insn (gen_pic_compute_got_from_pc (pic_offset_table_rtx, l1));
|
mgl@1371
|
3968 |
+
|
mgl@1371
|
3969 |
+ /* Need to emit this whether or not we obey regdecls, since setjmp/longjmp
|
mgl@1371
|
3970 |
+ can cause life info to screw up. */
|
mgl@1371
|
3971 |
+ emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
|
mgl@1371
|
3972 |
+}
|
mgl@1371
|
3973 |
+
|
mgl@1371
|
3974 |
+
|
mgl@1371
|
3975 |
+
|
mgl@1371
|
3976 |
+/* This hook should return true if values of type type are returned at the most
|
mgl@1371
|
3977 |
+ significant end of a register (in other words, if they are padded at the
|
mgl@1371
|
3978 |
+ least significant end). You can assume that type is returned in a register;
|
mgl@1371
|
3979 |
+ the caller is required to check this. Note that the register provided by
|
mgl@1371
|
3980 |
+ FUNCTION_VALUE must be able to hold the complete return value. For example,
|
mgl@1371
|
3981 |
+ if a 1-, 2- or 3-byte structure is returned at the most significant end of a
|
mgl@1371
|
3982 |
+ 4-byte register, FUNCTION_VALUE should provide an SImode rtx. */
|
mgl@1371
|
3983 |
+bool
|
mgl@1371
|
3984 |
+avr32_return_in_msb (tree type ATTRIBUTE_UNUSED)
|
mgl@1371
|
3985 |
+{
|
mgl@1371
|
3986 |
+ /* if ( AGGREGATE_TYPE_P (type) ) if ((int_size_in_bytes(type) == 1) ||
|
mgl@1371
|
3987 |
+ ((int_size_in_bytes(type) == 2) && TYPE_ALIGN_UNIT(type) >= 2)) return
|
mgl@1371
|
3988 |
+ false; else return true; */
|
mgl@1371
|
3989 |
+
|
mgl@1371
|
3990 |
+ return false;
|
mgl@1371
|
3991 |
+}
|
mgl@1371
|
3992 |
+
|
mgl@1371
|
3993 |
+
|
mgl@1371
|
3994 |
+/*
|
mgl@1371
|
3995 |
+ Returns one if a certain function value is going to be returned in memory
|
mgl@1371
|
3996 |
+ and zero if it is going to be returned in a register.
|
mgl@1371
|
3997 |
+
|
mgl@1371
|
3998 |
+ BLKmode and all other modes that is larger than 64 bits are returned in
|
mgl@1371
|
3999 |
+ memory.
|
mgl@1371
|
4000 |
+*/
|
mgl@1371
|
4001 |
+bool
|
mgl@1371
|
4002 |
+avr32_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
|
mgl@1371
|
4003 |
+{
|
mgl@1371
|
4004 |
+ if (TYPE_MODE (type) == VOIDmode)
|
mgl@1371
|
4005 |
+ return false;
|
mgl@1371
|
4006 |
+
|
mgl@1371
|
4007 |
+ if (int_size_in_bytes (type) > (2 * UNITS_PER_WORD)
|
mgl@1371
|
4008 |
+ || int_size_in_bytes (type) == -1)
|
mgl@1371
|
4009 |
+ {
|
mgl@1371
|
4010 |
+ return true;
|
mgl@1371
|
4011 |
+ }
|
mgl@1371
|
4012 |
+
|
mgl@1371
|
4013 |
+ /* If we have an aggregate then use the same mechanism as when checking if
|
mgl@1371
|
4014 |
+ it should be passed on the stack. */
|
mgl@1371
|
4015 |
+ if (type
|
mgl@1371
|
4016 |
+ && AGGREGATE_TYPE_P (type)
|
mgl@1371
|
4017 |
+ && (*targetm.calls.must_pass_in_stack) (TYPE_MODE (type), type))
|
mgl@1371
|
4018 |
+ return true;
|
mgl@1371
|
4019 |
+
|
mgl@1371
|
4020 |
+ return false;
|
mgl@1371
|
4021 |
+}
|
mgl@1371
|
4022 |
+
|
mgl@1371
|
4023 |
+
|
mgl@1371
|
4024 |
+/* Output the constant part of the trampoline.
|
mgl@1371
|
4025 |
+ lddpc r0, pc[0x8:e] ; load static chain register
|
mgl@1371
|
4026 |
+ lddpc pc, pc[0x8:e] ; jump to subrutine
|
mgl@1371
|
4027 |
+ .long 0 ; Address to static chain,
|
mgl@1371
|
4028 |
+ ; filled in by avr32_initialize_trampoline()
|
mgl@1371
|
4029 |
+ .long 0 ; Address to subrutine,
|
mgl@1371
|
4030 |
+ ; filled in by avr32_initialize_trampoline()
|
mgl@1371
|
4031 |
+*/
|
mgl@1371
|
4032 |
+void
|
mgl@1371
|
4033 |
+avr32_trampoline_template (FILE * file)
|
mgl@1371
|
4034 |
+{
|
mgl@1371
|
4035 |
+ fprintf (file, "\tlddpc r0, pc[8]\n");
|
mgl@1371
|
4036 |
+ fprintf (file, "\tlddpc pc, pc[8]\n");
|
mgl@1371
|
4037 |
+ /* make room for the address of the static chain. */
|
mgl@1371
|
4038 |
+ fprintf (file, "\t.long\t0\n");
|
mgl@1371
|
4039 |
+ /* make room for the address to the subrutine. */
|
mgl@1371
|
4040 |
+ fprintf (file, "\t.long\t0\n");
|
mgl@1371
|
4041 |
+}
|
mgl@1371
|
4042 |
+
|
mgl@1371
|
4043 |
+
|
mgl@1371
|
4044 |
+/*
|
mgl@1371
|
4045 |
+ Initialize the variable parts of a trampoline.
|
mgl@1371
|
4046 |
+*/
|
mgl@1371
|
4047 |
+void
|
mgl@1371
|
4048 |
+avr32_initialize_trampoline (rtx addr, rtx fnaddr, rtx static_chain)
|
mgl@1371
|
4049 |
+{
|
mgl@1371
|
4050 |
+ /* Store the address to the static chain. */
|
mgl@1371
|
4051 |
+ emit_move_insn (gen_rtx_MEM
|
mgl@1371
|
4052 |
+ (SImode, plus_constant (addr, TRAMPOLINE_SIZE - 4)),
|
mgl@1371
|
4053 |
+ static_chain);
|
mgl@1371
|
4054 |
+
|
mgl@1371
|
4055 |
+ /* Store the address to the function. */
|
mgl@1371
|
4056 |
+ emit_move_insn (gen_rtx_MEM (SImode, plus_constant (addr, TRAMPOLINE_SIZE)),
|
mgl@1371
|
4057 |
+ fnaddr);
|
mgl@1371
|
4058 |
+
|
mgl@1371
|
4059 |
+ emit_insn (gen_cache (gen_rtx_REG (SImode, 13),
|
mgl@1371
|
4060 |
+ gen_rtx_CONST_INT (SImode,
|
mgl@1371
|
4061 |
+ AVR32_CACHE_INVALIDATE_ICACHE)));
|
mgl@1371
|
4062 |
+}
|
mgl@1371
|
4063 |
+
|
mgl@1371
|
4064 |
+/* Return nonzero if X is valid as an addressing register. */
|
mgl@1371
|
4065 |
+int
|
mgl@1371
|
4066 |
+avr32_address_register_rtx_p (rtx x, int strict_p)
|
mgl@1371
|
4067 |
+{
|
mgl@1371
|
4068 |
+ int regno;
|
mgl@1371
|
4069 |
+
|
mgl@1371
|
4070 |
+ if (!register_operand(x, GET_MODE(x)))
|
mgl@1371
|
4071 |
+ return 0;
|
mgl@1371
|
4072 |
+
|
mgl@1371
|
4073 |
+ /* If strict we require the register to be a hard register. */
|
mgl@1371
|
4074 |
+ if (strict_p
|
mgl@1371
|
4075 |
+ && !REG_P(x))
|
mgl@1371
|
4076 |
+ return 0;
|
mgl@1371
|
4077 |
+
|
mgl@1371
|
4078 |
+ regno = REGNO (x);
|
mgl@1371
|
4079 |
+
|
mgl@1371
|
4080 |
+ if (strict_p)
|
mgl@1371
|
4081 |
+ return REGNO_OK_FOR_BASE_P (regno);
|
mgl@1371
|
4082 |
+
|
mgl@1371
|
4083 |
+ return (regno <= LAST_REGNUM || regno >= FIRST_PSEUDO_REGISTER);
|
mgl@1371
|
4084 |
+}
|
mgl@1371
|
4085 |
+
|
mgl@1371
|
4086 |
+/* Return nonzero if INDEX is valid for an address index operand. */
|
mgl@1371
|
4087 |
+int
|
mgl@1371
|
4088 |
+avr32_legitimate_index_p (enum machine_mode mode, rtx index, int strict_p)
|
mgl@1371
|
4089 |
+{
|
mgl@1371
|
4090 |
+ enum rtx_code code = GET_CODE (index);
|
mgl@1371
|
4091 |
+
|
mgl@1371
|
4092 |
+ if (GET_MODE_SIZE (mode) > 8)
|
mgl@1371
|
4093 |
+ return 0;
|
mgl@1371
|
4094 |
+
|
mgl@1371
|
4095 |
+ /* Standard coprocessor addressing modes. */
|
mgl@1371
|
4096 |
+ if (code == CONST_INT)
|
mgl@1371
|
4097 |
+ {
|
mgl@1371
|
4098 |
+ if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
|
mgl@1371
|
4099 |
+ /* Coprocessor mem insns has a smaller reach than ordinary mem insns */
|
mgl@1371
|
4100 |
+ return CONST_OK_FOR_CONSTRAINT_P (INTVAL (index), 'K', "Ku14");
|
mgl@1371
|
4101 |
+ else
|
mgl@1371
|
4102 |
+ return CONST_OK_FOR_CONSTRAINT_P (INTVAL (index), 'K', "Ks16");
|
mgl@1371
|
4103 |
+ }
|
mgl@1371
|
4104 |
+
|
mgl@1371
|
4105 |
+ if (avr32_address_register_rtx_p (index, strict_p))
|
mgl@1371
|
4106 |
+ return 1;
|
mgl@1371
|
4107 |
+
|
mgl@1371
|
4108 |
+ if (code == MULT)
|
mgl@1371
|
4109 |
+ {
|
mgl@1371
|
4110 |
+ rtx xiop0 = XEXP (index, 0);
|
mgl@1371
|
4111 |
+ rtx xiop1 = XEXP (index, 1);
|
mgl@1371
|
4112 |
+ return ((avr32_address_register_rtx_p (xiop0, strict_p)
|
mgl@1371
|
4113 |
+ && power_of_two_operand (xiop1, SImode)
|
mgl@1371
|
4114 |
+ && (INTVAL (xiop1) <= 8))
|
mgl@1371
|
4115 |
+ || (avr32_address_register_rtx_p (xiop1, strict_p)
|
mgl@1371
|
4116 |
+ && power_of_two_operand (xiop0, SImode)
|
mgl@1371
|
4117 |
+ && (INTVAL (xiop0) <= 8)));
|
mgl@1371
|
4118 |
+ }
|
mgl@1371
|
4119 |
+ else if (code == ASHIFT)
|
mgl@1371
|
4120 |
+ {
|
mgl@1371
|
4121 |
+ rtx op = XEXP (index, 1);
|
mgl@1371
|
4122 |
+
|
mgl@1371
|
4123 |
+ return (avr32_address_register_rtx_p (XEXP (index, 0), strict_p)
|
mgl@1371
|
4124 |
+ && GET_CODE (op) == CONST_INT
|
mgl@1371
|
4125 |
+ && INTVAL (op) > 0 && INTVAL (op) <= 3);
|
mgl@1371
|
4126 |
+ }
|
mgl@1371
|
4127 |
+
|
mgl@1371
|
4128 |
+ return 0;
|
mgl@1371
|
4129 |
+}
|
mgl@1371
|
4130 |
+
|
mgl@1371
|
4131 |
+/*
|
mgl@1371
|
4132 |
+ Used in the GO_IF_LEGITIMATE_ADDRESS macro. Returns a nonzero value if
|
mgl@1371
|
4133 |
+ the RTX x is a legitimate memory address.
|
mgl@1371
|
4134 |
+
|
mgl@1371
|
4135 |
+ Returns NO_REGS if the address is not legatime, GENERAL_REGS or ALL_REGS
|
mgl@1371
|
4136 |
+ if it is.
|
mgl@1371
|
4137 |
+*/
|
mgl@1371
|
4138 |
+
|
mgl@1371
|
4139 |
+/* Forward declaration*/
|
mgl@1371
|
4140 |
+int is_minipool_label (rtx label);
|
mgl@1371
|
4141 |
+
|
mgl@1371
|
4142 |
+int
|
mgl@1371
|
4143 |
+avr32_legitimate_address (enum machine_mode mode, rtx x, int strict)
|
mgl@1371
|
4144 |
+{
|
mgl@1371
|
4145 |
+
|
mgl@1371
|
4146 |
+ switch (GET_CODE (x))
|
mgl@1371
|
4147 |
+ {
|
mgl@1371
|
4148 |
+ case REG:
|
mgl@1371
|
4149 |
+ return avr32_address_register_rtx_p (x, strict);
|
mgl@1371
|
4150 |
+ case CONST_INT:
|
mgl@1371
|
4151 |
+ return ((mode==SImode)
|
mgl@1371
|
4152 |
+ && CONST_OK_FOR_CONSTRAINT_P(INTVAL(x), 'K', "Ks17"));
|
mgl@1371
|
4153 |
+ case CONST:
|
mgl@1371
|
4154 |
+ {
|
mgl@1371
|
4155 |
+ rtx label = avr32_find_symbol (x);
|
mgl@1371
|
4156 |
+ if (label
|
mgl@1371
|
4157 |
+ &&
|
mgl@1371
|
4158 |
+ ((CONSTANT_POOL_ADDRESS_P (label)
|
mgl@1371
|
4159 |
+ && !(flag_pic
|
mgl@1371
|
4160 |
+ && (symbol_mentioned_p (get_pool_constant (label))
|
mgl@1371
|
4161 |
+ || label_mentioned_p (get_pool_constant (label)))))
|
mgl@1371
|
4162 |
+ /* TODO! Can this ever happen??? */
|
mgl@1371
|
4163 |
+ || ((GET_CODE (label) == LABEL_REF)
|
mgl@1371
|
4164 |
+ && GET_CODE (XEXP (label, 0)) == CODE_LABEL
|
mgl@1371
|
4165 |
+ && is_minipool_label (XEXP (label, 0)))
|
mgl@1371
|
4166 |
+ /*|| ((GET_CODE (label) == SYMBOL_REF)
|
mgl@1371
|
4167 |
+ && mode == SImode
|
mgl@1371
|
4168 |
+ && SYMBOL_REF_RMW_ADDR(label))*/))
|
mgl@1371
|
4169 |
+ {
|
mgl@1371
|
4170 |
+ return TRUE;
|
mgl@1371
|
4171 |
+ }
|
mgl@1371
|
4172 |
+ }
|
mgl@1371
|
4173 |
+ break;
|
mgl@1371
|
4174 |
+ case LABEL_REF:
|
mgl@1371
|
4175 |
+ if (GET_CODE (XEXP (x, 0)) == CODE_LABEL
|
mgl@1371
|
4176 |
+ && is_minipool_label (XEXP (x, 0)))
|
mgl@1371
|
4177 |
+ {
|
mgl@1371
|
4178 |
+ return TRUE;
|
mgl@1371
|
4179 |
+ }
|
mgl@1371
|
4180 |
+ break;
|
mgl@1371
|
4181 |
+ case SYMBOL_REF:
|
mgl@1371
|
4182 |
+ {
|
mgl@1371
|
4183 |
+ if (CONSTANT_POOL_ADDRESS_P (x)
|
mgl@1371
|
4184 |
+ && !(flag_pic
|
mgl@1371
|
4185 |
+ && (symbol_mentioned_p (get_pool_constant (x))
|
mgl@1371
|
4186 |
+ || label_mentioned_p (get_pool_constant (x)))))
|
mgl@1371
|
4187 |
+ return TRUE;
|
mgl@1371
|
4188 |
+ else if (SYMBOL_REF_RCALL_FUNCTION_P (x)
|
mgl@1371
|
4189 |
+ || (mode == SImode
|
mgl@1371
|
4190 |
+ && SYMBOL_REF_RMW_ADDR (x)))
|
mgl@1371
|
4191 |
+ return TRUE;
|
mgl@1371
|
4192 |
+ break;
|
mgl@1371
|
4193 |
+ }
|
mgl@1371
|
4194 |
+ case PRE_DEC: /* (pre_dec (...)) */
|
mgl@1371
|
4195 |
+ case POST_INC: /* (post_inc (...)) */
|
mgl@1371
|
4196 |
+ return avr32_address_register_rtx_p (XEXP (x, 0), strict);
|
mgl@1371
|
4197 |
+ case PLUS: /* (plus (...) (...)) */
|
mgl@1371
|
4198 |
+ {
|
mgl@1371
|
4199 |
+ rtx xop0 = XEXP (x, 0);
|
mgl@1371
|
4200 |
+ rtx xop1 = XEXP (x, 1);
|
mgl@1371
|
4201 |
+
|
mgl@1371
|
4202 |
+ return ((avr32_address_register_rtx_p (xop0, strict)
|
mgl@1371
|
4203 |
+ && avr32_legitimate_index_p (mode, xop1, strict))
|
mgl@1371
|
4204 |
+ || (avr32_address_register_rtx_p (xop1, strict)
|
mgl@1371
|
4205 |
+ && avr32_legitimate_index_p (mode, xop0, strict)));
|
mgl@1371
|
4206 |
+ }
|
mgl@1371
|
4207 |
+ default:
|
mgl@1371
|
4208 |
+ break;
|
mgl@1371
|
4209 |
+ }
|
mgl@1371
|
4210 |
+
|
mgl@1371
|
4211 |
+ return FALSE;
|
mgl@1371
|
4212 |
+}
|
mgl@1371
|
4213 |
+
|
mgl@1371
|
4214 |
+
|
mgl@1371
|
4215 |
+int
|
mgl@1371
|
4216 |
+avr32_const_ok_for_move (HOST_WIDE_INT c)
|
mgl@1371
|
4217 |
+{
|
mgl@1371
|
4218 |
+ if ( TARGET_V2_INSNS )
|
mgl@1371
|
4219 |
+ return ( avr32_const_ok_for_constraint_p (c, 'K', "Ks21")
|
mgl@1371
|
4220 |
+ /* movh instruction */
|
mgl@1371
|
4221 |
+ || avr32_hi16_immediate_operand (GEN_INT(c), VOIDmode) );
|
mgl@1371
|
4222 |
+ else
|
mgl@1371
|
4223 |
+ return avr32_const_ok_for_constraint_p (c, 'K', "Ks21");
|
mgl@1371
|
4224 |
+}
|
mgl@1371
|
4225 |
+
|
mgl@1371
|
4226 |
+int
|
mgl@1371
|
4227 |
+avr32_const_double_immediate (rtx value)
|
mgl@1371
|
4228 |
+{
|
mgl@1371
|
4229 |
+ HOST_WIDE_INT hi, lo;
|
mgl@1371
|
4230 |
+
|
mgl@1371
|
4231 |
+ if (GET_CODE (value) != CONST_DOUBLE)
|
mgl@1371
|
4232 |
+ return FALSE;
|
mgl@1371
|
4233 |
+
|
mgl@1371
|
4234 |
+ if (SCALAR_FLOAT_MODE_P (GET_MODE (value)))
|
mgl@1371
|
4235 |
+ {
|
mgl@1371
|
4236 |
+ HOST_WIDE_INT target_float[2];
|
mgl@1371
|
4237 |
+ hi = lo = 0;
|
mgl@1371
|
4238 |
+ real_to_target (target_float, CONST_DOUBLE_REAL_VALUE (value),
|
mgl@1371
|
4239 |
+ GET_MODE (value));
|
mgl@1371
|
4240 |
+ lo = target_float[0];
|
mgl@1371
|
4241 |
+ hi = target_float[1];
|
mgl@1371
|
4242 |
+ }
|
mgl@1371
|
4243 |
+ else
|
mgl@1371
|
4244 |
+ {
|
mgl@1371
|
4245 |
+ hi = CONST_DOUBLE_HIGH (value);
|
mgl@1371
|
4246 |
+ lo = CONST_DOUBLE_LOW (value);
|
mgl@1371
|
4247 |
+ }
|
mgl@1371
|
4248 |
+
|
mgl@1371
|
4249 |
+ if (avr32_const_ok_for_constraint_p (lo, 'K', "Ks21")
|
mgl@1371
|
4250 |
+ && (GET_MODE (value) == SFmode
|
mgl@1371
|
4251 |
+ || avr32_const_ok_for_constraint_p (hi, 'K', "Ks21")))
|
mgl@1371
|
4252 |
+ {
|
mgl@1371
|
4253 |
+ return TRUE;
|
mgl@1371
|
4254 |
+ }
|
mgl@1371
|
4255 |
+
|
mgl@1371
|
4256 |
+ return FALSE;
|
mgl@1371
|
4257 |
+}
|
mgl@1371
|
4258 |
+
|
mgl@1371
|
4259 |
+
|
mgl@1371
|
4260 |
+int
|
mgl@1371
|
4261 |
+avr32_legitimate_constant_p (rtx x)
|
mgl@1371
|
4262 |
+{
|
mgl@1371
|
4263 |
+ switch (GET_CODE (x))
|
mgl@1371
|
4264 |
+ {
|
mgl@1371
|
4265 |
+ case CONST_INT:
|
mgl@1371
|
4266 |
+ /* Check if we should put large immediate into constant pool
|
mgl@1371
|
4267 |
+ or load them directly with mov/orh.*/
|
mgl@1371
|
4268 |
+ if (!avr32_imm_in_const_pool)
|
mgl@1371
|
4269 |
+ return 1;
|
mgl@1371
|
4270 |
+
|
mgl@1371
|
4271 |
+ return avr32_const_ok_for_move (INTVAL (x));
|
mgl@1371
|
4272 |
+ case CONST_DOUBLE:
|
mgl@1371
|
4273 |
+ /* Check if we should put large immediate into constant pool
|
mgl@1371
|
4274 |
+ or load them directly with mov/orh.*/
|
mgl@1371
|
4275 |
+ if (!avr32_imm_in_const_pool)
|
mgl@1371
|
4276 |
+ return 1;
|
mgl@1371
|
4277 |
+
|
mgl@1371
|
4278 |
+ if (GET_MODE (x) == SFmode
|
mgl@1371
|
4279 |
+ || GET_MODE (x) == DFmode || GET_MODE (x) == DImode)
|
mgl@1371
|
4280 |
+ return avr32_const_double_immediate (x);
|
mgl@1371
|
4281 |
+ else
|
mgl@1371
|
4282 |
+ return 0;
|
mgl@1371
|
4283 |
+ case LABEL_REF:
|
mgl@1371
|
4284 |
+ case SYMBOL_REF:
|
mgl@1371
|
4285 |
+ return avr32_find_symbol (x) && (flag_pic || TARGET_HAS_ASM_ADDR_PSEUDOS);
|
mgl@1371
|
4286 |
+ case CONST:
|
mgl@1371
|
4287 |
+ case HIGH:
|
mgl@1371
|
4288 |
+ case CONST_VECTOR:
|
mgl@1371
|
4289 |
+ return 0;
|
mgl@1371
|
4290 |
+ default:
|
mgl@1371
|
4291 |
+ printf ("%s():\n", __FUNCTION__);
|
mgl@1371
|
4292 |
+ debug_rtx (x);
|
mgl@1371
|
4293 |
+ return 1;
|
mgl@1371
|
4294 |
+ }
|
mgl@1371
|
4295 |
+}
|
mgl@1371
|
4296 |
+
|
mgl@1371
|
4297 |
+
|
mgl@1371
|
4298 |
+/* Strip any special encoding from labels */
|
mgl@1371
|
4299 |
+const char *
|
mgl@1371
|
4300 |
+avr32_strip_name_encoding (const char *name)
|
mgl@1371
|
4301 |
+{
|
mgl@1371
|
4302 |
+ const char *stripped = name;
|
mgl@1371
|
4303 |
+
|
mgl@1371
|
4304 |
+ while (1)
|
mgl@1371
|
4305 |
+ {
|
mgl@1371
|
4306 |
+ switch (stripped[0])
|
mgl@1371
|
4307 |
+ {
|
mgl@1371
|
4308 |
+ case '#':
|
mgl@1371
|
4309 |
+ stripped = strchr (name + 1, '#') + 1;
|
mgl@1371
|
4310 |
+ break;
|
mgl@1371
|
4311 |
+ case '*':
|
mgl@1371
|
4312 |
+ stripped = &stripped[1];
|
mgl@1371
|
4313 |
+ break;
|
mgl@1371
|
4314 |
+ default:
|
mgl@1371
|
4315 |
+ return stripped;
|
mgl@1371
|
4316 |
+ }
|
mgl@1371
|
4317 |
+ }
|
mgl@1371
|
4318 |
+}
|
mgl@1371
|
4319 |
+
|
mgl@1371
|
4320 |
+
|
mgl@1371
|
4321 |
+
|
mgl@1371
|
4322 |
+/* Do anything needed before RTL is emitted for each function. */
|
mgl@1371
|
4323 |
+static struct machine_function *
|
mgl@1371
|
4324 |
+avr32_init_machine_status (void)
|
mgl@1371
|
4325 |
+{
|
mgl@1371
|
4326 |
+ struct machine_function *machine;
|
mgl@1371
|
4327 |
+ machine =
|
mgl@1371
|
4328 |
+ (machine_function *) ggc_alloc_cleared (sizeof (machine_function));
|
mgl@1371
|
4329 |
+
|
mgl@1371
|
4330 |
+#if AVR32_FT_UNKNOWN != 0
|
mgl@1371
|
4331 |
+ machine->func_type = AVR32_FT_UNKNOWN;
|
mgl@1371
|
4332 |
+#endif
|
mgl@1371
|
4333 |
+
|
mgl@1371
|
4334 |
+ machine->minipool_label_head = 0;
|
mgl@1371
|
4335 |
+ machine->minipool_label_tail = 0;
|
mgl@1371
|
4336 |
+ machine->ifcvt_after_reload = 0;
|
mgl@1371
|
4337 |
+ return machine;
|
mgl@1371
|
4338 |
+}
|
mgl@1371
|
4339 |
+
|
mgl@1371
|
4340 |
+void
|
mgl@1371
|
4341 |
+avr32_init_expanders (void)
|
mgl@1371
|
4342 |
+{
|
mgl@1371
|
4343 |
+ /* Arrange to initialize and mark the machine per-function status. */
|
mgl@1371
|
4344 |
+ init_machine_status = avr32_init_machine_status;
|
mgl@1371
|
4345 |
+}
|
mgl@1371
|
4346 |
+
|
mgl@1371
|
4347 |
+
|
mgl@1371
|
4348 |
+/* Return an RTX indicating where the return address to the
|
mgl@1371
|
4349 |
+ calling function can be found. */
|
mgl@1371
|
4350 |
+
|
mgl@1371
|
4351 |
+rtx
|
mgl@1371
|
4352 |
+avr32_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
|
mgl@1371
|
4353 |
+{
|
mgl@1371
|
4354 |
+ if (count != 0)
|
mgl@1371
|
4355 |
+ return NULL_RTX;
|
mgl@1371
|
4356 |
+
|
mgl@1371
|
4357 |
+ return get_hard_reg_initial_val (Pmode, LR_REGNUM);
|
mgl@1371
|
4358 |
+}
|
mgl@1371
|
4359 |
+
|
mgl@1371
|
4360 |
+
|
mgl@1371
|
4361 |
+void
|
mgl@1371
|
4362 |
+avr32_encode_section_info (tree decl, rtx rtl, int first)
|
mgl@1371
|
4363 |
+{
|
mgl@1371
|
4364 |
+ default_encode_section_info(decl, rtl, first);
|
mgl@1371
|
4365 |
+
|
mgl@1371
|
4366 |
+ if ( TREE_CODE (decl) == VAR_DECL
|
mgl@1371
|
4367 |
+ && (GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF)
|
mgl@1371
|
4368 |
+ && (lookup_attribute ("rmw_addressable", DECL_ATTRIBUTES (decl))
|
mgl@1371
|
4369 |
+ || TARGET_RMW_ADDRESSABLE_DATA) ){
|
mgl@1371
|
4370 |
+ if ( !TARGET_RMW || flag_pic )
|
mgl@1371
|
4371 |
+ return;
|
mgl@1371
|
4372 |
+ SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= (1 << SYMBOL_FLAG_RMW_ADDR_SHIFT);
|
mgl@1371
|
4373 |
+ }
|
mgl@1371
|
4374 |
+}
|
mgl@1371
|
4375 |
+
|
mgl@1371
|
4376 |
+void
|
mgl@1371
|
4377 |
+avr32_asm_output_label (FILE * stream, const char *name)
|
mgl@1371
|
4378 |
+{
|
mgl@1371
|
4379 |
+ name = avr32_strip_name_encoding (name);
|
mgl@1371
|
4380 |
+
|
mgl@1371
|
4381 |
+ /* Print the label. */
|
mgl@1371
|
4382 |
+ assemble_name (stream, name);
|
mgl@1371
|
4383 |
+ fprintf (stream, ":\n");
|
mgl@1371
|
4384 |
+}
|
mgl@1371
|
4385 |
+
|
mgl@1371
|
4386 |
+
|
mgl@1371
|
4387 |
+
|
mgl@1371
|
4388 |
+void
|
mgl@1371
|
4389 |
+avr32_asm_weaken_label (FILE * stream, const char *name)
|
mgl@1371
|
4390 |
+{
|
mgl@1371
|
4391 |
+ fprintf (stream, "\t.weak ");
|
mgl@1371
|
4392 |
+ assemble_name (stream, name);
|
mgl@1371
|
4393 |
+ fprintf (stream, "\n");
|
mgl@1371
|
4394 |
+}
|
mgl@1371
|
4395 |
+
|
mgl@1371
|
4396 |
+/*
|
mgl@1371
|
4397 |
+ Checks if a labelref is equal to a reserved word in the assembler. If it is,
|
mgl@1371
|
4398 |
+ insert a '_' before the label name.
|
mgl@1371
|
4399 |
+*/
|
mgl@1371
|
4400 |
+void
|
mgl@1371
|
4401 |
+avr32_asm_output_labelref (FILE * stream, const char *name)
|
mgl@1371
|
4402 |
+{
|
mgl@1371
|
4403 |
+ int verbatim = FALSE;
|
mgl@1371
|
4404 |
+ const char *stripped = name;
|
mgl@1371
|
4405 |
+ int strip_finished = FALSE;
|
mgl@1371
|
4406 |
+
|
mgl@1371
|
4407 |
+ while (!strip_finished)
|
mgl@1371
|
4408 |
+ {
|
mgl@1371
|
4409 |
+ switch (stripped[0])
|
mgl@1371
|
4410 |
+ {
|
mgl@1371
|
4411 |
+ case '#':
|
mgl@1371
|
4412 |
+ stripped = strchr (name + 1, '#') + 1;
|
mgl@1371
|
4413 |
+ break;
|
mgl@1371
|
4414 |
+ case '*':
|
mgl@1371
|
4415 |
+ stripped = &stripped[1];
|
mgl@1371
|
4416 |
+ verbatim = TRUE;
|
mgl@1371
|
4417 |
+ break;
|
mgl@1371
|
4418 |
+ default:
|
mgl@1371
|
4419 |
+ strip_finished = TRUE;
|
mgl@1371
|
4420 |
+ break;
|
mgl@1371
|
4421 |
+ }
|
mgl@1371
|
4422 |
+ }
|
mgl@1371
|
4423 |
+
|
mgl@1371
|
4424 |
+ if (verbatim)
|
mgl@1371
|
4425 |
+ fputs (stripped, stream);
|
mgl@1371
|
4426 |
+ else
|
mgl@1371
|
4427 |
+ asm_fprintf (stream, "%U%s", stripped);
|
mgl@1371
|
4428 |
+}
|
mgl@1371
|
4429 |
+
|
mgl@1371
|
4430 |
+
|
mgl@1371
|
4431 |
+
|
mgl@1371
|
4432 |
+/*
|
mgl@1371
|
4433 |
+ Check if the comparison in compare_exp is redundant
|
mgl@1371
|
4434 |
+ for the condition given in next_cond given that the
|
mgl@1371
|
4435 |
+ needed flags are already set by an earlier instruction.
|
mgl@1371
|
4436 |
+ Uses cc_prev_status to check this.
|
mgl@1371
|
4437 |
+
|
mgl@1371
|
4438 |
+ Returns NULL_RTX if the compare is not redundant
|
mgl@1371
|
4439 |
+ or the new condition to use in the conditional
|
mgl@1371
|
4440 |
+ instruction if the compare is redundant.
|
mgl@1371
|
4441 |
+*/
|
mgl@1371
|
4442 |
+static rtx
|
mgl@1371
|
4443 |
+is_compare_redundant (rtx compare_exp, rtx next_cond)
|
mgl@1371
|
4444 |
+{
|
mgl@1371
|
4445 |
+ int z_flag_valid = FALSE;
|
mgl@1371
|
4446 |
+ int n_flag_valid = FALSE;
|
mgl@1371
|
4447 |
+ rtx new_cond;
|
mgl@1371
|
4448 |
+
|
mgl@1371
|
4449 |
+ if (GET_CODE (compare_exp) != COMPARE
|
mgl@1371
|
4450 |
+ && GET_CODE (compare_exp) != AND)
|
mgl@1371
|
4451 |
+ return NULL_RTX;
|
mgl@1371
|
4452 |
+
|
mgl@1371
|
4453 |
+
|
mgl@1371
|
4454 |
+ if (rtx_equal_p (cc_prev_status.mdep.value, compare_exp))
|
mgl@1371
|
4455 |
+ {
|
mgl@1371
|
4456 |
+ /* cc0 already contains the correct comparison -> delete cmp insn */
|
mgl@1371
|
4457 |
+ return next_cond;
|
mgl@1371
|
4458 |
+ }
|
mgl@1371
|
4459 |
+
|
mgl@1371
|
4460 |
+ if (GET_MODE (compare_exp) != SImode)
|
mgl@1371
|
4461 |
+ return NULL_RTX;
|
mgl@1371
|
4462 |
+
|
mgl@1371
|
4463 |
+ switch (cc_prev_status.mdep.flags)
|
mgl@1371
|
4464 |
+ {
|
mgl@1371
|
4465 |
+ case CC_SET_VNCZ:
|
mgl@1371
|
4466 |
+ case CC_SET_NCZ:
|
mgl@1371
|
4467 |
+ n_flag_valid = TRUE;
|
mgl@1371
|
4468 |
+ case CC_SET_CZ:
|
mgl@1371
|
4469 |
+ case CC_SET_Z:
|
mgl@1371
|
4470 |
+ z_flag_valid = TRUE;
|
mgl@1371
|
4471 |
+ }
|
mgl@1371
|
4472 |
+
|
mgl@1371
|
4473 |
+ if (cc_prev_status.mdep.value
|
mgl@1371
|
4474 |
+ && GET_CODE (compare_exp) == COMPARE
|
mgl@1371
|
4475 |
+ && REG_P (XEXP (compare_exp, 0))
|
mgl@1371
|
4476 |
+ && REGNO (XEXP (compare_exp, 0)) == REGNO (cc_prev_status.mdep.value)
|
mgl@1371
|
4477 |
+ && GET_CODE (XEXP (compare_exp, 1)) == CONST_INT
|
mgl@1371
|
4478 |
+ && next_cond != NULL_RTX)
|
mgl@1371
|
4479 |
+ {
|
mgl@1371
|
4480 |
+ if (INTVAL (XEXP (compare_exp, 1)) == 0
|
mgl@1371
|
4481 |
+ && z_flag_valid
|
mgl@1371
|
4482 |
+ && (GET_CODE (next_cond) == EQ || GET_CODE (next_cond) == NE))
|
mgl@1371
|
4483 |
+ /* We can skip comparison Z flag is already reflecting ops[0] */
|
mgl@1371
|
4484 |
+ return next_cond;
|
mgl@1371
|
4485 |
+ else if (n_flag_valid
|
mgl@1371
|
4486 |
+ && ((INTVAL (XEXP (compare_exp, 1)) == 0
|
mgl@1371
|
4487 |
+ && (GET_CODE (next_cond) == GE
|
mgl@1371
|
4488 |
+ || GET_CODE (next_cond) == LT))
|
mgl@1371
|
4489 |
+ || (INTVAL (XEXP (compare_exp, 1)) == -1
|
mgl@1371
|
4490 |
+ && (GET_CODE (next_cond) == GT
|
mgl@1371
|
4491 |
+ || GET_CODE (next_cond) == LE))))
|
mgl@1371
|
4492 |
+ {
|
mgl@1371
|
4493 |
+ /* We can skip comparison N flag is already reflecting ops[0],
|
mgl@1371
|
4494 |
+ which means that we can use the mi/pl conditions to check if
|
mgl@1371
|
4495 |
+ ops[0] is GE or LT 0. */
|
mgl@1371
|
4496 |
+ if ((GET_CODE (next_cond) == GE) || (GET_CODE (next_cond) == GT))
|
mgl@1371
|
4497 |
+ new_cond =
|
mgl@1371
|
4498 |
+ gen_rtx_UNSPEC (GET_MODE (next_cond), gen_rtvec (2, cc0_rtx, const0_rtx),
|
mgl@1371
|
4499 |
+ UNSPEC_COND_PL);
|
mgl@1371
|
4500 |
+ else
|
mgl@1371
|
4501 |
+ new_cond =
|
mgl@1371
|
4502 |
+ gen_rtx_UNSPEC (GET_MODE (next_cond), gen_rtvec (2, cc0_rtx, const0_rtx),
|
mgl@1371
|
4503 |
+ UNSPEC_COND_MI);
|
mgl@1371
|
4504 |
+ return new_cond;
|
mgl@1371
|
4505 |
+ }
|
mgl@1371
|
4506 |
+ }
|
mgl@1371
|
4507 |
+ return NULL_RTX;
|
mgl@1371
|
4508 |
+}
|
mgl@1371
|
4509 |
+
|
mgl@1371
|
4510 |
+/* Updates cc_status. */
|
mgl@1371
|
4511 |
+void
|
mgl@1371
|
4512 |
+avr32_notice_update_cc (rtx exp, rtx insn)
|
mgl@1371
|
4513 |
+{
|
mgl@1371
|
4514 |
+ enum attr_cc attr_cc = get_attr_cc (insn);
|
mgl@1371
|
4515 |
+
|
mgl@1371
|
4516 |
+ if ( attr_cc == CC_SET_Z_IF_NOT_V2 )
|
mgl@1371
|
4517 |
+ if (TARGET_V2_INSNS)
|
mgl@1371
|
4518 |
+ attr_cc = CC_NONE;
|
mgl@1371
|
4519 |
+ else
|
mgl@1371
|
4520 |
+ attr_cc = CC_SET_Z;
|
mgl@1371
|
4521 |
+
|
mgl@1371
|
4522 |
+ switch (attr_cc)
|
mgl@1371
|
4523 |
+ {
|
mgl@1371
|
4524 |
+ case CC_CALL_SET:
|
mgl@1371
|
4525 |
+ CC_STATUS_INIT;
|
mgl@1371
|
4526 |
+ FPCC_STATUS_INIT;
|
mgl@1371
|
4527 |
+ /* Check if the function call returns a value in r12 */
|
mgl@1371
|
4528 |
+ if (REG_P (recog_data.operand[0])
|
mgl@1371
|
4529 |
+ && REGNO (recog_data.operand[0]) == RETVAL_REGNUM)
|
mgl@1371
|
4530 |
+ {
|
mgl@1371
|
4531 |
+ cc_status.flags = 0;
|
mgl@1371
|
4532 |
+ cc_status.mdep.value =
|
mgl@1371
|
4533 |
+ gen_rtx_COMPARE (SImode, recog_data.operand[0], const0_rtx);
|
mgl@1371
|
4534 |
+ cc_status.mdep.flags = CC_SET_VNCZ;
|
mgl@1371
|
4535 |
+ cc_status.mdep.cond_exec_cmp_clobbered = 0;
|
mgl@1371
|
4536 |
+
|
mgl@1371
|
4537 |
+ }
|
mgl@1371
|
4538 |
+ break;
|
mgl@1371
|
4539 |
+ case CC_COMPARE:
|
mgl@1371
|
4540 |
+ {
|
mgl@1371
|
4541 |
+ /* Check that compare will not be optimized away if so nothing should
|
mgl@1371
|
4542 |
+ be done */
|
mgl@1371
|
4543 |
+ rtx compare_exp = SET_SRC (exp);
|
mgl@1371
|
4544 |
+ /* Check if we have a tst expression. If so convert it to a
|
mgl@1371
|
4545 |
+ compare with 0. */
|
mgl@1371
|
4546 |
+ if ( REG_P (SET_SRC (exp)) )
|
mgl@1371
|
4547 |
+ compare_exp = gen_rtx_COMPARE (GET_MODE (SET_SRC (exp)),
|
mgl@1371
|
4548 |
+ SET_SRC (exp),
|
mgl@1371
|
4549 |
+ const0_rtx);
|
mgl@1371
|
4550 |
+
|
mgl@1371
|
4551 |
+ if (is_compare_redundant (compare_exp, get_next_insn_cond (insn)) ==
|
mgl@1371
|
4552 |
+ NULL_RTX)
|
mgl@1371
|
4553 |
+ {
|
mgl@1371
|
4554 |
+
|
mgl@1371
|
4555 |
+ /* Reset the nonstandard flag */
|
mgl@1371
|
4556 |
+ CC_STATUS_INIT;
|
mgl@1371
|
4557 |
+ cc_status.flags = 0;
|
mgl@1371
|
4558 |
+ cc_status.mdep.value = compare_exp;
|
mgl@1371
|
4559 |
+ cc_status.mdep.flags = CC_SET_VNCZ;
|
mgl@1371
|
4560 |
+ cc_status.mdep.cond_exec_cmp_clobbered = 0;
|
mgl@1371
|
4561 |
+ }
|
mgl@1371
|
4562 |
+ }
|
mgl@1371
|
4563 |
+ break;
|
mgl@1371
|
4564 |
+ case CC_CMP_COND_INSN:
|
mgl@1371
|
4565 |
+ {
|
mgl@1371
|
4566 |
+ /* Conditional insn that emit the compare itself. */
|
mgl@1371
|
4567 |
+ rtx cmp;
|
mgl@1371
|
4568 |
+ rtx cmp_op0, cmp_op1;
|
mgl@1371
|
4569 |
+ rtx cond;
|
mgl@1371
|
4570 |
+ rtx dest;
|
mgl@1371
|
4571 |
+ rtx next_insn = next_nonnote_insn (insn);
|
mgl@1371
|
4572 |
+
|
mgl@1371
|
4573 |
+ if ( GET_CODE (exp) == COND_EXEC )
|
mgl@1371
|
4574 |
+ {
|
mgl@1371
|
4575 |
+ cmp_op0 = XEXP (COND_EXEC_TEST (exp), 0);
|
mgl@1371
|
4576 |
+ cmp_op1 = XEXP (COND_EXEC_TEST (exp), 1);
|
mgl@1371
|
4577 |
+ cond = COND_EXEC_TEST (exp);
|
mgl@1371
|
4578 |
+ dest = SET_DEST (COND_EXEC_CODE (exp));
|
mgl@1371
|
4579 |
+ }
|
mgl@1371
|
4580 |
+ else
|
mgl@1371
|
4581 |
+ {
|
mgl@1371
|
4582 |
+ /* If then else conditional. compare operands are in operands
|
mgl@1371
|
4583 |
+ 4 and 5. */
|
mgl@1371
|
4584 |
+ cmp_op0 = recog_data.operand[4];
|
mgl@1371
|
4585 |
+ cmp_op1 = recog_data.operand[5];
|
mgl@1371
|
4586 |
+ cond = recog_data.operand[1];
|
mgl@1371
|
4587 |
+ dest = SET_DEST (exp);
|
mgl@1371
|
4588 |
+ }
|
mgl@1371
|
4589 |
+
|
mgl@1371
|
4590 |
+ if ( GET_CODE (cmp_op0) == AND )
|
mgl@1371
|
4591 |
+ cmp = cmp_op0;
|
mgl@1371
|
4592 |
+ else
|
mgl@1371
|
4593 |
+ cmp = gen_rtx_COMPARE (GET_MODE (cmp_op0),
|
mgl@1371
|
4594 |
+ cmp_op0,
|
mgl@1371
|
4595 |
+ cmp_op1);
|
mgl@1371
|
4596 |
+
|
mgl@1371
|
4597 |
+ /* Check if the conditional insns updates a register present
|
mgl@1371
|
4598 |
+ in the comparison, if so then we must reset the cc_status. */
|
mgl@1371
|
4599 |
+ if (REG_P (dest)
|
mgl@1371
|
4600 |
+ && (reg_mentioned_p (dest, cmp_op0)
|
mgl@1371
|
4601 |
+ || reg_mentioned_p (dest, cmp_op1))
|
mgl@1371
|
4602 |
+ && GET_CODE (exp) != COND_EXEC )
|
mgl@1371
|
4603 |
+ {
|
mgl@1371
|
4604 |
+ CC_STATUS_INIT;
|
mgl@1371
|
4605 |
+ }
|
mgl@1371
|
4606 |
+ else if (is_compare_redundant (cmp, cond) == NULL_RTX)
|
mgl@1371
|
4607 |
+ {
|
mgl@1371
|
4608 |
+ /* Reset the nonstandard flag */
|
mgl@1371
|
4609 |
+ CC_STATUS_INIT;
|
mgl@1371
|
4610 |
+ if ( GET_CODE (cmp_op0) == AND )
|
mgl@1371
|
4611 |
+ {
|
mgl@1371
|
4612 |
+ cc_status.flags = CC_INVERTED;
|
mgl@1371
|
4613 |
+ cc_status.mdep.flags = CC_SET_Z;
|
mgl@1371
|
4614 |
+ }
|
mgl@1371
|
4615 |
+ else
|
mgl@1371
|
4616 |
+ {
|
mgl@1371
|
4617 |
+ cc_status.flags = 0;
|
mgl@1371
|
4618 |
+ cc_status.mdep.flags = CC_SET_VNCZ;
|
mgl@1371
|
4619 |
+ }
|
mgl@1371
|
4620 |
+ cc_status.mdep.value = cmp;
|
mgl@1371
|
4621 |
+ cc_status.mdep.cond_exec_cmp_clobbered = 0;
|
mgl@1371
|
4622 |
+ }
|
mgl@1371
|
4623 |
+
|
mgl@1371
|
4624 |
+
|
mgl@1371
|
4625 |
+ /* Check if we have a COND_EXEC insn which updates one
|
mgl@1371
|
4626 |
+ of the registers in the compare status. */
|
mgl@1371
|
4627 |
+ if (REG_P (dest)
|
mgl@1371
|
4628 |
+ && (reg_mentioned_p (dest, cmp_op0)
|
mgl@1371
|
4629 |
+ || reg_mentioned_p (dest, cmp_op1))
|
mgl@1371
|
4630 |
+ && GET_CODE (exp) == COND_EXEC )
|
mgl@1371
|
4631 |
+ cc_status.mdep.cond_exec_cmp_clobbered = 1;
|
mgl@1371
|
4632 |
+
|
mgl@1371
|
4633 |
+ if ( cc_status.mdep.cond_exec_cmp_clobbered
|
mgl@1371
|
4634 |
+ && GET_CODE (exp) == COND_EXEC
|
mgl@1371
|
4635 |
+ && next_insn != NULL
|
mgl@1371
|
4636 |
+ && INSN_P (next_insn)
|
mgl@1371
|
4637 |
+ && !(GET_CODE (PATTERN (next_insn)) == COND_EXEC
|
mgl@1371
|
4638 |
+ && rtx_equal_p (XEXP (COND_EXEC_TEST (PATTERN (next_insn)), 0), cmp_op0)
|
mgl@1371
|
4639 |
+ && rtx_equal_p (XEXP (COND_EXEC_TEST (PATTERN (next_insn)), 1), cmp_op1)
|
mgl@1371
|
4640 |
+ && (GET_CODE (COND_EXEC_TEST (PATTERN (next_insn))) == GET_CODE (cond)
|
mgl@1371
|
4641 |
+ || GET_CODE (COND_EXEC_TEST (PATTERN (next_insn))) == reverse_condition (GET_CODE (cond)))) )
|
mgl@1371
|
4642 |
+ {
|
mgl@1371
|
4643 |
+ /* We have a sequence of conditional insns where the compare status has been clobbered
|
mgl@1371
|
4644 |
+ since the compare no longer reflects the content of the values to compare. */
|
mgl@1371
|
4645 |
+ CC_STATUS_INIT;
|
mgl@1371
|
4646 |
+ cc_status.mdep.cond_exec_cmp_clobbered = 1;
|
mgl@1371
|
4647 |
+ }
|
mgl@1371
|
4648 |
+
|
mgl@1371
|
4649 |
+ }
|
mgl@1371
|
4650 |
+ break;
|
mgl@1371
|
4651 |
+ case CC_FPCOMPARE:
|
mgl@1371
|
4652 |
+ /* Check that floating-point compare will not be optimized away if so
|
mgl@1371
|
4653 |
+ nothing should be done */
|
mgl@1371
|
4654 |
+ if (!rtx_equal_p (cc_prev_status.mdep.fpvalue, SET_SRC (exp)))
|
mgl@1371
|
4655 |
+ {
|
mgl@1371
|
4656 |
+ /* cc0 already contains the correct comparison -> delete cmp insn */
|
mgl@1371
|
4657 |
+ /* Reset the nonstandard flag */
|
mgl@1371
|
4658 |
+ cc_status.mdep.fpvalue = SET_SRC (exp);
|
mgl@1371
|
4659 |
+ cc_status.mdep.fpflags = CC_SET_CZ;
|
mgl@1371
|
4660 |
+ }
|
mgl@1371
|
4661 |
+ break;
|
mgl@1371
|
4662 |
+ case CC_FROM_FPCC:
|
mgl@1371
|
4663 |
+ /* Flags are updated with flags from Floating-point coprocessor, set
|
mgl@1371
|
4664 |
+ CC_NOT_SIGNED flag since the flags are set so that unsigned
|
mgl@1371
|
4665 |
+ condidion codes can be used directly. */
|
mgl@1371
|
4666 |
+ CC_STATUS_INIT;
|
mgl@1371
|
4667 |
+ cc_status.flags = CC_NOT_SIGNED;
|
mgl@1371
|
4668 |
+ cc_status.mdep.value = cc_status.mdep.fpvalue;
|
mgl@1371
|
4669 |
+ cc_status.mdep.flags = cc_status.mdep.fpflags;
|
mgl@1371
|
4670 |
+ break;
|
mgl@1371
|
4671 |
+ case CC_BLD:
|
mgl@1371
|
4672 |
+ /* Bit load is kind of like an inverted testsi, because the Z flag is
|
mgl@1371
|
4673 |
+ inverted */
|
mgl@1371
|
4674 |
+ CC_STATUS_INIT;
|
mgl@1371
|
4675 |
+ cc_status.flags = CC_INVERTED;
|
mgl@1371
|
4676 |
+ cc_status.mdep.value = SET_SRC (exp);
|
mgl@1371
|
4677 |
+ cc_status.mdep.flags = CC_SET_Z;
|
mgl@1371
|
4678 |
+ cc_status.mdep.cond_exec_cmp_clobbered = 0;
|
mgl@1371
|
4679 |
+ break;
|
mgl@1371
|
4680 |
+ case CC_NONE:
|
mgl@1371
|
4681 |
+ /* Insn does not affect CC at all. Check if the instruction updates
|
mgl@1371
|
4682 |
+ some of the register currently reflected in cc0 */
|
mgl@1371
|
4683 |
+
|
mgl@1371
|
4684 |
+ if ((GET_CODE (exp) == SET)
|
mgl@1371
|
4685 |
+ && (cc_status.value1 || cc_status.value2 || cc_status.mdep.value)
|
mgl@1371
|
4686 |
+ && (reg_mentioned_p (SET_DEST (exp), cc_status.value1)
|
mgl@1371
|
4687 |
+ || reg_mentioned_p (SET_DEST (exp), cc_status.value2)
|
mgl@1371
|
4688 |
+ || reg_mentioned_p (SET_DEST (exp), cc_status.mdep.value)))
|
mgl@1371
|
4689 |
+ {
|
mgl@1371
|
4690 |
+ CC_STATUS_INIT;
|
mgl@1371
|
4691 |
+ }
|
mgl@1371
|
4692 |
+
|
mgl@1371
|
4693 |
+ /* If this is a parallel we must step through each of the parallel
|
mgl@1371
|
4694 |
+ expressions */
|
mgl@1371
|
4695 |
+ if (GET_CODE (exp) == PARALLEL)
|
mgl@1371
|
4696 |
+ {
|
mgl@1371
|
4697 |
+ int i;
|
mgl@1371
|
4698 |
+ for (i = 0; i < XVECLEN (exp, 0); ++i)
|
mgl@1371
|
4699 |
+ {
|
mgl@1371
|
4700 |
+ rtx vec_exp = XVECEXP (exp, 0, i);
|
mgl@1371
|
4701 |
+ if ((GET_CODE (vec_exp) == SET)
|
mgl@1371
|
4702 |
+ && (cc_status.value1 || cc_status.value2
|
mgl@1371
|
4703 |
+ || cc_status.mdep.value)
|
mgl@1371
|
4704 |
+ && (reg_mentioned_p (SET_DEST (vec_exp), cc_status.value1)
|
mgl@1371
|
4705 |
+ || reg_mentioned_p (SET_DEST (vec_exp),
|
mgl@1371
|
4706 |
+ cc_status.value2)
|
mgl@1371
|
4707 |
+ || reg_mentioned_p (SET_DEST (vec_exp),
|
mgl@1371
|
4708 |
+ cc_status.mdep.value)))
|
mgl@1371
|
4709 |
+ {
|
mgl@1371
|
4710 |
+ CC_STATUS_INIT;
|
mgl@1371
|
4711 |
+ }
|
mgl@1371
|
4712 |
+ }
|
mgl@1371
|
4713 |
+ }
|
mgl@1371
|
4714 |
+
|
mgl@1371
|
4715 |
+ /* Check if we have memory opartions with post_inc or pre_dec on the
|
mgl@1371
|
4716 |
+ register currently reflected in cc0 */
|
mgl@1371
|
4717 |
+ if (GET_CODE (exp) == SET
|
mgl@1371
|
4718 |
+ && GET_CODE (SET_SRC (exp)) == MEM
|
mgl@1371
|
4719 |
+ && (GET_CODE (XEXP (SET_SRC (exp), 0)) == POST_INC
|
mgl@1371
|
4720 |
+ || GET_CODE (XEXP (SET_SRC (exp), 0)) == PRE_DEC)
|
mgl@1371
|
4721 |
+ &&
|
mgl@1371
|
4722 |
+ (reg_mentioned_p
|
mgl@1371
|
4723 |
+ (XEXP (XEXP (SET_SRC (exp), 0), 0), cc_status.value1)
|
mgl@1371
|
4724 |
+ || reg_mentioned_p (XEXP (XEXP (SET_SRC (exp), 0), 0),
|
mgl@1371
|
4725 |
+ cc_status.value2)
|
mgl@1371
|
4726 |
+ || reg_mentioned_p (XEXP (XEXP (SET_SRC (exp), 0), 0),
|
mgl@1371
|
4727 |
+ cc_status.mdep.value)))
|
mgl@1371
|
4728 |
+ CC_STATUS_INIT;
|
mgl@1371
|
4729 |
+
|
mgl@1371
|
4730 |
+ if (GET_CODE (exp) == SET
|
mgl@1371
|
4731 |
+ && GET_CODE (SET_DEST (exp)) == MEM
|
mgl@1371
|
4732 |
+ && (GET_CODE (XEXP (SET_DEST (exp), 0)) == POST_INC
|
mgl@1371
|
4733 |
+ || GET_CODE (XEXP (SET_DEST (exp), 0)) == PRE_DEC)
|
mgl@1371
|
4734 |
+ &&
|
mgl@1371
|
4735 |
+ (reg_mentioned_p
|
mgl@1371
|
4736 |
+ (XEXP (XEXP (SET_DEST (exp), 0), 0), cc_status.value1)
|
mgl@1371
|
4737 |
+ || reg_mentioned_p (XEXP (XEXP (SET_DEST (exp), 0), 0),
|
mgl@1371
|
4738 |
+ cc_status.value2)
|
mgl@1371
|
4739 |
+ || reg_mentioned_p (XEXP (XEXP (SET_DEST (exp), 0), 0),
|
mgl@1371
|
4740 |
+ cc_status.mdep.value)))
|
mgl@1371
|
4741 |
+ CC_STATUS_INIT;
|
mgl@1371
|
4742 |
+ break;
|
mgl@1371
|
4743 |
+
|
mgl@1371
|
4744 |
+ case CC_SET_VNCZ:
|
mgl@1371
|
4745 |
+ CC_STATUS_INIT;
|
mgl@1371
|
4746 |
+ cc_status.mdep.value = recog_data.operand[0];
|
mgl@1371
|
4747 |
+ cc_status.mdep.flags = CC_SET_VNCZ;
|
mgl@1371
|
4748 |
+ cc_status.mdep.cond_exec_cmp_clobbered = 0;
|
mgl@1371
|
4749 |
+ break;
|
mgl@1371
|
4750 |
+
|
mgl@1371
|
4751 |
+ case CC_SET_NCZ:
|
mgl@1371
|
4752 |
+ CC_STATUS_INIT;
|
mgl@1371
|
4753 |
+ cc_status.mdep.value = recog_data.operand[0];
|
mgl@1371
|
4754 |
+ cc_status.mdep.flags = CC_SET_NCZ;
|
mgl@1371
|
4755 |
+ cc_status.mdep.cond_exec_cmp_clobbered = 0;
|
mgl@1371
|
4756 |
+ break;
|
mgl@1371
|
4757 |
+
|
mgl@1371
|
4758 |
+ case CC_SET_CZ:
|
mgl@1371
|
4759 |
+ CC_STATUS_INIT;
|
mgl@1371
|
4760 |
+ cc_status.mdep.value = recog_data.operand[0];
|
mgl@1371
|
4761 |
+ cc_status.mdep.flags = CC_SET_CZ;
|
mgl@1371
|
4762 |
+ cc_status.mdep.cond_exec_cmp_clobbered = 0;
|
mgl@1371
|
4763 |
+ break;
|
mgl@1371
|
4764 |
+
|
mgl@1371
|
4765 |
+ case CC_SET_Z:
|
mgl@1371
|
4766 |
+ CC_STATUS_INIT;
|
mgl@1371
|
4767 |
+ cc_status.mdep.value = recog_data.operand[0];
|
mgl@1371
|
4768 |
+ cc_status.mdep.flags = CC_SET_Z;
|
mgl@1371
|
4769 |
+ cc_status.mdep.cond_exec_cmp_clobbered = 0;
|
mgl@1371
|
4770 |
+ break;
|
mgl@1371
|
4771 |
+
|
mgl@1371
|
4772 |
+ case CC_CLOBBER:
|
mgl@1371
|
4773 |
+ CC_STATUS_INIT;
|
mgl@1371
|
4774 |
+ break;
|
mgl@1371
|
4775 |
+
|
mgl@1371
|
4776 |
+ default:
|
mgl@1371
|
4777 |
+ CC_STATUS_INIT;
|
mgl@1371
|
4778 |
+ }
|
mgl@1371
|
4779 |
+}
|
mgl@1371
|
4780 |
+
|
mgl@1371
|
4781 |
+
|
mgl@1371
|
4782 |
+/*
|
mgl@1371
|
4783 |
+ Outputs to stdio stream stream the assembler syntax for an instruction
|
mgl@1371
|
4784 |
+ operand x. x is an RTL expression.
|
mgl@1371
|
4785 |
+*/
|
mgl@1371
|
4786 |
+void
|
mgl@1371
|
4787 |
+avr32_print_operand (FILE * stream, rtx x, int code)
|
mgl@1371
|
4788 |
+{
|
mgl@1371
|
4789 |
+ int error = 0;
|
mgl@1371
|
4790 |
+
|
mgl@1371
|
4791 |
+ if ( code == '?' )
|
mgl@1371
|
4792 |
+ {
|
mgl@1371
|
4793 |
+ /* Predicable instruction, print condition code */
|
mgl@1371
|
4794 |
+
|
mgl@1371
|
4795 |
+ /* If the insn should not be conditional then do nothing. */
|
mgl@1371
|
4796 |
+ if ( current_insn_predicate == NULL_RTX )
|
mgl@1371
|
4797 |
+ return;
|
mgl@1371
|
4798 |
+
|
mgl@1371
|
4799 |
+ /* Set x to the predicate to force printing
|
mgl@1371
|
4800 |
+ the condition later on. */
|
mgl@1371
|
4801 |
+ x = current_insn_predicate;
|
mgl@1371
|
4802 |
+
|
mgl@1371
|
4803 |
+ /* Reverse condition if useing bld insn. */
|
mgl@1371
|
4804 |
+ if ( GET_CODE (XEXP(current_insn_predicate,0)) == AND )
|
mgl@1371
|
4805 |
+ x = reversed_condition (current_insn_predicate);
|
mgl@1371
|
4806 |
+ }
|
mgl@1371
|
4807 |
+ else if ( code == '!' )
|
mgl@1371
|
4808 |
+ {
|
mgl@1371
|
4809 |
+ /* Output compare for conditional insn if needed. */
|
mgl@1371
|
4810 |
+ rtx new_cond;
|
mgl@1371
|
4811 |
+ gcc_assert ( current_insn_predicate != NULL_RTX );
|
mgl@1371
|
4812 |
+ new_cond = avr32_output_cmp(current_insn_predicate,
|
mgl@1371
|
4813 |
+ GET_MODE(XEXP(current_insn_predicate,0)),
|
mgl@1371
|
4814 |
+ XEXP(current_insn_predicate,0),
|
mgl@1371
|
4815 |
+ XEXP(current_insn_predicate,1));
|
mgl@1371
|
4816 |
+
|
mgl@1371
|
4817 |
+ /* Check if the new condition is a special avr32 condition
|
mgl@1371
|
4818 |
+ specified using UNSPECs. If so we must handle it differently. */
|
mgl@1371
|
4819 |
+ if ( GET_CODE (new_cond) == UNSPEC )
|
mgl@1371
|
4820 |
+ {
|
mgl@1371
|
4821 |
+ current_insn_predicate =
|
mgl@1371
|
4822 |
+ gen_rtx_UNSPEC (CCmode,
|
mgl@1371
|
4823 |
+ gen_rtvec (2,
|
mgl@1371
|
4824 |
+ XEXP(current_insn_predicate,0),
|
mgl@1371
|
4825 |
+ XEXP(current_insn_predicate,1)),
|
mgl@1371
|
4826 |
+ XINT (new_cond, 1));
|
mgl@1371
|
4827 |
+ }
|
mgl@1371
|
4828 |
+ else
|
mgl@1371
|
4829 |
+ {
|
mgl@1371
|
4830 |
+ PUT_CODE(current_insn_predicate, GET_CODE(new_cond));
|
mgl@1371
|
4831 |
+ }
|
mgl@1371
|
4832 |
+ return;
|
mgl@1371
|
4833 |
+ }
|
mgl@1371
|
4834 |
+
|
mgl@1371
|
4835 |
+ switch (GET_CODE (x))
|
mgl@1371
|
4836 |
+ {
|
mgl@1371
|
4837 |
+ case UNSPEC:
|
mgl@1371
|
4838 |
+ switch (XINT (x, 1))
|
mgl@1371
|
4839 |
+ {
|
mgl@1371
|
4840 |
+ case UNSPEC_COND_PL:
|
mgl@1371
|
4841 |
+ if (code == 'i')
|
mgl@1371
|
4842 |
+ fputs ("mi", stream);
|
mgl@1371
|
4843 |
+ else
|
mgl@1371
|
4844 |
+ fputs ("pl", stream);
|
mgl@1371
|
4845 |
+ break;
|
mgl@1371
|
4846 |
+ case UNSPEC_COND_MI:
|
mgl@1371
|
4847 |
+ if (code == 'i')
|
mgl@1371
|
4848 |
+ fputs ("pl", stream);
|
mgl@1371
|
4849 |
+ else
|
mgl@1371
|
4850 |
+ fputs ("mi", stream);
|
mgl@1371
|
4851 |
+ break;
|
mgl@1371
|
4852 |
+ default:
|
mgl@1371
|
4853 |
+ error = 1;
|
mgl@1371
|
4854 |
+ }
|
mgl@1371
|
4855 |
+ break;
|
mgl@1371
|
4856 |
+ case EQ:
|
mgl@1371
|
4857 |
+ if (code == 'i')
|
mgl@1371
|
4858 |
+ fputs ("ne", stream);
|
mgl@1371
|
4859 |
+ else
|
mgl@1371
|
4860 |
+ fputs ("eq", stream);
|
mgl@1371
|
4861 |
+ break;
|
mgl@1371
|
4862 |
+ case NE:
|
mgl@1371
|
4863 |
+ if (code == 'i')
|
mgl@1371
|
4864 |
+ fputs ("eq", stream);
|
mgl@1371
|
4865 |
+ else
|
mgl@1371
|
4866 |
+ fputs ("ne", stream);
|
mgl@1371
|
4867 |
+ break;
|
mgl@1371
|
4868 |
+ case GT:
|
mgl@1371
|
4869 |
+ if (code == 'i')
|
mgl@1371
|
4870 |
+ fputs ("le", stream);
|
mgl@1371
|
4871 |
+ else
|
mgl@1371
|
4872 |
+ fputs ("gt", stream);
|
mgl@1371
|
4873 |
+ break;
|
mgl@1371
|
4874 |
+ case GTU:
|
mgl@1371
|
4875 |
+ if (code == 'i')
|
mgl@1371
|
4876 |
+ fputs ("ls", stream);
|
mgl@1371
|
4877 |
+ else
|
mgl@1371
|
4878 |
+ fputs ("hi", stream);
|
mgl@1371
|
4879 |
+ break;
|
mgl@1371
|
4880 |
+ case LT:
|
mgl@1371
|
4881 |
+ if (code == 'i')
|
mgl@1371
|
4882 |
+ fputs ("ge", stream);
|
mgl@1371
|
4883 |
+ else
|
mgl@1371
|
4884 |
+ fputs ("lt", stream);
|
mgl@1371
|
4885 |
+ break;
|
mgl@1371
|
4886 |
+ case LTU:
|
mgl@1371
|
4887 |
+ if (code == 'i')
|
mgl@1371
|
4888 |
+ fputs ("hs", stream);
|
mgl@1371
|
4889 |
+ else
|
mgl@1371
|
4890 |
+ fputs ("lo", stream);
|
mgl@1371
|
4891 |
+ break;
|
mgl@1371
|
4892 |
+ case GE:
|
mgl@1371
|
4893 |
+ if (code == 'i')
|
mgl@1371
|
4894 |
+ fputs ("lt", stream);
|
mgl@1371
|
4895 |
+ else
|
mgl@1371
|
4896 |
+ fputs ("ge", stream);
|
mgl@1371
|
4897 |
+ break;
|
mgl@1371
|
4898 |
+ case GEU:
|
mgl@1371
|
4899 |
+ if (code == 'i')
|
mgl@1371
|
4900 |
+ fputs ("lo", stream);
|
mgl@1371
|
4901 |
+ else
|
mgl@1371
|
4902 |
+ fputs ("hs", stream);
|
mgl@1371
|
4903 |
+ break;
|
mgl@1371
|
4904 |
+ case LE:
|
mgl@1371
|
4905 |
+ if (code == 'i')
|
mgl@1371
|
4906 |
+ fputs ("gt", stream);
|
mgl@1371
|
4907 |
+ else
|
mgl@1371
|
4908 |
+ fputs ("le", stream);
|
mgl@1371
|
4909 |
+ break;
|
mgl@1371
|
4910 |
+ case LEU:
|
mgl@1371
|
4911 |
+ if (code == 'i')
|
mgl@1371
|
4912 |
+ fputs ("hi", stream);
|
mgl@1371
|
4913 |
+ else
|
mgl@1371
|
4914 |
+ fputs ("ls", stream);
|
mgl@1371
|
4915 |
+ break;
|
mgl@1371
|
4916 |
+ case CONST_INT:
|
mgl@1371
|
4917 |
+ {
|
mgl@1371
|
4918 |
+ HOST_WIDE_INT value = INTVAL (x);
|
mgl@1371
|
4919 |
+
|
mgl@1371
|
4920 |
+ switch (code)
|
mgl@1371
|
4921 |
+ {
|
mgl@1371
|
4922 |
+ case 'm':
|
mgl@1371
|
4923 |
+ if ( HOST_BITS_PER_WIDE_INT > BITS_PER_WORD )
|
mgl@1371
|
4924 |
+ {
|
mgl@1371
|
4925 |
+ /* A const_int can be used to represent DImode constants. */
|
mgl@1371
|
4926 |
+ value >>= BITS_PER_WORD;
|
mgl@1371
|
4927 |
+ }
|
mgl@1371
|
4928 |
+ /* We might get a const_int immediate for setting a DI register,
|
mgl@1371
|
4929 |
+ we then must then return the correct sign extended DI. The most
|
mgl@1371
|
4930 |
+ significant word is just a sign extension. */
|
mgl@1371
|
4931 |
+ else if (value < 0)
|
mgl@1371
|
4932 |
+ value = -1;
|
mgl@1371
|
4933 |
+ else
|
mgl@1371
|
4934 |
+ value = 0;
|
mgl@1371
|
4935 |
+ break;
|
mgl@1371
|
4936 |
+ case 'i':
|
mgl@1371
|
4937 |
+ value++;
|
mgl@1371
|
4938 |
+ break;
|
mgl@1371
|
4939 |
+ case 'p':
|
mgl@1371
|
4940 |
+ {
|
mgl@1371
|
4941 |
+ /* Set to bit position of first bit set in immediate */
|
mgl@1371
|
4942 |
+ int i, bitpos = 32;
|
mgl@1371
|
4943 |
+ for (i = 0; i < 32; i++)
|
mgl@1371
|
4944 |
+ if (value & (1 << i))
|
mgl@1371
|
4945 |
+ {
|
mgl@1371
|
4946 |
+ bitpos = i;
|
mgl@1371
|
4947 |
+ break;
|
mgl@1371
|
4948 |
+ }
|
mgl@1371
|
4949 |
+ value = bitpos;
|
mgl@1371
|
4950 |
+ }
|
mgl@1371
|
4951 |
+ break;
|
mgl@1371
|
4952 |
+ case 'z':
|
mgl@1371
|
4953 |
+ {
|
mgl@1371
|
4954 |
+ /* Set to bit position of first bit cleared in immediate */
|
mgl@1371
|
4955 |
+ int i, bitpos = 32;
|
mgl@1371
|
4956 |
+ for (i = 0; i < 32; i++)
|
mgl@1371
|
4957 |
+ if (!(value & (1 << i)))
|
mgl@1371
|
4958 |
+ {
|
mgl@1371
|
4959 |
+ bitpos = i;
|
mgl@1371
|
4960 |
+ break;
|
mgl@1371
|
4961 |
+ }
|
mgl@1371
|
4962 |
+ value = bitpos;
|
mgl@1371
|
4963 |
+ }
|
mgl@1371
|
4964 |
+ break;
|
mgl@1371
|
4965 |
+ case 'r':
|
mgl@1371
|
4966 |
+ {
|
mgl@1371
|
4967 |
+ /* Reglist 8 */
|
mgl@1371
|
4968 |
+ char op[50];
|
mgl@1371
|
4969 |
+ op[0] = '\0';
|
mgl@1371
|
4970 |
+
|
mgl@1371
|
4971 |
+ if (value & 0x01)
|
mgl@1371
|
4972 |
+ sprintf (op, "r0-r3");
|
mgl@1371
|
4973 |
+ if (value & 0x02)
|
mgl@1371
|
4974 |
+ strlen (op) ? sprintf (op, "%s, r4-r7", op) : sprintf (op,
|
mgl@1371
|
4975 |
+ "r4-r7");
|
mgl@1371
|
4976 |
+ if (value & 0x04)
|
mgl@1371
|
4977 |
+ strlen (op) ? sprintf (op, "%s, r8-r9", op) : sprintf (op,
|
mgl@1371
|
4978 |
+ "r8-r9");
|
mgl@1371
|
4979 |
+ if (value & 0x08)
|
mgl@1371
|
4980 |
+ strlen (op) ? sprintf (op, "%s, r10", op) : sprintf (op,
|
mgl@1371
|
4981 |
+ "r10");
|
mgl@1371
|
4982 |
+ if (value & 0x10)
|
mgl@1371
|
4983 |
+ strlen (op) ? sprintf (op, "%s, r11", op) : sprintf (op,
|
mgl@1371
|
4984 |
+ "r11");
|
mgl@1371
|
4985 |
+ if (value & 0x20)
|
mgl@1371
|
4986 |
+ strlen (op) ? sprintf (op, "%s, r12", op) : sprintf (op,
|
mgl@1371
|
4987 |
+ "r12");
|
mgl@1371
|
4988 |
+ if (value & 0x40)
|
mgl@1371
|
4989 |
+ strlen (op) ? sprintf (op, "%s, lr", op) : sprintf (op, "lr");
|
mgl@1371
|
4990 |
+ if (value & 0x80)
|
mgl@1371
|
4991 |
+ strlen (op) ? sprintf (op, "%s, pc", op) : sprintf (op, "pc");
|
mgl@1371
|
4992 |
+
|
mgl@1371
|
4993 |
+ fputs (op, stream);
|
mgl@1371
|
4994 |
+ return;
|
mgl@1371
|
4995 |
+ }
|
mgl@1371
|
4996 |
+ case 's':
|
mgl@1371
|
4997 |
+ {
|
mgl@1371
|
4998 |
+ /* Reglist 16 */
|
mgl@1371
|
4999 |
+ char reglist16_string[100];
|
mgl@1371
|
5000 |
+ int i;
|
mgl@1371
|
5001 |
+ reglist16_string[0] = '\0';
|
mgl@1371
|
5002 |
+
|
mgl@1371
|
5003 |
+ for (i = 0; i < 16; ++i)
|
mgl@1371
|
5004 |
+ {
|
mgl@1371
|
5005 |
+ if (value & (1 << i))
|
mgl@1371
|
5006 |
+ {
|
mgl@1371
|
5007 |
+ strlen (reglist16_string) ? sprintf (reglist16_string,
|
mgl@1371
|
5008 |
+ "%s, %s",
|
mgl@1371
|
5009 |
+ reglist16_string,
|
mgl@1371
|
5010 |
+ reg_names
|
mgl@1371
|
5011 |
+ [INTERNAL_REGNUM
|
mgl@1371
|
5012 |
+ (i)]) :
|
mgl@1371
|
5013 |
+ sprintf (reglist16_string, "%s",
|
mgl@1371
|
5014 |
+ reg_names[INTERNAL_REGNUM (i)]);
|
mgl@1371
|
5015 |
+ }
|
mgl@1371
|
5016 |
+ }
|
mgl@1371
|
5017 |
+ fputs (reglist16_string, stream);
|
mgl@1371
|
5018 |
+ return;
|
mgl@1371
|
5019 |
+ }
|
mgl@1371
|
5020 |
+ case 'C':
|
mgl@1371
|
5021 |
+ {
|
mgl@1371
|
5022 |
+ /* RegListCP8 */
|
mgl@1371
|
5023 |
+ char reglist_string[100];
|
mgl@1371
|
5024 |
+ avr32_make_fp_reglist_w (value, (char *) reglist_string);
|
mgl@1371
|
5025 |
+ fputs (reglist_string, stream);
|
mgl@1371
|
5026 |
+ return;
|
mgl@1371
|
5027 |
+ }
|
mgl@1371
|
5028 |
+ case 'D':
|
mgl@1371
|
5029 |
+ {
|
mgl@1371
|
5030 |
+ /* RegListCPD8 */
|
mgl@1371
|
5031 |
+ char reglist_string[100];
|
mgl@1371
|
5032 |
+ avr32_make_fp_reglist_d (value, (char *) reglist_string);
|
mgl@1371
|
5033 |
+ fputs (reglist_string, stream);
|
mgl@1371
|
5034 |
+ return;
|
mgl@1371
|
5035 |
+ }
|
mgl@1371
|
5036 |
+ case 'h':
|
mgl@1371
|
5037 |
+ /* Print halfword part of word */
|
mgl@1371
|
5038 |
+ fputs (value ? "b" : "t", stream);
|
mgl@1371
|
5039 |
+ return;
|
mgl@1371
|
5040 |
+ }
|
mgl@1371
|
5041 |
+
|
mgl@1371
|
5042 |
+ /* Print Value */
|
mgl@1371
|
5043 |
+ fprintf (stream, "%d", value);
|
mgl@1371
|
5044 |
+ break;
|
mgl@1371
|
5045 |
+ }
|
mgl@1371
|
5046 |
+ case CONST_DOUBLE:
|
mgl@1371
|
5047 |
+ {
|
mgl@1371
|
5048 |
+ HOST_WIDE_INT hi, lo;
|
mgl@1371
|
5049 |
+ if (SCALAR_FLOAT_MODE_P (GET_MODE (x)))
|
mgl@1371
|
5050 |
+ {
|
mgl@1371
|
5051 |
+ HOST_WIDE_INT target_float[2];
|
mgl@1371
|
5052 |
+ hi = lo = 0;
|
mgl@1371
|
5053 |
+ real_to_target (target_float, CONST_DOUBLE_REAL_VALUE (x),
|
mgl@1371
|
5054 |
+ GET_MODE (x));
|
mgl@1371
|
5055 |
+ /* For doubles the most significant part starts at index 0. */
|
mgl@1371
|
5056 |
+ if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
|
mgl@1371
|
5057 |
+ {
|
mgl@1371
|
5058 |
+ hi = target_float[0];
|
mgl@1371
|
5059 |
+ lo = target_float[1];
|
mgl@1371
|
5060 |
+ }
|
mgl@1371
|
5061 |
+ else
|
mgl@1371
|
5062 |
+ {
|
mgl@1371
|
5063 |
+ lo = target_float[0];
|
mgl@1371
|
5064 |
+ }
|
mgl@1371
|
5065 |
+ }
|
mgl@1371
|
5066 |
+ else
|
mgl@1371
|
5067 |
+ {
|
mgl@1371
|
5068 |
+ hi = CONST_DOUBLE_HIGH (x);
|
mgl@1371
|
5069 |
+ lo = CONST_DOUBLE_LOW (x);
|
mgl@1371
|
5070 |
+ }
|
mgl@1371
|
5071 |
+
|
mgl@1371
|
5072 |
+ if (code == 'm')
|
mgl@1371
|
5073 |
+ fprintf (stream, "%ld", hi);
|
mgl@1371
|
5074 |
+ else
|
mgl@1371
|
5075 |
+ fprintf (stream, "%ld", lo);
|
mgl@1371
|
5076 |
+
|
mgl@1371
|
5077 |
+ break;
|
mgl@1371
|
5078 |
+ }
|
mgl@1371
|
5079 |
+ case CONST:
|
mgl@1371
|
5080 |
+ output_addr_const (stream, XEXP (XEXP (x, 0), 0));
|
mgl@1371
|
5081 |
+ fprintf (stream, "+%ld", INTVAL (XEXP (XEXP (x, 0), 1)));
|
mgl@1371
|
5082 |
+ break;
|
mgl@1371
|
5083 |
+ case REG:
|
mgl@1371
|
5084 |
+ /* Swap register name if the register is DImode or DFmode. */
|
mgl@1371
|
5085 |
+ if (GET_MODE (x) == DImode || GET_MODE (x) == DFmode)
|
mgl@1371
|
5086 |
+ {
|
mgl@1371
|
5087 |
+ /* Double register must have an even numbered address */
|
mgl@1371
|
5088 |
+ gcc_assert (!(REGNO (x) % 2));
|
mgl@1371
|
5089 |
+ if (code == 'm')
|
mgl@1371
|
5090 |
+ fputs (reg_names[true_regnum (x)], stream);
|
mgl@1371
|
5091 |
+ else
|
mgl@1371
|
5092 |
+ fputs (reg_names[true_regnum (x) + 1], stream);
|
mgl@1371
|
5093 |
+ }
|
mgl@1371
|
5094 |
+ else if (GET_MODE (x) == TImode)
|
mgl@1371
|
5095 |
+ {
|
mgl@1371
|
5096 |
+ switch (code)
|
mgl@1371
|
5097 |
+ {
|
mgl@1371
|
5098 |
+ case 'T':
|
mgl@1371
|
5099 |
+ fputs (reg_names[true_regnum (x)], stream);
|
mgl@1371
|
5100 |
+ break;
|
mgl@1371
|
5101 |
+ case 'U':
|
mgl@1371
|
5102 |
+ fputs (reg_names[true_regnum (x) + 1], stream);
|
mgl@1371
|
5103 |
+ break;
|
mgl@1371
|
5104 |
+ case 'L':
|
mgl@1371
|
5105 |
+ fputs (reg_names[true_regnum (x) + 2], stream);
|
mgl@1371
|
5106 |
+ break;
|
mgl@1371
|
5107 |
+ case 'B':
|
mgl@1371
|
5108 |
+ fputs (reg_names[true_regnum (x) + 3], stream);
|
mgl@1371
|
5109 |
+ break;
|
mgl@1371
|
5110 |
+ default:
|
mgl@1371
|
5111 |
+ fprintf (stream, "%s, %s, %s, %s",
|
mgl@1371
|
5112 |
+ reg_names[true_regnum (x) + 3],
|
mgl@1371
|
5113 |
+ reg_names[true_regnum (x) + 2],
|
mgl@1371
|
5114 |
+ reg_names[true_regnum (x) + 1],
|
mgl@1371
|
5115 |
+ reg_names[true_regnum (x)]);
|
mgl@1371
|
5116 |
+ break;
|
mgl@1371
|
5117 |
+ }
|
mgl@1371
|
5118 |
+ }
|
mgl@1371
|
5119 |
+ else
|
mgl@1371
|
5120 |
+ {
|
mgl@1371
|
5121 |
+ fputs (reg_names[true_regnum (x)], stream);
|
mgl@1371
|
5122 |
+ }
|
mgl@1371
|
5123 |
+ break;
|
mgl@1371
|
5124 |
+ case CODE_LABEL:
|
mgl@1371
|
5125 |
+ case LABEL_REF:
|
mgl@1371
|
5126 |
+ case SYMBOL_REF:
|
mgl@1371
|
5127 |
+ output_addr_const (stream, x);
|
mgl@1371
|
5128 |
+ break;
|
mgl@1371
|
5129 |
+ case MEM:
|
mgl@1371
|
5130 |
+ switch (GET_CODE (XEXP (x, 0)))
|
mgl@1371
|
5131 |
+ {
|
mgl@1371
|
5132 |
+ case LABEL_REF:
|
mgl@1371
|
5133 |
+ case SYMBOL_REF:
|
mgl@1371
|
5134 |
+ output_addr_const (stream, XEXP (x, 0));
|
mgl@1371
|
5135 |
+ break;
|
mgl@1371
|
5136 |
+ case MEM:
|
mgl@1371
|
5137 |
+ switch (GET_CODE (XEXP (XEXP (x, 0), 0)))
|
mgl@1371
|
5138 |
+ {
|
mgl@1371
|
5139 |
+ case SYMBOL_REF:
|
mgl@1371
|
5140 |
+ output_addr_const (stream, XEXP (XEXP (x, 0), 0));
|
mgl@1371
|
5141 |
+ break;
|
mgl@1371
|
5142 |
+ default:
|
mgl@1371
|
5143 |
+ error = 1;
|
mgl@1371
|
5144 |
+ break;
|
mgl@1371
|
5145 |
+ }
|
mgl@1371
|
5146 |
+ break;
|
mgl@1371
|
5147 |
+ case REG:
|
mgl@1371
|
5148 |
+ avr32_print_operand (stream, XEXP (x, 0), 0);
|
mgl@1371
|
5149 |
+ if (code != 'p')
|
mgl@1371
|
5150 |
+ fputs ("[0]", stream);
|
mgl@1371
|
5151 |
+ break;
|
mgl@1371
|
5152 |
+ case PRE_DEC:
|
mgl@1371
|
5153 |
+ fputs ("--", stream);
|
mgl@1371
|
5154 |
+ avr32_print_operand (stream, XEXP (XEXP (x, 0), 0), 0);
|
mgl@1371
|
5155 |
+ break;
|
mgl@1371
|
5156 |
+ case POST_INC:
|
mgl@1371
|
5157 |
+ avr32_print_operand (stream, XEXP (XEXP (x, 0), 0), 0);
|
mgl@1371
|
5158 |
+ fputs ("++", stream);
|
mgl@1371
|
5159 |
+ break;
|
mgl@1371
|
5160 |
+ case PLUS:
|
mgl@1371
|
5161 |
+ {
|
mgl@1371
|
5162 |
+ rtx op0 = XEXP (XEXP (x, 0), 0);
|
mgl@1371
|
5163 |
+ rtx op1 = XEXP (XEXP (x, 0), 1);
|
mgl@1371
|
5164 |
+ rtx base = NULL_RTX, offset = NULL_RTX;
|
mgl@1371
|
5165 |
+
|
mgl@1371
|
5166 |
+ if (avr32_address_register_rtx_p (op0, 1))
|
mgl@1371
|
5167 |
+ {
|
mgl@1371
|
5168 |
+ base = op0;
|
mgl@1371
|
5169 |
+ offset = op1;
|
mgl@1371
|
5170 |
+ }
|
mgl@1371
|
5171 |
+ else if (avr32_address_register_rtx_p (op1, 1))
|
mgl@1371
|
5172 |
+ {
|
mgl@1371
|
5173 |
+ /* Operands are switched. */
|
mgl@1371
|
5174 |
+ base = op1;
|
mgl@1371
|
5175 |
+ offset = op0;
|
mgl@1371
|
5176 |
+ }
|
mgl@1371
|
5177 |
+
|
mgl@1371
|
5178 |
+ gcc_assert (base && offset
|
mgl@1371
|
5179 |
+ && avr32_address_register_rtx_p (base, 1)
|
mgl@1371
|
5180 |
+ && avr32_legitimate_index_p (GET_MODE (x), offset,
|
mgl@1371
|
5181 |
+ 1));
|
mgl@1371
|
5182 |
+
|
mgl@1371
|
5183 |
+ avr32_print_operand (stream, base, 0);
|
mgl@1371
|
5184 |
+ fputs ("[", stream);
|
mgl@1371
|
5185 |
+ avr32_print_operand (stream, offset, 0);
|
mgl@1371
|
5186 |
+ fputs ("]", stream);
|
mgl@1371
|
5187 |
+ break;
|
mgl@1371
|
5188 |
+ }
|
mgl@1371
|
5189 |
+ case CONST:
|
mgl@1371
|
5190 |
+ output_addr_const (stream, XEXP (XEXP (XEXP (x, 0), 0), 0));
|
mgl@1371
|
5191 |
+ fprintf (stream, " + %ld",
|
mgl@1371
|
5192 |
+ INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1)));
|
mgl@1371
|
5193 |
+ break;
|
mgl@1371
|
5194 |
+ case CONST_INT:
|
mgl@1371
|
5195 |
+ avr32_print_operand (stream, XEXP (x, 0), 0);
|
mgl@1371
|
5196 |
+ break;
|
mgl@1371
|
5197 |
+ default:
|
mgl@1371
|
5198 |
+ error = 1;
|
mgl@1371
|
5199 |
+ }
|
mgl@1371
|
5200 |
+ break;
|
mgl@1371
|
5201 |
+ case MULT:
|
mgl@1371
|
5202 |
+ {
|
mgl@1371
|
5203 |
+ int value = INTVAL (XEXP (x, 1));
|
mgl@1371
|
5204 |
+
|
mgl@1371
|
5205 |
+ /* Convert immediate in multiplication into a shift immediate */
|
mgl@1371
|
5206 |
+ switch (value)
|
mgl@1371
|
5207 |
+ {
|
mgl@1371
|
5208 |
+ case 2:
|
mgl@1371
|
5209 |
+ value = 1;
|
mgl@1371
|
5210 |
+ break;
|
mgl@1371
|
5211 |
+ case 4:
|
mgl@1371
|
5212 |
+ value = 2;
|
mgl@1371
|
5213 |
+ break;
|
mgl@1371
|
5214 |
+ case 8:
|
mgl@1371
|
5215 |
+ value = 3;
|
mgl@1371
|
5216 |
+ break;
|
mgl@1371
|
5217 |
+ default:
|
mgl@1371
|
5218 |
+ value = 0;
|
mgl@1371
|
5219 |
+ }
|
mgl@1371
|
5220 |
+ fprintf (stream, "%s << %i", reg_names[true_regnum (XEXP (x, 0))],
|
mgl@1371
|
5221 |
+ value);
|
mgl@1371
|
5222 |
+ break;
|
mgl@1371
|
5223 |
+ }
|
mgl@1371
|
5224 |
+ case ASHIFT:
|
mgl@1371
|
5225 |
+ if (GET_CODE (XEXP (x, 1)) == CONST_INT)
|
mgl@1371
|
5226 |
+ fprintf (stream, "%s << %i", reg_names[true_regnum (XEXP (x, 0))],
|
mgl@1371
|
5227 |
+ (int) INTVAL (XEXP (x, 1)));
|
mgl@1371
|
5228 |
+ else if (REG_P (XEXP (x, 1)))
|
mgl@1371
|
5229 |
+ fprintf (stream, "%s << %s", reg_names[true_regnum (XEXP (x, 0))],
|
mgl@1371
|
5230 |
+ reg_names[true_regnum (XEXP (x, 1))]);
|
mgl@1371
|
5231 |
+ else
|
mgl@1371
|
5232 |
+ {
|
mgl@1371
|
5233 |
+ error = 1;
|
mgl@1371
|
5234 |
+ }
|
mgl@1371
|
5235 |
+ break;
|
mgl@1371
|
5236 |
+ case LSHIFTRT:
|
mgl@1371
|
5237 |
+ if (GET_CODE (XEXP (x, 1)) == CONST_INT)
|
mgl@1371
|
5238 |
+ fprintf (stream, "%s >> %i", reg_names[true_regnum (XEXP (x, 0))],
|
mgl@1371
|
5239 |
+ (int) INTVAL (XEXP (x, 1)));
|
mgl@1371
|
5240 |
+ else if (REG_P (XEXP (x, 1)))
|
mgl@1371
|
5241 |
+ fprintf (stream, "%s >> %s", reg_names[true_regnum (XEXP (x, 0))],
|
mgl@1371
|
5242 |
+ reg_names[true_regnum (XEXP (x, 1))]);
|
mgl@1371
|
5243 |
+ else
|
mgl@1371
|
5244 |
+ {
|
mgl@1371
|
5245 |
+ error = 1;
|
mgl@1371
|
5246 |
+ }
|
mgl@1371
|
5247 |
+ fprintf (stream, ">>");
|
mgl@1371
|
5248 |
+ break;
|
mgl@1371
|
5249 |
+ case PARALLEL:
|
mgl@1371
|
5250 |
+ {
|
mgl@1371
|
5251 |
+ /* Load store multiple */
|
mgl@1371
|
5252 |
+ int i;
|
mgl@1371
|
5253 |
+ int count = XVECLEN (x, 0);
|
mgl@1371
|
5254 |
+ int reglist16 = 0;
|
mgl@1371
|
5255 |
+ char reglist16_string[100];
|
mgl@1371
|
5256 |
+
|
mgl@1371
|
5257 |
+ for (i = 0; i < count; ++i)
|
mgl@1371
|
5258 |
+ {
|
mgl@1371
|
5259 |
+ rtx vec_elm = XVECEXP (x, 0, i);
|
mgl@1371
|
5260 |
+ if (GET_MODE (vec_elm) != SET)
|
mgl@1371
|
5261 |
+ {
|
mgl@1371
|
5262 |
+ debug_rtx (vec_elm);
|
mgl@1371
|
5263 |
+ internal_error ("Unknown element in parallel expression!");
|
mgl@1371
|
5264 |
+ }
|
mgl@1371
|
5265 |
+ if (GET_MODE (XEXP (vec_elm, 0)) == REG)
|
mgl@1371
|
5266 |
+ {
|
mgl@1371
|
5267 |
+ /* Load multiple */
|
mgl@1371
|
5268 |
+ reglist16 |= 1 << ASM_REGNUM (REGNO (XEXP (vec_elm, 0)));
|
mgl@1371
|
5269 |
+ }
|
mgl@1371
|
5270 |
+ else
|
mgl@1371
|
5271 |
+ {
|
mgl@1371
|
5272 |
+ /* Store multiple */
|
mgl@1371
|
5273 |
+ reglist16 |= 1 << ASM_REGNUM (REGNO (XEXP (vec_elm, 1)));
|
mgl@1371
|
5274 |
+ }
|
mgl@1371
|
5275 |
+ }
|
mgl@1371
|
5276 |
+
|
mgl@1371
|
5277 |
+ avr32_make_reglist16 (reglist16, reglist16_string);
|
mgl@1371
|
5278 |
+ fputs (reglist16_string, stream);
|
mgl@1371
|
5279 |
+
|
mgl@1371
|
5280 |
+ break;
|
mgl@1371
|
5281 |
+ }
|
mgl@1371
|
5282 |
+
|
mgl@1371
|
5283 |
+ case PLUS:
|
mgl@1371
|
5284 |
+ {
|
mgl@1371
|
5285 |
+ rtx op0 = XEXP (x, 0);
|
mgl@1371
|
5286 |
+ rtx op1 = XEXP (x, 1);
|
mgl@1371
|
5287 |
+ rtx base = NULL_RTX, offset = NULL_RTX;
|
mgl@1371
|
5288 |
+
|
mgl@1371
|
5289 |
+ if (avr32_address_register_rtx_p (op0, 1))
|
mgl@1371
|
5290 |
+ {
|
mgl@1371
|
5291 |
+ base = op0;
|
mgl@1371
|
5292 |
+ offset = op1;
|
mgl@1371
|
5293 |
+ }
|
mgl@1371
|
5294 |
+ else if (avr32_address_register_rtx_p (op1, 1))
|
mgl@1371
|
5295 |
+ {
|
mgl@1371
|
5296 |
+ /* Operands are switched. */
|
mgl@1371
|
5297 |
+ base = op1;
|
mgl@1371
|
5298 |
+ offset = op0;
|
mgl@1371
|
5299 |
+ }
|
mgl@1371
|
5300 |
+
|
mgl@1371
|
5301 |
+ gcc_assert (base && offset
|
mgl@1371
|
5302 |
+ && avr32_address_register_rtx_p (base, 1)
|
mgl@1371
|
5303 |
+ && avr32_legitimate_index_p (GET_MODE (x), offset, 1));
|
mgl@1371
|
5304 |
+
|
mgl@1371
|
5305 |
+ avr32_print_operand (stream, base, 0);
|
mgl@1371
|
5306 |
+ fputs ("[", stream);
|
mgl@1371
|
5307 |
+ avr32_print_operand (stream, offset, 0);
|
mgl@1371
|
5308 |
+ fputs ("]", stream);
|
mgl@1371
|
5309 |
+ break;
|
mgl@1371
|
5310 |
+ }
|
mgl@1371
|
5311 |
+
|
mgl@1371
|
5312 |
+ default:
|
mgl@1371
|
5313 |
+ error = 1;
|
mgl@1371
|
5314 |
+ }
|
mgl@1371
|
5315 |
+
|
mgl@1371
|
5316 |
+ if (error)
|
mgl@1371
|
5317 |
+ {
|
mgl@1371
|
5318 |
+ debug_rtx (x);
|
mgl@1371
|
5319 |
+ internal_error ("Illegal expression for avr32_print_operand");
|
mgl@1371
|
5320 |
+ }
|
mgl@1371
|
5321 |
+}
|
mgl@1371
|
5322 |
+
|
mgl@1371
|
5323 |
+rtx
|
mgl@1371
|
5324 |
+avr32_get_note_reg_equiv (rtx insn)
|
mgl@1371
|
5325 |
+{
|
mgl@1371
|
5326 |
+ rtx note;
|
mgl@1371
|
5327 |
+
|
mgl@1371
|
5328 |
+ note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
|
mgl@1371
|
5329 |
+
|
mgl@1371
|
5330 |
+ if (note != NULL_RTX)
|
mgl@1371
|
5331 |
+ return XEXP (note, 0);
|
mgl@1371
|
5332 |
+ else
|
mgl@1371
|
5333 |
+ return NULL_RTX;
|
mgl@1371
|
5334 |
+}
|
mgl@1371
|
5335 |
+
|
mgl@1371
|
5336 |
+/*
|
mgl@1371
|
5337 |
+ Outputs to stdio stream stream the assembler syntax for an instruction
|
mgl@1371
|
5338 |
+ operand that is a memory reference whose address is x. x is an RTL
|
mgl@1371
|
5339 |
+ expression.
|
mgl@1371
|
5340 |
+
|
mgl@1371
|
5341 |
+ ToDo: fixme.
|
mgl@1371
|
5342 |
+*/
|
mgl@1371
|
5343 |
+void
|
mgl@1371
|
5344 |
+avr32_print_operand_address (FILE * stream, rtx x)
|
mgl@1371
|
5345 |
+{
|
mgl@1371
|
5346 |
+ fprintf (stream, "(%d) /* address */", REGNO (x));
|
mgl@1371
|
5347 |
+}
|
mgl@1371
|
5348 |
+
|
mgl@1371
|
5349 |
+/* Return true if _GLOBAL_OFFSET_TABLE_ symbol is mentioned. */
|
mgl@1371
|
5350 |
+bool
|
mgl@1371
|
5351 |
+avr32_got_mentioned_p (rtx addr)
|
mgl@1371
|
5352 |
+{
|
mgl@1371
|
5353 |
+ if (GET_CODE (addr) == MEM)
|
mgl@1371
|
5354 |
+ addr = XEXP (addr, 0);
|
mgl@1371
|
5355 |
+ while (GET_CODE (addr) == CONST)
|
mgl@1371
|
5356 |
+ addr = XEXP (addr, 0);
|
mgl@1371
|
5357 |
+ if (GET_CODE (addr) == SYMBOL_REF)
|
mgl@1371
|
5358 |
+ {
|
mgl@1371
|
5359 |
+ return streq (XSTR (addr, 0), "_GLOBAL_OFFSET_TABLE_");
|
mgl@1371
|
5360 |
+ }
|
mgl@1371
|
5361 |
+ if (GET_CODE (addr) == PLUS || GET_CODE (addr) == MINUS)
|
mgl@1371
|
5362 |
+ {
|
mgl@1371
|
5363 |
+ bool l1, l2;
|
mgl@1371
|
5364 |
+
|
mgl@1371
|
5365 |
+ l1 = avr32_got_mentioned_p (XEXP (addr, 0));
|
mgl@1371
|
5366 |
+ l2 = avr32_got_mentioned_p (XEXP (addr, 1));
|
mgl@1371
|
5367 |
+ return l1 || l2;
|
mgl@1371
|
5368 |
+ }
|
mgl@1371
|
5369 |
+ return false;
|
mgl@1371
|
5370 |
+}
|
mgl@1371
|
5371 |
+
|
mgl@1371
|
5372 |
+
|
mgl@1371
|
5373 |
+/* Find the symbol in an address expression. */
|
mgl@1371
|
5374 |
+
|
mgl@1371
|
5375 |
+rtx
|
mgl@1371
|
5376 |
+avr32_find_symbol (rtx addr)
|
mgl@1371
|
5377 |
+{
|
mgl@1371
|
5378 |
+ if (GET_CODE (addr) == MEM)
|
mgl@1371
|
5379 |
+ addr = XEXP (addr, 0);
|
mgl@1371
|
5380 |
+
|
mgl@1371
|
5381 |
+ while (GET_CODE (addr) == CONST)
|
mgl@1371
|
5382 |
+ addr = XEXP (addr, 0);
|
mgl@1371
|
5383 |
+
|
mgl@1371
|
5384 |
+ if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
|
mgl@1371
|
5385 |
+ return addr;
|
mgl@1371
|
5386 |
+ if (GET_CODE (addr) == PLUS)
|
mgl@1371
|
5387 |
+ {
|
mgl@1371
|
5388 |
+ rtx l1, l2;
|
mgl@1371
|
5389 |
+
|
mgl@1371
|
5390 |
+ l1 = avr32_find_symbol (XEXP (addr, 0));
|
mgl@1371
|
5391 |
+ l2 = avr32_find_symbol (XEXP (addr, 1));
|
mgl@1371
|
5392 |
+ if (l1 != NULL_RTX && l2 == NULL_RTX)
|
mgl@1371
|
5393 |
+ return l1;
|
mgl@1371
|
5394 |
+ else if (l1 == NULL_RTX && l2 != NULL_RTX)
|
mgl@1371
|
5395 |
+ return l2;
|
mgl@1371
|
5396 |
+ }
|
mgl@1371
|
5397 |
+
|
mgl@1371
|
5398 |
+ return NULL_RTX;
|
mgl@1371
|
5399 |
+}
|
mgl@1371
|
5400 |
+
|
mgl@1371
|
5401 |
+
|
mgl@1371
|
5402 |
+/* Routines for manipulation of the constant pool. */
|
mgl@1371
|
5403 |
+
|
mgl@1371
|
5404 |
+/* AVR32 instructions cannot load a large constant directly into a
|
mgl@1371
|
5405 |
+ register; they have to come from a pc relative load. The constant
|
mgl@1371
|
5406 |
+ must therefore be placed in the addressable range of the pc
|
mgl@1371
|
5407 |
+ relative load. Depending on the precise pc relative load
|
mgl@1371
|
5408 |
+ instruction the range is somewhere between 256 bytes and 4k. This
|
mgl@1371
|
5409 |
+ means that we often have to dump a constant inside a function, and
|
mgl@1371
|
5410 |
+ generate code to branch around it.
|
mgl@1371
|
5411 |
+
|
mgl@1371
|
5412 |
+ It is important to minimize this, since the branches will slow
|
mgl@1371
|
5413 |
+ things down and make the code larger.
|
mgl@1371
|
5414 |
+
|
mgl@1371
|
5415 |
+ Normally we can hide the table after an existing unconditional
|
mgl@1371
|
5416 |
+ branch so that there is no interruption of the flow, but in the
|
mgl@1371
|
5417 |
+ worst case the code looks like this:
|
mgl@1371
|
5418 |
+
|
mgl@1371
|
5419 |
+ lddpc rn, L1
|
mgl@1371
|
5420 |
+ ...
|
mgl@1371
|
5421 |
+ rjmp L2
|
mgl@1371
|
5422 |
+ align
|
mgl@1371
|
5423 |
+ L1: .long value
|
mgl@1371
|
5424 |
+ L2:
|
mgl@1371
|
5425 |
+ ...
|
mgl@1371
|
5426 |
+
|
mgl@1371
|
5427 |
+ lddpc rn, L3
|
mgl@1371
|
5428 |
+ ...
|
mgl@1371
|
5429 |
+ rjmp L4
|
mgl@1371
|
5430 |
+ align
|
mgl@1371
|
5431 |
+ L3: .long value
|
mgl@1371
|
5432 |
+ L4:
|
mgl@1371
|
5433 |
+ ...
|
mgl@1371
|
5434 |
+
|
mgl@1371
|
5435 |
+ We fix this by performing a scan after scheduling, which notices
|
mgl@1371
|
5436 |
+ which instructions need to have their operands fetched from the
|
mgl@1371
|
5437 |
+ constant table and builds the table.
|
mgl@1371
|
5438 |
+
|
mgl@1371
|
5439 |
+ The algorithm starts by building a table of all the constants that
|
mgl@1371
|
5440 |
+ need fixing up and all the natural barriers in the function (places
|
mgl@1371
|
5441 |
+ where a constant table can be dropped without breaking the flow).
|
mgl@1371
|
5442 |
+ For each fixup we note how far the pc-relative replacement will be
|
mgl@1371
|
5443 |
+ able to reach and the offset of the instruction into the function.
|
mgl@1371
|
5444 |
+
|
mgl@1371
|
5445 |
+ Having built the table we then group the fixes together to form
|
mgl@1371
|
5446 |
+ tables that are as large as possible (subject to addressing
|
mgl@1371
|
5447 |
+ constraints) and emit each table of constants after the last
|
mgl@1371
|
5448 |
+ barrier that is within range of all the instructions in the group.
|
mgl@1371
|
5449 |
+ If a group does not contain a barrier, then we forcibly create one
|
mgl@1371
|
5450 |
+ by inserting a jump instruction into the flow. Once the table has
|
mgl@1371
|
5451 |
+ been inserted, the insns are then modified to reference the
|
mgl@1371
|
5452 |
+ relevant entry in the pool.
|
mgl@1371
|
5453 |
+
|
mgl@1371
|
5454 |
+ Possible enhancements to the algorithm (not implemented) are:
|
mgl@1371
|
5455 |
+
|
mgl@1371
|
5456 |
+ 1) For some processors and object formats, there may be benefit in
|
mgl@1371
|
5457 |
+ aligning the pools to the start of cache lines; this alignment
|
mgl@1371
|
5458 |
+ would need to be taken into account when calculating addressability
|
mgl@1371
|
5459 |
+ of a pool. */
|
mgl@1371
|
5460 |
+
|
mgl@1371
|
5461 |
+/* These typedefs are located at the start of this file, so that
|
mgl@1371
|
5462 |
+ they can be used in the prototypes there. This comment is to
|
mgl@1371
|
5463 |
+ remind readers of that fact so that the following structures
|
mgl@1371
|
5464 |
+ can be understood more easily.
|
mgl@1371
|
5465 |
+
|
mgl@1371
|
5466 |
+ typedef struct minipool_node Mnode;
|
mgl@1371
|
5467 |
+ typedef struct minipool_fixup Mfix; */
|
mgl@1371
|
5468 |
+
|
mgl@1371
|
5469 |
+struct minipool_node
|
mgl@1371
|
5470 |
+{
|
mgl@1371
|
5471 |
+ /* Doubly linked chain of entries. */
|
mgl@1371
|
5472 |
+ Mnode *next;
|
mgl@1371
|
5473 |
+ Mnode *prev;
|
mgl@1371
|
5474 |
+ /* The maximum offset into the code that this entry can be placed. While
|
mgl@1371
|
5475 |
+ pushing fixes for forward references, all entries are sorted in order of
|
mgl@1371
|
5476 |
+ increasing max_address. */
|
mgl@1371
|
5477 |
+ HOST_WIDE_INT max_address;
|
mgl@1371
|
5478 |
+ /* Similarly for an entry inserted for a backwards ref. */
|
mgl@1371
|
5479 |
+ HOST_WIDE_INT min_address;
|
mgl@1371
|
5480 |
+ /* The number of fixes referencing this entry. This can become zero if we
|
mgl@1371
|
5481 |
+ "unpush" an entry. In this case we ignore the entry when we come to
|
mgl@1371
|
5482 |
+ emit the code. */
|
mgl@1371
|
5483 |
+ int refcount;
|
mgl@1371
|
5484 |
+ /* The offset from the start of the minipool. */
|
mgl@1371
|
5485 |
+ HOST_WIDE_INT offset;
|
mgl@1371
|
5486 |
+ /* The value in table. */
|
mgl@1371
|
5487 |
+ rtx value;
|
mgl@1371
|
5488 |
+ /* The mode of value. */
|
mgl@1371
|
5489 |
+ enum machine_mode mode;
|
mgl@1371
|
5490 |
+ /* The size of the value. */
|
mgl@1371
|
5491 |
+ int fix_size;
|
mgl@1371
|
5492 |
+};
|
mgl@1371
|
5493 |
+
|
mgl@1371
|
5494 |
+struct minipool_fixup
|
mgl@1371
|
5495 |
+{
|
mgl@1371
|
5496 |
+ Mfix *next;
|
mgl@1371
|
5497 |
+ rtx insn;
|
mgl@1371
|
5498 |
+ HOST_WIDE_INT address;
|
mgl@1371
|
5499 |
+ rtx *loc;
|
mgl@1371
|
5500 |
+ enum machine_mode mode;
|
mgl@1371
|
5501 |
+ int fix_size;
|
mgl@1371
|
5502 |
+ rtx value;
|
mgl@1371
|
5503 |
+ Mnode *minipool;
|
mgl@1371
|
5504 |
+ HOST_WIDE_INT forwards;
|
mgl@1371
|
5505 |
+ HOST_WIDE_INT backwards;
|
mgl@1371
|
5506 |
+};
|
mgl@1371
|
5507 |
+
|
mgl@1371
|
5508 |
+
|
mgl@1371
|
5509 |
+/* Fixes less than a word need padding out to a word boundary. */
|
mgl@1371
|
5510 |
+#define MINIPOOL_FIX_SIZE(mode, value) \
|
mgl@1371
|
5511 |
+ (IS_FORCE_MINIPOOL(value) ? 0 : \
|
mgl@1371
|
5512 |
+ (GET_MODE_SIZE ((mode)) >= 4 ? GET_MODE_SIZE ((mode)) : 4))
|
mgl@1371
|
5513 |
+
|
mgl@1371
|
5514 |
+#define IS_FORCE_MINIPOOL(x) \
|
mgl@1371
|
5515 |
+ (GET_CODE(x) == UNSPEC && \
|
mgl@1371
|
5516 |
+ XINT(x, 1) == UNSPEC_FORCE_MINIPOOL)
|
mgl@1371
|
5517 |
+
|
mgl@1371
|
5518 |
+static Mnode *minipool_vector_head;
|
mgl@1371
|
5519 |
+static Mnode *minipool_vector_tail;
|
mgl@1371
|
5520 |
+
|
mgl@1371
|
5521 |
+/* The linked list of all minipool fixes required for this function. */
|
mgl@1371
|
5522 |
+Mfix *minipool_fix_head;
|
mgl@1371
|
5523 |
+Mfix *minipool_fix_tail;
|
mgl@1371
|
5524 |
+/* The fix entry for the current minipool, once it has been placed. */
|
mgl@1371
|
5525 |
+Mfix *minipool_barrier;
|
mgl@1371
|
5526 |
+
|
mgl@1371
|
5527 |
+/* Determines if INSN is the start of a jump table. Returns the end
|
mgl@1371
|
5528 |
+ of the TABLE or NULL_RTX. */
|
mgl@1371
|
5529 |
+static rtx
|
mgl@1371
|
5530 |
+is_jump_table (rtx insn)
|
mgl@1371
|
5531 |
+{
|
mgl@1371
|
5532 |
+ rtx table;
|
mgl@1371
|
5533 |
+
|
mgl@1371
|
5534 |
+ if (GET_CODE (insn) == JUMP_INSN
|
mgl@1371
|
5535 |
+ && JUMP_LABEL (insn) != NULL
|
mgl@1371
|
5536 |
+ && ((table = next_real_insn (JUMP_LABEL (insn)))
|
mgl@1371
|
5537 |
+ == next_real_insn (insn))
|
mgl@1371
|
5538 |
+ && table != NULL
|
mgl@1371
|
5539 |
+ && GET_CODE (table) == JUMP_INSN
|
mgl@1371
|
5540 |
+ && (GET_CODE (PATTERN (table)) == ADDR_VEC
|
mgl@1371
|
5541 |
+ || GET_CODE (PATTERN (table)) == ADDR_DIFF_VEC))
|
mgl@1371
|
5542 |
+ return table;
|
mgl@1371
|
5543 |
+
|
mgl@1371
|
5544 |
+ return NULL_RTX;
|
mgl@1371
|
5545 |
+}
|
mgl@1371
|
5546 |
+
|
mgl@1371
|
5547 |
+static HOST_WIDE_INT
|
mgl@1371
|
5548 |
+get_jump_table_size (rtx insn)
|
mgl@1371
|
5549 |
+{
|
mgl@1371
|
5550 |
+ /* ADDR_VECs only take room if read-only data does into the text section. */
|
mgl@1371
|
5551 |
+ if (JUMP_TABLES_IN_TEXT_SECTION
|
mgl@1371
|
5552 |
+#if !defined(READONLY_DATA_SECTION_ASM_OP)
|
mgl@1371
|
5553 |
+ || 1
|
mgl@1371
|
5554 |
+#endif
|
mgl@1371
|
5555 |
+ )
|
mgl@1371
|
5556 |
+ {
|
mgl@1371
|
5557 |
+ rtx body = PATTERN (insn);
|
mgl@1371
|
5558 |
+ int elt = GET_CODE (body) == ADDR_DIFF_VEC ? 1 : 0;
|
mgl@1371
|
5559 |
+
|
mgl@1371
|
5560 |
+ return GET_MODE_SIZE (GET_MODE (body)) * XVECLEN (body, elt);
|
mgl@1371
|
5561 |
+ }
|
mgl@1371
|
5562 |
+
|
mgl@1371
|
5563 |
+ return 0;
|
mgl@1371
|
5564 |
+}
|
mgl@1371
|
5565 |
+
|
mgl@1371
|
5566 |
+/* Move a minipool fix MP from its current location to before MAX_MP.
|
mgl@1371
|
5567 |
+ If MAX_MP is NULL, then MP doesn't need moving, but the addressing
|
mgl@1371
|
5568 |
+ constraints may need updating. */
|
mgl@1371
|
5569 |
+static Mnode *
|
mgl@1371
|
5570 |
+move_minipool_fix_forward_ref (Mnode * mp, Mnode * max_mp,
|
mgl@1371
|
5571 |
+ HOST_WIDE_INT max_address)
|
mgl@1371
|
5572 |
+{
|
mgl@1371
|
5573 |
+ /* This should never be true and the code below assumes these are
|
mgl@1371
|
5574 |
+ different. */
|
mgl@1371
|
5575 |
+ if (mp == max_mp)
|
mgl@1371
|
5576 |
+ abort ();
|
mgl@1371
|
5577 |
+
|
mgl@1371
|
5578 |
+ if (max_mp == NULL)
|
mgl@1371
|
5579 |
+ {
|
mgl@1371
|
5580 |
+ if (max_address < mp->max_address)
|
mgl@1371
|
5581 |
+ mp->max_address = max_address;
|
mgl@1371
|
5582 |
+ }
|
mgl@1371
|
5583 |
+ else
|
mgl@1371
|
5584 |
+ {
|
mgl@1371
|
5585 |
+ if (max_address > max_mp->max_address - mp->fix_size)
|
mgl@1371
|
5586 |
+ mp->max_address = max_mp->max_address - mp->fix_size;
|
mgl@1371
|
5587 |
+ else
|
mgl@1371
|
5588 |
+ mp->max_address = max_address;
|
mgl@1371
|
5589 |
+
|
mgl@1371
|
5590 |
+ /* Unlink MP from its current position. Since max_mp is non-null,
|
mgl@1371
|
5591 |
+ mp->prev must be non-null. */
|
mgl@1371
|
5592 |
+ mp->prev->next = mp->next;
|
mgl@1371
|
5593 |
+ if (mp->next != NULL)
|
mgl@1371
|
5594 |
+ mp->next->prev = mp->prev;
|
mgl@1371
|
5595 |
+ else
|
mgl@1371
|
5596 |
+ minipool_vector_tail = mp->prev;
|
mgl@1371
|
5597 |
+
|
mgl@1371
|
5598 |
+ /* Re-insert it before MAX_MP. */
|
mgl@1371
|
5599 |
+ mp->next = max_mp;
|
mgl@1371
|
5600 |
+ mp->prev = max_mp->prev;
|
mgl@1371
|
5601 |
+ max_mp->prev = mp;
|
mgl@1371
|
5602 |
+
|
mgl@1371
|
5603 |
+ if (mp->prev != NULL)
|
mgl@1371
|
5604 |
+ mp->prev->next = mp;
|
mgl@1371
|
5605 |
+ else
|
mgl@1371
|
5606 |
+ minipool_vector_head = mp;
|
mgl@1371
|
5607 |
+ }
|
mgl@1371
|
5608 |
+
|
mgl@1371
|
5609 |
+ /* Save the new entry. */
|
mgl@1371
|
5610 |
+ max_mp = mp;
|
mgl@1371
|
5611 |
+
|
mgl@1371
|
5612 |
+ /* Scan over the preceding entries and adjust their addresses as required.
|
mgl@1371
|
5613 |
+ */
|
mgl@1371
|
5614 |
+ while (mp->prev != NULL
|
mgl@1371
|
5615 |
+ && mp->prev->max_address > mp->max_address - mp->prev->fix_size)
|
mgl@1371
|
5616 |
+ {
|
mgl@1371
|
5617 |
+ mp->prev->max_address = mp->max_address - mp->prev->fix_size;
|
mgl@1371
|
5618 |
+ mp = mp->prev;
|
mgl@1371
|
5619 |
+ }
|
mgl@1371
|
5620 |
+
|
mgl@1371
|
5621 |
+ return max_mp;
|
mgl@1371
|
5622 |
+}
|
mgl@1371
|
5623 |
+
|
mgl@1371
|
5624 |
+/* Add a constant to the minipool for a forward reference. Returns the
|
mgl@1371
|
5625 |
+ node added or NULL if the constant will not fit in this pool. */
|
mgl@1371
|
5626 |
+static Mnode *
|
mgl@1371
|
5627 |
+add_minipool_forward_ref (Mfix * fix)
|
mgl@1371
|
5628 |
+{
|
mgl@1371
|
5629 |
+ /* If set, max_mp is the first pool_entry that has a lower constraint than
|
mgl@1371
|
5630 |
+ the one we are trying to add. */
|
mgl@1371
|
5631 |
+ Mnode *max_mp = NULL;
|
mgl@1371
|
5632 |
+ HOST_WIDE_INT max_address = fix->address + fix->forwards;
|
mgl@1371
|
5633 |
+ Mnode *mp;
|
mgl@1371
|
5634 |
+
|
mgl@1371
|
5635 |
+ /* If this fix's address is greater than the address of the first entry,
|
mgl@1371
|
5636 |
+ then we can't put the fix in this pool. We subtract the size of the
|
mgl@1371
|
5637 |
+ current fix to ensure that if the table is fully packed we still have
|
mgl@1371
|
5638 |
+ enough room to insert this value by suffling the other fixes forwards. */
|
mgl@1371
|
5639 |
+ if (minipool_vector_head &&
|
mgl@1371
|
5640 |
+ fix->address >= minipool_vector_head->max_address - fix->fix_size)
|
mgl@1371
|
5641 |
+ return NULL;
|
mgl@1371
|
5642 |
+
|
mgl@1371
|
5643 |
+ /* Scan the pool to see if a constant with the same value has already been
|
mgl@1371
|
5644 |
+ added. While we are doing this, also note the location where we must
|
mgl@1371
|
5645 |
+ insert the constant if it doesn't already exist. */
|
mgl@1371
|
5646 |
+ for (mp = minipool_vector_head; mp != NULL; mp = mp->next)
|
mgl@1371
|
5647 |
+ {
|
mgl@1371
|
5648 |
+ if (GET_CODE (fix->value) == GET_CODE (mp->value)
|
mgl@1371
|
5649 |
+ && fix->mode == mp->mode
|
mgl@1371
|
5650 |
+ && (GET_CODE (fix->value) != CODE_LABEL
|
mgl@1371
|
5651 |
+ || (CODE_LABEL_NUMBER (fix->value)
|
mgl@1371
|
5652 |
+ == CODE_LABEL_NUMBER (mp->value)))
|
mgl@1371
|
5653 |
+ && rtx_equal_p (fix->value, mp->value))
|
mgl@1371
|
5654 |
+ {
|
mgl@1371
|
5655 |
+ /* More than one fix references this entry. */
|
mgl@1371
|
5656 |
+ mp->refcount++;
|
mgl@1371
|
5657 |
+ return move_minipool_fix_forward_ref (mp, max_mp, max_address);
|
mgl@1371
|
5658 |
+ }
|
mgl@1371
|
5659 |
+
|
mgl@1371
|
5660 |
+ /* Note the insertion point if necessary. */
|
mgl@1371
|
5661 |
+ if (max_mp == NULL && mp->max_address > max_address)
|
mgl@1371
|
5662 |
+ max_mp = mp;
|
mgl@1371
|
5663 |
+
|
mgl@1371
|
5664 |
+ }
|
mgl@1371
|
5665 |
+
|
mgl@1371
|
5666 |
+ /* The value is not currently in the minipool, so we need to create a new
|
mgl@1371
|
5667 |
+ entry for it. If MAX_MP is NULL, the entry will be put on the end of
|
mgl@1371
|
5668 |
+ the list since the placement is less constrained than any existing
|
mgl@1371
|
5669 |
+ entry. Otherwise, we insert the new fix before MAX_MP and, if
|
mgl@1371
|
5670 |
+ necessary, adjust the constraints on the other entries. */
|
mgl@1371
|
5671 |
+ mp = xmalloc (sizeof (*mp));
|
mgl@1371
|
5672 |
+ mp->fix_size = fix->fix_size;
|
mgl@1371
|
5673 |
+ mp->mode = fix->mode;
|
mgl@1371
|
5674 |
+ mp->value = fix->value;
|
mgl@1371
|
5675 |
+ mp->refcount = 1;
|
mgl@1371
|
5676 |
+ /* Not yet required for a backwards ref. */
|
mgl@1371
|
5677 |
+ mp->min_address = -65536;
|
mgl@1371
|
5678 |
+
|
mgl@1371
|
5679 |
+ if (max_mp == NULL)
|
mgl@1371
|
5680 |
+ {
|
mgl@1371
|
5681 |
+ mp->max_address = max_address;
|
mgl@1371
|
5682 |
+ mp->next = NULL;
|
mgl@1371
|
5683 |
+ mp->prev = minipool_vector_tail;
|
mgl@1371
|
5684 |
+
|
mgl@1371
|
5685 |
+ if (mp->prev == NULL)
|
mgl@1371
|
5686 |
+ {
|
mgl@1371
|
5687 |
+ minipool_vector_head = mp;
|
mgl@1371
|
5688 |
+ minipool_vector_label = gen_label_rtx ();
|
mgl@1371
|
5689 |
+ }
|
mgl@1371
|
5690 |
+ else
|
mgl@1371
|
5691 |
+ mp->prev->next = mp;
|
mgl@1371
|
5692 |
+
|
mgl@1371
|
5693 |
+ minipool_vector_tail = mp;
|
mgl@1371
|
5694 |
+ }
|
mgl@1371
|
5695 |
+ else
|
mgl@1371
|
5696 |
+ {
|
mgl@1371
|
5697 |
+ if (max_address > max_mp->max_address - mp->fix_size)
|
mgl@1371
|
5698 |
+ mp->max_address = max_mp->max_address - mp->fix_size;
|
mgl@1371
|
5699 |
+ else
|
mgl@1371
|
5700 |
+ mp->max_address = max_address;
|
mgl@1371
|
5701 |
+
|
mgl@1371
|
5702 |
+ mp->next = max_mp;
|
mgl@1371
|
5703 |
+ mp->prev = max_mp->prev;
|
mgl@1371
|
5704 |
+ max_mp->prev = mp;
|
mgl@1371
|
5705 |
+ if (mp->prev != NULL)
|
mgl@1371
|
5706 |
+ mp->prev->next = mp;
|
mgl@1371
|
5707 |
+ else
|
mgl@1371
|
5708 |
+ minipool_vector_head = mp;
|
mgl@1371
|
5709 |
+ }
|
mgl@1371
|
5710 |
+
|
mgl@1371
|
5711 |
+ /* Save the new entry. */
|
mgl@1371
|
5712 |
+ max_mp = mp;
|
mgl@1371
|
5713 |
+
|
mgl@1371
|
5714 |
+ /* Scan over the preceding entries and adjust their addresses as required.
|
mgl@1371
|
5715 |
+ */
|
mgl@1371
|
5716 |
+ while (mp->prev != NULL
|
mgl@1371
|
5717 |
+ && mp->prev->max_address > mp->max_address - mp->prev->fix_size)
|
mgl@1371
|
5718 |
+ {
|
mgl@1371
|
5719 |
+ mp->prev->max_address = mp->max_address - mp->prev->fix_size;
|
mgl@1371
|
5720 |
+ mp = mp->prev;
|
mgl@1371
|
5721 |
+ }
|
mgl@1371
|
5722 |
+
|
mgl@1371
|
5723 |
+ return max_mp;
|
mgl@1371
|
5724 |
+}
|
mgl@1371
|
5725 |
+
|
mgl@1371
|
5726 |
+static Mnode *
|
mgl@1371
|
5727 |
+move_minipool_fix_backward_ref (Mnode * mp, Mnode * min_mp,
|
mgl@1371
|
5728 |
+ HOST_WIDE_INT min_address)
|
mgl@1371
|
5729 |
+{
|
mgl@1371
|
5730 |
+ HOST_WIDE_INT offset;
|
mgl@1371
|
5731 |
+
|
mgl@1371
|
5732 |
+ /* This should never be true, and the code below assumes these are
|
mgl@1371
|
5733 |
+ different. */
|
mgl@1371
|
5734 |
+ if (mp == min_mp)
|
mgl@1371
|
5735 |
+ abort ();
|
mgl@1371
|
5736 |
+
|
mgl@1371
|
5737 |
+ if (min_mp == NULL)
|
mgl@1371
|
5738 |
+ {
|
mgl@1371
|
5739 |
+ if (min_address > mp->min_address)
|
mgl@1371
|
5740 |
+ mp->min_address = min_address;
|
mgl@1371
|
5741 |
+ }
|
mgl@1371
|
5742 |
+ else
|
mgl@1371
|
5743 |
+ {
|
mgl@1371
|
5744 |
+ /* We will adjust this below if it is too loose. */
|
mgl@1371
|
5745 |
+ mp->min_address = min_address;
|
mgl@1371
|
5746 |
+
|
mgl@1371
|
5747 |
+ /* Unlink MP from its current position. Since min_mp is non-null,
|
mgl@1371
|
5748 |
+ mp->next must be non-null. */
|
mgl@1371
|
5749 |
+ mp->next->prev = mp->prev;
|
mgl@1371
|
5750 |
+ if (mp->prev != NULL)
|
mgl@1371
|
5751 |
+ mp->prev->next = mp->next;
|
mgl@1371
|
5752 |
+ else
|
mgl@1371
|
5753 |
+ minipool_vector_head = mp->next;
|
mgl@1371
|
5754 |
+
|
mgl@1371
|
5755 |
+ /* Reinsert it after MIN_MP. */
|
mgl@1371
|
5756 |
+ mp->prev = min_mp;
|
mgl@1371
|
5757 |
+ mp->next = min_mp->next;
|
mgl@1371
|
5758 |
+ min_mp->next = mp;
|
mgl@1371
|
5759 |
+ if (mp->next != NULL)
|
mgl@1371
|
5760 |
+ mp->next->prev = mp;
|
mgl@1371
|
5761 |
+ else
|
mgl@1371
|
5762 |
+ minipool_vector_tail = mp;
|
mgl@1371
|
5763 |
+ }
|
mgl@1371
|
5764 |
+
|
mgl@1371
|
5765 |
+ min_mp = mp;
|
mgl@1371
|
5766 |
+
|
mgl@1371
|
5767 |
+ offset = 0;
|
mgl@1371
|
5768 |
+ for (mp = minipool_vector_head; mp != NULL; mp = mp->next)
|
mgl@1371
|
5769 |
+ {
|
mgl@1371
|
5770 |
+ mp->offset = offset;
|
mgl@1371
|
5771 |
+ if (mp->refcount > 0)
|
mgl@1371
|
5772 |
+ offset += mp->fix_size;
|
mgl@1371
|
5773 |
+
|
mgl@1371
|
5774 |
+ if (mp->next && mp->next->min_address < mp->min_address + mp->fix_size)
|
mgl@1371
|
5775 |
+ mp->next->min_address = mp->min_address + mp->fix_size;
|
mgl@1371
|
5776 |
+ }
|
mgl@1371
|
5777 |
+
|
mgl@1371
|
5778 |
+ return min_mp;
|
mgl@1371
|
5779 |
+}
|
mgl@1371
|
5780 |
+
|
mgl@1371
|
5781 |
+/* Add a constant to the minipool for a backward reference. Returns the
|
mgl@1371
|
5782 |
+ node added or NULL if the constant will not fit in this pool.
|
mgl@1371
|
5783 |
+
|
mgl@1371
|
5784 |
+ Note that the code for insertion for a backwards reference can be
|
mgl@1371
|
5785 |
+ somewhat confusing because the calculated offsets for each fix do
|
mgl@1371
|
5786 |
+ not take into account the size of the pool (which is still under
|
mgl@1371
|
5787 |
+ construction. */
|
mgl@1371
|
5788 |
+static Mnode *
|
mgl@1371
|
5789 |
+add_minipool_backward_ref (Mfix * fix)
|
mgl@1371
|
5790 |
+{
|
mgl@1371
|
5791 |
+ /* If set, min_mp is the last pool_entry that has a lower constraint than
|
mgl@1371
|
5792 |
+ the one we are trying to add. */
|
mgl@1371
|
5793 |
+ Mnode *min_mp = NULL;
|
mgl@1371
|
5794 |
+ /* This can be negative, since it is only a constraint. */
|
mgl@1371
|
5795 |
+ HOST_WIDE_INT min_address = fix->address - fix->backwards;
|
mgl@1371
|
5796 |
+ Mnode *mp;
|
mgl@1371
|
5797 |
+
|
mgl@1371
|
5798 |
+ /* If we can't reach the current pool from this insn, or if we can't insert
|
mgl@1371
|
5799 |
+ this entry at the end of the pool without pushing other fixes out of
|
mgl@1371
|
5800 |
+ range, then we don't try. This ensures that we can't fail later on. */
|
mgl@1371
|
5801 |
+ if (min_address >= minipool_barrier->address
|
mgl@1371
|
5802 |
+ || (minipool_vector_tail->min_address + fix->fix_size
|
mgl@1371
|
5803 |
+ >= minipool_barrier->address))
|
mgl@1371
|
5804 |
+ return NULL;
|
mgl@1371
|
5805 |
+
|
mgl@1371
|
5806 |
+ /* Scan the pool to see if a constant with the same value has already been
|
mgl@1371
|
5807 |
+ added. While we are doing this, also note the location where we must
|
mgl@1371
|
5808 |
+ insert the constant if it doesn't already exist. */
|
mgl@1371
|
5809 |
+ for (mp = minipool_vector_tail; mp != NULL; mp = mp->prev)
|
mgl@1371
|
5810 |
+ {
|
mgl@1371
|
5811 |
+ if (GET_CODE (fix->value) == GET_CODE (mp->value)
|
mgl@1371
|
5812 |
+ && fix->mode == mp->mode
|
mgl@1371
|
5813 |
+ && (GET_CODE (fix->value) != CODE_LABEL
|
mgl@1371
|
5814 |
+ || (CODE_LABEL_NUMBER (fix->value)
|
mgl@1371
|
5815 |
+ == CODE_LABEL_NUMBER (mp->value)))
|
mgl@1371
|
5816 |
+ && rtx_equal_p (fix->value, mp->value)
|
mgl@1371
|
5817 |
+ /* Check that there is enough slack to move this entry to the end
|
mgl@1371
|
5818 |
+ of the table (this is conservative). */
|
mgl@1371
|
5819 |
+ && (mp->max_address
|
mgl@1371
|
5820 |
+ > (minipool_barrier->address
|
mgl@1371
|
5821 |
+ + minipool_vector_tail->offset
|
mgl@1371
|
5822 |
+ + minipool_vector_tail->fix_size)))
|
mgl@1371
|
5823 |
+ {
|
mgl@1371
|
5824 |
+ mp->refcount++;
|
mgl@1371
|
5825 |
+ return move_minipool_fix_backward_ref (mp, min_mp, min_address);
|
mgl@1371
|
5826 |
+ }
|
mgl@1371
|
5827 |
+
|
mgl@1371
|
5828 |
+ if (min_mp != NULL)
|
mgl@1371
|
5829 |
+ mp->min_address += fix->fix_size;
|
mgl@1371
|
5830 |
+ else
|
mgl@1371
|
5831 |
+ {
|
mgl@1371
|
5832 |
+ /* Note the insertion point if necessary. */
|
mgl@1371
|
5833 |
+ if (mp->min_address < min_address)
|
mgl@1371
|
5834 |
+ {
|
mgl@1371
|
5835 |
+ min_mp = mp;
|
mgl@1371
|
5836 |
+ }
|
mgl@1371
|
5837 |
+ else if (mp->max_address
|
mgl@1371
|
5838 |
+ < minipool_barrier->address + mp->offset + fix->fix_size)
|
mgl@1371
|
5839 |
+ {
|
mgl@1371
|
5840 |
+ /* Inserting before this entry would push the fix beyond its
|
mgl@1371
|
5841 |
+ maximum address (which can happen if we have re-located a
|
mgl@1371
|
5842 |
+ forwards fix); force the new fix to come after it. */
|
mgl@1371
|
5843 |
+ min_mp = mp;
|
mgl@1371
|
5844 |
+ min_address = mp->min_address + fix->fix_size;
|
mgl@1371
|
5845 |
+ }
|
mgl@1371
|
5846 |
+ }
|
mgl@1371
|
5847 |
+ }
|
mgl@1371
|
5848 |
+
|
mgl@1371
|
5849 |
+ /* We need to create a new entry. */
|
mgl@1371
|
5850 |
+ mp = xmalloc (sizeof (*mp));
|
mgl@1371
|
5851 |
+ mp->fix_size = fix->fix_size;
|
mgl@1371
|
5852 |
+ mp->mode = fix->mode;
|
mgl@1371
|
5853 |
+ mp->value = fix->value;
|
mgl@1371
|
5854 |
+ mp->refcount = 1;
|
mgl@1371
|
5855 |
+ mp->max_address = minipool_barrier->address + 65536;
|
mgl@1371
|
5856 |
+
|
mgl@1371
|
5857 |
+ mp->min_address = min_address;
|
mgl@1371
|
5858 |
+
|
mgl@1371
|
5859 |
+ if (min_mp == NULL)
|
mgl@1371
|
5860 |
+ {
|
mgl@1371
|
5861 |
+ mp->prev = NULL;
|
mgl@1371
|
5862 |
+ mp->next = minipool_vector_head;
|
mgl@1371
|
5863 |
+
|
mgl@1371
|
5864 |
+ if (mp->next == NULL)
|
mgl@1371
|
5865 |
+ {
|
mgl@1371
|
5866 |
+ minipool_vector_tail = mp;
|
mgl@1371
|
5867 |
+ minipool_vector_label = gen_label_rtx ();
|
mgl@1371
|
5868 |
+ }
|
mgl@1371
|
5869 |
+ else
|
mgl@1371
|
5870 |
+ mp->next->prev = mp;
|
mgl@1371
|
5871 |
+
|
mgl@1371
|
5872 |
+ minipool_vector_head = mp;
|
mgl@1371
|
5873 |
+ }
|
mgl@1371
|
5874 |
+ else
|
mgl@1371
|
5875 |
+ {
|
mgl@1371
|
5876 |
+ mp->next = min_mp->next;
|
mgl@1371
|
5877 |
+ mp->prev = min_mp;
|
mgl@1371
|
5878 |
+ min_mp->next = mp;
|
mgl@1371
|
5879 |
+
|
mgl@1371
|
5880 |
+ if (mp->next != NULL)
|
mgl@1371
|
5881 |
+ mp->next->prev = mp;
|
mgl@1371
|
5882 |
+ else
|
mgl@1371
|
5883 |
+ minipool_vector_tail = mp;
|
mgl@1371
|
5884 |
+ }
|
mgl@1371
|
5885 |
+
|
mgl@1371
|
5886 |
+ /* Save the new entry. */
|
mgl@1371
|
5887 |
+ min_mp = mp;
|
mgl@1371
|
5888 |
+
|
mgl@1371
|
5889 |
+ if (mp->prev)
|
mgl@1371
|
5890 |
+ mp = mp->prev;
|
mgl@1371
|
5891 |
+ else
|
mgl@1371
|
5892 |
+ mp->offset = 0;
|
mgl@1371
|
5893 |
+
|
mgl@1371
|
5894 |
+ /* Scan over the following entries and adjust their offsets. */
|
mgl@1371
|
5895 |
+ while (mp->next != NULL)
|
mgl@1371
|
5896 |
+ {
|
mgl@1371
|
5897 |
+ if (mp->next->min_address < mp->min_address + mp->fix_size)
|
mgl@1371
|
5898 |
+ mp->next->min_address = mp->min_address + mp->fix_size;
|
mgl@1371
|
5899 |
+
|
mgl@1371
|
5900 |
+ if (mp->refcount)
|
mgl@1371
|
5901 |
+ mp->next->offset = mp->offset + mp->fix_size;
|
mgl@1371
|
5902 |
+ else
|
mgl@1371
|
5903 |
+ mp->next->offset = mp->offset;
|
mgl@1371
|
5904 |
+
|
mgl@1371
|
5905 |
+ mp = mp->next;
|
mgl@1371
|
5906 |
+ }
|
mgl@1371
|
5907 |
+
|
mgl@1371
|
5908 |
+ return min_mp;
|
mgl@1371
|
5909 |
+}
|
mgl@1371
|
5910 |
+
|
mgl@1371
|
5911 |
+static void
|
mgl@1371
|
5912 |
+assign_minipool_offsets (Mfix * barrier)
|
mgl@1371
|
5913 |
+{
|
mgl@1371
|
5914 |
+ HOST_WIDE_INT offset = 0;
|
mgl@1371
|
5915 |
+ Mnode *mp;
|
mgl@1371
|
5916 |
+
|
mgl@1371
|
5917 |
+ minipool_barrier = barrier;
|
mgl@1371
|
5918 |
+
|
mgl@1371
|
5919 |
+ for (mp = minipool_vector_head; mp != NULL; mp = mp->next)
|
mgl@1371
|
5920 |
+ {
|
mgl@1371
|
5921 |
+ mp->offset = offset;
|
mgl@1371
|
5922 |
+
|
mgl@1371
|
5923 |
+ if (mp->refcount > 0)
|
mgl@1371
|
5924 |
+ offset += mp->fix_size;
|
mgl@1371
|
5925 |
+ }
|
mgl@1371
|
5926 |
+}
|
mgl@1371
|
5927 |
+
|
mgl@1371
|
5928 |
+/* Print a symbolic form of X to the debug file, F. */
|
mgl@1371
|
5929 |
+static void
|
mgl@1371
|
5930 |
+avr32_print_value (FILE * f, rtx x)
|
mgl@1371
|
5931 |
+{
|
mgl@1371
|
5932 |
+ switch (GET_CODE (x))
|
mgl@1371
|
5933 |
+ {
|
mgl@1371
|
5934 |
+ case CONST_INT:
|
mgl@1371
|
5935 |
+ fprintf (f, "0x%x", (int) INTVAL (x));
|
mgl@1371
|
5936 |
+ return;
|
mgl@1371
|
5937 |
+
|
mgl@1371
|
5938 |
+ case CONST_DOUBLE:
|
mgl@1371
|
5939 |
+ fprintf (f, "<0x%lx,0x%lx>", (long) XWINT (x, 2), (long) XWINT (x, 3));
|
mgl@1371
|
5940 |
+ return;
|
mgl@1371
|
5941 |
+
|
mgl@1371
|
5942 |
+ case CONST_VECTOR:
|
mgl@1371
|
5943 |
+ {
|
mgl@1371
|
5944 |
+ int i;
|
mgl@1371
|
5945 |
+
|
mgl@1371
|
5946 |
+ fprintf (f, "<");
|
mgl@1371
|
5947 |
+ for (i = 0; i < CONST_VECTOR_NUNITS (x); i++)
|
mgl@1371
|
5948 |
+ {
|
mgl@1371
|
5949 |
+ fprintf (f, "0x%x", (int) INTVAL (CONST_VECTOR_ELT (x, i)));
|
mgl@1371
|
5950 |
+ if (i < (CONST_VECTOR_NUNITS (x) - 1))
|
mgl@1371
|
5951 |
+ fputc (',', f);
|
mgl@1371
|
5952 |
+ }
|
mgl@1371
|
5953 |
+ fprintf (f, ">");
|
mgl@1371
|
5954 |
+ }
|
mgl@1371
|
5955 |
+ return;
|
mgl@1371
|
5956 |
+
|
mgl@1371
|
5957 |
+ case CONST_STRING:
|
mgl@1371
|
5958 |
+ fprintf (f, "\"%s\"", XSTR (x, 0));
|
mgl@1371
|
5959 |
+ return;
|
mgl@1371
|
5960 |
+
|
mgl@1371
|
5961 |
+ case SYMBOL_REF:
|
mgl@1371
|
5962 |
+ fprintf (f, "`%s'", XSTR (x, 0));
|
mgl@1371
|
5963 |
+ return;
|
mgl@1371
|
5964 |
+
|
mgl@1371
|
5965 |
+ case LABEL_REF:
|
mgl@1371
|
5966 |
+ fprintf (f, "L%d", INSN_UID (XEXP (x, 0)));
|
mgl@1371
|
5967 |
+ return;
|
mgl@1371
|
5968 |
+
|
mgl@1371
|
5969 |
+ case CONST:
|
mgl@1371
|
5970 |
+ avr32_print_value (f, XEXP (x, 0));
|
mgl@1371
|
5971 |
+ return;
|
mgl@1371
|
5972 |
+
|
mgl@1371
|
5973 |
+ case PLUS:
|
mgl@1371
|
5974 |
+ avr32_print_value (f, XEXP (x, 0));
|
mgl@1371
|
5975 |
+ fprintf (f, "+");
|
mgl@1371
|
5976 |
+ avr32_print_value (f, XEXP (x, 1));
|
mgl@1371
|
5977 |
+ return;
|
mgl@1371
|
5978 |
+
|
mgl@1371
|
5979 |
+ case PC:
|
mgl@1371
|
5980 |
+ fprintf (f, "pc");
|
mgl@1371
|
5981 |
+ return;
|
mgl@1371
|
5982 |
+
|
mgl@1371
|
5983 |
+ default:
|
mgl@1371
|
5984 |
+ fprintf (f, "????");
|
mgl@1371
|
5985 |
+ return;
|
mgl@1371
|
5986 |
+ }
|
mgl@1371
|
5987 |
+}
|
mgl@1371
|
5988 |
+
|
mgl@1371
|
5989 |
+int
|
mgl@1371
|
5990 |
+is_minipool_label (rtx label)
|
mgl@1371
|
5991 |
+{
|
mgl@1371
|
5992 |
+ minipool_labels *cur_mp_label = cfun->machine->minipool_label_head;
|
mgl@1371
|
5993 |
+
|
mgl@1371
|
5994 |
+ if (GET_CODE (label) != CODE_LABEL)
|
mgl@1371
|
5995 |
+ return FALSE;
|
mgl@1371
|
5996 |
+
|
mgl@1371
|
5997 |
+ while (cur_mp_label)
|
mgl@1371
|
5998 |
+ {
|
mgl@1371
|
5999 |
+ if (CODE_LABEL_NUMBER (label)
|
mgl@1371
|
6000 |
+ == CODE_LABEL_NUMBER (cur_mp_label->label))
|
mgl@1371
|
6001 |
+ return TRUE;
|
mgl@1371
|
6002 |
+ cur_mp_label = cur_mp_label->next;
|
mgl@1371
|
6003 |
+ }
|
mgl@1371
|
6004 |
+ return FALSE;
|
mgl@1371
|
6005 |
+}
|
mgl@1371
|
6006 |
+
|
mgl@1371
|
6007 |
+static void
|
mgl@1371
|
6008 |
+new_minipool_label (rtx label)
|
mgl@1371
|
6009 |
+{
|
mgl@1371
|
6010 |
+ if (!cfun->machine->minipool_label_head)
|
mgl@1371
|
6011 |
+ {
|
mgl@1371
|
6012 |
+ cfun->machine->minipool_label_head =
|
mgl@1371
|
6013 |
+ ggc_alloc (sizeof (minipool_labels));
|
mgl@1371
|
6014 |
+ cfun->machine->minipool_label_tail = cfun->machine->minipool_label_head;
|
mgl@1371
|
6015 |
+ cfun->machine->minipool_label_head->label = label;
|
mgl@1371
|
6016 |
+ cfun->machine->minipool_label_head->next = 0;
|
mgl@1371
|
6017 |
+ cfun->machine->minipool_label_head->prev = 0;
|
mgl@1371
|
6018 |
+ }
|
mgl@1371
|
6019 |
+ else
|
mgl@1371
|
6020 |
+ {
|
mgl@1371
|
6021 |
+ cfun->machine->minipool_label_tail->next =
|
mgl@1371
|
6022 |
+ ggc_alloc (sizeof (minipool_labels));
|
mgl@1371
|
6023 |
+ cfun->machine->minipool_label_tail->next->label = label;
|
mgl@1371
|
6024 |
+ cfun->machine->minipool_label_tail->next->next = 0;
|
mgl@1371
|
6025 |
+ cfun->machine->minipool_label_tail->next->prev =
|
mgl@1371
|
6026 |
+ cfun->machine->minipool_label_tail;
|
mgl@1371
|
6027 |
+ cfun->machine->minipool_label_tail =
|
mgl@1371
|
6028 |
+ cfun->machine->minipool_label_tail->next;
|
mgl@1371
|
6029 |
+ }
|
mgl@1371
|
6030 |
+}
|
mgl@1371
|
6031 |
+
|
mgl@1371
|
6032 |
+/* Output the literal table */
|
mgl@1371
|
6033 |
+static void
|
mgl@1371
|
6034 |
+dump_minipool (rtx scan)
|
mgl@1371
|
6035 |
+{
|
mgl@1371
|
6036 |
+ Mnode *mp;
|
mgl@1371
|
6037 |
+ Mnode *nmp;
|
mgl@1371
|
6038 |
+
|
mgl@1371
|
6039 |
+ if (dump_file)
|
mgl@1371
|
6040 |
+ fprintf (dump_file,
|
mgl@1371
|
6041 |
+ ";; Emitting minipool after insn %u; address %ld; align %d (bytes)\n",
|
mgl@1371
|
6042 |
+ INSN_UID (scan), (unsigned long) minipool_barrier->address, 4);
|
mgl@1371
|
6043 |
+
|
mgl@1371
|
6044 |
+ scan = emit_insn_after (gen_consttable_start (), scan);
|
mgl@1371
|
6045 |
+ scan = emit_insn_after (gen_align_4 (), scan);
|
mgl@1371
|
6046 |
+ scan = emit_label_after (minipool_vector_label, scan);
|
mgl@1371
|
6047 |
+ new_minipool_label (minipool_vector_label);
|
mgl@1371
|
6048 |
+
|
mgl@1371
|
6049 |
+ for (mp = minipool_vector_head; mp != NULL; mp = nmp)
|
mgl@1371
|
6050 |
+ {
|
mgl@1371
|
6051 |
+ if (mp->refcount > 0)
|
mgl@1371
|
6052 |
+ {
|
mgl@1371
|
6053 |
+ if (dump_file)
|
mgl@1371
|
6054 |
+ {
|
mgl@1371
|
6055 |
+ fprintf (dump_file,
|
mgl@1371
|
6056 |
+ ";; Offset %u, min %ld, max %ld ",
|
mgl@1371
|
6057 |
+ (unsigned) mp->offset, (unsigned long) mp->min_address,
|
mgl@1371
|
6058 |
+ (unsigned long) mp->max_address);
|
mgl@1371
|
6059 |
+ avr32_print_value (dump_file, mp->value);
|
mgl@1371
|
6060 |
+ fputc ('\n', dump_file);
|
mgl@1371
|
6061 |
+ }
|
mgl@1371
|
6062 |
+
|
mgl@1371
|
6063 |
+ switch (mp->fix_size)
|
mgl@1371
|
6064 |
+ {
|
mgl@1371
|
6065 |
+#ifdef HAVE_consttable_4
|
mgl@1371
|
6066 |
+ case 4:
|
mgl@1371
|
6067 |
+ scan = emit_insn_after (gen_consttable_4 (mp->value), scan);
|
mgl@1371
|
6068 |
+ break;
|
mgl@1371
|
6069 |
+
|
mgl@1371
|
6070 |
+#endif
|
mgl@1371
|
6071 |
+#ifdef HAVE_consttable_8
|
mgl@1371
|
6072 |
+ case 8:
|
mgl@1371
|
6073 |
+ scan = emit_insn_after (gen_consttable_8 (mp->value), scan);
|
mgl@1371
|
6074 |
+ break;
|
mgl@1371
|
6075 |
+
|
mgl@1371
|
6076 |
+#endif
|
mgl@1371
|
6077 |
+#ifdef HAVE_consttable_16
|
mgl@1371
|
6078 |
+ case 16:
|
mgl@1371
|
6079 |
+ scan = emit_insn_after (gen_consttable_16 (mp->value), scan);
|
mgl@1371
|
6080 |
+ break;
|
mgl@1371
|
6081 |
+
|
mgl@1371
|
6082 |
+#endif
|
mgl@1371
|
6083 |
+ case 0:
|
mgl@1371
|
6084 |
+ /* This can happen for force-minipool entries which just are
|
mgl@1371
|
6085 |
+ there to force the minipool to be generate. */
|
mgl@1371
|
6086 |
+ break;
|
mgl@1371
|
6087 |
+ default:
|
mgl@1371
|
6088 |
+ abort ();
|
mgl@1371
|
6089 |
+ break;
|
mgl@1371
|
6090 |
+ }
|
mgl@1371
|
6091 |
+ }
|
mgl@1371
|
6092 |
+
|
mgl@1371
|
6093 |
+ nmp = mp->next;
|
mgl@1371
|
6094 |
+ free (mp);
|
mgl@1371
|
6095 |
+ }
|
mgl@1371
|
6096 |
+
|
mgl@1371
|
6097 |
+ minipool_vector_head = minipool_vector_tail = NULL;
|
mgl@1371
|
6098 |
+ scan = emit_insn_after (gen_consttable_end (), scan);
|
mgl@1371
|
6099 |
+ scan = emit_barrier_after (scan);
|
mgl@1371
|
6100 |
+}
|
mgl@1371
|
6101 |
+
|
mgl@1371
|
6102 |
+/* Return the cost of forcibly inserting a barrier after INSN. */
|
mgl@1371
|
6103 |
+static int
|
mgl@1371
|
6104 |
+avr32_barrier_cost (rtx insn)
|
mgl@1371
|
6105 |
+{
|
mgl@1371
|
6106 |
+ /* Basing the location of the pool on the loop depth is preferable, but at
|
mgl@1371
|
6107 |
+ the moment, the basic block information seems to be corrupt by this
|
mgl@1371
|
6108 |
+ stage of the compilation. */
|
mgl@1371
|
6109 |
+ int base_cost = 50;
|
mgl@1371
|
6110 |
+ rtx next = next_nonnote_insn (insn);
|
mgl@1371
|
6111 |
+
|
mgl@1371
|
6112 |
+ if (next != NULL && GET_CODE (next) == CODE_LABEL)
|
mgl@1371
|
6113 |
+ base_cost -= 20;
|
mgl@1371
|
6114 |
+
|
mgl@1371
|
6115 |
+ switch (GET_CODE (insn))
|
mgl@1371
|
6116 |
+ {
|
mgl@1371
|
6117 |
+ case CODE_LABEL:
|
mgl@1371
|
6118 |
+ /* It will always be better to place the table before the label, rather
|
mgl@1371
|
6119 |
+ than after it. */
|
mgl@1371
|
6120 |
+ return 50;
|
mgl@1371
|
6121 |
+
|
mgl@1371
|
6122 |
+ case INSN:
|
mgl@1371
|
6123 |
+ case CALL_INSN:
|
mgl@1371
|
6124 |
+ return base_cost;
|
mgl@1371
|
6125 |
+
|
mgl@1371
|
6126 |
+ case JUMP_INSN:
|
mgl@1371
|
6127 |
+ return base_cost - 10;
|
mgl@1371
|
6128 |
+
|
mgl@1371
|
6129 |
+ default:
|
mgl@1371
|
6130 |
+ return base_cost + 10;
|
mgl@1371
|
6131 |
+ }
|
mgl@1371
|
6132 |
+}
|
mgl@1371
|
6133 |
+
|
mgl@1371
|
6134 |
+/* Find the best place in the insn stream in the range
|
mgl@1371
|
6135 |
+ (FIX->address,MAX_ADDRESS) to forcibly insert a minipool barrier.
|
mgl@1371
|
6136 |
+ Create the barrier by inserting a jump and add a new fix entry for
|
mgl@1371
|
6137 |
+ it. */
|
mgl@1371
|
6138 |
+static Mfix *
|
mgl@1371
|
6139 |
+create_fix_barrier (Mfix * fix, HOST_WIDE_INT max_address)
|
mgl@1371
|
6140 |
+{
|
mgl@1371
|
6141 |
+ HOST_WIDE_INT count = 0;
|
mgl@1371
|
6142 |
+ rtx barrier;
|
mgl@1371
|
6143 |
+ rtx from = fix->insn;
|
mgl@1371
|
6144 |
+ rtx selected = from;
|
mgl@1371
|
6145 |
+ int selected_cost;
|
mgl@1371
|
6146 |
+ HOST_WIDE_INT selected_address;
|
mgl@1371
|
6147 |
+ Mfix *new_fix;
|
mgl@1371
|
6148 |
+ HOST_WIDE_INT max_count = max_address - fix->address;
|
mgl@1371
|
6149 |
+ rtx label = gen_label_rtx ();
|
mgl@1371
|
6150 |
+
|
mgl@1371
|
6151 |
+ selected_cost = avr32_barrier_cost (from);
|
mgl@1371
|
6152 |
+ selected_address = fix->address;
|
mgl@1371
|
6153 |
+
|
mgl@1371
|
6154 |
+ while (from && count < max_count)
|
mgl@1371
|
6155 |
+ {
|
mgl@1371
|
6156 |
+ rtx tmp;
|
mgl@1371
|
6157 |
+ int new_cost;
|
mgl@1371
|
6158 |
+
|
mgl@1371
|
6159 |
+ /* This code shouldn't have been called if there was a natural barrier
|
mgl@1371
|
6160 |
+ within range. */
|
mgl@1371
|
6161 |
+ if (GET_CODE (from) == BARRIER)
|
mgl@1371
|
6162 |
+ abort ();
|
mgl@1371
|
6163 |
+
|
mgl@1371
|
6164 |
+ /* Count the length of this insn. */
|
mgl@1371
|
6165 |
+ count += get_attr_length (from);
|
mgl@1371
|
6166 |
+
|
mgl@1371
|
6167 |
+ /* If there is a jump table, add its length. */
|
mgl@1371
|
6168 |
+ tmp = is_jump_table (from);
|
mgl@1371
|
6169 |
+ if (tmp != NULL)
|
mgl@1371
|
6170 |
+ {
|
mgl@1371
|
6171 |
+ count += get_jump_table_size (tmp);
|
mgl@1371
|
6172 |
+
|
mgl@1371
|
6173 |
+ /* Jump tables aren't in a basic block, so base the cost on the
|
mgl@1371
|
6174 |
+ dispatch insn. If we select this location, we will still put
|
mgl@1371
|
6175 |
+ the pool after the table. */
|
mgl@1371
|
6176 |
+ new_cost = avr32_barrier_cost (from);
|
mgl@1371
|
6177 |
+
|
mgl@1371
|
6178 |
+ if (count < max_count && new_cost <= selected_cost)
|
mgl@1371
|
6179 |
+ {
|
mgl@1371
|
6180 |
+ selected = tmp;
|
mgl@1371
|
6181 |
+ selected_cost = new_cost;
|
mgl@1371
|
6182 |
+ selected_address = fix->address + count;
|
mgl@1371
|
6183 |
+ }
|
mgl@1371
|
6184 |
+
|
mgl@1371
|
6185 |
+ /* Continue after the dispatch table. */
|
mgl@1371
|
6186 |
+ from = NEXT_INSN (tmp);
|
mgl@1371
|
6187 |
+ continue;
|
mgl@1371
|
6188 |
+ }
|
mgl@1371
|
6189 |
+
|
mgl@1371
|
6190 |
+ new_cost = avr32_barrier_cost (from);
|
mgl@1371
|
6191 |
+
|
mgl@1371
|
6192 |
+ if (count < max_count && new_cost <= selected_cost)
|
mgl@1371
|
6193 |
+ {
|
mgl@1371
|
6194 |
+ selected = from;
|
mgl@1371
|
6195 |
+ selected_cost = new_cost;
|
mgl@1371
|
6196 |
+ selected_address = fix->address + count;
|
mgl@1371
|
6197 |
+ }
|
mgl@1371
|
6198 |
+
|
mgl@1371
|
6199 |
+ from = NEXT_INSN (from);
|
mgl@1371
|
6200 |
+ }
|
mgl@1371
|
6201 |
+
|
mgl@1371
|
6202 |
+ /* Create a new JUMP_INSN that branches around a barrier. */
|
mgl@1371
|
6203 |
+ from = emit_jump_insn_after (gen_jump (label), selected);
|
mgl@1371
|
6204 |
+ JUMP_LABEL (from) = label;
|
mgl@1371
|
6205 |
+ barrier = emit_barrier_after (from);
|
mgl@1371
|
6206 |
+ emit_label_after (label, barrier);
|
mgl@1371
|
6207 |
+
|
mgl@1371
|
6208 |
+ /* Create a minipool barrier entry for the new barrier. */
|
mgl@1371
|
6209 |
+ new_fix = (Mfix *) obstack_alloc (&minipool_obstack, sizeof (*new_fix));
|
mgl@1371
|
6210 |
+ new_fix->insn = barrier;
|
mgl@1371
|
6211 |
+ new_fix->address = selected_address;
|
mgl@1371
|
6212 |
+ new_fix->next = fix->next;
|
mgl@1371
|
6213 |
+ fix->next = new_fix;
|
mgl@1371
|
6214 |
+
|
mgl@1371
|
6215 |
+ return new_fix;
|
mgl@1371
|
6216 |
+}
|
mgl@1371
|
6217 |
+
|
mgl@1371
|
6218 |
+/* Record that there is a natural barrier in the insn stream at
|
mgl@1371
|
6219 |
+ ADDRESS. */
|
mgl@1371
|
6220 |
+static void
|
mgl@1371
|
6221 |
+push_minipool_barrier (rtx insn, HOST_WIDE_INT address)
|
mgl@1371
|
6222 |
+{
|
mgl@1371
|
6223 |
+ Mfix *fix = (Mfix *) obstack_alloc (&minipool_obstack, sizeof (*fix));
|
mgl@1371
|
6224 |
+
|
mgl@1371
|
6225 |
+ fix->insn = insn;
|
mgl@1371
|
6226 |
+ fix->address = address;
|
mgl@1371
|
6227 |
+
|
mgl@1371
|
6228 |
+ fix->next = NULL;
|
mgl@1371
|
6229 |
+ if (minipool_fix_head != NULL)
|
mgl@1371
|
6230 |
+ minipool_fix_tail->next = fix;
|
mgl@1371
|
6231 |
+ else
|
mgl@1371
|
6232 |
+ minipool_fix_head = fix;
|
mgl@1371
|
6233 |
+
|
mgl@1371
|
6234 |
+ minipool_fix_tail = fix;
|
mgl@1371
|
6235 |
+}
|
mgl@1371
|
6236 |
+
|
mgl@1371
|
6237 |
+/* Record INSN, which will need fixing up to load a value from the
|
mgl@1371
|
6238 |
+ minipool. ADDRESS is the offset of the insn since the start of the
|
mgl@1371
|
6239 |
+ function; LOC is a pointer to the part of the insn which requires
|
mgl@1371
|
6240 |
+ fixing; VALUE is the constant that must be loaded, which is of type
|
mgl@1371
|
6241 |
+ MODE. */
|
mgl@1371
|
6242 |
+static void
|
mgl@1371
|
6243 |
+push_minipool_fix (rtx insn, HOST_WIDE_INT address, rtx * loc,
|
mgl@1371
|
6244 |
+ enum machine_mode mode, rtx value)
|
mgl@1371
|
6245 |
+{
|
mgl@1371
|
6246 |
+ Mfix *fix = (Mfix *) obstack_alloc (&minipool_obstack, sizeof (*fix));
|
mgl@1371
|
6247 |
+ rtx body = PATTERN (insn);
|
mgl@1371
|
6248 |
+
|
mgl@1371
|
6249 |
+ fix->insn = insn;
|
mgl@1371
|
6250 |
+ fix->address = address;
|
mgl@1371
|
6251 |
+ fix->loc = loc;
|
mgl@1371
|
6252 |
+ fix->mode = mode;
|
mgl@1371
|
6253 |
+ fix->fix_size = MINIPOOL_FIX_SIZE (mode, value);
|
mgl@1371
|
6254 |
+ fix->value = value;
|
mgl@1371
|
6255 |
+
|
mgl@1371
|
6256 |
+ if (GET_CODE (body) == PARALLEL)
|
mgl@1371
|
6257 |
+ {
|
mgl@1371
|
6258 |
+ /* Mcall : Ks16 << 2 */
|
mgl@1371
|
6259 |
+ fix->forwards = ((1 << 15) - 1) << 2;
|
mgl@1371
|
6260 |
+ fix->backwards = (1 << 15) << 2;
|
mgl@1371
|
6261 |
+ }
|
mgl@1371
|
6262 |
+ else if (GET_CODE (body) == SET
|
mgl@1371
|
6263 |
+ && GET_MODE_SIZE (GET_MODE (SET_DEST (body))) == 4)
|
mgl@1371
|
6264 |
+ {
|
mgl@1371
|
6265 |
+ /* Word Load */
|
mgl@1371
|
6266 |
+ if (TARGET_HARD_FLOAT
|
mgl@1371
|
6267 |
+ && GET_MODE_CLASS (GET_MODE (SET_DEST (body))) == MODE_FLOAT)
|
mgl@1371
|
6268 |
+ {
|
mgl@1371
|
6269 |
+ /* Ldc0.w : Ku12 << 2 */
|
mgl@1371
|
6270 |
+ fix->forwards = ((1 << 12) - 1) << 2;
|
mgl@1371
|
6271 |
+ fix->backwards = 0;
|
mgl@1371
|
6272 |
+ }
|
mgl@1371
|
6273 |
+ else
|
mgl@1371
|
6274 |
+ {
|
mgl@1371
|
6275 |
+ if (optimize_size)
|
mgl@1371
|
6276 |
+ {
|
mgl@1371
|
6277 |
+ /* Lddpc : Ku7 << 2 */
|
mgl@1371
|
6278 |
+ fix->forwards = ((1 << 7) - 1) << 2;
|
mgl@1371
|
6279 |
+ fix->backwards = 0;
|
mgl@1371
|
6280 |
+ }
|
mgl@1371
|
6281 |
+ else
|
mgl@1371
|
6282 |
+ {
|
mgl@1371
|
6283 |
+ /* Ld.w : Ks16 */
|
mgl@1371
|
6284 |
+ fix->forwards = ((1 << 15) - 4);
|
mgl@1371
|
6285 |
+ fix->backwards = (1 << 15);
|
mgl@1371
|
6286 |
+ }
|
mgl@1371
|
6287 |
+ }
|
mgl@1371
|
6288 |
+ }
|
mgl@1371
|
6289 |
+ else if (GET_CODE (body) == SET
|
mgl@1371
|
6290 |
+ && GET_MODE_SIZE (GET_MODE (SET_DEST (body))) == 8)
|
mgl@1371
|
6291 |
+ {
|
mgl@1371
|
6292 |
+ /* Double word load */
|
mgl@1371
|
6293 |
+ if (TARGET_HARD_FLOAT
|
mgl@1371
|
6294 |
+ && GET_MODE_CLASS (GET_MODE (SET_DEST (body))) == MODE_FLOAT)
|
mgl@1371
|
6295 |
+ {
|
mgl@1371
|
6296 |
+ /* Ldc0.d : Ku12 << 2 */
|
mgl@1371
|
6297 |
+ fix->forwards = ((1 << 12) - 1) << 2;
|
mgl@1371
|
6298 |
+ fix->backwards = 0;
|
mgl@1371
|
6299 |
+ }
|
mgl@1371
|
6300 |
+ else
|
mgl@1371
|
6301 |
+ {
|
mgl@1371
|
6302 |
+ /* Ld.d : Ks16 */
|
mgl@1371
|
6303 |
+ fix->forwards = ((1 << 15) - 4);
|
mgl@1371
|
6304 |
+ fix->backwards = (1 << 15);
|
mgl@1371
|
6305 |
+ }
|
mgl@1371
|
6306 |
+ }
|
mgl@1371
|
6307 |
+ else if (GET_CODE (body) == UNSPEC_VOLATILE
|
mgl@1371
|
6308 |
+ && XINT (body, 1) == VUNSPEC_MVRC)
|
mgl@1371
|
6309 |
+ {
|
mgl@1371
|
6310 |
+ /* Coprocessor load */
|
mgl@1371
|
6311 |
+ /* Ldc : Ku8 << 2 */
|
mgl@1371
|
6312 |
+ fix->forwards = ((1 << 8) - 1) << 2;
|
mgl@1371
|
6313 |
+ fix->backwards = 0;
|
mgl@1371
|
6314 |
+ }
|
mgl@1371
|
6315 |
+ else
|
mgl@1371
|
6316 |
+ {
|
mgl@1371
|
6317 |
+ /* Assume worst case which is lddpc insn. */
|
mgl@1371
|
6318 |
+ fix->forwards = ((1 << 7) - 1) << 2;
|
mgl@1371
|
6319 |
+ fix->backwards = 0;
|
mgl@1371
|
6320 |
+ }
|
mgl@1371
|
6321 |
+
|
mgl@1371
|
6322 |
+ fix->minipool = NULL;
|
mgl@1371
|
6323 |
+
|
mgl@1371
|
6324 |
+ /* If an insn doesn't have a range defined for it, then it isn't expecting
|
mgl@1371
|
6325 |
+ to be reworked by this code. Better to abort now than to generate duff
|
mgl@1371
|
6326 |
+ assembly code. */
|
mgl@1371
|
6327 |
+ if (fix->forwards == 0 && fix->backwards == 0)
|
mgl@1371
|
6328 |
+ abort ();
|
mgl@1371
|
6329 |
+
|
mgl@1371
|
6330 |
+ if (dump_file)
|
mgl@1371
|
6331 |
+ {
|
mgl@1371
|
6332 |
+ fprintf (dump_file,
|
mgl@1371
|
6333 |
+ ";; %smode fixup for i%d; addr %lu, range (%ld,%ld): ",
|
mgl@1371
|
6334 |
+ GET_MODE_NAME (mode),
|
mgl@1371
|
6335 |
+ INSN_UID (insn), (unsigned long) address,
|
mgl@1371
|
6336 |
+ -1 * (long) fix->backwards, (long) fix->forwards);
|
mgl@1371
|
6337 |
+ avr32_print_value (dump_file, fix->value);
|
mgl@1371
|
6338 |
+ fprintf (dump_file, "\n");
|
mgl@1371
|
6339 |
+ }
|
mgl@1371
|
6340 |
+
|
mgl@1371
|
6341 |
+ /* Add it to the chain of fixes. */
|
mgl@1371
|
6342 |
+ fix->next = NULL;
|
mgl@1371
|
6343 |
+
|
mgl@1371
|
6344 |
+ if (minipool_fix_head != NULL)
|
mgl@1371
|
6345 |
+ minipool_fix_tail->next = fix;
|
mgl@1371
|
6346 |
+ else
|
mgl@1371
|
6347 |
+ minipool_fix_head = fix;
|
mgl@1371
|
6348 |
+
|
mgl@1371
|
6349 |
+ minipool_fix_tail = fix;
|
mgl@1371
|
6350 |
+}
|
mgl@1371
|
6351 |
+
|
mgl@1371
|
6352 |
+/* Scan INSN and note any of its operands that need fixing.
|
mgl@1371
|
6353 |
+ If DO_PUSHES is false we do not actually push any of the fixups
|
mgl@1371
|
6354 |
+ needed. The function returns TRUE is any fixups were needed/pushed.
|
mgl@1371
|
6355 |
+ This is used by avr32_memory_load_p() which needs to know about loads
|
mgl@1371
|
6356 |
+ of constants that will be converted into minipool loads. */
|
mgl@1371
|
6357 |
+static bool
|
mgl@1371
|
6358 |
+note_invalid_constants (rtx insn, HOST_WIDE_INT address, int do_pushes)
|
mgl@1371
|
6359 |
+{
|
mgl@1371
|
6360 |
+ bool result = false;
|
mgl@1371
|
6361 |
+ int opno;
|
mgl@1371
|
6362 |
+
|
mgl@1371
|
6363 |
+ extract_insn (insn);
|
mgl@1371
|
6364 |
+
|
mgl@1371
|
6365 |
+ if (!constrain_operands (1))
|
mgl@1371
|
6366 |
+ fatal_insn_not_found (insn);
|
mgl@1371
|
6367 |
+
|
mgl@1371
|
6368 |
+ if (recog_data.n_alternatives == 0)
|
mgl@1371
|
6369 |
+ return false;
|
mgl@1371
|
6370 |
+
|
mgl@1371
|
6371 |
+ /* Fill in recog_op_alt with information about the constraints of this
|
mgl@1371
|
6372 |
+ insn. */
|
mgl@1371
|
6373 |
+ preprocess_constraints ();
|
mgl@1371
|
6374 |
+
|
mgl@1371
|
6375 |
+ for (opno = 0; opno < recog_data.n_operands; opno++)
|
mgl@1371
|
6376 |
+ {
|
mgl@1371
|
6377 |
+ rtx op;
|
mgl@1371
|
6378 |
+
|
mgl@1371
|
6379 |
+ /* Things we need to fix can only occur in inputs. */
|
mgl@1371
|
6380 |
+ if (recog_data.operand_type[opno] != OP_IN)
|
mgl@1371
|
6381 |
+ continue;
|
mgl@1371
|
6382 |
+
|
mgl@1371
|
6383 |
+ op = recog_data.operand[opno];
|
mgl@1371
|
6384 |
+
|
mgl@1371
|
6385 |
+ if (avr32_const_pool_ref_operand (op, GET_MODE (op)))
|
mgl@1371
|
6386 |
+ {
|
mgl@1371
|
6387 |
+ if (do_pushes)
|
mgl@1371
|
6388 |
+ {
|
mgl@1371
|
6389 |
+ rtx cop = avoid_constant_pool_reference (op);
|
mgl@1371
|
6390 |
+
|
mgl@1371
|
6391 |
+ /* Casting the address of something to a mode narrower than a
|
mgl@1371
|
6392 |
+ word can cause avoid_constant_pool_reference() to return the
|
mgl@1371
|
6393 |
+ pool reference itself. That's no good to us here. Lets
|
mgl@1371
|
6394 |
+ just hope that we can use the constant pool value directly.
|
mgl@1371
|
6395 |
+ */
|
mgl@1371
|
6396 |
+ if (op == cop)
|
mgl@1371
|
6397 |
+ cop = get_pool_constant (XEXP (op, 0));
|
mgl@1371
|
6398 |
+
|
mgl@1371
|
6399 |
+ push_minipool_fix (insn, address,
|
mgl@1371
|
6400 |
+ recog_data.operand_loc[opno],
|
mgl@1371
|
6401 |
+ recog_data.operand_mode[opno], cop);
|
mgl@1371
|
6402 |
+ }
|
mgl@1371
|
6403 |
+
|
mgl@1371
|
6404 |
+ result = true;
|
mgl@1371
|
6405 |
+ }
|
mgl@1371
|
6406 |
+ else if (TARGET_HAS_ASM_ADDR_PSEUDOS
|
mgl@1371
|
6407 |
+ && avr32_address_operand (op, GET_MODE (op)))
|
mgl@1371
|
6408 |
+ {
|
mgl@1371
|
6409 |
+ /* Handle pseudo instructions using a direct address. These pseudo
|
mgl@1371
|
6410 |
+ instructions might need entries in the constant pool and we must
|
mgl@1371
|
6411 |
+ therefor create a constant pool for them, in case the
|
mgl@1371
|
6412 |
+ assembler/linker needs to insert entries. */
|
mgl@1371
|
6413 |
+ if (do_pushes)
|
mgl@1371
|
6414 |
+ {
|
mgl@1371
|
6415 |
+ /* Push a dummy constant pool entry so that the .cpool
|
mgl@1371
|
6416 |
+ directive should be inserted on the appropriate place in the
|
mgl@1371
|
6417 |
+ code even if there are no real constant pool entries. This
|
mgl@1371
|
6418 |
+ is used by the assembler and linker to know where to put
|
mgl@1371
|
6419 |
+ generated constant pool entries. */
|
mgl@1371
|
6420 |
+ push_minipool_fix (insn, address,
|
mgl@1371
|
6421 |
+ recog_data.operand_loc[opno],
|
mgl@1371
|
6422 |
+ recog_data.operand_mode[opno],
|
mgl@1371
|
6423 |
+ gen_rtx_UNSPEC (VOIDmode,
|
mgl@1371
|
6424 |
+ gen_rtvec (1, const0_rtx),
|
mgl@1371
|
6425 |
+ UNSPEC_FORCE_MINIPOOL));
|
mgl@1371
|
6426 |
+ result = true;
|
mgl@1371
|
6427 |
+ }
|
mgl@1371
|
6428 |
+ }
|
mgl@1371
|
6429 |
+ }
|
mgl@1371
|
6430 |
+ return result;
|
mgl@1371
|
6431 |
+}
|
mgl@1371
|
6432 |
+
|
mgl@1371
|
6433 |
+
|
mgl@1371
|
6434 |
+static int
|
mgl@1371
|
6435 |
+avr32_insn_is_cast (rtx insn)
|
mgl@1371
|
6436 |
+{
|
mgl@1371
|
6437 |
+
|
mgl@1371
|
6438 |
+ if (NONJUMP_INSN_P (insn)
|
mgl@1371
|
6439 |
+ && GET_CODE (PATTERN (insn)) == SET
|
mgl@1371
|
6440 |
+ && (GET_CODE (SET_SRC (PATTERN (insn))) == ZERO_EXTEND
|
mgl@1371
|
6441 |
+ || GET_CODE (SET_SRC (PATTERN (insn))) == SIGN_EXTEND)
|
mgl@1371
|
6442 |
+ && REG_P (XEXP (SET_SRC (PATTERN (insn)), 0))
|
mgl@1371
|
6443 |
+ && REG_P (SET_DEST (PATTERN (insn))))
|
mgl@1371
|
6444 |
+ return true;
|
mgl@1371
|
6445 |
+ return false;
|
mgl@1371
|
6446 |
+}
|
mgl@1371
|
6447 |
+
|
mgl@1371
|
6448 |
+/*
|
mgl@1371
|
6449 |
+ Replace all occurances of reg FROM with reg TO in X */
|
mgl@1371
|
6450 |
+
|
mgl@1371
|
6451 |
+rtx
|
mgl@1371
|
6452 |
+avr32_replace_reg (rtx x, rtx from, rtx to)
|
mgl@1371
|
6453 |
+{
|
mgl@1371
|
6454 |
+ int i, j;
|
mgl@1371
|
6455 |
+ const char *fmt;
|
mgl@1371
|
6456 |
+
|
mgl@1371
|
6457 |
+ gcc_assert ( REG_P (from) && REG_P (to) );
|
mgl@1371
|
6458 |
+
|
mgl@1371
|
6459 |
+ /* Allow this function to make replacements in EXPR_LISTs. */
|
mgl@1371
|
6460 |
+ if (x == 0)
|
mgl@1371
|
6461 |
+ return 0;
|
mgl@1371
|
6462 |
+
|
mgl@1371
|
6463 |
+ if (rtx_equal_p (x, from))
|
mgl@1371
|
6464 |
+ return to;
|
mgl@1371
|
6465 |
+
|
mgl@1371
|
6466 |
+ if (GET_CODE (x) == SUBREG)
|
mgl@1371
|
6467 |
+ {
|
mgl@1371
|
6468 |
+ rtx new = avr32_replace_reg (SUBREG_REG (x), from, to);
|
mgl@1371
|
6469 |
+
|
mgl@1371
|
6470 |
+ if (GET_CODE (new) == CONST_INT)
|
mgl@1371
|
6471 |
+ {
|
mgl@1371
|
6472 |
+ x = simplify_subreg (GET_MODE (x), new,
|
mgl@1371
|
6473 |
+ GET_MODE (SUBREG_REG (x)),
|
mgl@1371
|
6474 |
+ SUBREG_BYTE (x));
|
mgl@1371
|
6475 |
+ gcc_assert (x);
|
mgl@1371
|
6476 |
+ }
|
mgl@1371
|
6477 |
+ else
|
mgl@1371
|
6478 |
+ SUBREG_REG (x) = new;
|
mgl@1371
|
6479 |
+
|
mgl@1371
|
6480 |
+ return x;
|
mgl@1371
|
6481 |
+ }
|
mgl@1371
|
6482 |
+ else if (GET_CODE (x) == ZERO_EXTEND)
|
mgl@1371
|
6483 |
+ {
|
mgl@1371
|
6484 |
+ rtx new = avr32_replace_reg (XEXP (x, 0), from, to);
|
mgl@1371
|
6485 |
+
|
mgl@1371
|
6486 |
+ if (GET_CODE (new) == CONST_INT)
|
mgl@1371
|
6487 |
+ {
|
mgl@1371
|
6488 |
+ x = simplify_unary_operation (ZERO_EXTEND, GET_MODE (x),
|
mgl@1371
|
6489 |
+ new, GET_MODE (XEXP (x, 0)));
|
mgl@1371
|
6490 |
+ gcc_assert (x);
|
mgl@1371
|
6491 |
+ }
|
mgl@1371
|
6492 |
+ else
|
mgl@1371
|
6493 |
+ XEXP (x, 0) = new;
|
mgl@1371
|
6494 |
+
|
mgl@1371
|
6495 |
+ return x;
|
mgl@1371
|
6496 |
+ }
|
mgl@1371
|
6497 |
+
|
mgl@1371
|
6498 |
+ fmt = GET_RTX_FORMAT (GET_CODE (x));
|
mgl@1371
|
6499 |
+ for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
|
mgl@1371
|
6500 |
+ {
|
mgl@1371
|
6501 |
+ if (fmt[i] == 'e')
|
mgl@1371
|
6502 |
+ XEXP (x, i) = avr32_replace_reg (XEXP (x, i), from, to);
|
mgl@1371
|
6503 |
+ else if (fmt[i] == 'E')
|
mgl@1371
|
6504 |
+ for (j = XVECLEN (x, i) - 1; j >= 0; j--)
|
mgl@1371
|
6505 |
+ XVECEXP (x, i, j) = avr32_replace_reg (XVECEXP (x, i, j), from, to);
|
mgl@1371
|
6506 |
+ }
|
mgl@1371
|
6507 |
+
|
mgl@1371
|
6508 |
+ return x;
|
mgl@1371
|
6509 |
+}
|
mgl@1371
|
6510 |
+
|
mgl@1371
|
6511 |
+
|
mgl@1371
|
6512 |
+/* FIXME: The level of nesting in this function is way too deep. It needs to be
|
mgl@1371
|
6513 |
+ torn apart. */
|
mgl@1371
|
6514 |
+static void
|
mgl@1371
|
6515 |
+avr32_reorg_optimization (void)
|
mgl@1371
|
6516 |
+{
|
mgl@1371
|
6517 |
+ rtx first = get_first_nonnote_insn ();
|
mgl@1371
|
6518 |
+ rtx insn;
|
mgl@1371
|
6519 |
+
|
mgl@1371
|
6520 |
+ if (TARGET_MD_REORG_OPTIMIZATION && (optimize_size || (optimize > 0)))
|
mgl@1371
|
6521 |
+ {
|
mgl@1371
|
6522 |
+
|
mgl@1371
|
6523 |
+ /* Scan through all insns looking for cast operations. */
|
mgl@1371
|
6524 |
+ if (dump_file)
|
mgl@1371
|
6525 |
+ {
|
mgl@1371
|
6526 |
+ fprintf (dump_file, ";; Deleting redundant cast operations:\n");
|
mgl@1371
|
6527 |
+ }
|
mgl@1371
|
6528 |
+ for (insn = first; insn; insn = NEXT_INSN (insn))
|
mgl@1371
|
6529 |
+ {
|
mgl@1371
|
6530 |
+ rtx reg, src_reg, scan;
|
mgl@1371
|
6531 |
+ enum machine_mode mode;
|
mgl@1371
|
6532 |
+ int unused_cast;
|
mgl@1371
|
6533 |
+ rtx label_ref;
|
mgl@1371
|
6534 |
+
|
mgl@1371
|
6535 |
+ if (avr32_insn_is_cast (insn)
|
mgl@1371
|
6536 |
+ && (GET_MODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == QImode
|
mgl@1371
|
6537 |
+ || GET_MODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == HImode))
|
mgl@1371
|
6538 |
+ {
|
mgl@1371
|
6539 |
+ mode = GET_MODE (XEXP (SET_SRC (PATTERN (insn)), 0));
|
mgl@1371
|
6540 |
+ reg = SET_DEST (PATTERN (insn));
|
mgl@1371
|
6541 |
+ src_reg = XEXP (SET_SRC (PATTERN (insn)), 0);
|
mgl@1371
|
6542 |
+ }
|
mgl@1371
|
6543 |
+ else
|
mgl@1371
|
6544 |
+ {
|
mgl@1371
|
6545 |
+ continue;
|
mgl@1371
|
6546 |
+ }
|
mgl@1371
|
6547 |
+
|
mgl@1371
|
6548 |
+ unused_cast = false;
|
mgl@1371
|
6549 |
+ label_ref = NULL_RTX;
|
mgl@1371
|
6550 |
+ for (scan = NEXT_INSN (insn); scan; scan = NEXT_INSN (scan))
|
mgl@1371
|
6551 |
+ {
|
mgl@1371
|
6552 |
+ /* Check if we have reached the destination of a simple
|
mgl@1371
|
6553 |
+ conditional jump which we have already scanned past. If so,
|
mgl@1371
|
6554 |
+ we can safely continue scanning. */
|
mgl@1371
|
6555 |
+ if (LABEL_P (scan) && label_ref != NULL_RTX)
|
mgl@1371
|
6556 |
+ {
|
mgl@1371
|
6557 |
+ if (CODE_LABEL_NUMBER (scan) ==
|
mgl@1371
|
6558 |
+ CODE_LABEL_NUMBER (XEXP (label_ref, 0)))
|
mgl@1371
|
6559 |
+ label_ref = NULL_RTX;
|
mgl@1371
|
6560 |
+ else
|
mgl@1371
|
6561 |
+ break;
|
mgl@1371
|
6562 |
+ }
|
mgl@1371
|
6563 |
+
|
mgl@1371
|
6564 |
+ if (!INSN_P (scan))
|
mgl@1371
|
6565 |
+ continue;
|
mgl@1371
|
6566 |
+
|
mgl@1371
|
6567 |
+ /* For conditional jumps we can manage to keep on scanning if
|
mgl@1371
|
6568 |
+ we meet the destination label later on before any new jump
|
mgl@1371
|
6569 |
+ insns occure. */
|
mgl@1371
|
6570 |
+ if (GET_CODE (scan) == JUMP_INSN)
|
mgl@1371
|
6571 |
+ {
|
mgl@1371
|
6572 |
+ if (any_condjump_p (scan) && label_ref == NULL_RTX)
|
mgl@1371
|
6573 |
+ label_ref = condjump_label (scan);
|
mgl@1371
|
6574 |
+ else
|
mgl@1371
|
6575 |
+ break;
|
mgl@1371
|
6576 |
+ }
|
mgl@1371
|
6577 |
+
|
mgl@1371
|
6578 |
+ /* Check if we have a call and the register is used as an argument. */
|
mgl@1371
|
6579 |
+ if (CALL_P (scan)
|
mgl@1371
|
6580 |
+ && find_reg_fusage (scan, USE, reg) )
|
mgl@1371
|
6581 |
+ break;
|
mgl@1371
|
6582 |
+
|
mgl@1371
|
6583 |
+ if (!reg_mentioned_p (reg, PATTERN (scan)))
|
mgl@1371
|
6584 |
+ continue;
|
mgl@1371
|
6585 |
+
|
mgl@1371
|
6586 |
+ /* Check if casted register is used in this insn */
|
mgl@1371
|
6587 |
+ if ((regno_use_in (REGNO (reg), PATTERN (scan)) != NULL_RTX)
|
mgl@1371
|
6588 |
+ && (GET_MODE (regno_use_in (REGNO (reg), PATTERN (scan))) ==
|
mgl@1371
|
6589 |
+ GET_MODE (reg)))
|
mgl@1371
|
6590 |
+ {
|
mgl@1371
|
6591 |
+ /* If not used in the source to the set or in a memory
|
mgl@1371
|
6592 |
+ expression in the destiantion then the register is used
|
mgl@1371
|
6593 |
+ as a destination and is really dead. */
|
mgl@1371
|
6594 |
+ if (single_set (scan)
|
mgl@1371
|
6595 |
+ && GET_CODE (PATTERN (scan)) == SET
|
mgl@1371
|
6596 |
+ && REG_P (SET_DEST (PATTERN (scan)))
|
mgl@1371
|
6597 |
+ && !regno_use_in (REGNO (reg), SET_SRC (PATTERN (scan)))
|
mgl@1371
|
6598 |
+ && label_ref == NULL_RTX)
|
mgl@1371
|
6599 |
+ {
|
mgl@1371
|
6600 |
+ unused_cast = true;
|
mgl@1371
|
6601 |
+ }
|
mgl@1371
|
6602 |
+ break;
|
mgl@1371
|
6603 |
+ }
|
mgl@1371
|
6604 |
+
|
mgl@1371
|
6605 |
+ /* Check if register is dead or set in this insn */
|
mgl@1371
|
6606 |
+ if (dead_or_set_p (scan, reg))
|
mgl@1371
|
6607 |
+ {
|
mgl@1371
|
6608 |
+ unused_cast = true;
|
mgl@1371
|
6609 |
+ break;
|
mgl@1371
|
6610 |
+ }
|
mgl@1371
|
6611 |
+ }
|
mgl@1371
|
6612 |
+
|
mgl@1371
|
6613 |
+ /* Check if we have unresolved conditional jumps */
|
mgl@1371
|
6614 |
+ if (label_ref != NULL_RTX)
|
mgl@1371
|
6615 |
+ continue;
|
mgl@1371
|
6616 |
+
|
mgl@1371
|
6617 |
+ if (unused_cast)
|
mgl@1371
|
6618 |
+ {
|
mgl@1371
|
6619 |
+ if (REGNO (reg) == REGNO (XEXP (SET_SRC (PATTERN (insn)), 0)))
|
mgl@1371
|
6620 |
+ {
|
mgl@1371
|
6621 |
+ /* One operand cast, safe to delete */
|
mgl@1371
|
6622 |
+ if (dump_file)
|
mgl@1371
|
6623 |
+ {
|
mgl@1371
|
6624 |
+ fprintf (dump_file,
|
mgl@1371
|
6625 |
+ ";; INSN %i removed, casted register %i value not used.\n",
|
mgl@1371
|
6626 |
+ INSN_UID (insn), REGNO (reg));
|
mgl@1371
|
6627 |
+ }
|
mgl@1371
|
6628 |
+ SET_INSN_DELETED (insn);
|
mgl@1371
|
6629 |
+ /* Force the instruction to be recognized again */
|
mgl@1371
|
6630 |
+ INSN_CODE (insn) = -1;
|
mgl@1371
|
6631 |
+ }
|
mgl@1371
|
6632 |
+ else
|
mgl@1371
|
6633 |
+ {
|
mgl@1371
|
6634 |
+ /* Two operand cast, which really could be substituted with
|
mgl@1371
|
6635 |
+ a move, if the source register is dead after the cast
|
mgl@1371
|
6636 |
+ insn and then the insn which sets the source register
|
mgl@1371
|
6637 |
+ could instead directly set the destination register for
|
mgl@1371
|
6638 |
+ the cast. As long as there are no insns in between which
|
mgl@1371
|
6639 |
+ uses the register. */
|
mgl@1371
|
6640 |
+ rtx link = NULL_RTX;
|
mgl@1371
|
6641 |
+ rtx set;
|
mgl@1371
|
6642 |
+ rtx src_reg = XEXP (SET_SRC (PATTERN (insn)), 0);
|
mgl@1371
|
6643 |
+ unused_cast = false;
|
mgl@1371
|
6644 |
+
|
mgl@1371
|
6645 |
+ if (!find_reg_note (insn, REG_DEAD, src_reg))
|
mgl@1371
|
6646 |
+ continue;
|
mgl@1371
|
6647 |
+
|
mgl@1371
|
6648 |
+ /* Search for the insn which sets the source register */
|
mgl@1371
|
6649 |
+ for (link = LOG_LINKS (insn); link; link = XEXP (link, 1))
|
mgl@1371
|
6650 |
+ {
|
mgl@1371
|
6651 |
+ if (REG_NOTE_KIND (link) != 0)
|
mgl@1371
|
6652 |
+ continue;
|
mgl@1371
|
6653 |
+ set = single_set (XEXP (link, 0));
|
mgl@1371
|
6654 |
+ if (set && rtx_equal_p (src_reg, SET_DEST (set)))
|
mgl@1371
|
6655 |
+ {
|
mgl@1371
|
6656 |
+ link = XEXP (link, 0);
|
mgl@1371
|
6657 |
+ break;
|
mgl@1371
|
6658 |
+ }
|
mgl@1371
|
6659 |
+ }
|
mgl@1371
|
6660 |
+
|
mgl@1371
|
6661 |
+ /* Found no link or link is a call insn where we can not
|
mgl@1371
|
6662 |
+ change the destination register */
|
mgl@1371
|
6663 |
+ if (link == NULL_RTX || CALL_P (link))
|
mgl@1371
|
6664 |
+ continue;
|
mgl@1371
|
6665 |
+
|
mgl@1371
|
6666 |
+ /* Scan through all insn between link and insn */
|
mgl@1371
|
6667 |
+ for (scan = NEXT_INSN (link); scan; scan = NEXT_INSN (scan))
|
mgl@1371
|
6668 |
+ {
|
mgl@1371
|
6669 |
+ /* Don't try to trace forward past a CODE_LABEL if we
|
mgl@1371
|
6670 |
+ haven't seen INSN yet. Ordinarily, we will only
|
mgl@1371
|
6671 |
+ find the setting insn in LOG_LINKS if it is in the
|
mgl@1371
|
6672 |
+ same basic block. However, cross-jumping can insert
|
mgl@1371
|
6673 |
+ code labels in between the load and the call, and
|
mgl@1371
|
6674 |
+ can result in situations where a single call insn
|
mgl@1371
|
6675 |
+ may have two targets depending on where we came
|
mgl@1371
|
6676 |
+ from. */
|
mgl@1371
|
6677 |
+
|
mgl@1371
|
6678 |
+ if (GET_CODE (scan) == CODE_LABEL)
|
mgl@1371
|
6679 |
+ break;
|
mgl@1371
|
6680 |
+
|
mgl@1371
|
6681 |
+ if (!INSN_P (scan))
|
mgl@1371
|
6682 |
+ continue;
|
mgl@1371
|
6683 |
+
|
mgl@1371
|
6684 |
+ /* Don't try to trace forward past a JUMP. To optimize
|
mgl@1371
|
6685 |
+ safely, we would have to check that all the
|
mgl@1371
|
6686 |
+ instructions at the jump destination did not use REG.
|
mgl@1371
|
6687 |
+ */
|
mgl@1371
|
6688 |
+
|
mgl@1371
|
6689 |
+ if (GET_CODE (scan) == JUMP_INSN)
|
mgl@1371
|
6690 |
+ {
|
mgl@1371
|
6691 |
+ break;
|
mgl@1371
|
6692 |
+ }
|
mgl@1371
|
6693 |
+
|
mgl@1371
|
6694 |
+ if (!reg_mentioned_p (src_reg, PATTERN (scan)))
|
mgl@1371
|
6695 |
+ continue;
|
mgl@1371
|
6696 |
+
|
mgl@1371
|
6697 |
+ /* We have reached the cast insn */
|
mgl@1371
|
6698 |
+ if (scan == insn)
|
mgl@1371
|
6699 |
+ {
|
mgl@1371
|
6700 |
+ /* We can remove cast and replace the destination
|
mgl@1371
|
6701 |
+ register of the link insn with the destination
|
mgl@1371
|
6702 |
+ of the cast */
|
mgl@1371
|
6703 |
+ if (dump_file)
|
mgl@1371
|
6704 |
+ {
|
mgl@1371
|
6705 |
+ fprintf (dump_file,
|
mgl@1371
|
6706 |
+ ";; INSN %i removed, casted value unused. "
|
mgl@1371
|
6707 |
+ "Destination of removed cast operation: register %i, folded into INSN %i.\n",
|
mgl@1371
|
6708 |
+ INSN_UID (insn), REGNO (reg),
|
mgl@1371
|
6709 |
+ INSN_UID (link));
|
mgl@1371
|
6710 |
+ }
|
mgl@1371
|
6711 |
+ /* Update link insn */
|
mgl@1371
|
6712 |
+ SET_DEST (PATTERN (link)) =
|
mgl@1371
|
6713 |
+ gen_rtx_REG (mode, REGNO (reg));
|
mgl@1371
|
6714 |
+ /* Force the instruction to be recognized again */
|
mgl@1371
|
6715 |
+ INSN_CODE (link) = -1;
|
mgl@1371
|
6716 |
+
|
mgl@1371
|
6717 |
+ /* Delete insn */
|
mgl@1371
|
6718 |
+ SET_INSN_DELETED (insn);
|
mgl@1371
|
6719 |
+ /* Force the instruction to be recognized again */
|
mgl@1371
|
6720 |
+ INSN_CODE (insn) = -1;
|
mgl@1371
|
6721 |
+ break;
|
mgl@1371
|
6722 |
+ }
|
mgl@1371
|
6723 |
+ }
|
mgl@1371
|
6724 |
+ }
|
mgl@1371
|
6725 |
+ }
|
mgl@1371
|
6726 |
+ }
|
mgl@1371
|
6727 |
+ }
|
mgl@1371
|
6728 |
+
|
mgl@1371
|
6729 |
+ if (TARGET_MD_REORG_OPTIMIZATION && (optimize_size || (optimize > 0)))
|
mgl@1371
|
6730 |
+ {
|
mgl@1371
|
6731 |
+
|
mgl@1371
|
6732 |
+ /* Scan through all insns looking for shifted add operations */
|
mgl@1371
|
6733 |
+ if (dump_file)
|
mgl@1371
|
6734 |
+ {
|
mgl@1371
|
6735 |
+ fprintf (dump_file,
|
mgl@1371
|
6736 |
+ ";; Deleting redundant shifted add operations:\n");
|
mgl@1371
|
6737 |
+ }
|
mgl@1371
|
6738 |
+ for (insn = first; insn; insn = NEXT_INSN (insn))
|
mgl@1371
|
6739 |
+ {
|
mgl@1371
|
6740 |
+ rtx reg, mem_expr, scan, op0, op1;
|
mgl@1371
|
6741 |
+ int add_only_used_as_pointer;
|
mgl@1371
|
6742 |
+
|
mgl@1371
|
6743 |
+ if (INSN_P (insn)
|
mgl@1371
|
6744 |
+ && GET_CODE (PATTERN (insn)) == SET
|
mgl@1371
|
6745 |
+ && GET_CODE (SET_SRC (PATTERN (insn))) == PLUS
|
mgl@1371
|
6746 |
+ && (GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == MULT
|
mgl@1371
|
6747 |
+ || GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == ASHIFT)
|
mgl@1371
|
6748 |
+ && GET_CODE (XEXP (XEXP (SET_SRC (PATTERN (insn)), 0), 1)) ==
|
mgl@1371
|
6749 |
+ CONST_INT && REG_P (SET_DEST (PATTERN (insn)))
|
mgl@1371
|
6750 |
+ && REG_P (XEXP (SET_SRC (PATTERN (insn)), 1))
|
mgl@1371
|
6751 |
+ && REG_P (XEXP (XEXP (SET_SRC (PATTERN (insn)), 0), 0)))
|
mgl@1371
|
6752 |
+ {
|
mgl@1371
|
6753 |
+ reg = SET_DEST (PATTERN (insn));
|
mgl@1371
|
6754 |
+ mem_expr = SET_SRC (PATTERN (insn));
|
mgl@1371
|
6755 |
+ op0 = XEXP (XEXP (mem_expr, 0), 0);
|
mgl@1371
|
6756 |
+ op1 = XEXP (mem_expr, 1);
|
mgl@1371
|
6757 |
+ }
|
mgl@1371
|
6758 |
+ else
|
mgl@1371
|
6759 |
+ {
|
mgl@1371
|
6760 |
+ continue;
|
mgl@1371
|
6761 |
+ }
|
mgl@1371
|
6762 |
+
|
mgl@1371
|
6763 |
+ /* Scan forward the check if the result of the shifted add
|
mgl@1371
|
6764 |
+ operation is only used as an address in memory operations and
|
mgl@1371
|
6765 |
+ that the operands to the shifted add are not clobbered. */
|
mgl@1371
|
6766 |
+ add_only_used_as_pointer = false;
|
mgl@1371
|
6767 |
+ for (scan = NEXT_INSN (insn); scan; scan = NEXT_INSN (scan))
|
mgl@1371
|
6768 |
+ {
|
mgl@1371
|
6769 |
+ if (!INSN_P (scan))
|
mgl@1371
|
6770 |
+ continue;
|
mgl@1371
|
6771 |
+
|
mgl@1371
|
6772 |
+ /* Don't try to trace forward past a JUMP or CALL. To optimize
|
mgl@1371
|
6773 |
+ safely, we would have to check that all the instructions at
|
mgl@1371
|
6774 |
+ the jump destination did not use REG. */
|
mgl@1371
|
6775 |
+
|
mgl@1371
|
6776 |
+ if (GET_CODE (scan) == JUMP_INSN)
|
mgl@1371
|
6777 |
+ {
|
mgl@1371
|
6778 |
+ break;
|
mgl@1371
|
6779 |
+ }
|
mgl@1371
|
6780 |
+
|
mgl@1371
|
6781 |
+ /* If used in a call insn then we cannot optimize it away */
|
mgl@1371
|
6782 |
+ if (CALL_P (scan) && find_regno_fusage (scan, USE, REGNO (reg)))
|
mgl@1371
|
6783 |
+ break;
|
mgl@1371
|
6784 |
+
|
mgl@1371
|
6785 |
+ /* If any of the operands of the shifted add are clobbered we
|
mgl@1371
|
6786 |
+ cannot optimize the shifted adda away */
|
mgl@1371
|
6787 |
+ if ((reg_set_p (op0, scan) && (REGNO (op0) != REGNO (reg)))
|
mgl@1371
|
6788 |
+ || (reg_set_p (op1, scan) && (REGNO (op1) != REGNO (reg))))
|
mgl@1371
|
6789 |
+ break;
|
mgl@1371
|
6790 |
+
|
mgl@1371
|
6791 |
+ if (!reg_mentioned_p (reg, PATTERN (scan)))
|
mgl@1371
|
6792 |
+ continue;
|
mgl@1371
|
6793 |
+
|
mgl@1371
|
6794 |
+ /* If used any other place than as a pointer or as the
|
mgl@1371
|
6795 |
+ destination register we failed */
|
mgl@1371
|
6796 |
+ if (!(single_set (scan)
|
mgl@1371
|
6797 |
+ && GET_CODE (PATTERN (scan)) == SET
|
mgl@1371
|
6798 |
+ && ((MEM_P (SET_DEST (PATTERN (scan)))
|
mgl@1371
|
6799 |
+ && REG_P (XEXP (SET_DEST (PATTERN (scan)), 0))
|
mgl@1371
|
6800 |
+ && REGNO (XEXP (SET_DEST (PATTERN (scan)), 0)) == REGNO (reg))
|
mgl@1371
|
6801 |
+ || (MEM_P (SET_SRC (PATTERN (scan)))
|
mgl@1371
|
6802 |
+ && REG_P (XEXP (SET_SRC (PATTERN (scan)), 0))
|
mgl@1371
|
6803 |
+ && REGNO (XEXP
|
mgl@1371
|
6804 |
+ (SET_SRC (PATTERN (scan)), 0)) == REGNO (reg))))
|
mgl@1371
|
6805 |
+ && !(GET_CODE (PATTERN (scan)) == SET
|
mgl@1371
|
6806 |
+ && REG_P (SET_DEST (PATTERN (scan)))
|
mgl@1371
|
6807 |
+ && !regno_use_in (REGNO (reg),
|
mgl@1371
|
6808 |
+ SET_SRC (PATTERN (scan)))))
|
mgl@1371
|
6809 |
+ break;
|
mgl@1371
|
6810 |
+
|
mgl@1371
|
6811 |
+ /* We cannot replace the pointer in TImode insns
|
mgl@1371
|
6812 |
+ as these has a differene addressing mode than the other
|
mgl@1371
|
6813 |
+ memory insns. */
|
mgl@1371
|
6814 |
+ if ( GET_MODE (SET_DEST (PATTERN (scan))) == TImode )
|
mgl@1371
|
6815 |
+ break;
|
mgl@1371
|
6816 |
+
|
mgl@1371
|
6817 |
+ /* Check if register is dead or set in this insn */
|
mgl@1371
|
6818 |
+ if (dead_or_set_p (scan, reg))
|
mgl@1371
|
6819 |
+ {
|
mgl@1371
|
6820 |
+ add_only_used_as_pointer = true;
|
mgl@1371
|
6821 |
+ break;
|
mgl@1371
|
6822 |
+ }
|
mgl@1371
|
6823 |
+ }
|
mgl@1371
|
6824 |
+
|
mgl@1371
|
6825 |
+ if (add_only_used_as_pointer)
|
mgl@1371
|
6826 |
+ {
|
mgl@1371
|
6827 |
+ /* Lets delete the add insn and replace all memory references
|
mgl@1371
|
6828 |
+ which uses the pointer with the full expression. */
|
mgl@1371
|
6829 |
+ if (dump_file)
|
mgl@1371
|
6830 |
+ {
|
mgl@1371
|
6831 |
+ fprintf (dump_file,
|
mgl@1371
|
6832 |
+ ";; Deleting INSN %i since address expression can be folded into all "
|
mgl@1371
|
6833 |
+ "memory references using this expression\n",
|
mgl@1371
|
6834 |
+ INSN_UID (insn));
|
mgl@1371
|
6835 |
+ }
|
mgl@1371
|
6836 |
+ SET_INSN_DELETED (insn);
|
mgl@1371
|
6837 |
+ /* Force the instruction to be recognized again */
|
mgl@1371
|
6838 |
+ INSN_CODE (insn) = -1;
|
mgl@1371
|
6839 |
+
|
mgl@1371
|
6840 |
+ for (scan = NEXT_INSN (insn); scan; scan = NEXT_INSN (scan))
|
mgl@1371
|
6841 |
+ {
|
mgl@1371
|
6842 |
+ if (!INSN_P (scan))
|
mgl@1371
|
6843 |
+ continue;
|
mgl@1371
|
6844 |
+
|
mgl@1371
|
6845 |
+ if (!reg_mentioned_p (reg, PATTERN (scan)))
|
mgl@1371
|
6846 |
+ continue;
|
mgl@1371
|
6847 |
+
|
mgl@1371
|
6848 |
+ /* If used any other place than as a pointer or as the
|
mgl@1371
|
6849 |
+ destination register we failed */
|
mgl@1371
|
6850 |
+ if ((single_set (scan)
|
mgl@1371
|
6851 |
+ && GET_CODE (PATTERN (scan)) == SET
|
mgl@1371
|
6852 |
+ && ((MEM_P (SET_DEST (PATTERN (scan)))
|
mgl@1371
|
6853 |
+ && REG_P (XEXP (SET_DEST (PATTERN (scan)), 0))
|
mgl@1371
|
6854 |
+ && REGNO (XEXP (SET_DEST (PATTERN (scan)), 0)) ==
|
mgl@1371
|
6855 |
+ REGNO (reg)) || (MEM_P (SET_SRC (PATTERN (scan)))
|
mgl@1371
|
6856 |
+ &&
|
mgl@1371
|
6857 |
+ REG_P (XEXP
|
mgl@1371
|
6858 |
+ (SET_SRC (PATTERN (scan)),
|
mgl@1371
|
6859 |
+ 0))
|
mgl@1371
|
6860 |
+ &&
|
mgl@1371
|
6861 |
+ REGNO (XEXP
|
mgl@1371
|
6862 |
+ (SET_SRC (PATTERN (scan)),
|
mgl@1371
|
6863 |
+ 0)) == REGNO (reg)))))
|
mgl@1371
|
6864 |
+ {
|
mgl@1371
|
6865 |
+ if (dump_file)
|
mgl@1371
|
6866 |
+ {
|
mgl@1371
|
6867 |
+ fprintf (dump_file,
|
mgl@1371
|
6868 |
+ ";; Register %i replaced by indexed address in INSN %i\n",
|
mgl@1371
|
6869 |
+ REGNO (reg), INSN_UID (scan));
|
mgl@1371
|
6870 |
+ }
|
mgl@1371
|
6871 |
+ if (MEM_P (SET_DEST (PATTERN (scan))))
|
mgl@1371
|
6872 |
+ XEXP (SET_DEST (PATTERN (scan)), 0) = mem_expr;
|
mgl@1371
|
6873 |
+ else
|
mgl@1371
|
6874 |
+ XEXP (SET_SRC (PATTERN (scan)), 0) = mem_expr;
|
mgl@1371
|
6875 |
+ }
|
mgl@1371
|
6876 |
+
|
mgl@1371
|
6877 |
+ /* Check if register is dead or set in this insn */
|
mgl@1371
|
6878 |
+ if (dead_or_set_p (scan, reg))
|
mgl@1371
|
6879 |
+ {
|
mgl@1371
|
6880 |
+ break;
|
mgl@1371
|
6881 |
+ }
|
mgl@1371
|
6882 |
+
|
mgl@1371
|
6883 |
+ }
|
mgl@1371
|
6884 |
+ }
|
mgl@1371
|
6885 |
+ }
|
mgl@1371
|
6886 |
+ }
|
mgl@1371
|
6887 |
+
|
mgl@1371
|
6888 |
+
|
mgl@1371
|
6889 |
+ if (TARGET_MD_REORG_OPTIMIZATION && (optimize_size || (optimize > 0)))
|
mgl@1371
|
6890 |
+ {
|
mgl@1371
|
6891 |
+
|
mgl@1371
|
6892 |
+ /* Scan through all insns looking for conditional register to
|
mgl@1371
|
6893 |
+ register move operations */
|
mgl@1371
|
6894 |
+ if (dump_file)
|
mgl@1371
|
6895 |
+ {
|
mgl@1371
|
6896 |
+ fprintf (dump_file,
|
mgl@1371
|
6897 |
+ ";; Folding redundant conditional move operations:\n");
|
mgl@1371
|
6898 |
+ }
|
mgl@1371
|
6899 |
+ for (insn = first; insn; insn = next_nonnote_insn (insn))
|
mgl@1371
|
6900 |
+ {
|
mgl@1371
|
6901 |
+ rtx src_reg, dst_reg, scan, test;
|
mgl@1371
|
6902 |
+
|
mgl@1371
|
6903 |
+ if (INSN_P (insn)
|
mgl@1371
|
6904 |
+ && GET_CODE (PATTERN (insn)) == COND_EXEC
|
mgl@1371
|
6905 |
+ && GET_CODE (COND_EXEC_CODE (PATTERN (insn))) == SET
|
mgl@1371
|
6906 |
+ && REG_P (SET_SRC (COND_EXEC_CODE (PATTERN (insn))))
|
mgl@1371
|
6907 |
+ && REG_P (SET_DEST (COND_EXEC_CODE (PATTERN (insn))))
|
mgl@1371
|
6908 |
+ && find_reg_note (insn, REG_DEAD, SET_SRC (COND_EXEC_CODE (PATTERN (insn)))))
|
mgl@1371
|
6909 |
+ {
|
mgl@1371
|
6910 |
+ src_reg = SET_SRC (COND_EXEC_CODE (PATTERN (insn)));
|
mgl@1371
|
6911 |
+ dst_reg = SET_DEST (COND_EXEC_CODE (PATTERN (insn)));
|
mgl@1371
|
6912 |
+ test = COND_EXEC_TEST (PATTERN (insn));
|
mgl@1371
|
6913 |
+ }
|
mgl@1371
|
6914 |
+ else
|
mgl@1371
|
6915 |
+ {
|
mgl@1371
|
6916 |
+ continue;
|
mgl@1371
|
6917 |
+ }
|
mgl@1371
|
6918 |
+
|
mgl@1371
|
6919 |
+ /* Scan backward through the rest of insns in this if-then or if-else
|
mgl@1371
|
6920 |
+ block and check if we can fold the move into another of the conditional
|
mgl@1371
|
6921 |
+ insns in the same block. */
|
mgl@1371
|
6922 |
+ scan = prev_nonnote_insn (insn);
|
mgl@1371
|
6923 |
+ while (INSN_P (scan)
|
mgl@1371
|
6924 |
+ && GET_CODE (PATTERN (scan)) == COND_EXEC
|
mgl@1371
|
6925 |
+ && rtx_equal_p (COND_EXEC_TEST (PATTERN (scan)), test))
|
mgl@1371
|
6926 |
+ {
|
mgl@1371
|
6927 |
+ rtx pattern = COND_EXEC_CODE (PATTERN (scan));
|
mgl@1371
|
6928 |
+ if ( GET_CODE (pattern) == PARALLEL )
|
mgl@1371
|
6929 |
+ pattern = XVECEXP (pattern, 0, 0);
|
mgl@1371
|
6930 |
+
|
mgl@1371
|
6931 |
+ if ( reg_set_p (src_reg, pattern) )
|
mgl@1371
|
6932 |
+ {
|
mgl@1371
|
6933 |
+ /* Fold in the destination register for the cond. move
|
mgl@1371
|
6934 |
+ into this insn. */
|
mgl@1371
|
6935 |
+ SET_DEST (pattern) = dst_reg;
|
mgl@1371
|
6936 |
+ if (dump_file)
|
mgl@1371
|
6937 |
+ {
|
mgl@1371
|
6938 |
+ fprintf (dump_file,
|
mgl@1371
|
6939 |
+ ";; Deleting INSN %i since this operation can be folded into INSN %i\n",
|
mgl@1371
|
6940 |
+ INSN_UID (insn), INSN_UID (scan));
|
mgl@1371
|
6941 |
+ }
|
mgl@1371
|
6942 |
+
|
mgl@1371
|
6943 |
+ /* Scan and check if any of the insns in between uses the src_reg. We
|
mgl@1371
|
6944 |
+ must then replace it with the dst_reg. */
|
mgl@1371
|
6945 |
+ while ( (scan = next_nonnote_insn (scan)) != insn ){
|
mgl@1371
|
6946 |
+ avr32_replace_reg (scan, src_reg, dst_reg);
|
mgl@1371
|
6947 |
+ }
|
mgl@1371
|
6948 |
+ /* Delete the insn. */
|
mgl@1371
|
6949 |
+ SET_INSN_DELETED (insn);
|
mgl@1371
|
6950 |
+
|
mgl@1371
|
6951 |
+ /* Force the instruction to be recognized again */
|
mgl@1371
|
6952 |
+ INSN_CODE (insn) = -1;
|
mgl@1371
|
6953 |
+ break;
|
mgl@1371
|
6954 |
+ }
|
mgl@1371
|
6955 |
+
|
mgl@1371
|
6956 |
+ /* If the destination register is used but not set in this insn
|
mgl@1371
|
6957 |
+ we cannot fold. */
|
mgl@1371
|
6958 |
+ if ( reg_mentioned_p (dst_reg, pattern) )
|
mgl@1371
|
6959 |
+ break;
|
mgl@1371
|
6960 |
+
|
mgl@1371
|
6961 |
+ scan = prev_nonnote_insn (scan);
|
mgl@1371
|
6962 |
+ }
|
mgl@1371
|
6963 |
+ }
|
mgl@1371
|
6964 |
+ }
|
mgl@1371
|
6965 |
+
|
mgl@1371
|
6966 |
+}
|
mgl@1371
|
6967 |
+
|
mgl@1371
|
6968 |
+/* Exported to toplev.c.
|
mgl@1371
|
6969 |
+
|
mgl@1371
|
6970 |
+ Do a final pass over the function, just before delayed branch
|
mgl@1371
|
6971 |
+ scheduling. */
|
mgl@1371
|
6972 |
+
|
mgl@1371
|
6973 |
+static void
|
mgl@1371
|
6974 |
+avr32_reorg (void)
|
mgl@1371
|
6975 |
+{
|
mgl@1371
|
6976 |
+ rtx insn;
|
mgl@1371
|
6977 |
+ HOST_WIDE_INT address = 0;
|
mgl@1371
|
6978 |
+ Mfix *fix;
|
mgl@1371
|
6979 |
+
|
mgl@1371
|
6980 |
+ minipool_fix_head = minipool_fix_tail = NULL;
|
mgl@1371
|
6981 |
+
|
mgl@1371
|
6982 |
+ /* The first insn must always be a note, or the code below won't scan it
|
mgl@1371
|
6983 |
+ properly. */
|
mgl@1371
|
6984 |
+ insn = get_insns ();
|
mgl@1371
|
6985 |
+ if (GET_CODE (insn) != NOTE)
|
mgl@1371
|
6986 |
+ abort ();
|
mgl@1371
|
6987 |
+
|
mgl@1371
|
6988 |
+ /* Scan all the insns and record the operands that will need fixing. */
|
mgl@1371
|
6989 |
+ for (insn = next_nonnote_insn (insn); insn; insn = next_nonnote_insn (insn))
|
mgl@1371
|
6990 |
+ {
|
mgl@1371
|
6991 |
+ if (GET_CODE (insn) == BARRIER)
|
mgl@1371
|
6992 |
+ push_minipool_barrier (insn, address);
|
mgl@1371
|
6993 |
+ else if (INSN_P (insn))
|
mgl@1371
|
6994 |
+ {
|
mgl@1371
|
6995 |
+ rtx table;
|
mgl@1371
|
6996 |
+
|
mgl@1371
|
6997 |
+ note_invalid_constants (insn, address, true);
|
mgl@1371
|
6998 |
+ address += get_attr_length (insn);
|
mgl@1371
|
6999 |
+
|
mgl@1371
|
7000 |
+ /* If the insn is a vector jump, add the size of the table and skip
|
mgl@1371
|
7001 |
+ the table. */
|
mgl@1371
|
7002 |
+ if ((table = is_jump_table (insn)) != NULL)
|
mgl@1371
|
7003 |
+ {
|
mgl@1371
|
7004 |
+ address += get_jump_table_size (table);
|
mgl@1371
|
7005 |
+ insn = table;
|
mgl@1371
|
7006 |
+ }
|
mgl@1371
|
7007 |
+ }
|
mgl@1371
|
7008 |
+ }
|
mgl@1371
|
7009 |
+
|
mgl@1371
|
7010 |
+ fix = minipool_fix_head;
|
mgl@1371
|
7011 |
+
|
mgl@1371
|
7012 |
+ /* Now scan the fixups and perform the required changes. */
|
mgl@1371
|
7013 |
+ while (fix)
|
mgl@1371
|
7014 |
+ {
|
mgl@1371
|
7015 |
+ Mfix *ftmp;
|
mgl@1371
|
7016 |
+ Mfix *fdel;
|
mgl@1371
|
7017 |
+ Mfix *last_added_fix;
|
mgl@1371
|
7018 |
+ Mfix *last_barrier = NULL;
|
mgl@1371
|
7019 |
+ Mfix *this_fix;
|
mgl@1371
|
7020 |
+
|
mgl@1371
|
7021 |
+ /* Skip any further barriers before the next fix. */
|
mgl@1371
|
7022 |
+ while (fix && GET_CODE (fix->insn) == BARRIER)
|
mgl@1371
|
7023 |
+ fix = fix->next;
|
mgl@1371
|
7024 |
+
|
mgl@1371
|
7025 |
+ /* No more fixes. */
|
mgl@1371
|
7026 |
+ if (fix == NULL)
|
mgl@1371
|
7027 |
+ break;
|
mgl@1371
|
7028 |
+
|
mgl@1371
|
7029 |
+ last_added_fix = NULL;
|
mgl@1371
|
7030 |
+
|
mgl@1371
|
7031 |
+ for (ftmp = fix; ftmp; ftmp = ftmp->next)
|
mgl@1371
|
7032 |
+ {
|
mgl@1371
|
7033 |
+ if (GET_CODE (ftmp->insn) == BARRIER)
|
mgl@1371
|
7034 |
+ {
|
mgl@1371
|
7035 |
+ if (ftmp->address >= minipool_vector_head->max_address)
|
mgl@1371
|
7036 |
+ break;
|
mgl@1371
|
7037 |
+
|
mgl@1371
|
7038 |
+ last_barrier = ftmp;
|
mgl@1371
|
7039 |
+ }
|
mgl@1371
|
7040 |
+ else if ((ftmp->minipool = add_minipool_forward_ref (ftmp)) == NULL)
|
mgl@1371
|
7041 |
+ break;
|
mgl@1371
|
7042 |
+
|
mgl@1371
|
7043 |
+ last_added_fix = ftmp; /* Keep track of the last fix added.
|
mgl@1371
|
7044 |
+ */
|
mgl@1371
|
7045 |
+ }
|
mgl@1371
|
7046 |
+
|
mgl@1371
|
7047 |
+ /* If we found a barrier, drop back to that; any fixes that we could
|
mgl@1371
|
7048 |
+ have reached but come after the barrier will now go in the next
|
mgl@1371
|
7049 |
+ mini-pool. */
|
mgl@1371
|
7050 |
+ if (last_barrier != NULL)
|
mgl@1371
|
7051 |
+ {
|
mgl@1371
|
7052 |
+ /* Reduce the refcount for those fixes that won't go into this pool
|
mgl@1371
|
7053 |
+ after all. */
|
mgl@1371
|
7054 |
+ for (fdel = last_barrier->next;
|
mgl@1371
|
7055 |
+ fdel && fdel != ftmp; fdel = fdel->next)
|
mgl@1371
|
7056 |
+ {
|
mgl@1371
|
7057 |
+ fdel->minipool->refcount--;
|
mgl@1371
|
7058 |
+ fdel->minipool = NULL;
|
mgl@1371
|
7059 |
+ }
|
mgl@1371
|
7060 |
+
|
mgl@1371
|
7061 |
+ ftmp = last_barrier;
|
mgl@1371
|
7062 |
+ }
|
mgl@1371
|
7063 |
+ else
|
mgl@1371
|
7064 |
+ {
|
mgl@1371
|
7065 |
+ /* ftmp is first fix that we can't fit into this pool and there no
|
mgl@1371
|
7066 |
+ natural barriers that we could use. Insert a new barrier in the
|
mgl@1371
|
7067 |
+ code somewhere between the previous fix and this one, and
|
mgl@1371
|
7068 |
+ arrange to jump around it. */
|
mgl@1371
|
7069 |
+ HOST_WIDE_INT max_address;
|
mgl@1371
|
7070 |
+
|
mgl@1371
|
7071 |
+ /* The last item on the list of fixes must be a barrier, so we can
|
mgl@1371
|
7072 |
+ never run off the end of the list of fixes without last_barrier
|
mgl@1371
|
7073 |
+ being set. */
|
mgl@1371
|
7074 |
+ if (ftmp == NULL)
|
mgl@1371
|
7075 |
+ abort ();
|
mgl@1371
|
7076 |
+
|
mgl@1371
|
7077 |
+ max_address = minipool_vector_head->max_address;
|
mgl@1371
|
7078 |
+ /* Check that there isn't another fix that is in range that we
|
mgl@1371
|
7079 |
+ couldn't fit into this pool because the pool was already too
|
mgl@1371
|
7080 |
+ large: we need to put the pool before such an instruction. */
|
mgl@1371
|
7081 |
+ if (ftmp->address < max_address)
|
mgl@1371
|
7082 |
+ max_address = ftmp->address;
|
mgl@1371
|
7083 |
+
|
mgl@1371
|
7084 |
+ last_barrier = create_fix_barrier (last_added_fix, max_address);
|
mgl@1371
|
7085 |
+ }
|
mgl@1371
|
7086 |
+
|
mgl@1371
|
7087 |
+ assign_minipool_offsets (last_barrier);
|
mgl@1371
|
7088 |
+
|
mgl@1371
|
7089 |
+ while (ftmp)
|
mgl@1371
|
7090 |
+ {
|
mgl@1371
|
7091 |
+ if (GET_CODE (ftmp->insn) != BARRIER
|
mgl@1371
|
7092 |
+ && ((ftmp->minipool = add_minipool_backward_ref (ftmp))
|
mgl@1371
|
7093 |
+ == NULL))
|
mgl@1371
|
7094 |
+ break;
|
mgl@1371
|
7095 |
+
|
mgl@1371
|
7096 |
+ ftmp = ftmp->next;
|
mgl@1371
|
7097 |
+ }
|
mgl@1371
|
7098 |
+
|
mgl@1371
|
7099 |
+ /* Scan over the fixes we have identified for this pool, fixing them up
|
mgl@1371
|
7100 |
+ and adding the constants to the pool itself. */
|
mgl@1371
|
7101 |
+ for (this_fix = fix; this_fix && ftmp != this_fix;
|
mgl@1371
|
7102 |
+ this_fix = this_fix->next)
|
mgl@1371
|
7103 |
+ if (GET_CODE (this_fix->insn) != BARRIER
|
mgl@1371
|
7104 |
+ /* Do nothing for entries present just to force the insertion of
|
mgl@1371
|
7105 |
+ a minipool. */
|
mgl@1371
|
7106 |
+ && !IS_FORCE_MINIPOOL (this_fix->value))
|
mgl@1371
|
7107 |
+ {
|
mgl@1371
|
7108 |
+ rtx addr = plus_constant (gen_rtx_LABEL_REF (VOIDmode,
|
mgl@1371
|
7109 |
+ minipool_vector_label),
|
mgl@1371
|
7110 |
+ this_fix->minipool->offset);
|
mgl@1371
|
7111 |
+ *this_fix->loc = gen_rtx_MEM (this_fix->mode, addr);
|
mgl@1371
|
7112 |
+ }
|
mgl@1371
|
7113 |
+
|
mgl@1371
|
7114 |
+ dump_minipool (last_barrier->insn);
|
mgl@1371
|
7115 |
+ fix = ftmp;
|
mgl@1371
|
7116 |
+ }
|
mgl@1371
|
7117 |
+
|
mgl@1371
|
7118 |
+ /* Free the minipool memory. */
|
mgl@1371
|
7119 |
+ obstack_free (&minipool_obstack, minipool_startobj);
|
mgl@1371
|
7120 |
+
|
mgl@1371
|
7121 |
+ avr32_reorg_optimization ();
|
mgl@1371
|
7122 |
+}
|
mgl@1371
|
7123 |
+
|
mgl@1371
|
7124 |
+
|
mgl@1371
|
7125 |
+/*
|
mgl@1371
|
7126 |
+ Hook for doing some final scanning of instructions. Does nothing yet...*/
|
mgl@1371
|
7127 |
+void
|
mgl@1371
|
7128 |
+avr32_final_prescan_insn (rtx insn ATTRIBUTE_UNUSED,
|
mgl@1371
|
7129 |
+ rtx * opvec ATTRIBUTE_UNUSED,
|
mgl@1371
|
7130 |
+ int noperands ATTRIBUTE_UNUSED)
|
mgl@1371
|
7131 |
+{
|
mgl@1371
|
7132 |
+ return;
|
mgl@1371
|
7133 |
+}
|
mgl@1371
|
7134 |
+
|
mgl@1371
|
7135 |
+
|
mgl@1371
|
7136 |
+/* Function for changing the condition on the next instruction,
|
mgl@1371
|
7137 |
+ should be used when emmiting compare instructions and
|
mgl@1371
|
7138 |
+ the condition of the next instruction needs to change.
|
mgl@1371
|
7139 |
+*/
|
mgl@1371
|
7140 |
+int
|
mgl@1371
|
7141 |
+set_next_insn_cond (rtx cur_insn, rtx new_cond)
|
mgl@1371
|
7142 |
+{
|
mgl@1371
|
7143 |
+ rtx next_insn = next_nonnote_insn (cur_insn);
|
mgl@1371
|
7144 |
+ if ((next_insn != NULL_RTX)
|
mgl@1371
|
7145 |
+ && (INSN_P (next_insn)))
|
mgl@1371
|
7146 |
+ {
|
mgl@1371
|
7147 |
+ if ((GET_CODE (PATTERN (next_insn)) == SET)
|
mgl@1371
|
7148 |
+ && (GET_CODE (SET_SRC (PATTERN (next_insn))) == IF_THEN_ELSE))
|
mgl@1371
|
7149 |
+ {
|
mgl@1371
|
7150 |
+ /* Branch instructions */
|
mgl@1371
|
7151 |
+ XEXP (SET_SRC (PATTERN (next_insn)), 0) = new_cond;
|
mgl@1371
|
7152 |
+ /* Force the instruction to be recognized again */
|
mgl@1371
|
7153 |
+ INSN_CODE (next_insn) = -1;
|
mgl@1371
|
7154 |
+ return TRUE;
|
mgl@1371
|
7155 |
+ }
|
mgl@1371
|
7156 |
+ else if ((GET_CODE (PATTERN (next_insn)) == SET)
|
mgl@1371
|
7157 |
+ && avr32_comparison_operator (SET_SRC (PATTERN (next_insn)),
|
mgl@1371
|
7158 |
+ GET_MODE (SET_SRC (PATTERN (next_insn)))))
|
mgl@1371
|
7159 |
+ {
|
mgl@1371
|
7160 |
+ /* scc with no compare */
|
mgl@1371
|
7161 |
+ SET_SRC (PATTERN (next_insn)) = new_cond;
|
mgl@1371
|
7162 |
+ /* Force the instruction to be recognized again */
|
mgl@1371
|
7163 |
+ INSN_CODE (next_insn) = -1;
|
mgl@1371
|
7164 |
+ return TRUE;
|
mgl@1371
|
7165 |
+ }
|
mgl@1371
|
7166 |
+ else if (GET_CODE (PATTERN (next_insn)) == COND_EXEC)
|
mgl@1371
|
7167 |
+ {
|
mgl@1371
|
7168 |
+ if ( GET_CODE (new_cond) == UNSPEC )
|
mgl@1371
|
7169 |
+ {
|
mgl@1371
|
7170 |
+ COND_EXEC_TEST (PATTERN (next_insn)) =
|
mgl@1371
|
7171 |
+ gen_rtx_UNSPEC (CCmode,
|
mgl@1371
|
7172 |
+ gen_rtvec (2,
|
mgl@1371
|
7173 |
+ XEXP (COND_EXEC_TEST (PATTERN (next_insn)), 0),
|
mgl@1371
|
7174 |
+ XEXP (COND_EXEC_TEST (PATTERN (next_insn)), 1)),
|
mgl@1371
|
7175 |
+ XINT (new_cond, 1));
|
mgl@1371
|
7176 |
+ }
|
mgl@1371
|
7177 |
+ else
|
mgl@1371
|
7178 |
+ {
|
mgl@1371
|
7179 |
+ PUT_CODE(COND_EXEC_TEST (PATTERN (next_insn)), GET_CODE(new_cond));
|
mgl@1371
|
7180 |
+ }
|
mgl@1371
|
7181 |
+ }
|
mgl@1371
|
7182 |
+ }
|
mgl@1371
|
7183 |
+
|
mgl@1371
|
7184 |
+ return FALSE;
|
mgl@1371
|
7185 |
+}
|
mgl@1371
|
7186 |
+
|
mgl@1371
|
7187 |
+/* Function for obtaining the condition for the next instruction
|
mgl@1371
|
7188 |
+ after cur_insn.
|
mgl@1371
|
7189 |
+*/
|
mgl@1371
|
7190 |
+rtx
|
mgl@1371
|
7191 |
+get_next_insn_cond (rtx cur_insn)
|
mgl@1371
|
7192 |
+{
|
mgl@1371
|
7193 |
+ rtx next_insn = next_nonnote_insn (cur_insn);
|
mgl@1371
|
7194 |
+ rtx cond = NULL_RTX;
|
mgl@1371
|
7195 |
+ if (next_insn != NULL_RTX
|
mgl@1371
|
7196 |
+ && INSN_P (next_insn))
|
mgl@1371
|
7197 |
+ {
|
mgl@1371
|
7198 |
+ if ((GET_CODE (PATTERN (next_insn)) == SET)
|
mgl@1371
|
7199 |
+ && (GET_CODE (SET_SRC (PATTERN (next_insn))) == IF_THEN_ELSE))
|
mgl@1371
|
7200 |
+ {
|
mgl@1371
|
7201 |
+ /* Branch and cond if then else instructions */
|
mgl@1371
|
7202 |
+ cond = XEXP (SET_SRC (PATTERN (next_insn)), 0);
|
mgl@1371
|
7203 |
+ }
|
mgl@1371
|
7204 |
+ else if ((GET_CODE (PATTERN (next_insn)) == SET)
|
mgl@1371
|
7205 |
+ && avr32_comparison_operator (SET_SRC (PATTERN (next_insn)),
|
mgl@1371
|
7206 |
+ GET_MODE (SET_SRC (PATTERN (next_insn)))))
|
mgl@1371
|
7207 |
+ {
|
mgl@1371
|
7208 |
+ /* scc with no compare */
|
mgl@1371
|
7209 |
+ cond = SET_SRC (PATTERN (next_insn));
|
mgl@1371
|
7210 |
+ }
|
mgl@1371
|
7211 |
+ else if (GET_CODE (PATTERN (next_insn)) == COND_EXEC)
|
mgl@1371
|
7212 |
+ {
|
mgl@1371
|
7213 |
+ cond = COND_EXEC_TEST (PATTERN (next_insn));
|
mgl@1371
|
7214 |
+ }
|
mgl@1371
|
7215 |
+ }
|
mgl@1371
|
7216 |
+ return cond;
|
mgl@1371
|
7217 |
+}
|
mgl@1371
|
7218 |
+
|
mgl@1371
|
7219 |
+
|
mgl@1371
|
7220 |
+rtx
|
mgl@1371
|
7221 |
+avr32_output_cmp (rtx cond, enum machine_mode mode, rtx op0, rtx op1)
|
mgl@1371
|
7222 |
+{
|
mgl@1371
|
7223 |
+
|
mgl@1371
|
7224 |
+ rtx new_cond = NULL_RTX;
|
mgl@1371
|
7225 |
+ rtx ops[2];
|
mgl@1371
|
7226 |
+ rtx compare_pattern;
|
mgl@1371
|
7227 |
+ ops[0] = op0;
|
mgl@1371
|
7228 |
+ ops[1] = op1;
|
mgl@1371
|
7229 |
+
|
mgl@1371
|
7230 |
+ if ( GET_CODE (op0) == AND )
|
mgl@1371
|
7231 |
+ compare_pattern = op0;
|
mgl@1371
|
7232 |
+ else
|
mgl@1371
|
7233 |
+ compare_pattern = gen_rtx_COMPARE (mode, op0, op1);
|
mgl@1371
|
7234 |
+
|
mgl@1371
|
7235 |
+ new_cond = is_compare_redundant (compare_pattern, cond);
|
mgl@1371
|
7236 |
+
|
mgl@1371
|
7237 |
+ if (new_cond != NULL_RTX)
|
mgl@1371
|
7238 |
+ return new_cond;
|
mgl@1371
|
7239 |
+
|
mgl@1371
|
7240 |
+ /* Check if we are inserting a bit-load instead of a compare. */
|
mgl@1371
|
7241 |
+ if ( GET_CODE (op0) == AND )
|
mgl@1371
|
7242 |
+ {
|
mgl@1371
|
7243 |
+ ops[0] = XEXP (op0, 0);
|
mgl@1371
|
7244 |
+ ops[1] = XEXP (op0, 1);
|
mgl@1371
|
7245 |
+ output_asm_insn ("bld\t%0, %p1", ops);
|
mgl@1371
|
7246 |
+ return cond;
|
mgl@1371
|
7247 |
+ }
|
mgl@1371
|
7248 |
+
|
mgl@1371
|
7249 |
+ /* Insert compare */
|
mgl@1371
|
7250 |
+ switch (mode)
|
mgl@1371
|
7251 |
+ {
|
mgl@1371
|
7252 |
+ case QImode:
|
mgl@1371
|
7253 |
+ output_asm_insn ("cp.b\t%0, %1", ops);
|
mgl@1371
|
7254 |
+ break;
|
mgl@1371
|
7255 |
+ case HImode:
|
mgl@1371
|
7256 |
+ output_asm_insn ("cp.h\t%0, %1", ops);
|
mgl@1371
|
7257 |
+ break;
|
mgl@1371
|
7258 |
+ case SImode:
|
mgl@1371
|
7259 |
+ output_asm_insn ("cp.w\t%0, %1", ops);
|
mgl@1371
|
7260 |
+ break;
|
mgl@1371
|
7261 |
+ case DImode:
|
mgl@1371
|
7262 |
+ if (GET_CODE (op1) != REG)
|
mgl@1371
|
7263 |
+ output_asm_insn ("cp.w\t%0, %1\ncpc\t%m0", ops);
|
mgl@1371
|
7264 |
+ else
|
mgl@1371
|
7265 |
+ output_asm_insn ("cp.w\t%0, %1\ncpc\t%m0, %m1", ops);
|
mgl@1371
|
7266 |
+ break;
|
mgl@1371
|
7267 |
+ default:
|
mgl@1371
|
7268 |
+ internal_error ("Unknown comparison mode");
|
mgl@1371
|
7269 |
+ break;
|
mgl@1371
|
7270 |
+ }
|
mgl@1371
|
7271 |
+
|
mgl@1371
|
7272 |
+ return cond;
|
mgl@1371
|
7273 |
+}
|
mgl@1371
|
7274 |
+
|
mgl@1371
|
7275 |
+int
|
mgl@1371
|
7276 |
+avr32_load_multiple_operation (rtx op,
|
mgl@1371
|
7277 |
+ enum machine_mode mode ATTRIBUTE_UNUSED)
|
mgl@1371
|
7278 |
+{
|
mgl@1371
|
7279 |
+ int count = XVECLEN (op, 0);
|
mgl@1371
|
7280 |
+ unsigned int dest_regno;
|
mgl@1371
|
7281 |
+ rtx src_addr;
|
mgl@1371
|
7282 |
+ rtx elt;
|
mgl@1371
|
7283 |
+ int i = 1, base = 0;
|
mgl@1371
|
7284 |
+
|
mgl@1371
|
7285 |
+ if (count <= 1 || GET_CODE (XVECEXP (op, 0, 0)) != SET)
|
mgl@1371
|
7286 |
+ return 0;
|
mgl@1371
|
7287 |
+
|
mgl@1371
|
7288 |
+ /* Check to see if this might be a write-back. */
|
mgl@1371
|
7289 |
+ if (GET_CODE (SET_SRC (elt = XVECEXP (op, 0, 0))) == PLUS)
|
mgl@1371
|
7290 |
+ {
|
mgl@1371
|
7291 |
+ i++;
|
mgl@1371
|
7292 |
+ base = 1;
|
mgl@1371
|
7293 |
+
|
mgl@1371
|
7294 |
+ /* Now check it more carefully. */
|
mgl@1371
|
7295 |
+ if (GET_CODE (SET_DEST (elt)) != REG
|
mgl@1371
|
7296 |
+ || GET_CODE (XEXP (SET_SRC (elt), 0)) != REG
|
mgl@1371
|
7297 |
+ || GET_CODE (XEXP (SET_SRC (elt), 1)) != CONST_INT
|
mgl@1371
|
7298 |
+ || INTVAL (XEXP (SET_SRC (elt), 1)) != (count - 1) * 4)
|
mgl@1371
|
7299 |
+ return 0;
|
mgl@1371
|
7300 |
+ }
|
mgl@1371
|
7301 |
+
|
mgl@1371
|
7302 |
+ /* Perform a quick check so we don't blow up below. */
|
mgl@1371
|
7303 |
+ if (count <= 1
|
mgl@1371
|
7304 |
+ || GET_CODE (XVECEXP (op, 0, i - 1)) != SET
|
mgl@1371
|
7305 |
+ || GET_CODE (SET_DEST (XVECEXP (op, 0, i - 1))) != REG
|
mgl@1371
|
7306 |
+ || GET_CODE (SET_SRC (XVECEXP (op, 0, i - 1))) != UNSPEC)
|
mgl@1371
|
7307 |
+ return 0;
|
mgl@1371
|
7308 |
+
|
mgl@1371
|
7309 |
+ dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, i - 1)));
|
mgl@1371
|
7310 |
+ src_addr = XEXP (SET_SRC (XVECEXP (op, 0, i - 1)), 0);
|
mgl@1371
|
7311 |
+
|
mgl@1371
|
7312 |
+ for (; i < count; i++)
|
mgl@1371
|
7313 |
+ {
|
mgl@1371
|
7314 |
+ elt = XVECEXP (op, 0, i);
|
mgl@1371
|
7315 |
+
|
mgl@1371
|
7316 |
+ if (GET_CODE (elt) != SET
|
mgl@1371
|
7317 |
+ || GET_CODE (SET_DEST (elt)) != REG
|
mgl@1371
|
7318 |
+ || GET_MODE (SET_DEST (elt)) != SImode
|
mgl@1371
|
7319 |
+ || GET_CODE (SET_SRC (elt)) != UNSPEC)
|
mgl@1371
|
7320 |
+ return 0;
|
mgl@1371
|
7321 |
+ }
|
mgl@1371
|
7322 |
+
|
mgl@1371
|
7323 |
+ return 1;
|
mgl@1371
|
7324 |
+}
|
mgl@1371
|
7325 |
+
|
mgl@1371
|
7326 |
+int
|
mgl@1371
|
7327 |
+avr32_store_multiple_operation (rtx op,
|
mgl@1371
|
7328 |
+ enum machine_mode mode ATTRIBUTE_UNUSED)
|
mgl@1371
|
7329 |
+{
|
mgl@1371
|
7330 |
+ int count = XVECLEN (op, 0);
|
mgl@1371
|
7331 |
+ int src_regno;
|
mgl@1371
|
7332 |
+ rtx dest_addr;
|
mgl@1371
|
7333 |
+ rtx elt;
|
mgl@1371
|
7334 |
+ int i = 1;
|
mgl@1371
|
7335 |
+
|
mgl@1371
|
7336 |
+ if (count <= 1 || GET_CODE (XVECEXP (op, 0, 0)) != SET)
|
mgl@1371
|
7337 |
+ return 0;
|
mgl@1371
|
7338 |
+
|
mgl@1371
|
7339 |
+ /* Perform a quick check so we don't blow up below. */
|
mgl@1371
|
7340 |
+ if (count <= i
|
mgl@1371
|
7341 |
+ || GET_CODE (XVECEXP (op, 0, i - 1)) != SET
|
mgl@1371
|
7342 |
+ || GET_CODE (SET_DEST (XVECEXP (op, 0, i - 1))) != MEM
|
mgl@1371
|
7343 |
+ || GET_CODE (SET_SRC (XVECEXP (op, 0, i - 1))) != UNSPEC)
|
mgl@1371
|
7344 |
+ return 0;
|
mgl@1371
|
7345 |
+
|
mgl@1371
|
7346 |
+ src_regno = REGNO (SET_SRC (XVECEXP (op, 0, i - 1)));
|
mgl@1371
|
7347 |
+ dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, i - 1)), 0);
|
mgl@1371
|
7348 |
+
|
mgl@1371
|
7349 |
+ for (; i < count; i++)
|
mgl@1371
|
7350 |
+ {
|
mgl@1371
|
7351 |
+ elt = XVECEXP (op, 0, i);
|
mgl@1371
|
7352 |
+
|
mgl@1371
|
7353 |
+ if (GET_CODE (elt) != SET
|
mgl@1371
|
7354 |
+ || GET_CODE (SET_DEST (elt)) != MEM
|
mgl@1371
|
7355 |
+ || GET_MODE (SET_DEST (elt)) != SImode
|
mgl@1371
|
7356 |
+ || GET_CODE (SET_SRC (elt)) != UNSPEC)
|
mgl@1371
|
7357 |
+ return 0;
|
mgl@1371
|
7358 |
+ }
|
mgl@1371
|
7359 |
+
|
mgl@1371
|
7360 |
+ return 1;
|
mgl@1371
|
7361 |
+}
|
mgl@1371
|
7362 |
+
|
mgl@1371
|
7363 |
+int
|
mgl@1371
|
7364 |
+avr32_valid_macmac_bypass (rtx insn_out, rtx insn_in)
|
mgl@1371
|
7365 |
+{
|
mgl@1371
|
7366 |
+ /* Check if they use the same accumulator */
|
mgl@1371
|
7367 |
+ if (rtx_equal_p
|
mgl@1371
|
7368 |
+ (SET_DEST (PATTERN (insn_out)), SET_DEST (PATTERN (insn_in))))
|
mgl@1371
|
7369 |
+ {
|
mgl@1371
|
7370 |
+ return TRUE;
|
mgl@1371
|
7371 |
+ }
|
mgl@1371
|
7372 |
+
|
mgl@1371
|
7373 |
+ return FALSE;
|
mgl@1371
|
7374 |
+}
|
mgl@1371
|
7375 |
+
|
mgl@1371
|
7376 |
+int
|
mgl@1371
|
7377 |
+avr32_valid_mulmac_bypass (rtx insn_out, rtx insn_in)
|
mgl@1371
|
7378 |
+{
|
mgl@1371
|
7379 |
+ /*
|
mgl@1371
|
7380 |
+ Check if the mul instruction produces the accumulator for the mac
|
mgl@1371
|
7381 |
+ instruction. */
|
mgl@1371
|
7382 |
+ if (rtx_equal_p
|
mgl@1371
|
7383 |
+ (SET_DEST (PATTERN (insn_out)), SET_DEST (PATTERN (insn_in))))
|
mgl@1371
|
7384 |
+ {
|
mgl@1371
|
7385 |
+ return TRUE;
|
mgl@1371
|
7386 |
+ }
|
mgl@1371
|
7387 |
+ return FALSE;
|
mgl@1371
|
7388 |
+}
|
mgl@1371
|
7389 |
+
|
mgl@1371
|
7390 |
+int
|
mgl@1371
|
7391 |
+avr32_store_bypass (rtx insn_out, rtx insn_in)
|
mgl@1371
|
7392 |
+{
|
mgl@1371
|
7393 |
+ /* Only valid bypass if the output result is used as an src in the store
|
mgl@1371
|
7394 |
+ instruction, NOT if used as a pointer or base. */
|
mgl@1371
|
7395 |
+ if (rtx_equal_p
|
mgl@1371
|
7396 |
+ (SET_DEST (PATTERN (insn_out)), SET_SRC (PATTERN (insn_in))))
|
mgl@1371
|
7397 |
+ {
|
mgl@1371
|
7398 |
+ return TRUE;
|
mgl@1371
|
7399 |
+ }
|
mgl@1371
|
7400 |
+
|
mgl@1371
|
7401 |
+ return FALSE;
|
mgl@1371
|
7402 |
+}
|
mgl@1371
|
7403 |
+
|
mgl@1371
|
7404 |
+int
|
mgl@1371
|
7405 |
+avr32_mul_waw_bypass (rtx insn_out, rtx insn_in)
|
mgl@1371
|
7406 |
+{
|
mgl@1371
|
7407 |
+ /* Check if the register holding the result from the mul instruction is
|
mgl@1371
|
7408 |
+ used as a result register in the input instruction. */
|
mgl@1371
|
7409 |
+ if (rtx_equal_p
|
mgl@1371
|
7410 |
+ (SET_DEST (PATTERN (insn_out)), SET_DEST (PATTERN (insn_in))))
|
mgl@1371
|
7411 |
+ {
|
mgl@1371
|
7412 |
+ return TRUE;
|
mgl@1371
|
7413 |
+ }
|
mgl@1371
|
7414 |
+
|
mgl@1371
|
7415 |
+ return FALSE;
|
mgl@1371
|
7416 |
+}
|
mgl@1371
|
7417 |
+
|
mgl@1371
|
7418 |
+int
|
mgl@1371
|
7419 |
+avr32_valid_load_double_bypass (rtx insn_out, rtx insn_in)
|
mgl@1371
|
7420 |
+{
|
mgl@1371
|
7421 |
+ /* Check if the first loaded word in insn_out is used in insn_in. */
|
mgl@1371
|
7422 |
+ rtx dst_reg;
|
mgl@1371
|
7423 |
+ rtx second_loaded_reg;
|
mgl@1371
|
7424 |
+
|
mgl@1371
|
7425 |
+ /* If this is a double alu operation then the bypass is not valid */
|
mgl@1371
|
7426 |
+ if ((get_attr_type (insn_in) == TYPE_ALU
|
mgl@1371
|
7427 |
+ || get_attr_type (insn_in) == TYPE_ALU2)
|
mgl@1371
|
7428 |
+ && (GET_MODE_SIZE (GET_MODE (SET_DEST (PATTERN (insn_out)))) > 4))
|
mgl@1371
|
7429 |
+ return FALSE;
|
mgl@1371
|
7430 |
+
|
mgl@1371
|
7431 |
+ /* Get the destination register in the load */
|
mgl@1371
|
7432 |
+ if (!REG_P (SET_DEST (PATTERN (insn_out))))
|
mgl@1371
|
7433 |
+ return FALSE;
|
mgl@1371
|
7434 |
+
|
mgl@1371
|
7435 |
+ dst_reg = SET_DEST (PATTERN (insn_out));
|
mgl@1371
|
7436 |
+ second_loaded_reg = gen_rtx_REG (SImode, REGNO (dst_reg) + 1);
|
mgl@1371
|
7437 |
+
|
mgl@1371
|
7438 |
+ if (!reg_mentioned_p (second_loaded_reg, PATTERN (insn_in)))
|
mgl@1371
|
7439 |
+ return TRUE;
|
mgl@1371
|
7440 |
+
|
mgl@1371
|
7441 |
+ return FALSE;
|
mgl@1371
|
7442 |
+}
|
mgl@1371
|
7443 |
+
|
mgl@1371
|
7444 |
+
|
mgl@1371
|
7445 |
+int
|
mgl@1371
|
7446 |
+avr32_valid_load_quad_bypass (rtx insn_out, rtx insn_in)
|
mgl@1371
|
7447 |
+{
|
mgl@1371
|
7448 |
+ /*
|
mgl@1371
|
7449 |
+ Check if the two first loaded word in insn_out are used in insn_in. */
|
mgl@1371
|
7450 |
+ rtx dst_reg;
|
mgl@1371
|
7451 |
+ rtx third_loaded_reg, fourth_loaded_reg;
|
mgl@1371
|
7452 |
+
|
mgl@1371
|
7453 |
+ /* Get the destination register in the load */
|
mgl@1371
|
7454 |
+ if (!REG_P (SET_DEST (PATTERN (insn_out))))
|
mgl@1371
|
7455 |
+ return FALSE;
|
mgl@1371
|
7456 |
+
|
mgl@1371
|
7457 |
+ dst_reg = SET_DEST (PATTERN (insn_out));
|
mgl@1371
|
7458 |
+ third_loaded_reg = gen_rtx_REG (SImode, REGNO (dst_reg) + 2);
|
mgl@1371
|
7459 |
+ fourth_loaded_reg = gen_rtx_REG (SImode, REGNO (dst_reg) + 3);
|
mgl@1371
|
7460 |
+
|
mgl@1371
|
7461 |
+ if (!reg_mentioned_p (third_loaded_reg, PATTERN (insn_in))
|
mgl@1371
|
7462 |
+ && !reg_mentioned_p (fourth_loaded_reg, PATTERN (insn_in)))
|
mgl@1371
|
7463 |
+ {
|
mgl@1371
|
7464 |
+ return TRUE;
|
mgl@1371
|
7465 |
+ }
|
mgl@1371
|
7466 |
+
|
mgl@1371
|
7467 |
+ return FALSE;
|
mgl@1371
|
7468 |
+}
|
mgl@1371
|
7469 |
+
|
mgl@1371
|
7470 |
+
|
mgl@1371
|
7471 |
+
|
mgl@1371
|
7472 |
+rtx
|
mgl@1371
|
7473 |
+avr32_ifcvt_modify_test (ce_if_block_t *ce_info,
|
mgl@1371
|
7474 |
+ rtx test ){
|
mgl@1371
|
7475 |
+ rtx branch_insn;
|
mgl@1371
|
7476 |
+ rtx cmp_test;
|
mgl@1371
|
7477 |
+ rtx compare_op0;
|
mgl@1371
|
7478 |
+ rtx compare_op1;
|
mgl@1371
|
7479 |
+
|
mgl@1371
|
7480 |
+
|
mgl@1371
|
7481 |
+ if ( !ce_info
|
mgl@1371
|
7482 |
+ || test == NULL_RTX
|
mgl@1371
|
7483 |
+ || !reg_mentioned_p (cc0_rtx, test))
|
mgl@1371
|
7484 |
+ return test;
|
mgl@1371
|
7485 |
+
|
mgl@1371
|
7486 |
+ branch_insn = BB_END (ce_info->test_bb);
|
mgl@1371
|
7487 |
+ cmp_test = PATTERN(prev_nonnote_insn (branch_insn));
|
mgl@1371
|
7488 |
+
|
mgl@1371
|
7489 |
+ if (GET_CODE(cmp_test) != SET
|
mgl@1371
|
7490 |
+ || !CC0_P(XEXP(cmp_test, 0)) )
|
mgl@1371
|
7491 |
+ return cmp_test;
|
mgl@1371
|
7492 |
+
|
mgl@1371
|
7493 |
+ if ( GET_CODE(SET_SRC(cmp_test)) == COMPARE ){
|
mgl@1371
|
7494 |
+ compare_op0 = XEXP(SET_SRC(cmp_test), 0);
|
mgl@1371
|
7495 |
+ compare_op1 = XEXP(SET_SRC(cmp_test), 1);
|
mgl@1371
|
7496 |
+ } else {
|
mgl@1371
|
7497 |
+ compare_op0 = SET_SRC(cmp_test);
|
mgl@1371
|
7498 |
+ compare_op1 = const0_rtx;
|
mgl@1371
|
7499 |
+ }
|
mgl@1371
|
7500 |
+
|
mgl@1371
|
7501 |
+ return gen_rtx_fmt_ee (GET_CODE(test), GET_MODE (compare_op0),
|
mgl@1371
|
7502 |
+ compare_op0, compare_op1);
|
mgl@1371
|
7503 |
+}
|
mgl@1371
|
7504 |
+
|
mgl@1371
|
7505 |
+
|
mgl@1371
|
7506 |
+
|
mgl@1371
|
7507 |
+rtx
|
mgl@1371
|
7508 |
+avr32_ifcvt_modify_insn (ce_if_block_t *ce_info,
|
mgl@1371
|
7509 |
+ rtx pattern,
|
mgl@1371
|
7510 |
+ rtx insn,
|
mgl@1371
|
7511 |
+ int *num_true_changes){
|
mgl@1371
|
7512 |
+ rtx test = COND_EXEC_TEST(pattern);
|
mgl@1371
|
7513 |
+ rtx op = COND_EXEC_CODE(pattern);
|
mgl@1371
|
7514 |
+ rtx cmp_insn;
|
mgl@1371
|
7515 |
+ rtx cond_exec_insn;
|
mgl@1371
|
7516 |
+ int inputs_set_outside_ifblock = 1;
|
mgl@1371
|
7517 |
+ basic_block current_bb = BLOCK_FOR_INSN (insn);
|
mgl@1371
|
7518 |
+ rtx bb_insn ;
|
mgl@1371
|
7519 |
+ enum machine_mode mode = GET_MODE (XEXP (op, 0));
|
mgl@1371
|
7520 |
+
|
mgl@1371
|
7521 |
+ if (CC0_P(XEXP(test, 0)))
|
mgl@1371
|
7522 |
+ test = avr32_ifcvt_modify_test (ce_info,
|
mgl@1371
|
7523 |
+ test );
|
mgl@1371
|
7524 |
+
|
mgl@1371
|
7525 |
+ pattern = gen_rtx_COND_EXEC (VOIDmode, test, op);
|
mgl@1371
|
7526 |
+
|
mgl@1371
|
7527 |
+ if ( !reload_completed )
|
mgl@1371
|
7528 |
+ {
|
mgl@1371
|
7529 |
+ rtx start;
|
mgl@1371
|
7530 |
+ int num_insns;
|
mgl@1371
|
7531 |
+ int max_insns = MAX_CONDITIONAL_EXECUTE;
|
mgl@1371
|
7532 |
+
|
mgl@1371
|
7533 |
+ if ( !ce_info )
|
mgl@1371
|
7534 |
+ return op;
|
mgl@1371
|
7535 |
+
|
mgl@1371
|
7536 |
+ /* Check if the insn is not suitable for conditional
|
mgl@1371
|
7537 |
+ execution. */
|
mgl@1371
|
7538 |
+ start_sequence ();
|
mgl@1371
|
7539 |
+ cond_exec_insn = emit_insn (pattern);
|
mgl@1371
|
7540 |
+ if ( recog_memoized (cond_exec_insn) < 0
|
mgl@1371
|
7541 |
+ && !no_new_pseudos )
|
mgl@1371
|
7542 |
+ {
|
mgl@1371
|
7543 |
+ /* Insn is not suitable for conditional execution, try
|
mgl@1371
|
7544 |
+ to fix it up by using an extra scratch register or
|
mgl@1371
|
7545 |
+ by pulling the operation outside the if-then-else
|
mgl@1371
|
7546 |
+ and then emiting a conditional move inside the if-then-else. */
|
mgl@1371
|
7547 |
+ end_sequence ();
|
mgl@1371
|
7548 |
+ if ( GET_CODE (op) != SET
|
mgl@1371
|
7549 |
+ || !REG_P (SET_DEST (op))
|
mgl@1371
|
7550 |
+ || GET_CODE (SET_SRC (op)) == IF_THEN_ELSE
|
mgl@1371
|
7551 |
+ || GET_MODE_SIZE (mode) > UNITS_PER_WORD )
|
mgl@1371
|
7552 |
+ return NULL_RTX;
|
mgl@1371
|
7553 |
+
|
mgl@1371
|
7554 |
+ /* Check if any of the input operands to the insn is set inside the
|
mgl@1371
|
7555 |
+ current block. */
|
mgl@1371
|
7556 |
+ if ( current_bb->index == ce_info->then_bb->index )
|
mgl@1371
|
7557 |
+ start = PREV_INSN (BB_HEAD (ce_info->then_bb));
|
mgl@1371
|
7558 |
+ else
|
mgl@1371
|
7559 |
+ start = PREV_INSN (BB_HEAD (ce_info->else_bb));
|
mgl@1371
|
7560 |
+
|
mgl@1371
|
7561 |
+
|
mgl@1371
|
7562 |
+ for ( bb_insn = next_nonnote_insn (start); bb_insn != insn; bb_insn = next_nonnote_insn (bb_insn) )
|
mgl@1371
|
7563 |
+ {
|
mgl@1371
|
7564 |
+ rtx set = single_set (bb_insn);
|
mgl@1371
|
7565 |
+
|
mgl@1371
|
7566 |
+ if ( set && reg_mentioned_p (SET_DEST (set), SET_SRC (op)))
|
mgl@1371
|
7567 |
+ {
|
mgl@1371
|
7568 |
+ inputs_set_outside_ifblock = 0;
|
mgl@1371
|
7569 |
+ break;
|
mgl@1371
|
7570 |
+ }
|
mgl@1371
|
7571 |
+ }
|
mgl@1371
|
7572 |
+
|
mgl@1371
|
7573 |
+ cmp_insn = prev_nonnote_insn (BB_END (ce_info->test_bb));
|
mgl@1371
|
7574 |
+
|
mgl@1371
|
7575 |
+
|
mgl@1371
|
7576 |
+ /* Check if we can insert more insns. */
|
mgl@1371
|
7577 |
+ num_insns = ( ce_info->num_then_insns +
|
mgl@1371
|
7578 |
+ ce_info->num_else_insns +
|
mgl@1371
|
7579 |
+ ce_info->num_cond_clobber_insns +
|
mgl@1371
|
7580 |
+ ce_info->num_extra_move_insns );
|
mgl@1371
|
7581 |
+
|
mgl@1371
|
7582 |
+ if ( ce_info->num_else_insns != 0 )
|
mgl@1371
|
7583 |
+ max_insns *=2;
|
mgl@1371
|
7584 |
+
|
mgl@1371
|
7585 |
+ if ( num_insns >= max_insns )
|
mgl@1371
|
7586 |
+ return NULL_RTX;
|
mgl@1371
|
7587 |
+
|
mgl@1371
|
7588 |
+ /* Check if we have an instruction which might be converted to
|
mgl@1371
|
7589 |
+ conditional form if we give it a scratch register to clobber. */
|
mgl@1371
|
7590 |
+ {
|
mgl@1371
|
7591 |
+ rtx clobber_insn;
|
mgl@1371
|
7592 |
+ rtx scratch_reg = gen_reg_rtx (mode);
|
mgl@1371
|
7593 |
+ rtx new_pattern = copy_rtx (pattern);
|
mgl@1371
|
7594 |
+ rtx set_src = SET_SRC (COND_EXEC_CODE (new_pattern));
|
mgl@1371
|
7595 |
+
|
mgl@1371
|
7596 |
+ rtx clobber = gen_rtx_CLOBBER (mode, scratch_reg);
|
mgl@1371
|
7597 |
+ rtx vec[2] = { COND_EXEC_CODE (new_pattern), clobber };
|
mgl@1371
|
7598 |
+ COND_EXEC_CODE (new_pattern) = gen_rtx_PARALLEL (mode, gen_rtvec_v (2, vec));
|
mgl@1371
|
7599 |
+
|
mgl@1371
|
7600 |
+ start_sequence ();
|
mgl@1371
|
7601 |
+ clobber_insn = emit_insn (new_pattern);
|
mgl@1371
|
7602 |
+
|
mgl@1371
|
7603 |
+ if ( recog_memoized (clobber_insn) >= 0
|
mgl@1371
|
7604 |
+ && ( ( GET_RTX_LENGTH (GET_CODE (set_src)) == 2
|
mgl@1371
|
7605 |
+ && CONST_INT_P (XEXP (set_src, 1))
|
mgl@1371
|
7606 |
+ && avr32_const_ok_for_constraint_p (INTVAL (XEXP (set_src, 1)), 'K', "Ks08") )
|
mgl@1371
|
7607 |
+ || !ce_info->else_bb
|
mgl@1371
|
7608 |
+ || current_bb->index == ce_info->else_bb->index ))
|
mgl@1371
|
7609 |
+ {
|
mgl@1371
|
7610 |
+ end_sequence ();
|
mgl@1371
|
7611 |
+ /* Force the insn to be recognized again. */
|
mgl@1371
|
7612 |
+ INSN_CODE (insn) = -1;
|
mgl@1371
|
7613 |
+
|
mgl@1371
|
7614 |
+ /* If this is the first change in this IF-block then
|
mgl@1371
|
7615 |
+ signal that we have made a change. */
|
mgl@1371
|
7616 |
+ if ( ce_info->num_cond_clobber_insns == 0
|
mgl@1371
|
7617 |
+ && ce_info->num_extra_move_insns == 0 )
|
mgl@1371
|
7618 |
+ *num_true_changes += 1;
|
mgl@1371
|
7619 |
+
|
mgl@1371
|
7620 |
+ ce_info->num_cond_clobber_insns++;
|
mgl@1371
|
7621 |
+
|
mgl@1371
|
7622 |
+ if (dump_file)
|
mgl@1371
|
7623 |
+ fprintf (dump_file,
|
mgl@1371
|
7624 |
+ "\nReplacing INSN %d with an insn using a scratch register for later ifcvt passes...\n",
|
mgl@1371
|
7625 |
+ INSN_UID (insn));
|
mgl@1371
|
7626 |
+
|
mgl@1371
|
7627 |
+ return COND_EXEC_CODE (new_pattern);
|
mgl@1371
|
7628 |
+ }
|
mgl@1371
|
7629 |
+ end_sequence ();
|
mgl@1371
|
7630 |
+ }
|
mgl@1371
|
7631 |
+
|
mgl@1371
|
7632 |
+ if ( inputs_set_outside_ifblock )
|
mgl@1371
|
7633 |
+ {
|
mgl@1371
|
7634 |
+ /* Check if the insn before the cmp is an and which used
|
mgl@1371
|
7635 |
+ together with the cmp can be optimized into a bld. If
|
mgl@1371
|
7636 |
+ so then we should try to put the insn before the and
|
mgl@1371
|
7637 |
+ so that we can catch the bld peephole. */
|
mgl@1371
|
7638 |
+ rtx set;
|
mgl@1371
|
7639 |
+ rtx insn_before_cmp_insn = prev_nonnote_insn (cmp_insn);
|
mgl@1371
|
7640 |
+ if (insn_before_cmp_insn
|
mgl@1371
|
7641 |
+ && (set = single_set (insn_before_cmp_insn))
|
mgl@1371
|
7642 |
+ && GET_CODE (SET_SRC (set)) == AND
|
mgl@1371
|
7643 |
+ && one_bit_set_operand (XEXP (SET_SRC (set), 1), SImode)
|
mgl@1371
|
7644 |
+ /* Also make sure that the insn does not set any
|
mgl@1371
|
7645 |
+ of the input operands to the insn we are pulling out. */
|
mgl@1371
|
7646 |
+ && !reg_mentioned_p (SET_DEST (set), SET_SRC (op)) )
|
mgl@1371
|
7647 |
+ cmp_insn = prev_nonnote_insn (cmp_insn);
|
mgl@1371
|
7648 |
+
|
mgl@1371
|
7649 |
+ /* We can try to put the operation outside the if-then-else
|
mgl@1371
|
7650 |
+ blocks and insert a move. */
|
mgl@1371
|
7651 |
+ if ( !insn_invalid_p (insn)
|
mgl@1371
|
7652 |
+ /* Do not allow conditional insns to be moved outside the
|
mgl@1371
|
7653 |
+ if-then-else. */
|
mgl@1371
|
7654 |
+ && !reg_mentioned_p (cc0_rtx, insn)
|
mgl@1371
|
7655 |
+ /* We cannot move memory loads outside of the if-then-else
|
mgl@1371
|
7656 |
+ since the memory access should not be perfomed if the
|
mgl@1371
|
7657 |
+ condition is not met. */
|
mgl@1371
|
7658 |
+ && !mem_mentioned_p (SET_SRC (op)) )
|
mgl@1371
|
7659 |
+ {
|
mgl@1371
|
7660 |
+ rtx scratch_reg = gen_reg_rtx (mode);
|
mgl@1371
|
7661 |
+ rtx op_pattern = copy_rtx (op);
|
mgl@1371
|
7662 |
+ rtx new_insn, seq;
|
mgl@1371
|
7663 |
+ rtx link, prev_link;
|
mgl@1371
|
7664 |
+ op = copy_rtx (op);
|
mgl@1371
|
7665 |
+ /* Emit the operation to a temp reg before the compare,
|
mgl@1371
|
7666 |
+ and emit a move inside the if-then-else, hoping that the
|
mgl@1371
|
7667 |
+ whole if-then-else can be converted to conditional
|
mgl@1371
|
7668 |
+ execution. */
|
mgl@1371
|
7669 |
+ SET_DEST (op_pattern) = scratch_reg;
|
mgl@1371
|
7670 |
+ start_sequence ();
|
mgl@1371
|
7671 |
+ new_insn = emit_insn (op_pattern);
|
mgl@1371
|
7672 |
+ seq = get_insns();
|
mgl@1371
|
7673 |
+ end_sequence ();
|
mgl@1371
|
7674 |
+
|
mgl@1371
|
7675 |
+ /* Check again that the insn is valid. For some insns the insn might
|
mgl@1371
|
7676 |
+ become invalid if the destination register is changed. Ie. for mulacc
|
mgl@1371
|
7677 |
+ operations. */
|
mgl@1371
|
7678 |
+ if ( insn_invalid_p (new_insn) )
|
mgl@1371
|
7679 |
+ return NULL_RTX;
|
mgl@1371
|
7680 |
+
|
mgl@1371
|
7681 |
+ emit_insn_before_setloc (seq, cmp_insn, INSN_LOCATOR (insn));
|
mgl@1371
|
7682 |
+
|
mgl@1371
|
7683 |
+ if (dump_file)
|
mgl@1371
|
7684 |
+ fprintf (dump_file,
|
mgl@1371
|
7685 |
+ "\nMoving INSN %d out of IF-block by adding INSN %d...\n",
|
mgl@1371
|
7686 |
+ INSN_UID (insn), INSN_UID (new_insn));
|
mgl@1371
|
7687 |
+
|
mgl@1371
|
7688 |
+ ce_info->extra_move_insns[ce_info->num_extra_move_insns] = insn;
|
mgl@1371
|
7689 |
+ ce_info->moved_insns[ce_info->num_extra_move_insns] = new_insn;
|
mgl@1371
|
7690 |
+ XEXP (op, 1) = scratch_reg;
|
mgl@1371
|
7691 |
+ /* Force the insn to be recognized again. */
|
mgl@1371
|
7692 |
+ INSN_CODE (insn) = -1;
|
mgl@1371
|
7693 |
+
|
mgl@1371
|
7694 |
+ /* Move REG_DEAD notes to the moved insn. */
|
mgl@1371
|
7695 |
+ prev_link = NULL_RTX;
|
mgl@1371
|
7696 |
+ for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
|
mgl@1371
|
7697 |
+ {
|
mgl@1371
|
7698 |
+ if (REG_NOTE_KIND (link) == REG_DEAD)
|
mgl@1371
|
7699 |
+ {
|
mgl@1371
|
7700 |
+ /* Add the REG_DEAD note to the new insn. */
|
mgl@1371
|
7701 |
+ rtx dead_reg = XEXP (link, 0);
|
mgl@1371
|
7702 |
+ REG_NOTES (new_insn) = gen_rtx_EXPR_LIST (REG_DEAD, dead_reg, REG_NOTES (new_insn));
|
mgl@1371
|
7703 |
+ /* Remove the REG_DEAD note from the insn we convert to a move. */
|
mgl@1371
|
7704 |
+ if ( prev_link )
|
mgl@1371
|
7705 |
+ XEXP (prev_link, 1) = XEXP (link, 1);
|
mgl@1371
|
7706 |
+ else
|
mgl@1371
|
7707 |
+ REG_NOTES (insn) = XEXP (link, 1);
|
mgl@1371
|
7708 |
+ }
|
mgl@1371
|
7709 |
+ else
|
mgl@1371
|
7710 |
+ {
|
mgl@1371
|
7711 |
+ prev_link = link;
|
mgl@1371
|
7712 |
+ }
|
mgl@1371
|
7713 |
+ }
|
mgl@1371
|
7714 |
+ /* Add a REG_DEAD note to signal that the scratch register is dead. */
|
mgl@1371
|
7715 |
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_DEAD, scratch_reg, REG_NOTES (insn));
|
mgl@1371
|
7716 |
+
|
mgl@1371
|
7717 |
+ /* If this is the first change in this IF-block then
|
mgl@1371
|
7718 |
+ signal that we have made a change. */
|
mgl@1371
|
7719 |
+ if ( ce_info->num_cond_clobber_insns == 0
|
mgl@1371
|
7720 |
+ && ce_info->num_extra_move_insns == 0 )
|
mgl@1371
|
7721 |
+ *num_true_changes += 1;
|
mgl@1371
|
7722 |
+
|
mgl@1371
|
7723 |
+ ce_info->num_extra_move_insns++;
|
mgl@1371
|
7724 |
+ return op;
|
mgl@1371
|
7725 |
+ }
|
mgl@1371
|
7726 |
+ }
|
mgl@1371
|
7727 |
+
|
mgl@1371
|
7728 |
+ /* We failed to fixup the insns, so this if-then-else can not be made
|
mgl@1371
|
7729 |
+ conditional. Just return NULL_RTX so that the if-then-else conversion
|
mgl@1371
|
7730 |
+ for this if-then-else will be cancelled. */
|
mgl@1371
|
7731 |
+ return NULL_RTX;
|
mgl@1371
|
7732 |
+ }
|
mgl@1371
|
7733 |
+ end_sequence ();
|
mgl@1371
|
7734 |
+ return op;
|
mgl@1371
|
7735 |
+ }
|
mgl@1371
|
7736 |
+
|
mgl@1371
|
7737 |
+ /* Signal that we have started if conversion after reload, which means
|
mgl@1371
|
7738 |
+ that it should be safe to split all the predicable clobber insns which
|
mgl@1371
|
7739 |
+ did not become cond_exec back into a simpler form if possible. */
|
mgl@1371
|
7740 |
+ cfun->machine->ifcvt_after_reload = 1;
|
mgl@1371
|
7741 |
+
|
mgl@1371
|
7742 |
+ return pattern;
|
mgl@1371
|
7743 |
+}
|
mgl@1371
|
7744 |
+
|
mgl@1371
|
7745 |
+
|
mgl@1371
|
7746 |
+void
|
mgl@1371
|
7747 |
+avr32_ifcvt_modify_cancel ( ce_if_block_t *ce_info,
|
mgl@1371
|
7748 |
+ int *num_true_changes)
|
mgl@1371
|
7749 |
+{
|
mgl@1371
|
7750 |
+ int n;
|
mgl@1371
|
7751 |
+
|
mgl@1371
|
7752 |
+ if ( ce_info->num_extra_move_insns > 0
|
mgl@1371
|
7753 |
+ && ce_info->num_cond_clobber_insns == 0)
|
mgl@1371
|
7754 |
+ /* Signal that we did not do any changes after all. */
|
mgl@1371
|
7755 |
+ *num_true_changes -= 1;
|
mgl@1371
|
7756 |
+
|
mgl@1371
|
7757 |
+ /* Remove any inserted move insns. */
|
mgl@1371
|
7758 |
+ for ( n = 0; n < ce_info->num_extra_move_insns; n++ )
|
mgl@1371
|
7759 |
+ {
|
mgl@1371
|
7760 |
+ rtx link, prev_link;
|
mgl@1371
|
7761 |
+
|
mgl@1371
|
7762 |
+ /* Remove REG_DEAD note since we are not needing the scratch register anyway. */
|
mgl@1371
|
7763 |
+ prev_link = NULL_RTX;
|
mgl@1371
|
7764 |
+ for (link = REG_NOTES (ce_info->extra_move_insns[n]); link; link = XEXP (link, 1))
|
mgl@1371
|
7765 |
+ {
|
mgl@1371
|
7766 |
+ if (REG_NOTE_KIND (link) == REG_DEAD)
|
mgl@1371
|
7767 |
+ {
|
mgl@1371
|
7768 |
+ if ( prev_link )
|
mgl@1371
|
7769 |
+ XEXP (prev_link, 1) = XEXP (link, 1);
|
mgl@1371
|
7770 |
+ else
|
mgl@1371
|
7771 |
+ REG_NOTES (ce_info->extra_move_insns[n]) = XEXP (link, 1);
|
mgl@1371
|
7772 |
+ }
|
mgl@1371
|
7773 |
+ else
|
mgl@1371
|
7774 |
+ {
|
mgl@1371
|
7775 |
+ prev_link = link;
|
mgl@1371
|
7776 |
+ }
|
mgl@1371
|
7777 |
+ }
|
mgl@1371
|
7778 |
+
|
mgl@1371
|
7779 |
+ /* Revert all reg_notes for the moved insn. */
|
mgl@1371
|
7780 |
+ for (link = REG_NOTES (ce_info->moved_insns[n]); link; link = XEXP (link, 1))
|
mgl@1371
|
7781 |
+ {
|
mgl@1371
|
7782 |
+ REG_NOTES (ce_info->extra_move_insns[n]) = gen_rtx_EXPR_LIST (REG_NOTE_KIND (link),
|
mgl@1371
|
7783 |
+ XEXP (link, 0),
|
mgl@1371
|
7784 |
+ REG_NOTES (ce_info->extra_move_insns[n]));
|
mgl@1371
|
7785 |
+ }
|
mgl@1371
|
7786 |
+
|
mgl@1371
|
7787 |
+ /* Remove the moved insn. */
|
mgl@1371
|
7788 |
+ remove_insn ( ce_info->moved_insns[n] );
|
mgl@1371
|
7789 |
+ }
|
mgl@1371
|
7790 |
+}
|
mgl@1371
|
7791 |
+
|
mgl@1371
|
7792 |
+/* Function returning TRUE if INSN with OPERANDS is a splittable
|
mgl@1371
|
7793 |
+ conditional immediate clobber insn. We assume that the insn is
|
mgl@1371
|
7794 |
+ already a conditional immediate clobber insns and do not check
|
mgl@1371
|
7795 |
+ for that. */
|
mgl@1371
|
7796 |
+int
|
mgl@1371
|
7797 |
+avr32_cond_imm_clobber_splittable (rtx insn,
|
mgl@1371
|
7798 |
+ rtx operands[])
|
mgl@1371
|
7799 |
+{
|
mgl@1371
|
7800 |
+ if ( (REGNO (operands[0]) != REGNO (operands[1]))
|
mgl@1371
|
7801 |
+ && (logical_binary_operator (SET_SRC (XVECEXP (PATTERN (insn),0,0)), VOIDmode)
|
mgl@1371
|
7802 |
+ || (GET_CODE (SET_SRC (XVECEXP (PATTERN (insn),0,0))) == PLUS
|
mgl@1371
|
7803 |
+ && !avr32_const_ok_for_constraint_p (INTVAL (operands[2]), 'I', "Is16"))
|
mgl@1371
|
7804 |
+ || (GET_CODE (SET_SRC (XVECEXP (PATTERN (insn),0,0))) == MINUS
|
mgl@1371
|
7805 |
+ && !avr32_const_ok_for_constraint_p (INTVAL (operands[2]), 'K', "Ks16"))) )
|
mgl@1371
|
7806 |
+ return FALSE;
|
mgl@1371
|
7807 |
+
|
mgl@1371
|
7808 |
+ return TRUE;
|
mgl@1371
|
7809 |
+}
|
mgl@1371
|
7810 |
+
|
mgl@1371
|
7811 |
+/* Function for getting an integer value from a const_int or const_double
|
mgl@1371
|
7812 |
+ expression regardless of the HOST_WIDE_INT size. Each target cpu word
|
mgl@1371
|
7813 |
+ will be put into the val array where the LSW will be stored at the lowest
|
mgl@1371
|
7814 |
+ address and so forth. Assumes that const_expr is either a const_int or
|
mgl@1371
|
7815 |
+ const_double. Only valid for modes which have sizes that are a multiple
|
mgl@1371
|
7816 |
+ of the word size.
|
mgl@1371
|
7817 |
+*/
|
mgl@1371
|
7818 |
+void
|
mgl@1371
|
7819 |
+avr32_get_intval (enum machine_mode mode,
|
mgl@1371
|
7820 |
+ rtx const_expr,
|
mgl@1371
|
7821 |
+ HOST_WIDE_INT *val)
|
mgl@1371
|
7822 |
+{
|
mgl@1371
|
7823 |
+ int words_in_mode = GET_MODE_SIZE (mode)/UNITS_PER_WORD;
|
mgl@1371
|
7824 |
+ const int words_in_const_int = HOST_BITS_PER_WIDE_INT / BITS_PER_WORD;
|
mgl@1371
|
7825 |
+
|
mgl@1371
|
7826 |
+ if ( GET_CODE(const_expr) == CONST_DOUBLE ){
|
mgl@1371
|
7827 |
+ HOST_WIDE_INT hi = CONST_DOUBLE_HIGH(const_expr);
|
mgl@1371
|
7828 |
+ HOST_WIDE_INT lo = CONST_DOUBLE_LOW(const_expr);
|
mgl@1371
|
7829 |
+ /* Evaluate hi and lo values of const_double. */
|
mgl@1371
|
7830 |
+ avr32_get_intval (mode_for_size (HOST_BITS_PER_WIDE_INT, MODE_INT, 0),
|
mgl@1371
|
7831 |
+ GEN_INT (lo),
|
mgl@1371
|
7832 |
+ &val[0]);
|
mgl@1371
|
7833 |
+ avr32_get_intval (mode_for_size (HOST_BITS_PER_WIDE_INT, MODE_INT, 0),
|
mgl@1371
|
7834 |
+ GEN_INT (hi),
|
mgl@1371
|
7835 |
+ &val[words_in_const_int]);
|
mgl@1371
|
7836 |
+ } else if ( GET_CODE(const_expr) == CONST_INT ){
|
mgl@1371
|
7837 |
+ HOST_WIDE_INT value = INTVAL(const_expr);
|
mgl@1371
|
7838 |
+ int word;
|
mgl@1371
|
7839 |
+ for ( word = 0; (word < words_in_mode) && (word < words_in_const_int); word++ ){
|
mgl@1371
|
7840 |
+ /* Shift word up to the MSW and shift down again to extract the
|
mgl@1371
|
7841 |
+ word and sign-extend. */
|
mgl@1371
|
7842 |
+ int lshift = (words_in_const_int - word - 1) * BITS_PER_WORD;
|
mgl@1371
|
7843 |
+ int rshift = (words_in_const_int-1) * BITS_PER_WORD;
|
mgl@1371
|
7844 |
+ val[word] = (value << lshift) >> rshift;
|
mgl@1371
|
7845 |
+ }
|
mgl@1371
|
7846 |
+
|
mgl@1371
|
7847 |
+ for ( ; word < words_in_mode; word++ ){
|
mgl@1371
|
7848 |
+ /* Just put the sign bits in the remaining words. */
|
mgl@1371
|
7849 |
+ val[word] = value < 0 ? -1 : 0;
|
mgl@1371
|
7850 |
+ }
|
mgl@1371
|
7851 |
+ }
|
mgl@1371
|
7852 |
+}
|
mgl@1371
|
7853 |
+
|
mgl@1371
|
7854 |
+void
|
mgl@1371
|
7855 |
+avr32_split_const_expr (enum machine_mode mode,
|
mgl@1371
|
7856 |
+ enum machine_mode new_mode,
|
mgl@1371
|
7857 |
+ rtx expr,
|
mgl@1371
|
7858 |
+ rtx *split_expr)
|
mgl@1371
|
7859 |
+{
|
mgl@1371
|
7860 |
+ int i, word;
|
mgl@1371
|
7861 |
+ int words_in_intval = GET_MODE_SIZE (mode)/UNITS_PER_WORD;
|
mgl@1371
|
7862 |
+ int words_in_split_values = GET_MODE_SIZE (new_mode)/UNITS_PER_WORD;
|
mgl@1371
|
7863 |
+ const int words_in_const_int = HOST_BITS_PER_WIDE_INT / BITS_PER_WORD;
|
mgl@1371
|
7864 |
+ HOST_WIDE_INT *val = alloca (words_in_intval * UNITS_PER_WORD);
|
mgl@1371
|
7865 |
+
|
mgl@1371
|
7866 |
+ avr32_get_intval (mode, expr, val);
|
mgl@1371
|
7867 |
+
|
mgl@1371
|
7868 |
+ for ( i=0; i < (words_in_intval/words_in_split_values); i++ )
|
mgl@1371
|
7869 |
+ {
|
mgl@1371
|
7870 |
+ HOST_WIDE_INT value_lo = 0, value_hi = 0;
|
mgl@1371
|
7871 |
+ for ( word = 0; word < words_in_split_values; word++ )
|
mgl@1371
|
7872 |
+ {
|
mgl@1371
|
7873 |
+ if ( word >= words_in_const_int )
|
mgl@1371
|
7874 |
+ value_hi |= ((val[i * words_in_split_values + word] &
|
mgl@1371
|
7875 |
+ (((HOST_WIDE_INT)1 << BITS_PER_WORD)-1))
|
mgl@1371
|
7876 |
+ << (BITS_PER_WORD * (word - words_in_const_int)));
|
mgl@1371
|
7877 |
+ else
|
mgl@1371
|
7878 |
+ value_lo |= ((val[i * words_in_split_values + word] &
|
mgl@1371
|
7879 |
+ (((HOST_WIDE_INT)1 << BITS_PER_WORD)-1))
|
mgl@1371
|
7880 |
+ << (BITS_PER_WORD * word));
|
mgl@1371
|
7881 |
+ }
|
mgl@1371
|
7882 |
+ split_expr[i] = immed_double_const(value_lo, value_hi, new_mode);
|
mgl@1371
|
7883 |
+ }
|
mgl@1371
|
7884 |
+}
|
mgl@1371
|
7885 |
+
|
mgl@1371
|
7886 |
+
|
mgl@1371
|
7887 |
+/* Set up library functions to comply to AVR32 ABI */
|
mgl@1371
|
7888 |
+
|
mgl@1371
|
7889 |
+static void
|
mgl@1371
|
7890 |
+avr32_init_libfuncs (void)
|
mgl@1371
|
7891 |
+{
|
mgl@1371
|
7892 |
+ /* Convert gcc run-time function names to AVR32 ABI names */
|
mgl@1371
|
7893 |
+
|
mgl@1371
|
7894 |
+ /* Double-precision floating-point arithmetic. */
|
mgl@1371
|
7895 |
+ set_optab_libfunc (neg_optab, DFmode, NULL);
|
mgl@1371
|
7896 |
+
|
mgl@1371
|
7897 |
+ /* Double-precision comparisons. */
|
mgl@1371
|
7898 |
+ set_optab_libfunc (eq_optab, DFmode, "__avr32_f64_cmp_eq");
|
mgl@1371
|
7899 |
+ set_optab_libfunc (ne_optab, DFmode, NULL);
|
mgl@1371
|
7900 |
+ set_optab_libfunc (lt_optab, DFmode, "__avr32_f64_cmp_lt");
|
mgl@1371
|
7901 |
+ set_optab_libfunc (le_optab, DFmode, NULL);
|
mgl@1371
|
7902 |
+ set_optab_libfunc (ge_optab, DFmode, "__avr32_f64_cmp_ge");
|
mgl@1371
|
7903 |
+ set_optab_libfunc (gt_optab, DFmode, NULL);
|
mgl@1371
|
7904 |
+
|
mgl@1371
|
7905 |
+ /* Single-precision floating-point arithmetic. */
|
mgl@1371
|
7906 |
+ set_optab_libfunc (smul_optab, SFmode, "__avr32_f32_mul");
|
mgl@1371
|
7907 |
+ set_optab_libfunc (neg_optab, SFmode, NULL);
|
mgl@1371
|
7908 |
+
|
mgl@1371
|
7909 |
+ /* Single-precision comparisons. */
|
mgl@1371
|
7910 |
+ set_optab_libfunc (eq_optab, SFmode, "__avr32_f32_cmp_eq");
|
mgl@1371
|
7911 |
+ set_optab_libfunc (ne_optab, SFmode, NULL);
|
mgl@1371
|
7912 |
+ set_optab_libfunc (lt_optab, SFmode, "__avr32_f32_cmp_lt");
|
mgl@1371
|
7913 |
+ set_optab_libfunc (le_optab, SFmode, NULL);
|
mgl@1371
|
7914 |
+ set_optab_libfunc (ge_optab, SFmode, "__avr32_f32_cmp_ge");
|
mgl@1371
|
7915 |
+ set_optab_libfunc (gt_optab, SFmode, NULL);
|
mgl@1371
|
7916 |
+
|
mgl@1371
|
7917 |
+ /* Floating-point to integer conversions. */
|
mgl@1371
|
7918 |
+ set_conv_libfunc (sfix_optab, SImode, DFmode, "__avr32_f64_to_s32");
|
mgl@1371
|
7919 |
+ set_conv_libfunc (ufix_optab, SImode, DFmode, "__avr32_f64_to_u32");
|
mgl@1371
|
7920 |
+ set_conv_libfunc (sfix_optab, DImode, DFmode, "__avr32_f64_to_s64");
|
mgl@1371
|
7921 |
+ set_conv_libfunc (ufix_optab, DImode, DFmode, "__avr32_f64_to_u64");
|
mgl@1371
|
7922 |
+ set_conv_libfunc (sfix_optab, SImode, SFmode, "__avr32_f32_to_s32");
|
mgl@1371
|
7923 |
+ set_conv_libfunc (ufix_optab, SImode, SFmode, "__avr32_f32_to_u32");
|
mgl@1371
|
7924 |
+ set_conv_libfunc (sfix_optab, DImode, SFmode, "__avr32_f32_to_s64");
|
mgl@1371
|
7925 |
+ set_conv_libfunc (ufix_optab, DImode, SFmode, "__avr32_f32_to_u64");
|
mgl@1371
|
7926 |
+
|
mgl@1371
|
7927 |
+ /* Conversions between floating types. */
|
mgl@1371
|
7928 |
+ set_conv_libfunc (trunc_optab, SFmode, DFmode, "__avr32_f64_to_f32");
|
mgl@1371
|
7929 |
+ set_conv_libfunc (sext_optab, DFmode, SFmode, "__avr32_f32_to_f64");
|
mgl@1371
|
7930 |
+
|
mgl@1371
|
7931 |
+ /* Integer to floating-point conversions. Table 8. */
|
mgl@1371
|
7932 |
+ set_conv_libfunc (sfloat_optab, DFmode, SImode, "__avr32_s32_to_f64");
|
mgl@1371
|
7933 |
+ set_conv_libfunc (sfloat_optab, DFmode, DImode, "__avr32_s64_to_f64");
|
mgl@1371
|
7934 |
+ set_conv_libfunc (sfloat_optab, SFmode, SImode, "__avr32_s32_to_f32");
|
mgl@1371
|
7935 |
+ set_conv_libfunc (sfloat_optab, SFmode, DImode, "__avr32_s64_to_f32");
|
mgl@1371
|
7936 |
+ set_conv_libfunc (ufloat_optab, DFmode, SImode, "__avr32_u32_to_f64");
|
mgl@1371
|
7937 |
+ set_conv_libfunc (ufloat_optab, SFmode, SImode, "__avr32_u32_to_f32");
|
mgl@1371
|
7938 |
+ /* TODO: Add these to gcc library functions */
|
mgl@1371
|
7939 |
+ //set_conv_libfunc (ufloat_optab, DFmode, DImode, NULL);
|
mgl@1371
|
7940 |
+ //set_conv_libfunc (ufloat_optab, SFmode, DImode, NULL);
|
mgl@1371
|
7941 |
+
|
mgl@1371
|
7942 |
+ /* Long long. Table 9. */
|
mgl@1371
|
7943 |
+ set_optab_libfunc (smul_optab, DImode, "__avr32_mul64");
|
mgl@1371
|
7944 |
+ set_optab_libfunc (sdiv_optab, DImode, "__avr32_sdiv64");
|
mgl@1371
|
7945 |
+ set_optab_libfunc (udiv_optab, DImode, "__avr32_udiv64");
|
mgl@1371
|
7946 |
+ set_optab_libfunc (smod_optab, DImode, "__avr32_smod64");
|
mgl@1371
|
7947 |
+ set_optab_libfunc (umod_optab, DImode, "__avr32_umod64");
|
mgl@1371
|
7948 |
+ set_optab_libfunc (ashl_optab, DImode, "__avr32_lsl64");
|
mgl@1371
|
7949 |
+ set_optab_libfunc (lshr_optab, DImode, "__avr32_lsr64");
|
mgl@1371
|
7950 |
+ set_optab_libfunc (ashr_optab, DImode, "__avr32_asr64");
|
mgl@1371
|
7951 |
+
|
mgl@1371
|
7952 |
+ /* Floating point library functions which have fast versions. */
|
mgl@1371
|
7953 |
+ if ( TARGET_FAST_FLOAT )
|
mgl@1371
|
7954 |
+ {
|
mgl@1371
|
7955 |
+ set_optab_libfunc (sdiv_optab, DFmode, "__avr32_f64_div_fast");
|
mgl@1371
|
7956 |
+ set_optab_libfunc (smul_optab, DFmode, "__avr32_f64_mul_fast");
|
mgl@1371
|
7957 |
+ set_optab_libfunc (add_optab, DFmode, "__avr32_f64_add_fast");
|
mgl@1371
|
7958 |
+ set_optab_libfunc (sub_optab, DFmode, "__avr32_f64_sub_fast");
|
mgl@1371
|
7959 |
+ set_optab_libfunc (add_optab, SFmode, "__avr32_f32_add_fast");
|
mgl@1371
|
7960 |
+ set_optab_libfunc (sub_optab, SFmode, "__avr32_f32_sub_fast");
|
mgl@1371
|
7961 |
+ set_optab_libfunc (sdiv_optab, SFmode, "__avr32_f32_div_fast");
|
mgl@1371
|
7962 |
+ }
|
mgl@1371
|
7963 |
+ else
|
mgl@1371
|
7964 |
+ {
|
mgl@1371
|
7965 |
+ set_optab_libfunc (sdiv_optab, DFmode, "__avr32_f64_div");
|
mgl@1371
|
7966 |
+ set_optab_libfunc (smul_optab, DFmode, "__avr32_f64_mul");
|
mgl@1371
|
7967 |
+ set_optab_libfunc (add_optab, DFmode, "__avr32_f64_add");
|
mgl@1371
|
7968 |
+ set_optab_libfunc (sub_optab, DFmode, "__avr32_f64_sub");
|
mgl@1371
|
7969 |
+ set_optab_libfunc (add_optab, SFmode, "__avr32_f32_add");
|
mgl@1371
|
7970 |
+ set_optab_libfunc (sub_optab, SFmode, "__avr32_f32_sub");
|
mgl@1371
|
7971 |
+ set_optab_libfunc (sdiv_optab, SFmode, "__avr32_f32_div");
|
mgl@1371
|
7972 |
+ }
|
mgl@1371
|
7973 |
+}
|
mgl@1371
|
7974 |
--- /dev/null
|
mgl@1371
|
7975 |
+++ b/gcc/config/avr32/avr32-elf.h
|
mgl@1371
|
7976 |
@@ -0,0 +1,84 @@
|
mgl@1371
|
7977 |
+/*
|
mgl@1371
|
7978 |
+ Elf specific definitions.
|
mgl@1371
|
7979 |
+ Copyright 2003-2006 Atmel Corporation.
|
mgl@1371
|
7980 |
+
|
mgl@1371
|
7981 |
+ Written by Ronny Pedersen, Atmel Norway, <rpedersen@atmel.com>
|
mgl@1371
|
7982 |
+
|
mgl@1371
|
7983 |
+ This file is part of GCC.
|
mgl@1371
|
7984 |
+
|
mgl@1371
|
7985 |
+ This program is free software; you can redistribute it and/or modify
|
mgl@1371
|
7986 |
+ it under the terms of the GNU General Public License as published by
|
mgl@1371
|
7987 |
+ the Free Software Foundation; either version 2 of the License, or
|
mgl@1371
|
7988 |
+ (at your option) any later version.
|
mgl@1371
|
7989 |
+
|
mgl@1371
|
7990 |
+ This program is distributed in the hope that it will be useful,
|
mgl@1371
|
7991 |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
mgl@1371
|
7992 |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
mgl@1371
|
7993 |
+ GNU General Public License for more details.
|
mgl@1371
|
7994 |
+
|
mgl@1371
|
7995 |
+ You should have received a copy of the GNU General Public License
|
mgl@1371
|
7996 |
+ along with this program; if not, write to the Free Software
|
mgl@1371
|
7997 |
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
mgl@1371
|
7998 |
+
|
mgl@1371
|
7999 |
+
|
mgl@1371
|
8000 |
+/*****************************************************************************
|
mgl@1371
|
8001 |
+ * Controlling the Compilator Driver, 'gcc'
|
mgl@1371
|
8002 |
+ *****************************************************************************/
|
mgl@1371
|
8003 |
+
|
mgl@1371
|
8004 |
+/* Run-time Target Specification. */
|
mgl@1371
|
8005 |
+#undef TARGET_VERSION
|
mgl@1371
|
8006 |
+#define TARGET_VERSION fputs (" (AVR32 GNU with ELF)", stderr);
|
mgl@1371
|
8007 |
+
|
mgl@1371
|
8008 |
+/*
|
mgl@1371
|
8009 |
+Another C string constant used much like LINK_SPEC. The
|
mgl@1371
|
8010 |
+difference between the two is that STARTFILE_SPEC is used at
|
mgl@1371
|
8011 |
+the very beginning of the command given to the linker.
|
mgl@1371
|
8012 |
+
|
mgl@1371
|
8013 |
+If this macro is not defined, a default is provided that loads the
|
mgl@1371
|
8014 |
+standard C startup file from the usual place. See gcc.c.
|
mgl@1371
|
8015 |
+*/
|
mgl@1371
|
8016 |
+#undef STARTFILE_SPEC
|
mgl@1371
|
8017 |
+#define STARTFILE_SPEC "crt0%O%s crti%O%s crtbegin%O%s"
|
mgl@1371
|
8018 |
+
|
mgl@1371
|
8019 |
+#undef LINK_SPEC
|
mgl@1371
|
8020 |
+#define LINK_SPEC "%{muse-oscall:--defsym __do_not_use_oscall_coproc__=0} %{mrelax|O*:%{mno-relax|O0|O1: ;:--relax}} %{mpart=uc3a3revd:-mavr32elf_uc3a3256s;:%{mpart=*:-mavr32elf_%*}} %{mcpu=*:-mavr32elf_%*}"
|
mgl@1371
|
8021 |
+
|
mgl@1371
|
8022 |
+
|
mgl@1371
|
8023 |
+/*
|
mgl@1371
|
8024 |
+Another C string constant used much like LINK_SPEC. The
|
mgl@1371
|
8025 |
+difference between the two is that ENDFILE_SPEC is used at
|
mgl@1371
|
8026 |
+the very end of the command given to the linker.
|
mgl@1371
|
8027 |
+
|
mgl@1371
|
8028 |
+Do not define this macro if it does not need to do anything.
|
mgl@1371
|
8029 |
+*/
|
mgl@1371
|
8030 |
+#undef ENDFILE_SPEC
|
mgl@1371
|
8031 |
+#define ENDFILE_SPEC "crtend%O%s crtn%O%s"
|
mgl@1371
|
8032 |
+
|
mgl@1371
|
8033 |
+
|
mgl@1371
|
8034 |
+/* Target CPU builtins. */
|
mgl@1371
|
8035 |
+#define TARGET_CPU_CPP_BUILTINS() \
|
mgl@1371
|
8036 |
+ do \
|
mgl@1371
|
8037 |
+ { \
|
mgl@1371
|
8038 |
+ builtin_define ("__avr32__"); \
|
mgl@1371
|
8039 |
+ builtin_define ("__AVR32__"); \
|
mgl@1371
|
8040 |
+ builtin_define ("__AVR32_ELF__"); \
|
mgl@1371
|
8041 |
+ builtin_define (avr32_part->macro); \
|
mgl@1371
|
8042 |
+ builtin_define (avr32_arch->macro); \
|
mgl@1371
|
8043 |
+ if (avr32_arch->uarch_type == UARCH_TYPE_AVR32A) \
|
mgl@1371
|
8044 |
+ builtin_define ("__AVR32_AVR32A__"); \
|
mgl@1371
|
8045 |
+ else \
|
mgl@1371
|
8046 |
+ builtin_define ("__AVR32_AVR32B__"); \
|
mgl@1371
|
8047 |
+ if (TARGET_UNALIGNED_WORD) \
|
mgl@1371
|
8048 |
+ builtin_define ("__AVR32_HAS_UNALIGNED_WORD__"); \
|
mgl@1371
|
8049 |
+ if (TARGET_SIMD) \
|
mgl@1371
|
8050 |
+ builtin_define ("__AVR32_HAS_SIMD__"); \
|
mgl@1371
|
8051 |
+ if (TARGET_DSP) \
|
mgl@1371
|
8052 |
+ builtin_define ("__AVR32_HAS_DSP__"); \
|
mgl@1371
|
8053 |
+ if (TARGET_RMW) \
|
mgl@1371
|
8054 |
+ builtin_define ("__AVR32_HAS_RMW__"); \
|
mgl@1371
|
8055 |
+ if (TARGET_BRANCH_PRED) \
|
mgl@1371
|
8056 |
+ builtin_define ("__AVR32_HAS_BRANCH_PRED__"); \
|
mgl@1371
|
8057 |
+ if (TARGET_FAST_FLOAT) \
|
mgl@1371
|
8058 |
+ builtin_define ("__AVR32_FAST_FLOAT__"); \
|
mgl@1371
|
8059 |
+ } \
|
mgl@1371
|
8060 |
+ while (0)
|
mgl@1371
|
8061 |
--- /dev/null
|
mgl@1371
|
8062 |
+++ b/gcc/config/avr32/avr32.h
|
mgl@1371
|
8063 |
@@ -0,0 +1,3347 @@
|
mgl@1371
|
8064 |
+/*
|
mgl@1371
|
8065 |
+ Definitions of target machine for AVR32.
|
mgl@1371
|
8066 |
+ Copyright 2003-2006 Atmel Corporation.
|
mgl@1371
|
8067 |
+
|
mgl@1371
|
8068 |
+ Written by Ronny Pedersen, Atmel Norway, <rpedersen@atmel.com>
|
mgl@1371
|
8069 |
+ Initial porting by Anders �dland.
|
mgl@1371
|
8070 |
+
|
mgl@1371
|
8071 |
+ This file is part of GCC.
|
mgl@1371
|
8072 |
+
|
mgl@1371
|
8073 |
+ This program is free software; you can redistribute it and/or modify
|
mgl@1371
|
8074 |
+ it under the terms of the GNU General Public License as published by
|
mgl@1371
|
8075 |
+ the Free Software Foundation; either version 2 of the License, or
|
mgl@1371
|
8076 |
+ (at your option) any later version.
|
mgl@1371
|
8077 |
+
|
mgl@1371
|
8078 |
+ This program is distributed in the hope that it will be useful,
|
mgl@1371
|
8079 |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
mgl@1371
|
8080 |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
mgl@1371
|
8081 |
+ GNU General Public License for more details.
|
mgl@1371
|
8082 |
+
|
mgl@1371
|
8083 |
+ You should have received a copy of the GNU General Public License
|
mgl@1371
|
8084 |
+ along with this program; if not, write to the Free Software
|
mgl@1371
|
8085 |
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
mgl@1371
|
8086 |
+
|
mgl@1371
|
8087 |
+#ifndef GCC_AVR32_H
|
mgl@1371
|
8088 |
+#define GCC_AVR32_H
|
mgl@1371
|
8089 |
+
|
mgl@1371
|
8090 |
+
|
mgl@1371
|
8091 |
+#ifndef OBJECT_FORMAT_ELF
|
mgl@1371
|
8092 |
+#error avr32.h included before elfos.h
|
mgl@1371
|
8093 |
+#endif
|
mgl@1371
|
8094 |
+
|
mgl@1371
|
8095 |
+#ifndef LOCAL_LABEL_PREFIX
|
mgl@1371
|
8096 |
+#define LOCAL_LABEL_PREFIX "."
|
mgl@1371
|
8097 |
+#endif
|
mgl@1371
|
8098 |
+
|
mgl@1371
|
8099 |
+#ifndef SUBTARGET_CPP_SPEC
|
mgl@1371
|
8100 |
+#define SUBTARGET_CPP_SPEC "-D__ELF__"
|
mgl@1371
|
8101 |
+#endif
|
mgl@1371
|
8102 |
+
|
mgl@1371
|
8103 |
+
|
mgl@1371
|
8104 |
+extern struct rtx_def *avr32_compare_op0;
|
mgl@1371
|
8105 |
+extern struct rtx_def *avr32_compare_op1;
|
mgl@1371
|
8106 |
+
|
mgl@1371
|
8107 |
+
|
mgl@1371
|
8108 |
+extern struct rtx_def *avr32_acc_cache;
|
mgl@1371
|
8109 |
+
|
mgl@1371
|
8110 |
+/* cache instruction op5 codes */
|
mgl@1371
|
8111 |
+#define AVR32_CACHE_INVALIDATE_ICACHE 1
|
mgl@1371
|
8112 |
+
|
mgl@1371
|
8113 |
+/* These bits describe the different types of function supported
|
mgl@1371
|
8114 |
+ by the AVR32 backend. They are exclusive. ie a function cannot be both a
|
mgl@1371
|
8115 |
+ normal function and an interworked function, for example. Knowing the
|
mgl@1371
|
8116 |
+ type of a function is important for determining its prologue and
|
mgl@1371
|
8117 |
+ epilogue sequences.
|
mgl@1371
|
8118 |
+ Note value 7 is currently unassigned. Also note that the interrupt
|
mgl@1371
|
8119 |
+ function types all have bit 2 set, so that they can be tested for easily.
|
mgl@1371
|
8120 |
+ Note that 0 is deliberately chosen for AVR32_FT_UNKNOWN so that when the
|
mgl@1371
|
8121 |
+ machine_function structure is initialized (to zero) func_type will
|
mgl@1371
|
8122 |
+ default to unknown. This will force the first use of avr32_current_func_type
|
mgl@1371
|
8123 |
+ to call avr32_compute_func_type. */
|
mgl@1371
|
8124 |
+#define AVR32_FT_UNKNOWN 0 /* Type has not yet been determined.
|
mgl@1371
|
8125 |
+ */
|
mgl@1371
|
8126 |
+#define AVR32_FT_NORMAL 1 /* Your normal, straightforward
|
mgl@1371
|
8127 |
+ function. */
|
mgl@1371
|
8128 |
+#define AVR32_FT_ACALL 2 /* An acall function. */
|
mgl@1371
|
8129 |
+#define AVR32_FT_EXCEPTION_HANDLER 3 /* A C++ exception handler. */
|
mgl@1371
|
8130 |
+#define AVR32_FT_ISR_FULL 4 /* A fully shadowed interrupt mode. */
|
mgl@1371
|
8131 |
+#define AVR32_FT_ISR_HALF 5 /* A half shadowed interrupt mode. */
|
mgl@1371
|
8132 |
+#define AVR32_FT_ISR_NONE 6 /* No shadow registers. */
|
mgl@1371
|
8133 |
+
|
mgl@1371
|
8134 |
+#define AVR32_FT_TYPE_MASK ((1 << 3) - 1)
|
mgl@1371
|
8135 |
+
|
mgl@1371
|
8136 |
+/* In addition functions can have several type modifiers,
|
mgl@1371
|
8137 |
+ outlined by these bit masks: */
|
mgl@1371
|
8138 |
+#define AVR32_FT_INTERRUPT (1 << 2) /* Note overlap with FT_ISR
|
mgl@1371
|
8139 |
+ and above. */
|
mgl@1371
|
8140 |
+#define AVR32_FT_NAKED (1 << 3) /* No prologue or epilogue. */
|
mgl@1371
|
8141 |
+#define AVR32_FT_VOLATILE (1 << 4) /* Does not return. */
|
mgl@1371
|
8142 |
+#define AVR32_FT_NESTED (1 << 5) /* Embedded inside another
|
mgl@1371
|
8143 |
+ func. */
|
mgl@1371
|
8144 |
+
|
mgl@1371
|
8145 |
+/* Some macros to test these flags. */
|
mgl@1371
|
8146 |
+#define AVR32_FUNC_TYPE(t) (t & AVR32_FT_TYPE_MASK)
|
mgl@1371
|
8147 |
+#define IS_INTERRUPT(t) (t & AVR32_FT_INTERRUPT)
|
mgl@1371
|
8148 |
+#define IS_VOLATILE(t) (t & AVR32_FT_VOLATILE)
|
mgl@1371
|
8149 |
+#define IS_NAKED(t) (t & AVR32_FT_NAKED)
|
mgl@1371
|
8150 |
+#define IS_NESTED(t) (t & AVR32_FT_NESTED)
|
mgl@1371
|
8151 |
+
|
mgl@1371
|
8152 |
+#define SYMBOL_FLAG_RMW_ADDR_SHIFT SYMBOL_FLAG_MACH_DEP_SHIFT
|
mgl@1371
|
8153 |
+#define SYMBOL_REF_RMW_ADDR(RTX) \
|
mgl@1371
|
8154 |
+ ((SYMBOL_REF_FLAGS (RTX) & (1 << SYMBOL_FLAG_RMW_ADDR_SHIFT)) != 0)
|
mgl@1371
|
8155 |
+
|
mgl@1371
|
8156 |
+
|
mgl@1371
|
8157 |
+typedef struct minipool_labels
|
mgl@1371
|
8158 |
+GTY ((chain_next ("%h.next"), chain_prev ("%h.prev")))
|
mgl@1371
|
8159 |
+{
|
mgl@1371
|
8160 |
+ rtx label;
|
mgl@1371
|
8161 |
+ struct minipool_labels *prev;
|
mgl@1371
|
8162 |
+ struct minipool_labels *next;
|
mgl@1371
|
8163 |
+} minipool_labels;
|
mgl@1371
|
8164 |
+
|
mgl@1371
|
8165 |
+/* A C structure for machine-specific, per-function data.
|
mgl@1371
|
8166 |
+ This is added to the cfun structure. */
|
mgl@1371
|
8167 |
+
|
mgl@1371
|
8168 |
+typedef struct machine_function
|
mgl@1371
|
8169 |
+GTY (())
|
mgl@1371
|
8170 |
+{
|
mgl@1371
|
8171 |
+ /* Records the type of the current function. */
|
mgl@1371
|
8172 |
+ unsigned long func_type;
|
mgl@1371
|
8173 |
+ /* List of minipool labels, use for checking if code label is valid in a
|
mgl@1371
|
8174 |
+ memory expression */
|
mgl@1371
|
8175 |
+ minipool_labels *minipool_label_head;
|
mgl@1371
|
8176 |
+ minipool_labels *minipool_label_tail;
|
mgl@1371
|
8177 |
+ int ifcvt_after_reload;
|
mgl@1371
|
8178 |
+} machine_function;
|
mgl@1371
|
8179 |
+
|
mgl@1371
|
8180 |
+/* Initialize data used by insn expanders. This is called from insn_emit,
|
mgl@1371
|
8181 |
+ once for every function before code is generated. */
|
mgl@1371
|
8182 |
+#define INIT_EXPANDERS avr32_init_expanders ()
|
mgl@1371
|
8183 |
+
|
mgl@1371
|
8184 |
+/******************************************************************************
|
mgl@1371
|
8185 |
+ * SPECS
|
mgl@1371
|
8186 |
+ *****************************************************************************/
|
mgl@1371
|
8187 |
+
|
mgl@1371
|
8188 |
+#ifndef ASM_SPEC
|
mgl@1371
|
8189 |
+#define ASM_SPEC "%{fpic:--pic} %{mrelax|O*:%{mno-relax|O0|O1: ;:--linkrelax}} %{march=ucr2nomul:-march=ucr2;:%{march=*:-march=%*}} %{mpart=uc3a3revd:-mpart=uc3a3256s;:%{mpart=*:-mpart=%*}}"
|
mgl@1371
|
8190 |
+#endif
|
mgl@1371
|
8191 |
+
|
mgl@1371
|
8192 |
+#ifndef MULTILIB_DEFAULTS
|
mgl@1371
|
8193 |
+#define MULTILIB_DEFAULTS { "march=ap", "" }
|
mgl@1371
|
8194 |
+#endif
|
mgl@1371
|
8195 |
+
|
mgl@1371
|
8196 |
+/******************************************************************************
|
mgl@1371
|
8197 |
+ * Run-time Target Specification
|
mgl@1371
|
8198 |
+ *****************************************************************************/
|
mgl@1371
|
8199 |
+#ifndef TARGET_VERSION
|
mgl@1371
|
8200 |
+#define TARGET_VERSION fprintf(stderr, " (AVR32, GNU assembler syntax)");
|
mgl@1371
|
8201 |
+#endif
|
mgl@1371
|
8202 |
+
|
mgl@1371
|
8203 |
+
|
mgl@1371
|
8204 |
+/* Part types. Keep this in sync with the order of avr32_part_types in avr32.c*/
|
mgl@1371
|
8205 |
+enum part_type
|
mgl@1371
|
8206 |
+{
|
mgl@1371
|
8207 |
+ PART_TYPE_AVR32_NONE,
|
mgl@1371
|
8208 |
+ PART_TYPE_AVR32_AP7000,
|
mgl@1371
|
8209 |
+ PART_TYPE_AVR32_AP7001,
|
mgl@1371
|
8210 |
+ PART_TYPE_AVR32_AP7002,
|
mgl@1371
|
8211 |
+ PART_TYPE_AVR32_AP7200,
|
mgl@1371
|
8212 |
+ PART_TYPE_AVR32_UC3A0128,
|
mgl@1371
|
8213 |
+ PART_TYPE_AVR32_UC3A0256,
|
mgl@1371
|
8214 |
+ PART_TYPE_AVR32_UC3A0512,
|
mgl@1371
|
8215 |
+ PART_TYPE_AVR32_UC3A0512ES,
|
mgl@1371
|
8216 |
+ PART_TYPE_AVR32_UC3A1128,
|
mgl@1371
|
8217 |
+ PART_TYPE_AVR32_UC3A1256,
|
mgl@1371
|
8218 |
+ PART_TYPE_AVR32_UC3A1512,
|
mgl@1371
|
8219 |
+ PART_TYPE_AVR32_UC3A1512ES,
|
mgl@1371
|
8220 |
+ PART_TYPE_AVR32_UC3A3REVD,
|
mgl@1371
|
8221 |
+ PART_TYPE_AVR32_UC3A364,
|
mgl@1371
|
8222 |
+ PART_TYPE_AVR32_UC3A364S,
|
mgl@1371
|
8223 |
+ PART_TYPE_AVR32_UC3A3128,
|
mgl@1371
|
8224 |
+ PART_TYPE_AVR32_UC3A3128S,
|
mgl@1371
|
8225 |
+ PART_TYPE_AVR32_UC3A3256,
|
mgl@1371
|
8226 |
+ PART_TYPE_AVR32_UC3A3256S,
|
mgl@1371
|
8227 |
+ PART_TYPE_AVR32_UC3B064,
|
mgl@1371
|
8228 |
+ PART_TYPE_AVR32_UC3B0128,
|
mgl@1371
|
8229 |
+ PART_TYPE_AVR32_UC3B0256,
|
mgl@1371
|
8230 |
+ PART_TYPE_AVR32_UC3B0256ES,
|
mgl@1371
|
8231 |
+ PART_TYPE_AVR32_UC3B164,
|
mgl@1371
|
8232 |
+ PART_TYPE_AVR32_UC3B1128,
|
mgl@1371
|
8233 |
+ PART_TYPE_AVR32_UC3B1256,
|
mgl@1371
|
8234 |
+ PART_TYPE_AVR32_UC3B1256ES
|
mgl@1371
|
8235 |
+};
|
mgl@1371
|
8236 |
+
|
mgl@1371
|
8237 |
+/* Microarchitectures. */
|
mgl@1371
|
8238 |
+enum microarchitecture_type
|
mgl@1371
|
8239 |
+{
|
mgl@1371
|
8240 |
+ UARCH_TYPE_AVR32A,
|
mgl@1371
|
8241 |
+ UARCH_TYPE_AVR32B,
|
mgl@1371
|
8242 |
+ UARCH_TYPE_NONE
|
mgl@1371
|
8243 |
+};
|
mgl@1371
|
8244 |
+
|
mgl@1371
|
8245 |
+/* Architectures types which specifies the pipeline.
|
mgl@1371
|
8246 |
+ Keep this in sync with avr32_arch_types in avr32.c
|
mgl@1371
|
8247 |
+ and the pipeline attribute in avr32.md */
|
mgl@1371
|
8248 |
+enum architecture_type
|
mgl@1371
|
8249 |
+{
|
mgl@1371
|
8250 |
+ ARCH_TYPE_AVR32_AP,
|
mgl@1371
|
8251 |
+ ARCH_TYPE_AVR32_UCR1,
|
mgl@1371
|
8252 |
+ ARCH_TYPE_AVR32_UCR2,
|
mgl@1371
|
8253 |
+ ARCH_TYPE_AVR32_UCR2NOMUL,
|
mgl@1371
|
8254 |
+ ARCH_TYPE_AVR32_NONE
|
mgl@1371
|
8255 |
+};
|
mgl@1371
|
8256 |
+
|
mgl@1371
|
8257 |
+/* Flag specifying if the cpu has support for DSP instructions.*/
|
mgl@1371
|
8258 |
+#define FLAG_AVR32_HAS_DSP (1 << 0)
|
mgl@1371
|
8259 |
+/* Flag specifying if the cpu has support for Read-Modify-Write
|
mgl@1371
|
8260 |
+ instructions.*/
|
mgl@1371
|
8261 |
+#define FLAG_AVR32_HAS_RMW (1 << 1)
|
mgl@1371
|
8262 |
+/* Flag specifying if the cpu has support for SIMD instructions. */
|
mgl@1371
|
8263 |
+#define FLAG_AVR32_HAS_SIMD (1 << 2)
|
mgl@1371
|
8264 |
+/* Flag specifying if the cpu has support for unaligned memory word access. */
|
mgl@1371
|
8265 |
+#define FLAG_AVR32_HAS_UNALIGNED_WORD (1 << 3)
|
mgl@1371
|
8266 |
+/* Flag specifying if the cpu has support for branch prediction. */
|
mgl@1371
|
8267 |
+#define FLAG_AVR32_HAS_BRANCH_PRED (1 << 4)
|
mgl@1371
|
8268 |
+/* Flag specifying if the cpu has support for a return stack. */
|
mgl@1371
|
8269 |
+#define FLAG_AVR32_HAS_RETURN_STACK (1 << 5)
|
mgl@1371
|
8270 |
+/* Flag specifying if the cpu has caches. */
|
mgl@1371
|
8271 |
+#define FLAG_AVR32_HAS_CACHES (1 << 6)
|
mgl@1371
|
8272 |
+/* Flag specifying if the cpu has support for v2 insns. */
|
mgl@1371
|
8273 |
+#define FLAG_AVR32_HAS_V2_INSNS (1 << 7)
|
mgl@1371
|
8274 |
+/* Flag specifying that the cpu has buggy mul insns. */
|
mgl@1371
|
8275 |
+#define FLAG_AVR32_HAS_NO_MUL_INSNS (1 << 8)
|
mgl@1371
|
8276 |
+
|
mgl@1371
|
8277 |
+/* Structure for holding information about different avr32 CPUs/parts */
|
mgl@1371
|
8278 |
+struct part_type_s
|
mgl@1371
|
8279 |
+{
|
mgl@1371
|
8280 |
+ const char *const name;
|
mgl@1371
|
8281 |
+ enum part_type part_type;
|
mgl@1371
|
8282 |
+ enum architecture_type arch_type;
|
mgl@1371
|
8283 |
+ /* Must lie outside user's namespace. NULL == no macro. */
|
mgl@1371
|
8284 |
+ const char *const macro;
|
mgl@1371
|
8285 |
+};
|
mgl@1371
|
8286 |
+
|
mgl@1371
|
8287 |
+/* Structure for holding information about different avr32 pipeline
|
mgl@1371
|
8288 |
+ architectures. */
|
mgl@1371
|
8289 |
+struct arch_type_s
|
mgl@1371
|
8290 |
+{
|
mgl@1371
|
8291 |
+ const char *const name;
|
mgl@1371
|
8292 |
+ enum architecture_type arch_type;
|
mgl@1371
|
8293 |
+ enum microarchitecture_type uarch_type;
|
mgl@1371
|
8294 |
+ const unsigned long feature_flags;
|
mgl@1371
|
8295 |
+ /* Must lie outside user's namespace. NULL == no macro. */
|
mgl@1371
|
8296 |
+ const char *const macro;
|
mgl@1371
|
8297 |
+};
|
mgl@1371
|
8298 |
+
|
mgl@1371
|
8299 |
+extern const struct part_type_s *avr32_part;
|
mgl@1371
|
8300 |
+extern const struct arch_type_s *avr32_arch;
|
mgl@1371
|
8301 |
+
|
mgl@1371
|
8302 |
+#define TARGET_SIMD (avr32_arch->feature_flags & FLAG_AVR32_HAS_SIMD)
|
mgl@1371
|
8303 |
+#define TARGET_DSP (avr32_arch->feature_flags & FLAG_AVR32_HAS_DSP)
|
mgl@1371
|
8304 |
+#define TARGET_RMW (avr32_arch->feature_flags & FLAG_AVR32_HAS_RMW)
|
mgl@1371
|
8305 |
+#define TARGET_UNALIGNED_WORD (avr32_arch->feature_flags & FLAG_AVR32_HAS_UNALIGNED_WORD)
|
mgl@1371
|
8306 |
+#define TARGET_BRANCH_PRED (avr32_arch->feature_flags & FLAG_AVR32_HAS_BRANCH_PRED)
|
mgl@1371
|
8307 |
+#define TARGET_RETURN_STACK (avr32_arch->feature_flags & FLAG_AVR32_HAS_RETURN_STACK)
|
mgl@1371
|
8308 |
+#define TARGET_V2_INSNS (avr32_arch->feature_flags & FLAG_AVR32_HAS_V2_INSNS)
|
mgl@1371
|
8309 |
+#define TARGET_CACHES (avr32_arch->feature_flags & FLAG_AVR32_HAS_CACHES)
|
mgl@1371
|
8310 |
+#define TARGET_NO_MUL_INSNS (avr32_arch->feature_flags & FLAG_AVR32_HAS_NO_MUL_INSNS)
|
mgl@1371
|
8311 |
+#define TARGET_ARCH_AP (avr32_arch->arch_type == ARCH_TYPE_AVR32_AP)
|
mgl@1371
|
8312 |
+#define TARGET_ARCH_UCR1 (avr32_arch->arch_type == ARCH_TYPE_AVR32_UCR1)
|
mgl@1371
|
8313 |
+#define TARGET_ARCH_UCR2 (avr32_arch->arch_type == ARCH_TYPE_AVR32_UCR2)
|
mgl@1371
|
8314 |
+#define TARGET_ARCH_UC (TARGET_ARCH_UCR1 || TARGET_ARCH_UCR2)
|
mgl@1371
|
8315 |
+#define TARGET_UARCH_AVR32A (avr32_arch->uarch_type == UARCH_TYPE_AVR32A)
|
mgl@1371
|
8316 |
+#define TARGET_UARCH_AVR32B (avr32_arch->uarch_type == UARCH_TYPE_AVR32B)
|
mgl@1371
|
8317 |
+
|
mgl@1371
|
8318 |
+#define CAN_DEBUG_WITHOUT_FP
|
mgl@1371
|
8319 |
+
|
mgl@1371
|
8320 |
+
|
mgl@1371
|
8321 |
+
|
mgl@1371
|
8322 |
+
|
mgl@1371
|
8323 |
+/******************************************************************************
|
mgl@1371
|
8324 |
+ * Storage Layout
|
mgl@1371
|
8325 |
+ *****************************************************************************/
|
mgl@1371
|
8326 |
+
|
mgl@1371
|
8327 |
+/*
|
mgl@1371
|
8328 |
+Define this macro to have the value 1 if the most significant bit in a
|
mgl@1371
|
8329 |
+byte has the lowest number; otherwise define it to have the value zero.
|
mgl@1371
|
8330 |
+This means that bit-field instructions count from the most significant
|
mgl@1371
|
8331 |
+bit. If the machine has no bit-field instructions, then this must still
|
mgl@1371
|
8332 |
+be defined, but it doesn't matter which value it is defined to. This
|
mgl@1371
|
8333 |
+macro need not be a constant.
|
mgl@1371
|
8334 |
+
|
mgl@1371
|
8335 |
+This macro does not affect the way structure fields are packed into
|
mgl@1371
|
8336 |
+bytes or words; that is controlled by BYTES_BIG_ENDIAN.
|
mgl@1371
|
8337 |
+*/
|
mgl@1371
|
8338 |
+#define BITS_BIG_ENDIAN 0
|
mgl@1371
|
8339 |
+
|
mgl@1371
|
8340 |
+/*
|
mgl@1371
|
8341 |
+Define this macro to have the value 1 if the most significant byte in a
|
mgl@1371
|
8342 |
+word has the lowest number. This macro need not be a constant.
|
mgl@1371
|
8343 |
+*/
|
mgl@1371
|
8344 |
+/*
|
mgl@1371
|
8345 |
+ Data is stored in an big-endian way.
|
mgl@1371
|
8346 |
+*/
|
mgl@1371
|
8347 |
+#define BYTES_BIG_ENDIAN 1
|
mgl@1371
|
8348 |
+
|
mgl@1371
|
8349 |
+/*
|
mgl@1371
|
8350 |
+Define this macro to have the value 1 if, in a multiword object, the
|
mgl@1371
|
8351 |
+most significant word has the lowest number. This applies to both
|
mgl@1371
|
8352 |
+memory locations and registers; GCC fundamentally assumes that the
|
mgl@1371
|
8353 |
+order of words in memory is the same as the order in registers. This
|
mgl@1371
|
8354 |
+macro need not be a constant.
|
mgl@1371
|
8355 |
+*/
|
mgl@1371
|
8356 |
+/*
|
mgl@1371
|
8357 |
+ Data is stored in an bin-endian way.
|
mgl@1371
|
8358 |
+*/
|
mgl@1371
|
8359 |
+#define WORDS_BIG_ENDIAN 1
|
mgl@1371
|
8360 |
+
|
mgl@1371
|
8361 |
+/*
|
mgl@1371
|
8362 |
+Define this macro if WORDS_BIG_ENDIAN is not constant. This must be a
|
mgl@1371
|
8363 |
+constant value with the same meaning as WORDS_BIG_ENDIAN, which will be
|
mgl@1371
|
8364 |
+used only when compiling libgcc2.c. Typically the value will be set
|
mgl@1371
|
8365 |
+based on preprocessor defines.
|
mgl@1371
|
8366 |
+*/
|
mgl@1371
|
8367 |
+#define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
|
mgl@1371
|
8368 |
+
|
mgl@1371
|
8369 |
+/*
|
mgl@1371
|
8370 |
+Define this macro to have the value 1 if DFmode, XFmode or
|
mgl@1371
|
8371 |
+TFmode floating point numbers are stored in memory with the word
|
mgl@1371
|
8372 |
+containing the sign bit at the lowest address; otherwise define it to
|
mgl@1371
|
8373 |
+have the value 0. This macro need not be a constant.
|
mgl@1371
|
8374 |
+
|
mgl@1371
|
8375 |
+You need not define this macro if the ordering is the same as for
|
mgl@1371
|
8376 |
+multi-word integers.
|
mgl@1371
|
8377 |
+*/
|
mgl@1371
|
8378 |
+/* #define FLOAT_WORDS_BIG_ENDIAN 1 */
|
mgl@1371
|
8379 |
+
|
mgl@1371
|
8380 |
+/*
|
mgl@1371
|
8381 |
+Define this macro to be the number of bits in an addressable storage
|
mgl@1371
|
8382 |
+unit (byte); normally 8.
|
mgl@1371
|
8383 |
+*/
|
mgl@1371
|
8384 |
+#define BITS_PER_UNIT 8
|
mgl@1371
|
8385 |
+
|
mgl@1371
|
8386 |
+/*
|
mgl@1371
|
8387 |
+Number of bits in a word; normally 32.
|
mgl@1371
|
8388 |
+*/
|
mgl@1371
|
8389 |
+#define BITS_PER_WORD 32
|
mgl@1371
|
8390 |
+
|
mgl@1371
|
8391 |
+/*
|
mgl@1371
|
8392 |
+Maximum number of bits in a word. If this is undefined, the default is
|
mgl@1371
|
8393 |
+BITS_PER_WORD. Otherwise, it is the constant value that is the
|
mgl@1371
|
8394 |
+largest value that BITS_PER_WORD can have at run-time.
|
mgl@1371
|
8395 |
+*/
|
mgl@1371
|
8396 |
+/* MAX_BITS_PER_WORD not defined*/
|
mgl@1371
|
8397 |
+
|
mgl@1371
|
8398 |
+/*
|
mgl@1371
|
8399 |
+Number of storage units in a word; normally 4.
|
mgl@1371
|
8400 |
+*/
|
mgl@1371
|
8401 |
+#define UNITS_PER_WORD 4
|
mgl@1371
|
8402 |
+
|
mgl@1371
|
8403 |
+/*
|
mgl@1371
|
8404 |
+Minimum number of units in a word. If this is undefined, the default is
|
mgl@1371
|
8405 |
+UNITS_PER_WORD. Otherwise, it is the constant value that is the
|
mgl@1371
|
8406 |
+smallest value that UNITS_PER_WORD can have at run-time.
|
mgl@1371
|
8407 |
+*/
|
mgl@1371
|
8408 |
+/* MIN_UNITS_PER_WORD not defined */
|
mgl@1371
|
8409 |
+
|
mgl@1371
|
8410 |
+/*
|
mgl@1371
|
8411 |
+Width of a pointer, in bits. You must specify a value no wider than the
|
mgl@1371
|
8412 |
+width of Pmode. If it is not equal to the width of Pmode,
|
mgl@1371
|
8413 |
+you must define POINTERS_EXTEND_UNSIGNED.
|
mgl@1371
|
8414 |
+*/
|
mgl@1371
|
8415 |
+#define POINTER_SIZE 32
|
mgl@1371
|
8416 |
+
|
mgl@1371
|
8417 |
+/*
|
mgl@1371
|
8418 |
+A C expression whose value is greater than zero if pointers that need to be
|
mgl@1371
|
8419 |
+extended from being POINTER_SIZE bits wide to Pmode are to
|
mgl@1371
|
8420 |
+be zero-extended and zero if they are to be sign-extended. If the value
|
mgl@1371
|
8421 |
+is less then zero then there must be an "ptr_extend" instruction that
|
mgl@1371
|
8422 |
+extends a pointer from POINTER_SIZE to Pmode.
|
mgl@1371
|
8423 |
+
|
mgl@1371
|
8424 |
+You need not define this macro if the POINTER_SIZE is equal
|
mgl@1371
|
8425 |
+to the width of Pmode.
|
mgl@1371
|
8426 |
+*/
|
mgl@1371
|
8427 |
+/* #define POINTERS_EXTEND_UNSIGNED */
|
mgl@1371
|
8428 |
+
|
mgl@1371
|
8429 |
+/*
|
mgl@1371
|
8430 |
+A Macro to update M and UNSIGNEDP when an object whose type
|
mgl@1371
|
8431 |
+is TYPE and which has the specified mode and signedness is to be
|
mgl@1371
|
8432 |
+stored in a register. This macro is only called when TYPE is a
|
mgl@1371
|
8433 |
+scalar type.
|
mgl@1371
|
8434 |
+
|
mgl@1371
|
8435 |
+On most RISC machines, which only have operations that operate on a full
|
mgl@1371
|
8436 |
+register, define this macro to set M to word_mode if
|
mgl@1371
|
8437 |
+M is an integer mode narrower than BITS_PER_WORD. In most
|
mgl@1371
|
8438 |
+cases, only integer modes should be widened because wider-precision
|
mgl@1371
|
8439 |
+floating-point operations are usually more expensive than their narrower
|
mgl@1371
|
8440 |
+counterparts.
|
mgl@1371
|
8441 |
+
|
mgl@1371
|
8442 |
+For most machines, the macro definition does not change UNSIGNEDP.
|
mgl@1371
|
8443 |
+However, some machines, have instructions that preferentially handle
|
mgl@1371
|
8444 |
+either signed or unsigned quantities of certain modes. For example, on
|
mgl@1371
|
8445 |
+the DEC Alpha, 32-bit loads from memory and 32-bit add instructions
|
mgl@1371
|
8446 |
+sign-extend the result to 64 bits. On such machines, set
|
mgl@1371
|
8447 |
+UNSIGNEDP according to which kind of extension is more efficient.
|
mgl@1371
|
8448 |
+
|
mgl@1371
|
8449 |
+Do not define this macro if it would never modify M.
|
mgl@1371
|
8450 |
+*/
|
mgl@1371
|
8451 |
+#define PROMOTE_MODE(M, UNSIGNEDP, TYPE) \
|
mgl@1371
|
8452 |
+ { \
|
mgl@1371
|
8453 |
+ if (GET_MODE_CLASS (M) == MODE_INT \
|
mgl@1371
|
8454 |
+ && GET_MODE_SIZE (M) < 4) \
|
mgl@1371
|
8455 |
+ { \
|
mgl@1371
|
8456 |
+ if (M == QImode) \
|
mgl@1371
|
8457 |
+ UNSIGNEDP = 1; \
|
mgl@1371
|
8458 |
+ else if (M == SImode) \
|
mgl@1371
|
8459 |
+ UNSIGNEDP = 0; \
|
mgl@1371
|
8460 |
+ (M) = SImode; \
|
mgl@1371
|
8461 |
+ } \
|
mgl@1371
|
8462 |
+ }
|
mgl@1371
|
8463 |
+
|
mgl@1371
|
8464 |
+#define PROMOTE_FUNCTION_MODE(M, UNSIGNEDP, TYPE) \
|
mgl@1371
|
8465 |
+ { \
|
mgl@1371
|
8466 |
+ if (GET_MODE_CLASS (M) == MODE_INT \
|
mgl@1371
|
8467 |
+ && GET_MODE_SIZE (M) < 4) \
|
mgl@1371
|
8468 |
+ { \
|
mgl@1371
|
8469 |
+ (M) = SImode; \
|
mgl@1371
|
8470 |
+ } \
|
mgl@1371
|
8471 |
+ }
|
mgl@1371
|
8472 |
+
|
mgl@1371
|
8473 |
+/* Define if operations between registers always perform the operation
|
mgl@1371
|
8474 |
+ on the full register even if a narrower mode is specified. */
|
mgl@1371
|
8475 |
+#define WORD_REGISTER_OPERATIONS
|
mgl@1371
|
8476 |
+
|
mgl@1371
|
8477 |
+/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD
|
mgl@1371
|
8478 |
+ will either zero-extend or sign-extend. The value of this macro should
|
mgl@1371
|
8479 |
+ be the code that says which one of the two operations is implicitly
|
mgl@1371
|
8480 |
+ done, UNKNOWN if not known. */
|
mgl@1371
|
8481 |
+#define LOAD_EXTEND_OP(MODE) \
|
mgl@1371
|
8482 |
+ (((MODE) == QImode) ? ZERO_EXTEND \
|
mgl@1371
|
8483 |
+ : ((MODE) == HImode) ? SIGN_EXTEND : UNKNOWN)
|
mgl@1371
|
8484 |
+
|
mgl@1371
|
8485 |
+
|
mgl@1371
|
8486 |
+/*
|
mgl@1371
|
8487 |
+Define this macro if the promotion described by PROMOTE_MODE
|
mgl@1371
|
8488 |
+should only be performed for outgoing function arguments or
|
mgl@1371
|
8489 |
+function return values, as specified by PROMOTE_FUNCTION_ARGS
|
mgl@1371
|
8490 |
+and PROMOTE_FUNCTION_RETURN, respectively.
|
mgl@1371
|
8491 |
+*/
|
mgl@1371
|
8492 |
+/* #define PROMOTE_FOR_CALL_ONLY */
|
mgl@1371
|
8493 |
+
|
mgl@1371
|
8494 |
+/*
|
mgl@1371
|
8495 |
+Normal alignment required for function parameters on the stack, in
|
mgl@1371
|
8496 |
+bits. All stack parameters receive at least this much alignment
|
mgl@1371
|
8497 |
+regardless of data type. On most machines, this is the same as the
|
mgl@1371
|
8498 |
+size of an integer.
|
mgl@1371
|
8499 |
+*/
|
mgl@1371
|
8500 |
+#define PARM_BOUNDARY 32
|
mgl@1371
|
8501 |
+
|
mgl@1371
|
8502 |
+/*
|
mgl@1371
|
8503 |
+Define this macro to the minimum alignment enforced by hardware for the
|
mgl@1371
|
8504 |
+stack pointer on this machine. The definition is a C expression for the
|
mgl@1371
|
8505 |
+desired alignment (measured in bits). This value is used as a default
|
mgl@1371
|
8506 |
+if PREFERRED_STACK_BOUNDARY is not defined. On most machines,
|
mgl@1371
|
8507 |
+this should be the same as PARM_BOUNDARY.
|
mgl@1371
|
8508 |
+*/
|
mgl@1371
|
8509 |
+#define STACK_BOUNDARY 32
|
mgl@1371
|
8510 |
+
|
mgl@1371
|
8511 |
+/*
|
mgl@1371
|
8512 |
+Define this macro if you wish to preserve a certain alignment for the
|
mgl@1371
|
8513 |
+stack pointer, greater than what the hardware enforces. The definition
|
mgl@1371
|
8514 |
+is a C expression for the desired alignment (measured in bits). This
|
mgl@1371
|
8515 |
+macro must evaluate to a value equal to or larger than
|
mgl@1371
|
8516 |
+STACK_BOUNDARY.
|
mgl@1371
|
8517 |
+*/
|
mgl@1371
|
8518 |
+#define PREFERRED_STACK_BOUNDARY (TARGET_FORCE_DOUBLE_ALIGN ? 64 : 32 )
|
mgl@1371
|
8519 |
+
|
mgl@1371
|
8520 |
+/*
|
mgl@1371
|
8521 |
+Alignment required for a function entry point, in bits.
|
mgl@1371
|
8522 |
+*/
|
mgl@1371
|
8523 |
+#define FUNCTION_BOUNDARY 16
|
mgl@1371
|
8524 |
+
|
mgl@1371
|
8525 |
+/*
|
mgl@1371
|
8526 |
+Biggest alignment that any data type can require on this machine, in bits.
|
mgl@1371
|
8527 |
+*/
|
mgl@1371
|
8528 |
+#define BIGGEST_ALIGNMENT (TARGET_FORCE_DOUBLE_ALIGN ? 64 : 32 )
|
mgl@1371
|
8529 |
+
|
mgl@1371
|
8530 |
+/*
|
mgl@1371
|
8531 |
+If defined, the smallest alignment, in bits, that can be given to an
|
mgl@1371
|
8532 |
+object that can be referenced in one operation, without disturbing any
|
mgl@1371
|
8533 |
+nearby object. Normally, this is BITS_PER_UNIT, but may be larger
|
mgl@1371
|
8534 |
+on machines that don't have byte or half-word store operations.
|
mgl@1371
|
8535 |
+*/
|
mgl@1371
|
8536 |
+#define MINIMUM_ATOMIC_ALIGNMENT BITS_PER_UNIT
|
mgl@1371
|
8537 |
+
|
mgl@1371
|
8538 |
+
|
mgl@1371
|
8539 |
+/*
|
mgl@1371
|
8540 |
+An integer expression for the size in bits of the largest integer machine mode that
|
mgl@1371
|
8541 |
+should actually be used. All integer machine modes of this size or smaller can be
|
mgl@1371
|
8542 |
+used for structures and unions with the appropriate sizes. If this macro is undefined,
|
mgl@1371
|
8543 |
+GET_MODE_BITSIZE (DImode) is assumed.*/
|
mgl@1371
|
8544 |
+#define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (DImode)
|
mgl@1371
|
8545 |
+
|
mgl@1371
|
8546 |
+
|
mgl@1371
|
8547 |
+/*
|
mgl@1371
|
8548 |
+If defined, a C expression to compute the alignment given to a constant
|
mgl@1371
|
8549 |
+that is being placed in memory. CONSTANT is the constant and
|
mgl@1371
|
8550 |
+BASIC_ALIGN is the alignment that the object would ordinarily
|
mgl@1371
|
8551 |
+have. The value of this macro is used instead of that alignment to
|
mgl@1371
|
8552 |
+align the object.
|
mgl@1371
|
8553 |
+
|
mgl@1371
|
8554 |
+If this macro is not defined, then BASIC_ALIGN is used.
|
mgl@1371
|
8555 |
+
|
mgl@1371
|
8556 |
+The typical use of this macro is to increase alignment for string
|
mgl@1371
|
8557 |
+constants to be word aligned so that strcpy calls that copy
|
mgl@1371
|
8558 |
+constants can be done inline.
|
mgl@1371
|
8559 |
+*/
|
mgl@1371
|
8560 |
+#define CONSTANT_ALIGNMENT(CONSTANT, BASIC_ALIGN) \
|
mgl@1371
|
8561 |
+ ((TREE_CODE(CONSTANT) == STRING_CST) ? BITS_PER_WORD : BASIC_ALIGN)
|
mgl@1371
|
8562 |
+
|
mgl@1371
|
8563 |
+/* Try to align string to a word. */
|
mgl@1371
|
8564 |
+#define DATA_ALIGNMENT(TYPE, ALIGN) \
|
mgl@1371
|
8565 |
+ ({(TREE_CODE (TYPE) == ARRAY_TYPE \
|
mgl@1371
|
8566 |
+ && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \
|
mgl@1371
|
8567 |
+ && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN));})
|
mgl@1371
|
8568 |
+
|
mgl@1371
|
8569 |
+/* Try to align local store strings to a word. */
|
mgl@1371
|
8570 |
+#define LOCAL_ALIGNMENT(TYPE, ALIGN) \
|
mgl@1371
|
8571 |
+ ({(TREE_CODE (TYPE) == ARRAY_TYPE \
|
mgl@1371
|
8572 |
+ && TYPE_MODE (TREE_TYPE (TYPE)) == QImode \
|
mgl@1371
|
8573 |
+ && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN));})
|
mgl@1371
|
8574 |
+
|
mgl@1371
|
8575 |
+/*
|
mgl@1371
|
8576 |
+Define this macro to be the value 1 if instructions will fail to work
|
mgl@1371
|
8577 |
+if given data not on the nominal alignment. If instructions will merely
|
mgl@1371
|
8578 |
+go slower in that case, define this macro as 0.
|
mgl@1371
|
8579 |
+*/
|
mgl@1371
|
8580 |
+#define STRICT_ALIGNMENT 1
|
mgl@1371
|
8581 |
+
|
mgl@1371
|
8582 |
+/*
|
mgl@1371
|
8583 |
+Define this if you wish to imitate the way many other C compilers handle
|
mgl@1371
|
8584 |
+alignment of bit-fields and the structures that contain them.
|
mgl@1371
|
8585 |
+
|
mgl@1371
|
8586 |
+The behavior is that the type written for a bit-field (int,
|
mgl@1371
|
8587 |
+short, or other integer type) imposes an alignment for the
|
mgl@1371
|
8588 |
+entire structure, as if the structure really did contain an ordinary
|
mgl@1371
|
8589 |
+field of that type. In addition, the bit-field is placed within the
|
mgl@1371
|
8590 |
+structure so that it would fit within such a field, not crossing a
|
mgl@1371
|
8591 |
+boundary for it.
|
mgl@1371
|
8592 |
+
|
mgl@1371
|
8593 |
+Thus, on most machines, a bit-field whose type is written as int
|
mgl@1371
|
8594 |
+would not cross a four-byte boundary, and would force four-byte
|
mgl@1371
|
8595 |
+alignment for the whole structure. (The alignment used may not be four
|
mgl@1371
|
8596 |
+bytes; it is controlled by the other alignment parameters.)
|
mgl@1371
|
8597 |
+
|
mgl@1371
|
8598 |
+If the macro is defined, its definition should be a C expression;
|
mgl@1371
|
8599 |
+a nonzero value for the expression enables this behavior.
|
mgl@1371
|
8600 |
+
|
mgl@1371
|
8601 |
+Note that if this macro is not defined, or its value is zero, some
|
mgl@1371
|
8602 |
+bit-fields may cross more than one alignment boundary. The compiler can
|
mgl@1371
|
8603 |
+support such references if there are insv, extv, and
|
mgl@1371
|
8604 |
+extzv insns that can directly reference memory.
|
mgl@1371
|
8605 |
+
|
mgl@1371
|
8606 |
+The other known way of making bit-fields work is to define
|
mgl@1371
|
8607 |
+STRUCTURE_SIZE_BOUNDARY as large as BIGGEST_ALIGNMENT.
|
mgl@1371
|
8608 |
+Then every structure can be accessed with fullwords.
|
mgl@1371
|
8609 |
+
|
mgl@1371
|
8610 |
+Unless the machine has bit-field instructions or you define
|
mgl@1371
|
8611 |
+STRUCTURE_SIZE_BOUNDARY that way, you must define
|
mgl@1371
|
8612 |
+PCC_BITFIELD_TYPE_MATTERS to have a nonzero value.
|
mgl@1371
|
8613 |
+
|
mgl@1371
|
8614 |
+If your aim is to make GCC use the same conventions for laying out
|
mgl@1371
|
8615 |
+bit-fields as are used by another compiler, here is how to investigate
|
mgl@1371
|
8616 |
+what the other compiler does. Compile and run this program:
|
mgl@1371
|
8617 |
+
|
mgl@1371
|
8618 |
+struct foo1
|
mgl@1371
|
8619 |
+{
|
mgl@1371
|
8620 |
+ char x;
|
mgl@1371
|
8621 |
+ char :0;
|
mgl@1371
|
8622 |
+ char y;
|
mgl@1371
|
8623 |
+};
|
mgl@1371
|
8624 |
+
|
mgl@1371
|
8625 |
+struct foo2
|
mgl@1371
|
8626 |
+{
|
mgl@1371
|
8627 |
+ char x;
|
mgl@1371
|
8628 |
+ int :0;
|
mgl@1371
|
8629 |
+ char y;
|
mgl@1371
|
8630 |
+};
|
mgl@1371
|
8631 |
+
|
mgl@1371
|
8632 |
+main ()
|
mgl@1371
|
8633 |
+{
|
mgl@1371
|
8634 |
+ printf ("Size of foo1 is %d\n",
|
mgl@1371
|
8635 |
+ sizeof (struct foo1));
|
mgl@1371
|
8636 |
+ printf ("Size of foo2 is %d\n",
|
mgl@1371
|
8637 |
+ sizeof (struct foo2));
|
mgl@1371
|
8638 |
+ exit (0);
|
mgl@1371
|
8639 |
+}
|
mgl@1371
|
8640 |
+
|
mgl@1371
|
8641 |
+If this prints 2 and 5, then the compiler's behavior is what you would
|
mgl@1371
|
8642 |
+get from PCC_BITFIELD_TYPE_MATTERS.
|
mgl@1371
|
8643 |
+*/
|
mgl@1371
|
8644 |
+#define PCC_BITFIELD_TYPE_MATTERS 1
|
mgl@1371
|
8645 |
+
|
mgl@1371
|
8646 |
+
|
mgl@1371
|
8647 |
+/******************************************************************************
|
mgl@1371
|
8648 |
+ * Layout of Source Language Data Types
|
mgl@1371
|
8649 |
+ *****************************************************************************/
|
mgl@1371
|
8650 |
+
|
mgl@1371
|
8651 |
+/*
|
mgl@1371
|
8652 |
+A C expression for the size in bits of the type int on the
|
mgl@1371
|
8653 |
+target machine. If you don't define this, the default is one word.
|
mgl@1371
|
8654 |
+*/
|
mgl@1371
|
8655 |
+#define INT_TYPE_SIZE 32
|
mgl@1371
|
8656 |
+
|
mgl@1371
|
8657 |
+/*
|
mgl@1371
|
8658 |
+A C expression for the size in bits of the type short on the
|
mgl@1371
|
8659 |
+target machine. If you don't define this, the default is half a word. (If
|
mgl@1371
|
8660 |
+this would be less than one storage unit, it is rounded up to one unit.)
|
mgl@1371
|
8661 |
+*/
|
mgl@1371
|
8662 |
+#define SHORT_TYPE_SIZE 16
|
mgl@1371
|
8663 |
+
|
mgl@1371
|
8664 |
+/*
|
mgl@1371
|
8665 |
+A C expression for the size in bits of the type long on the
|
mgl@1371
|
8666 |
+target machine. If you don't define this, the default is one word.
|
mgl@1371
|
8667 |
+*/
|
mgl@1371
|
8668 |
+#define LONG_TYPE_SIZE 32
|
mgl@1371
|
8669 |
+
|
mgl@1371
|
8670 |
+
|
mgl@1371
|
8671 |
+/*
|
mgl@1371
|
8672 |
+A C expression for the size in bits of the type long long on the
|
mgl@1371
|
8673 |
+target machine. If you don't define this, the default is two
|
mgl@1371
|
8674 |
+words. If you want to support GNU Ada on your machine, the value of this
|
mgl@1371
|
8675 |
+macro must be at least 64.
|
mgl@1371
|
8676 |
+*/
|
mgl@1371
|
8677 |
+#define LONG_LONG_TYPE_SIZE 64
|
mgl@1371
|
8678 |
+
|
mgl@1371
|
8679 |
+/*
|
mgl@1371
|
8680 |
+A C expression for the size in bits of the type char on the
|
mgl@1371
|
8681 |
+target machine. If you don't define this, the default is
|
mgl@1371
|
8682 |
+BITS_PER_UNIT.
|
mgl@1371
|
8683 |
+*/
|
mgl@1371
|
8684 |
+#define CHAR_TYPE_SIZE 8
|
mgl@1371
|
8685 |
+
|
mgl@1371
|
8686 |
+
|
mgl@1371
|
8687 |
+/*
|
mgl@1371
|
8688 |
+A C expression for the size in bits of the C++ type bool and
|
mgl@1371
|
8689 |
+C99 type _Bool on the target machine. If you don't define
|
mgl@1371
|
8690 |
+this, and you probably shouldn't, the default is CHAR_TYPE_SIZE.
|
mgl@1371
|
8691 |
+*/
|
mgl@1371
|
8692 |
+#define BOOL_TYPE_SIZE 8
|
mgl@1371
|
8693 |
+
|
mgl@1371
|
8694 |
+
|
mgl@1371
|
8695 |
+/*
|
mgl@1371
|
8696 |
+An expression whose value is 1 or 0, according to whether the type
|
mgl@1371
|
8697 |
+char should be signed or unsigned by default. The user can
|
mgl@1371
|
8698 |
+always override this default with the options -fsigned-char
|
mgl@1371
|
8699 |
+and -funsigned-char.
|
mgl@1371
|
8700 |
+*/
|
mgl@1371
|
8701 |
+/* We are using unsigned char */
|
mgl@1371
|
8702 |
+#define DEFAULT_SIGNED_CHAR 0
|
mgl@1371
|
8703 |
+
|
mgl@1371
|
8704 |
+
|
mgl@1371
|
8705 |
+/*
|
mgl@1371
|
8706 |
+A C expression for a string describing the name of the data type to use
|
mgl@1371
|
8707 |
+for size values. The typedef name size_t is defined using the
|
mgl@1371
|
8708 |
+contents of the string.
|
mgl@1371
|
8709 |
+
|
mgl@1371
|
8710 |
+The string can contain more than one keyword. If so, separate them with
|
mgl@1371
|
8711 |
+spaces, and write first any length keyword, then unsigned if
|
mgl@1371
|
8712 |
+appropriate, and finally int. The string must exactly match one
|
mgl@1371
|
8713 |
+of the data type names defined in the function
|
mgl@1371
|
8714 |
+init_decl_processing in the file c-decl.c. You may not
|
mgl@1371
|
8715 |
+omit int or change the order - that would cause the compiler to
|
mgl@1371
|
8716 |
+crash on startup.
|
mgl@1371
|
8717 |
+
|
mgl@1371
|
8718 |
+If you don't define this macro, the default is "long unsigned int".
|
mgl@1371
|
8719 |
+*/
|
mgl@1371
|
8720 |
+#define SIZE_TYPE "long unsigned int"
|
mgl@1371
|
8721 |
+
|
mgl@1371
|
8722 |
+/*
|
mgl@1371
|
8723 |
+A C expression for a string describing the name of the data type to use
|
mgl@1371
|
8724 |
+for the result of subtracting two pointers. The typedef name
|
mgl@1371
|
8725 |
+ptrdiff_t is defined using the contents of the string. See
|
mgl@1371
|
8726 |
+SIZE_TYPE above for more information.
|
mgl@1371
|
8727 |
+
|
mgl@1371
|
8728 |
+If you don't define this macro, the default is "long int".
|
mgl@1371
|
8729 |
+*/
|
mgl@1371
|
8730 |
+#define PTRDIFF_TYPE "long int"
|
mgl@1371
|
8731 |
+
|
mgl@1371
|
8732 |
+
|
mgl@1371
|
8733 |
+/*
|
mgl@1371
|
8734 |
+A C expression for the size in bits of the data type for wide
|
mgl@1371
|
8735 |
+characters. This is used in cpp, which cannot make use of
|
mgl@1371
|
8736 |
+WCHAR_TYPE.
|
mgl@1371
|
8737 |
+*/
|
mgl@1371
|
8738 |
+#define WCHAR_TYPE_SIZE 32
|
mgl@1371
|
8739 |
+
|
mgl@1371
|
8740 |
+
|
mgl@1371
|
8741 |
+/*
|
mgl@1371
|
8742 |
+A C expression for a string describing the name of the data type to
|
mgl@1371
|
8743 |
+use for wide characters passed to printf and returned from
|
mgl@1371
|
8744 |
+getwc. The typedef name wint_t is defined using the
|
mgl@1371
|
8745 |
+contents of the string. See SIZE_TYPE above for more
|
mgl@1371
|
8746 |
+information.
|
mgl@1371
|
8747 |
+
|
mgl@1371
|
8748 |
+If you don't define this macro, the default is "unsigned int".
|
mgl@1371
|
8749 |
+*/
|
mgl@1371
|
8750 |
+#define WINT_TYPE "unsigned int"
|
mgl@1371
|
8751 |
+
|
mgl@1371
|
8752 |
+/*
|
mgl@1371
|
8753 |
+A C expression for a string describing the name of the data type that
|
mgl@1371
|
8754 |
+can represent any value of any standard or extended signed integer type.
|
mgl@1371
|
8755 |
+The typedef name intmax_t is defined using the contents of the
|
mgl@1371
|
8756 |
+string. See SIZE_TYPE above for more information.
|
mgl@1371
|
8757 |
+
|
mgl@1371
|
8758 |
+If you don't define this macro, the default is the first of
|
mgl@1371
|
8759 |
+"int", "long int", or "long long int" that has as
|
mgl@1371
|
8760 |
+much precision as long long int.
|
mgl@1371
|
8761 |
+*/
|
mgl@1371
|
8762 |
+#define INTMAX_TYPE "long long int"
|
mgl@1371
|
8763 |
+
|
mgl@1371
|
8764 |
+/*
|
mgl@1371
|
8765 |
+A C expression for a string describing the name of the data type that
|
mgl@1371
|
8766 |
+can represent any value of any standard or extended unsigned integer
|
mgl@1371
|
8767 |
+type. The typedef name uintmax_t is defined using the contents
|
mgl@1371
|
8768 |
+of the string. See SIZE_TYPE above for more information.
|
mgl@1371
|
8769 |
+
|
mgl@1371
|
8770 |
+If you don't define this macro, the default is the first of
|
mgl@1371
|
8771 |
+"unsigned int", "long unsigned int", or "long long unsigned int"
|
mgl@1371
|
8772 |
+that has as much precision as long long unsigned int.
|
mgl@1371
|
8773 |
+*/
|
mgl@1371
|
8774 |
+#define UINTMAX_TYPE "long long unsigned int"
|
mgl@1371
|
8775 |
+
|
mgl@1371
|
8776 |
+
|
mgl@1371
|
8777 |
+/******************************************************************************
|
mgl@1371
|
8778 |
+ * Register Usage
|
mgl@1371
|
8779 |
+ *****************************************************************************/
|
mgl@1371
|
8780 |
+
|
mgl@1371
|
8781 |
+/* Convert from gcc internal register number to register number
|
mgl@1371
|
8782 |
+ used in assembly code */
|
mgl@1371
|
8783 |
+#define ASM_REGNUM(reg) (LAST_REGNUM - (reg))
|
mgl@1371
|
8784 |
+#define ASM_FP_REGNUM(reg) (LAST_FP_REGNUM - (reg))
|
mgl@1371
|
8785 |
+
|
mgl@1371
|
8786 |
+/* Convert between register number used in assembly to gcc
|
mgl@1371
|
8787 |
+ internal register number */
|
mgl@1371
|
8788 |
+#define INTERNAL_REGNUM(reg) (LAST_REGNUM - (reg))
|
mgl@1371
|
8789 |
+#define INTERNAL_FP_REGNUM(reg) (LAST_FP_REGNUM - (reg))
|
mgl@1371
|
8790 |
+
|
mgl@1371
|
8791 |
+/** Basic Characteristics of Registers **/
|
mgl@1371
|
8792 |
+
|
mgl@1371
|
8793 |
+/*
|
mgl@1371
|
8794 |
+Number of hardware registers known to the compiler. They receive
|
mgl@1371
|
8795 |
+numbers 0 through FIRST_PSEUDO_REGISTER-1; thus, the first
|
mgl@1371
|
8796 |
+pseudo register's number really is assigned the number
|
mgl@1371
|
8797 |
+FIRST_PSEUDO_REGISTER.
|
mgl@1371
|
8798 |
+*/
|
mgl@1371
|
8799 |
+#define FIRST_PSEUDO_REGISTER (LAST_FP_REGNUM + 1)
|
mgl@1371
|
8800 |
+
|
mgl@1371
|
8801 |
+#define FIRST_REGNUM 0
|
mgl@1371
|
8802 |
+#define LAST_REGNUM 15
|
mgl@1371
|
8803 |
+#define NUM_FP_REGS 16
|
mgl@1371
|
8804 |
+#define FIRST_FP_REGNUM 16
|
mgl@1371
|
8805 |
+#define LAST_FP_REGNUM (16+NUM_FP_REGS-1)
|
mgl@1371
|
8806 |
+
|
mgl@1371
|
8807 |
+/*
|
mgl@1371
|
8808 |
+An initializer that says which registers are used for fixed purposes
|
mgl@1371
|
8809 |
+all throughout the compiled code and are therefore not available for
|
mgl@1371
|
8810 |
+general allocation. These would include the stack pointer, the frame
|
mgl@1371
|
8811 |
+pointer (except on machines where that can be used as a general
|
mgl@1371
|
8812 |
+register when no frame pointer is needed), the program counter on
|
mgl@1371
|
8813 |
+machines where that is considered one of the addressable registers,
|
mgl@1371
|
8814 |
+and any other numbered register with a standard use.
|
mgl@1371
|
8815 |
+
|
mgl@1371
|
8816 |
+This information is expressed as a sequence of numbers, separated by
|
mgl@1371
|
8817 |
+commas and surrounded by braces. The nth number is 1 if
|
mgl@1371
|
8818 |
+register n is fixed, 0 otherwise.
|
mgl@1371
|
8819 |
+
|
mgl@1371
|
8820 |
+The table initialized from this macro, and the table initialized by
|
mgl@1371
|
8821 |
+the following one, may be overridden at run time either automatically,
|
mgl@1371
|
8822 |
+by the actions of the macro CONDITIONAL_REGISTER_USAGE, or by
|
mgl@1371
|
8823 |
+the user with the command options -ffixed-[reg],
|
mgl@1371
|
8824 |
+-fcall-used-[reg] and -fcall-saved-[reg].
|
mgl@1371
|
8825 |
+*/
|
mgl@1371
|
8826 |
+
|
mgl@1371
|
8827 |
+/* The internal gcc register numbers are reversed
|
mgl@1371
|
8828 |
+ compared to the real register numbers since
|
mgl@1371
|
8829 |
+ gcc expects data types stored over multiple
|
mgl@1371
|
8830 |
+ registers in the register file to be big endian
|
mgl@1371
|
8831 |
+ if the memory layout is big endian. But this
|
mgl@1371
|
8832 |
+ is not the case for avr32 so we fake a big
|
mgl@1371
|
8833 |
+ endian register file. */
|
mgl@1371
|
8834 |
+
|
mgl@1371
|
8835 |
+#define FIXED_REGISTERS { \
|
mgl@1371
|
8836 |
+ 1, /* Program Counter */ \
|
mgl@1371
|
8837 |
+ 0, /* Link Register */ \
|
mgl@1371
|
8838 |
+ 1, /* Stack Pointer */ \
|
mgl@1371
|
8839 |
+ 0, /* r12 */ \
|
mgl@1371
|
8840 |
+ 0, /* r11 */ \
|
mgl@1371
|
8841 |
+ 0, /* r10 */ \
|
mgl@1371
|
8842 |
+ 0, /* r9 */ \
|
mgl@1371
|
8843 |
+ 0, /* r8 */ \
|
mgl@1371
|
8844 |
+ 0, /* r7 */ \
|
mgl@1371
|
8845 |
+ 0, /* r6 */ \
|
mgl@1371
|
8846 |
+ 0, /* r5 */ \
|
mgl@1371
|
8847 |
+ 0, /* r4 */ \
|
mgl@1371
|
8848 |
+ 0, /* r3 */ \
|
mgl@1371
|
8849 |
+ 0, /* r2 */ \
|
mgl@1371
|
8850 |
+ 0, /* r1 */ \
|
mgl@1371
|
8851 |
+ 0, /* r0 */ \
|
mgl@1371
|
8852 |
+ 0, /* f15 */ \
|
mgl@1371
|
8853 |
+ 0, /* f14 */ \
|
mgl@1371
|
8854 |
+ 0, /* f13 */ \
|
mgl@1371
|
8855 |
+ 0, /* f12 */ \
|
mgl@1371
|
8856 |
+ 0, /* f11 */ \
|
mgl@1371
|
8857 |
+ 0, /* f10 */ \
|
mgl@1371
|
8858 |
+ 0, /* f9 */ \
|
mgl@1371
|
8859 |
+ 0, /* f8 */ \
|
mgl@1371
|
8860 |
+ 0, /* f7 */ \
|
mgl@1371
|
8861 |
+ 0, /* f6 */ \
|
mgl@1371
|
8862 |
+ 0, /* f5 */ \
|
mgl@1371
|
8863 |
+ 0, /* f4 */ \
|
mgl@1371
|
8864 |
+ 0, /* f3 */ \
|
mgl@1371
|
8865 |
+ 0, /* f2*/ \
|
mgl@1371
|
8866 |
+ 0, /* f1 */ \
|
mgl@1371
|
8867 |
+ 0 /* f0 */ \
|
mgl@1371
|
8868 |
+}
|
mgl@1371
|
8869 |
+
|
mgl@1371
|
8870 |
+/*
|
mgl@1371
|
8871 |
+Like FIXED_REGISTERS but has 1 for each register that is
|
mgl@1371
|
8872 |
+clobbered (in general) by function calls as well as for fixed
|
mgl@1371
|
8873 |
+registers. This macro therefore identifies the registers that are not
|
mgl@1371
|
8874 |
+available for general allocation of values that must live across
|
mgl@1371
|
8875 |
+function calls.
|
mgl@1371
|
8876 |
+
|
mgl@1371
|
8877 |
+If a register has 0 in CALL_USED_REGISTERS, the compiler
|
mgl@1371
|
8878 |
+automatically saves it on function entry and restores it on function
|
mgl@1371
|
8879 |
+exit, if the register is used within the function.
|
mgl@1371
|
8880 |
+*/
|
mgl@1371
|
8881 |
+#define CALL_USED_REGISTERS { \
|
mgl@1371
|
8882 |
+ 1, /* Program Counter */ \
|
mgl@1371
|
8883 |
+ 0, /* Link Register */ \
|
mgl@1371
|
8884 |
+ 1, /* Stack Pointer */ \
|
mgl@1371
|
8885 |
+ 1, /* r12 */ \
|
mgl@1371
|
8886 |
+ 1, /* r11 */ \
|
mgl@1371
|
8887 |
+ 1, /* r10 */ \
|
mgl@1371
|
8888 |
+ 1, /* r9 */ \
|
mgl@1371
|
8889 |
+ 1, /* r8 */ \
|
mgl@1371
|
8890 |
+ 0, /* r7 */ \
|
mgl@1371
|
8891 |
+ 0, /* r6 */ \
|
mgl@1371
|
8892 |
+ 0, /* r5 */ \
|
mgl@1371
|
8893 |
+ 0, /* r4 */ \
|
mgl@1371
|
8894 |
+ 0, /* r3 */ \
|
mgl@1371
|
8895 |
+ 0, /* r2 */ \
|
mgl@1371
|
8896 |
+ 0, /* r1 */ \
|
mgl@1371
|
8897 |
+ 0, /* r0 */ \
|
mgl@1371
|
8898 |
+ 1, /* f15 */ \
|
mgl@1371
|
8899 |
+ 1, /* f14 */ \
|
mgl@1371
|
8900 |
+ 1, /* f13 */ \
|
mgl@1371
|
8901 |
+ 1, /* f12 */ \
|
mgl@1371
|
8902 |
+ 1, /* f11 */ \
|
mgl@1371
|
8903 |
+ 1, /* f10 */ \
|
mgl@1371
|
8904 |
+ 1, /* f9 */ \
|
mgl@1371
|
8905 |
+ 1, /* f8 */ \
|
mgl@1371
|
8906 |
+ 0, /* f7 */ \
|
mgl@1371
|
8907 |
+ 0, /* f6 */ \
|
mgl@1371
|
8908 |
+ 0, /* f5 */ \
|
mgl@1371
|
8909 |
+ 0, /* f4 */ \
|
mgl@1371
|
8910 |
+ 0, /* f3 */ \
|
mgl@1371
|
8911 |
+ 0, /* f2*/ \
|
mgl@1371
|
8912 |
+ 0, /* f1*/ \
|
mgl@1371
|
8913 |
+ 0, /* f0 */ \
|
mgl@1371
|
8914 |
+}
|
mgl@1371
|
8915 |
+
|
mgl@1371
|
8916 |
+/* Interrupt functions can only use registers that have already been
|
mgl@1371
|
8917 |
+ saved by the prologue, even if they would normally be
|
mgl@1371
|
8918 |
+ call-clobbered. */
|
mgl@1371
|
8919 |
+#define HARD_REGNO_RENAME_OK(SRC, DST) \
|
mgl@1371
|
8920 |
+ (! IS_INTERRUPT (cfun->machine->func_type) || \
|
mgl@1371
|
8921 |
+ regs_ever_live[DST])
|
mgl@1371
|
8922 |
+
|
mgl@1371
|
8923 |
+
|
mgl@1371
|
8924 |
+/*
|
mgl@1371
|
8925 |
+Zero or more C statements that may conditionally modify five variables
|
mgl@1371
|
8926 |
+fixed_regs, call_used_regs, global_regs,
|
mgl@1371
|
8927 |
+reg_names, and reg_class_contents, to take into account
|
mgl@1371
|
8928 |
+any dependence of these register sets on target flags. The first three
|
mgl@1371
|
8929 |
+of these are of type char [] (interpreted as Boolean vectors).
|
mgl@1371
|
8930 |
+global_regs is a const char *[], and
|
mgl@1371
|
8931 |
+reg_class_contents is a HARD_REG_SET. Before the macro is
|
mgl@1371
|
8932 |
+called, fixed_regs, call_used_regs,
|
mgl@1371
|
8933 |
+reg_class_contents, and reg_names have been initialized
|
mgl@1371
|
8934 |
+from FIXED_REGISTERS, CALL_USED_REGISTERS,
|
mgl@1371
|
8935 |
+REG_CLASS_CONTENTS, and REGISTER_NAMES, respectively.
|
mgl@1371
|
8936 |
+global_regs has been cleared, and any -ffixed-[reg],
|
mgl@1371
|
8937 |
+-fcall-used-[reg] and -fcall-saved-[reg]
|
mgl@1371
|
8938 |
+command options have been applied.
|
mgl@1371
|
8939 |
+
|
mgl@1371
|
8940 |
+You need not define this macro if it has no work to do.
|
mgl@1371
|
8941 |
+
|
mgl@1371
|
8942 |
+If the usage of an entire class of registers depends on the target
|
mgl@1371
|
8943 |
+flags, you may indicate this to GCC by using this macro to modify
|
mgl@1371
|
8944 |
+fixed_regs and call_used_regs to 1 for each of the
|
mgl@1371
|
8945 |
+registers in the classes which should not be used by GCC. Also define
|
mgl@1371
|
8946 |
+the macro REG_CLASS_FROM_LETTER to return NO_REGS if it
|
mgl@1371
|
8947 |
+is called with a letter for a class that shouldn't be used.
|
mgl@1371
|
8948 |
+
|
mgl@1371
|
8949 |
+ (However, if this class is not included in GENERAL_REGS and all
|
mgl@1371
|
8950 |
+of the insn patterns whose constraints permit this class are
|
mgl@1371
|
8951 |
+controlled by target switches, then GCC will automatically avoid using
|
mgl@1371
|
8952 |
+these registers when the target switches are opposed to them.)
|
mgl@1371
|
8953 |
+*/
|
mgl@1371
|
8954 |
+#define CONDITIONAL_REGISTER_USAGE \
|
mgl@1371
|
8955 |
+ do \
|
mgl@1371
|
8956 |
+ { \
|
mgl@1371
|
8957 |
+ int regno; \
|
mgl@1371
|
8958 |
+ \
|
mgl@1371
|
8959 |
+ if (TARGET_SOFT_FLOAT) \
|
mgl@1371
|
8960 |
+ { \
|
mgl@1371
|
8961 |
+ for (regno = FIRST_FP_REGNUM; \
|
mgl@1371
|
8962 |
+ regno <= LAST_FP_REGNUM; ++regno) \
|
mgl@1371
|
8963 |
+ fixed_regs[regno] = call_used_regs[regno] = 1; \
|
mgl@1371
|
8964 |
+ } \
|
mgl@1371
|
8965 |
+ if (flag_pic) \
|
mgl@1371
|
8966 |
+ { \
|
mgl@1371
|
8967 |
+ fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
|
mgl@1371
|
8968 |
+ call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
|
mgl@1371
|
8969 |
+ } \
|
mgl@1371
|
8970 |
+ } \
|
mgl@1371
|
8971 |
+ while (0)
|
mgl@1371
|
8972 |
+
|
mgl@1371
|
8973 |
+
|
mgl@1371
|
8974 |
+/*
|
mgl@1371
|
8975 |
+If the program counter has a register number, define this as that
|
mgl@1371
|
8976 |
+register number. Otherwise, do not define it.
|
mgl@1371
|
8977 |
+*/
|
mgl@1371
|
8978 |
+
|
mgl@1371
|
8979 |
+#define LAST_AVR32_REGNUM 16
|
mgl@1371
|
8980 |
+
|
mgl@1371
|
8981 |
+
|
mgl@1371
|
8982 |
+/** Order of Allocation of Registers **/
|
mgl@1371
|
8983 |
+
|
mgl@1371
|
8984 |
+/*
|
mgl@1371
|
8985 |
+If defined, an initializer for a vector of integers, containing the
|
mgl@1371
|
8986 |
+numbers of hard registers in the order in which GCC should prefer
|
mgl@1371
|
8987 |
+to use them (from most preferred to least).
|
mgl@1371
|
8988 |
+
|
mgl@1371
|
8989 |
+If this macro is not defined, registers are used lowest numbered first
|
mgl@1371
|
8990 |
+(all else being equal).
|
mgl@1371
|
8991 |
+
|
mgl@1371
|
8992 |
+One use of this macro is on machines where the highest numbered
|
mgl@1371
|
8993 |
+registers must always be saved and the save-multiple-registers
|
mgl@1371
|
8994 |
+instruction supports only sequences of consecutive registers. On such
|
mgl@1371
|
8995 |
+machines, define REG_ALLOC_ORDER to be an initializer that lists
|
mgl@1371
|
8996 |
+the highest numbered allocable register first.
|
mgl@1371
|
8997 |
+*/
|
mgl@1371
|
8998 |
+#define REG_ALLOC_ORDER \
|
mgl@1371
|
8999 |
+{ \
|
mgl@1371
|
9000 |
+ INTERNAL_REGNUM(8), \
|
mgl@1371
|
9001 |
+ INTERNAL_REGNUM(9), \
|
mgl@1371
|
9002 |
+ INTERNAL_REGNUM(10), \
|
mgl@1371
|
9003 |
+ INTERNAL_REGNUM(11), \
|
mgl@1371
|
9004 |
+ INTERNAL_REGNUM(12), \
|
mgl@1371
|
9005 |
+ LR_REGNUM, \
|
mgl@1371
|
9006 |
+ INTERNAL_REGNUM(7), \
|
mgl@1371
|
9007 |
+ INTERNAL_REGNUM(6), \
|
mgl@1371
|
9008 |
+ INTERNAL_REGNUM(5), \
|
mgl@1371
|
9009 |
+ INTERNAL_REGNUM(4), \
|
mgl@1371
|
9010 |
+ INTERNAL_REGNUM(3), \
|
mgl@1371
|
9011 |
+ INTERNAL_REGNUM(2), \
|
mgl@1371
|
9012 |
+ INTERNAL_REGNUM(1), \
|
mgl@1371
|
9013 |
+ INTERNAL_REGNUM(0), \
|
mgl@1371
|
9014 |
+ INTERNAL_FP_REGNUM(15), \
|
mgl@1371
|
9015 |
+ INTERNAL_FP_REGNUM(14), \
|
mgl@1371
|
9016 |
+ INTERNAL_FP_REGNUM(13), \
|
mgl@1371
|
9017 |
+ INTERNAL_FP_REGNUM(12), \
|
mgl@1371
|
9018 |
+ INTERNAL_FP_REGNUM(11), \
|
mgl@1371
|
9019 |
+ INTERNAL_FP_REGNUM(10), \
|
mgl@1371
|
9020 |
+ INTERNAL_FP_REGNUM(9), \
|
mgl@1371
|
9021 |
+ INTERNAL_FP_REGNUM(8), \
|
mgl@1371
|
9022 |
+ INTERNAL_FP_REGNUM(7), \
|
mgl@1371
|
9023 |
+ INTERNAL_FP_REGNUM(6), \
|
mgl@1371
|
9024 |
+ INTERNAL_FP_REGNUM(5), \
|
mgl@1371
|
9025 |
+ INTERNAL_FP_REGNUM(4), \
|
mgl@1371
|
9026 |
+ INTERNAL_FP_REGNUM(3), \
|
mgl@1371
|
9027 |
+ INTERNAL_FP_REGNUM(2), \
|
mgl@1371
|
9028 |
+ INTERNAL_FP_REGNUM(1), \
|
mgl@1371
|
9029 |
+ INTERNAL_FP_REGNUM(0), \
|
mgl@1371
|
9030 |
+ SP_REGNUM, \
|
mgl@1371
|
9031 |
+ PC_REGNUM \
|
mgl@1371
|
9032 |
+}
|
mgl@1371
|
9033 |
+
|
mgl@1371
|
9034 |
+
|
mgl@1371
|
9035 |
+/** How Values Fit in Registers **/
|
mgl@1371
|
9036 |
+
|
mgl@1371
|
9037 |
+/*
|
mgl@1371
|
9038 |
+A C expression for the number of consecutive hard registers, starting
|
mgl@1371
|
9039 |
+at register number REGNO, required to hold a value of mode
|
mgl@1371
|
9040 |
+MODE.
|
mgl@1371
|
9041 |
+
|
mgl@1371
|
9042 |
+On a machine where all registers are exactly one word, a suitable
|
mgl@1371
|
9043 |
+definition of this macro is
|
mgl@1371
|
9044 |
+
|
mgl@1371
|
9045 |
+#define HARD_REGNO_NREGS(REGNO, MODE) \
|
mgl@1371
|
9046 |
+ ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \
|
mgl@1371
|
9047 |
+ / UNITS_PER_WORD)
|
mgl@1371
|
9048 |
+*/
|
mgl@1371
|
9049 |
+#define HARD_REGNO_NREGS(REGNO, MODE) \
|
mgl@1371
|
9050 |
+ ((unsigned int)((GET_MODE_SIZE(MODE) + UNITS_PER_WORD -1 ) / UNITS_PER_WORD))
|
mgl@1371
|
9051 |
+
|
mgl@1371
|
9052 |
+/*
|
mgl@1371
|
9053 |
+A C expression that is nonzero if it is permissible to store a value
|
mgl@1371
|
9054 |
+of mode MODE in hard register number REGNO (or in several
|
mgl@1371
|
9055 |
+registers starting with that one). For a machine where all registers
|
mgl@1371
|
9056 |
+are equivalent, a suitable definition is
|
mgl@1371
|
9057 |
+
|
mgl@1371
|
9058 |
+ #define HARD_REGNO_MODE_OK(REGNO, MODE) 1
|
mgl@1371
|
9059 |
+
|
mgl@1371
|
9060 |
+You need not include code to check for the numbers of fixed registers,
|
mgl@1371
|
9061 |
+because the allocation mechanism considers them to be always occupied.
|
mgl@1371
|
9062 |
+
|
mgl@1371
|
9063 |
+On some machines, double-precision values must be kept in even/odd
|
mgl@1371
|
9064 |
+register pairs. You can implement that by defining this macro to reject
|
mgl@1371
|
9065 |
+odd register numbers for such modes.
|
mgl@1371
|
9066 |
+
|
mgl@1371
|
9067 |
+The minimum requirement for a mode to be OK in a register is that the
|
mgl@1371
|
9068 |
+mov[mode] instruction pattern support moves between the
|
mgl@1371
|
9069 |
+register and other hard register in the same class and that moving a
|
mgl@1371
|
9070 |
+value into the register and back out not alter it.
|
mgl@1371
|
9071 |
+
|
mgl@1371
|
9072 |
+Since the same instruction used to move word_mode will work for
|
mgl@1371
|
9073 |
+all narrower integer modes, it is not necessary on any machine for
|
mgl@1371
|
9074 |
+HARD_REGNO_MODE_OK to distinguish between these modes, provided
|
mgl@1371
|
9075 |
+you define patterns movhi, etc., to take advantage of this. This
|
mgl@1371
|
9076 |
+is useful because of the interaction between HARD_REGNO_MODE_OK
|
mgl@1371
|
9077 |
+and MODES_TIEABLE_P; it is very desirable for all integer modes
|
mgl@1371
|
9078 |
+to be tieable.
|
mgl@1371
|
9079 |
+
|
mgl@1371
|
9080 |
+Many machines have special registers for floating point arithmetic.
|
mgl@1371
|
9081 |
+Often people assume that floating point machine modes are allowed only
|
mgl@1371
|
9082 |
+in floating point registers. This is not true. Any registers that
|
mgl@1371
|
9083 |
+can hold integers can safely hold a floating point machine
|
mgl@1371
|
9084 |
+mode, whether or not floating arithmetic can be done on it in those
|
mgl@1371
|
9085 |
+registers. Integer move instructions can be used to move the values.
|
mgl@1371
|
9086 |
+
|
mgl@1371
|
9087 |
+On some machines, though, the converse is true: fixed-point machine
|
mgl@1371
|
9088 |
+modes may not go in floating registers. This is true if the floating
|
mgl@1371
|
9089 |
+registers normalize any value stored in them, because storing a
|
mgl@1371
|
9090 |
+non-floating value there would garble it. In this case,
|
mgl@1371
|
9091 |
+HARD_REGNO_MODE_OK should reject fixed-point machine modes in
|
mgl@1371
|
9092 |
+floating registers. But if the floating registers do not automatically
|
mgl@1371
|
9093 |
+normalize, if you can store any bit pattern in one and retrieve it
|
mgl@1371
|
9094 |
+unchanged without a trap, then any machine mode may go in a floating
|
mgl@1371
|
9095 |
+register, so you can define this macro to say so.
|
mgl@1371
|
9096 |
+
|
mgl@1371
|
9097 |
+The primary significance of special floating registers is rather that
|
mgl@1371
|
9098 |
+they are the registers acceptable in floating point arithmetic
|
mgl@1371
|
9099 |
+instructions. However, this is of no concern to
|
mgl@1371
|
9100 |
+HARD_REGNO_MODE_OK. You handle it by writing the proper
|
mgl@1371
|
9101 |
+constraints for those instructions.
|
mgl@1371
|
9102 |
+
|
mgl@1371
|
9103 |
+On some machines, the floating registers are especially slow to access,
|
mgl@1371
|
9104 |
+so that it is better to store a value in a stack frame than in such a
|
mgl@1371
|
9105 |
+register if floating point arithmetic is not being done. As long as the
|
mgl@1371
|
9106 |
+floating registers are not in class GENERAL_REGS, they will not
|
mgl@1371
|
9107 |
+be used unless some pattern's constraint asks for one.
|
mgl@1371
|
9108 |
+*/
|
mgl@1371
|
9109 |
+#define HARD_REGNO_MODE_OK(REGNO, MODE) avr32_hard_regno_mode_ok(REGNO, MODE)
|
mgl@1371
|
9110 |
+
|
mgl@1371
|
9111 |
+/*
|
mgl@1371
|
9112 |
+A C expression that is nonzero if a value of mode
|
mgl@1371
|
9113 |
+MODE1 is accessible in mode MODE2 without copying.
|
mgl@1371
|
9114 |
+
|
mgl@1371
|
9115 |
+If HARD_REGNO_MODE_OK(R, MODE1) and
|
mgl@1371
|
9116 |
+HARD_REGNO_MODE_OK(R, MODE2) are always the same for
|
mgl@1371
|
9117 |
+any R, then MODES_TIEABLE_P(MODE1, MODE2)
|
mgl@1371
|
9118 |
+should be nonzero. If they differ for any R, you should define
|
mgl@1371
|
9119 |
+this macro to return zero unless some other mechanism ensures the
|
mgl@1371
|
9120 |
+accessibility of the value in a narrower mode.
|
mgl@1371
|
9121 |
+
|
mgl@1371
|
9122 |
+You should define this macro to return nonzero in as many cases as
|
mgl@1371
|
9123 |
+possible since doing so will allow GCC to perform better register
|
mgl@1371
|
9124 |
+allocation.
|
mgl@1371
|
9125 |
+*/
|
mgl@1371
|
9126 |
+#define MODES_TIEABLE_P(MODE1, MODE2) \
|
mgl@1371
|
9127 |
+ (GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2))
|
mgl@1371
|
9128 |
+
|
mgl@1371
|
9129 |
+
|
mgl@1371
|
9130 |
+
|
mgl@1371
|
9131 |
+/******************************************************************************
|
mgl@1371
|
9132 |
+ * Register Classes
|
mgl@1371
|
9133 |
+ *****************************************************************************/
|
mgl@1371
|
9134 |
+
|
mgl@1371
|
9135 |
+/*
|
mgl@1371
|
9136 |
+An enumeral type that must be defined with all the register class names
|
mgl@1371
|
9137 |
+as enumeral values. NO_REGS must be first. ALL_REGS
|
mgl@1371
|
9138 |
+must be the last register class, followed by one more enumeral value,
|
mgl@1371
|
9139 |
+LIM_REG_CLASSES, which is not a register class but rather
|
mgl@1371
|
9140 |
+tells how many classes there are.
|
mgl@1371
|
9141 |
+
|
mgl@1371
|
9142 |
+Each register class has a number, which is the value of casting
|
mgl@1371
|
9143 |
+the class name to type int. The number serves as an index
|
mgl@1371
|
9144 |
+in many of the tables described below.
|
mgl@1371
|
9145 |
+*/
|
mgl@1371
|
9146 |
+enum reg_class
|
mgl@1371
|
9147 |
+{
|
mgl@1371
|
9148 |
+ NO_REGS,
|
mgl@1371
|
9149 |
+ GENERAL_REGS,
|
mgl@1371
|
9150 |
+ FP_REGS,
|
mgl@1371
|
9151 |
+ ALL_REGS,
|
mgl@1371
|
9152 |
+ LIM_REG_CLASSES
|
mgl@1371
|
9153 |
+};
|
mgl@1371
|
9154 |
+
|
mgl@1371
|
9155 |
+/*
|
mgl@1371
|
9156 |
+The number of distinct register classes, defined as follows:
|
mgl@1371
|
9157 |
+ #define N_REG_CLASSES (int) LIM_REG_CLASSES
|
mgl@1371
|
9158 |
+*/
|
mgl@1371
|
9159 |
+#define N_REG_CLASSES (int)LIM_REG_CLASSES
|
mgl@1371
|
9160 |
+
|
mgl@1371
|
9161 |
+/*
|
mgl@1371
|
9162 |
+An initializer containing the names of the register classes as C string
|
mgl@1371
|
9163 |
+constants. These names are used in writing some of the debugging dumps.
|
mgl@1371
|
9164 |
+*/
|
mgl@1371
|
9165 |
+#define REG_CLASS_NAMES \
|
mgl@1371
|
9166 |
+{ \
|
mgl@1371
|
9167 |
+ "NO_REGS", \
|
mgl@1371
|
9168 |
+ "GENERAL_REGS", \
|
mgl@1371
|
9169 |
+ "FLOATING_POINT_REGS", \
|
mgl@1371
|
9170 |
+ "ALL_REGS" \
|
mgl@1371
|
9171 |
+}
|
mgl@1371
|
9172 |
+
|
mgl@1371
|
9173 |
+/*
|
mgl@1371
|
9174 |
+An initializer containing the contents of the register classes, as integers
|
mgl@1371
|
9175 |
+which are bit masks. The nth integer specifies the contents of class
|
mgl@1371
|
9176 |
+n. The way the integer mask is interpreted is that
|
mgl@1371
|
9177 |
+register r is in the class if mask & (1 << r) is 1.
|
mgl@1371
|
9178 |
+
|
mgl@1371
|
9179 |
+When the machine has more than 32 registers, an integer does not suffice.
|
mgl@1371
|
9180 |
+Then the integers are replaced by sub-initializers, braced groupings containing
|
mgl@1371
|
9181 |
+several integers. Each sub-initializer must be suitable as an initializer
|
mgl@1371
|
9182 |
+for the type HARD_REG_SET which is defined in hard-reg-set.h.
|
mgl@1371
|
9183 |
+In this situation, the first integer in each sub-initializer corresponds to
|
mgl@1371
|
9184 |
+registers 0 through 31, the second integer to registers 32 through 63, and
|
mgl@1371
|
9185 |
+so on.
|
mgl@1371
|
9186 |
+*/
|
mgl@1371
|
9187 |
+#define REG_CLASS_CONTENTS { \
|
mgl@1371
|
9188 |
+ {0x00000000}, /* NO_REGS */ \
|
mgl@1371
|
9189 |
+ {0x0000FFFF}, /* GENERAL_REGS */ \
|
mgl@1371
|
9190 |
+ {0xFFFF0000}, /* FP_REGS */ \
|
mgl@1371
|
9191 |
+ {0x7FFFFFFF}, /* ALL_REGS */ \
|
mgl@1371
|
9192 |
+}
|
mgl@1371
|
9193 |
+
|
mgl@1371
|
9194 |
+
|
mgl@1371
|
9195 |
+/*
|
mgl@1371
|
9196 |
+A C expression whose value is a register class containing hard register
|
mgl@1371
|
9197 |
+REGNO. In general there is more than one such class; choose a class
|
mgl@1371
|
9198 |
+which is minimal, meaning that no smaller class also contains the
|
mgl@1371
|
9199 |
+register.
|
mgl@1371
|
9200 |
+*/
|
mgl@1371
|
9201 |
+#define REGNO_REG_CLASS(REGNO) ((REGNO < 16) ? GENERAL_REGS : FP_REGS)
|
mgl@1371
|
9202 |
+
|
mgl@1371
|
9203 |
+/*
|
mgl@1371
|
9204 |
+A macro whose definition is the name of the class to which a valid
|
mgl@1371
|
9205 |
+base register must belong. A base register is one used in an address
|
mgl@1371
|
9206 |
+which is the register value plus a displacement.
|
mgl@1371
|
9207 |
+*/
|
mgl@1371
|
9208 |
+#define BASE_REG_CLASS GENERAL_REGS
|
mgl@1371
|
9209 |
+
|
mgl@1371
|
9210 |
+/*
|
mgl@1371
|
9211 |
+This is a variation of the BASE_REG_CLASS macro which allows
|
mgl@1371
|
9212 |
+the selection of a base register in a mode depenedent manner. If
|
mgl@1371
|
9213 |
+mode is VOIDmode then it should return the same value as
|
mgl@1371
|
9214 |
+BASE_REG_CLASS.
|
mgl@1371
|
9215 |
+*/
|
mgl@1371
|
9216 |
+#define MODE_BASE_REG_CLASS(MODE) BASE_REG_CLASS
|
mgl@1371
|
9217 |
+
|
mgl@1371
|
9218 |
+/*
|
mgl@1371
|
9219 |
+A macro whose definition is the name of the class to which a valid
|
mgl@1371
|
9220 |
+index register must belong. An index register is one used in an
|
mgl@1371
|
9221 |
+address where its value is either multiplied by a scale factor or
|
mgl@1371
|
9222 |
+added to another register (as well as added to a displacement).
|
mgl@1371
|
9223 |
+*/
|
mgl@1371
|
9224 |
+#define INDEX_REG_CLASS BASE_REG_CLASS
|
mgl@1371
|
9225 |
+
|
mgl@1371
|
9226 |
+/*
|
mgl@1371
|
9227 |
+A C expression which defines the machine-dependent operand constraint
|
mgl@1371
|
9228 |
+letters for register classes. If CHAR is such a letter, the
|
mgl@1371
|
9229 |
+value should be the register class corresponding to it. Otherwise,
|
mgl@1371
|
9230 |
+the value should be NO_REGS. The register letter r,
|
mgl@1371
|
9231 |
+corresponding to class GENERAL_REGS, will not be passed
|
mgl@1371
|
9232 |
+to this macro; you do not need to handle it.
|
mgl@1371
|
9233 |
+*/
|
mgl@1371
|
9234 |
+#define REG_CLASS_FROM_LETTER(CHAR) ((CHAR) == 'f' ? FP_REGS : NO_REGS)
|
mgl@1371
|
9235 |
+
|
mgl@1371
|
9236 |
+
|
mgl@1371
|
9237 |
+/* These assume that REGNO is a hard or pseudo reg number.
|
mgl@1371
|
9238 |
+ They give nonzero only if REGNO is a hard reg of the suitable class
|
mgl@1371
|
9239 |
+ or a pseudo reg currently allocated to a suitable hard reg.
|
mgl@1371
|
9240 |
+ Since they use reg_renumber, they are safe only once reg_renumber
|
mgl@1371
|
9241 |
+ has been allocated, which happens in local-alloc.c. */
|
mgl@1371
|
9242 |
+#define TEST_REGNO(R, TEST, VALUE) \
|
mgl@1371
|
9243 |
+ ((R TEST VALUE) || ((unsigned) reg_renumber[R] TEST VALUE))
|
mgl@1371
|
9244 |
+
|
mgl@1371
|
9245 |
+/*
|
mgl@1371
|
9246 |
+A C expression which is nonzero if register number num is suitable for use as a base
|
mgl@1371
|
9247 |
+register in operand addresses. It may be either a suitable hard register or a pseudo
|
mgl@1371
|
9248 |
+register that has been allocated such a hard register.
|
mgl@1371
|
9249 |
+*/
|
mgl@1371
|
9250 |
+#define REGNO_OK_FOR_BASE_P(NUM) TEST_REGNO(NUM, <=, LAST_REGNUM)
|
mgl@1371
|
9251 |
+
|
mgl@1371
|
9252 |
+/*
|
mgl@1371
|
9253 |
+A C expression which is nonzero if register number NUM is
|
mgl@1371
|
9254 |
+suitable for use as an index register in operand addresses. It may be
|
mgl@1371
|
9255 |
+either a suitable hard register or a pseudo register that has been
|
mgl@1371
|
9256 |
+allocated such a hard register.
|
mgl@1371
|
9257 |
+
|
mgl@1371
|
9258 |
+The difference between an index register and a base register is that
|
mgl@1371
|
9259 |
+the index register may be scaled. If an address involves the sum of
|
mgl@1371
|
9260 |
+two registers, neither one of them scaled, then either one may be
|
mgl@1371
|
9261 |
+labeled the ``base'' and the other the ``index''; but whichever
|
mgl@1371
|
9262 |
+labeling is used must fit the machine's constraints of which registers
|
mgl@1371
|
9263 |
+may serve in each capacity. The compiler will try both labelings,
|
mgl@1371
|
9264 |
+looking for one that is valid, and will reload one or both registers
|
mgl@1371
|
9265 |
+only if neither labeling works.
|
mgl@1371
|
9266 |
+*/
|
mgl@1371
|
9267 |
+#define REGNO_OK_FOR_INDEX_P(NUM) TEST_REGNO(NUM, <=, LAST_REGNUM)
|
mgl@1371
|
9268 |
+
|
mgl@1371
|
9269 |
+/*
|
mgl@1371
|
9270 |
+A C expression that places additional restrictions on the register class
|
mgl@1371
|
9271 |
+to use when it is necessary to copy value X into a register in class
|
mgl@1371
|
9272 |
+CLASS. The value is a register class; perhaps CLASS, or perhaps
|
mgl@1371
|
9273 |
+another, smaller class. On many machines, the following definition is
|
mgl@1371
|
9274 |
+safe: #define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS
|
mgl@1371
|
9275 |
+
|
mgl@1371
|
9276 |
+Sometimes returning a more restrictive class makes better code. For
|
mgl@1371
|
9277 |
+example, on the 68000, when X is an integer constant that is in range
|
mgl@1371
|
9278 |
+for a 'moveq' instruction, the value of this macro is always
|
mgl@1371
|
9279 |
+DATA_REGS as long as CLASS includes the data registers.
|
mgl@1371
|
9280 |
+Requiring a data register guarantees that a 'moveq' will be used.
|
mgl@1371
|
9281 |
+
|
mgl@1371
|
9282 |
+If X is a const_double, by returning NO_REGS
|
mgl@1371
|
9283 |
+you can force X into a memory constant. This is useful on
|
mgl@1371
|
9284 |
+certain machines where immediate floating values cannot be loaded into
|
mgl@1371
|
9285 |
+certain kinds of registers.
|
mgl@1371
|
9286 |
+*/
|
mgl@1371
|
9287 |
+#define PREFERRED_RELOAD_CLASS(X, CLASS) CLASS
|
mgl@1371
|
9288 |
+
|
mgl@1371
|
9289 |
+
|
mgl@1371
|
9290 |
+
|
mgl@1371
|
9291 |
+/*
|
mgl@1371
|
9292 |
+A C expression for the maximum number of consecutive registers
|
mgl@1371
|
9293 |
+of class CLASS needed to hold a value of mode MODE.
|
mgl@1371
|
9294 |
+
|
mgl@1371
|
9295 |
+This is closely related to the macro HARD_REGNO_NREGS. In fact,
|
mgl@1371
|
9296 |
+the value of the macro CLASS_MAX_NREGS(CLASS, MODE)
|
mgl@1371
|
9297 |
+should be the maximum value of HARD_REGNO_NREGS(REGNO, MODE)
|
mgl@1371
|
9298 |
+for all REGNO values in the class CLASS.
|
mgl@1371
|
9299 |
+
|
mgl@1371
|
9300 |
+This macro helps control the handling of multiple-word values
|
mgl@1371
|
9301 |
+in the reload pass.
|
mgl@1371
|
9302 |
+*/
|
mgl@1371
|
9303 |
+#define CLASS_MAX_NREGS(CLASS, MODE) /* ToDo:fixme */ \
|
mgl@1371
|
9304 |
+ (unsigned int)((GET_MODE_SIZE(MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
|
mgl@1371
|
9305 |
+
|
mgl@1371
|
9306 |
+
|
mgl@1371
|
9307 |
+/*
|
mgl@1371
|
9308 |
+ Using CONST_OK_FOR_CONSTRAINT_P instead of CONS_OK_FOR_LETTER_P
|
mgl@1371
|
9309 |
+ in order to support constraints with more than one letter.
|
mgl@1371
|
9310 |
+ Only two letters are then used for constant constraints,
|
mgl@1371
|
9311 |
+ the letter 'K' and the letter 'I'. The constraint starting with
|
mgl@1371
|
9312 |
+ these letters must consist of four characters. The character following
|
mgl@1371
|
9313 |
+ 'K' or 'I' must be either 'u' (unsigned) or 's' (signed) to specify
|
mgl@1371
|
9314 |
+ if the constant is zero or sign extended. The last two characters specify
|
mgl@1371
|
9315 |
+ the length in bits of the constant. The base constraint letter 'I' means
|
mgl@1371
|
9316 |
+ that this is an negated constant, meaning that actually -VAL should be
|
mgl@1371
|
9317 |
+ checked to lie withing the valid range instead of VAL which is used when
|
mgl@1371
|
9318 |
+ 'K' is the base constraint letter.
|
mgl@1371
|
9319 |
+
|
mgl@1371
|
9320 |
+*/
|
mgl@1371
|
9321 |
+
|
mgl@1371
|
9322 |
+#define CONSTRAINT_LEN(C, STR) \
|
mgl@1371
|
9323 |
+ ( ((C) == 'K' || (C) == 'I') ? 4 : \
|
mgl@1371
|
9324 |
+ ((C) == 'R') ? 5 : \
|
mgl@1371
|
9325 |
+ ((C) == 'P') ? -1 : \
|
mgl@1371
|
9326 |
+ DEFAULT_CONSTRAINT_LEN((C), (STR)) )
|
mgl@1371
|
9327 |
+
|
mgl@1371
|
9328 |
+#define CONST_OK_FOR_CONSTRAINT_P(VALUE, C, STR) \
|
mgl@1371
|
9329 |
+ avr32_const_ok_for_constraint_p(VALUE, C, STR)
|
mgl@1371
|
9330 |
+
|
mgl@1371
|
9331 |
+/*
|
mgl@1371
|
9332 |
+A C expression that defines the machine-dependent operand constraint
|
mgl@1371
|
9333 |
+letters that specify particular ranges of const_double values ('G' or 'H').
|
mgl@1371
|
9334 |
+
|
mgl@1371
|
9335 |
+If C is one of those letters, the expression should check that
|
mgl@1371
|
9336 |
+VALUE, an RTX of code const_double, is in the appropriate
|
mgl@1371
|
9337 |
+range and return 1 if so, 0 otherwise. If C is not one of those
|
mgl@1371
|
9338 |
+letters, the value should be 0 regardless of VALUE.
|
mgl@1371
|
9339 |
+
|
mgl@1371
|
9340 |
+const_double is used for all floating-point constants and for
|
mgl@1371
|
9341 |
+DImode fixed-point constants. A given letter can accept either
|
mgl@1371
|
9342 |
+or both kinds of values. It can use GET_MODE to distinguish
|
mgl@1371
|
9343 |
+between these kinds.
|
mgl@1371
|
9344 |
+*/
|
mgl@1371
|
9345 |
+#define CONST_DOUBLE_OK_FOR_LETTER_P(OP, C) \
|
mgl@1371
|
9346 |
+ ((C) == 'G' ? avr32_const_double_immediate(OP) : 0)
|
mgl@1371
|
9347 |
+
|
mgl@1371
|
9348 |
+/*
|
mgl@1371
|
9349 |
+A C expression that defines the optional machine-dependent constraint
|
mgl@1371
|
9350 |
+letters that can be used to segregate specific types of operands, usually
|
mgl@1371
|
9351 |
+memory references, for the target machine. Any letter that is not
|
mgl@1371
|
9352 |
+elsewhere defined and not matched by REG_CLASS_FROM_LETTER
|
mgl@1371
|
9353 |
+may be used. Normally this macro will not be defined.
|
mgl@1371
|
9354 |
+
|
mgl@1371
|
9355 |
+If it is required for a particular target machine, it should return 1
|
mgl@1371
|
9356 |
+if VALUE corresponds to the operand type represented by the
|
mgl@1371
|
9357 |
+constraint letter C. If C is not defined as an extra
|
mgl@1371
|
9358 |
+constraint, the value returned should be 0 regardless of VALUE.
|
mgl@1371
|
9359 |
+
|
mgl@1371
|
9360 |
+For example, on the ROMP, load instructions cannot have their output
|
mgl@1371
|
9361 |
+in r0 if the memory reference contains a symbolic address. Constraint
|
mgl@1371
|
9362 |
+letter 'Q' is defined as representing a memory address that does
|
mgl@1371
|
9363 |
+not contain a symbolic address. An alternative is specified with
|
mgl@1371
|
9364 |
+a 'Q' constraint on the input and 'r' on the output. The next
|
mgl@1371
|
9365 |
+alternative specifies 'm' on the input and a register class that
|
mgl@1371
|
9366 |
+does not include r0 on the output.
|
mgl@1371
|
9367 |
+*/
|
mgl@1371
|
9368 |
+#define EXTRA_CONSTRAINT_STR(OP, C, STR) \
|
mgl@1371
|
9369 |
+ ((C) == 'W' ? avr32_address_operand(OP, GET_MODE(OP)) : \
|
mgl@1371
|
9370 |
+ (C) == 'R' ? (avr32_indirect_register_operand(OP, GET_MODE(OP)) || \
|
mgl@1371
|
9371 |
+ (avr32_imm_disp_memory_operand(OP, GET_MODE(OP)) \
|
mgl@1371
|
9372 |
+ && avr32_const_ok_for_constraint_p( \
|
mgl@1371
|
9373 |
+ INTVAL(XEXP(XEXP(OP, 0), 1)), \
|
mgl@1371
|
9374 |
+ (STR)[1], &(STR)[1]))) : \
|
mgl@1371
|
9375 |
+ (C) == 'S' ? avr32_indexed_memory_operand(OP, GET_MODE(OP)) : \
|
mgl@1371
|
9376 |
+ (C) == 'T' ? avr32_const_pool_ref_operand(OP, GET_MODE(OP)) : \
|
mgl@1371
|
9377 |
+ (C) == 'U' ? SYMBOL_REF_RCALL_FUNCTION_P(OP) : \
|
mgl@1371
|
9378 |
+ (C) == 'Z' ? avr32_cop_memory_operand(OP, GET_MODE(OP)) : \
|
mgl@1371
|
9379 |
+ (C) == 'Q' ? avr32_non_rmw_memory_operand(OP, GET_MODE(OP)) : \
|
mgl@1371
|
9380 |
+ (C) == 'Y' ? avr32_rmw_memory_operand(OP, GET_MODE(OP)) : \
|
mgl@1371
|
9381 |
+ 0)
|
mgl@1371
|
9382 |
+
|
mgl@1371
|
9383 |
+
|
mgl@1371
|
9384 |
+#define EXTRA_MEMORY_CONSTRAINT(C, STR) ( ((C) == 'R') || \
|
mgl@1371
|
9385 |
+ ((C) == 'Q') || \
|
mgl@1371
|
9386 |
+ ((C) == 'S') || \
|
mgl@1371
|
9387 |
+ ((C) == 'Y') || \
|
mgl@1371
|
9388 |
+ ((C) == 'Z') )
|
mgl@1371
|
9389 |
+
|
mgl@1371
|
9390 |
+
|
mgl@1371
|
9391 |
+/* Returns nonzero if op is a function SYMBOL_REF which
|
mgl@1371
|
9392 |
+ can be called using an rcall instruction */
|
mgl@1371
|
9393 |
+#define SYMBOL_REF_RCALL_FUNCTION_P(op) \
|
mgl@1371
|
9394 |
+ ( GET_CODE(op) == SYMBOL_REF \
|
mgl@1371
|
9395 |
+ && SYMBOL_REF_FUNCTION_P(op) \
|
mgl@1371
|
9396 |
+ && SYMBOL_REF_LOCAL_P(op) \
|
mgl@1371
|
9397 |
+ && !SYMBOL_REF_EXTERNAL_P(op) \
|
mgl@1371
|
9398 |
+ && !TARGET_HAS_ASM_ADDR_PSEUDOS )
|
mgl@1371
|
9399 |
+
|
mgl@1371
|
9400 |
+/******************************************************************************
|
mgl@1371
|
9401 |
+ * Stack Layout and Calling Conventions
|
mgl@1371
|
9402 |
+ *****************************************************************************/
|
mgl@1371
|
9403 |
+
|
mgl@1371
|
9404 |
+/** Basic Stack Layout **/
|
mgl@1371
|
9405 |
+
|
mgl@1371
|
9406 |
+/*
|
mgl@1371
|
9407 |
+Define this macro if pushing a word onto the stack moves the stack
|
mgl@1371
|
9408 |
+pointer to a smaller address.
|
mgl@1371
|
9409 |
+
|
mgl@1371
|
9410 |
+When we say, ``define this macro if ...,'' it means that the
|
mgl@1371
|
9411 |
+compiler checks this macro only with #ifdef so the precise
|
mgl@1371
|
9412 |
+definition used does not matter.
|
mgl@1371
|
9413 |
+*/
|
mgl@1371
|
9414 |
+/* pushm decrece SP: *(--SP) <-- Rx */
|
mgl@1371
|
9415 |
+#define STACK_GROWS_DOWNWARD
|
mgl@1371
|
9416 |
+
|
mgl@1371
|
9417 |
+/*
|
mgl@1371
|
9418 |
+This macro defines the operation used when something is pushed
|
mgl@1371
|
9419 |
+on the stack. In RTL, a push operation will be
|
mgl@1371
|
9420 |
+(set (mem (STACK_PUSH_CODE (reg sp))) ...)
|
mgl@1371
|
9421 |
+
|
mgl@1371
|
9422 |
+The choices are PRE_DEC, POST_DEC, PRE_INC,
|
mgl@1371
|
9423 |
+and POST_INC. Which of these is correct depends on
|
mgl@1371
|
9424 |
+the stack direction and on whether the stack pointer points
|
mgl@1371
|
9425 |
+to the last item on the stack or whether it points to the
|
mgl@1371
|
9426 |
+space for the next item on the stack.
|
mgl@1371
|
9427 |
+
|
mgl@1371
|
9428 |
+The default is PRE_DEC when STACK_GROWS_DOWNWARD is
|
mgl@1371
|
9429 |
+defined, which is almost always right, and PRE_INC otherwise,
|
mgl@1371
|
9430 |
+which is often wrong.
|
mgl@1371
|
9431 |
+*/
|
mgl@1371
|
9432 |
+/* pushm: *(--SP) <-- Rx */
|
mgl@1371
|
9433 |
+#define STACK_PUSH_CODE PRE_DEC
|
mgl@1371
|
9434 |
+
|
mgl@1371
|
9435 |
+/* Define this to nonzero if the nominal address of the stack frame
|
mgl@1371
|
9436 |
+ is at the high-address end of the local variables;
|
mgl@1371
|
9437 |
+ that is, each additional local variable allocated
|
mgl@1371
|
9438 |
+ goes at a more negative offset in the frame. */
|
mgl@1371
|
9439 |
+#define FRAME_GROWS_DOWNWARD 1
|
mgl@1371
|
9440 |
+
|
mgl@1371
|
9441 |
+
|
mgl@1371
|
9442 |
+/*
|
mgl@1371
|
9443 |
+Offset from the frame pointer to the first local variable slot to be allocated.
|
mgl@1371
|
9444 |
+
|
mgl@1371
|
9445 |
+If FRAME_GROWS_DOWNWARD, find the next slot's offset by
|
mgl@1371
|
9446 |
+subtracting the first slot's length from STARTING_FRAME_OFFSET.
|
mgl@1371
|
9447 |
+Otherwise, it is found by adding the length of the first slot to the
|
mgl@1371
|
9448 |
+value STARTING_FRAME_OFFSET.
|
mgl@1371
|
9449 |
+ (i'm not sure if the above is still correct.. had to change it to get
|
mgl@1371
|
9450 |
+ rid of an overfull. --mew 2feb93 )
|
mgl@1371
|
9451 |
+*/
|
mgl@1371
|
9452 |
+#define STARTING_FRAME_OFFSET 0
|
mgl@1371
|
9453 |
+
|
mgl@1371
|
9454 |
+/*
|
mgl@1371
|
9455 |
+Offset from the stack pointer register to the first location at which
|
mgl@1371
|
9456 |
+outgoing arguments are placed. If not specified, the default value of
|
mgl@1371
|
9457 |
+zero is used. This is the proper value for most machines.
|
mgl@1371
|
9458 |
+
|
mgl@1371
|
9459 |
+If ARGS_GROW_DOWNWARD, this is the offset to the location above
|
mgl@1371
|
9460 |
+the first location at which outgoing arguments are placed.
|
mgl@1371
|
9461 |
+*/
|
mgl@1371
|
9462 |
+#define STACK_POINTER_OFFSET 0
|
mgl@1371
|
9463 |
+
|
mgl@1371
|
9464 |
+/*
|
mgl@1371
|
9465 |
+Offset from the argument pointer register to the first argument's
|
mgl@1371
|
9466 |
+address. On some machines it may depend on the data type of the
|
mgl@1371
|
9467 |
+function.
|
mgl@1371
|
9468 |
+
|
mgl@1371
|
9469 |
+If ARGS_GROW_DOWNWARD, this is the offset to the location above
|
mgl@1371
|
9470 |
+the first argument's address.
|
mgl@1371
|
9471 |
+*/
|
mgl@1371
|
9472 |
+#define FIRST_PARM_OFFSET(FUNDECL) 0
|
mgl@1371
|
9473 |
+
|
mgl@1371
|
9474 |
+
|
mgl@1371
|
9475 |
+/*
|
mgl@1371
|
9476 |
+A C expression whose value is RTL representing the address in a stack
|
mgl@1371
|
9477 |
+frame where the pointer to the caller's frame is stored. Assume that
|
mgl@1371
|
9478 |
+FRAMEADDR is an RTL expression for the address of the stack frame
|
mgl@1371
|
9479 |
+itself.
|
mgl@1371
|
9480 |
+
|
mgl@1371
|
9481 |
+If you don't define this macro, the default is to return the value
|
mgl@1371
|
9482 |
+of FRAMEADDR - that is, the stack frame address is also the
|
mgl@1371
|
9483 |
+address of the stack word that points to the previous frame.
|
mgl@1371
|
9484 |
+*/
|
mgl@1371
|
9485 |
+#define DYNAMIC_CHAIN_ADDRESS(FRAMEADDR) plus_constant ((FRAMEADDR), 4)
|
mgl@1371
|
9486 |
+
|
mgl@1371
|
9487 |
+
|
mgl@1371
|
9488 |
+/*
|
mgl@1371
|
9489 |
+A C expression whose value is RTL representing the value of the return
|
mgl@1371
|
9490 |
+address for the frame COUNT steps up from the current frame, after
|
mgl@1371
|
9491 |
+the prologue. FRAMEADDR is the frame pointer of the COUNT
|
mgl@1371
|
9492 |
+frame, or the frame pointer of the COUNT - 1 frame if
|
mgl@1371
|
9493 |
+RETURN_ADDR_IN_PREVIOUS_FRAME is defined.
|
mgl@1371
|
9494 |
+
|
mgl@1371
|
9495 |
+The value of the expression must always be the correct address when
|
mgl@1371
|
9496 |
+COUNT is zero, but may be NULL_RTX if there is not way to
|
mgl@1371
|
9497 |
+determine the return address of other frames.
|
mgl@1371
|
9498 |
+*/
|
mgl@1371
|
9499 |
+#define RETURN_ADDR_RTX(COUNT, FRAMEADDR) avr32_return_addr(COUNT, FRAMEADDR)
|
mgl@1371
|
9500 |
+
|
mgl@1371
|
9501 |
+
|
mgl@1371
|
9502 |
+/*
|
mgl@1371
|
9503 |
+A C expression whose value is RTL representing the location of the
|
mgl@1371
|
9504 |
+incoming return address at the beginning of any function, before the
|
mgl@1371
|
9505 |
+prologue. This RTL is either a REG, indicating that the return
|
mgl@1371
|
9506 |
+value is saved in 'REG', or a MEM representing a location in
|
mgl@1371
|
9507 |
+the stack.
|
mgl@1371
|
9508 |
+
|
mgl@1371
|
9509 |
+You only need to define this macro if you want to support call frame
|
mgl@1371
|
9510 |
+debugging information like that provided by DWARF 2.
|
mgl@1371
|
9511 |
+
|
mgl@1371
|
9512 |
+If this RTL is a REG, you should also define
|
mgl@1371
|
9513 |
+DWARF_FRAME_RETURN_COLUMN to DWARF_FRAME_REGNUM (REGNO).
|
mgl@1371
|
9514 |
+*/
|
mgl@1371
|
9515 |
+#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, LR_REGNUM)
|
mgl@1371
|
9516 |
+
|
mgl@1371
|
9517 |
+
|
mgl@1371
|
9518 |
+
|
mgl@1371
|
9519 |
+/*
|
mgl@1371
|
9520 |
+A C expression whose value is an integer giving the offset, in bytes,
|
mgl@1371
|
9521 |
+from the value of the stack pointer register to the top of the stack
|
mgl@1371
|
9522 |
+frame at the beginning of any function, before the prologue. The top of
|
mgl@1371
|
9523 |
+the frame is defined to be the value of the stack pointer in the
|
mgl@1371
|
9524 |
+previous frame, just before the call instruction.
|
mgl@1371
|
9525 |
+
|
mgl@1371
|
9526 |
+You only need to define this macro if you want to support call frame
|
mgl@1371
|
9527 |
+debugging information like that provided by DWARF 2.
|
mgl@1371
|
9528 |
+*/
|
mgl@1371
|
9529 |
+#define INCOMING_FRAME_SP_OFFSET 0
|
mgl@1371
|
9530 |
+
|
mgl@1371
|
9531 |
+
|
mgl@1371
|
9532 |
+/** Exception Handling Support **/
|
mgl@1371
|
9533 |
+
|
mgl@1371
|
9534 |
+/* Use setjump/longjump for exception handling. */
|
mgl@1371
|
9535 |
+#define DWARF2_UNWIND_INFO 0
|
mgl@1371
|
9536 |
+#define MUST_USE_SJLJ_EXCEPTIONS 1
|
mgl@1371
|
9537 |
+
|
mgl@1371
|
9538 |
+/*
|
mgl@1371
|
9539 |
+A C expression whose value is the Nth register number used for
|
mgl@1371
|
9540 |
+data by exception handlers, or INVALID_REGNUM if fewer than
|
mgl@1371
|
9541 |
+N registers are usable.
|
mgl@1371
|
9542 |
+
|
mgl@1371
|
9543 |
+The exception handling library routines communicate with the exception
|
mgl@1371
|
9544 |
+handlers via a set of agreed upon registers. Ideally these registers
|
mgl@1371
|
9545 |
+should be call-clobbered; it is possible to use call-saved registers,
|
mgl@1371
|
9546 |
+but may negatively impact code size. The target must support at least
|
mgl@1371
|
9547 |
+2 data registers, but should define 4 if there are enough free registers.
|
mgl@1371
|
9548 |
+
|
mgl@1371
|
9549 |
+You must define this macro if you want to support call frame exception
|
mgl@1371
|
9550 |
+handling like that provided by DWARF 2.
|
mgl@1371
|
9551 |
+*/
|
mgl@1371
|
9552 |
+/*
|
mgl@1371
|
9553 |
+ Use r9-r11
|
mgl@1371
|
9554 |
+*/
|
mgl@1371
|
9555 |
+#define EH_RETURN_DATA_REGNO(N) \
|
mgl@1371
|
9556 |
+ ((N<3) ? INTERNAL_REGNUM(N+9) : INVALID_REGNUM)
|
mgl@1371
|
9557 |
+
|
mgl@1371
|
9558 |
+/*
|
mgl@1371
|
9559 |
+A C expression whose value is RTL representing a location in which
|
mgl@1371
|
9560 |
+to store a stack adjustment to be applied before function return.
|
mgl@1371
|
9561 |
+This is used to unwind the stack to an exception handler's call frame.
|
mgl@1371
|
9562 |
+It will be assigned zero on code paths that return normally.
|
mgl@1371
|
9563 |
+
|
mgl@1371
|
9564 |
+Typically this is a call-clobbered hard register that is otherwise
|
mgl@1371
|
9565 |
+untouched by the epilogue, but could also be a stack slot.
|
mgl@1371
|
9566 |
+
|
mgl@1371
|
9567 |
+You must define this macro if you want to support call frame exception
|
mgl@1371
|
9568 |
+handling like that provided by DWARF 2.
|
mgl@1371
|
9569 |
+*/
|
mgl@1371
|
9570 |
+/*
|
mgl@1371
|
9571 |
+ Use r8
|
mgl@1371
|
9572 |
+*/
|
mgl@1371
|
9573 |
+#define EH_RETURN_STACKADJ_REGNO INTERNAL_REGNUM(8)
|
mgl@1371
|
9574 |
+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG(SImode, EH_RETURN_STACKADJ_REGNO)
|
mgl@1371
|
9575 |
+
|
mgl@1371
|
9576 |
+/*
|
mgl@1371
|
9577 |
+A C expression whose value is RTL representing a location in which
|
mgl@1371
|
9578 |
+to store the address of an exception handler to which we should
|
mgl@1371
|
9579 |
+return. It will not be assigned on code paths that return normally.
|
mgl@1371
|
9580 |
+
|
mgl@1371
|
9581 |
+Typically this is the location in the call frame at which the normal
|
mgl@1371
|
9582 |
+return address is stored. For targets that return by popping an
|
mgl@1371
|
9583 |
+address off the stack, this might be a memory address just below
|
mgl@1371
|
9584 |
+the target call frame rather than inside the current call
|
mgl@1371
|
9585 |
+frame. EH_RETURN_STACKADJ_RTX will have already been assigned,
|
mgl@1371
|
9586 |
+so it may be used to calculate the location of the target call frame.
|
mgl@1371
|
9587 |
+
|
mgl@1371
|
9588 |
+Some targets have more complex requirements than storing to an
|
mgl@1371
|
9589 |
+address calculable during initial code generation. In that case
|
mgl@1371
|
9590 |
+the eh_return instruction pattern should be used instead.
|
mgl@1371
|
9591 |
+
|
mgl@1371
|
9592 |
+If you want to support call frame exception handling, you must
|
mgl@1371
|
9593 |
+define either this macro or the eh_return instruction pattern.
|
mgl@1371
|
9594 |
+*/
|
mgl@1371
|
9595 |
+/*
|
mgl@1371
|
9596 |
+ We define the eh_return instruction pattern, so this isn't needed.
|
mgl@1371
|
9597 |
+*/
|
mgl@1371
|
9598 |
+/* #define EH_RETURN_HANDLER_RTX gen_rtx_REG(Pmode, RET_REGISTER) */
|
mgl@1371
|
9599 |
+
|
mgl@1371
|
9600 |
+/*
|
mgl@1371
|
9601 |
+ This macro chooses the encoding of pointers embedded in the
|
mgl@1371
|
9602 |
+ exception handling sections. If at all possible, this should be
|
mgl@1371
|
9603 |
+ defined such that the exception handling section will not require
|
mgl@1371
|
9604 |
+ dynamic relocations, and so may be read-only.
|
mgl@1371
|
9605 |
+
|
mgl@1371
|
9606 |
+ code is 0 for data, 1 for code labels, 2 for function
|
mgl@1371
|
9607 |
+ pointers. global is true if the symbol may be affected by dynamic
|
mgl@1371
|
9608 |
+ relocations. The macro should return a combination of the DW_EH_PE_*
|
mgl@1371
|
9609 |
+ defines as found in dwarf2.h.
|
mgl@1371
|
9610 |
+
|
mgl@1371
|
9611 |
+ If this macro is not defined, pointers will not be encoded but
|
mgl@1371
|
9612 |
+ represented directly.
|
mgl@1371
|
9613 |
+*/
|
mgl@1371
|
9614 |
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL) \
|
mgl@1371
|
9615 |
+ ((flag_pic && (GLOBAL) ? DW_EH_PE_indirect : 0) \
|
mgl@1371
|
9616 |
+ | (flag_pic ? DW_EH_PE_pcrel : DW_EH_PE_absptr) \
|
mgl@1371
|
9617 |
+ | DW_EH_PE_sdata4)
|
mgl@1371
|
9618 |
+
|
mgl@1371
|
9619 |
+/* ToDo: The rest of this subsection */
|
mgl@1371
|
9620 |
+
|
mgl@1371
|
9621 |
+/** Specifying How Stack Checking is Done **/
|
mgl@1371
|
9622 |
+/* ToDo: All in this subsection */
|
mgl@1371
|
9623 |
+
|
mgl@1371
|
9624 |
+/** Registers That Address the Stack Frame **/
|
mgl@1371
|
9625 |
+
|
mgl@1371
|
9626 |
+/*
|
mgl@1371
|
9627 |
+The register number of the stack pointer register, which must also be a
|
mgl@1371
|
9628 |
+fixed register according to FIXED_REGISTERS. On most machines,
|
mgl@1371
|
9629 |
+the hardware determines which register this is.
|
mgl@1371
|
9630 |
+*/
|
mgl@1371
|
9631 |
+/* Using r13 as stack pointer. */
|
mgl@1371
|
9632 |
+#define STACK_POINTER_REGNUM INTERNAL_REGNUM(13)
|
mgl@1371
|
9633 |
+
|
mgl@1371
|
9634 |
+/*
|
mgl@1371
|
9635 |
+The register number of the frame pointer register, which is used to
|
mgl@1371
|
9636 |
+access automatic variables in the stack frame. On some machines, the
|
mgl@1371
|
9637 |
+hardware determines which register this is. On other machines, you can
|
mgl@1371
|
9638 |
+choose any register you wish for this purpose.
|
mgl@1371
|
9639 |
+*/
|
mgl@1371
|
9640 |
+/* Use r7 */
|
mgl@1371
|
9641 |
+#define FRAME_POINTER_REGNUM INTERNAL_REGNUM(7)
|
mgl@1371
|
9642 |
+
|
mgl@1371
|
9643 |
+
|
mgl@1371
|
9644 |
+
|
mgl@1371
|
9645 |
+/*
|
mgl@1371
|
9646 |
+The register number of the arg pointer register, which is used to access
|
mgl@1371
|
9647 |
+the function's argument list. On some machines, this is the same as the
|
mgl@1371
|
9648 |
+frame pointer register. On some machines, the hardware determines which
|
mgl@1371
|
9649 |
+register this is. On other machines, you can choose any register you
|
mgl@1371
|
9650 |
+wish for this purpose. If this is not the same register as the frame
|
mgl@1371
|
9651 |
+pointer register, then you must mark it as a fixed register according to
|
mgl@1371
|
9652 |
+FIXED_REGISTERS, or arrange to be able to eliminate it (see Section
|
mgl@1371
|
9653 |
+10.10.5 [Elimination], page 224).
|
mgl@1371
|
9654 |
+*/
|
mgl@1371
|
9655 |
+/* Using r5 */
|
mgl@1371
|
9656 |
+#define ARG_POINTER_REGNUM INTERNAL_REGNUM(4)
|
mgl@1371
|
9657 |
+
|
mgl@1371
|
9658 |
+
|
mgl@1371
|
9659 |
+/*
|
mgl@1371
|
9660 |
+Register numbers used for passing a function's static chain pointer. If
|
mgl@1371
|
9661 |
+register windows are used, the register number as seen by the called
|
mgl@1371
|
9662 |
+function is STATIC_CHAIN_INCOMING_REGNUM, while the register
|
mgl@1371
|
9663 |
+number as seen by the calling function is STATIC_CHAIN_REGNUM. If
|
mgl@1371
|
9664 |
+these registers are the same, STATIC_CHAIN_INCOMING_REGNUM need
|
mgl@1371
|
9665 |
+not be defined.
|
mgl@1371
|
9666 |
+
|
mgl@1371
|
9667 |
+The static chain register need not be a fixed register.
|
mgl@1371
|
9668 |
+
|
mgl@1371
|
9669 |
+If the static chain is passed in memory, these macros should not be
|
mgl@1371
|
9670 |
+defined; instead, the next two macros should be defined.
|
mgl@1371
|
9671 |
+*/
|
mgl@1371
|
9672 |
+/* Using r0 */
|
mgl@1371
|
9673 |
+#define STATIC_CHAIN_REGNUM INTERNAL_REGNUM(0)
|
mgl@1371
|
9674 |
+
|
mgl@1371
|
9675 |
+
|
mgl@1371
|
9676 |
+/** Eliminating Frame Pointer and Arg Pointer **/
|
mgl@1371
|
9677 |
+
|
mgl@1371
|
9678 |
+/*
|
mgl@1371
|
9679 |
+A C expression which is nonzero if a function must have and use a frame
|
mgl@1371
|
9680 |
+pointer. This expression is evaluated in the reload pass. If its value is
|
mgl@1371
|
9681 |
+nonzero the function will have a frame pointer.
|
mgl@1371
|
9682 |
+
|
mgl@1371
|
9683 |
+The expression can in principle examine the current function and decide
|
mgl@1371
|
9684 |
+according to the facts, but on most machines the constant 0 or the
|
mgl@1371
|
9685 |
+constant 1 suffices. Use 0 when the machine allows code to be generated
|
mgl@1371
|
9686 |
+with no frame pointer, and doing so saves some time or space. Use 1
|
mgl@1371
|
9687 |
+when there is no possible advantage to avoiding a frame pointer.
|
mgl@1371
|
9688 |
+
|
mgl@1371
|
9689 |
+In certain cases, the compiler does not know how to produce valid code
|
mgl@1371
|
9690 |
+without a frame pointer. The compiler recognizes those cases and
|
mgl@1371
|
9691 |
+automatically gives the function a frame pointer regardless of what
|
mgl@1371
|
9692 |
+FRAME_POINTER_REQUIRED says. You don't need to worry about
|
mgl@1371
|
9693 |
+them.
|
mgl@1371
|
9694 |
+
|
mgl@1371
|
9695 |
+In a function that does not require a frame pointer, the frame pointer
|
mgl@1371
|
9696 |
+register can be allocated for ordinary usage, unless you mark it as a
|
mgl@1371
|
9697 |
+fixed register. See FIXED_REGISTERS for more information.
|
mgl@1371
|
9698 |
+*/
|
mgl@1371
|
9699 |
+/* We need the frame pointer when compiling for profiling */
|
mgl@1371
|
9700 |
+#define FRAME_POINTER_REQUIRED (current_function_profile)
|
mgl@1371
|
9701 |
+
|
mgl@1371
|
9702 |
+/*
|
mgl@1371
|
9703 |
+A C statement to store in the variable DEPTH_VAR the difference
|
mgl@1371
|
9704 |
+between the frame pointer and the stack pointer values immediately after
|
mgl@1371
|
9705 |
+the function prologue. The value would be computed from information
|
mgl@1371
|
9706 |
+such as the result of get_frame_size () and the tables of
|
mgl@1371
|
9707 |
+registers regs_ever_live and call_used_regs.
|
mgl@1371
|
9708 |
+
|
mgl@1371
|
9709 |
+If ELIMINABLE_REGS is defined, this macro will be not be used and
|
mgl@1371
|
9710 |
+need not be defined. Otherwise, it must be defined even if
|
mgl@1371
|
9711 |
+FRAME_POINTER_REQUIRED is defined to always be true; in that
|
mgl@1371
|
9712 |
+case, you may set DEPTH_VAR to anything.
|
mgl@1371
|
9713 |
+*/
|
mgl@1371
|
9714 |
+#define INITIAL_FRAME_POINTER_OFFSET(DEPTH_VAR) ((DEPTH_VAR) = get_frame_size())
|
mgl@1371
|
9715 |
+
|
mgl@1371
|
9716 |
+/*
|
mgl@1371
|
9717 |
+If defined, this macro specifies a table of register pairs used to
|
mgl@1371
|
9718 |
+eliminate unneeded registers that point into the stack frame. If it is not
|
mgl@1371
|
9719 |
+defined, the only elimination attempted by the compiler is to replace
|
mgl@1371
|
9720 |
+references to the frame pointer with references to the stack pointer.
|
mgl@1371
|
9721 |
+
|
mgl@1371
|
9722 |
+The definition of this macro is a list of structure initializations, each
|
mgl@1371
|
9723 |
+of which specifies an original and replacement register.
|
mgl@1371
|
9724 |
+
|
mgl@1371
|
9725 |
+On some machines, the position of the argument pointer is not known until
|
mgl@1371
|
9726 |
+the compilation is completed. In such a case, a separate hard register
|
mgl@1371
|
9727 |
+must be used for the argument pointer. This register can be eliminated by
|
mgl@1371
|
9728 |
+replacing it with either the frame pointer or the argument pointer,
|
mgl@1371
|
9729 |
+depending on whether or not the frame pointer has been eliminated.
|
mgl@1371
|
9730 |
+
|
mgl@1371
|
9731 |
+In this case, you might specify:
|
mgl@1371
|
9732 |
+ #define ELIMINABLE_REGS \
|
mgl@1371
|
9733 |
+ {{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
|
mgl@1371
|
9734 |
+ {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
|
mgl@1371
|
9735 |
+ {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}}
|
mgl@1371
|
9736 |
+
|
mgl@1371
|
9737 |
+Note that the elimination of the argument pointer with the stack pointer is
|
mgl@1371
|
9738 |
+specified first since that is the preferred elimination.
|
mgl@1371
|
9739 |
+*/
|
mgl@1371
|
9740 |
+#define ELIMINABLE_REGS \
|
mgl@1371
|
9741 |
+{ \
|
mgl@1371
|
9742 |
+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
|
mgl@1371
|
9743 |
+ { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
|
mgl@1371
|
9744 |
+ { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM } \
|
mgl@1371
|
9745 |
+}
|
mgl@1371
|
9746 |
+
|
mgl@1371
|
9747 |
+/*
|
mgl@1371
|
9748 |
+A C expression that returns nonzero if the compiler is allowed to try
|
mgl@1371
|
9749 |
+to replace register number FROM with register number
|
mgl@1371
|
9750 |
+TO. This macro need only be defined if ELIMINABLE_REGS
|
mgl@1371
|
9751 |
+is defined, and will usually be the constant 1, since most of the cases
|
mgl@1371
|
9752 |
+preventing register elimination are things that the compiler already
|
mgl@1371
|
9753 |
+knows about.
|
mgl@1371
|
9754 |
+*/
|
mgl@1371
|
9755 |
+#define CAN_ELIMINATE(FROM, TO) 1
|
mgl@1371
|
9756 |
+
|
mgl@1371
|
9757 |
+/*
|
mgl@1371
|
9758 |
+This macro is similar to INITIAL_FRAME_POINTER_OFFSET. It
|
mgl@1371
|
9759 |
+specifies the initial difference between the specified pair of
|
mgl@1371
|
9760 |
+registers. This macro must be defined if ELIMINABLE_REGS is
|
mgl@1371
|
9761 |
+defined.
|
mgl@1371
|
9762 |
+*/
|
mgl@1371
|
9763 |
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
|
mgl@1371
|
9764 |
+ ((OFFSET) = avr32_initial_elimination_offset(FROM, TO))
|
mgl@1371
|
9765 |
+
|
mgl@1371
|
9766 |
+/** Passing Function Arguments on the Stack **/
|
mgl@1371
|
9767 |
+
|
mgl@1371
|
9768 |
+
|
mgl@1371
|
9769 |
+/*
|
mgl@1371
|
9770 |
+A C expression. If nonzero, push insns will be used to pass
|
mgl@1371
|
9771 |
+outgoing arguments.
|
mgl@1371
|
9772 |
+If the target machine does not have a push instruction, set it to zero.
|
mgl@1371
|
9773 |
+That directs GCC to use an alternate strategy: to
|
mgl@1371
|
9774 |
+allocate the entire argument block and then store the arguments into
|
mgl@1371
|
9775 |
+it. When PUSH_ARGS is nonzero, PUSH_ROUNDING must be defined too.
|
mgl@1371
|
9776 |
+*/
|
mgl@1371
|
9777 |
+#define PUSH_ARGS 1
|
mgl@1371
|
9778 |
+
|
mgl@1371
|
9779 |
+
|
mgl@1371
|
9780 |
+/*
|
mgl@1371
|
9781 |
+A C expression that is the number of bytes actually pushed onto the
|
mgl@1371
|
9782 |
+stack when an instruction attempts to push NPUSHED bytes.
|
mgl@1371
|
9783 |
+
|
mgl@1371
|
9784 |
+On some machines, the definition
|
mgl@1371
|
9785 |
+
|
mgl@1371
|
9786 |
+ #define PUSH_ROUNDING(BYTES) (BYTES)
|
mgl@1371
|
9787 |
+
|
mgl@1371
|
9788 |
+will suffice. But on other machines, instructions that appear
|
mgl@1371
|
9789 |
+to push one byte actually push two bytes in an attempt to maintain
|
mgl@1371
|
9790 |
+alignment. Then the definition should be
|
mgl@1371
|
9791 |
+
|
mgl@1371
|
9792 |
+ #define PUSH_ROUNDING(BYTES) (((BYTES) + 1) & ~1)
|
mgl@1371
|
9793 |
+*/
|
mgl@1371
|
9794 |
+/* Push 4 bytes at the time. */
|
mgl@1371
|
9795 |
+#define PUSH_ROUNDING(NPUSHED) (((NPUSHED) + 3) & ~3)
|
mgl@1371
|
9796 |
+
|
mgl@1371
|
9797 |
+/*
|
mgl@1371
|
9798 |
+A C expression. If nonzero, the maximum amount of space required for
|
mgl@1371
|
9799 |
+outgoing arguments will be computed and placed into the variable
|
mgl@1371
|
9800 |
+current_function_outgoing_args_size. No space will be pushed
|
mgl@1371
|
9801 |
+onto the stack for each call; instead, the function prologue should
|
mgl@1371
|
9802 |
+increase the stack frame size by this amount.
|
mgl@1371
|
9803 |
+
|
mgl@1371
|
9804 |
+Setting both PUSH_ARGS and ACCUMULATE_OUTGOING_ARGS is not proper.
|
mgl@1371
|
9805 |
+*/
|
mgl@1371
|
9806 |
+#define ACCUMULATE_OUTGOING_ARGS 0
|
mgl@1371
|
9807 |
+
|
mgl@1371
|
9808 |
+
|
mgl@1371
|
9809 |
+
|
mgl@1371
|
9810 |
+
|
mgl@1371
|
9811 |
+/*
|
mgl@1371
|
9812 |
+A C expression that should indicate the number of bytes of its own
|
mgl@1371
|
9813 |
+arguments that a function pops on returning, or 0 if the
|
mgl@1371
|
9814 |
+function pops no arguments and the caller must therefore pop them all
|
mgl@1371
|
9815 |
+after the function returns.
|
mgl@1371
|
9816 |
+
|
mgl@1371
|
9817 |
+FUNDECL is a C variable whose value is a tree node that describes
|
mgl@1371
|
9818 |
+the function in question. Normally it is a node of type
|
mgl@1371
|
9819 |
+FUNCTION_DECL that describes the declaration of the function.
|
mgl@1371
|
9820 |
+From this you can obtain the DECL_ATTRIBUTES of the function.
|
mgl@1371
|
9821 |
+
|
mgl@1371
|
9822 |
+FUNTYPE is a C variable whose value is a tree node that
|
mgl@1371
|
9823 |
+describes the function in question. Normally it is a node of type
|
mgl@1371
|
9824 |
+FUNCTION_TYPE that describes the data type of the function.
|
mgl@1371
|
9825 |
+From this it is possible to obtain the data types of the value and
|
mgl@1371
|
9826 |
+arguments (if known).
|
mgl@1371
|
9827 |
+
|
mgl@1371
|
9828 |
+When a call to a library function is being considered, FUNDECL
|
mgl@1371
|
9829 |
+will contain an identifier node for the library function. Thus, if
|
mgl@1371
|
9830 |
+you need to distinguish among various library functions, you can do so
|
mgl@1371
|
9831 |
+by their names. Note that ``library function'' in this context means
|
mgl@1371
|
9832 |
+a function used to perform arithmetic, whose name is known specially
|
mgl@1371
|
9833 |
+in the compiler and was not mentioned in the C code being compiled.
|
mgl@1371
|
9834 |
+
|
mgl@1371
|
9835 |
+STACK_SIZE is the number of bytes of arguments passed on the
|
mgl@1371
|
9836 |
+stack. If a variable number of bytes is passed, it is zero, and
|
mgl@1371
|
9837 |
+argument popping will always be the responsibility of the calling function.
|
mgl@1371
|
9838 |
+
|
mgl@1371
|
9839 |
+On the VAX, all functions always pop their arguments, so the definition
|
mgl@1371
|
9840 |
+of this macro is STACK_SIZE. On the 68000, using the standard
|
mgl@1371
|
9841 |
+calling convention, no functions pop their arguments, so the value of
|
mgl@1371
|
9842 |
+the macro is always 0 in this case. But an alternative calling
|
mgl@1371
|
9843 |
+convention is available in which functions that take a fixed number of
|
mgl@1371
|
9844 |
+arguments pop them but other functions (such as printf) pop
|
mgl@1371
|
9845 |
+nothing (the caller pops all). When this convention is in use,
|
mgl@1371
|
9846 |
+FUNTYPE is examined to determine whether a function takes a fixed
|
mgl@1371
|
9847 |
+number of arguments.
|
mgl@1371
|
9848 |
+*/
|
mgl@1371
|
9849 |
+#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0
|
mgl@1371
|
9850 |
+
|
mgl@1371
|
9851 |
+
|
mgl@1371
|
9852 |
+/*Return true if this function can we use a single return instruction*/
|
mgl@1371
|
9853 |
+#define USE_RETURN_INSN(ISCOND) avr32_use_return_insn(ISCOND)
|
mgl@1371
|
9854 |
+
|
mgl@1371
|
9855 |
+/*
|
mgl@1371
|
9856 |
+A C expression that should indicate the number of bytes a call sequence
|
mgl@1371
|
9857 |
+pops off the stack. It is added to the value of RETURN_POPS_ARGS
|
mgl@1371
|
9858 |
+when compiling a function call.
|
mgl@1371
|
9859 |
+
|
mgl@1371
|
9860 |
+CUM is the variable in which all arguments to the called function
|
mgl@1371
|
9861 |
+have been accumulated.
|
mgl@1371
|
9862 |
+
|
mgl@1371
|
9863 |
+On certain architectures, such as the SH5, a call trampoline is used
|
mgl@1371
|
9864 |
+that pops certain registers off the stack, depending on the arguments
|
mgl@1371
|
9865 |
+that have been passed to the function. Since this is a property of the
|
mgl@1371
|
9866 |
+call site, not of the called function, RETURN_POPS_ARGS is not
|
mgl@1371
|
9867 |
+appropriate.
|
mgl@1371
|
9868 |
+*/
|
mgl@1371
|
9869 |
+#define CALL_POPS_ARGS(CUM) 0
|
mgl@1371
|
9870 |
+
|
mgl@1371
|
9871 |
+/* Passing Arguments in Registers */
|
mgl@1371
|
9872 |
+
|
mgl@1371
|
9873 |
+/*
|
mgl@1371
|
9874 |
+A C expression that controls whether a function argument is passed
|
mgl@1371
|
9875 |
+in a register, and which register.
|
mgl@1371
|
9876 |
+
|
mgl@1371
|
9877 |
+The arguments are CUM, which summarizes all the previous
|
mgl@1371
|
9878 |
+arguments; MODE, the machine mode of the argument; TYPE,
|
mgl@1371
|
9879 |
+the data type of the argument as a tree node or 0 if that is not known
|
mgl@1371
|
9880 |
+(which happens for C support library functions); and NAMED,
|
mgl@1371
|
9881 |
+which is 1 for an ordinary argument and 0 for nameless arguments that
|
mgl@1371
|
9882 |
+correspond to '...' in the called function's prototype.
|
mgl@1371
|
9883 |
+TYPE can be an incomplete type if a syntax error has previously
|
mgl@1371
|
9884 |
+occurred.
|
mgl@1371
|
9885 |
+
|
mgl@1371
|
9886 |
+The value of the expression is usually either a reg RTX for the
|
mgl@1371
|
9887 |
+hard register in which to pass the argument, or zero to pass the
|
mgl@1371
|
9888 |
+argument on the stack.
|
mgl@1371
|
9889 |
+
|
mgl@1371
|
9890 |
+For machines like the VAX and 68000, where normally all arguments are
|
mgl@1371
|
9891 |
+pushed, zero suffices as a definition.
|
mgl@1371
|
9892 |
+
|
mgl@1371
|
9893 |
+The value of the expression can also be a parallel RTX. This is
|
mgl@1371
|
9894 |
+used when an argument is passed in multiple locations. The mode of the
|
mgl@1371
|
9895 |
+of the parallel should be the mode of the entire argument. The
|
mgl@1371
|
9896 |
+parallel holds any number of expr_list pairs; each one
|
mgl@1371
|
9897 |
+describes where part of the argument is passed. In each
|
mgl@1371
|
9898 |
+expr_list the first operand must be a reg RTX for the hard
|
mgl@1371
|
9899 |
+register in which to pass this part of the argument, and the mode of the
|
mgl@1371
|
9900 |
+register RTX indicates how large this part of the argument is. The
|
mgl@1371
|
9901 |
+second operand of the expr_list is a const_int which gives
|
mgl@1371
|
9902 |
+the offset in bytes into the entire argument of where this part starts.
|
mgl@1371
|
9903 |
+As a special exception the first expr_list in the parallel
|
mgl@1371
|
9904 |
+RTX may have a first operand of zero. This indicates that the entire
|
mgl@1371
|
9905 |
+argument is also stored on the stack.
|
mgl@1371
|
9906 |
+
|
mgl@1371
|
9907 |
+The last time this macro is called, it is called with MODE == VOIDmode,
|
mgl@1371
|
9908 |
+and its result is passed to the call or call_value
|
mgl@1371
|
9909 |
+pattern as operands 2 and 3 respectively.
|
mgl@1371
|
9910 |
+
|
mgl@1371
|
9911 |
+The usual way to make the ISO library 'stdarg.h' work on a machine
|
mgl@1371
|
9912 |
+where some arguments are usually passed in registers, is to cause
|
mgl@1371
|
9913 |
+nameless arguments to be passed on the stack instead. This is done
|
mgl@1371
|
9914 |
+by making FUNCTION_ARG return 0 whenever NAMED is 0.
|
mgl@1371
|
9915 |
+
|
mgl@1371
|
9916 |
+You may use the macro MUST_PASS_IN_STACK (MODE, TYPE)
|
mgl@1371
|
9917 |
+in the definition of this macro to determine if this argument is of a
|
mgl@1371
|
9918 |
+type that must be passed in the stack. If REG_PARM_STACK_SPACE
|
mgl@1371
|
9919 |
+is not defined and FUNCTION_ARG returns nonzero for such an
|
mgl@1371
|
9920 |
+argument, the compiler will abort. If REG_PARM_STACK_SPACE is
|
mgl@1371
|
9921 |
+defined, the argument will be computed in the stack and then loaded into
|
mgl@1371
|
9922 |
+a register. */
|
mgl@1371
|
9923 |
+
|
mgl@1371
|
9924 |
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
|
mgl@1371
|
9925 |
+ avr32_function_arg(&(CUM), MODE, TYPE, NAMED)
|
mgl@1371
|
9926 |
+
|
mgl@1371
|
9927 |
+
|
mgl@1371
|
9928 |
+
|
mgl@1371
|
9929 |
+
|
mgl@1371
|
9930 |
+/*
|
mgl@1371
|
9931 |
+A C type for declaring a variable that is used as the first argument of
|
mgl@1371
|
9932 |
+FUNCTION_ARG and other related values. For some target machines,
|
mgl@1371
|
9933 |
+the type int suffices and can hold the number of bytes of
|
mgl@1371
|
9934 |
+argument so far.
|
mgl@1371
|
9935 |
+
|
mgl@1371
|
9936 |
+There is no need to record in CUMULATIVE_ARGS anything about the
|
mgl@1371
|
9937 |
+arguments that have been passed on the stack. The compiler has other
|
mgl@1371
|
9938 |
+variables to keep track of that. For target machines on which all
|
mgl@1371
|
9939 |
+arguments are passed on the stack, there is no need to store anything in
|
mgl@1371
|
9940 |
+CUMULATIVE_ARGS; however, the data structure must exist and
|
mgl@1371
|
9941 |
+should not be empty, so use int.
|
mgl@1371
|
9942 |
+*/
|
mgl@1371
|
9943 |
+typedef struct avr32_args
|
mgl@1371
|
9944 |
+{
|
mgl@1371
|
9945 |
+ /* Index representing the argument register the current function argument
|
mgl@1371
|
9946 |
+ will occupy */
|
mgl@1371
|
9947 |
+ int index;
|
mgl@1371
|
9948 |
+ /* A mask with bits representing the argument registers: if a bit is set
|
mgl@1371
|
9949 |
+ then this register is used for an arguemnt */
|
mgl@1371
|
9950 |
+ int used_index;
|
mgl@1371
|
9951 |
+ /* TRUE if this function has anonymous arguments */
|
mgl@1371
|
9952 |
+ int uses_anonymous_args;
|
mgl@1371
|
9953 |
+ /* The size in bytes of the named arguments pushed on the stack */
|
mgl@1371
|
9954 |
+ int stack_pushed_args_size;
|
mgl@1371
|
9955 |
+ /* Set to true if this function needs a Return Value Pointer */
|
mgl@1371
|
9956 |
+ int use_rvp;
|
mgl@1371
|
9957 |
+
|
mgl@1371
|
9958 |
+} CUMULATIVE_ARGS;
|
mgl@1371
|
9959 |
+
|
mgl@1371
|
9960 |
+
|
mgl@1371
|
9961 |
+#define FIRST_CUM_REG_INDEX 0
|
mgl@1371
|
9962 |
+#define LAST_CUM_REG_INDEX 4
|
mgl@1371
|
9963 |
+#define GET_REG_INDEX(CUM) ((CUM)->index)
|
mgl@1371
|
9964 |
+#define SET_REG_INDEX(CUM, INDEX) ((CUM)->index = (INDEX));
|
mgl@1371
|
9965 |
+#define GET_USED_INDEX(CUM, INDEX) ((CUM)->used_index & (1 << (INDEX)))
|
mgl@1371
|
9966 |
+#define SET_USED_INDEX(CUM, INDEX) \
|
mgl@1371
|
9967 |
+ do \
|
mgl@1371
|
9968 |
+ { \
|
mgl@1371
|
9969 |
+ if (INDEX >= 0) \
|
mgl@1371
|
9970 |
+ (CUM)->used_index |= (1 << (INDEX)); \
|
mgl@1371
|
9971 |
+ } \
|
mgl@1371
|
9972 |
+ while (0)
|
mgl@1371
|
9973 |
+#define SET_INDEXES_UNUSED(CUM) ((CUM)->used_index = 0)
|
mgl@1371
|
9974 |
+
|
mgl@1371
|
9975 |
+
|
mgl@1371
|
9976 |
+/*
|
mgl@1371
|
9977 |
+ A C statement (sans semicolon) for initializing the variable cum for the
|
mgl@1371
|
9978 |
+ state at the beginning of the argument list. The variable has type
|
mgl@1371
|
9979 |
+ CUMULATIVE_ARGS. The value of FNTYPE is the tree node for the data type of
|
mgl@1371
|
9980 |
+ the function which will receive the args, or 0 if the args are to a compiler
|
mgl@1371
|
9981 |
+ support library function. For direct calls that are not libcalls, FNDECL
|
mgl@1371
|
9982 |
+ contain the declaration node of the function. FNDECL is also set when
|
mgl@1371
|
9983 |
+ INIT_CUMULATIVE_ARGS is used to find arguments for the function being
|
mgl@1371
|
9984 |
+ compiled. N_NAMED_ARGS is set to the number of named arguments, including a
|
mgl@1371
|
9985 |
+ structure return address if it is passed as a parameter, when making a call.
|
mgl@1371
|
9986 |
+ When processing incoming arguments, N_NAMED_ARGS is set to -1.
|
mgl@1371
|
9987 |
+
|
mgl@1371
|
9988 |
+ When processing a call to a compiler support library function, LIBNAME
|
mgl@1371
|
9989 |
+ identifies which one. It is a symbol_ref rtx which contains the name of the
|
mgl@1371
|
9990 |
+ function, as a string. LIBNAME is 0 when an ordinary C function call is
|
mgl@1371
|
9991 |
+ being processed. Thus, each time this macro is called, either LIBNAME or
|
mgl@1371
|
9992 |
+ FNTYPE is nonzero, but never both of them at once.
|
mgl@1371
|
9993 |
+*/
|
mgl@1371
|
9994 |
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
|
mgl@1371
|
9995 |
+ avr32_init_cumulative_args(&(CUM), FNTYPE, LIBNAME, FNDECL)
|
mgl@1371
|
9996 |
+
|
mgl@1371
|
9997 |
+
|
mgl@1371
|
9998 |
+/*
|
mgl@1371
|
9999 |
+A C statement (sans semicolon) to update the summarizer variable
|
mgl@1371
|
10000 |
+CUM to advance past an argument in the argument list. The
|
mgl@1371
|
10001 |
+values MODE, TYPE and NAMED describe that argument.
|
mgl@1371
|
10002 |
+Once this is done, the variable CUM is suitable for analyzing
|
mgl@1371
|
10003 |
+the following argument with FUNCTION_ARG, etc.
|
mgl@1371
|
10004 |
+
|
mgl@1371
|
10005 |
+This macro need not do anything if the argument in question was passed
|
mgl@1371
|
10006 |
+on the stack. The compiler knows how to track the amount of stack space
|
mgl@1371
|
10007 |
+used for arguments without any special help.
|
mgl@1371
|
10008 |
+*/
|
mgl@1371
|
10009 |
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
|
mgl@1371
|
10010 |
+ avr32_function_arg_advance(&(CUM), MODE, TYPE, NAMED)
|
mgl@1371
|
10011 |
+
|
mgl@1371
|
10012 |
+/*
|
mgl@1371
|
10013 |
+If defined, a C expression which determines whether, and in which direction,
|
mgl@1371
|
10014 |
+to pad out an argument with extra space. The value should be of type
|
mgl@1371
|
10015 |
+enum direction: either 'upward' to pad above the argument,
|
mgl@1371
|
10016 |
+'downward' to pad below, or 'none' to inhibit padding.
|
mgl@1371
|
10017 |
+
|
mgl@1371
|
10018 |
+The amount of padding is always just enough to reach the next
|
mgl@1371
|
10019 |
+multiple of FUNCTION_ARG_BOUNDARY; this macro does not control
|
mgl@1371
|
10020 |
+it.
|
mgl@1371
|
10021 |
+
|
mgl@1371
|
10022 |
+This macro has a default definition which is right for most systems.
|
mgl@1371
|
10023 |
+For little-endian machines, the default is to pad upward. For
|
mgl@1371
|
10024 |
+big-endian machines, the default is to pad downward for an argument of
|
mgl@1371
|
10025 |
+constant size shorter than an int, and upward otherwise.
|
mgl@1371
|
10026 |
+*/
|
mgl@1371
|
10027 |
+#define FUNCTION_ARG_PADDING(MODE, TYPE) \
|
mgl@1371
|
10028 |
+ avr32_function_arg_padding(MODE, TYPE)
|
mgl@1371
|
10029 |
+
|
mgl@1371
|
10030 |
+/*
|
mgl@1371
|
10031 |
+ Specify padding for the last element of a block move between registers
|
mgl@1371
|
10032 |
+ and memory. First is nonzero if this is the only element. Defining
|
mgl@1371
|
10033 |
+ this macro allows better control of register function parameters on
|
mgl@1371
|
10034 |
+ big-endian machines, without using PARALLEL rtl. In particular,
|
mgl@1371
|
10035 |
+ MUST_PASS_IN_STACK need not test padding and mode of types in registers,
|
mgl@1371
|
10036 |
+ as there is no longer a "wrong" part of a register; For example, a three
|
mgl@1371
|
10037 |
+ byte aggregate may be passed in the high part of a register if so required.
|
mgl@1371
|
10038 |
+*/
|
mgl@1371
|
10039 |
+#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
|
mgl@1371
|
10040 |
+ avr32_function_arg_padding(MODE, TYPE)
|
mgl@1371
|
10041 |
+
|
mgl@1371
|
10042 |
+/*
|
mgl@1371
|
10043 |
+If defined, a C expression which determines whether the default
|
mgl@1371
|
10044 |
+implementation of va_arg will attempt to pad down before reading the
|
mgl@1371
|
10045 |
+next argument, if that argument is smaller than its aligned space as
|
mgl@1371
|
10046 |
+controlled by PARM_BOUNDARY. If this macro is not defined, all such
|
mgl@1371
|
10047 |
+arguments are padded down if BYTES_BIG_ENDIAN is true.
|
mgl@1371
|
10048 |
+*/
|
mgl@1371
|
10049 |
+#define PAD_VARARGS_DOWN \
|
mgl@1371
|
10050 |
+ (FUNCTION_ARG_PADDING (TYPE_MODE (type), type) == downward)
|
mgl@1371
|
10051 |
+
|
mgl@1371
|
10052 |
+
|
mgl@1371
|
10053 |
+/*
|
mgl@1371
|
10054 |
+A C expression that is nonzero if REGNO is the number of a hard
|
mgl@1371
|
10055 |
+register in which function arguments are sometimes passed. This does
|
mgl@1371
|
10056 |
+not include implicit arguments such as the static chain and
|
mgl@1371
|
10057 |
+the structure-value address. On many machines, no registers can be
|
mgl@1371
|
10058 |
+used for this purpose since all function arguments are pushed on the
|
mgl@1371
|
10059 |
+stack.
|
mgl@1371
|
10060 |
+*/
|
mgl@1371
|
10061 |
+/*
|
mgl@1371
|
10062 |
+ Use r8 - r12 for function arguments.
|
mgl@1371
|
10063 |
+*/
|
mgl@1371
|
10064 |
+#define FUNCTION_ARG_REGNO_P(REGNO) \
|
mgl@1371
|
10065 |
+ (REGNO >= 3 && REGNO <= 7)
|
mgl@1371
|
10066 |
+
|
mgl@1371
|
10067 |
+/* Number of registers used for passing function arguments */
|
mgl@1371
|
10068 |
+#define NUM_ARG_REGS 5
|
mgl@1371
|
10069 |
+
|
mgl@1371
|
10070 |
+/*
|
mgl@1371
|
10071 |
+If defined, the order in which arguments are loaded into their
|
mgl@1371
|
10072 |
+respective argument registers is reversed so that the last
|
mgl@1371
|
10073 |
+argument is loaded first. This macro only affects arguments
|
mgl@1371
|
10074 |
+passed in registers.
|
mgl@1371
|
10075 |
+*/
|
mgl@1371
|
10076 |
+/* #define LOAD_ARGS_REVERSED */
|
mgl@1371
|
10077 |
+
|
mgl@1371
|
10078 |
+/** How Scalar Function Values Are Returned **/
|
mgl@1371
|
10079 |
+
|
mgl@1371
|
10080 |
+/* AVR32 is using r12 as return register. */
|
mgl@1371
|
10081 |
+#define RET_REGISTER (15 - 12)
|
mgl@1371
|
10082 |
+
|
mgl@1371
|
10083 |
+
|
mgl@1371
|
10084 |
+/*
|
mgl@1371
|
10085 |
+A C expression to create an RTX representing the place where a library
|
mgl@1371
|
10086 |
+function returns a value of mode MODE. If the precise function
|
mgl@1371
|
10087 |
+being called is known, FUNC is a tree node
|
mgl@1371
|
10088 |
+(FUNCTION_DECL) for it; otherwise, func is a null
|
mgl@1371
|
10089 |
+pointer. This makes it possible to use a different value-returning
|
mgl@1371
|
10090 |
+convention for specific functions when all their calls are
|
mgl@1371
|
10091 |
+known.
|
mgl@1371
|
10092 |
+
|
mgl@1371
|
10093 |
+Note that "library function" in this context means a compiler
|
mgl@1371
|
10094 |
+support routine, used to perform arithmetic, whose name is known
|
mgl@1371
|
10095 |
+specially by the compiler and was not mentioned in the C code being
|
mgl@1371
|
10096 |
+compiled.
|
mgl@1371
|
10097 |
+
|
mgl@1371
|
10098 |
+The definition of LIBRARY_VALUE need not be concerned aggregate
|
mgl@1371
|
10099 |
+data types, because none of the library functions returns such types.
|
mgl@1371
|
10100 |
+*/
|
mgl@1371
|
10101 |
+#define LIBCALL_VALUE(MODE) avr32_libcall_value(MODE)
|
mgl@1371
|
10102 |
+
|
mgl@1371
|
10103 |
+/*
|
mgl@1371
|
10104 |
+A C expression that is nonzero if REGNO is the number of a hard
|
mgl@1371
|
10105 |
+register in which the values of called function may come back.
|
mgl@1371
|
10106 |
+
|
mgl@1371
|
10107 |
+A register whose use for returning values is limited to serving as the
|
mgl@1371
|
10108 |
+second of a pair (for a value of type double, say) need not be
|
mgl@1371
|
10109 |
+recognized by this macro. So for most machines, this definition
|
mgl@1371
|
10110 |
+suffices:
|
mgl@1371
|
10111 |
+ #define FUNCTION_VALUE_REGNO_P(N) ((N) == 0)
|
mgl@1371
|
10112 |
+
|
mgl@1371
|
10113 |
+If the machine has register windows, so that the caller and the called
|
mgl@1371
|
10114 |
+function use different registers for the return value, this macro
|
mgl@1371
|
10115 |
+should recognize only the caller's register numbers.
|
mgl@1371
|
10116 |
+*/
|
mgl@1371
|
10117 |
+/*
|
mgl@1371
|
10118 |
+ When returning a value of mode DImode, r11:r10 is used, else r12 is used.
|
mgl@1371
|
10119 |
+*/
|
mgl@1371
|
10120 |
+#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == RET_REGISTER \
|
mgl@1371
|
10121 |
+ || (REGNO) == INTERNAL_REGNUM(11))
|
mgl@1371
|
10122 |
+
|
mgl@1371
|
10123 |
+
|
mgl@1371
|
10124 |
+/** How Large Values Are Returned **/
|
mgl@1371
|
10125 |
+
|
mgl@1371
|
10126 |
+
|
mgl@1371
|
10127 |
+/*
|
mgl@1371
|
10128 |
+Define this macro to be 1 if all structure and union return values must be
|
mgl@1371
|
10129 |
+in memory. Since this results in slower code, this should be defined
|
mgl@1371
|
10130 |
+only if needed for compatibility with other compilers or with an ABI.
|
mgl@1371
|
10131 |
+If you define this macro to be 0, then the conventions used for structure
|
mgl@1371
|
10132 |
+and union return values are decided by the RETURN_IN_MEMORY macro.
|
mgl@1371
|
10133 |
+
|
mgl@1371
|
10134 |
+If not defined, this defaults to the value 1.
|
mgl@1371
|
10135 |
+*/
|
mgl@1371
|
10136 |
+#define DEFAULT_PCC_STRUCT_RETURN 0
|
mgl@1371
|
10137 |
+
|
mgl@1371
|
10138 |
+
|
mgl@1371
|
10139 |
+
|
mgl@1371
|
10140 |
+
|
mgl@1371
|
10141 |
+/** Generating Code for Profiling **/
|
mgl@1371
|
10142 |
+
|
mgl@1371
|
10143 |
+/*
|
mgl@1371
|
10144 |
+A C statement or compound statement to output to FILE some
|
mgl@1371
|
10145 |
+assembler code to call the profiling subroutine mcount.
|
mgl@1371
|
10146 |
+
|
mgl@1371
|
10147 |
+The details of how mcount expects to be called are determined by
|
mgl@1371
|
10148 |
+your operating system environment, not by GCC. To figure them out,
|
mgl@1371
|
10149 |
+compile a small program for profiling using the system's installed C
|
mgl@1371
|
10150 |
+compiler and look at the assembler code that results.
|
mgl@1371
|
10151 |
+
|
mgl@1371
|
10152 |
+Older implementations of mcount expect the address of a counter
|
mgl@1371
|
10153 |
+variable to be loaded into some register. The name of this variable is
|
mgl@1371
|
10154 |
+'LP' followed by the number LABELNO, so you would generate
|
mgl@1371
|
10155 |
+the name using 'LP%d' in a fprintf.
|
mgl@1371
|
10156 |
+*/
|
mgl@1371
|
10157 |
+/* ToDo: fixme */
|
mgl@1371
|
10158 |
+#ifndef FUNCTION_PROFILER
|
mgl@1371
|
10159 |
+#define FUNCTION_PROFILER(FILE, LABELNO) \
|
mgl@1371
|
10160 |
+ fprintf((FILE), "/* profiler %d */", (LABELNO))
|
mgl@1371
|
10161 |
+#endif
|
mgl@1371
|
10162 |
+
|
mgl@1371
|
10163 |
+
|
mgl@1371
|
10164 |
+/*****************************************************************************
|
mgl@1371
|
10165 |
+ * Trampolines for Nested Functions *
|
mgl@1371
|
10166 |
+ *****************************************************************************/
|
mgl@1371
|
10167 |
+
|
mgl@1371
|
10168 |
+/*
|
mgl@1371
|
10169 |
+A C statement to output, on the stream FILE, assembler code for a
|
mgl@1371
|
10170 |
+block of data that contains the constant parts of a trampoline. This
|
mgl@1371
|
10171 |
+code should not include a label - the label is taken care of
|
mgl@1371
|
10172 |
+automatically.
|
mgl@1371
|
10173 |
+
|
mgl@1371
|
10174 |
+If you do not define this macro, it means no template is needed
|
mgl@1371
|
10175 |
+for the target. Do not define this macro on systems where the block move
|
mgl@1371
|
10176 |
+code to copy the trampoline into place would be larger than the code
|
mgl@1371
|
10177 |
+to generate it on the spot.
|
mgl@1371
|
10178 |
+*/
|
mgl@1371
|
10179 |
+/* ToDo: correct? */
|
mgl@1371
|
10180 |
+#define TRAMPOLINE_TEMPLATE(FILE) avr32_trampoline_template(FILE);
|
mgl@1371
|
10181 |
+
|
mgl@1371
|
10182 |
+
|
mgl@1371
|
10183 |
+/*
|
mgl@1371
|
10184 |
+A C expression for the size in bytes of the trampoline, as an integer.
|
mgl@1371
|
10185 |
+*/
|
mgl@1371
|
10186 |
+/* ToDo: fixme */
|
mgl@1371
|
10187 |
+#define TRAMPOLINE_SIZE 0x0C
|
mgl@1371
|
10188 |
+
|
mgl@1371
|
10189 |
+/*
|
mgl@1371
|
10190 |
+Alignment required for trampolines, in bits.
|
mgl@1371
|
10191 |
+
|
mgl@1371
|
10192 |
+If you don't define this macro, the value of BIGGEST_ALIGNMENT
|
mgl@1371
|
10193 |
+is used for aligning trampolines.
|
mgl@1371
|
10194 |
+*/
|
mgl@1371
|
10195 |
+#define TRAMPOLINE_ALIGNMENT 16
|
mgl@1371
|
10196 |
+
|
mgl@1371
|
10197 |
+/*
|
mgl@1371
|
10198 |
+A C statement to initialize the variable parts of a trampoline.
|
mgl@1371
|
10199 |
+ADDR is an RTX for the address of the trampoline; FNADDR is
|
mgl@1371
|
10200 |
+an RTX for the address of the nested function; STATIC_CHAIN is an
|
mgl@1371
|
10201 |
+RTX for the static chain value that should be passed to the function
|
mgl@1371
|
10202 |
+when it is called.
|
mgl@1371
|
10203 |
+*/
|
mgl@1371
|
10204 |
+#define INITIALIZE_TRAMPOLINE(ADDR, FNADDR, STATIC_CHAIN) \
|
mgl@1371
|
10205 |
+ avr32_initialize_trampoline(ADDR, FNADDR, STATIC_CHAIN)
|
mgl@1371
|
10206 |
+
|
mgl@1371
|
10207 |
+
|
mgl@1371
|
10208 |
+/******************************************************************************
|
mgl@1371
|
10209 |
+ * Implicit Calls to Library Routines
|
mgl@1371
|
10210 |
+ *****************************************************************************/
|
mgl@1371
|
10211 |
+
|
mgl@1371
|
10212 |
+/* Tail calling. */
|
mgl@1371
|
10213 |
+
|
mgl@1371
|
10214 |
+/* A C expression that evaluates to true if it is ok to perform a sibling
|
mgl@1371
|
10215 |
+ call to DECL. */
|
mgl@1371
|
10216 |
+#define FUNCTION_OK_FOR_SIBCALL(DECL) 0
|
mgl@1371
|
10217 |
+
|
mgl@1371
|
10218 |
+#define OVERRIDE_OPTIONS avr32_override_options ()
|
mgl@1371
|
10219 |
+
|
mgl@1371
|
10220 |
+#define OPTIMIZATION_OPTIONS(LEVEL, SIZE) avr32_optimization_options (LEVEL, SIZE)
|
mgl@1371
|
10221 |
+
|
mgl@1371
|
10222 |
+/******************************************************************************
|
mgl@1371
|
10223 |
+ * Addressing Modes
|
mgl@1371
|
10224 |
+ *****************************************************************************/
|
mgl@1371
|
10225 |
+
|
mgl@1371
|
10226 |
+/*
|
mgl@1371
|
10227 |
+A C expression that is nonzero if the machine supports pre-increment,
|
mgl@1371
|
10228 |
+pre-decrement, post-increment, or post-decrement addressing respectively.
|
mgl@1371
|
10229 |
+*/
|
mgl@1371
|
10230 |
+/*
|
mgl@1371
|
10231 |
+ AVR32 supports Rp++ and --Rp
|
mgl@1371
|
10232 |
+*/
|
mgl@1371
|
10233 |
+#define HAVE_PRE_INCREMENT 0
|
mgl@1371
|
10234 |
+#define HAVE_PRE_DECREMENT 1
|
mgl@1371
|
10235 |
+#define HAVE_POST_INCREMENT 1
|
mgl@1371
|
10236 |
+#define HAVE_POST_DECREMENT 0
|
mgl@1371
|
10237 |
+
|
mgl@1371
|
10238 |
+/*
|
mgl@1371
|
10239 |
+A C expression that is nonzero if the machine supports pre- or
|
mgl@1371
|
10240 |
+post-address side-effect generation involving constants other than
|
mgl@1371
|
10241 |
+the size of the memory operand.
|
mgl@1371
|
10242 |
+*/
|
mgl@1371
|
10243 |
+#define HAVE_PRE_MODIFY_DISP 0
|
mgl@1371
|
10244 |
+#define HAVE_POST_MODIFY_DISP 0
|
mgl@1371
|
10245 |
+
|
mgl@1371
|
10246 |
+/*
|
mgl@1371
|
10247 |
+A C expression that is nonzero if the machine supports pre- or
|
mgl@1371
|
10248 |
+post-address side-effect generation involving a register displacement.
|
mgl@1371
|
10249 |
+*/
|
mgl@1371
|
10250 |
+#define HAVE_PRE_MODIFY_REG 0
|
mgl@1371
|
10251 |
+#define HAVE_POST_MODIFY_REG 0
|
mgl@1371
|
10252 |
+
|
mgl@1371
|
10253 |
+/*
|
mgl@1371
|
10254 |
+A C expression that is 1 if the RTX X is a constant which
|
mgl@1371
|
10255 |
+is a valid address. On most machines, this can be defined as
|
mgl@1371
|
10256 |
+CONSTANT_P (X), but a few machines are more restrictive
|
mgl@1371
|
10257 |
+in which constant addresses are supported.
|
mgl@1371
|
10258 |
+
|
mgl@1371
|
10259 |
+CONSTANT_P accepts integer-values expressions whose values are
|
mgl@1371
|
10260 |
+not explicitly known, such as symbol_ref, label_ref, and
|
mgl@1371
|
10261 |
+high expressions and const arithmetic expressions, in
|
mgl@1371
|
10262 |
+addition to const_int and const_double expressions.
|
mgl@1371
|
10263 |
+*/
|
mgl@1371
|
10264 |
+#define CONSTANT_ADDRESS_P(X) CONSTANT_P(X)
|
mgl@1371
|
10265 |
+
|
mgl@1371
|
10266 |
+/*
|
mgl@1371
|
10267 |
+A number, the maximum number of registers that can appear in a valid
|
mgl@1371
|
10268 |
+memory address. Note that it is up to you to specify a value equal to
|
mgl@1371
|
10269 |
+the maximum number that GO_IF_LEGITIMATE_ADDRESS would ever
|
mgl@1371
|
10270 |
+accept.
|
mgl@1371
|
10271 |
+*/
|
mgl@1371
|
10272 |
+#define MAX_REGS_PER_ADDRESS 2
|
mgl@1371
|
10273 |
+
|
mgl@1371
|
10274 |
+/*
|
mgl@1371
|
10275 |
+A C compound statement with a conditional goto LABEL;
|
mgl@1371
|
10276 |
+executed if X (an RTX) is a legitimate memory address on the
|
mgl@1371
|
10277 |
+target machine for a memory operand of mode MODE.
|
mgl@1371
|
10278 |
+
|
mgl@1371
|
10279 |
+It usually pays to define several simpler macros to serve as
|
mgl@1371
|
10280 |
+subroutines for this one. Otherwise it may be too complicated to
|
mgl@1371
|
10281 |
+understand.
|
mgl@1371
|
10282 |
+
|
mgl@1371
|
10283 |
+This macro must exist in two variants: a strict variant and a
|
mgl@1371
|
10284 |
+non-strict one. The strict variant is used in the reload pass. It
|
mgl@1371
|
10285 |
+must be defined so that any pseudo-register that has not been
|
mgl@1371
|
10286 |
+allocated a hard register is considered a memory reference. In
|
mgl@1371
|
10287 |
+contexts where some kind of register is required, a pseudo-register
|
mgl@1371
|
10288 |
+with no hard register must be rejected.
|
mgl@1371
|
10289 |
+
|
mgl@1371
|
10290 |
+The non-strict variant is used in other passes. It must be defined to
|
mgl@1371
|
10291 |
+accept all pseudo-registers in every context where some kind of
|
mgl@1371
|
10292 |
+register is required.
|
mgl@1371
|
10293 |
+
|
mgl@1371
|
10294 |
+Compiler source files that want to use the strict variant of this
|
mgl@1371
|
10295 |
+macro define the macro REG_OK_STRICT. You should use an
|
mgl@1371
|
10296 |
+#ifdef REG_OK_STRICT conditional to define the strict variant
|
mgl@1371
|
10297 |
+in that case and the non-strict variant otherwise.
|
mgl@1371
|
10298 |
+
|
mgl@1371
|
10299 |
+Subroutines to check for acceptable registers for various purposes (one
|
mgl@1371
|
10300 |
+for base registers, one for index registers, and so on) are typically
|
mgl@1371
|
10301 |
+among the subroutines used to define GO_IF_LEGITIMATE_ADDRESS.
|
mgl@1371
|
10302 |
+Then only these subroutine macros need have two variants; the higher
|
mgl@1371
|
10303 |
+levels of macros may be the same whether strict or not.
|
mgl@1371
|
10304 |
+
|
mgl@1371
|
10305 |
+Normally, constant addresses which are the sum of a symbol_ref
|
mgl@1371
|
10306 |
+and an integer are stored inside a const RTX to mark them as
|
mgl@1371
|
10307 |
+constant. Therefore, there is no need to recognize such sums
|
mgl@1371
|
10308 |
+specifically as legitimate addresses. Normally you would simply
|
mgl@1371
|
10309 |
+recognize any const as legitimate.
|
mgl@1371
|
10310 |
+
|
mgl@1371
|
10311 |
+Usually PRINT_OPERAND_ADDRESS is not prepared to handle constant
|
mgl@1371
|
10312 |
+sums that are not marked with const. It assumes that a naked
|
mgl@1371
|
10313 |
+plus indicates indexing. If so, then you must reject such
|
mgl@1371
|
10314 |
+naked constant sums as illegitimate addresses, so that none of them will
|
mgl@1371
|
10315 |
+be given to PRINT_OPERAND_ADDRESS.
|
mgl@1371
|
10316 |
+
|
mgl@1371
|
10317 |
+On some machines, whether a symbolic address is legitimate depends on
|
mgl@1371
|
10318 |
+the section that the address refers to. On these machines, define the
|
mgl@1371
|
10319 |
+macro ENCODE_SECTION_INFO to store the information into the
|
mgl@1371
|
10320 |
+symbol_ref, and then check for it here. When you see a
|
mgl@1371
|
10321 |
+const, you will have to look inside it to find the
|
mgl@1371
|
10322 |
+symbol_ref in order to determine the section.
|
mgl@1371
|
10323 |
+
|
mgl@1371
|
10324 |
+The best way to modify the name string is by adding text to the
|
mgl@1371
|
10325 |
+beginning, with suitable punctuation to prevent any ambiguity. Allocate
|
mgl@1371
|
10326 |
+the new name in saveable_obstack. You will have to modify
|
mgl@1371
|
10327 |
+ASM_OUTPUT_LABELREF to remove and decode the added text and
|
mgl@1371
|
10328 |
+output the name accordingly, and define STRIP_NAME_ENCODING to
|
mgl@1371
|
10329 |
+access the original name string.
|
mgl@1371
|
10330 |
+
|
mgl@1371
|
10331 |
+You can check the information stored here into the symbol_ref in
|
mgl@1371
|
10332 |
+the definitions of the macros GO_IF_LEGITIMATE_ADDRESS and
|
mgl@1371
|
10333 |
+PRINT_OPERAND_ADDRESS.
|
mgl@1371
|
10334 |
+*/
|
mgl@1371
|
10335 |
+#ifdef REG_OK_STRICT
|
mgl@1371
|
10336 |
+# define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \
|
mgl@1371
|
10337 |
+ do \
|
mgl@1371
|
10338 |
+ { \
|
mgl@1371
|
10339 |
+ if (avr32_legitimate_address(MODE, X, 1)) \
|
mgl@1371
|
10340 |
+ goto LABEL; \
|
mgl@1371
|
10341 |
+ } \
|
mgl@1371
|
10342 |
+ while (0)
|
mgl@1371
|
10343 |
+#else
|
mgl@1371
|
10344 |
+# define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \
|
mgl@1371
|
10345 |
+ do \
|
mgl@1371
|
10346 |
+ { \
|
mgl@1371
|
10347 |
+ if (avr32_legitimate_address(MODE, X, 0)) \
|
mgl@1371
|
10348 |
+ goto LABEL; \
|
mgl@1371
|
10349 |
+ } \
|
mgl@1371
|
10350 |
+ while (0)
|
mgl@1371
|
10351 |
+#endif
|
mgl@1371
|
10352 |
+
|
mgl@1371
|
10353 |
+
|
mgl@1371
|
10354 |
+
|
mgl@1371
|
10355 |
+/*
|
mgl@1371
|
10356 |
+A C compound statement that attempts to replace X with a valid
|
mgl@1371
|
10357 |
+memory address for an operand of mode MODE. win will be a
|
mgl@1371
|
10358 |
+C statement label elsewhere in the code; the macro definition may use
|
mgl@1371
|
10359 |
+
|
mgl@1371
|
10360 |
+ GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN);
|
mgl@1371
|
10361 |
+
|
mgl@1371
|
10362 |
+to avoid further processing if the address has become legitimate.
|
mgl@1371
|
10363 |
+
|
mgl@1371
|
10364 |
+X will always be the result of a call to break_out_memory_refs,
|
mgl@1371
|
10365 |
+and OLDX will be the operand that was given to that function to produce
|
mgl@1371
|
10366 |
+X.
|
mgl@1371
|
10367 |
+
|
mgl@1371
|
10368 |
+The code generated by this macro should not alter the substructure of
|
mgl@1371
|
10369 |
+X. If it transforms X into a more legitimate form, it
|
mgl@1371
|
10370 |
+should assign X (which will always be a C variable) a new value.
|
mgl@1371
|
10371 |
+
|
mgl@1371
|
10372 |
+It is not necessary for this macro to come up with a legitimate
|
mgl@1371
|
10373 |
+address. The compiler has standard ways of doing so in all cases. In
|
mgl@1371
|
10374 |
+fact, it is safe for this macro to do nothing. But often a
|
mgl@1371
|
10375 |
+machine-dependent strategy can generate better code.
|
mgl@1371
|
10376 |
+*/
|
mgl@1371
|
10377 |
+#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
|
mgl@1371
|
10378 |
+ do \
|
mgl@1371
|
10379 |
+ { \
|
mgl@1371
|
10380 |
+ if (GET_CODE(X) == PLUS \
|
mgl@1371
|
10381 |
+ && GET_CODE(XEXP(X, 0)) == REG \
|
mgl@1371
|
10382 |
+ && GET_CODE(XEXP(X, 1)) == CONST_INT \
|
mgl@1371
|
10383 |
+ && !CONST_OK_FOR_CONSTRAINT_P(INTVAL(XEXP(X, 1)), \
|
mgl@1371
|
10384 |
+ 'K', "Ks16")) \
|
mgl@1371
|
10385 |
+ { \
|
mgl@1371
|
10386 |
+ rtx index = force_reg(SImode, XEXP(X, 1)); \
|
mgl@1371
|
10387 |
+ X = gen_rtx_PLUS( SImode, XEXP(X, 0), index); \
|
mgl@1371
|
10388 |
+ } \
|
mgl@1371
|
10389 |
+ GO_IF_LEGITIMATE_ADDRESS(MODE, X, WIN); \
|
mgl@1371
|
10390 |
+ } \
|
mgl@1371
|
10391 |
+ while(0)
|
mgl@1371
|
10392 |
+
|
mgl@1371
|
10393 |
+
|
mgl@1371
|
10394 |
+/*
|
mgl@1371
|
10395 |
+A C statement or compound statement with a conditional
|
mgl@1371
|
10396 |
+goto LABEL; executed if memory address X (an RTX) can have
|
mgl@1371
|
10397 |
+different meanings depending on the machine mode of the memory
|
mgl@1371
|
10398 |
+reference it is used for or if the address is valid for some modes
|
mgl@1371
|
10399 |
+but not others.
|
mgl@1371
|
10400 |
+
|
mgl@1371
|
10401 |
+Autoincrement and autodecrement addresses typically have mode-dependent
|
mgl@1371
|
10402 |
+effects because the amount of the increment or decrement is the size
|
mgl@1371
|
10403 |
+of the operand being addressed. Some machines have other mode-dependent
|
mgl@1371
|
10404 |
+addresses. Many RISC machines have no mode-dependent addresses.
|
mgl@1371
|
10405 |
+
|
mgl@1371
|
10406 |
+You may assume that ADDR is a valid address for the machine.
|
mgl@1371
|
10407 |
+*/
|
mgl@1371
|
10408 |
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \
|
mgl@1371
|
10409 |
+ do \
|
mgl@1371
|
10410 |
+ { \
|
mgl@1371
|
10411 |
+ if (GET_CODE (ADDR) == POST_INC \
|
mgl@1371
|
10412 |
+ || GET_CODE (ADDR) == PRE_DEC) \
|
mgl@1371
|
10413 |
+ goto LABEL; \
|
mgl@1371
|
10414 |
+ } \
|
mgl@1371
|
10415 |
+ while (0)
|
mgl@1371
|
10416 |
+
|
mgl@1371
|
10417 |
+/*
|
mgl@1371
|
10418 |
+A C expression that is nonzero if X is a legitimate constant for
|
mgl@1371
|
10419 |
+an immediate operand on the target machine. You can assume that
|
mgl@1371
|
10420 |
+X satisfies CONSTANT_P, so you need not check this. In fact,
|
mgl@1371
|
10421 |
+'1' is a suitable definition for this macro on machines where
|
mgl@1371
|
10422 |
+anything CONSTANT_P is valid.
|
mgl@1371
|
10423 |
+*/
|
mgl@1371
|
10424 |
+#define LEGITIMATE_CONSTANT_P(X) avr32_legitimate_constant_p(X)
|
mgl@1371
|
10425 |
+
|
mgl@1371
|
10426 |
+
|
mgl@1371
|
10427 |
+/******************************************************************************
|
mgl@1371
|
10428 |
+ * Condition Code Status
|
mgl@1371
|
10429 |
+ *****************************************************************************/
|
mgl@1371
|
10430 |
+
|
mgl@1371
|
10431 |
+/*
|
mgl@1371
|
10432 |
+C code for a data type which is used for declaring the mdep
|
mgl@1371
|
10433 |
+component of cc_status. It defaults to int.
|
mgl@1371
|
10434 |
+
|
mgl@1371
|
10435 |
+This macro is not used on machines that do not use cc0.
|
mgl@1371
|
10436 |
+*/
|
mgl@1371
|
10437 |
+
|
mgl@1371
|
10438 |
+typedef struct
|
mgl@1371
|
10439 |
+{
|
mgl@1371
|
10440 |
+ int flags;
|
mgl@1371
|
10441 |
+ rtx value;
|
mgl@1371
|
10442 |
+ int fpflags;
|
mgl@1371
|
10443 |
+ rtx fpvalue;
|
mgl@1371
|
10444 |
+ int cond_exec_cmp_clobbered;
|
mgl@1371
|
10445 |
+} avr32_status_reg;
|
mgl@1371
|
10446 |
+
|
mgl@1371
|
10447 |
+
|
mgl@1371
|
10448 |
+#define CC_STATUS_MDEP avr32_status_reg
|
mgl@1371
|
10449 |
+
|
mgl@1371
|
10450 |
+/*
|
mgl@1371
|
10451 |
+A C expression to initialize the mdep field to "empty".
|
mgl@1371
|
10452 |
+The default definition does nothing, since most machines don't use
|
mgl@1371
|
10453 |
+the field anyway. If you want to use the field, you should probably
|
mgl@1371
|
10454 |
+define this macro to initialize it.
|
mgl@1371
|
10455 |
+
|
mgl@1371
|
10456 |
+This macro is not used on machines that do not use cc0.
|
mgl@1371
|
10457 |
+*/
|
mgl@1371
|
10458 |
+
|
mgl@1371
|
10459 |
+#define CC_STATUS_MDEP_INIT \
|
mgl@1371
|
10460 |
+ (cc_status.mdep.flags = CC_NONE , cc_status.mdep.cond_exec_cmp_clobbered = 0, cc_status.mdep.value = 0)
|
mgl@1371
|
10461 |
+
|
mgl@1371
|
10462 |
+#define FPCC_STATUS_INIT \
|
mgl@1371
|
10463 |
+ (cc_status.mdep.fpflags = CC_NONE , cc_status.mdep.fpvalue = 0)
|
mgl@1371
|
10464 |
+
|
mgl@1371
|
10465 |
+/*
|
mgl@1371
|
10466 |
+A C compound statement to set the components of cc_status
|
mgl@1371
|
10467 |
+appropriately for an insn INSN whose body is EXP. It is
|
mgl@1371
|
10468 |
+this macro's responsibility to recognize insns that set the condition
|
mgl@1371
|
10469 |
+code as a byproduct of other activity as well as those that explicitly
|
mgl@1371
|
10470 |
+set (cc0).
|
mgl@1371
|
10471 |
+
|
mgl@1371
|
10472 |
+This macro is not used on machines that do not use cc0.
|
mgl@1371
|
10473 |
+
|
mgl@1371
|
10474 |
+If there are insns that do not set the condition code but do alter
|
mgl@1371
|
10475 |
+other machine registers, this macro must check to see whether they
|
mgl@1371
|
10476 |
+invalidate the expressions that the condition code is recorded as
|
mgl@1371
|
10477 |
+reflecting. For example, on the 68000, insns that store in address
|
mgl@1371
|
10478 |
+registers do not set the condition code, which means that usually
|
mgl@1371
|
10479 |
+NOTICE_UPDATE_CC can leave cc_status unaltered for such
|
mgl@1371
|
10480 |
+insns. But suppose that the previous insn set the condition code
|
mgl@1371
|
10481 |
+based on location 'a4@@(102)' and the current insn stores a new
|
mgl@1371
|
10482 |
+value in 'a4'. Although the condition code is not changed by
|
mgl@1371
|
10483 |
+this, it will no longer be true that it reflects the contents of
|
mgl@1371
|
10484 |
+'a4@@(102)'. Therefore, NOTICE_UPDATE_CC must alter
|
mgl@1371
|
10485 |
+cc_status in this case to say that nothing is known about the
|
mgl@1371
|
10486 |
+condition code value.
|
mgl@1371
|
10487 |
+
|
mgl@1371
|
10488 |
+The definition of NOTICE_UPDATE_CC must be prepared to deal
|
mgl@1371
|
10489 |
+with the results of peephole optimization: insns whose patterns are
|
mgl@1371
|
10490 |
+parallel RTXs containing various reg, mem or
|
mgl@1371
|
10491 |
+constants which are just the operands. The RTL structure of these
|
mgl@1371
|
10492 |
+insns is not sufficient to indicate what the insns actually do. What
|
mgl@1371
|
10493 |
+NOTICE_UPDATE_CC should do when it sees one is just to run
|
mgl@1371
|
10494 |
+CC_STATUS_INIT.
|
mgl@1371
|
10495 |
+
|
mgl@1371
|
10496 |
+A possible definition of NOTICE_UPDATE_CC is to call a function
|
mgl@1371
|
10497 |
+that looks at an attribute (see Insn Attributes) named, for example,
|
mgl@1371
|
10498 |
+'cc'. This avoids having detailed information about patterns in
|
mgl@1371
|
10499 |
+two places, the 'md' file and in NOTICE_UPDATE_CC.
|
mgl@1371
|
10500 |
+*/
|
mgl@1371
|
10501 |
+
|
mgl@1371
|
10502 |
+#define NOTICE_UPDATE_CC(EXP, INSN) avr32_notice_update_cc(EXP, INSN)
|
mgl@1371
|
10503 |
+
|
mgl@1371
|
10504 |
+
|
mgl@1371
|
10505 |
+
|
mgl@1371
|
10506 |
+
|
mgl@1371
|
10507 |
+/******************************************************************************
|
mgl@1371
|
10508 |
+ * Describing Relative Costs of Operations
|
mgl@1371
|
10509 |
+ *****************************************************************************/
|
mgl@1371
|
10510 |
+
|
mgl@1371
|
10511 |
+
|
mgl@1371
|
10512 |
+
|
mgl@1371
|
10513 |
+/*
|
mgl@1371
|
10514 |
+A C expression for the cost of moving data of mode MODE from a
|
mgl@1371
|
10515 |
+register in class FROM to one in class TO. The classes are
|
mgl@1371
|
10516 |
+expressed using the enumeration values such as GENERAL_REGS. A
|
mgl@1371
|
10517 |
+value of 2 is the default; other values are interpreted relative to
|
mgl@1371
|
10518 |
+that.
|
mgl@1371
|
10519 |
+
|
mgl@1371
|
10520 |
+It is not required that the cost always equal 2 when FROM is the
|
mgl@1371
|
10521 |
+same as TO; on some machines it is expensive to move between
|
mgl@1371
|
10522 |
+registers if they are not general registers.
|
mgl@1371
|
10523 |
+
|
mgl@1371
|
10524 |
+If reload sees an insn consisting of a single set between two
|
mgl@1371
|
10525 |
+hard registers, and if REGISTER_MOVE_COST applied to their
|
mgl@1371
|
10526 |
+classes returns a value of 2, reload does not check to ensure that the
|
mgl@1371
|
10527 |
+constraints of the insn are met. Setting a cost of other than 2 will
|
mgl@1371
|
10528 |
+allow reload to verify that the constraints are met. You should do this
|
mgl@1371
|
10529 |
+if the movm pattern's constraints do not allow such copying.
|
mgl@1371
|
10530 |
+*/
|
mgl@1371
|
10531 |
+#define REGISTER_MOVE_COST(MODE, FROM, TO) \
|
mgl@1371
|
10532 |
+ ((GET_MODE_SIZE(MODE) <= 4) ? 2: \
|
mgl@1371
|
10533 |
+ (GET_MODE_SIZE(MODE) <= 8) ? 3: \
|
mgl@1371
|
10534 |
+ 4)
|
mgl@1371
|
10535 |
+
|
mgl@1371
|
10536 |
+/*
|
mgl@1371
|
10537 |
+A C expression for the cost of moving data of mode MODE between a
|
mgl@1371
|
10538 |
+register of class CLASS and memory; IN is zero if the value
|
mgl@1371
|
10539 |
+is to be written to memory, nonzero if it is to be read in. This cost
|
mgl@1371
|
10540 |
+is relative to those in REGISTER_MOVE_COST. If moving between
|
mgl@1371
|
10541 |
+registers and memory is more expensive than between two registers, you
|
mgl@1371
|
10542 |
+should define this macro to express the relative cost.
|
mgl@1371
|
10543 |
+
|
mgl@1371
|
10544 |
+If you do not define this macro, GCC uses a default cost of 4 plus
|
mgl@1371
|
10545 |
+the cost of copying via a secondary reload register, if one is
|
mgl@1371
|
10546 |
+needed. If your machine requires a secondary reload register to copy
|
mgl@1371
|
10547 |
+between memory and a register of CLASS but the reload mechanism is
|
mgl@1371
|
10548 |
+more complex than copying via an intermediate, define this macro to
|
mgl@1371
|
10549 |
+reflect the actual cost of the move.
|
mgl@1371
|
10550 |
+
|
mgl@1371
|
10551 |
+GCC defines the function memory_move_secondary_cost if
|
mgl@1371
|
10552 |
+secondary reloads are needed. It computes the costs due to copying via
|
mgl@1371
|
10553 |
+a secondary register. If your machine copies from memory using a
|
mgl@1371
|
10554 |
+secondary register in the conventional way but the default base value of
|
mgl@1371
|
10555 |
+4 is not correct for your machine, define this macro to add some other
|
mgl@1371
|
10556 |
+value to the result of that function. The arguments to that function
|
mgl@1371
|
10557 |
+are the same as to this macro.
|
mgl@1371
|
10558 |
+*/
|
mgl@1371
|
10559 |
+/*
|
mgl@1371
|
10560 |
+ Memory moves are costly
|
mgl@1371
|
10561 |
+*/
|
mgl@1371
|
10562 |
+#define MEMORY_MOVE_COST(MODE, CLASS, IN) \
|
mgl@1371
|
10563 |
+ (((IN) ? ((GET_MODE_SIZE(MODE) < 4) ? 4 : \
|
mgl@1371
|
10564 |
+ (GET_MODE_SIZE(MODE) > 8) ? 6 : \
|
mgl@1371
|
10565 |
+ 3) \
|
mgl@1371
|
10566 |
+ : ((GET_MODE_SIZE(MODE) > 8) ? 6 : 3)))
|
mgl@1371
|
10567 |
+
|
mgl@1371
|
10568 |
+/*
|
mgl@1371
|
10569 |
+A C expression for the cost of a branch instruction. A value of 1 is
|
mgl@1371
|
10570 |
+the default; other values are interpreted relative to that.
|
mgl@1371
|
10571 |
+*/
|
mgl@1371
|
10572 |
+ /* Try to use conditionals as much as possible */
|
mgl@1371
|
10573 |
+#define BRANCH_COST (TARGET_BRANCH_PRED ? 3 : 4)
|
mgl@1371
|
10574 |
+
|
mgl@1371
|
10575 |
+/*A C expression for the maximum number of instructions to execute via conditional
|
mgl@1371
|
10576 |
+ execution instructions instead of a branch. A value of BRANCH_COST+1 is the default
|
mgl@1371
|
10577 |
+ if the machine does not use cc0, and 1 if it does use cc0.*/
|
mgl@1371
|
10578 |
+#define MAX_CONDITIONAL_EXECUTE 4
|
mgl@1371
|
10579 |
+
|
mgl@1371
|
10580 |
+/*
|
mgl@1371
|
10581 |
+Define this macro as a C expression which is nonzero if accessing less
|
mgl@1371
|
10582 |
+than a word of memory (i.e.: a char or a short) is no
|
mgl@1371
|
10583 |
+faster than accessing a word of memory, i.e., if such access
|
mgl@1371
|
10584 |
+require more than one instruction or if there is no difference in cost
|
mgl@1371
|
10585 |
+between byte and (aligned) word loads.
|
mgl@1371
|
10586 |
+
|
mgl@1371
|
10587 |
+When this macro is not defined, the compiler will access a field by
|
mgl@1371
|
10588 |
+finding the smallest containing object; when it is defined, a fullword
|
mgl@1371
|
10589 |
+load will be used if alignment permits. Unless bytes accesses are
|
mgl@1371
|
10590 |
+faster than word accesses, using word accesses is preferable since it
|
mgl@1371
|
10591 |
+may eliminate subsequent memory access if subsequent accesses occur to
|
mgl@1371
|
10592 |
+other fields in the same word of the structure, but to different bytes.
|
mgl@1371
|
10593 |
+*/
|
mgl@1371
|
10594 |
+#define SLOW_BYTE_ACCESS 1
|
mgl@1371
|
10595 |
+
|
mgl@1371
|
10596 |
+
|
mgl@1371
|
10597 |
+/*
|
mgl@1371
|
10598 |
+Define this macro if it is as good or better to call a constant
|
mgl@1371
|
10599 |
+function address than to call an address kept in a register.
|
mgl@1371
|
10600 |
+*/
|
mgl@1371
|
10601 |
+#define NO_FUNCTION_CSE
|
mgl@1371
|
10602 |
+
|
mgl@1371
|
10603 |
+
|
mgl@1371
|
10604 |
+/******************************************************************************
|
mgl@1371
|
10605 |
+ * Adjusting the Instruction Scheduler
|
mgl@1371
|
10606 |
+ *****************************************************************************/
|
mgl@1371
|
10607 |
+
|
mgl@1371
|
10608 |
+/*****************************************************************************
|
mgl@1371
|
10609 |
+ * Dividing the Output into Sections (Texts, Data, ...) *
|
mgl@1371
|
10610 |
+ *****************************************************************************/
|
mgl@1371
|
10611 |
+
|
mgl@1371
|
10612 |
+/*
|
mgl@1371
|
10613 |
+A C expression whose value is a string, including spacing, containing the
|
mgl@1371
|
10614 |
+assembler operation that should precede instructions and read-only data.
|
mgl@1371
|
10615 |
+Normally "\t.text" is right.
|
mgl@1371
|
10616 |
+*/
|
mgl@1371
|
10617 |
+#define TEXT_SECTION_ASM_OP "\t.text"
|
mgl@1371
|
10618 |
+/*
|
mgl@1371
|
10619 |
+A C statement that switches to the default section containing instructions.
|
mgl@1371
|
10620 |
+Normally this is not needed, as simply defining TEXT_SECTION_ASM_OP
|
mgl@1371
|
10621 |
+is enough. The MIPS port uses this to sort all functions after all data
|
mgl@1371
|
10622 |
+declarations.
|
mgl@1371
|
10623 |
+*/
|
mgl@1371
|
10624 |
+/* #define TEXT_SECTION */
|
mgl@1371
|
10625 |
+
|
mgl@1371
|
10626 |
+/*
|
mgl@1371
|
10627 |
+A C expression whose value is a string, including spacing, containing the
|
mgl@1371
|
10628 |
+assembler operation to identify the following data as writable initialized
|
mgl@1371
|
10629 |
+data. Normally "\t.data" is right.
|
mgl@1371
|
10630 |
+*/
|
mgl@1371
|
10631 |
+#define DATA_SECTION_ASM_OP "\t.data"
|
mgl@1371
|
10632 |
+
|
mgl@1371
|
10633 |
+/*
|
mgl@1371
|
10634 |
+If defined, a C expression whose value is a string, including spacing,
|
mgl@1371
|
10635 |
+containing the assembler operation to identify the following data as
|
mgl@1371
|
10636 |
+shared data. If not defined, DATA_SECTION_ASM_OP will be used.
|
mgl@1371
|
10637 |
+*/
|
mgl@1371
|
10638 |
+
|
mgl@1371
|
10639 |
+/*
|
mgl@1371
|
10640 |
+A C expression whose value is a string, including spacing, containing
|
mgl@1371
|
10641 |
+the assembler operation to identify the following data as read-only
|
mgl@1371
|
10642 |
+initialized data.
|
mgl@1371
|
10643 |
+*/
|
mgl@1371
|
10644 |
+#undef READONLY_DATA_SECTION_ASM_OP
|
mgl@1371
|
10645 |
+#define READONLY_DATA_SECTION_ASM_OP \
|
mgl@1371
|
10646 |
+ ((TARGET_USE_RODATA_SECTION) ? \
|
mgl@1371
|
10647 |
+ "\t.section\t.rodata" : \
|
mgl@1371
|
10648 |
+ TEXT_SECTION_ASM_OP )
|
mgl@1371
|
10649 |
+
|
mgl@1371
|
10650 |
+
|
mgl@1371
|
10651 |
+/*
|
mgl@1371
|
10652 |
+If defined, a C expression whose value is a string, including spacing,
|
mgl@1371
|
10653 |
+containing the assembler operation to identify the following data as
|
mgl@1371
|
10654 |
+uninitialized global data. If not defined, and neither
|
mgl@1371
|
10655 |
+ASM_OUTPUT_BSS nor ASM_OUTPUT_ALIGNED_BSS are defined,
|
mgl@1371
|
10656 |
+uninitialized global data will be output in the data section if
|
mgl@1371
|
10657 |
+-fno-common is passed, otherwise ASM_OUTPUT_COMMON will be
|
mgl@1371
|
10658 |
+used.
|
mgl@1371
|
10659 |
+*/
|
mgl@1371
|
10660 |
+#define BSS_SECTION_ASM_OP "\t.section\t.bss"
|
mgl@1371
|
10661 |
+
|
mgl@1371
|
10662 |
+/*
|
mgl@1371
|
10663 |
+If defined, a C expression whose value is a string, including spacing,
|
mgl@1371
|
10664 |
+containing the assembler operation to identify the following data as
|
mgl@1371
|
10665 |
+uninitialized global shared data. If not defined, and
|
mgl@1371
|
10666 |
+BSS_SECTION_ASM_OP is, the latter will be used.
|
mgl@1371
|
10667 |
+*/
|
mgl@1371
|
10668 |
+/*#define SHARED_BSS_SECTION_ASM_OP "\trseg\tshared_bbs_section:data:noroot(0)\n"*/
|
mgl@1371
|
10669 |
+/*
|
mgl@1371
|
10670 |
+If defined, a C expression whose value is a string, including spacing,
|
mgl@1371
|
10671 |
+containing the assembler operation to identify the following data as
|
mgl@1371
|
10672 |
+initialization code. If not defined, GCC will assume such a section does
|
mgl@1371
|
10673 |
+not exist.
|
mgl@1371
|
10674 |
+*/
|
mgl@1371
|
10675 |
+#undef INIT_SECTION_ASM_OP
|
mgl@1371
|
10676 |
+#define INIT_SECTION_ASM_OP "\t.section\t.init"
|
mgl@1371
|
10677 |
+
|
mgl@1371
|
10678 |
+/*
|
mgl@1371
|
10679 |
+If defined, a C expression whose value is a string, including spacing,
|
mgl@1371
|
10680 |
+containing the assembler operation to identify the following data as
|
mgl@1371
|
10681 |
+finalization code. If not defined, GCC will assume such a section does
|
mgl@1371
|
10682 |
+not exist.
|
mgl@1371
|
10683 |
+*/
|
mgl@1371
|
10684 |
+#undef FINI_SECTION_ASM_OP
|
mgl@1371
|
10685 |
+#define FINI_SECTION_ASM_OP "\t.section\t.fini"
|
mgl@1371
|
10686 |
+
|
mgl@1371
|
10687 |
+/*
|
mgl@1371
|
10688 |
+If defined, an ASM statement that switches to a different section
|
mgl@1371
|
10689 |
+via SECTION_OP, calls FUNCTION, and switches back to
|
mgl@1371
|
10690 |
+the text section. This is used in crtstuff.c if
|
mgl@1371
|
10691 |
+INIT_SECTION_ASM_OP or FINI_SECTION_ASM_OP to calls
|
mgl@1371
|
10692 |
+to initialization and finalization functions from the init and fini
|
mgl@1371
|
10693 |
+sections. By default, this macro uses a simple function call. Some
|
mgl@1371
|
10694 |
+ports need hand-crafted assembly code to avoid dependencies on
|
mgl@1371
|
10695 |
+registers initialized in the function prologue or to ensure that
|
mgl@1371
|
10696 |
+constant pools don't end up too far way in the text section.
|
mgl@1371
|
10697 |
+*/
|
mgl@1371
|
10698 |
+#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
|
mgl@1371
|
10699 |
+ asm ( SECTION_OP "\n" \
|
mgl@1371
|
10700 |
+ "mcall r6[" USER_LABEL_PREFIX #FUNC "@got]\n" \
|
mgl@1371
|
10701 |
+ TEXT_SECTION_ASM_OP);
|
mgl@1371
|
10702 |
+
|
mgl@1371
|
10703 |
+
|
mgl@1371
|
10704 |
+/*
|
mgl@1371
|
10705 |
+Define this macro to be an expression with a nonzero value if jump
|
mgl@1371
|
10706 |
+tables (for tablejump insns) should be output in the text
|
mgl@1371
|
10707 |
+section, along with the assembler instructions. Otherwise, the
|
mgl@1371
|
10708 |
+readonly data section is used.
|
mgl@1371
|
10709 |
+
|
mgl@1371
|
10710 |
+This macro is irrelevant if there is no separate readonly data section.
|
mgl@1371
|
10711 |
+*/
|
mgl@1371
|
10712 |
+/* Put jump tables in text section if we have caches. Otherwise assume that
|
mgl@1371
|
10713 |
+ loading data from code memory is slow. */
|
mgl@1371
|
10714 |
+#define JUMP_TABLES_IN_TEXT_SECTION \
|
mgl@1371
|
10715 |
+ (TARGET_CACHES ? 1 : 0)
|
mgl@1371
|
10716 |
+
|
mgl@1371
|
10717 |
+
|
mgl@1371
|
10718 |
+/******************************************************************************
|
mgl@1371
|
10719 |
+ * Position Independent Code (PIC)
|
mgl@1371
|
10720 |
+ *****************************************************************************/
|
mgl@1371
|
10721 |
+
|
mgl@1371
|
10722 |
+#ifndef AVR32_ALWAYS_PIC
|
mgl@1371
|
10723 |
+#define AVR32_ALWAYS_PIC 0
|
mgl@1371
|
10724 |
+#endif
|
mgl@1371
|
10725 |
+
|
mgl@1371
|
10726 |
+/* GOT is set to r6 */
|
mgl@1371
|
10727 |
+#define PIC_OFFSET_TABLE_REGNUM INTERNAL_REGNUM(6)
|
mgl@1371
|
10728 |
+
|
mgl@1371
|
10729 |
+/*
|
mgl@1371
|
10730 |
+A C expression that is nonzero if X is a legitimate immediate
|
mgl@1371
|
10731 |
+operand on the target machine when generating position independent code.
|
mgl@1371
|
10732 |
+You can assume that X satisfies CONSTANT_P, so you need not
|
mgl@1371
|
10733 |
+check this. You can also assume flag_pic is true, so you need not
|
mgl@1371
|
10734 |
+check it either. You need not define this macro if all constants
|
mgl@1371
|
10735 |
+(including SYMBOL_REF) can be immediate operands when generating
|
mgl@1371
|
10736 |
+position independent code.
|
mgl@1371
|
10737 |
+*/
|
mgl@1371
|
10738 |
+/* We can't directly access anything that contains a symbol,
|
mgl@1371
|
10739 |
+ nor can we indirect via the constant pool. */
|
mgl@1371
|
10740 |
+#define LEGITIMATE_PIC_OPERAND_P(X) avr32_legitimate_pic_operand_p(X)
|
mgl@1371
|
10741 |
+
|
mgl@1371
|
10742 |
+
|
mgl@1371
|
10743 |
+/* We need to know when we are making a constant pool; this determines
|
mgl@1371
|
10744 |
+ whether data needs to be in the GOT or can be referenced via a GOT
|
mgl@1371
|
10745 |
+ offset. */
|
mgl@1371
|
10746 |
+extern int making_const_table;
|
mgl@1371
|
10747 |
+
|
mgl@1371
|
10748 |
+/******************************************************************************
|
mgl@1371
|
10749 |
+ * Defining the Output Assembler Language
|
mgl@1371
|
10750 |
+ *****************************************************************************/
|
mgl@1371
|
10751 |
+
|
mgl@1371
|
10752 |
+
|
mgl@1371
|
10753 |
+/*
|
mgl@1371
|
10754 |
+A C string constant describing how to begin a comment in the target
|
mgl@1371
|
10755 |
+assembler language. The compiler assumes that the comment will end at
|
mgl@1371
|
10756 |
+the end of the line.
|
mgl@1371
|
10757 |
+*/
|
mgl@1371
|
10758 |
+#define ASM_COMMENT_START "# "
|
mgl@1371
|
10759 |
+
|
mgl@1371
|
10760 |
+/*
|
mgl@1371
|
10761 |
+A C string constant for text to be output before each asm
|
mgl@1371
|
10762 |
+statement or group of consecutive ones. Normally this is
|
mgl@1371
|
10763 |
+"#APP", which is a comment that has no effect on most
|
mgl@1371
|
10764 |
+assemblers but tells the GNU assembler that it must check the lines
|
mgl@1371
|
10765 |
+that follow for all valid assembler constructs.
|
mgl@1371
|
10766 |
+*/
|
mgl@1371
|
10767 |
+#undef ASM_APP_ON
|
mgl@1371
|
10768 |
+#define ASM_APP_ON "#APP\n"
|
mgl@1371
|
10769 |
+
|
mgl@1371
|
10770 |
+/*
|
mgl@1371
|
10771 |
+A C string constant for text to be output after each asm
|
mgl@1371
|
10772 |
+statement or group of consecutive ones. Normally this is
|
mgl@1371
|
10773 |
+"#NO_APP", which tells the GNU assembler to resume making the
|
mgl@1371
|
10774 |
+time-saving assumptions that are valid for ordinary compiler output.
|
mgl@1371
|
10775 |
+*/
|
mgl@1371
|
10776 |
+#undef ASM_APP_OFF
|
mgl@1371
|
10777 |
+#define ASM_APP_OFF "#NO_APP\n"
|
mgl@1371
|
10778 |
+
|
mgl@1371
|
10779 |
+
|
mgl@1371
|
10780 |
+
|
mgl@1371
|
10781 |
+#define FILE_ASM_OP "\t.file\n"
|
mgl@1371
|
10782 |
+#define IDENT_ASM_OP "\t.ident\t"
|
mgl@1371
|
10783 |
+#define SET_ASM_OP "\t.set\t"
|
mgl@1371
|
10784 |
+
|
mgl@1371
|
10785 |
+
|
mgl@1371
|
10786 |
+/*
|
mgl@1371
|
10787 |
+ * Output assembly directives to switch to section name. The section
|
mgl@1371
|
10788 |
+ * should have attributes as specified by flags, which is a bit mask
|
mgl@1371
|
10789 |
+ * of the SECTION_* flags defined in 'output.h'. If align is nonzero,
|
mgl@1371
|
10790 |
+ * it contains an alignment in bytes to be used for the section,
|
mgl@1371
|
10791 |
+ * otherwise some target default should be used. Only targets that
|
mgl@1371
|
10792 |
+ * must specify an alignment within the section directive need pay
|
mgl@1371
|
10793 |
+ * attention to align -- we will still use ASM_OUTPUT_ALIGN.
|
mgl@1371
|
10794 |
+ *
|
mgl@1371
|
10795 |
+ * NOTE: This one must not be moved to avr32.c
|
mgl@1371
|
10796 |
+ */
|
mgl@1371
|
10797 |
+#undef TARGET_ASM_NAMED_SECTION
|
mgl@1371
|
10798 |
+#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section
|
mgl@1371
|
10799 |
+
|
mgl@1371
|
10800 |
+
|
mgl@1371
|
10801 |
+/*
|
mgl@1371
|
10802 |
+You may define this macro as a C expression. You should define the
|
mgl@1371
|
10803 |
+expression to have a nonzero value if GCC should output the constant
|
mgl@1371
|
10804 |
+pool for a function before the code for the function, or a zero value if
|
mgl@1371
|
10805 |
+GCC should output the constant pool after the function. If you do
|
mgl@1371
|
10806 |
+not define this macro, the usual case, GCC will output the constant
|
mgl@1371
|
10807 |
+pool before the function.
|
mgl@1371
|
10808 |
+*/
|
mgl@1371
|
10809 |
+#define CONSTANT_POOL_BEFORE_FUNCTION 0
|
mgl@1371
|
10810 |
+
|
mgl@1371
|
10811 |
+
|
mgl@1371
|
10812 |
+/*
|
mgl@1371
|
10813 |
+Define this macro as a C expression which is nonzero if the constant
|
mgl@1371
|
10814 |
+EXP, of type tree, should be output after the code for a
|
mgl@1371
|
10815 |
+function. The compiler will normally output all constants before the
|
mgl@1371
|
10816 |
+function; you need not define this macro if this is OK.
|
mgl@1371
|
10817 |
+*/
|
mgl@1371
|
10818 |
+#define CONSTANT_AFTER_FUNCTION_P(EXP) 1
|
mgl@1371
|
10819 |
+
|
mgl@1371
|
10820 |
+
|
mgl@1371
|
10821 |
+/*
|
mgl@1371
|
10822 |
+Define this macro as a C expression which is nonzero if C is
|
mgl@1371
|
10823 |
+used as a logical line separator by the assembler.
|
mgl@1371
|
10824 |
+
|
mgl@1371
|
10825 |
+If you do not define this macro, the default is that only
|
mgl@1371
|
10826 |
+the character ';' is treated as a logical line separator.
|
mgl@1371
|
10827 |
+*/
|
mgl@1371
|
10828 |
+#define IS_ASM_LOGICAL_LINE_SEPARATOR(C) ((C) == '\n')
|
mgl@1371
|
10829 |
+
|
mgl@1371
|
10830 |
+
|
mgl@1371
|
10831 |
+/** Output of Uninitialized Variables **/
|
mgl@1371
|
10832 |
+
|
mgl@1371
|
10833 |
+/*
|
mgl@1371
|
10834 |
+A C statement (sans semicolon) to output to the stdio stream
|
mgl@1371
|
10835 |
+STREAM the assembler definition of a common-label named
|
mgl@1371
|
10836 |
+NAME whose size is SIZE bytes. The variable ROUNDED
|
mgl@1371
|
10837 |
+is the size rounded up to whatever alignment the caller wants.
|
mgl@1371
|
10838 |
+
|
mgl@1371
|
10839 |
+Use the expression assemble_name(STREAM, NAME) to
|
mgl@1371
|
10840 |
+output the name itself; before and after that, output the additional
|
mgl@1371
|
10841 |
+assembler syntax for defining the name, and a newline.
|
mgl@1371
|
10842 |
+
|
mgl@1371
|
10843 |
+This macro controls how the assembler definitions of uninitialized
|
mgl@1371
|
10844 |
+common global variables are output.
|
mgl@1371
|
10845 |
+*/
|
mgl@1371
|
10846 |
+/*
|
mgl@1371
|
10847 |
+#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \
|
mgl@1371
|
10848 |
+ avr32_asm_output_common(STREAM, NAME, SIZE, ROUNDED)
|
mgl@1371
|
10849 |
+*/
|
mgl@1371
|
10850 |
+
|
mgl@1371
|
10851 |
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
|
mgl@1371
|
10852 |
+ do \
|
mgl@1371
|
10853 |
+ { \
|
mgl@1371
|
10854 |
+ fputs ("\t.comm ", (FILE)); \
|
mgl@1371
|
10855 |
+ assemble_name ((FILE), (NAME)); \
|
mgl@1371
|
10856 |
+ fprintf ((FILE), ",%d\n", (SIZE)); \
|
mgl@1371
|
10857 |
+ } \
|
mgl@1371
|
10858 |
+ while (0)
|
mgl@1371
|
10859 |
+
|
mgl@1371
|
10860 |
+/*
|
mgl@1371
|
10861 |
+ * Like ASM_OUTPUT_BSS except takes the required alignment as a
|
mgl@1371
|
10862 |
+ * separate, explicit argument. If you define this macro, it is used
|
mgl@1371
|
10863 |
+ * in place of ASM_OUTPUT_BSS, and gives you more flexibility in
|
mgl@1371
|
10864 |
+ * handling the required alignment of the variable. The alignment is
|
mgl@1371
|
10865 |
+ * specified as the number of bits.
|
mgl@1371
|
10866 |
+ *
|
mgl@1371
|
10867 |
+ * Try to use function asm_output_aligned_bss defined in file varasm.c
|
mgl@1371
|
10868 |
+ * when defining this macro.
|
mgl@1371
|
10869 |
+ */
|
mgl@1371
|
10870 |
+#define ASM_OUTPUT_ALIGNED_BSS(STREAM, DECL, NAME, SIZE, ALIGNMENT) \
|
mgl@1371
|
10871 |
+ asm_output_aligned_bss (STREAM, DECL, NAME, SIZE, ALIGNMENT)
|
mgl@1371
|
10872 |
+
|
mgl@1371
|
10873 |
+/*
|
mgl@1371
|
10874 |
+A C statement (sans semicolon) to output to the stdio stream
|
mgl@1371
|
10875 |
+STREAM the assembler definition of a local-common-label named
|
mgl@1371
|
10876 |
+NAME whose size is SIZE bytes. The variable ROUNDED
|
mgl@1371
|
10877 |
+is the size rounded up to whatever alignment the caller wants.
|
mgl@1371
|
10878 |
+
|
mgl@1371
|
10879 |
+Use the expression assemble_name(STREAM, NAME) to
|
mgl@1371
|
10880 |
+output the name itself; before and after that, output the additional
|
mgl@1371
|
10881 |
+assembler syntax for defining the name, and a newline.
|
mgl@1371
|
10882 |
+
|
mgl@1371
|
10883 |
+This macro controls how the assembler definitions of uninitialized
|
mgl@1371
|
10884 |
+static variables are output.
|
mgl@1371
|
10885 |
+*/
|
mgl@1371
|
10886 |
+#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
|
mgl@1371
|
10887 |
+ do \
|
mgl@1371
|
10888 |
+ { \
|
mgl@1371
|
10889 |
+ fputs ("\t.lcomm ", (FILE)); \
|
mgl@1371
|
10890 |
+ assemble_name ((FILE), (NAME)); \
|
mgl@1371
|
10891 |
+ fprintf ((FILE), ",%d, %d\n", (SIZE), 2); \
|
mgl@1371
|
10892 |
+ } \
|
mgl@1371
|
10893 |
+ while (0)
|
mgl@1371
|
10894 |
+
|
mgl@1371
|
10895 |
+
|
mgl@1371
|
10896 |
+/*
|
mgl@1371
|
10897 |
+A C statement (sans semicolon) to output to the stdio stream
|
mgl@1371
|
10898 |
+STREAM the assembler definition of a label named NAME.
|
mgl@1371
|
10899 |
+Use the expression assemble_name(STREAM, NAME) to
|
mgl@1371
|
10900 |
+output the name itself; before and after that, output the additional
|
mgl@1371
|
10901 |
+assembler syntax for defining the name, and a newline.
|
mgl@1371
|
10902 |
+*/
|
mgl@1371
|
10903 |
+#define ASM_OUTPUT_LABEL(STREAM, NAME) avr32_asm_output_label(STREAM, NAME)
|
mgl@1371
|
10904 |
+
|
mgl@1371
|
10905 |
+/* A C string containing the appropriate assembler directive to
|
mgl@1371
|
10906 |
+ * specify the size of a symbol, without any arguments. On systems
|
mgl@1371
|
10907 |
+ * that use ELF, the default (in 'config/elfos.h') is '"\t.size\t"';
|
mgl@1371
|
10908 |
+ * on other systems, the default is not to define this macro.
|
mgl@1371
|
10909 |
+ *
|
mgl@1371
|
10910 |
+ * Define this macro only if it is correct to use the default
|
mgl@1371
|
10911 |
+ * definitions of ASM_ OUTPUT_SIZE_DIRECTIVE and
|
mgl@1371
|
10912 |
+ * ASM_OUTPUT_MEASURED_SIZE for your system. If you need your own
|
mgl@1371
|
10913 |
+ * custom definitions of those macros, or if you do not need explicit
|
mgl@1371
|
10914 |
+ * symbol sizes at all, do not define this macro.
|
mgl@1371
|
10915 |
+ */
|
mgl@1371
|
10916 |
+#define SIZE_ASM_OP "\t.size\t"
|
mgl@1371
|
10917 |
+
|
mgl@1371
|
10918 |
+
|
mgl@1371
|
10919 |
+/*
|
mgl@1371
|
10920 |
+A C statement (sans semicolon) to output to the stdio stream
|
mgl@1371
|
10921 |
+STREAM some commands that will make the label NAME global;
|
mgl@1371
|
10922 |
+that is, available for reference from other files. Use the expression
|
mgl@1371
|
10923 |
+assemble_name(STREAM, NAME) to output the name
|
mgl@1371
|
10924 |
+itself; before and after that, output the additional assembler syntax
|
mgl@1371
|
10925 |
+for making that name global, and a newline.
|
mgl@1371
|
10926 |
+*/
|
mgl@1371
|
10927 |
+#define GLOBAL_ASM_OP "\t.globl\t"
|
mgl@1371
|
10928 |
+
|
mgl@1371
|
10929 |
+
|
mgl@1371
|
10930 |
+
|
mgl@1371
|
10931 |
+/*
|
mgl@1371
|
10932 |
+A C expression which evaluates to true if the target supports weak symbols.
|
mgl@1371
|
10933 |
+
|
mgl@1371
|
10934 |
+If you don't define this macro, defaults.h provides a default
|
mgl@1371
|
10935 |
+definition. If either ASM_WEAKEN_LABEL or ASM_WEAKEN_DECL
|
mgl@1371
|
10936 |
+is defined, the default definition is '1'; otherwise, it is
|
mgl@1371
|
10937 |
+'0'. Define this macro if you want to control weak symbol support
|
mgl@1371
|
10938 |
+with a compiler flag such as -melf.
|
mgl@1371
|
10939 |
+*/
|
mgl@1371
|
10940 |
+#define SUPPORTS_WEAK 1
|
mgl@1371
|
10941 |
+
|
mgl@1371
|
10942 |
+/*
|
mgl@1371
|
10943 |
+A C statement (sans semicolon) to output to the stdio stream
|
mgl@1371
|
10944 |
+STREAM a reference in assembler syntax to a label named
|
mgl@1371
|
10945 |
+NAME. This should add '_' to the front of the name, if that
|
mgl@1371
|
10946 |
+is customary on your operating system, as it is in most Berkeley Unix
|
mgl@1371
|
10947 |
+systems. This macro is used in assemble_name.
|
mgl@1371
|
10948 |
+*/
|
mgl@1371
|
10949 |
+#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
|
mgl@1371
|
10950 |
+ avr32_asm_output_labelref(STREAM, NAME)
|
mgl@1371
|
10951 |
+
|
mgl@1371
|
10952 |
+
|
mgl@1371
|
10953 |
+
|
mgl@1371
|
10954 |
+/*
|
mgl@1371
|
10955 |
+A C expression to assign to OUTVAR (which is a variable of type
|
mgl@1371
|
10956 |
+char *) a newly allocated string made from the string
|
mgl@1371
|
10957 |
+NAME and the number NUMBER, with some suitable punctuation
|
mgl@1371
|
10958 |
+added. Use alloca to get space for the string.
|
mgl@1371
|
10959 |
+
|
mgl@1371
|
10960 |
+The string will be used as an argument to ASM_OUTPUT_LABELREF to
|
mgl@1371
|
10961 |
+produce an assembler label for an internal static variable whose name is
|
mgl@1371
|
10962 |
+NAME. Therefore, the string must be such as to result in valid
|
mgl@1371
|
10963 |
+assembler code. The argument NUMBER is different each time this
|
mgl@1371
|
10964 |
+macro is executed; it prevents conflicts between similarly-named
|
mgl@1371
|
10965 |
+internal static variables in different scopes.
|
mgl@1371
|
10966 |
+
|
mgl@1371
|
10967 |
+Ideally this string should not be a valid C identifier, to prevent any
|
mgl@1371
|
10968 |
+conflict with the user's own symbols. Most assemblers allow periods
|
mgl@1371
|
10969 |
+or percent signs in assembler symbols; putting at least one of these
|
mgl@1371
|
10970 |
+between the name and the number will suffice.
|
mgl@1371
|
10971 |
+*/
|
mgl@1371
|
10972 |
+#define ASM_FORMAT_PRIVATE_NAME(OUTVAR, NAME, NUMBER) \
|
mgl@1371
|
10973 |
+ do \
|
mgl@1371
|
10974 |
+ { \
|
mgl@1371
|
10975 |
+ (OUTVAR) = (char *) alloca (strlen ((NAME)) + 10); \
|
mgl@1371
|
10976 |
+ sprintf ((OUTVAR), "%s.%d", (NAME), (NUMBER)); \
|
mgl@1371
|
10977 |
+ } \
|
mgl@1371
|
10978 |
+ while (0)
|
mgl@1371
|
10979 |
+
|
mgl@1371
|
10980 |
+
|
mgl@1371
|
10981 |
+/** Macros Controlling Initialization Routines **/
|
mgl@1371
|
10982 |
+
|
mgl@1371
|
10983 |
+
|
mgl@1371
|
10984 |
+/*
|
mgl@1371
|
10985 |
+If defined, main will not call __main as described above.
|
mgl@1371
|
10986 |
+This macro should be defined for systems that control start-up code
|
mgl@1371
|
10987 |
+on a symbol-by-symbol basis, such as OSF/1, and should not
|
mgl@1371
|
10988 |
+be defined explicitly for systems that support INIT_SECTION_ASM_OP.
|
mgl@1371
|
10989 |
+*/
|
mgl@1371
|
10990 |
+/*
|
mgl@1371
|
10991 |
+ __main is not defined when debugging.
|
mgl@1371
|
10992 |
+*/
|
mgl@1371
|
10993 |
+#define HAS_INIT_SECTION
|
mgl@1371
|
10994 |
+
|
mgl@1371
|
10995 |
+
|
mgl@1371
|
10996 |
+/** Output of Assembler Instructions **/
|
mgl@1371
|
10997 |
+
|
mgl@1371
|
10998 |
+/*
|
mgl@1371
|
10999 |
+A C initializer containing the assembler's names for the machine
|
mgl@1371
|
11000 |
+registers, each one as a C string constant. This is what translates
|
mgl@1371
|
11001 |
+register numbers in the compiler into assembler language.
|
mgl@1371
|
11002 |
+*/
|
mgl@1371
|
11003 |
+
|
mgl@1371
|
11004 |
+#define REGISTER_NAMES \
|
mgl@1371
|
11005 |
+{ \
|
mgl@1371
|
11006 |
+ "pc", "lr", \
|
mgl@1371
|
11007 |
+ "sp", "r12", \
|
mgl@1371
|
11008 |
+ "r11", "r10", \
|
mgl@1371
|
11009 |
+ "r9", "r8", \
|
mgl@1371
|
11010 |
+ "r7", "r6", \
|
mgl@1371
|
11011 |
+ "r5", "r4", \
|
mgl@1371
|
11012 |
+ "r3", "r2", \
|
mgl@1371
|
11013 |
+ "r1", "r0", \
|
mgl@1371
|
11014 |
+ "f15","f14", \
|
mgl@1371
|
11015 |
+ "f13","f12", \
|
mgl@1371
|
11016 |
+ "f11","f10", \
|
mgl@1371
|
11017 |
+ "f9", "f8", \
|
mgl@1371
|
11018 |
+ "f7", "f6", \
|
mgl@1371
|
11019 |
+ "f5", "f4", \
|
mgl@1371
|
11020 |
+ "f3", "f2", \
|
mgl@1371
|
11021 |
+ "f1", "f0" \
|
mgl@1371
|
11022 |
+}
|
mgl@1371
|
11023 |
+
|
mgl@1371
|
11024 |
+/*
|
mgl@1371
|
11025 |
+A C compound statement to output to stdio stream STREAM the
|
mgl@1371
|
11026 |
+assembler syntax for an instruction operand X. X is an
|
mgl@1371
|
11027 |
+RTL expression.
|
mgl@1371
|
11028 |
+
|
mgl@1371
|
11029 |
+CODE is a value that can be used to specify one of several ways
|
mgl@1371
|
11030 |
+of printing the operand. It is used when identical operands must be
|
mgl@1371
|
11031 |
+printed differently depending on the context. CODE comes from
|
mgl@1371
|
11032 |
+the '%' specification that was used to request printing of the
|
mgl@1371
|
11033 |
+operand. If the specification was just '%digit' then
|
mgl@1371
|
11034 |
+CODE is 0; if the specification was '%ltr digit'
|
mgl@1371
|
11035 |
+then CODE is the ASCII code for ltr.
|
mgl@1371
|
11036 |
+
|
mgl@1371
|
11037 |
+If X is a register, this macro should print the register's name.
|
mgl@1371
|
11038 |
+The names can be found in an array reg_names whose type is
|
mgl@1371
|
11039 |
+char *[]. reg_names is initialized from REGISTER_NAMES.
|
mgl@1371
|
11040 |
+
|
mgl@1371
|
11041 |
+When the machine description has a specification '%punct'
|
mgl@1371
|
11042 |
+(a '%' followed by a punctuation character), this macro is called
|
mgl@1371
|
11043 |
+with a null pointer for X and the punctuation character for
|
mgl@1371
|
11044 |
+CODE.
|
mgl@1371
|
11045 |
+*/
|
mgl@1371
|
11046 |
+#define PRINT_OPERAND(STREAM, X, CODE) avr32_print_operand(STREAM, X, CODE)
|
mgl@1371
|
11047 |
+
|
mgl@1371
|
11048 |
+/* A C statement to be executed just prior to the output of
|
mgl@1371
|
11049 |
+ assembler code for INSN, to modify the extracted operands so
|
mgl@1371
|
11050 |
+ they will be output differently.
|
mgl@1371
|
11051 |
+
|
mgl@1371
|
11052 |
+ Here the argument OPVEC is the vector containing the operands
|
mgl@1371
|
11053 |
+ extracted from INSN, and NOPERANDS is the number of elements of
|
mgl@1371
|
11054 |
+ the vector which contain meaningful data for this insn.
|
mgl@1371
|
11055 |
+ The contents of this vector are what will be used to convert the insn
|
mgl@1371
|
11056 |
+ template into assembler code, so you can change the assembler output
|
mgl@1371
|
11057 |
+ by changing the contents of the vector. */
|
mgl@1371
|
11058 |
+#define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \
|
mgl@1371
|
11059 |
+ avr32_final_prescan_insn ((INSN), (OPVEC), (NOPERANDS))
|
mgl@1371
|
11060 |
+
|
mgl@1371
|
11061 |
+/*
|
mgl@1371
|
11062 |
+A C expression which evaluates to true if CODE is a valid
|
mgl@1371
|
11063 |
+punctuation character for use in the PRINT_OPERAND macro. If
|
mgl@1371
|
11064 |
+PRINT_OPERAND_PUNCT_VALID_P is not defined, it means that no
|
mgl@1371
|
11065 |
+punctuation characters (except for the standard one, '%') are used
|
mgl@1371
|
11066 |
+in this way.
|
mgl@1371
|
11067 |
+*/
|
mgl@1371
|
11068 |
+#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
|
mgl@1371
|
11069 |
+ (((CODE) == '?') \
|
mgl@1371
|
11070 |
+ || ((CODE) == '!'))
|
mgl@1371
|
11071 |
+
|
mgl@1371
|
11072 |
+/*
|
mgl@1371
|
11073 |
+A C compound statement to output to stdio stream STREAM the
|
mgl@1371
|
11074 |
+assembler syntax for an instruction operand that is a memory reference
|
mgl@1371
|
11075 |
+whose address is X. X is an RTL expression.
|
mgl@1371
|
11076 |
+
|
mgl@1371
|
11077 |
+On some machines, the syntax for a symbolic address depends on the
|
mgl@1371
|
11078 |
+section that the address refers to. On these machines, define the macro
|
mgl@1371
|
11079 |
+ENCODE_SECTION_INFO to store the information into the
|
mgl@1371
|
11080 |
+symbol_ref, and then check for it here. (see Assembler Format.)
|
mgl@1371
|
11081 |
+*/
|
mgl@1371
|
11082 |
+#define PRINT_OPERAND_ADDRESS(STREAM, X) avr32_print_operand_address(STREAM, X)
|
mgl@1371
|
11083 |
+
|
mgl@1371
|
11084 |
+
|
mgl@1371
|
11085 |
+/** Output of Dispatch Tables **/
|
mgl@1371
|
11086 |
+
|
mgl@1371
|
11087 |
+/*
|
mgl@1371
|
11088 |
+ * A C statement to output to the stdio stream stream an assembler
|
mgl@1371
|
11089 |
+ * pseudo-instruction to generate a difference between two
|
mgl@1371
|
11090 |
+ * labels. value and rel are the numbers of two internal labels. The
|
mgl@1371
|
11091 |
+ * definitions of these labels are output using
|
mgl@1371
|
11092 |
+ * (*targetm.asm_out.internal_label), and they must be printed in the
|
mgl@1371
|
11093 |
+ * same way here. For example,
|
mgl@1371
|
11094 |
+ *
|
mgl@1371
|
11095 |
+ * fprintf (stream, "\t.word L%d-L%d\n",
|
mgl@1371
|
11096 |
+ * value, rel)
|
mgl@1371
|
11097 |
+ *
|
mgl@1371
|
11098 |
+ * You must provide this macro on machines where the addresses in a
|
mgl@1371
|
11099 |
+ * dispatch table are relative to the table's own address. If defined,
|
mgl@1371
|
11100 |
+ * GCC will also use this macro on all machines when producing
|
mgl@1371
|
11101 |
+ * PIC. body is the body of the ADDR_DIFF_VEC; it is provided so that
|
mgl@1371
|
11102 |
+ * the mode and flags can be read.
|
mgl@1371
|
11103 |
+ */
|
mgl@1371
|
11104 |
+#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \
|
mgl@1371
|
11105 |
+ fprintf(STREAM, "\tbral\t%sL%d\n", LOCAL_LABEL_PREFIX, VALUE)
|
mgl@1371
|
11106 |
+
|
mgl@1371
|
11107 |
+/*
|
mgl@1371
|
11108 |
+This macro should be provided on machines where the addresses
|
mgl@1371
|
11109 |
+in a dispatch table are absolute.
|
mgl@1371
|
11110 |
+
|
mgl@1371
|
11111 |
+The definition should be a C statement to output to the stdio stream
|
mgl@1371
|
11112 |
+STREAM an assembler pseudo-instruction to generate a reference to
|
mgl@1371
|
11113 |
+a label. VALUE is the number of an internal label whose
|
mgl@1371
|
11114 |
+definition is output using ASM_OUTPUT_INTERNAL_LABEL.
|
mgl@1371
|
11115 |
+For example,
|
mgl@1371
|
11116 |
+
|
mgl@1371
|
11117 |
+fprintf(STREAM, "\t.word L%d\n", VALUE)
|
mgl@1371
|
11118 |
+*/
|
mgl@1371
|
11119 |
+
|
mgl@1371
|
11120 |
+#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
|
mgl@1371
|
11121 |
+ fprintf(STREAM, "\t.long %sL%d\n", LOCAL_LABEL_PREFIX, VALUE)
|
mgl@1371
|
11122 |
+
|
mgl@1371
|
11123 |
+/** Assembler Commands for Exception Regions */
|
mgl@1371
|
11124 |
+
|
mgl@1371
|
11125 |
+/* ToDo: All of this subsection */
|
mgl@1371
|
11126 |
+
|
mgl@1371
|
11127 |
+/** Assembler Commands for Alignment */
|
mgl@1371
|
11128 |
+
|
mgl@1371
|
11129 |
+
|
mgl@1371
|
11130 |
+/*
|
mgl@1371
|
11131 |
+A C statement to output to the stdio stream STREAM an assembler
|
mgl@1371
|
11132 |
+command to advance the location counter to a multiple of 2 to the
|
mgl@1371
|
11133 |
+POWER bytes. POWER will be a C expression of type int.
|
mgl@1371
|
11134 |
+*/
|
mgl@1371
|
11135 |
+#define ASM_OUTPUT_ALIGN(STREAM, POWER) \
|
mgl@1371
|
11136 |
+ do \
|
mgl@1371
|
11137 |
+ { \
|
mgl@1371
|
11138 |
+ if ((POWER) != 0) \
|
mgl@1371
|
11139 |
+ fprintf(STREAM, "\t.align\t%d\n", POWER); \
|
mgl@1371
|
11140 |
+ } \
|
mgl@1371
|
11141 |
+ while (0)
|
mgl@1371
|
11142 |
+
|
mgl@1371
|
11143 |
+/*
|
mgl@1371
|
11144 |
+Like ASM_OUTPUT_ALIGN, except that the \nop" instruction is used for padding, if
|
mgl@1371
|
11145 |
+necessary.
|
mgl@1371
|
11146 |
+*/
|
mgl@1371
|
11147 |
+#define ASM_OUTPUT_ALIGN_WITH_NOP(STREAM, POWER) \
|
mgl@1371
|
11148 |
+ fprintf(STREAM, "\t.balignw\t%d, 0xd703\n", (1 << POWER))
|
mgl@1371
|
11149 |
+
|
mgl@1371
|
11150 |
+
|
mgl@1371
|
11151 |
+
|
mgl@1371
|
11152 |
+/******************************************************************************
|
mgl@1371
|
11153 |
+ * Controlling Debugging Information Format
|
mgl@1371
|
11154 |
+ *****************************************************************************/
|
mgl@1371
|
11155 |
+
|
mgl@1371
|
11156 |
+/* How to renumber registers for dbx and gdb. */
|
mgl@1371
|
11157 |
+#define DBX_REGISTER_NUMBER(REGNO) ASM_REGNUM (REGNO)
|
mgl@1371
|
11158 |
+
|
mgl@1371
|
11159 |
+/* The DWARF 2 CFA column which tracks the return address. */
|
mgl@1371
|
11160 |
+#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM(LR_REGNUM)
|
mgl@1371
|
11161 |
+
|
mgl@1371
|
11162 |
+/*
|
mgl@1371
|
11163 |
+Define this macro if GCC should produce dwarf version 2 format
|
mgl@1371
|
11164 |
+debugging output in response to the -g option.
|
mgl@1371
|
11165 |
+
|
mgl@1371
|
11166 |
+To support optional call frame debugging information, you must also
|
mgl@1371
|
11167 |
+define INCOMING_RETURN_ADDR_RTX and either set
|
mgl@1371
|
11168 |
+RTX_FRAME_RELATED_P on the prologue insns if you use RTL for the
|
mgl@1371
|
11169 |
+prologue, or call dwarf2out_def_cfa and dwarf2out_reg_save
|
mgl@1371
|
11170 |
+as appropriate from TARGET_ASM_FUNCTION_PROLOGUE if you don't.
|
mgl@1371
|
11171 |
+*/
|
mgl@1371
|
11172 |
+#define DWARF2_DEBUGGING_INFO 1
|
mgl@1371
|
11173 |
+
|
mgl@1371
|
11174 |
+
|
mgl@1371
|
11175 |
+#define DWARF2_ASM_LINE_DEBUG_INFO 1
|
mgl@1371
|
11176 |
+#define DWARF2_FRAME_INFO 1
|
mgl@1371
|
11177 |
+
|
mgl@1371
|
11178 |
+
|
mgl@1371
|
11179 |
+/******************************************************************************
|
mgl@1371
|
11180 |
+ * Miscellaneous Parameters
|
mgl@1371
|
11181 |
+ *****************************************************************************/
|
mgl@1371
|
11182 |
+
|
mgl@1371
|
11183 |
+/* ToDo: a lot */
|
mgl@1371
|
11184 |
+
|
mgl@1371
|
11185 |
+/*
|
mgl@1371
|
11186 |
+An alias for a machine mode name. This is the machine mode that
|
mgl@1371
|
11187 |
+elements of a jump-table should have.
|
mgl@1371
|
11188 |
+*/
|
mgl@1371
|
11189 |
+#define CASE_VECTOR_MODE SImode
|
mgl@1371
|
11190 |
+
|
mgl@1371
|
11191 |
+/*
|
mgl@1371
|
11192 |
+Define this macro to be a C expression to indicate when jump-tables
|
mgl@1371
|
11193 |
+should contain relative addresses. If jump-tables never contain
|
mgl@1371
|
11194 |
+relative addresses, then you need not define this macro.
|
mgl@1371
|
11195 |
+*/
|
mgl@1371
|
11196 |
+#define CASE_VECTOR_PC_RELATIVE 0
|
mgl@1371
|
11197 |
+
|
mgl@1371
|
11198 |
+/* Increase the threshold for using table jumps on the UC arch. */
|
mgl@1371
|
11199 |
+#define CASE_VALUES_THRESHOLD (TARGET_BRANCH_PRED ? 4 : 7)
|
mgl@1371
|
11200 |
+
|
mgl@1371
|
11201 |
+/*
|
mgl@1371
|
11202 |
+The maximum number of bytes that a single instruction can move quickly
|
mgl@1371
|
11203 |
+between memory and registers or between two memory locations.
|
mgl@1371
|
11204 |
+*/
|
mgl@1371
|
11205 |
+#define MOVE_MAX (2*UNITS_PER_WORD)
|
mgl@1371
|
11206 |
+
|
mgl@1371
|
11207 |
+
|
mgl@1371
|
11208 |
+/* A C expression that is nonzero if on this machine the number of bits actually used
|
mgl@1371
|
11209 |
+ for the count of a shift operation is equal to the number of bits needed to represent
|
mgl@1371
|
11210 |
+ the size of the object being shifted. When this macro is nonzero, the compiler will
|
mgl@1371
|
11211 |
+ assume that it is safe to omit a sign-extend, zero-extend, and certain bitwise 'and'
|
mgl@1371
|
11212 |
+ instructions that truncates the count of a shift operation. On machines that have
|
mgl@1371
|
11213 |
+ instructions that act on bit-fields at variable positions, which may include 'bit test'
|
mgl@1371
|
11214 |
+ 378 GNU Compiler Collection (GCC) Internals
|
mgl@1371
|
11215 |
+ instructions, a nonzero SHIFT_COUNT_TRUNCATED also enables deletion of truncations
|
mgl@1371
|
11216 |
+ of the values that serve as arguments to bit-field instructions.
|
mgl@1371
|
11217 |
+ If both types of instructions truncate the count (for shifts) and position (for bit-field
|
mgl@1371
|
11218 |
+ operations), or if no variable-position bit-field instructions exist, you should define
|
mgl@1371
|
11219 |
+ this macro.
|
mgl@1371
|
11220 |
+ However, on some machines, such as the 80386 and the 680x0, truncation only applies
|
mgl@1371
|
11221 |
+ to shift operations and not the (real or pretended) bit-field operations. Define SHIFT_
|
mgl@1371
|
11222 |
+ COUNT_TRUNCATED to be zero on such machines. Instead, add patterns to the 'md' file
|
mgl@1371
|
11223 |
+ that include the implied truncation of the shift instructions.
|
mgl@1371
|
11224 |
+ You need not dene this macro if it would always have the value of zero. */
|
mgl@1371
|
11225 |
+#define SHIFT_COUNT_TRUNCATED 1
|
mgl@1371
|
11226 |
+
|
mgl@1371
|
11227 |
+/*
|
mgl@1371
|
11228 |
+A C expression which is nonzero if on this machine it is safe to
|
mgl@1371
|
11229 |
+convert an integer of INPREC bits to one of OUTPREC
|
mgl@1371
|
11230 |
+bits (where OUTPREC is smaller than INPREC) by merely
|
mgl@1371
|
11231 |
+operating on it as if it had only OUTPREC bits.
|
mgl@1371
|
11232 |
+
|
mgl@1371
|
11233 |
+On many machines, this expression can be 1.
|
mgl@1371
|
11234 |
+
|
mgl@1371
|
11235 |
+When TRULY_NOOP_TRUNCATION returns 1 for a pair of sizes for
|
mgl@1371
|
11236 |
+modes for which MODES_TIEABLE_P is 0, suboptimal code can result.
|
mgl@1371
|
11237 |
+If this is the case, making TRULY_NOOP_TRUNCATION return 0 in
|
mgl@1371
|
11238 |
+such cases may improve things.
|
mgl@1371
|
11239 |
+*/
|
mgl@1371
|
11240 |
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
|
mgl@1371
|
11241 |
+
|
mgl@1371
|
11242 |
+/*
|
mgl@1371
|
11243 |
+An alias for the machine mode for pointers. On most machines, define
|
mgl@1371
|
11244 |
+this to be the integer mode corresponding to the width of a hardware
|
mgl@1371
|
11245 |
+pointer; SImode on 32-bit machine or DImode on 64-bit machines.
|
mgl@1371
|
11246 |
+On some machines you must define this to be one of the partial integer
|
mgl@1371
|
11247 |
+modes, such as PSImode.
|
mgl@1371
|
11248 |
+
|
mgl@1371
|
11249 |
+The width of Pmode must be at least as large as the value of
|
mgl@1371
|
11250 |
+POINTER_SIZE. If it is not equal, you must define the macro
|
mgl@1371
|
11251 |
+POINTERS_EXTEND_UNSIGNED to specify how pointers are extended
|
mgl@1371
|
11252 |
+to Pmode.
|
mgl@1371
|
11253 |
+*/
|
mgl@1371
|
11254 |
+#define Pmode SImode
|
mgl@1371
|
11255 |
+
|
mgl@1371
|
11256 |
+/*
|
mgl@1371
|
11257 |
+An alias for the machine mode used for memory references to functions
|
mgl@1371
|
11258 |
+being called, in call RTL expressions. On most machines this
|
mgl@1371
|
11259 |
+should be QImode.
|
mgl@1371
|
11260 |
+*/
|
mgl@1371
|
11261 |
+#define FUNCTION_MODE SImode
|
mgl@1371
|
11262 |
+
|
mgl@1371
|
11263 |
+
|
mgl@1371
|
11264 |
+#define REG_S_P(x) \
|
mgl@1371
|
11265 |
+ (REG_P (x) || (GET_CODE (x) == SUBREG && REG_P (XEXP (x, 0))))
|
mgl@1371
|
11266 |
+
|
mgl@1371
|
11267 |
+
|
mgl@1371
|
11268 |
+/* If defined, modifies the length assigned to instruction INSN as a
|
mgl@1371
|
11269 |
+ function of the context in which it is used. LENGTH is an lvalue
|
mgl@1371
|
11270 |
+ that contains the initially computed length of the insn and should
|
mgl@1371
|
11271 |
+ be updated with the correct length of the insn. */
|
mgl@1371
|
11272 |
+#define ADJUST_INSN_LENGTH(INSN, LENGTH) \
|
mgl@1371
|
11273 |
+ ((LENGTH) = avr32_adjust_insn_length ((INSN), (LENGTH)))
|
mgl@1371
|
11274 |
+
|
mgl@1371
|
11275 |
+
|
mgl@1371
|
11276 |
+#define CLZ_DEFINED_VALUE_AT_ZERO(mode, value) \
|
mgl@1371
|
11277 |
+ (value = 32, (mode == SImode))
|
mgl@1371
|
11278 |
+
|
mgl@1371
|
11279 |
+#define CTZ_DEFINED_VALUE_AT_ZERO(mode, value) \
|
mgl@1371
|
11280 |
+ (value = 32, (mode == SImode))
|
mgl@1371
|
11281 |
+
|
mgl@1371
|
11282 |
+#define UNITS_PER_SIMD_WORD UNITS_PER_WORD
|
mgl@1371
|
11283 |
+
|
mgl@1371
|
11284 |
+#define STORE_FLAG_VALUE 1
|
mgl@1371
|
11285 |
+
|
mgl@1371
|
11286 |
+
|
mgl@1371
|
11287 |
+/* IF-conversion macros. */
|
mgl@1371
|
11288 |
+#define IFCVT_MODIFY_INSN( CE_INFO, PATTERN, INSN ) \
|
mgl@1371
|
11289 |
+ { \
|
mgl@1371
|
11290 |
+ (PATTERN) = avr32_ifcvt_modify_insn (CE_INFO, PATTERN, INSN, &num_true_changes); \
|
mgl@1371
|
11291 |
+ }
|
mgl@1371
|
11292 |
+
|
mgl@1371
|
11293 |
+#define IFCVT_EXTRA_FIELDS \
|
mgl@1371
|
11294 |
+ int num_cond_clobber_insns; \
|
mgl@1371
|
11295 |
+ int num_extra_move_insns; \
|
mgl@1371
|
11296 |
+ rtx extra_move_insns[MAX_CONDITIONAL_EXECUTE]; \
|
mgl@1371
|
11297 |
+ rtx moved_insns[MAX_CONDITIONAL_EXECUTE];
|
mgl@1371
|
11298 |
+
|
mgl@1371
|
11299 |
+#define IFCVT_INIT_EXTRA_FIELDS( CE_INFO ) \
|
mgl@1371
|
11300 |
+ { \
|
mgl@1371
|
11301 |
+ (CE_INFO)->num_cond_clobber_insns = 0; \
|
mgl@1371
|
11302 |
+ (CE_INFO)->num_extra_move_insns = 0; \
|
mgl@1371
|
11303 |
+ }
|
mgl@1371
|
11304 |
+
|
mgl@1371
|
11305 |
+
|
mgl@1371
|
11306 |
+#define IFCVT_MODIFY_CANCEL( CE_INFO ) avr32_ifcvt_modify_cancel (CE_INFO, &num_true_changes)
|
mgl@1371
|
11307 |
+
|
mgl@1371
|
11308 |
+#define IFCVT_ALLOW_MODIFY_TEST_IN_INSN 1
|
mgl@1371
|
11309 |
+#define IFCVT_COND_EXEC_BEFORE_RELOAD (TARGET_COND_EXEC_BEFORE_RELOAD)
|
mgl@1371
|
11310 |
+
|
mgl@1371
|
11311 |
+enum avr32_builtins
|
mgl@1371
|
11312 |
+{
|
mgl@1371
|
11313 |
+ AVR32_BUILTIN_MTSR,
|
mgl@1371
|
11314 |
+ AVR32_BUILTIN_MFSR,
|
mgl@1371
|
11315 |
+ AVR32_BUILTIN_MTDR,
|
mgl@1371
|
11316 |
+ AVR32_BUILTIN_MFDR,
|
mgl@1371
|
11317 |
+ AVR32_BUILTIN_CACHE,
|
mgl@1371
|
11318 |
+ AVR32_BUILTIN_SYNC,
|
mgl@1371
|
11319 |
+ AVR32_BUILTIN_SSRF,
|
mgl@1371
|
11320 |
+ AVR32_BUILTIN_CSRF,
|
mgl@1371
|
11321 |
+ AVR32_BUILTIN_TLBR,
|
mgl@1371
|
11322 |
+ AVR32_BUILTIN_TLBS,
|
mgl@1371
|
11323 |
+ AVR32_BUILTIN_TLBW,
|
mgl@1371
|
11324 |
+ AVR32_BUILTIN_BREAKPOINT,
|
mgl@1371
|
11325 |
+ AVR32_BUILTIN_XCHG,
|
mgl@1371
|
11326 |
+ AVR32_BUILTIN_LDXI,
|
mgl@1371
|
11327 |
+ AVR32_BUILTIN_BSWAP16,
|
mgl@1371
|
11328 |
+ AVR32_BUILTIN_BSWAP32,
|
mgl@1371
|
11329 |
+ AVR32_BUILTIN_COP,
|
mgl@1371
|
11330 |
+ AVR32_BUILTIN_MVCR_W,
|
mgl@1371
|
11331 |
+ AVR32_BUILTIN_MVRC_W,
|
mgl@1371
|
11332 |
+ AVR32_BUILTIN_MVCR_D,
|
mgl@1371
|
11333 |
+ AVR32_BUILTIN_MVRC_D,
|
mgl@1371
|
11334 |
+ AVR32_BUILTIN_MULSATHH_H,
|
mgl@1371
|
11335 |
+ AVR32_BUILTIN_MULSATHH_W,
|
mgl@1371
|
11336 |
+ AVR32_BUILTIN_MULSATRNDHH_H,
|
mgl@1371
|
11337 |
+ AVR32_BUILTIN_MULSATRNDWH_W,
|
mgl@1371
|
11338 |
+ AVR32_BUILTIN_MULSATWH_W,
|
mgl@1371
|
11339 |
+ AVR32_BUILTIN_MACSATHH_W,
|
mgl@1371
|
11340 |
+ AVR32_BUILTIN_SATADD_H,
|
mgl@1371
|
11341 |
+ AVR32_BUILTIN_SATSUB_H,
|
mgl@1371
|
11342 |
+ AVR32_BUILTIN_SATADD_W,
|
mgl@1371
|
11343 |
+ AVR32_BUILTIN_SATSUB_W,
|
mgl@1371
|
11344 |
+ AVR32_BUILTIN_MULWH_D,
|
mgl@1371
|
11345 |
+ AVR32_BUILTIN_MULNWH_D,
|
mgl@1371
|
11346 |
+ AVR32_BUILTIN_MACWH_D,
|
mgl@1371
|
11347 |
+ AVR32_BUILTIN_MACHH_D,
|
mgl@1371
|
11348 |
+ AVR32_BUILTIN_MUSFR,
|
mgl@1371
|
11349 |
+ AVR32_BUILTIN_MUSTR,
|
mgl@1371
|
11350 |
+ AVR32_BUILTIN_SATS,
|
mgl@1371
|
11351 |
+ AVR32_BUILTIN_SATU,
|
mgl@1371
|
11352 |
+ AVR32_BUILTIN_SATRNDS,
|
mgl@1371
|
11353 |
+ AVR32_BUILTIN_SATRNDU,
|
mgl@1371
|
11354 |
+ AVR32_BUILTIN_MEMS,
|
mgl@1371
|
11355 |
+ AVR32_BUILTIN_MEMC,
|
mgl@1371
|
11356 |
+ AVR32_BUILTIN_MEMT
|
mgl@1371
|
11357 |
+};
|
mgl@1371
|
11358 |
+
|
mgl@1371
|
11359 |
+
|
mgl@1371
|
11360 |
+#define FLOAT_LIB_COMPARE_RETURNS_BOOL(MODE, COMPARISON) \
|
mgl@1371
|
11361 |
+ ((MODE == SFmode) || (MODE == DFmode))
|
mgl@1371
|
11362 |
+
|
mgl@1371
|
11363 |
+#define RENAME_LIBRARY_SET ".set"
|
mgl@1371
|
11364 |
+
|
mgl@1371
|
11365 |
+/* Make ABI_NAME an alias for __GCC_NAME. */
|
mgl@1371
|
11366 |
+#define RENAME_LIBRARY(GCC_NAME, ABI_NAME) \
|
mgl@1371
|
11367 |
+ __asm__ (".globl\t__avr32_" #ABI_NAME "\n" \
|
mgl@1371
|
11368 |
+ ".set\t__avr32_" #ABI_NAME \
|
mgl@1371
|
11369 |
+ ", __" #GCC_NAME "\n");
|
mgl@1371
|
11370 |
+
|
mgl@1371
|
11371 |
+/* Give libgcc functions avr32 ABI name. */
|
mgl@1371
|
11372 |
+#ifdef L_muldi3
|
mgl@1371
|
11373 |
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (muldi3, mul64)
|
mgl@1371
|
11374 |
+#endif
|
mgl@1371
|
11375 |
+#ifdef L_divdi3
|
mgl@1371
|
11376 |
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (divdi3, sdiv64)
|
mgl@1371
|
11377 |
+#endif
|
mgl@1371
|
11378 |
+#ifdef L_udivdi3
|
mgl@1371
|
11379 |
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (udivdi3, udiv64)
|
mgl@1371
|
11380 |
+#endif
|
mgl@1371
|
11381 |
+#ifdef L_moddi3
|
mgl@1371
|
11382 |
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (moddi3, smod64)
|
mgl@1371
|
11383 |
+#endif
|
mgl@1371
|
11384 |
+#ifdef L_umoddi3
|
mgl@1371
|
11385 |
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (umoddi3, umod64)
|
mgl@1371
|
11386 |
+#endif
|
mgl@1371
|
11387 |
+#ifdef L_ashldi3
|
mgl@1371
|
11388 |
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (ashldi3, lsl64)
|
mgl@1371
|
11389 |
+#endif
|
mgl@1371
|
11390 |
+#ifdef L_lshrdi3
|
mgl@1371
|
11391 |
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (lshrdi3, lsr64)
|
mgl@1371
|
11392 |
+#endif
|
mgl@1371
|
11393 |
+#ifdef L_ashrdi3
|
mgl@1371
|
11394 |
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (ashrdi3, asr64)
|
mgl@1371
|
11395 |
+#endif
|
mgl@1371
|
11396 |
+
|
mgl@1371
|
11397 |
+#ifdef L_fixsfdi
|
mgl@1371
|
11398 |
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixsfdi, f32_to_s64)
|
mgl@1371
|
11399 |
+#endif
|
mgl@1371
|
11400 |
+#ifdef L_fixunssfdi
|
mgl@1371
|
11401 |
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunssfdi, f32_to_u64)
|
mgl@1371
|
11402 |
+#endif
|
mgl@1371
|
11403 |
+#ifdef L_floatdidf
|
mgl@1371
|
11404 |
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (floatdidf, s64_to_f64)
|
mgl@1371
|
11405 |
+#endif
|
mgl@1371
|
11406 |
+#ifdef L_floatdisf
|
mgl@1371
|
11407 |
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (floatdisf, s64_to_f32)
|
mgl@1371
|
11408 |
+#endif
|
mgl@1371
|
11409 |
+
|
mgl@1371
|
11410 |
+#endif
|
mgl@1371
|
11411 |
--- /dev/null
|
mgl@1371
|
11412 |
+++ b/gcc/config/avr32/avr32.md
|
mgl@1371
|
11413 |
@@ -0,0 +1,4893 @@
|
mgl@1371
|
11414 |
+;; AVR32 machine description file.
|
mgl@1371
|
11415 |
+;; Copyright 2003-2006 Atmel Corporation.
|
mgl@1371
|
11416 |
+;;
|
mgl@1371
|
11417 |
+;; Written by Ronny Pedersen, Atmel Norway, <rpedersen@atmel.com>
|
mgl@1371
|
11418 |
+;;
|
mgl@1371
|
11419 |
+;; This file is part of GCC.
|
mgl@1371
|
11420 |
+;;
|
mgl@1371
|
11421 |
+;; This program is free software; you can redistribute it and/or modify
|
mgl@1371
|
11422 |
+;; it under the terms of the GNU General Public License as published by
|
mgl@1371
|
11423 |
+;; the Free Software Foundation; either version 2 of the License, or
|
mgl@1371
|
11424 |
+;; (at your option) any later version.
|
mgl@1371
|
11425 |
+;;
|
mgl@1371
|
11426 |
+;; This program is distributed in the hope that it will be useful,
|
mgl@1371
|
11427 |
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
mgl@1371
|
11428 |
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
mgl@1371
|
11429 |
+;; GNU General Public License for more details.
|
mgl@1371
|
11430 |
+;;
|
mgl@1371
|
11431 |
+;; You should have received a copy of the GNU General Public License
|
mgl@1371
|
11432 |
+;; along with this program; if not, write to the Free Software
|
mgl@1371
|
11433 |
+;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
mgl@1371
|
11434 |
+
|
mgl@1371
|
11435 |
+;; -*- Mode: Scheme -*-
|
mgl@1371
|
11436 |
+
|
mgl@1371
|
11437 |
+(define_attr "type" "alu,alu2,alu_sat,mulhh,mulwh,mulww_w,mulww_d,div,machh_w,macww_w,macww_d,branch,call,load,load_rm,store,load2,load4,store2,store4,fmul,fcmps,fcmpd,fcast,fmv,fmvcpu,fldd,fstd,flds,fsts,fstm"
|
mgl@1371
|
11438 |
+ (const_string "alu"))
|
mgl@1371
|
11439 |
+
|
mgl@1371
|
11440 |
+
|
mgl@1371
|
11441 |
+(define_attr "cc" "none,set_vncz,set_ncz,set_cz,set_z,set_z_if_not_v2,bld,compare,cmp_cond_insn,clobber,call_set,fpcompare,from_fpcc"
|
mgl@1371
|
11442 |
+ (const_string "none"))
|
mgl@1371
|
11443 |
+
|
mgl@1371
|
11444 |
+
|
mgl@1371
|
11445 |
+; NB! Keep this in sync with enum architecture_type in avr32.h
|
mgl@1371
|
11446 |
+(define_attr "pipeline" "ap,ucr1,ucr2,ucr2nomul"
|
mgl@1371
|
11447 |
+ (const (symbol_ref "avr32_arch->arch_type")))
|
mgl@1371
|
11448 |
+
|
mgl@1371
|
11449 |
+; Insn length in bytes
|
mgl@1371
|
11450 |
+(define_attr "length" ""
|
mgl@1371
|
11451 |
+ (const_int 4))
|
mgl@1371
|
11452 |
+
|
mgl@1371
|
11453 |
+; Signal if an insn is predicable and hence can be conditionally executed.
|
mgl@1371
|
11454 |
+(define_attr "predicable" "no,yes" (const_string "no"))
|
mgl@1371
|
11455 |
+
|
mgl@1371
|
11456 |
+;; Uses of UNSPEC in this file:
|
mgl@1371
|
11457 |
+(define_constants
|
mgl@1371
|
11458 |
+ [(UNSPEC_PUSHM 0)
|
mgl@1371
|
11459 |
+ (UNSPEC_POPM 1)
|
mgl@1371
|
11460 |
+ (UNSPEC_UDIVMODSI4_INTERNAL 2)
|
mgl@1371
|
11461 |
+ (UNSPEC_DIVMODSI4_INTERNAL 3)
|
mgl@1371
|
11462 |
+ (UNSPEC_STM 4)
|
mgl@1371
|
11463 |
+ (UNSPEC_LDM 5)
|
mgl@1371
|
11464 |
+ (UNSPEC_MOVSICC 6)
|
mgl@1371
|
11465 |
+ (UNSPEC_ADDSICC 7)
|
mgl@1371
|
11466 |
+ (UNSPEC_COND_MI 8)
|
mgl@1371
|
11467 |
+ (UNSPEC_COND_PL 9)
|
mgl@1371
|
11468 |
+ (UNSPEC_PIC_SYM 10)
|
mgl@1371
|
11469 |
+ (UNSPEC_PIC_BASE 11)
|
mgl@1371
|
11470 |
+ (UNSPEC_STORE_MULTIPLE 12)
|
mgl@1371
|
11471 |
+ (UNSPEC_STMFP 13)
|
mgl@1371
|
11472 |
+ (UNSPEC_FPCC_TO_REG 14)
|
mgl@1371
|
11473 |
+ (UNSPEC_REG_TO_CC 15)
|
mgl@1371
|
11474 |
+ (UNSPEC_FORCE_MINIPOOL 16)
|
mgl@1371
|
11475 |
+ (UNSPEC_SATS 17)
|
mgl@1371
|
11476 |
+ (UNSPEC_SATU 18)
|
mgl@1371
|
11477 |
+ (UNSPEC_SATRNDS 19)
|
mgl@1371
|
11478 |
+ (UNSPEC_SATRNDU 20)
|
mgl@1371
|
11479 |
+ ])
|
mgl@1371
|
11480 |
+
|
mgl@1371
|
11481 |
+(define_constants
|
mgl@1371
|
11482 |
+ [(VUNSPEC_EPILOGUE 0)
|
mgl@1371
|
11483 |
+ (VUNSPEC_CACHE 1)
|
mgl@1371
|
11484 |
+ (VUNSPEC_MTSR 2)
|
mgl@1371
|
11485 |
+ (VUNSPEC_MFSR 3)
|
mgl@1371
|
11486 |
+ (VUNSPEC_BLOCKAGE 4)
|
mgl@1371
|
11487 |
+ (VUNSPEC_SYNC 5)
|
mgl@1371
|
11488 |
+ (VUNSPEC_TLBR 6)
|
mgl@1371
|
11489 |
+ (VUNSPEC_TLBW 7)
|
mgl@1371
|
11490 |
+ (VUNSPEC_TLBS 8)
|
mgl@1371
|
11491 |
+ (VUNSPEC_BREAKPOINT 9)
|
mgl@1371
|
11492 |
+ (VUNSPEC_MTDR 10)
|
mgl@1371
|
11493 |
+ (VUNSPEC_MFDR 11)
|
mgl@1371
|
11494 |
+ (VUNSPEC_MVCR 12)
|
mgl@1371
|
11495 |
+ (VUNSPEC_MVRC 13)
|
mgl@1371
|
11496 |
+ (VUNSPEC_COP 14)
|
mgl@1371
|
11497 |
+ (VUNSPEC_ALIGN 15)
|
mgl@1371
|
11498 |
+ (VUNSPEC_POOL_START 16)
|
mgl@1371
|
11499 |
+ (VUNSPEC_POOL_END 17)
|
mgl@1371
|
11500 |
+ (VUNSPEC_POOL_4 18)
|
mgl@1371
|
11501 |
+ (VUNSPEC_POOL_8 19)
|
mgl@1371
|
11502 |
+ (VUNSPEC_POOL_16 20)
|
mgl@1371
|
11503 |
+ (VUNSPEC_MUSFR 21)
|
mgl@1371
|
11504 |
+ (VUNSPEC_MUSTR 22)
|
mgl@1371
|
11505 |
+ (VUNSPEC_SYNC_CMPXCHG 23)
|
mgl@1371
|
11506 |
+ (VUNSPEC_SYNC_SET_LOCK_AND_LOAD 24)
|
mgl@1371
|
11507 |
+ (VUNSPEC_SYNC_STORE_IF_LOCK 25)
|
mgl@1371
|
11508 |
+ (VUNSPEC_EH_RETURN 26)
|
mgl@1371
|
11509 |
+ (VUNSPEC_FRS 27)
|
mgl@1371
|
11510 |
+ (VUNSPEC_CSRF 28)
|
mgl@1371
|
11511 |
+ (VUNSPEC_SSRF 29)
|
mgl@1371
|
11512 |
+ ])
|
mgl@1371
|
11513 |
+
|
mgl@1371
|
11514 |
+(define_constants
|
mgl@1371
|
11515 |
+ [
|
mgl@1371
|
11516 |
+ ;; R7 = 15-7 = 8
|
mgl@1371
|
11517 |
+ (FP_REGNUM 8)
|
mgl@1371
|
11518 |
+ ;; Return Register = R12 = 15 - 12 = 3
|
mgl@1371
|
11519 |
+ (RETVAL_REGNUM 3)
|
mgl@1371
|
11520 |
+ ;; SP = R13 = 15 - 13 = 2
|
mgl@1371
|
11521 |
+ (SP_REGNUM 2)
|
mgl@1371
|
11522 |
+ ;; LR = R14 = 15 - 14 = 1
|
mgl@1371
|
11523 |
+ (LR_REGNUM 1)
|
mgl@1371
|
11524 |
+ ;; PC = R15 = 15 - 15 = 0
|
mgl@1371
|
11525 |
+ (PC_REGNUM 0)
|
mgl@1371
|
11526 |
+ ;; FPSR = GENERAL_REGS + 1 = 17
|
mgl@1371
|
11527 |
+ (FPCC_REGNUM 17)
|
mgl@1371
|
11528 |
+ ])
|
mgl@1371
|
11529 |
+
|
mgl@1371
|
11530 |
+
|
mgl@1371
|
11531 |
+
|
mgl@1371
|
11532 |
+
|
mgl@1371
|
11533 |
+;;******************************************************************************
|
mgl@1371
|
11534 |
+;; Macros
|
mgl@1371
|
11535 |
+;;******************************************************************************
|
mgl@1371
|
11536 |
+
|
mgl@1371
|
11537 |
+;; Integer Modes for basic alu insns
|
mgl@1371
|
11538 |
+(define_mode_macro INTM [SI HI QI])
|
mgl@1371
|
11539 |
+(define_mode_attr alu_cc_attr [(SI "set_vncz") (HI "clobber") (QI "clobber")])
|
mgl@1371
|
11540 |
+
|
mgl@1371
|
11541 |
+;; Move word modes
|
mgl@1371
|
11542 |
+(define_mode_macro MOVM [SI V2HI V4QI])
|
mgl@1371
|
11543 |
+
|
mgl@1371
|
11544 |
+;; For mov/addcc insns
|
mgl@1371
|
11545 |
+(define_mode_macro ADDCC [SI HI QI])
|
mgl@1371
|
11546 |
+(define_mode_macro MOVCC [SF SI HI QI])
|
mgl@1371
|
11547 |
+(define_mode_macro CMP [DI SI HI QI])
|
mgl@1371
|
11548 |
+(define_mode_attr store_postfix [(SF ".w") (SI ".w") (HI ".h") (QI ".b")])
|
mgl@1371
|
11549 |
+(define_mode_attr load_postfix [(SF ".w") (SI ".w") (HI ".sh") (QI ".ub")])
|
mgl@1371
|
11550 |
+(define_mode_attr load_postfix_s [(SI ".w") (HI ".sh") (QI ".sb")])
|
mgl@1371
|
11551 |
+(define_mode_attr load_postfix_u [(SI ".w") (HI ".uh") (QI ".ub")])
|
mgl@1371
|
11552 |
+(define_mode_attr pred_mem_constraint [(SF "RKu11") (SI "RKu11") (HI "RKu10") (QI "RKu09")])
|
mgl@1371
|
11553 |
+(define_mode_attr cmp_constraint [(DI "rKu20") (SI "rKs21") (HI "r") (QI "r")])
|
mgl@1371
|
11554 |
+(define_mode_attr cmp_predicate [(DI "register_immediate_operand")
|
mgl@1371
|
11555 |
+ (SI "register_const_int_operand")
|
mgl@1371
|
11556 |
+ (HI "register_operand")
|
mgl@1371
|
11557 |
+ (QI "register_operand")])
|
mgl@1371
|
11558 |
+(define_mode_attr cmp_length [(DI "6")
|
mgl@1371
|
11559 |
+ (SI "4")
|
mgl@1371
|
11560 |
+ (HI "4")
|
mgl@1371
|
11561 |
+ (QI "4")])
|
mgl@1371
|
11562 |
+
|
mgl@1371
|
11563 |
+;; For all conditional insns
|
mgl@1371
|
11564 |
+(define_code_macro any_cond [eq ne gt ge lt le gtu geu ltu leu])
|
mgl@1371
|
11565 |
+(define_code_attr cond [(eq "eq") (ne "ne") (gt "gt") (ge "ge") (lt "lt") (le "le")
|
mgl@1371
|
11566 |
+ (gtu "hi") (geu "hs") (ltu "lo") (leu "ls")])
|
mgl@1371
|
11567 |
+(define_code_attr invcond [(eq "ne") (ne "eq") (gt "le") (ge "lt") (lt "ge") (le "gt")
|
mgl@1371
|
11568 |
+ (gtu "ls") (geu "lo") (ltu "hs") (leu "hi")])
|
mgl@1371
|
11569 |
+
|
mgl@1371
|
11570 |
+;; For logical operations
|
mgl@1371
|
11571 |
+(define_code_macro logical [and ior xor])
|
mgl@1371
|
11572 |
+(define_code_attr logical_insn [(and "and") (ior "or") (xor "eor")])
|
mgl@1371
|
11573 |
+
|
mgl@1371
|
11574 |
+;; Predicable operations with three register operands
|
mgl@1371
|
11575 |
+(define_code_macro predicable_op3 [and ior xor plus minus])
|
mgl@1371
|
11576 |
+(define_code_attr predicable_insn3 [(and "and") (ior "or") (xor "eor") (plus "add") (minus "sub")])
|
mgl@1371
|
11577 |
+(define_code_attr predicable_commutative3 [(and "%") (ior "%") (xor "%") (plus "%") (minus "")])
|
mgl@1371
|
11578 |
+
|
mgl@1371
|
11579 |
+;; Load the predicates
|
mgl@1371
|
11580 |
+(include "predicates.md")
|
mgl@1371
|
11581 |
+
|
mgl@1371
|
11582 |
+
|
mgl@1371
|
11583 |
+;;******************************************************************************
|
mgl@1371
|
11584 |
+;; Automaton pipeline description for avr32
|
mgl@1371
|
11585 |
+;;******************************************************************************
|
mgl@1371
|
11586 |
+
|
mgl@1371
|
11587 |
+(define_automaton "avr32_ap")
|
mgl@1371
|
11588 |
+
|
mgl@1371
|
11589 |
+
|
mgl@1371
|
11590 |
+(define_cpu_unit "is" "avr32_ap")
|
mgl@1371
|
11591 |
+(define_cpu_unit "a1,m1,da" "avr32_ap")
|
mgl@1371
|
11592 |
+(define_cpu_unit "a2,m2,d" "avr32_ap")
|
mgl@1371
|
11593 |
+
|
mgl@1371
|
11594 |
+;;Alu instructions
|
mgl@1371
|
11595 |
+(define_insn_reservation "alu_op" 1
|
mgl@1371
|
11596 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
11597 |
+ (eq_attr "type" "alu"))
|
mgl@1371
|
11598 |
+ "is,a1,a2")
|
mgl@1371
|
11599 |
+
|
mgl@1371
|
11600 |
+(define_insn_reservation "alu2_op" 2
|
mgl@1371
|
11601 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
11602 |
+ (eq_attr "type" "alu2"))
|
mgl@1371
|
11603 |
+ "is,is+a1,a1+a2,a2")
|
mgl@1371
|
11604 |
+
|
mgl@1371
|
11605 |
+(define_insn_reservation "alu_sat_op" 2
|
mgl@1371
|
11606 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
11607 |
+ (eq_attr "type" "alu_sat"))
|
mgl@1371
|
11608 |
+ "is,a1,a2")
|
mgl@1371
|
11609 |
+
|
mgl@1371
|
11610 |
+
|
mgl@1371
|
11611 |
+;;Mul instructions
|
mgl@1371
|
11612 |
+(define_insn_reservation "mulhh_op" 2
|
mgl@1371
|
11613 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
11614 |
+ (eq_attr "type" "mulhh,mulwh"))
|
mgl@1371
|
11615 |
+ "is,m1,m2")
|
mgl@1371
|
11616 |
+
|
mgl@1371
|
11617 |
+(define_insn_reservation "mulww_w_op" 3
|
mgl@1371
|
11618 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
11619 |
+ (eq_attr "type" "mulww_w"))
|
mgl@1371
|
11620 |
+ "is,m1,m1+m2,m2")
|
mgl@1371
|
11621 |
+
|
mgl@1371
|
11622 |
+(define_insn_reservation "mulww_d_op" 5
|
mgl@1371
|
11623 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
11624 |
+ (eq_attr "type" "mulww_d"))
|
mgl@1371
|
11625 |
+ "is,m1,m1+m2,m1+m2,m2,m2")
|
mgl@1371
|
11626 |
+
|
mgl@1371
|
11627 |
+(define_insn_reservation "div_op" 33
|
mgl@1371
|
11628 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
11629 |
+ (eq_attr "type" "div"))
|
mgl@1371
|
11630 |
+ "is,m1,m1*31 + m2*31,m2")
|
mgl@1371
|
11631 |
+
|
mgl@1371
|
11632 |
+(define_insn_reservation "machh_w_op" 3
|
mgl@1371
|
11633 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
11634 |
+ (eq_attr "type" "machh_w"))
|
mgl@1371
|
11635 |
+ "is*2,m1,m2")
|
mgl@1371
|
11636 |
+
|
mgl@1371
|
11637 |
+
|
mgl@1371
|
11638 |
+(define_insn_reservation "macww_w_op" 4
|
mgl@1371
|
11639 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
11640 |
+ (eq_attr "type" "macww_w"))
|
mgl@1371
|
11641 |
+ "is*2,m1,m1,m2")
|
mgl@1371
|
11642 |
+
|
mgl@1371
|
11643 |
+
|
mgl@1371
|
11644 |
+(define_insn_reservation "macww_d_op" 6
|
mgl@1371
|
11645 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
11646 |
+ (eq_attr "type" "macww_d"))
|
mgl@1371
|
11647 |
+ "is*2,m1,m1+m2,m1+m2,m2")
|
mgl@1371
|
11648 |
+
|
mgl@1371
|
11649 |
+;;Bypasses for Mac instructions, because of accumulator cache.
|
mgl@1371
|
11650 |
+;;Set latency as low as possible in order to let the compiler let
|
mgl@1371
|
11651 |
+;;mul -> mac and mac -> mac combinations which use the same
|
mgl@1371
|
11652 |
+;;accumulator cache be placed close together to avoid any
|
mgl@1371
|
11653 |
+;;instructions which can ruin the accumulator cache come inbetween.
|
mgl@1371
|
11654 |
+(define_bypass 4 "machh_w_op" "alu_op,alu2_op,alu_sat_op,load_op" "avr32_mul_waw_bypass")
|
mgl@1371
|
11655 |
+(define_bypass 5 "macww_w_op" "alu_op,alu2_op,alu_sat_op,load_op" "avr32_mul_waw_bypass")
|
mgl@1371
|
11656 |
+(define_bypass 7 "macww_d_op" "alu_op,alu2_op,alu_sat_op,load_op" "avr32_mul_waw_bypass")
|
mgl@1371
|
11657 |
+
|
mgl@1371
|
11658 |
+(define_bypass 3 "mulhh_op" "alu_op,alu2_op,alu_sat_op,load_op" "avr32_mul_waw_bypass")
|
mgl@1371
|
11659 |
+(define_bypass 4 "mulww_w_op" "alu_op,alu2_op,alu_sat_op,load_op" "avr32_mul_waw_bypass")
|
mgl@1371
|
11660 |
+(define_bypass 6 "mulww_d_op" "alu_op,alu2_op,alu_sat_op,load_op" "avr32_mul_waw_bypass")
|
mgl@1371
|
11661 |
+
|
mgl@1371
|
11662 |
+
|
mgl@1371
|
11663 |
+;;Bypasses for all mul/mac instructions followed by an instruction
|
mgl@1371
|
11664 |
+;;which reads the output AND writes the result to the same register.
|
mgl@1371
|
11665 |
+;;This will generate an Write After Write hazard which gives an
|
mgl@1371
|
11666 |
+;;extra cycle before the result is ready.
|
mgl@1371
|
11667 |
+(define_bypass 0 "machh_w_op" "machh_w_op" "avr32_valid_macmac_bypass")
|
mgl@1371
|
11668 |
+(define_bypass 0 "macww_w_op" "macww_w_op" "avr32_valid_macmac_bypass")
|
mgl@1371
|
11669 |
+(define_bypass 0 "macww_d_op" "macww_d_op" "avr32_valid_macmac_bypass")
|
mgl@1371
|
11670 |
+
|
mgl@1371
|
11671 |
+(define_bypass 0 "mulhh_op" "machh_w_op" "avr32_valid_mulmac_bypass")
|
mgl@1371
|
11672 |
+(define_bypass 0 "mulww_w_op" "macww_w_op" "avr32_valid_mulmac_bypass")
|
mgl@1371
|
11673 |
+(define_bypass 0 "mulww_d_op" "macww_d_op" "avr32_valid_mulmac_bypass")
|
mgl@1371
|
11674 |
+
|
mgl@1371
|
11675 |
+;;Branch and call instructions
|
mgl@1371
|
11676 |
+;;We assume that all branches and rcalls are predicted correctly :-)
|
mgl@1371
|
11677 |
+;;while calls use a lot of cycles.
|
mgl@1371
|
11678 |
+(define_insn_reservation "branch_op" 0
|
mgl@1371
|
11679 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
11680 |
+ (eq_attr "type" "branch"))
|
mgl@1371
|
11681 |
+ "nothing")
|
mgl@1371
|
11682 |
+
|
mgl@1371
|
11683 |
+(define_insn_reservation "call_op" 10
|
mgl@1371
|
11684 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
11685 |
+ (eq_attr "type" "call"))
|
mgl@1371
|
11686 |
+ "nothing")
|
mgl@1371
|
11687 |
+
|
mgl@1371
|
11688 |
+
|
mgl@1371
|
11689 |
+;;Load store instructions
|
mgl@1371
|
11690 |
+(define_insn_reservation "load_op" 2
|
mgl@1371
|
11691 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
11692 |
+ (eq_attr "type" "load"))
|
mgl@1371
|
11693 |
+ "is,da,d")
|
mgl@1371
|
11694 |
+
|
mgl@1371
|
11695 |
+(define_insn_reservation "load_rm_op" 3
|
mgl@1371
|
11696 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
11697 |
+ (eq_attr "type" "load_rm"))
|
mgl@1371
|
11698 |
+ "is,da,d")
|
mgl@1371
|
11699 |
+
|
mgl@1371
|
11700 |
+
|
mgl@1371
|
11701 |
+(define_insn_reservation "store_op" 0
|
mgl@1371
|
11702 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
11703 |
+ (eq_attr "type" "store"))
|
mgl@1371
|
11704 |
+ "is,da,d")
|
mgl@1371
|
11705 |
+
|
mgl@1371
|
11706 |
+
|
mgl@1371
|
11707 |
+(define_insn_reservation "load_double_op" 3
|
mgl@1371
|
11708 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
11709 |
+ (eq_attr "type" "load2"))
|
mgl@1371
|
11710 |
+ "is,da,da+d,d")
|
mgl@1371
|
11711 |
+
|
mgl@1371
|
11712 |
+(define_insn_reservation "load_quad_op" 4
|
mgl@1371
|
11713 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
11714 |
+ (eq_attr "type" "load4"))
|
mgl@1371
|
11715 |
+ "is,da,da+d,da+d,d")
|
mgl@1371
|
11716 |
+
|
mgl@1371
|
11717 |
+(define_insn_reservation "store_double_op" 0
|
mgl@1371
|
11718 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
11719 |
+ (eq_attr "type" "store2"))
|
mgl@1371
|
11720 |
+ "is,da,da+d,d")
|
mgl@1371
|
11721 |
+
|
mgl@1371
|
11722 |
+
|
mgl@1371
|
11723 |
+(define_insn_reservation "store_quad_op" 0
|
mgl@1371
|
11724 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
11725 |
+ (eq_attr "type" "store4"))
|
mgl@1371
|
11726 |
+ "is,da,da+d,da+d,d")
|
mgl@1371
|
11727 |
+
|
mgl@1371
|
11728 |
+;;For store the operand to write to memory is read in d and
|
mgl@1371
|
11729 |
+;;the real latency between any instruction and a store is therefore
|
mgl@1371
|
11730 |
+;;one less than for the instructions which reads the operands in the first
|
mgl@1371
|
11731 |
+;;excecution stage
|
mgl@1371
|
11732 |
+(define_bypass 2 "load_double_op" "store_double_op" "avr32_store_bypass")
|
mgl@1371
|
11733 |
+(define_bypass 3 "load_quad_op" "store_quad_op" "avr32_store_bypass")
|
mgl@1371
|
11734 |
+(define_bypass 1 "load_op" "store_op" "avr32_store_bypass")
|
mgl@1371
|
11735 |
+(define_bypass 2 "load_rm_op" "store_op" "avr32_store_bypass")
|
mgl@1371
|
11736 |
+(define_bypass 1 "alu_sat_op" "store_op" "avr32_store_bypass")
|
mgl@1371
|
11737 |
+(define_bypass 1 "alu2_op" "store_op" "avr32_store_bypass")
|
mgl@1371
|
11738 |
+(define_bypass 1 "mulhh_op" "store_op" "avr32_store_bypass")
|
mgl@1371
|
11739 |
+(define_bypass 2 "mulww_w_op" "store_op" "avr32_store_bypass")
|
mgl@1371
|
11740 |
+(define_bypass 4 "mulww_d_op" "store_op" "avr32_store_bypass" )
|
mgl@1371
|
11741 |
+(define_bypass 2 "machh_w_op" "store_op" "avr32_store_bypass")
|
mgl@1371
|
11742 |
+(define_bypass 3 "macww_w_op" "store_op" "avr32_store_bypass")
|
mgl@1371
|
11743 |
+(define_bypass 5 "macww_d_op" "store_op" "avr32_store_bypass")
|
mgl@1371
|
11744 |
+
|
mgl@1371
|
11745 |
+
|
mgl@1371
|
11746 |
+; Bypass for load double operation. If only the first loaded word is needed
|
mgl@1371
|
11747 |
+; then the latency is 2
|
mgl@1371
|
11748 |
+(define_bypass 2 "load_double_op"
|
mgl@1371
|
11749 |
+ "load_op,load_rm_op,alu_sat_op, alu2_op, alu_op, mulhh_op, mulww_w_op,
|
mgl@1371
|
11750 |
+ mulww_d_op, machh_w_op, macww_w_op, macww_d_op"
|
mgl@1371
|
11751 |
+ "avr32_valid_load_double_bypass")
|
mgl@1371
|
11752 |
+
|
mgl@1371
|
11753 |
+; Bypass for load quad operation. If only the first or second loaded word is needed
|
mgl@1371
|
11754 |
+; we set the latency to 2
|
mgl@1371
|
11755 |
+(define_bypass 2 "load_quad_op"
|
mgl@1371
|
11756 |
+ "load_op,load_rm_op,alu_sat_op, alu2_op, alu_op, mulhh_op, mulww_w_op,
|
mgl@1371
|
11757 |
+ mulww_d_op, machh_w_op, macww_w_op, macww_d_op"
|
mgl@1371
|
11758 |
+ "avr32_valid_load_quad_bypass")
|
mgl@1371
|
11759 |
+
|
mgl@1371
|
11760 |
+
|
mgl@1371
|
11761 |
+;;******************************************************************************
|
mgl@1371
|
11762 |
+;; End of Automaton pipeline description for avr32
|
mgl@1371
|
11763 |
+;;******************************************************************************
|
mgl@1371
|
11764 |
+
|
mgl@1371
|
11765 |
+(define_cond_exec
|
mgl@1371
|
11766 |
+ [(match_operator 0 "avr32_comparison_operator"
|
mgl@1371
|
11767 |
+ [(match_operand:CMP 1 "register_operand" "r")
|
mgl@1371
|
11768 |
+ (match_operand:CMP 2 "<CMP:cmp_predicate>" "<CMP:cmp_constraint>")])]
|
mgl@1371
|
11769 |
+ "TARGET_V2_INSNS"
|
mgl@1371
|
11770 |
+ "%!"
|
mgl@1371
|
11771 |
+)
|
mgl@1371
|
11772 |
+
|
mgl@1371
|
11773 |
+(define_cond_exec
|
mgl@1371
|
11774 |
+ [(match_operator 0 "avr32_comparison_operator"
|
mgl@1371
|
11775 |
+ [(and:SI (match_operand:SI 1 "register_operand" "r")
|
mgl@1371
|
11776 |
+ (match_operand:SI 2 "one_bit_set_operand" "i"))
|
mgl@1371
|
11777 |
+ (const_int 0)])]
|
mgl@1371
|
11778 |
+ "TARGET_V2_INSNS"
|
mgl@1371
|
11779 |
+ "%!"
|
mgl@1371
|
11780 |
+ )
|
mgl@1371
|
11781 |
+
|
mgl@1371
|
11782 |
+;;=============================================================================
|
mgl@1371
|
11783 |
+;; move
|
mgl@1371
|
11784 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
11785 |
+
|
mgl@1371
|
11786 |
+
|
mgl@1371
|
11787 |
+;;== char - 8 bits ============================================================
|
mgl@1371
|
11788 |
+(define_expand "movqi"
|
mgl@1371
|
11789 |
+ [(set (match_operand:QI 0 "nonimmediate_operand" "")
|
mgl@1371
|
11790 |
+ (match_operand:QI 1 "general_operand" ""))]
|
mgl@1371
|
11791 |
+ ""
|
mgl@1371
|
11792 |
+ {
|
mgl@1371
|
11793 |
+ if ( !no_new_pseudos ){
|
mgl@1371
|
11794 |
+ if (GET_CODE (operands[1]) == MEM && optimize){
|
mgl@1371
|
11795 |
+ rtx reg = gen_reg_rtx (SImode);
|
mgl@1371
|
11796 |
+
|
mgl@1371
|
11797 |
+ emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
|
mgl@1371
|
11798 |
+ operands[1] = gen_lowpart (QImode, reg);
|
mgl@1371
|
11799 |
+ }
|
mgl@1371
|
11800 |
+
|
mgl@1371
|
11801 |
+ /* One of the ops has to be in a register. */
|
mgl@1371
|
11802 |
+ if (GET_CODE (operands[0]) == MEM)
|
mgl@1371
|
11803 |
+ operands[1] = force_reg (QImode, operands[1]);
|
mgl@1371
|
11804 |
+ }
|
mgl@1371
|
11805 |
+
|
mgl@1371
|
11806 |
+ })
|
mgl@1371
|
11807 |
+
|
mgl@1371
|
11808 |
+(define_insn "*movqi_internal"
|
mgl@1371
|
11809 |
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m,r")
|
mgl@1371
|
11810 |
+ (match_operand:QI 1 "general_operand" "rKs08,m,r,i"))]
|
mgl@1371
|
11811 |
+ "register_operand (operands[0], QImode)
|
mgl@1371
|
11812 |
+ || register_operand (operands[1], QImode)"
|
mgl@1371
|
11813 |
+ "@
|
mgl@1371
|
11814 |
+ mov\t%0, %1
|
mgl@1371
|
11815 |
+ ld.ub\t%0, %1
|
mgl@1371
|
11816 |
+ st.b\t%0, %1
|
mgl@1371
|
11817 |
+ mov\t%0, %1"
|
mgl@1371
|
11818 |
+ [(set_attr "length" "2,4,4,4")
|
mgl@1371
|
11819 |
+ (set_attr "type" "alu,load_rm,store,alu")])
|
mgl@1371
|
11820 |
+
|
mgl@1371
|
11821 |
+
|
mgl@1371
|
11822 |
+
|
mgl@1371
|
11823 |
+;;== short - 16 bits ==========================================================
|
mgl@1371
|
11824 |
+(define_expand "movhi"
|
mgl@1371
|
11825 |
+ [(set (match_operand:HI 0 "nonimmediate_operand" "")
|
mgl@1371
|
11826 |
+ (match_operand:HI 1 "general_operand" ""))]
|
mgl@1371
|
11827 |
+ ""
|
mgl@1371
|
11828 |
+ {
|
mgl@1371
|
11829 |
+ if ( !no_new_pseudos ){
|
mgl@1371
|
11830 |
+ if (GET_CODE (operands[1]) == MEM && optimize){
|
mgl@1371
|
11831 |
+ rtx reg = gen_reg_rtx (SImode);
|
mgl@1371
|
11832 |
+
|
mgl@1371
|
11833 |
+ emit_insn (gen_extendhisi2 (reg, operands[1]));
|
mgl@1371
|
11834 |
+ operands[1] = gen_lowpart (HImode, reg);
|
mgl@1371
|
11835 |
+ }
|
mgl@1371
|
11836 |
+
|
mgl@1371
|
11837 |
+ /* One of the ops has to be in a register. */
|
mgl@1371
|
11838 |
+ if (GET_CODE (operands[0]) == MEM)
|
mgl@1371
|
11839 |
+ operands[1] = force_reg (HImode, operands[1]);
|
mgl@1371
|
11840 |
+ }
|
mgl@1371
|
11841 |
+
|
mgl@1371
|
11842 |
+ })
|
mgl@1371
|
11843 |
+
|
mgl@1371
|
11844 |
+
|
mgl@1371
|
11845 |
+(define_insn "*movhi_internal"
|
mgl@1371
|
11846 |
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
|
mgl@1371
|
11847 |
+ (match_operand:HI 1 "general_operand" "rKs08,m,r,i"))]
|
mgl@1371
|
11848 |
+ "register_operand (operands[0], HImode)
|
mgl@1371
|
11849 |
+ || register_operand (operands[1], HImode)"
|
mgl@1371
|
11850 |
+ "@
|
mgl@1371
|
11851 |
+ mov\t%0, %1
|
mgl@1371
|
11852 |
+ ld.sh\t%0, %1
|
mgl@1371
|
11853 |
+ st.h\t%0, %1
|
mgl@1371
|
11854 |
+ mov\t%0, %1"
|
mgl@1371
|
11855 |
+ [(set_attr "length" "2,4,4,4")
|
mgl@1371
|
11856 |
+ (set_attr "type" "alu,load_rm,store,alu")])
|
mgl@1371
|
11857 |
+
|
mgl@1371
|
11858 |
+
|
mgl@1371
|
11859 |
+;;== int - 32 bits ============================================================
|
mgl@1371
|
11860 |
+
|
mgl@1371
|
11861 |
+(define_expand "movmisalignsi"
|
mgl@1371
|
11862 |
+ [(set (match_operand:SI 0 "nonimmediate_operand" "")
|
mgl@1371
|
11863 |
+ (match_operand:SI 1 "nonimmediate_operand" ""))]
|
mgl@1371
|
11864 |
+ "TARGET_UNALIGNED_WORD"
|
mgl@1371
|
11865 |
+ {
|
mgl@1371
|
11866 |
+ }
|
mgl@1371
|
11867 |
+)
|
mgl@1371
|
11868 |
+
|
mgl@1371
|
11869 |
+
|
mgl@1371
|
11870 |
+(define_expand "mov<mode>"
|
mgl@1371
|
11871 |
+ [(set (match_operand:MOVM 0 "avr32_non_rmw_nonimmediate_operand" "")
|
mgl@1371
|
11872 |
+ (match_operand:MOVM 1 "avr32_non_rmw_general_operand" ""))]
|
mgl@1371
|
11873 |
+ ""
|
mgl@1371
|
11874 |
+ {
|
mgl@1371
|
11875 |
+
|
mgl@1371
|
11876 |
+ /* One of the ops has to be in a register. */
|
mgl@1371
|
11877 |
+ if (GET_CODE (operands[0]) == MEM)
|
mgl@1371
|
11878 |
+ operands[1] = force_reg (<MODE>mode, operands[1]);
|
mgl@1371
|
11879 |
+
|
mgl@1371
|
11880 |
+
|
mgl@1371
|
11881 |
+ /* Check for out of range immediate constants as these may
|
mgl@1371
|
11882 |
+ occur during reloading, since it seems like reload does
|
mgl@1371
|
11883 |
+ not check if the immediate is legitimate. Don't know if
|
mgl@1371
|
11884 |
+ this is a bug? */
|
mgl@1371
|
11885 |
+ if ( reload_in_progress
|
mgl@1371
|
11886 |
+ && avr32_imm_in_const_pool
|
mgl@1371
|
11887 |
+ && GET_CODE(operands[1]) == CONST_INT
|
mgl@1371
|
11888 |
+ && !avr32_const_ok_for_constraint_p(INTVAL(operands[1]), 'K', "Ks21") ){
|
mgl@1371
|
11889 |
+ operands[1] = force_const_mem(SImode, operands[1]);
|
mgl@1371
|
11890 |
+ }
|
mgl@1371
|
11891 |
+
|
mgl@1371
|
11892 |
+ /* Check for RMW memory operands. They are not allowed for mov operations
|
mgl@1371
|
11893 |
+ only the atomic memc/s/t operations */
|
mgl@1371
|
11894 |
+ if ( !reload_in_progress
|
mgl@1371
|
11895 |
+ && avr32_rmw_memory_operand (operands[0], <MODE>mode) ){
|
mgl@1371
|
11896 |
+ operands[0] = copy_rtx (operands[0]);
|
mgl@1371
|
11897 |
+ XEXP(operands[0], 0) = force_reg (<MODE>mode, XEXP(operands[0], 0));
|
mgl@1371
|
11898 |
+ }
|
mgl@1371
|
11899 |
+
|
mgl@1371
|
11900 |
+ if ( !reload_in_progress
|
mgl@1371
|
11901 |
+ && avr32_rmw_memory_operand (operands[1], <MODE>mode) ){
|
mgl@1371
|
11902 |
+ operands[1] = copy_rtx (operands[1]);
|
mgl@1371
|
11903 |
+ XEXP(operands[1], 0) = force_reg (<MODE>mode, XEXP(operands[1], 0));
|
mgl@1371
|
11904 |
+ }
|
mgl@1371
|
11905 |
+
|
mgl@1371
|
11906 |
+ if ( (flag_pic || TARGET_HAS_ASM_ADDR_PSEUDOS)
|
mgl@1371
|
11907 |
+ && !avr32_legitimate_pic_operand_p(operands[1]) )
|
mgl@1371
|
11908 |
+ operands[1] = legitimize_pic_address (operands[1], <MODE>mode,
|
mgl@1371
|
11909 |
+ (no_new_pseudos ? operands[0] : 0));
|
mgl@1371
|
11910 |
+ else if ( flag_pic && avr32_address_operand(operands[1], GET_MODE(operands[1])) )
|
mgl@1371
|
11911 |
+ /* If we have an address operand then this function uses the pic register. */
|
mgl@1371
|
11912 |
+ current_function_uses_pic_offset_table = 1;
|
mgl@1371
|
11913 |
+ })
|
mgl@1371
|
11914 |
+
|
mgl@1371
|
11915 |
+
|
mgl@1371
|
11916 |
+
|
mgl@1371
|
11917 |
+(define_insn "mov<mode>_internal"
|
mgl@1371
|
11918 |
+ [(set (match_operand:MOVM 0 "avr32_non_rmw_nonimmediate_operand" "=r, r, r,r,r,Q,r")
|
mgl@1371
|
11919 |
+ (match_operand:MOVM 1 "avr32_non_rmw_general_operand" "rKs08,Ks21,J,n,Q,r,W"))]
|
mgl@1371
|
11920 |
+ "(register_operand (operands[0], <MODE>mode)
|
mgl@1371
|
11921 |
+ || register_operand (operands[1], <MODE>mode))
|
mgl@1371
|
11922 |
+ && !avr32_rmw_memory_operand (operands[0], <MODE>mode)
|
mgl@1371
|
11923 |
+ && !avr32_rmw_memory_operand (operands[1], <MODE>mode)"
|
mgl@1371
|
11924 |
+ {
|
mgl@1371
|
11925 |
+ switch (which_alternative) {
|
mgl@1371
|
11926 |
+ case 0:
|
mgl@1371
|
11927 |
+ case 1: return "mov\t%0, %1";
|
mgl@1371
|
11928 |
+ case 2:
|
mgl@1371
|
11929 |
+ if ( TARGET_V2_INSNS )
|
mgl@1371
|
11930 |
+ return "movh\t%0, hi(%1)";
|
mgl@1371
|
11931 |
+ /* Fallthrough */
|
mgl@1371
|
11932 |
+ case 3: return "mov\t%0, lo(%1)\;orh\t%0,hi(%1)";
|
mgl@1371
|
11933 |
+ case 4:
|
mgl@1371
|
11934 |
+ if ( (REG_P(XEXP(operands[1], 0))
|
mgl@1371
|
11935 |
+ && REGNO(XEXP(operands[1], 0)) == SP_REGNUM)
|
mgl@1371
|
11936 |
+ || (GET_CODE(XEXP(operands[1], 0)) == PLUS
|
mgl@1371
|
11937 |
+ && REGNO(XEXP(XEXP(operands[1], 0), 0)) == SP_REGNUM
|
mgl@1371
|
11938 |
+ && GET_CODE(XEXP(XEXP(operands[1], 0), 1)) == CONST_INT
|
mgl@1371
|
11939 |
+ && INTVAL(XEXP(XEXP(operands[1], 0), 1)) % 4 == 0
|
mgl@1371
|
11940 |
+ && INTVAL(XEXP(XEXP(operands[1], 0), 1)) <= 0x1FC) )
|
mgl@1371
|
11941 |
+ return "lddsp\t%0, %1";
|
mgl@1371
|
11942 |
+ else if ( avr32_const_pool_ref_operand(operands[1], GET_MODE(operands[1])) )
|
mgl@1371
|
11943 |
+ return "lddpc\t%0, %1";
|
mgl@1371
|
11944 |
+ else
|
mgl@1371
|
11945 |
+ return "ld.w\t%0, %1";
|
mgl@1371
|
11946 |
+ case 5:
|
mgl@1371
|
11947 |
+ if ( (REG_P(XEXP(operands[0], 0))
|
mgl@1371
|
11948 |
+ && REGNO(XEXP(operands[0], 0)) == SP_REGNUM)
|
mgl@1371
|
11949 |
+ || (GET_CODE(XEXP(operands[0], 0)) == PLUS
|
mgl@1371
|
11950 |
+ && REGNO(XEXP(XEXP(operands[0], 0), 0)) == SP_REGNUM
|
mgl@1371
|
11951 |
+ && GET_CODE(XEXP(XEXP(operands[0], 0), 1)) == CONST_INT
|
mgl@1371
|
11952 |
+ && INTVAL(XEXP(XEXP(operands[0], 0), 1)) % 4 == 0
|
mgl@1371
|
11953 |
+ && INTVAL(XEXP(XEXP(operands[0], 0), 1)) <= 0x1FC) )
|
mgl@1371
|
11954 |
+ return "stdsp\t%0, %1";
|
mgl@1371
|
11955 |
+ else
|
mgl@1371
|
11956 |
+ return "st.w\t%0, %1";
|
mgl@1371
|
11957 |
+ case 6:
|
mgl@1371
|
11958 |
+ if ( TARGET_HAS_ASM_ADDR_PSEUDOS )
|
mgl@1371
|
11959 |
+ return "lda.w\t%0, %1";
|
mgl@1371
|
11960 |
+ else
|
mgl@1371
|
11961 |
+ return "ld.w\t%0, r6[%1@got]";
|
mgl@1371
|
11962 |
+ default:
|
mgl@1371
|
11963 |
+ abort();
|
mgl@1371
|
11964 |
+ }
|
mgl@1371
|
11965 |
+ }
|
mgl@1371
|
11966 |
+
|
mgl@1371
|
11967 |
+ [(set_attr "length" "2,4,4,8,4,4,8")
|
mgl@1371
|
11968 |
+ (set_attr "type" "alu,alu,alu,alu2,load,store,load")
|
mgl@1371
|
11969 |
+ (set_attr "cc" "none,none,set_z_if_not_v2,set_z,none,none,clobber")])
|
mgl@1371
|
11970 |
+
|
mgl@1371
|
11971 |
+
|
mgl@1371
|
11972 |
+(define_expand "reload_out_rmw_memory_operand"
|
mgl@1371
|
11973 |
+ [(set (match_operand:SI 2 "register_operand" "=r")
|
mgl@1371
|
11974 |
+ (match_operand:SI 0 "address_operand" ""))
|
mgl@1371
|
11975 |
+ (set (mem:SI (match_dup 2))
|
mgl@1371
|
11976 |
+ (match_operand:SI 1 "register_operand" ""))]
|
mgl@1371
|
11977 |
+ ""
|
mgl@1371
|
11978 |
+ {
|
mgl@1371
|
11979 |
+ operands[0] = XEXP(operands[0], 0);
|
mgl@1371
|
11980 |
+ }
|
mgl@1371
|
11981 |
+)
|
mgl@1371
|
11982 |
+
|
mgl@1371
|
11983 |
+(define_expand "reload_in_rmw_memory_operand"
|
mgl@1371
|
11984 |
+ [(set (match_operand:SI 2 "register_operand" "=r")
|
mgl@1371
|
11985 |
+ (match_operand:SI 1 "address_operand" ""))
|
mgl@1371
|
11986 |
+ (set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
11987 |
+ (mem:SI (match_dup 2)))]
|
mgl@1371
|
11988 |
+ ""
|
mgl@1371
|
11989 |
+ {
|
mgl@1371
|
11990 |
+ operands[1] = XEXP(operands[1], 0);
|
mgl@1371
|
11991 |
+ }
|
mgl@1371
|
11992 |
+)
|
mgl@1371
|
11993 |
+
|
mgl@1371
|
11994 |
+
|
mgl@1371
|
11995 |
+;; These instructions are for loading constants which cannot be loaded
|
mgl@1371
|
11996 |
+;; directly from the constant pool because the offset is too large
|
mgl@1371
|
11997 |
+;; high and lo_sum are used even tough for our case it should be
|
mgl@1371
|
11998 |
+;; low and high sum :-)
|
mgl@1371
|
11999 |
+(define_insn "mov_symbol_lo"
|
mgl@1371
|
12000 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
12001 |
+ (high:SI (match_operand:SI 1 "immediate_operand" "i" )))]
|
mgl@1371
|
12002 |
+ ""
|
mgl@1371
|
12003 |
+ "mov\t%0, lo(%1)"
|
mgl@1371
|
12004 |
+ [(set_attr "type" "alu")
|
mgl@1371
|
12005 |
+ (set_attr "length" "4")]
|
mgl@1371
|
12006 |
+)
|
mgl@1371
|
12007 |
+
|
mgl@1371
|
12008 |
+(define_insn "add_symbol_hi"
|
mgl@1371
|
12009 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
12010 |
+ (lo_sum:SI (match_dup 0)
|
mgl@1371
|
12011 |
+ (match_operand:SI 1 "immediate_operand" "i" )))]
|
mgl@1371
|
12012 |
+ ""
|
mgl@1371
|
12013 |
+ "orh\t%0, hi(%1)"
|
mgl@1371
|
12014 |
+ [(set_attr "type" "alu")
|
mgl@1371
|
12015 |
+ (set_attr "length" "4")]
|
mgl@1371
|
12016 |
+)
|
mgl@1371
|
12017 |
+
|
mgl@1371
|
12018 |
+
|
mgl@1371
|
12019 |
+
|
mgl@1371
|
12020 |
+;; When generating pic, we need to load the symbol offset into a register.
|
mgl@1371
|
12021 |
+;; So that the optimizer does not confuse this with a normal symbol load
|
mgl@1371
|
12022 |
+;; we use an unspec. The offset will be loaded from a constant pool entry,
|
mgl@1371
|
12023 |
+;; since that is the only type of relocation we can use.
|
mgl@1371
|
12024 |
+(define_insn "pic_load_addr"
|
mgl@1371
|
12025 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
12026 |
+ (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PIC_SYM))]
|
mgl@1371
|
12027 |
+ "flag_pic && CONSTANT_POOL_ADDRESS_P(XEXP(operands[1], 0))"
|
mgl@1371
|
12028 |
+ "lddpc\t%0, %1"
|
mgl@1371
|
12029 |
+ [(set_attr "type" "load")
|
mgl@1371
|
12030 |
+ (set_attr "length" "4")]
|
mgl@1371
|
12031 |
+)
|
mgl@1371
|
12032 |
+
|
mgl@1371
|
12033 |
+(define_insn "pic_compute_got_from_pc"
|
mgl@1371
|
12034 |
+ [(set (match_operand:SI 0 "register_operand" "+r")
|
mgl@1371
|
12035 |
+ (unspec:SI [(minus:SI (pc)
|
mgl@1371
|
12036 |
+ (match_dup 0))] UNSPEC_PIC_BASE))
|
mgl@1371
|
12037 |
+ (use (label_ref (match_operand 1 "" "")))]
|
mgl@1371
|
12038 |
+ "flag_pic"
|
mgl@1371
|
12039 |
+ {
|
mgl@1371
|
12040 |
+ (*targetm.asm_out.internal_label) (asm_out_file, "L",
|
mgl@1371
|
12041 |
+ CODE_LABEL_NUMBER (operands[1]));
|
mgl@1371
|
12042 |
+ return \"rsub\t%0, pc\";
|
mgl@1371
|
12043 |
+ }
|
mgl@1371
|
12044 |
+ [(set_attr "cc" "clobber")
|
mgl@1371
|
12045 |
+ (set_attr "length" "2")]
|
mgl@1371
|
12046 |
+)
|
mgl@1371
|
12047 |
+
|
mgl@1371
|
12048 |
+;;== long long int - 64 bits ==================================================
|
mgl@1371
|
12049 |
+
|
mgl@1371
|
12050 |
+(define_expand "movdi"
|
mgl@1371
|
12051 |
+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
|
mgl@1371
|
12052 |
+ (match_operand:DI 1 "general_operand" ""))]
|
mgl@1371
|
12053 |
+ ""
|
mgl@1371
|
12054 |
+ {
|
mgl@1371
|
12055 |
+
|
mgl@1371
|
12056 |
+ /* One of the ops has to be in a register. */
|
mgl@1371
|
12057 |
+ if (GET_CODE (operands[0]) != REG)
|
mgl@1371
|
12058 |
+ operands[1] = force_reg (DImode, operands[1]);
|
mgl@1371
|
12059 |
+
|
mgl@1371
|
12060 |
+ })
|
mgl@1371
|
12061 |
+
|
mgl@1371
|
12062 |
+
|
mgl@1371
|
12063 |
+(define_insn_and_split "*movdi_internal"
|
mgl@1371
|
12064 |
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r, r, r,r,r,m")
|
mgl@1371
|
12065 |
+ (match_operand:DI 1 "general_operand" "r, Ks08,Ks21,G,n,m,r"))]
|
mgl@1371
|
12066 |
+ "register_operand (operands[0], DImode)
|
mgl@1371
|
12067 |
+ || register_operand (operands[1], DImode)"
|
mgl@1371
|
12068 |
+ {
|
mgl@1371
|
12069 |
+ switch (which_alternative ){
|
mgl@1371
|
12070 |
+ case 0:
|
mgl@1371
|
12071 |
+ case 1:
|
mgl@1371
|
12072 |
+ case 2:
|
mgl@1371
|
12073 |
+ case 3:
|
mgl@1371
|
12074 |
+ case 4:
|
mgl@1371
|
12075 |
+ return "#";
|
mgl@1371
|
12076 |
+ case 5:
|
mgl@1371
|
12077 |
+ if ( avr32_const_pool_ref_operand(operands[1], GET_MODE(operands[1])))
|
mgl@1371
|
12078 |
+ return "ld.d\t%0, pc[%1 - .]";
|
mgl@1371
|
12079 |
+ else
|
mgl@1371
|
12080 |
+ return "ld.d\t%0, %1";
|
mgl@1371
|
12081 |
+ case 6:
|
mgl@1371
|
12082 |
+ return "st.d\t%0, %1";
|
mgl@1371
|
12083 |
+ default:
|
mgl@1371
|
12084 |
+ abort();
|
mgl@1371
|
12085 |
+ }
|
mgl@1371
|
12086 |
+ }
|
mgl@1371
|
12087 |
+;; Lets split all reg->reg or imm->reg transfers into two SImode transfers
|
mgl@1371
|
12088 |
+ "reload_completed &&
|
mgl@1371
|
12089 |
+ (REG_P (operands[0]) &&
|
mgl@1371
|
12090 |
+ (REG_P (operands[1])
|
mgl@1371
|
12091 |
+ || GET_CODE (operands[1]) == CONST_INT
|
mgl@1371
|
12092 |
+ || GET_CODE (operands[1]) == CONST_DOUBLE))"
|
mgl@1371
|
12093 |
+ [(set (match_dup 0) (match_dup 1))
|
mgl@1371
|
12094 |
+ (set (match_dup 2) (match_dup 3))]
|
mgl@1371
|
12095 |
+ {
|
mgl@1371
|
12096 |
+ operands[2] = gen_highpart (SImode, operands[0]);
|
mgl@1371
|
12097 |
+ operands[0] = gen_lowpart (SImode, operands[0]);
|
mgl@1371
|
12098 |
+ if ( REG_P(operands[1]) ){
|
mgl@1371
|
12099 |
+ operands[3] = gen_highpart(SImode, operands[1]);
|
mgl@1371
|
12100 |
+ operands[1] = gen_lowpart(SImode, operands[1]);
|
mgl@1371
|
12101 |
+ } else if ( GET_CODE(operands[1]) == CONST_DOUBLE
|
mgl@1371
|
12102 |
+ || GET_CODE(operands[1]) == CONST_INT ){
|
mgl@1371
|
12103 |
+ rtx split_const[2];
|
mgl@1371
|
12104 |
+ avr32_split_const_expr (DImode, SImode, operands[1], split_const);
|
mgl@1371
|
12105 |
+ operands[3] = split_const[1];
|
mgl@1371
|
12106 |
+ operands[1] = split_const[0];
|
mgl@1371
|
12107 |
+ } else {
|
mgl@1371
|
12108 |
+ internal_error("Illegal operand[1] for movdi split!");
|
mgl@1371
|
12109 |
+ }
|
mgl@1371
|
12110 |
+ }
|
mgl@1371
|
12111 |
+
|
mgl@1371
|
12112 |
+ [(set_attr "length" "*,*,*,*,*,4,4")
|
mgl@1371
|
12113 |
+ (set_attr "type" "*,*,*,*,*,load2,store2")
|
mgl@1371
|
12114 |
+ (set_attr "cc" "*,*,*,*,*,none,none")])
|
mgl@1371
|
12115 |
+
|
mgl@1371
|
12116 |
+
|
mgl@1371
|
12117 |
+;;== 128 bits ==================================================
|
mgl@1371
|
12118 |
+(define_expand "movti"
|
mgl@1371
|
12119 |
+ [(set (match_operand:TI 0 "nonimmediate_operand" "")
|
mgl@1371
|
12120 |
+ (match_operand:TI 1 "nonimmediate_operand" ""))]
|
mgl@1371
|
12121 |
+ "TARGET_ARCH_AP"
|
mgl@1371
|
12122 |
+ {
|
mgl@1371
|
12123 |
+
|
mgl@1371
|
12124 |
+ /* One of the ops has to be in a register. */
|
mgl@1371
|
12125 |
+ if (GET_CODE (operands[0]) != REG)
|
mgl@1371
|
12126 |
+ operands[1] = force_reg (TImode, operands[1]);
|
mgl@1371
|
12127 |
+
|
mgl@1371
|
12128 |
+ /* We must fix any pre_dec for loads and post_inc stores */
|
mgl@1371
|
12129 |
+ if ( GET_CODE (operands[0]) == MEM
|
mgl@1371
|
12130 |
+ && GET_CODE (XEXP(operands[0],0)) == POST_INC ){
|
mgl@1371
|
12131 |
+ emit_move_insn(gen_rtx_MEM(TImode, XEXP(XEXP(operands[0],0),0)), operands[1]);
|
mgl@1371
|
12132 |
+ emit_insn(gen_addsi3(XEXP(XEXP(operands[0],0),0), XEXP(XEXP(operands[0],0),0), GEN_INT(GET_MODE_SIZE(TImode))));
|
mgl@1371
|
12133 |
+ DONE;
|
mgl@1371
|
12134 |
+ }
|
mgl@1371
|
12135 |
+
|
mgl@1371
|
12136 |
+ if ( GET_CODE (operands[1]) == MEM
|
mgl@1371
|
12137 |
+ && GET_CODE (XEXP(operands[1],0)) == PRE_DEC ){
|
mgl@1371
|
12138 |
+ emit_insn(gen_addsi3(XEXP(XEXP(operands[1],0),0), XEXP(XEXP(operands[1],0),0), GEN_INT(-GET_MODE_SIZE(TImode))));
|
mgl@1371
|
12139 |
+ emit_move_insn(operands[0], gen_rtx_MEM(TImode, XEXP(XEXP(operands[1],0),0)));
|
mgl@1371
|
12140 |
+ DONE;
|
mgl@1371
|
12141 |
+ }
|
mgl@1371
|
12142 |
+ })
|
mgl@1371
|
12143 |
+
|
mgl@1371
|
12144 |
+
|
mgl@1371
|
12145 |
+(define_insn_and_split "*movti_internal"
|
mgl@1371
|
12146 |
+ [(set (match_operand:TI 0 "avr32_movti_dst_operand" "=r,&r, r, <RKu00,r,r")
|
mgl@1371
|
12147 |
+ (match_operand:TI 1 "avr32_movti_src_operand" " r,RKu00>,RKu00,r, n,T"))]
|
mgl@1371
|
12148 |
+ "(register_operand (operands[0], TImode)
|
mgl@1371
|
12149 |
+ || register_operand (operands[1], TImode))"
|
mgl@1371
|
12150 |
+ {
|
mgl@1371
|
12151 |
+ switch (which_alternative ){
|
mgl@1371
|
12152 |
+ case 0:
|
mgl@1371
|
12153 |
+ case 2:
|
mgl@1371
|
12154 |
+ case 4:
|
mgl@1371
|
12155 |
+ return "#";
|
mgl@1371
|
12156 |
+ case 1:
|
mgl@1371
|
12157 |
+ return "ldm\t%p1, %0";
|
mgl@1371
|
12158 |
+ case 3:
|
mgl@1371
|
12159 |
+ return "stm\t%p0, %1";
|
mgl@1371
|
12160 |
+ case 5:
|
mgl@1371
|
12161 |
+ return "ld.d\t%U0, pc[%1 - .]\;ld.d\t%B0, pc[%1 - . + 8]";
|
mgl@1371
|
12162 |
+ }
|
mgl@1371
|
12163 |
+ }
|
mgl@1371
|
12164 |
+
|
mgl@1371
|
12165 |
+ "reload_completed &&
|
mgl@1371
|
12166 |
+ (REG_P (operands[0]) &&
|
mgl@1371
|
12167 |
+ (REG_P (operands[1])
|
mgl@1371
|
12168 |
+ /* If this is a load from the constant pool we split it into
|
mgl@1371
|
12169 |
+ two double loads. */
|
mgl@1371
|
12170 |
+ || (GET_CODE (operands[1]) == MEM
|
mgl@1371
|
12171 |
+ && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
|
mgl@1371
|
12172 |
+ && CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0)))
|
mgl@1371
|
12173 |
+ /* If this is a load where the pointer register is a part
|
mgl@1371
|
12174 |
+ of the register list, we must split it into two double
|
mgl@1371
|
12175 |
+ loads in order for it to be exception safe. */
|
mgl@1371
|
12176 |
+ || (GET_CODE (operands[1]) == MEM
|
mgl@1371
|
12177 |
+ && register_operand (XEXP (operands[1], 0), SImode)
|
mgl@1371
|
12178 |
+ && reg_overlap_mentioned_p (operands[0], XEXP (operands[1], 0)))
|
mgl@1371
|
12179 |
+ || GET_CODE (operands[1]) == CONST_INT
|
mgl@1371
|
12180 |
+ || GET_CODE (operands[1]) == CONST_DOUBLE))"
|
mgl@1371
|
12181 |
+ [(set (match_dup 0) (match_dup 1))
|
mgl@1371
|
12182 |
+ (set (match_dup 2) (match_dup 3))]
|
mgl@1371
|
12183 |
+ {
|
mgl@1371
|
12184 |
+ operands[2] = simplify_gen_subreg ( DImode, operands[0],
|
mgl@1371
|
12185 |
+ TImode, 0 );
|
mgl@1371
|
12186 |
+ operands[0] = simplify_gen_subreg ( DImode, operands[0],
|
mgl@1371
|
12187 |
+ TImode, 8 );
|
mgl@1371
|
12188 |
+ if ( REG_P(operands[1]) ){
|
mgl@1371
|
12189 |
+ operands[3] = simplify_gen_subreg ( DImode, operands[1],
|
mgl@1371
|
12190 |
+ TImode, 0 );
|
mgl@1371
|
12191 |
+ operands[1] = simplify_gen_subreg ( DImode, operands[1],
|
mgl@1371
|
12192 |
+ TImode, 8 );
|
mgl@1371
|
12193 |
+ } else if ( GET_CODE(operands[1]) == CONST_DOUBLE
|
mgl@1371
|
12194 |
+ || GET_CODE(operands[1]) == CONST_INT ){
|
mgl@1371
|
12195 |
+ rtx split_const[2];
|
mgl@1371
|
12196 |
+ avr32_split_const_expr (TImode, DImode, operands[1], split_const);
|
mgl@1371
|
12197 |
+ operands[3] = split_const[1];
|
mgl@1371
|
12198 |
+ operands[1] = split_const[0];
|
mgl@1371
|
12199 |
+ } else if (avr32_const_pool_ref_operand (operands[1], GET_MODE(operands[1]))){
|
mgl@1371
|
12200 |
+ rtx split_const[2];
|
mgl@1371
|
12201 |
+ rtx cop = avoid_constant_pool_reference (operands[1]);
|
mgl@1371
|
12202 |
+ if (operands[1] == cop)
|
mgl@1371
|
12203 |
+ cop = get_pool_constant (XEXP (operands[1], 0));
|
mgl@1371
|
12204 |
+ avr32_split_const_expr (TImode, DImode, cop, split_const);
|
mgl@1371
|
12205 |
+ operands[3] = force_const_mem (DImode, split_const[1]);
|
mgl@1371
|
12206 |
+ operands[1] = force_const_mem (DImode, split_const[0]);
|
mgl@1371
|
12207 |
+ } else {
|
mgl@1371
|
12208 |
+ rtx ptr_reg = XEXP (operands[1], 0);
|
mgl@1371
|
12209 |
+ operands[1] = gen_rtx_MEM (DImode,
|
mgl@1371
|
12210 |
+ gen_rtx_PLUS ( SImode,
|
mgl@1371
|
12211 |
+ ptr_reg,
|
mgl@1371
|
12212 |
+ GEN_INT (8) ));
|
mgl@1371
|
12213 |
+ operands[3] = gen_rtx_MEM (DImode,
|
mgl@1371
|
12214 |
+ ptr_reg);
|
mgl@1371
|
12215 |
+
|
mgl@1371
|
12216 |
+ /* Check if the first load will clobber the pointer.
|
mgl@1371
|
12217 |
+ If so, we must switch the order of the operations. */
|
mgl@1371
|
12218 |
+ if ( reg_overlap_mentioned_p (operands[0], ptr_reg) )
|
mgl@1371
|
12219 |
+ {
|
mgl@1371
|
12220 |
+ /* We need to switch the order of the operations
|
mgl@1371
|
12221 |
+ so that the pointer register does not get clobbered
|
mgl@1371
|
12222 |
+ after the first double word load. */
|
mgl@1371
|
12223 |
+ rtx tmp;
|
mgl@1371
|
12224 |
+ tmp = operands[0];
|
mgl@1371
|
12225 |
+ operands[0] = operands[2];
|
mgl@1371
|
12226 |
+ operands[2] = tmp;
|
mgl@1371
|
12227 |
+ tmp = operands[1];
|
mgl@1371
|
12228 |
+ operands[1] = operands[3];
|
mgl@1371
|
12229 |
+ operands[3] = tmp;
|
mgl@1371
|
12230 |
+ }
|
mgl@1371
|
12231 |
+
|
mgl@1371
|
12232 |
+
|
mgl@1371
|
12233 |
+ }
|
mgl@1371
|
12234 |
+ }
|
mgl@1371
|
12235 |
+ [(set_attr "length" "*,*,4,4,*,8")
|
mgl@1371
|
12236 |
+ (set_attr "type" "*,*,load4,store4,*,load4")])
|
mgl@1371
|
12237 |
+
|
mgl@1371
|
12238 |
+
|
mgl@1371
|
12239 |
+;;== float - 32 bits ==========================================================
|
mgl@1371
|
12240 |
+(define_expand "movsf"
|
mgl@1371
|
12241 |
+ [(set (match_operand:SF 0 "nonimmediate_operand" "")
|
mgl@1371
|
12242 |
+ (match_operand:SF 1 "general_operand" ""))]
|
mgl@1371
|
12243 |
+ ""
|
mgl@1371
|
12244 |
+ {
|
mgl@1371
|
12245 |
+
|
mgl@1371
|
12246 |
+
|
mgl@1371
|
12247 |
+ /* One of the ops has to be in a register. */
|
mgl@1371
|
12248 |
+ if (GET_CODE (operands[0]) != REG)
|
mgl@1371
|
12249 |
+ operands[1] = force_reg (SFmode, operands[1]);
|
mgl@1371
|
12250 |
+
|
mgl@1371
|
12251 |
+ })
|
mgl@1371
|
12252 |
+
|
mgl@1371
|
12253 |
+(define_insn "*movsf_internal"
|
mgl@1371
|
12254 |
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r,r,m")
|
mgl@1371
|
12255 |
+ (match_operand:SF 1 "general_operand" "r, G,F,m,r"))]
|
mgl@1371
|
12256 |
+ "(register_operand (operands[0], SFmode)
|
mgl@1371
|
12257 |
+ || register_operand (operands[1], SFmode))"
|
mgl@1371
|
12258 |
+ {
|
mgl@1371
|
12259 |
+ switch (which_alternative) {
|
mgl@1371
|
12260 |
+ case 0:
|
mgl@1371
|
12261 |
+ case 1: return "mov\t%0, %1";
|
mgl@1371
|
12262 |
+ case 2:
|
mgl@1371
|
12263 |
+ {
|
mgl@1371
|
12264 |
+ HOST_WIDE_INT target_float[2];
|
mgl@1371
|
12265 |
+ real_to_target (target_float, CONST_DOUBLE_REAL_VALUE (operands[1]), SFmode);
|
mgl@1371
|
12266 |
+ if ( TARGET_V2_INSNS
|
mgl@1371
|
12267 |
+ && avr32_hi16_immediate_operand (GEN_INT (target_float[0]), VOIDmode) )
|
mgl@1371
|
12268 |
+ return "movh\t%0, hi(%1)";
|
mgl@1371
|
12269 |
+ else
|
mgl@1371
|
12270 |
+ return "mov\t%0, lo(%1)\;orh\t%0, hi(%1)";
|
mgl@1371
|
12271 |
+ }
|
mgl@1371
|
12272 |
+ case 3:
|
mgl@1371
|
12273 |
+ if ( (REG_P(XEXP(operands[1], 0))
|
mgl@1371
|
12274 |
+ && REGNO(XEXP(operands[1], 0)) == SP_REGNUM)
|
mgl@1371
|
12275 |
+ || (GET_CODE(XEXP(operands[1], 0)) == PLUS
|
mgl@1371
|
12276 |
+ && REGNO(XEXP(XEXP(operands[1], 0), 0)) == SP_REGNUM
|
mgl@1371
|
12277 |
+ && GET_CODE(XEXP(XEXP(operands[1], 0), 1)) == CONST_INT
|
mgl@1371
|
12278 |
+ && INTVAL(XEXP(XEXP(operands[1], 0), 1)) % 4 == 0
|
mgl@1371
|
12279 |
+ && INTVAL(XEXP(XEXP(operands[1], 0), 1)) <= 0x1FC) )
|
mgl@1371
|
12280 |
+ return "lddsp\t%0, %1";
|
mgl@1371
|
12281 |
+ else if ( avr32_const_pool_ref_operand(operands[1], GET_MODE(operands[1])) )
|
mgl@1371
|
12282 |
+ return "lddpc\t%0, %1";
|
mgl@1371
|
12283 |
+ else
|
mgl@1371
|
12284 |
+ return "ld.w\t%0, %1";
|
mgl@1371
|
12285 |
+ case 4:
|
mgl@1371
|
12286 |
+ if ( (REG_P(XEXP(operands[0], 0))
|
mgl@1371
|
12287 |
+ && REGNO(XEXP(operands[0], 0)) == SP_REGNUM)
|
mgl@1371
|
12288 |
+ || (GET_CODE(XEXP(operands[0], 0)) == PLUS
|
mgl@1371
|
12289 |
+ && REGNO(XEXP(XEXP(operands[0], 0), 0)) == SP_REGNUM
|
mgl@1371
|
12290 |
+ && GET_CODE(XEXP(XEXP(operands[0], 0), 1)) == CONST_INT
|
mgl@1371
|
12291 |
+ && INTVAL(XEXP(XEXP(operands[0], 0), 1)) % 4 == 0
|
mgl@1371
|
12292 |
+ && INTVAL(XEXP(XEXP(operands[0], 0), 1)) <= 0x1FC) )
|
mgl@1371
|
12293 |
+ return "stdsp\t%0, %1";
|
mgl@1371
|
12294 |
+ else
|
mgl@1371
|
12295 |
+ return "st.w\t%0, %1";
|
mgl@1371
|
12296 |
+ default:
|
mgl@1371
|
12297 |
+ abort();
|
mgl@1371
|
12298 |
+ }
|
mgl@1371
|
12299 |
+ }
|
mgl@1371
|
12300 |
+
|
mgl@1371
|
12301 |
+ [(set_attr "length" "2,4,8,4,4")
|
mgl@1371
|
12302 |
+ (set_attr "type" "alu,alu,alu2,load,store")
|
mgl@1371
|
12303 |
+ (set_attr "cc" "none,none,clobber,none,none")])
|
mgl@1371
|
12304 |
+
|
mgl@1371
|
12305 |
+
|
mgl@1371
|
12306 |
+
|
mgl@1371
|
12307 |
+;;== double - 64 bits =========================================================
|
mgl@1371
|
12308 |
+(define_expand "movdf"
|
mgl@1371
|
12309 |
+ [(set (match_operand:DF 0 "nonimmediate_operand" "")
|
mgl@1371
|
12310 |
+ (match_operand:DF 1 "general_operand" ""))]
|
mgl@1371
|
12311 |
+ ""
|
mgl@1371
|
12312 |
+ {
|
mgl@1371
|
12313 |
+ /* One of the ops has to be in a register. */
|
mgl@1371
|
12314 |
+ if (GET_CODE (operands[0]) != REG){
|
mgl@1371
|
12315 |
+ operands[1] = force_reg (DFmode, operands[1]);
|
mgl@1371
|
12316 |
+ }
|
mgl@1371
|
12317 |
+ })
|
mgl@1371
|
12318 |
+
|
mgl@1371
|
12319 |
+
|
mgl@1371
|
12320 |
+(define_insn_and_split "*movdf_internal"
|
mgl@1371
|
12321 |
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,r,r,m")
|
mgl@1371
|
12322 |
+ (match_operand:DF 1 "general_operand" " r,G,F,m,r"))]
|
mgl@1371
|
12323 |
+ "TARGET_SOFT_FLOAT
|
mgl@1371
|
12324 |
+ && (register_operand (operands[0], DFmode)
|
mgl@1371
|
12325 |
+ || register_operand (operands[1], DFmode))"
|
mgl@1371
|
12326 |
+ {
|
mgl@1371
|
12327 |
+ switch (which_alternative ){
|
mgl@1371
|
12328 |
+ case 0:
|
mgl@1371
|
12329 |
+ case 1:
|
mgl@1371
|
12330 |
+ case 2:
|
mgl@1371
|
12331 |
+ return "#";
|
mgl@1371
|
12332 |
+ case 3:
|
mgl@1371
|
12333 |
+ if ( avr32_const_pool_ref_operand(operands[1], GET_MODE(operands[1])))
|
mgl@1371
|
12334 |
+ return "ld.d\t%0, pc[%1 - .]";
|
mgl@1371
|
12335 |
+ else
|
mgl@1371
|
12336 |
+ return "ld.d\t%0, %1";
|
mgl@1371
|
12337 |
+ case 4:
|
mgl@1371
|
12338 |
+ return "st.d\t%0, %1";
|
mgl@1371
|
12339 |
+ default:
|
mgl@1371
|
12340 |
+ abort();
|
mgl@1371
|
12341 |
+ }
|
mgl@1371
|
12342 |
+ }
|
mgl@1371
|
12343 |
+ "TARGET_SOFT_FLOAT
|
mgl@1371
|
12344 |
+ && reload_completed
|
mgl@1371
|
12345 |
+ && (REG_P (operands[0])
|
mgl@1371
|
12346 |
+ && (REG_P (operands[1])
|
mgl@1371
|
12347 |
+ || GET_CODE (operands[1]) == CONST_DOUBLE))"
|
mgl@1371
|
12348 |
+ [(set (match_dup 0) (match_dup 1))
|
mgl@1371
|
12349 |
+ (set (match_dup 2) (match_dup 3))]
|
mgl@1371
|
12350 |
+ "
|
mgl@1371
|
12351 |
+ {
|
mgl@1371
|
12352 |
+ operands[2] = gen_highpart (SImode, operands[0]);
|
mgl@1371
|
12353 |
+ operands[0] = gen_lowpart (SImode, operands[0]);
|
mgl@1371
|
12354 |
+ operands[3] = gen_highpart(SImode, operands[1]);
|
mgl@1371
|
12355 |
+ operands[1] = gen_lowpart(SImode, operands[1]);
|
mgl@1371
|
12356 |
+ }
|
mgl@1371
|
12357 |
+ "
|
mgl@1371
|
12358 |
+
|
mgl@1371
|
12359 |
+ [(set_attr "length" "*,*,*,4,4")
|
mgl@1371
|
12360 |
+ (set_attr "type" "*,*,*,load2,store2")
|
mgl@1371
|
12361 |
+ (set_attr "cc" "*,*,*,none,none")])
|
mgl@1371
|
12362 |
+
|
mgl@1371
|
12363 |
+
|
mgl@1371
|
12364 |
+;;=============================================================================
|
mgl@1371
|
12365 |
+;; Conditional Moves
|
mgl@1371
|
12366 |
+;;=============================================================================
|
mgl@1371
|
12367 |
+(define_insn "ld<mode>_predicable"
|
mgl@1371
|
12368 |
+ [(set (match_operand:MOVCC 0 "register_operand" "=r")
|
mgl@1371
|
12369 |
+ (match_operand:MOVCC 1 "avr32_non_rmw_memory_operand" "<MOVCC:pred_mem_constraint>"))]
|
mgl@1371
|
12370 |
+ "TARGET_V2_INSNS"
|
mgl@1371
|
12371 |
+ "ld<MOVCC:load_postfix>%?\t%0, %1"
|
mgl@1371
|
12372 |
+ [(set_attr "length" "4")
|
mgl@1371
|
12373 |
+ (set_attr "cc" "cmp_cond_insn")
|
mgl@1371
|
12374 |
+ (set_attr "type" "load")
|
mgl@1371
|
12375 |
+ (set_attr "predicable" "yes")]
|
mgl@1371
|
12376 |
+)
|
mgl@1371
|
12377 |
+
|
mgl@1371
|
12378 |
+
|
mgl@1371
|
12379 |
+(define_insn "st<mode>_predicable"
|
mgl@1371
|
12380 |
+ [(set (match_operand:MOVCC 0 "avr32_non_rmw_memory_operand" "=<MOVCC:pred_mem_constraint>")
|
mgl@1371
|
12381 |
+ (match_operand:MOVCC 1 "register_operand" "r"))]
|
mgl@1371
|
12382 |
+ "TARGET_V2_INSNS"
|
mgl@1371
|
12383 |
+ "st<MOVCC:store_postfix>%?\t%0, %1"
|
mgl@1371
|
12384 |
+ [(set_attr "length" "4")
|
mgl@1371
|
12385 |
+ (set_attr "cc" "cmp_cond_insn")
|
mgl@1371
|
12386 |
+ (set_attr "type" "store")
|
mgl@1371
|
12387 |
+ (set_attr "predicable" "yes")]
|
mgl@1371
|
12388 |
+)
|
mgl@1371
|
12389 |
+
|
mgl@1371
|
12390 |
+(define_insn "mov<mode>_predicable"
|
mgl@1371
|
12391 |
+ [(set (match_operand:MOVCC 0 "register_operand" "=r")
|
mgl@1371
|
12392 |
+ (match_operand:MOVCC 1 "avr32_cond_register_immediate_operand" "rKs08"))]
|
mgl@1371
|
12393 |
+ ""
|
mgl@1371
|
12394 |
+ "mov%?\t%0, %1"
|
mgl@1371
|
12395 |
+ [(set_attr "length" "4")
|
mgl@1371
|
12396 |
+ (set_attr "cc" "cmp_cond_insn")
|
mgl@1371
|
12397 |
+ (set_attr "type" "alu")
|
mgl@1371
|
12398 |
+ (set_attr "predicable" "yes")]
|
mgl@1371
|
12399 |
+)
|
mgl@1371
|
12400 |
+
|
mgl@1371
|
12401 |
+
|
mgl@1371
|
12402 |
+;;=============================================================================
|
mgl@1371
|
12403 |
+;; Move chunks of memory
|
mgl@1371
|
12404 |
+;;=============================================================================
|
mgl@1371
|
12405 |
+
|
mgl@1371
|
12406 |
+(define_expand "movmemsi"
|
mgl@1371
|
12407 |
+ [(match_operand:BLK 0 "general_operand" "")
|
mgl@1371
|
12408 |
+ (match_operand:BLK 1 "general_operand" "")
|
mgl@1371
|
12409 |
+ (match_operand:SI 2 "const_int_operand" "")
|
mgl@1371
|
12410 |
+ (match_operand:SI 3 "const_int_operand" "")]
|
mgl@1371
|
12411 |
+ ""
|
mgl@1371
|
12412 |
+ "
|
mgl@1371
|
12413 |
+ if (avr32_gen_movmemsi (operands))
|
mgl@1371
|
12414 |
+ DONE;
|
mgl@1371
|
12415 |
+ FAIL;
|
mgl@1371
|
12416 |
+ "
|
mgl@1371
|
12417 |
+ )
|
mgl@1371
|
12418 |
+
|
mgl@1371
|
12419 |
+
|
mgl@1371
|
12420 |
+
|
mgl@1371
|
12421 |
+
|
mgl@1371
|
12422 |
+;;=============================================================================
|
mgl@1371
|
12423 |
+;; Bit field instructions
|
mgl@1371
|
12424 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
12425 |
+;; Instructions to insert or extract bit-fields
|
mgl@1371
|
12426 |
+;;=============================================================================
|
mgl@1371
|
12427 |
+
|
mgl@1371
|
12428 |
+(define_insn "insv"
|
mgl@1371
|
12429 |
+ [ (set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
|
mgl@1371
|
12430 |
+ (match_operand:SI 1 "immediate_operand" "Ku05")
|
mgl@1371
|
12431 |
+ (match_operand:SI 2 "immediate_operand" "Ku05"))
|
mgl@1371
|
12432 |
+ (match_operand 3 "register_operand" "r"))]
|
mgl@1371
|
12433 |
+ ""
|
mgl@1371
|
12434 |
+ "bfins\t%0, %3, %2, %1"
|
mgl@1371
|
12435 |
+ [(set_attr "type" "alu")
|
mgl@1371
|
12436 |
+ (set_attr "length" "4")
|
mgl@1371
|
12437 |
+ (set_attr "cc" "set_ncz")])
|
mgl@1371
|
12438 |
+
|
mgl@1371
|
12439 |
+
|
mgl@1371
|
12440 |
+
|
mgl@1371
|
12441 |
+(define_expand "extv"
|
mgl@1371
|
12442 |
+ [ (set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
12443 |
+ (sign_extract:SI (match_operand:SI 1 "register_operand" "")
|
mgl@1371
|
12444 |
+ (match_operand:SI 2 "immediate_operand" "")
|
mgl@1371
|
12445 |
+ (match_operand:SI 3 "immediate_operand" "")))]
|
mgl@1371
|
12446 |
+ ""
|
mgl@1371
|
12447 |
+ {
|
mgl@1371
|
12448 |
+ if ( INTVAL(operands[2]) >= 32 )
|
mgl@1371
|
12449 |
+ FAIL;
|
mgl@1371
|
12450 |
+ }
|
mgl@1371
|
12451 |
+)
|
mgl@1371
|
12452 |
+
|
mgl@1371
|
12453 |
+(define_expand "extzv"
|
mgl@1371
|
12454 |
+ [ (set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
12455 |
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "")
|
mgl@1371
|
12456 |
+ (match_operand:SI 2 "immediate_operand" "")
|
mgl@1371
|
12457 |
+ (match_operand:SI 3 "immediate_operand" "")))]
|
mgl@1371
|
12458 |
+ ""
|
mgl@1371
|
12459 |
+ {
|
mgl@1371
|
12460 |
+ if ( INTVAL(operands[2]) >= 32 )
|
mgl@1371
|
12461 |
+ FAIL;
|
mgl@1371
|
12462 |
+ }
|
mgl@1371
|
12463 |
+)
|
mgl@1371
|
12464 |
+
|
mgl@1371
|
12465 |
+(define_insn "extv_internal"
|
mgl@1371
|
12466 |
+ [ (set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
12467 |
+ (sign_extract:SI (match_operand:SI 1 "register_operand" "r")
|
mgl@1371
|
12468 |
+ (match_operand:SI 2 "immediate_operand" "Ku05")
|
mgl@1371
|
12469 |
+ (match_operand:SI 3 "immediate_operand" "Ku05")))]
|
mgl@1371
|
12470 |
+ "INTVAL(operands[2]) < 32"
|
mgl@1371
|
12471 |
+ "bfexts\t%0, %1, %3, %2"
|
mgl@1371
|
12472 |
+ [(set_attr "type" "alu")
|
mgl@1371
|
12473 |
+ (set_attr "length" "4")
|
mgl@1371
|
12474 |
+ (set_attr "cc" "set_ncz")])
|
mgl@1371
|
12475 |
+
|
mgl@1371
|
12476 |
+
|
mgl@1371
|
12477 |
+(define_insn "extzv_internal"
|
mgl@1371
|
12478 |
+ [ (set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
12479 |
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
|
mgl@1371
|
12480 |
+ (match_operand:SI 2 "immediate_operand" "Ku05")
|
mgl@1371
|
12481 |
+ (match_operand:SI 3 "immediate_operand" "Ku05")))]
|
mgl@1371
|
12482 |
+ "INTVAL(operands[2]) < 32"
|
mgl@1371
|
12483 |
+ "bfextu\t%0, %1, %3, %2"
|
mgl@1371
|
12484 |
+ [(set_attr "type" "alu")
|
mgl@1371
|
12485 |
+ (set_attr "length" "4")
|
mgl@1371
|
12486 |
+ (set_attr "cc" "set_ncz")])
|
mgl@1371
|
12487 |
+
|
mgl@1371
|
12488 |
+
|
mgl@1371
|
12489 |
+
|
mgl@1371
|
12490 |
+;;=============================================================================
|
mgl@1371
|
12491 |
+;; Some peepholes for avoiding unnecessary cast instructions
|
mgl@1371
|
12492 |
+;; followed by bfins.
|
mgl@1371
|
12493 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
12494 |
+
|
mgl@1371
|
12495 |
+(define_peephole2
|
mgl@1371
|
12496 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
12497 |
+ (zero_extend:SI (match_operand:QI 1 "register_operand" "")))
|
mgl@1371
|
12498 |
+ (set (zero_extract:SI (match_operand 2 "register_operand" "")
|
mgl@1371
|
12499 |
+ (match_operand:SI 3 "immediate_operand" "")
|
mgl@1371
|
12500 |
+ (match_operand:SI 4 "immediate_operand" ""))
|
mgl@1371
|
12501 |
+ (match_dup 0))]
|
mgl@1371
|
12502 |
+ "((peep2_reg_dead_p(2, operands[0]) &&
|
mgl@1371
|
12503 |
+ (INTVAL(operands[3]) <= 8)))"
|
mgl@1371
|
12504 |
+ [(set (zero_extract:SI (match_dup 2)
|
mgl@1371
|
12505 |
+ (match_dup 3)
|
mgl@1371
|
12506 |
+ (match_dup 4))
|
mgl@1371
|
12507 |
+ (match_dup 1))]
|
mgl@1371
|
12508 |
+ )
|
mgl@1371
|
12509 |
+
|
mgl@1371
|
12510 |
+(define_peephole2
|
mgl@1371
|
12511 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
12512 |
+ (zero_extend:SI (match_operand:HI 1 "register_operand" "")))
|
mgl@1371
|
12513 |
+ (set (zero_extract:SI (match_operand 2 "register_operand" "")
|
mgl@1371
|
12514 |
+ (match_operand:SI 3 "immediate_operand" "")
|
mgl@1371
|
12515 |
+ (match_operand:SI 4 "immediate_operand" ""))
|
mgl@1371
|
12516 |
+ (match_dup 0))]
|
mgl@1371
|
12517 |
+ "((peep2_reg_dead_p(2, operands[0]) &&
|
mgl@1371
|
12518 |
+ (INTVAL(operands[3]) <= 16)))"
|
mgl@1371
|
12519 |
+ [(set (zero_extract:SI (match_dup 2)
|
mgl@1371
|
12520 |
+ (match_dup 3)
|
mgl@1371
|
12521 |
+ (match_dup 4))
|
mgl@1371
|
12522 |
+ (match_dup 1))]
|
mgl@1371
|
12523 |
+ )
|
mgl@1371
|
12524 |
+
|
mgl@1371
|
12525 |
+;;=============================================================================
|
mgl@1371
|
12526 |
+;; push bytes
|
mgl@1371
|
12527 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
12528 |
+;; Implements the push instruction
|
mgl@1371
|
12529 |
+;;=============================================================================
|
mgl@1371
|
12530 |
+(define_insn "pushm"
|
mgl@1371
|
12531 |
+ [(set (mem:BLK (pre_dec:BLK (reg:SI SP_REGNUM)))
|
mgl@1371
|
12532 |
+ (unspec:BLK [(match_operand 0 "const_int_operand" "")]
|
mgl@1371
|
12533 |
+ UNSPEC_PUSHM))]
|
mgl@1371
|
12534 |
+ ""
|
mgl@1371
|
12535 |
+ {
|
mgl@1371
|
12536 |
+ if (INTVAL(operands[0])) {
|
mgl@1371
|
12537 |
+ return "pushm\t%r0";
|
mgl@1371
|
12538 |
+ } else {
|
mgl@1371
|
12539 |
+ return "";
|
mgl@1371
|
12540 |
+ }
|
mgl@1371
|
12541 |
+ }
|
mgl@1371
|
12542 |
+ [(set_attr "type" "store")
|
mgl@1371
|
12543 |
+ (set_attr "length" "2")
|
mgl@1371
|
12544 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
12545 |
+
|
mgl@1371
|
12546 |
+(define_insn "stm"
|
mgl@1371
|
12547 |
+ [(unspec [(match_operand 0 "register_operand" "r")
|
mgl@1371
|
12548 |
+ (match_operand 1 "const_int_operand" "")
|
mgl@1371
|
12549 |
+ (match_operand 2 "const_int_operand" "")]
|
mgl@1371
|
12550 |
+ UNSPEC_STM)]
|
mgl@1371
|
12551 |
+ ""
|
mgl@1371
|
12552 |
+ {
|
mgl@1371
|
12553 |
+ if (INTVAL(operands[1])) {
|
mgl@1371
|
12554 |
+ if (INTVAL(operands[2]) != 0)
|
mgl@1371
|
12555 |
+ return "stm\t--%0, %s1";
|
mgl@1371
|
12556 |
+ else
|
mgl@1371
|
12557 |
+ return "stm\t%0, %s1";
|
mgl@1371
|
12558 |
+ } else {
|
mgl@1371
|
12559 |
+ return "";
|
mgl@1371
|
12560 |
+ }
|
mgl@1371
|
12561 |
+ }
|
mgl@1371
|
12562 |
+ [(set_attr "type" "store")
|
mgl@1371
|
12563 |
+ (set_attr "length" "4")
|
mgl@1371
|
12564 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
12565 |
+
|
mgl@1371
|
12566 |
+
|
mgl@1371
|
12567 |
+
|
mgl@1371
|
12568 |
+(define_insn "popm"
|
mgl@1371
|
12569 |
+ [(unspec [(match_operand 0 "const_int_operand" "")]
|
mgl@1371
|
12570 |
+ UNSPEC_POPM)]
|
mgl@1371
|
12571 |
+ ""
|
mgl@1371
|
12572 |
+ {
|
mgl@1371
|
12573 |
+ if (INTVAL(operands[0])) {
|
mgl@1371
|
12574 |
+ return "popm %r0";
|
mgl@1371
|
12575 |
+ } else {
|
mgl@1371
|
12576 |
+ return "";
|
mgl@1371
|
12577 |
+ }
|
mgl@1371
|
12578 |
+ }
|
mgl@1371
|
12579 |
+ [(set_attr "type" "load")
|
mgl@1371
|
12580 |
+ (set_attr "length" "2")])
|
mgl@1371
|
12581 |
+
|
mgl@1371
|
12582 |
+
|
mgl@1371
|
12583 |
+
|
mgl@1371
|
12584 |
+;;=============================================================================
|
mgl@1371
|
12585 |
+;; add
|
mgl@1371
|
12586 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
12587 |
+;; Adds reg1 with reg2 and puts the result in reg0.
|
mgl@1371
|
12588 |
+;;=============================================================================
|
mgl@1371
|
12589 |
+(define_insn "add<mode>3"
|
mgl@1371
|
12590 |
+ [(set (match_operand:INTM 0 "register_operand" "=r,r,r,r,r")
|
mgl@1371
|
12591 |
+ (plus:INTM (match_operand:INTM 1 "register_operand" "%0,r,0,r,0")
|
mgl@1371
|
12592 |
+ (match_operand:INTM 2 "avr32_add_operand" "r,r,Is08,Is16,Is21")))]
|
mgl@1371
|
12593 |
+ ""
|
mgl@1371
|
12594 |
+ "@
|
mgl@1371
|
12595 |
+ add %0, %2
|
mgl@1371
|
12596 |
+ add %0, %1, %2
|
mgl@1371
|
12597 |
+ sub %0, %n2
|
mgl@1371
|
12598 |
+ sub %0, %1, %n2
|
mgl@1371
|
12599 |
+ sub %0, %n2"
|
mgl@1371
|
12600 |
+
|
mgl@1371
|
12601 |
+ [(set_attr "length" "2,4,2,4,4")
|
mgl@1371
|
12602 |
+ (set_attr "cc" "<INTM:alu_cc_attr>")])
|
mgl@1371
|
12603 |
+
|
mgl@1371
|
12604 |
+(define_insn "add<mode>3_lsl"
|
mgl@1371
|
12605 |
+ [(set (match_operand:INTM 0 "register_operand" "=r")
|
mgl@1371
|
12606 |
+ (plus:INTM (ashift:INTM (match_operand:INTM 1 "register_operand" "r")
|
mgl@1371
|
12607 |
+ (match_operand:INTM 3 "avr32_add_shift_immediate_operand" "Ku02"))
|
mgl@1371
|
12608 |
+ (match_operand:INTM 2 "register_operand" "r")))]
|
mgl@1371
|
12609 |
+ ""
|
mgl@1371
|
12610 |
+ "add %0, %2, %1 << %3"
|
mgl@1371
|
12611 |
+ [(set_attr "length" "4")
|
mgl@1371
|
12612 |
+ (set_attr "cc" "<INTM:alu_cc_attr>")])
|
mgl@1371
|
12613 |
+
|
mgl@1371
|
12614 |
+(define_insn "add<mode>3_lsl2"
|
mgl@1371
|
12615 |
+ [(set (match_operand:INTM 0 "register_operand" "=r")
|
mgl@1371
|
12616 |
+ (plus:INTM (match_operand:INTM 1 "register_operand" "r")
|
mgl@1371
|
12617 |
+ (ashift:INTM (match_operand:INTM 2 "register_operand" "r")
|
mgl@1371
|
12618 |
+ (match_operand:INTM 3 "avr32_add_shift_immediate_operand" "Ku02"))))]
|
mgl@1371
|
12619 |
+ ""
|
mgl@1371
|
12620 |
+ "add %0, %1, %2 << %3"
|
mgl@1371
|
12621 |
+ [(set_attr "length" "4")
|
mgl@1371
|
12622 |
+ (set_attr "cc" "<INTM:alu_cc_attr>")])
|
mgl@1371
|
12623 |
+
|
mgl@1371
|
12624 |
+
|
mgl@1371
|
12625 |
+(define_insn "add<mode>3_mul"
|
mgl@1371
|
12626 |
+ [(set (match_operand:INTM 0 "register_operand" "=r")
|
mgl@1371
|
12627 |
+ (plus:INTM (mult:INTM (match_operand:INTM 1 "register_operand" "r")
|
mgl@1371
|
12628 |
+ (match_operand:INTM 3 "immediate_operand" "Ku04" ))
|
mgl@1371
|
12629 |
+ (match_operand:INTM 2 "register_operand" "r")))]
|
mgl@1371
|
12630 |
+ "(INTVAL(operands[3]) == 0) || (INTVAL(operands[3]) == 2) ||
|
mgl@1371
|
12631 |
+ (INTVAL(operands[3]) == 4) || (INTVAL(operands[3]) == 8)"
|
mgl@1371
|
12632 |
+ "add %0, %2, %1 << %p3"
|
mgl@1371
|
12633 |
+ [(set_attr "length" "4")
|
mgl@1371
|
12634 |
+ (set_attr "cc" "<INTM:alu_cc_attr>")])
|
mgl@1371
|
12635 |
+
|
mgl@1371
|
12636 |
+(define_insn "add<mode>3_mul2"
|
mgl@1371
|
12637 |
+ [(set (match_operand:INTM 0 "register_operand" "=r")
|
mgl@1371
|
12638 |
+ (plus:INTM (match_operand:INTM 1 "register_operand" "r")
|
mgl@1371
|
12639 |
+ (mult:INTM (match_operand:INTM 2 "register_operand" "r")
|
mgl@1371
|
12640 |
+ (match_operand:INTM 3 "immediate_operand" "Ku04" ))))]
|
mgl@1371
|
12641 |
+ "(INTVAL(operands[3]) == 0) || (INTVAL(operands[3]) == 2) ||
|
mgl@1371
|
12642 |
+ (INTVAL(operands[3]) == 4) || (INTVAL(operands[3]) == 8)"
|
mgl@1371
|
12643 |
+ "add %0, %1, %2 << %p3"
|
mgl@1371
|
12644 |
+ [(set_attr "length" "4")
|
mgl@1371
|
12645 |
+ (set_attr "cc" "<INTM:alu_cc_attr>")])
|
mgl@1371
|
12646 |
+
|
mgl@1371
|
12647 |
+
|
mgl@1371
|
12648 |
+(define_peephole2
|
mgl@1371
|
12649 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
12650 |
+ (ashift:SI (match_operand:SI 1 "register_operand" "")
|
mgl@1371
|
12651 |
+ (match_operand:SI 2 "immediate_operand" "")))
|
mgl@1371
|
12652 |
+ (set (match_operand:SI 3 "register_operand" "")
|
mgl@1371
|
12653 |
+ (plus:SI (match_dup 0)
|
mgl@1371
|
12654 |
+ (match_operand:SI 4 "register_operand" "")))]
|
mgl@1371
|
12655 |
+ "(peep2_reg_dead_p(2, operands[0]) &&
|
mgl@1371
|
12656 |
+ (INTVAL(operands[2]) < 4 && INTVAL(operands[2]) > 0))"
|
mgl@1371
|
12657 |
+ [(set (match_dup 3)
|
mgl@1371
|
12658 |
+ (plus:SI (ashift:SI (match_dup 1)
|
mgl@1371
|
12659 |
+ (match_dup 2))
|
mgl@1371
|
12660 |
+ (match_dup 4)))]
|
mgl@1371
|
12661 |
+ )
|
mgl@1371
|
12662 |
+
|
mgl@1371
|
12663 |
+(define_peephole2
|
mgl@1371
|
12664 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
12665 |
+ (ashift:SI (match_operand:SI 1 "register_operand" "")
|
mgl@1371
|
12666 |
+ (match_operand:SI 2 "immediate_operand" "")))
|
mgl@1371
|
12667 |
+ (set (match_operand:SI 3 "register_operand" "")
|
mgl@1371
|
12668 |
+ (plus:SI (match_operand:SI 4 "register_operand" "")
|
mgl@1371
|
12669 |
+ (match_dup 0)))]
|
mgl@1371
|
12670 |
+ "(peep2_reg_dead_p(2, operands[0]) &&
|
mgl@1371
|
12671 |
+ (INTVAL(operands[2]) < 4 && INTVAL(operands[2]) > 0))"
|
mgl@1371
|
12672 |
+ [(set (match_dup 3)
|
mgl@1371
|
12673 |
+ (plus:SI (ashift:SI (match_dup 1)
|
mgl@1371
|
12674 |
+ (match_dup 2))
|
mgl@1371
|
12675 |
+ (match_dup 4)))]
|
mgl@1371
|
12676 |
+ )
|
mgl@1371
|
12677 |
+
|
mgl@1371
|
12678 |
+(define_insn "adddi3"
|
mgl@1371
|
12679 |
+ [(set (match_operand:DI 0 "register_operand" "=r,r")
|
mgl@1371
|
12680 |
+ (plus:DI (match_operand:DI 1 "register_operand" "%0,r")
|
mgl@1371
|
12681 |
+ (match_operand:DI 2 "register_operand" "r,r")))]
|
mgl@1371
|
12682 |
+ ""
|
mgl@1371
|
12683 |
+ "@
|
mgl@1371
|
12684 |
+ add %0, %2\;adc %m0, %m0, %m2
|
mgl@1371
|
12685 |
+ add %0, %1, %2\;adc %m0, %m1, %m2"
|
mgl@1371
|
12686 |
+ [(set_attr "length" "6,8")
|
mgl@1371
|
12687 |
+ (set_attr "type" "alu2")
|
mgl@1371
|
12688 |
+ (set_attr "cc" "set_vncz")])
|
mgl@1371
|
12689 |
+
|
mgl@1371
|
12690 |
+
|
mgl@1371
|
12691 |
+(define_insn "add<mode>_imm_predicable"
|
mgl@1371
|
12692 |
+ [(set (match_operand:INTM 0 "register_operand" "+r")
|
mgl@1371
|
12693 |
+ (plus:INTM (match_dup 0)
|
mgl@1371
|
12694 |
+ (match_operand:INTM 1 "avr32_cond_immediate_operand" "%Is08")))]
|
mgl@1371
|
12695 |
+ ""
|
mgl@1371
|
12696 |
+ "sub%?\t%0, -%1"
|
mgl@1371
|
12697 |
+ [(set_attr "length" "4")
|
mgl@1371
|
12698 |
+ (set_attr "cc" "cmp_cond_insn")
|
mgl@1371
|
12699 |
+ (set_attr "predicable" "yes")]
|
mgl@1371
|
12700 |
+)
|
mgl@1371
|
12701 |
+
|
mgl@1371
|
12702 |
+;;=============================================================================
|
mgl@1371
|
12703 |
+;; subtract
|
mgl@1371
|
12704 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
12705 |
+;; Subtract reg2 or immediate value from reg0 and puts the result in reg0.
|
mgl@1371
|
12706 |
+;;=============================================================================
|
mgl@1371
|
12707 |
+
|
mgl@1371
|
12708 |
+(define_insn "sub<mode>3"
|
mgl@1371
|
12709 |
+ [(set (match_operand:INTM 0 "general_operand" "=r,r,r,r,r,r,r")
|
mgl@1371
|
12710 |
+ (minus:INTM (match_operand:INTM 1 "nonmemory_operand" "0,r,0,r,0,r,Ks08")
|
mgl@1371
|
12711 |
+ (match_operand:INTM 2 "nonmemory_operand" "r,r,Ks08,Ks16,Ks21,0,r")))]
|
mgl@1371
|
12712 |
+ ""
|
mgl@1371
|
12713 |
+ "@
|
mgl@1371
|
12714 |
+ sub %0, %2
|
mgl@1371
|
12715 |
+ sub %0, %1, %2
|
mgl@1371
|
12716 |
+ sub %0, %2
|
mgl@1371
|
12717 |
+ sub %0, %1, %2
|
mgl@1371
|
12718 |
+ sub %0, %2
|
mgl@1371
|
12719 |
+ rsub %0, %1
|
mgl@1371
|
12720 |
+ rsub %0, %2, %1"
|
mgl@1371
|
12721 |
+ [(set_attr "length" "2,4,2,4,4,2,4")
|
mgl@1371
|
12722 |
+ (set_attr "cc" "<INTM:alu_cc_attr>")])
|
mgl@1371
|
12723 |
+
|
mgl@1371
|
12724 |
+(define_insn "*sub<mode>3_mul"
|
mgl@1371
|
12725 |
+ [(set (match_operand:INTM 0 "register_operand" "=r")
|
mgl@1371
|
12726 |
+ (minus:INTM (match_operand:INTM 1 "register_operand" "r")
|
mgl@1371
|
12727 |
+ (mult:INTM (match_operand:INTM 2 "register_operand" "r")
|
mgl@1371
|
12728 |
+ (match_operand:SI 3 "immediate_operand" "Ku04" ))))]
|
mgl@1371
|
12729 |
+ "(INTVAL(operands[3]) == 0) || (INTVAL(operands[3]) == 2) ||
|
mgl@1371
|
12730 |
+ (INTVAL(operands[3]) == 4) || (INTVAL(operands[3]) == 8)"
|
mgl@1371
|
12731 |
+ "sub %0, %1, %2 << %p3"
|
mgl@1371
|
12732 |
+ [(set_attr "length" "4")
|
mgl@1371
|
12733 |
+ (set_attr "cc" "<INTM:alu_cc_attr>")])
|
mgl@1371
|
12734 |
+
|
mgl@1371
|
12735 |
+(define_insn "*sub<mode>3_lsl"
|
mgl@1371
|
12736 |
+ [(set (match_operand:INTM 0 "register_operand" "=r")
|
mgl@1371
|
12737 |
+ (minus:INTM (match_operand:INTM 1 "register_operand" "r")
|
mgl@1371
|
12738 |
+ (ashift:INTM (match_operand:INTM 2 "register_operand" "r")
|
mgl@1371
|
12739 |
+ (match_operand:SI 3 "avr32_add_shift_immediate_operand" "Ku02"))))]
|
mgl@1371
|
12740 |
+ ""
|
mgl@1371
|
12741 |
+ "sub %0, %1, %2 << %3"
|
mgl@1371
|
12742 |
+ [(set_attr "length" "4")
|
mgl@1371
|
12743 |
+ (set_attr "cc" "<INTM:alu_cc_attr>")])
|
mgl@1371
|
12744 |
+
|
mgl@1371
|
12745 |
+
|
mgl@1371
|
12746 |
+(define_insn "subdi3"
|
mgl@1371
|
12747 |
+ [(set (match_operand:DI 0 "register_operand" "=r,r")
|
mgl@1371
|
12748 |
+ (minus:DI (match_operand:DI 1 "register_operand" "%0,r")
|
mgl@1371
|
12749 |
+ (match_operand:DI 2 "register_operand" "r,r")))]
|
mgl@1371
|
12750 |
+ ""
|
mgl@1371
|
12751 |
+ "@
|
mgl@1371
|
12752 |
+ sub %0, %2\;sbc %m0, %m0, %m2
|
mgl@1371
|
12753 |
+ sub %0, %1, %2\;sbc %m0, %m1, %m2"
|
mgl@1371
|
12754 |
+ [(set_attr "length" "6,8")
|
mgl@1371
|
12755 |
+ (set_attr "type" "alu2")
|
mgl@1371
|
12756 |
+ (set_attr "cc" "set_vncz")])
|
mgl@1371
|
12757 |
+
|
mgl@1371
|
12758 |
+
|
mgl@1371
|
12759 |
+(define_insn "sub<mode>_imm_predicable"
|
mgl@1371
|
12760 |
+ [(set (match_operand:INTM 0 "register_operand" "+r")
|
mgl@1371
|
12761 |
+ (minus:INTM (match_dup 0)
|
mgl@1371
|
12762 |
+ (match_operand:INTM 1 "avr32_cond_immediate_operand" "Ks08")))]
|
mgl@1371
|
12763 |
+ ""
|
mgl@1371
|
12764 |
+ "sub%?\t%0, %1"
|
mgl@1371
|
12765 |
+ [(set_attr "length" "4")
|
mgl@1371
|
12766 |
+ (set_attr "cc" "cmp_cond_insn")
|
mgl@1371
|
12767 |
+ (set_attr "predicable" "yes")])
|
mgl@1371
|
12768 |
+
|
mgl@1371
|
12769 |
+(define_insn "rsub<mode>_imm_predicable"
|
mgl@1371
|
12770 |
+ [(set (match_operand:INTM 0 "register_operand" "+r")
|
mgl@1371
|
12771 |
+ (minus:INTM (match_operand:INTM 1 "avr32_cond_immediate_operand" "Ks08")
|
mgl@1371
|
12772 |
+ (match_dup 0)))]
|
mgl@1371
|
12773 |
+ ""
|
mgl@1371
|
12774 |
+ "rsub%?\t%0, %1"
|
mgl@1371
|
12775 |
+ [(set_attr "length" "4")
|
mgl@1371
|
12776 |
+ (set_attr "cc" "cmp_cond_insn")
|
mgl@1371
|
12777 |
+ (set_attr "predicable" "yes")])
|
mgl@1371
|
12778 |
+
|
mgl@1371
|
12779 |
+;;=============================================================================
|
mgl@1371
|
12780 |
+;; multiply
|
mgl@1371
|
12781 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
12782 |
+;; Multiply op1 and op2 and put the value in op0.
|
mgl@1371
|
12783 |
+;;=============================================================================
|
mgl@1371
|
12784 |
+
|
mgl@1371
|
12785 |
+
|
mgl@1371
|
12786 |
+(define_insn "mulqi3"
|
mgl@1371
|
12787 |
+ [(set (match_operand:QI 0 "register_operand" "=r,r,r")
|
mgl@1371
|
12788 |
+ (mult:QI (match_operand:QI 1 "register_operand" "%0,r,r")
|
mgl@1371
|
12789 |
+ (match_operand:QI 2 "avr32_mul_operand" "r,r,Ks08")))]
|
mgl@1371
|
12790 |
+ "!TARGET_NO_MUL_INSNS"
|
mgl@1371
|
12791 |
+ {
|
mgl@1371
|
12792 |
+ switch (which_alternative){
|
mgl@1371
|
12793 |
+ case 0:
|
mgl@1371
|
12794 |
+ return "mul %0, %2";
|
mgl@1371
|
12795 |
+ case 1:
|
mgl@1371
|
12796 |
+ return "mul %0, %1, %2";
|
mgl@1371
|
12797 |
+ case 2:
|
mgl@1371
|
12798 |
+ return "mul %0, %1, %2";
|
mgl@1371
|
12799 |
+ default:
|
mgl@1371
|
12800 |
+ gcc_unreachable();
|
mgl@1371
|
12801 |
+ }
|
mgl@1371
|
12802 |
+ }
|
mgl@1371
|
12803 |
+ [(set_attr "type" "mulww_w,mulww_w,mulwh")
|
mgl@1371
|
12804 |
+ (set_attr "length" "2,4,4")
|
mgl@1371
|
12805 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
12806 |
+
|
mgl@1371
|
12807 |
+(define_insn "mulsi3"
|
mgl@1371
|
12808 |
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r")
|
mgl@1371
|
12809 |
+ (mult:SI (match_operand:SI 1 "register_operand" "%0,r,r")
|
mgl@1371
|
12810 |
+ (match_operand:SI 2 "avr32_mul_operand" "r,r,Ks08")))]
|
mgl@1371
|
12811 |
+ "!TARGET_NO_MUL_INSNS"
|
mgl@1371
|
12812 |
+ {
|
mgl@1371
|
12813 |
+ switch (which_alternative){
|
mgl@1371
|
12814 |
+ case 0:
|
mgl@1371
|
12815 |
+ return "mul %0, %2";
|
mgl@1371
|
12816 |
+ case 1:
|
mgl@1371
|
12817 |
+ return "mul %0, %1, %2";
|
mgl@1371
|
12818 |
+ case 2:
|
mgl@1371
|
12819 |
+ return "mul %0, %1, %2";
|
mgl@1371
|
12820 |
+ default:
|
mgl@1371
|
12821 |
+ gcc_unreachable();
|
mgl@1371
|
12822 |
+ }
|
mgl@1371
|
12823 |
+ }
|
mgl@1371
|
12824 |
+ [(set_attr "type" "mulww_w,mulww_w,mulwh")
|
mgl@1371
|
12825 |
+ (set_attr "length" "2,4,4")
|
mgl@1371
|
12826 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
12827 |
+
|
mgl@1371
|
12828 |
+
|
mgl@1371
|
12829 |
+(define_insn "mulhisi3"
|
mgl@1371
|
12830 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
12831 |
+ (mult:SI
|
mgl@1371
|
12832 |
+ (sign_extend:SI (match_operand:HI 1 "register_operand" "%r"))
|
mgl@1371
|
12833 |
+ (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
|
mgl@1371
|
12834 |
+ "!TARGET_NO_MUL_INSNS && TARGET_DSP"
|
mgl@1371
|
12835 |
+ "mulhh.w %0, %1:b, %2:b"
|
mgl@1371
|
12836 |
+ [(set_attr "type" "mulhh")
|
mgl@1371
|
12837 |
+ (set_attr "length" "4")
|
mgl@1371
|
12838 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
12839 |
+
|
mgl@1371
|
12840 |
+(define_peephole2
|
mgl@1371
|
12841 |
+ [(match_scratch:DI 6 "r")
|
mgl@1371
|
12842 |
+ (set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
12843 |
+ (mult:SI
|
mgl@1371
|
12844 |
+ (sign_extend:SI (match_operand:HI 1 "register_operand" ""))
|
mgl@1371
|
12845 |
+ (sign_extend:SI (match_operand:HI 2 "register_operand" ""))))
|
mgl@1371
|
12846 |
+ (set (match_operand:SI 3 "register_operand" "")
|
mgl@1371
|
12847 |
+ (ashiftrt:SI (match_dup 0)
|
mgl@1371
|
12848 |
+ (const_int 16)))]
|
mgl@1371
|
12849 |
+ "!TARGET_NO_MUL_INSNS && TARGET_DSP
|
mgl@1371
|
12850 |
+ && (peep2_reg_dead_p(1, operands[0]) || (REGNO(operands[0]) == REGNO(operands[3])))"
|
mgl@1371
|
12851 |
+ [(set (match_dup 4) (sign_extend:SI (match_dup 1)))
|
mgl@1371
|
12852 |
+ (set (match_dup 6)
|
mgl@1371
|
12853 |
+ (ashift:DI (mult:DI (sign_extend:DI (match_dup 4))
|
mgl@1371
|
12854 |
+ (sign_extend:DI (match_dup 2)))
|
mgl@1371
|
12855 |
+ (const_int 16)))
|
mgl@1371
|
12856 |
+ (set (match_dup 3) (match_dup 5))]
|
mgl@1371
|
12857 |
+
|
mgl@1371
|
12858 |
+ "{
|
mgl@1371
|
12859 |
+ operands[4] = gen_rtx_REG(SImode, REGNO(operands[1]));
|
mgl@1371
|
12860 |
+ operands[5] = gen_highpart (SImode, operands[4]);
|
mgl@1371
|
12861 |
+ }"
|
mgl@1371
|
12862 |
+ )
|
mgl@1371
|
12863 |
+
|
mgl@1371
|
12864 |
+(define_insn "mulnhisi3"
|
mgl@1371
|
12865 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
12866 |
+ (mult:SI
|
mgl@1371
|
12867 |
+ (sign_extend:SI (neg:HI (match_operand:HI 1 "register_operand" "r")))
|
mgl@1371
|
12868 |
+ (sign_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
|
mgl@1371
|
12869 |
+ "!TARGET_NO_MUL_INSNS && TARGET_DSP"
|
mgl@1371
|
12870 |
+ "mulnhh.w %0, %1:b, %2:b"
|
mgl@1371
|
12871 |
+ [(set_attr "type" "mulhh")
|
mgl@1371
|
12872 |
+ (set_attr "length" "4")
|
mgl@1371
|
12873 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
12874 |
+
|
mgl@1371
|
12875 |
+(define_insn "machisi3"
|
mgl@1371
|
12876 |
+ [(set (match_operand:SI 0 "register_operand" "+r")
|
mgl@1371
|
12877 |
+ (plus:SI (mult:SI
|
mgl@1371
|
12878 |
+ (sign_extend:SI (match_operand:HI 1 "register_operand" "%r"))
|
mgl@1371
|
12879 |
+ (sign_extend:SI (match_operand:HI 2 "register_operand" "r")))
|
mgl@1371
|
12880 |
+ (match_dup 0)))]
|
mgl@1371
|
12881 |
+ "!TARGET_NO_MUL_INSNS && TARGET_DSP"
|
mgl@1371
|
12882 |
+ "machh.w %0, %1:b, %2:b"
|
mgl@1371
|
12883 |
+ [(set_attr "type" "machh_w")
|
mgl@1371
|
12884 |
+ (set_attr "length" "4")
|
mgl@1371
|
12885 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
12886 |
+
|
mgl@1371
|
12887 |
+
|
mgl@1371
|
12888 |
+
|
mgl@1371
|
12889 |
+(define_insn "mulsidi3"
|
mgl@1371
|
12890 |
+ [(set (match_operand:DI 0 "register_operand" "=r")
|
mgl@1371
|
12891 |
+ (mult:DI
|
mgl@1371
|
12892 |
+ (sign_extend:DI (match_operand:SI 1 "register_operand" "%r"))
|
mgl@1371
|
12893 |
+ (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
|
mgl@1371
|
12894 |
+ "!TARGET_NO_MUL_INSNS"
|
mgl@1371
|
12895 |
+ "muls.d %0, %1, %2"
|
mgl@1371
|
12896 |
+ [(set_attr "type" "mulww_d")
|
mgl@1371
|
12897 |
+ (set_attr "length" "4")
|
mgl@1371
|
12898 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
12899 |
+
|
mgl@1371
|
12900 |
+(define_insn "umulsidi3"
|
mgl@1371
|
12901 |
+ [(set (match_operand:DI 0 "register_operand" "=r")
|
mgl@1371
|
12902 |
+ (mult:DI
|
mgl@1371
|
12903 |
+ (zero_extend:DI (match_operand:SI 1 "register_operand" "%r"))
|
mgl@1371
|
12904 |
+ (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))]
|
mgl@1371
|
12905 |
+ "!TARGET_NO_MUL_INSNS"
|
mgl@1371
|
12906 |
+ "mulu.d %0, %1, %2"
|
mgl@1371
|
12907 |
+ [(set_attr "type" "mulww_d")
|
mgl@1371
|
12908 |
+ (set_attr "length" "4")
|
mgl@1371
|
12909 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
12910 |
+
|
mgl@1371
|
12911 |
+(define_insn "*mulaccsi3"
|
mgl@1371
|
12912 |
+ [(set (match_operand:SI 0 "register_operand" "+r")
|
mgl@1371
|
12913 |
+ (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "%r")
|
mgl@1371
|
12914 |
+ (match_operand:SI 2 "register_operand" "r"))
|
mgl@1371
|
12915 |
+ (match_dup 0)))]
|
mgl@1371
|
12916 |
+ "!TARGET_NO_MUL_INSNS"
|
mgl@1371
|
12917 |
+ "mac %0, %1, %2"
|
mgl@1371
|
12918 |
+ [(set_attr "type" "macww_w")
|
mgl@1371
|
12919 |
+ (set_attr "length" "4")
|
mgl@1371
|
12920 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
12921 |
+
|
mgl@1371
|
12922 |
+(define_insn "*mulaccsidi3"
|
mgl@1371
|
12923 |
+ [(set (match_operand:DI 0 "register_operand" "+r")
|
mgl@1371
|
12924 |
+ (plus:DI (mult:DI
|
mgl@1371
|
12925 |
+ (sign_extend:DI (match_operand:SI 1 "register_operand" "%r"))
|
mgl@1371
|
12926 |
+ (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
|
mgl@1371
|
12927 |
+ (match_dup 0)))]
|
mgl@1371
|
12928 |
+ "!TARGET_NO_MUL_INSNS"
|
mgl@1371
|
12929 |
+ "macs.d %0, %1, %2"
|
mgl@1371
|
12930 |
+ [(set_attr "type" "macww_d")
|
mgl@1371
|
12931 |
+ (set_attr "length" "4")
|
mgl@1371
|
12932 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
12933 |
+
|
mgl@1371
|
12934 |
+(define_insn "*umulaccsidi3"
|
mgl@1371
|
12935 |
+ [(set (match_operand:DI 0 "register_operand" "+r")
|
mgl@1371
|
12936 |
+ (plus:DI (mult:DI
|
mgl@1371
|
12937 |
+ (zero_extend:DI (match_operand:SI 1 "register_operand" "%r"))
|
mgl@1371
|
12938 |
+ (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
|
mgl@1371
|
12939 |
+ (match_dup 0)))]
|
mgl@1371
|
12940 |
+ "!TARGET_NO_MUL_INSNS"
|
mgl@1371
|
12941 |
+ "macu.d %0, %1, %2"
|
mgl@1371
|
12942 |
+ [(set_attr "type" "macww_d")
|
mgl@1371
|
12943 |
+ (set_attr "length" "4")
|
mgl@1371
|
12944 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
12945 |
+
|
mgl@1371
|
12946 |
+
|
mgl@1371
|
12947 |
+
|
mgl@1371
|
12948 |
+;; Try to avoid Write-After-Write hazards for mul operations
|
mgl@1371
|
12949 |
+;; if it can be done
|
mgl@1371
|
12950 |
+(define_peephole2
|
mgl@1371
|
12951 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
12952 |
+ (mult:SI
|
mgl@1371
|
12953 |
+ (sign_extend:SI (match_operand 1 "general_operand" ""))
|
mgl@1371
|
12954 |
+ (sign_extend:SI (match_operand 2 "general_operand" ""))))
|
mgl@1371
|
12955 |
+ (set (match_dup 0)
|
mgl@1371
|
12956 |
+ (match_operator:SI 3 "alu_operator" [(match_dup 0)
|
mgl@1371
|
12957 |
+ (match_operand 4 "general_operand" "")]))]
|
mgl@1371
|
12958 |
+ "peep2_reg_dead_p(1, operands[2])"
|
mgl@1371
|
12959 |
+ [(set (match_dup 5)
|
mgl@1371
|
12960 |
+ (mult:SI
|
mgl@1371
|
12961 |
+ (sign_extend:SI (match_dup 1))
|
mgl@1371
|
12962 |
+ (sign_extend:SI (match_dup 2))))
|
mgl@1371
|
12963 |
+ (set (match_dup 0)
|
mgl@1371
|
12964 |
+ (match_op_dup 3 [(match_dup 5)
|
mgl@1371
|
12965 |
+ (match_dup 4)]))]
|
mgl@1371
|
12966 |
+ "{operands[5] = gen_rtx_REG(SImode, REGNO(operands[2]));}"
|
mgl@1371
|
12967 |
+ )
|
mgl@1371
|
12968 |
+
|
mgl@1371
|
12969 |
+
|
mgl@1371
|
12970 |
+
|
mgl@1371
|
12971 |
+;;=============================================================================
|
mgl@1371
|
12972 |
+;; DSP instructions
|
mgl@1371
|
12973 |
+;;=============================================================================
|
mgl@1371
|
12974 |
+(define_insn "mulsathh_h"
|
mgl@1371
|
12975 |
+ [(set (match_operand:HI 0 "register_operand" "=r")
|
mgl@1371
|
12976 |
+ (ss_truncate:HI (ashiftrt:SI (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%r"))
|
mgl@1371
|
12977 |
+ (sign_extend:SI (match_operand:HI 2 "register_operand" "r")))
|
mgl@1371
|
12978 |
+ (const_int 15))))]
|
mgl@1371
|
12979 |
+ "!TARGET_NO_MUL_INSNS && TARGET_DSP"
|
mgl@1371
|
12980 |
+ "mulsathh.h\t%0, %1:b, %2:b"
|
mgl@1371
|
12981 |
+ [(set_attr "length" "4")
|
mgl@1371
|
12982 |
+ (set_attr "cc" "none")
|
mgl@1371
|
12983 |
+ (set_attr "type" "mulhh")])
|
mgl@1371
|
12984 |
+
|
mgl@1371
|
12985 |
+(define_insn "mulsatrndhh_h"
|
mgl@1371
|
12986 |
+ [(set (match_operand:HI 0 "register_operand" "=r")
|
mgl@1371
|
12987 |
+ (ss_truncate:HI (ashiftrt:SI
|
mgl@1371
|
12988 |
+ (plus:SI (mult:SI (sign_extend:SI (match_operand:HI 1 "register_operand" "%r"))
|
mgl@1371
|
12989 |
+ (sign_extend:SI (match_operand:HI 2 "register_operand" "r")))
|
mgl@1371
|
12990 |
+ (const_int 1073741824))
|
mgl@1371
|
12991 |
+ (const_int 15))))]
|
mgl@1371
|
12992 |
+ "!TARGET_NO_MUL_INSNS && TARGET_DSP"
|
mgl@1371
|
12993 |
+ "mulsatrndhh.h\t%0, %1:b, %2:b"
|
mgl@1371
|
12994 |
+ [(set_attr "length" "4")
|
mgl@1371
|
12995 |
+ (set_attr "cc" "none")
|
mgl@1371
|
12996 |
+ (set_attr "type" "mulhh")])
|
mgl@1371
|
12997 |
+
|
mgl@1371
|
12998 |
+(define_insn "mulsathh_w"
|
mgl@1371
|
12999 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
13000 |
+ (ss_truncate:SI (ashift:DI (mult:DI (sign_extend:DI (match_operand:HI 1 "register_operand" "%r"))
|
mgl@1371
|
13001 |
+ (sign_extend:DI (match_operand:HI 2 "register_operand" "r")))
|
mgl@1371
|
13002 |
+ (const_int 1))))]
|
mgl@1371
|
13003 |
+ "!TARGET_NO_MUL_INSNS && TARGET_DSP"
|
mgl@1371
|
13004 |
+ "mulsathh.w\t%0, %1:b, %2:b"
|
mgl@1371
|
13005 |
+ [(set_attr "length" "4")
|
mgl@1371
|
13006 |
+ (set_attr "cc" "none")
|
mgl@1371
|
13007 |
+ (set_attr "type" "mulhh")])
|
mgl@1371
|
13008 |
+
|
mgl@1371
|
13009 |
+(define_insn "mulsatwh_w"
|
mgl@1371
|
13010 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
13011 |
+ (ss_truncate:SI (ashiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
|
mgl@1371
|
13012 |
+ (sign_extend:DI (match_operand:HI 2 "register_operand" "r")))
|
mgl@1371
|
13013 |
+ (const_int 15))))]
|
mgl@1371
|
13014 |
+ "!TARGET_NO_MUL_INSNS && TARGET_DSP"
|
mgl@1371
|
13015 |
+ "mulsatwh.w\t%0, %1, %2:b"
|
mgl@1371
|
13016 |
+ [(set_attr "length" "4")
|
mgl@1371
|
13017 |
+ (set_attr "cc" "none")
|
mgl@1371
|
13018 |
+ (set_attr "type" "mulwh")])
|
mgl@1371
|
13019 |
+
|
mgl@1371
|
13020 |
+(define_insn "mulsatrndwh_w"
|
mgl@1371
|
13021 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
13022 |
+ (ss_truncate:SI (ashiftrt:DI (plus:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
|
mgl@1371
|
13023 |
+ (sign_extend:DI (match_operand:HI 2 "register_operand" "r")))
|
mgl@1371
|
13024 |
+ (const_int 1073741824))
|
mgl@1371
|
13025 |
+ (const_int 15))))]
|
mgl@1371
|
13026 |
+ "!TARGET_NO_MUL_INSNS && TARGET_DSP"
|
mgl@1371
|
13027 |
+ "mulsatrndwh.w\t%0, %1, %2:b"
|
mgl@1371
|
13028 |
+ [(set_attr "length" "4")
|
mgl@1371
|
13029 |
+ (set_attr "cc" "none")
|
mgl@1371
|
13030 |
+ (set_attr "type" "mulwh")])
|
mgl@1371
|
13031 |
+
|
mgl@1371
|
13032 |
+(define_insn "macsathh_w"
|
mgl@1371
|
13033 |
+ [(set (match_operand:SI 0 "register_operand" "+r")
|
mgl@1371
|
13034 |
+ (plus:SI (match_dup 0)
|
mgl@1371
|
13035 |
+ (ss_truncate:SI (ashift:DI (mult:DI (sign_extend:DI (match_operand:HI 1 "register_operand" "%r"))
|
mgl@1371
|
13036 |
+ (sign_extend:DI (match_operand:HI 2 "register_operand" "r")))
|
mgl@1371
|
13037 |
+ (const_int 1)))))]
|
mgl@1371
|
13038 |
+ "!TARGET_NO_MUL_INSNS && TARGET_DSP"
|
mgl@1371
|
13039 |
+ "macsathh.w\t%0, %1:b, %2:b"
|
mgl@1371
|
13040 |
+ [(set_attr "length" "4")
|
mgl@1371
|
13041 |
+ (set_attr "cc" "none")
|
mgl@1371
|
13042 |
+ (set_attr "type" "mulhh")])
|
mgl@1371
|
13043 |
+
|
mgl@1371
|
13044 |
+
|
mgl@1371
|
13045 |
+(define_insn "mulwh_d"
|
mgl@1371
|
13046 |
+ [(set (match_operand:DI 0 "register_operand" "=r")
|
mgl@1371
|
13047 |
+ (ashift:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
|
mgl@1371
|
13048 |
+ (sign_extend:DI (match_operand:HI 2 "register_operand" "r")))
|
mgl@1371
|
13049 |
+ (const_int 16)))]
|
mgl@1371
|
13050 |
+ "!TARGET_NO_MUL_INSNS && TARGET_DSP"
|
mgl@1371
|
13051 |
+ "mulwh.d\t%0, %1, %2:b"
|
mgl@1371
|
13052 |
+ [(set_attr "length" "4")
|
mgl@1371
|
13053 |
+ (set_attr "cc" "none")
|
mgl@1371
|
13054 |
+ (set_attr "type" "mulwh")])
|
mgl@1371
|
13055 |
+
|
mgl@1371
|
13056 |
+
|
mgl@1371
|
13057 |
+(define_insn "mulnwh_d"
|
mgl@1371
|
13058 |
+ [(set (match_operand:DI 0 "register_operand" "=r")
|
mgl@1371
|
13059 |
+ (ashift:DI (mult:DI (not:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r")))
|
mgl@1371
|
13060 |
+ (sign_extend:DI (match_operand:HI 2 "register_operand" "r")))
|
mgl@1371
|
13061 |
+ (const_int 16)))]
|
mgl@1371
|
13062 |
+ "!TARGET_NO_MUL_INSNS && TARGET_DSP"
|
mgl@1371
|
13063 |
+ "mulnwh.d\t%0, %1, %2:b"
|
mgl@1371
|
13064 |
+ [(set_attr "length" "4")
|
mgl@1371
|
13065 |
+ (set_attr "cc" "none")
|
mgl@1371
|
13066 |
+ (set_attr "type" "mulwh")])
|
mgl@1371
|
13067 |
+
|
mgl@1371
|
13068 |
+(define_insn "macwh_d"
|
mgl@1371
|
13069 |
+ [(set (match_operand:DI 0 "register_operand" "+r")
|
mgl@1371
|
13070 |
+ (plus:DI (match_dup 0)
|
mgl@1371
|
13071 |
+ (ashift:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%r"))
|
mgl@1371
|
13072 |
+ (sign_extend:DI (match_operand:HI 2 "register_operand" "r")))
|
mgl@1371
|
13073 |
+ (const_int 16))))]
|
mgl@1371
|
13074 |
+ "!TARGET_NO_MUL_INSNS && TARGET_DSP"
|
mgl@1371
|
13075 |
+ "macwh.d\t%0, %1, %2:b"
|
mgl@1371
|
13076 |
+ [(set_attr "length" "4")
|
mgl@1371
|
13077 |
+ (set_attr "cc" "none")
|
mgl@1371
|
13078 |
+ (set_attr "type" "mulwh")])
|
mgl@1371
|
13079 |
+
|
mgl@1371
|
13080 |
+(define_insn "machh_d"
|
mgl@1371
|
13081 |
+ [(set (match_operand:DI 0 "register_operand" "+r")
|
mgl@1371
|
13082 |
+ (plus:DI (match_dup 0)
|
mgl@1371
|
13083 |
+ (mult:DI (sign_extend:DI (match_operand:HI 1 "register_operand" "%r"))
|
mgl@1371
|
13084 |
+ (sign_extend:DI (match_operand:HI 2 "register_operand" "r")))))]
|
mgl@1371
|
13085 |
+ "!TARGET_NO_MUL_INSNS && TARGET_DSP"
|
mgl@1371
|
13086 |
+ "machh.d\t%0, %1:b, %2:b"
|
mgl@1371
|
13087 |
+ [(set_attr "length" "4")
|
mgl@1371
|
13088 |
+ (set_attr "cc" "none")
|
mgl@1371
|
13089 |
+ (set_attr "type" "mulwh")])
|
mgl@1371
|
13090 |
+
|
mgl@1371
|
13091 |
+(define_insn "satadd_w"
|
mgl@1371
|
13092 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
13093 |
+ (ss_plus:SI (match_operand:SI 1 "register_operand" "r")
|
mgl@1371
|
13094 |
+ (match_operand:SI 2 "register_operand" "r")))]
|
mgl@1371
|
13095 |
+ "TARGET_DSP"
|
mgl@1371
|
13096 |
+ "satadd.w\t%0, %1, %2"
|
mgl@1371
|
13097 |
+ [(set_attr "length" "4")
|
mgl@1371
|
13098 |
+ (set_attr "cc" "none")
|
mgl@1371
|
13099 |
+ (set_attr "type" "alu_sat")])
|
mgl@1371
|
13100 |
+
|
mgl@1371
|
13101 |
+(define_insn "satsub_w"
|
mgl@1371
|
13102 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
13103 |
+ (ss_minus:SI (match_operand:SI 1 "register_operand" "r")
|
mgl@1371
|
13104 |
+ (match_operand:SI 2 "register_operand" "r")))]
|
mgl@1371
|
13105 |
+ "TARGET_DSP"
|
mgl@1371
|
13106 |
+ "satsub.w\t%0, %1, %2"
|
mgl@1371
|
13107 |
+ [(set_attr "length" "4")
|
mgl@1371
|
13108 |
+ (set_attr "cc" "none")
|
mgl@1371
|
13109 |
+ (set_attr "type" "alu_sat")])
|
mgl@1371
|
13110 |
+
|
mgl@1371
|
13111 |
+(define_insn "satadd_h"
|
mgl@1371
|
13112 |
+ [(set (match_operand:HI 0 "register_operand" "=r")
|
mgl@1371
|
13113 |
+ (ss_plus:HI (match_operand:HI 1 "register_operand" "r")
|
mgl@1371
|
13114 |
+ (match_operand:HI 2 "register_operand" "r")))]
|
mgl@1371
|
13115 |
+ "TARGET_DSP"
|
mgl@1371
|
13116 |
+ "satadd.h\t%0, %1, %2"
|
mgl@1371
|
13117 |
+ [(set_attr "length" "4")
|
mgl@1371
|
13118 |
+ (set_attr "cc" "none")
|
mgl@1371
|
13119 |
+ (set_attr "type" "alu_sat")])
|
mgl@1371
|
13120 |
+
|
mgl@1371
|
13121 |
+(define_insn "satsub_h"
|
mgl@1371
|
13122 |
+ [(set (match_operand:HI 0 "register_operand" "=r")
|
mgl@1371
|
13123 |
+ (ss_minus:HI (match_operand:HI 1 "register_operand" "r")
|
mgl@1371
|
13124 |
+ (match_operand:HI 2 "register_operand" "r")))]
|
mgl@1371
|
13125 |
+ "TARGET_DSP"
|
mgl@1371
|
13126 |
+ "satsub.h\t%0, %1, %2"
|
mgl@1371
|
13127 |
+ [(set_attr "length" "4")
|
mgl@1371
|
13128 |
+ (set_attr "cc" "none")
|
mgl@1371
|
13129 |
+ (set_attr "type" "alu_sat")])
|
mgl@1371
|
13130 |
+
|
mgl@1371
|
13131 |
+
|
mgl@1371
|
13132 |
+;;=============================================================================
|
mgl@1371
|
13133 |
+;; smin
|
mgl@1371
|
13134 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
13135 |
+;; Set reg0 to the smallest value of reg1 and reg2. It is used for signed
|
mgl@1371
|
13136 |
+;; values in the registers.
|
mgl@1371
|
13137 |
+;;=============================================================================
|
mgl@1371
|
13138 |
+(define_insn "sminsi3"
|
mgl@1371
|
13139 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
13140 |
+ (smin:SI (match_operand:SI 1 "register_operand" "r")
|
mgl@1371
|
13141 |
+ (match_operand:SI 2 "register_operand" "r")))]
|
mgl@1371
|
13142 |
+ ""
|
mgl@1371
|
13143 |
+ "min %0, %1, %2"
|
mgl@1371
|
13144 |
+ [(set_attr "length" "4")
|
mgl@1371
|
13145 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
13146 |
+
|
mgl@1371
|
13147 |
+;;=============================================================================
|
mgl@1371
|
13148 |
+;; smax
|
mgl@1371
|
13149 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
13150 |
+;; Set reg0 to the largest value of reg1 and reg2. It is used for signed
|
mgl@1371
|
13151 |
+;; values in the registers.
|
mgl@1371
|
13152 |
+;;=============================================================================
|
mgl@1371
|
13153 |
+(define_insn "smaxsi3"
|
mgl@1371
|
13154 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
13155 |
+ (smax:SI (match_operand:SI 1 "register_operand" "r")
|
mgl@1371
|
13156 |
+ (match_operand:SI 2 "register_operand" "r")))]
|
mgl@1371
|
13157 |
+ ""
|
mgl@1371
|
13158 |
+ "max %0, %1, %2"
|
mgl@1371
|
13159 |
+ [(set_attr "length" "4")
|
mgl@1371
|
13160 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
13161 |
+
|
mgl@1371
|
13162 |
+
|
mgl@1371
|
13163 |
+
|
mgl@1371
|
13164 |
+;;=============================================================================
|
mgl@1371
|
13165 |
+;; Logical operations
|
mgl@1371
|
13166 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
13167 |
+
|
mgl@1371
|
13168 |
+
|
mgl@1371
|
13169 |
+;; Split up simple DImode logical operations. Simply perform the logical
|
mgl@1371
|
13170 |
+;; operation on the upper and lower halves of the registers.
|
mgl@1371
|
13171 |
+(define_split
|
mgl@1371
|
13172 |
+ [(set (match_operand:DI 0 "register_operand" "")
|
mgl@1371
|
13173 |
+ (match_operator:DI 6 "logical_binary_operator"
|
mgl@1371
|
13174 |
+ [(match_operand:DI 1 "register_operand" "")
|
mgl@1371
|
13175 |
+ (match_operand:DI 2 "register_operand" "")]))]
|
mgl@1371
|
13176 |
+ "reload_completed"
|
mgl@1371
|
13177 |
+ [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
|
mgl@1371
|
13178 |
+ (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
|
mgl@1371
|
13179 |
+ "
|
mgl@1371
|
13180 |
+ {
|
mgl@1371
|
13181 |
+ operands[3] = gen_highpart (SImode, operands[0]);
|
mgl@1371
|
13182 |
+ operands[0] = gen_lowpart (SImode, operands[0]);
|
mgl@1371
|
13183 |
+ operands[4] = gen_highpart (SImode, operands[1]);
|
mgl@1371
|
13184 |
+ operands[1] = gen_lowpart (SImode, operands[1]);
|
mgl@1371
|
13185 |
+ operands[5] = gen_highpart (SImode, operands[2]);
|
mgl@1371
|
13186 |
+ operands[2] = gen_lowpart (SImode, operands[2]);
|
mgl@1371
|
13187 |
+ }"
|
mgl@1371
|
13188 |
+)
|
mgl@1371
|
13189 |
+
|
mgl@1371
|
13190 |
+;;=============================================================================
|
mgl@1371
|
13191 |
+;; Logical operations with shifted operand
|
mgl@1371
|
13192 |
+;;=============================================================================
|
mgl@1371
|
13193 |
+(define_insn "<code>si_lshift"
|
mgl@1371
|
13194 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
13195 |
+ (logical:SI (match_operator:SI 4 "logical_shift_operator"
|
mgl@1371
|
13196 |
+ [(match_operand:SI 2 "register_operand" "r")
|
mgl@1371
|
13197 |
+ (match_operand:SI 3 "immediate_operand" "Ku05")])
|
mgl@1371
|
13198 |
+ (match_operand:SI 1 "register_operand" "r")))]
|
mgl@1371
|
13199 |
+ ""
|
mgl@1371
|
13200 |
+ {
|
mgl@1371
|
13201 |
+ if ( GET_CODE(operands[4]) == ASHIFT )
|
mgl@1371
|
13202 |
+ return "<logical_insn>\t%0, %1, %2 << %3";
|
mgl@1371
|
13203 |
+ else
|
mgl@1371
|
13204 |
+ return "<logical_insn>\t%0, %1, %2 >> %3";
|
mgl@1371
|
13205 |
+ }
|
mgl@1371
|
13206 |
+
|
mgl@1371
|
13207 |
+ [(set_attr "cc" "set_z")]
|
mgl@1371
|
13208 |
+)
|
mgl@1371
|
13209 |
+
|
mgl@1371
|
13210 |
+
|
mgl@1371
|
13211 |
+;;************************************************
|
mgl@1371
|
13212 |
+;; Peepholes for detecting logical operantions
|
mgl@1371
|
13213 |
+;; with shifted operands
|
mgl@1371
|
13214 |
+;;************************************************
|
mgl@1371
|
13215 |
+
|
mgl@1371
|
13216 |
+(define_peephole
|
mgl@1371
|
13217 |
+ [(set (match_operand:SI 3 "register_operand" "")
|
mgl@1371
|
13218 |
+ (match_operator:SI 5 "logical_shift_operator"
|
mgl@1371
|
13219 |
+ [(match_operand:SI 1 "register_operand" "")
|
mgl@1371
|
13220 |
+ (match_operand:SI 2 "immediate_operand" "")]))
|
mgl@1371
|
13221 |
+ (set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
13222 |
+ (logical:SI (match_operand:SI 4 "register_operand" "")
|
mgl@1371
|
13223 |
+ (match_dup 3)))]
|
mgl@1371
|
13224 |
+ "(dead_or_set_p(insn, operands[3])) || (REGNO(operands[3]) == REGNO(operands[0]))"
|
mgl@1371
|
13225 |
+ {
|
mgl@1371
|
13226 |
+ if ( GET_CODE(operands[5]) == ASHIFT )
|
mgl@1371
|
13227 |
+ return "<logical_insn>\t%0, %4, %1 << %2";
|
mgl@1371
|
13228 |
+ else
|
mgl@1371
|
13229 |
+ return "<logical_insn>\t%0, %4, %1 >> %2";
|
mgl@1371
|
13230 |
+ }
|
mgl@1371
|
13231 |
+ [(set_attr "cc" "set_z")]
|
mgl@1371
|
13232 |
+ )
|
mgl@1371
|
13233 |
+
|
mgl@1371
|
13234 |
+(define_peephole
|
mgl@1371
|
13235 |
+ [(set (match_operand:SI 3 "register_operand" "")
|
mgl@1371
|
13236 |
+ (match_operator:SI 5 "logical_shift_operator"
|
mgl@1371
|
13237 |
+ [(match_operand:SI 1 "register_operand" "")
|
mgl@1371
|
13238 |
+ (match_operand:SI 2 "immediate_operand" "")]))
|
mgl@1371
|
13239 |
+ (set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
13240 |
+ (logical:SI (match_dup 3)
|
mgl@1371
|
13241 |
+ (match_operand:SI 4 "register_operand" "")))]
|
mgl@1371
|
13242 |
+ "(dead_or_set_p(insn, operands[3])) || (REGNO(operands[3]) == REGNO(operands[0]))"
|
mgl@1371
|
13243 |
+ {
|
mgl@1371
|
13244 |
+ if ( GET_CODE(operands[5]) == ASHIFT )
|
mgl@1371
|
13245 |
+ return "<logical_insn>\t%0, %4, %1 << %2";
|
mgl@1371
|
13246 |
+ else
|
mgl@1371
|
13247 |
+ return "<logical_insn>\t%0, %4, %1 >> %2";
|
mgl@1371
|
13248 |
+ }
|
mgl@1371
|
13249 |
+ [(set_attr "cc" "set_z")]
|
mgl@1371
|
13250 |
+ )
|
mgl@1371
|
13251 |
+
|
mgl@1371
|
13252 |
+
|
mgl@1371
|
13253 |
+(define_peephole2
|
mgl@1371
|
13254 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
13255 |
+ (match_operator:SI 5 "logical_shift_operator"
|
mgl@1371
|
13256 |
+ [(match_operand:SI 1 "register_operand" "")
|
mgl@1371
|
13257 |
+ (match_operand:SI 2 "immediate_operand" "")]))
|
mgl@1371
|
13258 |
+ (set (match_operand:SI 3 "register_operand" "")
|
mgl@1371
|
13259 |
+ (logical:SI (match_operand:SI 4 "register_operand" "")
|
mgl@1371
|
13260 |
+ (match_dup 0)))]
|
mgl@1371
|
13261 |
+ "(peep2_reg_dead_p(2, operands[0])) || (REGNO(operands[3]) == REGNO(operands[0]))"
|
mgl@1371
|
13262 |
+
|
mgl@1371
|
13263 |
+ [(set (match_dup 3)
|
mgl@1371
|
13264 |
+ (logical:SI (match_op_dup:SI 5 [(match_dup 1) (match_dup 2)])
|
mgl@1371
|
13265 |
+ (match_dup 4)))]
|
mgl@1371
|
13266 |
+
|
mgl@1371
|
13267 |
+ ""
|
mgl@1371
|
13268 |
+)
|
mgl@1371
|
13269 |
+
|
mgl@1371
|
13270 |
+(define_peephole2
|
mgl@1371
|
13271 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
13272 |
+ (match_operator:SI 5 "logical_shift_operator"
|
mgl@1371
|
13273 |
+ [(match_operand:SI 1 "register_operand" "")
|
mgl@1371
|
13274 |
+ (match_operand:SI 2 "immediate_operand" "")]))
|
mgl@1371
|
13275 |
+ (set (match_operand:SI 3 "register_operand" "")
|
mgl@1371
|
13276 |
+ (logical:SI (match_dup 0)
|
mgl@1371
|
13277 |
+ (match_operand:SI 4 "register_operand" "")))]
|
mgl@1371
|
13278 |
+ "(peep2_reg_dead_p(2, operands[0])) || (REGNO(operands[3]) == REGNO(operands[0]))"
|
mgl@1371
|
13279 |
+
|
mgl@1371
|
13280 |
+ [(set (match_dup 3)
|
mgl@1371
|
13281 |
+ (logical:SI (match_op_dup:SI 5 [(match_dup 1) (match_dup 2)])
|
mgl@1371
|
13282 |
+ (match_dup 4)))]
|
mgl@1371
|
13283 |
+
|
mgl@1371
|
13284 |
+ ""
|
mgl@1371
|
13285 |
+)
|
mgl@1371
|
13286 |
+
|
mgl@1371
|
13287 |
+
|
mgl@1371
|
13288 |
+;;=============================================================================
|
mgl@1371
|
13289 |
+;; and
|
mgl@1371
|
13290 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
13291 |
+;; Store the result after a bitwise logical-and between reg0 and reg2 in reg0.
|
mgl@1371
|
13292 |
+;;=============================================================================
|
mgl@1371
|
13293 |
+
|
mgl@1371
|
13294 |
+(define_insn "andnsi"
|
mgl@1371
|
13295 |
+ [(set (match_operand:SI 0 "register_operand" "+r")
|
mgl@1371
|
13296 |
+ (and:SI (match_dup 0)
|
mgl@1371
|
13297 |
+ (not:SI (match_operand:SI 1 "register_operand" "r"))))]
|
mgl@1371
|
13298 |
+ ""
|
mgl@1371
|
13299 |
+ "andn %0, %1"
|
mgl@1371
|
13300 |
+ [(set_attr "cc" "set_z")
|
mgl@1371
|
13301 |
+ (set_attr "length" "2")]
|
mgl@1371
|
13302 |
+)
|
mgl@1371
|
13303 |
+
|
mgl@1371
|
13304 |
+
|
mgl@1371
|
13305 |
+(define_insn "andsi3"
|
mgl@1371
|
13306 |
+ [(set (match_operand:SI 0 "avr32_rmw_memory_or_register_operand" "=Y,r,r,r, r, r,r,r,r,r")
|
mgl@1371
|
13307 |
+ (and:SI (match_operand:SI 1 "avr32_rmw_memory_or_register_operand" "%0,r,0,0, 0, 0,0,0,0,r" )
|
mgl@1371
|
13308 |
+ (match_operand:SI 2 "nonmemory_operand" " N,M,N,Ku16,Ks17,J,L,r,i,r")))]
|
mgl@1371
|
13309 |
+ ""
|
mgl@1371
|
13310 |
+ "@
|
mgl@1371
|
13311 |
+ memc\t%0, %z2
|
mgl@1371
|
13312 |
+ bfextu\t%0, %1, 0, %z2
|
mgl@1371
|
13313 |
+ cbr\t%0, %z2
|
mgl@1371
|
13314 |
+ andl\t%0, %2, COH
|
mgl@1371
|
13315 |
+ andl\t%0, lo(%2)
|
mgl@1371
|
13316 |
+ andh\t%0, hi(%2), COH
|
mgl@1371
|
13317 |
+ andh\t%0, hi(%2)
|
mgl@1371
|
13318 |
+ and\t%0, %2
|
mgl@1371
|
13319 |
+ andh\t%0, hi(%2)\;andl\t%0, lo(%2)
|
mgl@1371
|
13320 |
+ and\t%0, %1, %2"
|
mgl@1371
|
13321 |
+
|
mgl@1371
|
13322 |
+ [(set_attr "length" "4,4,2,4,4,4,4,2,8,4")
|
mgl@1371
|
13323 |
+ (set_attr "cc" "none,set_z,set_z,set_z,set_z,set_z,set_z,set_z,set_z,set_z")])
|
mgl@1371
|
13324 |
+
|
mgl@1371
|
13325 |
+(define_insn "anddi3"
|
mgl@1371
|
13326 |
+ [(set (match_operand:DI 0 "register_operand" "=&r,&r")
|
mgl@1371
|
13327 |
+ (and:DI (match_operand:DI 1 "register_operand" "%0,r")
|
mgl@1371
|
13328 |
+ (match_operand:DI 2 "register_operand" "r,r")))]
|
mgl@1371
|
13329 |
+ ""
|
mgl@1371
|
13330 |
+ "#"
|
mgl@1371
|
13331 |
+ [(set_attr "length" "8")
|
mgl@1371
|
13332 |
+ (set_attr "cc" "clobber")]
|
mgl@1371
|
13333 |
+)
|
mgl@1371
|
13334 |
+
|
mgl@1371
|
13335 |
+;;=============================================================================
|
mgl@1371
|
13336 |
+;; or
|
mgl@1371
|
13337 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
13338 |
+;; Store the result after a bitwise inclusive-or between reg0 and reg2 in reg0.
|
mgl@1371
|
13339 |
+;;=============================================================================
|
mgl@1371
|
13340 |
+
|
mgl@1371
|
13341 |
+(define_insn "iorsi3"
|
mgl@1371
|
13342 |
+ [(set (match_operand:SI 0 "avr32_rmw_memory_or_register_operand" "=Y,r,r, r,r,r,r")
|
mgl@1371
|
13343 |
+ (ior:SI (match_operand:SI 1 "avr32_rmw_memory_or_register_operand" "%0,0,0, 0,0,0,r" )
|
mgl@1371
|
13344 |
+ (match_operand:SI 2 "nonmemory_operand" " O,O,Ku16,J,r,i,r")))]
|
mgl@1371
|
13345 |
+ ""
|
mgl@1371
|
13346 |
+ "@
|
mgl@1371
|
13347 |
+ mems\t%0, %p2
|
mgl@1371
|
13348 |
+ sbr\t%0, %p2
|
mgl@1371
|
13349 |
+ orl\t%0, %2
|
mgl@1371
|
13350 |
+ orh\t%0, hi(%2)
|
mgl@1371
|
13351 |
+ or\t%0, %2
|
mgl@1371
|
13352 |
+ orh\t%0, hi(%2)\;orl\t%0, lo(%2)
|
mgl@1371
|
13353 |
+ or\t%0, %1, %2"
|
mgl@1371
|
13354 |
+
|
mgl@1371
|
13355 |
+ [(set_attr "length" "4,2,4,4,2,8,4")
|
mgl@1371
|
13356 |
+ (set_attr "cc" "none,set_z,set_z,set_z,set_z,set_z,set_z")])
|
mgl@1371
|
13357 |
+
|
mgl@1371
|
13358 |
+
|
mgl@1371
|
13359 |
+(define_insn "iordi3"
|
mgl@1371
|
13360 |
+ [(set (match_operand:DI 0 "register_operand" "=&r,&r")
|
mgl@1371
|
13361 |
+ (ior:DI (match_operand:DI 1 "register_operand" "%0,r")
|
mgl@1371
|
13362 |
+ (match_operand:DI 2 "register_operand" "r,r")))]
|
mgl@1371
|
13363 |
+ ""
|
mgl@1371
|
13364 |
+ "#"
|
mgl@1371
|
13365 |
+ [(set_attr "length" "8")
|
mgl@1371
|
13366 |
+ (set_attr "cc" "clobber")]
|
mgl@1371
|
13367 |
+)
|
mgl@1371
|
13368 |
+
|
mgl@1371
|
13369 |
+;;=============================================================================
|
mgl@1371
|
13370 |
+;; xor bytes
|
mgl@1371
|
13371 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
13372 |
+;; Store the result after a bitwise exclusive-or between reg0 and reg2 in reg0.
|
mgl@1371
|
13373 |
+;;=============================================================================
|
mgl@1371
|
13374 |
+
|
mgl@1371
|
13375 |
+(define_insn "xorsi3"
|
mgl@1371
|
13376 |
+ [(set (match_operand:SI 0 "avr32_rmw_memory_or_register_operand" "=Y,r, r,r,r,r")
|
mgl@1371
|
13377 |
+ (xor:SI (match_operand:SI 1 "avr32_rmw_memory_or_register_operand" "%0,0, 0,0,0,r" )
|
mgl@1371
|
13378 |
+ (match_operand:SI 2 "nonmemory_operand" " O,Ku16,J,r,i,r")))]
|
mgl@1371
|
13379 |
+ ""
|
mgl@1371
|
13380 |
+ "@
|
mgl@1371
|
13381 |
+ memt\t%0, %p2
|
mgl@1371
|
13382 |
+ eorl\t%0, %2
|
mgl@1371
|
13383 |
+ eorh\t%0, hi(%2)
|
mgl@1371
|
13384 |
+ eor\t%0, %2
|
mgl@1371
|
13385 |
+ eorh\t%0, hi(%2)\;eorl\t%0, lo(%2)
|
mgl@1371
|
13386 |
+ eor\t%0, %1, %2"
|
mgl@1371
|
13387 |
+
|
mgl@1371
|
13388 |
+ [(set_attr "length" "4,4,4,2,8,4")
|
mgl@1371
|
13389 |
+ (set_attr "cc" "none,set_z,set_z,set_z,set_z,set_z")])
|
mgl@1371
|
13390 |
+
|
mgl@1371
|
13391 |
+
|
mgl@1371
|
13392 |
+(define_insn "xordi3"
|
mgl@1371
|
13393 |
+ [(set (match_operand:DI 0 "register_operand" "=&r,&r")
|
mgl@1371
|
13394 |
+ (xor:DI (match_operand:DI 1 "register_operand" "%0,r")
|
mgl@1371
|
13395 |
+ (match_operand:DI 2 "register_operand" "r,r")))]
|
mgl@1371
|
13396 |
+ ""
|
mgl@1371
|
13397 |
+ "#"
|
mgl@1371
|
13398 |
+ [(set_attr "length" "8")
|
mgl@1371
|
13399 |
+ (set_attr "cc" "clobber")]
|
mgl@1371
|
13400 |
+)
|
mgl@1371
|
13401 |
+
|
mgl@1371
|
13402 |
+;;=============================================================================
|
mgl@1371
|
13403 |
+;; Three operand predicable insns
|
mgl@1371
|
13404 |
+;;=============================================================================
|
mgl@1371
|
13405 |
+
|
mgl@1371
|
13406 |
+(define_insn "<predicable_insn3><mode>_predicable"
|
mgl@1371
|
13407 |
+ [(set (match_operand:INTM 0 "register_operand" "=r")
|
mgl@1371
|
13408 |
+ (predicable_op3:INTM (match_operand:INTM 1 "register_operand" "<predicable_commutative3>r")
|
mgl@1371
|
13409 |
+ (match_operand:INTM 2 "register_operand" "r")))]
|
mgl@1371
|
13410 |
+ "TARGET_V2_INSNS"
|
mgl@1371
|
13411 |
+ "<predicable_insn3>%?\t%0, %1, %2"
|
mgl@1371
|
13412 |
+ [(set_attr "length" "4")
|
mgl@1371
|
13413 |
+ (set_attr "cc" "cmp_cond_insn")
|
mgl@1371
|
13414 |
+ (set_attr "predicable" "yes")]
|
mgl@1371
|
13415 |
+)
|
mgl@1371
|
13416 |
+
|
mgl@1371
|
13417 |
+(define_insn_and_split "<predicable_insn3><mode>_imm_clobber_predicable"
|
mgl@1371
|
13418 |
+ [(parallel
|
mgl@1371
|
13419 |
+ [(set (match_operand:INTM 0 "register_operand" "=r")
|
mgl@1371
|
13420 |
+ (predicable_op3:INTM (match_operand:INTM 1 "register_operand" "<predicable_commutative3>r")
|
mgl@1371
|
13421 |
+ (match_operand:INTM 2 "avr32_mov_immediate_operand" "JKs21")))
|
mgl@1371
|
13422 |
+ (clobber (match_operand:INTM 3 "register_operand" "=&r"))])]
|
mgl@1371
|
13423 |
+ "TARGET_V2_INSNS"
|
mgl@1371
|
13424 |
+ {
|
mgl@1371
|
13425 |
+ if ( current_insn_predicate != NULL_RTX )
|
mgl@1371
|
13426 |
+ {
|
mgl@1371
|
13427 |
+ if ( avr32_const_ok_for_constraint_p (INTVAL (operands[2]), 'K', "Ks08") )
|
mgl@1371
|
13428 |
+ return "%! mov%?\t%3, %2\;<predicable_insn3>%?\t%0, %1, %3";
|
mgl@1371
|
13429 |
+ else if ( avr32_const_ok_for_constraint_p (INTVAL (operands[2]), 'K', "Ks21") )
|
mgl@1371
|
13430 |
+ return "%! mov\t%3, %2\;<predicable_insn3>%?\t%0, %1, %3";
|
mgl@1371
|
13431 |
+ else
|
mgl@1371
|
13432 |
+ return "%! movh\t%3, hi(%2)\;<predicable_insn3>%?\t%0, %1, %3";
|
mgl@1371
|
13433 |
+ }
|
mgl@1371
|
13434 |
+ else
|
mgl@1371
|
13435 |
+ {
|
mgl@1371
|
13436 |
+ if ( !avr32_cond_imm_clobber_splittable (insn, operands) )
|
mgl@1371
|
13437 |
+ {
|
mgl@1371
|
13438 |
+ if ( avr32_const_ok_for_constraint_p (INTVAL (operands[2]), 'K', "Ks08") )
|
mgl@1371
|
13439 |
+ return "mov%?\t%3, %2\;<predicable_insn3>%?\t%0, %1, %3";
|
mgl@1371
|
13440 |
+ else if ( avr32_const_ok_for_constraint_p (INTVAL (operands[2]), 'K', "Ks21") )
|
mgl@1371
|
13441 |
+ return "mov\t%3, %2\;<predicable_insn3>%?\t%0, %1, %3";
|
mgl@1371
|
13442 |
+ else
|
mgl@1371
|
13443 |
+ return "movh\t%3, hi(%2)\;<predicable_insn3>%?\t%0, %1, %3";
|
mgl@1371
|
13444 |
+ }
|
mgl@1371
|
13445 |
+ return "#";
|
mgl@1371
|
13446 |
+ }
|
mgl@1371
|
13447 |
+
|
mgl@1371
|
13448 |
+ }
|
mgl@1371
|
13449 |
+ ;; If we find out that we could not actually do if-conversion on the block
|
mgl@1371
|
13450 |
+ ;; containing this insn we convert it back to normal immediate format
|
mgl@1371
|
13451 |
+ ;; to avoid outputing a redundant move insn
|
mgl@1371
|
13452 |
+ ;; Do not split until after we have checked if we can make the insn
|
mgl@1371
|
13453 |
+ ;; conditional.
|
mgl@1371
|
13454 |
+ "(GET_CODE (PATTERN (insn)) != COND_EXEC
|
mgl@1371
|
13455 |
+ && cfun->machine->ifcvt_after_reload
|
mgl@1371
|
13456 |
+ && avr32_cond_imm_clobber_splittable (insn, operands))"
|
mgl@1371
|
13457 |
+ [(set (match_dup 0)
|
mgl@1371
|
13458 |
+ (predicable_op3:INTM (match_dup 1)
|
mgl@1371
|
13459 |
+ (match_dup 2)))]
|
mgl@1371
|
13460 |
+ ""
|
mgl@1371
|
13461 |
+ [(set_attr "length" "8")
|
mgl@1371
|
13462 |
+ (set_attr "cc" "cmp_cond_insn")
|
mgl@1371
|
13463 |
+ (set_attr "predicable" "yes")]
|
mgl@1371
|
13464 |
+ )
|
mgl@1371
|
13465 |
+
|
mgl@1371
|
13466 |
+
|
mgl@1371
|
13467 |
+;;=============================================================================
|
mgl@1371
|
13468 |
+;; Zero extend predicable insns
|
mgl@1371
|
13469 |
+;;=============================================================================
|
mgl@1371
|
13470 |
+(define_insn_and_split "zero_extendhisi_clobber_predicable"
|
mgl@1371
|
13471 |
+ [(parallel
|
mgl@1371
|
13472 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
13473 |
+ (zero_extend:SI (match_operand:HI 1 "register_operand" "r")))
|
mgl@1371
|
13474 |
+ (clobber (match_operand:SI 2 "register_operand" "=&r"))])]
|
mgl@1371
|
13475 |
+ "TARGET_V2_INSNS"
|
mgl@1371
|
13476 |
+ {
|
mgl@1371
|
13477 |
+ if ( current_insn_predicate != NULL_RTX )
|
mgl@1371
|
13478 |
+ {
|
mgl@1371
|
13479 |
+ return "%! mov\t%2, 0xffff\;and%?\t%0, %1, %2";
|
mgl@1371
|
13480 |
+ }
|
mgl@1371
|
13481 |
+ else
|
mgl@1371
|
13482 |
+ {
|
mgl@1371
|
13483 |
+ return "#";
|
mgl@1371
|
13484 |
+ }
|
mgl@1371
|
13485 |
+
|
mgl@1371
|
13486 |
+ }
|
mgl@1371
|
13487 |
+ ;; If we find out that we could not actually do if-conversion on the block
|
mgl@1371
|
13488 |
+ ;; containing this insn we convert it back to normal immediate format
|
mgl@1371
|
13489 |
+ ;; to avoid outputing a redundant move insn
|
mgl@1371
|
13490 |
+ ;; Do not split until after we have checked if we can make the insn
|
mgl@1371
|
13491 |
+ ;; conditional.
|
mgl@1371
|
13492 |
+ "(GET_CODE (PATTERN (insn)) != COND_EXEC
|
mgl@1371
|
13493 |
+ && cfun->machine->ifcvt_after_reload)"
|
mgl@1371
|
13494 |
+ [(set (match_dup 0)
|
mgl@1371
|
13495 |
+ (zero_extend:SI (match_dup 1)))]
|
mgl@1371
|
13496 |
+ ""
|
mgl@1371
|
13497 |
+ [(set_attr "length" "8")
|
mgl@1371
|
13498 |
+ (set_attr "cc" "cmp_cond_insn")
|
mgl@1371
|
13499 |
+ (set_attr "predicable" "yes")]
|
mgl@1371
|
13500 |
+ )
|
mgl@1371
|
13501 |
+
|
mgl@1371
|
13502 |
+(define_insn_and_split "zero_extendqisi_clobber_predicable"
|
mgl@1371
|
13503 |
+ [(parallel
|
mgl@1371
|
13504 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
13505 |
+ (zero_extend:SI (match_operand:QI 1 "register_operand" "r")))
|
mgl@1371
|
13506 |
+ (clobber (match_operand:SI 2 "register_operand" "=&r"))])]
|
mgl@1371
|
13507 |
+ "TARGET_V2_INSNS"
|
mgl@1371
|
13508 |
+ {
|
mgl@1371
|
13509 |
+ if ( current_insn_predicate != NULL_RTX )
|
mgl@1371
|
13510 |
+ {
|
mgl@1371
|
13511 |
+ return "%! mov\t%2, 0xff\;and%?\t%0, %1, %2";
|
mgl@1371
|
13512 |
+ }
|
mgl@1371
|
13513 |
+ else
|
mgl@1371
|
13514 |
+ {
|
mgl@1371
|
13515 |
+ return "#";
|
mgl@1371
|
13516 |
+ }
|
mgl@1371
|
13517 |
+
|
mgl@1371
|
13518 |
+ }
|
mgl@1371
|
13519 |
+ ;; If we find out that we could not actually do if-conversion on the block
|
mgl@1371
|
13520 |
+ ;; containing this insn we convert it back to normal immediate format
|
mgl@1371
|
13521 |
+ ;; to avoid outputing a redundant move insn
|
mgl@1371
|
13522 |
+ ;; Do not split until after we have checked if we can make the insn
|
mgl@1371
|
13523 |
+ ;; conditional.
|
mgl@1371
|
13524 |
+ "(GET_CODE (PATTERN (insn)) != COND_EXEC
|
mgl@1371
|
13525 |
+ && cfun->machine->ifcvt_after_reload)"
|
mgl@1371
|
13526 |
+ [(set (match_dup 0)
|
mgl@1371
|
13527 |
+ (zero_extend:SI (match_dup 1)))]
|
mgl@1371
|
13528 |
+ ""
|
mgl@1371
|
13529 |
+ [(set_attr "length" "8")
|
mgl@1371
|
13530 |
+ (set_attr "cc" "cmp_cond_insn")
|
mgl@1371
|
13531 |
+ (set_attr "predicable" "yes")]
|
mgl@1371
|
13532 |
+ )
|
mgl@1371
|
13533 |
+
|
mgl@1371
|
13534 |
+(define_insn_and_split "zero_extendqihi_clobber_predicable"
|
mgl@1371
|
13535 |
+ [(parallel
|
mgl@1371
|
13536 |
+ [(set (match_operand:HI 0 "register_operand" "=r")
|
mgl@1371
|
13537 |
+ (zero_extend:HI (match_operand:QI 1 "register_operand" "r")))
|
mgl@1371
|
13538 |
+ (clobber (match_operand:SI 2 "register_operand" "=&r"))])]
|
mgl@1371
|
13539 |
+ "TARGET_V2_INSNS"
|
mgl@1371
|
13540 |
+ {
|
mgl@1371
|
13541 |
+ if ( current_insn_predicate != NULL_RTX )
|
mgl@1371
|
13542 |
+ {
|
mgl@1371
|
13543 |
+ return "%! mov\t%2, 0xff\;and%?\t%0, %1, %2";
|
mgl@1371
|
13544 |
+ }
|
mgl@1371
|
13545 |
+ else
|
mgl@1371
|
13546 |
+ {
|
mgl@1371
|
13547 |
+ return "#";
|
mgl@1371
|
13548 |
+ }
|
mgl@1371
|
13549 |
+
|
mgl@1371
|
13550 |
+ }
|
mgl@1371
|
13551 |
+ ;; If we find out that we could not actually do if-conversion on the block
|
mgl@1371
|
13552 |
+ ;; containing this insn we convert it back to normal immediate format
|
mgl@1371
|
13553 |
+ ;; to avoid outputing a redundant move insn
|
mgl@1371
|
13554 |
+ ;; Do not split until after we have checked if we can make the insn
|
mgl@1371
|
13555 |
+ ;; conditional.
|
mgl@1371
|
13556 |
+ "(GET_CODE (PATTERN (insn)) != COND_EXEC
|
mgl@1371
|
13557 |
+ && cfun->machine->ifcvt_after_reload)"
|
mgl@1371
|
13558 |
+ [(set (match_dup 0)
|
mgl@1371
|
13559 |
+ (zero_extend:HI (match_dup 1)))]
|
mgl@1371
|
13560 |
+ ""
|
mgl@1371
|
13561 |
+ [(set_attr "length" "8")
|
mgl@1371
|
13562 |
+ (set_attr "cc" "cmp_cond_insn")
|
mgl@1371
|
13563 |
+ (set_attr "predicable" "yes")]
|
mgl@1371
|
13564 |
+ )
|
mgl@1371
|
13565 |
+;;=============================================================================
|
mgl@1371
|
13566 |
+;; divmod
|
mgl@1371
|
13567 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
13568 |
+;; Signed division that produces both a quotient and a remainder.
|
mgl@1371
|
13569 |
+;;=============================================================================
|
mgl@1371
|
13570 |
+(define_expand "divmodsi4"
|
mgl@1371
|
13571 |
+ [(parallel [
|
mgl@1371
|
13572 |
+ (parallel [
|
mgl@1371
|
13573 |
+ (set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
13574 |
+ (div:SI (match_operand:SI 1 "register_operand" "r")
|
mgl@1371
|
13575 |
+ (match_operand:SI 2 "register_operand" "r")))
|
mgl@1371
|
13576 |
+ (set (match_operand:SI 3 "register_operand" "=r")
|
mgl@1371
|
13577 |
+ (mod:SI (match_dup 1)
|
mgl@1371
|
13578 |
+ (match_dup 2)))])
|
mgl@1371
|
13579 |
+ (use (match_dup 4))])]
|
mgl@1371
|
13580 |
+ ""
|
mgl@1371
|
13581 |
+ {
|
mgl@1371
|
13582 |
+ if (! no_new_pseudos) {
|
mgl@1371
|
13583 |
+ operands[4] = gen_reg_rtx (DImode);
|
mgl@1371
|
13584 |
+
|
mgl@1371
|
13585 |
+ emit_insn(gen_divmodsi4_internal(operands[4],operands[1],operands[2]));
|
mgl@1371
|
13586 |
+ emit_move_insn(operands[0], gen_rtx_SUBREG( SImode, operands[4], 4));
|
mgl@1371
|
13587 |
+ emit_move_insn(operands[3], gen_rtx_SUBREG( SImode, operands[4], 0));
|
mgl@1371
|
13588 |
+
|
mgl@1371
|
13589 |
+ DONE;
|
mgl@1371
|
13590 |
+ } else {
|
mgl@1371
|
13591 |
+ FAIL;
|
mgl@1371
|
13592 |
+ }
|
mgl@1371
|
13593 |
+
|
mgl@1371
|
13594 |
+ })
|
mgl@1371
|
13595 |
+
|
mgl@1371
|
13596 |
+
|
mgl@1371
|
13597 |
+(define_insn "divmodsi4_internal"
|
mgl@1371
|
13598 |
+ [(set (match_operand:DI 0 "register_operand" "=r")
|
mgl@1371
|
13599 |
+ (unspec:DI [(match_operand:SI 1 "register_operand" "r")
|
mgl@1371
|
13600 |
+ (match_operand:SI 2 "register_operand" "r")]
|
mgl@1371
|
13601 |
+ UNSPEC_DIVMODSI4_INTERNAL))]
|
mgl@1371
|
13602 |
+ ""
|
mgl@1371
|
13603 |
+ "divs %0, %1, %2"
|
mgl@1371
|
13604 |
+ [(set_attr "type" "div")
|
mgl@1371
|
13605 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
13606 |
+
|
mgl@1371
|
13607 |
+
|
mgl@1371
|
13608 |
+;;=============================================================================
|
mgl@1371
|
13609 |
+;; udivmod
|
mgl@1371
|
13610 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
13611 |
+;; Unsigned division that produces both a quotient and a remainder.
|
mgl@1371
|
13612 |
+;;=============================================================================
|
mgl@1371
|
13613 |
+(define_expand "udivmodsi4"
|
mgl@1371
|
13614 |
+ [(parallel [
|
mgl@1371
|
13615 |
+ (parallel [
|
mgl@1371
|
13616 |
+ (set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
13617 |
+ (udiv:SI (match_operand:SI 1 "register_operand" "r")
|
mgl@1371
|
13618 |
+ (match_operand:SI 2 "register_operand" "r")))
|
mgl@1371
|
13619 |
+ (set (match_operand:SI 3 "register_operand" "=r")
|
mgl@1371
|
13620 |
+ (umod:SI (match_dup 1)
|
mgl@1371
|
13621 |
+ (match_dup 2)))])
|
mgl@1371
|
13622 |
+ (use (match_dup 4))])]
|
mgl@1371
|
13623 |
+ ""
|
mgl@1371
|
13624 |
+ {
|
mgl@1371
|
13625 |
+ if (! no_new_pseudos) {
|
mgl@1371
|
13626 |
+ operands[4] = gen_reg_rtx (DImode);
|
mgl@1371
|
13627 |
+
|
mgl@1371
|
13628 |
+ emit_insn(gen_udivmodsi4_internal(operands[4],operands[1],operands[2]));
|
mgl@1371
|
13629 |
+ emit_move_insn(operands[0], gen_rtx_SUBREG( SImode, operands[4], 4));
|
mgl@1371
|
13630 |
+ emit_move_insn(operands[3], gen_rtx_SUBREG( SImode, operands[4], 0));
|
mgl@1371
|
13631 |
+
|
mgl@1371
|
13632 |
+ DONE;
|
mgl@1371
|
13633 |
+ } else {
|
mgl@1371
|
13634 |
+ FAIL;
|
mgl@1371
|
13635 |
+ }
|
mgl@1371
|
13636 |
+ })
|
mgl@1371
|
13637 |
+
|
mgl@1371
|
13638 |
+(define_insn "udivmodsi4_internal"
|
mgl@1371
|
13639 |
+ [(set (match_operand:DI 0 "register_operand" "=r")
|
mgl@1371
|
13640 |
+ (unspec:DI [(match_operand:SI 1 "register_operand" "r")
|
mgl@1371
|
13641 |
+ (match_operand:SI 2 "register_operand" "r")]
|
mgl@1371
|
13642 |
+ UNSPEC_UDIVMODSI4_INTERNAL))]
|
mgl@1371
|
13643 |
+ ""
|
mgl@1371
|
13644 |
+ "divu %0, %1, %2"
|
mgl@1371
|
13645 |
+ [(set_attr "type" "div")
|
mgl@1371
|
13646 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
13647 |
+
|
mgl@1371
|
13648 |
+
|
mgl@1371
|
13649 |
+;;=============================================================================
|
mgl@1371
|
13650 |
+;; Arithmetic-shift left
|
mgl@1371
|
13651 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
13652 |
+;; Arithmetic-shift reg0 left by reg2 or immediate value.
|
mgl@1371
|
13653 |
+;;=============================================================================
|
mgl@1371
|
13654 |
+
|
mgl@1371
|
13655 |
+(define_insn "ashlsi3"
|
mgl@1371
|
13656 |
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r")
|
mgl@1371
|
13657 |
+ (ashift:SI (match_operand:SI 1 "register_operand" "r,0,r")
|
mgl@1371
|
13658 |
+ (match_operand:SI 2 "nonmemory_operand" "r,Ku05,Ku05")))]
|
mgl@1371
|
13659 |
+ ""
|
mgl@1371
|
13660 |
+ "@
|
mgl@1371
|
13661 |
+ lsl %0, %1, %2
|
mgl@1371
|
13662 |
+ lsl %0, %2
|
mgl@1371
|
13663 |
+ lsl %0, %1, %2"
|
mgl@1371
|
13664 |
+ [(set_attr "length" "4,2,4")
|
mgl@1371
|
13665 |
+ (set_attr "cc" "set_ncz")])
|
mgl@1371
|
13666 |
+
|
mgl@1371
|
13667 |
+;;=============================================================================
|
mgl@1371
|
13668 |
+;; Arithmetic-shift right
|
mgl@1371
|
13669 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
13670 |
+;; Arithmetic-shift reg0 right by an immediate value.
|
mgl@1371
|
13671 |
+;;=============================================================================
|
mgl@1371
|
13672 |
+
|
mgl@1371
|
13673 |
+(define_insn "ashrsi3"
|
mgl@1371
|
13674 |
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r")
|
mgl@1371
|
13675 |
+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "r,0,r")
|
mgl@1371
|
13676 |
+ (match_operand:SI 2 "nonmemory_operand" "r,Ku05,Ku05")))]
|
mgl@1371
|
13677 |
+ ""
|
mgl@1371
|
13678 |
+ "@
|
mgl@1371
|
13679 |
+ asr %0, %1, %2
|
mgl@1371
|
13680 |
+ asr %0, %2
|
mgl@1371
|
13681 |
+ asr %0, %1, %2"
|
mgl@1371
|
13682 |
+ [(set_attr "length" "4,2,4")
|
mgl@1371
|
13683 |
+ (set_attr "cc" "set_ncz")])
|
mgl@1371
|
13684 |
+
|
mgl@1371
|
13685 |
+;;=============================================================================
|
mgl@1371
|
13686 |
+;; Logical shift right
|
mgl@1371
|
13687 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
13688 |
+;; Logical shift reg0 right by an immediate value.
|
mgl@1371
|
13689 |
+;;=============================================================================
|
mgl@1371
|
13690 |
+
|
mgl@1371
|
13691 |
+(define_insn "lshrsi3"
|
mgl@1371
|
13692 |
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r")
|
mgl@1371
|
13693 |
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,0,r")
|
mgl@1371
|
13694 |
+ (match_operand:SI 2 "nonmemory_operand" "r,Ku05,Ku05")))]
|
mgl@1371
|
13695 |
+ ""
|
mgl@1371
|
13696 |
+ "@
|
mgl@1371
|
13697 |
+ lsr %0, %1, %2
|
mgl@1371
|
13698 |
+ lsr %0, %2
|
mgl@1371
|
13699 |
+ lsr %0, %1, %2"
|
mgl@1371
|
13700 |
+ [(set_attr "length" "4,2,4")
|
mgl@1371
|
13701 |
+ (set_attr "cc" "set_ncz")])
|
mgl@1371
|
13702 |
+
|
mgl@1371
|
13703 |
+
|
mgl@1371
|
13704 |
+;;=============================================================================
|
mgl@1371
|
13705 |
+;; neg
|
mgl@1371
|
13706 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
13707 |
+;; Negate operand 1 and store the result in operand 0.
|
mgl@1371
|
13708 |
+;;=============================================================================
|
mgl@1371
|
13709 |
+(define_insn "negsi2"
|
mgl@1371
|
13710 |
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
|
mgl@1371
|
13711 |
+ (neg:SI (match_operand:SI 1 "register_operand" "0,r")))]
|
mgl@1371
|
13712 |
+ ""
|
mgl@1371
|
13713 |
+ "@
|
mgl@1371
|
13714 |
+ neg\t%0
|
mgl@1371
|
13715 |
+ rsub\t%0, %1, 0"
|
mgl@1371
|
13716 |
+ [(set_attr "length" "2,4")
|
mgl@1371
|
13717 |
+ (set_attr "cc" "set_vncz")])
|
mgl@1371
|
13718 |
+
|
mgl@1371
|
13719 |
+(define_insn "negsi2_predicable"
|
mgl@1371
|
13720 |
+ [(set (match_operand:SI 0 "register_operand" "+r")
|
mgl@1371
|
13721 |
+ (neg:SI (match_dup 0)))]
|
mgl@1371
|
13722 |
+ "TARGET_V2_INSNS"
|
mgl@1371
|
13723 |
+ "rsub%?\t%0, 0"
|
mgl@1371
|
13724 |
+ [(set_attr "length" "4")
|
mgl@1371
|
13725 |
+ (set_attr "cc" "cmp_cond_insn")
|
mgl@1371
|
13726 |
+ (set_attr "predicable" "yes")])
|
mgl@1371
|
13727 |
+
|
mgl@1371
|
13728 |
+;;=============================================================================
|
mgl@1371
|
13729 |
+;; abs
|
mgl@1371
|
13730 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
13731 |
+;; Store the absolute value of operand 1 into operand 0.
|
mgl@1371
|
13732 |
+;;=============================================================================
|
mgl@1371
|
13733 |
+(define_insn "abssi2"
|
mgl@1371
|
13734 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
13735 |
+ (abs:SI (match_operand:SI 1 "register_operand" "0")))]
|
mgl@1371
|
13736 |
+ ""
|
mgl@1371
|
13737 |
+ "abs\t%0"
|
mgl@1371
|
13738 |
+ [(set_attr "length" "2")
|
mgl@1371
|
13739 |
+ (set_attr "cc" "set_z")])
|
mgl@1371
|
13740 |
+
|
mgl@1371
|
13741 |
+
|
mgl@1371
|
13742 |
+;;=============================================================================
|
mgl@1371
|
13743 |
+;; one_cmpl
|
mgl@1371
|
13744 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
13745 |
+;; Store the bitwise-complement of operand 1 into operand 0.
|
mgl@1371
|
13746 |
+;;=============================================================================
|
mgl@1371
|
13747 |
+
|
mgl@1371
|
13748 |
+(define_insn "one_cmplsi2"
|
mgl@1371
|
13749 |
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
|
mgl@1371
|
13750 |
+ (not:SI (match_operand:SI 1 "register_operand" "0,r")))]
|
mgl@1371
|
13751 |
+ ""
|
mgl@1371
|
13752 |
+ "@
|
mgl@1371
|
13753 |
+ com\t%0
|
mgl@1371
|
13754 |
+ rsub\t%0, %1, -1"
|
mgl@1371
|
13755 |
+ [(set_attr "length" "2,4")
|
mgl@1371
|
13756 |
+ (set_attr "cc" "set_z")])
|
mgl@1371
|
13757 |
+
|
mgl@1371
|
13758 |
+
|
mgl@1371
|
13759 |
+(define_insn "one_cmplsi2_predicable"
|
mgl@1371
|
13760 |
+ [(set (match_operand:SI 0 "register_operand" "+r")
|
mgl@1371
|
13761 |
+ (not:SI (match_dup 0)))]
|
mgl@1371
|
13762 |
+ "TARGET_V2_INSNS"
|
mgl@1371
|
13763 |
+ "rsub%?\t%0, -1"
|
mgl@1371
|
13764 |
+ [(set_attr "length" "4")
|
mgl@1371
|
13765 |
+ (set_attr "cc" "cmp_cond_insn")
|
mgl@1371
|
13766 |
+ (set_attr "predicable" "yes")])
|
mgl@1371
|
13767 |
+
|
mgl@1371
|
13768 |
+
|
mgl@1371
|
13769 |
+;;=============================================================================
|
mgl@1371
|
13770 |
+;; Bit load
|
mgl@1371
|
13771 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
13772 |
+;; Load a bit into Z and C flags
|
mgl@1371
|
13773 |
+;;=============================================================================
|
mgl@1371
|
13774 |
+(define_insn "bldsi"
|
mgl@1371
|
13775 |
+ [(set (cc0)
|
mgl@1371
|
13776 |
+ (and:SI (match_operand:SI 0 "register_operand" "r")
|
mgl@1371
|
13777 |
+ (match_operand:SI 1 "one_bit_set_operand" "i")))]
|
mgl@1371
|
13778 |
+ ""
|
mgl@1371
|
13779 |
+ "bld\t%0, %p1"
|
mgl@1371
|
13780 |
+ [(set_attr "length" "4")
|
mgl@1371
|
13781 |
+ (set_attr "cc" "bld")]
|
mgl@1371
|
13782 |
+ )
|
mgl@1371
|
13783 |
+
|
mgl@1371
|
13784 |
+
|
mgl@1371
|
13785 |
+;;=============================================================================
|
mgl@1371
|
13786 |
+;; Compare
|
mgl@1371
|
13787 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
13788 |
+;; Compare reg0 with reg1 or an immediate value.
|
mgl@1371
|
13789 |
+;;=============================================================================
|
mgl@1371
|
13790 |
+
|
mgl@1371
|
13791 |
+(define_expand "cmp<mode>"
|
mgl@1371
|
13792 |
+ [(set (cc0)
|
mgl@1371
|
13793 |
+ (compare:CMP
|
mgl@1371
|
13794 |
+ (match_operand:CMP 0 "register_operand" "")
|
mgl@1371
|
13795 |
+ (match_operand:CMP 1 "<CMP:cmp_predicate>" "")))]
|
mgl@1371
|
13796 |
+ ""
|
mgl@1371
|
13797 |
+ "{
|
mgl@1371
|
13798 |
+ avr32_compare_op0 = operands[0];
|
mgl@1371
|
13799 |
+ avr32_compare_op1 = operands[1];
|
mgl@1371
|
13800 |
+ }"
|
mgl@1371
|
13801 |
+)
|
mgl@1371
|
13802 |
+
|
mgl@1371
|
13803 |
+(define_insn "cmp<mode>_internal"
|
mgl@1371
|
13804 |
+ [(set (cc0)
|
mgl@1371
|
13805 |
+ (compare:CMP
|
mgl@1371
|
13806 |
+ (match_operand:CMP 0 "register_operand" "r")
|
mgl@1371
|
13807 |
+ (match_operand:CMP 1 "<CMP:cmp_predicate>" "<CMP:cmp_constraint>")))]
|
mgl@1371
|
13808 |
+ ""
|
mgl@1371
|
13809 |
+ {
|
mgl@1371
|
13810 |
+ set_next_insn_cond(insn,
|
mgl@1371
|
13811 |
+ avr32_output_cmp(get_next_insn_cond(insn), GET_MODE (operands[0]), operands[0], operands[1]));
|
mgl@1371
|
13812 |
+ return "";
|
mgl@1371
|
13813 |
+ }
|
mgl@1371
|
13814 |
+ [(set_attr "length" "4")
|
mgl@1371
|
13815 |
+ (set_attr "cc" "compare")])
|
mgl@1371
|
13816 |
+
|
mgl@1371
|
13817 |
+
|
mgl@1371
|
13818 |
+;;;=============================================================================
|
mgl@1371
|
13819 |
+;; Test if zero
|
mgl@1371
|
13820 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
13821 |
+;; Compare reg against zero and set the condition codes.
|
mgl@1371
|
13822 |
+;;=============================================================================
|
mgl@1371
|
13823 |
+
|
mgl@1371
|
13824 |
+
|
mgl@1371
|
13825 |
+(define_expand "tstsi"
|
mgl@1371
|
13826 |
+ [(set (cc0)
|
mgl@1371
|
13827 |
+ (match_operand:SI 0 "register_operand" ""))]
|
mgl@1371
|
13828 |
+ ""
|
mgl@1371
|
13829 |
+ {
|
mgl@1371
|
13830 |
+ avr32_compare_op0 = operands[0];
|
mgl@1371
|
13831 |
+ avr32_compare_op1 = const0_rtx;
|
mgl@1371
|
13832 |
+ }
|
mgl@1371
|
13833 |
+)
|
mgl@1371
|
13834 |
+
|
mgl@1371
|
13835 |
+(define_insn "tstsi_internal"
|
mgl@1371
|
13836 |
+ [(set (cc0)
|
mgl@1371
|
13837 |
+ (match_operand:SI 0 "register_operand" "r"))]
|
mgl@1371
|
13838 |
+ ""
|
mgl@1371
|
13839 |
+ {
|
mgl@1371
|
13840 |
+ set_next_insn_cond(insn,
|
mgl@1371
|
13841 |
+ avr32_output_cmp(get_next_insn_cond(insn), SImode, operands[0], const0_rtx));
|
mgl@1371
|
13842 |
+
|
mgl@1371
|
13843 |
+ return "";
|
mgl@1371
|
13844 |
+ }
|
mgl@1371
|
13845 |
+ [(set_attr "length" "2")
|
mgl@1371
|
13846 |
+ (set_attr "cc" "compare")])
|
mgl@1371
|
13847 |
+
|
mgl@1371
|
13848 |
+
|
mgl@1371
|
13849 |
+(define_expand "tstdi"
|
mgl@1371
|
13850 |
+ [(set (cc0)
|
mgl@1371
|
13851 |
+ (match_operand:DI 0 "register_operand" ""))]
|
mgl@1371
|
13852 |
+ ""
|
mgl@1371
|
13853 |
+ {
|
mgl@1371
|
13854 |
+ avr32_compare_op0 = operands[0];
|
mgl@1371
|
13855 |
+ avr32_compare_op1 = const0_rtx;
|
mgl@1371
|
13856 |
+ }
|
mgl@1371
|
13857 |
+)
|
mgl@1371
|
13858 |
+
|
mgl@1371
|
13859 |
+(define_insn "tstdi_internal"
|
mgl@1371
|
13860 |
+ [(set (cc0)
|
mgl@1371
|
13861 |
+ (match_operand:DI 0 "register_operand" "r"))]
|
mgl@1371
|
13862 |
+ ""
|
mgl@1371
|
13863 |
+ {
|
mgl@1371
|
13864 |
+ set_next_insn_cond(insn,
|
mgl@1371
|
13865 |
+ avr32_output_cmp(get_next_insn_cond(insn), DImode, operands[0], const0_rtx));
|
mgl@1371
|
13866 |
+ return "";
|
mgl@1371
|
13867 |
+ }
|
mgl@1371
|
13868 |
+ [(set_attr "length" "4")
|
mgl@1371
|
13869 |
+ (set_attr "type" "alu2")
|
mgl@1371
|
13870 |
+ (set_attr "cc" "compare")])
|
mgl@1371
|
13871 |
+
|
mgl@1371
|
13872 |
+
|
mgl@1371
|
13873 |
+
|
mgl@1371
|
13874 |
+;;=============================================================================
|
mgl@1371
|
13875 |
+;; Convert operands
|
mgl@1371
|
13876 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
13877 |
+;;
|
mgl@1371
|
13878 |
+;;=============================================================================
|
mgl@1371
|
13879 |
+(define_insn "truncdisi2"
|
mgl@1371
|
13880 |
+ [(set (match_operand:SI 0 "general_operand" "")
|
mgl@1371
|
13881 |
+ (truncate:SI (match_operand:DI 1 "general_operand" "")))]
|
mgl@1371
|
13882 |
+ ""
|
mgl@1371
|
13883 |
+ "truncdisi2")
|
mgl@1371
|
13884 |
+
|
mgl@1371
|
13885 |
+;;=============================================================================
|
mgl@1371
|
13886 |
+;; Extend
|
mgl@1371
|
13887 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
13888 |
+;;
|
mgl@1371
|
13889 |
+;;=============================================================================
|
mgl@1371
|
13890 |
+
|
mgl@1371
|
13891 |
+
|
mgl@1371
|
13892 |
+(define_insn "extendhisi2"
|
mgl@1371
|
13893 |
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
|
mgl@1371
|
13894 |
+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,r,<RKu00>,m")))]
|
mgl@1371
|
13895 |
+ ""
|
mgl@1371
|
13896 |
+ {
|
mgl@1371
|
13897 |
+ switch ( which_alternative ){
|
mgl@1371
|
13898 |
+ case 0:
|
mgl@1371
|
13899 |
+ return "casts.h\t%0";
|
mgl@1371
|
13900 |
+ case 1:
|
mgl@1371
|
13901 |
+ return "bfexts\t%0, %1, 0, 16";
|
mgl@1371
|
13902 |
+ case 2:
|
mgl@1371
|
13903 |
+ case 3:
|
mgl@1371
|
13904 |
+ return "ld.sh\t%0, %1";
|
mgl@1371
|
13905 |
+ default:
|
mgl@1371
|
13906 |
+ abort();
|
mgl@1371
|
13907 |
+ }
|
mgl@1371
|
13908 |
+ }
|
mgl@1371
|
13909 |
+ [(set_attr "length" "2,4,2,4")
|
mgl@1371
|
13910 |
+ (set_attr "cc" "set_ncz,set_ncz,none,none")
|
mgl@1371
|
13911 |
+ (set_attr "type" "alu,alu,load_rm,load_rm")])
|
mgl@1371
|
13912 |
+
|
mgl@1371
|
13913 |
+(define_insn "extendqisi2"
|
mgl@1371
|
13914 |
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
|
mgl@1371
|
13915 |
+ (sign_extend:SI (match_operand:QI 1 "extendqi_operand" "0,r,RKu00,m")))]
|
mgl@1371
|
13916 |
+ ""
|
mgl@1371
|
13917 |
+ {
|
mgl@1371
|
13918 |
+ switch ( which_alternative ){
|
mgl@1371
|
13919 |
+ case 0:
|
mgl@1371
|
13920 |
+ return "casts.b\t%0";
|
mgl@1371
|
13921 |
+ case 1:
|
mgl@1371
|
13922 |
+ return "bfexts\t%0, %1, 0, 8";
|
mgl@1371
|
13923 |
+ case 2:
|
mgl@1371
|
13924 |
+ case 3:
|
mgl@1371
|
13925 |
+ return "ld.sb\t%0, %1";
|
mgl@1371
|
13926 |
+ default:
|
mgl@1371
|
13927 |
+ abort();
|
mgl@1371
|
13928 |
+ }
|
mgl@1371
|
13929 |
+ }
|
mgl@1371
|
13930 |
+ [(set_attr "length" "2,4,2,4")
|
mgl@1371
|
13931 |
+ (set_attr "cc" "set_ncz,set_ncz,none,none")
|
mgl@1371
|
13932 |
+ (set_attr "type" "alu,alu,load_rm,load_rm")])
|
mgl@1371
|
13933 |
+
|
mgl@1371
|
13934 |
+(define_insn "extendqihi2"
|
mgl@1371
|
13935 |
+ [(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
|
mgl@1371
|
13936 |
+ (sign_extend:HI (match_operand:QI 1 "extendqi_operand" "0,r,RKu00,m")))]
|
mgl@1371
|
13937 |
+ ""
|
mgl@1371
|
13938 |
+ {
|
mgl@1371
|
13939 |
+ switch ( which_alternative ){
|
mgl@1371
|
13940 |
+ case 0:
|
mgl@1371
|
13941 |
+ return "casts.b\t%0";
|
mgl@1371
|
13942 |
+ case 1:
|
mgl@1371
|
13943 |
+ return "bfexts\t%0, %1, 0, 8";
|
mgl@1371
|
13944 |
+ case 2:
|
mgl@1371
|
13945 |
+ case 3:
|
mgl@1371
|
13946 |
+ return "ld.sb\t%0, %1";
|
mgl@1371
|
13947 |
+ default:
|
mgl@1371
|
13948 |
+ abort();
|
mgl@1371
|
13949 |
+ }
|
mgl@1371
|
13950 |
+ }
|
mgl@1371
|
13951 |
+ [(set_attr "length" "2,4,2,4")
|
mgl@1371
|
13952 |
+ (set_attr "cc" "set_ncz,set_ncz,none,none")
|
mgl@1371
|
13953 |
+ (set_attr "type" "alu,alu,load_rm,load_rm")])
|
mgl@1371
|
13954 |
+
|
mgl@1371
|
13955 |
+
|
mgl@1371
|
13956 |
+;;=============================================================================
|
mgl@1371
|
13957 |
+;; Zero-extend
|
mgl@1371
|
13958 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
13959 |
+;;
|
mgl@1371
|
13960 |
+;;=============================================================================
|
mgl@1371
|
13961 |
+
|
mgl@1371
|
13962 |
+(define_insn "zero_extendhisi2"
|
mgl@1371
|
13963 |
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
|
mgl@1371
|
13964 |
+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,r,<RKu00>,m")))]
|
mgl@1371
|
13965 |
+ ""
|
mgl@1371
|
13966 |
+ {
|
mgl@1371
|
13967 |
+ switch ( which_alternative ){
|
mgl@1371
|
13968 |
+ case 0:
|
mgl@1371
|
13969 |
+ return "castu.h\t%0";
|
mgl@1371
|
13970 |
+ case 1:
|
mgl@1371
|
13971 |
+ return "bfextu\t%0, %1, 0, 16";
|
mgl@1371
|
13972 |
+ case 2:
|
mgl@1371
|
13973 |
+ case 3:
|
mgl@1371
|
13974 |
+ return "ld.uh\t%0, %1";
|
mgl@1371
|
13975 |
+ default:
|
mgl@1371
|
13976 |
+ abort();
|
mgl@1371
|
13977 |
+ }
|
mgl@1371
|
13978 |
+ }
|
mgl@1371
|
13979 |
+
|
mgl@1371
|
13980 |
+ [(set_attr "length" "2,4,2,4")
|
mgl@1371
|
13981 |
+ (set_attr "cc" "set_ncz,set_ncz,none,none")
|
mgl@1371
|
13982 |
+ (set_attr "type" "alu,alu,load_rm,load_rm")])
|
mgl@1371
|
13983 |
+
|
mgl@1371
|
13984 |
+(define_insn "zero_extendqisi2"
|
mgl@1371
|
13985 |
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
|
mgl@1371
|
13986 |
+ (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,r,<RKu00>,m")))]
|
mgl@1371
|
13987 |
+ ""
|
mgl@1371
|
13988 |
+ {
|
mgl@1371
|
13989 |
+ switch ( which_alternative ){
|
mgl@1371
|
13990 |
+ case 0:
|
mgl@1371
|
13991 |
+ return "castu.b\t%0";
|
mgl@1371
|
13992 |
+ case 1:
|
mgl@1371
|
13993 |
+ return "bfextu\t%0, %1, 0, 8";
|
mgl@1371
|
13994 |
+ case 2:
|
mgl@1371
|
13995 |
+ case 3:
|
mgl@1371
|
13996 |
+ return "ld.ub\t%0, %1";
|
mgl@1371
|
13997 |
+ default:
|
mgl@1371
|
13998 |
+ abort();
|
mgl@1371
|
13999 |
+ }
|
mgl@1371
|
14000 |
+ }
|
mgl@1371
|
14001 |
+ [(set_attr "length" "2,4,2,4")
|
mgl@1371
|
14002 |
+ (set_attr "cc" "set_ncz, set_ncz, none, none")
|
mgl@1371
|
14003 |
+ (set_attr "type" "alu, alu, load_rm, load_rm")])
|
mgl@1371
|
14004 |
+
|
mgl@1371
|
14005 |
+(define_insn "zero_extendqihi2"
|
mgl@1371
|
14006 |
+ [(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
|
mgl@1371
|
14007 |
+ (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,r,<RKu00>,m")))]
|
mgl@1371
|
14008 |
+ ""
|
mgl@1371
|
14009 |
+ {
|
mgl@1371
|
14010 |
+ switch ( which_alternative ){
|
mgl@1371
|
14011 |
+ case 0:
|
mgl@1371
|
14012 |
+ return "castu.b\t%0";
|
mgl@1371
|
14013 |
+ case 1:
|
mgl@1371
|
14014 |
+ return "bfextu\t%0, %1, 0, 8";
|
mgl@1371
|
14015 |
+ case 2:
|
mgl@1371
|
14016 |
+ case 3:
|
mgl@1371
|
14017 |
+ return "ld.ub\t%0, %1";
|
mgl@1371
|
14018 |
+ default:
|
mgl@1371
|
14019 |
+ abort();
|
mgl@1371
|
14020 |
+ }
|
mgl@1371
|
14021 |
+ }
|
mgl@1371
|
14022 |
+ [(set_attr "length" "2,4,2,4")
|
mgl@1371
|
14023 |
+ (set_attr "cc" "set_ncz, set_ncz, none, none")
|
mgl@1371
|
14024 |
+ (set_attr "type" "alu, alu, load_rm, load_rm")])
|
mgl@1371
|
14025 |
+
|
mgl@1371
|
14026 |
+
|
mgl@1371
|
14027 |
+;;=============================================================================
|
mgl@1371
|
14028 |
+;; Conditional load and extend insns
|
mgl@1371
|
14029 |
+;;=============================================================================
|
mgl@1371
|
14030 |
+(define_insn "ldsi<mode>_predicable_se"
|
mgl@1371
|
14031 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
14032 |
+ (sign_extend:SI
|
mgl@1371
|
14033 |
+ (match_operand:INTM 1 "memory_operand" "<INTM:pred_mem_constraint>")))]
|
mgl@1371
|
14034 |
+ "TARGET_V2_INSNS"
|
mgl@1371
|
14035 |
+ "ld<INTM:load_postfix_s>%?\t%0, %1"
|
mgl@1371
|
14036 |
+ [(set_attr "length" "4")
|
mgl@1371
|
14037 |
+ (set_attr "cc" "cmp_cond_insn")
|
mgl@1371
|
14038 |
+ (set_attr "type" "load")
|
mgl@1371
|
14039 |
+ (set_attr "predicable" "yes")]
|
mgl@1371
|
14040 |
+)
|
mgl@1371
|
14041 |
+
|
mgl@1371
|
14042 |
+(define_insn "ldsi<mode>_predicable_ze"
|
mgl@1371
|
14043 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
14044 |
+ (zero_extend:SI
|
mgl@1371
|
14045 |
+ (match_operand:INTM 1 "memory_operand" "<INTM:pred_mem_constraint>")))]
|
mgl@1371
|
14046 |
+ "TARGET_V2_INSNS"
|
mgl@1371
|
14047 |
+ "ld<INTM:load_postfix_u>%?\t%0, %1"
|
mgl@1371
|
14048 |
+ [(set_attr "length" "4")
|
mgl@1371
|
14049 |
+ (set_attr "cc" "cmp_cond_insn")
|
mgl@1371
|
14050 |
+ (set_attr "type" "load")
|
mgl@1371
|
14051 |
+ (set_attr "predicable" "yes")]
|
mgl@1371
|
14052 |
+)
|
mgl@1371
|
14053 |
+
|
mgl@1371
|
14054 |
+(define_insn "ldhi_predicable_ze"
|
mgl@1371
|
14055 |
+ [(set (match_operand:HI 0 "register_operand" "=r")
|
mgl@1371
|
14056 |
+ (zero_extend:HI
|
mgl@1371
|
14057 |
+ (match_operand:QI 1 "memory_operand" "RKs10")))]
|
mgl@1371
|
14058 |
+ "TARGET_V2_INSNS"
|
mgl@1371
|
14059 |
+ "ld.ub%?\t%0, %1"
|
mgl@1371
|
14060 |
+ [(set_attr "length" "4")
|
mgl@1371
|
14061 |
+ (set_attr "cc" "cmp_cond_insn")
|
mgl@1371
|
14062 |
+ (set_attr "type" "load")
|
mgl@1371
|
14063 |
+ (set_attr "predicable" "yes")]
|
mgl@1371
|
14064 |
+)
|
mgl@1371
|
14065 |
+
|
mgl@1371
|
14066 |
+(define_insn "ldhi_predicable_se"
|
mgl@1371
|
14067 |
+ [(set (match_operand:HI 0 "register_operand" "=r")
|
mgl@1371
|
14068 |
+ (sign_extend:HI
|
mgl@1371
|
14069 |
+ (match_operand:QI 1 "memory_operand" "RKs10")))]
|
mgl@1371
|
14070 |
+ "TARGET_V2_INSNS"
|
mgl@1371
|
14071 |
+ "ld.sb%?\t%0, %1"
|
mgl@1371
|
14072 |
+ [(set_attr "length" "4")
|
mgl@1371
|
14073 |
+ (set_attr "cc" "cmp_cond_insn")
|
mgl@1371
|
14074 |
+ (set_attr "type" "load")
|
mgl@1371
|
14075 |
+ (set_attr "predicable" "yes")]
|
mgl@1371
|
14076 |
+)
|
mgl@1371
|
14077 |
+
|
mgl@1371
|
14078 |
+;;=============================================================================
|
mgl@1371
|
14079 |
+;; Conditional set register
|
mgl@1371
|
14080 |
+;; sr{cond4} rd
|
mgl@1371
|
14081 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
14082 |
+
|
mgl@1371
|
14083 |
+;;Because of the same issue as with conditional moves and adds we must
|
mgl@1371
|
14084 |
+;;not separate the compare instrcution from the scc instruction as
|
mgl@1371
|
14085 |
+;;they might be sheduled "badly".
|
mgl@1371
|
14086 |
+
|
mgl@1371
|
14087 |
+(define_insn "s<code>"
|
mgl@1371
|
14088 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
14089 |
+ (any_cond:SI (cc0)
|
mgl@1371
|
14090 |
+ (const_int 0)))]
|
mgl@1371
|
14091 |
+ ""
|
mgl@1371
|
14092 |
+ "sr<cond>\t%0"
|
mgl@1371
|
14093 |
+ [(set_attr "length" "2")
|
mgl@1371
|
14094 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
14095 |
+
|
mgl@1371
|
14096 |
+(define_insn "smi"
|
mgl@1371
|
14097 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
14098 |
+ (unspec:SI [(cc0)
|
mgl@1371
|
14099 |
+ (const_int 0)] UNSPEC_COND_MI))]
|
mgl@1371
|
14100 |
+ ""
|
mgl@1371
|
14101 |
+ "srmi\t%0"
|
mgl@1371
|
14102 |
+ [(set_attr "length" "2")
|
mgl@1371
|
14103 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
14104 |
+
|
mgl@1371
|
14105 |
+(define_insn "spl"
|
mgl@1371
|
14106 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
14107 |
+ (unspec:SI [(cc0)
|
mgl@1371
|
14108 |
+ (const_int 0)] UNSPEC_COND_PL))]
|
mgl@1371
|
14109 |
+ ""
|
mgl@1371
|
14110 |
+ "srpl\t%0"
|
mgl@1371
|
14111 |
+ [(set_attr "length" "2")
|
mgl@1371
|
14112 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
14113 |
+
|
mgl@1371
|
14114 |
+
|
mgl@1371
|
14115 |
+;;=============================================================================
|
mgl@1371
|
14116 |
+;; Conditional branch
|
mgl@1371
|
14117 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
14118 |
+;; Branch to label if the specified condition codes are set.
|
mgl@1371
|
14119 |
+;;=============================================================================
|
mgl@1371
|
14120 |
+; branch if negative
|
mgl@1371
|
14121 |
+(define_insn "bmi"
|
mgl@1371
|
14122 |
+ [(set (pc)
|
mgl@1371
|
14123 |
+ (if_then_else (unspec:CC [(cc0) (const_int 0)] UNSPEC_COND_MI)
|
mgl@1371
|
14124 |
+ (label_ref (match_operand 0 "" ""))
|
mgl@1371
|
14125 |
+ (pc)))]
|
mgl@1371
|
14126 |
+ ""
|
mgl@1371
|
14127 |
+ "brmi %0"
|
mgl@1371
|
14128 |
+ [(set_attr "type" "branch")
|
mgl@1371
|
14129 |
+ (set (attr "length")
|
mgl@1371
|
14130 |
+ (cond [(and (le (minus (match_dup 0) (pc)) (const_int 254))
|
mgl@1371
|
14131 |
+ (le (minus (pc) (match_dup 0)) (const_int 256)))
|
mgl@1371
|
14132 |
+ (const_int 2)] ; use compact branch
|
mgl@1371
|
14133 |
+ (const_int 4))) ; use extended branch
|
mgl@1371
|
14134 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
14135 |
+
|
mgl@1371
|
14136 |
+(define_insn "*bmi-reverse"
|
mgl@1371
|
14137 |
+ [(set (pc)
|
mgl@1371
|
14138 |
+ (if_then_else (unspec:CC [(cc0) (const_int 0)] UNSPEC_COND_MI)
|
mgl@1371
|
14139 |
+ (pc)
|
mgl@1371
|
14140 |
+ (label_ref (match_operand 0 "" ""))))]
|
mgl@1371
|
14141 |
+ ""
|
mgl@1371
|
14142 |
+ "brpl %0"
|
mgl@1371
|
14143 |
+ [(set_attr "type" "branch")
|
mgl@1371
|
14144 |
+ (set (attr "length")
|
mgl@1371
|
14145 |
+ (cond [(and (le (minus (match_dup 0) (pc)) (const_int 254))
|
mgl@1371
|
14146 |
+ (le (minus (pc) (match_dup 0)) (const_int 256)))
|
mgl@1371
|
14147 |
+ (const_int 2)] ; use compact branch
|
mgl@1371
|
14148 |
+ (const_int 4))) ; use extended branch
|
mgl@1371
|
14149 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
14150 |
+
|
mgl@1371
|
14151 |
+; branch if positive
|
mgl@1371
|
14152 |
+(define_insn "bpl"
|
mgl@1371
|
14153 |
+ [(set (pc)
|
mgl@1371
|
14154 |
+ (if_then_else (unspec:CC [(cc0) (const_int 0)] UNSPEC_COND_PL)
|
mgl@1371
|
14155 |
+ (label_ref (match_operand 0 "" ""))
|
mgl@1371
|
14156 |
+ (pc)))]
|
mgl@1371
|
14157 |
+ ""
|
mgl@1371
|
14158 |
+ "brpl %0"
|
mgl@1371
|
14159 |
+ [(set_attr "type" "branch")
|
mgl@1371
|
14160 |
+ (set (attr "length")
|
mgl@1371
|
14161 |
+ (cond [(and (le (minus (match_dup 0) (pc)) (const_int 254))
|
mgl@1371
|
14162 |
+ (le (minus (pc) (match_dup 0)) (const_int 256)))
|
mgl@1371
|
14163 |
+ (const_int 2)] ; use compact branch
|
mgl@1371
|
14164 |
+ (const_int 4))) ; use extended branch
|
mgl@1371
|
14165 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
14166 |
+
|
mgl@1371
|
14167 |
+(define_insn "*bpl-reverse"
|
mgl@1371
|
14168 |
+ [(set (pc)
|
mgl@1371
|
14169 |
+ (if_then_else (unspec:CC [(cc0) (const_int 0)] UNSPEC_COND_PL)
|
mgl@1371
|
14170 |
+ (pc)
|
mgl@1371
|
14171 |
+ (label_ref (match_operand 0 "" ""))))]
|
mgl@1371
|
14172 |
+ ""
|
mgl@1371
|
14173 |
+ "brmi %0"
|
mgl@1371
|
14174 |
+ [(set_attr "type" "branch")
|
mgl@1371
|
14175 |
+ (set (attr "length")
|
mgl@1371
|
14176 |
+ (cond [(and (le (minus (match_dup 0) (pc)) (const_int 254))
|
mgl@1371
|
14177 |
+ (le (minus (pc) (match_dup 0)) (const_int 256)))
|
mgl@1371
|
14178 |
+ (const_int 2)] ; use compact branch
|
mgl@1371
|
14179 |
+ (const_int 4))) ; use extended branch
|
mgl@1371
|
14180 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
14181 |
+
|
mgl@1371
|
14182 |
+; branch if equal
|
mgl@1371
|
14183 |
+(define_insn "b<code>"
|
mgl@1371
|
14184 |
+ [(set (pc)
|
mgl@1371
|
14185 |
+ (if_then_else (any_cond:CC (cc0)
|
mgl@1371
|
14186 |
+ (const_int 0))
|
mgl@1371
|
14187 |
+ (label_ref (match_operand 0 "" ""))
|
mgl@1371
|
14188 |
+ (pc)))]
|
mgl@1371
|
14189 |
+ ""
|
mgl@1371
|
14190 |
+ "br<cond> %0 "
|
mgl@1371
|
14191 |
+ [(set_attr "type" "branch")
|
mgl@1371
|
14192 |
+ (set (attr "length")
|
mgl@1371
|
14193 |
+ (cond [(and (le (minus (match_dup 0) (pc)) (const_int 254))
|
mgl@1371
|
14194 |
+ (le (minus (pc) (match_dup 0)) (const_int 256)))
|
mgl@1371
|
14195 |
+ (const_int 2)] ; use compact branch
|
mgl@1371
|
14196 |
+ (const_int 4))) ; use extended branch
|
mgl@1371
|
14197 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
14198 |
+
|
mgl@1371
|
14199 |
+
|
mgl@1371
|
14200 |
+(define_insn "*b<code>-reverse"
|
mgl@1371
|
14201 |
+ [(set (pc)
|
mgl@1371
|
14202 |
+ (if_then_else (any_cond:CC (cc0)
|
mgl@1371
|
14203 |
+ (const_int 0))
|
mgl@1371
|
14204 |
+ (pc)
|
mgl@1371
|
14205 |
+ (label_ref (match_operand 0 "" ""))))]
|
mgl@1371
|
14206 |
+ ""
|
mgl@1371
|
14207 |
+ "br<invcond> %0 "
|
mgl@1371
|
14208 |
+ [(set_attr "type" "branch")
|
mgl@1371
|
14209 |
+ (set (attr "length")
|
mgl@1371
|
14210 |
+ (cond [(and (le (minus (match_dup 0) (pc)) (const_int 254))
|
mgl@1371
|
14211 |
+ (le (minus (pc) (match_dup 0)) (const_int 256)))
|
mgl@1371
|
14212 |
+ (const_int 2)] ; use compact branch
|
mgl@1371
|
14213 |
+ (const_int 4))) ; use extended branch
|
mgl@1371
|
14214 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
14215 |
+
|
mgl@1371
|
14216 |
+
|
mgl@1371
|
14217 |
+
|
mgl@1371
|
14218 |
+;=============================================================================
|
mgl@1371
|
14219 |
+; Conditional Add/Subtract
|
mgl@1371
|
14220 |
+;-----------------------------------------------------------------------------
|
mgl@1371
|
14221 |
+; sub{cond4} Rd, imm
|
mgl@1371
|
14222 |
+;=============================================================================
|
mgl@1371
|
14223 |
+
|
mgl@1371
|
14224 |
+
|
mgl@1371
|
14225 |
+(define_expand "add<mode>cc"
|
mgl@1371
|
14226 |
+ [(set (match_operand:ADDCC 0 "register_operand" "")
|
mgl@1371
|
14227 |
+ (if_then_else:ADDCC (match_operator 1 "avr32_comparison_operator"
|
mgl@1371
|
14228 |
+ [(match_dup 4)
|
mgl@1371
|
14229 |
+ (match_dup 5)])
|
mgl@1371
|
14230 |
+ (match_operand:ADDCC 2 "register_operand" "")
|
mgl@1371
|
14231 |
+ (plus:ADDCC
|
mgl@1371
|
14232 |
+ (match_dup 2)
|
mgl@1371
|
14233 |
+ (match_operand:ADDCC 3 "" ""))))]
|
mgl@1371
|
14234 |
+ ""
|
mgl@1371
|
14235 |
+ {
|
mgl@1371
|
14236 |
+ if ( !(GET_CODE (operands[3]) == CONST_INT
|
mgl@1371
|
14237 |
+ || (TARGET_V2_INSNS && REG_P(operands[3]))) ){
|
mgl@1371
|
14238 |
+ FAIL;
|
mgl@1371
|
14239 |
+ }
|
mgl@1371
|
14240 |
+
|
mgl@1371
|
14241 |
+ /* Delete compare instruction as it is merged into this instruction */
|
mgl@1371
|
14242 |
+ remove_insn (get_last_insn_anywhere ());
|
mgl@1371
|
14243 |
+
|
mgl@1371
|
14244 |
+ operands[4] = avr32_compare_op0;
|
mgl@1371
|
14245 |
+ operands[5] = avr32_compare_op1;
|
mgl@1371
|
14246 |
+
|
mgl@1371
|
14247 |
+ if ( TARGET_V2_INSNS
|
mgl@1371
|
14248 |
+ && REG_P(operands[3])
|
mgl@1371
|
14249 |
+ && REGNO(operands[0]) != REGNO(operands[2]) ){
|
mgl@1371
|
14250 |
+ emit_move_insn (operands[0], operands[2]);
|
mgl@1371
|
14251 |
+ operands[2] = operands[0];
|
mgl@1371
|
14252 |
+ }
|
mgl@1371
|
14253 |
+ }
|
mgl@1371
|
14254 |
+ )
|
mgl@1371
|
14255 |
+
|
mgl@1371
|
14256 |
+(define_insn "add<ADDCC:mode>cc_cmp<CMP:mode>_reg"
|
mgl@1371
|
14257 |
+ [(set (match_operand:ADDCC 0 "register_operand" "=r")
|
mgl@1371
|
14258 |
+ (if_then_else:ADDCC (match_operator 1 "avr32_comparison_operator"
|
mgl@1371
|
14259 |
+ [(match_operand:CMP 4 "register_operand" "r")
|
mgl@1371
|
14260 |
+ (match_operand:CMP 5 "<CMP:cmp_predicate>" "<CMP:cmp_constraint>")])
|
mgl@1371
|
14261 |
+ (match_dup 0)
|
mgl@1371
|
14262 |
+ (plus:ADDCC
|
mgl@1371
|
14263 |
+ (match_operand:ADDCC 2 "register_operand" "r")
|
mgl@1371
|
14264 |
+ (match_operand:ADDCC 3 "register_operand" "r"))))]
|
mgl@1371
|
14265 |
+ "TARGET_V2_INSNS"
|
mgl@1371
|
14266 |
+ {
|
mgl@1371
|
14267 |
+ operands[1] = avr32_output_cmp(operands[1], GET_MODE(operands[4]), operands[4], operands[5]);
|
mgl@1371
|
14268 |
+ return "add%i1\t%0, %2, %3";
|
mgl@1371
|
14269 |
+ }
|
mgl@1371
|
14270 |
+ [(set_attr "length" "8")
|
mgl@1371
|
14271 |
+ (set_attr "cc" "cmp_cond_insn")])
|
mgl@1371
|
14272 |
+
|
mgl@1371
|
14273 |
+(define_insn "add<ADDCC:mode>cc_cmp<CMP:mode>"
|
mgl@1371
|
14274 |
+ [(set (match_operand:ADDCC 0 "register_operand" "=r")
|
mgl@1371
|
14275 |
+ (if_then_else:ADDCC (match_operator 1 "avr32_comparison_operator"
|
mgl@1371
|
14276 |
+ [(match_operand:CMP 4 "register_operand" "r")
|
mgl@1371
|
14277 |
+ (match_operand:CMP 5 "<CMP:cmp_predicate>" "<CMP:cmp_constraint>")])
|
mgl@1371
|
14278 |
+ (match_operand:ADDCC 2 "register_operand" "0")
|
mgl@1371
|
14279 |
+ (plus:ADDCC
|
mgl@1371
|
14280 |
+ (match_dup 2)
|
mgl@1371
|
14281 |
+ (match_operand:ADDCC 3 "avr32_cond_immediate_operand" "Is08"))))]
|
mgl@1371
|
14282 |
+ ""
|
mgl@1371
|
14283 |
+ {
|
mgl@1371
|
14284 |
+ operands[1] = avr32_output_cmp(operands[1], GET_MODE(operands[4]), operands[4], operands[5]);
|
mgl@1371
|
14285 |
+ return "sub%i1\t%0, -%3";
|
mgl@1371
|
14286 |
+ }
|
mgl@1371
|
14287 |
+ [(set_attr "length" "8")
|
mgl@1371
|
14288 |
+ (set_attr "cc" "cmp_cond_insn")])
|
mgl@1371
|
14289 |
+
|
mgl@1371
|
14290 |
+;=============================================================================
|
mgl@1371
|
14291 |
+; Conditional Move
|
mgl@1371
|
14292 |
+;-----------------------------------------------------------------------------
|
mgl@1371
|
14293 |
+; mov{cond4} Rd, (Rs/imm)
|
mgl@1371
|
14294 |
+;=============================================================================
|
mgl@1371
|
14295 |
+(define_expand "mov<mode>cc"
|
mgl@1371
|
14296 |
+ [(set (match_operand:MOVCC 0 "register_operand" "")
|
mgl@1371
|
14297 |
+ (if_then_else:MOVCC (match_operator 1 "avr32_comparison_operator"
|
mgl@1371
|
14298 |
+ [(match_dup 4)
|
mgl@1371
|
14299 |
+ (match_dup 5)])
|
mgl@1371
|
14300 |
+ (match_operand:MOVCC 2 "avr32_cond_register_immediate_operand" "")
|
mgl@1371
|
14301 |
+ (match_operand:MOVCC 3 "avr32_cond_register_immediate_operand" "")))]
|
mgl@1371
|
14302 |
+ ""
|
mgl@1371
|
14303 |
+ {
|
mgl@1371
|
14304 |
+ /* Delete compare instruction as it is merged into this instruction */
|
mgl@1371
|
14305 |
+ remove_insn (get_last_insn_anywhere ());
|
mgl@1371
|
14306 |
+
|
mgl@1371
|
14307 |
+ operands[4] = avr32_compare_op0;
|
mgl@1371
|
14308 |
+ operands[5] = avr32_compare_op1;
|
mgl@1371
|
14309 |
+ }
|
mgl@1371
|
14310 |
+ )
|
mgl@1371
|
14311 |
+
|
mgl@1371
|
14312 |
+
|
mgl@1371
|
14313 |
+(define_insn "mov<MOVCC:mode>cc_cmp<CMP:mode>"
|
mgl@1371
|
14314 |
+ [(set (match_operand:MOVCC 0 "register_operand" "=r,r,r")
|
mgl@1371
|
14315 |
+ (if_then_else:MOVCC (match_operator 1 "avr32_comparison_operator"
|
mgl@1371
|
14316 |
+ [(match_operand:CMP 4 "register_operand" "r,r,r")
|
mgl@1371
|
14317 |
+ (match_operand:CMP 5 "<CMP:cmp_predicate>" "<CMP:cmp_constraint>,<CMP:cmp_constraint>,<CMP:cmp_constraint>")])
|
mgl@1371
|
14318 |
+ (match_operand:MOVCC 2 "avr32_cond_register_immediate_operand" "0, rKs08,rKs08")
|
mgl@1371
|
14319 |
+ (match_operand:MOVCC 3 "avr32_cond_register_immediate_operand" "rKs08,0,rKs08")))]
|
mgl@1371
|
14320 |
+ ""
|
mgl@1371
|
14321 |
+ {
|
mgl@1371
|
14322 |
+ operands[1] = avr32_output_cmp(operands[1], GET_MODE(operands[4]), operands[4], operands[5]);
|
mgl@1371
|
14323 |
+
|
mgl@1371
|
14324 |
+ switch( which_alternative ){
|
mgl@1371
|
14325 |
+ case 0:
|
mgl@1371
|
14326 |
+ return "mov%i1 %0, %3";
|
mgl@1371
|
14327 |
+ case 1:
|
mgl@1371
|
14328 |
+ return "mov%1 %0, %2";
|
mgl@1371
|
14329 |
+ case 2:
|
mgl@1371
|
14330 |
+ return "mov%1 %0, %2\;mov%i1 %0, %3";
|
mgl@1371
|
14331 |
+ default:
|
mgl@1371
|
14332 |
+ abort();
|
mgl@1371
|
14333 |
+ }
|
mgl@1371
|
14334 |
+
|
mgl@1371
|
14335 |
+ }
|
mgl@1371
|
14336 |
+ [(set_attr "length" "8,8,12")
|
mgl@1371
|
14337 |
+ (set_attr "cc" "cmp_cond_insn")])
|
mgl@1371
|
14338 |
+
|
mgl@1371
|
14339 |
+
|
mgl@1371
|
14340 |
+
|
mgl@1371
|
14341 |
+
|
mgl@1371
|
14342 |
+;;=============================================================================
|
mgl@1371
|
14343 |
+;; jump
|
mgl@1371
|
14344 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
14345 |
+;; Jump inside a function; an unconditional branch to a label.
|
mgl@1371
|
14346 |
+;;=============================================================================
|
mgl@1371
|
14347 |
+(define_insn "jump"
|
mgl@1371
|
14348 |
+ [(set (pc)
|
mgl@1371
|
14349 |
+ (label_ref (match_operand 0 "" "")))]
|
mgl@1371
|
14350 |
+ ""
|
mgl@1371
|
14351 |
+ {
|
mgl@1371
|
14352 |
+ if (get_attr_length(insn) > 4)
|
mgl@1371
|
14353 |
+ return "Can't jump this far";
|
mgl@1371
|
14354 |
+ return (get_attr_length(insn) == 2 ?
|
mgl@1371
|
14355 |
+ "rjmp %0" : "bral %0");
|
mgl@1371
|
14356 |
+ }
|
mgl@1371
|
14357 |
+ [(set_attr "type" "branch")
|
mgl@1371
|
14358 |
+ (set (attr "length")
|
mgl@1371
|
14359 |
+ (cond [(and (le (minus (match_dup 0) (pc)) (const_int 1022))
|
mgl@1371
|
14360 |
+ (le (minus (pc) (match_dup 0)) (const_int 1024)))
|
mgl@1371
|
14361 |
+ (const_int 2) ; use rjmp
|
mgl@1371
|
14362 |
+ (le (match_dup 0) (const_int 1048575))
|
mgl@1371
|
14363 |
+ (const_int 4)] ; use bral
|
mgl@1371
|
14364 |
+ (const_int 8))) ; do something else
|
mgl@1371
|
14365 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
14366 |
+
|
mgl@1371
|
14367 |
+;;=============================================================================
|
mgl@1371
|
14368 |
+;; call
|
mgl@1371
|
14369 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
14370 |
+;; Subroutine call instruction returning no value.
|
mgl@1371
|
14371 |
+;;=============================================================================
|
mgl@1371
|
14372 |
+(define_insn "call_internal"
|
mgl@1371
|
14373 |
+ [(parallel [(call (mem:SI (match_operand:SI 0 "avr32_call_operand" "r,U,T,W"))
|
mgl@1371
|
14374 |
+ (match_operand 1 "" ""))
|
mgl@1371
|
14375 |
+ (clobber (reg:SI LR_REGNUM))])]
|
mgl@1371
|
14376 |
+ ""
|
mgl@1371
|
14377 |
+ {
|
mgl@1371
|
14378 |
+ switch (which_alternative){
|
mgl@1371
|
14379 |
+ case 0:
|
mgl@1371
|
14380 |
+ return "icall\t%0";
|
mgl@1371
|
14381 |
+ case 1:
|
mgl@1371
|
14382 |
+ return "rcall\t%0";
|
mgl@1371
|
14383 |
+ case 2:
|
mgl@1371
|
14384 |
+ return "mcall\t%0";
|
mgl@1371
|
14385 |
+ case 3:
|
mgl@1371
|
14386 |
+ if ( TARGET_HAS_ASM_ADDR_PSEUDOS )
|
mgl@1371
|
14387 |
+ return "call\t%0";
|
mgl@1371
|
14388 |
+ else
|
mgl@1371
|
14389 |
+ return "mcall\tr6[%0@got]";
|
mgl@1371
|
14390 |
+ default:
|
mgl@1371
|
14391 |
+ abort();
|
mgl@1371
|
14392 |
+ }
|
mgl@1371
|
14393 |
+ }
|
mgl@1371
|
14394 |
+ [(set_attr "type" "call")
|
mgl@1371
|
14395 |
+ (set_attr "length" "2,4,4,10")
|
mgl@1371
|
14396 |
+ (set_attr "cc" "clobber")])
|
mgl@1371
|
14397 |
+
|
mgl@1371
|
14398 |
+
|
mgl@1371
|
14399 |
+(define_expand "call"
|
mgl@1371
|
14400 |
+ [(parallel [(call (match_operand:SI 0 "" "")
|
mgl@1371
|
14401 |
+ (match_operand 1 "" ""))
|
mgl@1371
|
14402 |
+ (clobber (reg:SI LR_REGNUM))])]
|
mgl@1371
|
14403 |
+ ""
|
mgl@1371
|
14404 |
+ {
|
mgl@1371
|
14405 |
+ rtx call_address;
|
mgl@1371
|
14406 |
+ if ( GET_CODE(operands[0]) != MEM )
|
mgl@1371
|
14407 |
+ FAIL;
|
mgl@1371
|
14408 |
+
|
mgl@1371
|
14409 |
+ call_address = XEXP(operands[0], 0);
|
mgl@1371
|
14410 |
+
|
mgl@1371
|
14411 |
+ /* If assembler supports call pseudo insn and the call
|
mgl@1371
|
14412 |
+ address is a symbol then nothing special needs to be done. */
|
mgl@1371
|
14413 |
+ if ( TARGET_HAS_ASM_ADDR_PSEUDOS
|
mgl@1371
|
14414 |
+ && (GET_CODE(call_address) == SYMBOL_REF) ){
|
mgl@1371
|
14415 |
+ /* We must however mark the function as using the GOT if
|
mgl@1371
|
14416 |
+ flag_pic is set, since the call insn might turn into
|
mgl@1371
|
14417 |
+ a mcall using the GOT ptr register. */
|
mgl@1371
|
14418 |
+ if ( flag_pic ){
|
mgl@1371
|
14419 |
+ current_function_uses_pic_offset_table = 1;
|
mgl@1371
|
14420 |
+ emit_call_insn(gen_call_internal(call_address, operands[1]));
|
mgl@1371
|
14421 |
+ DONE;
|
mgl@1371
|
14422 |
+ }
|
mgl@1371
|
14423 |
+ } else {
|
mgl@1371
|
14424 |
+ if ( flag_pic &&
|
mgl@1371
|
14425 |
+ GET_CODE(call_address) == SYMBOL_REF ){
|
mgl@1371
|
14426 |
+ current_function_uses_pic_offset_table = 1;
|
mgl@1371
|
14427 |
+ emit_call_insn(gen_call_internal(call_address, operands[1]));
|
mgl@1371
|
14428 |
+ DONE;
|
mgl@1371
|
14429 |
+ }
|
mgl@1371
|
14430 |
+
|
mgl@1371
|
14431 |
+ if ( !SYMBOL_REF_RCALL_FUNCTION_P(operands[0]) ){
|
mgl@1371
|
14432 |
+ if ( optimize_size &&
|
mgl@1371
|
14433 |
+ GET_CODE(call_address) == SYMBOL_REF ){
|
mgl@1371
|
14434 |
+ call_address = force_const_mem(SImode, call_address);
|
mgl@1371
|
14435 |
+ } else {
|
mgl@1371
|
14436 |
+ call_address = force_reg(SImode, call_address);
|
mgl@1371
|
14437 |
+ }
|
mgl@1371
|
14438 |
+ }
|
mgl@1371
|
14439 |
+ }
|
mgl@1371
|
14440 |
+ emit_call_insn(gen_call_internal(call_address, operands[1]));
|
mgl@1371
|
14441 |
+ DONE;
|
mgl@1371
|
14442 |
+ }
|
mgl@1371
|
14443 |
+)
|
mgl@1371
|
14444 |
+
|
mgl@1371
|
14445 |
+;;=============================================================================
|
mgl@1371
|
14446 |
+;; call_value
|
mgl@1371
|
14447 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
14448 |
+;; Subrutine call instruction returning a value.
|
mgl@1371
|
14449 |
+;;=============================================================================
|
mgl@1371
|
14450 |
+(define_expand "call_value"
|
mgl@1371
|
14451 |
+ [(parallel [(set (match_operand:SI 0 "" "")
|
mgl@1371
|
14452 |
+ (call (match_operand:SI 1 "" "")
|
mgl@1371
|
14453 |
+ (match_operand 2 "" "")))
|
mgl@1371
|
14454 |
+ (clobber (reg:SI LR_REGNUM))])]
|
mgl@1371
|
14455 |
+ ""
|
mgl@1371
|
14456 |
+ {
|
mgl@1371
|
14457 |
+ rtx call_address;
|
mgl@1371
|
14458 |
+ if ( GET_CODE(operands[1]) != MEM )
|
mgl@1371
|
14459 |
+ FAIL;
|
mgl@1371
|
14460 |
+
|
mgl@1371
|
14461 |
+ call_address = XEXP(operands[1], 0);
|
mgl@1371
|
14462 |
+
|
mgl@1371
|
14463 |
+ /* If assembler supports call pseudo insn and the call
|
mgl@1371
|
14464 |
+ address is a symbol then nothing special needs to be done. */
|
mgl@1371
|
14465 |
+ if ( TARGET_HAS_ASM_ADDR_PSEUDOS
|
mgl@1371
|
14466 |
+ && (GET_CODE(call_address) == SYMBOL_REF) ){
|
mgl@1371
|
14467 |
+ /* We must however mark the function as using the GOT if
|
mgl@1371
|
14468 |
+ flag_pic is set, since the call insn might turn into
|
mgl@1371
|
14469 |
+ a mcall using the GOT ptr register. */
|
mgl@1371
|
14470 |
+ if ( flag_pic ) {
|
mgl@1371
|
14471 |
+ current_function_uses_pic_offset_table = 1;
|
mgl@1371
|
14472 |
+ emit_call_insn(gen_call_value_internal(operands[0], call_address, operands[2]));
|
mgl@1371
|
14473 |
+ DONE;
|
mgl@1371
|
14474 |
+ }
|
mgl@1371
|
14475 |
+ } else {
|
mgl@1371
|
14476 |
+ if ( flag_pic &&
|
mgl@1371
|
14477 |
+ GET_CODE(call_address) == SYMBOL_REF ){
|
mgl@1371
|
14478 |
+ current_function_uses_pic_offset_table = 1;
|
mgl@1371
|
14479 |
+ emit_call_insn(gen_call_value_internal(operands[0], call_address, operands[2]));
|
mgl@1371
|
14480 |
+ DONE;
|
mgl@1371
|
14481 |
+ }
|
mgl@1371
|
14482 |
+
|
mgl@1371
|
14483 |
+ if ( !SYMBOL_REF_RCALL_FUNCTION_P(operands[1]) ){
|
mgl@1371
|
14484 |
+ if ( optimize_size &&
|
mgl@1371
|
14485 |
+ GET_CODE(call_address) == SYMBOL_REF){
|
mgl@1371
|
14486 |
+ call_address = force_const_mem(SImode, call_address);
|
mgl@1371
|
14487 |
+ } else {
|
mgl@1371
|
14488 |
+ call_address = force_reg(SImode, call_address);
|
mgl@1371
|
14489 |
+ }
|
mgl@1371
|
14490 |
+ }
|
mgl@1371
|
14491 |
+ }
|
mgl@1371
|
14492 |
+ emit_call_insn(gen_call_value_internal(operands[0], call_address,
|
mgl@1371
|
14493 |
+ operands[2]));
|
mgl@1371
|
14494 |
+ DONE;
|
mgl@1371
|
14495 |
+
|
mgl@1371
|
14496 |
+ })
|
mgl@1371
|
14497 |
+
|
mgl@1371
|
14498 |
+(define_insn "call_value_internal"
|
mgl@1371
|
14499 |
+ [(parallel [(set (match_operand 0 "register_operand" "=r,r,r,r")
|
mgl@1371
|
14500 |
+ (call (mem:SI (match_operand:SI 1 "avr32_call_operand" "r,U,T,W"))
|
mgl@1371
|
14501 |
+ (match_operand 2 "" "")))
|
mgl@1371
|
14502 |
+ (clobber (reg:SI LR_REGNUM))])]
|
mgl@1371
|
14503 |
+ ;; Operand 2 not used on the AVR32.
|
mgl@1371
|
14504 |
+ ""
|
mgl@1371
|
14505 |
+ {
|
mgl@1371
|
14506 |
+ switch (which_alternative){
|
mgl@1371
|
14507 |
+ case 0:
|
mgl@1371
|
14508 |
+ return "icall\t%1";
|
mgl@1371
|
14509 |
+ case 1:
|
mgl@1371
|
14510 |
+ return "rcall\t%1";
|
mgl@1371
|
14511 |
+ case 2:
|
mgl@1371
|
14512 |
+ return "mcall\t%1";
|
mgl@1371
|
14513 |
+ case 3:
|
mgl@1371
|
14514 |
+ if ( TARGET_HAS_ASM_ADDR_PSEUDOS )
|
mgl@1371
|
14515 |
+ return "call\t%1";
|
mgl@1371
|
14516 |
+ else
|
mgl@1371
|
14517 |
+ return "mcall\tr6[%1@got]";
|
mgl@1371
|
14518 |
+ default:
|
mgl@1371
|
14519 |
+ abort();
|
mgl@1371
|
14520 |
+ }
|
mgl@1371
|
14521 |
+ }
|
mgl@1371
|
14522 |
+ [(set_attr "type" "call")
|
mgl@1371
|
14523 |
+ (set_attr "length" "2,4,4,10")
|
mgl@1371
|
14524 |
+ (set_attr "cc" "call_set")])
|
mgl@1371
|
14525 |
+
|
mgl@1371
|
14526 |
+
|
mgl@1371
|
14527 |
+;;=============================================================================
|
mgl@1371
|
14528 |
+;; untyped_call
|
mgl@1371
|
14529 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
14530 |
+;; Subrutine call instruction returning a value of any type.
|
mgl@1371
|
14531 |
+;; The code is copied from m68k.md (except gen_blockage is removed)
|
mgl@1371
|
14532 |
+;; Fixme!
|
mgl@1371
|
14533 |
+;;=============================================================================
|
mgl@1371
|
14534 |
+(define_expand "untyped_call"
|
mgl@1371
|
14535 |
+ [(parallel [(call (match_operand 0 "avr32_call_operand" "")
|
mgl@1371
|
14536 |
+ (const_int 0))
|
mgl@1371
|
14537 |
+ (match_operand 1 "" "")
|
mgl@1371
|
14538 |
+ (match_operand 2 "" "")])]
|
mgl@1371
|
14539 |
+ ""
|
mgl@1371
|
14540 |
+ {
|
mgl@1371
|
14541 |
+ int i;
|
mgl@1371
|
14542 |
+
|
mgl@1371
|
14543 |
+ emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
|
mgl@1371
|
14544 |
+
|
mgl@1371
|
14545 |
+ for (i = 0; i < XVECLEN (operands[2], 0); i++) {
|
mgl@1371
|
14546 |
+ rtx set = XVECEXP (operands[2], 0, i);
|
mgl@1371
|
14547 |
+ emit_move_insn (SET_DEST (set), SET_SRC (set));
|
mgl@1371
|
14548 |
+ }
|
mgl@1371
|
14549 |
+
|
mgl@1371
|
14550 |
+ /* The optimizer does not know that the call sets the function value
|
mgl@1371
|
14551 |
+ registers we stored in the result block. We avoid problems by
|
mgl@1371
|
14552 |
+ claiming that all hard registers are used and clobbered at this
|
mgl@1371
|
14553 |
+ point. */
|
mgl@1371
|
14554 |
+ emit_insn (gen_blockage ());
|
mgl@1371
|
14555 |
+
|
mgl@1371
|
14556 |
+ DONE;
|
mgl@1371
|
14557 |
+ })
|
mgl@1371
|
14558 |
+
|
mgl@1371
|
14559 |
+
|
mgl@1371
|
14560 |
+;;=============================================================================
|
mgl@1371
|
14561 |
+;; return
|
mgl@1371
|
14562 |
+;;=============================================================================
|
mgl@1371
|
14563 |
+
|
mgl@1371
|
14564 |
+(define_insn "return"
|
mgl@1371
|
14565 |
+ [(return)]
|
mgl@1371
|
14566 |
+ "USE_RETURN_INSN (FALSE)"
|
mgl@1371
|
14567 |
+ {
|
mgl@1371
|
14568 |
+ avr32_output_return_instruction(TRUE, FALSE, NULL, NULL);
|
mgl@1371
|
14569 |
+ return "";
|
mgl@1371
|
14570 |
+ }
|
mgl@1371
|
14571 |
+ [(set_attr "length" "4")
|
mgl@1371
|
14572 |
+ (set_attr "type" "call")]
|
mgl@1371
|
14573 |
+ )
|
mgl@1371
|
14574 |
+
|
mgl@1371
|
14575 |
+
|
mgl@1371
|
14576 |
+(define_insn "return_cond"
|
mgl@1371
|
14577 |
+ [(set (pc)
|
mgl@1371
|
14578 |
+ (if_then_else (match_operand 0 "avr32_comparison_operand" "")
|
mgl@1371
|
14579 |
+ (return)
|
mgl@1371
|
14580 |
+ (pc)))]
|
mgl@1371
|
14581 |
+ "USE_RETURN_INSN (TRUE)"
|
mgl@1371
|
14582 |
+ "ret%0\tr12";
|
mgl@1371
|
14583 |
+ [(set_attr "type" "call")])
|
mgl@1371
|
14584 |
+
|
mgl@1371
|
14585 |
+(define_insn "return_cond_predicable"
|
mgl@1371
|
14586 |
+ [(return)]
|
mgl@1371
|
14587 |
+ "USE_RETURN_INSN (TRUE)"
|
mgl@1371
|
14588 |
+ "ret%?\tr12";
|
mgl@1371
|
14589 |
+ [(set_attr "type" "call")
|
mgl@1371
|
14590 |
+ (set_attr "predicable" "yes")])
|
mgl@1371
|
14591 |
+
|
mgl@1371
|
14592 |
+
|
mgl@1371
|
14593 |
+(define_insn "return_imm"
|
mgl@1371
|
14594 |
+ [(parallel [(set (reg RETVAL_REGNUM) (match_operand 0 "immediate_operand" "i"))
|
mgl@1371
|
14595 |
+ (use (reg RETVAL_REGNUM))
|
mgl@1371
|
14596 |
+ (return)])]
|
mgl@1371
|
14597 |
+ "USE_RETURN_INSN (FALSE) &&
|
mgl@1371
|
14598 |
+ ((INTVAL(operands[0]) == -1) || (INTVAL(operands[0]) == 0) || (INTVAL(operands[0]) == 1))"
|
mgl@1371
|
14599 |
+ {
|
mgl@1371
|
14600 |
+ avr32_output_return_instruction(TRUE, FALSE, NULL, operands[0]);
|
mgl@1371
|
14601 |
+ return "";
|
mgl@1371
|
14602 |
+ }
|
mgl@1371
|
14603 |
+ [(set_attr "length" "4")
|
mgl@1371
|
14604 |
+ (set_attr "type" "call")]
|
mgl@1371
|
14605 |
+ )
|
mgl@1371
|
14606 |
+
|
mgl@1371
|
14607 |
+(define_insn "return_imm_cond"
|
mgl@1371
|
14608 |
+ [(parallel [(set (reg RETVAL_REGNUM) (match_operand 0 "immediate_operand" "i"))
|
mgl@1371
|
14609 |
+ (use (reg RETVAL_REGNUM))
|
mgl@1371
|
14610 |
+ (set (pc)
|
mgl@1371
|
14611 |
+ (if_then_else (match_operand 1 "avr32_comparison_operand" "")
|
mgl@1371
|
14612 |
+ (return)
|
mgl@1371
|
14613 |
+ (pc)))])]
|
mgl@1371
|
14614 |
+ "USE_RETURN_INSN (TRUE) &&
|
mgl@1371
|
14615 |
+ ((INTVAL(operands[0]) == -1) || (INTVAL(operands[0]) == 0) || (INTVAL(operands[0]) == 1))"
|
mgl@1371
|
14616 |
+ "ret%1\t%0";
|
mgl@1371
|
14617 |
+ [(set_attr "type" "call")]
|
mgl@1371
|
14618 |
+ )
|
mgl@1371
|
14619 |
+
|
mgl@1371
|
14620 |
+(define_insn "return_imm_predicable"
|
mgl@1371
|
14621 |
+ [(parallel [(set (reg RETVAL_REGNUM) (match_operand 0 "immediate_operand" "i"))
|
mgl@1371
|
14622 |
+ (use (reg RETVAL_REGNUM))
|
mgl@1371
|
14623 |
+ (return)])]
|
mgl@1371
|
14624 |
+ "USE_RETURN_INSN (TRUE) &&
|
mgl@1371
|
14625 |
+ ((INTVAL(operands[0]) == -1) || (INTVAL(operands[0]) == 0) || (INTVAL(operands[0]) == 1))"
|
mgl@1371
|
14626 |
+ "ret%?\t%0";
|
mgl@1371
|
14627 |
+ [(set_attr "type" "call")
|
mgl@1371
|
14628 |
+ (set_attr "predicable" "yes")])
|
mgl@1371
|
14629 |
+
|
mgl@1371
|
14630 |
+(define_insn "return_<mode>reg"
|
mgl@1371
|
14631 |
+ [(set (reg RETVAL_REGNUM) (match_operand:MOVM 0 "register_operand" "r"))
|
mgl@1371
|
14632 |
+ (use (reg RETVAL_REGNUM))
|
mgl@1371
|
14633 |
+ (return)]
|
mgl@1371
|
14634 |
+ "USE_RETURN_INSN (TRUE)"
|
mgl@1371
|
14635 |
+ "ret%?\t%0";
|
mgl@1371
|
14636 |
+ [(set_attr "type" "call")
|
mgl@1371
|
14637 |
+ (set_attr "predicable" "yes")])
|
mgl@1371
|
14638 |
+
|
mgl@1371
|
14639 |
+(define_insn "return_<mode>reg_cond"
|
mgl@1371
|
14640 |
+ [(set (reg RETVAL_REGNUM) (match_operand:MOVM 0 "register_operand" "r"))
|
mgl@1371
|
14641 |
+ (use (reg RETVAL_REGNUM))
|
mgl@1371
|
14642 |
+ (set (pc)
|
mgl@1371
|
14643 |
+ (if_then_else (match_operator 1 "avr32_comparison_operator"
|
mgl@1371
|
14644 |
+ [(cc0) (const_int 0)])
|
mgl@1371
|
14645 |
+ (return)
|
mgl@1371
|
14646 |
+ (pc)))]
|
mgl@1371
|
14647 |
+ "USE_RETURN_INSN (TRUE)"
|
mgl@1371
|
14648 |
+ "ret%1\t%0";
|
mgl@1371
|
14649 |
+ [(set_attr "type" "call")])
|
mgl@1371
|
14650 |
+
|
mgl@1371
|
14651 |
+;;=============================================================================
|
mgl@1371
|
14652 |
+;; nop
|
mgl@1371
|
14653 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
14654 |
+;; No-op instruction.
|
mgl@1371
|
14655 |
+;;=============================================================================
|
mgl@1371
|
14656 |
+(define_insn "nop"
|
mgl@1371
|
14657 |
+ [(const_int 0)]
|
mgl@1371
|
14658 |
+ ""
|
mgl@1371
|
14659 |
+ "nop"
|
mgl@1371
|
14660 |
+ [(set_attr "length" "2")
|
mgl@1371
|
14661 |
+ (set_attr "type" "alu")
|
mgl@1371
|
14662 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
14663 |
+
|
mgl@1371
|
14664 |
+;;=============================================================================
|
mgl@1371
|
14665 |
+;; nonlocal_goto_receiver
|
mgl@1371
|
14666 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
14667 |
+;; For targets with a return stack we must make sure to flush the return stack
|
mgl@1371
|
14668 |
+;; since it will be corrupt after a nonlocal goto.
|
mgl@1371
|
14669 |
+;;=============================================================================
|
mgl@1371
|
14670 |
+(define_expand "nonlocal_goto_receiver"
|
mgl@1371
|
14671 |
+ [(const_int 0)]
|
mgl@1371
|
14672 |
+ "TARGET_RETURN_STACK"
|
mgl@1371
|
14673 |
+ "
|
mgl@1371
|
14674 |
+ {
|
mgl@1371
|
14675 |
+ emit_insn ( gen_frs() );
|
mgl@1371
|
14676 |
+ DONE;
|
mgl@1371
|
14677 |
+ }
|
mgl@1371
|
14678 |
+ "
|
mgl@1371
|
14679 |
+ )
|
mgl@1371
|
14680 |
+
|
mgl@1371
|
14681 |
+
|
mgl@1371
|
14682 |
+;;=============================================================================
|
mgl@1371
|
14683 |
+;; builtin_setjmp_receiver
|
mgl@1371
|
14684 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
14685 |
+;; For pic code we need to reload the pic register.
|
mgl@1371
|
14686 |
+;; For targets with a return stack we must make sure to flush the return stack
|
mgl@1371
|
14687 |
+;; since it will probably be corrupted.
|
mgl@1371
|
14688 |
+;;=============================================================================
|
mgl@1371
|
14689 |
+(define_expand "builtin_setjmp_receiver"
|
mgl@1371
|
14690 |
+ [(label_ref (match_operand 0 "" ""))]
|
mgl@1371
|
14691 |
+ "flag_pic"
|
mgl@1371
|
14692 |
+ "
|
mgl@1371
|
14693 |
+ {
|
mgl@1371
|
14694 |
+ if ( TARGET_RETURN_STACK )
|
mgl@1371
|
14695 |
+ emit_insn ( gen_frs() );
|
mgl@1371
|
14696 |
+
|
mgl@1371
|
14697 |
+ avr32_load_pic_register ();
|
mgl@1371
|
14698 |
+ DONE;
|
mgl@1371
|
14699 |
+ }
|
mgl@1371
|
14700 |
+ "
|
mgl@1371
|
14701 |
+)
|
mgl@1371
|
14702 |
+
|
mgl@1371
|
14703 |
+
|
mgl@1371
|
14704 |
+;;=============================================================================
|
mgl@1371
|
14705 |
+;; indirect_jump
|
mgl@1371
|
14706 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
14707 |
+;; Jump to an address in reg or memory.
|
mgl@1371
|
14708 |
+;;=============================================================================
|
mgl@1371
|
14709 |
+(define_expand "indirect_jump"
|
mgl@1371
|
14710 |
+ [(set (pc)
|
mgl@1371
|
14711 |
+ (match_operand:SI 0 "general_operand" ""))]
|
mgl@1371
|
14712 |
+ ""
|
mgl@1371
|
14713 |
+ {
|
mgl@1371
|
14714 |
+ /* One of the ops has to be in a register. */
|
mgl@1371
|
14715 |
+ if ( (flag_pic || TARGET_HAS_ASM_ADDR_PSEUDOS )
|
mgl@1371
|
14716 |
+ && !avr32_legitimate_pic_operand_p(operands[0]) )
|
mgl@1371
|
14717 |
+ operands[0] = legitimize_pic_address (operands[0], SImode, 0);
|
mgl@1371
|
14718 |
+ else if ( flag_pic && avr32_address_operand(operands[0], GET_MODE(operands[0])) )
|
mgl@1371
|
14719 |
+ /* If we have an address operand then this function uses the pic register. */
|
mgl@1371
|
14720 |
+ current_function_uses_pic_offset_table = 1;
|
mgl@1371
|
14721 |
+ })
|
mgl@1371
|
14722 |
+
|
mgl@1371
|
14723 |
+
|
mgl@1371
|
14724 |
+(define_insn "indirect_jump_internal"
|
mgl@1371
|
14725 |
+ [(set (pc)
|
mgl@1371
|
14726 |
+ (match_operand:SI 0 "avr32_non_rmw_general_operand" "r,m,W"))]
|
mgl@1371
|
14727 |
+ ""
|
mgl@1371
|
14728 |
+ {
|
mgl@1371
|
14729 |
+ switch( which_alternative ){
|
mgl@1371
|
14730 |
+ case 0:
|
mgl@1371
|
14731 |
+ return "mov\tpc, %0";
|
mgl@1371
|
14732 |
+ case 1:
|
mgl@1371
|
14733 |
+ if ( avr32_const_pool_ref_operand(operands[0], GET_MODE(operands[0])) )
|
mgl@1371
|
14734 |
+ return "lddpc\tpc, %0";
|
mgl@1371
|
14735 |
+ else
|
mgl@1371
|
14736 |
+ return "ld.w\tpc, %0";
|
mgl@1371
|
14737 |
+ case 2:
|
mgl@1371
|
14738 |
+ if ( flag_pic )
|
mgl@1371
|
14739 |
+ return "ld.w\tpc, r6[%0@got]";
|
mgl@1371
|
14740 |
+ else
|
mgl@1371
|
14741 |
+ return "lda.w\tpc, %0";
|
mgl@1371
|
14742 |
+ default:
|
mgl@1371
|
14743 |
+ abort();
|
mgl@1371
|
14744 |
+ }
|
mgl@1371
|
14745 |
+ }
|
mgl@1371
|
14746 |
+ [(set_attr "length" "2,4,8")
|
mgl@1371
|
14747 |
+ (set_attr "type" "call,call,call")
|
mgl@1371
|
14748 |
+ (set_attr "cc" "none,none,clobber")])
|
mgl@1371
|
14749 |
+
|
mgl@1371
|
14750 |
+
|
mgl@1371
|
14751 |
+
|
mgl@1371
|
14752 |
+;;=============================================================================
|
mgl@1371
|
14753 |
+;; casesi and tablejump
|
mgl@1371
|
14754 |
+;;=============================================================================
|
mgl@1371
|
14755 |
+(define_insn "tablejump_add"
|
mgl@1371
|
14756 |
+ [(set (pc)
|
mgl@1371
|
14757 |
+ (plus:SI (match_operand:SI 0 "register_operand" "r")
|
mgl@1371
|
14758 |
+ (mult:SI (match_operand:SI 1 "register_operand" "r")
|
mgl@1371
|
14759 |
+ (match_operand:SI 2 "immediate_operand" "Ku04" ))))
|
mgl@1371
|
14760 |
+ (use (label_ref (match_operand 3 "" "")))]
|
mgl@1371
|
14761 |
+ "flag_pic &&
|
mgl@1371
|
14762 |
+ ((INTVAL(operands[2]) == 0) || (INTVAL(operands[2]) == 2) ||
|
mgl@1371
|
14763 |
+ (INTVAL(operands[2]) == 4) || (INTVAL(operands[2]) == 8))"
|
mgl@1371
|
14764 |
+ "add\tpc, %0, %1 << %p2"
|
mgl@1371
|
14765 |
+ [(set_attr "length" "4")
|
mgl@1371
|
14766 |
+ (set_attr "cc" "clobber")])
|
mgl@1371
|
14767 |
+
|
mgl@1371
|
14768 |
+(define_insn "tablejump_insn"
|
mgl@1371
|
14769 |
+ [(set (pc) (match_operand:SI 0 "memory_operand" "m"))
|
mgl@1371
|
14770 |
+ (use (label_ref (match_operand 1 "" "")))]
|
mgl@1371
|
14771 |
+ "!flag_pic"
|
mgl@1371
|
14772 |
+ "ld.w\tpc, %0"
|
mgl@1371
|
14773 |
+ [(set_attr "length" "4")
|
mgl@1371
|
14774 |
+ (set_attr "type" "call")
|
mgl@1371
|
14775 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
14776 |
+
|
mgl@1371
|
14777 |
+(define_expand "casesi"
|
mgl@1371
|
14778 |
+ [(match_operand:SI 0 "register_operand" "") ; index to jump on
|
mgl@1371
|
14779 |
+ (match_operand:SI 1 "const_int_operand" "") ; lower bound
|
mgl@1371
|
14780 |
+ (match_operand:SI 2 "const_int_operand" "") ; total range
|
mgl@1371
|
14781 |
+ (match_operand:SI 3 "" "") ; table label
|
mgl@1371
|
14782 |
+ (match_operand:SI 4 "" "")] ; Out of range label
|
mgl@1371
|
14783 |
+ ""
|
mgl@1371
|
14784 |
+ "
|
mgl@1371
|
14785 |
+ {
|
mgl@1371
|
14786 |
+ rtx reg;
|
mgl@1371
|
14787 |
+ rtx index = operands[0];
|
mgl@1371
|
14788 |
+ rtx low_bound = operands[1];
|
mgl@1371
|
14789 |
+ rtx range = operands[2];
|
mgl@1371
|
14790 |
+ rtx table_label = operands[3];
|
mgl@1371
|
14791 |
+ rtx oor_label = operands[4];
|
mgl@1371
|
14792 |
+
|
mgl@1371
|
14793 |
+ index = force_reg ( SImode, index );
|
mgl@1371
|
14794 |
+ if (low_bound != const0_rtx)
|
mgl@1371
|
14795 |
+ {
|
mgl@1371
|
14796 |
+ if (!avr32_const_ok_for_constraint_p(INTVAL (low_bound), 'I', \"Is21\")){
|
mgl@1371
|
14797 |
+ reg = force_reg(SImode, GEN_INT (INTVAL (low_bound)));
|
mgl@1371
|
14798 |
+ emit_insn (gen_subsi3 (reg, index,
|
mgl@1371
|
14799 |
+ reg));
|
mgl@1371
|
14800 |
+ } else {
|
mgl@1371
|
14801 |
+ reg = gen_reg_rtx (SImode);
|
mgl@1371
|
14802 |
+ emit_insn (gen_addsi3 (reg, index,
|
mgl@1371
|
14803 |
+ GEN_INT (-INTVAL (low_bound))));
|
mgl@1371
|
14804 |
+ }
|
mgl@1371
|
14805 |
+ index = reg;
|
mgl@1371
|
14806 |
+ }
|
mgl@1371
|
14807 |
+
|
mgl@1371
|
14808 |
+ if (!avr32_const_ok_for_constraint_p (INTVAL (range), 'K', \"Ks21\"))
|
mgl@1371
|
14809 |
+ range = force_reg (SImode, range);
|
mgl@1371
|
14810 |
+
|
mgl@1371
|
14811 |
+ emit_cmp_and_jump_insns ( index, range, GTU, NULL_RTX, SImode, 1, oor_label );
|
mgl@1371
|
14812 |
+ reg = gen_reg_rtx (SImode);
|
mgl@1371
|
14813 |
+ emit_move_insn ( reg, gen_rtx_LABEL_REF (VOIDmode, table_label));
|
mgl@1371
|
14814 |
+
|
mgl@1371
|
14815 |
+ if ( flag_pic )
|
mgl@1371
|
14816 |
+ emit_jump_insn ( gen_tablejump_add ( reg, index, GEN_INT(4), table_label));
|
mgl@1371
|
14817 |
+ else
|
mgl@1371
|
14818 |
+ emit_jump_insn (
|
mgl@1371
|
14819 |
+ gen_tablejump_insn ( gen_rtx_MEM ( SImode,
|
mgl@1371
|
14820 |
+ gen_rtx_PLUS ( SImode,
|
mgl@1371
|
14821 |
+ reg,
|
mgl@1371
|
14822 |
+ gen_rtx_MULT ( SImode,
|
mgl@1371
|
14823 |
+ index,
|
mgl@1371
|
14824 |
+ GEN_INT(4)))),
|
mgl@1371
|
14825 |
+ table_label));
|
mgl@1371
|
14826 |
+ DONE;
|
mgl@1371
|
14827 |
+ }"
|
mgl@1371
|
14828 |
+)
|
mgl@1371
|
14829 |
+
|
mgl@1371
|
14830 |
+
|
mgl@1371
|
14831 |
+
|
mgl@1371
|
14832 |
+(define_insn "prefetch"
|
mgl@1371
|
14833 |
+ [(prefetch (match_operand:SI 0 "avr32_ks16_address_operand" "p")
|
mgl@1371
|
14834 |
+ (match_operand 1 "const_int_operand" "")
|
mgl@1371
|
14835 |
+ (match_operand 2 "const_int_operand" ""))]
|
mgl@1371
|
14836 |
+ ""
|
mgl@1371
|
14837 |
+ {
|
mgl@1371
|
14838 |
+ return "pref\t%0";
|
mgl@1371
|
14839 |
+ }
|
mgl@1371
|
14840 |
+
|
mgl@1371
|
14841 |
+ [(set_attr "length" "4")
|
mgl@1371
|
14842 |
+ (set_attr "type" "load")
|
mgl@1371
|
14843 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
14844 |
+
|
mgl@1371
|
14845 |
+
|
mgl@1371
|
14846 |
+
|
mgl@1371
|
14847 |
+;;=============================================================================
|
mgl@1371
|
14848 |
+;; prologue
|
mgl@1371
|
14849 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
14850 |
+;; This pattern, if defined, emits RTL for entry to a function. The function
|
mgl@1371
|
14851 |
+;; entry i responsible for setting up the stack frame, initializing the frame
|
mgl@1371
|
14852 |
+;; pointer register, saving callee saved registers, etc.
|
mgl@1371
|
14853 |
+;;=============================================================================
|
mgl@1371
|
14854 |
+(define_expand "prologue"
|
mgl@1371
|
14855 |
+ [(clobber (const_int 0))]
|
mgl@1371
|
14856 |
+ ""
|
mgl@1371
|
14857 |
+ "
|
mgl@1371
|
14858 |
+ avr32_expand_prologue();
|
mgl@1371
|
14859 |
+ DONE;
|
mgl@1371
|
14860 |
+ "
|
mgl@1371
|
14861 |
+ )
|
mgl@1371
|
14862 |
+
|
mgl@1371
|
14863 |
+;;=============================================================================
|
mgl@1371
|
14864 |
+;; eh_return
|
mgl@1371
|
14865 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
14866 |
+;; This pattern, if defined, affects the way __builtin_eh_return, and
|
mgl@1371
|
14867 |
+;; thence the call frame exception handling library routines, are
|
mgl@1371
|
14868 |
+;; built. It is intended to handle non-trivial actions needed along
|
mgl@1371
|
14869 |
+;; the abnormal return path.
|
mgl@1371
|
14870 |
+;;
|
mgl@1371
|
14871 |
+;; The address of the exception handler to which the function should
|
mgl@1371
|
14872 |
+;; return is passed as operand to this pattern. It will normally need
|
mgl@1371
|
14873 |
+;; to copied by the pattern to some special register or memory
|
mgl@1371
|
14874 |
+;; location. If the pattern needs to determine the location of the
|
mgl@1371
|
14875 |
+;; target call frame in order to do so, it may use
|
mgl@1371
|
14876 |
+;; EH_RETURN_STACKADJ_RTX, if defined; it will have already been
|
mgl@1371
|
14877 |
+;; assigned.
|
mgl@1371
|
14878 |
+;;
|
mgl@1371
|
14879 |
+;; If this pattern is not defined, the default action will be to
|
mgl@1371
|
14880 |
+;; simply copy the return address to EH_RETURN_HANDLER_RTX. Either
|
mgl@1371
|
14881 |
+;; that macro or this pattern needs to be defined if call frame
|
mgl@1371
|
14882 |
+;; exception handling is to be used.
|
mgl@1371
|
14883 |
+
|
mgl@1371
|
14884 |
+;; We can't expand this before we know where the link register is stored.
|
mgl@1371
|
14885 |
+(define_insn_and_split "eh_return"
|
mgl@1371
|
14886 |
+ [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")]
|
mgl@1371
|
14887 |
+ VUNSPEC_EH_RETURN)
|
mgl@1371
|
14888 |
+ (clobber (match_scratch:SI 1 "=&r"))]
|
mgl@1371
|
14889 |
+ ""
|
mgl@1371
|
14890 |
+ "#"
|
mgl@1371
|
14891 |
+ "reload_completed"
|
mgl@1371
|
14892 |
+ [(const_int 0)]
|
mgl@1371
|
14893 |
+ "
|
mgl@1371
|
14894 |
+ {
|
mgl@1371
|
14895 |
+ avr32_set_return_address (operands[0], operands[1]);
|
mgl@1371
|
14896 |
+ DONE;
|
mgl@1371
|
14897 |
+ }"
|
mgl@1371
|
14898 |
+ )
|
mgl@1371
|
14899 |
+
|
mgl@1371
|
14900 |
+
|
mgl@1371
|
14901 |
+;;=============================================================================
|
mgl@1371
|
14902 |
+;; ffssi2
|
mgl@1371
|
14903 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
14904 |
+(define_insn "ffssi2"
|
mgl@1371
|
14905 |
+ [ (set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
14906 |
+ (ffs:SI (match_operand:SI 1 "register_operand" "r"))) ]
|
mgl@1371
|
14907 |
+ ""
|
mgl@1371
|
14908 |
+ "mov %0, %1
|
mgl@1371
|
14909 |
+ brev %0
|
mgl@1371
|
14910 |
+ clz %0, %0
|
mgl@1371
|
14911 |
+ sub %0, -1
|
mgl@1371
|
14912 |
+ cp %0, 33
|
mgl@1371
|
14913 |
+ moveq %0, 0"
|
mgl@1371
|
14914 |
+ [(set_attr "length" "18")
|
mgl@1371
|
14915 |
+ (set_attr "cc" "clobber")]
|
mgl@1371
|
14916 |
+ )
|
mgl@1371
|
14917 |
+
|
mgl@1371
|
14918 |
+
|
mgl@1371
|
14919 |
+
|
mgl@1371
|
14920 |
+;;=============================================================================
|
mgl@1371
|
14921 |
+;; swap_h
|
mgl@1371
|
14922 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
14923 |
+(define_insn "*swap_h"
|
mgl@1371
|
14924 |
+ [ (set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
14925 |
+ (ior:SI (ashift:SI (match_dup 0) (const_int 16))
|
mgl@1371
|
14926 |
+ (lshiftrt:SI (match_dup 0) (const_int 16))))]
|
mgl@1371
|
14927 |
+ ""
|
mgl@1371
|
14928 |
+ "swap.h %0"
|
mgl@1371
|
14929 |
+ [(set_attr "length" "2")]
|
mgl@1371
|
14930 |
+ )
|
mgl@1371
|
14931 |
+
|
mgl@1371
|
14932 |
+(define_insn_and_split "bswap_16"
|
mgl@1371
|
14933 |
+ [ (set (match_operand:HI 0 "avr32_bswap_operand" "=r,RKs13,r")
|
mgl@1371
|
14934 |
+ (ior:HI (and:HI (lshiftrt:HI (match_operand:HI 1 "avr32_bswap_operand" "r,r,RKs13")
|
mgl@1371
|
14935 |
+ (const_int 8))
|
mgl@1371
|
14936 |
+ (const_int 255))
|
mgl@1371
|
14937 |
+ (ashift:HI (and:HI (match_dup 1)
|
mgl@1371
|
14938 |
+ (const_int 255))
|
mgl@1371
|
14939 |
+ (const_int 8))))]
|
mgl@1371
|
14940 |
+ ""
|
mgl@1371
|
14941 |
+ {
|
mgl@1371
|
14942 |
+ switch ( which_alternative ){
|
mgl@1371
|
14943 |
+ case 0:
|
mgl@1371
|
14944 |
+ if ( REGNO(operands[0]) == REGNO(operands[1]))
|
mgl@1371
|
14945 |
+ return "swap.bh\t%0";
|
mgl@1371
|
14946 |
+ else
|
mgl@1371
|
14947 |
+ return "mov\t%0, %1\;swap.bh\t%0";
|
mgl@1371
|
14948 |
+ case 1:
|
mgl@1371
|
14949 |
+ return "stswp.h\t%0, %1";
|
mgl@1371
|
14950 |
+ case 2:
|
mgl@1371
|
14951 |
+ return "ldswp.sh\t%0, %1";
|
mgl@1371
|
14952 |
+ default:
|
mgl@1371
|
14953 |
+ abort();
|
mgl@1371
|
14954 |
+ }
|
mgl@1371
|
14955 |
+ }
|
mgl@1371
|
14956 |
+
|
mgl@1371
|
14957 |
+ "(reload_completed &&
|
mgl@1371
|
14958 |
+ REG_P(operands[0]) && REG_P(operands[1])
|
mgl@1371
|
14959 |
+ && (REGNO(operands[0]) != REGNO(operands[1])))"
|
mgl@1371
|
14960 |
+ [(set (match_dup 0) (match_dup 1))
|
mgl@1371
|
14961 |
+ (set (match_dup 0)
|
mgl@1371
|
14962 |
+ (ior:HI (and:HI (lshiftrt:HI (match_dup 0)
|
mgl@1371
|
14963 |
+ (const_int 8))
|
mgl@1371
|
14964 |
+ (const_int 255))
|
mgl@1371
|
14965 |
+ (ashift:HI (and:HI (match_dup 0)
|
mgl@1371
|
14966 |
+ (const_int 255))
|
mgl@1371
|
14967 |
+ (const_int 8))))]
|
mgl@1371
|
14968 |
+ ""
|
mgl@1371
|
14969 |
+
|
mgl@1371
|
14970 |
+ [(set_attr "length" "4,4,4")
|
mgl@1371
|
14971 |
+ (set_attr "type" "alu,store,load_rm")]
|
mgl@1371
|
14972 |
+ )
|
mgl@1371
|
14973 |
+
|
mgl@1371
|
14974 |
+(define_insn_and_split "bswap_32"
|
mgl@1371
|
14975 |
+ [ (set (match_operand:SI 0 "avr32_bswap_operand" "=r,RKs14,r")
|
mgl@1371
|
14976 |
+ (ior:SI (ior:SI (lshiftrt:SI (and:SI (match_operand:SI 1 "avr32_bswap_operand" "r,r,RKs14")
|
mgl@1371
|
14977 |
+ (const_int -16777216))
|
mgl@1371
|
14978 |
+ (const_int 24))
|
mgl@1371
|
14979 |
+ (lshiftrt:SI (and:SI (match_dup 1)
|
mgl@1371
|
14980 |
+ (const_int 16711680))
|
mgl@1371
|
14981 |
+ (const_int 8)))
|
mgl@1371
|
14982 |
+ (ior:SI (ashift:SI (and:SI (match_dup 1)
|
mgl@1371
|
14983 |
+ (const_int 65280))
|
mgl@1371
|
14984 |
+ (const_int 8))
|
mgl@1371
|
14985 |
+ (ashift:SI (and:SI (match_dup 1)
|
mgl@1371
|
14986 |
+ (const_int 255))
|
mgl@1371
|
14987 |
+ (const_int 24)))))]
|
mgl@1371
|
14988 |
+ ""
|
mgl@1371
|
14989 |
+ {
|
mgl@1371
|
14990 |
+ switch ( which_alternative ){
|
mgl@1371
|
14991 |
+ case 0:
|
mgl@1371
|
14992 |
+ if ( REGNO(operands[0]) == REGNO(operands[1]))
|
mgl@1371
|
14993 |
+ return "swap.b\t%0";
|
mgl@1371
|
14994 |
+ else
|
mgl@1371
|
14995 |
+ return "#";
|
mgl@1371
|
14996 |
+ case 1:
|
mgl@1371
|
14997 |
+ return "stswp.w\t%0, %1";
|
mgl@1371
|
14998 |
+ case 2:
|
mgl@1371
|
14999 |
+ return "ldswp.w\t%0, %1";
|
mgl@1371
|
15000 |
+ default:
|
mgl@1371
|
15001 |
+ abort();
|
mgl@1371
|
15002 |
+ }
|
mgl@1371
|
15003 |
+ }
|
mgl@1371
|
15004 |
+ "(reload_completed &&
|
mgl@1371
|
15005 |
+ REG_P(operands[0]) && REG_P(operands[1])
|
mgl@1371
|
15006 |
+ && (REGNO(operands[0]) != REGNO(operands[1])))"
|
mgl@1371
|
15007 |
+ [(set (match_dup 0) (match_dup 1))
|
mgl@1371
|
15008 |
+ (set (match_dup 0)
|
mgl@1371
|
15009 |
+ (ior:SI (ior:SI (lshiftrt:SI (and:SI (match_dup 0)
|
mgl@1371
|
15010 |
+ (const_int -16777216))
|
mgl@1371
|
15011 |
+ (const_int 24))
|
mgl@1371
|
15012 |
+ (lshiftrt:SI (and:SI (match_dup 0)
|
mgl@1371
|
15013 |
+ (const_int 16711680))
|
mgl@1371
|
15014 |
+ (const_int 8)))
|
mgl@1371
|
15015 |
+ (ior:SI (ashift:SI (and:SI (match_dup 0)
|
mgl@1371
|
15016 |
+ (const_int 65280))
|
mgl@1371
|
15017 |
+ (const_int 8))
|
mgl@1371
|
15018 |
+ (ashift:SI (and:SI (match_dup 0)
|
mgl@1371
|
15019 |
+ (const_int 255))
|
mgl@1371
|
15020 |
+ (const_int 24)))))]
|
mgl@1371
|
15021 |
+ ""
|
mgl@1371
|
15022 |
+
|
mgl@1371
|
15023 |
+ [(set_attr "length" "4,4,4")
|
mgl@1371
|
15024 |
+ (set_attr "type" "alu,store,load_rm")]
|
mgl@1371
|
15025 |
+ )
|
mgl@1371
|
15026 |
+
|
mgl@1371
|
15027 |
+
|
mgl@1371
|
15028 |
+;;=============================================================================
|
mgl@1371
|
15029 |
+;; blockage
|
mgl@1371
|
15030 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
15031 |
+;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
|
mgl@1371
|
15032 |
+;; all of memory. This blocks insns from being moved across this point.
|
mgl@1371
|
15033 |
+
|
mgl@1371
|
15034 |
+(define_insn "blockage"
|
mgl@1371
|
15035 |
+ [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
|
mgl@1371
|
15036 |
+ ""
|
mgl@1371
|
15037 |
+ ""
|
mgl@1371
|
15038 |
+ [(set_attr "length" "0")]
|
mgl@1371
|
15039 |
+)
|
mgl@1371
|
15040 |
+
|
mgl@1371
|
15041 |
+;;=============================================================================
|
mgl@1371
|
15042 |
+;; clzsi2
|
mgl@1371
|
15043 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
15044 |
+(define_insn "clzsi2"
|
mgl@1371
|
15045 |
+ [ (set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
15046 |
+ (clz:SI (match_operand:SI 1 "register_operand" "r"))) ]
|
mgl@1371
|
15047 |
+ ""
|
mgl@1371
|
15048 |
+ "clz %0, %1"
|
mgl@1371
|
15049 |
+ [(set_attr "length" "4")
|
mgl@1371
|
15050 |
+ (set_attr "cc" "set_z")]
|
mgl@1371
|
15051 |
+ )
|
mgl@1371
|
15052 |
+
|
mgl@1371
|
15053 |
+;;=============================================================================
|
mgl@1371
|
15054 |
+;; ctzsi2
|
mgl@1371
|
15055 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
15056 |
+(define_insn "ctzsi2"
|
mgl@1371
|
15057 |
+ [ (set (match_operand:SI 0 "register_operand" "=r,r")
|
mgl@1371
|
15058 |
+ (ctz:SI (match_operand:SI 1 "register_operand" "0,r"))) ]
|
mgl@1371
|
15059 |
+ ""
|
mgl@1371
|
15060 |
+ "@
|
mgl@1371
|
15061 |
+ brev\t%0\;clz\t%0, %0
|
mgl@1371
|
15062 |
+ mov\t%0, %1\;brev\t%0\;clz\t%0, %0"
|
mgl@1371
|
15063 |
+ [(set_attr "length" "8")
|
mgl@1371
|
15064 |
+ (set_attr "cc" "set_z")]
|
mgl@1371
|
15065 |
+ )
|
mgl@1371
|
15066 |
+
|
mgl@1371
|
15067 |
+;;=============================================================================
|
mgl@1371
|
15068 |
+;; cache instructions
|
mgl@1371
|
15069 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
15070 |
+(define_insn "cache"
|
mgl@1371
|
15071 |
+ [ (unspec_volatile [(match_operand:SI 0 "avr32_ks11_address_operand" "p")
|
mgl@1371
|
15072 |
+ (match_operand:SI 1 "immediate_operand" "Ku05")] VUNSPEC_CACHE)]
|
mgl@1371
|
15073 |
+ ""
|
mgl@1371
|
15074 |
+ "cache %0, %1"
|
mgl@1371
|
15075 |
+ [(set_attr "length" "4")]
|
mgl@1371
|
15076 |
+ )
|
mgl@1371
|
15077 |
+
|
mgl@1371
|
15078 |
+(define_insn "sync"
|
mgl@1371
|
15079 |
+ [ (unspec_volatile [(match_operand:SI 0 "immediate_operand" "Ku08")] VUNSPEC_SYNC)]
|
mgl@1371
|
15080 |
+ ""
|
mgl@1371
|
15081 |
+ "sync %0"
|
mgl@1371
|
15082 |
+ [(set_attr "length" "4")]
|
mgl@1371
|
15083 |
+ )
|
mgl@1371
|
15084 |
+
|
mgl@1371
|
15085 |
+;;=============================================================================
|
mgl@1371
|
15086 |
+;; TLB instructions
|
mgl@1371
|
15087 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
15088 |
+(define_insn "tlbr"
|
mgl@1371
|
15089 |
+ [ (unspec_volatile [(const_int 0)] VUNSPEC_TLBR)]
|
mgl@1371
|
15090 |
+ ""
|
mgl@1371
|
15091 |
+ "tlbr"
|
mgl@1371
|
15092 |
+ [(set_attr "length" "2")]
|
mgl@1371
|
15093 |
+ )
|
mgl@1371
|
15094 |
+
|
mgl@1371
|
15095 |
+(define_insn "tlbw"
|
mgl@1371
|
15096 |
+ [ (unspec_volatile [(const_int 0)] VUNSPEC_TLBW)]
|
mgl@1371
|
15097 |
+ ""
|
mgl@1371
|
15098 |
+ "tlbw"
|
mgl@1371
|
15099 |
+ [(set_attr "length" "2")]
|
mgl@1371
|
15100 |
+ )
|
mgl@1371
|
15101 |
+
|
mgl@1371
|
15102 |
+(define_insn "tlbs"
|
mgl@1371
|
15103 |
+ [ (unspec_volatile [(const_int 0)] VUNSPEC_TLBS)]
|
mgl@1371
|
15104 |
+ ""
|
mgl@1371
|
15105 |
+ "tlbs"
|
mgl@1371
|
15106 |
+ [(set_attr "length" "2")]
|
mgl@1371
|
15107 |
+ )
|
mgl@1371
|
15108 |
+
|
mgl@1371
|
15109 |
+;;=============================================================================
|
mgl@1371
|
15110 |
+;; Breakpoint instruction
|
mgl@1371
|
15111 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
15112 |
+(define_insn "breakpoint"
|
mgl@1371
|
15113 |
+ [ (unspec_volatile [(const_int 0)] VUNSPEC_BREAKPOINT)]
|
mgl@1371
|
15114 |
+ ""
|
mgl@1371
|
15115 |
+ "breakpoint"
|
mgl@1371
|
15116 |
+ [(set_attr "length" "2")]
|
mgl@1371
|
15117 |
+ )
|
mgl@1371
|
15118 |
+
|
mgl@1371
|
15119 |
+
|
mgl@1371
|
15120 |
+;;=============================================================================
|
mgl@1371
|
15121 |
+;; mtsr/mfsr instruction
|
mgl@1371
|
15122 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
15123 |
+(define_insn "mtsr"
|
mgl@1371
|
15124 |
+ [ (unspec_volatile [(match_operand 0 "immediate_operand" "i")
|
mgl@1371
|
15125 |
+ (match_operand:SI 1 "register_operand" "r")] VUNSPEC_MTSR)]
|
mgl@1371
|
15126 |
+ ""
|
mgl@1371
|
15127 |
+ "mtsr\t%0, %1"
|
mgl@1371
|
15128 |
+ [(set_attr "length" "4")]
|
mgl@1371
|
15129 |
+ )
|
mgl@1371
|
15130 |
+
|
mgl@1371
|
15131 |
+(define_insn "mfsr"
|
mgl@1371
|
15132 |
+ [ (set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
15133 |
+ (unspec_volatile:SI [(match_operand 1 "immediate_operand" "i")] VUNSPEC_MFSR)) ]
|
mgl@1371
|
15134 |
+ ""
|
mgl@1371
|
15135 |
+ "mfsr\t%0, %1"
|
mgl@1371
|
15136 |
+ [(set_attr "length" "4")]
|
mgl@1371
|
15137 |
+ )
|
mgl@1371
|
15138 |
+
|
mgl@1371
|
15139 |
+;;=============================================================================
|
mgl@1371
|
15140 |
+;; mtdr/mfdr instruction
|
mgl@1371
|
15141 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
15142 |
+(define_insn "mtdr"
|
mgl@1371
|
15143 |
+ [ (unspec_volatile [(match_operand 0 "immediate_operand" "i")
|
mgl@1371
|
15144 |
+ (match_operand:SI 1 "register_operand" "r")] VUNSPEC_MTDR)]
|
mgl@1371
|
15145 |
+ ""
|
mgl@1371
|
15146 |
+ "mtdr\t%0, %1"
|
mgl@1371
|
15147 |
+ [(set_attr "length" "4")]
|
mgl@1371
|
15148 |
+ )
|
mgl@1371
|
15149 |
+
|
mgl@1371
|
15150 |
+(define_insn "mfdr"
|
mgl@1371
|
15151 |
+ [ (set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
15152 |
+ (unspec_volatile:SI [(match_operand 1 "immediate_operand" "i")] VUNSPEC_MFDR)) ]
|
mgl@1371
|
15153 |
+ ""
|
mgl@1371
|
15154 |
+ "mfdr\t%0, %1"
|
mgl@1371
|
15155 |
+ [(set_attr "length" "4")]
|
mgl@1371
|
15156 |
+ )
|
mgl@1371
|
15157 |
+
|
mgl@1371
|
15158 |
+;;=============================================================================
|
mgl@1371
|
15159 |
+;; musfr
|
mgl@1371
|
15160 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
15161 |
+(define_insn "musfr"
|
mgl@1371
|
15162 |
+ [ (unspec_volatile [(match_operand:SI 0 "register_operand" "r")] VUNSPEC_MUSFR)]
|
mgl@1371
|
15163 |
+ ""
|
mgl@1371
|
15164 |
+ "musfr\t%0"
|
mgl@1371
|
15165 |
+ [(set_attr "length" "2")
|
mgl@1371
|
15166 |
+ (set_attr "cc" "clobber")]
|
mgl@1371
|
15167 |
+ )
|
mgl@1371
|
15168 |
+
|
mgl@1371
|
15169 |
+(define_insn "mustr"
|
mgl@1371
|
15170 |
+ [ (set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
15171 |
+ (unspec_volatile:SI [(const_int 0)] VUNSPEC_MUSTR)) ]
|
mgl@1371
|
15172 |
+ ""
|
mgl@1371
|
15173 |
+ "mustr\t%0"
|
mgl@1371
|
15174 |
+ [(set_attr "length" "2")]
|
mgl@1371
|
15175 |
+ )
|
mgl@1371
|
15176 |
+
|
mgl@1371
|
15177 |
+(define_insn "ssrf"
|
mgl@1371
|
15178 |
+ [ (unspec_volatile [(match_operand:SI 0 "immediate_operand" "Ku05")] VUNSPEC_SSRF)]
|
mgl@1371
|
15179 |
+ ""
|
mgl@1371
|
15180 |
+ "ssrf %0"
|
mgl@1371
|
15181 |
+ [(set_attr "length" "2")
|
mgl@1371
|
15182 |
+ (set_attr "cc" "clobber")]
|
mgl@1371
|
15183 |
+ )
|
mgl@1371
|
15184 |
+
|
mgl@1371
|
15185 |
+(define_insn "csrf"
|
mgl@1371
|
15186 |
+ [ (unspec_volatile [(match_operand:SI 0 "immediate_operand" "Ku05")] VUNSPEC_CSRF)]
|
mgl@1371
|
15187 |
+ ""
|
mgl@1371
|
15188 |
+ "csrf %0"
|
mgl@1371
|
15189 |
+ [(set_attr "length" "2")
|
mgl@1371
|
15190 |
+ (set_attr "cc" "clobber")]
|
mgl@1371
|
15191 |
+ )
|
mgl@1371
|
15192 |
+
|
mgl@1371
|
15193 |
+;;=============================================================================
|
mgl@1371
|
15194 |
+;; Flush Return Stack instruction
|
mgl@1371
|
15195 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
15196 |
+(define_insn "frs"
|
mgl@1371
|
15197 |
+ [ (unspec_volatile [(const_int 0)] VUNSPEC_FRS)]
|
mgl@1371
|
15198 |
+ ""
|
mgl@1371
|
15199 |
+ "frs"
|
mgl@1371
|
15200 |
+ [(set_attr "length" "2")
|
mgl@1371
|
15201 |
+ (set_attr "cc" "none")]
|
mgl@1371
|
15202 |
+ )
|
mgl@1371
|
15203 |
+
|
mgl@1371
|
15204 |
+
|
mgl@1371
|
15205 |
+;;=============================================================================
|
mgl@1371
|
15206 |
+;; Saturation Round Scale instruction
|
mgl@1371
|
15207 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
15208 |
+(define_insn "sats"
|
mgl@1371
|
15209 |
+ [ (set (match_operand:SI 0 "register_operand" "+r")
|
mgl@1371
|
15210 |
+ (unspec:SI [(match_dup 0)
|
mgl@1371
|
15211 |
+ (match_operand 1 "immediate_operand" "Ku05")
|
mgl@1371
|
15212 |
+ (match_operand 2 "immediate_operand" "Ku05")]
|
mgl@1371
|
15213 |
+ UNSPEC_SATS)) ]
|
mgl@1371
|
15214 |
+ "TARGET_DSP"
|
mgl@1371
|
15215 |
+ "sats\t%0 >> %1, %2"
|
mgl@1371
|
15216 |
+ [(set_attr "type" "alu_sat")
|
mgl@1371
|
15217 |
+ (set_attr "length" "4")]
|
mgl@1371
|
15218 |
+ )
|
mgl@1371
|
15219 |
+
|
mgl@1371
|
15220 |
+(define_insn "satu"
|
mgl@1371
|
15221 |
+ [ (set (match_operand:SI 0 "register_operand" "+r")
|
mgl@1371
|
15222 |
+ (unspec:SI [(match_dup 0)
|
mgl@1371
|
15223 |
+ (match_operand 1 "immediate_operand" "Ku05")
|
mgl@1371
|
15224 |
+ (match_operand 2 "immediate_operand" "Ku05")]
|
mgl@1371
|
15225 |
+ UNSPEC_SATU)) ]
|
mgl@1371
|
15226 |
+ "TARGET_DSP"
|
mgl@1371
|
15227 |
+ "satu\t%0 >> %1, %2"
|
mgl@1371
|
15228 |
+ [(set_attr "type" "alu_sat")
|
mgl@1371
|
15229 |
+ (set_attr "length" "4")]
|
mgl@1371
|
15230 |
+ )
|
mgl@1371
|
15231 |
+
|
mgl@1371
|
15232 |
+(define_insn "satrnds"
|
mgl@1371
|
15233 |
+ [ (set (match_operand:SI 0 "register_operand" "+r")
|
mgl@1371
|
15234 |
+ (unspec:SI [(match_dup 0)
|
mgl@1371
|
15235 |
+ (match_operand 1 "immediate_operand" "Ku05")
|
mgl@1371
|
15236 |
+ (match_operand 2 "immediate_operand" "Ku05")]
|
mgl@1371
|
15237 |
+ UNSPEC_SATRNDS)) ]
|
mgl@1371
|
15238 |
+ "TARGET_DSP"
|
mgl@1371
|
15239 |
+ "satrnds\t%0 >> %1, %2"
|
mgl@1371
|
15240 |
+ [(set_attr "type" "alu_sat")
|
mgl@1371
|
15241 |
+ (set_attr "length" "4")]
|
mgl@1371
|
15242 |
+ )
|
mgl@1371
|
15243 |
+
|
mgl@1371
|
15244 |
+(define_insn "satrndu"
|
mgl@1371
|
15245 |
+ [ (set (match_operand:SI 0 "register_operand" "+r")
|
mgl@1371
|
15246 |
+ (unspec:SI [(match_dup 0)
|
mgl@1371
|
15247 |
+ (match_operand 1 "immediate_operand" "Ku05")
|
mgl@1371
|
15248 |
+ (match_operand 2 "immediate_operand" "Ku05")]
|
mgl@1371
|
15249 |
+ UNSPEC_SATRNDU)) ]
|
mgl@1371
|
15250 |
+ "TARGET_DSP"
|
mgl@1371
|
15251 |
+ "sats\t%0 >> %1, %2"
|
mgl@1371
|
15252 |
+ [(set_attr "type" "alu_sat")
|
mgl@1371
|
15253 |
+ (set_attr "length" "4")]
|
mgl@1371
|
15254 |
+ )
|
mgl@1371
|
15255 |
+
|
mgl@1371
|
15256 |
+;; Special patterns for dealing with the constant pool
|
mgl@1371
|
15257 |
+
|
mgl@1371
|
15258 |
+(define_insn "align_4"
|
mgl@1371
|
15259 |
+ [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
|
mgl@1371
|
15260 |
+ ""
|
mgl@1371
|
15261 |
+ {
|
mgl@1371
|
15262 |
+ assemble_align (32);
|
mgl@1371
|
15263 |
+ return "";
|
mgl@1371
|
15264 |
+ }
|
mgl@1371
|
15265 |
+ [(set_attr "length" "2")]
|
mgl@1371
|
15266 |
+)
|
mgl@1371
|
15267 |
+
|
mgl@1371
|
15268 |
+(define_insn "consttable_start"
|
mgl@1371
|
15269 |
+ [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_START)]
|
mgl@1371
|
15270 |
+ ""
|
mgl@1371
|
15271 |
+ {
|
mgl@1371
|
15272 |
+ return ".cpool";
|
mgl@1371
|
15273 |
+ }
|
mgl@1371
|
15274 |
+ [(set_attr "length" "0")]
|
mgl@1371
|
15275 |
+ )
|
mgl@1371
|
15276 |
+
|
mgl@1371
|
15277 |
+(define_insn "consttable_end"
|
mgl@1371
|
15278 |
+ [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
|
mgl@1371
|
15279 |
+ ""
|
mgl@1371
|
15280 |
+ {
|
mgl@1371
|
15281 |
+ making_const_table = FALSE;
|
mgl@1371
|
15282 |
+ return "";
|
mgl@1371
|
15283 |
+ }
|
mgl@1371
|
15284 |
+ [(set_attr "length" "0")]
|
mgl@1371
|
15285 |
+)
|
mgl@1371
|
15286 |
+
|
mgl@1371
|
15287 |
+
|
mgl@1371
|
15288 |
+(define_insn "consttable_4"
|
mgl@1371
|
15289 |
+ [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
|
mgl@1371
|
15290 |
+ ""
|
mgl@1371
|
15291 |
+ {
|
mgl@1371
|
15292 |
+ making_const_table = TRUE;
|
mgl@1371
|
15293 |
+ switch (GET_MODE_CLASS (GET_MODE (operands[0])))
|
mgl@1371
|
15294 |
+ {
|
mgl@1371
|
15295 |
+ case MODE_FLOAT:
|
mgl@1371
|
15296 |
+ {
|
mgl@1371
|
15297 |
+ REAL_VALUE_TYPE r;
|
mgl@1371
|
15298 |
+ char real_string[1024];
|
mgl@1371
|
15299 |
+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
|
mgl@1371
|
15300 |
+ real_to_decimal(real_string, &r, 1024, 0, 1);
|
mgl@1371
|
15301 |
+ asm_fprintf (asm_out_file, "\t.float\t%s\n", real_string);
|
mgl@1371
|
15302 |
+ break;
|
mgl@1371
|
15303 |
+ }
|
mgl@1371
|
15304 |
+ default:
|
mgl@1371
|
15305 |
+ assemble_integer (operands[0], 4, 0, 1);
|
mgl@1371
|
15306 |
+ break;
|
mgl@1371
|
15307 |
+ }
|
mgl@1371
|
15308 |
+ return "";
|
mgl@1371
|
15309 |
+ }
|
mgl@1371
|
15310 |
+ [(set_attr "length" "4")]
|
mgl@1371
|
15311 |
+)
|
mgl@1371
|
15312 |
+
|
mgl@1371
|
15313 |
+(define_insn "consttable_8"
|
mgl@1371
|
15314 |
+ [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
|
mgl@1371
|
15315 |
+ ""
|
mgl@1371
|
15316 |
+ {
|
mgl@1371
|
15317 |
+ making_const_table = TRUE;
|
mgl@1371
|
15318 |
+ switch (GET_MODE_CLASS (GET_MODE (operands[0])))
|
mgl@1371
|
15319 |
+ {
|
mgl@1371
|
15320 |
+ case MODE_FLOAT:
|
mgl@1371
|
15321 |
+ {
|
mgl@1371
|
15322 |
+ REAL_VALUE_TYPE r;
|
mgl@1371
|
15323 |
+ char real_string[1024];
|
mgl@1371
|
15324 |
+ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
|
mgl@1371
|
15325 |
+ real_to_decimal(real_string, &r, 1024, 0, 1);
|
mgl@1371
|
15326 |
+ asm_fprintf (asm_out_file, "\t.double\t%s\n", real_string);
|
mgl@1371
|
15327 |
+ break;
|
mgl@1371
|
15328 |
+ }
|
mgl@1371
|
15329 |
+ default:
|
mgl@1371
|
15330 |
+ assemble_integer(operands[0], 8, 0, 1);
|
mgl@1371
|
15331 |
+ break;
|
mgl@1371
|
15332 |
+ }
|
mgl@1371
|
15333 |
+ return "";
|
mgl@1371
|
15334 |
+ }
|
mgl@1371
|
15335 |
+ [(set_attr "length" "8")]
|
mgl@1371
|
15336 |
+)
|
mgl@1371
|
15337 |
+
|
mgl@1371
|
15338 |
+(define_insn "consttable_16"
|
mgl@1371
|
15339 |
+ [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_16)]
|
mgl@1371
|
15340 |
+ ""
|
mgl@1371
|
15341 |
+ {
|
mgl@1371
|
15342 |
+ making_const_table = TRUE;
|
mgl@1371
|
15343 |
+ assemble_integer(operands[0], 16, 0, 1);
|
mgl@1371
|
15344 |
+ return "";
|
mgl@1371
|
15345 |
+ }
|
mgl@1371
|
15346 |
+ [(set_attr "length" "16")]
|
mgl@1371
|
15347 |
+)
|
mgl@1371
|
15348 |
+
|
mgl@1371
|
15349 |
+;;=============================================================================
|
mgl@1371
|
15350 |
+;; coprocessor instructions
|
mgl@1371
|
15351 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
15352 |
+(define_insn "cop"
|
mgl@1371
|
15353 |
+ [ (unspec_volatile [(match_operand 0 "immediate_operand" "Ku03")
|
mgl@1371
|
15354 |
+ (match_operand 1 "immediate_operand" "Ku04")
|
mgl@1371
|
15355 |
+ (match_operand 2 "immediate_operand" "Ku04")
|
mgl@1371
|
15356 |
+ (match_operand 3 "immediate_operand" "Ku04")
|
mgl@1371
|
15357 |
+ (match_operand 4 "immediate_operand" "Ku07")] VUNSPEC_COP)]
|
mgl@1371
|
15358 |
+ ""
|
mgl@1371
|
15359 |
+ "cop\tcp%0, cr%1, cr%2, cr%3, %4"
|
mgl@1371
|
15360 |
+ [(set_attr "length" "4")]
|
mgl@1371
|
15361 |
+ )
|
mgl@1371
|
15362 |
+
|
mgl@1371
|
15363 |
+(define_insn "mvcrsi"
|
mgl@1371
|
15364 |
+ [ (set (match_operand:SI 0 "avr32_cop_move_operand" "=r,<,Z")
|
mgl@1371
|
15365 |
+ (unspec_volatile:SI [(match_operand 1 "immediate_operand" "Ku03,Ku03,Ku03")
|
mgl@1371
|
15366 |
+ (match_operand 2 "immediate_operand" "Ku04,Ku04,Ku04")]
|
mgl@1371
|
15367 |
+ VUNSPEC_MVCR)) ]
|
mgl@1371
|
15368 |
+ ""
|
mgl@1371
|
15369 |
+ "@
|
mgl@1371
|
15370 |
+ mvcr.w\tcp%1, %0, cr%2
|
mgl@1371
|
15371 |
+ stcm.w\tcp%1, %0, cr%2
|
mgl@1371
|
15372 |
+ stc.w\tcp%1, %0, cr%2"
|
mgl@1371
|
15373 |
+ [(set_attr "length" "4")]
|
mgl@1371
|
15374 |
+ )
|
mgl@1371
|
15375 |
+
|
mgl@1371
|
15376 |
+(define_insn "mvcrdi"
|
mgl@1371
|
15377 |
+ [ (set (match_operand:DI 0 "avr32_cop_move_operand" "=r,<,Z")
|
mgl@1371
|
15378 |
+ (unspec_volatile:DI [(match_operand 1 "immediate_operand" "Ku03,Ku03,Ku03")
|
mgl@1371
|
15379 |
+ (match_operand 2 "immediate_operand" "Ku04,Ku04,Ku04")]
|
mgl@1371
|
15380 |
+ VUNSPEC_MVCR)) ]
|
mgl@1371
|
15381 |
+ ""
|
mgl@1371
|
15382 |
+ "@
|
mgl@1371
|
15383 |
+ mvcr.d\tcp%1, %0, cr%2
|
mgl@1371
|
15384 |
+ stcm.d\tcp%1, %0, cr%2-cr%i2
|
mgl@1371
|
15385 |
+ stc.d\tcp%1, %0, cr%2"
|
mgl@1371
|
15386 |
+ [(set_attr "length" "4")]
|
mgl@1371
|
15387 |
+ )
|
mgl@1371
|
15388 |
+
|
mgl@1371
|
15389 |
+(define_insn "mvrcsi"
|
mgl@1371
|
15390 |
+ [ (unspec_volatile:SI [(match_operand 0 "immediate_operand" "Ku03,Ku03,Ku03")
|
mgl@1371
|
15391 |
+ (match_operand 1 "immediate_operand" "Ku04,Ku04,Ku04")
|
mgl@1371
|
15392 |
+ (match_operand:SI 2 "avr32_cop_move_operand" "r,>,Z")]
|
mgl@1371
|
15393 |
+ VUNSPEC_MVRC)]
|
mgl@1371
|
15394 |
+ ""
|
mgl@1371
|
15395 |
+ {
|
mgl@1371
|
15396 |
+ switch (which_alternative){
|
mgl@1371
|
15397 |
+ case 0:
|
mgl@1371
|
15398 |
+ return "mvrc.w\tcp%0, cr%1, %2";
|
mgl@1371
|
15399 |
+ case 1:
|
mgl@1371
|
15400 |
+ return "ldcm.w\tcp%0, %2, cr%1";
|
mgl@1371
|
15401 |
+ case 2:
|
mgl@1371
|
15402 |
+ return "ldc.w\tcp%0, cr%1, %2";
|
mgl@1371
|
15403 |
+ default:
|
mgl@1371
|
15404 |
+ abort();
|
mgl@1371
|
15405 |
+ }
|
mgl@1371
|
15406 |
+ }
|
mgl@1371
|
15407 |
+ [(set_attr "length" "4")]
|
mgl@1371
|
15408 |
+ )
|
mgl@1371
|
15409 |
+
|
mgl@1371
|
15410 |
+(define_insn "mvrcdi"
|
mgl@1371
|
15411 |
+ [ (unspec_volatile:DI [(match_operand 0 "immediate_operand" "Ku03,Ku03,Ku03")
|
mgl@1371
|
15412 |
+ (match_operand 1 "immediate_operand" "Ku04,Ku04,Ku04")
|
mgl@1371
|
15413 |
+ (match_operand:DI 2 "avr32_cop_move_operand" "r,>,Z")]
|
mgl@1371
|
15414 |
+ VUNSPEC_MVRC)]
|
mgl@1371
|
15415 |
+ ""
|
mgl@1371
|
15416 |
+ {
|
mgl@1371
|
15417 |
+ switch (which_alternative){
|
mgl@1371
|
15418 |
+ case 0:
|
mgl@1371
|
15419 |
+ return "mvrc.d\tcp%0, cr%1, %2";
|
mgl@1371
|
15420 |
+ case 1:
|
mgl@1371
|
15421 |
+ return "ldcm.d\tcp%0, %2, cr%1-cr%i1";
|
mgl@1371
|
15422 |
+ case 2:
|
mgl@1371
|
15423 |
+ return "ldc.d\tcp%0, cr%1, %2";
|
mgl@1371
|
15424 |
+ default:
|
mgl@1371
|
15425 |
+ abort();
|
mgl@1371
|
15426 |
+ }
|
mgl@1371
|
15427 |
+ }
|
mgl@1371
|
15428 |
+ [(set_attr "length" "4")]
|
mgl@1371
|
15429 |
+ )
|
mgl@1371
|
15430 |
+
|
mgl@1371
|
15431 |
+;;=============================================================================
|
mgl@1371
|
15432 |
+;; epilogue
|
mgl@1371
|
15433 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
15434 |
+;; This pattern emits RTL for exit from a function. The function exit is
|
mgl@1371
|
15435 |
+;; responsible for deallocating the stack frame, restoring callee saved
|
mgl@1371
|
15436 |
+;; registers and emitting the return instruction.
|
mgl@1371
|
15437 |
+;; ToDo: using TARGET_ASM_FUNCTION_PROLOGUE instead.
|
mgl@1371
|
15438 |
+;;=============================================================================
|
mgl@1371
|
15439 |
+(define_expand "epilogue"
|
mgl@1371
|
15440 |
+ [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
|
mgl@1371
|
15441 |
+ ""
|
mgl@1371
|
15442 |
+ "
|
mgl@1371
|
15443 |
+ if (USE_RETURN_INSN (FALSE)){
|
mgl@1371
|
15444 |
+ emit_jump_insn (gen_return ());
|
mgl@1371
|
15445 |
+ DONE;
|
mgl@1371
|
15446 |
+ }
|
mgl@1371
|
15447 |
+ emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
|
mgl@1371
|
15448 |
+ gen_rtvec (1,
|
mgl@1371
|
15449 |
+ gen_rtx_RETURN (VOIDmode)),
|
mgl@1371
|
15450 |
+ VUNSPEC_EPILOGUE));
|
mgl@1371
|
15451 |
+ DONE;
|
mgl@1371
|
15452 |
+ "
|
mgl@1371
|
15453 |
+ )
|
mgl@1371
|
15454 |
+
|
mgl@1371
|
15455 |
+(define_insn "*epilogue_insns"
|
mgl@1371
|
15456 |
+ [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
|
mgl@1371
|
15457 |
+ ""
|
mgl@1371
|
15458 |
+ {
|
mgl@1371
|
15459 |
+ avr32_output_return_instruction (FALSE, FALSE, NULL, NULL);
|
mgl@1371
|
15460 |
+ return "";
|
mgl@1371
|
15461 |
+ }
|
mgl@1371
|
15462 |
+ ; Length is absolute worst case
|
mgl@1371
|
15463 |
+ [(set_attr "type" "branch")
|
mgl@1371
|
15464 |
+ (set_attr "length" "12")]
|
mgl@1371
|
15465 |
+ )
|
mgl@1371
|
15466 |
+
|
mgl@1371
|
15467 |
+(define_insn "*epilogue_insns_ret_imm"
|
mgl@1371
|
15468 |
+ [(parallel [(set (reg RETVAL_REGNUM) (match_operand 0 "immediate_operand" "i"))
|
mgl@1371
|
15469 |
+ (use (reg RETVAL_REGNUM))
|
mgl@1371
|
15470 |
+ (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
|
mgl@1371
|
15471 |
+ "((INTVAL(operands[0]) == -1) || (INTVAL(operands[0]) == 0) || (INTVAL(operands[0]) == 1))"
|
mgl@1371
|
15472 |
+ {
|
mgl@1371
|
15473 |
+ avr32_output_return_instruction (FALSE, FALSE, NULL, operands[0]);
|
mgl@1371
|
15474 |
+ return "";
|
mgl@1371
|
15475 |
+ }
|
mgl@1371
|
15476 |
+ ; Length is absolute worst case
|
mgl@1371
|
15477 |
+ [(set_attr "type" "branch")
|
mgl@1371
|
15478 |
+ (set_attr "length" "12")]
|
mgl@1371
|
15479 |
+ )
|
mgl@1371
|
15480 |
+
|
mgl@1371
|
15481 |
+(define_insn "sibcall_epilogue"
|
mgl@1371
|
15482 |
+ [(unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)]
|
mgl@1371
|
15483 |
+ ""
|
mgl@1371
|
15484 |
+ {
|
mgl@1371
|
15485 |
+ avr32_output_return_instruction (FALSE, FALSE, NULL, NULL);
|
mgl@1371
|
15486 |
+ return "";
|
mgl@1371
|
15487 |
+ }
|
mgl@1371
|
15488 |
+;; Length is absolute worst case
|
mgl@1371
|
15489 |
+ [(set_attr "type" "branch")
|
mgl@1371
|
15490 |
+ (set_attr "length" "12")]
|
mgl@1371
|
15491 |
+ )
|
mgl@1371
|
15492 |
+
|
mgl@1371
|
15493 |
+(define_insn "*sibcall_epilogue_insns_ret_imm"
|
mgl@1371
|
15494 |
+ [(parallel [(set (reg RETVAL_REGNUM) (match_operand 0 "immediate_operand" "i"))
|
mgl@1371
|
15495 |
+ (use (reg RETVAL_REGNUM))
|
mgl@1371
|
15496 |
+ (unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)])]
|
mgl@1371
|
15497 |
+ "((INTVAL(operands[0]) == -1) || (INTVAL(operands[0]) == 0) || (INTVAL(operands[0]) == 1))"
|
mgl@1371
|
15498 |
+ {
|
mgl@1371
|
15499 |
+ avr32_output_return_instruction (FALSE, FALSE, NULL, operands[0]);
|
mgl@1371
|
15500 |
+ return "";
|
mgl@1371
|
15501 |
+ }
|
mgl@1371
|
15502 |
+ ; Length is absolute worst case
|
mgl@1371
|
15503 |
+ [(set_attr "type" "branch")
|
mgl@1371
|
15504 |
+ (set_attr "length" "12")]
|
mgl@1371
|
15505 |
+ )
|
mgl@1371
|
15506 |
+
|
mgl@1371
|
15507 |
+(define_insn "ldxi"
|
mgl@1371
|
15508 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
15509 |
+ (mem:SI (plus:SI
|
mgl@1371
|
15510 |
+ (match_operand:SI 1 "register_operand" "r")
|
mgl@1371
|
15511 |
+ (mult:SI (zero_extract:SI (match_operand:SI 2 "register_operand" "r")
|
mgl@1371
|
15512 |
+ (const_int 8)
|
mgl@1371
|
15513 |
+ (match_operand:SI 3 "immediate_operand" "Ku05"))
|
mgl@1371
|
15514 |
+ (const_int 4)))))]
|
mgl@1371
|
15515 |
+ "(INTVAL(operands[3]) == 24 || INTVAL(operands[3]) == 16 || INTVAL(operands[3]) == 8
|
mgl@1371
|
15516 |
+ || INTVAL(operands[3]) == 0)"
|
mgl@1371
|
15517 |
+ {
|
mgl@1371
|
15518 |
+ switch ( INTVAL(operands[3]) ){
|
mgl@1371
|
15519 |
+ case 0:
|
mgl@1371
|
15520 |
+ return "ld.w %0, %1[%2:b << 2]";
|
mgl@1371
|
15521 |
+ case 8:
|
mgl@1371
|
15522 |
+ return "ld.w %0, %1[%2:l << 2]";
|
mgl@1371
|
15523 |
+ case 16:
|
mgl@1371
|
15524 |
+ return "ld.w %0, %1[%2:u << 2]";
|
mgl@1371
|
15525 |
+ case 24:
|
mgl@1371
|
15526 |
+ return "ld.w %0, %1[%2:t << 2]";
|
mgl@1371
|
15527 |
+ default:
|
mgl@1371
|
15528 |
+ internal_error("illegal operand for ldxi");
|
mgl@1371
|
15529 |
+ }
|
mgl@1371
|
15530 |
+ }
|
mgl@1371
|
15531 |
+ [(set_attr "type" "load")
|
mgl@1371
|
15532 |
+ (set_attr "length" "4")
|
mgl@1371
|
15533 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
15534 |
+
|
mgl@1371
|
15535 |
+
|
mgl@1371
|
15536 |
+
|
mgl@1371
|
15537 |
+
|
mgl@1371
|
15538 |
+
|
mgl@1371
|
15539 |
+
|
mgl@1371
|
15540 |
+;;=============================================================================
|
mgl@1371
|
15541 |
+;; Peephole optimizing
|
mgl@1371
|
15542 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
15543 |
+;; Changing
|
mgl@1371
|
15544 |
+;; sub r8, r7, 8
|
mgl@1371
|
15545 |
+;; st.w r8[0x0], r12
|
mgl@1371
|
15546 |
+;; to
|
mgl@1371
|
15547 |
+;; sub r8, r7, 8
|
mgl@1371
|
15548 |
+;; st.w r7[-0x8], r12
|
mgl@1371
|
15549 |
+;;=============================================================================
|
mgl@1371
|
15550 |
+; (set (reg:SI 9 r8)
|
mgl@1371
|
15551 |
+; (plus:SI (reg/f:SI 6 r7)
|
mgl@1371
|
15552 |
+; (const_int ...)))
|
mgl@1371
|
15553 |
+; (set (mem:SI (reg:SI 9 r8))
|
mgl@1371
|
15554 |
+; (reg:SI 12 r12))
|
mgl@1371
|
15555 |
+(define_peephole2
|
mgl@1371
|
15556 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
15557 |
+ (plus:SI (match_operand:SI 1 "register_operand" "")
|
mgl@1371
|
15558 |
+ (match_operand:SI 2 "immediate_operand" "")))
|
mgl@1371
|
15559 |
+ (set (mem:SI (match_dup 0))
|
mgl@1371
|
15560 |
+ (match_operand:SI 3 "register_operand" ""))]
|
mgl@1371
|
15561 |
+ "REGNO(operands[0]) != REGNO(operands[1]) && avr32_const_ok_for_constraint_p(INTVAL(operands[2]), 'K', \"Ks16\")"
|
mgl@1371
|
15562 |
+ [(set (match_dup 0)
|
mgl@1371
|
15563 |
+ (plus:SI (match_dup 1)
|
mgl@1371
|
15564 |
+ (match_dup 2)))
|
mgl@1371
|
15565 |
+ (set (mem:SI (plus:SI (match_dup 1)
|
mgl@1371
|
15566 |
+ (match_dup 2)))
|
mgl@1371
|
15567 |
+ (match_dup 3))]
|
mgl@1371
|
15568 |
+ "")
|
mgl@1371
|
15569 |
+
|
mgl@1371
|
15570 |
+;;=============================================================================
|
mgl@1371
|
15571 |
+;; Peephole optimizing
|
mgl@1371
|
15572 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
15573 |
+;; Changing
|
mgl@1371
|
15574 |
+;; sub r6, r7, 4
|
mgl@1371
|
15575 |
+;; ld.w r6, r6[0x0]
|
mgl@1371
|
15576 |
+;; to
|
mgl@1371
|
15577 |
+;; sub r6, r7, 4
|
mgl@1371
|
15578 |
+;; ld.w r6, r7[-0x4]
|
mgl@1371
|
15579 |
+;;=============================================================================
|
mgl@1371
|
15580 |
+; (set (reg:SI 7 r6)
|
mgl@1371
|
15581 |
+; (plus:SI (reg/f:SI 6 r7)
|
mgl@1371
|
15582 |
+; (const_int -4 [0xfffffffc])))
|
mgl@1371
|
15583 |
+; (set (reg:SI 7 r6)
|
mgl@1371
|
15584 |
+; (mem:SI (reg:SI 7 r6)))
|
mgl@1371
|
15585 |
+(define_peephole2
|
mgl@1371
|
15586 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
15587 |
+ (plus:SI (match_operand:SI 1 "register_operand" "")
|
mgl@1371
|
15588 |
+ (match_operand:SI 2 "immediate_operand" "")))
|
mgl@1371
|
15589 |
+ (set (match_operand:SI 3 "register_operand" "")
|
mgl@1371
|
15590 |
+ (mem:SI (match_dup 0)))]
|
mgl@1371
|
15591 |
+ "REGNO(operands[0]) != REGNO(operands[1]) && avr32_const_ok_for_constraint_p(INTVAL(operands[2]), 'K', \"Ks16\")"
|
mgl@1371
|
15592 |
+ [(set (match_dup 0)
|
mgl@1371
|
15593 |
+ (plus:SI (match_dup 1)
|
mgl@1371
|
15594 |
+ (match_dup 2)))
|
mgl@1371
|
15595 |
+ (set (match_dup 3)
|
mgl@1371
|
15596 |
+ (mem:SI (plus:SI (match_dup 1)
|
mgl@1371
|
15597 |
+ (match_dup 2))))]
|
mgl@1371
|
15598 |
+ "")
|
mgl@1371
|
15599 |
+
|
mgl@1371
|
15600 |
+;;=============================================================================
|
mgl@1371
|
15601 |
+;; Peephole optimizing
|
mgl@1371
|
15602 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
15603 |
+;; Changing
|
mgl@1371
|
15604 |
+;; ld.sb r0, r7[-0x6]
|
mgl@1371
|
15605 |
+;; cashs.b r0
|
mgl@1371
|
15606 |
+;; to
|
mgl@1371
|
15607 |
+;; ld.sb r0, r7[-0x6]
|
mgl@1371
|
15608 |
+;;=============================================================================
|
mgl@1371
|
15609 |
+(define_peephole2
|
mgl@1371
|
15610 |
+ [(set (match_operand:QI 0 "register_operand" "")
|
mgl@1371
|
15611 |
+ (match_operand:QI 1 "load_sb_memory_operand" ""))
|
mgl@1371
|
15612 |
+ (set (match_operand:SI 2 "register_operand" "")
|
mgl@1371
|
15613 |
+ (sign_extend:SI (match_dup 0)))]
|
mgl@1371
|
15614 |
+ "(REGNO(operands[0]) == REGNO(operands[2]) || peep2_reg_dead_p(2, operands[0]))"
|
mgl@1371
|
15615 |
+ [(set (match_dup 2)
|
mgl@1371
|
15616 |
+ (sign_extend:SI (match_dup 1)))]
|
mgl@1371
|
15617 |
+ "")
|
mgl@1371
|
15618 |
+
|
mgl@1371
|
15619 |
+;;=============================================================================
|
mgl@1371
|
15620 |
+;; Peephole optimizing
|
mgl@1371
|
15621 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
15622 |
+;; Changing
|
mgl@1371
|
15623 |
+;; ld.ub r0, r7[-0x6]
|
mgl@1371
|
15624 |
+;; cashu.b r0
|
mgl@1371
|
15625 |
+;; to
|
mgl@1371
|
15626 |
+;; ld.ub r0, r7[-0x6]
|
mgl@1371
|
15627 |
+;;=============================================================================
|
mgl@1371
|
15628 |
+(define_peephole2
|
mgl@1371
|
15629 |
+ [(set (match_operand:QI 0 "register_operand" "")
|
mgl@1371
|
15630 |
+ (match_operand:QI 1 "memory_operand" ""))
|
mgl@1371
|
15631 |
+ (set (match_operand:SI 2 "register_operand" "")
|
mgl@1371
|
15632 |
+ (zero_extend:SI (match_dup 0)))]
|
mgl@1371
|
15633 |
+ "(REGNO(operands[0]) == REGNO(operands[2])) || peep2_reg_dead_p(2, operands[0])"
|
mgl@1371
|
15634 |
+ [(set (match_dup 2)
|
mgl@1371
|
15635 |
+ (zero_extend:SI (match_dup 1)))]
|
mgl@1371
|
15636 |
+ "")
|
mgl@1371
|
15637 |
+
|
mgl@1371
|
15638 |
+;;=============================================================================
|
mgl@1371
|
15639 |
+;; Peephole optimizing
|
mgl@1371
|
15640 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
15641 |
+;; Changing
|
mgl@1371
|
15642 |
+;; ld.sh r0, r7[-0x6]
|
mgl@1371
|
15643 |
+;; casts.h r0
|
mgl@1371
|
15644 |
+;; to
|
mgl@1371
|
15645 |
+;; ld.sh r0, r7[-0x6]
|
mgl@1371
|
15646 |
+;;=============================================================================
|
mgl@1371
|
15647 |
+(define_peephole2
|
mgl@1371
|
15648 |
+ [(set (match_operand:HI 0 "register_operand" "")
|
mgl@1371
|
15649 |
+ (match_operand:HI 1 "memory_operand" ""))
|
mgl@1371
|
15650 |
+ (set (match_operand:SI 2 "register_operand" "")
|
mgl@1371
|
15651 |
+ (sign_extend:SI (match_dup 0)))]
|
mgl@1371
|
15652 |
+ "(REGNO(operands[0]) == REGNO(operands[2])) || peep2_reg_dead_p(2, operands[0])"
|
mgl@1371
|
15653 |
+ [(set (match_dup 2)
|
mgl@1371
|
15654 |
+ (sign_extend:SI (match_dup 1)))]
|
mgl@1371
|
15655 |
+ "")
|
mgl@1371
|
15656 |
+
|
mgl@1371
|
15657 |
+;;=============================================================================
|
mgl@1371
|
15658 |
+;; Peephole optimizing
|
mgl@1371
|
15659 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
15660 |
+;; Changing
|
mgl@1371
|
15661 |
+;; ld.uh r0, r7[-0x6]
|
mgl@1371
|
15662 |
+;; castu.h r0
|
mgl@1371
|
15663 |
+;; to
|
mgl@1371
|
15664 |
+;; ld.uh r0, r7[-0x6]
|
mgl@1371
|
15665 |
+;;=============================================================================
|
mgl@1371
|
15666 |
+(define_peephole2
|
mgl@1371
|
15667 |
+ [(set (match_operand:HI 0 "register_operand" "")
|
mgl@1371
|
15668 |
+ (match_operand:HI 1 "memory_operand" ""))
|
mgl@1371
|
15669 |
+ (set (match_operand:SI 2 "register_operand" "")
|
mgl@1371
|
15670 |
+ (zero_extend:SI (match_dup 0)))]
|
mgl@1371
|
15671 |
+ "(REGNO(operands[0]) == REGNO(operands[2])) || peep2_reg_dead_p(2, operands[0])"
|
mgl@1371
|
15672 |
+ [(set (match_dup 2)
|
mgl@1371
|
15673 |
+ (zero_extend:SI (match_dup 1)))]
|
mgl@1371
|
15674 |
+ "")
|
mgl@1371
|
15675 |
+
|
mgl@1371
|
15676 |
+;;=============================================================================
|
mgl@1371
|
15677 |
+;; Peephole optimizing
|
mgl@1371
|
15678 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
15679 |
+;; Changing
|
mgl@1371
|
15680 |
+;; mul rd, rx, ry
|
mgl@1371
|
15681 |
+;; add rd2, rd
|
mgl@1371
|
15682 |
+;; or
|
mgl@1371
|
15683 |
+;; add rd2, rd, rd2
|
mgl@1371
|
15684 |
+;; to
|
mgl@1371
|
15685 |
+;; mac rd2, rx, ry
|
mgl@1371
|
15686 |
+;;=============================================================================
|
mgl@1371
|
15687 |
+(define_peephole2
|
mgl@1371
|
15688 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
15689 |
+ (mult:SI (match_operand:SI 1 "register_operand" "")
|
mgl@1371
|
15690 |
+ (match_operand:SI 2 "register_operand" "")))
|
mgl@1371
|
15691 |
+ (set (match_operand:SI 3 "register_operand" "")
|
mgl@1371
|
15692 |
+ (plus:SI (match_dup 3)
|
mgl@1371
|
15693 |
+ (match_dup 0)))]
|
mgl@1371
|
15694 |
+ "peep2_reg_dead_p(2, operands[0])"
|
mgl@1371
|
15695 |
+ [(set (match_dup 3)
|
mgl@1371
|
15696 |
+ (plus:SI (mult:SI (match_dup 1)
|
mgl@1371
|
15697 |
+ (match_dup 2))
|
mgl@1371
|
15698 |
+ (match_dup 3)))]
|
mgl@1371
|
15699 |
+ "")
|
mgl@1371
|
15700 |
+
|
mgl@1371
|
15701 |
+(define_peephole2
|
mgl@1371
|
15702 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
15703 |
+ (mult:SI (match_operand:SI 1 "register_operand" "")
|
mgl@1371
|
15704 |
+ (match_operand:SI 2 "register_operand" "")))
|
mgl@1371
|
15705 |
+ (set (match_operand:SI 3 "register_operand" "")
|
mgl@1371
|
15706 |
+ (plus:SI (match_dup 0)
|
mgl@1371
|
15707 |
+ (match_dup 3)))]
|
mgl@1371
|
15708 |
+ "peep2_reg_dead_p(2, operands[0])"
|
mgl@1371
|
15709 |
+ [(set (match_dup 3)
|
mgl@1371
|
15710 |
+ (plus:SI (mult:SI (match_dup 1)
|
mgl@1371
|
15711 |
+ (match_dup 2))
|
mgl@1371
|
15712 |
+ (match_dup 3)))]
|
mgl@1371
|
15713 |
+ "")
|
mgl@1371
|
15714 |
+
|
mgl@1371
|
15715 |
+
|
mgl@1371
|
15716 |
+;;=============================================================================
|
mgl@1371
|
15717 |
+;; Peephole optimizing
|
mgl@1371
|
15718 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
15719 |
+;; Changing
|
mgl@1371
|
15720 |
+;; bfextu rd, rs, k5, 1 or and(h/l) rd, one_bit_set_mask
|
mgl@1371
|
15721 |
+;; to
|
mgl@1371
|
15722 |
+;; bld rs, k5
|
mgl@1371
|
15723 |
+;;
|
mgl@1371
|
15724 |
+;; If rd is dead after the operation.
|
mgl@1371
|
15725 |
+;;=============================================================================
|
mgl@1371
|
15726 |
+(define_peephole2
|
mgl@1371
|
15727 |
+ [ (set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
15728 |
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "")
|
mgl@1371
|
15729 |
+ (const_int 1)
|
mgl@1371
|
15730 |
+ (match_operand:SI 2 "immediate_operand" "")))
|
mgl@1371
|
15731 |
+ (set (cc0)
|
mgl@1371
|
15732 |
+ (match_dup 0))]
|
mgl@1371
|
15733 |
+ "peep2_reg_dead_p(2, operands[0])"
|
mgl@1371
|
15734 |
+ [(set (cc0)
|
mgl@1371
|
15735 |
+ (and:SI (match_dup 1)
|
mgl@1371
|
15736 |
+ (match_dup 2)))]
|
mgl@1371
|
15737 |
+ "operands[2] = GEN_INT(1 << INTVAL(operands[2]));")
|
mgl@1371
|
15738 |
+
|
mgl@1371
|
15739 |
+(define_peephole2
|
mgl@1371
|
15740 |
+ [ (set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
15741 |
+ (and:SI (match_operand:SI 1 "register_operand" "")
|
mgl@1371
|
15742 |
+ (match_operand:SI 2 "one_bit_set_operand" "")))
|
mgl@1371
|
15743 |
+ (set (cc0)
|
mgl@1371
|
15744 |
+ (match_dup 0))]
|
mgl@1371
|
15745 |
+ "peep2_reg_dead_p(2, operands[0])"
|
mgl@1371
|
15746 |
+ [(set (cc0)
|
mgl@1371
|
15747 |
+ (and:SI (match_dup 1)
|
mgl@1371
|
15748 |
+ (match_dup 2)))]
|
mgl@1371
|
15749 |
+ "")
|
mgl@1371
|
15750 |
+
|
mgl@1371
|
15751 |
+;;=============================================================================
|
mgl@1371
|
15752 |
+;; Peephole optimizing
|
mgl@1371
|
15753 |
+;;-----------------------------------------------------------------------------
|
mgl@1371
|
15754 |
+;; Load with extracted index: ld.w Rd, Rb[Ri:{t/u/b/l} << 2]
|
mgl@1371
|
15755 |
+;;
|
mgl@1371
|
15756 |
+;;=============================================================================
|
mgl@1371
|
15757 |
+
|
mgl@1371
|
15758 |
+
|
mgl@1371
|
15759 |
+(define_peephole
|
mgl@1371
|
15760 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
15761 |
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "")
|
mgl@1371
|
15762 |
+ (const_int 8)
|
mgl@1371
|
15763 |
+ (match_operand:SI 2 "avr32_extract_shift_operand" "")))
|
mgl@1371
|
15764 |
+ (set (match_operand:SI 3 "register_operand" "")
|
mgl@1371
|
15765 |
+ (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
|
mgl@1371
|
15766 |
+ (match_operand:SI 4 "register_operand" ""))))]
|
mgl@1371
|
15767 |
+
|
mgl@1371
|
15768 |
+ "(dead_or_set_p(insn, operands[0]))"
|
mgl@1371
|
15769 |
+ {
|
mgl@1371
|
15770 |
+ switch ( INTVAL(operands[2]) ){
|
mgl@1371
|
15771 |
+ case 0:
|
mgl@1371
|
15772 |
+ return "ld.w %3, %4[%1:b << 2]";
|
mgl@1371
|
15773 |
+ case 8:
|
mgl@1371
|
15774 |
+ return "ld.w %3, %4[%1:l << 2]";
|
mgl@1371
|
15775 |
+ case 16:
|
mgl@1371
|
15776 |
+ return "ld.w %3, %4[%1:u << 2]";
|
mgl@1371
|
15777 |
+ case 24:
|
mgl@1371
|
15778 |
+ return "ld.w %3, %4[%1:t << 2]";
|
mgl@1371
|
15779 |
+ default:
|
mgl@1371
|
15780 |
+ internal_error("illegal operand for ldxi");
|
mgl@1371
|
15781 |
+ }
|
mgl@1371
|
15782 |
+ }
|
mgl@1371
|
15783 |
+ [(set_attr "type" "load")
|
mgl@1371
|
15784 |
+ (set_attr "length" "4")
|
mgl@1371
|
15785 |
+ (set_attr "cc" "clobber")]
|
mgl@1371
|
15786 |
+ )
|
mgl@1371
|
15787 |
+
|
mgl@1371
|
15788 |
+
|
mgl@1371
|
15789 |
+
|
mgl@1371
|
15790 |
+(define_peephole
|
mgl@1371
|
15791 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
15792 |
+ (and:SI (match_operand:SI 1 "register_operand" "") (const_int 255)))
|
mgl@1371
|
15793 |
+ (set (match_operand:SI 2 "register_operand" "")
|
mgl@1371
|
15794 |
+ (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
|
mgl@1371
|
15795 |
+ (match_operand:SI 3 "register_operand" ""))))]
|
mgl@1371
|
15796 |
+
|
mgl@1371
|
15797 |
+ "(dead_or_set_p(insn, operands[0]))"
|
mgl@1371
|
15798 |
+
|
mgl@1371
|
15799 |
+ "ld.w %2, %3[%1:b << 2]"
|
mgl@1371
|
15800 |
+ [(set_attr "type" "load")
|
mgl@1371
|
15801 |
+ (set_attr "length" "4")
|
mgl@1371
|
15802 |
+ (set_attr "cc" "clobber")]
|
mgl@1371
|
15803 |
+ )
|
mgl@1371
|
15804 |
+
|
mgl@1371
|
15805 |
+
|
mgl@1371
|
15806 |
+(define_peephole2
|
mgl@1371
|
15807 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
15808 |
+ (zero_extract:SI (match_operand:SI 1 "register_operand" "")
|
mgl@1371
|
15809 |
+ (const_int 8)
|
mgl@1371
|
15810 |
+ (match_operand:SI 2 "avr32_extract_shift_operand" "")))
|
mgl@1371
|
15811 |
+ (set (match_operand:SI 3 "register_operand" "")
|
mgl@1371
|
15812 |
+ (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
|
mgl@1371
|
15813 |
+ (match_operand:SI 4 "register_operand" ""))))]
|
mgl@1371
|
15814 |
+
|
mgl@1371
|
15815 |
+ "(peep2_reg_dead_p(2, operands[0]))
|
mgl@1371
|
15816 |
+ || (REGNO(operands[0]) == REGNO(operands[3]))"
|
mgl@1371
|
15817 |
+ [(set (match_dup 3)
|
mgl@1371
|
15818 |
+ (mem:SI (plus:SI
|
mgl@1371
|
15819 |
+ (match_dup 4)
|
mgl@1371
|
15820 |
+ (mult:SI (zero_extract:SI (match_dup 1)
|
mgl@1371
|
15821 |
+ (const_int 8)
|
mgl@1371
|
15822 |
+ (match_dup 2))
|
mgl@1371
|
15823 |
+ (const_int 4)))))]
|
mgl@1371
|
15824 |
+ )
|
mgl@1371
|
15825 |
+
|
mgl@1371
|
15826 |
+(define_peephole2
|
mgl@1371
|
15827 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
15828 |
+ (zero_extend:SI (match_operand:QI 1 "register_operand" "")))
|
mgl@1371
|
15829 |
+ (set (match_operand:SI 2 "register_operand" "")
|
mgl@1371
|
15830 |
+ (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
|
mgl@1371
|
15831 |
+ (match_operand:SI 3 "register_operand" ""))))]
|
mgl@1371
|
15832 |
+
|
mgl@1371
|
15833 |
+ "(peep2_reg_dead_p(2, operands[0]))
|
mgl@1371
|
15834 |
+ || (REGNO(operands[0]) == REGNO(operands[2]))"
|
mgl@1371
|
15835 |
+ [(set (match_dup 2)
|
mgl@1371
|
15836 |
+ (mem:SI (plus:SI
|
mgl@1371
|
15837 |
+ (match_dup 3)
|
mgl@1371
|
15838 |
+ (mult:SI (zero_extract:SI (match_dup 1)
|
mgl@1371
|
15839 |
+ (const_int 8)
|
mgl@1371
|
15840 |
+ (const_int 0))
|
mgl@1371
|
15841 |
+ (const_int 4)))))]
|
mgl@1371
|
15842 |
+ "operands[1] = gen_rtx_REG(SImode, REGNO(operands[1]));"
|
mgl@1371
|
15843 |
+ )
|
mgl@1371
|
15844 |
+
|
mgl@1371
|
15845 |
+
|
mgl@1371
|
15846 |
+(define_peephole2
|
mgl@1371
|
15847 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
15848 |
+ (and:SI (match_operand:SI 1 "register_operand" "")
|
mgl@1371
|
15849 |
+ (const_int 255)))
|
mgl@1371
|
15850 |
+ (set (match_operand:SI 2 "register_operand" "")
|
mgl@1371
|
15851 |
+ (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
|
mgl@1371
|
15852 |
+ (match_operand:SI 3 "register_operand" ""))))]
|
mgl@1371
|
15853 |
+
|
mgl@1371
|
15854 |
+ "(peep2_reg_dead_p(2, operands[0]))
|
mgl@1371
|
15855 |
+ || (REGNO(operands[0]) == REGNO(operands[2]))"
|
mgl@1371
|
15856 |
+ [(set (match_dup 2)
|
mgl@1371
|
15857 |
+ (mem:SI (plus:SI
|
mgl@1371
|
15858 |
+ (match_dup 3)
|
mgl@1371
|
15859 |
+ (mult:SI (zero_extract:SI (match_dup 1)
|
mgl@1371
|
15860 |
+ (const_int 8)
|
mgl@1371
|
15861 |
+ (const_int 0))
|
mgl@1371
|
15862 |
+ (const_int 4)))))]
|
mgl@1371
|
15863 |
+ ""
|
mgl@1371
|
15864 |
+ )
|
mgl@1371
|
15865 |
+
|
mgl@1371
|
15866 |
+
|
mgl@1371
|
15867 |
+
|
mgl@1371
|
15868 |
+(define_peephole2
|
mgl@1371
|
15869 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
15870 |
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
|
mgl@1371
|
15871 |
+ (const_int 24)))
|
mgl@1371
|
15872 |
+ (set (match_operand:SI 2 "register_operand" "")
|
mgl@1371
|
15873 |
+ (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
|
mgl@1371
|
15874 |
+ (match_operand:SI 3 "register_operand" ""))))]
|
mgl@1371
|
15875 |
+
|
mgl@1371
|
15876 |
+ "(peep2_reg_dead_p(2, operands[0]))
|
mgl@1371
|
15877 |
+ || (REGNO(operands[0]) == REGNO(operands[2]))"
|
mgl@1371
|
15878 |
+ [(set (match_dup 2)
|
mgl@1371
|
15879 |
+ (mem:SI (plus:SI
|
mgl@1371
|
15880 |
+ (match_dup 3)
|
mgl@1371
|
15881 |
+ (mult:SI (zero_extract:SI (match_dup 1)
|
mgl@1371
|
15882 |
+ (const_int 8)
|
mgl@1371
|
15883 |
+ (const_int 24))
|
mgl@1371
|
15884 |
+ (const_int 4)))))]
|
mgl@1371
|
15885 |
+ ""
|
mgl@1371
|
15886 |
+ )
|
mgl@1371
|
15887 |
+
|
mgl@1371
|
15888 |
+
|
mgl@1371
|
15889 |
+;;************************************************
|
mgl@1371
|
15890 |
+;; ANDN
|
mgl@1371
|
15891 |
+;;
|
mgl@1371
|
15892 |
+;;************************************************
|
mgl@1371
|
15893 |
+
|
mgl@1371
|
15894 |
+
|
mgl@1371
|
15895 |
+(define_peephole2
|
mgl@1371
|
15896 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
15897 |
+ (not:SI (match_operand:SI 1 "register_operand" "")))
|
mgl@1371
|
15898 |
+ (set (match_operand:SI 2 "register_operand" "")
|
mgl@1371
|
15899 |
+ (and:SI (match_dup 2)
|
mgl@1371
|
15900 |
+ (match_dup 0)))]
|
mgl@1371
|
15901 |
+ "peep2_reg_dead_p(2, operands[0])"
|
mgl@1371
|
15902 |
+
|
mgl@1371
|
15903 |
+ [(set (match_dup 2)
|
mgl@1371
|
15904 |
+ (and:SI (match_dup 2)
|
mgl@1371
|
15905 |
+ (not:SI (match_dup 1))
|
mgl@1371
|
15906 |
+ ))]
|
mgl@1371
|
15907 |
+ ""
|
mgl@1371
|
15908 |
+)
|
mgl@1371
|
15909 |
+
|
mgl@1371
|
15910 |
+(define_peephole2
|
mgl@1371
|
15911 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
15912 |
+ (not:SI (match_operand:SI 1 "register_operand" "")))
|
mgl@1371
|
15913 |
+ (set (match_operand:SI 2 "register_operand" "")
|
mgl@1371
|
15914 |
+ (and:SI (match_dup 0)
|
mgl@1371
|
15915 |
+ (match_dup 2)
|
mgl@1371
|
15916 |
+ ))]
|
mgl@1371
|
15917 |
+ "peep2_reg_dead_p(2, operands[0])"
|
mgl@1371
|
15918 |
+
|
mgl@1371
|
15919 |
+ [(set (match_dup 2)
|
mgl@1371
|
15920 |
+ (and:SI (match_dup 2)
|
mgl@1371
|
15921 |
+ (not:SI (match_dup 1))
|
mgl@1371
|
15922 |
+ ))]
|
mgl@1371
|
15923 |
+
|
mgl@1371
|
15924 |
+ ""
|
mgl@1371
|
15925 |
+)
|
mgl@1371
|
15926 |
+
|
mgl@1371
|
15927 |
+
|
mgl@1371
|
15928 |
+;;=================================================================
|
mgl@1371
|
15929 |
+;; Addabs peephole
|
mgl@1371
|
15930 |
+;;=================================================================
|
mgl@1371
|
15931 |
+
|
mgl@1371
|
15932 |
+(define_peephole
|
mgl@1371
|
15933 |
+ [(set (match_operand:SI 2 "register_operand" "=r")
|
mgl@1371
|
15934 |
+ (abs:SI (match_operand:SI 1 "register_operand" "r")))
|
mgl@1371
|
15935 |
+ (set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
15936 |
+ (plus:SI (match_operand:SI 3 "register_operand" "r")
|
mgl@1371
|
15937 |
+ (match_dup 2)))]
|
mgl@1371
|
15938 |
+ "dead_or_set_p(insn, operands[2])"
|
mgl@1371
|
15939 |
+ "addabs %0, %3, %1"
|
mgl@1371
|
15940 |
+ [(set_attr "length" "4")
|
mgl@1371
|
15941 |
+ (set_attr "cc" "set_z")])
|
mgl@1371
|
15942 |
+
|
mgl@1371
|
15943 |
+(define_peephole
|
mgl@1371
|
15944 |
+ [(set (match_operand:SI 2 "register_operand" "=r")
|
mgl@1371
|
15945 |
+ (abs:SI (match_operand:SI 1 "register_operand" "r")))
|
mgl@1371
|
15946 |
+ (set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
15947 |
+ (plus:SI (match_dup 2)
|
mgl@1371
|
15948 |
+ (match_operand:SI 3 "register_operand" "r")))]
|
mgl@1371
|
15949 |
+ "dead_or_set_p(insn, operands[2])"
|
mgl@1371
|
15950 |
+ "addabs %0, %3, %1"
|
mgl@1371
|
15951 |
+ [(set_attr "length" "4")
|
mgl@1371
|
15952 |
+ (set_attr "cc" "set_z")])
|
mgl@1371
|
15953 |
+
|
mgl@1371
|
15954 |
+
|
mgl@1371
|
15955 |
+;;=================================================================
|
mgl@1371
|
15956 |
+;; Detect roundings
|
mgl@1371
|
15957 |
+;;=================================================================
|
mgl@1371
|
15958 |
+
|
mgl@1371
|
15959 |
+(define_insn "*round"
|
mgl@1371
|
15960 |
+ [(set (match_operand:SI 0 "register_operand" "+r")
|
mgl@1371
|
15961 |
+ (ashiftrt:SI (plus:SI (match_dup 0)
|
mgl@1371
|
15962 |
+ (match_operand:SI 1 "immediate_operand" "i"))
|
mgl@1371
|
15963 |
+ (match_operand:SI 2 "immediate_operand" "i")))]
|
mgl@1371
|
15964 |
+ "avr32_rnd_operands(operands[1], operands[2])"
|
mgl@1371
|
15965 |
+
|
mgl@1371
|
15966 |
+ "satrnds %0 >> %2, 31"
|
mgl@1371
|
15967 |
+
|
mgl@1371
|
15968 |
+ [(set_attr "type" "alu_sat")
|
mgl@1371
|
15969 |
+ (set_attr "length" "4")]
|
mgl@1371
|
15970 |
+
|
mgl@1371
|
15971 |
+ )
|
mgl@1371
|
15972 |
+
|
mgl@1371
|
15973 |
+
|
mgl@1371
|
15974 |
+(define_peephole2
|
mgl@1371
|
15975 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
15976 |
+ (plus:SI (match_dup 0)
|
mgl@1371
|
15977 |
+ (match_operand:SI 1 "immediate_operand" "")))
|
mgl@1371
|
15978 |
+ (set (match_dup 0)
|
mgl@1371
|
15979 |
+ (ashiftrt:SI (match_dup 0)
|
mgl@1371
|
15980 |
+ (match_operand:SI 2 "immediate_operand" "")))]
|
mgl@1371
|
15981 |
+ "avr32_rnd_operands(operands[1], operands[2])"
|
mgl@1371
|
15982 |
+
|
mgl@1371
|
15983 |
+ [(set (match_dup 0)
|
mgl@1371
|
15984 |
+ (ashiftrt:SI (plus:SI (match_dup 0)
|
mgl@1371
|
15985 |
+ (match_dup 1))
|
mgl@1371
|
15986 |
+ (match_dup 2)))]
|
mgl@1371
|
15987 |
+ )
|
mgl@1371
|
15988 |
+
|
mgl@1371
|
15989 |
+(define_peephole
|
mgl@1371
|
15990 |
+ [(set (match_operand:SI 0 "register_operand" "r")
|
mgl@1371
|
15991 |
+ (plus:SI (match_dup 0)
|
mgl@1371
|
15992 |
+ (match_operand:SI 1 "immediate_operand" "i")))
|
mgl@1371
|
15993 |
+ (set (match_dup 0)
|
mgl@1371
|
15994 |
+ (ashiftrt:SI (match_dup 0)
|
mgl@1371
|
15995 |
+ (match_operand:SI 2 "immediate_operand" "i")))]
|
mgl@1371
|
15996 |
+ "avr32_rnd_operands(operands[1], operands[2])"
|
mgl@1371
|
15997 |
+
|
mgl@1371
|
15998 |
+ "satrnds %0 >> %2, 31"
|
mgl@1371
|
15999 |
+
|
mgl@1371
|
16000 |
+ [(set_attr "type" "alu_sat")
|
mgl@1371
|
16001 |
+ (set_attr "length" "4")
|
mgl@1371
|
16002 |
+ (set_attr "cc" "clobber")]
|
mgl@1371
|
16003 |
+
|
mgl@1371
|
16004 |
+ )
|
mgl@1371
|
16005 |
+
|
mgl@1371
|
16006 |
+
|
mgl@1371
|
16007 |
+;;=================================================================
|
mgl@1371
|
16008 |
+;; mcall
|
mgl@1371
|
16009 |
+;;=================================================================
|
mgl@1371
|
16010 |
+(define_peephole
|
mgl@1371
|
16011 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
16012 |
+ (match_operand 1 "avr32_const_pool_ref_operand" ""))
|
mgl@1371
|
16013 |
+ (parallel [(call (mem:SI (match_dup 0))
|
mgl@1371
|
16014 |
+ (match_operand 2 "" ""))
|
mgl@1371
|
16015 |
+ (clobber (reg:SI LR_REGNUM))])]
|
mgl@1371
|
16016 |
+ "dead_or_set_p(insn, operands[0])"
|
mgl@1371
|
16017 |
+ "mcall %1"
|
mgl@1371
|
16018 |
+ [(set_attr "type" "call")
|
mgl@1371
|
16019 |
+ (set_attr "length" "4")
|
mgl@1371
|
16020 |
+ (set_attr "cc" "clobber")]
|
mgl@1371
|
16021 |
+)
|
mgl@1371
|
16022 |
+
|
mgl@1371
|
16023 |
+(define_peephole
|
mgl@1371
|
16024 |
+ [(set (match_operand:SI 2 "register_operand" "")
|
mgl@1371
|
16025 |
+ (match_operand 1 "avr32_const_pool_ref_operand" ""))
|
mgl@1371
|
16026 |
+ (parallel [(set (match_operand 0 "register_operand" "")
|
mgl@1371
|
16027 |
+ (call (mem:SI (match_dup 2))
|
mgl@1371
|
16028 |
+ (match_operand 3 "" "")))
|
mgl@1371
|
16029 |
+ (clobber (reg:SI LR_REGNUM))])]
|
mgl@1371
|
16030 |
+ "dead_or_set_p(insn, operands[2])"
|
mgl@1371
|
16031 |
+ "mcall %1"
|
mgl@1371
|
16032 |
+ [(set_attr "type" "call")
|
mgl@1371
|
16033 |
+ (set_attr "length" "4")
|
mgl@1371
|
16034 |
+ (set_attr "cc" "call_set")]
|
mgl@1371
|
16035 |
+)
|
mgl@1371
|
16036 |
+
|
mgl@1371
|
16037 |
+
|
mgl@1371
|
16038 |
+(define_peephole2
|
mgl@1371
|
16039 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
16040 |
+ (match_operand 1 "avr32_const_pool_ref_operand" ""))
|
mgl@1371
|
16041 |
+ (parallel [(call (mem:SI (match_dup 0))
|
mgl@1371
|
16042 |
+ (match_operand 2 "" ""))
|
mgl@1371
|
16043 |
+ (clobber (reg:SI LR_REGNUM))])]
|
mgl@1371
|
16044 |
+ "peep2_reg_dead_p(2, operands[0])"
|
mgl@1371
|
16045 |
+ [(parallel [(call (mem:SI (match_dup 1))
|
mgl@1371
|
16046 |
+ (match_dup 2))
|
mgl@1371
|
16047 |
+ (clobber (reg:SI LR_REGNUM))])]
|
mgl@1371
|
16048 |
+ ""
|
mgl@1371
|
16049 |
+)
|
mgl@1371
|
16050 |
+
|
mgl@1371
|
16051 |
+(define_peephole2
|
mgl@1371
|
16052 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
16053 |
+ (match_operand 1 "avr32_const_pool_ref_operand" ""))
|
mgl@1371
|
16054 |
+ (parallel [(set (match_operand 2 "register_operand" "")
|
mgl@1371
|
16055 |
+ (call (mem:SI (match_dup 0))
|
mgl@1371
|
16056 |
+ (match_operand 3 "" "")))
|
mgl@1371
|
16057 |
+ (clobber (reg:SI LR_REGNUM))])]
|
mgl@1371
|
16058 |
+ "(peep2_reg_dead_p(2, operands[0]) || (REGNO(operands[2]) == REGNO(operands[0])))"
|
mgl@1371
|
16059 |
+ [(parallel [(set (match_dup 2)
|
mgl@1371
|
16060 |
+ (call (mem:SI (match_dup 1))
|
mgl@1371
|
16061 |
+ (match_dup 3)))
|
mgl@1371
|
16062 |
+ (clobber (reg:SI LR_REGNUM))])]
|
mgl@1371
|
16063 |
+ ""
|
mgl@1371
|
16064 |
+)
|
mgl@1371
|
16065 |
+
|
mgl@1371
|
16066 |
+;;=================================================================
|
mgl@1371
|
16067 |
+;; Returning a value
|
mgl@1371
|
16068 |
+;;=================================================================
|
mgl@1371
|
16069 |
+
|
mgl@1371
|
16070 |
+
|
mgl@1371
|
16071 |
+(define_peephole
|
mgl@1371
|
16072 |
+ [(set (match_operand 0 "register_operand" "")
|
mgl@1371
|
16073 |
+ (match_operand 1 "register_operand" ""))
|
mgl@1371
|
16074 |
+ (return)]
|
mgl@1371
|
16075 |
+ "USE_RETURN_INSN (TRUE) && (REGNO(operands[0]) == RETVAL_REGNUM)
|
mgl@1371
|
16076 |
+ && (REGNO(operands[1]) != LR_REGNUM)
|
mgl@1371
|
16077 |
+ && (REGNO_REG_CLASS(REGNO(operands[1])) == GENERAL_REGS)"
|
mgl@1371
|
16078 |
+ "retal %1"
|
mgl@1371
|
16079 |
+ [(set_attr "type" "call")
|
mgl@1371
|
16080 |
+ (set_attr "length" "2")]
|
mgl@1371
|
16081 |
+ )
|
mgl@1371
|
16082 |
+
|
mgl@1371
|
16083 |
+
|
mgl@1371
|
16084 |
+(define_peephole
|
mgl@1371
|
16085 |
+ [(set (match_operand 0 "register_operand" "r")
|
mgl@1371
|
16086 |
+ (match_operand 1 "immediate_operand" "i"))
|
mgl@1371
|
16087 |
+ (return)]
|
mgl@1371
|
16088 |
+ "(USE_RETURN_INSN (FALSE) && (REGNO(operands[0]) == RETVAL_REGNUM) &&
|
mgl@1371
|
16089 |
+ ((INTVAL(operands[1]) == -1) || (INTVAL(operands[1]) == 0) || (INTVAL(operands[1]) == 1)))"
|
mgl@1371
|
16090 |
+ {
|
mgl@1371
|
16091 |
+ avr32_output_return_instruction (TRUE, FALSE, NULL, operands[1]);
|
mgl@1371
|
16092 |
+ return "";
|
mgl@1371
|
16093 |
+ }
|
mgl@1371
|
16094 |
+ [(set_attr "type" "call")
|
mgl@1371
|
16095 |
+ (set_attr "length" "4")]
|
mgl@1371
|
16096 |
+ )
|
mgl@1371
|
16097 |
+
|
mgl@1371
|
16098 |
+(define_peephole
|
mgl@1371
|
16099 |
+ [(set (match_operand 0 "register_operand" "r")
|
mgl@1371
|
16100 |
+ (match_operand 1 "immediate_operand" "i"))
|
mgl@1371
|
16101 |
+ (unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
|
mgl@1371
|
16102 |
+ "(REGNO(operands[0]) == RETVAL_REGNUM) &&
|
mgl@1371
|
16103 |
+ ((INTVAL(operands[1]) == -1) || (INTVAL(operands[1]) == 0) || (INTVAL(operands[1]) == 1))"
|
mgl@1371
|
16104 |
+ {
|
mgl@1371
|
16105 |
+ avr32_output_return_instruction (FALSE, FALSE, NULL, operands[1]);
|
mgl@1371
|
16106 |
+ return "";
|
mgl@1371
|
16107 |
+ }
|
mgl@1371
|
16108 |
+ ; Length is absolute worst case
|
mgl@1371
|
16109 |
+ [(set_attr "type" "branch")
|
mgl@1371
|
16110 |
+ (set_attr "length" "12")]
|
mgl@1371
|
16111 |
+ )
|
mgl@1371
|
16112 |
+
|
mgl@1371
|
16113 |
+(define_peephole
|
mgl@1371
|
16114 |
+ [(set (match_operand 0 "register_operand" "=r")
|
mgl@1371
|
16115 |
+ (if_then_else (match_operator 1 "avr32_comparison_operator"
|
mgl@1371
|
16116 |
+ [(match_operand 4 "register_operand" "r")
|
mgl@1371
|
16117 |
+ (match_operand 5 "register_immediate_operand" "rKs21")])
|
mgl@1371
|
16118 |
+ (match_operand 2 "avr32_cond_register_immediate_operand" "rKs08")
|
mgl@1371
|
16119 |
+ (match_operand 3 "avr32_cond_register_immediate_operand" "rKs08")))
|
mgl@1371
|
16120 |
+ (return)]
|
mgl@1371
|
16121 |
+ "USE_RETURN_INSN (TRUE) && (REGNO(operands[0]) == RETVAL_REGNUM)"
|
mgl@1371
|
16122 |
+ {
|
mgl@1371
|
16123 |
+ operands[1] = avr32_output_cmp(operands[1], GET_MODE(operands[4]), operands[4], operands[5]);
|
mgl@1371
|
16124 |
+
|
mgl@1371
|
16125 |
+ if ( GET_CODE(operands[2]) == REG
|
mgl@1371
|
16126 |
+ && GET_CODE(operands[3]) == REG
|
mgl@1371
|
16127 |
+ && REGNO(operands[2]) != LR_REGNUM
|
mgl@1371
|
16128 |
+ && REGNO(operands[3]) != LR_REGNUM ){
|
mgl@1371
|
16129 |
+ return "ret%1 %2\;ret%i1 %3";
|
mgl@1371
|
16130 |
+ } else if ( GET_CODE(operands[2]) == REG
|
mgl@1371
|
16131 |
+ && GET_CODE(operands[3]) == CONST_INT ){
|
mgl@1371
|
16132 |
+ if ( INTVAL(operands[3]) == -1
|
mgl@1371
|
16133 |
+ || INTVAL(operands[3]) == 0
|
mgl@1371
|
16134 |
+ || INTVAL(operands[3]) == 1 ){
|
mgl@1371
|
16135 |
+ return "ret%1 %2\;ret%i1 %d3";
|
mgl@1371
|
16136 |
+ } else {
|
mgl@1371
|
16137 |
+ return "mov%1 r12, %2\;mov%i1 r12, %3\;retal r12";
|
mgl@1371
|
16138 |
+ }
|
mgl@1371
|
16139 |
+ } else if ( GET_CODE(operands[2]) == CONST_INT
|
mgl@1371
|
16140 |
+ && GET_CODE(operands[3]) == REG ){
|
mgl@1371
|
16141 |
+ if ( INTVAL(operands[2]) == -1
|
mgl@1371
|
16142 |
+ || INTVAL(operands[2]) == 0
|
mgl@1371
|
16143 |
+ || INTVAL(operands[2]) == 1 ){
|
mgl@1371
|
16144 |
+ return "ret%1 %d2\;ret%i1 %3";
|
mgl@1371
|
16145 |
+ } else {
|
mgl@1371
|
16146 |
+ return "mov%1 r12, %2\;mov%i1 r12, %3\;retal r12";
|
mgl@1371
|
16147 |
+ }
|
mgl@1371
|
16148 |
+ } else {
|
mgl@1371
|
16149 |
+ if ( (INTVAL(operands[2]) == -1
|
mgl@1371
|
16150 |
+ || INTVAL(operands[2]) == 0
|
mgl@1371
|
16151 |
+ || INTVAL(operands[2]) == 1 )
|
mgl@1371
|
16152 |
+ && (INTVAL(operands[3]) == -1
|
mgl@1371
|
16153 |
+ || INTVAL(operands[3]) == 0
|
mgl@1371
|
16154 |
+ || INTVAL(operands[3]) == 1 )){
|
mgl@1371
|
16155 |
+ return "ret%1 %d2\;ret%i1 %d3";
|
mgl@1371
|
16156 |
+ } else {
|
mgl@1371
|
16157 |
+ return "mov%1 r12, %2\;mov%i1 r12, %3\;retal r12";
|
mgl@1371
|
16158 |
+ }
|
mgl@1371
|
16159 |
+ }
|
mgl@1371
|
16160 |
+ }
|
mgl@1371
|
16161 |
+
|
mgl@1371
|
16162 |
+ [(set_attr "length" "10")
|
mgl@1371
|
16163 |
+ (set_attr "cc" "none")
|
mgl@1371
|
16164 |
+ (set_attr "type" "call")])
|
mgl@1371
|
16165 |
+
|
mgl@1371
|
16166 |
+
|
mgl@1371
|
16167 |
+
|
mgl@1371
|
16168 |
+;;=================================================================
|
mgl@1371
|
16169 |
+;; mulnhh.w
|
mgl@1371
|
16170 |
+;;=================================================================
|
mgl@1371
|
16171 |
+
|
mgl@1371
|
16172 |
+(define_peephole2
|
mgl@1371
|
16173 |
+ [(set (match_operand:HI 0 "register_operand" "")
|
mgl@1371
|
16174 |
+ (neg:HI (match_operand:HI 1 "register_operand" "")))
|
mgl@1371
|
16175 |
+ (set (match_operand:SI 2 "register_operand" "")
|
mgl@1371
|
16176 |
+ (mult:SI
|
mgl@1371
|
16177 |
+ (sign_extend:SI (match_dup 0))
|
mgl@1371
|
16178 |
+ (sign_extend:SI (match_operand:HI 3 "register_operand" ""))))]
|
mgl@1371
|
16179 |
+ "(peep2_reg_dead_p(2, operands[0])) || (REGNO(operands[2]) == REGNO(operands[0]))"
|
mgl@1371
|
16180 |
+ [ (set (match_dup 2)
|
mgl@1371
|
16181 |
+ (mult:SI
|
mgl@1371
|
16182 |
+ (sign_extend:SI (neg:HI (match_dup 1)))
|
mgl@1371
|
16183 |
+ (sign_extend:SI (match_dup 3))))]
|
mgl@1371
|
16184 |
+ ""
|
mgl@1371
|
16185 |
+ )
|
mgl@1371
|
16186 |
+
|
mgl@1371
|
16187 |
+(define_peephole2
|
mgl@1371
|
16188 |
+ [(set (match_operand:HI 0 "register_operand" "")
|
mgl@1371
|
16189 |
+ (neg:HI (match_operand:HI 1 "register_operand" "")))
|
mgl@1371
|
16190 |
+ (set (match_operand:SI 2 "register_operand" "")
|
mgl@1371
|
16191 |
+ (mult:SI
|
mgl@1371
|
16192 |
+ (sign_extend:SI (match_operand:HI 3 "register_operand" ""))
|
mgl@1371
|
16193 |
+ (sign_extend:SI (match_dup 0))))]
|
mgl@1371
|
16194 |
+ "(peep2_reg_dead_p(2, operands[0])) || (REGNO(operands[2]) == REGNO(operands[0]))"
|
mgl@1371
|
16195 |
+ [ (set (match_dup 2)
|
mgl@1371
|
16196 |
+ (mult:SI
|
mgl@1371
|
16197 |
+ (sign_extend:SI (neg:HI (match_dup 1)))
|
mgl@1371
|
16198 |
+ (sign_extend:SI (match_dup 3))))]
|
mgl@1371
|
16199 |
+ ""
|
mgl@1371
|
16200 |
+ )
|
mgl@1371
|
16201 |
+
|
mgl@1371
|
16202 |
+
|
mgl@1371
|
16203 |
+
|
mgl@1371
|
16204 |
+;;=================================================================
|
mgl@1371
|
16205 |
+;; Vector set and extract operations
|
mgl@1371
|
16206 |
+;;=================================================================
|
mgl@1371
|
16207 |
+(define_insn "vec_setv2hi_hi"
|
mgl@1371
|
16208 |
+ [(set (match_operand:V2HI 0 "register_operand" "=r")
|
mgl@1371
|
16209 |
+ (vec_merge:V2HI
|
mgl@1371
|
16210 |
+ (match_dup 0)
|
mgl@1371
|
16211 |
+ (vec_duplicate:V2HI
|
mgl@1371
|
16212 |
+ (match_operand:HI 1 "register_operand" "r"))
|
mgl@1371
|
16213 |
+ (const_int 1)))]
|
mgl@1371
|
16214 |
+ ""
|
mgl@1371
|
16215 |
+ "bfins\t%0, %1, 16, 16"
|
mgl@1371
|
16216 |
+ [(set_attr "type" "alu")
|
mgl@1371
|
16217 |
+ (set_attr "length" "4")
|
mgl@1371
|
16218 |
+ (set_attr "cc" "clobber")])
|
mgl@1371
|
16219 |
+
|
mgl@1371
|
16220 |
+(define_insn "vec_setv2hi_lo"
|
mgl@1371
|
16221 |
+ [(set (match_operand:V2HI 0 "register_operand" "+r")
|
mgl@1371
|
16222 |
+ (vec_merge:V2HI
|
mgl@1371
|
16223 |
+ (match_dup 0)
|
mgl@1371
|
16224 |
+ (vec_duplicate:V2HI
|
mgl@1371
|
16225 |
+ (match_operand:HI 1 "register_operand" "r"))
|
mgl@1371
|
16226 |
+ (const_int 2)))]
|
mgl@1371
|
16227 |
+ ""
|
mgl@1371
|
16228 |
+ "bfins\t%0, %1, 0, 16"
|
mgl@1371
|
16229 |
+ [(set_attr "type" "alu")
|
mgl@1371
|
16230 |
+ (set_attr "length" "4")
|
mgl@1371
|
16231 |
+ (set_attr "cc" "clobber")])
|
mgl@1371
|
16232 |
+
|
mgl@1371
|
16233 |
+(define_expand "vec_setv2hi"
|
mgl@1371
|
16234 |
+ [(set (match_operand:V2HI 0 "register_operand" "")
|
mgl@1371
|
16235 |
+ (vec_merge:V2HI
|
mgl@1371
|
16236 |
+ (match_dup 0)
|
mgl@1371
|
16237 |
+ (vec_duplicate:V2HI
|
mgl@1371
|
16238 |
+ (match_operand:HI 1 "register_operand" ""))
|
mgl@1371
|
16239 |
+ (match_operand 2 "immediate_operand" "")))]
|
mgl@1371
|
16240 |
+ ""
|
mgl@1371
|
16241 |
+ { operands[2] = GEN_INT(INTVAL(operands[2]) + 1); }
|
mgl@1371
|
16242 |
+ )
|
mgl@1371
|
16243 |
+
|
mgl@1371
|
16244 |
+(define_insn "vec_extractv2hi"
|
mgl@1371
|
16245 |
+ [(set (match_operand:HI 0 "register_operand" "=r")
|
mgl@1371
|
16246 |
+ (vec_select:HI
|
mgl@1371
|
16247 |
+ (match_operand:V2HI 1 "register_operand" "r")
|
mgl@1371
|
16248 |
+ (parallel [(match_operand:SI 2 "immediate_operand" "i")])))]
|
mgl@1371
|
16249 |
+ ""
|
mgl@1371
|
16250 |
+ {
|
mgl@1371
|
16251 |
+ if ( INTVAL(operands[2]) == 0 )
|
mgl@1371
|
16252 |
+ return "bfextu\t%0, %1, 16, 16";
|
mgl@1371
|
16253 |
+ else
|
mgl@1371
|
16254 |
+ return "bfextu\t%0, %1, 0, 16";
|
mgl@1371
|
16255 |
+ }
|
mgl@1371
|
16256 |
+ [(set_attr "type" "alu")
|
mgl@1371
|
16257 |
+ (set_attr "length" "4")
|
mgl@1371
|
16258 |
+ (set_attr "cc" "clobber")])
|
mgl@1371
|
16259 |
+
|
mgl@1371
|
16260 |
+(define_insn "vec_extractv4qi"
|
mgl@1371
|
16261 |
+ [(set (match_operand:QI 0 "register_operand" "=r")
|
mgl@1371
|
16262 |
+ (vec_select:QI
|
mgl@1371
|
16263 |
+ (match_operand:V4QI 1 "register_operand" "r")
|
mgl@1371
|
16264 |
+ (parallel [(match_operand:SI 2 "immediate_operand" "i")])))]
|
mgl@1371
|
16265 |
+ ""
|
mgl@1371
|
16266 |
+ {
|
mgl@1371
|
16267 |
+ switch ( INTVAL(operands[2]) ){
|
mgl@1371
|
16268 |
+ case 0:
|
mgl@1371
|
16269 |
+ return "bfextu\t%0, %1, 24, 8";
|
mgl@1371
|
16270 |
+ case 1:
|
mgl@1371
|
16271 |
+ return "bfextu\t%0, %1, 16, 8";
|
mgl@1371
|
16272 |
+ case 2:
|
mgl@1371
|
16273 |
+ return "bfextu\t%0, %1, 8, 8";
|
mgl@1371
|
16274 |
+ case 3:
|
mgl@1371
|
16275 |
+ return "bfextu\t%0, %1, 0, 8";
|
mgl@1371
|
16276 |
+ default:
|
mgl@1371
|
16277 |
+ abort();
|
mgl@1371
|
16278 |
+ }
|
mgl@1371
|
16279 |
+ }
|
mgl@1371
|
16280 |
+ [(set_attr "type" "alu")
|
mgl@1371
|
16281 |
+ (set_attr "length" "4")
|
mgl@1371
|
16282 |
+ (set_attr "cc" "clobber")])
|
mgl@1371
|
16283 |
+
|
mgl@1371
|
16284 |
+
|
mgl@1371
|
16285 |
+(define_insn "concatv2hi"
|
mgl@1371
|
16286 |
+ [(set (match_operand:V2HI 0 "register_operand" "=r, r, r")
|
mgl@1371
|
16287 |
+ (vec_concat:V2HI
|
mgl@1371
|
16288 |
+ (match_operand:HI 1 "register_operand" "r, r, 0")
|
mgl@1371
|
16289 |
+ (match_operand:HI 2 "register_operand" "r, 0, r")))]
|
mgl@1371
|
16290 |
+ ""
|
mgl@1371
|
16291 |
+ "@
|
mgl@1371
|
16292 |
+ mov\t%0, %1\;bfins\t%0, %2, 0, 16
|
mgl@1371
|
16293 |
+ bfins\t%0, %2, 0, 16
|
mgl@1371
|
16294 |
+ bfins\t%0, %1, 16, 16"
|
mgl@1371
|
16295 |
+ [(set_attr "length" "6, 4, 4")
|
mgl@1371
|
16296 |
+ (set_attr "type" "alu")])
|
mgl@1371
|
16297 |
+
|
mgl@1371
|
16298 |
+
|
mgl@1371
|
16299 |
+;; Load the atomic operation description
|
mgl@1371
|
16300 |
+(include "sync.md")
|
mgl@1371
|
16301 |
+
|
mgl@1371
|
16302 |
+;; Load the SIMD description
|
mgl@1371
|
16303 |
+(include "simd.md")
|
mgl@1371
|
16304 |
+
|
mgl@1371
|
16305 |
+;; Load the FP coprAocessor patterns
|
mgl@1371
|
16306 |
+(include "fpcp.md")
|
mgl@1371
|
16307 |
--- /dev/null
|
mgl@1371
|
16308 |
+++ b/gcc/config/avr32/avr32-modes.def
|
mgl@1371
|
16309 |
@@ -0,0 +1 @@
|
mgl@1371
|
16310 |
+VECTOR_MODES (INT, 4); /* V4QI V2HI */
|
mgl@1371
|
16311 |
--- /dev/null
|
mgl@1371
|
16312 |
+++ b/gcc/config/avr32/avr32.opt
|
mgl@1371
|
16313 |
@@ -0,0 +1,86 @@
|
mgl@1371
|
16314 |
+; Options for the ATMEL AVR32 port of the compiler.
|
mgl@1371
|
16315 |
+
|
mgl@1371
|
16316 |
+; Copyright 2007 Atmel Corporation.
|
mgl@1371
|
16317 |
+;
|
mgl@1371
|
16318 |
+; This file is part of GCC.
|
mgl@1371
|
16319 |
+;
|
mgl@1371
|
16320 |
+; GCC is free software; you can redistribute it and/or modify it under
|
mgl@1371
|
16321 |
+; the terms of the GNU General Public License as published by the Free
|
mgl@1371
|
16322 |
+; Software Foundation; either version 2, or (at your option) any later
|
mgl@1371
|
16323 |
+; version.
|
mgl@1371
|
16324 |
+;
|
mgl@1371
|
16325 |
+; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
mgl@1371
|
16326 |
+; WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
mgl@1371
|
16327 |
+; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
mgl@1371
|
16328 |
+; for more details.
|
mgl@1371
|
16329 |
+;
|
mgl@1371
|
16330 |
+; You should have received a copy of the GNU General Public License
|
mgl@1371
|
16331 |
+; along with GCC; see the file COPYING. If not, write to the Free
|
mgl@1371
|
16332 |
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
mgl@1371
|
16333 |
+; 02110-1301, USA.
|
mgl@1371
|
16334 |
+
|
mgl@1371
|
16335 |
+muse-rodata-section
|
mgl@1371
|
16336 |
+Target Report Mask(USE_RODATA_SECTION)
|
mgl@1371
|
16337 |
+Use section .rodata for read-only data instead of .text.
|
mgl@1371
|
16338 |
+
|
mgl@1371
|
16339 |
+mhard-float
|
mgl@1371
|
16340 |
+Target Report Undocumented Mask(HARD_FLOAT)
|
mgl@1371
|
16341 |
+Use floating point coprocessor instructions.
|
mgl@1371
|
16342 |
+
|
mgl@1371
|
16343 |
+msoft-float
|
mgl@1371
|
16344 |
+Target Report Undocumented InverseMask(HARD_FLOAT, SOFT_FLOAT)
|
mgl@1371
|
16345 |
+Use software floating-point library for floating-point operations.
|
mgl@1371
|
16346 |
+
|
mgl@1371
|
16347 |
+mforce-double-align
|
mgl@1371
|
16348 |
+Target Report RejectNegative Mask(FORCE_DOUBLE_ALIGN)
|
mgl@1371
|
16349 |
+Force double-word alignment for double-word memory accesses.
|
mgl@1371
|
16350 |
+
|
mgl@1371
|
16351 |
+mno-init-got
|
mgl@1371
|
16352 |
+Target Report RejectNegative Mask(NO_INIT_GOT)
|
mgl@1371
|
16353 |
+Do not initialize GOT register before using it when compiling PIC code.
|
mgl@1371
|
16354 |
+
|
mgl@1371
|
16355 |
+mrelax
|
mgl@1371
|
16356 |
+Target Report Mask(RELAX)
|
mgl@1371
|
16357 |
+Let invoked assembler and linker do relaxing (Enabled by default when optimization level is >1).
|
mgl@1371
|
16358 |
+
|
mgl@1371
|
16359 |
+mmd-reorg-opt
|
mgl@1371
|
16360 |
+Target Report Undocumented Mask(MD_REORG_OPTIMIZATION)
|
mgl@1371
|
16361 |
+Perform machine dependent optimizations in reorg stage.
|
mgl@1371
|
16362 |
+
|
mgl@1371
|
16363 |
+masm-addr-pseudos
|
mgl@1371
|
16364 |
+Target Report Mask(HAS_ASM_ADDR_PSEUDOS)
|
mgl@1371
|
16365 |
+Use assembler pseudo-instructions lda.w and call for handling direct addresses. (Enabled by default)
|
mgl@1371
|
16366 |
+
|
mgl@1371
|
16367 |
+mpart=
|
mgl@1371
|
16368 |
+Target Report RejectNegative Joined Var(avr32_part_name)
|
mgl@1371
|
16369 |
+Specify the AVR32 part name
|
mgl@1371
|
16370 |
+
|
mgl@1371
|
16371 |
+mcpu=
|
mgl@1371
|
16372 |
+Target Report RejectNegative Joined Undocumented Var(avr32_part_name)
|
mgl@1371
|
16373 |
+Specify the AVR32 part name (deprecated)
|
mgl@1371
|
16374 |
+
|
mgl@1371
|
16375 |
+march=
|
mgl@1371
|
16376 |
+Target Report RejectNegative Joined Var(avr32_arch_name)
|
mgl@1371
|
16377 |
+Specify the AVR32 architecture name
|
mgl@1371
|
16378 |
+
|
mgl@1371
|
16379 |
+mfast-float
|
mgl@1371
|
16380 |
+Target Report Mask(FAST_FLOAT)
|
mgl@1371
|
16381 |
+Enable fast floating-point library. Enabled by default if the -funsafe-math-optimizations switch is specified.
|
mgl@1371
|
16382 |
+
|
mgl@1371
|
16383 |
+mimm-in-const-pool
|
mgl@1371
|
16384 |
+Target Report Var(avr32_imm_in_const_pool) Init(-1)
|
mgl@1371
|
16385 |
+Put large immediates in constant pool. This is enabled by default for archs with insn-cache.
|
mgl@1371
|
16386 |
+
|
mgl@1371
|
16387 |
+mno-pic
|
mgl@1371
|
16388 |
+Target Report RejectNegative Mask(NO_PIC)
|
mgl@1371
|
16389 |
+Do not generate position-independent code. (deprecated, use -fno-pic instead)
|
mgl@1371
|
16390 |
+
|
mgl@1371
|
16391 |
+mcond-exec-before-reload
|
mgl@1371
|
16392 |
+Target Report Undocumented Mask(COND_EXEC_BEFORE_RELOAD)
|
mgl@1371
|
16393 |
+Enable experimental conditional execution preparation before the reload stage.
|
mgl@1371
|
16394 |
+
|
mgl@1371
|
16395 |
+mrmw-addressable-data
|
mgl@1371
|
16396 |
+Target Report Mask(RMW_ADDRESSABLE_DATA)
|
mgl@1371
|
16397 |
+Signal that all data is in range for the Atomic Read-Modify-Write memory instructions, and that
|
mgl@1371
|
16398 |
+gcc can safely generate these whenever possible.
|
mgl@1371
|
16399 |
+
|
mgl@1371
|
16400 |
--- /dev/null
|
mgl@1371
|
16401 |
+++ b/gcc/config/avr32/avr32-protos.h
|
mgl@1371
|
16402 |
@@ -0,0 +1,196 @@
|
mgl@1371
|
16403 |
+/*
|
mgl@1371
|
16404 |
+ Prototypes for exported functions defined in avr32.c
|
mgl@1371
|
16405 |
+ Copyright 2003-2006 Atmel Corporation.
|
mgl@1371
|
16406 |
+
|
mgl@1371
|
16407 |
+ Written by Ronny Pedersen, Atmel Norway, <rpedersen@atmel.com>
|
mgl@1371
|
16408 |
+ Initial porting by Anders �dland.
|
mgl@1371
|
16409 |
+
|
mgl@1371
|
16410 |
+ This file is part of GCC.
|
mgl@1371
|
16411 |
+
|
mgl@1371
|
16412 |
+ This program is free software; you can redistribute it and/or modify
|
mgl@1371
|
16413 |
+ it under the terms of the GNU General Public License as published by
|
mgl@1371
|
16414 |
+ the Free Software Foundation; either version 2 of the License, or
|
mgl@1371
|
16415 |
+ (at your option) any later version.
|
mgl@1371
|
16416 |
+
|
mgl@1371
|
16417 |
+ This program is distributed in the hope that it will be useful,
|
mgl@1371
|
16418 |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
mgl@1371
|
16419 |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
mgl@1371
|
16420 |
+ GNU General Public License for more details.
|
mgl@1371
|
16421 |
+
|
mgl@1371
|
16422 |
+ You should have received a copy of the GNU General Public License
|
mgl@1371
|
16423 |
+ along with this program; if not, write to the Free Software
|
mgl@1371
|
16424 |
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
mgl@1371
|
16425 |
+
|
mgl@1371
|
16426 |
+
|
mgl@1371
|
16427 |
+#ifndef AVR32_PROTOS_H
|
mgl@1371
|
16428 |
+#define AVR32_PROTOS_H
|
mgl@1371
|
16429 |
+
|
mgl@1371
|
16430 |
+extern const int swap_reg[];
|
mgl@1371
|
16431 |
+
|
mgl@1371
|
16432 |
+extern int avr32_valid_macmac_bypass (rtx, rtx);
|
mgl@1371
|
16433 |
+extern int avr32_valid_mulmac_bypass (rtx, rtx);
|
mgl@1371
|
16434 |
+
|
mgl@1371
|
16435 |
+extern int avr32_decode_lcomm_symbol_offset (rtx, int *);
|
mgl@1371
|
16436 |
+extern void avr32_encode_lcomm_symbol_offset (tree, char *, int);
|
mgl@1371
|
16437 |
+
|
mgl@1371
|
16438 |
+extern const char *avr32_strip_name_encoding (const char *);
|
mgl@1371
|
16439 |
+
|
mgl@1371
|
16440 |
+extern rtx avr32_get_note_reg_equiv (rtx insn);
|
mgl@1371
|
16441 |
+
|
mgl@1371
|
16442 |
+extern int avr32_use_return_insn (int iscond);
|
mgl@1371
|
16443 |
+
|
mgl@1371
|
16444 |
+extern void avr32_make_reglist16 (int reglist16_vect, char *reglist16_string);
|
mgl@1371
|
16445 |
+
|
mgl@1371
|
16446 |
+extern void avr32_make_reglist8 (int reglist8_vect, char *reglist8_string);
|
mgl@1371
|
16447 |
+extern void avr32_make_fp_reglist_w (int reglist_mask, char *reglist_string);
|
mgl@1371
|
16448 |
+extern void avr32_make_fp_reglist_d (int reglist_mask, char *reglist_string);
|
mgl@1371
|
16449 |
+
|
mgl@1371
|
16450 |
+extern void avr32_output_return_instruction (int single_ret_inst,
|
mgl@1371
|
16451 |
+ int iscond, rtx cond,
|
mgl@1371
|
16452 |
+ rtx r12_imm);
|
mgl@1371
|
16453 |
+extern void avr32_expand_prologue (void);
|
mgl@1371
|
16454 |
+extern void avr32_set_return_address (rtx source, rtx scratch);
|
mgl@1371
|
16455 |
+
|
mgl@1371
|
16456 |
+extern int avr32_hard_regno_mode_ok (int regno, enum machine_mode mode);
|
mgl@1371
|
16457 |
+extern int avr32_extra_constraint_s (rtx value, const int strict);
|
mgl@1371
|
16458 |
+extern int avr32_eh_return_data_regno (const int n);
|
mgl@1371
|
16459 |
+extern int avr32_initial_elimination_offset (const int from, const int to);
|
mgl@1371
|
16460 |
+extern rtx avr32_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode,
|
mgl@1371
|
16461 |
+ tree type, int named);
|
mgl@1371
|
16462 |
+extern void avr32_init_cumulative_args (CUMULATIVE_ARGS * cum, tree fntype,
|
mgl@1371
|
16463 |
+ rtx libname, tree fndecl);
|
mgl@1371
|
16464 |
+extern void avr32_function_arg_advance (CUMULATIVE_ARGS * cum,
|
mgl@1371
|
16465 |
+ enum machine_mode mode,
|
mgl@1371
|
16466 |
+ tree type, int named);
|
mgl@1371
|
16467 |
+#ifdef ARGS_SIZE_RTX
|
mgl@1371
|
16468 |
+/* expr.h defines ARGS_SIZE_RTX and `enum direction'. */
|
mgl@1371
|
16469 |
+extern enum direction avr32_function_arg_padding (enum machine_mode mode,
|
mgl@1371
|
16470 |
+ tree type);
|
mgl@1371
|
16471 |
+#endif /* ARGS_SIZE_RTX */
|
mgl@1371
|
16472 |
+extern rtx avr32_function_value (tree valtype, tree func, bool outgoing);
|
mgl@1371
|
16473 |
+extern rtx avr32_libcall_value (enum machine_mode mode);
|
mgl@1371
|
16474 |
+extern int avr32_sched_use_dfa_pipeline_interface (void);
|
mgl@1371
|
16475 |
+extern bool avr32_return_in_memory (tree type, tree fntype);
|
mgl@1371
|
16476 |
+extern void avr32_regs_to_save (char *operand);
|
mgl@1371
|
16477 |
+extern void avr32_target_asm_function_prologue (FILE * file,
|
mgl@1371
|
16478 |
+ HOST_WIDE_INT size);
|
mgl@1371
|
16479 |
+extern void avr32_target_asm_function_epilogue (FILE * file,
|
mgl@1371
|
16480 |
+ HOST_WIDE_INT size);
|
mgl@1371
|
16481 |
+extern void avr32_trampoline_template (FILE * file);
|
mgl@1371
|
16482 |
+extern void avr32_initialize_trampoline (rtx addr, rtx fnaddr,
|
mgl@1371
|
16483 |
+ rtx static_chain);
|
mgl@1371
|
16484 |
+extern int avr32_legitimate_address (enum machine_mode mode, rtx x,
|
mgl@1371
|
16485 |
+ int strict);
|
mgl@1371
|
16486 |
+extern int avr32_legitimate_constant_p (rtx x);
|
mgl@1371
|
16487 |
+
|
mgl@1371
|
16488 |
+extern int avr32_legitimate_pic_operand_p (rtx x);
|
mgl@1371
|
16489 |
+
|
mgl@1371
|
16490 |
+extern rtx avr32_find_symbol (rtx x);
|
mgl@1371
|
16491 |
+extern void avr32_select_section (rtx exp, int reloc, int align);
|
mgl@1371
|
16492 |
+extern void avr32_encode_section_info (tree decl, rtx rtl, int first);
|
mgl@1371
|
16493 |
+extern void avr32_asm_file_end (FILE * stream);
|
mgl@1371
|
16494 |
+extern void avr32_asm_output_ascii (FILE * stream, char *ptr, int len);
|
mgl@1371
|
16495 |
+extern void avr32_asm_output_common (FILE * stream, const char *name,
|
mgl@1371
|
16496 |
+ int size, int rounded);
|
mgl@1371
|
16497 |
+extern void avr32_asm_output_label (FILE * stream, const char *name);
|
mgl@1371
|
16498 |
+extern void avr32_asm_declare_object_name (FILE * stream, char *name,
|
mgl@1371
|
16499 |
+ tree decl);
|
mgl@1371
|
16500 |
+extern void avr32_asm_globalize_label (FILE * stream, const char *name);
|
mgl@1371
|
16501 |
+extern void avr32_asm_weaken_label (FILE * stream, const char *name);
|
mgl@1371
|
16502 |
+extern void avr32_asm_output_external (FILE * stream, tree decl,
|
mgl@1371
|
16503 |
+ const char *name);
|
mgl@1371
|
16504 |
+extern void avr32_asm_output_external_libcall (FILE * stream, rtx symref);
|
mgl@1371
|
16505 |
+extern void avr32_asm_output_labelref (FILE * stream, const char *name);
|
mgl@1371
|
16506 |
+extern void avr32_notice_update_cc (rtx exp, rtx insn);
|
mgl@1371
|
16507 |
+extern void avr32_print_operand (FILE * stream, rtx x, int code);
|
mgl@1371
|
16508 |
+extern void avr32_print_operand_address (FILE * stream, rtx x);
|
mgl@1371
|
16509 |
+
|
mgl@1371
|
16510 |
+extern int avr32_symbol (rtx x);
|
mgl@1371
|
16511 |
+
|
mgl@1371
|
16512 |
+extern void avr32_select_rtx_section (enum machine_mode mode, rtx x,
|
mgl@1371
|
16513 |
+ unsigned HOST_WIDE_INT align);
|
mgl@1371
|
16514 |
+
|
mgl@1371
|
16515 |
+extern int avr32_load_multiple_operation (rtx op, enum machine_mode mode);
|
mgl@1371
|
16516 |
+extern int avr32_store_multiple_operation (rtx op, enum machine_mode mode);
|
mgl@1371
|
16517 |
+
|
mgl@1371
|
16518 |
+extern int avr32_const_ok_for_constraint_p (HOST_WIDE_INT value, char c,
|
mgl@1371
|
16519 |
+ const char *str);
|
mgl@1371
|
16520 |
+
|
mgl@1371
|
16521 |
+extern bool avr32_cannot_force_const_mem (rtx x);
|
mgl@1371
|
16522 |
+
|
mgl@1371
|
16523 |
+extern void avr32_init_builtins (void);
|
mgl@1371
|
16524 |
+
|
mgl@1371
|
16525 |
+extern rtx avr32_expand_builtin (tree exp, rtx target, rtx subtarget,
|
mgl@1371
|
16526 |
+ enum machine_mode mode, int ignore);
|
mgl@1371
|
16527 |
+
|
mgl@1371
|
16528 |
+extern bool avr32_must_pass_in_stack (enum machine_mode mode, tree type);
|
mgl@1371
|
16529 |
+
|
mgl@1371
|
16530 |
+extern bool avr32_strict_argument_naming (CUMULATIVE_ARGS * ca);
|
mgl@1371
|
16531 |
+
|
mgl@1371
|
16532 |
+extern bool avr32_pass_by_reference (CUMULATIVE_ARGS * cum,
|
mgl@1371
|
16533 |
+ enum machine_mode mode,
|
mgl@1371
|
16534 |
+ tree type, bool named);
|
mgl@1371
|
16535 |
+
|
mgl@1371
|
16536 |
+extern rtx avr32_gen_load_multiple (rtx * regs, int count, rtx from,
|
mgl@1371
|
16537 |
+ int write_back, int in_struct_p,
|
mgl@1371
|
16538 |
+ int scalar_p);
|
mgl@1371
|
16539 |
+extern rtx avr32_gen_store_multiple (rtx * regs, int count, rtx to,
|
mgl@1371
|
16540 |
+ int in_struct_p, int scalar_p);
|
mgl@1371
|
16541 |
+extern int avr32_gen_movmemsi (rtx * operands);
|
mgl@1371
|
16542 |
+
|
mgl@1371
|
16543 |
+extern int avr32_rnd_operands (rtx add, rtx shift);
|
mgl@1371
|
16544 |
+extern int avr32_adjust_insn_length (rtx insn, int length);
|
mgl@1371
|
16545 |
+
|
mgl@1371
|
16546 |
+extern int symbol_mentioned_p (rtx x);
|
mgl@1371
|
16547 |
+extern int label_mentioned_p (rtx x);
|
mgl@1371
|
16548 |
+extern rtx legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg);
|
mgl@1371
|
16549 |
+extern int avr32_address_register_rtx_p (rtx x, int strict_p);
|
mgl@1371
|
16550 |
+extern int avr32_legitimate_index_p (enum machine_mode mode, rtx index,
|
mgl@1371
|
16551 |
+ int strict_p);
|
mgl@1371
|
16552 |
+
|
mgl@1371
|
16553 |
+extern int avr32_const_double_immediate (rtx value);
|
mgl@1371
|
16554 |
+extern void avr32_init_expanders (void);
|
mgl@1371
|
16555 |
+extern rtx avr32_return_addr (int count, rtx frame);
|
mgl@1371
|
16556 |
+extern bool avr32_got_mentioned_p (rtx addr);
|
mgl@1371
|
16557 |
+
|
mgl@1371
|
16558 |
+extern void avr32_final_prescan_insn (rtx insn, rtx * opvec, int noperands);
|
mgl@1371
|
16559 |
+
|
mgl@1371
|
16560 |
+extern int avr32_expand_movcc (enum machine_mode mode, rtx operands[]);
|
mgl@1371
|
16561 |
+extern int avr32_expand_addcc (enum machine_mode mode, rtx operands[]);
|
mgl@1371
|
16562 |
+#ifdef RTX_CODE
|
mgl@1371
|
16563 |
+extern int avr32_expand_scc (RTX_CODE cond, rtx * operands);
|
mgl@1371
|
16564 |
+#endif
|
mgl@1371
|
16565 |
+
|
mgl@1371
|
16566 |
+extern int avr32_store_bypass (rtx insn_out, rtx insn_in);
|
mgl@1371
|
16567 |
+extern int avr32_mul_waw_bypass (rtx insn_out, rtx insn_in);
|
mgl@1371
|
16568 |
+extern int avr32_valid_load_double_bypass (rtx insn_out, rtx insn_in);
|
mgl@1371
|
16569 |
+extern int avr32_valid_load_quad_bypass (rtx insn_out, rtx insn_in);
|
mgl@1371
|
16570 |
+extern rtx avr32_output_cmp (rtx cond, enum machine_mode mode,
|
mgl@1371
|
16571 |
+ rtx op0, rtx op1);
|
mgl@1371
|
16572 |
+
|
mgl@1371
|
16573 |
+rtx get_next_insn_cond (rtx cur_insn);
|
mgl@1371
|
16574 |
+int set_next_insn_cond (rtx cur_insn, rtx cond);
|
mgl@1371
|
16575 |
+void avr32_override_options (void);
|
mgl@1371
|
16576 |
+void avr32_load_pic_register (void);
|
mgl@1371
|
16577 |
+#ifdef GCC_BASIC_BLOCK_H
|
mgl@1371
|
16578 |
+rtx avr32_ifcvt_modify_insn (ce_if_block_t *ce_info, rtx pattern, rtx insn,
|
mgl@1371
|
16579 |
+ int *num_true_changes);
|
mgl@1371
|
16580 |
+rtx avr32_ifcvt_modify_test (ce_if_block_t *ce_info, rtx test );
|
mgl@1371
|
16581 |
+void avr32_ifcvt_modify_cancel ( ce_if_block_t *ce_info, int *num_true_changes);
|
mgl@1371
|
16582 |
+#endif
|
mgl@1371
|
16583 |
+void avr32_optimization_options (int level, int size);
|
mgl@1371
|
16584 |
+int avr32_const_ok_for_move (HOST_WIDE_INT c);
|
mgl@1371
|
16585 |
+
|
mgl@1371
|
16586 |
+void avr32_split_const_expr (enum machine_mode mode,
|
mgl@1371
|
16587 |
+ enum machine_mode new_mode,
|
mgl@1371
|
16588 |
+ rtx expr,
|
mgl@1371
|
16589 |
+ rtx *split_expr);
|
mgl@1371
|
16590 |
+void avr32_get_intval (enum machine_mode mode,
|
mgl@1371
|
16591 |
+ rtx const_expr,
|
mgl@1371
|
16592 |
+ HOST_WIDE_INT *val);
|
mgl@1371
|
16593 |
+
|
mgl@1371
|
16594 |
+int avr32_cond_imm_clobber_splittable (rtx insn,
|
mgl@1371
|
16595 |
+ rtx operands[]);
|
mgl@1371
|
16596 |
+
|
mgl@1371
|
16597 |
+
|
mgl@1371
|
16598 |
+#endif /* AVR32_PROTOS_H */
|
mgl@1371
|
16599 |
--- /dev/null
|
mgl@1371
|
16600 |
+++ b/gcc/config/avr32/crti.asm
|
mgl@1371
|
16601 |
@@ -0,0 +1,64 @@
|
mgl@1371
|
16602 |
+/*
|
mgl@1371
|
16603 |
+ Init/fini stuff for AVR32.
|
mgl@1371
|
16604 |
+ Copyright 2003-2006 Atmel Corporation.
|
mgl@1371
|
16605 |
+
|
mgl@1371
|
16606 |
+ Written by Ronny Pedersen, Atmel Norway, <rpedersen@atmel.com>
|
mgl@1371
|
16607 |
+
|
mgl@1371
|
16608 |
+ This file is part of GCC.
|
mgl@1371
|
16609 |
+
|
mgl@1371
|
16610 |
+ This program is free software; you can redistribute it and/or modify
|
mgl@1371
|
16611 |
+ it under the terms of the GNU General Public License as published by
|
mgl@1371
|
16612 |
+ the Free Software Foundation; either version 2 of the License, or
|
mgl@1371
|
16613 |
+ (at your option) any later version.
|
mgl@1371
|
16614 |
+
|
mgl@1371
|
16615 |
+ This program is distributed in the hope that it will be useful,
|
mgl@1371
|
16616 |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
mgl@1371
|
16617 |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
mgl@1371
|
16618 |
+ GNU General Public License for more details.
|
mgl@1371
|
16619 |
+
|
mgl@1371
|
16620 |
+ You should have received a copy of the GNU General Public License
|
mgl@1371
|
16621 |
+ along with this program; if not, write to the Free Software
|
mgl@1371
|
16622 |
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
mgl@1371
|
16623 |
+
|
mgl@1371
|
16624 |
+
|
mgl@1371
|
16625 |
+/* The code in sections .init and .fini is supposed to be a single
|
mgl@1371
|
16626 |
+ regular function. The function in .init is called directly from
|
mgl@1371
|
16627 |
+ start in crt1.asm. The function in .fini is atexit()ed in crt1.asm
|
mgl@1371
|
16628 |
+ too.
|
mgl@1371
|
16629 |
+
|
mgl@1371
|
16630 |
+ crti.asm contributes the prologue of a function to these sections,
|
mgl@1371
|
16631 |
+ and crtn.asm comes up the epilogue. STARTFILE_SPEC should list
|
mgl@1371
|
16632 |
+ crti.o before any other object files that might add code to .init
|
mgl@1371
|
16633 |
+ or .fini sections, and ENDFILE_SPEC should list crtn.o after any
|
mgl@1371
|
16634 |
+ such object files. */
|
mgl@1371
|
16635 |
+
|
mgl@1371
|
16636 |
+ .file "crti.asm"
|
mgl@1371
|
16637 |
+
|
mgl@1371
|
16638 |
+ .section ".init"
|
mgl@1371
|
16639 |
+/* Just load the GOT */
|
mgl@1371
|
16640 |
+ .align 2
|
mgl@1371
|
16641 |
+ .global _init
|
mgl@1371
|
16642 |
+_init:
|
mgl@1371
|
16643 |
+ stm --sp, r6, lr
|
mgl@1371
|
16644 |
+ lddpc r6, 1f
|
mgl@1371
|
16645 |
+0:
|
mgl@1371
|
16646 |
+ rsub r6, pc
|
mgl@1371
|
16647 |
+ rjmp 2f
|
mgl@1371
|
16648 |
+ .align 2
|
mgl@1371
|
16649 |
+1: .long 0b - _GLOBAL_OFFSET_TABLE_
|
mgl@1371
|
16650 |
+2:
|
mgl@1371
|
16651 |
+
|
mgl@1371
|
16652 |
+ .section ".fini"
|
mgl@1371
|
16653 |
+/* Just load the GOT */
|
mgl@1371
|
16654 |
+ .align 2
|
mgl@1371
|
16655 |
+ .global _fini
|
mgl@1371
|
16656 |
+_fini:
|
mgl@1371
|
16657 |
+ stm --sp, r6, lr
|
mgl@1371
|
16658 |
+ lddpc r6, 1f
|
mgl@1371
|
16659 |
+0:
|
mgl@1371
|
16660 |
+ rsub r6, pc
|
mgl@1371
|
16661 |
+ rjmp 2f
|
mgl@1371
|
16662 |
+ .align 2
|
mgl@1371
|
16663 |
+1: .long 0b - _GLOBAL_OFFSET_TABLE_
|
mgl@1371
|
16664 |
+2:
|
mgl@1371
|
16665 |
+
|
mgl@1371
|
16666 |
--- /dev/null
|
mgl@1371
|
16667 |
+++ b/gcc/config/avr32/crtn.asm
|
mgl@1371
|
16668 |
@@ -0,0 +1,44 @@
|
mgl@1371
|
16669 |
+/* Copyright (C) 2001 Free Software Foundation, Inc.
|
mgl@1371
|
16670 |
+ Written By Nick Clifton
|
mgl@1371
|
16671 |
+
|
mgl@1371
|
16672 |
+ This file is free software; you can redistribute it and/or modify it
|
mgl@1371
|
16673 |
+ under the terms of the GNU General Public License as published by the
|
mgl@1371
|
16674 |
+ Free Software Foundation; either version 2, or (at your option) any
|
mgl@1371
|
16675 |
+ later version.
|
mgl@1371
|
16676 |
+
|
mgl@1371
|
16677 |
+ In addition to the permissions in the GNU General Public License, the
|
mgl@1371
|
16678 |
+ Free Software Foundation gives you unlimited permission to link the
|
mgl@1371
|
16679 |
+ compiled version of this file with other programs, and to distribute
|
mgl@1371
|
16680 |
+ those programs without any restriction coming from the use of this
|
mgl@1371
|
16681 |
+ file. (The General Public License restrictions do apply in other
|
mgl@1371
|
16682 |
+ respects; for example, they cover modification of the file, and
|
mgl@1371
|
16683 |
+ distribution when not linked into another program.)
|
mgl@1371
|
16684 |
+
|
mgl@1371
|
16685 |
+ This file is distributed in the hope that it will be useful, but
|
mgl@1371
|
16686 |
+ WITHOUT ANY WARRANTY; without even the implied warranty of
|
mgl@1371
|
16687 |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
mgl@1371
|
16688 |
+ General Public License for more details.
|
mgl@1371
|
16689 |
+
|
mgl@1371
|
16690 |
+ You should have received a copy of the GNU General Public License
|
mgl@1371
|
16691 |
+ along with this program; see the file COPYING. If not, write to
|
mgl@1371
|
16692 |
+ the Free Software Foundation, 59 Temple Place - Suite 330,
|
mgl@1371
|
16693 |
+ Boston, MA 02111-1307, USA.
|
mgl@1371
|
16694 |
+
|
mgl@1371
|
16695 |
+ As a special exception, if you link this library with files
|
mgl@1371
|
16696 |
+ compiled with GCC to produce an executable, this does not cause
|
mgl@1371
|
16697 |
+ the resulting executable to be covered by the GNU General Public License.
|
mgl@1371
|
16698 |
+ This exception does not however invalidate any other reasons why
|
mgl@1371
|
16699 |
+ the executable file might be covered by the GNU General Public License.
|
mgl@1371
|
16700 |
+*/
|
mgl@1371
|
16701 |
+
|
mgl@1371
|
16702 |
+
|
mgl@1371
|
16703 |
+
|
mgl@1371
|
16704 |
+
|
mgl@1371
|
16705 |
+ .file "crtn.asm"
|
mgl@1371
|
16706 |
+
|
mgl@1371
|
16707 |
+ .section ".init"
|
mgl@1371
|
16708 |
+ ldm sp++, r6, pc
|
mgl@1371
|
16709 |
+
|
mgl@1371
|
16710 |
+ .section ".fini"
|
mgl@1371
|
16711 |
+ ldm sp++, r6, pc
|
mgl@1371
|
16712 |
+
|
mgl@1371
|
16713 |
--- /dev/null
|
mgl@1371
|
16714 |
+++ b/gcc/config/avr32/fpcp.md
|
mgl@1371
|
16715 |
@@ -0,0 +1,551 @@
|
mgl@1371
|
16716 |
+;; AVR32 machine description file for Floating-Point instructions.
|
mgl@1371
|
16717 |
+;; Copyright 2003-2006 Atmel Corporation.
|
mgl@1371
|
16718 |
+;;
|
mgl@1371
|
16719 |
+;; Written by Ronny Pedersen, Atmel Norway, <rpedersen@atmel.com>
|
mgl@1371
|
16720 |
+;;
|
mgl@1371
|
16721 |
+;; This file is part of GCC.
|
mgl@1371
|
16722 |
+;;
|
mgl@1371
|
16723 |
+;; This program is free software; you can redistribute it and/or modify
|
mgl@1371
|
16724 |
+;; it under the terms of the GNU General Public License as published by
|
mgl@1371
|
16725 |
+;; the Free Software Foundation; either version 2 of the License, or
|
mgl@1371
|
16726 |
+;; (at your option) any later version.
|
mgl@1371
|
16727 |
+;;
|
mgl@1371
|
16728 |
+;; This program is distributed in the hope that it will be useful,
|
mgl@1371
|
16729 |
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
mgl@1371
|
16730 |
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
mgl@1371
|
16731 |
+;; GNU General Public License for more details.
|
mgl@1371
|
16732 |
+;;
|
mgl@1371
|
16733 |
+;; You should have received a copy of the GNU General Public License
|
mgl@1371
|
16734 |
+;; along with this program; if not, write to the Free Software
|
mgl@1371
|
16735 |
+;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
mgl@1371
|
16736 |
+
|
mgl@1371
|
16737 |
+;; -*- Mode: Scheme -*-
|
mgl@1371
|
16738 |
+
|
mgl@1371
|
16739 |
+;;******************************************************************************
|
mgl@1371
|
16740 |
+;; Automaton pipeline description for floating-point coprocessor insns
|
mgl@1371
|
16741 |
+;;******************************************************************************
|
mgl@1371
|
16742 |
+(define_cpu_unit "fid,fm1,fm2,fm3,fm4,fwb,fcmp,fcast" "avr32_ap")
|
mgl@1371
|
16743 |
+
|
mgl@1371
|
16744 |
+(define_insn_reservation "fmv_op" 1
|
mgl@1371
|
16745 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
16746 |
+ (eq_attr "type" "fmv"))
|
mgl@1371
|
16747 |
+ "is,da,d,fid,fwb")
|
mgl@1371
|
16748 |
+
|
mgl@1371
|
16749 |
+(define_insn_reservation "fmul_op" 5
|
mgl@1371
|
16750 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
16751 |
+ (eq_attr "type" "fmul"))
|
mgl@1371
|
16752 |
+ "is,da,d,fid,fm1,fm2,fm3,fm4,fwb")
|
mgl@1371
|
16753 |
+
|
mgl@1371
|
16754 |
+(define_insn_reservation "fcmps_op" 1
|
mgl@1371
|
16755 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
16756 |
+ (eq_attr "type" "fcmps"))
|
mgl@1371
|
16757 |
+ "is,da,d,fid,fcmp")
|
mgl@1371
|
16758 |
+
|
mgl@1371
|
16759 |
+(define_insn_reservation "fcmpd_op" 2
|
mgl@1371
|
16760 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
16761 |
+ (eq_attr "type" "fcmpd"))
|
mgl@1371
|
16762 |
+ "is,da,d,fid*2,fcmp")
|
mgl@1371
|
16763 |
+
|
mgl@1371
|
16764 |
+(define_insn_reservation "fcast_op" 3
|
mgl@1371
|
16765 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
16766 |
+ (eq_attr "type" "fcast"))
|
mgl@1371
|
16767 |
+ "is,da,d,fid,fcmp,fcast,fwb")
|
mgl@1371
|
16768 |
+
|
mgl@1371
|
16769 |
+(define_insn_reservation "fmvcpu_op" 2
|
mgl@1371
|
16770 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
16771 |
+ (eq_attr "type" "fmvcpu"))
|
mgl@1371
|
16772 |
+ "is,da,d")
|
mgl@1371
|
16773 |
+
|
mgl@1371
|
16774 |
+(define_insn_reservation "fldd_op" 1
|
mgl@1371
|
16775 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
16776 |
+ (eq_attr "type" "fldd"))
|
mgl@1371
|
16777 |
+ "is,da,d,fwb")
|
mgl@1371
|
16778 |
+
|
mgl@1371
|
16779 |
+(define_insn_reservation "flds_op" 1
|
mgl@1371
|
16780 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
16781 |
+ (eq_attr "type" "flds"))
|
mgl@1371
|
16782 |
+ "is,da,d,fwb")
|
mgl@1371
|
16783 |
+
|
mgl@1371
|
16784 |
+(define_insn_reservation "fsts_op" 0
|
mgl@1371
|
16785 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
16786 |
+ (eq_attr "type" "fsts"))
|
mgl@1371
|
16787 |
+ "is,da*2,d")
|
mgl@1371
|
16788 |
+
|
mgl@1371
|
16789 |
+(define_insn_reservation "fstd_op" 0
|
mgl@1371
|
16790 |
+ (and (eq_attr "pipeline" "ap")
|
mgl@1371
|
16791 |
+ (eq_attr "type" "fstd"))
|
mgl@1371
|
16792 |
+ "is,da*2,d")
|
mgl@1371
|
16793 |
+
|
mgl@1371
|
16794 |
+
|
mgl@1371
|
16795 |
+(define_insn "*movsf_fpcp"
|
mgl@1371
|
16796 |
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,r,f,m,r,r,r,m")
|
mgl@1371
|
16797 |
+ (match_operand:SF 1 "general_operand" " f,r,f,m,f,r,G,m,r"))]
|
mgl@1371
|
16798 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
16799 |
+ "@
|
mgl@1371
|
16800 |
+ fmov.s\t%0, %1
|
mgl@1371
|
16801 |
+ fmov.s\t%0, %1
|
mgl@1371
|
16802 |
+ fmov.s\t%0, %1
|
mgl@1371
|
16803 |
+ fld.s\t%0, %1
|
mgl@1371
|
16804 |
+ fst.s\t%0, %1
|
mgl@1371
|
16805 |
+ mov\t%0, %1
|
mgl@1371
|
16806 |
+ mov\t%0, %1
|
mgl@1371
|
16807 |
+ ld.w\t%0, %1
|
mgl@1371
|
16808 |
+ st.w\t%0, %1"
|
mgl@1371
|
16809 |
+ [(set_attr "length" "4,4,4,4,4,2,4,4,4")
|
mgl@1371
|
16810 |
+ (set_attr "type" "fmv,flds,fmvcpu,flds,fsts,alu,alu,load,store")])
|
mgl@1371
|
16811 |
+
|
mgl@1371
|
16812 |
+(define_insn_and_split "*movdf_fpcp"
|
mgl@1371
|
16813 |
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,r,f,m,r,r,m")
|
mgl@1371
|
16814 |
+ (match_operand:DF 1 "general_operand" " f,r,f,m,f,r,m,r"))]
|
mgl@1371
|
16815 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
16816 |
+ "@
|
mgl@1371
|
16817 |
+ fmov.d\t%0, %1
|
mgl@1371
|
16818 |
+ fmov.d\t%0, %1
|
mgl@1371
|
16819 |
+ fmov.d\t%0, %1
|
mgl@1371
|
16820 |
+ fld.d\t%0, %1
|
mgl@1371
|
16821 |
+ fst.d\t%0, %1
|
mgl@1371
|
16822 |
+ mov\t%0, %1\;mov\t%m0, %m1
|
mgl@1371
|
16823 |
+ ld.d\t%0, %1
|
mgl@1371
|
16824 |
+ st.d\t%0, %1"
|
mgl@1371
|
16825 |
+
|
mgl@1371
|
16826 |
+ "TARGET_HARD_FLOAT
|
mgl@1371
|
16827 |
+ && reload_completed
|
mgl@1371
|
16828 |
+ && (REG_P(operands[0]) && (REGNO_REG_CLASS(REGNO(operands[0])) == GENERAL_REGS))
|
mgl@1371
|
16829 |
+ && (REG_P(operands[1]) && (REGNO_REG_CLASS(REGNO(operands[1])) == GENERAL_REGS))"
|
mgl@1371
|
16830 |
+ [(set (match_dup 0) (match_dup 1))
|
mgl@1371
|
16831 |
+ (set (match_dup 2) (match_dup 3))]
|
mgl@1371
|
16832 |
+ "
|
mgl@1371
|
16833 |
+ {
|
mgl@1371
|
16834 |
+ operands[2] = gen_highpart (SImode, operands[0]);
|
mgl@1371
|
16835 |
+ operands[0] = gen_lowpart (SImode, operands[0]);
|
mgl@1371
|
16836 |
+ operands[3] = gen_highpart(SImode, operands[1]);
|
mgl@1371
|
16837 |
+ operands[1] = gen_lowpart(SImode, operands[1]);
|
mgl@1371
|
16838 |
+ }
|
mgl@1371
|
16839 |
+ "
|
mgl@1371
|
16840 |
+
|
mgl@1371
|
16841 |
+ [(set_attr "length" "4,4,4,4,4,4,4,4")
|
mgl@1371
|
16842 |
+ (set_attr "type" "fmv,fldd,fmvcpu,fldd,fstd,alu2,load2,store2")])
|
mgl@1371
|
16843 |
+
|
mgl@1371
|
16844 |
+
|
mgl@1371
|
16845 |
+(define_insn "mulsf3"
|
mgl@1371
|
16846 |
+ [(set (match_operand:SF 0 "avr32_fp_register_operand" "=f")
|
mgl@1371
|
16847 |
+ (mult:SF (match_operand:SF 1 "avr32_fp_register_operand" "f")
|
mgl@1371
|
16848 |
+ (match_operand:SF 2 "avr32_fp_register_operand" "f")))]
|
mgl@1371
|
16849 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
16850 |
+ "fmul.s\t%0, %1, %2"
|
mgl@1371
|
16851 |
+ [(set_attr "length" "4")
|
mgl@1371
|
16852 |
+ (set_attr "type" "fmul")])
|
mgl@1371
|
16853 |
+
|
mgl@1371
|
16854 |
+(define_insn "nmulsf3"
|
mgl@1371
|
16855 |
+ [(set (match_operand:SF 0 "avr32_fp_register_operand" "=f")
|
mgl@1371
|
16856 |
+ (neg:SF (mult:SF (match_operand:SF 1 "avr32_fp_register_operand" "f")
|
mgl@1371
|
16857 |
+ (match_operand:SF 2 "avr32_fp_register_operand" "f"))))]
|
mgl@1371
|
16858 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
16859 |
+ "fnmul.s\t%0, %1, %2"
|
mgl@1371
|
16860 |
+ [(set_attr "length" "4")
|
mgl@1371
|
16861 |
+ (set_attr "type" "fmul")])
|
mgl@1371
|
16862 |
+
|
mgl@1371
|
16863 |
+(define_peephole2
|
mgl@1371
|
16864 |
+ [(set (match_operand:SF 0 "avr32_fp_register_operand" "")
|
mgl@1371
|
16865 |
+ (mult:SF (match_operand:SF 1 "avr32_fp_register_operand" "")
|
mgl@1371
|
16866 |
+ (match_operand:SF 2 "avr32_fp_register_operand" "")))
|
mgl@1371
|
16867 |
+ (set (match_operand:SF 3 "avr32_fp_register_operand" "")
|
mgl@1371
|
16868 |
+ (neg:SF (match_dup 0)))]
|
mgl@1371
|
16869 |
+ "TARGET_HARD_FLOAT &&
|
mgl@1371
|
16870 |
+ (peep2_reg_dead_p(2, operands[0]) || (REGNO(operands[3]) == REGNO(operands[0])))"
|
mgl@1371
|
16871 |
+ [(set (match_dup 3)
|
mgl@1371
|
16872 |
+ (neg:SF (mult:SF (match_dup 1)
|
mgl@1371
|
16873 |
+ (match_dup 2))))]
|
mgl@1371
|
16874 |
+)
|
mgl@1371
|
16875 |
+
|
mgl@1371
|
16876 |
+
|
mgl@1371
|
16877 |
+(define_insn "macsf3"
|
mgl@1371
|
16878 |
+ [(set (match_operand:SF 0 "avr32_fp_register_operand" "=f")
|
mgl@1371
|
16879 |
+ (plus:SF (mult:SF (match_operand:SF 1 "avr32_fp_register_operand" "f")
|
mgl@1371
|
16880 |
+ (match_operand:SF 2 "avr32_fp_register_operand" "f"))
|
mgl@1371
|
16881 |
+ (match_operand:SF 3 "avr32_fp_register_operand" "0")))]
|
mgl@1371
|
16882 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
16883 |
+ "fmac.s\t%0, %1, %2"
|
mgl@1371
|
16884 |
+ [(set_attr "length" "4")
|
mgl@1371
|
16885 |
+ (set_attr "type" "fmul")])
|
mgl@1371
|
16886 |
+
|
mgl@1371
|
16887 |
+(define_insn "nmacsf3"
|
mgl@1371
|
16888 |
+ [(set (match_operand:SF 0 "avr32_fp_register_operand" "=f")
|
mgl@1371
|
16889 |
+ (plus:SF (neg:SF (mult:SF (match_operand:SF 1 "avr32_fp_register_operand" "f")
|
mgl@1371
|
16890 |
+ (match_operand:SF 2 "avr32_fp_register_operand" "f")))
|
mgl@1371
|
16891 |
+ (match_operand:SF 3 "avr32_fp_register_operand" "0")))]
|
mgl@1371
|
16892 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
16893 |
+ "fnmac.s\t%0, %1, %2"
|
mgl@1371
|
16894 |
+ [(set_attr "length" "4")
|
mgl@1371
|
16895 |
+ (set_attr "type" "fmul")])
|
mgl@1371
|
16896 |
+
|
mgl@1371
|
16897 |
+(define_peephole2
|
mgl@1371
|
16898 |
+ [(set (match_operand:SF 0 "avr32_fp_register_operand" "")
|
mgl@1371
|
16899 |
+ (mult:SF (match_operand:SF 1 "avr32_fp_register_operand" "")
|
mgl@1371
|
16900 |
+ (match_operand:SF 2 "avr32_fp_register_operand" "")))
|
mgl@1371
|
16901 |
+ (set (match_operand:SF 3 "avr32_fp_register_operand" "")
|
mgl@1371
|
16902 |
+ (minus:SF
|
mgl@1371
|
16903 |
+ (match_dup 3)
|
mgl@1371
|
16904 |
+ (match_dup 0)))]
|
mgl@1371
|
16905 |
+ "TARGET_HARD_FLOAT && peep2_reg_dead_p(2, operands[0])"
|
mgl@1371
|
16906 |
+ [(set (match_dup 3)
|
mgl@1371
|
16907 |
+ (plus:SF (neg:SF (mult:SF (match_dup 1)
|
mgl@1371
|
16908 |
+ (match_dup 2)))
|
mgl@1371
|
16909 |
+ (match_dup 3)))]
|
mgl@1371
|
16910 |
+)
|
mgl@1371
|
16911 |
+
|
mgl@1371
|
16912 |
+
|
mgl@1371
|
16913 |
+(define_insn "msubacsf3"
|
mgl@1371
|
16914 |
+ [(set (match_operand:SF 0 "avr32_fp_register_operand" "=f")
|
mgl@1371
|
16915 |
+ (minus:SF (mult:SF (match_operand:SF 1 "avr32_fp_register_operand" "f")
|
mgl@1371
|
16916 |
+ (match_operand:SF 2 "avr32_fp_register_operand" "f"))
|
mgl@1371
|
16917 |
+ (match_operand:SF 3 "avr32_fp_register_operand" "0")))]
|
mgl@1371
|
16918 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
16919 |
+ "fmsc.s\t%0, %1, %2"
|
mgl@1371
|
16920 |
+ [(set_attr "length" "4")
|
mgl@1371
|
16921 |
+ (set_attr "type" "fmul")])
|
mgl@1371
|
16922 |
+
|
mgl@1371
|
16923 |
+(define_peephole2
|
mgl@1371
|
16924 |
+ [(set (match_operand:SF 0 "avr32_fp_register_operand" "")
|
mgl@1371
|
16925 |
+ (mult:SF (match_operand:SF 1 "avr32_fp_register_operand" "")
|
mgl@1371
|
16926 |
+ (match_operand:SF 2 "avr32_fp_register_operand" "")))
|
mgl@1371
|
16927 |
+ (set (match_operand:SF 3 "avr32_fp_register_operand" "")
|
mgl@1371
|
16928 |
+ (minus:SF
|
mgl@1371
|
16929 |
+ (match_dup 0)
|
mgl@1371
|
16930 |
+ (match_dup 3)))]
|
mgl@1371
|
16931 |
+ "TARGET_HARD_FLOAT && peep2_reg_dead_p(2, operands[0])"
|
mgl@1371
|
16932 |
+ [(set (match_dup 3)
|
mgl@1371
|
16933 |
+ (minus:SF (mult:SF (match_dup 1)
|
mgl@1371
|
16934 |
+ (match_dup 2))
|
mgl@1371
|
16935 |
+ (match_dup 3)))]
|
mgl@1371
|
16936 |
+)
|
mgl@1371
|
16937 |
+
|
mgl@1371
|
16938 |
+(define_insn "nmsubacsf3"
|
mgl@1371
|
16939 |
+ [(set (match_operand:SF 0 "avr32_fp_register_operand" "=f")
|
mgl@1371
|
16940 |
+ (minus:SF (neg:SF (mult:SF (match_operand:SF 1 "avr32_fp_register_operand" "f")
|
mgl@1371
|
16941 |
+ (match_operand:SF 2 "avr32_fp_register_operand" "f")))
|
mgl@1371
|
16942 |
+ (match_operand:SF 3 "avr32_fp_register_operand" "0")))]
|
mgl@1371
|
16943 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
16944 |
+ "fnmsc.s\t%0, %1, %2"
|
mgl@1371
|
16945 |
+ [(set_attr "length" "4")
|
mgl@1371
|
16946 |
+ (set_attr "type" "fmul")])
|
mgl@1371
|
16947 |
+
|
mgl@1371
|
16948 |
+
|
mgl@1371
|
16949 |
+
|
mgl@1371
|
16950 |
+(define_insn "addsf3"
|
mgl@1371
|
16951 |
+ [(set (match_operand:SF 0 "avr32_fp_register_operand" "=f")
|
mgl@1371
|
16952 |
+ (plus:SF (match_operand:SF 1 "avr32_fp_register_operand" "f")
|
mgl@1371
|
16953 |
+ (match_operand:SF 2 "avr32_fp_register_operand" "f")))]
|
mgl@1371
|
16954 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
16955 |
+ "fadd.s\t%0, %1, %2"
|
mgl@1371
|
16956 |
+ [(set_attr "length" "4")
|
mgl@1371
|
16957 |
+ (set_attr "type" "fmul")])
|
mgl@1371
|
16958 |
+
|
mgl@1371
|
16959 |
+(define_insn "subsf3"
|
mgl@1371
|
16960 |
+ [(set (match_operand:SF 0 "avr32_fp_register_operand" "=f")
|
mgl@1371
|
16961 |
+ (minus:SF (match_operand:SF 1 "avr32_fp_register_operand" "f")
|
mgl@1371
|
16962 |
+ (match_operand:SF 2 "avr32_fp_register_operand" "f")))]
|
mgl@1371
|
16963 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
16964 |
+ "fsub.s\t%0, %1, %2"
|
mgl@1371
|
16965 |
+ [(set_attr "length" "4")
|
mgl@1371
|
16966 |
+ (set_attr "type" "fmul")])
|
mgl@1371
|
16967 |
+
|
mgl@1371
|
16968 |
+
|
mgl@1371
|
16969 |
+(define_insn "negsf2"
|
mgl@1371
|
16970 |
+ [(set (match_operand:SF 0 "avr32_fp_register_operand" "=f")
|
mgl@1371
|
16971 |
+ (neg:SF (match_operand:SF 1 "avr32_fp_register_operand" "f")))]
|
mgl@1371
|
16972 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
16973 |
+ "fneg.s\t%0, %1"
|
mgl@1371
|
16974 |
+ [(set_attr "length" "4")
|
mgl@1371
|
16975 |
+ (set_attr "type" "fmv")])
|
mgl@1371
|
16976 |
+
|
mgl@1371
|
16977 |
+(define_insn "abssf2"
|
mgl@1371
|
16978 |
+ [(set (match_operand:SF 0 "avr32_fp_register_operand" "=f")
|
mgl@1371
|
16979 |
+ (abs:SF (match_operand:SF 1 "avr32_fp_register_operand" "f")))]
|
mgl@1371
|
16980 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
16981 |
+ "fabs.s\t%0, %1"
|
mgl@1371
|
16982 |
+ [(set_attr "length" "4")
|
mgl@1371
|
16983 |
+ (set_attr "type" "fmv")])
|
mgl@1371
|
16984 |
+
|
mgl@1371
|
16985 |
+(define_insn "truncdfsf2"
|
mgl@1371
|
16986 |
+ [(set (match_operand:SF 0 "avr32_fp_register_operand" "=f")
|
mgl@1371
|
16987 |
+ (float_truncate:SF
|
mgl@1371
|
16988 |
+ (match_operand:DF 1 "avr32_fp_register_operand" "f")))]
|
mgl@1371
|
16989 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
16990 |
+ "fcastd.s\t%0, %1"
|
mgl@1371
|
16991 |
+ [(set_attr "length" "4")
|
mgl@1371
|
16992 |
+ (set_attr "type" "fcast")])
|
mgl@1371
|
16993 |
+
|
mgl@1371
|
16994 |
+(define_insn "extendsfdf2"
|
mgl@1371
|
16995 |
+ [(set (match_operand:DF 0 "avr32_fp_register_operand" "=f")
|
mgl@1371
|
16996 |
+ (float_extend:DF
|
mgl@1371
|
16997 |
+ (match_operand:SF 1 "avr32_fp_register_operand" "f")))]
|
mgl@1371
|
16998 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
16999 |
+ "fcasts.d\t%0, %1"
|
mgl@1371
|
17000 |
+ [(set_attr "length" "4")
|
mgl@1371
|
17001 |
+ (set_attr "type" "fcast")])
|
mgl@1371
|
17002 |
+
|
mgl@1371
|
17003 |
+(define_insn "muldf3"
|
mgl@1371
|
17004 |
+ [(set (match_operand:DF 0 "avr32_fp_register_operand" "=f")
|
mgl@1371
|
17005 |
+ (mult:DF (match_operand:DF 1 "avr32_fp_register_operand" "f")
|
mgl@1371
|
17006 |
+ (match_operand:DF 2 "avr32_fp_register_operand" "f")))]
|
mgl@1371
|
17007 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
17008 |
+ "fmul.d\t%0, %1, %2"
|
mgl@1371
|
17009 |
+ [(set_attr "length" "4")
|
mgl@1371
|
17010 |
+ (set_attr "type" "fmul")])
|
mgl@1371
|
17011 |
+
|
mgl@1371
|
17012 |
+(define_insn "nmuldf3"
|
mgl@1371
|
17013 |
+ [(set (match_operand:DF 0 "avr32_fp_register_operand" "=f")
|
mgl@1371
|
17014 |
+ (neg:DF (mult:DF (match_operand:DF 1 "avr32_fp_register_operand" "f")
|
mgl@1371
|
17015 |
+ (match_operand:DF 2 "avr32_fp_register_operand" "f"))))]
|
mgl@1371
|
17016 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
17017 |
+ "fnmul.d\t%0, %1, %2"
|
mgl@1371
|
17018 |
+ [(set_attr "length" "4")
|
mgl@1371
|
17019 |
+ (set_attr "type" "fmul")])
|
mgl@1371
|
17020 |
+
|
mgl@1371
|
17021 |
+(define_peephole2
|
mgl@1371
|
17022 |
+ [(set (match_operand:DF 0 "avr32_fp_register_operand" "")
|
mgl@1371
|
17023 |
+ (mult:DF (match_operand:DF 1 "avr32_fp_register_operand" "")
|
mgl@1371
|
17024 |
+ (match_operand:DF 2 "avr32_fp_register_operand" "")))
|
mgl@1371
|
17025 |
+ (set (match_operand:DF 3 "avr32_fp_register_operand" "")
|
mgl@1371
|
17026 |
+ (neg:DF (match_dup 0)))]
|
mgl@1371
|
17027 |
+ "TARGET_HARD_FLOAT &&
|
mgl@1371
|
17028 |
+ (peep2_reg_dead_p(2, operands[0]) || (REGNO(operands[3]) == REGNO(operands[0])))"
|
mgl@1371
|
17029 |
+ [(set (match_dup 3)
|
mgl@1371
|
17030 |
+ (neg:DF (mult:DF (match_dup 1)
|
mgl@1371
|
17031 |
+ (match_dup 2))))]
|
mgl@1371
|
17032 |
+)
|
mgl@1371
|
17033 |
+
|
mgl@1371
|
17034 |
+(define_insn "macdf3"
|
mgl@1371
|
17035 |
+ [(set (match_operand:DF 0 "avr32_fp_register_operand" "=f")
|
mgl@1371
|
17036 |
+ (plus:DF (mult:DF (match_operand:DF 1 "avr32_fp_register_operand" "f")
|
mgl@1371
|
17037 |
+ (match_operand:DF 2 "avr32_fp_register_operand" "f"))
|
mgl@1371
|
17038 |
+ (match_operand:DF 3 "avr32_fp_register_operand" "0")))]
|
mgl@1371
|
17039 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
17040 |
+ "fmac.d\t%0, %1, %2"
|
mgl@1371
|
17041 |
+ [(set_attr "length" "4")
|
mgl@1371
|
17042 |
+ (set_attr "type" "fmul")])
|
mgl@1371
|
17043 |
+
|
mgl@1371
|
17044 |
+(define_insn "msubacdf3"
|
mgl@1371
|
17045 |
+ [(set (match_operand:DF 0 "avr32_fp_register_operand" "=f")
|
mgl@1371
|
17046 |
+ (minus:DF (mult:DF (match_operand:DF 1 "avr32_fp_register_operand" "f")
|
mgl@1371
|
17047 |
+ (match_operand:DF 2 "avr32_fp_register_operand" "f"))
|
mgl@1371
|
17048 |
+ (match_operand:DF 3 "avr32_fp_register_operand" "0")))]
|
mgl@1371
|
17049 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
17050 |
+ "fmsc.d\t%0, %1, %2"
|
mgl@1371
|
17051 |
+ [(set_attr "length" "4")
|
mgl@1371
|
17052 |
+ (set_attr "type" "fmul")])
|
mgl@1371
|
17053 |
+
|
mgl@1371
|
17054 |
+(define_peephole2
|
mgl@1371
|
17055 |
+ [(set (match_operand:DF 0 "avr32_fp_register_operand" "")
|
mgl@1371
|
17056 |
+ (mult:DF (match_operand:DF 1 "avr32_fp_register_operand" "")
|
mgl@1371
|
17057 |
+ (match_operand:DF 2 "avr32_fp_register_operand" "")))
|
mgl@1371
|
17058 |
+ (set (match_operand:DF 3 "avr32_fp_register_operand" "")
|
mgl@1371
|
17059 |
+ (minus:DF
|
mgl@1371
|
17060 |
+ (match_dup 0)
|
mgl@1371
|
17061 |
+ (match_dup 3)))]
|
mgl@1371
|
17062 |
+ "TARGET_HARD_FLOAT && peep2_reg_dead_p(2, operands[0])"
|
mgl@1371
|
17063 |
+ [(set (match_dup 3)
|
mgl@1371
|
17064 |
+ (minus:DF (mult:DF (match_dup 1)
|
mgl@1371
|
17065 |
+ (match_dup 2))
|
mgl@1371
|
17066 |
+ (match_dup 3)))]
|
mgl@1371
|
17067 |
+ )
|
mgl@1371
|
17068 |
+
|
mgl@1371
|
17069 |
+(define_insn "nmsubacdf3"
|
mgl@1371
|
17070 |
+ [(set (match_operand:DF 0 "avr32_fp_register_operand" "=f")
|
mgl@1371
|
17071 |
+ (minus:DF (neg:DF (mult:DF (match_operand:DF 1 "avr32_fp_register_operand" "f")
|
mgl@1371
|
17072 |
+ (match_operand:DF 2 "avr32_fp_register_operand" "f")))
|
mgl@1371
|
17073 |
+ (match_operand:DF 3 "avr32_fp_register_operand" "0")))]
|
mgl@1371
|
17074 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
17075 |
+ "fnmsc.d\t%0, %1, %2"
|
mgl@1371
|
17076 |
+ [(set_attr "length" "4")
|
mgl@1371
|
17077 |
+ (set_attr "type" "fmul")])
|
mgl@1371
|
17078 |
+
|
mgl@1371
|
17079 |
+(define_insn "nmacdf3"
|
mgl@1371
|
17080 |
+ [(set (match_operand:DF 0 "avr32_fp_register_operand" "=f")
|
mgl@1371
|
17081 |
+ (plus:DF (neg:DF (mult:DF (match_operand:DF 1 "avr32_fp_register_operand" "f")
|
mgl@1371
|
17082 |
+ (match_operand:DF 2 "avr32_fp_register_operand" "f")))
|
mgl@1371
|
17083 |
+ (match_operand:DF 3 "avr32_fp_register_operand" "0")))]
|
mgl@1371
|
17084 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
17085 |
+ "fnmac.d\t%0, %1, %2"
|
mgl@1371
|
17086 |
+ [(set_attr "length" "4")
|
mgl@1371
|
17087 |
+ (set_attr "type" "fmul")])
|
mgl@1371
|
17088 |
+
|
mgl@1371
|
17089 |
+(define_peephole2
|
mgl@1371
|
17090 |
+ [(set (match_operand:DF 0 "avr32_fp_register_operand" "")
|
mgl@1371
|
17091 |
+ (mult:DF (match_operand:DF 1 "avr32_fp_register_operand" "")
|
mgl@1371
|
17092 |
+ (match_operand:DF 2 "avr32_fp_register_operand" "")))
|
mgl@1371
|
17093 |
+ (set (match_operand:DF 3 "avr32_fp_register_operand" "")
|
mgl@1371
|
17094 |
+ (minus:DF
|
mgl@1371
|
17095 |
+ (match_dup 3)
|
mgl@1371
|
17096 |
+ (match_dup 0)))]
|
mgl@1371
|
17097 |
+ "TARGET_HARD_FLOAT && peep2_reg_dead_p(2, operands[0])"
|
mgl@1371
|
17098 |
+ [(set (match_dup 3)
|
mgl@1371
|
17099 |
+ (plus:DF (neg:DF (mult:DF (match_dup 1)
|
mgl@1371
|
17100 |
+ (match_dup 2)))
|
mgl@1371
|
17101 |
+ (match_dup 3)))]
|
mgl@1371
|
17102 |
+)
|
mgl@1371
|
17103 |
+
|
mgl@1371
|
17104 |
+(define_insn "adddf3"
|
mgl@1371
|
17105 |
+ [(set (match_operand:DF 0 "avr32_fp_register_operand" "=f")
|
mgl@1371
|
17106 |
+ (plus:DF (match_operand:DF 1 "avr32_fp_register_operand" "f")
|
mgl@1371
|
17107 |
+ (match_operand:DF 2 "avr32_fp_register_operand" "f")))]
|
mgl@1371
|
17108 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
17109 |
+ "fadd.d\t%0, %1, %2"
|
mgl@1371
|
17110 |
+ [(set_attr "length" "4")
|
mgl@1371
|
17111 |
+ (set_attr "type" "fmul")])
|
mgl@1371
|
17112 |
+
|
mgl@1371
|
17113 |
+(define_insn "subdf3"
|
mgl@1371
|
17114 |
+ [(set (match_operand:DF 0 "avr32_fp_register_operand" "=f")
|
mgl@1371
|
17115 |
+ (minus:DF (match_operand:DF 1 "avr32_fp_register_operand" "f")
|
mgl@1371
|
17116 |
+ (match_operand:DF 2 "avr32_fp_register_operand" "f")))]
|
mgl@1371
|
17117 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
17118 |
+ "fsub.d\t%0, %1, %2"
|
mgl@1371
|
17119 |
+ [(set_attr "length" "4")
|
mgl@1371
|
17120 |
+ (set_attr "type" "fmul")])
|
mgl@1371
|
17121 |
+
|
mgl@1371
|
17122 |
+(define_insn "negdf2"
|
mgl@1371
|
17123 |
+ [(set (match_operand:DF 0 "avr32_fp_register_operand" "=f")
|
mgl@1371
|
17124 |
+ (neg:DF (match_operand:DF 1 "avr32_fp_register_operand" "f")))]
|
mgl@1371
|
17125 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
17126 |
+ "fneg.d\t%0, %1"
|
mgl@1371
|
17127 |
+ [(set_attr "length" "4")
|
mgl@1371
|
17128 |
+ (set_attr "type" "fmv")])
|
mgl@1371
|
17129 |
+
|
mgl@1371
|
17130 |
+(define_insn "absdf2"
|
mgl@1371
|
17131 |
+ [(set (match_operand:DF 0 "avr32_fp_register_operand" "=f")
|
mgl@1371
|
17132 |
+ (abs:DF (match_operand:DF 1 "avr32_fp_register_operand" "f")))]
|
mgl@1371
|
17133 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
17134 |
+ "fabs.d\t%0, %1"
|
mgl@1371
|
17135 |
+ [(set_attr "length" "4")
|
mgl@1371
|
17136 |
+ (set_attr "type" "fmv")])
|
mgl@1371
|
17137 |
+
|
mgl@1371
|
17138 |
+
|
mgl@1371
|
17139 |
+(define_expand "cmpdf"
|
mgl@1371
|
17140 |
+ [(set (cc0)
|
mgl@1371
|
17141 |
+ (compare:DF
|
mgl@1371
|
17142 |
+ (match_operand:DF 0 "general_operand" "")
|
mgl@1371
|
17143 |
+ (match_operand:DF 1 "general_operand" "")))]
|
mgl@1371
|
17144 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
17145 |
+ "{
|
mgl@1371
|
17146 |
+ rtx tmpreg;
|
mgl@1371
|
17147 |
+ if ( !REG_P(operands[0]) )
|
mgl@1371
|
17148 |
+ operands[0] = force_reg(DFmode, operands[0]);
|
mgl@1371
|
17149 |
+
|
mgl@1371
|
17150 |
+ if ( !REG_P(operands[1]) )
|
mgl@1371
|
17151 |
+ operands[1] = force_reg(DFmode, operands[1]);
|
mgl@1371
|
17152 |
+
|
mgl@1371
|
17153 |
+ avr32_compare_op0 = operands[0];
|
mgl@1371
|
17154 |
+ avr32_compare_op1 = operands[1];
|
mgl@1371
|
17155 |
+
|
mgl@1371
|
17156 |
+ emit_insn(gen_cmpdf_internal(operands[0], operands[1]));
|
mgl@1371
|
17157 |
+
|
mgl@1371
|
17158 |
+ tmpreg = gen_reg_rtx(SImode);
|
mgl@1371
|
17159 |
+ emit_insn(gen_fpcc_to_reg(tmpreg));
|
mgl@1371
|
17160 |
+ emit_insn(gen_reg_to_cc(tmpreg));
|
mgl@1371
|
17161 |
+
|
mgl@1371
|
17162 |
+ DONE;
|
mgl@1371
|
17163 |
+ }"
|
mgl@1371
|
17164 |
+)
|
mgl@1371
|
17165 |
+
|
mgl@1371
|
17166 |
+(define_insn "cmpdf_internal"
|
mgl@1371
|
17167 |
+ [(set (reg:CC FPCC_REGNUM)
|
mgl@1371
|
17168 |
+ (compare:CC
|
mgl@1371
|
17169 |
+ (match_operand:DF 0 "avr32_fp_register_operand" "f")
|
mgl@1371
|
17170 |
+ (match_operand:DF 1 "avr32_fp_register_operand" "f")))]
|
mgl@1371
|
17171 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
17172 |
+ {
|
mgl@1371
|
17173 |
+ if (!rtx_equal_p(cc_prev_status.mdep.fpvalue, SET_SRC(PATTERN (insn))) )
|
mgl@1371
|
17174 |
+ return "fcmp.d\t%0, %1";
|
mgl@1371
|
17175 |
+ return "";
|
mgl@1371
|
17176 |
+ }
|
mgl@1371
|
17177 |
+ [(set_attr "length" "4")
|
mgl@1371
|
17178 |
+ (set_attr "type" "fcmpd")
|
mgl@1371
|
17179 |
+ (set_attr "cc" "fpcompare")])
|
mgl@1371
|
17180 |
+
|
mgl@1371
|
17181 |
+(define_expand "cmpsf"
|
mgl@1371
|
17182 |
+ [(set (cc0)
|
mgl@1371
|
17183 |
+ (compare:SF
|
mgl@1371
|
17184 |
+ (match_operand:SF 0 "general_operand" "")
|
mgl@1371
|
17185 |
+ (match_operand:SF 1 "general_operand" "")))]
|
mgl@1371
|
17186 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
17187 |
+ "{
|
mgl@1371
|
17188 |
+ rtx tmpreg;
|
mgl@1371
|
17189 |
+ if ( !REG_P(operands[0]) )
|
mgl@1371
|
17190 |
+ operands[0] = force_reg(SFmode, operands[0]);
|
mgl@1371
|
17191 |
+
|
mgl@1371
|
17192 |
+ if ( !REG_P(operands[1]) )
|
mgl@1371
|
17193 |
+ operands[1] = force_reg(SFmode, operands[1]);
|
mgl@1371
|
17194 |
+
|
mgl@1371
|
17195 |
+ avr32_compare_op0 = operands[0];
|
mgl@1371
|
17196 |
+ avr32_compare_op1 = operands[1];
|
mgl@1371
|
17197 |
+
|
mgl@1371
|
17198 |
+ emit_insn(gen_cmpsf_internal(operands[0], operands[1]));
|
mgl@1371
|
17199 |
+
|
mgl@1371
|
17200 |
+ tmpreg = gen_reg_rtx(SImode);
|
mgl@1371
|
17201 |
+ emit_insn(gen_fpcc_to_reg(tmpreg));
|
mgl@1371
|
17202 |
+ emit_insn(gen_reg_to_cc(tmpreg));
|
mgl@1371
|
17203 |
+
|
mgl@1371
|
17204 |
+ DONE;
|
mgl@1371
|
17205 |
+ }"
|
mgl@1371
|
17206 |
+)
|
mgl@1371
|
17207 |
+
|
mgl@1371
|
17208 |
+(define_insn "cmpsf_internal"
|
mgl@1371
|
17209 |
+ [(set (reg:CC FPCC_REGNUM)
|
mgl@1371
|
17210 |
+ (compare:CC
|
mgl@1371
|
17211 |
+ (match_operand:SF 0 "avr32_fp_register_operand" "f")
|
mgl@1371
|
17212 |
+ (match_operand:SF 1 "avr32_fp_register_operand" "f")))]
|
mgl@1371
|
17213 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
17214 |
+ {
|
mgl@1371
|
17215 |
+ if (!rtx_equal_p(cc_prev_status.mdep.fpvalue, SET_SRC(PATTERN (insn))) )
|
mgl@1371
|
17216 |
+ return "fcmp.s\t%0, %1";
|
mgl@1371
|
17217 |
+ return "";
|
mgl@1371
|
17218 |
+ }
|
mgl@1371
|
17219 |
+ [(set_attr "length" "4")
|
mgl@1371
|
17220 |
+ (set_attr "type" "fcmps")
|
mgl@1371
|
17221 |
+ (set_attr "cc" "fpcompare")])
|
mgl@1371
|
17222 |
+
|
mgl@1371
|
17223 |
+(define_insn "fpcc_to_reg"
|
mgl@1371
|
17224 |
+ [(set (match_operand:SI 0 "register_operand" "=r")
|
mgl@1371
|
17225 |
+ (unspec:SI [(reg:CC FPCC_REGNUM)]
|
mgl@1371
|
17226 |
+ UNSPEC_FPCC_TO_REG))]
|
mgl@1371
|
17227 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
17228 |
+ "fmov.s\t%0, fsr"
|
mgl@1371
|
17229 |
+ [(set_attr "length" "4")
|
mgl@1371
|
17230 |
+ (set_attr "type" "fmvcpu")])
|
mgl@1371
|
17231 |
+
|
mgl@1371
|
17232 |
+(define_insn "reg_to_cc"
|
mgl@1371
|
17233 |
+ [(set (cc0)
|
mgl@1371
|
17234 |
+ (unspec:SI [(match_operand:SI 0 "register_operand" "r")]
|
mgl@1371
|
17235 |
+ UNSPEC_REG_TO_CC))]
|
mgl@1371
|
17236 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
17237 |
+ "musfr\t%0"
|
mgl@1371
|
17238 |
+ [(set_attr "length" "2")
|
mgl@1371
|
17239 |
+ (set_attr "type" "alu")
|
mgl@1371
|
17240 |
+ (set_attr "cc" "from_fpcc")])
|
mgl@1371
|
17241 |
+
|
mgl@1371
|
17242 |
+(define_insn "stm_fp"
|
mgl@1371
|
17243 |
+ [(unspec [(match_operand 0 "register_operand" "r")
|
mgl@1371
|
17244 |
+ (match_operand 1 "const_int_operand" "")
|
mgl@1371
|
17245 |
+ (match_operand 2 "const_int_operand" "")]
|
mgl@1371
|
17246 |
+ UNSPEC_STMFP)]
|
mgl@1371
|
17247 |
+ "TARGET_HARD_FLOAT"
|
mgl@1371
|
17248 |
+ {
|
mgl@1371
|
17249 |
+ int cop_reglist = INTVAL(operands[1]);
|
mgl@1371
|
17250 |
+
|
mgl@1371
|
17251 |
+ if (INTVAL(operands[2]) != 0)
|
mgl@1371
|
17252 |
+ return "stcm.w\tcp0, --%0, %C1";
|
mgl@1371
|
17253 |
+ else
|
mgl@1371
|
17254 |
+ return "stcm.w\tcp0, %0, %C1";
|
mgl@1371
|
17255 |
+
|
mgl@1371
|
17256 |
+ if ( cop_reglist & ~0xff ){
|
mgl@1371
|
17257 |
+ operands[1] = GEN_INT(cop_reglist & ~0xff);
|
mgl@1371
|
17258 |
+ if (INTVAL(operands[2]) != 0)
|
mgl@1371
|
17259 |
+ return "stcm.d\tcp0, --%0, %D1";
|
mgl@1371
|
17260 |
+ else
|
mgl@1371
|
17261 |
+ return "stcm.d\tcp0, %0, %D1";
|
mgl@1371
|
17262 |
+ }
|
mgl@1371
|
17263 |
+ }
|
mgl@1371
|
17264 |
+ [(set_attr "type" "fstm")
|
mgl@1371
|
17265 |
+ (set_attr "length" "4")
|
mgl@1371
|
17266 |
+ (set_attr "cc" "none")])
|
mgl@1371
|
17267 |
--- /dev/null
|
mgl@1371
|
17268 |
+++ b/gcc/config/avr32/lib1funcs.S
|
mgl@1371
|
17269 |
@@ -0,0 +1,2874 @@
|
mgl@1371
|
17270 |
+/* Macro for moving immediate value to register. */
|
mgl@1371
|
17271 |
+.macro mov_imm reg, imm
|
mgl@1371
|
17272 |
+.if (((\imm & 0xfffff) == \imm) || ((\imm | 0xfff00000) == \imm))
|
mgl@1371
|
17273 |
+ mov \reg, \imm
|
mgl@1371
|
17274 |
+#if __AVR32_UC__ >= 2
|
mgl@1371
|
17275 |
+.elseif ((\imm & 0xffff) == 0)
|
mgl@1371
|
17276 |
+ movh \reg, hi(\imm)
|
mgl@1371
|
17277 |
+
|
mgl@1371
|
17278 |
+#endif
|
mgl@1371
|
17279 |
+.else
|
mgl@1371
|
17280 |
+ mov \reg, lo(\imm)
|
mgl@1371
|
17281 |
+ orh \reg, hi(\imm)
|
mgl@1371
|
17282 |
+.endif
|
mgl@1371
|
17283 |
+.endm
|
mgl@1371
|
17284 |
+
|
mgl@1371
|
17285 |
+
|
mgl@1371
|
17286 |
+
|
mgl@1371
|
17287 |
+/* Adjust the unpacked double number if it is a subnormal number.
|
mgl@1371
|
17288 |
+ The exponent and mantissa pair are stored
|
mgl@1371
|
17289 |
+ in [mant_hi,mant_lo] and [exp]. A register with the correct sign bit in
|
mgl@1371
|
17290 |
+ the MSB is passed in [sign]. Needs two scratch
|
mgl@1371
|
17291 |
+ registers [scratch1] and [scratch2]. An adjusted and packed double float
|
mgl@1371
|
17292 |
+ is present in [mant_hi,mant_lo] after macro has executed */
|
mgl@1371
|
17293 |
+.macro adjust_subnormal_df exp, mant_lo, mant_hi, sign, scratch1, scratch2
|
mgl@1371
|
17294 |
+ /* We have an exponent which is <=0 indicating a subnormal number
|
mgl@1371
|
17295 |
+ As it should be stored as if the exponent was 1 (although the
|
mgl@1371
|
17296 |
+ exponent field is all zeros to indicate a subnormal number)
|
mgl@1371
|
17297 |
+ we have to shift down the mantissa to its correct position. */
|
mgl@1371
|
17298 |
+ neg \exp
|
mgl@1371
|
17299 |
+ sub \exp,-1 /* amount to shift down */
|
mgl@1371
|
17300 |
+ cp.w \exp,54
|
mgl@1371
|
17301 |
+ brlo 50f /* if more than 53 shift steps, the
|
mgl@1371
|
17302 |
+ entire mantissa will disappear
|
mgl@1371
|
17303 |
+ without any rounding to occur */
|
mgl@1371
|
17304 |
+ mov \mant_hi, 0
|
mgl@1371
|
17305 |
+ mov \mant_lo, 0
|
mgl@1371
|
17306 |
+ rjmp 52f
|
mgl@1371
|
17307 |
+50:
|
mgl@1371
|
17308 |
+ sub \exp,-10 /* do the shift to position the
|
mgl@1371
|
17309 |
+ mantissa at the same time
|
mgl@1371
|
17310 |
+ note! this does not include the
|
mgl@1371
|
17311 |
+ final 1 step shift to add the sign */
|
mgl@1371
|
17312 |
+
|
mgl@1371
|
17313 |
+ /* when shifting, save all shifted out bits in [scratch2]. we may need to
|
mgl@1371
|
17314 |
+ look at them to make correct rounding. */
|
mgl@1371
|
17315 |
+
|
mgl@1371
|
17316 |
+ rsub \scratch1,\exp,32 /* get inverted shift count */
|
mgl@1371
|
17317 |
+ cp.w \exp,32 /* handle shifts >= 32 separately */
|
mgl@1371
|
17318 |
+ brhs 51f
|
mgl@1371
|
17319 |
+
|
mgl@1371
|
17320 |
+ /* small (<32) shift amount, both words are part of the shift */
|
mgl@1371
|
17321 |
+ lsl \scratch2,\mant_lo,\scratch1 /* save bits to shift out from lsw*/
|
mgl@1371
|
17322 |
+ lsl \scratch1,\mant_hi,\scratch1 /* get bits from msw destined for lsw*/
|
mgl@1371
|
17323 |
+ lsr \mant_lo,\mant_lo,\exp /* shift down lsw */
|
mgl@1371
|
17324 |
+ lsr \mant_hi,\mant_hi,\exp /* shift down msw */
|
mgl@1371
|
17325 |
+ or \mant_hi,\scratch1 /* add bits from msw with prepared lsw */
|
mgl@1371
|
17326 |
+ rjmp 50f
|
mgl@1371
|
17327 |
+
|
mgl@1371
|
17328 |
+ /* large (>=32) shift amount, only lsw will have bits left after shift.
|
mgl@1371
|
17329 |
+ note that shift operations will use ((shift count) mod 32) so
|
mgl@1371
|
17330 |
+ we do not need to subtract 32 from shift count. */
|
mgl@1371
|
17331 |
+51:
|
mgl@1371
|
17332 |
+ lsl \scratch2,\mant_hi,\scratch1 /* save bits to shift out from msw */
|
mgl@1371
|
17333 |
+ or \scratch2,\mant_lo /* also save all bits from lsw */
|
mgl@1371
|
17334 |
+ mov \mant_lo,\mant_hi /* msw -> lsw (i.e. "shift 32 first") */
|
mgl@1371
|
17335 |
+ mov \mant_hi,0 /* clear msw */
|
mgl@1371
|
17336 |
+ lsr \mant_lo,\mant_lo,\exp /* make rest of shift inside lsw */
|
mgl@1371
|
17337 |
+
|
mgl@1371
|
17338 |
+50:
|
mgl@1371
|
17339 |
+ /* result is almost ready to return, except that least significant bit
|
mgl@1371
|
17340 |
+ and the part we already shifted out may cause the result to be
|
mgl@1371
|
17341 |
+ rounded */
|
mgl@1371
|
17342 |
+ bld \mant_lo,0 /* get bit to be shifted out */
|
mgl@1371
|
17343 |
+ brcc 51f /* if bit was 0, no rounding */
|
mgl@1371
|
17344 |
+
|
mgl@1371
|
17345 |
+ /* msb of part to remove is 1, so rounding depends on rest of bits */
|
mgl@1371
|
17346 |
+ tst \scratch2,\scratch2 /* get shifted out tail */
|
mgl@1371
|
17347 |
+ brne 50f /* if rest > 0, do round */
|
mgl@1371
|
17348 |
+ bld \mant_lo,1 /* we have to look at lsb in result */
|
mgl@1371
|
17349 |
+ brcc 51f /* if lsb is 0, don't round */
|
mgl@1371
|
17350 |
+
|
mgl@1371
|
17351 |
+50:
|
mgl@1371
|
17352 |
+ /* subnormal result requires rounding
|
mgl@1371
|
17353 |
+ rounding may cause subnormal to become smallest normal number
|
mgl@1371
|
17354 |
+ luckily, smallest normal number has exactly the representation
|
mgl@1371
|
17355 |
+ we got by rippling a one bit up from mantissa into exponent field. */
|
mgl@1371
|
17356 |
+ sub \mant_lo,-1
|
mgl@1371
|
17357 |
+ subcc \mant_hi,-1
|
mgl@1371
|
17358 |
+
|
mgl@1371
|
17359 |
+51:
|
mgl@1371
|
17360 |
+ /* shift and return packed double with correct sign */
|
mgl@1371
|
17361 |
+ rol \sign
|
mgl@1371
|
17362 |
+ ror \mant_hi
|
mgl@1371
|
17363 |
+ ror \mant_lo
|
mgl@1371
|
17364 |
+52:
|
mgl@1371
|
17365 |
+.endm
|
mgl@1371
|
17366 |
+
|
mgl@1371
|
17367 |
+
|
mgl@1371
|
17368 |
+/* Adjust subnormal single float number with exponent [exp]
|
mgl@1371
|
17369 |
+ and mantissa [mant] and round. */
|
mgl@1371
|
17370 |
+.macro adjust_subnormal_sf sf, exp, mant, sign, scratch
|
mgl@1371
|
17371 |
+ /* subnormal number */
|
mgl@1371
|
17372 |
+ rsub \exp,\exp, 1 /* shift amount */
|
mgl@1371
|
17373 |
+ cp.w \exp, 25
|
mgl@1371
|
17374 |
+ movhs \mant, 0
|
mgl@1371
|
17375 |
+ brhs 90f /* Return zero */
|
mgl@1371
|
17376 |
+ rsub \scratch, \exp, 32
|
mgl@1371
|
17377 |
+ lsl \scratch, \mant,\scratch/* Check if there are any bits set
|
mgl@1371
|
17378 |
+ in the bits discarded in the mantissa */
|
mgl@1371
|
17379 |
+ srne \scratch /* If so set the lsb of the shifted mantissa */
|
mgl@1371
|
17380 |
+ lsr \mant,\mant,\exp /* Shift the mantissa */
|
mgl@1371
|
17381 |
+ or \mant, \scratch /* Round lsb if any bits were shifted out */
|
mgl@1371
|
17382 |
+ /* Rounding : For explaination, see round_sf. */
|
mgl@1371
|
17383 |
+ mov \scratch, 0x7f /* Set rounding constant */
|
mgl@1371
|
17384 |
+ bld \mant, 8
|
mgl@1371
|
17385 |
+ subeq \scratch, -1 /* For odd numbers use rounding constant 0x80 */
|
mgl@1371
|
17386 |
+ add \mant, \scratch /* Add rounding constant to mantissa */
|
mgl@1371
|
17387 |
+ /* We can't overflow because mantissa is at least shifted one position
|
mgl@1371
|
17388 |
+ to the right so the implicit bit is zero. We can however get the implicit
|
mgl@1371
|
17389 |
+ bit set after rounding which means that we have the lowest normal number
|
mgl@1371
|
17390 |
+ but this is ok since this bit has the same position as the LSB of the
|
mgl@1371
|
17391 |
+ exponent */
|
mgl@1371
|
17392 |
+ lsr \sf, \mant, 7
|
mgl@1371
|
17393 |
+ /* Rotate in sign */
|
mgl@1371
|
17394 |
+ lsl \sign, 1
|
mgl@1371
|
17395 |
+ ror \sf
|
mgl@1371
|
17396 |
+90:
|
mgl@1371
|
17397 |
+.endm
|
mgl@1371
|
17398 |
+
|
mgl@1371
|
17399 |
+
|
mgl@1371
|
17400 |
+/* Round the unpacked df number with exponent [exp] and
|
mgl@1371
|
17401 |
+ mantissa [mant_hi, mant_lo]. Uses scratch register
|
mgl@1371
|
17402 |
+ [scratch] */
|
mgl@1371
|
17403 |
+.macro round_df exp, mant_lo, mant_hi, scratch
|
mgl@1371
|
17404 |
+ mov \scratch, 0x3ff /* Rounding constant */
|
mgl@1371
|
17405 |
+ bld \mant_lo,11 /* Check if lsb in the final result is
|
mgl@1371
|
17406 |
+ set */
|
mgl@1371
|
17407 |
+ subeq \scratch, -1 /* Adjust rounding constant to 0x400
|
mgl@1371
|
17408 |
+ if rounding 0.5 upwards */
|
mgl@1371
|
17409 |
+ add \mant_lo, \scratch /* Round */
|
mgl@1371
|
17410 |
+ acr \mant_hi /* If overflowing we know that
|
mgl@1371
|
17411 |
+ we have all zeros in the bits not
|
mgl@1371
|
17412 |
+ scaled out so we can leave them
|
mgl@1371
|
17413 |
+ but we must increase the exponent with
|
mgl@1371
|
17414 |
+ two since we had an implicit bit
|
mgl@1371
|
17415 |
+ which is lost + the extra overflow bit */
|
mgl@1371
|
17416 |
+ subcs \exp, -2 /* Update exponent */
|
mgl@1371
|
17417 |
+.endm
|
mgl@1371
|
17418 |
+
|
mgl@1371
|
17419 |
+/* Round single float number stored in [mant] and [exp] */
|
mgl@1371
|
17420 |
+.macro round_sf exp, mant, scratch
|
mgl@1371
|
17421 |
+ /* Round:
|
mgl@1371
|
17422 |
+ For 0.5 we round to nearest even integer
|
mgl@1371
|
17423 |
+ for all other cases we round to nearest integer.
|
mgl@1371
|
17424 |
+ This means that if the digit left of the "point" (.)
|
mgl@1371
|
17425 |
+ is 1 we can add 0x80 to the mantissa since the
|
mgl@1371
|
17426 |
+ corner case 0x180 will round up to 0x200. If the
|
mgl@1371
|
17427 |
+ digit left of the "point" is 0 we will have to
|
mgl@1371
|
17428 |
+ add 0x7f since this will give 0xff and hence a
|
mgl@1371
|
17429 |
+ truncation/rounding downwards for the corner
|
mgl@1371
|
17430 |
+ case when the 9 lowest bits are 0x080 */
|
mgl@1371
|
17431 |
+ mov \scratch, 0x7f /* Set rounding constant */
|
mgl@1371
|
17432 |
+ /* Check if the mantissa is even or odd */
|
mgl@1371
|
17433 |
+ bld \mant, 8
|
mgl@1371
|
17434 |
+ subeq \scratch, -1 /* Rounding constant should be 0x80 */
|
mgl@1371
|
17435 |
+ add \mant, \scratch
|
mgl@1371
|
17436 |
+ subcs \exp, -2 /* Adjust exponent if we overflowed */
|
mgl@1371
|
17437 |
+.endm
|
mgl@1371
|
17438 |
+
|
mgl@1371
|
17439 |
+
|
mgl@1371
|
17440 |
+
|
mgl@1371
|
17441 |
+/* Pack a single float number stored in [mant] and [exp]
|
mgl@1371
|
17442 |
+ into a single float number in [sf] */
|
mgl@1371
|
17443 |
+.macro pack_sf sf, exp, mant
|
mgl@1371
|
17444 |
+ bld \mant,31 /* implicit bit to z */
|
mgl@1371
|
17445 |
+ subne \exp,1 /* if subnormal (implicit bit 0)
|
mgl@1371
|
17446 |
+ adjust exponent to storage format */
|
mgl@1371
|
17447 |
+
|
mgl@1371
|
17448 |
+ lsr \sf, \mant, 7
|
mgl@1371
|
17449 |
+ bfins \sf, \exp, 24, 8
|
mgl@1371
|
17450 |
+.endm
|
mgl@1371
|
17451 |
+
|
mgl@1371
|
17452 |
+/* Pack exponent [exp] and mantissa [mant_hi, mant_lo]
|
mgl@1371
|
17453 |
+ into [df_hi, df_lo]. [df_hi] is shifted
|
mgl@1371
|
17454 |
+ one bit up so the sign bit can be shifted into it */
|
mgl@1371
|
17455 |
+
|
mgl@1371
|
17456 |
+.macro pack_df exp, mant_lo, mant_hi, df_lo, df_hi
|
mgl@1371
|
17457 |
+ bld \mant_hi,31 /* implicit bit to z */
|
mgl@1371
|
17458 |
+ subne \exp,1 /* if subnormal (implicit bit 0)
|
mgl@1371
|
17459 |
+ adjust exponent to storage format */
|
mgl@1371
|
17460 |
+
|
mgl@1371
|
17461 |
+ lsr \mant_lo,11 /* shift back lsw */
|
mgl@1371
|
17462 |
+ or \df_lo,\mant_lo,\mant_hi<<21 /* combine with low bits from msw */
|
mgl@1371
|
17463 |
+ lsl \mant_hi,1 /* get rid of implicit bit */
|
mgl@1371
|
17464 |
+ lsr \mant_hi,11 /* shift back msw except for one step*/
|
mgl@1371
|
17465 |
+ or \df_hi,\mant_hi,\exp<<21 /* combine msw with exponent */
|
mgl@1371
|
17466 |
+.endm
|
mgl@1371
|
17467 |
+
|
mgl@1371
|
17468 |
+/* Normalize single float number stored in [mant] and [exp]
|
mgl@1371
|
17469 |
+ using scratch register [scratch] */
|
mgl@1371
|
17470 |
+.macro normalize_sf exp, mant, scratch
|
mgl@1371
|
17471 |
+ /* Adjust exponent and mantissa */
|
mgl@1371
|
17472 |
+ clz \scratch, \mant
|
mgl@1371
|
17473 |
+ sub \exp, \scratch
|
mgl@1371
|
17474 |
+ lsl \mant, \mant, \scratch
|
mgl@1371
|
17475 |
+.endm
|
mgl@1371
|
17476 |
+
|
mgl@1371
|
17477 |
+/* Normalize the exponent and mantissa pair stored
|
mgl@1371
|
17478 |
+ in [mant_hi,mant_lo] and [exp]. Needs two scratch
|
mgl@1371
|
17479 |
+ registers [scratch1] and [scratch2]. */
|
mgl@1371
|
17480 |
+.macro normalize_df exp, mant_lo, mant_hi, scratch1, scratch2
|
mgl@1371
|
17481 |
+ clz \scratch1,\mant_hi /* Check if we have zeros in high bits */
|
mgl@1371
|
17482 |
+ breq 80f /* No need for scaling if no zeros in high bits */
|
mgl@1371
|
17483 |
+ brcs 81f /* Check for all zeros */
|
mgl@1371
|
17484 |
+
|
mgl@1371
|
17485 |
+ /* shift amount is smaller than 32, and involves both msw and lsw*/
|
mgl@1371
|
17486 |
+ rsub \scratch2,\scratch1,32 /* shift mantissa */
|
mgl@1371
|
17487 |
+ lsl \mant_hi,\mant_hi,\scratch1
|
mgl@1371
|
17488 |
+ lsr \scratch2,\mant_lo,\scratch2
|
mgl@1371
|
17489 |
+ or \mant_hi,\scratch2
|
mgl@1371
|
17490 |
+ lsl \mant_lo,\mant_lo,\scratch1
|
mgl@1371
|
17491 |
+ sub \exp,\scratch1 /* adjust exponent */
|
mgl@1371
|
17492 |
+ rjmp 80f /* Finished */
|
mgl@1371
|
17493 |
+81:
|
mgl@1371
|
17494 |
+ /* shift amount is greater than 32 */
|
mgl@1371
|
17495 |
+ clz \scratch1,\mant_lo /* shift mantissa */
|
mgl@1371
|
17496 |
+ movcs \scratch1, 0
|
mgl@1371
|
17497 |
+ subcc \scratch1,-32
|
mgl@1371
|
17498 |
+ lsl \mant_hi,\mant_lo,\scratch1
|
mgl@1371
|
17499 |
+ mov \mant_lo,0
|
mgl@1371
|
17500 |
+ sub \exp,\scratch1 /* adjust exponent */
|
mgl@1371
|
17501 |
+80:
|
mgl@1371
|
17502 |
+.endm
|
mgl@1371
|
17503 |
+
|
mgl@1371
|
17504 |
+
|
mgl@1371
|
17505 |
+/* Fast but approximate multiply of two 64-bit numbers to give a 64 bit result.
|
mgl@1371
|
17506 |
+ The multiplication of [al]x[bl] is discarded.
|
mgl@1371
|
17507 |
+ Operands in [ah], [al], [bh], [bl].
|
mgl@1371
|
17508 |
+ Scratch registers in [sh], [sl].
|
mgl@1371
|
17509 |
+ Returns results in registers [rh], [rl].*/
|
mgl@1371
|
17510 |
+.macro mul_approx_df ah, al, bh, bl, rh, rl, sh, sl
|
mgl@1371
|
17511 |
+ mulu.d \sl, \ah, \bl
|
mgl@1371
|
17512 |
+ macu.d \sl, \al, \bh
|
mgl@1371
|
17513 |
+ mulu.d \rl, \ah, \bh
|
mgl@1371
|
17514 |
+ add \rl, \sh
|
mgl@1371
|
17515 |
+ acr \rh
|
mgl@1371
|
17516 |
+.endm
|
mgl@1371
|
17517 |
+
|
mgl@1371
|
17518 |
+
|
mgl@1371
|
17519 |
+
|
mgl@1371
|
17520 |
+#if defined(L_avr32_f64_mul) || defined(L_avr32_f64_mul_fast)
|
mgl@1371
|
17521 |
+ .align 2
|
mgl@1371
|
17522 |
+#if defined(L_avr32_f64_mul)
|
mgl@1371
|
17523 |
+ .global __avr32_f64_mul
|
mgl@1371
|
17524 |
+ .type __avr32_f64_mul,@function
|
mgl@1371
|
17525 |
+__avr32_f64_mul:
|
mgl@1371
|
17526 |
+#else
|
mgl@1371
|
17527 |
+ .global __avr32_f64_mul_fast
|
mgl@1371
|
17528 |
+ .type __avr32_f64_mul_fast,@function
|
mgl@1371
|
17529 |
+__avr32_f64_mul_fast:
|
mgl@1371
|
17530 |
+#endif
|
mgl@1371
|
17531 |
+ or r12, r10, r11 << 1
|
mgl@1371
|
17532 |
+ breq __avr32_f64_mul_op1_zero
|
mgl@1371
|
17533 |
+
|
mgl@1371
|
17534 |
+#if defined(L_avr32_f64_mul)
|
mgl@1371
|
17535 |
+ pushm r4-r7, lr
|
mgl@1371
|
17536 |
+#else
|
mgl@1371
|
17537 |
+ stm --sp, r5,r6,r7,lr
|
mgl@1371
|
17538 |
+#endif
|
mgl@1371
|
17539 |
+
|
mgl@1371
|
17540 |
+#define AVR32_F64_MUL_OP1_INT_BITS 1
|
mgl@1371
|
17541 |
+#define AVR32_F64_MUL_OP2_INT_BITS 10
|
mgl@1371
|
17542 |
+#define AVR32_F64_MUL_RES_INT_BITS 11
|
mgl@1371
|
17543 |
+
|
mgl@1371
|
17544 |
+ /* op1 in {r11,r10}*/
|
mgl@1371
|
17545 |
+ /* op2 in {r9,r8}*/
|
mgl@1371
|
17546 |
+ eor lr, r11, r9 /* MSB(lr) = Sign(op1) ^ Sign(op2) */
|
mgl@1371
|
17547 |
+
|
mgl@1371
|
17548 |
+ /* Unpack op1 to 1.63 format*/
|
mgl@1371
|
17549 |
+ /* exp: r7 */
|
mgl@1371
|
17550 |
+ /* sf: r11, r10 */
|
mgl@1371
|
17551 |
+ bfextu r7, r11, 20, 11 /* Extract exponent */
|
mgl@1371
|
17552 |
+
|
mgl@1371
|
17553 |
+ mov r5, 1
|
mgl@1371
|
17554 |
+
|
mgl@1371
|
17555 |
+ /* Check if normalization is needed */
|
mgl@1371
|
17556 |
+ breq __avr32_f64_mul_op1_subnormal /*If number is subnormal, normalize it */
|
mgl@1371
|
17557 |
+
|
mgl@1371
|
17558 |
+ lsl r11, (12-AVR32_F64_MUL_OP1_INT_BITS-1) /* Extract mantissa, leave room for implicit bit */
|
mgl@1371
|
17559 |
+ or r11, r11, r10>>(32-(12-AVR32_F64_MUL_OP1_INT_BITS-1))
|
mgl@1371
|
17560 |
+ lsl r10, (12-AVR32_F64_MUL_OP1_INT_BITS-1)
|
mgl@1371
|
17561 |
+ bfins r11, r5, 32 - (1 + AVR32_F64_MUL_OP1_INT_BITS), 1 + AVR32_F64_MUL_OP1_INT_BITS /* Insert implicit bit */
|
mgl@1371
|
17562 |
+
|
mgl@1371
|
17563 |
+
|
mgl@1371
|
17564 |
+22:
|
mgl@1371
|
17565 |
+ /* Unpack op2 to 10.54 format */
|
mgl@1371
|
17566 |
+ /* exp: r6 */
|
mgl@1371
|
17567 |
+ /* sf: r9, r8 */
|
mgl@1371
|
17568 |
+ bfextu r6, r9, 20, 11 /* Extract exponent */
|
mgl@1371
|
17569 |
+
|
mgl@1371
|
17570 |
+ /* Check if normalization is needed */
|
mgl@1371
|
17571 |
+ breq __avr32_f64_mul_op2_subnormal /*If number is subnormal, normalize it */
|
mgl@1371
|
17572 |
+
|
mgl@1371
|
17573 |
+ lsl r8, 1 /* Extract mantissa, leave room for implicit bit */
|
mgl@1371
|
17574 |
+ rol r9
|
mgl@1371
|
17575 |
+ bfins r9, r5, 32 - (1 + AVR32_F64_MUL_OP2_INT_BITS), 1 + AVR32_F64_MUL_OP2_INT_BITS /* Insert implicit bit */
|
mgl@1371
|
17576 |
+
|
mgl@1371
|
17577 |
+23:
|
mgl@1371
|
17578 |
+
|
mgl@1371
|
17579 |
+ /* Check if any operands are NaN or INF */
|
mgl@1371
|
17580 |
+ cp r7, 0x7ff
|
mgl@1371
|
17581 |
+ breq __avr32_f64_mul_op_nan_or_inf /* Check op1 for NaN or Inf */
|
mgl@1371
|
17582 |
+ cp r6, 0x7ff
|
mgl@1371
|
17583 |
+ breq __avr32_f64_mul_op_nan_or_inf /* Check op2 for NaN or Inf */
|
mgl@1371
|
17584 |
+
|
mgl@1371
|
17585 |
+
|
mgl@1371
|
17586 |
+ /* Calculate new exponent in r12*/
|
mgl@1371
|
17587 |
+ add r12, r7, r6
|
mgl@1371
|
17588 |
+ sub r12, (1023-1)
|
mgl@1371
|
17589 |
+
|
mgl@1371
|
17590 |
+#if defined(L_avr32_f64_mul)
|
mgl@1371
|
17591 |
+ /* Do the multiplication.
|
mgl@1371
|
17592 |
+ Place result in [r11, r10, r7, r6]. The result is in 11.117 format. */
|
mgl@1371
|
17593 |
+ mulu.d r4, r11, r8
|
mgl@1371
|
17594 |
+ macu.d r4, r10, r9
|
mgl@1371
|
17595 |
+ mulu.d r6, r10, r8
|
mgl@1371
|
17596 |
+ mulu.d r10, r11, r9
|
mgl@1371
|
17597 |
+ add r7, r4
|
mgl@1371
|
17598 |
+ adc r10, r10, r5
|
mgl@1371
|
17599 |
+ acr r11
|
mgl@1371
|
17600 |
+#else
|
mgl@1371
|
17601 |
+ /* Do the multiplication using approximate calculation. discard the al x bl
|
mgl@1371
|
17602 |
+ calculation.
|
mgl@1371
|
17603 |
+ Place result in [r11, r10, r7]. The result is in 11.85 format. */
|
mgl@1371
|
17604 |
+
|
mgl@1371
|
17605 |
+ /* Do the multiplication using approximate calculation.
|
mgl@1371
|
17606 |
+ Place result in r11, r10. Use r7, r6 as scratch registers */
|
mgl@1371
|
17607 |
+ mulu.d r6, r11, r8
|
mgl@1371
|
17608 |
+ macu.d r6, r10, r9
|
mgl@1371
|
17609 |
+ mulu.d r10, r11, r9
|
mgl@1371
|
17610 |
+ add r10, r7
|
mgl@1371
|
17611 |
+ acr r11
|
mgl@1371
|
17612 |
+#endif
|
mgl@1371
|
17613 |
+ /* Adjust exponent and mantissa */
|
mgl@1371
|
17614 |
+ /* [r12]:exp, [r11, r10]:mant [r7, r6]:sticky bits */
|
mgl@1371
|
17615 |
+ /* Mantissa may be of the format 00000000000.0xxx or 00000000000.1xxx. */
|
mgl@1371
|
17616 |
+ /* In the first case, shift one pos to left.*/
|
mgl@1371
|
17617 |
+ bld r11, 32-AVR32_F64_MUL_RES_INT_BITS-1
|
mgl@1371
|
17618 |
+ breq 0f
|
mgl@1371
|
17619 |
+ lsl r7, 1
|
mgl@1371
|
17620 |
+ rol r10
|
mgl@1371
|
17621 |
+ rol r11
|
mgl@1371
|
17622 |
+ sub r12, 1
|
mgl@1371
|
17623 |
+0:
|
mgl@1371
|
17624 |
+ cp r12, 0
|
mgl@1371
|
17625 |
+ brle __avr32_f64_mul_res_subnormal /*Result was subnormal.*/
|
mgl@1371
|
17626 |
+
|
mgl@1371
|
17627 |
+ /* Check for Inf. */
|
mgl@1371
|
17628 |
+ cp.w r12, 0x7ff
|
mgl@1371
|
17629 |
+ brge __avr32_f64_mul_res_inf
|
mgl@1371
|
17630 |
+
|
mgl@1371
|
17631 |
+ /* Insert exponent. */
|
mgl@1371
|
17632 |
+ bfins r11, r12, 20, 11
|
mgl@1371
|
17633 |
+
|
mgl@1371
|
17634 |
+ /* Result was not subnormal. Perform rounding. */
|
mgl@1371
|
17635 |
+ /* For the fast version we discard the sticky bits and always round
|
mgl@1371
|
17636 |
+ the halfwaycase up. */
|
mgl@1371
|
17637 |
+24:
|
mgl@1371
|
17638 |
+#if defined(L_avr32_f64_mul)
|
mgl@1371
|
17639 |
+ or r6, r6, r10 << 31 /* Or in parity bit into stickybits */
|
mgl@1371
|
17640 |
+ or r7, r7, r6 >> 1 /* Or together sticky and still make the msb
|
mgl@1371
|
17641 |
+ of r7 represent the halfway bit. */
|
mgl@1371
|
17642 |
+ eorh r7, 0x8000 /* Toggle halfway bit. */
|
mgl@1371
|
17643 |
+ /* We should now round up by adding one for the following cases:
|
mgl@1371
|
17644 |
+
|
mgl@1371
|
17645 |
+ halfway sticky|parity round-up
|
mgl@1371
|
17646 |
+ 0 x no
|
mgl@1371
|
17647 |
+ 1 0 no
|
mgl@1371
|
17648 |
+ 1 1 yes
|
mgl@1371
|
17649 |
+
|
mgl@1371
|
17650 |
+ Since we have inverted the halfway bit we can use the satu instruction
|
mgl@1371
|
17651 |
+ by saturating to 1 bit to implement this.
|
mgl@1371
|
17652 |
+ */
|
mgl@1371
|
17653 |
+ satu r7 >> 0, 1
|
mgl@1371
|
17654 |
+#else
|
mgl@1371
|
17655 |
+ lsr r7, 31
|
mgl@1371
|
17656 |
+#endif
|
mgl@1371
|
17657 |
+ add r10, r7
|
mgl@1371
|
17658 |
+ acr r11
|
mgl@1371
|
17659 |
+
|
mgl@1371
|
17660 |
+ /* Insert sign bit*/
|
mgl@1371
|
17661 |
+ bld lr, 31
|
mgl@1371
|
17662 |
+ bst r11, 31
|
mgl@1371
|
17663 |
+
|
mgl@1371
|
17664 |
+ /* Return result in [r11,r10] */
|
mgl@1371
|
17665 |
+#if defined(L_avr32_f64_mul)
|
mgl@1371
|
17666 |
+ popm r4-r7, pc
|
mgl@1371
|
17667 |
+#else
|
mgl@1371
|
17668 |
+ ldm sp++, r5, r6, r7,pc
|
mgl@1371
|
17669 |
+#endif
|
mgl@1371
|
17670 |
+
|
mgl@1371
|
17671 |
+
|
mgl@1371
|
17672 |
+__avr32_f64_mul_op1_subnormal:
|
mgl@1371
|
17673 |
+ andh r11, 0x000f /* Remove sign bit and exponent */
|
mgl@1371
|
17674 |
+ clz r12, r10 /* Count leading zeros in lsw */
|
mgl@1371
|
17675 |
+ clz r6, r11 /* Count leading zeros in msw */
|
mgl@1371
|
17676 |
+ subcs r12, -32 + AVR32_F64_MUL_OP1_INT_BITS
|
mgl@1371
|
17677 |
+ movcs r6, r12
|
mgl@1371
|
17678 |
+ subcc r6, AVR32_F64_MUL_OP1_INT_BITS
|
mgl@1371
|
17679 |
+ cp.w r6, 32
|
mgl@1371
|
17680 |
+ brge 0f
|
mgl@1371
|
17681 |
+
|
mgl@1371
|
17682 |
+ /* shifting involves both msw and lsw*/
|
mgl@1371
|
17683 |
+ rsub r12, r6, 32 /* shift mantissa */
|
mgl@1371
|
17684 |
+ lsl r11, r11, r6
|
mgl@1371
|
17685 |
+ lsr r12, r10, r12
|
mgl@1371
|
17686 |
+ or r11, r12
|
mgl@1371
|
17687 |
+ lsl r10, r10, r6
|
mgl@1371
|
17688 |
+ sub r6, 12-AVR32_F64_MUL_OP1_INT_BITS
|
mgl@1371
|
17689 |
+ sub r7, r6 /* adjust exponent */
|
mgl@1371
|
17690 |
+ rjmp 22b /* Finished */
|
mgl@1371
|
17691 |
+0:
|
mgl@1371
|
17692 |
+ /* msw is zero so only need to consider lsw */
|
mgl@1371
|
17693 |
+ lsl r11, r10, r6
|
mgl@1371
|
17694 |
+ breq __avr32_f64_mul_res_zero
|
mgl@1371
|
17695 |
+ mov r10, 0
|
mgl@1371
|
17696 |
+ sub r6, 12-AVR32_F64_MUL_OP1_INT_BITS
|
mgl@1371
|
17697 |
+ sub r7, r6 /* adjust exponent */
|
mgl@1371
|
17698 |
+ rjmp 22b
|
mgl@1371
|
17699 |
+
|
mgl@1371
|
17700 |
+
|
mgl@1371
|
17701 |
+__avr32_f64_mul_op2_subnormal:
|
mgl@1371
|
17702 |
+ andh r9, 0x000f /* Remove sign bit and exponent */
|
mgl@1371
|
17703 |
+ clz r12, r8 /* Count leading zeros in lsw */
|
mgl@1371
|
17704 |
+ clz r5, r9 /* Count leading zeros in msw */
|
mgl@1371
|
17705 |
+ subcs r12, -32 + AVR32_F64_MUL_OP2_INT_BITS
|
mgl@1371
|
17706 |
+ movcs r5, r12
|
mgl@1371
|
17707 |
+ subcc r5, AVR32_F64_MUL_OP2_INT_BITS
|
mgl@1371
|
17708 |
+ cp.w r5, 32
|
mgl@1371
|
17709 |
+ brge 0f
|
mgl@1371
|
17710 |
+
|
mgl@1371
|
17711 |
+ /* shifting involves both msw and lsw*/
|
mgl@1371
|
17712 |
+ rsub r12, r5, 32 /* shift mantissa */
|
mgl@1371
|
17713 |
+ lsl r9, r9, r5
|
mgl@1371
|
17714 |
+ lsr r12, r8, r12
|
mgl@1371
|
17715 |
+ or r9, r12
|
mgl@1371
|
17716 |
+ lsl r8, r8, r5
|
mgl@1371
|
17717 |
+ sub r5, 12 - AVR32_F64_MUL_OP2_INT_BITS
|
mgl@1371
|
17718 |
+ sub r6, r5 /* adjust exponent */
|
mgl@1371
|
17719 |
+ rjmp 23b /* Finished */
|
mgl@1371
|
17720 |
+0:
|
mgl@1371
|
17721 |
+ /* msw is zero so only need to consider lsw */
|
mgl@1371
|
17722 |
+ lsl r9, r8, r5
|
mgl@1371
|
17723 |
+ breq __avr32_f64_mul_res_zero
|
mgl@1371
|
17724 |
+ mov r8, 0
|
mgl@1371
|
17725 |
+ sub r5, 12 - AVR32_F64_MUL_OP2_INT_BITS
|
mgl@1371
|
17726 |
+ sub r6, r5 /* adjust exponent */
|
mgl@1371
|
17727 |
+ rjmp 23b
|
mgl@1371
|
17728 |
+
|
mgl@1371
|
17729 |
+
|
mgl@1371
|
17730 |
+__avr32_f64_mul_op_nan_or_inf:
|
mgl@1371
|
17731 |
+ /* Same code for OP1 and OP2*/
|
mgl@1371
|
17732 |
+ /* Since we are here, at least one of the OPs were NaN or INF*/
|
mgl@1371
|
17733 |
+ andh r9, 0x000f /* Remove sign bit and exponent */
|
mgl@1371
|
17734 |
+ andh r11, 0x000f /* Remove sign bit and exponent */
|
mgl@1371
|
17735 |
+ /* Merge the regs in each operand to check for zero*/
|
mgl@1371
|
17736 |
+ or r11, r10 /* op1 */
|
mgl@1371
|
17737 |
+ or r9, r8 /* op2 */
|
mgl@1371
|
17738 |
+ /* Check if op1 is NaN or INF */
|
mgl@1371
|
17739 |
+ cp r7, 0x7ff
|
mgl@1371
|
17740 |
+ brne __avr32_f64_mul_op1_not_naninf
|
mgl@1371
|
17741 |
+ /* op1 was NaN or INF.*/
|
mgl@1371
|
17742 |
+ cp r11, 0
|
mgl@1371
|
17743 |
+ brne __avr32_f64_mul_res_nan /* op1 was NaN. Result will be NaN*/
|
mgl@1371
|
17744 |
+ /*op1 was INF. check if op2 is NaN or INF*/
|
mgl@1371
|
17745 |
+ cp r6, 0x7ff
|
mgl@1371
|
17746 |
+ brne __avr32_f64_mul_res_inf /*op1 was INF, op2 was neither NaN nor INF*/
|
mgl@1371
|
17747 |
+ /* op1 is INF, op2 is either NaN or INF*/
|
mgl@1371
|
17748 |
+ cp r9, 0
|
mgl@1371
|
17749 |
+ breq __avr32_f64_mul_res_inf /*op2 was also INF*/
|
mgl@1371
|
17750 |
+ rjmp __avr32_f64_mul_res_nan /*op2 was NaN*/
|
mgl@1371
|
17751 |
+
|
mgl@1371
|
17752 |
+__avr32_f64_mul_op1_not_naninf:
|
mgl@1371
|
17753 |
+ /* op1 was not NaN nor INF. Then op2 must be NaN or INF*/
|
mgl@1371
|
17754 |
+ cp r9, 0
|
mgl@1371
|
17755 |
+ breq __avr32_f64_mul_res_inf /*op2 was INF, return INF*/
|
mgl@1371
|
17756 |
+ rjmp __avr32_f64_mul_res_nan /*else return NaN*/
|
mgl@1371
|
17757 |
+
|
mgl@1371
|
17758 |
+__avr32_f64_mul_res_subnormal:/* Multiply result was subnormal. */
|
mgl@1371
|
17759 |
+#if defined(L_avr32_f64_mul)
|
mgl@1371
|
17760 |
+ /* Check how much we must scale down the mantissa. */
|
mgl@1371
|
17761 |
+ neg r12
|
mgl@1371
|
17762 |
+ sub r12, -1 /* We do no longer have an implicit bit. */
|
mgl@1371
|
17763 |
+ satu r12 >> 0, 6 /* Saturate shift amount to max 63. */
|
mgl@1371
|
17764 |
+ cp.w r12, 32
|
mgl@1371
|
17765 |
+ brge 0f
|
mgl@1371
|
17766 |
+ /* Shift amount <32 */
|
mgl@1371
|
17767 |
+ rsub r8, r12, 32
|
mgl@1371
|
17768 |
+ or r6, r7
|
mgl@1371
|
17769 |
+ lsr r7, r7, r12
|
mgl@1371
|
17770 |
+ lsl r9, r10, r8
|
mgl@1371
|
17771 |
+ or r7, r9
|
mgl@1371
|
17772 |
+ lsr r10, r10, r12
|
mgl@1371
|
17773 |
+ lsl r9, r11, r8
|
mgl@1371
|
17774 |
+ or r10, r9
|
mgl@1371
|
17775 |
+ lsr r11, r11, r12
|
mgl@1371
|
17776 |
+ rjmp 24b
|
mgl@1371
|
17777 |
+0:
|
mgl@1371
|
17778 |
+ /* Shift amount >=32 */
|
mgl@1371
|
17779 |
+ rsub r8, r12, 32
|
mgl@1371
|
17780 |
+ moveq r9, 0
|
mgl@1371
|
17781 |
+ breq 0f
|
mgl@1371
|
17782 |
+ lsl r9, r11, r8
|
mgl@1371
|
17783 |
+0:
|
mgl@1371
|
17784 |
+ or r6, r7
|
mgl@1371
|
17785 |
+ or r6, r6, r10 << 1
|
mgl@1371
|
17786 |
+ lsr r10, r10, r12
|
mgl@1371
|
17787 |
+ or r7, r9, r10
|
mgl@1371
|
17788 |
+ lsr r10, r11, r12
|
mgl@1371
|
17789 |
+ mov r11, 0
|
mgl@1371
|
17790 |
+ rjmp 24b
|
mgl@1371
|
17791 |
+#else
|
mgl@1371
|
17792 |
+ /* Flush to zero for the fast version. */
|
mgl@1371
|
17793 |
+ mov r11, lr /*Get correct sign*/
|
mgl@1371
|
17794 |
+ andh r11, 0x8000, COH
|
mgl@1371
|
17795 |
+ mov r10, 0
|
mgl@1371
|
17796 |
+ ldm sp++, r5, r6, r7,pc
|
mgl@1371
|
17797 |
+#endif
|
mgl@1371
|
17798 |
+
|
mgl@1371
|
17799 |
+__avr32_f64_mul_res_zero:/* Multiply result is zero. */
|
mgl@1371
|
17800 |
+ mov r11, lr /*Get correct sign*/
|
mgl@1371
|
17801 |
+ andh r11, 0x8000, COH
|
mgl@1371
|
17802 |
+ mov r10, 0
|
mgl@1371
|
17803 |
+#if defined(L_avr32_f64_mul)
|
mgl@1371
|
17804 |
+ popm r4-r7, pc
|
mgl@1371
|
17805 |
+#else
|
mgl@1371
|
17806 |
+ ldm sp++, r5, r6, r7,pc
|
mgl@1371
|
17807 |
+#endif
|
mgl@1371
|
17808 |
+
|
mgl@1371
|
17809 |
+__avr32_f64_mul_res_nan: /* Return NaN. */
|
mgl@1371
|
17810 |
+ mov r11, -1
|
mgl@1371
|
17811 |
+ mov r10, -1
|
mgl@1371
|
17812 |
+#if defined(L_avr32_f64_mul)
|
mgl@1371
|
17813 |
+ popm r4-r7, pc
|
mgl@1371
|
17814 |
+#else
|
mgl@1371
|
17815 |
+ ldm sp++, r5, r6, r7,pc
|
mgl@1371
|
17816 |
+#endif
|
mgl@1371
|
17817 |
+
|
mgl@1371
|
17818 |
+__avr32_f64_mul_res_inf: /* Return INF. */
|
mgl@1371
|
17819 |
+ mov r11, 0xfff00000
|
mgl@1371
|
17820 |
+ bld lr, 31
|
mgl@1371
|
17821 |
+ bst r11, 31
|
mgl@1371
|
17822 |
+ mov r10, 0
|
mgl@1371
|
17823 |
+#if defined(L_avr32_f64_mul)
|
mgl@1371
|
17824 |
+ popm r4-r7, pc
|
mgl@1371
|
17825 |
+#else
|
mgl@1371
|
17826 |
+ ldm sp++, r5, r6, r7,pc
|
mgl@1371
|
17827 |
+#endif
|
mgl@1371
|
17828 |
+
|
mgl@1371
|
17829 |
+__avr32_f64_mul_op1_zero:
|
mgl@1371
|
17830 |
+ /* Get sign */
|
mgl@1371
|
17831 |
+ eor r11, r11, r9
|
mgl@1371
|
17832 |
+ andh r11, 0x8000, COH
|
mgl@1371
|
17833 |
+ /* Check if op2 is Inf or NaN. */
|
mgl@1371
|
17834 |
+ bfextu r12, r9, 20, 11
|
mgl@1371
|
17835 |
+ cp.w r12, 0x7ff
|
mgl@1371
|
17836 |
+ retne r12 /* Return 0.0 */
|
mgl@1371
|
17837 |
+ /* Return NaN */
|
mgl@1371
|
17838 |
+ mov r10, -1
|
mgl@1371
|
17839 |
+ mov r11, -1
|
mgl@1371
|
17840 |
+ ret r12
|
mgl@1371
|
17841 |
+
|
mgl@1371
|
17842 |
+
|
mgl@1371
|
17843 |
+
|
mgl@1371
|
17844 |
+#endif
|
mgl@1371
|
17845 |
+
|
mgl@1371
|
17846 |
+
|
mgl@1371
|
17847 |
+#if defined(L_avr32_f64_addsub) || defined(L_avr32_f64_addsub_fast)
|
mgl@1371
|
17848 |
+ .align 2
|
mgl@1371
|
17849 |
+
|
mgl@1371
|
17850 |
+__avr32_f64_sub_from_add:
|
mgl@1371
|
17851 |
+ /* Switch sign on op2 */
|
mgl@1371
|
17852 |
+ eorh r9, 0x8000
|
mgl@1371
|
17853 |
+
|
mgl@1371
|
17854 |
+#if defined(L_avr32_f64_addsub_fast)
|
mgl@1371
|
17855 |
+ .global __avr32_f64_sub_fast
|
mgl@1371
|
17856 |
+ .type __avr32_f64_sub_fast,@function
|
mgl@1371
|
17857 |
+__avr32_f64_sub_fast:
|
mgl@1371
|
17858 |
+#else
|
mgl@1371
|
17859 |
+ .global __avr32_f64_sub
|
mgl@1371
|
17860 |
+ .type __avr32_f64_sub,@function
|
mgl@1371
|
17861 |
+__avr32_f64_sub:
|
mgl@1371
|
17862 |
+#endif
|
mgl@1371
|
17863 |
+
|
mgl@1371
|
17864 |
+ /* op1 in {r11,r10}*/
|
mgl@1371
|
17865 |
+ /* op2 in {r9,r8}*/
|
mgl@1371
|
17866 |
+
|
mgl@1371
|
17867 |
+#if defined(L_avr32_f64_addsub_fast)
|
mgl@1371
|
17868 |
+ /* If op2 is zero just return op1 */
|
mgl@1371
|
17869 |
+ or r12, r8, r9 << 1
|
mgl@1371
|
17870 |
+ reteq r12
|
mgl@1371
|
17871 |
+#endif
|
mgl@1371
|
17872 |
+
|
mgl@1371
|
17873 |
+ /* Check signs */
|
mgl@1371
|
17874 |
+ eor r12, r11, r9
|
mgl@1371
|
17875 |
+ /* Different signs, use addition. */
|
mgl@1371
|
17876 |
+ brmi __avr32_f64_add_from_sub
|
mgl@1371
|
17877 |
+
|
mgl@1371
|
17878 |
+ stm --sp, r5, r6, r7, lr
|
mgl@1371
|
17879 |
+
|
mgl@1371
|
17880 |
+ /* Get sign of op1 into r12 */
|
mgl@1371
|
17881 |
+ mov r12, r11
|
mgl@1371
|
17882 |
+ andh r12, 0x8000, COH
|
mgl@1371
|
17883 |
+
|
mgl@1371
|
17884 |
+ /* Remove sign from operands */
|
mgl@1371
|
17885 |
+ cbr r11, 31
|
mgl@1371
|
17886 |
+ cbr r9, 31
|
mgl@1371
|
17887 |
+
|
mgl@1371
|
17888 |
+ /* Put the largest number in [r11, r10]
|
mgl@1371
|
17889 |
+ and the smallest number in [r9, r8] */
|
mgl@1371
|
17890 |
+ cp r10, r8
|
mgl@1371
|
17891 |
+ cpc r11, r9
|
mgl@1371
|
17892 |
+ brhs 1f /* Skip swap if operands already correctly ordered*/
|
mgl@1371
|
17893 |
+ /* Operands were not correctly ordered, swap them*/
|
mgl@1371
|
17894 |
+ mov r7, r11
|
mgl@1371
|
17895 |
+ mov r11, r9
|
mgl@1371
|
17896 |
+ mov r9, r7
|
mgl@1371
|
17897 |
+ mov r7, r10
|
mgl@1371
|
17898 |
+ mov r10, r8
|
mgl@1371
|
17899 |
+ mov r8, r7
|
mgl@1371
|
17900 |
+ eorh r12, 0x8000 /* Invert sign in r12*/
|
mgl@1371
|
17901 |
+1:
|
mgl@1371
|
17902 |
+ /* Unpack largest operand - opH */
|
mgl@1371
|
17903 |
+ /* exp: r7 */
|
mgl@1371
|
17904 |
+ /* sf: r11, r10 */
|
mgl@1371
|
17905 |
+ lsr r7, r11, 20 /* Extract exponent */
|
mgl@1371
|
17906 |
+ lsl r11, 11 /* Extract mantissa, leave room for implicit bit */
|
mgl@1371
|
17907 |
+ or r11, r11, r10>>21
|
mgl@1371
|
17908 |
+ lsl r10, 11
|
mgl@1371
|
17909 |
+ sbr r11, 31 /* Insert implicit bit */
|
mgl@1371
|
17910 |
+
|
mgl@1371
|
17911 |
+
|
mgl@1371
|
17912 |
+ /* Unpack smallest operand - opL */
|
mgl@1371
|
17913 |
+ /* exp: r6 */
|
mgl@1371
|
17914 |
+ /* sf: r9, r8 */
|
mgl@1371
|
17915 |
+ lsr r6, r9, 20 /* Extract exponent */
|
mgl@1371
|
17916 |
+ breq __avr32_f64_sub_opL_subnormal /* If either zero or subnormal */
|
mgl@1371
|
17917 |
+ lsl r9, 11 /* Extract mantissa, leave room for implicit bit */
|
mgl@1371
|
17918 |
+ or r9, r9, r8>>21
|
mgl@1371
|
17919 |
+ lsl r8, 11
|
mgl@1371
|
17920 |
+ sbr r9, 31 /* Insert implicit bit */
|
mgl@1371
|
17921 |
+
|
mgl@1371
|
17922 |
+
|
mgl@1371
|
17923 |
+__avr32_f64_sub_opL_subnormal_done:
|
mgl@1371
|
17924 |
+ /* opH is NaN or Inf. */
|
mgl@1371
|
17925 |
+ cp.w r7, 0x7ff
|
mgl@1371
|
17926 |
+ breq __avr32_f64_sub_opH_nan_or_inf
|
mgl@1371
|
17927 |
+
|
mgl@1371
|
17928 |
+ /* Get shift amount to scale mantissa of op2. */
|
mgl@1371
|
17929 |
+ rsub r6, r7
|
mgl@1371
|
17930 |
+ breq __avr32_f64_sub_shift_done /* No need to shift, exponents are equal*/
|
mgl@1371
|
17931 |
+
|
mgl@1371
|
17932 |
+ /* Scale mantissa [r9, r8] with amount [r6].
|
mgl@1371
|
17933 |
+ Uses scratch registers [r5] and [lr].
|
mgl@1371
|
17934 |
+ In IEEE mode:Must not forget the sticky bits we intend to shift out. */
|
mgl@1371
|
17935 |
+
|
mgl@1371
|
17936 |
+ rsub r5,r6,32 /* get (32 - shift count)
|
mgl@1371
|
17937 |
+ (if shift count > 32 we get a
|
mgl@1371
|
17938 |
+ negative value, but that will
|
mgl@1371
|
17939 |
+ work as well in the code below.) */
|
mgl@1371
|
17940 |
+
|
mgl@1371
|
17941 |
+ cp.w r6,32 /* handle shifts >= 32 separately */
|
mgl@1371
|
17942 |
+ brhs __avr32_f64_sub_longshift
|
mgl@1371
|
17943 |
+
|
mgl@1371
|
17944 |
+ /* small (<32) shift amount, both words are part of the shift
|
mgl@1371
|
17945 |
+ first remember whether part that is lost contains any 1 bits ... */
|
mgl@1371
|
17946 |
+ lsl lr,r8,r5 /* shift away bits that are part of
|
mgl@1371
|
17947 |
+ final mantissa. only part that goes
|
mgl@1371
|
17948 |
+ to lr are bits that will be lost */
|
mgl@1371
|
17949 |
+
|
mgl@1371
|
17950 |
+ /* ... and now to the actual shift */
|
mgl@1371
|
17951 |
+ lsl r5,r9,r5 /* get bits from msw destined for lsw*/
|
mgl@1371
|
17952 |
+ lsr r8,r8,r6 /* shift down lsw of mantissa */
|
mgl@1371
|
17953 |
+ lsr r9,r9,r6 /* shift down msw of mantissa */
|
mgl@1371
|
17954 |
+ or r8,r5 /* combine these bits with prepared lsw*/
|
mgl@1371
|
17955 |
+#if defined(L_avr32_f64_addsub)
|
mgl@1371
|
17956 |
+ cp.w lr,0 /* if any '1' bit in part we lost ...*/
|
mgl@1371
|
17957 |
+ srne lr
|
mgl@1371
|
17958 |
+ or r8, lr /* ... we need to set sticky bit*/
|
mgl@1371
|
17959 |
+#endif
|
mgl@1371
|
17960 |
+
|
mgl@1371
|
17961 |
+__avr32_f64_sub_shift_done:
|
mgl@1371
|
17962 |
+ /* Now subtract the mantissas. */
|
mgl@1371
|
17963 |
+ sub r10, r8
|
mgl@1371
|
17964 |
+ sbc r11, r11, r9
|
mgl@1371
|
17965 |
+
|
mgl@1371
|
17966 |
+ /* Normalize the exponent and mantissa pair stored in
|
mgl@1371
|
17967 |
+ [r11,r10] and exponent in [r7]. Needs two scratch registers [r6] and [lr]. */
|
mgl@1371
|
17968 |
+ clz r6,r11 /* Check if we have zeros in high bits */
|
mgl@1371
|
17969 |
+ breq __avr32_f64_sub_longnormalize_done /* No need for scaling if no zeros in high bits */
|
mgl@1371
|
17970 |
+ brcs __avr32_f64_sub_longnormalize
|
mgl@1371
|
17971 |
+
|
mgl@1371
|
17972 |
+
|
mgl@1371
|
17973 |
+ /* shift amount is smaller than 32, and involves both msw and lsw*/
|
mgl@1371
|
17974 |
+ rsub lr,r6,32 /* shift mantissa */
|
mgl@1371
|
17975 |
+ lsl r11,r11,r6
|
mgl@1371
|
17976 |
+ lsr lr,r10,lr
|
mgl@1371
|
17977 |
+ or r11,lr
|
mgl@1371
|
17978 |
+ lsl r10,r10,r6
|
mgl@1371
|
17979 |
+
|
mgl@1371
|
17980 |
+ sub r7,r6 /* adjust exponent */
|
mgl@1371
|
17981 |
+ brle __avr32_f64_sub_subnormal_result
|
mgl@1371
|
17982 |
+__avr32_f64_sub_longnormalize_done:
|
mgl@1371
|
17983 |
+
|
mgl@1371
|
17984 |
+#if defined(L_avr32_f64_addsub)
|
mgl@1371
|
17985 |
+ /* Insert the bits we will remove from the mantissa r9[31:21] */
|
mgl@1371
|
17986 |
+ lsl r9, r10, (32 - 11)
|
mgl@1371
|
17987 |
+#else
|
mgl@1371
|
17988 |
+ /* Keep the last bit shifted out. */
|
mgl@1371
|
17989 |
+ bfextu r9, r10, 10, 1
|
mgl@1371
|
17990 |
+#endif
|
mgl@1371
|
17991 |
+
|
mgl@1371
|
17992 |
+ /* Pack final result*/
|
mgl@1371
|
17993 |
+ /* Input: [r7]:exp, [r11, r10]:mant, [r12]:sign in MSB */
|
mgl@1371
|
17994 |
+ /* Result in [r11,r10] */
|
mgl@1371
|
17995 |
+ /* Insert mantissa */
|
mgl@1371
|
17996 |
+ lsr r10, 11
|
mgl@1371
|
17997 |
+ or r10, r10, r11<<21
|
mgl@1371
|
17998 |
+ lsr r11, 11
|
mgl@1371
|
17999 |
+ /* Insert exponent and sign bit*/
|
mgl@1371
|
18000 |
+ bfins r11, r7, 20, 11
|
mgl@1371
|
18001 |
+ or r11, r12
|
mgl@1371
|
18002 |
+
|
mgl@1371
|
18003 |
+ /* Round */
|
mgl@1371
|
18004 |
+__avr32_f64_sub_round:
|
mgl@1371
|
18005 |
+#if defined(L_avr32_f64_addsub)
|
mgl@1371
|
18006 |
+ mov_imm r7, 0x80000000
|
mgl@1371
|
18007 |
+ bld r10, 0
|
mgl@1371
|
18008 |
+ subne r7, -1
|
mgl@1371
|
18009 |
+
|
mgl@1371
|
18010 |
+ cp.w r9, r7
|
mgl@1371
|
18011 |
+ srhs r9
|
mgl@1371
|
18012 |
+#endif
|
mgl@1371
|
18013 |
+ add r10, r9
|
mgl@1371
|
18014 |
+ acr r11
|
mgl@1371
|
18015 |
+
|
mgl@1371
|
18016 |
+ /* Return result in [r11,r10] */
|
mgl@1371
|
18017 |
+ ldm sp++, r5, r6, r7,pc
|
mgl@1371
|
18018 |
+
|
mgl@1371
|
18019 |
+
|
mgl@1371
|
18020 |
+
|
mgl@1371
|
18021 |
+__avr32_f64_sub_opL_subnormal:
|
mgl@1371
|
18022 |
+ /* Extract the of mantissa */
|
mgl@1371
|
18023 |
+ lsl r9, 11 /* Extract mantissa, leave room for implicit bit */
|
mgl@1371
|
18024 |
+ or r9, r9, r8>>21
|
mgl@1371
|
18025 |
+ lsl r8, 11
|
mgl@1371
|
18026 |
+
|
mgl@1371
|
18027 |
+ /* Set exponent to 1 if we do not have a zero. */
|
mgl@1371
|
18028 |
+ or lr, r9, r8
|
mgl@1371
|
18029 |
+ movne r6,1
|
mgl@1371
|
18030 |
+
|
mgl@1371
|
18031 |
+ /* Check if opH is also subnormal. If so, clear implicit bit in r11*/
|
mgl@1371
|
18032 |
+ rsub lr, r7, 0
|
mgl@1371
|
18033 |
+ moveq r7,1
|
mgl@1371
|
18034 |
+ bst r11, 31
|
mgl@1371
|
18035 |
+
|
mgl@1371
|
18036 |
+ /* Check if op1 is zero, if so set exponent to 0. */
|
mgl@1371
|
18037 |
+ or lr, r11, r10
|
mgl@1371
|
18038 |
+ moveq r7,0
|
mgl@1371
|
18039 |
+
|
mgl@1371
|
18040 |
+ rjmp __avr32_f64_sub_opL_subnormal_done
|
mgl@1371
|
18041 |
+
|
mgl@1371
|
18042 |
+__avr32_f64_sub_opH_nan_or_inf:
|
mgl@1371
|
18043 |
+ /* Check if opH is NaN, if so return NaN */
|
mgl@1371
|
18044 |
+ cbr r11, 31
|
mgl@1371
|
18045 |
+ or lr, r11, r10
|
mgl@1371
|
18046 |
+ brne __avr32_f64_sub_return_nan
|
mgl@1371
|
18047 |
+
|
mgl@1371
|
18048 |
+ /* opH is Inf. */
|
mgl@1371
|
18049 |
+ /* Check if opL is Inf. or NaN */
|
mgl@1371
|
18050 |
+ cp.w r6, 0x7ff
|
mgl@1371
|
18051 |
+ breq __avr32_f64_sub_return_nan
|
mgl@1371
|
18052 |
+ /* Return infinity with correct sign. */
|
mgl@1371
|
18053 |
+ or r11, r12, r7 << 20
|
mgl@1371
|
18054 |
+ ldm sp++, r5, r6, r7, pc/* opL not Inf or NaN, return opH */
|
mgl@1371
|
18055 |
+__avr32_f64_sub_return_nan:
|
mgl@1371
|
18056 |
+ mov r10, -1 /* Generate NaN in r11, r10 */
|
mgl@1371
|
18057 |
+ mov r11, -1
|
mgl@1371
|
18058 |
+ ldm sp++, r5, r6, r7, pc/* opL Inf or NaN, return NaN */
|
mgl@1371
|
18059 |
+
|
mgl@1371
|
18060 |
+
|
mgl@1371
|
18061 |
+__avr32_f64_sub_subnormal_result:
|
mgl@1371
|
18062 |
+#if defined(L_avr32_f64_addsub)
|
mgl@1371
|
18063 |
+ /* Check how much we must scale down the mantissa. */
|
mgl@1371
|
18064 |
+ neg r7
|
mgl@1371
|
18065 |
+ sub r7, -1 /* We do no longer have an implicit bit. */
|
mgl@1371
|
18066 |
+ satu r7 >> 0, 6 /* Saturate shift amount to max 63. */
|
mgl@1371
|
18067 |
+ cp.w r7, 32
|
mgl@1371
|
18068 |
+ brge 0f
|
mgl@1371
|
18069 |
+ /* Shift amount <32 */
|
mgl@1371
|
18070 |
+ rsub r8, r7, 32
|
mgl@1371
|
18071 |
+ lsl r9, r10, r8
|
mgl@1371
|
18072 |
+ srne r6
|
mgl@1371
|
18073 |
+ lsr r10, r10, r7
|
mgl@1371
|
18074 |
+ or r10, r6 /* Sticky bit from the
|
mgl@1371
|
18075 |
+ part that was shifted out. */
|
mgl@1371
|
18076 |
+ lsl r9, r11, r8
|
mgl@1371
|
18077 |
+ or r10, r10, r9
|
mgl@1371
|
18078 |
+ lsr r11, r10, r7
|
mgl@1371
|
18079 |
+ /* Set exponent */
|
mgl@1371
|
18080 |
+ mov r7, 0
|
mgl@1371
|
18081 |
+ rjmp __avr32_f64_sub_longnormalize_done
|
mgl@1371
|
18082 |
+0:
|
mgl@1371
|
18083 |
+ /* Shift amount >=32 */
|
mgl@1371
|
18084 |
+ rsub r8, r7, 64
|
mgl@1371
|
18085 |
+ lsl r9, r11, r8
|
mgl@1371
|
18086 |
+ or r9, r10
|
mgl@1371
|
18087 |
+ srne r6
|
mgl@1371
|
18088 |
+ lsr r10, r11, r7
|
mgl@1371
|
18089 |
+ or r10, r6 /* Sticky bit from the
|
mgl@1371
|
18090 |
+ part that was shifted out. */
|
mgl@1371
|
18091 |
+ mov r11, 0
|
mgl@1371
|
18092 |
+ /* Set exponent */
|
mgl@1371
|
18093 |
+ mov r7, 0
|
mgl@1371
|
18094 |
+ rjmp __avr32_f64_sub_longnormalize_done
|
mgl@1371
|
18095 |
+#else
|
mgl@1371
|
18096 |
+ /* Just flush subnormals to zero. */
|
mgl@1371
|
18097 |
+ mov r10, 0
|
mgl@1371
|
18098 |
+ mov r11, 0
|
mgl@1371
|
18099 |
+#endif
|
mgl@1371
|
18100 |
+ ldm sp++, r5, r6, r7, pc
|
mgl@1371
|
18101 |
+
|
mgl@1371
|
18102 |
+__avr32_f64_sub_longshift:
|
mgl@1371
|
18103 |
+ /* large (>=32) shift amount, only lsw will have bits left after shift.
|
mgl@1371
|
18104 |
+ note that shift operations will use ((shift count=r6) mod 32) so
|
mgl@1371
|
18105 |
+ we do not need to subtract 32 from shift count. */
|
mgl@1371
|
18106 |
+ /* Saturate the shift amount to 63. If the amount
|
mgl@1371
|
18107 |
+ is any larger op2 is insignificant. */
|
mgl@1371
|
18108 |
+ satu r6 >> 0, 6
|
mgl@1371
|
18109 |
+
|
mgl@1371
|
18110 |
+#if defined(L_avr32_f64_addsub)
|
mgl@1371
|
18111 |
+ /* first remember whether part that is lost contains any 1 bits ... */
|
mgl@1371
|
18112 |
+ moveq lr, r8 /* If shift amount is 32, no bits from msw are lost. */
|
mgl@1371
|
18113 |
+ breq 0f
|
mgl@1371
|
18114 |
+ lsl lr,r9,r5 /* save all lost bits from msw */
|
mgl@1371
|
18115 |
+ or lr,r8 /* also save lost bits (all) from lsw
|
mgl@1371
|
18116 |
+ now lr != 0 if we lose any bits */
|
mgl@1371
|
18117 |
+#endif
|
mgl@1371
|
18118 |
+0:
|
mgl@1371
|
18119 |
+ /* ... and now to the actual shift */
|
mgl@1371
|
18120 |
+ lsr r8,r9,r6 /* Move msw to lsw and shift. */
|
mgl@1371
|
18121 |
+ mov r9,0 /* clear msw */
|
mgl@1371
|
18122 |
+#if defined(L_avr32_f64_addsub)
|
mgl@1371
|
18123 |
+ cp.w lr,0 /* if any '1' bit in part we lost ...*/
|
mgl@1371
|
18124 |
+ srne lr
|
mgl@1371
|
18125 |
+ or r8, lr /* ... we need to set sticky bit*/
|
mgl@1371
|
18126 |
+#endif
|
mgl@1371
|
18127 |
+ rjmp __avr32_f64_sub_shift_done
|
mgl@1371
|
18128 |
+
|
mgl@1371
|
18129 |
+__avr32_f64_sub_longnormalize:
|
mgl@1371
|
18130 |
+ /* shift amount is greater than 32 */
|
mgl@1371
|
18131 |
+ clz r6,r10 /* shift mantissa */
|
mgl@1371
|
18132 |
+ /* If the resulting mantissa is zero the result is
|
mgl@1371
|
18133 |
+ zero so force exponent to zero. */
|
mgl@1371
|
18134 |
+ movcs r7, 0
|
mgl@1371
|
18135 |
+ movcs r6, 0
|
mgl@1371
|
18136 |
+ movcs r12, 0 /* Also clear sign bit. A zero result from subtraction
|
mgl@1371
|
18137 |
+ always is +0.0 */
|
mgl@1371
|
18138 |
+ subcc r6,-32
|
mgl@1371
|
18139 |
+ lsl r11,r10,r6
|
mgl@1371
|
18140 |
+ mov r10,0
|
mgl@1371
|
18141 |
+ sub r7,r6 /* adjust exponent */
|
mgl@1371
|
18142 |
+ brle __avr32_f64_sub_subnormal_result
|
mgl@1371
|
18143 |
+ rjmp __avr32_f64_sub_longnormalize_done
|
mgl@1371
|
18144 |
+
|
mgl@1371
|
18145 |
+
|
mgl@1371
|
18146 |
+
|
mgl@1371
|
18147 |
+ .align 2
|
mgl@1371
|
18148 |
+__avr32_f64_add_from_sub:
|
mgl@1371
|
18149 |
+ /* Switch sign on op2 */
|
mgl@1371
|
18150 |
+ eorh r9, 0x8000
|
mgl@1371
|
18151 |
+
|
mgl@1371
|
18152 |
+#if defined(L_avr32_f64_addsub_fast)
|
mgl@1371
|
18153 |
+ .global __avr32_f64_add_fast
|
mgl@1371
|
18154 |
+ .type __avr32_f64_add_fast,@function
|
mgl@1371
|
18155 |
+__avr32_f64_add_fast:
|
mgl@1371
|
18156 |
+#else
|
mgl@1371
|
18157 |
+ .global __avr32_f64_add
|
mgl@1371
|
18158 |
+ .type __avr32_f64_add,@function
|
mgl@1371
|
18159 |
+__avr32_f64_add:
|
mgl@1371
|
18160 |
+#endif
|
mgl@1371
|
18161 |
+
|
mgl@1371
|
18162 |
+ /* op1 in {r11,r10}*/
|
mgl@1371
|
18163 |
+ /* op2 in {r9,r8}*/
|
mgl@1371
|
18164 |
+
|
mgl@1371
|
18165 |
+#if defined(L_avr32_f64_addsub_fast)
|
mgl@1371
|
18166 |
+ /* If op2 is zero just return op1 */
|
mgl@1371
|
18167 |
+ or r12, r8, r9 << 1
|
mgl@1371
|
18168 |
+ reteq r12
|
mgl@1371
|
18169 |
+#endif
|
mgl@1371
|
18170 |
+
|
mgl@1371
|
18171 |
+ /* Check signs */
|
mgl@1371
|
18172 |
+ eor r12, r11, r9
|
mgl@1371
|
18173 |
+ /* Different signs, use subtraction. */
|
mgl@1371
|
18174 |
+ brmi __avr32_f64_sub_from_add
|
mgl@1371
|
18175 |
+
|
mgl@1371
|
18176 |
+ stm --sp, r5, r6, r7, lr
|
mgl@1371
|
18177 |
+
|
mgl@1371
|
18178 |
+ /* Get sign of op1 into r12 */
|
mgl@1371
|
18179 |
+ mov r12, r11
|
mgl@1371
|
18180 |
+ andh r12, 0x8000, COH
|
mgl@1371
|
18181 |
+
|
mgl@1371
|
18182 |
+ /* Remove sign from operands */
|
mgl@1371
|
18183 |
+ cbr r11, 31
|
mgl@1371
|
18184 |
+ cbr r9, 31
|
mgl@1371
|
18185 |
+
|
mgl@1371
|
18186 |
+ /* Put the number with the largest exponent in [r11, r10]
|
mgl@1371
|
18187 |
+ and the number with the smallest exponent in [r9, r8] */
|
mgl@1371
|
18188 |
+ cp r11, r9
|
mgl@1371
|
18189 |
+ brhs 1f /* Skip swap if operands already correctly ordered */
|
mgl@1371
|
18190 |
+ /* Operands were not correctly ordered, swap them */
|
mgl@1371
|
18191 |
+ mov r7, r11
|
mgl@1371
|
18192 |
+ mov r11, r9
|
mgl@1371
|
18193 |
+ mov r9, r7
|
mgl@1371
|
18194 |
+ mov r7, r10
|
mgl@1371
|
18195 |
+ mov r10, r8
|
mgl@1371
|
18196 |
+ mov r8, r7
|
mgl@1371
|
18197 |
+1:
|
mgl@1371
|
18198 |
+ mov lr, 0 /* Set sticky bits to zero */
|
mgl@1371
|
18199 |
+ /* Unpack largest operand - opH */
|
mgl@1371
|
18200 |
+ /* exp: r7 */
|
mgl@1371
|
18201 |
+ /* sf: r11, r10 */
|
mgl@1371
|
18202 |
+ bfextu R7, R11, 20, 11 /* Extract exponent */
|
mgl@1371
|
18203 |
+ bfextu r11, r11, 0, 20 /* Extract mantissa */
|
mgl@1371
|
18204 |
+ sbr r11, 20 /* Insert implicit bit */
|
mgl@1371
|
18205 |
+
|
mgl@1371
|
18206 |
+ /* Unpack smallest operand - opL */
|
mgl@1371
|
18207 |
+ /* exp: r6 */
|
mgl@1371
|
18208 |
+ /* sf: r9, r8 */
|
mgl@1371
|
18209 |
+ bfextu R6, R9, 20, 11 /* Extract exponent */
|
mgl@1371
|
18210 |
+ breq __avr32_f64_add_op2_subnormal
|
mgl@1371
|
18211 |
+ bfextu r9, r9, 0, 20 /* Extract mantissa */
|
mgl@1371
|
18212 |
+ sbr r9, 20 /* Insert implicit bit */
|
mgl@1371
|
18213 |
+
|
mgl@1371
|
18214 |
+2:
|
mgl@1371
|
18215 |
+ /* opH is NaN or Inf. */
|
mgl@1371
|
18216 |
+ cp.w r7, 0x7ff
|
mgl@1371
|
18217 |
+ breq __avr32_f64_add_opH_nan_or_inf
|
mgl@1371
|
18218 |
+
|
mgl@1371
|
18219 |
+ /* Get shift amount to scale mantissa of op2. */
|
mgl@1371
|
18220 |
+ rsub r6, r7
|
mgl@1371
|
18221 |
+ breq __avr32_f64_add_shift_done /* No need to shift, exponents are equal*/
|
mgl@1371
|
18222 |
+
|
mgl@1371
|
18223 |
+ /* Scale mantissa [r9, r8] with amount [r6].
|
mgl@1371
|
18224 |
+ Uses scratch registers [r5] and [lr].
|
mgl@1371
|
18225 |
+ In IEEE mode:Must not forget the sticky bits we intend to shift out. */
|
mgl@1371
|
18226 |
+ rsub r5,r6,32 /* get (32 - shift count)
|
mgl@1371
|
18227 |
+ (if shift count > 32 we get a
|
mgl@1371
|
18228 |
+ negative value, but that will
|
mgl@1371
|
18229 |
+ work as well in the code below.) */
|
mgl@1371
|
18230 |
+
|
mgl@1371
|
18231 |
+ cp.w r6,32 /* handle shifts >= 32 separately */
|
mgl@1371
|
18232 |
+ brhs __avr32_f64_add_longshift
|
mgl@1371
|
18233 |
+
|
mgl@1371
|
18234 |
+ /* small (<32) shift amount, both words are part of the shift
|
mgl@1371
|
18235 |
+ first remember whether part that is lost contains any 1 bits ... */
|
mgl@1371
|
18236 |
+ lsl lr,r8,r5 /* shift away bits that are part of
|
mgl@1371
|
18237 |
+ final mantissa. only part that goes
|
mgl@1371
|
18238 |
+ to lr are bits that will be lost */
|
mgl@1371
|
18239 |
+
|
mgl@1371
|
18240 |
+ /* ... and now to the actual shift */
|
mgl@1371
|
18241 |
+ lsl r5,r9,r5 /* get bits from msw destined for lsw*/
|
mgl@1371
|
18242 |
+ lsr r8,r8,r6 /* shift down lsw of mantissa */
|
mgl@1371
|
18243 |
+ lsr r9,r9,r6 /* shift down msw of mantissa */
|
mgl@1371
|
18244 |
+ or r8,r5 /* combine these bits with prepared lsw*/
|
mgl@1371
|
18245 |
+
|
mgl@1371
|
18246 |
+__avr32_f64_add_shift_done:
|
mgl@1371
|
18247 |
+ /* Now add the mantissas. */
|
mgl@1371
|
18248 |
+ add r10, r8
|
mgl@1371
|
18249 |
+ adc r11, r11, r9
|
mgl@1371
|
18250 |
+
|
mgl@1371
|
18251 |
+ /* Check if we overflowed. */
|
mgl@1371
|
18252 |
+ bld r11, 21
|
mgl@1371
|
18253 |
+ breq __avr32_f64_add_res_of:
|
mgl@1371
|
18254 |
+
|
mgl@1371
|
18255 |
+__avr32_f64_add_res_of_done:
|
mgl@1371
|
18256 |
+
|
mgl@1371
|
18257 |
+ /* Pack final result*/
|
mgl@1371
|
18258 |
+ /* Input: [r7]:exp, [r11, r10]:mant, [r12]:sign in MSB */
|
mgl@1371
|
18259 |
+ /* Result in [r11,r10] */
|
mgl@1371
|
18260 |
+ /* Insert exponent and sign bit*/
|
mgl@1371
|
18261 |
+ bfins r11, r7, 20, 11
|
mgl@1371
|
18262 |
+ or r11, r12
|
mgl@1371
|
18263 |
+
|
mgl@1371
|
18264 |
+ /* Round */
|
mgl@1371
|
18265 |
+__avr32_f64_add_round:
|
mgl@1371
|
18266 |
+#if defined(L_avr32_f64_addsub)
|
mgl@1371
|
18267 |
+ bfextu r12, r10, 0, 1 /* Extract parity bit.*/
|
mgl@1371
|
18268 |
+ or lr, r12 /* or it together with the sticky bits. */
|
mgl@1371
|
18269 |
+ eorh lr, 0x8000 /* Toggle round bit. */
|
mgl@1371
|
18270 |
+ /* We should now round up by adding one for the following cases:
|
mgl@1371
|
18271 |
+
|
mgl@1371
|
18272 |
+ halfway sticky|parity round-up
|
mgl@1371
|
18273 |
+ 0 x no
|
mgl@1371
|
18274 |
+ 1 0 no
|
mgl@1371
|
18275 |
+ 1 1 yes
|
mgl@1371
|
18276 |
+
|
mgl@1371
|
18277 |
+ Since we have inverted the halfway bit we can use the satu instruction
|
mgl@1371
|
18278 |
+ by saturating to 1 bit to implement this.
|
mgl@1371
|
18279 |
+ */
|
mgl@1371
|
18280 |
+ satu lr >> 0, 1
|
mgl@1371
|
18281 |
+#else
|
mgl@1371
|
18282 |
+ lsr lr, 31
|
mgl@1371
|
18283 |
+#endif
|
mgl@1371
|
18284 |
+ add r10, lr
|
mgl@1371
|
18285 |
+ acr r11
|
mgl@1371
|
18286 |
+
|
mgl@1371
|
18287 |
+ /* Return result in [r11,r10] */
|
mgl@1371
|
18288 |
+ ldm sp++, r5, r6, r7,pc
|
mgl@1371
|
18289 |
+
|
mgl@1371
|
18290 |
+
|
mgl@1371
|
18291 |
+__avr32_f64_add_opH_nan_or_inf:
|
mgl@1371
|
18292 |
+ /* Check if opH is NaN, if so return NaN */
|
mgl@1371
|
18293 |
+ cbr r11, 20
|
mgl@1371
|
18294 |
+ or lr, r11, r10
|
mgl@1371
|
18295 |
+ brne __avr32_f64_add_return_nan
|
mgl@1371
|
18296 |
+
|
mgl@1371
|
18297 |
+ /* opH is Inf. */
|
mgl@1371
|
18298 |
+ /* Check if opL is Inf. or NaN */
|
mgl@1371
|
18299 |
+ cp.w r6, 0x7ff
|
mgl@1371
|
18300 |
+ breq __avr32_f64_add_opL_nan_or_inf
|
mgl@1371
|
18301 |
+ ldm sp++, r5, r6, r7, pc/* opL not Inf or NaN, return opH */
|
mgl@1371
|
18302 |
+__avr32_f64_add_opL_nan_or_inf:
|
mgl@1371
|
18303 |
+ cbr r9, 20
|
mgl@1371
|
18304 |
+ or lr, r9, r8
|
mgl@1371
|
18305 |
+ brne __avr32_f64_add_return_nan
|
mgl@1371
|
18306 |
+ mov r10, 0 /* Generate Inf in r11, r10 */
|
mgl@1371
|
18307 |
+ mov_imm r11, 0x7ff00000
|
mgl@1371
|
18308 |
+ ldm sp++, r5, r6, r7, pc/* opL Inf, return Inf */
|
mgl@1371
|
18309 |
+__avr32_f64_add_return_nan:
|
mgl@1371
|
18310 |
+ mov r10, -1 /* Generate NaN in r11, r10 */
|
mgl@1371
|
18311 |
+ mov r11, -1
|
mgl@1371
|
18312 |
+ ldm sp++, r5, r6, r7, pc/* opL Inf or NaN, return NaN */
|
mgl@1371
|
18313 |
+
|
mgl@1371
|
18314 |
+
|
mgl@1371
|
18315 |
+__avr32_f64_add_longshift:
|
mgl@1371
|
18316 |
+ /* large (>=32) shift amount, only lsw will have bits left after shift.
|
mgl@1371
|
18317 |
+ note that shift operations will use ((shift count=r6) mod 32) so
|
mgl@1371
|
18318 |
+ we do not need to subtract 32 from shift count. */
|
mgl@1371
|
18319 |
+ /* Saturate the shift amount to 63. If the amount
|
mgl@1371
|
18320 |
+ is any larger op2 is insignificant. */
|
mgl@1371
|
18321 |
+ satu r6 >> 0, 6
|
mgl@1371
|
18322 |
+ /* If shift amount is 32 there are no bits from the msw that are lost. */
|
mgl@1371
|
18323 |
+ moveq lr, r8
|
mgl@1371
|
18324 |
+ breq 0f
|
mgl@1371
|
18325 |
+ /* first remember whether part that is lost contains any 1 bits ... */
|
mgl@1371
|
18326 |
+ lsl lr,r9,r5 /* save all lost bits from msw */
|
mgl@1371
|
18327 |
+#if defined(L_avr32_f64_addsub)
|
mgl@1371
|
18328 |
+ cp.w r8, 0
|
mgl@1371
|
18329 |
+ srne r8
|
mgl@1371
|
18330 |
+ or lr,r8 /* also save lost bits (all) from lsw
|
mgl@1371
|
18331 |
+ now lr != 0 if we lose any bits */
|
mgl@1371
|
18332 |
+#endif
|
mgl@1371
|
18333 |
+0:
|
mgl@1371
|
18334 |
+ /* ... and now to the actual shift */
|
mgl@1371
|
18335 |
+ lsr r8,r9,r6 /* msw -> lsw and make rest of shift inside lsw*/
|
mgl@1371
|
18336 |
+ mov r9,0 /* clear msw */
|
mgl@1371
|
18337 |
+ rjmp __avr32_f64_add_shift_done
|
mgl@1371
|
18338 |
+
|
mgl@1371
|
18339 |
+__avr32_f64_add_res_of:
|
mgl@1371
|
18340 |
+ /* We overflowed. Scale down mantissa by shifting right one position. */
|
mgl@1371
|
18341 |
+ or lr, lr, lr << 1 /* Remember stickybits*/
|
mgl@1371
|
18342 |
+ lsr r11, 1
|
mgl@1371
|
18343 |
+ ror r10
|
mgl@1371
|
18344 |
+ ror lr
|
mgl@1371
|
18345 |
+ sub r7, -1 /* Increment exponent */
|
mgl@1371
|
18346 |
+
|
mgl@1371
|
18347 |
+ /* Clear mantissa to set result to Inf if the exponent is 255. */
|
mgl@1371
|
18348 |
+ cp.w r7, 0x7ff
|
mgl@1371
|
18349 |
+ moveq r10, 0
|
mgl@1371
|
18350 |
+ moveq r11, 0
|
mgl@1371
|
18351 |
+ moveq lr, 0
|
mgl@1371
|
18352 |
+ rjmp __avr32_f64_add_res_of_done
|
mgl@1371
|
18353 |
+
|
mgl@1371
|
18354 |
+__avr32_f64_add_op2_subnormal:
|
mgl@1371
|
18355 |
+ /* Set epxponent to 1 */
|
mgl@1371
|
18356 |
+ mov r6, 1
|
mgl@1371
|
18357 |
+
|
mgl@1371
|
18358 |
+ /* Check if op2 is also subnormal. */
|
mgl@1371
|
18359 |
+ cp.w r7, 0
|
mgl@1371
|
18360 |
+ brne 2b
|
mgl@1371
|
18361 |
+
|
mgl@1371
|
18362 |
+ cbr r11, 20
|
mgl@1371
|
18363 |
+ /* Both operands are subnormal. Just addd the mantissas
|
mgl@1371
|
18364 |
+ and the exponent will automatically be set to 1 if
|
mgl@1371
|
18365 |
+ we overflow into a normal number. */
|
mgl@1371
|
18366 |
+ add r10, r8
|
mgl@1371
|
18367 |
+ adc r11, r11, r9
|
mgl@1371
|
18368 |
+
|
mgl@1371
|
18369 |
+ /* Add sign bit */
|
mgl@1371
|
18370 |
+ or r11, r12
|
mgl@1371
|
18371 |
+
|
mgl@1371
|
18372 |
+ /* Return result in [r11,r10] */
|
mgl@1371
|
18373 |
+ ldm sp++, r5, r6, r7,pc
|
mgl@1371
|
18374 |
+
|
mgl@1371
|
18375 |
+
|
mgl@1371
|
18376 |
+
|
mgl@1371
|
18377 |
+#endif
|
mgl@1371
|
18378 |
+
|
mgl@1371
|
18379 |
+#ifdef L_avr32_f64_to_u32
|
mgl@1371
|
18380 |
+ /* This goes into L_fixdfsi */
|
mgl@1371
|
18381 |
+#endif
|
mgl@1371
|
18382 |
+
|
mgl@1371
|
18383 |
+
|
mgl@1371
|
18384 |
+#ifdef L_avr32_f64_to_s32
|
mgl@1371
|
18385 |
+ .global __avr32_f64_to_u32
|
mgl@1371
|
18386 |
+ .type __avr32_f64_to_u32,@function
|
mgl@1371
|
18387 |
+__avr32_f64_to_u32:
|
mgl@1371
|
18388 |
+ cp.w r11, 0
|
mgl@1371
|
18389 |
+ retmi 0 /* Negative returns 0 */
|
mgl@1371
|
18390 |
+
|
mgl@1371
|
18391 |
+ /* Fallthrough to df to signed si conversion */
|
mgl@1371
|
18392 |
+ .global __avr32_f64_to_s32
|
mgl@1371
|
18393 |
+ .type __avr32_f64_to_s32,@function
|
mgl@1371
|
18394 |
+__avr32_f64_to_s32:
|
mgl@1371
|
18395 |
+ lsl r12,r11,1
|
mgl@1371
|
18396 |
+ lsr r12,21 /* extract exponent*/
|
mgl@1371
|
18397 |
+ sub r12,1023 /* convert to unbiased exponent.*/
|
mgl@1371
|
18398 |
+ retlo 0 /* too small exponent implies zero. */
|
mgl@1371
|
18399 |
+
|
mgl@1371
|
18400 |
+1:
|
mgl@1371
|
18401 |
+ rsub r12,r12,31 /* shift count = 31 - exponent */
|
mgl@1371
|
18402 |
+ mov r9,r11 /* save sign for later...*/
|
mgl@1371
|
18403 |
+ lsl r11,11 /* remove exponent and sign*/
|
mgl@1371
|
18404 |
+ sbr r11,31 /* add implicit bit*/
|
mgl@1371
|
18405 |
+ or r11,r11,r10>>21 /* get rest of bits from lsw of double */
|
mgl@1371
|
18406 |
+ lsr r11,r11,r12 /* shift down mantissa to final place */
|
mgl@1371
|
18407 |
+ lsl r9,1 /* sign -> carry */
|
mgl@1371
|
18408 |
+ retcc r11 /* if positive, we are done */
|
mgl@1371
|
18409 |
+ neg r11 /* if negative float, negate result */
|
mgl@1371
|
18410 |
+ ret r11
|
mgl@1371
|
18411 |
+
|
mgl@1371
|
18412 |
+#endif /* L_fixdfsi*/
|
mgl@1371
|
18413 |
+
|
mgl@1371
|
18414 |
+#ifdef L_avr32_f64_to_u64
|
mgl@1371
|
18415 |
+ /* Actual function is in L_fixdfdi */
|
mgl@1371
|
18416 |
+#endif
|
mgl@1371
|
18417 |
+
|
mgl@1371
|
18418 |
+#ifdef L_avr32_f64_to_s64
|
mgl@1371
|
18419 |
+ .global __avr32_f64_to_u64
|
mgl@1371
|
18420 |
+ .type __avr32_f64_to_u64,@function
|
mgl@1371
|
18421 |
+__avr32_f64_to_u64:
|
mgl@1371
|
18422 |
+ cp.w r11,0
|
mgl@1371
|
18423 |
+ /* Negative numbers return zero */
|
mgl@1371
|
18424 |
+ movmi r10, 0
|
mgl@1371
|
18425 |
+ movmi r11, 0
|
mgl@1371
|
18426 |
+ retmi r11
|
mgl@1371
|
18427 |
+
|
mgl@1371
|
18428 |
+
|
mgl@1371
|
18429 |
+
|
mgl@1371
|
18430 |
+ /* Fallthrough */
|
mgl@1371
|
18431 |
+ .global __avr32_f64_to_s64
|
mgl@1371
|
18432 |
+ .type __avr32_f64_to_s64,@function
|
mgl@1371
|
18433 |
+__avr32_f64_to_s64:
|
mgl@1371
|
18434 |
+ lsl r9,r11,1
|
mgl@1371
|
18435 |
+ lsr r9,21 /* get exponent*/
|
mgl@1371
|
18436 |
+ sub r9,1023 /* convert to correct range*/
|
mgl@1371
|
18437 |
+ /* Return zero if exponent to small */
|
mgl@1371
|
18438 |
+ movlo r10, 0
|
mgl@1371
|
18439 |
+ movlo r11, 0
|
mgl@1371
|
18440 |
+ retlo r11
|
mgl@1371
|
18441 |
+
|
mgl@1371
|
18442 |
+ mov r8,r11 /* save sign for later...*/
|
mgl@1371
|
18443 |
+1:
|
mgl@1371
|
18444 |
+ lsl r11,11 /* remove exponent */
|
mgl@1371
|
18445 |
+ sbr r11,31 /* add implicit bit*/
|
mgl@1371
|
18446 |
+ or r11,r11,r10>>21 /* get rest of bits from lsw of double*/
|
mgl@1371
|
18447 |
+ lsl r10,11 /* align lsw correctly as well */
|
mgl@1371
|
18448 |
+ rsub r9,r9,63 /* shift count = 63 - exponent */
|
mgl@1371
|
18449 |
+ breq 1f
|
mgl@1371
|
18450 |
+
|
mgl@1371
|
18451 |
+ cp.w r9,32 /* is shift count more than one reg? */
|
mgl@1371
|
18452 |
+ brhs 0f
|
mgl@1371
|
18453 |
+
|
mgl@1371
|
18454 |
+ mov r12,r11 /* save msw */
|
mgl@1371
|
18455 |
+ lsr r10,r10,r9 /* small shift count, shift down lsw */
|
mgl@1371
|
18456 |
+ lsr r11,r11,r9 /* small shift count, shift down msw */
|
mgl@1371
|
18457 |
+ rsub r9,r9,32 /* get 32-size of shifted out tail */
|
mgl@1371
|
18458 |
+ lsl r12,r12,r9 /* align part to move from msw to lsw */
|
mgl@1371
|
18459 |
+ or r10,r12 /* combine to get new lsw */
|
mgl@1371
|
18460 |
+ rjmp 1f
|
mgl@1371
|
18461 |
+
|
mgl@1371
|
18462 |
+0:
|
mgl@1371
|
18463 |
+ lsr r10,r11,r9 /* large shift count,only lsw get bits
|
mgl@1371
|
18464 |
+ note that shift count is modulo 32*/
|
mgl@1371
|
18465 |
+ mov r11,0 /* msw will be 0 */
|
mgl@1371
|
18466 |
+
|
mgl@1371
|
18467 |
+1:
|
mgl@1371
|
18468 |
+ lsl r8,1 /* sign -> carry */
|
mgl@1371
|
18469 |
+ retcc r11 /* if positive, we are done */
|
mgl@1371
|
18470 |
+
|
mgl@1371
|
18471 |
+ neg r11 /* if negative float, negate result */
|
mgl@1371
|
18472 |
+ neg r10
|
mgl@1371
|
18473 |
+ scr r11
|
mgl@1371
|
18474 |
+ ret r11
|
mgl@1371
|
18475 |
+
|
mgl@1371
|
18476 |
+#endif
|
mgl@1371
|
18477 |
+
|
mgl@1371
|
18478 |
+#ifdef L_avr32_u32_to_f64
|
mgl@1371
|
18479 |
+ /* Code located in L_floatsidf */
|
mgl@1371
|
18480 |
+#endif
|
mgl@1371
|
18481 |
+
|
mgl@1371
|
18482 |
+#ifdef L_avr32_s32_to_f64
|
mgl@1371
|
18483 |
+ .global __avr32_u32_to_f64
|
mgl@1371
|
18484 |
+ .type __avr32_u32_to_f64,@function
|
mgl@1371
|
18485 |
+__avr32_u32_to_f64:
|
mgl@1371
|
18486 |
+ sub r11, r12, 0 /* Move to r11 and force Z flag to be updated */
|
mgl@1371
|
18487 |
+ mov r12, 0 /* always positive */
|
mgl@1371
|
18488 |
+ rjmp 0f /* Jump to common code for floatsidf */
|
mgl@1371
|
18489 |
+
|
mgl@1371
|
18490 |
+ .global __avr32_s32_to_f64
|
mgl@1371
|
18491 |
+ .type __avr32_s32_to_f64,@function
|
mgl@1371
|
18492 |
+__avr32_s32_to_f64:
|
mgl@1371
|
18493 |
+ mov r11, r12 /* Keep original value in r12 for sign */
|
mgl@1371
|
18494 |
+ abs r11 /* Absolute value if r12 */
|
mgl@1371
|
18495 |
+0:
|
mgl@1371
|
18496 |
+ mov r10,0 /* let remaining bits be zero */
|
mgl@1371
|
18497 |
+ reteq r11 /* zero long will return zero float */
|
mgl@1371
|
18498 |
+
|
mgl@1371
|
18499 |
+ pushm lr
|
mgl@1371
|
18500 |
+ mov r9,31+1023 /* set exponent */
|
mgl@1371
|
18501 |
+
|
mgl@1371
|
18502 |
+ normalize_df r9 /*exp*/, r10, r11 /* mantissa */, r8, lr /* scratch */
|
mgl@1371
|
18503 |
+
|
mgl@1371
|
18504 |
+ /* Check if a subnormal result was created */
|
mgl@1371
|
18505 |
+ cp.w r9, 0
|
mgl@1371
|
18506 |
+ brgt 0f
|
mgl@1371
|
18507 |
+
|
mgl@1371
|
18508 |
+ adjust_subnormal_df r9 /* exp */, r10, r11 /* Mantissa */, r12 /*sign*/, r8, lr /* scratch */
|
mgl@1371
|
18509 |
+ popm pc
|
mgl@1371
|
18510 |
+0:
|
mgl@1371
|
18511 |
+
|
mgl@1371
|
18512 |
+ /* Round result */
|
mgl@1371
|
18513 |
+ round_df r9 /*exp*/, r10, r11 /* Mantissa */, r8 /*scratch*/
|
mgl@1371
|
18514 |
+ cp.w r9,0x7ff
|
mgl@1371
|
18515 |
+ brlt 0f
|
mgl@1371
|
18516 |
+ /*Return infinity */
|
mgl@1371
|
18517 |
+ mov r10, 0
|
mgl@1371
|
18518 |
+ mov_imm r11, 0xffe00000
|
mgl@1371
|
18519 |
+ rjmp __floatsidf_return_op1
|
mgl@1371
|
18520 |
+
|
mgl@1371
|
18521 |
+0:
|
mgl@1371
|
18522 |
+
|
mgl@1371
|
18523 |
+ /* Pack */
|
mgl@1371
|
18524 |
+ pack_df r9 /*exp*/, r10, r11 /* mantissa */, r10, r11 /* Output df number*/
|
mgl@1371
|
18525 |
+__floatsidf_return_op1:
|
mgl@1371
|
18526 |
+ lsl r12,1 /* shift in sign bit */
|
mgl@1371
|
18527 |
+ ror r11
|
mgl@1371
|
18528 |
+
|
mgl@1371
|
18529 |
+ popm pc
|
mgl@1371
|
18530 |
+#endif
|
mgl@1371
|
18531 |
+
|
mgl@1371
|
18532 |
+
|
mgl@1371
|
18533 |
+#ifdef L_avr32_f32_cmp_eq
|
mgl@1371
|
18534 |
+ .global __avr32_f32_cmp_eq
|
mgl@1371
|
18535 |
+ .type __avr32_f32_cmp_eq,@function
|
mgl@1371
|
18536 |
+__avr32_f32_cmp_eq:
|
mgl@1371
|
18537 |
+ cp.w r12, r11
|
mgl@1371
|
18538 |
+ breq 0f
|
mgl@1371
|
18539 |
+ /* If not equal check for +/-0 */
|
mgl@1371
|
18540 |
+ /* Or together the two values and shift out the sign bit.
|
mgl@1371
|
18541 |
+ If the result is zero, then the two values are both zero. */
|
mgl@1371
|
18542 |
+ or r12, r11
|
mgl@1371
|
18543 |
+ lsl r12, 1
|
mgl@1371
|
18544 |
+ reteq 1
|
mgl@1371
|
18545 |
+ ret 0
|
mgl@1371
|
18546 |
+0:
|
mgl@1371
|
18547 |
+ /* Numbers were equal. Check for NaN or Inf */
|
mgl@1371
|
18548 |
+ mov_imm r11, 0xff000000
|
mgl@1371
|
18549 |
+ lsl r12, 1
|
mgl@1371
|
18550 |
+ cp.w r12, r11
|
mgl@1371
|
18551 |
+ retls 1 /* 0 if NaN, 1 otherwise */
|
mgl@1371
|
18552 |
+ ret 0
|
mgl@1371
|
18553 |
+#endif
|
mgl@1371
|
18554 |
+
|
mgl@1371
|
18555 |
+#if defined(L_avr32_f32_cmp_ge) || defined(L_avr32_f32_cmp_lt)
|
mgl@1371
|
18556 |
+#ifdef L_avr32_f32_cmp_ge
|
mgl@1371
|
18557 |
+ .global __avr32_f32_cmp_ge
|
mgl@1371
|
18558 |
+ .type __avr32_f32_cmp_ge,@function
|
mgl@1371
|
18559 |
+__avr32_f32_cmp_ge:
|
mgl@1371
|
18560 |
+#endif
|
mgl@1371
|
18561 |
+#ifdef L_avr32_f32_cmp_lt
|
mgl@1371
|
18562 |
+ .global __avr32_f32_cmp_lt
|
mgl@1371
|
18563 |
+ .type __avr32_f32_cmp_lt,@function
|
mgl@1371
|
18564 |
+__avr32_f32_cmp_lt:
|
mgl@1371
|
18565 |
+#endif
|
mgl@1371
|
18566 |
+ lsl r10, r12, 1 /* Remove sign bits */
|
mgl@1371
|
18567 |
+ lsl r9, r11, 1
|
mgl@1371
|
18568 |
+ subfeq r10, 0
|
mgl@1371
|
18569 |
+#ifdef L_avr32_f32_cmp_ge
|
mgl@1371
|
18570 |
+ reteq 1 /* Both number are zero. Return true. */
|
mgl@1371
|
18571 |
+#endif
|
mgl@1371
|
18572 |
+#ifdef L_avr32_f32_cmp_lt
|
mgl@1371
|
18573 |
+ reteq 0 /* Both number are zero. Return false. */
|
mgl@1371
|
18574 |
+#endif
|
mgl@1371
|
18575 |
+ mov_imm r8, 0xff000000
|
mgl@1371
|
18576 |
+ cp.w r10, r8
|
mgl@1371
|
18577 |
+ rethi 0 /* Op0 is NaN */
|
mgl@1371
|
18578 |
+ cp.w r9, r8
|
mgl@1371
|
18579 |
+ rethi 0 /* Op1 is Nan */
|
mgl@1371
|
18580 |
+
|
mgl@1371
|
18581 |
+ eor r8, r11, r12
|
mgl@1371
|
18582 |
+ bld r12, 31
|
mgl@1371
|
18583 |
+#ifdef L_avr32_f32_cmp_ge
|
mgl@1371
|
18584 |
+ srcc r8 /* Set result to true if op0 is positive*/
|
mgl@1371
|
18585 |
+#endif
|
mgl@1371
|
18586 |
+#ifdef L_avr32_f32_cmp_lt
|
mgl@1371
|
18587 |
+ srcs r8 /* Set result to true if op0 is negative*/
|
mgl@1371
|
18588 |
+#endif
|
mgl@1371
|
18589 |
+ retmi r8 /* Return if signs are different */
|
mgl@1371
|
18590 |
+ brcs 0f /* Both signs negative? */
|
mgl@1371
|
18591 |
+
|
mgl@1371
|
18592 |
+ /* Both signs positive */
|
mgl@1371
|
18593 |
+ cp.w r12, r11
|
mgl@1371
|
18594 |
+#ifdef L_avr32_f32_cmp_ge
|
mgl@1371
|
18595 |
+ reths 1
|
mgl@1371
|
18596 |
+ retlo 0
|
mgl@1371
|
18597 |
+#endif
|
mgl@1371
|
18598 |
+#ifdef L_avr32_f32_cmp_lt
|
mgl@1371
|
18599 |
+ reths 0
|
mgl@1371
|
18600 |
+ retlo 1
|
mgl@1371
|
18601 |
+#endif
|
mgl@1371
|
18602 |
+0:
|
mgl@1371
|
18603 |
+ /* Both signs negative */
|
mgl@1371
|
18604 |
+ cp.w r11, r12
|
mgl@1371
|
18605 |
+#ifdef L_avr32_f32_cmp_ge
|
mgl@1371
|
18606 |
+ reths 1
|
mgl@1371
|
18607 |
+ retlo 0
|
mgl@1371
|
18608 |
+#endif
|
mgl@1371
|
18609 |
+#ifdef L_avr32_f32_cmp_lt
|
mgl@1371
|
18610 |
+ reths 0
|
mgl@1371
|
18611 |
+ retlo 1
|
mgl@1371
|
18612 |
+#endif
|
mgl@1371
|
18613 |
+#endif
|
mgl@1371
|
18614 |
+
|
mgl@1371
|
18615 |
+
|
mgl@1371
|
18616 |
+#ifdef L_avr32_f64_cmp_eq
|
mgl@1371
|
18617 |
+ .global __avr32_f64_cmp_eq
|
mgl@1371
|
18618 |
+ .type __avr32_f64_cmp_eq,@function
|
mgl@1371
|
18619 |
+__avr32_f64_cmp_eq:
|
mgl@1371
|
18620 |
+ cp.w r10,r8
|
mgl@1371
|
18621 |
+ cpc r11,r9
|
mgl@1371
|
18622 |
+ breq 0f
|
mgl@1371
|
18623 |
+
|
mgl@1371
|
18624 |
+ /* Args were not equal*/
|
mgl@1371
|
18625 |
+ /* Both args could be zero with different sign bits */
|
mgl@1371
|
18626 |
+ lsl r11,1 /* get rid of sign bits */
|
mgl@1371
|
18627 |
+ lsl r9,1
|
mgl@1371
|
18628 |
+ or r11,r10 /* Check if all bits are zero */
|
mgl@1371
|
18629 |
+ or r11,r9
|
mgl@1371
|
18630 |
+ or r11,r8
|
mgl@1371
|
18631 |
+ reteq 1 /* If all zeros the arguments are equal
|
mgl@1371
|
18632 |
+ so return 1 else return 0 */
|
mgl@1371
|
18633 |
+ ret 0
|
mgl@1371
|
18634 |
+0:
|
mgl@1371
|
18635 |
+ /* check for NaN */
|
mgl@1371
|
18636 |
+ lsl r11,1
|
mgl@1371
|
18637 |
+ mov_imm r12, 0xffe00000
|
mgl@1371
|
18638 |
+ cp.w r10,0
|
mgl@1371
|
18639 |
+ cpc r11,r12 /* check if nan or inf */
|
mgl@1371
|
18640 |
+ retls 1 /* If Arg is NaN return 0 else 1*/
|
mgl@1371
|
18641 |
+ ret 0 /* Return */
|
mgl@1371
|
18642 |
+
|
mgl@1371
|
18643 |
+#endif
|
mgl@1371
|
18644 |
+
|
mgl@1371
|
18645 |
+
|
mgl@1371
|
18646 |
+#if defined(L_avr32_f64_cmp_ge) || defined(L_avr32_f64_cmp_lt)
|
mgl@1371
|
18647 |
+
|
mgl@1371
|
18648 |
+#ifdef L_avr32_f64_cmp_ge
|
mgl@1371
|
18649 |
+ .global __avr32_f64_cmp_ge
|
mgl@1371
|
18650 |
+ .type __avr32_f64_cmp_ge,@function
|
mgl@1371
|
18651 |
+__avr32_f64_cmp_ge:
|
mgl@1371
|
18652 |
+#endif
|
mgl@1371
|
18653 |
+#ifdef L_avr32_f64_cmp_lt
|
mgl@1371
|
18654 |
+ .global __avr32_f64_cmp_lt
|
mgl@1371
|
18655 |
+ .type __avr32_f64_cmp_lt,@function
|
mgl@1371
|
18656 |
+__avr32_f64_cmp_lt:
|
mgl@1371
|
18657 |
+#endif
|
mgl@1371
|
18658 |
+
|
mgl@1371
|
18659 |
+ /* compare magnitude of op1 and op2 */
|
mgl@1371
|
18660 |
+ lsl r11,1 /* Remove sign bit of op1 */
|
mgl@1371
|
18661 |
+ srcs r12 /* Sign op1 to lsb of r12*/
|
mgl@1371
|
18662 |
+ subfeq r10, 0
|
mgl@1371
|
18663 |
+ breq 3f /* op1 zero */
|
mgl@1371
|
18664 |
+ lsl r9,1 /* Remove sign bit of op2 */
|
mgl@1371
|
18665 |
+ rol r12 /* Sign op2 to lsb of lr, sign bit op1 bit 1 of r12*/
|
mgl@1371
|
18666 |
+
|
mgl@1371
|
18667 |
+
|
mgl@1371
|
18668 |
+ /* Check for Nan */
|
mgl@1371
|
18669 |
+ pushm lr
|
mgl@1371
|
18670 |
+ mov_imm lr, 0xffe00000
|
mgl@1371
|
18671 |
+ cp.w r10,0
|
mgl@1371
|
18672 |
+ cpc r11,lr
|
mgl@1371
|
18673 |
+ brhi 0f /* We have NaN */
|
mgl@1371
|
18674 |
+ cp.w r8,0
|
mgl@1371
|
18675 |
+ cpc r9,lr
|
mgl@1371
|
18676 |
+ brhi 0f /* We have NaN */
|
mgl@1371
|
18677 |
+ popm lr
|
mgl@1371
|
18678 |
+
|
mgl@1371
|
18679 |
+ cp.w r12,3 /* both operands negative ?*/
|
mgl@1371
|
18680 |
+ breq 1f
|
mgl@1371
|
18681 |
+
|
mgl@1371
|
18682 |
+ cp.w r12,1 /* both operands positive? */
|
mgl@1371
|
18683 |
+ brlo 2f
|
mgl@1371
|
18684 |
+
|
mgl@1371
|
18685 |
+ /* Different signs. If sign of op1 is negative the difference
|
mgl@1371
|
18686 |
+ between op1 and op2 will always be negative, and if op1 is
|
mgl@1371
|
18687 |
+ positive the difference will always be positive */
|
mgl@1371
|
18688 |
+#ifdef L_avr32_f64_cmp_ge
|
mgl@1371
|
18689 |
+ reteq 1
|
mgl@1371
|
18690 |
+ retne 0
|
mgl@1371
|
18691 |
+#endif
|
mgl@1371
|
18692 |
+#ifdef L_avr32_f64_cmp_lt
|
mgl@1371
|
18693 |
+ reteq 0
|
mgl@1371
|
18694 |
+ retne 1
|
mgl@1371
|
18695 |
+#endif
|
mgl@1371
|
18696 |
+
|
mgl@1371
|
18697 |
+2:
|
mgl@1371
|
18698 |
+ /* Both operands positive. Just compute the difference */
|
mgl@1371
|
18699 |
+ cp.w r10,r8
|
mgl@1371
|
18700 |
+ cpc r11,r9
|
mgl@1371
|
18701 |
+#ifdef L_avr32_f64_cmp_ge
|
mgl@1371
|
18702 |
+ reths 1
|
mgl@1371
|
18703 |
+ retlo 0
|
mgl@1371
|
18704 |
+#endif
|
mgl@1371
|
18705 |
+#ifdef L_avr32_f64_cmp_lt
|
mgl@1371
|
18706 |
+ reths 0
|
mgl@1371
|
18707 |
+ retlo 1
|
mgl@1371
|
18708 |
+#endif
|
mgl@1371
|
18709 |
+
|
mgl@1371
|
18710 |
+1:
|
mgl@1371
|
18711 |
+ /* Both operands negative. Compute the difference with operands switched */
|
mgl@1371
|
18712 |
+ cp r8,r10
|
mgl@1371
|
18713 |
+ cpc r9,r11
|
mgl@1371
|
18714 |
+#ifdef L_avr32_f64_cmp_ge
|
mgl@1371
|
18715 |
+ reths 1
|
mgl@1371
|
18716 |
+ retlo 0
|
mgl@1371
|
18717 |
+#endif
|
mgl@1371
|
18718 |
+#ifdef L_avr32_f64_cmp_lt
|
mgl@1371
|
18719 |
+ reths 0
|
mgl@1371
|
18720 |
+ retlo 1
|
mgl@1371
|
18721 |
+#endif
|
mgl@1371
|
18722 |
+
|
mgl@1371
|
18723 |
+0:
|
mgl@1371
|
18724 |
+ popm pc, r12=0
|
mgl@1371
|
18725 |
+#endif
|
mgl@1371
|
18726 |
+
|
mgl@1371
|
18727 |
+3:
|
mgl@1371
|
18728 |
+ lsl r9,1 /* Remove sign bit of op1 */
|
mgl@1371
|
18729 |
+#ifdef L_avr32_f64_cmp_ge
|
mgl@1371
|
18730 |
+ srcs r12 /* If op2 is negative then op1 >= op2. */
|
mgl@1371
|
18731 |
+#endif
|
mgl@1371
|
18732 |
+#ifdef L_avr32_f64_cmp_lt
|
mgl@1371
|
18733 |
+ srcc r12 /* If op2 is positve then op1 <= op2. */
|
mgl@1371
|
18734 |
+#endif
|
mgl@1371
|
18735 |
+ subfeq r8, 0
|
mgl@1371
|
18736 |
+#ifdef L_avr32_f64_cmp_ge
|
mgl@1371
|
18737 |
+ reteq 1 /* Both operands are zero. Return true. */
|
mgl@1371
|
18738 |
+#endif
|
mgl@1371
|
18739 |
+#ifdef L_avr32_f64_cmp_lt
|
mgl@1371
|
18740 |
+ reteq 0 /* Both operands are zero. Return false. */
|
mgl@1371
|
18741 |
+#endif
|
mgl@1371
|
18742 |
+ ret r12
|
mgl@1371
|
18743 |
+
|
mgl@1371
|
18744 |
+
|
mgl@1371
|
18745 |
+#if defined(L_avr32_f64_div) || defined(L_avr32_f64_div_fast)
|
mgl@1371
|
18746 |
+ .align 2
|
mgl@1371
|
18747 |
+
|
mgl@1371
|
18748 |
+#if defined(L_avr32_f64_div_fast)
|
mgl@1371
|
18749 |
+ .global __avr32_f64_div_fast
|
mgl@1371
|
18750 |
+ .type __avr32_f64_div_fast,@function
|
mgl@1371
|
18751 |
+__avr32_f64_div_fast:
|
mgl@1371
|
18752 |
+#else
|
mgl@1371
|
18753 |
+ .global __avr32_f64_div
|
mgl@1371
|
18754 |
+ .type __avr32_f64_div,@function
|
mgl@1371
|
18755 |
+__avr32_f64_div:
|
mgl@1371
|
18756 |
+#endif
|
mgl@1371
|
18757 |
+ stm --sp, r0, r1, r2, r3, r4, r5, r6, r7,lr
|
mgl@1371
|
18758 |
+ /* op1 in {r11,r10}*/
|
mgl@1371
|
18759 |
+ /* op2 in {r9,r8}*/
|
mgl@1371
|
18760 |
+ eor lr, r11, r9 /* MSB(lr) = Sign(op1) ^ Sign(op2) */
|
mgl@1371
|
18761 |
+
|
mgl@1371
|
18762 |
+
|
mgl@1371
|
18763 |
+ /* Unpack op1 to 2.62 format*/
|
mgl@1371
|
18764 |
+ /* exp: r7 */
|
mgl@1371
|
18765 |
+ /* sf: r11, r10 */
|
mgl@1371
|
18766 |
+ lsr r7, r11, 20 /* Extract exponent */
|
mgl@1371
|
18767 |
+
|
mgl@1371
|
18768 |
+ lsl r11, 9 /* Extract mantissa, leave room for implicit bit */
|
mgl@1371
|
18769 |
+ or r11, r11, r10>>23
|
mgl@1371
|
18770 |
+ lsl r10, 9
|
mgl@1371
|
18771 |
+ sbr r11, 29 /* Insert implicit bit */
|
mgl@1371
|
18772 |
+ andh r11, 0x3fff /*Mask last part of exponent since we use 2.62 format*/
|
mgl@1371
|
18773 |
+
|
mgl@1371
|
18774 |
+ cbr r7, 11 /* Clear sign bit */
|
mgl@1371
|
18775 |
+ /* Check if normalization is needed */
|
mgl@1371
|
18776 |
+ breq 11f /*If number is subnormal, normalize it */
|
mgl@1371
|
18777 |
+22:
|
mgl@1371
|
18778 |
+ cp r7, 0x7ff
|
mgl@1371
|
18779 |
+ brge 2f /* Check op1 for NaN or Inf */
|
mgl@1371
|
18780 |
+
|
mgl@1371
|
18781 |
+ /* Unpack op2 to 2.62 format*/
|
mgl@1371
|
18782 |
+ /* exp: r6 */
|
mgl@1371
|
18783 |
+ /* sf: r9, r8 */
|
mgl@1371
|
18784 |
+ lsr r6, r9, 20 /* Extract exponent */
|
mgl@1371
|
18785 |
+
|
mgl@1371
|
18786 |
+ lsl r9, 9 /* Extract mantissa, leave room for implicit bit */
|
mgl@1371
|
18787 |
+ or r9, r9, r8>>23
|
mgl@1371
|
18788 |
+ lsl r8, 9
|
mgl@1371
|
18789 |
+ sbr r9, 29 /* Insert implicit bit */
|
mgl@1371
|
18790 |
+ andh r9, 0x3fff /*Mask last part of exponent since we use 2.62 format*/
|
mgl@1371
|
18791 |
+
|
mgl@1371
|
18792 |
+ cbr r6, 11 /* Clear sign bit */
|
mgl@1371
|
18793 |
+ /* Check if normalization is needed */
|
mgl@1371
|
18794 |
+ breq 13f /*If number is subnormal, normalize it */
|
mgl@1371
|
18795 |
+23:
|
mgl@1371
|
18796 |
+ cp r6, 0x7ff
|
mgl@1371
|
18797 |
+ brge 3f /* Check op2 for NaN or Inf */
|
mgl@1371
|
18798 |
+
|
mgl@1371
|
18799 |
+ /* Calculate new exponent */
|
mgl@1371
|
18800 |
+ sub r7, r6
|
mgl@1371
|
18801 |
+ sub r7,-1023
|
mgl@1371
|
18802 |
+
|
mgl@1371
|
18803 |
+ /* Divide */
|
mgl@1371
|
18804 |
+ /* Approximating 1/d with the following recurrence: */
|
mgl@1371
|
18805 |
+ /* R[j+1] = R[j]*(2-R[j]*d) */
|
mgl@1371
|
18806 |
+ /* Using 2.62 format */
|
mgl@1371
|
18807 |
+ /* TWO: r12 */
|
mgl@1371
|
18808 |
+ /* d = op2 = divisor (2.62 format): r9,r8 */
|
mgl@1371
|
18809 |
+ /* Multiply result : r5, r4 */
|
mgl@1371
|
18810 |
+ /* Initial guess : r3, r2 */
|
mgl@1371
|
18811 |
+ /* New approximations : r3, r2 */
|
mgl@1371
|
18812 |
+ /* op1 = Dividend (2.62 format) : r11, r10 */
|
mgl@1371
|
18813 |
+
|
mgl@1371
|
18814 |
+ mov_imm r12, 0x80000000
|
mgl@1371
|
18815 |
+
|
mgl@1371
|
18816 |
+ /* Load initial guess, using look-up table */
|
mgl@1371
|
18817 |
+ /* Initial guess is of format 01.XY, where XY is constructed as follows: */
|
mgl@1371
|
18818 |
+ /* Let d be of following format: 00.1xy....., then XY=~xy */
|
mgl@1371
|
18819 |
+ /* For d=00.100 = 0,5 -> initial guess=01.11 = 1,75 */
|
mgl@1371
|
18820 |
+ /* For d=00.101 = 0,625 -> initial guess=01.11 = 1,5 */
|
mgl@1371
|
18821 |
+ /* For d=00.110 = 0,75 -> initial guess=01.11 = 1,25 */
|
mgl@1371
|
18822 |
+ /* For d=00.111 = 0,875 -> initial guess=01.11 = 1,0 */
|
mgl@1371
|
18823 |
+ /* r2 is also part of the reg pair forming initial guess, but it*/
|
mgl@1371
|
18824 |
+ /* is kept uninitialized to save one cycle since it has so low significance*/
|
mgl@1371
|
18825 |
+
|
mgl@1371
|
18826 |
+ lsr r3, r12, 1
|
mgl@1371
|
18827 |
+ bfextu r4, r9, 27, 2
|
mgl@1371
|
18828 |
+ com r4
|
mgl@1371
|
18829 |
+ bfins r3, r4, 28, 2
|
mgl@1371
|
18830 |
+
|
mgl@1371
|
18831 |
+ /* First approximation */
|
mgl@1371
|
18832 |
+ /* Approximating to 32 bits */
|
mgl@1371
|
18833 |
+ /* r5 = R[j]*d */
|
mgl@1371
|
18834 |
+ mulu.d r4, r3, r9
|
mgl@1371
|
18835 |
+ /* r5 = 2-R[j]*d */
|
mgl@1371
|
18836 |
+ sub r5, r12, r5<<2
|
mgl@1371
|
18837 |
+ /* r3 = R[j]*(2-R[j]*d) */
|
mgl@1371
|
18838 |
+ mulu.d r4, r3, r5
|
mgl@1371
|
18839 |
+ lsl r3, r5, 2
|
mgl@1371
|
18840 |
+
|
mgl@1371
|
18841 |
+ /* Second approximation */
|
mgl@1371
|
18842 |
+ /* Approximating to 32 bits */
|
mgl@1371
|
18843 |
+ /* r5 = R[j]*d */
|
mgl@1371
|
18844 |
+ mulu.d r4, r3, r9
|
mgl@1371
|
18845 |
+ /* r5 = 2-R[j]*d */
|
mgl@1371
|
18846 |
+ sub r5, r12, r5<<2
|
mgl@1371
|
18847 |
+ /* r3 = R[j]*(2-R[j]*d) */
|
mgl@1371
|
18848 |
+ mulu.d r4, r3, r5
|
mgl@1371
|
18849 |
+ lsl r3, r5, 2
|
mgl@1371
|
18850 |
+
|
mgl@1371
|
18851 |
+ /* Third approximation */
|
mgl@1371
|
18852 |
+ /* Approximating to 32 bits */
|
mgl@1371
|
18853 |
+ /* r5 = R[j]*d */
|
mgl@1371
|
18854 |
+ mulu.d r4, r3, r9
|
mgl@1371
|
18855 |
+ /* r5 = 2-R[j]*d */
|
mgl@1371
|
18856 |
+ sub r5, r12, r5<<2
|
mgl@1371
|
18857 |
+ /* r3 = R[j]*(2-R[j]*d) */
|
mgl@1371
|
18858 |
+ mulu.d r4, r3, r5
|
mgl@1371
|
18859 |
+ lsl r3, r5, 2
|
mgl@1371
|
18860 |
+
|
mgl@1371
|
18861 |
+ /* Fourth approximation */
|
mgl@1371
|
18862 |
+ /* Approximating to 64 bits */
|
mgl@1371
|
18863 |
+ /* r5,r4 = R[j]*d */
|
mgl@1371
|
18864 |
+ mul_approx_df r3 /*ah*/, r2 /*al*/, r9 /*bh*/, r8 /*bl*/, r5 /*rh*/, r4 /*rl*/, r1 /*sh*/, r0 /*sl*/
|
mgl@1371
|
18865 |
+ lsl r5, 2
|
mgl@1371
|
18866 |
+ or r5, r5, r4>>30
|
mgl@1371
|
18867 |
+ lsl r4, 2
|
mgl@1371
|
18868 |
+ /* r5,r4 = 2-R[j]*d */
|
mgl@1371
|
18869 |
+ neg r4
|
mgl@1371
|
18870 |
+ sbc r5, r12, r5
|
mgl@1371
|
18871 |
+ /* r3,r2 = R[j]*(2-R[j]*d) */
|
mgl@1371
|
18872 |
+ mul_approx_df r3 /*ah*/, r2 /*al*/, r5 /*bh*/, r4 /*bl*/, r5 /*rh*/, r4 /*rl*/, r1 /*sh*/, r0 /*sl*/
|
mgl@1371
|
18873 |
+ lsl r3, r5, 2
|
mgl@1371
|
18874 |
+ or r3, r3, r4>>30
|
mgl@1371
|
18875 |
+ lsl r2, r4, 2
|
mgl@1371
|
18876 |
+
|
mgl@1371
|
18877 |
+
|
mgl@1371
|
18878 |
+ /* Fifth approximation */
|
mgl@1371
|
18879 |
+ /* Approximating to 64 bits */
|
mgl@1371
|
18880 |
+ /* r5,r4 = R[j]*d */
|
mgl@1371
|
18881 |
+ mul_approx_df r3 /*ah*/, r2 /*al*/, r9 /*bh*/, r8 /*bl*/, r5 /*rh*/, r4 /*rl*/, r1 /*sh*/, r0 /*sl*/
|
mgl@1371
|
18882 |
+ lsl r5, 2
|
mgl@1371
|
18883 |
+ or r5, r5, r4>>30
|
mgl@1371
|
18884 |
+ lsl r4, 2
|
mgl@1371
|
18885 |
+ /* r5,r4 = 2-R[j]*d */
|
mgl@1371
|
18886 |
+ neg r4
|
mgl@1371
|
18887 |
+ sbc r5, r12, r5
|
mgl@1371
|
18888 |
+ /* r3,r2 = R[j]*(2-R[j]*d) */
|
mgl@1371
|
18889 |
+ mul_approx_df r3 /*ah*/, r2 /*al*/, r5 /*bh*/, r4 /*bl*/, r5 /*rh*/, r4 /*rl*/, r1 /*sh*/, r0 /*sl*/
|
mgl@1371
|
18890 |
+ lsl r3, r5, 2
|
mgl@1371
|
18891 |
+ or r3, r3, r4>>30
|
mgl@1371
|
18892 |
+ lsl r2, r4, 2
|
mgl@1371
|
18893 |
+
|
mgl@1371
|
18894 |
+
|
mgl@1371
|
18895 |
+ /* Multiply with dividend to get quotient */
|
mgl@1371
|
18896 |
+ mul_approx_df r3 /*ah*/, r2 /*al*/, r11 /*bh*/, r10 /*bl*/, r3 /*rh*/, r2 /*rl*/, r1 /*sh*/, r0 /*sl*/
|
mgl@1371
|
18897 |
+
|
mgl@1371
|
18898 |
+
|
mgl@1371
|
18899 |
+ /* To increase speed, this result is not corrected before final rounding.*/
|
mgl@1371
|
18900 |
+ /* This may give a difference to IEEE compliant code of 1 ULP.*/
|
mgl@1371
|
18901 |
+
|
mgl@1371
|
18902 |
+
|
mgl@1371
|
18903 |
+ /* Adjust exponent and mantissa */
|
mgl@1371
|
18904 |
+ /* r7:exp, [r3, r2]:mant, [r5, r4]:scratch*/
|
mgl@1371
|
18905 |
+ /* Mantissa may be of the format 0.xxxx or 1.xxxx. */
|
mgl@1371
|
18906 |
+ /* In the first case, shift one pos to left.*/
|
mgl@1371
|
18907 |
+ bld r3, 31-3
|
mgl@1371
|
18908 |
+ breq 0f
|
mgl@1371
|
18909 |
+ lsl r2, 1
|
mgl@1371
|
18910 |
+ rol r3
|
mgl@1371
|
18911 |
+ sub r7, 1
|
mgl@1371
|
18912 |
+#if defined(L_avr32_f64_div)
|
mgl@1371
|
18913 |
+ /* We must scale down the dividend to 5.59 format. */
|
mgl@1371
|
18914 |
+ lsr r10, 3
|
mgl@1371
|
18915 |
+ or r10, r10, r11 << 29
|
mgl@1371
|
18916 |
+ lsr r11, 3
|
mgl@1371
|
18917 |
+ rjmp 1f
|
mgl@1371
|
18918 |
+#endif
|
mgl@1371
|
18919 |
+0:
|
mgl@1371
|
18920 |
+#if defined(L_avr32_f64_div)
|
mgl@1371
|
18921 |
+ /* We must scale down the dividend to 6.58 format. */
|
mgl@1371
|
18922 |
+ lsr r10, 4
|
mgl@1371
|
18923 |
+ or r10, r10, r11 << 28
|
mgl@1371
|
18924 |
+ lsr r11, 4
|
mgl@1371
|
18925 |
+1:
|
mgl@1371
|
18926 |
+#endif
|
mgl@1371
|
18927 |
+ cp r7, 0
|
mgl@1371
|
18928 |
+ brle __avr32_f64_div_res_subnormal /* Result was subnormal. */
|
mgl@1371
|
18929 |
+
|
mgl@1371
|
18930 |
+
|
mgl@1371
|
18931 |
+#if defined(L_avr32_f64_div)
|
mgl@1371
|
18932 |
+ /* In order to round correctly we calculate the remainder:
|
mgl@1371
|
18933 |
+ Remainder = dividend[11:r10] - divisor[r9:r8]*quotient[r3:r2]
|
mgl@1371
|
18934 |
+ for the case when the quotient is halfway between the round-up
|
mgl@1371
|
18935 |
+ value and the round down value. If the remainder then is negative
|
mgl@1371
|
18936 |
+ it means that the quotient was to big and that it should not be
|
mgl@1371
|
18937 |
+ rounded up, if the remainder is positive the quotient was to small
|
mgl@1371
|
18938 |
+ and we need to round up. If the remainder is zero it means that the
|
mgl@1371
|
18939 |
+ quotient is exact but since we need to remove the guard bit we should
|
mgl@1371
|
18940 |
+ round to even. */
|
mgl@1371
|
18941 |
+
|
mgl@1371
|
18942 |
+ /* Truncate and add guard bit. */
|
mgl@1371
|
18943 |
+ andl r2, 0xff00
|
mgl@1371
|
18944 |
+ orl r2, 0x0080
|
mgl@1371
|
18945 |
+
|
mgl@1371
|
18946 |
+
|
mgl@1371
|
18947 |
+ /* Now do the multiplication. The quotient has the format 4.60
|
mgl@1371
|
18948 |
+ while the divisor has the format 2.62 which gives a result
|
mgl@1371
|
18949 |
+ of 6.58 */
|
mgl@1371
|
18950 |
+ mulu.d r0, r3, r8
|
mgl@1371
|
18951 |
+ macu.d r0, r2, r9
|
mgl@1371
|
18952 |
+ mulu.d r4, r2, r8
|
mgl@1371
|
18953 |
+ mulu.d r8, r3, r9
|
mgl@1371
|
18954 |
+ add r5, r0
|
mgl@1371
|
18955 |
+ adc r8, r8, r1
|
mgl@1371
|
18956 |
+ acr r9
|
mgl@1371
|
18957 |
+
|
mgl@1371
|
18958 |
+
|
mgl@1371
|
18959 |
+ /* Check if remainder is positive, negative or equal. */
|
mgl@1371
|
18960 |
+ bfextu r12, r2, 8, 1 /* Get parity bit into bit 0 of r0 */
|
mgl@1371
|
18961 |
+ cp r4, 0
|
mgl@1371
|
18962 |
+ cpc r5
|
mgl@1371
|
18963 |
+__avr32_f64_div_round_subnormal:
|
mgl@1371
|
18964 |
+ cpc r8, r10
|
mgl@1371
|
18965 |
+ cpc r9, r11
|
mgl@1371
|
18966 |
+ srlo r6 /* Remainder positive: we need to round up.*/
|
mgl@1371
|
18967 |
+ moveq r6, r12 /* Remainder zero: round up if mantissa odd. */
|
mgl@1371
|
18968 |
+#else
|
mgl@1371
|
18969 |
+ bfextu r6, r2, 7, 1 /* Get guard bit */
|
mgl@1371
|
18970 |
+#endif
|
mgl@1371
|
18971 |
+ /* Final packing, scale down mantissa. */
|
mgl@1371
|
18972 |
+ lsr r10, r2, 8
|
mgl@1371
|
18973 |
+ or r10, r10, r3<<24
|
mgl@1371
|
18974 |
+ lsr r11, r3, 8
|
mgl@1371
|
18975 |
+ /* Insert exponent and sign bit*/
|
mgl@1371
|
18976 |
+ bfins r11, r7, 20, 11
|
mgl@1371
|
18977 |
+ bld lr, 31
|
mgl@1371
|
18978 |
+ bst r11, 31
|
mgl@1371
|
18979 |
+
|
mgl@1371
|
18980 |
+ /* Final rounding */
|
mgl@1371
|
18981 |
+ add r10, r6
|
mgl@1371
|
18982 |
+ acr r11
|
mgl@1371
|
18983 |
+
|
mgl@1371
|
18984 |
+ /* Return result in [r11,r10] */
|
mgl@1371
|
18985 |
+ ldm sp++, r0, r1, r2, r3, r4, r5, r6, r7,pc
|
mgl@1371
|
18986 |
+
|
mgl@1371
|
18987 |
+
|
mgl@1371
|
18988 |
+2:
|
mgl@1371
|
18989 |
+ /* Op1 is NaN or inf */
|
mgl@1371
|
18990 |
+ andh r11, 0x000f /* Extract mantissa */
|
mgl@1371
|
18991 |
+ or r11, r10
|
mgl@1371
|
18992 |
+ brne 16f /* Return NaN if op1 is NaN */
|
mgl@1371
|
18993 |
+ /* Op1 is inf check op2 */
|
mgl@1371
|
18994 |
+ lsr r6, r9, 20 /* Extract exponent */
|
mgl@1371
|
18995 |
+ cbr r6, 8 /* Clear sign bit */
|
mgl@1371
|
18996 |
+ cp r6, 0x7ff
|
mgl@1371
|
18997 |
+ brne 17f /* Inf/number gives inf, return inf */
|
mgl@1371
|
18998 |
+ rjmp 16f /* The rest gives NaN*/
|
mgl@1371
|
18999 |
+
|
mgl@1371
|
19000 |
+3:
|
mgl@1371
|
19001 |
+ /* Op1 is a valid number. Op 2 is NaN or inf */
|
mgl@1371
|
19002 |
+ andh r9, 0x000f /* Extract mantissa */
|
mgl@1371
|
19003 |
+ or r9, r8
|
mgl@1371
|
19004 |
+ brne 16f /* Return NaN if op2 is NaN */
|
mgl@1371
|
19005 |
+ rjmp 15f /* Op2 was inf, return zero*/
|
mgl@1371
|
19006 |
+
|
mgl@1371
|
19007 |
+11: /* Op1 was denormal. Fix it. */
|
mgl@1371
|
19008 |
+ lsl r11, 3
|
mgl@1371
|
19009 |
+ or r11, r11, r10 >> 29
|
mgl@1371
|
19010 |
+ lsl r10, 3
|
mgl@1371
|
19011 |
+ /* Check if op1 is zero. */
|
mgl@1371
|
19012 |
+ or r4, r10, r11
|
mgl@1371
|
19013 |
+ breq __avr32_f64_div_op1_zero
|
mgl@1371
|
19014 |
+ normalize_df r7 /*exp*/, r10, r11 /*Mantissa*/, r4, r5 /*scratch*/
|
mgl@1371
|
19015 |
+ lsr r10, 2
|
mgl@1371
|
19016 |
+ or r10, r10, r11 << 30
|
mgl@1371
|
19017 |
+ lsr r11, 2
|
mgl@1371
|
19018 |
+ rjmp 22b
|
mgl@1371
|
19019 |
+
|
mgl@1371
|
19020 |
+
|
mgl@1371
|
19021 |
+13: /* Op2 was denormal. Fix it */
|
mgl@1371
|
19022 |
+ lsl r9, 3
|
mgl@1371
|
19023 |
+ or r9, r9, r8 >> 29
|
mgl@1371
|
19024 |
+ lsl r8, 3
|
mgl@1371
|
19025 |
+ /* Check if op2 is zero. */
|
mgl@1371
|
19026 |
+ or r4, r9, r8
|
mgl@1371
|
19027 |
+ breq 17f /* Divisor is zero -> return Inf */
|
mgl@1371
|
19028 |
+ normalize_df r6 /*exp*/, r8, r9 /*Mantissa*/, r4, r5 /*scratch*/
|
mgl@1371
|
19029 |
+ lsr r8, 2
|
mgl@1371
|
19030 |
+ or r8, r8, r9 << 30
|
mgl@1371
|
19031 |
+ lsr r9, 2
|
mgl@1371
|
19032 |
+ rjmp 23b
|
mgl@1371
|
19033 |
+
|
mgl@1371
|
19034 |
+
|
mgl@1371
|
19035 |
+__avr32_f64_div_res_subnormal:/* Divide result was subnormal. */
|
mgl@1371
|
19036 |
+#if defined(L_avr32_f64_div)
|
mgl@1371
|
19037 |
+ /* Check how much we must scale down the mantissa. */
|
mgl@1371
|
19038 |
+ neg r7
|
mgl@1371
|
19039 |
+ sub r7, -1 /* We do no longer have an implicit bit. */
|
mgl@1371
|
19040 |
+ satu r7 >> 0, 6 /* Saturate shift amount to max 63. */
|
mgl@1371
|
19041 |
+ cp.w r7, 32
|
mgl@1371
|
19042 |
+ brge 0f
|
mgl@1371
|
19043 |
+ /* Shift amount <32 */
|
mgl@1371
|
19044 |
+ /* Scale down quotient */
|
mgl@1371
|
19045 |
+ rsub r6, r7, 32
|
mgl@1371
|
19046 |
+ lsr r2, r2, r7
|
mgl@1371
|
19047 |
+ lsl r12, r3, r6
|
mgl@1371
|
19048 |
+ or r2, r12
|
mgl@1371
|
19049 |
+ lsr r3, r3, r7
|
mgl@1371
|
19050 |
+ /* Scale down the dividend to match the scaling of the quotient. */
|
mgl@1371
|
19051 |
+ lsl r1, r10, r6
|
mgl@1371
|
19052 |
+ lsr r10, r10, r7
|
mgl@1371
|
19053 |
+ lsl r12, r11, r6
|
mgl@1371
|
19054 |
+ or r10, r12
|
mgl@1371
|
19055 |
+ lsr r11, r11, r7
|
mgl@1371
|
19056 |
+ mov r0, 0
|
mgl@1371
|
19057 |
+ rjmp 1f
|
mgl@1371
|
19058 |
+0:
|
mgl@1371
|
19059 |
+ /* Shift amount >=32 */
|
mgl@1371
|
19060 |
+ rsub r6, r7, 32
|
mgl@1371
|
19061 |
+ moveq r0, 0
|
mgl@1371
|
19062 |
+ moveq r12, 0
|
mgl@1371
|
19063 |
+ breq 0f
|
mgl@1371
|
19064 |
+ lsl r0, r10, r6
|
mgl@1371
|
19065 |
+ lsl r12, r11, r6
|
mgl@1371
|
19066 |
+0:
|
mgl@1371
|
19067 |
+ lsr r2, r3, r7
|
mgl@1371
|
19068 |
+ mov r3, 0
|
mgl@1371
|
19069 |
+ /* Scale down the dividend to match the scaling of the quotient. */
|
mgl@1371
|
19070 |
+ lsr r1, r10, r7
|
mgl@1371
|
19071 |
+ or r1, r12
|
mgl@1371
|
19072 |
+ lsr r10, r11, r7
|
mgl@1371
|
19073 |
+ mov r11, 0
|
mgl@1371
|
19074 |
+1:
|
mgl@1371
|
19075 |
+ /* Start performing the same rounding as done for normal numbers
|
mgl@1371
|
19076 |
+ but this time we have scaled the quotient and dividend and hence
|
mgl@1371
|
19077 |
+ need a little different comparison. */
|
mgl@1371
|
19078 |
+ /* Truncate and add guard bit. */
|
mgl@1371
|
19079 |
+ andl r2, 0xff00
|
mgl@1371
|
19080 |
+ orl r2, 0x0080
|
mgl@1371
|
19081 |
+
|
mgl@1371
|
19082 |
+ /* Now do the multiplication. */
|
mgl@1371
|
19083 |
+ mulu.d r6, r3, r8
|
mgl@1371
|
19084 |
+ macu.d r6, r2, r9
|
mgl@1371
|
19085 |
+ mulu.d r4, r2, r8
|
mgl@1371
|
19086 |
+ mulu.d r8, r3, r9
|
mgl@1371
|
19087 |
+ add r5, r6
|
mgl@1371
|
19088 |
+ adc r8, r8, r7
|
mgl@1371
|
19089 |
+ acr r9
|
mgl@1371
|
19090 |
+
|
mgl@1371
|
19091 |
+ /* Set exponent to 0 */
|
mgl@1371
|
19092 |
+ mov r7, 0
|
mgl@1371
|
19093 |
+
|
mgl@1371
|
19094 |
+ /* Check if remainder is positive, negative or equal. */
|
mgl@1371
|
19095 |
+ bfextu r12, r2, 8, 1 /* Get parity bit into bit 0 of r0 */
|
mgl@1371
|
19096 |
+ cp r4, r0
|
mgl@1371
|
19097 |
+ cpc r5, r1
|
mgl@1371
|
19098 |
+ /* Now the rest of the rounding is the same as for normals. */
|
mgl@1371
|
19099 |
+ rjmp __avr32_f64_div_round_subnormal
|
mgl@1371
|
19100 |
+
|
mgl@1371
|
19101 |
+#endif
|
mgl@1371
|
19102 |
+15:
|
mgl@1371
|
19103 |
+ /* Flush to zero for the fast version. */
|
mgl@1371
|
19104 |
+ mov r11, lr /*Get correct sign*/
|
mgl@1371
|
19105 |
+ andh r11, 0x8000, COH
|
mgl@1371
|
19106 |
+ mov r10, 0
|
mgl@1371
|
19107 |
+ ldm sp++, r0, r1, r2, r3, r4, r5, r6, r7,pc
|
mgl@1371
|
19108 |
+
|
mgl@1371
|
19109 |
+16: /* Return NaN. */
|
mgl@1371
|
19110 |
+ mov r11, -1
|
mgl@1371
|
19111 |
+ mov r10, -1
|
mgl@1371
|
19112 |
+ ldm sp++, r0, r1, r2, r3, r4, r5, r6, r7,pc
|
mgl@1371
|
19113 |
+
|
mgl@1371
|
19114 |
+17: /* Return INF. */
|
mgl@1371
|
19115 |
+ mov r11, lr /*Get correct sign*/
|
mgl@1371
|
19116 |
+ andh r11, 0x8000, COH
|
mgl@1371
|
19117 |
+ orh r11, 0x7ff0
|
mgl@1371
|
19118 |
+ mov r10, 0
|
mgl@1371
|
19119 |
+ ldm sp++, r0, r1, r2, r3, r4, r5, r6, r7,pc
|
mgl@1371
|
19120 |
+
|
mgl@1371
|
19121 |
+__avr32_f64_div_op1_zero:
|
mgl@1371
|
19122 |
+ or r5, r8, r9 << 1
|
mgl@1371
|
19123 |
+ breq 16b /* 0.0/0.0 -> NaN */
|
mgl@1371
|
19124 |
+ bfextu r4, r9, 20, 11
|
mgl@1371
|
19125 |
+ cp r4, 0x7ff
|
mgl@1371
|
19126 |
+ brne 15b /* Return zero */
|
mgl@1371
|
19127 |
+ /* Check if divisor is Inf or NaN */
|
mgl@1371
|
19128 |
+ or r5, r8, r9 << 12
|
mgl@1371
|
19129 |
+ breq 15b /* Divisor is inf -> return zero */
|
mgl@1371
|
19130 |
+ rjmp 16b /* Return NaN */
|
mgl@1371
|
19131 |
+
|
mgl@1371
|
19132 |
+
|
mgl@1371
|
19133 |
+
|
mgl@1371
|
19134 |
+
|
mgl@1371
|
19135 |
+#endif
|
mgl@1371
|
19136 |
+
|
mgl@1371
|
19137 |
+#if defined(L_avr32_f32_addsub) || defined(L_avr32_f32_addsub_fast)
|
mgl@1371
|
19138 |
+
|
mgl@1371
|
19139 |
+ .align 2
|
mgl@1371
|
19140 |
+__avr32_f32_sub_from_add:
|
mgl@1371
|
19141 |
+ /* Switch sign on op2 */
|
mgl@1371
|
19142 |
+ eorh r11, 0x8000
|
mgl@1371
|
19143 |
+
|
mgl@1371
|
19144 |
+#if defined(L_avr32_f32_addsub_fast)
|
mgl@1371
|
19145 |
+ .global __avr32_f32_sub_fast
|
mgl@1371
|
19146 |
+ .type __avr32_f32_sub_fast,@function
|
mgl@1371
|
19147 |
+__avr32_f32_sub_fast:
|
mgl@1371
|
19148 |
+#else
|
mgl@1371
|
19149 |
+ .global __avr32_f32_sub
|
mgl@1371
|
19150 |
+ .type __avr32_f32_sub,@function
|
mgl@1371
|
19151 |
+__avr32_f32_sub:
|
mgl@1371
|
19152 |
+#endif
|
mgl@1371
|
19153 |
+
|
mgl@1371
|
19154 |
+ /* Check signs */
|
mgl@1371
|
19155 |
+ eor r8, r11, r12
|
mgl@1371
|
19156 |
+ /* Different signs, use subtraction. */
|
mgl@1371
|
19157 |
+ brmi __avr32_f32_add_from_sub
|
mgl@1371
|
19158 |
+
|
mgl@1371
|
19159 |
+ /* Get sign of op1 */
|
mgl@1371
|
19160 |
+ mov r8, r12
|
mgl@1371
|
19161 |
+ andh r12, 0x8000, COH
|
mgl@1371
|
19162 |
+
|
mgl@1371
|
19163 |
+ /* Remove sign from operands */
|
mgl@1371
|
19164 |
+ cbr r11, 31
|
mgl@1371
|
19165 |
+#if defined(L_avr32_f32_addsub_fast)
|
mgl@1371
|
19166 |
+ reteq r8 /* If op2 is zero return op1 */
|
mgl@1371
|
19167 |
+#endif
|
mgl@1371
|
19168 |
+ cbr r8, 31
|
mgl@1371
|
19169 |
+
|
mgl@1371
|
19170 |
+ /* Put the number with the largest exponent in r10
|
mgl@1371
|
19171 |
+ and the number with the smallest exponent in r9 */
|
mgl@1371
|
19172 |
+ max r10, r8, r11
|
mgl@1371
|
19173 |
+ min r9, r8, r11
|
mgl@1371
|
19174 |
+ cp r10, r8 /*If largest operand (in R10) is not equal to op1*/
|
mgl@1371
|
19175 |
+ subne r12, 1 /* Subtract 1 from sign, which will invert MSB of r12*/
|
mgl@1371
|
19176 |
+ andh r12, 0x8000, COH /*Mask all but MSB*/
|
mgl@1371
|
19177 |
+
|
mgl@1371
|
19178 |
+ /* Unpack exponent and mantissa of op1 */
|
mgl@1371
|
19179 |
+ lsl r8, r10, 8
|
mgl@1371
|
19180 |
+ sbr r8, 31 /* Set implicit bit. */
|
mgl@1371
|
19181 |
+ lsr r10, 23
|
mgl@1371
|
19182 |
+
|
mgl@1371
|
19183 |
+ /* op1 is NaN or Inf. */
|
mgl@1371
|
19184 |
+ cp.w r10, 0xff
|
mgl@1371
|
19185 |
+ breq __avr32_f32_sub_op1_nan_or_inf
|
mgl@1371
|
19186 |
+
|
mgl@1371
|
19187 |
+ /* Unpack exponent and mantissa of op2 */
|
mgl@1371
|
19188 |
+ lsl r11, r9, 8
|
mgl@1371
|
19189 |
+ sbr r11, 31 /* Set implicit bit. */
|
mgl@1371
|
19190 |
+ lsr r9, 23
|
mgl@1371
|
19191 |
+
|
mgl@1371
|
19192 |
+#if defined(L_avr32_f32_addsub)
|
mgl@1371
|
19193 |
+ /* Keep sticky bit for correct IEEE rounding */
|
mgl@1371
|
19194 |
+ st.w --sp, r12
|
mgl@1371
|
19195 |
+
|
mgl@1371
|
19196 |
+ /* op2 is either zero or subnormal. */
|
mgl@1371
|
19197 |
+ breq __avr32_f32_sub_op2_subnormal
|
mgl@1371
|
19198 |
+0:
|
mgl@1371
|
19199 |
+ /* Get shift amount to scale mantissa of op2. */
|
mgl@1371
|
19200 |
+ sub r12, r10, r9
|
mgl@1371
|
19201 |
+
|
mgl@1371
|
19202 |
+ breq __avr32_f32_sub_shift_done
|
mgl@1371
|
19203 |
+
|
mgl@1371
|
19204 |
+ /* Saturate the shift amount to 31. If the amount
|
mgl@1371
|
19205 |
+ is any larger op2 is insignificant. */
|
mgl@1371
|
19206 |
+ satu r12 >> 0, 5
|
mgl@1371
|
19207 |
+
|
mgl@1371
|
19208 |
+ /* Put the remaining bits into r9.*/
|
mgl@1371
|
19209 |
+ rsub r9, r12, 32
|
mgl@1371
|
19210 |
+ lsl r9, r11, r9
|
mgl@1371
|
19211 |
+
|
mgl@1371
|
19212 |
+ /* If the remaining bits are non-zero then we must subtract one
|
mgl@1371
|
19213 |
+ more from opL. */
|
mgl@1371
|
19214 |
+ subne r8, 1
|
mgl@1371
|
19215 |
+ srne r9 /* LSB of r9 represents sticky bits. */
|
mgl@1371
|
19216 |
+
|
mgl@1371
|
19217 |
+ /* Shift mantissa of op2 to same decimal point as the mantissa
|
mgl@1371
|
19218 |
+ of op1. */
|
mgl@1371
|
19219 |
+ lsr r11, r11, r12
|
mgl@1371
|
19220 |
+
|
mgl@1371
|
19221 |
+
|
mgl@1371
|
19222 |
+__avr32_f32_sub_shift_done:
|
mgl@1371
|
19223 |
+ /* Now subtract the mantissas. */
|
mgl@1371
|
19224 |
+ sub r8, r11
|
mgl@1371
|
19225 |
+
|
mgl@1371
|
19226 |
+ ld.w r12, sp++
|
mgl@1371
|
19227 |
+
|
mgl@1371
|
19228 |
+ /* Normalize resulting mantissa. */
|
mgl@1371
|
19229 |
+ clz r11, r8
|
mgl@1371
|
19230 |
+
|
mgl@1371
|
19231 |
+ retcs 0
|
mgl@1371
|
19232 |
+ lsl r8, r8, r11
|
mgl@1371
|
19233 |
+ sub r10, r11
|
mgl@1371
|
19234 |
+ brle __avr32_f32_sub_subnormal_result
|
mgl@1371
|
19235 |
+
|
mgl@1371
|
19236 |
+ /* Insert the bits we will remove from the mantissa into r9[31:24] */
|
mgl@1371
|
19237 |
+ or r9, r9, r8 << 24
|
mgl@1371
|
19238 |
+#else
|
mgl@1371
|
19239 |
+ /* Ignore sticky bit to simplify and speed up rounding */
|
mgl@1371
|
19240 |
+ /* op2 is either zero or subnormal. */
|
mgl@1371
|
19241 |
+ breq __avr32_f32_sub_op2_subnormal
|
mgl@1371
|
19242 |
+0:
|
mgl@1371
|
19243 |
+ /* Get shift amount to scale mantissa of op2. */
|
mgl@1371
|
19244 |
+ rsub r9, r10
|
mgl@1371
|
19245 |
+
|
mgl@1371
|
19246 |
+ /* Saturate the shift amount to 31. If the amount
|
mgl@1371
|
19247 |
+ is any larger op2 is insignificant. */
|
mgl@1371
|
19248 |
+ satu r9 >> 0, 5
|
mgl@1371
|
19249 |
+
|
mgl@1371
|
19250 |
+ /* Shift mantissa of op2 to same decimal point as the mantissa
|
mgl@1371
|
19251 |
+ of op1. */
|
mgl@1371
|
19252 |
+ lsr r11, r11, r9
|
mgl@1371
|
19253 |
+
|
mgl@1371
|
19254 |
+ /* Now subtract the mantissas. */
|
mgl@1371
|
19255 |
+ sub r8, r11
|
mgl@1371
|
19256 |
+
|
mgl@1371
|
19257 |
+ /* Normalize resulting mantissa. */
|
mgl@1371
|
19258 |
+ clz r9, r8
|
mgl@1371
|
19259 |
+ retcs 0
|
mgl@1371
|
19260 |
+ lsl r8, r8, r9
|
mgl@1371
|
19261 |
+ sub r10, r9
|
mgl@1371
|
19262 |
+ brle __avr32_f32_sub_subnormal_result
|
mgl@1371
|
19263 |
+#endif
|
mgl@1371
|
19264 |
+
|
mgl@1371
|
19265 |
+ /* Pack result. */
|
mgl@1371
|
19266 |
+ or r12, r12, r8 >> 8
|
mgl@1371
|
19267 |
+ bfins r12, r10, 23, 8
|
mgl@1371
|
19268 |
+
|
mgl@1371
|
19269 |
+ /* Round */
|
mgl@1371
|
19270 |
+__avr32_f32_sub_round:
|
mgl@1371
|
19271 |
+#if defined(L_avr32_f32_addsub)
|
mgl@1371
|
19272 |
+ mov_imm r10, 0x80000000
|
mgl@1371
|
19273 |
+ bld r12, 0
|
mgl@1371
|
19274 |
+ subne r10, -1
|
mgl@1371
|
19275 |
+ cp.w r9, r10
|
mgl@1371
|
19276 |
+ subhs r12, -1
|
mgl@1371
|
19277 |
+#else
|
mgl@1371
|
19278 |
+ bld r8, 7
|
mgl@1371
|
19279 |
+ acr r12
|
mgl@1371
|
19280 |
+#endif
|
mgl@1371
|
19281 |
+
|
mgl@1371
|
19282 |
+ ret r12
|
mgl@1371
|
19283 |
+
|
mgl@1371
|
19284 |
+
|
mgl@1371
|
19285 |
+__avr32_f32_sub_op2_subnormal:
|
mgl@1371
|
19286 |
+ /* Fix implicit bit and adjust exponent of subnormals. */
|
mgl@1371
|
19287 |
+ cbr r11, 31
|
mgl@1371
|
19288 |
+ /* Set exponent to 1 if we do not have a zero. */
|
mgl@1371
|
19289 |
+ movne r9,1
|
mgl@1371
|
19290 |
+
|
mgl@1371
|
19291 |
+ /* Check if op1 is also subnormal. */
|
mgl@1371
|
19292 |
+ cp.w r10, 0
|
mgl@1371
|
19293 |
+ brne 0b
|
mgl@1371
|
19294 |
+
|
mgl@1371
|
19295 |
+ cbr r8, 31
|
mgl@1371
|
19296 |
+ /* If op1 is not zero set exponent to 1. */
|
mgl@1371
|
19297 |
+ movne r10,1
|
mgl@1371
|
19298 |
+
|
mgl@1371
|
19299 |
+ rjmp 0b
|
mgl@1371
|
19300 |
+
|
mgl@1371
|
19301 |
+__avr32_f32_sub_op1_nan_or_inf:
|
mgl@1371
|
19302 |
+ /* Check if op1 is NaN, if so return NaN */
|
mgl@1371
|
19303 |
+ lsl r11, r8, 1
|
mgl@1371
|
19304 |
+ retne -1
|
mgl@1371
|
19305 |
+
|
mgl@1371
|
19306 |
+ /* op1 is Inf. */
|
mgl@1371
|
19307 |
+ bfins r12, r10, 23, 8 /* Generate Inf in r12 */
|
mgl@1371
|
19308 |
+
|
mgl@1371
|
19309 |
+ /* Check if op2 is Inf. or NaN */
|
mgl@1371
|
19310 |
+ lsr r11, r9, 23
|
mgl@1371
|
19311 |
+ cp.w r11, 0xff
|
mgl@1371
|
19312 |
+ retne r12 /* op2 not Inf or NaN, return op1 */
|
mgl@1371
|
19313 |
+
|
mgl@1371
|
19314 |
+ ret -1 /* op2 Inf or NaN, return NaN */
|
mgl@1371
|
19315 |
+
|
mgl@1371
|
19316 |
+__avr32_f32_sub_subnormal_result:
|
mgl@1371
|
19317 |
+ /* Check if the number is so small that
|
mgl@1371
|
19318 |
+ it will be represented with zero. */
|
mgl@1371
|
19319 |
+ rsub r10, r10, 9
|
mgl@1371
|
19320 |
+ rsub r11, r10, 32
|
mgl@1371
|
19321 |
+ retcs 0
|
mgl@1371
|
19322 |
+
|
mgl@1371
|
19323 |
+ /* Shift the mantissa into the correct position.*/
|
mgl@1371
|
19324 |
+ lsr r10, r8, r10
|
mgl@1371
|
19325 |
+ /* Add sign bit. */
|
mgl@1371
|
19326 |
+ or r12, r10
|
mgl@1371
|
19327 |
+
|
mgl@1371
|
19328 |
+ /* Put the shifted out bits in the most significant part
|
mgl@1371
|
19329 |
+ of r8. */
|
mgl@1371
|
19330 |
+ lsl r8, r8, r11
|
mgl@1371
|
19331 |
+
|
mgl@1371
|
19332 |
+#if defined(L_avr32_f32_addsub)
|
mgl@1371
|
19333 |
+ /* Add all the remainder bits used for rounding into r9 */
|
mgl@1371
|
19334 |
+ or r9, r8
|
mgl@1371
|
19335 |
+#else
|
mgl@1371
|
19336 |
+ lsr r8, 24
|
mgl@1371
|
19337 |
+#endif
|
mgl@1371
|
19338 |
+ rjmp __avr32_f32_sub_round
|
mgl@1371
|
19339 |
+
|
mgl@1371
|
19340 |
+
|
mgl@1371
|
19341 |
+ .align 2
|
mgl@1371
|
19342 |
+
|
mgl@1371
|
19343 |
+__avr32_f32_add_from_sub:
|
mgl@1371
|
19344 |
+ /* Switch sign on op2 */
|
mgl@1371
|
19345 |
+ eorh r11, 0x8000
|
mgl@1371
|
19346 |
+
|
mgl@1371
|
19347 |
+#if defined(L_avr32_f32_addsub_fast)
|
mgl@1371
|
19348 |
+ .global __avr32_f32_add_fast
|
mgl@1371
|
19349 |
+ .type __avr32_f32_add_fast,@function
|
mgl@1371
|
19350 |
+__avr32_f32_add_fast:
|
mgl@1371
|
19351 |
+#else
|
mgl@1371
|
19352 |
+ .global __avr32_f32_add
|
mgl@1371
|
19353 |
+ .type __avr32_f32_add,@function
|
mgl@1371
|
19354 |
+__avr32_f32_add:
|
mgl@1371
|
19355 |
+#endif
|
mgl@1371
|
19356 |
+
|
mgl@1371
|
19357 |
+ /* Check signs */
|
mgl@1371
|
19358 |
+ eor r8, r11, r12
|
mgl@1371
|
19359 |
+ /* Different signs, use subtraction. */
|
mgl@1371
|
19360 |
+ brmi __avr32_f32_sub_from_add
|
mgl@1371
|
19361 |
+
|
mgl@1371
|
19362 |
+ /* Get sign of op1 */
|
mgl@1371
|
19363 |
+ mov r8, r12
|
mgl@1371
|
19364 |
+ andh r12, 0x8000, COH
|
mgl@1371
|
19365 |
+
|
mgl@1371
|
19366 |
+ /* Remove sign from operands */
|
mgl@1371
|
19367 |
+ cbr r11, 31
|
mgl@1371
|
19368 |
+#if defined(L_avr32_f32_addsub_fast)
|
mgl@1371
|
19369 |
+ reteq r8 /* If op2 is zero return op1 */
|
mgl@1371
|
19370 |
+#endif
|
mgl@1371
|
19371 |
+ cbr r8, 31
|
mgl@1371
|
19372 |
+
|
mgl@1371
|
19373 |
+ /* Put the number with the largest exponent in r10
|
mgl@1371
|
19374 |
+ and the number with the smallest exponent in r9 */
|
mgl@1371
|
19375 |
+ max r10, r8, r11
|
mgl@1371
|
19376 |
+ min r9, r8, r11
|
mgl@1371
|
19377 |
+
|
mgl@1371
|
19378 |
+ /* Unpack exponent and mantissa of op1 */
|
mgl@1371
|
19379 |
+ lsl r8, r10, 8
|
mgl@1371
|
19380 |
+ sbr r8, 31 /* Set implicit bit. */
|
mgl@1371
|
19381 |
+ lsr r10, 23
|
mgl@1371
|
19382 |
+
|
mgl@1371
|
19383 |
+ /* op1 is NaN or Inf. */
|
mgl@1371
|
19384 |
+ cp.w r10, 0xff
|
mgl@1371
|
19385 |
+ breq __avr32_f32_add_op1_nan_or_inf
|
mgl@1371
|
19386 |
+
|
mgl@1371
|
19387 |
+ /* Unpack exponent and mantissa of op2 */
|
mgl@1371
|
19388 |
+ lsl r11, r9, 8
|
mgl@1371
|
19389 |
+ sbr r11, 31 /* Set implicit bit. */
|
mgl@1371
|
19390 |
+ lsr r9, 23
|
mgl@1371
|
19391 |
+
|
mgl@1371
|
19392 |
+#if defined(L_avr32_f32_addsub)
|
mgl@1371
|
19393 |
+ /* op2 is either zero or subnormal. */
|
mgl@1371
|
19394 |
+ breq __avr32_f32_add_op2_subnormal
|
mgl@1371
|
19395 |
+0:
|
mgl@1371
|
19396 |
+ /* Keep sticky bit for correct IEEE rounding */
|
mgl@1371
|
19397 |
+ st.w --sp, r12
|
mgl@1371
|
19398 |
+
|
mgl@1371
|
19399 |
+ /* Get shift amount to scale mantissa of op2. */
|
mgl@1371
|
19400 |
+ rsub r9, r10
|
mgl@1371
|
19401 |
+
|
mgl@1371
|
19402 |
+ /* Saturate the shift amount to 31. If the amount
|
mgl@1371
|
19403 |
+ is any larger op2 is insignificant. */
|
mgl@1371
|
19404 |
+ satu r9 >> 0, 5
|
mgl@1371
|
19405 |
+
|
mgl@1371
|
19406 |
+ /* Shift mantissa of op2 to same decimal point as the mantissa
|
mgl@1371
|
19407 |
+ of op1. */
|
mgl@1371
|
19408 |
+ lsr r12, r11, r9
|
mgl@1371
|
19409 |
+
|
mgl@1371
|
19410 |
+ /* Put the remainding bits into r11[23:..].*/
|
mgl@1371
|
19411 |
+ rsub r9, r9, (32-8)
|
mgl@1371
|
19412 |
+ lsl r11, r11, r9
|
mgl@1371
|
19413 |
+ /* Insert the bits we will remove from the mantissa into r11[31:24] */
|
mgl@1371
|
19414 |
+ bfins r11, r12, 24, 8
|
mgl@1371
|
19415 |
+
|
mgl@1371
|
19416 |
+ /* Now add the mantissas. */
|
mgl@1371
|
19417 |
+ add r8, r12
|
mgl@1371
|
19418 |
+
|
mgl@1371
|
19419 |
+ ld.w r12, sp++
|
mgl@1371
|
19420 |
+#else
|
mgl@1371
|
19421 |
+ /* Ignore sticky bit to simplify and speed up rounding */
|
mgl@1371
|
19422 |
+ /* op2 is either zero or subnormal. */
|
mgl@1371
|
19423 |
+ breq __avr32_f32_add_op2_subnormal
|
mgl@1371
|
19424 |
+0:
|
mgl@1371
|
19425 |
+ /* Get shift amount to scale mantissa of op2. */
|
mgl@1371
|
19426 |
+ rsub r9, r10
|
mgl@1371
|
19427 |
+
|
mgl@1371
|
19428 |
+ /* Saturate the shift amount to 31. If the amount
|
mgl@1371
|
19429 |
+ is any larger op2 is insignificant. */
|
mgl@1371
|
19430 |
+ satu r9 >> 0, 5
|
mgl@1371
|
19431 |
+
|
mgl@1371
|
19432 |
+ /* Shift mantissa of op2 to same decimal point as the mantissa
|
mgl@1371
|
19433 |
+ of op1. */
|
mgl@1371
|
19434 |
+ lsr r11, r11, r9
|
mgl@1371
|
19435 |
+
|
mgl@1371
|
19436 |
+ /* Now add the mantissas. */
|
mgl@1371
|
19437 |
+ add r8, r11
|
mgl@1371
|
19438 |
+
|
mgl@1371
|
19439 |
+#endif
|
mgl@1371
|
19440 |
+ /* Check if we overflowed. */
|
mgl@1371
|
19441 |
+ brcs __avr32_f32_add_res_of
|
mgl@1371
|
19442 |
+1:
|
mgl@1371
|
19443 |
+ /* Pack result. */
|
mgl@1371
|
19444 |
+ or r12, r12, r8 >> 8
|
mgl@1371
|
19445 |
+ bfins r12, r10, 23, 8
|
mgl@1371
|
19446 |
+
|
mgl@1371
|
19447 |
+ /* Round */
|
mgl@1371
|
19448 |
+#if defined(L_avr32_f32_addsub)
|
mgl@1371
|
19449 |
+ mov_imm r10, 0x80000000
|
mgl@1371
|
19450 |
+ bld r12, 0
|
mgl@1371
|
19451 |
+ subne r10, -1
|
mgl@1371
|
19452 |
+ cp.w r11, r10
|
mgl@1371
|
19453 |
+ subhs r12, -1
|
mgl@1371
|
19454 |
+#else
|
mgl@1371
|
19455 |
+ bld r8, 7
|
mgl@1371
|
19456 |
+ acr r12
|
mgl@1371
|
19457 |
+#endif
|
mgl@1371
|
19458 |
+
|
mgl@1371
|
19459 |
+ ret r12
|
mgl@1371
|
19460 |
+
|
mgl@1371
|
19461 |
+__avr32_f32_add_op2_subnormal:
|
mgl@1371
|
19462 |
+ /* Fix implicit bit and adjust exponent of subnormals. */
|
mgl@1371
|
19463 |
+ cbr r11, 31
|
mgl@1371
|
19464 |
+ /* Set exponent to 1 if we do not have a zero. */
|
mgl@1371
|
19465 |
+ movne r9,1
|
mgl@1371
|
19466 |
+
|
mgl@1371
|
19467 |
+ /* Check if op1 is also subnormal. */
|
mgl@1371
|
19468 |
+ cp.w r10, 0
|
mgl@1371
|
19469 |
+ brne 0b
|
mgl@1371
|
19470 |
+ /* Both operands subnormal, just add the mantissas and
|
mgl@1371
|
19471 |
+ pack. If the addition of the subnormal numbers results
|
mgl@1371
|
19472 |
+ in a normal number then the exponent will automatically
|
mgl@1371
|
19473 |
+ be set to 1 by the addition. */
|
mgl@1371
|
19474 |
+ cbr r8, 31
|
mgl@1371
|
19475 |
+ add r11, r8
|
mgl@1371
|
19476 |
+ or r12, r12, r11 >> 8
|
mgl@1371
|
19477 |
+ ret r12
|
mgl@1371
|
19478 |
+
|
mgl@1371
|
19479 |
+__avr32_f32_add_op1_nan_or_inf:
|
mgl@1371
|
19480 |
+ /* Check if op1 is NaN, if so return NaN */
|
mgl@1371
|
19481 |
+ lsl r11, r8, 1
|
mgl@1371
|
19482 |
+ retne -1
|
mgl@1371
|
19483 |
+
|
mgl@1371
|
19484 |
+ /* op1 is Inf. */
|
mgl@1371
|
19485 |
+ bfins r12, r10, 23, 8 /* Generate Inf in r12 */
|
mgl@1371
|
19486 |
+
|
mgl@1371
|
19487 |
+ /* Check if op2 is Inf. or NaN */
|
mgl@1371
|
19488 |
+ lsr r11, r9, 23
|
mgl@1371
|
19489 |
+ cp.w r11, 0xff
|
mgl@1371
|
19490 |
+ retne r12 /* op2 not Inf or NaN, return op1 */
|
mgl@1371
|
19491 |
+
|
mgl@1371
|
19492 |
+ lsl r9, 9
|
mgl@1371
|
19493 |
+ reteq r12 /* op2 Inf return op1 */
|
mgl@1371
|
19494 |
+ ret -1 /* op2 is NaN, return NaN */
|
mgl@1371
|
19495 |
+
|
mgl@1371
|
19496 |
+__avr32_f32_add_res_of:
|
mgl@1371
|
19497 |
+ /* We overflowed. Increase exponent and shift mantissa.*/
|
mgl@1371
|
19498 |
+ lsr r8, 1
|
mgl@1371
|
19499 |
+ sub r10, -1
|
mgl@1371
|
19500 |
+
|
mgl@1371
|
19501 |
+ /* Clear mantissa to set result to Inf if the exponent is 255. */
|
mgl@1371
|
19502 |
+ cp.w r10, 255
|
mgl@1371
|
19503 |
+ moveq r8, 0
|
mgl@1371
|
19504 |
+ moveq r11, 0
|
mgl@1371
|
19505 |
+ rjmp 1b
|
mgl@1371
|
19506 |
+
|
mgl@1371
|
19507 |
+
|
mgl@1371
|
19508 |
+#endif
|
mgl@1371
|
19509 |
+
|
mgl@1371
|
19510 |
+
|
mgl@1371
|
19511 |
+#if defined(L_avr32_f32_div) || defined(L_avr32_f32_div_fast)
|
mgl@1371
|
19512 |
+ .align 2
|
mgl@1371
|
19513 |
+
|
mgl@1371
|
19514 |
+#if defined(L_avr32_f32_div_fast)
|
mgl@1371
|
19515 |
+ .global __avr32_f32_div_fast
|
mgl@1371
|
19516 |
+ .type __avr32_f32_div_fast,@function
|
mgl@1371
|
19517 |
+__avr32_f32_div_fast:
|
mgl@1371
|
19518 |
+#else
|
mgl@1371
|
19519 |
+ .global __avr32_f32_div
|
mgl@1371
|
19520 |
+ .type __avr32_f32_div,@function
|
mgl@1371
|
19521 |
+__avr32_f32_div:
|
mgl@1371
|
19522 |
+#endif
|
mgl@1371
|
19523 |
+
|
mgl@1371
|
19524 |
+ eor r8, r11, r12 /* MSB(r8) = Sign(op1) ^ Sign(op2) */
|
mgl@1371
|
19525 |
+
|
mgl@1371
|
19526 |
+ /* Unpack */
|
mgl@1371
|
19527 |
+ lsl r12,1
|
mgl@1371
|
19528 |
+ reteq 0 /* Return zero if op1 is zero */
|
mgl@1371
|
19529 |
+ lsl r11,1
|
mgl@1371
|
19530 |
+ breq 4f /* Check op2 for zero */
|
mgl@1371
|
19531 |
+
|
mgl@1371
|
19532 |
+ /* Unpack op1*/
|
mgl@1371
|
19533 |
+ /* exp: r9 */
|
mgl@1371
|
19534 |
+ /* sf: r12 */
|
mgl@1371
|
19535 |
+ lsr r9, r12, 24
|
mgl@1371
|
19536 |
+ breq 11f /*If number is subnormal*/
|
mgl@1371
|
19537 |
+ cp r9, 0xff
|
mgl@1371
|
19538 |
+ brhs 2f /* Check op1 for NaN or Inf */
|
mgl@1371
|
19539 |
+ lsl r12, 7
|
mgl@1371
|
19540 |
+ sbr r12, 31 /*Implicit bit*/
|
mgl@1371
|
19541 |
+12:
|
mgl@1371
|
19542 |
+
|
mgl@1371
|
19543 |
+ /* Unpack op2*/
|
mgl@1371
|
19544 |
+ /* exp: r10 */
|
mgl@1371
|
19545 |
+ /* sf: r11 */
|
mgl@1371
|
19546 |
+ lsr r10, r11, 24
|
mgl@1371
|
19547 |
+ breq 13f /*If number is subnormal*/
|
mgl@1371
|
19548 |
+ cp r10, 0xff
|
mgl@1371
|
19549 |
+ brhs 3f /* Check op2 for NaN or Inf */
|
mgl@1371
|
19550 |
+
|
mgl@1371
|
19551 |
+ lsl r11,7
|
mgl@1371
|
19552 |
+ sbr r11, 31 /*Implicit bit*/
|
mgl@1371
|
19553 |
+14:
|
mgl@1371
|
19554 |
+
|
mgl@1371
|
19555 |
+ /* For UC3, store with predecrement is faster than stm */
|
mgl@1371
|
19556 |
+ st.w --sp, r5
|
mgl@1371
|
19557 |
+ st.d --sp, r6
|
mgl@1371
|
19558 |
+
|
mgl@1371
|
19559 |
+ /* Calculate new exponent */
|
mgl@1371
|
19560 |
+ sub r9, r10
|
mgl@1371
|
19561 |
+ sub r9,-127
|
mgl@1371
|
19562 |
+
|
mgl@1371
|
19563 |
+ /* Divide */
|
mgl@1371
|
19564 |
+ /* Approximating 1/d with the following recurrence: */
|
mgl@1371
|
19565 |
+ /* R[j+1] = R[j]*(2-R[j]*d) */
|
mgl@1371
|
19566 |
+ /* Using 2.30 format */
|
mgl@1371
|
19567 |
+ /* TWO: r10 */
|
mgl@1371
|
19568 |
+ /* d: r5 */
|
mgl@1371
|
19569 |
+ /* Multiply result : r6, r7 */
|
mgl@1371
|
19570 |
+ /* Initial guess : r11 */
|
mgl@1371
|
19571 |
+ /* New approximations : r11 */
|
mgl@1371
|
19572 |
+ /* Dividend : r12 */
|
mgl@1371
|
19573 |
+
|
mgl@1371
|
19574 |
+ /* Load TWO */
|
mgl@1371
|
19575 |
+ mov_imm r10, 0x80000000
|
mgl@1371
|
19576 |
+
|
mgl@1371
|
19577 |
+ lsr r12, 2 /* Get significand of Op1 in 2.30 format */
|
mgl@1371
|
19578 |
+ lsr r5, r11, 2 /* Get significand of Op2 (=d) in 2.30 format */
|
mgl@1371
|
19579 |
+
|
mgl@1371
|
19580 |
+ /* Load initial guess, using look-up table */
|
mgl@1371
|
19581 |
+ /* Initial guess is of format 01.XY, where XY is constructed as follows: */
|
mgl@1371
|
19582 |
+ /* Let d be of following format: 00.1xy....., then XY=~xy */
|
mgl@1371
|
19583 |
+ /* For d=00.100 = 0,5 -> initial guess=01.11 = 1,75 */
|
mgl@1371
|
19584 |
+ /* For d=00.101 = 0,625 -> initial guess=01.11 = 1,5 */
|
mgl@1371
|
19585 |
+ /* For d=00.110 = 0,75 -> initial guess=01.11 = 1,25 */
|
mgl@1371
|
19586 |
+ /* For d=00.111 = 0,875 -> initial guess=01.11 = 1,0 */
|
mgl@1371
|
19587 |
+
|
mgl@1371
|
19588 |
+ lsr r11, r10, 1
|
mgl@1371
|
19589 |
+ bfextu r6, r5, 27, 2
|
mgl@1371
|
19590 |
+ com r6
|
mgl@1371
|
19591 |
+ bfins r11, r6, 28, 2
|
mgl@1371
|
19592 |
+
|
mgl@1371
|
19593 |
+ /* First approximation */
|
mgl@1371
|
19594 |
+ /* r7 = R[j]*d */
|
mgl@1371
|
19595 |
+ mulu.d r6, r11, r5
|
mgl@1371
|
19596 |
+ /* r7 = 2-R[j]*d */
|
mgl@1371
|
19597 |
+ sub r7, r10, r7<<2
|
mgl@1371
|
19598 |
+ /* r11 = R[j]*(2-R[j]*d) */
|
mgl@1371
|
19599 |
+ mulu.d r6, r11, r7
|
mgl@1371
|
19600 |
+ lsl r11, r7, 2
|
mgl@1371
|
19601 |
+
|
mgl@1371
|
19602 |
+ /* Second approximation */
|
mgl@1371
|
19603 |
+ /* r7 = R[j]*d */
|
mgl@1371
|
19604 |
+ mulu.d r6, r11, r5
|
mgl@1371
|
19605 |
+ /* r7 = 2-R[j]*d */
|
mgl@1371
|
19606 |
+ sub r7, r10, r7<<2
|
mgl@1371
|
19607 |
+ /* r11 = R[j]*(2-R[j]*d) */
|
mgl@1371
|
19608 |
+ mulu.d r6, r11, r7
|
mgl@1371
|
19609 |
+ lsl r11, r7, 2
|
mgl@1371
|
19610 |
+
|
mgl@1371
|
19611 |
+ /* Third approximation */
|
mgl@1371
|
19612 |
+ /* r7 = R[j]*d */
|
mgl@1371
|
19613 |
+ mulu.d r6, r11, r5
|
mgl@1371
|
19614 |
+ /* r7 = 2-R[j]*d */
|
mgl@1371
|
19615 |
+ sub r7, r10, r7<<2
|
mgl@1371
|
19616 |
+ /* r11 = R[j]*(2-R[j]*d) */
|
mgl@1371
|
19617 |
+ mulu.d r6, r11, r7
|
mgl@1371
|
19618 |
+ lsl r11, r7, 2
|
mgl@1371
|
19619 |
+
|
mgl@1371
|
19620 |
+ /* Fourth approximation */
|
mgl@1371
|
19621 |
+ /* r7 = R[j]*d */
|
mgl@1371
|
19622 |
+ mulu.d r6, r11, r5
|
mgl@1371
|
19623 |
+ /* r7 = 2-R[j]*d */
|
mgl@1371
|
19624 |
+ sub r7, r10, r7<<2
|
mgl@1371
|
19625 |
+ /* r11 = R[j]*(2-R[j]*d) */
|
mgl@1371
|
19626 |
+ mulu.d r6, r11, r7
|
mgl@1371
|
19627 |
+ lsl r11, r7, 2
|
mgl@1371
|
19628 |
+
|
mgl@1371
|
19629 |
+
|
mgl@1371
|
19630 |
+ /* Multiply with dividend to get quotient, r7 = sf(op1)/sf(op2) */
|
mgl@1371
|
19631 |
+ mulu.d r6, r11, r12
|
mgl@1371
|
19632 |
+
|
mgl@1371
|
19633 |
+ /* Shift by 3 to get result in 1.31 format, as required by the exponent. */
|
mgl@1371
|
19634 |
+ /* Note that 1.31 format is already used by the exponent in r9, since */
|
mgl@1371
|
19635 |
+ /* a bias of 127 was added to the result exponent, even though the implicit */
|
mgl@1371
|
19636 |
+ /* bit was inserted. This gives the exponent an additional bias of 1, which */
|
mgl@1371
|
19637 |
+ /* supports 1.31 format. */
|
mgl@1371
|
19638 |
+ //lsl r10, r7, 3
|
mgl@1371
|
19639 |
+
|
mgl@1371
|
19640 |
+ /* Adjust exponent and mantissa in case the result is of format
|
mgl@1371
|
19641 |
+ 0000.1xxx to 0001.xxx*/
|
mgl@1371
|
19642 |
+#if defined(L_avr32_f32_div)
|
mgl@1371
|
19643 |
+ lsr r12, 4 /* Scale dividend to 6.26 format to match the
|
mgl@1371
|
19644 |
+ result of the multiplication of the divisor and
|
mgl@1371
|
19645 |
+ quotient to get the remainder. */
|
mgl@1371
|
19646 |
+#endif
|
mgl@1371
|
19647 |
+ bld r7, 31-3
|
mgl@1371
|
19648 |
+ breq 0f
|
mgl@1371
|
19649 |
+ lsl r7, 1
|
mgl@1371
|
19650 |
+ sub r9, 1
|
mgl@1371
|
19651 |
+#if defined(L_avr32_f32_div)
|
mgl@1371
|
19652 |
+ lsl r12, 1 /* Scale dividend to 5.27 format to match the
|
mgl@1371
|
19653 |
+ result of the multiplication of the divisor and
|
mgl@1371
|
19654 |
+ quotient to get the remainder. */
|
mgl@1371
|
19655 |
+#endif
|
mgl@1371
|
19656 |
+0:
|
mgl@1371
|
19657 |
+ cp r9, 0
|
mgl@1371
|
19658 |
+ brle __avr32_f32_div_res_subnormal /* Result was subnormal. */
|
mgl@1371
|
19659 |
+
|
mgl@1371
|
19660 |
+
|
mgl@1371
|
19661 |
+#if defined(L_avr32_f32_div)
|
mgl@1371
|
19662 |
+ /* In order to round correctly we calculate the remainder:
|
mgl@1371
|
19663 |
+ Remainder = dividend[r12] - divisor[r5]*quotient[r7]
|
mgl@1371
|
19664 |
+ for the case when the quotient is halfway between the round-up
|
mgl@1371
|
19665 |
+ value and the round down value. If the remainder then is negative
|
mgl@1371
|
19666 |
+ it means that the quotient was to big and that it should not be
|
mgl@1371
|
19667 |
+ rounded up, if the remainder is positive the quotient was to small
|
mgl@1371
|
19668 |
+ and we need to round up. If the remainder is zero it means that the
|
mgl@1371
|
19669 |
+ quotient is exact but since we need to remove the guard bit we should
|
mgl@1371
|
19670 |
+ round to even. */
|
mgl@1371
|
19671 |
+ andl r7, 0xffe0
|
mgl@1371
|
19672 |
+ orl r7, 0x0010
|
mgl@1371
|
19673 |
+
|
mgl@1371
|
19674 |
+ /* Now do the multiplication. The quotient has the format 4.28
|
mgl@1371
|
19675 |
+ while the divisor has the format 2.30 which gives a result
|
mgl@1371
|
19676 |
+ of 6.26 */
|
mgl@1371
|
19677 |
+ mulu.d r10, r5, r7
|
mgl@1371
|
19678 |
+
|
mgl@1371
|
19679 |
+ /* Check if remainder is positive, negative or equal. */
|
mgl@1371
|
19680 |
+ bfextu r5, r7, 5, 1 /* Get parity bit into bit 0 of r5 */
|
mgl@1371
|
19681 |
+ cp r10, 0
|
mgl@1371
|
19682 |
+__avr32_f32_div_round_subnormal:
|
mgl@1371
|
19683 |
+ cpc r11, r12
|
mgl@1371
|
19684 |
+ srlo r11 /* Remainder positive: we need to round up.*/
|
mgl@1371
|
19685 |
+ moveq r11, r5 /* Remainder zero: round up if mantissa odd. */
|
mgl@1371
|
19686 |
+#else
|
mgl@1371
|
19687 |
+ bfextu r11, r7, 4, 1 /* Get guard bit */
|
mgl@1371
|
19688 |
+#endif
|
mgl@1371
|
19689 |
+
|
mgl@1371
|
19690 |
+ /* Pack final result*/
|
mgl@1371
|
19691 |
+ lsr r12, r7, 5
|
mgl@1371
|
19692 |
+ bfins r12, r9, 23, 8
|
mgl@1371
|
19693 |
+ /* For UC3, load with postincrement is faster than ldm */
|
mgl@1371
|
19694 |
+ ld.d r6, sp++
|
mgl@1371
|
19695 |
+ ld.w r5, sp++
|
mgl@1371
|
19696 |
+ bld r8, 31
|
mgl@1371
|
19697 |
+ bst r12, 31
|
mgl@1371
|
19698 |
+ /* Rounding add. */
|
mgl@1371
|
19699 |
+ add r12, r11
|
mgl@1371
|
19700 |
+ ret r12
|
mgl@1371
|
19701 |
+
|
mgl@1371
|
19702 |
+__divsf_return_op1:
|
mgl@1371
|
19703 |
+ lsl r8, 1
|
mgl@1371
|
19704 |
+ ror r12
|
mgl@1371
|
19705 |
+ ret r12
|
mgl@1371
|
19706 |
+
|
mgl@1371
|
19707 |
+
|
mgl@1371
|
19708 |
+2:
|
mgl@1371
|
19709 |
+ /* Op1 is NaN or inf */
|
mgl@1371
|
19710 |
+ retne -1 /* Return NaN if op1 is NaN */
|
mgl@1371
|
19711 |
+ /* Op1 is inf check op2 */
|
mgl@1371
|
19712 |
+ mov_imm r9, 0xff000000
|
mgl@1371
|
19713 |
+ cp r11, r9
|
mgl@1371
|
19714 |
+ brlo __divsf_return_op1 /* inf/number gives inf */
|
mgl@1371
|
19715 |
+ ret -1 /* The rest gives NaN*/
|
mgl@1371
|
19716 |
+3:
|
mgl@1371
|
19717 |
+ /* Op2 is NaN or inf */
|
mgl@1371
|
19718 |
+ reteq 0 /* Return zero if number/inf*/
|
mgl@1371
|
19719 |
+ ret -1 /* Return NaN*/
|
mgl@1371
|
19720 |
+4:
|
mgl@1371
|
19721 |
+ /* Op2 is zero ? */
|
mgl@1371
|
19722 |
+ tst r12,r12
|
mgl@1371
|
19723 |
+ reteq -1 /* 0.0/0.0 is NaN */
|
mgl@1371
|
19724 |
+ /* Nonzero/0.0 is Inf. Sign bit will be shifted in before returning*/
|
mgl@1371
|
19725 |
+ mov_imm r12, 0xff000000
|
mgl@1371
|
19726 |
+ rjmp __divsf_return_op1
|
mgl@1371
|
19727 |
+
|
mgl@1371
|
19728 |
+11: /* Op1 was denormal. Fix it. */
|
mgl@1371
|
19729 |
+ lsl r12,7
|
mgl@1371
|
19730 |
+ clz r9,r12
|
mgl@1371
|
19731 |
+ lsl r12,r12,r9
|
mgl@1371
|
19732 |
+ rsub r9,r9,1
|
mgl@1371
|
19733 |
+ rjmp 12b
|
mgl@1371
|
19734 |
+
|
mgl@1371
|
19735 |
+13: /* Op2 was denormal. Fix it. */
|
mgl@1371
|
19736 |
+ lsl r11,7
|
mgl@1371
|
19737 |
+ clz r10,r11
|
mgl@1371
|
19738 |
+ lsl r11,r11,r10
|
mgl@1371
|
19739 |
+ rsub r10,r10,1
|
mgl@1371
|
19740 |
+ rjmp 14b
|
mgl@1371
|
19741 |
+
|
mgl@1371
|
19742 |
+
|
mgl@1371
|
19743 |
+__avr32_f32_div_res_subnormal: /* Divide result was subnormal */
|
mgl@1371
|
19744 |
+#if defined(L_avr32_f32_div)
|
mgl@1371
|
19745 |
+ /* Check how much we must scale down the mantissa. */
|
mgl@1371
|
19746 |
+ neg r9
|
mgl@1371
|
19747 |
+ sub r9, -1 /* We do no longer have an implicit bit. */
|
mgl@1371
|
19748 |
+ satu r9 >> 0, 5 /* Saturate shift amount to max 32. */
|
mgl@1371
|
19749 |
+ /* Scale down quotient */
|
mgl@1371
|
19750 |
+ rsub r10, r9, 32
|
mgl@1371
|
19751 |
+ lsr r7, r7, r9
|
mgl@1371
|
19752 |
+ /* Scale down the dividend to match the scaling of the quotient. */
|
mgl@1371
|
19753 |
+ lsl r6, r12, r10 /* Make the divident 64-bit and put the lsw in r6 */
|
mgl@1371
|
19754 |
+ lsr r12, r12, r9
|
mgl@1371
|
19755 |
+
|
mgl@1371
|
19756 |
+ /* Start performing the same rounding as done for normal numbers
|
mgl@1371
|
19757 |
+ but this time we have scaled the quotient and dividend and hence
|
mgl@1371
|
19758 |
+ need a little different comparison. */
|
mgl@1371
|
19759 |
+ andl r7, 0xffe0
|
mgl@1371
|
19760 |
+ orl r7, 0x0010
|
mgl@1371
|
19761 |
+
|
mgl@1371
|
19762 |
+ /* Now do the multiplication. The quotient has the format 4.28
|
mgl@1371
|
19763 |
+ while the divisor has the format 2.30 which gives a result
|
mgl@1371
|
19764 |
+ of 6.26 */
|
mgl@1371
|
19765 |
+ mulu.d r10, r5, r7
|
mgl@1371
|
19766 |
+
|
mgl@1371
|
19767 |
+ /* Set exponent to 0 */
|
mgl@1371
|
19768 |
+ mov r9, 0
|
mgl@1371
|
19769 |
+
|
mgl@1371
|
19770 |
+ /* Check if remainder is positive, negative or equal. */
|
mgl@1371
|
19771 |
+ bfextu r5, r7, 5, 1 /* Get parity bit into bit 0 of r5 */
|
mgl@1371
|
19772 |
+ cp r10, r6
|
mgl@1371
|
19773 |
+ rjmp __avr32_f32_div_round_subnormal
|
mgl@1371
|
19774 |
+
|
mgl@1371
|
19775 |
+#else
|
mgl@1371
|
19776 |
+ ld.d r6, sp++
|
mgl@1371
|
19777 |
+ ld.w r5, sp++
|
mgl@1371
|
19778 |
+ /*Flush to zero*/
|
mgl@1371
|
19779 |
+ ret 0
|
mgl@1371
|
19780 |
+#endif
|
mgl@1371
|
19781 |
+#endif
|
mgl@1371
|
19782 |
+
|
mgl@1371
|
19783 |
+#ifdef L_avr32_f32_mul
|
mgl@1371
|
19784 |
+ .global __avr32_f32_mul
|
mgl@1371
|
19785 |
+ .type __avr32_f32_mul,@function
|
mgl@1371
|
19786 |
+
|
mgl@1371
|
19787 |
+
|
mgl@1371
|
19788 |
+__avr32_f32_mul:
|
mgl@1371
|
19789 |
+ mov r8, r12
|
mgl@1371
|
19790 |
+ eor r12, r11 /* MSB(r8) = Sign(op1) ^ Sign(op2) */
|
mgl@1371
|
19791 |
+ andh r12, 0x8000, COH
|
mgl@1371
|
19792 |
+
|
mgl@1371
|
19793 |
+ /* arrange operands so that that op1 >= op2 */
|
mgl@1371
|
19794 |
+ cbr r8, 31
|
mgl@1371
|
19795 |
+ breq __avr32_f32_mul_op1_zero
|
mgl@1371
|
19796 |
+ cbr r11, 31
|
mgl@1371
|
19797 |
+
|
mgl@1371
|
19798 |
+ /* Put the number with the largest exponent in r10
|
mgl@1371
|
19799 |
+ and the number with the smallest exponent in r9 */
|
mgl@1371
|
19800 |
+ max r10, r8, r11
|
mgl@1371
|
19801 |
+ min r9, r8, r11
|
mgl@1371
|
19802 |
+
|
mgl@1371
|
19803 |
+ /* Unpack exponent and mantissa of op1 */
|
mgl@1371
|
19804 |
+ lsl r8, r10, 8
|
mgl@1371
|
19805 |
+ sbr r8, 31 /* Set implicit bit. */
|
mgl@1371
|
19806 |
+ lsr r10, 23
|
mgl@1371
|
19807 |
+
|
mgl@1371
|
19808 |
+ /* op1 is NaN or Inf. */
|
mgl@1371
|
19809 |
+ cp.w r10, 0xff
|
mgl@1371
|
19810 |
+ breq __avr32_f32_mul_op1_nan_or_inf
|
mgl@1371
|
19811 |
+
|
mgl@1371
|
19812 |
+ /* Unpack exponent and mantissa of op2 */
|
mgl@1371
|
19813 |
+ lsl r11, r9, 8
|
mgl@1371
|
19814 |
+ sbr r11, 31 /* Set implicit bit. */
|
mgl@1371
|
19815 |
+ lsr r9, 23
|
mgl@1371
|
19816 |
+
|
mgl@1371
|
19817 |
+ /* op2 is either zero or subnormal. */
|
mgl@1371
|
19818 |
+ breq __avr32_f32_mul_op2_subnormal
|
mgl@1371
|
19819 |
+0:
|
mgl@1371
|
19820 |
+ /* Calculate new exponent */
|
mgl@1371
|
19821 |
+ add r9,r10
|
mgl@1371
|
19822 |
+
|
mgl@1371
|
19823 |
+ /* Do the multiplication */
|
mgl@1371
|
19824 |
+ mulu.d r10,r8,r11
|
mgl@1371
|
19825 |
+
|
mgl@1371
|
19826 |
+ /* We might need to scale up by two if the MSB of the result is
|
mgl@1371
|
19827 |
+ zero. */
|
mgl@1371
|
19828 |
+ lsl r8, r11, 1
|
mgl@1371
|
19829 |
+ movcc r11, r8
|
mgl@1371
|
19830 |
+ subcc r9, 1
|
mgl@1371
|
19831 |
+
|
mgl@1371
|
19832 |
+ /* Put the shifted out bits of the mantissa into r10 */
|
mgl@1371
|
19833 |
+ lsr r10, 8
|
mgl@1371
|
19834 |
+ bfins r10, r11, 24, 8
|
mgl@1371
|
19835 |
+
|
mgl@1371
|
19836 |
+ sub r9,(127-1) /* remove extra exponent bias */
|
mgl@1371
|
19837 |
+ brle __avr32_f32_mul_res_subnormal
|
mgl@1371
|
19838 |
+
|
mgl@1371
|
19839 |
+ /* Check for Inf. */
|
mgl@1371
|
19840 |
+ cp.w r9, 0xff
|
mgl@1371
|
19841 |
+ brge 1f
|
mgl@1371
|
19842 |
+
|
mgl@1371
|
19843 |
+ /* Pack result. */
|
mgl@1371
|
19844 |
+ or r12, r12, r11 >> 8
|
mgl@1371
|
19845 |
+ bfins r12, r9, 23, 8
|
mgl@1371
|
19846 |
+
|
mgl@1371
|
19847 |
+ /* Round */
|
mgl@1371
|
19848 |
+__avr32_f32_mul_round:
|
mgl@1371
|
19849 |
+ mov_imm r8, 0x80000000
|
mgl@1371
|
19850 |
+ bld r12, 0
|
mgl@1371
|
19851 |
+ subne r8, -1
|
mgl@1371
|
19852 |
+
|
mgl@1371
|
19853 |
+ cp.w r10, r8
|
mgl@1371
|
19854 |
+ subhs r12, -1
|
mgl@1371
|
19855 |
+
|
mgl@1371
|
19856 |
+ ret r12
|
mgl@1371
|
19857 |
+
|
mgl@1371
|
19858 |
+1:
|
mgl@1371
|
19859 |
+ /* Return Inf */
|
mgl@1371
|
19860 |
+ orh r12, 0x7f80
|
mgl@1371
|
19861 |
+ ret r12
|
mgl@1371
|
19862 |
+
|
mgl@1371
|
19863 |
+__avr32_f32_mul_op2_subnormal:
|
mgl@1371
|
19864 |
+ cbr r11, 31
|
mgl@1371
|
19865 |
+ clz r9, r11
|
mgl@1371
|
19866 |
+ retcs 0 /* op2 is zero. Return 0 */
|
mgl@1371
|
19867 |
+ lsl r11, r11, r9
|
mgl@1371
|
19868 |
+ rsub r9, r9, 1
|
mgl@1371
|
19869 |
+
|
mgl@1371
|
19870 |
+ /* Check if op2 is subnormal. */
|
mgl@1371
|
19871 |
+ tst r10, r10
|
mgl@1371
|
19872 |
+ brne 0b
|
mgl@1371
|
19873 |
+
|
mgl@1371
|
19874 |
+ /* op2 is subnormal */
|
mgl@1371
|
19875 |
+ cbr r8, 31
|
mgl@1371
|
19876 |
+ clz r10, r11
|
mgl@1371
|
19877 |
+ retcs 0 /* op1 is zero. Return 0 */
|
mgl@1371
|
19878 |
+ lsl r8, r8, r10
|
mgl@1371
|
19879 |
+ rsub r10, r10, 1
|
mgl@1371
|
19880 |
+
|
mgl@1371
|
19881 |
+ rjmp 0b
|
mgl@1371
|
19882 |
+
|
mgl@1371
|
19883 |
+
|
mgl@1371
|
19884 |
+__avr32_f32_mul_op1_nan_or_inf:
|
mgl@1371
|
19885 |
+ /* Check if op1 is NaN, if so return NaN */
|
mgl@1371
|
19886 |
+ lsl r11, r8, 1
|
mgl@1371
|
19887 |
+ retne -1
|
mgl@1371
|
19888 |
+
|
mgl@1371
|
19889 |
+ /* op1 is Inf. */
|
mgl@1371
|
19890 |
+ tst r9, r9
|
mgl@1371
|
19891 |
+ reteq -1 /* Inf * 0 -> NaN */
|
mgl@1371
|
19892 |
+
|
mgl@1371
|
19893 |
+ bfins r12, r10, 23, 8 /* Generate Inf in r12 */
|
mgl@1371
|
19894 |
+
|
mgl@1371
|
19895 |
+ /* Check if op2 is Inf. or NaN */
|
mgl@1371
|
19896 |
+ lsr r11, r9, 23
|
mgl@1371
|
19897 |
+ cp.w r11, 0xff
|
mgl@1371
|
19898 |
+ retne r12 /* op2 not Inf or NaN, return Info */
|
mgl@1371
|
19899 |
+
|
mgl@1371
|
19900 |
+ lsl r9, 9
|
mgl@1371
|
19901 |
+ reteq r12 /* op2 Inf return Inf */
|
mgl@1371
|
19902 |
+ ret -1 /* op2 is NaN, return NaN */
|
mgl@1371
|
19903 |
+
|
mgl@1371
|
19904 |
+__avr32_f32_mul_res_subnormal:
|
mgl@1371
|
19905 |
+ /* Check if the number is so small that
|
mgl@1371
|
19906 |
+ it will be represented with zero. */
|
mgl@1371
|
19907 |
+ rsub r9, r9, 9
|
mgl@1371
|
19908 |
+ rsub r8, r9, 32
|
mgl@1371
|
19909 |
+ retcs 0
|
mgl@1371
|
19910 |
+
|
mgl@1371
|
19911 |
+ /* Shift the mantissa into the correct position.*/
|
mgl@1371
|
19912 |
+ lsr r9, r11, r9
|
mgl@1371
|
19913 |
+ /* Add sign bit. */
|
mgl@1371
|
19914 |
+ or r12, r9
|
mgl@1371
|
19915 |
+ /* Put the shifted out bits in the most significant part
|
mgl@1371
|
19916 |
+ of r8. */
|
mgl@1371
|
19917 |
+ lsl r11, r11, r8
|
mgl@1371
|
19918 |
+
|
mgl@1371
|
19919 |
+ /* Add all the remainder bits used for rounding into r11 */
|
mgl@1371
|
19920 |
+ andh r10, 0x00FF
|
mgl@1371
|
19921 |
+ or r10, r11
|
mgl@1371
|
19922 |
+ rjmp __avr32_f32_mul_round
|
mgl@1371
|
19923 |
+
|
mgl@1371
|
19924 |
+__avr32_f32_mul_op1_zero:
|
mgl@1371
|
19925 |
+ bfextu r10, r11, 23, 8
|
mgl@1371
|
19926 |
+ cp.w r10, 0xff
|
mgl@1371
|
19927 |
+ retne r12
|
mgl@1371
|
19928 |
+ reteq -1
|
mgl@1371
|
19929 |
+
|
mgl@1371
|
19930 |
+#endif
|
mgl@1371
|
19931 |
+
|
mgl@1371
|
19932 |
+
|
mgl@1371
|
19933 |
+#ifdef L_avr32_s32_to_f32
|
mgl@1371
|
19934 |
+ .global __avr32_s32_to_f32
|
mgl@1371
|
19935 |
+ .type __avr32_s32_to_f32,@function
|
mgl@1371
|
19936 |
+__avr32_s32_to_f32:
|
mgl@1371
|
19937 |
+ cp r12, 0
|
mgl@1371
|
19938 |
+ reteq r12 /* If zero then return zero float */
|
mgl@1371
|
19939 |
+ mov r11, r12 /* Keep the sign */
|
mgl@1371
|
19940 |
+ abs r12 /* Compute the absolute value */
|
mgl@1371
|
19941 |
+ mov r10, 31 + 127 /* Set the correct exponent */
|
mgl@1371
|
19942 |
+
|
mgl@1371
|
19943 |
+ /* Normalize */
|
mgl@1371
|
19944 |
+ normalize_sf r10 /*exp*/, r12 /*mant*/, r9 /*scratch*/
|
mgl@1371
|
19945 |
+
|
mgl@1371
|
19946 |
+ /* Check for subnormal result */
|
mgl@1371
|
19947 |
+ cp.w r10, 0
|
mgl@1371
|
19948 |
+ brle __avr32_s32_to_f32_subnormal
|
mgl@1371
|
19949 |
+
|
mgl@1371
|
19950 |
+ round_sf r10 /*exp*/, r12 /*mant*/, r9 /*scratch*/
|
mgl@1371
|
19951 |
+ pack_sf r12 /*sf*/, r10 /*exp*/, r12 /*mant*/
|
mgl@1371
|
19952 |
+ lsl r11, 1
|
mgl@1371
|
19953 |
+ ror r12
|
mgl@1371
|
19954 |
+ ret r12
|
mgl@1371
|
19955 |
+
|
mgl@1371
|
19956 |
+__avr32_s32_to_f32_subnormal:
|
mgl@1371
|
19957 |
+ /* Adjust a subnormal result */
|
mgl@1371
|
19958 |
+ adjust_subnormal_sf r12/*sf*/, r10 /*exp*/, r12 /*mant*/, r11/*sign*/, r9 /*scratch*/
|
mgl@1371
|
19959 |
+ ret r12
|
mgl@1371
|
19960 |
+
|
mgl@1371
|
19961 |
+#endif
|
mgl@1371
|
19962 |
+
|
mgl@1371
|
19963 |
+#ifdef L_avr32_u32_to_f32
|
mgl@1371
|
19964 |
+ .global __avr32_u32_to_f32
|
mgl@1371
|
19965 |
+ .type __avr32_u32_to_f32,@function
|
mgl@1371
|
19966 |
+__avr32_u32_to_f32:
|
mgl@1371
|
19967 |
+ cp r12, 0
|
mgl@1371
|
19968 |
+ reteq r12 /* If zero then return zero float */
|
mgl@1371
|
19969 |
+ mov r10, 31 + 127 /* Set the correct exponent */
|
mgl@1371
|
19970 |
+
|
mgl@1371
|
19971 |
+ /* Normalize */
|
mgl@1371
|
19972 |
+ normalize_sf r10 /*exp*/, r12 /*mant*/, r9 /*scratch*/
|
mgl@1371
|
19973 |
+
|
mgl@1371
|
19974 |
+ /* Check for subnormal result */
|
mgl@1371
|
19975 |
+ cp.w r10, 0
|
mgl@1371
|
19976 |
+ brle __avr32_u32_to_f32_subnormal
|
mgl@1371
|
19977 |
+
|
mgl@1371
|
19978 |
+ round_sf r10 /*exp*/, r12 /*mant*/, r9 /*scratch*/
|
mgl@1371
|
19979 |
+ pack_sf r12 /*sf*/, r10 /*exp*/, r12 /*mant*/
|
mgl@1371
|
19980 |
+ lsr r12,1 /* Sign bit is 0 for unsigned int */
|
mgl@1371
|
19981 |
+ ret r12
|
mgl@1371
|
19982 |
+
|
mgl@1371
|
19983 |
+__avr32_u32_to_f32_subnormal:
|
mgl@1371
|
19984 |
+ /* Adjust a subnormal result */
|
mgl@1371
|
19985 |
+ mov r8, 0
|
mgl@1371
|
19986 |
+ adjust_subnormal_sf r12/*sf*/,r10 /*exp*/, r12 /*mant*/,r8/*sign*/, r9 /*scratch*/
|
mgl@1371
|
19987 |
+ ret r12
|
mgl@1371
|
19988 |
+
|
mgl@1371
|
19989 |
+
|
mgl@1371
|
19990 |
+#endif
|
mgl@1371
|
19991 |
+
|
mgl@1371
|
19992 |
+
|
mgl@1371
|
19993 |
+#ifdef L_avr32_f32_to_s32
|
mgl@1371
|
19994 |
+ .global __avr32_f32_to_s32
|
mgl@1371
|
19995 |
+ .type __avr32_f32_to_s32,@function
|
mgl@1371
|
19996 |
+__avr32_f32_to_s32:
|
mgl@1371
|
19997 |
+ bfextu r11, r12, 23, 8
|
mgl@1371
|
19998 |
+ sub r11,127 /* Fix bias */
|
mgl@1371
|
19999 |
+ retlo 0 /* Negative exponent yields zero integer */
|
mgl@1371
|
20000 |
+
|
mgl@1371
|
20001 |
+ /* Shift mantissa into correct position */
|
mgl@1371
|
20002 |
+ rsub r11,r11,31 /* Shift amount */
|
mgl@1371
|
20003 |
+ lsl r10,r12,8 /* Get mantissa */
|
mgl@1371
|
20004 |
+ sbr r10,31 /* Add implicit bit */
|
mgl@1371
|
20005 |
+ lsr r10,r10,r11 /* Perform shift */
|
mgl@1371
|
20006 |
+ lsl r12,1 /* Check sign */
|
mgl@1371
|
20007 |
+ retcc r10 /* if positive, we are done */
|
mgl@1371
|
20008 |
+ neg r10 /* if negative float, negate result */
|
mgl@1371
|
20009 |
+ ret r10
|
mgl@1371
|
20010 |
+
|
mgl@1371
|
20011 |
+#endif
|
mgl@1371
|
20012 |
+
|
mgl@1371
|
20013 |
+#ifdef L_avr32_f32_to_u32
|
mgl@1371
|
20014 |
+ .global __avr32_f32_to_u32
|
mgl@1371
|
20015 |
+ .type __avr32_f32_to_u32,@function
|
mgl@1371
|
20016 |
+__avr32_f32_to_u32:
|
mgl@1371
|
20017 |
+ cp r12,0
|
mgl@1371
|
20018 |
+ retmi 0 /* Negative numbers gives 0 */
|
mgl@1371
|
20019 |
+ bfextu r11, r12, 23, 8 /* Extract exponent */
|
mgl@1371
|
20020 |
+ sub r11,127 /* Fix bias */
|
mgl@1371
|
20021 |
+ retlo 0 /* Negative exponent yields zero integer */
|
mgl@1371
|
20022 |
+
|
mgl@1371
|
20023 |
+ /* Shift mantissa into correct position */
|
mgl@1371
|
20024 |
+ rsub r11,r11,31 /* Shift amount */
|
mgl@1371
|
20025 |
+ lsl r12,8 /* Get mantissa */
|
mgl@1371
|
20026 |
+ sbr r12,31 /* Add implicit bit */
|
mgl@1371
|
20027 |
+ lsr r12,r12,r11 /* Perform shift */
|
mgl@1371
|
20028 |
+ ret r12
|
mgl@1371
|
20029 |
+
|
mgl@1371
|
20030 |
+#endif
|
mgl@1371
|
20031 |
+
|
mgl@1371
|
20032 |
+#ifdef L_avr32_f32_to_f64
|
mgl@1371
|
20033 |
+ .global __avr32_f32_to_f64
|
mgl@1371
|
20034 |
+ .type __avr32_f32_to_f64,@function
|
mgl@1371
|
20035 |
+
|
mgl@1371
|
20036 |
+__avr32_f32_to_f64:
|
mgl@1371
|
20037 |
+ lsl r11,r12,1 /* Remove sign bit, keep original value in r12*/
|
mgl@1371
|
20038 |
+ moveq r10, 0
|
mgl@1371
|
20039 |
+ reteq r11 /* Return zero if input is zero */
|
mgl@1371
|
20040 |
+
|
mgl@1371
|
20041 |
+ bfextu r9,r11,24,8 /* Get exponent */
|
mgl@1371
|
20042 |
+ cp.w r9,0xff /* check for NaN or inf */
|
mgl@1371
|
20043 |
+ breq 0f
|
mgl@1371
|
20044 |
+
|
mgl@1371
|
20045 |
+ lsl r11,7 /* Convert sf mantissa to df format */
|
mgl@1371
|
20046 |
+ mov r10,0
|
mgl@1371
|
20047 |
+
|
mgl@1371
|
20048 |
+ /* Check if implicit bit should be set */
|
mgl@1371
|
20049 |
+ cp.w r9, 0
|
mgl@1371
|
20050 |
+ subeq r9,-1 /* Adjust exponent if it was 0 */
|
mgl@1371
|
20051 |
+ srne r8
|
mgl@1371
|
20052 |
+ or r11, r11, r8 << 31 /* Set implicit bit if needed */
|
mgl@1371
|
20053 |
+ sub r9,(127-0x3ff) /* Convert exponent to df format exponent */
|
mgl@1371
|
20054 |
+
|
mgl@1371
|
20055 |
+ /*We know that low register of mantissa is 0, and will be unaffected by normalization.*/
|
mgl@1371
|
20056 |
+ /*We can therefore use the faster normalize_sf function instead of normalize_df.*/
|
mgl@1371
|
20057 |
+ normalize_sf r9 /*exp*/, r11 /*mantissa*/, r8 /*scratch*/
|
mgl@1371
|
20058 |
+ pack_df r9 /*exp*/, r10, r11 /*mantissa*/, r10, r11 /*df*/
|
mgl@1371
|
20059 |
+
|
mgl@1371
|
20060 |
+__extendsfdf_return_op1:
|
mgl@1371
|
20061 |
+ /* Rotate in sign bit */
|
mgl@1371
|
20062 |
+ lsl r12, 1
|
mgl@1371
|
20063 |
+ ror r11
|
mgl@1371
|
20064 |
+ ret r11
|
mgl@1371
|
20065 |
+
|
mgl@1371
|
20066 |
+0:
|
mgl@1371
|
20067 |
+ /* Inf or NaN*/
|
mgl@1371
|
20068 |
+ mov_imm r10, 0xffe00000
|
mgl@1371
|
20069 |
+ lsl r11,8 /* check mantissa */
|
mgl@1371
|
20070 |
+ movne r11, -1 /* Return NaN */
|
mgl@1371
|
20071 |
+ moveq r11, r10 /* Return inf */
|
mgl@1371
|
20072 |
+ rjmp __extendsfdf_return_op1
|
mgl@1371
|
20073 |
+#endif
|
mgl@1371
|
20074 |
+
|
mgl@1371
|
20075 |
+
|
mgl@1371
|
20076 |
+#ifdef L_avr32_f64_to_f32
|
mgl@1371
|
20077 |
+ .global __avr32_f64_to_f32
|
mgl@1371
|
20078 |
+ .type __avr32_f64_to_f32,@function
|
mgl@1371
|
20079 |
+
|
mgl@1371
|
20080 |
+__avr32_f64_to_f32:
|
mgl@1371
|
20081 |
+ /* Unpack */
|
mgl@1371
|
20082 |
+ lsl r9,r11,1 /* Unpack exponent */
|
mgl@1371
|
20083 |
+ lsr r9,21
|
mgl@1371
|
20084 |
+
|
mgl@1371
|
20085 |
+ reteq 0 /* If exponent is 0 the number is so small
|
mgl@1371
|
20086 |
+ that the conversion to single float gives
|
mgl@1371
|
20087 |
+ zero */
|
mgl@1371
|
20088 |
+
|
mgl@1371
|
20089 |
+ lsl r8,r11,10 /* Adjust mantissa */
|
mgl@1371
|
20090 |
+ or r12,r8,r10>>22
|
mgl@1371
|
20091 |
+
|
mgl@1371
|
20092 |
+ lsl r10,10 /* Check if there are any remaining bits
|
mgl@1371
|
20093 |
+ in the low part of the mantissa.*/
|
mgl@1371
|
20094 |
+ neg r10
|
mgl@1371
|
20095 |
+ rol r12 /* If there were remaining bits then set lsb
|
mgl@1371
|
20096 |
+ of mantissa to 1 */
|
mgl@1371
|
20097 |
+
|
mgl@1371
|
20098 |
+ cp r9,0x7ff
|
mgl@1371
|
20099 |
+ breq 2f /* Check for NaN or inf */
|
mgl@1371
|
20100 |
+
|
mgl@1371
|
20101 |
+ sub r9,(0x3ff-127) /* Adjust bias of exponent */
|
mgl@1371
|
20102 |
+ sbr r12,31 /* set the implicit bit.*/
|
mgl@1371
|
20103 |
+
|
mgl@1371
|
20104 |
+ cp.w r9, 0 /* Check for subnormal number */
|
mgl@1371
|
20105 |
+ brle 3f
|
mgl@1371
|
20106 |
+
|
mgl@1371
|
20107 |
+ round_sf r9 /*exp*/, r12 /*mant*/, r10 /*scratch*/
|
mgl@1371
|
20108 |
+ pack_sf r12 /*sf*/, r9 /*exp*/, r12 /*mant*/
|
mgl@1371
|
20109 |
+__truncdfsf_return_op1:
|
mgl@1371
|
20110 |
+ /* Rotate in sign bit */
|
mgl@1371
|
20111 |
+ lsl r11, 1
|
mgl@1371
|
20112 |
+ ror r12
|
mgl@1371
|
20113 |
+ ret r12
|
mgl@1371
|
20114 |
+
|
mgl@1371
|
20115 |
+2:
|
mgl@1371
|
20116 |
+ /* NaN or inf */
|
mgl@1371
|
20117 |
+ cbr r12,31 /* clear implicit bit */
|
mgl@1371
|
20118 |
+ retne -1 /* Return NaN if mantissa not zero */
|
mgl@1371
|
20119 |
+ mov_imm r12, 0xff000000
|
mgl@1371
|
20120 |
+ ret r12 /* Return inf */
|
mgl@1371
|
20121 |
+
|
mgl@1371
|
20122 |
+3: /* Result is subnormal. Adjust it.*/
|
mgl@1371
|
20123 |
+ adjust_subnormal_sf r12/*sf*/,r9 /*exp*/, r12 /*mant*/, r11/*sign*/, r10 /*scratch*/
|
mgl@1371
|
20124 |
+ ret r12
|
mgl@1371
|
20125 |
+
|
mgl@1371
|
20126 |
+
|
mgl@1371
|
20127 |
+#endif
|
mgl@1371
|
20128 |
+
|
mgl@1371
|
20129 |
+#if defined(L_mulsi3) && (__AVR32_UC__ == 3)
|
mgl@1371
|
20130 |
+ .global __mulsi3
|
mgl@1371
|
20131 |
+ .type __mulsi3,@function
|
mgl@1371
|
20132 |
+
|
mgl@1371
|
20133 |
+__mulsi3:
|
mgl@1371
|
20134 |
+ mov r9, 0
|
mgl@1371
|
20135 |
+0:
|
mgl@1371
|
20136 |
+ lsr r11, 1
|
mgl@1371
|
20137 |
+ addcs r9, r9, r12
|
mgl@1371
|
20138 |
+ breq 1f
|
mgl@1371
|
20139 |
+ lsl r12, 1
|
mgl@1371
|
20140 |
+ rjmp 0b
|
mgl@1371
|
20141 |
+1:
|
mgl@1371
|
20142 |
+ ret r9
|
mgl@1371
|
20143 |
+#endif
|
mgl@1371
|
20144 |
--- /dev/null
|
mgl@1371
|
20145 |
+++ b/gcc/config/avr32/lib2funcs.S
|
mgl@1371
|
20146 |
@@ -0,0 +1,21 @@
|
mgl@1371
|
20147 |
+ .align 4
|
mgl@1371
|
20148 |
+ .global __nonlocal_goto
|
mgl@1371
|
20149 |
+ .type __nonlocal_goto,@function
|
mgl@1371
|
20150 |
+
|
mgl@1371
|
20151 |
+/* __nonlocal_goto: This function handles nonlocal_goto's in gcc.
|
mgl@1371
|
20152 |
+
|
mgl@1371
|
20153 |
+ parameter 0 (r12) = New Frame Pointer
|
mgl@1371
|
20154 |
+ parameter 1 (r11) = Address to goto
|
mgl@1371
|
20155 |
+ parameter 2 (r10) = New Stack Pointer
|
mgl@1371
|
20156 |
+
|
mgl@1371
|
20157 |
+ This function invalidates the return stack, since it returns from a
|
mgl@1371
|
20158 |
+ function without using a return instruction.
|
mgl@1371
|
20159 |
+*/
|
mgl@1371
|
20160 |
+__nonlocal_goto:
|
mgl@1371
|
20161 |
+ mov r7, r12
|
mgl@1371
|
20162 |
+ mov sp, r10
|
mgl@1371
|
20163 |
+ frs # Flush return stack
|
mgl@1371
|
20164 |
+ mov pc, r11
|
mgl@1371
|
20165 |
+
|
mgl@1371
|
20166 |
+
|
mgl@1371
|
20167 |
+
|
mgl@1371
|
20168 |
--- /dev/null
|
mgl@1371
|
20169 |
+++ b/gcc/config/avr32/linux-elf.h
|
mgl@1371
|
20170 |
@@ -0,0 +1,151 @@
|
mgl@1371
|
20171 |
+/*
|
mgl@1371
|
20172 |
+ Linux/Elf specific definitions.
|
mgl@1371
|
20173 |
+ Copyright 2003-2006 Atmel Corporation.
|
mgl@1371
|
20174 |
+
|
mgl@1371
|
20175 |
+ Written by Ronny Pedersen, Atmel Norway, <rpedersen@atmel.com>
|
mgl@1371
|
20176 |
+ and H�vard Skinnemoen, Atmel Norway, <hskinnemoen@atmel.com>
|
mgl@1371
|
20177 |
+
|
mgl@1371
|
20178 |
+ This file is part of GCC.
|
mgl@1371
|
20179 |
+
|
mgl@1371
|
20180 |
+ This program is free software; you can redistribute it and/or modify
|
mgl@1371
|
20181 |
+ it under the terms of the GNU General Public License as published by
|
mgl@1371
|
20182 |
+ the Free Software Foundation; either version 2 of the License, or
|
mgl@1371
|
20183 |
+ (at your option) any later version.
|
mgl@1371
|
20184 |
+
|
mgl@1371
|
20185 |
+ This program is distributed in the hope that it will be useful,
|
mgl@1371
|
20186 |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
mgl@1371
|
20187 |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
mgl@1371
|
20188 |
+ GNU General Public License for more details.
|
mgl@1371
|
20189 |
+
|
mgl@1371
|
20190 |
+ You should have received a copy of the GNU General Public License
|
mgl@1371
|
20191 |
+ along with this program; if not, write to the Free Software
|
mgl@1371
|
20192 |
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
mgl@1371
|
20193 |
+
|
mgl@1371
|
20194 |
+
|
mgl@1371
|
20195 |
+
|
mgl@1371
|
20196 |
+/* elfos.h should have already been included. Now just override
|
mgl@1371
|
20197 |
+ any conflicting definitions and add any extras. */
|
mgl@1371
|
20198 |
+
|
mgl@1371
|
20199 |
+/* Run-time Target Specification. */
|
mgl@1371
|
20200 |
+#undef TARGET_VERSION
|
mgl@1371
|
20201 |
+#define TARGET_VERSION fputs (" (AVR32 GNU/Linux with ELF)", stderr);
|
mgl@1371
|
20202 |
+
|
mgl@1371
|
20203 |
+/* Do not assume anything about header files. */
|
mgl@1371
|
20204 |
+#define NO_IMPLICIT_EXTERN_C
|
mgl@1371
|
20205 |
+
|
mgl@1371
|
20206 |
+/* The GNU C++ standard library requires that these macros be defined. */
|
mgl@1371
|
20207 |
+#undef CPLUSPLUS_CPP_SPEC
|
mgl@1371
|
20208 |
+#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
|
mgl@1371
|
20209 |
+
|
mgl@1371
|
20210 |
+/* Now we define the strings used to build the spec file. */
|
mgl@1371
|
20211 |
+#undef LIB_SPEC
|
mgl@1371
|
20212 |
+#define LIB_SPEC \
|
mgl@1371
|
20213 |
+ "%{pthread:-lpthread} \
|
mgl@1371
|
20214 |
+ %{shared:-lc} \
|
mgl@1371
|
20215 |
+ %{!shared:%{profile:-lc_p}%{!profile:-lc}}"
|
mgl@1371
|
20216 |
+
|
mgl@1371
|
20217 |
+/* Provide a STARTFILE_SPEC appropriate for GNU/Linux. Here we add
|
mgl@1371
|
20218 |
+ the GNU/Linux magical crtbegin.o file (see crtstuff.c) which
|
mgl@1371
|
20219 |
+ provides part of the support for getting C++ file-scope static
|
mgl@1371
|
20220 |
+ object constructed before entering `main'. */
|
mgl@1371
|
20221 |
+
|
mgl@1371
|
20222 |
+#undef STARTFILE_SPEC
|
mgl@1371
|
20223 |
+#define STARTFILE_SPEC \
|
mgl@1371
|
20224 |
+ "%{!shared: \
|
mgl@1371
|
20225 |
+ %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} \
|
mgl@1371
|
20226 |
+ %{!p:%{profile:gcrt1.o%s} \
|
mgl@1371
|
20227 |
+ %{!profile:crt1.o%s}}}} \
|
mgl@1371
|
20228 |
+ crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}"
|
mgl@1371
|
20229 |
+
|
mgl@1371
|
20230 |
+/* Provide a ENDFILE_SPEC appropriate for GNU/Linux. Here we tack on
|
mgl@1371
|
20231 |
+ the GNU/Linux magical crtend.o file (see crtstuff.c) which
|
mgl@1371
|
20232 |
+ provides part of the support for getting C++ file-scope static
|
mgl@1371
|
20233 |
+ object constructed before entering `main', followed by a normal
|
mgl@1371
|
20234 |
+ GNU/Linux "finalizer" file, `crtn.o'. */
|
mgl@1371
|
20235 |
+
|
mgl@1371
|
20236 |
+#undef ENDFILE_SPEC
|
mgl@1371
|
20237 |
+#define ENDFILE_SPEC \
|
mgl@1371
|
20238 |
+ "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s"
|
mgl@1371
|
20239 |
+
|
mgl@1371
|
20240 |
+#undef ASM_SPEC
|
mgl@1371
|
20241 |
+#define ASM_SPEC "%{!mno-pic:%{!fno-pic:--pic}} %{mrelax|O*:%{mno-relax|O0|O1: ;:--linkrelax}} %{mcpu=*:-mcpu=%*}"
|
mgl@1371
|
20242 |
+
|
mgl@1371
|
20243 |
+#undef LINK_SPEC
|
mgl@1371
|
20244 |
+#define LINK_SPEC "%{version:-v} \
|
mgl@1371
|
20245 |
+ %{static:-Bstatic} \
|
mgl@1371
|
20246 |
+ %{shared:-shared} \
|
mgl@1371
|
20247 |
+ %{symbolic:-Bsymbolic} \
|
mgl@1371
|
20248 |
+ %{rdynamic:-export-dynamic} \
|
mgl@1371
|
20249 |
+ %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0} \
|
mgl@1371
|
20250 |
+ %{mrelax|O*:%{mno-relax|O0|O1: ;:--relax}}"
|
mgl@1371
|
20251 |
+
|
mgl@1371
|
20252 |
+#define TARGET_OS_CPP_BUILTINS() LINUX_TARGET_OS_CPP_BUILTINS()
|
mgl@1371
|
20253 |
+
|
mgl@1371
|
20254 |
+/* This is how we tell the assembler that two symbols have the same value. */
|
mgl@1371
|
20255 |
+#define ASM_OUTPUT_DEF(FILE, NAME1, NAME2) \
|
mgl@1371
|
20256 |
+ do \
|
mgl@1371
|
20257 |
+ { \
|
mgl@1371
|
20258 |
+ assemble_name (FILE, NAME1); \
|
mgl@1371
|
20259 |
+ fputs (" = ", FILE); \
|
mgl@1371
|
20260 |
+ assemble_name (FILE, NAME2); \
|
mgl@1371
|
20261 |
+ fputc ('\n', FILE); \
|
mgl@1371
|
20262 |
+ } \
|
mgl@1371
|
20263 |
+ while (0)
|
mgl@1371
|
20264 |
+
|
mgl@1371
|
20265 |
+
|
mgl@1371
|
20266 |
+
|
mgl@1371
|
20267 |
+#undef CC1_SPEC
|
mgl@1371
|
20268 |
+#define CC1_SPEC "%{profile:-p}"
|
mgl@1371
|
20269 |
+
|
mgl@1371
|
20270 |
+/* Target CPU builtins. */
|
mgl@1371
|
20271 |
+#define TARGET_CPU_CPP_BUILTINS() \
|
mgl@1371
|
20272 |
+ do \
|
mgl@1371
|
20273 |
+ { \
|
mgl@1371
|
20274 |
+ builtin_define ("__avr32__"); \
|
mgl@1371
|
20275 |
+ builtin_define ("__AVR32__"); \
|
mgl@1371
|
20276 |
+ builtin_define ("__AVR32_LINUX__"); \
|
mgl@1371
|
20277 |
+ builtin_define (avr32_part->macro); \
|
mgl@1371
|
20278 |
+ builtin_define (avr32_arch->macro); \
|
mgl@1371
|
20279 |
+ if (avr32_arch->uarch_type == UARCH_TYPE_AVR32A) \
|
mgl@1371
|
20280 |
+ builtin_define ("__AVR32_AVR32A__"); \
|
mgl@1371
|
20281 |
+ else \
|
mgl@1371
|
20282 |
+ builtin_define ("__AVR32_AVR32B__"); \
|
mgl@1371
|
20283 |
+ if (TARGET_UNALIGNED_WORD) \
|
mgl@1371
|
20284 |
+ builtin_define ("__AVR32_HAS_UNALIGNED_WORD__"); \
|
mgl@1371
|
20285 |
+ if (TARGET_SIMD) \
|
mgl@1371
|
20286 |
+ builtin_define ("__AVR32_HAS_SIMD__"); \
|
mgl@1371
|
20287 |
+ if (TARGET_DSP) \
|
mgl@1371
|
20288 |
+ builtin_define ("__AVR32_HAS_DSP__"); \
|
mgl@1371
|
20289 |
+ if (TARGET_RMW) \
|
mgl@1371
|
20290 |
+ builtin_define ("__AVR32_HAS_RMW__"); \
|
mgl@1371
|
20291 |
+ if (TARGET_BRANCH_PRED) \
|
mgl@1371
|
20292 |
+ builtin_define ("__AVR32_HAS_BRANCH_PRED__"); \
|
mgl@1371
|
20293 |
+ if (TARGET_FAST_FLOAT) \
|
mgl@1371
|
20294 |
+ builtin_define ("__AVR32_FAST_FLOAT__"); \
|
mgl@1371
|
20295 |
+ } \
|
mgl@1371
|
20296 |
+ while (0)
|
mgl@1371
|
20297 |
+
|
mgl@1371
|
20298 |
+
|
mgl@1371
|
20299 |
+
|
mgl@1371
|
20300 |
+/* Call the function profiler with a given profile label. */
|
mgl@1371
|
20301 |
+#undef FUNCTION_PROFILER
|
mgl@1371
|
20302 |
+#define FUNCTION_PROFILER(STREAM, LABELNO) \
|
mgl@1371
|
20303 |
+ do \
|
mgl@1371
|
20304 |
+ { \
|
mgl@1371
|
20305 |
+ fprintf (STREAM, "\tmov\tlr, lo(mcount)\n\torh\tlr, hi(mcount)\n"); \
|
mgl@1371
|
20306 |
+ fprintf (STREAM, "\ticall lr\n"); \
|
mgl@1371
|
20307 |
+ } \
|
mgl@1371
|
20308 |
+ while (0)
|
mgl@1371
|
20309 |
+
|
mgl@1371
|
20310 |
+#define NO_PROFILE_COUNTERS 1
|
mgl@1371
|
20311 |
+
|
mgl@1371
|
20312 |
+/* For dynamic libraries to work */
|
mgl@1371
|
20313 |
+/* #define PLT_REG_CALL_CLOBBERED 1 */
|
mgl@1371
|
20314 |
+#define AVR32_ALWAYS_PIC 1
|
mgl@1371
|
20315 |
+
|
mgl@1371
|
20316 |
+/* uclibc does not implement sinf, cosf etc. */
|
mgl@1371
|
20317 |
+#undef TARGET_C99_FUNCTIONS
|
mgl@1371
|
20318 |
+#define TARGET_C99_FUNCTIONS 0
|
mgl@1371
|
20319 |
+
|
mgl@1371
|
20320 |
+#define LINK_GCC_C_SEQUENCE_SPEC \
|
mgl@1371
|
20321 |
+ "%{static:--start-group} %G %L %{static:--end-group}%{!static:%G}"
|
mgl@1371
|
20322 |
--- /dev/null
|
mgl@1371
|
20323 |
+++ b/gcc/config/avr32/predicates.md
|
mgl@1371
|
20324 |
@@ -0,0 +1,419 @@
|
mgl@1371
|
20325 |
+;; AVR32 predicates file.
|
mgl@1371
|
20326 |
+;; Copyright 2003-2006 Atmel Corporation.
|
mgl@1371
|
20327 |
+;;
|
mgl@1371
|
20328 |
+;; Written by Ronny Pedersen, Atmel Norway, <rpedersen@atmel.com>
|
mgl@1371
|
20329 |
+;;
|
mgl@1371
|
20330 |
+;; This file is part of GCC.
|
mgl@1371
|
20331 |
+;;
|
mgl@1371
|
20332 |
+;; This program is free software; you can redistribute it and/or modify
|
mgl@1371
|
20333 |
+;; it under the terms of the GNU General Public License as published by
|
mgl@1371
|
20334 |
+;; the Free Software Foundation; either version 2 of the License, or
|
mgl@1371
|
20335 |
+;; (at your option) any later version.
|
mgl@1371
|
20336 |
+;;
|
mgl@1371
|
20337 |
+;; This program is distributed in the hope that it will be useful,
|
mgl@1371
|
20338 |
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
mgl@1371
|
20339 |
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
mgl@1371
|
20340 |
+;; GNU General Public License for more details.
|
mgl@1371
|
20341 |
+;;
|
mgl@1371
|
20342 |
+;; You should have received a copy of the GNU General Public License
|
mgl@1371
|
20343 |
+;; along with this program; if not, write to the Free Software
|
mgl@1371
|
20344 |
+;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
mgl@1371
|
20345 |
+
|
mgl@1371
|
20346 |
+
|
mgl@1371
|
20347 |
+;; True if the operand is a memory reference which contains an
|
mgl@1371
|
20348 |
+;; Address consisting of a single pointer register
|
mgl@1371
|
20349 |
+(define_predicate "avr32_indirect_register_operand"
|
mgl@1371
|
20350 |
+ (and (match_code "mem")
|
mgl@1371
|
20351 |
+ (match_test "register_operand(XEXP(op, 0), SImode)")))
|
mgl@1371
|
20352 |
+
|
mgl@1371
|
20353 |
+
|
mgl@1371
|
20354 |
+
|
mgl@1371
|
20355 |
+;; Address expression with a base pointer offset with
|
mgl@1371
|
20356 |
+;; a register displacement
|
mgl@1371
|
20357 |
+(define_predicate "avr32_indexed_memory_operand"
|
mgl@1371
|
20358 |
+ (and (match_code "mem")
|
mgl@1371
|
20359 |
+ (match_test "GET_CODE(XEXP(op, 0)) == PLUS"))
|
mgl@1371
|
20360 |
+ {
|
mgl@1371
|
20361 |
+
|
mgl@1371
|
20362 |
+ rtx op0 = XEXP(XEXP(op, 0), 0);
|
mgl@1371
|
20363 |
+ rtx op1 = XEXP(XEXP(op, 0), 1);
|
mgl@1371
|
20364 |
+
|
mgl@1371
|
20365 |
+ return ((avr32_address_register_rtx_p (op0, 0)
|
mgl@1371
|
20366 |
+ && avr32_legitimate_index_p (GET_MODE(op), op1, 0))
|
mgl@1371
|
20367 |
+ || (avr32_address_register_rtx_p (op1, 0)
|
mgl@1371
|
20368 |
+ && avr32_legitimate_index_p (GET_MODE(op), op0, 0)));
|
mgl@1371
|
20369 |
+
|
mgl@1371
|
20370 |
+ })
|
mgl@1371
|
20371 |
+
|
mgl@1371
|
20372 |
+;; Operand suitable for the ld.sb instruction
|
mgl@1371
|
20373 |
+(define_predicate "load_sb_memory_operand"
|
mgl@1371
|
20374 |
+ (ior (match_operand 0 "avr32_indirect_register_operand")
|
mgl@1371
|
20375 |
+ (match_operand 0 "avr32_indexed_memory_operand")))
|
mgl@1371
|
20376 |
+
|
mgl@1371
|
20377 |
+
|
mgl@1371
|
20378 |
+;; Operand suitable as operand to insns sign extending QI values
|
mgl@1371
|
20379 |
+(define_predicate "extendqi_operand"
|
mgl@1371
|
20380 |
+ (ior (match_operand 0 "load_sb_memory_operand")
|
mgl@1371
|
20381 |
+ (match_operand 0 "register_operand")))
|
mgl@1371
|
20382 |
+
|
mgl@1371
|
20383 |
+(define_predicate "post_inc_memory_operand"
|
mgl@1371
|
20384 |
+ (and (match_code "mem")
|
mgl@1371
|
20385 |
+ (match_test "(GET_CODE(XEXP(op, 0)) == POST_INC)
|
mgl@1371
|
20386 |
+ && REG_P(XEXP(XEXP(op, 0), 0))")))
|
mgl@1371
|
20387 |
+
|
mgl@1371
|
20388 |
+(define_predicate "pre_dec_memory_operand"
|
mgl@1371
|
20389 |
+ (and (match_code "mem")
|
mgl@1371
|
20390 |
+ (match_test "(GET_CODE(XEXP(op, 0)) == PRE_DEC)
|
mgl@1371
|
20391 |
+ && REG_P(XEXP(XEXP(op, 0), 0))")))
|
mgl@1371
|
20392 |
+
|
mgl@1371
|
20393 |
+;; Operand suitable for add instructions
|
mgl@1371
|
20394 |
+(define_predicate "avr32_add_operand"
|
mgl@1371
|
20395 |
+ (ior (match_operand 0 "register_operand")
|
mgl@1371
|
20396 |
+ (and (match_operand 0 "immediate_operand")
|
mgl@1371
|
20397 |
+ (match_test "CONST_OK_FOR_CONSTRAINT_P(INTVAL(op), 'I', \"Is21\")"))))
|
mgl@1371
|
20398 |
+
|
mgl@1371
|
20399 |
+;; Operand is a power of two immediate
|
mgl@1371
|
20400 |
+(define_predicate "power_of_two_operand"
|
mgl@1371
|
20401 |
+ (match_code "const_int")
|
mgl@1371
|
20402 |
+{
|
mgl@1371
|
20403 |
+ HOST_WIDE_INT value = INTVAL (op);
|
mgl@1371
|
20404 |
+
|
mgl@1371
|
20405 |
+ return value != 0 && (value & (value - 1)) == 0;
|
mgl@1371
|
20406 |
+})
|
mgl@1371
|
20407 |
+
|
mgl@1371
|
20408 |
+;; Operand is a multiple of 8 immediate
|
mgl@1371
|
20409 |
+(define_predicate "multiple_of_8_operand"
|
mgl@1371
|
20410 |
+ (match_code "const_int")
|
mgl@1371
|
20411 |
+{
|
mgl@1371
|
20412 |
+ HOST_WIDE_INT value = INTVAL (op);
|
mgl@1371
|
20413 |
+
|
mgl@1371
|
20414 |
+ return (value & 0x7) == 0 ;
|
mgl@1371
|
20415 |
+})
|
mgl@1371
|
20416 |
+
|
mgl@1371
|
20417 |
+;; Operand is a multiple of 16 immediate
|
mgl@1371
|
20418 |
+(define_predicate "multiple_of_16_operand"
|
mgl@1371
|
20419 |
+ (match_code "const_int")
|
mgl@1371
|
20420 |
+{
|
mgl@1371
|
20421 |
+ HOST_WIDE_INT value = INTVAL (op);
|
mgl@1371
|
20422 |
+
|
mgl@1371
|
20423 |
+ return (value & 0xf) == 0 ;
|
mgl@1371
|
20424 |
+})
|
mgl@1371
|
20425 |
+
|
mgl@1371
|
20426 |
+;; Operand is a mask used for masking away upper bits of a reg
|
mgl@1371
|
20427 |
+(define_predicate "avr32_mask_upper_bits_operand"
|
mgl@1371
|
20428 |
+ (match_code "const_int")
|
mgl@1371
|
20429 |
+{
|
mgl@1371
|
20430 |
+ HOST_WIDE_INT value = INTVAL (op) + 1;
|
mgl@1371
|
20431 |
+
|
mgl@1371
|
20432 |
+ return value != 1 && value != 0 && (value & (value - 1)) == 0;
|
mgl@1371
|
20433 |
+})
|
mgl@1371
|
20434 |
+
|
mgl@1371
|
20435 |
+
|
mgl@1371
|
20436 |
+;; Operand suitable for mul instructions
|
mgl@1371
|
20437 |
+(define_predicate "avr32_mul_operand"
|
mgl@1371
|
20438 |
+ (ior (match_operand 0 "register_operand")
|
mgl@1371
|
20439 |
+ (and (match_operand 0 "immediate_operand")
|
mgl@1371
|
20440 |
+ (match_test "CONST_OK_FOR_CONSTRAINT_P(INTVAL(op), 'K', \"Ks08\")"))))
|
mgl@1371
|
20441 |
+
|
mgl@1371
|
20442 |
+;; True for logical binary operators.
|
mgl@1371
|
20443 |
+(define_predicate "logical_binary_operator"
|
mgl@1371
|
20444 |
+ (match_code "ior,xor,and"))
|
mgl@1371
|
20445 |
+
|
mgl@1371
|
20446 |
+;; True for logical shift operators
|
mgl@1371
|
20447 |
+(define_predicate "logical_shift_operator"
|
mgl@1371
|
20448 |
+ (match_code "ashift,lshiftrt"))
|
mgl@1371
|
20449 |
+
|
mgl@1371
|
20450 |
+;; True for shift operand for logical and, or and eor insns
|
mgl@1371
|
20451 |
+(define_predicate "avr32_logical_shift_operand"
|
mgl@1371
|
20452 |
+ (and (match_code "ashift,lshiftrt")
|
mgl@1371
|
20453 |
+ (ior (and (match_test "GET_CODE(XEXP(op, 1)) == CONST_INT")
|
mgl@1371
|
20454 |
+ (match_test "register_operand(XEXP(op, 0), GET_MODE(XEXP(op, 0)))"))
|
mgl@1371
|
20455 |
+ (and (match_test "GET_CODE(XEXP(op, 0)) == CONST_INT")
|
mgl@1371
|
20456 |
+ (match_test "register_operand(XEXP(op, 1), GET_MODE(XEXP(op, 1)))"))))
|
mgl@1371
|
20457 |
+ )
|
mgl@1371
|
20458 |
+
|
mgl@1371
|
20459 |
+
|
mgl@1371
|
20460 |
+;; Predicate for second operand to and, ior and xor insn patterns
|
mgl@1371
|
20461 |
+(define_predicate "avr32_logical_insn_operand"
|
mgl@1371
|
20462 |
+ (ior (match_operand 0 "register_operand")
|
mgl@1371
|
20463 |
+ (match_operand 0 "avr32_logical_shift_operand"))
|
mgl@1371
|
20464 |
+)
|
mgl@1371
|
20465 |
+
|
mgl@1371
|
20466 |
+
|
mgl@1371
|
20467 |
+;; True for avr32 comparison operators
|
mgl@1371
|
20468 |
+(define_predicate "avr32_comparison_operator"
|
mgl@1371
|
20469 |
+ (ior (match_code "eq, ne, gt, ge, lt, le, gtu, geu, ltu, leu")
|
mgl@1371
|
20470 |
+ (and (match_code "unspec")
|
mgl@1371
|
20471 |
+ (match_test "(XINT(op, 1) == UNSPEC_COND_MI)
|
mgl@1371
|
20472 |
+ || (XINT(op, 1) == UNSPEC_COND_PL)"))))
|
mgl@1371
|
20473 |
+
|
mgl@1371
|
20474 |
+(define_predicate "avr32_cond3_comparison_operator"
|
mgl@1371
|
20475 |
+ (ior (match_code "eq, ne, ge, lt, geu, ltu")
|
mgl@1371
|
20476 |
+ (and (match_code "unspec")
|
mgl@1371
|
20477 |
+ (match_test "(XINT(op, 1) == UNSPEC_COND_MI)
|
mgl@1371
|
20478 |
+ || (XINT(op, 1) == UNSPEC_COND_PL)"))))
|
mgl@1371
|
20479 |
+
|
mgl@1371
|
20480 |
+;; True for avr32 comparison operand
|
mgl@1371
|
20481 |
+(define_predicate "avr32_comparison_operand"
|
mgl@1371
|
20482 |
+ (ior (and (match_code "eq, ne, gt, ge, lt, le, gtu, geu, ltu, leu")
|
mgl@1371
|
20483 |
+ (match_test "(CC0_P (XEXP(op,0)) && rtx_equal_p (XEXP(op,1), const0_rtx))"))
|
mgl@1371
|
20484 |
+ (and (match_code "unspec")
|
mgl@1371
|
20485 |
+ (match_test "(XINT(op, 1) == UNSPEC_COND_MI)
|
mgl@1371
|
20486 |
+ || (XINT(op, 1) == UNSPEC_COND_PL)"))))
|
mgl@1371
|
20487 |
+
|
mgl@1371
|
20488 |
+;; True if this is a const_int with one bit set
|
mgl@1371
|
20489 |
+(define_predicate "one_bit_set_operand"
|
mgl@1371
|
20490 |
+ (match_code "const_int")
|
mgl@1371
|
20491 |
+ {
|
mgl@1371
|
20492 |
+ int i;
|
mgl@1371
|
20493 |
+ int value;
|
mgl@1371
|
20494 |
+ int ones = 0;
|
mgl@1371
|
20495 |
+
|
mgl@1371
|
20496 |
+ value = INTVAL(op);
|
mgl@1371
|
20497 |
+ for ( i = 0 ; i < 32; i++ ){
|
mgl@1371
|
20498 |
+ if ( value & ( 1 << i ) ){
|
mgl@1371
|
20499 |
+ ones++;
|
mgl@1371
|
20500 |
+ }
|
mgl@1371
|
20501 |
+ }
|
mgl@1371
|
20502 |
+
|
mgl@1371
|
20503 |
+ return ( ones == 1 );
|
mgl@1371
|
20504 |
+ })
|
mgl@1371
|
20505 |
+
|
mgl@1371
|
20506 |
+
|
mgl@1371
|
20507 |
+;; True if this is a const_int with one bit cleared
|
mgl@1371
|
20508 |
+(define_predicate "one_bit_cleared_operand"
|
mgl@1371
|
20509 |
+ (match_code "const_int")
|
mgl@1371
|
20510 |
+ {
|
mgl@1371
|
20511 |
+ int i;
|
mgl@1371
|
20512 |
+ int value;
|
mgl@1371
|
20513 |
+ int zeroes = 0;
|
mgl@1371
|
20514 |
+
|
mgl@1371
|
20515 |
+ value = INTVAL(op);
|
mgl@1371
|
20516 |
+ for ( i = 0 ; i < 32; i++ ){
|
mgl@1371
|
20517 |
+ if ( !(value & ( 1 << i )) ){
|
mgl@1371
|
20518 |
+ zeroes++;
|
mgl@1371
|
20519 |
+ }
|
mgl@1371
|
20520 |
+ }
|
mgl@1371
|
20521 |
+
|
mgl@1371
|
20522 |
+ return ( zeroes == 1 );
|
mgl@1371
|
20523 |
+ })
|
mgl@1371
|
20524 |
+
|
mgl@1371
|
20525 |
+
|
mgl@1371
|
20526 |
+;; Immediate all the low 16-bits cleared
|
mgl@1371
|
20527 |
+(define_predicate "avr32_hi16_immediate_operand"
|
mgl@1371
|
20528 |
+ (match_code "const_int")
|
mgl@1371
|
20529 |
+ {
|
mgl@1371
|
20530 |
+ /* If the low 16-bits are zero then this
|
mgl@1371
|
20531 |
+ is a hi16 immediate. */
|
mgl@1371
|
20532 |
+ return ((INTVAL(op) & 0xffff) == 0);
|
mgl@1371
|
20533 |
+ }
|
mgl@1371
|
20534 |
+)
|
mgl@1371
|
20535 |
+
|
mgl@1371
|
20536 |
+;; True if this is a register or immediate operand
|
mgl@1371
|
20537 |
+(define_predicate "register_immediate_operand"
|
mgl@1371
|
20538 |
+ (ior (match_operand 0 "register_operand")
|
mgl@1371
|
20539 |
+ (match_operand 0 "immediate_operand")))
|
mgl@1371
|
20540 |
+
|
mgl@1371
|
20541 |
+;; True if this is a register or const_int operand
|
mgl@1371
|
20542 |
+(define_predicate "register_const_int_operand"
|
mgl@1371
|
20543 |
+ (ior (match_operand 0 "register_operand")
|
mgl@1371
|
20544 |
+ (and (match_operand 0 "const_int_operand")
|
mgl@1371
|
20545 |
+ (match_operand 0 "immediate_operand"))))
|
mgl@1371
|
20546 |
+
|
mgl@1371
|
20547 |
+;; True if this is a register or const_double operand
|
mgl@1371
|
20548 |
+(define_predicate "register_const_double_operand"
|
mgl@1371
|
20549 |
+ (ior (match_operand 0 "register_operand")
|
mgl@1371
|
20550 |
+ (match_operand 0 "const_double_operand")))
|
mgl@1371
|
20551 |
+
|
mgl@1371
|
20552 |
+;; True is this is an operand containing a label_ref
|
mgl@1371
|
20553 |
+(define_predicate "avr32_label_ref_operand"
|
mgl@1371
|
20554 |
+ (and (match_code "mem")
|
mgl@1371
|
20555 |
+ (match_test "avr32_find_symbol(op)
|
mgl@1371
|
20556 |
+ && (GET_CODE(avr32_find_symbol(op)) == LABEL_REF)")))
|
mgl@1371
|
20557 |
+
|
mgl@1371
|
20558 |
+;; True is this is a valid symbol pointing to the constant pool
|
mgl@1371
|
20559 |
+(define_predicate "avr32_const_pool_operand"
|
mgl@1371
|
20560 |
+ (and (match_code "symbol_ref")
|
mgl@1371
|
20561 |
+ (match_test "CONSTANT_POOL_ADDRESS_P(op)"))
|
mgl@1371
|
20562 |
+ {
|
mgl@1371
|
20563 |
+ return (flag_pic ? (!(symbol_mentioned_p (get_pool_constant (op))
|
mgl@1371
|
20564 |
+ || label_mentioned_p (get_pool_constant (op)))
|
mgl@1371
|
20565 |
+ || avr32_got_mentioned_p(get_pool_constant (op)))
|
mgl@1371
|
20566 |
+ : true);
|
mgl@1371
|
20567 |
+ }
|
mgl@1371
|
20568 |
+)
|
mgl@1371
|
20569 |
+
|
mgl@1371
|
20570 |
+;; True is this is a memory reference to the constant or mini pool
|
mgl@1371
|
20571 |
+(define_predicate "avr32_const_pool_ref_operand"
|
mgl@1371
|
20572 |
+ (ior (match_operand 0 "avr32_label_ref_operand")
|
mgl@1371
|
20573 |
+ (and (match_code "mem")
|
mgl@1371
|
20574 |
+ (match_test "avr32_const_pool_operand(XEXP(op,0), GET_MODE(XEXP(op,0)))"))))
|
mgl@1371
|
20575 |
+
|
mgl@1371
|
20576 |
+
|
mgl@1371
|
20577 |
+;; Legal source operand for movti insns
|
mgl@1371
|
20578 |
+(define_predicate "avr32_movti_src_operand"
|
mgl@1371
|
20579 |
+ (ior (match_operand 0 "avr32_const_pool_ref_operand")
|
mgl@1371
|
20580 |
+ (ior (ior (match_operand 0 "register_immediate_operand")
|
mgl@1371
|
20581 |
+ (match_operand 0 "avr32_indirect_register_operand"))
|
mgl@1371
|
20582 |
+ (match_operand 0 "post_inc_memory_operand"))))
|
mgl@1371
|
20583 |
+
|
mgl@1371
|
20584 |
+;; Legal destination operand for movti insns
|
mgl@1371
|
20585 |
+(define_predicate "avr32_movti_dst_operand"
|
mgl@1371
|
20586 |
+ (ior (ior (match_operand 0 "register_operand")
|
mgl@1371
|
20587 |
+ (match_operand 0 "avr32_indirect_register_operand"))
|
mgl@1371
|
20588 |
+ (match_operand 0 "pre_dec_memory_operand")))
|
mgl@1371
|
20589 |
+
|
mgl@1371
|
20590 |
+
|
mgl@1371
|
20591 |
+;; True is this is a k12 offseted memory operand
|
mgl@1371
|
20592 |
+(define_predicate "avr32_k12_memory_operand"
|
mgl@1371
|
20593 |
+ (and (match_code "mem")
|
mgl@1371
|
20594 |
+ (ior (match_test "REG_P(XEXP(op, 0))")
|
mgl@1371
|
20595 |
+ (match_test "GET_CODE(XEXP(op, 0)) == PLUS
|
mgl@1371
|
20596 |
+ && REG_P(XEXP(XEXP(op, 0), 0))
|
mgl@1371
|
20597 |
+ && (GET_CODE(XEXP(XEXP(op, 0), 1)) == CONST_INT)
|
mgl@1371
|
20598 |
+ && (CONST_OK_FOR_CONSTRAINT_P(INTVAL(XEXP(XEXP(op, 0), 0)),
|
mgl@1371
|
20599 |
+ 'K', (mode == SImode) ? \"Ks14\" : ((mode == HImode) ? \"Ks13\" : \"Ks12\")))"))))
|
mgl@1371
|
20600 |
+
|
mgl@1371
|
20601 |
+;; True is this is a memory operand with an immediate displacement
|
mgl@1371
|
20602 |
+(define_predicate "avr32_imm_disp_memory_operand"
|
mgl@1371
|
20603 |
+ (and (match_code "mem")
|
mgl@1371
|
20604 |
+ (match_test "GET_CODE(XEXP(op, 0)) == PLUS
|
mgl@1371
|
20605 |
+ && REG_P(XEXP(XEXP(op, 0), 0))
|
mgl@1371
|
20606 |
+ && (GET_CODE(XEXP(XEXP(op, 0), 1)) == CONST_INT)")))
|
mgl@1371
|
20607 |
+
|
mgl@1371
|
20608 |
+;; True is this is a bswap operand
|
mgl@1371
|
20609 |
+(define_predicate "avr32_bswap_operand"
|
mgl@1371
|
20610 |
+ (ior (match_operand 0 "avr32_k12_memory_operand")
|
mgl@1371
|
20611 |
+ (match_operand 0 "register_operand")))
|
mgl@1371
|
20612 |
+
|
mgl@1371
|
20613 |
+;; True is this is a valid coprocessor insn memory operand
|
mgl@1371
|
20614 |
+(define_predicate "avr32_cop_memory_operand"
|
mgl@1371
|
20615 |
+ (and (match_operand 0 "memory_operand")
|
mgl@1371
|
20616 |
+ (not (match_test "GET_CODE(XEXP(op, 0)) == PLUS
|
mgl@1371
|
20617 |
+ && REG_P(XEXP(XEXP(op, 0), 0))
|
mgl@1371
|
20618 |
+ && (GET_CODE(XEXP(XEXP(op, 0), 1)) == CONST_INT)
|
mgl@1371
|
20619 |
+ && !(CONST_OK_FOR_CONSTRAINT_P(INTVAL(XEXP(XEXP(op, 0), 0)), 'K', \"Ku10\"))"))))
|
mgl@1371
|
20620 |
+
|
mgl@1371
|
20621 |
+;; True is this is a valid source/destination operand
|
mgl@1371
|
20622 |
+;; for moving values to/from a coprocessor
|
mgl@1371
|
20623 |
+(define_predicate "avr32_cop_move_operand"
|
mgl@1371
|
20624 |
+ (ior (match_operand 0 "register_operand")
|
mgl@1371
|
20625 |
+ (match_operand 0 "avr32_cop_memory_operand")))
|
mgl@1371
|
20626 |
+
|
mgl@1371
|
20627 |
+
|
mgl@1371
|
20628 |
+;; True is this is a valid extract byte offset for use in
|
mgl@1371
|
20629 |
+;; load extracted index insns
|
mgl@1371
|
20630 |
+(define_predicate "avr32_extract_shift_operand"
|
mgl@1371
|
20631 |
+ (and (match_operand 0 "const_int_operand")
|
mgl@1371
|
20632 |
+ (match_test "(INTVAL(op) == 0) || (INTVAL(op) == 8)
|
mgl@1371
|
20633 |
+ || (INTVAL(op) == 16) || (INTVAL(op) == 24)")))
|
mgl@1371
|
20634 |
+
|
mgl@1371
|
20635 |
+;; True is this is a floating-point register
|
mgl@1371
|
20636 |
+(define_predicate "avr32_fp_register_operand"
|
mgl@1371
|
20637 |
+ (and (match_operand 0 "register_operand")
|
mgl@1371
|
20638 |
+ (match_test "REGNO_REG_CLASS(REGNO(op)) == FP_REGS")))
|
mgl@1371
|
20639 |
+
|
mgl@1371
|
20640 |
+;; True is this is valid avr32 symbol operand
|
mgl@1371
|
20641 |
+(define_predicate "avr32_symbol_operand"
|
mgl@1371
|
20642 |
+ (and (match_code "label_ref, symbol_ref, const")
|
mgl@1371
|
20643 |
+ (match_test "avr32_find_symbol(op)")))
|
mgl@1371
|
20644 |
+
|
mgl@1371
|
20645 |
+;; True is this is valid operand for the lda.w and call pseudo insns
|
mgl@1371
|
20646 |
+(define_predicate "avr32_address_operand"
|
mgl@1371
|
20647 |
+ (and (and (match_code "label_ref, symbol_ref")
|
mgl@1371
|
20648 |
+ (match_test "avr32_find_symbol(op)"))
|
mgl@1371
|
20649 |
+ (ior (match_test "TARGET_HAS_ASM_ADDR_PSEUDOS")
|
mgl@1371
|
20650 |
+ (match_test "flag_pic")) ))
|
mgl@1371
|
20651 |
+
|
mgl@1371
|
20652 |
+;; An immediate k16 address operand
|
mgl@1371
|
20653 |
+(define_predicate "avr32_ks16_address_operand"
|
mgl@1371
|
20654 |
+ (and (match_operand 0 "address_operand")
|
mgl@1371
|
20655 |
+ (ior (match_test "REG_P(op)")
|
mgl@1371
|
20656 |
+ (match_test "GET_CODE(op) == PLUS
|
mgl@1371
|
20657 |
+ && ((GET_CODE(XEXP(op,0)) == CONST_INT)
|
mgl@1371
|
20658 |
+ || (GET_CODE(XEXP(op,1)) == CONST_INT))")) ))
|
mgl@1371
|
20659 |
+
|
mgl@1371
|
20660 |
+;; An offset k16 memory operand
|
mgl@1371
|
20661 |
+(define_predicate "avr32_ks16_memory_operand"
|
mgl@1371
|
20662 |
+ (and (match_code "mem")
|
mgl@1371
|
20663 |
+ (match_test "avr32_ks16_address_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0)))")))
|
mgl@1371
|
20664 |
+
|
mgl@1371
|
20665 |
+;; An immediate k11 address operand
|
mgl@1371
|
20666 |
+(define_predicate "avr32_ks11_address_operand"
|
mgl@1371
|
20667 |
+ (and (match_operand 0 "address_operand")
|
mgl@1371
|
20668 |
+ (ior (match_test "REG_P(op)")
|
mgl@1371
|
20669 |
+ (match_test "GET_CODE(op) == PLUS
|
mgl@1371
|
20670 |
+ && (((GET_CODE(XEXP(op,0)) == CONST_INT)
|
mgl@1371
|
20671 |
+ && avr32_const_ok_for_constraint_p(INTVAL(XEXP(op,0)), 'K', \"Ks11\"))
|
mgl@1371
|
20672 |
+ || ((GET_CODE(XEXP(op,1)) == CONST_INT)
|
mgl@1371
|
20673 |
+ && avr32_const_ok_for_constraint_p(INTVAL(XEXP(op,1)), 'K', \"Ks11\")))")) ))
|
mgl@1371
|
20674 |
+
|
mgl@1371
|
20675 |
+;; True if this is a avr32 call operand
|
mgl@1371
|
20676 |
+(define_predicate "avr32_call_operand"
|
mgl@1371
|
20677 |
+ (ior (ior (match_operand 0 "register_operand")
|
mgl@1371
|
20678 |
+ (ior (match_operand 0 "avr32_const_pool_ref_operand")
|
mgl@1371
|
20679 |
+ (match_operand 0 "avr32_address_operand")))
|
mgl@1371
|
20680 |
+ (match_test "SYMBOL_REF_RCALL_FUNCTION_P(op)")))
|
mgl@1371
|
20681 |
+
|
mgl@1371
|
20682 |
+;; Return true for operators performing ALU operations
|
mgl@1371
|
20683 |
+
|
mgl@1371
|
20684 |
+(define_predicate "alu_operator"
|
mgl@1371
|
20685 |
+ (match_code "ior, xor, and, plus, minus, ashift, lshiftrt, ashiftrt"))
|
mgl@1371
|
20686 |
+
|
mgl@1371
|
20687 |
+(define_predicate "avr32_add_shift_immediate_operand"
|
mgl@1371
|
20688 |
+ (and (match_operand 0 "immediate_operand")
|
mgl@1371
|
20689 |
+ (match_test "CONST_OK_FOR_CONSTRAINT_P(INTVAL(op), 'K', \"Ku02\")")))
|
mgl@1371
|
20690 |
+
|
mgl@1371
|
20691 |
+(define_predicate "avr32_cond_register_immediate_operand"
|
mgl@1371
|
20692 |
+ (ior (match_operand 0 "register_operand")
|
mgl@1371
|
20693 |
+ (and (match_operand 0 "immediate_operand")
|
mgl@1371
|
20694 |
+ (match_test "CONST_OK_FOR_CONSTRAINT_P(INTVAL(op), 'K', \"Ks08\")"))))
|
mgl@1371
|
20695 |
+
|
mgl@1371
|
20696 |
+(define_predicate "avr32_cond_immediate_operand"
|
mgl@1371
|
20697 |
+ (and (match_operand 0 "immediate_operand")
|
mgl@1371
|
20698 |
+ (match_test "CONST_OK_FOR_CONSTRAINT_P(INTVAL(op), 'I', \"Is08\")")))
|
mgl@1371
|
20699 |
+
|
mgl@1371
|
20700 |
+
|
mgl@1371
|
20701 |
+(define_predicate "avr32_cond_move_operand"
|
mgl@1371
|
20702 |
+ (ior (ior (match_operand 0 "register_operand")
|
mgl@1371
|
20703 |
+ (and (match_operand 0 "immediate_operand")
|
mgl@1371
|
20704 |
+ (match_test "CONST_OK_FOR_CONSTRAINT_P(INTVAL(op), 'K', \"Ks08\")")))
|
mgl@1371
|
20705 |
+ (and (match_test "TARGET_V2_INSNS")
|
mgl@1371
|
20706 |
+ (match_operand 0 "memory_operand"))))
|
mgl@1371
|
20707 |
+
|
mgl@1371
|
20708 |
+(define_predicate "avr32_mov_immediate_operand"
|
mgl@1371
|
20709 |
+ (and (match_operand 0 "immediate_operand")
|
mgl@1371
|
20710 |
+ (match_test "avr32_const_ok_for_move(INTVAL(op))")))
|
mgl@1371
|
20711 |
+
|
mgl@1371
|
20712 |
+
|
mgl@1371
|
20713 |
+(define_predicate "avr32_rmw_address_operand"
|
mgl@1371
|
20714 |
+ (ior (and (match_code "symbol_ref")
|
mgl@1371
|
20715 |
+ (match_test "({rtx symbol = avr32_find_symbol(op); \
|
mgl@1371
|
20716 |
+ symbol && (GET_CODE (symbol) == SYMBOL_REF) && SYMBOL_REF_RMW_ADDR(symbol);})"))
|
mgl@1371
|
20717 |
+ (and (match_operand 0 "immediate_operand")
|
mgl@1371
|
20718 |
+ (match_test "CONST_OK_FOR_CONSTRAINT_P(INTVAL(op), 'K', \"Ks17\")")))
|
mgl@1371
|
20719 |
+ {
|
mgl@1371
|
20720 |
+ return TARGET_RMW && !flag_pic;
|
mgl@1371
|
20721 |
+ }
|
mgl@1371
|
20722 |
+)
|
mgl@1371
|
20723 |
+
|
mgl@1371
|
20724 |
+(define_predicate "avr32_rmw_memory_operand"
|
mgl@1371
|
20725 |
+ (and (match_code "mem")
|
mgl@1371
|
20726 |
+ (match_test "(GET_MODE(op) == SImode) &&
|
mgl@1371
|
20727 |
+ avr32_rmw_address_operand(XEXP(op, 0), GET_MODE(XEXP(op, 0)))")))
|
mgl@1371
|
20728 |
+
|
mgl@1371
|
20729 |
+(define_predicate "avr32_rmw_memory_or_register_operand"
|
mgl@1371
|
20730 |
+ (ior (match_operand 0 "avr32_rmw_memory_operand")
|
mgl@1371
|
20731 |
+ (match_operand 0 "register_operand")))
|
mgl@1371
|
20732 |
+
|
mgl@1371
|
20733 |
+(define_predicate "avr32_non_rmw_memory_operand"
|
mgl@1371
|
20734 |
+ (and (not (match_operand 0 "avr32_rmw_memory_operand"))
|
mgl@1371
|
20735 |
+ (match_operand 0 "memory_operand")))
|
mgl@1371
|
20736 |
+
|
mgl@1371
|
20737 |
+(define_predicate "avr32_non_rmw_general_operand"
|
mgl@1371
|
20738 |
+ (and (not (match_operand 0 "avr32_rmw_memory_operand"))
|
mgl@1371
|
20739 |
+ (match_operand 0 "general_operand")))
|
mgl@1371
|
20740 |
+
|
mgl@1371
|
20741 |
+(define_predicate "avr32_non_rmw_nonimmediate_operand"
|
mgl@1371
|
20742 |
+ (and (not (match_operand 0 "avr32_rmw_memory_operand"))
|
mgl@1371
|
20743 |
+ (match_operand 0 "nonimmediate_operand")))
|
mgl@1371
|
20744 |
--- /dev/null
|
mgl@1371
|
20745 |
+++ b/gcc/config/avr32/simd.md
|
mgl@1371
|
20746 |
@@ -0,0 +1,145 @@
|
mgl@1371
|
20747 |
+;; AVR32 machine description file for SIMD instructions.
|
mgl@1371
|
20748 |
+;; Copyright 2003-2006 Atmel Corporation.
|
mgl@1371
|
20749 |
+;;
|
mgl@1371
|
20750 |
+;; Written by Ronny Pedersen, Atmel Norway, <rpedersen@atmel.com>
|
mgl@1371
|
20751 |
+;;
|
mgl@1371
|
20752 |
+;; This file is part of GCC.
|
mgl@1371
|
20753 |
+;;
|
mgl@1371
|
20754 |
+;; This program is free software; you can redistribute it and/or modify
|
mgl@1371
|
20755 |
+;; it under the terms of the GNU General Public License as published by
|
mgl@1371
|
20756 |
+;; the Free Software Foundation; either version 2 of the License, or
|
mgl@1371
|
20757 |
+;; (at your option) any later version.
|
mgl@1371
|
20758 |
+;;
|
mgl@1371
|
20759 |
+;; This program is distributed in the hope that it will be useful,
|
mgl@1371
|
20760 |
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
mgl@1371
|
20761 |
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
mgl@1371
|
20762 |
+;; GNU General Public License for more details.
|
mgl@1371
|
20763 |
+;;
|
mgl@1371
|
20764 |
+;; You should have received a copy of the GNU General Public License
|
mgl@1371
|
20765 |
+;; along with this program; if not, write to the Free Software
|
mgl@1371
|
20766 |
+;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
mgl@1371
|
20767 |
+
|
mgl@1371
|
20768 |
+;; -*- Mode: Scheme -*-
|
mgl@1371
|
20769 |
+
|
mgl@1371
|
20770 |
+
|
mgl@1371
|
20771 |
+;; Vector modes
|
mgl@1371
|
20772 |
+(define_mode_macro VECM [V2HI V4QI])
|
mgl@1371
|
20773 |
+(define_mode_attr size [(V2HI "h") (V4QI "b")])
|
mgl@1371
|
20774 |
+
|
mgl@1371
|
20775 |
+(define_insn "add<mode>3"
|
mgl@1371
|
20776 |
+ [(set (match_operand:VECM 0 "register_operand" "=r")
|
mgl@1371
|
20777 |
+ (plus:VECM (match_operand:VECM 1 "register_operand" "r")
|
mgl@1371
|
20778 |
+ (match_operand:VECM 2 "register_operand" "r")))]
|
mgl@1371
|
20779 |
+ "TARGET_SIMD"
|
mgl@1371
|
20780 |
+ "padd.<size>\t%0, %1, %2"
|
mgl@1371
|
20781 |
+ [(set_attr "length" "4")
|
mgl@1371
|
20782 |
+ (set_attr "type" "alu")])
|
mgl@1371
|
20783 |
+
|
mgl@1371
|
20784 |
+
|
mgl@1371
|
20785 |
+(define_insn "sub<mode>3"
|
mgl@1371
|
20786 |
+ [(set (match_operand:VECM 0 "register_operand" "=r")
|
mgl@1371
|
20787 |
+ (minus:VECM (match_operand:VECM 1 "register_operand" "r")
|
mgl@1371
|
20788 |
+ (match_operand:VECM 2 "register_operand" "r")))]
|
mgl@1371
|
20789 |
+ "TARGET_SIMD"
|
mgl@1371
|
20790 |
+ "psub.<size>\t%0, %1, %2"
|
mgl@1371
|
20791 |
+ [(set_attr "length" "4")
|
mgl@1371
|
20792 |
+ (set_attr "type" "alu")])
|
mgl@1371
|
20793 |
+
|
mgl@1371
|
20794 |
+
|
mgl@1371
|
20795 |
+(define_insn "abs<mode>2"
|
mgl@1371
|
20796 |
+ [(set (match_operand:VECM 0 "register_operand" "=r")
|
mgl@1371
|
20797 |
+ (abs:VECM (match_operand:VECM 1 "register_operand" "r")))]
|
mgl@1371
|
20798 |
+ "TARGET_SIMD"
|
mgl@1371
|
20799 |
+ "pabs.s<size>\t%0, %1"
|
mgl@1371
|
20800 |
+ [(set_attr "length" "4")
|
mgl@1371
|
20801 |
+ (set_attr "type" "alu")])
|
mgl@1371
|
20802 |
+
|
mgl@1371
|
20803 |
+(define_insn "ashl<mode>3"
|
mgl@1371
|
20804 |
+ [(set (match_operand:VECM 0 "register_operand" "=r")
|
mgl@1371
|
20805 |
+ (ashift:VECM (match_operand:VECM 1 "register_operand" "r")
|
mgl@1371
|
20806 |
+ (match_operand:SI 2 "immediate_operand" "Ku04")))]
|
mgl@1371
|
20807 |
+ "TARGET_SIMD"
|
mgl@1371
|
20808 |
+ "plsl.<size>\t%0, %1, %2"
|
mgl@1371
|
20809 |
+ [(set_attr "length" "4")
|
mgl@1371
|
20810 |
+ (set_attr "type" "alu")])
|
mgl@1371
|
20811 |
+
|
mgl@1371
|
20812 |
+(define_insn "ashr<mode>3"
|
mgl@1371
|
20813 |
+ [(set (match_operand:VECM 0 "register_operand" "=r")
|
mgl@1371
|
20814 |
+ (ashiftrt:VECM (match_operand:VECM 1 "register_operand" "r")
|
mgl@1371
|
20815 |
+ (match_operand:SI 2 "immediate_operand" "Ku04")))]
|
mgl@1371
|
20816 |
+ "TARGET_SIMD"
|
mgl@1371
|
20817 |
+ "pasr.<size>\t%0, %1, %2"
|
mgl@1371
|
20818 |
+ [(set_attr "length" "4")
|
mgl@1371
|
20819 |
+ (set_attr "type" "alu")])
|
mgl@1371
|
20820 |
+
|
mgl@1371
|
20821 |
+(define_insn "lshr<mode>3"
|
mgl@1371
|
20822 |
+ [(set (match_operand:VECM 0 "register_operand" "=r")
|
mgl@1371
|
20823 |
+ (lshiftrt:VECM (match_operand:VECM 1 "register_operand" "r")
|
mgl@1371
|
20824 |
+ (match_operand:SI 2 "immediate_operand" "Ku04")))]
|
mgl@1371
|
20825 |
+ "TARGET_SIMD"
|
mgl@1371
|
20826 |
+ "plsr.<size>\t%0, %1, %2"
|
mgl@1371
|
20827 |
+ [(set_attr "length" "4")
|
mgl@1371
|
20828 |
+ (set_attr "type" "alu")])
|
mgl@1371
|
20829 |
+
|
mgl@1371
|
20830 |
+(define_insn "smaxv2hi3"
|
mgl@1371
|
20831 |
+ [(set (match_operand:V2HI 0 "register_operand" "=r")
|
mgl@1371
|
20832 |
+ (smax:V2HI (match_operand:V2HI 1 "register_operand" "r")
|
mgl@1371
|
20833 |
+ (match_operand:V2HI 2 "register_operand" "r")))]
|
mgl@1371
|
20834 |
+
|
mgl@1371
|
20835 |
+ "TARGET_SIMD"
|
mgl@1371
|
20836 |
+ "pmax.sh\t%0, %1, %2"
|
mgl@1371
|
20837 |
+ [(set_attr "length" "4")
|
mgl@1371
|
20838 |
+ (set_attr "type" "alu")])
|
mgl@1371
|
20839 |
+
|
mgl@1371
|
20840 |
+(define_insn "sminv2hi3"
|
mgl@1371
|
20841 |
+ [(set (match_operand:V2HI 0 "register_operand" "=r")
|
mgl@1371
|
20842 |
+ (smin:V2HI (match_operand:V2HI 1 "register_operand" "r")
|
mgl@1371
|
20843 |
+ (match_operand:V2HI 2 "register_operand" "r")))]
|
mgl@1371
|
20844 |
+
|
mgl@1371
|
20845 |
+ "TARGET_SIMD"
|
mgl@1371
|
20846 |
+ "pmin.sh\t%0, %1, %2"
|
mgl@1371
|
20847 |
+ [(set_attr "length" "4")
|
mgl@1371
|
20848 |
+ (set_attr "type" "alu")])
|
mgl@1371
|
20849 |
+
|
mgl@1371
|
20850 |
+(define_insn "umaxv4qi3"
|
mgl@1371
|
20851 |
+ [(set (match_operand:V4QI 0 "register_operand" "=r")
|
mgl@1371
|
20852 |
+ (umax:V4QI (match_operand:V4QI 1 "register_operand" "r")
|
mgl@1371
|
20853 |
+ (match_operand:V4QI 2 "register_operand" "r")))]
|
mgl@1371
|
20854 |
+
|
mgl@1371
|
20855 |
+ "TARGET_SIMD"
|
mgl@1371
|
20856 |
+ "pmax.ub\t%0, %1, %2"
|
mgl@1371
|
20857 |
+ [(set_attr "length" "4")
|
mgl@1371
|
20858 |
+ (set_attr "type" "alu")])
|
mgl@1371
|
20859 |
+
|
mgl@1371
|
20860 |
+(define_insn "uminv4qi3"
|
mgl@1371
|
20861 |
+ [(set (match_operand:V4QI 0 "register_operand" "=r")
|
mgl@1371
|
20862 |
+ (umin:V4QI (match_operand:V4QI 1 "register_operand" "r")
|
mgl@1371
|
20863 |
+ (match_operand:V4QI 2 "register_operand" "r")))]
|
mgl@1371
|
20864 |
+
|
mgl@1371
|
20865 |
+ "TARGET_SIMD"
|
mgl@1371
|
20866 |
+ "pmin.ub\t%0, %1, %2"
|
mgl@1371
|
20867 |
+ [(set_attr "length" "4")
|
mgl@1371
|
20868 |
+ (set_attr "type" "alu")])
|
mgl@1371
|
20869 |
+
|
mgl@1371
|
20870 |
+
|
mgl@1371
|
20871 |
+(define_insn "addsubv2hi"
|
mgl@1371
|
20872 |
+ [(set (match_operand:V2HI 0 "register_operand" "=r")
|
mgl@1371
|
20873 |
+ (vec_concat:V2HI
|
mgl@1371
|
20874 |
+ (plus:HI (match_operand:HI 1 "register_operand" "r")
|
mgl@1371
|
20875 |
+ (match_operand:HI 2 "register_operand" "r"))
|
mgl@1371
|
20876 |
+ (minus:HI (match_dup 1) (match_dup 2))))]
|
mgl@1371
|
20877 |
+ "TARGET_SIMD"
|
mgl@1371
|
20878 |
+ "paddsub.h\t%0, %1:b, %2:b"
|
mgl@1371
|
20879 |
+ [(set_attr "length" "4")
|
mgl@1371
|
20880 |
+ (set_attr "type" "alu")])
|
mgl@1371
|
20881 |
+
|
mgl@1371
|
20882 |
+(define_insn "subaddv2hi"
|
mgl@1371
|
20883 |
+ [(set (match_operand:V2HI 0 "register_operand" "=r")
|
mgl@1371
|
20884 |
+ (vec_concat:V2HI
|
mgl@1371
|
20885 |
+ (minus:HI (match_operand:HI 1 "register_operand" "r")
|
mgl@1371
|
20886 |
+ (match_operand:HI 2 "register_operand" "r"))
|
mgl@1371
|
20887 |
+ (plus:HI (match_dup 1) (match_dup 2))))]
|
mgl@1371
|
20888 |
+ "TARGET_SIMD"
|
mgl@1371
|
20889 |
+ "psubadd.h\t%0, %1:b, %2:b"
|
mgl@1371
|
20890 |
+ [(set_attr "length" "4")
|
mgl@1371
|
20891 |
+ (set_attr "type" "alu")])
|
mgl@1371
|
20892 |
--- /dev/null
|
mgl@1371
|
20893 |
+++ b/gcc/config/avr32/sync.md
|
mgl@1371
|
20894 |
@@ -0,0 +1,244 @@
|
mgl@1371
|
20895 |
+;;=================================================================
|
mgl@1371
|
20896 |
+;; Atomic operations
|
mgl@1371
|
20897 |
+;;=================================================================
|
mgl@1371
|
20898 |
+
|
mgl@1371
|
20899 |
+
|
mgl@1371
|
20900 |
+(define_insn "sync_compare_and_swapsi"
|
mgl@1371
|
20901 |
+ [(set (match_operand:SI 0 "register_operand" "=&r,&r")
|
mgl@1371
|
20902 |
+ (match_operand:SI 1 "memory_operand" "+RKs16,+RKs16"))
|
mgl@1371
|
20903 |
+ (set (match_dup 1)
|
mgl@1371
|
20904 |
+ (unspec_volatile:SI
|
mgl@1371
|
20905 |
+ [(match_dup 1)
|
mgl@1371
|
20906 |
+ (match_operand:SI 2 "register_immediate_operand" "r,Ks21")
|
mgl@1371
|
20907 |
+ (match_operand:SI 3 "register_operand" "r,r")]
|
mgl@1371
|
20908 |
+ VUNSPEC_SYNC_CMPXCHG)) ]
|
mgl@1371
|
20909 |
+ ""
|
mgl@1371
|
20910 |
+ "0:
|
mgl@1371
|
20911 |
+ ssrf\t5
|
mgl@1371
|
20912 |
+ ld.w\t%0,%1
|
mgl@1371
|
20913 |
+ cp.w\t%0,%2
|
mgl@1371
|
20914 |
+ brne\t0f
|
mgl@1371
|
20915 |
+ stcond\t%1, %3
|
mgl@1371
|
20916 |
+ brne\t0b
|
mgl@1371
|
20917 |
+ 0:
|
mgl@1371
|
20918 |
+ "
|
mgl@1371
|
20919 |
+ [(set_attr "length" "16,18")
|
mgl@1371
|
20920 |
+ (set_attr "cc" "clobber")]
|
mgl@1371
|
20921 |
+ )
|
mgl@1371
|
20922 |
+
|
mgl@1371
|
20923 |
+
|
mgl@1371
|
20924 |
+(define_code_macro atomic_op [plus minus and ior xor])
|
mgl@1371
|
20925 |
+(define_code_attr atomic_asm_insn [(plus "add") (minus "sub") (and "and") (ior "or") (xor "eor")])
|
mgl@1371
|
20926 |
+(define_code_attr atomic_insn [(plus "add") (minus "sub") (and "and") (ior "ior") (xor "xor")])
|
mgl@1371
|
20927 |
+
|
mgl@1371
|
20928 |
+(define_insn "sync_loadsi"
|
mgl@1371
|
20929 |
+ ; NB! Put an early clobber on the destination operand to
|
mgl@1371
|
20930 |
+ ; avoid gcc using the same register in the source and
|
mgl@1371
|
20931 |
+ ; destination. This is done in order to avoid gcc to
|
mgl@1371
|
20932 |
+ ; clobber the source operand since these instructions
|
mgl@1371
|
20933 |
+ ; are actually inside a "loop".
|
mgl@1371
|
20934 |
+ [(set (match_operand:SI 0 "register_operand" "=&r")
|
mgl@1371
|
20935 |
+ (unspec_volatile:SI
|
mgl@1371
|
20936 |
+ [(match_operand:SI 1 "avr32_ks16_memory_operand" "RKs16")
|
mgl@1371
|
20937 |
+ (label_ref (match_operand 2 "" ""))]
|
mgl@1371
|
20938 |
+ VUNSPEC_SYNC_SET_LOCK_AND_LOAD) )]
|
mgl@1371
|
20939 |
+ ""
|
mgl@1371
|
20940 |
+ "%2:
|
mgl@1371
|
20941 |
+ ssrf\t5
|
mgl@1371
|
20942 |
+ ld.w\t%0,%1"
|
mgl@1371
|
20943 |
+ [(set_attr "length" "6")
|
mgl@1371
|
20944 |
+ (set_attr "cc" "clobber")]
|
mgl@1371
|
20945 |
+ )
|
mgl@1371
|
20946 |
+
|
mgl@1371
|
20947 |
+(define_insn "sync_store_if_lock"
|
mgl@1371
|
20948 |
+ [(set (match_operand:SI 0 "avr32_ks16_memory_operand" "=RKs16")
|
mgl@1371
|
20949 |
+ (unspec_volatile:SI
|
mgl@1371
|
20950 |
+ [(match_operand:SI 1 "register_operand" "r")
|
mgl@1371
|
20951 |
+ (label_ref (match_operand 2 "" ""))]
|
mgl@1371
|
20952 |
+ VUNSPEC_SYNC_STORE_IF_LOCK) )]
|
mgl@1371
|
20953 |
+ ""
|
mgl@1371
|
20954 |
+ "stcond\t%0, %1
|
mgl@1371
|
20955 |
+ brne\t%2"
|
mgl@1371
|
20956 |
+ [(set_attr "length" "6")
|
mgl@1371
|
20957 |
+ (set_attr "cc" "clobber")]
|
mgl@1371
|
20958 |
+ )
|
mgl@1371
|
20959 |
+
|
mgl@1371
|
20960 |
+
|
mgl@1371
|
20961 |
+(define_expand "sync_<atomic_insn>si"
|
mgl@1371
|
20962 |
+ [(set (match_dup 2)
|
mgl@1371
|
20963 |
+ (unspec_volatile:SI
|
mgl@1371
|
20964 |
+ [(match_operand:SI 0 "avr32_ks16_memory_operand" "")
|
mgl@1371
|
20965 |
+ (match_dup 3)]
|
mgl@1371
|
20966 |
+ VUNSPEC_SYNC_SET_LOCK_AND_LOAD))
|
mgl@1371
|
20967 |
+ (set (match_dup 2)
|
mgl@1371
|
20968 |
+ (atomic_op:SI (match_dup 2)
|
mgl@1371
|
20969 |
+ (match_operand:SI 1 "register_immediate_operand" "")))
|
mgl@1371
|
20970 |
+ (set (match_dup 0)
|
mgl@1371
|
20971 |
+ (unspec_volatile:SI
|
mgl@1371
|
20972 |
+ [(match_dup 2)
|
mgl@1371
|
20973 |
+ (match_dup 3)]
|
mgl@1371
|
20974 |
+ VUNSPEC_SYNC_STORE_IF_LOCK) )
|
mgl@1371
|
20975 |
+ (use (match_dup 1))
|
mgl@1371
|
20976 |
+ (use (match_dup 4))]
|
mgl@1371
|
20977 |
+ ""
|
mgl@1371
|
20978 |
+ {
|
mgl@1371
|
20979 |
+ rtx *mem_expr = &operands[0];
|
mgl@1371
|
20980 |
+ rtx ptr_reg;
|
mgl@1371
|
20981 |
+ if ( !avr32_ks16_memory_operand (*mem_expr, GET_MODE (*mem_expr)) )
|
mgl@1371
|
20982 |
+ {
|
mgl@1371
|
20983 |
+ ptr_reg = force_reg (Pmode, XEXP (*mem_expr, 0));
|
mgl@1371
|
20984 |
+ XEXP (*mem_expr, 0) = ptr_reg;
|
mgl@1371
|
20985 |
+ }
|
mgl@1371
|
20986 |
+ else
|
mgl@1371
|
20987 |
+ {
|
mgl@1371
|
20988 |
+ rtx address = XEXP (*mem_expr, 0);
|
mgl@1371
|
20989 |
+ if ( REG_P (address) )
|
mgl@1371
|
20990 |
+ ptr_reg = address;
|
mgl@1371
|
20991 |
+ else if ( REG_P (XEXP (address, 0)) )
|
mgl@1371
|
20992 |
+ ptr_reg = XEXP (address, 0);
|
mgl@1371
|
20993 |
+ else
|
mgl@1371
|
20994 |
+ ptr_reg = XEXP (address, 1);
|
mgl@1371
|
20995 |
+ }
|
mgl@1371
|
20996 |
+
|
mgl@1371
|
20997 |
+ operands[2] = gen_reg_rtx (SImode);
|
mgl@1371
|
20998 |
+ operands[3] = gen_rtx_LABEL_REF(Pmode, gen_label_rtx ());
|
mgl@1371
|
20999 |
+ operands[4] = ptr_reg;
|
mgl@1371
|
21000 |
+
|
mgl@1371
|
21001 |
+ }
|
mgl@1371
|
21002 |
+ )
|
mgl@1371
|
21003 |
+
|
mgl@1371
|
21004 |
+
|
mgl@1371
|
21005 |
+
|
mgl@1371
|
21006 |
+(define_expand "sync_old_<atomic_insn>si"
|
mgl@1371
|
21007 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
21008 |
+ (unspec_volatile:SI
|
mgl@1371
|
21009 |
+ [(match_operand:SI 1 "avr32_ks16_memory_operand" "")
|
mgl@1371
|
21010 |
+ (match_dup 4)]
|
mgl@1371
|
21011 |
+ VUNSPEC_SYNC_SET_LOCK_AND_LOAD))
|
mgl@1371
|
21012 |
+ (set (match_dup 3)
|
mgl@1371
|
21013 |
+ (atomic_op:SI (match_dup 0)
|
mgl@1371
|
21014 |
+ (match_operand:SI 2 "register_immediate_operand" "")))
|
mgl@1371
|
21015 |
+ (set (match_dup 1)
|
mgl@1371
|
21016 |
+ (unspec_volatile:SI
|
mgl@1371
|
21017 |
+ [(match_dup 3)
|
mgl@1371
|
21018 |
+ (match_dup 4)]
|
mgl@1371
|
21019 |
+ VUNSPEC_SYNC_STORE_IF_LOCK) )
|
mgl@1371
|
21020 |
+ (use (match_dup 2))
|
mgl@1371
|
21021 |
+ (use (match_dup 5))]
|
mgl@1371
|
21022 |
+ ""
|
mgl@1371
|
21023 |
+ {
|
mgl@1371
|
21024 |
+ rtx *mem_expr = &operands[1];
|
mgl@1371
|
21025 |
+ rtx ptr_reg;
|
mgl@1371
|
21026 |
+ if ( !avr32_ks16_memory_operand (*mem_expr, GET_MODE (*mem_expr)) )
|
mgl@1371
|
21027 |
+ {
|
mgl@1371
|
21028 |
+ ptr_reg = force_reg (Pmode, XEXP (*mem_expr, 0));
|
mgl@1371
|
21029 |
+ XEXP (*mem_expr, 0) = ptr_reg;
|
mgl@1371
|
21030 |
+ }
|
mgl@1371
|
21031 |
+ else
|
mgl@1371
|
21032 |
+ {
|
mgl@1371
|
21033 |
+ rtx address = XEXP (*mem_expr, 0);
|
mgl@1371
|
21034 |
+ if ( REG_P (address) )
|
mgl@1371
|
21035 |
+ ptr_reg = address;
|
mgl@1371
|
21036 |
+ else if ( REG_P (XEXP (address, 0)) )
|
mgl@1371
|
21037 |
+ ptr_reg = XEXP (address, 0);
|
mgl@1371
|
21038 |
+ else
|
mgl@1371
|
21039 |
+ ptr_reg = XEXP (address, 1);
|
mgl@1371
|
21040 |
+ }
|
mgl@1371
|
21041 |
+
|
mgl@1371
|
21042 |
+ operands[3] = gen_reg_rtx (SImode);
|
mgl@1371
|
21043 |
+ operands[4] = gen_rtx_LABEL_REF(Pmode, gen_label_rtx ());
|
mgl@1371
|
21044 |
+ operands[5] = ptr_reg;
|
mgl@1371
|
21045 |
+ }
|
mgl@1371
|
21046 |
+ )
|
mgl@1371
|
21047 |
+
|
mgl@1371
|
21048 |
+(define_expand "sync_new_<atomic_insn>si"
|
mgl@1371
|
21049 |
+ [(set (match_operand:SI 0 "register_operand" "")
|
mgl@1371
|
21050 |
+ (unspec_volatile:SI
|
mgl@1371
|
21051 |
+ [(match_operand:SI 1 "avr32_ks16_memory_operand" "")
|
mgl@1371
|
21052 |
+ (match_dup 3)]
|
mgl@1371
|
21053 |
+ VUNSPEC_SYNC_SET_LOCK_AND_LOAD))
|
mgl@1371
|
21054 |
+ (set (match_dup 0)
|
mgl@1371
|
21055 |
+ (atomic_op:SI (match_dup 0)
|
mgl@1371
|
21056 |
+ (match_operand:SI 2 "register_immediate_operand" "")))
|
mgl@1371
|
21057 |
+ (set (match_dup 1)
|
mgl@1371
|
21058 |
+ (unspec_volatile:SI
|
mgl@1371
|
21059 |
+ [(match_dup 0)
|
mgl@1371
|
21060 |
+ (match_dup 3)]
|
mgl@1371
|
21061 |
+ VUNSPEC_SYNC_STORE_IF_LOCK) )
|
mgl@1371
|
21062 |
+ (use (match_dup 2))
|
mgl@1371
|
21063 |
+ (use (match_dup 4))]
|
mgl@1371
|
21064 |
+ ""
|
mgl@1371
|
21065 |
+ {
|
mgl@1371
|
21066 |
+ rtx *mem_expr = &operands[1];
|
mgl@1371
|
21067 |
+ rtx ptr_reg;
|
mgl@1371
|
21068 |
+ if ( !avr32_ks16_memory_operand (*mem_expr, GET_MODE (*mem_expr)) )
|
mgl@1371
|
21069 |
+ {
|
mgl@1371
|
21070 |
+ ptr_reg = force_reg (Pmode, XEXP (*mem_expr, 0));
|
mgl@1371
|
21071 |
+ XEXP (*mem_expr, 0) = ptr_reg;
|
mgl@1371
|
21072 |
+ }
|
mgl@1371
|
21073 |
+ else
|
mgl@1371
|
21074 |
+ {
|
mgl@1371
|
21075 |
+ rtx address = XEXP (*mem_expr, 0);
|
mgl@1371
|
21076 |
+ if ( REG_P (address) )
|
mgl@1371
|
21077 |
+ ptr_reg = address;
|
mgl@1371
|
21078 |
+ else if ( REG_P (XEXP (address, 0)) )
|
mgl@1371
|
21079 |
+ ptr_reg = XEXP (address, 0);
|
mgl@1371
|
21080 |
+ else
|
mgl@1371
|
21081 |
+ ptr_reg = XEXP (address, 1);
|
mgl@1371
|
21082 |
+ }
|
mgl@1371
|
21083 |
+
|
mgl@1371
|
21084 |
+ operands[3] = gen_rtx_LABEL_REF(Pmode, gen_label_rtx ());
|
mgl@1371
|
21085 |
+ operands[4] = ptr_reg;
|
mgl@1371
|
21086 |
+ }
|
mgl@1371
|
21087 |
+ )
|
mgl@1371
|
21088 |
+
|
mgl@1371
|
21089 |
+
|
mgl@1371
|
21090 |
+;(define_insn "sync_<atomic_insn>si"
|
mgl@1371
|
21091 |
+; [(set (match_operand:SI 0 "memory_operand" "+RKs16")
|
mgl@1371
|
21092 |
+; (unspec_volatile:SI
|
mgl@1371
|
21093 |
+; [(atomic_op:SI (match_dup 0)
|
mgl@1371
|
21094 |
+; (match_operand:SI 1 "register_operand" "r"))]
|
mgl@1371
|
21095 |
+; VUNSPEC_SYNC_CMPXCHG))
|
mgl@1371
|
21096 |
+; (clobber (match_scratch:SI 2 "=&r"))]
|
mgl@1371
|
21097 |
+; ""
|
mgl@1371
|
21098 |
+; "0:
|
mgl@1371
|
21099 |
+; ssrf\t5
|
mgl@1371
|
21100 |
+; ld.w\t%2,%0
|
mgl@1371
|
21101 |
+; <atomic_asm_insn>\t%2,%1
|
mgl@1371
|
21102 |
+; stcond\t%0, %2
|
mgl@1371
|
21103 |
+; brne\t0b
|
mgl@1371
|
21104 |
+; "
|
mgl@1371
|
21105 |
+; [(set_attr "length" "14")
|
mgl@1371
|
21106 |
+; (set_attr "cc" "clobber")]
|
mgl@1371
|
21107 |
+; )
|
mgl@1371
|
21108 |
+;
|
mgl@1371
|
21109 |
+;(define_insn "sync_new_<atomic_insn>si"
|
mgl@1371
|
21110 |
+; [(set (match_operand:SI 1 "memory_operand" "+RKs16")
|
mgl@1371
|
21111 |
+; (unspec_volatile:SI
|
mgl@1371
|
21112 |
+; [(atomic_op:SI (match_dup 1)
|
mgl@1371
|
21113 |
+; (match_operand:SI 2 "register_operand" "r"))]
|
mgl@1371
|
21114 |
+; VUNSPEC_SYNC_CMPXCHG))
|
mgl@1371
|
21115 |
+; (set (match_operand:SI 0 "register_operand" "=&r")
|
mgl@1371
|
21116 |
+; (atomic_op:SI (match_dup 1)
|
mgl@1371
|
21117 |
+; (match_dup 2)))]
|
mgl@1371
|
21118 |
+; ""
|
mgl@1371
|
21119 |
+; "0:
|
mgl@1371
|
21120 |
+; ssrf\t5
|
mgl@1371
|
21121 |
+; ld.w\t%0,%1
|
mgl@1371
|
21122 |
+; <atomic_asm_insn>\t%0,%2
|
mgl@1371
|
21123 |
+; stcond\t%1, %0
|
mgl@1371
|
21124 |
+; brne\t0b
|
mgl@1371
|
21125 |
+; "
|
mgl@1371
|
21126 |
+; [(set_attr "length" "14")
|
mgl@1371
|
21127 |
+; (set_attr "cc" "clobber")]
|
mgl@1371
|
21128 |
+; )
|
mgl@1371
|
21129 |
+
|
mgl@1371
|
21130 |
+(define_insn "sync_lock_test_and_setsi"
|
mgl@1371
|
21131 |
+ [ (set (match_operand:SI 0 "register_operand" "=&r")
|
mgl@1371
|
21132 |
+ (match_operand:SI 1 "memory_operand" "+RKu00"))
|
mgl@1371
|
21133 |
+ (set (match_dup 1)
|
mgl@1371
|
21134 |
+ (match_operand:SI 2 "register_operand" "r")) ]
|
mgl@1371
|
21135 |
+ ""
|
mgl@1371
|
21136 |
+ "xchg\t%0, %p1, %2"
|
mgl@1371
|
21137 |
+ [(set_attr "length" "4")]
|
mgl@1371
|
21138 |
+ )
|
mgl@1371
|
21139 |
--- /dev/null
|
mgl@1371
|
21140 |
+++ b/gcc/config/avr32/t-avr32
|
mgl@1371
|
21141 |
@@ -0,0 +1,77 @@
|
mgl@1371
|
21142 |
+
|
mgl@1371
|
21143 |
+MD_INCLUDES= $(srcdir)/config/avr32/avr32.md \
|
mgl@1371
|
21144 |
+ $(srcdir)/config/avr32/sync.md \
|
mgl@1371
|
21145 |
+ $(srcdir)/config/avr32/fpcp.md \
|
mgl@1371
|
21146 |
+ $(srcdir)/config/avr32/simd.md \
|
mgl@1371
|
21147 |
+ $(srcdir)/config/avr32/predicates.md
|
mgl@1371
|
21148 |
+
|
mgl@1371
|
21149 |
+s-config s-conditions s-flags s-codes s-constants s-emit s-recog s-preds \
|
mgl@1371
|
21150 |
+ s-opinit s-extract s-peep s-attr s-attrtab s-output: $(MD_INCLUDES)
|
mgl@1371
|
21151 |
+
|
mgl@1371
|
21152 |
+# We want fine grained libraries, so use the new code
|
mgl@1371
|
21153 |
+# to build the floating point emulation libraries.
|
mgl@1371
|
21154 |
+FPBIT = fp-bit.c
|
mgl@1371
|
21155 |
+DPBIT = dp-bit.c
|
mgl@1371
|
21156 |
+
|
mgl@1371
|
21157 |
+LIB1ASMSRC = avr32/lib1funcs.S
|
mgl@1371
|
21158 |
+LIB1ASMFUNCS = _avr32_f64_mul _avr32_f64_mul_fast _avr32_f64_addsub _avr32_f64_addsub_fast _avr32_f64_to_u32 \
|
mgl@1371
|
21159 |
+ _avr32_f64_to_s32 _avr32_f64_to_u64 _avr32_f64_to_s64 _avr32_u32_to_f64 \
|
mgl@1371
|
21160 |
+ _avr32_s32_to_f64 _avr32_f64_cmp_eq _avr32_f64_cmp_ge _avr32_f64_cmp_lt \
|
mgl@1371
|
21161 |
+ _avr32_f32_cmp_eq _avr32_f32_cmp_ge _avr32_f32_cmp_lt _avr32_f64_div _avr32_f64_div_fast \
|
mgl@1371
|
21162 |
+ _avr32_f32_div _avr32_f32_div_fast _avr32_f32_addsub _avr32_f32_addsub_fast \
|
mgl@1371
|
21163 |
+ _avr32_f32_mul _avr32_s32_to_f32 _avr32_u32_to_f32 _avr32_f32_to_s32 \
|
mgl@1371
|
21164 |
+ _avr32_f32_to_u32 _avr32_f32_to_f64 _avr32_f64_to_f32 _mulsi3
|
mgl@1371
|
21165 |
+
|
mgl@1371
|
21166 |
+#LIB2FUNCS_EXTRA += $(srcdir)/config/avr32/lib2funcs.S
|
mgl@1371
|
21167 |
+
|
mgl@1371
|
21168 |
+MULTILIB_OPTIONS = march=ap/march=ucr1/march=ucr2/march=ucr2nomul
|
mgl@1371
|
21169 |
+MULTILIB_DIRNAMES = ap ucr1 ucr2 ucr2nomul
|
mgl@1371
|
21170 |
+MULTILIB_EXCEPTIONS =
|
mgl@1371
|
21171 |
+MULTILIB_MATCHES += march?ap=mpart?ap7000
|
mgl@1371
|
21172 |
+MULTILIB_MATCHES += march?ap=mpart?ap7001
|
mgl@1371
|
21173 |
+MULTILIB_MATCHES += march?ap=mpart?ap7002
|
mgl@1371
|
21174 |
+MULTILIB_MATCHES += march?ap=mpart?ap7200
|
mgl@1371
|
21175 |
+MULTILIB_MATCHES += march?ucr1=march?uc
|
mgl@1371
|
21176 |
+MULTILIB_MATCHES += march?ucr1=mpart?uc3a0512es
|
mgl@1371
|
21177 |
+MULTILIB_MATCHES += march?ucr2=mpart?uc3a0128
|
mgl@1371
|
21178 |
+MULTILIB_MATCHES += march?ucr2=mpart?uc3a0256
|
mgl@1371
|
21179 |
+MULTILIB_MATCHES += march?ucr2=mpart?uc3a0512
|
mgl@1371
|
21180 |
+MULTILIB_MATCHES += march?ucr2=mpart?uc3a1128
|
mgl@1371
|
21181 |
+MULTILIB_MATCHES += march?ucr2=mpart?uc3a1256
|
mgl@1371
|
21182 |
+MULTILIB_MATCHES += march?ucr1=mpart?uc3a1512es
|
mgl@1371
|
21183 |
+MULTILIB_MATCHES += march?ucr2=mpart?uc3a1512
|
mgl@1371
|
21184 |
+MULTILIB_MATCHES += march?ucr2nomul=mpart?uc3a3revd
|
mgl@1371
|
21185 |
+MULTILIB_MATCHES += march?ucr2=mpart?uc3a364
|
mgl@1371
|
21186 |
+MULTILIB_MATCHES += march?ucr2=mpart?uc3a364s
|
mgl@1371
|
21187 |
+MULTILIB_MATCHES += march?ucr2=mpart?uc3a3128
|
mgl@1371
|
21188 |
+MULTILIB_MATCHES += march?ucr2=mpart?uc3a3128s
|
mgl@1371
|
21189 |
+MULTILIB_MATCHES += march?ucr2=mpart?uc3a3256
|
mgl@1371
|
21190 |
+MULTILIB_MATCHES += march?ucr2=mpart?uc3a3256s
|
mgl@1371
|
21191 |
+MULTILIB_MATCHES += march?ucr1=mpart?uc3b064
|
mgl@1371
|
21192 |
+MULTILIB_MATCHES += march?ucr1=mpart?uc3b0128
|
mgl@1371
|
21193 |
+MULTILIB_MATCHES += march?ucr1=mpart?uc3b0256es
|
mgl@1371
|
21194 |
+MULTILIB_MATCHES += march?ucr1=mpart?uc3b0256
|
mgl@1371
|
21195 |
+MULTILIB_MATCHES += march?ucr1=mpart?uc3b164
|
mgl@1371
|
21196 |
+MULTILIB_MATCHES += march?ucr1=mpart?uc3b1128
|
mgl@1371
|
21197 |
+MULTILIB_MATCHES += march?ucr1=mpart?uc3b1256es
|
mgl@1371
|
21198 |
+MULTILIB_MATCHES += march?ucr1=mpart?uc3b1256
|
mgl@1371
|
21199 |
+
|
mgl@1371
|
21200 |
+
|
mgl@1371
|
21201 |
+EXTRA_MULTILIB_PARTS = crtbegin.o crtbeginS.o crtend.o crtendS.o crti.o crtn.o
|
mgl@1371
|
21202 |
+
|
mgl@1371
|
21203 |
+CRTSTUFF_T_CFLAGS = -mrelax
|
mgl@1371
|
21204 |
+CRTSTUFF_T_CFLAGS_S = -mrelax -fPIC
|
mgl@1371
|
21205 |
+TARGET_LIBGCC2_CFLAGS += -mrelax
|
mgl@1371
|
21206 |
+
|
mgl@1371
|
21207 |
+LIBGCC = stmp-multilib
|
mgl@1371
|
21208 |
+INSTALL_LIBGCC = install-multilib
|
mgl@1371
|
21209 |
+
|
mgl@1371
|
21210 |
+fp-bit.c: $(srcdir)/config/fp-bit.c
|
mgl@1371
|
21211 |
+ echo '#define FLOAT' > fp-bit.c
|
mgl@1371
|
21212 |
+ cat $(srcdir)/config/fp-bit.c >> fp-bit.c
|
mgl@1371
|
21213 |
+
|
mgl@1371
|
21214 |
+dp-bit.c: $(srcdir)/config/fp-bit.c
|
mgl@1371
|
21215 |
+ cat $(srcdir)/config/fp-bit.c > dp-bit.c
|
mgl@1371
|
21216 |
+
|
mgl@1371
|
21217 |
+
|
mgl@1371
|
21218 |
+
|
mgl@1371
|
21219 |
--- /dev/null
|
mgl@1371
|
21220 |
+++ b/gcc/config/avr32/t-elf
|
mgl@1371
|
21221 |
@@ -0,0 +1,16 @@
|
mgl@1371
|
21222 |
+
|
mgl@1371
|
21223 |
+# Assemble startup files.
|
mgl@1371
|
21224 |
+$(T)crti.o: $(srcdir)/config/avr32/crti.asm $(GCC_PASSES)
|
mgl@1371
|
21225 |
+ $(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) $(CRTSTUFF_T_CFLAGS) $(INCLUDES) \
|
mgl@1371
|
21226 |
+ -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/avr32/crti.asm
|
mgl@1371
|
21227 |
+
|
mgl@1371
|
21228 |
+$(T)crtn.o: $(srcdir)/config/avr32/crtn.asm $(GCC_PASSES)
|
mgl@1371
|
21229 |
+ $(GCC_FOR_TARGET) $(CRTSTUFF_CFLAGS) $(CRTSTUFF_T_CFLAGS) $(INCLUDES) \
|
mgl@1371
|
21230 |
+ -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/avr32/crtn.asm
|
mgl@1371
|
21231 |
+
|
mgl@1371
|
21232 |
+
|
mgl@1371
|
21233 |
+# Build the libraries for both hard and soft floating point
|
mgl@1371
|
21234 |
+EXTRA_MULTILIB_PARTS = crtbegin.o crtbeginS.o crtend.o crtendS.o crti.o crtn.o
|
mgl@1371
|
21235 |
+
|
mgl@1371
|
21236 |
+LIBGCC = stmp-multilib
|
mgl@1371
|
21237 |
+INSTALL_LIBGCC = install-multilib
|
mgl@1371
|
21238 |
--- /dev/null
|
mgl@1371
|
21239 |
+++ b/gcc/config/avr32/uclinux-elf.h
|
mgl@1371
|
21240 |
@@ -0,0 +1,20 @@
|
mgl@1371
|
21241 |
+
|
mgl@1371
|
21242 |
+/* Run-time Target Specification. */
|
mgl@1371
|
21243 |
+#undef TARGET_VERSION
|
mgl@1371
|
21244 |
+#define TARGET_VERSION fputs (" (AVR32 uClinux with ELF)", stderr)
|
mgl@1371
|
21245 |
+
|
mgl@1371
|
21246 |
+/* We don't want a .jcr section on uClinux. As if this makes a difference... */
|
mgl@1371
|
21247 |
+#define TARGET_USE_JCR_SECTION 0
|
mgl@1371
|
21248 |
+
|
mgl@1371
|
21249 |
+/* Here we go. Drop the crtbegin/crtend stuff completely. */
|
mgl@1371
|
21250 |
+#undef STARTFILE_SPEC
|
mgl@1371
|
21251 |
+#define STARTFILE_SPEC \
|
mgl@1371
|
21252 |
+ "%{!shared: %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s}" \
|
mgl@1371
|
21253 |
+ " %{!p:%{profile:gcrt1.o%s}" \
|
mgl@1371
|
21254 |
+ " %{!profile:crt1.o%s}}}} crti.o%s"
|
mgl@1371
|
21255 |
+
|
mgl@1371
|
21256 |
+#undef ENDFILE_SPEC
|
mgl@1371
|
21257 |
+#define ENDFILE_SPEC "crtn.o%s"
|
mgl@1371
|
21258 |
+
|
mgl@1371
|
21259 |
+#undef TARGET_DEFAULT
|
mgl@1371
|
21260 |
+#define TARGET_DEFAULT (AVR32_FLAG_NO_INIT_GOT)
|
mgl@1371
|
21261 |
--- a/gcc/config/host-linux.c
|
mgl@1371
|
21262 |
+++ b/gcc/config/host-linux.c
|
mgl@1371
|
21263 |
@@ -25,6 +25,9 @@
|
mgl@1371
|
21264 |
#include "hosthooks.h"
|
mgl@1371
|
21265 |
#include "hosthooks-def.h"
|
mgl@1371
|
21266 |
|
mgl@1371
|
21267 |
+#ifndef SSIZE_MAX
|
mgl@1371
|
21268 |
+#define SSIZE_MAX LONG_MAX
|
mgl@1371
|
21269 |
+#endif
|
mgl@1371
|
21270 |
|
mgl@1371
|
21271 |
/* Linux has a feature called exec-shield-randomize that perturbs the
|
mgl@1371
|
21272 |
address of non-fixed mapped segments by a (relatively) small amount.
|
mgl@1371
|
21273 |
--- a/gcc/config.gcc
|
mgl@1371
|
21274 |
+++ b/gcc/config.gcc
|
mgl@1371
|
21275 |
@@ -781,6 +781,24 @@ avr-*-*)
|
mgl@1371
|
21276 |
tm_file="avr/avr.h dbxelf.h"
|
mgl@1371
|
21277 |
use_fixproto=yes
|
mgl@1371
|
21278 |
;;
|
mgl@1371
|
21279 |
+avr32*-*-linux*)
|
mgl@1371
|
21280 |
+ tm_file="dbxelf.h elfos.h linux.h avr32/linux-elf.h avr32/avr32.h "
|
mgl@1371
|
21281 |
+ tmake_file="t-linux avr32/t-avr32 avr32/t-elf"
|
mgl@1371
|
21282 |
+ extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
|
mgl@1371
|
21283 |
+ extra_modes=avr32/avr32-modes.def
|
mgl@1371
|
21284 |
+ gnu_ld=yes
|
mgl@1371
|
21285 |
+ ;;
|
mgl@1371
|
21286 |
+avr32*-*-uclinux*)
|
mgl@1371
|
21287 |
+ tm_file="dbxelf.h elfos.h linux.h avr32/linux-elf.h avr32/uclinux-elf.h avr32/avr32.h"
|
mgl@1371
|
21288 |
+ tmake_file="t-linux avr32/t-avr32 avr32/t-elf"
|
mgl@1371
|
21289 |
+ extra_modes=avr32/avr32-modes.def
|
mgl@1371
|
21290 |
+ gnu_ld=yes
|
mgl@1371
|
21291 |
+ ;;
|
mgl@1371
|
21292 |
+avr32-*-*)
|
mgl@1371
|
21293 |
+ tm_file="dbxelf.h elfos.h avr32/avr32.h avr32/avr32-elf.h"
|
mgl@1371
|
21294 |
+ tmake_file="avr32/t-avr32 avr32/t-elf"
|
mgl@1371
|
21295 |
+ extra_modes=avr32/avr32-modes.def
|
mgl@1371
|
21296 |
+ ;;
|
mgl@1371
|
21297 |
bfin*-elf*)
|
mgl@1371
|
21298 |
tm_file="${tm_file} dbxelf.h elfos.h bfin/elf.h"
|
mgl@1371
|
21299 |
tmake_file=bfin/t-bfin-elf
|
mgl@1371
|
21300 |
@@ -1681,6 +1699,9 @@ pdp11-*-bsd)
|
mgl@1371
|
21301 |
pdp11-*-*)
|
mgl@1371
|
21302 |
use_fixproto=yes
|
mgl@1371
|
21303 |
;;
|
mgl@1371
|
21304 |
+avr-*-*)
|
mgl@1371
|
21305 |
+ use_fixproto=yes
|
mgl@1371
|
21306 |
+ ;;
|
mgl@1371
|
21307 |
# port not yet contributed
|
mgl@1371
|
21308 |
#powerpc-*-openbsd*)
|
mgl@1371
|
21309 |
# tmake_file="${tmake_file} rs6000/t-fprules rs6000/t-fprules-fpbit "
|
mgl@1371
|
21310 |
@@ -2717,6 +2738,32 @@ case "${target}" in
|
mgl@1371
|
21311 |
fi
|
mgl@1371
|
21312 |
;;
|
mgl@1371
|
21313 |
|
mgl@1371
|
21314 |
+ avr32*-*-*)
|
mgl@1371
|
21315 |
+ supported_defaults="part arch"
|
mgl@1371
|
21316 |
+
|
mgl@1371
|
21317 |
+ case "$with_part" in
|
mgl@1371
|
21318 |
+ "" \
|
mgl@1371
|
21319 |
+ | "ap7000" | "ap7010" | "ap7020" | "uc3a0256" | "uc3a0512" | "uc3a1128" | "uc3a1256" | "uc3a1512" )
|
mgl@1371
|
21320 |
+ # OK
|
mgl@1371
|
21321 |
+ ;;
|
mgl@1371
|
21322 |
+ *)
|
mgl@1371
|
21323 |
+ echo "Unknown part used in --with-part=$with_part" 1>&2
|
mgl@1371
|
21324 |
+ exit 1
|
mgl@1371
|
21325 |
+ ;;
|
mgl@1371
|
21326 |
+ esac
|
mgl@1371
|
21327 |
+
|
mgl@1371
|
21328 |
+ case "$with_arch" in
|
mgl@1371
|
21329 |
+ "" \
|
mgl@1371
|
21330 |
+ | "ap" | "uc")
|
mgl@1371
|
21331 |
+ # OK
|
mgl@1371
|
21332 |
+ ;;
|
mgl@1371
|
21333 |
+ *)
|
mgl@1371
|
21334 |
+ echo "Unknown arch used in --with-arch=$with_arch" 1>&2
|
mgl@1371
|
21335 |
+ exit 1
|
mgl@1371
|
21336 |
+ ;;
|
mgl@1371
|
21337 |
+ esac
|
mgl@1371
|
21338 |
+ ;;
|
mgl@1371
|
21339 |
+
|
mgl@1371
|
21340 |
fr*-*-*linux*)
|
mgl@1371
|
21341 |
supported_defaults=cpu
|
mgl@1371
|
21342 |
case "$with_cpu" in
|
mgl@1371
|
21343 |
--- a/gcc/doc/extend.texi
|
mgl@1371
|
21344 |
+++ b/gcc/doc/extend.texi
|
mgl@1371
|
21345 |
@@ -1981,7 +1981,7 @@ this attribute to work correctly.
|
mgl@1371
|
21346 |
|
mgl@1371
|
21347 |
@item interrupt
|
mgl@1371
|
21348 |
@cindex interrupt handler functions
|
mgl@1371
|
21349 |
-Use this attribute on the ARM, AVR, C4x, CRX, M32C, M32R/D, MS1, and Xstormy16
|
mgl@1371
|
21350 |
+Use this attribute on the ARM, AVR, AVR32, C4x, CRX, M32C, M32R/D, MS1, and Xstormy16
|
mgl@1371
|
21351 |
ports to indicate that the specified function is an interrupt handler.
|
mgl@1371
|
21352 |
The compiler will generate function entry and exit sequences suitable
|
mgl@1371
|
21353 |
for use in an interrupt handler when this attribute is present.
|
mgl@1371
|
21354 |
@@ -2000,6 +2000,15 @@ void f () __attribute__ ((interrupt ("IR
|
mgl@1371
|
21355 |
|
mgl@1371
|
21356 |
Permissible values for this parameter are: IRQ, FIQ, SWI, ABORT and UNDEF@.
|
mgl@1371
|
21357 |
|
mgl@1371
|
21358 |
+Note, for the AVR32, you can specify which banking scheme is used for
|
mgl@1371
|
21359 |
+the interrupt mode this interrupt handler is used in like this:
|
mgl@1371
|
21360 |
+
|
mgl@1371
|
21361 |
+@smallexample
|
mgl@1371
|
21362 |
+void f () __attribute__ ((interrupt ("FULL")));
|
mgl@1371
|
21363 |
+@end smallexample
|
mgl@1371
|
21364 |
+
|
mgl@1371
|
21365 |
+Permissible values for this parameter are: FULL, HALF, NONE and UNDEF.
|
mgl@1371
|
21366 |
+
|
mgl@1371
|
21367 |
@item interrupt_handler
|
mgl@1371
|
21368 |
@cindex interrupt handler functions on the Blackfin, m68k, H8/300 and SH processors
|
mgl@1371
|
21369 |
Use this attribute on the Blackfin, m68k, H8/300, H8/300H, H8S, and SH to
|
mgl@1371
|
21370 |
@@ -3460,6 +3469,23 @@ placed in either the @code{.bss_below100
|
mgl@1371
|
21371 |
|
mgl@1371
|
21372 |
@end table
|
mgl@1371
|
21373 |
|
mgl@1371
|
21374 |
+@subsection AVR32 Variable Attributes
|
mgl@1371
|
21375 |
+
|
mgl@1371
|
21376 |
+One attribute is currently defined for AVR32 configurations:
|
mgl@1371
|
21377 |
+@code{rmw_addressable}
|
mgl@1371
|
21378 |
+
|
mgl@1371
|
21379 |
+@table @code
|
mgl@1371
|
21380 |
+@item rmw_addressable
|
mgl@1371
|
21381 |
+@cindex @code{rmw_addressable} attribute
|
mgl@1371
|
21382 |
+
|
mgl@1371
|
21383 |
+This attribute can be used to signal that a variable can be accessed
|
mgl@1371
|
21384 |
+with the addressing mode of the AVR32 Atomic Read-Modify-Write memory
|
mgl@1371
|
21385 |
+instructions and hence make it possible for gcc to generate these
|
mgl@1371
|
21386 |
+instructions without using built-in functions or inline assembly statements.
|
mgl@1371
|
21387 |
+Variables used within the AVR32 Atomic Read-Modify-Write built-in
|
mgl@1371
|
21388 |
+functions will automatically get the @code{rmw_addressable} attribute.
|
mgl@1371
|
21389 |
+@end table
|
mgl@1371
|
21390 |
+
|
mgl@1371
|
21391 |
@node Type Attributes
|
mgl@1371
|
21392 |
@section Specifying Attributes of Types
|
mgl@1371
|
21393 |
@cindex attribute of types
|
mgl@1371
|
21394 |
@@ -6167,6 +6193,7 @@ instructions, but allow the compiler to
|
mgl@1371
|
21395 |
@menu
|
mgl@1371
|
21396 |
* Alpha Built-in Functions::
|
mgl@1371
|
21397 |
* ARM Built-in Functions::
|
mgl@1371
|
21398 |
+* AVR32 Built-in Functions::
|
mgl@1371
|
21399 |
* Blackfin Built-in Functions::
|
mgl@1371
|
21400 |
* FR-V Built-in Functions::
|
mgl@1371
|
21401 |
* X86 Built-in Functions::
|
mgl@1371
|
21402 |
@@ -6405,6 +6432,76 @@ long long __builtin_arm_wxor (long long,
|
mgl@1371
|
21403 |
long long __builtin_arm_wzero ()
|
mgl@1371
|
21404 |
@end smallexample
|
mgl@1371
|
21405 |
|
mgl@1371
|
21406 |
+@node AVR32 Built-in Functions
|
mgl@1371
|
21407 |
+@subsection AVR32 Built-in Functions
|
mgl@1371
|
21408 |
+
|
mgl@1371
|
21409 |
+
|
mgl@1371
|
21410 |
+
|
mgl@1371
|
21411 |
+Built-in functions for atomic memory (RMW) instructions. Note that these
|
mgl@1371
|
21412 |
+built-ins will fail for targets where the RMW instructions are not
|
mgl@1371
|
21413 |
+implemented. Also note that these instructions only that a Ks15 << 2
|
mgl@1371
|
21414 |
+memory address and will therefor not work with any runtime computed
|
mgl@1371
|
21415 |
+memory addresses. The user is responsible for making sure that any
|
mgl@1371
|
21416 |
+pointers used within these functions points to a valid memory address.
|
mgl@1371
|
21417 |
+
|
mgl@1371
|
21418 |
+@smallexample
|
mgl@1371
|
21419 |
+void __builtin_mems(int */*ptr*/, int /*bit*/)
|
mgl@1371
|
21420 |
+void __builtin_memc(int */*ptr*/, int /*bit*/)
|
mgl@1371
|
21421 |
+void __builtin_memt(int */*ptr*/, int /*bit*/)
|
mgl@1371
|
21422 |
+@end smallexample
|
mgl@1371
|
21423 |
+
|
mgl@1371
|
21424 |
+Built-in functions for DSP instructions. Note that these built-ins will
|
mgl@1371
|
21425 |
+fail for targets where the DSP instructions are not implemented.
|
mgl@1371
|
21426 |
+
|
mgl@1371
|
21427 |
+@smallexample
|
mgl@1371
|
21428 |
+int __builtin_sats (int /*Rd*/,int /*sa*/, int /*bn*/)
|
mgl@1371
|
21429 |
+int __builtin_satu (int /*Rd*/,int /*sa*/, int /*bn*/)
|
mgl@1371
|
21430 |
+int __builtin_satrnds (int /*Rd*/,int /*sa*/, int /*bn*/)
|
mgl@1371
|
21431 |
+int __builtin_satrndu (int /*Rd*/,int /*sa*/, int /*bn*/)
|
mgl@1371
|
21432 |
+short __builtin_mulsathh_h (short, short)
|
mgl@1371
|
21433 |
+int __builtin_mulsathh_w (short, short)
|
mgl@1371
|
21434 |
+short __builtin_mulsatrndhh_h (short, short)
|
mgl@1371
|
21435 |
+int __builtin_mulsatrndwh_w (int, short)
|
mgl@1371
|
21436 |
+int __builtin_mulsatwh_w (int, short)
|
mgl@1371
|
21437 |
+int __builtin_macsathh_w (int, short, short)
|
mgl@1371
|
21438 |
+short __builtin_satadd_h (short, short)
|
mgl@1371
|
21439 |
+short __builtin_satsub_h (short, short)
|
mgl@1371
|
21440 |
+int __builtin_satadd_w (int, int)
|
mgl@1371
|
21441 |
+int __builtin_satsub_w (int, int)
|
mgl@1371
|
21442 |
+long long __builtin_mulwh_d(int, short)
|
mgl@1371
|
21443 |
+long long __builtin_mulnwh_d(int, short)
|
mgl@1371
|
21444 |
+long long __builtin_macwh_d(long long, int, short)
|
mgl@1371
|
21445 |
+long long __builtin_machh_d(long long, short, short)
|
mgl@1371
|
21446 |
+@end smallexample
|
mgl@1371
|
21447 |
+
|
mgl@1371
|
21448 |
+Other built-in functions for instructions that cannot easily be
|
mgl@1371
|
21449 |
+generated by the compiler.
|
mgl@1371
|
21450 |
+
|
mgl@1371
|
21451 |
+@smallexample
|
mgl@1371
|
21452 |
+void __builtin_ssrf(int);
|
mgl@1371
|
21453 |
+void __builtin_csrf(int);
|
mgl@1371
|
21454 |
+void __builtin_musfr(int);
|
mgl@1371
|
21455 |
+int __builtin_mustr(void);
|
mgl@1371
|
21456 |
+int __builtin_mfsr(int /*Status Register Address*/)
|
mgl@1371
|
21457 |
+void __builtin_mtsr(int /*Status Register Address*/, int /*Value*/)
|
mgl@1371
|
21458 |
+int __builtin_mfdr(int /*Debug Register Address*/)
|
mgl@1371
|
21459 |
+void __builtin_mtdr(int /*Debug Register Address*/, int /*Value*/)
|
mgl@1371
|
21460 |
+void __builtin_cache(void * /*Address*/, int /*Cache Operation*/)
|
mgl@1371
|
21461 |
+void __builtin_sync(int /*Sync Operation*/)
|
mgl@1371
|
21462 |
+void __builtin_tlbr(void)
|
mgl@1371
|
21463 |
+void __builtin_tlbs(void)
|
mgl@1371
|
21464 |
+void __builtin_tlbw(void)
|
mgl@1371
|
21465 |
+void __builtin_breakpoint(void)
|
mgl@1371
|
21466 |
+int __builtin_xchg(void * /*Address*/, int /*Value*/ )
|
mgl@1371
|
21467 |
+short __builtin_bswap_16(short)
|
mgl@1371
|
21468 |
+int __builtin_bswap_32(int)
|
mgl@1371
|
21469 |
+void __builtin_cop(int/*cpnr*/, int/*crd*/, int/*crx*/, int/*cry*/, int/*op*/)
|
mgl@1371
|
21470 |
+int __builtin_mvcr_w(int/*cpnr*/, int/*crs*/)
|
mgl@1371
|
21471 |
+void __builtin_mvrc_w(int/*cpnr*/, int/*crd*/, int/*value*/)
|
mgl@1371
|
21472 |
+long long __builtin_mvcr_d(int/*cpnr*/, int/*crs*/)
|
mgl@1371
|
21473 |
+void __builtin_mvrc_d(int/*cpnr*/, int/*crd*/, long long/*value*/)
|
mgl@1371
|
21474 |
+@end smallexample
|
mgl@1371
|
21475 |
+
|
mgl@1371
|
21476 |
@node Blackfin Built-in Functions
|
mgl@1371
|
21477 |
@subsection Blackfin Built-in Functions
|
mgl@1371
|
21478 |
|
mgl@1371
|
21479 |
--- a/gcc/doc/invoke.texi
|
mgl@1371
|
21480 |
+++ b/gcc/doc/invoke.texi
|
mgl@1371
|
21481 |
@@ -190,7 +190,7 @@ in the following sections.
|
mgl@1371
|
21482 |
-fno-default-inline -fvisibility-inlines-hidden @gol
|
mgl@1371
|
21483 |
-Wabi -Wctor-dtor-privacy @gol
|
mgl@1371
|
21484 |
-Wnon-virtual-dtor -Wreorder @gol
|
mgl@1371
|
21485 |
--Weffc++ -Wno-deprecated -Wstrict-null-sentinel @gol
|
mgl@1371
|
21486 |
+-Weffc++ -Wno-deprecated @gol
|
mgl@1371
|
21487 |
-Wno-non-template-friend -Wold-style-cast @gol
|
mgl@1371
|
21488 |
-Woverloaded-virtual -Wno-pmf-conversions @gol
|
mgl@1371
|
21489 |
-Wsign-promo}
|
mgl@1371
|
21490 |
@@ -588,6 +588,12 @@ Objective-C and Objective-C++ Dialects}.
|
mgl@1371
|
21491 |
-mauto-incdec -minmax -mlong-calls -mshort @gol
|
mgl@1371
|
21492 |
-msoft-reg-count=@var{count}}
|
mgl@1371
|
21493 |
|
mgl@1371
|
21494 |
+@emph{AVR32 Options}
|
mgl@1371
|
21495 |
+@gccoptlist{-muse-rodata-section -mhard-float -msoft-float -mrelax @gol
|
mgl@1371
|
21496 |
+-mforce-double-align -mno-init-got -mrelax -mmd-reorg-opt -masm-addr-pseudos @gol
|
mgl@1371
|
21497 |
+-mpart=@var{part} -mcpu=@var{cpu} -march=@var{arch} @gol
|
mgl@1371
|
21498 |
+-mfast-float -mimm-in-const-pool}
|
mgl@1371
|
21499 |
+
|
mgl@1371
|
21500 |
@emph{MCore Options}
|
mgl@1371
|
21501 |
@gccoptlist{-mhardlit -mno-hardlit -mdiv -mno-div -mrelax-immediates @gol
|
mgl@1371
|
21502 |
-mno-relax-immediates -mwide-bitfields -mno-wide-bitfields @gol
|
mgl@1371
|
21503 |
@@ -1868,14 +1874,6 @@ to filter out those warnings.
|
mgl@1371
|
21504 |
@opindex Wno-deprecated
|
mgl@1371
|
21505 |
Do not warn about usage of deprecated features. @xref{Deprecated Features}.
|
mgl@1371
|
21506 |
|
mgl@1371
|
21507 |
-@item -Wstrict-null-sentinel @r{(C++ only)}
|
mgl@1371
|
21508 |
-@opindex Wstrict-null-sentinel
|
mgl@1371
|
21509 |
-Warn also about the use of an uncasted @code{NULL} as sentinel. When
|
mgl@1371
|
21510 |
-compiling only with GCC this is a valid sentinel, as @code{NULL} is defined
|
mgl@1371
|
21511 |
-to @code{__null}. Although it is a null pointer constant not a null pointer,
|
mgl@1371
|
21512 |
-it is guaranteed to of the same size as a pointer. But this use is
|
mgl@1371
|
21513 |
-not portable across different compilers.
|
mgl@1371
|
21514 |
-
|
mgl@1371
|
21515 |
@item -Wno-non-template-friend @r{(C++ only)}
|
mgl@1371
|
21516 |
@opindex Wno-non-template-friend
|
mgl@1371
|
21517 |
Disable warnings when non-templatized friend functions are declared
|
mgl@1371
|
21518 |
@@ -2732,13 +2730,11 @@ requiring @option{-O}.
|
mgl@1371
|
21519 |
If you want to warn about code which uses the uninitialized value of the
|
mgl@1371
|
21520 |
variable in its own initializer, use the @option{-Winit-self} option.
|
mgl@1371
|
21521 |
|
mgl@1371
|
21522 |
-These warnings occur for individual uninitialized or clobbered
|
mgl@1371
|
21523 |
-elements of structure, union or array variables as well as for
|
mgl@1371
|
21524 |
-variables which are uninitialized or clobbered as a whole. They do
|
mgl@1371
|
21525 |
-not occur for variables or elements declared @code{volatile}. Because
|
mgl@1371
|
21526 |
-these warnings depend on optimization, the exact variables or elements
|
mgl@1371
|
21527 |
-for which there are warnings will depend on the precise optimization
|
mgl@1371
|
21528 |
-options and version of GCC used.
|
mgl@1371
|
21529 |
+These warnings occur only for variables that are candidates for
|
mgl@1371
|
21530 |
+register allocation. Therefore, they do not occur for a variable that
|
mgl@1371
|
21531 |
+is declared @code{volatile}, or whose address is taken, or whose size
|
mgl@1371
|
21532 |
+is other than 1, 2, 4 or 8 bytes. Also, they do not occur for
|
mgl@1371
|
21533 |
+structures, unions or arrays, even when they are in registers.
|
mgl@1371
|
21534 |
|
mgl@1371
|
21535 |
Note that there may be no warning about a variable that is used only
|
mgl@1371
|
21536 |
to compute a value that itself is never used, because such
|
mgl@1371
|
21537 |
@@ -6201,10 +6197,6 @@ If number of candidates in the set is sm
|
mgl@1371
|
21538 |
we always try to remove unnecessary ivs from the set during its
|
mgl@1371
|
21539 |
optimization when a new iv is added to the set.
|
mgl@1371
|
21540 |
|
mgl@1371
|
21541 |
-@item scev-max-expr-size
|
mgl@1371
|
21542 |
-Bound on size of expressions used in the scalar evolutions analyzer.
|
mgl@1371
|
21543 |
-Large expressions slow the analyzer.
|
mgl@1371
|
21544 |
-
|
mgl@1371
|
21545 |
@item vect-max-version-checks
|
mgl@1371
|
21546 |
The maximum number of runtime checks that can be performed when doing
|
mgl@1371
|
21547 |
loop versioning in the vectorizer. See option ftree-vect-loop-version
|
mgl@1371
|
21548 |
@@ -7402,7 +7394,7 @@ platform.
|
mgl@1371
|
21549 |
* ARC Options::
|
mgl@1371
|
21550 |
* ARM Options::
|
mgl@1371
|
21551 |
* AVR Options::
|
mgl@1371
|
21552 |
-* Blackfin Options::
|
mgl@1371
|
21553 |
+* AVR32 Options::
|
mgl@1371
|
21554 |
* CRIS Options::
|
mgl@1371
|
21555 |
* CRX Options::
|
mgl@1371
|
21556 |
* Darwin Options::
|
mgl@1371
|
21557 |
@@ -7867,81 +7859,80 @@ comply to the C standards, but it will p
|
mgl@1371
|
21558 |
size.
|
mgl@1371
|
21559 |
@end table
|
mgl@1371
|
21560 |
|
mgl@1371
|
21561 |
-@node Blackfin Options
|
mgl@1371
|
21562 |
-@subsection Blackfin Options
|
mgl@1371
|
21563 |
-@cindex Blackfin Options
|
mgl@1371
|
21564 |
+@node AVR32 Options
|
mgl@1371
|
21565 |
+@subsection AVR32 Options
|
mgl@1371
|
21566 |
+@cindex AVR32 Options
|
mgl@1371
|
21567 |
+
|
mgl@1371
|
21568 |
+These options are defined for AVR32 implementations:
|
mgl@1371
|
21569 |
|
mgl@1371
|
21570 |
@table @gcctabopt
|
mgl@1371
|
21571 |
-@item -momit-leaf-frame-pointer
|
mgl@1371
|
21572 |
-@opindex momit-leaf-frame-pointer
|
mgl@1371
|
21573 |
-Don't keep the frame pointer in a register for leaf functions. This
|
mgl@1371
|
21574 |
-avoids the instructions to save, set up and restore frame pointers and
|
mgl@1371
|
21575 |
-makes an extra register available in leaf functions. The option
|
mgl@1371
|
21576 |
-@option{-fomit-frame-pointer} removes the frame pointer for all functions
|
mgl@1371
|
21577 |
-which might make debugging harder.
|
mgl@1371
|
21578 |
+@item -muse-rodata-section
|
mgl@1371
|
21579 |
+@opindex muse-rodata-section
|
mgl@1371
|
21580 |
+Use section @samp{.rodata} for read-only data instead of @samp{.text}.
|
mgl@1371
|
21581 |
|
mgl@1371
|
21582 |
-@item -mspecld-anomaly
|
mgl@1371
|
21583 |
-@opindex mspecld-anomaly
|
mgl@1371
|
21584 |
-When enabled, the compiler will ensure that the generated code does not
|
mgl@1371
|
21585 |
-contain speculative loads after jump instructions. This option is enabled
|
mgl@1371
|
21586 |
-by default.
|
mgl@1371
|
21587 |
-
|
mgl@1371
|
21588 |
-@item -mno-specld-anomaly
|
mgl@1371
|
21589 |
-@opindex mno-specld-anomaly
|
mgl@1371
|
21590 |
-Don't generate extra code to prevent speculative loads from occurring.
|
mgl@1371
|
21591 |
-
|
mgl@1371
|
21592 |
-@item -mcsync-anomaly
|
mgl@1371
|
21593 |
-@opindex mcsync-anomaly
|
mgl@1371
|
21594 |
-When enabled, the compiler will ensure that the generated code does not
|
mgl@1371
|
21595 |
-contain CSYNC or SSYNC instructions too soon after conditional branches.
|
mgl@1371
|
21596 |
-This option is enabled by default.
|
mgl@1371
|
21597 |
-
|
mgl@1371
|
21598 |
-@item -mno-csync-anomaly
|
mgl@1371
|
21599 |
-@opindex mno-csync-anomaly
|
mgl@1371
|
21600 |
-Don't generate extra code to prevent CSYNC or SSYNC instructions from
|
mgl@1371
|
21601 |
-occurring too soon after a conditional branch.
|
mgl@1371
|
21602 |
-
|
mgl@1371
|
21603 |
-@item -mlow-64k
|
mgl@1371
|
21604 |
-@opindex mlow-64k
|
mgl@1371
|
21605 |
-When enabled, the compiler is free to take advantage of the knowledge that
|
mgl@1371
|
21606 |
-the entire program fits into the low 64k of memory.
|
mgl@1371
|
21607 |
-
|
mgl@1371
|
21608 |
-@item -mno-low-64k
|
mgl@1371
|
21609 |
-@opindex mno-low-64k
|
mgl@1371
|
21610 |
-Assume that the program is arbitrarily large. This is the default.
|
mgl@1371
|
21611 |
+@item -mhard-float
|
mgl@1371
|
21612 |
+@opindex mhard-float
|
mgl@1371
|
21613 |
+Use floating point coprocessor instructions.
|
mgl@1371
|
21614 |
|
mgl@1371
|
21615 |
-@item -mid-shared-library
|
mgl@1371
|
21616 |
-@opindex mid-shared-library
|
mgl@1371
|
21617 |
-Generate code that supports shared libraries via the library ID method.
|
mgl@1371
|
21618 |
-This allows for execute in place and shared libraries in an environment
|
mgl@1371
|
21619 |
-without virtual memory management. This option implies @option{-fPIC}.
|
mgl@1371
|
21620 |
+@item -msoft-float
|
mgl@1371
|
21621 |
+@opindex msoft-float
|
mgl@1371
|
21622 |
+Use software floating-point library for floating-point operations.
|
mgl@1371
|
21623 |
|
mgl@1371
|
21624 |
-@item -mno-id-shared-library
|
mgl@1371
|
21625 |
-@opindex mno-id-shared-library
|
mgl@1371
|
21626 |
-Generate code that doesn't assume ID based shared libraries are being used.
|
mgl@1371
|
21627 |
-This is the default.
|
mgl@1371
|
21628 |
+@item -mforce-double-align
|
mgl@1371
|
21629 |
+@opindex mforce-double-align
|
mgl@1371
|
21630 |
+Force double-word alignment for double-word memory accesses.
|
mgl@1371
|
21631 |
+
|
mgl@1371
|
21632 |
+@item -mno-init-got
|
mgl@1371
|
21633 |
+@opindex mno-init-got
|
mgl@1371
|
21634 |
+Do not initialize the GOT register before using it when compiling PIC
|
mgl@1371
|
21635 |
+code.
|
mgl@1371
|
21636 |
|
mgl@1371
|
21637 |
-@item -mshared-library-id=n
|
mgl@1371
|
21638 |
-@opindex mshared-library-id
|
mgl@1371
|
21639 |
-Specified the identification number of the ID based shared library being
|
mgl@1371
|
21640 |
-compiled. Specifying a value of 0 will generate more compact code, specifying
|
mgl@1371
|
21641 |
-other values will force the allocation of that number to the current
|
mgl@1371
|
21642 |
-library but is no more space or time efficient than omitting this option.
|
mgl@1371
|
21643 |
+@item -mrelax
|
mgl@1371
|
21644 |
+@opindex mrelax
|
mgl@1371
|
21645 |
+Let invoked assembler and linker do relaxing
|
mgl@1371
|
21646 |
+(Enabled by default when optimization level is >1).
|
mgl@1371
|
21647 |
+This means that when the address of symbols are known at link time,
|
mgl@1371
|
21648 |
+the linker can optimize @samp{icall} and @samp{mcall}
|
mgl@1371
|
21649 |
+instructions into a @samp{rcall} instruction if possible.
|
mgl@1371
|
21650 |
+Loading the address of a symbol can also be optimized.
|
mgl@1371
|
21651 |
+
|
mgl@1371
|
21652 |
+@item -mmd-reorg-opt
|
mgl@1371
|
21653 |
+@opindex mmd-reorg-opt
|
mgl@1371
|
21654 |
+Perform machine dependent optimizations in reorg stage.
|
mgl@1371
|
21655 |
+
|
mgl@1371
|
21656 |
+@item -masm-addr-pseudos
|
mgl@1371
|
21657 |
+@opindex masm-addr-pseudos
|
mgl@1371
|
21658 |
+Use assembler pseudo-instructions lda.w and call for handling direct
|
mgl@1371
|
21659 |
+addresses. (Enabled by default)
|
mgl@1371
|
21660 |
+
|
mgl@1371
|
21661 |
+@item -mpart=@var{part}
|
mgl@1371
|
21662 |
+@opindex mpart
|
mgl@1371
|
21663 |
+Generate code for the specified part. Permissible parts are:
|
mgl@1371
|
21664 |
+@samp{ap7000}, @samp{ap7010},@samp{ap7020},
|
mgl@1371
|
21665 |
+@samp{uc3a0128}, @samp{uc3a0256}, @samp{uc3a0512},
|
mgl@1371
|
21666 |
+@samp{uc3a1128}, @samp{uc3a1256}, @samp{uc3a1512},
|
mgl@1371
|
21667 |
+@samp{uc3b064}, @samp{uc3b0128}, @samp{uc3b0256},
|
mgl@1371
|
21668 |
+@samp{uc3b164}, @samp{uc3b1128}, @samp{uc3b1256}.
|
mgl@1371
|
21669 |
|
mgl@1371
|
21670 |
-@item -mlong-calls
|
mgl@1371
|
21671 |
-@itemx -mno-long-calls
|
mgl@1371
|
21672 |
-@opindex mlong-calls
|
mgl@1371
|
21673 |
-@opindex mno-long-calls
|
mgl@1371
|
21674 |
-Tells the compiler to perform function calls by first loading the
|
mgl@1371
|
21675 |
-address of the function into a register and then performing a subroutine
|
mgl@1371
|
21676 |
-call on this register. This switch is needed if the target function
|
mgl@1371
|
21677 |
-will lie outside of the 24 bit addressing range of the offset based
|
mgl@1371
|
21678 |
-version of subroutine call instruction.
|
mgl@1371
|
21679 |
+@item -mcpu=@var{cpu-type}
|
mgl@1371
|
21680 |
+@opindex mcpu
|
mgl@1371
|
21681 |
+Same as -mpart. Obsolete.
|
mgl@1371
|
21682 |
+
|
mgl@1371
|
21683 |
+@item -march=@var{arch}
|
mgl@1371
|
21684 |
+@opindex march
|
mgl@1371
|
21685 |
+Generate code for the specified architecture. Permissible architectures are:
|
mgl@1371
|
21686 |
+@samp{ap} and @samp{uc}.
|
mgl@1371
|
21687 |
+
|
mgl@1371
|
21688 |
+@item -mfast-float
|
mgl@1371
|
21689 |
+@opindex mfast-float
|
mgl@1371
|
21690 |
+Enable fast floating-point library that does not conform to ieee but is still good enough
|
mgl@1371
|
21691 |
+for most applications. The fast floating-point library does not round to the nearest even
|
mgl@1371
|
21692 |
+but away from zero. Enabled by default if the -funsafe-math-optimizations switch is specified.
|
mgl@1371
|
21693 |
+
|
mgl@1371
|
21694 |
+@item -mimm-in-const-pool
|
mgl@1371
|
21695 |
+@opindex mimm-in-const-pool
|
mgl@1371
|
21696 |
+Put large immediates in constant pool. This is enabled by default for archs with insn-cache.
|
mgl@1371
|
21697 |
|
mgl@1371
|
21698 |
-This feature is not enabled by default. Specifying
|
mgl@1371
|
21699 |
-@option{-mno-long-calls} will restore the default behavior. Note these
|
mgl@1371
|
21700 |
-switches have no effect on how the compiler generates code to handle
|
mgl@1371
|
21701 |
-function calls via function pointers.
|
mgl@1371
|
21702 |
@end table
|
mgl@1371
|
21703 |
|
mgl@1371
|
21704 |
@node CRIS Options
|
mgl@1371
|
21705 |
--- a/gcc/doc/md.texi
|
mgl@1371
|
21706 |
+++ b/gcc/doc/md.texi
|
mgl@1371
|
21707 |
@@ -1681,6 +1681,80 @@ A memory reference suitable for iWMMXt l
|
mgl@1371
|
21708 |
A memory reference suitable for the ARMv4 ldrsb instruction.
|
mgl@1371
|
21709 |
@end table
|
mgl@1371
|
21710 |
|
mgl@1371
|
21711 |
+@item AVR32 family---@file{avr32.h}
|
mgl@1371
|
21712 |
+@table @code
|
mgl@1371
|
21713 |
+@item f
|
mgl@1371
|
21714 |
+Floating-point registers (f0 to f15) (Reserved for future use)
|
mgl@1371
|
21715 |
+
|
mgl@1371
|
21716 |
+@item Ku@var{bits}
|
mgl@1371
|
21717 |
+Unsigned constant representable with @var{bits} number of bits (Must be
|
mgl@1371
|
21718 |
+two digits). I.e: An unsigned 8-bit constant is written as @samp{Ku08}
|
mgl@1371
|
21719 |
+
|
mgl@1371
|
21720 |
+@item Ks@var{bits}
|
mgl@1371
|
21721 |
+Signed constant representable with @var{bits} number of bits (Must be
|
mgl@1371
|
21722 |
+two digits). I.e: A signed 12-bit constant is written as @samp{Ks12}
|
mgl@1371
|
21723 |
+
|
mgl@1371
|
21724 |
+@item Is@var{bits}
|
mgl@1371
|
21725 |
+The negated range of a signed constant representable with @var{bits}
|
mgl@1371
|
21726 |
+number of bits. The same as @samp{Ks@var{bits}} with a negated range.
|
mgl@1371
|
21727 |
+This means that the constant must be in the range @math{-2^{bits-1}-1} to @math{2^{bits-1}}
|
mgl@1371
|
21728 |
+
|
mgl@1371
|
21729 |
+@item G
|
mgl@1371
|
21730 |
+A single/double precision floating-point immediate or 64-bit integer
|
mgl@1371
|
21731 |
+immediate where the least and most significant words both can be
|
mgl@1371
|
21732 |
+loaded with a move instruction. That is the the integer form of the
|
mgl@1371
|
21733 |
+values in the least and most significant words both are in the range
|
mgl@1371
|
21734 |
+@math{-2^{20}} to @math{2^{20}-1}.
|
mgl@1371
|
21735 |
+
|
mgl@1371
|
21736 |
+@item M
|
mgl@1371
|
21737 |
+Any 32-bit immediate with the most significant bits set to zero and the
|
mgl@1371
|
21738 |
+remaining least significant bits set to one.
|
mgl@1371
|
21739 |
+
|
mgl@1371
|
21740 |
+@item J
|
mgl@1371
|
21741 |
+A 32-bit immediate where all the lower 16-bits are zero.
|
mgl@1371
|
21742 |
+
|
mgl@1371
|
21743 |
+@item O
|
mgl@1371
|
21744 |
+A 32-bit immediate with one bit set and the rest of the bits cleared.
|
mgl@1371
|
21745 |
+
|
mgl@1371
|
21746 |
+@item N
|
mgl@1371
|
21747 |
+A 32-bit immediate with one bit cleared and the rest of the bits set.
|
mgl@1371
|
21748 |
+
|
mgl@1371
|
21749 |
+@item L
|
mgl@1371
|
21750 |
+A 32-bit immediate where all the lower 16-bits are set.
|
mgl@1371
|
21751 |
+
|
mgl@1371
|
21752 |
+@item Q
|
mgl@1371
|
21753 |
+Any AVR32 memory reference except for reference used for the atomic memory (RMW) instructions.
|
mgl@1371
|
21754 |
+
|
mgl@1371
|
21755 |
+@item RKs@var{bits}
|
mgl@1371
|
21756 |
+A memory reference where the address consists of a base register
|
mgl@1371
|
21757 |
+plus a signed immediate displacement with range given by @samp{Ks@var{bits}}
|
mgl@1371
|
21758 |
+which has the same format as for the signed immediate integer constraint
|
mgl@1371
|
21759 |
+given above.
|
mgl@1371
|
21760 |
+
|
mgl@1371
|
21761 |
+@item RKu@var{bits}
|
mgl@1371
|
21762 |
+A memory reference where the address consists of a base register
|
mgl@1371
|
21763 |
+plus an unsigned immediate displacement with range given by @samp{Ku@var{bits}}
|
mgl@1371
|
21764 |
+which has the same format as for the unsigned immediate integer constraint
|
mgl@1371
|
21765 |
+given above.
|
mgl@1371
|
21766 |
+
|
mgl@1371
|
21767 |
+@item S
|
mgl@1371
|
21768 |
+A memory reference with an immediate or register offset
|
mgl@1371
|
21769 |
+
|
mgl@1371
|
21770 |
+@item T
|
mgl@1371
|
21771 |
+A memory reference to a constant pool entry
|
mgl@1371
|
21772 |
+
|
mgl@1371
|
21773 |
+@item W
|
mgl@1371
|
21774 |
+A valid operand for use in the @samp{lda.w} instruction macro when
|
mgl@1371
|
21775 |
+relaxing is enabled
|
mgl@1371
|
21776 |
+
|
mgl@1371
|
21777 |
+@item Y
|
mgl@1371
|
21778 |
+A memory reference suitable for the atomic memory (RMW) instructions.
|
mgl@1371
|
21779 |
+
|
mgl@1371
|
21780 |
+@item Z
|
mgl@1371
|
21781 |
+A memory reference valid for coprocessor memory instructions
|
mgl@1371
|
21782 |
+
|
mgl@1371
|
21783 |
+@end table
|
mgl@1371
|
21784 |
+
|
mgl@1371
|
21785 |
@item AVR family---@file{config/avr/constraints.md}
|
mgl@1371
|
21786 |
@table @code
|
mgl@1371
|
21787 |
@item l
|
mgl@1371
|
21788 |
--- a/gcc/expmed.c
|
mgl@1371
|
21789 |
+++ b/gcc/expmed.c
|
mgl@1371
|
21790 |
@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3.
|
mgl@1371
|
21791 |
#include "real.h"
|
mgl@1371
|
21792 |
#include "recog.h"
|
mgl@1371
|
21793 |
#include "langhooks.h"
|
mgl@1371
|
21794 |
+#include "target.h"
|
mgl@1371
|
21795 |
|
mgl@1371
|
21796 |
static void store_fixed_bit_field (rtx, unsigned HOST_WIDE_INT,
|
mgl@1371
|
21797 |
unsigned HOST_WIDE_INT,
|
mgl@1371
|
21798 |
@@ -454,9 +455,19 @@ store_bit_field (rtx str_rtx, unsigned H
|
mgl@1371
|
21799 |
? ((GET_MODE_SIZE (fieldmode) >= UNITS_PER_WORD
|
mgl@1371
|
21800 |
|| GET_MODE_SIZE (GET_MODE (op0)) == GET_MODE_SIZE (fieldmode))
|
mgl@1371
|
21801 |
&& byte_offset % GET_MODE_SIZE (fieldmode) == 0)
|
mgl@1371
|
21802 |
- : (! SLOW_UNALIGNED_ACCESS (fieldmode, MEM_ALIGN (op0))
|
mgl@1371
|
21803 |
- || (offset * BITS_PER_UNIT % bitsize == 0
|
mgl@1371
|
21804 |
- && MEM_ALIGN (op0) % GET_MODE_BITSIZE (fieldmode) == 0))))
|
mgl@1371
|
21805 |
+ : (
|
mgl@1371
|
21806 |
+
|
mgl@1371
|
21807 |
+ /* NB! Added for AVR32, and I think this should be true for
|
mgl@1371
|
21808 |
+ all targets not using narrow volatile bitfields. If the
|
mgl@1371
|
21809 |
+ bitfield is volatile then we need to perform an access
|
mgl@1371
|
21810 |
+ consistent with the container type. */
|
mgl@1371
|
21811 |
+ !(MEM_VOLATILE_P (op0)
|
mgl@1371
|
21812 |
+ && GET_MODE_BITSIZE (GET_MODE (op0)) != bitsize
|
mgl@1371
|
21813 |
+ && bitsize < BITS_PER_WORD
|
mgl@1371
|
21814 |
+ && !targetm.narrow_volatile_bitfield ())
|
mgl@1371
|
21815 |
+ && (! SLOW_UNALIGNED_ACCESS (fieldmode, MEM_ALIGN (op0))
|
mgl@1371
|
21816 |
+ || (offset * BITS_PER_UNIT % bitsize == 0
|
mgl@1371
|
21817 |
+ && MEM_ALIGN (op0) % GET_MODE_BITSIZE (fieldmode) == 0)))))
|
mgl@1371
|
21818 |
{
|
mgl@1371
|
21819 |
if (MEM_P (op0))
|
mgl@1371
|
21820 |
op0 = adjust_address (op0, fieldmode, offset);
|
mgl@1371
|
21821 |
@@ -1256,6 +1267,13 @@ extract_bit_field (rtx str_rtx, unsigned
|
mgl@1371
|
21822 |
&& GET_MODE_SIZE (mode1) != 0
|
mgl@1371
|
21823 |
&& byte_offset % GET_MODE_SIZE (mode1) == 0)
|
mgl@1371
|
21824 |
|| (MEM_P (op0)
|
mgl@1371
|
21825 |
+ /* NB! Added for AVR32, and I think this should be true for
|
mgl@1371
|
21826 |
+ all targets not using narrow volatile bitfields. If the
|
mgl@1371
|
21827 |
+ bitfield is volatile then we need to perform an access
|
mgl@1371
|
21828 |
+ consistent with the container type. */
|
mgl@1371
|
21829 |
+ && !(MEM_VOLATILE_P (op0)
|
mgl@1371
|
21830 |
+ && GET_MODE_BITSIZE (GET_MODE (op0)) != bitsize
|
mgl@1371
|
21831 |
+ && !targetm.narrow_volatile_bitfield ())
|
mgl@1371
|
21832 |
&& (! SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (op0))
|
mgl@1371
|
21833 |
|| (offset * BITS_PER_UNIT % bitsize == 0
|
mgl@1371
|
21834 |
&& MEM_ALIGN (op0) % bitsize == 0)))))
|
mgl@1371
|
21835 |
--- a/gcc/expr.c
|
mgl@1371
|
21836 |
+++ b/gcc/expr.c
|
mgl@1371
|
21837 |
@@ -3519,18 +3519,19 @@ emit_single_push_insn (enum machine_mode
|
mgl@1371
|
21838 |
}
|
mgl@1371
|
21839 |
else
|
mgl@1371
|
21840 |
{
|
mgl@1371
|
21841 |
+ emit_move_insn (stack_pointer_rtx,
|
mgl@1371
|
21842 |
+ expand_binop (Pmode,
|
mgl@1371
|
21843 |
#ifdef STACK_GROWS_DOWNWARD
|
mgl@1371
|
21844 |
- /* ??? This seems wrong if STACK_PUSH_CODE == POST_DEC. */
|
mgl@1371
|
21845 |
- dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
|
mgl@1371
|
21846 |
- GEN_INT (-(HOST_WIDE_INT) rounded_size));
|
mgl@1371
|
21847 |
+ sub_optab,
|
mgl@1371
|
21848 |
#else
|
mgl@1371
|
21849 |
- /* ??? This seems wrong if STACK_PUSH_CODE == POST_INC. */
|
mgl@1371
|
21850 |
- dest_addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
|
mgl@1371
|
21851 |
- GEN_INT (rounded_size));
|
mgl@1371
|
21852 |
+ add_optab,
|
mgl@1371
|
21853 |
#endif
|
mgl@1371
|
21854 |
- dest_addr = gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx, dest_addr);
|
mgl@1371
|
21855 |
+ stack_pointer_rtx,
|
mgl@1371
|
21856 |
+ GEN_INT (rounded_size),
|
mgl@1371
|
21857 |
+ NULL_RTX, 0, OPTAB_LIB_WIDEN));
|
mgl@1371
|
21858 |
+ dest_addr = stack_pointer_rtx;
|
mgl@1371
|
21859 |
}
|
mgl@1371
|
21860 |
-
|
mgl@1371
|
21861 |
+
|
mgl@1371
|
21862 |
dest = gen_rtx_MEM (mode, dest_addr);
|
mgl@1371
|
21863 |
|
mgl@1371
|
21864 |
if (type != 0)
|
mgl@1371
|
21865 |
@@ -5509,7 +5510,21 @@ store_field (rtx target, HOST_WIDE_INT b
|
mgl@1371
|
21866 |
is a bit field, we cannot use addressing to access it.
|
mgl@1371
|
21867 |
Use bit-field techniques or SUBREG to store in it. */
|
mgl@1371
|
21868 |
|
mgl@1371
|
21869 |
- if (mode == VOIDmode
|
mgl@1371
|
21870 |
+ if (
|
mgl@1371
|
21871 |
+ /* NB! Added for AVR32, and I think this should be true for
|
mgl@1371
|
21872 |
+ all targets not using narrow volatile bitfields. If the
|
mgl@1371
|
21873 |
+ bitfield is volatile then we need to perform an access
|
mgl@1371
|
21874 |
+ consistent with the container type. */
|
mgl@1371
|
21875 |
+ (MEM_P (target)
|
mgl@1371
|
21876 |
+ && MEM_VOLATILE_P (target)
|
mgl@1371
|
21877 |
+ && ((GET_MODE (target) != BLKmode
|
mgl@1371
|
21878 |
+ && GET_MODE_BITSIZE (GET_MODE (target)) > bitsize )
|
mgl@1371
|
21879 |
+ /* If BLKmode, check if this is a record. Do not know
|
mgl@1371
|
21880 |
+ if this is really necesarry though...*/
|
mgl@1371
|
21881 |
+ || (GET_MODE (target) == BLKmode
|
mgl@1371
|
21882 |
+ && TREE_CODE (type) == RECORD_TYPE))
|
mgl@1371
|
21883 |
+ && !targetm.narrow_volatile_bitfield ())
|
mgl@1371
|
21884 |
+ || mode == VOIDmode
|
mgl@1371
|
21885 |
|| (mode != BLKmode && ! direct_store[(int) mode]
|
mgl@1371
|
21886 |
&& GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
|
mgl@1371
|
21887 |
&& GET_MODE_CLASS (mode) != MODE_COMPLEX_FLOAT)
|
mgl@1371
|
21888 |
@@ -7560,7 +7575,21 @@ expand_expr_real_1 (tree exp, rtx target
|
mgl@1371
|
21889 |
by doing the extract into an object as wide as the field
|
mgl@1371
|
21890 |
(which we know to be the width of a basic mode), then
|
mgl@1371
|
21891 |
storing into memory, and changing the mode to BLKmode. */
|
mgl@1371
|
21892 |
- if (mode1 == VOIDmode
|
mgl@1371
|
21893 |
+ if (
|
mgl@1371
|
21894 |
+ /* NB! Added for AVR32, and I think this should be true for
|
mgl@1371
|
21895 |
+ all targets not using narrow volatile bitfields. If the
|
mgl@1371
|
21896 |
+ bitfield is volatile then we need to perform an access
|
mgl@1371
|
21897 |
+ consistent with the container type. */
|
mgl@1371
|
21898 |
+ (MEM_P (op0)
|
mgl@1371
|
21899 |
+ && MEM_VOLATILE_P (op0)
|
mgl@1371
|
21900 |
+ && ((GET_MODE (op0) != BLKmode
|
mgl@1371
|
21901 |
+ && GET_MODE_BITSIZE (GET_MODE (op0)) > bitsize )
|
mgl@1371
|
21902 |
+ /* If BLKmode, check if this is a record. Do not know
|
mgl@1371
|
21903 |
+ if this is really necesarry though...*/
|
mgl@1371
|
21904 |
+ || (GET_MODE (op0) == BLKmode
|
mgl@1371
|
21905 |
+ && TREE_CODE (type) == RECORD_TYPE))
|
mgl@1371
|
21906 |
+ && !targetm.narrow_volatile_bitfield ())
|
mgl@1371
|
21907 |
+ || mode1 == VOIDmode
|
mgl@1371
|
21908 |
|| REG_P (op0) || GET_CODE (op0) == SUBREG
|
mgl@1371
|
21909 |
|| (mode1 != BLKmode && ! direct_load[(int) mode1]
|
mgl@1371
|
21910 |
&& GET_MODE_CLASS (mode) != MODE_COMPLEX_INT
|
mgl@1371
|
21911 |
--- a/gcc/flow.c
|
mgl@1371
|
21912 |
+++ b/gcc/flow.c
|
mgl@1371
|
21913 |
@@ -3327,12 +3327,12 @@ not_reg_cond (rtx x)
|
mgl@1371
|
21914 |
if (GET_CODE (x) == NOT)
|
mgl@1371
|
21915 |
return XEXP (x, 0);
|
mgl@1371
|
21916 |
if (COMPARISON_P (x)
|
mgl@1371
|
21917 |
- && REG_P (XEXP (x, 0)))
|
mgl@1371
|
21918 |
+ /* && REG_P (XEXP (x, 0))*/)
|
mgl@1371
|
21919 |
{
|
mgl@1371
|
21920 |
- gcc_assert (XEXP (x, 1) == const0_rtx);
|
mgl@1371
|
21921 |
+ /*gcc_assert (XEXP (x, 1) == const0_rtx);*/
|
mgl@1371
|
21922 |
|
mgl@1371
|
21923 |
return gen_rtx_fmt_ee (reversed_comparison_code (x, NULL),
|
mgl@1371
|
21924 |
- VOIDmode, XEXP (x, 0), const0_rtx);
|
mgl@1371
|
21925 |
+ VOIDmode, XEXP (x, 0), XEXP (x, 0) /*const0_rtx*/);
|
mgl@1371
|
21926 |
}
|
mgl@1371
|
21927 |
return gen_rtx_NOT (0, x);
|
mgl@1371
|
21928 |
}
|
mgl@1371
|
21929 |
--- a/gcc/function.c
|
mgl@1371
|
21930 |
+++ b/gcc/function.c
|
mgl@1371
|
21931 |
@@ -2676,8 +2676,12 @@ assign_parm_setup_reg (struct assign_par
|
mgl@1371
|
21932 |
SET_DECL_RTL (parm, parmreg);
|
mgl@1371
|
21933 |
|
mgl@1371
|
21934 |
/* Copy the value into the register. */
|
mgl@1371
|
21935 |
- if (data->nominal_mode != data->passed_mode
|
mgl@1371
|
21936 |
- || promoted_nominal_mode != data->promoted_mode)
|
mgl@1371
|
21937 |
+ if ( (data->nominal_mode != data->passed_mode
|
mgl@1371
|
21938 |
+ /* Added for AVR32: If passed_mode is equal
|
mgl@1371
|
21939 |
+ to promoted nominal mode why should be convert?
|
mgl@1371
|
21940 |
+ The conversion should make no difference. */
|
mgl@1371
|
21941 |
+ && data->passed_mode != promoted_nominal_mode)
|
mgl@1371
|
21942 |
+ || promoted_nominal_mode != data->promoted_mode)
|
mgl@1371
|
21943 |
{
|
mgl@1371
|
21944 |
int save_tree_used;
|
mgl@1371
|
21945 |
|
mgl@1371
|
21946 |
--- a/gcc/genemit.c
|
mgl@1371
|
21947 |
+++ b/gcc/genemit.c
|
mgl@1371
|
21948 |
@@ -121,6 +121,24 @@ max_operand_vec (rtx insn, int arg)
|
mgl@1371
|
21949 |
}
|
mgl@1371
|
21950 |
|
mgl@1371
|
21951 |
static void
|
mgl@1371
|
21952 |
+gen_vararg_prologue(int operands)
|
mgl@1371
|
21953 |
+{
|
mgl@1371
|
21954 |
+ int i;
|
mgl@1371
|
21955 |
+
|
mgl@1371
|
21956 |
+ if (operands > 1)
|
mgl@1371
|
21957 |
+ {
|
mgl@1371
|
21958 |
+ for (i = 1; i < operands; i++)
|
mgl@1371
|
21959 |
+ printf(" rtx operand%d ATTRIBUTE_UNUSED;\n", i);
|
mgl@1371
|
21960 |
+
|
mgl@1371
|
21961 |
+ printf(" va_list args;\n\n");
|
mgl@1371
|
21962 |
+ printf(" va_start(args, operand0);\n");
|
mgl@1371
|
21963 |
+ for (i = 1; i < operands; i++)
|
mgl@1371
|
21964 |
+ printf(" operand%d = va_arg(args, rtx);\n", i);
|
mgl@1371
|
21965 |
+ printf(" va_end(args);\n\n");
|
mgl@1371
|
21966 |
+ }
|
mgl@1371
|
21967 |
+}
|
mgl@1371
|
21968 |
+
|
mgl@1371
|
21969 |
+static void
|
mgl@1371
|
21970 |
print_code (RTX_CODE code)
|
mgl@1371
|
21971 |
{
|
mgl@1371
|
21972 |
const char *p1;
|
mgl@1371
|
21973 |
@@ -405,18 +423,16 @@ gen_insn (rtx insn, int lineno)
|
mgl@1371
|
21974 |
fatal ("match_dup operand number has no match_operand");
|
mgl@1371
|
21975 |
|
mgl@1371
|
21976 |
/* Output the function name and argument declarations. */
|
mgl@1371
|
21977 |
- printf ("rtx\ngen_%s (", XSTR (insn, 0));
|
mgl@1371
|
21978 |
+ printf ("rtx\ngen_%s ", XSTR (insn, 0));
|
mgl@1371
|
21979 |
+
|
mgl@1371
|
21980 |
if (operands)
|
mgl@1371
|
21981 |
- for (i = 0; i < operands; i++)
|
mgl@1371
|
21982 |
- if (i)
|
mgl@1371
|
21983 |
- printf (",\n\trtx operand%d ATTRIBUTE_UNUSED", i);
|
mgl@1371
|
21984 |
- else
|
mgl@1371
|
21985 |
- printf ("rtx operand%d ATTRIBUTE_UNUSED", i);
|
mgl@1371
|
21986 |
+ printf("(rtx operand0 ATTRIBUTE_UNUSED, ...)\n");
|
mgl@1371
|
21987 |
else
|
mgl@1371
|
21988 |
- printf ("void");
|
mgl@1371
|
21989 |
- printf (")\n");
|
mgl@1371
|
21990 |
+ printf("(void)\n");
|
mgl@1371
|
21991 |
printf ("{\n");
|
mgl@1371
|
21992 |
|
mgl@1371
|
21993 |
+ gen_vararg_prologue(operands);
|
mgl@1371
|
21994 |
+
|
mgl@1371
|
21995 |
/* Output code to construct and return the rtl for the instruction body. */
|
mgl@1371
|
21996 |
|
mgl@1371
|
21997 |
if (XVECLEN (insn, 1) == 1)
|
mgl@1371
|
21998 |
@@ -456,16 +472,12 @@ gen_expand (rtx expand)
|
mgl@1371
|
21999 |
operands = max_operand_vec (expand, 1);
|
mgl@1371
|
22000 |
|
mgl@1371
|
22001 |
/* Output the function name and argument declarations. */
|
mgl@1371
|
22002 |
- printf ("rtx\ngen_%s (", XSTR (expand, 0));
|
mgl@1371
|
22003 |
+ printf ("rtx\ngen_%s ", XSTR (expand, 0));
|
mgl@1371
|
22004 |
if (operands)
|
mgl@1371
|
22005 |
- for (i = 0; i < operands; i++)
|
mgl@1371
|
22006 |
- if (i)
|
mgl@1371
|
22007 |
- printf (",\n\trtx operand%d", i);
|
mgl@1371
|
22008 |
- else
|
mgl@1371
|
22009 |
- printf ("rtx operand%d", i);
|
mgl@1371
|
22010 |
+ printf("(rtx operand0 ATTRIBUTE_UNUSED, ...)\n");
|
mgl@1371
|
22011 |
else
|
mgl@1371
|
22012 |
- printf ("void");
|
mgl@1371
|
22013 |
- printf (")\n");
|
mgl@1371
|
22014 |
+ printf("(void)\n");
|
mgl@1371
|
22015 |
+
|
mgl@1371
|
22016 |
printf ("{\n");
|
mgl@1371
|
22017 |
|
mgl@1371
|
22018 |
/* If we don't have any C code to write, only one insn is being written,
|
mgl@1371
|
22019 |
@@ -475,6 +487,8 @@ gen_expand (rtx expand)
|
mgl@1371
|
22020 |
&& operands > max_dup_opno
|
mgl@1371
|
22021 |
&& XVECLEN (expand, 1) == 1)
|
mgl@1371
|
22022 |
{
|
mgl@1371
|
22023 |
+ gen_vararg_prologue(operands);
|
mgl@1371
|
22024 |
+
|
mgl@1371
|
22025 |
printf (" return ");
|
mgl@1371
|
22026 |
gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL);
|
mgl@1371
|
22027 |
printf (";\n}\n\n");
|
mgl@1371
|
22028 |
@@ -488,6 +502,7 @@ gen_expand (rtx expand)
|
mgl@1371
|
22029 |
for (; i <= max_scratch_opno; i++)
|
mgl@1371
|
22030 |
printf (" rtx operand%d ATTRIBUTE_UNUSED;\n", i);
|
mgl@1371
|
22031 |
printf (" rtx _val = 0;\n");
|
mgl@1371
|
22032 |
+ gen_vararg_prologue(operands);
|
mgl@1371
|
22033 |
printf (" start_sequence ();\n");
|
mgl@1371
|
22034 |
|
mgl@1371
|
22035 |
/* The fourth operand of DEFINE_EXPAND is some code to be executed
|
mgl@1371
|
22036 |
--- a/gcc/genflags.c
|
mgl@1371
|
22037 |
+++ b/gcc/genflags.c
|
mgl@1371
|
22038 |
@@ -127,7 +127,6 @@ static void
|
mgl@1371
|
22039 |
gen_proto (rtx insn)
|
mgl@1371
|
22040 |
{
|
mgl@1371
|
22041 |
int num = num_operands (insn);
|
mgl@1371
|
22042 |
- int i;
|
mgl@1371
|
22043 |
const char *name = XSTR (insn, 0);
|
mgl@1371
|
22044 |
int truth = maybe_eval_c_test (XSTR (insn, 2));
|
mgl@1371
|
22045 |
|
mgl@1371
|
22046 |
@@ -158,12 +157,7 @@ gen_proto (rtx insn)
|
mgl@1371
|
22047 |
if (num == 0)
|
mgl@1371
|
22048 |
fputs ("void", stdout);
|
mgl@1371
|
22049 |
else
|
mgl@1371
|
22050 |
- {
|
mgl@1371
|
22051 |
- for (i = 1; i < num; i++)
|
mgl@1371
|
22052 |
- fputs ("rtx, ", stdout);
|
mgl@1371
|
22053 |
-
|
mgl@1371
|
22054 |
- fputs ("rtx", stdout);
|
mgl@1371
|
22055 |
- }
|
mgl@1371
|
22056 |
+ fputs("rtx, ...", stdout);
|
mgl@1371
|
22057 |
|
mgl@1371
|
22058 |
puts (");");
|
mgl@1371
|
22059 |
|
mgl@1371
|
22060 |
@@ -173,12 +167,7 @@ gen_proto (rtx insn)
|
mgl@1371
|
22061 |
{
|
mgl@1371
|
22062 |
printf ("static inline rtx\ngen_%s", name);
|
mgl@1371
|
22063 |
if (num > 0)
|
mgl@1371
|
22064 |
- {
|
mgl@1371
|
22065 |
- putchar ('(');
|
mgl@1371
|
22066 |
- for (i = 0; i < num-1; i++)
|
mgl@1371
|
22067 |
- printf ("rtx ARG_UNUSED (%c), ", 'a' + i);
|
mgl@1371
|
22068 |
- printf ("rtx ARG_UNUSED (%c))\n", 'a' + i);
|
mgl@1371
|
22069 |
- }
|
mgl@1371
|
22070 |
+ puts("(rtx ARG_UNUSED(a), ...)");
|
mgl@1371
|
22071 |
else
|
mgl@1371
|
22072 |
puts ("(void)");
|
mgl@1371
|
22073 |
puts ("{\n return 0;\n}");
|
mgl@1371
|
22074 |
--- a/gcc/genoutput.c
|
mgl@1371
|
22075 |
+++ b/gcc/genoutput.c
|
mgl@1371
|
22076 |
@@ -386,7 +386,7 @@ output_insn_data (void)
|
mgl@1371
|
22077 |
}
|
mgl@1371
|
22078 |
|
mgl@1371
|
22079 |
if (d->name && d->name[0] != '*')
|
mgl@1371
|
22080 |
- printf (" (insn_gen_fn) gen_%s,\n", d->name);
|
mgl@1371
|
22081 |
+ printf (" gen_%s,\n", d->name);
|
mgl@1371
|
22082 |
else
|
mgl@1371
|
22083 |
printf (" 0,\n");
|
mgl@1371
|
22084 |
|
mgl@1371
|
22085 |
--- a/gcc/ifcvt.c
|
mgl@1371
|
22086 |
+++ b/gcc/ifcvt.c
|
mgl@1371
|
22087 |
@@ -77,7 +77,7 @@ static int num_possible_if_blocks;
|
mgl@1371
|
22088 |
static int num_updated_if_blocks;
|
mgl@1371
|
22089 |
|
mgl@1371
|
22090 |
/* # of changes made which require life information to be updated. */
|
mgl@1371
|
22091 |
-static int num_true_changes;
|
mgl@1371
|
22092 |
+int num_true_changes;
|
mgl@1371
|
22093 |
|
mgl@1371
|
22094 |
/* Whether conditional execution changes were made. */
|
mgl@1371
|
22095 |
static int cond_exec_changed_p;
|
mgl@1371
|
22096 |
@@ -287,12 +287,15 @@ cond_exec_process_insns (ce_if_block_t *
|
mgl@1371
|
22097 |
if (must_be_last)
|
mgl@1371
|
22098 |
return FALSE;
|
mgl@1371
|
22099 |
|
mgl@1371
|
22100 |
- if (modified_in_p (test, insn))
|
mgl@1371
|
22101 |
- {
|
mgl@1371
|
22102 |
- if (!mod_ok)
|
mgl@1371
|
22103 |
- return FALSE;
|
mgl@1371
|
22104 |
- must_be_last = TRUE;
|
mgl@1371
|
22105 |
- }
|
mgl@1371
|
22106 |
+#ifdef IFCVT_ALLOW_MODIFY_TEST_IN_INSN
|
mgl@1371
|
22107 |
+ if ( !IFCVT_ALLOW_MODIFY_TEST_IN_INSN )
|
mgl@1371
|
22108 |
+#endif
|
mgl@1371
|
22109 |
+ if (modified_in_p (test, insn))
|
mgl@1371
|
22110 |
+ {
|
mgl@1371
|
22111 |
+ if (!mod_ok)
|
mgl@1371
|
22112 |
+ return FALSE;
|
mgl@1371
|
22113 |
+ must_be_last = TRUE;
|
mgl@1371
|
22114 |
+ }
|
mgl@1371
|
22115 |
|
mgl@1371
|
22116 |
/* Now build the conditional form of the instruction. */
|
mgl@1371
|
22117 |
pattern = PATTERN (insn);
|
mgl@1371
|
22118 |
@@ -566,16 +569,19 @@ cond_exec_process_if_block (ce_if_block_
|
mgl@1371
|
22119 |
/* Do any machine dependent final modifications. */
|
mgl@1371
|
22120 |
IFCVT_MODIFY_FINAL (ce_info);
|
mgl@1371
|
22121 |
#endif
|
mgl@1371
|
22122 |
-
|
mgl@1371
|
22123 |
- /* Conversion succeeded. */
|
mgl@1371
|
22124 |
- if (dump_file)
|
mgl@1371
|
22125 |
- fprintf (dump_file, "%d insn%s converted to conditional execution.\n",
|
mgl@1371
|
22126 |
- n_insns, (n_insns == 1) ? " was" : "s were");
|
mgl@1371
|
22127 |
-
|
mgl@1371
|
22128 |
+
|
mgl@1371
|
22129 |
/* Merge the blocks! */
|
mgl@1371
|
22130 |
- merge_if_block (ce_info);
|
mgl@1371
|
22131 |
- cond_exec_changed_p = TRUE;
|
mgl@1371
|
22132 |
- return TRUE;
|
mgl@1371
|
22133 |
+ if ( reload_completed ){
|
mgl@1371
|
22134 |
+ /* Conversion succeeded. */
|
mgl@1371
|
22135 |
+ if (dump_file)
|
mgl@1371
|
22136 |
+ fprintf (dump_file, "%d insn%s converted to conditional execution.\n",
|
mgl@1371
|
22137 |
+ n_insns, (n_insns == 1) ? " was" : "s were");
|
mgl@1371
|
22138 |
+
|
mgl@1371
|
22139 |
+ merge_if_block (ce_info);
|
mgl@1371
|
22140 |
+ cond_exec_changed_p = TRUE;
|
mgl@1371
|
22141 |
+ return TRUE;
|
mgl@1371
|
22142 |
+ }
|
mgl@1371
|
22143 |
+ return FALSE;
|
mgl@1371
|
22144 |
|
mgl@1371
|
22145 |
fail:
|
mgl@1371
|
22146 |
#ifdef IFCVT_MODIFY_CANCEL
|
mgl@1371
|
22147 |
@@ -1050,7 +1056,11 @@ noce_try_addcc (struct noce_if_info *if_
|
mgl@1371
|
22148 |
!= UNKNOWN))
|
mgl@1371
|
22149 |
{
|
mgl@1371
|
22150 |
rtx cond = if_info->cond;
|
mgl@1371
|
22151 |
- enum rtx_code code = reversed_comparison_code (cond, if_info->jump);
|
mgl@1371
|
22152 |
+ /* This generates wrong code for AVR32. The cond code need not be reversed
|
mgl@1371
|
22153 |
+ since the addmodecc patterns add if the condition is NOT met. */
|
mgl@1371
|
22154 |
+ /* enum rtx_code code = reversed_comparison_code (cond, if_info->jump);*/
|
mgl@1371
|
22155 |
+ enum rtx_code code = GET_CODE(cond);
|
mgl@1371
|
22156 |
+
|
mgl@1371
|
22157 |
|
mgl@1371
|
22158 |
/* First try to use addcc pattern. */
|
mgl@1371
|
22159 |
if (general_operand (XEXP (cond, 0), VOIDmode)
|
mgl@1371
|
22160 |
@@ -2651,7 +2661,12 @@ process_if_block (struct ce_if_block * c
|
mgl@1371
|
22161 |
&& cond_move_process_if_block (ce_info))
|
mgl@1371
|
22162 |
return TRUE;
|
mgl@1371
|
22163 |
|
mgl@1371
|
22164 |
- if (HAVE_conditional_execution && reload_completed)
|
mgl@1371
|
22165 |
+ if (HAVE_conditional_execution &&
|
mgl@1371
|
22166 |
+#ifdef IFCVT_COND_EXEC_BEFORE_RELOAD
|
mgl@1371
|
22167 |
+ (reload_completed || IFCVT_COND_EXEC_BEFORE_RELOAD))
|
mgl@1371
|
22168 |
+#else
|
mgl@1371
|
22169 |
+ reload_completed)
|
mgl@1371
|
22170 |
+#endif
|
mgl@1371
|
22171 |
{
|
mgl@1371
|
22172 |
/* If we have && and || tests, try to first handle combining the && and
|
mgl@1371
|
22173 |
|| tests into the conditional code, and if that fails, go back and
|
mgl@1371
|
22174 |
@@ -4036,6 +4051,15 @@ rest_of_handle_if_after_reload (void)
|
mgl@1371
|
22175 |
cleanup_cfg (CLEANUP_EXPENSIVE
|
mgl@1371
|
22176 |
| CLEANUP_UPDATE_LIFE
|
mgl@1371
|
22177 |
| (flag_crossjumping ? CLEANUP_CROSSJUMP : 0));
|
mgl@1371
|
22178 |
+
|
mgl@1371
|
22179 |
+ /* Hack for the AVR32 experimental ifcvt processing before reload.
|
mgl@1371
|
22180 |
+ The AVR32 specific ifcvt code needs to know when ifcvt after reload
|
mgl@1371
|
22181 |
+ has begun. */
|
mgl@1371
|
22182 |
+#ifdef IFCVT_COND_EXEC_BEFORE_RELOAD
|
mgl@1371
|
22183 |
+ if ( IFCVT_COND_EXEC_BEFORE_RELOAD )
|
mgl@1371
|
22184 |
+ cfun->machine->ifcvt_after_reload = 1;
|
mgl@1371
|
22185 |
+#endif
|
mgl@1371
|
22186 |
+
|
mgl@1371
|
22187 |
if (flag_if_conversion2)
|
mgl@1371
|
22188 |
if_convert (1);
|
mgl@1371
|
22189 |
return 0;
|
mgl@1371
|
22190 |
--- a/gcc/longlong.h
|
mgl@1371
|
22191 |
+++ b/gcc/longlong.h
|
mgl@1371
|
22192 |
@@ -226,6 +226,41 @@ UDItype __umulsidi3 (USItype, USItype);
|
mgl@1371
|
22193 |
#define UDIV_TIME 100
|
mgl@1371
|
22194 |
#endif /* __arm__ */
|
mgl@1371
|
22195 |
|
mgl@1371
|
22196 |
+#if defined (__avr32__) && W_TYPE_SIZE == 32
|
mgl@1371
|
22197 |
+#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
|
mgl@1371
|
22198 |
+ __asm__ ("add\t%1, %4, %5\n\tadc\t%0, %2, %3" \
|
mgl@1371
|
22199 |
+ : "=r" ((USItype) (sh)), \
|
mgl@1371
|
22200 |
+ "=&r" ((USItype) (sl)) \
|
mgl@1371
|
22201 |
+ : "r" ((USItype) (ah)), \
|
mgl@1371
|
22202 |
+ "r" ((USItype) (bh)), \
|
mgl@1371
|
22203 |
+ "r" ((USItype) (al)), \
|
mgl@1371
|
22204 |
+ "r" ((USItype) (bl)) __CLOBBER_CC)
|
mgl@1371
|
22205 |
+#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
|
mgl@1371
|
22206 |
+ __asm__ ("sub\t%1, %4, %5\n\tsbc\t%0, %2, %3" \
|
mgl@1371
|
22207 |
+ : "=r" ((USItype) (sh)), \
|
mgl@1371
|
22208 |
+ "=&r" ((USItype) (sl)) \
|
mgl@1371
|
22209 |
+ : "r" ((USItype) (ah)), \
|
mgl@1371
|
22210 |
+ "r" ((USItype) (bh)), \
|
mgl@1371
|
22211 |
+ "r" ((USItype) (al)), \
|
mgl@1371
|
22212 |
+ "r" ((USItype) (bl)) __CLOBBER_CC)
|
mgl@1371
|
22213 |
+
|
mgl@1371
|
22214 |
+#if !defined (__AVR32_UC__) || __AVR32_UC__ != 3
|
mgl@1371
|
22215 |
+#define __umulsidi3(a,b) ((UDItype)(a) * (UDItype)(b))
|
mgl@1371
|
22216 |
+
|
mgl@1371
|
22217 |
+#define umul_ppmm(w1, w0, u, v) \
|
mgl@1371
|
22218 |
+{ \
|
mgl@1371
|
22219 |
+ DWunion __w; \
|
mgl@1371
|
22220 |
+ __w.ll = __umulsidi3 (u, v); \
|
mgl@1371
|
22221 |
+ w1 = __w.s.high; \
|
mgl@1371
|
22222 |
+ w0 = __w.s.low; \
|
mgl@1371
|
22223 |
+}
|
mgl@1371
|
22224 |
+#endif
|
mgl@1371
|
22225 |
+
|
mgl@1371
|
22226 |
+#define count_leading_zeros(COUNT,X) ((COUNT) = __builtin_clz (X))
|
mgl@1371
|
22227 |
+#define count_trailing_zeros(COUNT,X) ((COUNT) = __builtin_ctz (X))
|
mgl@1371
|
22228 |
+#define COUNT_LEADING_ZEROS_0 32
|
mgl@1371
|
22229 |
+#endif
|
mgl@1371
|
22230 |
+
|
mgl@1371
|
22231 |
#if defined (__hppa) && W_TYPE_SIZE == 32
|
mgl@1371
|
22232 |
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
|
mgl@1371
|
22233 |
__asm__ ("add %4,%5,%1\n\taddc %2,%3,%0" \
|
mgl@1371
|
22234 |
--- a/gcc/optabs.h
|
mgl@1371
|
22235 |
+++ b/gcc/optabs.h
|
mgl@1371
|
22236 |
@@ -431,7 +431,7 @@ extern enum insn_code reload_out_optab[N
|
mgl@1371
|
22237 |
extern GTY(()) optab code_to_optab[NUM_RTX_CODE + 1];
|
mgl@1371
|
22238 |
|
mgl@1371
|
22239 |
|
mgl@1371
|
22240 |
-typedef rtx (*rtxfun) (rtx);
|
mgl@1371
|
22241 |
+typedef rtx (*rtxfun) (rtx, ...);
|
mgl@1371
|
22242 |
|
mgl@1371
|
22243 |
/* Indexed by the rtx-code for a conditional (e.g. EQ, LT,...)
|
mgl@1371
|
22244 |
gives the gen_function to make a branch to test that condition. */
|
mgl@1371
|
22245 |
--- a/gcc/regrename.c
|
mgl@1371
|
22246 |
+++ b/gcc/regrename.c
|
mgl@1371
|
22247 |
@@ -1592,6 +1592,9 @@ copyprop_hardreg_forward_1 (basic_block
|
mgl@1371
|
22248 |
bool changed = false;
|
mgl@1371
|
22249 |
rtx insn;
|
mgl@1371
|
22250 |
|
mgl@1371
|
22251 |
+ rtx prev_pred_test;
|
mgl@1371
|
22252 |
+ int prev_pred_insn_skipped = 0;
|
mgl@1371
|
22253 |
+
|
mgl@1371
|
22254 |
for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn))
|
mgl@1371
|
22255 |
{
|
mgl@1371
|
22256 |
int n_ops, i, alt, predicated;
|
mgl@1371
|
22257 |
@@ -1630,7 +1633,60 @@ copyprop_hardreg_forward_1 (basic_block
|
mgl@1371
|
22258 |
|| (predicated && recog_data.operand_type[i] == OP_OUT))
|
mgl@1371
|
22259 |
recog_data.operand_type[i] = OP_INOUT;
|
mgl@1371
|
22260 |
}
|
mgl@1371
|
22261 |
+
|
mgl@1371
|
22262 |
|
mgl@1371
|
22263 |
+ /* Added for targets (AVR32) which supports test operands to be modified
|
mgl@1371
|
22264 |
+ in cond_exec instruction. For these targets we cannot make a change to
|
mgl@1371
|
22265 |
+ the test operands if one of the test operands is an output operand This beacuse
|
mgl@1371
|
22266 |
+ changing the test operands might cause the need for inserting a new test
|
mgl@1371
|
22267 |
+ insns in the middle of a sequence of cond_exec insns and if the test operands
|
mgl@1371
|
22268 |
+ are modified these tests will fail.
|
mgl@1371
|
22269 |
+ */
|
mgl@1371
|
22270 |
+
|
mgl@1371
|
22271 |
+ if ( IFCVT_ALLOW_MODIFY_TEST_IN_INSN
|
mgl@1371
|
22272 |
+ && predicated )
|
mgl@1371
|
22273 |
+ {
|
mgl@1371
|
22274 |
+ int insn_skipped = 0;
|
mgl@1371
|
22275 |
+ rtx test = COND_EXEC_TEST (PATTERN (insn));
|
mgl@1371
|
22276 |
+
|
mgl@1371
|
22277 |
+ /* Check if the previous insn was a skipped predicated insn with the same
|
mgl@1371
|
22278 |
+ test as this predicated insns. If so we cannot do any modification to
|
mgl@1371
|
22279 |
+ this insn either since we cannot emit the test insn because the operands
|
mgl@1371
|
22280 |
+ are clobbered. */
|
mgl@1371
|
22281 |
+ if ( prev_pred_insn_skipped
|
mgl@1371
|
22282 |
+ && (rtx_equal_p (test, prev_pred_test)
|
mgl@1371
|
22283 |
+ || rtx_equal_p (test, reversed_condition (prev_pred_test))) )
|
mgl@1371
|
22284 |
+ {
|
mgl@1371
|
22285 |
+ insn_skipped = 1;
|
mgl@1371
|
22286 |
+ }
|
mgl@1371
|
22287 |
+ else
|
mgl@1371
|
22288 |
+ {
|
mgl@1371
|
22289 |
+ /* Check if the output operand is used in the test expression. */
|
mgl@1371
|
22290 |
+ for (i = 0; i < n_ops; ++i)
|
mgl@1371
|
22291 |
+ if ( recog_data.operand_type[i] == OP_INOUT
|
mgl@1371
|
22292 |
+ && reg_mentioned_p (recog_data.operand[i], test) )
|
mgl@1371
|
22293 |
+ {
|
mgl@1371
|
22294 |
+ insn_skipped = 1;
|
mgl@1371
|
22295 |
+ break;
|
mgl@1371
|
22296 |
+ }
|
mgl@1371
|
22297 |
+
|
mgl@1371
|
22298 |
+ }
|
mgl@1371
|
22299 |
+
|
mgl@1371
|
22300 |
+ prev_pred_test = test;
|
mgl@1371
|
22301 |
+ prev_pred_insn_skipped = insn_skipped;
|
mgl@1371
|
22302 |
+ if ( insn_skipped )
|
mgl@1371
|
22303 |
+ {
|
mgl@1371
|
22304 |
+ if (insn == BB_END (bb))
|
mgl@1371
|
22305 |
+ break;
|
mgl@1371
|
22306 |
+ else
|
mgl@1371
|
22307 |
+ continue;
|
mgl@1371
|
22308 |
+ }
|
mgl@1371
|
22309 |
+ }
|
mgl@1371
|
22310 |
+ else
|
mgl@1371
|
22311 |
+ {
|
mgl@1371
|
22312 |
+ prev_pred_insn_skipped = 0;
|
mgl@1371
|
22313 |
+ }
|
mgl@1371
|
22314 |
+
|
mgl@1371
|
22315 |
/* For each earlyclobber operand, zap the value data. */
|
mgl@1371
|
22316 |
for (i = 0; i < n_ops; i++)
|
mgl@1371
|
22317 |
if (recog_op_alt[i][alt].earlyclobber)
|
mgl@1371
|
22318 |
--- a/gcc/reload.c
|
mgl@1371
|
22319 |
+++ b/gcc/reload.c
|
mgl@1371
|
22320 |
@@ -4574,7 +4574,7 @@ find_reloads_toplev (rtx x, int opnum, e
|
mgl@1371
|
22321 |
x = mem;
|
mgl@1371
|
22322 |
i = find_reloads_address (GET_MODE (x), &x, XEXP (x, 0), &XEXP (x, 0),
|
mgl@1371
|
22323 |
opnum, type, ind_levels, insn);
|
mgl@1371
|
22324 |
- if (x != mem)
|
mgl@1371
|
22325 |
+ if (!rtx_equal_p (x, mem))
|
mgl@1371
|
22326 |
push_reg_equiv_alt_mem (regno, x);
|
mgl@1371
|
22327 |
if (address_reloaded)
|
mgl@1371
|
22328 |
*address_reloaded = i;
|
mgl@1371
|
22329 |
--- a/gcc/sched-deps.c
|
mgl@1371
|
22330 |
+++ b/gcc/sched-deps.c
|
mgl@1371
|
22331 |
@@ -649,7 +649,14 @@ fixup_sched_groups (rtx insn)
|
mgl@1371
|
22332 |
|
mgl@1371
|
22333 |
prev_nonnote = prev_nonnote_insn (insn);
|
mgl@1371
|
22334 |
if (BLOCK_FOR_INSN (insn) == BLOCK_FOR_INSN (prev_nonnote)
|
mgl@1371
|
22335 |
- && ! sched_insns_conditions_mutex_p (insn, prev_nonnote))
|
mgl@1371
|
22336 |
+ /* Modification for AVR32 by RP: Why is this here, this will
|
mgl@1371
|
22337 |
+ cause instruction to be without any dependencies which might
|
mgl@1371
|
22338 |
+ cause it to be moved anywhere. For the AVR32 we try to keep
|
mgl@1371
|
22339 |
+ a group of conditionals together even if they are mutual exclusive.
|
mgl@1371
|
22340 |
+ */
|
mgl@1371
|
22341 |
+ && (! sched_insns_conditions_mutex_p (insn, prev_nonnote)
|
mgl@1371
|
22342 |
+ || GET_CODE (PATTERN (insn)) == COND_EXEC )
|
mgl@1371
|
22343 |
+ )
|
mgl@1371
|
22344 |
add_dependence (insn, prev_nonnote, REG_DEP_ANTI);
|
mgl@1371
|
22345 |
}
|
mgl@1371
|
22346 |
|
mgl@1371
|
22347 |
@@ -1123,8 +1130,29 @@ sched_analyze_insn (struct deps *deps, r
|
mgl@1371
|
22348 |
|
mgl@1371
|
22349 |
if (code == COND_EXEC)
|
mgl@1371
|
22350 |
{
|
mgl@1371
|
22351 |
+#ifdef IFCVT_ALLOW_MODIFY_TEST_IN_INSN
|
mgl@1371
|
22352 |
+ if (IFCVT_ALLOW_MODIFY_TEST_IN_INSN)
|
mgl@1371
|
22353 |
+ {
|
mgl@1371
|
22354 |
+ /* Check if we have a group og conditional instructions with the same test.
|
mgl@1371
|
22355 |
+ If so we must make sure that they are not scheduled apart in order to
|
mgl@1371
|
22356 |
+ avoid unnecesarry tests and if one of the registers in the test is modified
|
mgl@1371
|
22357 |
+ in the instruction this is needed to ensure correct code. */
|
mgl@1371
|
22358 |
+ if ( prev_nonnote_insn (insn)
|
mgl@1371
|
22359 |
+ && INSN_P (prev_nonnote_insn (insn))
|
mgl@1371
|
22360 |
+ && GET_CODE (PATTERN (prev_nonnote_insn (insn))) == COND_EXEC
|
mgl@1371
|
22361 |
+ && rtx_equal_p (XEXP(COND_EXEC_TEST (PATTERN (prev_nonnote_insn (insn))), 0), XEXP (COND_EXEC_TEST (x), 0))
|
mgl@1371
|
22362 |
+ && rtx_equal_p (XEXP(COND_EXEC_TEST (PATTERN (prev_nonnote_insn (insn))), 1), XEXP (COND_EXEC_TEST (x), 1))
|
mgl@1371
|
22363 |
+ && ( GET_CODE (COND_EXEC_TEST (PATTERN (prev_nonnote_insn (insn)))) == GET_CODE (COND_EXEC_TEST (x))
|
mgl@1371
|
22364 |
+ || GET_CODE (COND_EXEC_TEST (PATTERN (prev_nonnote_insn (insn)))) == reversed_comparison_code (COND_EXEC_TEST (x), insn)))
|
mgl@1371
|
22365 |
+ {
|
mgl@1371
|
22366 |
+ SCHED_GROUP_P (insn) = 1;
|
mgl@1371
|
22367 |
+ //CANT_MOVE (prev_nonnote_insn (insn)) = 1;
|
mgl@1371
|
22368 |
+ }
|
mgl@1371
|
22369 |
+ }
|
mgl@1371
|
22370 |
+#endif
|
mgl@1371
|
22371 |
sched_analyze_2 (deps, COND_EXEC_TEST (x), insn);
|
mgl@1371
|
22372 |
|
mgl@1371
|
22373 |
+
|
mgl@1371
|
22374 |
/* ??? Should be recording conditions so we reduce the number of
|
mgl@1371
|
22375 |
false dependencies. */
|
mgl@1371
|
22376 |
x = COND_EXEC_CODE (x);
|
mgl@1371
|
22377 |
--- a/gcc/testsuite/gcc.dg/sibcall-3.c
|
mgl@1371
|
22378 |
+++ b/gcc/testsuite/gcc.dg/sibcall-3.c
|
mgl@1371
|
22379 |
@@ -5,7 +5,7 @@
|
mgl@1371
|
22380 |
Copyright (C) 2002 Free Software Foundation Inc.
|
mgl@1371
|
22381 |
Contributed by Hans-Peter Nilsson <hp@bitrange.com> */
|
mgl@1371
|
22382 |
|
mgl@1371
|
22383 |
-/* { dg-do run { xfail arc-*-* avr-*-* c4x-*-* cris-*-* h8300-*-* hppa*64*-*-* m32r-*-* m68hc1?-*-* m681?-*-* m680*-*-* m68k-*-* mcore-*-* mn10300-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */
|
mgl@1371
|
22384 |
+/* { dg-do run { xfail arc-*-* avr-*-* avr32-*-* c4x-*-* cris-*-* h8300-*-* hppa*64*-*-* m32r-*-* m68hc1?-*-* m681?-*-* m680*-*-* m68k-*-* mcore-*-* mn10300-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */
|
mgl@1371
|
22385 |
/* { dg-options "-O2 -foptimize-sibling-calls" } */
|
mgl@1371
|
22386 |
|
mgl@1371
|
22387 |
/* The option -foptimize-sibling-calls is the default, but serves as
|
mgl@1371
|
22388 |
--- a/gcc/testsuite/gcc.dg/sibcall-4.c
|
mgl@1371
|
22389 |
+++ b/gcc/testsuite/gcc.dg/sibcall-4.c
|
mgl@1371
|
22390 |
@@ -5,7 +5,7 @@
|
mgl@1371
|
22391 |
Copyright (C) 2002 Free Software Foundation Inc.
|
mgl@1371
|
22392 |
Contributed by Hans-Peter Nilsson <hp@bitrange.com> */
|
mgl@1371
|
22393 |
|
mgl@1371
|
22394 |
-/* { dg-do run { xfail arc-*-* avr-*-* c4x-*-* cris-*-* h8300-*-* hppa*64*-*-* m32r-*-* m68hc1?-*-* m681?-*-* m680*-*-* m68k-*-* mcore-*-* mn10300-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */
|
mgl@1371
|
22395 |
+/* { dg-do run { xfail arc-*-* avr-*-* avr32-*-* c4x-*-* cris-*-* h8300-*-* hppa*64*-*-* m32r-*-* m68hc1?-*-* m681?-*-* m680*-*-* m68k-*-* mcore-*-* mn10300-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa-*-* } } */
|
mgl@1371
|
22396 |
/* { dg-options "-O2 -foptimize-sibling-calls" } */
|
mgl@1371
|
22397 |
|
mgl@1371
|
22398 |
/* The option -foptimize-sibling-calls is the default, but serves as
|
mgl@1371
|
22399 |
--- a/gcc/testsuite/gcc.dg/trampoline-1.c
|
mgl@1371
|
22400 |
+++ b/gcc/testsuite/gcc.dg/trampoline-1.c
|
mgl@1371
|
22401 |
@@ -46,6 +46,8 @@ void foo (void)
|
mgl@1371
|
22402 |
|
mgl@1371
|
22403 |
int main (void)
|
mgl@1371
|
22404 |
{
|
mgl@1371
|
22405 |
+#ifndef NO_TRAMPOLINES
|
mgl@1371
|
22406 |
foo ();
|
mgl@1371
|
22407 |
+#endif
|
mgl@1371
|
22408 |
return 0;
|
mgl@1371
|
22409 |
}
|
mgl@1371
|
22410 |
--- a/gcc/testsuite/g++.old-deja/g++.pt/static11.C
|
mgl@1371
|
22411 |
+++ b/gcc/testsuite/g++.old-deja/g++.pt/static11.C
|
mgl@1371
|
22412 |
@@ -2,7 +2,7 @@
|
mgl@1371
|
22413 |
// in their dejagnu baseboard description) require that the status is
|
mgl@1371
|
22414 |
// final when exit is entered (or main returns), and not "overruled" by a
|
mgl@1371
|
22415 |
// destructor calling _exit. It's not really worth it to handle that.
|
mgl@1371
|
22416 |
-// { dg-do run { xfail mmix-knuth-mmixware xtensa-*-elf* arm*-*-elf arm*-*-eabi m68k-*-elf } }
|
mgl@1371
|
22417 |
+// { dg-do run { xfail mmix-knuth-mmixware xtensa-*-elf* avr32-*-elf arm*-*-elf arm*-*-eabi m68k-*-elf } }
|
mgl@1371
|
22418 |
|
mgl@1371
|
22419 |
// Bug: g++ was failing to destroy C<int>::a because it was using two
|
mgl@1371
|
22420 |
// different sentry variables for construction and destruction.
|
mgl@1371
|
22421 |
--- a/gcc/version.c
|
mgl@1371
|
22422 |
+++ b/gcc/version.c
|
mgl@1371
|
22423 |
@@ -8,7 +8,7 @@
|
mgl@1371
|
22424 |
in parentheses. You may also wish to include a number indicating
|
mgl@1371
|
22425 |
the revision of your modified compiler. */
|
mgl@1371
|
22426 |
|
mgl@1371
|
22427 |
-#define VERSUFFIX ""
|
mgl@1371
|
22428 |
+#define VERSUFFIX "-atmel.1.1.3.avr32linux.1"
|
mgl@1371
|
22429 |
|
mgl@1371
|
22430 |
/* This is the location of the online document giving instructions for
|
mgl@1371
|
22431 |
reporting bugs. If you distribute a modified version of GCC,
|
mgl@1371
|
22432 |
@@ -17,9 +17,9 @@
|
mgl@1371
|
22433 |
forward us bugs reported to you, if you determine that they are
|
mgl@1371
|
22434 |
not bugs in your modifications.) */
|
mgl@1371
|
22435 |
|
mgl@1371
|
22436 |
-const char bug_report_url[] = "<URL:http://gcc.gnu.org/bugs.html>";
|
mgl@1371
|
22437 |
+const char bug_report_url[] = "<URL:http://www.atmel.com/avr32/>";
|
mgl@1371
|
22438 |
|
mgl@1371
|
22439 |
/* The complete version string, assembled from several pieces.
|
mgl@1371
|
22440 |
BASEVER, DATESTAMP, and DEVPHASE are defined by the Makefile. */
|
mgl@1371
|
22441 |
|
mgl@1371
|
22442 |
-const char version_string[] = BASEVER DATESTAMP DEVPHASE VERSUFFIX;
|
mgl@1371
|
22443 |
+const char version_string[] = BASEVER VERSUFFIX DATESTAMP DEVPHASE;
|
mgl@1371
|
22444 |
--- a/libstdc++-v3/acinclude.m4
|
mgl@1371
|
22445 |
+++ b/libstdc++-v3/acinclude.m4
|
mgl@1371
|
22446 |
@@ -125,15 +125,6 @@ AC_DEFUN([GLIBCXX_CONFIGURE], [
|
mgl@1371
|
22447 |
## other macros from doing the same. This should be automated.) -pme
|
mgl@1371
|
22448 |
need_libmath=no
|
mgl@1371
|
22449 |
|
mgl@1371
|
22450 |
- # Check for uClibc since Linux platforms use different configuration
|
mgl@1371
|
22451 |
- # directories depending on the C library in use.
|
mgl@1371
|
22452 |
- AC_EGREP_CPP([_using_uclibc], [
|
mgl@1371
|
22453 |
- #include <stdio.h>
|
mgl@1371
|
22454 |
- #if __UCLIBC__
|
mgl@1371
|
22455 |
- _using_uclibc
|
mgl@1371
|
22456 |
- #endif
|
mgl@1371
|
22457 |
- ], uclibc=yes, uclibc=no)
|
mgl@1371
|
22458 |
-
|
mgl@1371
|
22459 |
# Find platform-specific directories containing configuration info.
|
mgl@1371
|
22460 |
# Also possibly modify flags used elsewhere, as needed by the platform.
|
mgl@1371
|
22461 |
GLIBCXX_CHECK_HOST
|
mgl@1371
|
22462 |
@@ -1389,8 +1380,8 @@ AC_DEFUN([GLIBCXX_ENABLE_CLOCALE], [
|
mgl@1371
|
22463 |
#endif
|
mgl@1371
|
22464 |
int main()
|
mgl@1371
|
22465 |
{
|
mgl@1371
|
22466 |
- const char __one[] = "Äuglein Augmen";
|
mgl@1371
|
22467 |
- const char __two[] = "Äuglein";
|
mgl@1371
|
22468 |
+ const char __one[] = "Äuglein Augmen";
|
mgl@1371
|
22469 |
+ const char __two[] = "Äuglein";
|
mgl@1371
|
22470 |
int i;
|
mgl@1371
|
22471 |
int j;
|
mgl@1371
|
22472 |
__locale_t loc;
|
mgl@1371
|
22473 |
--- a/libstdc++-v3/config/os/gnu-linux/ctype_base.h
|
mgl@1371
|
22474 |
+++ b/libstdc++-v3/config/os/gnu-linux/ctype_base.h
|
mgl@1371
|
22475 |
@@ -31,6 +31,8 @@
|
mgl@1371
|
22476 |
//
|
mgl@1371
|
22477 |
// ISO C++ 14882: 22.1 Locales
|
mgl@1371
|
22478 |
//
|
mgl@1371
|
22479 |
+#include <features.h>
|
mgl@1371
|
22480 |
+#include <ctype.h>
|
mgl@1371
|
22481 |
|
mgl@1371
|
22482 |
/** @file ctype_base.h
|
mgl@1371
|
22483 |
* This is an internal header file, included by other library headers.
|
mgl@1371
|
22484 |
@@ -45,8 +47,12 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
|
mgl@1371
|
22485 |
struct ctype_base
|
mgl@1371
|
22486 |
{
|
mgl@1371
|
22487 |
// Non-standard typedefs.
|
mgl@1371
|
22488 |
- typedef const int* __to_type;
|
mgl@1371
|
22489 |
-
|
mgl@1371
|
22490 |
+#ifdef __UCLIBC__
|
mgl@1371
|
22491 |
+ typedef const __ctype_touplow_t* __to_type;
|
mgl@1371
|
22492 |
+#else
|
mgl@1371
|
22493 |
+ typedef const int* __to_type;
|
mgl@1371
|
22494 |
+#endif
|
mgl@1371
|
22495 |
+
|
mgl@1371
|
22496 |
// NB: Offsets into ctype<char>::_M_table force a particular size
|
mgl@1371
|
22497 |
// on the mask type. Because of this, we don't use an enum.
|
mgl@1371
|
22498 |
typedef unsigned short mask;
|
mgl@1371
|
22499 |
--- a/libstdc++-v3/include/Makefile.in
|
mgl@1371
|
22500 |
+++ b/libstdc++-v3/include/Makefile.in
|
mgl@1371
|
22501 |
@@ -36,6 +36,7 @@ POST_UNINSTALL = :
|
mgl@1371
|
22502 |
build_triplet = @build@
|
mgl@1371
|
22503 |
host_triplet = @host@
|
mgl@1371
|
22504 |
target_triplet = @target@
|
mgl@1371
|
22505 |
+LIBOBJDIR =
|
mgl@1371
|
22506 |
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
|
mgl@1371
|
22507 |
$(top_srcdir)/fragment.am
|
mgl@1371
|
22508 |
subdir = include
|
mgl@1371
|
22509 |
--- a/libstdc++-v3/libmath/Makefile.in
|
mgl@1371
|
22510 |
+++ b/libstdc++-v3/libmath/Makefile.in
|
mgl@1371
|
22511 |
@@ -37,6 +37,7 @@ POST_UNINSTALL = :
|
mgl@1371
|
22512 |
build_triplet = @build@
|
mgl@1371
|
22513 |
host_triplet = @host@
|
mgl@1371
|
22514 |
target_triplet = @target@
|
mgl@1371
|
22515 |
+LIBOBJDIR =
|
mgl@1371
|
22516 |
subdir = libmath
|
mgl@1371
|
22517 |
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
mgl@1371
|
22518 |
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
mgl@1371
|
22519 |
--- a/libstdc++-v3/libsupc++/Makefile.in
|
mgl@1371
|
22520 |
+++ b/libstdc++-v3/libsupc++/Makefile.in
|
mgl@1371
|
22521 |
@@ -38,6 +38,7 @@ POST_UNINSTALL = :
|
mgl@1371
|
22522 |
build_triplet = @build@
|
mgl@1371
|
22523 |
host_triplet = @host@
|
mgl@1371
|
22524 |
target_triplet = @target@
|
mgl@1371
|
22525 |
+LIBOBJDIR =
|
mgl@1371
|
22526 |
DIST_COMMON = $(glibcxxinstall_HEADERS) $(srcdir)/Makefile.am \
|
mgl@1371
|
22527 |
$(srcdir)/Makefile.in $(top_srcdir)/fragment.am
|
mgl@1371
|
22528 |
subdir = libsupc++
|
mgl@1371
|
22529 |
--- a/libstdc++-v3/Makefile.in
|
mgl@1371
|
22530 |
+++ b/libstdc++-v3/Makefile.in
|
mgl@1371
|
22531 |
@@ -36,6 +36,7 @@ POST_UNINSTALL = :
|
mgl@1371
|
22532 |
build_triplet = @build@
|
mgl@1371
|
22533 |
host_triplet = @host@
|
mgl@1371
|
22534 |
target_triplet = @target@
|
mgl@1371
|
22535 |
+LIBOBJDIR =
|
mgl@1371
|
22536 |
DIST_COMMON = README $(am__configure_deps) $(srcdir)/../config.guess \
|
mgl@1371
|
22537 |
$(srcdir)/../config.sub $(srcdir)/../install-sh \
|
mgl@1371
|
22538 |
$(srcdir)/../ltmain.sh $(srcdir)/../missing \
|
mgl@1371
|
22539 |
--- a/libstdc++-v3/po/Makefile.in
|
mgl@1371
|
22540 |
+++ b/libstdc++-v3/po/Makefile.in
|
mgl@1371
|
22541 |
@@ -36,6 +36,7 @@ POST_UNINSTALL = :
|
mgl@1371
|
22542 |
build_triplet = @build@
|
mgl@1371
|
22543 |
host_triplet = @host@
|
mgl@1371
|
22544 |
target_triplet = @target@
|
mgl@1371
|
22545 |
+LIBOBJDIR =
|
mgl@1371
|
22546 |
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
|
mgl@1371
|
22547 |
$(top_srcdir)/fragment.am
|
mgl@1371
|
22548 |
subdir = po
|
mgl@1371
|
22549 |
--- a/libstdc++-v3/src/Makefile.in
|
mgl@1371
|
22550 |
+++ b/libstdc++-v3/src/Makefile.in
|
mgl@1371
|
22551 |
@@ -36,6 +36,7 @@ POST_UNINSTALL = :
|
mgl@1371
|
22552 |
build_triplet = @build@
|
mgl@1371
|
22553 |
host_triplet = @host@
|
mgl@1371
|
22554 |
target_triplet = @target@
|
mgl@1371
|
22555 |
+LIBOBJDIR =
|
mgl@1371
|
22556 |
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
|
mgl@1371
|
22557 |
$(top_srcdir)/fragment.am
|
mgl@1371
|
22558 |
subdir = src
|
mgl@1371
|
22559 |
--- a/Makefile.def
|
mgl@1371
|
22560 |
+++ b/Makefile.def
|
mgl@1371
|
22561 |
@@ -481,7 +481,7 @@ lang_env_dependencies = { module=rda; };
|
mgl@1371
|
22562 |
lang_env_dependencies = { module=winsup; };
|
mgl@1371
|
22563 |
lang_env_dependencies = { module=qthreads; };
|
mgl@1371
|
22564 |
|
mgl@1371
|
22565 |
-dependencies = { module=all-target-libgloss; on=configure-target-newlib; };
|
mgl@1371
|
22566 |
+dependencies = { module=all-target-libgloss; on=all-target-newlib; };
|
mgl@1371
|
22567 |
dependencies = { module=all-target-winsup; on=all-target-libiberty; };
|
mgl@1371
|
22568 |
dependencies = { module=all-target-winsup; on=all-target-libtermcap; };
|
mgl@1371
|
22569 |
|
mgl@1371
|
22570 |
--- a/Makefile.in
|
mgl@1371
|
22571 |
+++ b/Makefile.in
|
mgl@1371
|
22572 |
@@ -43791,7 +43791,7 @@ all-target-libobjc: maybe-all-target-boe
|
mgl@1371
|
22573 |
all-target-libstdc++-v3: maybe-all-target-libiberty
|
mgl@1371
|
22574 |
install-target-libssp: maybe-install-gcc
|
mgl@1371
|
22575 |
install-target-libgomp: maybe-install-gcc
|
mgl@1371
|
22576 |
-all-target-libgloss: maybe-configure-target-newlib
|
mgl@1371
|
22577 |
+all-target-libgloss: maybe-all-target-newlib
|
mgl@1371
|
22578 |
all-target-winsup: maybe-all-target-libiberty
|
mgl@1371
|
22579 |
all-target-winsup: maybe-all-target-libtermcap
|
mgl@1371
|
22580 |
|
mgl@1371
|
22581 |
--- a/gcc/configure.ac
|
mgl@1371
|
22582 |
+++ b/gcc/configure.ac
|
mgl@1371
|
22583 |
@@ -2158,7 +2158,7 @@ L2:],
|
mgl@1371
|
22584 |
as_ver=`$gcc_cv_as --version 2>/dev/null | sed 1q`
|
mgl@1371
|
22585 |
if echo "$as_ver" | grep GNU > /dev/null; then
|
mgl@1371
|
22586 |
changequote(,)dnl
|
mgl@1371
|
22587 |
- as_ver=`echo $as_ver | sed -e 's/GNU assembler \([0-9.][0-9.]*\).*/\1/'`
|
mgl@1371
|
22588 |
+ as_ver=`echo $as_ver | sed -e 's/GNU assembler\( (GNU Binutils)\)\? \([0-9.][0-9.]*\).*/\2/'`
|
mgl@1371
|
22589 |
as_major=`echo $as_ver | sed 's/\..*//'`
|
mgl@1371
|
22590 |
as_minor=`echo $as_ver | sed 's/[^.]*\.\([0-9]*\).*/\1/'`
|
mgl@1371
|
22591 |
changequote([,])dnl
|
mgl@1371
|
22592 |
@@ -2971,7 +2971,7 @@ esac
|
mgl@1371
|
22593 |
case "$target" in
|
mgl@1371
|
22594 |
i?86*-*-* | mips*-*-* | alpha*-*-* | powerpc*-*-* | sparc*-*-* | m68*-*-* \
|
mgl@1371
|
22595 |
| x86_64*-*-* | hppa*-*-* | arm*-*-* | strongarm*-*-* | xscale*-*-* \
|
mgl@1371
|
22596 |
- | xstormy16*-*-* | cris-*-* | xtensa-*-* | bfin-*-* | score*-*-*)
|
mgl@1371
|
22597 |
+ | xstormy16*-*-* | cris-*-* | xtensa-*-* | bfin-*-* | score*-*-* | avr32-*-*)
|
mgl@1371
|
22598 |
insn="nop"
|
mgl@1371
|
22599 |
;;
|
mgl@1371
|
22600 |
ia64*-*-* | s390*-*-*)
|
mgl@1371
|
22601 |
--- a/gcc/configure
|
mgl@1371
|
22602 |
+++ b/gcc/configure
|
mgl@1371
|
22603 |
@@ -14023,7 +14023,7 @@ L2:' > conftest.s
|
mgl@1371
|
22604 |
# arbitrary sections are supported and try the test.
|
mgl@1371
|
22605 |
as_ver=`$gcc_cv_as --version 2>/dev/null | sed 1q`
|
mgl@1371
|
22606 |
if echo "$as_ver" | grep GNU > /dev/null; then
|
mgl@1371
|
22607 |
- as_ver=`echo $as_ver | sed -e 's/GNU assembler \([0-9.][0-9.]*\).*/\1/'`
|
mgl@1371
|
22608 |
+ as_ver=`echo $as_ver | sed -e 's/GNU assembler\( (GNU Binutils)\)\? \([0-9.][0-9.]*\).*/\2/'`
|
mgl@1371
|
22609 |
as_major=`echo $as_ver | sed 's/\..*//'`
|
mgl@1371
|
22610 |
as_minor=`echo $as_ver | sed 's/[^.]*\.\([0-9]*\).*/\1/'`
|
mgl@1371
|
22611 |
if test $as_major -eq 2 && test $as_minor -lt 11
|
mgl@1371
|
22612 |
@@ -15610,7 +15610,7 @@ esac
|
mgl@1371
|
22613 |
case "$target" in
|
mgl@1371
|
22614 |
i?86*-*-* | mips*-*-* | alpha*-*-* | powerpc*-*-* | sparc*-*-* | m68*-*-* \
|
mgl@1371
|
22615 |
| x86_64*-*-* | hppa*-*-* | arm*-*-* | strongarm*-*-* | xscale*-*-* \
|
mgl@1371
|
22616 |
- | xstormy16*-*-* | cris-*-* | xtensa-*-* | bfin-*-* | score*-*-*)
|
mgl@1371
|
22617 |
+ | xstormy16*-*-* | cris-*-* | xtensa-*-* | bfin-*-* | score*-*-* | avr32-*-*)
|
mgl@1371
|
22618 |
insn="nop"
|
mgl@1371
|
22619 |
;;
|
mgl@1371
|
22620 |
ia64*-*-* | s390*-*-*)
|