[toolchain]: replace gcc 4.5.2 support with 4.6.1
[openwrt.git] / toolchain / gcc / patches / 4.6.1 / 600-ubicom_support.patch
1 --- a/configure
2 +++ b/configure
3 @@ -3608,6 +3608,9 @@ case "${target}" in
4    ip2k-*-*)
5      noconfigdirs="$noconfigdirs target-libiberty target-libstdc++-v3 ${libgcj}"
6      ;;
7 +  ubicom32-*-*)
8 +    noconfigdirs="$noconfigdirs target-libffi"
9 +    ;;
10    *-*-linux* | *-*-gnu* | *-*-k*bsd*-gnu | *-*-kopensolaris*-gnu)
11      noconfigdirs="$noconfigdirs target-newlib target-libgloss"
12      ;;
13 --- /dev/null
14 +++ b/gcc/config/ubicom32/constraints.md
15 @@ -0,0 +1,149 @@
16 +; Constraint definitions for Ubicom32
17 +
18 +; Copyright (C) 2009 Free Software Foundation, Inc.
19 +; Contributed by Ubicom, Inc.
20 +
21 +; This file is part of GCC.
22 +
23 +; GCC is free software; you can redistribute it and/or modify it
24 +; under the terms of the GNU General Public License as published
25 +; by the Free Software Foundation; either version 3, or (at your
26 +; option) any later version.
27 +
28 +; GCC is distributed in the hope that it will be useful, but WITHOUT
29 +; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
30 +; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
31 +; License for more details.
32 +
33 +; You should have received a copy of the GNU General Public License
34 +; along with GCC; see the file COPYING3.  If not see
35 +; <http://www.gnu.org/licenses/>.
36 +
37 +(define_register_constraint "a" "ALL_ADDRESS_REGS"
38 +  "An An register.")
39 +
40 +(define_register_constraint "d" "DATA_REGS"
41 +  "A Dn register.")
42 +
43 +(define_register_constraint "h" "ACC_REGS"
44 +  "An accumulator register.")
45 +
46 +(define_register_constraint "l" "ACC_LO_REGS"
47 +  "An accn_lo register.")
48 +
49 +(define_register_constraint "Z" "FDPIC_REG"
50 +  "The FD-PIC GOT pointer: A0.")
51 +
52 +(define_constraint "I"
53 +  "An 8-bit signed constant value."
54 +  (and (match_code "const_int")
55 +       (match_test "(ival >= -128) && (ival <= 127)")))
56 +
57 +(define_constraint "Q"
58 +  "An 8-bit signed constant value represented as unsigned."
59 +  (and (match_code "const_int")
60 +       (match_test "(ival >= 0x00) && (ival <= 0xff)")))
61 +
62 +(define_constraint "R"
63 +  "An 8-bit signed constant value represented as unsigned."
64 +  (and (match_code "const_int")
65 +       (match_test "((ival >= 0x0000) && (ival <= 0x007f)) || ((ival >= 0xff80) && (ival <= 0xffff))")))
66 +
67 +(define_constraint "J"
68 +  "A 7-bit unsigned constant value."
69 +  (and (match_code "const_int")
70 +       (match_test "(ival >= 0) && (ival <= 127)")))
71 +
72 +(define_constraint "K"
73 +  "A 7-bit unsigned constant value shifted << 1."
74 +  (and (match_code "const_int")
75 +       (match_test "(ival >= 0) && (ival <= 254) && ((ival & 1) == 0)")))
76 +
77 +(define_constraint "L"
78 +  "A 7-bit unsigned constant value shifted << 2."
79 +  (and (match_code "const_int")
80 +       (match_test "(ival >= 0) && (ival <= 508) && ((ival & 3) == 0)")))
81 +
82 +(define_constraint "M"
83 +  "A 5-bit unsigned constant value."
84 +  (and (match_code "const_int")
85 +       (match_test "(ival >= 0) && (ival <= 31)")))
86 +
87 +(define_constraint "N"
88 +  "A signed 16 bit constant value."
89 +  (and (match_code "const_int")
90 +       (match_test "(ival >= -32768) && (ival <= 32767)")))
91 +
92 +(define_constraint "O"
93 +  "An exact bitmask of contiguous 1 bits starting at bit 0."
94 +  (and (match_code "const_int")
95 +       (match_test "exact_log2 (ival + 1) != -1")))
96 +
97 +(define_constraint "P"
98 +  "A 7-bit negative constant value shifted << 2."
99 +  (and (match_code "const_int")
100 +       (match_test "(ival >= -504) && (ival <= 0) && ((ival & 3) == 0)")))
101 +
102 +(define_constraint "S"
103 +  "A symbolic reference."
104 +  (match_code "symbol_ref"))
105 +
106 +(define_constraint "Y"
107 +  "An FD-PIC symbolic reference."
108 +  (and (match_test "TARGET_FDPIC")
109 +       (match_test "GET_CODE (op) == UNSPEC")
110 +       (ior (match_test "XINT (op, 1) == UNSPEC_FDPIC_GOT")
111 +           (match_test "XINT (op, 1) == UNSPEC_FDPIC_GOT_FUNCDESC"))))
112 +
113 +(define_memory_constraint "T1"
114 +  "A memory operand that can be used for .1 instruction."
115 +  (and (match_test "memory_operand (op, GET_MODE(op))")
116 +       (match_test "GET_MODE (op) == QImode")))
117 +
118 +(define_memory_constraint "T2"
119 +  "A memory operand that can be used for .2 instruction."
120 +  (and (match_test "memory_operand (op, GET_MODE(op))")
121 +       (match_test "GET_MODE (op) == HImode")))
122 +
123 +(define_memory_constraint "T4"
124 +  "A memory operand that can be used for .4 instruction."
125 +  (and (match_test "memory_operand (op, GET_MODE(op))")
126 +       (ior (match_test "GET_MODE (op) == SImode")
127 +           (match_test "GET_MODE (op) == DImode")
128 +           (match_test "GET_MODE (op) == SFmode"))))
129 +
130 +(define_memory_constraint "U1"
131 +  "An offsettable memory operand that can be used for .1 instruction."
132 +  (and (match_test "memory_operand (op, GET_MODE(op))")
133 +       (match_test "GET_MODE (op) == QImode")
134 +       (match_test "GET_CODE (XEXP (op, 0)) != POST_INC")
135 +       (match_test "GET_CODE (XEXP (op, 0)) != PRE_INC")
136 +       (match_test "GET_CODE (XEXP (op, 0)) != POST_DEC")
137 +       (match_test "GET_CODE (XEXP (op, 0)) != PRE_DEC")
138 +       (match_test "GET_CODE (XEXP (op, 0)) != POST_MODIFY")
139 +       (match_test "GET_CODE (XEXP (op, 0)) != PRE_MODIFY")))
140 +
141 +(define_memory_constraint "U2"
142 +  "An offsettable memory operand that can be used for .2 instruction."
143 +  (and (match_test "memory_operand (op, GET_MODE(op))")
144 +       (match_test "GET_MODE (op) == HImode")
145 +       (match_test "GET_CODE (XEXP (op, 0)) != POST_INC")
146 +       (match_test "GET_CODE (XEXP (op, 0)) != PRE_INC")
147 +       (match_test "GET_CODE (XEXP (op, 0)) != POST_DEC")
148 +       (match_test "GET_CODE (XEXP (op, 0)) != PRE_DEC")
149 +       (match_test "GET_CODE (XEXP (op, 0)) != POST_MODIFY")
150 +       (match_test "GET_CODE (XEXP (op, 0)) != PRE_MODIFY")))
151 +
152 +(define_memory_constraint "U4"
153 +  "An offsettable memory operand that can be used for .4 instruction."
154 +  (and (match_test "memory_operand (op, GET_MODE(op))")
155 +       (ior (match_test "GET_MODE (op) == SImode")
156 +           (match_test "GET_MODE (op) == DImode")
157 +           (match_test "GET_MODE (op) == SFmode"))
158 +       (match_test "GET_CODE (XEXP (op, 0)) != POST_INC")
159 +       (match_test "GET_CODE (XEXP (op, 0)) != PRE_INC")
160 +       (match_test "GET_CODE (XEXP (op, 0)) != POST_DEC")
161 +       (match_test "GET_CODE (XEXP (op, 0)) != PRE_DEC")
162 +       (match_test "GET_CODE (XEXP (op, 0)) != POST_MODIFY")
163 +       (match_test "GET_CODE (XEXP (op, 0)) != PRE_MODIFY")))
164 +
165 --- /dev/null
166 +++ b/gcc/config/ubicom32/crti.S
167 @@ -0,0 +1,54 @@
168 +/* Specialized code needed to support construction and destruction of
169 +   file-scope objects in C++ and Java code, and to support exception handling.
170 +   Copyright (C) 1999 Free Software Foundation, Inc.
171 +   Contributed by Charles-Antoine Gauthier (charles.gauthier@iit.nrc.ca).
172 +
173 +This file is part of GCC.
174 +
175 +GCC is free software; you can redistribute it and/or modify
176 +it under the terms of the GNU General Public License as published by
177 +the Free Software Foundation; either version 2, or (at your option)
178 +any later version.
179 +
180 +GCC is distributed in the hope that it will be useful,
181 +but WITHOUT ANY WARRANTY; without even the implied warranty of
182 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
183 +GNU General Public License for more details.
184 +
185 +You should have received a copy of the GNU General Public License
186 +along with GCC; see the file COPYING.  If not, write to
187 +the Free Software Foundation, 59 Temple Place - Suite 330,
188 +Boston, MA 02111-1307, USA.  */
189 +
190 +/* As a special exception, if you link this library with files
191 +   compiled with GCC to produce an executable, this does not cause
192 +   the resulting executable to be covered by the GNU General Public License.
193 +   This exception does not however invalidate any other reasons why
194 +   the executable file might be covered by the GNU General Public License.  */
195 +
196 +/*
197 + * This file just supplies function prologues for the .init and .fini
198 + * sections.  It is linked in before crtbegin.o.
199 + */
200 +       .file   "crti.o"
201 +       .ident  "GNU C crti.o"
202 +
203 +       .section .init
204 +       .align  2
205 +       .globl  _init
206 +       .type   _init, @function
207 +_init:
208 +       move.4 -4(sp)++, a5
209 +#ifdef __UBICOM32_FDPIC__
210 +       move.4 -4(sp)++, a0
211 +#endif
212 +
213 +       .section .fini
214 +       .align  2
215 +       .globl  _fini
216 +       .type   _fini, @function
217 +_fini:
218 +       move.4 -4(sp)++, a5
219 +#ifdef __UBICOM32_FDPIC__
220 +       move.4 -4(sp)++, a0
221 +#endif
222 --- /dev/null
223 +++ b/gcc/config/ubicom32/crtn.S
224 @@ -0,0 +1,47 @@
225 +/* Specialized code needed to support construction and destruction of
226 +   file-scope objects in C++ and Java code, and to support exception handling.
227 +   Copyright (C) 1999 Free Software Foundation, Inc.
228 +   Contributed by Charles-Antoine Gauthier (charles.gauthier@iit.nrc.ca).
229 +
230 +This file is part of GCC.
231 +
232 +GCC is free software; you can redistribute it and/or modify
233 +it under the terms of the GNU General Public License as published by
234 +the Free Software Foundation; either version 2, or (at your option)
235 +any later version.
236 +
237 +GCC is distributed in the hope that it will be useful,
238 +but WITHOUT ANY WARRANTY; without even the implied warranty of
239 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
240 +GNU General Public License for more details.
241 +
242 +You should have received a copy of the GNU General Public License
243 +along with GCC; see the file COPYING.  If not, write to
244 +the Free Software Foundation, 59 Temple Place - Suite 330,
245 +Boston, MA 02111-1307, USA.  */
246 +
247 +/* As a special exception, if you link this library with files
248 +   compiled with GCC to produce an executable, this does not cause
249 +   the resulting executable to be covered by the GNU General Public License.
250 +   This exception does not however invalidate any other reasons why
251 +   the executable file might be covered by the GNU General Public License.  */
252 +
253 +/*
254 + * This file supplies function epilogues for the .init and .fini sections.
255 + * It is linked in after all other files.
256 + */
257 +
258 +       .file   "crtn.o"
259 +       .ident  "GNU C crtn.o"
260 +
261 +       .section .init
262 +#ifdef __UBICOM32_FDPIC__
263 +       move.4  a0, (sp)4++
264 +#endif
265 +       ret     (sp)4++
266 +
267 +       .section .fini
268 +#ifdef __UBICOM32_FDPIC__
269 +       move.4  a0, (sp)4++
270 +#endif
271 +       ret     (sp)4++
272 --- /dev/null
273 +++ b/gcc/config/ubicom32/elf.h
274 @@ -0,0 +1,29 @@
275 +#undef  STARTFILE_SPEC
276 +#define STARTFILE_SPEC "\
277 +%{msim:%{!shared:crt0%O%s}} \
278 +crti%O%s crtbegin%O%s"
279 +
280 +#undef  ENDFILE_SPEC
281 +#define ENDFILE_SPEC   "crtend%O%s crtn%O%s"
282 +
283 +#ifdef __UBICOM32_FDPIC__
284 +#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC)                     \
285 +  asm (SECTION_OP);                                                    \
286 +  asm ("move.4 a0, 0(sp);\n\t"                                         \
287 +       "call a5," USER_LABEL_PREFIX #FUNC ";");                                \
288 +  asm (TEXT_SECTION_ASM_OP);
289 +#endif
290 +
291 +#undef SUBTARGET_DRIVER_SELF_SPECS
292 +#define SUBTARGET_DRIVER_SELF_SPECS \
293 +     "%{mfdpic:-msim} "
294 +
295 +#define NO_IMPLICIT_EXTERN_C
296 +
297 +/*
298 + * We need this to compile crtbegin/crtend. This should really be picked
299 + * up from elfos.h but at the moment including elfos.h causes other more
300 + * serous linker issues.
301 + */
302 +#define INIT_SECTION_ASM_OP    "\t.section\t.init"
303 +#define FINI_SECTION_ASM_OP    "\t.section\t.fini"
304 --- /dev/null
305 +++ b/gcc/config/ubicom32/linux.h
306 @@ -0,0 +1,80 @@
307 +/* Definitions of target machine for Ubicom32-uclinux
308 +
309 +   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
310 +   2009 Free Software Foundation, Inc.
311 +   Contributed by Ubicom, Inc.
312 +
313 +   This file is part of GCC.
314 +
315 +   GCC is free software; you can redistribute it and/or modify it
316 +   under the terms of the GNU General Public License as published
317 +   by the Free Software Foundation; either version 3, or (at your
318 +   option) any later version.
319 +
320 +   GCC is distributed in the hope that it will be useful, but WITHOUT
321 +   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
322 +   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
323 +   License for more details.
324 +
325 +   You should have received a copy of the GNU General Public License
326 +   along with GCC; see the file COPYING3.  If not see
327 +   <http://www.gnu.org/licenses/>.  */
328 +
329 +/* Don't assume anything about the header files.  */
330 +#define NO_IMPLICIT_EXTERN_C
331 +
332 +#undef  LIB_SPEC
333 +#define LIB_SPEC  \
334 +       "%{pthread:-lpthread} " \
335 +       "-lc"
336 +
337 +#undef LINK_GCC_C_SEQUENCE_SPEC
338 +#define LINK_GCC_C_SEQUENCE_SPEC \
339 +  "%{static:--start-group} %G %L %{static:--end-group} " \
340 +  "%{!static: %G}"
341 +
342 +#undef STARTFILE_SPEC
343 +#define STARTFILE_SPEC \
344 +  "%{!shared: %{pg|p|profile:gcrt1%O%s;pie:Scrt1%O%s;:crt1%O%s}} " \
345 +  "crtreloc%O%s crti%O%s %{shared|pie:crtbeginS%O%s;:crtbegin%O%s}"
346 +
347 +#undef ENDFILE_SPEC
348 +#define ENDFILE_SPEC \
349 +  "%{shared|pie:crtendS%O%s;:crtend%O%s} crtn%O%s"
350 +
351 +/* taken from linux.h */
352 +/* The GNU C++ standard library requires that these macros be defined.  */
353 +#undef CPLUSPLUS_CPP_SPEC
354 +#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
355 +
356 +#define TARGET_OS_CPP_BUILTINS()                               \
357 +    do {                                                       \
358 +       builtin_define_std ("__UBICOM32__");                    \
359 +       builtin_define_std ("__ubicom32__");                    \
360 +       builtin_define ("__gnu_linux__");                       \
361 +       builtin_define_std ("linux");                           \
362 +       builtin_define_std ("unix");                            \
363 +       builtin_assert ("system=linux");                        \
364 +       builtin_assert ("system=unix");                         \
365 +       builtin_assert ("system=posix");                        \
366 +    } while (0)
367 +
368 +#define OBJECT_FORMAT_ELF
369 +
370 +
371 +#undef DRIVER_SELF_SPECS
372 +#define DRIVER_SELF_SPECS \
373 +  "%{!mno-fdpic:-mfdpic}"
374 +
375 +#undef LINK_SPEC
376 +#define LINK_SPEC "%{mfdpic: -m elf32ubicom32fdpic -z text } %{shared} %{pie} \
377 +  %{static:-dn -Bstatic} \
378 +  %{shared:-G -Bdynamic} \
379 +  %{!shared: %{!static: \
380 +   %{rdynamic:-export-dynamic} \
381 +   %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}} \
382 +   %{static}} "
383 +
384 +/*
385 +#define MD_UNWIND_SUPPORT "config/bfin/linux-unwind.h"
386 +*/
387 --- /dev/null
388 +++ b/gcc/config/ubicom32/predicates.md
389 @@ -0,0 +1,327 @@
390 +; Predicate definitions for Ubicom32.
391 +
392 +; Copyright (C) 2009 Free Software Foundation, Inc.
393 +; Contributed by Ubicom, Inc.
394 +
395 +; This file is part of GCC.
396 +
397 +; GCC is free software; you can redistribute it and/or modify it
398 +; under the terms of the GNU General Public License as published
399 +; by the Free Software Foundation; either version 3, or (at your
400 +; option) any later version.
401 +
402 +; GCC is distributed in the hope that it will be useful, but WITHOUT
403 +; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
404 +; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
405 +; License for more details.
406 +
407 +; You should have received a copy of the GNU General Public License
408 +; along with GCC; see the file COPYING3.  If not see
409 +; <http://www.gnu.org/licenses/>.
410 +
411 +(define_predicate "ubicom32_move_operand"
412 +  (match_code "const_int, const_double, const, mem, subreg, reg, lo_sum")
413 +{
414 +  if (CONST_INT_P (op))
415 +    return true;
416 +
417 +  if (GET_CODE (op) == CONST_DOUBLE)
418 +    return true;
419 +  
420 +  if (GET_CODE (op) == CONST)
421 +    return memory_address_p (mode, op);
422 +
423 +  if (GET_MODE (op) != mode)
424 +    return false;
425 +
426 +  if (MEM_P (op))
427 +    return memory_address_p (mode, XEXP (op, 0));
428 +  
429 +  if (GET_CODE (op) == SUBREG) {
430 +      op = SUBREG_REG (op);
431 +
432 +      if (REG_P (op))
433 +       return true;
434 +  
435 +      if (! MEM_P (op))
436 +       return false;
437 +
438 +      /* Paradoxical SUBREG.  */
439 +      if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (op)))
440 +       return false;
441 +
442 +      return memory_address_p (GET_MODE (op), XEXP (op, 0));
443 +    }
444 +
445 +  return register_operand (op, mode);
446 +})
447 +
448 +;; Returns true if OP is either a symbol reference or a sum of a
449 +;; symbol reference and a constant.
450 +
451 +(define_predicate "ubicom32_symbolic_address_operand"
452 +  (match_code "symbol_ref, label_ref, const")
453 +{
454 +  switch (GET_CODE (op))
455 +    {
456 +    case SYMBOL_REF:
457 +    case LABEL_REF:
458 +      return true;
459 +
460 +    case CONST:
461 +      op = XEXP (op, 0);
462 +      return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
463 +              || GET_CODE (XEXP (op, 0)) == LABEL_REF)
464 +             && CONST_INT_P (XEXP (op, 1)));
465 +
466 +    default:
467 +      return false;
468 +    }
469 +})
470 +
471 +;; Return true if operand is the uClinux FD-PIC register.
472 +
473 +(define_predicate "ubicom32_fdpic_operand"
474 +  (match_code "reg")
475 +{
476 +  if (! TARGET_FDPIC)
477 +    return false;
478 +
479 +  if (!REG_P (op))
480 +    return false;
481 +
482 +  if (GET_MODE (op) != mode && mode != VOIDmode)
483 +    return false;
484 +
485 +  if (REGNO (op) != FDPIC_REGNUM && REGNO (op) < FIRST_PSEUDO_REGISTER)
486 +    return false;
487 +
488 +  return true;
489 +})
490 +
491 +(define_predicate "ubicom32_fdpic_got_offset_operand"
492 +  (match_code "unspec")
493 +{
494 +  if (! TARGET_FDPIC)
495 +    return false;
496 +
497 +  if (GET_CODE (op) != UNSPEC)
498 +    return false;
499 +
500 +  if (XINT (op, 1) != UNSPEC_FDPIC_GOT
501 +      && XINT (op, 1) != UNSPEC_FDPIC_GOT_FUNCDESC)
502 +    return false;
503 +
504 +  return true;
505 +})
506 +
507 +(define_predicate "ubicom32_arith_operand"
508 +  (match_code "subreg, reg, const_int, lo_sum, mem")
509 +{
510 +  return (ubicom32_move_operand (op, mode)
511 +         && ! ubicom32_symbolic_address_operand (op, mode)
512 +         && (! CONST_INT_P (op)
513 +             || satisfies_constraint_I (op)));
514 +})
515 +
516 +(define_predicate "ubicom32_arith_operand_dot1"
517 +  (match_code "subreg, reg, const_int, lo_sum, mem")
518 +{
519 +  return (ubicom32_move_operand (op, mode)
520 +         && ! ubicom32_symbolic_address_operand (op, mode)
521 +         && (! CONST_INT_P (op)
522 +             || satisfies_constraint_Q (op)));
523 +})
524 +
525 +(define_predicate "ubicom32_arith_operand_dot2"
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_R (op)));
532 +})
533 +
534 +(define_predicate "ubicom32_compare_operand"
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_N (op)));
541 +})
542 +
543 +(define_predicate "ubicom32_compare_operator"
544 +  (match_code "compare"))
545 +
546 +(define_predicate "ubicom32_and_or_si3_operand"
547 +  (match_code "subreg, reg, const_int, lo_sum, mem")
548 +{
549 +  return (ubicom32_arith_operand (op, mode)
550 +         || (CONST_INT_P (op)
551 +             && ((exact_log2 (INTVAL (op) + 1) != -1
552 +                  && exact_log2 (INTVAL (op) + 1) <= 31)
553 +                 || (exact_log2 (INTVAL (op)) != -1
554 +                     && exact_log2 (INTVAL (op)) <= 31)
555 +                 || (exact_log2 (~INTVAL (op)) != -1
556 +                     && exact_log2 (~INTVAL (op)) <= 31))));
557 +})
558 +
559 +(define_predicate "ubicom32_and_or_hi3_operand"
560 +  (match_code "subreg, reg, const_int, lo_sum, mem")
561 +{
562 +  return (ubicom32_arith_operand (op, mode)
563 +         || (CONST_INT_P (op)
564 +             && exact_log2 (INTVAL (op) + 1) != -1
565 +             && exact_log2 (INTVAL (op) + 1) <= 15));
566 +})
567 +
568 +(define_predicate "ubicom32_mem_or_address_register_operand"
569 +  (match_code "subreg, reg, mem")
570 +{
571 +  unsigned int regno;
572 +
573 +  if (MEM_P (op)
574 +      && memory_operand (op, mode))
575 +    return true;
576 +
577 +  if (REG_P (op))
578 +    regno = REGNO (op);
579 +  else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
580 +    {
581 +      int offset;
582 +      if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)
583 +       offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op)));
584 +      else
585 +       offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
586 +                                     GET_MODE (SUBREG_REG (op)),
587 +                                     SUBREG_BYTE (op),
588 +                                     GET_MODE (op));
589 +      regno = REGNO (SUBREG_REG (op)) + offset;
590 +    }
591 +  else
592 +    return false;
593 +
594 +  return (regno >= FIRST_PSEUDO_REGISTER 
595 +         || REGNO_REG_CLASS (regno) == FDPIC_REG
596 +         || REGNO_REG_CLASS (regno) == ADDRESS_REGS);
597 +})
598 +
599 +(define_predicate "ubicom32_data_register_operand"
600 +  (match_code "subreg, reg")
601 +{
602 +  unsigned int regno;
603 +
604 +  if (REG_P (op))
605 +    regno = REGNO (op);
606 +  else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
607 +    {
608 +      int offset;
609 +      if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)
610 +       offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op)));
611 +      else
612 +       offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
613 +                                     GET_MODE (SUBREG_REG (op)),
614 +                                     SUBREG_BYTE (op),
615 +                                     GET_MODE (op));
616 +      regno = REGNO (SUBREG_REG (op)) + offset;
617 +    }
618 +  else
619 +    return false;
620 +
621 +  return ((regno >= FIRST_PSEUDO_REGISTER 
622 +          && regno != REGNO (virtual_stack_vars_rtx))
623 +         || REGNO_REG_CLASS (regno) == DATA_REGS);
624 +})
625 +
626 +(define_predicate "ubicom32_address_register_operand"
627 +  (match_code "subreg, reg")
628 +{
629 +  unsigned int regno;
630 +
631 +  if (REG_P (op))
632 +    regno = REGNO (op);
633 +  else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
634 +    {
635 +      int offset;
636 +      if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)
637 +       offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op)));
638 +      else
639 +       offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
640 +                                     GET_MODE (SUBREG_REG (op)),
641 +                                     SUBREG_BYTE (op),
642 +                                     GET_MODE (op));
643 +      regno = REGNO (SUBREG_REG (op)) + offset;
644 +    }
645 +  else
646 +    return false;
647 +
648 +  return (regno >= FIRST_PSEUDO_REGISTER 
649 +         || REGNO_REG_CLASS (regno) == FDPIC_REG
650 +         || REGNO_REG_CLASS (regno) == ADDRESS_REGS);
651 +})
652 +
653 +(define_predicate "ubicom32_acc_lo_register_operand"
654 +  (match_code "subreg, reg")
655 +{
656 +  unsigned int regno;
657 +
658 +  if (REG_P (op))
659 +    regno = REGNO (op);
660 +  else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
661 +    {
662 +      int offset;
663 +      if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)
664 +       offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op)));
665 +      else
666 +       offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
667 +                                     GET_MODE (SUBREG_REG (op)),
668 +                                     SUBREG_BYTE (op),
669 +                                     GET_MODE (op));
670 +      regno = REGNO (SUBREG_REG (op)) + offset;
671 +    }
672 +  else
673 +    return false;
674 +
675 +  return ((regno >= FIRST_PSEUDO_REGISTER 
676 +          && regno != REGNO (virtual_stack_vars_rtx))
677 +         || REGNO_REG_CLASS (regno) == ACC_LO_REGS);
678 +})
679 +
680 +(define_predicate "ubicom32_acc_hi_register_operand"
681 +  (match_code "subreg, reg")
682 +{
683 +  unsigned int regno;
684 +
685 +  if (REG_P (op))
686 +    regno = REGNO (op);
687 +  else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
688 +    {
689 +      int offset;
690 +      if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)
691 +       offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op)));
692 +      else
693 +       offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
694 +                                     GET_MODE (SUBREG_REG (op)),
695 +                                     SUBREG_BYTE (op),
696 +                                     GET_MODE (op));
697 +      regno = REGNO (SUBREG_REG (op)) + offset;
698 +    }
699 +  else
700 +    return false;
701 +
702 +  return ((regno >= FIRST_PSEUDO_REGISTER 
703 +          && regno != REGNO (virtual_stack_vars_rtx))
704 +         || REGNO_REG_CLASS (regno) == ACC_REGS);
705 +})
706 +
707 +(define_predicate "ubicom32_call_address_operand"
708 +  (match_code "symbol_ref, subreg, reg")
709 +{
710 +  return (GET_CODE (op) == SYMBOL_REF || REG_P (op));
711 +})
712 +
713 +(define_special_predicate "ubicom32_cc_register_operand"
714 +  (and (match_code "reg")
715 +       (match_test "REGNO (op) == CC_REGNUM")))
716 +
717 --- /dev/null
718 +++ b/gcc/config/ubicom32/t-ubicom32
719 @@ -0,0 +1,52 @@
720 +# Name of assembly file containing libgcc1 functions.
721 +# This entry must be present, but it can be empty if the target does
722 +# not need any assembler functions to support its code generation.
723 +CROSS_LIBGCC1 =
724 +
725 +# Alternatively if assembler functions *are* needed then define the
726 +# entries below:
727 +# CROSS_LIBGCC1 = libgcc1-asm.a
728 +
729 +LIB2FUNCS_EXTRA = \
730 +       $(srcdir)/config/udivmodsi4.c \
731 +       $(srcdir)/config/divmod.c \
732 +       $(srcdir)/config/udivmod.c
733 +
734 +# If any special flags are necessary when building libgcc2 put them here.
735 +#
736 +# TARGET_LIBGCC2_CFLAGS = 
737 +
738 +# We want fine grained libraries, so use the new code to build the
739 +# floating point emulation libraries.
740 +FPBIT = fp-bit.c
741 +DPBIT = dp-bit.c
742 +
743 +fp-bit.c: $(srcdir)/config/fp-bit.c
744 +       echo '#define FLOAT'                            > fp-bit.c
745 +       cat $(srcdir)/config/fp-bit.c                   >> fp-bit.c
746 +
747 +dp-bit.c: $(srcdir)/config/fp-bit.c
748 +       cat $(srcdir)/config/fp-bit.c > dp-bit.c
749 +
750 +# Commented out to speed up compiler development!
751 +#
752 +# MULTILIB_OPTIONS = march=ubicom32v1/march=ubicom32v2/march=ubicom32v3/march=ubicom32v4
753 +# MULTILIB_DIRNAMES = ubicom32v1 ubicom32v2 ubicom32v3 ubicom32v4
754 +
755 +MULTILIB_OPTIONS = march=ubicom32v3/march=ubicom32v4
756 +MULTILIB_OPTIONS += mfdpic
757 +MULTILIB_OPTIONS += mno-ipos-abi/mipos-abi
758 +MULTILIB_OPTIONS += fno-leading-underscore/fleading-underscore
759 +
760 +# Assemble startup files.
761 +$(T)crti.o: $(srcdir)/config/ubicom32/crti.S $(GCC_PASSES)
762 +       $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
763 +       -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/ubicom32/crti.S
764 +
765 +$(T)crtn.o: $(srcdir)/config/ubicom32/crtn.S $(GCC_PASSES)
766 +       $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
767 +       -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/ubicom32/crtn.S
768 +
769 +# these parts are required because uClibc ldso needs them to link.
770 +# they are not in the specfile so they will not be included automatically.
771 +EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crtbeginS.o crtendS.o crti.o crtn.o
772 --- /dev/null
773 +++ b/gcc/config/ubicom32/t-ubicom32-linux
774 @@ -0,0 +1,35 @@
775 +# Name of assembly file containing libgcc1 functions.
776 +# This entry must be present, but it can be empty if the target does
777 +# not need any assembler functions to support its code generation.
778 +CROSS_LIBGCC1 =
779 +
780 +# Alternatively if assembler functions *are* needed then define the
781 +# entries below:
782 +# CROSS_LIBGCC1 = libgcc1-asm.a
783 +
784 +LIB2FUNCS_EXTRA = \
785 +       $(srcdir)/config/udivmodsi4.c \
786 +       $(srcdir)/config/divmod.c \
787 +       $(srcdir)/config/udivmod.c
788 +
789 +# If any special flags are necessary when building libgcc2 put them here.
790 +#
791 +# TARGET_LIBGCC2_CFLAGS =
792 +
793 +# We want fine grained libraries, so use the new code to build the
794 +# floating point emulation libraries.
795 +FPBIT = fp-bit.c
796 +DPBIT = dp-bit.c
797 +
798 +fp-bit.c: $(srcdir)/config/fp-bit.c
799 +       echo '#define FLOAT'                            > fp-bit.c
800 +       cat $(srcdir)/config/fp-bit.c                   >> fp-bit.c
801 +
802 +dp-bit.c: $(srcdir)/config/fp-bit.c
803 +       cat $(srcdir)/config/fp-bit.c > dp-bit.c
804 +
805 +# We only support v3 and v4 ISAs for uClinux.
806 +
807 +MULTILIB_OPTIONS = march=ubicom32v3/march=ubicom32v4
808 +
809 +#EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crtbeginS.o crtendS.o
810 --- /dev/null
811 +++ b/gcc/config/ubicom32/t-ubicom32-uclinux
812 @@ -0,0 +1,35 @@
813 +# Name of assembly file containing libgcc1 functions.
814 +# This entry must be present, but it can be empty if the target does
815 +# not need any assembler functions to support its code generation.
816 +CROSS_LIBGCC1 =
817 +
818 +# Alternatively if assembler functions *are* needed then define the
819 +# entries below:
820 +# CROSS_LIBGCC1 = libgcc1-asm.a
821 +
822 +LIB2FUNCS_EXTRA = \
823 +       $(srcdir)/config/udivmodsi4.c \
824 +       $(srcdir)/config/divmod.c \
825 +       $(srcdir)/config/udivmod.c
826 +
827 +# If any special flags are necessary when building libgcc2 put them here.
828 +#
829 +# TARGET_LIBGCC2_CFLAGS = 
830 +
831 +# We want fine grained libraries, so use the new code to build the
832 +# floating point emulation libraries.
833 +FPBIT = fp-bit.c
834 +DPBIT = dp-bit.c
835 +
836 +fp-bit.c: $(srcdir)/config/fp-bit.c
837 +       echo '#define FLOAT'                            > fp-bit.c
838 +       cat $(srcdir)/config/fp-bit.c                   >> fp-bit.c
839 +
840 +dp-bit.c: $(srcdir)/config/fp-bit.c
841 +       cat $(srcdir)/config/fp-bit.c > dp-bit.c
842 +
843 +# We only support v3 and v4 ISAs for uClinux.
844 +
845 +MULTILIB_OPTIONS = march=ubicom32v3/march=ubicom32v4
846 +
847 +EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o # crtbeginS.o crtendS.o
848 --- /dev/null
849 +++ b/gcc/config/ubicom32/ubicom32-modes.def
850 @@ -0,0 +1,30 @@
851 +/* Definitions of target machine for GNU compiler, Ubicom32 architecture.
852 +   Copyright (C) 2009 Free Software Foundation, Inc.
853 +   Contributed by Ubicom, Inc.
854 +
855 +   This file is part of GCC.
856 +
857 +   GCC is free software; you can redistribute it and/or modify it
858 +   under the terms of the GNU General Public License as published
859 +   by the Free Software Foundation; either version 3, or (at your
860 +   option) any later version.
861 +
862 +   GCC is distributed in the hope that it will be useful, but WITHOUT
863 +   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
864 +   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
865 +   License for more details.
866 +
867 +   You should have received a copy of the GNU General Public License
868 +   along with GCC; see the file COPYING3.  If not see
869 +   <http://www.gnu.org/licenses/>.  */
870 +
871 +/* Some insns set all condition code flags, some only set the Z and N flags, and
872 +   some only set the Z flag.  */
873 +
874 +CC_MODE (CCW);
875 +CC_MODE (CCWZN);
876 +CC_MODE (CCWZ);
877 +CC_MODE (CCS);
878 +CC_MODE (CCSZN);
879 +CC_MODE (CCSZ);
880 +
881 --- /dev/null
882 +++ b/gcc/config/ubicom32/ubicom32-protos.h
883 @@ -0,0 +1,84 @@
884 +/* Function prototypes for Ubicom IP3000.
885 +
886 +   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
887 +   2009 Free Software Foundation, Inc.
888 +   Contributed by Ubicom, Inc.
889 +
890 +   This file is part of GNU CC.
891 +
892 +   GNU CC is free software; you can redistribute it and/or modify it under
893 +   the terms of the GNU General Public License as published by the Free
894 +   Software Foundation; either version 2, or (at your option) any later
895 +   version.
896 +
897 +   GNU CC is distributed in the hope that it will be useful, but WITHOUT
898 +   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
899 +   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
900 +   for more details.
901 +
902 +   You should have received a copy of the GNU General Public License along
903 +   with GNU CC; see the file COPYING.  If not, write to the Free Software
904 +   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
905 +
906 +#ifdef RTX_CODE
907 +
908 +#ifdef TREE_CODE
909 +extern void ubicom32_va_start (tree, rtx);
910 +#endif /* TREE_CODE */
911 +
912 +extern void ubicom32_print_operand (FILE *, rtx, int);
913 +extern void ubicom32_print_operand_address (FILE *, rtx);
914 +
915 +extern void ubicom32_conditional_register_usage (void);
916 +extern enum reg_class ubicom32_preferred_reload_class (rtx, enum reg_class);
917 +extern int ubicom32_regno_ok_for_index_p (int, int);
918 +extern void ubicom32_expand_movsi (rtx *);
919 +extern void ubicom32_expand_addsi3 (rtx *);
920 +extern int ubicom32_emit_mult_sequence (rtx *);
921 +extern void ubicom32_emit_move_const_int (rtx, rtx);
922 +extern bool ubicom32_legitimate_constant_p (rtx);
923 +extern bool ubicom32_legitimate_address_p (enum machine_mode, rtx, int);
924 +extern rtx ubicom32_legitimize_address (rtx, rtx, enum machine_mode);
925 +extern rtx ubicom32_legitimize_reload_address (rtx, enum machine_mode, int, int);
926 +extern void ubicom32_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1);
927 +extern int ubicom32_mode_dependent_address_p (rtx);
928 +extern void ubicom32_output_cond_jump (rtx, rtx, rtx);
929 +extern void ubicom32_expand_eh_return (rtx *);
930 +extern void ubicom32_expand_call_fdpic (rtx *);
931 +extern void ubicom32_expand_call_value_fdpic (rtx *);
932 +extern enum machine_mode ubicom32_select_cc_mode (RTX_CODE, rtx, rtx);
933 +extern rtx ubicom32_gen_compare_reg (RTX_CODE, rtx, rtx);
934 +extern int ubicom32_shiftable_const_int (int);
935 +#endif /* RTX_CODE */
936 +
937 +#ifdef TREE_CODE
938 +extern void init_cumulative_args (CUMULATIVE_ARGS *cum,
939 +                                 tree fntype,
940 +                                 struct rtx_def *libname,
941 +                                 int indirect);
942 +extern struct rtx_def *function_arg (CUMULATIVE_ARGS *,
943 +                                    enum machine_mode, tree, int);
944 +extern struct rtx_def *function_incoming_arg (CUMULATIVE_ARGS *,
945 +                                             enum machine_mode,
946 +                                             tree, int);
947 +extern int function_arg_partial_nregs (CUMULATIVE_ARGS *,
948 +                                      enum machine_mode, tree, int);
949 +extern struct rtx_def *ubicom32_va_arg (tree, tree);
950 +extern int ubicom32_reg_parm_stack_space (tree);
951 +#endif /* TREE_CODE */
952 +
953 +extern struct rtx_def * ubicom32_builtin_saveregs (void);
954 +extern void asm_file_start (FILE *);
955 +extern void ubicom32_expand_prologue (void);
956 +extern void ubicom32_expand_epilogue (void);
957 +extern int ubicom32_initial_elimination_offset (int, int);
958 +extern int ubicom32_regno_ok_for_base_p (int, int);
959 +extern bool ubicom32_hard_regno_mode_ok (unsigned int, enum machine_mode);
960 +extern int ubicom32_can_use_return_insn_p (void);
961 +extern rtx ubicom32_return_addr_rtx (int, rtx);
962 +extern void ubicom32_optimization_options (int, int);
963 +extern void ubicom32_override_options (void);
964 +extern bool ubicom32_match_cc_mode (rtx, enum machine_mode);
965 +
966 +extern int ubicom32_reorg_completed;
967 +
968 --- /dev/null
969 +++ b/gcc/config/ubicom32/ubicom32.c
970 @@ -0,0 +1,2881 @@
971 +/* Subroutines for insn-output.c for Ubicom32
972 +
973 +   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
974 +   2009 Free Software Foundation, Inc.
975 +   Contributed by Ubicom, Inc.
976 +
977 +   This file is part of GCC.
978 +
979 +   GCC is free software; you can redistribute it and/or modify it
980 +   under the terms of the GNU General Public License as published
981 +   by the Free Software Foundation; either version 3, or (at your
982 +   option) any later version.
983 +
984 +   GCC is distributed in the hope that it will be useful, but WITHOUT
985 +   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
986 +   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
987 +   License for more details.
988 +
989 +   You should have received a copy of the GNU General Public License
990 +   along with GCC; see the file COPYING3.  If not see
991 +   <http://www.gnu.org/licenses/>.  */
992 +
993 +#include "config.h"
994 +#include "system.h"
995 +#include "coretypes.h"
996 +#include "tm.h"
997 +#include "rtl.h"
998 +#include "tree.h"
999 +#include "regs.h"
1000 +#include "hard-reg-set.h"
1001 +#include "real.h"
1002 +#include "insn-config.h"
1003 +#include "conditions.h"
1004 +#include "insn-flags.h"
1005 +#include "output.h"
1006 +#include "insn-attr.h"
1007 +#include "insn-codes.h"
1008 +#include "flags.h"
1009 +#include "recog.h"
1010 +#include "expr.h"
1011 +#include "function.h"
1012 +#include "obstack.h"
1013 +#include "toplev.h"
1014 +#include "tm_p.h"
1015 +#include "tm-constrs.h"
1016 +#include "basic-block.h"
1017 +#include "integrate.h"
1018 +#include "target.h"
1019 +#include "target-def.h"
1020 +#include "reload.h"
1021 +#include "df.h"
1022 +#include "langhooks.h"
1023 +#include "optabs.h"
1024 +
1025 +static tree ubicom32_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
1026 +static void ubicom32_layout_frame (void);
1027 +static void ubicom32_function_prologue (FILE *, HOST_WIDE_INT);
1028 +static void ubicom32_function_epilogue (FILE *, HOST_WIDE_INT);
1029 +static bool ubicom32_rtx_costs (rtx, int, int, int *, bool speed);
1030 +static bool ubicom32_fixed_condition_code_regs (unsigned int *,
1031 +                                               unsigned int *);
1032 +static enum machine_mode ubicom32_cc_modes_compatible (enum machine_mode,
1033 +                                                      enum machine_mode);
1034 +static int ubicom32_naked_function_p (void);
1035 +static void ubicom32_machine_dependent_reorg (void);
1036 +static bool ubicom32_assemble_integer (rtx, unsigned int, int);
1037 +static void ubicom32_asm_init_sections (void);
1038 +static int ubicom32_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,tree, 
1039 +                                      bool);
1040 +static bool ubicom32_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
1041 +                                       enum machine_mode mode, const_tree type,
1042 +                                       bool named ATTRIBUTE_UNUSED);
1043 +static bool ubicom32_callee_copies (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
1044 +                                   enum machine_mode mode, const_tree type,
1045 +                                   bool named ATTRIBUTE_UNUSED);
1046 +
1047 +static bool ubicom32_return_in_memory (const_tree type, 
1048 +                                      const_tree fntype ATTRIBUTE_UNUSED);
1049 +static bool ubicom32_is_base_reg (rtx, int);
1050 +static void ubicom32_init_builtins (void);
1051 +static rtx ubicom32_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
1052 +static tree ubicom32_fold_builtin (tree, tree, bool);
1053 +static int ubicom32_get_valid_offset_mask (enum machine_mode);
1054 +static bool ubicom32_cannot_force_const_mem (rtx);
1055 +
1056 +/* Case values threshold */
1057 +int ubicom32_case_values_threshold = 6;
1058 +
1059 +/* Nonzero if this chip supports the Ubicom32 v3 ISA.  */
1060 +int ubicom32_v3 = 1;
1061 +
1062 +/* Nonzero if this chip supports the Ubicom32 v4 ISA.  */
1063 +int ubicom32_v4 = 1;
1064 +
1065 +/* Valid attributes:
1066 +   naked - don't generate function prologue/epilogue and `ret' command.  */
1067 +const struct attribute_spec ubicom32_attribute_table[] =
1068 +{
1069 +  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
1070 +  { "naked", 0, 0, true,  false, false, ubicom32_handle_fndecl_attribute },
1071 +  { NULL,    0, 0, false, false, false, NULL }
1072 +};
1073 +
1074 +#undef TARGET_ASM_FUNCTION_PROLOGUE
1075 +#define TARGET_ASM_FUNCTION_PROLOGUE ubicom32_function_prologue
1076 +
1077 +#undef TARGET_ASM_FUNCTION_EPILOGUE
1078 +#define TARGET_ASM_FUNCTION_EPILOGUE ubicom32_function_epilogue
1079 +
1080 +#undef TARGET_ATTRIBUTE_TABLE
1081 +#define TARGET_ATTRIBUTE_TABLE ubicom32_attribute_table
1082 +
1083 +/* All addresses cost the same amount.  */
1084 +#undef TARGET_ADDRESS_COST
1085 +#define TARGET_ADDRESS_COST hook_int_rtx_bool_0
1086 +
1087 +#undef TARGET_RTX_COSTS
1088 +#define TARGET_RTX_COSTS ubicom32_rtx_costs
1089 +
1090 +#undef TARGET_FIXED_CONDITION_CODE_REGS
1091 +#define TARGET_FIXED_CONDITION_CODE_REGS ubicom32_fixed_condition_code_regs
1092 +
1093 +#undef TARGET_CC_MODES_COMPATIBLE
1094 +#define TARGET_CC_MODES_COMPATIBLE ubicom32_cc_modes_compatible
1095 +
1096 +#undef TARGET_MACHINE_DEPENDENT_REORG
1097 +#define TARGET_MACHINE_DEPENDENT_REORG ubicom32_machine_dependent_reorg
1098 +
1099 +#undef  TARGET_ASM_INTEGER
1100 +#define TARGET_ASM_INTEGER ubicom32_assemble_integer
1101 +
1102 +#undef TARGET_ASM_INIT_SECTIONS
1103 +#define TARGET_ASM_INIT_SECTIONS ubicom32_asm_init_sections
1104 +
1105 +#undef TARGET_ARG_PARTIAL_BYTES
1106 +#define TARGET_ARG_PARTIAL_BYTES ubicom32_arg_partial_bytes
1107 +
1108 +#undef TARGET_PASS_BY_REFERENCE
1109 +#define TARGET_PASS_BY_REFERENCE ubicom32_pass_by_reference
1110 +
1111 +#undef TARGET_CALLEE_COPIES
1112 +#define TARGET_CALLEE_COPIES ubicom32_callee_copies
1113 +
1114 +#undef TARGET_RETURN_IN_MEMORY
1115 +#define TARGET_RETURN_IN_MEMORY ubicom32_return_in_memory
1116 +
1117 +#undef TARGET_INIT_BUILTINS
1118 +#define TARGET_INIT_BUILTINS ubicom32_init_builtins
1119 +
1120 +#undef TARGET_EXPAND_BUILTIN
1121 +#define TARGET_EXPAND_BUILTIN ubicom32_expand_builtin
1122 +
1123 +#undef TARGET_FOLD_BUILTIN
1124 +#define TARGET_FOLD_BUILTIN ubicom32_fold_builtin
1125 +
1126 +#undef TARGET_CANNOT_FORCE_CONST_MEM
1127 +#define TARGET_CANNOT_FORCE_CONST_MEM ubicom32_cannot_force_const_mem
1128 +
1129 +struct gcc_target targetm = TARGET_INITIALIZER;
1130 +
1131 +static char save_regs[FIRST_PSEUDO_REGISTER];
1132 +static int nregs;
1133 +static int frame_size;
1134 +int ubicom32_stack_size = 0;   /* size of allocated stack (including frame) */
1135 +int ubicom32_can_use_calli_to_ret;
1136 +
1137 +#define STACK_UNIT_BOUNDARY (STACK_BOUNDARY / BITS_PER_UNIT)
1138 +#define ROUND_CALL_BLOCK_SIZE(BYTES) \
1139 +  (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1))
1140 +
1141 +/* In case of a PRE_INC, POST_INC, PRE_DEC, POST_DEC memory reference, we
1142 +   must report the mode of the memory reference from PRINT_OPERAND to
1143 +   PRINT_OPERAND_ADDRESS.  */
1144 +enum machine_mode output_memory_reference_mode;
1145 +
1146 +/* Flag for some split insns from the ubicom32.md.  */
1147 +int ubicom32_reorg_completed;
1148 +
1149 +enum reg_class const ubicom32_regclass_map[FIRST_PSEUDO_REGISTER] =
1150 +{
1151 +  DATA_REGS, 
1152 +  DATA_REGS, 
1153 +  DATA_REGS, 
1154 +  DATA_REGS, 
1155 +  DATA_REGS, 
1156 +  DATA_REGS, 
1157 +  DATA_REGS, 
1158 +  DATA_REGS, 
1159 +  DATA_REGS, 
1160 +  DATA_REGS, 
1161 +  DATA_REGS, 
1162 +  DATA_REGS, 
1163 +  DATA_REGS, 
1164 +  DATA_REGS, 
1165 +  DATA_REGS, 
1166 +  DATA_REGS, 
1167 +  FDPIC_REG, 
1168 +  ADDRESS_REGS, 
1169 +  ADDRESS_REGS, 
1170 +  ADDRESS_REGS, 
1171 +  ADDRESS_REGS, 
1172 +  ADDRESS_REGS, 
1173 +  ADDRESS_REGS, 
1174 +  ADDRESS_REGS, 
1175 +  ACC_REGS,
1176 +  ACC_LO_REGS,
1177 +  ACC_REGS,
1178 +  ACC_LO_REGS,
1179 +  SOURCE3_REG,
1180 +  ADDRESS_REGS,
1181 +  NO_REGS,                     /* CC_REG must be NO_REGS */
1182 +  SPECIAL_REGS,
1183 +  SPECIAL_REGS,
1184 +  SPECIAL_REGS,
1185 +  SPECIAL_REGS,
1186 +  SPECIAL_REGS,
1187 +  SPECIAL_REGS,
1188 +  SPECIAL_REGS,
1189 +  SPECIAL_REGS
1190 +};
1191 +
1192 +rtx ubicom32_compare_op0;
1193 +rtx ubicom32_compare_op1;
1194 +
1195 +/* Handle command line option overrides.  */
1196 +
1197 +void
1198 +ubicom32_override_options (void)
1199 +{
1200 +  flag_pic = 0;
1201 +
1202 +  if (strcmp (ubicom32_arch_name, "ubicom32v1") == 0) {
1203 +    /* If we have a version 1 architecture then we want to avoid using jump
1204 +       tables.  */
1205 +    ubicom32_case_values_threshold = 30000;
1206 +    ubicom32_v3 = 0;
1207 +    ubicom32_v4 = 0;
1208 +  } else if (strcmp (ubicom32_arch_name, "ubicom32v2") == 0) {
1209 +    ubicom32_v3 = 0;
1210 +    ubicom32_v4 = 0;
1211 +  } else if (strcmp (ubicom32_arch_name, "ubicom32v3") == 0) {
1212 +    ubicom32_v3 = 1;
1213 +    ubicom32_v4 = 0;
1214 +  } else if (strcmp (ubicom32_arch_name, "ubicom32v4") == 0) {
1215 +    ubicom32_v3 = 1;
1216 +    ubicom32_v4 = 1;
1217 +  }
1218 +
1219 +  /* There is no single unaligned SI op for PIC code.  Sometimes we
1220 +     need to use ".4byte" and sometimes we need to use ".picptr".
1221 +     See ubicom32_assemble_integer for details.  */
1222 +  if (TARGET_FDPIC)
1223 +    targetm.asm_out.unaligned_op.si = 0;
1224 +}
1225 +
1226 +void
1227 +ubicom32_conditional_register_usage (void)
1228 +{
1229 +  /* If we're using the old ipOS ABI we need to make D10 through D13
1230 +     caller-clobbered.  */
1231 +  if (TARGET_IPOS_ABI)
1232 +    {
1233 +      call_used_regs[D10_REGNUM] = 1;
1234 +      call_used_regs[D11_REGNUM] = 1;
1235 +      call_used_regs[D12_REGNUM] = 1;
1236 +      call_used_regs[D13_REGNUM] = 1;
1237 +    }
1238 +}
1239 +
1240 +/* We have some number of optimizations that don't really work for the Ubicom32
1241 +   architecture so we deal with them here.  */
1242 +
1243 +void
1244 +ubicom32_optimization_options (int level ATTRIBUTE_UNUSED,
1245 +                              int size ATTRIBUTE_UNUSED)
1246 +{
1247 +  /* The tree IVOPTs pass seems to do really bad things for the Ubicom32
1248 +     architecture - it tends to turn things that would happily use pre/post
1249 +     increment/decrement into operations involving unecessary loop
1250 +     indicies.  */
1251 +  flag_ivopts = 0;
1252 +
1253 +  /* We have problems where DSE at the RTL level misses partial stores
1254 +     to the stack.  For now we disable it to avoid this.  */
1255 +  flag_dse = 0;
1256 +}
1257 +
1258 +/* Print operand X using operand code CODE to assembly language output file
1259 +   FILE.  */
1260 +
1261 +void
1262 +ubicom32_print_operand (FILE *file, rtx x, int code)
1263 +{
1264 +  switch (code)
1265 +    {
1266 +    case 'A':
1267 +      /* Identify the correct accumulator to use.  */
1268 +      if (REGNO (x) == ACC0_HI_REGNUM || REGNO (x) == ACC0_LO_REGNUM)
1269 +       fprintf (file, "acc0");
1270 +      else if (REGNO (x) == ACC1_HI_REGNUM || REGNO (x) == ACC1_LO_REGNUM)
1271 +       fprintf (file, "acc1");
1272 +      else
1273 +       abort ();
1274 +      break;
1275 +
1276 +    case 'b':
1277 +    case 'B':
1278 +      {
1279 +       enum machine_mode mode;
1280 +
1281 +       mode = GET_MODE (XEXP (x, 0));
1282 +
1283 +       /* These are normal and reversed branches.  */
1284 +       switch (code == 'b' ? GET_CODE (x) : reverse_condition (GET_CODE (x)))
1285 +         {
1286 +         case NE:
1287 +           fprintf (file, "ne");
1288 +           break;
1289 +
1290 +         case EQ:
1291 +           fprintf (file, "eq");
1292 +           break;
1293 +
1294 +         case GE:
1295 +           if (mode == CCSZNmode || mode == CCWZNmode)
1296 +             fprintf (file, "pl");
1297 +           else
1298 +             fprintf (file, "ge");
1299 +           break;
1300 +
1301 +         case GT:
1302 +           fprintf (file, "gt");
1303 +           break;
1304 +
1305 +         case LE:
1306 +           fprintf (file, "le");
1307 +           break;
1308 +
1309 +         case LT:
1310 +           if (mode == CCSZNmode || mode == CCWZNmode)
1311 +             fprintf (file, "mi");
1312 +           else
1313 +             fprintf (file, "lt");
1314 +           break;
1315 +
1316 +         case GEU:
1317 +           fprintf (file, "cs");
1318 +           break;
1319 +
1320 +         case GTU:
1321 +           fprintf (file, "hi");
1322 +           break;
1323 +
1324 +         case LEU:
1325 +           fprintf (file, "ls");
1326 +           break;
1327 +
1328 +         case LTU:
1329 +           fprintf (file, "cc");
1330 +           break;
1331 +
1332 +         default:
1333 +           abort ();
1334 +         }
1335 +      }
1336 +      break;
1337 +
1338 +    case 'C':
1339 +      /* This is used for the operand to a call instruction;
1340 +        if it's a REG, enclose it in parens, else output
1341 +        the operand normally.  */
1342 +      if (REG_P (x))
1343 +       {
1344 +         fputc ('(', file);
1345 +         ubicom32_print_operand (file, x, 0);
1346 +         fputc (')', file);
1347 +       }
1348 +      else
1349 +       ubicom32_print_operand (file, x, 0);
1350 +      break;
1351 +
1352 +    case 'd':
1353 +      /* Bit operations we need bit numbers. */
1354 +      fprintf (file, "%d", exact_log2 (INTVAL (x)));
1355 +      break;
1356 +
1357 +    case 'D':
1358 +      /* Bit operations we need bit numbers. */
1359 +      fprintf (file, "%d", exact_log2 (~ INTVAL (x)));
1360 +      break;
1361 +
1362 +    case 'E':
1363 +      /* For lea, which we use to add address registers.
1364 +        We don't want the '#' on a constant. */
1365 +      if (CONST_INT_P (x))
1366 +       {
1367 +         fprintf (file, "%ld", INTVAL (x));
1368 +         break;
1369 +       }
1370 +      /* FALL THROUGH */
1371 +
1372 +    default:
1373 +      switch (GET_CODE (x))
1374 +       {
1375 +       case MEM:
1376 +         output_memory_reference_mode = GET_MODE (x);
1377 +         output_address (XEXP (x, 0));
1378 +         break;
1379 +
1380 +       case PLUS:
1381 +         output_address (x);
1382 +         break;
1383 +
1384 +       case REG:
1385 +         fprintf (file, "%s", reg_names[REGNO (x)]);
1386 +         break;
1387 +
1388 +       case SUBREG:
1389 +         fprintf (file, "%s", reg_names[subreg_regno (x)]);
1390 +         break;
1391 +
1392 +       /* This will only be single precision....  */
1393 +       case CONST_DOUBLE:
1394 +         {
1395 +           unsigned long val;
1396 +           REAL_VALUE_TYPE rv;
1397 +
1398 +           REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1399 +           REAL_VALUE_TO_TARGET_SINGLE (rv, val);
1400 +           fprintf (file, "0x%lx", val);
1401 +           break;
1402 +         }
1403 +
1404 +       case CONST_INT:
1405 +       case SYMBOL_REF:
1406 +       case CONST:
1407 +       case LABEL_REF:
1408 +       case CODE_LABEL:
1409 +       case LO_SUM:
1410 +         ubicom32_print_operand_address (file, x);
1411 +         break;
1412 +
1413 +       case HIGH:
1414 +         fprintf (file, "#%%hi(");
1415 +         ubicom32_print_operand_address (file, XEXP (x, 0));
1416 +         fprintf (file, ")");
1417 +         break;
1418 +
1419 +       case UNSPEC:
1420 +         switch (XINT (x, 1))
1421 +           {
1422 +           case UNSPEC_FDPIC_GOT:
1423 +             fprintf (file, "#%%got_lo(");
1424 +             ubicom32_print_operand_address (file, XVECEXP (x, 0, 0));
1425 +             fprintf (file, ")");
1426 +             break;
1427 +
1428 +           case UNSPEC_FDPIC_GOT_FUNCDESC:
1429 +             fprintf (file, "#%%got_funcdesc_lo(");
1430 +             ubicom32_print_operand_address (file, XVECEXP (x, 0, 0));
1431 +             fprintf (file, ")");
1432 +             break;
1433 +
1434 +           default:
1435 +             abort ();
1436 +           }
1437 +          break;
1438 +
1439 +       default:
1440 +         abort ();
1441 +       }
1442 +      break;
1443 +   }
1444 +}
1445 +
1446 +/* Output assembly language output for the address ADDR to FILE.  */
1447 +
1448 +void
1449 +ubicom32_print_operand_address (FILE *file, rtx addr)
1450 +{
1451 +  switch (GET_CODE (addr))
1452 +    {
1453 +    case POST_INC:
1454 +      ubicom32_print_operand_address (file, XEXP (addr, 0));
1455 +      fprintf (file, "%d++", GET_MODE_SIZE (output_memory_reference_mode));
1456 +      break;
1457 +
1458 +    case PRE_INC:
1459 +      fprintf (file, "%d", GET_MODE_SIZE (output_memory_reference_mode));
1460 +      ubicom32_print_operand_address (file, XEXP (addr, 0));
1461 +      fprintf (file, "++");
1462 +      break;
1463 +
1464 +    case POST_DEC:
1465 +      ubicom32_print_operand_address (file, XEXP (addr, 0));
1466 +      fprintf (file, "%d++", -GET_MODE_SIZE (output_memory_reference_mode));
1467 +      break;
1468 +
1469 +    case PRE_DEC:
1470 +      fprintf (file, "%d", -GET_MODE_SIZE (output_memory_reference_mode));
1471 +      ubicom32_print_operand_address (file, XEXP (addr, 0));
1472 +      fprintf (file, "++");
1473 +      break;
1474 +
1475 +    case POST_MODIFY:
1476 +      ubicom32_print_operand_address (file, XEXP (addr, 0));
1477 +      fprintf (file, "%ld++", INTVAL (XEXP (XEXP (addr,1), 1)));
1478 +      break;
1479 +
1480 +    case PRE_MODIFY:
1481 +      fprintf (file, "%ld", INTVAL (XEXP (XEXP (addr,1), 1)));
1482 +      ubicom32_print_operand_address (file, XEXP (addr, 0));
1483 +      fprintf (file, "++");
1484 +      break;
1485 +
1486 +    case REG:
1487 +      fputc ('(', file);
1488 +      fprintf (file, "%s", reg_names[REGNO (addr)]); 
1489 +      fputc (')', file);
1490 +      break;
1491 +
1492 +    case PLUS:
1493 +      {
1494 +       rtx base = XEXP (addr, 0);
1495 +       rtx index = XEXP (addr, 1); 
1496 +
1497 +       /* Switch around addresses of the form index * scaling + base.  */
1498 +       if (! ubicom32_is_base_reg (base, 1))
1499 +         {
1500 +           rtx tmp = base;
1501 +           base = index;
1502 +           index = tmp;
1503 +         }
1504 +
1505 +       if (CONST_INT_P (index)) 
1506 +         {
1507 +           fprintf (file, "%ld", INTVAL (index)); 
1508 +           fputc ('(', file);
1509 +           fputs (reg_names[REGNO (base)], file); 
1510 +         }
1511 +       else if (GET_CODE (index) == MULT
1512 +                || REG_P (index))
1513 +         {
1514 +           if (GET_CODE (index) == MULT)
1515 +             index = XEXP (index, 0);
1516 +           fputc ('(', file);
1517 +           fputs (reg_names[REGNO (base)], file); 
1518 +           fputc (',', file);
1519 +           fputs (reg_names[REGNO (index)], file); 
1520 +         }
1521 +       else 
1522 +         abort (); 
1523 +
1524 +       fputc (')', file);
1525 +       break;
1526 +      }
1527 +
1528 +    case LO_SUM:
1529 +      fprintf (file, "%%lo(");
1530 +      ubicom32_print_operand (file, XEXP (addr, 1), 'L');
1531 +      fprintf (file, ")(");
1532 +      ubicom32_print_operand (file, XEXP (addr, 0), 0);
1533 +      fprintf (file, ")");
1534 +      break;
1535 +
1536 +    case CONST_INT:
1537 +      fputc ('#', file);
1538 +      output_addr_const (file, addr); 
1539 +      break;
1540 +
1541 +    default:
1542 +      output_addr_const (file, addr);
1543 +      break;
1544 +    }
1545 +}
1546 +
1547 +/* X and Y are two things to compare using CODE.  Emit the compare insn and
1548 +   return the rtx for the cc reg in the proper mode.  */
1549 +
1550 +rtx
1551 +ubicom32_gen_compare_reg (enum rtx_code code, rtx x, rtx y)
1552 +{
1553 +  enum machine_mode mode = SELECT_CC_MODE (code, x, y);
1554 +  rtx cc_reg;
1555 +
1556 +  cc_reg = gen_rtx_REG (mode, CC_REGNUM);
1557 +
1558 +  emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
1559 +                         gen_rtx_COMPARE (mode, x, y)));
1560 +
1561 +  return cc_reg;
1562 +}
1563 +
1564 +/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
1565 +   return the mode to be used for the comparison.  */
1566 +
1567 +enum machine_mode
1568 +ubicom32_select_cc_mode (enum rtx_code op, rtx x, rtx y)
1569 +{
1570 +  /* Is this a short compare?  */
1571 +  if (GET_MODE (x) == QImode
1572 +      || GET_MODE (x) == HImode
1573 +      || GET_MODE (y) == QImode
1574 +      || GET_MODE (y) == HImode)
1575 +    {
1576 +      switch (op)
1577 +       {
1578 +       case EQ :
1579 +       case NE :
1580 +         return CCSZmode;
1581 +
1582 +       case GE:
1583 +       case LT:
1584 +         if (y == const0_rtx)
1585 +           return CCSZNmode;
1586 +
1587 +       default :
1588 +         return CCSmode;
1589 +       }
1590 +    }
1591 +
1592 +  /* We have a word compare.  */
1593 +  switch (op)
1594 +    {
1595 +    case EQ :
1596 +    case NE :
1597 +      return CCWZmode;
1598 +
1599 +    case GE :
1600 +    case LT :
1601 +      if (y == const0_rtx)
1602 +       return CCWZNmode;
1603 +
1604 +    default :
1605 +      return CCWmode;
1606 +    }
1607 +}
1608 +
1609 +/* Return TRUE or FALSE depending on whether the first SET in INSN
1610 +   has source and destination with matching CC modes, and that the
1611 +   CC mode is at least as constrained as REQ_MODE.  */
1612 +bool
1613 +ubicom32_match_cc_mode (rtx insn, enum machine_mode req_mode)
1614 +{
1615 +  rtx set;
1616 +  enum machine_mode set_mode;
1617 +
1618 +  set = PATTERN (insn);
1619 +  if (GET_CODE (set) == PARALLEL)
1620 +    set = XVECEXP (set, 0, 0);
1621 +  gcc_assert (GET_CODE (set) == SET);
1622 +  gcc_assert (GET_CODE (SET_SRC (set)) == COMPARE);
1623 +
1624 +  /* SET_MODE is the mode we have in the instruction.  This must either
1625 +     be the same or less restrictive that the required mode REQ_MODE.  */
1626 +  set_mode = GET_MODE (SET_DEST (set));
1627 +
1628 +  switch (req_mode)
1629 +    {
1630 +    case CCSZmode:
1631 +      if (set_mode != CCSZmode)
1632 +       return 0;
1633 +      break;
1634 +
1635 +    case CCSZNmode:
1636 +      if (set_mode != CCSZmode
1637 +         && set_mode != CCSZNmode)
1638 +       return 0;
1639 +      break;
1640 +
1641 +    case CCSmode:
1642 +      if (set_mode != CCSmode
1643 +         && set_mode != CCSZmode
1644 +         && set_mode != CCSZNmode)
1645 +       return 0;
1646 +      break;
1647 +
1648 +    case CCWZmode:
1649 +      if (set_mode != CCWZmode)
1650 +       return 0;
1651 +      break;
1652 +
1653 +    case CCWZNmode:
1654 +      if (set_mode != CCWZmode
1655 +         && set_mode != CCWZNmode)
1656 +       return 0;
1657 +      break;
1658 +
1659 +    case CCWmode:
1660 +      if (set_mode != CCWmode
1661 +         && set_mode != CCWZmode
1662 +         && set_mode != CCWZNmode)
1663 +       return 0;
1664 +      break;
1665 +
1666 +    default:
1667 +      gcc_unreachable ();
1668 +    }
1669 +
1670 +  return (GET_MODE (SET_SRC (set)) == set_mode);
1671 +}
1672 +
1673 +/* Replace the comparison OP0 CODE OP1 by a semantically equivalent one
1674 +   that we can implement more efficiently.  */
1675 +
1676 +void
1677 +ubicom32_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1)
1678 +{
1679 +  /* If we have a REG and a MEM then compare the MEM with the REG and not
1680 +     the other way round.  */
1681 +  if (REG_P (*op0) && MEM_P (*op1))
1682 +    {
1683 +      rtx tem = *op0;
1684 +      *op0 = *op1;
1685 +      *op1 = tem;
1686 +      *code = swap_condition (*code);
1687 +      return;
1688 +    }
1689 +
1690 +  /* If we have a REG and a CONST_INT then we may want to reverse things
1691 +     if the constant can be represented as an "I" constraint.  */
1692 +  if (REG_P (*op0) && CONST_INT_P (*op1) && satisfies_constraint_I (*op1))
1693 +    {
1694 +      rtx tem = *op0;
1695 +      *op0 = *op1;
1696 +      *op1 = tem;
1697 +      *code = swap_condition (*code);
1698 +      return;
1699 +    }
1700 +}
1701 +
1702 +/* Return the fixed registers used for condition codes.  */
1703 +
1704 +static bool
1705 +ubicom32_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
1706 +{
1707 +  *p1 = CC_REGNUM;
1708 +  *p2 = INVALID_REGNUM;
1709
1710 +  return true;
1711 +}
1712 +
1713 +/* If two condition code modes are compatible, return a condition code
1714 +   mode which is compatible with both.  Otherwise, return
1715 +   VOIDmode.  */
1716 +
1717 +static enum machine_mode
1718 +ubicom32_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
1719 +{
1720 +  if (m1 == m2)
1721 +    return m1;
1722 +
1723 +  if (GET_MODE_CLASS (m1) != MODE_CC || GET_MODE_CLASS (m2) != MODE_CC)
1724 +    return VOIDmode;
1725 +
1726 +  switch (m1)
1727 +    {
1728 +    case CCWmode:
1729 +      if (m2 == CCWZNmode || m2 == CCWZmode)
1730 +       return m1;
1731 +
1732 +      return VOIDmode;
1733 +
1734 +    case CCWZNmode:
1735 +      if (m2 == CCWmode)
1736 +       return m2;
1737 +
1738 +      if (m2 == CCWZmode)
1739 +       return m1;
1740 +
1741 +      return VOIDmode;
1742 +
1743 +    case CCWZmode:
1744 +      if (m2 == CCWmode || m2 == CCWZNmode)
1745 +       return m2;
1746 +
1747 +      return VOIDmode;
1748 +
1749 +    case CCSmode:
1750 +      if (m2 == CCSZNmode || m2 == CCSZmode)
1751 +       return m1;
1752 +
1753 +      return VOIDmode;
1754 +
1755 +    case CCSZNmode:
1756 +      if (m2 == CCSmode)
1757 +       return m2;
1758 +
1759 +      if (m2 == CCSZmode)
1760 +       return m1;
1761 +
1762 +      return VOIDmode;
1763 +
1764 +    case CCSZmode:
1765 +      if (m2 == CCSmode || m2 == CCSZNmode)
1766 +       return m2;
1767 +
1768 +      return VOIDmode;
1769 +
1770 +    default:
1771 +      gcc_unreachable ();
1772 +    }
1773 +}
1774 +
1775 +static rtx
1776 +ubicom32_legitimize_fdpic_address_symbol (rtx orig, rtx reg, rtx fdpic_reg)
1777 +{
1778 +  int unspec;
1779 +  rtx got_offs;
1780 +  rtx got_offs_scaled;
1781 +  rtx plus_scaled;
1782 +  rtx tmp;
1783 +  rtx new_rtx;
1784 +
1785 +  gcc_assert (reg != 0);
1786 +
1787 +  if (GET_CODE (orig) == SYMBOL_REF
1788 +      && SYMBOL_REF_FUNCTION_P (orig))
1789 +    unspec = UNSPEC_FDPIC_GOT_FUNCDESC;
1790 +  else
1791 +    unspec = UNSPEC_FDPIC_GOT;
1792 +
1793 +  got_offs = gen_reg_rtx (SImode);
1794 +  tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, orig), unspec);
1795 +  emit_move_insn (got_offs, tmp);
1796 +
1797 +  got_offs_scaled = gen_rtx_MULT (SImode, got_offs, GEN_INT (4));
1798 +  plus_scaled = gen_rtx_PLUS (Pmode, fdpic_reg, got_offs_scaled);
1799 +  new_rtx = gen_const_mem (Pmode, plus_scaled);
1800 +  emit_move_insn (reg, new_rtx);
1801 +
1802 +  return reg;
1803 +}
1804 +
1805 +static rtx
1806 +ubicom32_legitimize_fdpic_address (rtx orig, rtx reg, rtx fdpic_reg)
1807 +{
1808 +  rtx addr = orig;
1809 +  rtx new_rtx = orig;
1810 +
1811 +  if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
1812 +    {
1813 +      rtx base;
1814 +
1815 +      if (GET_CODE (addr) == CONST)
1816 +       {
1817 +         addr = XEXP (addr, 0);
1818 +         gcc_assert (GET_CODE (addr) == PLUS);
1819 +       }
1820 +
1821 +      base = ubicom32_legitimize_fdpic_address_symbol (XEXP (addr, 0), reg, fdpic_reg);
1822 +      return gen_rtx_PLUS (Pmode, base, XEXP (addr, 1));
1823 +    }
1824 +
1825 +  return new_rtx;
1826 +}
1827 +
1828 +/* Code generation.  */
1829 +
1830 +void
1831 +ubicom32_expand_movsi (rtx *operands)
1832 +{
1833 +  if (GET_CODE (operands[1]) == SYMBOL_REF
1834 +      || (GET_CODE (operands[1]) == CONST
1835 +         && GET_CODE (XEXP (operands[1], 0)) == PLUS
1836 +         && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF)
1837 +      || CONSTANT_ADDRESS_P (operands[1]))
1838 +    {
1839 +      if (TARGET_FDPIC)
1840 +       {
1841 +         rtx tmp;
1842 +         rtx fdpic_reg;
1843 +
1844 +         gcc_assert (can_create_pseudo_p ());
1845 +         tmp = gen_reg_rtx (Pmode);
1846 +         fdpic_reg = get_hard_reg_initial_val (SImode, FDPIC_REGNUM);
1847 +         if (GET_CODE (operands[1]) == SYMBOL_REF
1848 +             || GET_CODE (operands[1]) == LABEL_REF)
1849 +           operands[1] = ubicom32_legitimize_fdpic_address_symbol (operands[1], tmp, fdpic_reg);
1850 +         else
1851 +           operands[1] = ubicom32_legitimize_fdpic_address (operands[1], tmp, fdpic_reg);
1852 +       }
1853 +      else
1854 +       {
1855 +         rtx tmp;
1856 +         enum machine_mode mode;
1857 +
1858 +         /* We want to avoid reusing operand 0 if we can because it limits
1859 +            our ability to optimize later.  */
1860 +         tmp = ! can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
1861 +
1862 +         mode = GET_MODE (operands[0]);
1863 +         emit_insn (gen_rtx_SET (VOIDmode, tmp,
1864 +                                 gen_rtx_HIGH (mode, operands[1])));
1865 +         operands[1] = gen_rtx_LO_SUM (mode, tmp, operands[1]);
1866 +         if (can_create_pseudo_p() && ! REG_P (operands[0]))
1867 +           {
1868 +             tmp = gen_reg_rtx (mode);
1869 +             emit_insn (gen_rtx_SET (VOIDmode, tmp, operands[1]));
1870 +             operands[1] = tmp;
1871 +           }
1872 +       }
1873 +    }
1874 +}
1875 +
1876 +/* Emit code for addsi3.  */
1877 +
1878 +void
1879 +ubicom32_expand_addsi3 (rtx *operands)
1880 +{
1881 +  rtx op, clob;
1882 +
1883 +  if (can_create_pseudo_p ())
1884 +    {
1885 +      /* If we have a non-data reg for operand 1 then prefer that over
1886 +         a CONST_INT in operand 2.  */
1887 +      if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
1888 +         && CONST_INT_P (operands[2]))
1889 +       operands[2] = copy_to_mode_reg (SImode, operands[2]);
1890 +
1891 +      if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
1892 +       operands[2] = copy_to_mode_reg (SImode, operands[2]);
1893 +    }
1894 +
1895 +  /* Emit the instruction.  */
1896 +
1897 +  op = gen_rtx_SET (VOIDmode, operands[0],
1898 +                   gen_rtx_PLUS (SImode, operands[1], operands[2]));
1899 +
1900 +  if (! can_create_pseudo_p ())
1901 +    {
1902 +      /* Reload doesn't know about the flags register, and doesn't know that
1903 +         it doesn't want to clobber it.  We can only do this with PLUS.  */
1904 +      emit_insn (op);
1905 +    }
1906 +  else
1907 +    {
1908 +      clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM));
1909 +      emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
1910 +    }
1911 +}
1912 +
1913 +/* Emit code for mulsi3.  Return 1 if we have generated all the code
1914 +   necessary to do the multiplication.  */
1915 +
1916 +int
1917 +ubicom32_emit_mult_sequence (rtx *operands)
1918 +{
1919 +  if (! ubicom32_v4)
1920 +    {
1921 +      rtx a1, a1_1, a2;
1922 +      rtx b1, b1_1, b2;
1923 +      rtx mac_lo_rtx;
1924 +      rtx t1, t2, t3;
1925 +
1926 +      /* Give up if we cannot create new pseudos.  */
1927 +      if (!can_create_pseudo_p())
1928 +       return 0;
1929 +
1930 +      /* Synthesize 32-bit multiplication using 16-bit operations:
1931 +     
1932 +        a1 = highpart (a)
1933 +        a2 = lowpart (a)
1934 +
1935 +        b1 = highpart (b)
1936 +        b2 = lowpart (b)
1937 +
1938 +        c = (a1 * b1) << 32 + (a1 * b2) << 16 + (a2 * b1) << 16 + a2 * b2
1939 +          =        0        + (a1 * b2) << 16 + (a2 * b1) << 16 + a2 * b2
1940 +                              ^^^^^^^^^^^^^^^   ^^^^^^^^^^^^^^^   ^^^^^^^
1941 +                                  Signed             Signed      Unsigned  */
1942 +
1943 +      if (!ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])))
1944 +       {
1945 +         rtx op1;
1946 +
1947 +         op1 = gen_reg_rtx (SImode);
1948 +         emit_move_insn (op1, operands[1]);
1949 +         operands[1] = op1;
1950 +       }
1951 +
1952 +      if (!ubicom32_data_register_operand (operands[2], GET_MODE (operands[2])))
1953 +       {
1954 +         rtx op2;
1955 +
1956 +         op2 = gen_reg_rtx (SImode);
1957 +         emit_move_insn (op2, operands[2]);
1958 +         operands[2] = op2;
1959 +       }
1960 +
1961 +      /* a1 = highpart (a)  */
1962 +      a1 = gen_reg_rtx (HImode);
1963 +      a1_1 = gen_reg_rtx (SImode);
1964 +      emit_insn (gen_ashrsi3 (a1_1, operands[1], GEN_INT (16)));
1965 +      emit_move_insn (a1, gen_lowpart (HImode, a1_1));
1966 +
1967 +      /* a2 = lowpart (a)  */
1968 +      a2 = gen_reg_rtx (HImode);
1969 +      emit_move_insn (a2, gen_lowpart (HImode, operands[1]));
1970 +
1971 +      /* b1 = highpart (b)  */
1972 +      b1 = gen_reg_rtx (HImode);
1973 +      b1_1 = gen_reg_rtx (SImode);
1974 +      emit_insn (gen_ashrsi3 (b1_1, operands[2], GEN_INT (16)));
1975 +      emit_move_insn (b1, gen_lowpart (HImode, b1_1));
1976 +
1977 +      /* b2 = lowpart (b)  */
1978 +      b2 = gen_reg_rtx (HImode);
1979 +      emit_move_insn (b2, gen_lowpart (HImode, operands[2]));
1980 +
1981 +      /* t1 = (a1 * b2) << 16  */
1982 +      t1 = gen_reg_rtx (SImode);
1983 +      mac_lo_rtx = gen_rtx_REG (SImode, ACC0_LO_REGNUM);
1984 +      emit_insn (gen_mulhisi3 (mac_lo_rtx, a1, b2));
1985 +      emit_insn (gen_ashlsi3 (t1, mac_lo_rtx, GEN_INT (16)));
1986 +
1987 +      /* t2 = (a2 * b1) << 16  */
1988 +      t2 = gen_reg_rtx (SImode);
1989 +      emit_insn (gen_mulhisi3 (mac_lo_rtx, a2, b1));
1990 +      emit_insn (gen_ashlsi3 (t2, mac_lo_rtx, GEN_INT (16)));
1991 +
1992 +      /* mac_lo = a2 * b2  */
1993 +      emit_insn (gen_umulhisi3 (mac_lo_rtx, a2, b2));
1994 +
1995 +      /* t3 = t1 + t2  */
1996 +      t3 = gen_reg_rtx (SImode);
1997 +      emit_insn (gen_addsi3 (t3, t1, t2));
1998 +
1999 +      /* c = t3 + mac_lo_rtx  */
2000 +      emit_insn (gen_addsi3 (operands[0], mac_lo_rtx, t3));
2001 +
2002 +      return 1;
2003 +    }
2004 +  else
2005 +    {
2006 +      rtx acc_rtx;
2007 +
2008 +      /* Give up if we cannot create new pseudos.  */
2009 +      if (!can_create_pseudo_p())
2010 +       return 0;
2011 +
2012 +      if (!ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])))
2013 +        {
2014 +         rtx op1;
2015 +
2016 +         op1 = gen_reg_rtx (SImode);
2017 +         emit_move_insn (op1, operands[1]);
2018 +         operands[1] = op1;
2019 +       }
2020 +
2021 +      if (!ubicom32_data_register_operand (operands[2], GET_MODE (operands[2])))
2022 +       {
2023 +         rtx op2;
2024 +
2025 +         op2 = gen_reg_rtx (SImode);
2026 +         emit_move_insn (op2, operands[2]);
2027 +         operands[2] = op2;
2028 +       }
2029 +
2030 +      acc_rtx = gen_reg_rtx (DImode);
2031 +      emit_insn (gen_umulsidi3 (acc_rtx, operands[1], operands[2]));
2032 +      emit_move_insn (operands[0], gen_lowpart (SImode, acc_rtx));
2033 +
2034 +      return 1;
2035 +    }
2036 +}
2037 +
2038 +/* Move the integer value VAL into OPERANDS[0].  */
2039 +
2040 +void
2041 +ubicom32_emit_move_const_int (rtx dest, rtx imm)
2042 +{
2043 +  rtx xoperands[2];
2044 +  
2045 +  xoperands[0] = dest;
2046 +  xoperands[1] = imm;
2047 +
2048 +  /* Treat mem destinations separately.  Values must be explicitly sign
2049 +     extended.  */
2050 +  if (MEM_P (dest))
2051 +    {
2052 +      rtx low_hword_mem;
2053 +      rtx low_hword_addr;
2054 +
2055 +      /* Emit shorter sequence for signed 7-bit quantities.  */
2056 +      if (satisfies_constraint_I (imm))
2057 +       {
2058 +          output_asm_insn ("move.4\t%0, %1", xoperands);
2059 +          return;
2060 +       }
2061 +
2062 +      /* Special case for pushing constants.  */
2063 +      if (GET_CODE (XEXP (dest, 0)) == PRE_DEC
2064 +         && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx)
2065 +       {
2066 +         output_asm_insn ("movei\t-4(sp)++, #%%hi(%E1)", xoperands);
2067 +         output_asm_insn ("movei\t2(sp), #%%lo(%E1)", xoperands);
2068 +         return;
2069 +       }
2070 +
2071 +      /* See if we can add 2 to the original address.  This is only
2072 +        possible if the original address is of the form REG or
2073 +        REG+const.  */
2074 +      low_hword_addr = plus_constant (XEXP (dest, 0), 2);
2075 +      if (ubicom32_legitimate_address_p (HImode, low_hword_addr, 1))
2076 +       {
2077 +         low_hword_mem = gen_rtx_MEM (HImode, low_hword_addr);
2078 +         MEM_COPY_ATTRIBUTES (low_hword_mem, dest);
2079 +         output_asm_insn ("movei\t%0, #%%hi(%E1)", xoperands);
2080 +         xoperands[0] = low_hword_mem;
2081 +         output_asm_insn ("movei\t%0, #%%lo(%E1)", xoperands);
2082 +         return;
2083 +       }
2084 +
2085 +      /* The original address is too complex.  We need to use a
2086 +        scratch memory by (sp) and move that to the original
2087 +        destination.  */
2088 +      if (! reg_mentioned_p (stack_pointer_rtx, dest))
2089 +       {
2090 +         output_asm_insn ("movei\t-4(sp)++, #%%hi(%E1)", xoperands);
2091 +         output_asm_insn ("movei\t2(sp), #%%lo(%E1)", xoperands);
2092 +         output_asm_insn ("move.4\t%0, (sp)4++", xoperands);
2093 +         return;
2094 +       }
2095 +
2096 +      /* Our address mentions the stack pointer so we need to
2097 +        use our scratch data register here as well as scratch
2098 +        memory.  */
2099 +      output_asm_insn ("movei\t-4(sp)++, #%%hi(%E1)", xoperands);
2100 +      output_asm_insn ("movei\t2(sp), #%%lo(%E1)", xoperands);
2101 +      output_asm_insn ("move.4\td15, (sp)4++", xoperands);
2102 +      output_asm_insn ("move.4\t%0, d15", xoperands);
2103 +      return;
2104 +    }
2105 +
2106 +  /* Move into registers are zero extended by default.  */
2107 +  if (! REG_P (dest))
2108 +    abort ();
2109 +
2110 +  if (satisfies_constraint_N (imm))
2111 +    {
2112 +      output_asm_insn ("movei\t%0, %1", xoperands);
2113 +      return;
2114 +    }
2115 +
2116 +  if (INTVAL (xoperands[1]) >= 0xff80
2117 +      && INTVAL (xoperands[1]) < 0x10000)
2118 +    {
2119 +      xoperands[1] = GEN_INT (INTVAL (xoperands[1]) - 0x10000);
2120 +      output_asm_insn ("move.2\t%0, %1", xoperands);
2121 +      return;
2122 +    }
2123 +
2124 +  if ((REGNO_REG_CLASS (REGNO (xoperands[0])) == ADDRESS_REGS
2125 +       || REGNO_REG_CLASS (REGNO (xoperands[0])) == FDPIC_REG)
2126 +      && ((INTVAL (xoperands[1]) & 0x80000000) == 0))
2127 +    {
2128 +      output_asm_insn ("moveai\t%0, #%%hi(%E1)", xoperands);
2129 +      if ((INTVAL (xoperands[1]) & 0x7f) != 0)
2130 +       output_asm_insn ("lea.1\t%0, %%lo(%E1)(%0)", xoperands);
2131 +      return;
2132 +    }
2133 +
2134 +  if ((INTVAL (xoperands[1]) & 0xffff0000) == 0)
2135 +    {
2136 +      output_asm_insn ("movei\t%0, #%%lo(%E1)", xoperands);
2137 +      output_asm_insn ("move.2\t%0, %0", xoperands);
2138 +      return;
2139 +    }
2140 +
2141 +  /* This is very expensive.  The constant is so large that we
2142 +     need to use the stack to do the load.  */
2143 +  output_asm_insn ("movei\t-4(sp)++, #%%hi(%E1)", xoperands);
2144 +  output_asm_insn ("movei\t2(sp), #%%lo(%E1)", xoperands);
2145 +  output_asm_insn ("move.4\t%0, (sp)4++", xoperands);
2146 +}
2147 +
2148 +/* Stack layout. Prologue/Epilogue.  */
2149 +
2150 +static int save_regs_size;
2151 +
2152 +static void 
2153 +ubicom32_layout_frame (void)
2154 +{
2155 +  int regno;
2156 +  
2157 +  memset ((char *) &save_regs[0], 0, sizeof (save_regs));
2158 +  nregs = 0;
2159 +  frame_size = get_frame_size ();
2160 +
2161 +  if (frame_pointer_needed || df_regs_ever_live_p (FRAME_POINTER_REGNUM))
2162 +    {
2163 +      save_regs[FRAME_POINTER_REGNUM] = 1;
2164 +      ++nregs;
2165 +    }
2166 +
2167 +  if (current_function_is_leaf && ! df_regs_ever_live_p (LINK_REGNO))
2168 +    ubicom32_can_use_calli_to_ret = 1;
2169 +  else
2170 +    {
2171 +      ubicom32_can_use_calli_to_ret = 0;
2172 +      save_regs[LINK_REGNO] = 1;
2173 +      ++nregs;
2174 +    }
2175 +
2176 +  /* Figure out which register(s) needs to be saved.  */
2177 +  for (regno = 0; regno <= LAST_ADDRESS_REGNUM; regno++)
2178 +       if (df_regs_ever_live_p(regno)
2179 +       && ! call_used_regs[regno]
2180 +       && ! fixed_regs[regno]
2181 +       && ! save_regs[regno])
2182 +    {
2183 +      save_regs[regno] = 1;
2184 +      ++nregs;
2185 +    }
2186 +
2187 +  save_regs_size = 4 * nregs;
2188 +}
2189 +
2190 +static void
2191 +ubicom32_emit_add_movsi (int regno, int adj)
2192 +{
2193 +  rtx x;
2194 +  rtx reg = gen_rtx_REG (SImode, regno);
2195 +
2196 +  adj += 4;
2197 +  if (adj > 8 * 4) 
2198 +    {
2199 +      x = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
2200 +                                GEN_INT (-adj)));
2201 +      RTX_FRAME_RELATED_P (x) = 1;
2202 +      x = emit_move_insn (gen_rtx_MEM (SImode, stack_pointer_rtx), reg);
2203 +    }
2204 +  else
2205 +    {
2206 +      rtx addr = gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx,
2207 +                                    gen_rtx_PLUS (Pmode, stack_pointer_rtx,
2208 +                                                  GEN_INT (-adj)));
2209 +      x = emit_move_insn (gen_rtx_MEM (SImode, addr), reg);
2210 +    }
2211 +  RTX_FRAME_RELATED_P (x) = 1;      
2212 +}
2213 +
2214 +void
2215 +ubicom32_expand_prologue (void)
2216 +{
2217 +  rtx x;
2218 +  int regno;
2219 +  int outgoing_args_size = crtl->outgoing_args_size;
2220 +  int adj;
2221 +
2222 +  if (ubicom32_naked_function_p ())
2223 +    return;
2224 +
2225 +  ubicom32_builtin_saveregs ();
2226 +  
2227 +  ubicom32_layout_frame ();
2228 +  adj = (outgoing_args_size + get_frame_size () + save_regs_size
2229 +        + crtl->args.pretend_args_size);
2230 +  
2231 +  if (!adj)
2232 +    ;
2233 +  else if (outgoing_args_size + save_regs_size < 508
2234 +          && get_frame_size () + save_regs_size > 508)
2235 +    {
2236 +      int i = 0;
2237 +      x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
2238 +                     GEN_INT (-adj));
2239 +      x = emit_insn (x);
2240 +      RTX_FRAME_RELATED_P (x) = 1;
2241 +
2242 +      for (regno = LAST_ADDRESS_REGNUM; regno >= 0; --regno)
2243 +       if (save_regs[regno] && regno != LINK_REGNO)
2244 +         {
2245 +           x = gen_rtx_MEM (SImode,
2246 +                            gen_rtx_PLUS (Pmode,
2247 +                                          stack_pointer_rtx,
2248 +                                          GEN_INT (i * 4 + outgoing_args_size)));
2249 +           x = emit_move_insn (x, gen_rtx_REG (SImode, regno));
2250 +           RTX_FRAME_RELATED_P (x) = 1;
2251 +           ++i;
2252 +         }
2253 +      if (save_regs[LINK_REGNO])
2254 +       {
2255 +         x = gen_rtx_MEM (SImode,
2256 +                          gen_rtx_PLUS (Pmode,
2257 +                                        stack_pointer_rtx,
2258 +                                        GEN_INT (i * 4 + outgoing_args_size)));
2259 +         x = emit_move_insn (x, gen_rtx_REG (SImode, LINK_REGNO));
2260 +         RTX_FRAME_RELATED_P (x) = 1;
2261 +       }
2262 +    }
2263 +  else
2264 +    {
2265 +      int regno;
2266 +      int adj = get_frame_size () + crtl->args.pretend_args_size;
2267 +      int i = 0;
2268 +
2269 +      if (save_regs[LINK_REGNO])
2270 +       {
2271 +         ubicom32_emit_add_movsi (LINK_REGNO, adj);
2272 +         ++i;
2273 +       }
2274 +      
2275 +      for (regno = 0; regno <= LAST_ADDRESS_REGNUM; ++regno)
2276 +       if (save_regs[regno] && regno != LINK_REGNO)
2277 +         {
2278 +           if (i)
2279 +             {
2280 +               rtx mem = gen_rtx_MEM (SImode,
2281 +                                      gen_rtx_PRE_DEC (Pmode,
2282 +                                                       stack_pointer_rtx));
2283 +               x = emit_move_insn (mem, gen_rtx_REG (SImode, regno));
2284 +               RTX_FRAME_RELATED_P (x) = 1;
2285 +             }
2286 +           else
2287 +             ubicom32_emit_add_movsi (regno, adj);
2288 +           ++i;
2289 +         }
2290 +      
2291 +      if (outgoing_args_size || (!i && adj))
2292 +       {
2293 +         x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
2294 +                         GEN_INT (-outgoing_args_size - (i ? 0 : adj)));
2295 +         x = emit_insn (x);
2296 +         RTX_FRAME_RELATED_P (x) = 1;
2297 +       }
2298 +    }
2299 +
2300 +  if (frame_pointer_needed)
2301 +    {
2302 +      int fp_adj = save_regs_size + outgoing_args_size;
2303 +      x = gen_addsi3 (frame_pointer_rtx, stack_pointer_rtx,
2304 +                     GEN_INT (fp_adj));
2305 +      x = emit_insn (x);
2306 +      RTX_FRAME_RELATED_P (x) = 1;
2307 +    }
2308 +}
2309 +
2310 +void
2311 +ubicom32_expand_epilogue (void)
2312 +{
2313 +  rtx x;
2314 +  int regno;
2315 +  int outgoing_args_size = crtl->outgoing_args_size;
2316 +  int adj;
2317 +  int i;
2318 +
2319 +  if (ubicom32_naked_function_p ())
2320 +    {
2321 +      emit_jump_insn (gen_return_internal (gen_rtx_REG (SImode,
2322 +                                                       LINK_REGNO)));
2323 +      return;
2324 +    }
2325 +
2326 +  if (cfun->calls_alloca)
2327 +    {
2328 +      x = gen_addsi3 (stack_pointer_rtx, frame_pointer_rtx,
2329 +                     GEN_INT (-save_regs_size));
2330 +      emit_insn (x);
2331 +      outgoing_args_size = 0;
2332 +    }
2333 +  
2334 +  if (outgoing_args_size)
2335 +    {
2336 +      x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
2337 +                     GEN_INT (outgoing_args_size));
2338 +      emit_insn (x);
2339 +    }
2340 +
2341 +  i = 0;
2342 +  for (regno = LAST_ADDRESS_REGNUM; regno >= 0; --regno)
2343 +    if (save_regs[regno] && regno != LINK_REGNO)
2344 +      {
2345 +       x = gen_rtx_MEM (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
2346 +       emit_move_insn (gen_rtx_REG (SImode, regno), x);
2347 +       ++i;
2348 +      }
2349 +
2350 +  /* Do we have to adjust the stack after we've finished restoring regs?  */
2351 +  adj = get_frame_size() + crtl->args.pretend_args_size;
2352 +  if (cfun->stdarg)
2353 +    adj += UBICOM32_FUNCTION_ARG_REGS * UNITS_PER_WORD;
2354
2355 +#if 0
2356 +  if (crtl->calls_eh_return && 0)
2357 +    {
2358 +      if (save_regs[LINK_REGNO])
2359 +        {
2360 +          x = gen_rtx_MEM (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
2361 +          emit_move_insn (gen_rtx_REG (SImode, LINK_REGNO), x);
2362 +        }
2363 +
2364 +      if (adj)
2365 +        {
2366 +          x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
2367 +                         GEN_INT (adj));
2368 +          x = emit_insn (x);
2369 +        }
2370 +
2371 +      /* Perform the additional bump for __throw.  */
2372 +      emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
2373 +                            EH_RETURN_STACKADJ_RTX));
2374 +      emit_jump_insn (gen_eh_return_internal ());
2375 +      return;
2376 +    }
2377 +#endif
2378 +
2379 +  if (save_regs[LINK_REGNO])
2380 +    {
2381 +      if (adj >= 4 && adj <= (6 * 4))
2382 +        {
2383 +         x = GEN_INT (adj + 4);
2384 +          emit_jump_insn (gen_return_from_post_modify_sp (x));
2385 +         return;
2386 +        }
2387 +
2388 +      if (adj == 0)
2389 +       {
2390 +          x = gen_rtx_MEM (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
2391 +          emit_jump_insn (gen_return_internal (x));
2392 +          return;
2393 +       }
2394 +
2395 +      x = gen_rtx_MEM (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
2396 +      emit_move_insn (gen_rtx_REG (SImode, LINK_REGNO), x);
2397 +    }
2398 +
2399 +  if (adj)
2400 +    {
2401 +      x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
2402 +                     GEN_INT (adj));
2403 +      x = emit_insn (x);
2404 +      adj = 0;
2405 +    }
2406 +
2407 +  /* Given that we've just done all the hard work here we may as well use
2408 +     a calli to return.  */
2409 +  ubicom32_can_use_calli_to_ret = 1;
2410 +  emit_jump_insn (gen_return_internal (gen_rtx_REG (SImode, LINK_REGNO)));
2411 +}
2412 +
2413 +void
2414 +ubicom32_expand_call_fdpic (rtx *operands)
2415 +{
2416 +  rtx c;
2417 +  rtx addr;
2418 +  rtx fdpic_reg = get_hard_reg_initial_val (SImode, FDPIC_REGNUM);
2419 +
2420 +  addr = XEXP (operands[0], 0);
2421 +
2422 +  c = gen_call_fdpic (addr, operands[1], fdpic_reg);
2423 +  emit_call_insn (c);
2424 +}
2425 +
2426 +void
2427 +ubicom32_expand_call_value_fdpic (rtx *operands)
2428 +{
2429 +  rtx c;
2430 +  rtx addr;
2431 +  rtx fdpic_reg = get_hard_reg_initial_val (SImode, FDPIC_REGNUM);
2432 +
2433 +  addr = XEXP (operands[1], 0);
2434 +
2435 +  c = gen_call_value_fdpic (operands[0], addr, operands[2], fdpic_reg);
2436 +  emit_call_insn (c);
2437 +}
2438 +
2439 +void
2440 +ubicom32_expand_eh_return (rtx *operands)
2441 +{
2442 +  if (REG_P (operands[0])
2443 +      || REGNO (operands[0]) != EH_RETURN_STACKADJ_REGNO)
2444 +    {
2445 +      rtx sp = EH_RETURN_STACKADJ_RTX;
2446 +      emit_move_insn (sp, operands[0]);
2447 +      operands[0] = sp;
2448 +    }
2449 +
2450 +  if (REG_P (operands[1])
2451 +      || REGNO (operands[1]) != EH_RETURN_HANDLER_REGNO)
2452 +    {
2453 +      rtx ra = EH_RETURN_HANDLER_RTX;
2454 +      emit_move_insn (ra, operands[1]);
2455 +      operands[1] = ra;
2456 +    }
2457 +}
2458 +
2459 +/* Compute the offsets between eliminable registers.  */
2460 +
2461 +int
2462 +ubicom32_initial_elimination_offset (int from, int to)
2463 +{
2464 +  ubicom32_layout_frame ();
2465 +  if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
2466 +    return save_regs_size + crtl->outgoing_args_size;
2467 +
2468 +  if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
2469 +    return get_frame_size ()/* + save_regs_size */;
2470 +
2471 +  if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
2472 +    return get_frame_size ()
2473 +          + crtl->outgoing_args_size
2474 +          + save_regs_size;
2475 +
2476 +  return 0;
2477 +}
2478 +
2479 +/* Return 1 if it is appropriate to emit `ret' instructions in the
2480 +   body of a function.  Do this only if the epilogue is simple, needing a
2481 +   couple of insns.  Prior to reloading, we can't tell how many registers
2482 +   must be saved, so return 0 then.  Return 0 if there is no frame
2483 +   marker to de-allocate.
2484 +
2485 +   If NON_SAVING_SETJMP is defined and true, then it is not possible
2486 +   for the epilogue to be simple, so return 0.  This is a special case
2487 +   since NON_SAVING_SETJMP will not cause regs_ever_live to change
2488 +   until final, but jump_optimize may need to know sooner if a
2489 +   `return' is OK.  */
2490 +
2491 +int
2492 +ubicom32_can_use_return_insn_p (void)
2493 +{
2494 +  if (! reload_completed || frame_pointer_needed)
2495 +    return 0;
2496 +
2497 +  return 1;
2498 +}
2499 +
2500 +/* Attributes and CC handling.  */
2501 +
2502 +/* Handle an attribute requiring a FUNCTION_DECL; arguments as in
2503 +   struct attribute_spec.handler.  */
2504 +static tree
2505 +ubicom32_handle_fndecl_attribute (tree *node, tree name,
2506 +                             tree args ATTRIBUTE_UNUSED,
2507 +                             int flags ATTRIBUTE_UNUSED,
2508 +                             bool *no_add_attrs)
2509 +{
2510 +  if (TREE_CODE (*node) != FUNCTION_DECL)
2511 +    {
2512 +      warning ("'%s' attribute only applies to functions",
2513 +              IDENTIFIER_POINTER (name));
2514 +      *no_add_attrs = true;
2515 +    }
2516 +
2517 +  return NULL_TREE;
2518 +}
2519 +
2520 +/* A C expression that places additional restrictions on the register class to
2521 +   use when it is necessary to copy value X into a register in class CLASS.
2522 +   The value is a register class; perhaps CLASS, or perhaps another, smaller
2523 +   class.  On many machines, the following definition is safe:
2524 +
2525 +        #define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS
2526 +
2527 +   Sometimes returning a more restrictive class makes better code.  For
2528 +   example, on the 68000, when X is an integer constant that is in range for a
2529 +   `moveq' instruction, the value of this macro is always `DATA_REGS' as long
2530 +   as CLASS includes the data registers.  Requiring a data register guarantees
2531 +   that a `moveq' will be used.
2532 +
2533 +   If X is a `const_double', by returning `NO_REGS' you can force X into a
2534 +   memory constant.  This is useful on certain machines where immediate
2535 +   floating values cannot be loaded into certain kinds of registers.  */
2536 +
2537 +enum reg_class
2538 +ubicom32_preferred_reload_class (rtx x, enum reg_class class)
2539 +{
2540 +  /* If a symbolic constant, HIGH or a PLUS is reloaded,
2541 +     it is most likely being used as an address, so
2542 +     prefer ADDRESS_REGS.  If 'class' is not a superset
2543 +     of ADDRESS_REGS, e.g. DATA_REGS, then reject this reload.  */
2544 +  if (GET_CODE (x) == PLUS
2545 +      || GET_CODE (x) == HIGH
2546 +      || GET_CODE (x) == LABEL_REF
2547 +      || GET_CODE (x) == SYMBOL_REF
2548 +      || GET_CODE (x) == CONST)
2549 +    {
2550 +      if (reg_class_subset_p (ALL_ADDRESS_REGS, class))
2551 +       return ALL_ADDRESS_REGS;
2552 +
2553 +      return NO_REGS;
2554 +    }
2555 +
2556 +  return class;
2557 +}
2558 +
2559 +/* Function arguments and varargs.  */
2560 +
2561 +int
2562 +ubicom32_reg_parm_stack_space (tree fndecl)
2563 +{
2564 +  return 0;
2565 +  
2566 +  if (fndecl
2567 +      && TYPE_ARG_TYPES (TREE_TYPE (fndecl)) != 0
2568 +      && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))) 
2569 +         != void_type_node))
2570 +    return UBICOM32_FUNCTION_ARG_REGS * UNITS_PER_WORD;
2571 +
2572 +  return 0;
2573 +}
2574 +
2575 +/* Flush the argument registers to the stack for a stdarg function;
2576 +   return the new argument pointer.  */
2577 +
2578 +rtx
2579 +ubicom32_builtin_saveregs (void)
2580 +{
2581 +  int regno;
2582 +  
2583 +  if (! cfun->stdarg)
2584 +    return 0;
2585 +  
2586 +  for (regno = UBICOM32_FUNCTION_ARG_REGS - 1; regno >= 0; --regno)
2587 +    emit_move_insn (gen_rtx_MEM (SImode,
2588 +                                gen_rtx_PRE_DEC (SImode,
2589 +                                                 stack_pointer_rtx)),
2590 +                   gen_rtx_REG (SImode, regno));
2591 +  
2592 +  return stack_pointer_rtx;
2593 +}
2594 +
2595 +void
2596 +ubicom32_va_start (tree valist, rtx nextarg)
2597 +{
2598 +  std_expand_builtin_va_start (valist, nextarg);
2599 +}
2600 +
2601 +rtx
2602 +ubicom32_va_arg (tree valist, tree type)
2603 +{
2604 +  HOST_WIDE_INT size, rsize;
2605 +  tree addr, incr, tmp;
2606 +  rtx addr_rtx;
2607 +  int indirect = 0;
2608 +
2609 +  /* Round up sizeof(type) to a word.  */
2610 +  size = int_size_in_bytes (type);
2611 +  rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
2612 +
2613 +  /* Large types are passed by reference.  */
2614 +  if (size > 8)
2615 +    {
2616 +      indirect = 1;
2617 +      size = rsize = UNITS_PER_WORD;
2618 +    }
2619 +
2620 +  incr = valist;
2621 +  addr = incr = save_expr (incr);
2622 +
2623 +  /* FIXME Nat's version - is it correct?  */
2624 +  tmp = fold_convert (ptr_type_node, size_int (rsize));
2625 +  tmp = build2 (PLUS_EXPR, ptr_type_node, incr, tmp);
2626 +  incr = fold (tmp);
2627 +
2628 +  /* FIXME Nat's version - is it correct? */
2629 +  incr = build2 (MODIFY_EXPR, ptr_type_node, valist, incr);
2630 +
2631 +  TREE_SIDE_EFFECTS (incr) = 1;
2632 +  expand_expr (incr, const0_rtx, VOIDmode, EXPAND_NORMAL);
2633 +
2634 +  addr_rtx = expand_expr (addr, NULL, Pmode, EXPAND_NORMAL);
2635 +
2636 +  if (size < UNITS_PER_WORD)
2637 +    emit_insn (gen_addsi3 (addr_rtx, addr_rtx,
2638 +                          GEN_INT (UNITS_PER_WORD - size)));
2639 +
2640 +  if (indirect)
2641 +    {
2642 +      addr_rtx = force_reg (Pmode, addr_rtx);
2643 +      addr_rtx = gen_rtx_MEM (Pmode, addr_rtx);
2644 +      set_mem_alias_set (addr_rtx, get_varargs_alias_set ());
2645 +    }
2646 +
2647 +  return addr_rtx;
2648 +}
2649 +
2650 +void
2651 +init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
2652 +                     int indirect ATTRIBUTE_UNUSED)
2653 +{
2654 +  cum->nbytes = 0;
2655 +
2656 +  if (!libname)
2657 +    {
2658 +      cum->stdarg = (TYPE_ARG_TYPES (fntype) != 0
2659 +                    && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2660 +                        != void_type_node));
2661 +    }
2662 +}
2663 +
2664 +/* Return an RTX to represent where a value in mode MODE will be passed
2665 +   to a function.  If the result is 0, the argument will be pushed.  */
2666 +
2667 +rtx
2668 +function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
2669 +             int named ATTRIBUTE_UNUSED)
2670 +{
2671 +  rtx result = 0;
2672 +  int size, align;
2673 +  int nregs = UBICOM32_FUNCTION_ARG_REGS;
2674 +  
2675 +  /* Figure out the size of the object to be passed.  */
2676 +  if (mode == BLKmode)
2677 +    size = int_size_in_bytes (type);
2678 +  else
2679 +    size = GET_MODE_SIZE (mode);
2680 +
2681 +  /* Figure out the alignment of the object to be passed.  */
2682 +  align = size;
2683 +
2684 +  cum->nbytes = (cum->nbytes + 3) & ~3;
2685 +
2686 +  /* Don't pass this arg via a register if all the argument registers
2687 +     are used up.  */
2688 +  if (cum->nbytes >= nregs * UNITS_PER_WORD)
2689 +    return 0;
2690 +
2691 +  /* Don't pass this arg via a register if it would be split between
2692 +     registers and memory.  */
2693 +  result = gen_rtx_REG (mode, cum->nbytes / UNITS_PER_WORD);
2694 +
2695 +  return result;
2696 +}
2697 +
2698 +rtx
2699 +function_incoming_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
2700 +                      int named ATTRIBUTE_UNUSED)
2701 +{
2702 +  if (cfun->stdarg)
2703 +    return 0;
2704 +
2705 +  return function_arg (cum, mode, type, named);
2706 +}
2707 +
2708 +
2709 +/* Implement hook TARGET_ARG_PARTIAL_BYTES.
2710 +
2711 +   Returns the number of bytes at the beginning of an argument that
2712 +   must be put in registers.  The value must be zero for arguments
2713 +   that are passed entirely in registers or that are entirely pushed
2714 +   on the stack.  */
2715 +static int
2716 +ubicom32_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
2717 +                           tree type, bool named ATTRIBUTE_UNUSED)
2718 +{
2719 +  int size, diff;
2720 +
2721 +  int nregs = UBICOM32_FUNCTION_ARG_REGS;
2722 +
2723 +  /* round up to full word */
2724 +  cum->nbytes = (cum->nbytes + 3) & ~3;
2725 +
2726 +  if (targetm.calls.pass_by_reference (cum, mode, type, named))
2727 +      return 0;
2728 +
2729 +  /* number of bytes left in registers */
2730 +  diff = nregs*UNITS_PER_WORD - cum->nbytes;
2731 +
2732 +  /* regs all used up */
2733 +  if (diff <= 0)
2734 +    return 0;
2735 +
2736 +  /* Figure out the size of the object to be passed.  */
2737 +  if (mode == BLKmode)
2738 +    size = int_size_in_bytes (type);
2739 +  else
2740 +    size = GET_MODE_SIZE (mode);
2741 +
2742 +  /* enough space left in regs for size */
2743 +  if (size <= diff)
2744 +    return 0;
2745 +
2746 +  /* put diff bytes in regs and rest on stack */
2747 +  return diff;
2748 +
2749 +}
2750 +
2751 +static bool
2752 +ubicom32_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
2753 +                           enum machine_mode mode, const_tree type,
2754 +                           bool named ATTRIBUTE_UNUSED)
2755 +{
2756 +  int size;
2757 +
2758 +  if (type)
2759 +    size = int_size_in_bytes (type);
2760 +  else
2761 +    size = GET_MODE_SIZE (mode);
2762 +
2763 +  return size <= 0 || size > 8;
2764 +}
2765 +
2766 +static bool
2767 +ubicom32_callee_copies (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
2768 +                       enum machine_mode mode, const_tree type,
2769 +                       bool named ATTRIBUTE_UNUSED)
2770 +{
2771 +  int size;
2772 +
2773 +  if (type)
2774 +    size = int_size_in_bytes (type);
2775 +  else
2776 +    size = GET_MODE_SIZE (mode);
2777 +
2778 +  return size <= 0 || size > 8;
2779 +}
2780
2781 +static bool
2782 +ubicom32_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
2783 +{
2784 +  int size, mode;
2785 +
2786 +  if (!type)
2787 +    return true;
2788 +
2789 +  size = int_size_in_bytes(type);
2790 +  if (size > 8) 
2791 +    return true;
2792 +
2793 +  mode = TYPE_MODE(type);
2794 +  if (mode == BLKmode)
2795 +    return true;
2796 +
2797 +  return false;
2798 +}
2799 +
2800 +/* Return true if a given register number REGNO is acceptable for machine
2801 +   mode MODE.  */
2802 +bool
2803 +ubicom32_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
2804 +{
2805 +  /* If we're not at least a v3 ISA then ACC0_HI is only 16 bits.  */
2806 +  if (! ubicom32_v3)
2807 +    {
2808 +      if (regno == ACC0_HI_REGNUM)
2809 +       return (mode == QImode || mode == HImode);
2810 +    }
2811 +
2812 +  /* Only the flags reg can hold CCmode.  */
2813 +  if (GET_MODE_CLASS (mode) == MODE_CC)
2814 +    return regno == CC_REGNUM;
2815 +
2816 +  /* We restrict the choice of DImode registers to only being address,
2817 +     data or accumulator regs.  We also restrict them to only start on
2818 +     even register numbers so we never have to worry about partial
2819 +     overlaps between operands in instructions.  */
2820 +  if (GET_MODE_SIZE (mode) > 4)
2821 +    {
2822 +      switch (REGNO_REG_CLASS (regno))
2823 +       {
2824 +       case ADDRESS_REGS:
2825 +       case DATA_REGS:
2826 +       case ACC_REGS:
2827 +         return (regno & 1) == 0;
2828 +
2829 +        default:
2830 +         return false;
2831 +       }
2832 +    }
2833 +
2834 +  return true;
2835 +}
2836 +
2837 +/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
2838 +   and check its validity for a certain class.
2839 +   We have two alternate definitions for each of them.
2840 +   The usual definition accepts all pseudo regs; the other rejects
2841 +   them unless they have been allocated suitable hard regs.
2842 +   The symbol REG_OK_STRICT causes the latter definition to be used.
2843 +
2844 +   Most source files want to accept pseudo regs in the hope that
2845 +   they will get allocated to the class that the insn wants them to be in.
2846 +   Source files for reload pass need to be strict.
2847 +   After reload, it makes no difference, since pseudo regs have
2848 +   been eliminated by then.  
2849 +
2850 +   These assume that REGNO is a hard or pseudo reg number.
2851 +   They give nonzero only if REGNO is a hard reg of the suitable class
2852 +   or a pseudo reg currently allocated to a suitable hard reg.
2853 +   Since they use reg_renumber, they are safe only once reg_renumber
2854 +   has been allocated, which happens in local-alloc.c.  */
2855 +
2856 +int
2857 +ubicom32_regno_ok_for_base_p (int regno, int strict)
2858 +{
2859 +  if ((regno >= FIRST_ADDRESS_REGNUM && regno <= STACK_POINTER_REGNUM) 
2860 +      || (!strict
2861 +         && (regno >= FIRST_PSEUDO_REGISTER
2862 +             || regno == ARG_POINTER_REGNUM))
2863 +      || (strict && (reg_renumber 
2864 +                    && reg_renumber[regno] >= FIRST_ADDRESS_REGNUM
2865 +                    && reg_renumber[regno] <= STACK_POINTER_REGNUM)))
2866 +    return 1;
2867 +
2868 +  return 0;
2869 +}
2870 +
2871 +int
2872 +ubicom32_regno_ok_for_index_p (int regno, int strict)
2873 +{
2874 +  if ((regno >= FIRST_DATA_REGNUM && regno <= LAST_DATA_REGNUM)
2875 +      || (!strict && regno >= FIRST_PSEUDO_REGISTER)
2876 +      || (strict && (reg_renumber 
2877 +                    && reg_renumber[regno] >= FIRST_DATA_REGNUM
2878 +                    && reg_renumber[regno] <= LAST_DATA_REGNUM)))
2879 +    return 1;
2880 +
2881 +  return 0;
2882 +}
2883 +
2884 +/* Returns 1 if X is a valid index register.  STRICT is 1 if only hard
2885 +   registers should be accepted.  Accept either REG or SUBREG where a
2886 +   register is valid.  */
2887 +
2888 +static bool
2889 +ubicom32_is_index_reg (rtx x, int strict)
2890 +{
2891 +  if ((REG_P (x) && ubicom32_regno_ok_for_index_p (REGNO (x), strict))
2892 +      || (GET_CODE (x) == SUBREG && REG_P (SUBREG_REG (x))
2893 +         && ubicom32_regno_ok_for_index_p (REGNO (SUBREG_REG (x)), strict)))
2894 +    return true;
2895 +
2896 +  return false;
2897 +}
2898 +
2899 +/* Return 1 if X is a valid index for a memory address.  */
2900 +
2901 +static bool
2902 +ubicom32_is_index_expr (enum machine_mode mode, rtx x, int strict)
2903 +{
2904 +  /* Immediate index must be an unsigned 7-bit offset multiple of 1, 2
2905 +     or 4 depending on mode.  */
2906 +  if (CONST_INT_P (x))
2907 +    {
2908 +      switch (mode)
2909 +       {
2910 +       case QImode:
2911 +         return satisfies_constraint_J (x);
2912 +         
2913 +       case HImode:
2914 +         return satisfies_constraint_K (x);
2915 +
2916 +       case SImode:
2917 +       case SFmode:
2918 +         return satisfies_constraint_L (x);
2919 +
2920 +       case DImode:
2921 +         return satisfies_constraint_L (x)
2922 +                && satisfies_constraint_L (GEN_INT (INTVAL (x) + 4));
2923 +         
2924 +       default:          
2925 +         return false;
2926 +       }
2927 +    }
2928 +
2929 +  if (mode != SImode && mode != HImode && mode != QImode)
2930 +    return false;
2931 +
2932 +  /* Register index scaled by mode of operand: REG + REG * modesize.
2933 +     Valid scaled index registers are:
2934 +
2935 +     SImode    (mult (dreg) 4))
2936 +     HImode    (mult (dreg) 2))
2937 +     QImode    (mult (dreg) 1))  */
2938 +  if (GET_CODE (x) == MULT
2939 +      && ubicom32_is_index_reg (XEXP (x, 0), strict)
2940 +      && CONST_INT_P (XEXP (x, 1))
2941 +      && INTVAL (XEXP (x, 1)) == (HOST_WIDE_INT)GET_MODE_SIZE (mode))
2942 +    return true;
2943 +
2944 +  /* REG + REG addressing is allowed for QImode.  */
2945 +  if (ubicom32_is_index_reg (x, strict) && mode == QImode)
2946 +    return true;
2947 +
2948 +  return false;
2949 +}
2950 +
2951 +static bool
2952 +ubicom32_is_valid_offset (enum machine_mode mode, HOST_WIDE_INT offs)
2953 +{
2954 +  if (offs < 0)
2955 +    return false;
2956 +
2957 +  switch (mode)
2958 +    {
2959 +    case QImode:
2960 +      return offs <= 127;
2961 +
2962 +    case HImode:
2963 +      return offs <= 254;
2964 +
2965 +    case SImode:
2966 +    case SFmode:
2967 +      return offs <= 508;
2968 +
2969 +    case DImode:
2970 +      return offs <= 504;
2971 +
2972 +    default:
2973 +      return false;
2974 +    }
2975 +}
2976 +
2977 +static int
2978 +ubicom32_get_valid_offset_mask (enum machine_mode mode)
2979 +{
2980 +  switch (mode)
2981 +    {
2982 +    case QImode:
2983 +      return 127;
2984 +
2985 +    case HImode:
2986 +      return 255;
2987 +
2988 +    case SImode:
2989 +    case SFmode:
2990 +      return 511;
2991 +
2992 +    case DImode:
2993 +      return 255;
2994 +
2995 +    default:
2996 +      return 0;
2997 +    }
2998 +}
2999 +
3000 +/* Returns 1 if X is a valid base register.  STRICT is 1 if only hard
3001 +   registers should be accepted.  Accept either REG or SUBREG where a
3002 +   register is valid.  */
3003 +
3004 +static bool
3005 +ubicom32_is_base_reg (rtx x, int strict)
3006 +{
3007 +  if ((REG_P (x) && ubicom32_regno_ok_for_base_p (REGNO (x), strict))
3008 +      || (GET_CODE (x) == SUBREG && REG_P (SUBREG_REG (x))
3009 +         && ubicom32_regno_ok_for_base_p (REGNO (SUBREG_REG (x)), strict)))
3010 +    return true;
3011 +
3012 +  return false;
3013 +}
3014 +
3015 +static bool
3016 +ubicom32_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
3017 +{
3018 +  return TARGET_FDPIC;
3019 +}
3020 +
3021 +/* Determine if X is a legitimate constant.  */
3022 +
3023 +bool
3024 +ubicom32_legitimate_constant_p (rtx x)
3025 +{
3026 +  /* Among its other duties, LEGITIMATE_CONSTANT_P decides whether
3027 +     a constant can be entered into reg_equiv_constant[].  If we return true,
3028 +     reload can create new instances of the constant whenever it likes.
3029 +
3030 +     The idea is therefore to accept as many constants as possible (to give
3031 +     reload more freedom) while rejecting constants that can only be created
3032 +     at certain times.  In particular, anything with a symbolic component will
3033 +     require use of the pseudo FDPIC register, which is only available before
3034 +     reload.  */
3035 +  if (TARGET_FDPIC)
3036 +    {
3037 +      if (GET_CODE (x) == SYMBOL_REF
3038 +         || (GET_CODE (x) == CONST
3039 +             && GET_CODE (XEXP (x, 0)) == PLUS
3040 +             && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)
3041 +         || CONSTANT_ADDRESS_P (x))
3042 +       return false;
3043 +
3044 +      return true;
3045 +    }
3046 +
3047 +  /* For non-PIC code anything goes!  */
3048 +  return true;
3049 +}
3050 +
3051 +/* Address validation.  */
3052 +
3053 +bool
3054 +ubicom32_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
3055 +{
3056 +  if (TARGET_DEBUG_ADDRESS)
3057 +    {                                                                  
3058 +      fprintf (stderr, "\n==> GO_IF_LEGITIMATE_ADDRESS%s\n",
3059 +              (strict) ? " (STRICT)" : "");
3060 +      debug_rtx (x);
3061 +    }                                                                  
3062 +
3063 +  if (CONSTANT_ADDRESS_P (x))
3064 +    return false;
3065 +
3066 +  if (ubicom32_is_base_reg (x, strict)) 
3067 +    return true;
3068 +
3069 +  if ((GET_CODE (x) == POST_INC 
3070 +       || GET_CODE (x) == PRE_INC 
3071 +       || GET_CODE (x) == POST_DEC 
3072 +       || GET_CODE (x) == PRE_DEC)
3073 +      && REG_P (XEXP (x, 0))
3074 +      && ubicom32_is_base_reg (XEXP (x, 0), strict)
3075 +      && mode != DImode)
3076 +    return true;
3077 +
3078 +  if ((GET_CODE (x) == PRE_MODIFY || GET_CODE (x) == POST_MODIFY)
3079 +      && ubicom32_is_base_reg (XEXP (x, 0), strict)
3080 +      && GET_CODE (XEXP (x, 1)) == PLUS
3081 +      && rtx_equal_p (XEXP (x, 0), XEXP (XEXP (x, 1), 0))
3082 +      && CONST_INT_P (XEXP (XEXP (x, 1), 1))
3083 +      && mode != DImode)
3084 +    {
3085 +      HOST_WIDE_INT disp = INTVAL (XEXP (XEXP (x, 1), 1));
3086 +      switch (mode)
3087 +       {
3088 +       case QImode:
3089 +         return disp >= -8 && disp <= 7;
3090 +         
3091 +       case HImode:
3092 +         return disp >= -16 && disp <= 14 && ! (disp & 1);
3093 +         
3094 +       case SImode:
3095 +         return disp >= -32 && disp <= 28 && ! (disp & 3);
3096 +         
3097 +       default:
3098 +         return false;
3099 +       }
3100 +    }
3101 +  
3102 +  /* Accept base + index * scale.  */
3103 +  if (GET_CODE (x) == PLUS
3104 +      && ubicom32_is_base_reg (XEXP (x, 0), strict)
3105 +      && ubicom32_is_index_expr (mode, XEXP (x, 1), strict))
3106 +    return true;
3107 +
3108 +  /* Accept index * scale + base.  */
3109 +  if (GET_CODE (x) == PLUS
3110 +      && ubicom32_is_base_reg (XEXP (x, 1), strict)
3111 +      && ubicom32_is_index_expr (mode, XEXP (x, 0), strict))
3112 +    return true;
3113 +
3114 +  if (! TARGET_FDPIC)
3115 +    {
3116 +      /* Accept (lo_sum (reg) (symbol_ref)) that can be used as a mem+7bits
3117 +        displacement operand:
3118 +
3119 +        moveai a1, #%hi(SYM)
3120 +        move.4 d3, %lo(SYM)(a1)  */
3121 +      if (GET_CODE (x) == LO_SUM
3122 +         && ubicom32_is_base_reg (XEXP (x, 0), strict)
3123 +         && (GET_CODE (XEXP (x, 1)) == SYMBOL_REF
3124 +             || GET_CODE (XEXP (x, 1)) == LABEL_REF /* FIXME: wrong */)
3125 +         && mode != DImode)
3126 +       return true;
3127 +    }
3128 +
3129 +  if (TARGET_DEBUG_ADDRESS)
3130 +    fprintf (stderr, "\nNot a legitimate address.\n");
3131 +
3132 +  return false;
3133 +}
3134 +
3135 +rtx
3136 +ubicom32_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
3137 +                            enum machine_mode mode)
3138 +{
3139 +  if (mode == BLKmode)
3140 +    return NULL_RTX;
3141 +
3142 +  if (GET_CODE (x) == PLUS
3143 +      && REG_P (XEXP (x, 0))
3144 +      && ! REGNO_PTR_FRAME_P (REGNO (XEXP (x, 0))) 
3145 +      && CONST_INT_P (XEXP (x, 1))
3146 +      && ! ubicom32_is_valid_offset (mode, INTVAL (XEXP (x, 1))))
3147 +    {
3148 +      rtx base;
3149 +      rtx plus;
3150 +      rtx new_rtx;
3151 +      HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
3152 +      HOST_WIDE_INT low = val & ubicom32_get_valid_offset_mask (mode);
3153 +      HOST_WIDE_INT high = val ^ low;
3154 +
3155 +      if (val < 0)
3156 +       return NULL_RTX;
3157 +
3158 +      if (! low)
3159 +       return NULL_RTX;
3160 +
3161 +      /* Reload the high part into a base reg; leave the low part
3162 +        in the mem directly.  */
3163 +      base = XEXP (x, 0);
3164 +      if (! ubicom32_is_base_reg (base, 0))
3165 +       base = copy_to_mode_reg (Pmode, base);
3166 +
3167 +      plus = expand_simple_binop (Pmode, PLUS,
3168 +                                 gen_int_mode (high, Pmode),
3169 +                                 base, NULL, 0, OPTAB_WIDEN);
3170 +      new_rtx = plus_constant (plus, low);
3171 +
3172 +      return new_rtx;
3173 +    }
3174 +
3175 +  return NULL_RTX;
3176 +}
3177 +
3178 +/* Try a machine-dependent way of reloading an illegitimate address AD
3179 +   operand.  If we find one, push the reload and and return the new address.
3180 +
3181 +   MODE is the mode of the enclosing MEM.  OPNUM is the operand number
3182 +   and TYPE is the reload type of the current reload.  */
3183 +
3184 +rtx 
3185 +ubicom32_legitimize_reload_address (rtx ad, enum machine_mode mode,
3186 +                                   int opnum, int type)
3187 +{
3188 +  /* Is this an address that we've already fixed up?  If it is then
3189 +     recognize it and move on.  */
3190 +  if (GET_CODE (ad) == PLUS
3191 +      && GET_CODE (XEXP (ad, 0)) == PLUS
3192 +      && REG_P (XEXP (XEXP (ad, 0), 0))
3193 +      && CONST_INT_P (XEXP (XEXP (ad, 0), 1))
3194 +      && CONST_INT_P (XEXP (ad, 1)))
3195 +    {
3196 +      push_reload (XEXP (ad, 0), NULL_RTX, &XEXP (ad, 0), NULL,
3197 +                  BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
3198 +                  opnum, (enum reload_type) type);
3199 +      return ad;
3200 +    }
3201 +
3202 +  /* Have we got an address where the offset is simply out of range?  If
3203 +     yes then reload the range as a high part and smaller offset.  */
3204 +  if (GET_CODE (ad) == PLUS
3205 +      && REG_P (XEXP (ad, 0))
3206 +      && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
3207 +      && REGNO_OK_FOR_BASE_P (REGNO (XEXP (ad, 0)))
3208 +      && CONST_INT_P (XEXP (ad, 1))
3209 +      && ! ubicom32_is_valid_offset (mode, INTVAL (XEXP (ad, 1))))
3210 +    {
3211 +      rtx temp;
3212 +      rtx new_rtx;
3213 +
3214 +      HOST_WIDE_INT val = INTVAL (XEXP (ad, 1));
3215 +      HOST_WIDE_INT low = val & ubicom32_get_valid_offset_mask (mode);
3216 +      HOST_WIDE_INT high = val ^ low;
3217 +
3218 +      /* Reload the high part into a base reg; leave the low part
3219 +        in the mem directly.  */
3220 +      temp = gen_rtx_PLUS (Pmode, XEXP (ad, 0), GEN_INT (high));
3221 +      new_rtx = gen_rtx_PLUS (Pmode, temp, GEN_INT (low));
3222 +
3223 +      push_reload (XEXP (new_rtx, 0), NULL_RTX, &XEXP (new_rtx, 0), NULL,
3224 +                  BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
3225 +                  opnum, (enum reload_type) type);
3226 +      return new_rtx;
3227 +    }
3228 +
3229 +  /* If we're presented with an pre/post inc/dec then we must force this
3230 +     to be done in an address register.  The register allocator should
3231 +     work this out for itself but at times ends up trying to use the wrong
3232 +     class.  If we get the wrong class then reload will end up generating
3233 +     at least 3 instructions whereas this way we can hopefully keep it to
3234 +     just 2.  */
3235 +  if ((GET_CODE (ad) == POST_INC 
3236 +       || GET_CODE (ad) == PRE_INC 
3237 +       || GET_CODE (ad) == POST_DEC 
3238 +       || GET_CODE (ad) == PRE_DEC)
3239 +      && REG_P (XEXP (ad, 0))
3240 +      && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
3241 +      && ! REGNO_OK_FOR_BASE_P (REGNO (XEXP (ad, 0))))
3242 +    {
3243 +      push_reload (XEXP (ad, 0), XEXP (ad, 0), &XEXP (ad, 0), &XEXP (ad, 0),
3244 +                  BASE_REG_CLASS, GET_MODE (XEXP (ad, 0)), GET_MODE (XEXP (ad, 0)), 0, 0,
3245 +                  opnum, RELOAD_OTHER);
3246 +      return ad;
3247 +    }
3248 +
3249 +  return NULL_RTX;
3250 +}
3251 +
3252 +/* Compute a (partial) cost for rtx X.  Return true if the complete
3253 +   cost has been computed, and false if subexpressions should be
3254 +   scanned.  In either case, *TOTAL contains the cost result.  */
3255 +
3256 +static bool
3257 +ubicom32_rtx_costs (rtx x, int code, int outer_code, int *total,
3258 +                   bool speed ATTRIBUTE_UNUSED)
3259 +{
3260 +  enum machine_mode mode = GET_MODE (x);
3261 +
3262 +  switch (code)
3263 +    {
3264 +    case CONST_INT:
3265 +      /* Very short constants often fold into instructions so
3266 +         we pretend that they don't cost anything!  This is
3267 +        really important as regards zero values as otherwise
3268 +        the compiler has a nasty habit of wanting to reuse
3269 +        zeroes that are in regs but that tends to pessimize
3270 +        the code.  */
3271 +      if (satisfies_constraint_I (x))
3272 +       {
3273 +         *total = 0;
3274 +         return true;
3275 +       }
3276 +
3277 +      /* Bit clearing costs nothing  */
3278 +      if (outer_code == AND
3279 +         && exact_log2 (~INTVAL (x)) != -1)
3280 +       {
3281 +         *total = 0;
3282 +         return true;
3283 +       }
3284 +
3285 +      /* Masking the lower set of bits costs nothing.  */
3286 +      if (outer_code == AND
3287 +         && exact_log2 (INTVAL (x) + 1) != -1)
3288 +       {
3289 +         *total = 0;
3290 +         return true;
3291 +       }
3292 +
3293 +      /* Bit setting costs nothing.  */
3294 +      if (outer_code == IOR
3295 +         && exact_log2 (INTVAL (x)) != -1)
3296 +       {
3297 +         *total = 0;
3298 +         return true;
3299 +       }
3300 +
3301 +      /* Larger constants that can be loaded via movei aren't too
3302 +         bad.  If we're just doing a set they cost nothing extra.  */
3303 +      if (satisfies_constraint_N (x))
3304 +       {
3305 +         if (mode == DImode)
3306 +           *total = COSTS_N_INSNS (2);
3307 +         else 
3308 +           *total = COSTS_N_INSNS (1);
3309 +         return true;
3310 +       }
3311 +
3312 +      if (mode == DImode)
3313 +       *total = COSTS_N_INSNS (5);
3314 +      else
3315 +        *total = COSTS_N_INSNS (3);
3316 +      return true;
3317 +
3318 +    case CONST_DOUBLE:
3319 +      /* We don't optimize CONST_DOUBLEs well nor do we relax them well,
3320 +        so their cost is very high.  */
3321 +      *total = COSTS_N_INSNS (6);
3322 +      return true;
3323 +
3324 +    case CONST:
3325 +    case SYMBOL_REF:
3326 +    case MEM:
3327 +      *total = 0;
3328 +      return true;
3329 +
3330 +    case IF_THEN_ELSE:
3331 +      *total = COSTS_N_INSNS (1);
3332 +      return true;
3333 +
3334 +    case LABEL_REF:
3335 +    case HIGH:
3336 +    case LO_SUM:
3337 +    case BSWAP:
3338 +    case PLUS:
3339 +    case MINUS:
3340 +    case AND:
3341 +    case IOR:
3342 +    case XOR:
3343 +    case ASHIFT:
3344 +    case ASHIFTRT:
3345 +    case LSHIFTRT:
3346 +    case NEG:
3347 +    case NOT:
3348 +    case SIGN_EXTEND:
3349 +    case ZERO_EXTEND:
3350 +    case ZERO_EXTRACT:
3351 +      if (outer_code == SET)
3352 +       {
3353 +         if (mode == DImode)
3354 +           *total = COSTS_N_INSNS (2);
3355 +         else
3356 +           *total = COSTS_N_INSNS (1);
3357 +       }
3358 +      return true;
3359 +
3360 +    case COMPARE:
3361 +      if (outer_code == SET)
3362 +       {
3363 +         if (GET_MODE (XEXP (x, 0)) == DImode
3364 +             || GET_MODE (XEXP (x, 1)) == DImode)
3365 +           *total = COSTS_N_INSNS (2);
3366 +         else
3367 +           *total = COSTS_N_INSNS (1);
3368 +       }
3369 +      return true;
3370 +
3371 +    case UMOD:
3372 +    case UDIV:
3373 +    case MOD:
3374 +    case DIV:
3375 +      if (outer_code == SET)
3376 +       {
3377 +         if (mode == DImode)
3378 +           *total = COSTS_N_INSNS (600);
3379 +         else
3380 +           *total = COSTS_N_INSNS (200);
3381 +       }
3382 +      return true;
3383 +
3384 +    case MULT:
3385 +      if (outer_code == SET)
3386 +       {
3387 +         if (! ubicom32_v4)
3388 +           {
3389 +             if (mode == DImode)
3390 +               *total = COSTS_N_INSNS (15);
3391 +             else
3392 +               *total = COSTS_N_INSNS (5);
3393 +           }
3394 +         else
3395 +           {
3396 +             if (mode == DImode)
3397 +               *total = COSTS_N_INSNS (6);
3398 +             else
3399 +               *total = COSTS_N_INSNS (2);
3400 +           }
3401 +       }
3402 +      return true;
3403 +
3404 +    case UNSPEC:
3405 +      if (XINT (x, 1) == UNSPEC_FDPIC_GOT
3406 +         || XINT (x, 1) == UNSPEC_FDPIC_GOT_FUNCDESC)
3407 +       *total = 0;
3408 +      return true;
3409 +
3410 +    default:
3411 +      return false;
3412 +    }
3413 +}
3414 +
3415 +/* Return 1 if ADDR can have different meanings depending on the machine
3416 +   mode of the memory reference it is used for or if the address is
3417 +   valid for some modes but not others.
3418 +
3419 +   Autoincrement and autodecrement addresses typically have
3420 +   mode-dependent effects because the amount of the increment or
3421 +   decrement is the size of the operand being addressed.  Some machines
3422 +   have other mode-dependent addresses. Many RISC machines have no
3423 +   mode-dependent addresses.
3424 +
3425 +   You may assume that ADDR is a valid address for the machine.  */
3426 +
3427 +int
3428 +ubicom32_mode_dependent_address_p (rtx addr)
3429 +{
3430 +  if (GET_CODE (addr) == POST_INC 
3431 +      || GET_CODE (addr) == PRE_INC 
3432 +      || GET_CODE (addr) == POST_DEC 
3433 +      || GET_CODE (addr) == PRE_DEC 
3434 +      || GET_CODE (addr) == POST_MODIFY 
3435 +      || GET_CODE (addr) == PRE_MODIFY)
3436 +    return 1;
3437 +
3438 +  return 0;
3439 +}
3440 +
3441 +static void
3442 +ubicom32_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
3443 +{
3444 +  fprintf (file, "/* frame/pretend: %ld/%d save_regs: %d out_args: %d  %s */\n",
3445 +          get_frame_size (), crtl->args.pretend_args_size,
3446 +          save_regs_size, crtl->outgoing_args_size,
3447 +          current_function_is_leaf ? "leaf" : "nonleaf");
3448 +}
3449 +
3450 +static void
3451 +ubicom32_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
3452 +                           HOST_WIDE_INT size ATTRIBUTE_UNUSED)
3453 +{
3454 +  ubicom32_reorg_completed = 0;  
3455 +}
3456 +
3457 +static void
3458 +ubicom32_machine_dependent_reorg (void)
3459 +{
3460 +#if 0 /* Commenting out this optimization until it is fixed */
3461 +  if (optimize)
3462 +    {
3463 +      compute_bb_for_insn ();
3464 +
3465 +      /* Do a very simple CSE pass over just the hard registers.  */
3466 +      reload_cse_regs (get_insns ());
3467 +
3468 +      /* Reload_cse_regs can eliminate potentially-trapping MEMs.
3469 +        Remove any EH edges associated with them.  */
3470 +      if (flag_non_call_exceptions)
3471 +       purge_all_dead_edges ();
3472 +    }
3473 +#endif
3474 +  ubicom32_reorg_completed = 1;
3475 +}
3476 +
3477 +void
3478 +ubicom32_output_cond_jump (rtx insn, rtx cond, rtx target)
3479 +{
3480 +  rtx note;
3481 +  int mostly_false_jump;
3482 +  rtx xoperands[2];
3483 +  rtx cc_reg;
3484 +
3485 +  note = find_reg_note (insn, REG_BR_PROB, 0);
3486 +  mostly_false_jump = !note || (INTVAL (XEXP (note, 0))
3487 +                               <= REG_BR_PROB_BASE / 2);
3488 +
3489 +  xoperands[0] = target;
3490 +  xoperands[1] = cond;
3491 +  cc_reg = XEXP (cond, 0);
3492 +
3493 +  if (GET_MODE (cc_reg) == CCWmode
3494 +      || GET_MODE (cc_reg) == CCWZmode
3495 +      || GET_MODE (cc_reg) == CCWZNmode)
3496 +    {
3497 +      if (mostly_false_jump)
3498 +        output_asm_insn ("jmp%b1.w.f\t%0", xoperands);
3499 +      else
3500 +        output_asm_insn ("jmp%b1.w.t\t%0", xoperands);
3501 +      return;
3502 +    }
3503 +
3504 +  if (GET_MODE (cc_reg) == CCSmode
3505 +      || GET_MODE (cc_reg) == CCSZmode
3506 +      || GET_MODE (cc_reg) == CCSZNmode)
3507 +    {
3508 +      if (mostly_false_jump)
3509 +        output_asm_insn ("jmp%b1.s.f\t%0", xoperands);
3510 +      else
3511 +        output_asm_insn ("jmp%b1.s.t\t%0", xoperands);
3512 +      return;
3513 +    }
3514 +
3515 +  abort ();
3516 +}
3517 +
3518 +/* Return non-zero if FUNC is a naked function.  */
3519 +
3520 +static int
3521 +ubicom32_naked_function_p (void)
3522 +{
3523 +  return lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE;
3524 +}
3525 +
3526 +/* Return an RTX indicating where the return address to the
3527 +   calling function can be found.  */
3528 +rtx
3529 +ubicom32_return_addr_rtx (int count, rtx frame ATTRIBUTE_UNUSED)
3530 +{
3531 +  if (count != 0)
3532 +    return NULL_RTX;
3533 +
3534 +  return get_hard_reg_initial_val (Pmode, LINK_REGNO);
3535 +}
3536 +
3537 +/*
3538 + * ubicom32_readonly_data_section: This routtine handles code
3539 + * at the start of readonly data sections
3540 + */
3541 +static void
3542 +ubicom32_readonly_data_section (const void *data ATTRIBUTE_UNUSED)
3543 +{
3544 +  static int num = 0;
3545 +  if (in_section == readonly_data_section){
3546 +    fprintf (asm_out_file, "%s", DATA_SECTION_ASM_OP);
3547 +    if (flag_data_sections){
3548 +      fprintf (asm_out_file, ".rodata%d", num);
3549 +      fprintf (asm_out_file, ",\"a\"");
3550 +    }
3551 +    fprintf (asm_out_file, "\n");
3552 +  }
3553 +  num++;
3554 +}
3555 +
3556 +/*
3557 + * ubicom32_text_section: not in readonly section
3558 + */
3559 +static void
3560 +ubicom32_text_section(const void *data ATTRIBUTE_UNUSED)
3561 +{
3562 +  fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP);
3563 +}
3564 +
3565 +/*
3566 + * ubicom32_data_section: not in readonly section
3567 + */
3568 +static void
3569 +ubicom32_data_section(const void *data ATTRIBUTE_UNUSED)
3570 +{
3571 +  fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP);
3572 +}
3573 +
3574 +/*
3575 + * ubicom32_asm_init_sections: This routine implements special
3576 + * section handling
3577 + */
3578 +static void
3579 +ubicom32_asm_init_sections(void)
3580 +{
3581 +  text_section = get_unnamed_section(SECTION_CODE, ubicom32_text_section, NULL);
3582 +
3583 +  data_section = get_unnamed_section(SECTION_WRITE, ubicom32_data_section, NULL);
3584 +
3585 +  readonly_data_section = get_unnamed_section(0, ubicom32_readonly_data_section, NULL);
3586 +}
3587 +
3588 +/*
3589 + * ubicom32_profiler:  This routine would call
3590 + * mcount to support prof and gprof if mcount
3591 + * was supported. Currently, do nothing.
3592 + */
3593 +void
3594 +ubicom32_profiler(void)
3595 +{
3596 +}
3597 +
3598 +/* Initialise the builtin functions.  Start by initialising
3599 +   descriptions of different types of functions (e.g., void fn(int),
3600 +   int fn(void)), and then use these to define the builtins. */
3601 +static void
3602 +ubicom32_init_builtins (void)
3603 +{
3604 +  tree endlink;
3605 +  tree short_unsigned_endlink;
3606 +  tree unsigned_endlink;
3607 +  tree short_unsigned_ftype_short_unsigned;
3608 +  tree unsigned_ftype_unsigned;
3609 +
3610 +  endlink = void_list_node;
3611 +
3612 +  short_unsigned_endlink
3613 +    = tree_cons (NULL_TREE, short_unsigned_type_node, endlink);
3614 +
3615 +  unsigned_endlink
3616 +    = tree_cons (NULL_TREE, unsigned_type_node, endlink);
3617 +
3618 +  short_unsigned_ftype_short_unsigned
3619 +    = build_function_type (short_unsigned_type_node, short_unsigned_endlink);
3620 +
3621 +  unsigned_ftype_unsigned
3622 +    = build_function_type (unsigned_type_node, unsigned_endlink);
3623 +
3624 +  /* Initialise the byte swap function. */
3625 +  add_builtin_function ("__builtin_ubicom32_swapb_2",
3626 +                       short_unsigned_ftype_short_unsigned,
3627 +                       UBICOM32_BUILTIN_UBICOM32_SWAPB_2,
3628 +                       BUILT_IN_MD, NULL,
3629 +                       NULL_TREE);
3630 +
3631 +  /* Initialise the byte swap function. */
3632 +  add_builtin_function ("__builtin_ubicom32_swapb_4",
3633 +                       unsigned_ftype_unsigned,
3634 +                       UBICOM32_BUILTIN_UBICOM32_SWAPB_4,
3635 +                       BUILT_IN_MD, NULL,
3636 +                       NULL_TREE);
3637 +}
3638 +
3639 +/* Given a builtin function taking 2 operands (i.e., target + source),
3640 +   emit the RTL for the underlying instruction. */
3641 +static rtx
3642 +ubicom32_expand_builtin_2op (enum insn_code icode, tree arglist, rtx target)
3643 +{
3644 +  tree arg0;
3645 +  rtx op0, pat;
3646 +  enum machine_mode tmode, mode0;
3647 +
3648 +  /* Grab the incoming argument and emit its RTL. */
3649 +  arg0 = TREE_VALUE (arglist);
3650 +  op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
3651 +
3652 +  /* Determine the modes of the instruction operands. */
3653 +  tmode = insn_data[icode].operand[0].mode;
3654 +  mode0 = insn_data[icode].operand[1].mode;
3655 +
3656 +  /* Ensure that the incoming argument RTL is in a register of the
3657 +     correct mode. */
3658 +  if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
3659 +    op0 = copy_to_mode_reg (mode0, op0);
3660 +
3661 +  /* If there isn't a suitable target, emit a target register. */
3662 +  if (target == 0
3663 +      || GET_MODE (target) != tmode
3664 +      || !(*insn_data[icode].operand[0].predicate) (target, tmode))
3665 +    target = gen_reg_rtx (tmode);
3666 +
3667 +  /* Emit and return the new instruction. */
3668 +  pat = GEN_FCN (icode) (target, op0);
3669 +  if (!pat)
3670 +    return 0;
3671 +  emit_insn (pat);
3672 +
3673 +  return target;
3674 +}
3675 +
3676 +/* Expand a call to a builtin function. */
3677 +static rtx
3678 +ubicom32_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
3679 +                        enum machine_mode mode ATTRIBUTE_UNUSED,
3680 +                        int ignore ATTRIBUTE_UNUSED)
3681 +{
3682 +  tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
3683 +  tree arglist = CALL_EXPR_ARGS(exp);
3684 +  int fcode = DECL_FUNCTION_CODE (fndecl);
3685 +
3686 +  switch (fcode)
3687 +    {
3688 +    case UBICOM32_BUILTIN_UBICOM32_SWAPB_2:
3689 +      return ubicom32_expand_builtin_2op (CODE_FOR_bswaphi, arglist, target);
3690 +
3691 +    case UBICOM32_BUILTIN_UBICOM32_SWAPB_4:
3692 +      return ubicom32_expand_builtin_2op (CODE_FOR_bswapsi, arglist, target);
3693 +
3694 +    default:
3695 +      gcc_unreachable();
3696 +    }
3697 +
3698 +  /* Should really do something sensible here.  */
3699 +  return NULL_RTX;
3700 +}
3701 +
3702 +/* Fold any constant argument for a swapb.2 instruction.  */
3703 +static tree
3704 +ubicom32_fold_builtin_ubicom32_swapb_2 (tree fndecl, tree arglist)
3705 +{
3706 +  tree arg0;
3707 +
3708 +  arg0 = TREE_VALUE (arglist);
3709 +
3710 +  /* Optimize constant value.  */
3711 +  if (TREE_CODE (arg0) == INTEGER_CST)
3712 +    {
3713 +      HOST_WIDE_INT v;
3714 +      HOST_WIDE_INT res;
3715 +
3716 +      v = TREE_INT_CST_LOW (arg0);
3717 +      res = ((v >> 8) & 0xff)
3718 +            | ((v & 0xff) << 8);
3719 +
3720 +      return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), res);
3721 +    }
3722 +
3723 +  return NULL_TREE;
3724 +}
3725 +
3726 +/* Fold any constant argument for a swapb.4 instruction.  */
3727 +static tree
3728 +ubicom32_fold_builtin_ubicom32_swapb_4 (tree fndecl, tree arglist)
3729 +{
3730 +  tree arg0;
3731 +
3732 +  arg0 = TREE_VALUE (arglist);
3733 +
3734 +  /* Optimize constant value.  */
3735 +  if (TREE_CODE (arg0) == INTEGER_CST)
3736 +    {
3737 +      unsigned HOST_WIDE_INT v;
3738 +      unsigned HOST_WIDE_INT res;
3739 +
3740 +      v = TREE_INT_CST_LOW (arg0);
3741 +      res = ((v >> 24) & 0xff)
3742 +            | (((v >> 16) & 0xff) << 8)
3743 +            | (((v >> 8) & 0xff) << 16)
3744 +            | ((v & 0xff) << 24);
3745 +
3746 +      return build_int_cst_wide (TREE_TYPE (TREE_TYPE (fndecl)), res, 0);
3747 +    }
3748 +
3749 +  return NULL_TREE;
3750 +}
3751 +
3752 +/* Fold any constant arguments for builtin functions.  */
3753 +static tree
3754 +ubicom32_fold_builtin (tree fndecl, tree arglist, bool ignore ATTRIBUTE_UNUSED)
3755 +{
3756 +  switch (DECL_FUNCTION_CODE (fndecl))
3757 +    {
3758 +    case UBICOM32_BUILTIN_UBICOM32_SWAPB_2:
3759 +      return ubicom32_fold_builtin_ubicom32_swapb_2 (fndecl, arglist);
3760 +
3761 +    case UBICOM32_BUILTIN_UBICOM32_SWAPB_4:
3762 +      return ubicom32_fold_builtin_ubicom32_swapb_4 (fndecl, arglist);
3763 +
3764 +    default:
3765 +      return NULL;
3766 +    }
3767 +}
3768 +
3769 +/* Implementation of TARGET_ASM_INTEGER.  When using FD-PIC, we need to
3770 +   tell the assembler to generate pointers to function descriptors in
3771 +   some cases.  */
3772 +static bool
3773 +ubicom32_assemble_integer (rtx value, unsigned int size, int aligned_p)
3774 +{
3775 +  if (TARGET_FDPIC && size == UNITS_PER_WORD)
3776 +    {
3777 +      if (GET_CODE (value) == SYMBOL_REF
3778 +         && SYMBOL_REF_FUNCTION_P (value))
3779 +       {
3780 +         fputs ("\t.picptr\t%funcdesc(", asm_out_file);
3781 +         output_addr_const (asm_out_file, value);
3782 +         fputs (")\n", asm_out_file);
3783 +         return true;
3784 +       }
3785 +
3786 +      if (!aligned_p)
3787 +       {
3788 +         /* We've set the unaligned SI op to NULL, so we always have to
3789 +            handle the unaligned case here.  */
3790 +         assemble_integer_with_op ("\t.4byte\t", value);
3791 +         return true;
3792 +       }
3793 +    }
3794 +
3795 +  return default_assemble_integer (value, size, aligned_p);
3796 +}
3797 +
3798 +/* If the constant I can be constructed by shifting a source-1 immediate
3799 +   by a constant number of bits then return the bit count.  If not
3800 +   return 0.  */
3801 +
3802 +int
3803 +ubicom32_shiftable_const_int (int i)
3804 +{
3805 +  int shift = 0;
3806 +
3807 +  /* Note that any constant that can be represented as an immediate to
3808 +     a movei instruction is automatically ignored here in the interests
3809 +     of the clarity of the output asm code.  */
3810 +  if (i >= -32768 && i <= 32767)
3811 +    return 0;
3812 +
3813 +  /* Find the number of trailing zeroes.  We could use __builtin_ctz
3814 +     here but it's not obvious if this is supported on all build
3815 +     compilers so we err on the side of caution.  */
3816 +  if ((i & 0xffff) == 0)
3817 +    {
3818 +      shift += 16;
3819 +      i >>= 16;
3820 +    }
3821 +
3822 +  if ((i & 0xff) == 0)
3823 +    {
3824 +      shift += 8;
3825 +      i >>= 8;
3826 +    }
3827 +
3828 +  if ((i & 0xf) == 0)
3829 +    {
3830 +      shift += 4;
3831 +      i >>= 4;
3832 +    }
3833 +
3834 +  if ((i & 0x3) == 0)
3835 +    {
3836 +      shift += 2;
3837 +      i >>= 2;
3838 +    }
3839 +
3840 +  if ((i & 0x1) == 0)
3841 +    {
3842 +      shift += 1;
3843 +      i >>= 1;
3844 +    }
3845 +
3846 +  if (i >= -128 && i <= 127)
3847 +    return shift;
3848 +
3849 +  return 0;
3850 +}
3851 +
3852 --- /dev/null
3853 +++ b/gcc/config/ubicom32/ubicom32.h
3854 @@ -0,0 +1,1564 @@
3855 +/* Definitions of target machine for Ubicom32
3856 +
3857 +   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
3858 +   2009 Free Software Foundation, Inc.
3859 +   Contributed by Ubicom, Inc.
3860 +
3861 +   This file is part of GCC.
3862 +
3863 +   GCC is free software; you can redistribute it and/or modify it
3864 +   under the terms of the GNU General Public License as published
3865 +   by the Free Software Foundation; either version 3, or (at your
3866 +   option) any later version.
3867 +
3868 +   GCC is distributed in the hope that it will be useful, but WITHOUT
3869 +   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
3870 +   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
3871 +   License for more details.
3872 +
3873 +   You should have received a copy of the GNU General Public License
3874 +   along with GCC; see the file COPYING3.  If not see
3875 +   <http://www.gnu.org/licenses/>.  */
3876 +
3877 +\f
3878 +
3879 +#define OBJECT_FORMAT_ELF
3880 +
3881 +/* Run-time target specifications. */
3882 +
3883 +/* Target CPU builtins.  */
3884 +#define TARGET_CPU_CPP_BUILTINS()                      \
3885 +  do                                                   \
3886 +    {                                                  \
3887 +      builtin_define_std ("__UBICOM32__");             \
3888 +      builtin_define_std ("__ubicom32__");             \
3889 +                                                       \
3890 +      if (TARGET_FDPIC)                                        \
3891 +       {                                               \
3892 +         builtin_define ("__UBICOM32_FDPIC__");        \
3893 +         builtin_define ("__FDPIC__");                 \
3894 +       }                                               \
3895 +    }                                                  \
3896 +  while (0)
3897 +
3898 +#ifndef TARGET_DEFAULT
3899 +#define TARGET_DEFAULT 0
3900 +#endif
3901 +
3902 +extern int ubicom32_case_values_threshold;
3903 +
3904 +/* Nonzero if this chip supports the Ubicom32 v3 ISA.  */
3905 +extern int ubicom32_v3;
3906 +
3907 +/* Nonzero if this chip supports the Ubicom32 v4 ISA.  */
3908 +extern int ubicom32_v4;
3909 +
3910 +extern int ubicom32_stack_size;
3911 +
3912 +/* Flag for whether we can use calli instead of ret in returns.  */
3913 +extern int ubicom32_can_use_calli_to_ret;
3914 +
3915 +/* This macro is a C statement to print on `stderr' a string describing the
3916 +   particular machine description choice.  Every machine description should
3917 +   define `TARGET_VERSION'. */
3918 +#define TARGET_VERSION fprintf (stderr, " (UBICOM32)");
3919 +
3920 +/* We don't need a frame pointer to debug things.  Doing this means
3921 +   that gcc can turn on -fomit-frame-pointer when '-O' is specified.  */
3922 +#define CAN_DEBUG_WITHOUT_FP
3923 +
3924 +/* We need to handle processor-specific options.  */
3925 +#define OVERRIDE_OPTIONS ubicom32_override_options ()
3926 +
3927 +#define OPTIMIZATION_OPTIONS(LEVEL, SIZE) \
3928 +  ubicom32_optimization_options (LEVEL, SIZE)
3929 +
3930 +/* For Ubicom32 the least significant bit has the lowest bit number
3931 +   so we define this to be 0.  */
3932 +#define BITS_BIG_ENDIAN 0
3933 +
3934 +/* For Ubicom32 the most significant byte in a word has the lowest
3935 +   number.  */
3936 +#define BYTES_BIG_ENDIAN 1
3937 +
3938 +/* For Ubicom32, in a multiword object, the most signifant word has the
3939 +   lowest number.  */
3940 +#define WORDS_BIG_ENDIAN 1
3941 +
3942 +/* Ubicom32 has 8 bits per byte.  */
3943 +#define BITS_PER_UNIT 8
3944 +
3945 +/* Ubicom32 has 32 bits per word.  */
3946 +#define BITS_PER_WORD 32
3947 +
3948 +/* Width of a word, in units (bytes).  */
3949 +#define UNITS_PER_WORD 4
3950 +
3951 +/* Width of a pointer, in bits.  */
3952 +#define POINTER_SIZE 32
3953 +
3954 +/* Alias for pointers.  Ubicom32 is a 32-bit architecture so we use
3955 +   SImode.  */
3956 +#define Pmode SImode
3957 +
3958 +/* Normal alignment required for function parameters on the stack, in
3959 +   bits.  */
3960 +#define PARM_BOUNDARY 32
3961 +
3962 +/* We need to maintain the stack on a 32-bit boundary.  */
3963 +#define STACK_BOUNDARY 32
3964 +
3965 +/* Alignment required for a function entry point, in bits.  */
3966 +#define FUNCTION_BOUNDARY 32
3967 +
3968 +/* Alias for the machine mode used for memory references to functions being
3969 +   called, in `call' RTL expressions.  We use byte-oriented addresses
3970 +   here.  */
3971 +#define FUNCTION_MODE QImode
3972 +
3973 +/* Biggest alignment that any data type can require on this machine,
3974 +   in bits.  */
3975 +#define BIGGEST_ALIGNMENT 32
3976 +
3977 +/* this default to BIGGEST_ALIGNMENT unless defined       */
3978 +/* ART: What's the correct value here? Default is (((unsigned int)1<<28)*8)*/
3979 +#undef MAX_OFILE_ALIGNMENT
3980 +#define MAX_OFILE_ALIGNMENT (128 * 8)
3981 +
3982 +/* Alignment in bits to be given to a structure bit field that follows an empty
3983 +   field such as `int : 0;'.  */
3984 +#define EMPTY_FIELD_BOUNDARY 32
3985 +
3986 +/* All structures must be a multiple of 32 bits in size.  */
3987 +#define STRUCTURE_SIZE_BOUNDARY 32
3988 +
3989 +/* A bit-field declared as `int' forces `int' alignment for the struct.  */
3990 +#define PCC_BITFIELD_TYPE_MATTERS 1
3991 +
3992 +/* For Ubicom32 we absolutely require that data be aligned with nominal
3993 +   alignment.  */
3994 +#define STRICT_ALIGNMENT 1
3995 +
3996 +/* Make strcpy of constants fast.  */
3997 +#define CONSTANT_ALIGNMENT(EXP, ALIGN)  \
3998 +  (TREE_CODE (EXP) == STRING_CST       \
3999 +   && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
4000 +
4001 +/* Define this macro as an expression for the alignment of a structure
4002 +   (given by STRUCT as a tree node) if the alignment computed in the
4003 +   usual way is COMPUTED and the alignment explicitly specified was
4004 +   SPECIFIED. */
4005 +#define DATA_ALIGNMENT(TYPE, ALIGN)                                    \
4006 +  ((((ALIGN) < BITS_PER_WORD)                                          \
4007 +    && (TREE_CODE (TYPE) == ARRAY_TYPE                                 \
4008 +       || TREE_CODE (TYPE) == UNION_TYPE                               \
4009 +       || TREE_CODE (TYPE) == RECORD_TYPE)) ? BITS_PER_WORD : (ALIGN))
4010 +
4011 +#define LOCAL_ALIGNMENT(TYPE,ALIGN) DATA_ALIGNMENT(TYPE,ALIGN)
4012 +
4013 +/* For Ubicom32 we default to unsigned chars.  */
4014 +#define DEFAULT_SIGNED_CHAR 0
4015 +
4016 +/* Machine-specific data register numbers.  */
4017 +#define FIRST_DATA_REGNUM 0
4018 +#define D10_REGNUM 10
4019 +#define D11_REGNUM 11
4020 +#define D12_REGNUM 12
4021 +#define D13_REGNUM 13
4022 +#define LAST_DATA_REGNUM 15
4023 +
4024 +/* Machine-specific address register numbers.  */
4025 +#define FIRST_ADDRESS_REGNUM 16
4026 +#define LAST_ADDRESS_REGNUM 22
4027 +
4028 +/* Register numbers used for passing a function's static chain pointer.  If
4029 +   register windows are used, the register number as seen by the called
4030 +   function is `STATIC_CHAIN_INCOMING_REGNUM', while the register number as
4031 +   seen by the calling function is `STATIC_CHAIN_REGNUM'.  If these registers
4032 +   are the same, `STATIC_CHAIN_INCOMING_REGNUM' need not be defined.
4033 +
4034 +   The static chain register need not be a fixed register.
4035 +
4036 +   If the static chain is passed in memory, these macros should not be defined;
4037 +   instead, the next two macros should be defined.  */
4038 +#define STATIC_CHAIN_REGNUM (FIRST_ADDRESS_REGNUM + 1)
4039 +
4040 +/* The register number of the frame pointer register, which is used to access
4041 +   automatic variables in the stack frame.  We generally eliminate this anyway
4042 +   for Ubicom32 but we make it A6 by default.  */
4043 +#define FRAME_POINTER_REGNUM (LAST_ADDRESS_REGNUM)
4044 +
4045 +/* The register number of the stack pointer register, which is also be a
4046 +   fixed register according to `FIXED_REGISTERS'.  For Ubicom32 we don't
4047 +   have a hardware requirement about which register this is, but by convention
4048 +   we use A7.  */
4049 +#define STACK_POINTER_REGNUM (LAST_ADDRESS_REGNUM + 1)
4050 +
4051 +/* Machine-specific accumulator register numbers.  */
4052 +#define ACC0_HI_REGNUM 24
4053 +#define ACC0_LO_REGNUM 25
4054 +#define ACC1_HI_REGNUM 26
4055 +#define ACC1_LO_REGNUM 27
4056 +
4057 +/* source3 register number */
4058 +#define SOURCE3_REGNUM 28
4059 +
4060 +/* The register number of the arg pointer register, which is used to access the
4061 +   function's argument list.  On some machines, this is the same as the frame
4062 +   pointer register.  On some machines, the hardware determines which register
4063 +   this is.  On other machines, you can choose any register you wish for this
4064 +   purpose.  If this is not the same register as the frame pointer register,
4065 +   then you must mark it as a fixed register according to `FIXED_REGISTERS', or
4066 +   arrange to be able to eliminate it.  */
4067 +#define ARG_POINTER_REGNUM 29
4068 +
4069 +/* Pseudo-reg for condition code.  */
4070 +#define CC_REGNUM 30
4071 +
4072 +/* Interrupt set/clear registers.  */
4073 +#define INT_SET0_REGNUM 31
4074 +#define INT_SET1_REGNUM 32
4075 +#define INT_CLR0_REGNUM 33
4076 +#define INT_CLR1_REGNUM 34
4077 +
4078 +/* Scratchpad registers.  */
4079 +#define SCRATCHPAD0_REGNUM 35
4080 +#define SCRATCHPAD1_REGNUM 36
4081 +#define SCRATCHPAD2_REGNUM 37
4082 +#define SCRATCHPAD3_REGNUM 38
4083 +
4084 +/* FDPIC register.  */
4085 +#define FDPIC_REGNUM 16
4086 +
4087 +/* Number of hardware registers known to the compiler.  They receive numbers 0
4088 +   through `FIRST_PSEUDO_REGISTER-1'; thus, the first pseudo register's number
4089 +   really is assigned the number `FIRST_PSEUDO_REGISTER'.  */
4090 +#define FIRST_PSEUDO_REGISTER 39
4091 +
4092 +/* An initializer that says which registers are used for fixed purposes all
4093 +   throughout the compiled code and are therefore not available for general
4094 +   allocation.  These would include the stack pointer, the frame pointer
4095 +   (except on machines where that can be used as a general register when no
4096 +   frame pointer is needed), the program counter on machines where that is
4097 +   considered one of the addressable registers, and any other numbered register
4098 +   with a standard use.
4099 +
4100 +   This information is expressed as a sequence of numbers, separated by commas
4101 +   and surrounded by braces.  The Nth number is 1 if register N is fixed, 0
4102 +   otherwise.
4103 +
4104 +   The table initialized from this macro, and the table initialized by the
4105 +   following one, may be overridden at run time either automatically, by the
4106 +   actions of the macro `CONDITIONAL_REGISTER_USAGE', or by the user with the
4107 +   command options `-ffixed-REG', `-fcall-used-REG' and `-fcall-saved-REG'.  */
4108 +#define FIXED_REGISTERS                                        \
4109 +  {                                                    \
4110 +    0, 0, 0, 0, 0, 0, 0, 0,    /* d0 - d7 */           \
4111 +    0, 0, 0, 0, 0, 0, 0, 1,    /* d8 - d15 */          \
4112 +    0, 0, 0, 0, 0, 0, 0, 1,    /* a0 - a7 */           \
4113 +    0, 0,                      /* acc0 hi/lo */        \
4114 +    0, 0,                      /* acc1 hi/lo */        \
4115 +    0,                         /* source3 */           \
4116 +    1,                         /* arg */               \
4117 +    1,                         /* cc */                \
4118 +    1, 1,                      /* int_set[01] */       \
4119 +    1, 1,                      /* int_clr[01] */       \
4120 +    1, 1, 1, 1                 /* scratchpad[0123] */  \
4121 +  }
4122 +
4123 +/* Like `FIXED_REGISTERS' but has 1 for each register that is clobbered (in
4124 +   general) by function calls as well as for fixed registers.  This macro
4125 +   therefore identifies the registers that are not available for general
4126 +   allocation of values that must live across function calls.
4127 +
4128 +   If a register has 0 in `CALL_USED_REGISTERS', the compiler automatically
4129 +   saves it on function entry and restores it on function exit, if the register
4130 +   is used within the function.  */
4131 +#define CALL_USED_REGISTERS                            \
4132 +  {                                                    \
4133 +    1, 1, 1, 1, 1, 1, 1, 1,    /* d0 - d7 */           \
4134 +    1, 1, 0, 0, 0, 0, 1, 1,    /* d8 - d15 */          \
4135 +    1, 0, 0, 1, 1, 1, 0, 1,    /* a0 - a7 */           \
4136 +    1, 1,                      /* acc0 hi/lo */        \
4137 +    1, 1,                      /* acc1 hi/lo */        \
4138 +    1,                         /* source3 */           \
4139 +    1,                         /* arg */               \
4140 +    1,                         /* cc */                \
4141 +    1, 1,                      /* int_set[01] */       \
4142 +    1, 1,                      /* int_clr[01] */       \
4143 +    1, 1, 1, 1                 /* scratchpad[0123] */  \
4144 +  }
4145 +
4146 +/* How to refer to registers in assembler output.
4147 +   This sequence is indexed by compiler's hard-register-number (see above).  */
4148 +
4149 +/* A C initializer containing the assembler's names for the machine registers,
4150 +   each one as a C string constant.  This is what translates register numbers
4151 +   in the compiler into assembler language.  */
4152 +#define REGISTER_NAMES                                         \
4153 +  {                                                            \
4154 +    "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",            \
4155 +    "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15",      \
4156 +    "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp",            \
4157 +    "acc0_hi", "acc0_lo",                                      \
4158 +    "acc1_hi", "acc1_lo",                                      \
4159 +    "source3",                                                 \
4160 +    "arg",                                                     \
4161 +    "cc",                                                      \
4162 +    "int_set0", "int_set1",                                    \
4163 +    "int_clr0", "int_clr1",                                    \
4164 +    "scratchpad0", "scratchpad1", "scratchpad2", "scratchpad3" \
4165 +  }
4166 +
4167 +#define CONDITIONAL_REGISTER_USAGE                             \
4168 +  ubicom32_conditional_register_usage ();
4169 +
4170 +/* Order of allocation of registers.  */
4171 +
4172 +/* If defined, an initializer for a vector of integers, containing the numbers
4173 +   of hard registers in the order in which GNU CC should prefer to use them
4174 +   (from most preferred to least).
4175 +
4176 +   For Ubicom32 we try using caller-clobbered data registers first, then
4177 +   callee-saved data registers, then caller-clobbered address registers,
4178 +   then callee-saved address registers and finally everything else.
4179 +
4180 +   The caller-clobbered registers are usually slightly cheaper to use because
4181 +   there's no need to save/restore.  */
4182 +#define REG_ALLOC_ORDER                                                \
4183 +  {                                                            \
4184 +    0, 1, 2, 3, 4,             /* d0 - d4 */                   \
4185 +    5, 6, 7, 8, 9,             /* d5 - d9 */                   \
4186 +    14,                                /* d14 */                       \
4187 +    10, 11, 12, 13,            /* d10 - d13 */                 \
4188 +    19, 20, 16, 21,            /* a3, a4, a0, a5 */            \
4189 +    17, 18, 22,                        /* a1, a2, a6 */                \
4190 +    24, 25,                    /* acc0 hi/lo */                \
4191 +    26, 27,                    /* acc0 hi/lo */                \
4192 +    28                         /* source3 */                   \
4193 +  }
4194 +
4195 +/* C expression for the number of consecutive hard registers, starting at
4196 +   register number REGNO, required to hold a value of mode MODE.  */
4197 +#define HARD_REGNO_NREGS(REGNO, MODE) \
4198 +  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
4199 +
4200 +/* Most registers can hold QImode, HImode and SImode values but we have to
4201 +   be able to indicate any hard registers that cannot hold values with some
4202 +   modes.  */
4203 +#define HARD_REGNO_MODE_OK(REGNO, MODE) \
4204 +  ubicom32_hard_regno_mode_ok(REGNO, MODE)
4205 +
4206 +/* We can rename most registers aside from the FDPIC register if we're using
4207 +   FDPIC.  */
4208 +#define HARD_REGNO_RENAME_OK(from, to) (TARGET_FDPIC ? ((to) != FDPIC_REGNUM) : 1)
4209 +
4210 +/* A C expression that is nonzero if it is desirable to choose register
4211 +   allocation so as to avoid move instructions between a value of mode MODE1
4212 +   and a value of mode MODE2.
4213 +
4214 +   If `HARD_REGNO_MODE_OK (R, MODE1)' and `HARD_REGNO_MODE_OK (R, MODE2)' are
4215 +   ever different for any R, then `MODES_TIEABLE_P (MODE1, MODE2)' must be
4216 +   zero.  */
4217 +#define MODES_TIEABLE_P(MODE1, MODE2) 1
4218 +
4219 +/* An enumeral type that must be defined with all the register class names as
4220 +   enumeral values.  `NO_REGS' must be first.  `ALL_REGS' must be the last
4221 +   register class, followed by one more enumeral value, `LIM_REG_CLASSES',
4222 +   which is not a register class but rather tells how many classes there are.
4223 +
4224 +   Each register class has a number, which is the value of casting the class
4225 +   name to type `int'.  The number serves as an index in many of the tables
4226 +   described below.  */
4227 +
4228 +enum reg_class
4229 +{
4230 +  NO_REGS,
4231 +  DATA_REGS,
4232 +  FDPIC_REG,
4233 +  ADDRESS_REGS,
4234 +  ALL_ADDRESS_REGS,
4235 +  ACC_LO_REGS,
4236 +  ACC_REGS,
4237 +  CC_REG,
4238 +  DATA_ACC_REGS,
4239 +  SOURCE3_REG,
4240 +  SPECIAL_REGS,
4241 +  GENERAL_REGS,
4242 +  ALL_REGS,
4243 +  LIM_REG_CLASSES
4244 +};
4245 +
4246 +/* The number of distinct register classes.  */
4247 +#define N_REG_CLASSES (int) LIM_REG_CLASSES
4248 +
4249 +/* An initializer containing the names of the register classes as C string
4250 +   constants.  These names are used in writing some of the debugging dumps.  */
4251 +
4252 +#define REG_CLASS_NAMES                \
4253 +{                              \
4254 +  "NO_REGS",                   \
4255 +  "DATA_REGS",                 \
4256 +  "FDPIC_REG",                 \
4257 +  "ADDRESS_REGS",              \
4258 +  "ALL_ADDRESS_REGS",          \
4259 +  "ACC_LO_REGS",               \
4260 +  "ACC_REGS",                  \
4261 +  "CC_REG",                    \
4262 +  "DATA_ACC_REGS",             \
4263 +  "SOURCE3_REG",               \
4264 +  "SPECIAL_REGS",              \
4265 +  "GENERAL_REGS",              \
4266 +  "ALL_REGS",                  \
4267 +  "LIM_REGS"                   \
4268 +}
4269 +
4270 +/* An initializer containing the contents of the register classes, as integers
4271 +   which are bit masks.  The Nth integer specifies the contents of class N.
4272 +   The way the integer MASK is interpreted is that register R is in the class
4273 +   if `MASK & (1 << R)' is 1.
4274 +
4275 +   When the machine has more than 32 registers, an integer does not suffice.
4276 +   Then the integers are replaced by sub-initializers, braced groupings
4277 +   containing several integers.  Each sub-initializer must be suitable as an
4278 +   initializer for the type `HARD_REG_SET' which is defined in
4279 +   `hard-reg-set.h'.  */
4280 +#define REG_CLASS_CONTENTS                                     \
4281 +{                                                              \
4282 +  {0x00000000, 0x00000000},    /* No regs */                   \
4283 +  {0x0000ffff, 0x00000000},    /* DATA_REGS */                 \
4284 +  {0x00010000, 0x00000000},    /* FDPIC_REG */                 \
4285 +  {0x20fe0000, 0x00000000},    /* ADDRESS_REGS */              \
4286 +  {0x20ff0000, 0x00000000},    /* ALL_ADDRESS_REGS */          \
4287 +  {0x0a000000, 0x00000000},    /* ACC_LO_REGS */               \
4288 +  {0x0f000000, 0x00000000},    /* ACC_REGS */                  \
4289 +  {0x40000000, 0x00000000},    /* CC_REG */                    \
4290 +  {0x0f00ffff, 0x00000000},    /* DATA_ACC_REGS */             \
4291 +  {0x10000000, 0x00000000},    /* SOURGE3_REG */               \
4292 +  {0x80000000, 0x0000007f},    /* SPECIAL_REGS */              \
4293 +  {0xbfffffff, 0x0000007f},    /* GENERAL_REGS */              \
4294 +  {0xbfffffff, 0x0000007f}     /* ALL_REGS     */              \
4295 +}
4296 +
4297 +extern enum reg_class const ubicom32_regclass_map[FIRST_PSEUDO_REGISTER];
4298 +
4299 +/* A C expression whose value is a register class containing hard register
4300 +   REGNO.  In general there is more than one such class; choose a class which
4301 +   is "minimal", meaning that no smaller class also contains the register.  */
4302 +#define REGNO_REG_CLASS(REGNO) (ubicom32_regclass_map[REGNO])
4303 +
4304 +#define IRA_COVER_CLASSES              \
4305 +{                                      \
4306 +  GENERAL_REGS,                                \
4307 +  LIM_REG_CLASSES                      \
4308 +}
4309 +
4310 +/* Ubicom32 base registers must be address registers since addresses can
4311 +   only be reached via address registers.  */
4312 +#define BASE_REG_CLASS ALL_ADDRESS_REGS
4313 +
4314 +/* Ubicom32 index registers must be data registers since we cannot add
4315 +   two address registers together to form an address.  */
4316 +#define INDEX_REG_CLASS DATA_REGS
4317 +
4318 +/* A C expression which is nonzero if register number NUM is suitable for use
4319 +   as a base register in operand addresses.  It may be either a suitable hard
4320 +   register or a pseudo register that has been allocated such a hard register.  */
4321 +
4322 +#ifndef REG_OK_STRICT
4323 +#define REGNO_OK_FOR_BASE_P(regno) \
4324 +  ubicom32_regno_ok_for_base_p (regno, 0)
4325 +#else
4326 +#define REGNO_OK_FOR_BASE_P(regno) \
4327 +  ubicom32_regno_ok_for_base_p (regno, 1)
4328 +#endif
4329 +
4330 +/* A C expression which is nonzero if register number NUM is suitable for use
4331 +   as an index register in operand addresses.  It may be either a suitable hard
4332 +   register or a pseudo register that has been allocated such a hard register.
4333 +
4334 +   The difference between an index register and a base register is that the
4335 +   index register may be scaled.  If an address involves the sum of two
4336 +   registers, neither one of them scaled, then either one may be labeled the
4337 +   "base" and the other the "index"; but whichever labeling is used must fit
4338 +   the machine's constraints of which registers may serve in each capacity.
4339 +   The compiler will try both labelings, looking for one that is valid, and
4340 +   will reload one or both registers only if neither labeling works.  */
4341 +#ifndef REG_OK_STRICT
4342 +#define REGNO_OK_FOR_INDEX_P(regno) \
4343 +  ubicom32_regno_ok_for_index_p (regno, 0)
4344 +#else
4345 +#define REGNO_OK_FOR_INDEX_P(regno) \
4346 +  ubicom32_regno_ok_for_index_p (regno, 1)
4347 +#endif
4348 +
4349 +/* Attempt to restrict the register class we need to copy value X intoto the
4350 +   would-be register class CLASS.  Most things are fine for Ubicom32 but we
4351 +   have to restrict certain types of address loads.  */
4352 +#define PREFERRED_RELOAD_CLASS(X, CLASS) \
4353 +  ubicom32_preferred_reload_class (X, CLASS)
4354 +
4355 +/* A C expression for the maximum number of consecutive registers of
4356 +   class CLASS needed to hold a value of mode MODE.  For Ubicom32 this
4357 +   is pretty much identical to HARD_REGNO_NREGS.  */
4358 +#define CLASS_MAX_NREGS(CLASS, MODE)   \
4359 +  ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
4360 +
4361 +/* For Ubicom32 the stack grows downwards when we push a word onto the stack
4362 +   - i.e. it moves to a smaller address.  */
4363 +#define STACK_GROWS_DOWNWARD 1
4364 +
4365 +/* Offset from the frame pointer to the first local variable slot to
4366 +   be allocated.  */
4367 +#define STARTING_FRAME_OFFSET 0
4368 +
4369 +/* Offset from the argument pointer register to the first argument's
4370 +   address.  */
4371 +#define FIRST_PARM_OFFSET(FNDECL) 0
4372 +
4373 +/* A C expression whose value is RTL representing the value of the return
4374 +   address for the frame COUNT steps up from the current frame, after the
4375 +   prologue.  FRAMEADDR is the frame pointer of the COUNT frame, or the frame
4376 +   pointer of the COUNT - 1 frame if `RETURN_ADDR_IN_PREVIOUS_FRAME' is
4377 +   defined.
4378 +
4379 +   The value of the expression must always be the correct address when COUNT is
4380 +   zero, but may be `NULL_RTX' if there is not way to determine the return
4381 +   address of other frames.  */
4382 +#define RETURN_ADDR_RTX(COUNT, FRAME) \
4383 +  ubicom32_return_addr_rtx (COUNT, FRAME)
4384 +
4385 +/* Register That Address the Stack Frame.  */
4386 +
4387 +/* We don't actually require a frame pointer in most functions with the
4388 +   Ubicom32 architecture so we allow it to be eliminated.  */
4389 +#define FRAME_POINTER_REQUIRED 0
4390 +
4391 +/* Macro that defines a table of register pairs used to eliminate unecessary
4392 +   registers that point into the stack frame.
4393 +
4394 +   For Ubicom32 we don't generally need an arg pointer of a frame pointer
4395 +   so we allow the arg pointer to be replaced by either the frame pointer or
4396 +   the stack pointer.  We also allow the frame pointer to be replaced by
4397 +   the stack pointer.  */
4398 +#define ELIMINABLE_REGS                                        \
4399 +{                                                      \
4400 +  {ARG_POINTER_REGNUM,  STACK_POINTER_REGNUM},         \
4401 +  {ARG_POINTER_REGNUM,  FRAME_POINTER_REGNUM},         \
4402 +  {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}         \
4403 +}
4404 +
4405 +/* Let the compiler know that we want to use the ELIMINABLE_REGS macro
4406 +   above.  */
4407 +#define CAN_ELIMINATE(FROM, TO) 1
4408 +
4409 +/* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'.  It specifies the
4410 +   initial difference between the specified pair of registers.  This macro must
4411 +   be defined if `ELIMINABLE_REGS' is defined.  */
4412 +#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
4413 +  (OFFSET) = ubicom32_initial_elimination_offset (FROM, TO)
4414 +
4415 +/* If defined, the maximum amount of space required for outgoing arguments will
4416 +   be computed and placed into the variable
4417 +   `current_function_outgoing_args_size'.  No space will be pushed onto the
4418 +   stack for each call; instead, the function prologue should increase the
4419 +   stack frame size by this amount.
4420 +
4421 +   Defining both `PUSH_ROUNDING' and `ACCUMULATE_OUTGOING_ARGS' is not
4422 +   proper.  */
4423 +#define ACCUMULATE_OUTGOING_ARGS 1
4424 +
4425 +/* Define this macro if functions should assume that stack space has been
4426 +   allocated for arguments even when their values are passed in registers.
4427 +
4428 +   The value of this macro is the size, in bytes, of the area reserved for
4429 +   arguments passed in registers for the function represented by FNDECL.
4430 +
4431 +   This space can be allocated by the caller, or be a part of the
4432 +   machine-dependent stack frame: `OUTGOING_REG_PARM_STACK_SPACE' says
4433 +   which.  */
4434 +#define REG_PARM_STACK_SPACE(FNDECL) ubicom32_reg_parm_stack_space(FNDECL)
4435 +
4436 +/* A C expression that should indicate the number of bytes of its own arguments
4437 +   that a function pops on returning, or 0 if the function pops no arguments
4438 +   and the caller must therefore pop them all after the function returns.
4439 +
4440 +   FUNDECL is a C variable whose value is a tree node that describes the
4441 +   function in question.  Normally it is a node of type `FUNCTION_DECL' that
4442 +   describes the declaration of the function.  From this it is possible to
4443 +   obtain the DECL_MACHINE_ATTRIBUTES of the function.
4444 +
4445 +   FUNTYPE is a C variable whose value is a tree node that describes the
4446 +   function in question.  Normally it is a node of type `FUNCTION_TYPE' that
4447 +   describes the data type of the function.  From this it is possible to obtain
4448 +   the data types of the value and arguments (if known).
4449 +
4450 +   When a call to a library function is being considered, FUNTYPE will contain
4451 +   an identifier node for the library function.  Thus, if you need to
4452 +   distinguish among various library functions, you can do so by their names.
4453 +   Note that "library function" in this context means a function used to
4454 +   perform arithmetic, whose name is known specially in the compiler and was
4455 +   not mentioned in the C code being compiled.
4456 +
4457 +   STACK-SIZE is the number of bytes of arguments passed on the stack.  If a
4458 +   variable number of bytes is passed, it is zero, and argument popping will
4459 +   always be the responsibility of the calling function.
4460 +
4461 +   On the Vax, all functions always pop their arguments, so the definition of
4462 +   this macro is STACK-SIZE.  On the 68000, using the standard calling
4463 +   convention, no functions pop their arguments, so the value of the macro is
4464 +   always 0 in this case.  But an alternative calling convention is available
4465 +   in which functions that take a fixed number of arguments pop them but other
4466 +   functions (such as `printf') pop nothing (the caller pops all).  When this
4467 +   convention is in use, FUNTYPE is examined to determine whether a function
4468 +   takes a fixed number of arguments.  */
4469 +#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0
4470 +
4471 +/* A C expression that controls whether a function argument is passed in a
4472 +   register, and which register.
4473 +
4474 +   The arguments are CUM, of type CUMULATIVE_ARGS, which summarizes (in a way
4475 +   defined by INIT_CUMULATIVE_ARGS and FUNCTION_ARG_ADVANCE) all of the previous
4476 +   arguments so far passed in registers; MODE, the machine mode of the argument;
4477 +   TYPE, the data type of the argument as a tree node or 0 if that is not known
4478 +   (which happens for C support library functions); and NAMED, which is 1 for an
4479 +   ordinary argument and 0 for nameless arguments that correspond to `...' in the
4480 +   called function's prototype.
4481 +
4482 +   The value of the expression should either be a `reg' RTX for the hard
4483 +   register in which to pass the argument, or zero to pass the argument on the
4484 +   stack.
4485 +
4486 +   For machines like the Vax and 68000, where normally all arguments are
4487 +   pushed, zero suffices as a definition.
4488 +
4489 +   The usual way to make the ANSI library `stdarg.h' work on a machine where
4490 +   some arguments are usually passed in registers, is to cause nameless
4491 +   arguments to be passed on the stack instead.  This is done by making
4492 +   `FUNCTION_ARG' return 0 whenever NAMED is 0.
4493 +
4494 +   You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the definition of
4495 +   this macro to determine if this argument is of a type that must be passed in
4496 +   the stack.  If `REG_PARM_STACK_SPACE' is not defined and `FUNCTION_ARG'
4497 +   returns non-zero for such an argument, the compiler will abort.  If
4498 +   `REG_PARM_STACK_SPACE' is defined, the argument will be computed in the
4499 +   stack and then loaded into a register.  */
4500 +#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
4501 +  function_arg (&CUM, MODE, TYPE, NAMED)
4502 +
4503 +#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \
4504 +  function_incoming_arg (&CUM, MODE, TYPE, NAMED)
4505 +
4506 +/* A C expression for the number of words, at the beginning of an argument,
4507 +   must be put in registers.  The value must be zero for arguments that are
4508 +   passed entirely in registers or that are entirely pushed on the stack.
4509 +
4510 +   On some machines, certain arguments must be passed partially in registers
4511 +   and partially in memory.  On these machines, typically the first N words of
4512 +   arguments are passed in registers, and the rest on the stack.  If a
4513 +   multi-word argument (a `double' or a structure) crosses that boundary, its
4514 +   first few words must be passed in registers and the rest must be pushed.
4515 +   This macro tells the compiler when this occurs, and how many of the words
4516 +   should go in registers.
4517 +
4518 +   `FUNCTION_ARG' for these arguments should return the first register to be
4519 +   used by the caller for this argument; likewise `FUNCTION_INCOMING_ARG', for
4520 +   the called function.  */
4521 +
4522 +/* A C expression that indicates when an argument must be passed by reference.
4523 +   If nonzero for an argument, a copy of that argument is made in memory and a
4524 +   pointer to the argument is passed instead of the argument itself.  The
4525 +   pointer is passed in whatever way is appropriate for passing a pointer to
4526 +   that type.
4527 +
4528 +   On machines where `REG_PARM_STACK_SPACE' is not defined, a suitable
4529 +   definition of this macro might be
4530 +       #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED)  \
4531 +         MUST_PASS_IN_STACK (MODE, TYPE)  */
4532 +
4533 +/* If defined, a C expression that indicates when it is the called function's
4534 +   responsibility to make a copy of arguments passed by invisible reference.
4535 +   Normally, the caller makes a copy and passes the address of the copy to the
4536 +   routine being called.  When FUNCTION_ARG_CALLEE_COPIES is defined and is
4537 +   nonzero, the caller does not make a copy.  Instead, it passes a pointer to
4538 +   the "live" value.  The called function must not modify this value.  If it
4539 +   can be determined that the value won't be modified, it need not make a copy;
4540 +   otherwise a copy must be made.  */
4541 +
4542 +/* A C type for declaring a variable that is used as the first argument of
4543 +   `FUNCTION_ARG' and other related values.  For some target machines, the type
4544 +   `int' suffices and can hold the number of bytes of argument so far.
4545 +
4546 +   There is no need to record in `CUMULATIVE_ARGS' anything about the arguments
4547 +   that have been passed on the stack.  The compiler has other variables to
4548 +   keep track of that.  For target machines on which all arguments are passed
4549 +   on the stack, there is no need to store anything in `CUMULATIVE_ARGS';
4550 +   however, the data structure must exist and should not be empty, so use
4551 +   `int'.  */
4552 +struct cum_arg
4553 +{
4554 +  int nbytes;
4555 +  int reg;
4556 +  int stdarg;
4557 +};
4558 +#define CUMULATIVE_ARGS struct cum_arg
4559 +
4560 +/* A C statement (sans semicolon) for initializing the variable CUM for the
4561 +   state at the beginning of the argument list.  The variable has type
4562 +   `CUMULATIVE_ARGS'.  The value of FNTYPE is the tree node for the data type
4563 +   of the function which will receive the args, or 0 if the args are to a
4564 +   compiler support library function.  The value of INDIRECT is nonzero when
4565 +   processing an indirect call, for example a call through a function pointer.
4566 +   The value of INDIRECT is zero for a call to an explicitly named function, a
4567 +   library function call, or when `INIT_CUMULATIVE_ARGS' is used to find
4568 +   arguments for the function being compiled.
4569 +
4570 +   When processing a call to a compiler support library function, LIBNAME
4571 +   identifies which one.  It is a `symbol_ref' rtx which contains the name of
4572 +   the function, as a string.  LIBNAME is 0 when an ordinary C function call is
4573 +   being processed.  Thus, each time this macro is called, either LIBNAME or
4574 +   FNTYPE is nonzero, but never both of them at once.  */
4575 +
4576 +#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT, NAMED_ARGS)  \
4577 + init_cumulative_args (&(CUM), FNTYPE, LIBNAME, INDIRECT);
4578 +
4579 +/* A C statement (sans semicolon) to update the summarizer variable CUM to
4580 +   advance past an argument in the argument list.  The values MODE, TYPE and
4581 +   NAMED describe that argument.  Once this is done, the variable CUM is
4582 +   suitable for analyzing the *following* argument with `FUNCTION_ARG', etc.
4583 +
4584 +   This macro need not do anything if the argument in question was passed on
4585 +   the stack.  The compiler knows how to track the amount of stack space used
4586 +   for arguments without any special help.  */
4587 +#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED)   \
4588 + ((CUM).nbytes += ((MODE) != BLKmode                   \
4589 +                  ? (GET_MODE_SIZE (MODE) + 3) & ~3    \
4590 +                  : (int_size_in_bytes (TYPE) + 3) & ~3))
4591 +
4592 +/* For the Ubicom32 we define the upper function argument register here.  */
4593 +#define UBICOM32_FUNCTION_ARG_REGS 10
4594 +
4595 +/* A C expression that is nonzero if REGNO is the number of a hard register in
4596 +   which function arguments are sometimes passed.  This does *not* include
4597 +   implicit arguments such as the static chain and the structure-value address.
4598 +   On many machines, no registers can be used for this purpose since all
4599 +   function arguments are pushed on the stack.  */
4600 +#define FUNCTION_ARG_REGNO_P(N) ((N) < UBICOM32_FUNCTION_ARG_REGS)
4601 +
4602 +\f
4603 +/* How Scalar Function Values are Returned.  */
4604 +
4605 +/* The number of the hard register that is used to return a scalar value from a
4606 +   function call.  */
4607 +#define RETURN_VALUE_REGNUM 0
4608 +
4609 +/* A C expression to create an RTX representing the place where a function
4610 +   returns a value of data type VALTYPE.  VALTYPE is a tree node representing a
4611 +   data type.  Write `TYPE_MODE (VALTYPE)' to get the machine mode used to
4612 +   represent that type.  On many machines, only the mode is relevant.
4613 +   (Actually, on most machines, scalar values are returned in the same place
4614 +   regardless of mode).
4615 +
4616 +   If `PROMOTE_FUNCTION_RETURN' is defined, you must apply the same promotion
4617 +   rules specified in `PROMOTE_MODE' if VALTYPE is a scalar type.
4618 +
4619 +   If the precise function being called is known, FUNC is a tree node
4620 +   (`FUNCTION_DECL') for it; otherwise, FUNC is a null pointer.  This makes it
4621 +   possible to use a different value-returning convention for specific
4622 +   functions when all their calls are known.
4623 +
4624 +   `FUNCTION_VALUE' is not used for return vales with aggregate data types,
4625 +   because these are returned in another way.  See `STRUCT_VALUE_REGNUM' and
4626 +   related macros, below.  */
4627 +#define FUNCTION_VALUE(VALTYPE, FUNC) \
4628 +  gen_rtx_REG (TYPE_MODE (VALTYPE), FIRST_DATA_REGNUM)
4629 +
4630 +/* A C expression to create an RTX representing the place where a library
4631 +   function returns a value of mode MODE.
4632 +
4633 +   Note that "library function" in this context means a compiler support
4634 +   routine, used to perform arithmetic, whose name is known specially by the
4635 +   compiler and was not mentioned in the C code being compiled.
4636 +
4637 +   The definition of `LIBRARY_VALUE' need not be concerned aggregate data
4638 +   types, because none of the library functions returns such types.  */
4639 +#define LIBCALL_VALUE(MODE) gen_rtx_REG (MODE, FIRST_DATA_REGNUM)
4640 +
4641 +/* A C expression that is nonzero if REGNO is the number of a hard register in
4642 +   which the values of called function may come back.
4643 +
4644 +   A register whose use for returning values is limited to serving as the
4645 +   second of a pair (for a value of type `double', say) need not be recognized
4646 +   by this macro.  So for most machines, this definition suffices:
4647 +
4648 +       #define FUNCTION_VALUE_REGNO_P(N) ((N) == RETURN)
4649 +
4650 +   If the machine has register windows, so that the caller and the called
4651 +   function use different registers for the return value, this macro should
4652 +   recognize only the caller's register numbers.  */
4653 +#define FUNCTION_VALUE_REGNO_P(N) ((N) == FIRST_DATA_REGNUM)
4654 +
4655 +\f
4656 +/* How Large Values are Returned.  */
4657 +
4658 +/* A C expression which can inhibit the returning of certain function values in
4659 +   registers, based on the type of value.  A nonzero value says to return the
4660 +   function value in memory, just as large structures are always returned.
4661 +   Here TYPE will be a C expression of type `tree', representing the data type
4662 +   of the value.
4663 +
4664 +   Note that values of mode `BLKmode' must be explicitly handled by this macro.
4665 +   Also, the option `-fpcc-struct-return' takes effect regardless of this
4666 +   macro.  On most systems, it is possible to leave the macro undefined; this
4667 +   causes a default definition to be used, whose value is the constant 1 for
4668 +   `BLKmode' values, and 0 otherwise.
4669 +
4670 +   Do not use this macro to indicate that structures and unions should always
4671 +   be returned in memory.  You should instead use `DEFAULT_PCC_STRUCT_RETURN'
4672 +   to indicate this.  */
4673 +#define RETURN_IN_MEMORY(TYPE)  \
4674 +  (int_size_in_bytes (TYPE) > 8 || TYPE_MODE (TYPE) == BLKmode)
4675 +
4676 +/* Define this macro to be 1 if all structure and union return values must be
4677 +   in memory.  Since this results in slower code, this should be defined only
4678 +   if needed for compatibility with other compilers or with an ABI.  If you
4679 +   define this macro to be 0, then the conventions used for structure and union
4680 +   return values are decided by the `RETURN_IN_MEMORY' macro.
4681 +
4682 +   If not defined, this defaults to the value 1.  */
4683 +#define DEFAULT_PCC_STRUCT_RETURN 0
4684 +
4685 +/*   If the structure value address is not passed in a register, define
4686 +     `STRUCT_VALUE' as an expression returning an RTX for the place
4687 +     where the address is passed.  If it returns 0, the address is
4688 +     passed as an "invisible" first argument.  */
4689 +#define STRUCT_VALUE 0
4690 +
4691 +/* Define this macro as a C expression that is nonzero if the return
4692 +   instruction or the function epilogue ignores the value of the stack pointer;
4693 +   in other words, if it is safe to delete an instruction to adjust the stack
4694 +   pointer before a return from the function.
4695 +
4696 +   Note that this macro's value is relevant only for functions for which frame
4697 +   pointers are maintained.  It is never safe to delete a final stack
4698 +   adjustment in a function that has no frame pointer, and the compiler knows
4699 +   this regardless of `EXIT_IGNORE_STACK'.  */
4700 +#define EXIT_IGNORE_STACK 1
4701 +
4702 +/* A C statement or compound statement to output to FILE some assembler code to
4703 +   call the profiling subroutine `mcount'.  Before calling, the assembler code
4704 +   must load the address of a counter variable into a register where `mcount'
4705 +   expects to find the address.  The name of this variable is `LP' followed by
4706 +   the number LABELNO, so you would generate the name using `LP%d' in a
4707 +   `fprintf'.
4708 +
4709 +   The details of how the address should be passed to `mcount' are determined
4710 +   by your operating system environment, not by GNU CC.  To figure them out,
4711 +   compile a small program for profiling using the system's installed C
4712 +   compiler and look at the assembler code that results.
4713 +
4714 +   This declaration must be present, but it can be an abort if profiling is
4715 +   not implemented.  */
4716 +
4717 +#define FUNCTION_PROFILER(file, labelno) ubicom32_profiler(file, labelno)
4718 +
4719 +/* A C statement to output, on the stream FILE, assembler code for a block of
4720 +   data that contains the constant parts of a trampoline.  This code should not
4721 +   include a label--the label is taken care of automatically.  */
4722 +#if 0
4723 +#define TRAMPOLINE_TEMPLATE(FILE)                      \
4724 +  do {                                                 \
4725 +    fprintf (FILE, "\tadd -4,sp\n");                   \
4726 +    fprintf (FILE, "\t.long 0x0004fffa\n");            \
4727 +    fprintf (FILE, "\tmov (0,sp),a0\n");               \
4728 +    fprintf (FILE, "\tadd 4,sp\n");                    \
4729 +    fprintf (FILE, "\tmov (13,a0),a1\n");              \
4730 +    fprintf (FILE, "\tmov (17,a0),a0\n");              \
4731 +    fprintf (FILE, "\tjmp (a0)\n");                    \
4732 +    fprintf (FILE, "\t.long 0\n");                     \
4733 +    fprintf (FILE, "\t.long 0\n");                     \
4734 +  } while (0)
4735 +#endif
4736 +
4737 +/* A C expression for the size in bytes of the trampoline, as an integer.  */
4738 +#define TRAMPOLINE_SIZE 0x1b
4739 +
4740 +/* Alignment required for trampolines, in bits.
4741 +
4742 +   If you don't define this macro, the value of `BIGGEST_ALIGNMENT' is used for
4743 +   aligning trampolines.  */
4744 +#define TRAMPOLINE_ALIGNMENT 32
4745 +
4746 +/* A C statement to initialize the variable parts of a trampoline.  ADDR is an
4747 +   RTX for the address of the trampoline; FNADDR is an RTX for the address of
4748 +   the nested function; STATIC_CHAIN is an RTX for the static chain value that
4749 +   should be passed to the function when it is called.  */
4750 +#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT)                      \
4751 +{                                                                      \
4752 +  emit_move_insn (gen_rtx_MEM (SImode, plus_constant ((TRAMP), 0x14)), \
4753 +                (CXT));                                                \
4754 +  emit_move_insn (gen_rtx_MEM (SImode, plus_constant ((TRAMP), 0x18)), \
4755 +                (FNADDR));                                             \
4756 +}
4757 +
4758 +/* Ubicom32 supports pre and post increment/decrement addressing.  */
4759 +#define HAVE_POST_INCREMENT 1
4760 +#define HAVE_PRE_INCREMENT 1
4761 +#define HAVE_POST_DECREMENT 1
4762 +#define HAVE_PRE_DECREMENT 1
4763 +
4764 +/* Ubicom32 supports pre and post address side-effects with constants
4765 +   other than the size of the memory operand.  */
4766 +#define HAVE_PRE_MODIFY_DISP 1
4767 +#define HAVE_POST_MODIFY_DISP 1
4768 +
4769 +/* A C expression that is 1 if the RTX X is a constant which is a valid
4770 +   address.  On most machines, this can be defined as `CONSTANT_P (X)',
4771 +   but a few machines are more restrictive in which constant addresses
4772 +   are supported.
4773 +
4774 +   `CONSTANT_P' accepts integer-values expressions whose values are not
4775 +   explicitly known, such as `symbol_ref', `label_ref', and `high'
4776 +   expressions and `const' arithmetic expressions, in addition to
4777 +   `const_int' and `const_double' expressions.  */
4778 +#define CONSTANT_ADDRESS_P(X)                                          \
4779 +  (GET_CODE (X) == LABEL_REF                                           \
4780 +   || (GET_CODE (X) == CONST                                           \
4781 +       && GET_CODE (XEXP (X, 0)) == PLUS                               \
4782 +       && GET_CODE (XEXP (XEXP (X, 0), 0)) == LABEL_REF))
4783 +
4784 +/* Ubicom32 supports a maximum of 2 registers in a valid memory address.
4785 +   One is always an address register while a second, optional, one may be a
4786 +   data register.  */
4787 +#define MAX_REGS_PER_ADDRESS 2
4788 +
4789 +/* A C compound statement with a conditional `goto LABEL;' executed if X (an
4790 +   RTX) is a legitimate memory address on the target machine for a memory
4791 +   operand of mode MODE.
4792 +
4793 +   It usually pays to define several simpler macros to serve as subroutines for
4794 +   this one.  Otherwise it may be too complicated to understand.
4795 +
4796 +   This macro must exist in two variants: a strict variant and a non-strict
4797 +   one.  The strict variant is used in the reload pass.  It must be defined so
4798 +   that any pseudo-register that has not been allocated a hard register is
4799 +   considered a memory reference.  In contexts where some kind of register is
4800 +   required, a pseudo-register with no hard register must be rejected.
4801 +
4802 +   The non-strict variant is used in other passes.  It must be defined to
4803 +   accept all pseudo-registers in every context where some kind of register is
4804 +   required.
4805 +
4806 +   Compiler source files that want to use the strict variant of this macro
4807 +   define the macro `REG_OK_STRICT'.  You should use an `#ifdef REG_OK_STRICT'
4808 +   conditional to define the strict variant in that case and the non-strict
4809 +   variant otherwise.
4810 +
4811 +   Subroutines to check for acceptable registers for various purposes (one for
4812 +   base registers, one for index registers, and so on) are typically among the
4813 +   subroutines used to define `GO_IF_LEGITIMATE_ADDRESS'.  Then only these
4814 +   subroutine macros need have two variants; the higher levels of macros may be
4815 +   the same whether strict or not.
4816 +
4817 +   Normally, constant addresses which are the sum of a `symbol_ref' and an
4818 +   integer are stored inside a `const' RTX to mark them as constant.
4819 +   Therefore, there is no need to recognize such sums specifically as
4820 +   legitimate addresses.  Normally you would simply recognize any `const' as
4821 +   legitimate.
4822 +
4823 +   Usually `PRINT_OPERAND_ADDRESS' is not prepared to handle constant sums that
4824 +   are not marked with `const'.  It assumes that a naked `plus' indicates
4825 +   indexing.  If so, then you *must* reject such naked constant sums as
4826 +   illegitimate addresses, so that none of them will be given to
4827 +   `PRINT_OPERAND_ADDRESS'.
4828 +
4829 +   On some machines, whether a symbolic address is legitimate depends on the
4830 +   section that the address refers to.  On these machines, define the macro
4831 +   `ENCODE_SECTION_INFO' to store the information into the `symbol_ref', and
4832 +   then check for it here.  When you see a `const', you will have to look
4833 +   inside it to find the `symbol_ref' in order to determine the section.
4834 +
4835 +   The best way to modify the name string is by adding text to the beginning,
4836 +   with suitable punctuation to prevent any ambiguity.  Allocate the new name
4837 +   in `saveable_obstack'.  You will have to modify `ASM_OUTPUT_LABELREF' to
4838 +   remove and decode the added text and output the name accordingly, and define
4839 +   `STRIP_NAME_ENCODING' to access the original name string.
4840 +
4841 +   You can check the information stored here into the `symbol_ref' in the
4842 +   definitions of the macros `GO_IF_LEGITIMATE_ADDRESS' and
4843 +   `PRINT_OPERAND_ADDRESS'.  */
4844 +/* On the ubicom32, the value in the address register must be
4845 +   in the same memory space/segment as the effective address.
4846 +
4847 +   This is problematical for reload since it does not understand
4848 +   that base+index != index+base in a memory reference.  */
4849 +
4850 +#ifdef REG_OK_STRICT
4851 +#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)        \
4852 +  if (ubicom32_legitimate_address_p (MODE, X, 1)) goto ADDR;
4853 +#else
4854 +#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)        \
4855 +  if (ubicom32_legitimate_address_p (MODE, X, 0)) goto ADDR;
4856 +#endif
4857 +
4858 +/* Try machine-dependent ways of modifying an illegitimate address
4859 +   to be legitimate.  If we find one, return the new, valid address.
4860 +   This macro is used in only one place: `memory_address' in explow.c.
4861 +
4862 +   OLDX is the address as it was before break_out_memory_refs was called.
4863 +   In some cases it is useful to look at this to decide what needs to be done.
4864 +
4865 +   MODE and WIN are passed so that this macro can use
4866 +   GO_IF_LEGITIMATE_ADDRESS.
4867 +
4868 +   It is always safe for this macro to do nothing.  It exists to recognize
4869 +   opportunities to optimize the output.
4870 +
4871 +   On RS/6000, first check for the sum of a register with a constant
4872 +   integer that is out of range.  If so, generate code to add the
4873 +   constant with the low-order 16 bits masked to the register and force
4874 +   this result into another register (this can be done with `cau').
4875 +   Then generate an address of REG+(CONST&0xffff), allowing for the
4876 +   possibility of bit 16 being a one.
4877 +
4878 +   Then check for the sum of a register and something not constant, try to
4879 +   load the other things into a register and return the sum.  */
4880 +
4881 +#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)                         \
4882 +{                                                                      \
4883 +   rtx result = ubicom32_legitimize_address ((X), (OLDX), (MODE));     \
4884 +   if (result != NULL_RTX)                                             \
4885 +     {                                                                 \
4886 +       (X) = result;                                                   \
4887 +       goto WIN;                                                       \
4888 +     }                                                                 \
4889 +}
4890 +
4891 +/* Try a machine-dependent way of reloading an illegitimate address
4892 +   operand.  If we find one, push the reload and jump to WIN.  This
4893 +   macro is used in only one place: `find_reloads_address' in reload.c.  */
4894 +#define LEGITIMIZE_RELOAD_ADDRESS(AD, MODE, OPNUM, TYPE, IND, WIN)     \
4895 +{                                                                      \
4896 +  rtx new_rtx = ubicom32_legitimize_reload_address ((AD), (MODE), (OPNUM), (int)(TYPE));       \
4897 +  if (new_rtx)                                                         \
4898 +    {                                                                  \
4899 +      (AD) = new_rtx;                                                  \
4900 +      goto WIN;                                                                \
4901 +    }                                                                  \
4902 +}
4903 +
4904 +/* A C statement or compound statement with a conditional `goto LABEL;'
4905 +   executed if memory address X (an RTX) can have different meanings depending
4906 +   on the machine mode of the memory reference it is used for or if the address
4907 +   is valid for some modes but not others.
4908 +
4909 +   Autoincrement and autodecrement addresses typically have mode-dependent
4910 +   effects because the amount of the increment or decrement is the size of the
4911 +   operand being addressed.  Some machines have other mode-dependent addresses.
4912 +   Many RISC machines have no mode-dependent addresses.
4913 +
4914 +   You may assume that ADDR is a valid address for the machine.  */
4915 +#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)      \
4916 +  if (ubicom32_mode_dependent_address_p (ADDR))                \
4917 +    goto LABEL;
4918 +
4919 +/* A C expression that is nonzero if X is a legitimate constant for an
4920 +   immediate operand on the target machine.  You can assume that X
4921 +   satisfies `CONSTANT_P', so you need not check this.  In fact, `1' is
4922 +   a suitable definition for this macro on machines where anything
4923 +   `CONSTANT_P' is valid.  */
4924 +#define LEGITIMATE_CONSTANT_P(X) \
4925 +  ubicom32_legitimate_constant_p ((X))
4926 +
4927 +/* Moves between registers are pretty-much single instructions for
4928 +   Ubicom32.  We make this the default "2" that gcc likes.  */
4929 +#define REGISTER_MOVE_COST(MODE, FROM, TO) 2
4930 +
4931 +/* This is a little bit of magic from the S390 port that wins 2% on code
4932 +   size when building the Linux kernel!  Unfortunately while it wins on
4933 +   that size the user-space apps built using FD-PIC don't improve and the
4934 +   performance is lower because we put more pressure on the caches.  We may
4935 +   want this back on some future CPU that has higher cache performance.  */
4936 +/* #define IRA_HARD_REGNO_ADD_COST_MULTIPLIER(regno) 0.5 */
4937 +
4938 +/* Moves between registers and memory are more expensive than between
4939 +   registers because we have caches and write buffers that slow things
4940 +   down!  */
4941 +#define MEMORY_MOVE_COST(MODE, CLASS, IN) 2
4942 +
4943 +/* A fall-through branch is very low cost but anything that changes the PC
4944 +   incurs a major pipeline hazard.  We don't make the full extent of this
4945 +   hazard visible because we hope that multiple threads will absorb much
4946 +   of the cost and so we don't want a jump being replaced with, say, 7
4947 +   instructions.  */
4948 +#define BRANCH_COST(SPEED_P, PREDICTABLE_P) \
4949 +  ((PREDICTABLE_P) ? 1 : 3)
4950 +
4951 +/* Define this macro as a C expression which is nonzero if accessing less than
4952 +   a word of memory (i.e. a `char' or a `short') is no faster than accessing a
4953 +   word of memory, i.e., if such access require more than one instruction or if
4954 +   there is no difference in cost between byte and (aligned) word loads.
4955 +
4956 +   When this macro is not defined, the compiler will access a field by finding
4957 +   the smallest containing object; when it is defined, a fullword load will be
4958 +   used if alignment permits.  Unless bytes accesses are faster than word
4959 +   accesses, using word accesses is preferable since it may eliminate
4960 +   subsequent memory access if subsequent accesses occur to other fields in the
4961 +   same word of the structure, but to different bytes.  */
4962 +#define SLOW_BYTE_ACCESS 0
4963 +
4964 +/* The number of scalar move insns which should be generated instead of a
4965 +   string move insn or a library call.  Increasing the value will always make
4966 +   code faster, but eventually incurs high cost in increased code size.
4967 +
4968 +   If you don't define this, a reasonable default is used.  */
4969 +/* According to expr.c, a value of around 6 should minimize code size.  */
4970 +#define MOVE_RATIO(SPEED) 6
4971 +
4972 +/* We're much better off calling a constant function address with the
4973 +   Ubicom32 architecture because we have an opcode for doing so.  Don't
4974 +   let the compiler extract function addresses as common subexpressions
4975 +   into an address register.  */
4976 +#define NO_FUNCTION_CSE
4977 +
4978 +#define SELECT_CC_MODE(OP, X, Y) ubicom32_select_cc_mode (OP, X, Y)
4979 +
4980 +#define REVERSIBLE_CC_MODE(MODE) 1
4981 +
4982 +/* Canonicalize a comparison from one we don't have to one we do have.  */
4983 +#define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
4984 +  ubicom32_canonicalize_comparison (&(CODE), &(OP0), &(OP1))
4985 +
4986 +/* Dividing the output into sections.  */
4987 +
4988 +/* A C expression whose value is a string containing the assembler operation
4989 +   that should precede instructions and read-only data.  Normally `".text"' is
4990 +   right.  */
4991 +#define TEXT_SECTION_ASM_OP "\t.section .text"
4992 +
4993 +/* A C expression whose value is a string containing the assembler operation to
4994 +   identify the following data as writable initialized data.  Normally
4995 +   `".data"' is right.  */
4996 +#define DATA_SECTION_ASM_OP "\t.section .data"
4997 +
4998 +
4999 +/* If defined, a C expression whose value is a string containing the
5000 +   assembler operation to identify the following data as
5001 +   uninitialized global data.  If not defined, and neither
5002 +   `ASM_OUTPUT_BSS' nor `ASM_OUTPUT_ALIGNED_BSS' are defined,
5003 +   uninitialized global data will be output in the data section if
5004 +   `-fno-common' is passed, otherwise `ASM_OUTPUT_COMMON' will be
5005 +   used.  */
5006 +#define BSS_SECTION_ASM_OP "\t.section .bss"
5007 +
5008 +/* This is how we tell the assembler that a symbol is weak.  */
5009 +
5010 +#define ASM_WEAKEN_LABEL(FILE, NAME)   \
5011 +  do                                   \
5012 +    {                                  \
5013 +      fputs ("\t.weak\t", (FILE));     \
5014 +      assemble_name ((FILE), (NAME));  \
5015 +      fputc ('\n', (FILE));            \
5016 +    }                                  \
5017 +  while (0)
5018 +
5019 +/* The Overall Framework of an Assembler File.  */
5020 +
5021 +#undef SET_ASM_OP
5022 +#define SET_ASM_OP "\t.set\t"
5023 +
5024 +/* A C string constant describing how to begin a comment in the target
5025 +   assembler language.  The compiler assumes that the comment will end at the
5026 +   end of the line.  */
5027 +#define ASM_COMMENT_START ";"
5028 +
5029 +/* A C string constant for text to be output before each `asm' statement or
5030 +   group of consecutive ones.  Normally this is `"#APP"', which is a comment
5031 +   that has no effect on most assemblers but tells the GNU assembler that it
5032 +   must check the lines that follow for all valid assembler constructs.  */
5033 +#define ASM_APP_ON "#APP\n"
5034 +
5035 +/* A C string constant for text to be output after each `asm' statement or
5036 +   group of consecutive ones.  Normally this is `"#NO_APP"', which tells the
5037 +   GNU assembler to resume making the time-saving assumptions that are valid
5038 +   for ordinary compiler output.  */
5039 +#define ASM_APP_OFF "#NO_APP\n"
5040 +
5041 +/* Like `ASM_OUTPUT_BSS' except takes the required alignment as a separate,
5042 +   explicit argument.  If you define this macro, it is used in place of
5043 +   `ASM_OUTPUT_BSS', and gives you more flexibility in handling the required
5044 +   alignment of the variable.  The alignment is specified as the number of
5045 +   bits.
5046 +
5047 +   Try to use function `asm_output_aligned_bss' defined in file `varasm.c' when
5048 +   defining this macro.  */
5049 +#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
5050 +  asm_output_aligned_bss ((FILE), (DECL), (NAME), (SIZE), (ALIGN))
5051 +
5052 +/* A C expression to assign to OUTVAR (which is a variable of type `char *') a
5053 +   newly allocated string made from the string NAME and the number NUMBER, with
5054 +   some suitable punctuation added.  Use `alloca' to get space for the string.
5055 +
5056 +   The string will be used as an argument to `ASM_OUTPUT_LABELREF' to produce
5057 +   an assembler label for an internal static variable whose name is NAME.
5058 +   Therefore, the string must be such as to result in valid assembler code.
5059 +   The argument NUMBER is different each time this macro is executed; it
5060 +   prevents conflicts between similarly-named internal static variables in
5061 +   different scopes.
5062 +
5063 +   Ideally this string should not be a valid C identifier, to prevent any
5064 +   conflict with the user's own symbols.  Most assemblers allow periods or
5065 +   percent signs in assembler symbols; putting at least one of these between
5066 +   the name and the number will suffice.  */
5067 +#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
5068 +  ((OUTPUT) = (char *) alloca (strlen ((NAME)) + 10),  \
5069 +   sprintf ((OUTPUT), "%s___%d", (NAME), (LABELNO)))
5070 +
5071 +#define ASM_GENERATE_INTERNAL_LABEL(STRING, PREFIX, NUM)       \
5072 +  sprintf (STRING, "*.%s%ld", PREFIX, (long)(NUM))
5073 +/* A C statement to store into the string STRING a label whose name
5074 +   is made from the string PREFIX and the number NUM.
5075 +
5076 +   This string, when output subsequently by `assemble_name', should
5077 +   produce the output that `(*targetm.asm_out.internal_label)' would produce
5078 +   with the same PREFIX and NUM.
5079 +
5080 +   If the string begins with `*', then `assemble_name' will output
5081 +   the rest of the string unchanged.  It is often convenient for
5082 +   `ASM_GENERATE_INTERNAL_LABEL' to use `*' in this way.  If the
5083 +   string doesn't start with `*', then `ASM_OUTPUT_LABELREF' gets to
5084 +   output the string, and may change it.  (Of course,
5085 +   `ASM_OUTPUT_LABELREF' is also part of your machine description, so
5086 +   you should know what it does on your machine.)  */
5087 +
5088 +/* This says how to output assembler code to declare an
5089 +   uninitialized external linkage data object.  Under SVR4,
5090 +   the linker seems to want the alignment of data objects
5091 +   to depend on their types.  We do exactly that here.  */
5092 +
5093 +#define COMMON_ASM_OP  "\t.comm\t"
5094 +
5095 +#undef  ASM_OUTPUT_COMMON
5096 +#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED)           \
5097 +  do                                                           \
5098 +    {                                                          \
5099 +      fprintf ((FILE), "%s", COMMON_ASM_OP);                   \
5100 +      assemble_name ((FILE), (NAME));                          \
5101 +      fprintf ((FILE), ", %u\n", (SIZE));                      \
5102 +    }                                                          \
5103 +  while (0)
5104 +
5105 +/* This says how to output assembler code to declare an
5106 +   uninitialized internal linkage data object.  Under SVR4,
5107 +   the linker seems to want the alignment of data objects
5108 +   to depend on their types.  We do exactly that here.  */
5109 +#define LOCAL_ASM_OP   "\t.lcomm\t"
5110 +
5111 +#undef  ASM_OUTPUT_LOCAL
5112 +#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED)            \
5113 +  do                                                           \
5114 +    {                                                          \
5115 +      fprintf ((FILE), "%s", LOCAL_ASM_OP);                    \
5116 +      assemble_name ((FILE), (NAME));                          \
5117 +      fprintf ((FILE), ", %u\n", (SIZE));                      \
5118 +    }                                                          \
5119 +  while (0)
5120 +
5121 +/* Globalizing directive for a label.  */
5122 +#define GLOBAL_ASM_OP ".global\t"
5123 +
5124 +/* Output the operand of an instruction.  */
5125 +#define PRINT_OPERAND(FILE, X, CODE) \
5126 +  ubicom32_print_operand(FILE, X, CODE)
5127 +
5128 +/* Output the address of an operand.  */
5129 +#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
5130 +  ubicom32_print_operand_address (FILE, ADDR)
5131 +
5132 +/* A C expression to output to STREAM some assembler code which will push hard
5133 +   register number REGNO onto the stack.  The code need not be optimal, since
5134 +   this macro is used only when profiling.  */
5135 +#define ASM_OUTPUT_REG_PUSH(FILE, REGNO)
5136 +
5137 +/* A C expression to output to STREAM some assembler code which will pop hard
5138 +   register number REGNO off of the stack.  The code need not be optimal, since
5139 +   this macro is used only when profiling.  */
5140 +#define ASM_OUTPUT_REG_POP(FILE, REGNO)
5141 +
5142 +/* This macro should be provided on machines where the addresses in a dispatch
5143 +   table are relative to the table's own address.
5144 +
5145 +   The definition should be a C statement to output to the stdio stream STREAM
5146 +   an assembler pseudo-instruction to generate a difference between two labels.
5147 +   VALUE and REL are the numbers of two internal labels.  The definitions of
5148 +   these labels are output using `ASM_OUTPUT_INTERNAL_LABEL', and they must be
5149 +   printed in the same way here.  For example,
5150 +
5151 +       fprintf (STREAM, "\t.word L%d-L%d\n", VALUE, REL)  */
5152 +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
5153 +  fprintf (FILE, "\t%s .L%d-.L%d\n", ".long", VALUE, REL)
5154 +
5155 +/* This macro should be provided on machines where the addresses in a dispatch
5156 +   table are absolute.
5157 +
5158 +   The definition should be a C statement to output to the stdio stream STREAM
5159 +   an assembler pseudo-instruction to generate a reference to a label.  VALUE
5160 +   is the number of an internal label whose definition is output using
5161 +   `ASM_OUTPUT_INTERNAL_LABEL'.  For example,
5162 +
5163 +       fprintf (STREAM, "\t.word L%d\n", VALUE)  */
5164 +#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
5165 +  fprintf (STREAM, "\t.word .L%d\n", VALUE)
5166 +
5167 +/* Switch into a generic section.  */
5168 +#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section
5169 +
5170 +/* Assembler Commands for Alignment.  */
5171 +
5172 +#define ASM_OUTPUT_SKIP(STREAM, N) fprintf (STREAM, "\t.skip %d,0\n", N)
5173 +/* A C statement to output to the stdio stream STREAM an assembler
5174 +   instruction to advance the location counter by NBYTES bytes.
5175 +   Those bytes should be zero when loaded.  NBYTES will be a C
5176 +   expression of type `int'.  */
5177 +
5178 +/* A C statement to output to the stdio stream STREAM an assembler command to
5179 +   advance the location counter to a multiple of 2 to the POWER bytes.  POWER
5180 +   will be a C expression of type `int'.  */
5181 +#define ASM_OUTPUT_ALIGN(FILE, LOG)    \
5182 +  if ((LOG) != 0)                      \
5183 +    fprintf (FILE, "\t.align %d\n", (LOG))
5184 +
5185 +/* A C expression that returns the DBX register number for the compiler
5186 +   register number REGNO.  In simple cases, the value of this expression may be
5187 +   REGNO itself.  But sometimes there are some registers that the compiler
5188 +   knows about and DBX does not, or vice versa.  In such cases, some register
5189 +   may need to have one number in the compiler and another for DBX.
5190 +
5191 +   If two registers have consecutive numbers inside GNU CC, and they can be
5192 +   used as a pair to hold a multiword value, then they *must* have consecutive
5193 +   numbers after renumbering with `DBX_REGISTER_NUMBER'.  Otherwise, debuggers
5194 +   will be unable to access such a pair, because they expect register pairs to
5195 +   be consecutive in their own numbering scheme.
5196 +
5197 +   If you find yourself defining `DBX_REGISTER_NUMBER' in way that does not
5198 +   preserve register pairs, then what you must do instead is redefine the
5199 +   actual register numbering scheme.
5200 +
5201 +   This declaration is required.  */
5202 +#define DBX_REGISTER_NUMBER(REGNO) REGNO
5203 +
5204 +/* A C expression that returns the integer offset value for an automatic
5205 +   variable having address X (an RTL expression).  The default computation
5206 +   assumes that X is based on the frame-pointer and gives the offset from the
5207 +   frame-pointer.  This is required for targets that produce debugging output
5208 +   for DBX or COFF-style debugging output for SDB and allow the frame-pointer
5209 +   to be eliminated when the `-g' options is used.  */
5210 +#define DEBUGGER_AUTO_OFFSET(X)                                                \
5211 +  ((GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0)                   \
5212 +    + (frame_pointer_needed                                            \
5213 +       ? 0 : -initial_elimination_offset (FRAME_POINTER_REGNUM,                \
5214 +                                         STACK_POINTER_REGNUM)))
5215 +
5216 +/* A C expression that returns the integer offset value for an argument having
5217 +   address X (an RTL expression).  The nominal offset is OFFSET.  */
5218 +#define DEBUGGER_ARG_OFFSET(OFFSET, X)                                 \
5219 +  ((GET_CODE (X) == PLUS ? OFFSET : 0)                                 \
5220 +    + (frame_pointer_needed                                            \
5221 +       ? 0 : -initial_elimination_offset (ARG_POINTER_REGNUM,          \
5222 +                                         STACK_POINTER_REGNUM)))
5223 +
5224 +/* A C expression that returns the type of debugging output GNU CC produces
5225 +   when the user specifies `-g' or `-ggdb'.  Define this if you have arranged
5226 +   for GNU CC to support more than one format of debugging output.  Currently,
5227 +   the allowable values are `DBX_DEBUG', `SDB_DEBUG', `DWARF_DEBUG',
5228 +   `DWARF2_DEBUG', and `XCOFF_DEBUG'.
5229 +
5230 +   The value of this macro only affects the default debugging output; the user
5231 +   can always get a specific type of output by using `-gstabs', `-gcoff',
5232 +   `-gdwarf-1', `-gdwarf-2', or `-gxcoff'.
5233 +
5234 +   Defined in svr4.h.
5235 +*/
5236 +#undef PREFERRED_DEBUGGING_TYPE
5237 +#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
5238 +
5239 +/* Define this macro if GNU CC should produce dwarf version 2 format debugging
5240 +   output in response to the `-g' option.
5241 +
5242 +   To support optional call frame debugging information, you must also define
5243 +   `INCOMING_RETURN_ADDR_RTX' and either set `RTX_FRAME_RELATED_P' on the
5244 +   prologue insns if you use RTL for the prologue, or call `dwarf2out_def_cfa'
5245 +   and `dwarf2out_reg_save' as appropriate from `FUNCTION_PROLOGUE' if you
5246 +   don't.
5247 +
5248 +   Defined in svr4.h.  */
5249 +
5250 +#define DWARF2_DEBUGGING_INFO 1
5251 +/*#define DWARF2_UNWIND_INFO 1*/
5252 +#define DWARF2_UNWIND_INFO 0
5253 +#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, LINK_REGNO)
5254 +#define INCOMING_FRAME_SP_OFFSET 0
5255 +#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (LINK_REGNO)
5256 +#define EH_RETURN_FIRST 9
5257 +#define EH_RETURN_DATA_REGNO(N) ((N) < 2 ? (N) + EH_RETURN_FIRST : INVALID_REGNUM)
5258 +
5259 +/* The EH_RETURN_STACKADJ_RTX macro returns RTL which describes the
5260 +   location used to store the amount to ajdust the stack.  This is
5261 +   usually a registers that is available from end of the function's body
5262 +   to the end of the epilogue. Thus, this cannot be a register used as a
5263 +   temporary by the epilogue.
5264 +
5265 +   This must be an integer register.  */
5266 +#define EH_RETURN_STACKADJ_REGNO       11
5267 +#define EH_RETURN_STACKADJ_RTX         \
5268 +       gen_rtx_REG (Pmode, EH_RETURN_STACKADJ_REGNO)
5269 +
5270 +/* The EH_RETURN_HANDLER_RTX macro returns RTL which describes the
5271 +   location used to store the address the processor should jump to
5272 +   catch exception.  This is usually a registers that is available from
5273 +   end of the function's body to the end of the epilogue. Thus, this
5274 +   cannot be a register used as a temporary by the epilogue.
5275 +
5276 +   This must be an address register.  */
5277 +#define EH_RETURN_HANDLER_REGNO                18
5278 +#define EH_RETURN_HANDLER_RTX          \
5279 +       gen_rtx_REG (Pmode, EH_RETURN_HANDLER_REGNO)
5280 +
5281 +/* #define DWARF2_DEBUGGING_INFO */
5282 +
5283 +/* Define this macro if GNU CC should produce dwarf version 2-style
5284 +   line numbers.  This usually requires extending the assembler to
5285 +   support them, and #defining DWARF2_LINE_MIN_INSN_LENGTH in the
5286 +   assembler configuration header files.  */
5287 +/* #define DWARF2_ASM_LINE_DEBUG_INFO 1 */
5288 +
5289 +
5290 +/* An alias for a machine mode name.  This is the machine mode that elements
5291 +   of a jump-table have.  */
5292 +#define CASE_VECTOR_MODE Pmode
5293 +
5294 +/* Smallest number of different values for which it is best to use a
5295 +   jump-table instead of a tree of conditional branches.  For most Ubicom32
5296 +   targets this is quite small, but for the v1 architecture implementations
5297 +   we had very little data memory and so heavily prefer the tree approach
5298 +   rather than the jump tables.  */
5299 +#define CASE_VALUES_THRESHOLD ubicom32_case_values_threshold
5300 +
5301 +/* Register operations within the Ubicom32 architecture always operate on
5302 +   the whole register word and not just the sub-bits required for the opcode
5303 +   mode size.  */
5304 +#define WORD_REGISTER_OPERATIONS
5305 +
5306 +/* The maximum number of bytes that a single instruction can move quickly from
5307 +   memory to memory.  */
5308 +#define MOVE_MAX 4
5309 +
5310 +/* A C expression that is nonzero if on this machine the number of bits
5311 +   actually used for the count of a shift operation is equal to the number of
5312 +   bits needed to represent the size of the object being shifted.  When this
5313 +   macro is non-zero, the compiler will assume that it is safe to omit a
5314 +   sign-extend, zero-extend, and certain bitwise `and' instructions that
5315 +   truncates the count of a shift operation.  On machines that have
5316 +   instructions that act on bitfields at variable positions, which may include
5317 +   `bit test' instructions, a nonzero `SHIFT_COUNT_TRUNCATED' also enables
5318 +   deletion of truncations of the values that serve as arguments to bitfield
5319 +   instructions.
5320 +
5321 +   If both types of instructions truncate the count (for shifts) and position
5322 +   (for bitfield operations), or if no variable-position bitfield instructions
5323 +   exist, you should define this macro.
5324 +
5325 +   However, on some machines, such as the 80386 and the 680x0, truncation only
5326 +   applies to shift operations and not the (real or pretended) bitfield
5327 +   operations.  Define `SHIFT_COUNT_TRUNCATED' to be zero on such machines.
5328 +   Instead, add patterns to the `md' file that include the implied truncation
5329 +   of the shift instructions.
5330 +
5331 +   You need not define this macro if it would always have the value of zero.  */
5332 +#define SHIFT_COUNT_TRUNCATED 1
5333 +
5334 +/* A C expression which is nonzero if on this machine it is safe to "convert"
5335 +   an integer of INPREC bits to one of OUTPREC bits (where OUTPREC is smaller
5336 +   than INPREC) by merely operating on it as if it had only OUTPREC bits.
5337 +
5338 +   On many machines, this expression can be 1.
5339 +
5340 +   When `TRULY_NOOP_TRUNCATION' returns 1 for a pair of sizes for modes for
5341 +   which `MODES_TIEABLE_P' is 0, suboptimal code can result.  If this is the
5342 +   case, making `TRULY_NOOP_TRUNCATION' return 0 in such cases may improve
5343 +   things.  */
5344 +#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
5345 +
5346 +/* A C string constant that tells the GNU CC driver program options to pass
5347 +   to the assembler.  It can also specify how to translate options you give
5348 +   to GNU CC into options for GNU CC to pass to the assembler.  See the
5349 +   file `sun3.h' for an example of this.
5350 +
5351 +   Defined in svr4.h.  */
5352 +#undef ASM_SPEC
5353 +#define ASM_SPEC \
5354 +  "%{march=*:-m%*} %{!march=*:-mubicom32v4} %{mfdpic:-mfdpic}"
5355 +
5356 +#define LINK_SPEC "\
5357 +%{h*} %{v:-V} \
5358 +%{b} \
5359 +%{mfdpic:-melf32ubicom32fdpic -z text} \
5360 +%{static:-dn -Bstatic} \
5361 +%{shared:-G -Bdynamic} \
5362 +%{symbolic:-Bsymbolic} \
5363 +%{G*} \
5364 +%{YP,*} \
5365 +%{Qy:} %{!Qn:-Qy}"
5366 +
5367 +#undef STARTFILE_SPEC
5368 +#undef ENDFILE_SPEC
5369 +
5370 +/* The svr4.h LIB_SPEC with -leval and --*group tacked on */
5371 +
5372 +#undef  LIB_SPEC
5373 +#define LIB_SPEC "%{!shared:%{!symbolic:--start-group -lc -leval -lgcc --end-group}}"
5374 +
5375 +#undef HAVE_GAS_SHF_MERGE
5376 +#define HAVE_GAS_SHF_MERGE 0
5377 +
5378 +#define HANDLE_SYSV_PRAGMA 1
5379 +#undef HANDLE_PRAGMA_PACK
5380 +
5381 +typedef void (*ubicom32_func_ptr) (void);
5382 +
5383 +/* Define builtins for selected special-purpose instructions. */
5384 +enum ubicom32_builtins
5385 +{
5386 +  UBICOM32_BUILTIN_UBICOM32_SWAPB_2,
5387 +  UBICOM32_BUILTIN_UBICOM32_SWAPB_4
5388 +};
5389 +
5390 +extern rtx ubicom32_compare_op0;
5391 +extern rtx ubicom32_compare_op1;
5392 +
5393 +#define TYPE_ASM_OP    "\t.type\t"
5394 +#define TYPE_OPERAND_FMT       "@%s"
5395 +
5396 +#ifndef ASM_DECLARE_RESULT
5397 +#define ASM_DECLARE_RESULT(FILE, RESULT)
5398 +#endif
5399 +
5400 +/* These macros generate the special .type and .size directives which
5401 +   are used to set the corresponding fields of the linker symbol table
5402 +   entries in an ELF object file under SVR4.  These macros also output
5403 +   the starting labels for the relevant functions/objects.  */
5404 +
5405 +/* Write the extra assembler code needed to declare a function properly.
5406 +   Some svr4 assemblers need to also have something extra said about the
5407 +   function's return value.  We allow for that here.  */
5408 +
5409 +#ifndef ASM_DECLARE_FUNCTION_NAME
5410 +#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL)            \
5411 +  do                                                           \
5412 +    {                                                          \
5413 +      ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function");      \
5414 +      ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL));           \
5415 +      ASM_OUTPUT_LABEL (FILE, NAME);                           \
5416 +    }                                                          \
5417 +  while (0)
5418 +#endif
5419 --- /dev/null
5420 +++ b/gcc/config/ubicom32/ubicom32.md
5421 @@ -0,0 +1,3753 @@
5422 +; GCC machine description for Ubicom32
5423 +;
5424 +; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Free Software
5425 +; Foundation, Inc.
5426 +; Contributed by Ubicom, Inc.
5427 +;
5428 +; This file is part of GCC.
5429 +;
5430 +; GCC is free software; you can redistribute it and/or modify
5431 +; it under the terms of the GNU General Public License as published by
5432 +; the Free Software Foundation; either version 3, or (at your option)
5433 +; any later version.
5434 +;
5435 +; GCC is distributed in the hope that it will be useful,
5436 +; but WITHOUT ANY WARRANTY; without even the implied warranty of
5437 +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
5438 +; GNU General Public License for more details.
5439 +;
5440 +; You should have received a copy of the GNU General Public License
5441 +; along with GCC; see the file COPYING3.  If not see
5442 +; <http://www.gnu.org/licenses/>.
5443 +
5444 +(define_constants
5445 +  [(AUX_DATA_REGNO 15)
5446 +   (LINK_REGNO     21)
5447 +   (SP_REGNO       23)
5448 +   (ACC0_HI_REGNO  24)
5449 +   (ACC1_HI_REGNO  26)
5450 +   (CC_REGNO       30)])
5451 +
5452 +(define_constants
5453 +  [(UNSPEC_FDPIC_GOT 0)
5454 +   (UNSPEC_FDPIC_GOT_FUNCDESC 1)])
5455 +
5456 +(define_constants
5457 +  [(UNSPEC_VOLATILE_LOAD_FDPIC_FUNCDESC 0)])
5458 +
5459 +;; Types of instructions (for scheduling purposes).
5460 +
5461 +(define_attr "type" "mul,addr,other"
5462 +  (const_string "other"))
5463 +
5464 +; Define instruction scheduling characteristics.  We can only issue
5465 +; one instruction per clock so we don't need to define CPU units.
5466 +;
5467 +(define_automaton "ubicom32")
5468 +
5469 +(define_cpu_unit "i_pipeline" "ubicom32");
5470 +
5471 +; We have a 4 cycle hazard associated with address calculations which
5472 +; seems rather tricky to avoid so we go with a defensive assumption
5473 +; that almost anything can be used to generate addresses.
5474 +;
5475 +;(define_insn_reservation "ubicom32_other" 4
5476 +;                       (eq_attr "type" "other")
5477 +;                       "i_pipeline")
5478 +
5479 +; Some moves don't generate hazards.
5480 +;
5481 +;(define_insn_reservation "ubicom32_addr" 1
5482 +;                       (eq_attr "type" "addr")
5483 +;                       "i_pipeline")
5484 +
5485 +; We need 3 cycles between a multiply instruction and any use of the
5486 +; matching accumulator register(s).
5487 +;
5488 +(define_insn_reservation "ubicom32_mul" 4
5489 +                        (eq_attr "type" "mul")
5490 +                        "i_pipeline")
5491 +
5492 +(define_attr "length" ""
5493 +  (const_int 4))
5494 +
5495 +(include "predicates.md")
5496 +(include "constraints.md")
5497 +
5498 +; 8-bit move with no change to the flags reg.
5499 +;
5500 +(define_insn "movqi"
5501 +  [(set (match_operand:QI 0 "nonimmediate_operand" "=rm")
5502 +       (match_operand:QI 1 "ubicom32_move_operand"  "g"))]
5503 +  ""
5504 +  "move.1\\t%0, %1")
5505 +
5506 +; Combiner-generated 8-bit move with the zero flag set accordingly.
5507 +;
5508 +(define_insn "movqi_ccszn"
5509 +  [(set (reg CC_REGNO)
5510 +       (compare (match_operand:QI 0 "nonimmediate_operand" "rm")
5511 +                (const_int 0)))
5512 +   (set (match_operand:QI 1 "nonimmediate_operand"        "=rm")
5513 +       (match_dup 0))]
5514 +  "ubicom32_match_cc_mode(insn, CCSZNmode)"
5515 +  "ext.1\\t%1, %0")
5516 +
5517 +; Combine isn't very good at merging some types of operations so we
5518 +; have to make do with a peephole.  It's not as effective but it's better
5519 +; than doing nothing.
5520 +;
5521 +(define_peephole2
5522 +  [(set (match_operand:QI 0 "nonimmediate_operand" "")
5523 +       (match_operand:QI 1 "nonimmediate_operand" ""))
5524 +   (set (match_operand 2 "ubicom32_cc_register_operand" "")
5525 +       (match_operator 3 "ubicom32_compare_operator"
5526 +         [(match_dup 0)
5527 +          (const_int 0)]))]
5528 +  "(GET_MODE (operands[2]) == CCSZNmode
5529 +    || GET_MODE (operands[2]) == CCSZmode)"
5530 +  [(parallel
5531 +     [(set (match_dup 2)
5532 +          (match_op_dup 3
5533 +            [(match_dup 1)
5534 +             (const_int 0)]))
5535 +      (set (match_dup 0)
5536 +          (match_dup 1))])]
5537 +   "")
5538 +
5539 +; Combine isn't very good at merging some types of operations so we
5540 +; have to make do with a peephole.  It's not as effective but it's better
5541 +; than doing nothing.
5542 +;
5543 +(define_peephole2
5544 +  [(set (match_operand:QI 0 "nonimmediate_operand" "")
5545 +       (match_operand:QI 1 "nonimmediate_operand" ""))
5546 +   (set (match_operand 2 "ubicom32_cc_register_operand" "")
5547 +       (match_operator 3 "ubicom32_compare_operator"
5548 +         [(match_dup 1)
5549 +          (const_int 0)]))]
5550 +  "(GET_MODE (operands[2]) == CCSZNmode
5551 +    || GET_MODE (operands[2]) == CCSZmode)"
5552 +  [(parallel
5553 +     [(set (match_dup 2)
5554 +          (match_op_dup 3
5555 +            [(match_dup 1)
5556 +             (const_int 0)]))
5557 +      (set (match_dup 0)
5558 +          (match_dup 1))])]
5559 +   "")
5560 +
5561 +; 16-bit move with no change to the flags reg.
5562 +;
5563 +(define_insn "movhi"
5564 +  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
5565 +       (match_operand:HI 1 "ubicom32_move_operand"  "g"))]
5566 +  ""
5567 +  "*
5568 +   {
5569 +     if (CONST_INT_P (operands[1]))
5570 +       return \"movei\\t%0, %1\";
5571 +
5572 +     return \"move.2\\t%0, %1\";
5573 +   }")
5574 +
5575 +; Combiner-generated 16-bit move with the zero flag set accordingly.
5576 +;
5577 +(define_insn "movhi_ccszn"
5578 +  [(set (reg CC_REGNO)
5579 +       (compare (match_operand:HI 0 "nonimmediate_operand" "rm")
5580 +                (const_int 0)))
5581 +   (set (match_operand:HI 1 "nonimmediate_operand"        "=rm")
5582 +       (match_dup 0))]
5583 +  "ubicom32_match_cc_mode(insn, CCSZNmode)"
5584 +  "ext.2\\t%1, %0")
5585 +
5586 +; Combine isn't very good at merging some types of operations so we
5587 +; have to make do with a peephole.  It's not as effective but it's better
5588 +; than doing nothing.
5589 +;
5590 +(define_peephole2
5591 +  [(set (match_operand:HI 0 "nonimmediate_operand" "")
5592 +       (match_operand:HI 1 "nonimmediate_operand" ""))
5593 +   (set (match_operand 2 "ubicom32_cc_register_operand" "")
5594 +       (match_operator 3 "ubicom32_compare_operator"
5595 +         [(match_dup 0)
5596 +          (const_int 0)]))]
5597 +  "(GET_MODE (operands[2]) == CCSZNmode
5598 +    || GET_MODE (operands[2]) == CCSZmode)"
5599 +  [(parallel
5600 +     [(set (match_dup 2)
5601 +          (match_op_dup 3
5602 +            [(match_dup 1)
5603 +             (const_int 0)]))
5604 +      (set (match_dup 0)
5605 +          (match_dup 1))])]
5606 +   "")
5607 +
5608 +; Combine isn't very good at merging some types of operations so we
5609 +; have to make do with a peephole.  It's not as effective but it's better
5610 +; than doing nothing.
5611 +;
5612 +(define_peephole2
5613 +  [(set (match_operand:HI 0 "nonimmediate_operand" "")
5614 +       (match_operand:HI 1 "nonimmediate_operand" ""))
5615 +   (set (match_operand 2 "ubicom32_cc_register_operand" "")
5616 +       (match_operator 3 "ubicom32_compare_operator"
5617 +         [(match_dup 1)
5618 +          (const_int 0)]))]
5619 +  "(GET_MODE (operands[2]) == CCSZNmode
5620 +    || GET_MODE (operands[2]) == CCSZmode)"
5621 +  [(parallel
5622 +     [(set (match_dup 2)
5623 +          (match_op_dup 3
5624 +            [(match_dup 1)
5625 +             (const_int 0)]))
5626 +      (set (match_dup 0)
5627 +          (match_dup 1))])]
5628 +   "")
5629 +
5630 +; 32-bit move with no change to the flags reg.
5631 +;
5632 +(define_expand "movsi"
5633 +  [(set (match_operand:SI 0 "nonimmediate_operand" "")
5634 +       (match_operand:SI 1 "general_operand" ""))]
5635 +  ""
5636 +  "{
5637 +     /* Convert any complexities in operand 1 into something that can just
5638 +        fall into the default expander code.  */
5639 +     ubicom32_expand_movsi (operands);
5640 +   }")
5641 +
5642 +(define_insn "movsi_high"
5643 +  [(set (match_operand:SI 0 "ubicom32_address_register_operand"                "=a")
5644 +       (high:SI (match_operand:SI 1 "ubicom32_symbolic_address_operand" "s")))]
5645 +  ""
5646 +  "moveai\\t%0, #%%hi(%E1)")
5647 +
5648 +(define_insn "movsi_lo_sum"
5649 +  [(set (match_operand:SI 0 "nonimmediate_operand"                      "=rm")
5650 +       (lo_sum:SI (match_operand:SI 1 "ubicom32_address_register_operand" "a")
5651 +                   (match_operand:SI 2 "immediate_operand"                "s")))]
5652 +  ""
5653 +  "lea.1\\t%0, %%lo(%E2)(%1)")
5654 +
5655 +(define_insn "movsi_internal"
5656 +  [(set (match_operand:SI 0 "nonimmediate_operand"   "=rm")
5657 +       (match_operand:SI 1 "ubicom32_move_operand" "rmnY"))]
5658 +  ""
5659 +  "*
5660 +   {
5661 +     if (CONST_INT_P (operands[1]))
5662 +       {
5663 +         ubicom32_emit_move_const_int (operands[0], operands[1]);
5664 +         return \"\";
5665 +       }
5666 +
5667 +     if (GET_CODE (operands[1]) == CONST_DOUBLE)
5668 +       {
5669 +         HOST_WIDE_INT i = CONST_DOUBLE_LOW (operands[1]);
5670 +
5671 +         ubicom32_emit_move_const_int (operands[0], GEN_INT (i));
5672 +         return \"\";
5673 +       }
5674 +
5675 +     if (ubicom32_address_register_operand (operands[0], VOIDmode)
5676 +        && register_operand (operands[1], VOIDmode))
5677 +       {
5678 +        if (ubicom32_address_register_operand (operands[1], VOIDmode))
5679 +          return \"lea.1\\t%0, 0(%1)\";
5680 +
5681 +        /* Use movea here to utilize the hazard bypass in the >= v4 ISA.  */
5682 +         if (ubicom32_v4)
5683 +          return \"movea\\t%0, %1\";
5684 +
5685 +         return \"move.4\\t%0, %1\";
5686 +       }
5687 +
5688 +     return \"move.4\\t%0, %1\";
5689 +   }")
5690 +
5691 +; If we're not dependent on the state of the condition codes we can construct
5692 +; constants of value 2^n by using a bset.
5693 +;
5694 +(define_peephole2
5695 +  [(set (match_operand:SI 0 "nonimmediate_operand" "")
5696 +       (match_operand:SI 1 "const_int_operand" ""))]
5697 +  "(exact_log2 (INTVAL (operands[1])) > 14
5698 +    && peep2_regno_dead_p (0, CC_REGNO))"
5699 +  [(parallel
5700 +     [(set (match_dup 0)
5701 +          (ior:SI (const_int 0)
5702 +                  (match_dup 1)))
5703 +      (clobber (reg:CC CC_REGNO))])]
5704 +  "")
5705 +
5706 +; If we're not dependent on the state of the condition codes we can construct
5707 +; constants of value ~(2^n) by using a bclr.
5708 +;
5709 +(define_peephole2
5710 +  [(set (match_operand:SI 0 "nonimmediate_operand" "")
5711 +       (match_operand:SI 1 "const_int_operand" ""))]
5712 +  "(exact_log2 (~INTVAL (operands[1])) > 14
5713 +    && peep2_regno_dead_p (0, CC_REGNO))"
5714 +  [(parallel
5715 +     [(set (match_dup 0)
5716 +          (and:SI (const_int -1)
5717 +                  (match_dup 1)))
5718 +      (clobber (reg:CC CC_REGNO))])]
5719 +  "")
5720 +
5721 +; For 32-bit constants that have bits 0 through 24 and bit 31 set the same
5722 +; we can use swapb.4!
5723 +;
5724 +(define_peephole2
5725 +  [(set (match_operand:SI 0 "nonimmediate_operand" "")
5726 +       (match_operand:SI 1 "const_int_operand" ""))]
5727 +  "(ubicom32_v4
5728 +    && (INTVAL (operands[1]) & 0xffffffff) != 0xffffffff
5729 +    && (INTVAL (operands[1]) & 0xffffffff) != 0
5730 +    && ((INTVAL (operands[1]) & 0x80ffffff) == 0
5731 +       || (INTVAL (operands[1]) & 0x80ffffff) == 0x80ffffff))"
5732 +  [(set (match_dup 0)
5733 +       (bswap:SI (match_dup 2)))]
5734 +  "{
5735 +     operands[2] = GEN_INT (INTVAL (operands[1]) >> 24);
5736 +   }")
5737 +
5738 +; If this is a write of a constant to memory look to see if we can usefully
5739 +; transform this into 2 smaller writes.
5740 +;
5741 +(define_peephole2
5742 +  [(set (match_operand:SI 0 "memory_operand" "")
5743 +       (match_operand:SI 1 "const_int_operand" ""))]
5744 +  "! satisfies_constraint_I (operands[1])
5745 +   && ubicom32_legitimate_address_p (HImode, plus_constant (XEXP (operands[0], 0), 2), 1)"
5746 +  [(set (match_dup 4) (match_dup 2))
5747 +   (set (match_dup 5) (match_dup 3))]
5748 +  "{
5749 +     rtx low_hword_addr;
5750 +
5751 +     operands[2] = gen_highpart_mode (HImode, SImode, operands[1]);
5752 +     operands[3] = gen_lowpart (HImode, operands[1]);
5753 +
5754 +     operands[4] = gen_rtx_MEM (HImode, XEXP (operands[0], 0));
5755 +     MEM_COPY_ATTRIBUTES (operands[4], operands[0]);
5756 +
5757 +     low_hword_addr = plus_constant (XEXP (operands[0], 0), 2);
5758 +     operands[5] = gen_rtx_MEM (HImode, low_hword_addr);
5759 +     MEM_COPY_ATTRIBUTES (operands[5], operands[0]);
5760 +   }")
5761 +
5762 +; If we're writing memory and we've not found a better way to do this then
5763 +; try loading into a D register and then copying to memory.  This will
5764 +; perform the fewest possible memory read/writes.
5765 +;
5766 +(define_peephole2
5767 +  [(match_scratch:SI 2 "d")
5768 +   (set (match_operand:SI 0 "memory_operand" "")
5769 +       (match_operand:SI 1 "const_int_operand" ""))]
5770 +  "! satisfies_constraint_I (operands[1])"
5771 +  [(set (match_dup 2) (match_dup 1))
5772 +   (set (match_dup 0) (match_dup 2))]
5773 +  "")
5774 +
5775 +; If we're not dependent on the state of the condition codes we can construct
5776 +; constants of value (2^n - 1) by using an lsr.4.
5777 +;
5778 +(define_peephole2
5779 +  [(set (match_operand:SI 0 "ubicom32_data_register_operand" "")
5780 +       (match_operand:SI 1 "const_int_operand" ""))]
5781 +  "(exact_log2 (INTVAL (operands[1]) + 1) > 14
5782 +    && peep2_regno_dead_p (0, CC_REGNO))"
5783 +  [(parallel
5784 +     [(set (match_dup 0)
5785 +          (lshiftrt:SI (const_int -1)
5786 +                       (match_dup 2)))
5787 +      (clobber (reg:CC CC_REGNO))])]
5788 +  "{
5789 +     operands[2] = GEN_INT (32 - exact_log2 (INTVAL (operands[1]) + 1));
5790 +   }")
5791 +
5792 +; If we're not dependent on the state of the condition codes we can construct
5793 +; constants of value (2^n - 1) by using an lsr.4.
5794 +;
5795 +(define_peephole2
5796 +  [(match_scratch:SI 2 "d")
5797 +   (set (match_operand:SI 0 "nonimmediate_operand" "")
5798 +       (match_operand:SI 1 "const_int_operand" ""))]
5799 +  "(exact_log2 (INTVAL (operands[1]) + 1) > 14
5800 +    && peep2_regno_dead_p (0, CC_REGNO))"
5801 +  [(parallel
5802 +     [(set (match_dup 2)
5803 +          (lshiftrt:SI (const_int -1)
5804 +                       (match_dup 3)))
5805 +      (clobber (reg:CC CC_REGNO))])
5806 +   (set (match_dup 0)
5807 +       (match_dup 2))]
5808 +  "{
5809 +     operands[3] = GEN_INT (32 - exact_log2 (INTVAL (operands[1]) + 1));
5810 +   }")
5811 +
5812 +; If we're not dependent on the state of the condition codes we can construct
5813 +; some other constants by using an lsl.4 to shift 7 bits left by some
5814 +; constant.
5815 +;
5816 +(define_peephole2
5817 +  [(set (match_operand:SI 0 "ubicom32_data_register_operand" "")
5818 +       (match_operand:SI 1 "const_int_operand" ""))]
5819 +  "(ubicom32_shiftable_const_int (INTVAL (operands[1]))
5820 +    && peep2_regno_dead_p (0, CC_REGNO))"
5821 +  [(parallel
5822 +     [(set (match_dup 0)
5823 +          (ashift:SI (match_dup 2)
5824 +                     (match_dup 3)))
5825 +      (clobber (reg:CC CC_REGNO))])]
5826 +  "{
5827 +     int shift = ubicom32_shiftable_const_int (INTVAL (operands[1]));
5828 +     operands[2] = GEN_INT (INTVAL (operands[1]) >> shift);
5829 +     operands[3] = GEN_INT (shift);
5830 +   }")
5831 +
5832 +; If we're not dependent on the state of the condition codes we can construct
5833 +; some other constants by using an lsl.4 to shift 7 bits left by some
5834 +; constant.
5835 +;
5836 +(define_peephole2
5837 +  [(match_scratch:SI 2 "d")
5838 +   (set (match_operand:SI 0 "nonimmediate_operand" "")
5839 +       (match_operand:SI 1 "const_int_operand" ""))]
5840 +  "(ubicom32_shiftable_const_int (INTVAL (operands[1]))
5841 +    && peep2_regno_dead_p (0, CC_REGNO))"
5842 +  [(parallel
5843 +     [(set (match_dup 2)
5844 +          (ashift:SI (match_dup 3)
5845 +                     (match_dup 4)))
5846 +      (clobber (reg:CC CC_REGNO))])
5847 +   (set (match_dup 0)
5848 +       (match_dup 2))]
5849 +  "{
5850 +     int shift = ubicom32_shiftable_const_int (INTVAL (operands[1]));
5851 +     operands[3] = GEN_INT (INTVAL (operands[1]) >> shift);
5852 +     operands[4] = GEN_INT (shift);
5853 +   }")
5854 +
5855 +; For some 16-bit unsigned constants that have bit 15 set we can use
5856 +; swapb.2!
5857 +;
5858 +; Note that the movsi code emits the same sequence but by using a peephole2
5859 +; we split the pattern early enough to allow instruction scheduling to
5860 +; occur.
5861 +;
5862 +(define_peephole2
5863 +  [(set (match_operand:SI 0 "register_operand" "")
5864 +       (match_operand:SI 1 "const_int_operand" ""))]
5865 +  "(ubicom32_v4
5866 +    && (INTVAL (operands[1]) & 0xffff80ff) == 0x80ff)"
5867 +  [(set (match_dup 0)
5868 +       (zero_extend:SI (bswap:HI (match_dup 2))))]
5869 +  "{
5870 +     HOST_WIDE_INT i = INTVAL (operands[1]) >> 8;
5871 +     if (i >= 0x80)
5872 +       i -= 0x100;
5873 +     operands[2] = GEN_INT (i);
5874 +   }")
5875 +
5876 +; In general for a 16-bit unsigned constant that has bit 15 set
5877 +; then we need a movei/move.2 pair unless we can represent it
5878 +; via just a move.2.
5879 +;
5880 +(define_peephole2
5881 +  [(set (match_operand:SI 0 "register_operand" "")
5882 +       (match_operand:SI 1 "const_int_operand" ""))]
5883 +  "(INTVAL (operands[1]) & 0xffff8000) == 0x8000
5884 +    && (INTVAL (operands[1]) & 0xffff) < 0xff80"
5885 +  [(set (match_dup 2)
5886 +       (match_dup 1))
5887 +   (set (match_dup 0)
5888 +       (zero_extend:SI (match_dup 2)))]
5889 +  "{
5890 +     operands[2] = gen_rtx_REG (HImode, REGNO (operands[0]));
5891 +   }")
5892 +
5893 +; If we're not dependent on the state of the condition codes we can construct
5894 +; 32-bit constants that have bits 16 through 31 set to arbitrary values
5895 +; and have bits 0 through 15 set to something representable as a default
5896 +; source-1 immediate - we use movei/shmrg.2
5897 +;
5898 +(define_peephole2
5899 +  [(set (match_operand:SI 0 "ubicom32_data_register_operand" "")
5900 +       (match_operand:SI 1 "const_int_operand" ""))]
5901 +  "(((INTVAL (operands[1]) >= 0x8000
5902 +      && INTVAL (operands[1]) < 0xff80)
5903 +     || INTVAL (operands[1]) >= 0x10000
5904 +     || INTVAL (operands[1]) < -0x8000)
5905 +    && ((INTVAL (operands[1]) & 0xffff) >= 0xff80
5906 +       || (INTVAL (operands[1]) & 0xffff) < 0x80)
5907 +    && peep2_regno_dead_p (0, CC_REGNO))"
5908 +  [(set (match_dup 0)
5909 +       (match_dup 2))
5910 +   (parallel
5911 +     [(set (match_dup 0)
5912 +          (ior:SI
5913 +            (ashift:SI (match_dup 0)
5914 +                       (const_int 16))
5915 +            (zero_extend:SI
5916 +              (match_dup 3))))
5917 +      (clobber (reg:CC CC_REGNO))])]
5918 +  "{
5919 +     operands[2] = gen_highpart_mode (HImode, SImode, operands[1]);
5920 +     operands[3] = gen_lowpart (HImode, operands[1]);
5921 +   }")
5922 +
5923 +; Exactly the same as the peephole2 preceding except that this targets a
5924 +; general register instead of D register.  Hopefully the later optimization
5925 +; passes will notice that the value ended up in a D register first here
5926 +; and eliminate away the other register!
5927 +;
5928 +(define_peephole2
5929 +  [(match_scratch:SI 2 "d")
5930 +   (set (match_operand:SI 0 "register_operand" "")
5931 +       (match_operand:SI 1 "const_int_operand" ""))]
5932 +  "(((INTVAL (operands[1]) >= 0x8000
5933 +      && INTVAL (operands[1]) < 0xff80)
5934 +     || INTVAL (operands[1]) >= 0x10000
5935 +     || INTVAL (operands[1]) < -0x8000)
5936 +    && ((INTVAL (operands[1]) & 0xffff) >= 0xff80
5937 +       || (INTVAL (operands[1]) & 0xffff) < 0x80)
5938 +    && peep2_regno_dead_p (0, CC_REGNO))"
5939 +  [(set (match_dup 2)
5940 +       (match_dup 3))
5941 +   (parallel
5942 +     [(set (match_dup 2)
5943 +          (ior:SI
5944 +            (ashift:SI (match_dup 2)
5945 +                       (const_int 16))
5946 +            (zero_extend:SI
5947 +              (match_dup 4))))
5948 +      (clobber (reg:CC CC_REGNO))])
5949 +   (set (match_dup 0)
5950 +       (match_dup 2))]
5951 +  "{
5952 +     operands[3] = gen_highpart_mode (HImode, SImode, operands[1]);
5953 +     operands[4] = gen_lowpart (HImode, operands[1]);
5954 +   }")
5955 +
5956 +; If we have a load of a large integer constant which does not have bit 31
5957 +; set and we have a spare A reg then construct it with a moveai/lea.1 pair
5958 +; instead.  This avoids constructing it in 3 instructions on the stack.
5959 +;
5960 +; Note that we have to be careful not to match anything that matches
5961 +; something we can do in a single instruction!  There aren't many such
5962 +; constants but there are some.
5963 +;
5964 +(define_peephole2
5965 +  [(match_scratch:SI 2 "a")
5966 +   (set (match_operand:SI 0 "register_operand" "")
5967 +       (match_operand:SI 1 "const_int_operand" ""))]
5968 +  "(! (INTVAL (operands[1]) & 0x80000000)
5969 +    && ((INTVAL (operands[1]) >= 0x8000
5970 +        && INTVAL (operands[1]) < 0xff80)
5971 +       || INTVAL (operands[1]) >= 0x10000))"
5972 +  [(set (match_dup 2)
5973 +       (match_dup 3))
5974 +   (set (match_dup 0)
5975 +       (plus:SI (match_dup 2)
5976 +                (match_dup 4)))]
5977 +  "{
5978 +     HOST_WIDE_INT i = INTVAL (operands[1]);
5979 +     operands[3] = GEN_INT (i & 0xffffff80);
5980 +     operands[4] = GEN_INT (i & 0x7f);
5981 +   }")
5982 +
5983 +; If we're not dependent on the state of the condition codes we can construct
5984 +; a 32-bit constant with a movei/movei/shmrg.2 sequence if possible.
5985 +;
5986 +(define_peephole2
5987 +  [(match_scratch:HI 2 "d")
5988 +   (set (match_operand:SI 0 "ubicom32_data_register_operand" "")
5989 +       (match_operand:SI 1 "const_int_operand" ""))
5990 +   (match_dup 2)]
5991 +  "(INTVAL (operands[1]) & 0x80000000
5992 +    && INTVAL (operands[1]) < -0x8000
5993 +    && peep2_regno_dead_p (0, CC_REGNO))"
5994 +  [(set (match_dup 0)
5995 +       (match_dup 3))
5996 +   (set (match_dup 2)
5997 +       (match_dup 4))
5998 +   (parallel
5999 +     [(set (match_dup 0)
6000 +          (ior:SI
6001 +            (ashift:SI (match_dup 0)
6002 +                       (const_int 16))
6003 +            (zero_extend:SI
6004 +              (match_dup 2))))
6005 +      (clobber (reg:CC CC_REGNO))])]
6006 +  "{
6007 +     operands[3] = gen_highpart_mode (HImode, SImode, operands[1]);
6008 +     operands[4] = gen_lowpart (HImode, operands[1]);
6009 +   }")
6010 +
6011 +; Exactly the same as the peephole2 preceding except that this targets a
6012 +; general register instead of D register.  Hopefully the later optimization
6013 +; passes will notice that the value ended up in a D register first here
6014 +; and eliminate away the other register!
6015 +;
6016 +(define_peephole2
6017 +  [(match_scratch:SI 2 "d")
6018 +   (match_scratch:HI 3 "d")
6019 +   (set (match_operand:SI 0 "register_operand" "")
6020 +       (match_operand:SI 1 "const_int_operand" ""))
6021 +   (match_dup 3)]
6022 +  "(INTVAL (operands[1]) & 0x80000000
6023 +    && INTVAL (operands[1]) < -0x8000
6024 +    && peep2_regno_dead_p (0, CC_REGNO))"
6025 +  [(set (match_dup 2)
6026 +       (match_dup 4))
6027 +   (set (match_dup 3)
6028 +       (match_dup 5))
6029 +   (parallel
6030 +     [(set (match_dup 2)
6031 +          (ior:SI
6032 +            (ashift:SI (match_dup 2)
6033 +                       (const_int 16))
6034 +            (zero_extend:SI
6035 +              (match_dup 3))))
6036 +      (clobber (reg:CC CC_REGNO))])
6037 +   (set (match_dup 0)
6038 +       (match_dup 2))]
6039 +  "{
6040 +     operands[4] = gen_highpart_mode (HImode, SImode, operands[1]);
6041 +     operands[5] = gen_lowpart (HImode, operands[1]);
6042 +   }")
6043 +
6044 +(define_insn "movsi_fdpic_got_offset"
6045 +  [(set (match_operand:SI 0 "ubicom32_data_register_operand"   "=d")
6046 +       (match_operand:SI 1 "ubicom32_fdpic_got_offset_operand" "Y"))]
6047 +  ""
6048 +  "movei\\t%0, %1")
6049 +
6050 +; The explicit MEM inside the UNSPEC prevents the compiler from moving
6051 +; the load before a branch after a NULL test, or before a store that
6052 +; initializes a function descriptor.
6053 +
6054 +(define_insn_and_split "load_fdpic_funcdesc"
6055 +  [(set (match_operand:SI 0 "ubicom32_address_register_operand" "=a")
6056 +       (unspec_volatile:SI [(mem:SI (match_operand:SI 1 "address_operand" "p"))]
6057 +                            UNSPEC_VOLATILE_LOAD_FDPIC_FUNCDESC))]
6058 +  ""
6059 +  "#"
6060 +  "reload_completed"
6061 +  [(set (match_dup 0)
6062 +       (mem:SI (match_dup 1)))])
6063 +
6064 +; Combiner-generated 32-bit move with the zero flag set accordingly.
6065 +;
6066 +(define_insn "movsi_ccwzn"
6067 +  [(set (reg CC_REGNO)
6068 +       (compare (match_operand:SI 0 "nonimmediate_operand" "rm, d")
6069 +                (const_int 0)))
6070 +   (set (match_operand:SI 1 "nonimmediate_operand"         "=d,rm")
6071 +       (match_dup 0))]
6072 +  "ubicom32_match_cc_mode(insn, CCWZNmode)"
6073 +  "@
6074 +   lsl.4\\t%1, %0, #0
6075 +   add.4\\t%1, #0, %0")
6076 +
6077 +; Combiner-generated 32-bit move with all flags set accordingly.
6078 +;
6079 +(define_insn "movsi_ccw"
6080 +  [(set (reg CC_REGNO)
6081 +       (compare (match_operand:SI 0 "ubicom32_data_register_operand" "d")
6082 +                (const_int 0)))
6083 +   (set (match_operand:SI 1 "nonimmediate_operand"                 "=rm")
6084 +       (match_dup 0))]
6085 +  "ubicom32_match_cc_mode(insn, CCWmode)"
6086 +  "add.4\\t%1, #0, %0")
6087 +
6088 +; Combine isn't very good at merging some types of operations so we
6089 +; have to make do with a peephole.  It's not as effective but it's better
6090 +; than doing nothing.
6091 +;
6092 +(define_peephole2
6093 +  [(set (match_operand:SI 0 "ubicom32_data_register_operand" "")
6094 +       (match_operand:SI 1 "nonimmediate_operand" ""))
6095 +   (parallel
6096 +     [(set (match_operand 2 "ubicom32_cc_register_operand" "")
6097 +          (match_operator 3 "ubicom32_compare_operator"
6098 +            [(match_dup 0)
6099 +             (const_int 0)]))
6100 +      (clobber (match_operand:SI 4 "ubicom32_data_register_operand" ""))])]
6101 +  "(GET_MODE (operands[2]) == CCWZNmode
6102 +    || GET_MODE (operands[2]) == CCWZmode)"
6103 +  [(parallel
6104 +     [(set (match_dup 2)
6105 +          (match_op_dup 3
6106 +            [(match_dup 1)
6107 +             (const_int 0)]))
6108 +      (set (match_dup 0)
6109 +          (match_dup 1))])]
6110 +   "")
6111 +
6112 +; Combine isn't very good at merging some types of operations so we
6113 +; have to make do with a peephole.  It's not as effective but it's better
6114 +; than doing nothing.
6115 +;
6116 +(define_peephole2
6117 +  [(set (match_operand:SI 0 "nonimmediate_operand" "")
6118 +       (match_operand:SI 1 "ubicom32_data_register_operand" ""))
6119 +   (parallel
6120 +     [(set (match_operand 2 "ubicom32_cc_register_operand" "")
6121 +          (match_operator 3 "ubicom32_compare_operator"
6122 +            [(match_dup 1)
6123 +             (const_int 0)]))
6124 +      (clobber (match_operand:SI 4 "ubicom32_data_register_operand" ""))])]
6125 +  "(GET_MODE (operands[2]) == CCWZNmode
6126 +    || GET_MODE (operands[2]) == CCWZmode)"
6127 +  [(parallel
6128 +     [(set (match_dup 2)
6129 +          (match_op_dup 3
6130 +            [(match_dup 1)
6131 +             (const_int 0)]))
6132 +      (set (match_dup 0)
6133 +          (match_dup 1))])]
6134 +   "")
6135 +
6136 +; Combine isn't very good at merging some types of operations so we
6137 +; have to make do with a peephole.  It's not as effective but it's better
6138 +; than doing nothing.
6139 +;
6140 +(define_peephole2
6141 +  [(set (match_operand:SI 0 "register_operand" "")
6142 +       (match_operand:SI 1 "nonimmediate_operand" ""))
6143 +   (parallel
6144 +     [(set (match_operand 2 "ubicom32_cc_register_operand" "")
6145 +          (match_operator 3 "ubicom32_compare_operator"
6146 +            [(match_dup 0)
6147 +             (const_int 0)]))
6148 +      (set (match_operand:SI 4 "ubicom32_data_register_operand" "")
6149 +          (match_dup 0))])]
6150 +  "(peep2_reg_dead_p (2, operands[0])
6151 +    && (GET_MODE (operands[2]) == CCWZNmode
6152 +       || GET_MODE (operands[2]) == CCWZmode))"
6153 +  [(parallel
6154 +     [(set (match_dup 2)
6155 +          (match_op_dup 3
6156 +            [(match_dup 1)
6157 +             (const_int 0)]))
6158 +      (set (match_dup 4)
6159 +          (match_dup 1))])]
6160 +   "")
6161 +
6162 +; Register renaming may make a general reg into a D reg in which case
6163 +; we may be able to simplify a compare.
6164 +;
6165 +(define_peephole2
6166 +  [(set (match_operand:SI 0 "register_operand" "")
6167 +       (match_operand:SI 1 "nonimmediate_operand" ""))
6168 +   (parallel
6169 +     [(set (match_operand 2 "ubicom32_cc_register_operand" "")
6170 +          (match_operator 3 "ubicom32_compare_operator"
6171 +            [(match_dup 0)
6172 +             (const_int 0)]))
6173 +      (clobber (match_operand:SI 4 "ubicom32_data_register_operand" ""))])]
6174 +  "(peep2_reg_dead_p (2, operands[0])
6175 +    && (GET_MODE (operands[2]) == CCWZNmode
6176 +       || GET_MODE (operands[2]) == CCWZmode))"
6177 +  [(parallel
6178 +     [(set (match_dup 2)
6179 +          (match_op_dup 3
6180 +            [(match_dup 1)
6181 +             (const_int 0)]))
6182 +      (clobber (match_dup 4))])]
6183 +   "")
6184 +
6185 +(define_insn_and_split "movdi"
6186 +  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm")
6187 +       (match_operand:DI 1 "general_operand"     "rmi,ri"))]
6188 +  ""
6189 +  "#"
6190 +  "reload_completed"
6191 +  [(set (match_dup 2) (match_dup 3))
6192 +   (set (match_dup 4) (match_dup 5))]
6193 +  "{
6194 +     rtx dest_low;
6195 +     rtx src_low;
6196 +
6197 +     dest_low = gen_lowpart (SImode, operands[0]);
6198 +     src_low = gen_lowpart (SImode, operands[1]);
6199 +
6200 +     if (REG_P (operands[0])
6201 +        && REG_P (operands[1])
6202 +        && REGNO (operands[0]) < REGNO (operands[1]))
6203 +       {
6204 +        operands[2] = gen_highpart (SImode, operands[0]);
6205 +        operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
6206 +        operands[4] = dest_low;
6207 +        operands[5] = src_low;
6208 +       }
6209 +     else if (reg_mentioned_p (dest_low, src_low))
6210 +       {
6211 +        operands[2] = gen_highpart (SImode, operands[0]);
6212 +        operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
6213 +        operands[4] = dest_low;
6214 +        operands[5] = src_low;
6215 +       }
6216 +     else
6217 +       {
6218 +        operands[2] = dest_low;
6219 +        operands[3] = src_low;
6220 +        operands[4] = gen_highpart (SImode, operands[0]);
6221 +        operands[5] = gen_highpart_mode (SImode, DImode, operands[1]);
6222 +       }
6223 +   }"
6224 +  [(set_attr "length" "8")])
6225 +
6226 +; Combiner-generated 64-bit move with all flags set accordingly.
6227 +;
6228 +(define_insn "movdi_ccwzn"
6229 +  [(set (reg CC_REGNO)
6230 +       (compare (match_operand:DI 0 "nonimmediate_operand" "d, m,   r")
6231 +                (const_int 0)))
6232 +   (set (match_operand:DI 1 "nonimmediate_operand"      "=&rm,rm,!&rm")
6233 +       (match_dup 0))
6234 +   (clobber (match_scratch:SI 2                                   "=X, d,   d"))]
6235 +  "ubicom32_match_cc_mode(insn, CCWZNmode)"
6236 +  "*
6237 +   {
6238 +     operands[3] = gen_lowpart (SImode, operands[0]);
6239 +     operands[4] = gen_lowpart (SImode, operands[1]);
6240 +     operands[5] = gen_highpart (SImode, operands[0]);
6241 +     operands[6] = gen_highpart (SImode, operands[1]);
6242 +
6243 +     if (ubicom32_data_register_operand (operands[0], VOIDmode))
6244 +       return \"add.4\\t%4, #0, %3\;addc\\t%6, #0, %5\";
6245 +
6246 +     return \"movei\\t%2, #0\;add.4\\t%4, %3, %2\;addc\\t%6, %5, %2\";
6247 +   }"
6248 +  [(set_attr "length" "8")])
6249 +
6250 +(define_insn "movdi_ccw"
6251 +  [(set (reg CC_REGNO)
6252 +       (compare (match_operand:DI 0 "nonimmediate_operand" "d, m,   r")
6253 +                (const_int 0)))
6254 +   (set (match_operand:DI 1 "nonimmediate_operand"      "=&rm,rm,!&rm")
6255 +       (match_dup 0))
6256 +   (clobber (match_scratch:SI 2                                   "=X, d,   d"))]
6257 +  "ubicom32_match_cc_mode(insn, CCWmode)"
6258 +  "*
6259 +   {
6260 +     operands[3] = gen_lowpart (SImode, operands[0]);
6261 +     operands[4] = gen_lowpart (SImode, operands[1]);
6262 +     operands[5] = gen_highpart (SImode, operands[0]);
6263 +     operands[6] = gen_highpart (SImode, operands[1]);
6264 +
6265 +     if (ubicom32_data_register_operand (operands[0], VOIDmode))
6266 +       return \"add.4\\t%4, #0, %3\;addc\\t%6, #0, %5\";
6267 +
6268 +     return \"movei\\t%2, #0\;add.4\\t%4, %3, %2\;addc\\t%6, %5, %2\";
6269 +   }"
6270 +  [(set_attr "length" "8")])
6271 +
6272 +(define_insn "movsf"
6273 +  [(set (match_operand:SF 0 "nonimmediate_operand"  "=!d,*rm")
6274 +       (match_operand:SF 1 "ubicom32_move_operand" "rmF,rmF"))]
6275 +  ""
6276 +  "*
6277 +   {
6278 +     if (GET_CODE (operands[1]) == CONST_DOUBLE)
6279 +       {
6280 +        HOST_WIDE_INT val;
6281 +        REAL_VALUE_TYPE rv;
6282 +
6283 +        REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
6284 +        REAL_VALUE_TO_TARGET_SINGLE (rv, val);
6285 +
6286 +        ubicom32_emit_move_const_int (operands[0], GEN_INT (val));
6287 +        return \"\";
6288 +       }
6289 +
6290 +     return \"move.4\\t%0, %1\";
6291 +   }")
6292 +
6293 +(define_insn "zero_extendqihi2"
6294 +  [(set (match_operand:HI 0 "register_operand"                    "=r")
6295 +       (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
6296 +  ""
6297 +  "move.1\\t%0, %1")
6298 +
6299 +(define_insn "zero_extendqisi2"
6300 +  [(set (match_operand:SI 0 "register_operand"                    "=r")
6301 +       (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
6302 +  ""
6303 +  "move.1\\t%0, %1")
6304 +
6305 +(define_insn "zero_extendqisi2_ccwz_1"
6306 +  [(set (reg CC_REGNO)
6307 +       (compare
6308 +         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm"))
6309 +          (const_int 0)))
6310 +   (set (match_operand:SI 0 "ubicom32_data_register_operand"        "=d")
6311 +       (zero_extend:SI (match_dup 1)))]
6312 +  "ubicom32_match_cc_mode(insn, CCWZmode)"
6313 +  "shmrg.1\\t%0, %1, #0")
6314 +
6315 +(define_insn "zero_extendhisi2"
6316 +  [(set (match_operand:SI 0 "register_operand"                    "=r")
6317 +       (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
6318 +  ""
6319 +  "move.2\\t%0, %1")
6320 +
6321 +(define_insn "zero_extendhisi2_ccwz_1"
6322 +  [(set (reg CC_REGNO)
6323 +       (compare
6324 +         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm"))
6325 +          (const_int 0)))
6326 +   (set (match_operand:SI 0 "ubicom32_data_register_operand"        "=d")
6327 +       (zero_extend:SI (match_dup 1)))]
6328 +  "ubicom32_match_cc_mode(insn, CCWZmode)"
6329 +  "shmrg.2\\t%0, %1, #0")
6330 +
6331 +(define_insn_and_split "zero_extendqidi2"
6332 +  [(set (match_operand:DI 0 "register_operand"                    "=r")
6333 +       (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
6334 +  ""
6335 +  "#"
6336 +  "reload_completed"
6337 +  [(set (match_dup 2)
6338 +       (zero_extend:SI (match_dup 1)))
6339 +   (set (match_dup 3)
6340 +       (const_int 0))]
6341 +  "{
6342 +     operands[2] = gen_lowpart (SImode, operands[0]);
6343 +     operands[3] = gen_highpart (SImode, operands[0]);
6344 +   }"
6345 +  [(set_attr "length" "8")])
6346 +
6347 +(define_insn_and_split "zero_extendhidi2"
6348 +  [(set (match_operand:DI 0 "register_operand"                    "=r")
6349 +       (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
6350 +  ""
6351 +  "#"
6352 +  "reload_completed"
6353 +  [(set (match_dup 2)
6354 +       (zero_extend:SI (match_dup 1)))
6355 +   (set (match_dup 3)
6356 +       (const_int 0))]
6357 +  "{
6358 +     operands[2] = gen_lowpart (SImode, operands[0]);
6359 +     operands[3] = gen_highpart (SImode, operands[0]);
6360 +   }"
6361 +  [(set_attr "length" "8")])
6362 +
6363 +(define_insn_and_split "zero_extendsidi2"
6364 +  [(set (match_operand:DI 0 "nonimmediate_operand"               "=rm")
6365 +       (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm")))]
6366 +  ""
6367 +  "#"
6368 +  "reload_completed"
6369 +  [(set (match_dup 2)
6370 +       (match_dup 1))
6371 +   (set (match_dup 3)
6372 +       (const_int 0))]
6373 +  "{
6374 +     operands[2] = gen_lowpart (SImode, operands[0]);
6375 +     operands[3] = gen_highpart (SImode, operands[0]);
6376 +   }"
6377 +  [(set_attr "length" "8")])
6378 +
6379 +(define_insn "extendqihi2"
6380 +  [(set (match_operand:HI 0 "register_operand"                    "=r")
6381 +       (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "rm")))
6382 +   (clobber (reg:CC CC_REGNO))]
6383 +  ""
6384 +  "ext.1\\t%0, %1")
6385 +
6386 +(define_insn "extendqisi2"
6387 +  [(set (match_operand:SI 0 "register_operand"                    "=r")
6388 +       (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm")))
6389 +   (clobber (reg:CC CC_REGNO))]
6390 +  ""
6391 +  "ext.1\\t%0, %1")
6392 +
6393 +(define_insn "extendhisi2"
6394 +  [(set (match_operand:SI 0 "register_operand"                    "=r")
6395 +       (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))
6396 +   (clobber (reg:CC CC_REGNO))]
6397 +  ""
6398 +  "ext.2\\t%0, %1")
6399 +
6400 +(define_insn_and_split "extendsidi2"
6401 +  [(set (match_operand:DI 0 "nonimmediate_operand"                "=d")
6402 +       (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm")))
6403 +   (clobber (reg:CC CC_REGNO))]
6404 +  ""
6405 +  "#"
6406 +  "reload_completed"
6407 +  [(set (match_dup 2)
6408 +       (match_dup 1))
6409 +   (parallel
6410 +     [(set (match_dup 3)
6411 +          (ashiftrt:SI (match_dup 2)
6412 +                       (const_int 31)))
6413 +      (clobber (reg:CC CC_REGNO))])]
6414 +  "{
6415 +     operands[2] = gen_lowpart (SImode, operands[0]);
6416 +     operands[3] = gen_highpart (SImode, operands[0]);
6417 +   }"
6418 +  [(set_attr "length" "8")])
6419 +
6420 +(define_insn "bswaphi"
6421 +  [(set (match_operand:HI 0 "nonimmediate_operand"            "=rm")
6422 +       (bswap:HI (match_operand:HI 1 "ubicom32_arith_operand" "rmI")))]
6423 +  "(ubicom32_v4)"
6424 +  "swapb.2\\t%0, %1");
6425 +
6426 +(define_insn "bswaphisi"
6427 +  [(set (match_operand:SI 0 "register_operand"                   "=r")
6428 +       (zero_extend:SI
6429 +         (bswap:HI (match_operand:HI 1 "ubicom32_arith_operand" "rmI"))))]
6430 +  "(ubicom32_v4)"
6431 +  "swapb.2\\t%0, %1");
6432 +
6433 +(define_insn "bswapsi"
6434 +  [(set (match_operand:SI 0 "nonimmediate_operand"            "=rm")
6435 +       (bswap:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")))]
6436 +  "(ubicom32_v4)"
6437 +  "swapb.4\\t%0, %1");
6438 +
6439 +(define_insn "tstqi_ext1"
6440 +  [(set (reg CC_REGNO)
6441 +       (compare (match_operand:QI 0 "nonimmediate_operand" "rm")
6442 +                (const_int 0)))]
6443 +  "ubicom32_match_cc_mode(insn, CCSZNmode)"
6444 +  "ext.1\\t#0, %0")
6445 +
6446 +(define_expand "cmpqi"
6447 +  [(set (reg CC_REGNO)
6448 +       (compare (match_operand:QI 0 "ubicom32_arith_operand" "")
6449 +                (match_operand:QI 1 "ubicom32_data_register_operand" "")))]
6450 +  "(ubicom32_v4)"
6451 +  "{
6452 +     ubicom32_compare_op0 = operands[0];
6453 +     ubicom32_compare_op1 = operands[1];
6454 +     DONE;
6455 +   }")
6456 +
6457 +(define_insn "sub1_ccs"
6458 +  [(set (reg CC_REGNO)
6459 +       (compare (match_operand:QI 0 "ubicom32_arith_operand"       "rmI")
6460 +                (match_operand:QI 1 "ubicom32_data_register_operand" "d")))]
6461 +  "(ubicom32_v4)"
6462 +  "sub.1\\t#0, %0, %1")
6463 +
6464 +; If we're testing for equality we don't have to worry about reversing conditions.
6465 +;
6466 +(define_insn "sub1_ccsz_1"
6467 +  [(set (reg:CCSZ CC_REGNO)
6468 +       (compare:CCSZ (match_operand:QI 0 "nonimmediate_operand"          "rm")
6469 +                     (match_operand:QI 1 "ubicom32_data_register_operand" "d")))]
6470 +  "(ubicom32_v4)"
6471 +  "sub.1\\t#0, %0, %1")
6472 +
6473 +(define_insn "sub1_ccsz_2"
6474 +  [(set (reg:CCSZ CC_REGNO)
6475 +       (compare:CCSZ (match_operand:QI 0 "ubicom32_data_register_operand" "d")
6476 +                     (match_operand:QI 1 "ubicom32_arith_operand"       "rmI")))]
6477 +  "(ubicom32_v4)"
6478 +  "sub.1\\t#0, %1, %0")
6479 +
6480 +; When the combiner runs it doesn't have any insight into whether or not an argument
6481 +; to a compare is spilled to the stack and therefore can't swap the comparison in
6482 +; an attempt to use sub.1 more effectively.  We peephole this case here.
6483 +;
6484 +(define_peephole2
6485 +  [(set (match_operand:QI 0 "register_operand" "")
6486 +       (match_operand:QI 1 "ubicom32_arith_operand" ""))
6487 +   (set (match_operand 2 "ubicom32_cc_register_operand" "")
6488 +       (compare (match_operand:QI 3 "ubicom32_data_register_operand" "")
6489 +                (match_dup 0)))
6490 +   (set (pc)
6491 +       (if_then_else (match_operator 4 "comparison_operator"
6492 +                       [(match_dup 2)
6493 +                        (const_int 0)])
6494 +                     (label_ref (match_operand 5 "" ""))
6495 +                     (pc)))]
6496 +  "(peep2_reg_dead_p (2, operands[0])
6497 +    && peep2_regno_dead_p (3, CC_REGNO))"
6498 +  [(set (match_dup 2)
6499 +       (compare (match_dup 1)
6500 +                (match_dup 3)))
6501 +   (set (pc)
6502 +       (if_then_else (match_op_dup 6
6503 +                       [(match_dup 2)
6504 +                        (const_int 0)])
6505 +                     (label_ref (match_dup 5))
6506 +                     (pc)))]
6507 +  "{
6508 +     rtx cc_reg;
6509 +
6510 +     cc_reg = gen_rtx_REG (GET_MODE (operands[2]), CC_REGNO);
6511 +     operands[6] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[4])),
6512 +                                  GET_MODE (operands[4]),
6513 +                                  cc_reg,
6514 +                                  const0_rtx);
6515 +   }")
6516 +
6517 +(define_insn "tsthi_ext2"
6518 +  [(set (reg CC_REGNO)
6519 +       (compare (match_operand:HI 0 "nonimmediate_operand" "rm")
6520 +                (const_int 0)))]
6521 +  "ubicom32_match_cc_mode(insn, CCSZNmode)"
6522 +  "ext.2\\t#0, %0")
6523 +
6524 +(define_expand "cmphi"
6525 +  [(set (reg CC_REGNO)
6526 +       (compare (match_operand:HI 0 "ubicom32_arith_operand" "")
6527 +                (match_operand:HI 1 "ubicom32_compare_operand" "")))]
6528 +  ""
6529 +  "{
6530 +     do
6531 +       {
6532 +        /* Is this a cmpi? */
6533 +        if (CONST_INT_P (operands[1]))
6534 +          break;
6535 +
6536 +        /* Must be a sub.2 - if necessary copy an operand into a reg.  */
6537 +        if (! ubicom32_data_register_operand (operands[1], HImode))
6538 +          operands[1] = copy_to_mode_reg (HImode, operands[1]);
6539 +       }
6540 +     while (0);
6541 +
6542 +     ubicom32_compare_op0 = operands[0];
6543 +     ubicom32_compare_op1 = operands[1];
6544 +     DONE;
6545 +   }")
6546 +
6547 +(define_insn "cmpi"
6548 +  [(set (reg CC_REGNO)
6549 +       (compare (match_operand:HI 0 "nonimmediate_operand" "rm")
6550 +                (match_operand 1 "const_int_operand"        "N")))]
6551 +  ""
6552 +  "cmpi\\t%0, %1")
6553 +
6554 +(define_insn "sub2_ccs"
6555 +  [(set (reg CC_REGNO)
6556 +       (compare (match_operand:HI 0 "ubicom32_arith_operand"       "rmI")
6557 +                (match_operand:HI 1 "ubicom32_data_register_operand" "d")))]
6558 +  ""
6559 +  "sub.2\\t#0, %0, %1")
6560 +
6561 +; If we're testing for equality we don't have to worry about reversing conditions.
6562 +;
6563 +(define_insn "sub2_ccsz_1"
6564 +  [(set (reg:CCSZ CC_REGNO)
6565 +       (compare:CCSZ (match_operand:HI 0 "nonimmediate_operand"          "rm")
6566 +                     (match_operand:HI 1 "ubicom32_data_register_operand" "d")))]
6567 +  ""
6568 +  "sub.2\\t#0, %0, %1")
6569 +
6570 +(define_insn "sub2_ccsz_2"
6571 +  [(set (reg:CCSZ CC_REGNO)
6572 +       (compare:CCSZ (match_operand:HI 0 "ubicom32_data_register_operand" "d")
6573 +                     (match_operand:HI 1 "ubicom32_arith_operand"       "rmI")))]
6574 +  ""
6575 +  "sub.2\\t#0, %1, %0")
6576 +
6577 +; When the combiner runs it doesn't have any insight into whether or not an argument
6578 +; to a compare is spilled to the stack and therefore can't swap the comparison in
6579 +; an attempt to use sub.2 more effectively.  We peephole this case here.
6580 +;
6581 +(define_peephole2
6582 +  [(set (match_operand:HI 0 "register_operand" "")
6583 +       (match_operand:HI 1 "ubicom32_arith_operand" ""))
6584 +   (set (match_operand 2 "ubicom32_cc_register_operand" "")
6585 +       (compare (match_operand:HI 3 "ubicom32_data_register_operand" "")
6586 +                (match_dup 0)))
6587 +   (set (pc)
6588 +       (if_then_else (match_operator 4 "comparison_operator"
6589 +                       [(match_dup 2)
6590 +                        (const_int 0)])
6591 +                     (label_ref (match_operand 5 "" ""))
6592 +                     (pc)))]
6593 +  "(peep2_reg_dead_p (2, operands[0])
6594 +    && peep2_regno_dead_p (3, CC_REGNO))"
6595 +  [(set (match_dup 2)
6596 +       (compare (match_dup 1)
6597 +                (match_dup 3)))
6598 +   (set (pc)
6599 +       (if_then_else (match_op_dup 6
6600 +                       [(match_dup 2)
6601 +                        (const_int 0)])
6602 +                     (label_ref (match_dup 5))
6603 +                     (pc)))]
6604 +  "{
6605 +     rtx cc_reg;
6606 +
6607 +     cc_reg = gen_rtx_REG (GET_MODE (operands[2]), CC_REGNO);
6608 +     operands[6] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[4])),
6609 +                                  GET_MODE (operands[4]),
6610 +                                  cc_reg,
6611 +                                  const0_rtx);
6612 +   }")
6613 +
6614 +(define_insn_and_split "tstsi_lsl4"
6615 +  [(set (match_operand 0 "ubicom32_cc_register_operand" "=r")
6616 +       (match_operator 1 "ubicom32_compare_operator"
6617 +         [(match_operand:SI 2 "nonimmediate_operand"   "rm")
6618 +          (const_int 0)]))]
6619 +  "ubicom32_match_cc_mode(insn, CCWZNmode)"
6620 +  "#"
6621 +  "ubicom32_match_cc_mode(insn, CCWZNmode)"
6622 +  [(parallel
6623 +     [(set (match_dup 0)
6624 +          (match_op_dup 1
6625 +            [(match_dup 2)
6626 +             (const_int 0)]))
6627 +      (clobber (match_dup 3))])]
6628 +  "{
6629 +     operands[3] = gen_reg_rtx (SImode);
6630 +   }")
6631 +
6632 +(define_insn "tstsi_lsl4_d"
6633 +  [(set (reg CC_REGNO)
6634 +       (compare (match_operand:SI 0 "nonimmediate_operand" "rm")
6635 +                (const_int 0)))
6636 +   (clobber (match_operand:SI 1 "ubicom32_data_register_operand" "=d"))]
6637 +  "ubicom32_match_cc_mode(insn, CCWZNmode)"
6638 +  "lsl.4\\t%1, %0, #0")
6639 +
6640 +; Comparison for equality with -1.
6641 +;
6642 +(define_insn "cmpsi_not4_ccwz"
6643 +  [(set (reg CC_REGNO)
6644 +       (compare (match_operand:SI 0 "nonimmediate_operand" "rm")
6645 +                (const_int -1)))]
6646 +  "ubicom32_match_cc_mode(insn, CCWZmode)"
6647 +  "not.4\\t#0, %0")
6648 +
6649 +(define_expand "cmpsi"
6650 +  [(set (reg CC_REGNO)
6651 +       (compare (match_operand:SI 0 "ubicom32_arith_operand" "")
6652 +                (match_operand:SI 1 "ubicom32_compare_operand" "")))]
6653 +  ""
6654 +  "{
6655 +     do
6656 +       {
6657 +        /* Is this a cmpi?  We can't take a memory address as cmpi takes
6658 +            16-bit operands.  */
6659 +        if (register_operand (operands[0], SImode)
6660 +            && CONST_INT_P (operands[1])
6661 +            && satisfies_constraint_N (operands[1]))
6662 +          break;
6663 +
6664 +        /* Must be a sub.4 - if necessary copy an operand into a reg.  */
6665 +        if (! ubicom32_data_register_operand (operands[1], SImode))
6666 +          operands[1] = copy_to_mode_reg (SImode, operands[1]);
6667 +       }
6668 +     while (0);
6669 +
6670 +     ubicom32_compare_op0 = operands[0];
6671 +     ubicom32_compare_op1 = operands[1];
6672 +     DONE;
6673 +   }")
6674 +
6675 +(define_insn "cmpsi_cmpi"
6676 +  [(set (reg CC_REGNO)
6677 +       (compare (match_operand:SI 0 "register_operand" "r")
6678 +                (match_operand 1 "const_int_operand"   "N")))]
6679 +  "(satisfies_constraint_N (operands[1]))"
6680 +  "cmpi\\t%0, %1")
6681 +
6682 +(define_insn "cmpsi_sub4"
6683 +  [(set (reg CC_REGNO)
6684 +       (compare (match_operand:SI 0 "ubicom32_arith_operand"       "rmI")
6685 +                (match_operand:SI 1 "ubicom32_data_register_operand" "d")))]
6686 +  ""
6687 +  "sub.4\\t#0, %0, %1")
6688 +
6689 +; If we're testing for equality we don't have to worry about reversing conditions.
6690 +;
6691 +(define_insn "cmpsi_sub4_ccwz_1"
6692 +  [(set (reg CC_REGNO)
6693 +       (compare (match_operand:SI 0 "nonimmediate_operand"          "rm")
6694 +                (match_operand:SI 1 "ubicom32_data_register_operand" "d")))]
6695 +  "ubicom32_match_cc_mode(insn, CCWZmode)"
6696 +  "sub.4\\t#0, %0, %1")
6697 +
6698 +(define_insn "cmpsi_sub4_ccwz_2"
6699 +  [(set (reg CC_REGNO)
6700 +       (compare (match_operand:SI 0 "ubicom32_data_register_operand" "d")
6701 +                (match_operand:SI 1 "nonimmediate_operand"          "rm")))]
6702 +  "ubicom32_match_cc_mode(insn, CCWZmode)"
6703 +  "sub.4\\t#0, %1, %0")
6704 +
6705 +; When the combiner runs it doesn't have any insight into whether or not an argument
6706 +; to a compare is spilled to the stack and therefore can't swap the comparison in
6707 +; an attempt to use sub.4 more effectively.  We peephole this case here.
6708 +;
6709 +(define_peephole2
6710 +  [(set (match_operand:SI 0 "register_operand" "")
6711 +       (match_operand:SI 1 "ubicom32_arith_operand" ""))
6712 +   (set (match_operand 2 "ubicom32_cc_register_operand" "")
6713 +       (compare (match_operand:SI 3 "ubicom32_data_register_operand" "")
6714 +                (match_dup 0)))
6715 +   (set (pc)
6716 +       (if_then_else (match_operator 4 "comparison_operator"
6717 +                       [(match_dup 2)
6718 +                        (const_int 0)])
6719 +                     (label_ref (match_operand 5 "" ""))
6720 +                     (pc)))]
6721 +  "(peep2_reg_dead_p (2, operands[0])
6722 +    && peep2_regno_dead_p (3, CC_REGNO))"
6723 +  [(set (match_dup 2)
6724 +       (compare (match_dup 1)
6725 +                (match_dup 3)))
6726 +   (set (pc)
6727 +       (if_then_else (match_op_dup 6
6728 +                       [(match_dup 2)
6729 +                        (const_int 0)])
6730 +                     (label_ref (match_dup 5))
6731 +                     (pc)))]
6732 +  "{
6733 +     rtx cc_reg;
6734 +
6735 +     cc_reg = gen_rtx_REG (GET_MODE (operands[2]), CC_REGNO);
6736 +     operands[6] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[4])),
6737 +                                  GET_MODE (operands[4]),
6738 +                                  cc_reg,
6739 +                                  const0_rtx);
6740 +   }")
6741 +
6742 +(define_insn_and_split "tstdi_or4"
6743 +  [(set (reg:CCWZ CC_REGNO)
6744 +       (compare:CCWZ (match_operand:DI 0 "nonimmediate_operand" "rm")
6745 +                     (const_int 0)))]
6746 +  ""
6747 +  "#"
6748 +  ""
6749 +  [(parallel
6750 +     [(set (reg:CCWZ CC_REGNO)
6751 +          (compare:CCWZ (match_dup 0)
6752 +                        (const_int 0)))
6753 +      (clobber (match_dup 1))])]
6754 +  "{
6755 +     operands[1] = gen_reg_rtx (SImode);
6756 +   }")
6757 +
6758 +(define_insn "tstdi_or4_d"
6759 +  [(set (reg:CCWZ CC_REGNO)
6760 +       (compare:CCWZ (match_operand:DI 0 "nonimmediate_operand" "rm")
6761 +                     (const_int 0)))
6762 +   (clobber (match_operand:SI 1 "ubicom32_data_register_operand" "=d"))]
6763 +  ""
6764 +  "*
6765 +   {
6766 +     operands[2] = gen_lowpart (SImode, operands[0]);
6767 +     operands[3] = gen_highpart_mode (SImode, DImode, operands[0]);
6768 +
6769 +     if (ubicom32_data_register_operand (operands[0], GET_MODE (operands[0])))
6770 +       return \"or.4\\t#0, %2, %3\";
6771 +
6772 +     return \"move.4\\t%1, %2\;or.4\\t%1, %3, %1\";
6773 +   }"
6774 +  [(set_attr "length" "8")])
6775 +
6776 +(define_expand "cmpdi"
6777 +  [(set (reg CC_REGNO)
6778 +       (compare (match_operand:DI 0 "ubicom32_arith_operand" "")
6779 +                (match_operand:DI 1 "ubicom32_data_register_operand" "")))]
6780 +  ""
6781 +  "{
6782 +     ubicom32_compare_op0 = operands[0];
6783 +     ubicom32_compare_op1 = operands[1];
6784 +     DONE;
6785 +   }")
6786 +
6787 +(define_insn "cmpdi_sub4subc"
6788 +  [(set (reg CC_REGNO)
6789 +       (compare (match_operand:DI 0 "ubicom32_arith_operand"       "rmI")
6790 +                (match_operand:DI 1 "ubicom32_data_register_operand" "d")))]
6791 +  ""
6792 +  "*
6793 +   {
6794 +     operands[2] = gen_lowpart (SImode, operands[0]);
6795 +     operands[3] = gen_lowpart (SImode, operands[1]);
6796 +     operands[4] = gen_highpart_mode (SImode, DImode, operands[0]);
6797 +     operands[5] = gen_highpart_mode (SImode, DImode, operands[1]);
6798 +
6799 +     return \"sub.4\\t#0, %2, %3\;subc\\t#0, %4, %5\";
6800 +   }"
6801 +  [(set_attr "length" "8")])
6802 +
6803 +; When the combiner runs it doesn't have any insight into whether or not an argument
6804 +; to a compare is spilled to the stack and therefore can't swap the comparison in
6805 +; an attempt to use sub.4/subc more effectively.  We peephole this case here.
6806 +;
6807 +(define_peephole2
6808 +  [(set (match_operand:DI 0 "register_operand" "")
6809 +       (match_operand:DI 1 "ubicom32_arith_operand" ""))
6810 +   (set (match_operand 2 "ubicom32_cc_register_operand" "")
6811 +       (compare (match_operand:DI 3 "ubicom32_data_register_operand" "")
6812 +                (match_dup 0)))
6813 +   (set (pc)
6814 +       (if_then_else (match_operator 4 "comparison_operator"
6815 +                       [(match_dup 2)
6816 +                        (const_int 0)])
6817 +                     (label_ref (match_operand 5 "" ""))
6818 +                     (pc)))]
6819 +  "(peep2_reg_dead_p (2, operands[0])
6820 +    && peep2_regno_dead_p (3, CC_REGNO))"
6821 +  [(set (match_dup 2)
6822 +       (compare (match_dup 1)
6823 +                (match_dup 3)))
6824 +   (set (pc)
6825 +       (if_then_else (match_op_dup 6
6826 +                       [(match_dup 2)
6827 +                        (const_int 0)])
6828 +                     (label_ref (match_dup 5))
6829 +                     (pc)))]
6830 +  "{
6831 +     rtx cc_reg;
6832 +
6833 +     cc_reg = gen_rtx_REG (GET_MODE (operands[2]), CC_REGNO);
6834 +     operands[6] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[4])),
6835 +                                  GET_MODE (operands[4]),
6836 +                                  cc_reg,
6837 +                                  const0_rtx);
6838 +   }")
6839 +
6840 +(define_insn "btst"
6841 +  [(set (reg:CCWZ CC_REGNO)
6842 +       (compare:CCWZ
6843 +         (zero_extract:SI
6844 +           (match_operand:SI 0 "nonimmediate_operand"   "rm")
6845 +           (const_int 1)
6846 +           (match_operand:SI 1 "ubicom32_arith_operand" "dM"))
6847 +         (const_int 0)))]
6848 +  ""
6849 +  "btst\\t%0, %1")
6850 +
6851 +(define_insn "bfextu_ccwz_null"
6852 +  [(set (reg:CCWZ CC_REGNO)
6853 +       (compare:CCWZ
6854 +         (zero_extract:SI
6855 +           (match_operand:SI 0 "nonimmediate_operand" "rm")
6856 +           (match_operand 1 "const_int_operand"        "M")
6857 +           (const_int 0))
6858 +         (const_int 0)))
6859 +   (clobber (match_scratch:SI 2                               "=d"))]
6860 +  ""
6861 +  "bfextu\\t%2, %0, %1")
6862 +
6863 +(define_expand "addqi3"
6864 +  [(parallel
6865 +     [(set (match_operand:QI 0 "memory_operand" "")
6866 +          (plus:QI (match_operand:QI 1 "nonimmediate_operand" "")
6867 +                   (match_operand:QI 2 "ubicom32_arith_operand" "")))
6868 +      (clobber (reg:CC CC_REGNO))])]
6869 +  "(ubicom32_v4)"
6870 +  "{
6871 +     if (!memory_operand (operands[0], QImode))
6872 +       FAIL;
6873 +
6874 +     /* If we have a non-data reg for operand 1 then prefer that over
6875 +        a CONST_INT in operand 2.  */
6876 +     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
6877 +        && CONST_INT_P (operands[2]))
6878 +       operands[2] = copy_to_mode_reg (QImode, operands[2]);
6879 +
6880 +     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
6881 +       operands[2] = copy_to_mode_reg (QImode, operands[2]);
6882 +   }")
6883 +
6884 +(define_insn "addqi3_add1"
6885 +  [(set (match_operand:QI 0 "memory_operand"                  "=m, m")
6886 +       (plus:QI (match_operand:QI 1 "nonimmediate_operand"    "%d,rm")
6887 +                (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d")))
6888 +   (clobber (reg:CC CC_REGNO))]
6889 +  "(ubicom32_v4)"
6890 +  "@
6891 +   add.1\\t%0, %2, %1
6892 +   add.1\\t%0, %1, %2")
6893 +
6894 +(define_insn "addqi3_add1_ccszn_null"
6895 +  [(set (reg CC_REGNO)
6896 +       (compare
6897 +         (neg:QI (match_operand:QI 0 "nonimmediate_operand" "%d,rm"))
6898 +         (match_operand:QI 1 "ubicom32_arith_operand"      "rmI, d")))]
6899 +  "(ubicom32_v4
6900 +    && ubicom32_match_cc_mode(insn, CCSZNmode))"
6901 +  "@
6902 +   add.1\\t#0, %1, %0
6903 +   add.1\\t#0, %0, %1")
6904 +
6905 +(define_expand "addhi3"
6906 +  [(parallel
6907 +     [(set (match_operand:HI 0 "memory_operand" "")
6908 +          (plus:HI (match_operand:HI 1 "nonimmediate_operand" "")
6909 +                   (match_operand:HI 2 "ubicom32_arith_operand" "")))
6910 +      (clobber (reg:CC CC_REGNO))])]
6911 +  ""
6912 +  "{
6913 +     if (!memory_operand (operands[0], HImode))
6914 +       FAIL;
6915 +
6916 +     /* If we have a non-data reg for operand 1 then prefer that over
6917 +        a CONST_INT in operand 2.  */
6918 +     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
6919 +        && CONST_INT_P (operands[2]))
6920 +       operands[2] = copy_to_mode_reg (HImode, operands[2]);
6921 +
6922 +     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
6923 +       operands[2] = copy_to_mode_reg (HImode, operands[2]);
6924 +   }")
6925 +
6926 +(define_insn "addhi3_add2"
6927 +  [(set (match_operand:HI 0 "memory_operand"                  "=m, m")
6928 +       (plus:HI (match_operand:HI 1 "nonimmediate_operand"    "%d,rm")
6929 +                (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d")))
6930 +   (clobber (reg:CC CC_REGNO))]
6931 +  ""
6932 +  "@
6933 +   add.2\\t%0, %2, %1
6934 +   add.2\\t%0, %1, %2")
6935 +
6936 +(define_insn "addhi3_add2_ccszn_null"
6937 +  [(set (reg CC_REGNO)
6938 +       (compare
6939 +         (neg:HI (match_operand:HI 0 "nonimmediate_operand" "%d,rm"))
6940 +         (match_operand:HI 1 "ubicom32_arith_operand"      "rmI, d")))]
6941 +  "ubicom32_match_cc_mode(insn, CCSZNmode)"
6942 +  "@
6943 +   add.2\\t#0, %1, %0
6944 +   add.2\\t#0, %0, %1")
6945 +
6946 +(define_expand "addsi3"
6947 +  [(set (match_operand:SI 0 "nonimmediate_operand" "")
6948 +       (plus:SI (match_operand:SI 1 "nonimmediate_operand" "")
6949 +                (match_operand:SI 2 "ubicom32_move_operand" "")))]
6950 +  ""
6951 +  "{
6952 +     ubicom32_expand_addsi3 (operands);
6953 +     DONE;
6954 +   }")
6955 +
6956 +; We start with an instruction pattern that can do all sorts of interesting
6957 +; things but we split out any uses of lea or pdec instructions because
6958 +; those instructions don't clobber the condition codes.
6959 +;
6960 +(define_insn_and_split "addsi3_1"
6961 +  [(set (match_operand:SI 0 "nonimmediate_operand"        "=rm,rm,rm,rm,rm, rm,rm")
6962 +       (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%a, a, a, a, a,  d,rm")
6963 +                (match_operand:SI 2 "ubicom32_move_operand" "L, K, J, P, d,rmI, d")))
6964 +   (clobber (reg:CC CC_REGNO))]
6965 +  ""
6966 +  "@
6967 +   #
6968 +   #
6969 +   #
6970 +   #
6971 +   #
6972 +   add.4\\t%0, %2, %1
6973 +   add.4\\t%0, %1, %2"
6974 +  "(reload_completed
6975 +    && ubicom32_address_register_operand (operands[1], GET_MODE (operands[1])))"
6976 +  [(set (match_dup 0)
6977 +       (plus:SI (match_dup 1)
6978 +                (match_dup 2)))]
6979 +  ""
6980 +)
6981 +
6982 +(define_insn "addsi3_1_ccwzn"
6983 +  [(set (reg CC_REGNO)
6984 +       (compare
6985 +         (plus:SI (match_operand:SI 1 "nonimmediate_operand"    "%d,rm")
6986 +                  (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d"))
6987 +         (const_int 0)))
6988 +   (set (match_operand:SI 0 "nonimmediate_operand"             "=rm,rm")
6989 +       (plus:SI (match_dup 1)
6990 +                (match_dup 2)))]
6991 +  "ubicom32_match_cc_mode(insn, CCWZNmode)"
6992 +  "@
6993 +   add.4\\t%0, %2, %1
6994 +   add.4\\t%0, %1, %2")
6995 +
6996 +(define_insn "addsi3_1_ccwzn_null"
6997 +  [(set (reg CC_REGNO)
6998 +       (compare
6999 +         (neg:SI (match_operand:SI 0 "nonimmediate_operand" "%d,rm"))
7000 +         (match_operand:SI 1 "ubicom32_arith_operand"      "rmI, d")))]
7001 +  "ubicom32_match_cc_mode(insn, CCWZNmode)"
7002 +  "@
7003 +   add.4\\t#0, %1, %0
7004 +   add.4\\t#0, %0, %1")
7005 +
7006 +(define_insn_and_split "addsi3_2"
7007 +  [(set (match_operand:SI 0 "nonimmediate_operand"                     "=rm,rm,rm,rm,rm,rm")
7008 +       (plus:SI (match_operand:SI 1 "ubicom32_address_register_operand" "%a, a, a, a, a, a")
7009 +                (match_operand:SI 2 "ubicom32_move_operand"              "L, K, J, P, d, n")))]
7010 +  ""
7011 +  "@
7012 +   lea.4\\t%0, %E2(%1)
7013 +   lea.2\\t%0, %E2(%1)
7014 +   lea.1\\t%0, %E2(%1)
7015 +   pdec\\t%0, %n2(%1)
7016 +   lea.1\\t%0, (%1,%2)
7017 +   #"
7018 +  "(reload_completed
7019 +    && ! satisfies_constraint_L (operands[2])
7020 +    && ! satisfies_constraint_K (operands[2])
7021 +    && ! satisfies_constraint_J (operands[2])
7022 +    && ! satisfies_constraint_P (operands[2])
7023 +    && ! ubicom32_data_register_operand (operands[2], GET_MODE (operands[2])))"
7024 +  [(set (reg:SI AUX_DATA_REGNO)
7025 +       (match_dup 2))
7026 +   (set (match_dup 0)
7027 +       (plus:SI (match_dup 1)
7028 +                (reg:SI AUX_DATA_REGNO)))]
7029 +  ""
7030 +)
7031 +
7032 +(define_insn "lea_2"
7033 +  [(set (match_operand:SI 0 "nonimmediate_operand"                          "=rm")
7034 +       (plus:SI (mult:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")
7035 +                         (const_int 2))
7036 +                (match_operand:SI 2 "ubicom32_address_register_operand"       "a")))]
7037 +  ""
7038 +  "lea.2\\t%0, (%2,%1)")
7039 +
7040 +(define_insn "lea_4"
7041 +  [(set (match_operand:SI 0 "nonimmediate_operand"                          "=rm")
7042 +       (plus:SI (mult:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")
7043 +                         (const_int 4))
7044 +                (match_operand:SI 2 "ubicom32_address_register_operand"       "a")))]
7045 +  ""
7046 +  "lea.4\\t%0, (%2,%1)")
7047 +
7048 +(define_expand "adddi3"
7049 +  [(parallel
7050 +     [(set (match_operand:DI 0 "nonimmediate_operand" "")
7051 +          (plus:DI (match_operand:DI 1 "nonimmediate_operand" "")
7052 +                   (match_operand:DI 2 "ubicom32_arith_operand" "")))
7053 +      (clobber (reg:CC CC_REGNO))])]
7054 +  ""
7055 +  "{
7056 +     /* If we have a non-data reg for operand 1 then prefer that over
7057 +        a CONST_INT in operand 2.  */
7058 +     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
7059 +        && CONST_INT_P (operands[2]))
7060 +       operands[2] = copy_to_mode_reg (DImode, operands[2]);
7061 +
7062 +     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
7063 +       operands[2] = copy_to_mode_reg (DImode, operands[2]);
7064 +   }")
7065 +
7066 +; We construct a 64-bit add from 32-bit operations.  Note that we use the
7067 +; & constraint to prevent overlapping registers being allocated.  We do
7068 +; allow identical registers though as that won't break anything.
7069 +;
7070 +(define_insn "adddi3_add4addc"
7071 +  [(set (match_operand:DI 0 "nonimmediate_operand"           "=&r,&r,rm,  d,  m, m")
7072 +       (plus:DI (match_operand:DI 1 "nonimmediate_operand"    "%d,rm, 0,  0,  d,rm")
7073 +                (match_operand:DI 2 "ubicom32_arith_operand" "rmI, d, d,rmI,rmI, d")))
7074 +   (clobber (reg:CC CC_REGNO))]
7075 +  ""
7076 +  "*
7077 +   {
7078 +     operands[3] = gen_lowpart (SImode, operands[0]);
7079 +     operands[4] = gen_lowpart (SImode, operands[1]);
7080 +     operands[5] = gen_lowpart (SImode, operands[2]);
7081 +     operands[6] = gen_highpart (SImode, operands[0]);
7082 +     operands[7] = gen_highpart (SImode, operands[1]);
7083 +     operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
7084 +
7085 +     if (ubicom32_data_register_operand (operands[2], GET_MODE (operands[2])))
7086 +       return \"add.4\\t%3, %4, %5\;addc\\t%6, %7, %8\";
7087 +
7088 +     return \"add.4\\t%3, %5, %4\;addc\\t%6, %8, %7\";
7089 +   }"
7090 +  [(set_attr "length" "8")])
7091 +
7092 +(define_insn "adddi3_ccwz"
7093 +  [(set (reg CC_REGNO)
7094 +       (compare
7095 +         (plus:DI (match_operand:DI 1 "nonimmediate_operand"    "%d,rm, 0,  0,  d,rm")
7096 +                  (match_operand:DI 2 "ubicom32_arith_operand" "rmI, d, d,rmI,rmI, d"))
7097 +         (const_int 0)))
7098 +   (set (match_operand:DI 0 "nonimmediate_operand"             "=&r,&r,rm,  d,  m, m")
7099 +       (plus:DI (match_dup 1)
7100 +                (match_dup 2)))]
7101 +  "ubicom32_match_cc_mode(insn, CCWZNmode)"
7102 +  "*
7103 +   {
7104 +     operands[3] = gen_lowpart (SImode, operands[0]);
7105 +     operands[6] = gen_highpart (SImode, operands[0]);
7106 +
7107 +     if (ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])))
7108 +       {
7109 +        operands[4] = gen_lowpart (SImode, operands[1]);
7110 +        operands[5] = gen_lowpart (SImode, operands[2]);
7111 +        operands[7] = gen_highpart (SImode, operands[1]);
7112 +        operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
7113 +       }
7114 +     else
7115 +       {
7116 +        operands[4] = gen_lowpart (SImode, operands[2]);
7117 +        operands[5] = gen_lowpart (SImode, operands[1]);
7118 +        operands[7] = gen_highpart (SImode, operands[2]);
7119 +        operands[8] = gen_highpart (SImode, operands[1]);
7120 +       }
7121 +
7122 +     return \"add.4\\t%3, %5, %4\;addc\\t%6, %8, %7\";
7123 +   }"
7124 +  [(set_attr "length" "8")])
7125 +
7126 +(define_insn "adddi3_ccwz_null"
7127 +  [(set (reg CC_REGNO)
7128 +       (compare
7129 +         (neg:DI (match_operand:DI 0 "nonimmediate_operand" "%d,rm"))
7130 +         (match_operand:DI 1 "ubicom32_arith_operand"      "rmI, d")))]
7131 +  "ubicom32_match_cc_mode(insn, CCWZNmode)"
7132 +  "*
7133 +   {
7134 +     if (ubicom32_data_register_operand (operands[0], GET_MODE (operands[0])))
7135 +       {
7136 +        operands[2] = gen_lowpart (SImode, operands[0]);
7137 +        operands[3] = gen_lowpart (SImode, operands[1]);
7138 +        operands[4] = gen_highpart (SImode, operands[0]);
7139 +        operands[5] = gen_highpart_mode (SImode, DImode, operands[1]);
7140 +       }
7141 +     else
7142 +       {
7143 +        operands[2] = gen_lowpart (SImode, operands[1]);
7144 +        operands[3] = gen_lowpart (SImode, operands[0]);
7145 +        operands[4] = gen_highpart (SImode, operands[1]);
7146 +        operands[5] = gen_highpart (SImode, operands[0]);
7147 +       }
7148 +
7149 +     return \"add.4\\t#0, %3, %2\;addc\\t#0, %5, %4\";
7150 +   }"
7151 +  [(set_attr "length" "8")])
7152 +
7153 +(define_expand "subqi3"
7154 +  [(parallel
7155 +     [(set (match_operand:QI 0 "memory_operand" "")
7156 +          (minus:QI (match_operand:QI 1 "ubicom32_arith_operand" "")
7157 +                    (match_operand:QI 2 "ubicom32_data_register_operand" "")))
7158 +      (clobber (reg:CC CC_REGNO))])]
7159 +  "(ubicom32_v4)"
7160 +  "{
7161 +     if (!memory_operand (operands[0], QImode))
7162 +       FAIL;
7163 +   }")
7164 +
7165 +(define_insn "subqi3_sub1"
7166 +  [(set (match_operand:QI 0 "memory_operand"                         "=m")
7167 +       (minus:QI (match_operand:QI 1 "ubicom32_arith_operand"       "rmI")
7168 +                 (match_operand:QI 2 "ubicom32_data_register_operand" "d")))
7169 +   (clobber (reg:CC CC_REGNO))]
7170 +  "(ubicom32_v4)"
7171 +  "sub.1\\t%0, %1, %2")
7172 +
7173 +(define_expand "subhi3"
7174 +  [(parallel
7175 +     [(set (match_operand:HI 0 "memory_operand" "")
7176 +          (minus:HI (match_operand:HI 1 "ubicom32_arith_operand" "")
7177 +                    (match_operand:HI 2 "ubicom32_data_register_operand" "")))
7178 +      (clobber (reg:CC CC_REGNO))])]
7179 +  "(ubicom32_v4)"
7180 +  "{
7181 +     if (!memory_operand (operands[0], HImode))
7182 +       FAIL;
7183 +   }")
7184 +
7185 +(define_insn "subhi3_sub2"
7186 +  [(set (match_operand:HI 0 "memory_operand"                         "=m")
7187 +       (minus:HI (match_operand:HI 1 "ubicom32_arith_operand"       "rmI")
7188 +                 (match_operand:HI 2 "ubicom32_data_register_operand" "d")))
7189 +   (clobber (reg:CC CC_REGNO))]
7190 +  ""
7191 +  "sub.2\\t%0, %1, %2")
7192 +
7193 +(define_insn "subsi3"
7194 +  [(set (match_operand:SI 0 "nonimmediate_operand"                  "=rm")
7195 +       (minus:SI (match_operand:SI 1 "ubicom32_arith_operand"       "rmI")
7196 +                 (match_operand:SI 2 "ubicom32_data_register_operand" "d")))
7197 +   (clobber (reg:CC CC_REGNO))]
7198 +  ""
7199 +  "sub.4\\t%0, %1, %2")
7200 +
7201 +(define_insn "subsi3_ccwz"
7202 +  [(set (reg CC_REGNO)
7203 +       (compare
7204 +         (minus:SI (match_operand:SI 1 "ubicom32_arith_operand"       "rmI")
7205 +                   (match_operand:SI 2 "ubicom32_data_register_operand" "d"))
7206 +         (const_int 0)))
7207 +   (set (match_operand:SI 0 "nonimmediate_operand"                    "=rm")
7208 +       (minus:SI (match_dup 1)
7209 +                 (match_dup 2)))]
7210 +  "ubicom32_match_cc_mode(insn, CCWZNmode)"
7211 +  "sub.4\\t%0, %1, %2")
7212 +
7213 +; We construct a 64-bit add from 32-bit operations.  Note that we use the
7214 +; & constraint to prevent overlapping registers being allocated.  We do
7215 +; allow identical registers though as that won't break anything.
7216 +;
7217 +(define_insn "subdi3"
7218 +  [(set (match_operand:DI 0 "nonimmediate_operand"                  "=&r,r,  d,  m")
7219 +       (minus:DI (match_operand:DI 1 "ubicom32_arith_operand"       "rmI,0,rmI,rmI")
7220 +                 (match_operand:DI 2 "ubicom32_data_register_operand" "d,d,  0,  d")))
7221 +   (clobber (reg:CC CC_REGNO))]
7222 +  ""
7223 +  "*
7224 +   {
7225 +     operands[3] = gen_lowpart (SImode, operands[0]);
7226 +     operands[4] = gen_lowpart (SImode, operands[1]);
7227 +     operands[5] = gen_lowpart (SImode, operands[2]);
7228 +     operands[6] = gen_highpart (SImode, operands[0]);
7229 +     operands[7] = gen_highpart_mode (SImode, DImode, operands[1]);
7230 +     operands[8] = gen_highpart (SImode, operands[2]);
7231 +
7232 +     return \"sub.4\\t%3, %4, %5\;subc\\t%6, %7, %8\";
7233 +   }"
7234 +  [(set_attr "length" "8")])
7235 +
7236 +(define_insn "subdi3_ccwz"
7237 +  [(set (reg CC_REGNO)
7238 +       (compare
7239 +         (minus:DI (match_operand:DI 1 "ubicom32_arith_operand"       "rmI,rmI")
7240 +                   (match_operand:DI 2 "ubicom32_data_register_operand" "d,  d"))
7241 +         (const_int 0)))
7242 +   (set (match_operand:DI 0 "nonimmediate_operand"                    "=&r,  m")
7243 +       (minus:DI (match_dup 1)
7244 +                 (match_dup 2)))]
7245 +  "ubicom32_match_cc_mode(insn, CCWZNmode)"
7246 +  "*
7247 +   {
7248 +     operands[3] = gen_lowpart (SImode, operands[0]);
7249 +     operands[4] = gen_lowpart (SImode, operands[1]);
7250 +     operands[5] = gen_lowpart (SImode, operands[2]);
7251 +     operands[6] = gen_highpart (SImode, operands[0]);
7252 +     operands[7] = gen_highpart_mode (SImode, DImode, operands[1]);
7253 +     operands[8] = gen_highpart (SImode, operands[2]);
7254 +
7255 +     return \"sub.4\\t%3, %4, %5\;subc\\t%6, %7, %8\";
7256 +   }"
7257 +  [(set_attr "length" "8")])
7258 +
7259 +;(define_insn "negqi2"
7260 +;  [(set (match_operand:QI 0 "nonimmediate_operand"               "=rm")
7261 +;      (neg:QI (match_operand:QI 1 "ubicom32_data_register_operand" "d")))
7262 +;   (clobber (reg:CC CC_REGNO))]
7263 +;  "(ubicom32_v4)"
7264 +;  "sub.1\\t%0, #0, %1")
7265 +
7266 +;(define_insn "neghi2"
7267 +;  [(set (match_operand:HI 0 "nonimmediate_operand"               "=rm")
7268 +;      (neg:HI (match_operand:HI 1 "ubicom32_data_register_operand" "d")))
7269 +;   (clobber (reg:CC CC_REGNO))]
7270 +;  ""
7271 +;  "sub.2\\t%0, #0, %1")
7272 +
7273 +(define_insn "negsi2"
7274 +  [(set (match_operand:SI 0 "nonimmediate_operand"                "=rm")
7275 +       (neg:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")))
7276 +   (clobber (reg:CC CC_REGNO))]
7277 +  ""
7278 +  "sub.4\\t%0, #0, %1")
7279 +
7280 +(define_insn_and_split "negdi2"
7281 +  [(set (match_operand:DI 0 "nonimmediate_operand"               "=&rm")
7282 +       (neg:DI (match_operand:DI 1 "ubicom32_data_register_operand" "d")))
7283 +   (clobber (reg:CC CC_REGNO))]
7284 +  ""
7285 +  "#"
7286 +  "reload_completed"
7287 +  [(parallel [(set (match_dup 0)
7288 +                  (minus:DI (const_int 0)
7289 +                            (match_dup 1)))
7290 +             (clobber (reg:CC CC_REGNO))])]
7291 +  ""
7292 +  [(set_attr "length" "8")])
7293 +
7294 +(define_insn "umulhisi3"
7295 +  [(set (match_operand:SI 0 "ubicom32_acc_lo_register_operand"      "=l, l")
7296 +       (mult:SI
7297 +         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "%d,rm"))
7298 +         (zero_extend:SI (match_operand:HI 2 "nonimmediate_operand" "rm, d"))))
7299 +   (clobber (reg:HI ACC0_HI_REGNO))
7300 +   (clobber (reg:HI ACC1_HI_REGNO))]
7301 +  ""
7302 +  "@
7303 +   mulu\\t%A0, %2, %1
7304 +   mulu\\t%A0, %1, %2"
7305 +  [(set_attr "type" "mul,mul")])
7306 +
7307 +(define_insn "mulhisi3"
7308 +  [(set (match_operand:SI 0 "ubicom32_acc_lo_register_operand"      "=l, l")
7309 +       (mult:SI
7310 +         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "%d,rm"))
7311 +         (sign_extend:SI (match_operand:HI 2 "nonimmediate_operand" "rm, d"))))
7312 +   (clobber (reg:HI ACC0_HI_REGNO))
7313 +   (clobber (reg:HI ACC1_HI_REGNO))]
7314 +  ""
7315 +  "@
7316 +   muls\\t%A0, %2, %1
7317 +   muls\\t%A0, %1, %2"
7318 +  [(set_attr "type" "mul,mul")])
7319 +
7320 +(define_expand "mulsi3"
7321 +  [(set (match_operand:SI 0 "ubicom32_acc_hi_register_operand" "")
7322 +       (mult:SI (match_operand:SI 1 "ubicom32_arith_operand" "")
7323 +                (match_operand:SI 2 "ubicom32_arith_operand" "")))]
7324 +  ""
7325 +  "{
7326 +     if (ubicom32_emit_mult_sequence (operands))
7327 +       DONE;
7328 +   }")
7329 +
7330 +(define_insn "umulsidi3"
7331 +  [(set (match_operand:DI 0 "ubicom32_acc_hi_register_operand"      "=h, h")
7332 +       (mult:DI
7333 +         (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "%d,rm"))
7334 +         (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm, d"))))]
7335 +  "(ubicom32_v4)"
7336 +  "@
7337 +   mulu.4\\t%A0, %2, %1
7338 +   mulu.4\\t%A0, %1, %2"
7339 +  [(set_attr "type" "mul,mul")])
7340 +
7341 +(define_peephole2
7342 +  [(set (match_operand:SI 0 "register_operand" "")
7343 +       (match_operand:SI 1 "nonimmediate_operand" ""))
7344 +   (set (match_operand:DI 2 "ubicom32_acc_hi_register_operand" "")
7345 +       (mult:DI
7346 +         (zero_extend:DI (match_dup 0))
7347 +         (zero_extend:DI (match_operand:SI 3 "ubicom32_data_register_operand" ""))))]
7348 +  "(peep2_reg_dead_p (2, operands[0])
7349 +    || REGNO (operands[0]) == REGNO (operands[2])
7350 +    || REGNO (operands[0]) == REGNO (operands[2]) + 1)
7351 +   && ! rtx_equal_p (operands[0], operands[3])"
7352 +  [(set (match_dup 2)
7353 +       (mult:DI
7354 +         (zero_extend:DI (match_dup 1))
7355 +         (zero_extend:DI (match_dup 3))))]
7356 +  "")
7357 +
7358 +(define_peephole2
7359 +  [(set (match_operand:SI 0 "register_operand" "")
7360 +       (match_operand:SI 1 "nonimmediate_operand" ""))
7361 +   (set (match_operand:DI 2 "ubicom32_acc_hi_register_operand" "")
7362 +       (mult:DI
7363 +         (zero_extend:DI (match_operand:SI 3 "ubicom32_data_register_operand" ""))
7364 +         (zero_extend:DI (match_dup 0))))]
7365 +  "(peep2_reg_dead_p (2, operands[0])
7366 +    || REGNO (operands[0]) == REGNO (operands[2])
7367 +    || REGNO (operands[0]) == REGNO (operands[2]) + 1)
7368 +   && ! rtx_equal_p (operands[0], operands[3])"
7369 +  [(set (match_dup 2)
7370 +       (mult:DI
7371 +         (zero_extend:DI (match_dup 1))
7372 +         (zero_extend:DI (match_dup 3))))]
7373 +  "")
7374 +
7375 +(define_insn "umulsidi3_const"
7376 +  [(set (match_operand:DI 0 "ubicom32_acc_hi_register_operand"                "=h")
7377 +       (mult:DI
7378 +         (zero_extend:DI (match_operand:SI 1 "ubicom32_data_register_operand" "%d"))
7379 +         (match_operand 2 "const_int_operand"                                  "I")))]
7380 +  "(ubicom32_v4 && satisfies_constraint_I (operands[2]))"
7381 +  "mulu.4\\t%A0, %2, %1"
7382 +  [(set_attr "type" "mul")])
7383 +
7384 +(define_insn "mulsidi3"
7385 +  [(set (match_operand:DI 0 "ubicom32_acc_hi_register_operand"      "=h, h")
7386 +       (mult:DI
7387 +         (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "%d,rm"))
7388 +         (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm, d"))))]
7389 +  "(ubicom32_v4)"
7390 +  "@
7391 +   muls.4\\t%A0, %2, %1
7392 +   muls.4\\t%A0, %1, %2"
7393 +  [(set_attr "type" "mul,mul")])
7394 +
7395 +(define_peephole2
7396 +  [(set (match_operand:SI 0 "register_operand" "")
7397 +       (match_operand:SI 1 "nonimmediate_operand" ""))
7398 +   (set (match_operand:DI 2 "ubicom32_acc_hi_register_operand" "")
7399 +       (mult:DI
7400 +         (sign_extend:DI (match_dup 0))
7401 +         (sign_extend:DI (match_operand:SI 3 "ubicom32_data_register_operand" ""))))]
7402 +  "(peep2_reg_dead_p (2, operands[0])
7403 +    || REGNO (operands[0]) == REGNO (operands[2])
7404 +    || REGNO (operands[0]) == REGNO (operands[2]) + 1)
7405 +   && ! rtx_equal_p (operands[0], operands[3])"
7406 +  [(set (match_dup 2)
7407 +       (mult:DI
7408 +         (sign_extend:DI (match_dup 1))
7409 +         (sign_extend:DI (match_dup 3))))]
7410 +  "")
7411 +
7412 +(define_peephole2
7413 +  [(set (match_operand:SI 0 "register_operand" "")
7414 +       (match_operand:SI 1 "nonimmediate_operand" ""))
7415 +   (set (match_operand:DI 2 "ubicom32_acc_hi_register_operand" "")
7416 +       (mult:DI
7417 +         (sign_extend:DI (match_operand:SI 3 "ubicom32_data_register_operand" ""))
7418 +         (sign_extend:DI (match_dup 0))))]
7419 +  "(peep2_reg_dead_p (2, operands[0])
7420 +    || REGNO (operands[0]) == REGNO (operands[2])
7421 +    || REGNO (operands[0]) == REGNO (operands[2]) + 1)
7422 +   && ! rtx_equal_p (operands[0], operands[3])"
7423 +  [(set (match_dup 2)
7424 +       (mult:DI
7425 +         (sign_extend:DI (match_dup 1))
7426 +         (sign_extend:DI (match_dup 3))))]
7427 +  "")
7428 +
7429 +(define_insn "mulsidi3_const"
7430 +  [(set (match_operand:DI 0 "ubicom32_acc_hi_register_operand"                "=h")
7431 +       (mult:DI
7432 +         (sign_extend:DI (match_operand:SI 1 "ubicom32_data_register_operand" "%d"))
7433 +         (match_operand 2 "const_int_operand"                                  "I")))]
7434 +  "(ubicom32_v4 && satisfies_constraint_I (operands[2]))"
7435 +  "muls.4\\t%A0, %2, %1"
7436 +  [(set_attr "type" "mul")])
7437 +
7438 +(define_expand "andqi3"
7439 +  [(parallel
7440 +     [(set (match_operand:QI 0 "memory_operand" "")
7441 +          (and:QI (match_operand:QI 1 "nonimmediate_operand" "")
7442 +                  (match_operand:QI 2 "ubicom32_arith_operand" "")))
7443 +      (clobber (reg:CC CC_REGNO))])]
7444 +  "(ubicom32_v4)"
7445 +  "{
7446 +     if (!memory_operand (operands[0], QImode))
7447 +       FAIL;
7448 +
7449 +     /* If we have a non-data reg for operand 1 then prefer that over
7450 +        a CONST_INT in operand 2.  */
7451 +     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
7452 +        && CONST_INT_P (operands[2]))
7453 +       operands[2] = copy_to_mode_reg (QImode, operands[2]);
7454 +
7455 +     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
7456 +       operands[2] = copy_to_mode_reg (QImode, operands[2]);
7457 +   }")
7458 +
7459 +(define_insn "andqi3_and1"
7460 +  [(set (match_operand:QI 0 "memory_operand"                 "=m, m")
7461 +       (and:QI (match_operand:QI 1 "nonimmediate_operand"    "%d,rm")
7462 +               (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d")))
7463 +   (clobber (reg:CC CC_REGNO))]
7464 +  "(ubicom32_v4)"
7465 +  "@
7466 +   and.1\\t%0, %2, %1
7467 +   and.1\\t%0, %1, %2")
7468 +
7469 +(define_insn "andqi3_and1_ccszn"
7470 +  [(set (reg CC_REGNO)
7471 +       (compare
7472 +         (and:QI (match_operand:QI 1 "nonimmediate_operand"    "%d,rm")
7473 +                 (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d"))
7474 +         (const_int 0)))
7475 +   (set (match_operand:QI 0 "memory_operand"                   "=m, m")
7476 +       (and:QI (match_dup 1)
7477 +               (match_dup 2)))]
7478 +  "(ubicom32_v4
7479 +    && ubicom32_match_cc_mode(insn, CCSZNmode))"
7480 +  "@
7481 +   and.1\\t%0, %2, %1
7482 +   and.1\\t%0, %1, %2")
7483 +
7484 +(define_insn "andqi3_and1_ccszn_null"
7485 +  [(set (reg CC_REGNO)
7486 +       (compare
7487 +         (and:QI (match_operand:QI 0 "nonimmediate_operand"    "%d,rm")
7488 +                 (match_operand:QI 1 "ubicom32_arith_operand" "rmI, d"))
7489 +         (const_int 0)))]
7490 +  "(ubicom32_v4
7491 +    && ubicom32_match_cc_mode(insn, CCSZNmode))"
7492 +  "@
7493 +   and.1\\t#0, %1, %0
7494 +   and.1\\t#0, %0, %1")
7495 +
7496 +(define_insn "and1_ccszn_null_1"
7497 +  [(set (reg CC_REGNO)
7498 +       (compare
7499 +         (subreg:QI
7500 +           (and:SI (match_operand:SI 0 "ubicom32_data_register_operand" "%d")
7501 +                   (match_operand:SI 1 "ubicom32_arith_operand"         "rI"))
7502 +           3)
7503 +         (const_int 0)))]
7504 +  "(ubicom32_v4
7505 +    && ubicom32_match_cc_mode(insn, CCSZNmode))"
7506 +  "and.1\\t#0, %1, %0")
7507 +
7508 +(define_insn "and1_ccszn_null_2"
7509 +  [(set (reg CC_REGNO)
7510 +       (compare
7511 +         (subreg:QI
7512 +           (and:SI (match_operand:SI 0 "ubicom32_data_register_operand" "d")
7513 +                   (subreg:SI
7514 +                     (match_operand:QI 1 "memory_operand"               "m")
7515 +                     0))
7516 +           3)
7517 +         (const_int 0)))]
7518 +  "(ubicom32_v4
7519 +    && ubicom32_match_cc_mode(insn, CCSZNmode))"
7520 +  "and.1\\t#0, %1, %0")
7521 +
7522 +(define_insn "and1_ccszn_null_3"
7523 +  [(set (reg CC_REGNO)
7524 +       (compare
7525 +         (subreg:QI
7526 +           (and:SI (subreg:SI
7527 +                     (match_operand:QI 0 "memory_operand"               "m")
7528 +                     0)
7529 +                   (match_operand:SI 1 "ubicom32_data_register_operand" "d"))
7530 +           3)
7531 +         (const_int 0)))]
7532 +  "(ubicom32_v4
7533 +    && ubicom32_match_cc_mode(insn, CCSZNmode))"
7534 +  "and.1\\t#0, %0, %1")
7535 +
7536 +(define_expand "andhi3"
7537 +  [(parallel
7538 +     [(set (match_operand:HI 0 "memory_operand" "")
7539 +          (and:HI (match_operand:HI 1 "nonimmediate_operand" "")
7540 +                  (match_operand:HI 2 "ubicom32_arith_operand" "")))
7541 +      (clobber (reg:CC CC_REGNO))])]
7542 +  ""
7543 +  "{
7544 +     if (!memory_operand (operands[0], HImode))
7545 +       FAIL;
7546 +
7547 +     /* If we have a non-data reg for operand 1 then prefer that over
7548 +        a CONST_INT in operand 2.  */
7549 +     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
7550 +        && CONST_INT_P (operands[2]))
7551 +       operands[2] = copy_to_mode_reg (HImode, operands[2]);
7552 +
7553 +     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
7554 +       operands[2] = copy_to_mode_reg (HImode, operands[2]);
7555 +   }")
7556 +
7557 +(define_insn "andhi3_and2"
7558 +  [(set (match_operand:HI 0 "memory_operand"                 "=m, m")
7559 +       (and:HI (match_operand:HI 1 "nonimmediate_operand"    "%d,rm")
7560 +               (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d")))
7561 +   (clobber (reg:CC CC_REGNO))]
7562 +  ""
7563 +  "@
7564 +   and.2\\t%0, %2, %1
7565 +   and.2\\t%0, %1, %2")
7566 +
7567 +(define_insn "andhi3_and2_ccszn"
7568 +  [(set (reg CC_REGNO)
7569 +       (compare
7570 +         (and:HI (match_operand:HI 1 "nonimmediate_operand"    "%d,rm")
7571 +                 (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d"))
7572 +         (const_int 0)))
7573 +   (set (match_operand:HI 0 "memory_operand"                   "=m, m")
7574 +       (and:HI (match_dup 1)
7575 +               (match_dup 2)))]
7576 +  "ubicom32_match_cc_mode(insn, CCSZNmode)"
7577 +  "@
7578 +   and.2\\t%0, %2, %1
7579 +   and.2\\t%0, %1, %2")
7580 +
7581 +(define_insn "andhi3_and2_ccszn_null"
7582 +  [(set (reg CC_REGNO)
7583 +       (compare
7584 +         (and:HI (match_operand:HI 0 "nonimmediate_operand"    "%d,rm")
7585 +                 (match_operand:HI 1 "ubicom32_arith_operand" "rmI, d"))
7586 +         (const_int 0)))]
7587 +  "ubicom32_match_cc_mode(insn, CCSZNmode)"
7588 +  "@
7589 +   and.2\\t#0, %1, %0
7590 +   and.2\\t#0, %0, %1")
7591 +
7592 +(define_insn "and2_ccszn_null_1"
7593 +  [(set (reg CC_REGNO)
7594 +       (compare
7595 +         (subreg:HI
7596 +           (and:SI (match_operand:SI 0 "ubicom32_data_register_operand" "%d")
7597 +                   (match_operand:SI 1 "ubicom32_arith_operand"         "rI"))
7598 +           2)
7599 +         (const_int 0)))]
7600 +  "ubicom32_match_cc_mode(insn, CCSZNmode)"
7601 +  "and.2\\t#0, %1, %0")
7602 +
7603 +(define_insn "and2_ccszn_null_2"
7604 +  [(set (reg CC_REGNO)
7605 +       (compare
7606 +         (subreg:HI
7607 +           (and:SI (match_operand:SI 0 "ubicom32_data_register_operand" "d")
7608 +                   (subreg:SI
7609 +                     (match_operand:HI 1 "memory_operand"               "m")
7610 +                     0))
7611 +           2)
7612 +         (const_int 0)))]
7613 +  "ubicom32_match_cc_mode(insn, CCSZNmode)"
7614 +  "and.2\\t#0, %1, %0")
7615 +
7616 +(define_insn "and2_ccszn_null_3"
7617 +  [(set (reg CC_REGNO)
7618 +       (compare
7619 +         (subreg:HI
7620 +           (and:SI (subreg:SI
7621 +                     (match_operand:HI 0 "memory_operand"               "m")
7622 +                     0)
7623 +                   (match_operand:SI 1 "ubicom32_data_register_operand" "d"))
7624 +           2)
7625 +         (const_int 0)))]
7626 +  "ubicom32_match_cc_mode(insn, CCSZNmode)"
7627 +  "and.2\\t#0, %0, %1")
7628 +
7629 +(define_expand "andsi3"
7630 +  [(parallel
7631 +     [(set (match_operand:SI 0 "nonimmediate_operand" "")
7632 +          (and:SI (match_operand:SI 1 "nonimmediate_operand" "")
7633 +                  (match_operand:SI 2 "ubicom32_and_or_si3_operand" "")))
7634 +      (clobber (reg:CC CC_REGNO))])]
7635 +  ""
7636 +  "{
7637 +     do
7638 +       {
7639 +        /* Is this a bfextu?  */
7640 +        if (ubicom32_data_register_operand (operands[0], SImode)
7641 +            && CONST_INT_P (operands[2])
7642 +            && exact_log2 (INTVAL (operands[2]) + 1) != -1)
7643 +          break;
7644 +
7645 +        /* Is this a bclr?  */
7646 +        if (CONST_INT_P (operands[2])
7647 +            && exact_log2 (~INTVAL (operands[2])) != -1)
7648 +          break;
7649 +
7650 +        /* Must be an and.4  */
7651 +        if (!ubicom32_data_register_operand (operands[1], SImode))
7652 +          operands[1] = copy_to_mode_reg (SImode, operands[1]);
7653 +
7654 +        if (!ubicom32_arith_operand (operands[2], SImode))
7655 +          operands[2] = copy_to_mode_reg (SImode, operands[2]);
7656 +       }
7657 +     while (0);
7658 +   }")
7659 +
7660 +(define_insn "andsi3_bfextu"
7661 +  [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
7662 +       (and:SI (match_operand:SI 1 "nonimmediate_operand"  "%rm")
7663 +               (match_operand:SI 2 "const_int_operand"       "O")))
7664 +   (clobber (reg:CC CC_REGNO))]
7665 +  "(satisfies_constraint_O (operands[2]))"
7666 +  "*
7667 +   {
7668 +     operands[3] = GEN_INT (exact_log2 (INTVAL (operands[2]) + 1));
7669 +
7670 +     return \"bfextu\\t%0, %1, %3\";
7671 +   }")
7672 +
7673 +(define_insn "andsi3_bfextu_ccwz"
7674 +  [(set (reg CC_REGNO)
7675 +       (compare
7676 +         (and:SI (match_operand:SI 1 "nonimmediate_operand" "%rm")
7677 +                 (match_operand:SI 2 "const_int_operand"      "O"))
7678 +         (const_int 0)))
7679 +   (set (match_operand:SI 0 "ubicom32_data_register_operand"  "=d")
7680 +       (and:SI (match_dup 1)
7681 +               (match_dup 2)))]
7682 +  "(satisfies_constraint_O (operands[2])
7683 +    && ubicom32_match_cc_mode(insn, CCWZmode))"
7684 +  "*
7685 +   {
7686 +     operands[3] = GEN_INT (exact_log2 (INTVAL (operands[2]) + 1));
7687 +
7688 +     return \"bfextu\\t%0, %1, %3\";
7689 +   }")
7690 +
7691 +(define_insn "andsi3_bfextu_ccwz_null"
7692 +  [(set (reg CC_REGNO)
7693 +       (compare
7694 +         (and:SI (match_operand:SI 0 "nonimmediate_operand" "%rm")
7695 +                 (match_operand:SI 1 "const_int_operand"      "O"))
7696 +         (const_int 0)))
7697 +   (clobber (match_scratch:SI 2                                      "=d"))]
7698 +  "(satisfies_constraint_O (operands[1])
7699 +    && ubicom32_match_cc_mode(insn, CCWZmode))"
7700 +  "*
7701 +   {
7702 +     operands[3] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1));
7703 +
7704 +     return \"bfextu\\t%2, %0, %3\";
7705 +   }")
7706 +
7707 +(define_insn "andsi3_bclr"
7708 +  [(set (match_operand:SI 0 "nonimmediate_operand"           "=rm")
7709 +       (and:SI (match_operand:SI 1 "ubicom32_arith_operand" "%rmI")
7710 +               (match_operand:SI 2 "const_int_operand"         "n")))
7711 +   (clobber (reg:CC CC_REGNO))]
7712 +  "(exact_log2 (~INTVAL (operands[2])) != -1)"
7713 +  "bclr\\t%0, %1, #%D2")
7714 +
7715 +(define_insn "andsi3_and4"
7716 +  [(set (match_operand:SI 0 "nonimmediate_operand"          "=rm,rm")
7717 +       (and:SI (match_operand:SI 1 "nonimmediate_operand"    "%d,rm")
7718 +               (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d")))
7719 +   (clobber (reg:CC CC_REGNO))]
7720 +  ""
7721 +  "@
7722 +   and.4\\t%0, %2, %1
7723 +   and.4\\t%0, %1, %2")
7724 +
7725 +(define_insn "andsi3_and4_ccwzn"
7726 +  [(set (reg CC_REGNO)
7727 +       (compare
7728 +         (and:SI (match_operand:SI 1 "nonimmediate_operand"    "%d,rm")
7729 +                 (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d"))
7730 +         (const_int 0)))
7731 +   (set (match_operand:SI 0 "nonimmediate_operand"            "=rm,rm")
7732 +       (and:SI (match_dup 1)
7733 +               (match_dup 2)))]
7734 +  "ubicom32_match_cc_mode(insn, CCWZNmode)"
7735 +  "@
7736 +   and.4\\t%0, %2, %1
7737 +   and.4\\t%0, %1, %2")
7738 +
7739 +(define_insn "andsi3_and4_ccwzn_null"
7740 +  [(set (reg CC_REGNO)
7741 +       (compare
7742 +         (and:SI (match_operand:SI 0 "nonimmediate_operand"    "%d,rm")
7743 +                 (match_operand:SI 1 "ubicom32_arith_operand" "rmI, d"))
7744 +         (const_int 0)))]
7745 +  "ubicom32_match_cc_mode(insn, CCWZNmode)"
7746 +  "@
7747 +   and.4\\t#0, %1, %0
7748 +   and.4\\t#0, %0, %1")
7749 +
7750 +(define_insn "andsi3_lsr4_ccwz_null"
7751 +  [(set (reg CC_REGNO)
7752 +       (compare
7753 +         (and:SI (match_operand:SI 0 "nonimmediate_operand" "%rm")
7754 +                 (match_operand:SI 1 "const_int_operand"      "n"))
7755 +         (const_int 0)))
7756 +   (clobber (match_scratch:SI 2                                      "=d"))]
7757 +  "(exact_log2 ((~(INTVAL (operands[1]))) + 1) != -1
7758 +    && ubicom32_match_cc_mode(insn, CCWZmode))"
7759 +  "*
7760 +   {
7761 +     operands[3] = GEN_INT (exact_log2 ((~(INTVAL (operands[1]))) + 1));
7762 +
7763 +     return \"lsr.4\\t%2, %0, %3\";
7764 +   }")
7765 +
7766 +; We really would like the combiner to recognize this scenario and deal with
7767 +; it but unfortunately it tries to canonicalize zero_extract ops on MEMs
7768 +; into QImode operations and we can't match them in any useful way.
7769 +;
7770 +(define_peephole2
7771 +  [(set (match_operand:SI 0 "register_operand" "")
7772 +       (match_operand:SI 1 "const_int_operand" ""))
7773 +   (set (reg:CCWZ CC_REGNO)
7774 +       (compare:CCWZ
7775 +         (and:SI (match_operand:SI 2 "nonimmediate_operand" "")
7776 +                 (match_dup 0))
7777 +         (const_int 0)))]
7778 +  "(exact_log2 (INTVAL (operands[1])) != -1
7779 +    && peep2_reg_dead_p (2, operands[0]))"
7780 +  [(set (reg:CCWZ CC_REGNO)
7781 +       (compare:CCWZ
7782 +         (zero_extract:SI
7783 +           (match_dup 2)
7784 +           (const_int 1)
7785 +           (match_dup 3))
7786 +         (const_int 0)))]
7787 +  "{
7788 +     operands[3] = GEN_INT (exact_log2 (INTVAL (operands[1])));
7789 +   }")
7790 +
7791 +(define_expand "anddi3"
7792 +  [(parallel
7793 +     [(set (match_operand:DI 0 "nonimmediate_operand" "")
7794 +          (and:DI (match_operand:DI 1 "nonimmediate_operand" "")
7795 +                  (match_operand:DI 2 "ubicom32_arith_operand" "")))
7796 +      (clobber (reg:CC CC_REGNO))])]
7797 +  ""
7798 +  "{
7799 +     /* If we have a non-data reg for operand 1 then prefer that over
7800 +        a CONST_INT in operand 2.  */
7801 +     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
7802 +        && CONST_INT_P (operands[2]))
7803 +       operands[2] = copy_to_mode_reg (DImode, operands[2]);
7804 +
7805 +     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
7806 +       operands[2] = copy_to_mode_reg (DImode, operands[2]);
7807 +   }")
7808 +
7809 +(define_insn_and_split "anddi3_and4"
7810 +  [(set (match_operand:DI 0 "nonimmediate_operand"          "=&r,&r,  d,rm,  m, m")
7811 +       (and:DI (match_operand:DI 1 "nonimmediate_operand"    "%d,rm,  0, 0,  d,rm")
7812 +               (match_operand:DI 2 "ubicom32_arith_operand" "rmI, d,rmI, d,rmI, d")))
7813 +   (clobber (reg:CC CC_REGNO))]
7814 +  ""
7815 +  "#"
7816 +  "reload_completed"
7817 +  [(parallel [(set (match_dup 3)
7818 +                  (and:SI (match_dup 4)
7819 +                          (match_dup 5)))
7820 +             (clobber (reg:CC CC_REGNO))])
7821 +   (parallel [(set (match_dup 6)
7822 +                  (and:SI (match_dup 7)
7823 +                          (match_dup 8)))
7824 +             (clobber (reg:CC CC_REGNO))])]
7825 +  "{
7826 +     operands[3] = gen_lowpart (SImode, operands[0]);
7827 +     operands[4] = gen_lowpart (SImode, operands[1]);
7828 +     operands[5] = gen_lowpart (SImode, operands[2]);
7829 +     operands[6] = gen_highpart (SImode, operands[0]);
7830 +     operands[7] = gen_highpart (SImode, operands[1]);
7831 +     operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
7832 +   }"
7833 +  [(set_attr "length" "8")])
7834 +
7835 +(define_expand "iorqi3"
7836 +  [(parallel
7837 +     [(set (match_operand:QI 0 "memory_operand" "")
7838 +          (ior:QI (match_operand:QI 1 "nonimmediate_operand" "")
7839 +                  (match_operand:QI 2 "ubicom32_arith_operand" "")))
7840 +      (clobber (reg:CC CC_REGNO))])]
7841 +  "(ubicom32_v4)"
7842 +  "{
7843 +     if (!memory_operand (operands[0], QImode))
7844 +       FAIL;
7845 +
7846 +     /* If we have a non-data reg for operand 1 then prefer that over
7847 +        a CONST_INT in operand 2.  */
7848 +     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
7849 +        && CONST_INT_P (operands[2]))
7850 +       operands[2] = copy_to_mode_reg (QImode, operands[2]);
7851 +
7852 +     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
7853 +       operands[2] = copy_to_mode_reg (QImode, operands[2]);
7854 +   }")
7855 +
7856 +(define_insn "iorqi3_or1"
7857 +  [(set (match_operand:QI 0 "memory_operand"                 "=m, m")
7858 +       (ior:QI (match_operand:QI 1 "nonimmediate_operand"    "%d,rm")
7859 +               (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d")))
7860 +   (clobber (reg:CC CC_REGNO))]
7861 +  "(ubicom32_v4)"
7862 +  "@
7863 +   or.1\\t%0, %2, %1
7864 +   or.1\\t%0, %1, %2")
7865 +
7866 +(define_expand "iorhi3"
7867 +  [(parallel
7868 +     [(set (match_operand:HI 0 "memory_operand" "")
7869 +          (ior:HI (match_operand:HI 1 "nonimmediate_operand" "")
7870 +                  (match_operand:HI 2 "ubicom32_arith_operand" "")))
7871 +      (clobber (reg:CC CC_REGNO))])]
7872 +  ""
7873 +  "{
7874 +     if (!memory_operand (operands[0], HImode))
7875 +       FAIL;
7876 +
7877 +     /* If we have a non-data reg for operand 1 then prefer that over
7878 +        a CONST_INT in operand 2.  */
7879 +     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
7880 +        && CONST_INT_P (operands[2]))
7881 +       operands[2] = copy_to_mode_reg (HImode, operands[2]);
7882 +
7883 +     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
7884 +       operands[2] = copy_to_mode_reg (HImode, operands[2]);
7885 +   }")
7886 +
7887 +(define_insn "iorhi3_or2"
7888 +  [(set (match_operand:HI 0 "memory_operand"                 "=m, m")
7889 +       (ior:HI (match_operand:HI 1 "nonimmediate_operand"    "%d,rm")
7890 +               (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d")))
7891 +   (clobber (reg:CC CC_REGNO))]
7892 +  ""
7893 +  "@
7894 +   or.2\\t%0, %2, %1
7895 +   or.2\\t%0, %1, %2")
7896 +
7897 +(define_expand "iorsi3"
7898 +  [(parallel
7899 +     [(set (match_operand:SI 0 "nonimmediate_operand" "")
7900 +          (ior:SI (match_operand:SI 1 "nonimmediate_operand" "")
7901 +                  (match_operand:SI 2 "ubicom32_and_or_si3_operand" "")))
7902 +      (clobber (reg:CC CC_REGNO))])]
7903 +  ""
7904 +  "{
7905 +     do
7906 +       {
7907 +        /* Is this a bset?  */
7908 +        if (CONST_INT_P (operands[2])
7909 +            && exact_log2 (INTVAL (operands[2])) != -1)
7910 +          break;
7911 +
7912 +        /* Must be an or.4  */
7913 +        if (!ubicom32_data_register_operand (operands[1], SImode))
7914 +          operands[1] = copy_to_mode_reg (SImode, operands[1]);
7915 +
7916 +        if (!ubicom32_arith_operand (operands[2], SImode))
7917 +          operands[2] = copy_to_mode_reg (SImode, operands[2]);
7918 +       } 
7919 +     while (0);
7920 +   }")
7921 +
7922 +(define_insn "iorsi3_bset"
7923 +  [(set (match_operand:SI 0 "nonimmediate_operand"           "=rm")
7924 +       (ior:SI (match_operand:SI 1 "ubicom32_arith_operand" "%rmI")
7925 +               (match_operand 2 "const_int_operand"            "n")))
7926 +   (clobber (reg:CC CC_REGNO))]
7927 +  "(exact_log2 (INTVAL (operands[2])) != -1)"
7928 +  "bset\\t%0, %1, #%d2")
7929 +
7930 +(define_insn "iorsi3_or4"
7931 +  [(set (match_operand:SI 0 "nonimmediate_operand"          "=rm,rm")
7932 +       (ior:SI (match_operand:SI 1 "nonimmediate_operand"    "%d,rm")
7933 +               (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d")))
7934 +   (clobber (reg:CC CC_REGNO))]
7935 +  ""
7936 +  "@
7937 +   or.4\\t%0, %2, %1
7938 +   or.4\\t%0, %1, %2")
7939 +
7940 +(define_insn "iorsi3_ccwzn"
7941 +  [(set (reg CC_REGNO)
7942 +       (compare
7943 +         (ior:SI (match_operand:SI 1 "nonimmediate_operand"    "%d,rm")
7944 +                 (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d"))
7945 +         (const_int 0)))
7946 +   (set (match_operand:SI 0 "nonimmediate_operand"            "=rm,rm")
7947 +       (ior:SI (match_dup 1)
7948 +               (match_dup 2)))]
7949 +  "ubicom32_match_cc_mode(insn, CCWZNmode)"
7950 +  "@
7951 +   or.4\\t%0, %2, %1
7952 +   or.4\\t%0, %1, %2")
7953 +
7954 +(define_insn "iorsi3_ccwzn_null"
7955 +  [(set (reg CC_REGNO)
7956 +       (compare
7957 +         (ior:SI (match_operand:SI 0 "nonimmediate_operand"    "%d,rm")
7958 +                 (match_operand:SI 1 "ubicom32_arith_operand" "rmI, d"))
7959 +         (const_int 0)))]
7960 +  "ubicom32_match_cc_mode(insn, CCWZNmode)"
7961 +  "@
7962 +   or.4\\t#0, %1, %0
7963 +   or.4\\t#0, %0, %1")
7964 +
7965 +(define_expand "iordi3"
7966 +  [(parallel
7967 +     [(set (match_operand:DI 0 "nonimmediate_operand" "")
7968 +          (ior:DI (match_operand:DI 1 "nonimmediate_operand" "")
7969 +                  (match_operand:DI 2 "ubicom32_arith_operand" "")))
7970 +      (clobber (reg:CC CC_REGNO))])]
7971 +  ""
7972 +  "{
7973 +     /* If we have a non-data reg for operand 1 then prefer that over
7974 +        a CONST_INT in operand 2.  */
7975 +     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
7976 +        && CONST_INT_P (operands[2]))
7977 +       operands[2] = copy_to_mode_reg (DImode, operands[2]);
7978 +
7979 +     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
7980 +       operands[2] = copy_to_mode_reg (DImode, operands[2]);
7981 +   }")
7982 +
7983 +(define_insn_and_split "iordi3_or4"
7984 +  [(set (match_operand:DI 0 "nonimmediate_operand"          "=&r,&r,  d,rm,  m, m")
7985 +       (ior:DI (match_operand:DI 1 "nonimmediate_operand"    "%d,rm,  0, 0,  d,rm")
7986 +               (match_operand:DI 2 "ubicom32_arith_operand" "rmI, d,rmI, d,rmI, d")))
7987 +   (clobber (reg:CC CC_REGNO))]
7988 +  ""
7989 +  "#"
7990 +  "reload_completed"
7991 +  [(parallel [(set (match_dup 3)
7992 +                  (ior:SI (match_dup 4)
7993 +                          (match_dup 5)))
7994 +             (clobber (reg:CC CC_REGNO))])
7995 +   (parallel [(set (match_dup 6)
7996 +                  (ior:SI (match_dup 7)
7997 +                          (match_dup 8)))
7998 +             (clobber (reg:CC CC_REGNO))])]
7999 +  "{
8000 +     operands[3] = gen_lowpart (SImode, operands[0]);
8001 +     operands[4] = gen_lowpart (SImode, operands[1]);
8002 +     operands[5] = gen_lowpart (SImode, operands[2]);
8003 +     operands[6] = gen_highpart (SImode, operands[0]);
8004 +     operands[7] = gen_highpart (SImode, operands[1]);
8005 +     operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
8006 +   }"
8007 +  [(set_attr "length" "8")])
8008 +
8009 +(define_expand "xorqi3"
8010 +  [(parallel
8011 +     [(set (match_operand:QI 0 "memory_operand" "")
8012 +          (xor:QI (match_operand:QI 1 "nonimmediate_operand" "")
8013 +                  (match_operand:QI 2 "ubicom32_arith_operand" "")))
8014 +      (clobber (reg:CC CC_REGNO))])]
8015 +  "(ubicom32_v4)"
8016 +  "{
8017 +     if (!memory_operand (operands[0], QImode))
8018 +       FAIL;
8019 +
8020 +     /* If we have a non-data reg for operand 1 then prefer that over
8021 +        a CONST_INT in operand 2.  */
8022 +     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
8023 +        && CONST_INT_P (operands[2]))
8024 +       operands[2] = copy_to_mode_reg (QImode, operands[2]);
8025 +
8026 +     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
8027 +       operands[2] = copy_to_mode_reg (QImode, operands[2]);
8028 +   }")
8029 +
8030 +(define_insn "xorqi3_xor1"
8031 +  [(set (match_operand:QI 0 "memory_operand"                 "=m, m")
8032 +       (xor:QI (match_operand:QI 1 "nonimmediate_operand"    "%d,rm")
8033 +               (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d")))
8034 +   (clobber (reg:CC CC_REGNO))]
8035 +  "(ubicom32_v4)"
8036 +  "@
8037 +   xor.1\\t%0, %2, %1
8038 +   xor.1\\t%0, %1, %2")
8039 +
8040 +(define_insn "xorqi3_xor1_ccszn"
8041 +  [(set (reg CC_REGNO)
8042 +       (compare
8043 +         (xor:QI (match_operand:QI 1 "nonimmediate_operand"    "%d,rm")
8044 +                 (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d"))
8045 +         (const_int 0)))
8046 +   (set (match_operand:QI 0 "memory_operand"                   "=m, m")
8047 +       (xor:QI (match_dup 1)
8048 +               (match_dup 2)))]
8049 +  "(ubicom32_v4
8050 +    && ubicom32_match_cc_mode(insn, CCSZNmode))"
8051 +  "@
8052 +   xor.1\\t%0, %2, %1
8053 +   xor.1\\t%0, %1, %2")
8054 +
8055 +(define_insn "xorqi3_xor1_ccszn_null"
8056 +  [(set (reg CC_REGNO)
8057 +       (compare
8058 +         (xor:QI (match_operand:QI 0 "nonimmediate_operand"    "%d,rm")
8059 +                 (match_operand:QI 1 "ubicom32_arith_operand" "rmI, d"))
8060 +         (const_int 0)))]
8061 +  "(ubicom32_v4
8062 +    && ubicom32_match_cc_mode(insn, CCSZNmode))"
8063 +  "@
8064 +   xor.1\\t#0, %1, %0
8065 +   xor.1\\t#0, %0, %1")
8066 +
8067 +(define_insn "xor1_ccszn_null_1"
8068 +  [(set (reg CC_REGNO)
8069 +       (compare
8070 +         (subreg:QI
8071 +           (xor:SI (match_operand:SI 0 "ubicom32_data_register_operand" "%d")
8072 +                   (match_operand:SI 1 "ubicom32_arith_operand"         "rI"))
8073 +           3)
8074 +         (const_int 0)))]
8075 +  "(ubicom32_v4
8076 +    && ubicom32_match_cc_mode(insn, CCSZNmode))"
8077 +  "xor.1\\t#0, %1, %0")
8078 +
8079 +(define_insn "xor1_ccszn_null_2"
8080 +  [(set (reg CC_REGNO)
8081 +       (compare
8082 +         (subreg:QI
8083 +           (xor:SI (match_operand:SI 0 "ubicom32_data_register_operand" "d")
8084 +                   (subreg:SI
8085 +                     (match_operand:QI 1 "memory_operand"               "m")
8086 +                     0))
8087 +           3)
8088 +         (const_int 0)))]
8089 +  "(ubicom32_v4
8090 +    && ubicom32_match_cc_mode(insn, CCSZNmode))"
8091 +  "xor.1\\t#0, %1, %0")
8092 +
8093 +(define_insn "xor1_ccwzn_null_3"
8094 +  [(set (reg CC_REGNO)
8095 +       (compare
8096 +         (subreg:QI
8097 +           (xor:SI (subreg:SI
8098 +                     (match_operand:QI 0 "memory_operand"               "m")
8099 +                     0)
8100 +                   (match_operand:SI 1 "ubicom32_data_register_operand" "d"))
8101 +           3)
8102 +         (const_int 0)))]
8103 +  "(ubicom32_v4
8104 +    && ubicom32_match_cc_mode(insn, CCSZNmode))"
8105 +  "xor.1\\t#0, %0, %1")
8106 +
8107 +(define_expand "xorhi3"
8108 +  [(parallel
8109 +     [(set (match_operand:HI 0 "memory_operand" "")
8110 +          (xor:HI (match_operand:HI 1 "nonimmediate_operand" "")
8111 +                  (match_operand:HI 2 "ubicom32_arith_operand" "")))
8112 +      (clobber (reg:CC CC_REGNO))])]
8113 +  ""
8114 +  "{
8115 +     if (!memory_operand (operands[0], HImode))
8116 +       FAIL;
8117 +
8118 +     /* If we have a non-data reg for operand 1 then prefer that over
8119 +        a CONST_INT in operand 2.  */
8120 +     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
8121 +        && CONST_INT_P (operands[2]))
8122 +       operands[2] = copy_to_mode_reg (HImode, operands[2]);
8123 +
8124 +     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
8125 +       operands[2] = copy_to_mode_reg (HImode, operands[2]);
8126 +   }")
8127 +
8128 +(define_insn "xorhi3_xor2"
8129 +  [(set (match_operand:HI 0 "memory_operand"                 "=m, m")
8130 +       (xor:HI (match_operand:HI 1 "nonimmediate_operand"    "%d,rm")
8131 +               (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d")))
8132 +   (clobber (reg:CC CC_REGNO))]
8133 +  ""
8134 +  "@
8135 +   xor.2\\t%0, %2, %1
8136 +   xor.2\\t%0, %1, %2")
8137 +
8138 +(define_insn "xorhi3_xor2_ccszn"
8139 +  [(set (reg CC_REGNO)
8140 +       (compare
8141 +         (xor:HI (match_operand:HI 1 "nonimmediate_operand"    "%d,rm")
8142 +                 (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d"))
8143 +         (const_int 0)))
8144 +   (set (match_operand:HI 0 "memory_operand"                   "=m, m")
8145 +       (xor:HI (match_dup 1)
8146 +               (match_dup 2)))]
8147 +  "ubicom32_match_cc_mode(insn, CCSZNmode)"
8148 +  "@
8149 +   xor.2\\t%0, %2, %1
8150 +   xor.2\\t%0, %1, %2")
8151 +
8152 +(define_insn "xorhi3_xor2_ccszn_null"
8153 +  [(set (reg CC_REGNO)
8154 +       (compare
8155 +         (xor:HI (match_operand:HI 0 "nonimmediate_operand"    "%d,rm")
8156 +                 (match_operand:HI 1 "ubicom32_arith_operand" "rmI, d"))
8157 +         (const_int 0)))]
8158 +  "ubicom32_match_cc_mode(insn, CCSZNmode)"
8159 +  "@
8160 +   xor.2\\t#0, %1, %0
8161 +   xor.2\\t#0, %0, %1")
8162 +
8163 +(define_insn "xor2_ccszn_null_1"
8164 +  [(set (reg CC_REGNO)
8165 +       (compare
8166 +         (subreg:HI
8167 +           (xor:SI (match_operand:SI 0 "ubicom32_data_register_operand" "%d")
8168 +                   (match_operand:SI 1 "ubicom32_arith_operand"         "rI"))
8169 +           2)
8170 +         (const_int 0)))]
8171 +  "ubicom32_match_cc_mode(insn, CCSZNmode)"
8172 +  "xor.2\\t#0, %1, %0")
8173 +
8174 +(define_insn "xor2_ccszn_null_2"
8175 +  [(set (reg CC_REGNO)
8176 +       (compare
8177 +         (subreg:HI
8178 +           (xor:SI (match_operand:SI 0 "ubicom32_data_register_operand" "d")
8179 +                   (subreg:SI
8180 +                     (match_operand:HI 1 "memory_operand"               "m")
8181 +                     0))
8182 +           2)
8183 +         (const_int 0)))]
8184 +  "ubicom32_match_cc_mode(insn, CCSZNmode)"
8185 +  "xor.2\\t#0, %1, %0")
8186 +
8187 +(define_insn "xor2_ccszn_null_3"
8188 +  [(set (reg CC_REGNO)
8189 +       (compare
8190 +         (subreg:HI
8191 +           (xor:SI (subreg:SI
8192 +                     (match_operand:HI 0 "memory_operand"               "m")
8193 +                     0)
8194 +                   (match_operand:SI 1 "ubicom32_data_register_operand" "d"))
8195 +           2)
8196 +         (const_int 0)))]
8197 +  "ubicom32_match_cc_mode(insn, CCSZNmode)"
8198 +  "xor.2\\t#0, %0, %1")
8199 +
8200 +(define_insn "xorsi3"
8201 +  [(set (match_operand:SI 0 "nonimmediate_operand"          "=rm,rm")
8202 +       (xor:SI (match_operand:SI 1 "nonimmediate_operand"    "%d,rm")
8203 +               (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d")))
8204 +   (clobber (reg:CC CC_REGNO))]
8205 +  ""
8206 +  "@
8207 +   xor.4\\t%0, %2, %1
8208 +   xor.4\\t%0, %1, %2")
8209 +
8210 +(define_insn "xorsi3_ccwzn"
8211 +  [(set (reg CC_REGNO)
8212 +       (compare
8213 +         (xor:SI (match_operand:SI 1 "nonimmediate_operand"    "%d,rm")
8214 +                 (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d"))
8215 +         (const_int 0)))
8216 +   (set (match_operand:SI 0 "nonimmediate_operand"            "=rm,rm")
8217 +       (xor:SI (match_dup 1)
8218 +               (match_dup 2)))]
8219 +  "ubicom32_match_cc_mode(insn, CCWZNmode)"
8220 +  "@
8221 +   xor.4\\t%0, %2, %1
8222 +   xor.4\\t%0, %1, %2")
8223 +
8224 +(define_insn "xorsi3_ccwzn_null"
8225 +  [(set (reg CC_REGNO)
8226 +       (compare
8227 +         (xor:SI (match_operand:SI 0 "nonimmediate_operand"    "%d,rm")
8228 +                 (match_operand:SI 1 "ubicom32_arith_operand" "rmI, d"))
8229 +         (const_int 0)))]
8230 +  "ubicom32_match_cc_mode(insn, CCWZNmode)"
8231 +  "@
8232 +   xor.4\\t#0, %1, %0
8233 +   xor.4\\t#0, %0, %1")
8234 +
8235 +(define_expand "xordi3"
8236 +  [(parallel
8237 +     [(set (match_operand:DI 0 "nonimmediate_operand" "")
8238 +          (xor:DI (match_operand:DI 1 "nonimmediate_operand" "")
8239 +                  (match_operand:DI 2 "ubicom32_arith_operand" "")))
8240 +      (clobber (reg:CC CC_REGNO))])]
8241 +  ""
8242 +  "{
8243 +     /* If we have a non-data reg for operand 1 then prefer that over
8244 +        a CONST_INT in operand 2.  */
8245 +     if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
8246 +        && CONST_INT_P (operands[2]))
8247 +       operands[2] = copy_to_mode_reg (DImode, operands[2]);
8248 +
8249 +     if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
8250 +       operands[2] = copy_to_mode_reg (DImode, operands[2]);
8251 +   }")
8252 +
8253 +(define_insn_and_split "xordi3_xor4"
8254 +  [(set (match_operand:DI 0 "nonimmediate_operand"          "=&r,&r,  d,rm,  m, m")
8255 +       (xor:DI (match_operand:DI 1 "nonimmediate_operand"    "%d,rm,  0, 0,  d,rm")
8256 +               (match_operand:DI 2 "ubicom32_arith_operand" "rmI, d,rmI, d,rmI, d")))
8257 +   (clobber (reg:CC CC_REGNO))]
8258 +  ""
8259 +  "#"
8260 +  "reload_completed"
8261 +  [(parallel [(set (match_dup 3)
8262 +                  (xor:SI (match_dup 4)
8263 +                          (match_dup 5)))
8264 +             (clobber (reg:CC CC_REGNO))])
8265 +   (parallel [(set (match_dup 6)
8266 +                  (xor:SI (match_dup 7)
8267 +                          (match_dup 8)))
8268 +             (clobber (reg:CC CC_REGNO))])]
8269 +  "{
8270 +     operands[3] = gen_lowpart (SImode, operands[0]);
8271 +     operands[4] = gen_lowpart (SImode, operands[1]);
8272 +     operands[5] = gen_lowpart (SImode, operands[2]);
8273 +     operands[6] = gen_highpart (SImode, operands[0]);
8274 +     operands[7] = gen_highpart (SImode, operands[1]);
8275 +     operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
8276 +   }"
8277 +  [(set_attr "length" "8")])
8278 +
8279 +(define_insn "not2_2"
8280 +  [(set (match_operand:HI 0 "memory_operand"                   "=m")
8281 +       (subreg:HI
8282 +         (not:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI"))
8283 +         2))
8284 +   (clobber (reg:CC CC_REGNO))]
8285 +  ""
8286 +  "not.2\\t%0, %1")
8287 +
8288 +(define_insn "one_cmplsi2"
8289 +  [(set (match_operand:SI 0 "nonimmediate_operand"          "=rm")
8290 +       (not:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")))
8291 +   (clobber (reg:CC CC_REGNO))]
8292 +  ""
8293 +  "not.4\\t%0, %1")
8294 +
8295 +(define_insn "one_cmplsi2_ccwzn"
8296 +  [(set (reg CC_REGNO)
8297 +       (compare
8298 +         (not:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI"))
8299 +         (const_int 0)))
8300 +   (set (match_operand:SI 0 "nonimmediate_operand"            "=rm")
8301 +       (not:SI (match_dup 1)))]
8302 +  "ubicom32_match_cc_mode(insn, CCWZNmode)"
8303 +  "not.4\\t%0, %1")
8304 +
8305 +(define_insn "one_cmplsi2_ccwzn_null"
8306 +  [(set (reg CC_REGNO)
8307 +       (compare
8308 +         (not:SI (match_operand:SI 0 "ubicom32_arith_operand" "rmI"))
8309 +         (const_int 0)))]
8310 +  "ubicom32_match_cc_mode(insn, CCWZNmode)"
8311 +  "not.4\\t#0, %0")
8312 +
8313 +(define_insn_and_split "one_cmpldi2"
8314 +  [(set (match_operand:DI 0 "nonimmediate_operand"        "=&rm")
8315 +       (not:DI (match_operand:DI 1 "nonimmediate_operand" "rmI0")))
8316 +   (clobber (reg:CC CC_REGNO))]
8317 +  ""
8318 +  "#"
8319 +  ""
8320 +  [(parallel [(set (match_dup 2)
8321 +                  (not:SI (match_dup 3)))
8322 +             (clobber (reg:CC CC_REGNO))])
8323 +   (parallel [(set (match_dup 4)
8324 +                  (not:SI (match_dup 5)))
8325 +             (clobber (reg:CC CC_REGNO))])]
8326 +  "{
8327 +     operands[2] = gen_lowpart (SImode, operands[0]);
8328 +     operands[3] = gen_lowpart (SImode, operands[1]);
8329 +     operands[4] = gen_highpart (SImode, operands[0]);
8330 +     operands[5] = gen_highpart (SImode, operands[1]);
8331 +   }"
8332 +  [(set_attr "length" "8")])
8333 +
8334 +; Conditional jump instructions
8335 +
8336 +(define_expand "beq"
8337 +  [(set (pc)
8338 +       (if_then_else (eq (match_dup 1)
8339 +                         (const_int 0))
8340 +                     (label_ref (match_operand 0 "" ""))
8341 +                     (pc)))]
8342 +  ""
8343 +  "{
8344 +     operands[1] = ubicom32_gen_compare_reg (EQ, ubicom32_compare_op0,
8345 +                                            ubicom32_compare_op1);
8346 +   }")
8347 +
8348 +(define_expand "bne"
8349 +  [(set (pc)
8350 +       (if_then_else (ne (match_dup 1)
8351 +                         (const_int 0))
8352 +                     (label_ref (match_operand 0 "" ""))
8353 +                     (pc)))]
8354 +  ""
8355 +  "{
8356 +     operands[1] = ubicom32_gen_compare_reg (NE, ubicom32_compare_op0,
8357 +                                            ubicom32_compare_op1);
8358 +   }")
8359 +
8360 +(define_expand "bgt"
8361 +  [(set (pc)
8362 +       (if_then_else (gt (match_dup 1)
8363 +                         (const_int 0))
8364 +                     (label_ref (match_operand 0 "" ""))
8365 +                     (pc)))]
8366 +  ""
8367 +  "{
8368 +     operands[1] = ubicom32_gen_compare_reg (GT, ubicom32_compare_op0,
8369 +                                            ubicom32_compare_op1);
8370 +   }")
8371 +
8372 +(define_expand "ble"
8373 +  [(set (pc)
8374 +       (if_then_else (le (match_dup 1)
8375 +                         (const_int 0))
8376 +                     (label_ref (match_operand 0 "" ""))
8377 +                     (pc)))]
8378 +  ""
8379 +  "{
8380 +     operands[1] = ubicom32_gen_compare_reg (LE, ubicom32_compare_op0,
8381 +                                            ubicom32_compare_op1);
8382 +   }")
8383 +
8384 +(define_expand "bge"
8385 +  [(set (pc)
8386 +       (if_then_else (ge (match_dup 1)
8387 +                         (const_int 0))
8388 +                     (label_ref (match_operand 0 "" ""))
8389 +                     (pc)))]
8390 +  ""
8391 +  "{
8392 +     operands[1] = ubicom32_gen_compare_reg (GE, ubicom32_compare_op0,
8393 +                                            ubicom32_compare_op1);
8394 +   }")
8395 +
8396 +(define_expand "blt"
8397 +  [(set (pc)
8398 +       (if_then_else (lt (match_dup 1)
8399 +                         (const_int 0))
8400 +                     (label_ref (match_operand 0 "" ""))
8401 +                     (pc)))]
8402 +  ""
8403 +  "{
8404 +     operands[1] = ubicom32_gen_compare_reg (LT, ubicom32_compare_op0,
8405 +                                            ubicom32_compare_op1);
8406 +   }")
8407 +
8408 +(define_expand "bgtu"
8409 +  [(set (pc)
8410 +       (if_then_else (gtu (match_dup 1)
8411 +                          (const_int 0))
8412 +                     (label_ref (match_operand 0 "" ""))
8413 +                     (pc)))]
8414 +  ""
8415 +  "{
8416 +     operands[1] = ubicom32_gen_compare_reg (GTU, ubicom32_compare_op0,
8417 +                                            ubicom32_compare_op1);
8418 +   }")
8419 +
8420 +(define_expand "bleu"
8421 +  [(set (pc)
8422 +       (if_then_else (leu (match_dup 1)
8423 +                          (const_int 0))
8424 +                     (label_ref (match_operand 0 "" ""))
8425 +                     (pc)))]
8426 +  ""
8427 +  "{
8428 +     operands[1] = ubicom32_gen_compare_reg (LEU, ubicom32_compare_op0,
8429 +                                            ubicom32_compare_op1);
8430 +   }")
8431 +
8432 +(define_expand "bgeu"
8433 +  [(set (pc)
8434 +       (if_then_else (geu (match_dup 1)
8435 +                          (const_int 0))
8436 +                     (label_ref (match_operand 0 "" ""))
8437 +                     (pc)))]
8438 +  ""
8439 +  "{
8440 +     operands[1] = ubicom32_gen_compare_reg (GEU, ubicom32_compare_op0,
8441 +                                            ubicom32_compare_op1);
8442 +   }")
8443 +
8444 +(define_expand "bltu"
8445 +  [(set (pc)
8446 +       (if_then_else (ltu (match_dup 1)
8447 +                          (const_int 0))
8448 +                     (label_ref (match_operand 0 "" ""))
8449 +                     (pc)))]
8450 +  ""
8451 +  "{
8452 +     operands[1] = ubicom32_gen_compare_reg (LTU, ubicom32_compare_op0,
8453 +                                            ubicom32_compare_op1);
8454 +   }")
8455 +
8456 +(define_insn "jcc"
8457 +  [(set (pc)
8458 +       (if_then_else (match_operator 1 "comparison_operator"
8459 +                       [(match_operand 2 "ubicom32_cc_register_operand" "")
8460 +                        (const_int 0)])
8461 +                     (label_ref (match_operand 0 "" ""))
8462 +                     (pc)))]
8463 +  ""
8464 +  "*
8465 +   {
8466 +     ubicom32_output_cond_jump (insn, operands[1], operands[0]);
8467 +     return \"\";
8468 +   }")
8469 +
8470 +; Reverse branch - reverse our comparison condition so that we can
8471 +; branch in the opposite sense.
8472 +;
8473 +(define_insn_and_split "jcc_reverse"
8474 +  [(set (pc)
8475 +       (if_then_else (match_operator 1 "comparison_operator"
8476 +                       [(match_operand 2 "ubicom32_cc_register_operand" "")
8477 +                        (const_int 0)])
8478 +                     (pc)
8479 +                     (label_ref (match_operand 0 "" ""))))]
8480 +  ""
8481 +  "#"
8482 +  "reload_completed"
8483 +  [(set (pc)
8484 +       (if_then_else (match_dup 3)
8485 +                     (label_ref (match_dup 0))
8486 +                     (pc)))]
8487 +  "{
8488 +     rtx cc_reg;
8489 +
8490 +     cc_reg = gen_rtx_REG (GET_MODE (operands[2]), CC_REGNO);
8491 +     operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[1])),
8492 +                                  GET_MODE (operands[1]),
8493 +                                  cc_reg,
8494 +                                  const0_rtx);
8495 +   }")
8496 +
8497 +(define_insn "jump"
8498 +  [(set (pc)
8499 +       (label_ref (match_operand 0 "" "")))]
8500 +  ""
8501 +  "jmpt\\t%l0")
8502 +
8503 +(define_expand "indirect_jump"
8504 +  [(parallel [(set (pc)
8505 +                  (match_operand:SI 0 "register_operand" ""))
8506 +             (clobber (match_dup 0))])]
8507 +  ""
8508 +  "")
8509 +
8510 +(define_insn "indirect_jump_internal"
8511 +  [(set (pc)
8512 +       (match_operand:SI 0 "register_operand" "a"))
8513 +  (clobber (match_dup 0))]
8514 +  ""
8515 +  "calli\\t%0,0(%0)")
8516 +
8517 +; Program Space: The table contains instructions, typically jumps. 
8518 +; CALL An,TABLE_SIZE(PC)       ;An = Jump Table Base Address. 
8519 +; <Jump Table is Here> ;An -> Here. 
8520 +; LEA Ak, (An,Dn)      ;Ak -> Table Entry
8521 +; JMP/CALL (Ak) 
8522 +
8523 +(define_expand "tablejump"
8524 +  [(parallel [(set (pc)
8525 +                  (match_operand:SI 0 "nonimmediate_operand" ""))
8526 +             (use (label_ref (match_operand 1 "" "")))])]
8527 +  ""
8528 +  "")
8529 +
8530 +(define_insn "tablejump_internal"
8531 +  [(set (pc)
8532 +       (match_operand:SI 0 "nonimmediate_operand" "rm"))
8533 +   (use (label_ref (match_operand 1 "" "")))]
8534 +  ""
8535 +  "ret\\t%0")
8536 +
8537 +; Call subroutine with no return value.
8538 +;
8539 +(define_expand "call"
8540 +  [(call (match_operand:QI 0 "general_operand" "")
8541 +        (match_operand:SI 1 "general_operand" ""))]
8542 +  ""
8543 +  "{
8544 +     if (TARGET_FDPIC)
8545 +       {
8546 +        ubicom32_expand_call_fdpic (operands);
8547 +        DONE;
8548 +       }
8549 +
8550 +     if (! ubicom32_call_address_operand (XEXP (operands[0], 0), VOIDmode))
8551 +       XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
8552 +   }")
8553 +
8554 +; We expand to a simple form that doesn't clobber the link register and
8555 +; then split to a form that does.  This allows the RTL optimizers that
8556 +; run before the splitter to have the opportunity to eliminate the call
8557 +; without marking A5 as being clobbered and this in turn avoids saves
8558 +; and returns in a number of cases.
8559 +;
8560 +(define_insn_and_split "call_1"
8561 +  [(call (mem:QI (match_operand:SI 0 "ubicom32_call_address_operand" "a,S"))
8562 +        (match_operand:SI 1 "general_operand"                       "g,g"))]
8563 +  "! TARGET_FDPIC"
8564 +  "#"
8565 +  ""
8566 +  [(parallel
8567 +     [(call (mem:QI (match_dup 0))
8568 +           (match_dup 1))
8569 +      (clobber (reg:SI LINK_REGNO))])]
8570 +  "")
8571 +
8572 +(define_insn "call_slow"
8573 +  [(call (mem:QI (match_operand:SI 0 "ubicom32_call_address_operand" "a,S"))
8574 +        (match_operand:SI 1 "general_operand"                       "g,g"))
8575 +   (clobber (reg:SI LINK_REGNO))]
8576 +  "(! TARGET_FDPIC && ! TARGET_FASTCALL)"
8577 +  "@
8578 +   calli\\ta5, 0(%0)
8579 +   moveai\\ta5, #%%hi(%C0)\;calli\\ta5, %%lo(%C0)(a5)")
8580 +
8581 +(define_insn "call_fast"
8582 +  [(call (mem:QI (match_operand:SI 0 "ubicom32_call_address_operand" "a,S"))
8583 +        (match_operand:SI 1 "general_operand"                       "g,g"))
8584 +   (clobber (reg:SI LINK_REGNO))]
8585 +  "(! TARGET_FDPIC && TARGET_FASTCALL)"
8586 +  "@
8587 +   calli\\ta5, 0(%0)
8588 +   call\\ta5, %C0")
8589 +
8590 +; We expand to a simple form that doesn't clobber the link register and
8591 +; then split to a form that does.  This allows the RTL optimizers that
8592 +; run before the splitter to have the opportunity to eliminate the call
8593 +; without marking A5 as being clobbered and this in turn avoids saves
8594 +; and returns in a number of cases.
8595 +;
8596 +(define_insn_and_split "call_fdpic"
8597 +  [(call (mem:QI (match_operand:SI 0 "ubicom32_call_address_operand" "a,S"))
8598 +        (match_operand:SI 1 "general_operand"                       "g,g"))
8599 +   (use (match_operand:SI 2 "ubicom32_fdpic_operand"                "Z,Z"))]
8600 +  "TARGET_FDPIC"
8601 +  "#"
8602 +  ""
8603 +  [(parallel
8604 +     [(call (mem:QI (match_dup 0))
8605 +           (match_dup 1))
8606 +      (use (match_dup 2))
8607 +      (clobber (reg:SI LINK_REGNO))])]
8608 +  "")
8609 +
8610 +(define_insn "call_fdpic_clobber"
8611 +  [(call (mem:QI (match_operand:SI 0 "ubicom32_call_address_operand" "a,S"))
8612 +        (match_operand:SI 1 "general_operand"                       "g,g"))
8613 +   (use (match_operand:SI 2 "ubicom32_fdpic_operand"                "Z,Z"))
8614 +   (clobber (reg:SI LINK_REGNO))]
8615 +  "TARGET_FDPIC"
8616 +  "@
8617 +   move.4\\ta5, 0(%0)\;move.4\\t%2, 4(%0)\;calli\\ta5, 0(a5)
8618 +   call\\ta5, %C0")
8619 +
8620 +; Call subroutine, returning value in operand 0
8621 +; (which must be a hard register).
8622 +;
8623 +(define_expand "call_value"
8624 +  [(set (match_operand 0 "" "")
8625 +       (call (match_operand:QI 1 "general_operand" "")
8626 +             (match_operand:SI 2 "general_operand" "")))]
8627 +  ""
8628 +  "{
8629 +     if (TARGET_FDPIC)
8630 +       {
8631 +        ubicom32_expand_call_value_fdpic (operands);
8632 +        DONE;
8633 +       }
8634 +
8635 +     if (! ubicom32_call_address_operand (XEXP (operands[1], 0), VOIDmode))
8636 +       XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
8637 +   }")
8638 +
8639 +; We expand to a simple form that doesn't clobber the link register and
8640 +; then split to a form that does.  This allows the RTL optimizers that
8641 +; run before the splitter to have the opportunity to eliminate the call
8642 +; without marking A5 as being clobbered and this in turn avoids saves
8643 +; and returns in a number of cases.
8644 +;
8645 +(define_insn_and_split "call_value_1"
8646 +  [(set (match_operand 0 "register_operand"                             "=r,r")
8647 +       (call (mem:QI (match_operand:SI 1 "ubicom32_call_address_operand" "a,S"))
8648 +             (match_operand:SI 2 "general_operand"                       "g,g")))]
8649 +  "! TARGET_FDPIC"
8650 +  "#"
8651 +  ""
8652 +  [(parallel
8653 +     [(set (match_dup 0)
8654 +          (call (mem:QI (match_dup 1))
8655 +                (match_dup 2)))
8656 +      (clobber (reg:SI LINK_REGNO))])]
8657 +  "")
8658 +
8659 +(define_insn "call_value_slow"
8660 +  [(set (match_operand 0 "register_operand"                             "=r,r")
8661 +       (call (mem:QI (match_operand:SI 1 "ubicom32_call_address_operand" "a,S"))
8662 +             (match_operand:SI 2 "general_operand"                       "g,g")))
8663 +   (clobber (reg:SI LINK_REGNO))]
8664 +  "(! TARGET_FDPIC && ! TARGET_FASTCALL)"
8665 +  "@
8666 +   calli\\ta5, 0(%1)
8667 +   moveai\\ta5, #%%hi(%C1)\;calli\\ta5, %%lo(%C1)(a5)")
8668 +
8669 +(define_insn "call_value_fast"
8670 +  [(set (match_operand 0 "register_operand"                             "=r,r")
8671 +       (call (mem:QI (match_operand:SI 1 "ubicom32_call_address_operand" "a,S"))
8672 +             (match_operand:SI 2 "general_operand"                       "g,g")))
8673 +   (clobber (reg:SI LINK_REGNO))]
8674 +  "(! TARGET_FDPIC && TARGET_FASTCALL)"
8675 +  "@
8676 +   calli\\ta5, 0(%1)
8677 +   call\\ta5, %C1")
8678 +
8679 +; We expand to a simple form that doesn't clobber the link register and
8680 +; then split to a form that does.  This allows the RTL optimizers that
8681 +; run before the splitter to have the opportunity to eliminate the call
8682 +; without marking A5 as being clobbered and this in turn avoids saves
8683 +; and returns in a number of cases.
8684 +;
8685 +(define_insn_and_split "call_value_fdpic"
8686 +  [(set (match_operand 0 "register_operand"                             "=r,r")
8687 +       (call (mem:QI (match_operand:SI 1 "ubicom32_call_address_operand" "a,S"))
8688 +             (match_operand:SI 2 "general_operand"                       "g,g")))
8689 +   (use (match_operand:SI 3 "ubicom32_fdpic_operand"                     "Z,Z"))]
8690 +  "TARGET_FDPIC"
8691 +  "#"
8692 +  ""
8693 +  [(parallel
8694 +     [(set (match_dup 0)
8695 +          (call (mem:QI (match_dup 1))
8696 +                (match_dup 2)))
8697 +      (use (match_dup 3))
8698 +      (clobber (reg:SI LINK_REGNO))])]
8699 +  "")
8700 +
8701 +(define_insn "call_value_fdpic_clobber"
8702 +  [(set (match_operand 0 "register_operand"                             "=r,r")
8703 +       (call (mem:QI (match_operand:SI 1 "ubicom32_call_address_operand" "a,S"))
8704 +             (match_operand:SI 2 "general_operand"                       "g,g")))
8705 +   (use (match_operand:SI 3 "ubicom32_fdpic_operand"                     "Z,Z"))
8706 +   (clobber (reg:SI LINK_REGNO))]
8707 +  "TARGET_FDPIC"
8708 +  "@
8709 +   move.4\\ta5, 0(%1)\;move.4\\t%3, 4(%1)\;calli\\ta5, 0(a5)
8710 +   call\\ta5, %C1")
8711 +
8712 +(define_expand "untyped_call"
8713 +  [(parallel [(call (match_operand 0 "" "")
8714 +                    (const_int 0))
8715 +              (match_operand 1 "" "")
8716 +              (match_operand 2 "" "")])]
8717 +  ""
8718 +  "{
8719 +     int i;
8720 +
8721 +     emit_call_insn (gen_call (operands[0], const0_rtx));
8722 +
8723 +     for (i = 0; i < XVECLEN (operands[2], 0); i++)
8724 +       {
8725 +         rtx set = XVECEXP (operands[2], 0, i);
8726 +         emit_move_insn (SET_DEST (set), SET_SRC (set));
8727 +       }
8728 +     DONE;
8729 +   }")
8730 +
8731 +(define_insn "lsl1_1"
8732 +  [(set (match_operand:SI 0 "ubicom32_data_register_operand"    "=d")
8733 +       (ashift:SI (subreg:SI
8734 +                    (match_operand:QI 1 "memory_operand"         "m")
8735 +                    0)
8736 +                  (match_operand:SI 2 "ubicom32_arith_operand"  "dM")))
8737 +   (clobber (reg:CC CC_REGNO))]
8738 +  "(ubicom32_v4)"
8739 +  "lsl.1\\t%0, %1, %2")
8740 +
8741 +; The combiner gets rather creative about left shifts of sub-word memory
8742 +; operands because it's uncertain about whether the memory is sign or
8743 +; zero extended.  It only wants zero-extended behaviour and so throws
8744 +; in an extra and operation.
8745 +;
8746 +(define_insn "lsl1_2"
8747 +  [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
8748 +       (and:SI
8749 +         (ashift:SI (subreg:SI
8750 +                      (match_operand:QI 1 "memory_operand"   "m")
8751 +                      0)
8752 +                    (match_operand:SI 2 "const_int_operand"  "M"))
8753 +         (match_operand:SI 3 "const_int_operand"             "n")))
8754 +   (clobber (reg:CC CC_REGNO))]
8755 +  "(ubicom32_v4
8756 +    && INTVAL (operands[3]) == (0xff << INTVAL (operands[2])))"
8757 +  "lsl.1\\t%0, %1, %2")
8758 +
8759 +(define_insn "lsl2_1"
8760 +  [(set (match_operand:SI 0 "ubicom32_data_register_operand"    "=d")
8761 +       (ashift:SI (subreg:SI
8762 +                    (match_operand:HI 1 "memory_operand"         "m")
8763 +                    0)
8764 +                  (match_operand:SI 2 "ubicom32_arith_operand"  "dM")))
8765 +   (clobber (reg:CC CC_REGNO))]
8766 +  "(ubicom32_v4)"
8767 +  "lsl.2\\t%0, %1, %2")
8768 +
8769 +; The combiner gets rather creative about left shifts of sub-word memory
8770 +; operands because it's uncertain about whether the memory is sign or
8771 +; zero extended.  It only wants zero-extended behaviour and so throws
8772 +; in an extra and operation.
8773 +;
8774 +(define_insn "lsl2_2"
8775 +  [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
8776 +       (and:SI
8777 +         (ashift:SI (subreg:SI
8778 +                      (match_operand:HI 1 "memory_operand"   "m")
8779 +                      0)
8780 +                    (match_operand:SI 2 "const_int_operand"  "M"))
8781 +         (match_operand:SI 3 "const_int_operand"             "n")))
8782 +   (clobber (reg:CC CC_REGNO))]
8783 +  "(ubicom32_v4
8784 +    && INTVAL (operands[3]) == (0xffff << INTVAL (operands[2])))"
8785 +  "lsl.2\\t%0, %1, %2")
8786 +
8787 +(define_insn "ashlsi3"
8788 +  [(set (match_operand:SI 0 "ubicom32_data_register_operand"    "=d")
8789 +       (ashift:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")
8790 +                  (match_operand:SI 2 "ubicom32_arith_operand"  "dM")))
8791 +   (clobber (reg:CC CC_REGNO))]
8792 +  ""
8793 +  "lsl.4\\t%0, %1, %2")
8794 +
8795 +(define_insn "lshlsi3_ccwz"
8796 +  [(set (reg CC_REGNO)
8797 +       (compare
8798 +         (ashift:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")
8799 +                    (match_operand:SI 2 "ubicom32_arith_operand"  "dM"))
8800 +         (const_int 0)))
8801 +   (set (match_operand:SI 0 "ubicom32_data_register_operand"      "=d")
8802 +       (ashift:SI (match_dup 1)
8803 +                  (match_dup 2)))]
8804 +  "ubicom32_match_cc_mode(insn, CCWZmode)"
8805 +  "lsl.4\\t%0, %1, %2")
8806 +
8807 +(define_insn "lshlsi3_ccwz_null"
8808 +  [(set (reg CC_REGNO)
8809 +       (compare
8810 +         (ashift:SI (match_operand:SI 0 "ubicom32_arith_operand" "rmI")
8811 +                    (match_operand:SI 1 "ubicom32_arith_operand"  "dM"))
8812 +         (const_int 0)))
8813 +   (clobber (match_scratch:SI 2                                           "=d"))]
8814 +  "ubicom32_match_cc_mode(insn, CCWZmode)"
8815 +  "lsl.4\\t%2, %0, %1")
8816 +
8817 +; The combiner finds this canonical form for what is in essence a right
8818 +; shift.
8819 +;
8820 +(define_insn "asr1_2"
8821 +  [(set (match_operand:SI 0 "ubicom32_data_register_operand"    "=d")
8822 +       (sign_extract:SI (match_operand:QI 1 "memory_operand"     "m")
8823 +                        (match_operand:SI 2 "const_int_operand"  "M")
8824 +                        (match_operand:SI 3 "const_int_operand"  "M")))
8825 +   (clobber (reg:CC CC_REGNO))]
8826 +  "(ubicom32_v4
8827 +    && (INTVAL (operands[2]) + INTVAL (operands[3]) == 8))"
8828 +  "asr.1\\t%0, %1, %3")
8829 +
8830 +; The combiner finds this canonical form for what is in essence a right
8831 +; shift.
8832 +;
8833 +(define_insn "asr2_2"
8834 +  [(set (match_operand:SI 0 "ubicom32_data_register_operand"    "=d")
8835 +       (sign_extract:SI (match_operand:HI 1 "memory_operand"     "m")
8836 +                        (match_operand:SI 2 "const_int_operand"  "M")
8837 +                        (match_operand:SI 3 "const_int_operand"  "M")))
8838 +   (clobber (reg:CC CC_REGNO))]
8839 +  "(ubicom32_v4
8840 +    && (INTVAL (operands[2]) + INTVAL (operands[3]) == 16))"
8841 +  "asr.2\\t%0, %1, %3")
8842 +
8843 +(define_insn "ashrsi3"
8844 +  [(set (match_operand:SI 0 "ubicom32_data_register_operand"      "=d")
8845 +       (ashiftrt:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmJ")
8846 +                    (match_operand:SI 2 "ubicom32_arith_operand"  "dM")))
8847 +   (clobber (reg:CC CC_REGNO))]
8848 +  ""
8849 +  "asr.4\\t%0, %1, %2")
8850 +
8851 +(define_insn "ashrsi3_ccwzn"
8852 +  [(set (reg CC_REGNO)
8853 +       (compare
8854 +         (ashiftrt:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmJ")
8855 +                      (match_operand:SI 2 "ubicom32_arith_operand"  "dM"))
8856 +         (const_int 0)))
8857 +   (set (match_operand:SI 0 "ubicom32_data_register_operand"        "=d")
8858 +       (ashiftrt:SI (match_dup 1)
8859 +                    (match_dup 2)))]
8860 +  "ubicom32_match_cc_mode(insn, CCWZNmode)"
8861 +  "asr.4\\t%0, %1, %2")
8862 +
8863 +(define_insn "ashrsi3_ccwzn_null"
8864 +  [(set (reg CC_REGNO)
8865 +       (compare
8866 +         (ashiftrt:SI (match_operand:SI 0 "ubicom32_arith_operand" "rmJ")
8867 +                      (match_operand:SI 1 "ubicom32_arith_operand"  "dM"))
8868 +         (const_int 0)))
8869 +   (clobber (match_scratch:SI 2                                             "=d"))]
8870 +  "ubicom32_match_cc_mode(insn, CCWZNmode)"
8871 +  "asr.4\\t%2, %0, %1")
8872 +
8873 +(define_insn "lsr1_1"
8874 +  [(set (match_operand:SI 0 "ubicom32_data_register_operand"    "=d")
8875 +       (lshiftrt:SI (subreg:SI
8876 +                      (match_operand:QI 1 "memory_operand"       "m")
8877 +                      0)
8878 +                  (match_operand:SI 2 "ubicom32_arith_operand"  "dM")))
8879 +   (clobber (reg:CC CC_REGNO))]
8880 +  "(ubicom32_v4)"
8881 +  "lsr.1\\t%0, %1, %2")
8882 +
8883 +; The combiner finds this canonical form for what is in essence a right
8884 +; shift.
8885 +;
8886 +(define_insn "lsr1_2"
8887 +  [(set (match_operand:SI 0 "ubicom32_data_register_operand"    "=d")
8888 +       (zero_extract:SI (match_operand:QI 1 "memory_operand"     "m")
8889 +                        (match_operand:SI 2 "const_int_operand"  "M")
8890 +                        (match_operand:SI 3 "const_int_operand"  "M")))
8891 +   (clobber (reg:CC CC_REGNO))]
8892 +  "(ubicom32_v4
8893 +    && (INTVAL (operands[2]) + INTVAL (operands[3]) == 8))"
8894 +  "lsr.1\\t%0, %1, %3")
8895 +
8896 +(define_insn "lsr2_1"
8897 +  [(set (match_operand:SI 0 "ubicom32_data_register_operand"    "=d")
8898 +       (lshiftrt:SI (subreg:SI
8899 +                      (match_operand:HI 1 "memory_operand"       "m")
8900 +                      0)
8901 +                  (match_operand:SI 2 "ubicom32_arith_operand"  "dM")))
8902 +   (clobber (reg:CC CC_REGNO))]
8903 +  "(ubicom32_v4)"
8904 +  "lsr.2\\t%0, %1, %2")
8905 +
8906 +; The combiner finds this canonical form for what is in essence a right
8907 +; shift.
8908 +;
8909 +(define_insn "lsr2_2"
8910 +  [(set (match_operand:SI 0 "ubicom32_data_register_operand"    "=d")
8911 +       (zero_extract:SI (match_operand:HI 1 "memory_operand"     "m")
8912 +                        (match_operand:SI 2 "const_int_operand"  "M")
8913 +                        (match_operand:SI 3 "const_int_operand"  "M")))
8914 +   (clobber (reg:CC CC_REGNO))]
8915 +  "(ubicom32_v4
8916 +    && (INTVAL (operands[2]) + INTVAL (operands[3]) == 16))"
8917 +  "lsr.2\\t%0, %1, %3")
8918 +
8919 +(define_insn "lshrsi3"
8920 +  [(set (match_operand:SI 0 "ubicom32_data_register_operand"      "=d")
8921 +       (lshiftrt:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")
8922 +                    (match_operand:SI 2 "ubicom32_arith_operand"  "dM")))
8923 +   (clobber (reg:CC CC_REGNO))]
8924 +  ""
8925 +  "lsr.4\\t%0, %1, %2")
8926 +
8927 +(define_insn "lshrsi3_ccwz"
8928 +  [(set (reg CC_REGNO)
8929 +       (compare
8930 +         (lshiftrt:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")
8931 +                      (match_operand:SI 2 "ubicom32_arith_operand"  "dM"))
8932 +         (const_int 0)))
8933 +   (set (match_operand:SI 0 "ubicom32_data_register_operand"        "=d")
8934 +       (lshiftrt:SI (match_dup 1)
8935 +                    (match_dup 2)))]
8936 +  "ubicom32_match_cc_mode(insn, CCWZmode)"
8937 +  "lsr.4\\t%0, %1, %2")
8938 +
8939 +(define_insn "lshrsi3_ccwz_null"
8940 +  [(set (reg CC_REGNO)
8941 +       (compare
8942 +         (lshiftrt:SI (match_operand:SI 0 "ubicom32_arith_operand" "rmI")
8943 +                      (match_operand:SI 1 "ubicom32_arith_operand"  "dM"))
8944 +         (const_int 0)))
8945 +   (clobber (match_scratch:SI 2                                             "=d"))]
8946 +  "ubicom32_match_cc_mode(insn, CCWZmode)"
8947 +  "lsr.4\\t%2, %0, %1")
8948 +
8949 +(define_expand "prologue"
8950 +  [(const_int 0)]
8951 +  ""
8952 +  "{
8953 +     ubicom32_expand_prologue ();
8954 +     DONE;
8955 +   }")
8956 +
8957 +(define_expand "epilogue"
8958 +  [(return)]
8959 +  ""
8960 +  "{
8961 +     ubicom32_expand_epilogue ();
8962 +     DONE;
8963 +   }")
8964 +
8965 +(define_expand "return"
8966 +  [(return)]
8967 +  ""
8968 +  "{
8969 +     ubicom32_expand_epilogue ();
8970 +     DONE;
8971 +   }")
8972 +
8973 +(define_expand "_eh_return"
8974 +  [(use (match_operand:SI 0 "register_operand" "r"))
8975 +   (use (match_operand:SI 1 "register_operand" "r"))]
8976 +  ""
8977 +  "{
8978 +     ubicom32_expand_eh_return (operands);
8979 +     DONE;
8980 +   }")
8981 +
8982 +; XXX - it looks almost certain that we could make return_internal use a Dn
8983 +; register too.  In that instance we'd have to use a ret instruction
8984 +; rather than a calli but it might save cycles.
8985 +;
8986 +(define_insn "return_internal"
8987 +  [(const_int 2)
8988 +   (return)
8989 +   (use (match_operand:SI 0 "ubicom32_mem_or_address_register_operand" "rm"))]
8990 +  ""
8991 +  "*
8992 +   {
8993 +     if (REG_P (operands[0]) && REGNO (operands[0]) == LINK_REGNO
8994 +        && ubicom32_can_use_calli_to_ret)
8995 +       return \"calli\\t%0, 0(%0)\";
8996 +
8997 +     return \"ret\\t%0\";
8998 +   }")
8999 +
9000 +(define_insn "return_from_post_modify_sp"
9001 +  [(parallel
9002 +     [(const_int 2)
9003 +      (return)
9004 +      (use (mem:SI (post_modify:SI
9005 +                    (reg:SI SP_REGNO)
9006 +                    (plus:SI (reg:SI SP_REGNO)
9007 +                             (match_operand:SI 0 "const_int_operand" "n")))))])]
9008 +  "INTVAL (operands[0]) >= 4 && INTVAL (operands[0]) <= 7 * 4"
9009 +  "ret\\t(sp)%E0++")
9010 +
9011 +;(define_insn "eh_return_internal"
9012 +;  [(const_int 4)
9013 +;   (return)
9014 +;   (use (reg:SI 34))]
9015 +;  ""
9016 +;  "ret\\ta2")
9017 +
9018 +; No operation, needed in case the user uses -g but not -O.
9019 +(define_expand "nop"
9020 +  [(const_int 0)]
9021 +  ""
9022 +  "")
9023 +
9024 +(define_insn "nop_internal"
9025 +  [(const_int 0)]
9026 +  ""
9027 +  "nop")
9028 +
9029 +; The combiner will generate this pattern given shift and add operations.
9030 +; The canonical form that the combiner wants to use appears to be multiplies
9031 +; instead of shifts even if the compiled sources use shifts.
9032 +;
9033 +(define_insn "shmrg1_add"
9034 +  [(set (match_operand:SI 0 "ubicom32_data_register_operand"          "=d")
9035 +       (plus:SI
9036 +         (mult:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")
9037 +                  (const_int 256))
9038 +         (zero_extend:SI
9039 +           (match_operand:QI 2 "ubicom32_arith_operand"              "rmI"))))
9040 +   (clobber (reg:CC CC_REGNO))]
9041 +  ""
9042 +  "shmrg.1\\t%0, %2, %1")
9043 +
9044 +; The combiner will generate this pattern given shift and or operations.
9045 +;
9046 +(define_insn "shmrg1_ior"
9047 +  [(set (match_operand:SI 0 "ubicom32_data_register_operand"            "=d")
9048 +       (ior:SI
9049 +         (ashift:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")
9050 +                    (const_int 8))
9051 +         (zero_extend:SI
9052 +           (match_operand:QI 2 "ubicom32_arith_operand"                "rmI"))))
9053 +   (clobber (reg:CC CC_REGNO))]
9054 +  ""
9055 +  "shmrg.1\\t%0, %2, %1")
9056 +
9057 +; The combiner will generate this pattern given shift and add operations.
9058 +; The canonical form that the combiner wants to use appears to be multiplies
9059 +; instead of shifts even if the compiled sources use shifts.
9060 +;
9061 +(define_insn "shmrg2_add"
9062 +  [(set (match_operand:SI 0 "ubicom32_data_register_operand"          "=d")
9063 +       (plus:SI
9064 +         (mult:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")
9065 +                  (const_int 65536))
9066 +         (zero_extend:SI
9067 +           (match_operand:HI 2 "ubicom32_arith_operand"              "rmI"))))
9068 +   (clobber (reg:CC CC_REGNO))]
9069 +  ""
9070 +  "shmrg.2\\t%0, %2, %1")
9071 +
9072 +; The combiner will generate this pattern given shift and or operations.
9073 +;
9074 +(define_insn "shmrg2_ior"
9075 +  [(set (match_operand:SI 0 "ubicom32_data_register_operand"            "=d")
9076 +       (ior:SI
9077 +         (ashift:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")
9078 +                    (const_int 16))
9079 +         (zero_extend:SI
9080 +           (match_operand:HI 2 "ubicom32_arith_operand"                "rmI"))))
9081 +   (clobber (reg:CC CC_REGNO))]
9082 +  ""
9083 +  "shmrg.2\\t%0, %2, %1")
9084 +
9085 +; Match the case where we load a word from the stack but then discard the
9086 +; upper 16 bits.  We turn this into a zero-extended load of that useful
9087 +; 16 bits direct from the stack where possible.
9088 +;
9089 +
9090 +; XXX - do these peephole2 ops actually work after the CCmode conversion?
9091 +(define_peephole2
9092 +  [(set (match_operand:SI 0 "register_operand" "")
9093 +       (mem:SI (plus:SI (reg:SI SP_REGNO)
9094 +                        (match_operand:SI 1 "const_int_operand" ""))))
9095 +   (set (match_operand:SI 2 "nonimmediate_operand" "")
9096 +       (zero_extend:SI (match_operand:HI 3 "register_operand" "")))]
9097 +  "(INTVAL (operands[1]) <= 252
9098 +    && REGNO (operands[3]) == REGNO (operands[0])
9099 +    && ((peep2_reg_dead_p (2, operands[0])
9100 +        && ! reg_mentioned_p (operands[0], operands[2]))
9101 +        || rtx_equal_p (operands[0], operands[2])))"
9102 +  [(set (match_dup 2)
9103 +       (zero_extend:SI (mem:HI (plus:SI (reg:SI SP_REGNO)
9104 +                                        (match_dup 4)))))]
9105 +  "{
9106 +     operands[4] = GEN_INT (INTVAL (operands[1]) + 2);
9107 +   }")
9108 +
9109 +; Match the case where we load a word from the stack but then discard the
9110 +; upper 16 bits.  We turn this into a 16-bit load of that useful
9111 +; 16 bits direct from the stack where possible.
9112 +;
9113 +(define_peephole2
9114 +  [(set (match_operand:SI 0 "register_operand" "")
9115 +       (mem:SI (plus:SI (reg:SI SP_REGNO)
9116 +                        (match_operand:SI 1 "const_int_operand" ""))))
9117 +   (set (match_operand:HI 2 "nonimmediate_operand" "")
9118 +       (match_operand:HI 3 "register_operand" ""))]
9119 +  "(INTVAL (operands[1]) <= 252
9120 +    && REGNO (operands[3]) == REGNO (operands[0])
9121 +    && ((peep2_reg_dead_p (2, operands[0])
9122 +        && ! reg_mentioned_p (operands[0], operands[2]))
9123 +        || rtx_equal_p (operands[0], operands[2])))"
9124 +  [(set (match_dup 2)
9125 +       (mem:HI (plus:SI (reg:SI SP_REGNO)
9126 +                        (match_dup 4))))]
9127 +  "{
9128 +     operands[4] = GEN_INT (INTVAL (operands[1]) + 2);
9129 +   }")
9130 +
9131 +; Match the case where we load a word from the stack but then discard the
9132 +; upper 24 bits.  We turn this into a zero-extended load of that useful
9133 +; 8 bits direct from the stack where possible.
9134 +;
9135 +(define_peephole2
9136 +  [(set (match_operand:SI 0 "register_operand" "")
9137 +       (mem:SI (plus:SI (reg:SI SP_REGNO)
9138 +                        (match_operand:SI 1 "const_int_operand" ""))))
9139 +   (set (match_operand:SI 2 "nonimmediate_operand" "")
9140 +       (zero_extend:SI (match_operand:QI 3 "register_operand" "")))]
9141 +  "(INTVAL (operands[1]) <= 124
9142 +    && REGNO (operands[3]) == REGNO (operands[0])
9143 +    && ((peep2_reg_dead_p (2, operands[0])
9144 +        && ! reg_mentioned_p (operands[0], operands[2]))
9145 +        || rtx_equal_p (operands[0], operands[2])))"
9146 +  [(set (match_dup 2)
9147 +       (zero_extend:SI (mem:QI (plus:SI (reg:SI SP_REGNO)
9148 +                                        (match_dup 4)))))]
9149 +  "{
9150 +     operands[4] = GEN_INT (INTVAL (operands[1]) + 3);
9151 +   }")
9152 +
9153 +; Match the case where we load a word from the stack but then discard the
9154 +; upper 24 bits.  We turn this into an 8-bit load of that useful
9155 +; 8 bits direct from the stack where possible.
9156 +;
9157 +(define_peephole2
9158 +  [(set (match_operand:SI 0 "register_operand" "")
9159 +       (mem:SI (plus:SI (reg:SI SP_REGNO)
9160 +                        (match_operand:SI 1 "const_int_operand" ""))))
9161 +   (set (match_operand:QI 2 "nonimmediate_operand" "")
9162 +       (match_operand:QI 3 "register_operand" ""))]
9163 +  "(INTVAL (operands[1]) <= 124
9164 +    && REGNO (operands[3]) == REGNO (operands[0])
9165 +    && ((peep2_reg_dead_p (2, operands[0])
9166 +        && ! reg_mentioned_p (operands[0], operands[2]))
9167 +        || rtx_equal_p (operands[0], operands[2])))"
9168 +  [(set (match_dup 2)
9169 +       (mem:QI (plus:SI (reg:SI SP_REGNO)
9170 +                        (match_dup 4))))]
9171 +  "{
9172 +     operands[4] = GEN_INT (INTVAL (operands[1]) + 3);
9173 +   }")
9174 +
9175 --- /dev/null
9176 +++ b/gcc/config/ubicom32/ubicom32.opt
9177 @@ -0,0 +1,27 @@
9178 +mdebug-address
9179 +Target RejectNegative Report Undocumented Mask(DEBUG_ADDRESS)
9180 +Debug addresses
9181 +
9182 +mdebug-context
9183 +Target RejectNegative Report Undocumented Mask(DEBUG_CONTEXT)
9184 +Debug contexts
9185 +
9186 +march=
9187 +Target Report Var(ubicom32_arch_name) Init("ubicom32v4") Joined
9188 +Specify the name of the target architecture
9189 +
9190 +mfdpic
9191 +Target Report Mask(FDPIC)
9192 +Enable Function Descriptor PIC mode
9193 +
9194 +minline-plt
9195 +Target Report Mask(INLINE_PLT)
9196 +Enable inlining of PLT in function calls
9197 +
9198 +mfastcall
9199 +Target Report Mask(FASTCALL)
9200 +Enable default fast (call) calling sequence for smaller applications
9201 +
9202 +mipos-abi
9203 +Target Report Mask(IPOS_ABI)
9204 +Enable the ipOS ABI in which D10-D13 are caller-clobbered
9205 --- /dev/null
9206 +++ b/gcc/config/ubicom32/uclinux.h
9207 @@ -0,0 +1,67 @@
9208 +/* Definitions of target machine for Ubicom32-uclinux
9209 +
9210 +   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
9211 +   2009 Free Software Foundation, Inc.
9212 +   Contributed by Ubicom, Inc.
9213 +
9214 +   This file is part of GCC.
9215 +
9216 +   GCC is free software; you can redistribute it and/or modify it
9217 +   under the terms of the GNU General Public License as published
9218 +   by the Free Software Foundation; either version 3, or (at your
9219 +   option) any later version.
9220 +
9221 +   GCC is distributed in the hope that it will be useful, but WITHOUT
9222 +   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
9223 +   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
9224 +   License for more details.
9225 +
9226 +   You should have received a copy of the GNU General Public License
9227 +   along with GCC; see the file COPYING3.  If not see
9228 +   <http://www.gnu.org/licenses/>.  */
9229 +
9230 +/* Don't assume anything about the header files.  */
9231 +#define NO_IMPLICIT_EXTERN_C
9232 +
9233 +#undef  LIB_SPEC
9234 +#define LIB_SPEC  \
9235 +       "%{pthread:-lpthread} " \
9236 +       "%{!shared:%{!symbolic: -lc}} "
9237 +
9238 +
9239 +#undef LINK_GCC_C_SEQUENCE_SPEC
9240 +#define LINK_GCC_C_SEQUENCE_SPEC \
9241 +  "%{!shared:--start-group} %G %L %{!shared:--end-group}%{shared:%G} "
9242 +
9243 +#undef STARTFILE_SPEC
9244 +#define STARTFILE_SPEC \
9245 +       "%{!shared: crt1%O%s}" \
9246 +       " crti%O%s crtbegin%O%s"
9247 +
9248 +#undef ENDFILE_SPEC
9249 +#define ENDFILE_SPEC "crtend%O%s crtn%O%s"
9250 +
9251 +/* This macro applies on top of OBJECT_FORMAT_ELF and indicates that
9252 +   we want to support both flat and ELF output.  */
9253 +#define OBJECT_FORMAT_FLAT
9254 +
9255 +#undef DRIVER_SELF_SPECS
9256 +#define DRIVER_SELF_SPECS \
9257 +  "%{!mno-fastcall:-mfastcall}"
9258 +
9259 +/* taken from linux.h */
9260 +/* The GNU C++ standard library requires that these macros be defined.  */
9261 +#undef CPLUSPLUS_CPP_SPEC
9262 +#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
9263 +
9264 +#define TARGET_OS_CPP_BUILTINS()                               \
9265 +    do {                                                       \
9266 +       builtin_define_std ("__UBICOM32__");                    \
9267 +       builtin_define_std ("__ubicom32__");                    \
9268 +       builtin_define ("__gnu_linux__");                       \
9269 +       builtin_define_std ("linux");                           \
9270 +       builtin_define_std ("unix");                            \
9271 +       builtin_assert ("system=linux");                        \
9272 +       builtin_assert ("system=unix");                         \
9273 +       builtin_assert ("system=posix");                        \
9274 +    } while (0)
9275 --- /dev/null
9276 +++ b/gcc/config/ubicom32/xm-ubicom32.h
9277 @@ -0,0 +1,36 @@
9278 +/* Configuration for Ubicom's Ubicom32 architecture.
9279 +   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Free Software
9280 +   Foundation, Inc.
9281 +   Contributed by Ubicom Inc.
9282 +
9283 +This file is part of GNU CC.
9284 +
9285 +GNU CC is free software; you can redistribute it and/or modify
9286 +it under the terms of the GNU General Public License as published by
9287 +the Free Software Foundation; either version 2, or (at your option)
9288 +any later version.
9289 +
9290 +GNU CC is distributed in the hope that it will be useful,
9291 +but WITHOUT ANY WARRANTY; without even the implied warranty of
9292 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9293 +GNU General Public License for more details.
9294 +
9295 +You should have received a copy of the GNU General Public License
9296 +along with GNU CC; see the file COPYING.  If not, write to
9297 +the Free Software Foundation, 59 Temple Place - Suite 330,
9298 +Boston, MA 02111-1307, USA.  */
9299 +
9300 +/* #defines that need visibility everywhere.  */
9301 +#define FALSE 0
9302 +#define TRUE 1
9303 +
9304 +/* This describes the machine the compiler is hosted on.  */
9305 +#define HOST_BITS_PER_CHAR 8
9306 +#define HOST_BITS_PER_SHORT 16
9307 +#define HOST_BITS_PER_INT 32
9308 +#define HOST_BITS_PER_LONG 32
9309 +#define HOST_BITS_PER_LONGLONG 64
9310 +
9311 +/* Arguments to use with `exit'.  */
9312 +#define SUCCESS_EXIT_CODE 0
9313 +#define FATAL_EXIT_CODE 33
9314 --- a/gcc/config.gcc
9315 +++ b/gcc/config.gcc
9316 @@ -2662,6 +2662,34 @@ spu-*-elf*)
9317         c_target_objs="${c_target_objs} spu-c.o"
9318         cxx_target_objs="${cxx_target_objs} spu-c.o"
9319         ;;
9320 +ubicom32-*-elf)
9321 +       xm_file=ubicom32/xm-ubicom32.h
9322 +       tm_file="${tm_file} ubicom32/elf.h" # still need dbxelf.h elfos.h
9323 +       tmake_file=ubicom32/t-ubicom32
9324 +       ;;
9325 +ubicom32-*-uclinux*)
9326 +       xm_file=ubicom32/xm-ubicom32.h
9327 +       tm_file="${tm_file} ubicom32/elf.h ubicom32/uclinux.h"  # still need dbxelf.h elfos.h linux.h
9328 +       tm_defines="${tm_defines} UCLIBC_DEFAULT=1"
9329 +       extra_options="${extra_options} linux.opt"
9330 +       tmake_file=ubicom32/t-ubicom32-uclinux
9331 +       use_collect2=no
9332 +       ;;
9333 +ubicom32-*-linux-uclibc)
9334 +       xm_file=ubicom32/xm-ubicom32.h
9335 +       tm_file="${tm_file} ubicom32/elf.h linux.h ubicom32/linux.h"  # still need dbxelf.h elfos.h
9336 +       tmake_file="t-slibgcc-elf-ver ubicom32/t-ubicom32-linux"
9337 +       extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
9338 +       use_collect2=no
9339 +       ;;
9340 +ubicom32-*-linux*)
9341 +       xm_file=ubicom32/xm-ubicom32.h
9342 +       tm_file="${tm_file} ubicom32/elf.h linux.h ubicom32/linux.h"  # still need dbxelf.h elfos.h
9343 +       tmake_file="t-slibgcc-elf-ver ubicom32/t-ubicom32-linux"
9344 +       tm_defines="${tm_defines} UCLIBC_DEFAULT=1"
9345 +       extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
9346 +       use_collect2=no
9347 +       ;;
9348  v850e1-*-*)
9349         target_cpu_default="TARGET_CPU_v850e1"
9350         tm_file="dbxelf.h elfos.h newlib-stdint.h v850/v850.h"
9351 --- a/libgcc/config.host
9352 +++ b/libgcc/config.host
9353 @@ -572,6 +572,15 @@ sparc64-*-netbsd*)
9354         ;;
9355  spu-*-elf*)
9356         ;;
9357 +ubicom32*-*-elf*)
9358 +       ;;
9359 +ubicom32*-*-uclinux*)
9360 +        ;;
9361 +ubicom32*-*-linux*)
9362 +       # No need to build crtbeginT.o on uClibc systems.  Should probably
9363 +       # be moved to the OS specific section above.
9364 +       extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
9365 +        ;;
9366  v850e1-*-*)
9367         ;;
9368  v850e-*-*)