[toolchain] refresh toolchain patches, add ubicom32 patch to gcc 4.4.1 and 4.4.2
[openwrt/svn-archive/archive.git] / toolchain / gcc / patches / 4.4.1 / 600-ubicom_support.patch
1 --- a/config.sub
2 +++ b/config.sub
3 @@ -283,6 +283,7 @@ case $basic_machine in
4 | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
5 | spu | strongarm \
6 | tahoe | thumb | tic4x | tic80 | tron \
7 + | ubicom32 \
8 | v850 | v850e \
9 | ubicom32 \
10 | we32k \
11 @@ -367,6 +368,7 @@ case $basic_machine in
12 | tahoe-* | thumb-* \
13 | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
14 | tron-* \
15 + | ubicom32-* \
16 | v850-* | v850e-* | vax-* \
17 | ubicom32-* \
18 | we32k-* \
19 --- a/configure
20 +++ b/configure
21 @@ -2688,6 +2688,9 @@ case "${target}" in
22 ip2k-*-*)
23 noconfigdirs="$noconfigdirs target-libiberty target-libstdc++-v3 ${libgcj}"
24 ;;
25 + ubicom32-*-*)
26 + noconfigdirs="$noconfigdirs target-libffi"
27 + ;;
28 *-*-linux* | *-*-gnu* | *-*-k*bsd*-gnu | *-*-kopensolaris*-gnu)
29 noconfigdirs="$noconfigdirs target-newlib target-libgloss"
30 ;;
31 --- /dev/null
32 +++ b/gcc/config/ubicom32/constraints.md
33 @@ -0,0 +1,149 @@
34 +; Constraint definitions for Ubicom32
35 +
36 +; Copyright (C) 2009 Free Software Foundation, Inc.
37 +; Contributed by Ubicom, Inc.
38 +
39 +; This file is part of GCC.
40 +
41 +; GCC is free software; you can redistribute it and/or modify it
42 +; under the terms of the GNU General Public License as published
43 +; by the Free Software Foundation; either version 3, or (at your
44 +; option) any later version.
45 +
46 +; GCC is distributed in the hope that it will be useful, but WITHOUT
47 +; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
48 +; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
49 +; License for more details.
50 +
51 +; You should have received a copy of the GNU General Public License
52 +; along with GCC; see the file COPYING3. If not see
53 +; <http://www.gnu.org/licenses/>.
54 +
55 +(define_register_constraint "a" "ALL_ADDRESS_REGS"
56 + "An An register.")
57 +
58 +(define_register_constraint "d" "DATA_REGS"
59 + "A Dn register.")
60 +
61 +(define_register_constraint "h" "ACC_REGS"
62 + "An accumulator register.")
63 +
64 +(define_register_constraint "l" "ACC_LO_REGS"
65 + "An accn_lo register.")
66 +
67 +(define_register_constraint "Z" "FDPIC_REG"
68 + "The FD-PIC GOT pointer: A0.")
69 +
70 +(define_constraint "I"
71 + "An 8-bit signed constant value."
72 + (and (match_code "const_int")
73 + (match_test "(ival >= -128) && (ival <= 127)")))
74 +
75 +(define_constraint "Q"
76 + "An 8-bit signed constant value represented as unsigned."
77 + (and (match_code "const_int")
78 + (match_test "(ival >= 0x00) && (ival <= 0xff)")))
79 +
80 +(define_constraint "R"
81 + "An 8-bit signed constant value represented as unsigned."
82 + (and (match_code "const_int")
83 + (match_test "((ival >= 0x0000) && (ival <= 0x007f)) || ((ival >= 0xff80) && (ival <= 0xffff))")))
84 +
85 +(define_constraint "J"
86 + "A 7-bit unsigned constant value."
87 + (and (match_code "const_int")
88 + (match_test "(ival >= 0) && (ival <= 127)")))
89 +
90 +(define_constraint "K"
91 + "A 7-bit unsigned constant value shifted << 1."
92 + (and (match_code "const_int")
93 + (match_test "(ival >= 0) && (ival <= 254) && ((ival & 1) == 0)")))
94 +
95 +(define_constraint "L"
96 + "A 7-bit unsigned constant value shifted << 2."
97 + (and (match_code "const_int")
98 + (match_test "(ival >= 0) && (ival <= 508) && ((ival & 3) == 0)")))
99 +
100 +(define_constraint "M"
101 + "A 5-bit unsigned constant value."
102 + (and (match_code "const_int")
103 + (match_test "(ival >= 0) && (ival <= 31)")))
104 +
105 +(define_constraint "N"
106 + "A signed 16 bit constant value."
107 + (and (match_code "const_int")
108 + (match_test "(ival >= -32768) && (ival <= 32767)")))
109 +
110 +(define_constraint "O"
111 + "An exact bitmask of contiguous 1 bits starting at bit 0."
112 + (and (match_code "const_int")
113 + (match_test "exact_log2 (ival + 1) != -1")))
114 +
115 +(define_constraint "P"
116 + "A 7-bit negative constant value shifted << 2."
117 + (and (match_code "const_int")
118 + (match_test "(ival >= -504) && (ival <= 0) && ((ival & 3) == 0)")))
119 +
120 +(define_constraint "S"
121 + "A symbolic reference."
122 + (match_code "symbol_ref"))
123 +
124 +(define_constraint "Y"
125 + "An FD-PIC symbolic reference."
126 + (and (match_test "TARGET_FDPIC")
127 + (match_test "GET_CODE (op) == UNSPEC")
128 + (ior (match_test "XINT (op, 1) == UNSPEC_FDPIC_GOT")
129 + (match_test "XINT (op, 1) == UNSPEC_FDPIC_GOT_FUNCDESC"))))
130 +
131 +(define_memory_constraint "T1"
132 + "A memory operand that can be used for .1 instruction."
133 + (and (match_test "memory_operand (op, GET_MODE(op))")
134 + (match_test "GET_MODE (op) == QImode")))
135 +
136 +(define_memory_constraint "T2"
137 + "A memory operand that can be used for .2 instruction."
138 + (and (match_test "memory_operand (op, GET_MODE(op))")
139 + (match_test "GET_MODE (op) == HImode")))
140 +
141 +(define_memory_constraint "T4"
142 + "A memory operand that can be used for .4 instruction."
143 + (and (match_test "memory_operand (op, GET_MODE(op))")
144 + (ior (match_test "GET_MODE (op) == SImode")
145 + (match_test "GET_MODE (op) == DImode")
146 + (match_test "GET_MODE (op) == SFmode"))))
147 +
148 +(define_memory_constraint "U1"
149 + "An offsettable memory operand that can be used for .1 instruction."
150 + (and (match_test "memory_operand (op, GET_MODE(op))")
151 + (match_test "GET_MODE (op) == QImode")
152 + (match_test "GET_CODE (XEXP (op, 0)) != POST_INC")
153 + (match_test "GET_CODE (XEXP (op, 0)) != PRE_INC")
154 + (match_test "GET_CODE (XEXP (op, 0)) != POST_DEC")
155 + (match_test "GET_CODE (XEXP (op, 0)) != PRE_DEC")
156 + (match_test "GET_CODE (XEXP (op, 0)) != POST_MODIFY")
157 + (match_test "GET_CODE (XEXP (op, 0)) != PRE_MODIFY")))
158 +
159 +(define_memory_constraint "U2"
160 + "An offsettable memory operand that can be used for .2 instruction."
161 + (and (match_test "memory_operand (op, GET_MODE(op))")
162 + (match_test "GET_MODE (op) == HImode")
163 + (match_test "GET_CODE (XEXP (op, 0)) != POST_INC")
164 + (match_test "GET_CODE (XEXP (op, 0)) != PRE_INC")
165 + (match_test "GET_CODE (XEXP (op, 0)) != POST_DEC")
166 + (match_test "GET_CODE (XEXP (op, 0)) != PRE_DEC")
167 + (match_test "GET_CODE (XEXP (op, 0)) != POST_MODIFY")
168 + (match_test "GET_CODE (XEXP (op, 0)) != PRE_MODIFY")))
169 +
170 +(define_memory_constraint "U4"
171 + "An offsettable memory operand that can be used for .4 instruction."
172 + (and (match_test "memory_operand (op, GET_MODE(op))")
173 + (ior (match_test "GET_MODE (op) == SImode")
174 + (match_test "GET_MODE (op) == DImode")
175 + (match_test "GET_MODE (op) == SFmode"))
176 + (match_test "GET_CODE (XEXP (op, 0)) != POST_INC")
177 + (match_test "GET_CODE (XEXP (op, 0)) != PRE_INC")
178 + (match_test "GET_CODE (XEXP (op, 0)) != POST_DEC")
179 + (match_test "GET_CODE (XEXP (op, 0)) != PRE_DEC")
180 + (match_test "GET_CODE (XEXP (op, 0)) != POST_MODIFY")
181 + (match_test "GET_CODE (XEXP (op, 0)) != PRE_MODIFY")))
182 +
183 --- /dev/null
184 +++ b/gcc/config/ubicom32/crti.S
185 @@ -0,0 +1,54 @@
186 +/* Specialized code needed to support construction and destruction of
187 + file-scope objects in C++ and Java code, and to support exception handling.
188 + Copyright (C) 1999 Free Software Foundation, Inc.
189 + Contributed by Charles-Antoine Gauthier (charles.gauthier@iit.nrc.ca).
190 +
191 +This file is part of GCC.
192 +
193 +GCC is free software; you can redistribute it and/or modify
194 +it under the terms of the GNU General Public License as published by
195 +the Free Software Foundation; either version 2, or (at your option)
196 +any later version.
197 +
198 +GCC is distributed in the hope that it will be useful,
199 +but WITHOUT ANY WARRANTY; without even the implied warranty of
200 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
201 +GNU General Public License for more details.
202 +
203 +You should have received a copy of the GNU General Public License
204 +along with GCC; see the file COPYING. If not, write to
205 +the Free Software Foundation, 59 Temple Place - Suite 330,
206 +Boston, MA 02111-1307, USA. */
207 +
208 +/* As a special exception, if you link this library with files
209 + compiled with GCC to produce an executable, this does not cause
210 + the resulting executable to be covered by the GNU General Public License.
211 + This exception does not however invalidate any other reasons why
212 + the executable file might be covered by the GNU General Public License. */
213 +
214 +/*
215 + * This file just supplies function prologues for the .init and .fini
216 + * sections. It is linked in before crtbegin.o.
217 + */
218 + .file "crti.o"
219 + .ident "GNU C crti.o"
220 +
221 + .section .init
222 + .align 2
223 + .globl _init
224 + .type _init, @function
225 +_init:
226 + move.4 -4(sp)++, a5
227 +#ifdef __UBICOM32_FDPIC__
228 + move.4 -4(sp)++, a0
229 +#endif
230 +
231 + .section .fini
232 + .align 2
233 + .globl _fini
234 + .type _fini, @function
235 +_fini:
236 + move.4 -4(sp)++, a5
237 +#ifdef __UBICOM32_FDPIC__
238 + move.4 -4(sp)++, a0
239 +#endif
240 --- /dev/null
241 +++ b/gcc/config/ubicom32/crtn.S
242 @@ -0,0 +1,47 @@
243 +/* Specialized code needed to support construction and destruction of
244 + file-scope objects in C++ and Java code, and to support exception handling.
245 + Copyright (C) 1999 Free Software Foundation, Inc.
246 + Contributed by Charles-Antoine Gauthier (charles.gauthier@iit.nrc.ca).
247 +
248 +This file is part of GCC.
249 +
250 +GCC is free software; you can redistribute it and/or modify
251 +it under the terms of the GNU General Public License as published by
252 +the Free Software Foundation; either version 2, or (at your option)
253 +any later version.
254 +
255 +GCC is distributed in the hope that it will be useful,
256 +but WITHOUT ANY WARRANTY; without even the implied warranty of
257 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
258 +GNU General Public License for more details.
259 +
260 +You should have received a copy of the GNU General Public License
261 +along with GCC; see the file COPYING. If not, write to
262 +the Free Software Foundation, 59 Temple Place - Suite 330,
263 +Boston, MA 02111-1307, USA. */
264 +
265 +/* As a special exception, if you link this library with files
266 + compiled with GCC to produce an executable, this does not cause
267 + the resulting executable to be covered by the GNU General Public License.
268 + This exception does not however invalidate any other reasons why
269 + the executable file might be covered by the GNU General Public License. */
270 +
271 +/*
272 + * This file supplies function epilogues for the .init and .fini sections.
273 + * It is linked in after all other files.
274 + */
275 +
276 + .file "crtn.o"
277 + .ident "GNU C crtn.o"
278 +
279 + .section .init
280 +#ifdef __UBICOM32_FDPIC__
281 + move.4 a0, (sp)4++
282 +#endif
283 + ret (sp)4++
284 +
285 + .section .fini
286 +#ifdef __UBICOM32_FDPIC__
287 + move.4 a0, (sp)4++
288 +#endif
289 + ret (sp)4++
290 --- /dev/null
291 +++ b/gcc/config/ubicom32/elf.h
292 @@ -0,0 +1,29 @@
293 +#undef STARTFILE_SPEC
294 +#define STARTFILE_SPEC "\
295 +%{msim:%{!shared:crt0%O%s}} \
296 +crti%O%s crtbegin%O%s"
297 +
298 +#undef ENDFILE_SPEC
299 +#define ENDFILE_SPEC "crtend%O%s crtn%O%s"
300 +
301 +#ifdef __UBICOM32_FDPIC__
302 +#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
303 + asm (SECTION_OP); \
304 + asm ("move.4 a0, 0(sp);\n\t" \
305 + "call a5," USER_LABEL_PREFIX #FUNC ";"); \
306 + asm (TEXT_SECTION_ASM_OP);
307 +#endif
308 +
309 +#undef SUBTARGET_DRIVER_SELF_SPECS
310 +#define SUBTARGET_DRIVER_SELF_SPECS \
311 + "%{mfdpic:-msim} "
312 +
313 +#define NO_IMPLICIT_EXTERN_C
314 +
315 +/*
316 + * We need this to compile crtbegin/crtend. This should really be picked
317 + * up from elfos.h but at the moment including elfos.h causes other more
318 + * serous linker issues.
319 + */
320 +#define INIT_SECTION_ASM_OP "\t.section\t.init"
321 +#define FINI_SECTION_ASM_OP "\t.section\t.fini"
322 --- /dev/null
323 +++ b/gcc/config/ubicom32/linux.h
324 @@ -0,0 +1,80 @@
325 +/* Definitions of target machine for Ubicom32-uclinux
326 +
327 + Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
328 + 2009 Free Software Foundation, Inc.
329 + Contributed by Ubicom, Inc.
330 +
331 + This file is part of GCC.
332 +
333 + GCC is free software; you can redistribute it and/or modify it
334 + under the terms of the GNU General Public License as published
335 + by the Free Software Foundation; either version 3, or (at your
336 + option) any later version.
337 +
338 + GCC is distributed in the hope that it will be useful, but WITHOUT
339 + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
340 + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
341 + License for more details.
342 +
343 + You should have received a copy of the GNU General Public License
344 + along with GCC; see the file COPYING3. If not see
345 + <http://www.gnu.org/licenses/>. */
346 +
347 +/* Don't assume anything about the header files. */
348 +#define NO_IMPLICIT_EXTERN_C
349 +
350 +#undef LIB_SPEC
351 +#define LIB_SPEC \
352 + "%{pthread:-lpthread} " \
353 + "-lc"
354 +
355 +#undef LINK_GCC_C_SEQUENCE_SPEC
356 +#define LINK_GCC_C_SEQUENCE_SPEC \
357 + "%{static:--start-group} %G %L %{static:--end-group} " \
358 + "%{!static: %G}"
359 +
360 +#undef STARTFILE_SPEC
361 +#define STARTFILE_SPEC \
362 + "%{!shared: %{pg|p|profile:gcrt1%O%s;pie:Scrt1%O%s;:crt1%O%s}} " \
363 + "crtreloc%O%s crti%O%s %{shared|pie:crtbeginS%O%s;:crtbegin%O%s}"
364 +
365 +#undef ENDFILE_SPEC
366 +#define ENDFILE_SPEC \
367 + "%{shared|pie:crtendS%O%s;:crtend%O%s} crtn%O%s"
368 +
369 +/* taken from linux.h */
370 +/* The GNU C++ standard library requires that these macros be defined. */
371 +#undef CPLUSPLUS_CPP_SPEC
372 +#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
373 +
374 +#define TARGET_OS_CPP_BUILTINS() \
375 + do { \
376 + builtin_define_std ("__UBICOM32__"); \
377 + builtin_define_std ("__ubicom32__"); \
378 + builtin_define ("__gnu_linux__"); \
379 + builtin_define_std ("linux"); \
380 + builtin_define_std ("unix"); \
381 + builtin_assert ("system=linux"); \
382 + builtin_assert ("system=unix"); \
383 + builtin_assert ("system=posix"); \
384 + } while (0)
385 +
386 +#define OBJECT_FORMAT_ELF
387 +
388 +
389 +#undef DRIVER_SELF_SPECS
390 +#define DRIVER_SELF_SPECS \
391 + "%{!mno-fdpic:-mfdpic}"
392 +
393 +#undef LINK_SPEC
394 +#define LINK_SPEC "%{mfdpic: -m elf32ubicom32fdpic -z text } %{shared} %{pie} \
395 + %{static:-dn -Bstatic} \
396 + %{shared:-G -Bdynamic} \
397 + %{!shared: %{!static: \
398 + %{rdynamic:-export-dynamic} \
399 + %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}} \
400 + %{static}} "
401 +
402 +/*
403 +#define MD_UNWIND_SUPPORT "config/bfin/linux-unwind.h"
404 +*/
405 --- /dev/null
406 +++ b/gcc/config/ubicom32/predicates.md
407 @@ -0,0 +1,327 @@
408 +; Predicate definitions for Ubicom32.
409 +
410 +; Copyright (C) 2009 Free Software Foundation, Inc.
411 +; Contributed by Ubicom, Inc.
412 +
413 +; This file is part of GCC.
414 +
415 +; GCC is free software; you can redistribute it and/or modify it
416 +; under the terms of the GNU General Public License as published
417 +; by the Free Software Foundation; either version 3, or (at your
418 +; option) any later version.
419 +
420 +; GCC is distributed in the hope that it will be useful, but WITHOUT
421 +; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
422 +; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
423 +; License for more details.
424 +
425 +; You should have received a copy of the GNU General Public License
426 +; along with GCC; see the file COPYING3. If not see
427 +; <http://www.gnu.org/licenses/>.
428 +
429 +(define_predicate "ubicom32_move_operand"
430 + (match_code "const_int, const_double, const, mem, subreg, reg, lo_sum")
431 +{
432 + if (CONST_INT_P (op))
433 + return true;
434 +
435 + if (GET_CODE (op) == CONST_DOUBLE)
436 + return true;
437 +
438 + if (GET_CODE (op) == CONST)
439 + return memory_address_p (mode, op);
440 +
441 + if (GET_MODE (op) != mode)
442 + return false;
443 +
444 + if (MEM_P (op))
445 + return memory_address_p (mode, XEXP (op, 0));
446 +
447 + if (GET_CODE (op) == SUBREG) {
448 + op = SUBREG_REG (op);
449 +
450 + if (REG_P (op))
451 + return true;
452 +
453 + if (! MEM_P (op))
454 + return false;
455 +
456 + /* Paradoxical SUBREG. */
457 + if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (op)))
458 + return false;
459 +
460 + return memory_address_p (GET_MODE (op), XEXP (op, 0));
461 + }
462 +
463 + return register_operand (op, mode);
464 +})
465 +
466 +;; Returns true if OP is either a symbol reference or a sum of a
467 +;; symbol reference and a constant.
468 +
469 +(define_predicate "ubicom32_symbolic_address_operand"
470 + (match_code "symbol_ref, label_ref, const")
471 +{
472 + switch (GET_CODE (op))
473 + {
474 + case SYMBOL_REF:
475 + case LABEL_REF:
476 + return true;
477 +
478 + case CONST:
479 + op = XEXP (op, 0);
480 + return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
481 + || GET_CODE (XEXP (op, 0)) == LABEL_REF)
482 + && CONST_INT_P (XEXP (op, 1)));
483 +
484 + default:
485 + return false;
486 + }
487 +})
488 +
489 +;; Return true if operand is the uClinux FD-PIC register.
490 +
491 +(define_predicate "ubicom32_fdpic_operand"
492 + (match_code "reg")
493 +{
494 + if (! TARGET_FDPIC)
495 + return false;
496 +
497 + if (!REG_P (op))
498 + return false;
499 +
500 + if (GET_MODE (op) != mode && mode != VOIDmode)
501 + return false;
502 +
503 + if (REGNO (op) != FDPIC_REGNUM && REGNO (op) < FIRST_PSEUDO_REGISTER)
504 + return false;
505 +
506 + return true;
507 +})
508 +
509 +(define_predicate "ubicom32_fdpic_got_offset_operand"
510 + (match_code "unspec")
511 +{
512 + if (! TARGET_FDPIC)
513 + return false;
514 +
515 + if (GET_CODE (op) != UNSPEC)
516 + return false;
517 +
518 + if (XINT (op, 1) != UNSPEC_FDPIC_GOT
519 + && XINT (op, 1) != UNSPEC_FDPIC_GOT_FUNCDESC)
520 + return false;
521 +
522 + return true;
523 +})
524 +
525 +(define_predicate "ubicom32_arith_operand"
526 + (match_code "subreg, reg, const_int, lo_sum, mem")
527 +{
528 + return (ubicom32_move_operand (op, mode)
529 + && ! ubicom32_symbolic_address_operand (op, mode)
530 + && (! CONST_INT_P (op)
531 + || satisfies_constraint_I (op)));
532 +})
533 +
534 +(define_predicate "ubicom32_arith_operand_dot1"
535 + (match_code "subreg, reg, const_int, lo_sum, mem")
536 +{
537 + return (ubicom32_move_operand (op, mode)
538 + && ! ubicom32_symbolic_address_operand (op, mode)
539 + && (! CONST_INT_P (op)
540 + || satisfies_constraint_Q (op)));
541 +})
542 +
543 +(define_predicate "ubicom32_arith_operand_dot2"
544 + (match_code "subreg, reg, const_int, lo_sum, mem")
545 +{
546 + return (ubicom32_move_operand (op, mode)
547 + && ! ubicom32_symbolic_address_operand (op, mode)
548 + && (! CONST_INT_P (op)
549 + || satisfies_constraint_R (op)));
550 +})
551 +
552 +(define_predicate "ubicom32_compare_operand"
553 + (match_code "subreg, reg, const_int, lo_sum, mem")
554 +{
555 + return (ubicom32_move_operand (op, mode)
556 + && ! ubicom32_symbolic_address_operand (op, mode)
557 + && (! CONST_INT_P (op)
558 + || satisfies_constraint_N (op)));
559 +})
560 +
561 +(define_predicate "ubicom32_compare_operator"
562 + (match_code "compare"))
563 +
564 +(define_predicate "ubicom32_and_or_si3_operand"
565 + (match_code "subreg, reg, const_int, lo_sum, mem")
566 +{
567 + return (ubicom32_arith_operand (op, mode)
568 + || (CONST_INT_P (op)
569 + && ((exact_log2 (INTVAL (op) + 1) != -1
570 + && exact_log2 (INTVAL (op) + 1) <= 31)
571 + || (exact_log2 (INTVAL (op)) != -1
572 + && exact_log2 (INTVAL (op)) <= 31)
573 + || (exact_log2 (~INTVAL (op)) != -1
574 + && exact_log2 (~INTVAL (op)) <= 31))));
575 +})
576 +
577 +(define_predicate "ubicom32_and_or_hi3_operand"
578 + (match_code "subreg, reg, const_int, lo_sum, mem")
579 +{
580 + return (ubicom32_arith_operand (op, mode)
581 + || (CONST_INT_P (op)
582 + && exact_log2 (INTVAL (op) + 1) != -1
583 + && exact_log2 (INTVAL (op) + 1) <= 15));
584 +})
585 +
586 +(define_predicate "ubicom32_mem_or_address_register_operand"
587 + (match_code "subreg, reg, mem")
588 +{
589 + unsigned int regno;
590 +
591 + if (MEM_P (op)
592 + && memory_operand (op, mode))
593 + return true;
594 +
595 + if (REG_P (op))
596 + regno = REGNO (op);
597 + else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
598 + {
599 + int offset;
600 + if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)
601 + offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op)));
602 + else
603 + offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
604 + GET_MODE (SUBREG_REG (op)),
605 + SUBREG_BYTE (op),
606 + GET_MODE (op));
607 + regno = REGNO (SUBREG_REG (op)) + offset;
608 + }
609 + else
610 + return false;
611 +
612 + return (regno >= FIRST_PSEUDO_REGISTER
613 + || REGNO_REG_CLASS (regno) == FDPIC_REG
614 + || REGNO_REG_CLASS (regno) == ADDRESS_REGS);
615 +})
616 +
617 +(define_predicate "ubicom32_data_register_operand"
618 + (match_code "subreg, reg")
619 +{
620 + unsigned int regno;
621 +
622 + if (REG_P (op))
623 + regno = REGNO (op);
624 + else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
625 + {
626 + int offset;
627 + if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)
628 + offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op)));
629 + else
630 + offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
631 + GET_MODE (SUBREG_REG (op)),
632 + SUBREG_BYTE (op),
633 + GET_MODE (op));
634 + regno = REGNO (SUBREG_REG (op)) + offset;
635 + }
636 + else
637 + return false;
638 +
639 + return ((regno >= FIRST_PSEUDO_REGISTER
640 + && regno != REGNO (virtual_stack_vars_rtx))
641 + || REGNO_REG_CLASS (regno) == DATA_REGS);
642 +})
643 +
644 +(define_predicate "ubicom32_address_register_operand"
645 + (match_code "subreg, reg")
646 +{
647 + unsigned int regno;
648 +
649 + if (REG_P (op))
650 + regno = REGNO (op);
651 + else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
652 + {
653 + int offset;
654 + if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)
655 + offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op)));
656 + else
657 + offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
658 + GET_MODE (SUBREG_REG (op)),
659 + SUBREG_BYTE (op),
660 + GET_MODE (op));
661 + regno = REGNO (SUBREG_REG (op)) + offset;
662 + }
663 + else
664 + return false;
665 +
666 + return (regno >= FIRST_PSEUDO_REGISTER
667 + || REGNO_REG_CLASS (regno) == FDPIC_REG
668 + || REGNO_REG_CLASS (regno) == ADDRESS_REGS);
669 +})
670 +
671 +(define_predicate "ubicom32_acc_lo_register_operand"
672 + (match_code "subreg, reg")
673 +{
674 + unsigned int regno;
675 +
676 + if (REG_P (op))
677 + regno = REGNO (op);
678 + else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
679 + {
680 + int offset;
681 + if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)
682 + offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op)));
683 + else
684 + offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
685 + GET_MODE (SUBREG_REG (op)),
686 + SUBREG_BYTE (op),
687 + GET_MODE (op));
688 + regno = REGNO (SUBREG_REG (op)) + offset;
689 + }
690 + else
691 + return false;
692 +
693 + return ((regno >= FIRST_PSEUDO_REGISTER
694 + && regno != REGNO (virtual_stack_vars_rtx))
695 + || REGNO_REG_CLASS (regno) == ACC_LO_REGS);
696 +})
697 +
698 +(define_predicate "ubicom32_acc_hi_register_operand"
699 + (match_code "subreg, reg")
700 +{
701 + unsigned int regno;
702 +
703 + if (REG_P (op))
704 + regno = REGNO (op);
705 + else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
706 + {
707 + int offset;
708 + if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)
709 + offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op)));
710 + else
711 + offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
712 + GET_MODE (SUBREG_REG (op)),
713 + SUBREG_BYTE (op),
714 + GET_MODE (op));
715 + regno = REGNO (SUBREG_REG (op)) + offset;
716 + }
717 + else
718 + return false;
719 +
720 + return ((regno >= FIRST_PSEUDO_REGISTER
721 + && regno != REGNO (virtual_stack_vars_rtx))
722 + || REGNO_REG_CLASS (regno) == ACC_REGS);
723 +})
724 +
725 +(define_predicate "ubicom32_call_address_operand"
726 + (match_code "symbol_ref, subreg, reg")
727 +{
728 + return (GET_CODE (op) == SYMBOL_REF || REG_P (op));
729 +})
730 +
731 +(define_special_predicate "ubicom32_cc_register_operand"
732 + (and (match_code "reg")
733 + (match_test "REGNO (op) == CC_REGNUM")))
734 +
735 --- /dev/null
736 +++ b/gcc/config/ubicom32/t-ubicom32
737 @@ -0,0 +1,52 @@
738 +# Name of assembly file containing libgcc1 functions.
739 +# This entry must be present, but it can be empty if the target does
740 +# not need any assembler functions to support its code generation.
741 +CROSS_LIBGCC1 =
742 +
743 +# Alternatively if assembler functions *are* needed then define the
744 +# entries below:
745 +# CROSS_LIBGCC1 = libgcc1-asm.a
746 +
747 +LIB2FUNCS_EXTRA = \
748 + $(srcdir)/config/udivmodsi4.c \
749 + $(srcdir)/config/divmod.c \
750 + $(srcdir)/config/udivmod.c
751 +
752 +# If any special flags are necessary when building libgcc2 put them here.
753 +#
754 +# TARGET_LIBGCC2_CFLAGS =
755 +
756 +# We want fine grained libraries, so use the new code to build the
757 +# floating point emulation libraries.
758 +FPBIT = fp-bit.c
759 +DPBIT = dp-bit.c
760 +
761 +fp-bit.c: $(srcdir)/config/fp-bit.c
762 + echo '#define FLOAT' > fp-bit.c
763 + cat $(srcdir)/config/fp-bit.c >> fp-bit.c
764 +
765 +dp-bit.c: $(srcdir)/config/fp-bit.c
766 + cat $(srcdir)/config/fp-bit.c > dp-bit.c
767 +
768 +# Commented out to speed up compiler development!
769 +#
770 +# MULTILIB_OPTIONS = march=ubicom32v1/march=ubicom32v2/march=ubicom32v3/march=ubicom32v4
771 +# MULTILIB_DIRNAMES = ubicom32v1 ubicom32v2 ubicom32v3 ubicom32v4
772 +
773 +MULTILIB_OPTIONS = march=ubicom32v3/march=ubicom32v4
774 +MULTILIB_OPTIONS += mfdpic
775 +MULTILIB_OPTIONS += mno-ipos-abi/mipos-abi
776 +MULTILIB_OPTIONS += fno-leading-underscore/fleading-underscore
777 +
778 +# Assemble startup files.
779 +$(T)crti.o: $(srcdir)/config/ubicom32/crti.S $(GCC_PASSES)
780 + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
781 + -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/ubicom32/crti.S
782 +
783 +$(T)crtn.o: $(srcdir)/config/ubicom32/crtn.S $(GCC_PASSES)
784 + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
785 + -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/ubicom32/crtn.S
786 +
787 +# these parts are required because uClibc ldso needs them to link.
788 +# they are not in the specfile so they will not be included automatically.
789 +EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crtbeginS.o crtendS.o crti.o crtn.o
790 --- /dev/null
791 +++ b/gcc/config/ubicom32/t-ubicom32-linux
792 @@ -0,0 +1,35 @@
793 +# Name of assembly file containing libgcc1 functions.
794 +# This entry must be present, but it can be empty if the target does
795 +# not need any assembler functions to support its code generation.
796 +CROSS_LIBGCC1 =
797 +
798 +# Alternatively if assembler functions *are* needed then define the
799 +# entries below:
800 +# CROSS_LIBGCC1 = libgcc1-asm.a
801 +
802 +LIB2FUNCS_EXTRA = \
803 + $(srcdir)/config/udivmodsi4.c \
804 + $(srcdir)/config/divmod.c \
805 + $(srcdir)/config/udivmod.c
806 +
807 +# If any special flags are necessary when building libgcc2 put them here.
808 +#
809 +# TARGET_LIBGCC2_CFLAGS =
810 +
811 +# We want fine grained libraries, so use the new code to build the
812 +# floating point emulation libraries.
813 +FPBIT = fp-bit.c
814 +DPBIT = dp-bit.c
815 +
816 +fp-bit.c: $(srcdir)/config/fp-bit.c
817 + echo '#define FLOAT' > fp-bit.c
818 + cat $(srcdir)/config/fp-bit.c >> fp-bit.c
819 +
820 +dp-bit.c: $(srcdir)/config/fp-bit.c
821 + cat $(srcdir)/config/fp-bit.c > dp-bit.c
822 +
823 +# We only support v3 and v4 ISAs for uClinux.
824 +
825 +MULTILIB_OPTIONS = march=ubicom32v3/march=ubicom32v4
826 +
827 +#EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crtbeginS.o crtendS.o
828 --- /dev/null
829 +++ b/gcc/config/ubicom32/t-ubicom32-uclinux
830 @@ -0,0 +1,35 @@
831 +# Name of assembly file containing libgcc1 functions.
832 +# This entry must be present, but it can be empty if the target does
833 +# not need any assembler functions to support its code generation.
834 +CROSS_LIBGCC1 =
835 +
836 +# Alternatively if assembler functions *are* needed then define the
837 +# entries below:
838 +# CROSS_LIBGCC1 = libgcc1-asm.a
839 +
840 +LIB2FUNCS_EXTRA = \
841 + $(srcdir)/config/udivmodsi4.c \
842 + $(srcdir)/config/divmod.c \
843 + $(srcdir)/config/udivmod.c
844 +
845 +# If any special flags are necessary when building libgcc2 put them here.
846 +#
847 +# TARGET_LIBGCC2_CFLAGS =
848 +
849 +# We want fine grained libraries, so use the new code to build the
850 +# floating point emulation libraries.
851 +FPBIT = fp-bit.c
852 +DPBIT = dp-bit.c
853 +
854 +fp-bit.c: $(srcdir)/config/fp-bit.c
855 + echo '#define FLOAT' > fp-bit.c
856 + cat $(srcdir)/config/fp-bit.c >> fp-bit.c
857 +
858 +dp-bit.c: $(srcdir)/config/fp-bit.c
859 + cat $(srcdir)/config/fp-bit.c > dp-bit.c
860 +
861 +# We only support v3 and v4 ISAs for uClinux.
862 +
863 +MULTILIB_OPTIONS = march=ubicom32v3/march=ubicom32v4
864 +
865 +EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o # crtbeginS.o crtendS.o
866 --- /dev/null
867 +++ b/gcc/config/ubicom32/ubicom32-modes.def
868 @@ -0,0 +1,30 @@
869 +/* Definitions of target machine for GNU compiler, Ubicom32 architecture.
870 + Copyright (C) 2009 Free Software Foundation, Inc.
871 + Contributed by Ubicom, Inc.
872 +
873 + This file is part of GCC.
874 +
875 + GCC is free software; you can redistribute it and/or modify it
876 + under the terms of the GNU General Public License as published
877 + by the Free Software Foundation; either version 3, or (at your
878 + option) any later version.
879 +
880 + GCC is distributed in the hope that it will be useful, but WITHOUT
881 + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
882 + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
883 + License for more details.
884 +
885 + You should have received a copy of the GNU General Public License
886 + along with GCC; see the file COPYING3. If not see
887 + <http://www.gnu.org/licenses/>. */
888 +
889 +/* Some insns set all condition code flags, some only set the Z and N flags, and
890 + some only set the Z flag. */
891 +
892 +CC_MODE (CCW);
893 +CC_MODE (CCWZN);
894 +CC_MODE (CCWZ);
895 +CC_MODE (CCS);
896 +CC_MODE (CCSZN);
897 +CC_MODE (CCSZ);
898 +
899 --- /dev/null
900 +++ b/gcc/config/ubicom32/ubicom32-protos.h
901 @@ -0,0 +1,84 @@
902 +/* Function prototypes for Ubicom IP3000.
903 +
904 + Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
905 + 2009 Free Software Foundation, Inc.
906 + Contributed by Ubicom, Inc.
907 +
908 + This file is part of GNU CC.
909 +
910 + GNU CC is free software; you can redistribute it and/or modify it under
911 + the terms of the GNU General Public License as published by the Free
912 + Software Foundation; either version 2, or (at your option) any later
913 + version.
914 +
915 + GNU CC is distributed in the hope that it will be useful, but WITHOUT
916 + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
917 + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
918 + for more details.
919 +
920 + You should have received a copy of the GNU General Public License along
921 + with GNU CC; see the file COPYING. If not, write to the Free Software
922 + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
923 +
924 +#ifdef RTX_CODE
925 +
926 +#ifdef TREE_CODE
927 +extern void ubicom32_va_start (tree, rtx);
928 +#endif /* TREE_CODE */
929 +
930 +extern void ubicom32_print_operand (FILE *, rtx, int);
931 +extern void ubicom32_print_operand_address (FILE *, rtx);
932 +
933 +extern void ubicom32_conditional_register_usage (void);
934 +extern enum reg_class ubicom32_preferred_reload_class (rtx, enum reg_class);
935 +extern int ubicom32_regno_ok_for_index_p (int, int);
936 +extern void ubicom32_expand_movsi (rtx *);
937 +extern void ubicom32_expand_addsi3 (rtx *);
938 +extern int ubicom32_emit_mult_sequence (rtx *);
939 +extern void ubicom32_emit_move_const_int (rtx, rtx);
940 +extern bool ubicom32_legitimate_constant_p (rtx);
941 +extern bool ubicom32_legitimate_address_p (enum machine_mode, rtx, int);
942 +extern rtx ubicom32_legitimize_address (rtx, rtx, enum machine_mode);
943 +extern rtx ubicom32_legitimize_reload_address (rtx, enum machine_mode, int, int);
944 +extern void ubicom32_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1);
945 +extern int ubicom32_mode_dependent_address_p (rtx);
946 +extern void ubicom32_output_cond_jump (rtx, rtx, rtx);
947 +extern void ubicom32_expand_eh_return (rtx *);
948 +extern void ubicom32_expand_call_fdpic (rtx *);
949 +extern void ubicom32_expand_call_value_fdpic (rtx *);
950 +extern enum machine_mode ubicom32_select_cc_mode (RTX_CODE, rtx, rtx);
951 +extern rtx ubicom32_gen_compare_reg (RTX_CODE, rtx, rtx);
952 +extern int ubicom32_shiftable_const_int (int);
953 +#endif /* RTX_CODE */
954 +
955 +#ifdef TREE_CODE
956 +extern void init_cumulative_args (CUMULATIVE_ARGS *cum,
957 + tree fntype,
958 + struct rtx_def *libname,
959 + int indirect);
960 +extern struct rtx_def *function_arg (CUMULATIVE_ARGS *,
961 + enum machine_mode, tree, int);
962 +extern struct rtx_def *function_incoming_arg (CUMULATIVE_ARGS *,
963 + enum machine_mode,
964 + tree, int);
965 +extern int function_arg_partial_nregs (CUMULATIVE_ARGS *,
966 + enum machine_mode, tree, int);
967 +extern struct rtx_def *ubicom32_va_arg (tree, tree);
968 +extern int ubicom32_reg_parm_stack_space (tree);
969 +#endif /* TREE_CODE */
970 +
971 +extern struct rtx_def * ubicom32_builtin_saveregs (void);
972 +extern void asm_file_start (FILE *);
973 +extern void ubicom32_expand_prologue (void);
974 +extern void ubicom32_expand_epilogue (void);
975 +extern int ubicom32_initial_elimination_offset (int, int);
976 +extern int ubicom32_regno_ok_for_base_p (int, int);
977 +extern bool ubicom32_hard_regno_mode_ok (unsigned int, enum machine_mode);
978 +extern int ubicom32_can_use_return_insn_p (void);
979 +extern rtx ubicom32_return_addr_rtx (int, rtx);
980 +extern void ubicom32_optimization_options (int, int);
981 +extern void ubicom32_override_options (void);
982 +extern bool ubicom32_match_cc_mode (rtx, enum machine_mode);
983 +
984 +extern int ubicom32_reorg_completed;
985 +
986 --- /dev/null
987 +++ b/gcc/config/ubicom32/ubicom32.c
988 @@ -0,0 +1,2881 @@
989 +/* Subroutines for insn-output.c for Ubicom32
990 +
991 + Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
992 + 2009 Free Software Foundation, Inc.
993 + Contributed by Ubicom, Inc.
994 +
995 + This file is part of GCC.
996 +
997 + GCC is free software; you can redistribute it and/or modify it
998 + under the terms of the GNU General Public License as published
999 + by the Free Software Foundation; either version 3, or (at your
1000 + option) any later version.
1001 +
1002 + GCC is distributed in the hope that it will be useful, but WITHOUT
1003 + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
1004 + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
1005 + License for more details.
1006 +
1007 + You should have received a copy of the GNU General Public License
1008 + along with GCC; see the file COPYING3. If not see
1009 + <http://www.gnu.org/licenses/>. */
1010 +
1011 +#include "config.h"
1012 +#include "system.h"
1013 +#include "coretypes.h"
1014 +#include "tm.h"
1015 +#include "rtl.h"
1016 +#include "tree.h"
1017 +#include "regs.h"
1018 +#include "hard-reg-set.h"
1019 +#include "real.h"
1020 +#include "insn-config.h"
1021 +#include "conditions.h"
1022 +#include "insn-flags.h"
1023 +#include "output.h"
1024 +#include "insn-attr.h"
1025 +#include "insn-codes.h"
1026 +#include "flags.h"
1027 +#include "recog.h"
1028 +#include "expr.h"
1029 +#include "function.h"
1030 +#include "obstack.h"
1031 +#include "toplev.h"
1032 +#include "tm_p.h"
1033 +#include "tm-constrs.h"
1034 +#include "basic-block.h"
1035 +#include "integrate.h"
1036 +#include "target.h"
1037 +#include "target-def.h"
1038 +#include "reload.h"
1039 +#include "df.h"
1040 +#include "langhooks.h"
1041 +#include "optabs.h"
1042 +
1043 +static tree ubicom32_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
1044 +static void ubicom32_layout_frame (void);
1045 +static void ubicom32_function_prologue (FILE *, HOST_WIDE_INT);
1046 +static void ubicom32_function_epilogue (FILE *, HOST_WIDE_INT);
1047 +static bool ubicom32_rtx_costs (rtx, int, int, int *, bool speed);
1048 +static bool ubicom32_fixed_condition_code_regs (unsigned int *,
1049 + unsigned int *);
1050 +static enum machine_mode ubicom32_cc_modes_compatible (enum machine_mode,
1051 + enum machine_mode);
1052 +static int ubicom32_naked_function_p (void);
1053 +static void ubicom32_machine_dependent_reorg (void);
1054 +static bool ubicom32_assemble_integer (rtx, unsigned int, int);
1055 +static void ubicom32_asm_init_sections (void);
1056 +static int ubicom32_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,tree,
1057 + bool);
1058 +static bool ubicom32_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
1059 + enum machine_mode mode, const_tree type,
1060 + bool named ATTRIBUTE_UNUSED);
1061 +static bool ubicom32_callee_copies (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
1062 + enum machine_mode mode, const_tree type,
1063 + bool named ATTRIBUTE_UNUSED);
1064 +
1065 +static bool ubicom32_return_in_memory (const_tree type,
1066 + const_tree fntype ATTRIBUTE_UNUSED);
1067 +static bool ubicom32_is_base_reg (rtx, int);
1068 +static void ubicom32_init_builtins (void);
1069 +static rtx ubicom32_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
1070 +static tree ubicom32_fold_builtin (tree, tree, bool);
1071 +static int ubicom32_get_valid_offset_mask (enum machine_mode);
1072 +static bool ubicom32_cannot_force_const_mem (rtx);
1073 +
1074 +/* Case values threshold */
1075 +int ubicom32_case_values_threshold = 6;
1076 +
1077 +/* Nonzero if this chip supports the Ubicom32 v3 ISA. */
1078 +int ubicom32_v3 = 1;
1079 +
1080 +/* Nonzero if this chip supports the Ubicom32 v4 ISA. */
1081 +int ubicom32_v4 = 1;
1082 +
1083 +/* Valid attributes:
1084 + naked - don't generate function prologue/epilogue and `ret' command. */
1085 +const struct attribute_spec ubicom32_attribute_table[] =
1086 +{
1087 + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
1088 + { "naked", 0, 0, true, false, false, ubicom32_handle_fndecl_attribute },
1089 + { NULL, 0, 0, false, false, false, NULL }
1090 +};
1091 +
1092 +#undef TARGET_ASM_FUNCTION_PROLOGUE
1093 +#define TARGET_ASM_FUNCTION_PROLOGUE ubicom32_function_prologue
1094 +
1095 +#undef TARGET_ASM_FUNCTION_EPILOGUE
1096 +#define TARGET_ASM_FUNCTION_EPILOGUE ubicom32_function_epilogue
1097 +
1098 +#undef TARGET_ATTRIBUTE_TABLE
1099 +#define TARGET_ATTRIBUTE_TABLE ubicom32_attribute_table
1100 +
1101 +/* All addresses cost the same amount. */
1102 +#undef TARGET_ADDRESS_COST
1103 +#define TARGET_ADDRESS_COST hook_int_rtx_bool_0
1104 +
1105 +#undef TARGET_RTX_COSTS
1106 +#define TARGET_RTX_COSTS ubicom32_rtx_costs
1107 +
1108 +#undef TARGET_FIXED_CONDITION_CODE_REGS
1109 +#define TARGET_FIXED_CONDITION_CODE_REGS ubicom32_fixed_condition_code_regs
1110 +
1111 +#undef TARGET_CC_MODES_COMPATIBLE
1112 +#define TARGET_CC_MODES_COMPATIBLE ubicom32_cc_modes_compatible
1113 +
1114 +#undef TARGET_MACHINE_DEPENDENT_REORG
1115 +#define TARGET_MACHINE_DEPENDENT_REORG ubicom32_machine_dependent_reorg
1116 +
1117 +#undef TARGET_ASM_INTEGER
1118 +#define TARGET_ASM_INTEGER ubicom32_assemble_integer
1119 +
1120 +#undef TARGET_ASM_INIT_SECTIONS
1121 +#define TARGET_ASM_INIT_SECTIONS ubicom32_asm_init_sections
1122 +
1123 +#undef TARGET_ARG_PARTIAL_BYTES
1124 +#define TARGET_ARG_PARTIAL_BYTES ubicom32_arg_partial_bytes
1125 +
1126 +#undef TARGET_PASS_BY_REFERENCE
1127 +#define TARGET_PASS_BY_REFERENCE ubicom32_pass_by_reference
1128 +
1129 +#undef TARGET_CALLEE_COPIES
1130 +#define TARGET_CALLEE_COPIES ubicom32_callee_copies
1131 +
1132 +#undef TARGET_RETURN_IN_MEMORY
1133 +#define TARGET_RETURN_IN_MEMORY ubicom32_return_in_memory
1134 +
1135 +#undef TARGET_INIT_BUILTINS
1136 +#define TARGET_INIT_BUILTINS ubicom32_init_builtins
1137 +
1138 +#undef TARGET_EXPAND_BUILTIN
1139 +#define TARGET_EXPAND_BUILTIN ubicom32_expand_builtin
1140 +
1141 +#undef TARGET_FOLD_BUILTIN
1142 +#define TARGET_FOLD_BUILTIN ubicom32_fold_builtin
1143 +
1144 +#undef TARGET_CANNOT_FORCE_CONST_MEM
1145 +#define TARGET_CANNOT_FORCE_CONST_MEM ubicom32_cannot_force_const_mem
1146 +
1147 +struct gcc_target targetm = TARGET_INITIALIZER;
1148 +
1149 +static char save_regs[FIRST_PSEUDO_REGISTER];
1150 +static int nregs;
1151 +static int frame_size;
1152 +int ubicom32_stack_size = 0; /* size of allocated stack (including frame) */
1153 +int ubicom32_can_use_calli_to_ret;
1154 +
1155 +#define STACK_UNIT_BOUNDARY (STACK_BOUNDARY / BITS_PER_UNIT)
1156 +#define ROUND_CALL_BLOCK_SIZE(BYTES) \
1157 + (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1))
1158 +
1159 +/* In case of a PRE_INC, POST_INC, PRE_DEC, POST_DEC memory reference, we
1160 + must report the mode of the memory reference from PRINT_OPERAND to
1161 + PRINT_OPERAND_ADDRESS. */
1162 +enum machine_mode output_memory_reference_mode;
1163 +
1164 +/* Flag for some split insns from the ubicom32.md. */
1165 +int ubicom32_reorg_completed;
1166 +
1167 +enum reg_class const ubicom32_regclass_map[FIRST_PSEUDO_REGISTER] =
1168 +{
1169 + DATA_REGS,
1170 + DATA_REGS,
1171 + DATA_REGS,
1172 + DATA_REGS,
1173 + DATA_REGS,
1174 + DATA_REGS,
1175 + DATA_REGS,
1176 + DATA_REGS,
1177 + DATA_REGS,
1178 + DATA_REGS,
1179 + DATA_REGS,
1180 + DATA_REGS,
1181 + DATA_REGS,
1182 + DATA_REGS,
1183 + DATA_REGS,
1184 + DATA_REGS,
1185 + FDPIC_REG,
1186 + ADDRESS_REGS,
1187 + ADDRESS_REGS,
1188 + ADDRESS_REGS,
1189 + ADDRESS_REGS,
1190 + ADDRESS_REGS,
1191 + ADDRESS_REGS,
1192 + ADDRESS_REGS,
1193 + ACC_REGS,
1194 + ACC_LO_REGS,
1195 + ACC_REGS,
1196 + ACC_LO_REGS,
1197 + SOURCE3_REG,
1198 + ADDRESS_REGS,
1199 + NO_REGS, /* CC_REG must be NO_REGS */
1200 + SPECIAL_REGS,
1201 + SPECIAL_REGS,
1202 + SPECIAL_REGS,
1203 + SPECIAL_REGS,
1204 + SPECIAL_REGS,
1205 + SPECIAL_REGS,
1206 + SPECIAL_REGS,
1207 + SPECIAL_REGS
1208 +};
1209 +
1210 +rtx ubicom32_compare_op0;
1211 +rtx ubicom32_compare_op1;
1212 +
1213 +/* Handle command line option overrides. */
1214 +
1215 +void
1216 +ubicom32_override_options (void)
1217 +{
1218 + flag_pic = 0;
1219 +
1220 + if (strcmp (ubicom32_arch_name, "ubicom32v1") == 0) {
1221 + /* If we have a version 1 architecture then we want to avoid using jump
1222 + tables. */
1223 + ubicom32_case_values_threshold = 30000;
1224 + ubicom32_v3 = 0;
1225 + ubicom32_v4 = 0;
1226 + } else if (strcmp (ubicom32_arch_name, "ubicom32v2") == 0) {
1227 + ubicom32_v3 = 0;
1228 + ubicom32_v4 = 0;
1229 + } else if (strcmp (ubicom32_arch_name, "ubicom32v3") == 0) {
1230 + ubicom32_v3 = 1;
1231 + ubicom32_v4 = 0;
1232 + } else if (strcmp (ubicom32_arch_name, "ubicom32v4") == 0) {
1233 + ubicom32_v3 = 1;
1234 + ubicom32_v4 = 1;
1235 + }
1236 +
1237 + /* There is no single unaligned SI op for PIC code. Sometimes we
1238 + need to use ".4byte" and sometimes we need to use ".picptr".
1239 + See ubicom32_assemble_integer for details. */
1240 + if (TARGET_FDPIC)
1241 + targetm.asm_out.unaligned_op.si = 0;
1242 +}
1243 +
1244 +void
1245 +ubicom32_conditional_register_usage (void)
1246 +{
1247 + /* If we're using the old ipOS ABI we need to make D10 through D13
1248 + caller-clobbered. */
1249 + if (TARGET_IPOS_ABI)
1250 + {
1251 + call_used_regs[D10_REGNUM] = 1;
1252 + call_used_regs[D11_REGNUM] = 1;
1253 + call_used_regs[D12_REGNUM] = 1;
1254 + call_used_regs[D13_REGNUM] = 1;
1255 + }
1256 +}
1257 +
1258 +/* We have some number of optimizations that don't really work for the Ubicom32
1259 + architecture so we deal with them here. */
1260 +
1261 +void
1262 +ubicom32_optimization_options (int level ATTRIBUTE_UNUSED,
1263 + int size ATTRIBUTE_UNUSED)
1264 +{
1265 + /* The tree IVOPTs pass seems to do really bad things for the Ubicom32
1266 + architecture - it tends to turn things that would happily use pre/post
1267 + increment/decrement into operations involving unecessary loop
1268 + indicies. */
1269 + flag_ivopts = 0;
1270 +
1271 + /* We have problems where DSE at the RTL level misses partial stores
1272 + to the stack. For now we disable it to avoid this. */
1273 + flag_dse = 0;
1274 +}
1275 +
1276 +/* Print operand X using operand code CODE to assembly language output file
1277 + FILE. */
1278 +
1279 +void
1280 +ubicom32_print_operand (FILE *file, rtx x, int code)
1281 +{
1282 + switch (code)
1283 + {
1284 + case 'A':
1285 + /* Identify the correct accumulator to use. */
1286 + if (REGNO (x) == ACC0_HI_REGNUM || REGNO (x) == ACC0_LO_REGNUM)
1287 + fprintf (file, "acc0");
1288 + else if (REGNO (x) == ACC1_HI_REGNUM || REGNO (x) == ACC1_LO_REGNUM)
1289 + fprintf (file, "acc1");
1290 + else
1291 + abort ();
1292 + break;
1293 +
1294 + case 'b':
1295 + case 'B':
1296 + {
1297 + enum machine_mode mode;
1298 +
1299 + mode = GET_MODE (XEXP (x, 0));
1300 +
1301 + /* These are normal and reversed branches. */
1302 + switch (code == 'b' ? GET_CODE (x) : reverse_condition (GET_CODE (x)))
1303 + {
1304 + case NE:
1305 + fprintf (file, "ne");
1306 + break;
1307 +
1308 + case EQ:
1309 + fprintf (file, "eq");
1310 + break;
1311 +
1312 + case GE:
1313 + if (mode == CCSZNmode || mode == CCWZNmode)
1314 + fprintf (file, "pl");
1315 + else
1316 + fprintf (file, "ge");
1317 + break;
1318 +
1319 + case GT:
1320 + fprintf (file, "gt");
1321 + break;
1322 +
1323 + case LE:
1324 + fprintf (file, "le");
1325 + break;
1326 +
1327 + case LT:
1328 + if (mode == CCSZNmode || mode == CCWZNmode)
1329 + fprintf (file, "mi");
1330 + else
1331 + fprintf (file, "lt");
1332 + break;
1333 +
1334 + case GEU:
1335 + fprintf (file, "cs");
1336 + break;
1337 +
1338 + case GTU:
1339 + fprintf (file, "hi");
1340 + break;
1341 +
1342 + case LEU:
1343 + fprintf (file, "ls");
1344 + break;
1345 +
1346 + case LTU:
1347 + fprintf (file, "cc");
1348 + break;
1349 +
1350 + default:
1351 + abort ();
1352 + }
1353 + }
1354 + break;
1355 +
1356 + case 'C':
1357 + /* This is used for the operand to a call instruction;
1358 + if it's a REG, enclose it in parens, else output
1359 + the operand normally. */
1360 + if (REG_P (x))
1361 + {
1362 + fputc ('(', file);
1363 + ubicom32_print_operand (file, x, 0);
1364 + fputc (')', file);
1365 + }
1366 + else
1367 + ubicom32_print_operand (file, x, 0);
1368 + break;
1369 +
1370 + case 'd':
1371 + /* Bit operations we need bit numbers. */
1372 + fprintf (file, "%d", exact_log2 (INTVAL (x)));
1373 + break;
1374 +
1375 + case 'D':
1376 + /* Bit operations we need bit numbers. */
1377 + fprintf (file, "%d", exact_log2 (~ INTVAL (x)));
1378 + break;
1379 +
1380 + case 'E':
1381 + /* For lea, which we use to add address registers.
1382 + We don't want the '#' on a constant. */
1383 + if (CONST_INT_P (x))
1384 + {
1385 + fprintf (file, "%ld", INTVAL (x));
1386 + break;
1387 + }
1388 + /* FALL THROUGH */
1389 +
1390 + default:
1391 + switch (GET_CODE (x))
1392 + {
1393 + case MEM:
1394 + output_memory_reference_mode = GET_MODE (x);
1395 + output_address (XEXP (x, 0));
1396 + break;
1397 +
1398 + case PLUS:
1399 + output_address (x);
1400 + break;
1401 +
1402 + case REG:
1403 + fprintf (file, "%s", reg_names[REGNO (x)]);
1404 + break;
1405 +
1406 + case SUBREG:
1407 + fprintf (file, "%s", reg_names[subreg_regno (x)]);
1408 + break;
1409 +
1410 + /* This will only be single precision.... */
1411 + case CONST_DOUBLE:
1412 + {
1413 + unsigned long val;
1414 + REAL_VALUE_TYPE rv;
1415 +
1416 + REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1417 + REAL_VALUE_TO_TARGET_SINGLE (rv, val);
1418 + fprintf (file, "0x%lx", val);
1419 + break;
1420 + }
1421 +
1422 + case CONST_INT:
1423 + case SYMBOL_REF:
1424 + case CONST:
1425 + case LABEL_REF:
1426 + case CODE_LABEL:
1427 + case LO_SUM:
1428 + ubicom32_print_operand_address (file, x);
1429 + break;
1430 +
1431 + case HIGH:
1432 + fprintf (file, "#%%hi(");
1433 + ubicom32_print_operand_address (file, XEXP (x, 0));
1434 + fprintf (file, ")");
1435 + break;
1436 +
1437 + case UNSPEC:
1438 + switch (XINT (x, 1))
1439 + {
1440 + case UNSPEC_FDPIC_GOT:
1441 + fprintf (file, "#%%got_lo(");
1442 + ubicom32_print_operand_address (file, XVECEXP (x, 0, 0));
1443 + fprintf (file, ")");
1444 + break;
1445 +
1446 + case UNSPEC_FDPIC_GOT_FUNCDESC:
1447 + fprintf (file, "#%%got_funcdesc_lo(");
1448 + ubicom32_print_operand_address (file, XVECEXP (x, 0, 0));
1449 + fprintf (file, ")");
1450 + break;
1451 +
1452 + default:
1453 + abort ();
1454 + }
1455 + break;
1456 +
1457 + default:
1458 + abort ();
1459 + }
1460 + break;
1461 + }
1462 +}
1463 +
1464 +/* Output assembly language output for the address ADDR to FILE. */
1465 +
1466 +void
1467 +ubicom32_print_operand_address (FILE *file, rtx addr)
1468 +{
1469 + switch (GET_CODE (addr))
1470 + {
1471 + case POST_INC:
1472 + ubicom32_print_operand_address (file, XEXP (addr, 0));
1473 + fprintf (file, "%d++", GET_MODE_SIZE (output_memory_reference_mode));
1474 + break;
1475 +
1476 + case PRE_INC:
1477 + fprintf (file, "%d", GET_MODE_SIZE (output_memory_reference_mode));
1478 + ubicom32_print_operand_address (file, XEXP (addr, 0));
1479 + fprintf (file, "++");
1480 + break;
1481 +
1482 + case POST_DEC:
1483 + ubicom32_print_operand_address (file, XEXP (addr, 0));
1484 + fprintf (file, "%d++", -GET_MODE_SIZE (output_memory_reference_mode));
1485 + break;
1486 +
1487 + case PRE_DEC:
1488 + fprintf (file, "%d", -GET_MODE_SIZE (output_memory_reference_mode));
1489 + ubicom32_print_operand_address (file, XEXP (addr, 0));
1490 + fprintf (file, "++");
1491 + break;
1492 +
1493 + case POST_MODIFY:
1494 + ubicom32_print_operand_address (file, XEXP (addr, 0));
1495 + fprintf (file, "%ld++", INTVAL (XEXP (XEXP (addr,1), 1)));
1496 + break;
1497 +
1498 + case PRE_MODIFY:
1499 + fprintf (file, "%ld", INTVAL (XEXP (XEXP (addr,1), 1)));
1500 + ubicom32_print_operand_address (file, XEXP (addr, 0));
1501 + fprintf (file, "++");
1502 + break;
1503 +
1504 + case REG:
1505 + fputc ('(', file);
1506 + fprintf (file, "%s", reg_names[REGNO (addr)]);
1507 + fputc (')', file);
1508 + break;
1509 +
1510 + case PLUS:
1511 + {
1512 + rtx base = XEXP (addr, 0);
1513 + rtx index = XEXP (addr, 1);
1514 +
1515 + /* Switch around addresses of the form index * scaling + base. */
1516 + if (! ubicom32_is_base_reg (base, 1))
1517 + {
1518 + rtx tmp = base;
1519 + base = index;
1520 + index = tmp;
1521 + }
1522 +
1523 + if (CONST_INT_P (index))
1524 + {
1525 + fprintf (file, "%ld", INTVAL (index));
1526 + fputc ('(', file);
1527 + fputs (reg_names[REGNO (base)], file);
1528 + }
1529 + else if (GET_CODE (index) == MULT
1530 + || REG_P (index))
1531 + {
1532 + if (GET_CODE (index) == MULT)
1533 + index = XEXP (index, 0);
1534 + fputc ('(', file);
1535 + fputs (reg_names[REGNO (base)], file);
1536 + fputc (',', file);
1537 + fputs (reg_names[REGNO (index)], file);
1538 + }
1539 + else
1540 + abort ();
1541 +
1542 + fputc (')', file);
1543 + break;
1544 + }
1545 +
1546 + case LO_SUM:
1547 + fprintf (file, "%%lo(");
1548 + ubicom32_print_operand (file, XEXP (addr, 1), 'L');
1549 + fprintf (file, ")(");
1550 + ubicom32_print_operand (file, XEXP (addr, 0), 0);
1551 + fprintf (file, ")");
1552 + break;
1553 +
1554 + case CONST_INT:
1555 + fputc ('#', file);
1556 + output_addr_const (file, addr);
1557 + break;
1558 +
1559 + default:
1560 + output_addr_const (file, addr);
1561 + break;
1562 + }
1563 +}
1564 +
1565 +/* X and Y are two things to compare using CODE. Emit the compare insn and
1566 + return the rtx for the cc reg in the proper mode. */
1567 +
1568 +rtx
1569 +ubicom32_gen_compare_reg (enum rtx_code code, rtx x, rtx y)
1570 +{
1571 + enum machine_mode mode = SELECT_CC_MODE (code, x, y);
1572 + rtx cc_reg;
1573 +
1574 + cc_reg = gen_rtx_REG (mode, CC_REGNUM);
1575 +
1576 + emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
1577 + gen_rtx_COMPARE (mode, x, y)));
1578 +
1579 + return cc_reg;
1580 +}
1581 +
1582 +/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
1583 + return the mode to be used for the comparison. */
1584 +
1585 +enum machine_mode
1586 +ubicom32_select_cc_mode (enum rtx_code op, rtx x, rtx y)
1587 +{
1588 + /* Is this a short compare? */
1589 + if (GET_MODE (x) == QImode
1590 + || GET_MODE (x) == HImode
1591 + || GET_MODE (y) == QImode
1592 + || GET_MODE (y) == HImode)
1593 + {
1594 + switch (op)
1595 + {
1596 + case EQ :
1597 + case NE :
1598 + return CCSZmode;
1599 +
1600 + case GE:
1601 + case LT:
1602 + if (y == const0_rtx)
1603 + return CCSZNmode;
1604 +
1605 + default :
1606 + return CCSmode;
1607 + }
1608 + }
1609 +
1610 + /* We have a word compare. */
1611 + switch (op)
1612 + {
1613 + case EQ :
1614 + case NE :
1615 + return CCWZmode;
1616 +
1617 + case GE :
1618 + case LT :
1619 + if (y == const0_rtx)
1620 + return CCWZNmode;
1621 +
1622 + default :
1623 + return CCWmode;
1624 + }
1625 +}
1626 +
1627 +/* Return TRUE or FALSE depending on whether the first SET in INSN
1628 + has source and destination with matching CC modes, and that the
1629 + CC mode is at least as constrained as REQ_MODE. */
1630 +bool
1631 +ubicom32_match_cc_mode (rtx insn, enum machine_mode req_mode)
1632 +{
1633 + rtx set;
1634 + enum machine_mode set_mode;
1635 +
1636 + set = PATTERN (insn);
1637 + if (GET_CODE (set) == PARALLEL)
1638 + set = XVECEXP (set, 0, 0);
1639 + gcc_assert (GET_CODE (set) == SET);
1640 + gcc_assert (GET_CODE (SET_SRC (set)) == COMPARE);
1641 +
1642 + /* SET_MODE is the mode we have in the instruction. This must either
1643 + be the same or less restrictive that the required mode REQ_MODE. */
1644 + set_mode = GET_MODE (SET_DEST (set));
1645 +
1646 + switch (req_mode)
1647 + {
1648 + case CCSZmode:
1649 + if (set_mode != CCSZmode)
1650 + return 0;
1651 + break;
1652 +
1653 + case CCSZNmode:
1654 + if (set_mode != CCSZmode
1655 + && set_mode != CCSZNmode)
1656 + return 0;
1657 + break;
1658 +
1659 + case CCSmode:
1660 + if (set_mode != CCSmode
1661 + && set_mode != CCSZmode
1662 + && set_mode != CCSZNmode)
1663 + return 0;
1664 + break;
1665 +
1666 + case CCWZmode:
1667 + if (set_mode != CCWZmode)
1668 + return 0;
1669 + break;
1670 +
1671 + case CCWZNmode:
1672 + if (set_mode != CCWZmode
1673 + && set_mode != CCWZNmode)
1674 + return 0;
1675 + break;
1676 +
1677 + case CCWmode:
1678 + if (set_mode != CCWmode
1679 + && set_mode != CCWZmode
1680 + && set_mode != CCWZNmode)
1681 + return 0;
1682 + break;
1683 +
1684 + default:
1685 + gcc_unreachable ();
1686 + }
1687 +
1688 + return (GET_MODE (SET_SRC (set)) == set_mode);
1689 +}
1690 +
1691 +/* Replace the comparison OP0 CODE OP1 by a semantically equivalent one
1692 + that we can implement more efficiently. */
1693 +
1694 +void
1695 +ubicom32_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1)
1696 +{
1697 + /* If we have a REG and a MEM then compare the MEM with the REG and not
1698 + the other way round. */
1699 + if (REG_P (*op0) && MEM_P (*op1))
1700 + {
1701 + rtx tem = *op0;
1702 + *op0 = *op1;
1703 + *op1 = tem;
1704 + *code = swap_condition (*code);
1705 + return;
1706 + }
1707 +
1708 + /* If we have a REG and a CONST_INT then we may want to reverse things
1709 + if the constant can be represented as an "I" constraint. */
1710 + if (REG_P (*op0) && CONST_INT_P (*op1) && satisfies_constraint_I (*op1))
1711 + {
1712 + rtx tem = *op0;
1713 + *op0 = *op1;
1714 + *op1 = tem;
1715 + *code = swap_condition (*code);
1716 + return;
1717 + }
1718 +}
1719 +
1720 +/* Return the fixed registers used for condition codes. */
1721 +
1722 +static bool
1723 +ubicom32_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
1724 +{
1725 + *p1 = CC_REGNUM;
1726 + *p2 = INVALID_REGNUM;
1727 +
1728 + return true;
1729 +}
1730 +
1731 +/* If two condition code modes are compatible, return a condition code
1732 + mode which is compatible with both. Otherwise, return
1733 + VOIDmode. */
1734 +
1735 +static enum machine_mode
1736 +ubicom32_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
1737 +{
1738 + if (m1 == m2)
1739 + return m1;
1740 +
1741 + if (GET_MODE_CLASS (m1) != MODE_CC || GET_MODE_CLASS (m2) != MODE_CC)
1742 + return VOIDmode;
1743 +
1744 + switch (m1)
1745 + {
1746 + case CCWmode:
1747 + if (m2 == CCWZNmode || m2 == CCWZmode)
1748 + return m1;
1749 +
1750 + return VOIDmode;
1751 +
1752 + case CCWZNmode:
1753 + if (m2 == CCWmode)
1754 + return m2;
1755 +
1756 + if (m2 == CCWZmode)
1757 + return m1;
1758 +
1759 + return VOIDmode;
1760 +
1761 + case CCWZmode:
1762 + if (m2 == CCWmode || m2 == CCWZNmode)
1763 + return m2;
1764 +
1765 + return VOIDmode;
1766 +
1767 + case CCSmode:
1768 + if (m2 == CCSZNmode || m2 == CCSZmode)
1769 + return m1;
1770 +
1771 + return VOIDmode;
1772 +
1773 + case CCSZNmode:
1774 + if (m2 == CCSmode)
1775 + return m2;
1776 +
1777 + if (m2 == CCSZmode)
1778 + return m1;
1779 +
1780 + return VOIDmode;
1781 +
1782 + case CCSZmode:
1783 + if (m2 == CCSmode || m2 == CCSZNmode)
1784 + return m2;
1785 +
1786 + return VOIDmode;
1787 +
1788 + default:
1789 + gcc_unreachable ();
1790 + }
1791 +}
1792 +
1793 +static rtx
1794 +ubicom32_legitimize_fdpic_address_symbol (rtx orig, rtx reg, rtx fdpic_reg)
1795 +{
1796 + int unspec;
1797 + rtx got_offs;
1798 + rtx got_offs_scaled;
1799 + rtx plus_scaled;
1800 + rtx tmp;
1801 + rtx new_rtx;
1802 +
1803 + gcc_assert (reg != 0);
1804 +
1805 + if (GET_CODE (orig) == SYMBOL_REF
1806 + && SYMBOL_REF_FUNCTION_P (orig))
1807 + unspec = UNSPEC_FDPIC_GOT_FUNCDESC;
1808 + else
1809 + unspec = UNSPEC_FDPIC_GOT;
1810 +
1811 + got_offs = gen_reg_rtx (SImode);
1812 + tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, orig), unspec);
1813 + emit_move_insn (got_offs, tmp);
1814 +
1815 + got_offs_scaled = gen_rtx_MULT (SImode, got_offs, GEN_INT (4));
1816 + plus_scaled = gen_rtx_PLUS (Pmode, fdpic_reg, got_offs_scaled);
1817 + new_rtx = gen_const_mem (Pmode, plus_scaled);
1818 + emit_move_insn (reg, new_rtx);
1819 +
1820 + return reg;
1821 +}
1822 +
1823 +static rtx
1824 +ubicom32_legitimize_fdpic_address (rtx orig, rtx reg, rtx fdpic_reg)
1825 +{
1826 + rtx addr = orig;
1827 + rtx new_rtx = orig;
1828 +
1829 + if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
1830 + {
1831 + rtx base;
1832 +
1833 + if (GET_CODE (addr) == CONST)
1834 + {
1835 + addr = XEXP (addr, 0);
1836 + gcc_assert (GET_CODE (addr) == PLUS);
1837 + }
1838 +
1839 + base = ubicom32_legitimize_fdpic_address_symbol (XEXP (addr, 0), reg, fdpic_reg);
1840 + return gen_rtx_PLUS (Pmode, base, XEXP (addr, 1));
1841 + }
1842 +
1843 + return new_rtx;
1844 +}
1845 +
1846 +/* Code generation. */
1847 +
1848 +void
1849 +ubicom32_expand_movsi (rtx *operands)
1850 +{
1851 + if (GET_CODE (operands[1]) == SYMBOL_REF
1852 + || (GET_CODE (operands[1]) == CONST
1853 + && GET_CODE (XEXP (operands[1], 0)) == PLUS
1854 + && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF)
1855 + || CONSTANT_ADDRESS_P (operands[1]))
1856 + {
1857 + if (TARGET_FDPIC)
1858 + {
1859 + rtx tmp;
1860 + rtx fdpic_reg;
1861 +
1862 + gcc_assert (can_create_pseudo_p ());
1863 + tmp = gen_reg_rtx (Pmode);
1864 + fdpic_reg = get_hard_reg_initial_val (SImode, FDPIC_REGNUM);
1865 + if (GET_CODE (operands[1]) == SYMBOL_REF
1866 + || GET_CODE (operands[1]) == LABEL_REF)
1867 + operands[1] = ubicom32_legitimize_fdpic_address_symbol (operands[1], tmp, fdpic_reg);
1868 + else
1869 + operands[1] = ubicom32_legitimize_fdpic_address (operands[1], tmp, fdpic_reg);
1870 + }
1871 + else
1872 + {
1873 + rtx tmp;
1874 + enum machine_mode mode;
1875 +
1876 + /* We want to avoid reusing operand 0 if we can because it limits
1877 + our ability to optimize later. */
1878 + tmp = ! can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
1879 +
1880 + mode = GET_MODE (operands[0]);
1881 + emit_insn (gen_rtx_SET (VOIDmode, tmp,
1882 + gen_rtx_HIGH (mode, operands[1])));
1883 + operands[1] = gen_rtx_LO_SUM (mode, tmp, operands[1]);
1884 + if (can_create_pseudo_p() && ! REG_P (operands[0]))
1885 + {
1886 + tmp = gen_reg_rtx (mode);
1887 + emit_insn (gen_rtx_SET (VOIDmode, tmp, operands[1]));
1888 + operands[1] = tmp;
1889 + }
1890 + }
1891 + }
1892 +}
1893 +
1894 +/* Emit code for addsi3. */
1895 +
1896 +void
1897 +ubicom32_expand_addsi3 (rtx *operands)
1898 +{
1899 + rtx op, clob;
1900 +
1901 + if (can_create_pseudo_p ())
1902 + {
1903 + /* If we have a non-data reg for operand 1 then prefer that over
1904 + a CONST_INT in operand 2. */
1905 + if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
1906 + && CONST_INT_P (operands[2]))
1907 + operands[2] = copy_to_mode_reg (SImode, operands[2]);
1908 +
1909 + if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
1910 + operands[2] = copy_to_mode_reg (SImode, operands[2]);
1911 + }
1912 +
1913 + /* Emit the instruction. */
1914 +
1915 + op = gen_rtx_SET (VOIDmode, operands[0],
1916 + gen_rtx_PLUS (SImode, operands[1], operands[2]));
1917 +
1918 + if (! can_create_pseudo_p ())
1919 + {
1920 + /* Reload doesn't know about the flags register, and doesn't know that
1921 + it doesn't want to clobber it. We can only do this with PLUS. */
1922 + emit_insn (op);
1923 + }
1924 + else
1925 + {
1926 + clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM));
1927 + emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
1928 + }
1929 +}
1930 +
1931 +/* Emit code for mulsi3. Return 1 if we have generated all the code
1932 + necessary to do the multiplication. */
1933 +
1934 +int
1935 +ubicom32_emit_mult_sequence (rtx *operands)
1936 +{
1937 + if (! ubicom32_v4)
1938 + {
1939 + rtx a1, a1_1, a2;
1940 + rtx b1, b1_1, b2;
1941 + rtx mac_lo_rtx;
1942 + rtx t1, t2, t3;
1943 +
1944 + /* Give up if we cannot create new pseudos. */
1945 + if (!can_create_pseudo_p())
1946 + return 0;
1947 +
1948 + /* Synthesize 32-bit multiplication using 16-bit operations:
1949 +
1950 + a1 = highpart (a)
1951 + a2 = lowpart (a)
1952 +
1953 + b1 = highpart (b)
1954 + b2 = lowpart (b)
1955 +
1956 + c = (a1 * b1) << 32 + (a1 * b2) << 16 + (a2 * b1) << 16 + a2 * b2
1957 + = 0 + (a1 * b2) << 16 + (a2 * b1) << 16 + a2 * b2
1958 + ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^^^^
1959 + Signed Signed Unsigned */
1960 +
1961 + if (!ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])))
1962 + {
1963 + rtx op1;
1964 +
1965 + op1 = gen_reg_rtx (SImode);
1966 + emit_move_insn (op1, operands[1]);
1967 + operands[1] = op1;
1968 + }
1969 +
1970 + if (!ubicom32_data_register_operand (operands[2], GET_MODE (operands[2])))
1971 + {
1972 + rtx op2;
1973 +
1974 + op2 = gen_reg_rtx (SImode);
1975 + emit_move_insn (op2, operands[2]);
1976 + operands[2] = op2;
1977 + }
1978 +
1979 + /* a1 = highpart (a) */
1980 + a1 = gen_reg_rtx (HImode);
1981 + a1_1 = gen_reg_rtx (SImode);
1982 + emit_insn (gen_ashrsi3 (a1_1, operands[1], GEN_INT (16)));
1983 + emit_move_insn (a1, gen_lowpart (HImode, a1_1));
1984 +
1985 + /* a2 = lowpart (a) */
1986 + a2 = gen_reg_rtx (HImode);
1987 + emit_move_insn (a2, gen_lowpart (HImode, operands[1]));
1988 +
1989 + /* b1 = highpart (b) */
1990 + b1 = gen_reg_rtx (HImode);
1991 + b1_1 = gen_reg_rtx (SImode);
1992 + emit_insn (gen_ashrsi3 (b1_1, operands[2], GEN_INT (16)));
1993 + emit_move_insn (b1, gen_lowpart (HImode, b1_1));
1994 +
1995 + /* b2 = lowpart (b) */
1996 + b2 = gen_reg_rtx (HImode);
1997 + emit_move_insn (b2, gen_lowpart (HImode, operands[2]));
1998 +
1999 + /* t1 = (a1 * b2) << 16 */
2000 + t1 = gen_reg_rtx (SImode);
2001 + mac_lo_rtx = gen_rtx_REG (SImode, ACC0_LO_REGNUM);
2002 + emit_insn (gen_mulhisi3 (mac_lo_rtx, a1, b2));
2003 + emit_insn (gen_ashlsi3 (t1, mac_lo_rtx, GEN_INT (16)));
2004 +
2005 + /* t2 = (a2 * b1) << 16 */
2006 + t2 = gen_reg_rtx (SImode);
2007 + emit_insn (gen_mulhisi3 (mac_lo_rtx, a2, b1));
2008 + emit_insn (gen_ashlsi3 (t2, mac_lo_rtx, GEN_INT (16)));
2009 +
2010 + /* mac_lo = a2 * b2 */
2011 + emit_insn (gen_umulhisi3 (mac_lo_rtx, a2, b2));
2012 +
2013 + /* t3 = t1 + t2 */
2014 + t3 = gen_reg_rtx (SImode);
2015 + emit_insn (gen_addsi3 (t3, t1, t2));
2016 +
2017 + /* c = t3 + mac_lo_rtx */
2018 + emit_insn (gen_addsi3 (operands[0], mac_lo_rtx, t3));
2019 +
2020 + return 1;
2021 + }
2022 + else
2023 + {
2024 + rtx acc_rtx;
2025 +
2026 + /* Give up if we cannot create new pseudos. */
2027 + if (!can_create_pseudo_p())
2028 + return 0;
2029 +
2030 + if (!ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])))
2031 + {
2032 + rtx op1;
2033 +
2034 + op1 = gen_reg_rtx (SImode);
2035 + emit_move_insn (op1, operands[1]);
2036 + operands[1] = op1;
2037 + }
2038 +
2039 + if (!ubicom32_data_register_operand (operands[2], GET_MODE (operands[2])))
2040 + {
2041 + rtx op2;
2042 +
2043 + op2 = gen_reg_rtx (SImode);
2044 + emit_move_insn (op2, operands[2]);
2045 + operands[2] = op2;
2046 + }
2047 +
2048 + acc_rtx = gen_reg_rtx (DImode);
2049 + emit_insn (gen_umulsidi3 (acc_rtx, operands[1], operands[2]));
2050 + emit_move_insn (operands[0], gen_lowpart (SImode, acc_rtx));
2051 +
2052 + return 1;
2053 + }
2054 +}
2055 +
2056 +/* Move the integer value VAL into OPERANDS[0]. */
2057 +
2058 +void
2059 +ubicom32_emit_move_const_int (rtx dest, rtx imm)
2060 +{
2061 + rtx xoperands[2];
2062 +
2063 + xoperands[0] = dest;
2064 + xoperands[1] = imm;
2065 +
2066 + /* Treat mem destinations separately. Values must be explicitly sign
2067 + extended. */
2068 + if (MEM_P (dest))
2069 + {
2070 + rtx low_hword_mem;
2071 + rtx low_hword_addr;
2072 +
2073 + /* Emit shorter sequence for signed 7-bit quantities. */
2074 + if (satisfies_constraint_I (imm))
2075 + {
2076 + output_asm_insn ("move.4\t%0, %1", xoperands);
2077 + return;
2078 + }
2079 +
2080 + /* Special case for pushing constants. */
2081 + if (GET_CODE (XEXP (dest, 0)) == PRE_DEC
2082 + && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx)
2083 + {
2084 + output_asm_insn ("movei\t-4(sp)++, #%%hi(%E1)", xoperands);
2085 + output_asm_insn ("movei\t2(sp), #%%lo(%E1)", xoperands);
2086 + return;
2087 + }
2088 +
2089 + /* See if we can add 2 to the original address. This is only
2090 + possible if the original address is of the form REG or
2091 + REG+const. */
2092 + low_hword_addr = plus_constant (XEXP (dest, 0), 2);
2093 + if (ubicom32_legitimate_address_p (HImode, low_hword_addr, 1))
2094 + {
2095 + low_hword_mem = gen_rtx_MEM (HImode, low_hword_addr);
2096 + MEM_COPY_ATTRIBUTES (low_hword_mem, dest);
2097 + output_asm_insn ("movei\t%0, #%%hi(%E1)", xoperands);
2098 + xoperands[0] = low_hword_mem;
2099 + output_asm_insn ("movei\t%0, #%%lo(%E1)", xoperands);
2100 + return;
2101 + }
2102 +
2103 + /* The original address is too complex. We need to use a
2104 + scratch memory by (sp) and move that to the original
2105 + destination. */
2106 + if (! reg_mentioned_p (stack_pointer_rtx, dest))
2107 + {
2108 + output_asm_insn ("movei\t-4(sp)++, #%%hi(%E1)", xoperands);
2109 + output_asm_insn ("movei\t2(sp), #%%lo(%E1)", xoperands);
2110 + output_asm_insn ("move.4\t%0, (sp)4++", xoperands);
2111 + return;
2112 + }
2113 +
2114 + /* Our address mentions the stack pointer so we need to
2115 + use our scratch data register here as well as scratch
2116 + memory. */
2117 + output_asm_insn ("movei\t-4(sp)++, #%%hi(%E1)", xoperands);
2118 + output_asm_insn ("movei\t2(sp), #%%lo(%E1)", xoperands);
2119 + output_asm_insn ("move.4\td15, (sp)4++", xoperands);
2120 + output_asm_insn ("move.4\t%0, d15", xoperands);
2121 + return;
2122 + }
2123 +
2124 + /* Move into registers are zero extended by default. */
2125 + if (! REG_P (dest))
2126 + abort ();
2127 +
2128 + if (satisfies_constraint_N (imm))
2129 + {
2130 + output_asm_insn ("movei\t%0, %1", xoperands);
2131 + return;
2132 + }
2133 +
2134 + if (INTVAL (xoperands[1]) >= 0xff80
2135 + && INTVAL (xoperands[1]) < 0x10000)
2136 + {
2137 + xoperands[1] = GEN_INT (INTVAL (xoperands[1]) - 0x10000);
2138 + output_asm_insn ("move.2\t%0, %1", xoperands);
2139 + return;
2140 + }
2141 +
2142 + if ((REGNO_REG_CLASS (REGNO (xoperands[0])) == ADDRESS_REGS
2143 + || REGNO_REG_CLASS (REGNO (xoperands[0])) == FDPIC_REG)
2144 + && ((INTVAL (xoperands[1]) & 0x80000000) == 0))
2145 + {
2146 + output_asm_insn ("moveai\t%0, #%%hi(%E1)", xoperands);
2147 + if ((INTVAL (xoperands[1]) & 0x7f) != 0)
2148 + output_asm_insn ("lea.1\t%0, %%lo(%E1)(%0)", xoperands);
2149 + return;
2150 + }
2151 +
2152 + if ((INTVAL (xoperands[1]) & 0xffff0000) == 0)
2153 + {
2154 + output_asm_insn ("movei\t%0, #%%lo(%E1)", xoperands);
2155 + output_asm_insn ("move.2\t%0, %0", xoperands);
2156 + return;
2157 + }
2158 +
2159 + /* This is very expensive. The constant is so large that we
2160 + need to use the stack to do the load. */
2161 + output_asm_insn ("movei\t-4(sp)++, #%%hi(%E1)", xoperands);
2162 + output_asm_insn ("movei\t2(sp), #%%lo(%E1)", xoperands);
2163 + output_asm_insn ("move.4\t%0, (sp)4++", xoperands);
2164 +}
2165 +
2166 +/* Stack layout. Prologue/Epilogue. */
2167 +
2168 +static int save_regs_size;
2169 +
2170 +static void
2171 +ubicom32_layout_frame (void)
2172 +{
2173 + int regno;
2174 +
2175 + memset ((char *) &save_regs[0], 0, sizeof (save_regs));
2176 + nregs = 0;
2177 + frame_size = get_frame_size ();
2178 +
2179 + if (frame_pointer_needed || df_regs_ever_live_p (FRAME_POINTER_REGNUM))
2180 + {
2181 + save_regs[FRAME_POINTER_REGNUM] = 1;
2182 + ++nregs;
2183 + }
2184 +
2185 + if (current_function_is_leaf && ! df_regs_ever_live_p (LINK_REGNO))
2186 + ubicom32_can_use_calli_to_ret = 1;
2187 + else
2188 + {
2189 + ubicom32_can_use_calli_to_ret = 0;
2190 + save_regs[LINK_REGNO] = 1;
2191 + ++nregs;
2192 + }
2193 +
2194 + /* Figure out which register(s) needs to be saved. */
2195 + for (regno = 0; regno <= LAST_ADDRESS_REGNUM; regno++)
2196 + if (df_regs_ever_live_p(regno)
2197 + && ! call_used_regs[regno]
2198 + && ! fixed_regs[regno]
2199 + && ! save_regs[regno])
2200 + {
2201 + save_regs[regno] = 1;
2202 + ++nregs;
2203 + }
2204 +
2205 + save_regs_size = 4 * nregs;
2206 +}
2207 +
2208 +static void
2209 +ubicom32_emit_add_movsi (int regno, int adj)
2210 +{
2211 + rtx x;
2212 + rtx reg = gen_rtx_REG (SImode, regno);
2213 +
2214 + adj += 4;
2215 + if (adj > 8 * 4)
2216 + {
2217 + x = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
2218 + GEN_INT (-adj)));
2219 + RTX_FRAME_RELATED_P (x) = 1;
2220 + x = emit_move_insn (gen_rtx_MEM (SImode, stack_pointer_rtx), reg);
2221 + }
2222 + else
2223 + {
2224 + rtx addr = gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx,
2225 + gen_rtx_PLUS (Pmode, stack_pointer_rtx,
2226 + GEN_INT (-adj)));
2227 + x = emit_move_insn (gen_rtx_MEM (SImode, addr), reg);
2228 + }
2229 + RTX_FRAME_RELATED_P (x) = 1;
2230 +}
2231 +
2232 +void
2233 +ubicom32_expand_prologue (void)
2234 +{
2235 + rtx x;
2236 + int regno;
2237 + int outgoing_args_size = crtl->outgoing_args_size;
2238 + int adj;
2239 +
2240 + if (ubicom32_naked_function_p ())
2241 + return;
2242 +
2243 + ubicom32_builtin_saveregs ();
2244 +
2245 + ubicom32_layout_frame ();
2246 + adj = (outgoing_args_size + get_frame_size () + save_regs_size
2247 + + crtl->args.pretend_args_size);
2248 +
2249 + if (!adj)
2250 + ;
2251 + else if (outgoing_args_size + save_regs_size < 508
2252 + && get_frame_size () + save_regs_size > 508)
2253 + {
2254 + int i = 0;
2255 + x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
2256 + GEN_INT (-adj));
2257 + x = emit_insn (x);
2258 + RTX_FRAME_RELATED_P (x) = 1;
2259 +
2260 + for (regno = LAST_ADDRESS_REGNUM; regno >= 0; --regno)
2261 + if (save_regs[regno] && regno != LINK_REGNO)
2262 + {
2263 + x = gen_rtx_MEM (SImode,
2264 + gen_rtx_PLUS (Pmode,
2265 + stack_pointer_rtx,
2266 + GEN_INT (i * 4 + outgoing_args_size)));
2267 + x = emit_move_insn (x, gen_rtx_REG (SImode, regno));
2268 + RTX_FRAME_RELATED_P (x) = 1;
2269 + ++i;
2270 + }
2271 + if (save_regs[LINK_REGNO])
2272 + {
2273 + x = gen_rtx_MEM (SImode,
2274 + gen_rtx_PLUS (Pmode,
2275 + stack_pointer_rtx,
2276 + GEN_INT (i * 4 + outgoing_args_size)));
2277 + x = emit_move_insn (x, gen_rtx_REG (SImode, LINK_REGNO));
2278 + RTX_FRAME_RELATED_P (x) = 1;
2279 + }
2280 + }
2281 + else
2282 + {
2283 + int regno;
2284 + int adj = get_frame_size () + crtl->args.pretend_args_size;
2285 + int i = 0;
2286 +
2287 + if (save_regs[LINK_REGNO])
2288 + {
2289 + ubicom32_emit_add_movsi (LINK_REGNO, adj);
2290 + ++i;
2291 + }
2292 +
2293 + for (regno = 0; regno <= LAST_ADDRESS_REGNUM; ++regno)
2294 + if (save_regs[regno] && regno != LINK_REGNO)
2295 + {
2296 + if (i)
2297 + {
2298 + rtx mem = gen_rtx_MEM (SImode,
2299 + gen_rtx_PRE_DEC (Pmode,
2300 + stack_pointer_rtx));
2301 + x = emit_move_insn (mem, gen_rtx_REG (SImode, regno));
2302 + RTX_FRAME_RELATED_P (x) = 1;
2303 + }
2304 + else
2305 + ubicom32_emit_add_movsi (regno, adj);
2306 + ++i;
2307 + }
2308 +
2309 + if (outgoing_args_size || (!i && adj))
2310 + {
2311 + x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
2312 + GEN_INT (-outgoing_args_size - (i ? 0 : adj)));
2313 + x = emit_insn (x);
2314 + RTX_FRAME_RELATED_P (x) = 1;
2315 + }
2316 + }
2317 +
2318 + if (frame_pointer_needed)
2319 + {
2320 + int fp_adj = save_regs_size + outgoing_args_size;
2321 + x = gen_addsi3 (frame_pointer_rtx, stack_pointer_rtx,
2322 + GEN_INT (fp_adj));
2323 + x = emit_insn (x);
2324 + RTX_FRAME_RELATED_P (x) = 1;
2325 + }
2326 +}
2327 +
2328 +void
2329 +ubicom32_expand_epilogue (void)
2330 +{
2331 + rtx x;
2332 + int regno;
2333 + int outgoing_args_size = crtl->outgoing_args_size;
2334 + int adj;
2335 + int i;
2336 +
2337 + if (ubicom32_naked_function_p ())
2338 + {
2339 + emit_jump_insn (gen_return_internal (gen_rtx_REG (SImode,
2340 + LINK_REGNO)));
2341 + return;
2342 + }
2343 +
2344 + if (cfun->calls_alloca)
2345 + {
2346 + x = gen_addsi3 (stack_pointer_rtx, frame_pointer_rtx,
2347 + GEN_INT (-save_regs_size));
2348 + emit_insn (x);
2349 + outgoing_args_size = 0;
2350 + }
2351 +
2352 + if (outgoing_args_size)
2353 + {
2354 + x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
2355 + GEN_INT (outgoing_args_size));
2356 + emit_insn (x);
2357 + }
2358 +
2359 + i = 0;
2360 + for (regno = LAST_ADDRESS_REGNUM; regno >= 0; --regno)
2361 + if (save_regs[regno] && regno != LINK_REGNO)
2362 + {
2363 + x = gen_rtx_MEM (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
2364 + emit_move_insn (gen_rtx_REG (SImode, regno), x);
2365 + ++i;
2366 + }
2367 +
2368 + /* Do we have to adjust the stack after we've finished restoring regs? */
2369 + adj = get_frame_size() + crtl->args.pretend_args_size;
2370 + if (cfun->stdarg)
2371 + adj += UBICOM32_FUNCTION_ARG_REGS * UNITS_PER_WORD;
2372 +
2373 +#if 0
2374 + if (crtl->calls_eh_return && 0)
2375 + {
2376 + if (save_regs[LINK_REGNO])
2377 + {
2378 + x = gen_rtx_MEM (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
2379 + emit_move_insn (gen_rtx_REG (SImode, LINK_REGNO), x);
2380 + }
2381 +
2382 + if (adj)
2383 + {
2384 + x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
2385 + GEN_INT (adj));
2386 + x = emit_insn (x);
2387 + }
2388 +
2389 + /* Perform the additional bump for __throw. */
2390 + emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
2391 + EH_RETURN_STACKADJ_RTX));
2392 + emit_jump_insn (gen_eh_return_internal ());
2393 + return;
2394 + }
2395 +#endif
2396 +
2397 + if (save_regs[LINK_REGNO])
2398 + {
2399 + if (adj >= 4 && adj <= (6 * 4))
2400 + {
2401 + x = GEN_INT (adj + 4);
2402 + emit_jump_insn (gen_return_from_post_modify_sp (x));
2403 + return;
2404 + }
2405 +
2406 + if (adj == 0)
2407 + {
2408 + x = gen_rtx_MEM (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
2409 + emit_jump_insn (gen_return_internal (x));
2410 + return;
2411 + }
2412 +
2413 + x = gen_rtx_MEM (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
2414 + emit_move_insn (gen_rtx_REG (SImode, LINK_REGNO), x);
2415 + }
2416 +
2417 + if (adj)
2418 + {
2419 + x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
2420 + GEN_INT (adj));
2421 + x = emit_insn (x);
2422 + adj = 0;
2423 + }
2424 +
2425 + /* Given that we've just done all the hard work here we may as well use
2426 + a calli to return. */
2427 + ubicom32_can_use_calli_to_ret = 1;
2428 + emit_jump_insn (gen_return_internal (gen_rtx_REG (SImode, LINK_REGNO)));
2429 +}
2430 +
2431 +void
2432 +ubicom32_expand_call_fdpic (rtx *operands)
2433 +{
2434 + rtx c;
2435 + rtx addr;
2436 + rtx fdpic_reg = get_hard_reg_initial_val (SImode, FDPIC_REGNUM);
2437 +
2438 + addr = XEXP (operands[0], 0);
2439 +
2440 + c = gen_call_fdpic (addr, operands[1], fdpic_reg);
2441 + emit_call_insn (c);
2442 +}
2443 +
2444 +void
2445 +ubicom32_expand_call_value_fdpic (rtx *operands)
2446 +{
2447 + rtx c;
2448 + rtx addr;
2449 + rtx fdpic_reg = get_hard_reg_initial_val (SImode, FDPIC_REGNUM);
2450 +
2451 + addr = XEXP (operands[1], 0);
2452 +
2453 + c = gen_call_value_fdpic (operands[0], addr, operands[2], fdpic_reg);
2454 + emit_call_insn (c);
2455 +}
2456 +
2457 +void
2458 +ubicom32_expand_eh_return (rtx *operands)
2459 +{
2460 + if (REG_P (operands[0])
2461 + || REGNO (operands[0]) != EH_RETURN_STACKADJ_REGNO)
2462 + {
2463 + rtx sp = EH_RETURN_STACKADJ_RTX;
2464 + emit_move_insn (sp, operands[0]);
2465 + operands[0] = sp;
2466 + }
2467 +
2468 + if (REG_P (operands[1])
2469 + || REGNO (operands[1]) != EH_RETURN_HANDLER_REGNO)
2470 + {
2471 + rtx ra = EH_RETURN_HANDLER_RTX;
2472 + emit_move_insn (ra, operands[1]);
2473 + operands[1] = ra;
2474 + }
2475 +}
2476 +
2477 +/* Compute the offsets between eliminable registers. */
2478 +
2479 +int
2480 +ubicom32_initial_elimination_offset (int from, int to)
2481 +{
2482 + ubicom32_layout_frame ();
2483 + if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
2484 + return save_regs_size + crtl->outgoing_args_size;
2485 +
2486 + if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
2487 + return get_frame_size ()/* + save_regs_size */;
2488 +
2489 + if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
2490 + return get_frame_size ()
2491 + + crtl->outgoing_args_size
2492 + + save_regs_size;
2493 +
2494 + return 0;
2495 +}
2496 +
2497 +/* Return 1 if it is appropriate to emit `ret' instructions in the
2498 + body of a function. Do this only if the epilogue is simple, needing a
2499 + couple of insns. Prior to reloading, we can't tell how many registers
2500 + must be saved, so return 0 then. Return 0 if there is no frame
2501 + marker to de-allocate.
2502 +
2503 + If NON_SAVING_SETJMP is defined and true, then it is not possible
2504 + for the epilogue to be simple, so return 0. This is a special case
2505 + since NON_SAVING_SETJMP will not cause regs_ever_live to change
2506 + until final, but jump_optimize may need to know sooner if a
2507 + `return' is OK. */
2508 +
2509 +int
2510 +ubicom32_can_use_return_insn_p (void)
2511 +{
2512 + if (! reload_completed || frame_pointer_needed)
2513 + return 0;
2514 +
2515 + return 1;
2516 +}
2517 +
2518 +/* Attributes and CC handling. */
2519 +
2520 +/* Handle an attribute requiring a FUNCTION_DECL; arguments as in
2521 + struct attribute_spec.handler. */
2522 +static tree
2523 +ubicom32_handle_fndecl_attribute (tree *node, tree name,
2524 + tree args ATTRIBUTE_UNUSED,
2525 + int flags ATTRIBUTE_UNUSED,
2526 + bool *no_add_attrs)
2527 +{
2528 + if (TREE_CODE (*node) != FUNCTION_DECL)
2529 + {
2530 + warning ("'%s' attribute only applies to functions",
2531 + IDENTIFIER_POINTER (name));
2532 + *no_add_attrs = true;
2533 + }
2534 +
2535 + return NULL_TREE;
2536 +}
2537 +
2538 +/* A C expression that places additional restrictions on the register class to
2539 + use when it is necessary to copy value X into a register in class CLASS.
2540 + The value is a register class; perhaps CLASS, or perhaps another, smaller
2541 + class. On many machines, the following definition is safe:
2542 +
2543 + #define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS
2544 +
2545 + Sometimes returning a more restrictive class makes better code. For
2546 + example, on the 68000, when X is an integer constant that is in range for a
2547 + `moveq' instruction, the value of this macro is always `DATA_REGS' as long
2548 + as CLASS includes the data registers. Requiring a data register guarantees
2549 + that a `moveq' will be used.
2550 +
2551 + If X is a `const_double', by returning `NO_REGS' you can force X into a
2552 + memory constant. This is useful on certain machines where immediate
2553 + floating values cannot be loaded into certain kinds of registers. */
2554 +
2555 +enum reg_class
2556 +ubicom32_preferred_reload_class (rtx x, enum reg_class class)
2557 +{
2558 + /* If a symbolic constant, HIGH or a PLUS is reloaded,
2559 + it is most likely being used as an address, so
2560 + prefer ADDRESS_REGS. If 'class' is not a superset
2561 + of ADDRESS_REGS, e.g. DATA_REGS, then reject this reload. */
2562 + if (GET_CODE (x) == PLUS
2563 + || GET_CODE (x) == HIGH
2564 + || GET_CODE (x) == LABEL_REF
2565 + || GET_CODE (x) == SYMBOL_REF
2566 + || GET_CODE (x) == CONST)
2567 + {
2568 + if (reg_class_subset_p (ALL_ADDRESS_REGS, class))
2569 + return ALL_ADDRESS_REGS;
2570 +
2571 + return NO_REGS;
2572 + }
2573 +
2574 + return class;
2575 +}
2576 +
2577 +/* Function arguments and varargs. */
2578 +
2579 +int
2580 +ubicom32_reg_parm_stack_space (tree fndecl)
2581 +{
2582 + return 0;
2583 +
2584 + if (fndecl
2585 + && TYPE_ARG_TYPES (TREE_TYPE (fndecl)) != 0
2586 + && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (fndecl))))
2587 + != void_type_node))
2588 + return UBICOM32_FUNCTION_ARG_REGS * UNITS_PER_WORD;
2589 +
2590 + return 0;
2591 +}
2592 +
2593 +/* Flush the argument registers to the stack for a stdarg function;
2594 + return the new argument pointer. */
2595 +
2596 +rtx
2597 +ubicom32_builtin_saveregs (void)
2598 +{
2599 + int regno;
2600 +
2601 + if (! cfun->stdarg)
2602 + return 0;
2603 +
2604 + for (regno = UBICOM32_FUNCTION_ARG_REGS - 1; regno >= 0; --regno)
2605 + emit_move_insn (gen_rtx_MEM (SImode,
2606 + gen_rtx_PRE_DEC (SImode,
2607 + stack_pointer_rtx)),
2608 + gen_rtx_REG (SImode, regno));
2609 +
2610 + return stack_pointer_rtx;
2611 +}
2612 +
2613 +void
2614 +ubicom32_va_start (tree valist, rtx nextarg)
2615 +{
2616 + std_expand_builtin_va_start (valist, nextarg);
2617 +}
2618 +
2619 +rtx
2620 +ubicom32_va_arg (tree valist, tree type)
2621 +{
2622 + HOST_WIDE_INT size, rsize;
2623 + tree addr, incr, tmp;
2624 + rtx addr_rtx;
2625 + int indirect = 0;
2626 +
2627 + /* Round up sizeof(type) to a word. */
2628 + size = int_size_in_bytes (type);
2629 + rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
2630 +
2631 + /* Large types are passed by reference. */
2632 + if (size > 8)
2633 + {
2634 + indirect = 1;
2635 + size = rsize = UNITS_PER_WORD;
2636 + }
2637 +
2638 + incr = valist;
2639 + addr = incr = save_expr (incr);
2640 +
2641 + /* FIXME Nat's version - is it correct? */
2642 + tmp = fold_convert (ptr_type_node, size_int (rsize));
2643 + tmp = build2 (PLUS_EXPR, ptr_type_node, incr, tmp);
2644 + incr = fold (tmp);
2645 +
2646 + /* FIXME Nat's version - is it correct? */
2647 + incr = build2 (MODIFY_EXPR, ptr_type_node, valist, incr);
2648 +
2649 + TREE_SIDE_EFFECTS (incr) = 1;
2650 + expand_expr (incr, const0_rtx, VOIDmode, EXPAND_NORMAL);
2651 +
2652 + addr_rtx = expand_expr (addr, NULL, Pmode, EXPAND_NORMAL);
2653 +
2654 + if (size < UNITS_PER_WORD)
2655 + emit_insn (gen_addsi3 (addr_rtx, addr_rtx,
2656 + GEN_INT (UNITS_PER_WORD - size)));
2657 +
2658 + if (indirect)
2659 + {
2660 + addr_rtx = force_reg (Pmode, addr_rtx);
2661 + addr_rtx = gen_rtx_MEM (Pmode, addr_rtx);
2662 + set_mem_alias_set (addr_rtx, get_varargs_alias_set ());
2663 + }
2664 +
2665 + return addr_rtx;
2666 +}
2667 +
2668 +void
2669 +init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
2670 + int indirect ATTRIBUTE_UNUSED)
2671 +{
2672 + cum->nbytes = 0;
2673 +
2674 + if (!libname)
2675 + {
2676 + cum->stdarg = (TYPE_ARG_TYPES (fntype) != 0
2677 + && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2678 + != void_type_node));
2679 + }
2680 +}
2681 +
2682 +/* Return an RTX to represent where a value in mode MODE will be passed
2683 + to a function. If the result is 0, the argument will be pushed. */
2684 +
2685 +rtx
2686 +function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
2687 + int named ATTRIBUTE_UNUSED)
2688 +{
2689 + rtx result = 0;
2690 + int size, align;
2691 + int nregs = UBICOM32_FUNCTION_ARG_REGS;
2692 +
2693 + /* Figure out the size of the object to be passed. */
2694 + if (mode == BLKmode)
2695 + size = int_size_in_bytes (type);
2696 + else
2697 + size = GET_MODE_SIZE (mode);
2698 +
2699 + /* Figure out the alignment of the object to be passed. */
2700 + align = size;
2701 +
2702 + cum->nbytes = (cum->nbytes + 3) & ~3;
2703 +
2704 + /* Don't pass this arg via a register if all the argument registers
2705 + are used up. */
2706 + if (cum->nbytes >= nregs * UNITS_PER_WORD)
2707 + return 0;
2708 +
2709 + /* Don't pass this arg via a register if it would be split between
2710 + registers and memory. */
2711 + result = gen_rtx_REG (mode, cum->nbytes / UNITS_PER_WORD);
2712 +
2713 + return result;
2714 +}
2715 +
2716 +rtx
2717 +function_incoming_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
2718 + int named ATTRIBUTE_UNUSED)
2719 +{
2720 + if (cfun->stdarg)
2721 + return 0;
2722 +
2723 + return function_arg (cum, mode, type, named);
2724 +}
2725 +
2726 +
2727 +/* Implement hook TARGET_ARG_PARTIAL_BYTES.
2728 +
2729 + Returns the number of bytes at the beginning of an argument that
2730 + must be put in registers. The value must be zero for arguments
2731 + that are passed entirely in registers or that are entirely pushed
2732 + on the stack. */
2733 +static int
2734 +ubicom32_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
2735 + tree type, bool named ATTRIBUTE_UNUSED)
2736 +{
2737 + int size, diff;
2738 +
2739 + int nregs = UBICOM32_FUNCTION_ARG_REGS;
2740 +
2741 + /* round up to full word */
2742 + cum->nbytes = (cum->nbytes + 3) & ~3;
2743 +
2744 + if (targetm.calls.pass_by_reference (cum, mode, type, named))
2745 + return 0;
2746 +
2747 + /* number of bytes left in registers */
2748 + diff = nregs*UNITS_PER_WORD - cum->nbytes;
2749 +
2750 + /* regs all used up */
2751 + if (diff <= 0)
2752 + return 0;
2753 +
2754 + /* Figure out the size of the object to be passed. */
2755 + if (mode == BLKmode)
2756 + size = int_size_in_bytes (type);
2757 + else
2758 + size = GET_MODE_SIZE (mode);
2759 +
2760 + /* enough space left in regs for size */
2761 + if (size <= diff)
2762 + return 0;
2763 +
2764 + /* put diff bytes in regs and rest on stack */
2765 + return diff;
2766 +
2767 +}
2768 +
2769 +static bool
2770 +ubicom32_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
2771 + enum machine_mode mode, const_tree type,
2772 + bool named ATTRIBUTE_UNUSED)
2773 +{
2774 + int size;
2775 +
2776 + if (type)
2777 + size = int_size_in_bytes (type);
2778 + else
2779 + size = GET_MODE_SIZE (mode);
2780 +
2781 + return size <= 0 || size > 8;
2782 +}
2783 +
2784 +static bool
2785 +ubicom32_callee_copies (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
2786 + enum machine_mode mode, const_tree type,
2787 + bool named ATTRIBUTE_UNUSED)
2788 +{
2789 + int size;
2790 +
2791 + if (type)
2792 + size = int_size_in_bytes (type);
2793 + else
2794 + size = GET_MODE_SIZE (mode);
2795 +
2796 + return size <= 0 || size > 8;
2797 +}
2798 +
2799 +static bool
2800 +ubicom32_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
2801 +{
2802 + int size, mode;
2803 +
2804 + if (!type)
2805 + return true;
2806 +
2807 + size = int_size_in_bytes(type);
2808 + if (size > 8)
2809 + return true;
2810 +
2811 + mode = TYPE_MODE(type);
2812 + if (mode == BLKmode)
2813 + return true;
2814 +
2815 + return false;
2816 +}
2817 +
2818 +/* Return true if a given register number REGNO is acceptable for machine
2819 + mode MODE. */
2820 +bool
2821 +ubicom32_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
2822 +{
2823 + /* If we're not at least a v3 ISA then ACC0_HI is only 16 bits. */
2824 + if (! ubicom32_v3)
2825 + {
2826 + if (regno == ACC0_HI_REGNUM)
2827 + return (mode == QImode || mode == HImode);
2828 + }
2829 +
2830 + /* Only the flags reg can hold CCmode. */
2831 + if (GET_MODE_CLASS (mode) == MODE_CC)
2832 + return regno == CC_REGNUM;
2833 +
2834 + /* We restrict the choice of DImode registers to only being address,
2835 + data or accumulator regs. We also restrict them to only start on
2836 + even register numbers so we never have to worry about partial
2837 + overlaps between operands in instructions. */
2838 + if (GET_MODE_SIZE (mode) > 4)
2839 + {
2840 + switch (REGNO_REG_CLASS (regno))
2841 + {
2842 + case ADDRESS_REGS:
2843 + case DATA_REGS:
2844 + case ACC_REGS:
2845 + return (regno & 1) == 0;
2846 +
2847 + default:
2848 + return false;
2849 + }
2850 + }
2851 +
2852 + return true;
2853 +}
2854 +
2855 +/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
2856 + and check its validity for a certain class.
2857 + We have two alternate definitions for each of them.
2858 + The usual definition accepts all pseudo regs; the other rejects
2859 + them unless they have been allocated suitable hard regs.
2860 + The symbol REG_OK_STRICT causes the latter definition to be used.
2861 +
2862 + Most source files want to accept pseudo regs in the hope that
2863 + they will get allocated to the class that the insn wants them to be in.
2864 + Source files for reload pass need to be strict.
2865 + After reload, it makes no difference, since pseudo regs have
2866 + been eliminated by then.
2867 +
2868 + These assume that REGNO is a hard or pseudo reg number.
2869 + They give nonzero only if REGNO is a hard reg of the suitable class
2870 + or a pseudo reg currently allocated to a suitable hard reg.
2871 + Since they use reg_renumber, they are safe only once reg_renumber
2872 + has been allocated, which happens in local-alloc.c. */
2873 +
2874 +int
2875 +ubicom32_regno_ok_for_base_p (int regno, int strict)
2876 +{
2877 + if ((regno >= FIRST_ADDRESS_REGNUM && regno <= STACK_POINTER_REGNUM)
2878 + || (!strict
2879 + && (regno >= FIRST_PSEUDO_REGISTER
2880 + || regno == ARG_POINTER_REGNUM))
2881 + || (strict && (reg_renumber
2882 + && reg_renumber[regno] >= FIRST_ADDRESS_REGNUM
2883 + && reg_renumber[regno] <= STACK_POINTER_REGNUM)))
2884 + return 1;
2885 +
2886 + return 0;
2887 +}
2888 +
2889 +int
2890 +ubicom32_regno_ok_for_index_p (int regno, int strict)
2891 +{
2892 + if ((regno >= FIRST_DATA_REGNUM && regno <= LAST_DATA_REGNUM)
2893 + || (!strict && regno >= FIRST_PSEUDO_REGISTER)
2894 + || (strict && (reg_renumber
2895 + && reg_renumber[regno] >= FIRST_DATA_REGNUM
2896 + && reg_renumber[regno] <= LAST_DATA_REGNUM)))
2897 + return 1;
2898 +
2899 + return 0;
2900 +}
2901 +
2902 +/* Returns 1 if X is a valid index register. STRICT is 1 if only hard
2903 + registers should be accepted. Accept either REG or SUBREG where a
2904 + register is valid. */
2905 +
2906 +static bool
2907 +ubicom32_is_index_reg (rtx x, int strict)
2908 +{
2909 + if ((REG_P (x) && ubicom32_regno_ok_for_index_p (REGNO (x), strict))
2910 + || (GET_CODE (x) == SUBREG && REG_P (SUBREG_REG (x))
2911 + && ubicom32_regno_ok_for_index_p (REGNO (SUBREG_REG (x)), strict)))
2912 + return true;
2913 +
2914 + return false;
2915 +}
2916 +
2917 +/* Return 1 if X is a valid index for a memory address. */
2918 +
2919 +static bool
2920 +ubicom32_is_index_expr (enum machine_mode mode, rtx x, int strict)
2921 +{
2922 + /* Immediate index must be an unsigned 7-bit offset multiple of 1, 2
2923 + or 4 depending on mode. */
2924 + if (CONST_INT_P (x))
2925 + {
2926 + switch (mode)
2927 + {
2928 + case QImode:
2929 + return satisfies_constraint_J (x);
2930 +
2931 + case HImode:
2932 + return satisfies_constraint_K (x);
2933 +
2934 + case SImode:
2935 + case SFmode:
2936 + return satisfies_constraint_L (x);
2937 +
2938 + case DImode:
2939 + return satisfies_constraint_L (x)
2940 + && satisfies_constraint_L (GEN_INT (INTVAL (x) + 4));
2941 +
2942 + default:
2943 + return false;
2944 + }
2945 + }
2946 +
2947 + if (mode != SImode && mode != HImode && mode != QImode)
2948 + return false;
2949 +
2950 + /* Register index scaled by mode of operand: REG + REG * modesize.
2951 + Valid scaled index registers are:
2952 +
2953 + SImode (mult (dreg) 4))
2954 + HImode (mult (dreg) 2))
2955 + QImode (mult (dreg) 1)) */
2956 + if (GET_CODE (x) == MULT
2957 + && ubicom32_is_index_reg (XEXP (x, 0), strict)
2958 + && CONST_INT_P (XEXP (x, 1))
2959 + && INTVAL (XEXP (x, 1)) == (HOST_WIDE_INT)GET_MODE_SIZE (mode))
2960 + return true;
2961 +
2962 + /* REG + REG addressing is allowed for QImode. */
2963 + if (ubicom32_is_index_reg (x, strict) && mode == QImode)
2964 + return true;
2965 +
2966 + return false;
2967 +}
2968 +
2969 +static bool
2970 +ubicom32_is_valid_offset (enum machine_mode mode, HOST_WIDE_INT offs)
2971 +{
2972 + if (offs < 0)
2973 + return false;
2974 +
2975 + switch (mode)
2976 + {
2977 + case QImode:
2978 + return offs <= 127;
2979 +
2980 + case HImode:
2981 + return offs <= 254;
2982 +
2983 + case SImode:
2984 + case SFmode:
2985 + return offs <= 508;
2986 +
2987 + case DImode:
2988 + return offs <= 504;
2989 +
2990 + default:
2991 + return false;
2992 + }
2993 +}
2994 +
2995 +static int
2996 +ubicom32_get_valid_offset_mask (enum machine_mode mode)
2997 +{
2998 + switch (mode)
2999 + {
3000 + case QImode:
3001 + return 127;
3002 +
3003 + case HImode:
3004 + return 255;
3005 +
3006 + case SImode:
3007 + case SFmode:
3008 + return 511;
3009 +
3010 + case DImode:
3011 + return 255;
3012 +
3013 + default:
3014 + return 0;
3015 + }
3016 +}
3017 +
3018 +/* Returns 1 if X is a valid base register. STRICT is 1 if only hard
3019 + registers should be accepted. Accept either REG or SUBREG where a
3020 + register is valid. */
3021 +
3022 +static bool
3023 +ubicom32_is_base_reg (rtx x, int strict)
3024 +{
3025 + if ((REG_P (x) && ubicom32_regno_ok_for_base_p (REGNO (x), strict))
3026 + || (GET_CODE (x) == SUBREG && REG_P (SUBREG_REG (x))
3027 + && ubicom32_regno_ok_for_base_p (REGNO (SUBREG_REG (x)), strict)))
3028 + return true;
3029 +
3030 + return false;
3031 +}
3032 +
3033 +static bool
3034 +ubicom32_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
3035 +{
3036 + return TARGET_FDPIC;
3037 +}
3038 +
3039 +/* Determine if X is a legitimate constant. */
3040 +
3041 +bool
3042 +ubicom32_legitimate_constant_p (rtx x)
3043 +{
3044 + /* Among its other duties, LEGITIMATE_CONSTANT_P decides whether
3045 + a constant can be entered into reg_equiv_constant[]. If we return true,
3046 + reload can create new instances of the constant whenever it likes.
3047 +
3048 + The idea is therefore to accept as many constants as possible (to give
3049 + reload more freedom) while rejecting constants that can only be created
3050 + at certain times. In particular, anything with a symbolic component will
3051 + require use of the pseudo FDPIC register, which is only available before
3052 + reload. */
3053 + if (TARGET_FDPIC)
3054 + {
3055 + if (GET_CODE (x) == SYMBOL_REF
3056 + || (GET_CODE (x) == CONST
3057 + && GET_CODE (XEXP (x, 0)) == PLUS
3058 + && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)
3059 + || CONSTANT_ADDRESS_P (x))
3060 + return false;
3061 +
3062 + return true;
3063 + }
3064 +
3065 + /* For non-PIC code anything goes! */
3066 + return true;
3067 +}
3068 +
3069 +/* Address validation. */
3070 +
3071 +bool
3072 +ubicom32_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
3073 +{
3074 + if (TARGET_DEBUG_ADDRESS)
3075 + {
3076 + fprintf (stderr, "\n==> GO_IF_LEGITIMATE_ADDRESS%s\n",
3077 + (strict) ? " (STRICT)" : "");
3078 + debug_rtx (x);
3079 + }
3080 +
3081 + if (CONSTANT_ADDRESS_P (x))
3082 + return false;
3083 +
3084 + if (ubicom32_is_base_reg (x, strict))
3085 + return true;
3086 +
3087 + if ((GET_CODE (x) == POST_INC
3088 + || GET_CODE (x) == PRE_INC
3089 + || GET_CODE (x) == POST_DEC
3090 + || GET_CODE (x) == PRE_DEC)
3091 + && REG_P (XEXP (x, 0))
3092 + && ubicom32_is_base_reg (XEXP (x, 0), strict)
3093 + && mode != DImode)
3094 + return true;
3095 +
3096 + if ((GET_CODE (x) == PRE_MODIFY || GET_CODE (x) == POST_MODIFY)
3097 + && ubicom32_is_base_reg (XEXP (x, 0), strict)
3098 + && GET_CODE (XEXP (x, 1)) == PLUS
3099 + && rtx_equal_p (XEXP (x, 0), XEXP (XEXP (x, 1), 0))
3100 + && CONST_INT_P (XEXP (XEXP (x, 1), 1))
3101 + && mode != DImode)
3102 + {
3103 + HOST_WIDE_INT disp = INTVAL (XEXP (XEXP (x, 1), 1));
3104 + switch (mode)
3105 + {
3106 + case QImode:
3107 + return disp >= -8 && disp <= 7;
3108 +
3109 + case HImode:
3110 + return disp >= -16 && disp <= 14 && ! (disp & 1);
3111 +
3112 + case SImode:
3113 + return disp >= -32 && disp <= 28 && ! (disp & 3);
3114 +
3115 + default:
3116 + return false;
3117 + }
3118 + }
3119 +
3120 + /* Accept base + index * scale. */
3121 + if (GET_CODE (x) == PLUS
3122 + && ubicom32_is_base_reg (XEXP (x, 0), strict)
3123 + && ubicom32_is_index_expr (mode, XEXP (x, 1), strict))
3124 + return true;
3125 +
3126 + /* Accept index * scale + base. */
3127 + if (GET_CODE (x) == PLUS
3128 + && ubicom32_is_base_reg (XEXP (x, 1), strict)
3129 + && ubicom32_is_index_expr (mode, XEXP (x, 0), strict))
3130 + return true;
3131 +
3132 + if (! TARGET_FDPIC)
3133 + {
3134 + /* Accept (lo_sum (reg) (symbol_ref)) that can be used as a mem+7bits
3135 + displacement operand:
3136 +
3137 + moveai a1, #%hi(SYM)
3138 + move.4 d3, %lo(SYM)(a1) */
3139 + if (GET_CODE (x) == LO_SUM
3140 + && ubicom32_is_base_reg (XEXP (x, 0), strict)
3141 + && (GET_CODE (XEXP (x, 1)) == SYMBOL_REF
3142 + || GET_CODE (XEXP (x, 1)) == LABEL_REF /* FIXME: wrong */)
3143 + && mode != DImode)
3144 + return true;
3145 + }
3146 +
3147 + if (TARGET_DEBUG_ADDRESS)
3148 + fprintf (stderr, "\nNot a legitimate address.\n");
3149 +
3150 + return false;
3151 +}
3152 +
3153 +rtx
3154 +ubicom32_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
3155 + enum machine_mode mode)
3156 +{
3157 + if (mode == BLKmode)
3158 + return NULL_RTX;
3159 +
3160 + if (GET_CODE (x) == PLUS
3161 + && REG_P (XEXP (x, 0))
3162 + && ! REGNO_PTR_FRAME_P (REGNO (XEXP (x, 0)))
3163 + && CONST_INT_P (XEXP (x, 1))
3164 + && ! ubicom32_is_valid_offset (mode, INTVAL (XEXP (x, 1))))
3165 + {
3166 + rtx base;
3167 + rtx plus;
3168 + rtx new_rtx;
3169 + HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
3170 + HOST_WIDE_INT low = val & ubicom32_get_valid_offset_mask (mode);
3171 + HOST_WIDE_INT high = val ^ low;
3172 +
3173 + if (val < 0)
3174 + return NULL_RTX;
3175 +
3176 + if (! low)
3177 + return NULL_RTX;
3178 +
3179 + /* Reload the high part into a base reg; leave the low part
3180 + in the mem directly. */
3181 + base = XEXP (x, 0);
3182 + if (! ubicom32_is_base_reg (base, 0))
3183 + base = copy_to_mode_reg (Pmode, base);
3184 +
3185 + plus = expand_simple_binop (Pmode, PLUS,
3186 + gen_int_mode (high, Pmode),
3187 + base, NULL, 0, OPTAB_WIDEN);
3188 + new_rtx = plus_constant (plus, low);
3189 +
3190 + return new_rtx;
3191 + }
3192 +
3193 + return NULL_RTX;
3194 +}
3195 +
3196 +/* Try a machine-dependent way of reloading an illegitimate address AD
3197 + operand. If we find one, push the reload and and return the new address.
3198 +
3199 + MODE is the mode of the enclosing MEM. OPNUM is the operand number
3200 + and TYPE is the reload type of the current reload. */
3201 +
3202 +rtx
3203 +ubicom32_legitimize_reload_address (rtx ad, enum machine_mode mode,
3204 + int opnum, int type)
3205 +{
3206 + /* Is this an address that we've already fixed up? If it is then
3207 + recognize it and move on. */
3208 + if (GET_CODE (ad) == PLUS
3209 + && GET_CODE (XEXP (ad, 0)) == PLUS
3210 + && REG_P (XEXP (XEXP (ad, 0), 0))
3211 + && CONST_INT_P (XEXP (XEXP (ad, 0), 1))
3212 + && CONST_INT_P (XEXP (ad, 1)))
3213 + {
3214 + push_reload (XEXP (ad, 0), NULL_RTX, &XEXP (ad, 0), NULL,
3215 + BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
3216 + opnum, (enum reload_type) type);
3217 + return ad;
3218 + }
3219 +
3220 + /* Have we got an address where the offset is simply out of range? If
3221 + yes then reload the range as a high part and smaller offset. */
3222 + if (GET_CODE (ad) == PLUS
3223 + && REG_P (XEXP (ad, 0))
3224 + && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
3225 + && REGNO_OK_FOR_BASE_P (REGNO (XEXP (ad, 0)))
3226 + && CONST_INT_P (XEXP (ad, 1))
3227 + && ! ubicom32_is_valid_offset (mode, INTVAL (XEXP (ad, 1))))
3228 + {
3229 + rtx temp;
3230 + rtx new_rtx;
3231 +
3232 + HOST_WIDE_INT val = INTVAL (XEXP (ad, 1));
3233 + HOST_WIDE_INT low = val & ubicom32_get_valid_offset_mask (mode);
3234 + HOST_WIDE_INT high = val ^ low;
3235 +
3236 + /* Reload the high part into a base reg; leave the low part
3237 + in the mem directly. */
3238 + temp = gen_rtx_PLUS (Pmode, XEXP (ad, 0), GEN_INT (high));
3239 + new_rtx = gen_rtx_PLUS (Pmode, temp, GEN_INT (low));
3240 +
3241 + push_reload (XEXP (new_rtx, 0), NULL_RTX, &XEXP (new_rtx, 0), NULL,
3242 + BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
3243 + opnum, (enum reload_type) type);
3244 + return new_rtx;
3245 + }
3246 +
3247 + /* If we're presented with an pre/post inc/dec then we must force this
3248 + to be done in an address register. The register allocator should
3249 + work this out for itself but at times ends up trying to use the wrong
3250 + class. If we get the wrong class then reload will end up generating
3251 + at least 3 instructions whereas this way we can hopefully keep it to
3252 + just 2. */
3253 + if ((GET_CODE (ad) == POST_INC
3254 + || GET_CODE (ad) == PRE_INC
3255 + || GET_CODE (ad) == POST_DEC
3256 + || GET_CODE (ad) == PRE_DEC)
3257 + && REG_P (XEXP (ad, 0))
3258 + && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
3259 + && ! REGNO_OK_FOR_BASE_P (REGNO (XEXP (ad, 0))))
3260 + {
3261 + push_reload (XEXP (ad, 0), XEXP (ad, 0), &XEXP (ad, 0), &XEXP (ad, 0),
3262 + BASE_REG_CLASS, GET_MODE (XEXP (ad, 0)), GET_MODE (XEXP (ad, 0)), 0, 0,
3263 + opnum, RELOAD_OTHER);
3264 + return ad;
3265 + }
3266 +
3267 + return NULL_RTX;
3268 +}
3269 +
3270 +/* Compute a (partial) cost for rtx X. Return true if the complete
3271 + cost has been computed, and false if subexpressions should be
3272 + scanned. In either case, *TOTAL contains the cost result. */
3273 +
3274 +static bool
3275 +ubicom32_rtx_costs (rtx x, int code, int outer_code, int *total,
3276 + bool speed ATTRIBUTE_UNUSED)
3277 +{
3278 + enum machine_mode mode = GET_MODE (x);
3279 +
3280 + switch (code)
3281 + {
3282 + case CONST_INT:
3283 + /* Very short constants often fold into instructions so
3284 + we pretend that they don't cost anything! This is
3285 + really important as regards zero values as otherwise
3286 + the compiler has a nasty habit of wanting to reuse
3287 + zeroes that are in regs but that tends to pessimize
3288 + the code. */
3289 + if (satisfies_constraint_I (x))
3290 + {
3291 + *total = 0;
3292 + return true;
3293 + }
3294 +
3295 + /* Bit clearing costs nothing */
3296 + if (outer_code == AND
3297 + && exact_log2 (~INTVAL (x)) != -1)
3298 + {
3299 + *total = 0;
3300 + return true;
3301 + }
3302 +
3303 + /* Masking the lower set of bits costs nothing. */
3304 + if (outer_code == AND
3305 + && exact_log2 (INTVAL (x) + 1) != -1)
3306 + {
3307 + *total = 0;
3308 + return true;
3309 + }
3310 +
3311 + /* Bit setting costs nothing. */
3312 + if (outer_code == IOR
3313 + && exact_log2 (INTVAL (x)) != -1)
3314 + {
3315 + *total = 0;
3316 + return true;
3317 + }
3318 +
3319 + /* Larger constants that can be loaded via movei aren't too
3320 + bad. If we're just doing a set they cost nothing extra. */
3321 + if (satisfies_constraint_N (x))
3322 + {
3323 + if (mode == DImode)
3324 + *total = COSTS_N_INSNS (2);
3325 + else
3326 + *total = COSTS_N_INSNS (1);
3327 + return true;
3328 + }
3329 +
3330 + if (mode == DImode)
3331 + *total = COSTS_N_INSNS (5);
3332 + else
3333 + *total = COSTS_N_INSNS (3);
3334 + return true;
3335 +
3336 + case CONST_DOUBLE:
3337 + /* We don't optimize CONST_DOUBLEs well nor do we relax them well,
3338 + so their cost is very high. */
3339 + *total = COSTS_N_INSNS (6);
3340 + return true;
3341 +
3342 + case CONST:
3343 + case SYMBOL_REF:
3344 + case MEM:
3345 + *total = 0;
3346 + return true;
3347 +
3348 + case IF_THEN_ELSE:
3349 + *total = COSTS_N_INSNS (1);
3350 + return true;
3351 +
3352 + case LABEL_REF:
3353 + case HIGH:
3354 + case LO_SUM:
3355 + case BSWAP:
3356 + case PLUS:
3357 + case MINUS:
3358 + case AND:
3359 + case IOR:
3360 + case XOR:
3361 + case ASHIFT:
3362 + case ASHIFTRT:
3363 + case LSHIFTRT:
3364 + case NEG:
3365 + case NOT:
3366 + case SIGN_EXTEND:
3367 + case ZERO_EXTEND:
3368 + case ZERO_EXTRACT:
3369 + if (outer_code == SET)
3370 + {
3371 + if (mode == DImode)
3372 + *total = COSTS_N_INSNS (2);
3373 + else
3374 + *total = COSTS_N_INSNS (1);
3375 + }
3376 + return true;
3377 +
3378 + case COMPARE:
3379 + if (outer_code == SET)
3380 + {
3381 + if (GET_MODE (XEXP (x, 0)) == DImode
3382 + || GET_MODE (XEXP (x, 1)) == DImode)
3383 + *total = COSTS_N_INSNS (2);
3384 + else
3385 + *total = COSTS_N_INSNS (1);
3386 + }
3387 + return true;
3388 +
3389 + case UMOD:
3390 + case UDIV:
3391 + case MOD:
3392 + case DIV:
3393 + if (outer_code == SET)
3394 + {
3395 + if (mode == DImode)
3396 + *total = COSTS_N_INSNS (600);
3397 + else
3398 + *total = COSTS_N_INSNS (200);
3399 + }
3400 + return true;
3401 +
3402 + case MULT:
3403 + if (outer_code == SET)
3404 + {
3405 + if (! ubicom32_v4)
3406 + {
3407 + if (mode == DImode)
3408 + *total = COSTS_N_INSNS (15);
3409 + else
3410 + *total = COSTS_N_INSNS (5);
3411 + }
3412 + else
3413 + {
3414 + if (mode == DImode)
3415 + *total = COSTS_N_INSNS (6);
3416 + else
3417 + *total = COSTS_N_INSNS (2);
3418 + }
3419 + }
3420 + return true;
3421 +
3422 + case UNSPEC:
3423 + if (XINT (x, 1) == UNSPEC_FDPIC_GOT
3424 + || XINT (x, 1) == UNSPEC_FDPIC_GOT_FUNCDESC)
3425 + *total = 0;
3426 + return true;
3427 +
3428 + default:
3429 + return false;
3430 + }
3431 +}
3432 +
3433 +/* Return 1 if ADDR can have different meanings depending on the machine
3434 + mode of the memory reference it is used for or if the address is
3435 + valid for some modes but not others.
3436 +
3437 + Autoincrement and autodecrement addresses typically have
3438 + mode-dependent effects because the amount of the increment or
3439 + decrement is the size of the operand being addressed. Some machines
3440 + have other mode-dependent addresses. Many RISC machines have no
3441 + mode-dependent addresses.
3442 +
3443 + You may assume that ADDR is a valid address for the machine. */
3444 +
3445 +int
3446 +ubicom32_mode_dependent_address_p (rtx addr)
3447 +{
3448 + if (GET_CODE (addr) == POST_INC
3449 + || GET_CODE (addr) == PRE_INC
3450 + || GET_CODE (addr) == POST_DEC
3451 + || GET_CODE (addr) == PRE_DEC
3452 + || GET_CODE (addr) == POST_MODIFY
3453 + || GET_CODE (addr) == PRE_MODIFY)
3454 + return 1;
3455 +
3456 + return 0;
3457 +}
3458 +
3459 +static void
3460 +ubicom32_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
3461 +{
3462 + fprintf (file, "/* frame/pretend: %ld/%d save_regs: %d out_args: %d %s */\n",
3463 + get_frame_size (), crtl->args.pretend_args_size,
3464 + save_regs_size, crtl->outgoing_args_size,
3465 + current_function_is_leaf ? "leaf" : "nonleaf");
3466 +}
3467 +
3468 +static void
3469 +ubicom32_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
3470 + HOST_WIDE_INT size ATTRIBUTE_UNUSED)
3471 +{
3472 + ubicom32_reorg_completed = 0;
3473 +}
3474 +
3475 +static void
3476 +ubicom32_machine_dependent_reorg (void)
3477 +{
3478 +#if 0 /* Commenting out this optimization until it is fixed */
3479 + if (optimize)
3480 + {
3481 + compute_bb_for_insn ();
3482 +
3483 + /* Do a very simple CSE pass over just the hard registers. */
3484 + reload_cse_regs (get_insns ());
3485 +
3486 + /* Reload_cse_regs can eliminate potentially-trapping MEMs.
3487 + Remove any EH edges associated with them. */
3488 + if (flag_non_call_exceptions)
3489 + purge_all_dead_edges ();
3490 + }
3491 +#endif
3492 + ubicom32_reorg_completed = 1;
3493 +}
3494 +
3495 +void
3496 +ubicom32_output_cond_jump (rtx insn, rtx cond, rtx target)
3497 +{
3498 + rtx note;
3499 + int mostly_false_jump;
3500 + rtx xoperands[2];
3501 + rtx cc_reg;
3502 +
3503 + note = find_reg_note (insn, REG_BR_PROB, 0);
3504 + mostly_false_jump = !note || (INTVAL (XEXP (note, 0))
3505 + <= REG_BR_PROB_BASE / 2);
3506 +
3507 + xoperands[0] = target;
3508 + xoperands[1] = cond;
3509 + cc_reg = XEXP (cond, 0);
3510 +
3511 + if (GET_MODE (cc_reg) == CCWmode
3512 + || GET_MODE (cc_reg) == CCWZmode
3513 + || GET_MODE (cc_reg) == CCWZNmode)
3514 + {
3515 + if (mostly_false_jump)
3516 + output_asm_insn ("jmp%b1.w.f\t%0", xoperands);
3517 + else
3518 + output_asm_insn ("jmp%b1.w.t\t%0", xoperands);
3519 + return;
3520 + }
3521 +
3522 + if (GET_MODE (cc_reg) == CCSmode
3523 + || GET_MODE (cc_reg) == CCSZmode
3524 + || GET_MODE (cc_reg) == CCSZNmode)
3525 + {
3526 + if (mostly_false_jump)
3527 + output_asm_insn ("jmp%b1.s.f\t%0", xoperands);
3528 + else
3529 + output_asm_insn ("jmp%b1.s.t\t%0", xoperands);
3530 + return;
3531 + }
3532 +
3533 + abort ();
3534 +}
3535 +
3536 +/* Return non-zero if FUNC is a naked function. */
3537 +
3538 +static int
3539 +ubicom32_naked_function_p (void)
3540 +{
3541 + return lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE;
3542 +}
3543 +
3544 +/* Return an RTX indicating where the return address to the
3545 + calling function can be found. */
3546 +rtx
3547 +ubicom32_return_addr_rtx (int count, rtx frame ATTRIBUTE_UNUSED)
3548 +{
3549 + if (count != 0)
3550 + return NULL_RTX;
3551 +
3552 + return get_hard_reg_initial_val (Pmode, LINK_REGNO);
3553 +}
3554 +
3555 +/*
3556 + * ubicom32_readonly_data_section: This routtine handles code
3557 + * at the start of readonly data sections
3558 + */
3559 +static void
3560 +ubicom32_readonly_data_section (const void *data ATTRIBUTE_UNUSED)
3561 +{
3562 + static int num = 0;
3563 + if (in_section == readonly_data_section){
3564 + fprintf (asm_out_file, "%s", DATA_SECTION_ASM_OP);
3565 + if (flag_data_sections){
3566 + fprintf (asm_out_file, ".rodata%d", num);
3567 + fprintf (asm_out_file, ",\"a\"");
3568 + }
3569 + fprintf (asm_out_file, "\n");
3570 + }
3571 + num++;
3572 +}
3573 +
3574 +/*
3575 + * ubicom32_text_section: not in readonly section
3576 + */
3577 +static void
3578 +ubicom32_text_section(const void *data ATTRIBUTE_UNUSED)
3579 +{
3580 + fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP);
3581 +}
3582 +
3583 +/*
3584 + * ubicom32_data_section: not in readonly section
3585 + */
3586 +static void
3587 +ubicom32_data_section(const void *data ATTRIBUTE_UNUSED)
3588 +{
3589 + fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP);
3590 +}
3591 +
3592 +/*
3593 + * ubicom32_asm_init_sections: This routine implements special
3594 + * section handling
3595 + */
3596 +static void
3597 +ubicom32_asm_init_sections(void)
3598 +{
3599 + text_section = get_unnamed_section(SECTION_CODE, ubicom32_text_section, NULL);
3600 +
3601 + data_section = get_unnamed_section(SECTION_WRITE, ubicom32_data_section, NULL);
3602 +
3603 + readonly_data_section = get_unnamed_section(0, ubicom32_readonly_data_section, NULL);
3604 +}
3605 +
3606 +/*
3607 + * ubicom32_profiler: This routine would call
3608 + * mcount to support prof and gprof if mcount
3609 + * was supported. Currently, do nothing.
3610 + */
3611 +void