1 /* Subroutines used for code generation on Ubicom IP2022
2 Communications Controller.
3 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
4 Free Software Foundation, Inc.
5 Contributed by Red Hat, Inc and Ubicom, Inc.
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
14 GCC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING. If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
26 #include "coretypes.h"
30 #include "hard-reg-set.h"
32 #include "insn-config.h"
33 #include "conditions.h"
34 #include "insn-flags.h"
36 #include "insn-attr.h"
37 #include "insn-addr.h"
49 #include "target-def.h"
50 #include "basic-block.h"
52 /* There are problems with 'frame_pointer_needed'. If we force it
53 on, we either end up not eliminating uses of FP, which results in
54 SPILL register failures or we may end up with calculation errors in
55 the stack offsets. Isolate the decision process into a simple macro. */
56 #define CHAIN_FRAMES (frame_pointer_needed || FRAME_POINTER_REQUIRED)
58 static int ip2k_naked_function_p (tree
);
59 #ifdef IP2K_MD_REORG_PASS
60 static void mdr_resequence_xy_yx (rtx
);
61 static void mdr_pres_replace_and_recurse (rtx
, rtx
, rtx
);
62 static void mdr_propagate_reg_equivs_sequence (rtx
, rtx
, rtx
);
63 static void mdr_propagate_reg_equivs (rtx
);
64 static int track_dp_reload (rtx
, rtx
*, int , int);
65 static void mdr_try_dp_reload_elim (rtx
);
66 static void mdr_try_move_dp_reload (rtx
);
67 static void mdr_try_move_pushes (rtx
);
68 static void mdr_try_propagate_clr_sequence (rtx
, unsigned int);
69 static void mdr_try_propagate_clr (rtx
);
70 static void mdr_try_propagate_move_sequence (rtx
, rtx
, rtx
);
71 static void mdr_try_propagate_move (rtx
);
72 static void mdr_try_remove_redundant_insns (rtx
);
73 static int track_w_reload (rtx
, rtx
*, int , int);
74 static void mdr_try_wreg_elim (rtx
);
75 #endif /* IP2K_MD_REORG_PASS */
76 static void ip2k_reorg (void);
77 static int ip2k_check_can_adjust_stack_ref (rtx
, int);
78 static void ip2k_adjust_stack_ref (rtx
*, int);
79 static int ip2k_xexp_not_uses_reg_for_mem (rtx
, unsigned int);
80 static tree
ip2k_handle_progmem_attribute (tree
*, tree
, tree
, int, bool *);
81 static tree
ip2k_handle_fndecl_attribute (tree
*, tree
, tree
, int, bool *);
82 static bool ip2k_rtx_costs (rtx
, int, int, int *);
83 static int ip2k_address_cost (rtx
);
84 static void ip2k_init_libfuncs (void);
85 static bool ip2k_return_in_memory (tree
, tree
);
86 static void ip2k_setup_incoming_varargs (CUMULATIVE_ARGS
*, enum machine_mode
,
89 const struct attribute_spec ip2k_attribute_table
[];
92 /* Initialize the GCC target structure. */
93 #undef TARGET_ASM_ALIGNED_HI_OP
94 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
96 #undef TARGET_ASM_FUNCTION_PROLOGUE
97 #define TARGET_ASM_FUNCTION_PROLOGUE function_prologue
99 #undef TARGET_ASM_FUNCTION_EPILOGUE
100 #define TARGET_ASM_FUNCTION_EPILOGUE function_epilogue
102 #undef TARGET_ASM_UNIQUE_SECTION
103 #define TARGET_ASM_UNIQUE_SECTION unique_section
105 #undef TARGET_ASM_FUNCTION_RODATA_SECTION
106 #define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
108 #undef TARGET_ATTRIBUTE_TABLE
109 #define TARGET_ATTRIBUTE_TABLE ip2k_attribute_table
111 #undef TARGET_RTX_COSTS
112 #define TARGET_RTX_COSTS ip2k_rtx_costs
113 #undef TARGET_ADDRESS_COST
114 #define TARGET_ADDRESS_COST ip2k_address_cost
116 #undef TARGET_MACHINE_DEPENDENT_REORG
117 #define TARGET_MACHINE_DEPENDENT_REORG ip2k_reorg
119 #undef TARGET_INIT_LIBFUNCS
120 #define TARGET_INIT_LIBFUNCS ip2k_init_libfuncs
122 #undef TARGET_RETURN_IN_MEMORY
123 #define TARGET_RETURN_IN_MEMORY ip2k_return_in_memory
125 #undef TARGET_SETUP_INCOMING_VARARGS
126 #define TARGET_SETUP_INCOMING_VARARGS ip2k_setup_incoming_varargs
128 struct gcc_target targetm
= TARGET_INITIALIZER
;
130 /* Prologue/Epilogue size in words. */
131 static int prologue_size
;
132 static int epilogue_size
;
134 /* compare and test instructions for the IP2K are materialized by
135 the conditional branch that uses them. This is because conditional
136 branches are skips over unconditional branches. */
137 rtx ip2k_compare_operands
[3]; /* Additional operands for condition code. */
138 int ip2k_test_flag
; /* Indicates Z, WREG contain condition code
141 /* Some ip2k patterns push a byte onto the stack and then access
142 SP-relative addresses. Since reload doesn't know about these
143 pushes, we must track them internally with a %< (push) or %> (pop)
145 static int ip2k_stack_delta
;
147 /* Track if or how far our ip2k reorganization pass has run. */
148 int ip2k_reorg_in_progress
= 0;
149 int ip2k_reorg_completed
= 0;
150 int ip2k_reorg_split_dimode
= 0;
151 int ip2k_reorg_split_simode
= 0;
152 int ip2k_reorg_split_himode
= 0;
153 int ip2k_reorg_split_qimode
= 0;
154 int ip2k_reorg_merge_qimode
= 0;
156 /* Set up local allocation order. */
159 ip2k_init_local_alloc (int *rao
)
161 static const int alloc_order
[] = REG_ALLOC_ORDER
;
163 memcpy (rao
, alloc_order
, sizeof (alloc_order
));
166 /* Returns the number of bytes of arguments automatically
167 popped when returning from a subroutine call.
168 FUNDECL is the declaration node of the function (as a tree),
169 FUNTYPE is the data type of the function (as a tree),
170 or for a library call it is an identifier node for the subroutine name.
171 SIZE is the number of bytes of arguments passed on the stack. */
174 ip2k_return_pops_args (tree fundecl ATTRIBUTE_UNUSED
, tree funtype
, int size
)
176 if (TREE_CODE (funtype
) == IDENTIFIER_NODE
)
179 if (TYPE_ARG_TYPES (funtype
) == NULL_TREE
180 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype
))) == void_type_node
))
186 /* Return nonzero if FUNC is a naked function. */
189 ip2k_naked_function_p (tree func
)
193 if (TREE_CODE (func
) != FUNCTION_DECL
)
196 a
= lookup_attribute ("naked", DECL_ATTRIBUTES (func
));
197 return a
!= NULL_TREE
;
200 /* Output function prologue. */
202 function_prologue (FILE *file
, HOST_WIDE_INT size
)
209 prologue_size
= epilogue_size
= 0;
211 if (ip2k_naked_function_p (current_function_decl
))
213 fprintf (file
, "/* prologue: naked */\n");
217 leaf_func_p
= leaf_function_p ();
218 main_p
= MAIN_NAME_P (DECL_NAME (current_function_decl
));
220 /* For now, we compute all these facts about the function, but don't
221 take any action based on the information. */
224 fprintf (file
, "/* prologue: frame size=" HOST_WIDE_INT_PRINT_DEC
" */\n",
227 /* Unless we're a leaf we need to save the return PC. */
231 OUT_AS1 (push
, calll
);
232 OUT_AS1 (push
, callh
);
236 /* We need to save the old FP and set the new FP pointing at the
237 stack location where the old one is saved. Note that because of
238 post-decrement addressing, the SP is off-by-one after the
239 push, so we harvest the SP address BEFORE we push the MSBs of
243 OUT_AS1 (push
, REG_FP
+1); /* Save old LSBs. */
244 OUT_AS2 (mov
, w
, spl
);
245 OUT_AS2 (mov
, REG_FP
+1, w
); /* SPL -> FPL */
247 OUT_AS2 (mov
, w
, sph
); /* Freeze SP MSBs */
248 OUT_AS1 (push
, REG_FP
); /* Save old MSBs */
249 OUT_AS2 (mov
, REG_FP
, w
); /* SPH -> FPH */
253 for (reg
= (CHAIN_FRAMES
) ? (REG_FP
- 1) : (REG_FP
+ 1);
256 if (regs_ever_live
[reg
] && ! call_used_regs
[reg
])
258 fprintf (file
, "\t" AS1 (push
,%s
) "\n", reg_names
[reg
]);
265 operands
[0] = GEN_INT (size
);
276 OUT_AS2 (mov
, w
, %L0
);
277 OUT_AS2 (sub
, spl
, w
);
281 switch (size
& 0xff00)
290 if ((size
& 0xff) != ((size
>> 8) & 0xff))
291 OUT_AS2 (mov
, w
, %H0
); /* Otherwise W has value we want. */
292 OUT_AS2 (sub
, sph
, w
);
297 /* XXX - change this to use the carry-propagating subtract trick. */
298 if (flag_stack_check
)
300 OUT_AS2 (mov
, w
, sph
);
301 OUT_AS2 (cmp
, w
, #%%hi8data(_end));
302 OUT_AS1 (sc
, ); /* C == 0 -> hi8(edata) < sph */
305 OUT_AS1 (sz
, ); /* Z == 1 -> look at low byte */
307 OUT_AS1 (jmp
,0f
); /* sp < edata, so raise stack fault */
308 OUT_AS2 (mov
, w
, spl
);
309 OUT_AS2 (cmp
, w
, #%%lo8data(_end));
310 OUT_AS1 (sc
,); /* C==1 -> lo8(edata) >= spl */
314 output_asm_insn ("push\t$ff", operands
);
321 /* Output function epilogue. */
323 function_epilogue (FILE *file
, HOST_WIDE_INT size
)
327 rtx operands
[2]; /* Dummy used by OUT_ASn */
328 int args_locals_size
= current_function_args_size
;
329 int saved_regs_p
= 0;
332 /* Use this opportunity to reset the reorg flags! */
333 ip2k_reorg_in_progress
= 0;
334 ip2k_reorg_completed
= 0;
335 ip2k_reorg_split_dimode
= 0;
336 ip2k_reorg_split_simode
= 0;
337 ip2k_reorg_split_himode
= 0;
338 ip2k_reorg_split_qimode
= 0;
339 ip2k_reorg_merge_qimode
= 0;
341 if (ip2k_naked_function_p (current_function_decl
))
343 fprintf (file
, "/* epilogue: naked */\n");
347 leaf_func_p
= leaf_function_p ();
349 fprintf (file
, "/* epilogue: frame size=" HOST_WIDE_INT_PRINT_DEC
" */\n",
352 savelimit
= (CHAIN_FRAMES
) ? REG_FP
: (REG_FP
+ 2);
353 for (reg
= 0; reg
< savelimit
; reg
++)
354 if (regs_ever_live
[reg
] && ! call_used_regs
[reg
])
362 if (leaf_func_p
&& !CHAIN_FRAMES
&& !saved_regs_p
363 && current_function_pops_args
)
364 args_locals_size
= current_function_args_size
+ size
;
367 operands
[0] = GEN_INT (size
);
372 OUT_AS2 (mov
, w
, %L0
);
373 OUT_AS2 (add
, spl
, w
);
383 switch (size
& 0xff00)
386 if ((size
& 0xff) != ((size
>> 8) & 0xff))
387 OUT_AS2 (mov
, w
, %H0
);
388 OUT_AS2 (add
, sph
, w
);
400 for (reg
= 0; reg
< savelimit
; reg
++)
402 if (regs_ever_live
[reg
] && ! call_used_regs
[reg
])
404 fprintf (file
, "\t" AS1 (pop
,%s
) "\n", reg_names
[reg
]);
410 && ! (current_function_pops_args
411 && current_function_args_size
>= 2
412 && current_function_args_size
< 0x100))
414 OUT_AS1 (pop
, REG_FP
);
415 OUT_AS1 (pop
, REG_FP
+1);
421 if (current_function_pops_args
422 && current_function_args_size
>= 2
423 && current_function_args_size
< 0x100)
425 if (current_function_args_size
== 2)
429 OUT_AS1 (page
, __fp_pop2_args_ret
);
430 OUT_AS1 (jmp
, __fp_pop2_args_ret
);
434 OUT_AS1 (page
, __pop2_args_ret
);
435 OUT_AS1 (jmp
, __pop2_args_ret
);
441 operands
[0] = GEN_INT (current_function_args_size
);
442 OUT_AS2 (mov
, w
, %L0
);
445 OUT_AS1 (page
, __fp_pop_args_ret
);
446 OUT_AS1 (jmp
, __fp_pop_args_ret
);
450 OUT_AS1 (page
, __pop_args_ret
);
451 OUT_AS1 (jmp
, __pop_args_ret
);
459 OUT_AS1 (pop
, callh
);
460 OUT_AS1 (pop
, calll
);
466 if (current_function_pops_args
467 && args_locals_size
>= 2
468 && args_locals_size
< 0x100)
470 if (args_locals_size
== 2)
474 OUT_AS1 (page
, __leaf_fp_pop2_args_ret
);
475 OUT_AS1 (jmp
, __leaf_fp_pop2_args_ret
);
482 operands
[0] = GEN_INT (args_locals_size
);
485 OUT_AS2 (mov
, w
, %L0
);
486 OUT_AS1 (page
, __leaf_fp_pop_args_ret
);
487 OUT_AS1 (jmp
, __leaf_fp_pop_args_ret
);
495 if (current_function_pops_args
&& args_locals_size
&& need_ret
)
497 operands
[0] = GEN_INT (args_locals_size
);
499 switch (args_locals_size
& 0xff)
502 OUT_AS2 (mov
, w
, %L0
);
503 OUT_AS2 (add
, spl
, w
);
515 switch (args_locals_size
& 0xff00)
518 if ((args_locals_size
& 0xff) != ((args_locals_size
>> 8) & 0xff))
519 OUT_AS2 (mov
, w
, %H0
);
520 OUT_AS2 (add
, sph
, w
);
539 fprintf (file
, "/* epilogue end (size=%d) */\n", epilogue_size
);
542 /* Return the difference between the registers after the function
545 Stack Frame grows down:
548 <------ AP ($102:$103)
549 RETURN PC (unless leaf function)
551 <------ FP [HARD_FRAME_POINTER] ($FD:$FE)
553 <------ VFP [$100:$101]
555 <------ SP ($6:$7) */
557 ip2k_init_elim_offset (int from
, int to
)
559 int leaf_func_p
= leaf_function_p ();
560 int no_saved_pc
= leaf_func_p
561 || ip2k_naked_function_p (current_function_decl
);
566 if (from
== FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
567 return get_frame_size () + 1;
569 if (from
== ARG_POINTER_REGNUM
&& to
== HARD_FRAME_POINTER_REGNUM
)
570 return (CHAIN_FRAMES
? 2 : 0) + (no_saved_pc
? 0 : 2);
572 /* Count all the registers we had to preserve. */
574 reglimit
= CHAIN_FRAMES
? REG_FP
: (REG_FP
+ 2);
575 for (offset
= 0,reg
= 0; reg
< reglimit
; ++reg
)
577 if ((regs_ever_live
[reg
] && ! call_used_regs
[reg
]))
583 if (from
== FRAME_POINTER_REGNUM
&& to
== HARD_FRAME_POINTER_REGNUM
)
586 if (from
== HARD_FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
587 /* Add in the stack-local variables. */
588 return offset
+ get_frame_size () + 1;
590 if (from
== ARG_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
591 /* Add stack-locals plus saved FP and PC. */
592 return offset
+ get_frame_size () + 1
593 + (CHAIN_FRAMES
? 2 : 0) + (no_saved_pc
? 0 : 2);
595 abort (); /* Unanticipated elimination. */
598 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
599 machine for a memory operand of mode MODE. */
602 legitimate_address_p (enum machine_mode mode
, rtx x
, int strict
)
606 if (GET_CODE (x
) == SUBREG
)
609 switch (GET_CODE (x
))
612 /* IP allows indirection without offset - only okay if
613 we don't require access to multiple bytes. */
614 if (REGNO (x
) == REG_IP
)
615 return (GET_MODE_SIZE (mode
) == 1) ? 'R' : 0;
617 /* We can indirect through DP or SP register. */
618 if (strict
? REG_OK_FOR_BASE_STRICT_P (x
)
619 : REG_OK_FOR_BASE_NOSTRICT_P (x
))
624 /* Offsets from DP or SP are legal in the range 0..127 */
631 if (REG_P (op2
) && ! REG_P (op1
))
638 /* Don't let anything but R+I through.. */
641 || GET_CODE (op2
) != CONST_INT
)
646 case REG_DP
: /* only 0..127 displacement */
648 off
= 2 * GET_MODE_SIZE (mode
);
652 if (INTVAL (op2
) < 0 || INTVAL (op2
) > (128 - off
))
653 return 0; /* Positive must be small enough that after
654 splitting all pieces are addressed. */
655 return 'S'; /* Safe displacement. */
658 if (GET_MODE_SIZE (mode
) <= 1 && INTVAL (op2
) == 0)
659 return (GET_MODE_SIZE (mode
) == 1) ? 'R' : 0;
666 if (strict
|| ! REG_OK_FOR_BASE_NOSTRICT_P (op1
))
667 return 0; /* Allow until reload. */
676 /* We always allow references to things in code space. */
677 return is_regfile_address (x
) ? 0 : 'C';
689 /* Is ADDR mode dependent? */
691 ip2k_mode_dependent_address (rtx addr
)
693 switch (GET_CODE (addr
))
702 return (REGNO (addr
) == REG_IP
); /* Can't do IP displaced addresses. */
705 return 0; /* Assume no dependency. */
709 /* Attempts to replace X with a valid
710 memory address for an operand of mode MODE. */
713 legitimize_address (rtx x
, rtx oldx ATTRIBUTE_UNUSED
,
714 enum machine_mode mode ATTRIBUTE_UNUSED
, rtx scratch
)
718 /* You might think that we could split up a symbolic address by
719 adding the HIGH 8 bits and doing a displacement off the dp. But
720 because we only have 7 bits of offset, that doesn't actually
721 help. So only constant displacements are likely to obtain an
724 if (GET_CODE (x
) == PLUS
&& REG_P (XEXP (x
, 0))
725 && GET_CODE (XEXP (x
, 1)) == CONST_INT
726 && ! CONST_OK_FOR_LETTER_P (INTVAL (XEXP (x
, 1)), 'K'))
728 int offset
= INTVAL (XEXP (x
, 1));
730 reg
= scratch
? scratch
: gen_reg_rtx (Pmode
);
732 emit_insn (gen_rtx_SET (VOIDmode
, reg
,
733 gen_rtx_PLUS (Pmode
, XEXP (x
, 0),
734 GEN_INT (offset
& 0xffc0))));
735 x
= gen_rtx_PLUS (Pmode
, reg
, GEN_INT (offset
& 0x3f));
738 return x
; /* We don't have any other tricks. */
741 /* Determine if X is a 'data' address or a code address. All static
742 data and stack variables reside in data memory. Only code is believed
743 to be in PRAM or FLASH. */
745 is_regfile_address (rtx x
)
748 switch (GET_CODE (x
))
751 return ! SYMBOL_REF_FUNCTION_P (x
); /* Declared as function. */
769 /* Output ADDR to FILE as address. */
772 print_operand_address (FILE *file
, rtx addr
)
774 switch (GET_CODE (addr
))
777 addr
= alter_subreg (&addr
);
781 fprintf (file
, "(%s)",
782 REGNO (addr
) == REG_DP
? "DP"
783 : REGNO (addr
) == REG_SP
? "SP"
784 : REGNO (addr
) == REG_IP
? "IP"
785 : REGNO (addr
) == REG_VFP
? "VFP" /* Should never see this */
786 : REGNO (addr
) == REG_AP
? "AP" /* or this, either. */
787 : reg_names
[REGNO (addr
)]);
796 addr
= XEXP (addr
, 0);
797 print_operand_address (file
, XEXP (addr
, 0));
799 print_operand_address (file
, XEXP (addr
, 1));
803 if (is_regfile_address (XEXP (addr
, 1)))
804 fprintf (file
, "%%lo8data(");
806 fprintf (file
, "%%lo8insn(");
807 print_operand_address (file
, XEXP (addr
, 1));
809 print_operand_address (file
, XEXP (addr
, 0));
812 case PLUS
: /* Ought to be stack or dp references. */
813 if (XEXP (addr
, 1) == const0_rtx
814 && GET_CODE (XEXP (addr
, 0)) == PLUS
)
816 print_operand_address (file
, XEXP (addr
, 0));
820 if (! REG_P (XEXP (addr
, 0)) || REGNO (XEXP (addr
, 0)) != REG_IP
)
821 print_operand_address (file
, XEXP (addr
, 1)); /* const */
822 print_operand_address (file
, XEXP (addr
, 0)); /* (reg) */
826 if (is_regfile_address (XEXP (addr
, 0)))
827 fprintf (file
, "%%hi8data(");
829 fprintf (file
, "%%hi8insn(");
830 output_addr_const (file
, XEXP (addr
, 0));
835 output_addr_const (file
, addr
);
840 /* Output X as assembler operand to file FILE. */
843 print_operand (FILE *file
, rtx x
, int code
)
887 if (ip2k_short_operand (x
, GET_MODE (x
))
888 && ip2k_address_uses_reg_p (x
, REG_SP
))
889 /* An SP-relative address needs to account for interior stack
890 pushes that reload didn't know about when it calculated the
892 abcd
+= ip2k_stack_delta
;
894 switch (GET_CODE (x
))
897 x
= alter_subreg (&x
);
901 fprintf (file
, reg_names
[true_regnum (x
) + abcd
]);
908 fprintf (file
, "$%x", (int)(INTVAL (x
) & 0xffff));
912 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
)); /* bit selector */
915 case 'e': /* "1 << n" - e.g. "exp" */
916 fprintf (file
, "#%d", 1 << INTVAL (x
));
924 value
>>= 8 * (3 - abcd
);
927 fprintf (file
, "#%ld", value
);
931 fprintf (file
, "#%d", (int)((INTVAL (x
) >> 8) & 0xff));
935 fprintf (file
, "#%d", (int)(INTVAL (x
) & 0xff));
946 value
= ((unsigned long long)INTVAL (x
)) >> (8 * (7 - abcd
)) & 0xff;
947 fprintf (file
, "#%ld", value
);
951 fprintf (file
, "#" HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
));
973 abort (); /* Probably an error. */
977 fprintf (file
, "#%s(",
978 is_regfile_address (x
) ? "%hi8data"
980 print_operand_address (file
, x
);
985 fprintf (file
, "#%s(",
986 is_regfile_address (x
) ? "%lo8data"
988 print_operand_address (file
, x
);
993 print_operand_address (file
, x
);
999 rtx addr
= XEXP (x
, 0);
1001 if (GET_CODE (addr
) == SUBREG
)
1002 addr
= alter_subreg (&x
);
1004 if (CONSTANT_P (addr
) && abcd
)
1007 print_operand_address (file
, addr
);
1008 fprintf (file
, ")+%d", abcd
);
1012 switch (GET_CODE (addr
))
1015 abcd
+= INTVAL (XEXP (addr
, 1));
1017 /* Worry about (plus (plus (reg DP) (const_int 10))
1019 if (GET_CODE (XEXP (addr
, 0)) == PLUS
)
1021 addr
= XEXP (addr
, 0);
1022 abcd
+= INTVAL (XEXP (addr
, 1));
1025 fprintf (file
, "%d", abcd
);
1026 print_operand_address (file
, XEXP (addr
, 0));
1031 fprintf (file
, "%d", abcd
);
1032 print_operand_address (file
, addr
);
1035 else if (GET_CODE (addr
) == REG
1036 && (REGNO (addr
) == REG_DP
|| REGNO (addr
) == REG_SP
))
1038 fprintf (file
, "0");
1039 print_operand_address (file
, addr
);
1042 print_operand_address (file
, addr
);
1047 /* Is this an integer or a floating point value? */
1048 if (GET_MODE (x
) == VOIDmode
)
1056 value
= CONST_DOUBLE_HIGH (x
);
1057 value
>>= 8 * (3 - abcd
);
1060 fprintf (file
, "#%ld", value
);
1067 value
= CONST_DOUBLE_LOW (x
);
1068 value
>>= 8 * (7 - abcd
);
1071 fprintf (file
, "#%ld", value
);
1080 REAL_VALUE_FROM_CONST_DOUBLE (rv
, x
);
1081 REAL_VALUE_TO_TARGET_SINGLE (rv
, value
);
1082 fprintf (file
, "0x%lx", value
);
1087 fatal_insn ("bad operand", x
);
1091 /* Remember the operands for the compare. */
1093 ip2k_set_compare (rtx x
, rtx y
)
1095 ip2k_compare_operands
[0] = x
;
1096 ip2k_compare_operands
[1] = y
;
1100 /* Emit the code for sCOND instructions. */
1102 ip2k_gen_sCOND (rtx insn ATTRIBUTE_UNUSED
, enum rtx_code code
, rtx dest
)
1104 #define operands ip2k_compare_operands
1105 enum machine_mode mode
;
1109 mode
= GET_MODE (operands
[0]);
1110 if ((mode
!= QImode
) && (mode
!= HImode
)
1111 && (mode
!= SImode
) && (mode
!= DImode
))
1112 mode
= GET_MODE (operands
[1]);
1114 /* We have a fast path for a specific type of QImode compare. We ought
1115 to extend this for larger cases too but that wins less frequently and
1116 introduces a lot of complexity. */
1118 && !rtx_equal_p (operands
[0], operands
[2])
1119 && !rtx_equal_p (operands
[1], operands
[2])
1120 && (! REG_P (operands
[2])
1121 || (ip2k_xexp_not_uses_reg_p (operands
[0], REGNO (operands
[2]), 1)
1122 && ip2k_xexp_not_uses_reg_p (operands
[1],
1123 REGNO (operands
[2]), 1))))
1126 if (immediate_operand (operands
[1], QImode
)
1127 && ((INTVAL (operands
[1]) & 0xff) == 0xff))
1130 OUT_AS2 (incsnz
, w
, %0);
1132 OUT_AS2 (incsz
, w
, %0);
1134 else if (immediate_operand (operands
[1], QImode
)
1135 && ((INTVAL (operands
[1]) & 0xff) == 0x01))
1138 OUT_AS2 (decsnz
, w
, %0);
1140 OUT_AS2 (decsz
, w
, %0);
1142 else if (ip2k_compare_operands
[1] == const0_rtx
)
1144 OUT_AS2 (mov
, w
, %0);
1152 OUT_AS2 (mov
, w
, %0);
1154 OUT_AS2 (csne
, w
, %1);
1156 OUT_AS2 (cse
, w
, %1);
1162 if (ip2k_compare_operands
[1] == const0_rtx
)
1167 OUT_AS2 (mov
, w
, %0);
1171 OUT_AS2 (mov
, w
, %H0
);
1172 OUT_AS2 (or, w
, %L0
);
1176 OUT_AS2 (mov
, w
, %A0
);
1177 OUT_AS2 (or, w
, %B0
);
1178 OUT_AS2 (or, w
, %C0
);
1179 OUT_AS2 (or, w
, %D0
);
1183 OUT_AS2 (mov
, w
, %S0
);
1184 OUT_AS2 (or, w
, %T0
);
1185 OUT_AS2 (or, w
, %U0
);
1186 OUT_AS2 (or, w
, %V0
);
1187 OUT_AS2 (or, w
, %W0
);
1188 OUT_AS2 (or, w
, %X0
);
1189 OUT_AS2 (or, w
, %Y0
);
1190 OUT_AS2 (or, w
, %Z0
);
1202 OUT_AS2 (mov
, w
, %1);
1203 OUT_AS2 (cmp
, w
, %0);
1207 OUT_AS2 (mov
, w
, %H1
);
1208 OUT_AS2 (cmp
, w
, %H0
);
1212 OUT_AS2 (mov
, w
, %L1
);
1213 OUT_AS2 (cmp
, w
, %L0
);
1220 OUT_AS2 (mov
, w
, #1);
1221 OUT_AS2 (mov
, mulh
, w
);
1224 OUT_AS1 (clr
, mulh
);
1225 OUT_AS2 (mov
, w
, %A1
);
1226 OUT_AS2 (cse
, w
, %A0
);
1229 OUT_AS2 (mov
, w
, %B1
);
1230 OUT_AS2 (cse
, w
, %B0
);
1233 OUT_AS2 (mov
, w
, %C1
);
1234 OUT_AS2 (cse
, w
, %C0
);
1237 OUT_AS2 (mov
, w
, %D1
);
1238 OUT_AS2 (cse
, w
, %D0
);
1241 OUT_AS1 (dec
, mulh
);
1243 OUT_AS1 (inc
, mulh
);
1244 OUT_AS2 (mov
, w
, mulh
);
1245 OUT_AS2 (mov
, %2, w
);
1251 OUT_AS2 (mov
, w
, #1);
1252 OUT_AS2 (mov
, mulh
, w
);
1255 OUT_AS1 (clr
, mulh
);
1256 OUT_AS2 (mov
, w
, %S1
);
1257 OUT_AS2 (cse
, w
, %S0
);
1260 OUT_AS2 (mov
, w
, %T1
);
1261 OUT_AS2 (cse
, w
, %T0
);
1264 OUT_AS2 (mov
, w
, %U1
);
1265 OUT_AS2 (cse
, w
, %U0
);
1268 OUT_AS2 (mov
, w
, %V1
);
1269 OUT_AS2 (cse
, w
, %V0
);
1272 OUT_AS2 (mov
, w
, %W1
);
1273 OUT_AS2 (cse
, w
, %W0
);
1276 OUT_AS2 (mov
, w
, %X1
);
1277 OUT_AS2 (cse
, w
, %X0
);
1280 OUT_AS2 (mov
, w
, %Y1
);
1281 OUT_AS2 (cse
, w
, %Y0
);
1284 OUT_AS2 (mov
, w
, %Z1
);
1285 OUT_AS2 (cse
, w
, %Z0
);
1288 OUT_AS1 (dec
, mulh
);
1290 OUT_AS1 (inc
, mulh
);
1291 OUT_AS2 (mov
, w
, mulh
);
1292 OUT_AS2 (mov
, %2, w
);
1299 OUT_AS2 (mov
, w
, #0);
1304 OUT_AS1 (inc
, wreg
);
1305 OUT_AS2 (mov
, %2, w
);
1313 ip2k_gen_signed_comp_branch (rtx insn
, enum rtx_code code
, rtx label
)
1315 #define operands ip2k_compare_operands
1316 enum machine_mode mode
;
1317 int can_use_skip
= 0;
1320 operands
[2] = label
;
1322 mode
= GET_MODE (operands
[0]);
1323 if ((mode
!= QImode
) && (mode
!= HImode
)
1324 && (mode
!= SImode
) && (mode
!= DImode
))
1325 mode
= GET_MODE (operands
[1]);
1327 /* Look for situations where we can just skip the next instruction instead
1328 of skipping and then branching! */
1329 ninsn
= next_real_insn (insn
);
1331 && (recog_memoized (ninsn
) >= 0)
1332 && get_attr_skip (ninsn
) == SKIP_YES
)
1334 rtx skip_tgt
= next_nonnote_insn (next_real_insn (insn
));
1336 /* The first situation is where the target of the jump is one insn
1337 after the jump insn and the insn being jumped is only one machine
1339 if (label
== skip_tgt
)
1343 /* If our skip target is in fact a code label then we ignore the
1344 label and move onto the next useful instruction. Nothing we do
1345 here has any effect on the use of skipping instructions. */
1346 if (GET_CODE (skip_tgt
) == CODE_LABEL
)
1347 skip_tgt
= next_nonnote_insn (skip_tgt
);
1349 /* The second situation is where we have something of the form:
1355 optional_label (this may or may not exist):
1359 In this case we can eliminate the first "page/jump label". */
1360 if (GET_CODE (skip_tgt
) == JUMP_INSN
)
1362 rtx set
= single_set (skip_tgt
);
1363 if (GET_CODE (XEXP (set
, 0)) == PC
1364 && GET_CODE (XEXP (set
, 1)) == LABEL_REF
1365 && label
== JUMP_LABEL (skip_tgt
))
1371 /* gcc is a little braindead and does some rather stateful things while
1372 inspecting attributes - we have to put this state back to what it's
1374 extract_constrain_insn_cached (insn
);
1376 if (ip2k_compare_operands
[1] == const0_rtx
) /* These are easier. */
1383 OUT_AS2 (sb
, %0, 7);
1387 OUT_AS2 (snb
, %0, 7);
1397 OUT_AS2 (rl
, w
, %S0
);
1398 OUT_AS2 (mov
, w
, %S0
);
1399 OUT_AS2 (or, w
, %T0
);
1400 OUT_AS2 (or, w
, %U0
);
1401 OUT_AS2 (or, w
, %V0
);
1402 OUT_AS2 (or, w
, %W0
);
1403 OUT_AS2 (or, w
, %X0
);
1404 OUT_AS2 (or, w
, %Y0
);
1405 OUT_AS2 (or, w
, %Z0
);
1407 OUT_AS2 (setb
, status
, 0);
1408 OUT_AS2 (sb
, status
, 0);
1414 OUT_AS2 (rl
, w
, %A0
);
1415 OUT_AS2 (mov
, w
, %A0
);
1416 OUT_AS2 (or, w
, %B0
);
1417 OUT_AS2 (or, w
, %C0
);
1418 OUT_AS2 (or, w
, %D0
);
1420 OUT_AS2 (setb
, status
, 0);
1421 OUT_AS2 (sb
, status
, 0);
1427 OUT_AS2 (rl
, w
, %H0
);
1428 OUT_AS2 (mov
, w
, %H0
);
1429 OUT_AS2 (or, w
, %L0
);
1431 OUT_AS2 (setb
, status
, 0);
1432 OUT_AS2 (sb
, status
, 0);
1438 OUT_AS2 (mov
, w
, %0); /* Will just do "sb w, 7". */
1440 OUT_AS2 (setb
, wreg
, 7);
1441 OUT_AS2 (sb
, wreg
, 7);
1455 OUT_AS2 (mov
, w
, %S0
);
1456 OUT_AS2 (or, w
, %T0
);
1457 OUT_AS2 (or, w
, %U0
);
1458 OUT_AS2 (or, w
, %V0
);
1459 OUT_AS2 (or, w
, %W0
);
1460 OUT_AS2 (or, w
, %X0
);
1461 OUT_AS2 (or, w
, %Y0
);
1462 OUT_AS2 (or, w
, %Z0
); /* Z is correct. */
1464 OUT_AS2 (snb
, %S0
, 7);
1470 OUT_AS2 (mov
, w
, %A0
);
1471 OUT_AS2 (or, w
, %B0
);
1472 OUT_AS2 (or, w
, %C0
);
1473 OUT_AS2 (or, w
, %D0
); /* Z is correct. */
1475 OUT_AS2 (snb
, %A0
, 7);
1481 OUT_AS2 (mov
, w
, %H0
);
1482 OUT_AS2 (or, w
, %L0
);
1484 OUT_AS2 (snb
, %H0
, 7);
1490 OUT_AS2 (mov
, w
, %0); /* Will just do "sb w, 7". */
1492 OUT_AS2 (snb
, wreg
, 7);
1505 OUT_AS2 (snb
, %0, 7);
1509 OUT_AS2 (sb
, %0, 7);
1521 /* signed compares are out of line because we can't get
1522 the hardware to compute the overflow for us. */
1527 OUT_AS1 (push
, %1%<);
1528 OUT_AS1 (push
, %0%>);
1529 OUT_AS1 (page
, __cmpqi2
);
1530 OUT_AS1 (call
, __cmpqi2
);
1534 OUT_AS1 (push
, %L1
%<);
1535 OUT_AS1 (push
, %H1
%<);
1536 OUT_AS1 (push
, %L0
%<);
1537 OUT_AS1 (push
, %H0
%>%>%>);
1538 OUT_AS1 (page
, __cmphi2
);
1539 OUT_AS1 (call
, __cmphi2
);
1543 OUT_AS1 (push
, %D1
%<);
1544 OUT_AS1 (push
, %C1
%<);
1545 OUT_AS1 (push
, %B1
%<);
1546 OUT_AS1 (push
, %A1
%<);
1547 OUT_AS1 (push
, %D0
%<);
1548 OUT_AS1 (push
, %C0
%<);
1549 OUT_AS1 (push
, %B0
%<);
1550 OUT_AS1 (push
, %A0
%>%>%>%>%>%>%>);
1551 OUT_AS1 (page
, __cmpsi2
);
1552 OUT_AS1 (call
, __cmpsi2
);
1556 if (GET_CODE (operands
[0]) == MEM
1557 && true_regnum (XEXP (operands
[0], 0)) == REG_DP
)
1559 OUT_AS1 (push
, %Z1
%<);
1560 OUT_AS1 (push
, %Y1
%<);
1561 OUT_AS1 (push
, %X1
%<);
1562 OUT_AS1 (push
, %W1
%<);
1563 OUT_AS1 (push
, %V1
%<);
1564 OUT_AS1 (push
, %U1
%<);
1565 OUT_AS1 (push
, %T1
%<);
1566 OUT_AS1 (push
, %S1
%>%>%>%>%>%>%>);
1567 OUT_AS1 (page
, __cmpdi2_dp
);
1568 OUT_AS1 (call
, __cmpdi2_dp
);
1572 OUT_AS1 (push
, %Z1
%<);
1573 OUT_AS1 (push
, %Y1
%<);
1574 OUT_AS1 (push
, %X1
%<);
1575 OUT_AS1 (push
, %W1
%<);
1576 OUT_AS1 (push
, %V1
%<);
1577 OUT_AS1 (push
, %U1
%<);
1578 OUT_AS1 (push
, %T1
%<);
1579 OUT_AS1 (push
, %S1
%<);
1580 OUT_AS1 (push
, %Z0
%<);
1581 OUT_AS1 (push
, %Y0
%<);
1582 OUT_AS1 (push
, %X0
%<);
1583 OUT_AS1 (push
, %W0
%<);
1584 OUT_AS1 (push
, %V0
%<);
1585 OUT_AS1 (push
, %U0
%<);
1586 OUT_AS1 (push
, %T0
%<);
1587 OUT_AS1 (push
, %S0
%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>);
1588 OUT_AS1 (page
, __cmpdi2
);
1589 OUT_AS1 (call
, __cmpdi2
);
1602 OUT_AS2 (cse
, w
, #0);
1606 OUT_AS2 (csne
, w
, #0);
1615 OUT_AS2 (cse
, w
, #2);
1619 OUT_AS2 (csne
, w
, #2);
1628 OUT_AS2 (snb
, wreg
, 1);
1632 OUT_AS2 (sb
, wreg
, 1);
1641 OUT_AS2 (csne
, w
, #0);
1645 OUT_AS2 (cse
, w
, #0);
1659 ip2k_gen_unsigned_comp_branch (rtx insn
, enum rtx_code code
, rtx label
)
1661 #define operands ip2k_compare_operands
1662 enum machine_mode mode
;
1665 int can_use_skip
= 0;
1667 HOST_WIDE_INT const_low
;
1668 HOST_WIDE_INT const_high
;
1670 operands
[2] = label
;
1672 mode
= GET_MODE (operands
[0]);
1673 if ((mode
!= QImode
) && (mode
!= HImode
) && (mode
!= SImode
)
1674 && (mode
!= DImode
))
1676 mode
= GET_MODE (operands
[1]);
1679 /* Look for situations where we can just skip the next instruction instead
1680 of skipping and then branching! */
1681 ninsn
= next_real_insn (insn
);
1683 && (recog_memoized (ninsn
) >= 0)
1684 && get_attr_skip (ninsn
) == SKIP_YES
)
1686 rtx skip_tgt
= next_nonnote_insn (next_real_insn (insn
));
1688 /* The first situation is where the target of the jump is one insn
1689 after the jump insn and the insn being jumped is only one machine
1691 if (label
== skip_tgt
)
1695 /* If our skip target is in fact a code label then we ignore the
1696 label and move onto the next useful instruction. Nothing we do
1697 here has any effect on the use of skipping instructions. */
1698 if (GET_CODE (skip_tgt
) == CODE_LABEL
)
1699 skip_tgt
= next_nonnote_insn (skip_tgt
);
1701 /* The second situation is where we have something of the form:
1707 optional_label (this may or may not exist):
1711 In this case we can eliminate the first "page/jump label". */
1712 if (GET_CODE (skip_tgt
) == JUMP_INSN
)
1714 rtx set
= single_set (skip_tgt
);
1715 if (GET_CODE (XEXP (set
, 0)) == PC
1716 && GET_CODE (XEXP (set
, 1)) == LABEL_REF
1717 && label
== JUMP_LABEL (skip_tgt
))
1723 /* gcc is a little braindead and does some rather stateful things while
1724 inspecting attributes - we have to put this state back to what it's
1726 extract_constrain_insn_cached (insn
);
1728 if (ip2k_compare_operands
[1] == const0_rtx
)
1733 code
= EQ
; /* Nothing is LTU 0. */
1737 code
= NE
; /* Anything nonzero is GTU. */
1741 case NE
: /* Test all the bits, result in
1747 OUT_AS2 (mov
, w
, %S0
);
1748 OUT_AS2 (or, w
, %T0
);
1749 OUT_AS2 (or, w
, %U0
);
1750 OUT_AS2 (or, w
, %V0
);
1751 OUT_AS2 (or, w
, %W0
);
1752 OUT_AS2 (or, w
, %X0
);
1753 OUT_AS2 (or, w
, %Y0
);
1754 OUT_AS2 (or, w
, %Z0
);
1758 OUT_AS2 (mov
, w
, %A0
);
1759 OUT_AS2 (or, w
, %B0
);
1760 OUT_AS2 (or, w
, %C0
);
1761 OUT_AS2 (or, w
, %D0
);
1765 OUT_AS2 (mov
, w
, %H0
);
1766 OUT_AS2 (or, w
, %L0
);
1770 OUT_AS2 (mov
, w
, %0);
1796 /* Always succeed. */
1811 /* Look at whether we have a constant as one of our operands. If we do
1812 and it's in the position that we use to subtract from during our
1813 normal optimized comparison concept then we have to shuffle things
1817 if ((immediate_operand (operands
[1], GET_MODE (operands
[1]))
1818 && ((code
== LEU
) || (code
== GTU
)))
1819 || (immediate_operand (operands
[0], GET_MODE (operands
[0]))
1820 && ((code
== LTU
) || (code
== GEU
))))
1826 /* Same as above - look if we have a constant that we can compare
1827 for equality or non-equality. If we know this then we can look
1828 for common value eliminations. Note that we want to ensure that
1829 any immediate value is operand 1 to simplify the code later! */
1830 if ((code
== EQ
) || (code
== NE
))
1832 imm_cmp
= immediate_operand (operands
[1], GET_MODE (operands
[1]));
1835 imm_cmp
= immediate_operand (operands
[0], GET_MODE (operands
[0]));
1838 rtx tmp
= operands
[1];
1839 operands
[1] = operands
[0];
1851 if (imm_cmp
&& ((INTVAL (operands
[1]) & 0xff) == 0xff))
1852 OUT_AS2 (incsnz
, w
, %0);
1853 else if (imm_cmp
&& ((INTVAL (operands
[1]) & 0xff) == 0x01))
1854 OUT_AS2 (decsnz
, w
, %0);
1857 OUT_AS2 (mov
, w
, %1);
1858 OUT_AS2 (csne
, w
, %0);
1865 if (imm_cmp
&& ((INTVAL (operands
[1]) & 0xff) == 0xff))
1866 OUT_AS2 (incsz
, w
, %0);
1867 else if (imm_cmp
&& ((INTVAL (operands
[1]) & 0xff) == 0x01))
1868 OUT_AS2 (decsz
, w
, %0);
1871 OUT_AS2 (mov
, w
, %1);
1872 OUT_AS2 (cse
, w
, %0);
1879 OUT_AS2 (mov
, w
, %0);
1880 OUT_AS2 (cmp
, w
, %1);
1887 OUT_AS2 (mov
, w
, %1);
1888 OUT_AS2 (cmp
, w
, %0);
1895 OUT_AS2 (mov
, w
, %1);
1896 OUT_AS2 (cmp
, w
, %0);
1903 OUT_AS2 (mov
, w
, %0);
1904 OUT_AS2 (cmp
, w
, %1);
1920 unsigned char h
= 0, l
= 1;
1924 h
= (INTVAL (operands
[1]) >> 8) & 0xff;
1925 l
= INTVAL (operands
[1]) & 0xff;
1927 if ((h
== 0xff) && (l
== 0xff))
1929 /* We should be able to do the following, but the
1930 IP2k simulator doesn't like it and we get a load
1931 of failures in gcc-c-torture. */
1932 OUT_AS2 (incsnz
, w
, %L0
);
1933 OUT_AS2 (incsz
, w
, %H0
);
1934 /* OUT_AS1 (skip,); Should have this */
1935 OUT_AS1 (page
, 1f
);/* Shouldn't need this! */
1936 OUT_AS1 (jmp
, 1f
); /* Shouldn't need this either. */
1945 OUT_AS2 (dec
, w
, %L0
);
1948 OUT_AS2 (mov
, w
, %L0
);
1949 OUT_AS2 (sub
, w
, %L1
);
1951 OUT_AS2 (or, w
, %H0
);
1960 OUT_AS2 (dec
, w
, %H0
);
1963 OUT_AS2 (mov
, w
, %H0
);
1964 OUT_AS2 (sub
, w
, %H1
);
1966 OUT_AS2 (or, w
, %L0
);
1974 OUT_AS2 (mov
, w
, %H1
);
1975 OUT_AS2 (cse
, w
, %H0
);
1978 if (! imm_cmp
|| (h
!= l
))
1979 OUT_AS2 (mov
, w
, %L1
);
1980 OUT_AS2 (csne
, w
, %L0
);
1989 unsigned char h
= 0, l
= 1;
1993 h
= (INTVAL (operands
[1]) >> 8) & 0xff;
1994 l
= INTVAL (operands
[1]) & 0xff;
1996 if ((h
== 0xff) && (l
== 0xff))
1998 OUT_AS2 (incsnz
, w
, %L0
);
1999 OUT_AS2 (incsz
, w
, %H0
);
2007 OUT_AS2 (dec
, w
, %L0
);
2010 OUT_AS2 (mov
, w
, %L0
);
2011 OUT_AS2 (sub
, w
, %L1
);
2013 OUT_AS2 (or, w
, %H0
);
2022 OUT_AS2 (dec
, w
, %H0
);
2025 OUT_AS2 (mov
, w
, %H0
);
2026 OUT_AS2 (sub
, w
, %H1
);
2028 OUT_AS2 (or, w
, %L0
);
2036 OUT_AS2 (mov
, w
, %H1
);
2037 if (imm_cmp
&& (h
== l
))
2039 OUT_AS2 (csne
, w
, %H0
);
2040 OUT_AS2 (cse
, w
, %L0
);
2044 OUT_AS2 (cse
, w
, %H0
);
2047 OUT_AS2 (mov
, w
, %L1
);
2048 OUT_AS2 (cse
, w
, %L0
);
2058 /* > 0xffff never succeeds! */
2059 if ((INTVAL (operands
[1]) & 0xffff) != 0xffff)
2061 operands
[3] = GEN_INT (INTVAL (operands
[1]) + 1);
2062 OUT_AS2 (mov
, w
, %L3
);
2063 OUT_AS2 (sub
, w
, %L0
);
2064 OUT_AS2 (mov
, w
, %H3
);
2065 OUT_AS2 (subc
, w
, %H0
);
2073 OUT_AS2 (mov
, w
, %L0
);
2074 OUT_AS2 (sub
, w
, %L1
);
2075 OUT_AS2 (mov
, w
, %H0
);
2076 OUT_AS2 (subc
, w
, %H1
);
2086 if (INTVAL (operands
[0]) == 0)
2088 OUT_AS2 (mov
, w
, %H1
);
2089 OUT_AS2 (or, w
, %L1
);
2096 operands
[3] = GEN_INT (INTVAL (operands
[0]) - 1);
2097 OUT_AS2 (mov
, w
, %L3
);
2098 OUT_AS2 (sub
, w
, %L1
);
2099 OUT_AS2 (mov
, w
, %H3
);
2100 OUT_AS2 (subc
, w
, %H1
);
2108 OUT_AS2 (mov
, w
, %L1
);
2109 OUT_AS2 (sub
, w
, %L0
);
2110 OUT_AS2 (mov
, w
, %H1
);
2111 OUT_AS2 (subc
, w
, %H0
);
2121 if (INTVAL (operands
[0]) == 0)
2123 OUT_AS2 (mov
, w
, %H1
);
2124 OUT_AS2 (or, w
, %L1
);
2131 operands
[3] = GEN_INT (INTVAL (operands
[0]) - 1);
2132 OUT_AS2 (mov
, w
, %L3
);
2133 OUT_AS2 (sub
, w
, %L1
);
2134 OUT_AS2 (mov
, w
, %H3
);
2135 OUT_AS2 (subc
, w
, %H1
);
2143 OUT_AS2 (mov
, w
, %L1
);
2144 OUT_AS2 (sub
, w
, %L0
);
2145 OUT_AS2 (mov
, w
, %H1
);
2146 OUT_AS2 (subc
, w
, %H0
);
2156 if ((INTVAL (operands
[1]) & 0xffff) == 0xffff)
2158 /* <= 0xffff always succeeds. */
2164 operands
[3] = GEN_INT (INTVAL (operands
[1]) + 1);
2165 OUT_AS2 (mov
, w
, %L3
);
2166 OUT_AS2 (sub
, w
, %L0
);
2167 OUT_AS2 (mov
, w
, %H3
);
2168 OUT_AS2 (subc
, w
, %H0
);
2176 OUT_AS2 (mov
, w
, %L0
);
2177 OUT_AS2 (sub
, w
, %L1
);
2178 OUT_AS2 (mov
, w
, %H0
);
2179 OUT_AS2 (subc
, w
, %H1
);
2196 unsigned char a
= 0, b
= 1, c
= 2, d
= 3;
2200 a
= (INTVAL (operands
[1]) >> 24) & 0xff;
2201 b
= (INTVAL (operands
[1]) >> 16) & 0xff;
2202 c
= (INTVAL (operands
[1]) >> 8) & 0xff;
2203 d
= INTVAL (operands
[1]) & 0xff;
2206 OUT_AS2 (mov
, w
, %A1
);
2207 if (imm_cmp
&& (b
== a
))
2209 OUT_AS2 (csne
, w
, %A0
);
2210 OUT_AS2 (cse
, w
, %B0
);
2214 OUT_AS2 (cse
, w
, %A0
);
2217 OUT_AS2 (mov
, w
, %B1
);
2218 OUT_AS2 (cse
, w
, %B0
);
2222 if (! imm_cmp
|| (c
!= b
))
2223 OUT_AS2 (mov
, w
, %C1
);
2224 OUT_AS2 (cse
, w
, %C0
);
2227 if (! imm_cmp
|| (d
!= c
))
2228 OUT_AS2 (mov
, w
, %D1
);
2229 OUT_AS2 (csne
, w
, %D0
);
2238 unsigned char a
= 0, b
= 1, c
= 2, d
= 3;
2242 a
= (INTVAL (operands
[1]) >> 24) & 0xff;
2243 b
= (INTVAL (operands
[1]) >> 16) & 0xff;
2244 c
= (INTVAL (operands
[1]) >> 8) & 0xff;
2245 d
= INTVAL (operands
[1]) & 0xff;
2248 OUT_AS2 (mov
, w
, %A1
);
2249 if (imm_cmp
&& (b
== a
))
2251 OUT_AS2 (csne
, w
, %A0
);
2252 OUT_AS2 (cse
, w
, %B0
);
2256 OUT_AS2 (cse
, w
, %A0
);
2259 OUT_AS2 (mov
, w
, %B1
);
2260 OUT_AS2 (cse
, w
, %B0
);
2264 if (! imm_cmp
|| (c
!= b
))
2265 OUT_AS2 (mov
, w
, %C1
);
2266 if (imm_cmp
&& (d
== c
))
2268 OUT_AS2 (csne
, w
, %C0
);
2269 OUT_AS2 (cse
, w
, %D0
);
2273 OUT_AS2 (cse
, w
, %C0
);
2276 OUT_AS2 (mov
, w
, %D1
);
2277 OUT_AS2 (cse
, w
, %D0
);
2287 /* > 0xffffffff never succeeds! */
2288 if ((unsigned HOST_WIDE_INT
)(INTVAL (operands
[1]) & 0xffffffff)
2291 operands
[3] = GEN_INT (INTVAL (operands
[1]) + 1);
2292 OUT_AS2 (mov
, w
, %D3
);
2293 OUT_AS2 (sub
, w
, %D0
);
2294 OUT_AS2 (mov
, w
, %C3
);
2295 OUT_AS2 (subc
, w
, %C0
);
2296 OUT_AS2 (mov
, w
, %B3
);
2297 OUT_AS2 (subc
, w
, %B0
);
2298 OUT_AS2 (mov
, w
, %A3
);
2299 OUT_AS2 (subc
, w
, %A0
);
2307 OUT_AS2 (mov
, w
, %D0
);
2308 OUT_AS2 (sub
, w
, %D1
);
2309 OUT_AS2 (mov
, w
, %C0
);
2310 OUT_AS2 (subc
, w
, %C1
);
2311 OUT_AS2 (mov
, w
, %B0
);
2312 OUT_AS2 (subc
, w
, %B1
);
2313 OUT_AS2 (mov
, w
, %A0
);
2314 OUT_AS2 (subc
, w
, %A1
);
2324 if (INTVAL (operands
[0]) == 0)
2326 OUT_AS2 (mov
, w
, %A1
);
2327 OUT_AS2 (or, w
, %B1
);
2328 OUT_AS2 (or, w
, %C1
);
2329 OUT_AS2 (or, w
, %D1
);
2336 operands
[3] = GEN_INT (INTVAL (operands
[0]) - 1);
2337 OUT_AS2 (mov
, w
, %D3
);
2338 OUT_AS2 (sub
, w
, %D1
);
2339 OUT_AS2 (mov
, w
, %C3
);
2340 OUT_AS2 (subc
, w
, %C1
);
2341 OUT_AS2 (mov
, w
, %B3
);
2342 OUT_AS2 (subc
, w
, %B1
);
2343 OUT_AS2 (mov
, w
, %A3
);
2344 OUT_AS2 (subc
, w
, %A1
);
2352 OUT_AS2 (mov
, w
, %D1
);
2353 OUT_AS2 (sub
, w
, %D0
);
2354 OUT_AS2 (mov
, w
, %C1
);
2355 OUT_AS2 (subc
, w
, %C0
);
2356 OUT_AS2 (mov
, w
, %B1
);
2357 OUT_AS2 (subc
, w
, %B0
);
2358 OUT_AS2 (mov
, w
, %A1
);
2359 OUT_AS2 (subc
, w
, %A0
);
2369 if (INTVAL (operands
[0]) == 0)
2371 OUT_AS2 (mov
, w
, %A1
);
2372 OUT_AS2 (or, w
, %B1
);
2373 OUT_AS2 (or, w
, %C1
);
2374 OUT_AS2 (or, w
, %D1
);
2381 operands
[3] = GEN_INT (INTVAL (operands
[0]) - 1);
2382 OUT_AS2 (mov
, w
, %D3
);
2383 OUT_AS2 (sub
, w
, %D1
);
2384 OUT_AS2 (mov
, w
, %C3
);
2385 OUT_AS2 (subc
, w
, %C1
);
2386 OUT_AS2 (mov
, w
, %B3
);
2387 OUT_AS2 (subc
, w
, %B1
);
2388 OUT_AS2 (mov
, w
, %A3
);
2389 OUT_AS2 (subc
, w
, %A1
);
2397 OUT_AS2 (mov
, w
, %D1
);
2398 OUT_AS2 (sub
, w
, %D0
);
2399 OUT_AS2 (mov
, w
, %C1
);
2400 OUT_AS2 (subc
, w
, %C0
);
2401 OUT_AS2 (mov
, w
, %B1
);
2402 OUT_AS2 (subc
, w
, %B0
);
2403 OUT_AS2 (mov
, w
, %A1
);
2404 OUT_AS2 (subc
, w
, %A0
);
2414 if ((unsigned HOST_WIDE_INT
)(INTVAL (operands
[1]) & 0xffffffff)
2417 /* <= 0xffffffff always succeeds. */
2423 operands
[3] = GEN_INT (INTVAL (operands
[1]) + 1);
2424 OUT_AS2 (mov
, w
, %D3
);
2425 OUT_AS2 (sub
, w
, %D0
);
2426 OUT_AS2 (mov
, w
, %C3
);
2427 OUT_AS2 (subc
, w
, %C0
);
2428 OUT_AS2 (mov
, w
, %B3
);
2429 OUT_AS2 (subc
, w
, %B0
);
2430 OUT_AS2 (mov
, w
, %A3
);
2431 OUT_AS2 (subc
, w
, %A0
);
2439 OUT_AS2 (mov
, w
, %D0
);
2440 OUT_AS2 (sub
, w
, %D1
);
2441 OUT_AS2 (mov
, w
, %C0
);
2442 OUT_AS2 (subc
, w
, %C1
);
2443 OUT_AS2 (mov
, w
, %B0
);
2444 OUT_AS2 (subc
, w
, %B1
);
2445 OUT_AS2 (mov
, w
, %A0
);
2446 OUT_AS2 (subc
, w
, %A1
);
2459 if (GET_CODE (operands
[1]) == CONST_INT
)
2461 const_low
= INTVAL (operands
[1]);
2462 const_high
= (const_low
>= 0) - 1;
2464 else if (GET_CODE (operands
[1]) == CONST_DOUBLE
)
2466 const_low
= CONST_DOUBLE_LOW (operands
[1]);
2467 const_high
= CONST_DOUBLE_HIGH (operands
[1]);
2473 unsigned char s
= 0, t
= 1, u
= 2, v
= 3;
2474 unsigned char w
= 4, x
= 5, y
= 6, z
= 7;
2477 if (GET_CODE (operands
[0]) == MEM
2478 && true_regnum (XEXP (operands
[0], 0)) == REG_DP
)
2480 OUT_AS1 (push
, %Z1
%<);
2481 OUT_AS1 (push
, %Y1
%<);
2482 OUT_AS1 (push
, %X1
%<);
2483 OUT_AS1 (push
, %W1
%<);
2484 OUT_AS1 (push
, %V1
%<);
2485 OUT_AS1 (push
, %U1
%<);
2486 OUT_AS1 (push
, %T1
%<);
2487 OUT_AS1 (push
, %S1
%>%>%>%>%>%>%>);
2488 OUT_AS1 (page
, __cmpdi2_dp
);
2489 OUT_AS1 (call
, __cmpdi2_dp
);
2490 OUT_AS2 (csne
, w
, #1);
2496 OUT_AS1 (push
, %Z1
%<);
2497 OUT_AS1 (push
, %Y1
%<);
2498 OUT_AS1 (push
, %X1
%<);
2499 OUT_AS1 (push
, %W1
%<);
2500 OUT_AS1 (push
, %V1
%<);
2501 OUT_AS1 (push
, %U1
%<);
2502 OUT_AS1 (push
, %T1
%<);
2503 OUT_AS1 (push
, %S1
%<);
2504 OUT_AS1 (push
, %Z0
%<);
2505 OUT_AS1 (push
, %Y0
%<);
2506 OUT_AS1 (push
, %X0
%<);
2507 OUT_AS1 (push
, %W0
%<);
2508 OUT_AS1 (push
, %V0
%<);
2509 OUT_AS1 (push
, %U0
%<);
2510 OUT_AS1 (push
, %T0
%<);
2511 OUT_AS1 (push
, %S0
%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>);
2512 OUT_AS1 (page
, __cmpdi2
);
2513 OUT_AS1 (call
, __cmpdi2
);
2514 OUT_AS2 (csne
, w
, #1);
2523 s
= (const_high
>> 24) & 0xff;
2524 t
= (const_high
>> 16) & 0xff;
2525 u
= (const_high
>> 8) & 0xff;
2526 v
= const_high
& 0xff;
2527 w
= (const_low
>> 24) & 0xff;
2528 x
= (const_low
>> 16) & 0xff;
2529 y
= (const_low
>> 8) & 0xff;
2530 z
= const_low
& 0xff;
2533 OUT_AS2 (mov
, w
, %S1
);
2534 if (imm_cmp
&& (s
== t
))
2536 OUT_AS2 (csne
, w
, %S0
);
2537 OUT_AS2 (cse
, w
, %T0
);
2541 OUT_AS2 (cse
, w
, %S0
);
2544 OUT_AS2 (mov
, w
, %T1
);
2545 OUT_AS2 (cse
, w
, %T0
);
2550 OUT_AS2 (mov
, w
, %U1
);
2551 if (imm_cmp
&& (u
== v
))
2553 OUT_AS2 (csne
, w
, %U0
);
2554 OUT_AS2 (cse
, w
, %V0
);
2558 OUT_AS2 (cse
, w
, %U0
);
2561 OUT_AS2 (mov
, w
, %V1
);
2562 OUT_AS2 (cse
, w
, %V0
);
2567 OUT_AS2 (mov
, w
, %W1
);
2568 if (imm_cmp
&& (w
== x
))
2570 OUT_AS2 (csne
, w
, %W0
);
2571 OUT_AS2 (cse
, w
, %X0
);
2575 OUT_AS2 (cse
, w
, %W0
);
2578 OUT_AS2 (mov
, w
, %X1
);
2579 OUT_AS2 (cse
, w
, %X0
);
2584 if (! imm_cmp
|| (x
!= y
))
2585 OUT_AS2 (mov
, w
, %Y1
);
2586 OUT_AS2 (cse
, w
, %Y0
);
2589 if (! imm_cmp
|| (z
!= y
))
2590 OUT_AS2 (mov
, w
, %Z1
);
2591 OUT_AS2 (csne
, w
, %Z0
);
2601 unsigned char s
= 0, t
= 1, u
= 2, v
= 3;
2602 unsigned char w
= 4, x
= 5, y
= 6, z
= 7;
2606 if (GET_CODE (operands
[0]) == MEM
2607 && true_regnum (XEXP (operands
[0], 0)) == REG_DP
)
2609 OUT_AS1 (push
, %Z1
%<);
2610 OUT_AS1 (push
, %Y1
%<);
2611 OUT_AS1 (push
, %X1
%<);
2612 OUT_AS1 (push
, %W1
%<);
2613 OUT_AS1 (push
, %V1
%<);
2614 OUT_AS1 (push
, %U1
%<);
2615 OUT_AS1 (push
, %T1
%<);
2616 OUT_AS1 (push
, %S1
%>%>%>%>%>%>%>);
2617 OUT_AS1 (page
, __cmpdi2_dp
);
2618 OUT_AS1 (call
, __cmpdi2_dp
);
2619 OUT_AS2 (cse
, w
, #1);
2625 OUT_AS1 (push
, %Z1
%<);
2626 OUT_AS1 (push
, %Y1
%<);
2627 OUT_AS1 (push
, %X1
%<);
2628 OUT_AS1 (push
, %W1
%<);
2629 OUT_AS1 (push
, %V1
%<);
2630 OUT_AS1 (push
, %U1
%<);
2631 OUT_AS1 (push
, %T1
%<);
2632 OUT_AS1 (push
, %S1
%<);
2633 OUT_AS1 (push
, %Z0
%<);
2634 OUT_AS1 (push
, %Y0
%<);
2635 OUT_AS1 (push
, %X0
%<);
2636 OUT_AS1 (push
, %W0
%<);
2637 OUT_AS1 (push
, %V0
%<);
2638 OUT_AS1 (push
, %U0
%<);
2639 OUT_AS1 (push
, %T0
%<);
2640 OUT_AS1 (push
, %S0
%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>);
2641 OUT_AS1 (page
, __cmpdi2
);
2642 OUT_AS1 (call
, __cmpdi2
);
2643 OUT_AS2 (cse
, w
, #1);
2652 s
= (const_high
>> 24) & 0xff;
2653 t
= (const_high
>> 16) & 0xff;
2654 u
= (const_high
>> 8) & 0xff;
2655 v
= const_high
& 0xff;
2656 w
= (const_low
>> 24) & 0xff;
2657 x
= (const_low
>> 16) & 0xff;
2658 y
= (const_low
>> 8) & 0xff;
2659 z
= const_low
& 0xff;
2662 OUT_AS2 (mov
, w
, %S1
);
2663 if (imm_cmp
&& (s
== t
))
2665 OUT_AS2 (csne
, w
, %S0
);
2666 OUT_AS2 (cse
, w
, %T0
);
2670 OUT_AS2 (cse
, w
, %S0
);
2673 OUT_AS2 (mov
, w
, %T1
);
2674 OUT_AS2 (cse
, w
, %T0
);
2679 OUT_AS2 (mov
, w
, %U1
);
2680 if (imm_cmp
&& (u
== v
))
2682 OUT_AS2 (csne
, w
, %U0
);
2683 OUT_AS2 (cse
, w
, %V0
);
2687 OUT_AS2 (cse
, w
, %U0
);
2690 OUT_AS2 (mov
, w
, %V1
);
2691 OUT_AS2 (cse
, w
, %V0
);
2696 OUT_AS2 (mov
, w
, %W1
);
2697 if (imm_cmp
&& (w
== x
))
2699 OUT_AS2 (csne
, w
, %W0
);
2700 OUT_AS2 (cse
, w
, %X0
);
2704 OUT_AS2 (cse
, w
, %W0
);
2707 OUT_AS2 (mov
, w
, %X1
);
2708 OUT_AS2 (cse
, w
, %X0
);
2713 if (! imm_cmp
|| (y
!= x
))
2714 OUT_AS2 (mov
, w
, %Y1
);
2715 if (imm_cmp
&& (z
== y
))
2717 OUT_AS2 (csne
, w
, %Y0
);
2718 OUT_AS2 (cse
, w
, %Z0
);
2722 OUT_AS2 (cse
, w
, %Y0
);
2725 OUT_AS2 (mov
, w
, %Z1
);
2726 OUT_AS2 (cse
, w
, %Z0
);
2737 /* > 0xffffffffffffffff never succeeds! */
2738 if (((const_high
& 0xffffffff) != 0xffffffff)
2739 || ((const_low
& 0xffffffff) != 0xffffffff))
2741 operands
[3] = GEN_INT (const_low
+ 1);
2742 operands
[4] = GEN_INT (const_high
2743 + (INTVAL (operands
[3]) ? 0 : 1));
2744 OUT_AS2 (mov
, w
, %D3
);
2745 OUT_AS2 (sub
, w
, %Z0
);
2746 OUT_AS2 (mov
, w
, %C3
);
2747 OUT_AS2 (subc
, w
, %Y0
);
2748 OUT_AS2 (mov
, w
, %B3
);
2749 OUT_AS2 (subc
, w
, %X0
);
2750 OUT_AS2 (mov
, w
, %A3
);
2751 OUT_AS2 (subc
, w
, %W0
);
2752 OUT_AS2 (mov
, w
, %D4
);
2753 OUT_AS2 (subc
, w
, %V0
);
2754 OUT_AS2 (mov
, w
, %C4
);
2755 OUT_AS2 (subc
, w
, %U0
);
2756 OUT_AS2 (mov
, w
, %B4
);
2757 OUT_AS2 (subc
, w
, %T0
);
2758 OUT_AS2 (mov
, w
, %A4
);
2759 OUT_AS2 (subc
, w
, %S0
);
2767 OUT_AS2 (mov
, w
, %Z0
);
2768 OUT_AS2 (sub
, w
, %Z1
);
2769 OUT_AS2 (mov
, w
, %Y0
);
2770 OUT_AS2 (subc
, w
, %Y1
);
2771 OUT_AS2 (mov
, w
, %X0
);
2772 OUT_AS2 (subc
, w
, %X1
);
2773 OUT_AS2 (mov
, w
, %W0
);
2774 OUT_AS2 (subc
, w
, %W1
);
2775 OUT_AS2 (mov
, w
, %V0
);
2776 OUT_AS2 (subc
, w
, %V1
);
2777 OUT_AS2 (mov
, w
, %U0
);
2778 OUT_AS2 (subc
, w
, %U1
);
2779 OUT_AS2 (mov
, w
, %T0
);
2780 OUT_AS2 (subc
, w
, %T1
);
2781 OUT_AS2 (mov
, w
, %S0
);
2782 OUT_AS2 (subc
, w
, %S1
);
2792 HOST_WIDE_INT const_low0
;
2793 HOST_WIDE_INT const_high0
;
2795 if (GET_CODE (operands
[0]) == CONST_INT
)
2797 const_low0
= INTVAL (operands
[0]);
2798 const_high0
= (const_low
>= 0) - 1;
2800 else if (GET_CODE (operands
[0]) == CONST_DOUBLE
)
2802 const_low0
= CONST_DOUBLE_LOW (operands
[0]);
2803 const_high0
= CONST_DOUBLE_HIGH (operands
[0]);
2806 if (const_high0
== 0 && const_low0
== 0)
2808 OUT_AS2 (mov
, w
, %S1
);
2809 OUT_AS2 (or, w
, %T1
);
2810 OUT_AS2 (or, w
, %U1
);
2811 OUT_AS2 (or, w
, %V1
);
2812 OUT_AS2 (or, w
, %W1
);
2813 OUT_AS2 (or, w
, %X1
);
2814 OUT_AS2 (or, w
, %Y1
);
2815 OUT_AS2 (or, w
, %Z1
);
2822 operands
[3] = GEN_INT (const_low0
- 1);
2823 operands
[4] = GEN_INT (const_high0
- (const_low0
? 1 : 0));
2824 OUT_AS2 (mov
, w
, %D3
);
2825 OUT_AS2 (sub
, w
, %Z1
);
2826 OUT_AS2 (mov
, w
, %C3
);
2827 OUT_AS2 (subc
, w
, %Y1
);
2828 OUT_AS2 (mov
, w
, %B3
);
2829 OUT_AS2 (subc
, w
, %X1
);
2830 OUT_AS2 (mov
, w
, %A3
);
2831 OUT_AS2 (subc
, w
, %W1
);
2832 OUT_AS2 (mov
, w
, %D4
);
2833 OUT_AS2 (subc
, w
, %V1
);
2834 OUT_AS2 (mov
, w
, %C4
);
2835 OUT_AS2 (subc
, w
, %U1
);
2836 OUT_AS2 (mov
, w
, %B4
);
2837 OUT_AS2 (subc
, w
, %T1
);
2838 OUT_AS2 (mov
, w
, %A4
);
2839 OUT_AS2 (subc
, w
, %S1
);
2847 OUT_AS2 (mov
, w
, %Z1
);
2848 OUT_AS2 (sub
, w
, %Z0
);
2849 OUT_AS2 (mov
, w
, %Y1
);
2850 OUT_AS2 (subc
, w
, %Y0
);
2851 OUT_AS2 (mov
, w
, %X1
);
2852 OUT_AS2 (subc
, w
, %X0
);
2853 OUT_AS2 (mov
, w
, %W1
);
2854 OUT_AS2 (subc
, w
, %W0
);
2855 OUT_AS2 (mov
, w
, %V1
);
2856 OUT_AS2 (subc
, w
, %V0
);
2857 OUT_AS2 (mov
, w
, %U1
);
2858 OUT_AS2 (subc
, w
, %U0
);
2859 OUT_AS2 (mov
, w
, %T1
);
2860 OUT_AS2 (subc
, w
, %T0
);
2861 OUT_AS2 (mov
, w
, %S1
);
2862 OUT_AS2 (subc
, w
, %S0
);
2872 HOST_WIDE_INT const_low0
;
2873 HOST_WIDE_INT const_high0
;
2875 if (GET_CODE (operands
[0]) == CONST_INT
)
2877 const_low0
= INTVAL (operands
[0]);
2878 const_high0
= (const_low
>= 0) - 1;
2880 else if (GET_CODE (operands
[0]) == CONST_DOUBLE
)
2882 const_low0
= CONST_DOUBLE_LOW (operands
[0]);
2883 const_high0
= CONST_DOUBLE_HIGH (operands
[0]);
2886 if (const_high0
== 0 && const_low0
== 0)
2888 OUT_AS2 (mov
, w
, %S1
);
2889 OUT_AS2 (or, w
, %T1
);
2890 OUT_AS2 (or, w
, %U1
);
2891 OUT_AS2 (or, w
, %V1
);
2892 OUT_AS2 (or, w
, %W1
);
2893 OUT_AS2 (or, w
, %X1
);
2894 OUT_AS2 (or, w
, %Y1
);
2895 OUT_AS2 (or, w
, %Z1
);
2902 operands
[3] = GEN_INT (const_low0
- 1);
2903 operands
[4] = GEN_INT (const_high0
- (const_low0
? 1 : 0));
2904 OUT_AS2 (mov
, w
, %D3
);
2905 OUT_AS2 (sub
, w
, %Z1
);
2906 OUT_AS2 (mov
, w
, %C3
);
2907 OUT_AS2 (subc
, w
, %Y1
);
2908 OUT_AS2 (mov
, w
, %B3
);
2909 OUT_AS2 (subc
, w
, %X1
);
2910 OUT_AS2 (mov
, w
, %A3
);
2911 OUT_AS2 (subc
, w
, %W1
);
2912 OUT_AS2 (mov
, w
, %D4
);
2913 OUT_AS2 (subc
, w
, %V1
);
2914 OUT_AS2 (mov
, w
, %C4
);
2915 OUT_AS2 (subc
, w
, %U1
);
2916 OUT_AS2 (mov
, w
, %B4
);
2917 OUT_AS2 (subc
, w
, %T1
);
2918 OUT_AS2 (mov
, w
, %A4
);
2919 OUT_AS2 (subc
, w
, %S1
);
2927 OUT_AS2 (mov
, w
, %Z1
);
2928 OUT_AS2 (sub
, w
, %Z0
);
2929 OUT_AS2 (mov
, w
, %Y1
);
2930 OUT_AS2 (subc
, w
, %Y0
);
2931 OUT_AS2 (mov
, w
, %X1
);
2932 OUT_AS2 (subc
, w
, %X0
);
2933 OUT_AS2 (mov
, w
, %W1
);
2934 OUT_AS2 (subc
, w
, %W0
);
2935 OUT_AS2 (mov
, w
, %V1
);
2936 OUT_AS2 (subc
, w
, %V0
);
2937 OUT_AS2 (mov
, w
, %U1
);
2938 OUT_AS2 (subc
, w
, %U0
);
2939 OUT_AS2 (mov
, w
, %T1
);
2940 OUT_AS2 (subc
, w
, %T0
);
2941 OUT_AS2 (mov
, w
, %S1
);
2942 OUT_AS2 (subc
, w
, %S0
);
2952 if (((const_high
& 0xffffffff) == 0xffffffff)
2953 && ((const_low
& 0xffffffff) == 0xffffffff))
2955 /* <= 0xffffffffffffffff always succeeds. */
2961 operands
[3] = GEN_INT (const_low
+ 1);
2962 operands
[4] = GEN_INT (const_high
2963 + (INTVAL (operands
[3]) ? 0 : 1));
2964 OUT_AS2 (mov
, w
, %D3
);
2965 OUT_AS2 (sub
, w
, %Z0
);
2966 OUT_AS2 (mov
, w
, %C3
);
2967 OUT_AS2 (subc
, w
, %Y0
);
2968 OUT_AS2 (mov
, w
, %B3
);
2969 OUT_AS2 (subc
, w
, %X0
);
2970 OUT_AS2 (mov
, w
, %A3
);
2971 OUT_AS2 (subc
, w
, %W0
);
2972 OUT_AS2 (mov
, w
, %D4
);
2973 OUT_AS2 (subc
, w
, %V0
);
2974 OUT_AS2 (mov
, w
, %C4
);
2975 OUT_AS2 (subc
, w
, %U0
);
2976 OUT_AS2 (mov
, w
, %B4
);
2977 OUT_AS2 (subc
, w
, %T0
);
2978 OUT_AS2 (mov
, w
, %A4
);
2979 OUT_AS2 (subc
, w
, %S0
);
2987 OUT_AS2 (mov
, w
, %Z0
);
2988 OUT_AS2 (sub
, w
, %Z1
);
2989 OUT_AS2 (mov
, w
, %Y0
);
2990 OUT_AS2 (subc
, w
, %Y1
);
2991 OUT_AS2 (mov
, w
, %X0
);
2992 OUT_AS2 (subc
, w
, %X1
);
2993 OUT_AS2 (mov
, w
, %W0
);
2994 OUT_AS2 (subc
, w
, %W1
);
2995 OUT_AS2 (mov
, w
, %V0
);
2996 OUT_AS2 (subc
, w
, %V1
);
2997 OUT_AS2 (mov
, w
, %U0
);
2998 OUT_AS2 (subc
, w
, %U1
);
2999 OUT_AS2 (mov
, w
, %T0
);
3000 OUT_AS2 (subc
, w
, %T1
);
3001 OUT_AS2 (mov
, w
, %S0
);
3002 OUT_AS2 (subc
, w
, %S1
);
3021 /* Output rtx VALUE as .byte to file FILE. */
3024 asm_output_char (FILE *file
, rtx value
)
3026 fprintf (file
, "\t.byte ");
3027 output_addr_const (file
, value
);
3028 fprintf (file
, "\n");
3032 /* Output VALUE as .byte to file FILE. */
3035 asm_output_byte (FILE *file
, int value
)
3037 fprintf (file
, "\t.byte 0x%x\n",value
& 0xff);
3041 /* Output rtx VALUE as .word to file FILE. */
3044 asm_output_short (FILE *file
, rtx value
)
3046 fprintf (file
, "\t.word ");
3047 output_addr_const (file
, (value
));
3048 fprintf (file
, "\n");
3052 /* Output real N to file FILE. */
3055 asm_output_float (FILE *file
, REAL_VALUE_TYPE n
)
3060 REAL_VALUE_TO_TARGET_SINGLE (n
, val
);
3061 real_to_decimal (dstr
, &n
, sizeof (dstr
), 0, 1);
3063 fprintf (file
, "\t.long 0x%08lx\t/* %s */\n", val
, dstr
);
3066 /* Sets section name for declaration DECL. */
3069 unique_section (tree decl
, int reloc ATTRIBUTE_UNUSED
)
3075 name
= IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
));
3076 /* Strip off any encoding in name. */
3077 name
= (* targetm
.strip_name_encoding
) (name
);
3079 if (TREE_CODE (decl
) == FUNCTION_DECL
)
3081 if (flag_function_sections
)
3089 if (flag_function_sections
)
3091 len
= strlen (name
) + strlen (prefix
);
3092 string
= alloca (len
+ 1);
3093 sprintf (string
, "%s%s", prefix
, name
);
3094 DECL_SECTION_NAME (decl
) = build_string (len
, string
);
3098 /* Return value is nonzero if pseudos that have been
3099 assigned to registers of class CLASS would likely be spilled
3100 because registers of CLASS are needed for spill registers. */
3103 class_likely_spilled_p (int c
)
3105 return (c
== IP_REGS
3116 /* Valid attributes:
3117 progmem - put data to program memory;
3118 naked - don't generate function prologue/epilogue and `ret' command.
3120 Only `progmem' attribute valid for type. */
3122 const struct attribute_spec ip2k_attribute_table
[] =
3124 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
3125 { "progmem", 0, 0, false, false, false, ip2k_handle_progmem_attribute
},
3126 { "naked", 0, 0, true, false, false, ip2k_handle_fndecl_attribute
},
3127 { NULL
, 0, 0, false, false, false, NULL
}
3130 /* Handle a "progmem" attribute; arguments as in
3131 struct attribute_spec.handler. */
3133 ip2k_handle_progmem_attribute (tree
*node
, tree name
,
3134 tree args ATTRIBUTE_UNUSED
,
3135 int flags ATTRIBUTE_UNUSED
,
3140 if (TREE_CODE (*node
) == TYPE_DECL
)
3142 /* This is really a decl attribute, not a type attribute,
3143 but try to handle it for GCC 3.0 backwards compatibility. */
3145 tree type
= TREE_TYPE (*node
);
3146 tree attr
= tree_cons (name
, args
, TYPE_ATTRIBUTES (type
));
3147 tree newtype
= build_type_attribute_variant (type
, attr
);
3149 TYPE_MAIN_VARIANT (newtype
) = TYPE_MAIN_VARIANT (type
);
3150 TREE_TYPE (*node
) = newtype
;
3151 *no_add_attrs
= true;
3153 else if (TREE_STATIC (*node
) || DECL_EXTERNAL (*node
))
3155 if (DECL_INITIAL (*node
) == NULL_TREE
&& !DECL_EXTERNAL (*node
))
3157 warning (0, "only initialized variables can be placed into "
3158 "program memory area");
3159 *no_add_attrs
= true;
3164 warning (OPT_Wattributes
, "%qs attribute ignored",
3165 IDENTIFIER_POINTER (name
));
3166 *no_add_attrs
= true;
3173 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
3174 struct attribute_spec.handler. */
3176 ip2k_handle_fndecl_attribute (tree
*node
, tree name
,
3177 tree args ATTRIBUTE_UNUSED
,
3178 int flags ATTRIBUTE_UNUSED
,
3181 if (TREE_CODE (*node
) != FUNCTION_DECL
)
3183 warning (OPT_Wattributes
, "%qs attribute only applies to functions",
3184 IDENTIFIER_POINTER (name
));
3185 *no_add_attrs
= true;
3191 /* Cost functions. */
3193 /* Compute a (partial) cost for rtx X. Return true if the complete
3194 cost has been computed, and false if subexpressions should be
3195 scanned. In either case, *TOTAL contains the cost result. */
3198 ip2k_rtx_costs (rtx x
, int code
, int outer_code
, int *total
)
3200 enum machine_mode mode
= GET_MODE (x
);
3216 *total
= ip2k_address_cost (XEXP (x
, 0));
3224 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
3226 int val
= INTVAL (XEXP (x
, 1));
3229 /* Shift by const instructions are proportional to
3230 the shift count modulus 8. Note that we increase the mode
3231 size multiplier by 1 to account for clearing the carry flag. */
3232 cost
= COSTS_N_INSNS (abs (val
) % 8);
3233 cost
+= rtx_cost (XEXP (x
, 0), code
);
3234 cost
*= (GET_MODE_SIZE (mode
) + 1);
3236 /* Sign-preserving shifts require 2 extra instructions. */
3238 cost
+= COSTS_N_INSNS (2);
3243 *total
= rtx_cost (XEXP (x
, 0), code
);
3244 *total
+= COSTS_N_INSNS (GET_MODE_SIZE (mode
) * 8);
3252 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
) * 3);
3258 *total
= COSTS_N_INSNS (20);
3259 else if (mode
== HImode
)
3260 *total
= COSTS_N_INSNS (60);
3261 else if (mode
== SImode
)
3262 *total
= COSTS_N_INSNS (180);
3264 *total
= COSTS_N_INSNS (540);
3268 /* These costs are OK, but should really handle subtle cases
3269 where we're using sign or zero extended args as these are
3270 *much* cheaper than those given below! */
3272 *total
= COSTS_N_INSNS (4);
3273 else if (mode
== HImode
)
3274 *total
= COSTS_N_INSNS (12);
3275 else if (mode
== SImode
)
3276 *total
= COSTS_N_INSNS (36);
3278 *total
= COSTS_N_INSNS (108);
3283 extra_cost
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
3289 *total
= extra_cost
+ COSTS_N_INSNS (GET_MODE_SIZE (mode
) * 2);
3294 if (outer_code
== SET
)
3296 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
) * 3 / 2);
3301 *total
= -(COSTS_N_INSNS (GET_MODE_SIZE (mode
)) / 2);
3306 *total
= rtx_cost (XEXP (x
, 0), code
) + COSTS_N_INSNS (2);
3323 *total
= COSTS_N_INSNS (4);
3328 /* Calculate the cost of a memory address. */
3331 ip2k_address_cost (rtx x
)
3333 switch (legitimate_address_p (VOIDmode
, x
, 0))
3335 case 'S': /* Very low cost - (IP), (SP+N) or (DP+N) */
3338 case 'R': /* Indirected through IP. */
3341 case 'L': /* Label references. */
3344 case 'C': /* Constants and symbol references. */
3348 return 1000; /* Must reload. */
3352 /* As part of the machine-dependent reorg we look for opcode sequences where
3353 we do some operation and then move the results back to one of the original
3354 source operands. With working on the source operand directly is probably
3355 much cheaper and the move from this to the original source operand will be
3356 no more expensive than the original move. */
3358 #ifdef IP2K_MD_REORG_PASS
3360 mdr_resequence_xy_yx (first_insn
)
3365 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
3369 if (GET_CODE (insn
) != INSN
)
3372 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
3373 if (set
== NULL_RTX
)
3376 /* Look for operations that tend to be very cheap to run when the source
3377 * and dest args are the same because the IP2022 has opcodes that can
3378 operate on the source directly. If we have to spill through the W
3379 register then we've possibly not got a good case for doing this. */
3380 if ((GET_CODE (XEXP (set
, 0)) == REG
3381 || GET_CODE (XEXP (set
, 0)) == MEM
)
3382 && (GET_CODE (XEXP (set
, 1)) == ASHIFT
3383 || GET_CODE (XEXP (set
, 1)) == ASHIFTRT
3384 || GET_CODE (XEXP (set
, 1)) == LSHIFTRT
3385 || GET_CODE (XEXP (set
, 1)) == XOR
3386 || GET_CODE (XEXP (set
, 1)) == IOR
3387 || GET_CODE (XEXP (set
, 1)) == AND
3388 || GET_CODE (XEXP (set
, 1)) == PLUS
3389 || GET_CODE (XEXP (set
, 1)) == MINUS
3390 || GET_CODE (XEXP (set
, 1)) == MULT
))
3395 next_insn
= next_nonnote_insn (insn
);
3399 if (GET_CODE (next_insn
) != INSN
)
3402 set2
= ((GET_CODE (PATTERN (next_insn
)) == SET
)
3403 ? PATTERN (next_insn
) : NULL_RTX
);
3404 if (set2
== NULL_RTX
)
3407 if ((GET_CODE (XEXP (XEXP (set
, 1), 0)) == REG
3408 || GET_CODE (XEXP (XEXP (set
, 1), 0)) == MEM
)
3409 && rtx_equal_p (XEXP (set2
, 0), XEXP (XEXP (set
, 1), 0))
3410 && rtx_equal_p (XEXP (set2
, 1), XEXP (set
, 0)))
3415 b_insn
= gen_rtx_SET (VOIDmode
,
3416 XEXP (XEXP (set
, 1), 0),
3417 gen_rtx_fmt_ee (GET_CODE (XEXP (set
, 1)),
3418 GET_MODE (XEXP (set
, 0)),
3419 XEXP (XEXP (set
, 1), 0),
3420 XEXP (XEXP (set
, 1), 1)));
3422 emit_insn_before (b_insn
, insn
);
3423 b_insn
= gen_rtx_SET (GET_MODE (XEXP (set
, 0)), XEXP (set
, 0),
3424 XEXP (XEXP (set
, 1), 0));
3425 next2_insn
= emit_insn_before (b_insn
, insn
);
3427 delete_insn (next_insn
);
3432 /* Having tried with one operand of the expression, now, if
3433 appropriate, try to do the same thing with the second operand.
3434 Of course there are fewer operations that can match here
3435 because they must be commutative. */
3436 if (GET_RTX_CLASS (GET_CODE (XEXP (set
, 1))) == RTX_COMM_ARITH
3437 && (GET_CODE (XEXP (XEXP (set
, 1), 1)) == REG
3438 || GET_CODE (XEXP (XEXP (set
, 1), 1)) == MEM
)
3439 && rtx_equal_p (XEXP (set2
, 0), XEXP (XEXP (set
, 1), 1))
3440 && rtx_equal_p (XEXP (set2
, 1), XEXP (set
, 0)))
3446 /* Try to ensure that we put things in a canonical form. */
3447 swap_args
= (GET_CODE (XEXP (XEXP (set
, 1), 0)) == REG
3448 || GET_CODE (XEXP (XEXP (set
, 1), 0)) == MEM
);
3449 rtx_ee
= gen_rtx_fmt_ee (GET_CODE (XEXP (set
, 1)),
3450 GET_MODE (XEXP (set
, 0)),
3451 XEXP (XEXP (set
, 1), swap_args
? 1 : 0),
3452 XEXP (XEXP (set
, 1),
3453 swap_args
? 0 : 1));
3455 emit_insn_before (gen_rtx_SET (VOIDmode
,
3456 XEXP (XEXP (set
, 1), 1),
3459 next2_insn
= emit_insn_before (gen_rtx_SET
3460 (GET_MODE (XEXP (set
, 0)),
3462 XEXP (XEXP (set
, 1), 1)),
3465 delete_insn (next_insn
);
3472 /* Replace and recurse until we've tried QImode pieces! */
3475 mdr_pres_replace_and_recurse (orig
, with
, insn
)
3480 enum machine_mode new_mode
;
3482 validate_replace_rtx (orig
, with
, insn
);
3484 switch (GET_MODE (orig
))
3504 mdr_pres_replace_and_recurse (ip2k_get_low_half (orig
, new_mode
),
3505 ip2k_get_low_half (with
, new_mode
),
3507 mdr_pres_replace_and_recurse (ip2k_get_high_half (orig
, new_mode
),
3508 ip2k_get_high_half (with
, new_mode
),
3512 /* Assist the following function, mdr_propagate_reg_equivs(). */
3515 mdr_propagate_reg_equivs_sequence (first_insn
, orig
, equiv
)
3521 rtx try_equiv
= equiv
;
3523 /* First scan the RTL looking for anything else that might clobber what
3524 we're doing. If we find anything then we can't do the replacement. */
3525 for (try_insn
= next_nonnote_insn (first_insn
);
3526 try_insn
; try_insn
= next_nonnote_insn (try_insn
))
3530 if (GET_CODE (try_insn
) != JUMP_INSN
&& GET_CODE (try_insn
) != INSN
)
3533 pattern
= PATTERN (try_insn
);
3534 if (GET_CODE (pattern
) == PARALLEL
)
3538 for (j
= 0; j
< XVECLEN (pattern
, 0); j
++)
3540 rtx px
= XVECEXP (pattern
, 0, j
);
3542 if (GET_CODE (px
) == SET
)
3543 if (! ip2k_composite_xexp_not_uses_reg_p (XEXP (px
, 0),
3545 GET_MODE_SIZE (GET_MODE (orig
))))
3549 else if (GET_CODE (pattern
) == SET
)
3551 if (! ip2k_composite_xexp_not_uses_reg_p (XEXP (pattern
, 0),
3553 GET_MODE_SIZE (GET_MODE (orig
))))
3558 /* Once we've decided that we're safe to do the replacement then make the
3560 for (try_insn
= next_nonnote_insn (first_insn
); try_insn
;
3561 try_insn
= next_nonnote_insn (try_insn
))
3564 rtx new_equiv
= NULL_RTX
;
3566 if (GET_CODE (try_insn
) != JUMP_INSN
&& GET_CODE (try_insn
) != INSN
)
3572 set
= ((GET_CODE (PATTERN (try_insn
)) == SET
)
3573 ? PATTERN (try_insn
) : NULL_RTX
);
3574 if (set
== NULL_RTX
)
3577 /* We look for a special case of "push" operations screwing our
3578 register equivalence when it's based on a stack slot. We can
3579 track this one and replace the old equivalence expression with
3581 if (GET_CODE (XEXP (set
, 0)) == MEM
3582 && GET_CODE (XEXP (XEXP (set
, 0), 0)) == POST_DEC
3583 && REG_P (XEXP (XEXP (XEXP (set
, 0), 0), 0))
3584 && REGNO (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG_SP
)
3586 /* XXX - need to ensure that we can track this without going
3588 HOST_WIDE_INT disp
= (INTVAL (XEXP (XEXP (try_equiv
, 0), 1))
3589 + GET_MODE_SIZE (GET_MODE (XEXP (set
, 0))));
3590 new_equiv
= gen_rtx_MEM (GET_MODE (try_equiv
),
3591 gen_rtx_PLUS (Pmode
,
3592 gen_rtx_REG (HImode
, REG_SP
),
3596 /* The replacement process is somewhat complicated by the fact that we
3597 might be dealing with what were originally subregs and thus we have
3598 to replace parts of our original expression! */
3599 mdr_pres_replace_and_recurse (orig
, try_equiv
, try_insn
);
3601 if (new_equiv
!= NULL_RTX
)
3602 try_equiv
= new_equiv
;
3606 /* Try propagating register equivalences forwards. It may be that we can
3607 replace a register use with an equivalent expression that already
3608 holds the same value and thus allow one or more register loads to
3612 mdr_propagate_reg_equivs (first_insn
)
3618 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
3620 if (GET_CODE (insn
) != INSN
)
3623 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
3624 if (set
== NULL_RTX
)
3627 /* Have we found a stack slot equivalence for a register? */
3628 if (REG_P (XEXP (set
, 0))
3629 && REGNO (XEXP (set
, 0)) >= 0x88
3630 && GET_CODE (XEXP (set
, 1)) == MEM
3631 && GET_CODE (XEXP (XEXP (set
, 1), 0)) == PLUS
3632 && REG_P (XEXP (XEXP (XEXP (set
, 1), 0), 0))
3633 && REGNO (XEXP (XEXP (XEXP (set
, 1), 0), 0)) == REG_SP
3634 && find_reg_note (insn
, REG_EQUIV
, NULL_RTX
))
3636 mdr_propagate_reg_equivs_sequence (insn
, XEXP (set
, 0),
3642 /* Structure used to track jump targets. */
3644 struct dpre_jump_targets
3646 int target
; /* Is this a jump target? */
3647 int reach_count
; /* Number of ways we can reach this insn. */
3648 int touch_count
; /* Number of times we've touched this
3649 insns during scanning. */
3650 rtx dp_equiv
; /* DP-equivalence at this point. */
3653 struct dpre_jump_targets
*ip2k_dpre_jump_targets
;
3655 /* DP equivalence tracking used within DP reload elimination. */
3658 track_dp_reload (insn
, dp_current
, dp_current_ok
, modifying
)
3666 if (GET_CODE (insn
) != INSN
)
3668 *dp_current
= NULL_RTX
;
3672 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
3673 if (set
== NULL_RTX
)
3675 *dp_current
= NULL_RTX
;
3679 /* If we're pushing a PLUS or MINUS then it's a win if we can replace
3680 an expression for which DP is equivalent with DP. This happens
3681 surprisingly often when we pass a pointer to a structure embedded
3682 within another structure. */
3683 if (*dp_current
!= NULL_RTX
3684 && GET_CODE (XEXP (set
, 0)) == MEM
3685 && GET_CODE (XEXP (XEXP (set
, 0), 0)) == POST_DEC
3686 && GET_CODE (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG
3687 && REGNO (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG_SP
3688 && (GET_CODE (XEXP (set
, 1)) == PLUS
3689 || GET_CODE (XEXP (set
, 1)) == MINUS
)
3690 && GET_CODE (*dp_current
) != SYMBOL_REF
3691 && GET_CODE (*dp_current
) != LABEL_REF
3692 && GET_CODE (*dp_current
) != CONST
)
3695 validate_replace_rtx (*dp_current
, gen_rtx_REG (HImode
, REG_DP
), insn
);
3698 /* Look for DP being modified. If it is, see if it's being changed
3699 to what it already is! */
3700 if (GET_CODE (XEXP (set
, 0)) == REG
3701 && REGNO (XEXP (set
, 0)) == REG_DP
3702 && GET_MODE (XEXP (set
, 0)) == HImode
)
3704 /* If this is an equivalence we can delete the new set operation. */
3705 if (*dp_current
!= NULL_RTX
3706 && rtx_equal_p (XEXP (set
, 1), *dp_current
))
3713 /* If we've not found an equivalence we can look for a special
3714 case where an operand of the expression that sets DP is
3715 already equivalent to DP and in that circumstance we simplify
3716 by replacing that expression with DP. */
3717 if (*dp_current
!= NULL_RTX
3718 && GET_CODE (*dp_current
) != SYMBOL_REF
3719 && GET_CODE (*dp_current
) != LABEL_REF
3720 && GET_CODE (*dp_current
) != CONST
3722 validate_replace_rtx (*dp_current
, XEXP (set
, 0), insn
);
3724 /* Assuming that we're not loading DP from something that uses DP
3725 itself then we mark the new equivalence for DP. If we did match
3726 DP then we can't re-use this one. */
3727 if (ip2k_xexp_not_uses_reg_p (XEXP (set
, 1), REG_DP
, 2))
3729 *dp_current
= XEXP (set
, 1);
3734 *dp_current
= NULL_RTX
;
3739 else if (GET_CODE (XEXP (set
, 0)) == REG
3740 && (REGNO (XEXP (set
, 0)) == REG_DPL
3741 || REGNO (XEXP (set
, 0)) == REG_DPH
))
3743 /* If we clobber part of DP then we've clobbered any equivalences! */
3744 *dp_current
= NULL_RTX
;
3747 else if (! ip2k_xexp_not_uses_reg_p (XEXP (set
, 0), REG_SP
, 2)
3748 && *dp_current
!= NULL_RTX
3749 && !ip2k_xexp_not_uses_reg_p (*dp_current
, REG_SP
, 2))
3751 /* We look for a special case of "push" operations screwing up the
3752 setting of DP when it's based on the stack. We can track this one
3753 and replace the old expression for DP with a new one. */
3754 if (GET_CODE (XEXP (set
, 0)) == MEM
3755 && GET_CODE (XEXP (XEXP (set
, 0), 0)) == POST_DEC
3756 && GET_CODE (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG
3757 && REGNO (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG_SP
3758 && GET_CODE (*dp_current
) == MEM
3759 && GET_CODE (XEXP (*dp_current
, 0)) == PLUS
)
3761 /* XXX - need to ensure that we can track this without going
3763 HOST_WIDE_INT disp
= (INTVAL (XEXP (XEXP (*dp_current
, 0), 1))
3764 + GET_MODE_SIZE (GET_MODE (XEXP (set
, 0))));
3765 *dp_current
= gen_rtx_MEM (HImode
,
3766 gen_rtx_PLUS (Pmode
,
3767 gen_rtx_REG (HImode
, REG_SP
),
3772 /* Now we look for writes to the stack. We can determine if these will
3773 affect the equivalence we're tracking for DP and if not then we can
3774 keep tracking it. */
3775 if (GET_CODE (XEXP (set
, 0)) == MEM
3776 && GET_CODE (*dp_current
) == MEM
)
3778 /* Look at the SP offsets and look for any overlaps. */
3779 int dp_cur_sp_offs
= INTVAL (XEXP (XEXP (*dp_current
, 0), 1));
3780 int set_sp_offs
= INTVAL (XEXP (XEXP (XEXP (set
, 0), 0), 1));
3782 if (abs (dp_cur_sp_offs
- set_sp_offs
) < 2)
3784 *dp_current
= NULL_RTX
;
3789 else if (GET_CODE (XEXP (set
, 0)) == REG
3790 && *dp_current
!= NULL_RTX
3791 && !ip2k_xexp_not_uses_reg_p (*dp_current
, REGNO (XEXP (set
, 0)),
3792 GET_MODE_SIZE (GET_MODE (XEXP (set
,
3795 /* If we've just clobbered all or part of a register reference that we
3796 were sharing for DP then we can't share it any more! */
3797 *dp_current
= NULL_RTX
;
3800 return dp_current_ok
;
3803 /* As part of the machine-dependent reorg we scan loads and reloads of
3804 DP to see where any are redundant. This does happens because we
3805 are able to subsequently transform things in interesting ways. Sometimes
3806 gcc also does unnecessary reloads too so we try to eliminate these too. */
3809 mdr_try_dp_reload_elim (first_insn
)
3813 struct dpre_jump_targets
*djt
;
3815 int incomplete_scan
;
3816 int last_incomplete_scan
;
3818 ip2k_dpre_jump_targets
3819 = (struct dpre_jump_targets
*) xcalloc (get_max_uid (),
3820 sizeof (struct dpre_jump_targets
));
3822 /* First we scan to build up a list of all CODE_LABEL insns and we work out
3823 how many different ways we can reach them. */
3824 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
3826 if (GET_CODE (insn
) == CODE_LABEL
)
3828 djt
= &ip2k_dpre_jump_targets
[INSN_UID (insn
)];
3830 djt
->reach_count
= LABEL_NUSES (insn
);
3831 djt
->touch_count
= 0;
3832 djt
->dp_equiv
= NULL_RTX
;
3833 if (! prev_nonnote_insn (insn
)
3834 || (prev_nonnote_insn (insn
)
3835 && GET_CODE (prev_nonnote_insn (insn
)) != BARRIER
))
3840 /* Next we scan all of the ways of reaching the code labels to see
3841 what the DP register is equivalent to as we reach them. If we find
3842 that they're the same then we keep noting the matched value. We
3843 iterate around this until we reach a convergence on DP equivalences
3844 at all code labels - we have to be very careful not to be too
3846 incomplete_scan
= -1;
3849 int dp_current_ok
= 0;
3850 last_incomplete_scan
= incomplete_scan
;
3851 dp_current
= NULL_RTX
;
3853 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
3855 /* If we have a code label then we need to see if we already know
3856 what the equivalence is at this point. If we do then we use it
3857 immediately, but if we don't then we have a special case to track
3858 when we hit a fallthrough-edge (label with no barrier preceding
3859 it). Any other accesses to the label must be from jump insns
3860 and so they're handled elsewhere. */
3861 if (GET_CODE (insn
) == CODE_LABEL
)
3863 djt
= &ip2k_dpre_jump_targets
[INSN_UID (insn
)];
3865 /* If we're fully characterized the use the equivalence. */
3866 if (djt
->touch_count
== djt
->reach_count
)
3868 dp_current
= djt
->dp_equiv
;
3873 /* If we have a known equivalence for DP as we reach the
3874 fallthrough-edge then track this into the code label. */
3876 && (! prev_nonnote_insn (insn
)
3877 || (prev_nonnote_insn (insn
)
3878 && GET_CODE (prev_nonnote_insn (insn
)) != BARRIER
)))
3880 if (djt
->touch_count
== 0)
3881 djt
->dp_equiv
= dp_current
;
3883 if (djt
->touch_count
< djt
->reach_count
)
3886 if (! rtx_equal_p (djt
->dp_equiv
, dp_current
))
3888 /* When we definitely know that we can't form an
3889 equivalence for DP here we must clobber anything
3890 that we'd started to track too. */
3891 djt
->dp_equiv
= NULL_RTX
;
3892 dp_current
= NULL_RTX
;
3898 /* If we've not completely characterized this code label then
3899 be cautious and assume that we don't know what DP is
3901 if (djt
->touch_count
< djt
->reach_count
)
3903 dp_current
= NULL_RTX
;
3910 /* If we've hit a jump insn then we look for either an address
3911 vector (jump table) or for jump label references. */
3912 if (GET_CODE (insn
) == JUMP_INSN
)
3914 /* Don't attempt to track here if we don't have a known
3915 equivalence for DP at this point. */
3918 rtx pat
= PATTERN (insn
);
3919 if (GET_CODE (pat
) == ADDR_VEC
)
3922 int len
= XVECLEN (pat
, 0);
3924 for (i
= 0; i
< len
; i
++)
3926 rtx vec_insn
= XEXP (XVECEXP (pat
, 0, i
), 0);
3927 djt
= &ip2k_dpre_jump_targets
[INSN_UID (vec_insn
)];
3929 if (djt
->touch_count
== 0)
3930 djt
->dp_equiv
= dp_current
;
3932 if (djt
->touch_count
< djt
->reach_count
)
3935 if (! rtx_equal_p (djt
->dp_equiv
, dp_current
))
3936 djt
->dp_equiv
= NULL_RTX
;
3940 else if (JUMP_LABEL (insn
))
3942 rtx j_insn
= JUMP_LABEL (insn
);
3943 djt
= &ip2k_dpre_jump_targets
[INSN_UID (j_insn
)];
3945 if (djt
->touch_count
== 0)
3946 djt
->dp_equiv
= dp_current
;
3948 if (djt
->touch_count
< djt
->reach_count
)
3951 if (! rtx_equal_p (djt
->dp_equiv
, dp_current
))
3952 djt
->dp_equiv
= NULL_RTX
;
3960 /* Anything other than a code labal or jump arrives here.
3961 We try and track DP, but sometimes we might not be able to. */
3962 dp_current_ok
= track_dp_reload (insn
, &dp_current
,
3966 /* When we're looking to see if we've finished we count the number of
3967 paths through the code labels where we weren't able to definitively
3969 This number is used to see if we're converging on a solution.
3970 If this hits zero then we've fully converged, but if this stays the
3971 same as last time then we probably can't make any further
3973 incomplete_scan
= 0;
3974 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
3976 if (GET_CODE (insn
) == CODE_LABEL
)
3978 djt
= &ip2k_dpre_jump_targets
[INSN_UID (insn
)];
3979 if (djt
->touch_count
!= djt
->reach_count
)
3981 incomplete_scan
+= (djt
->reach_count
- djt
->touch_count
);
3982 djt
->dp_equiv
= NULL_RTX
;
3983 djt
->touch_count
= 0;
3988 while (incomplete_scan
&& incomplete_scan
!= last_incomplete_scan
);
3990 /* Finally we scan the whole function and run DP elimination. When we hit
3991 a CODE_LABEL we pick up any stored equivalence since we now know that
3992 every path to this point entered with DP holding the same thing! If
3993 we subsequently have a reload that matches then we can eliminate it. */
3994 dp_current
= NULL_RTX
;
3995 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
3997 if (GET_CODE (insn
) == JUMP_INSN
)
4000 if (GET_CODE (insn
) == CODE_LABEL
)
4002 djt
= &ip2k_dpre_jump_targets
[INSN_UID (insn
)];
4003 dp_current
= djt
->dp_equiv
;
4007 track_dp_reload (insn
, &dp_current
, 1, 1);
4010 free (ip2k_dpre_jump_targets
);
4013 /* As part of the machine-dependent reorg we look for reloads of DP
4014 that we can move to earlier points within the file.
4015 Moving these out of the way allows more peepholes to match. */
4018 mdr_try_move_dp_reload (first_insn
)
4025 /* Don't try to match the first instruction because we can't move it
4027 orig_first
= first_insn
;
4028 first_insn
= next_nonnote_insn (first_insn
);
4030 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
4032 if (GET_CODE (insn
) != INSN
)
4035 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
4036 if (set
== NULL_RTX
)
4039 /* Look for DP being loaded. When we find this we start a rewind
4040 scan looking for possible positions to move this to. */
4041 if (GET_CODE (XEXP (set
, 0)) == REG
4042 && REGNO (XEXP (set
, 0)) == REG_DP
4043 && GET_MODE (XEXP (set
, 0)) == HImode
)
4046 rtx try_insn
= insn
;
4055 /* For now we do the *really* simple version of things and only
4056 attempt to move the load of DP if it's very safe to do so. */
4057 rewind
= prev_nonnote_insn (try_insn
);
4058 if (rewind
!= orig_first
&& rewind
!= NULL_RTX
4059 && GET_CODE (rewind
) == INSN
)
4061 check
= ((GET_CODE (PATTERN (rewind
)) == SET
)
4062 ? PATTERN (rewind
) : NULL_RTX
);
4063 if (check
!= NULL_RTX
4064 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (check
, 0))
4065 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (check
, 1)))
4067 if (GET_CODE (XEXP (check
, 0)) == REG
4068 && REGNO (XEXP (check
, 0)) != REG_DPH
4069 && REGNO (XEXP (check
, 0)) != REG_DPL
4070 && (ip2k_composite_xexp_not_uses_reg_p
4071 (XEXP (check
, 1), REG_DP
, 2))
4072 && (ip2k_composite_xexp_not_uses_reg_p
4074 REGNO (XEXP (check
, 0)),
4075 GET_MODE_SIZE (GET_MODE (XEXP (check
, 0))))))
4077 emit_insn_before (set
, rewind
);
4078 if (try_insn
== insn
)
4079 insn
= prev_nonnote_insn (insn
);
4080 delete_insn (try_insn
);
4081 try_insn
= prev_nonnote_insn (rewind
);
4084 else if (GET_CODE (XEXP (set
, 1)) == REG
4085 && ip2k_composite_xexp_not_uses_reg_p (XEXP (check
, 1), REG_DP
, 2)
4086 && ip2k_composite_xexp_not_uses_reg_p (XEXP (check
, 0), REG_DP
, 2)
4087 && ip2k_composite_xexp_not_uses_reg_p (XEXP (check
, 0), REGNO (XEXP (set
, 1)),
4088 GET_MODE_SIZE (GET_MODE (XEXP (set
, 1)))))
4090 emit_insn_before (set
, rewind
);
4091 if (try_insn
== insn
)
4092 insn
= prev_nonnote_insn (insn
);
4093 delete_insn (try_insn
);
4094 try_insn
= prev_nonnote_insn (rewind
);
4100 while (try_again
&& try_insn
);
4104 #endif /* IP2K_MD_REORG_PASS */
4106 /* Look to see if the expression, x, can have any stack references offset by
4107 a fixed constant, offset. If it definitely can then returns nonzero. */
4110 ip2k_check_can_adjust_stack_ref (rtx x
, int offset
)
4112 if (ARITHMETIC_P (x
))
4113 return (ip2k_check_can_adjust_stack_ref (XEXP (x
, 0), offset
)
4114 && ip2k_check_can_adjust_stack_ref (XEXP (x
, 1), offset
));
4117 return ip2k_check_can_adjust_stack_ref (XEXP (x
, 0), offset
);
4119 switch (GET_CODE (x
))
4122 return (REGNO (x
) != REG_SPH
&& REGNO (x
) != REG_SPL
);
4125 if (GET_CODE (XEXP (x
, 0)) != PLUS
)
4128 if (GET_CODE (XEXP (XEXP (x
, 0), 0)) != REG
)
4131 if (REGNO (XEXP (XEXP (x
, 0), 0)) != REG_SP
)
4134 /* We can't allow this if the adjustment will create an
4136 return (INTVAL (XEXP (XEXP (x
, 0), 1))
4137 + offset
<= (128 - 2 * GET_MODE_SIZE (GET_MODE (x
))));
4151 /* Adjusts all of the stack references in the expression pointed to by x by
4155 ip2k_adjust_stack_ref (rtx
*x
, int offset
)
4157 if (ARITHMETIC_P (*x
))
4159 ip2k_adjust_stack_ref (&XEXP (*x
, 0), offset
);
4160 ip2k_adjust_stack_ref (&XEXP (*x
, 1), offset
);
4166 ip2k_adjust_stack_ref (&XEXP (*x
, 0), offset
);
4170 switch (GET_CODE (*x
))
4173 if (GET_CODE (XEXP (*x
, 0)) != PLUS
)
4176 if (GET_CODE (XEXP (XEXP (*x
, 0), 0)) != REG
)
4179 if (REGNO (XEXP (XEXP (*x
, 0), 0)) != REG_SP
)
4183 XEXP (XEXP (*x
, 0), 1) = GEN_INT (INTVAL (XEXP (XEXP (*x
, 0), 1))
4192 #ifdef IP2K_MD_REORG_PASS
4193 /* As part of the machine-dependent reorg we look to move push instructions
4194 to earlier points within the file. Moving these out of the way allows more
4195 peepholes to match. */
4198 mdr_try_move_pushes (first_insn
)
4205 /* Don't try to match the first instruction because we can't move
4207 orig_first
= first_insn
;
4208 first_insn
= next_nonnote_insn (first_insn
);
4210 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
4212 if (GET_CODE (insn
) != INSN
)
4215 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
4216 if (set
== NULL_RTX
)
4219 /* Have we found a push instruction? */
4220 if (GET_CODE (XEXP (set
, 0)) == MEM
4221 && GET_CODE (XEXP (XEXP (set
, 0), 0)) == POST_DEC
4222 && GET_CODE (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG
4223 && REGNO (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG_SP
4224 && GET_CODE (XEXP (set
, 1)) == REG
)
4226 rtx try_insn
= insn
;
4227 unsigned int regno
= REGNO (XEXP (set
, 1));
4228 int reg_range
= GET_MODE_SIZE (GET_MODE (XEXP (set
, 1)));
4235 rewind
= prev_nonnote_insn (try_insn
);
4236 if (rewind
== orig_first
|| rewind
== NULL_RTX
4237 || GET_CODE (rewind
) != INSN
)
4240 check
= (GET_CODE (PATTERN (rewind
)) == SET
) ? PATTERN (rewind
) : NULL_RTX
;
4241 if (check
== NULL_RTX
)
4244 if (! ip2k_check_can_adjust_stack_ref (XEXP (check
, 0),
4246 || ! ip2k_check_can_adjust_stack_ref (XEXP (check
, 1),
4250 /* If we've hit another push instruction we can't go any
4252 if (GET_CODE (XEXP (check
, 0)) == MEM
4253 && GET_CODE (XEXP (XEXP (check
, 0), 0)) == POST_DEC
4254 && GET_CODE (XEXP (XEXP (XEXP (check
, 0), 0), 0)) == REG
4255 && REGNO (XEXP (XEXP (XEXP (check
, 0), 0), 0)) == REG_SP
)
4258 /* If this is a register move then check that it doesn't clobber
4259 SP or any part of the instruction we're trying to move. */
4260 if (GET_CODE (XEXP (check
, 0)) == REG
)
4262 unsigned int check_reg
= REGNO (XEXP (check
, 0));
4263 int check_reg_range
= GET_MODE_SIZE (GET_MODE (XEXP (check
,
4266 /* If we have a special case where what we want to push is
4267 being loaded by this "clobbering" insn then we can just
4268 push what is being used to load us and then do the load.
4269 This may seem a little odd, but we may subsequently be
4270 able to merge the load with another instruction as it
4271 may only be used once now! Note though that we
4272 specifically don't try this if the expression being
4273 loaded is an HImode MEM using IP. */
4274 if (check_reg
== regno
4275 && check_reg_range
== reg_range
4276 && ((GET_CODE (XEXP (check
, 1)) == REG
4277 || (GET_CODE (XEXP (check
, 1)) == MEM
4278 && (GET_MODE (XEXP (check
, 1)) != HImode
4279 || ip2k_xexp_not_uses_reg_for_mem (XEXP (check
, 1), REG_IP
))))))
4281 switch (check_reg_range
)
4284 emit_insn_before (gen_movqi (XEXP (set
, 0),
4287 delete_insn (try_insn
);
4291 emit_insn_before (gen_movhi (XEXP (set
, 0),
4294 delete_insn (try_insn
);
4298 emit_insn_before (gen_movsi (XEXP (set
, 0),
4301 delete_insn (try_insn
);
4305 emit_insn_before (gen_movdi (XEXP (set
, 0),
4308 delete_insn (try_insn
);
4312 ip2k_adjust_stack_ref (&XEXP (check
, 0), reg_range
);
4313 ip2k_adjust_stack_ref (&XEXP (check
, 1), reg_range
);
4314 try_insn
= prev_nonnote_insn (rewind
);
4315 /* XXX - should be a continue? */
4319 if ((check_reg
== REG_SPL
)
4320 || (check_reg
== REG_SPH
)
4321 || (((regno
<= check_reg
)
4322 && (regno
+ reg_range
- 1) >= check_reg
)
4323 || ((regno
<= (check_reg
+ check_reg_range
- 1))
4324 && ((regno
+ reg_range
- 1)
4325 >= (check_reg
+ check_reg_range
- 1)))))
4329 emit_insn_before (set
, rewind
);
4330 delete_insn (try_insn
);
4331 ip2k_adjust_stack_ref (&XEXP (check
, 0), reg_range
);
4332 ip2k_adjust_stack_ref (&XEXP (check
, 1), reg_range
);
4333 try_insn
= prev_nonnote_insn (rewind
);
4339 /* Assist the following function, mdr_try_propagate_clr(). */
4342 mdr_try_propagate_clr_sequence (first_insn
, regno
)
4348 for (try_insn
= next_nonnote_insn (first_insn
); try_insn
;
4349 try_insn
= next_nonnote_insn (try_insn
))
4351 rtx new_insn
= NULL_RTX
;
4354 if (GET_CODE (try_insn
) == JUMP_INSN
)
4357 if (GET_CODE (try_insn
) != INSN
)
4360 set2
= ((GET_CODE (PATTERN (try_insn
)) == SET
)
4361 ? PATTERN (try_insn
) : NULL_RTX
);
4362 if (set2
== NULL_RTX
)
4365 if (GET_CODE (XEXP (set2
, 1)) == AND
4366 && ((GET_CODE (XEXP (XEXP (set2
, 1), 0)) == REG
4367 && REGNO (XEXP (XEXP (set2
, 1), 0)) == regno
)
4368 || (GET_CODE (XEXP (XEXP (set2
, 1), 1)) == REG
4369 && REGNO (XEXP (XEXP (set2
, 1), 1)) == regno
)))
4371 rtx remove_insn
= try_insn
;
4372 try_insn
= emit_insn_before (gen_rtx_SET (QImode
, XEXP (set2
, 0),
4373 const0_rtx
), try_insn
);
4374 delete_insn (remove_insn
);
4376 else if (GET_CODE (XEXP (set2
, 1)) == IOR
4377 && GET_CODE (XEXP (XEXP (set2
, 1), 0)) == REG
4378 && REGNO (XEXP (XEXP (set2
, 1), 0)) == regno
)
4380 rtx remove_insn
= try_insn
;
4381 try_insn
= emit_insn_before (gen_rtx_SET (QImode
, XEXP (set2
, 0),
4382 XEXP (XEXP (set2
, 1), 1)),
4384 delete_insn (remove_insn
);
4386 else if (GET_CODE (XEXP (set2
, 1)) == IOR
4387 && GET_CODE (XEXP (XEXP (set2
, 1), 1)) == REG
4388 && REGNO (XEXP (XEXP (set2
, 1), 1)) == regno
)
4390 rtx remove_insn
= try_insn
;
4391 try_insn
= emit_insn_before (gen_rtx_SET (QImode
, XEXP (set2
, 0),
4392 XEXP (XEXP (set2
, 1), 0)),
4394 delete_insn (remove_insn
);
4396 else if (GET_CODE (XEXP (set2
, 1)) == XOR
4397 && GET_CODE (XEXP (XEXP (set2
, 1), 0)) == REG
4398 && REGNO (XEXP (XEXP (set2
, 1), 0)) == regno
)
4400 rtx remove_insn
= try_insn
;
4401 try_insn
= emit_insn_before (gen_rtx_SET (QImode
, XEXP (set2
, 0),
4402 XEXP (XEXP (set2
, 1), 1)),
4404 delete_insn (remove_insn
);
4406 else if (GET_CODE (XEXP (set2
, 1)) == XOR
4407 && GET_CODE (XEXP (XEXP (set2
, 1), 1)) == REG
4408 && REGNO (XEXP (XEXP (set2
, 1), 1)) == regno
)
4410 rtx remove_insn
= try_insn
;
4411 try_insn
= emit_insn_before (gen_rtx_SET (QImode
, XEXP (set2
, 0),
4412 XEXP (XEXP (set2
, 1), 0)),
4414 delete_insn (remove_insn
);
4417 if (GET_CODE (XEXP (set2
, 0)) == REG
)
4419 int reg2_range
= GET_MODE_SIZE (GET_MODE (XEXP (set2
, 0)));
4420 unsigned int regno2
= REGNO (XEXP (set2
, 0));
4424 && GET_CODE (XEXP (set2
, 1)) == CONST_INT
)
4426 int iv
= INTVAL (XEXP (set2
, 1));
4429 if (iv
== 1 || iv
== -1)
4431 new_insn
= gen_rtx_SET (QImode
, XEXP (set2
, 0),
4432 gen_rtx_PLUS (QImode
, XEXP (set2
, 0),
4434 new_insn
= emit_insn_before (new_insn
, try_insn
);
4435 delete_insn (try_insn
);
4436 try_insn
= new_insn
;
4441 if ((regno
>= regno2
) && (regno
<= regno2
+ reg2_range
- 1))
4444 if (GET_CODE (XEXP (set2
, 1)) == REG
4445 && REGNO (XEXP (set2
, 1)) == regno
)
4447 new_insn
= emit_insn_before (gen_rtx_SET (QImode
,
4451 delete_insn (try_insn
);
4452 try_insn
= new_insn
;
4456 if (GET_CODE (XEXP (set2
, 0)) == CC0
)
4458 if (GET_CODE (XEXP (set2
, 1)) == REG
4459 && GET_MODE_SIZE (GET_MODE (XEXP (set2
, 1))) == 2
4460 && REGNO (XEXP (set2
, 1)) == regno
)
4462 new_insn
= gen_rtx_SET (VOIDmode
, gen_rtx_CC0 (VOIDmode
),
4463 gen_rtx_REG(QImode
, regno
+ 1));
4464 new_insn
= emit_insn_before (new_insn
, try_insn
);
4466 else if (GET_CODE (XEXP (set2
, 1)) == COMPARE
4467 && GET_CODE (XEXP (XEXP (set2
, 1), 0)) == REG
4468 && GET_MODE_SIZE (GET_MODE (XEXP (XEXP (set2
, 1), 0))) == 2
4469 && REGNO (XEXP (XEXP (set2
, 1), 0)) == regno
4470 && GET_CODE (XEXP (XEXP (set2
, 1), 1)) == CONST_INT
4471 && INTVAL (XEXP (XEXP (set2
, 1), 1)) >= 0
4472 && INTVAL (XEXP (XEXP (set2
, 1), 1)) < 256)
4474 new_insn
= gen_rtx_SET (VOIDmode
, cc0_rtx
,
4475 gen_rtx_COMPARE(QImode
,
4476 gen_rtx_REG (QImode
,
4478 XEXP (XEXP (set2
, 1),
4480 new_insn
= emit_insn_before (new_insn
, try_insn
);
4483 /* If we have inserted a replacement for a CC0 setter operation
4484 then we need to delete the old one. */
4485 if (new_insn
!= NULL_RTX
)
4487 delete_insn (try_insn
);
4488 try_insn
= new_insn
;
4490 /* Now as we know that we have just done an unsigned compare
4491 (remember we were zero-extended by the clr!) we also know
4492 that we don't need a signed jump insn. If we find that
4493 our next isns is a signed jump then make it unsigned! */
4494 if (GET_CODE (next_nonnote_insn (try_insn
)) == JUMP_INSN
)
4498 try_insn
= next_nonnote_insn (try_insn
);
4499 set3
= ((GET_CODE (PATTERN (try_insn
)) == SET
)
4500 ? PATTERN (try_insn
) : NULL_RTX
);
4501 if (set3
== NULL_RTX
)
4504 /* If we discover that our jump target is only accessible
4505 from here then we can continue our "clr" propagation to
4507 if (LABEL_NUSES (JUMP_LABEL (try_insn
)) == 1)
4508 mdr_try_propagate_clr_sequence (JUMP_LABEL (try_insn
),
4511 if (GET_CODE (XEXP (set3
, 0)) == PC
4512 && GET_CODE (XEXP (set3
, 1)) == IF_THEN_ELSE
4513 && (GET_CODE (XEXP (XEXP (set3
, 1), 0)) == GT
4514 || GET_CODE (XEXP (XEXP (set3
, 1), 0)) == GE
4515 || GET_CODE (XEXP (XEXP (set3
, 1), 0)) == LT
4516 || GET_CODE (XEXP (XEXP (set3
, 1), 0)) == LE
)
4517 && GET_CODE (XEXP (XEXP (XEXP (set3
, 1), 0), 0)) == CC0
4518 && (GET_CODE (XEXP (XEXP (XEXP (set3
, 1), 0), 1))
4520 && GET_CODE (XEXP (XEXP (set3
, 1), 1)) == LABEL_REF
4521 && GET_CODE (XEXP (XEXP (set3
, 1), 2)) == PC
)
4527 /* Replace our old conditional jump with a new one that
4528 does the unsigned form of what was previously a
4529 signed comparison. */
4530 code
= GET_CODE (XEXP (XEXP (set3
, 1), 0));
4531 cmp
= gen_rtx_fmt_ee ((code
== GT
4535 : (code
== LT
? LTU
: LEU
))),
4537 XEXP (XEXP (XEXP (set3
, 1), 0), 0),
4538 XEXP (XEXP (XEXP (set3
, 1), 0),
4541 = gen_rtx_SET (GET_MODE (set3
),
4543 gen_rtx_IF_THEN_ELSE
4544 (GET_MODE (XEXP (set3
, 1)), cmp
,
4545 XEXP (XEXP (set3
, 1), 1),
4546 XEXP (XEXP (set3
, 1), 2)));
4547 new_insn
= emit_jump_insn_before (new_if
, try_insn
);
4548 LABEL_NUSES (JUMP_LABEL (try_insn
))++;
4549 delete_insn (try_insn
);
4550 try_insn
= new_insn
;
4555 else if (GET_CODE (XEXP (set2
, 1)) == PLUS
4556 && GET_CODE (XEXP (XEXP (set2
, 1), 0)) == REG
4557 && GET_MODE_SIZE (GET_MODE (XEXP (XEXP (set2
, 1), 0))) == 2
4558 && REGNO (XEXP (XEXP (set2
, 1), 0)) == regno
4559 && (GET_CODE (XEXP (XEXP (set2
, 1), 1)) == REG
4560 || GET_CODE (XEXP (XEXP (set2
, 1), 1)) == MEM
4561 || GET_CODE (XEXP (XEXP (set2
, 1), 1)) == CONST_INT
4562 || GET_CODE (XEXP (XEXP (set2
, 1), 1)) == CONST
4563 || GET_CODE (XEXP (XEXP (set2
, 1), 1)) == SYMBOL_REF
))
4565 rtx extend
= gen_rtx_ZERO_EXTEND (HImode
,
4566 gen_rtx_REG (QImode
, regno
+ 1));
4567 new_insn
= gen_rtx_SET (HImode
, XEXP (set2
, 0),
4568 gen_rtx_PLUS (HImode
, extend
,
4569 XEXP (XEXP (set2
, 1), 1)));
4570 new_insn
= emit_insn_before (new_insn
, try_insn
);
4571 delete_insn (try_insn
);
4572 try_insn
= new_insn
;
4574 else if (GET_CODE (XEXP (set2
, 1)) == PLUS
4575 && GET_CODE (XEXP (XEXP (set2
, 1), 1)) == REG
4576 && GET_MODE_SIZE (GET_MODE (XEXP (XEXP (set2
, 1), 1))) == 2
4577 && REGNO (XEXP (XEXP (set2
, 1), 1)) == regno
4578 && (GET_CODE (XEXP (XEXP (set2
, 1), 0)) == REG
4579 || GET_CODE (XEXP (XEXP (set2
, 1), 0)) == MEM
4580 || GET_CODE (XEXP (XEXP (set2
, 1), 0)) == CONST_INT
4581 || GET_CODE (XEXP (XEXP (set2
, 1), 0)) == CONST
4582 || GET_CODE (XEXP (XEXP (set2
, 1), 0)) == SYMBOL_REF
))
4584 rtx t_src
= gen_rtx_PLUS (HImode
,
4585 gen_rtx_ZERO_EXTEND (HImode
,
4586 gen_rtx_REG (QImode
,
4589 XEXP (XEXP (set2
, 1), 0));
4590 new_insn
= emit_insn_before (gen_rtx_SET (HImode
, XEXP (set2
, 0),
4593 delete_insn (try_insn
);
4594 try_insn
= new_insn
;
4599 /* One of the things that can quite often happen with an 8-bit CPU is that
4600 we end up clearing the MSByte of a 16-bit value. Unfortunately, all too
4601 often gcc doesn't have any way to realize that only half of the value is
4602 useful and ends up doing more work than it should. We scan for such
4603 occurrences here, track them and reduce compare operations to a smaller
4604 size where possible.
4606 Note that this is somewhat different to move propagation as we may
4607 actually change some instruction patterns when we're doing this whereas
4608 move propagation is just about doing a search and replace. */
4611 mdr_try_propagate_clr (first_insn
)
4617 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
4619 if (GET_CODE (insn
) != INSN
)
4622 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
4623 if (set
== NULL_RTX
)
4626 /* Have we found a "clr" instruction? */
4627 if (GET_CODE (XEXP (set
, 0)) == REG
4628 && GET_CODE (XEXP (set
, 1)) == CONST_INT
4629 && GET_MODE_SIZE (GET_MODE (XEXP (set
, 0))) == 1
4630 && INTVAL (XEXP (set
, 1)) == 0)
4632 mdr_try_propagate_clr_sequence (insn
, REGNO (XEXP (set
, 0)));
4636 #endif /* IP2K_MD_REORG_PASS */
4638 /* Look to see if the expression, x, does not make any memory references
4639 via the specified register. This is very conservative and only returns
4640 nonzero if we definitely don't have such a memory ref. */
4643 ip2k_xexp_not_uses_reg_for_mem (rtx x
, unsigned int regno
)
4646 regno
&= 0xfffffffe;
4648 switch (GET_CODE (x
))
4654 if ((GET_CODE (XEXP (x
, 0)) == PLUS
4655 && GET_CODE (XEXP (XEXP (x
, 0), 0)) == REG
4656 && REGNO (XEXP (XEXP (x
, 0), 0)) == regno
)
4657 || (GET_CODE (XEXP (x
, 0)) == REG
4658 && REGNO (XEXP (x
, 0)) == regno
))
4673 if (GET_RTX_CLASS (GET_CODE (x
)) == RTX_BITFIELD_OPS
)
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
)
4676 && ip2k_xexp_not_uses_reg_for_mem (XEXP (x
, 2), regno
));
4679 return (ip2k_xexp_not_uses_reg_for_mem (XEXP (x
, 0), regno
)
4680 && ip2k_xexp_not_uses_reg_for_mem (XEXP (x
, 1), regno
));
4683 || GET_RTX_CLASS (GET_CODE (x
)) == '3')
4684 return ip2k_xexp_not_uses_reg_for_mem (XEXP (x
, 0), regno
);
4690 #ifdef IP2K_MD_REORG_PASS
4691 /* Assist the following function, mdr_try_propagate_move(). */
4694 mdr_try_propagate_move_sequence (first_insn
, orig
, equiv
)
4701 for (try_insn
= next_nonnote_insn (first_insn
); try_insn
;
4702 try_insn
= next_nonnote_insn (try_insn
))
4706 rtx new_equiv
= NULL_RTX
;
4708 if (GET_CODE (try_insn
) != JUMP_INSN
&& GET_CODE (try_insn
) != INSN
)
4711 set
= single_set (try_insn
);
4712 if (set
== NULL_RTX
)
4715 range
= MAX (GET_MODE_SIZE (GET_MODE (equiv
)),
4716 GET_MODE_SIZE (GET_MODE (XEXP (set
, 0))));
4718 if (GET_CODE (equiv
) == REG
4719 && REGNO (equiv
) == REG_W
4720 && (recog_memoized (try_insn
) < 0
4721 || get_attr_clobberw (try_insn
) != CLOBBERW_NO
)
4722 && (! (GET_CODE (XEXP (set
, 0)) == REG
4723 && REGNO (XEXP (set
, 0)) == REG_W
4724 && rtx_equal_p (XEXP (set
, 1), orig
))))
4726 else if (GET_CODE (XEXP (set
, 0)) == REG
4727 && (REGNO (XEXP (set
, 0)) == REG_SP
4728 || ! ip2k_xexp_not_uses_reg_p (equiv
, REGNO (XEXP (set
, 0)),
4730 || ! ip2k_xexp_not_uses_reg_p (orig
, REGNO (XEXP (set
, 0)),
4732 && ! rtx_equal_p (equiv
, XEXP (set
, 0))
4733 && ! rtx_equal_p (orig
, XEXP (set
, 0)))
4735 else if (GET_CODE (orig
) == REG
4736 && (REGNO (orig
) == REG_IPL
4737 || REGNO (orig
) == REG_IPH
4738 || REGNO (orig
) == REG_DPL
4739 || REGNO (orig
) == REG_DPH
)
4740 && (! ip2k_xexp_not_uses_reg_for_mem (XEXP (set
, 0),
4742 || ! ip2k_xexp_not_uses_reg_for_mem (XEXP (set
, 1),
4745 else if (GET_CODE (XEXP (set
, 0)) == MEM
4746 && GET_CODE (equiv
) == MEM
)
4748 if (! ip2k_xexp_not_uses_reg_p (equiv
, REG_SP
, 2))
4750 if (! ip2k_xexp_not_uses_reg_p (XEXP (set
, 0), REG_SP
, 2))
4752 /* We look for a special case of "push" operations screwing
4753 our register equivalence when it's based on a stack slot.
4754 We can track this one and replace the old equivalence
4755 expression with a new one. */
4756 if (GET_CODE (XEXP (XEXP (set
, 0), 0)) == POST_DEC
4757 && GET_CODE (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG
4758 && REGNO (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG_SP
4759 && GET_CODE (XEXP (equiv
, 0)) == PLUS
4760 && REGNO (XEXP (XEXP (equiv
, 0), 0)) == REG_SP
)
4762 int md_size
= GET_MODE_SIZE (GET_MODE (XEXP (set
, 0)));
4763 int new_sp_offs
= INTVAL (XEXP (XEXP (equiv
, 0), 1))
4766 /* Don't allow an invalid stack pointer offset to be
4768 if (new_sp_offs
> (128 - 2 * md_size
))
4772 = gen_rtx_MEM (GET_MODE (equiv
),
4773 gen_rtx_PLUS (Pmode
,
4774 gen_rtx_REG (HImode
,
4776 GEN_INT (new_sp_offs
)));
4778 else if (! rtx_equal_p (equiv
, XEXP (set
, 0)))
4780 /* Look at the SP offsets and look for any overlaps. */
4781 int equiv_offs
= GET_CODE (XEXP (equiv
, 0)) == PLUS
4782 ? INTVAL (XEXP (XEXP (equiv
, 0), 1))
4785 = (GET_CODE (XEXP (XEXP (set
, 0), 0)) == PLUS
4786 ? INTVAL (XEXP (XEXP (XEXP (set
, 0), 0), 1))
4789 if (abs (equiv_offs
- set_offs
) < range
)
4795 if (! ip2k_xexp_not_uses_reg_p (equiv
, REG_IP
, 2))
4798 if (! ip2k_xexp_not_uses_reg_p (XEXP (set
, 0), REG_DP
, 2)
4799 && ! ip2k_xexp_not_uses_reg_p (equiv
, REG_DP
, 2)
4800 && ! rtx_equal_p (equiv
, XEXP (set
, 0)))
4802 /* Look at the DP offsets and look for any overlaps. */
4803 int equiv_offs
= GET_CODE (XEXP (equiv
, 0)) == PLUS
4804 ? INTVAL (XEXP (XEXP (equiv
, 0), 1))
4806 int set_offs
= GET_CODE (XEXP (XEXP (set
, 0), 0)) == PLUS
4807 ? INTVAL (XEXP (XEXP (XEXP (set
, 0), 0), 1))
4810 if (abs (equiv_offs
- set_offs
) < range
)
4815 validate_replace_rtx_subexp (orig
, equiv
, try_insn
, &XEXP (set
, 1));
4817 if (rtx_equal_p (equiv
, XEXP (set
, 0))
4818 || rtx_equal_p (orig
, XEXP (set
, 0)))
4821 if (new_equiv
!= NULL_RTX
)
4826 /* Try propagating move instructions forwards. It may be that we can
4827 replace a register use with an equivalent expression that already
4828 holds the same value and thus allow one or more register loads to
4832 mdr_try_propagate_move (first_insn
)
4838 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
4840 if (GET_CODE (insn
) != INSN
)
4843 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
4844 if (set
== NULL_RTX
)
4847 /* Have we found a simple move instruction? */
4848 if (GET_CODE (XEXP (set
, 0)) == REG
4849 && (REGNO (XEXP (set
, 0)) >= 0x80
4850 || REGNO (XEXP (set
, 0)) == REG_DPL
4851 || REGNO (XEXP (set
, 0)) == REG_DPH
4852 || REGNO (XEXP (set
, 0)) == REG_IPL
4853 || REGNO (XEXP (set
, 0)) == REG_IPH
)
4854 && ((GET_CODE (XEXP (set
, 1)) == REG
4855 && REGNO (XEXP (set
, 1)) != REG_SP
4856 && ip2k_xexp_not_uses_reg_p (XEXP (set
, 0),
4857 REGNO (XEXP (set
, 1)),
4858 GET_MODE_SIZE (GET_MODE (XEXP (set
,
4860 || (GET_CODE (XEXP (set
, 1)) == MEM
4861 && (ip2k_xexp_not_uses_reg_p (XEXP (set
, 1), REG_IP
, 2)
4862 || GET_MODE (XEXP (set
, 1)) == QImode
)
4863 && ((REGNO (XEXP (set
, 0)) != REG_DPH
4864 && REGNO (XEXP (set
, 0)) != REG_DPL
)
4865 || ip2k_xexp_not_uses_reg_p (XEXP (set
, 1), REG_DP
, 2)))
4866 || (GET_CODE (XEXP (set
, 1)) == CONST_INT
4867 && (GET_MODE (XEXP (set
, 0)) != QImode
4868 || INTVAL (XEXP (set
, 1)) != 0))
4869 || GET_CODE (XEXP (set
, 1)) == CONST_DOUBLE
4870 || GET_CODE (XEXP (set
, 1)) == CONST
4871 || GET_CODE (XEXP (set
, 1)) == SYMBOL_REF
))
4873 mdr_try_propagate_move_sequence (insn
, XEXP (set
, 0), XEXP (set
, 1));
4878 /* Try to remove redundant instructions. */
4881 mdr_try_remove_redundant_insns (first_insn
)
4886 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
4889 enum machine_mode mode
;
4891 HOST_WIDE_INT pattern
;
4894 if (GET_CODE (insn
) != INSN
)
4897 if (GET_CODE (PATTERN (insn
)) == CONST_INT
)
4899 /* We've found a dummy expression. */
4900 rtx remove_insn
= insn
;
4901 insn
= prev_nonnote_insn (insn
);
4902 delete_insn (remove_insn
);
4906 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
4907 if (set
== NULL_RTX
)
4910 mode
= GET_MODE (XEXP (set
, 0));
4911 md_size
= GET_MODE_SIZE (mode
);
4912 if ((md_size
< 1) || (md_size
> 4))
4916 for (i
= 0; i
< md_size
; i
++)
4922 if ((GET_CODE (XEXP (set
, 1)) == AND
4923 && GET_CODE (XEXP (XEXP (set
, 1), 1)) == CONST_INT
4924 && INTVAL (XEXP (XEXP (set
, 1), 1)) == pattern
)
4925 || ((GET_CODE (XEXP (set
, 1)) == IOR
4926 || GET_CODE (XEXP (set
, 1)) == XOR
)
4927 && GET_CODE (XEXP (XEXP (set
, 1), 1)) == CONST_INT
4928 && INTVAL (XEXP (XEXP (set
, 1), 1)) == 0x00))
4930 /* We've found an AND with all 1's, an XOR with all 0's or an
4932 rtx remove_insn
= insn
;
4934 /* Is it completely redundant or should it become a move insn? */
4935 if (! rtx_equal_p (XEXP (set
, 0), XEXP (XEXP (set
, 1), 0)))
4937 emit_insn_before (gen_rtx_SET (mode
,
4939 XEXP (XEXP (set
, 1), 0)),
4943 insn
= prev_nonnote_insn(insn
);
4944 delete_insn (remove_insn
);
4946 else if (GET_CODE (XEXP (set
, 1)) == AND
4947 && GET_CODE (XEXP (XEXP (set
, 1), 1)) == CONST_INT
4948 && INTVAL (XEXP (XEXP (set
, 1), 1)) == 0)
4950 /* We've found an AND with all 0's. */
4951 rtx remove_insn
= insn
;
4952 insn
= emit_insn_before (gen_rtx_SET (mode
,
4954 XEXP (XEXP (set
, 1), 1)),
4956 delete_insn (remove_insn
);
4961 /* Structure used to track jump targets. */
4963 struct we_jump_targets
4965 int target
; /* Is this a jump target? */
4966 int reach_count
; /* Number of ways we can reach this insn. */
4967 int touch_count
; /* Number of times we've touched this insn
4969 rtx w_equiv
; /* WREG-equivalence at this point. */
4972 struct we_jump_targets
*ip2k_we_jump_targets
;
4974 /* WREG equivalence tracking used within DP reload elimination. */
4977 track_w_reload (insn
, w_current
, w_current_ok
, modifying
)
4985 if (GET_CODE (insn
) != INSN
)
4987 *w_current
= NULL_RTX
;
4991 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
4992 if (set
== NULL_RTX
)
4994 *w_current
= NULL_RTX
;
4998 /* Look for W being modified. If it is, see if it's being changed
4999 to what it already is! */
5000 if (GET_CODE (XEXP (set
, 0)) == REG
5001 && REGNO (XEXP (set
, 0)) == REG_W
5002 && GET_MODE (XEXP (set
, 0)) == QImode
)
5004 /* If this is an equivalence we can delete the new set operation. */
5005 if (*w_current
!= NULL_RTX
5006 && rtx_equal_p (XEXP (set
, 1), *w_current
))
5013 *w_current
= XEXP (set
, 1);
5017 else if (recog_memoized (insn
) < 0
5018 || get_attr_clobberw (insn
) != CLOBBERW_NO
)
5020 /* If we clobber W then we've clobbered any equivalences ! */
5021 *w_current
= NULL_RTX
;
5024 else if (! ip2k_xexp_not_uses_reg_p (XEXP (set
, 0), REG_SP
, 2)
5025 && *w_current
!= NULL_RTX
5026 && !ip2k_xexp_not_uses_reg_p (*w_current
, REG_SP
, 2))
5028 /* We look for a special case of "push" operations screwing up the
5029 setting of DP when it's based on the stack. We can track this one
5030 and replace the old expression for DP with a new one. */
5031 if (GET_CODE (XEXP (set
, 0)) == MEM
5032 && GET_CODE (XEXP (XEXP (set
, 0), 0)) == POST_DEC
5033 && GET_CODE (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG
5034 && REGNO (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG_SP
5035 && GET_CODE (*w_current
) == MEM
5036 && GET_CODE (XEXP (*w_current
, 0)) == PLUS
)
5038 /* XXX - need to ensure that we can track this without going
5040 rtx val
= GEN_INT (INTVAL (XEXP (XEXP (*w_current
, 0), 1))
5041 + GET_MODE_SIZE (GET_MODE (XEXP (set
, 0))));
5043 = gen_rtx_MEM (HImode
, gen_rtx_PLUS (Pmode
,
5044 gen_rtx_REG(HImode
, REG_SP
),
5049 else if (GET_CODE (XEXP (set
, 0)) == REG
5050 && *w_current
!= NULL_RTX
5051 && !ip2k_xexp_not_uses_reg_p (*w_current
, REGNO (XEXP (set
, 0)),
5052 GET_MODE_SIZE (GET_MODE (XEXP (set
5055 /* If we've just clobbered all or part of a register reference that we
5056 were sharing for W then we can't share it any more! */
5057 *w_current
= NULL_RTX
;
5060 return w_current_ok
;
5063 /* As part of the machine-dependent reorg we scan moves into w and track them
5064 to see where any are redundant. */
5067 mdr_try_wreg_elim (first_insn
)
5071 struct we_jump_targets
*wjt
;
5073 int incomplete_scan
;
5074 int last_incomplete_scan
;
5076 ip2k_we_jump_targets
5077 = (struct we_jump_targets
*) xcalloc (get_max_uid (),
5078 sizeof (struct we_jump_targets
));
5080 /* First we scan to build up a list of all CODE_LABEL insns and we work out
5081 how many different ways we can reach them. */
5082 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
5084 if (GET_CODE (insn
) == CODE_LABEL
)
5086 wjt
= &ip2k_we_jump_targets
[INSN_UID (insn
)];
5088 wjt
->reach_count
= LABEL_NUSES (insn
);
5089 wjt
->touch_count
= 0;
5090 wjt
->w_equiv
= NULL_RTX
;
5091 if (! prev_nonnote_insn (insn
)
5092 || (prev_nonnote_insn (insn
)
5093 && GET_CODE (prev_nonnote_insn (insn
)) != BARRIER
))
5098 /* Next we scan all of the ways of reaching the code labels to see
5099 what the WREG register is equivalent to as we reach them. If we find
5100 that they're the same then we keep noting the matched value. We
5101 iterate around this until we reach a convergence on WREG equivalences
5102 at all code labels - we have to be very careful not to be too
5104 incomplete_scan
= -1;
5107 int w_current_ok
= 0;
5108 last_incomplete_scan
= incomplete_scan
;
5109 w_current
= NULL_RTX
;
5111 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
5113 /* If we have a code label then we need to see if we already know
5114 what the equivalence is at this point. If we do then we use it
5115 immediately, but if we don't then we have a special case to track
5116 when we hit a fallthrough-edge (label with no barrier preceding
5117 it). Any other accesses to the label must be from jump insns
5118 and so they're handled elsewhere. */
5119 if (GET_CODE (insn
) == CODE_LABEL
)
5121 wjt
= &ip2k_we_jump_targets
[INSN_UID (insn
)];
5123 /* If we're fully characterized the use the equivalence. */
5124 if (wjt
->touch_count
== wjt
->reach_count
)
5126 w_current
= wjt
->w_equiv
;
5131 /* If we have a known equivalence for WREG as we reach the
5132 fallthrough-edge then track this into the code label. */
5134 && (! prev_nonnote_insn (insn
)
5135 || (prev_nonnote_insn (insn
)
5136 && GET_CODE (prev_nonnote_insn (insn
)) != BARRIER
)))
5138 if (wjt
->touch_count
== 0)
5139 wjt
->w_equiv
= w_current
;
5141 if (wjt
->touch_count
< wjt
->reach_count
)
5144 if (! rtx_equal_p (wjt
->w_equiv
, w_current
))
5146 /* When we definitely know that we can't form an
5147 equivalence for WREG here we must clobber anything
5148 that we'd started to track too. */
5149 wjt
->w_equiv
= NULL_RTX
;
5150 w_current
= NULL_RTX
;
5156 /* If we've not completely characterized this code label then
5157 be cautious and assume that we don't know what WREG is
5159 if (wjt
->touch_count
< wjt
->reach_count
)
5161 w_current
= NULL_RTX
;
5168 /* If we've hit a jump insn then we look for either an address
5169 vector (jump table) or for jump label references. */
5170 if (GET_CODE (insn
) == JUMP_INSN
)
5172 /* Don't attempt to track here if we don't have a known
5173 equivalence for WREG at this point. */
5176 if (JUMP_LABEL (insn
))
5179 = &ip2k_we_jump_targets
[INSN_UID (JUMP_LABEL (insn
))];
5181 if (wjt
->touch_count
== 0)
5182 wjt
->w_equiv
= w_current
;
5184 if (wjt
->touch_count
< wjt
->reach_count
)
5187 if (! rtx_equal_p (wjt
->w_equiv
, w_current
))
5188 wjt
->w_equiv
= NULL_RTX
;
5196 /* Anything other than a code labal or jump arrives here. We try and
5197 track WREG, but sometimes we might not be able to. */
5198 w_current_ok
= track_w_reload (insn
, &w_current
, w_current_ok
, 0);
5201 /* When we're looking to see if we've finished we count the number of
5202 paths through the code labels where we weren't able to definitively
5203 track WREG. This number is used to see if we're converging on a
5205 If this hits zero then we've fully converged, but if this stays the
5206 same as last time then we probably can't make any further
5208 incomplete_scan
= 0;
5209 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
5211 if (GET_CODE (insn
) == CODE_LABEL
)
5213 wjt
= &ip2k_we_jump_targets
[INSN_UID (insn
)];
5214 if (wjt
->touch_count
!= wjt
->reach_count
)
5216 incomplete_scan
+= (wjt
->reach_count
- wjt
->touch_count
);
5217 wjt
->w_equiv
= NULL_RTX
;
5218 wjt
->touch_count
= 0;
5223 while (incomplete_scan
&& incomplete_scan
!= last_incomplete_scan
);
5225 /* Finally we scan the whole function and run WREG elimination. When we hit
5226 a CODE_LABEL we pick up any stored equivalence since we now know that
5227 every path to this point entered with WREG holding the same thing! If
5228 we subsequently have a reload that matches then we can eliminate it. */
5229 w_current
= NULL_RTX
;
5230 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
5232 if (GET_CODE (insn
) == JUMP_INSN
)
5235 if (GET_CODE (insn
) == CODE_LABEL
)
5237 wjt
= &ip2k_we_jump_targets
[INSN_UID (insn
)];
5238 w_current
= wjt
->w_equiv
;
5242 track_w_reload (insn
, &w_current
, 1, 1);
5245 free (ip2k_we_jump_targets
);
5247 #endif /* IP2K_MD_REORG_PASS */
5249 /* We perform a lot of untangling of the RTL within the reorg pass since
5250 the IP2k requires some really bizarre (and really undesirable) things
5251 to happen in order to guarantee not aborting. This pass causes several
5252 earlier passes to be re-run as it progressively transforms things,
5253 making the subsequent runs continue to win. */
5258 #ifdef IP2K_MD_REORG_PASS
5259 rtx first_insn
, insn
, set
;
5266 ip2k_reorg_completed
= 1;
5267 ip2k_reorg_split_dimode
= 1;
5268 ip2k_reorg_split_simode
= 1;
5269 ip2k_reorg_split_himode
= 1;
5270 ip2k_reorg_split_qimode
= 1;
5271 ip2k_reorg_merge_qimode
= 1;
5274 #ifndef IP2K_MD_REORG_PASS
5275 ip2k_reorg_completed
= 1;
5276 ip2k_reorg_split_dimode
= 1;
5277 ip2k_reorg_split_simode
= 1;
5278 ip2k_reorg_split_himode
= 1;
5279 ip2k_reorg_split_qimode
= 1;
5280 ip2k_reorg_merge_qimode
= 1;
5282 /* All optimizations below must be debugged and enabled one by one.
5283 All of them commented now because of abort in GCC core. */
5285 ip2k_reorg_in_progress
= 1;
5287 first_insn
= get_insns ();
5289 /* Look for size effects of earlier optimizations - in particular look for
5290 situations where we're saying "use" a register on one hand but immediately
5291 tagging it as "REG_DEAD" at the same time! Seems like a bug in core-gcc
5292 somewhere really but this is what we have to live with! */
5293 for (insn
= first_insn
; insn
; insn
= NEXT_INSN (insn
))
5297 if (GET_CODE (insn
) == CODE_LABEL
5298 || GET_CODE (insn
) == NOTE
5299 || GET_CODE (insn
) == BARRIER
)
5305 body
= PATTERN (insn
);
5306 if (GET_CODE (body
) == USE
)
5307 if (GET_CODE (XEXP (body
, 0)) == REG
)
5311 reg
= REGNO (XEXP (body
, 0));
5312 if (find_regno_note (insn
, REG_DEAD
, reg
))
5319 /* There's a good chance that since we last did CSE that we've rearranged
5320 things in such a way that another go will win. Do so now! */
5321 reload_cse_regs (first_insn
);
5322 find_basic_blocks (first_insn
);
5323 life_analysis (0, PROP_REG_INFO
| PROP_DEATH_NOTES
);
5325 /* Look for where absurd things are happening with DP. */
5326 mdr_try_dp_reload_elim (first_insn
);
5328 ip2k_reorg_in_progress
= 0;
5329 ip2k_reorg_completed
= 1;
5331 split_all_insns (0);
5333 reload_cse_regs (first_insn
);
5334 find_basic_blocks (first_insn
);
5335 life_analysis (0, PROP_REG_INFO
| PROP_DEATH_NOTES
);
5337 peephole2_optimize (NULL
);
5339 mdr_resequence_xy_yx (first_insn
);
5340 mdr_propagate_reg_equivs (first_insn
);
5342 /* Look for redundant set instructions. These can occur when we split
5343 instruction patterns and end up with the second half merging with
5344 or being replaced by something that clobbers the first half. */
5345 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
5347 if (GET_CODE (insn
) == INSN
)
5349 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
5350 if ((set
!= NULL_RTX
)
5351 && (GET_CODE (XEXP (set
, 0)) == REG
)
5352 && (GET_MODE (XEXP (set
, 0)) == QImode
)
5353 && (find_regno_note (insn
, REG_UNUSED
, REGNO (XEXP (set
, 0)))))
5358 mdr_try_move_dp_reload (first_insn
);
5359 mdr_try_move_pushes (first_insn
);
5361 find_basic_blocks (first_insn
);
5362 life_analysis (0, PROP_FINAL
);
5364 mdr_try_propagate_move (first_insn
);
5365 mdr_resequence_xy_yx (first_insn
);
5367 ip2k_reorg_split_dimode
= 1;
5368 split_all_insns (0);
5370 mdr_try_remove_redundant_insns (first_insn
);
5372 mdr_try_propagate_move (first_insn
);
5374 reload_cse_regs (first_insn
);
5375 find_basic_blocks (first_insn
);
5376 life_analysis (0, PROP_FINAL
);
5378 peephole2_optimize (NULL
);
5380 mdr_try_propagate_move (first_insn
);
5382 find_basic_blocks (first_insn
);
5383 life_analysis (0, PROP_FINAL
);
5385 ip2k_reorg_split_simode
= 1;
5386 split_all_insns (0);
5388 mdr_try_remove_redundant_insns (first_insn
);
5390 mdr_try_propagate_move (first_insn
);
5392 reload_cse_regs (first_insn
);
5393 find_basic_blocks (first_insn
);
5394 life_analysis (0, PROP_FINAL
);
5396 peephole2_optimize (NULL
);
5398 mdr_try_propagate_move (first_insn
);
5400 find_basic_blocks (first_insn
);
5401 life_analysis (0, PROP_FINAL
);
5403 ip2k_reorg_split_himode
= 1;
5404 ip2k_reorg_merge_qimode
= 1;
5405 split_all_insns (0);
5407 mdr_try_remove_redundant_insns (first_insn
);
5408 mdr_try_propagate_clr (first_insn
);
5409 mdr_try_propagate_move (first_insn
);
5411 mdr_try_dp_reload_elim (first_insn
);
5412 mdr_try_move_dp_reload (first_insn
);
5414 rebuild_jump_labels (first_insn
);
5416 /* Call to jump_optimize (...) was here, but now I removed it. */
5418 find_basic_blocks (first_insn
);
5419 life_analysis (0, PROP_FINAL
);
5421 peephole2_optimize (NULL
);
5423 mdr_try_propagate_move (first_insn
);
5425 find_basic_blocks (first_insn
);
5426 life_analysis (0, PROP_FINAL
);
5427 mdr_try_remove_redundant_insns (first_insn
);
5429 mdr_try_propagate_clr (first_insn
);
5430 mdr_try_propagate_move (first_insn
);
5432 find_basic_blocks (first_insn
);
5433 life_analysis (0, PROP_FINAL
);
5435 ip2k_reorg_split_qimode
= 1;
5436 split_all_insns (0);
5438 mdr_try_wreg_elim (first_insn
);
5439 mdr_try_propagate_move (first_insn
);
5441 find_basic_blocks (first_insn
);
5442 life_analysis (0, PROP_FINAL
);
5447 ip2k_init_libfuncs (void)
5449 set_optab_libfunc (smul_optab
, SImode
, "_mulsi3");
5450 set_optab_libfunc (smul_optab
, DImode
, "_muldi3");
5451 set_optab_libfunc (cmp_optab
, HImode
, "_cmphi2");
5452 set_optab_libfunc (cmp_optab
, SImode
, "_cmpsi2");
5455 /* Returns a bit position if mask contains only a single bit. Returns -1 if
5456 there were zero or more than one set bits. */
5458 find_one_set_bit_p (HOST_WIDE_INT mask
)
5461 unsigned HOST_WIDE_INT n
= mask
;
5462 for (i
= 0; i
< 32; i
++)
5464 if (n
& 0x80000000UL
)
5466 if (n
& 0x7fffffffUL
)
5476 /* Returns a bit position if mask contains only a single clear bit.
5477 Returns -1 if there were zero or more than one clear bits. */
5479 find_one_clear_bit_p (HOST_WIDE_INT mask
)
5482 unsigned HOST_WIDE_INT n
= mask
;
5483 for (i
= 0; i
< 32; i
++)
5485 if ((n
& 0x80000000UL
) == 0UL)
5487 if ((n
& 0x7fffffffUL
) != 0x7fffffffUL
)
5499 /* Split a move into two smaller pieces.
5500 MODE indicates the reduced mode. OPERANDS[0] is the original destination
5501 OPERANDS[1] is the original src. The new destinations are
5502 OPERANDS[2] and OPERANDS[4], while the new sources are OPERANDS[3]
5506 ip2k_split_words (enum machine_mode nmode
, enum machine_mode omode
,
5509 rtx dl
, dh
; /* src/dest pieces. */
5511 int move_high_first
= 0; /* Assume no overlap. */
5514 switch (GET_CODE (operands
[0])) /* DEST */
5518 if ((GET_CODE (operands
[1]) == REG
5519 || GET_CODE (operands
[1]) == SUBREG
)
5520 && (true_regnum (operands
[0]) <= true_regnum (operands
[1])
5521 || (true_regnum (operands
[1])
5522 + GET_MODE_SIZE (omode
) - 1 < true_regnum (operands
[0]))))
5523 move_high_first
= 1;
5525 if (GET_CODE (operands
[0]) == SUBREG
)
5527 dl
= simplify_gen_subreg (nmode
, operands
[0], omode
,
5528 GET_MODE_SIZE (nmode
));
5529 dh
= simplify_gen_subreg (nmode
, operands
[0], omode
, 0);
5531 else if (GET_CODE (operands
[0]) == REG
&& ! IS_PSEUDO_P (operands
[0]))
5533 int r
= REGNO (operands
[0]);
5534 dh
= gen_rtx_REG (nmode
, r
);
5535 dl
= gen_rtx_REG (nmode
, r
+ HARD_REGNO_NREGS (r
, nmode
));
5539 dh
= gen_rtx_SUBREG (nmode
, operands
[0], 0);
5540 dl
= gen_rtx_SUBREG (nmode
, operands
[0], GET_MODE_SIZE (nmode
));
5545 switch (GET_CODE (XEXP (operands
[0], 0)))
5550 dl
= dh
= gen_rtx_MEM (nmode
, XEXP (operands
[0], 0));
5554 dl
= change_address (operands
[0], nmode
,
5555 plus_constant (XEXP (operands
[0], 0),
5556 GET_MODE_SIZE (nmode
)));
5557 dh
= gen_rtx_MEM (nmode
, XEXP (operands
[0], 0));
5564 switch (GET_CODE (operands
[1]))
5567 if (! IS_PSEUDO_P (operands
[1]))
5569 int r
= REGNO (operands
[1]);
5571 sh
= gen_rtx_REG (nmode
, r
);
5572 sl
= gen_rtx_REG (nmode
, r
+ HARD_REGNO_NREGS (r
, nmode
));
5576 sh
= gen_rtx_SUBREG (nmode
, operands
[1], 0);
5577 sl
= gen_rtx_SUBREG (nmode
, operands
[1], GET_MODE_SIZE (nmode
));
5582 if (operands
[1] == const0_rtx
)
5583 sh
= sl
= const0_rtx
;
5586 if (GET_MODE (operands
[0]) != DImode
)
5591 REAL_VALUE_FROM_CONST_DOUBLE (rv
, operands
[1]);
5592 REAL_VALUE_TO_TARGET_SINGLE (rv
, value
);
5594 sh
= gen_int_mode ((value
>> 16) & 0xffff, nmode
);
5595 sl
= gen_int_mode (value
& 0xffff, nmode
);
5599 sh
= gen_int_mode (CONST_DOUBLE_HIGH (operands
[1]), nmode
);
5600 sl
= gen_int_mode (CONST_DOUBLE_LOW (operands
[1]), nmode
);
5606 if (operands
[1] == const0_rtx
)
5607 sh
= sl
= const0_rtx
;
5610 int val
= INTVAL (operands
[1]);
5616 vh
= (val
>> 8) & 0xff;
5621 vh
= (val
>> 16) & 0xffff;
5626 if (val
< 0) /* sign extend */
5630 vl
= val
; /* Give low 32 bits back. */
5637 sl
= gen_int_mode (vl
, nmode
);
5638 sh
= gen_int_mode (vh
, nmode
);
5643 sl
= simplify_gen_subreg (nmode
, operands
[1], omode
,
5644 GET_MODE_SIZE (nmode
));
5645 sh
= simplify_gen_subreg (nmode
, operands
[1], omode
, 0);
5649 switch (GET_CODE (XEXP (operands
[1], 0)))
5657 /* Worry about splitting stack pushes. */
5658 if (pushflag
&& ip2k_address_uses_reg_p (operands
[1], REG_SP
))
5659 sl
= sh
= change_address (operands
[1], nmode
,
5660 plus_constant (XEXP (operands
[1], 0),
5661 GET_MODE_SIZE (nmode
)));
5664 sl
= change_address (operands
[1], nmode
,
5665 plus_constant (XEXP (operands
[1], 0),
5666 GET_MODE_SIZE (nmode
)));
5667 sh
= gen_rtx_MEM (nmode
, XEXP (operands
[1], 0));
5676 if (move_high_first
)
5693 /* Get the low half of an operand. */
5695 ip2k_get_low_half (rtx x
, enum machine_mode mode
)
5697 switch (GET_CODE (x
))
5700 if (! IS_PSEUDO_P (x
))
5702 unsigned int r
= REGNO (x
);
5704 return gen_rtx_REG (mode
, r
+ HARD_REGNO_NREGS (r
, mode
));
5708 return gen_rtx_SUBREG (mode
, x
, GET_MODE_SIZE (mode
));
5713 if (x
== const0_rtx
)
5722 REAL_VALUE_FROM_CONST_DOUBLE (rv
, x
);
5723 REAL_VALUE_TO_TARGET_SINGLE (rv
, value
);
5725 return gen_int_mode (value
& 0xffff, mode
);
5728 return gen_int_mode (CONST_DOUBLE_LOW (x
), mode
);
5733 if (x
== const0_rtx
)
5737 int val
= INTVAL (x
);
5743 vh
= (val
>> 8) & 0xff;
5748 vh
= (val
>> 16) & 0xffff;
5753 if (val
< 0) /* sign extend */
5757 vl
= val
; /* Give low 32 bits back. */
5764 return gen_int_mode (vl
, mode
);
5769 return simplify_gen_subreg (mode
, x
, GET_MODE (x
), GET_MODE_SIZE (mode
));
5772 switch (GET_CODE (XEXP (x
, 0)))
5780 return change_address (x
, mode
,
5781 plus_constant (XEXP (x
, 0),
5782 GET_MODE_SIZE (mode
)));
5792 /* Get the high half of an operand. */
5794 ip2k_get_high_half (rtx x
, enum machine_mode mode
)
5796 switch (GET_CODE (x
))
5799 if (! IS_PSEUDO_P (x
))
5801 unsigned int r
= REGNO (x
);
5803 return gen_rtx_REG (mode
, r
);
5807 return gen_rtx_SUBREG (mode
, x
, 0);
5812 if (x
== const0_rtx
)
5821 REAL_VALUE_FROM_CONST_DOUBLE (rv
, x
);
5822 REAL_VALUE_TO_TARGET_SINGLE (rv
, value
);
5824 return gen_int_mode ((value
>> 16) & 0xffff, mode
);
5827 return gen_int_mode (CONST_DOUBLE_HIGH (x
), mode
);
5832 if (x
== const0_rtx
)
5836 int val
= INTVAL (x
);
5842 vh
= (val
>> 8) & 0xff;
5847 vh
= (val
>> 16) & 0xffff;
5852 if (val
< 0) /* sign extend */
5856 vl
= val
; /* Give low 32 bits back. */
5863 return gen_int_mode (vh
, mode
);
5868 return simplify_gen_subreg (mode
, x
, GET_MODE (x
), 0);
5872 switch (GET_CODE (XEXP (x
, 0)))
5880 return change_address (x
, mode
, plus_constant (XEXP (x
, 0), 0));
5890 /* Does address X use register R. Only valid for REG_SP, REG_DP, REG_IP
5894 ip2k_address_uses_reg_p (rtx x
, unsigned int r
)
5896 if (GET_CODE (x
) != MEM
)
5902 switch (GET_CODE (x
))
5912 if (ip2k_address_uses_reg_p (XEXP (x
, 1), r
))
5919 /* Ignore subwords. */
5924 /* Have to consider that r might be LSB of a pointer reg. */
5925 return ((REGNO (x
) == r
) || (REGNO (x
) == (r
- 1))) ? 1 : 0;
5928 /* We might be looking at a (mem:BLK (mem (...))) */
5937 /* Does the queried XEXP not use a particular register? If we're certain
5938 that it doesn't then we return TRUE otherwise we assume FALSE. */
5941 ip2k_xexp_not_uses_reg_p (rtx x
, unsigned int r
, int rsz
)
5943 switch (GET_CODE (x
))
5947 int msz
= GET_MODE_SIZE (GET_MODE (x
));
5949 return (((REGNO (x
) + msz
- 1) < r
)
5950 || (REGNO (x
) > (r
+ rsz
- 1)));
5954 return !ip2k_address_uses_reg_p (x
, r
);
5970 /* Does the queried XEXP not use a particular register? If we're certain
5971 that it doesn't then we return TRUE otherwise we assume FALSE. */
5974 ip2k_composite_xexp_not_uses_reg_p (rtx x
, unsigned int r
, int rsz
)
5976 if (GET_RTX_CLASS (GET_CODE (x
)) == RTX_BITFIELD_OPS
)
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
)
5979 && ip2k_composite_xexp_not_uses_reg_p (XEXP (x
, 2), r
, rsz
));
5982 return (ip2k_composite_xexp_not_uses_reg_p (XEXP (x
, 0), r
, rsz
)
5983 && ip2k_composite_xexp_not_uses_reg_p (XEXP (x
, 1), r
, rsz
));
5986 || GET_RTX_CLASS (GET_CODE (x
)) == RTX_TERNARY
)
5987 return ip2k_composite_xexp_not_uses_reg_p (XEXP (x
, 0), r
, rsz
);
5989 return ip2k_xexp_not_uses_reg_p (x
, r
, rsz
);
5992 /* Does the queried XEXP not use CC0? If we're certain that
5993 it doesn't then we return TRUE otherwise we assume FALSE. */
5996 ip2k_composite_xexp_not_uses_cc0_p (rtx x
)
5998 if (GET_RTX_CLASS (GET_CODE (x
)) == RTX_BITFIELD_OPS
)
5999 return (ip2k_composite_xexp_not_uses_cc0_p (XEXP (x
, 0))
6000 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (x
, 1))
6001 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (x
, 2)));
6004 return (ip2k_composite_xexp_not_uses_cc0_p (XEXP (x
, 0))
6005 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (x
, 1)));
6008 || GET_RTX_CLASS (GET_CODE (x
)) == RTX_TERNARY
)
6009 return ip2k_composite_xexp_not_uses_cc0_p (XEXP (x
, 0));
6011 return GET_CODE (x
) != CC0
;
6015 ip2k_split_dest_operand (rtx x
, enum machine_mode mode
)
6017 return nonimmediate_operand (x
, mode
) || push_operand (x
, mode
);
6021 ip2k_nonptr_operand (rtx x
, enum machine_mode mode
)
6023 return register_operand (x
, mode
) && !ip2k_ptr_operand (x
, mode
);
6026 /* Is X a reference to IP or DP or SP? */
6029 ip2k_ptr_operand (rtx x
, enum machine_mode mode
)
6032 if (GET_CODE (x
) == SUBREG
)
6036 && (mode
== HImode
|| mode
== VOIDmode
)
6037 && (REGNO (x
) == REG_IP
6038 || REGNO (x
) == REG_DP
6039 || REGNO (x
) == REG_SP
));
6043 ip2k_sp_operand (rtx x
, enum machine_mode mode ATTRIBUTE_UNUSED
)
6046 return REG_P (x
) && REGNO (x
) == REG_SP
;
6050 ip2k_ip_operand (rtx x
, enum machine_mode mode
)
6053 if (GET_CODE (x
) != MEM
)
6058 if (GET_CODE (x
) == PLUS
&& XEXP (x
, 1) == const0_rtx
)
6064 if (GET_MODE_SIZE (mode
) > 1)
6065 return 0; /* Can't access offset bytes. */
6067 return REGNO (x
) == REG_IP
;
6070 /* Is X a memory address suitable for SP or DP relative addressing? */
6072 ip2k_short_operand (rtx x
, enum machine_mode mode
)
6075 unsigned int offs
= 0;
6077 if (! memory_operand (x
, mode
))
6078 return 0; /* Got to be a memory address. */
6081 switch (GET_CODE (x
))
6087 if (! REG_P (XEXP (x
, 0))
6088 || GET_CODE (XEXP (x
, 1)) != CONST_INT
)
6091 offs
= INTVAL (XEXP (x
, 1));
6101 if (IS_PSEUDO_P (x
))
6102 return 0; /* Optimistic - doesn't work. */
6106 /* For 'S' constraint, we presume that no IP adjustment
6107 simulation is performed - so only QI mode allows IP to be a
6108 short offset address. All other IP references must be
6109 handled by 'R' constraints. */
6110 if (r
== REG_IP
&& offs
== 0 && GET_MODE_SIZE (mode
) <= 1)
6113 return (r
== REG_SP
|| r
== REG_DP
);
6118 ip2k_nonsp_reg_operand (rtx x
, enum machine_mode mode ATTRIBUTE_UNUSED
)
6120 if (GET_CODE (x
) == SUBREG
)
6123 return (REG_P (x
) && REGNO (x
) != REG_SP
);
6127 ip2k_gen_operand (rtx x
, enum machine_mode mode
)
6129 return ip2k_short_operand (x
, mode
)
6130 || (GET_CODE (x
) == SUBREG
6131 && REG_P (SUBREG_REG (x
)))
6132 || (ip2k_nonsp_reg_operand (x
, mode
));
6136 ip2k_extra_constraint (rtx x
, int c
)
6140 case 'S': /* Allow offset in stack frame... */
6141 return ip2k_short_operand (x
, GET_MODE (x
));
6144 return ip2k_ip_operand (x
, GET_MODE (x
));
6146 case 'T': /* Constant int or .data address. */
6147 return CONSTANT_P (x
) && is_regfile_address (x
);
6155 ip2k_unary_operator (rtx op
, enum machine_mode mode
)
6157 return ((mode
== VOIDmode
|| GET_MODE (op
) == mode
)
6162 ip2k_binary_operator (rtx op
, enum machine_mode mode
)
6164 return ((mode
== VOIDmode
|| GET_MODE (op
) == mode
)
6165 && ARITHMETIC_P (op
));
6169 ip2k_symbol_ref_operand (rtx op
, enum machine_mode mode ATTRIBUTE_UNUSED
)
6171 /* We define an IP2k symbol ref to be either a direct reference or one
6172 with a constant offset. */
6173 return (GET_CODE (op
) == SYMBOL_REF
)
6174 || (GET_CODE (op
) == CONST
6175 && GET_CODE (XEXP (op
, 0)) == PLUS
6176 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == SYMBOL_REF
);
6180 ip2k_signed_comparison_operator (rtx op
, enum machine_mode mode
)
6182 return (comparison_operator (op
, mode
)
6183 && signed_condition (GET_CODE (op
)) == GET_CODE (op
));
6187 ip2k_unsigned_comparison_operator (rtx op
, enum machine_mode mode
)
6189 return (comparison_operator (op
, mode
)
6190 && unsigned_condition (GET_CODE (op
)) == GET_CODE (op
));
6193 /* Worker function for TARGET_RETURN_IN_MEMORY. */
6196 ip2k_return_in_memory (tree type
, tree fntype ATTRIBUTE_UNUSED
)
6198 if (TYPE_MODE (type
) == BLKmode
)
6200 HOST_WIDE_INT size
= int_size_in_bytes (type
);
6201 return (size
== -1 || size
> 8);
6207 /* Worker function for TARGET_SETUP_INCOMING_VARARGS. */
6210 ip2k_setup_incoming_varargs (CUMULATIVE_ARGS
*ca ATTRIBUTE_UNUSED
,
6211 enum machine_mode mode ATTRIBUTE_UNUSED
,
6212 tree type ATTRIBUTE_UNUSED
,
6213 int *pretend_arg_size
,
6214 int second_time ATTRIBUTE_UNUSED
)
6216 *pretend_arg_size
= 0;