1 /* Subroutines used for code generation on Ubicom IP2022
2 Communications Controller.
3 Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
4 Contributed by Red Hat, Inc and Ubicom, Inc.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
25 #include "coretypes.h"
29 #include "hard-reg-set.h"
31 #include "insn-config.h"
32 #include "conditions.h"
33 #include "insn-flags.h"
35 #include "insn-attr.h"
36 #include "insn-addr.h"
48 #include "target-def.h"
49 #include "basic-block.h"
51 /* There are problems with 'frame_pointer_needed'. If we force it
52 on, we either end up not eliminating uses of FP, which results in
53 SPILL register failures or we may end up with calculation errors in
54 the stack offsets. Isolate the decision process into a simple macro. */
55 #define CHAIN_FRAMES (frame_pointer_needed || FRAME_POINTER_REQUIRED)
57 static int ip2k_naked_function_p (tree
);
58 #ifdef IP2K_MD_REORG_PASS
59 static void mdr_resequence_xy_yx (rtx
);
60 static void mdr_pres_replace_and_recurse (rtx
, rtx
, rtx
);
61 static void mdr_propagate_reg_equivs_sequence (rtx
, rtx
, rtx
);
62 static void mdr_propagate_reg_equivs (rtx
);
63 static int track_dp_reload (rtx
, rtx
*, int , int);
64 static void mdr_try_dp_reload_elim (rtx
);
65 static void mdr_try_move_dp_reload (rtx
);
66 static void mdr_try_move_pushes (rtx
);
67 static void mdr_try_propagate_clr_sequence (rtx
, unsigned int);
68 static void mdr_try_propagate_clr (rtx
);
69 static void mdr_try_propagate_move_sequence (rtx
, rtx
, rtx
);
70 static void mdr_try_propagate_move (rtx
);
71 static void mdr_try_remove_redundant_insns (rtx
);
72 static int track_w_reload (rtx
, rtx
*, int , int);
73 static void mdr_try_wreg_elim (rtx
);
74 #endif /* IP2K_MD_REORG_PASS */
75 static void ip2k_reorg (void);
76 static int ip2k_check_can_adjust_stack_ref (rtx
, int);
77 static void ip2k_adjust_stack_ref (rtx
*, int);
78 static int ip2k_xexp_not_uses_reg_for_mem (rtx
, unsigned int);
79 static tree
ip2k_handle_progmem_attribute (tree
*, tree
, tree
, int, bool *);
80 static tree
ip2k_handle_fndecl_attribute (tree
*, tree
, tree
, int, bool *);
81 static bool ip2k_rtx_costs (rtx
, int, int, int *);
82 static int ip2k_address_cost (rtx
);
83 static void ip2k_init_libfuncs (void);
85 const struct attribute_spec ip2k_attribute_table
[];
88 /* Initialize the GCC target structure. */
89 #undef TARGET_ASM_ALIGNED_HI_OP
90 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
92 #undef TARGET_ASM_FUNCTION_PROLOGUE
93 #define TARGET_ASM_FUNCTION_PROLOGUE function_prologue
95 #undef TARGET_ASM_FUNCTION_EPILOGUE
96 #define TARGET_ASM_FUNCTION_EPILOGUE function_epilogue
98 #undef TARGET_ASM_UNIQUE_SECTION
99 #define TARGET_ASM_UNIQUE_SECTION unique_section
101 #undef TARGET_ATTRIBUTE_TABLE
102 #define TARGET_ATTRIBUTE_TABLE ip2k_attribute_table
104 #undef TARGET_RTX_COSTS
105 #define TARGET_RTX_COSTS ip2k_rtx_costs
106 #undef TARGET_ADDRESS_COST
107 #define TARGET_ADDRESS_COST ip2k_address_cost
109 #undef TARGET_MACHINE_DEPENDENT_REORG
110 #define TARGET_MACHINE_DEPENDENT_REORG ip2k_reorg
112 #undef TARGET_INIT_LIBFUNCS
113 #define TARGET_INIT_LIBFUNCS ip2k_init_libfuncs
115 struct gcc_target targetm
= TARGET_INITIALIZER
;
117 /* Prologue/Epilogue size in words. */
118 static int prologue_size
;
119 static int epilogue_size
;
121 /* compare and test instructions for the IP2K are materialized by
122 the conditional branch that uses them. This is because conditional
123 branches are skips over unconditional branches. */
124 rtx ip2k_compare_operands
[3]; /* Additional operands for condition code. */
125 int ip2k_test_flag
; /* Indicates Z, WREG contain condition code
128 /* Some ip2k patterns push a byte onto the stack and then access
129 SP-relative addresses. Since reload doesn't know about these
130 pushes, we must track them internally with a %< (push) or %> (pop)
132 static int ip2k_stack_delta
;
134 /* Track if or how far our ip2k reorganization pass has run. */
135 int ip2k_reorg_in_progress
= 0;
136 int ip2k_reorg_completed
= 0;
137 int ip2k_reorg_split_dimode
= 0;
138 int ip2k_reorg_split_simode
= 0;
139 int ip2k_reorg_split_himode
= 0;
140 int ip2k_reorg_split_qimode
= 0;
141 int ip2k_reorg_merge_qimode
= 0;
143 /* Set up local allocation order. */
146 ip2k_init_local_alloc (int *rao
)
148 static const int alloc_order
[] = REG_ALLOC_ORDER
;
150 memcpy (rao
, alloc_order
, sizeof (alloc_order
));
153 /* Returns the number of bytes of arguments automatically
154 popped when returning from a subroutine call.
155 FUNDECL is the declaration node of the function (as a tree),
156 FUNTYPE is the data type of the function (as a tree),
157 or for a library call it is an identifier node for the subroutine name.
158 SIZE is the number of bytes of arguments passed on the stack. */
161 ip2k_return_pops_args (tree fundecl ATTRIBUTE_UNUSED
, tree funtype
, int size
)
163 if (TREE_CODE (funtype
) == IDENTIFIER_NODE
)
166 if (TYPE_ARG_TYPES (funtype
) == NULL_TREE
167 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype
))) == void_type_node
))
173 /* Return nonzero if FUNC is a naked function. */
176 ip2k_naked_function_p (tree func
)
180 if (TREE_CODE (func
) != FUNCTION_DECL
)
183 a
= lookup_attribute ("naked", DECL_ATTRIBUTES (func
));
184 return a
!= NULL_TREE
;
187 /* Output function prologue. */
189 function_prologue (FILE *file
, HOST_WIDE_INT size
)
196 prologue_size
= epilogue_size
= 0;
198 if (ip2k_naked_function_p (current_function_decl
))
200 fprintf (file
, "/* prologue: naked */\n");
204 leaf_func_p
= leaf_function_p ();
205 main_p
= ! strcmp ("main", current_function_name
);
207 /* For now, we compute all these facts about the function, but don't
208 take any action based on the information. */
211 fprintf (file
, "/* prologue: frame size=" HOST_WIDE_INT_PRINT_DEC
" */\n",
214 /* Unless we're a leaf we need to save the return PC. */
218 OUT_AS1 (push
, calll
);
219 OUT_AS1 (push
, callh
);
223 /* We need to save the old FP and set the new FP pointing at the
224 stack location where the old one is saved. Note that because of
225 post-decrement addressing, the SP is off-by-one after the
226 push, so we harvest the SP address BEFORE we push the MSBs of
230 OUT_AS1 (push
, REG_FP
+1); /* Save old LSBs. */
231 OUT_AS2 (mov
, w
, spl
);
232 OUT_AS2 (mov
, REG_FP
+1, w
); /* SPL -> FPL */
234 OUT_AS2 (mov
, w
, sph
); /* Freeze SP MSBs */
235 OUT_AS1 (push
, REG_FP
); /* Save old MSBs */
236 OUT_AS2 (mov
, REG_FP
, w
); /* SPH -> FPH */
240 for (reg
= (CHAIN_FRAMES
) ? (REG_FP
- 1) : (REG_FP
+ 1);
243 if (regs_ever_live
[reg
] && ! call_used_regs
[reg
])
245 fprintf (file
, "\t" AS1 (push
,%s
) "\n", reg_names
[reg
]);
252 operands
[0] = GEN_INT (size
);
263 OUT_AS2 (mov
, w
, %L0
);
264 OUT_AS2 (sub
, spl
, w
);
268 switch (size
& 0xff00)
277 if ((size
& 0xff) != ((size
>> 8) & 0xff))
278 OUT_AS2 (mov
, w
, %H0
); /* Otherwise W has value we want. */
279 OUT_AS2 (sub
, sph
, w
);
284 /* XXX - change this to use the carry-propagating subtract trick. */
285 if (flag_stack_check
)
287 OUT_AS2 (mov
, w
, sph
);
288 OUT_AS2 (cmp
, w
, #%%hi8data(_end));
289 OUT_AS1 (sc
, ); /* C == 0 -> hi8(edata) < sph */
292 OUT_AS1 (sz
, ); /* Z == 1 -> look at low byte */
294 OUT_AS1 (jmp
,0f
); /* sp < edata, so raise stack fault */
295 OUT_AS2 (mov
, w
, spl
);
296 OUT_AS2 (cmp
, w
, #%%lo8data(_end));
297 OUT_AS1 (sc
,); /* C==1 -> lo8(edata) >= spl */
301 output_asm_insn ("push\t$ff", operands
);
308 /* Output function epilogue. */
310 function_epilogue (FILE *file
, HOST_WIDE_INT size
)
314 rtx operands
[2]; /* Dummy used by OUT_ASn */
315 int args_locals_size
= current_function_args_size
;
316 int saved_regs_p
= 0;
319 /* Use this opportunity to reset the reorg flags! */
320 ip2k_reorg_in_progress
= 0;
321 ip2k_reorg_completed
= 0;
322 ip2k_reorg_split_dimode
= 0;
323 ip2k_reorg_split_simode
= 0;
324 ip2k_reorg_split_himode
= 0;
325 ip2k_reorg_split_qimode
= 0;
326 ip2k_reorg_merge_qimode
= 0;
328 if (ip2k_naked_function_p (current_function_decl
))
330 fprintf (file
, "/* epilogue: naked */\n");
334 leaf_func_p
= leaf_function_p ();
336 fprintf (file
, "/* epilogue: frame size=" HOST_WIDE_INT_PRINT_DEC
" */\n",
339 savelimit
= (CHAIN_FRAMES
) ? REG_FP
: (REG_FP
+ 2);
340 for (reg
= 0; reg
< savelimit
; reg
++)
341 if (regs_ever_live
[reg
] && ! call_used_regs
[reg
])
349 if (leaf_func_p
&& !CHAIN_FRAMES
&& !saved_regs_p
350 && current_function_pops_args
)
351 args_locals_size
= current_function_args_size
+ size
;
354 operands
[0] = GEN_INT (size
);
359 OUT_AS2 (mov
, w
, %L0
);
360 OUT_AS2 (add
, spl
, w
);
370 switch (size
& 0xff00)
373 if ((size
& 0xff) != ((size
>> 8) & 0xff))
374 OUT_AS2 (mov
, w
, %H0
);
375 OUT_AS2 (add
, sph
, w
);
387 for (reg
= 0; reg
< savelimit
; reg
++)
389 if (regs_ever_live
[reg
] && ! call_used_regs
[reg
])
391 fprintf (file
, "\t" AS1 (pop
,%s
) "\n", reg_names
[reg
]);
397 && ! (current_function_pops_args
398 && current_function_args_size
>= 2
399 && current_function_args_size
< 0x100))
401 OUT_AS1 (pop
, REG_FP
);
402 OUT_AS1 (pop
, REG_FP
+1);
408 if (current_function_pops_args
409 && current_function_args_size
>= 2
410 && current_function_args_size
< 0x100)
412 if (current_function_args_size
== 2)
416 OUT_AS1 (page
, __fp_pop2_args_ret
);
417 OUT_AS1 (jmp
, __fp_pop2_args_ret
);
421 OUT_AS1 (page
, __pop2_args_ret
);
422 OUT_AS1 (jmp
, __pop2_args_ret
);
428 operands
[0] = GEN_INT (current_function_args_size
);
429 OUT_AS2 (mov
, w
, %L0
);
432 OUT_AS1 (page
, __fp_pop_args_ret
);
433 OUT_AS1 (jmp
, __fp_pop_args_ret
);
437 OUT_AS1 (page
, __pop_args_ret
);
438 OUT_AS1 (jmp
, __pop_args_ret
);
446 OUT_AS1 (pop
, callh
);
447 OUT_AS1 (pop
, calll
);
453 if (current_function_pops_args
454 && args_locals_size
>= 2
455 && args_locals_size
< 0x100)
457 if (args_locals_size
== 2)
461 OUT_AS1 (page
, __leaf_fp_pop2_args_ret
);
462 OUT_AS1 (jmp
, __leaf_fp_pop2_args_ret
);
469 operands
[0] = GEN_INT (args_locals_size
);
472 OUT_AS2 (mov
, w
, %L0
);
473 OUT_AS1 (page
, __leaf_fp_pop_args_ret
);
474 OUT_AS1 (jmp
, __leaf_fp_pop_args_ret
);
482 if (current_function_pops_args
&& args_locals_size
&& need_ret
)
484 operands
[0] = GEN_INT (args_locals_size
);
486 switch (args_locals_size
& 0xff)
489 OUT_AS2 (mov
, w
, %L0
);
490 OUT_AS2 (add
, spl
, w
);
502 switch (args_locals_size
& 0xff00)
505 if ((args_locals_size
& 0xff) != ((args_locals_size
>> 8) & 0xff))
506 OUT_AS2 (mov
, w
, %H0
);
507 OUT_AS2 (add
, sph
, w
);
526 fprintf (file
, "/* epilogue end (size=%d) */\n", epilogue_size
);
529 /* Return the difference between the registers after the function
532 Stack Frame grows down:
535 <------ AP ($102:$103)
536 RETURN PC (unless leaf function)
538 <------ FP [HARD_FRAME_POINTER] ($FD:$FE)
540 <------ VFP [$100:$101]
542 <------ SP ($6:$7) */
544 ip2k_init_elim_offset (int from
, int to
)
546 int leaf_func_p
= leaf_function_p ();
547 int no_saved_pc
= leaf_func_p
548 || ip2k_naked_function_p (current_function_decl
);
553 if (from
== FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
554 return get_frame_size () + 1;
556 if (from
== ARG_POINTER_REGNUM
&& to
== HARD_FRAME_POINTER_REGNUM
)
557 return (CHAIN_FRAMES
? 2 : 0) + (no_saved_pc
? 0 : 2);
559 /* Count all the registers we had to preserve. */
561 reglimit
= CHAIN_FRAMES
? REG_FP
: (REG_FP
+ 2);
562 for (offset
= 0,reg
= 0; reg
< reglimit
; ++reg
)
564 if ((regs_ever_live
[reg
] && ! call_used_regs
[reg
]))
570 if (from
== FRAME_POINTER_REGNUM
&& to
== HARD_FRAME_POINTER_REGNUM
)
573 if (from
== HARD_FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
574 /* Add in the stack-local variables. */
575 return offset
+ get_frame_size () + 1;
577 if (from
== ARG_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
578 /* Add stack-locals plus saved FP and PC. */
579 return offset
+ get_frame_size () + 1
580 + (CHAIN_FRAMES
? 2 : 0) + (no_saved_pc
? 0 : 2);
582 abort (); /* Unanticipated elimination. */
585 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
586 machine for a memory operand of mode MODE. */
589 legitimate_address_p (enum machine_mode mode
, rtx x
, int strict
)
593 if (GET_CODE (x
) == SUBREG
)
596 switch (GET_CODE (x
))
599 /* IP allows indirection without offset - only okay if
600 we don't require access to multiple bytes. */
601 if (REGNO (x
) == REG_IP
)
602 return (GET_MODE_SIZE (mode
) == 1) ? 'R' : 0;
604 /* We can indirect through DP or SP register. */
605 if (strict
? REG_OK_FOR_BASE_STRICT_P (x
)
606 : REG_OK_FOR_BASE_NOSTRICT_P (x
))
611 /* Offsets from DP or SP are legal in the range 0..127 */
618 if (REG_P (op2
) && ! REG_P (op1
))
625 /* Don't let anything but R+I through.. */
628 || GET_CODE (op2
) != CONST_INT
)
633 case REG_DP
: /* only 0..127 displacement */
635 off
= 2 * GET_MODE_SIZE (mode
);
639 if (INTVAL (op2
) < 0 || INTVAL (op2
) > (128 - off
))
640 return 0; /* Positive must be small enough that after
641 splitting all pieces are addressed. */
642 return 'S'; /* Safe displacement. */
645 if (GET_MODE_SIZE (mode
) <= 1 && INTVAL (op2
) == 0)
646 return (GET_MODE_SIZE (mode
) == 1) ? 'R' : 0;
653 if (strict
|| ! REG_OK_FOR_BASE_NOSTRICT_P (op1
))
654 return 0; /* Allow until reload. */
663 /* We always allow references to things in code space. */
664 return is_regfile_address (x
) ? 0 : 'C';
676 /* Is ADDR mode dependent? */
678 ip2k_mode_dependent_address (rtx addr
)
680 switch (GET_CODE (addr
))
689 return (REGNO (addr
) == REG_IP
); /* Can't do IP displaced addresses. */
692 return 0; /* Assume no dependency. */
696 /* Attempts to replace X with a valid
697 memory address for an operand of mode MODE. */
700 legitimize_address (rtx x
, rtx oldx ATTRIBUTE_UNUSED
,
701 enum machine_mode mode ATTRIBUTE_UNUSED
, rtx scratch
)
705 /* You might think that we could split up a symbolic address by
706 adding the HIGH 8 bits and doing a displacement off the dp. But
707 because we only have 7 bits of offset, that doesn't actually
708 help. So only constant displacements are likely to obtain an
711 if (GET_CODE (x
) == PLUS
&& REG_P (XEXP (x
, 0))
712 && GET_CODE (XEXP (x
, 1)) == CONST_INT
713 && ! CONST_OK_FOR_LETTER_P (INTVAL (XEXP (x
, 1)), 'K'))
715 int offset
= INTVAL (XEXP (x
, 1));
717 reg
= scratch
? scratch
: gen_reg_rtx (Pmode
);
719 emit_insn (gen_rtx_SET (VOIDmode
, reg
,
720 gen_rtx_PLUS (Pmode
, XEXP (x
, 0),
721 GEN_INT (offset
& 0xffc0))));
722 x
= gen_rtx_PLUS (Pmode
, reg
, GEN_INT (offset
& 0x3f));
725 return x
; /* We don't have any other tricks. */
728 /* Determine if X is a 'data' address or a code address. All static
729 data and stack variables reside in data memory. Only code is believed
730 to be in PRAM or FLASH. */
732 is_regfile_address (rtx x
)
735 switch (GET_CODE (x
))
738 return ! SYMBOL_REF_FUNCTION_P (x
); /* Declared as function. */
756 /* Output ADDR to FILE as address. */
759 print_operand_address (FILE *file
, rtx addr
)
761 switch (GET_CODE (addr
))
764 addr
= alter_subreg (&addr
);
768 fprintf (file
, "(%s)",
769 REGNO (addr
) == REG_DP
? "DP"
770 : REGNO (addr
) == REG_SP
? "SP"
771 : REGNO (addr
) == REG_IP
? "IP"
772 : REGNO (addr
) == REG_VFP
? "VFP" /* Should never see this */
773 : REGNO (addr
) == REG_AP
? "AP" /* or this, either. */
774 : reg_names
[REGNO (addr
)]);
783 addr
= XEXP (addr
, 0);
784 print_operand_address (file
, XEXP (addr
, 0));
786 print_operand_address (file
, XEXP (addr
, 1));
790 if (is_regfile_address (XEXP (addr
, 1)))
791 fprintf (file
, "%%lo8data(");
793 fprintf (file
, "%%lo8insn(");
794 print_operand_address (file
, XEXP (addr
, 1));
796 print_operand_address (file
, XEXP (addr
, 0));
799 case PLUS
: /* Ought to be stack or dp references. */
800 if (XEXP (addr
, 1) == const0_rtx
801 && GET_CODE (XEXP (addr
, 0)) == PLUS
)
803 print_operand_address (file
, XEXP (addr
, 0));
807 if (! REG_P (XEXP (addr
, 0)) || REGNO (XEXP (addr
, 0)) != REG_IP
)
808 print_operand_address (file
, XEXP (addr
, 1)); /* const */
809 print_operand_address (file
, XEXP (addr
, 0)); /* (reg) */
813 if (is_regfile_address (XEXP (addr
, 0)))
814 fprintf (file
, "%%hi8data(");
816 fprintf (file
, "%%hi8insn(");
817 output_addr_const (file
, XEXP (addr
, 0));
822 output_addr_const (file
, addr
);
827 /* Output X as assembler operand to file FILE. */
830 print_operand (FILE *file
, rtx x
, int code
)
874 if (ip2k_short_operand (x
, GET_MODE (x
))
875 && ip2k_address_uses_reg_p (x
, REG_SP
))
876 /* An SP-relative address needs to account for interior stack
877 pushes that reload didn't know about when it calculated the
879 abcd
+= ip2k_stack_delta
;
881 switch (GET_CODE (x
))
884 x
= alter_subreg (&x
);
888 fprintf (file
, reg_names
[true_regnum (x
) + abcd
]);
895 fprintf (file
, "$%x", (int)(INTVAL (x
) & 0xffff));
899 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
)); /* bit selector */
902 case 'e': /* "1 << n" - e.g. "exp" */
903 fprintf (file
, "#%d", 1 << INTVAL (x
));
911 value
>>= 8 * (3 - abcd
);
914 fprintf (file
, "#%ld", value
);
918 fprintf (file
, "#%d", (int)((INTVAL (x
) >> 8) & 0xff));
922 fprintf (file
, "#%d", (int)(INTVAL (x
) & 0xff));
933 value
= ((unsigned long long)INTVAL (x
)) >> (8 * (7 - abcd
)) & 0xff;
934 fprintf (file
, "#%ld", value
);
938 fprintf (file
, "#" HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
));
960 abort (); /* Probably an error. */
964 fprintf (file
, "#%s(",
965 is_regfile_address (x
) ? "%hi8data"
967 print_operand_address (file
, x
);
972 fprintf (file
, "#%s(",
973 is_regfile_address (x
) ? "%lo8data"
975 print_operand_address (file
, x
);
980 print_operand_address (file
, x
);
986 rtx addr
= XEXP (x
, 0);
988 if (GET_CODE (addr
) == SUBREG
)
989 addr
= alter_subreg (&x
);
991 if (CONSTANT_P (addr
) && abcd
)
994 print_operand_address (file
, addr
);
995 fprintf (file
, ")+%d", abcd
);
999 switch (GET_CODE (addr
))
1002 abcd
+= INTVAL (XEXP (addr
, 1));
1004 /* Worry about (plus (plus (reg DP) (const_int 10))
1006 if (GET_CODE (XEXP (addr
, 0)) == PLUS
)
1008 addr
= XEXP (addr
, 0);
1009 abcd
+= INTVAL (XEXP (addr
, 1));
1012 fprintf (file
, "%d", abcd
);
1013 print_operand_address (file
, XEXP (addr
, 0));
1018 fprintf (file
, "%d", abcd
);
1019 print_operand_address (file
, addr
);
1022 else if (GET_CODE (addr
) == REG
1023 && (REGNO (addr
) == REG_DP
|| REGNO (addr
) == REG_SP
))
1025 fprintf (file
, "0");
1026 print_operand_address (file
, addr
);
1029 print_operand_address (file
, addr
);
1034 /* Is this an integer or a floating point value? */
1035 if (GET_MODE (x
) == VOIDmode
)
1043 value
= CONST_DOUBLE_HIGH (x
);
1044 value
>>= 8 * (3 - abcd
);
1047 fprintf (file
, "#%ld", value
);
1054 value
= CONST_DOUBLE_LOW (x
);
1055 value
>>= 8 * (7 - abcd
);
1058 fprintf (file
, "#%ld", value
);
1067 REAL_VALUE_FROM_CONST_DOUBLE (rv
, x
);
1068 REAL_VALUE_TO_TARGET_SINGLE (rv
, value
);
1069 fprintf (file
, "0x%lx", value
);
1074 fatal_insn ("bad operand", x
);
1078 /* Remember the operands for the compare. */
1080 ip2k_set_compare (rtx x
, rtx y
)
1082 ip2k_compare_operands
[0] = x
;
1083 ip2k_compare_operands
[1] = y
;
1087 /* Emit the code for sCOND instructions. */
1089 ip2k_gen_sCOND (rtx insn ATTRIBUTE_UNUSED
, enum rtx_code code
, rtx dest
)
1091 #define operands ip2k_compare_operands
1092 enum machine_mode mode
;
1096 mode
= GET_MODE (operands
[0]);
1097 if ((mode
!= QImode
) && (mode
!= HImode
)
1098 && (mode
!= SImode
) && (mode
!= DImode
))
1099 mode
= GET_MODE (operands
[1]);
1101 /* We have a fast path for a specific type of QImode compare. We ought
1102 to extend this for larger cases too but that wins less frequently and
1103 introduces a lot of complexity. */
1105 && !rtx_equal_p (operands
[0], operands
[2])
1106 && !rtx_equal_p (operands
[1], operands
[2])
1107 && (! REG_P (operands
[2])
1108 || (ip2k_xexp_not_uses_reg_p (operands
[0], REGNO (operands
[2]), 1)
1109 && ip2k_xexp_not_uses_reg_p (operands
[1],
1110 REGNO (operands
[2]), 1))))
1113 if (immediate_operand (operands
[1], QImode
)
1114 && ((INTVAL (operands
[1]) & 0xff) == 0xff))
1117 OUT_AS2 (incsnz
, w
, %0);
1119 OUT_AS2 (incsz
, w
, %0);
1121 else if (immediate_operand (operands
[1], QImode
)
1122 && ((INTVAL (operands
[1]) & 0xff) == 0x01))
1125 OUT_AS2 (decsnz
, w
, %0);
1127 OUT_AS2 (decsz
, w
, %0);
1129 else if (ip2k_compare_operands
[1] == const0_rtx
)
1131 OUT_AS2 (mov
, w
, %0);
1139 OUT_AS2 (mov
, w
, %0);
1141 OUT_AS2 (csne
, w
, %1);
1143 OUT_AS2 (cse
, w
, %1);
1149 if (ip2k_compare_operands
[1] == const0_rtx
)
1154 OUT_AS2 (mov
, w
, %0);
1158 OUT_AS2 (mov
, w
, %H0
);
1159 OUT_AS2 (or, w
, %L0
);
1163 OUT_AS2 (mov
, w
, %A0
);
1164 OUT_AS2 (or, w
, %B0
);
1165 OUT_AS2 (or, w
, %C0
);
1166 OUT_AS2 (or, w
, %D0
);
1170 OUT_AS2 (mov
, w
, %S0
);
1171 OUT_AS2 (or, w
, %T0
);
1172 OUT_AS2 (or, w
, %U0
);
1173 OUT_AS2 (or, w
, %V0
);
1174 OUT_AS2 (or, w
, %W0
);
1175 OUT_AS2 (or, w
, %X0
);
1176 OUT_AS2 (or, w
, %Y0
);
1177 OUT_AS2 (or, w
, %Z0
);
1189 OUT_AS2 (mov
, w
, %1);
1190 OUT_AS2 (cmp
, w
, %0);
1194 OUT_AS2 (mov
, w
, %H1
);
1195 OUT_AS2 (cmp
, w
, %H0
);
1199 OUT_AS2 (mov
, w
, %L1
);
1200 OUT_AS2 (cmp
, w
, %L0
);
1207 OUT_AS2 (mov
, w
, #1);
1208 OUT_AS2 (mov
, mulh
, w
);
1211 OUT_AS1 (clr
, mulh
);
1212 OUT_AS2 (mov
, w
, %A1
);
1213 OUT_AS2 (cse
, w
, %A0
);
1216 OUT_AS2 (mov
, w
, %B1
);
1217 OUT_AS2 (cse
, w
, %B0
);
1220 OUT_AS2 (mov
, w
, %C1
);
1221 OUT_AS2 (cse
, w
, %C0
);
1224 OUT_AS2 (mov
, w
, %D1
);
1225 OUT_AS2 (cse
, w
, %D0
);
1228 OUT_AS1 (dec
, mulh
);
1230 OUT_AS1 (inc
, mulh
);
1231 OUT_AS2 (mov
, w
, mulh
);
1232 OUT_AS2 (mov
, %2, w
);
1238 OUT_AS2 (mov
, w
, #1);
1239 OUT_AS2 (mov
, mulh
, w
);
1242 OUT_AS1 (clr
, mulh
);
1243 OUT_AS2 (mov
, w
, %S1
);
1244 OUT_AS2 (cse
, w
, %S0
);
1247 OUT_AS2 (mov
, w
, %T1
);
1248 OUT_AS2 (cse
, w
, %T0
);
1251 OUT_AS2 (mov
, w
, %U1
);
1252 OUT_AS2 (cse
, w
, %U0
);
1255 OUT_AS2 (mov
, w
, %V1
);
1256 OUT_AS2 (cse
, w
, %V0
);
1259 OUT_AS2 (mov
, w
, %W1
);
1260 OUT_AS2 (cse
, w
, %W0
);
1263 OUT_AS2 (mov
, w
, %X1
);
1264 OUT_AS2 (cse
, w
, %X0
);
1267 OUT_AS2 (mov
, w
, %Y1
);
1268 OUT_AS2 (cse
, w
, %Y0
);
1271 OUT_AS2 (mov
, w
, %Z1
);
1272 OUT_AS2 (cse
, w
, %Z0
);
1275 OUT_AS1 (dec
, mulh
);
1277 OUT_AS1 (inc
, mulh
);
1278 OUT_AS2 (mov
, w
, mulh
);
1279 OUT_AS2 (mov
, %2, w
);
1286 OUT_AS2 (mov
, w
, #0);
1291 OUT_AS1 (inc
, wreg
);
1292 OUT_AS2 (mov
, %2, w
);
1300 ip2k_gen_signed_comp_branch (rtx insn
, enum rtx_code code
, rtx label
)
1302 #define operands ip2k_compare_operands
1303 enum machine_mode mode
;
1304 int can_use_skip
= 0;
1307 operands
[2] = label
;
1309 mode
= GET_MODE (operands
[0]);
1310 if ((mode
!= QImode
) && (mode
!= HImode
)
1311 && (mode
!= SImode
) && (mode
!= DImode
))
1312 mode
= GET_MODE (operands
[1]);
1314 /* Look for situations where we can just skip the next instruction instead
1315 of skipping and then branching! */
1316 ninsn
= next_real_insn (insn
);
1318 && (recog_memoized (ninsn
) >= 0)
1319 && get_attr_skip (ninsn
) == SKIP_YES
)
1321 rtx skip_tgt
= next_nonnote_insn (next_real_insn (insn
));
1323 /* The first situation is where the target of the jump is one insn
1324 after the jump insn and the insn being jumped is only one machine
1326 if (label
== skip_tgt
)
1330 /* If our skip target is in fact a code label then we ignore the
1331 label and move onto the next useful instruction. Nothing we do
1332 here has any effect on the use of skipping instructions. */
1333 if (GET_CODE (skip_tgt
) == CODE_LABEL
)
1334 skip_tgt
= next_nonnote_insn (skip_tgt
);
1336 /* The second situation is where we have something of the form:
1342 optional_label (this may or may not exist):
1346 In this case we can eliminate the first "page/jump label". */
1347 if (GET_CODE (skip_tgt
) == JUMP_INSN
)
1349 rtx set
= single_set (skip_tgt
);
1350 if (GET_CODE (XEXP (set
, 0)) == PC
1351 && GET_CODE (XEXP (set
, 1)) == LABEL_REF
1352 && label
== JUMP_LABEL (skip_tgt
))
1358 /* gcc is a little braindead and does some rather stateful things while
1359 inspecting attributes - we have to put this state back to what it's
1361 extract_constrain_insn_cached (insn
);
1363 if (ip2k_compare_operands
[1] == const0_rtx
) /* These are easier. */
1370 OUT_AS2 (sb
, %0, 7);
1374 OUT_AS2 (snb
, %0, 7);
1384 OUT_AS2 (rl
, w
, %S0
);
1385 OUT_AS2 (mov
, w
, %S0
);
1386 OUT_AS2 (or, w
, %T0
);
1387 OUT_AS2 (or, w
, %U0
);
1388 OUT_AS2 (or, w
, %V0
);
1389 OUT_AS2 (or, w
, %W0
);
1390 OUT_AS2 (or, w
, %X0
);
1391 OUT_AS2 (or, w
, %Y0
);
1392 OUT_AS2 (or, w
, %Z0
);
1394 OUT_AS2 (setb
, status
, 0);
1395 OUT_AS2 (sb
, status
, 0);
1401 OUT_AS2 (rl
, w
, %A0
);
1402 OUT_AS2 (mov
, w
, %A0
);
1403 OUT_AS2 (or, w
, %B0
);
1404 OUT_AS2 (or, w
, %C0
);
1405 OUT_AS2 (or, w
, %D0
);
1407 OUT_AS2 (setb
, status
, 0);
1408 OUT_AS2 (sb
, status
, 0);
1414 OUT_AS2 (rl
, w
, %H0
);
1415 OUT_AS2 (mov
, w
, %H0
);
1416 OUT_AS2 (or, w
, %L0
);
1418 OUT_AS2 (setb
, status
, 0);
1419 OUT_AS2 (sb
, status
, 0);
1425 OUT_AS2 (mov
, w
, %0); /* Will just do "sb w, 7". */
1427 OUT_AS2 (setb
, wreg
, 7);
1428 OUT_AS2 (sb
, wreg
, 7);
1442 OUT_AS2 (mov
, w
, %S0
);
1443 OUT_AS2 (or, w
, %T0
);
1444 OUT_AS2 (or, w
, %U0
);
1445 OUT_AS2 (or, w
, %V0
);
1446 OUT_AS2 (or, w
, %W0
);
1447 OUT_AS2 (or, w
, %X0
);
1448 OUT_AS2 (or, w
, %Y0
);
1449 OUT_AS2 (or, w
, %Z0
); /* Z is correct. */
1451 OUT_AS2 (snb
, %S0
, 7);
1457 OUT_AS2 (mov
, w
, %A0
);
1458 OUT_AS2 (or, w
, %B0
);
1459 OUT_AS2 (or, w
, %C0
);
1460 OUT_AS2 (or, w
, %D0
); /* Z is correct. */
1462 OUT_AS2 (snb
, %A0
, 7);
1468 OUT_AS2 (mov
, w
, %H0
);
1469 OUT_AS2 (or, w
, %L0
);
1471 OUT_AS2 (snb
, %H0
, 7);
1477 OUT_AS2 (mov
, w
, %0); /* Will just do "sb w, 7". */
1479 OUT_AS2 (snb
, wreg
, 7);
1492 OUT_AS2 (snb
, %0, 7);
1496 OUT_AS2 (sb
, %0, 7);
1508 /* signed compares are out of line because we can't get
1509 the hardware to compute the overflow for us. */
1514 OUT_AS1 (push
, %1%<);
1515 OUT_AS1 (push
, %0%>);
1516 OUT_AS1 (page
, __cmpqi2
);
1517 OUT_AS1 (call
, __cmpqi2
);
1521 OUT_AS1 (push
, %L1
%<);
1522 OUT_AS1 (push
, %H1
%<);
1523 OUT_AS1 (push
, %L0
%<);
1524 OUT_AS1 (push
, %H0
%>%>%>);
1525 OUT_AS1 (page
, __cmphi2
);
1526 OUT_AS1 (call
, __cmphi2
);
1530 OUT_AS1 (push
, %D1
%<);
1531 OUT_AS1 (push
, %C1
%<);
1532 OUT_AS1 (push
, %B1
%<);
1533 OUT_AS1 (push
, %A1
%<);
1534 OUT_AS1 (push
, %D0
%<);
1535 OUT_AS1 (push
, %C0
%<);
1536 OUT_AS1 (push
, %B0
%<);
1537 OUT_AS1 (push
, %A0
%>%>%>%>%>%>%>);
1538 OUT_AS1 (page
, __cmpsi2
);
1539 OUT_AS1 (call
, __cmpsi2
);
1543 if (GET_CODE (operands
[0]) == MEM
1544 && true_regnum (XEXP (operands
[0], 0)) == REG_DP
)
1546 OUT_AS1 (push
, %Z1
%<);
1547 OUT_AS1 (push
, %Y1
%<);
1548 OUT_AS1 (push
, %X1
%<);
1549 OUT_AS1 (push
, %W1
%<);
1550 OUT_AS1 (push
, %V1
%<);
1551 OUT_AS1 (push
, %U1
%<);
1552 OUT_AS1 (push
, %T1
%<);
1553 OUT_AS1 (push
, %S1
%>%>%>%>%>%>%>);
1554 OUT_AS1 (page
, __cmpdi2_dp
);
1555 OUT_AS1 (call
, __cmpdi2_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 (push
, %Z0
%<);
1568 OUT_AS1 (push
, %Y0
%<);
1569 OUT_AS1 (push
, %X0
%<);
1570 OUT_AS1 (push
, %W0
%<);
1571 OUT_AS1 (push
, %V0
%<);
1572 OUT_AS1 (push
, %U0
%<);
1573 OUT_AS1 (push
, %T0
%<);
1574 OUT_AS1 (push
, %S0
%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>);
1575 OUT_AS1 (page
, __cmpdi2
);
1576 OUT_AS1 (call
, __cmpdi2
);
1589 OUT_AS2 (cse
, w
, #0);
1593 OUT_AS2 (csne
, w
, #0);
1602 OUT_AS2 (cse
, w
, #2);
1606 OUT_AS2 (csne
, w
, #2);
1615 OUT_AS2 (snb
, wreg
, 1);
1619 OUT_AS2 (sb
, wreg
, 1);
1628 OUT_AS2 (csne
, w
, #0);
1632 OUT_AS2 (cse
, w
, #0);
1646 ip2k_gen_unsigned_comp_branch (rtx insn
, enum rtx_code code
, rtx label
)
1648 #define operands ip2k_compare_operands
1649 enum machine_mode mode
;
1652 int can_use_skip
= 0;
1654 HOST_WIDE_INT const_low
;
1655 HOST_WIDE_INT const_high
;
1657 operands
[2] = label
;
1659 mode
= GET_MODE (operands
[0]);
1660 if ((mode
!= QImode
) && (mode
!= HImode
) && (mode
!= SImode
)
1661 && (mode
!= DImode
))
1663 mode
= GET_MODE (operands
[1]);
1666 /* Look for situations where we can just skip the next instruction instead
1667 of skipping and then branching! */
1668 ninsn
= next_real_insn (insn
);
1670 && (recog_memoized (ninsn
) >= 0)
1671 && get_attr_skip (ninsn
) == SKIP_YES
)
1673 rtx skip_tgt
= next_nonnote_insn (next_real_insn (insn
));
1675 /* The first situation is where the target of the jump is one insn
1676 after the jump insn and the insn being jumped is only one machine
1678 if (label
== skip_tgt
)
1682 /* If our skip target is in fact a code label then we ignore the
1683 label and move onto the next useful instruction. Nothing we do
1684 here has any effect on the use of skipping instructions. */
1685 if (GET_CODE (skip_tgt
) == CODE_LABEL
)
1686 skip_tgt
= next_nonnote_insn (skip_tgt
);
1688 /* The second situation is where we have something of the form:
1694 optional_label (this may or may not exist):
1698 In this case we can eliminate the first "page/jump label". */
1699 if (GET_CODE (skip_tgt
) == JUMP_INSN
)
1701 rtx set
= single_set (skip_tgt
);
1702 if (GET_CODE (XEXP (set
, 0)) == PC
1703 && GET_CODE (XEXP (set
, 1)) == LABEL_REF
1704 && label
== JUMP_LABEL (skip_tgt
))
1710 /* gcc is a little braindead and does some rather stateful things while
1711 inspecting attributes - we have to put this state back to what it's
1713 extract_constrain_insn_cached (insn
);
1715 if (ip2k_compare_operands
[1] == const0_rtx
)
1720 code
= EQ
; /* Nothing is LTU 0. */
1724 code
= NE
; /* Anything nonzero is GTU. */
1728 case NE
: /* Test all the bits, result in
1734 OUT_AS2 (mov
, w
, %S0
);
1735 OUT_AS2 (or, w
, %T0
);
1736 OUT_AS2 (or, w
, %U0
);
1737 OUT_AS2 (or, w
, %V0
);
1738 OUT_AS2 (or, w
, %W0
);
1739 OUT_AS2 (or, w
, %X0
);
1740 OUT_AS2 (or, w
, %Y0
);
1741 OUT_AS2 (or, w
, %Z0
);
1745 OUT_AS2 (mov
, w
, %A0
);
1746 OUT_AS2 (or, w
, %B0
);
1747 OUT_AS2 (or, w
, %C0
);
1748 OUT_AS2 (or, w
, %D0
);
1752 OUT_AS2 (mov
, w
, %H0
);
1753 OUT_AS2 (or, w
, %L0
);
1757 OUT_AS2 (mov
, w
, %0);
1783 /* Always succeed. */
1798 /* Look at whether we have a constant as one of our operands. If we do
1799 and it's in the position that we use to subtract from during our
1800 normal optimized comparison concept then we have to shuffle things
1804 if ((immediate_operand (operands
[1], GET_MODE (operands
[1]))
1805 && ((code
== LEU
) || (code
== GTU
)))
1806 || (immediate_operand (operands
[0], GET_MODE (operands
[0]))
1807 && ((code
== LTU
) || (code
== GEU
))))
1813 /* Same as above - look if we have a constant that we can compare
1814 for equality or non-equality. If we know this then we can look
1815 for common value eliminations. Note that we want to ensure that
1816 any immediate value is operand 1 to simplify the code later! */
1817 if ((code
== EQ
) || (code
== NE
))
1819 imm_cmp
= immediate_operand (operands
[1], GET_MODE (operands
[1]));
1822 imm_cmp
= immediate_operand (operands
[0], GET_MODE (operands
[0]));
1825 rtx tmp
= operands
[1];
1826 operands
[1] = operands
[0];
1838 if (imm_cmp
&& ((INTVAL (operands
[1]) & 0xff) == 0xff))
1839 OUT_AS2 (incsnz
, w
, %0);
1840 else if (imm_cmp
&& ((INTVAL (operands
[1]) & 0xff) == 0x01))
1841 OUT_AS2 (decsnz
, w
, %0);
1844 OUT_AS2 (mov
, w
, %1);
1845 OUT_AS2 (csne
, w
, %0);
1852 if (imm_cmp
&& ((INTVAL (operands
[1]) & 0xff) == 0xff))
1853 OUT_AS2 (incsz
, w
, %0);
1854 else if (imm_cmp
&& ((INTVAL (operands
[1]) & 0xff) == 0x01))
1855 OUT_AS2 (decsz
, w
, %0);
1858 OUT_AS2 (mov
, w
, %1);
1859 OUT_AS2 (cse
, w
, %0);
1866 OUT_AS2 (mov
, w
, %0);
1867 OUT_AS2 (cmp
, w
, %1);
1874 OUT_AS2 (mov
, w
, %1);
1875 OUT_AS2 (cmp
, w
, %0);
1882 OUT_AS2 (mov
, w
, %1);
1883 OUT_AS2 (cmp
, w
, %0);
1890 OUT_AS2 (mov
, w
, %0);
1891 OUT_AS2 (cmp
, w
, %1);
1907 unsigned char h
= 0, l
= 1;
1911 h
= (INTVAL (operands
[1]) >> 8) & 0xff;
1912 l
= INTVAL (operands
[1]) & 0xff;
1914 if ((h
== 0xff) && (l
== 0xff))
1916 /* We should be able to do the following, but the
1917 IP2k simulator doesn't like it and we get a load
1918 of failures in gcc-c-torture. */
1919 OUT_AS2 (incsnz
, w
, %L0
);
1920 OUT_AS2 (incsz
, w
, %H0
);
1921 /* OUT_AS1 (skip,); Should have this */
1922 OUT_AS1 (page
, 1f
);/* Shouldn't need this! */
1923 OUT_AS1 (jmp
, 1f
); /* Shouldn't need this either. */
1932 OUT_AS2 (dec
, w
, %L0
);
1935 OUT_AS2 (mov
, w
, %L0
);
1936 OUT_AS2 (sub
, w
, %L1
);
1938 OUT_AS2 (or, w
, %H0
);
1947 OUT_AS2 (dec
, w
, %H0
);
1950 OUT_AS2 (mov
, w
, %H0
);
1951 OUT_AS2 (sub
, w
, %H1
);
1953 OUT_AS2 (or, w
, %L0
);
1961 OUT_AS2 (mov
, w
, %H1
);
1962 OUT_AS2 (cse
, w
, %H0
);
1965 if (! imm_cmp
|| (h
!= l
))
1966 OUT_AS2 (mov
, w
, %L1
);
1967 OUT_AS2 (csne
, w
, %L0
);
1976 unsigned char h
= 0, l
= 1;
1980 h
= (INTVAL (operands
[1]) >> 8) & 0xff;
1981 l
= INTVAL (operands
[1]) & 0xff;
1983 if ((h
== 0xff) && (l
== 0xff))
1985 OUT_AS2 (incsnz
, w
, %L0
);
1986 OUT_AS2 (incsz
, w
, %H0
);
1994 OUT_AS2 (dec
, w
, %L0
);
1997 OUT_AS2 (mov
, w
, %L0
);
1998 OUT_AS2 (sub
, w
, %L1
);
2000 OUT_AS2 (or, w
, %H0
);
2009 OUT_AS2 (dec
, w
, %H0
);
2012 OUT_AS2 (mov
, w
, %H0
);
2013 OUT_AS2 (sub
, w
, %H1
);
2015 OUT_AS2 (or, w
, %L0
);
2023 OUT_AS2 (mov
, w
, %H1
);
2024 if (imm_cmp
&& (h
== l
))
2026 OUT_AS2 (csne
, w
, %H0
);
2027 OUT_AS2 (cse
, w
, %L0
);
2031 OUT_AS2 (cse
, w
, %H0
);
2034 OUT_AS2 (mov
, w
, %L1
);
2035 OUT_AS2 (cse
, w
, %L0
);
2045 /* > 0xffff never succeeds! */
2046 if ((INTVAL (operands
[1]) & 0xffff) != 0xffff)
2048 operands
[3] = GEN_INT (INTVAL (operands
[1]) + 1);
2049 OUT_AS2 (mov
, w
, %L3
);
2050 OUT_AS2 (sub
, w
, %L0
);
2051 OUT_AS2 (mov
, w
, %H3
);
2052 OUT_AS2 (subc
, w
, %H0
);
2060 OUT_AS2 (mov
, w
, %L0
);
2061 OUT_AS2 (sub
, w
, %L1
);
2062 OUT_AS2 (mov
, w
, %H0
);
2063 OUT_AS2 (subc
, w
, %H1
);
2073 if (INTVAL (operands
[0]) == 0)
2075 OUT_AS2 (mov
, w
, %H1
);
2076 OUT_AS2 (or, w
, %L1
);
2083 operands
[3] = GEN_INT (INTVAL (operands
[0]) - 1);
2084 OUT_AS2 (mov
, w
, %L3
);
2085 OUT_AS2 (sub
, w
, %L1
);
2086 OUT_AS2 (mov
, w
, %H3
);
2087 OUT_AS2 (subc
, w
, %H1
);
2095 OUT_AS2 (mov
, w
, %L1
);
2096 OUT_AS2 (sub
, w
, %L0
);
2097 OUT_AS2 (mov
, w
, %H1
);
2098 OUT_AS2 (subc
, w
, %H0
);
2108 if (INTVAL (operands
[0]) == 0)
2110 OUT_AS2 (mov
, w
, %H1
);
2111 OUT_AS2 (or, w
, %L1
);
2118 operands
[3] = GEN_INT (INTVAL (operands
[0]) - 1);
2119 OUT_AS2 (mov
, w
, %L3
);
2120 OUT_AS2 (sub
, w
, %L1
);
2121 OUT_AS2 (mov
, w
, %H3
);
2122 OUT_AS2 (subc
, w
, %H1
);
2130 OUT_AS2 (mov
, w
, %L1
);
2131 OUT_AS2 (sub
, w
, %L0
);
2132 OUT_AS2 (mov
, w
, %H1
);
2133 OUT_AS2 (subc
, w
, %H0
);
2143 if ((INTVAL (operands
[1]) & 0xffff) == 0xffff)
2145 /* <= 0xffff always succeeds. */
2151 operands
[3] = GEN_INT (INTVAL (operands
[1]) + 1);
2152 OUT_AS2 (mov
, w
, %L3
);
2153 OUT_AS2 (sub
, w
, %L0
);
2154 OUT_AS2 (mov
, w
, %H3
);
2155 OUT_AS2 (subc
, w
, %H0
);
2163 OUT_AS2 (mov
, w
, %L0
);
2164 OUT_AS2 (sub
, w
, %L1
);
2165 OUT_AS2 (mov
, w
, %H0
);
2166 OUT_AS2 (subc
, w
, %H1
);
2183 unsigned char a
= 0, b
= 1, c
= 2, d
= 3;
2187 a
= (INTVAL (operands
[1]) >> 24) & 0xff;
2188 b
= (INTVAL (operands
[1]) >> 16) & 0xff;
2189 c
= (INTVAL (operands
[1]) >> 8) & 0xff;
2190 d
= INTVAL (operands
[1]) & 0xff;
2193 OUT_AS2 (mov
, w
, %A1
);
2194 if (imm_cmp
&& (b
== a
))
2196 OUT_AS2 (csne
, w
, %A0
);
2197 OUT_AS2 (cse
, w
, %B0
);
2201 OUT_AS2 (cse
, w
, %A0
);
2204 OUT_AS2 (mov
, w
, %B1
);
2205 OUT_AS2 (cse
, w
, %B0
);
2209 if (! imm_cmp
|| (c
!= b
))
2210 OUT_AS2 (mov
, w
, %C1
);
2211 OUT_AS2 (cse
, w
, %C0
);
2214 if (! imm_cmp
|| (d
!= c
))
2215 OUT_AS2 (mov
, w
, %D1
);
2216 OUT_AS2 (csne
, w
, %D0
);
2225 unsigned char a
= 0, b
= 1, c
= 2, d
= 3;
2229 a
= (INTVAL (operands
[1]) >> 24) & 0xff;
2230 b
= (INTVAL (operands
[1]) >> 16) & 0xff;
2231 c
= (INTVAL (operands
[1]) >> 8) & 0xff;
2232 d
= INTVAL (operands
[1]) & 0xff;
2235 OUT_AS2 (mov
, w
, %A1
);
2236 if (imm_cmp
&& (b
== a
))
2238 OUT_AS2 (csne
, w
, %A0
);
2239 OUT_AS2 (cse
, w
, %B0
);
2243 OUT_AS2 (cse
, w
, %A0
);
2246 OUT_AS2 (mov
, w
, %B1
);
2247 OUT_AS2 (cse
, w
, %B0
);
2251 if (! imm_cmp
|| (c
!= b
))
2252 OUT_AS2 (mov
, w
, %C1
);
2253 if (imm_cmp
&& (d
== c
))
2255 OUT_AS2 (csne
, w
, %C0
);
2256 OUT_AS2 (cse
, w
, %D0
);
2260 OUT_AS2 (cse
, w
, %C0
);
2263 OUT_AS2 (mov
, w
, %D1
);
2264 OUT_AS2 (cse
, w
, %D0
);
2274 /* > 0xffffffff never succeeds! */
2275 if ((unsigned HOST_WIDE_INT
)(INTVAL (operands
[1]) & 0xffffffff)
2278 operands
[3] = GEN_INT (INTVAL (operands
[1]) + 1);
2279 OUT_AS2 (mov
, w
, %D3
);
2280 OUT_AS2 (sub
, w
, %D0
);
2281 OUT_AS2 (mov
, w
, %C3
);
2282 OUT_AS2 (subc
, w
, %C0
);
2283 OUT_AS2 (mov
, w
, %B3
);
2284 OUT_AS2 (subc
, w
, %B0
);
2285 OUT_AS2 (mov
, w
, %A3
);
2286 OUT_AS2 (subc
, w
, %A0
);
2294 OUT_AS2 (mov
, w
, %D0
);
2295 OUT_AS2 (sub
, w
, %D1
);
2296 OUT_AS2 (mov
, w
, %C0
);
2297 OUT_AS2 (subc
, w
, %C1
);
2298 OUT_AS2 (mov
, w
, %B0
);
2299 OUT_AS2 (subc
, w
, %B1
);
2300 OUT_AS2 (mov
, w
, %A0
);
2301 OUT_AS2 (subc
, w
, %A1
);
2311 if (INTVAL (operands
[0]) == 0)
2313 OUT_AS2 (mov
, w
, %A1
);
2314 OUT_AS2 (or, w
, %B1
);
2315 OUT_AS2 (or, w
, %C1
);
2316 OUT_AS2 (or, w
, %D1
);
2323 operands
[3] = GEN_INT (INTVAL (operands
[0]) - 1);
2324 OUT_AS2 (mov
, w
, %D3
);
2325 OUT_AS2 (sub
, w
, %D1
);
2326 OUT_AS2 (mov
, w
, %C3
);
2327 OUT_AS2 (subc
, w
, %C1
);
2328 OUT_AS2 (mov
, w
, %B3
);
2329 OUT_AS2 (subc
, w
, %B1
);
2330 OUT_AS2 (mov
, w
, %A3
);
2331 OUT_AS2 (subc
, w
, %A1
);
2339 OUT_AS2 (mov
, w
, %D1
);
2340 OUT_AS2 (sub
, w
, %D0
);
2341 OUT_AS2 (mov
, w
, %C1
);
2342 OUT_AS2 (subc
, w
, %C0
);
2343 OUT_AS2 (mov
, w
, %B1
);
2344 OUT_AS2 (subc
, w
, %B0
);
2345 OUT_AS2 (mov
, w
, %A1
);
2346 OUT_AS2 (subc
, w
, %A0
);
2356 if (INTVAL (operands
[0]) == 0)
2358 OUT_AS2 (mov
, w
, %A1
);
2359 OUT_AS2 (or, w
, %B1
);
2360 OUT_AS2 (or, w
, %C1
);
2361 OUT_AS2 (or, w
, %D1
);
2368 operands
[3] = GEN_INT (INTVAL (operands
[0]) - 1);
2369 OUT_AS2 (mov
, w
, %D3
);
2370 OUT_AS2 (sub
, w
, %D1
);
2371 OUT_AS2 (mov
, w
, %C3
);
2372 OUT_AS2 (subc
, w
, %C1
);
2373 OUT_AS2 (mov
, w
, %B3
);
2374 OUT_AS2 (subc
, w
, %B1
);
2375 OUT_AS2 (mov
, w
, %A3
);
2376 OUT_AS2 (subc
, w
, %A1
);
2384 OUT_AS2 (mov
, w
, %D1
);
2385 OUT_AS2 (sub
, w
, %D0
);
2386 OUT_AS2 (mov
, w
, %C1
);
2387 OUT_AS2 (subc
, w
, %C0
);
2388 OUT_AS2 (mov
, w
, %B1
);
2389 OUT_AS2 (subc
, w
, %B0
);
2390 OUT_AS2 (mov
, w
, %A1
);
2391 OUT_AS2 (subc
, w
, %A0
);
2401 if ((unsigned HOST_WIDE_INT
)(INTVAL (operands
[1]) & 0xffffffff)
2404 /* <= 0xffffffff always succeeds. */
2410 operands
[3] = GEN_INT (INTVAL (operands
[1]) + 1);
2411 OUT_AS2 (mov
, w
, %D3
);
2412 OUT_AS2 (sub
, w
, %D0
);
2413 OUT_AS2 (mov
, w
, %C3
);
2414 OUT_AS2 (subc
, w
, %C0
);
2415 OUT_AS2 (mov
, w
, %B3
);
2416 OUT_AS2 (subc
, w
, %B0
);
2417 OUT_AS2 (mov
, w
, %A3
);
2418 OUT_AS2 (subc
, w
, %A0
);
2426 OUT_AS2 (mov
, w
, %D0
);
2427 OUT_AS2 (sub
, w
, %D1
);
2428 OUT_AS2 (mov
, w
, %C0
);
2429 OUT_AS2 (subc
, w
, %C1
);
2430 OUT_AS2 (mov
, w
, %B0
);
2431 OUT_AS2 (subc
, w
, %B1
);
2432 OUT_AS2 (mov
, w
, %A0
);
2433 OUT_AS2 (subc
, w
, %A1
);
2446 if (GET_CODE (operands
[1]) == CONST_INT
)
2448 const_low
= INTVAL (operands
[1]);
2449 const_high
= (const_low
>= 0) - 1;
2451 else if (GET_CODE (operands
[1]) == CONST_DOUBLE
)
2453 const_low
= CONST_DOUBLE_LOW (operands
[1]);
2454 const_high
= CONST_DOUBLE_HIGH (operands
[1]);
2460 unsigned char s
= 0, t
= 1, u
= 2, v
= 3;
2461 unsigned char w
= 4, x
= 5, y
= 6, z
= 7;
2464 if (GET_CODE (operands
[0]) == MEM
2465 && true_regnum (XEXP (operands
[0], 0)) == REG_DP
)
2467 OUT_AS1 (push
, %Z1
%<);
2468 OUT_AS1 (push
, %Y1
%<);
2469 OUT_AS1 (push
, %X1
%<);
2470 OUT_AS1 (push
, %W1
%<);
2471 OUT_AS1 (push
, %V1
%<);
2472 OUT_AS1 (push
, %U1
%<);
2473 OUT_AS1 (push
, %T1
%<);
2474 OUT_AS1 (push
, %S1
%>%>%>%>%>%>%>);
2475 OUT_AS1 (page
, __cmpdi2_dp
);
2476 OUT_AS1 (call
, __cmpdi2_dp
);
2477 OUT_AS2 (csne
, w
, #1);
2483 OUT_AS1 (push
, %Z1
%<);
2484 OUT_AS1 (push
, %Y1
%<);
2485 OUT_AS1 (push
, %X1
%<);
2486 OUT_AS1 (push
, %W1
%<);
2487 OUT_AS1 (push
, %V1
%<);
2488 OUT_AS1 (push
, %U1
%<);
2489 OUT_AS1 (push
, %T1
%<);
2490 OUT_AS1 (push
, %S1
%<);
2491 OUT_AS1 (push
, %Z0
%<);
2492 OUT_AS1 (push
, %Y0
%<);
2493 OUT_AS1 (push
, %X0
%<);
2494 OUT_AS1 (push
, %W0
%<);
2495 OUT_AS1 (push
, %V0
%<);
2496 OUT_AS1 (push
, %U0
%<);
2497 OUT_AS1 (push
, %T0
%<);
2498 OUT_AS1 (push
, %S0
%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>);
2499 OUT_AS1 (page
, __cmpdi2
);
2500 OUT_AS1 (call
, __cmpdi2
);
2501 OUT_AS2 (csne
, w
, #1);
2510 s
= (const_high
>> 24) & 0xff;
2511 t
= (const_high
>> 16) & 0xff;
2512 u
= (const_high
>> 8) & 0xff;
2513 v
= const_high
& 0xff;
2514 w
= (const_low
>> 24) & 0xff;
2515 x
= (const_low
>> 16) & 0xff;
2516 y
= (const_low
>> 8) & 0xff;
2517 z
= const_low
& 0xff;
2520 OUT_AS2 (mov
, w
, %S1
);
2521 if (imm_cmp
&& (s
== t
))
2523 OUT_AS2 (csne
, w
, %S0
);
2524 OUT_AS2 (cse
, w
, %T0
);
2528 OUT_AS2 (cse
, w
, %S0
);
2531 OUT_AS2 (mov
, w
, %T1
);
2532 OUT_AS2 (cse
, w
, %T0
);
2537 OUT_AS2 (mov
, w
, %U1
);
2538 if (imm_cmp
&& (u
== v
))
2540 OUT_AS2 (csne
, w
, %U0
);
2541 OUT_AS2 (cse
, w
, %V0
);
2545 OUT_AS2 (cse
, w
, %U0
);
2548 OUT_AS2 (mov
, w
, %V1
);
2549 OUT_AS2 (cse
, w
, %V0
);
2554 OUT_AS2 (mov
, w
, %W1
);
2555 if (imm_cmp
&& (w
== x
))
2557 OUT_AS2 (csne
, w
, %W0
);
2558 OUT_AS2 (cse
, w
, %X0
);
2562 OUT_AS2 (cse
, w
, %W0
);
2565 OUT_AS2 (mov
, w
, %X1
);
2566 OUT_AS2 (cse
, w
, %X0
);
2571 if (! imm_cmp
|| (x
!= y
))
2572 OUT_AS2 (mov
, w
, %Y1
);
2573 OUT_AS2 (cse
, w
, %Y0
);
2576 if (! imm_cmp
|| (z
!= y
))
2577 OUT_AS2 (mov
, w
, %Z1
);
2578 OUT_AS2 (csne
, w
, %Z0
);
2588 unsigned char s
= 0, t
= 1, u
= 2, v
= 3;
2589 unsigned char w
= 4, x
= 5, y
= 6, z
= 7;
2593 if (GET_CODE (operands
[0]) == MEM
2594 && true_regnum (XEXP (operands
[0], 0)) == REG_DP
)
2596 OUT_AS1 (push
, %Z1
%<);
2597 OUT_AS1 (push
, %Y1
%<);
2598 OUT_AS1 (push
, %X1
%<);
2599 OUT_AS1 (push
, %W1
%<);
2600 OUT_AS1 (push
, %V1
%<);
2601 OUT_AS1 (push
, %U1
%<);
2602 OUT_AS1 (push
, %T1
%<);
2603 OUT_AS1 (push
, %S1
%>%>%>%>%>%>%>);
2604 OUT_AS1 (page
, __cmpdi2_dp
);
2605 OUT_AS1 (call
, __cmpdi2_dp
);
2606 OUT_AS2 (cse
, w
, #1);
2612 OUT_AS1 (push
, %Z1
%<);
2613 OUT_AS1 (push
, %Y1
%<);
2614 OUT_AS1 (push
, %X1
%<);
2615 OUT_AS1 (push
, %W1
%<);
2616 OUT_AS1 (push
, %V1
%<);
2617 OUT_AS1 (push
, %U1
%<);
2618 OUT_AS1 (push
, %T1
%<);
2619 OUT_AS1 (push
, %S1
%<);
2620 OUT_AS1 (push
, %Z0
%<);
2621 OUT_AS1 (push
, %Y0
%<);
2622 OUT_AS1 (push
, %X0
%<);
2623 OUT_AS1 (push
, %W0
%<);
2624 OUT_AS1 (push
, %V0
%<);
2625 OUT_AS1 (push
, %U0
%<);
2626 OUT_AS1 (push
, %T0
%<);
2627 OUT_AS1 (push
, %S0
%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>);
2628 OUT_AS1 (page
, __cmpdi2
);
2629 OUT_AS1 (call
, __cmpdi2
);
2630 OUT_AS2 (cse
, w
, #1);
2639 s
= (const_high
>> 24) & 0xff;
2640 t
= (const_high
>> 16) & 0xff;
2641 u
= (const_high
>> 8) & 0xff;
2642 v
= const_high
& 0xff;
2643 w
= (const_low
>> 24) & 0xff;
2644 x
= (const_low
>> 16) & 0xff;
2645 y
= (const_low
>> 8) & 0xff;
2646 z
= const_low
& 0xff;
2649 OUT_AS2 (mov
, w
, %S1
);
2650 if (imm_cmp
&& (s
== t
))
2652 OUT_AS2 (csne
, w
, %S0
);
2653 OUT_AS2 (cse
, w
, %T0
);
2657 OUT_AS2 (cse
, w
, %S0
);
2660 OUT_AS2 (mov
, w
, %T1
);
2661 OUT_AS2 (cse
, w
, %T0
);
2666 OUT_AS2 (mov
, w
, %U1
);
2667 if (imm_cmp
&& (u
== v
))
2669 OUT_AS2 (csne
, w
, %U0
);
2670 OUT_AS2 (cse
, w
, %V0
);
2674 OUT_AS2 (cse
, w
, %U0
);
2677 OUT_AS2 (mov
, w
, %V1
);
2678 OUT_AS2 (cse
, w
, %V0
);
2683 OUT_AS2 (mov
, w
, %W1
);
2684 if (imm_cmp
&& (w
== x
))
2686 OUT_AS2 (csne
, w
, %W0
);
2687 OUT_AS2 (cse
, w
, %X0
);
2691 OUT_AS2 (cse
, w
, %W0
);
2694 OUT_AS2 (mov
, w
, %X1
);
2695 OUT_AS2 (cse
, w
, %X0
);
2700 if (! imm_cmp
|| (y
!= x
))
2701 OUT_AS2 (mov
, w
, %Y1
);
2702 if (imm_cmp
&& (z
== y
))
2704 OUT_AS2 (csne
, w
, %Y0
);
2705 OUT_AS2 (cse
, w
, %Z0
);
2709 OUT_AS2 (cse
, w
, %Y0
);
2712 OUT_AS2 (mov
, w
, %Z1
);
2713 OUT_AS2 (cse
, w
, %Z0
);
2724 /* > 0xffffffffffffffff never suceeds! */
2725 if (((const_high
& 0xffffffff) != 0xffffffff)
2726 || ((const_low
& 0xffffffff) != 0xffffffff))
2728 operands
[3] = GEN_INT (const_low
+ 1);
2729 operands
[4] = GEN_INT (const_high
2730 + (INTVAL (operands
[3]) ? 0 : 1));
2731 OUT_AS2 (mov
, w
, %D3
);
2732 OUT_AS2 (sub
, w
, %Z0
);
2733 OUT_AS2 (mov
, w
, %C3
);
2734 OUT_AS2 (subc
, w
, %Y0
);
2735 OUT_AS2 (mov
, w
, %B3
);
2736 OUT_AS2 (subc
, w
, %X0
);
2737 OUT_AS2 (mov
, w
, %A3
);
2738 OUT_AS2 (subc
, w
, %W0
);
2739 OUT_AS2 (mov
, w
, %D4
);
2740 OUT_AS2 (subc
, w
, %V0
);
2741 OUT_AS2 (mov
, w
, %C4
);
2742 OUT_AS2 (subc
, w
, %U0
);
2743 OUT_AS2 (mov
, w
, %B4
);
2744 OUT_AS2 (subc
, w
, %T0
);
2745 OUT_AS2 (mov
, w
, %A4
);
2746 OUT_AS2 (subc
, w
, %S0
);
2754 OUT_AS2 (mov
, w
, %Z0
);
2755 OUT_AS2 (sub
, w
, %Z1
);
2756 OUT_AS2 (mov
, w
, %Y0
);
2757 OUT_AS2 (subc
, w
, %Y1
);
2758 OUT_AS2 (mov
, w
, %X0
);
2759 OUT_AS2 (subc
, w
, %X1
);
2760 OUT_AS2 (mov
, w
, %W0
);
2761 OUT_AS2 (subc
, w
, %W1
);
2762 OUT_AS2 (mov
, w
, %V0
);
2763 OUT_AS2 (subc
, w
, %V1
);
2764 OUT_AS2 (mov
, w
, %U0
);
2765 OUT_AS2 (subc
, w
, %U1
);
2766 OUT_AS2 (mov
, w
, %T0
);
2767 OUT_AS2 (subc
, w
, %T1
);
2768 OUT_AS2 (mov
, w
, %S0
);
2769 OUT_AS2 (subc
, w
, %S1
);
2779 HOST_WIDE_INT const_low0
;
2780 HOST_WIDE_INT const_high0
;
2782 if (GET_CODE (operands
[0]) == CONST_INT
)
2784 const_low0
= INTVAL (operands
[0]);
2785 const_high0
= (const_low
>= 0) - 1;
2787 else if (GET_CODE (operands
[0]) == CONST_DOUBLE
)
2789 const_low0
= CONST_DOUBLE_LOW (operands
[0]);
2790 const_high0
= CONST_DOUBLE_HIGH (operands
[0]);
2793 if (const_high0
== 0 && const_low0
== 0)
2795 OUT_AS2 (mov
, w
, %S1
);
2796 OUT_AS2 (or, w
, %T1
);
2797 OUT_AS2 (or, w
, %U1
);
2798 OUT_AS2 (or, w
, %V1
);
2799 OUT_AS2 (or, w
, %W1
);
2800 OUT_AS2 (or, w
, %X1
);
2801 OUT_AS2 (or, w
, %Y1
);
2802 OUT_AS2 (or, w
, %Z1
);
2809 operands
[3] = GEN_INT (const_low0
- 1);
2810 operands
[4] = GEN_INT (const_high0
- (const_low0
? 1 : 0));
2811 OUT_AS2 (mov
, w
, %D3
);
2812 OUT_AS2 (sub
, w
, %Z1
);
2813 OUT_AS2 (mov
, w
, %C3
);
2814 OUT_AS2 (subc
, w
, %Y1
);
2815 OUT_AS2 (mov
, w
, %B3
);
2816 OUT_AS2 (subc
, w
, %X1
);
2817 OUT_AS2 (mov
, w
, %A3
);
2818 OUT_AS2 (subc
, w
, %W1
);
2819 OUT_AS2 (mov
, w
, %D4
);
2820 OUT_AS2 (subc
, w
, %V1
);
2821 OUT_AS2 (mov
, w
, %C4
);
2822 OUT_AS2 (subc
, w
, %U1
);
2823 OUT_AS2 (mov
, w
, %B4
);
2824 OUT_AS2 (subc
, w
, %T1
);
2825 OUT_AS2 (mov
, w
, %A4
);
2826 OUT_AS2 (subc
, w
, %S1
);
2834 OUT_AS2 (mov
, w
, %Z1
);
2835 OUT_AS2 (sub
, w
, %Z0
);
2836 OUT_AS2 (mov
, w
, %Y1
);
2837 OUT_AS2 (subc
, w
, %Y0
);
2838 OUT_AS2 (mov
, w
, %X1
);
2839 OUT_AS2 (subc
, w
, %X0
);
2840 OUT_AS2 (mov
, w
, %W1
);
2841 OUT_AS2 (subc
, w
, %W0
);
2842 OUT_AS2 (mov
, w
, %V1
);
2843 OUT_AS2 (subc
, w
, %V0
);
2844 OUT_AS2 (mov
, w
, %U1
);
2845 OUT_AS2 (subc
, w
, %U0
);
2846 OUT_AS2 (mov
, w
, %T1
);
2847 OUT_AS2 (subc
, w
, %T0
);
2848 OUT_AS2 (mov
, w
, %S1
);
2849 OUT_AS2 (subc
, w
, %S0
);
2859 HOST_WIDE_INT const_low0
;
2860 HOST_WIDE_INT const_high0
;
2862 if (GET_CODE (operands
[0]) == CONST_INT
)
2864 const_low0
= INTVAL (operands
[0]);
2865 const_high0
= (const_low
>= 0) - 1;
2867 else if (GET_CODE (operands
[0]) == CONST_DOUBLE
)
2869 const_low0
= CONST_DOUBLE_LOW (operands
[0]);
2870 const_high0
= CONST_DOUBLE_HIGH (operands
[0]);
2873 if (const_high0
== 0 && const_low0
== 0)
2875 OUT_AS2 (mov
, w
, %S1
);
2876 OUT_AS2 (or, w
, %T1
);
2877 OUT_AS2 (or, w
, %U1
);
2878 OUT_AS2 (or, w
, %V1
);
2879 OUT_AS2 (or, w
, %W1
);
2880 OUT_AS2 (or, w
, %X1
);
2881 OUT_AS2 (or, w
, %Y1
);
2882 OUT_AS2 (or, w
, %Z1
);
2889 operands
[3] = GEN_INT (const_low0
- 1);
2890 operands
[4] = GEN_INT (const_high0
- (const_low0
? 1 : 0));
2891 OUT_AS2 (mov
, w
, %D3
);
2892 OUT_AS2 (sub
, w
, %Z1
);
2893 OUT_AS2 (mov
, w
, %C3
);
2894 OUT_AS2 (subc
, w
, %Y1
);
2895 OUT_AS2 (mov
, w
, %B3
);
2896 OUT_AS2 (subc
, w
, %X1
);
2897 OUT_AS2 (mov
, w
, %A3
);
2898 OUT_AS2 (subc
, w
, %W1
);
2899 OUT_AS2 (mov
, w
, %D4
);
2900 OUT_AS2 (subc
, w
, %V1
);
2901 OUT_AS2 (mov
, w
, %C4
);
2902 OUT_AS2 (subc
, w
, %U1
);
2903 OUT_AS2 (mov
, w
, %B4
);
2904 OUT_AS2 (subc
, w
, %T1
);
2905 OUT_AS2 (mov
, w
, %A4
);
2906 OUT_AS2 (subc
, w
, %S1
);
2914 OUT_AS2 (mov
, w
, %Z1
);
2915 OUT_AS2 (sub
, w
, %Z0
);
2916 OUT_AS2 (mov
, w
, %Y1
);
2917 OUT_AS2 (subc
, w
, %Y0
);
2918 OUT_AS2 (mov
, w
, %X1
);
2919 OUT_AS2 (subc
, w
, %X0
);
2920 OUT_AS2 (mov
, w
, %W1
);
2921 OUT_AS2 (subc
, w
, %W0
);
2922 OUT_AS2 (mov
, w
, %V1
);
2923 OUT_AS2 (subc
, w
, %V0
);
2924 OUT_AS2 (mov
, w
, %U1
);
2925 OUT_AS2 (subc
, w
, %U0
);
2926 OUT_AS2 (mov
, w
, %T1
);
2927 OUT_AS2 (subc
, w
, %T0
);
2928 OUT_AS2 (mov
, w
, %S1
);
2929 OUT_AS2 (subc
, w
, %S0
);
2939 if (((const_high
& 0xffffffff) == 0xffffffff)
2940 && ((const_low
& 0xffffffff) == 0xffffffff))
2942 /* <= 0xffffffffffffffff always suceeds. */
2948 operands
[3] = GEN_INT (const_low
+ 1);
2949 operands
[4] = GEN_INT (const_high
2950 + (INTVAL (operands
[3]) ? 0 : 1));
2951 OUT_AS2 (mov
, w
, %D3
);
2952 OUT_AS2 (sub
, w
, %Z0
);
2953 OUT_AS2 (mov
, w
, %C3
);
2954 OUT_AS2 (subc
, w
, %Y0
);
2955 OUT_AS2 (mov
, w
, %B3
);
2956 OUT_AS2 (subc
, w
, %X0
);
2957 OUT_AS2 (mov
, w
, %A3
);
2958 OUT_AS2 (subc
, w
, %W0
);
2959 OUT_AS2 (mov
, w
, %D4
);
2960 OUT_AS2 (subc
, w
, %V0
);
2961 OUT_AS2 (mov
, w
, %C4
);
2962 OUT_AS2 (subc
, w
, %U0
);
2963 OUT_AS2 (mov
, w
, %B4
);
2964 OUT_AS2 (subc
, w
, %T0
);
2965 OUT_AS2 (mov
, w
, %A4
);
2966 OUT_AS2 (subc
, w
, %S0
);
2974 OUT_AS2 (mov
, w
, %Z0
);
2975 OUT_AS2 (sub
, w
, %Z1
);
2976 OUT_AS2 (mov
, w
, %Y0
);
2977 OUT_AS2 (subc
, w
, %Y1
);
2978 OUT_AS2 (mov
, w
, %X0
);
2979 OUT_AS2 (subc
, w
, %X1
);
2980 OUT_AS2 (mov
, w
, %W0
);
2981 OUT_AS2 (subc
, w
, %W1
);
2982 OUT_AS2 (mov
, w
, %V0
);
2983 OUT_AS2 (subc
, w
, %V1
);
2984 OUT_AS2 (mov
, w
, %U0
);
2985 OUT_AS2 (subc
, w
, %U1
);
2986 OUT_AS2 (mov
, w
, %T0
);
2987 OUT_AS2 (subc
, w
, %T1
);
2988 OUT_AS2 (mov
, w
, %S0
);
2989 OUT_AS2 (subc
, w
, %S1
);
3008 /* Output rtx VALUE as .byte to file FILE. */
3011 asm_output_char (FILE *file
, rtx value
)
3013 fprintf (file
, "\t.byte ");
3014 output_addr_const (file
, value
);
3015 fprintf (file
, "\n");
3019 /* Output VALUE as .byte to file FILE. */
3022 asm_output_byte (FILE *file
, int value
)
3024 fprintf (file
, "\t.byte 0x%x\n",value
& 0xff);
3028 /* Output rtx VALUE as .word to file FILE. */
3031 asm_output_short (FILE *file
, rtx value
)
3033 fprintf (file
, "\t.word ");
3034 output_addr_const (file
, (value
));
3035 fprintf (file
, "\n");
3039 /* Output real N to file FILE. */
3042 asm_output_float (FILE *file
, REAL_VALUE_TYPE n
)
3047 REAL_VALUE_TO_TARGET_SINGLE (n
, val
);
3048 real_to_decimal (dstr
, &n
, sizeof (dstr
), 0, 1);
3050 fprintf (file
, "\t.long 0x%08lx\t/* %s */\n", val
, dstr
);
3053 /* Sets section name for declaration DECL. */
3056 unique_section (tree decl
, int reloc ATTRIBUTE_UNUSED
)
3062 name
= IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
));
3063 /* Strip off any encoding in name. */
3064 name
= (* targetm
.strip_name_encoding
) (name
);
3066 if (TREE_CODE (decl
) == FUNCTION_DECL
)
3068 if (flag_function_sections
)
3076 if (flag_function_sections
)
3078 len
= strlen (name
) + strlen (prefix
);
3079 string
= alloca (len
+ 1);
3080 sprintf (string
, "%s%s", prefix
, name
);
3081 DECL_SECTION_NAME (decl
) = build_string (len
, string
);
3085 /* Return value is nonzero if pseudos that have been
3086 assigned to registers of class CLASS would likely be spilled
3087 because registers of CLASS are needed for spill registers. */
3090 class_likely_spilled_p (int c
)
3092 return (c
== IP_REGS
3103 /* Valid attributes:
3104 progmem - put data to program memory;
3105 naked - don't generate function prologue/epilogue and `ret' command.
3107 Only `progmem' attribute valid for type. */
3109 const struct attribute_spec ip2k_attribute_table
[] =
3111 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
3112 { "progmem", 0, 0, false, false, false, ip2k_handle_progmem_attribute
},
3113 { "naked", 0, 0, true, false, false, ip2k_handle_fndecl_attribute
},
3114 { NULL
, 0, 0, false, false, false, NULL
}
3117 /* Handle a "progmem" attribute; arguments as in
3118 struct attribute_spec.handler. */
3120 ip2k_handle_progmem_attribute (tree
*node
, tree name
,
3121 tree args ATTRIBUTE_UNUSED
,
3122 int flags ATTRIBUTE_UNUSED
,
3127 if (TREE_CODE (*node
) == TYPE_DECL
)
3129 /* This is really a decl attribute, not a type attribute,
3130 but try to handle it for GCC 3.0 backwards compatibility. */
3132 tree type
= TREE_TYPE (*node
);
3133 tree attr
= tree_cons (name
, args
, TYPE_ATTRIBUTES (type
));
3134 tree newtype
= build_type_attribute_variant (type
, attr
);
3136 TYPE_MAIN_VARIANT (newtype
) = TYPE_MAIN_VARIANT (type
);
3137 TREE_TYPE (*node
) = newtype
;
3138 *no_add_attrs
= true;
3140 else if (TREE_STATIC (*node
) || DECL_EXTERNAL (*node
))
3142 if (DECL_INITIAL (*node
) == NULL_TREE
&& !DECL_EXTERNAL (*node
))
3144 warning ("only initialized variables can be placed into "
3145 "program memory area");
3146 *no_add_attrs
= true;
3151 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name
));
3152 *no_add_attrs
= true;
3159 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
3160 struct attribute_spec.handler. */
3162 ip2k_handle_fndecl_attribute (tree
*node
, tree name
,
3163 tree args ATTRIBUTE_UNUSED
,
3164 int flags ATTRIBUTE_UNUSED
,
3167 if (TREE_CODE (*node
) != FUNCTION_DECL
)
3169 warning ("`%s' attribute only applies to functions",
3170 IDENTIFIER_POINTER (name
));
3171 *no_add_attrs
= true;
3177 /* Cost functions. */
3179 /* Compute a (partial) cost for rtx X. Return true if the complete
3180 cost has been computed, and false if subexpressions should be
3181 scanned. In either case, *TOTAL contains the cost result. */
3184 ip2k_rtx_costs (rtx x
, int code
, int outer_code
, int *total
)
3186 enum machine_mode mode
= GET_MODE (x
);
3202 *total
= ip2k_address_cost (XEXP (x
, 0));
3210 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
3212 int val
= INTVAL (XEXP (x
, 1));
3215 /* Shift by const instructions are proportional to
3216 the shift count modulus 8. Note that we increase the mode
3217 size multiplier by 1 to account for clearing the carry flag. */
3218 cost
= COSTS_N_INSNS (abs (val
) % 8);
3219 cost
+= rtx_cost (XEXP (x
, 0), code
);
3220 cost
*= (GET_MODE_SIZE (mode
) + 1);
3222 /* Sign-preserving shifts require 2 extra instructions. */
3224 cost
+= COSTS_N_INSNS (2);
3229 *total
= rtx_cost (XEXP (x
, 0), code
);
3230 *total
+= COSTS_N_INSNS (GET_MODE_SIZE (mode
) * 8);
3238 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
) * 3);
3244 *total
= COSTS_N_INSNS (20);
3245 else if (mode
== HImode
)
3246 *total
= COSTS_N_INSNS (60);
3247 else if (mode
== SImode
)
3248 *total
= COSTS_N_INSNS (180);
3250 *total
= COSTS_N_INSNS (540);
3254 /* These costs are OK, but should really handle subtle cases
3255 where we're using sign or zero extended args as these are
3256 *much* cheaper than those given below! */
3258 *total
= COSTS_N_INSNS (4);
3259 else if (mode
== HImode
)
3260 *total
= COSTS_N_INSNS (12);
3261 else if (mode
== SImode
)
3262 *total
= COSTS_N_INSNS (36);
3264 *total
= COSTS_N_INSNS (108);
3269 extra_cost
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
3275 *total
= extra_cost
+ COSTS_N_INSNS (GET_MODE_SIZE (mode
) * 2);
3280 if (outer_code
== SET
)
3282 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
) * 3 / 2);
3287 *total
= -(COSTS_N_INSNS (GET_MODE_SIZE (mode
)) / 2);
3292 *total
= rtx_cost (XEXP (x
, 0), code
) + COSTS_N_INSNS (2);
3309 *total
= COSTS_N_INSNS (4);
3314 /* Calculate the cost of a memory address. */
3317 ip2k_address_cost (rtx x
)
3319 switch (legitimate_address_p (VOIDmode
, x
, 0))
3321 case 'S': /* Very low cost - (IP), (SP+N) or (DP+N) */
3324 case 'R': /* Indirected through IP. */
3327 case 'L': /* Label references. */
3330 case 'C': /* Constants and symbol references. */
3334 return 1000; /* Must reload. */
3338 /* As part of the machine-dependent reorg we look for opcode sequences where
3339 we do some operation and then move the results back to one of the original
3340 source operands. With working on the source operand directly is probably
3341 much cheaper and the move from this to the original source operand will be
3342 no more expensive than the original move. */
3344 #ifdef IP2K_MD_REORG_PASS
3346 mdr_resequence_xy_yx (first_insn
)
3351 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
3355 if (GET_CODE (insn
) != INSN
)
3358 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
3359 if (set
== NULL_RTX
)
3362 /* Look for operations that tend to be very cheap to run when the source
3363 * and dest args are the same because the IP2022 has opcodes that can
3364 operate on the source directly. If we have to spill through the W
3365 register then we've possibly not got a good case for doing this. */
3366 if ((GET_CODE (XEXP (set
, 0)) == REG
3367 || GET_CODE (XEXP (set
, 0)) == MEM
)
3368 && (GET_CODE (XEXP (set
, 1)) == ASHIFT
3369 || GET_CODE (XEXP (set
, 1)) == ASHIFTRT
3370 || GET_CODE (XEXP (set
, 1)) == LSHIFTRT
3371 || GET_CODE (XEXP (set
, 1)) == XOR
3372 || GET_CODE (XEXP (set
, 1)) == IOR
3373 || GET_CODE (XEXP (set
, 1)) == AND
3374 || GET_CODE (XEXP (set
, 1)) == PLUS
3375 || GET_CODE (XEXP (set
, 1)) == MINUS
3376 || GET_CODE (XEXP (set
, 1)) == MULT
))
3381 next_insn
= next_nonnote_insn (insn
);
3385 if (GET_CODE (next_insn
) != INSN
)
3388 set2
= ((GET_CODE (PATTERN (next_insn
)) == SET
)
3389 ? PATTERN (next_insn
) : NULL_RTX
);
3390 if (set2
== NULL_RTX
)
3393 if ((GET_CODE (XEXP (XEXP (set
, 1), 0)) == REG
3394 || GET_CODE (XEXP (XEXP (set
, 1), 0)) == MEM
)
3395 && rtx_equal_p (XEXP (set2
, 0), XEXP (XEXP (set
, 1), 0))
3396 && rtx_equal_p (XEXP (set2
, 1), XEXP (set
, 0)))
3401 b_insn
= gen_rtx_SET (VOIDmode
,
3402 XEXP (XEXP (set
, 1), 0),
3403 gen_rtx_fmt_ee (GET_CODE (XEXP (set
, 1)),
3404 GET_MODE (XEXP (set
, 0)),
3405 XEXP (XEXP (set
, 1), 0),
3406 XEXP (XEXP (set
, 1), 1)));
3408 emit_insn_before (b_insn
, insn
);
3409 b_insn
= gen_rtx_SET (GET_MODE (XEXP (set
, 0)), XEXP (set
, 0),
3410 XEXP (XEXP (set
, 1), 0));
3411 next2_insn
= emit_insn_before (b_insn
, insn
);
3413 delete_insn (next_insn
);
3418 /* Having tried with one operand of the expression, now, if
3419 appropriate, try to do the same thing with the second operand.
3420 Of course there are fewer operations that can match here
3421 because they must be commutative. */
3422 if (GET_RTX_CLASS (GET_CODE (XEXP (set
, 1))) == 'c'
3423 && (GET_CODE (XEXP (XEXP (set
, 1), 1)) == REG
3424 || GET_CODE (XEXP (XEXP (set
, 1), 1)) == MEM
)
3425 && rtx_equal_p (XEXP (set2
, 0), XEXP (XEXP (set
, 1), 1))
3426 && rtx_equal_p (XEXP (set2
, 1), XEXP (set
, 0)))
3432 /* Try to ensure that we put things in a canonical form. */
3433 swap_args
= (GET_CODE (XEXP (XEXP (set
, 1), 0)) == REG
3434 || GET_CODE (XEXP (XEXP (set
, 1), 0)) == MEM
);
3435 rtx_ee
= gen_rtx_fmt_ee (GET_CODE (XEXP (set
, 1)),
3436 GET_MODE (XEXP (set
, 0)),
3437 XEXP (XEXP (set
, 1), swap_args
? 1 : 0),
3438 XEXP (XEXP (set
, 1),
3439 swap_args
? 0 : 1));
3441 emit_insn_before (gen_rtx_SET (VOIDmode
,
3442 XEXP (XEXP (set
, 1), 1),
3445 next2_insn
= emit_insn_before (gen_rtx_SET
3446 (GET_MODE (XEXP (set
, 0)),
3448 XEXP (XEXP (set
, 1), 1)),
3451 delete_insn (next_insn
);
3458 /* Replace and recurse until we've tried QImode pieces! */
3461 mdr_pres_replace_and_recurse (orig
, with
, insn
)
3466 enum machine_mode new_mode
;
3468 validate_replace_rtx (orig
, with
, insn
);
3470 switch (GET_MODE (orig
))
3490 mdr_pres_replace_and_recurse (ip2k_get_low_half (orig
, new_mode
),
3491 ip2k_get_low_half (with
, new_mode
),
3493 mdr_pres_replace_and_recurse (ip2k_get_high_half (orig
, new_mode
),
3494 ip2k_get_high_half (with
, new_mode
),
3498 /* Assist the following function, mdr_propagate_reg_equivs(). */
3501 mdr_propagate_reg_equivs_sequence (first_insn
, orig
, equiv
)
3507 rtx try_equiv
= equiv
;
3509 /* First scan the RTL looking for anything else that might clobber what
3510 we're doing. If we find anything then we can't do the replacement. */
3511 for (try_insn
= next_nonnote_insn (first_insn
);
3512 try_insn
; try_insn
= next_nonnote_insn (try_insn
))
3516 if (GET_CODE (try_insn
) != JUMP_INSN
&& GET_CODE (try_insn
) != INSN
)
3519 pattern
= PATTERN (try_insn
);
3520 if (GET_CODE (pattern
) == PARALLEL
)
3524 for (j
= 0; j
< XVECLEN (pattern
, 0); j
++)
3526 rtx px
= XVECEXP (pattern
, 0, j
);
3528 if (GET_CODE (px
) == SET
)
3529 if (! ip2k_composite_xexp_not_uses_reg_p (XEXP (px
, 0),
3531 GET_MODE_SIZE (GET_MODE (orig
))))
3535 else if (GET_CODE (pattern
) == SET
)
3537 if (! ip2k_composite_xexp_not_uses_reg_p (XEXP (pattern
, 0),
3539 GET_MODE_SIZE (GET_MODE (orig
))))
3544 /* Once we've decided that we're safe to do the replacement then make the
3546 for (try_insn
= next_nonnote_insn (first_insn
); try_insn
;
3547 try_insn
= next_nonnote_insn (try_insn
))
3550 rtx new_equiv
= NULL_RTX
;
3552 if (GET_CODE (try_insn
) != JUMP_INSN
&& GET_CODE (try_insn
) != INSN
)
3558 set
= ((GET_CODE (PATTERN (try_insn
)) == SET
)
3559 ? PATTERN (try_insn
) : NULL_RTX
);
3560 if (set
== NULL_RTX
)
3563 /* We look for a special case of "push" operations screwing our
3564 register equivalence when it's based on a stack slot. We can
3565 track this one and replace the old equivalence expression with
3567 if (GET_CODE (XEXP (set
, 0)) == MEM
3568 && GET_CODE (XEXP (XEXP (set
, 0), 0)) == POST_DEC
3569 && REG_P (XEXP (XEXP (XEXP (set
, 0), 0), 0))
3570 && REGNO (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG_SP
)
3572 /* XXX - need to ensure that we can track this without going
3574 HOST_WIDE_INT disp
= (INTVAL (XEXP (XEXP (try_equiv
, 0), 1))
3575 + GET_MODE_SIZE (GET_MODE (XEXP (set
, 0))));
3576 new_equiv
= gen_rtx_MEM (GET_MODE (try_equiv
),
3577 gen_rtx_PLUS (Pmode
,
3578 gen_rtx_REG (HImode
, REG_SP
),
3582 /* The replacement process is somewhat complicated by the fact that we
3583 might be dealing with what were originally subregs and thus we have
3584 to replace parts of our original expression! */
3585 mdr_pres_replace_and_recurse (orig
, try_equiv
, try_insn
);
3587 if (new_equiv
!= NULL_RTX
)
3588 try_equiv
= new_equiv
;
3592 /* Try propagating register equivalences forwards. It may be that we can
3593 replace a register use with an equivalent expression that already
3594 holds the same value and thus allow one or more register loads to
3598 mdr_propagate_reg_equivs (first_insn
)
3604 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
3606 if (GET_CODE (insn
) != INSN
)
3609 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
3610 if (set
== NULL_RTX
)
3613 /* Have we found a stack slot equivalence for a register? */
3614 if (REG_P (XEXP (set
, 0))
3615 && REGNO (XEXP (set
, 0)) >= 0x88
3616 && GET_CODE (XEXP (set
, 1)) == MEM
3617 && GET_CODE (XEXP (XEXP (set
, 1), 0)) == PLUS
3618 && REG_P (XEXP (XEXP (XEXP (set
, 1), 0), 0))
3619 && REGNO (XEXP (XEXP (XEXP (set
, 1), 0), 0)) == REG_SP
3620 && find_reg_note (insn
, REG_EQUIV
, NULL_RTX
))
3622 mdr_propagate_reg_equivs_sequence (insn
, XEXP (set
, 0),
3628 /* Structure used to track jump targets. */
3630 struct dpre_jump_targets
3632 int target
; /* Is this a jump target? */
3633 int reach_count
; /* Number of ways we can reach this insn. */
3634 int touch_count
; /* Number of times we've touched this
3635 insns during scanning. */
3636 rtx dp_equiv
; /* DP-equivalence at this point. */
3639 struct dpre_jump_targets
*ip2k_dpre_jump_targets
;
3641 /* DP equivalence tracking used within DP reload elimination. */
3644 track_dp_reload (insn
, dp_current
, dp_current_ok
, modifying
)
3652 if (GET_CODE (insn
) != INSN
)
3654 *dp_current
= NULL_RTX
;
3658 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
3659 if (set
== NULL_RTX
)
3661 *dp_current
= NULL_RTX
;
3665 /* If we're pushing a PLUS or MINUS then it's a win if we can replace
3666 an expression for which DP is equivalent with DP. This happens
3667 surprisingly often when we pass a pointer to a structure embedded
3668 within another structure. */
3669 if (*dp_current
!= NULL_RTX
3670 && GET_CODE (XEXP (set
, 0)) == MEM
3671 && GET_CODE (XEXP (XEXP (set
, 0), 0)) == POST_DEC
3672 && GET_CODE (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG
3673 && REGNO (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG_SP
3674 && (GET_CODE (XEXP (set
, 1)) == PLUS
3675 || GET_CODE (XEXP (set
, 1)) == MINUS
)
3676 && GET_CODE (*dp_current
) != SYMBOL_REF
3677 && GET_CODE (*dp_current
) != LABEL_REF
3678 && GET_CODE (*dp_current
) != CONST
)
3681 validate_replace_rtx (*dp_current
, gen_rtx_REG (HImode
, REG_DP
), insn
);
3684 /* Look for DP being modified. If it is, see if it's being changed
3685 to what it already is! */
3686 if (GET_CODE (XEXP (set
, 0)) == REG
3687 && REGNO (XEXP (set
, 0)) == REG_DP
3688 && GET_MODE (XEXP (set
, 0)) == HImode
)
3690 /* If this is an equivalence we can delete the new set operation. */
3691 if (*dp_current
!= NULL_RTX
3692 && rtx_equal_p (XEXP (set
, 1), *dp_current
))
3699 /* If we've not found an equivalence we can look for a special
3700 case where an operand of the expression that sets DP is
3701 already equivalent to DP and in that circumstance we simplify
3702 by replacing that expression with DP. */
3703 if (*dp_current
!= NULL_RTX
3704 && GET_CODE (*dp_current
) != SYMBOL_REF
3705 && GET_CODE (*dp_current
) != LABEL_REF
3706 && GET_CODE (*dp_current
) != CONST
3708 validate_replace_rtx (*dp_current
, XEXP (set
, 0), insn
);
3710 /* Assuming that we're not loading DP from something that uses DP
3711 itself then we mark the new equivalence for DP. If we did match
3712 DP then we can't re-use this one. */
3713 if (ip2k_xexp_not_uses_reg_p (XEXP (set
, 1), REG_DP
, 2))
3715 *dp_current
= XEXP (set
, 1);
3720 *dp_current
= NULL_RTX
;
3725 else if (GET_CODE (XEXP (set
, 0)) == REG
3726 && (REGNO (XEXP (set
, 0)) == REG_DPL
3727 || REGNO (XEXP (set
, 0)) == REG_DPH
))
3729 /* If we clobber part of DP then we've clobbered any equivalences! */
3730 *dp_current
= NULL_RTX
;
3733 else if (! ip2k_xexp_not_uses_reg_p (XEXP (set
, 0), REG_SP
, 2)
3734 && *dp_current
!= NULL_RTX
3735 && !ip2k_xexp_not_uses_reg_p (*dp_current
, REG_SP
, 2))
3737 /* We look for a special case of "push" operations screwing up the
3738 setting of DP when it's based on the stack. We can track this one
3739 and replace the old expression for DP with a new one. */
3740 if (GET_CODE (XEXP (set
, 0)) == MEM
3741 && GET_CODE (XEXP (XEXP (set
, 0), 0)) == POST_DEC
3742 && GET_CODE (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG
3743 && REGNO (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG_SP
3744 && GET_CODE (*dp_current
) == MEM
3745 && GET_CODE (XEXP (*dp_current
, 0)) == PLUS
)
3747 /* XXX - need to ensure that we can track this without going
3749 HOST_WIDE_INT disp
= (INTVAL (XEXP (XEXP (*dp_current
, 0), 1))
3750 + GET_MODE_SIZE (GET_MODE (XEXP (set
, 0))));
3751 *dp_current
= gen_rtx_MEM (HImode
,
3752 gen_rtx_PLUS (Pmode
,
3753 gen_rtx_REG(HImode
, REG_SP
),
3758 /* Now we look for writes to the stack. We can determine if these will
3759 affect the equivalence we're tracking for DP and if not then we can
3760 keep tracking it. */
3761 if (GET_CODE (XEXP (set
, 0)) == MEM
3762 && GET_CODE (*dp_current
) == MEM
)
3764 /* Look at the SP offsets and look for any overlaps. */
3765 int dp_cur_sp_offs
= INTVAL (XEXP (XEXP (*dp_current
, 0), 1));
3766 int set_sp_offs
= INTVAL (XEXP (XEXP (XEXP (set
, 0), 0), 1));
3768 if (abs (dp_cur_sp_offs
- set_sp_offs
) < 2)
3770 *dp_current
= NULL_RTX
;
3775 else if (GET_CODE (XEXP (set
, 0)) == REG
3776 && *dp_current
!= NULL_RTX
3777 && !ip2k_xexp_not_uses_reg_p (*dp_current
, REGNO (XEXP (set
, 0)),
3778 GET_MODE_SIZE (GET_MODE (XEXP (set
,
3781 /* If we've just clobbered all or part of a register reference that we
3782 were sharing for DP then we can't share it any more! */
3783 *dp_current
= NULL_RTX
;
3786 return dp_current_ok
;
3789 /* As part of the machine-dependent reorg we scan loads and reloads of
3790 DP to see where any are redundant. This does happens because we
3791 are able to subsequently transform things in interesting ways. Sometimes
3792 gcc also does unnecessary reloads too so we try to eliminate these too. */
3795 mdr_try_dp_reload_elim (first_insn
)
3799 struct dpre_jump_targets
*djt
;
3801 int incomplete_scan
;
3802 int last_incomplete_scan
;
3804 ip2k_dpre_jump_targets
3805 = (struct dpre_jump_targets
*) xcalloc (get_max_uid (),
3806 sizeof (struct dpre_jump_targets
));
3808 /* First we scan to build up a list of all CODE_LABEL insns and we work out
3809 how many different ways we can reach them. */
3810 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
3812 if (GET_CODE (insn
) == CODE_LABEL
)
3814 djt
= &ip2k_dpre_jump_targets
[INSN_UID (insn
)];
3816 djt
->reach_count
= LABEL_NUSES (insn
);
3817 djt
->touch_count
= 0;
3818 djt
->dp_equiv
= NULL_RTX
;
3819 if (! prev_nonnote_insn (insn
)
3820 || (prev_nonnote_insn (insn
)
3821 && GET_CODE (prev_nonnote_insn (insn
)) != BARRIER
))
3826 /* Next we scan all of the ways of reaching the code labels to see
3827 what the DP register is equivalent to as we reach them. If we find
3828 that they're the same then we keep noting the matched value. We
3829 iterate around this until we reach a convergence on DP equivalences
3830 at all code labels - we have to be very careful not to be too
3832 incomplete_scan
= -1;
3835 int dp_current_ok
= 0;
3836 last_incomplete_scan
= incomplete_scan
;
3837 dp_current
= NULL_RTX
;
3839 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
3841 /* If we have a code label then we need to see if we already know
3842 what the equivalence is at this point. If we do then we use it
3843 immediately, but if we don't then we have a special case to track
3844 when we hit a fallthrough-edge (label with no barrier preceding
3845 it). Any other accesses to the label must be from jump insns
3846 and so they're handled elsewhere. */
3847 if (GET_CODE (insn
) == CODE_LABEL
)
3849 djt
= &ip2k_dpre_jump_targets
[INSN_UID (insn
)];
3851 /* If we're fully characterized the use the equivalence. */
3852 if (djt
->touch_count
== djt
->reach_count
)
3854 dp_current
= djt
->dp_equiv
;
3859 /* If we have a known equivalence for DP as we reach the
3860 fallthrough-edge then track this into the code label. */
3862 && (! prev_nonnote_insn (insn
)
3863 || (prev_nonnote_insn (insn
)
3864 && GET_CODE (prev_nonnote_insn (insn
)) != BARRIER
)))
3866 if (djt
->touch_count
== 0)
3867 djt
->dp_equiv
= dp_current
;
3869 if (djt
->touch_count
< djt
->reach_count
)
3872 if (! rtx_equal_p (djt
->dp_equiv
, dp_current
))
3874 /* When we definitely know that we can't form an
3875 equivalence for DP here we must clobber anything
3876 that we'd started to track too. */
3877 djt
->dp_equiv
= NULL_RTX
;
3878 dp_current
= NULL_RTX
;
3884 /* If we've not completely characterized this code label then
3885 be cautious and assume that we don't know what DP is
3887 if (djt
->touch_count
< djt
->reach_count
)
3889 dp_current
= NULL_RTX
;
3896 /* If we've hit a jump insn then we look for either an address
3897 vector (jump table) or for jump label references. */
3898 if (GET_CODE (insn
) == JUMP_INSN
)
3900 /* Don't attempt to track here if we don't have a known
3901 equivalence for DP at this point. */
3904 rtx pat
= PATTERN (insn
);
3905 if (GET_CODE (pat
) == ADDR_VEC
)
3908 int len
= XVECLEN (pat
, 0);
3910 for (i
= 0; i
< len
; i
++)
3912 rtx vec_insn
= XEXP (XVECEXP (pat
, 0, i
), 0);
3913 djt
= &ip2k_dpre_jump_targets
[INSN_UID (vec_insn
)];
3915 if (djt
->touch_count
== 0)
3916 djt
->dp_equiv
= dp_current
;
3918 if (djt
->touch_count
< djt
->reach_count
)
3921 if (! rtx_equal_p (djt
->dp_equiv
, dp_current
))
3922 djt
->dp_equiv
= NULL_RTX
;
3926 else if (JUMP_LABEL (insn
))
3928 rtx j_insn
= JUMP_LABEL (insn
);
3929 djt
= &ip2k_dpre_jump_targets
[INSN_UID (j_insn
)];
3931 if (djt
->touch_count
== 0)
3932 djt
->dp_equiv
= dp_current
;
3934 if (djt
->touch_count
< djt
->reach_count
)
3937 if (! rtx_equal_p (djt
->dp_equiv
, dp_current
))
3938 djt
->dp_equiv
= NULL_RTX
;
3946 /* Anything other than a code labal or jump arrives here.
3947 We try and track DP, but sometimes we might not be able to. */
3948 dp_current_ok
= track_dp_reload (insn
, &dp_current
,
3952 /* When we're looking to see if we've finished we count the number of
3953 paths through the code labels where we weren't able to definitively
3955 This number is used to see if we're converging on a solution.
3956 If this hits zero then we've fully converged, but if this stays the
3957 same as last time then we probably can't make any further
3959 incomplete_scan
= 0;
3960 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
3962 if (GET_CODE (insn
) == CODE_LABEL
)
3964 djt
= &ip2k_dpre_jump_targets
[INSN_UID (insn
)];
3965 if (djt
->touch_count
!= djt
->reach_count
)
3967 incomplete_scan
+= (djt
->reach_count
- djt
->touch_count
);
3968 djt
->dp_equiv
= NULL_RTX
;
3969 djt
->touch_count
= 0;
3974 while (incomplete_scan
&& incomplete_scan
!= last_incomplete_scan
);
3976 /* Finally we scan the whole function and run DP elimination. When we hit
3977 a CODE_LABEL we pick up any stored equivalence since we now know that
3978 every path to this point entered with DP holding the same thing! If
3979 we subsequently have a reload that matches then we can eliminate it. */
3980 dp_current
= NULL_RTX
;
3981 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
3983 if (GET_CODE (insn
) == JUMP_INSN
)
3986 if (GET_CODE (insn
) == CODE_LABEL
)
3988 djt
= &ip2k_dpre_jump_targets
[INSN_UID (insn
)];
3989 dp_current
= djt
->dp_equiv
;
3993 track_dp_reload (insn
, &dp_current
, 1, 1);
3996 free (ip2k_dpre_jump_targets
);
3999 /* As part of the machine-dependent reorg we look for reloads of DP
4000 that we can move to earlier points within the file.
4001 Moving these out of the way allows more peepholes to match. */
4004 mdr_try_move_dp_reload (first_insn
)
4011 /* Don't try to match the first instruction because we can't move it
4013 orig_first
= first_insn
;
4014 first_insn
= next_nonnote_insn (first_insn
);
4016 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
4018 if (GET_CODE (insn
) != INSN
)
4021 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
4022 if (set
== NULL_RTX
)
4025 /* Look for DP being loaded. When we find this we start a rewind
4026 scan looking for possible positions to move this to. */
4027 if (GET_CODE (XEXP (set
, 0)) == REG
4028 && REGNO (XEXP (set
, 0)) == REG_DP
4029 && GET_MODE (XEXP (set
, 0)) == HImode
)
4032 rtx try_insn
= insn
;
4041 /* For now we do the *really* simple version of things and only
4042 attempt to move the load of DP if it's very safe to do so. */
4043 rewind
= prev_nonnote_insn (try_insn
);
4044 if (rewind
!= orig_first
&& rewind
!= NULL_RTX
4045 && GET_CODE (rewind
) == INSN
)
4047 check
= ((GET_CODE (PATTERN (rewind
)) == SET
)
4048 ? PATTERN (rewind
) : NULL_RTX
);
4049 if (check
!= NULL_RTX
4050 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (check
, 0))
4051 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (check
, 1)))
4053 if (GET_CODE (XEXP (check
, 0)) == REG
4054 && REGNO (XEXP (check
, 0)) != REG_DPH
4055 && REGNO (XEXP (check
, 0)) != REG_DPL
4056 && (ip2k_composite_xexp_not_uses_reg_p
4057 (XEXP (check
, 1), REG_DP
, 2))
4058 && (ip2k_composite_xexp_not_uses_reg_p
4060 REGNO (XEXP (check
, 0)),
4061 GET_MODE_SIZE (GET_MODE (XEXP (check
, 0))))))
4063 emit_insn_before (set
, rewind
);
4064 if (try_insn
== insn
)
4065 insn
= prev_nonnote_insn (insn
);
4066 delete_insn (try_insn
);
4067 try_insn
= prev_nonnote_insn (rewind
);
4070 else if (GET_CODE (XEXP (set
, 1)) == REG
4071 && ip2k_composite_xexp_not_uses_reg_p (XEXP (check
, 1), REG_DP
, 2)
4072 && ip2k_composite_xexp_not_uses_reg_p (XEXP (check
, 0), REG_DP
, 2)
4073 && ip2k_composite_xexp_not_uses_reg_p (XEXP (check
, 0), REGNO (XEXP (set
, 1)),
4074 GET_MODE_SIZE (GET_MODE (XEXP (set
, 1)))))
4076 emit_insn_before (set
, rewind
);
4077 if (try_insn
== insn
)
4078 insn
= prev_nonnote_insn (insn
);
4079 delete_insn (try_insn
);
4080 try_insn
= prev_nonnote_insn (rewind
);
4086 while (try_again
&& try_insn
);
4090 #endif /* IP2K_MD_REORG_PASS */
4092 /* Look to see if the expression, x, can have any stack references offset by
4093 a fixed constant, offset. If it definitely can then returns nonzero. */
4096 ip2k_check_can_adjust_stack_ref (rtx x
, int offset
)
4098 if (GET_RTX_CLASS (GET_CODE (x
)) == '2'
4099 || GET_RTX_CLASS (GET_CODE (x
)) == 'c')
4100 return (ip2k_check_can_adjust_stack_ref (XEXP (x
, 0), offset
)
4101 && ip2k_check_can_adjust_stack_ref (XEXP (x
, 1), offset
));
4103 if (GET_RTX_CLASS (GET_CODE (x
)) == '1')
4104 return ip2k_check_can_adjust_stack_ref (XEXP (x
, 0), offset
);
4106 switch (GET_CODE (x
))
4109 return (REGNO (x
) != REG_SPH
&& REGNO (x
) != REG_SPL
);
4112 if (GET_CODE (XEXP (x
, 0)) != PLUS
)
4115 if (GET_CODE (XEXP (XEXP (x
, 0), 0)) != REG
)
4118 if (REGNO (XEXP (XEXP (x
, 0), 0)) != REG_SP
)
4121 /* We can't allow this if the adjustment will create an
4123 return (INTVAL (XEXP (XEXP (x
, 0), 1))
4124 + offset
<= (128 - 2 * GET_MODE_SIZE (GET_MODE (x
))));
4138 /* Adjusts all of the stack references in the expression pointed to by x by
4142 ip2k_adjust_stack_ref (rtx
*x
, int offset
)
4144 if (GET_RTX_CLASS (GET_CODE (*x
)) == '2'
4145 || GET_RTX_CLASS (GET_CODE (*x
)) == 'c')
4147 ip2k_adjust_stack_ref (&XEXP (*x
, 0), offset
);
4148 ip2k_adjust_stack_ref (&XEXP (*x
, 1), offset
);
4152 if (GET_RTX_CLASS (GET_CODE (*x
)) == '1')
4154 ip2k_adjust_stack_ref (&XEXP (*x
, 0), offset
);
4158 switch (GET_CODE (*x
))
4161 if (GET_CODE (XEXP (*x
, 0)) != PLUS
)
4164 if (GET_CODE (XEXP (XEXP (*x
, 0), 0)) != REG
)
4167 if (REGNO (XEXP (XEXP (*x
, 0), 0)) != REG_SP
)
4171 XEXP (XEXP (*x
, 0), 1) = GEN_INT (INTVAL (XEXP (XEXP (*x
, 0), 1))
4180 #ifdef IP2K_MD_REORG_PASS
4181 /* As part of the machine-dependent reorg we look to move push instructions
4182 to earlier points within the file. Moving these out of the way allows more
4183 peepholes to match. */
4186 mdr_try_move_pushes (first_insn
)
4193 /* Don't try to match the first instruction because we can't move
4195 orig_first
= first_insn
;
4196 first_insn
= next_nonnote_insn (first_insn
);
4198 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
4200 if (GET_CODE (insn
) != INSN
)
4203 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
4204 if (set
== NULL_RTX
)
4207 /* Have we found a push instruction? */
4208 if (GET_CODE (XEXP (set
, 0)) == MEM
4209 && GET_CODE (XEXP (XEXP (set
, 0), 0)) == POST_DEC
4210 && GET_CODE (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG
4211 && REGNO (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG_SP
4212 && GET_CODE (XEXP (set
, 1)) == REG
)
4214 rtx try_insn
= insn
;
4215 unsigned int regno
= REGNO (XEXP (set
, 1));
4216 int reg_range
= GET_MODE_SIZE (GET_MODE (XEXP (set
, 1)));
4223 rewind
= prev_nonnote_insn (try_insn
);
4224 if (rewind
== orig_first
|| rewind
== NULL_RTX
4225 || GET_CODE (rewind
) != INSN
)
4228 check
= (GET_CODE (PATTERN (rewind
)) == SET
) ? PATTERN (rewind
) : NULL_RTX
;
4229 if (check
== NULL_RTX
)
4232 if (! ip2k_check_can_adjust_stack_ref (XEXP (check
, 0),
4234 || ! ip2k_check_can_adjust_stack_ref (XEXP (check
, 1),
4238 /* If we've hit another push instruction we can't go any
4240 if (GET_CODE (XEXP (check
, 0)) == MEM
4241 && GET_CODE (XEXP (XEXP (check
, 0), 0)) == POST_DEC
4242 && GET_CODE (XEXP (XEXP (XEXP (check
, 0), 0), 0)) == REG
4243 && REGNO (XEXP (XEXP (XEXP (check
, 0), 0), 0)) == REG_SP
)
4246 /* If this is a register move then check that it doesn't clobber
4247 SP or any part of the instruction we're trying to move. */
4248 if (GET_CODE (XEXP (check
, 0)) == REG
)
4250 unsigned int check_reg
= REGNO (XEXP (check
, 0));
4251 int check_reg_range
= GET_MODE_SIZE (GET_MODE (XEXP (check
,
4254 /* If we have a special case where what we want to push is
4255 being loaded by this "clobbering" insn then we can just
4256 push what is being used to load us and then do the load.
4257 This may seem a little odd, but we may subsequently be
4258 able to merge the load with another instruction as it
4259 may only be used once now! Note though that we
4260 specifically don't try this if the expression being
4261 loaded is an HImode MEM using IP. */
4262 if (check_reg
== regno
4263 && check_reg_range
== reg_range
4264 && ((GET_CODE (XEXP (check
, 1)) == REG
4265 || (GET_CODE (XEXP (check
, 1)) == MEM
4266 && (GET_MODE (XEXP (check
, 1)) != HImode
4267 || ip2k_xexp_not_uses_reg_for_mem (XEXP (check
, 1), REG_IP
))))))
4269 switch (check_reg_range
)
4272 emit_insn_before (gen_movqi (XEXP (set
, 0),
4275 delete_insn (try_insn
);
4279 emit_insn_before (gen_movhi (XEXP (set
, 0),
4282 delete_insn (try_insn
);
4286 emit_insn_before (gen_movsi (XEXP (set
, 0),
4289 delete_insn (try_insn
);
4293 emit_insn_before (gen_movdi (XEXP (set
, 0),
4296 delete_insn (try_insn
);
4300 ip2k_adjust_stack_ref (&XEXP (check
, 0), reg_range
);
4301 ip2k_adjust_stack_ref (&XEXP (check
, 1), reg_range
);
4302 try_insn
= prev_nonnote_insn (rewind
);
4303 /* XXX - should be a continue? */
4307 if ((check_reg
== REG_SPL
)
4308 || (check_reg
== REG_SPH
)
4309 || (((regno
<= check_reg
)
4310 && (regno
+ reg_range
- 1) >= check_reg
)
4311 || ((regno
<= (check_reg
+ check_reg_range
- 1))
4312 && ((regno
+ reg_range
- 1)
4313 >= (check_reg
+ check_reg_range
- 1)))))
4317 emit_insn_before (set
, rewind
);
4318 delete_insn (try_insn
);
4319 ip2k_adjust_stack_ref (&XEXP (check
, 0), reg_range
);
4320 ip2k_adjust_stack_ref (&XEXP (check
, 1), reg_range
);
4321 try_insn
= prev_nonnote_insn (rewind
);
4327 /* Assist the following function, mdr_try_propagate_clr(). */
4330 mdr_try_propagate_clr_sequence (first_insn
, regno
)
4336 for (try_insn
= next_nonnote_insn (first_insn
); try_insn
;
4337 try_insn
= next_nonnote_insn (try_insn
))
4339 rtx new_insn
= NULL_RTX
;
4342 if (GET_CODE (try_insn
) == JUMP_INSN
)
4345 if (GET_CODE (try_insn
) != INSN
)
4348 set2
= ((GET_CODE (PATTERN (try_insn
)) == SET
)
4349 ? PATTERN (try_insn
) : NULL_RTX
);
4350 if (set2
== NULL_RTX
)
4353 if (GET_CODE (XEXP (set2
, 1)) == AND
4354 && ((GET_CODE (XEXP (XEXP (set2
, 1), 0)) == REG
4355 && REGNO (XEXP (XEXP (set2
, 1), 0)) == regno
)
4356 || (GET_CODE (XEXP (XEXP (set2
, 1), 1)) == REG
4357 && REGNO (XEXP (XEXP (set2
, 1), 1)) == regno
)))
4359 rtx remove_insn
= try_insn
;
4360 try_insn
= emit_insn_before (gen_rtx_SET (QImode
, XEXP (set2
, 0),
4361 const0_rtx
), try_insn
);
4362 delete_insn (remove_insn
);
4364 else if (GET_CODE (XEXP (set2
, 1)) == IOR
4365 && GET_CODE (XEXP (XEXP (set2
, 1), 0)) == REG
4366 && REGNO (XEXP (XEXP (set2
, 1), 0)) == regno
)
4368 rtx remove_insn
= try_insn
;
4369 try_insn
= emit_insn_before (gen_rtx_SET (QImode
, XEXP (set2
, 0),
4370 XEXP (XEXP (set2
, 1), 1)),
4372 delete_insn (remove_insn
);
4374 else if (GET_CODE (XEXP (set2
, 1)) == IOR
4375 && GET_CODE (XEXP (XEXP (set2
, 1), 1)) == REG
4376 && REGNO (XEXP (XEXP (set2
, 1), 1)) == regno
)
4378 rtx remove_insn
= try_insn
;
4379 try_insn
= emit_insn_before (gen_rtx_SET (QImode
, XEXP (set2
, 0),
4380 XEXP (XEXP (set2
, 1), 0)),
4382 delete_insn (remove_insn
);
4384 else if (GET_CODE (XEXP (set2
, 1)) == XOR
4385 && GET_CODE (XEXP (XEXP (set2
, 1), 0)) == REG
4386 && REGNO (XEXP (XEXP (set2
, 1), 0)) == regno
)
4388 rtx remove_insn
= try_insn
;
4389 try_insn
= emit_insn_before (gen_rtx_SET (QImode
, XEXP (set2
, 0),
4390 XEXP (XEXP (set2
, 1), 1)),
4392 delete_insn (remove_insn
);
4394 else if (GET_CODE (XEXP (set2
, 1)) == XOR
4395 && GET_CODE (XEXP (XEXP (set2
, 1), 1)) == REG
4396 && REGNO (XEXP (XEXP (set2
, 1), 1)) == regno
)
4398 rtx remove_insn
= try_insn
;
4399 try_insn
= emit_insn_before (gen_rtx_SET (QImode
, XEXP (set2
, 0),
4400 XEXP (XEXP (set2
, 1), 0)),
4402 delete_insn (remove_insn
);
4405 if (GET_CODE (XEXP (set2
, 0)) == REG
)
4407 int reg2_range
= GET_MODE_SIZE (GET_MODE (XEXP (set2
, 0)));
4408 unsigned int regno2
= REGNO (XEXP (set2
, 0));
4412 && GET_CODE (XEXP (set2
, 1)) == CONST_INT
)
4414 int iv
= INTVAL (XEXP (set2
, 1));
4417 if (iv
== 1 || iv
== -1)
4419 new_insn
= gen_rtx_SET (QImode
, XEXP (set2
, 0),
4420 gen_rtx_PLUS (QImode
, XEXP (set2
, 0),
4422 new_insn
= emit_insn_before (new_insn
, try_insn
);
4423 delete_insn (try_insn
);
4424 try_insn
= new_insn
;
4429 if ((regno
>= regno2
) && (regno
<= regno2
+ reg2_range
- 1))
4432 if (GET_CODE (XEXP (set2
, 1)) == REG
4433 && REGNO (XEXP (set2
, 1)) == regno
)
4435 new_insn
= emit_insn_before (gen_rtx_SET (QImode
,
4439 delete_insn (try_insn
);
4440 try_insn
= new_insn
;
4444 if (GET_CODE (XEXP (set2
, 0)) == CC0
)
4446 if (GET_CODE (XEXP (set2
, 1)) == REG
4447 && GET_MODE_SIZE (GET_MODE (XEXP (set2
, 1))) == 2
4448 && REGNO (XEXP (set2
, 1)) == regno
)
4450 new_insn
= gen_rtx_SET (VOIDmode
, gen_rtx (CC0
, VOIDmode
),
4451 gen_rtx_REG(QImode
, regno
+ 1));
4452 new_insn
= emit_insn_before (new_insn
, try_insn
);
4454 else if (GET_CODE (XEXP (set2
, 1)) == COMPARE
4455 && GET_CODE (XEXP (XEXP (set2
, 1), 0)) == REG
4456 && GET_MODE_SIZE (GET_MODE (XEXP (XEXP (set2
, 1), 0))) == 2
4457 && REGNO (XEXP (XEXP (set2
, 1), 0)) == regno
4458 && GET_CODE (XEXP (XEXP (set2
, 1), 1)) == CONST_INT
4459 && INTVAL (XEXP (XEXP (set2
, 1), 1)) >= 0
4460 && INTVAL (XEXP (XEXP (set2
, 1), 1)) < 256)
4462 new_insn
= gen_rtx_SET (VOIDmode
, cc0_rtx
,
4463 gen_rtx_COMPARE(QImode
,
4464 gen_rtx_REG (QImode
,
4466 XEXP (XEXP (set2
, 1),
4468 new_insn
= emit_insn_before (new_insn
, try_insn
);
4471 /* If we have inserted a replacement for a CC0 setter operation
4472 then we need to delete the old one. */
4473 if (new_insn
!= NULL_RTX
)
4475 delete_insn (try_insn
);
4476 try_insn
= new_insn
;
4478 /* Now as we know that we have just done an unsigned compare
4479 (remember we were zero-extended by the clr!) we also know
4480 that we don't need a signed jump insn. If we find that
4481 our next isns is a signed jump then make it unsigned! */
4482 if (GET_CODE (next_nonnote_insn (try_insn
)) == JUMP_INSN
)
4486 try_insn
= next_nonnote_insn (try_insn
);
4487 set3
= ((GET_CODE (PATTERN (try_insn
)) == SET
)
4488 ? PATTERN (try_insn
) : NULL_RTX
);
4489 if (set3
== NULL_RTX
)
4492 /* If we discover that our jump target is only accessible
4493 from here then we can continue our "clr" propagation to
4495 if (LABEL_NUSES (JUMP_LABEL (try_insn
)) == 1)
4496 mdr_try_propagate_clr_sequence (JUMP_LABEL (try_insn
),
4499 if (GET_CODE (XEXP (set3
, 0)) == PC
4500 && GET_CODE (XEXP (set3
, 1)) == IF_THEN_ELSE
4501 && (GET_CODE (XEXP (XEXP (set3
, 1), 0)) == GT
4502 || GET_CODE (XEXP (XEXP (set3
, 1), 0)) == GE
4503 || GET_CODE (XEXP (XEXP (set3
, 1), 0)) == LT
4504 || GET_CODE (XEXP (XEXP (set3
, 1), 0)) == LE
)
4505 && GET_CODE (XEXP (XEXP (XEXP (set3
, 1), 0), 0)) == CC0
4506 && (GET_CODE (XEXP (XEXP (XEXP (set3
, 1), 0), 1))
4508 && GET_CODE (XEXP (XEXP (set3
, 1), 1)) == LABEL_REF
4509 && GET_CODE (XEXP (XEXP (set3
, 1), 2)) == PC
)
4515 /* Replace our old conditional jump with a new one that
4516 does the unsigned form of what was previously a
4517 signed comparison. */
4518 code
= GET_CODE (XEXP (XEXP (set3
, 1), 0));
4519 cmp
= gen_rtx_fmt_ee ((code
== GT
4523 : (code
== LT
? LTU
: LEU
))),
4525 XEXP (XEXP (XEXP (set3
, 1), 0), 0),
4526 XEXP (XEXP (XEXP (set3
, 1), 0),
4529 = gen_rtx_SET (GET_MODE (set3
),
4531 gen_rtx_IF_THEN_ELSE
4532 (GET_MODE (XEXP (set3
, 1)), cmp
,
4533 XEXP (XEXP (set3
, 1), 1),
4534 XEXP (XEXP (set3
, 1), 2)));
4535 new_insn
= emit_jump_insn_before (new_if
, try_insn
);
4536 LABEL_NUSES (JUMP_LABEL (try_insn
))++;
4537 delete_insn (try_insn
);
4538 try_insn
= new_insn
;
4543 else if (GET_CODE (XEXP (set2
, 1)) == PLUS
4544 && GET_CODE (XEXP (XEXP (set2
, 1), 0)) == REG
4545 && GET_MODE_SIZE (GET_MODE (XEXP (XEXP (set2
, 1), 0))) == 2
4546 && REGNO (XEXP (XEXP (set2
, 1), 0)) == regno
4547 && (GET_CODE (XEXP (XEXP (set2
, 1), 1)) == REG
4548 || GET_CODE (XEXP (XEXP (set2
, 1), 1)) == MEM
4549 || GET_CODE (XEXP (XEXP (set2
, 1), 1)) == CONST_INT
4550 || GET_CODE (XEXP (XEXP (set2
, 1), 1)) == CONST
4551 || GET_CODE (XEXP (XEXP (set2
, 1), 1)) == SYMBOL_REF
))
4553 rtx extend
= gen_rtx_ZERO_EXTEND (HImode
,
4554 gen_rtx_REG (QImode
, regno
+ 1));
4555 new_insn
= gen_rtx_SET (HImode
, XEXP (set2
, 0),
4556 gen_rtx_PLUS (HImode
, extend
,
4557 XEXP (XEXP (set2
, 1), 1)));
4558 new_insn
= emit_insn_before (new_insn
, try_insn
);
4559 delete_insn (try_insn
);
4560 try_insn
= new_insn
;
4562 else if (GET_CODE (XEXP (set2
, 1)) == PLUS
4563 && GET_CODE (XEXP (XEXP (set2
, 1), 1)) == REG
4564 && GET_MODE_SIZE (GET_MODE (XEXP (XEXP (set2
, 1), 1))) == 2
4565 && REGNO (XEXP (XEXP (set2
, 1), 1)) == regno
4566 && (GET_CODE (XEXP (XEXP (set2
, 1), 0)) == REG
4567 || GET_CODE (XEXP (XEXP (set2
, 1), 0)) == MEM
4568 || GET_CODE (XEXP (XEXP (set2
, 1), 0)) == CONST_INT
4569 || GET_CODE (XEXP (XEXP (set2
, 1), 0)) == CONST
4570 || GET_CODE (XEXP (XEXP (set2
, 1), 0)) == SYMBOL_REF
))
4572 rtx t_src
= gen_rtx_PLUS (HImode
,
4573 gen_rtx_ZERO_EXTEND (HImode
,
4574 gen_rtx_REG (QImode
,
4577 XEXP (XEXP (set2
, 1), 0));
4578 new_insn
= emit_insn_before (gen_rtx_SET (HImode
, XEXP (set2
, 0),
4581 delete_insn (try_insn
);
4582 try_insn
= new_insn
;
4587 /* One of the things that can quite often happen with an 8-bit CPU is that
4588 we end up clearing the MSByte of a 16-bit value. Unfortunately, all too
4589 often gcc doesn't have any way to realize that only half of the value is
4590 useful and ends up doing more work than it should. We scan for such
4591 occurrences here, track them and reduce compare operations to a smaller
4592 size where possible.
4594 Note that this is somewhat different to move propagation as we may
4595 actually change some instruction patterns when we're doing this whereas
4596 move propagation is just about doing a search and replace. */
4599 mdr_try_propagate_clr (first_insn
)
4605 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
4607 if (GET_CODE (insn
) != INSN
)
4610 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
4611 if (set
== NULL_RTX
)
4614 /* Have we found a "clr" instruction? */
4615 if (GET_CODE (XEXP (set
, 0)) == REG
4616 && GET_CODE (XEXP (set
, 1)) == CONST_INT
4617 && GET_MODE_SIZE (GET_MODE (XEXP (set
, 0))) == 1
4618 && INTVAL (XEXP (set
, 1)) == 0)
4620 mdr_try_propagate_clr_sequence (insn
, REGNO (XEXP (set
, 0)));
4624 #endif /* IP2K_MD_REORG_PASS */
4626 /* Look to see if the expression, x, does not make any memory references
4627 via the specified register. This is very conservative and only returns
4628 nonzero if we definitely don't have such a memory ref. */
4631 ip2k_xexp_not_uses_reg_for_mem (rtx x
, unsigned int regno
)
4634 regno
&= 0xfffffffe;
4636 if (GET_RTX_CLASS (GET_CODE (x
)) == 'b')
4637 return (ip2k_xexp_not_uses_reg_for_mem (XEXP (x
, 0), regno
)
4638 && ip2k_xexp_not_uses_reg_for_mem (XEXP (x
, 1), regno
)
4639 && ip2k_xexp_not_uses_reg_for_mem (XEXP (x
, 2), regno
));
4641 if (GET_RTX_CLASS (GET_CODE (x
)) == '2'
4642 || GET_RTX_CLASS (GET_CODE (x
)) == 'c'
4643 || GET_RTX_CLASS (GET_CODE (x
)) == '<')
4644 return (ip2k_xexp_not_uses_reg_for_mem (XEXP (x
, 0), regno
)
4645 && ip2k_xexp_not_uses_reg_for_mem (XEXP (x
, 1), regno
));
4647 if (GET_RTX_CLASS (GET_CODE (x
)) == '1'
4648 || GET_RTX_CLASS (GET_CODE (x
)) == '3')
4649 return ip2k_xexp_not_uses_reg_for_mem (XEXP (x
, 0), regno
);
4651 switch (GET_CODE (x
))
4657 if ((GET_CODE (XEXP (x
, 0)) == PLUS
4658 && GET_CODE (XEXP (XEXP (x
, 0), 0)) == REG
4659 && REGNO (XEXP (XEXP (x
, 0), 0)) == regno
)
4660 || (GET_CODE (XEXP (x
, 0)) == REG
4661 && REGNO (XEXP (x
, 0)) == regno
))
4680 #ifdef IP2K_MD_REORG_PASS
4681 /* Assist the following function, mdr_try_propagate_move(). */
4684 mdr_try_propagate_move_sequence (first_insn
, orig
, equiv
)
4691 for (try_insn
= next_nonnote_insn (first_insn
); try_insn
;
4692 try_insn
= next_nonnote_insn (try_insn
))
4696 rtx new_equiv
= NULL_RTX
;
4698 if (GET_CODE (try_insn
) != JUMP_INSN
&& GET_CODE (try_insn
) != INSN
)
4701 set
= single_set (try_insn
);
4702 if (set
== NULL_RTX
)
4705 range
= MAX (GET_MODE_SIZE (GET_MODE (equiv
)),
4706 GET_MODE_SIZE (GET_MODE (XEXP (set
, 0))));
4708 if (GET_CODE (equiv
) == REG
4709 && REGNO (equiv
) == REG_W
4710 && (recog_memoized (try_insn
) < 0
4711 || get_attr_clobberw (try_insn
) != CLOBBERW_NO
)
4712 && (! (GET_CODE (XEXP (set
, 0)) == REG
4713 && REGNO (XEXP (set
, 0)) == REG_W
4714 && rtx_equal_p (XEXP (set
, 1), orig
))))
4716 else if (GET_CODE (XEXP (set
, 0)) == REG
4717 && (REGNO (XEXP (set
, 0)) == REG_SP
4718 || ! ip2k_xexp_not_uses_reg_p (equiv
, REGNO (XEXP (set
, 0)),
4720 || ! ip2k_xexp_not_uses_reg_p (orig
, REGNO (XEXP (set
, 0)),
4722 && ! rtx_equal_p (equiv
, XEXP (set
, 0))
4723 && ! rtx_equal_p (orig
, XEXP (set
, 0)))
4725 else if (GET_CODE (orig
) == REG
4726 && (REGNO (orig
) == REG_IPL
4727 || REGNO (orig
) == REG_IPH
4728 || REGNO (orig
) == REG_DPL
4729 || REGNO (orig
) == REG_DPH
)
4730 && (! ip2k_xexp_not_uses_reg_for_mem (XEXP (set
, 0),
4732 || ! ip2k_xexp_not_uses_reg_for_mem (XEXP (set
, 1),
4735 else if (GET_CODE (XEXP (set
, 0)) == MEM
4736 && GET_CODE (equiv
) == MEM
)
4738 if (! ip2k_xexp_not_uses_reg_p (equiv
, REG_SP
, 2))
4740 if (! ip2k_xexp_not_uses_reg_p (XEXP (set
, 0), REG_SP
, 2))
4742 /* We look for a special case of "push" operations screwing
4743 our register equivalence when it's based on a stack slot.
4744 We can track this one and replace the old equivalence
4745 expression with a new one. */
4746 if (GET_CODE (XEXP (XEXP (set
, 0), 0)) == POST_DEC
4747 && GET_CODE (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG
4748 && REGNO (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG_SP
4749 && GET_CODE (XEXP (equiv
, 0)) == PLUS
4750 && REGNO (XEXP (XEXP (equiv
, 0), 0)) == REG_SP
)
4752 int md_size
= GET_MODE_SIZE (GET_MODE (XEXP (set
, 0)));
4753 int new_sp_offs
= INTVAL (XEXP (XEXP (equiv
, 0), 1))
4756 /* Don't allow an invalid stack pointer offset to be
4758 if (new_sp_offs
> (128 - 2 * md_size
))
4762 = gen_rtx_MEM (GET_MODE (equiv
),
4763 gen_rtx_PLUS (Pmode
,
4764 gen_rtx_REG (HImode
,
4766 GEN_INT (new_sp_offs
)));
4768 else if (! rtx_equal_p (equiv
, XEXP (set
, 0)))
4770 /* Look at the SP offsets and look for any overlaps. */
4771 int equiv_offs
= GET_CODE (XEXP (equiv
, 0)) == PLUS
4772 ? INTVAL (XEXP (XEXP (equiv
, 0), 1))
4775 = (GET_CODE (XEXP (XEXP (set
, 0), 0)) == PLUS
4776 ? INTVAL (XEXP (XEXP (XEXP (set
, 0), 0), 1))
4779 if (abs (equiv_offs
- set_offs
) < range
)
4785 if (! ip2k_xexp_not_uses_reg_p (equiv
, REG_IP
, 2))
4788 if (! ip2k_xexp_not_uses_reg_p (XEXP (set
, 0), REG_DP
, 2)
4789 && ! ip2k_xexp_not_uses_reg_p (equiv
, REG_DP
, 2)
4790 && ! rtx_equal_p (equiv
, XEXP (set
, 0)))
4792 /* Look at the DP offsets and look for any overlaps. */
4793 int equiv_offs
= GET_CODE (XEXP (equiv
, 0)) == PLUS
4794 ? INTVAL (XEXP (XEXP (equiv
, 0), 1))
4796 int set_offs
= GET_CODE (XEXP (XEXP (set
, 0), 0)) == PLUS
4797 ? INTVAL (XEXP (XEXP (XEXP (set
, 0), 0), 1))
4800 if (abs (equiv_offs
- set_offs
) < range
)
4805 validate_replace_rtx_subexp (orig
, equiv
, try_insn
, &XEXP (set
, 1));
4807 if (rtx_equal_p (equiv
, XEXP (set
, 0))
4808 || rtx_equal_p (orig
, XEXP (set
, 0)))
4811 if (new_equiv
!= NULL_RTX
)
4816 /* Try propagating move instructions forwards. It may be that we can
4817 replace a register use with an equivalent expression that already
4818 holds the same value and thus allow one or more register loads to
4822 mdr_try_propagate_move (first_insn
)
4828 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
4830 if (GET_CODE (insn
) != INSN
)
4833 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
4834 if (set
== NULL_RTX
)
4837 /* Have we found a simple move instruction? */
4838 if (GET_CODE (XEXP (set
, 0)) == REG
4839 && (REGNO (XEXP (set
, 0)) >= 0x80
4840 || REGNO (XEXP (set
, 0)) == REG_DPL
4841 || REGNO (XEXP (set
, 0)) == REG_DPH
4842 || REGNO (XEXP (set
, 0)) == REG_IPL
4843 || REGNO (XEXP (set
, 0)) == REG_IPH
)
4844 && ((GET_CODE (XEXP (set
, 1)) == REG
4845 && REGNO (XEXP (set
, 1)) != REG_SP
4846 && ip2k_xexp_not_uses_reg_p (XEXP (set
, 0),
4847 REGNO (XEXP (set
, 1)),
4848 GET_MODE_SIZE (GET_MODE (XEXP (set
,
4850 || (GET_CODE (XEXP (set
, 1)) == MEM
4851 && (ip2k_xexp_not_uses_reg_p (XEXP (set
, 1), REG_IP
, 2)
4852 || GET_MODE (XEXP (set
, 1)) == QImode
)
4853 && ((REGNO (XEXP (set
, 0)) != REG_DPH
4854 && REGNO (XEXP (set
, 0)) != REG_DPL
)
4855 || ip2k_xexp_not_uses_reg_p (XEXP (set
, 1), REG_DP
, 2)))
4856 || (GET_CODE (XEXP (set
, 1)) == CONST_INT
4857 && (GET_MODE (XEXP (set
, 0)) != QImode
4858 || INTVAL (XEXP (set
, 1)) != 0))
4859 || GET_CODE (XEXP (set
, 1)) == CONST_DOUBLE
4860 || GET_CODE (XEXP (set
, 1)) == CONST
4861 || GET_CODE (XEXP (set
, 1)) == SYMBOL_REF
))
4863 mdr_try_propagate_move_sequence (insn
, XEXP (set
, 0), XEXP (set
, 1));
4868 /* Try to remove redundant instructions. */
4871 mdr_try_remove_redundant_insns (first_insn
)
4876 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
4879 enum machine_mode mode
;
4881 HOST_WIDE_INT pattern
;
4884 if (GET_CODE (insn
) != INSN
)
4887 if (GET_CODE (PATTERN (insn
)) == CONST_INT
)
4889 /* We've found a dummy expression. */
4890 rtx remove_insn
= insn
;
4891 insn
= prev_nonnote_insn (insn
);
4892 delete_insn (remove_insn
);
4896 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
4897 if (set
== NULL_RTX
)
4900 mode
= GET_MODE (XEXP (set
, 0));
4901 md_size
= GET_MODE_SIZE (mode
);
4902 if ((md_size
< 1) || (md_size
> 4))
4906 for (i
= 0; i
< md_size
; i
++)
4912 if ((GET_CODE (XEXP (set
, 1)) == AND
4913 && GET_CODE (XEXP (XEXP (set
, 1), 1)) == CONST_INT
4914 && INTVAL (XEXP (XEXP (set
, 1), 1)) == pattern
)
4915 || ((GET_CODE (XEXP (set
, 1)) == IOR
4916 || GET_CODE (XEXP (set
, 1)) == XOR
)
4917 && GET_CODE (XEXP (XEXP (set
, 1), 1)) == CONST_INT
4918 && INTVAL (XEXP (XEXP (set
, 1), 1)) == 0x00))
4920 /* We've found an AND with all 1's, an XOR with all 0's or an
4922 rtx remove_insn
= insn
;
4924 /* Is it completely redundant or should it become a move insn? */
4925 if (! rtx_equal_p (XEXP (set
, 0), XEXP (XEXP (set
, 1), 0)))
4927 emit_insn_before (gen_rtx_SET (mode
,
4929 XEXP (XEXP (set
, 1), 0)),
4933 insn
= prev_nonnote_insn(insn
);
4934 delete_insn (remove_insn
);
4936 else if (GET_CODE (XEXP (set
, 1)) == AND
4937 && GET_CODE (XEXP (XEXP (set
, 1), 1)) == CONST_INT
4938 && INTVAL (XEXP (XEXP (set
, 1), 1)) == 0)
4940 /* We've found an AND with all 0's. */
4941 rtx remove_insn
= insn
;
4942 insn
= emit_insn_before (gen_rtx_SET (mode
,
4944 XEXP (XEXP (set
, 1), 1)),
4946 delete_insn (remove_insn
);
4951 /* Structure used to track jump targets. */
4953 struct we_jump_targets
4955 int target
; /* Is this a jump target? */
4956 int reach_count
; /* Number of ways we can reach this insn. */
4957 int touch_count
; /* Number of times we've touched this insn
4959 rtx w_equiv
; /* WREG-equivalence at this point. */
4962 struct we_jump_targets
*ip2k_we_jump_targets
;
4964 /* WREG equivalence tracking used within DP reload elimination. */
4967 track_w_reload (insn
, w_current
, w_current_ok
, modifying
)
4975 if (GET_CODE (insn
) != INSN
)
4977 *w_current
= NULL_RTX
;
4981 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
4982 if (set
== NULL_RTX
)
4984 *w_current
= NULL_RTX
;
4988 /* Look for W being modified. If it is, see if it's being changed
4989 to what it already is! */
4990 if (GET_CODE (XEXP (set
, 0)) == REG
4991 && REGNO (XEXP (set
, 0)) == REG_W
4992 && GET_MODE (XEXP (set
, 0)) == QImode
)
4994 /* If this is an equivalence we can delete the new set operation. */
4995 if (*w_current
!= NULL_RTX
4996 && rtx_equal_p (XEXP (set
, 1), *w_current
))
5003 *w_current
= XEXP (set
, 1);
5007 else if (recog_memoized (insn
) < 0
5008 || get_attr_clobberw (insn
) != CLOBBERW_NO
)
5010 /* If we clobber W then we've clobbered any equivalences ! */
5011 *w_current
= NULL_RTX
;
5014 else if (! ip2k_xexp_not_uses_reg_p (XEXP (set
, 0), REG_SP
, 2)
5015 && *w_current
!= NULL_RTX
5016 && !ip2k_xexp_not_uses_reg_p (*w_current
, REG_SP
, 2))
5018 /* We look for a special case of "push" operations screwing up the
5019 setting of DP when it's based on the stack. We can track this one
5020 and replace the old expression for DP with a new one. */
5021 if (GET_CODE (XEXP (set
, 0)) == MEM
5022 && GET_CODE (XEXP (XEXP (set
, 0), 0)) == POST_DEC
5023 && GET_CODE (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG
5024 && REGNO (XEXP (XEXP (XEXP (set
, 0), 0), 0)) == REG_SP
5025 && GET_CODE (*w_current
) == MEM
5026 && GET_CODE (XEXP (*w_current
, 0)) == PLUS
)
5028 /* XXX - need to ensure that we can track this without going
5030 rtx val
= GEN_INT (INTVAL (XEXP (XEXP (*w_current
, 0), 1))
5031 + GET_MODE_SIZE (GET_MODE (XEXP (set
, 0))));
5033 = gen_rtx_MEM (HImode
, gen_rtx_PLUS (Pmode
,
5034 gen_rtx_REG(HImode
, REG_SP
),
5039 else if (GET_CODE (XEXP (set
, 0)) == REG
5040 && *w_current
!= NULL_RTX
5041 && !ip2k_xexp_not_uses_reg_p (*w_current
, REGNO (XEXP (set
, 0)),
5042 GET_MODE_SIZE (GET_MODE (XEXP (set
5045 /* If we've just clobbered all or part of a register reference that we
5046 were sharing for W then we can't share it any more! */
5047 *w_current
= NULL_RTX
;
5050 return w_current_ok
;
5053 /* As part of the machine-dependent reorg we scan moves into w and track them
5054 to see where any are redundant. */
5057 mdr_try_wreg_elim (first_insn
)
5061 struct we_jump_targets
*wjt
;
5063 int incomplete_scan
;
5064 int last_incomplete_scan
;
5066 ip2k_we_jump_targets
5067 = (struct we_jump_targets
*) xcalloc (get_max_uid (),
5068 sizeof (struct we_jump_targets
));
5070 /* First we scan to build up a list of all CODE_LABEL insns and we work out
5071 how many different ways we can reach them. */
5072 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
5074 if (GET_CODE (insn
) == CODE_LABEL
)
5076 wjt
= &ip2k_we_jump_targets
[INSN_UID (insn
)];
5078 wjt
->reach_count
= LABEL_NUSES (insn
);
5079 wjt
->touch_count
= 0;
5080 wjt
->w_equiv
= NULL_RTX
;
5081 if (! prev_nonnote_insn (insn
)
5082 || (prev_nonnote_insn (insn
)
5083 && GET_CODE (prev_nonnote_insn (insn
)) != BARRIER
))
5088 /* Next we scan all of the ways of reaching the code labels to see
5089 what the WREG register is equivalent to as we reach them. If we find
5090 that they're the same then we keep noting the matched value. We
5091 iterate around this until we reach a convergence on WREG equivalences
5092 at all code labels - we have to be very careful not to be too
5094 incomplete_scan
= -1;
5097 int w_current_ok
= 0;
5098 last_incomplete_scan
= incomplete_scan
;
5099 w_current
= NULL_RTX
;
5101 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
5103 /* If we have a code label then we need to see if we already know
5104 what the equivalence is at this point. If we do then we use it
5105 immediately, but if we don't then we have a special case to track
5106 when we hit a fallthrough-edge (label with no barrier preceding
5107 it). Any other accesses to the label must be from jump insns
5108 and so they're handled elsewhere. */
5109 if (GET_CODE (insn
) == CODE_LABEL
)
5111 wjt
= &ip2k_we_jump_targets
[INSN_UID (insn
)];
5113 /* If we're fully characterized the use the equivalence. */
5114 if (wjt
->touch_count
== wjt
->reach_count
)
5116 w_current
= wjt
->w_equiv
;
5121 /* If we have a known equivalence for WREG as we reach the
5122 fallthrough-edge then track this into the code label. */
5124 && (! prev_nonnote_insn (insn
)
5125 || (prev_nonnote_insn (insn
)
5126 && GET_CODE (prev_nonnote_insn (insn
)) != BARRIER
)))
5128 if (wjt
->touch_count
== 0)
5129 wjt
->w_equiv
= w_current
;
5131 if (wjt
->touch_count
< wjt
->reach_count
)
5134 if (! rtx_equal_p (wjt
->w_equiv
, w_current
))
5136 /* When we definitely know that we can't form an
5137 equivalence for WREG here we must clobber anything
5138 that we'd started to track too. */
5139 wjt
->w_equiv
= NULL_RTX
;
5140 w_current
= NULL_RTX
;
5146 /* If we've not completely characterized this code label then
5147 be cautious and assume that we don't know what WREG is
5149 if (wjt
->touch_count
< wjt
->reach_count
)
5151 w_current
= NULL_RTX
;
5158 /* If we've hit a jump insn then we look for either an address
5159 vector (jump table) or for jump label references. */
5160 if (GET_CODE (insn
) == JUMP_INSN
)
5162 /* Don't attempt to track here if we don't have a known
5163 equivalence for WREG at this point. */
5166 if (JUMP_LABEL (insn
))
5169 = &ip2k_we_jump_targets
[INSN_UID (JUMP_LABEL (insn
))];
5171 if (wjt
->touch_count
== 0)
5172 wjt
->w_equiv
= w_current
;
5174 if (wjt
->touch_count
< wjt
->reach_count
)
5177 if (! rtx_equal_p (wjt
->w_equiv
, w_current
))
5178 wjt
->w_equiv
= NULL_RTX
;
5186 /* Anything other than a code labal or jump arrives here. We try and
5187 track WREG, but sometimes we might not be able to. */
5188 w_current_ok
= track_w_reload (insn
, &w_current
, w_current_ok
, 0);
5191 /* When we're looking to see if we've finished we count the number of
5192 paths through the code labels where we weren't able to definitively
5193 track WREG. This number is used to see if we're converging on a
5195 If this hits zero then we've fully converged, but if this stays the
5196 same as last time then we probably can't make any further
5198 incomplete_scan
= 0;
5199 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
5201 if (GET_CODE (insn
) == CODE_LABEL
)
5203 wjt
= &ip2k_we_jump_targets
[INSN_UID (insn
)];
5204 if (wjt
->touch_count
!= wjt
->reach_count
)
5206 incomplete_scan
+= (wjt
->reach_count
- wjt
->touch_count
);
5207 wjt
->w_equiv
= NULL_RTX
;
5208 wjt
->touch_count
= 0;
5213 while (incomplete_scan
&& incomplete_scan
!= last_incomplete_scan
);
5215 /* Finally we scan the whole function and run WREG elimination. When we hit
5216 a CODE_LABEL we pick up any stored equivalence since we now know that
5217 every path to this point entered with WREG holding the same thing! If
5218 we subsequently have a reload that matches then we can eliminate it. */
5219 w_current
= NULL_RTX
;
5220 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
5222 if (GET_CODE (insn
) == JUMP_INSN
)
5225 if (GET_CODE (insn
) == CODE_LABEL
)
5227 wjt
= &ip2k_we_jump_targets
[INSN_UID (insn
)];
5228 w_current
= wjt
->w_equiv
;
5232 track_w_reload (insn
, &w_current
, 1, 1);
5235 free (ip2k_we_jump_targets
);
5237 #endif /* IP2K_MD_REORG_PASS */
5239 /* We perform a lot of untangling of the RTL within the reorg pass since
5240 the IP2k requires some really bizarre (and really undesireable) things
5241 to happen in order to guarantee not aborting. This pass causes several
5242 earlier passes to be re-run as it progressively transforms things,
5243 making the subsequent runs continue to win. */
5248 #ifdef IP2K_MD_REORG_PASS
5249 rtx first_insn
, insn
, set
;
5256 ip2k_reorg_completed
= 1;
5257 ip2k_reorg_split_dimode
= 1;
5258 ip2k_reorg_split_simode
= 1;
5259 ip2k_reorg_split_himode
= 1;
5260 ip2k_reorg_split_qimode
= 1;
5261 ip2k_reorg_merge_qimode
= 1;
5264 #ifndef IP2K_MD_REORG_PASS
5265 ip2k_reorg_completed
= 1;
5266 ip2k_reorg_split_dimode
= 1;
5267 ip2k_reorg_split_simode
= 1;
5268 ip2k_reorg_split_himode
= 1;
5269 ip2k_reorg_split_qimode
= 1;
5270 ip2k_reorg_merge_qimode
= 1;
5272 /* All optimizations below must be debugged and enabled one by one.
5273 All of them commented now because of abort in GCC core. */
5275 ip2k_reorg_in_progress
= 1;
5277 first_insn
= get_insns ();
5279 /* Look for size effects of earlier optimizations - in particular look for
5280 situations where we're saying "use" a register on one hand but immediately
5281 tagging it as "REG_DEAD" at the same time! Seems like a bug in core-gcc
5282 somewhere really but this is what we have to live with! */
5283 for (insn
= first_insn
; insn
; insn
= NEXT_INSN (insn
))
5287 if (GET_CODE (insn
) == CODE_LABEL
5288 || GET_CODE (insn
) == NOTE
5289 || GET_CODE (insn
) == BARRIER
)
5295 body
= PATTERN (insn
);
5296 if (GET_CODE (body
) == USE
)
5297 if (GET_CODE (XEXP (body
, 0)) == REG
)
5301 reg
= REGNO (XEXP (body
, 0));
5302 if (find_regno_note (insn
, REG_DEAD
, reg
))
5309 /* There's a good chance that since we last did CSE that we've rearranged
5310 things in such a way that another go will win. Do so now! */
5311 reload_cse_regs (first_insn
);
5312 find_basic_blocks (first_insn
, max_reg_num (), 0);
5313 life_analysis (first_insn
, 0, PROP_REG_INFO
| PROP_DEATH_NOTES
);
5315 /* Look for where absurd things are happening with DP. */
5316 mdr_try_dp_reload_elim (first_insn
);
5318 ip2k_reorg_in_progress
= 0;
5319 ip2k_reorg_completed
= 1;
5321 split_all_insns (0);
5323 reload_cse_regs (first_insn
);
5324 find_basic_blocks (first_insn
, max_reg_num (), 0);
5325 life_analysis (first_insn
, 0, PROP_REG_INFO
| PROP_DEATH_NOTES
);
5327 peephole2_optimize (NULL
);
5329 mdr_resequence_xy_yx (first_insn
);
5330 mdr_propagate_reg_equivs (first_insn
);
5332 /* Look for redundant set instructions. These can occur when we split
5333 instruction patterns and end up with the second half merging with
5334 or being replaced by something that clobbers the first half. */
5335 for (insn
= first_insn
; insn
; insn
= next_nonnote_insn (insn
))
5337 if (GET_CODE (insn
) == INSN
)
5339 set
= (GET_CODE (PATTERN (insn
)) == SET
) ? PATTERN (insn
) : NULL_RTX
;
5340 if ((set
!= NULL_RTX
)
5341 && (GET_CODE (XEXP (set
, 0)) == REG
)
5342 && (GET_MODE (XEXP (set
, 0)) == QImode
)
5343 && (find_regno_note (insn
, REG_UNUSED
, REGNO (XEXP (set
, 0)))))
5348 mdr_try_move_dp_reload (first_insn
);
5349 mdr_try_move_pushes (first_insn
);
5351 find_basic_blocks (first_insn
, max_reg_num (), 0);
5352 life_analysis (first_insn
, 0, PROP_FINAL
);
5354 mdr_try_propagate_move (first_insn
);
5355 mdr_resequence_xy_yx (first_insn
);
5357 ip2k_reorg_split_dimode
= 1;
5358 split_all_insns (0);
5360 mdr_try_remove_redundant_insns (first_insn
);
5362 mdr_try_propagate_move (first_insn
);
5364 reload_cse_regs (first_insn
);
5365 find_basic_blocks (first_insn
, max_reg_num (), 0);
5366 life_analysis (first_insn
, 0, PROP_FINAL
);
5368 peephole2_optimize (NULL
);
5370 mdr_try_propagate_move (first_insn
);
5372 find_basic_blocks (first_insn
, max_reg_num (), 0);
5373 life_analysis (first_insn
, 0, PROP_FINAL
);
5375 ip2k_reorg_split_simode
= 1;
5376 split_all_insns (0);
5378 mdr_try_remove_redundant_insns (first_insn
);
5380 mdr_try_propagate_move (first_insn
);
5382 reload_cse_regs (first_insn
);
5383 find_basic_blocks (first_insn
, max_reg_num (), 0);
5384 life_analysis (first_insn
, 0, PROP_FINAL
);
5386 peephole2_optimize (NULL
);
5388 mdr_try_propagate_move (first_insn
);
5390 find_basic_blocks (first_insn
, max_reg_num (), 0);
5391 life_analysis (first_insn
, 0, PROP_FINAL
);
5393 ip2k_reorg_split_himode
= 1;
5394 ip2k_reorg_merge_qimode
= 1;
5395 split_all_insns (0);
5397 mdr_try_remove_redundant_insns (first_insn
);
5398 mdr_try_propagate_clr (first_insn
);
5399 mdr_try_propagate_move (first_insn
);
5401 mdr_try_dp_reload_elim (first_insn
);
5402 mdr_try_move_dp_reload (first_insn
);
5404 rebuild_jump_labels (first_insn
);
5406 /* Call to jump_optimize (...) was here, but now I removed it. */
5408 find_basic_blocks (first_insn
, max_reg_num (), 0);
5409 life_analysis (first_insn
, 0, PROP_FINAL
);
5411 peephole2_optimize (NULL
);
5413 mdr_try_propagate_move (first_insn
);
5415 find_basic_blocks (first_insn
, max_reg_num (), 0);
5416 life_analysis (first_insn
, 0, PROP_FINAL
);
5417 mdr_try_remove_redundant_insns (first_insn
);
5419 mdr_try_propagate_clr (first_insn
);
5420 mdr_try_propagate_move (first_insn
);
5422 find_basic_blocks (first_insn
, max_reg_num (), 0);
5423 life_analysis (first_insn
, 0, PROP_FINAL
);
5425 ip2k_reorg_split_qimode
= 1;
5426 split_all_insns (0);
5428 mdr_try_wreg_elim (first_insn
);
5429 mdr_try_propagate_move (first_insn
);
5431 find_basic_blocks (first_insn
, max_reg_num (), 0);
5432 life_analysis (first_insn
, 0, PROP_FINAL
);
5437 ip2k_init_libfuncs (void)
5439 set_optab_libfunc (smul_optab
, SImode
, "_mulsi3");
5440 set_optab_libfunc (smul_optab
, DImode
, "_muldi3");
5441 set_optab_libfunc (cmp_optab
, HImode
, "_cmphi2");
5442 set_optab_libfunc (cmp_optab
, SImode
, "_cmpsi2");
5445 /* Returns a bit position if mask contains only a single bit. Returns -1 if
5446 there were zero or more than one set bits. */
5448 find_one_set_bit_p (HOST_WIDE_INT mask
)
5451 unsigned HOST_WIDE_INT n
= mask
;
5452 for (i
= 0; i
< 32; i
++)
5454 if (n
& 0x80000000UL
)
5456 if (n
& 0x7fffffffUL
)
5466 /* Returns a bit position if mask contains only a single clear bit.
5467 Returns -1 if there were zero or more than one clear bits. */
5469 find_one_clear_bit_p (HOST_WIDE_INT mask
)
5472 unsigned HOST_WIDE_INT n
= mask
;
5473 for (i
= 0; i
< 32; i
++)
5475 if ((n
& 0x80000000UL
) == 0UL)
5477 if ((n
& 0x7fffffffUL
) != 0x7fffffffUL
)
5489 /* Split a move into two smaller pieces.
5490 MODE indicates the reduced mode. OPERANDS[0] is the original destination
5491 OPERANDS[1] is the original src. The new destinations are
5492 OPERANDS[2] and OPERANDS[4], while the new sources are OPERANDS[3]
5496 ip2k_split_words (enum machine_mode nmode
, enum machine_mode omode
,
5499 rtx dl
, dh
; /* src/dest pieces. */
5501 int move_high_first
= 0; /* Assume no overlap. */
5504 switch (GET_CODE (operands
[0])) /* DEST */
5508 if ((GET_CODE (operands
[1]) == REG
5509 || GET_CODE (operands
[1]) == SUBREG
)
5510 && (true_regnum (operands
[0]) <= true_regnum (operands
[1])
5511 || (true_regnum (operands
[1])
5512 + GET_MODE_SIZE (omode
) - 1 < true_regnum (operands
[0]))))
5513 move_high_first
= 1;
5515 if (GET_CODE (operands
[0]) == SUBREG
)
5517 dl
= simplify_gen_subreg (nmode
, operands
[0], omode
,
5518 GET_MODE_SIZE (nmode
));
5519 dh
= simplify_gen_subreg (nmode
, operands
[0], omode
, 0);
5521 else if (GET_CODE (operands
[0]) == REG
&& ! IS_PSEUDO_P (operands
[0]))
5523 int r
= REGNO (operands
[0]);
5524 dh
= gen_rtx_REG (nmode
, r
);
5525 dl
= gen_rtx_REG (nmode
, r
+ HARD_REGNO_NREGS (r
, nmode
));
5529 dh
= gen_rtx_SUBREG (nmode
, operands
[0], 0);
5530 dl
= gen_rtx_SUBREG (nmode
, operands
[0], GET_MODE_SIZE (nmode
));
5535 switch (GET_CODE (XEXP (operands
[0], 0)))
5540 dl
= dh
= gen_rtx_MEM (nmode
, XEXP (operands
[0], 0));
5544 dl
= change_address (operands
[0], nmode
,
5545 plus_constant (XEXP (operands
[0], 0),
5546 GET_MODE_SIZE (nmode
)));
5547 dh
= gen_rtx_MEM (nmode
, XEXP (operands
[0], 0));
5554 switch (GET_CODE (operands
[1]))
5557 if (! IS_PSEUDO_P (operands
[1]))
5559 int r
= REGNO (operands
[1]);
5561 sh
= gen_rtx_REG (nmode
, r
);
5562 sl
= gen_rtx_REG (nmode
, r
+ HARD_REGNO_NREGS (r
, nmode
));
5566 sh
= gen_rtx_SUBREG (nmode
, operands
[1], 0);
5567 sl
= gen_rtx_SUBREG (nmode
, operands
[1], GET_MODE_SIZE (nmode
));
5572 if (operands
[1] == const0_rtx
)
5573 sh
= sl
= const0_rtx
;
5576 if (GET_MODE (operands
[0]) != DImode
)
5581 REAL_VALUE_FROM_CONST_DOUBLE (rv
, operands
[1]);
5582 REAL_VALUE_TO_TARGET_SINGLE (rv
, value
);
5584 sh
= gen_int_mode ((value
>> 16) & 0xffff, nmode
);
5585 sl
= gen_int_mode (value
& 0xffff, nmode
);
5589 sh
= gen_int_mode (CONST_DOUBLE_HIGH (operands
[1]), nmode
);
5590 sl
= gen_int_mode (CONST_DOUBLE_LOW (operands
[1]), nmode
);
5596 if (operands
[1] == const0_rtx
)
5597 sh
= sl
= const0_rtx
;
5600 int val
= INTVAL (operands
[1]);
5606 vh
= (val
>> 8) & 0xff;
5611 vh
= (val
>> 16) & 0xffff;
5616 if (val
< 0) /* sign extend */
5620 vl
= val
; /* Give low 32 bits back. */
5627 sl
= gen_int_mode (vl
, nmode
);
5628 sh
= gen_int_mode (vh
, nmode
);
5633 sl
= simplify_gen_subreg (nmode
, operands
[1], omode
,
5634 GET_MODE_SIZE (nmode
));
5635 sh
= simplify_gen_subreg (nmode
, operands
[1], omode
, 0);
5639 switch (GET_CODE (XEXP (operands
[1], 0)))
5647 /* Worry about splitting stack pushes. */
5648 if (pushflag
&& ip2k_address_uses_reg_p (operands
[1], REG_SP
))
5649 sl
= sh
= change_address (operands
[1], nmode
,
5650 plus_constant (XEXP (operands
[1], 0),
5651 GET_MODE_SIZE (nmode
)));
5654 sl
= change_address (operands
[1], nmode
,
5655 plus_constant (XEXP (operands
[1], 0),
5656 GET_MODE_SIZE (nmode
)));
5657 sh
= gen_rtx_MEM (nmode
, XEXP (operands
[1], 0));
5666 if (move_high_first
)
5683 /* Get the low half of an operand. */
5685 ip2k_get_low_half (rtx x
, enum machine_mode mode
)
5687 switch (GET_CODE (x
))
5690 if (! IS_PSEUDO_P (x
))
5692 unsigned int r
= REGNO (x
);
5694 return gen_rtx_REG (mode
, r
+ HARD_REGNO_NREGS (r
, mode
));
5698 return gen_rtx_SUBREG (mode
, x
, GET_MODE_SIZE (mode
));
5703 if (x
== const0_rtx
)
5712 REAL_VALUE_FROM_CONST_DOUBLE (rv
, x
);
5713 REAL_VALUE_TO_TARGET_SINGLE (rv
, value
);
5715 return gen_int_mode (value
& 0xffff, mode
);
5718 return gen_int_mode (CONST_DOUBLE_LOW (x
), mode
);
5723 if (x
== const0_rtx
)
5727 int val
= INTVAL (x
);
5733 vh
= (val
>> 8) & 0xff;
5738 vh
= (val
>> 16) & 0xffff;
5743 if (val
< 0) /* sign extend */
5747 vl
= val
; /* Give low 32 bits back. */
5754 return gen_int_mode (vl
, mode
);
5759 return simplify_gen_subreg (mode
, x
, GET_MODE (x
), GET_MODE_SIZE (mode
));
5762 switch (GET_CODE (XEXP (x
, 0)))
5770 return change_address (x
, mode
,
5771 plus_constant (XEXP (x
, 0),
5772 GET_MODE_SIZE (mode
)));
5782 /* Get the high half of an operand. */
5784 ip2k_get_high_half (rtx x
, enum machine_mode mode
)
5786 switch (GET_CODE (x
))
5789 if (! IS_PSEUDO_P (x
))
5791 unsigned int r
= REGNO (x
);
5793 return gen_rtx_REG (mode
, r
);
5797 return gen_rtx_SUBREG (mode
, x
, 0);
5802 if (x
== const0_rtx
)
5811 REAL_VALUE_FROM_CONST_DOUBLE (rv
, x
);
5812 REAL_VALUE_TO_TARGET_SINGLE (rv
, value
);
5814 return gen_int_mode ((value
>> 16) & 0xffff, mode
);
5817 return gen_int_mode (CONST_DOUBLE_HIGH (x
), mode
);
5822 if (x
== const0_rtx
)
5826 int val
= INTVAL (x
);
5832 vh
= (val
>> 8) & 0xff;
5837 vh
= (val
>> 16) & 0xffff;
5842 if (val
< 0) /* sign extend */
5846 vl
= val
; /* Give low 32 bits back. */
5853 return gen_int_mode (vh
, mode
);
5858 return simplify_gen_subreg (mode
, x
, GET_MODE (x
), 0);
5862 switch (GET_CODE (XEXP (x
, 0)))
5870 return change_address (x
, mode
, plus_constant (XEXP (x
, 0), 0));
5880 /* Does address X use register R. Only valid for REG_SP, REG_DP, REG_IP
5884 ip2k_address_uses_reg_p (rtx x
, unsigned int r
)
5886 if (GET_CODE (x
) != MEM
)
5892 switch (GET_CODE (x
))
5902 if (ip2k_address_uses_reg_p (XEXP (x
, 1), r
))
5909 /* Ignore subwords. */
5914 /* Have to consider that r might be LSB of a pointer reg. */
5915 return ((REGNO (x
) == r
) || (REGNO (x
) == (r
- 1))) ? 1 : 0;
5918 /* We might be looking at a (mem:BLK (mem (...))) */
5927 /* Does the queried XEXP not use a particular register? If we're certain
5928 that it doesn't then we return TRUE otherwise we assume FALSE. */
5931 ip2k_xexp_not_uses_reg_p (rtx x
, unsigned int r
, int rsz
)
5933 switch (GET_CODE (x
))
5937 int msz
= GET_MODE_SIZE (GET_MODE (x
));
5939 return (((REGNO (x
) + msz
- 1) < r
)
5940 || (REGNO (x
) > (r
+ rsz
- 1)));
5944 return !ip2k_address_uses_reg_p (x
, r
);
5960 /* Does the queried XEXP not use a particular register? If we're certain
5961 that it doesn't then we return TRUE otherwise we assume FALSE. */
5964 ip2k_composite_xexp_not_uses_reg_p (rtx x
, unsigned int r
, int rsz
)
5966 if (GET_RTX_CLASS (GET_CODE (x
)) == 'b')
5967 return (ip2k_composite_xexp_not_uses_reg_p (XEXP (x
, 0), r
, rsz
)
5968 && ip2k_composite_xexp_not_uses_reg_p (XEXP (x
, 1), r
, rsz
)
5969 && ip2k_composite_xexp_not_uses_reg_p (XEXP (x
, 2), r
, rsz
));
5971 if (GET_RTX_CLASS (GET_CODE (x
)) == '2'
5972 || GET_RTX_CLASS (GET_CODE (x
)) == 'c'
5973 || GET_RTX_CLASS (GET_CODE (x
)) == '<')
5974 return (ip2k_composite_xexp_not_uses_reg_p (XEXP (x
, 0), r
, rsz
)
5975 && ip2k_composite_xexp_not_uses_reg_p (XEXP (x
, 1), r
, rsz
));
5977 if (GET_RTX_CLASS (GET_CODE (x
)) == '1'
5978 || GET_RTX_CLASS (GET_CODE (x
)) == '3')
5979 return ip2k_composite_xexp_not_uses_reg_p (XEXP (x
, 0), r
, rsz
);
5981 return ip2k_xexp_not_uses_reg_p (x
, r
, rsz
);
5984 /* Does the queried XEXP not use CC0? If we're certain that
5985 it doesn't then we return TRUE otherwise we assume FALSE. */
5988 ip2k_composite_xexp_not_uses_cc0_p (rtx x
)
5990 if (GET_RTX_CLASS (GET_CODE (x
)) == 'b')
5991 return (ip2k_composite_xexp_not_uses_cc0_p (XEXP (x
, 0))
5992 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (x
, 1))
5993 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (x
, 2)));
5995 if (GET_RTX_CLASS (GET_CODE (x
)) == '2'
5996 || GET_RTX_CLASS (GET_CODE (x
)) == 'c'
5997 || GET_RTX_CLASS (GET_CODE (x
)) == '<')
5998 return (ip2k_composite_xexp_not_uses_cc0_p (XEXP (x
, 0))
5999 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (x
, 1)));
6001 if (GET_RTX_CLASS (GET_CODE (x
)) == '1'
6002 || GET_RTX_CLASS (GET_CODE (x
)) == '3')
6003 return ip2k_composite_xexp_not_uses_cc0_p (XEXP (x
, 0));
6005 return GET_CODE (x
) != CC0
;
6009 ip2k_split_dest_operand (rtx x
, enum machine_mode mode
)
6011 return nonimmediate_operand (x
, mode
) || push_operand (x
, mode
);
6015 ip2k_nonptr_operand (rtx x
, enum machine_mode mode
)
6017 return register_operand (x
, mode
) && !ip2k_ptr_operand (x
, mode
);
6020 /* Is X a reference to IP or DP or SP? */
6023 ip2k_ptr_operand (rtx x
, enum machine_mode mode
)
6026 if (GET_CODE (x
) == SUBREG
)
6030 && (mode
== HImode
|| mode
== VOIDmode
)
6031 && (REGNO (x
) == REG_IP
6032 || REGNO (x
) == REG_DP
6033 || REGNO (x
) == REG_SP
));
6037 ip2k_sp_operand (rtx x
, enum machine_mode mode ATTRIBUTE_UNUSED
)
6040 return REG_P (x
) && REGNO (x
) == REG_SP
;
6044 ip2k_ip_operand (rtx x
, enum machine_mode mode
)
6047 if (GET_CODE (x
) != MEM
)
6052 if (GET_CODE (x
) == PLUS
&& XEXP (x
, 1) == const0_rtx
)
6058 if (GET_MODE_SIZE (mode
) > 1)
6059 return 0; /* Can't access offset bytes. */
6061 return REGNO (x
) == REG_IP
;
6064 /* Is X a memory address suitable for SP or DP relative addressing? */
6066 ip2k_short_operand (rtx x
, enum machine_mode mode
)
6069 unsigned int offs
= 0;
6071 if (! memory_operand (x
, mode
))
6072 return 0; /* Got to be a memory address. */
6075 switch (GET_CODE (x
))
6081 if (! REG_P (XEXP (x
, 0))
6082 || GET_CODE (XEXP (x
, 1)) != CONST_INT
)
6085 offs
= INTVAL (XEXP (x
, 1));
6095 if (IS_PSEUDO_P (x
))
6096 return 0; /* Optimistic - doesn't work. */
6100 /* For 'S' constraint, we presume that no IP adjustment
6101 simulation is performed - so only QI mode allows IP to be a
6102 short offset address. All other IP references must be
6103 handled by 'R' constraints. */
6104 if (r
== REG_IP
&& offs
== 0 && GET_MODE_SIZE (mode
) <= 1)
6107 return (r
== REG_SP
|| r
== REG_DP
);
6112 ip2k_nonsp_reg_operand (rtx x
, enum machine_mode mode ATTRIBUTE_UNUSED
)
6114 if (GET_CODE (x
) == SUBREG
)
6117 return (REG_P (x
) && REGNO (x
) != REG_SP
);
6121 ip2k_gen_operand (rtx x
, enum machine_mode mode
)
6123 return ip2k_short_operand (x
, mode
)
6124 || (GET_CODE (x
) == SUBREG
6125 && REG_P (SUBREG_REG (x
)))
6126 || (ip2k_nonsp_reg_operand (x
, mode
));
6130 ip2k_extra_constraint (rtx x
, int c
)
6134 case 'S': /* Allow offset in stack frame... */
6135 return ip2k_short_operand (x
, GET_MODE (x
));
6138 return ip2k_ip_operand (x
, GET_MODE (x
));
6140 case 'T': /* Constant int or .data address. */
6141 return CONSTANT_P (x
) && is_regfile_address (x
);
6149 ip2k_unary_operator (rtx op
, enum machine_mode mode
)
6151 return ((mode
== VOIDmode
|| GET_MODE (op
) == mode
)
6152 && GET_RTX_CLASS (GET_CODE (op
)) == '1');
6156 ip2k_binary_operator (rtx op
, enum machine_mode mode
)
6158 return ((mode
== VOIDmode
|| GET_MODE (op
) == mode
)
6159 && (GET_RTX_CLASS (GET_CODE (op
)) == 'c'
6160 || GET_RTX_CLASS (GET_CODE (op
)) == '2'));
6164 ip2k_symbol_ref_operand (rtx op
, enum machine_mode mode ATTRIBUTE_UNUSED
)
6166 /* We define an IP2k symbol ref to be either a direct reference or one
6167 with a constant offset. */
6168 return (GET_CODE (op
) == SYMBOL_REF
)
6169 || (GET_CODE (op
) == CONST
6170 && GET_CODE (XEXP (op
, 0)) == PLUS
6171 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == SYMBOL_REF
);
6175 ip2k_signed_comparison_operator (rtx op
, enum machine_mode mode
)
6177 return (comparison_operator (op
, mode
)
6178 && signed_condition (GET_CODE (op
)) == GET_CODE (op
));
6182 ip2k_unsigned_comparison_operator (rtx op
, enum machine_mode mode
)
6184 return (comparison_operator (op
, mode
)
6185 && unsigned_condition (GET_CODE (op
)) == GET_CODE (op
));