Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/xtensa/xtensa.c @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | a06113de4d67 |
children | b7f97abdc517 |
comparison
equal
deleted
inserted
replaced
52:c156f1bd5cd9 | 55:77e2b8dfacca |
---|---|
1 /* Subroutines for insn-output.c for Tensilica's Xtensa architecture. | 1 /* Subroutines for insn-output.c for Tensilica's Xtensa architecture. |
2 Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 | 2 Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 |
3 Free Software Foundation, Inc. | 3 Free Software Foundation, Inc. |
4 Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica. | 4 Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica. |
5 | 5 |
6 This file is part of GCC. | 6 This file is part of GCC. |
7 | 7 |
69 ITEST_LTU, | 69 ITEST_LTU, |
70 ITEST_LEU, | 70 ITEST_LEU, |
71 ITEST_MAX | 71 ITEST_MAX |
72 }; | 72 }; |
73 | 73 |
74 /* Cached operands, and operator to compare for use in set/branch on | |
75 condition codes. */ | |
76 rtx branch_cmp[2]; | |
77 | |
78 /* what type of branch to use */ | |
79 enum cmp_type branch_type; | |
80 | |
81 /* Array giving truth value on whether or not a given hard register | 74 /* Array giving truth value on whether or not a given hard register |
82 can support a given mode. */ | 75 can support a given mode. */ |
83 char xtensa_hard_regno_mode_ok[(int) MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER]; | 76 char xtensa_hard_regno_mode_ok[(int) MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER]; |
84 | 77 |
85 /* Current frame size calculated by compute_frame_size. */ | 78 /* Current frame size calculated by compute_frame_size. */ |
87 | 80 |
88 /* Largest block move to handle in-line. */ | 81 /* Largest block move to handle in-line. */ |
89 #define LARGEST_MOVE_RATIO 15 | 82 #define LARGEST_MOVE_RATIO 15 |
90 | 83 |
91 /* Define the structure for the machine field in struct function. */ | 84 /* Define the structure for the machine field in struct function. */ |
92 struct machine_function GTY(()) | 85 struct GTY(()) machine_function |
93 { | 86 { |
94 int accesses_prev_frame; | 87 int accesses_prev_frame; |
95 bool need_a7_copy; | 88 bool need_a7_copy; |
96 bool vararg_a7; | 89 bool vararg_a7; |
97 rtx vararg_a7_copy; | 90 rtx vararg_a7_copy; |
126 }; | 119 }; |
127 | 120 |
128 static enum internal_test map_test_to_internal_test (enum rtx_code); | 121 static enum internal_test map_test_to_internal_test (enum rtx_code); |
129 static rtx gen_int_relational (enum rtx_code, rtx, rtx, int *); | 122 static rtx gen_int_relational (enum rtx_code, rtx, rtx, int *); |
130 static rtx gen_float_relational (enum rtx_code, rtx, rtx); | 123 static rtx gen_float_relational (enum rtx_code, rtx, rtx); |
131 static rtx gen_conditional_move (rtx); | 124 static rtx gen_conditional_move (enum rtx_code, enum machine_mode, rtx, rtx); |
132 static rtx fixup_subreg_mem (rtx); | 125 static rtx fixup_subreg_mem (rtx); |
133 static struct machine_function * xtensa_init_machine_status (void); | 126 static struct machine_function * xtensa_init_machine_status (void); |
134 static rtx xtensa_legitimize_tls_address (rtx); | 127 static rtx xtensa_legitimize_tls_address (rtx); |
128 static rtx xtensa_legitimize_address (rtx, rtx, enum machine_mode); | |
135 static bool xtensa_return_in_msb (const_tree); | 129 static bool xtensa_return_in_msb (const_tree); |
136 static void printx (FILE *, signed int); | 130 static void printx (FILE *, signed int); |
137 static void xtensa_function_epilogue (FILE *, HOST_WIDE_INT); | 131 static void xtensa_function_epilogue (FILE *, HOST_WIDE_INT); |
138 static rtx xtensa_builtin_saveregs (void); | 132 static rtx xtensa_builtin_saveregs (void); |
133 static bool xtensa_legitimate_address_p (enum machine_mode, rtx, bool); | |
139 static unsigned int xtensa_multibss_section_type_flags (tree, const char *, | 134 static unsigned int xtensa_multibss_section_type_flags (tree, const char *, |
140 int) ATTRIBUTE_UNUSED; | 135 int) ATTRIBUTE_UNUSED; |
141 static section *xtensa_select_rtx_section (enum machine_mode, rtx, | 136 static section *xtensa_select_rtx_section (enum machine_mode, rtx, |
142 unsigned HOST_WIDE_INT); | 137 unsigned HOST_WIDE_INT); |
143 static bool xtensa_rtx_costs (rtx, int, int, int *, bool); | 138 static bool xtensa_rtx_costs (rtx, int, int, int *, bool); |
148 static rtx xtensa_function_value (const_tree, const_tree, bool); | 143 static rtx xtensa_function_value (const_tree, const_tree, bool); |
149 static void xtensa_init_builtins (void); | 144 static void xtensa_init_builtins (void); |
150 static tree xtensa_fold_builtin (tree, tree, bool); | 145 static tree xtensa_fold_builtin (tree, tree, bool); |
151 static rtx xtensa_expand_builtin (tree, rtx, rtx, enum machine_mode, int); | 146 static rtx xtensa_expand_builtin (tree, rtx, rtx, enum machine_mode, int); |
152 static void xtensa_va_start (tree, rtx); | 147 static void xtensa_va_start (tree, rtx); |
148 static bool xtensa_frame_pointer_required (void); | |
149 static rtx xtensa_static_chain (const_tree, bool); | |
150 static void xtensa_asm_trampoline_template (FILE *); | |
151 static void xtensa_trampoline_init (rtx, tree, rtx); | |
153 | 152 |
154 static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] = | 153 static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] = |
155 REG_ALLOC_ORDER; | 154 REG_ALLOC_ORDER; |
156 | 155 |
157 | 156 |
173 #define TARGET_ASM_SELECT_RTX_SECTION xtensa_select_rtx_section | 172 #define TARGET_ASM_SELECT_RTX_SECTION xtensa_select_rtx_section |
174 | 173 |
175 #undef TARGET_DEFAULT_TARGET_FLAGS | 174 #undef TARGET_DEFAULT_TARGET_FLAGS |
176 #define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT | MASK_FUSED_MADD) | 175 #define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT | MASK_FUSED_MADD) |
177 | 176 |
177 #undef TARGET_LEGITIMIZE_ADDRESS | |
178 #define TARGET_LEGITIMIZE_ADDRESS xtensa_legitimize_address | |
179 | |
178 #undef TARGET_RTX_COSTS | 180 #undef TARGET_RTX_COSTS |
179 #define TARGET_RTX_COSTS xtensa_rtx_costs | 181 #define TARGET_RTX_COSTS xtensa_rtx_costs |
180 #undef TARGET_ADDRESS_COST | 182 #undef TARGET_ADDRESS_COST |
181 #define TARGET_ADDRESS_COST hook_int_rtx_bool_0 | 183 #define TARGET_ADDRESS_COST hook_int_rtx_bool_0 |
182 | 184 |
184 #define TARGET_BUILD_BUILTIN_VA_LIST xtensa_build_builtin_va_list | 186 #define TARGET_BUILD_BUILTIN_VA_LIST xtensa_build_builtin_va_list |
185 | 187 |
186 #undef TARGET_EXPAND_BUILTIN_VA_START | 188 #undef TARGET_EXPAND_BUILTIN_VA_START |
187 #define TARGET_EXPAND_BUILTIN_VA_START xtensa_va_start | 189 #define TARGET_EXPAND_BUILTIN_VA_START xtensa_va_start |
188 | 190 |
189 #undef TARGET_PROMOTE_FUNCTION_ARGS | 191 #undef TARGET_PROMOTE_FUNCTION_MODE |
190 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true | 192 #define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote |
191 #undef TARGET_PROMOTE_FUNCTION_RETURN | |
192 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true | |
193 #undef TARGET_PROMOTE_PROTOTYPES | 193 #undef TARGET_PROMOTE_PROTOTYPES |
194 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true | 194 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true |
195 | 195 |
196 #undef TARGET_RETURN_IN_MEMORY | 196 #undef TARGET_RETURN_IN_MEMORY |
197 #define TARGET_RETURN_IN_MEMORY xtensa_return_in_memory | 197 #define TARGET_RETURN_IN_MEMORY xtensa_return_in_memory |
223 #undef TARGET_HAVE_TLS | 223 #undef TARGET_HAVE_TLS |
224 #define TARGET_HAVE_TLS (TARGET_THREADPTR && HAVE_AS_TLS) | 224 #define TARGET_HAVE_TLS (TARGET_THREADPTR && HAVE_AS_TLS) |
225 | 225 |
226 #undef TARGET_CANNOT_FORCE_CONST_MEM | 226 #undef TARGET_CANNOT_FORCE_CONST_MEM |
227 #define TARGET_CANNOT_FORCE_CONST_MEM xtensa_tls_referenced_p | 227 #define TARGET_CANNOT_FORCE_CONST_MEM xtensa_tls_referenced_p |
228 | |
229 #undef TARGET_LEGITIMATE_ADDRESS_P | |
230 #define TARGET_LEGITIMATE_ADDRESS_P xtensa_legitimate_address_p | |
231 | |
232 #undef TARGET_FRAME_POINTER_REQUIRED | |
233 #define TARGET_FRAME_POINTER_REQUIRED xtensa_frame_pointer_required | |
234 | |
235 #undef TARGET_STATIC_CHAIN | |
236 #define TARGET_STATIC_CHAIN xtensa_static_chain | |
237 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE | |
238 #define TARGET_ASM_TRAMPOLINE_TEMPLATE xtensa_asm_trampoline_template | |
239 #undef TARGET_TRAMPOLINE_INIT | |
240 #define TARGET_TRAMPOLINE_INIT xtensa_trampoline_init | |
228 | 241 |
229 struct gcc_target targetm = TARGET_INITIALIZER; | 242 struct gcc_target targetm = TARGET_INITIALIZER; |
230 | 243 |
231 | 244 |
232 /* Functions to test Xtensa immediate operand validity. */ | 245 /* Functions to test Xtensa immediate operand validity. */ |
706 return gen_rtx_fmt_ee (invert ? EQ : NE, VOIDmode, brtmp, const0_rtx); | 719 return gen_rtx_fmt_ee (invert ? EQ : NE, VOIDmode, brtmp, const0_rtx); |
707 } | 720 } |
708 | 721 |
709 | 722 |
710 void | 723 void |
711 xtensa_expand_conditional_branch (rtx *operands, enum rtx_code test_code) | 724 xtensa_expand_conditional_branch (rtx *operands, enum machine_mode mode) |
712 { | 725 { |
713 enum cmp_type type = branch_type; | 726 enum rtx_code test_code = GET_CODE (operands[0]); |
714 rtx cmp0 = branch_cmp[0]; | 727 rtx cmp0 = operands[1]; |
715 rtx cmp1 = branch_cmp[1]; | 728 rtx cmp1 = operands[2]; |
716 rtx cmp; | 729 rtx cmp; |
717 int invert; | 730 int invert; |
718 rtx label1, label2; | 731 rtx label1, label2; |
719 | 732 |
720 switch (type) | 733 switch (mode) |
721 { | 734 { |
722 case CMP_DF: | 735 case DFmode: |
723 default: | 736 default: |
724 fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1)); | 737 fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1)); |
725 | 738 |
726 case CMP_SI: | 739 case SImode: |
727 invert = FALSE; | 740 invert = FALSE; |
728 cmp = gen_int_relational (test_code, cmp0, cmp1, &invert); | 741 cmp = gen_int_relational (test_code, cmp0, cmp1, &invert); |
729 break; | 742 break; |
730 | 743 |
731 case CMP_SF: | 744 case SFmode: |
732 if (!TARGET_HARD_FLOAT) | 745 if (!TARGET_HARD_FLOAT) |
733 fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode, | 746 fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode, |
734 cmp0, cmp1)); | 747 cmp0, cmp1)); |
735 invert = FALSE; | 748 invert = FALSE; |
736 cmp = gen_float_relational (test_code, cmp0, cmp1); | 749 cmp = gen_float_relational (test_code, cmp0, cmp1); |
737 break; | 750 break; |
738 } | 751 } |
739 | 752 |
740 /* Generate the branch. */ | 753 /* Generate the branch. */ |
741 | 754 |
742 label1 = gen_rtx_LABEL_REF (VOIDmode, operands[0]); | 755 label1 = gen_rtx_LABEL_REF (VOIDmode, operands[3]); |
743 label2 = pc_rtx; | 756 label2 = pc_rtx; |
744 | 757 |
745 if (invert) | 758 if (invert) |
746 { | 759 { |
747 label2 = label1; | 760 label2 = label1; |
754 label2))); | 767 label2))); |
755 } | 768 } |
756 | 769 |
757 | 770 |
758 static rtx | 771 static rtx |
759 gen_conditional_move (rtx cmp) | 772 gen_conditional_move (enum rtx_code code, enum machine_mode mode, |
760 { | 773 rtx op0, rtx op1) |
761 enum rtx_code code = GET_CODE (cmp); | 774 { |
762 rtx op0 = branch_cmp[0]; | 775 if (mode == SImode) |
763 rtx op1 = branch_cmp[1]; | 776 { |
764 | 777 rtx cmp; |
765 if (branch_type == CMP_SI) | 778 |
766 { | |
767 /* Jump optimization calls get_condition() which canonicalizes | 779 /* Jump optimization calls get_condition() which canonicalizes |
768 comparisons like (GE x <const>) to (GT x <const-1>). | 780 comparisons like (GE x <const>) to (GT x <const-1>). |
769 Transform those comparisons back to GE, since that is the | 781 Transform those comparisons back to GE, since that is the |
770 comparison supported in Xtensa. We shouldn't have to | 782 comparison supported in Xtensa. We shouldn't have to |
771 transform <LE x const> comparisons, because neither | 783 transform <LE x const> comparisons, because neither |
819 return 0; | 831 return 0; |
820 | 832 |
821 return gen_rtx_fmt_ee (code, VOIDmode, op0, op1); | 833 return gen_rtx_fmt_ee (code, VOIDmode, op0, op1); |
822 } | 834 } |
823 | 835 |
824 if (TARGET_HARD_FLOAT && (branch_type == CMP_SF)) | 836 if (TARGET_HARD_FLOAT && mode == SFmode) |
825 return gen_float_relational (code, op0, op1); | 837 return gen_float_relational (code, op0, op1); |
826 | 838 |
827 return 0; | 839 return 0; |
828 } | 840 } |
829 | 841 |
830 | 842 |
831 int | 843 int |
832 xtensa_expand_conditional_move (rtx *operands, int isflt) | 844 xtensa_expand_conditional_move (rtx *operands, int isflt) |
833 { | 845 { |
834 rtx cmp; | 846 rtx dest = operands[0]; |
847 rtx cmp = operands[1]; | |
848 enum machine_mode cmp_mode = GET_MODE (XEXP (cmp, 0)); | |
835 rtx (*gen_fn) (rtx, rtx, rtx, rtx, rtx); | 849 rtx (*gen_fn) (rtx, rtx, rtx, rtx, rtx); |
836 | 850 |
837 if (!(cmp = gen_conditional_move (operands[1]))) | 851 if (!(cmp = gen_conditional_move (GET_CODE (cmp), cmp_mode, |
852 XEXP (cmp, 0), XEXP (cmp, 1)))) | |
838 return 0; | 853 return 0; |
839 | 854 |
840 if (isflt) | 855 if (isflt) |
841 gen_fn = (branch_type == CMP_SI | 856 gen_fn = (cmp_mode == SImode |
842 ? gen_movsfcc_internal0 | 857 ? gen_movsfcc_internal0 |
843 : gen_movsfcc_internal1); | 858 : gen_movsfcc_internal1); |
844 else | 859 else |
845 gen_fn = (branch_type == CMP_SI | 860 gen_fn = (cmp_mode == SImode |
846 ? gen_movsicc_internal0 | 861 ? gen_movsicc_internal0 |
847 : gen_movsicc_internal1); | 862 : gen_movsicc_internal1); |
848 | 863 |
849 emit_insn (gen_fn (operands[0], XEXP (cmp, 0), | 864 emit_insn (gen_fn (dest, XEXP (cmp, 0), operands[2], operands[3], cmp)); |
850 operands[2], operands[3], cmp)); | |
851 return 1; | 865 return 1; |
852 } | 866 } |
853 | 867 |
854 | 868 |
855 int | 869 int |
856 xtensa_expand_scc (rtx *operands) | 870 xtensa_expand_scc (rtx operands[4], enum machine_mode cmp_mode) |
857 { | 871 { |
858 rtx dest = operands[0]; | 872 rtx dest = operands[0]; |
859 rtx cmp = operands[1]; | 873 rtx cmp; |
860 rtx one_tmp, zero_tmp; | 874 rtx one_tmp, zero_tmp; |
861 rtx (*gen_fn) (rtx, rtx, rtx, rtx, rtx); | 875 rtx (*gen_fn) (rtx, rtx, rtx, rtx, rtx); |
862 | 876 |
863 if (!(cmp = gen_conditional_move (cmp))) | 877 if (!(cmp = gen_conditional_move (GET_CODE (operands[1]), cmp_mode, |
878 operands[2], operands[3]))) | |
864 return 0; | 879 return 0; |
865 | 880 |
866 one_tmp = gen_reg_rtx (SImode); | 881 one_tmp = gen_reg_rtx (SImode); |
867 zero_tmp = gen_reg_rtx (SImode); | 882 zero_tmp = gen_reg_rtx (SImode); |
868 emit_insn (gen_movsi (one_tmp, const_true_rtx)); | 883 emit_insn (gen_movsi (one_tmp, const_true_rtx)); |
869 emit_insn (gen_movsi (zero_tmp, const0_rtx)); | 884 emit_insn (gen_movsi (zero_tmp, const0_rtx)); |
870 | 885 |
871 gen_fn = (branch_type == CMP_SI | 886 gen_fn = (cmp_mode == SImode |
872 ? gen_movsicc_internal0 | 887 ? gen_movsicc_internal0 |
873 : gen_movsicc_internal1); | 888 : gen_movsicc_internal1); |
874 emit_insn (gen_fn (dest, XEXP (cmp, 0), one_tmp, zero_tmp, cmp)); | 889 emit_insn (gen_fn (dest, XEXP (cmp, 0), one_tmp, zero_tmp, cmp)); |
875 return 1; | 890 return 1; |
876 } | 891 } |
1529 | 1544 |
1530 | 1545 |
1531 void | 1546 void |
1532 xtensa_setup_frame_addresses (void) | 1547 xtensa_setup_frame_addresses (void) |
1533 { | 1548 { |
1534 /* Set flag to cause FRAME_POINTER_REQUIRED to be set. */ | 1549 /* Set flag to cause TARGET_FRAME_POINTER_REQUIRED to return true. */ |
1535 cfun->machine->accesses_prev_frame = 1; | 1550 cfun->machine->accesses_prev_frame = 1; |
1536 | 1551 |
1537 emit_library_call | 1552 emit_library_call |
1538 (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_libgcc_window_spill"), | 1553 (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_libgcc_window_spill"), |
1539 0, VOIDmode, 0); | 1554 0, VOIDmode, 0); |
1871 gen_rtx_PLUS (Pmode, plus0, addmi_offset))); | 1886 gen_rtx_PLUS (Pmode, plus0, addmi_offset))); |
1872 return gen_rtx_PLUS (Pmode, temp, GEN_INT (INTVAL (plus1) & 0xff)); | 1887 return gen_rtx_PLUS (Pmode, temp, GEN_INT (INTVAL (plus1) & 0xff)); |
1873 } | 1888 } |
1874 } | 1889 } |
1875 | 1890 |
1876 return NULL_RTX; | 1891 return x; |
1877 } | 1892 } |
1878 | 1893 |
1879 | 1894 |
1880 /* Helper for xtensa_tls_referenced_p. */ | 1895 /* Helper for xtensa_tls_referenced_p. */ |
1881 | 1896 |
2490 + (WINDOW_SIZE * UNITS_PER_WORD)); | 2505 + (WINDOW_SIZE * UNITS_PER_WORD)); |
2491 return xtensa_current_frame_size; | 2506 return xtensa_current_frame_size; |
2492 } | 2507 } |
2493 | 2508 |
2494 | 2509 |
2495 int | 2510 bool |
2496 xtensa_frame_pointer_required (void) | 2511 xtensa_frame_pointer_required (void) |
2497 { | 2512 { |
2498 /* The code to expand builtin_frame_addr and builtin_return_addr | 2513 /* The code to expand builtin_frame_addr and builtin_return_addr |
2499 currently uses the hard_frame_pointer instead of frame_pointer. | 2514 currently uses the hard_frame_pointer instead of frame_pointer. |
2500 This seems wrong but maybe it's necessary for other architectures. | 2515 This seems wrong but maybe it's necessary for other architectures. |
2501 This function is derived from the i386 code. */ | 2516 This function is derived from the i386 code. */ |
2502 | 2517 |
2503 if (cfun->machine->accesses_prev_frame) | 2518 if (cfun->machine->accesses_prev_frame) |
2504 return 1; | 2519 return true; |
2505 | 2520 |
2506 return 0; | 2521 return false; |
2507 } | 2522 } |
2508 | 2523 |
2509 | 2524 |
2510 /* minimum frame = reg save area (4 words) plus static chain (1 word) | 2525 /* minimum frame = reg save area (4 words) plus static chain (1 word) |
2511 and the total number of words must be a multiple of 128 bits. */ | 2526 and the total number of words must be a multiple of 128 bits. */ |
2646 xtensa_build_builtin_va_list (void) | 2661 xtensa_build_builtin_va_list (void) |
2647 { | 2662 { |
2648 tree f_stk, f_reg, f_ndx, record, type_decl; | 2663 tree f_stk, f_reg, f_ndx, record, type_decl; |
2649 | 2664 |
2650 record = (*lang_hooks.types.make_type) (RECORD_TYPE); | 2665 record = (*lang_hooks.types.make_type) (RECORD_TYPE); |
2651 type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record); | 2666 type_decl = build_decl (BUILTINS_LOCATION, |
2652 | 2667 TYPE_DECL, get_identifier ("__va_list_tag"), record); |
2653 f_stk = build_decl (FIELD_DECL, get_identifier ("__va_stk"), | 2668 |
2669 f_stk = build_decl (BUILTINS_LOCATION, | |
2670 FIELD_DECL, get_identifier ("__va_stk"), | |
2654 ptr_type_node); | 2671 ptr_type_node); |
2655 f_reg = build_decl (FIELD_DECL, get_identifier ("__va_reg"), | 2672 f_reg = build_decl (BUILTINS_LOCATION, |
2673 FIELD_DECL, get_identifier ("__va_reg"), | |
2656 ptr_type_node); | 2674 ptr_type_node); |
2657 f_ndx = build_decl (FIELD_DECL, get_identifier ("__va_ndx"), | 2675 f_ndx = build_decl (BUILTINS_LOCATION, |
2676 FIELD_DECL, get_identifier ("__va_ndx"), | |
2658 integer_type_node); | 2677 integer_type_node); |
2659 | 2678 |
2660 DECL_FIELD_CONTEXT (f_stk) = record; | 2679 DECL_FIELD_CONTEXT (f_stk) = record; |
2661 DECL_FIELD_CONTEXT (f_reg) = record; | 2680 DECL_FIELD_CONTEXT (f_reg) = record; |
2662 DECL_FIELD_CONTEXT (f_ndx) = record; | 2681 DECL_FIELD_CONTEXT (f_ndx) = record; |
2843 array = create_tmp_var (ptr_type_node, NULL); | 2862 array = create_tmp_var (ptr_type_node, NULL); |
2844 | 2863 |
2845 lab_over = NULL; | 2864 lab_over = NULL; |
2846 if (!targetm.calls.must_pass_in_stack (TYPE_MODE (type), type)) | 2865 if (!targetm.calls.must_pass_in_stack (TYPE_MODE (type), type)) |
2847 { | 2866 { |
2848 lab_false = create_artificial_label (); | 2867 lab_false = create_artificial_label (UNKNOWN_LOCATION); |
2849 lab_over = create_artificial_label (); | 2868 lab_over = create_artificial_label (UNKNOWN_LOCATION); |
2850 | 2869 |
2851 t = build2 (GT_EXPR, boolean_type_node, unshare_expr (ndx), | 2870 t = build2 (GT_EXPR, boolean_type_node, unshare_expr (ndx), |
2852 build_int_cst (integer_type_node, | 2871 build_int_cst (integer_type_node, |
2853 MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD)); | 2872 MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD)); |
2854 t = build3 (COND_EXPR, void_type_node, t, | 2873 t = build3 (COND_EXPR, void_type_node, t, |
2874 if (orig_ndx <= __MAX_ARGS_IN_REGISTERS * 4) | 2893 if (orig_ndx <= __MAX_ARGS_IN_REGISTERS * 4) |
2875 (AP).__va_ndx = 32 + __va_size (TYPE); | 2894 (AP).__va_ndx = 32 + __va_size (TYPE); |
2876 __array = (AP).__va_stk; | 2895 __array = (AP).__va_stk; |
2877 } */ | 2896 } */ |
2878 | 2897 |
2879 lab_false2 = create_artificial_label (); | 2898 lab_false2 = create_artificial_label (UNKNOWN_LOCATION); |
2880 | 2899 |
2881 t = build2 (GT_EXPR, boolean_type_node, unshare_expr (orig_ndx), | 2900 t = build2 (GT_EXPR, boolean_type_node, unshare_expr (orig_ndx), |
2882 build_int_cst (integer_type_node, | 2901 build_int_cst (integer_type_node, |
2883 MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD)); | 2902 MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD)); |
2884 t = build3 (COND_EXPR, void_type_node, t, | 2903 t = build3 (COND_EXPR, void_type_node, t, |
3416 && TYPE_PRECISION (valtype) < BITS_PER_WORD) | 3435 && TYPE_PRECISION (valtype) < BITS_PER_WORD) |
3417 ? SImode : TYPE_MODE (valtype), | 3436 ? SImode : TYPE_MODE (valtype), |
3418 outgoing ? GP_OUTGOING_RETURN : GP_RETURN); | 3437 outgoing ? GP_OUTGOING_RETURN : GP_RETURN); |
3419 } | 3438 } |
3420 | 3439 |
3440 /* The static chain is passed in memory. Provide rtx giving 'mem' | |
3441 expressions that denote where they are stored. */ | |
3442 | |
3443 static rtx | |
3444 xtensa_static_chain (const_tree ARG_UNUSED (fndecl), bool incoming_p) | |
3445 { | |
3446 rtx base = incoming_p ? arg_pointer_rtx : stack_pointer_rtx; | |
3447 return gen_frame_mem (Pmode, plus_constant (base, -5 * UNITS_PER_WORD)); | |
3448 } | |
3449 | |
3450 | |
3421 /* TRAMPOLINE_TEMPLATE: For Xtensa, the trampoline must perform an ENTRY | 3451 /* TRAMPOLINE_TEMPLATE: For Xtensa, the trampoline must perform an ENTRY |
3422 instruction with a minimal stack frame in order to get some free | 3452 instruction with a minimal stack frame in order to get some free |
3423 registers. Once the actual call target is known, the proper stack frame | 3453 registers. Once the actual call target is known, the proper stack frame |
3424 size is extracted from the ENTRY instruction at the target and the | 3454 size is extracted from the ENTRY instruction at the target and the |
3425 current frame is adjusted to match. The trampoline then transfers | 3455 current frame is adjusted to match. The trampoline then transfers |
3426 control to the instruction following the ENTRY at the target. Note: | 3456 control to the instruction following the ENTRY at the target. Note: |
3427 this assumes that the target begins with an ENTRY instruction. */ | 3457 this assumes that the target begins with an ENTRY instruction. */ |
3428 | 3458 |
3429 void | 3459 static void |
3430 xtensa_trampoline_template (FILE *stream) | 3460 xtensa_asm_trampoline_template (FILE *stream) |
3431 { | 3461 { |
3432 bool use_call0 = (TARGET_CONST16 || TARGET_ABSOLUTE_LITERALS); | 3462 bool use_call0 = (TARGET_CONST16 || TARGET_ABSOLUTE_LITERALS); |
3433 | 3463 |
3434 fprintf (stream, "\t.begin no-transform\n"); | 3464 fprintf (stream, "\t.begin no-transform\n"); |
3435 fprintf (stream, "\tentry\tsp, %d\n", MIN_FRAME_SIZE); | 3465 fprintf (stream, "\tentry\tsp, %d\n", MIN_FRAME_SIZE); |
3492 fprintf (stream, "\tnop\n"); | 3522 fprintf (stream, "\tnop\n"); |
3493 | 3523 |
3494 fprintf (stream, "\t.end no-transform\n"); | 3524 fprintf (stream, "\t.end no-transform\n"); |
3495 } | 3525 } |
3496 | 3526 |
3497 | 3527 static void |
3498 void | 3528 xtensa_trampoline_init (rtx m_tramp, tree fndecl, rtx chain) |
3499 xtensa_initialize_trampoline (rtx addr, rtx func, rtx chain) | 3529 { |
3500 { | 3530 rtx func = XEXP (DECL_RTL (fndecl), 0); |
3501 bool use_call0 = (TARGET_CONST16 || TARGET_ABSOLUTE_LITERALS); | 3531 bool use_call0 = (TARGET_CONST16 || TARGET_ABSOLUTE_LITERALS); |
3502 int chain_off = use_call0 ? 12 : 8; | 3532 int chain_off = use_call0 ? 12 : 8; |
3503 int func_off = use_call0 ? 16 : 12; | 3533 int func_off = use_call0 ? 16 : 12; |
3504 emit_move_insn (gen_rtx_MEM (SImode, plus_constant (addr, chain_off)), chain); | 3534 |
3505 emit_move_insn (gen_rtx_MEM (SImode, plus_constant (addr, func_off)), func); | 3535 emit_block_move (m_tramp, assemble_trampoline_template (), |
3536 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL); | |
3537 | |
3538 emit_move_insn (adjust_address (m_tramp, SImode, chain_off), chain); | |
3539 emit_move_insn (adjust_address (m_tramp, SImode, func_off), func); | |
3506 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_sync_caches"), | 3540 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_sync_caches"), |
3507 0, VOIDmode, 1, addr, Pmode); | 3541 0, VOIDmode, 1, XEXP (m_tramp, 0), Pmode); |
3508 } | 3542 } |
3509 | 3543 |
3510 | 3544 |
3511 #include "gt-xtensa.h" | 3545 #include "gt-xtensa.h" |