1 /* Subroutines used for code generation on Ubicom IP2022
2 Communications Controller.
3 Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
4 Contributed by Red Hat, Inc and Ubicom, Inc.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
25 #include "coretypes.h"
29 #include "hard-reg-set.h"
31 #include "insn-config.h"
32 #include "conditions.h"
33 #include "insn-flags.h"
35 #include "insn-attr.h"
36 #include "insn-addr.h"
48 #include "target-def.h"
49 #include "basic-block.h"
51 /* There are problems with 'frame_pointer_needed'. If we force it
52 on, we either end up not eliminating uses of FP, which results in
53 SPILL register failures or we may end up with calculation errors in
54 the stack offsets. Isolate the decision process into a simple macro. */
55 #define CHAIN_FRAMES (frame_pointer_needed || FRAME_POINTER_REQUIRED)
57 static int ip2k_naked_function_p (tree);
58 #ifdef IP2K_MD_REORG_PASS
59 static void mdr_resequence_xy_yx (rtx);
60 static void mdr_pres_replace_and_recurse (rtx, rtx, rtx);
61 static void mdr_propagate_reg_equivs_sequence (rtx, rtx, rtx);
62 static void mdr_propagate_reg_equivs (rtx);
63 static int track_dp_reload (rtx , rtx *, int , int);
64 static void mdr_try_dp_reload_elim (rtx);
65 static void mdr_try_move_dp_reload (rtx);
66 static void mdr_try_move_pushes (rtx);
67 static void mdr_try_propagate_clr_sequence (rtx, unsigned int);
68 static void mdr_try_propagate_clr (rtx);
69 static void mdr_try_propagate_move_sequence (rtx, rtx, rtx);
70 static void mdr_try_propagate_move (rtx);
71 static void mdr_try_remove_redundant_insns (rtx);
72 static int track_w_reload (rtx, rtx *, int , int);
73 static void mdr_try_wreg_elim (rtx);
74 #endif /* IP2K_MD_REORG_PASS */
75 static void ip2k_reorg (void);
76 static int ip2k_check_can_adjust_stack_ref (rtx, int);
77 static void ip2k_adjust_stack_ref (rtx *, int);
78 static int ip2k_xexp_not_uses_reg_for_mem (rtx, unsigned int);
79 static tree ip2k_handle_progmem_attribute (tree *, tree, tree, int, bool *);
80 static tree ip2k_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
81 static bool ip2k_rtx_costs (rtx, int, int, int *);
82 static int ip2k_address_cost (rtx);
83 static void ip2k_init_libfuncs (void);
84 static bool ip2k_return_in_memory (tree, tree);
85 static void ip2k_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
88 const struct attribute_spec ip2k_attribute_table[];
91 /* Initialize the GCC target structure. */
92 #undef TARGET_ASM_ALIGNED_HI_OP
93 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
95 #undef TARGET_ASM_FUNCTION_PROLOGUE
96 #define TARGET_ASM_FUNCTION_PROLOGUE function_prologue
98 #undef TARGET_ASM_FUNCTION_EPILOGUE
99 #define TARGET_ASM_FUNCTION_EPILOGUE function_epilogue
101 #undef TARGET_ASM_UNIQUE_SECTION
102 #define TARGET_ASM_UNIQUE_SECTION unique_section
104 #undef TARGET_ASM_FUNCTION_RODATA_SECTION
105 #define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
107 #undef TARGET_ATTRIBUTE_TABLE
108 #define TARGET_ATTRIBUTE_TABLE ip2k_attribute_table
110 #undef TARGET_RTX_COSTS
111 #define TARGET_RTX_COSTS ip2k_rtx_costs
112 #undef TARGET_ADDRESS_COST
113 #define TARGET_ADDRESS_COST ip2k_address_cost
115 #undef TARGET_MACHINE_DEPENDENT_REORG
116 #define TARGET_MACHINE_DEPENDENT_REORG ip2k_reorg
118 #undef TARGET_INIT_LIBFUNCS
119 #define TARGET_INIT_LIBFUNCS ip2k_init_libfuncs
121 #undef TARGET_RETURN_IN_MEMORY
122 #define TARGET_RETURN_IN_MEMORY ip2k_return_in_memory
124 #undef TARGET_SETUP_INCOMING_VARARGS
125 #define TARGET_SETUP_INCOMING_VARARGS ip2k_setup_incoming_varargs
127 struct gcc_target targetm = TARGET_INITIALIZER;
129 /* Prologue/Epilogue size in words. */
130 static int prologue_size;
131 static int epilogue_size;
133 /* compare and test instructions for the IP2K are materialized by
134 the conditional branch that uses them. This is because conditional
135 branches are skips over unconditional branches. */
136 rtx ip2k_compare_operands[3]; /* Additional operands for condition code. */
137 int ip2k_test_flag; /* Indicates Z, WREG contain condition code
140 /* Some ip2k patterns push a byte onto the stack and then access
141 SP-relative addresses. Since reload doesn't know about these
142 pushes, we must track them internally with a %< (push) or %> (pop)
144 static int ip2k_stack_delta;
146 /* Track if or how far our ip2k reorganization pass has run. */
147 int ip2k_reorg_in_progress = 0;
148 int ip2k_reorg_completed = 0;
149 int ip2k_reorg_split_dimode = 0;
150 int ip2k_reorg_split_simode = 0;
151 int ip2k_reorg_split_himode = 0;
152 int ip2k_reorg_split_qimode = 0;
153 int ip2k_reorg_merge_qimode = 0;
155 /* Set up local allocation order. */
158 ip2k_init_local_alloc (int *rao)
160 static const int alloc_order[] = REG_ALLOC_ORDER;
162 memcpy (rao, alloc_order, sizeof (alloc_order));
165 /* Returns the number of bytes of arguments automatically
166 popped when returning from a subroutine call.
167 FUNDECL is the declaration node of the function (as a tree),
168 FUNTYPE is the data type of the function (as a tree),
169 or for a library call it is an identifier node for the subroutine name.
170 SIZE is the number of bytes of arguments passed on the stack. */
173 ip2k_return_pops_args (tree fundecl ATTRIBUTE_UNUSED, tree funtype, int size)
175 if (TREE_CODE (funtype) == IDENTIFIER_NODE)
178 if (TYPE_ARG_TYPES (funtype) == NULL_TREE
179 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype))) == void_type_node))
185 /* Return nonzero if FUNC is a naked function. */
188 ip2k_naked_function_p (tree func)
192 if (TREE_CODE (func) != FUNCTION_DECL)
195 a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
196 return a != NULL_TREE;
199 /* Output function prologue. */
201 function_prologue (FILE *file, HOST_WIDE_INT size)
208 prologue_size = epilogue_size = 0;
210 if (ip2k_naked_function_p (current_function_decl))
212 fprintf (file, "/* prologue: naked */\n");
216 leaf_func_p = leaf_function_p ();
217 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
219 /* For now, we compute all these facts about the function, but don't
220 take any action based on the information. */
223 fprintf (file, "/* prologue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n",
226 /* Unless we're a leaf we need to save the return PC. */
230 OUT_AS1 (push, calll);
231 OUT_AS1 (push, callh);
235 /* We need to save the old FP and set the new FP pointing at the
236 stack location where the old one is saved. Note that because of
237 post-decrement addressing, the SP is off-by-one after the
238 push, so we harvest the SP address BEFORE we push the MSBs of
242 OUT_AS1 (push, REG_FP+1); /* Save old LSBs. */
243 OUT_AS2 (mov, w, spl);
244 OUT_AS2 (mov, REG_FP+1, w); /* SPL -> FPL */
246 OUT_AS2 (mov, w, sph); /* Freeze SP MSBs */
247 OUT_AS1 (push, REG_FP); /* Save old MSBs */
248 OUT_AS2 (mov, REG_FP, w); /* SPH -> FPH */
252 for (reg = (CHAIN_FRAMES) ? (REG_FP - 1) : (REG_FP + 1);
255 if (regs_ever_live[reg] && ! call_used_regs[reg])
257 fprintf (file, "\t" AS1 (push,%s) "\n", reg_names[reg]);
264 operands[0] = GEN_INT (size);
275 OUT_AS2 (mov, w, %L0);
276 OUT_AS2 (sub, spl, w);
280 switch (size & 0xff00)
289 if ((size & 0xff) != ((size >> 8) & 0xff))
290 OUT_AS2 (mov, w, %H0); /* Otherwise W has value we want. */
291 OUT_AS2 (sub, sph, w);
296 /* XXX - change this to use the carry-propagating subtract trick. */
297 if (flag_stack_check)
299 OUT_AS2 (mov, w, sph);
300 OUT_AS2 (cmp, w, #%%hi8data(_end));
301 OUT_AS1 (sc, ); /* C == 0 -> hi8(edata) < sph */
304 OUT_AS1 (sz, ); /* Z == 1 -> look at low byte */
306 OUT_AS1 (jmp,0f); /* sp < edata, so raise stack fault */
307 OUT_AS2 (mov, w, spl);
308 OUT_AS2 (cmp, w, #%%lo8data(_end));
309 OUT_AS1 (sc,); /* C==1 -> lo8(edata) >= spl */
313 output_asm_insn ("push\t$ff", operands);
320 /* Output function epilogue. */
322 function_epilogue (FILE *file, HOST_WIDE_INT size)
326 rtx operands[2]; /* Dummy used by OUT_ASn */
327 int args_locals_size = current_function_args_size;
328 int saved_regs_p = 0;
331 /* Use this opportunity to reset the reorg flags! */
332 ip2k_reorg_in_progress = 0;
333 ip2k_reorg_completed = 0;
334 ip2k_reorg_split_dimode = 0;
335 ip2k_reorg_split_simode = 0;
336 ip2k_reorg_split_himode = 0;
337 ip2k_reorg_split_qimode = 0;
338 ip2k_reorg_merge_qimode = 0;
340 if (ip2k_naked_function_p (current_function_decl))
342 fprintf (file, "/* epilogue: naked */\n");
346 leaf_func_p = leaf_function_p ();
348 fprintf (file, "/* epilogue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n",
351 savelimit = (CHAIN_FRAMES) ? REG_FP : (REG_FP + 2);
352 for (reg = 0; reg < savelimit; reg++)
353 if (regs_ever_live[reg] && ! call_used_regs[reg])
361 if (leaf_func_p && !CHAIN_FRAMES && !saved_regs_p
362 && current_function_pops_args)
363 args_locals_size = current_function_args_size + size;
366 operands[0] = GEN_INT (size);
371 OUT_AS2 (mov, w, %L0);
372 OUT_AS2 (add, spl, w);
382 switch (size & 0xff00)
385 if ((size & 0xff) != ((size >> 8) & 0xff))
386 OUT_AS2 (mov, w, %H0);
387 OUT_AS2 (add, sph, w);
399 for (reg = 0; reg < savelimit; reg++)
401 if (regs_ever_live[reg] && ! call_used_regs[reg])
403 fprintf (file, "\t" AS1 (pop,%s) "\n", reg_names[reg]);
409 && ! (current_function_pops_args
410 && current_function_args_size >= 2
411 && current_function_args_size < 0x100))
413 OUT_AS1 (pop, REG_FP);
414 OUT_AS1 (pop, REG_FP+1);
420 if (current_function_pops_args
421 && current_function_args_size >= 2
422 && current_function_args_size < 0x100)
424 if (current_function_args_size == 2)
428 OUT_AS1 (page, __fp_pop2_args_ret);
429 OUT_AS1 (jmp, __fp_pop2_args_ret);
433 OUT_AS1 (page, __pop2_args_ret);
434 OUT_AS1 (jmp, __pop2_args_ret);
440 operands[0] = GEN_INT (current_function_args_size);
441 OUT_AS2 (mov, w, %L0);
444 OUT_AS1 (page, __fp_pop_args_ret);
445 OUT_AS1 (jmp, __fp_pop_args_ret);
449 OUT_AS1 (page, __pop_args_ret);
450 OUT_AS1 (jmp, __pop_args_ret);
458 OUT_AS1 (pop, callh);
459 OUT_AS1 (pop, calll);
465 if (current_function_pops_args
466 && args_locals_size >= 2
467 && args_locals_size < 0x100)
469 if (args_locals_size == 2)
473 OUT_AS1 (page, __leaf_fp_pop2_args_ret);
474 OUT_AS1 (jmp, __leaf_fp_pop2_args_ret);
481 operands[0] = GEN_INT (args_locals_size);
484 OUT_AS2 (mov, w, %L0);
485 OUT_AS1 (page, __leaf_fp_pop_args_ret);
486 OUT_AS1 (jmp, __leaf_fp_pop_args_ret);
494 if (current_function_pops_args && args_locals_size && need_ret)
496 operands[0] = GEN_INT (args_locals_size);
498 switch (args_locals_size & 0xff)
501 OUT_AS2 (mov, w, %L0);
502 OUT_AS2 (add, spl, w);
514 switch (args_locals_size & 0xff00)
517 if ((args_locals_size & 0xff) != ((args_locals_size >> 8) & 0xff))
518 OUT_AS2 (mov, w, %H0);
519 OUT_AS2 (add, sph, w);
538 fprintf (file, "/* epilogue end (size=%d) */\n", epilogue_size);
541 /* Return the difference between the registers after the function
544 Stack Frame grows down:
547 <------ AP ($102:$103)
548 RETURN PC (unless leaf function)
550 <------ FP [HARD_FRAME_POINTER] ($FD:$FE)
552 <------ VFP [$100:$101]
554 <------ SP ($6:$7) */
556 ip2k_init_elim_offset (int from, int to)
558 int leaf_func_p = leaf_function_p ();
559 int no_saved_pc = leaf_func_p
560 || ip2k_naked_function_p (current_function_decl);
565 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
566 return get_frame_size () + 1;
568 if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
569 return (CHAIN_FRAMES ? 2 : 0) + (no_saved_pc ? 0 : 2);
571 /* Count all the registers we had to preserve. */
573 reglimit = CHAIN_FRAMES ? REG_FP : (REG_FP + 2);
574 for (offset = 0,reg = 0; reg < reglimit; ++reg)
576 if ((regs_ever_live[reg] && ! call_used_regs[reg]))
582 if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
585 if (from == HARD_FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
586 /* Add in the stack-local variables. */
587 return offset + get_frame_size () + 1;
589 if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
590 /* Add stack-locals plus saved FP and PC. */
591 return offset + get_frame_size () + 1
592 + (CHAIN_FRAMES ? 2 : 0) + (no_saved_pc ? 0 : 2);
594 abort (); /* Unanticipated elimination. */
597 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
598 machine for a memory operand of mode MODE. */
601 legitimate_address_p (enum machine_mode mode, rtx x, int strict)
605 if (GET_CODE (x) == SUBREG)
608 switch (GET_CODE (x))
611 /* IP allows indirection without offset - only okay if
612 we don't require access to multiple bytes. */
613 if (REGNO (x) == REG_IP)
614 return (GET_MODE_SIZE (mode) == 1) ? 'R' : 0;
616 /* We can indirect through DP or SP register. */
617 if (strict ? REG_OK_FOR_BASE_STRICT_P (x)
618 : REG_OK_FOR_BASE_NOSTRICT_P (x))
623 /* Offsets from DP or SP are legal in the range 0..127 */
630 if (REG_P (op2) && ! REG_P (op1))
637 /* Don't let anything but R+I through.. */
640 || GET_CODE (op2) != CONST_INT)
645 case REG_DP: /* only 0..127 displacement */
647 off = 2 * GET_MODE_SIZE (mode);
651 if (INTVAL (op2) < 0 || INTVAL (op2) > (128 - off))
652 return 0; /* Positive must be small enough that after
653 splitting all pieces are addressed. */
654 return 'S'; /* Safe displacement. */
657 if (GET_MODE_SIZE (mode) <= 1 && INTVAL (op2) == 0)
658 return (GET_MODE_SIZE (mode) == 1) ? 'R' : 0;
665 if (strict || ! REG_OK_FOR_BASE_NOSTRICT_P (op1))
666 return 0; /* Allow until reload. */
675 /* We always allow references to things in code space. */
676 return is_regfile_address (x) ? 0 : 'C';
688 /* Is ADDR mode dependent? */
690 ip2k_mode_dependent_address (rtx addr)
692 switch (GET_CODE (addr))
701 return (REGNO (addr) == REG_IP); /* Can't do IP displaced addresses. */
704 return 0; /* Assume no dependency. */
708 /* Attempts to replace X with a valid
709 memory address for an operand of mode MODE. */
712 legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
713 enum machine_mode mode ATTRIBUTE_UNUSED, rtx scratch)
717 /* You might think that we could split up a symbolic address by
718 adding the HIGH 8 bits and doing a displacement off the dp. But
719 because we only have 7 bits of offset, that doesn't actually
720 help. So only constant displacements are likely to obtain an
723 if (GET_CODE (x) == PLUS && REG_P (XEXP (x, 0))
724 && GET_CODE (XEXP (x, 1)) == CONST_INT
725 && ! CONST_OK_FOR_LETTER_P (INTVAL (XEXP (x, 1)), 'K'))
727 int offset = INTVAL (XEXP (x, 1));
729 reg = scratch ? scratch : gen_reg_rtx (Pmode);
731 emit_insn (gen_rtx_SET (VOIDmode, reg,
732 gen_rtx_PLUS (Pmode, XEXP (x, 0),
733 GEN_INT (offset & 0xffc0))));
734 x = gen_rtx_PLUS (Pmode, reg, GEN_INT (offset & 0x3f));
737 return x; /* We don't have any other tricks. */
740 /* Determine if X is a 'data' address or a code address. All static
741 data and stack variables reside in data memory. Only code is believed
742 to be in PRAM or FLASH. */
744 is_regfile_address (rtx x)
747 switch (GET_CODE (x))
750 return ! SYMBOL_REF_FUNCTION_P (x); /* Declared as function. */
768 /* Output ADDR to FILE as address. */
771 print_operand_address (FILE *file, rtx addr)
773 switch (GET_CODE (addr))
776 addr = alter_subreg (&addr);
780 fprintf (file, "(%s)",
781 REGNO (addr) == REG_DP ? "DP"
782 : REGNO (addr) == REG_SP ? "SP"
783 : REGNO (addr) == REG_IP ? "IP"
784 : REGNO (addr) == REG_VFP ? "VFP" /* Should never see this */
785 : REGNO (addr) == REG_AP ? "AP" /* or this, either. */
786 : reg_names[REGNO (addr)]);
795 addr = XEXP (addr, 0);
796 print_operand_address (file, XEXP (addr, 0));
798 print_operand_address (file, XEXP (addr, 1));
802 if (is_regfile_address (XEXP (addr, 1)))
803 fprintf (file, "%%lo8data(");
805 fprintf (file, "%%lo8insn(");
806 print_operand_address (file, XEXP (addr, 1));
808 print_operand_address (file, XEXP (addr, 0));
811 case PLUS: /* Ought to be stack or dp references. */
812 if (XEXP (addr, 1) == const0_rtx
813 && GET_CODE (XEXP (addr, 0)) == PLUS)
815 print_operand_address (file, XEXP (addr, 0));
819 if (! REG_P (XEXP (addr, 0)) || REGNO (XEXP (addr, 0)) != REG_IP)
820 print_operand_address (file, XEXP (addr, 1)); /* const */
821 print_operand_address (file, XEXP (addr, 0)); /* (reg) */
825 if (is_regfile_address (XEXP (addr, 0)))
826 fprintf (file, "%%hi8data(");
828 fprintf (file, "%%hi8insn(");
829 output_addr_const (file, XEXP (addr, 0));
834 output_addr_const (file, addr);
839 /* Output X as assembler operand to file FILE. */
842 print_operand (FILE *file, rtx x, int code)
886 if (ip2k_short_operand (x, GET_MODE (x))
887 && ip2k_address_uses_reg_p (x, REG_SP))
888 /* An SP-relative address needs to account for interior stack
889 pushes that reload didn't know about when it calculated the
891 abcd += ip2k_stack_delta;
893 switch (GET_CODE (x))
896 x = alter_subreg (&x);
900 fprintf (file, reg_names[true_regnum (x) + abcd]);
907 fprintf (file, "$%x", (int)(INTVAL (x) & 0xffff));
911 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x)); /* bit selector */
914 case 'e': /* "1 << n" - e.g. "exp" */
915 fprintf (file, "#%d", 1 << INTVAL (x));
923 value >>= 8 * (3 - abcd);
926 fprintf (file, "#%ld", value);
930 fprintf (file, "#%d", (int)((INTVAL (x) >> 8) & 0xff));
934 fprintf (file, "#%d", (int)(INTVAL (x) & 0xff));
945 value = ((unsigned long long)INTVAL (x)) >> (8 * (7 - abcd)) & 0xff;
946 fprintf (file, "#%ld", value);
950 fprintf (file, "#" HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
972 abort (); /* Probably an error. */
976 fprintf (file, "#%s(",
977 is_regfile_address (x) ? "%hi8data"
979 print_operand_address (file, x);
984 fprintf (file, "#%s(",
985 is_regfile_address (x) ? "%lo8data"
987 print_operand_address (file, x);
992 print_operand_address (file, x);
998 rtx addr = XEXP (x, 0);
1000 if (GET_CODE (addr) == SUBREG)
1001 addr = alter_subreg (&x);
1003 if (CONSTANT_P (addr) && abcd)
1006 print_operand_address (file, addr);
1007 fprintf (file, ")+%d", abcd);
1011 switch (GET_CODE (addr))
1014 abcd += INTVAL (XEXP (addr, 1));
1016 /* Worry about (plus (plus (reg DP) (const_int 10))
1018 if (GET_CODE (XEXP (addr, 0)) == PLUS)
1020 addr = XEXP (addr, 0);
1021 abcd += INTVAL (XEXP (addr, 1));
1024 fprintf (file, "%d", abcd);
1025 print_operand_address (file, XEXP (addr, 0));
1030 fprintf (file, "%d", abcd);
1031 print_operand_address (file, addr);
1034 else if (GET_CODE (addr) == REG
1035 && (REGNO (addr) == REG_DP || REGNO (addr) == REG_SP))
1037 fprintf (file, "0");
1038 print_operand_address (file, addr);
1041 print_operand_address (file, addr);
1046 /* Is this an integer or a floating point value? */
1047 if (GET_MODE (x) == VOIDmode)
1055 value = CONST_DOUBLE_HIGH (x);
1056 value >>= 8 * (3 - abcd);
1059 fprintf (file, "#%ld", value);
1066 value = CONST_DOUBLE_LOW (x);
1067 value >>= 8 * (7 - abcd);
1070 fprintf (file, "#%ld", value);
1079 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1080 REAL_VALUE_TO_TARGET_SINGLE (rv, value);
1081 fprintf (file, "0x%lx", value);
1086 fatal_insn ("bad operand", x);
1090 /* Remember the operands for the compare. */
1092 ip2k_set_compare (rtx x, rtx y)
1094 ip2k_compare_operands[0] = x;
1095 ip2k_compare_operands[1] = y;
1099 /* Emit the code for sCOND instructions. */
1101 ip2k_gen_sCOND (rtx insn ATTRIBUTE_UNUSED, enum rtx_code code, rtx dest)
1103 #define operands ip2k_compare_operands
1104 enum machine_mode mode;
1108 mode = GET_MODE (operands[0]);
1109 if ((mode != QImode) && (mode != HImode)
1110 && (mode != SImode) && (mode != DImode))
1111 mode = GET_MODE (operands[1]);
1113 /* We have a fast path for a specific type of QImode compare. We ought
1114 to extend this for larger cases too but that wins less frequently and
1115 introduces a lot of complexity. */
1117 && !rtx_equal_p (operands[0], operands[2])
1118 && !rtx_equal_p (operands[1], operands[2])
1119 && (! REG_P (operands[2])
1120 || (ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[2]), 1)
1121 && ip2k_xexp_not_uses_reg_p (operands[1],
1122 REGNO (operands[2]), 1))))
1125 if (immediate_operand (operands[1], QImode)
1126 && ((INTVAL (operands[1]) & 0xff) == 0xff))
1129 OUT_AS2 (incsnz, w, %0);
1131 OUT_AS2 (incsz, w, %0);
1133 else if (immediate_operand (operands[1], QImode)
1134 && ((INTVAL (operands[1]) & 0xff) == 0x01))
1137 OUT_AS2 (decsnz, w, %0);
1139 OUT_AS2 (decsz, w, %0);
1141 else if (ip2k_compare_operands[1] == const0_rtx)
1143 OUT_AS2 (mov, w, %0);
1151 OUT_AS2 (mov, w, %0);
1153 OUT_AS2 (csne, w, %1);
1155 OUT_AS2 (cse, w, %1);
1161 if (ip2k_compare_operands[1] == const0_rtx)
1166 OUT_AS2 (mov, w, %0);
1170 OUT_AS2 (mov, w, %H0);
1171 OUT_AS2 (or, w, %L0);
1175 OUT_AS2 (mov, w, %A0);
1176 OUT_AS2 (or, w, %B0);
1177 OUT_AS2 (or, w, %C0);
1178 OUT_AS2 (or, w, %D0);
1182 OUT_AS2 (mov, w, %S0);
1183 OUT_AS2 (or, w, %T0);
1184 OUT_AS2 (or, w, %U0);
1185 OUT_AS2 (or, w, %V0);
1186 OUT_AS2 (or, w, %W0);
1187 OUT_AS2 (or, w, %X0);
1188 OUT_AS2 (or, w, %Y0);
1189 OUT_AS2 (or, w, %Z0);
1201 OUT_AS2 (mov, w, %1);
1202 OUT_AS2 (cmp, w, %0);
1206 OUT_AS2 (mov, w, %H1);
1207 OUT_AS2 (cmp, w, %H0);
1211 OUT_AS2 (mov, w, %L1);
1212 OUT_AS2 (cmp, w, %L0);
1219 OUT_AS2 (mov, w, #1);
1220 OUT_AS2 (mov, mulh, w);
1223 OUT_AS1 (clr, mulh);
1224 OUT_AS2 (mov, w, %A1);
1225 OUT_AS2 (cse, w, %A0);
1228 OUT_AS2 (mov, w, %B1);
1229 OUT_AS2 (cse, w, %B0);
1232 OUT_AS2 (mov, w, %C1);
1233 OUT_AS2 (cse, w, %C0);
1236 OUT_AS2 (mov, w, %D1);
1237 OUT_AS2 (cse, w, %D0);
1240 OUT_AS1 (dec, mulh);
1242 OUT_AS1 (inc, mulh);
1243 OUT_AS2 (mov, w, mulh);
1244 OUT_AS2 (mov, %2, w);
1250 OUT_AS2 (mov, w, #1);
1251 OUT_AS2 (mov, mulh, w);
1254 OUT_AS1 (clr, mulh);
1255 OUT_AS2 (mov, w, %S1);
1256 OUT_AS2 (cse, w, %S0);
1259 OUT_AS2 (mov, w, %T1);
1260 OUT_AS2 (cse, w, %T0);
1263 OUT_AS2 (mov, w, %U1);
1264 OUT_AS2 (cse, w, %U0);
1267 OUT_AS2 (mov, w, %V1);
1268 OUT_AS2 (cse, w, %V0);
1271 OUT_AS2 (mov, w, %W1);
1272 OUT_AS2 (cse, w, %W0);
1275 OUT_AS2 (mov, w, %X1);
1276 OUT_AS2 (cse, w, %X0);
1279 OUT_AS2 (mov, w, %Y1);
1280 OUT_AS2 (cse, w, %Y0);
1283 OUT_AS2 (mov, w, %Z1);
1284 OUT_AS2 (cse, w, %Z0);
1287 OUT_AS1 (dec, mulh);
1289 OUT_AS1 (inc, mulh);
1290 OUT_AS2 (mov, w, mulh);
1291 OUT_AS2 (mov, %2, w);
1298 OUT_AS2 (mov, w, #0);
1303 OUT_AS1 (inc, wreg);
1304 OUT_AS2 (mov, %2, w);
1312 ip2k_gen_signed_comp_branch (rtx insn, enum rtx_code code, rtx label)
1314 #define operands ip2k_compare_operands
1315 enum machine_mode mode;
1316 int can_use_skip = 0;
1319 operands[2] = label;
1321 mode = GET_MODE (operands[0]);
1322 if ((mode != QImode) && (mode != HImode)
1323 && (mode != SImode) && (mode != DImode))
1324 mode = GET_MODE (operands[1]);
1326 /* Look for situations where we can just skip the next instruction instead
1327 of skipping and then branching! */
1328 ninsn = next_real_insn (insn);
1330 && (recog_memoized (ninsn) >= 0)
1331 && get_attr_skip (ninsn) == SKIP_YES)
1333 rtx skip_tgt = next_nonnote_insn (next_real_insn (insn));
1335 /* The first situation is where the target of the jump is one insn
1336 after the jump insn and the insn being jumped is only one machine
1338 if (label == skip_tgt)
1342 /* If our skip target is in fact a code label then we ignore the
1343 label and move onto the next useful instruction. Nothing we do
1344 here has any effect on the use of skipping instructions. */
1345 if (GET_CODE (skip_tgt) == CODE_LABEL)
1346 skip_tgt = next_nonnote_insn (skip_tgt);
1348 /* The second situation is where we have something of the form:
1354 optional_label (this may or may not exist):
1358 In this case we can eliminate the first "page/jump label". */
1359 if (GET_CODE (skip_tgt) == JUMP_INSN)
1361 rtx set = single_set (skip_tgt);
1362 if (GET_CODE (XEXP (set, 0)) == PC
1363 && GET_CODE (XEXP (set, 1)) == LABEL_REF
1364 && label == JUMP_LABEL (skip_tgt))
1370 /* gcc is a little braindead and does some rather stateful things while
1371 inspecting attributes - we have to put this state back to what it's
1373 extract_constrain_insn_cached (insn);
1375 if (ip2k_compare_operands[1] == const0_rtx) /* These are easier. */
1382 OUT_AS2 (sb, %0, 7);
1386 OUT_AS2 (snb, %0, 7);
1396 OUT_AS2 (rl, w, %S0);
1397 OUT_AS2 (mov, w, %S0);
1398 OUT_AS2 (or, w, %T0);
1399 OUT_AS2 (or, w, %U0);
1400 OUT_AS2 (or, w, %V0);
1401 OUT_AS2 (or, w, %W0);
1402 OUT_AS2 (or, w, %X0);
1403 OUT_AS2 (or, w, %Y0);
1404 OUT_AS2 (or, w, %Z0);
1406 OUT_AS2 (setb, status, 0);
1407 OUT_AS2 (sb, status, 0);
1413 OUT_AS2 (rl, w, %A0);
1414 OUT_AS2 (mov, w, %A0);
1415 OUT_AS2 (or, w, %B0);
1416 OUT_AS2 (or, w, %C0);
1417 OUT_AS2 (or, w, %D0);
1419 OUT_AS2 (setb, status, 0);
1420 OUT_AS2 (sb, status, 0);
1426 OUT_AS2 (rl, w, %H0);
1427 OUT_AS2 (mov, w, %H0);
1428 OUT_AS2 (or, w, %L0);
1430 OUT_AS2 (setb, status, 0);
1431 OUT_AS2 (sb, status, 0);
1437 OUT_AS2 (mov, w, %0); /* Will just do "sb w, 7". */
1439 OUT_AS2 (setb, wreg, 7);
1440 OUT_AS2 (sb, wreg, 7);
1454 OUT_AS2 (mov, w, %S0);
1455 OUT_AS2 (or, w, %T0);
1456 OUT_AS2 (or, w, %U0);
1457 OUT_AS2 (or, w, %V0);
1458 OUT_AS2 (or, w, %W0);
1459 OUT_AS2 (or, w, %X0);
1460 OUT_AS2 (or, w, %Y0);
1461 OUT_AS2 (or, w, %Z0); /* Z is correct. */
1463 OUT_AS2 (snb, %S0, 7);
1469 OUT_AS2 (mov, w, %A0);
1470 OUT_AS2 (or, w, %B0);
1471 OUT_AS2 (or, w, %C0);
1472 OUT_AS2 (or, w, %D0); /* Z is correct. */
1474 OUT_AS2 (snb, %A0, 7);
1480 OUT_AS2 (mov, w, %H0);
1481 OUT_AS2 (or, w, %L0);
1483 OUT_AS2 (snb, %H0, 7);
1489 OUT_AS2 (mov, w, %0); /* Will just do "sb w, 7". */
1491 OUT_AS2 (snb, wreg, 7);
1504 OUT_AS2 (snb, %0, 7);
1508 OUT_AS2 (sb, %0, 7);
1520 /* signed compares are out of line because we can't get
1521 the hardware to compute the overflow for us. */
1526 OUT_AS1 (push, %1%<);
1527 OUT_AS1 (push, %0%>);
1528 OUT_AS1 (page, __cmpqi2);
1529 OUT_AS1 (call, __cmpqi2);
1533 OUT_AS1 (push, %L1%<);
1534 OUT_AS1 (push, %H1%<);
1535 OUT_AS1 (push, %L0%<);
1536 OUT_AS1 (push, %H0%>%>%>);
1537 OUT_AS1 (page, __cmphi2);
1538 OUT_AS1 (call, __cmphi2);
1542 OUT_AS1 (push, %D1%<);
1543 OUT_AS1 (push, %C1%<);
1544 OUT_AS1 (push, %B1%<);
1545 OUT_AS1 (push, %A1%<);
1546 OUT_AS1 (push, %D0%<);
1547 OUT_AS1 (push, %C0%<);
1548 OUT_AS1 (push, %B0%<);
1549 OUT_AS1 (push, %A0%>%>%>%>%>%>%>);
1550 OUT_AS1 (page, __cmpsi2);
1551 OUT_AS1 (call, __cmpsi2);
1555 if (GET_CODE (operands[0]) == MEM
1556 && true_regnum (XEXP (operands[0], 0)) == REG_DP)
1558 OUT_AS1 (push, %Z1%<);
1559 OUT_AS1 (push, %Y1%<);
1560 OUT_AS1 (push, %X1%<);
1561 OUT_AS1 (push, %W1%<);
1562 OUT_AS1 (push, %V1%<);
1563 OUT_AS1 (push, %U1%<);
1564 OUT_AS1 (push, %T1%<);
1565 OUT_AS1 (push, %S1%>%>%>%>%>%>%>);
1566 OUT_AS1 (page, __cmpdi2_dp);
1567 OUT_AS1 (call, __cmpdi2_dp);
1571 OUT_AS1 (push, %Z1%<);
1572 OUT_AS1 (push, %Y1%<);
1573 OUT_AS1 (push, %X1%<);
1574 OUT_AS1 (push, %W1%<);
1575 OUT_AS1 (push, %V1%<);
1576 OUT_AS1 (push, %U1%<);
1577 OUT_AS1 (push, %T1%<);
1578 OUT_AS1 (push, %S1%<);
1579 OUT_AS1 (push, %Z0%<);
1580 OUT_AS1 (push, %Y0%<);
1581 OUT_AS1 (push, %X0%<);
1582 OUT_AS1 (push, %W0%<);
1583 OUT_AS1 (push, %V0%<);
1584 OUT_AS1 (push, %U0%<);
1585 OUT_AS1 (push, %T0%<);
1586 OUT_AS1 (push, %S0%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>);
1587 OUT_AS1 (page, __cmpdi2);
1588 OUT_AS1 (call, __cmpdi2);
1601 OUT_AS2 (cse, w, #0);
1605 OUT_AS2 (csne, w, #0);
1614 OUT_AS2 (cse, w, #2);
1618 OUT_AS2 (csne, w, #2);
1627 OUT_AS2 (snb, wreg, 1);
1631 OUT_AS2 (sb, wreg, 1);
1640 OUT_AS2 (csne, w, #0);
1644 OUT_AS2 (cse, w, #0);
1658 ip2k_gen_unsigned_comp_branch (rtx insn, enum rtx_code code, rtx label)
1660 #define operands ip2k_compare_operands
1661 enum machine_mode mode;
1664 int can_use_skip = 0;
1666 HOST_WIDE_INT const_low;
1667 HOST_WIDE_INT const_high;
1669 operands[2] = label;
1671 mode = GET_MODE (operands[0]);
1672 if ((mode != QImode) && (mode != HImode) && (mode != SImode)
1673 && (mode != DImode))
1675 mode = GET_MODE (operands[1]);
1678 /* Look for situations where we can just skip the next instruction instead
1679 of skipping and then branching! */
1680 ninsn = next_real_insn (insn);
1682 && (recog_memoized (ninsn) >= 0)
1683 && get_attr_skip (ninsn) == SKIP_YES)
1685 rtx skip_tgt = next_nonnote_insn (next_real_insn (insn));
1687 /* The first situation is where the target of the jump is one insn
1688 after the jump insn and the insn being jumped is only one machine
1690 if (label == skip_tgt)
1694 /* If our skip target is in fact a code label then we ignore the
1695 label and move onto the next useful instruction. Nothing we do
1696 here has any effect on the use of skipping instructions. */
1697 if (GET_CODE (skip_tgt) == CODE_LABEL)
1698 skip_tgt = next_nonnote_insn (skip_tgt);
1700 /* The second situation is where we have something of the form:
1706 optional_label (this may or may not exist):
1710 In this case we can eliminate the first "page/jump label". */
1711 if (GET_CODE (skip_tgt) == JUMP_INSN)
1713 rtx set = single_set (skip_tgt);
1714 if (GET_CODE (XEXP (set, 0)) == PC
1715 && GET_CODE (XEXP (set, 1)) == LABEL_REF
1716 && label == JUMP_LABEL (skip_tgt))
1722 /* gcc is a little braindead and does some rather stateful things while
1723 inspecting attributes - we have to put this state back to what it's
1725 extract_constrain_insn_cached (insn);
1727 if (ip2k_compare_operands[1] == const0_rtx)
1732 code = EQ; /* Nothing is LTU 0. */
1736 code = NE; /* Anything nonzero is GTU. */
1740 case NE: /* Test all the bits, result in
1746 OUT_AS2 (mov, w, %S0);
1747 OUT_AS2 (or, w, %T0);
1748 OUT_AS2 (or, w, %U0);
1749 OUT_AS2 (or, w, %V0);
1750 OUT_AS2 (or, w, %W0);
1751 OUT_AS2 (or, w, %X0);
1752 OUT_AS2 (or, w, %Y0);
1753 OUT_AS2 (or, w, %Z0);
1757 OUT_AS2 (mov, w, %A0);
1758 OUT_AS2 (or, w, %B0);
1759 OUT_AS2 (or, w, %C0);
1760 OUT_AS2 (or, w, %D0);
1764 OUT_AS2 (mov, w, %H0);
1765 OUT_AS2 (or, w, %L0);
1769 OUT_AS2 (mov, w, %0);
1795 /* Always succeed. */
1810 /* Look at whether we have a constant as one of our operands. If we do
1811 and it's in the position that we use to subtract from during our
1812 normal optimized comparison concept then we have to shuffle things
1816 if ((immediate_operand (operands[1], GET_MODE (operands[1]))
1817 && ((code == LEU) || (code == GTU)))
1818 || (immediate_operand (operands[0], GET_MODE (operands[0]))
1819 && ((code == LTU) || (code == GEU))))
1825 /* Same as above - look if we have a constant that we can compare
1826 for equality or non-equality. If we know this then we can look
1827 for common value eliminations. Note that we want to ensure that
1828 any immediate value is operand 1 to simplify the code later! */
1829 if ((code == EQ) || (code == NE))
1831 imm_cmp = immediate_operand (operands[1], GET_MODE (operands[1]));
1834 imm_cmp = immediate_operand (operands[0], GET_MODE (operands[0]));
1837 rtx tmp = operands[1];
1838 operands[1] = operands[0];
1850 if (imm_cmp && ((INTVAL (operands[1]) & 0xff) == 0xff))
1851 OUT_AS2 (incsnz, w, %0);
1852 else if (imm_cmp && ((INTVAL (operands[1]) & 0xff) == 0x01))
1853 OUT_AS2 (decsnz, w, %0);
1856 OUT_AS2 (mov, w, %1);
1857 OUT_AS2 (csne, w, %0);
1864 if (imm_cmp && ((INTVAL (operands[1]) & 0xff) == 0xff))
1865 OUT_AS2 (incsz, w, %0);
1866 else if (imm_cmp && ((INTVAL (operands[1]) & 0xff) == 0x01))
1867 OUT_AS2 (decsz, w, %0);
1870 OUT_AS2 (mov, w, %1);
1871 OUT_AS2 (cse, w, %0);
1878 OUT_AS2 (mov, w, %0);
1879 OUT_AS2 (cmp, w, %1);
1886 OUT_AS2 (mov, w, %1);
1887 OUT_AS2 (cmp, w, %0);
1894 OUT_AS2 (mov, w, %1);
1895 OUT_AS2 (cmp, w, %0);
1902 OUT_AS2 (mov, w, %0);
1903 OUT_AS2 (cmp, w, %1);
1919 unsigned char h = 0, l = 1;
1923 h = (INTVAL (operands[1]) >> 8) & 0xff;
1924 l = INTVAL (operands[1]) & 0xff;
1926 if ((h == 0xff) && (l == 0xff))
1928 /* We should be able to do the following, but the
1929 IP2k simulator doesn't like it and we get a load
1930 of failures in gcc-c-torture. */
1931 OUT_AS2 (incsnz, w, %L0);
1932 OUT_AS2 (incsz, w, %H0);
1933 /* OUT_AS1 (skip,); Should have this */
1934 OUT_AS1 (page, 1f);/* Shouldn't need this! */
1935 OUT_AS1 (jmp, 1f); /* Shouldn't need this either. */
1944 OUT_AS2 (dec, w, %L0);
1947 OUT_AS2 (mov, w, %L0);
1948 OUT_AS2 (sub, w, %L1);
1950 OUT_AS2 (or, w, %H0);
1959 OUT_AS2 (dec, w, %H0);
1962 OUT_AS2 (mov, w, %H0);
1963 OUT_AS2 (sub, w, %H1);
1965 OUT_AS2 (or, w, %L0);
1973 OUT_AS2 (mov, w, %H1);
1974 OUT_AS2 (cse, w, %H0);
1977 if (! imm_cmp || (h != l))
1978 OUT_AS2 (mov, w, %L1);
1979 OUT_AS2 (csne, w, %L0);
1988 unsigned char h = 0, l = 1;
1992 h = (INTVAL (operands[1]) >> 8) & 0xff;
1993 l = INTVAL (operands[1]) & 0xff;
1995 if ((h == 0xff) && (l == 0xff))
1997 OUT_AS2 (incsnz, w, %L0);
1998 OUT_AS2 (incsz, w, %H0);
2006 OUT_AS2 (dec, w, %L0);
2009 OUT_AS2 (mov, w, %L0);
2010 OUT_AS2 (sub, w, %L1);
2012 OUT_AS2 (or, w, %H0);
2021 OUT_AS2 (dec, w, %H0);
2024 OUT_AS2 (mov, w, %H0);
2025 OUT_AS2 (sub, w, %H1);
2027 OUT_AS2 (or, w, %L0);
2035 OUT_AS2 (mov, w, %H1);
2036 if (imm_cmp && (h == l))
2038 OUT_AS2 (csne, w, %H0);
2039 OUT_AS2 (cse, w, %L0);
2043 OUT_AS2 (cse, w, %H0);
2046 OUT_AS2 (mov, w, %L1);
2047 OUT_AS2 (cse, w, %L0);
2057 /* > 0xffff never succeeds! */
2058 if ((INTVAL (operands[1]) & 0xffff) != 0xffff)
2060 operands[3] = GEN_INT (INTVAL (operands[1]) + 1);
2061 OUT_AS2 (mov, w, %L3);
2062 OUT_AS2 (sub, w, %L0);
2063 OUT_AS2 (mov, w, %H3);
2064 OUT_AS2 (subc, w, %H0);
2072 OUT_AS2 (mov, w, %L0);
2073 OUT_AS2 (sub, w, %L1);
2074 OUT_AS2 (mov, w, %H0);
2075 OUT_AS2 (subc, w, %H1);
2085 if (INTVAL (operands[0]) == 0)
2087 OUT_AS2 (mov, w, %H1);
2088 OUT_AS2 (or, w, %L1);
2095 operands[3] = GEN_INT (INTVAL (operands[0]) - 1);
2096 OUT_AS2 (mov, w, %L3);
2097 OUT_AS2 (sub, w, %L1);
2098 OUT_AS2 (mov, w, %H3);
2099 OUT_AS2 (subc, w, %H1);
2107 OUT_AS2 (mov, w, %L1);
2108 OUT_AS2 (sub, w, %L0);
2109 OUT_AS2 (mov, w, %H1);
2110 OUT_AS2 (subc, w, %H0);
2120 if (INTVAL (operands[0]) == 0)
2122 OUT_AS2 (mov, w, %H1);
2123 OUT_AS2 (or, w, %L1);
2130 operands[3] = GEN_INT (INTVAL (operands[0]) - 1);
2131 OUT_AS2 (mov, w, %L3);
2132 OUT_AS2 (sub, w, %L1);
2133 OUT_AS2 (mov, w, %H3);
2134 OUT_AS2 (subc, w, %H1);
2142 OUT_AS2 (mov, w, %L1);
2143 OUT_AS2 (sub, w, %L0);
2144 OUT_AS2 (mov, w, %H1);
2145 OUT_AS2 (subc, w, %H0);
2155 if ((INTVAL (operands[1]) & 0xffff) == 0xffff)
2157 /* <= 0xffff always succeeds. */
2163 operands[3] = GEN_INT (INTVAL (operands[1]) + 1);
2164 OUT_AS2 (mov, w, %L3);
2165 OUT_AS2 (sub, w, %L0);
2166 OUT_AS2 (mov, w, %H3);
2167 OUT_AS2 (subc, w, %H0);
2175 OUT_AS2 (mov, w, %L0);
2176 OUT_AS2 (sub, w, %L1);
2177 OUT_AS2 (mov, w, %H0);
2178 OUT_AS2 (subc, w, %H1);
2195 unsigned char a = 0, b = 1, c = 2, d = 3;
2199 a = (INTVAL (operands[1]) >> 24) & 0xff;
2200 b = (INTVAL (operands[1]) >> 16) & 0xff;
2201 c = (INTVAL (operands[1]) >> 8) & 0xff;
2202 d = INTVAL (operands[1]) & 0xff;
2205 OUT_AS2 (mov, w, %A1);
2206 if (imm_cmp && (b == a))
2208 OUT_AS2 (csne, w, %A0);
2209 OUT_AS2 (cse, w, %B0);
2213 OUT_AS2 (cse, w, %A0);
2216 OUT_AS2 (mov, w, %B1);
2217 OUT_AS2 (cse, w, %B0);
2221 if (! imm_cmp || (c != b))
2222 OUT_AS2 (mov, w, %C1);
2223 OUT_AS2 (cse, w, %C0);
2226 if (! imm_cmp || (d != c))
2227 OUT_AS2 (mov, w, %D1);
2228 OUT_AS2 (csne, w, %D0);
2237 unsigned char a = 0, b = 1, c = 2, d = 3;
2241 a = (INTVAL (operands[1]) >> 24) & 0xff;
2242 b = (INTVAL (operands[1]) >> 16) & 0xff;
2243 c = (INTVAL (operands[1]) >> 8) & 0xff;
2244 d = INTVAL (operands[1]) & 0xff;
2247 OUT_AS2 (mov, w, %A1);
2248 if (imm_cmp && (b == a))
2250 OUT_AS2 (csne, w, %A0);
2251 OUT_AS2 (cse, w, %B0);
2255 OUT_AS2 (cse, w, %A0);
2258 OUT_AS2 (mov, w, %B1);
2259 OUT_AS2 (cse, w, %B0);
2263 if (! imm_cmp || (c != b))
2264 OUT_AS2 (mov, w, %C1);
2265 if (imm_cmp && (d == c))
2267 OUT_AS2 (csne, w, %C0);
2268 OUT_AS2 (cse, w, %D0);
2272 OUT_AS2 (cse, w, %C0);
2275 OUT_AS2 (mov, w, %D1);
2276 OUT_AS2 (cse, w, %D0);
2286 /* > 0xffffffff never succeeds! */
2287 if ((unsigned HOST_WIDE_INT)(INTVAL (operands[1]) & 0xffffffff)
2290 operands[3] = GEN_INT (INTVAL (operands[1]) + 1);
2291 OUT_AS2 (mov, w, %D3);
2292 OUT_AS2 (sub, w, %D0);
2293 OUT_AS2 (mov, w, %C3);
2294 OUT_AS2 (subc, w, %C0);
2295 OUT_AS2 (mov, w, %B3);
2296 OUT_AS2 (subc, w, %B0);
2297 OUT_AS2 (mov, w, %A3);
2298 OUT_AS2 (subc, w, %A0);
2306 OUT_AS2 (mov, w, %D0);
2307 OUT_AS2 (sub, w, %D1);
2308 OUT_AS2 (mov, w, %C0);
2309 OUT_AS2 (subc, w, %C1);
2310 OUT_AS2 (mov, w, %B0);
2311 OUT_AS2 (subc, w, %B1);
2312 OUT_AS2 (mov, w, %A0);
2313 OUT_AS2 (subc, w, %A1);
2323 if (INTVAL (operands[0]) == 0)
2325 OUT_AS2 (mov, w, %A1);
2326 OUT_AS2 (or, w, %B1);
2327 OUT_AS2 (or, w, %C1);
2328 OUT_AS2 (or, w, %D1);
2335 operands[3] = GEN_INT (INTVAL (operands[0]) - 1);
2336 OUT_AS2 (mov, w, %D3);
2337 OUT_AS2 (sub, w, %D1);
2338 OUT_AS2 (mov, w, %C3);
2339 OUT_AS2 (subc, w, %C1);
2340 OUT_AS2 (mov, w, %B3);
2341 OUT_AS2 (subc, w, %B1);
2342 OUT_AS2 (mov, w, %A3);
2343 OUT_AS2 (subc, w, %A1);
2351 OUT_AS2 (mov, w, %D1);
2352 OUT_AS2 (sub, w, %D0);
2353 OUT_AS2 (mov, w, %C1);
2354 OUT_AS2 (subc, w, %C0);
2355 OUT_AS2 (mov, w, %B1);
2356 OUT_AS2 (subc, w, %B0);
2357 OUT_AS2 (mov, w, %A1);
2358 OUT_AS2 (subc, w, %A0);
2368 if (INTVAL (operands[0]) == 0)
2370 OUT_AS2 (mov, w, %A1);
2371 OUT_AS2 (or, w, %B1);
2372 OUT_AS2 (or, w, %C1);
2373 OUT_AS2 (or, w, %D1);
2380 operands[3] = GEN_INT (INTVAL (operands[0]) - 1);
2381 OUT_AS2 (mov, w, %D3);
2382 OUT_AS2 (sub, w, %D1);
2383 OUT_AS2 (mov, w, %C3);
2384 OUT_AS2 (subc, w, %C1);
2385 OUT_AS2 (mov, w, %B3);
2386 OUT_AS2 (subc, w, %B1);
2387 OUT_AS2 (mov, w, %A3);
2388 OUT_AS2 (subc, w, %A1);
2396 OUT_AS2 (mov, w, %D1);
2397 OUT_AS2 (sub, w, %D0);
2398 OUT_AS2 (mov, w, %C1);
2399 OUT_AS2 (subc, w, %C0);
2400 OUT_AS2 (mov, w, %B1);
2401 OUT_AS2 (subc, w, %B0);
2402 OUT_AS2 (mov, w, %A1);
2403 OUT_AS2 (subc, w, %A0);
2413 if ((unsigned HOST_WIDE_INT)(INTVAL (operands[1]) & 0xffffffff)
2416 /* <= 0xffffffff always succeeds. */
2422 operands[3] = GEN_INT (INTVAL (operands[1]) + 1);
2423 OUT_AS2 (mov, w, %D3);
2424 OUT_AS2 (sub, w, %D0);
2425 OUT_AS2 (mov, w, %C3);
2426 OUT_AS2 (subc, w, %C0);
2427 OUT_AS2 (mov, w, %B3);
2428 OUT_AS2 (subc, w, %B0);
2429 OUT_AS2 (mov, w, %A3);
2430 OUT_AS2 (subc, w, %A0);
2438 OUT_AS2 (mov, w, %D0);
2439 OUT_AS2 (sub, w, %D1);
2440 OUT_AS2 (mov, w, %C0);
2441 OUT_AS2 (subc, w, %C1);
2442 OUT_AS2 (mov, w, %B0);
2443 OUT_AS2 (subc, w, %B1);
2444 OUT_AS2 (mov, w, %A0);
2445 OUT_AS2 (subc, w, %A1);
2458 if (GET_CODE (operands[1]) == CONST_INT)
2460 const_low = INTVAL (operands[1]);
2461 const_high = (const_low >= 0) - 1;
2463 else if (GET_CODE (operands[1]) == CONST_DOUBLE)
2465 const_low = CONST_DOUBLE_LOW (operands[1]);
2466 const_high = CONST_DOUBLE_HIGH (operands[1]);
2472 unsigned char s = 0, t = 1, u = 2, v = 3;
2473 unsigned char w = 4, x = 5, y = 6, z = 7;
2476 if (GET_CODE (operands[0]) == MEM
2477 && true_regnum (XEXP (operands[0], 0)) == REG_DP)
2479 OUT_AS1 (push, %Z1%<);
2480 OUT_AS1 (push, %Y1%<);
2481 OUT_AS1 (push, %X1%<);
2482 OUT_AS1 (push, %W1%<);
2483 OUT_AS1 (push, %V1%<);
2484 OUT_AS1 (push, %U1%<);
2485 OUT_AS1 (push, %T1%<);
2486 OUT_AS1 (push, %S1%>%>%>%>%>%>%>);
2487 OUT_AS1 (page, __cmpdi2_dp);
2488 OUT_AS1 (call, __cmpdi2_dp);
2489 OUT_AS2 (csne, w, #1);
2495 OUT_AS1 (push, %Z1%<);
2496 OUT_AS1 (push, %Y1%<);
2497 OUT_AS1 (push, %X1%<);
2498 OUT_AS1 (push, %W1%<);
2499 OUT_AS1 (push, %V1%<);
2500 OUT_AS1 (push, %U1%<);
2501 OUT_AS1 (push, %T1%<);
2502 OUT_AS1 (push, %S1%<);
2503 OUT_AS1 (push, %Z0%<);
2504 OUT_AS1 (push, %Y0%<);
2505 OUT_AS1 (push, %X0%<);
2506 OUT_AS1 (push, %W0%<);
2507 OUT_AS1 (push, %V0%<);
2508 OUT_AS1 (push, %U0%<);
2509 OUT_AS1 (push, %T0%<);
2510 OUT_AS1 (push, %S0%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>);
2511 OUT_AS1 (page, __cmpdi2);
2512 OUT_AS1 (call, __cmpdi2);
2513 OUT_AS2 (csne, w, #1);
2522 s = (const_high >> 24) & 0xff;
2523 t = (const_high >> 16) & 0xff;
2524 u = (const_high >> 8) & 0xff;
2525 v = const_high & 0xff;
2526 w = (const_low >> 24) & 0xff;
2527 x = (const_low >> 16) & 0xff;
2528 y = (const_low >> 8) & 0xff;
2529 z = const_low & 0xff;
2532 OUT_AS2 (mov, w, %S1);
2533 if (imm_cmp && (s == t))
2535 OUT_AS2 (csne, w, %S0);
2536 OUT_AS2 (cse, w, %T0);
2540 OUT_AS2 (cse, w, %S0);
2543 OUT_AS2 (mov, w, %T1);
2544 OUT_AS2 (cse, w, %T0);
2549 OUT_AS2 (mov, w, %U1);
2550 if (imm_cmp && (u == v))
2552 OUT_AS2 (csne, w, %U0);
2553 OUT_AS2 (cse, w, %V0);
2557 OUT_AS2 (cse, w, %U0);
2560 OUT_AS2 (mov, w, %V1);
2561 OUT_AS2 (cse, w, %V0);
2566 OUT_AS2 (mov, w, %W1);
2567 if (imm_cmp && (w == x))
2569 OUT_AS2 (csne, w, %W0);
2570 OUT_AS2 (cse, w, %X0);
2574 OUT_AS2 (cse, w, %W0);
2577 OUT_AS2 (mov, w, %X1);
2578 OUT_AS2 (cse, w, %X0);
2583 if (! imm_cmp || (x != y))
2584 OUT_AS2 (mov, w, %Y1);
2585 OUT_AS2 (cse, w, %Y0);
2588 if (! imm_cmp || (z != y))
2589 OUT_AS2 (mov, w, %Z1);
2590 OUT_AS2 (csne, w, %Z0);
2600 unsigned char s = 0, t = 1, u = 2, v = 3;
2601 unsigned char w = 4, x = 5, y = 6, z = 7;
2605 if (GET_CODE (operands[0]) == MEM
2606 && true_regnum (XEXP (operands[0], 0)) == REG_DP)
2608 OUT_AS1 (push, %Z1%<);
2609 OUT_AS1 (push, %Y1%<);
2610 OUT_AS1 (push, %X1%<);
2611 OUT_AS1 (push, %W1%<);
2612 OUT_AS1 (push, %V1%<);
2613 OUT_AS1 (push, %U1%<);
2614 OUT_AS1 (push, %T1%<);
2615 OUT_AS1 (push, %S1%>%>%>%>%>%>%>);
2616 OUT_AS1 (page, __cmpdi2_dp);
2617 OUT_AS1 (call, __cmpdi2_dp);
2618 OUT_AS2 (cse, w, #1);
2624 OUT_AS1 (push, %Z1%<);
2625 OUT_AS1 (push, %Y1%<);
2626 OUT_AS1 (push, %X1%<);
2627 OUT_AS1 (push, %W1%<);
2628 OUT_AS1 (push, %V1%<);
2629 OUT_AS1 (push, %U1%<);
2630 OUT_AS1 (push, %T1%<);
2631 OUT_AS1 (push, %S1%<);
2632 OUT_AS1 (push, %Z0%<);
2633 OUT_AS1 (push, %Y0%<);
2634 OUT_AS1 (push, %X0%<);
2635 OUT_AS1 (push, %W0%<);
2636 OUT_AS1 (push, %V0%<);
2637 OUT_AS1 (push, %U0%<);
2638 OUT_AS1 (push, %T0%<);
2639 OUT_AS1 (push, %S0%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>);
2640 OUT_AS1 (page, __cmpdi2);
2641 OUT_AS1 (call, __cmpdi2);
2642 OUT_AS2 (cse, w, #1);
2651 s = (const_high >> 24) & 0xff;
2652 t = (const_high >> 16) & 0xff;
2653 u = (const_high >> 8) & 0xff;
2654 v = const_high & 0xff;
2655 w = (const_low >> 24) & 0xff;
2656 x = (const_low >> 16) & 0xff;
2657 y = (const_low >> 8) & 0xff;
2658 z = const_low & 0xff;
2661 OUT_AS2 (mov, w, %S1);
2662 if (imm_cmp && (s == t))
2664 OUT_AS2 (csne, w, %S0);
2665 OUT_AS2 (cse, w, %T0);
2669 OUT_AS2 (cse, w, %S0);
2672 OUT_AS2 (mov, w, %T1);
2673 OUT_AS2 (cse, w, %T0);
2678 OUT_AS2 (mov, w, %U1);
2679 if (imm_cmp && (u == v))
2681 OUT_AS2 (csne, w, %U0);
2682 OUT_AS2 (cse, w, %V0);
2686 OUT_AS2 (cse, w, %U0);
2689 OUT_AS2 (mov, w, %V1);
2690 OUT_AS2 (cse, w, %V0);
2695 OUT_AS2 (mov, w, %W1);
2696 if (imm_cmp && (w == x))
2698 OUT_AS2 (csne, w, %W0);
2699 OUT_AS2 (cse, w, %X0);
2703 OUT_AS2 (cse, w, %W0);
2706 OUT_AS2 (mov, w, %X1);
2707 OUT_AS2 (cse, w, %X0);
2712 if (! imm_cmp || (y != x))
2713 OUT_AS2 (mov, w, %Y1);
2714 if (imm_cmp && (z == y))
2716 OUT_AS2 (csne, w, %Y0);
2717 OUT_AS2 (cse, w, %Z0);
2721 OUT_AS2 (cse, w, %Y0);
2724 OUT_AS2 (mov, w, %Z1);
2725 OUT_AS2 (cse, w, %Z0);
2736 /* > 0xffffffffffffffff never succeeds! */
2737 if (((const_high & 0xffffffff) != 0xffffffff)
2738 || ((const_low & 0xffffffff) != 0xffffffff))
2740 operands[3] = GEN_INT (const_low + 1);
2741 operands[4] = GEN_INT (const_high
2742 + (INTVAL (operands[3]) ? 0 : 1));
2743 OUT_AS2 (mov, w, %D3);
2744 OUT_AS2 (sub, w, %Z0);
2745 OUT_AS2 (mov, w, %C3);
2746 OUT_AS2 (subc, w, %Y0);
2747 OUT_AS2 (mov, w, %B3);
2748 OUT_AS2 (subc, w, %X0);
2749 OUT_AS2 (mov, w, %A3);
2750 OUT_AS2 (subc, w, %W0);
2751 OUT_AS2 (mov, w, %D4);
2752 OUT_AS2 (subc, w, %V0);
2753 OUT_AS2 (mov, w, %C4);
2754 OUT_AS2 (subc, w, %U0);
2755 OUT_AS2 (mov, w, %B4);
2756 OUT_AS2 (subc, w, %T0);
2757 OUT_AS2 (mov, w, %A4);
2758 OUT_AS2 (subc, w, %S0);
2766 OUT_AS2 (mov, w, %Z0);
2767 OUT_AS2 (sub, w, %Z1);
2768 OUT_AS2 (mov, w, %Y0);
2769 OUT_AS2 (subc, w, %Y1);
2770 OUT_AS2 (mov, w, %X0);
2771 OUT_AS2 (subc, w, %X1);
2772 OUT_AS2 (mov, w, %W0);
2773 OUT_AS2 (subc, w, %W1);
2774 OUT_AS2 (mov, w, %V0);
2775 OUT_AS2 (subc, w, %V1);
2776 OUT_AS2 (mov, w, %U0);
2777 OUT_AS2 (subc, w, %U1);
2778 OUT_AS2 (mov, w, %T0);
2779 OUT_AS2 (subc, w, %T1);
2780 OUT_AS2 (mov, w, %S0);
2781 OUT_AS2 (subc, w, %S1);
2791 HOST_WIDE_INT const_low0;
2792 HOST_WIDE_INT const_high0;
2794 if (GET_CODE (operands[0]) == CONST_INT)
2796 const_low0 = INTVAL (operands[0]);
2797 const_high0 = (const_low >= 0) - 1;
2799 else if (GET_CODE (operands[0]) == CONST_DOUBLE)
2801 const_low0 = CONST_DOUBLE_LOW (operands[0]);
2802 const_high0 = CONST_DOUBLE_HIGH (operands[0]);
2805 if (const_high0 == 0 && const_low0 == 0)
2807 OUT_AS2 (mov, w, %S1);
2808 OUT_AS2 (or, w, %T1);
2809 OUT_AS2 (or, w, %U1);
2810 OUT_AS2 (or, w, %V1);
2811 OUT_AS2 (or, w, %W1);
2812 OUT_AS2 (or, w, %X1);
2813 OUT_AS2 (or, w, %Y1);
2814 OUT_AS2 (or, w, %Z1);
2821 operands[3] = GEN_INT (const_low0 - 1);
2822 operands[4] = GEN_INT (const_high0 - (const_low0 ? 1 : 0));
2823 OUT_AS2 (mov, w, %D3);
2824 OUT_AS2 (sub, w, %Z1);
2825 OUT_AS2 (mov, w, %C3);
2826 OUT_AS2 (subc, w, %Y1);
2827 OUT_AS2 (mov, w, %B3);
2828 OUT_AS2 (subc, w, %X1);
2829 OUT_AS2 (mov, w, %A3);
2830 OUT_AS2 (subc, w, %W1);
2831 OUT_AS2 (mov, w, %D4);
2832 OUT_AS2 (subc, w, %V1);
2833 OUT_AS2 (mov, w, %C4);
2834 OUT_AS2 (subc, w, %U1);
2835 OUT_AS2 (mov, w, %B4);
2836 OUT_AS2 (subc, w, %T1);
2837 OUT_AS2 (mov, w, %A4);
2838 OUT_AS2 (subc, w, %S1);
2846 OUT_AS2 (mov, w, %Z1);
2847 OUT_AS2 (sub, w, %Z0);
2848 OUT_AS2 (mov, w, %Y1);
2849 OUT_AS2 (subc, w, %Y0);
2850 OUT_AS2 (mov, w, %X1);
2851 OUT_AS2 (subc, w, %X0);
2852 OUT_AS2 (mov, w, %W1);
2853 OUT_AS2 (subc, w, %W0);
2854 OUT_AS2 (mov, w, %V1);
2855 OUT_AS2 (subc, w, %V0);
2856 OUT_AS2 (mov, w, %U1);
2857 OUT_AS2 (subc, w, %U0);
2858 OUT_AS2 (mov, w, %T1);
2859 OUT_AS2 (subc, w, %T0);
2860 OUT_AS2 (mov, w, %S1);
2861 OUT_AS2 (subc, w, %S0);
2871 HOST_WIDE_INT const_low0;
2872 HOST_WIDE_INT const_high0;
2874 if (GET_CODE (operands[0]) == CONST_INT)
2876 const_low0 = INTVAL (operands[0]);
2877 const_high0 = (const_low >= 0) - 1;
2879 else if (GET_CODE (operands[0]) == CONST_DOUBLE)
2881 const_low0 = CONST_DOUBLE_LOW (operands[0]);
2882 const_high0 = CONST_DOUBLE_HIGH (operands[0]);
2885 if (const_high0 == 0 && const_low0 == 0)
2887 OUT_AS2 (mov, w, %S1);
2888 OUT_AS2 (or, w, %T1);
2889 OUT_AS2 (or, w, %U1);
2890 OUT_AS2 (or, w, %V1);
2891 OUT_AS2 (or, w, %W1);
2892 OUT_AS2 (or, w, %X1);
2893 OUT_AS2 (or, w, %Y1);
2894 OUT_AS2 (or, w, %Z1);
2901 operands[3] = GEN_INT (const_low0 - 1);
2902 operands[4] = GEN_INT (const_high0 - (const_low0 ? 1 : 0));
2903 OUT_AS2 (mov, w, %D3);
2904 OUT_AS2 (sub, w, %Z1);
2905 OUT_AS2 (mov, w, %C3);
2906 OUT_AS2 (subc, w, %Y1);
2907 OUT_AS2 (mov, w, %B3);
2908 OUT_AS2 (subc, w, %X1);
2909 OUT_AS2 (mov, w, %A3);
2910 OUT_AS2 (subc, w, %W1);
2911 OUT_AS2 (mov, w, %D4);
2912 OUT_AS2 (subc, w, %V1);
2913 OUT_AS2 (mov, w, %C4);
2914 OUT_AS2 (subc, w, %U1);
2915 OUT_AS2 (mov, w, %B4);
2916 OUT_AS2 (subc, w, %T1);
2917 OUT_AS2 (mov, w, %A4);
2918 OUT_AS2 (subc, w, %S1);
2926 OUT_AS2 (mov, w, %Z1);
2927 OUT_AS2 (sub, w, %Z0);
2928 OUT_AS2 (mov, w, %Y1);
2929 OUT_AS2 (subc, w, %Y0);
2930 OUT_AS2 (mov, w, %X1);
2931 OUT_AS2 (subc, w, %X0);
2932 OUT_AS2 (mov, w, %W1);
2933 OUT_AS2 (subc, w, %W0);
2934 OUT_AS2 (mov, w, %V1);
2935 OUT_AS2 (subc, w, %V0);
2936 OUT_AS2 (mov, w, %U1);
2937 OUT_AS2 (subc, w, %U0);
2938 OUT_AS2 (mov, w, %T1);
2939 OUT_AS2 (subc, w, %T0);
2940 OUT_AS2 (mov, w, %S1);
2941 OUT_AS2 (subc, w, %S0);
2951 if (((const_high & 0xffffffff) == 0xffffffff)
2952 && ((const_low & 0xffffffff) == 0xffffffff))
2954 /* <= 0xffffffffffffffff always succeeds. */
2960 operands[3] = GEN_INT (const_low + 1);
2961 operands[4] = GEN_INT (const_high
2962 + (INTVAL (operands[3]) ? 0 : 1));
2963 OUT_AS2 (mov, w, %D3);
2964 OUT_AS2 (sub, w, %Z0);
2965 OUT_AS2 (mov, w, %C3);
2966 OUT_AS2 (subc, w, %Y0);
2967 OUT_AS2 (mov, w, %B3);
2968 OUT_AS2 (subc, w, %X0);
2969 OUT_AS2 (mov, w, %A3);
2970 OUT_AS2 (subc, w, %W0);
2971 OUT_AS2 (mov, w, %D4);
2972 OUT_AS2 (subc, w, %V0);
2973 OUT_AS2 (mov, w, %C4);
2974 OUT_AS2 (subc, w, %U0);
2975 OUT_AS2 (mov, w, %B4);
2976 OUT_AS2 (subc, w, %T0);
2977 OUT_AS2 (mov, w, %A4);
2978 OUT_AS2 (subc, w, %S0);
2986 OUT_AS2 (mov, w, %Z0);
2987 OUT_AS2 (sub, w, %Z1);
2988 OUT_AS2 (mov, w, %Y0);
2989 OUT_AS2 (subc, w, %Y1);
2990 OUT_AS2 (mov, w, %X0);
2991 OUT_AS2 (subc, w, %X1);
2992 OUT_AS2 (mov, w, %W0);
2993 OUT_AS2 (subc, w, %W1);
2994 OUT_AS2 (mov, w, %V0);
2995 OUT_AS2 (subc, w, %V1);
2996 OUT_AS2 (mov, w, %U0);
2997 OUT_AS2 (subc, w, %U1);
2998 OUT_AS2 (mov, w, %T0);
2999 OUT_AS2 (subc, w, %T1);
3000 OUT_AS2 (mov, w, %S0);
3001 OUT_AS2 (subc, w, %S1);
3020 /* Output rtx VALUE as .byte to file FILE. */
3023 asm_output_char (FILE *file, rtx value)
3025 fprintf (file, "\t.byte ");
3026 output_addr_const (file, value);
3027 fprintf (file, "\n");
3031 /* Output VALUE as .byte to file FILE. */
3034 asm_output_byte (FILE *file, int value)
3036 fprintf (file, "\t.byte 0x%x\n",value & 0xff);
3040 /* Output rtx VALUE as .word to file FILE. */
3043 asm_output_short (FILE *file, rtx value)
3045 fprintf (file, "\t.word ");
3046 output_addr_const (file, (value));
3047 fprintf (file, "\n");
3051 /* Output real N to file FILE. */
3054 asm_output_float (FILE *file, REAL_VALUE_TYPE n)
3059 REAL_VALUE_TO_TARGET_SINGLE (n, val);
3060 real_to_decimal (dstr, &n, sizeof (dstr), 0, 1);
3062 fprintf (file, "\t.long 0x%08lx\t/* %s */\n", val, dstr);
3065 /* Sets section name for declaration DECL. */
3068 unique_section (tree decl, int reloc ATTRIBUTE_UNUSED)
3074 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
3075 /* Strip off any encoding in name. */
3076 name = (* targetm.strip_name_encoding) (name);
3078 if (TREE_CODE (decl) == FUNCTION_DECL)
3080 if (flag_function_sections)
3088 if (flag_function_sections)
3090 len = strlen (name) + strlen (prefix);
3091 string = alloca (len + 1);
3092 sprintf (string, "%s%s", prefix, name);
3093 DECL_SECTION_NAME (decl) = build_string (len, string);
3097 /* Return value is nonzero if pseudos that have been
3098 assigned to registers of class CLASS would likely be spilled
3099 because registers of CLASS are needed for spill registers. */
3102 class_likely_spilled_p (int c)
3104 return (c == IP_REGS
3115 /* Valid attributes:
3116 progmem - put data to program memory;
3117 naked - don't generate function prologue/epilogue and `ret' command.
3119 Only `progmem' attribute valid for type. */
3121 const struct attribute_spec ip2k_attribute_table[] =
3123 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
3124 { "progmem", 0, 0, false, false, false, ip2k_handle_progmem_attribute },
3125 { "naked", 0, 0, true, false, false, ip2k_handle_fndecl_attribute },
3126 { NULL, 0, 0, false, false, false, NULL }
3129 /* Handle a "progmem" attribute; arguments as in
3130 struct attribute_spec.handler. */
3132 ip2k_handle_progmem_attribute (tree *node, tree name,
3133 tree args ATTRIBUTE_UNUSED,
3134 int flags ATTRIBUTE_UNUSED,
3139 if (TREE_CODE (*node) == TYPE_DECL)
3141 /* This is really a decl attribute, not a type attribute,
3142 but try to handle it for GCC 3.0 backwards compatibility. */
3144 tree type = TREE_TYPE (*node);
3145 tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
3146 tree newtype = build_type_attribute_variant (type, attr);
3148 TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
3149 TREE_TYPE (*node) = newtype;
3150 *no_add_attrs = true;
3152 else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
3154 if (DECL_INITIAL (*node) == NULL_TREE && !DECL_EXTERNAL (*node))
3156 warning ("only initialized variables can be placed into "
3157 "program memory area");
3158 *no_add_attrs = true;
3163 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
3164 *no_add_attrs = true;
3171 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
3172 struct attribute_spec.handler. */
3174 ip2k_handle_fndecl_attribute (tree *node, tree name,
3175 tree args ATTRIBUTE_UNUSED,
3176 int flags ATTRIBUTE_UNUSED,
3179 if (TREE_CODE (*node) != FUNCTION_DECL)
3181 warning ("`%s' attribute only applies to functions",
3182 IDENTIFIER_POINTER (name));
3183 *no_add_attrs = true;
3189 /* Cost functions. */
3191 /* Compute a (partial) cost for rtx X. Return true if the complete
3192 cost has been computed, and false if subexpressions should be
3193 scanned. In either case, *TOTAL contains the cost result. */
3196 ip2k_rtx_costs (rtx x, int code, int outer_code, int *total)
3198 enum machine_mode mode = GET_MODE (x);
3214 *total = ip2k_address_cost (XEXP (x, 0));
3222 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
3224 int val = INTVAL (XEXP (x, 1));
3227 /* Shift by const instructions are proportional to
3228 the shift count modulus 8. Note that we increase the mode
3229 size multiplier by 1 to account for clearing the carry flag. */
3230 cost = COSTS_N_INSNS (abs (val) % 8);
3231 cost += rtx_cost (XEXP (x, 0), code);
3232 cost *= (GET_MODE_SIZE (mode) + 1);
3234 /* Sign-preserving shifts require 2 extra instructions. */
3236 cost += COSTS_N_INSNS (2);
3241 *total = rtx_cost (XEXP (x, 0), code);
3242 *total += COSTS_N_INSNS (GET_MODE_SIZE (mode) * 8);
3250 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) * 3);
3256 *total = COSTS_N_INSNS (20);
3257 else if (mode == HImode)
3258 *total = COSTS_N_INSNS (60);
3259 else if (mode == SImode)
3260 *total = COSTS_N_INSNS (180);
3262 *total = COSTS_N_INSNS (540);
3266 /* These costs are OK, but should really handle subtle cases
3267 where we're using sign or zero extended args as these are
3268 *much* cheaper than those given below! */
3270 *total = COSTS_N_INSNS (4);
3271 else if (mode == HImode)
3272 *total = COSTS_N_INSNS (12);
3273 else if (mode == SImode)
3274 *total = COSTS_N_INSNS (36);
3276 *total = COSTS_N_INSNS (108);
3281 extra_cost = COSTS_N_INSNS (GET_MODE_SIZE (mode));
3287 *total = extra_cost + COSTS_N_INSNS (GET_MODE_SIZE (mode) * 2);
3292 if (outer_code == SET)
3294 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) * 3 / 2);
3299 *total = -(COSTS_N_INSNS (GET_MODE_SIZE (mode)) / 2);
3304 *total = rtx_cost (XEXP (x, 0), code) + COSTS_N_INSNS (2);
3321 *total = COSTS_N_INSNS (4);
3326 /* Calculate the cost of a memory address. */
3329 ip2k_address_cost (rtx x)
3331 switch (legitimate_address_p (VOIDmode, x, 0))
3333 case 'S': /* Very low cost - (IP), (SP+N) or (DP+N) */
3336 case 'R': /* Indirected through IP. */
3339 case 'L': /* Label references. */
3342 case 'C': /* Constants and symbol references. */
3346 return 1000; /* Must reload. */
3350 /* As part of the machine-dependent reorg we look for opcode sequences where
3351 we do some operation and then move the results back to one of the original
3352 source operands. With working on the source operand directly is probably
3353 much cheaper and the move from this to the original source operand will be
3354 no more expensive than the original move. */
3356 #ifdef IP2K_MD_REORG_PASS
3358 mdr_resequence_xy_yx (first_insn)
3363 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
3367 if (GET_CODE (insn) != INSN)
3370 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
3371 if (set == NULL_RTX)
3374 /* Look for operations that tend to be very cheap to run when the source
3375 * and dest args are the same because the IP2022 has opcodes that can
3376 operate on the source directly. If we have to spill through the W
3377 register then we've possibly not got a good case for doing this. */
3378 if ((GET_CODE (XEXP (set, 0)) == REG
3379 || GET_CODE (XEXP (set, 0)) == MEM)
3380 && (GET_CODE (XEXP (set, 1)) == ASHIFT
3381 || GET_CODE (XEXP (set, 1)) == ASHIFTRT
3382 || GET_CODE (XEXP (set, 1)) == LSHIFTRT
3383 || GET_CODE (XEXP (set, 1)) == XOR
3384 || GET_CODE (XEXP (set, 1)) == IOR
3385 || GET_CODE (XEXP (set, 1)) == AND
3386 || GET_CODE (XEXP (set, 1)) == PLUS
3387 || GET_CODE (XEXP (set, 1)) == MINUS
3388 || GET_CODE (XEXP (set, 1)) == MULT))
3393 next_insn = next_nonnote_insn (insn);
3397 if (GET_CODE (next_insn) != INSN)
3400 set2 = ((GET_CODE (PATTERN (next_insn)) == SET)
3401 ? PATTERN (next_insn) : NULL_RTX);
3402 if (set2 == NULL_RTX)
3405 if ((GET_CODE (XEXP (XEXP (set, 1), 0)) == REG
3406 || GET_CODE (XEXP (XEXP (set, 1), 0)) == MEM)
3407 && rtx_equal_p (XEXP (set2, 0), XEXP (XEXP (set, 1), 0))
3408 && rtx_equal_p (XEXP (set2, 1), XEXP (set, 0)))
3413 b_insn = gen_rtx_SET (VOIDmode,
3414 XEXP (XEXP (set, 1), 0),
3415 gen_rtx_fmt_ee (GET_CODE (XEXP (set, 1)),
3416 GET_MODE (XEXP (set, 0)),
3417 XEXP (XEXP (set, 1), 0),
3418 XEXP (XEXP (set, 1), 1)));
3420 emit_insn_before (b_insn, insn);
3421 b_insn = gen_rtx_SET (GET_MODE (XEXP (set, 0)), XEXP (set, 0),
3422 XEXP (XEXP (set, 1), 0));
3423 next2_insn = emit_insn_before (b_insn, insn);
3425 delete_insn (next_insn);
3430 /* Having tried with one operand of the expression, now, if
3431 appropriate, try to do the same thing with the second operand.
3432 Of course there are fewer operations that can match here
3433 because they must be commutative. */
3434 if (GET_RTX_CLASS (GET_CODE (XEXP (set, 1))) == RTX_COMM_ARITH
3435 && (GET_CODE (XEXP (XEXP (set, 1), 1)) == REG
3436 || GET_CODE (XEXP (XEXP (set, 1), 1)) == MEM)
3437 && rtx_equal_p (XEXP (set2, 0), XEXP (XEXP (set, 1), 1))
3438 && rtx_equal_p (XEXP (set2, 1), XEXP (set, 0)))
3444 /* Try to ensure that we put things in a canonical form. */
3445 swap_args = (GET_CODE (XEXP (XEXP (set, 1), 0)) == REG
3446 || GET_CODE (XEXP (XEXP (set, 1), 0)) == MEM);
3447 rtx_ee = gen_rtx_fmt_ee (GET_CODE (XEXP (set, 1)),
3448 GET_MODE (XEXP (set, 0)),
3449 XEXP (XEXP (set, 1), swap_args ? 1 : 0),
3450 XEXP (XEXP (set, 1),
3451 swap_args ? 0 : 1));
3453 emit_insn_before (gen_rtx_SET (VOIDmode,
3454 XEXP (XEXP (set, 1), 1),
3457 next2_insn = emit_insn_before (gen_rtx_SET
3458 (GET_MODE (XEXP (set, 0)),
3460 XEXP (XEXP (set, 1), 1)),
3463 delete_insn (next_insn);
3470 /* Replace and recurse until we've tried QImode pieces! */
3473 mdr_pres_replace_and_recurse (orig, with, insn)
3478 enum machine_mode new_mode;
3480 validate_replace_rtx (orig, with, insn);
3482 switch (GET_MODE (orig))
3502 mdr_pres_replace_and_recurse (ip2k_get_low_half (orig, new_mode),
3503 ip2k_get_low_half (with, new_mode),
3505 mdr_pres_replace_and_recurse (ip2k_get_high_half (orig, new_mode),
3506 ip2k_get_high_half (with, new_mode),
3510 /* Assist the following function, mdr_propagate_reg_equivs(). */
3513 mdr_propagate_reg_equivs_sequence (first_insn, orig, equiv)
3519 rtx try_equiv = equiv;
3521 /* First scan the RTL looking for anything else that might clobber what
3522 we're doing. If we find anything then we can't do the replacement. */
3523 for (try_insn = next_nonnote_insn (first_insn);
3524 try_insn; try_insn = next_nonnote_insn (try_insn))
3528 if (GET_CODE (try_insn) != JUMP_INSN && GET_CODE (try_insn) != INSN)
3531 pattern = PATTERN (try_insn);
3532 if (GET_CODE (pattern) == PARALLEL)
3536 for (j = 0; j < XVECLEN (pattern, 0); j++)
3538 rtx px = XVECEXP (pattern, 0, j);
3540 if (GET_CODE (px) == SET)
3541 if (! ip2k_composite_xexp_not_uses_reg_p (XEXP (px, 0),
3543 GET_MODE_SIZE (GET_MODE (orig))))
3547 else if (GET_CODE (pattern) == SET)
3549 if (! ip2k_composite_xexp_not_uses_reg_p (XEXP (pattern, 0),
3551 GET_MODE_SIZE (GET_MODE (orig))))
3556 /* Once we've decided that we're safe to do the replacement then make the
3558 for (try_insn = next_nonnote_insn (first_insn); try_insn;
3559 try_insn = next_nonnote_insn (try_insn))
3562 rtx new_equiv = NULL_RTX;
3564 if (GET_CODE (try_insn) != JUMP_INSN && GET_CODE (try_insn) != INSN)
3570 set = ((GET_CODE (PATTERN (try_insn)) == SET)
3571 ? PATTERN (try_insn) : NULL_RTX);
3572 if (set == NULL_RTX)
3575 /* We look for a special case of "push" operations screwing our
3576 register equivalence when it's based on a stack slot. We can
3577 track this one and replace the old equivalence expression with
3579 if (GET_CODE (XEXP (set, 0)) == MEM
3580 && GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC
3581 && REG_P (XEXP (XEXP (XEXP (set, 0), 0), 0))
3582 && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP)
3584 /* XXX - need to ensure that we can track this without going
3586 HOST_WIDE_INT disp = (INTVAL (XEXP (XEXP (try_equiv, 0), 1))
3587 + GET_MODE_SIZE (GET_MODE (XEXP (set, 0))));
3588 new_equiv = gen_rtx_MEM (GET_MODE (try_equiv),
3589 gen_rtx_PLUS (Pmode,
3590 gen_rtx_REG (HImode, REG_SP),
3594 /* The replacement process is somewhat complicated by the fact that we
3595 might be dealing with what were originally subregs and thus we have
3596 to replace parts of our original expression! */
3597 mdr_pres_replace_and_recurse (orig, try_equiv, try_insn);
3599 if (new_equiv != NULL_RTX)
3600 try_equiv = new_equiv;
3604 /* Try propagating register equivalences forwards. It may be that we can
3605 replace a register use with an equivalent expression that already
3606 holds the same value and thus allow one or more register loads to
3610 mdr_propagate_reg_equivs (first_insn)
3616 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
3618 if (GET_CODE (insn) != INSN)
3621 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
3622 if (set == NULL_RTX)
3625 /* Have we found a stack slot equivalence for a register? */
3626 if (REG_P (XEXP (set, 0))
3627 && REGNO (XEXP (set, 0)) >= 0x88
3628 && GET_CODE (XEXP (set, 1)) == MEM
3629 && GET_CODE (XEXP (XEXP (set, 1), 0)) == PLUS
3630 && REG_P (XEXP (XEXP (XEXP (set, 1), 0), 0))
3631 && REGNO (XEXP (XEXP (XEXP (set, 1), 0), 0)) == REG_SP
3632 && find_reg_note (insn, REG_EQUIV, NULL_RTX))
3634 mdr_propagate_reg_equivs_sequence (insn, XEXP (set, 0),
3640 /* Structure used to track jump targets. */
3642 struct dpre_jump_targets
3644 int target; /* Is this a jump target? */
3645 int reach_count; /* Number of ways we can reach this insn. */
3646 int touch_count; /* Number of times we've touched this
3647 insns during scanning. */
3648 rtx dp_equiv; /* DP-equivalence at this point. */
3651 struct dpre_jump_targets *ip2k_dpre_jump_targets;
3653 /* DP equivalence tracking used within DP reload elimination. */
3656 track_dp_reload (insn, dp_current, dp_current_ok, modifying)
3664 if (GET_CODE (insn) != INSN)
3666 *dp_current = NULL_RTX;
3670 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
3671 if (set == NULL_RTX)
3673 *dp_current = NULL_RTX;
3677 /* If we're pushing a PLUS or MINUS then it's a win if we can replace
3678 an expression for which DP is equivalent with DP. This happens
3679 surprisingly often when we pass a pointer to a structure embedded
3680 within another structure. */
3681 if (*dp_current != NULL_RTX
3682 && GET_CODE (XEXP (set, 0)) == MEM
3683 && GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC
3684 && GET_CODE (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG
3685 && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP
3686 && (GET_CODE (XEXP (set, 1)) == PLUS
3687 || GET_CODE (XEXP (set, 1)) == MINUS)
3688 && GET_CODE (*dp_current) != SYMBOL_REF
3689 && GET_CODE (*dp_current) != LABEL_REF
3690 && GET_CODE (*dp_current) != CONST)
3693 validate_replace_rtx (*dp_current, gen_rtx_REG (HImode, REG_DP), insn);
3696 /* Look for DP being modified. If it is, see if it's being changed
3697 to what it already is! */
3698 if (GET_CODE (XEXP (set, 0)) == REG
3699 && REGNO (XEXP (set, 0)) == REG_DP
3700 && GET_MODE (XEXP (set, 0)) == HImode)
3702 /* If this is an equivalence we can delete the new set operation. */
3703 if (*dp_current != NULL_RTX
3704 && rtx_equal_p (XEXP (set, 1), *dp_current))
3711 /* If we've not found an equivalence we can look for a special
3712 case where an operand of the expression that sets DP is
3713 already equivalent to DP and in that circumstance we simplify
3714 by replacing that expression with DP. */
3715 if (*dp_current != NULL_RTX
3716 && GET_CODE (*dp_current) != SYMBOL_REF
3717 && GET_CODE (*dp_current) != LABEL_REF
3718 && GET_CODE (*dp_current) != CONST
3720 validate_replace_rtx (*dp_current, XEXP (set, 0), insn);
3722 /* Assuming that we're not loading DP from something that uses DP
3723 itself then we mark the new equivalence for DP. If we did match
3724 DP then we can't re-use this one. */
3725 if (ip2k_xexp_not_uses_reg_p (XEXP (set, 1), REG_DP, 2))
3727 *dp_current = XEXP (set, 1);
3732 *dp_current = NULL_RTX;
3737 else if (GET_CODE (XEXP (set, 0)) == REG
3738 && (REGNO (XEXP (set, 0)) == REG_DPL
3739 || REGNO (XEXP (set, 0)) == REG_DPH))
3741 /* If we clobber part of DP then we've clobbered any equivalences! */
3742 *dp_current = NULL_RTX;
3745 else if (! ip2k_xexp_not_uses_reg_p (XEXP (set, 0), REG_SP, 2)
3746 && *dp_current != NULL_RTX
3747 && !ip2k_xexp_not_uses_reg_p (*dp_current, REG_SP, 2))
3749 /* We look for a special case of "push" operations screwing up the
3750 setting of DP when it's based on the stack. We can track this one
3751 and replace the old expression for DP with a new one. */
3752 if (GET_CODE (XEXP (set, 0)) == MEM
3753 && GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC
3754 && GET_CODE (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG
3755 && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP
3756 && GET_CODE (*dp_current) == MEM
3757 && GET_CODE (XEXP (*dp_current, 0)) == PLUS)
3759 /* XXX - need to ensure that we can track this without going
3761 HOST_WIDE_INT disp = (INTVAL (XEXP (XEXP (*dp_current, 0), 1))
3762 + GET_MODE_SIZE (GET_MODE (XEXP (set, 0))));
3763 *dp_current = gen_rtx_MEM (HImode,
3764 gen_rtx_PLUS (Pmode,
3765 gen_rtx_REG (HImode, REG_SP),
3770 /* Now we look for writes to the stack. We can determine if these will
3771 affect the equivalence we're tracking for DP and if not then we can
3772 keep tracking it. */
3773 if (GET_CODE (XEXP (set, 0)) == MEM
3774 && GET_CODE (*dp_current) == MEM)
3776 /* Look at the SP offsets and look for any overlaps. */
3777 int dp_cur_sp_offs = INTVAL (XEXP (XEXP (*dp_current, 0), 1));
3778 int set_sp_offs = INTVAL (XEXP (XEXP (XEXP (set, 0), 0), 1));
3780 if (abs (dp_cur_sp_offs - set_sp_offs) < 2)
3782 *dp_current = NULL_RTX;
3787 else if (GET_CODE (XEXP (set, 0)) == REG
3788 && *dp_current != NULL_RTX
3789 && !ip2k_xexp_not_uses_reg_p (*dp_current, REGNO (XEXP (set, 0)),
3790 GET_MODE_SIZE (GET_MODE (XEXP (set,
3793 /* If we've just clobbered all or part of a register reference that we
3794 were sharing for DP then we can't share it any more! */
3795 *dp_current = NULL_RTX;
3798 return dp_current_ok;
3801 /* As part of the machine-dependent reorg we scan loads and reloads of
3802 DP to see where any are redundant. This does happens because we
3803 are able to subsequently transform things in interesting ways. Sometimes
3804 gcc also does unnecessary reloads too so we try to eliminate these too. */
3807 mdr_try_dp_reload_elim (first_insn)
3811 struct dpre_jump_targets *djt;
3813 int incomplete_scan;
3814 int last_incomplete_scan;
3816 ip2k_dpre_jump_targets
3817 = (struct dpre_jump_targets *) xcalloc (get_max_uid (),
3818 sizeof (struct dpre_jump_targets));
3820 /* First we scan to build up a list of all CODE_LABEL insns and we work out
3821 how many different ways we can reach them. */
3822 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
3824 if (GET_CODE (insn) == CODE_LABEL)
3826 djt = &ip2k_dpre_jump_targets[INSN_UID (insn)];
3828 djt->reach_count = LABEL_NUSES (insn);
3829 djt->touch_count = 0;
3830 djt->dp_equiv = NULL_RTX;
3831 if (! prev_nonnote_insn (insn)
3832 || (prev_nonnote_insn (insn)
3833 && GET_CODE (prev_nonnote_insn (insn)) != BARRIER))
3838 /* Next we scan all of the ways of reaching the code labels to see
3839 what the DP register is equivalent to as we reach them. If we find
3840 that they're the same then we keep noting the matched value. We
3841 iterate around this until we reach a convergence on DP equivalences
3842 at all code labels - we have to be very careful not to be too
3844 incomplete_scan = -1;
3847 int dp_current_ok = 0;
3848 last_incomplete_scan = incomplete_scan;
3849 dp_current = NULL_RTX;
3851 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
3853 /* If we have a code label then we need to see if we already know
3854 what the equivalence is at this point. If we do then we use it
3855 immediately, but if we don't then we have a special case to track
3856 when we hit a fallthrough-edge (label with no barrier preceding
3857 it). Any other accesses to the label must be from jump insns
3858 and so they're handled elsewhere. */
3859 if (GET_CODE (insn) == CODE_LABEL)
3861 djt = &ip2k_dpre_jump_targets[INSN_UID (insn)];
3863 /* If we're fully characterized the use the equivalence. */
3864 if (djt->touch_count == djt->reach_count)
3866 dp_current = djt->dp_equiv;
3871 /* If we have a known equivalence for DP as we reach the
3872 fallthrough-edge then track this into the code label. */
3874 && (! prev_nonnote_insn (insn)
3875 || (prev_nonnote_insn (insn)
3876 && GET_CODE (prev_nonnote_insn (insn)) != BARRIER)))
3878 if (djt->touch_count == 0)
3879 djt->dp_equiv = dp_current;
3881 if (djt->touch_count < djt->reach_count)
3884 if (! rtx_equal_p (djt->dp_equiv, dp_current))
3886 /* When we definitely know that we can't form an
3887 equivalence for DP here we must clobber anything
3888 that we'd started to track too. */
3889 djt->dp_equiv = NULL_RTX;
3890 dp_current = NULL_RTX;
3896 /* If we've not completely characterized this code label then
3897 be cautious and assume that we don't know what DP is
3899 if (djt->touch_count < djt->reach_count)
3901 dp_current = NULL_RTX;
3908 /* If we've hit a jump insn then we look for either an address
3909 vector (jump table) or for jump label references. */
3910 if (GET_CODE (insn) == JUMP_INSN)
3912 /* Don't attempt to track here if we don't have a known
3913 equivalence for DP at this point. */
3916 rtx pat = PATTERN (insn);
3917 if (GET_CODE (pat) == ADDR_VEC)
3920 int len = XVECLEN (pat, 0);
3922 for (i = 0; i < len; i++)
3924 rtx vec_insn = XEXP (XVECEXP (pat, 0, i), 0);
3925 djt = &ip2k_dpre_jump_targets [INSN_UID (vec_insn)];
3927 if (djt->touch_count == 0)
3928 djt->dp_equiv = dp_current;
3930 if (djt->touch_count < djt->reach_count)
3933 if (! rtx_equal_p (djt->dp_equiv, dp_current))
3934 djt->dp_equiv = NULL_RTX;
3938 else if (JUMP_LABEL (insn))
3940 rtx j_insn = JUMP_LABEL (insn);
3941 djt = &ip2k_dpre_jump_targets[INSN_UID (j_insn)];
3943 if (djt->touch_count == 0)
3944 djt->dp_equiv = dp_current;
3946 if (djt->touch_count < djt->reach_count)
3949 if (! rtx_equal_p (djt->dp_equiv, dp_current))
3950 djt->dp_equiv = NULL_RTX;
3958 /* Anything other than a code labal or jump arrives here.
3959 We try and track DP, but sometimes we might not be able to. */
3960 dp_current_ok = track_dp_reload (insn, &dp_current,
3964 /* When we're looking to see if we've finished we count the number of
3965 paths through the code labels where we weren't able to definitively
3967 This number is used to see if we're converging on a solution.
3968 If this hits zero then we've fully converged, but if this stays the
3969 same as last time then we probably can't make any further
3971 incomplete_scan = 0;
3972 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
3974 if (GET_CODE (insn) == CODE_LABEL)
3976 djt = &ip2k_dpre_jump_targets[INSN_UID (insn)];
3977 if (djt->touch_count != djt->reach_count)
3979 incomplete_scan += (djt->reach_count - djt->touch_count);
3980 djt->dp_equiv = NULL_RTX;
3981 djt->touch_count = 0;
3986 while (incomplete_scan && incomplete_scan != last_incomplete_scan);
3988 /* Finally we scan the whole function and run DP elimination. When we hit
3989 a CODE_LABEL we pick up any stored equivalence since we now know that
3990 every path to this point entered with DP holding the same thing! If
3991 we subsequently have a reload that matches then we can eliminate it. */
3992 dp_current = NULL_RTX;
3993 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
3995 if (GET_CODE (insn) == JUMP_INSN)
3998 if (GET_CODE (insn) == CODE_LABEL)
4000 djt = &ip2k_dpre_jump_targets[INSN_UID (insn)];
4001 dp_current = djt->dp_equiv;
4005 track_dp_reload (insn, &dp_current, 1, 1);
4008 free (ip2k_dpre_jump_targets);
4011 /* As part of the machine-dependent reorg we look for reloads of DP
4012 that we can move to earlier points within the file.
4013 Moving these out of the way allows more peepholes to match. */
4016 mdr_try_move_dp_reload (first_insn)
4023 /* Don't try to match the first instruction because we can't move it
4025 orig_first = first_insn;
4026 first_insn = next_nonnote_insn (first_insn);
4028 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
4030 if (GET_CODE (insn) != INSN)
4033 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
4034 if (set == NULL_RTX)
4037 /* Look for DP being loaded. When we find this we start a rewind
4038 scan looking for possible positions to move this to. */
4039 if (GET_CODE (XEXP (set, 0)) == REG
4040 && REGNO (XEXP (set, 0)) == REG_DP
4041 && GET_MODE (XEXP (set, 0)) == HImode)
4044 rtx try_insn = insn;
4053 /* For now we do the *really* simple version of things and only
4054 attempt to move the load of DP if it's very safe to do so. */
4055 rewind = prev_nonnote_insn (try_insn);
4056 if (rewind != orig_first && rewind != NULL_RTX
4057 && GET_CODE (rewind) == INSN)
4059 check = ((GET_CODE (PATTERN (rewind)) == SET)
4060 ? PATTERN (rewind) : NULL_RTX);
4061 if (check != NULL_RTX
4062 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (check, 0))
4063 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (check, 1)))
4065 if (GET_CODE (XEXP (check, 0)) == REG
4066 && REGNO (XEXP (check, 0)) != REG_DPH
4067 && REGNO (XEXP (check, 0)) != REG_DPL
4068 && (ip2k_composite_xexp_not_uses_reg_p
4069 (XEXP (check, 1), REG_DP, 2))
4070 && (ip2k_composite_xexp_not_uses_reg_p
4072 REGNO (XEXP (check, 0)),
4073 GET_MODE_SIZE (GET_MODE (XEXP (check, 0))))))
4075 emit_insn_before (set, rewind);
4076 if (try_insn == insn)
4077 insn = prev_nonnote_insn (insn);
4078 delete_insn (try_insn);
4079 try_insn = prev_nonnote_insn (rewind);
4082 else if (GET_CODE (XEXP (set, 1)) == REG
4083 && ip2k_composite_xexp_not_uses_reg_p (XEXP (check, 1), REG_DP, 2)
4084 && ip2k_composite_xexp_not_uses_reg_p (XEXP (check, 0), REG_DP, 2)
4085 && ip2k_composite_xexp_not_uses_reg_p (XEXP (check, 0), REGNO (XEXP (set, 1)),
4086 GET_MODE_SIZE (GET_MODE (XEXP (set, 1)))))
4088 emit_insn_before (set, rewind);
4089 if (try_insn == insn)
4090 insn = prev_nonnote_insn (insn);
4091 delete_insn (try_insn);
4092 try_insn = prev_nonnote_insn (rewind);
4098 while (try_again && try_insn);
4102 #endif /* IP2K_MD_REORG_PASS */
4104 /* Look to see if the expression, x, can have any stack references offset by
4105 a fixed constant, offset. If it definitely can then returns nonzero. */
4108 ip2k_check_can_adjust_stack_ref (rtx x, int offset)
4110 if (ARITHMETIC_P (x))
4111 return (ip2k_check_can_adjust_stack_ref (XEXP (x, 0), offset)
4112 && ip2k_check_can_adjust_stack_ref (XEXP (x, 1), offset));
4115 return ip2k_check_can_adjust_stack_ref (XEXP (x, 0), offset);
4117 switch (GET_CODE (x))
4120 return (REGNO (x) != REG_SPH && REGNO (x) != REG_SPL);
4123 if (GET_CODE (XEXP (x, 0)) != PLUS)
4126 if (GET_CODE (XEXP (XEXP (x, 0), 0)) != REG)
4129 if (REGNO (XEXP (XEXP (x, 0), 0)) != REG_SP)
4132 /* We can't allow this if the adjustment will create an
4134 return (INTVAL (XEXP (XEXP (x, 0), 1))
4135 + offset <= (128 - 2 * GET_MODE_SIZE (GET_MODE (x))));
4149 /* Adjusts all of the stack references in the expression pointed to by x by
4153 ip2k_adjust_stack_ref (rtx *x, int offset)
4155 if (ARITHMETIC_P (*x))
4157 ip2k_adjust_stack_ref (&XEXP (*x, 0), offset);
4158 ip2k_adjust_stack_ref (&XEXP (*x, 1), offset);
4164 ip2k_adjust_stack_ref (&XEXP (*x, 0), offset);
4168 switch (GET_CODE (*x))
4171 if (GET_CODE (XEXP (*x, 0)) != PLUS)
4174 if (GET_CODE (XEXP (XEXP (*x, 0), 0)) != REG)
4177 if (REGNO (XEXP (XEXP (*x, 0), 0)) != REG_SP)
4181 XEXP (XEXP (*x, 0), 1) = GEN_INT (INTVAL (XEXP (XEXP (*x, 0), 1))
4190 #ifdef IP2K_MD_REORG_PASS
4191 /* As part of the machine-dependent reorg we look to move push instructions
4192 to earlier points within the file. Moving these out of the way allows more
4193 peepholes to match. */
4196 mdr_try_move_pushes (first_insn)
4203 /* Don't try to match the first instruction because we can't move
4205 orig_first = first_insn;
4206 first_insn = next_nonnote_insn (first_insn);
4208 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
4210 if (GET_CODE (insn) != INSN)
4213 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
4214 if (set == NULL_RTX)
4217 /* Have we found a push instruction? */
4218 if (GET_CODE (XEXP (set, 0)) == MEM
4219 && GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC
4220 && GET_CODE (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG
4221 && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP
4222 && GET_CODE (XEXP (set, 1)) == REG)
4224 rtx try_insn = insn;
4225 unsigned int regno = REGNO (XEXP (set, 1));
4226 int reg_range = GET_MODE_SIZE (GET_MODE (XEXP (set, 1)));
4233 rewind = prev_nonnote_insn (try_insn);
4234 if (rewind == orig_first || rewind == NULL_RTX
4235 || GET_CODE (rewind) != INSN)
4238 check = (GET_CODE (PATTERN (rewind)) == SET) ? PATTERN (rewind) : NULL_RTX;
4239 if (check == NULL_RTX)
4242 if (! ip2k_check_can_adjust_stack_ref (XEXP (check, 0),
4244 || ! ip2k_check_can_adjust_stack_ref (XEXP (check, 1),
4248 /* If we've hit another push instruction we can't go any
4250 if (GET_CODE (XEXP (check, 0)) == MEM
4251 && GET_CODE (XEXP (XEXP (check, 0), 0)) == POST_DEC
4252 && GET_CODE (XEXP (XEXP (XEXP (check, 0), 0), 0)) == REG
4253 && REGNO (XEXP (XEXP (XEXP (check, 0), 0), 0)) == REG_SP)
4256 /* If this is a register move then check that it doesn't clobber
4257 SP or any part of the instruction we're trying to move. */
4258 if (GET_CODE (XEXP (check, 0)) == REG)
4260 unsigned int check_reg = REGNO (XEXP (check, 0));
4261 int check_reg_range = GET_MODE_SIZE (GET_MODE (XEXP (check,
4264 /* If we have a special case where what we want to push is
4265 being loaded by this "clobbering" insn then we can just
4266 push what is being used to load us and then do the load.
4267 This may seem a little odd, but we may subsequently be
4268 able to merge the load with another instruction as it
4269 may only be used once now! Note though that we
4270 specifically don't try this if the expression being
4271 loaded is an HImode MEM using IP. */
4272 if (check_reg == regno
4273 && check_reg_range == reg_range
4274 && ((GET_CODE (XEXP (check, 1)) == REG
4275 || (GET_CODE (XEXP (check, 1)) == MEM
4276 && (GET_MODE (XEXP (check, 1)) != HImode
4277 || ip2k_xexp_not_uses_reg_for_mem (XEXP (check, 1), REG_IP))))))
4279 switch (check_reg_range)
4282 emit_insn_before (gen_movqi (XEXP (set, 0),
4285 delete_insn (try_insn);
4289 emit_insn_before (gen_movhi (XEXP (set, 0),
4292 delete_insn (try_insn);
4296 emit_insn_before (gen_movsi (XEXP (set, 0),
4299 delete_insn (try_insn);
4303 emit_insn_before (gen_movdi (XEXP (set, 0),
4306 delete_insn (try_insn);
4310 ip2k_adjust_stack_ref (&XEXP (check, 0), reg_range);
4311 ip2k_adjust_stack_ref (&XEXP (check, 1), reg_range);
4312 try_insn = prev_nonnote_insn (rewind);
4313 /* XXX - should be a continue? */
4317 if ((check_reg == REG_SPL)
4318 || (check_reg == REG_SPH)
4319 || (((regno <= check_reg)
4320 && (regno + reg_range - 1) >= check_reg)
4321 || ((regno <= (check_reg + check_reg_range - 1))
4322 && ((regno + reg_range - 1)
4323 >= (check_reg + check_reg_range - 1)))))
4327 emit_insn_before (set, rewind);
4328 delete_insn (try_insn);
4329 ip2k_adjust_stack_ref (&XEXP (check, 0), reg_range);
4330 ip2k_adjust_stack_ref (&XEXP (check, 1), reg_range);
4331 try_insn = prev_nonnote_insn (rewind);
4337 /* Assist the following function, mdr_try_propagate_clr(). */
4340 mdr_try_propagate_clr_sequence (first_insn, regno)
4346 for (try_insn = next_nonnote_insn (first_insn); try_insn;
4347 try_insn = next_nonnote_insn (try_insn))
4349 rtx new_insn = NULL_RTX;
4352 if (GET_CODE (try_insn) == JUMP_INSN)
4355 if (GET_CODE (try_insn) != INSN)
4358 set2 = ((GET_CODE (PATTERN (try_insn)) == SET)
4359 ? PATTERN (try_insn) : NULL_RTX);
4360 if (set2 == NULL_RTX)
4363 if (GET_CODE (XEXP (set2, 1)) == AND
4364 && ((GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG
4365 && REGNO (XEXP (XEXP (set2, 1), 0)) == regno)
4366 || (GET_CODE (XEXP (XEXP (set2, 1), 1)) == REG
4367 && REGNO (XEXP (XEXP (set2, 1), 1)) == regno)))
4369 rtx remove_insn = try_insn;
4370 try_insn = emit_insn_before (gen_rtx_SET (QImode, XEXP (set2, 0),
4371 const0_rtx), try_insn);
4372 delete_insn (remove_insn);
4374 else if (GET_CODE (XEXP (set2, 1)) == IOR
4375 && GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG
4376 && REGNO (XEXP (XEXP (set2, 1), 0)) == regno)
4378 rtx remove_insn = try_insn;
4379 try_insn = emit_insn_before (gen_rtx_SET (QImode, XEXP (set2, 0),
4380 XEXP (XEXP (set2, 1), 1)),
4382 delete_insn (remove_insn);
4384 else if (GET_CODE (XEXP (set2, 1)) == IOR
4385 && GET_CODE (XEXP (XEXP (set2, 1), 1)) == REG
4386 && REGNO (XEXP (XEXP (set2, 1), 1)) == regno)
4388 rtx remove_insn = try_insn;
4389 try_insn = emit_insn_before (gen_rtx_SET (QImode, XEXP (set2, 0),
4390 XEXP (XEXP (set2, 1), 0)),
4392 delete_insn (remove_insn);
4394 else if (GET_CODE (XEXP (set2, 1)) == XOR
4395 && GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG
4396 && REGNO (XEXP (XEXP (set2, 1), 0)) == regno)
4398 rtx remove_insn = try_insn;
4399 try_insn = emit_insn_before (gen_rtx_SET (QImode, XEXP (set2, 0),
4400 XEXP (XEXP (set2, 1), 1)),
4402 delete_insn (remove_insn);
4404 else if (GET_CODE (XEXP (set2, 1)) == XOR
4405 && GET_CODE (XEXP (XEXP (set2, 1), 1)) == REG
4406 && REGNO (XEXP (XEXP (set2, 1), 1)) == regno)
4408 rtx remove_insn = try_insn;
4409 try_insn = emit_insn_before (gen_rtx_SET (QImode, XEXP (set2, 0),
4410 XEXP (XEXP (set2, 1), 0)),
4412 delete_insn (remove_insn);
4415 if (GET_CODE (XEXP (set2, 0)) == REG)
4417 int reg2_range = GET_MODE_SIZE (GET_MODE (XEXP (set2, 0)));
4418 unsigned int regno2 = REGNO (XEXP (set2, 0));
4422 && GET_CODE (XEXP (set2, 1)) == CONST_INT)
4424 int iv = INTVAL (XEXP (set2, 1));
4427 if (iv == 1 || iv == -1)
4429 new_insn = gen_rtx_SET (QImode, XEXP (set2, 0),
4430 gen_rtx_PLUS (QImode, XEXP (set2, 0),
4432 new_insn = emit_insn_before (new_insn, try_insn);
4433 delete_insn (try_insn);
4434 try_insn = new_insn;
4439 if ((regno >= regno2) && (regno <= regno2 + reg2_range - 1))
4442 if (GET_CODE (XEXP (set2, 1)) == REG
4443 && REGNO (XEXP (set2, 1)) == regno)
4445 new_insn = emit_insn_before (gen_rtx_SET (QImode,
4449 delete_insn (try_insn);
4450 try_insn = new_insn;
4454 if (GET_CODE (XEXP (set2, 0)) == CC0)
4456 if (GET_CODE (XEXP (set2, 1)) == REG
4457 && GET_MODE_SIZE (GET_MODE (XEXP (set2, 1))) == 2
4458 && REGNO (XEXP (set2, 1)) == regno)
4460 new_insn = gen_rtx_SET (VOIDmode, gen_rtx_CC0 (VOIDmode),
4461 gen_rtx_REG(QImode, regno + 1));
4462 new_insn = emit_insn_before (new_insn, try_insn);
4464 else if (GET_CODE (XEXP (set2, 1)) == COMPARE
4465 && GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG
4466 && GET_MODE_SIZE (GET_MODE (XEXP (XEXP (set2, 1), 0))) == 2
4467 && REGNO (XEXP (XEXP (set2, 1), 0)) == regno
4468 && GET_CODE (XEXP (XEXP (set2, 1), 1)) == CONST_INT
4469 && INTVAL (XEXP (XEXP (set2, 1), 1)) >= 0
4470 && INTVAL (XEXP (XEXP (set2, 1), 1)) < 256)
4472 new_insn = gen_rtx_SET (VOIDmode, cc0_rtx,
4473 gen_rtx_COMPARE(QImode,
4474 gen_rtx_REG (QImode,
4476 XEXP (XEXP (set2, 1),
4478 new_insn = emit_insn_before (new_insn, try_insn);
4481 /* If we have inserted a replacement for a CC0 setter operation
4482 then we need to delete the old one. */
4483 if (new_insn != NULL_RTX)
4485 delete_insn (try_insn);
4486 try_insn = new_insn;
4488 /* Now as we know that we have just done an unsigned compare
4489 (remember we were zero-extended by the clr!) we also know
4490 that we don't need a signed jump insn. If we find that
4491 our next isns is a signed jump then make it unsigned! */
4492 if (GET_CODE (next_nonnote_insn (try_insn)) == JUMP_INSN)
4496 try_insn = next_nonnote_insn (try_insn);
4497 set3 = ((GET_CODE (PATTERN (try_insn)) == SET)
4498 ? PATTERN (try_insn) : NULL_RTX);
4499 if (set3 == NULL_RTX)
4502 /* If we discover that our jump target is only accessible
4503 from here then we can continue our "clr" propagation to
4505 if (LABEL_NUSES (JUMP_LABEL (try_insn)) == 1)
4506 mdr_try_propagate_clr_sequence (JUMP_LABEL (try_insn),
4509 if (GET_CODE (XEXP (set3, 0)) == PC
4510 && GET_CODE (XEXP (set3, 1)) == IF_THEN_ELSE
4511 && (GET_CODE (XEXP (XEXP (set3, 1), 0)) == GT
4512 || GET_CODE (XEXP (XEXP (set3, 1), 0)) == GE
4513 || GET_CODE (XEXP (XEXP (set3, 1), 0)) == LT
4514 || GET_CODE (XEXP (XEXP (set3, 1), 0)) == LE)
4515 && GET_CODE (XEXP (XEXP (XEXP (set3, 1), 0), 0)) == CC0
4516 && (GET_CODE (XEXP (XEXP (XEXP (set3, 1), 0), 1))
4518 && GET_CODE (XEXP (XEXP (set3, 1), 1)) == LABEL_REF
4519 && GET_CODE (XEXP (XEXP (set3, 1), 2)) == PC)
4525 /* Replace our old conditional jump with a new one that
4526 does the unsigned form of what was previously a
4527 signed comparison. */
4528 code = GET_CODE (XEXP (XEXP (set3, 1), 0));
4529 cmp = gen_rtx_fmt_ee ((code == GT
4533 : (code == LT ? LTU : LEU))),
4535 XEXP (XEXP (XEXP (set3, 1), 0), 0),
4536 XEXP (XEXP (XEXP (set3, 1), 0),
4539 = gen_rtx_SET (GET_MODE (set3),
4541 gen_rtx_IF_THEN_ELSE
4542 (GET_MODE (XEXP (set3, 1)), cmp,
4543 XEXP (XEXP (set3, 1), 1),
4544 XEXP (XEXP (set3, 1), 2)));
4545 new_insn = emit_jump_insn_before (new_if, try_insn);
4546 LABEL_NUSES (JUMP_LABEL (try_insn))++;
4547 delete_insn (try_insn);
4548 try_insn = new_insn;
4553 else if (GET_CODE (XEXP (set2, 1)) == PLUS
4554 && GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG
4555 && GET_MODE_SIZE (GET_MODE (XEXP (XEXP (set2, 1), 0))) == 2
4556 && REGNO (XEXP (XEXP (set2, 1), 0)) == regno
4557 && (GET_CODE (XEXP (XEXP (set2, 1), 1)) == REG
4558 || GET_CODE (XEXP (XEXP (set2, 1), 1)) == MEM
4559 || GET_CODE (XEXP (XEXP (set2, 1), 1)) == CONST_INT
4560 || GET_CODE (XEXP (XEXP (set2, 1), 1)) == CONST
4561 || GET_CODE (XEXP (XEXP (set2, 1), 1)) == SYMBOL_REF))
4563 rtx extend = gen_rtx_ZERO_EXTEND (HImode,
4564 gen_rtx_REG (QImode, regno + 1));
4565 new_insn = gen_rtx_SET (HImode, XEXP (set2, 0),
4566 gen_rtx_PLUS (HImode, extend,
4567 XEXP (XEXP (set2, 1), 1)));
4568 new_insn = emit_insn_before (new_insn, try_insn);
4569 delete_insn (try_insn);
4570 try_insn = new_insn;
4572 else if (GET_CODE (XEXP (set2, 1)) == PLUS
4573 && GET_CODE (XEXP (XEXP (set2, 1), 1)) == REG
4574 && GET_MODE_SIZE (GET_MODE (XEXP (XEXP (set2, 1), 1))) == 2
4575 && REGNO (XEXP (XEXP (set2, 1), 1)) == regno
4576 && (GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG
4577 || GET_CODE (XEXP (XEXP (set2, 1), 0)) == MEM
4578 || GET_CODE (XEXP (XEXP (set2, 1), 0)) == CONST_INT
4579 || GET_CODE (XEXP (XEXP (set2, 1), 0)) == CONST
4580 || GET_CODE (XEXP (XEXP (set2, 1), 0)) == SYMBOL_REF))
4582 rtx t_src = gen_rtx_PLUS (HImode,
4583 gen_rtx_ZERO_EXTEND (HImode,
4584 gen_rtx_REG (QImode,
4587 XEXP (XEXP (set2, 1), 0));
4588 new_insn = emit_insn_before (gen_rtx_SET (HImode, XEXP (set2, 0),
4591 delete_insn (try_insn);
4592 try_insn = new_insn;
4597 /* One of the things that can quite often happen with an 8-bit CPU is that
4598 we end up clearing the MSByte of a 16-bit value. Unfortunately, all too
4599 often gcc doesn't have any way to realize that only half of the value is
4600 useful and ends up doing more work than it should. We scan for such
4601 occurrences here, track them and reduce compare operations to a smaller
4602 size where possible.
4604 Note that this is somewhat different to move propagation as we may
4605 actually change some instruction patterns when we're doing this whereas
4606 move propagation is just about doing a search and replace. */
4609 mdr_try_propagate_clr (first_insn)
4615 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
4617 if (GET_CODE (insn) != INSN)
4620 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
4621 if (set == NULL_RTX)
4624 /* Have we found a "clr" instruction? */
4625 if (GET_CODE (XEXP (set, 0)) == REG
4626 && GET_CODE (XEXP (set, 1)) == CONST_INT
4627 && GET_MODE_SIZE (GET_MODE (XEXP (set, 0))) == 1
4628 && INTVAL (XEXP (set, 1)) == 0)
4630 mdr_try_propagate_clr_sequence (insn, REGNO (XEXP (set, 0)));
4634 #endif /* IP2K_MD_REORG_PASS */
4636 /* Look to see if the expression, x, does not make any memory references
4637 via the specified register. This is very conservative and only returns
4638 nonzero if we definitely don't have such a memory ref. */
4641 ip2k_xexp_not_uses_reg_for_mem (rtx x, unsigned int regno)
4644 regno &= 0xfffffffe;
4646 switch (GET_CODE (x))
4652 if ((GET_CODE (XEXP (x, 0)) == PLUS
4653 && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
4654 && REGNO (XEXP (XEXP (x, 0), 0)) == regno)
4655 || (GET_CODE (XEXP (x, 0)) == REG
4656 && REGNO (XEXP (x, 0)) == regno))
4671 if (GET_RTX_CLASS (GET_CODE (x)) == RTX_BITFIELD_OPS)
4672 return (ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 0), regno)
4673 && ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 1), regno)
4674 && ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 2), regno));
4677 return (ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 0), regno)
4678 && ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 1), regno));
4681 || GET_RTX_CLASS (GET_CODE (x)) == '3')
4682 return ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 0), regno);
4688 #ifdef IP2K_MD_REORG_PASS
4689 /* Assist the following function, mdr_try_propagate_move(). */
4692 mdr_try_propagate_move_sequence (first_insn, orig, equiv)
4699 for (try_insn = next_nonnote_insn (first_insn); try_insn;
4700 try_insn = next_nonnote_insn (try_insn))
4704 rtx new_equiv = NULL_RTX;
4706 if (GET_CODE (try_insn) != JUMP_INSN && GET_CODE (try_insn) != INSN)
4709 set = single_set (try_insn);
4710 if (set == NULL_RTX)
4713 range = MAX (GET_MODE_SIZE (GET_MODE (equiv)),
4714 GET_MODE_SIZE (GET_MODE (XEXP (set, 0))));
4716 if (GET_CODE (equiv) == REG
4717 && REGNO (equiv) == REG_W
4718 && (recog_memoized (try_insn) < 0
4719 || get_attr_clobberw (try_insn) != CLOBBERW_NO)
4720 && (! (GET_CODE (XEXP (set, 0)) == REG
4721 && REGNO (XEXP (set, 0)) == REG_W
4722 && rtx_equal_p (XEXP (set, 1), orig))))
4724 else if (GET_CODE (XEXP (set, 0)) == REG
4725 && (REGNO (XEXP (set, 0)) == REG_SP
4726 || ! ip2k_xexp_not_uses_reg_p (equiv, REGNO (XEXP (set, 0)),
4728 || ! ip2k_xexp_not_uses_reg_p (orig, REGNO (XEXP (set, 0)),
4730 && ! rtx_equal_p (equiv, XEXP (set, 0))
4731 && ! rtx_equal_p (orig, XEXP (set, 0)))
4733 else if (GET_CODE (orig) == REG
4734 && (REGNO (orig) == REG_IPL
4735 || REGNO (orig) == REG_IPH
4736 || REGNO (orig) == REG_DPL
4737 || REGNO (orig) == REG_DPH)
4738 && (! ip2k_xexp_not_uses_reg_for_mem (XEXP (set, 0),
4740 || ! ip2k_xexp_not_uses_reg_for_mem (XEXP (set, 1),
4743 else if (GET_CODE (XEXP (set, 0)) == MEM
4744 && GET_CODE (equiv) == MEM)
4746 if (! ip2k_xexp_not_uses_reg_p (equiv, REG_SP, 2))
4748 if (! ip2k_xexp_not_uses_reg_p (XEXP (set, 0), REG_SP, 2))
4750 /* We look for a special case of "push" operations screwing
4751 our register equivalence when it's based on a stack slot.
4752 We can track this one and replace the old equivalence
4753 expression with a new one. */
4754 if (GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC
4755 && GET_CODE (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG
4756 && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP
4757 && GET_CODE (XEXP (equiv, 0)) == PLUS
4758 && REGNO (XEXP (XEXP (equiv, 0), 0)) == REG_SP)
4760 int md_size = GET_MODE_SIZE (GET_MODE (XEXP (set, 0)));
4761 int new_sp_offs = INTVAL (XEXP (XEXP (equiv, 0), 1))
4764 /* Don't allow an invalid stack pointer offset to be
4766 if (new_sp_offs > (128 - 2 * md_size))
4770 = gen_rtx_MEM (GET_MODE (equiv),
4771 gen_rtx_PLUS (Pmode,
4772 gen_rtx_REG (HImode ,
4774 GEN_INT (new_sp_offs)));
4776 else if (! rtx_equal_p (equiv, XEXP (set, 0)))
4778 /* Look at the SP offsets and look for any overlaps. */
4779 int equiv_offs = GET_CODE (XEXP (equiv, 0)) == PLUS
4780 ? INTVAL (XEXP (XEXP (equiv, 0), 1))
4783 = (GET_CODE (XEXP (XEXP (set, 0), 0)) == PLUS
4784 ? INTVAL (XEXP (XEXP (XEXP (set, 0), 0), 1))
4787 if (abs (equiv_offs - set_offs) < range)
4793 if (! ip2k_xexp_not_uses_reg_p (equiv, REG_IP, 2))
4796 if (! ip2k_xexp_not_uses_reg_p (XEXP (set, 0), REG_DP, 2)
4797 && ! ip2k_xexp_not_uses_reg_p (equiv, REG_DP, 2)
4798 && ! rtx_equal_p (equiv, XEXP (set, 0)))
4800 /* Look at the DP offsets and look for any overlaps. */
4801 int equiv_offs = GET_CODE (XEXP (equiv, 0)) == PLUS
4802 ? INTVAL (XEXP (XEXP (equiv, 0), 1))
4804 int set_offs = GET_CODE (XEXP (XEXP (set, 0), 0)) == PLUS
4805 ? INTVAL (XEXP (XEXP (XEXP (set, 0), 0), 1))
4808 if (abs (equiv_offs - set_offs) < range)
4813 validate_replace_rtx_subexp (orig, equiv, try_insn, &XEXP (set, 1));
4815 if (rtx_equal_p (equiv, XEXP (set, 0))
4816 || rtx_equal_p (orig, XEXP (set, 0)))
4819 if (new_equiv != NULL_RTX)
4824 /* Try propagating move instructions forwards. It may be that we can
4825 replace a register use with an equivalent expression that already
4826 holds the same value and thus allow one or more register loads to
4830 mdr_try_propagate_move (first_insn)
4836 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
4838 if (GET_CODE (insn) != INSN)
4841 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
4842 if (set == NULL_RTX)
4845 /* Have we found a simple move instruction? */
4846 if (GET_CODE (XEXP (set, 0)) == REG
4847 && (REGNO (XEXP (set, 0)) >= 0x80
4848 || REGNO (XEXP (set, 0)) == REG_DPL
4849 || REGNO (XEXP (set, 0)) == REG_DPH
4850 || REGNO (XEXP (set, 0)) == REG_IPL
4851 || REGNO (XEXP (set, 0)) == REG_IPH)
4852 && ((GET_CODE (XEXP (set, 1)) == REG
4853 && REGNO (XEXP (set, 1)) != REG_SP
4854 && ip2k_xexp_not_uses_reg_p (XEXP (set, 0),
4855 REGNO (XEXP (set, 1)),
4856 GET_MODE_SIZE (GET_MODE (XEXP (set,
4858 || (GET_CODE (XEXP (set, 1)) == MEM
4859 && (ip2k_xexp_not_uses_reg_p (XEXP (set, 1), REG_IP, 2)
4860 || GET_MODE (XEXP (set, 1)) == QImode)
4861 && ((REGNO (XEXP (set, 0)) != REG_DPH
4862 && REGNO (XEXP (set, 0)) != REG_DPL)
4863 || ip2k_xexp_not_uses_reg_p (XEXP (set, 1), REG_DP, 2)))
4864 || (GET_CODE (XEXP (set, 1)) == CONST_INT
4865 && (GET_MODE (XEXP (set, 0)) != QImode
4866 || INTVAL (XEXP (set, 1)) != 0))
4867 || GET_CODE (XEXP (set, 1)) == CONST_DOUBLE
4868 || GET_CODE (XEXP (set, 1)) == CONST
4869 || GET_CODE (XEXP (set, 1)) == SYMBOL_REF))
4871 mdr_try_propagate_move_sequence (insn, XEXP (set, 0), XEXP (set, 1));
4876 /* Try to remove redundant instructions. */
4879 mdr_try_remove_redundant_insns (first_insn)
4884 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
4887 enum machine_mode mode;
4889 HOST_WIDE_INT pattern;
4892 if (GET_CODE (insn) != INSN)
4895 if (GET_CODE (PATTERN (insn)) == CONST_INT)
4897 /* We've found a dummy expression. */
4898 rtx remove_insn = insn;
4899 insn = prev_nonnote_insn (insn);
4900 delete_insn (remove_insn);
4904 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
4905 if (set == NULL_RTX)
4908 mode = GET_MODE (XEXP (set, 0));
4909 md_size = GET_MODE_SIZE (mode);
4910 if ((md_size < 1) || (md_size > 4))
4914 for (i = 0; i < md_size; i++)
4920 if ((GET_CODE (XEXP (set, 1)) == AND
4921 && GET_CODE (XEXP (XEXP (set, 1), 1)) == CONST_INT
4922 && INTVAL (XEXP (XEXP (set, 1), 1)) == pattern)
4923 || ((GET_CODE (XEXP (set, 1)) == IOR
4924 || GET_CODE (XEXP (set, 1)) == XOR)
4925 && GET_CODE (XEXP (XEXP (set, 1), 1)) == CONST_INT
4926 && INTVAL (XEXP (XEXP (set, 1), 1)) == 0x00))
4928 /* We've found an AND with all 1's, an XOR with all 0's or an
4930 rtx remove_insn = insn;
4932 /* Is it completely redundant or should it become a move insn? */
4933 if (! rtx_equal_p (XEXP (set, 0), XEXP (XEXP (set, 1), 0)))
4935 emit_insn_before (gen_rtx_SET (mode,
4937 XEXP (XEXP (set, 1), 0)),
4941 insn = prev_nonnote_insn(insn);
4942 delete_insn (remove_insn);
4944 else if (GET_CODE (XEXP (set, 1)) == AND
4945 && GET_CODE (XEXP (XEXP (set, 1), 1)) == CONST_INT
4946 && INTVAL (XEXP (XEXP (set, 1), 1)) == 0)
4948 /* We've found an AND with all 0's. */
4949 rtx remove_insn = insn;
4950 insn = emit_insn_before (gen_rtx_SET (mode,
4952 XEXP (XEXP (set, 1), 1)),
4954 delete_insn (remove_insn);
4959 /* Structure used to track jump targets. */
4961 struct we_jump_targets
4963 int target; /* Is this a jump target? */
4964 int reach_count; /* Number of ways we can reach this insn. */
4965 int touch_count; /* Number of times we've touched this insn
4967 rtx w_equiv; /* WREG-equivalence at this point. */
4970 struct we_jump_targets *ip2k_we_jump_targets;
4972 /* WREG equivalence tracking used within DP reload elimination. */
4975 track_w_reload (insn, w_current, w_current_ok, modifying)
4983 if (GET_CODE (insn) != INSN)
4985 *w_current = NULL_RTX;
4989 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
4990 if (set == NULL_RTX)
4992 *w_current = NULL_RTX;
4996 /* Look for W being modified. If it is, see if it's being changed
4997 to what it already is! */
4998 if (GET_CODE (XEXP (set, 0)) == REG
4999 && REGNO (XEXP (set, 0)) == REG_W
5000 && GET_MODE (XEXP (set, 0)) == QImode)
5002 /* If this is an equivalence we can delete the new set operation. */
5003 if (*w_current != NULL_RTX
5004 && rtx_equal_p (XEXP (set, 1), *w_current))
5011 *w_current = XEXP (set, 1);
5015 else if (recog_memoized (insn) < 0
5016 || get_attr_clobberw (insn) != CLOBBERW_NO)
5018 /* If we clobber W then we've clobbered any equivalences ! */
5019 *w_current = NULL_RTX;
5022 else if (! ip2k_xexp_not_uses_reg_p (XEXP (set, 0), REG_SP, 2)
5023 && *w_current != NULL_RTX
5024 && !ip2k_xexp_not_uses_reg_p (*w_current, REG_SP, 2))
5026 /* We look for a special case of "push" operations screwing up the
5027 setting of DP when it's based on the stack. We can track this one
5028 and replace the old expression for DP with a new one. */
5029 if (GET_CODE (XEXP (set, 0)) == MEM
5030 && GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC
5031 && GET_CODE (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG
5032 && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP
5033 && GET_CODE (*w_current) == MEM
5034 && GET_CODE (XEXP (*w_current, 0)) == PLUS)
5036 /* XXX - need to ensure that we can track this without going
5038 rtx val = GEN_INT (INTVAL (XEXP (XEXP (*w_current, 0), 1))
5039 + GET_MODE_SIZE (GET_MODE (XEXP (set, 0))));
5041 = gen_rtx_MEM (HImode, gen_rtx_PLUS (Pmode,
5042 gen_rtx_REG(HImode, REG_SP),
5047 else if (GET_CODE (XEXP (set, 0)) == REG
5048 && *w_current != NULL_RTX
5049 && !ip2k_xexp_not_uses_reg_p (*w_current, REGNO (XEXP (set, 0)),
5050 GET_MODE_SIZE (GET_MODE (XEXP (set
5053 /* If we've just clobbered all or part of a register reference that we
5054 were sharing for W then we can't share it any more! */
5055 *w_current = NULL_RTX;
5058 return w_current_ok;
5061 /* As part of the machine-dependent reorg we scan moves into w and track them
5062 to see where any are redundant. */
5065 mdr_try_wreg_elim (first_insn)
5069 struct we_jump_targets *wjt;
5071 int incomplete_scan;
5072 int last_incomplete_scan;
5074 ip2k_we_jump_targets
5075 = (struct we_jump_targets *) xcalloc (get_max_uid (),
5076 sizeof (struct we_jump_targets));
5078 /* First we scan to build up a list of all CODE_LABEL insns and we work out
5079 how many different ways we can reach them. */
5080 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
5082 if (GET_CODE (insn) == CODE_LABEL)
5084 wjt = &ip2k_we_jump_targets[INSN_UID (insn)];
5086 wjt->reach_count = LABEL_NUSES (insn);
5087 wjt->touch_count = 0;
5088 wjt->w_equiv = NULL_RTX;
5089 if (! prev_nonnote_insn (insn)
5090 || (prev_nonnote_insn (insn)
5091 && GET_CODE (prev_nonnote_insn (insn)) != BARRIER))
5096 /* Next we scan all of the ways of reaching the code labels to see
5097 what the WREG register is equivalent to as we reach them. If we find
5098 that they're the same then we keep noting the matched value. We
5099 iterate around this until we reach a convergence on WREG equivalences
5100 at all code labels - we have to be very careful not to be too
5102 incomplete_scan = -1;
5105 int w_current_ok = 0;
5106 last_incomplete_scan = incomplete_scan;
5107 w_current = NULL_RTX;
5109 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
5111 /* If we have a code label then we need to see if we already know
5112 what the equivalence is at this point. If we do then we use it
5113 immediately, but if we don't then we have a special case to track
5114 when we hit a fallthrough-edge (label with no barrier preceding
5115 it). Any other accesses to the label must be from jump insns
5116 and so they're handled elsewhere. */
5117 if (GET_CODE (insn) == CODE_LABEL)
5119 wjt = &ip2k_we_jump_targets[INSN_UID (insn)];
5121 /* If we're fully characterized the use the equivalence. */
5122 if (wjt->touch_count == wjt->reach_count)
5124 w_current = wjt->w_equiv;
5129 /* If we have a known equivalence for WREG as we reach the
5130 fallthrough-edge then track this into the code label. */
5132 && (! prev_nonnote_insn (insn)
5133 || (prev_nonnote_insn (insn)
5134 && GET_CODE (prev_nonnote_insn (insn)) != BARRIER)))
5136 if (wjt->touch_count == 0)
5137 wjt->w_equiv = w_current;
5139 if (wjt->touch_count < wjt->reach_count)
5142 if (! rtx_equal_p (wjt->w_equiv, w_current))
5144 /* When we definitely know that we can't form an
5145 equivalence for WREG here we must clobber anything
5146 that we'd started to track too. */
5147 wjt->w_equiv = NULL_RTX;
5148 w_current = NULL_RTX;
5154 /* If we've not completely characterized this code label then
5155 be cautious and assume that we don't know what WREG is
5157 if (wjt->touch_count < wjt->reach_count)
5159 w_current = NULL_RTX;
5166 /* If we've hit a jump insn then we look for either an address
5167 vector (jump table) or for jump label references. */
5168 if (GET_CODE (insn) == JUMP_INSN)
5170 /* Don't attempt to track here if we don't have a known
5171 equivalence for WREG at this point. */
5174 if (JUMP_LABEL (insn))
5177 = &ip2k_we_jump_targets[INSN_UID (JUMP_LABEL (insn))];
5179 if (wjt->touch_count == 0)
5180 wjt->w_equiv = w_current;
5182 if (wjt->touch_count < wjt->reach_count)
5185 if (! rtx_equal_p (wjt->w_equiv, w_current))
5186 wjt->w_equiv = NULL_RTX;
5194 /* Anything other than a code labal or jump arrives here. We try and
5195 track WREG, but sometimes we might not be able to. */
5196 w_current_ok = track_w_reload (insn, &w_current, w_current_ok, 0);
5199 /* When we're looking to see if we've finished we count the number of
5200 paths through the code labels where we weren't able to definitively
5201 track WREG. This number is used to see if we're converging on a
5203 If this hits zero then we've fully converged, but if this stays the
5204 same as last time then we probably can't make any further
5206 incomplete_scan = 0;
5207 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
5209 if (GET_CODE (insn) == CODE_LABEL)
5211 wjt = &ip2k_we_jump_targets[INSN_UID (insn)];
5212 if (wjt->touch_count != wjt->reach_count)
5214 incomplete_scan += (wjt->reach_count - wjt->touch_count);
5215 wjt->w_equiv = NULL_RTX;
5216 wjt->touch_count = 0;
5221 while (incomplete_scan && incomplete_scan != last_incomplete_scan);
5223 /* Finally we scan the whole function and run WREG elimination. When we hit
5224 a CODE_LABEL we pick up any stored equivalence since we now know that
5225 every path to this point entered with WREG holding the same thing! If
5226 we subsequently have a reload that matches then we can eliminate it. */
5227 w_current = NULL_RTX;
5228 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
5230 if (GET_CODE (insn) == JUMP_INSN)
5233 if (GET_CODE (insn) == CODE_LABEL)
5235 wjt = &ip2k_we_jump_targets[INSN_UID (insn)];
5236 w_current = wjt->w_equiv;
5240 track_w_reload (insn, &w_current, 1, 1);
5243 free (ip2k_we_jump_targets);
5245 #endif /* IP2K_MD_REORG_PASS */
5247 /* We perform a lot of untangling of the RTL within the reorg pass since
5248 the IP2k requires some really bizarre (and really undesireable) things
5249 to happen in order to guarantee not aborting. This pass causes several
5250 earlier passes to be re-run as it progressively transforms things,
5251 making the subsequent runs continue to win. */
5256 #ifdef IP2K_MD_REORG_PASS
5257 rtx first_insn, insn, set;
5264 ip2k_reorg_completed = 1;
5265 ip2k_reorg_split_dimode = 1;
5266 ip2k_reorg_split_simode = 1;
5267 ip2k_reorg_split_himode = 1;
5268 ip2k_reorg_split_qimode = 1;
5269 ip2k_reorg_merge_qimode = 1;
5272 #ifndef IP2K_MD_REORG_PASS
5273 ip2k_reorg_completed = 1;
5274 ip2k_reorg_split_dimode = 1;
5275 ip2k_reorg_split_simode = 1;
5276 ip2k_reorg_split_himode = 1;
5277 ip2k_reorg_split_qimode = 1;
5278 ip2k_reorg_merge_qimode = 1;
5280 /* All optimizations below must be debugged and enabled one by one.
5281 All of them commented now because of abort in GCC core. */
5283 ip2k_reorg_in_progress = 1;
5285 first_insn = get_insns ();
5287 /* Look for size effects of earlier optimizations - in particular look for
5288 situations where we're saying "use" a register on one hand but immediately
5289 tagging it as "REG_DEAD" at the same time! Seems like a bug in core-gcc
5290 somewhere really but this is what we have to live with! */
5291 for (insn = first_insn; insn; insn = NEXT_INSN (insn))
5295 if (GET_CODE (insn) == CODE_LABEL
5296 || GET_CODE (insn) == NOTE
5297 || GET_CODE (insn) == BARRIER)
5303 body = PATTERN (insn);
5304 if (GET_CODE (body) == USE)
5305 if (GET_CODE (XEXP (body, 0)) == REG)
5309 reg = REGNO (XEXP (body, 0));
5310 if (find_regno_note (insn, REG_DEAD, reg))
5317 /* There's a good chance that since we last did CSE that we've rearranged
5318 things in such a way that another go will win. Do so now! */
5319 reload_cse_regs (first_insn);
5320 find_basic_blocks (first_insn, max_reg_num (), 0);
5321 life_analysis (0, PROP_REG_INFO | PROP_DEATH_NOTES);
5323 /* Look for where absurd things are happening with DP. */
5324 mdr_try_dp_reload_elim (first_insn);
5326 ip2k_reorg_in_progress = 0;
5327 ip2k_reorg_completed = 1;
5329 split_all_insns (0);
5331 reload_cse_regs (first_insn);
5332 find_basic_blocks (first_insn, max_reg_num (), 0);
5333 life_analysis (0, PROP_REG_INFO | PROP_DEATH_NOTES);
5335 peephole2_optimize (NULL);
5337 mdr_resequence_xy_yx (first_insn);
5338 mdr_propagate_reg_equivs (first_insn);
5340 /* Look for redundant set instructions. These can occur when we split
5341 instruction patterns and end up with the second half merging with
5342 or being replaced by something that clobbers the first half. */
5343 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
5345 if (GET_CODE (insn) == INSN)
5347 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
5348 if ((set != NULL_RTX)
5349 && (GET_CODE (XEXP (set, 0)) == REG)
5350 && (GET_MODE (XEXP (set, 0)) == QImode)
5351 && (find_regno_note (insn, REG_UNUSED, REGNO (XEXP (set, 0)))))
5356 mdr_try_move_dp_reload (first_insn);
5357 mdr_try_move_pushes (first_insn);
5359 find_basic_blocks (first_insn, max_reg_num (), 0);
5360 life_analysis (0, PROP_FINAL);
5362 mdr_try_propagate_move (first_insn);
5363 mdr_resequence_xy_yx (first_insn);
5365 ip2k_reorg_split_dimode = 1;
5366 split_all_insns (0);
5368 mdr_try_remove_redundant_insns (first_insn);
5370 mdr_try_propagate_move (first_insn);
5372 reload_cse_regs (first_insn);
5373 find_basic_blocks (first_insn, max_reg_num (), 0);
5374 life_analysis (0, PROP_FINAL);
5376 peephole2_optimize (NULL);
5378 mdr_try_propagate_move (first_insn);
5380 find_basic_blocks (first_insn, max_reg_num (), 0);
5381 life_analysis (0, PROP_FINAL);
5383 ip2k_reorg_split_simode = 1;
5384 split_all_insns (0);
5386 mdr_try_remove_redundant_insns (first_insn);
5388 mdr_try_propagate_move (first_insn);
5390 reload_cse_regs (first_insn);
5391 find_basic_blocks (first_insn, max_reg_num (), 0);
5392 life_analysis (0, PROP_FINAL);
5394 peephole2_optimize (NULL);
5396 mdr_try_propagate_move (first_insn);
5398 find_basic_blocks (first_insn, max_reg_num (), 0);
5399 life_analysis (0, PROP_FINAL);
5401 ip2k_reorg_split_himode = 1;
5402 ip2k_reorg_merge_qimode = 1;
5403 split_all_insns (0);
5405 mdr_try_remove_redundant_insns (first_insn);
5406 mdr_try_propagate_clr (first_insn);
5407 mdr_try_propagate_move (first_insn);
5409 mdr_try_dp_reload_elim (first_insn);
5410 mdr_try_move_dp_reload (first_insn);
5412 rebuild_jump_labels (first_insn);
5414 /* Call to jump_optimize (...) was here, but now I removed it. */
5416 find_basic_blocks (first_insn, max_reg_num (), 0);
5417 life_analysis (0, PROP_FINAL);
5419 peephole2_optimize (NULL);
5421 mdr_try_propagate_move (first_insn);
5423 find_basic_blocks (first_insn, max_reg_num (), 0);
5424 life_analysis (0, PROP_FINAL);
5425 mdr_try_remove_redundant_insns (first_insn);
5427 mdr_try_propagate_clr (first_insn);
5428 mdr_try_propagate_move (first_insn);
5430 find_basic_blocks (first_insn, max_reg_num (), 0);
5431 life_analysis (0, PROP_FINAL);
5433 ip2k_reorg_split_qimode = 1;
5434 split_all_insns (0);
5436 mdr_try_wreg_elim (first_insn);
5437 mdr_try_propagate_move (first_insn);
5439 find_basic_blocks (first_insn, max_reg_num (), 0);
5440 life_analysis (0, PROP_FINAL);
5445 ip2k_init_libfuncs (void)
5447 set_optab_libfunc (smul_optab, SImode, "_mulsi3");
5448 set_optab_libfunc (smul_optab, DImode, "_muldi3");
5449 set_optab_libfunc (cmp_optab, HImode, "_cmphi2");
5450 set_optab_libfunc (cmp_optab, SImode, "_cmpsi2");
5453 /* Returns a bit position if mask contains only a single bit. Returns -1 if
5454 there were zero or more than one set bits. */
5456 find_one_set_bit_p (HOST_WIDE_INT mask)
5459 unsigned HOST_WIDE_INT n = mask;
5460 for (i = 0; i < 32; i++)
5462 if (n & 0x80000000UL)
5464 if (n & 0x7fffffffUL)
5474 /* Returns a bit position if mask contains only a single clear bit.
5475 Returns -1 if there were zero or more than one clear bits. */
5477 find_one_clear_bit_p (HOST_WIDE_INT mask)
5480 unsigned HOST_WIDE_INT n = mask;
5481 for (i = 0; i < 32; i++)
5483 if ((n & 0x80000000UL) == 0UL)
5485 if ((n & 0x7fffffffUL) != 0x7fffffffUL)
5497 /* Split a move into two smaller pieces.
5498 MODE indicates the reduced mode. OPERANDS[0] is the original destination
5499 OPERANDS[1] is the original src. The new destinations are
5500 OPERANDS[2] and OPERANDS[4], while the new sources are OPERANDS[3]
5504 ip2k_split_words (enum machine_mode nmode, enum machine_mode omode,
5507 rtx dl, dh; /* src/dest pieces. */
5509 int move_high_first = 0; /* Assume no overlap. */
5512 switch (GET_CODE (operands[0])) /* DEST */
5516 if ((GET_CODE (operands[1]) == REG
5517 || GET_CODE (operands[1]) == SUBREG)
5518 && (true_regnum (operands[0]) <= true_regnum (operands[1])
5519 || (true_regnum (operands[1])
5520 + GET_MODE_SIZE (omode) - 1 < true_regnum (operands[0]))))
5521 move_high_first = 1;
5523 if (GET_CODE (operands[0]) == SUBREG)
5525 dl = simplify_gen_subreg (nmode, operands[0], omode,
5526 GET_MODE_SIZE (nmode));
5527 dh = simplify_gen_subreg (nmode, operands[0], omode, 0);
5529 else if (GET_CODE (operands[0]) == REG && ! IS_PSEUDO_P (operands[0]))
5531 int r = REGNO (operands[0]);
5532 dh = gen_rtx_REG (nmode, r);
5533 dl = gen_rtx_REG (nmode, r + HARD_REGNO_NREGS (r, nmode));
5537 dh = gen_rtx_SUBREG (nmode, operands[0], 0);
5538 dl = gen_rtx_SUBREG (nmode, operands[0], GET_MODE_SIZE (nmode));
5543 switch (GET_CODE (XEXP (operands[0], 0)))
5548 dl = dh = gen_rtx_MEM (nmode, XEXP (operands[0], 0));
5552 dl = change_address (operands[0], nmode,
5553 plus_constant (XEXP (operands[0], 0),
5554 GET_MODE_SIZE (nmode)));
5555 dh = gen_rtx_MEM (nmode, XEXP (operands[0], 0));
5562 switch (GET_CODE (operands[1]))
5565 if (! IS_PSEUDO_P (operands[1]))
5567 int r = REGNO (operands[1]);
5569 sh = gen_rtx_REG (nmode, r);
5570 sl = gen_rtx_REG (nmode, r + HARD_REGNO_NREGS (r, nmode));
5574 sh = gen_rtx_SUBREG (nmode, operands[1], 0);
5575 sl = gen_rtx_SUBREG (nmode, operands[1], GET_MODE_SIZE (nmode));
5580 if (operands[1] == const0_rtx)
5581 sh = sl = const0_rtx;
5584 if (GET_MODE (operands[0]) != DImode)
5589 REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
5590 REAL_VALUE_TO_TARGET_SINGLE (rv, value);
5592 sh = gen_int_mode ((value >> 16) & 0xffff, nmode);
5593 sl = gen_int_mode (value & 0xffff, nmode);
5597 sh = gen_int_mode (CONST_DOUBLE_HIGH (operands[1]), nmode);
5598 sl = gen_int_mode (CONST_DOUBLE_LOW (operands[1]), nmode);
5604 if (operands[1] == const0_rtx)
5605 sh = sl = const0_rtx;
5608 int val = INTVAL (operands[1]);
5614 vh = (val >> 8) & 0xff;
5619 vh = (val >> 16) & 0xffff;
5624 if (val < 0) /* sign extend */
5628 vl = val; /* Give low 32 bits back. */
5635 sl = gen_int_mode (vl, nmode);
5636 sh = gen_int_mode (vh, nmode);
5641 sl = simplify_gen_subreg (nmode, operands[1], omode,
5642 GET_MODE_SIZE (nmode));
5643 sh = simplify_gen_subreg (nmode, operands[1], omode, 0);
5647 switch (GET_CODE (XEXP (operands[1], 0)))
5655 /* Worry about splitting stack pushes. */
5656 if (pushflag && ip2k_address_uses_reg_p (operands[1], REG_SP))
5657 sl = sh = change_address (operands[1], nmode,
5658 plus_constant (XEXP (operands[1], 0),
5659 GET_MODE_SIZE (nmode)));
5662 sl = change_address (operands[1], nmode,
5663 plus_constant (XEXP (operands[1], 0),
5664 GET_MODE_SIZE (nmode)));
5665 sh = gen_rtx_MEM (nmode, XEXP (operands[1], 0));
5674 if (move_high_first)
5691 /* Get the low half of an operand. */
5693 ip2k_get_low_half (rtx x, enum machine_mode mode)
5695 switch (GET_CODE (x))
5698 if (! IS_PSEUDO_P (x))
5700 unsigned int r = REGNO (x);
5702 return gen_rtx_REG (mode, r + HARD_REGNO_NREGS (r, mode));
5706 return gen_rtx_SUBREG (mode, x, GET_MODE_SIZE (mode));
5711 if (x == const0_rtx)
5720 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
5721 REAL_VALUE_TO_TARGET_SINGLE (rv, value);
5723 return gen_int_mode (value & 0xffff, mode);
5726 return gen_int_mode (CONST_DOUBLE_LOW (x), mode);
5731 if (x == const0_rtx)
5735 int val = INTVAL (x);
5741 vh = (val >> 8) & 0xff;
5746 vh = (val >> 16) & 0xffff;
5751 if (val < 0) /* sign extend */
5755 vl = val; /* Give low 32 bits back. */
5762 return gen_int_mode (vl, mode);
5767 return simplify_gen_subreg (mode, x, GET_MODE (x), GET_MODE_SIZE (mode));
5770 switch (GET_CODE (XEXP (x, 0)))
5778 return change_address (x, mode,
5779 plus_constant (XEXP (x, 0),
5780 GET_MODE_SIZE (mode)));
5790 /* Get the high half of an operand. */
5792 ip2k_get_high_half (rtx x, enum machine_mode mode)
5794 switch (GET_CODE (x))
5797 if (! IS_PSEUDO_P (x))
5799 unsigned int r = REGNO (x);
5801 return gen_rtx_REG (mode, r);
5805 return gen_rtx_SUBREG (mode, x, 0);
5810 if (x == const0_rtx)
5819 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
5820 REAL_VALUE_TO_TARGET_SINGLE (rv, value);
5822 return gen_int_mode ((value >> 16) & 0xffff, mode);
5825 return gen_int_mode (CONST_DOUBLE_HIGH (x), mode);
5830 if (x == const0_rtx)
5834 int val = INTVAL (x);
5840 vh = (val >> 8) & 0xff;
5845 vh = (val >> 16) & 0xffff;
5850 if (val < 0) /* sign extend */
5854 vl = val; /* Give low 32 bits back. */
5861 return gen_int_mode (vh, mode);
5866 return simplify_gen_subreg (mode, x, GET_MODE (x), 0);
5870 switch (GET_CODE (XEXP (x, 0)))
5878 return change_address (x, mode, plus_constant (XEXP (x, 0), 0));
5888 /* Does address X use register R. Only valid for REG_SP, REG_DP, REG_IP
5892 ip2k_address_uses_reg_p (rtx x, unsigned int r)
5894 if (GET_CODE (x) != MEM)
5900 switch (GET_CODE (x))
5910 if (ip2k_address_uses_reg_p (XEXP (x, 1), r))
5917 /* Ignore subwords. */
5922 /* Have to consider that r might be LSB of a pointer reg. */
5923 return ((REGNO (x) == r) || (REGNO (x) == (r - 1))) ? 1 : 0;
5926 /* We might be looking at a (mem:BLK (mem (...))) */
5935 /* Does the queried XEXP not use a particular register? If we're certain
5936 that it doesn't then we return TRUE otherwise we assume FALSE. */
5939 ip2k_xexp_not_uses_reg_p (rtx x, unsigned int r, int rsz)
5941 switch (GET_CODE (x))
5945 int msz = GET_MODE_SIZE (GET_MODE (x));
5947 return (((REGNO (x) + msz - 1) < r)
5948 || (REGNO (x) > (r + rsz - 1)));
5952 return !ip2k_address_uses_reg_p (x, r);
5968 /* Does the queried XEXP not use a particular register? If we're certain
5969 that it doesn't then we return TRUE otherwise we assume FALSE. */
5972 ip2k_composite_xexp_not_uses_reg_p (rtx x, unsigned int r, int rsz)
5974 if (GET_RTX_CLASS (GET_CODE (x)) == RTX_BITFIELD_OPS)
5975 return (ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 0), r, rsz)
5976 && ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 1), r, rsz)
5977 && ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 2), r, rsz));
5980 return (ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 0), r, rsz)
5981 && ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 1), r, rsz));
5984 || GET_RTX_CLASS (GET_CODE (x)) == RTX_TERNARY)
5985 return ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 0), r, rsz);
5987 return ip2k_xexp_not_uses_reg_p (x, r, rsz);
5990 /* Does the queried XEXP not use CC0? If we're certain that
5991 it doesn't then we return TRUE otherwise we assume FALSE. */
5994 ip2k_composite_xexp_not_uses_cc0_p (rtx x)
5996 if (GET_RTX_CLASS (GET_CODE (x)) == RTX_BITFIELD_OPS)
5997 return (ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 0))
5998 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 1))
5999 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 2)));
6002 return (ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 0))
6003 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 1)));
6006 || GET_RTX_CLASS (GET_CODE (x)) == RTX_TERNARY)
6007 return ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 0));
6009 return GET_CODE (x) != CC0;
6013 ip2k_split_dest_operand (rtx x, enum machine_mode mode)
6015 return nonimmediate_operand (x, mode) || push_operand (x, mode);
6019 ip2k_nonptr_operand (rtx x, enum machine_mode mode)
6021 return register_operand (x, mode) && !ip2k_ptr_operand (x, mode);
6024 /* Is X a reference to IP or DP or SP? */
6027 ip2k_ptr_operand (rtx x, enum machine_mode mode)
6030 if (GET_CODE (x) == SUBREG)
6034 && (mode == HImode || mode == VOIDmode)
6035 && (REGNO (x) == REG_IP
6036 || REGNO (x) == REG_DP
6037 || REGNO (x) == REG_SP));
6041 ip2k_sp_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
6044 return REG_P (x) && REGNO (x) == REG_SP;
6048 ip2k_ip_operand (rtx x, enum machine_mode mode)
6051 if (GET_CODE (x) != MEM)
6056 if (GET_CODE (x) == PLUS && XEXP (x, 1) == const0_rtx)
6062 if (GET_MODE_SIZE (mode) > 1)
6063 return 0; /* Can't access offset bytes. */
6065 return REGNO (x) == REG_IP;
6068 /* Is X a memory address suitable for SP or DP relative addressing? */
6070 ip2k_short_operand (rtx x, enum machine_mode mode)
6073 unsigned int offs = 0;
6075 if (! memory_operand (x, mode))
6076 return 0; /* Got to be a memory address. */
6079 switch (GET_CODE (x))
6085 if (! REG_P (XEXP (x, 0))
6086 || GET_CODE (XEXP (x, 1)) != CONST_INT)
6089 offs = INTVAL (XEXP (x, 1));
6099 if (IS_PSEUDO_P (x))
6100 return 0; /* Optimistic - doesn't work. */
6104 /* For 'S' constraint, we presume that no IP adjustment
6105 simulation is performed - so only QI mode allows IP to be a
6106 short offset address. All other IP references must be
6107 handled by 'R' constraints. */
6108 if (r == REG_IP && offs == 0 && GET_MODE_SIZE (mode) <= 1)
6111 return (r == REG_SP || r == REG_DP);
6116 ip2k_nonsp_reg_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
6118 if (GET_CODE (x) == SUBREG)
6121 return (REG_P (x) && REGNO (x) != REG_SP);
6125 ip2k_gen_operand (rtx x, enum machine_mode mode)
6127 return ip2k_short_operand (x, mode)
6128 || (GET_CODE (x) == SUBREG
6129 && REG_P (SUBREG_REG (x)))
6130 || (ip2k_nonsp_reg_operand (x, mode));
6134 ip2k_extra_constraint (rtx x, int c)
6138 case 'S': /* Allow offset in stack frame... */
6139 return ip2k_short_operand (x, GET_MODE (x));
6142 return ip2k_ip_operand (x, GET_MODE (x));
6144 case 'T': /* Constant int or .data address. */
6145 return CONSTANT_P (x) && is_regfile_address (x);
6153 ip2k_unary_operator (rtx op, enum machine_mode mode)
6155 return ((mode == VOIDmode || GET_MODE (op) == mode)
6160 ip2k_binary_operator (rtx op, enum machine_mode mode)
6162 return ((mode == VOIDmode || GET_MODE (op) == mode)
6163 && ARITHMETIC_P (op));
6167 ip2k_symbol_ref_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
6169 /* We define an IP2k symbol ref to be either a direct reference or one
6170 with a constant offset. */
6171 return (GET_CODE (op) == SYMBOL_REF)
6172 || (GET_CODE (op) == CONST
6173 && GET_CODE (XEXP (op, 0)) == PLUS
6174 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF);
6178 ip2k_signed_comparison_operator (rtx op, enum machine_mode mode)
6180 return (comparison_operator (op, mode)
6181 && signed_condition (GET_CODE (op)) == GET_CODE (op));
6185 ip2k_unsigned_comparison_operator (rtx op, enum machine_mode mode)
6187 return (comparison_operator (op, mode)
6188 && unsigned_condition (GET_CODE (op)) == GET_CODE (op));
6191 /* Worker function for TARGET_RETURN_IN_MEMORY. */
6194 ip2k_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
6196 if (TYPE_MODE (type) == BLKmode)
6198 HOST_WIDE_INT size = int_size_in_bytes (type);
6199 return (size == -1 || size > 8);
6205 /* Worker function for TARGET_SETUP_INCOMING_VARARGS. */
6208 ip2k_setup_incoming_varargs (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
6209 enum machine_mode mode ATTRIBUTE_UNUSED,
6210 tree type ATTRIBUTE_UNUSED,
6211 int *pretend_arg_size,
6212 int second_time ATTRIBUTE_UNUSED)
6214 *pretend_arg_size = 0;