1 /* Subroutines used for code generation on Ubicom IP2022
2 Communications Controller.
3 Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
4 Contributed by Red Hat, Inc and Ubicom, Inc.
6 This file is part of GNU CC.
8 GNU CC 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 GNU CC 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 GNU CC; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
27 #include "hard-reg-set.h"
29 #include "insn-config.h"
30 #include "conditions.h"
31 #include "insn-flags.h"
33 #include "insn-attr.h"
34 #include "insn-addr.h"
45 #include "target-def.h"
46 #include "basic-block.h"
48 /* There are problems with 'frame_pointer_needed'. If we force it
49 on, we either end up not eliminating uses of FP, which results in
50 SPILL register failures or we may end up with calculation errors in
51 the stack offsets. Isolate the decision process into a simple macro. */
52 #define CHAIN_FRAMES (frame_pointer_needed || FRAME_POINTER_REQUIRED)
54 static int ip2k_naked_function_p PARAMS ((tree));
55 static void mdr_resequence_xy_yx PARAMS ((rtx));
56 static void mdr_pres_replace_and_recurse PARAMS ((rtx, rtx, rtx));
57 static void mdr_propagate_reg_equivs_sequence PARAMS ((rtx, rtx, rtx));
58 static void mdr_propagate_reg_equivs PARAMS ((rtx));
59 static int track_dp_reload PARAMS ((rtx , rtx *, int , int));
60 static void mdr_try_dp_reload_elim PARAMS ((rtx));
61 static void mdr_try_move_dp_reload PARAMS ((rtx));
62 static int ip2k_check_can_adjust_stack_ref PARAMS ((rtx, int));
63 static void ip2k_adjust_stack_ref PARAMS ((rtx *, int));
64 static void mdr_try_move_pushes PARAMS ((rtx));
65 static int ip2k_xexp_not_uses_reg_for_mem PARAMS ((rtx, unsigned int));
66 static void mdr_try_propagate_clr_sequence PARAMS ((rtx, unsigned int));
67 static void mdr_try_propagate_clr PARAMS ((rtx));
68 static void mdr_try_propagate_move_sequence PARAMS ((rtx, rtx, rtx));
69 static void mdr_try_propagate_move PARAMS ((rtx));
70 static void mdr_try_remove_redundant_insns PARAMS ((rtx));
71 static int track_w_reload PARAMS ((rtx, rtx *, int , int));
72 static void mdr_try_wreg_elim PARAMS ((rtx));
75 /* Initialize the GCC target structure. */
76 #undef TARGET_ASM_ALIGNED_HI_OP
77 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
79 #undef TARGET_ASM_FUNCTION_PROLOGUE
80 #define TARGET_ASM_FUNCTION_PROLOGUE function_prologue
82 #undef TARGET_ASM_FUNCTION_EPILOGUE
83 #define TARGET_ASM_FUNCTION_EPILOGUE function_epilogue
85 #undef TARGET_ASM_UNIQUE_SECTION
86 #define TARGET_ASM_UNIQUE_SECTION unique_section
88 #undef TARGET_ENCODE_SECTION_INFO
89 #define TARGET_ENCODE_SECTION_INFO encode_section_info
91 struct gcc_target targetm = TARGET_INITIALIZER;
93 /* Commands count in the compiled file. */
94 static int commands_in_file;
96 /* Commands in the functions prologues in the compiled file. */
97 static int commands_in_prologues;
99 /* Commands in the functions epilogues in the compiled file. */
100 static int commands_in_epilogues;
102 /* Prologue/Epilogue size in words. */
103 static int prologue_size;
104 static int epilogue_size;
106 /* compare and test instructions for the IP2K are materialized by
107 the conditional branch that uses them. This is because conditional
108 branches are skips over unconditional branches. */
109 rtx ip2k_compare_operands[3]; /* Additional operands for condition code. */
110 int ip2k_test_flag; /* Indicates Z, WREG contain condition code
113 /* Some ip2k patterns push a byte onto the stack and then access
114 SP-relative addresses. Since reload doesn't know about these
115 pushes, we must track them internally with a %< (push) or %> (pop)
117 static int ip2k_stack_delta;
119 /* Track if or how far our ip2k reorganization pass has run. */
120 int ip2k_reorg_in_progress = 0;
121 int ip2k_reorg_completed = 0;
122 int ip2k_reorg_split_dimode = 0;
123 int ip2k_reorg_split_simode = 0;
124 int ip2k_reorg_split_himode = 0;
125 int ip2k_reorg_split_qimode = 0;
126 int ip2k_reorg_merge_qimode = 0;
128 /* Set up local allocation order. */
131 ip2k_init_local_alloc (rao)
134 static const int alloc_order[] = REG_ALLOC_ORDER;
136 memcpy (rao, alloc_order, sizeof (alloc_order));
139 /* Returns the number of bytes of arguments automatically
140 popped when returning from a subroutine call.
141 FUNDECL is the declaration node of the function (as a tree),
142 FUNTYPE is the data type of the function (as a tree),
143 or for a library call it is an identifier node for the subroutine name.
144 SIZE is the number of bytes of arguments passed on the stack. */
147 ip2k_return_pops_args (fundecl, funtype, size)
148 tree fundecl ATTRIBUTE_UNUSED;
152 if (TREE_CODE (funtype) == IDENTIFIER_NODE)
155 if (TYPE_ARG_TYPES (funtype) == NULL_TREE
156 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype))) == void_type_node))
162 /* Return non-zero if FUNC is a naked function. */
165 ip2k_naked_function_p (func)
170 if (TREE_CODE (func) != FUNCTION_DECL)
173 a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
174 return a != NULL_TREE;
177 /* Output function prologue. */
179 function_prologue (file, size)
188 prologue_size = epilogue_size = 0;
190 if (ip2k_naked_function_p (current_function_decl))
192 fprintf (file, "/* prologue: naked */\n");
196 leaf_func_p = leaf_function_p ();
197 main_p = ! strcmp ("main", current_function_name);
199 /* For now, we compute all these facts about the function, but don't
200 take any action based on the information. */
203 fprintf (file, "/* prologue: frame size=%d */\n", size);
205 /* Unless we're a leaf we need to save the return PC. */
209 OUT_AS1 (push, calll);
210 OUT_AS1 (push, callh);
214 /* We need to save the old FP and set the new FP pointing at the
215 stack location where the old one is saved. Note that because of
216 post-decrement addressing, the SP is off-by-one after the
217 push, so we harvest the SP address BEFORE we push the MSBs of
221 OUT_AS1 (push, REG_FP+1); /* Save old LSBs. */
222 OUT_AS2 (mov, w, spl);
223 OUT_AS2 (mov, REG_FP+1, w); /* SPL -> FPL */
225 OUT_AS2 (mov, w, sph); /* Freeze SP MSBs */
226 OUT_AS1 (push, REG_FP); /* Save old MSBs */
227 OUT_AS2 (mov, REG_FP, w); /* SPH -> FPH */
231 for (reg = (CHAIN_FRAMES) ? (REG_FP - 1) : (REG_FP + 1);
234 if (regs_ever_live[reg] && ! call_used_regs[reg])
236 fprintf (file, "\t" AS1 (push,%s) "\n", reg_names[reg]);
243 operands[0] = GEN_INT (size);
254 OUT_AS2 (mov, w, %L0);
255 OUT_AS2 (sub, spl, w);
259 switch (size & 0xff00)
268 if ((size & 0xff) != ((size >> 8) & 0xff))
269 OUT_AS2 (mov, w, %H0); /* Otherwise W has value we want. */
270 OUT_AS2 (sub, sph, w);
275 /* XXX - change this to use the carry-propagating subtract trick. */
276 if (flag_stack_check)
278 OUT_AS2 (mov, w, sph);
279 OUT_AS2 (cmp, w, #%%hi8data(_end));
280 OUT_AS1 (sc, ); /* C == 0 -> hi8(edata) < sph */
283 OUT_AS1 (sz, ); /* Z == 1 -> look at low byte */
285 OUT_AS1 (jmp,0f); /* sp < edata, so raise stack fault */
286 OUT_AS2 (mov, w, spl);
287 OUT_AS2 (cmp, w, #%%lo8data(_end));
288 OUT_AS1 (sc,); /* C==1 -> lo8(edata) >= spl */
292 output_asm_insn ("push\t$ff", operands);
299 /* Output function epilogue. */
301 function_epilogue (file, size)
308 rtx operands[2]; /* Dummy used by OUT_ASn */
311 /* Use this opportunity to reset the reorg flags! */
312 ip2k_reorg_in_progress = 0;
313 ip2k_reorg_completed = 0;
314 ip2k_reorg_split_dimode = 0;
315 ip2k_reorg_split_simode = 0;
316 ip2k_reorg_split_himode = 0;
317 ip2k_reorg_split_qimode = 0;
318 ip2k_reorg_merge_qimode = 0;
320 if (ip2k_naked_function_p (current_function_decl))
322 fprintf (file, "/* epilogue: naked */\n");
326 leaf_func_p = leaf_function_p ();
327 function_size = (INSN_ADDRESSES (INSN_UID (get_last_insn ()))
328 - INSN_ADDRESSES (INSN_UID (get_insns ())));
331 fprintf (file, "/* epilogue: frame size=%d */\n", size);
335 operands[0] = GEN_INT (size);
340 OUT_AS2 (mov, w, %L0);
341 OUT_AS2 (add, spl, w);
351 switch (size & 0xff00)
354 if ((size & 0xff) != ((size >> 8) & 0xff))
355 OUT_AS2 (mov, w, %H0);
356 OUT_AS2 (add, sph, w);
367 savelimit = (CHAIN_FRAMES) ? REG_FP : (REG_FP + 2);
369 for (reg = 0; reg < savelimit; reg++)
371 if (regs_ever_live[reg] && ! call_used_regs[reg])
373 fprintf (file, "\t" AS1 (pop,%s) "\n", reg_names[reg]);
379 && ! (current_function_pops_args
380 && current_function_args_size >= 2
381 && current_function_args_size < 0x100))
383 OUT_AS1 (pop, REG_FP);
384 OUT_AS1 (pop, REG_FP+1);
390 if (current_function_pops_args
391 && current_function_args_size >= 2
392 && current_function_args_size < 0x100)
394 if (current_function_args_size == 2)
398 OUT_AS1 (page, __fp_pop2_args_ret);
399 OUT_AS1 (jmp, __fp_pop2_args_ret);
403 OUT_AS1 (page, __pop2_args_ret);
404 OUT_AS1 (jmp, __pop2_args_ret);
410 operands[0] = GEN_INT (current_function_args_size);
411 OUT_AS2 (mov, w, %L0);
414 OUT_AS1 (page, __fp_pop_args_ret);
415 OUT_AS1 (jmp, __fp_pop_args_ret);
419 OUT_AS1 (page, __pop_args_ret);
420 OUT_AS1 (jmp, __pop_args_ret);
428 OUT_AS1 (pop, callh);
429 OUT_AS1 (pop, calll);
435 if (current_function_pops_args
436 && current_function_args_size >= 2
437 && current_function_args_size < 0x100)
439 if (current_function_args_size == 2)
443 OUT_AS1 (page, __leaf_fp_pop2_args_ret);
444 OUT_AS1 (jmp, __leaf_fp_pop2_args_ret);
451 operands[0] = GEN_INT (current_function_args_size);
454 OUT_AS2 (mov, w, %L0);
455 OUT_AS1 (page, __leaf_fp_pop_args_ret);
456 OUT_AS1 (jmp, __leaf_fp_pop_args_ret);
464 if (current_function_pops_args && current_function_args_size
467 operands[0] = GEN_INT (current_function_args_size);
469 switch (current_function_args_size & 0xff)
472 OUT_AS2 (mov, w, %L0);
473 OUT_AS2 (add, spl, w);
485 switch (current_function_args_size & 0xff00)
488 if ((current_function_args_size & 0xff)
489 != ((current_function_args_size >> 8) & 0xff))
490 OUT_AS2 (mov, w, %H0);
491 OUT_AS2 (add, sph, w);
510 fprintf (file, "/* epilogue end (size=%d) */\n", epilogue_size);
511 fprintf (file, "/* function %s size %d (%d) */\n", current_function_name,
512 prologue_size + function_size + epilogue_size, function_size);
513 commands_in_file += prologue_size + function_size + epilogue_size;
514 commands_in_prologues += prologue_size;
515 commands_in_epilogues += epilogue_size;
518 /* Return the difference between the registers after the function
521 Stack Frame grows down:
524 <------ AP ($102:$103)
525 RETURN PC (unless leaf function)
527 <------ FP [HARD_FRAME_POINTER] ($FD:$FE)
529 <------ VFP [$100:$101]
531 <------ SP ($6:$7) */
533 ip2k_init_elim_offset (from, to)
537 int leaf_func_p = leaf_function_p ();
538 int no_saved_pc = leaf_func_p
539 || ip2k_naked_function_p (current_function_decl);
544 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
545 return get_frame_size () + 1;
547 if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
548 return (CHAIN_FRAMES ? 2 : 0) + (no_saved_pc ? 0 : 2);
550 /* Count all the registers we had to preserve. */
552 reglimit = CHAIN_FRAMES ? REG_FP : (REG_FP + 2);
553 for (offset = 0,reg = 0; reg < reglimit; ++reg)
555 if ((regs_ever_live[reg] && ! call_used_regs[reg]))
561 if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
564 if (from == HARD_FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
565 /* Add in the stack-local variables. */
566 return offset + get_frame_size () + 1;
568 if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
569 /* Add stack-locals plus saved FP and PC. */
570 return offset + get_frame_size () + 1
571 + (CHAIN_FRAMES ? 2 : 0) + (no_saved_pc ? 0 : 2);
573 abort (); /* Unanticipated elimination. */
576 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
577 machine for a memory operand of mode MODE. */
580 legitimate_address_p (mode, x, strict)
581 enum machine_mode mode;
587 if (GET_CODE (x) == SUBREG)
590 switch (GET_CODE (x))
593 /* IP allows indirection without offset - only okay if
594 we don't require access to multiple bytes. */
595 if (REGNO (x) == REG_IP)
596 return (GET_MODE_SIZE (mode) == 1) ? 'R' : 0;
598 /* We can indirect thru DP or SP register. */
599 if (strict ? REG_OK_FOR_BASE_STRICT_P (x)
600 : REG_OK_FOR_BASE_NOSTRICT_P (x))
605 /* Offsets from DP or SP are legal in the range 0..127 */
612 if (REG_P (op2) && ! REG_P (op1))
619 /* Don't let anything but R+I thru.. */
622 || GET_CODE (op2) != CONST_INT)
627 case REG_DP: /* only 0..127 displacement */
629 off = 2 * GET_MODE_SIZE (mode);
633 if (INTVAL (op2) < 0 || INTVAL (op2) > (128 - off))
634 return 0; /* Positive must be small enough that after
635 splitting all pieces are addressed. */
636 return 'S'; /* Safe displacement. */
639 if (GET_MODE_SIZE (mode) <= 1 && INTVAL (op2) == 0)
640 return (GET_MODE_SIZE (mode) == 1) ? 'R' : 0;
647 if (strict || ! REG_OK_FOR_BASE_NOSTRICT_P (op1))
648 return 0; /* Allow until reload. */
657 /* We always allow references to things in code space. */
658 return is_regfile_address (x) ? 0 : 'C';
670 /* Is ADDR mode dependent? */
672 ip2k_mode_dependent_address (addr)
675 switch (GET_CODE (addr))
684 return (REGNO (addr) == REG_IP); /* Can't do IP displaced addresses. */
687 return 0; /* Assume no dependency. */
691 /* Attempts to replace X with a valid
692 memory address for an operand of mode MODE. */
695 legitimize_address (x, oldx, mode, scratch)
697 rtx oldx ATTRIBUTE_UNUSED;
699 enum machine_mode mode ATTRIBUTE_UNUSED;
703 /* You might think that we could split up a symbolic address by
704 adding the HIGH 8 bits and doing a displacement off the dp. But
705 because we only have 7 bits of offset, that doesn't actually
706 help. So only constant displacements are likely to obtain an
709 if (GET_CODE (x) == PLUS && REG_P (XEXP (x, 0))
710 && GET_CODE (XEXP (x, 1)) == CONST_INT
711 && ! CONST_OK_FOR_LETTER_P (INTVAL (XEXP (x, 1)), 'K'))
713 int offset = INTVAL (XEXP (x, 1));
715 reg = scratch ? scratch : gen_reg_rtx (Pmode);
717 emit_insn (gen_rtx_SET (VOIDmode, reg,
718 gen_rtx_PLUS (Pmode, XEXP (x, 0),
719 GEN_INT (offset & 0xffc0))));
720 x = gen_rtx_PLUS (Pmode, reg, GEN_INT (offset & 0x3f));
723 return x; /* We don't have any other tricks. */
726 /* Determine if X is a 'data' address or a code address. All static
727 data and stack variables reside in data memory. Only code is believed
728 to be in PRAM or FLASH. */
730 is_regfile_address (x)
734 switch (GET_CODE (x))
737 return ! SYMBOL_REF_FLAG (x); /* Declared as function. */
755 /* Output ADDR to FILE as address. */
758 print_operand_address (file, addr)
762 switch (GET_CODE (addr))
765 addr = alter_subreg (&addr);
769 fprintf (file, "(%s)",
770 REGNO (addr) == REG_DP ? "DP"
771 : REGNO (addr) == REG_SP ? "SP"
772 : REGNO (addr) == REG_IP ? "IP"
773 : REGNO (addr) == REG_VFP ? "VFP" /* Should never see this */
774 : REGNO (addr) == REG_AP ? "AP" /* or this, either. */
775 : reg_names[REGNO (addr)]);
784 addr = XEXP (addr, 0);
785 print_operand_address (file, XEXP (addr, 0));
787 print_operand_address (file, XEXP (addr, 1));
791 if (is_regfile_address (XEXP (addr, 1)))
792 fprintf (file, "%%lo8data(");
794 fprintf (file, "%%lo8insn(");
795 print_operand_address (file, XEXP (addr, 1));
797 print_operand_address (file, XEXP (addr, 0));
800 case PLUS: /* Ought to be stack or dp references. */
801 if (XEXP (addr, 1) == const0_rtx
802 && GET_CODE (XEXP (addr, 0)) == PLUS)
804 print_operand_address (file, XEXP (addr, 0));
808 if (! REG_P (XEXP (addr, 0)) || REGNO (XEXP (addr, 0)) != REG_IP)
809 print_operand_address (file, XEXP (addr, 1)); /* const */
810 print_operand_address (file, XEXP (addr, 0)); /* (reg) */
814 if (is_regfile_address (XEXP (addr, 0)))
815 fprintf (file, "%%hi8data(");
817 fprintf (file, "%%hi8insn(");
818 output_addr_const (file, XEXP (addr, 0));
823 output_addr_const (file, addr);
828 /* Output X as assembler operand to file FILE. */
831 print_operand (file, x, code)
878 if (ip2k_short_operand (x, GET_MODE (x))
879 && ip2k_address_uses_reg_p (x, REG_SP))
880 /* An SP-relative address needs to account for interior stack
881 pushes that reload didn't know about when it calculated the
883 abcd += ip2k_stack_delta;
885 switch (GET_CODE (x))
888 x = alter_subreg (&x);
892 fprintf (file, reg_names[true_regnum (x) + abcd]);
899 fprintf (file, "$%x", INTVAL (x) & 0xffff);
903 fprintf (file, "%d", INTVAL (x)); /* bit selector */
906 case 'e': /* "1 << n" - e.g. "exp" */
907 fprintf (file, "#%d", 1 << INTVAL (x));
915 value >>= 8 * (3 - abcd);
918 fprintf (file, "#%ld", value);
922 fprintf (file, "#%d", (INTVAL (x) >> 8) & 0xff);
926 fprintf (file, "#%d", INTVAL (x) & 0xff);
937 value = ((unsigned long long)INTVAL (x)) >> (8 * (7 - abcd)) & 0xff;
938 fprintf (file, "#%ld", value);
942 fprintf (file, "#%d", INTVAL (x));
964 abort (); /* Probably an error. */
968 fprintf (file, "#%s(",
969 is_regfile_address (x) ? "%hi8data"
971 print_operand_address (file, x);
976 fprintf (file, "#%s(",
977 is_regfile_address (x) ? "%lo8data"
979 print_operand_address (file, x);
984 print_operand_address (file, x);
990 rtx addr = XEXP (x, 0);
992 if (GET_CODE (addr) == SUBREG)
993 addr = alter_subreg (&x);
995 if (CONSTANT_P (addr) && abcd)
998 print_operand_address (file, addr);
999 fprintf (file, ")+%d", abcd);
1003 switch (GET_CODE (addr))
1006 abcd += INTVAL (XEXP (addr, 1));
1008 /* Worry about (plus (plus (reg DP) (const_int 10))
1010 if (GET_CODE (XEXP (addr, 0)) == PLUS)
1012 addr = XEXP (addr, 0);
1013 abcd += INTVAL (XEXP (addr, 1));
1016 fprintf (file, "%d", abcd);
1017 print_operand_address (file, XEXP (addr, 0));
1022 fprintf (file, "%d", abcd);
1023 print_operand_address (file, addr);
1026 else if (GET_CODE (addr) == REG
1027 && (REGNO (addr) == REG_DP || REGNO (addr) == REG_SP))
1029 fprintf (file, "0");
1030 print_operand_address (file, addr);
1033 print_operand_address (file, addr);
1038 /* Is this an integer or a floating point value? */
1039 if (GET_MODE (x) == VOIDmode)
1047 value = CONST_DOUBLE_HIGH (x);
1048 value >>= 8 * (3 - abcd);
1051 fprintf (file, "#%ld", value);
1058 value = CONST_DOUBLE_LOW (x);
1059 value >>= 8 * (7 - abcd);
1062 fprintf (file, "#%ld", value);
1071 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1072 REAL_VALUE_TO_TARGET_SINGLE (rv, value);
1073 asm_fprintf (file, "0x%x", value);
1078 fatal_insn ("bad operand", x);
1082 /* Remember the operands for the compare. */
1084 ip2k_set_compare (x, y)
1088 /* If we're doing a DImode compare then force any CONST_INT second
1089 operand to be CONST_DOUBLE. */
1090 if (GET_MODE (x) == DImode && GET_CODE (y) == CONST_INT)
1094 value = rtx_alloc (CONST_DOUBLE);
1095 PUT_MODE (value, VOIDmode);
1097 CONST_DOUBLE_LOW (value) = INTVAL (y);
1098 CONST_DOUBLE_HIGH (value) = INTVAL (y) > 0 ? 0 : -1;
1100 for (i = 2; i < (sizeof CONST_DOUBLE_FORMAT - 1); i++)
1101 XWINT (value, i) = 0;
1103 y = lookup_const_double (value);
1106 ip2k_compare_operands[0] = x;
1107 ip2k_compare_operands[1] = y;
1111 /* Emit the code for sCOND instructions. */
1113 ip2k_gen_sCOND (insn, code, dest)
1114 rtx insn ATTRIBUTE_UNUSED;
1118 #define operands ip2k_compare_operands
1119 enum machine_mode mode;
1123 mode = GET_MODE (operands[0]);
1124 if ((mode != QImode) && (mode != HImode)
1125 && (mode != SImode) && (mode != DImode))
1126 mode = GET_MODE (operands[1]);
1128 /* We have a fast path for a specific type of QImode compare. We ought
1129 to extend this for larger cases too but that wins less frequently and
1130 introduces a lot of complexity. */
1132 && !rtx_equal_p (operands[0], operands[2])
1133 && !rtx_equal_p (operands[1], operands[2])
1134 && (! REG_P (operands[2])
1135 || (ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[2]), 1)
1136 && ip2k_xexp_not_uses_reg_p (operands[1],
1137 REGNO (operands[2]), 1))))
1140 if (immediate_operand (operands[1], QImode)
1141 && ((INTVAL (operands[1]) & 0xff) == 0xff))
1144 OUT_AS2 (incsnz, w, %0);
1146 OUT_AS2 (incsz, w, %0);
1148 else if (immediate_operand (operands[1], QImode)
1149 && ((INTVAL (operands[1]) & 0xff) == 0x01))
1152 OUT_AS2 (decsnz, w, %0);
1154 OUT_AS2 (decsz, w, %0);
1156 else if (ip2k_compare_operands[1] == const0_rtx)
1158 OUT_AS2 (mov, w, %0);
1166 OUT_AS2 (mov, w, %0);
1168 OUT_AS2 (csne, w, %1);
1170 OUT_AS2 (cse, w, %1);
1176 if (ip2k_compare_operands[1] == const0_rtx)
1181 OUT_AS2 (mov, w, %0);
1185 OUT_AS2 (mov, w, %H0);
1186 OUT_AS2 (or, w, %L0);
1190 OUT_AS2 (mov, w, %A0);
1191 OUT_AS2 (or, w, %B0);
1192 OUT_AS2 (or, w, %C0);
1193 OUT_AS2 (or, w, %D0);
1197 OUT_AS2 (mov, w, %S0);
1198 OUT_AS2 (or, w, %T0);
1199 OUT_AS2 (or, w, %U0);
1200 OUT_AS2 (or, w, %V0);
1201 OUT_AS2 (or, w, %W0);
1202 OUT_AS2 (or, w, %X0);
1203 OUT_AS2 (or, w, %Y0);
1204 OUT_AS2 (or, w, %Z0);
1216 OUT_AS2 (mov, w, %1);
1217 OUT_AS2 (cmp, w, %0);
1221 OUT_AS2 (mov, w, %H1);
1222 OUT_AS2 (cmp, w, %H0);
1226 OUT_AS2 (mov, w, %L1);
1227 OUT_AS2 (cmp, w, %L0);
1234 OUT_AS2 (mov, w, #1);
1235 OUT_AS2 (mov, mulh, w);
1238 OUT_AS1 (clr, mulh);
1239 OUT_AS2 (mov, w, %A1);
1240 OUT_AS2 (cse, w, %A0);
1243 OUT_AS2 (mov, w, %B1);
1244 OUT_AS2 (cse, w, %B0);
1247 OUT_AS2 (mov, w, %C1);
1248 OUT_AS2 (cse, w, %C0);
1251 OUT_AS2 (mov, w, %D1);
1252 OUT_AS2 (cse, w, %D0);
1255 OUT_AS1 (dec, mulh);
1257 OUT_AS1 (inc, mulh);
1258 OUT_AS2 (mov, w, mulh);
1259 OUT_AS2 (mov, %2, w);
1265 OUT_AS2 (mov, w, #1);
1266 OUT_AS2 (mov, mulh, w);
1269 OUT_AS1 (clr, mulh);
1270 OUT_AS2 (mov, w, %S1);
1271 OUT_AS2 (cse, w, %S0);
1274 OUT_AS2 (mov, w, %T1);
1275 OUT_AS2 (cse, w, %T0);
1278 OUT_AS2 (mov, w, %U1);
1279 OUT_AS2 (cse, w, %U0);
1282 OUT_AS2 (mov, w, %V1);
1283 OUT_AS2 (cse, w, %V0);
1286 OUT_AS2 (mov, w, %W1);
1287 OUT_AS2 (cse, w, %W0);
1290 OUT_AS2 (mov, w, %X1);
1291 OUT_AS2 (cse, w, %X0);
1294 OUT_AS2 (mov, w, %Y1);
1295 OUT_AS2 (cse, w, %Y0);
1298 OUT_AS2 (mov, w, %Z1);
1299 OUT_AS2 (cse, w, %Z0);
1302 OUT_AS1 (dec, mulh);
1304 OUT_AS1 (inc, mulh);
1305 OUT_AS2 (mov, w, mulh);
1306 OUT_AS2 (mov, %2, w);
1313 OUT_AS2 (mov, w, #0);
1318 OUT_AS1 (inc, wreg);
1319 OUT_AS2 (mov, %2, w);
1327 ip2k_gen_signed_comp_branch (insn, code, label)
1332 #define operands ip2k_compare_operands
1333 enum machine_mode mode;
1334 int can_use_skip = 0;
1337 operands[2] = label;
1339 mode = GET_MODE (operands[0]);
1340 if ((mode != QImode) && (mode != HImode)
1341 && (mode != SImode) && (mode != DImode))
1342 mode = GET_MODE (operands[1]);
1344 /* Look for situations where we can just skip the next instruction instead
1345 of skipping and then branching! */
1346 ninsn = next_real_insn (insn);
1348 && (recog_memoized (ninsn) >= 0)
1349 && get_attr_skip (ninsn) == SKIP_YES)
1351 rtx skip_tgt = next_nonnote_insn (next_real_insn (insn));
1353 /* The first situation is where the target of the jump is one insn
1354 after the jump insn and the insn being jumped is only one machine
1356 if (label == skip_tgt)
1360 /* If our skip target is in fact a code label then we ignore the
1361 label and move onto the next useful instruction. Nothing we do
1362 here has any effect on the use of skipping instructions. */
1363 if (GET_CODE (skip_tgt) == CODE_LABEL)
1364 skip_tgt = next_nonnote_insn (skip_tgt);
1366 /* The second situation is where we have something of the form:
1372 optional_label (this may or may not exist):
1376 In this case we can eliminate the first "page/jump label". */
1377 if (GET_CODE (skip_tgt) == JUMP_INSN)
1379 rtx set = single_set (skip_tgt);
1380 if (GET_CODE (XEXP (set, 0)) == PC
1381 && GET_CODE (XEXP (set, 1)) == LABEL_REF
1382 && label == JUMP_LABEL (skip_tgt))
1388 /* gcc is a little braindead and does some rather stateful things while
1389 inspecting attributes - we have to put this state back to what it's
1391 extract_constrain_insn_cached (insn);
1393 if (ip2k_compare_operands[1] == const0_rtx) /* These are easier. */
1400 OUT_AS2 (sb, %0, 7);
1404 OUT_AS2 (snb, %0, 7);
1414 OUT_AS2 (rl, w, %S0);
1415 OUT_AS2 (mov, w, %S0);
1416 OUT_AS2 (or, w, %T0);
1417 OUT_AS2 (or, w, %U0);
1418 OUT_AS2 (or, w, %V0);
1419 OUT_AS2 (or, w, %W0);
1420 OUT_AS2 (or, w, %X0);
1421 OUT_AS2 (or, w, %Y0);
1422 OUT_AS2 (or, w, %Z0);
1424 OUT_AS2 (setb, status, 0);
1425 OUT_AS2 (sb, status, 0);
1431 OUT_AS2 (rl, w, %A0);
1432 OUT_AS2 (mov, w, %A0);
1433 OUT_AS2 (or, w, %B0);
1434 OUT_AS2 (or, w, %C0);
1435 OUT_AS2 (or, w, %D0);
1437 OUT_AS2 (setb, status, 0);
1438 OUT_AS2 (sb, status, 0);
1444 OUT_AS2 (rl, w, %H0);
1445 OUT_AS2 (mov, w, %H0);
1446 OUT_AS2 (or, w, %L0);
1448 OUT_AS2 (setb, status, 0);
1449 OUT_AS2 (sb, status, 0);
1455 OUT_AS2 (mov, w, %0); /* Will just do "sb w, 7". */
1457 OUT_AS2 (setb, wreg, 7);
1458 OUT_AS2 (sb, wreg, 7);
1472 OUT_AS2 (mov, w, %S0);
1473 OUT_AS2 (or, w, %T0);
1474 OUT_AS2 (or, w, %U0);
1475 OUT_AS2 (or, w, %V0);
1476 OUT_AS2 (or, w, %W0);
1477 OUT_AS2 (or, w, %X0);
1478 OUT_AS2 (or, w, %Y0);
1479 OUT_AS2 (or, w, %Z0); /* Z is correct. */
1481 OUT_AS2 (snb, %S0, 7);
1487 OUT_AS2 (mov, w, %A0);
1488 OUT_AS2 (or, w, %B0);
1489 OUT_AS2 (or, w, %C0);
1490 OUT_AS2 (or, w, %D0); /* Z is correct. */
1492 OUT_AS2 (snb, %A0, 7);
1498 OUT_AS2 (mov, w, %H0);
1499 OUT_AS2 (or, w, %L0);
1501 OUT_AS2 (snb, %H0, 7);
1507 OUT_AS2 (mov, w, %0); /* Will just do "sb w, 7". */
1509 OUT_AS2 (snb, wreg, 7);
1522 OUT_AS2 (snb, %0, 7);
1526 OUT_AS2 (sb, %0, 7);
1538 /* signed compares are out of line because we can't get
1539 the hardware to compute the overflow for us. */
1544 OUT_AS1 (push, %1%<);
1545 OUT_AS1 (push, %0%>);
1546 OUT_AS1 (page, __cmpqi2);
1547 OUT_AS1 (call, __cmpqi2);
1551 OUT_AS1 (push, %L1%<);
1552 OUT_AS1 (push, %H1%<);
1553 OUT_AS1 (push, %L0%<);
1554 OUT_AS1 (push, %H0%>%>%>);
1555 OUT_AS1 (page, __cmphi2);
1556 OUT_AS1 (call, __cmphi2);
1560 OUT_AS1 (push, %D1%<);
1561 OUT_AS1 (push, %C1%<);
1562 OUT_AS1 (push, %B1%<);
1563 OUT_AS1 (push, %A1%<);
1564 OUT_AS1 (push, %D0%<);
1565 OUT_AS1 (push, %C0%<);
1566 OUT_AS1 (push, %B0%<);
1567 OUT_AS1 (push, %A0%>%>%>%>%>%>%>);
1568 OUT_AS1 (page, __cmpsi2);
1569 OUT_AS1 (call, __cmpsi2);
1573 if (GET_CODE (operands[0]) == MEM
1574 && true_regnum (XEXP (operands[0], 0)) == REG_DP)
1576 OUT_AS1 (push, %Z1%<);
1577 OUT_AS1 (push, %Y1%<);
1578 OUT_AS1 (push, %X1%<);
1579 OUT_AS1 (push, %W1%<);
1580 OUT_AS1 (push, %V1%<);
1581 OUT_AS1 (push, %U1%<);
1582 OUT_AS1 (push, %T1%<);
1583 OUT_AS1 (push, %S1%>%>%>%>%>%>%>);
1584 OUT_AS1 (page, __cmpdi2_dp);
1585 OUT_AS1 (call, __cmpdi2_dp);
1589 OUT_AS1 (push, %Z1%<);
1590 OUT_AS1 (push, %Y1%<);
1591 OUT_AS1 (push, %X1%<);
1592 OUT_AS1 (push, %W1%<);
1593 OUT_AS1 (push, %V1%<);
1594 OUT_AS1 (push, %U1%<);
1595 OUT_AS1 (push, %T1%<);
1596 OUT_AS1 (push, %S1%<);
1597 OUT_AS1 (push, %Z0%<);
1598 OUT_AS1 (push, %Y0%<);
1599 OUT_AS1 (push, %X0%<);
1600 OUT_AS1 (push, %W0%<);
1601 OUT_AS1 (push, %V0%<);
1602 OUT_AS1 (push, %U0%<);
1603 OUT_AS1 (push, %T0%<);
1604 OUT_AS1 (push, %S0%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>);
1605 OUT_AS1 (page, __cmpdi2);
1606 OUT_AS1 (call, __cmpdi2);
1619 OUT_AS2 (cse, w, #0);
1623 OUT_AS2 (csne, w, #0);
1632 OUT_AS2 (cse, w, #2);
1636 OUT_AS2 (csne, w, #2);
1645 OUT_AS2 (snb, wreg, 1);
1649 OUT_AS2 (sb, wreg, 1);
1658 OUT_AS2 (csne, w, #0);
1662 OUT_AS2 (cse, w, #0);
1676 ip2k_gen_unsigned_comp_branch (insn, code, label)
1681 #define operands ip2k_compare_operands
1682 enum machine_mode mode;
1685 int can_use_skip = 0;
1688 operands[2] = label;
1690 mode = GET_MODE (operands[0]);
1691 if ((mode != QImode) && (mode != HImode) && (mode != SImode)
1692 && (mode != DImode))
1694 mode = GET_MODE (operands[1]);
1697 /* Look for situations where we can just skip the next instruction instead
1698 of skipping and then branching! */
1699 ninsn = next_real_insn (insn);
1701 && (recog_memoized (ninsn) >= 0)
1702 && get_attr_skip (ninsn) == SKIP_YES)
1704 rtx skip_tgt = next_nonnote_insn (next_real_insn (insn));
1706 /* The first situation is where the target of the jump is one insn
1707 after the jump insn and the insn being jumped is only one machine
1709 if (label == skip_tgt)
1713 /* If our skip target is in fact a code label then we ignore the
1714 label and move onto the next useful instruction. Nothing we do
1715 here has any effect on the use of skipping instructions. */
1716 if (GET_CODE (skip_tgt) == CODE_LABEL)
1717 skip_tgt = next_nonnote_insn (skip_tgt);
1719 /* The second situation is where we have something of the form:
1725 optional_label (this may or may not exist):
1729 In this case we can eliminate the first "page/jump label". */
1730 if (GET_CODE (skip_tgt) == JUMP_INSN)
1732 rtx set = single_set (skip_tgt);
1733 if (GET_CODE (XEXP (set, 0)) == PC
1734 && GET_CODE (XEXP (set, 1)) == LABEL_REF
1735 && label == JUMP_LABEL (skip_tgt))
1741 /* gcc is a little braindead and does some rather stateful things while
1742 inspecting attributes - we have to put this state back to what it's
1744 extract_constrain_insn_cached (insn);
1746 if (ip2k_compare_operands[1] == const0_rtx)
1751 code = EQ; /* Nothing is LTU 0. */
1755 code = NE; /* Anything non-zero is GTU. */
1759 case NE: /* Test all the bits, result in
1765 OUT_AS2 (mov, w, %S0);
1766 OUT_AS2 (or, w, %T0);
1767 OUT_AS2 (or, w, %U0);
1768 OUT_AS2 (or, w, %V0);
1769 OUT_AS2 (or, w, %W0);
1770 OUT_AS2 (or, w, %X0);
1771 OUT_AS2 (or, w, %Y0);
1772 OUT_AS2 (or, w, %Z0);
1776 OUT_AS2 (mov, w, %A0);
1777 OUT_AS2 (or, w, %B0);
1778 OUT_AS2 (or, w, %C0);
1779 OUT_AS2 (or, w, %D0);
1783 OUT_AS2 (mov, w, %H0);
1784 OUT_AS2 (or, w, %L0);
1788 OUT_AS2 (mov, w, %0);
1814 /* Always succeed. */
1829 /* Look at whether we have a constant as one of our operands. If we do
1830 and it's in the position that we use to subtract from during our
1831 normal optimized comparison concept then we have to shuffle things
1835 if ((immediate_operand (operands[1], GET_MODE (operands[1]))
1836 && ((code == LEU) || (code == GTU)))
1837 || (immediate_operand (operands[0], GET_MODE (operands[0]))
1838 && ((code == LTU) || (code == GEU))))
1844 /* Same as above - look if we have a constant that we can compare
1845 for equality or non-equality. If we know this then we can look
1846 for common value eliminations. Note that we want to ensure that
1847 any immediate value is operand 1 to simplify the code later! */
1848 if ((code == EQ) || (code == NE))
1850 imm_cmp = immediate_operand (operands[1], GET_MODE (operands[1]));
1853 imm_cmp = immediate_operand (operands[0], GET_MODE (operands[0]));
1856 rtx tmp = operands[1];
1857 operands[1] = operands[0];
1869 if (imm_cmp && ((INTVAL (operands[1]) & 0xff) == 0xff))
1870 OUT_AS2 (incsnz, w, %0);
1871 else if (imm_cmp && ((INTVAL (operands[1]) & 0xff) == 0x01))
1872 OUT_AS2 (decsnz, w, %0);
1875 OUT_AS2 (mov, w, %1);
1876 OUT_AS2 (csne, w, %0);
1883 if (imm_cmp && ((INTVAL (operands[1]) & 0xff) == 0xff))
1884 OUT_AS2 (incsz, w, %0);
1885 else if (imm_cmp && ((INTVAL (operands[1]) & 0xff) == 0x01))
1886 OUT_AS2 (decsz, w, %0);
1889 OUT_AS2 (mov, w, %1);
1890 OUT_AS2 (cse, w, %0);
1897 OUT_AS2 (mov, w, %0);
1898 OUT_AS2 (cmp, w, %1);
1905 OUT_AS2 (mov, w, %1);
1906 OUT_AS2 (cmp, w, %0);
1913 OUT_AS2 (mov, w, %1);
1914 OUT_AS2 (cmp, w, %0);
1921 OUT_AS2 (mov, w, %0);
1922 OUT_AS2 (cmp, w, %1);
1938 unsigned char h = 0, l = 1;
1942 h = (INTVAL (operands[1]) >> 8) & 0xff;
1943 l = INTVAL (operands[1]) & 0xff;
1945 if ((h == 0xff) && (l == 0xff))
1947 /* We should be able to do the following, but the
1948 IP2k simulator doesn't like it and we get a load
1949 of failures in gcc-c-torture. */
1950 OUT_AS2 (incsnz, w, %L0);
1951 OUT_AS2 (incsz, w, %H0);
1952 /* OUT_AS1 (skip,); Should have this */
1953 OUT_AS1 (page, 1f);/* Shouldn't need this! */
1954 OUT_AS1 (jmp, 1f); /* Shouldn't need this either. */
1963 OUT_AS2 (dec, w, %L0);
1966 OUT_AS2 (mov, w, %L0);
1967 OUT_AS2 (sub, w, %L1);
1969 OUT_AS2 (or, w, %H0);
1978 OUT_AS2 (dec, w, %H0);
1981 OUT_AS2 (mov, w, %H0);
1982 OUT_AS2 (sub, w, %H1);
1984 OUT_AS2 (or, w, %L0);
1992 OUT_AS2 (mov, w, %H1);
1993 OUT_AS2 (cse, w, %H0);
1996 if (! imm_cmp || (h != l))
1997 OUT_AS2 (mov, w, %L1);
1998 OUT_AS2 (csne, w, %L0);
2007 unsigned char h = 0, l = 1;
2011 h = (INTVAL (operands[1]) >> 8) & 0xff;
2012 l = INTVAL (operands[1]) & 0xff;
2014 if ((h == 0xff) && (l == 0xff))
2016 OUT_AS2 (incsnz, w, %L0);
2017 OUT_AS2 (incsz, w, %H0);
2025 OUT_AS2 (dec, w, %L0);
2028 OUT_AS2 (mov, w, %L0);
2029 OUT_AS2 (sub, w, %L1);
2031 OUT_AS2 (or, w, %H0);
2040 OUT_AS2 (dec, w, %H0);
2043 OUT_AS2 (mov, w, %H0);
2044 OUT_AS2 (sub, w, %H1);
2046 OUT_AS2 (or, w, %L0);
2054 OUT_AS2 (mov, w, %H1);
2055 if (imm_cmp && (h == l))
2057 OUT_AS2 (csne, w, %H0);
2058 OUT_AS2 (cse, w, %L0);
2062 OUT_AS2 (cse, w, %H0);
2065 OUT_AS2 (mov, w, %L1);
2066 OUT_AS2 (cse, w, %L0);
2076 /* > 0xffff never suceeds! */
2077 if ((INTVAL (operands[1]) & 0xffff) != 0xffff)
2079 operands[3] = GEN_INT (INTVAL (operands[1]) + 1);
2080 OUT_AS2 (mov, w, %L3);
2081 OUT_AS2 (sub, w, %L0);
2082 OUT_AS2 (mov, w, %H3);
2083 OUT_AS2 (subc, w, %H0);
2091 OUT_AS2 (mov, w, %L0);
2092 OUT_AS2 (sub, w, %L1);
2093 OUT_AS2 (mov, w, %H0);
2094 OUT_AS2 (subc, w, %H1);
2104 if (INTVAL (operands[0]) == 0)
2106 OUT_AS2 (mov, w, %H1);
2107 OUT_AS2 (or, w, %L1);
2114 operands[3] = GEN_INT (INTVAL (operands[0]) - 1);
2115 OUT_AS2 (mov, w, %L3);
2116 OUT_AS2 (sub, w, %L1);
2117 OUT_AS2 (mov, w, %H3);
2118 OUT_AS2 (subc, w, %H1);
2126 OUT_AS2 (mov, w, %L1);
2127 OUT_AS2 (sub, w, %L0);
2128 OUT_AS2 (mov, w, %H1);
2129 OUT_AS2 (subc, w, %H0);
2139 if (INTVAL (operands[0]) == 0)
2141 OUT_AS2 (mov, w, %H1);
2142 OUT_AS2 (or, w, %L1);
2149 operands[3] = GEN_INT (INTVAL (operands[0]) - 1);
2150 OUT_AS2 (mov, w, %L3);
2151 OUT_AS2 (sub, w, %L1);
2152 OUT_AS2 (mov, w, %H3);
2153 OUT_AS2 (subc, w, %H1);
2161 OUT_AS2 (mov, w, %L1);
2162 OUT_AS2 (sub, w, %L0);
2163 OUT_AS2 (mov, w, %H1);
2164 OUT_AS2 (subc, w, %H0);
2174 if ((INTVAL (operands[1]) & 0xffff) == 0xffff)
2176 /* <= 0xffff always suceeds. */
2182 operands[3] = GEN_INT (INTVAL (operands[1]) + 1);
2183 OUT_AS2 (mov, w, %L3);
2184 OUT_AS2 (sub, w, %L0);
2185 OUT_AS2 (mov, w, %H3);
2186 OUT_AS2 (subc, w, %H0);
2194 OUT_AS2 (mov, w, %L0);
2195 OUT_AS2 (sub, w, %L1);
2196 OUT_AS2 (mov, w, %H0);
2197 OUT_AS2 (subc, w, %H1);
2214 unsigned char a = 0, b = 1, c = 2, d = 3;
2218 a = (INTVAL (operands[1]) >> 24) & 0xff;
2219 b = (INTVAL (operands[1]) >> 16) & 0xff;
2220 c = (INTVAL (operands[1]) >> 8) & 0xff;
2221 d = INTVAL (operands[1]) & 0xff;
2224 OUT_AS2 (mov, w, %A1);
2225 if (imm_cmp && (b == a))
2227 OUT_AS2 (csne, w, %A0);
2228 OUT_AS2 (cse, w, %B0);
2232 OUT_AS2 (cse, w, %A0);
2235 OUT_AS2 (mov, w, %B1);
2236 OUT_AS2 (cse, w, %B0);
2240 if (! imm_cmp || (c != b))
2241 OUT_AS2 (mov, w, %C1);
2242 OUT_AS2 (cse, w, %C0);
2245 if (! imm_cmp || (d != c))
2246 OUT_AS2 (mov, w, %D1);
2247 OUT_AS2 (csne, w, %D0);
2256 unsigned char a = 0, b = 1, c = 2, d = 3;
2260 a = (INTVAL (operands[1]) >> 24) & 0xff;
2261 b = (INTVAL (operands[1]) >> 16) & 0xff;
2262 c = (INTVAL (operands[1]) >> 8) & 0xff;
2263 d = INTVAL (operands[1]) & 0xff;
2266 OUT_AS2 (mov, w, %A1);
2267 if (imm_cmp && (b == a))
2269 OUT_AS2 (csne, w, %A0);
2270 OUT_AS2 (cse, w, %B0);
2274 OUT_AS2 (cse, w, %A0);
2277 OUT_AS2 (mov, w, %B1);
2278 OUT_AS2 (cse, w, %B0);
2282 if (! imm_cmp || (c != b))
2283 OUT_AS2 (mov, w, %C1);
2284 if (imm_cmp && (d == c))
2286 OUT_AS2 (csne, w, %C0);
2287 OUT_AS2 (cse, w, %D0);
2291 OUT_AS2 (cse, w, %C0);
2294 OUT_AS2 (mov, w, %D1);
2295 OUT_AS2 (cse, w, %D0);
2305 /* > 0xffffffff never suceeds! */
2306 if ((unsigned HOST_WIDE_INT)(INTVAL (operands[1]) & 0xffffffff)
2309 operands[3] = GEN_INT (INTVAL (operands[1]) + 1);
2310 OUT_AS2 (mov, w, %D3);
2311 OUT_AS2 (sub, w, %D0);
2312 OUT_AS2 (mov, w, %C3);
2313 OUT_AS2 (subc, w, %C0);
2314 OUT_AS2 (mov, w, %B3);
2315 OUT_AS2 (subc, w, %B0);
2316 OUT_AS2 (mov, w, %A3);
2317 OUT_AS2 (subc, w, %A0);
2325 OUT_AS2 (mov, w, %D0);
2326 OUT_AS2 (sub, w, %D1);
2327 OUT_AS2 (mov, w, %C0);
2328 OUT_AS2 (subc, w, %C1);
2329 OUT_AS2 (mov, w, %B0);
2330 OUT_AS2 (subc, w, %B1);
2331 OUT_AS2 (mov, w, %A0);
2332 OUT_AS2 (subc, w, %A1);
2342 if (INTVAL (operands[0]) == 0)
2344 OUT_AS2 (mov, w, %A0);
2345 OUT_AS2 (or, w, %B0);
2346 OUT_AS2 (or, w, %C0);
2347 OUT_AS2 (or, w, %D0);
2354 operands[3] = GEN_INT (INTVAL (operands[0]) - 1);
2355 OUT_AS2 (mov, w, %D3);
2356 OUT_AS2 (sub, w, %D1);
2357 OUT_AS2 (mov, w, %C3);
2358 OUT_AS2 (subc, w, %C1);
2359 OUT_AS2 (mov, w, %B3);
2360 OUT_AS2 (subc, w, %B1);
2361 OUT_AS2 (mov, w, %A3);
2362 OUT_AS2 (subc, w, %A1);
2370 OUT_AS2 (mov, w, %D1);
2371 OUT_AS2 (sub, w, %D0);
2372 OUT_AS2 (mov, w, %C1);
2373 OUT_AS2 (subc, w, %C0);
2374 OUT_AS2 (mov, w, %B1);
2375 OUT_AS2 (subc, w, %B0);
2376 OUT_AS2 (mov, w, %A1);
2377 OUT_AS2 (subc, w, %A0);
2387 if (INTVAL (operands[0]) == 0)
2389 OUT_AS2 (mov, w, %A0);
2390 OUT_AS2 (or, w, %B0);
2391 OUT_AS2 (or, w, %C0);
2392 OUT_AS2 (or, w, %D0);
2399 operands[3] = GEN_INT (INTVAL (operands[0]) - 1);
2400 OUT_AS2 (mov, w, %D3);
2401 OUT_AS2 (sub, w, %D1);
2402 OUT_AS2 (mov, w, %C3);
2403 OUT_AS2 (subc, w, %C1);
2404 OUT_AS2 (mov, w, %B3);
2405 OUT_AS2 (subc, w, %B1);
2406 OUT_AS2 (mov, w, %A3);
2407 OUT_AS2 (subc, w, %A1);
2415 OUT_AS2 (mov, w, %D1);
2416 OUT_AS2 (sub, w, %D0);
2417 OUT_AS2 (mov, w, %C1);
2418 OUT_AS2 (subc, w, %C0);
2419 OUT_AS2 (mov, w, %B1);
2420 OUT_AS2 (subc, w, %B0);
2421 OUT_AS2 (mov, w, %A1);
2422 OUT_AS2 (subc, w, %A0);
2432 if ((unsigned HOST_WIDE_INT)(INTVAL (operands[1]) & 0xffffffff)
2435 /* <= 0xffffffff always suceeds. */
2441 operands[3] = GEN_INT (INTVAL (operands[1]) + 1);
2442 OUT_AS2 (mov, w, %D3);
2443 OUT_AS2 (sub, w, %D0);
2444 OUT_AS2 (mov, w, %C3);
2445 OUT_AS2 (subc, w, %C0);
2446 OUT_AS2 (mov, w, %B3);
2447 OUT_AS2 (subc, w, %B0);
2448 OUT_AS2 (mov, w, %A3);
2449 OUT_AS2 (subc, w, %A0);
2457 OUT_AS2 (mov, w, %D0);
2458 OUT_AS2 (sub, w, %D1);
2459 OUT_AS2 (mov, w, %C0);
2460 OUT_AS2 (subc, w, %C1);
2461 OUT_AS2 (mov, w, %B0);
2462 OUT_AS2 (subc, w, %B1);
2463 OUT_AS2 (mov, w, %A0);
2464 OUT_AS2 (subc, w, %A1);
2481 unsigned char s = 0, t = 1, u = 2, v = 3;
2482 unsigned char w = 4, x = 5, y = 6, z = 7;
2485 if (GET_CODE (operands[0]) == MEM
2486 && true_regnum (XEXP (operands[0], 0)) == REG_DP)
2488 OUT_AS1 (push, %Z1%<);
2489 OUT_AS1 (push, %Y1%<);
2490 OUT_AS1 (push, %X1%<);
2491 OUT_AS1 (push, %W1%<);
2492 OUT_AS1 (push, %V1%<);
2493 OUT_AS1 (push, %U1%<);
2494 OUT_AS1 (push, %T1%<);
2495 OUT_AS1 (push, %S1%>%>%>%>%>%>%>);
2496 OUT_AS1 (page, __cmpdi2_dp);
2497 OUT_AS1 (call, __cmpdi2_dp);
2498 OUT_AS2 (csne, w, #1);
2504 OUT_AS1 (push, %Z1%<);
2505 OUT_AS1 (push, %Y1%<);
2506 OUT_AS1 (push, %X1%<);
2507 OUT_AS1 (push, %W1%<);
2508 OUT_AS1 (push, %V1%<);
2509 OUT_AS1 (push, %U1%<);
2510 OUT_AS1 (push, %T1%<);
2511 OUT_AS1 (push, %S1%<);
2512 OUT_AS1 (push, %Z0%<);
2513 OUT_AS1 (push, %Y0%<);
2514 OUT_AS1 (push, %X0%<);
2515 OUT_AS1 (push, %W0%<);
2516 OUT_AS1 (push, %V0%<);
2517 OUT_AS1 (push, %U0%<);
2518 OUT_AS1 (push, %T0%<);
2519 OUT_AS1 (push, %S0%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>);
2520 OUT_AS1 (page, __cmpdi2);
2521 OUT_AS1 (call, __cmpdi2);
2522 OUT_AS2 (csne, w, #1);
2531 s = (CONST_DOUBLE_HIGH (operands[1]) >> 24) & 0xff;
2532 t = (CONST_DOUBLE_HIGH (operands[1]) >> 16) & 0xff;
2533 u = (CONST_DOUBLE_HIGH (operands[1]) >> 8) & 0xff;
2534 v = CONST_DOUBLE_HIGH (operands[1]) & 0xff;
2535 w = (CONST_DOUBLE_LOW (operands[1]) >> 24) & 0xff;
2536 x = (CONST_DOUBLE_LOW (operands[1]) >> 16) & 0xff;
2537 y = (CONST_DOUBLE_LOW (operands[1]) >> 8) & 0xff;
2538 z = CONST_DOUBLE_LOW (operands[1]) & 0xff;
2541 OUT_AS2 (mov, w, %S1);
2542 if (imm_cmp && (s == t))
2544 OUT_AS2 (csne, w, %S0);
2545 OUT_AS2 (cse, w, %T0);
2549 OUT_AS2 (cse, w, %S0);
2552 OUT_AS2 (mov, w, %T1);
2553 OUT_AS2 (cse, w, %T0);
2558 OUT_AS2 (mov, w, %U1);
2559 if (imm_cmp && (u == v))
2561 OUT_AS2 (csne, w, %U0);
2562 OUT_AS2 (cse, w, %V0);
2566 OUT_AS2 (cse, w, %U0);
2569 OUT_AS2 (mov, w, %V1);
2570 OUT_AS2 (cse, w, %V0);
2575 OUT_AS2 (mov, w, %W1);
2576 if (imm_cmp && (w == x))
2578 OUT_AS2 (csne, w, %W0);
2579 OUT_AS2 (cse, w, %X0);
2583 OUT_AS2 (cse, w, %W0);
2586 OUT_AS2 (mov, w, %X1);
2587 OUT_AS2 (cse, w, %X0);
2592 if (! imm_cmp || (x != y))
2593 OUT_AS2 (mov, w, %Y1);
2594 OUT_AS2 (cse, w, %Y0);
2597 if (! imm_cmp || (z != y))
2598 OUT_AS2 (mov, w, %Z1);
2599 OUT_AS2 (csne, w, %Z0);
2609 unsigned char s = 0, t = 1, u = 2, v = 3;
2610 unsigned char w = 4, x = 5, y = 6, z = 7;
2614 if (GET_CODE (operands[0]) == MEM
2615 && true_regnum (XEXP (operands[0], 0)) == REG_DP)
2617 OUT_AS1 (push, %Z1%<);
2618 OUT_AS1 (push, %Y1%<);
2619 OUT_AS1 (push, %X1%<);
2620 OUT_AS1 (push, %W1%<);
2621 OUT_AS1 (push, %V1%<);
2622 OUT_AS1 (push, %U1%<);
2623 OUT_AS1 (push, %T1%<);
2624 OUT_AS1 (push, %S1%>%>%>%>%>%>%>);
2625 OUT_AS1 (page, __cmpdi2_dp);
2626 OUT_AS1 (call, __cmpdi2_dp);
2627 OUT_AS2 (cse, w, #1);
2633 OUT_AS1 (push, %Z1%<);
2634 OUT_AS1 (push, %Y1%<);
2635 OUT_AS1 (push, %X1%<);
2636 OUT_AS1 (push, %W1%<);
2637 OUT_AS1 (push, %V1%<);
2638 OUT_AS1 (push, %U1%<);
2639 OUT_AS1 (push, %T1%<);
2640 OUT_AS1 (push, %S1%<);
2641 OUT_AS1 (push, %Z0%<);
2642 OUT_AS1 (push, %Y0%<);
2643 OUT_AS1 (push, %X0%<);
2644 OUT_AS1 (push, %W0%<);
2645 OUT_AS1 (push, %V0%<);
2646 OUT_AS1 (push, %U0%<);
2647 OUT_AS1 (push, %T0%<);
2648 OUT_AS1 (push, %S0%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>);
2649 OUT_AS1 (page, __cmpdi2);
2650 OUT_AS1 (call, __cmpdi2);
2651 OUT_AS2 (cse, w, #1);
2660 s = (CONST_DOUBLE_HIGH (operands[1]) >> 24) & 0xff;
2661 t = (CONST_DOUBLE_HIGH (operands[1]) >> 16) & 0xff;
2662 u = (CONST_DOUBLE_HIGH (operands[1]) >> 8) & 0xff;
2663 v = CONST_DOUBLE_HIGH (operands[1]) & 0xff;
2664 w = (CONST_DOUBLE_LOW (operands[1]) >> 24) & 0xff;
2665 x = (CONST_DOUBLE_LOW (operands[1]) >> 16) & 0xff;
2666 y = (CONST_DOUBLE_LOW (operands[1]) >> 8) & 0xff;
2667 z = CONST_DOUBLE_LOW (operands[1]) & 0xff;
2670 OUT_AS2 (mov, w, %S1);
2671 if (imm_cmp && (s == t))
2673 OUT_AS2 (csne, w, %S0);
2674 OUT_AS2 (cse, w, %T0);
2678 OUT_AS2 (cse, w, %S0);
2681 OUT_AS2 (mov, w, %T1);
2682 OUT_AS2 (cse, w, %T0);
2687 OUT_AS2 (mov, w, %U1);
2688 if (imm_cmp && (u == v))
2690 OUT_AS2 (csne, w, %U0);
2691 OUT_AS2 (cse, w, %V0);
2695 OUT_AS2 (cse, w, %U0);
2698 OUT_AS2 (mov, w, %V1);
2699 OUT_AS2 (cse, w, %V0);
2704 OUT_AS2 (mov, w, %W1);
2705 if (imm_cmp && (w == x))
2707 OUT_AS2 (csne, w, %W0);
2708 OUT_AS2 (cse, w, %X0);
2712 OUT_AS2 (cse, w, %W0);
2715 OUT_AS2 (mov, w, %X1);
2716 OUT_AS2 (cse, w, %X0);
2721 if (! imm_cmp || (y != x))
2722 OUT_AS2 (mov, w, %Y1);
2723 if (imm_cmp && (z == y))
2725 OUT_AS2 (csne, w, %Y0);
2726 OUT_AS2 (cse, w, %Z0);
2730 OUT_AS2 (cse, w, %Y0);
2733 OUT_AS2 (mov, w, %Z1);
2734 OUT_AS2 (cse, w, %Z0);
2745 /* > 0xffffffffffffffff never suceeds! */
2746 if (((CONST_DOUBLE_HIGH (operands[1]) & 0xffffffff)
2748 || ((CONST_DOUBLE_LOW (operands[1]) & 0xffffffff)
2751 operands[3] = GEN_INT (CONST_DOUBLE_LOW (operands[1]) + 1);
2752 operands[4] = GEN_INT (CONST_DOUBLE_HIGH (operands[1])
2753 + (INTVAL (operands[3]) ? 0 : 1));
2754 OUT_AS2 (mov, w, %D3);
2755 OUT_AS2 (sub, w, %Z0);
2756 OUT_AS2 (mov, w, %C3);
2757 OUT_AS2 (subc, w, %Y0);
2758 OUT_AS2 (mov, w, %B3);
2759 OUT_AS2 (subc, w, %X0);
2760 OUT_AS2 (mov, w, %A3);
2761 OUT_AS2 (subc, w, %W0);
2762 OUT_AS2 (mov, w, %D4);
2763 OUT_AS2 (subc, w, %V0);
2764 OUT_AS2 (mov, w, %C4);
2765 OUT_AS2 (subc, w, %U0);
2766 OUT_AS2 (mov, w, %B4);
2767 OUT_AS2 (subc, w, %T0);
2768 OUT_AS2 (mov, w, %A4);
2769 OUT_AS2 (subc, w, %S0);
2777 OUT_AS2 (mov, w, %Z0);
2778 OUT_AS2 (sub, w, %Z1);
2779 OUT_AS2 (mov, w, %Y0);
2780 OUT_AS2 (subc, w, %Y1);
2781 OUT_AS2 (mov, w, %X0);
2782 OUT_AS2 (subc, w, %X1);
2783 OUT_AS2 (mov, w, %W0);
2784 OUT_AS2 (subc, w, %W1);
2785 OUT_AS2 (mov, w, %V0);
2786 OUT_AS2 (subc, w, %V1);
2787 OUT_AS2 (mov, w, %U0);
2788 OUT_AS2 (subc, w, %U1);
2789 OUT_AS2 (mov, w, %T0);
2790 OUT_AS2 (subc, w, %T1);
2791 OUT_AS2 (mov, w, %S0);
2792 OUT_AS2 (subc, w, %S1);
2802 if ((CONST_DOUBLE_HIGH (operands[0]) == 0)
2803 && (CONST_DOUBLE_LOW (operands[0]) == 0))
2805 OUT_AS2 (mov, w, %S0);
2806 OUT_AS2 (or, w, %T0);
2807 OUT_AS2 (or, w, %U0);
2808 OUT_AS2 (or, w, %V0);
2809 OUT_AS2 (or, w, %W0);
2810 OUT_AS2 (or, w, %X0);
2811 OUT_AS2 (or, w, %Y0);
2812 OUT_AS2 (or, w, %Z0);
2819 operands[3] = GEN_INT (CONST_DOUBLE_LOW (operands[0]) - 1);
2820 operands[4] = GEN_INT (CONST_DOUBLE_HIGH (operands[0])
2821 - (CONST_DOUBLE_LOW (operands[0])
2823 OUT_AS2 (mov, w, %D3);
2824 OUT_AS2 (sub, w, %Z1);
2825 OUT_AS2 (mov, w, %C3);
2826 OUT_AS2 (subc, w, %Y1);
2827 OUT_AS2 (mov, w, %B3);
2828 OUT_AS2 (subc, w, %X1);
2829 OUT_AS2 (mov, w, %A3);
2830 OUT_AS2 (subc, w, %W1);
2831 OUT_AS2 (mov, w, %D4);
2832 OUT_AS2 (subc, w, %V1);
2833 OUT_AS2 (mov, w, %C4);
2834 OUT_AS2 (subc, w, %U1);
2835 OUT_AS2 (mov, w, %B4);
2836 OUT_AS2 (subc, w, %T1);
2837 OUT_AS2 (mov, w, %A4);
2838 OUT_AS2 (subc, w, %S1);
2846 OUT_AS2 (mov, w, %Z1);
2847 OUT_AS2 (sub, w, %Z0);
2848 OUT_AS2 (mov, w, %Y1);
2849 OUT_AS2 (subc, w, %Y0);
2850 OUT_AS2 (mov, w, %X1);
2851 OUT_AS2 (subc, w, %X0);
2852 OUT_AS2 (mov, w, %W1);
2853 OUT_AS2 (subc, w, %W0);
2854 OUT_AS2 (mov, w, %V1);
2855 OUT_AS2 (subc, w, %V0);
2856 OUT_AS2 (mov, w, %U1);
2857 OUT_AS2 (subc, w, %U0);
2858 OUT_AS2 (mov, w, %T1);
2859 OUT_AS2 (subc, w, %T0);
2860 OUT_AS2 (mov, w, %S1);
2861 OUT_AS2 (subc, w, %S0);
2871 if ((CONST_DOUBLE_HIGH (operands[0]) == 0)
2872 && (CONST_DOUBLE_LOW (operands[0]) == 0))
2874 OUT_AS2 (mov, w, %S0);
2875 OUT_AS2 (or, w, %T0);
2876 OUT_AS2 (or, w, %U0);
2877 OUT_AS2 (or, w, %V0);
2878 OUT_AS2 (or, w, %W0);
2879 OUT_AS2 (or, w, %X0);
2880 OUT_AS2 (or, w, %Y0);
2881 OUT_AS2 (or, w, %Z0);
2888 operands[3] = GEN_INT (CONST_DOUBLE_LOW (operands[0]) - 1);
2889 operands[4] = GEN_INT (CONST_DOUBLE_HIGH (operands[0])
2890 - (CONST_DOUBLE_LOW (operands[0])
2892 OUT_AS2 (mov, w, %D3);
2893 OUT_AS2 (sub, w, %Z1);
2894 OUT_AS2 (mov, w, %C3);
2895 OUT_AS2 (subc, w, %Y1);
2896 OUT_AS2 (mov, w, %B3);
2897 OUT_AS2 (subc, w, %X1);
2898 OUT_AS2 (mov, w, %A3);
2899 OUT_AS2 (subc, w, %W1);
2900 OUT_AS2 (mov, w, %D4);
2901 OUT_AS2 (subc, w, %V1);
2902 OUT_AS2 (mov, w, %C4);
2903 OUT_AS2 (subc, w, %U1);
2904 OUT_AS2 (mov, w, %B4);
2905 OUT_AS2 (subc, w, %T1);
2906 OUT_AS2 (mov, w, %A4);
2907 OUT_AS2 (subc, w, %S1);
2915 OUT_AS2 (mov, w, %Z1);
2916 OUT_AS2 (sub, w, %Z0);
2917 OUT_AS2 (mov, w, %Y1);
2918 OUT_AS2 (subc, w, %Y0);
2919 OUT_AS2 (mov, w, %X1);
2920 OUT_AS2 (subc, w, %X0);
2921 OUT_AS2 (mov, w, %W1);
2922 OUT_AS2 (subc, w, %W0);
2923 OUT_AS2 (mov, w, %V1);
2924 OUT_AS2 (subc, w, %V0);
2925 OUT_AS2 (mov, w, %U1);
2926 OUT_AS2 (subc, w, %U0);
2927 OUT_AS2 (mov, w, %T1);
2928 OUT_AS2 (subc, w, %T0);
2929 OUT_AS2 (mov, w, %S1);
2930 OUT_AS2 (subc, w, %S0);
2940 if (((CONST_DOUBLE_HIGH (operands[1]) & 0xffffffff)
2942 && ((CONST_DOUBLE_LOW (operands[1]) & 0xffffffff)
2945 /* <= 0xffffffffffffffff always suceeds. */
2951 operands[3] = GEN_INT (CONST_DOUBLE_LOW (operands[1]) + 1);
2952 operands[4] = GEN_INT (CONST_DOUBLE_HIGH (operands[1])
2953 + (INTVAL (operands[3]) ? 0 : 1));
2954 OUT_AS2 (mov, w, %D3);
2955 OUT_AS2 (sub, w, %Z0);
2956 OUT_AS2 (mov, w, %C3);
2957 OUT_AS2 (subc, w, %Y0);
2958 OUT_AS2 (mov, w, %B3);
2959 OUT_AS2 (subc, w, %X0);
2960 OUT_AS2 (mov, w, %A3);
2961 OUT_AS2 (subc, w, %W0);
2962 OUT_AS2 (mov, w, %D4);
2963 OUT_AS2 (subc, w, %V0);
2964 OUT_AS2 (mov, w, %C4);
2965 OUT_AS2 (subc, w, %U0);
2966 OUT_AS2 (mov, w, %B4);
2967 OUT_AS2 (subc, w, %T0);
2968 OUT_AS2 (mov, w, %A4);
2969 OUT_AS2 (subc, w, %S0);
2977 OUT_AS2 (mov, w, %Z0);
2978 OUT_AS2 (sub, w, %Z1);
2979 OUT_AS2 (mov, w, %Y0);
2980 OUT_AS2 (subc, w, %Y1);
2981 OUT_AS2 (mov, w, %X0);
2982 OUT_AS2 (subc, w, %X1);
2983 OUT_AS2 (mov, w, %W0);
2984 OUT_AS2 (subc, w, %W1);
2985 OUT_AS2 (mov, w, %V0);
2986 OUT_AS2 (subc, w, %V1);
2987 OUT_AS2 (mov, w, %U0);
2988 OUT_AS2 (subc, w, %U1);
2989 OUT_AS2 (mov, w, %T0);
2990 OUT_AS2 (subc, w, %T1);
2991 OUT_AS2 (mov, w, %S0);
2992 OUT_AS2 (subc, w, %S1);
3011 /* Output rtx VALUE as .byte to file FILE. */
3014 asm_output_char(file, value)
3018 fprintf (file, "\t.byte ");
3019 output_addr_const (file, value);
3020 fprintf (file, "\n");
3024 /* Output VALUE as .byte to file FILE. */
3027 asm_output_byte (file,value)
3031 fprintf (file, "\t.byte 0x%x\n",value & 0xff);
3035 /* Output rtx VALUE as .word to file FILE. */
3038 asm_output_short (file, value)
3042 fprintf (file, "\t.word ");
3043 output_addr_const (file, (value));
3044 fprintf (file, "\n");
3048 /* Output real N to file FILE. */
3051 asm_output_float (file, n)
3058 REAL_VALUE_TO_TARGET_SINGLE (n, val);
3059 REAL_VALUE_TO_DECIMAL (n, "%g", dstr);
3060 fprintf (file, "\t.long 0x%08lx\t/* %s */\n",val, dstr);
3063 /* Sets section name for declaration DECL. */
3066 unique_section (decl, reloc)
3068 int reloc ATTRIBUTE_UNUSED;
3074 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
3075 /* Strip off any encoding in name. */
3076 name = (* targetm.strip_name_encoding) (name);
3078 if (TREE_CODE (decl) == FUNCTION_DECL)
3080 if (flag_function_sections)
3088 if (flag_function_sections)
3090 len = strlen (name) + strlen (prefix);
3091 string = alloca (len + 1);
3092 sprintf (string, "%s%s", prefix, name);
3093 DECL_SECTION_NAME (decl) = build_string (len, string);
3098 /* Output section name to file FILE. */
3101 asm_output_section_name(file, decl, name, reloc)
3103 tree decl ATTRIBUTE_UNUSED;
3105 int reloc ATTRIBUTE_UNUSED;
3107 fprintf (file, ".section %s\n", name);
3110 /* Return value is nonzero if pseudos that have been
3111 assigned to registers of class CLASS would likely be spilled
3112 because registers of CLASS are needed for spill registers. */
3115 class_likely_spilled_p(c)
3118 return (c == IP_REGS
3129 /* Only `progmem' attribute valid for type. */
3132 valid_machine_type_attribute(type, attributes, identifier, args)
3133 tree type ATTRIBUTE_UNUSED;
3134 tree attributes ATTRIBUTE_UNUSED;
3136 tree args ATTRIBUTE_UNUSED;
3138 return is_attribute_p ("progmem", identifier);
3141 /* If IDENTIFIER with arguments ARGS is a valid machine specific
3142 attribute for DECL return 1.
3144 progmem - put data to program memory;
3145 naked - don't generate function prologue/epilogue and `ret' command. */
3148 valid_machine_decl_attribute (decl, attributes, attr, args)
3150 tree attributes ATTRIBUTE_UNUSED;
3152 tree args ATTRIBUTE_UNUSED;
3154 if (is_attribute_p ("naked", attr))
3155 return TREE_CODE (decl) == FUNCTION_DECL;
3157 if (is_attribute_p ("progmem", attr)
3158 && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
3160 /* Data stored in program RAM or FLASH must be word aligned or
3161 it won't be directly addressable. */
3162 if (DECL_ALIGN (decl) < FUNCTION_BOUNDARY)
3163 DECL_ALIGN (decl) = FUNCTION_BOUNDARY;
3165 if (DECL_INITIAL (decl) == NULL_TREE)
3167 warning ("Only initialized variables can be placed into "
3168 "program memory area.");
3176 /* Encode section information about tree DECL. */
3179 encode_section_info (decl)
3182 if (! DECL_P (decl))
3185 if (TREE_CODE (decl) == FUNCTION_DECL)
3186 SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
3189 /* Outputs to the stdio stream FILE some
3190 appropriate text to go at the start of an assembler file. */
3193 asm_file_start (file)
3196 output_file_directive (file, main_input_filename);
3198 commands_in_file = 0;
3199 commands_in_prologues = 0;
3200 commands_in_epilogues = 0;
3203 /* Outputs to the stdio stream FILE some
3204 appropriate text to go at the end of an assembler file. */
3212 "/* File %s: code %4d = 0x%04x (%4d), prologues %3d, epilogues %3d */\n",
3213 main_input_filename,
3216 commands_in_file - commands_in_prologues - commands_in_epilogues,
3217 commands_in_prologues, commands_in_epilogues);
3220 /* Cost functions. */
3222 /* Calculate the cost of X code of the expression in which it is contained,
3223 found in OUTER_CODE. */
3226 default_rtx_costs (x, code, outer_code)
3229 enum rtx_code outer_code;
3231 enum machine_mode mode = GET_MODE (x);
3238 return ip2k_address_cost (XEXP (x, 0));
3245 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
3247 int val = INTVAL (XEXP (x, 1));
3250 /* Shift by const instructions are proportional to
3251 the shift count modulus 8. Note that we increase the mode
3252 size multiplier by 1 to account for clearing the carry flag. */
3253 cost = COSTS_N_INSNS (abs (val) % 8);
3254 cost += rtx_cost (XEXP (x, 0), code);
3255 cost *= (GET_MODE_SIZE (mode) + 1);
3257 /* Sign-preserving shifts require 2 extra instructions. */
3259 cost += COSTS_N_INSNS (2);
3262 total = rtx_cost (XEXP (x, 0), code);
3263 total += COSTS_N_INSNS (GET_MODE_SIZE (mode) * 8);
3271 total = rtx_cost (XEXP (x, 0), code)
3272 + rtx_cost (XEXP (x, 1), code);
3273 total += COSTS_N_INSNS (GET_MODE_SIZE (mode) * 3);
3279 return COSTS_N_INSNS (20);
3281 return COSTS_N_INSNS (60);
3282 else if (mode == SImode)
3283 return COSTS_N_INSNS (180);
3285 return COSTS_N_INSNS (540);
3288 /* These costs are OK, but should really handle subtle cases
3289 where we're using sign or zero extended args as these are
3290 *much* cheaper than those given below! */
3292 return COSTS_N_INSNS (4);
3294 return COSTS_N_INSNS (12);
3296 return COSTS_N_INSNS (36);
3298 return COSTS_N_INSNS (108);
3302 extra_cost = COSTS_N_INSNS (GET_MODE_SIZE (mode));
3308 total = rtx_cost (XEXP (x, 0), code);
3309 return total + extra_cost + COSTS_N_INSNS (GET_MODE_SIZE (mode) * 2);
3313 if (outer_code == SET)
3314 return rtx_cost (XEXP (x, 0), code)
3315 + COSTS_N_INSNS (GET_MODE_SIZE (mode) * 3 / 2);
3317 return -(COSTS_N_INSNS (GET_MODE_SIZE (mode)) / 2);
3320 return rtx_cost (XEXP (x, 0), code)
3321 + COSTS_N_INSNS (2);
3333 return rtx_cost (XEXP (x, 0), code)
3334 + rtx_cost (XEXP (x, 1), code);
3337 return COSTS_N_INSNS (4);
3341 /* Calculate the cost of a memory address. */
3344 ip2k_address_cost (x)
3347 switch (legitimate_address_p (VOIDmode, x, 0))
3349 case 'S': /* Very low cost - (IP), (SP+N) or (DP+N) */
3352 case 'R': /* Indirected through IP. */
3355 case 'L': /* Label references. */
3358 case 'C': /* Constants and symbol references. */
3362 return 1000; /* Must reload. */
3366 /* As part of the machine-dependent reorg we look for opcode sequences where
3367 we do some operation and then move the results back to one of the original
3368 source operands. With working on the source operand directly is probably
3369 much cheaper and the move from this to the original source operand will be
3370 no more expensive than the original move. */
3373 mdr_resequence_xy_yx (first_insn)
3378 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
3382 if (GET_CODE (insn) != INSN)
3385 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
3386 if (set == NULL_RTX)
3389 /* Look for operations that tend to be very cheap to run when the source
3390 * and dest args are the same because the IP2022 has opcodes that can
3391 operate on the source directly. If we have to spill through the W
3392 register then we've possibly not got a good case for doing this. */
3393 if ((GET_CODE (XEXP (set, 0)) == REG
3394 || GET_CODE (XEXP (set, 0)) == MEM)
3395 && (GET_CODE (XEXP (set, 1)) == ASHIFT
3396 || GET_CODE (XEXP (set, 1)) == ASHIFTRT
3397 || GET_CODE (XEXP (set, 1)) == LSHIFTRT
3398 || GET_CODE (XEXP (set, 1)) == XOR
3399 || GET_CODE (XEXP (set, 1)) == IOR
3400 || GET_CODE (XEXP (set, 1)) == AND
3401 || GET_CODE (XEXP (set, 1)) == PLUS
3402 || GET_CODE (XEXP (set, 1)) == MINUS
3403 || GET_CODE (XEXP (set, 1)) == MULT))
3408 next_insn = next_nonnote_insn (insn);
3412 if (GET_CODE (next_insn) != INSN)
3415 set2 = ((GET_CODE (PATTERN (next_insn)) == SET)
3416 ? PATTERN (next_insn) : NULL_RTX);
3417 if (set2 == NULL_RTX)
3420 if ((GET_CODE (XEXP (XEXP (set, 1), 0)) == REG
3421 || GET_CODE (XEXP (XEXP (set, 1), 0)) == MEM)
3422 && rtx_equal_p (XEXP (set2, 0), XEXP (XEXP (set, 1), 0))
3423 && rtx_equal_p (XEXP (set2, 1), XEXP (set, 0)))
3428 b_insn = gen_rtx_SET (VOIDmode,
3429 XEXP (XEXP (set, 1), 0),
3430 gen_rtx_fmt_ee (GET_CODE (XEXP (set, 1)),
3431 GET_MODE (XEXP (set, 0)),
3432 XEXP (XEXP (set, 1), 0),
3433 XEXP (XEXP (set, 1), 1)));
3435 emit_insn_before (b_insn, insn);
3436 b_insn = gen_rtx_SET (GET_MODE (XEXP (set, 0)), XEXP (set, 0),
3437 XEXP (XEXP (set, 1), 0));
3438 next2_insn = emit_insn_before (b_insn, insn);
3440 delete_insn (next_insn);
3445 /* Having tried with one operand of the expression, now, if
3446 appropriate, try to do the same thing with the second operand.
3447 Of course there are fewer operations that can match here
3448 because they must be commutative. */
3449 if (GET_RTX_CLASS (GET_CODE (XEXP (set, 1))) == 'c'
3450 && (GET_CODE (XEXP (XEXP (set, 1), 1)) == REG
3451 || GET_CODE (XEXP (XEXP (set, 1), 1)) == MEM)
3452 && rtx_equal_p (XEXP (set2, 0), XEXP (XEXP (set, 1), 1))
3453 && rtx_equal_p (XEXP (set2, 1), XEXP (set, 0)))
3459 /* Try to ensure that we put things in a canonical form. */
3460 swap_args = (GET_CODE (XEXP (XEXP (set, 1), 0)) == REG
3461 || GET_CODE (XEXP (XEXP (set, 1), 0)) == MEM);
3462 rtx_ee = gen_rtx_fmt_ee (GET_CODE (XEXP (set, 1)),
3463 GET_MODE (XEXP (set, 0)),
3464 XEXP (XEXP (set, 1), swap_args ? 1 : 0),
3465 XEXP (XEXP (set, 1),
3466 swap_args ? 0 : 1));
3468 emit_insn_before (gen_rtx_SET (VOIDmode,
3469 XEXP (XEXP (set, 1), 1),
3472 next2_insn = emit_insn_before (gen_rtx_SET
3473 (GET_MODE (XEXP (set, 0)),
3475 XEXP (XEXP (set, 1), 1)),
3478 delete_insn (next_insn);
3485 /* Replace and recurse until we've tried QImode pieces! */
3488 mdr_pres_replace_and_recurse (orig, with, insn)
3493 enum machine_mode new_mode;
3495 validate_replace_rtx (orig, with, insn);
3497 switch (GET_MODE (orig))
3517 mdr_pres_replace_and_recurse (ip2k_get_low_half (orig, new_mode),
3518 ip2k_get_low_half (with, new_mode),
3520 mdr_pres_replace_and_recurse (ip2k_get_high_half (orig, new_mode),
3521 ip2k_get_high_half (with, new_mode),
3525 /* Assist the following function, mdr_propagate_reg_equivs(). */
3528 mdr_propagate_reg_equivs_sequence (first_insn, orig, equiv)
3534 rtx try_equiv = equiv;
3536 /* First scan the RTL looking for anything else that might clobber what
3537 we're doing. If we find anything then we can't do the replacement. */
3538 for (try_insn = next_nonnote_insn (first_insn);
3539 try_insn; try_insn = next_nonnote_insn (try_insn))
3543 if (GET_CODE (try_insn) != JUMP_INSN && GET_CODE (try_insn) != INSN)
3546 pattern = PATTERN (try_insn);
3547 if (GET_CODE (pattern) == PARALLEL)
3551 for (j = 0; j < XVECLEN (pattern, 0); j++)
3553 rtx px = XVECEXP (pattern, 0, j);
3555 if (GET_CODE (px) == SET)
3556 if (! ip2k_composite_xexp_not_uses_reg_p (XEXP (px, 0),
3558 GET_MODE_SIZE (GET_MODE (orig))))
3562 else if (GET_CODE (pattern) == SET)
3564 if (! ip2k_composite_xexp_not_uses_reg_p (XEXP (pattern, 0),
3566 GET_MODE_SIZE (GET_MODE (orig))))
3571 /* Once we've decided that we're safe to do the replacement then make the
3573 for (try_insn = next_nonnote_insn (first_insn); try_insn;
3574 try_insn = next_nonnote_insn (try_insn))
3577 rtx new_equiv = NULL_RTX;
3579 if (GET_CODE (try_insn) != JUMP_INSN && GET_CODE (try_insn) != INSN)
3585 set = ((GET_CODE (PATTERN (try_insn)) == SET)
3586 ? PATTERN (try_insn) : NULL_RTX);
3587 if (set == NULL_RTX)
3590 /* We look for a special case of "push" operations screwing our
3591 register equivalence when it's based on a stack slot. We can
3592 track this one and replace the old equivalence expression with
3594 if (GET_CODE (XEXP (set, 0)) == MEM
3595 && GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC
3596 && REG_P (XEXP (XEXP (XEXP (set, 0), 0), 0))
3597 && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP)
3599 /* XXX - need to ensure that we can track this without going
3601 HOST_WIDE_INT disp = (INTVAL (XEXP (XEXP (try_equiv, 0), 1))
3602 + GET_MODE_SIZE (GET_MODE (XEXP (set, 0))));
3603 new_equiv = gen_rtx_MEM (GET_MODE (try_equiv),
3604 gen_rtx_PLUS (Pmode,
3605 gen_rtx_REG (HImode, REG_SP),
3609 /* The replacement process is somewhat complicated by the fact that we
3610 might be dealing with what were originally subregs and thus we have
3611 to replace parts of our original expression! */
3612 mdr_pres_replace_and_recurse (orig, try_equiv, try_insn);
3614 if (new_equiv != NULL_RTX)
3615 try_equiv = new_equiv;
3619 /* Try propagating register equivalences forwards. It may be that we can
3620 replace a register use with an equivalent expression that already
3621 holds the same value and thus allow one or more register loads to
3625 mdr_propagate_reg_equivs (first_insn)
3631 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
3633 if (GET_CODE (insn) != INSN)
3636 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
3637 if (set == NULL_RTX)
3640 /* Have we found a stack slot equivalence for a register? */
3641 if (REG_P (XEXP (set, 0))
3642 && REGNO (XEXP (set, 0)) >= 0x88
3643 && GET_CODE (XEXP (set, 1)) == MEM
3644 && GET_CODE (XEXP (XEXP (set, 1), 0)) == PLUS
3645 && REG_P (XEXP (XEXP (XEXP (set, 1), 0), 0))
3646 && REGNO (XEXP (XEXP (XEXP (set, 1), 0), 0)) == REG_SP
3647 && find_reg_note (insn, REG_EQUIV, NULL_RTX))
3649 mdr_propagate_reg_equivs_sequence (insn, XEXP (set, 0),
3655 /* Structure used to track jump targets. */
3657 struct dpre_jump_targets
3659 int target; /* Is this a jump target? */
3660 int reach_count; /* Number of ways we can reach this insn. */
3661 int touch_count; /* Number of times we've touched this
3662 insns during scanning. */
3663 rtx dp_equiv; /* DP-equivalence at this point. */
3666 struct dpre_jump_targets *ip2k_dpre_jump_targets;
3668 /* DP equivalence tracking used within DP reload elimination. */
3671 track_dp_reload (insn, dp_current, dp_current_ok, modifying)
3679 if (GET_CODE (insn) != INSN)
3681 *dp_current = NULL_RTX;
3685 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
3686 if (set == NULL_RTX)
3688 *dp_current = NULL_RTX;
3692 /* If we're pushing a PLUS or MINUS then it's a win if we can replace
3693 an expression for which DP is equivalent with DP. This happens
3694 surprisingly often when we pass a pointer to a structure embedded
3695 within another structure. */
3696 if (*dp_current != NULL_RTX
3697 && GET_CODE (XEXP (set, 0)) == MEM
3698 && GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC
3699 && GET_CODE (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG
3700 && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP
3701 && (GET_CODE (XEXP (set, 1)) == PLUS
3702 || GET_CODE (XEXP (set, 1)) == MINUS)
3703 && GET_CODE (*dp_current) != SYMBOL_REF
3704 && GET_CODE (*dp_current) != LABEL_REF
3705 && GET_CODE (*dp_current) != CONST)
3708 validate_replace_rtx (*dp_current, gen_rtx_REG (HImode, REG_DP), insn);
3711 /* Look for DP being modified. If it is, see if it's being changed
3712 to what it already is! */
3713 if (GET_CODE (XEXP (set, 0)) == REG
3714 && REGNO (XEXP (set, 0)) == REG_DP
3715 && GET_MODE (XEXP (set, 0)) == HImode)
3717 /* If this is an equivalence we can delete the new set operation. */
3718 if (*dp_current != NULL_RTX
3719 && rtx_equal_p (XEXP (set, 1), *dp_current))
3726 /* If we've not found an equivalence we can look for a special
3727 case where an operand of the expression that sets DP is
3728 already equivalent to DP and in that circumstance we simplify
3729 by replacing that expression with DP. */
3730 if (*dp_current != NULL_RTX
3731 && GET_CODE (*dp_current) != SYMBOL_REF
3732 && GET_CODE (*dp_current) != LABEL_REF
3733 && GET_CODE (*dp_current) != CONST
3735 validate_replace_rtx (*dp_current, XEXP (set, 0), insn);
3737 /* Assuming that we're not loading DP from something that uses DP
3738 itself then we mark the new equivalence for DP. If we did match
3739 DP then we can't re-use this one. */
3740 if (ip2k_xexp_not_uses_reg_p (XEXP (set, 1), REG_DP, 2))
3742 *dp_current = XEXP (set, 1);
3747 *dp_current = NULL_RTX;
3752 else if (GET_CODE (XEXP (set, 0)) == REG
3753 && (REGNO (XEXP (set, 0)) == REG_DPL
3754 || REGNO (XEXP (set, 0)) == REG_DPH))
3756 /* If we clobber part of DP then we've clobbered any equivalences! */
3757 *dp_current = NULL_RTX;
3760 else if (! ip2k_xexp_not_uses_reg_p (XEXP (set, 0), REG_SP, 2)
3761 && *dp_current != NULL_RTX
3762 && !ip2k_xexp_not_uses_reg_p (*dp_current, REG_SP, 2))
3764 /* We look for a special case of "push" operations screwing up the
3765 setting of DP when it's based on the stack. We can track this one
3766 and replace the old expression for DP with a new one. */
3767 if (GET_CODE (XEXP (set, 0)) == MEM
3768 && GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC
3769 && GET_CODE (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG
3770 && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP
3771 && GET_CODE (*dp_current) == MEM
3772 && GET_CODE (XEXP (*dp_current, 0)) == PLUS)
3774 /* XXX - need to ensure that we can track this without going
3776 HOST_WIDE_INT disp = (INTVAL (XEXP (XEXP (*dp_current, 0), 1))
3777 + GET_MODE_SIZE (GET_MODE (XEXP (set, 0))));
3778 *dp_current = gen_rtx_MEM (HImode,
3779 gen_rtx_PLUS (Pmode,
3780 gen_rtx_REG(HImode, REG_SP),
3785 /* Now we look for writes to the stack. We can determine if these will
3786 affect the equivalence we're tracking for DP and if not then we can
3787 keep tracking it. */
3788 if (GET_CODE (XEXP (set, 0)) == MEM
3789 && GET_CODE (*dp_current) == MEM)
3791 /* Look at the SP offsets and look for any overlaps. */
3792 int dp_cur_sp_offs = INTVAL (XEXP (XEXP (*dp_current, 0), 1));
3793 int set_sp_offs = INTVAL (XEXP (XEXP (XEXP (set, 0), 0), 1));
3795 if (abs (dp_cur_sp_offs - set_sp_offs) < 2)
3797 *dp_current = NULL_RTX;
3802 else if (GET_CODE (XEXP (set, 0)) == REG
3803 && *dp_current != NULL_RTX
3804 && !ip2k_xexp_not_uses_reg_p (*dp_current, REGNO (XEXP (set, 0)),
3805 GET_MODE_SIZE (GET_MODE (XEXP (set,
3808 /* If we've just clobbered all or part of a register reference that we
3809 were sharing for DP then we can't share it any more! */
3810 *dp_current = NULL_RTX;
3813 return dp_current_ok;
3816 /* As part of the machine-dependent reorg we scan loads and reloads of
3817 DP to see where any are redundant. This does happens because we
3818 are able to subsequently transform things in interesting ways. Sometimes
3819 gcc also does unecessary reloads too so we try to eliminate these too. */
3822 mdr_try_dp_reload_elim (first_insn)
3826 struct dpre_jump_targets *djt;
3828 int incomplete_scan;
3829 int last_incomplete_scan;
3831 ip2k_dpre_jump_targets
3832 = (struct dpre_jump_targets *) xcalloc (get_max_uid (),
3833 sizeof (struct dpre_jump_targets));
3835 /* First we scan to build up a list of all CODE_LABEL insns and we work out
3836 how many different ways we can reach them. */
3837 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
3839 if (GET_CODE (insn) == CODE_LABEL)
3841 djt = &ip2k_dpre_jump_targets[INSN_UID (insn)];
3843 djt->reach_count = LABEL_NUSES (insn);
3844 djt->touch_count = 0;
3845 djt->dp_equiv = NULL_RTX;
3846 if (! prev_nonnote_insn (insn)
3847 || (prev_nonnote_insn (insn)
3848 && GET_CODE (prev_nonnote_insn (insn)) != BARRIER))
3853 /* Next we scan all of the ways of reaching the code labels to see
3854 what the DP register is equivalent to as we reach them. If we find
3855 that they're the same then we keep noting the matched value. We
3856 iterate around this until we reach a convergence on DP equivalences
3857 at all code labels - we have to be very careful not to be too
3859 incomplete_scan = -1;
3862 int dp_current_ok = 0;
3863 last_incomplete_scan = incomplete_scan;
3864 dp_current = NULL_RTX;
3866 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
3868 /* If we have a code label then we need to see if we already know
3869 what the equivalence is at this point. If we do then we use it
3870 immediately, but if we don't then we have a special case to track
3871 when we hit a fallthrough-edge (label with no barrier preceding
3872 it). Any other accesses to the label must be from jump insns
3873 and so they're handled elsewhere. */
3874 if (GET_CODE (insn) == CODE_LABEL)
3876 djt = &ip2k_dpre_jump_targets[INSN_UID (insn)];
3878 /* If we're fully characterized the use the equivalence. */
3879 if (djt->touch_count == djt->reach_count)
3881 dp_current = djt->dp_equiv;
3886 /* If we have a known equivalence for DP as we reach the
3887 fallthrough-edge then track this into the code label. */
3889 && (! prev_nonnote_insn (insn)
3890 || (prev_nonnote_insn (insn)
3891 && GET_CODE (prev_nonnote_insn (insn)) != BARRIER)))
3893 if (djt->touch_count == 0)
3894 djt->dp_equiv = dp_current;
3896 if (djt->touch_count < djt->reach_count)
3899 if (! rtx_equal_p (djt->dp_equiv, dp_current))
3901 /* When we definitely know that we can't form an
3902 equivalence for DP here we must clobber anything
3903 that we'd started to track too. */
3904 djt->dp_equiv = NULL_RTX;
3905 dp_current = NULL_RTX;
3911 /* If we've not completely characterized this code label then
3912 be cautious and assume that we don't know what DP is
3914 if (djt->touch_count < djt->reach_count)
3916 dp_current = NULL_RTX;
3923 /* If we've hit a jump insn then we look for either an address
3924 vector (jump table) or for jump label references. */
3925 if (GET_CODE (insn) == JUMP_INSN)
3927 /* Don't attempt to track here if we don't have a known
3928 equivalence for DP at this point. */
3931 rtx pat = PATTERN (insn);
3932 if (GET_CODE (pat) == ADDR_VEC)
3935 int len = XVECLEN (pat, 0);
3937 for (i = 0; i < len; i++)
3939 rtx vec_insn = XEXP (XVECEXP (pat, 0, i), 0);
3940 djt = &ip2k_dpre_jump_targets [INSN_UID (vec_insn)];
3942 if (djt->touch_count == 0)
3943 djt->dp_equiv = dp_current;
3945 if (djt->touch_count < djt->reach_count)
3948 if (! rtx_equal_p (djt->dp_equiv, dp_current))
3949 djt->dp_equiv = NULL_RTX;
3953 else if (JUMP_LABEL (insn))
3955 rtx j_insn = JUMP_LABEL (insn);
3956 djt = &ip2k_dpre_jump_targets[INSN_UID (j_insn)];
3958 if (djt->touch_count == 0)
3959 djt->dp_equiv = dp_current;
3961 if (djt->touch_count < djt->reach_count)
3964 if (! rtx_equal_p (djt->dp_equiv, dp_current))
3965 djt->dp_equiv = NULL_RTX;
3973 /* Anything other than a code labal or jump arrives here.
3974 We try and track DP, but sometimes we might not be able to. */
3975 dp_current_ok = track_dp_reload (insn, &dp_current,
3979 /* When we're looking to see if we've finished we count the number of
3980 paths throught the code labels where we weren't able to definitively
3982 This number is used to see if we're converging on a solution.
3983 If this hits zero then we've fully converged, but if this stays the
3984 same as last time then we probably can't make any further
3986 incomplete_scan = 0;
3987 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
3989 if (GET_CODE (insn) == CODE_LABEL)
3991 djt = &ip2k_dpre_jump_targets[INSN_UID (insn)];
3992 if (djt->touch_count != djt->reach_count)
3994 incomplete_scan += (djt->reach_count - djt->touch_count);
3995 djt->dp_equiv = NULL_RTX;
3996 djt->touch_count = 0;
4001 while (incomplete_scan && incomplete_scan != last_incomplete_scan);
4003 /* Finally we scan the whole function and run DP elimination. When we hit
4004 a CODE_LABEL we pick up any stored equivalence since we now know that
4005 every path to this point entered with DP holding the same thing! If
4006 we subsequently have a reload that matches then we can eliminate it. */
4007 dp_current = NULL_RTX;
4008 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
4010 if (GET_CODE (insn) == JUMP_INSN)
4013 if (GET_CODE (insn) == CODE_LABEL)
4015 djt = &ip2k_dpre_jump_targets[INSN_UID (insn)];
4016 dp_current = djt->dp_equiv;
4020 track_dp_reload (insn, &dp_current, 1, 1);
4023 free (ip2k_dpre_jump_targets);
4026 /* As part of the machine-dependent reorg we look for reloads of DP
4027 that we can move to earlier points within the file.
4028 Moving these out of the way allows more peepholes to match. */
4031 mdr_try_move_dp_reload (first_insn)
4038 /* Don't try to match the first instruction because we can't move it
4040 orig_first = first_insn;
4041 first_insn = next_nonnote_insn (first_insn);
4043 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
4045 if (GET_CODE (insn) != INSN)
4048 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
4049 if (set == NULL_RTX)
4052 /* Look for DP being loaded. When we find this we start a rewind
4053 scan looking for possible positions to move this to. */
4054 if (GET_CODE (XEXP (set, 0)) == REG
4055 && REGNO (XEXP (set, 0)) == REG_DP
4056 && GET_MODE (XEXP (set, 0)) == HImode)
4059 rtx try_insn = insn;
4068 /* For now we do the *really* simple version of things and only
4069 attempt to move the load of DP if it's very safe to do so. */
4070 rewind = prev_nonnote_insn (try_insn);
4071 if (rewind != orig_first && rewind != NULL_RTX
4072 && GET_CODE (rewind) == INSN)
4074 check = ((GET_CODE (PATTERN (rewind)) == SET)
4075 ? PATTERN (rewind) : NULL_RTX);
4076 if (check != NULL_RTX
4077 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (check, 0))
4078 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (check, 1)))
4080 if (GET_CODE (XEXP (check, 0)) == REG
4081 && REGNO (XEXP (check, 0)) != REG_DPH
4082 && REGNO (XEXP (check, 0)) != REG_DPL
4083 && (ip2k_composite_xexp_not_uses_reg_p
4084 (XEXP (check, 1), REG_DP, 2))
4085 && (ip2k_composite_xexp_not_uses_reg_p
4087 REGNO (XEXP (check, 0)),
4088 GET_MODE_SIZE (GET_MODE (XEXP (check, 0))))))
4090 emit_insn_before (set, rewind);
4091 if (try_insn == insn)
4092 insn = prev_nonnote_insn (insn);
4093 delete_insn (try_insn);
4094 try_insn = prev_nonnote_insn (rewind);
4097 else if (GET_CODE (XEXP (set, 1)) == REG
4098 && ip2k_composite_xexp_not_uses_reg_p (XEXP (check, 1), REG_DP, 2)
4099 && ip2k_composite_xexp_not_uses_reg_p (XEXP (check, 0), REG_DP, 2)
4100 && ip2k_composite_xexp_not_uses_reg_p (XEXP (check, 0), REGNO (XEXP (set, 1)),
4101 GET_MODE_SIZE (GET_MODE (XEXP (set, 1)))))
4103 emit_insn_before (set, rewind);
4104 if (try_insn == insn)
4105 insn = prev_nonnote_insn (insn);
4106 delete_insn (try_insn);
4107 try_insn = prev_nonnote_insn (rewind);
4113 while (try_again && try_insn);
4118 /* Look to see if the expression, x, can have any stack references offset by
4119 a fixed constant, offset. If it definitely can then returns non-zero. */
4122 ip2k_check_can_adjust_stack_ref (x, offset)
4126 if (GET_RTX_CLASS (GET_CODE (x)) == '2'
4127 || GET_RTX_CLASS (GET_CODE (x)) == 'c')
4128 return (ip2k_check_can_adjust_stack_ref (XEXP (x, 0), offset)
4129 && ip2k_check_can_adjust_stack_ref (XEXP (x, 1), offset));
4131 if (GET_RTX_CLASS (GET_CODE (x)) == '1')
4132 return ip2k_check_can_adjust_stack_ref (XEXP (x, 0), offset);
4134 switch (GET_CODE (x))
4137 return (REGNO (x) != REG_SPH && REGNO (x) != REG_SPL);
4140 if (GET_CODE (XEXP (x, 0)) != PLUS)
4143 if (GET_CODE (XEXP (XEXP (x, 0), 0)) != REG)
4146 if (REGNO (XEXP (XEXP (x, 0), 0)) != REG_SP)
4149 /* We can't allow this if the adjustment will create an
4151 return (INTVAL (XEXP (XEXP (x, 0), 1))
4152 + offset <= (128 - 2 * GET_MODE_SIZE (GET_MODE (x))));
4166 /* Adjusts all of the stack references in the expression pointed to by x by
4170 ip2k_adjust_stack_ref (x, offset)
4174 if (GET_RTX_CLASS (GET_CODE (*x)) == '2'
4175 || GET_RTX_CLASS (GET_CODE (*x)) == 'c')
4177 ip2k_adjust_stack_ref (&XEXP (*x, 0), offset);
4178 ip2k_adjust_stack_ref (&XEXP (*x, 1), offset);
4182 if (GET_RTX_CLASS (GET_CODE (*x)) == '1')
4184 ip2k_adjust_stack_ref (&XEXP (*x, 0), offset);
4188 switch (GET_CODE (*x))
4191 if (GET_CODE (XEXP (*x, 0)) != PLUS)
4194 if (GET_CODE (XEXP (XEXP (*x, 0), 0)) != REG)
4197 if (REGNO (XEXP (XEXP (*x, 0), 0)) != REG_SP)
4201 XEXP (XEXP (*x, 0), 1) = GEN_INT (INTVAL (XEXP (XEXP (*x, 0), 1))
4210 /* As part of the machine-dependent reorg we look to move push instructions
4211 to earlier points within the file. Moving these out of the way allows more
4212 peepholes to match. */
4215 mdr_try_move_pushes (first_insn)
4222 /* Don't try to match the first instruction because we can't move
4224 orig_first = first_insn;
4225 first_insn = next_nonnote_insn (first_insn);
4227 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
4229 if (GET_CODE (insn) != INSN)
4232 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
4233 if (set == NULL_RTX)
4236 /* Have we found a push instruction? */
4237 if (GET_CODE (XEXP (set, 0)) == MEM
4238 && GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC
4239 && GET_CODE (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG
4240 && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP
4241 && GET_CODE (XEXP (set, 1)) == REG)
4243 rtx try_insn = insn;
4244 unsigned int regno = REGNO (XEXP (set, 1));
4245 int reg_range = GET_MODE_SIZE (GET_MODE (XEXP (set, 1)));
4252 rewind = prev_nonnote_insn (try_insn);
4253 if (rewind == orig_first || rewind == NULL_RTX
4254 || GET_CODE (rewind) != INSN)
4257 check = (GET_CODE (PATTERN (rewind)) == SET) ? PATTERN (rewind) : NULL_RTX;
4258 if (check == NULL_RTX)
4261 if (! ip2k_check_can_adjust_stack_ref (XEXP (check, 0),
4263 || ! ip2k_check_can_adjust_stack_ref (XEXP (check, 1),
4267 /* If we've hit another push instruction we can't go any
4269 if (GET_CODE (XEXP (check, 0)) == MEM
4270 && GET_CODE (XEXP (XEXP (check, 0), 0)) == POST_DEC
4271 && GET_CODE (XEXP (XEXP (XEXP (check, 0), 0), 0)) == REG
4272 && REGNO (XEXP (XEXP (XEXP (check, 0), 0), 0)) == REG_SP)
4275 /* If this is a register move then check that it doesn't clobber
4276 SP or any part of the instruction we're trying to move. */
4277 if (GET_CODE (XEXP (check, 0)) == REG)
4279 unsigned int check_reg = REGNO (XEXP (check, 0));
4280 int check_reg_range = GET_MODE_SIZE (GET_MODE (XEXP (check,
4283 /* If we have a special case where what we want to push is
4284 being loaded by this "clobbering" insn then we can just
4285 push what is being used to load us and then do the load.
4286 This may seem a little odd, but we may subsequently be
4287 able to merge the load with another instruction as it
4288 may only be used once now! Note though that we
4289 specifically don't try this if the expression being
4290 loaded is an HImode MEM using IP. */
4291 if (check_reg == regno
4292 && check_reg_range == reg_range
4293 && ((GET_CODE (XEXP (check, 1)) == REG
4294 || (GET_CODE (XEXP (check, 1)) == MEM
4295 && (GET_MODE (XEXP (check, 1)) != HImode
4296 || ip2k_xexp_not_uses_reg_for_mem (XEXP (check, 1), REG_IP))))))
4298 switch (check_reg_range)
4301 emit_insn_before (gen_movqi (XEXP (set, 0),
4304 delete_insn (try_insn);
4308 emit_insn_before (gen_movhi (XEXP (set, 0),
4311 delete_insn (try_insn);
4315 emit_insn_before (gen_movsi (XEXP (set, 0),
4318 delete_insn (try_insn);
4322 emit_insn_before (gen_movdi (XEXP (set, 0),
4325 delete_insn (try_insn);
4329 ip2k_adjust_stack_ref (&XEXP (check, 0), reg_range);
4330 ip2k_adjust_stack_ref (&XEXP (check, 1), reg_range);
4331 try_insn = prev_nonnote_insn (rewind);
4332 /* XXX - should be a continue? */
4336 if ((check_reg == REG_SPL)
4337 || (check_reg == REG_SPH)
4338 || (((regno <= check_reg)
4339 && (regno + reg_range - 1) >= check_reg)
4340 || ((regno <= (check_reg + check_reg_range - 1))
4341 && ((regno + reg_range - 1)
4342 >= (check_reg + check_reg_range - 1)))))
4346 emit_insn_before (set, rewind);
4347 delete_insn (try_insn);
4348 ip2k_adjust_stack_ref (&XEXP (check, 0), reg_range);
4349 ip2k_adjust_stack_ref (&XEXP (check, 1), reg_range);
4350 try_insn = prev_nonnote_insn (rewind);
4356 /* Assist the following function, mdr_try_propagate_clr(). */
4359 mdr_try_propagate_clr_sequence (first_insn, regno)
4365 for (try_insn = next_nonnote_insn (first_insn); try_insn;
4366 try_insn = next_nonnote_insn (try_insn))
4368 rtx new_insn = NULL_RTX;
4371 if (GET_CODE (try_insn) == JUMP_INSN)
4374 if (GET_CODE (try_insn) != INSN)
4377 set2 = ((GET_CODE (PATTERN (try_insn)) == SET)
4378 ? PATTERN (try_insn) : NULL_RTX);
4379 if (set2 == NULL_RTX)
4382 if (GET_CODE (XEXP (set2, 1)) == AND
4383 && ((GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG
4384 && REGNO (XEXP (XEXP (set2, 1), 0)) == regno)
4385 || (GET_CODE (XEXP (XEXP (set2, 1), 1)) == REG
4386 && REGNO (XEXP (XEXP (set2, 1), 1)) == regno)))
4388 rtx remove_insn = try_insn;
4389 try_insn = emit_insn_before (gen_rtx_SET (QImode, XEXP (set2, 0),
4390 const0_rtx), try_insn);
4391 delete_insn (remove_insn);
4393 else if (GET_CODE (XEXP (set2, 1)) == IOR
4394 && GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG
4395 && REGNO (XEXP (XEXP (set2, 1), 0)) == regno)
4397 rtx remove_insn = try_insn;
4398 try_insn = emit_insn_before (gen_rtx_SET (QImode, XEXP (set2, 0),
4399 XEXP (XEXP (set2, 1), 1)),
4401 delete_insn (remove_insn);
4403 else if (GET_CODE (XEXP (set2, 1)) == IOR
4404 && GET_CODE (XEXP (XEXP (set2, 1), 1)) == REG
4405 && REGNO (XEXP (XEXP (set2, 1), 1)) == regno)
4407 rtx remove_insn = try_insn;
4408 try_insn = emit_insn_before (gen_rtx_SET (QImode, XEXP (set2, 0),
4409 XEXP (XEXP (set2, 1), 0)),
4411 delete_insn (remove_insn);
4413 else if (GET_CODE (XEXP (set2, 1)) == XOR
4414 && GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG
4415 && REGNO (XEXP (XEXP (set2, 1), 0)) == regno)
4417 rtx remove_insn = try_insn;
4418 try_insn = emit_insn_before (gen_rtx_SET (QImode, XEXP (set2, 0),
4419 XEXP (XEXP (set2, 1), 1)),
4421 delete_insn (remove_insn);
4423 else if (GET_CODE (XEXP (set2, 1)) == XOR
4424 && GET_CODE (XEXP (XEXP (set2, 1), 1)) == REG
4425 && REGNO (XEXP (XEXP (set2, 1), 1)) == regno)
4427 rtx remove_insn = try_insn;
4428 try_insn = emit_insn_before (gen_rtx_SET (QImode, XEXP (set2, 0),
4429 XEXP (XEXP (set2, 1), 0)),
4431 delete_insn (remove_insn);
4434 if (GET_CODE (XEXP (set2, 0)) == REG)
4436 int reg2_range = GET_MODE_SIZE (GET_MODE (XEXP (set2, 0)));
4437 unsigned int regno2 = REGNO (XEXP (set2, 0));
4441 && GET_CODE (XEXP (set2, 1)) == CONST_INT)
4443 int iv = INTVAL (XEXP (set2, 1));
4446 if (iv == 1 || iv == -1)
4448 new_insn = gen_rtx_SET (QImode, XEXP (set2, 0),
4449 gen_rtx_PLUS (QImode, XEXP (set2, 0),
4451 new_insn = emit_insn_before (new_insn, try_insn);
4452 delete_insn (try_insn);
4453 try_insn = new_insn;
4458 if ((regno >= regno2) && (regno <= regno2 + reg2_range - 1))
4461 if (GET_CODE (XEXP (set2, 1)) == REG
4462 && REGNO (XEXP (set2, 1)) == regno)
4464 new_insn = emit_insn_before (gen_rtx_SET (QImode,
4468 delete_insn (try_insn);
4469 try_insn = new_insn;
4473 if (GET_CODE (XEXP (set2, 0)) == CC0)
4475 if (GET_CODE (XEXP (set2, 1)) == REG
4476 && GET_MODE_SIZE (GET_MODE (XEXP (set2, 1))) == 2
4477 && REGNO (XEXP (set2, 1)) == regno)
4479 new_insn = gen_rtx_SET (VOIDmode, gen_rtx (CC0, VOIDmode),
4480 gen_rtx_REG(QImode, regno + 1));
4481 new_insn = emit_insn_before (new_insn, try_insn);
4483 else if (GET_CODE (XEXP (set2, 1)) == COMPARE
4484 && GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG
4485 && GET_MODE_SIZE (GET_MODE (XEXP (XEXP (set2, 1), 0))) == 2
4486 && REGNO (XEXP (XEXP (set2, 1), 0)) == regno
4487 && GET_CODE (XEXP (XEXP (set2, 1), 1)) == CONST_INT
4488 && INTVAL (XEXP (XEXP (set2, 1), 1)) >= 0
4489 && INTVAL (XEXP (XEXP (set2, 1), 1)) < 256)
4491 new_insn = gen_rtx_SET (VOIDmode, cc0_rtx,
4492 gen_rtx_COMPARE(QImode,
4493 gen_rtx_REG (QImode,
4495 XEXP (XEXP (set2, 1),
4497 new_insn = emit_insn_before (new_insn, try_insn);
4500 /* If we have inserted a replacement for a CC0 setter operation
4501 then we need to delete the old one. */
4502 if (new_insn != NULL_RTX)
4504 delete_insn (try_insn);
4505 try_insn = new_insn;
4507 /* Now as we know that we have just done an unsigned compare
4508 (remember we were zero-extended by the clr!) we also know
4509 that we don't need a signed jump insn. If we find that
4510 our next isns is a signed jump then make it unsigned! */
4511 if (GET_CODE (next_nonnote_insn (try_insn)) == JUMP_INSN)
4515 try_insn = next_nonnote_insn (try_insn);
4516 set3 = ((GET_CODE (PATTERN (try_insn)) == SET)
4517 ? PATTERN (try_insn) : NULL_RTX);
4518 if (set3 == NULL_RTX)
4521 /* If we discover that our jump target is only accessible
4522 from here then we can continue our "clr" propagation to
4524 if (LABEL_NUSES (JUMP_LABEL (try_insn)) == 1)
4525 mdr_try_propagate_clr_sequence (JUMP_LABEL (try_insn),
4528 if (GET_CODE (XEXP (set3, 0)) == PC
4529 && GET_CODE (XEXP (set3, 1)) == IF_THEN_ELSE
4530 && (GET_CODE (XEXP (XEXP (set3, 1), 0)) == GT
4531 || GET_CODE (XEXP (XEXP (set3, 1), 0)) == GE
4532 || GET_CODE (XEXP (XEXP (set3, 1), 0)) == LT
4533 || GET_CODE (XEXP (XEXP (set3, 1), 0)) == LE)
4534 && GET_CODE (XEXP (XEXP (XEXP (set3, 1), 0), 0)) == CC0
4535 && (GET_CODE (XEXP (XEXP (XEXP (set3, 1), 0), 1))
4537 && GET_CODE (XEXP (XEXP (set3, 1), 1)) == LABEL_REF
4538 && GET_CODE (XEXP (XEXP (set3, 1), 2)) == PC)
4544 /* Replace our old conditional jump with a new one that
4545 does the unsigned form of what was previously a
4546 signed comparison. */
4547 code = GET_CODE (XEXP (XEXP (set3, 1), 0));
4548 cmp = gen_rtx_fmt_ee ((code == GT
4552 : (code == LT ? LTU : LEU))),
4554 XEXP (XEXP (XEXP (set3, 1), 0), 0),
4555 XEXP (XEXP (XEXP (set3, 1), 0),
4558 = gen_rtx_SET (GET_MODE (set3),
4560 gen_rtx_IF_THEN_ELSE
4561 (GET_MODE (XEXP (set3, 1)), cmp,
4562 XEXP (XEXP (set3, 1), 1),
4563 XEXP (XEXP (set3, 1), 2)));
4564 new_insn = emit_jump_insn_before (new_if, try_insn);
4565 LABEL_NUSES (JUMP_LABEL (try_insn))++;
4566 delete_insn (try_insn);
4567 try_insn = new_insn;
4572 else if (GET_CODE (XEXP (set2, 1)) == PLUS
4573 && GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG
4574 && GET_MODE_SIZE (GET_MODE (XEXP (XEXP (set2, 1), 0))) == 2
4575 && REGNO (XEXP (XEXP (set2, 1), 0)) == regno
4576 && (GET_CODE (XEXP (XEXP (set2, 1), 1)) == REG
4577 || GET_CODE (XEXP (XEXP (set2, 1), 1)) == MEM
4578 || GET_CODE (XEXP (XEXP (set2, 1), 1)) == CONST_INT
4579 || GET_CODE (XEXP (XEXP (set2, 1), 1)) == CONST
4580 || GET_CODE (XEXP (XEXP (set2, 1), 1)) == SYMBOL_REF))
4582 rtx extend = gen_rtx_ZERO_EXTEND (HImode,
4583 gen_rtx_REG (QImode, regno + 1));
4584 new_insn = gen_rtx_SET (HImode, XEXP (set2, 0),
4585 gen_rtx_PLUS (HImode, extend,
4586 XEXP (XEXP (set2, 1), 1)));
4587 new_insn = emit_insn_before (new_insn, try_insn);
4588 delete_insn (try_insn);
4589 try_insn = new_insn;
4591 else if (GET_CODE (XEXP (set2, 1)) == PLUS
4592 && GET_CODE (XEXP (XEXP (set2, 1), 1)) == REG
4593 && GET_MODE_SIZE (GET_MODE (XEXP (XEXP (set2, 1), 1))) == 2
4594 && REGNO (XEXP (XEXP (set2, 1), 1)) == regno
4595 && (GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG
4596 || GET_CODE (XEXP (XEXP (set2, 1), 0)) == MEM
4597 || GET_CODE (XEXP (XEXP (set2, 1), 0)) == CONST_INT
4598 || GET_CODE (XEXP (XEXP (set2, 1), 0)) == CONST
4599 || GET_CODE (XEXP (XEXP (set2, 1), 0)) == SYMBOL_REF))
4601 rtx t_src = gen_rtx_PLUS (HImode,
4602 gen_rtx_ZERO_EXTEND (HImode,
4603 gen_rtx_REG (QImode,
4606 XEXP (XEXP (set2, 1), 0));
4607 new_insn = emit_insn_before (gen_rtx_SET (HImode, XEXP (set2, 0),
4610 delete_insn (try_insn);
4611 try_insn = new_insn;
4616 /* One of the things that can quite often happen with an 8-bit CPU is that
4617 we end up clearing the MSByte of a 16-bit value. Unfortunately, all too
4618 often gcc doesn't have any way to realize that only half of the value is
4619 useful and ends up doing more work than it should. We scan for such
4620 occurrences here, track them and reduce compare operations to a smaller
4621 size where possible.
4623 Note that this is somewhat different to move propagation as we may
4624 actually change some instruction patterns when we're doing this whereas
4625 move propagation is just about doing a search and replace. */
4628 mdr_try_propagate_clr (first_insn)
4634 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
4636 if (GET_CODE (insn) != INSN)
4639 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
4640 if (set == NULL_RTX)
4643 /* Have we found a "clr" instruction? */
4644 if (GET_CODE (XEXP (set, 0)) == REG
4645 && GET_CODE (XEXP (set, 1)) == CONST_INT
4646 && GET_MODE_SIZE (GET_MODE (XEXP (set, 0))) == 1
4647 && INTVAL (XEXP (set, 1)) == 0)
4649 mdr_try_propagate_clr_sequence (insn, REGNO (XEXP (set, 0)));
4654 /* Look to see if the expression, x, does not make any memory references
4655 via the specified register. This is very conservative and only returns
4656 non-zero if we definitely don't have such a memory ref. */
4659 ip2k_xexp_not_uses_reg_for_mem (x, regno)
4664 regno &= 0xfffffffe;
4666 if (GET_RTX_CLASS (GET_CODE (x)) == 'b')
4667 return (ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 0), regno)
4668 && ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 1), regno)
4669 && ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 2), regno));
4671 if (GET_RTX_CLASS (GET_CODE (x)) == '2'
4672 || GET_RTX_CLASS (GET_CODE (x)) == 'c'
4673 || GET_RTX_CLASS (GET_CODE (x)) == '<')
4674 return (ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 0), regno)
4675 && ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 1), regno));
4677 if (GET_RTX_CLASS (GET_CODE (x)) == '1'
4678 || GET_RTX_CLASS (GET_CODE (x)) == '3')
4679 return ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 0), regno);
4681 switch (GET_CODE (x))
4687 if ((GET_CODE (XEXP (x, 0)) == PLUS
4688 && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
4689 && REGNO (XEXP (XEXP (x, 0), 0)) == regno)
4690 || (GET_CODE (XEXP (x, 0)) == REG
4691 && REGNO (XEXP (x, 0)) == regno))
4710 /* Assist the following function, mdr_try_propagate_move(). */
4713 mdr_try_propagate_move_sequence (first_insn, orig, equiv)
4720 for (try_insn = next_nonnote_insn (first_insn); try_insn;
4721 try_insn = next_nonnote_insn (try_insn))
4725 rtx new_equiv = NULL_RTX;
4727 if (GET_CODE (try_insn) != JUMP_INSN && GET_CODE (try_insn) != INSN)
4730 set = single_set (try_insn);
4731 if (set == NULL_RTX)
4734 range = MAX (GET_MODE_SIZE (GET_MODE (equiv)),
4735 GET_MODE_SIZE (GET_MODE (XEXP (set, 0))));
4737 if (GET_CODE (equiv) == REG
4738 && REGNO (equiv) == REG_W
4739 && (recog_memoized (try_insn) < 0
4740 || get_attr_clobberw (try_insn) != CLOBBERW_NO)
4741 && (! (GET_CODE (XEXP (set, 0)) == REG
4742 && REGNO (XEXP (set, 0)) == REG_W
4743 && rtx_equal_p (XEXP (set, 1), orig))))
4745 else if (GET_CODE (XEXP (set, 0)) == REG
4746 && (REGNO (XEXP (set, 0)) == REG_SP
4747 || ! ip2k_xexp_not_uses_reg_p (equiv, REGNO (XEXP (set, 0)),
4749 || ! ip2k_xexp_not_uses_reg_p (orig, REGNO (XEXP (set, 0)),
4751 && ! rtx_equal_p (equiv, XEXP (set, 0))
4752 && ! rtx_equal_p (orig, XEXP (set, 0)))
4754 else if (GET_CODE (orig) == REG
4755 && (REGNO (orig) == REG_IPL
4756 || REGNO (orig) == REG_IPH
4757 || REGNO (orig) == REG_DPL
4758 || REGNO (orig) == REG_DPH)
4759 && (! ip2k_xexp_not_uses_reg_for_mem (XEXP (set, 0),
4761 || ! ip2k_xexp_not_uses_reg_for_mem (XEXP (set, 1),
4764 else if (GET_CODE (XEXP (set, 0)) == MEM
4765 && GET_CODE (equiv) == MEM)
4767 if (! ip2k_xexp_not_uses_reg_p (equiv, REG_SP, 2))
4769 if (! ip2k_xexp_not_uses_reg_p (XEXP (set, 0), REG_SP, 2))
4771 /* We look for a special case of "push" operations screwing
4772 our register equivalence when it's based on a stack slot.
4773 We can track this one and replace the old equivalence
4774 expression with a new one. */
4775 if (GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC
4776 && GET_CODE (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG
4777 && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP
4778 && GET_CODE (XEXP (equiv, 0)) == PLUS
4779 && REGNO (XEXP (XEXP (equiv, 0), 0)) == REG_SP)
4781 int md_size = GET_MODE_SIZE (GET_MODE (XEXP (set, 0)));
4782 int new_sp_offs = INTVAL (XEXP (XEXP (equiv, 0), 1))
4785 /* Don't allow an invalid stack pointer offset to be
4787 if (new_sp_offs > (128 - 2 * md_size))
4791 = gen_rtx_MEM (GET_MODE (equiv),
4792 gen_rtx_PLUS (Pmode,
4793 gen_rtx_REG (HImode ,
4795 GEN_INT (new_sp_offs)));
4797 else if (! rtx_equal_p (equiv, XEXP (set, 0)))
4799 /* Look at the SP offsets and look for any overlaps. */
4800 int equiv_offs = GET_CODE (XEXP (equiv, 0)) == PLUS
4801 ? INTVAL (XEXP (XEXP (equiv, 0), 1))
4804 = (GET_CODE (XEXP (XEXP (set, 0), 0)) == PLUS
4805 ? INTVAL (XEXP (XEXP (XEXP (set, 0), 0), 1))
4808 if (abs (equiv_offs - set_offs) < range)
4814 if (! ip2k_xexp_not_uses_reg_p (equiv, REG_IP, 2))
4817 if (! ip2k_xexp_not_uses_reg_p (XEXP (set, 0), REG_DP, 2)
4818 && ! ip2k_xexp_not_uses_reg_p (equiv, REG_DP, 2)
4819 && ! rtx_equal_p (equiv, XEXP (set, 0)))
4821 /* Look at the DP offsets and look for any overlaps. */
4822 int equiv_offs = GET_CODE (XEXP (equiv, 0)) == PLUS
4823 ? INTVAL (XEXP (XEXP (equiv, 0), 1))
4825 int set_offs = GET_CODE (XEXP (XEXP (set, 0), 0)) == PLUS
4826 ? INTVAL (XEXP (XEXP (XEXP (set, 0), 0), 1))
4829 if (abs (equiv_offs - set_offs) < range)
4834 validate_replace_rtx_subexp (orig, equiv, try_insn, &XEXP (set, 1));
4836 if (rtx_equal_p (equiv, XEXP (set, 0))
4837 || rtx_equal_p (orig, XEXP (set, 0)))
4840 if (new_equiv != NULL_RTX)
4845 /* Try propagating move instructions forwards. It may be that we can
4846 replace a register use with an equivalent expression that already
4847 holds the same value and thus allow one or more register loads to
4851 mdr_try_propagate_move (first_insn)
4857 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
4859 if (GET_CODE (insn) != INSN)
4862 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
4863 if (set == NULL_RTX)
4866 /* Have we found a simple move instruction? */
4867 if (GET_CODE (XEXP (set, 0)) == REG
4868 && (REGNO (XEXP (set, 0)) >= 0x80
4869 || REGNO (XEXP (set, 0)) == REG_DPL
4870 || REGNO (XEXP (set, 0)) == REG_DPH
4871 || REGNO (XEXP (set, 0)) == REG_IPL
4872 || REGNO (XEXP (set, 0)) == REG_IPH)
4873 && ((GET_CODE (XEXP (set, 1)) == REG
4874 && REGNO (XEXP (set, 1)) != REG_SP
4875 && ip2k_xexp_not_uses_reg_p (XEXP (set, 0),
4876 REGNO (XEXP (set, 1)),
4877 GET_MODE_SIZE (GET_MODE (XEXP (set,
4879 || (GET_CODE (XEXP (set, 1)) == MEM
4880 && (ip2k_xexp_not_uses_reg_p (XEXP (set, 1), REG_IP, 2)
4881 || GET_MODE (XEXP (set, 1)) == QImode)
4882 && ((REGNO (XEXP (set, 0)) != REG_DPH
4883 && REGNO (XEXP (set, 0)) != REG_DPL)
4884 || ip2k_xexp_not_uses_reg_p (XEXP (set, 1), REG_DP, 2)))
4885 || (GET_CODE (XEXP (set, 1)) == CONST_INT
4886 && (GET_MODE (XEXP (set, 0)) != QImode
4887 || INTVAL (XEXP (set, 1)) != 0))
4888 || GET_CODE (XEXP (set, 1)) == CONST_DOUBLE
4889 || GET_CODE (XEXP (set, 1)) == CONST
4890 || GET_CODE (XEXP (set, 1)) == SYMBOL_REF))
4892 mdr_try_propagate_move_sequence (insn, XEXP (set, 0), XEXP (set, 1));
4897 /* Try to remove redundant instructions. */
4900 mdr_try_remove_redundant_insns (first_insn)
4905 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
4908 enum machine_mode mode;
4910 HOST_WIDE_INT pattern;
4913 if (GET_CODE (insn) != INSN)
4916 if (GET_CODE (PATTERN (insn)) == CONST_INT)
4918 /* We've found a dummy expression. */
4919 rtx remove_insn = insn;
4920 insn = prev_nonnote_insn (insn);
4921 delete_insn (remove_insn);
4925 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
4926 if (set == NULL_RTX)
4929 mode = GET_MODE (XEXP (set, 0));
4930 md_size = GET_MODE_SIZE (mode);
4931 if ((md_size < 1) || (md_size > 4))
4935 for (i = 0; i < md_size; i++)
4941 if ((GET_CODE (XEXP (set, 1)) == AND
4942 && GET_CODE (XEXP (XEXP (set, 1), 1)) == CONST_INT
4943 && INTVAL (XEXP (XEXP (set, 1), 1)) == pattern)
4944 || ((GET_CODE (XEXP (set, 1)) == IOR
4945 || GET_CODE (XEXP (set, 1)) == XOR)
4946 && GET_CODE (XEXP (XEXP (set, 1), 1)) == CONST_INT
4947 && INTVAL (XEXP (XEXP (set, 1), 1)) == 0x00))
4949 /* We've found an AND with all 1's, an XOR with all 0's or an
4951 rtx remove_insn = insn;
4953 /* Is it completely redundant or should it become a move insn? */
4954 if (! rtx_equal_p (XEXP (set, 0), XEXP (XEXP (set, 1), 0)))
4956 emit_insn_before (gen_rtx_SET (mode,
4958 XEXP (XEXP (set, 1), 0)),
4962 insn = prev_nonnote_insn(insn);
4963 delete_insn (remove_insn);
4965 else if (GET_CODE (XEXP (set, 1)) == AND
4966 && GET_CODE (XEXP (XEXP (set, 1), 1)) == CONST_INT
4967 && INTVAL (XEXP (XEXP (set, 1), 1)) == 0)
4969 /* We've found an AND with all 0's. */
4970 rtx remove_insn = insn;
4971 insn = emit_insn_before (gen_rtx_SET (mode,
4973 XEXP (XEXP (set, 1), 1)),
4975 delete_insn (remove_insn);
4980 /* Structure used to track jump targets. */
4982 struct we_jump_targets
4984 int target; /* Is this a jump target? */
4985 int reach_count; /* Number of ways we can reach this insn. */
4986 int touch_count; /* Number of times we've touched this insn
4988 rtx w_equiv; /* WREG-equivalence at this point. */
4991 struct we_jump_targets *ip2k_we_jump_targets;
4993 /* WREG equivalence tracking used within DP reload elimination. */
4996 track_w_reload (insn, w_current, w_current_ok, modifying)
5004 if (GET_CODE (insn) != INSN)
5006 *w_current = NULL_RTX;
5010 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
5011 if (set == NULL_RTX)
5013 *w_current = NULL_RTX;
5017 /* Look for W being modified. If it is, see if it's being changed
5018 to what it already is! */
5019 if (GET_CODE (XEXP (set, 0)) == REG
5020 && REGNO (XEXP (set, 0)) == REG_W
5021 && GET_MODE (XEXP (set, 0)) == QImode)
5023 /* If this is an equivalence we can delete the new set operation. */
5024 if (*w_current != NULL_RTX
5025 && rtx_equal_p (XEXP (set, 1), *w_current))
5032 *w_current = XEXP (set, 1);
5036 else if (recog_memoized (insn) < 0
5037 || get_attr_clobberw (insn) != CLOBBERW_NO)
5039 /* If we clobber W then we've clobbered any equivalences ! */
5040 *w_current = NULL_RTX;
5043 else if (! ip2k_xexp_not_uses_reg_p (XEXP (set, 0), REG_SP, 2)
5044 && *w_current != NULL_RTX
5045 && !ip2k_xexp_not_uses_reg_p (*w_current, REG_SP, 2))
5047 /* We look for a special case of "push" operations screwing up the
5048 setting of DP when it's based on the stack. We can track this one
5049 and replace the old expression for DP with a new one. */
5050 if (GET_CODE (XEXP (set, 0)) == MEM
5051 && GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC
5052 && GET_CODE (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG
5053 && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP
5054 && GET_CODE (*w_current) == MEM
5055 && GET_CODE (XEXP (*w_current, 0)) == PLUS)
5057 /* XXX - need to ensure that we can track this without going
5059 rtx val = GEN_INT (INTVAL (XEXP (XEXP (*w_current, 0), 1))
5060 + GET_MODE_SIZE (GET_MODE (XEXP (set, 0))));
5062 = gen_rtx_MEM (HImode, gen_rtx_PLUS (Pmode,
5063 gen_rtx_REG(HImode, REG_SP),
5068 else if (GET_CODE (XEXP (set, 0)) == REG
5069 && *w_current != NULL_RTX
5070 && !ip2k_xexp_not_uses_reg_p (*w_current, REGNO (XEXP (set, 0)),
5071 GET_MODE_SIZE (GET_MODE (XEXP (set
5074 /* If we've just clobbered all or part of a register reference that we
5075 were sharing for W then we can't share it any more! */
5076 *w_current = NULL_RTX;
5079 return w_current_ok;
5082 /* As part of the machine-dependent reorg we scan moves into w and track them
5083 to see where any are redundant. */
5086 mdr_try_wreg_elim (first_insn)
5090 struct we_jump_targets *wjt;
5092 int incomplete_scan;
5093 int last_incomplete_scan;
5095 ip2k_we_jump_targets
5096 = (struct we_jump_targets *) xcalloc (get_max_uid (),
5097 sizeof (struct we_jump_targets));
5099 /* First we scan to build up a list of all CODE_LABEL insns and we work out
5100 how many different ways we can reach them. */
5101 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
5103 if (GET_CODE (insn) == CODE_LABEL)
5105 wjt = &ip2k_we_jump_targets[INSN_UID (insn)];
5107 wjt->reach_count = LABEL_NUSES (insn);
5108 wjt->touch_count = 0;
5109 wjt->w_equiv = NULL_RTX;
5110 if (! prev_nonnote_insn (insn)
5111 || (prev_nonnote_insn (insn)
5112 && GET_CODE (prev_nonnote_insn (insn)) != BARRIER))
5117 /* Next we scan all of the ways of reaching the code labels to see
5118 what the WREG register is equivalent to as we reach them. If we find
5119 that they're the same then we keep noting the matched value. We
5120 iterate around this until we reach a convergence on WREG equivalences
5121 at all code labels - we have to be very careful not to be too
5123 incomplete_scan = -1;
5126 int w_current_ok = 0;
5127 last_incomplete_scan = incomplete_scan;
5128 w_current = NULL_RTX;
5130 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
5132 /* If we have a code label then we need to see if we already know
5133 what the equivalence is at this point. If we do then we use it
5134 immediately, but if we don't then we have a special case to track
5135 when we hit a fallthrough-edge (label with no barrier preceding
5136 it). Any other accesses to the label must be from jump insns
5137 and so they're handled elsewhere. */
5138 if (GET_CODE (insn) == CODE_LABEL)
5140 wjt = &ip2k_we_jump_targets[INSN_UID (insn)];
5142 /* If we're fully characterized the use the equivalence. */
5143 if (wjt->touch_count == wjt->reach_count)
5145 w_current = wjt->w_equiv;
5150 /* If we have a known equivalence for WREG as we reach the
5151 fallthrough-edge then track this into the code label. */
5153 && (! prev_nonnote_insn (insn)
5154 || (prev_nonnote_insn (insn)
5155 && GET_CODE (prev_nonnote_insn (insn)) != BARRIER)))
5157 if (wjt->touch_count == 0)
5158 wjt->w_equiv = w_current;
5160 if (wjt->touch_count < wjt->reach_count)
5163 if (! rtx_equal_p (wjt->w_equiv, w_current))
5165 /* When we definitely know that we can't form an
5166 equivalence for WREG here we must clobber anything
5167 that we'd started to track too. */
5168 wjt->w_equiv = NULL_RTX;
5169 w_current = NULL_RTX;
5175 /* If we've not completely characterized this code label then
5176 be cautious and assume that we don't know what WREG is
5178 if (wjt->touch_count < wjt->reach_count)
5180 w_current = NULL_RTX;
5187 /* If we've hit a jump insn then we look for either an address
5188 vector (jump table) or for jump label references. */
5189 if (GET_CODE (insn) == JUMP_INSN)
5191 /* Don't attempt to track here if we don't have a known
5192 equivalence for WREG at this point. */
5195 if (JUMP_LABEL (insn))
5198 = &ip2k_we_jump_targets[INSN_UID (JUMP_LABEL (insn))];
5200 if (wjt->touch_count == 0)
5201 wjt->w_equiv = w_current;
5203 if (wjt->touch_count < wjt->reach_count)
5206 if (! rtx_equal_p (wjt->w_equiv, w_current))
5207 wjt->w_equiv = NULL_RTX;
5215 /* Anything other than a code labal or jump arrives here. We try and
5216 track WREG, but sometimes we might not be able to. */
5217 w_current_ok = track_w_reload (insn, &w_current, w_current_ok, 0);
5220 /* When we're looking to see if we've finished we count the number of
5221 paths throught the code labels where we weren't able to definitively
5222 track WREG. This number is used to see if we're converging on a
5224 If this hits zero then we've fully converged, but if this stays the
5225 same as last time then we probably can't make any further
5227 incomplete_scan = 0;
5228 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
5230 if (GET_CODE (insn) == CODE_LABEL)
5232 wjt = &ip2k_we_jump_targets[INSN_UID (insn)];
5233 if (wjt->touch_count != wjt->reach_count)
5235 incomplete_scan += (wjt->reach_count - wjt->touch_count);
5236 wjt->w_equiv = NULL_RTX;
5237 wjt->touch_count = 0;
5242 while (incomplete_scan && incomplete_scan != last_incomplete_scan);
5244 /* Finally we scan the whole function and run WREG elimination. When we hit
5245 a CODE_LABEL we pick up any stored equivalence since we now know that
5246 every path to this point entered with WREG holding the same thing! If
5247 we subsequently have a reload that matches then we can eliminate it. */
5248 w_current = NULL_RTX;
5249 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
5251 if (GET_CODE (insn) == JUMP_INSN)
5254 if (GET_CODE (insn) == CODE_LABEL)
5256 wjt = &ip2k_we_jump_targets[INSN_UID (insn)];
5257 w_current = wjt->w_equiv;
5261 track_w_reload (insn, &w_current, 1, 1);
5264 free (ip2k_we_jump_targets);
5267 /* We perform a lot of untangling of the RTL within the reorg pass since
5268 the IP2k requires some really bizarre (and really undesireable) things
5269 to happen in order to guarantee not aborting. This pass causes several
5270 earlier passes to be re-run as it progressively transforms things,
5271 making the subsequent runs continue to win. */
5274 machine_dependent_reorg (first_insn)
5283 ip2k_reorg_completed = 1;
5284 ip2k_reorg_split_dimode = 1;
5285 ip2k_reorg_split_simode = 1;
5286 ip2k_reorg_split_himode = 1;
5287 ip2k_reorg_split_qimode = 1;
5288 ip2k_reorg_merge_qimode = 1;
5291 #ifndef IP2K_MD_REORG_PASS
5292 ip2k_reorg_completed = 1;
5293 ip2k_reorg_split_dimode = 1;
5294 ip2k_reorg_split_simode = 1;
5295 ip2k_reorg_split_himode = 1;
5296 ip2k_reorg_split_qimode = 1;
5297 ip2k_reorg_merge_qimode = 1;
5299 /* All optimizations below must be debugged and enabled one by one.
5300 All of them commented now because of abort in GCC core. */
5302 ip2k_reorg_in_progress = 1;
5304 /* Look for size effects of earlier optimizations - in particular look for
5305 situations where we're saying "use" a register on one hand but immediately
5306 tagging it as "REG_DEAD" at the same time! Seems like a bug in core-gcc
5307 somewhere really but this is what we have to live with! */
5308 for (insn = first_insn; insn; insn = NEXT_INSN (insn))
5312 if (GET_CODE (insn) == CODE_LABEL
5313 || GET_CODE (insn) == NOTE
5314 || GET_CODE (insn) == BARRIER)
5317 if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
5320 body = PATTERN (insn);
5321 if (GET_CODE (body) == USE)
5322 if (GET_CODE (XEXP (body, 0)) == REG)
5326 reg = REGNO (XEXP (body, 0));
5327 if (find_regno_note (insn, REG_DEAD, reg))
5334 /* There's a good chance that since we last did CSE that we've rearranged
5335 things in such a way that another go will win. Do so now! */
5336 reload_cse_regs (first_insn);
5337 find_basic_blocks (first_insn, max_reg_num (), 0);
5338 life_analysis (first_insn, 0, PROP_REG_INFO | PROP_DEATH_NOTES);
5340 /* Look for where absurd things are happening with DP. */
5341 mdr_try_dp_reload_elim (first_insn);
5343 ip2k_reorg_in_progress = 0;
5344 ip2k_reorg_completed = 1;
5346 split_all_insns (0);
5348 reload_cse_regs (first_insn);
5349 find_basic_blocks (first_insn, max_reg_num (), 0);
5350 life_analysis (first_insn, 0, PROP_REG_INFO | PROP_DEATH_NOTES);
5352 peephole2_optimize (NULL);
5354 mdr_resequence_xy_yx (first_insn);
5355 mdr_propagate_reg_equivs (first_insn);
5357 /* Look for redundant set instructions. These can occur when we split
5358 instruction patterns and end up with the second half merging with
5359 or being replaced by something that clobbers the first half. */
5360 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
5362 if (GET_CODE (insn) == INSN)
5364 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
5365 if ((set != NULL_RTX)
5366 && (GET_CODE (XEXP (set, 0)) == REG)
5367 && (GET_MODE (XEXP (set, 0)) == QImode)
5368 && (find_regno_note (insn, REG_UNUSED, REGNO (XEXP (set, 0)))))
5373 mdr_try_move_dp_reload (first_insn);
5374 mdr_try_move_pushes (first_insn);
5376 find_basic_blocks (first_insn, max_reg_num (), 0);
5377 life_analysis (first_insn, 0, PROP_FINAL);
5379 mdr_try_propagate_move (first_insn);
5380 mdr_resequence_xy_yx (first_insn);
5382 ip2k_reorg_split_dimode = 1;
5383 split_all_insns (0);
5385 mdr_try_remove_redundant_insns (first_insn);
5387 mdr_try_propagate_move (first_insn);
5389 reload_cse_regs (first_insn);
5390 find_basic_blocks (first_insn, max_reg_num (), 0);
5391 life_analysis (first_insn, 0, PROP_FINAL);
5393 peephole2_optimize (NULL);
5395 mdr_try_propagate_move (first_insn);
5397 find_basic_blocks (first_insn, max_reg_num (), 0);
5398 life_analysis (first_insn, 0, PROP_FINAL);
5400 ip2k_reorg_split_simode = 1;
5401 split_all_insns (0);
5403 mdr_try_remove_redundant_insns (first_insn);
5405 mdr_try_propagate_move (first_insn);
5407 reload_cse_regs (first_insn);
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);
5418 ip2k_reorg_split_himode = 1;
5419 ip2k_reorg_merge_qimode = 1;
5420 split_all_insns (0);
5422 mdr_try_remove_redundant_insns (first_insn);
5423 mdr_try_propagate_clr (first_insn);
5424 mdr_try_propagate_move (first_insn);
5426 mdr_try_dp_reload_elim (first_insn);
5427 mdr_try_move_dp_reload (first_insn);
5429 rebuild_jump_labels (first_insn);
5431 /* Call to jump_optimize (...) was here, but now I removed it. */
5433 find_basic_blocks (first_insn, max_reg_num (), 0);
5434 life_analysis (first_insn, 0, PROP_FINAL);
5436 peephole2_optimize (NULL);
5438 mdr_try_propagate_move (first_insn);
5440 find_basic_blocks (first_insn, max_reg_num (), 0);
5441 life_analysis (first_insn, 0, PROP_FINAL);
5442 mdr_try_remove_redundant_insns (first_insn);
5444 mdr_try_propagate_clr (first_insn);
5445 mdr_try_propagate_move (first_insn);
5447 find_basic_blocks (first_insn, max_reg_num (), 0);
5448 life_analysis (first_insn, 0, PROP_FINAL);
5450 ip2k_reorg_split_qimode = 1;
5451 split_all_insns (0);
5453 mdr_try_wreg_elim (first_insn);
5454 mdr_try_propagate_move (first_insn);
5456 find_basic_blocks (first_insn, max_reg_num (), 0);
5457 life_analysis (first_insn, 0, PROP_FINAL);
5461 /* Returns a bit position if mask contains only a single bit. Returns -1 if
5462 there were zero or more than one set bits. */
5464 find_one_set_bit_p (mask)
5468 unsigned HOST_WIDE_INT n = mask;
5469 for (i = 0; i < 32; i++)
5471 if (n & 0x80000000UL)
5473 if (n & 0x7fffffffUL)
5483 /* Returns a bit position if mask contains only a single clear bit.
5484 Returns -1 if there were zero or more than one clear bits. */
5486 find_one_clear_bit_p (mask)
5490 unsigned HOST_WIDE_INT n = mask;
5491 for (i = 0; i < 32; i++)
5493 if ((n & 0x80000000UL) == 0UL)
5495 if ((n & 0x7fffffffUL) != 0x7fffffffUL)
5507 /* Split a move into two smaller pieces.
5508 MODE indicates the reduced mode. OPERANDS[0] is the original destination
5509 OPERANDS[1] is the original src. The new destinations are
5510 OPERANDS[2] and OPERANDS[4], while the new sources are OPERANDS[3]
5514 ip2k_split_words (nmode, omode, operands)
5515 enum machine_mode nmode;
5516 enum machine_mode omode;
5519 rtx dl, dh; /* src/dest pieces. */
5521 int move_high_first = 0; /* Assume no overlap. */
5524 switch (GET_CODE (operands[0])) /* DEST */
5528 if ((GET_CODE (operands[1]) == REG
5529 || GET_CODE (operands[1]) == SUBREG)
5530 && (true_regnum (operands[0]) <= true_regnum (operands[1])
5531 || (true_regnum (operands[1])
5532 + GET_MODE_SIZE (omode) - 1 < true_regnum (operands[0]))))
5533 move_high_first = 1;
5535 if (GET_CODE (operands[0]) == SUBREG)
5537 dl = simplify_gen_subreg (nmode, operands[0], omode,
5538 GET_MODE_SIZE (nmode));
5539 dh = simplify_gen_subreg (nmode, operands[0], omode, 0);
5541 else if (GET_CODE (operands[0]) == REG && ! IS_PSEUDO_P (operands[0]))
5543 int r = REGNO (operands[0]);
5544 dh = gen_rtx_REG (nmode, r);
5545 dl = gen_rtx_REG (nmode, r + HARD_REGNO_NREGS (r, nmode));
5549 dh = gen_rtx_SUBREG (nmode, operands[0], 0);
5550 dl = gen_rtx_SUBREG (nmode, operands[0], GET_MODE_SIZE (nmode));
5555 switch (GET_CODE (XEXP (operands[0], 0)))
5560 dl = dh = gen_rtx_MEM (nmode, XEXP (operands[0], 0));
5564 dl = change_address (operands[0], nmode,
5565 plus_constant (XEXP (operands[0], 0),
5566 GET_MODE_SIZE (nmode)));
5567 dh = gen_rtx_MEM (nmode, XEXP (operands[0], 0));
5574 switch (GET_CODE (operands[1]))
5577 if (! IS_PSEUDO_P (operands[1]))
5579 int r = REGNO (operands[1]);
5581 sh = gen_rtx_REG (nmode, r);
5582 sl = gen_rtx_REG (nmode, r + HARD_REGNO_NREGS (r, nmode));
5586 sh = gen_rtx_SUBREG (nmode, operands[1], 0);
5587 sl = gen_rtx_SUBREG (nmode, operands[1], GET_MODE_SIZE (nmode));
5592 if (operands[1] == const0_rtx)
5593 sh = sl = const0_rtx;
5596 if (GET_MODE (operands[0]) != DImode)
5601 REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
5602 REAL_VALUE_TO_TARGET_SINGLE (rv, value);
5604 sh = gen_int_mode ((value >> 16) & 0xffff, nmode);
5605 sl = gen_int_mode (value & 0xffff, nmode);
5609 sh = gen_int_mode (CONST_DOUBLE_HIGH (operands[1]), nmode);
5610 sl = gen_int_mode (CONST_DOUBLE_LOW (operands[1]), nmode);
5616 if (operands[1] == const0_rtx)
5617 sh = sl = const0_rtx;
5620 int val = INTVAL (operands[1]);
5626 vh = (val >> 8) & 0xff;
5631 vh = (val >> 16) & 0xffff;
5636 if (val < 0) /* sign extend */
5640 vl = val; /* Give low 32 bits back. */
5647 sl = gen_int_mode (vl, nmode);
5648 sh = gen_int_mode (vh, nmode);
5653 sl = simplify_gen_subreg (nmode, operands[1], omode,
5654 GET_MODE_SIZE (nmode));
5655 sh = simplify_gen_subreg (nmode, operands[1], omode, 0);
5659 switch (GET_CODE (XEXP (operands[1], 0)))
5667 /* Worry about splitting stack pushes. */
5668 if (pushflag && ip2k_address_uses_reg_p (operands[1], REG_SP))
5669 sl = sh = change_address (operands[1], nmode,
5670 plus_constant (XEXP (operands[1], 0),
5671 GET_MODE_SIZE (nmode)));
5674 sl = change_address (operands[1], nmode,
5675 plus_constant (XEXP (operands[1], 0),
5676 GET_MODE_SIZE (nmode)));
5677 sh = gen_rtx_MEM (nmode, XEXP (operands[1], 0));
5686 if (move_high_first)
5703 /* Get the low half of an operand. */
5705 ip2k_get_low_half (x, mode)
5707 enum machine_mode mode;
5709 switch (GET_CODE (x))
5712 if (! IS_PSEUDO_P (x))
5714 unsigned int r = REGNO (x);
5716 return gen_rtx_REG (mode, r + HARD_REGNO_NREGS (r, mode));
5720 return gen_rtx_SUBREG (mode, x, GET_MODE_SIZE (mode));
5725 if (x == const0_rtx)
5734 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
5735 REAL_VALUE_TO_TARGET_SINGLE (rv, value);
5737 return gen_int_mode (value & 0xffff, mode);
5740 return gen_int_mode (CONST_DOUBLE_LOW (x), mode);
5745 if (x == const0_rtx)
5749 int val = INTVAL (x);
5755 vh = (val >> 8) & 0xff;
5760 vh = (val >> 16) & 0xffff;
5765 if (val < 0) /* sign extend */
5769 vl = val; /* Give low 32 bits back. */
5776 return gen_int_mode (vl, mode);
5781 return simplify_gen_subreg (mode, x, GET_MODE (x), GET_MODE_SIZE (mode));
5784 switch (GET_CODE (XEXP (x, 0)))
5792 return change_address (x, mode,
5793 plus_constant (XEXP (x, 0),
5794 GET_MODE_SIZE (mode)));
5804 /* Get the high half of an operand. */
5806 ip2k_get_high_half (x, mode)
5808 enum machine_mode mode;
5810 switch (GET_CODE (x))
5813 if (! IS_PSEUDO_P (x))
5815 unsigned int r = REGNO (x);
5817 return gen_rtx_REG (mode, r);
5821 return gen_rtx_SUBREG (mode, x, 0);
5826 if (x == const0_rtx)
5835 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
5836 REAL_VALUE_TO_TARGET_SINGLE (rv, value);
5838 return gen_int_mode ((value >> 16) & 0xffff, mode);
5841 return gen_int_mode (CONST_DOUBLE_HIGH (x), mode);
5846 if (x == const0_rtx)
5850 int val = INTVAL (x);
5856 vh = (val >> 8) & 0xff;
5861 vh = (val >> 16) & 0xffff;
5866 if (val < 0) /* sign extend */
5870 vl = val; /* Give low 32 bits back. */
5877 return gen_int_mode (vh, mode);
5882 return simplify_gen_subreg (mode, x, GET_MODE (x), 0);
5886 switch (GET_CODE (XEXP (x, 0)))
5894 return change_address (x, mode, plus_constant (XEXP (x, 0), 0));
5904 /* Does address X use register R. Only valid for REG_SP, REG_DP, REG_IP
5908 ip2k_address_uses_reg_p (x, r)
5912 if (GET_CODE (x) != MEM)
5918 switch (GET_CODE (x))
5928 if (ip2k_address_uses_reg_p (XEXP (x, 1), r))
5935 /* Ignore subwords. */
5940 /* Have to consider that r might be LSB of a pointer reg. */
5941 return ((REGNO (x) == r) || (REGNO (x) == (r - 1))) ? 1 : 0;
5944 /* We might be looking at a (mem:BLK (mem (...))) */
5953 /* Does the queried XEXP not use a particular register? If we're certain
5954 that it doesn't then we return TRUE otherwise we assume FALSE. */
5957 ip2k_xexp_not_uses_reg_p (x, r, rsz)
5962 switch (GET_CODE (x))
5966 int msz = GET_MODE_SIZE (GET_MODE (x));
5968 return (((REGNO (x) + msz - 1) < r)
5969 || (REGNO (x) > (r + rsz - 1)));
5973 return !ip2k_address_uses_reg_p (x, r);
5989 /* Does the queried XEXP not use a particular register? If we're certain
5990 that it doesn't then we return TRUE otherwise we assume FALSE. */
5993 ip2k_composite_xexp_not_uses_reg_p (x, r, rsz)
5998 if (GET_RTX_CLASS (GET_CODE (x)) == 'b')
5999 return (ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 0), r, rsz)
6000 && ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 1), r, rsz)
6001 && ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 2), r, rsz));
6003 if (GET_RTX_CLASS (GET_CODE (x)) == '2'
6004 || GET_RTX_CLASS (GET_CODE (x)) == 'c'
6005 || GET_RTX_CLASS (GET_CODE (x)) == '<')
6006 return (ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 0), r, rsz)
6007 && ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 1), r, rsz));
6009 if (GET_RTX_CLASS (GET_CODE (x)) == '1'
6010 || GET_RTX_CLASS (GET_CODE (x)) == '3')
6011 return ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 0), r, rsz);
6013 return ip2k_xexp_not_uses_reg_p (x, r, rsz);
6016 /* Does the queried XEXP not use CC0? If we're certain that
6017 it doesn't then we return TRUE otherwise we assume FALSE. */
6020 ip2k_composite_xexp_not_uses_cc0_p (x)
6023 if (GET_RTX_CLASS (GET_CODE (x)) == 'b')
6024 return (ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 0))
6025 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 1))
6026 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 2)));
6028 if (GET_RTX_CLASS (GET_CODE (x)) == '2'
6029 || GET_RTX_CLASS (GET_CODE (x)) == 'c'
6030 || GET_RTX_CLASS (GET_CODE (x)) == '<')
6031 return (ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 0))
6032 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 1)));
6034 if (GET_RTX_CLASS (GET_CODE (x)) == '1'
6035 || GET_RTX_CLASS (GET_CODE (x)) == '3')
6036 return ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 0));
6038 return GET_CODE (x) != CC0;
6042 ip2k_split_dest_operand (x, mode)
6044 enum machine_mode mode;
6046 return nonimmediate_operand (x, mode) || push_operand (x, mode);
6050 ip2k_nonptr_operand (x, mode)
6052 enum machine_mode mode;
6054 return register_operand (x, mode) && !ip2k_ptr_operand (x, mode);
6057 /* Is X a reference to IP or DP or SP? */
6060 ip2k_ptr_operand (x, mode)
6062 enum machine_mode mode;
6065 if (GET_CODE (x) == SUBREG)
6069 && (mode == HImode || mode == VOIDmode)
6070 && (REGNO (x) == REG_IP
6071 || REGNO (x) == REG_DP
6072 || REGNO (x) == REG_SP));
6076 ip2k_sp_operand (x, mode)
6078 enum machine_mode mode ATTRIBUTE_UNUSED;
6081 return REG_P (x) && REGNO (x) == REG_SP;
6085 ip2k_ip_operand (x, mode)
6087 enum machine_mode mode;
6090 if (GET_CODE (x) != MEM)
6095 if (GET_CODE (x) == PLUS && XEXP (x, 1) == const0_rtx)
6101 if (GET_MODE_SIZE (mode) > 1)
6102 return 0; /* Can't access offset bytes. */
6104 return REGNO (x) == REG_IP;
6107 /* Is X a memory address suitable for SP or DP relative addressing? */
6109 ip2k_short_operand (x, mode)
6111 enum machine_mode mode;
6114 unsigned int offs = 0;
6116 if (! memory_operand (x, mode))
6117 return 0; /* Got to be a memory address. */
6120 switch (GET_CODE (x))
6126 if (! REG_P (XEXP (x, 0))
6127 || GET_CODE (XEXP (x, 1)) != CONST_INT)
6130 offs = INTVAL (XEXP (x, 1));
6140 if (IS_PSEUDO_P (x))
6141 return 0; /* Optimistic - doesn't work. */
6145 /* For 'S' constraint, we presume that no IP adjustment
6146 simulation is performed - so only QI mode allows IP to be a
6147 short offset address. All other IP references must be
6148 handled by 'R' constraints. */
6149 if (r == REG_IP && offs == 0 && GET_MODE_SIZE (mode) <= 1)
6152 return (r == REG_SP || r == REG_DP);
6157 ip2k_nonsp_reg_operand (x, mode)
6159 enum machine_mode mode ATTRIBUTE_UNUSED;
6161 if (GET_CODE (x) == SUBREG)
6164 return (REG_P (x) && REGNO (x) != REG_SP);
6168 ip2k_gen_operand (x, mode)
6170 enum machine_mode mode;
6172 return ip2k_short_operand (x, mode)
6173 || (GET_CODE (x) == SUBREG
6174 && REG_P (SUBREG_REG (x)))
6175 || (ip2k_nonsp_reg_operand (x, mode));
6179 ip2k_extra_constraint (x, c)
6185 case 'S': /* Allow offset in stack frame... */
6186 return ip2k_short_operand (x, GET_MODE (x));
6189 return ip2k_ip_operand (x, GET_MODE (x));
6191 case 'T': /* Constant int or .data address. */
6192 return CONSTANT_P (x) && is_regfile_address (x);
6200 ip2k_unary_operator (op, mode)
6202 enum machine_mode mode;
6204 return ((mode == VOIDmode || GET_MODE (op) == mode)
6205 && GET_RTX_CLASS (GET_CODE (op)) == '1');
6209 ip2k_binary_operator (op, mode)
6211 enum machine_mode mode;
6213 return ((mode == VOIDmode || GET_MODE (op) == mode)
6214 && (GET_RTX_CLASS (GET_CODE (op)) == 'c'
6215 || GET_RTX_CLASS (GET_CODE (op)) == '2'));
6219 ip2k_symbol_ref_operand (op, mode)
6221 enum machine_mode mode ATTRIBUTE_UNUSED;
6223 /* We define an IP2k symbol ref to be either a direct reference or one
6224 with a constant offset. */
6225 return (GET_CODE (op) == SYMBOL_REF)
6226 || (GET_CODE (op) == CONST
6227 && GET_CODE (XEXP (op, 0)) == PLUS
6228 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF);
6232 ip2k_signed_comparison_operator (op, mode)
6234 enum machine_mode mode;
6236 return (comparison_operator (op, mode)
6237 && signed_condition (GET_CODE (op)) == GET_CODE (op));
6241 ip2k_unsigned_comparison_operator (op, mode)
6243 enum machine_mode mode;
6245 return (comparison_operator (op, mode)
6246 && unsigned_condition (GET_CODE (op)) == GET_CODE (op));