Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/v850/v850.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 NEC V850 series | 1 /* Subroutines for insn-output.c for NEC V850 series |
2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, | 2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, |
3 2006, 2007, 2008 Free Software Foundation, Inc. | 3 2006, 2007, 2008, 2009 Free Software Foundation, Inc. |
4 Contributed by Jeff Law (law@cygnus.com). | 4 Contributed by Jeff Law (law@cygnus.com). |
5 | 5 |
6 This file is part of GCC. | 6 This file is part of GCC. |
7 | 7 |
8 GCC is free software; you can redistribute it and/or modify it | 8 GCC is free software; you can redistribute it and/or modify it |
56 static bool v850_rtx_costs (rtx, int, int, int *, bool); | 56 static bool v850_rtx_costs (rtx, int, int, int *, bool); |
57 static void substitute_ep_register (rtx, rtx, int, int, rtx *, rtx *); | 57 static void substitute_ep_register (rtx, rtx, int, int, rtx *, rtx *); |
58 static void v850_reorg (void); | 58 static void v850_reorg (void); |
59 static int ep_memory_offset (enum machine_mode, int); | 59 static int ep_memory_offset (enum machine_mode, int); |
60 static void v850_set_data_area (tree, v850_data_area); | 60 static void v850_set_data_area (tree, v850_data_area); |
61 const struct attribute_spec v850_attribute_table[]; | |
62 static tree v850_handle_interrupt_attribute (tree *, tree, tree, int, bool *); | 61 static tree v850_handle_interrupt_attribute (tree *, tree, tree, int, bool *); |
63 static tree v850_handle_data_area_attribute (tree *, tree, tree, int, bool *); | 62 static tree v850_handle_data_area_attribute (tree *, tree, tree, int, bool *); |
64 static void v850_insert_attributes (tree, tree *); | 63 static void v850_insert_attributes (tree, tree *); |
65 static void v850_asm_init_sections (void); | 64 static void v850_asm_init_sections (void); |
66 static section *v850_select_section (tree, int, unsigned HOST_WIDE_INT); | 65 static section *v850_select_section (tree, int, unsigned HOST_WIDE_INT); |
67 static void v850_encode_data_area (tree, rtx); | 66 static void v850_encode_data_area (tree, rtx); |
68 static void v850_encode_section_info (tree, rtx, int); | 67 static void v850_encode_section_info (tree, rtx, int); |
69 static bool v850_return_in_memory (const_tree, const_tree); | 68 static bool v850_return_in_memory (const_tree, const_tree); |
69 static rtx v850_function_value (const_tree, const_tree, bool); | |
70 static void v850_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, | 70 static void v850_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, |
71 tree, int *, int); | 71 tree, int *, int); |
72 static bool v850_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode, | 72 static bool v850_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode, |
73 const_tree, bool); | 73 const_tree, bool); |
74 static int v850_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, | 74 static int v850_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, |
75 tree, bool); | 75 tree, bool); |
76 static bool v850_can_eliminate (const int, const int); | |
77 static void v850_asm_trampoline_template (FILE *); | |
78 static void v850_trampoline_init (rtx, tree, rtx); | |
76 | 79 |
77 /* Information about the various small memory areas. */ | 80 /* Information about the various small memory areas. */ |
78 struct small_memory_info small_memory[ (int)SMALL_MEMORY_max ] = | 81 struct small_memory_info small_memory[ (int)SMALL_MEMORY_max ] = |
79 { | 82 { |
80 /* name max physical max */ | 83 /* name max physical max */ |
102 static GTY(()) section *rozdata_section; | 105 static GTY(()) section *rozdata_section; |
103 static GTY(()) section *tdata_section; | 106 static GTY(()) section *tdata_section; |
104 static GTY(()) section *zdata_section; | 107 static GTY(()) section *zdata_section; |
105 static GTY(()) section *zbss_section; | 108 static GTY(()) section *zbss_section; |
106 | 109 |
110 /* V850 specific attributes. */ | |
111 | |
112 static const struct attribute_spec v850_attribute_table[] = | |
113 { | |
114 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ | |
115 { "interrupt_handler", 0, 0, true, false, false, v850_handle_interrupt_attribute }, | |
116 { "interrupt", 0, 0, true, false, false, v850_handle_interrupt_attribute }, | |
117 { "sda", 0, 0, true, false, false, v850_handle_data_area_attribute }, | |
118 { "tda", 0, 0, true, false, false, v850_handle_data_area_attribute }, | |
119 { "zda", 0, 0, true, false, false, v850_handle_data_area_attribute }, | |
120 { NULL, 0, 0, false, false, false, NULL } | |
121 }; | |
122 | |
123 | |
107 /* Initialize the GCC target structure. */ | 124 /* Initialize the GCC target structure. */ |
108 #undef TARGET_ASM_ALIGNED_HI_OP | 125 #undef TARGET_ASM_ALIGNED_HI_OP |
109 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t" | 126 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t" |
110 | 127 |
111 #undef TARGET_ATTRIBUTE_TABLE | 128 #undef TARGET_ATTRIBUTE_TABLE |
146 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true | 163 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true |
147 | 164 |
148 #undef TARGET_RETURN_IN_MEMORY | 165 #undef TARGET_RETURN_IN_MEMORY |
149 #define TARGET_RETURN_IN_MEMORY v850_return_in_memory | 166 #define TARGET_RETURN_IN_MEMORY v850_return_in_memory |
150 | 167 |
168 #undef TARGET_FUNCTION_VALUE | |
169 #define TARGET_FUNCTION_VALUE v850_function_value | |
170 | |
151 #undef TARGET_PASS_BY_REFERENCE | 171 #undef TARGET_PASS_BY_REFERENCE |
152 #define TARGET_PASS_BY_REFERENCE v850_pass_by_reference | 172 #define TARGET_PASS_BY_REFERENCE v850_pass_by_reference |
153 | 173 |
154 #undef TARGET_CALLEE_COPIES | 174 #undef TARGET_CALLEE_COPIES |
155 #define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true | 175 #define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true |
157 #undef TARGET_SETUP_INCOMING_VARARGS | 177 #undef TARGET_SETUP_INCOMING_VARARGS |
158 #define TARGET_SETUP_INCOMING_VARARGS v850_setup_incoming_varargs | 178 #define TARGET_SETUP_INCOMING_VARARGS v850_setup_incoming_varargs |
159 | 179 |
160 #undef TARGET_ARG_PARTIAL_BYTES | 180 #undef TARGET_ARG_PARTIAL_BYTES |
161 #define TARGET_ARG_PARTIAL_BYTES v850_arg_partial_bytes | 181 #define TARGET_ARG_PARTIAL_BYTES v850_arg_partial_bytes |
182 | |
183 #undef TARGET_CAN_ELIMINATE | |
184 #define TARGET_CAN_ELIMINATE v850_can_eliminate | |
185 | |
186 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE | |
187 #define TARGET_ASM_TRAMPOLINE_TEMPLATE v850_asm_trampoline_template | |
188 #undef TARGET_TRAMPOLINE_INIT | |
189 #define TARGET_TRAMPOLINE_INIT v850_trampoline_init | |
162 | 190 |
163 struct gcc_target targetm = TARGET_INITIALIZER; | 191 struct gcc_target targetm = TARGET_INITIALIZER; |
164 | 192 |
165 /* Set the maximum size of small memory area TYPE to the value given | 193 /* Set the maximum size of small memory area TYPE to the value given |
166 by VALUE. Return true if VALUE was syntactically correct. VALUE | 194 by VALUE. Return true if VALUE was syntactically correct. VALUE |
234 size = GET_MODE_SIZE (mode); | 262 size = GET_MODE_SIZE (mode); |
235 | 263 |
236 return size > 8; | 264 return size > 8; |
237 } | 265 } |
238 | 266 |
239 /* Return an RTX to represent where a value with mode MODE will be returned | 267 /* Return an RTX to represent where an argument with mode MODE |
240 from a function. If the result is 0, the argument is pushed. */ | 268 and type TYPE will be passed to a function. If the result |
269 is NULL_RTX, the argument will be pushed. */ | |
241 | 270 |
242 rtx | 271 rtx |
243 function_arg (CUMULATIVE_ARGS * cum, | 272 function_arg (CUMULATIVE_ARGS * cum, |
244 enum machine_mode mode, | 273 enum machine_mode mode, |
245 tree type, | 274 tree type, |
246 int named) | 275 int named) |
247 { | 276 { |
248 rtx result = 0; | 277 rtx result = NULL_RTX; |
249 int size, align; | 278 int size, align; |
250 | 279 |
251 if (TARGET_GHS && !named) | 280 if (TARGET_GHS && !named) |
252 return NULL_RTX; | 281 return NULL_RTX; |
253 | 282 |
255 size = int_size_in_bytes (type); | 284 size = int_size_in_bytes (type); |
256 else | 285 else |
257 size = GET_MODE_SIZE (mode); | 286 size = GET_MODE_SIZE (mode); |
258 | 287 |
259 if (size < 1) | 288 if (size < 1) |
260 return 0; | 289 { |
290 /* Once we have stopped using argument registers, do not start up again. */ | |
291 cum->nbytes = 4 * UNITS_PER_WORD; | |
292 return NULL_RTX; | |
293 } | |
261 | 294 |
262 if (type) | 295 if (type) |
263 align = TYPE_ALIGN (type) / BITS_PER_UNIT; | 296 align = TYPE_ALIGN (type) / BITS_PER_UNIT; |
264 else | 297 else |
265 align = size; | 298 align = size; |
266 | 299 |
267 cum->nbytes = (cum->nbytes + align - 1) &~(align - 1); | 300 cum->nbytes = (cum->nbytes + align - 1) &~(align - 1); |
268 | 301 |
269 if (cum->nbytes > 4 * UNITS_PER_WORD) | 302 if (cum->nbytes > 4 * UNITS_PER_WORD) |
270 return 0; | 303 return NULL_RTX; |
271 | 304 |
272 if (type == NULL_TREE | 305 if (type == NULL_TREE |
273 && cum->nbytes + size > 4 * UNITS_PER_WORD) | 306 && cum->nbytes + size > 4 * UNITS_PER_WORD) |
274 return 0; | 307 return NULL_RTX; |
275 | 308 |
276 switch (cum->nbytes / UNITS_PER_WORD) | 309 switch (cum->nbytes / UNITS_PER_WORD) |
277 { | 310 { |
278 case 0: | 311 case 0: |
279 result = gen_rtx_REG (mode, 6); | 312 result = gen_rtx_REG (mode, 6); |
286 break; | 319 break; |
287 case 3: | 320 case 3: |
288 result = gen_rtx_REG (mode, 9); | 321 result = gen_rtx_REG (mode, 9); |
289 break; | 322 break; |
290 default: | 323 default: |
291 result = 0; | 324 result = NULL_RTX; |
292 } | 325 } |
293 | 326 |
294 return result; | 327 return result; |
295 } | 328 } |
296 | 329 |
310 if (mode == BLKmode) | 343 if (mode == BLKmode) |
311 size = int_size_in_bytes (type); | 344 size = int_size_in_bytes (type); |
312 else | 345 else |
313 size = GET_MODE_SIZE (mode); | 346 size = GET_MODE_SIZE (mode); |
314 | 347 |
348 if (size < 1) | |
349 size = 1; | |
350 | |
315 if (type) | 351 if (type) |
316 align = TYPE_ALIGN (type) / BITS_PER_UNIT; | 352 align = TYPE_ALIGN (type) / BITS_PER_UNIT; |
317 else | 353 else |
318 align = size; | 354 align = size; |
319 | 355 |
320 cum->nbytes = (cum->nbytes + align - 1) &~(align - 1); | 356 cum->nbytes = (cum->nbytes + align - 1) & ~ (align - 1); |
321 | 357 |
322 if (cum->nbytes > 4 * UNITS_PER_WORD) | 358 if (cum->nbytes > 4 * UNITS_PER_WORD) |
323 return 0; | 359 return 0; |
324 | 360 |
325 if (cum->nbytes + size <= 4 * UNITS_PER_WORD) | 361 if (cum->nbytes + size <= 4 * UNITS_PER_WORD) |
418 } | 454 } |
419 } | 455 } |
420 | 456 |
421 static bool | 457 static bool |
422 v850_rtx_costs (rtx x, | 458 v850_rtx_costs (rtx x, |
423 int code, | 459 int codearg, |
424 int outer_code ATTRIBUTE_UNUSED, | 460 int outer_code ATTRIBUTE_UNUSED, |
425 int * total, bool speed) | 461 int * total, bool speed) |
426 { | 462 { |
463 enum rtx_code code = (enum rtx_code) codearg; | |
464 | |
427 switch (code) | 465 switch (code) |
428 { | 466 { |
429 case CONST_INT: | 467 case CONST_INT: |
430 case CONST_DOUBLE: | 468 case CONST_DOUBLE: |
431 case CONST: | 469 case CONST: |
461 } | 499 } |
462 } | 500 } |
463 else | 501 else |
464 *total = 20; | 502 *total = 20; |
465 return true; | 503 return true; |
504 | |
505 case ZERO_EXTRACT: | |
506 if (outer_code == COMPARE) | |
507 *total = 0; | |
508 return false; | |
466 | 509 |
467 default: | 510 default: |
468 return false; | 511 return false; |
469 } | 512 } |
470 } | 513 } |
1855 init_stack_free = 4 * num_restore; | 1898 init_stack_free = 4 * num_restore; |
1856 else | 1899 else |
1857 init_stack_free = (signed) actual_fsize; | 1900 init_stack_free = (signed) actual_fsize; |
1858 | 1901 |
1859 /* Deallocate the rest of the stack if it is > 32K. */ | 1902 /* Deallocate the rest of the stack if it is > 32K. */ |
1860 if (actual_fsize > init_stack_free) | 1903 if ((unsigned int) actual_fsize > init_stack_free) |
1861 { | 1904 { |
1862 int diff; | 1905 int diff; |
1863 | 1906 |
1864 diff = actual_fsize - ((interrupt_handler) ? 0 : init_stack_free); | 1907 diff = actual_fsize - ((interrupt_handler) ? 0 : init_stack_free); |
1865 | 1908 |
1929 emit_jump_insn (gen_return_interrupt ()); | 1972 emit_jump_insn (gen_return_interrupt ()); |
1930 } | 1973 } |
1931 else if (actual_fsize) | 1974 else if (actual_fsize) |
1932 emit_jump_insn (gen_return_internal ()); | 1975 emit_jump_insn (gen_return_internal ()); |
1933 else | 1976 else |
1934 emit_jump_insn (gen_return ()); | 1977 emit_jump_insn (gen_return_simple ()); |
1935 } | 1978 } |
1936 | 1979 |
1937 v850_interrupt_cache_p = FALSE; | 1980 v850_interrupt_cache_p = FALSE; |
1938 v850_interrupt_p = FALSE; | 1981 v850_interrupt_p = FALSE; |
1939 } | 1982 } |
2021 | 2064 |
2022 DECL_ATTRIBUTES (decl) = tree_cons | 2065 DECL_ATTRIBUTES (decl) = tree_cons |
2023 (name, NULL, DECL_ATTRIBUTES (decl)); | 2066 (name, NULL, DECL_ATTRIBUTES (decl)); |
2024 } | 2067 } |
2025 | 2068 |
2026 const struct attribute_spec v850_attribute_table[] = | |
2027 { | |
2028 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ | |
2029 { "interrupt_handler", 0, 0, true, false, false, v850_handle_interrupt_attribute }, | |
2030 { "interrupt", 0, 0, true, false, false, v850_handle_interrupt_attribute }, | |
2031 { "sda", 0, 0, true, false, false, v850_handle_data_area_attribute }, | |
2032 { "tda", 0, 0, true, false, false, v850_handle_data_area_attribute }, | |
2033 { "zda", 0, 0, true, false, false, v850_handle_data_area_attribute }, | |
2034 { NULL, 0, 0, false, false, false, NULL } | |
2035 }; | |
2036 | |
2037 /* Handle an "interrupt" attribute; arguments as in | 2069 /* Handle an "interrupt" attribute; arguments as in |
2038 struct attribute_spec.handler. */ | 2070 struct attribute_spec.handler. */ |
2039 static tree | 2071 static tree |
2040 v850_handle_interrupt_attribute (tree * node, | 2072 v850_handle_interrupt_attribute (tree * node, |
2041 tree name, | 2073 tree name, |
2043 int flags ATTRIBUTE_UNUSED, | 2075 int flags ATTRIBUTE_UNUSED, |
2044 bool * no_add_attrs) | 2076 bool * no_add_attrs) |
2045 { | 2077 { |
2046 if (TREE_CODE (*node) != FUNCTION_DECL) | 2078 if (TREE_CODE (*node) != FUNCTION_DECL) |
2047 { | 2079 { |
2048 warning (OPT_Wattributes, "%qs attribute only applies to functions", | 2080 warning (OPT_Wattributes, "%qE attribute only applies to functions", |
2049 IDENTIFIER_POINTER (name)); | 2081 name); |
2050 *no_add_attrs = true; | 2082 *no_add_attrs = true; |
2051 } | 2083 } |
2052 | 2084 |
2053 return NULL_TREE; | 2085 return NULL_TREE; |
2054 } | 2086 } |
2079 switch (TREE_CODE (decl)) | 2111 switch (TREE_CODE (decl)) |
2080 { | 2112 { |
2081 case VAR_DECL: | 2113 case VAR_DECL: |
2082 if (current_function_decl != NULL_TREE) | 2114 if (current_function_decl != NULL_TREE) |
2083 { | 2115 { |
2084 error ("%Jdata area attributes cannot be specified for " | 2116 error_at (DECL_SOURCE_LOCATION (decl), |
2085 "local variables", decl); | 2117 "data area attributes cannot be specified for " |
2118 "local variables"); | |
2086 *no_add_attrs = true; | 2119 *no_add_attrs = true; |
2087 } | 2120 } |
2088 | 2121 |
2089 /* Drop through. */ | 2122 /* Drop through. */ |
2090 | 2123 |
2932 v850_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) | 2965 v850_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) |
2933 { | 2966 { |
2934 /* Return values > 8 bytes in length in memory. */ | 2967 /* Return values > 8 bytes in length in memory. */ |
2935 return int_size_in_bytes (type) > 8 || TYPE_MODE (type) == BLKmode; | 2968 return int_size_in_bytes (type) > 8 || TYPE_MODE (type) == BLKmode; |
2936 } | 2969 } |
2970 | |
2971 /* Worker function for TARGET_FUNCTION_VALUE. */ | |
2972 | |
2973 rtx | |
2974 v850_function_value (const_tree valtype, | |
2975 const_tree fn_decl_or_type ATTRIBUTE_UNUSED, | |
2976 bool outgoing ATTRIBUTE_UNUSED) | |
2977 { | |
2978 return gen_rtx_REG (TYPE_MODE (valtype), 10); | |
2979 } | |
2980 | |
2937 | 2981 |
2938 /* Worker function for TARGET_SETUP_INCOMING_VARARGS. */ | 2982 /* Worker function for TARGET_SETUP_INCOMING_VARARGS. */ |
2939 | 2983 |
2940 static void | 2984 static void |
2941 v850_setup_incoming_varargs (CUMULATIVE_ARGS *ca, | 2985 v850_setup_incoming_varargs (CUMULATIVE_ARGS *ca, |
2945 int second_time ATTRIBUTE_UNUSED) | 2989 int second_time ATTRIBUTE_UNUSED) |
2946 { | 2990 { |
2947 ca->anonymous_args = (!TARGET_GHS ? 1 : 0); | 2991 ca->anonymous_args = (!TARGET_GHS ? 1 : 0); |
2948 } | 2992 } |
2949 | 2993 |
2994 /* Worker function for TARGET_CAN_ELIMINATE. */ | |
2995 | |
2996 static bool | |
2997 v850_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to) | |
2998 { | |
2999 return (to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true); | |
3000 } | |
3001 | |
3002 | |
3003 /* Worker function for TARGET_ASM_TRAMPOLINE_TEMPLATE. */ | |
3004 | |
3005 static void | |
3006 v850_asm_trampoline_template (FILE *f) | |
3007 { | |
3008 fprintf (f, "\tjarl .+4,r12\n"); | |
3009 fprintf (f, "\tld.w 12[r12],r20\n"); | |
3010 fprintf (f, "\tld.w 16[r12],r12\n"); | |
3011 fprintf (f, "\tjmp [r12]\n"); | |
3012 fprintf (f, "\tnop\n"); | |
3013 fprintf (f, "\t.long 0\n"); | |
3014 fprintf (f, "\t.long 0\n"); | |
3015 } | |
3016 | |
3017 /* Worker function for TARGET_TRAMPOLINE_INIT. */ | |
3018 | |
3019 static void | |
3020 v850_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) | |
3021 { | |
3022 rtx mem, fnaddr = XEXP (DECL_RTL (fndecl), 0); | |
3023 | |
3024 emit_block_move (m_tramp, assemble_trampoline_template (), | |
3025 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL); | |
3026 | |
3027 mem = adjust_address (m_tramp, SImode, 16); | |
3028 emit_move_insn (mem, chain_value); | |
3029 mem = adjust_address (m_tramp, SImode, 20); | |
3030 emit_move_insn (mem, fnaddr); | |
3031 } | |
3032 | |
2950 #include "gt-v850.h" | 3033 #include "gt-v850.h" |