Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/xtensa/xtensa.c @ 67:f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 22 Mar 2011 17:18:12 +0900 |
parents | b7f97abdc517 |
children | 04ced10e8804 |
comparison
equal
deleted
inserted
replaced
65:65488c3d617d | 67:f6334be47118 |
---|---|
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, 2009 | 2 Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 |
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 |
38 #include "expr.h" | 38 #include "expr.h" |
39 #include "flags.h" | 39 #include "flags.h" |
40 #include "reload.h" | 40 #include "reload.h" |
41 #include "tm_p.h" | 41 #include "tm_p.h" |
42 #include "function.h" | 42 #include "function.h" |
43 #include "toplev.h" | 43 #include "diagnostic-core.h" |
44 #include "optabs.h" | 44 #include "optabs.h" |
45 #include "libfuncs.h" | 45 #include "libfuncs.h" |
46 #include "ggc.h" | 46 #include "ggc.h" |
47 #include "target.h" | 47 #include "target.h" |
48 #include "target-def.h" | 48 #include "target-def.h" |
115 FP_REGS, FP_REGS, FP_REGS, FP_REGS, | 115 FP_REGS, FP_REGS, FP_REGS, FP_REGS, |
116 FP_REGS, FP_REGS, FP_REGS, FP_REGS, | 116 FP_REGS, FP_REGS, FP_REGS, FP_REGS, |
117 ACC_REG, | 117 ACC_REG, |
118 }; | 118 }; |
119 | 119 |
120 static void xtensa_option_override (void); | |
120 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); |
121 static rtx gen_int_relational (enum rtx_code, rtx, rtx, int *); | 122 static rtx gen_int_relational (enum rtx_code, rtx, rtx, int *); |
122 static rtx gen_float_relational (enum rtx_code, rtx, rtx); | 123 static rtx gen_float_relational (enum rtx_code, rtx, rtx); |
123 static rtx gen_conditional_move (enum rtx_code, enum machine_mode, rtx, rtx); | 124 static rtx gen_conditional_move (enum rtx_code, enum machine_mode, rtx, rtx); |
124 static rtx fixup_subreg_mem (rtx); | 125 static rtx fixup_subreg_mem (rtx); |
125 static struct machine_function * xtensa_init_machine_status (void); | 126 static struct machine_function * xtensa_init_machine_status (void); |
126 static rtx xtensa_legitimize_tls_address (rtx); | 127 static rtx xtensa_legitimize_tls_address (rtx); |
127 static rtx xtensa_legitimize_address (rtx, rtx, enum machine_mode); | 128 static rtx xtensa_legitimize_address (rtx, rtx, enum machine_mode); |
129 static bool xtensa_mode_dependent_address_p (const_rtx); | |
128 static bool xtensa_return_in_msb (const_tree); | 130 static bool xtensa_return_in_msb (const_tree); |
129 static void printx (FILE *, signed int); | 131 static void printx (FILE *, signed int); |
130 static void xtensa_function_epilogue (FILE *, HOST_WIDE_INT); | 132 static void xtensa_function_epilogue (FILE *, HOST_WIDE_INT); |
131 static rtx xtensa_builtin_saveregs (void); | 133 static rtx xtensa_builtin_saveregs (void); |
132 static bool xtensa_legitimate_address_p (enum machine_mode, rtx, bool); | 134 static bool xtensa_legitimate_address_p (enum machine_mode, rtx, bool); |
133 static unsigned int xtensa_multibss_section_type_flags (tree, const char *, | 135 static unsigned int xtensa_multibss_section_type_flags (tree, const char *, |
134 int) ATTRIBUTE_UNUSED; | 136 int) ATTRIBUTE_UNUSED; |
135 static section *xtensa_select_rtx_section (enum machine_mode, rtx, | 137 static section *xtensa_select_rtx_section (enum machine_mode, rtx, |
136 unsigned HOST_WIDE_INT); | 138 unsigned HOST_WIDE_INT); |
137 static bool xtensa_rtx_costs (rtx, int, int, int *, bool); | 139 static bool xtensa_rtx_costs (rtx, int, int, int *, bool); |
140 static int xtensa_register_move_cost (enum machine_mode, reg_class_t, | |
141 reg_class_t); | |
142 static int xtensa_memory_move_cost (enum machine_mode, reg_class_t, bool); | |
138 static tree xtensa_build_builtin_va_list (void); | 143 static tree xtensa_build_builtin_va_list (void); |
139 static bool xtensa_return_in_memory (const_tree, const_tree); | 144 static bool xtensa_return_in_memory (const_tree, const_tree); |
140 static tree xtensa_gimplify_va_arg_expr (tree, tree, gimple_seq *, | 145 static tree xtensa_gimplify_va_arg_expr (tree, tree, gimple_seq *, |
141 gimple_seq *); | 146 gimple_seq *); |
147 static void xtensa_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, | |
148 const_tree, bool); | |
149 static rtx xtensa_function_arg (CUMULATIVE_ARGS *, enum machine_mode, | |
150 const_tree, bool); | |
151 static rtx xtensa_function_incoming_arg (CUMULATIVE_ARGS *, | |
152 enum machine_mode, const_tree, bool); | |
142 static rtx xtensa_function_value (const_tree, const_tree, bool); | 153 static rtx xtensa_function_value (const_tree, const_tree, bool); |
154 static rtx xtensa_libcall_value (enum machine_mode, const_rtx); | |
155 static bool xtensa_function_value_regno_p (const unsigned int); | |
156 static unsigned int xtensa_function_arg_boundary (enum machine_mode, | |
157 const_tree); | |
143 static void xtensa_init_builtins (void); | 158 static void xtensa_init_builtins (void); |
144 static tree xtensa_fold_builtin (tree, int, tree *, bool); | 159 static tree xtensa_fold_builtin (tree, int, tree *, bool); |
145 static rtx xtensa_expand_builtin (tree, rtx, rtx, enum machine_mode, int); | 160 static rtx xtensa_expand_builtin (tree, rtx, rtx, enum machine_mode, int); |
146 static void xtensa_va_start (tree, rtx); | 161 static void xtensa_va_start (tree, rtx); |
147 static bool xtensa_frame_pointer_required (void); | 162 static bool xtensa_frame_pointer_required (void); |
148 static rtx xtensa_static_chain (const_tree, bool); | 163 static rtx xtensa_static_chain (const_tree, bool); |
149 static void xtensa_asm_trampoline_template (FILE *); | 164 static void xtensa_asm_trampoline_template (FILE *); |
150 static void xtensa_trampoline_init (rtx, tree, rtx); | 165 static void xtensa_trampoline_init (rtx, tree, rtx); |
166 static bool xtensa_output_addr_const_extra (FILE *, rtx); | |
167 | |
168 static reg_class_t xtensa_preferred_reload_class (rtx, reg_class_t); | |
169 static reg_class_t xtensa_preferred_output_reload_class (rtx, reg_class_t); | |
170 static reg_class_t xtensa_secondary_reload (bool, rtx, reg_class_t, | |
171 enum machine_mode, | |
172 struct secondary_reload_info *); | |
173 | |
174 static bool constantpool_address_p (const_rtx addr); | |
151 | 175 |
152 static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] = | 176 static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] = |
153 REG_ALLOC_ORDER; | 177 REG_ALLOC_ORDER; |
178 | |
179 /* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */ | |
180 | |
181 static const struct default_options xtensa_option_optimization_table[] = | |
182 { | |
183 { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 }, | |
184 /* Reordering blocks for Xtensa is not a good idea unless the | |
185 compiler understands the range of conditional branches. | |
186 Currently all branch relaxation for Xtensa is handled in the | |
187 assembler, so GCC cannot do a good job of reordering blocks. | |
188 Do not enable reordering unless it is explicitly requested. */ | |
189 { OPT_LEVELS_ALL, OPT_freorder_blocks, NULL, 0 }, | |
190 { OPT_LEVELS_NONE, 0, NULL, 0 } | |
191 }; | |
154 | 192 |
155 | 193 |
156 /* This macro generates the assembly code for function exit, | 194 /* This macro generates the assembly code for function exit, |
157 on machines that need it. If FUNCTION_EPILOGUE is not defined | 195 on machines that need it. If FUNCTION_EPILOGUE is not defined |
158 then individual return instructions are generated for each | 196 then individual return instructions are generated for each |
169 | 207 |
170 #undef TARGET_ASM_SELECT_RTX_SECTION | 208 #undef TARGET_ASM_SELECT_RTX_SECTION |
171 #define TARGET_ASM_SELECT_RTX_SECTION xtensa_select_rtx_section | 209 #define TARGET_ASM_SELECT_RTX_SECTION xtensa_select_rtx_section |
172 | 210 |
173 #undef TARGET_DEFAULT_TARGET_FLAGS | 211 #undef TARGET_DEFAULT_TARGET_FLAGS |
174 #define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT | MASK_FUSED_MADD) | 212 #define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT) |
175 | 213 |
176 #undef TARGET_LEGITIMIZE_ADDRESS | 214 #undef TARGET_LEGITIMIZE_ADDRESS |
177 #define TARGET_LEGITIMIZE_ADDRESS xtensa_legitimize_address | 215 #define TARGET_LEGITIMIZE_ADDRESS xtensa_legitimize_address |
178 | 216 #undef TARGET_MODE_DEPENDENT_ADDRESS_P |
217 #define TARGET_MODE_DEPENDENT_ADDRESS_P xtensa_mode_dependent_address_p | |
218 | |
219 #undef TARGET_REGISTER_MOVE_COST | |
220 #define TARGET_REGISTER_MOVE_COST xtensa_register_move_cost | |
221 #undef TARGET_MEMORY_MOVE_COST | |
222 #define TARGET_MEMORY_MOVE_COST xtensa_memory_move_cost | |
179 #undef TARGET_RTX_COSTS | 223 #undef TARGET_RTX_COSTS |
180 #define TARGET_RTX_COSTS xtensa_rtx_costs | 224 #define TARGET_RTX_COSTS xtensa_rtx_costs |
181 #undef TARGET_ADDRESS_COST | 225 #undef TARGET_ADDRESS_COST |
182 #define TARGET_ADDRESS_COST hook_int_rtx_bool_0 | 226 #define TARGET_ADDRESS_COST hook_int_rtx_bool_0 |
183 | 227 |
194 | 238 |
195 #undef TARGET_RETURN_IN_MEMORY | 239 #undef TARGET_RETURN_IN_MEMORY |
196 #define TARGET_RETURN_IN_MEMORY xtensa_return_in_memory | 240 #define TARGET_RETURN_IN_MEMORY xtensa_return_in_memory |
197 #undef TARGET_FUNCTION_VALUE | 241 #undef TARGET_FUNCTION_VALUE |
198 #define TARGET_FUNCTION_VALUE xtensa_function_value | 242 #define TARGET_FUNCTION_VALUE xtensa_function_value |
243 #undef TARGET_LIBCALL_VALUE | |
244 #define TARGET_LIBCALL_VALUE xtensa_libcall_value | |
245 #undef TARGET_FUNCTION_VALUE_REGNO_P | |
246 #define TARGET_FUNCTION_VALUE_REGNO_P xtensa_function_value_regno_p | |
247 | |
199 #undef TARGET_SPLIT_COMPLEX_ARG | 248 #undef TARGET_SPLIT_COMPLEX_ARG |
200 #define TARGET_SPLIT_COMPLEX_ARG hook_bool_const_tree_true | 249 #define TARGET_SPLIT_COMPLEX_ARG hook_bool_const_tree_true |
201 #undef TARGET_MUST_PASS_IN_STACK | 250 #undef TARGET_MUST_PASS_IN_STACK |
202 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size | 251 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size |
252 #undef TARGET_FUNCTION_ARG_ADVANCE | |
253 #define TARGET_FUNCTION_ARG_ADVANCE xtensa_function_arg_advance | |
254 #undef TARGET_FUNCTION_ARG | |
255 #define TARGET_FUNCTION_ARG xtensa_function_arg | |
256 #undef TARGET_FUNCTION_INCOMING_ARG | |
257 #define TARGET_FUNCTION_INCOMING_ARG xtensa_function_incoming_arg | |
258 #undef TARGET_FUNCTION_ARG_BOUNDARY | |
259 #define TARGET_FUNCTION_ARG_BOUNDARY xtensa_function_arg_boundary | |
203 | 260 |
204 #undef TARGET_EXPAND_BUILTIN_SAVEREGS | 261 #undef TARGET_EXPAND_BUILTIN_SAVEREGS |
205 #define TARGET_EXPAND_BUILTIN_SAVEREGS xtensa_builtin_saveregs | 262 #define TARGET_EXPAND_BUILTIN_SAVEREGS xtensa_builtin_saveregs |
206 #undef TARGET_GIMPLIFY_VA_ARG_EXPR | 263 #undef TARGET_GIMPLIFY_VA_ARG_EXPR |
207 #define TARGET_GIMPLIFY_VA_ARG_EXPR xtensa_gimplify_va_arg_expr | 264 #define TARGET_GIMPLIFY_VA_ARG_EXPR xtensa_gimplify_va_arg_expr |
214 #undef TARGET_FOLD_BUILTIN | 271 #undef TARGET_FOLD_BUILTIN |
215 #define TARGET_FOLD_BUILTIN xtensa_fold_builtin | 272 #define TARGET_FOLD_BUILTIN xtensa_fold_builtin |
216 #undef TARGET_EXPAND_BUILTIN | 273 #undef TARGET_EXPAND_BUILTIN |
217 #define TARGET_EXPAND_BUILTIN xtensa_expand_builtin | 274 #define TARGET_EXPAND_BUILTIN xtensa_expand_builtin |
218 | 275 |
276 #undef TARGET_PREFERRED_RELOAD_CLASS | |
277 #define TARGET_PREFERRED_RELOAD_CLASS xtensa_preferred_reload_class | |
278 #undef TARGET_PREFERRED_OUTPUT_RELOAD_CLASS | |
279 #define TARGET_PREFERRED_OUTPUT_RELOAD_CLASS xtensa_preferred_output_reload_class | |
280 | |
219 #undef TARGET_SECONDARY_RELOAD | 281 #undef TARGET_SECONDARY_RELOAD |
220 #define TARGET_SECONDARY_RELOAD xtensa_secondary_reload | 282 #define TARGET_SECONDARY_RELOAD xtensa_secondary_reload |
221 | 283 |
222 #undef TARGET_HAVE_TLS | 284 #undef TARGET_HAVE_TLS |
223 #define TARGET_HAVE_TLS (TARGET_THREADPTR && HAVE_AS_TLS) | 285 #define TARGET_HAVE_TLS (TARGET_THREADPTR && HAVE_AS_TLS) |
235 #define TARGET_STATIC_CHAIN xtensa_static_chain | 297 #define TARGET_STATIC_CHAIN xtensa_static_chain |
236 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE | 298 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE |
237 #define TARGET_ASM_TRAMPOLINE_TEMPLATE xtensa_asm_trampoline_template | 299 #define TARGET_ASM_TRAMPOLINE_TEMPLATE xtensa_asm_trampoline_template |
238 #undef TARGET_TRAMPOLINE_INIT | 300 #undef TARGET_TRAMPOLINE_INIT |
239 #define TARGET_TRAMPOLINE_INIT xtensa_trampoline_init | 301 #define TARGET_TRAMPOLINE_INIT xtensa_trampoline_init |
302 | |
303 #undef TARGET_OPTION_OVERRIDE | |
304 #define TARGET_OPTION_OVERRIDE xtensa_option_override | |
305 #undef TARGET_OPTION_OPTIMIZATION_TABLE | |
306 #define TARGET_OPTION_OPTIMIZATION_TABLE xtensa_option_optimization_table | |
307 | |
308 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA | |
309 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA xtensa_output_addr_const_extra | |
240 | 310 |
241 struct gcc_target targetm = TARGET_INITIALIZER; | 311 struct gcc_target targetm = TARGET_INITIALIZER; |
242 | 312 |
243 | 313 |
244 /* Functions to test Xtensa immediate operand validity. */ | 314 /* Functions to test Xtensa immediate operand validity. */ |
445 } | 515 } |
446 return FALSE; | 516 return FALSE; |
447 } | 517 } |
448 | 518 |
449 | 519 |
450 int | 520 static bool |
451 constantpool_address_p (rtx addr) | 521 constantpool_address_p (const_rtx addr) |
452 { | 522 { |
453 rtx sym = addr; | 523 const_rtx sym = addr; |
454 | 524 |
455 if (GET_CODE (addr) == CONST) | 525 if (GET_CODE (addr) == CONST) |
456 { | 526 { |
457 rtx offset; | 527 rtx offset; |
458 | 528 |
459 /* Only handle (PLUS (SYM, OFFSET)) form. */ | 529 /* Only handle (PLUS (SYM, OFFSET)) form. */ |
460 addr = XEXP (addr, 0); | 530 addr = XEXP (addr, 0); |
461 if (GET_CODE (addr) != PLUS) | 531 if (GET_CODE (addr) != PLUS) |
462 return FALSE; | 532 return false; |
463 | 533 |
464 /* Make sure the address is word aligned. */ | 534 /* Make sure the address is word aligned. */ |
465 offset = XEXP (addr, 1); | 535 offset = XEXP (addr, 1); |
466 if ((GET_CODE (offset) != CONST_INT) | 536 if ((!CONST_INT_P (offset)) |
467 || ((INTVAL (offset) & 3) != 0)) | 537 || ((INTVAL (offset) & 3) != 0)) |
468 return FALSE; | 538 return false; |
469 | 539 |
470 sym = XEXP (addr, 0); | 540 sym = XEXP (addr, 0); |
471 } | 541 } |
472 | 542 |
473 if ((GET_CODE (sym) == SYMBOL_REF) | 543 if ((GET_CODE (sym) == SYMBOL_REF) |
474 && CONSTANT_POOL_ADDRESS_P (sym)) | 544 && CONSTANT_POOL_ADDRESS_P (sym)) |
475 return TRUE; | 545 return true; |
476 return FALSE; | 546 return false; |
477 } | 547 } |
478 | 548 |
479 | 549 |
480 int | 550 int |
481 constantpool_mem_p (rtx op) | 551 constantpool_mem_p (rtx op) |
1270 | 1340 |
1271 if (GET_CODE (containing_fp) != REG) | 1341 if (GET_CODE (containing_fp) != REG) |
1272 containing_fp = force_reg (Pmode, containing_fp); | 1342 containing_fp = force_reg (Pmode, containing_fp); |
1273 | 1343 |
1274 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_nonlocal_goto"), | 1344 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_nonlocal_goto"), |
1275 0, VOIDmode, 2, | 1345 LCT_NORMAL, VOIDmode, 2, |
1276 containing_fp, Pmode, | 1346 containing_fp, Pmode, |
1277 goto_handler, Pmode); | 1347 goto_handler, Pmode); |
1278 } | 1348 } |
1279 | 1349 |
1280 | 1350 |
1281 static struct machine_function * | 1351 static struct machine_function * |
1282 xtensa_init_machine_status (void) | 1352 xtensa_init_machine_status (void) |
1283 { | 1353 { |
1284 return GGC_CNEW (struct machine_function); | 1354 return ggc_alloc_cleared_machine_function (); |
1285 } | 1355 } |
1286 | 1356 |
1287 | 1357 |
1288 /* Shift VAL of mode MODE left by COUNT bits. */ | 1358 /* Shift VAL of mode MODE left by COUNT bits. */ |
1289 | 1359 |
1548 /* Set flag to cause TARGET_FRAME_POINTER_REQUIRED to return true. */ | 1618 /* Set flag to cause TARGET_FRAME_POINTER_REQUIRED to return true. */ |
1549 cfun->machine->accesses_prev_frame = 1; | 1619 cfun->machine->accesses_prev_frame = 1; |
1550 | 1620 |
1551 emit_library_call | 1621 emit_library_call |
1552 (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_libgcc_window_spill"), | 1622 (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_libgcc_window_spill"), |
1553 0, VOIDmode, 0); | 1623 LCT_NORMAL, VOIDmode, 0); |
1554 } | 1624 } |
1555 | 1625 |
1556 | 1626 |
1557 /* Emit the assembly for the end of a zero-cost loop. Normally we just emit | 1627 /* Emit the assembly for the end of a zero-cost loop. Normally we just emit |
1558 a comment showing where the end of the loop is. However, if there is a | 1628 a comment showing where the end of the loop is. However, if there is a |
1888 } | 1958 } |
1889 | 1959 |
1890 return x; | 1960 return x; |
1891 } | 1961 } |
1892 | 1962 |
1963 /* Worker function for TARGET_MODE_DEPENDENT_ADDRESS_P. | |
1964 | |
1965 Treat constant-pool references as "mode dependent" since they can | |
1966 only be accessed with SImode loads. This works around a bug in the | |
1967 combiner where a constant pool reference is temporarily converted | |
1968 to an HImode load, which is then assumed to zero-extend based on | |
1969 our definition of LOAD_EXTEND_OP. This is wrong because the high | |
1970 bits of a 16-bit value in the constant pool are now sign-extended | |
1971 by default. */ | |
1972 | |
1973 static bool | |
1974 xtensa_mode_dependent_address_p (const_rtx addr) | |
1975 { | |
1976 return constantpool_address_p (addr); | |
1977 } | |
1893 | 1978 |
1894 /* Helper for xtensa_tls_referenced_p. */ | 1979 /* Helper for xtensa_tls_referenced_p. */ |
1895 | 1980 |
1896 static int | 1981 static int |
1897 xtensa_tls_referenced_p_1 (rtx *x, void *data ATTRIBUTE_UNUSED) | 1982 xtensa_tls_referenced_p_1 (rtx *x, void *data ATTRIBUTE_UNUSED) |
1980 } | 2065 } |
1981 | 2066 |
1982 | 2067 |
1983 /* Advance the argument to the next argument position. */ | 2068 /* Advance the argument to the next argument position. */ |
1984 | 2069 |
1985 void | 2070 static void |
1986 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type) | 2071 xtensa_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, |
2072 const_tree type, bool named ATTRIBUTE_UNUSED) | |
1987 { | 2073 { |
1988 int words, max; | 2074 int words, max; |
1989 int *arg_words; | 2075 int *arg_words; |
1990 | 2076 |
1991 arg_words = &cum->arg_words; | 2077 arg_words = &cum->arg_words; |
2006 | 2092 |
2007 /* Return an RTL expression containing the register for the given mode, | 2093 /* Return an RTL expression containing the register for the given mode, |
2008 or 0 if the argument is to be passed on the stack. INCOMING_P is nonzero | 2094 or 0 if the argument is to be passed on the stack. INCOMING_P is nonzero |
2009 if this is an incoming argument to the current function. */ | 2095 if this is an incoming argument to the current function. */ |
2010 | 2096 |
2011 rtx | 2097 static rtx |
2012 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, | 2098 xtensa_function_arg_1 (CUMULATIVE_ARGS *cum, enum machine_mode mode, |
2013 int incoming_p) | 2099 const_tree type, bool incoming_p) |
2014 { | 2100 { |
2015 int regbase, words, max; | 2101 int regbase, words, max; |
2016 int *arg_words; | 2102 int *arg_words; |
2017 int regno; | 2103 int regno; |
2018 | 2104 |
2039 cfun->machine->need_a7_copy = true; | 2125 cfun->machine->need_a7_copy = true; |
2040 | 2126 |
2041 return gen_rtx_REG (mode, regno); | 2127 return gen_rtx_REG (mode, regno); |
2042 } | 2128 } |
2043 | 2129 |
2044 | 2130 /* Implement TARGET_FUNCTION_ARG. */ |
2045 int | 2131 |
2046 function_arg_boundary (enum machine_mode mode, tree type) | 2132 static rtx |
2133 xtensa_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, | |
2134 const_tree type, bool named ATTRIBUTE_UNUSED) | |
2135 { | |
2136 return xtensa_function_arg_1 (cum, mode, type, false); | |
2137 } | |
2138 | |
2139 /* Implement TARGET_FUNCTION_INCOMING_ARG. */ | |
2140 | |
2141 static rtx | |
2142 xtensa_function_incoming_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, | |
2143 const_tree type, bool named ATTRIBUTE_UNUSED) | |
2144 { | |
2145 return xtensa_function_arg_1 (cum, mode, type, true); | |
2146 } | |
2147 | |
2148 static unsigned int | |
2149 xtensa_function_arg_boundary (enum machine_mode mode, const_tree type) | |
2047 { | 2150 { |
2048 unsigned int alignment; | 2151 unsigned int alignment; |
2049 | 2152 |
2050 alignment = type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode); | 2153 alignment = type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode); |
2051 if (alignment < PARM_BOUNDARY) | 2154 if (alignment < PARM_BOUNDARY) |
2063 && AGGREGATE_TYPE_P (valtype) | 2166 && AGGREGATE_TYPE_P (valtype) |
2064 && int_size_in_bytes (valtype) >= UNITS_PER_WORD); | 2167 && int_size_in_bytes (valtype) >= UNITS_PER_WORD); |
2065 } | 2168 } |
2066 | 2169 |
2067 | 2170 |
2068 void | 2171 static void |
2069 override_options (void) | 2172 xtensa_option_override (void) |
2070 { | 2173 { |
2071 int regno; | 2174 int regno; |
2072 enum machine_mode mode; | 2175 enum machine_mode mode; |
2073 | 2176 |
2074 if (!TARGET_BOOLEANS && TARGET_HARD_FLOAT) | 2177 if (!TARGET_BOOLEANS && TARGET_HARD_FLOAT) |
2107 /* Check PIC settings. PIC is only supported when using L32R | 2210 /* Check PIC settings. PIC is only supported when using L32R |
2108 instructions, and some targets need to always use PIC. */ | 2211 instructions, and some targets need to always use PIC. */ |
2109 if (flag_pic && TARGET_CONST16) | 2212 if (flag_pic && TARGET_CONST16) |
2110 error ("-f%s is not supported with CONST16 instructions", | 2213 error ("-f%s is not supported with CONST16 instructions", |
2111 (flag_pic > 1 ? "PIC" : "pic")); | 2214 (flag_pic > 1 ? "PIC" : "pic")); |
2215 else if (TARGET_FORCE_NO_PIC) | |
2216 flag_pic = 0; | |
2112 else if (XTENSA_ALWAYS_PIC) | 2217 else if (XTENSA_ALWAYS_PIC) |
2113 { | 2218 { |
2114 if (TARGET_CONST16) | 2219 if (TARGET_CONST16) |
2115 error ("PIC is required but not supported with CONST16 instructions"); | 2220 error ("PIC is required but not supported with CONST16 instructions"); |
2116 flag_pic = 1; | 2221 flag_pic = 1; |
2128 { | 2233 { |
2129 flag_reorder_blocks_and_partition = 0; | 2234 flag_reorder_blocks_and_partition = 0; |
2130 flag_reorder_blocks = 1; | 2235 flag_reorder_blocks = 1; |
2131 } | 2236 } |
2132 } | 2237 } |
2133 | |
2134 | 2238 |
2135 /* A C compound statement to output to stdio stream STREAM the | 2239 /* A C compound statement to output to stdio stream STREAM the |
2136 assembler syntax for an instruction operand X. X is an RTL | 2240 assembler syntax for an instruction operand X. X is an RTL |
2137 expression. | 2241 expression. |
2138 | 2242 |
2380 output_addr_const (file, addr); | 2484 output_addr_const (file, addr); |
2381 break; | 2485 break; |
2382 } | 2486 } |
2383 } | 2487 } |
2384 | 2488 |
2385 | 2489 /* Implement TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA. */ |
2386 bool | 2490 |
2491 static bool | |
2387 xtensa_output_addr_const_extra (FILE *fp, rtx x) | 2492 xtensa_output_addr_const_extra (FILE *fp, rtx x) |
2388 { | 2493 { |
2389 if (GET_CODE (x) == UNSPEC && XVECLEN (x, 0) == 1) | 2494 if (GET_CODE (x) == UNSPEC && XVECLEN (x, 0) == 1) |
2390 { | 2495 { |
2391 switch (XINT (x, 1)) | 2496 switch (XINT (x, 1)) |
2583 note_rtx = gen_rtx_SET (VOIDmode, (frame_pointer_needed | 2688 note_rtx = gen_rtx_SET (VOIDmode, (frame_pointer_needed |
2584 ? hard_frame_pointer_rtx | 2689 ? hard_frame_pointer_rtx |
2585 : stack_pointer_rtx), | 2690 : stack_pointer_rtx), |
2586 plus_constant (stack_pointer_rtx, -total_size)); | 2691 plus_constant (stack_pointer_rtx, -total_size)); |
2587 RTX_FRAME_RELATED_P (insn) = 1; | 2692 RTX_FRAME_RELATED_P (insn) = 1; |
2588 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, | 2693 add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx); |
2589 note_rtx, REG_NOTES (insn)); | |
2590 } | 2694 } |
2591 | 2695 |
2592 | 2696 |
2593 /* Clear variables at function end. */ | 2697 /* Clear variables at function end. */ |
2594 | 2698 |
2677 | 2781 |
2678 DECL_FIELD_CONTEXT (f_stk) = record; | 2782 DECL_FIELD_CONTEXT (f_stk) = record; |
2679 DECL_FIELD_CONTEXT (f_reg) = record; | 2783 DECL_FIELD_CONTEXT (f_reg) = record; |
2680 DECL_FIELD_CONTEXT (f_ndx) = record; | 2784 DECL_FIELD_CONTEXT (f_ndx) = record; |
2681 | 2785 |
2682 TREE_CHAIN (record) = type_decl; | 2786 TYPE_STUB_DECL (record) = type_decl; |
2683 TYPE_NAME (record) = type_decl; | 2787 TYPE_NAME (record) = type_decl; |
2684 TYPE_FIELDS (record) = f_stk; | 2788 TYPE_FIELDS (record) = f_stk; |
2685 TREE_CHAIN (f_stk) = f_reg; | 2789 DECL_CHAIN (f_stk) = f_reg; |
2686 TREE_CHAIN (f_reg) = f_ndx; | 2790 DECL_CHAIN (f_reg) = f_ndx; |
2687 | 2791 |
2688 layout_type (record); | 2792 layout_type (record); |
2689 return record; | 2793 return record; |
2690 } | 2794 } |
2691 | 2795 |
2735 int arg_words; | 2839 int arg_words; |
2736 | 2840 |
2737 arg_words = crtl->args.info.arg_words; | 2841 arg_words = crtl->args.info.arg_words; |
2738 | 2842 |
2739 f_stk = TYPE_FIELDS (va_list_type_node); | 2843 f_stk = TYPE_FIELDS (va_list_type_node); |
2740 f_reg = TREE_CHAIN (f_stk); | 2844 f_reg = DECL_CHAIN (f_stk); |
2741 f_ndx = TREE_CHAIN (f_reg); | 2845 f_ndx = DECL_CHAIN (f_reg); |
2742 | 2846 |
2743 stk = build3 (COMPONENT_REF, TREE_TYPE (f_stk), valist, f_stk, NULL_TREE); | 2847 stk = build3 (COMPONENT_REF, TREE_TYPE (f_stk), valist, f_stk, NULL_TREE); |
2744 reg = build3 (COMPONENT_REF, TREE_TYPE (f_reg), unshare_expr (valist), | 2848 reg = build3 (COMPONENT_REF, TREE_TYPE (f_reg), unshare_expr (valist), |
2745 f_reg, NULL_TREE); | 2849 f_reg, NULL_TREE); |
2746 ndx = build3 (COMPONENT_REF, TREE_TYPE (f_ndx), unshare_expr (valist), | 2850 ndx = build3 (COMPONENT_REF, TREE_TYPE (f_ndx), unshare_expr (valist), |
2805 | 2909 |
2806 return build2 (COMPLEX_EXPR, type, real_part, imag_part); | 2910 return build2 (COMPLEX_EXPR, type, real_part, imag_part); |
2807 } | 2911 } |
2808 | 2912 |
2809 f_stk = TYPE_FIELDS (va_list_type_node); | 2913 f_stk = TYPE_FIELDS (va_list_type_node); |
2810 f_reg = TREE_CHAIN (f_stk); | 2914 f_reg = DECL_CHAIN (f_stk); |
2811 f_ndx = TREE_CHAIN (f_reg); | 2915 f_ndx = DECL_CHAIN (f_reg); |
2812 | 2916 |
2813 stk = build3 (COMPONENT_REF, TREE_TYPE (f_stk), valist, | 2917 stk = build3 (COMPONENT_REF, TREE_TYPE (f_stk), valist, |
2814 f_stk, NULL_TREE); | 2918 f_stk, NULL_TREE); |
2815 reg = build3 (COMPONENT_REF, TREE_TYPE (f_reg), unshare_expr (valist), | 2919 reg = build3 (COMPONENT_REF, TREE_TYPE (f_reg), unshare_expr (valist), |
2816 f_reg, NULL_TREE); | 2920 f_reg, NULL_TREE); |
3065 internal_error ("bad builtin code"); | 3169 internal_error ("bad builtin code"); |
3066 } | 3170 } |
3067 return NULL_RTX; | 3171 return NULL_RTX; |
3068 } | 3172 } |
3069 | 3173 |
3070 | 3174 /* Worker function for TARGET_PREFERRED_RELOAD_CLASS. */ |
3071 enum reg_class | 3175 |
3072 xtensa_preferred_reload_class (rtx x, enum reg_class rclass, int isoutput) | 3176 static reg_class_t |
3073 { | 3177 xtensa_preferred_reload_class (rtx x, reg_class_t rclass) |
3074 if (!isoutput && CONSTANT_P (x) && GET_CODE (x) == CONST_DOUBLE) | 3178 { |
3179 if (CONSTANT_P (x) && CONST_DOUBLE_P (x)) | |
3075 return NO_REGS; | 3180 return NO_REGS; |
3076 | 3181 |
3077 /* Don't use the stack pointer or hard frame pointer for reloads! | 3182 /* Don't use the stack pointer or hard frame pointer for reloads! |
3078 The hard frame pointer would normally be OK except that it may | 3183 The hard frame pointer would normally be OK except that it may |
3079 briefly hold an incoming argument in the prologue, and reload | 3184 briefly hold an incoming argument in the prologue, and reload |
3084 return RL_REGS; | 3189 return RL_REGS; |
3085 | 3190 |
3086 return rclass; | 3191 return rclass; |
3087 } | 3192 } |
3088 | 3193 |
3089 | 3194 /* Worker function for TARGET_PREFERRED_OUTPUT_RELOAD_CLASS. */ |
3090 enum reg_class | 3195 |
3091 xtensa_secondary_reload (bool in_p, rtx x, enum reg_class rclass, | 3196 static reg_class_t |
3197 xtensa_preferred_output_reload_class (rtx x ATTRIBUTE_UNUSED, | |
3198 reg_class_t rclass) | |
3199 { | |
3200 /* Don't use the stack pointer or hard frame pointer for reloads! | |
3201 The hard frame pointer would normally be OK except that it may | |
3202 briefly hold an incoming argument in the prologue, and reload | |
3203 won't know that it is live because the hard frame pointer is | |
3204 treated specially. */ | |
3205 | |
3206 if (rclass == AR_REGS || rclass == GR_REGS) | |
3207 return RL_REGS; | |
3208 | |
3209 return rclass; | |
3210 } | |
3211 | |
3212 /* Worker function for TARGET_SECONDARY_RELOAD. */ | |
3213 | |
3214 static reg_class_t | |
3215 xtensa_secondary_reload (bool in_p, rtx x, reg_class_t rclass, | |
3092 enum machine_mode mode, secondary_reload_info *sri) | 3216 enum machine_mode mode, secondary_reload_info *sri) |
3093 { | 3217 { |
3094 int regno; | 3218 int regno; |
3095 | 3219 |
3096 if (in_p && constantpool_mem_p (x)) | 3220 if (in_p && constantpool_mem_p (x)) |
3188 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED) | 3312 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED) |
3189 { | 3313 { |
3190 return function_section (current_function_decl); | 3314 return function_section (current_function_decl); |
3191 } | 3315 } |
3192 | 3316 |
3317 /* Worker function for TARGET_REGISTER_MOVE_COST. */ | |
3318 | |
3319 static int | |
3320 xtensa_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED, | |
3321 reg_class_t from, reg_class_t to) | |
3322 { | |
3323 if (from == to && from != BR_REGS && to != BR_REGS) | |
3324 return 2; | |
3325 else if (reg_class_subset_p (from, AR_REGS) | |
3326 && reg_class_subset_p (to, AR_REGS)) | |
3327 return 2; | |
3328 else if (reg_class_subset_p (from, AR_REGS) && to == ACC_REG) | |
3329 return 3; | |
3330 else if (from == ACC_REG && reg_class_subset_p (to, AR_REGS)) | |
3331 return 3; | |
3332 else | |
3333 return 10; | |
3334 } | |
3335 | |
3336 /* Worker function for TARGET_MEMORY_MOVE_COST. */ | |
3337 | |
3338 static int | |
3339 xtensa_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED, | |
3340 reg_class_t rclass ATTRIBUTE_UNUSED, | |
3341 bool in ATTRIBUTE_UNUSED) | |
3342 { | |
3343 return 4; | |
3344 } | |
3193 | 3345 |
3194 /* Compute a (partial) cost for rtx X. Return true if the complete | 3346 /* Compute a (partial) cost for rtx X. Return true if the complete |
3195 cost has been computed, and false if subexpressions should be | 3347 cost has been computed, and false if subexpressions should be |
3196 scanned. In either case, *TOTAL contains the cost result. */ | 3348 scanned. In either case, *TOTAL contains the cost result. */ |
3197 | 3349 |
3435 && TYPE_PRECISION (valtype) < BITS_PER_WORD) | 3587 && TYPE_PRECISION (valtype) < BITS_PER_WORD) |
3436 ? SImode : TYPE_MODE (valtype), | 3588 ? SImode : TYPE_MODE (valtype), |
3437 outgoing ? GP_OUTGOING_RETURN : GP_RETURN); | 3589 outgoing ? GP_OUTGOING_RETURN : GP_RETURN); |
3438 } | 3590 } |
3439 | 3591 |
3592 /* Worker function for TARGET_LIBCALL_VALUE. */ | |
3593 | |
3594 static rtx | |
3595 xtensa_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED) | |
3596 { | |
3597 return gen_rtx_REG ((GET_MODE_CLASS (mode) == MODE_INT | |
3598 && GET_MODE_SIZE (mode) < UNITS_PER_WORD) | |
3599 ? SImode : mode, GP_RETURN); | |
3600 } | |
3601 | |
3602 /* Worker function TARGET_FUNCTION_VALUE_REGNO_P. */ | |
3603 | |
3604 static bool | |
3605 xtensa_function_value_regno_p (const unsigned int regno) | |
3606 { | |
3607 return (regno == GP_RETURN); | |
3608 } | |
3609 | |
3440 /* The static chain is passed in memory. Provide rtx giving 'mem' | 3610 /* The static chain is passed in memory. Provide rtx giving 'mem' |
3441 expressions that denote where they are stored. */ | 3611 expressions that denote where they are stored. */ |
3442 | 3612 |
3443 static rtx | 3613 static rtx |
3444 xtensa_static_chain (const_tree ARG_UNUSED (fndecl), bool incoming_p) | 3614 xtensa_static_chain (const_tree ARG_UNUSED (fndecl), bool incoming_p) |
3536 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL); | 3706 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL); |
3537 | 3707 |
3538 emit_move_insn (adjust_address (m_tramp, SImode, chain_off), chain); | 3708 emit_move_insn (adjust_address (m_tramp, SImode, chain_off), chain); |
3539 emit_move_insn (adjust_address (m_tramp, SImode, func_off), func); | 3709 emit_move_insn (adjust_address (m_tramp, SImode, func_off), func); |
3540 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_sync_caches"), | 3710 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_sync_caches"), |
3541 0, VOIDmode, 1, XEXP (m_tramp, 0), Pmode); | 3711 LCT_NORMAL, VOIDmode, 1, XEXP (m_tramp, 0), Pmode); |
3542 } | 3712 } |
3543 | 3713 |
3544 | 3714 |
3545 #include "gt-xtensa.h" | 3715 #include "gt-xtensa.h" |