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_ATTRIBUTE_TABLE
105 #define TARGET_ATTRIBUTE_TABLE ip2k_attribute_table
107 #undef TARGET_RTX_COSTS
108 #define TARGET_RTX_COSTS ip2k_rtx_costs
109 #undef TARGET_ADDRESS_COST
110 #define TARGET_ADDRESS_COST ip2k_address_cost
112 #undef TARGET_MACHINE_DEPENDENT_REORG
113 #define TARGET_MACHINE_DEPENDENT_REORG ip2k_reorg
115 #undef TARGET_INIT_LIBFUNCS
116 #define TARGET_INIT_LIBFUNCS ip2k_init_libfuncs
118 #undef TARGET_RETURN_IN_MEMORY
119 #define TARGET_RETURN_IN_MEMORY ip2k_return_in_memory
121 #undef TARGET_SETUP_INCOMING_VARARGS
122 #define TARGET_SETUP_INCOMING_VARARGS ip2k_setup_incoming_varargs
124 struct gcc_target targetm
= TARGET_INITIALIZER
;
126 /* Prologue/Epilogue size in words. */
127 static int prologue_size
;
128 static int epilogue_size
;
130 /* compare and test instructions for the IP2K are materialized by
131 the conditional branch that uses them. This is because conditional
132 branches are skips over unconditional branches. */
133 rtx ip2k_compare_operands
[3]; /* Additional operands for condition code. */
134 int ip2k_test_flag
; /* Indicates Z, WREG contain condition code
137 /* Some ip2k patterns push a byte onto the stack and then access
138 SP-relative addresses. Since reload doesn't know about these
139 pushes, we must track them internally with a %< (push) or %> (pop)
141 static int ip2k_stack_delta
;
143 /* Track if or how far our ip2k reorganization pass has run. */
144 int ip2k_reorg_in_progress
= 0;
145 int ip2k_reorg_completed
= 0;
146 int ip2k_reorg_split_dimode
= 0;
147 int ip2k_reorg_split_simode
= 0;
148 int ip2k_reorg_split_himode
= 0;
149 int ip2k_reorg_split_qimode
= 0;
150 int ip2k_reorg_merge_qimode
= 0;
152 /* Set up local allocation order. */
155 ip2k_init_local_alloc (int *rao
)
157 static const int alloc_order
[] = REG_ALLOC_ORDER
;
159 memcpy (rao
, alloc_order
, sizeof (alloc_order
));
162 /* Returns the number of bytes of arguments automatically
163 popped when returning from a subroutine call.
164 FUNDECL is the declaration node of the function (as a tree),
165 FUNTYPE is the data type of the function (as a tree),
166 or for a library call it is an identifier node for the subroutine name.
167 SIZE is the number of bytes of arguments passed on the stack. */
170 ip2k_return_pops_args (tree fundecl ATTRIBUTE_UNUSED
, tree funtype
, int size
)
172 if (TREE_CODE (funtype
) == IDENTIFIER_NODE
)
175 if (TYPE_ARG_TYPES (funtype
) == NULL_TREE
176 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype
))) == void_type_node
))
182 /* Return nonzero if FUNC is a naked function. */
185 ip2k_naked_function_p (tree func
)
189 if (TREE_CODE (func
) != FUNCTION_DECL
)
192 a
= lookup_attribute ("naked", DECL_ATTRIBUTES (func
));
193 return a
!= NULL_TREE
;
196 /* Output function prologue. */
198 function_prologue (FILE *file
, HOST_WIDE_INT size
)
205 prologue_size
= epilogue_size
= 0;
207 if (ip2k_naked_function_p (current_function_decl
))
209 fprintf (file
, "/* prologue: naked */\n");
213 leaf_func_p
= leaf_function_p ();
214 main_p
= MAIN_NAME_P (DECL_NAME (current_function_decl
));
216 /* For now, we compute all these facts about the function, but don't
217 take any action based on the information. */
220 fprintf (file
, "/* prologue: frame size=" HOST_WIDE_INT_PRINT_DEC
" */\n",
223 /* Unless we're a leaf we need to save the return PC. */
227 OUT_AS1 (push
, calll
);
228 OUT_AS1 (push
, callh
);
232 /* We need to save the old FP and set the new FP pointing at the
233 stack location where the old one is saved. Note that because of
234 post-decrement addressing, the SP is off-by-one after the
235 push, so we harvest the SP address BEFORE we push the MSBs of
239 OUT_AS1 (push
, REG_FP
+1); /* Save old LSBs. */
240 OUT_AS2 (mov
, w
, spl
);
241 OUT_AS2 (mov
, REG_FP
+1, w
); /* SPL -> FPL */
243 OUT_AS2 (mov
, w
, sph
); /* Freeze SP MSBs */
244 OUT_AS1 (push
, REG_FP
); /* Save old MSBs */
245 OUT_AS2 (mov
, REG_FP
, w
); /* SPH -> FPH */
249 for (reg
= (CHAIN_FRAMES
) ? (REG_FP
- 1) : (REG_FP
+ 1);
252 if (regs_ever_live
[reg
] && ! call_used_regs
[reg
])
254 fprintf (file
, "\t" AS1 (push
,%s
) "\n", reg_names
[reg
]);
261 operands
[0] = GEN_INT (size
);
272 OUT_AS2 (mov
, w
, %L0
);
273 OUT_AS2 (sub
, spl
, w
);
277 switch (size
& 0xff00)
286 if ((size
& 0xff) != ((size
>> 8) & 0xff))
287 OUT_AS2 (mov
, w
, %H0
); /* Otherwise W has value we want. */
288 OUT_AS2 (sub
, sph
, w
);
293 /* XXX - change this to use the carry-propagating subtract trick. */
294 if (flag_stack_check
)
296 OUT_AS2 (mov
, w
, sph
);
297 OUT_AS2 (cmp
, w
, #%%hi8data(_end));
298 OUT_AS1 (sc
, ); /* C == 0 -> hi8(edata) < sph */
301 OUT_AS1 (sz
, ); /* Z == 1 -> look at low byte */
303 OUT_AS1 (jmp
,0f
); /* sp < edata, so raise stack fault */
304 OUT_AS2 (mov
, w
, spl
);
305 OUT_AS2 (cmp
, w
, #%%lo8data(_end));
306 OUT_AS1 (sc
,); /* C==1 -> lo8(edata) >= spl */
310 output_asm_insn ("push\t$ff", operands
);
317 /* Output function epilogue. */
319 function_epilogue (FILE *file
, HOST_WIDE_INT size
)
323 rtx operands
[2]; /* Dummy used by OUT_ASn */
324 int args_locals_size
= current_function_args_size
;
325 int saved_regs_p
= 0;
328 /* Use this opportunity to reset the reorg flags! */
329 ip2k_reorg_in_progress
= 0;
330 ip2k_reorg_completed
= 0;
331 ip2k_reorg_split_dimode
= 0;
332 ip2k_reorg_split_simode
= 0;
333 ip2k_reorg_split_himode
= 0;
334 ip2k_reorg_split_qimode
= 0;
335 ip2k_reorg_merge_qimode
= 0;
337 if (ip2k_naked_function_p (current_function_decl
))
339 fprintf (file
, "/* epilogue: naked */\n");
343 leaf_func_p
= leaf_function_p ();
345 fprintf (file
, "/* epilogue: frame size=" HOST_WIDE_INT_PRINT_DEC
" */\n",
348 savelimit
= (CHAIN_FRAMES
) ? REG_FP
: (REG_FP
+ 2);
349 for (reg
= 0; reg
< savelimit
; reg
++)
350 if (regs_ever_live
[reg
] && ! call_used_regs
[reg
])
358 if (leaf_func_p
&& !CHAIN_FRAMES
&& !saved_regs_p
359 && current_function_pops_args
)
360 args_locals_size
= current_function_args_size
+ size
;
363 operands
[0] = GEN_INT (size
);
368 OUT_AS2 (mov
, w
, %L0
);
369 OUT_AS2 (add
, spl
, w
);
379 switch (size
& 0xff00)
382 if ((size
& 0xff) != ((size
>> 8) & 0xff))
383 OUT_AS2 (mov
, w
, %H0
);
384 OUT_AS2 (add
, sph
, w
);
396 for (reg
= 0; reg
< savelimit
; reg
++)
398 if (regs_ever_live
[reg
] && ! call_used_regs
[reg
])
400 fprintf (file
, "\t" AS1 (pop
,%s
) "\n", reg_names
[reg
]);
406 && ! (current_function_pops_args
407 && current_function_args_size
>= 2
408 && current_function_args_size
< 0x100))
410 OUT_AS1 (pop
, REG_FP
);
411 OUT_AS1 (pop
, REG_FP
+1);
417 if (current_function_pops_args
418 && current_function_args_size
>= 2
419 && current_function_args_size
< 0x100)
421 if (current_function_args_size
== 2)
425 OUT_AS1 (page
, __fp_pop2_args_ret
);
426 OUT_AS1 (jmp
, __fp_pop2_args_ret
);
430 OUT_AS1 (page
, __pop2_args_ret
);
431 OUT_AS1 (jmp
, __pop2_args_ret
);
437 operands
[0] = GEN_INT (current_function_args_size
);
438 OUT_AS2 (mov
, w
, %L0
);
441 OUT_AS1 (page
, __fp_pop_args_ret
);
442 OUT_AS1 (jmp
, __fp_pop_args_ret
);
446 OUT_AS1 (page
, __pop_args_ret
);
447 OUT_AS1 (jmp
, __pop_args_ret
);
455 OUT_AS1 (pop
, callh
);
456 OUT_AS1 (pop
, calll
);
462 if (current_function_pops_args
463 && args_locals_size
>= 2
464 && args_locals_size
< 0x100)
466 if (args_locals_size
== 2)
470 OUT_AS1 (page
, __leaf_fp_pop2_args_ret
);
471 OUT_AS1 (jmp
, __leaf_fp_pop2_args_ret
);
478 operands
[0] = GEN_INT (args_locals_size
);
481 OUT_AS2 (mov
, w
, %L0
);
482 OUT_AS1 (page
, __leaf_fp_pop_args_ret
);
483 OUT_AS1 (jmp
, __leaf_fp_pop_args_ret
);
491 if (current_function_pops_args
&& args_locals_size
&& need_ret
)
493 operands
[0] = GEN_INT (args_locals_size
);
495 switch (args_locals_size
& 0xff)
498 OUT_AS2 (mov
, w
, %L0
);
499 OUT_AS2 (add
, spl
, w
);
511 switch (args_locals_size
& 0xff00)
514 if ((args_locals_size
& 0xff) != ((args_locals_size
>> 8) & 0xff))
515 OUT_AS2 (mov
, w
, %H0
);
516 OUT_AS2 (add
, sph
, w
);
535 fprintf (file
, "/* epilogue end (size=%d) */\n", epilogue_size
);
538 /* Return the difference between the registers after the function
541 Stack Frame grows down:
544 <------ AP ($102:$103)
545 RETURN PC (unless leaf function)
547 <------ FP [HARD_FRAME_POINTER] ($FD:$FE)
549 <------ VFP [$100:$101]
551 <------ SP ($6:$7) */
553 ip2k_init_elim_offset (int from
, int to
)
555 int leaf_func_p
= leaf_function_p ();
556 int no_saved_pc
= leaf_func_p
557 || ip2k_naked_function_p (current_function_decl
);
562 if (from
== FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
563 return get_frame_size () + 1;
565 if (from
== ARG_POINTER_REGNUM
&& to
== HARD_FRAME_POINTER_REGNUM
)
566 return (CHAIN_FRAMES
? 2 : 0) + (no_saved_pc
? 0 : 2);
568 /* Count all the registers we had to preserve. */
570 reglimit
= CHAIN_FRAMES
? REG_FP
: (REG_FP
+ 2);
571 for (offset
= 0,reg
= 0; reg
< reglimit
; ++reg
)
573 if ((regs_ever_live
[reg
] && ! call_used_regs
[reg
]))
579 if (from
== FRAME_POINTER_REGNUM
&& to
== HARD_FRAME_POINTER_REGNUM
)
582 if (from
== HARD_FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
583 /* Add in the stack-local variables. */
584 return offset
+ get_frame_size () + 1;
586 if (from
== ARG_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
587 /* Add stack-locals plus saved FP and PC. */
588 return offset
+ get_frame_size () + 1
589 + (CHAIN_FRAMES
? 2 : 0) + (no_saved_pc
? 0 : 2);
591 abort (); /* Unanticipated elimination. */
594 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
595 machine for a memory operand of mode MODE. */
598 legitimate_address_p (enum machine_mode mode
, rtx x
, int strict
)
602 if (GET_CODE (x
) == SUBREG
)
605 switch (GET_CODE (x
))
608 /* IP allows indirection without offset - only okay if
609 we don't require access to multiple bytes. */
610 if (REGNO (x
) == REG_IP
)
611 return (GET_MODE_SIZE (mode
) == 1) ? 'R' : 0;
613 /* We can indirect through DP or SP register. */
614 if (strict
? REG_OK_FOR_BASE_STRICT_P (x
)
615 : REG_OK_FOR_BASE_NOSTRICT_P (x
))
620 /* Offsets from DP or SP are legal in the range 0..127 */
627 if (REG_P (op2
) && ! REG_P (op1
))
634 /* Don't let anything but R+I through.. */
637 || GET_CODE (op2
) != CONST_INT
)
642 case REG_DP
: /* only 0..127 displacement */
644 off
= 2 * GET_MODE_SIZE (mode
);
648 if (INTVAL (op2
) < 0 || INTVAL (op2
) > (128 - off
))
649 return 0; /* Positive must be small enough that after
650 splitting all pieces are addressed. */
651 return 'S'; /* Safe displacement. */
654 if (GET_MODE_SIZE (mode
) <= 1 && INTVAL (op2
) == 0)
655 return (GET_MODE_SIZE (mode
) == 1) ? 'R' : 0;
662 if (strict
|| ! REG_OK_FOR_BASE_NOSTRICT_P (op1
))
663 return 0; /* Allow until reload. */
672 /* We always allow references to things in code space. */
673 return is_regfile_address (x
) ? 0 : 'C';
685 /* Is ADDR mode dependent? */
687 ip2k_mode_dependent_address (rtx addr
)
689 switch (GET_CODE (addr
))
698 return (REGNO (addr
) == REG_IP
); /* Can't do IP displaced addresses. */
701 return 0; /* Assume no dependency. */
705 /* Attempts to replace X with a valid
706 memory address for an operand of mode MODE. */
709 legitimize_address (rtx x
, rtx oldx ATTRIBUTE_UNUSED
,
710 enum machine_mode mode ATTRIBUTE_UNUSED
, rtx scratch
)
714 /* You might think that we could split up a symbolic address by
715 adding the HIGH 8 bits and doing a displacement off the dp. But
716 because we only have 7 bits of offset, that doesn't actually
717 help. So only constant displacements are likely to obtain an
720 if (GET_CODE (x
) == PLUS
&& REG_P (XEXP (x
, 0))
721 && GET_CODE (XEXP (x
, 1)) == CONST_INT
722 && ! CONST_OK_FOR_LETTER_P (INTVAL (XEXP (x
, 1)), 'K'))
724 int offset
= INTVAL (XEXP (x
, 1));
726 reg
= scratch
? scratch
: gen_reg_rtx (Pmode
);
728 emit_insn (gen_rtx_SET (VOIDmode
, reg
,
729 gen_rtx_PLUS (Pmode
, XEXP (x
, 0),
730 GEN_INT (offset
& 0xffc0))));
731 x
= gen_rtx_PLUS (Pmode
, reg
, GEN_INT (offset
& 0x3f));
734 return x
; /* We don't have any other tricks. */
737 /* Determine if X is a 'data' address or a code address. All static
738 data and stack variables reside in data memory. Only code is believed
739 to be in PRAM or FLASH. */
741 is_regfile_address (rtx x
)
744 switch (GET_CODE (x
))
747 return ! SYMBOL_REF_FUNCTION_P (x
); /* Declared as function. */
765 /* Output ADDR to FILE as address. */
768 print_operand_address (FILE *file
, rtx addr
)
770 switch (GET_CODE (addr
))
773 addr
= alter_subreg (&addr
);
777 fprintf (file
, "(%s)",
778 REGNO (addr
) == REG_DP
? "DP"
779 : REGNO (addr
) == REG_SP
? "SP"
780 : REGNO (addr
) == REG_IP
? "IP"
781 : REGNO (addr
) == REG_VFP
? "VFP" /* Should never see this */
782 : REGNO (addr
) == REG_AP
? "AP" /* or this, either. */
783 : reg_names
[REGNO (addr
)]);
792 addr
= XEXP (addr
, 0);
793 print_operand_address (file
, XEXP (addr
, 0));
795 print_operand_address (file
, XEXP (addr
, 1));
799 if (is_regfile_address (XEXP (addr
, 1)))
800 fprintf (file
, "%%lo8data(");
802 fprintf (file
, "%%lo8insn(");
803 print_operand_address (file
, XEXP (addr
, 1));
805 print_operand_address (file
, XEXP (addr
, 0));
808 case PLUS
: /* Ought to be stack or dp references. */
809 if (XEXP (addr
, 1) == const0_rtx
810 && GET_CODE (XEXP (addr
, 0)) == PLUS
)
812 print_operand_address (file
, XEXP (addr
, 0));
816 if (! REG_P (XEXP (addr
, 0)) || REGNO (XEXP (addr
, 0)) != REG_IP
)
817 print_operand_address (file
, XEXP (addr
, 1)); /* const */
818 print_operand_address (file
, XEXP (addr
, 0)); /* (reg) */
822 if (is_regfile_address (XEXP (addr
, 0)))
823 fprintf (file
, "%%hi8data(");
825 fprintf (file
, "%%hi8insn(");
826 output_addr_const (file
, XEXP (addr
, 0));
831 output_addr_const (file
, addr
);
836 /* Output X as assembler operand to file FILE. */
839 print_operand (FILE *file
, rtx x
, int code
)
883 if (ip2k_short_operand (x
, GET_MODE (x
))
884 && ip2k_address_uses_reg_p (x
, REG_SP
))
885 /* An SP-relative address needs to account for interior stack
886 pushes that reload didn't know about when it calculated the
888 abcd
+= ip2k_stack_delta
;
890 switch (GET_CODE (x
))
893 x
= alter_subreg (&x
);
897 fprintf (file
, reg_names
[true_regnum (x
) + abcd
]);
904 fprintf (file
, "$%x", (int)(INTVAL (x
) & 0xffff));
908 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
)); /* bit selector */
911 case 'e': /* "1 << n" - e.g. "exp" */
912 fprintf (file
, "#%d", 1 << INTVAL (x
));
920 value
>>= 8 * (3 - abcd
);
923 fprintf (file
, "#%ld", value
);
927 fprintf (file
, "#%d", (int)((INTVAL (x
) >> 8) & 0xff));
931 fprintf (file
, "#%d", (int)(INTVAL (x
) & 0xff));
942 value
= ((unsigned long long)INTVAL (x
)) >> (8 * (7 - abcd
)) & 0xff;
943 fprintf (file
, "#%ld", value
);
947 fprintf (file
, "#" HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
));
969 abort (); /* Probably an error. */
973 fprintf (file
, "#%s(",
974 is_regfile_address (x
) ? "%hi8data"
976 print_operand_address (file
, x
);
981 fprintf (file
, "#%s(",
982 is_regfile_address (x
) ? "%lo8data"
984 print_operand_address (file
, x
);
989 print_operand_address (file
, x
);
995 rtx addr
= XEXP (x
, 0);
997 if (GET_CODE (addr
) == SUBREG
)
998 addr
= alter_subreg (&x
);
1000 if (CONSTANT_P (addr
) && abcd
)
1003 print_operand_address (file
, addr
);
1004 fprintf (file
, ")+%d", abcd
);
1008 switch (GET_CODE (addr
))
1011 abcd
+= INTVAL (XEXP (addr
, 1));
1013 /* Worry about (plus (plus (reg DP) (const_int 10))
1015 if (GET_CODE (XEXP (addr
, 0)) == PLUS
)
1017 addr
= XEXP (addr
, 0);
1018 abcd
+= INTVAL (XEXP (addr
, 1));
1021 fprintf (file
, "%d", abcd
);
1022 print_operand_address (file
, XEXP (addr
, 0));
1027 fprintf (file
, "%d", abcd
);
1028 print_operand_address (file
, addr
);
1031 else if (GET_CODE (addr
) == REG
1032 && (REGNO (addr
) == REG_DP
|| REGNO (addr
) == REG_SP
))
1034 fprintf (file
, "0");
1035 print_operand_address (file
, addr
);
1038 print_operand_address (file
, addr
);
1043 /* Is this an integer or a floating point value? */
1044 if (GET_MODE (x
) == VOIDmode
)
1052 value
= CONST_DOUBLE_HIGH (x
);
1053 value
>>= 8 * (3 - abcd
);
1056 fprintf (file
, "#%ld", value
);
1063 value
= CONST_DOUBLE_LOW (x
);
1064 value
>>= 8 * (7 - abcd
);
1067 fprintf (file
, "#%ld", value
);
1076 REAL_VALUE_FROM_CONST_DOUBLE (rv
, x
);
1077 REAL_VALUE_TO_TARGET_SINGLE (rv
, value
);
1078 fprintf (file
, "0x%lx", value
);
1083 fatal_insn ("bad operand", x
);
1087 /* Remember the operands for the compare. */
1089 ip2k_set_compare (rtx x
, rtx y
)
1091 ip2k_compare_operands
[0] = x
;
1092 ip2k_compare_operands
[1] = y
;
1096 /* Emit the code for sCOND instructions. */
1098 ip2k_gen_sCOND (rtx insn ATTRIBUTE_UNUSED
, enum rtx_code code
, rtx dest
)
1100 #define operands ip2k_compare_operands
1101 enum machine_mode mode
;
1105 mode
= GET_MODE (operands
[0]);
1106 if ((mode
!= QImode
) && (mode
!= HImode
)
1107 && (mode
!= SImode
) && (mode
!= DImode
))
1108 mode
= GET_MODE (operands
[1]);
1110 /* We have a fast path for a specific type of QImode compare. We ought
1111 to extend this for larger cases too but that wins less frequently and
1112 introduces a lot of complexity. */
1114 && !rtx_equal_p (operands
[0], operands
[2])
1115 && !rtx_equal_p (operands
[1], operands
[2])
1116 && (! REG_P (operands
[2])
1117 || (ip2k_xexp_not_uses_reg_p (operands
[0], REGNO (operands
[2]), 1)
1118 && ip2k_xexp_not_uses_reg_p (operands
[1],
1119 REGNO (operands
[2]), 1))))
1122 if (immediate_operand (operands
[1], QImode
)
1123 && ((INTVAL (operands
[1]) & 0xff) == 0xff))
1126 OUT_AS2 (incsnz
, w
, %0);
1128 OUT_AS2 (incsz
, w
, %0);
1130 else if (immediate_operand (operands
[1], QImode
)
1131 && ((INTVAL (operands
[1]) & 0xff) == 0x01))
1134 OUT_AS2 (decsnz
, w
, %0);
1136 OUT_AS2 (decsz
, w
, %0);
1138 else if (ip2k_compare_operands
[1] == const0_rtx
)
1140 OUT_AS2 (mov
, w
, %0);
1148 OUT_AS2 (mov
, w
, %0);
1150 OUT_AS2 (csne
, w
, %1);
1152 OUT_AS2 (cse
, w
, %1);
1158 if (ip2k_compare_operands
[1] == const0_rtx
)
1163 OUT_AS2 (mov
, w
, %0);
1167 OUT_AS2 (mov
, w
, %H0
);
1168 OUT_AS2 (or, w
, %L0
);
1172 OUT_AS2 (mov
, w
, %A0
);
1173 OUT_AS2 (or, w
, %B0
);
1174 OUT_AS2 (or, w
, %C0
);
1175 OUT_AS2 (or, w
, %D0
);
1179 OUT_AS2 (mov
, w
, %S0
);
1180 OUT_AS2 (or, w
, %T0
);
1181 OUT_AS2 (or, w
, %U0
);
1182 OUT_AS2 (or, w
, %V0
);
1183 OUT_AS2 (or, w
, %W0
);
1184 OUT_AS2 (or, w
, %X0
);
1185 OUT_AS2 (or, w
, %Y0
);
1186 OUT_AS2 (or, w
, %Z0
);
1198 OUT_AS2 (mov
, w
, %1);
1199 OUT_AS2 (cmp
, w
, %0);
1203 OUT_AS2 (mov
, w
, %H1
);
1204 OUT_AS2 (cmp
, w
, %H0
);
1208 OUT_AS2 (mov
, w
, %L1
);
1209 OUT_AS2 (cmp
, w
, %L0
);
1216 OUT_AS2 (mov
, w
, #1);
1217 OUT_AS2 (mov
, mulh
, w
);
1220 OUT_AS1 (clr
, mulh
);
1221 OUT_AS2 (mov
, w
, %A1
);
1222 OUT_AS2 (cse
, w
, %A0
);
1225 OUT_AS2 (mov
, w
, %B1
);
1226 OUT_AS2 (cse
, w
, %B0
);
1229 OUT_AS2 (mov
, w
, %C1
);
1230 OUT_AS2 (cse
, w
, %C0
);
1233 OUT_AS2 (mov
, w
, %D1
);
1234 OUT_AS2 (cse
, w
, %D0
);
1237 OUT_AS1 (dec
, mulh
);
1239 OUT_AS1 (inc
, mulh
);
1240 OUT_AS2 (mov
, w
, mulh
);
1241 OUT_AS2 (mov
, %2, w
);
1247 OUT_AS2 (mov
, w
, #1);
1248 OUT_AS2 (mov
, mulh
, w
);
1251 OUT_AS1 (clr
, mulh
);
1252 OUT_AS2 (mov
, w
, %S1
);
1253 OUT_AS2 (cse
, w
, %S0
);
1256 OUT_AS2 (mov
, w
, %T1
);
1257 OUT_AS2 (cse
, w
, %T0
);
1260 OUT_AS2 (mov
, w
, %U1
);
1261 OUT_AS2 (cse
, w
, %U0
);
1264 OUT_AS2 (mov
, w
, %V1
);
1265 OUT_AS2 (cse
, w
, %V0
);
1268 OUT_AS2 (mov
, w
, %W1
);
1269 OUT_AS2 (cse
, w
, %W0
);
1272 OUT_AS2 (mov
, w
, %X1
);
1273 OUT_AS2 (cse
, w
, %X0
);
1276 OUT_AS2 (mov
, w
, %Y1
);
1277 OUT_AS2 (cse
, w
, %Y0
);
1280 OUT_AS2 (mov
, w
, %Z1
);
1281 OUT_AS2 (cse
, w
, %Z0
);
1284 OUT_AS1 (dec
, mulh
);
1286 OUT_AS1 (inc
, mulh
);
1287 OUT_AS2 (mov
, w
, mulh
);
1288 OUT_AS2 (mov
, %2, w
);
1295 OUT_AS2 (mov
, w
, #0);
1300 OUT_AS1 (inc
, wreg
);
1301 OUT_AS2 (mov
, %2, w
);
1309 ip2k_gen_signed_comp_branch (rtx insn
, enum rtx_code code
, rtx label
)
1311 #define operands ip2k_compare_operands
1312 enum machine_mode mode
;
1313 int can_use_skip
= 0;
1316 operands
[2] = label
;
1318 mode
= GET_MODE (operands
[0]);
1319 if ((mode
!= QImode
) && (mode
!= HImode
)
1320 && (mode
!= SImode
) && (mode
!= DImode
))
1321 mode
= GET_MODE (operands
[1]);
1323 /* Look for situations where we can just skip the next instruction instead
1324 of skipping and then branching! */
1325 ninsn
= next_real_insn (insn
);
1327 && (recog_memoized (ninsn
) >= 0)
1328 && get_attr_skip (ninsn
) == SKIP_YES
)
1330 rtx skip_tgt
= next_nonnote_insn (next_real_insn (insn
));
1332 /* The first situation is where the target of the jump is one insn
1333 after the jump insn and the insn being jumped is only one machine
1335 if (label
== skip_tgt
)
1339 /* If our skip target is in fact a code label then we ignore the
1340 label and move onto the next useful instruction. Nothing we do
1341 here has any effect on the use of skipping instructions. */
1342 if (GET_CODE (skip_tgt
) == CODE_LABEL
)
1343 skip_tgt
= next_nonnote_insn (skip_tgt
);
1345 /* The second situation is where we have something of the form:
1351 optional_label (this may or may not exist):
1355 In this case we can eliminate the first "page/jump label". */
1356 if (GET_CODE (skip_tgt
) == JUMP_INSN
)
1358 rtx set
= single_set (skip_tgt
);
1359 if (GET_CODE (XEXP (set
, 0)) == PC
1360 && GET_CODE (XEXP (set
, 1)) == LABEL_REF
1361 && label
== JUMP_LABEL (skip_tgt
))
1367 /* gcc is a little braindead and does some rather stateful things while
1368 inspecting attributes - we have to put this state back to what it's
1370 extract_constrain_insn_cached (insn
);
1372 if (ip2k_compare_operands
[1] == const0_rtx
) /* These are easier. */
1379 OUT_AS2 (sb
, %0, 7);
1383 OUT_AS2 (snb
, %0, 7);
1393 OUT_AS2 (rl
, w
, %S0
);
1394 OUT_AS2 (mov
, w
, %S0
);
1395 OUT_AS2 (or, w
, %T0
);
1396 OUT_AS2 (or, w
, %U0
);
1397 OUT_AS2 (or, w
, %V0
);
1398 OUT_AS2 (or, w
, %W0
);
1399 OUT_AS2 (or, w
, %X0
);
1400 OUT_AS2 (or, w
, %Y0
);
1401 OUT_AS2 (or, w
, %Z0
);
1403 OUT_AS2 (setb
, status
, 0);
1404 OUT_AS2 (sb
, status
, 0);
1410 OUT_AS2 (rl
, w
, %A0
);
1411 OUT_AS2 (mov
, w
, %A0
);
1412 OUT_AS2 (or, w
, %B0
);
1413 OUT_AS2 (or, w
, %C0
);
1414 OUT_AS2 (or, w
, %D0
);
1416 OUT_AS2 (setb
, status
, 0);
1417 OUT_AS2 (sb
, status
, 0);
1423 OUT_AS2 (rl
, w
, %H0
);
1424 OUT_AS2 (mov
, w
, %H0
);
1425 OUT_AS2 (or, w
, %L0
);
1427 OUT_AS2 (setb
, status
, 0);
1428 OUT_AS2 (sb
, status
, 0);
1434 OUT_AS2 (mov
, w
, %0); /* Will just do "sb w, 7". */
1436 OUT_AS2 (setb
, wreg
, 7);
1437 OUT_AS2 (sb
, wreg
, 7);
1451 OUT_AS2 (mov
, w
, %S0
);
1452 OUT_AS2 (or, w
, %T0
);
1453 OUT_AS2 (or, w
, %U0
);
1454 OUT_AS2 (or, w
, %V0
);
1455 OUT_AS2 (or, w
, %W0
);
1456 OUT_AS2 (or, w
, %X0
);
1457 OUT_AS2 (or, w
, %Y0
);
1458 OUT_AS2 (or, w
, %Z0
); /* Z is correct. */
1460 OUT_AS2 (snb
, %S0
, 7);
1466 OUT_AS2 (mov
, w
, %A0
);
1467 OUT_AS2 (or, w
, %B0
);
1468 OUT_AS2 (or, w
, %C0
);
1469 OUT_AS2 (or, w
, %D0
); /* Z is correct. */
1471 OUT_AS2 (snb
, %A0
, 7);
1477 OUT_AS2 (mov
, w
, %H0
);
1478 OUT_AS2 (or, w
, %L0
);
1480 OUT_AS2 (snb
, %H0
, 7);
1486 OUT_AS2 (mov
, w
, %0); /* Will just do "sb w, 7". */
1488 OUT_AS2 (snb
, wreg
, 7);
1501 OUT_AS2 (snb
, %0, 7);
1505 OUT_AS2 (sb
, %0, 7);
1517 /* signed compares are out of line because we can't get
1518 the hardware to compute the overflow for us. */
1523 OUT_AS1 (push
, %1%<);
1524 OUT_AS1 (push
, %0%>);
1525 OUT_AS1 (page
, __cmpqi2
);
1526 OUT_AS1 (call
, __cmpqi2
);
1530 OUT_AS1 (push
, %L1
%<);
1531 OUT_AS1 (push
, %H1
%<);
1532 OUT_AS1 (push
, %L0
%<);
1533 OUT_AS1 (push
, %H0
%>%>%>);
1534 OUT_AS1 (page
, __cmphi2
);
1535 OUT_AS1 (call
, __cmphi2
);
1539 OUT_AS1 (push
, %D1
%<);
1540 OUT_AS1 (push
, %C1
%<);
1541 OUT_AS1 (push
, %B1
%<);
1542 OUT_AS1 (push
, %A1
%<);
1543 OUT_AS1 (push
, %D0
%<);
1544 OUT_AS1 (push
, %C0
%<);
1545 OUT_AS1 (push
, %B0
%<);
1546 OUT_AS1 (push
, %A0
%>%>%>%>%>%>%>);
1547 OUT_AS1 (page
, __cmpsi2
);
1548 OUT_AS1 (call
, __cmpsi2
);
1552 if (GET_CODE (operands
[0]) == MEM
1553 && true_regnum (XEXP (operands
[0], 0)) == REG_DP
)
1555 OUT_AS1 (push
, %Z1
%<);
1556 OUT_AS1 (push
, %Y1
%<);
1557 OUT_AS1 (push
, %X1
%<);
1558 OUT_AS1 (push
, %W1
%<);
1559 OUT_AS1 (push
, %V1
%<);
1560 OUT_AS1 (push
, %U1
%<);
1561 OUT_AS1 (push
, %T1
%<);
1562 OUT_AS1 (push
, %S1
%>%>%>%>%>%>%>);
1563 OUT_AS1 (page
, __cmpdi2_dp
);
1564 OUT_AS1 (call
, __cmpdi2_dp
);
1568 OUT_AS1 (push
, %Z1
%<);
1569 OUT_AS1 (push
, %Y1
%<);
1570 OUT_AS1 (push
, %X1
%<);
1571 OUT_AS1 (push
, %W1
%<);
1572 OUT_AS1 (push
, %V1
%<);
1573 OUT_AS1 (push
, %U1
%<);
1574 OUT_AS1 (push
, %T1
%<);
1575 OUT_AS1 (push
, %S1
%<);
1576 OUT_AS1 (push
, %Z0
%<);
1577 OUT_AS1 (push
, %Y0
%<);
1578 OUT_AS1 (push
, %X0
%<);
1579 OUT_AS1 (push
, %W0
%<);
1580 OUT_AS1 (push
, %V0
%<);
1581 OUT_AS1 (push
, %U0
%<);
1582 OUT_AS1 (push
, %T0
%<);
1583 OUT_AS1 (push
, %S0
%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>);
1584 OUT_AS1 (page
, __cmpdi2
);
1585 OUT_AS1 (call
, __cmpdi2
);
1598 OUT_AS2 (cse
, w
, #0);
1602 OUT_AS2 (csne
, w
, #0);
1611 OUT_AS2 (cse
, w
, #2);
1615 OUT_AS2 (csne
, w
, #2);
1624 OUT_AS2 (snb
, wreg
, 1);
1628 OUT_AS2 (sb
, wreg
, 1);
1637 OUT_AS2 (csne
, w
, #0);
1641 OUT_AS2 (cse
, w
, #0);
1655 ip2k_gen_unsigned_comp_branch (rtx insn
, enum rtx_code code
, rtx label
)
1657 #define operands ip2k_compare_operands
1658 enum machine_mode mode
;
1661 int can_use_skip
= 0;
1663 HOST_WIDE_INT const_low
;
1664 HOST_WIDE_INT const_high
;
1666 operands
[2] = label
;
1668 mode
= GET_MODE (operands
[0]);
1669 if ((mode
!= QImode
) && (mode
!= HImode
) && (mode
!= SImode
)
1670 && (mode
!= DImode
))
1672 mode
= GET_MODE (operands
[1]);
1675 /* Look for situations where we can just skip the next instruction instead
1676 of skipping and then branching! */
1677 ninsn
= next_real_insn (insn
);
1679 && (recog_memoized (ninsn
) >= 0)
1680 && get_attr_skip (ninsn
) == SKIP_YES
)
1682 rtx skip_tgt
= next_nonnote_insn (next_real_insn (insn
));
1684 /* The first situation is where the target of the jump is one insn
1685 after the jump insn and the insn being jumped is only one machine
1687 if (label
== skip_tgt
)
1691 /* If our skip target is in fact a code label then we ignore the
1692 label and move onto the next useful instruction. Nothing we do
1693 here has any effect on the use of skipping instructions. */
1694 if (GET_CODE (skip_tgt
) == CODE_LABEL
)
1695 skip_tgt
= next_nonnote_insn (skip_tgt
);
1697 /* The second situation is where we have something of the form:
1703 optional_label (this may or may not exist):
1707 In this case we can eliminate the first "page/jump label". */
1708 if (GET_CODE (skip_tgt
) == JUMP_INSN
)
1710 rtx set
= single_set (skip_tgt
);
1711 if (GET_CODE (XEXP (set
, 0)) == PC
1712 && GET_CODE (XEXP (set
, 1)) == LABEL_REF
1713 && label
== JUMP_LABEL (skip_tgt
))
1719 /* gcc is a little braindead and does some rather stateful things while
1720 inspecting attributes - we have to put this state back to what it's
1722 extract_constrain_insn_cached (insn
);
1724 if (ip2k_compare_operands
[1] == const0_rtx
)
1729 code
= EQ
; /* Nothing is LTU 0. */
1733 code
= NE
; /* Anything nonzero is GTU. */
1737 case NE
: /* Test all the bits, result in
1743 OUT_AS2 (mov
, w
, %S0
);
1744 OUT_AS2 (or, w
, %T0
);
1745 OUT_AS2 (or, w
, %U0
);
1746 OUT_AS2 (or, w
, %V0
);
1747 OUT_AS2 (or, w
, %W0
);
1748 OUT_AS2 (or, w
, %X0
);
1749 OUT_AS2 (or, w
, %Y0
);
1750 OUT_AS2 (or, w
, %Z0
);
1754 OUT_AS2 (mov
, w
, %A0
);
1755 OUT_AS2 (or, w
, %B0
);
1756 OUT_AS2 (or, w
, %C0
);
1757 OUT_AS2 (or, w
, %D0
);
1761 OUT_AS2 (mov
, w
, %H0
);
1762 OUT_AS2 (or, w
, %L0
);
1766 OUT_AS2 (mov
, w
, %0);
1792 /* Always succeed. */
1807 /* Look at whether we have a constant as one of our operands. If we do
1808 and it's in the position that we use to subtract from during our
1809 normal optimized comparison concept then we have to shuffle things
1813 if ((immediate_operand (operands
[1], GET_MODE (operands
[1]))
1814 && ((code
== LEU
) || (code
== GTU
)))
1815 || (immediate_operand (operands
[0], GET_MODE (operands
[0]))
1816 && ((code
== LTU
) || (code
== GEU
))))
1822 /* Same as above - look if we have a constant that we can compare
1823 for equality or non-equality. If we know this then we can look
1824 for common value eliminations. Note that we want to ensure that
1825 any immediate value is operand 1 to simplify the code later! */
1826 if ((code
== EQ
) || (code
== NE
))
1828 imm_cmp
= immediate_operand (operands
[1], GET_MODE (operands
[1]));
1831 imm_cmp
= immediate_operand (operands
[0], GET_MODE (operands
[0]));
1834 rtx tmp
= operands
[1];
1835 operands
[1] = operands
[0];
1847 if (imm_cmp
&& ((INTVAL (operands
[1]) & 0xff) == 0xff))
1848 OUT_AS2 (incsnz
, w
, %0);
1849 else if (imm_cmp
&& ((INTVAL (operands
[1]) & 0xff) == 0x01))
1850 OUT_AS2 (decsnz
, w
, %0);
1853 OUT_AS2 (mov
, w
, %1);
1854 OUT_AS2 (csne
, w
, %0);
1861 if (imm_cmp
&& ((INTVAL (operands
[1]) & 0xff) == 0xff))
1862 OUT_AS2 (incsz
, w
, %0);
1863 else if (imm_cmp
&& ((INTVAL (operands
[1]) & 0xff) == 0x01))
1864 OUT_AS2 (decsz
, w
, %0);
1867 OUT_AS2 (mov
, w
, %1);
1868 OUT_AS2 (cse
, w
, %0);
1875 OUT_AS2 (mov
, w
, %0);
1876 OUT_AS2 (cmp
, w
, %1);
1883 OUT_AS2 (mov
, w
, %1);
1884 OUT_AS2 (cmp
, w
, %0);
1891 OUT_AS2 (mov
, w
, %1);
1892 OUT_AS2 (cmp
, w
, %0);
1899 OUT_AS2 (mov
, w
, %0);
1900 OUT_AS2 (cmp
, w
, %1);
1916 unsigned char h
= 0, l
= 1;
1920 h
= (INTVAL (operands
[1]) >> 8) & 0xff;
1921 l
= INTVAL (operands
[1]) & 0xff;
1923 if ((h
== 0xff) && (l
== 0xff))
1925 /* We should be able to do the following, but the
1926 IP2k simulator doesn't like it and we get a load
1927 of failures in gcc-c-torture. */
1928 OUT_AS2 (incsnz
, w
, %L0
);
1929 OUT_AS2 (incsz
, w
, %H0
);
1930 /* OUT_AS1 (skip,); Should have this */
1931 OUT_AS1 (page
, 1f
);/* Shouldn't need this! */
1932 OUT_AS1 (jmp
, 1f
); /* Shouldn't need this either. */
1941 OUT_AS2 (dec
, w
, %L0
);
1944 OUT_AS2 (mov
, w
, %L0
);
1945 OUT_AS2 (sub
, w
, %L1
);
1947 OUT_AS2 (or, w
, %H0
);
1956 OUT_AS2 (dec
, w
, %H0
);
1959 OUT_AS2 (mov
, w
, %H0
);
1960 OUT_AS2 (sub
, w
, %H1
);
1962 OUT_AS2 (or, w
, %L0
);
1970 OUT_AS2 (mov
, w
, %H1
);
1971 OUT_AS2 (cse
, w
, %H0
);
1974 if (! imm_cmp
|| (h
!= l
))
1975 OUT_AS2 (mov
, w
, %L1
);
1976 OUT_AS2 (csne
, w
, %L0
);
1985 unsigned char h
= 0, l
= 1;
1989 h
= (INTVAL (operands
[1]) >> 8) & 0xff;
1990 l
= INTVAL (operands
[1]) & 0xff;
1992 if ((h
== 0xff) && (l
== 0xff))
1994 OUT_AS2 (incsnz
, w
, %L0
);
1995 OUT_AS2 (incsz
, w
, %H0
);
2003 OUT_AS2 (dec
, w
, %L0
);
2006 OUT_AS2 (mov
, w
, %L0
);
2007 OUT_AS2 (sub
, w
, %L1
);
2009 OUT_AS2 (or, w
, %H0
);
2018 OUT_AS2 (dec
, w
, %H0
);
2021 OUT_AS2 (mov
, w
, %H0
);
2022 OUT_AS2 (sub
, w
, %H1
);
2024 OUT_AS2 (or, w
, %L0
);
2032 OUT_AS2 (mov
, w
, %H1
);
2033 if (imm_cmp
&& (h
== l
))
2035 OUT_AS2 (csne
, w
, %H0
);
2036 OUT_AS2 (cse
, w
, %L0
);
2040 OUT_AS2 (cse
, w
, %H0
);
2043 OUT_AS2 (mov
, w
, %L1
);
2044 OUT_AS2 (cse
, w
, %L0
);
2054 /* > 0xffff never succeeds! */
2055 if ((INTVAL (operands
[1]) & 0xffff) != 0xffff)
2057 operands
[3] = GEN_INT (INTVAL (operands
[1]) + 1);
2058 OUT_AS2 (mov
, w
, %L3
);
2059 OUT_AS2 (sub
, w
, %L0
);
2060 OUT_AS2 (mov
, w
, %H3
);
2061 OUT_AS2 (subc
, w
, %H0
);
2069 OUT_AS2 (mov
, w
, %L0
);
2070 OUT_AS2 (sub
, w
, %L1
);
2071 OUT_AS2 (mov
, w
, %H0
);
2072 OUT_AS2 (subc
, w
, %H1
);
2082 if (INTVAL (operands
[0]) == 0)
2084 OUT_AS2 (mov
, w
, %H1
);
2085 OUT_AS2 (or, w
, %L1
);
2092 operands
[3] = GEN_INT (INTVAL (operands
[0]) - 1);
2093 OUT_AS2 (mov
, w
, %L3
);
2094 OUT_AS2 (sub
, w
, %L1
);
2095 OUT_AS2 (mov
, w
, %H3
);
2096 OUT_AS2 (subc
, w
, %H1
);
2104 OUT_AS2 (mov
, w
, %L1
);
2105 OUT_AS2 (sub
, w
, %L0
);
2106 OUT_AS2 (mov
, w
, %H1
);
2107 OUT_AS2 (subc
, w
, %H0
);
2117 if (INTVAL (operands
[0]) == 0)
2119 OUT_AS2 (mov
, w
, %H1
);
2120 OUT_AS2 (or, w
, %L1
);
2127 operands
[3] = GEN_INT (INTVAL (operands
[0]) - 1);
2128 OUT_AS2 (mov
, w
, %L3
);
2129 OUT_AS2 (sub
, w
, %L1
);
2130 OUT_AS2 (mov
, w
, %H3
);
2131 OUT_AS2 (subc
, w
, %H1
);
2139 OUT_AS2 (mov
, w
, %L1
);
2140 OUT_AS2 (sub
, w
, %L0
);
2141 OUT_AS2 (mov
, w
, %H1
);
2142 OUT_AS2 (subc
, w
, %H0
);
2152 if ((INTVAL (operands
[1]) & 0xffff) == 0xffff)
2154 /* <= 0xffff always succeeds. */
2160 operands
[3] = GEN_INT (INTVAL (operands
[1]) + 1);
2161 OUT_AS2 (mov
, w
, %L3
);
2162 OUT_AS2 (sub
, w
, %L0
);
2163 OUT_AS2 (mov
, w
, %H3
);
2164 OUT_AS2 (subc
, w
, %H0
);
2172 OUT_AS2 (mov
, w
, %L0
);
2173 OUT_AS2 (sub
, w
, %L1
);
2174 OUT_AS2 (mov
, w
, %H0
);
2175 OUT_AS2 (subc
, w
, %H1
);
2192 unsigned char a
= 0, b
= 1, c
= 2, d
= 3;
2196 a
= (INTVAL (operands
[1]) >> 24) & 0xff;
2197 b
= (INTVAL (operands
[1]) >> 16) & 0xff;
2198 c
= (INTVAL (operands
[1]) >> 8) & 0xff;
2199 d
= INTVAL (operands
[1]) & 0xff;
2202 OUT_AS2 (mov
, w
, %A1
);
2203 if (imm_cmp
&& (b
== a
))
2205 OUT_AS2 (csne
, w
, %A0
);
2206 OUT_AS2 (cse
, w
, %B0
);
2210 OUT_AS2 (cse
, w
, %A0
);
2213 OUT_AS2 (mov
, w
, %B1
);
2214 OUT_AS2 (cse
, w
, %B0
);
2218 if (! imm_cmp
|| (c
!= b
))
2219 OUT_AS2 (mov
, w
, %C1
);
2220 OUT_AS2 (cse
, w
, %C0
);
2223 if (! imm_cmp
|| (d
!= c
))
2224 OUT_AS2 (mov
, w
, %D1
);
2225 OUT_AS2 (csne
, w
, %D0
);
2234 unsigned char a
= 0, b
= 1, c
= 2, d
= 3;
2238 a
= (INTVAL (operands
[1]) >> 24) & 0xff;
2239 b
= (INTVAL (operands
[1]) >> 16) & 0xff;
2240 c
= (INTVAL (operands
[1]) >> 8) & 0xff;
2241 d
= INTVAL (operands
[1]) & 0xff;
2244 OUT_AS2 (mov
, w
, %A1
);
2245 if (imm_cmp
&& (b
== a
))
2247 OUT_AS2 (csne
, w
, %A0
);
2248 OUT_AS2 (cse
, w
, %B0
);
2252 OUT_AS2 (cse
, w
, %A0
);
2255 OUT_AS2 (mov
, w
, %B1
);
2256 OUT_AS2 (cse
, w
, %B0
);
2260 if (! imm_cmp
|| (c
!= b
))
2261 OUT_AS2 (mov
, w
, %C1
);
2262 if (imm_cmp
&& (d
== c
))
2264 OUT_AS2 (csne
, w
, %C0
);
2265 OUT_AS2 (cse
, w
, %D0
);
2269 OUT_AS2 (cse
, w
, %C0
);
2272 OUT_AS2 (mov
, w
, %D1
);
2273 OUT_AS2 (cse
, w
, %D0
);
2283 /* > 0xffffffff never succeeds! */
2284 if ((unsigned HOST_WIDE_INT
)(INTVAL (operands
[1]) & 0xffffffff)
2287 operands
[3] = GEN_INT (INTVAL (operands
[1]) + 1);
2288 OUT_AS2 (mov
, w
, %D3
);
2289 OUT_AS2 (sub
, w
, %D0
);
2290 OUT_AS2 (mov
, w
, %C3
);
2291 OUT_AS2 (subc
, w
, %C0
);
2292 OUT_AS2 (mov
, w
, %B3
);
2293 OUT_AS2 (subc
, w
, %B0
);
2294 OUT_AS2 (mov
, w
, %A3
);
2295 OUT_AS2 (subc
, w
, %A0
);
2303 OUT_AS2 (mov
, w
, %D0
);
2304 OUT_AS2 (sub
, w
, %D1
);
2305 OUT_AS2 (mov
, w
, %C0
);
2306 OUT_AS2 (subc
, w
, %C1
);
2307 OUT_AS2 (mov
, w
, %B0
);
2308 OUT_AS2 (subc
, w
, %B1
);
2309 OUT_AS2 (mov
, w
, %A0
);
2310 OUT_AS2 (subc
, w
, %A1
);
2320 if (INTVAL (operands
[0]) == 0)
2322 OUT_AS2 (mov
, w
, %A1
);
2323 OUT_AS2 (or, w
, %B1
);
2324 OUT_AS2 (or, w
, %C1
);
2325 OUT_AS2 (or, w
, %D1
);
2332 operands
[3] = GEN_INT (INTVAL (operands
[0]) - 1);
2333 OUT_AS2 (mov
, w
, %D3
);
2334 OUT_AS2 (sub
, w
, %D1
);
2335 OUT_AS2 (mov
, w
, %C3
);
2336 OUT_AS2 (subc
, w
, %C1
);
2337 OUT_AS2 (mov
, w
, %B3
);
2338 OUT_AS2 (subc
, w
, %B1
);
2339 OUT_AS2 (mov
, w
, %A3
);
2340 OUT_AS2 (subc
, w
, %A1
);
2348 OUT_AS2 (mov
, w
, %D1
);
2349 OUT_AS2 (sub
, w
, %D0
);
2350 OUT_AS2 (mov
, w
, %C1
);
2351 OUT_AS2 (subc
, w
, %C0
);
2352 OUT_AS2 (mov
, w
, %B1
);
2353 OUT_AS2 (subc
, w
, %B0
);
2354 OUT_AS2 (mov
, w
, %A1
);
2355 OUT_AS2 (subc
, w
, %A0
);
2365 if (INTVAL (operands
[0]) == 0)
2367 OUT_AS2 (mov
, w
, %A1
);
2368 OUT_AS2 (or, w
, %B1
);
2369 OUT_AS2 (or, w
, %C1
);
2370 OUT_AS2 (or, w
, %D1
);
2377 operands
[3] = GEN_INT (INTVAL (operands
[0]) - 1);
2378 OUT_AS2 (mov
, w
, %D3
);
2379 OUT_AS2 (sub
, w
, %D1
);
2380 OUT_AS2 (mov
, w
, %C3
);
2381 OUT_AS2 (subc
, w
, %C1
);
2382 OUT_AS2 (mov
, w
, %B3
);
2383 OUT_AS2 (subc
, w
, %B1
);
2384 OUT_AS2 (mov
, w
, %A3
);
2385 OUT_AS2 (subc
, w
, %A1
);
2393 OUT_AS2 (mov
, w
, %D1
);
2394 OUT_AS2 (sub
, w
, %D0
);
2395 OUT_AS2 (mov
, w
, %C1
);
2396 OUT_AS2 (subc
, w
, %C0
);
2397 OUT_AS2 (mov
, w
, %B1
);
2398 OUT_AS2 (subc
, w
, %B0
);
2399 OUT_AS2 (mov
, w
, %A1
);
2400 OUT_AS2 (subc
, w
, %A0
);
2410 if ((unsigned HOST_WIDE_INT
)(INTVAL (operands
[1]) & 0xffffffff)
2413 /* <= 0xffffffff always succeeds. */
2419 operands
[3] = GEN_INT (INTVAL (operands
[1]) + 1);
2420 OUT_AS2 (mov
, w
, %D3
);
2421 OUT_AS2 (sub
, w
, %D0
);
2422 OUT_AS2 (mov
, w
, %C3
);
2423 OUT_AS2 (subc
, w
, %C0
);
2424 OUT_AS2 (mov
, w
, %B3
);
2425 OUT_AS2 (subc
, w
, %B0
);
2426 OUT_AS2 (mov
, w
, %A3
);
2427 OUT_AS2 (subc
, w
, %A0
);
2435 OUT_AS2 (mov
, w
, %D0
);
2436 OUT_AS2 (sub
, w
, %D1
);
2437 OUT_AS2 (mov
, w
, %C0
);
2438 OUT_AS2 (subc
, w
, %C1
);
2439 OUT_AS2 (mov
, w
, %B0
);
2440 OUT_AS2 (subc
, w
, %B1
);
2441 OUT_AS2 (mov
, w
, %A0
);
2442 OUT_AS2 (subc
, w
, %A1
);
2455 if (GET_CODE (operands
[1]) == CONST_INT
)
2457 const_low
= INTVAL (operands
[1]);
2458 const_high
= (const_low
>= 0) - 1;
2460 else if (GET_CODE (operands
[1]) == CONST_DOUBLE
)
2462 const_low
= CONST_DOUBLE_LOW (operands
[1]);
2463 const_high
= CONST_DOUBLE_HIGH (operands
[1]);
2469 unsigned char s
= 0, t
= 1, u
= 2, v
= 3;
2470 unsigned char w
= 4, x
= 5, y
= 6, z
= 7;
2473 if (GET_CODE (operands
[0]) == MEM
2474 && true_regnum (XEXP (operands
[0], 0)) == REG_DP
)
2476 OUT_AS1 (push
, %Z1
%<);
2477 OUT_AS1 (push
, %Y1
%<);
2478 OUT_AS1 (push
, %X1
%<);
2479 OUT_AS1 (push
, %W1
%<);
2480 OUT_AS1 (push
, %V1
%<);
2481 OUT_AS1 (push
, %U1
%<);
2482 OUT_AS1 (push
, %T1
%<);
2483 OUT_AS1 (push
, %S1
%>%>%>%>%>%>%>);
2484 OUT_AS1 (page
, __cmpdi2_dp
);
2485 OUT_AS1 (call
, __cmpdi2_dp
);
2486 OUT_AS2 (csne
, w
, #1);
2492 OUT_AS1 (push
, %Z1
%<);
2493 OUT_AS1 (push
, %Y1
%<);
2494 OUT_AS1 (push
, %X1
%<);
2495 OUT_AS1 (push
, %W1
%<);
2496 OUT_AS1 (push
, %V1
%<);
2497 OUT_AS1 (push
, %U1
%<);
2498 OUT_AS1 (push
, %T1
%<);
2499 OUT_AS1 (push
, %S1
%<);
2500 OUT_AS1 (push
, %Z0
%<);
2501 OUT_AS1 (push
, %Y0
%<);
2502 OUT_AS1 (push
, %X0
%<);
2503 OUT_AS1 (push
, %W0
%<);
2504 OUT_AS1 (push
, %V0
%<);
2505 OUT_AS1 (push
, %U0
%<);
2506 OUT_AS1 (push
, %T0
%<);
2507 OUT_AS1 (push
, %S0
%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>);
2508 OUT_AS1 (page
, __cmpdi2
);
2509 OUT_AS1 (call
, __cmpdi2
);
2510 OUT_AS2 (csne
, w
, #1);
2519 s
= (const_high
>> 24) & 0xff;
2520 t
= (const_high
>> 16) & 0xff;
2521 u
= (const_high
>> 8) & 0xff;
2522 v
= const_high
& 0xff;
2523 w
= (const_low
>> 24) & 0xff;
2524 x
= (const_low
>> 16) & 0xff;
2525 y
= (const_low
>> 8) & 0xff;
2526 z
= const_low
& 0xff;
2529 OUT_AS2 (mov
, w
, %S1
);
2530 if (imm_cmp
&& (s
== t
))
2532 OUT_AS2 (csne
, w
, %S0
);
2533 OUT_AS2 (cse
, w
, %T0
);
2537 OUT_AS2 (cse
, w
, %S0
);
2540 OUT_AS2 (mov
, w
, %T1
);
2541 OUT_AS2 (cse
, w
, %T0
);
2546 OUT_AS2 (mov
, w
, %U1
);
2547 if (imm_cmp
&& (u
== v
))
2549 OUT_AS2 (csne
, w
, %U0
);
2550 OUT_AS2 (cse
, w
, %V0
);
2554 OUT_AS2 (cse
, w
, %U0
);
2557 OUT_AS2 (mov
, w
, %V1
);
2558 OUT_AS2 (cse
, w
, %V0
);
2563 OUT_AS2 (mov
, w
, %W1
);
2564 if (imm_cmp
&& (w
== x
))
2566 OUT_AS2 (csne
, w
, %W0
);
2567 OUT_AS2 (cse
, w
, %X0
);
2571 OUT_AS2 (cse
, w
, %W0
);
2574 OUT_AS2 (mov
, w
, %X1
);
2575 OUT_AS2 (cse
, w
, %X0
);
2580 if (! imm_cmp
|| (x
!= y
))
2581 OUT_AS2 (mov
, w
, %Y1
);
2582 OUT_AS2 (cse
, w
, %Y0
);
2585 if (! imm_cmp
|| (z
!= y
))
2586 OUT_AS2 (mov
, w
, %Z1
);
2587 OUT_AS2 (csne
, w
, %Z0
);
2597 unsigned char s
= 0, t
= 1, u
= 2, v
= 3;
2598 unsigned char w
= 4, x
= 5, y
= 6, z
= 7;
2602 if (GET_CODE (operands
[0]) == MEM
2603 && true_regnum (XEXP (operands
[0], 0)) == REG_DP
)
2605 OUT_AS1 (push
, %Z1
%<);
2606 OUT_AS1 (push
, %Y1
%<);
2607 OUT_AS1 (push
, %X1
%<);
2608 OUT_AS1 (push
, %W1
%<);
2609 OUT_AS1 (push
, %V1
%<);
2610 OUT_AS1 (push
, %U1
%<);
2611 OUT_AS1 (push
, %T1
%<);
2612 OUT_AS1 (push
, %S1
%>%>%>%>%>%>%>);
2613 OUT_AS1 (page
, __cmpdi2_dp
);
2614 OUT_AS1 (call
, __cmpdi2_dp
);
2615 OUT_AS2 (cse
, w
, #1);
2621 OUT_AS1 (push
, %Z1
%<);
2622 OUT_AS1 (push
, %Y1
%<);
2623 OUT_AS1 (push
, %X1
%<);
2624 OUT_AS1 (push
, %W1
%<);
2625 OUT_AS1 (push
, %V1
%<);
2626 OUT_AS1 (push
, %U1
%<);
2627 OUT_AS1 (push
, %T1
%<);
2628 OUT_AS1 (push
, %S1
%<);
2629 OUT_AS1 (push
, %Z0
%<);
2630 OUT_AS1 (push
, %Y0
%<);
2631 OUT_AS1 (push
, %X0
%<);
2632 OUT_AS1 (push
, %W0
%<);
2633 OUT_AS1 (push
, %V0
%<);
2634 OUT_AS1 (push
, %U0
%<);
2635 OUT_AS1 (push
, %T0
%<);
2636 OUT_AS1 (push
, %S0
%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>);
2637 OUT_AS1 (page
, __cmpdi2
);
2638 OUT_AS1 (call
, __cmpdi2
);
2639 OUT_AS2 (cse
, w
, #1);
2648 s
= (const_high
>> 24) & 0xff;
2649 t
= (const_high
>> 16) & 0xff;
2650 u
= (const_high
>> 8) & 0xff;
2651 v
= const_high
& 0xff;
2652 w
= (const_low
>> 24) & 0xff;
2653 x
= (const_low
>> 16) & 0xff;
2654 y
= (const_low
>> 8) & 0xff;
2655 z
= const_low
& 0xff;
2658 OUT_AS2 (mov
, w
, %S1
);
2659 if (imm_cmp
&& (s
== t
))
2661 OUT_AS2 (csne
, w
, %S0
);
2662 OUT_AS2 (cse
, w
, %T0
);
2666 OUT_AS2 (cse
, w
, %S0
);
2669 OUT_AS2 (mov
, w
, %T1
);
2670 OUT_AS2 (cse
, w
, %T0
);
2675 OUT_AS2 (mov
, w
, %U1
);
2676 if (imm_cmp
&& (u
== v
))
2678 OUT_AS2 (csne
, w
, %U0
);
2679 OUT_AS2 (cse
, w
, %V0
);
2683 OUT_AS2 (cse
, w
, %U0
);
2686 OUT_AS2 (mov
, w
, %V1
);
2687 OUT_AS2 (cse
, w
, %V0
);
2692 OUT_AS2 (mov
, w
, %W1
);
2693 if (imm_cmp
&& (w
== x
))
2695 OUT_AS2 (csne
, w
, %W0
);
2696 OUT_AS2 (cse
, w
, %X0
);
2700 OUT_AS2 (cse
, w
, %W0
);
2703 OUT_AS2 (mov
, w
, %X1
);
2704 OUT_AS2 (cse
, w
, %X0
);
2709 if (! imm_cmp
|| (y
!= x
))
2710 OUT_AS2 (mov
, w
, %Y1
);
2711 if (imm_cmp
&& (z
== y
))
2713 OUT_AS2 (csne
, w
, %Y0
);
2714 OUT_AS2 (cse
, w
, %Z0
);
2718 OUT_AS2 (cse
, w
, %Y0
);
2721 OUT_AS2 (mov
, w
, %Z1
);
2722 OUT_AS2 (cse
, w
, %Z0
);
2733 /* > 0xffffffffffffffff never succeeds! */
2734 if (((const_high
& 0xffffffff) != 0xffffffff)
2735 || ((const_low
& 0xffffffff) != 0xffffffff))
2737 operands
[3] = GEN_INT (const_low
+ 1);
2738 operands
[4] = GEN_INT (const_high
2739 + (INTVAL (operands
[3]) ? 0 : 1));
2740 OUT_AS2 (mov
, w
, %D3
);
2741 OUT_AS2 (sub
, w
, %Z0
);
2742 OUT_AS2 (mov
, w
, %C3
);
2743 OUT_AS2 (subc
, w
, %Y0
);
2744 OUT_AS2 (mov
, w
, %B3
);
2745 OUT_AS2 (subc
, w
, %X0
);
2746 OUT_AS2 (mov
, w
, %A3
);
2747 OUT_AS2 (subc
, w
, %W0
);
2748 OUT_AS2 (mov
, w
, %D4
);
2749 OUT_AS2 (subc
, w
, %V0
);
2750 OUT_AS2 (mov
, w
, %C4
);
2751 OUT_AS2 (subc
, w
, %U0
);
2752 OUT_AS2 (mov
, w
, %B4
);
2753 OUT_AS2 (subc
, w
, %T0
);
2754 OUT_AS2 (mov
, w
, %A4
);
2755 OUT_AS2 (subc
, w
, %S0
);
2763 OUT_AS2 (mov
, w
, %Z0
);
2764 OUT_AS2 (sub
, w
, %Z1
);
2765 OUT_AS2 (mov
, w
, %Y0
);
2766 OUT_AS2 (subc
, w
, %Y1
);
2767 OUT_AS2 (mov
, w
, %X0
);
2768 OUT_AS2 (subc
, w
, %X1
);
2769 OUT_AS2 (mov
, w
, %W0
);
2770 OUT_AS2 (subc
, w
, %W1
);
2771 OUT_AS2 (mov
, w
, %V0
);
2772 OUT_AS2 (subc
, w
, %V1
);
2773 OUT_AS2 (mov
, w
, %U0
);
2774 OUT_AS2 (subc
, w
, %U1
);
2775 OUT_AS2 (mov
, w
, %T0
);
2776 OUT_AS2 (subc
, w
, %T1
);
2777 OUT_AS2 (mov
, w
, %S0
);
2778 OUT_AS2 (subc
, w
, %S1
);
2788 HOST_WIDE_INT const_low0
;
2789 HOST_WIDE_INT const_high0
;
2791 if (GET_CODE (operands
[0]) == CONST_INT
)
2793 const_low0
= INTVAL (operands
[0]);
2794 const_high0
= (const_low
>= 0) - 1;
2796 else if (GET_CODE (operands
[0]) == CONST_DOUBLE
)
2798 const_low0
= CONST_DOUBLE_LOW (operands
[0]);
2799 const_high0
= CONST_DOUBLE_HIGH (operands
[0]);
2802 if (const_high0
== 0 && const_low0
== 0)
2804 OUT_AS2 (mov
, w
, %S1
);
2805 OUT_AS2 (or, w
, %T1
);
2806 OUT_AS2 (or, w
, %U1
);
2807 OUT_AS2 (or, w
, %V1
);
2808 OUT_AS2 (or, w
, %W1
);
2809 OUT_AS2 (or, w
, %X1
);
2810 OUT_AS2 (or, w
, %Y1
);
2811 OUT_AS2 (or, w
, %Z1
);
2818 operands
[3] = GEN_INT (const_low0
- 1);
2819 operands
[4] = GEN_INT (const_high0
- (const_low0
? 1 : 0));
2820 OUT_AS2 (mov
, w
, %D3
);
2821 OUT_AS2 (sub
, w
, %Z1
);
2822 OUT_AS2 (mov
, w
, %C3
);
2823 OUT_AS2 (subc
, w
, %Y1
);
2824 OUT_AS2 (mov
, w
, %B3
);
2825 OUT_AS2 (subc
, w
, %X1
);
2826 OUT_AS2 (mov
, w
, %A3
);
2827 OUT_AS2 (subc
, w
, %W1
);
2828 OUT_AS2 (mov
, w
, %D4
);
2829 OUT_AS2 (subc
, w
, %V1
);
2830 OUT_AS2 (mov
, w
, %C4
);
2831 OUT_AS2 (subc
, w
, %U1
);
2832 OUT_AS2 (mov
, w
, %B4
);
2833 OUT_AS2 (subc
, w
, %T1
);
2834 OUT_AS2 (mov
, w
, %A4
);
2835 OUT_AS2 (subc
, w
, %S1
);
2843 OUT_AS2 (mov
, w
, %Z1
);
2844 OUT_AS2 (sub
, w
, %Z0
);
2845 OUT_AS2 (mov
, w
, %Y1
);
2846 OUT_AS2 (subc
, w
, %Y0
);
2847 OUT_AS2 (mov
, w
, %X1
);
2848 OUT_AS2 (subc
, w
, %X0
);
2849 OUT_AS2 (mov
, w
, %W1
);
2850 OUT_AS2 (subc
, w
, %W0
);
2851 OUT_AS2 (mov
, w
, %V1
);
2852 OUT_AS2 (subc
, w
, %V0
);
2853 OUT_AS2 (mov
, w
, %U1
);
2854 OUT_AS2 (subc
, w
, %U0
);
2855 OUT_AS2 (mov
, w
, %T1
);
2856 OUT_AS2 (subc
, w
, %T0
);
2857 OUT_AS2 (mov
, w
, %S1
);
2858 OUT_AS2 (subc
, w
, %S0
);
2868 HOST_WIDE_INT const_low0
;
2869 HOST_WIDE_INT const_high0
;
2871 if (GET_CODE (operands
[0]) == CONST_INT
)
2873 const_low0
= INTVAL (operands
[0]);
2874 const_high0
= (const_low
>= 0) - 1;
2876 else if (GET_CODE (operands
[0]) == CONST_DOUBLE
)
2878 const_low0
= CONST_DOUBLE_LOW (operands
[0]);
2879 const_high0
= CONST_DOUBLE_HIGH (operands
[0]);
2882 if (const_high0
== 0 && const_low0
== 0)
2884 OUT_AS2 (mov
, w
, %S1
);
2885 OUT_AS2 (or, w
, %T1
);
2886 OUT_AS2 (or, w
, %U1
);
2887 OUT_AS2 (or, w
, %V1
);
2888 OUT_AS2 (or, w
, %W1
);
2889 OUT_AS2 (or, w
, %X1
);
2890 OUT_AS2 (or, w
, %Y1
);
2891 OUT_AS2 (or, w
, %Z1
);
2898 operands
[3] = GEN_INT (const_low0
- 1);
2899 operands
[4] = GEN_INT (const_high0
- (const_low0
? 1 : 0));
2900 OUT_AS2 (mov
, w
, %D3
);
2901 OUT_AS2 (sub
, w
, %Z1
);
2902 OUT_AS2 (mov
, w
, %C3
);
2903 OUT_AS2 (subc
, w
, %Y1
);
2904 OUT_AS2 (mov
, w
, %B3
);
2905 OUT_AS2 (subc
, w
, %X1
);
2906 OUT_AS2 (mov
, w
, %A3
);
2907 OUT_AS2 (subc
, w
, %W1
);
2908 OUT_AS2 (mov
, w
, %D4
);
2909 OUT_AS2 (subc
, w
, %V1
);
2910 OUT_AS2 (mov
, w
, %C4
);
2911 OUT_AS2 (subc
, w
, %U1
);
2912 OUT_AS2 (mov
, w
, %B4
);
2913 OUT_AS2 (subc
, w
, %T1
);
2914 OUT_AS2 (mov
, w
, %A4
);
2915 OUT_AS2 (subc
, w
, %S1
);
2923 OUT_AS2 (mov
, w
, %Z1
);
2924 OUT_AS2 (sub
, w
, %Z0
);
2925 OUT_AS2 (mov
, w
, %Y1
);
2926 OUT_AS2 (subc
, w
, %Y0
);
2927 OUT_AS2 (mov
, w
, %X1
);
2928 OUT_AS2 (subc
, w
, %X0
);
2929 OUT_AS2 (mov
, w
, %W1
);
2930 OUT_AS2 (subc
, w
, %W0
);
2931 OUT_AS2 (mov
, w
, %V1
);
2932 OUT_AS2 (subc
, w
, %V0
);
2933 OUT_AS2 (mov
, w
, %U1
);
2934 OUT_AS2 (subc
, w
, %U0
);
2935 OUT_AS2 (mov
, w
, %T1
);
2936 OUT_AS2 (subc
, w
, %T0
);
2937 OUT_AS2 (mov
, w
, %S1
);
2938 OUT_AS2 (subc
, w
, %S0
);
2948 if (((const_high
& 0xffffffff) == 0xffffffff)
2949 && ((const_low
& 0xffffffff) == 0xffffffff))
2951 /* <= 0xffffffffffffffff always succeeds. */
2957 operands
[3] = GEN_INT (const_low
+ 1);
2958 operands
[4] = GEN_INT (const_high
2959 + (INTVAL (operands
[3]) ? 0 : 1));
2960 OUT_AS2 (mov
, w
, %D3
);
2961 OUT_AS2 (sub
, w
, %Z0
);
2962 OUT_AS2 (mov
, w
, %C3
);
2963 OUT_AS2 (subc
, w
, %Y0
);
2964 OUT_AS2 (mov
, w
, %B3
);
2965 OUT_AS2 (subc
, w
, %X0
);
2966 OUT_AS2 (mov
, w
, %A3
);
2967 OUT_AS2 (subc
, w
, %W0
);
2968 OUT_AS2 (mov
, w
, %D4
);
2969 OUT_AS2 (subc
, w
, %V0
);
2970 OUT_AS2 (mov
, w
, %C4
);
2971 OUT_AS2 (subc
, w
, %U0
);
2972 OUT_AS2 (mov
, w
, %B4
);
2973 OUT_AS2 (subc
, w
, %T0
);
2974 OUT_AS2 (mov
, w
, %A4
);
2975 OUT_AS2 (subc
, w
, %S0
);
2983 OUT_AS2 (mov
, w
, %Z0
);
2984 OUT_AS2 (sub
, w
, %Z1
);
2985 OUT_AS2 (mov
, w
, %Y0
);
2986 OUT_AS2 (subc
, w
, %Y1
);
2987 OUT_AS2 (mov
, w
, %X0
);
2988 OUT_AS2 (subc
, w
, %X1
);
2989 OUT_AS2 (mov
, w
, %W0
);
2990 OUT_AS2 (subc
, w
, %W1
);
2991 OUT_AS2 (mov
, w
, %V0
);
2992 OUT_AS2 (subc
, w
, %V1
);
2993 OUT_AS2 (mov
, w
, %U0
);
2994 OUT_AS2 (subc
, w
, %U1
);
2995 OUT_AS2 (mov
, w
, %T0
);
2996 OUT_AS2 (subc
, w
, %T1
);
2997 OUT_AS2 (mov
, w
, %S0
);
2998 OUT_AS2 (subc
, w
, %S1
);
3017 /* Output rtx VALUE as .byte to file FILE. */
3020 asm_output_char (FILE *file
, rtx value
)
3022 fprintf (file
, "\t.byte ");
3023 output_addr_const (file
, value
);
3024 fprintf (file
, "\n");
3028 /* Output VALUE as .byte to file FILE. */
3031 asm_output_byte (FILE *file
, int value
)
3033 fprintf (file
, "\t.byte 0x%x\n",value
& 0xff);
3037 /* Output rtx VALUE as .word to file FILE. */
3040 asm_output_short (FILE *file
, rtx value
)
3042 fprintf (file
, "\t.word ");
3043 output_addr_const (file
, (value
));
3044 fprintf (file
, "\n");
3048 /* Output real N to file FILE. */
3051 asm_output_float (FILE *file
, REAL_VALUE_TYPE n
)
3056 REAL_VALUE_TO_TARGET_SINGLE (n
, val
);
3057 real_to_decimal (dstr
, &n
, sizeof (dstr
), 0, 1);
3059 fprintf (file
, "\t.long 0x%08lx\t/* %s */\n", val
, dstr
);
3062 /* Sets section name for declaration DECL. */
3065 unique_section (tree decl
, int reloc ATTRIBUTE_UNUSED
)
3071 name
= IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
));
3072 /* Strip off any encoding in name. */
3073 name
= (* targetm
.strip_name_encoding
) (name
);
3075 if (TREE_CODE (decl
) == FUNCTION_DECL
)
3077 if (flag_function_sections
)
3085 if (flag_function_sections
)
3087 len
= strlen (name
) + strlen (prefix
);
3088 string
= alloca (len
+ 1);
3089 sprintf (string
, "%s%s", prefix
, name
);
3090 DECL_SECTION_NAME (decl
) = build_string (len
, string
);
3094 /* Return value is nonzero if pseudos that have been
3095 assigned to registers of class CLASS would likely be spilled
3096 because registers of CLASS are needed for spill registers. */
3099 class_likely_spilled_p (int c
)
3101 return (c
== IP_REGS
3112 /* Valid attributes:
3113 progmem - put data to program memory;
3114 naked - don't generate function prologue/epilogue and `ret' command.
3116 Only `progmem' attribute valid for type. */
3118 const struct attribute_spec ip2k_attribute_table
[] =
3120 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
3121 { "progmem", 0, 0, false, false, false, ip2k_handle_progmem_attribute
},
3122 { "naked", 0, 0, true, false, false, ip2k_handle_fndecl_attribute
},
3123 { NULL
, 0, 0, false, false, false, NULL
}
3126 /* Handle a "progmem" attribute; arguments as in
3127 struct attribute_spec.handler. */
3129 ip2k_handle_progmem_attribute (tree
*node
, tree name
,
3130 tree args ATTRIBUTE_UNUSED
,
3131 int flags ATTRIBUTE_UNUSED
,
3136 if (TREE_CODE (*node
) == TYPE_DECL
)
3138 /* This is really a decl attribute, not a type attribute,
3139 but try to handle it for GCC 3.0 backwards compatibility. */
3141 tree type
= TREE_TYPE (*node
);
3142 tree attr
= tree_cons (name
, args
, TYPE_ATTRIBUTES (type
));
3143 tree newtype
= build_type_attribute_variant (type
, attr
);
3145 TYPE_MAIN_VARIANT (newtype
) = TYPE_MAIN_VARIANT (type
);
3146 TREE_TYPE (*node
) = newtype
;
3147 *no_add_attrs
= true;
3149 else if (TREE_STATIC (*node
) || DECL_EXTERNAL (*node
))
3151 if (DECL_INITIAL (*node
) == NULL_TREE
&& !DECL_EXTERNAL (*node
))
3153 warning ("only initialized variables can be placed into "
3154 "program memory area");
3155 *no_add_attrs
= true;
3160 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name
));
3161 *no_add_attrs
= true;
3168 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
3169 struct attribute_spec.handler. */
3171 ip2k_handle_fndecl_attribute (tree
*node
, tree name
,
3172 tree args ATTRIBUTE_UNUSED
,
3173 int flags ATTRIBUTE_UNUSED
,
3176 if (TREE_CODE (*node
) != FUNCTION_DECL
)
3178 warning ("`%s' attribute only applies to functions",
3179 IDENTIFIER_POINTER (name
));
3180 *no_add_attrs
= true;
3186 /* Cost functions. */
3188 /* Compute a (partial) cost for rtx X. Return true if the complete
3189 cost has been computed, and false if subexpressions should be
3190 scanned. In either case, *TOTAL contains the cost result. */
3193 ip2k_rtx_costs (rtx x
, int code
, int outer_code
, int *total
)
3195 enum machine_mode mode
= GET_MODE (x
);
3211 *total
= ip2k_address_cost (XEXP (x
, 0));
3219 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
3221 int val
= INTVAL (XEXP (x
, 1));
3224 /* Shift by const instructions are proportional to
3225 the shift count modulus 8. Note that we increase the mode
3226 size multiplier by 1 to account for clearing the carry flag. */
3227 cost
= COSTS_N_INSNS (abs (val
) % 8);
3228 cost
+= rtx_cost (XEXP (x
, 0), code
);
3229 cost
*= (GET_MODE_SIZE (mode
) + 1);
3231 /* Sign-preserving shifts require 2 extra instructions. */
3233 cost
+= COSTS_N_INSNS (2);
3238 *total
= rtx_cost (XEXP (x
, 0), code
);
3239 *total
+= COSTS_N_INSNS (GET_MODE_SIZE (mode
) * 8);
3247 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
) * 3);
3253 *total
= COSTS_N_INSNS (20);
3254 else if (mode
== HImode
)
3255 *total
= COSTS_N_INSNS (60);
3256 else if (mode
== SImode
)
3257 *total
= COSTS_N_INSNS (180);
3259 *total
= COSTS_N_INSNS (540);
3263 /* These costs are OK, but should really handle subtle cases
3264 where we're using sign or zero extended args as these are
3265 *much* cheaper than those given below! */
3267 *total
= COSTS_N_INSNS (4);
3268 else if (mode
== HImode
)
3269 *total
= COSTS_N_INSNS (12);
3270 else if (mode
== SImode
)
3271 *total
= COSTS_N_INSNS (36);
3273 *total
= COSTS_N_INSNS (108);
3278 extra_cost
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
3284 *total
= extra_cost
+ COSTS_N_INSNS (GET_MODE_SIZE (mode
) * 2);
3289 if (outer_code
== SET
)
3291 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
) * 3 / 2);
3296 *total
= -(COSTS_N_INSNS (GET_MODE_SIZE (mode
)) / 2);
3301 *total
= rtx_cost (XEXP (x
, 0), code
) + COSTS_N_INSNS (2);
3318 *total
= COSTS_N_INSNS (4);
3323 /* Calculate the cost of a memory address. */
3326 ip2k_address_cost (rtx x
)
3328 switch (legitimate_address_p (VOIDmode
, x
, 0))
3330 case 'S': /* Very low cost - (IP), (SP+N) or (DP+N) */
3333 case 'R': /* Indirected through IP. */
3336 case 'L': /* Label references. */
3339 case 'C': /* Constants and symbol references. */
3343 return 1000; /* Must reload. */
3347 /* As part of the machine-dependent reorg we look for opcode sequences where
3348 we do some operation and then move the results back to one of the original
3349 source operands. With working on the source operand directly is probably
3350 much cheaper and the move from this to the original source operand will be
3351 no more expensive than the original move. */
3353 #ifdef IP2K_MD_REORG_PASS
3355 mdr_resequence_xy_yx (first_insn
)
3360 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
3364 if (GET_CODE (insn
) != INSN
)
3367 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
3368 if (set
== NULL_RTX
)
3371 /* Look for operations that tend to be very cheap to run when the source
3372 * and dest args are the same because the IP2022 has opcodes that can
3373 operate on the source directly. If we have to spill through the W
3374 register then we've possibly not got a good case for doing this. */
3375 if ((GET_CODE (XEXP (set
, 0)) == REG
3376 || GET_CODE (XEXP (set
, 0)) == MEM
)
3377 && (GET_CODE (XEXP (set
, 1)) == ASHIFT
3378 || GET_CODE (XEXP (set
, 1)) == ASHIFTRT
3379 || GET_CODE (XEXP (set
, 1)) == LSHIFTRT
3380 || GET_CODE (XEXP (set
, 1)) == XOR
3381 || GET_CODE (XEXP (set
, 1)) == IOR
3382 || GET_CODE (XEXP (set
, 1)) == AND
3383 || GET_CODE (XEXP (set
, 1)) == PLUS
3384 || GET_CODE (XEXP (set
, 1)) == MINUS
3385 || GET_CODE (XEXP (set
, 1)) == MULT
))
3390 next_insn
= next_nonnote_insn (insn
);
3394 if (GET_CODE (next_insn
) != INSN
)
3397 set2
= ((GET_CODE (PATTERN (next_insn
)) == SET
)
3398 ? PATTERN (next_insn
) : NULL_RTX
);
3399 if (set2
== NULL_RTX
)
3402 if ((GET_CODE (XEXP (XEXP (set
, 1), 0)) == REG
3403 || GET_CODE (XEXP (XEXP (set
, 1), 0)) == MEM
)
3404 && rtx_equal_p (XEXP (set2
, 0), XEXP (XEXP (set
, 1), 0))
3405 && rtx_equal_p (XEXP (set2
, 1), XEXP (set
, 0)))
3410 b_insn
= gen_rtx_SET (VOIDmode
,
3411 XEXP (XEXP (set
, 1), 0),
3412 gen_rtx_fmt_ee (GET_CODE (XEXP (set
, 1)),
3413 GET_MODE (XEXP (set
, 0)),
3414 XEXP (XEXP (set
, 1), 0),
3415 XEXP (XEXP (set
, 1), 1)));
3417 emit_insn_before (b_insn
, insn
);
3418 b_insn
= gen_rtx_SET (GET_MODE (XEXP (set
, 0)), XEXP (set
, 0),
3419 XEXP (XEXP (set
, 1), 0));
3420 next2_insn
= emit_insn_before (b_insn
, insn
);
3422 delete_insn (next_insn
);
3427 /* Having tried with one operand of the expression, now, if
3428 appropriate, try to do the same thing with the second operand.
3429 Of course there are fewer operations that can match here
3430 because they must be commutative. */
3431 if (GET_RTX_CLASS (GET_CODE (XEXP (set
, 1))) == RTX_COMM_ARITH
3432 && (GET_CODE (XEXP (XEXP (set
, 1), 1)) == REG
3433 || GET_CODE (XEXP (XEXP (set
, 1), 1)) == MEM
)
3434 && rtx_equal_p (XEXP (set2
, 0), XEXP (XEXP (set
, 1), 1))
3435 && rtx_equal_p (XEXP (set2
, 1), XEXP (set
, 0)))
3441 /* Try to ensure that we put things in a canonical form. */
3442 swap_args
= (GET_CODE (XEXP (XEXP (set
, 1), 0)) == REG
3443 || GET_CODE (XEXP (XEXP (set
, 1), 0)) == MEM
);
3444 rtx_ee
= gen_rtx_fmt_ee (GET_CODE (XEXP (set
, 1)),
3445 GET_MODE (XEXP (set
, 0)),
3446 XEXP (XEXP (set
, 1), swap_args
? 1 : 0),
3447 XEXP (XEXP (set
, 1),
3448 swap_args
? 0 : 1));
3450 emit_insn_before (gen_rtx_SET (VOIDmode
,
3451 XEXP (XEXP (set
, 1), 1),
3454 next2_insn
= emit_insn_before (gen_rtx_SET
3455 (GET_MODE (XEXP (set
, 0)),
3457 XEXP (XEXP (set
, 1), 1)),
3460 delete_insn (next_insn
);
3467 /* Replace and recurse until we've tried QImode pieces! */
3470 mdr_pres_replace_and_recurse (orig
, with
, insn
)
3475 enum machine_mode new_mode
;
3477 validate_replace_rtx (orig
, with
, insn
);
3479 switch (GET_MODE (orig
))
3499 mdr_pres_replace_and_recurse (ip2k_get_low_half (orig
, new_mode
),
3500 ip2k_get_low_half (with
, new_mode
),
3502 mdr_pres_replace_and_recurse (ip2k_get_high_half (orig
, new_mode
),
3503 ip2k_get_high_half (with
, new_mode
),
3507 /* Assist the following function, mdr_propagate_reg_equivs(). */
3510 mdr_propagate_reg_equivs_sequence (first_insn
, orig
, equiv
)
3516 rtx try_equiv
= equiv
;
3518 /* First scan the RTL looking for anything else that might clobber what
3519 we're doing. If we find anything then we can't do the replacement. */
3520 for (try_insn
= next_nonnote_insn (first_insn
);
3521 try_insn
; try_insn
= next_nonnote_insn (try_insn
))
3525 if (GET_CODE (try_insn
) != JUMP_INSN
&& GET_CODE (try_insn
) != INSN
)
3528 pattern
= PATTERN (try_insn
);
3529 if (GET_CODE (pattern
) == PARALLEL
)
3533 for (j
= 0; j
< XVECLEN (pattern
, 0); j
++)
3535 rtx px
= XVECEXP (pattern
, 0, j
);
3537 if (GET_CODE (px
) == SET
)
3538 if (! ip2k_composite_xexp_not_uses_reg_p (XEXP (px
, 0),
3540 GET_MODE_SIZE (GET_MODE (orig
))))
3544 else if (GET_CODE (pattern
) == SET
)
3546 if (! ip2k_composite_xexp_not_uses_reg_p (XEXP (pattern
, 0),
3548 GET_MODE_SIZE (GET_MODE (orig
))))
3553 /* Once we've decided that we're safe to do the replacement then make the
3555 for (try_insn
= next_nonnote_insn (first_insn
); try_insn
;
3556 try_insn
= next_nonnote_insn (try_insn
))
3559 rtx new_equiv
= NULL_RTX
;
3561 if (GET_CODE (try_insn
) != JUMP_INSN
&& GET_CODE (try_insn
) != INSN
)
3567 set
= ((GET_CODE (PATTERN (try_insn
)) == SET
)
3568 ? PATTERN (try_insn
) : NULL_RTX
);
3569 if (set
== NULL_RTX
)
3572 /* We look for a special case of "push" operations screwing our
3573 register equivalence when it's based on a stack slot. We can
3574 track this one and replace the old equivalence expression with
3576 if (GET_CODE (XEXP (set
, 0)) == MEM
3577 && GET_CODE (XEXP (XEXP (set
, 0), 0)) == POST_DEC
3578 && REG_P (XEXP (XEXP (XEXP (set
, 0), 0), 0))
3579 && REGNO (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG_SP
)
3581 /* XXX - need to ensure that we can track this without going
3583 HOST_WIDE_INT disp
= (INTVAL (XEXP (XEXP (try_equiv
, 0), 1))
3584 + GET_MODE_SIZE (GET_MODE (XEXP (set
, 0))));
3585 new_equiv
= gen_rtx_MEM (GET_MODE (try_equiv
),
3586 gen_rtx_PLUS (Pmode
,
3587 gen_rtx_REG (HImode
, REG_SP
),
3591 /* The replacement process is somewhat complicated by the fact that we
3592 might be dealing with what were originally subregs and thus we have
3593 to replace parts of our original expression! */
3594 mdr_pres_replace_and_recurse (orig
, try_equiv
, try_insn
);
3596 if (new_equiv
!= NULL_RTX
)
3597 try_equiv
= new_equiv
;
3601 /* Try propagating register equivalences forwards. It may be that we can
3602 replace a register use with an equivalent expression that already
3603 holds the same value and thus allow one or more register loads to
3607 mdr_propagate_reg_equivs (first_insn
)
3613 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
3615 if (GET_CODE (insn
) != INSN
)
3618 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
3619 if (set
== NULL_RTX
)
3622 /* Have we found a stack slot equivalence for a register? */
3623 if (REG_P (XEXP (set
, 0))
3624 && REGNO (XEXP (set
, 0)) >= 0x88
3625 && GET_CODE (XEXP (set
, 1)) == MEM
3626 && GET_CODE (XEXP (XEXP (set
, 1), 0)) == PLUS
3627 && REG_P (XEXP (XEXP (XEXP (set
, 1), 0), 0))
3628 && REGNO (XEXP (XEXP (XEXP (set
, 1), 0), 0)) == REG_SP
3629 && find_reg_note (insn
, REG_EQUIV
, NULL_RTX
))
3631 mdr_propagate_reg_equivs_sequence (insn
, XEXP (set
, 0),
3637 /* Structure used to track jump targets. */
3639 struct dpre_jump_targets
3641 int target
; /* Is this a jump target? */
3642 int reach_count
; /* Number of ways we can reach this insn. */
3643 int touch_count
; /* Number of times we've touched this
3644 insns during scanning. */
3645 rtx dp_equiv
; /* DP-equivalence at this point. */
3648 struct dpre_jump_targets
*ip2k_dpre_jump_targets
;
3650 /* DP equivalence tracking used within DP reload elimination. */
3653 track_dp_reload (insn
, dp_current
, dp_current_ok
, modifying
)
3661 if (GET_CODE (insn
) != INSN
)
3663 *dp_current
= NULL_RTX
;
3667 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
3668 if (set
== NULL_RTX
)
3670 *dp_current
= NULL_RTX
;
3674 /* If we're pushing a PLUS or MINUS then it's a win if we can replace
3675 an expression for which DP is equivalent with DP. This happens
3676 surprisingly often when we pass a pointer to a structure embedded
3677 within another structure. */
3678 if (*dp_current
!= NULL_RTX
3679 && GET_CODE (XEXP (set
, 0)) == MEM
3680 && GET_CODE (XEXP (XEXP (set
, 0), 0)) == POST_DEC
3681 && GET_CODE (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG
3682 && REGNO (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG_SP
3683 && (GET_CODE (XEXP (set
, 1)) == PLUS
3684 || GET_CODE (XEXP (set
, 1)) == MINUS
)
3685 && GET_CODE (*dp_current
) != SYMBOL_REF
3686 && GET_CODE (*dp_current
) != LABEL_REF
3687 && GET_CODE (*dp_current
) != CONST
)
3690 validate_replace_rtx (*dp_current
, gen_rtx_REG (HImode
, REG_DP
), insn
);
3693 /* Look for DP being modified. If it is, see if it's being changed
3694 to what it already is! */
3695 if (GET_CODE (XEXP (set
, 0)) == REG
3696 && REGNO (XEXP (set
, 0)) == REG_DP
3697 && GET_MODE (XEXP (set
, 0)) == HImode
)
3699 /* If this is an equivalence we can delete the new set operation. */
3700 if (*dp_current
!= NULL_RTX
3701 && rtx_equal_p (XEXP (set
, 1), *dp_current
))
3708 /* If we've not found an equivalence we can look for a special
3709 case where an operand of the expression that sets DP is
3710 already equivalent to DP and in that circumstance we simplify
3711 by replacing that expression with DP. */
3712 if (*dp_current
!= NULL_RTX
3713 && GET_CODE (*dp_current
) != SYMBOL_REF
3714 && GET_CODE (*dp_current
) != LABEL_REF
3715 && GET_CODE (*dp_current
) != CONST
3717 validate_replace_rtx (*dp_current
, XEXP (set
, 0), insn
);
3719 /* Assuming that we're not loading DP from something that uses DP
3720 itself then we mark the new equivalence for DP. If we did match
3721 DP then we can't re-use this one. */
3722 if (ip2k_xexp_not_uses_reg_p (XEXP (set
, 1), REG_DP
, 2))
3724 *dp_current
= XEXP (set
, 1);
3729 *dp_current
= NULL_RTX
;
3734 else if (GET_CODE (XEXP (set
, 0)) == REG
3735 && (REGNO (XEXP (set
, 0)) == REG_DPL
3736 || REGNO (XEXP (set
, 0)) == REG_DPH
))
3738 /* If we clobber part of DP then we've clobbered any equivalences! */
3739 *dp_current
= NULL_RTX
;
3742 else if (! ip2k_xexp_not_uses_reg_p (XEXP (set
, 0), REG_SP
, 2)
3743 && *dp_current
!= NULL_RTX
3744 && !ip2k_xexp_not_uses_reg_p (*dp_current
, REG_SP
, 2))
3746 /* We look for a special case of "push" operations screwing up the
3747 setting of DP when it's based on the stack. We can track this one
3748 and replace the old expression for DP with a new one. */
3749 if (GET_CODE (XEXP (set
, 0)) == MEM
3750 && GET_CODE (XEXP (XEXP (set
, 0), 0)) == POST_DEC
3751 && GET_CODE (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG
3752 && REGNO (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG_SP
3753 && GET_CODE (*dp_current
) == MEM
3754 && GET_CODE (XEXP (*dp_current
, 0)) == PLUS
)
3756 /* XXX - need to ensure that we can track this without going
3758 HOST_WIDE_INT disp
= (INTVAL (XEXP (XEXP (*dp_current
, 0), 1))
3759 + GET_MODE_SIZE (GET_MODE (XEXP (set
, 0))));
3760 *dp_current
= gen_rtx_MEM (HImode
,
3761 gen_rtx_PLUS (Pmode
,
3762 gen_rtx_REG (HImode
, REG_SP
),
3767 /* Now we look for writes to the stack. We can determine if these will
3768 affect the equivalence we're tracking for DP and if not then we can
3769 keep tracking it. */
3770 if (GET_CODE (XEXP (set
, 0)) == MEM
3771 && GET_CODE (*dp_current
) == MEM
)
3773 /* Look at the SP offsets and look for any overlaps. */
3774 int dp_cur_sp_offs
= INTVAL (XEXP (XEXP (*dp_current
, 0), 1));
3775 int set_sp_offs
= INTVAL (XEXP (XEXP (XEXP (set
, 0), 0), 1));
3777 if (abs (dp_cur_sp_offs
- set_sp_offs
) < 2)
3779 *dp_current
= NULL_RTX
;
3784 else if (GET_CODE (XEXP (set
, 0)) == REG
3785 && *dp_current
!= NULL_RTX
3786 && !ip2k_xexp_not_uses_reg_p (*dp_current
, REGNO (XEXP (set
, 0)),
3787 GET_MODE_SIZE (GET_MODE (XEXP (set
,
3790 /* If we've just clobbered all or part of a register reference that we
3791 were sharing for DP then we can't share it any more! */
3792 *dp_current
= NULL_RTX
;
3795 return dp_current_ok
;
3798 /* As part of the machine-dependent reorg we scan loads and reloads of
3799 DP to see where any are redundant. This does happens because we
3800 are able to subsequently transform things in interesting ways. Sometimes
3801 gcc also does unnecessary reloads too so we try to eliminate these too. */
3804 mdr_try_dp_reload_elim (first_insn
)
3808 struct dpre_jump_targets
*djt
;
3810 int incomplete_scan
;
3811 int last_incomplete_scan
;
3813 ip2k_dpre_jump_targets
3814 = (struct dpre_jump_targets
*) xcalloc (get_max_uid (),
3815 sizeof (struct dpre_jump_targets
));
3817 /* First we scan to build up a list of all CODE_LABEL insns and we work out
3818 how many different ways we can reach them. */
3819 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
3821 if (GET_CODE (insn
) == CODE_LABEL
)
3823 djt
= &ip2k_dpre_jump_targets
[INSN_UID (insn
)];
3825 djt
->reach_count
= LABEL_NUSES (insn
);
3826 djt
->touch_count
= 0;
3827 djt
->dp_equiv
= NULL_RTX
;
3828 if (! prev_nonnote_insn (insn
)
3829 || (prev_nonnote_insn (insn
)
3830 && GET_CODE (prev_nonnote_insn (insn
)) != BARRIER
))
3835 /* Next we scan all of the ways of reaching the code labels to see
3836 what the DP register is equivalent to as we reach them. If we find
3837 that they're the same then we keep noting the matched value. We
3838 iterate around this until we reach a convergence on DP equivalences
3839 at all code labels - we have to be very careful not to be too
3841 incomplete_scan
= -1;
3844 int dp_current_ok
= 0;
3845 last_incomplete_scan
= incomplete_scan
;
3846 dp_current
= NULL_RTX
;
3848 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
3850 /* If we have a code label then we need to see if we already know
3851 what the equivalence is at this point. If we do then we use it
3852 immediately, but if we don't then we have a special case to track
3853 when we hit a fallthrough-edge (label with no barrier preceding
3854 it). Any other accesses to the label must be from jump insns
3855 and so they're handled elsewhere. */
3856 if (GET_CODE (insn
) == CODE_LABEL
)
3858 djt
= &ip2k_dpre_jump_targets
[INSN_UID (insn
)];
3860 /* If we're fully characterized the use the equivalence. */
3861 if (djt
->touch_count
== djt
->reach_count
)
3863 dp_current
= djt
->dp_equiv
;
3868 /* If we have a known equivalence for DP as we reach the
3869 fallthrough-edge then track this into the code label. */
3871 && (! prev_nonnote_insn (insn
)
3872 || (prev_nonnote_insn (insn
)
3873 && GET_CODE (prev_nonnote_insn (insn
)) != BARRIER
)))
3875 if (djt
->touch_count
== 0)
3876 djt
->dp_equiv
= dp_current
;
3878 if (djt
->touch_count
< djt
->reach_count
)
3881 if (! rtx_equal_p (djt
->dp_equiv
, dp_current
))
3883 /* When we definitely know that we can't form an
3884 equivalence for DP here we must clobber anything
3885 that we'd started to track too. */
3886 djt
->dp_equiv
= NULL_RTX
;
3887 dp_current
= NULL_RTX
;
3893 /* If we've not completely characterized this code label then
3894 be cautious and assume that we don't know what DP is
3896 if (djt
->touch_count
< djt
->reach_count
)
3898 dp_current
= NULL_RTX
;
3905 /* If we've hit a jump insn then we look for either an address
3906 vector (jump table) or for jump label references. */
3907 if (GET_CODE (insn
) == JUMP_INSN
)
3909 /* Don't attempt to track here if we don't have a known
3910 equivalence for DP at this point. */
3913 rtx pat
= PATTERN (insn
);
3914 if (GET_CODE (pat
) == ADDR_VEC
)
3917 int len
= XVECLEN (pat
, 0);
3919 for (i
= 0; i
< len
; i
++)
3921 rtx vec_insn
= XEXP (XVECEXP (pat
, 0, i
), 0);
3922 djt
= &ip2k_dpre_jump_targets
[INSN_UID (vec_insn
)];
3924 if (djt
->touch_count
== 0)
3925 djt
->dp_equiv
= dp_current
;
3927 if (djt
->touch_count
< djt
->reach_count
)
3930 if (! rtx_equal_p (djt
->dp_equiv
, dp_current
))
3931 djt
->dp_equiv
= NULL_RTX
;
3935 else if (JUMP_LABEL (insn
))
3937 rtx j_insn
= JUMP_LABEL (insn
);
3938 djt
= &ip2k_dpre_jump_targets
[INSN_UID (j_insn
)];
3940 if (djt
->touch_count
== 0)
3941 djt
->dp_equiv
= dp_current
;
3943 if (djt
->touch_count
< djt
->reach_count
)
3946 if (! rtx_equal_p (djt
->dp_equiv
, dp_current
))
3947 djt
->dp_equiv
= NULL_RTX
;
3955 /* Anything other than a code labal or jump arrives here.
3956 We try and track DP, but sometimes we might not be able to. */
3957 dp_current_ok
= track_dp_reload (insn
, &dp_current
,
3961 /* When we're looking to see if we've finished we count the number of
3962 paths through the code labels where we weren't able to definitively
3964 This number is used to see if we're converging on a solution.
3965 If this hits zero then we've fully converged, but if this stays the
3966 same as last time then we probably can't make any further
3968 incomplete_scan
= 0;
3969 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
3971 if (GET_CODE (insn
) == CODE_LABEL
)
3973 djt
= &ip2k_dpre_jump_targets
[INSN_UID (insn
)];
3974 if (djt
->touch_count
!= djt
->reach_count
)
3976 incomplete_scan
+= (djt
->reach_count
- djt
->touch_count
);
3977 djt
->dp_equiv
= NULL_RTX
;
3978 djt
->touch_count
= 0;
3983 while (incomplete_scan
&& incomplete_scan
!= last_incomplete_scan
);
3985 /* Finally we scan the whole function and run DP elimination. When we hit
3986 a CODE_LABEL we pick up any stored equivalence since we now know that
3987 every path to this point entered with DP holding the same thing! If
3988 we subsequently have a reload that matches then we can eliminate it. */
3989 dp_current
= NULL_RTX
;
3990 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
3992 if (GET_CODE (insn
) == JUMP_INSN
)
3995 if (GET_CODE (insn
) == CODE_LABEL
)
3997 djt
= &ip2k_dpre_jump_targets
[INSN_UID (insn
)];
3998 dp_current
= djt
->dp_equiv
;
4002 track_dp_reload (insn
, &dp_current
, 1, 1);
4005 free (ip2k_dpre_jump_targets
);
4008 /* As part of the machine-dependent reorg we look for reloads of DP
4009 that we can move to earlier points within the file.
4010 Moving these out of the way allows more peepholes to match. */
4013 mdr_try_move_dp_reload (first_insn
)
4020 /* Don't try to match the first instruction because we can't move it
4022 orig_first
= first_insn
;
4023 first_insn
= next_nonnote_insn (first_insn
);
4025 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
4027 if (GET_CODE (insn
) != INSN
)
4030 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
4031 if (set
== NULL_RTX
)
4034 /* Look for DP being loaded. When we find this we start a rewind
4035 scan looking for possible positions to move this to. */
4036 if (GET_CODE (XEXP (set
, 0)) == REG
4037 && REGNO (XEXP (set
, 0)) == REG_DP
4038 && GET_MODE (XEXP (set
, 0)) == HImode
)
4041 rtx try_insn
= insn
;
4050 /* For now we do the *really* simple version of things and only
4051 attempt to move the load of DP if it's very safe to do so. */
4052 rewind
= prev_nonnote_insn (try_insn
);
4053 if (rewind
!= orig_first
&& rewind
!= NULL_RTX
4054 && GET_CODE (rewind
) == INSN
)
4056 check
= ((GET_CODE (PATTERN (rewind
)) == SET
)
4057 ? PATTERN (rewind
) : NULL_RTX
);
4058 if (check
!= NULL_RTX
4059 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (check
, 0))
4060 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (check
, 1)))
4062 if (GET_CODE (XEXP (check
, 0)) == REG
4063 && REGNO (XEXP (check
, 0)) != REG_DPH
4064 && REGNO (XEXP (check
, 0)) != REG_DPL
4065 && (ip2k_composite_xexp_not_uses_reg_p
4066 (XEXP (check
, 1), REG_DP
, 2))
4067 && (ip2k_composite_xexp_not_uses_reg_p
4069 REGNO (XEXP (check
, 0)),
4070 GET_MODE_SIZE (GET_MODE (XEXP (check
, 0))))))
4072 emit_insn_before (set
, rewind
);
4073 if (try_insn
== insn
)
4074 insn
= prev_nonnote_insn (insn
);
4075 delete_insn (try_insn
);
4076 try_insn
= prev_nonnote_insn (rewind
);
4079 else if (GET_CODE (XEXP (set
, 1)) == REG
4080 && ip2k_composite_xexp_not_uses_reg_p (XEXP (check
, 1), REG_DP
, 2)
4081 && ip2k_composite_xexp_not_uses_reg_p (XEXP (check
, 0), REG_DP
, 2)
4082 && ip2k_composite_xexp_not_uses_reg_p (XEXP (check
, 0), REGNO (XEXP (set
, 1)),
4083 GET_MODE_SIZE (GET_MODE (XEXP (set
, 1)))))
4085 emit_insn_before (set
, rewind
);
4086 if (try_insn
== insn
)
4087 insn
= prev_nonnote_insn (insn
);
4088 delete_insn (try_insn
);
4089 try_insn
= prev_nonnote_insn (rewind
);
4095 while (try_again
&& try_insn
);
4099 #endif /* IP2K_MD_REORG_PASS */
4101 /* Look to see if the expression, x, can have any stack references offset by
4102 a fixed constant, offset. If it definitely can then returns nonzero. */
4105 ip2k_check_can_adjust_stack_ref (rtx x
, int offset
)
4107 if (ARITHMETIC_P (x
))
4108 return (ip2k_check_can_adjust_stack_ref (XEXP (x
, 0), offset
)
4109 && ip2k_check_can_adjust_stack_ref (XEXP (x
, 1), offset
));
4112 return ip2k_check_can_adjust_stack_ref (XEXP (x
, 0), offset
);
4114 switch (GET_CODE (x
))
4117 return (REGNO (x
) != REG_SPH
&& REGNO (x
) != REG_SPL
);
4120 if (GET_CODE (XEXP (x
, 0)) != PLUS
)
4123 if (GET_CODE (XEXP (XEXP (x
, 0), 0)) != REG
)
4126 if (REGNO (XEXP (XEXP (x
, 0), 0)) != REG_SP
)
4129 /* We can't allow this if the adjustment will create an
4131 return (INTVAL (XEXP (XEXP (x
, 0), 1))
4132 + offset
<= (128 - 2 * GET_MODE_SIZE (GET_MODE (x
))));
4146 /* Adjusts all of the stack references in the expression pointed to by x by
4150 ip2k_adjust_stack_ref (rtx
*x
, int offset
)
4152 if (ARITHMETIC_P (*x
))
4154 ip2k_adjust_stack_ref (&XEXP (*x
, 0), offset
);
4155 ip2k_adjust_stack_ref (&XEXP (*x
, 1), offset
);
4161 ip2k_adjust_stack_ref (&XEXP (*x
, 0), offset
);
4165 switch (GET_CODE (*x
))
4168 if (GET_CODE (XEXP (*x
, 0)) != PLUS
)
4171 if (GET_CODE (XEXP (XEXP (*x
, 0), 0)) != REG
)
4174 if (REGNO (XEXP (XEXP (*x
, 0), 0)) != REG_SP
)
4178 XEXP (XEXP (*x
, 0), 1) = GEN_INT (INTVAL (XEXP (XEXP (*x
, 0), 1))
4187 #ifdef IP2K_MD_REORG_PASS
4188 /* As part of the machine-dependent reorg we look to move push instructions
4189 to earlier points within the file. Moving these out of the way allows more
4190 peepholes to match. */
4193 mdr_try_move_pushes (first_insn
)
4200 /* Don't try to match the first instruction because we can't move
4202 orig_first
= first_insn
;
4203 first_insn
= next_nonnote_insn (first_insn
);
4205 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
4207 if (GET_CODE (insn
) != INSN
)
4210 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
4211 if (set
== NULL_RTX
)
4214 /* Have we found a push instruction? */
4215 if (GET_CODE (XEXP (set
, 0)) == MEM
4216 && GET_CODE (XEXP (XEXP (set
, 0), 0)) == POST_DEC
4217 && GET_CODE (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG
4218 && REGNO (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG_SP
4219 && GET_CODE (XEXP (set
, 1)) == REG
)
4221 rtx try_insn
= insn
;
4222 unsigned int regno
= REGNO (XEXP (set
, 1));
4223 int reg_range
= GET_MODE_SIZE (GET_MODE (XEXP (set
, 1)));
4230 rewind
= prev_nonnote_insn (try_insn
);
4231 if (rewind
== orig_first
|| rewind
== NULL_RTX
4232 || GET_CODE (rewind
) != INSN
)
4235 check
= (GET_CODE (PATTERN (rewind
)) == SET
) ? PATTERN (rewind
) : NULL_RTX
;
4236 if (check
== NULL_RTX
)
4239 if (! ip2k_check_can_adjust_stack_ref (XEXP (check
, 0),
4241 || ! ip2k_check_can_adjust_stack_ref (XEXP (check
, 1),
4245 /* If we've hit another push instruction we can't go any
4247 if (GET_CODE (XEXP (check
, 0)) == MEM
4248 && GET_CODE (XEXP (XEXP (check
, 0), 0)) == POST_DEC
4249 && GET_CODE (XEXP (XEXP (XEXP (check
, 0), 0), 0)) == REG
4250 && REGNO (XEXP (XEXP (XEXP (check
, 0), 0), 0)) == REG_SP
)
4253 /* If this is a register move then check that it doesn't clobber
4254 SP or any part of the instruction we're trying to move. */
4255 if (GET_CODE (XEXP (check
, 0)) == REG
)
4257 unsigned int check_reg
= REGNO (XEXP (check
, 0));
4258 int check_reg_range
= GET_MODE_SIZE (GET_MODE (XEXP (check
,
4261 /* If we have a special case where what we want to push is
4262 being loaded by this "clobbering" insn then we can just
4263 push what is being used to load us and then do the load.
4264 This may seem a little odd, but we may subsequently be
4265 able to merge the load with another instruction as it
4266 may only be used once now! Note though that we
4267 specifically don't try this if the expression being
4268 loaded is an HImode MEM using IP. */
4269 if (check_reg
== regno
4270 && check_reg_range
== reg_range
4271 && ((GET_CODE (XEXP (check
, 1)) == REG
4272 || (GET_CODE (XEXP (check
, 1)) == MEM
4273 && (GET_MODE (XEXP (check
, 1)) != HImode
4274 || ip2k_xexp_not_uses_reg_for_mem (XEXP (check
, 1), REG_IP
))))))
4276 switch (check_reg_range
)
4279 emit_insn_before (gen_movqi (XEXP (set
, 0),
4282 delete_insn (try_insn
);
4286 emit_insn_before (gen_movhi (XEXP (set
, 0),
4289 delete_insn (try_insn
);
4293 emit_insn_before (gen_movsi (XEXP (set
, 0),
4296 delete_insn (try_insn
);
4300 emit_insn_before (gen_movdi (XEXP (set
, 0),
4303 delete_insn (try_insn
);
4307 ip2k_adjust_stack_ref (&XEXP (check
, 0), reg_range
);
4308 ip2k_adjust_stack_ref (&XEXP (check
, 1), reg_range
);
4309 try_insn
= prev_nonnote_insn (rewind
);
4310 /* XXX - should be a continue? */
4314 if ((check_reg
== REG_SPL
)
4315 || (check_reg
== REG_SPH
)
4316 || (((regno
<= check_reg
)
4317 && (regno
+ reg_range
- 1) >= check_reg
)
4318 || ((regno
<= (check_reg
+ check_reg_range
- 1))
4319 && ((regno
+ reg_range
- 1)
4320 >= (check_reg
+ check_reg_range
- 1)))))
4324 emit_insn_before (set
, rewind
);
4325 delete_insn (try_insn
);
4326 ip2k_adjust_stack_ref (&XEXP (check
, 0), reg_range
);
4327 ip2k_adjust_stack_ref (&XEXP (check
, 1), reg_range
);
4328 try_insn
= prev_nonnote_insn (rewind
);
4334 /* Assist the following function, mdr_try_propagate_clr(). */
4337 mdr_try_propagate_clr_sequence (first_insn
, regno
)
4343 for (try_insn
= next_nonnote_insn (first_insn
); try_insn
;
4344 try_insn
= next_nonnote_insn (try_insn
))
4346 rtx new_insn
= NULL_RTX
;
4349 if (GET_CODE (try_insn
) == JUMP_INSN
)
4352 if (GET_CODE (try_insn
) != INSN
)
4355 set2
= ((GET_CODE (PATTERN (try_insn
)) == SET
)
4356 ? PATTERN (try_insn
) : NULL_RTX
);
4357 if (set2
== NULL_RTX
)
4360 if (GET_CODE (XEXP (set2
, 1)) == AND
4361 && ((GET_CODE (XEXP (XEXP (set2
, 1), 0)) == REG
4362 && REGNO (XEXP (XEXP (set2
, 1), 0)) == regno
)
4363 || (GET_CODE (XEXP (XEXP (set2
, 1), 1)) == REG
4364 && REGNO (XEXP (XEXP (set2
, 1), 1)) == regno
)))
4366 rtx remove_insn
= try_insn
;
4367 try_insn
= emit_insn_before (gen_rtx_SET (QImode
, XEXP (set2
, 0),
4368 const0_rtx
), try_insn
);
4369 delete_insn (remove_insn
);
4371 else if (GET_CODE (XEXP (set2
, 1)) == IOR
4372 && GET_CODE (XEXP (XEXP (set2
, 1), 0)) == REG
4373 && REGNO (XEXP (XEXP (set2
, 1), 0)) == regno
)
4375 rtx remove_insn
= try_insn
;
4376 try_insn
= emit_insn_before (gen_rtx_SET (QImode
, XEXP (set2
, 0),
4377 XEXP (XEXP (set2
, 1), 1)),
4379 delete_insn (remove_insn
);
4381 else if (GET_CODE (XEXP (set2
, 1)) == IOR
4382 && GET_CODE (XEXP (XEXP (set2
, 1), 1)) == REG
4383 && REGNO (XEXP (XEXP (set2
, 1), 1)) == regno
)
4385 rtx remove_insn
= try_insn
;
4386 try_insn
= emit_insn_before (gen_rtx_SET (QImode
, XEXP (set2
, 0),
4387 XEXP (XEXP (set2
, 1), 0)),
4389 delete_insn (remove_insn
);
4391 else if (GET_CODE (XEXP (set2
, 1)) == XOR
4392 && GET_CODE (XEXP (XEXP (set2
, 1), 0)) == REG
4393 && REGNO (XEXP (XEXP (set2
, 1), 0)) == regno
)
4395 rtx remove_insn
= try_insn
;
4396 try_insn
= emit_insn_before (gen_rtx_SET (QImode
, XEXP (set2
, 0),
4397 XEXP (XEXP (set2
, 1), 1)),
4399 delete_insn (remove_insn
);
4401 else if (GET_CODE (XEXP (set2
, 1)) == XOR
4402 && GET_CODE (XEXP (XEXP (set2
, 1), 1)) == REG
4403 && REGNO (XEXP (XEXP (set2
, 1), 1)) == regno
)
4405 rtx remove_insn
= try_insn
;
4406 try_insn
= emit_insn_before (gen_rtx_SET (QImode
, XEXP (set2
, 0),
4407 XEXP (XEXP (set2
, 1), 0)),
4409 delete_insn (remove_insn
);
4412 if (GET_CODE (XEXP (set2
, 0)) == REG
)
4414 int reg2_range
= GET_MODE_SIZE (GET_MODE (XEXP (set2
, 0)));
4415 unsigned int regno2
= REGNO (XEXP (set2
, 0));
4419 && GET_CODE (XEXP (set2
, 1)) == CONST_INT
)
4421 int iv
= INTVAL (XEXP (set2
, 1));
4424 if (iv
== 1 || iv
== -1)
4426 new_insn
= gen_rtx_SET (QImode
, XEXP (set2
, 0),
4427 gen_rtx_PLUS (QImode
, XEXP (set2
, 0),
4429 new_insn
= emit_insn_before (new_insn
, try_insn
);
4430 delete_insn (try_insn
);
4431 try_insn
= new_insn
;
4436 if ((regno
>= regno2
) && (regno
<= regno2
+ reg2_range
- 1))
4439 if (GET_CODE (XEXP (set2
, 1)) == REG
4440 && REGNO (XEXP (set2
, 1)) == regno
)
4442 new_insn
= emit_insn_before (gen_rtx_SET (QImode
,
4446 delete_insn (try_insn
);
4447 try_insn
= new_insn
;
4451 if (GET_CODE (XEXP (set2
, 0)) == CC0
)
4453 if (GET_CODE (XEXP (set2
, 1)) == REG
4454 && GET_MODE_SIZE (GET_MODE (XEXP (set2
, 1))) == 2
4455 && REGNO (XEXP (set2
, 1)) == regno
)
4457 new_insn
= gen_rtx_SET (VOIDmode
, gen_rtx_CC0 (VOIDmode
),
4458 gen_rtx_REG(QImode
, regno
+ 1));
4459 new_insn
= emit_insn_before (new_insn
, try_insn
);
4461 else if (GET_CODE (XEXP (set2
, 1)) == COMPARE
4462 && GET_CODE (XEXP (XEXP (set2
, 1), 0)) == REG
4463 && GET_MODE_SIZE (GET_MODE (XEXP (XEXP (set2
, 1), 0))) == 2
4464 && REGNO (XEXP (XEXP (set2
, 1), 0)) == regno
4465 && GET_CODE (XEXP (XEXP (set2
, 1), 1)) == CONST_INT
4466 && INTVAL (XEXP (XEXP (set2
, 1), 1)) >= 0
4467 && INTVAL (XEXP (XEXP (set2
, 1), 1)) < 256)
4469 new_insn
= gen_rtx_SET (VOIDmode
, cc0_rtx
,
4470 gen_rtx_COMPARE(QImode
,
4471 gen_rtx_REG (QImode
,
4473 XEXP (XEXP (set2
, 1),
4475 new_insn
= emit_insn_before (new_insn
, try_insn
);
4478 /* If we have inserted a replacement for a CC0 setter operation
4479 then we need to delete the old one. */
4480 if (new_insn
!= NULL_RTX
)
4482 delete_insn (try_insn
);
4483 try_insn
= new_insn
;
4485 /* Now as we know that we have just done an unsigned compare
4486 (remember we were zero-extended by the clr!) we also know
4487 that we don't need a signed jump insn. If we find that
4488 our next isns is a signed jump then make it unsigned! */
4489 if (GET_CODE (next_nonnote_insn (try_insn
)) == JUMP_INSN
)
4493 try_insn
= next_nonnote_insn (try_insn
);
4494 set3
= ((GET_CODE (PATTERN (try_insn
)) == SET
)
4495 ? PATTERN (try_insn
) : NULL_RTX
);
4496 if (set3
== NULL_RTX
)
4499 /* If we discover that our jump target is only accessible
4500 from here then we can continue our "clr" propagation to
4502 if (LABEL_NUSES (JUMP_LABEL (try_insn
)) == 1)
4503 mdr_try_propagate_clr_sequence (JUMP_LABEL (try_insn
),
4506 if (GET_CODE (XEXP (set3
, 0)) == PC
4507 && GET_CODE (XEXP (set3
, 1)) == IF_THEN_ELSE
4508 && (GET_CODE (XEXP (XEXP (set3
, 1), 0)) == GT
4509 || GET_CODE (XEXP (XEXP (set3
, 1), 0)) == GE
4510 || GET_CODE (XEXP (XEXP (set3
, 1), 0)) == LT
4511 || GET_CODE (XEXP (XEXP (set3
, 1), 0)) == LE
)
4512 && GET_CODE (XEXP (XEXP (XEXP (set3
, 1), 0), 0)) == CC0
4513 && (GET_CODE (XEXP (XEXP (XEXP (set3
, 1), 0), 1))
4515 && GET_CODE (XEXP (XEXP (set3
, 1), 1)) == LABEL_REF
4516 && GET_CODE (XEXP (XEXP (set3
, 1), 2)) == PC
)
4522 /* Replace our old conditional jump with a new one that
4523 does the unsigned form of what was previously a
4524 signed comparison. */
4525 code
= GET_CODE (XEXP (XEXP (set3
, 1), 0));
4526 cmp
= gen_rtx_fmt_ee ((code
== GT
4530 : (code
== LT
? LTU
: LEU
))),
4532 XEXP (XEXP (XEXP (set3
, 1), 0), 0),
4533 XEXP (XEXP (XEXP (set3
, 1), 0),
4536 = gen_rtx_SET (GET_MODE (set3
),
4538 gen_rtx_IF_THEN_ELSE
4539 (GET_MODE (XEXP (set3
, 1)), cmp
,
4540 XEXP (XEXP (set3
, 1), 1),
4541 XEXP (XEXP (set3
, 1), 2)));
4542 new_insn
= emit_jump_insn_before (new_if
, try_insn
);
4543 LABEL_NUSES (JUMP_LABEL (try_insn
))++;
4544 delete_insn (try_insn
);
4545 try_insn
= new_insn
;
4550 else if (GET_CODE (XEXP (set2
, 1)) == PLUS
4551 && GET_CODE (XEXP (XEXP (set2
, 1), 0)) == REG
4552 && GET_MODE_SIZE (GET_MODE (XEXP (XEXP (set2
, 1), 0))) == 2
4553 && REGNO (XEXP (XEXP (set2
, 1), 0)) == regno
4554 && (GET_CODE (XEXP (XEXP (set2
, 1), 1)) == REG
4555 || GET_CODE (XEXP (XEXP (set2
, 1), 1)) == MEM
4556 || GET_CODE (XEXP (XEXP (set2
, 1), 1)) == CONST_INT
4557 || GET_CODE (XEXP (XEXP (set2
, 1), 1)) == CONST
4558 || GET_CODE (XEXP (XEXP (set2
, 1), 1)) == SYMBOL_REF
))
4560 rtx extend
= gen_rtx_ZERO_EXTEND (HImode
,
4561 gen_rtx_REG (QImode
, regno
+ 1));
4562 new_insn
= gen_rtx_SET (HImode
, XEXP (set2
, 0),
4563 gen_rtx_PLUS (HImode
, extend
,
4564 XEXP (XEXP (set2
, 1), 1)));
4565 new_insn
= emit_insn_before (new_insn
, try_insn
);
4566 delete_insn (try_insn
);
4567 try_insn
= new_insn
;
4569 else if (GET_CODE (XEXP (set2
, 1)) == PLUS
4570 && GET_CODE (XEXP (XEXP (set2
, 1), 1)) == REG
4571 && GET_MODE_SIZE (GET_MODE (XEXP (XEXP (set2
, 1), 1))) == 2
4572 && REGNO (XEXP (XEXP (set2
, 1), 1)) == regno
4573 && (GET_CODE (XEXP (XEXP (set2
, 1), 0)) == REG
4574 || GET_CODE (XEXP (XEXP (set2
, 1), 0)) == MEM
4575 || GET_CODE (XEXP (XEXP (set2
, 1), 0)) == CONST_INT
4576 || GET_CODE (XEXP (XEXP (set2
, 1), 0)) == CONST
4577 || GET_CODE (XEXP (XEXP (set2
, 1), 0)) == SYMBOL_REF
))
4579 rtx t_src
= gen_rtx_PLUS (HImode
,
4580 gen_rtx_ZERO_EXTEND (HImode
,
4581 gen_rtx_REG (QImode
,
4584 XEXP (XEXP (set2
, 1), 0));
4585 new_insn
= emit_insn_before (gen_rtx_SET (HImode
, XEXP (set2
, 0),
4588 delete_insn (try_insn
);
4589 try_insn
= new_insn
;
4594 /* One of the things that can quite often happen with an 8-bit CPU is that
4595 we end up clearing the MSByte of a 16-bit value. Unfortunately, all too
4596 often gcc doesn't have any way to realize that only half of the value is
4597 useful and ends up doing more work than it should. We scan for such
4598 occurrences here, track them and reduce compare operations to a smaller
4599 size where possible.
4601 Note that this is somewhat different to move propagation as we may
4602 actually change some instruction patterns when we're doing this whereas
4603 move propagation is just about doing a search and replace. */
4606 mdr_try_propagate_clr (first_insn
)
4612 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
4614 if (GET_CODE (insn
) != INSN
)
4617 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
4618 if (set
== NULL_RTX
)
4621 /* Have we found a "clr" instruction? */
4622 if (GET_CODE (XEXP (set
, 0)) == REG
4623 && GET_CODE (XEXP (set
, 1)) == CONST_INT
4624 && GET_MODE_SIZE (GET_MODE (XEXP (set
, 0))) == 1
4625 && INTVAL (XEXP (set
, 1)) == 0)
4627 mdr_try_propagate_clr_sequence (insn
, REGNO (XEXP (set
, 0)));
4631 #endif /* IP2K_MD_REORG_PASS */
4633 /* Look to see if the expression, x, does not make any memory references
4634 via the specified register. This is very conservative and only returns
4635 nonzero if we definitely don't have such a memory ref. */
4638 ip2k_xexp_not_uses_reg_for_mem (rtx x
, unsigned int regno
)
4641 regno
&= 0xfffffffe;
4643 switch (GET_CODE (x
))
4649 if ((GET_CODE (XEXP (x
, 0)) == PLUS
4650 && GET_CODE (XEXP (XEXP (x
, 0), 0)) == REG
4651 && REGNO (XEXP (XEXP (x
, 0), 0)) == regno
)
4652 || (GET_CODE (XEXP (x
, 0)) == REG
4653 && REGNO (XEXP (x
, 0)) == regno
))
4668 if (GET_RTX_CLASS (GET_CODE (x
)) == RTX_BITFIELD_OPS
)
4669 return (ip2k_xexp_not_uses_reg_for_mem (XEXP (x
, 0), regno
)
4670 && ip2k_xexp_not_uses_reg_for_mem (XEXP (x
, 1), regno
)
4671 && ip2k_xexp_not_uses_reg_for_mem (XEXP (x
, 2), regno
));
4674 return (ip2k_xexp_not_uses_reg_for_mem (XEXP (x
, 0), regno
)
4675 && ip2k_xexp_not_uses_reg_for_mem (XEXP (x
, 1), regno
));
4678 || GET_RTX_CLASS (GET_CODE (x
)) == '3')
4679 return ip2k_xexp_not_uses_reg_for_mem (XEXP (x
, 0), regno
);
4685 #ifdef IP2K_MD_REORG_PASS
4686 /* Assist the following function, mdr_try_propagate_move(). */
4689 mdr_try_propagate_move_sequence (first_insn
, orig
, equiv
)
4696 for (try_insn
= next_nonnote_insn (first_insn
); try_insn
;
4697 try_insn
= next_nonnote_insn (try_insn
))
4701 rtx new_equiv
= NULL_RTX
;
4703 if (GET_CODE (try_insn
) != JUMP_INSN
&& GET_CODE (try_insn
) != INSN
)
4706 set
= single_set (try_insn
);
4707 if (set
== NULL_RTX
)
4710 range
= MAX (GET_MODE_SIZE (GET_MODE (equiv
)),
4711 GET_MODE_SIZE (GET_MODE (XEXP (set
, 0))));
4713 if (GET_CODE (equiv
) == REG
4714 && REGNO (equiv
) == REG_W
4715 && (recog_memoized (try_insn
) < 0
4716 || get_attr_clobberw (try_insn
) != CLOBBERW_NO
)
4717 && (! (GET_CODE (XEXP (set
, 0)) == REG
4718 && REGNO (XEXP (set
, 0)) == REG_W
4719 && rtx_equal_p (XEXP (set
, 1), orig
))))
4721 else if (GET_CODE (XEXP (set
, 0)) == REG
4722 && (REGNO (XEXP (set
, 0)) == REG_SP
4723 || ! ip2k_xexp_not_uses_reg_p (equiv
, REGNO (XEXP (set
, 0)),
4725 || ! ip2k_xexp_not_uses_reg_p (orig
, REGNO (XEXP (set
, 0)),
4727 && ! rtx_equal_p (equiv
, XEXP (set
, 0))
4728 && ! rtx_equal_p (orig
, XEXP (set
, 0)))
4730 else if (GET_CODE (orig
) == REG
4731 && (REGNO (orig
) == REG_IPL
4732 || REGNO (orig
) == REG_IPH
4733 || REGNO (orig
) == REG_DPL
4734 || REGNO (orig
) == REG_DPH
)
4735 && (! ip2k_xexp_not_uses_reg_for_mem (XEXP (set
, 0),
4737 || ! ip2k_xexp_not_uses_reg_for_mem (XEXP (set
, 1),
4740 else if (GET_CODE (XEXP (set
, 0)) == MEM
4741 && GET_CODE (equiv
) == MEM
)
4743 if (! ip2k_xexp_not_uses_reg_p (equiv
, REG_SP
, 2))
4745 if (! ip2k_xexp_not_uses_reg_p (XEXP (set
, 0), REG_SP
, 2))
4747 /* We look for a special case of "push" operations screwing
4748 our register equivalence when it's based on a stack slot.
4749 We can track this one and replace the old equivalence
4750 expression with a new one. */
4751 if (GET_CODE (XEXP (XEXP (set
, 0), 0)) == POST_DEC
4752 && GET_CODE (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG
4753 && REGNO (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG_SP
4754 && GET_CODE (XEXP (equiv
, 0)) == PLUS
4755 && REGNO (XEXP (XEXP (equiv
, 0), 0)) == REG_SP
)
4757 int md_size
= GET_MODE_SIZE (GET_MODE (XEXP (set
, 0)));
4758 int new_sp_offs
= INTVAL (XEXP (XEXP (equiv
, 0), 1))
4761 /* Don't allow an invalid stack pointer offset to be
4763 if (new_sp_offs
> (128 - 2 * md_size
))
4767 = gen_rtx_MEM (GET_MODE (equiv
),
4768 gen_rtx_PLUS (Pmode
,
4769 gen_rtx_REG (HImode
,
4771 GEN_INT (new_sp_offs
)));
4773 else if (! rtx_equal_p (equiv
, XEXP (set
, 0)))
4775 /* Look at the SP offsets and look for any overlaps. */
4776 int equiv_offs
= GET_CODE (XEXP (equiv
, 0)) == PLUS
4777 ? INTVAL (XEXP (XEXP (equiv
, 0), 1))
4780 = (GET_CODE (XEXP (XEXP (set
, 0), 0)) == PLUS
4781 ? INTVAL (XEXP (XEXP (XEXP (set
, 0), 0), 1))
4784 if (abs (equiv_offs
- set_offs
) < range
)
4790 if (! ip2k_xexp_not_uses_reg_p (equiv
, REG_IP
, 2))
4793 if (! ip2k_xexp_not_uses_reg_p (XEXP (set
, 0), REG_DP
, 2)
4794 && ! ip2k_xexp_not_uses_reg_p (equiv
, REG_DP
, 2)
4795 && ! rtx_equal_p (equiv
, XEXP (set
, 0)))
4797 /* Look at the DP offsets and look for any overlaps. */
4798 int equiv_offs
= GET_CODE (XEXP (equiv
, 0)) == PLUS
4799 ? INTVAL (XEXP (XEXP (equiv
, 0), 1))
4801 int set_offs
= GET_CODE (XEXP (XEXP (set
, 0), 0)) == PLUS
4802 ? INTVAL (XEXP (XEXP (XEXP (set
, 0), 0), 1))
4805 if (abs (equiv_offs
- set_offs
) < range
)
4810 validate_replace_rtx_subexp (orig
, equiv
, try_insn
, &XEXP (set
, 1));
4812 if (rtx_equal_p (equiv
, XEXP (set
, 0))
4813 || rtx_equal_p (orig
, XEXP (set
, 0)))
4816 if (new_equiv
!= NULL_RTX
)
4821 /* Try propagating move instructions forwards. It may be that we can
4822 replace a register use with an equivalent expression that already
4823 holds the same value and thus allow one or more register loads to
4827 mdr_try_propagate_move (first_insn
)
4833 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
4835 if (GET_CODE (insn
) != INSN
)
4838 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
4839 if (set
== NULL_RTX
)
4842 /* Have we found a simple move instruction? */
4843 if (GET_CODE (XEXP (set
, 0)) == REG
4844 && (REGNO (XEXP (set
, 0)) >= 0x80
4845 || REGNO (XEXP (set
, 0)) == REG_DPL
4846 || REGNO (XEXP (set
, 0)) == REG_DPH
4847 || REGNO (XEXP (set
, 0)) == REG_IPL
4848 || REGNO (XEXP (set
, 0)) == REG_IPH
)
4849 && ((GET_CODE (XEXP (set
, 1)) == REG
4850 && REGNO (XEXP (set
, 1)) != REG_SP
4851 && ip2k_xexp_not_uses_reg_p (XEXP (set
, 0),
4852 REGNO (XEXP (set
, 1)),
4853 GET_MODE_SIZE (GET_MODE (XEXP (set
,
4855 || (GET_CODE (XEXP (set
, 1)) == MEM
4856 && (ip2k_xexp_not_uses_reg_p (XEXP (set
, 1), REG_IP
, 2)
4857 || GET_MODE (XEXP (set
, 1)) == QImode
)
4858 && ((REGNO (XEXP (set
, 0)) != REG_DPH
4859 && REGNO (XEXP (set
, 0)) != REG_DPL
)
4860 || ip2k_xexp_not_uses_reg_p (XEXP (set
, 1), REG_DP
, 2)))
4861 || (GET_CODE (XEXP (set
, 1)) == CONST_INT
4862 && (GET_MODE (XEXP (set
, 0)) != QImode
4863 || INTVAL (XEXP (set
, 1)) != 0))
4864 || GET_CODE (XEXP (set
, 1)) == CONST_DOUBLE
4865 || GET_CODE (XEXP (set
, 1)) == CONST
4866 || GET_CODE (XEXP (set
, 1)) == SYMBOL_REF
))
4868 mdr_try_propagate_move_sequence (insn
, XEXP (set
, 0), XEXP (set
, 1));
4873 /* Try to remove redundant instructions. */
4876 mdr_try_remove_redundant_insns (first_insn
)
4881 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
4884 enum machine_mode mode
;
4886 HOST_WIDE_INT pattern
;
4889 if (GET_CODE (insn
) != INSN
)
4892 if (GET_CODE (PATTERN (insn
)) == CONST_INT
)
4894 /* We've found a dummy expression. */
4895 rtx remove_insn
= insn
;
4896 insn
= prev_nonnote_insn (insn
);
4897 delete_insn (remove_insn
);
4901 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
4902 if (set
== NULL_RTX
)
4905 mode
= GET_MODE (XEXP (set
, 0));
4906 md_size
= GET_MODE_SIZE (mode
);
4907 if ((md_size
< 1) || (md_size
> 4))
4911 for (i
= 0; i
< md_size
; i
++)
4917 if ((GET_CODE (XEXP (set
, 1)) == AND
4918 && GET_CODE (XEXP (XEXP (set
, 1), 1)) == CONST_INT
4919 && INTVAL (XEXP (XEXP (set
, 1), 1)) == pattern
)
4920 || ((GET_CODE (XEXP (set
, 1)) == IOR
4921 || GET_CODE (XEXP (set
, 1)) == XOR
)
4922 && GET_CODE (XEXP (XEXP (set
, 1), 1)) == CONST_INT
4923 && INTVAL (XEXP (XEXP (set
, 1), 1)) == 0x00))
4925 /* We've found an AND with all 1's, an XOR with all 0's or an
4927 rtx remove_insn
= insn
;
4929 /* Is it completely redundant or should it become a move insn? */
4930 if (! rtx_equal_p (XEXP (set
, 0), XEXP (XEXP (set
, 1), 0)))
4932 emit_insn_before (gen_rtx_SET (mode
,
4934 XEXP (XEXP (set
, 1), 0)),
4938 insn
= prev_nonnote_insn(insn
);
4939 delete_insn (remove_insn
);
4941 else if (GET_CODE (XEXP (set
, 1)) == AND
4942 && GET_CODE (XEXP (XEXP (set
, 1), 1)) == CONST_INT
4943 && INTVAL (XEXP (XEXP (set
, 1), 1)) == 0)
4945 /* We've found an AND with all 0's. */
4946 rtx remove_insn
= insn
;
4947 insn
= emit_insn_before (gen_rtx_SET (mode
,
4949 XEXP (XEXP (set
, 1), 1)),
4951 delete_insn (remove_insn
);
4956 /* Structure used to track jump targets. */
4958 struct we_jump_targets
4960 int target
; /* Is this a jump target? */
4961 int reach_count
; /* Number of ways we can reach this insn. */
4962 int touch_count
; /* Number of times we've touched this insn
4964 rtx w_equiv
; /* WREG-equivalence at this point. */
4967 struct we_jump_targets
*ip2k_we_jump_targets
;
4969 /* WREG equivalence tracking used within DP reload elimination. */
4972 track_w_reload (insn
, w_current
, w_current_ok
, modifying
)
4980 if (GET_CODE (insn
) != INSN
)
4982 *w_current
= NULL_RTX
;
4986 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
4987 if (set
== NULL_RTX
)
4989 *w_current
= NULL_RTX
;
4993 /* Look for W being modified. If it is, see if it's being changed
4994 to what it already is! */
4995 if (GET_CODE (XEXP (set
, 0)) == REG
4996 && REGNO (XEXP (set
, 0)) == REG_W
4997 && GET_MODE (XEXP (set
, 0)) == QImode
)
4999 /* If this is an equivalence we can delete the new set operation. */
5000 if (*w_current
!= NULL_RTX
5001 && rtx_equal_p (XEXP (set
, 1), *w_current
))
5008 *w_current
= XEXP (set
, 1);
5012 else if (recog_memoized (insn
) < 0
5013 || get_attr_clobberw (insn
) != CLOBBERW_NO
)
5015 /* If we clobber W then we've clobbered any equivalences ! */
5016 *w_current
= NULL_RTX
;
5019 else if (! ip2k_xexp_not_uses_reg_p (XEXP (set
, 0), REG_SP
, 2)
5020 && *w_current
!= NULL_RTX
5021 && !ip2k_xexp_not_uses_reg_p (*w_current
, REG_SP
, 2))
5023 /* We look for a special case of "push" operations screwing up the
5024 setting of DP when it's based on the stack. We can track this one
5025 and replace the old expression for DP with a new one. */
5026 if (GET_CODE (XEXP (set
, 0)) == MEM
5027 && GET_CODE (XEXP (XEXP (set
, 0), 0)) == POST_DEC
5028 && GET_CODE (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG
5029 && REGNO (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG_SP
5030 && GET_CODE (*w_current
) == MEM
5031 && GET_CODE (XEXP (*w_current
, 0)) == PLUS
)
5033 /* XXX - need to ensure that we can track this without going
5035 rtx val
= GEN_INT (INTVAL (XEXP (XEXP (*w_current
, 0), 1))
5036 + GET_MODE_SIZE (GET_MODE (XEXP (set
, 0))));
5038 = gen_rtx_MEM (HImode
, gen_rtx_PLUS (Pmode
,
5039 gen_rtx_REG(HImode
, REG_SP
),
5044 else if (GET_CODE (XEXP (set
, 0)) == REG
5045 && *w_current
!= NULL_RTX
5046 && !ip2k_xexp_not_uses_reg_p (*w_current
, REGNO (XEXP (set
, 0)),
5047 GET_MODE_SIZE (GET_MODE (XEXP (set
5050 /* If we've just clobbered all or part of a register reference that we
5051 were sharing for W then we can't share it any more! */
5052 *w_current
= NULL_RTX
;
5055 return w_current_ok
;
5058 /* As part of the machine-dependent reorg we scan moves into w and track them
5059 to see where any are redundant. */
5062 mdr_try_wreg_elim (first_insn
)
5066 struct we_jump_targets
*wjt
;
5068 int incomplete_scan
;
5069 int last_incomplete_scan
;
5071 ip2k_we_jump_targets
5072 = (struct we_jump_targets
*) xcalloc (get_max_uid (),
5073 sizeof (struct we_jump_targets
));
5075 /* First we scan to build up a list of all CODE_LABEL insns and we work out
5076 how many different ways we can reach them. */
5077 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
5079 if (GET_CODE (insn
) == CODE_LABEL
)
5081 wjt
= &ip2k_we_jump_targets
[INSN_UID (insn
)];
5083 wjt
->reach_count
= LABEL_NUSES (insn
);
5084 wjt
->touch_count
= 0;
5085 wjt
->w_equiv
= NULL_RTX
;
5086 if (! prev_nonnote_insn (insn
)
5087 || (prev_nonnote_insn (insn
)
5088 && GET_CODE (prev_nonnote_insn (insn
)) != BARRIER
))
5093 /* Next we scan all of the ways of reaching the code labels to see
5094 what the WREG register is equivalent to as we reach them. If we find
5095 that they're the same then we keep noting the matched value. We
5096 iterate around this until we reach a convergence on WREG equivalences
5097 at all code labels - we have to be very careful not to be too
5099 incomplete_scan
= -1;
5102 int w_current_ok
= 0;
5103 last_incomplete_scan
= incomplete_scan
;
5104 w_current
= NULL_RTX
;
5106 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
5108 /* If we have a code label then we need to see if we already know
5109 what the equivalence is at this point. If we do then we use it
5110 immediately, but if we don't then we have a special case to track
5111 when we hit a fallthrough-edge (label with no barrier preceding
5112 it). Any other accesses to the label must be from jump insns
5113 and so they're handled elsewhere. */
5114 if (GET_CODE (insn
) == CODE_LABEL
)
5116 wjt
= &ip2k_we_jump_targets
[INSN_UID (insn
)];
5118 /* If we're fully characterized the use the equivalence. */
5119 if (wjt
->touch_count
== wjt
->reach_count
)
5121 w_current
= wjt
->w_equiv
;
5126 /* If we have a known equivalence for WREG as we reach the
5127 fallthrough-edge then track this into the code label. */
5129 && (! prev_nonnote_insn (insn
)
5130 || (prev_nonnote_insn (insn
)
5131 && GET_CODE (prev_nonnote_insn (insn
)) != BARRIER
)))
5133 if (wjt
->touch_count
== 0)
5134 wjt
->w_equiv
= w_current
;
5136 if (wjt
->touch_count
< wjt
->reach_count
)
5139 if (! rtx_equal_p (wjt
->w_equiv
, w_current
))
5141 /* When we definitely know that we can't form an
5142 equivalence for WREG here we must clobber anything
5143 that we'd started to track too. */
5144 wjt
->w_equiv
= NULL_RTX
;
5145 w_current
= NULL_RTX
;
5151 /* If we've not completely characterized this code label then
5152 be cautious and assume that we don't know what WREG is
5154 if (wjt
->touch_count
< wjt
->reach_count
)
5156 w_current
= NULL_RTX
;
5163 /* If we've hit a jump insn then we look for either an address
5164 vector (jump table) or for jump label references. */
5165 if (GET_CODE (insn
) == JUMP_INSN
)
5167 /* Don't attempt to track here if we don't have a known
5168 equivalence for WREG at this point. */
5171 if (JUMP_LABEL (insn
))
5174 = &ip2k_we_jump_targets
[INSN_UID (JUMP_LABEL (insn
))];
5176 if (wjt
->touch_count
== 0)
5177 wjt
->w_equiv
= w_current
;
5179 if (wjt
->touch_count
< wjt
->reach_count
)
5182 if (! rtx_equal_p (wjt
->w_equiv
, w_current
))
5183 wjt
->w_equiv
= NULL_RTX
;
5191 /* Anything other than a code labal or jump arrives here. We try and
5192 track WREG, but sometimes we might not be able to. */
5193 w_current_ok
= track_w_reload (insn
, &w_current
, w_current_ok
, 0);
5196 /* When we're looking to see if we've finished we count the number of
5197 paths through the code labels where we weren't able to definitively
5198 track WREG. This number is used to see if we're converging on a
5200 If this hits zero then we've fully converged, but if this stays the
5201 same as last time then we probably can't make any further
5203 incomplete_scan
= 0;
5204 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
5206 if (GET_CODE (insn
) == CODE_LABEL
)
5208 wjt
= &ip2k_we_jump_targets
[INSN_UID (insn
)];
5209 if (wjt
->touch_count
!= wjt
->reach_count
)
5211 incomplete_scan
+= (wjt
->reach_count
- wjt
->touch_count
);
5212 wjt
->w_equiv
= NULL_RTX
;
5213 wjt
->touch_count
= 0;
5218 while (incomplete_scan
&& incomplete_scan
!= last_incomplete_scan
);
5220 /* Finally we scan the whole function and run WREG elimination. When we hit
5221 a CODE_LABEL we pick up any stored equivalence since we now know that
5222 every path to this point entered with WREG holding the same thing! If
5223 we subsequently have a reload that matches then we can eliminate it. */
5224 w_current
= NULL_RTX
;
5225 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
5227 if (GET_CODE (insn
) == JUMP_INSN
)
5230 if (GET_CODE (insn
) == CODE_LABEL
)
5232 wjt
= &ip2k_we_jump_targets
[INSN_UID (insn
)];
5233 w_current
= wjt
->w_equiv
;
5237 track_w_reload (insn
, &w_current
, 1, 1);
5240 free (ip2k_we_jump_targets
);
5242 #endif /* IP2K_MD_REORG_PASS */
5244 /* We perform a lot of untangling of the RTL within the reorg pass since
5245 the IP2k requires some really bizarre (and really undesireable) things
5246 to happen in order to guarantee not aborting. This pass causes several
5247 earlier passes to be re-run as it progressively transforms things,
5248 making the subsequent runs continue to win. */
5253 #ifdef IP2K_MD_REORG_PASS
5254 rtx first_insn
, insn
, set
;
5261 ip2k_reorg_completed
= 1;
5262 ip2k_reorg_split_dimode
= 1;
5263 ip2k_reorg_split_simode
= 1;
5264 ip2k_reorg_split_himode
= 1;
5265 ip2k_reorg_split_qimode
= 1;
5266 ip2k_reorg_merge_qimode
= 1;
5269 #ifndef IP2K_MD_REORG_PASS
5270 ip2k_reorg_completed
= 1;
5271 ip2k_reorg_split_dimode
= 1;
5272 ip2k_reorg_split_simode
= 1;
5273 ip2k_reorg_split_himode
= 1;
5274 ip2k_reorg_split_qimode
= 1;
5275 ip2k_reorg_merge_qimode
= 1;
5277 /* All optimizations below must be debugged and enabled one by one.
5278 All of them commented now because of abort in GCC core. */
5280 ip2k_reorg_in_progress
= 1;
5282 first_insn
= get_insns ();
5284 /* Look for size effects of earlier optimizations - in particular look for
5285 situations where we're saying "use" a register on one hand but immediately
5286 tagging it as "REG_DEAD" at the same time! Seems like a bug in core-gcc
5287 somewhere really but this is what we have to live with! */
5288 for (insn
= first_insn
; insn
; insn
= NEXT_INSN (insn
))
5292 if (GET_CODE (insn
) == CODE_LABEL
5293 || GET_CODE (insn
) == NOTE
5294 || GET_CODE (insn
) == BARRIER
)
5300 body
= PATTERN (insn
);
5301 if (GET_CODE (body
) == USE
)
5302 if (GET_CODE (XEXP (body
, 0)) == REG
)
5306 reg
= REGNO (XEXP (body
, 0));
5307 if (find_regno_note (insn
, REG_DEAD
, reg
))
5314 /* There's a good chance that since we last did CSE that we've rearranged
5315 things in such a way that another go will win. Do so now! */
5316 reload_cse_regs (first_insn
);
5317 find_basic_blocks (first_insn
, max_reg_num (), 0);
5318 life_analysis (0, PROP_REG_INFO
| PROP_DEATH_NOTES
);
5320 /* Look for where absurd things are happening with DP. */
5321 mdr_try_dp_reload_elim (first_insn
);
5323 ip2k_reorg_in_progress
= 0;
5324 ip2k_reorg_completed
= 1;
5326 split_all_insns (0);
5328 reload_cse_regs (first_insn
);
5329 find_basic_blocks (first_insn
, max_reg_num (), 0);
5330 life_analysis (0, PROP_REG_INFO
| PROP_DEATH_NOTES
);
5332 peephole2_optimize (NULL
);
5334 mdr_resequence_xy_yx (first_insn
);
5335 mdr_propagate_reg_equivs (first_insn
);
5337 /* Look for redundant set instructions. These can occur when we split
5338 instruction patterns and end up with the second half merging with
5339 or being replaced by something that clobbers the first half. */
5340 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
5342 if (GET_CODE (insn
) == INSN
)
5344 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
5345 if ((set
!= NULL_RTX
)
5346 && (GET_CODE (XEXP (set
, 0)) == REG
)
5347 && (GET_MODE (XEXP (set
, 0)) == QImode
)
5348 && (find_regno_note (insn
, REG_UNUSED
, REGNO (XEXP (set
, 0)))))
5353 mdr_try_move_dp_reload (first_insn
);
5354 mdr_try_move_pushes (first_insn
);
5356 find_basic_blocks (first_insn
, max_reg_num (), 0);
5357 life_analysis (0, PROP_FINAL
);
5359 mdr_try_propagate_move (first_insn
);
5360 mdr_resequence_xy_yx (first_insn
);
5362 ip2k_reorg_split_dimode
= 1;
5363 split_all_insns (0);
5365 mdr_try_remove_redundant_insns (first_insn
);
5367 mdr_try_propagate_move (first_insn
);
5369 reload_cse_regs (first_insn
);
5370 find_basic_blocks (first_insn
, max_reg_num (), 0);
5371 life_analysis (0, PROP_FINAL
);
5373 peephole2_optimize (NULL
);
5375 mdr_try_propagate_move (first_insn
);
5377 find_basic_blocks (first_insn
, max_reg_num (), 0);
5378 life_analysis (0, PROP_FINAL
);
5380 ip2k_reorg_split_simode
= 1;
5381 split_all_insns (0);
5383 mdr_try_remove_redundant_insns (first_insn
);
5385 mdr_try_propagate_move (first_insn
);
5387 reload_cse_regs (first_insn
);
5388 find_basic_blocks (first_insn
, max_reg_num (), 0);
5389 life_analysis (0, PROP_FINAL
);
5391 peephole2_optimize (NULL
);
5393 mdr_try_propagate_move (first_insn
);
5395 find_basic_blocks (first_insn
, max_reg_num (), 0);
5396 life_analysis (0, PROP_FINAL
);
5398 ip2k_reorg_split_himode
= 1;
5399 ip2k_reorg_merge_qimode
= 1;
5400 split_all_insns (0);
5402 mdr_try_remove_redundant_insns (first_insn
);
5403 mdr_try_propagate_clr (first_insn
);
5404 mdr_try_propagate_move (first_insn
);
5406 mdr_try_dp_reload_elim (first_insn
);
5407 mdr_try_move_dp_reload (first_insn
);
5409 rebuild_jump_labels (first_insn
);
5411 /* Call to jump_optimize (...) was here, but now I removed it. */
5413 find_basic_blocks (first_insn
, max_reg_num (), 0);
5414 life_analysis (0, PROP_FINAL
);
5416 peephole2_optimize (NULL
);
5418 mdr_try_propagate_move (first_insn
);
5420 find_basic_blocks (first_insn
, max_reg_num (), 0);
5421 life_analysis (0, PROP_FINAL
);
5422 mdr_try_remove_redundant_insns (first_insn
);
5424 mdr_try_propagate_clr (first_insn
);
5425 mdr_try_propagate_move (first_insn
);
5427 find_basic_blocks (first_insn
, max_reg_num (), 0);
5428 life_analysis (0, PROP_FINAL
);
5430 ip2k_reorg_split_qimode
= 1;
5431 split_all_insns (0);
5433 mdr_try_wreg_elim (first_insn
);
5434 mdr_try_propagate_move (first_insn
);
5436 find_basic_blocks (first_insn
, max_reg_num (), 0);
5437 life_analysis (0, PROP_FINAL
);
5442 ip2k_init_libfuncs (void)
5444 set_optab_libfunc (smul_optab
, SImode
, "_mulsi3");
5445 set_optab_libfunc (smul_optab
, DImode
, "_muldi3");
5446 set_optab_libfunc (cmp_optab
, HImode
, "_cmphi2");
5447 set_optab_libfunc (cmp_optab
, SImode
, "_cmpsi2");
5450 /* Returns a bit position if mask contains only a single bit. Returns -1 if
5451 there were zero or more than one set bits. */
5453 find_one_set_bit_p (HOST_WIDE_INT mask
)
5456 unsigned HOST_WIDE_INT n
= mask
;
5457 for (i
= 0; i
< 32; i
++)
5459 if (n
& 0x80000000UL
)
5461 if (n
& 0x7fffffffUL
)
5471 /* Returns a bit position if mask contains only a single clear bit.
5472 Returns -1 if there were zero or more than one clear bits. */
5474 find_one_clear_bit_p (HOST_WIDE_INT mask
)
5477 unsigned HOST_WIDE_INT n
= mask
;
5478 for (i
= 0; i
< 32; i
++)
5480 if ((n
& 0x80000000UL
) == 0UL)
5482 if ((n
& 0x7fffffffUL
) != 0x7fffffffUL
)
5494 /* Split a move into two smaller pieces.
5495 MODE indicates the reduced mode. OPERANDS[0] is the original destination
5496 OPERANDS[1] is the original src. The new destinations are
5497 OPERANDS[2] and OPERANDS[4], while the new sources are OPERANDS[3]
5501 ip2k_split_words (enum machine_mode nmode
, enum machine_mode omode
,
5504 rtx dl
, dh
; /* src/dest pieces. */
5506 int move_high_first
= 0; /* Assume no overlap. */
5509 switch (GET_CODE (operands
[0])) /* DEST */
5513 if ((GET_CODE (operands
[1]) == REG
5514 || GET_CODE (operands
[1]) == SUBREG
)
5515 && (true_regnum (operands
[0]) <= true_regnum (operands
[1])
5516 || (true_regnum (operands
[1])
5517 + GET_MODE_SIZE (omode
) - 1 < true_regnum (operands
[0]))))
5518 move_high_first
= 1;
5520 if (GET_CODE (operands
[0]) == SUBREG
)
5522 dl
= simplify_gen_subreg (nmode
, operands
[0], omode
,
5523 GET_MODE_SIZE (nmode
));
5524 dh
= simplify_gen_subreg (nmode
, operands
[0], omode
, 0);
5526 else if (GET_CODE (operands
[0]) == REG
&& ! IS_PSEUDO_P (operands
[0]))
5528 int r
= REGNO (operands
[0]);
5529 dh
= gen_rtx_REG (nmode
, r
);
5530 dl
= gen_rtx_REG (nmode
, r
+ HARD_REGNO_NREGS (r
, nmode
));
5534 dh
= gen_rtx_SUBREG (nmode
, operands
[0], 0);
5535 dl
= gen_rtx_SUBREG (nmode
, operands
[0], GET_MODE_SIZE (nmode
));
5540 switch (GET_CODE (XEXP (operands
[0], 0)))
5545 dl
= dh
= gen_rtx_MEM (nmode
, XEXP (operands
[0], 0));
5549 dl
= change_address (operands
[0], nmode
,
5550 plus_constant (XEXP (operands
[0], 0),
5551 GET_MODE_SIZE (nmode
)));
5552 dh
= gen_rtx_MEM (nmode
, XEXP (operands
[0], 0));
5559 switch (GET_CODE (operands
[1]))
5562 if (! IS_PSEUDO_P (operands
[1]))
5564 int r
= REGNO (operands
[1]);
5566 sh
= gen_rtx_REG (nmode
, r
);
5567 sl
= gen_rtx_REG (nmode
, r
+ HARD_REGNO_NREGS (r
, nmode
));
5571 sh
= gen_rtx_SUBREG (nmode
, operands
[1], 0);
5572 sl
= gen_rtx_SUBREG (nmode
, operands
[1], GET_MODE_SIZE (nmode
));
5577 if (operands
[1] == const0_rtx
)
5578 sh
= sl
= const0_rtx
;
5581 if (GET_MODE (operands
[0]) != DImode
)
5586 REAL_VALUE_FROM_CONST_DOUBLE (rv
, operands
[1]);
5587 REAL_VALUE_TO_TARGET_SINGLE (rv
, value
);
5589 sh
= gen_int_mode ((value
>> 16) & 0xffff, nmode
);
5590 sl
= gen_int_mode (value
& 0xffff, nmode
);
5594 sh
= gen_int_mode (CONST_DOUBLE_HIGH (operands
[1]), nmode
);
5595 sl
= gen_int_mode (CONST_DOUBLE_LOW (operands
[1]), nmode
);
5601 if (operands
[1] == const0_rtx
)
5602 sh
= sl
= const0_rtx
;
5605 int val
= INTVAL (operands
[1]);
5611 vh
= (val
>> 8) & 0xff;
5616 vh
= (val
>> 16) & 0xffff;
5621 if (val
< 0) /* sign extend */
5625 vl
= val
; /* Give low 32 bits back. */
5632 sl
= gen_int_mode (vl
, nmode
);
5633 sh
= gen_int_mode (vh
, nmode
);
5638 sl
= simplify_gen_subreg (nmode
, operands
[1], omode
,
5639 GET_MODE_SIZE (nmode
));
5640 sh
= simplify_gen_subreg (nmode
, operands
[1], omode
, 0);
5644 switch (GET_CODE (XEXP (operands
[1], 0)))
5652 /* Worry about splitting stack pushes. */
5653 if (pushflag
&& ip2k_address_uses_reg_p (operands
[1], REG_SP
))
5654 sl
= sh
= change_address (operands
[1], nmode
,
5655 plus_constant (XEXP (operands
[1], 0),
5656 GET_MODE_SIZE (nmode
)));
5659 sl
= change_address (operands
[1], nmode
,
5660 plus_constant (XEXP (operands
[1], 0),
5661 GET_MODE_SIZE (nmode
)));
5662 sh
= gen_rtx_MEM (nmode
, XEXP (operands
[1], 0));
5671 if (move_high_first
)
5688 /* Get the low half of an operand. */
5690 ip2k_get_low_half (rtx x
, enum machine_mode mode
)
5692 switch (GET_CODE (x
))
5695 if (! IS_PSEUDO_P (x
))
5697 unsigned int r
= REGNO (x
);
5699 return gen_rtx_REG (mode
, r
+ HARD_REGNO_NREGS (r
, mode
));
5703 return gen_rtx_SUBREG (mode
, x
, GET_MODE_SIZE (mode
));
5708 if (x
== const0_rtx
)
5717 REAL_VALUE_FROM_CONST_DOUBLE (rv
, x
);
5718 REAL_VALUE_TO_TARGET_SINGLE (rv
, value
);
5720 return gen_int_mode (value
& 0xffff, mode
);
5723 return gen_int_mode (CONST_DOUBLE_LOW (x
), mode
);
5728 if (x
== const0_rtx
)
5732 int val
= INTVAL (x
);
5738 vh
= (val
>> 8) & 0xff;
5743 vh
= (val
>> 16) & 0xffff;
5748 if (val
< 0) /* sign extend */
5752 vl
= val
; /* Give low 32 bits back. */
5759 return gen_int_mode (vl
, mode
);
5764 return simplify_gen_subreg (mode
, x
, GET_MODE (x
), GET_MODE_SIZE (mode
));
5767 switch (GET_CODE (XEXP (x
, 0)))
5775 return change_address (x
, mode
,
5776 plus_constant (XEXP (x
, 0),
5777 GET_MODE_SIZE (mode
)));
5787 /* Get the high half of an operand. */
5789 ip2k_get_high_half (rtx x
, enum machine_mode mode
)
5791 switch (GET_CODE (x
))
5794 if (! IS_PSEUDO_P (x
))
5796 unsigned int r
= REGNO (x
);
5798 return gen_rtx_REG (mode
, r
);
5802 return gen_rtx_SUBREG (mode
, x
, 0);
5807 if (x
== const0_rtx
)
5816 REAL_VALUE_FROM_CONST_DOUBLE (rv
, x
);
5817 REAL_VALUE_TO_TARGET_SINGLE (rv
, value
);
5819 return gen_int_mode ((value
>> 16) & 0xffff, mode
);
5822 return gen_int_mode (CONST_DOUBLE_HIGH (x
), mode
);
5827 if (x
== const0_rtx
)
5831 int val
= INTVAL (x
);
5837 vh
= (val
>> 8) & 0xff;
5842 vh
= (val
>> 16) & 0xffff;
5847 if (val
< 0) /* sign extend */
5851 vl
= val
; /* Give low 32 bits back. */
5858 return gen_int_mode (vh
, mode
);
5863 return simplify_gen_subreg (mode
, x
, GET_MODE (x
), 0);
5867 switch (GET_CODE (XEXP (x
, 0)))
5875 return change_address (x
, mode
, plus_constant (XEXP (x
, 0), 0));
5885 /* Does address X use register R. Only valid for REG_SP, REG_DP, REG_IP
5889 ip2k_address_uses_reg_p (rtx x
, unsigned int r
)
5891 if (GET_CODE (x
) != MEM
)
5897 switch (GET_CODE (x
))
5907 if (ip2k_address_uses_reg_p (XEXP (x
, 1), r
))
5914 /* Ignore subwords. */
5919 /* Have to consider that r might be LSB of a pointer reg. */
5920 return ((REGNO (x
) == r
) || (REGNO (x
) == (r
- 1))) ? 1 : 0;
5923 /* We might be looking at a (mem:BLK (mem (...))) */
5932 /* Does the queried XEXP not use a particular register? If we're certain
5933 that it doesn't then we return TRUE otherwise we assume FALSE. */
5936 ip2k_xexp_not_uses_reg_p (rtx x
, unsigned int r
, int rsz
)
5938 switch (GET_CODE (x
))
5942 int msz
= GET_MODE_SIZE (GET_MODE (x
));
5944 return (((REGNO (x
) + msz
- 1) < r
)
5945 || (REGNO (x
) > (r
+ rsz
- 1)));
5949 return !ip2k_address_uses_reg_p (x
, r
);
5965 /* Does the queried XEXP not use a particular register? If we're certain
5966 that it doesn't then we return TRUE otherwise we assume FALSE. */
5969 ip2k_composite_xexp_not_uses_reg_p (rtx x
, unsigned int r
, int rsz
)
5971 if (GET_RTX_CLASS (GET_CODE (x
)) == RTX_BITFIELD_OPS
)
5972 return (ip2k_composite_xexp_not_uses_reg_p (XEXP (x
, 0), r
, rsz
)
5973 && ip2k_composite_xexp_not_uses_reg_p (XEXP (x
, 1), r
, rsz
)
5974 && ip2k_composite_xexp_not_uses_reg_p (XEXP (x
, 2), r
, rsz
));
5977 return (ip2k_composite_xexp_not_uses_reg_p (XEXP (x
, 0), r
, rsz
)
5978 && ip2k_composite_xexp_not_uses_reg_p (XEXP (x
, 1), r
, rsz
));
5981 || GET_RTX_CLASS (GET_CODE (x
)) == RTX_TERNARY
)
5982 return ip2k_composite_xexp_not_uses_reg_p (XEXP (x
, 0), r
, rsz
);
5984 return ip2k_xexp_not_uses_reg_p (x
, r
, rsz
);
5987 /* Does the queried XEXP not use CC0? If we're certain that
5988 it doesn't then we return TRUE otherwise we assume FALSE. */
5991 ip2k_composite_xexp_not_uses_cc0_p (rtx x
)
5993 if (GET_RTX_CLASS (GET_CODE (x
)) == RTX_BITFIELD_OPS
)
5994 return (ip2k_composite_xexp_not_uses_cc0_p (XEXP (x
, 0))
5995 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (x
, 1))
5996 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (x
, 2)));
5999 return (ip2k_composite_xexp_not_uses_cc0_p (XEXP (x
, 0))
6000 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (x
, 1)));
6003 || GET_RTX_CLASS (GET_CODE (x
)) == RTX_TERNARY
)
6004 return ip2k_composite_xexp_not_uses_cc0_p (XEXP (x
, 0));
6006 return GET_CODE (x
) != CC0
;
6010 ip2k_split_dest_operand (rtx x
, enum machine_mode mode
)
6012 return nonimmediate_operand (x
, mode
) || push_operand (x
, mode
);
6016 ip2k_nonptr_operand (rtx x
, enum machine_mode mode
)
6018 return register_operand (x
, mode
) && !ip2k_ptr_operand (x
, mode
);
6021 /* Is X a reference to IP or DP or SP? */
6024 ip2k_ptr_operand (rtx x
, enum machine_mode mode
)
6027 if (GET_CODE (x
) == SUBREG
)
6031 && (mode
== HImode
|| mode
== VOIDmode
)
6032 && (REGNO (x
) == REG_IP
6033 || REGNO (x
) == REG_DP
6034 || REGNO (x
) == REG_SP
));
6038 ip2k_sp_operand (rtx x
, enum machine_mode mode ATTRIBUTE_UNUSED
)
6041 return REG_P (x
) && REGNO (x
) == REG_SP
;
6045 ip2k_ip_operand (rtx x
, enum machine_mode mode
)
6048 if (GET_CODE (x
) != MEM
)
6053 if (GET_CODE (x
) == PLUS
&& XEXP (x
, 1) == const0_rtx
)
6059 if (GET_MODE_SIZE (mode
) > 1)
6060 return 0; /* Can't access offset bytes. */
6062 return REGNO (x
) == REG_IP
;
6065 /* Is X a memory address suitable for SP or DP relative addressing? */
6067 ip2k_short_operand (rtx x
, enum machine_mode mode
)
6070 unsigned int offs
= 0;
6072 if (! memory_operand (x
, mode
))
6073 return 0; /* Got to be a memory address. */
6076 switch (GET_CODE (x
))
6082 if (! REG_P (XEXP (x
, 0))
6083 || GET_CODE (XEXP (x
, 1)) != CONST_INT
)
6086 offs
= INTVAL (XEXP (x
, 1));
6096 if (IS_PSEUDO_P (x
))
6097 return 0; /* Optimistic - doesn't work. */
6101 /* For 'S' constraint, we presume that no IP adjustment
6102 simulation is performed - so only QI mode allows IP to be a
6103 short offset address. All other IP references must be
6104 handled by 'R' constraints. */
6105 if (r
== REG_IP
&& offs
== 0 && GET_MODE_SIZE (mode
) <= 1)
6108 return (r
== REG_SP
|| r
== REG_DP
);
6113 ip2k_nonsp_reg_operand (rtx x
, enum machine_mode mode ATTRIBUTE_UNUSED
)
6115 if (GET_CODE (x
) == SUBREG
)
6118 return (REG_P (x
) && REGNO (x
) != REG_SP
);
6122 ip2k_gen_operand (rtx x
, enum machine_mode mode
)
6124 return ip2k_short_operand (x
, mode
)
6125 || (GET_CODE (x
) == SUBREG
6126 && REG_P (SUBREG_REG (x
)))
6127 || (ip2k_nonsp_reg_operand (x
, mode
));
6131 ip2k_extra_constraint (rtx x
, int c
)
6135 case 'S': /* Allow offset in stack frame... */
6136 return ip2k_short_operand (x
, GET_MODE (x
));
6139 return ip2k_ip_operand (x
, GET_MODE (x
));
6141 case 'T': /* Constant int or .data address. */
6142 return CONSTANT_P (x
) && is_regfile_address (x
);
6150 ip2k_unary_operator (rtx op
, enum machine_mode mode
)
6152 return ((mode
== VOIDmode
|| GET_MODE (op
) == mode
)
6157 ip2k_binary_operator (rtx op
, enum machine_mode mode
)
6159 return ((mode
== VOIDmode
|| GET_MODE (op
) == mode
)
6160 && ARITHMETIC_P (op
));
6164 ip2k_symbol_ref_operand (rtx op
, enum machine_mode mode ATTRIBUTE_UNUSED
)
6166 /* We define an IP2k symbol ref to be either a direct reference or one
6167 with a constant offset. */
6168 return (GET_CODE (op
) == SYMBOL_REF
)
6169 || (GET_CODE (op
) == CONST
6170 && GET_CODE (XEXP (op
, 0)) == PLUS
6171 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == SYMBOL_REF
);
6175 ip2k_signed_comparison_operator (rtx op
, enum machine_mode mode
)
6177 return (comparison_operator (op
, mode
)
6178 && signed_condition (GET_CODE (op
)) == GET_CODE (op
));
6182 ip2k_unsigned_comparison_operator (rtx op
, enum machine_mode mode
)
6184 return (comparison_operator (op
, mode
)
6185 && unsigned_condition (GET_CODE (op
)) == GET_CODE (op
));
6188 /* Worker function for TARGET_RETURN_IN_MEMORY. */
6191 ip2k_return_in_memory (tree type
, tree fntype ATTRIBUTE_UNUSED
)
6193 if (TYPE_MODE (type
) == BLKmode
)
6195 HOST_WIDE_INT size
= int_size_in_bytes (type
);
6196 return (size
== -1 || size
> 8);
6202 /* Worker function for TARGET_SETUP_INCOMING_VARARGS. */
6205 ip2k_setup_incoming_varargs (CUMULATIVE_ARGS
*ca ATTRIBUTE_UNUSED
,
6206 enum machine_mode mode ATTRIBUTE_UNUSED
,
6207 tree type ATTRIBUTE_UNUSED
,
6208 int *pretend_arg_size
,
6209 int second_time ATTRIBUTE_UNUSED
)
6211 *pretend_arg_size
= 0;