Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/iq2000/iq2000.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 used for code generation on Vitesse IQ2000 processors | 1 /* Subroutines used for code generation on Vitesse IQ2000 processors |
2 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 | 2 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 |
3 Free Software Foundation, Inc. | 3 Free Software Foundation, Inc. |
4 | 4 |
5 This file is part of GCC. | 5 This file is part of GCC. |
6 | 6 |
7 GCC is free software; you can redistribute it and/or modify | 7 GCC is free software; you can redistribute it and/or modify |
19 <http://www.gnu.org/licenses/>. */ | 19 <http://www.gnu.org/licenses/>. */ |
20 | 20 |
21 #include "config.h" | 21 #include "config.h" |
22 #include "system.h" | 22 #include "system.h" |
23 #include "coretypes.h" | 23 #include "coretypes.h" |
24 #include <signal.h> | |
25 #include "tm.h" | 24 #include "tm.h" |
26 #include "tree.h" | 25 #include "tree.h" |
27 #include "rtl.h" | 26 #include "rtl.h" |
28 #include "regs.h" | 27 #include "regs.h" |
29 #include "hard-reg-set.h" | 28 #include "hard-reg-set.h" |
35 #include "function.h" | 34 #include "function.h" |
36 #include "expr.h" | 35 #include "expr.h" |
37 #include "optabs.h" | 36 #include "optabs.h" |
38 #include "libfuncs.h" | 37 #include "libfuncs.h" |
39 #include "recog.h" | 38 #include "recog.h" |
40 #include "toplev.h" | 39 #include "diagnostic-core.h" |
41 #include "reload.h" | 40 #include "reload.h" |
42 #include "ggc.h" | 41 #include "ggc.h" |
43 #include "tm_p.h" | 42 #include "tm_p.h" |
44 #include "debug.h" | 43 #include "debug.h" |
45 #include "target.h" | 44 #include "target.h" |
46 #include "target-def.h" | 45 #include "target-def.h" |
47 #include "langhooks.h" | 46 #include "langhooks.h" |
47 #include "df.h" | |
48 | 48 |
49 /* Enumeration for all of the relational tests, so that we can build | 49 /* Enumeration for all of the relational tests, so that we can build |
50 arrays indexed by the test type, and not worry about the order | 50 arrays indexed by the test type, and not worry about the order |
51 of EQ, NE, etc. */ | 51 of EQ, NE, etc. */ |
52 | 52 |
106 int num_gp; /* Number of gp registers saved. */ | 106 int num_gp; /* Number of gp registers saved. */ |
107 }; | 107 }; |
108 | 108 |
109 /* Global variables for machine-dependent things. */ | 109 /* Global variables for machine-dependent things. */ |
110 | 110 |
111 /* List of all IQ2000 punctuation characters used by print_operand. */ | 111 /* List of all IQ2000 punctuation characters used by iq2000_print_operand. */ |
112 char iq2000_print_operand_punct[256]; | 112 static char iq2000_print_operand_punct[256]; |
113 | 113 |
114 /* The target cpu for optimization and scheduling. */ | 114 /* The target cpu for optimization and scheduling. */ |
115 enum processor_type iq2000_tune; | 115 enum processor_type iq2000_tune; |
116 | 116 |
117 /* Which instruction set architecture to use. */ | 117 /* Which instruction set architecture to use. */ |
144 | 144 |
145 | 145 |
146 /* Initialize the GCC target structure. */ | 146 /* Initialize the GCC target structure. */ |
147 static struct machine_function* iq2000_init_machine_status (void); | 147 static struct machine_function* iq2000_init_machine_status (void); |
148 static bool iq2000_handle_option (size_t, const char *, int); | 148 static bool iq2000_handle_option (size_t, const char *, int); |
149 static void iq2000_option_override (void); | |
149 static section *iq2000_select_rtx_section (enum machine_mode, rtx, | 150 static section *iq2000_select_rtx_section (enum machine_mode, rtx, |
150 unsigned HOST_WIDE_INT); | 151 unsigned HOST_WIDE_INT); |
151 static void iq2000_init_builtins (void); | 152 static void iq2000_init_builtins (void); |
152 static rtx iq2000_expand_builtin (tree, rtx, rtx, enum machine_mode, int); | 153 static rtx iq2000_expand_builtin (tree, rtx, rtx, enum machine_mode, int); |
153 static bool iq2000_return_in_memory (const_tree, const_tree); | 154 static bool iq2000_return_in_memory (const_tree, const_tree); |
160 static rtx iq2000_legitimize_address (rtx, rtx, enum machine_mode); | 161 static rtx iq2000_legitimize_address (rtx, rtx, enum machine_mode); |
161 static bool iq2000_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode, | 162 static bool iq2000_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode, |
162 const_tree, bool); | 163 const_tree, bool); |
163 static int iq2000_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, | 164 static int iq2000_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, |
164 tree, bool); | 165 tree, bool); |
166 static rtx iq2000_function_arg (CUMULATIVE_ARGS *, | |
167 enum machine_mode, const_tree, bool); | |
168 static void iq2000_function_arg_advance (CUMULATIVE_ARGS *, | |
169 enum machine_mode, const_tree, bool); | |
170 static unsigned int iq2000_function_arg_boundary (enum machine_mode, | |
171 const_tree); | |
165 static void iq2000_va_start (tree, rtx); | 172 static void iq2000_va_start (tree, rtx); |
166 static bool iq2000_legitimate_address_p (enum machine_mode, rtx, bool); | 173 static bool iq2000_legitimate_address_p (enum machine_mode, rtx, bool); |
167 static bool iq2000_can_eliminate (const int, const int); | 174 static bool iq2000_can_eliminate (const int, const int); |
168 static void iq2000_asm_trampoline_template (FILE *); | 175 static void iq2000_asm_trampoline_template (FILE *); |
169 static void iq2000_trampoline_init (rtx, tree, rtx); | 176 static void iq2000_trampoline_init (rtx, tree, rtx); |
170 static rtx iq2000_function_value (const_tree, const_tree, bool); | 177 static rtx iq2000_function_value (const_tree, const_tree, bool); |
171 static rtx iq2000_libcall_value (enum machine_mode, const_rtx); | 178 static rtx iq2000_libcall_value (enum machine_mode, const_rtx); |
179 static void iq2000_print_operand (FILE *, rtx, int); | |
180 static void iq2000_print_operand_address (FILE *, rtx); | |
181 static bool iq2000_print_operand_punct_valid_p (unsigned char code); | |
182 | |
183 /* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */ | |
184 static const struct default_options iq2000_option_optimization_table[] = | |
185 { | |
186 { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 }, | |
187 { OPT_LEVELS_NONE, 0, NULL, 0 } | |
188 }; | |
172 | 189 |
173 #undef TARGET_INIT_BUILTINS | 190 #undef TARGET_INIT_BUILTINS |
174 #define TARGET_INIT_BUILTINS iq2000_init_builtins | 191 #define TARGET_INIT_BUILTINS iq2000_init_builtins |
175 #undef TARGET_EXPAND_BUILTIN | 192 #undef TARGET_EXPAND_BUILTIN |
176 #define TARGET_EXPAND_BUILTIN iq2000_expand_builtin | 193 #define TARGET_EXPAND_BUILTIN iq2000_expand_builtin |
177 #undef TARGET_ASM_SELECT_RTX_SECTION | 194 #undef TARGET_ASM_SELECT_RTX_SECTION |
178 #define TARGET_ASM_SELECT_RTX_SECTION iq2000_select_rtx_section | 195 #define TARGET_ASM_SELECT_RTX_SECTION iq2000_select_rtx_section |
179 #undef TARGET_HANDLE_OPTION | 196 #undef TARGET_HANDLE_OPTION |
180 #define TARGET_HANDLE_OPTION iq2000_handle_option | 197 #define TARGET_HANDLE_OPTION iq2000_handle_option |
198 #undef TARGET_OPTION_OVERRIDE | |
199 #define TARGET_OPTION_OVERRIDE iq2000_option_override | |
200 #undef TARGET_OPTION_OPTIMIZATION_TABLE | |
201 #define TARGET_OPTION_OPTIMIZATION_TABLE iq2000_option_optimization_table | |
181 #undef TARGET_RTX_COSTS | 202 #undef TARGET_RTX_COSTS |
182 #define TARGET_RTX_COSTS iq2000_rtx_costs | 203 #define TARGET_RTX_COSTS iq2000_rtx_costs |
183 #undef TARGET_ADDRESS_COST | 204 #undef TARGET_ADDRESS_COST |
184 #define TARGET_ADDRESS_COST iq2000_address_cost | 205 #define TARGET_ADDRESS_COST iq2000_address_cost |
185 #undef TARGET_ASM_SELECT_SECTION | 206 #undef TARGET_ASM_SELECT_SECTION |
190 | 211 |
191 /* The assembler supports switchable .bss sections, but | 212 /* The assembler supports switchable .bss sections, but |
192 iq2000_select_section doesn't yet make use of them. */ | 213 iq2000_select_section doesn't yet make use of them. */ |
193 #undef TARGET_HAVE_SWITCHABLE_BSS_SECTIONS | 214 #undef TARGET_HAVE_SWITCHABLE_BSS_SECTIONS |
194 #define TARGET_HAVE_SWITCHABLE_BSS_SECTIONS false | 215 #define TARGET_HAVE_SWITCHABLE_BSS_SECTIONS false |
216 | |
217 #undef TARGET_PRINT_OPERAND | |
218 #define TARGET_PRINT_OPERAND iq2000_print_operand | |
219 #undef TARGET_PRINT_OPERAND_ADDRESS | |
220 #define TARGET_PRINT_OPERAND_ADDRESS iq2000_print_operand_address | |
221 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P | |
222 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P iq2000_print_operand_punct_valid_p | |
195 | 223 |
196 #undef TARGET_PROMOTE_FUNCTION_MODE | 224 #undef TARGET_PROMOTE_FUNCTION_MODE |
197 #define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote | 225 #define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote |
198 #undef TARGET_PROMOTE_PROTOTYPES | 226 #undef TARGET_PROMOTE_PROTOTYPES |
199 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true | 227 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true |
208 #define TARGET_PASS_BY_REFERENCE iq2000_pass_by_reference | 236 #define TARGET_PASS_BY_REFERENCE iq2000_pass_by_reference |
209 #undef TARGET_CALLEE_COPIES | 237 #undef TARGET_CALLEE_COPIES |
210 #define TARGET_CALLEE_COPIES hook_callee_copies_named | 238 #define TARGET_CALLEE_COPIES hook_callee_copies_named |
211 #undef TARGET_ARG_PARTIAL_BYTES | 239 #undef TARGET_ARG_PARTIAL_BYTES |
212 #define TARGET_ARG_PARTIAL_BYTES iq2000_arg_partial_bytes | 240 #define TARGET_ARG_PARTIAL_BYTES iq2000_arg_partial_bytes |
241 #undef TARGET_FUNCTION_ARG | |
242 #define TARGET_FUNCTION_ARG iq2000_function_arg | |
243 #undef TARGET_FUNCTION_ARG_ADVANCE | |
244 #define TARGET_FUNCTION_ARG_ADVANCE iq2000_function_arg_advance | |
245 #undef TARGET_FUNCTION_ARG_BOUNDARY | |
246 #define TARGET_FUNCTION_ARG_BOUNDARY iq2000_function_arg_boundary | |
213 | 247 |
214 #undef TARGET_SETUP_INCOMING_VARARGS | 248 #undef TARGET_SETUP_INCOMING_VARARGS |
215 #define TARGET_SETUP_INCOMING_VARARGS iq2000_setup_incoming_varargs | 249 #define TARGET_SETUP_INCOMING_VARARGS iq2000_setup_incoming_varargs |
216 #undef TARGET_STRICT_ARGUMENT_NAMING | 250 #undef TARGET_STRICT_ARGUMENT_NAMING |
217 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true | 251 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true |
1107 } | 1141 } |
1108 | 1142 |
1109 /* Advance the argument of type TYPE and mode MODE to the next argument | 1143 /* Advance the argument of type TYPE and mode MODE to the next argument |
1110 position in CUM. */ | 1144 position in CUM. */ |
1111 | 1145 |
1112 void | 1146 static void |
1113 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, | 1147 iq2000_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, |
1114 int named) | 1148 const_tree type, bool named) |
1115 { | 1149 { |
1116 if (TARGET_DEBUG_D_MODE) | 1150 if (TARGET_DEBUG_D_MODE) |
1117 { | 1151 { |
1118 fprintf (stderr, | 1152 fprintf (stderr, |
1119 "function_adv({gp reg found = %d, arg # = %2d, words = %2d}, %4s, ", | 1153 "function_adv({gp reg found = %d, arg # = %2d, words = %2d}, %4s, ", |
1120 cum->gp_reg_found, cum->arg_number, cum->arg_words, | 1154 cum->gp_reg_found, cum->arg_number, cum->arg_words, |
1121 GET_MODE_NAME (mode)); | 1155 GET_MODE_NAME (mode)); |
1122 fprintf (stderr, "%p", (void *) type); | 1156 fprintf (stderr, "%p", CONST_CAST2 (void *, const_tree, type)); |
1123 fprintf (stderr, ", %d )\n\n", named); | 1157 fprintf (stderr, ", %d )\n\n", named); |
1124 } | 1158 } |
1125 | 1159 |
1126 cum->arg_number++; | 1160 cum->arg_number++; |
1127 switch (mode) | 1161 switch (mode) |
1176 } | 1210 } |
1177 | 1211 |
1178 /* Return an RTL expression containing the register for the given mode MODE | 1212 /* Return an RTL expression containing the register for the given mode MODE |
1179 and type TYPE in CUM, or 0 if the argument is to be passed on the stack. */ | 1213 and type TYPE in CUM, or 0 if the argument is to be passed on the stack. */ |
1180 | 1214 |
1181 struct rtx_def * | 1215 static rtx |
1182 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, const_tree type, | 1216 iq2000_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, |
1183 int named) | 1217 const_tree type, bool named) |
1184 { | 1218 { |
1185 rtx ret; | 1219 rtx ret; |
1186 int regbase = -1; | 1220 int regbase = -1; |
1187 int bias = 0; | 1221 int bias = 0; |
1188 unsigned int *arg_words = &cum->arg_words; | 1222 unsigned int *arg_words = &cum->arg_words; |
1261 ret = gen_rtx_REG (mode, regbase + *arg_words + bias); | 1295 ret = gen_rtx_REG (mode, regbase + *arg_words + bias); |
1262 else | 1296 else |
1263 { | 1297 { |
1264 tree field; | 1298 tree field; |
1265 | 1299 |
1266 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) | 1300 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) |
1267 if (TREE_CODE (field) == FIELD_DECL | 1301 if (TREE_CODE (field) == FIELD_DECL |
1268 && TREE_CODE (TREE_TYPE (field)) == REAL_TYPE | 1302 && TREE_CODE (TREE_TYPE (field)) == REAL_TYPE |
1269 && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD | 1303 && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD |
1270 && host_integerp (bit_position (field), 0) | 1304 && host_integerp (bit_position (field), 0) |
1271 && int_bit_position (field) % BITS_PER_WORD == 0) | 1305 && int_bit_position (field) % BITS_PER_WORD == 0) |
1298 field = TYPE_FIELDS (type); | 1332 field = TYPE_FIELDS (type); |
1299 for (i = 0; i < chunks; i++) | 1333 for (i = 0; i < chunks; i++) |
1300 { | 1334 { |
1301 rtx reg; | 1335 rtx reg; |
1302 | 1336 |
1303 for (; field; field = TREE_CHAIN (field)) | 1337 for (; field; field = DECL_CHAIN (field)) |
1304 if (TREE_CODE (field) == FIELD_DECL | 1338 if (TREE_CODE (field) == FIELD_DECL |
1305 && int_bit_position (field) >= bitpos) | 1339 && int_bit_position (field) >= bitpos) |
1306 break; | 1340 break; |
1307 | 1341 |
1308 if (field | 1342 if (field |
1340 } | 1374 } |
1341 | 1375 |
1342 return ret; | 1376 return ret; |
1343 } | 1377 } |
1344 | 1378 |
1379 static unsigned int | |
1380 iq2000_function_arg_boundary (enum machine_mode mode, const_tree type) | |
1381 { | |
1382 return (type != NULL_TREE | |
1383 ? (TYPE_ALIGN (type) <= PARM_BOUNDARY | |
1384 ? PARM_BOUNDARY | |
1385 : TYPE_ALIGN (type)) | |
1386 : (GET_MODE_ALIGNMENT (mode) <= PARM_BOUNDARY | |
1387 ? PARM_BOUNDARY | |
1388 : GET_MODE_ALIGNMENT (mode))); | |
1389 } | |
1390 | |
1345 static int | 1391 static int |
1346 iq2000_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode, | 1392 iq2000_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode, |
1347 tree type ATTRIBUTE_UNUSED, | 1393 tree type ATTRIBUTE_UNUSED, |
1348 bool named ATTRIBUTE_UNUSED) | 1394 bool named ATTRIBUTE_UNUSED) |
1349 { | 1395 { |
1383 /* Allocate a chunk of memory for per-function machine-dependent data. */ | 1429 /* Allocate a chunk of memory for per-function machine-dependent data. */ |
1384 | 1430 |
1385 static struct machine_function * | 1431 static struct machine_function * |
1386 iq2000_init_machine_status (void) | 1432 iq2000_init_machine_status (void) |
1387 { | 1433 { |
1388 struct machine_function *f; | 1434 return ggc_alloc_cleared_machine_function (); |
1389 | |
1390 f = GGC_CNEW (struct machine_function); | |
1391 | |
1392 return f; | |
1393 } | 1435 } |
1394 | 1436 |
1395 /* Implement TARGET_HANDLE_OPTION. */ | 1437 /* Implement TARGET_HANDLE_OPTION. */ |
1396 | 1438 |
1397 static bool | 1439 static bool |
1419 } | 1461 } |
1420 } | 1462 } |
1421 | 1463 |
1422 /* Detect any conflicts in the switches. */ | 1464 /* Detect any conflicts in the switches. */ |
1423 | 1465 |
1424 void | 1466 static void |
1425 override_options (void) | 1467 iq2000_option_override (void) |
1426 { | 1468 { |
1427 target_flags &= ~MASK_GPOPT; | 1469 target_flags &= ~MASK_GPOPT; |
1428 | 1470 |
1429 iq2000_isa = IQ2000_ISA_DEFAULT; | 1471 iq2000_isa = IQ2000_ISA_DEFAULT; |
1430 | 1472 |
1603 HOST_WIDE_INT extra_size; /* # extra bytes. */ | 1645 HOST_WIDE_INT extra_size; /* # extra bytes. */ |
1604 HOST_WIDE_INT gp_reg_rounded; /* # bytes needed to store gp after rounding. */ | 1646 HOST_WIDE_INT gp_reg_rounded; /* # bytes needed to store gp after rounding. */ |
1605 HOST_WIDE_INT gp_reg_size; /* # bytes needed to store gp regs. */ | 1647 HOST_WIDE_INT gp_reg_size; /* # bytes needed to store gp regs. */ |
1606 HOST_WIDE_INT fp_reg_size; /* # bytes needed to store fp regs. */ | 1648 HOST_WIDE_INT fp_reg_size; /* # bytes needed to store fp regs. */ |
1607 long mask; /* mask of saved gp registers. */ | 1649 long mask; /* mask of saved gp registers. */ |
1608 int fp_inc; /* 1 or 2 depending on the size of fp regs. */ | |
1609 long fp_bits; /* bitmask to use for each fp register. */ | |
1610 | 1650 |
1611 gp_reg_size = 0; | 1651 gp_reg_size = 0; |
1612 fp_reg_size = 0; | 1652 fp_reg_size = 0; |
1613 mask = 0; | 1653 mask = 0; |
1614 extra_size = IQ2000_STACK_ALIGN ((0)); | 1654 extra_size = IQ2000_STACK_ALIGN ((0)); |
1645 gp_reg_size += GET_MODE_SIZE (gpr_mode); | 1685 gp_reg_size += GET_MODE_SIZE (gpr_mode); |
1646 mask |= 1L << (regno - GP_REG_FIRST); | 1686 mask |= 1L << (regno - GP_REG_FIRST); |
1647 } | 1687 } |
1648 } | 1688 } |
1649 | 1689 |
1650 fp_inc = 2; | |
1651 fp_bits = 3; | |
1652 gp_reg_rounded = IQ2000_STACK_ALIGN (gp_reg_size); | 1690 gp_reg_rounded = IQ2000_STACK_ALIGN (gp_reg_size); |
1653 total_size += gp_reg_rounded + IQ2000_STACK_ALIGN (fp_reg_size); | 1691 total_size += gp_reg_rounded + IQ2000_STACK_ALIGN (fp_reg_size); |
1654 | 1692 |
1655 /* The gp reg is caller saved, so there is no need for leaf routines | 1693 /* The gp reg is caller saved, so there is no need for leaf routines |
1656 (total_size == extra_size) to save the gp reg. */ | 1694 (total_size == extra_size) to save the gp reg. */ |
1701 bool | 1739 bool |
1702 iq2000_can_eliminate (const int from, const int to) | 1740 iq2000_can_eliminate (const int from, const int to) |
1703 { | 1741 { |
1704 return (from == RETURN_ADDRESS_POINTER_REGNUM | 1742 return (from == RETURN_ADDRESS_POINTER_REGNUM |
1705 && (! leaf_function_p () | 1743 && (! leaf_function_p () |
1706 || (to == GP_REG_FIRST + 31 && leaf_function_p))) | 1744 || (to == GP_REG_FIRST + 31 && leaf_function_p ()))) |
1707 || (from != RETURN_ADDRESS_POINTER_REGNUM | 1745 || (from != RETURN_ADDRESS_POINTER_REGNUM |
1708 && (to == HARD_FRAME_POINTER_REGNUM | 1746 && (to == HARD_FRAME_POINTER_REGNUM |
1709 || (to == STACK_POINTER_REGNUM | 1747 || (to == STACK_POINTER_REGNUM |
1710 && ! frame_pointer_needed))); | 1748 && ! frame_pointer_needed))); |
1711 } | 1749 } |
1730 (offset) = 0; | 1768 (offset) = 0; |
1731 else (offset) = cfun->machine->gp_sp_offset | 1769 else (offset) = cfun->machine->gp_sp_offset |
1732 + ((UNITS_PER_WORD - (POINTER_SIZE / BITS_PER_UNIT)) | 1770 + ((UNITS_PER_WORD - (POINTER_SIZE / BITS_PER_UNIT)) |
1733 * (BYTES_BIG_ENDIAN != 0)); | 1771 * (BYTES_BIG_ENDIAN != 0)); |
1734 } | 1772 } |
1773 else | |
1774 gcc_unreachable (); | |
1735 | 1775 |
1736 return offset; | 1776 return offset; |
1737 } | 1777 } |
1738 | 1778 |
1739 /* Common code to emit the insns (or to write the instructions to a file) | 1779 /* Common code to emit the insns (or to write the instructions to a file) |
1892 tree type = build_pointer_type (fntype); | 1932 tree type = build_pointer_type (fntype); |
1893 tree function_result_decl = build_decl (BUILTINS_LOCATION, | 1933 tree function_result_decl = build_decl (BUILTINS_LOCATION, |
1894 PARM_DECL, NULL_TREE, type); | 1934 PARM_DECL, NULL_TREE, type); |
1895 | 1935 |
1896 DECL_ARG_TYPE (function_result_decl) = type; | 1936 DECL_ARG_TYPE (function_result_decl) = type; |
1897 TREE_CHAIN (function_result_decl) = fnargs; | 1937 DECL_CHAIN (function_result_decl) = fnargs; |
1898 fnargs = function_result_decl; | 1938 fnargs = function_result_decl; |
1899 } | 1939 } |
1900 | 1940 |
1901 /* For arguments passed in registers, find the register number | 1941 /* For arguments passed in registers, find the register number |
1902 of the first argument in the variable part of the argument list, | 1942 of the first argument in the variable part of the argument list, |
1918 { | 1958 { |
1919 passed_type = build_pointer_type (passed_type); | 1959 passed_type = build_pointer_type (passed_type); |
1920 passed_mode = Pmode; | 1960 passed_mode = Pmode; |
1921 } | 1961 } |
1922 | 1962 |
1923 entry_parm = FUNCTION_ARG (args_so_far, passed_mode, passed_type, 1); | 1963 entry_parm = iq2000_function_arg (&args_so_far, passed_mode, |
1924 | 1964 passed_type, true); |
1925 FUNCTION_ARG_ADVANCE (args_so_far, passed_mode, passed_type, 1); | 1965 |
1926 next_arg = TREE_CHAIN (cur_arg); | 1966 iq2000_function_arg_advance (&args_so_far, passed_mode, |
1967 passed_type, true); | |
1968 next_arg = DECL_CHAIN (cur_arg); | |
1927 | 1969 |
1928 if (entry_parm && store_args_on_stack) | 1970 if (entry_parm && store_args_on_stack) |
1929 { | 1971 { |
1930 if (next_arg == 0 | 1972 if (next_arg == 0 |
1931 && DECL_NAME (cur_arg) | 1973 && DECL_NAME (cur_arg) |
1959 } | 2001 } |
1960 } | 2002 } |
1961 | 2003 |
1962 /* In order to pass small structures by value in registers we need to | 2004 /* In order to pass small structures by value in registers we need to |
1963 shift the value into the high part of the register. | 2005 shift the value into the high part of the register. |
1964 Function_arg has encoded a PARALLEL rtx, holding a vector of | 2006 iq2000_unction_arg has encoded a PARALLEL rtx, holding a vector of |
1965 adjustments to be made as the next_arg_reg variable, so we split up the | 2007 adjustments to be made as the next_arg_reg variable, so we split up |
1966 insns, and emit them separately. */ | 2008 the insns, and emit them separately. */ |
1967 next_arg_reg = FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1); | 2009 next_arg_reg = iq2000_function_arg (&args_so_far, VOIDmode, |
2010 void_type_node, true); | |
1968 if (next_arg_reg != 0 && GET_CODE (next_arg_reg) == PARALLEL) | 2011 if (next_arg_reg != 0 && GET_CODE (next_arg_reg) == PARALLEL) |
1969 { | 2012 { |
1970 rtvec adjust = XVEC (next_arg_reg, 0); | 2013 rtvec adjust = XVEC (next_arg_reg, 0); |
1971 int num = GET_NUM_ELEM (adjust); | 2014 int num = GET_NUM_ELEM (adjust); |
1972 | 2015 |
1973 for (i = 0; i < num; i++) | 2016 for (i = 0; i < num; i++) |
1974 { | 2017 { |
1975 rtx insn, pattern; | 2018 rtx pattern; |
1976 | 2019 |
1977 pattern = RTVEC_ELT (adjust, i); | 2020 pattern = RTVEC_ELT (adjust, i); |
1978 if (GET_CODE (pattern) != SET | 2021 if (GET_CODE (pattern) != SET |
1979 || GET_CODE (SET_SRC (pattern)) != ASHIFT) | 2022 || GET_CODE (SET_SRC (pattern)) != ASHIFT) |
1980 abort_with_insn (pattern, "Insn is not a shift"); | 2023 abort_with_insn (pattern, "Insn is not a shift"); |
1981 PUT_CODE (SET_SRC (pattern), ASHIFTRT); | 2024 PUT_CODE (SET_SRC (pattern), ASHIFTRT); |
1982 | 2025 |
1983 insn = emit_insn (pattern); | 2026 emit_insn (pattern); |
1984 } | 2027 } |
1985 } | 2028 } |
1986 | 2029 |
1987 tsize = compute_frame_size (get_frame_size ()); | 2030 tsize = compute_frame_size (get_frame_size ()); |
1988 | 2031 |
1989 /* If this function is a varargs function, store any registers that | 2032 /* If this function is a varargs function, store any registers that |
1990 would normally hold arguments ($4 - $7) on the stack. */ | 2033 would normally hold arguments ($4 - $7) on the stack. */ |
1991 if (store_args_on_stack | 2034 if (store_args_on_stack |
1992 && ((TYPE_ARG_TYPES (fntype) != 0 | 2035 && (stdarg_p (fntype) |
1993 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype))) | |
1994 != void_type_node)) | |
1995 || last_arg_is_vararg_marker)) | 2036 || last_arg_is_vararg_marker)) |
1996 { | 2037 { |
1997 int offset = (regno - GP_ARG_FIRST) * UNITS_PER_WORD; | 2038 int offset = (regno - GP_ARG_FIRST) * UNITS_PER_WORD; |
1998 rtx ptr = stack_pointer_rtx; | 2039 rtx ptr = stack_pointer_rtx; |
1999 | 2040 |
2135 return cfun->machine->total_size == 0; | 2176 return cfun->machine->total_size == 0; |
2136 | 2177 |
2137 return compute_frame_size (get_frame_size ()) == 0; | 2178 return compute_frame_size (get_frame_size ()) == 0; |
2138 } | 2179 } |
2139 | 2180 |
2140 /* Returns nonzero if X contains a SYMBOL_REF. */ | |
2141 | |
2142 static int | |
2143 symbolic_expression_p (rtx x) | |
2144 { | |
2145 if (GET_CODE (x) == SYMBOL_REF) | |
2146 return 1; | |
2147 | |
2148 if (GET_CODE (x) == CONST) | |
2149 return symbolic_expression_p (XEXP (x, 0)); | |
2150 | |
2151 if (UNARY_P (x)) | |
2152 return symbolic_expression_p (XEXP (x, 0)); | |
2153 | |
2154 if (ARITHMETIC_P (x)) | |
2155 return (symbolic_expression_p (XEXP (x, 0)) | |
2156 || symbolic_expression_p (XEXP (x, 1))); | |
2157 | |
2158 return 0; | |
2159 } | |
2160 | |
2161 /* Choose the section to use for the constant rtx expression X that has | 2181 /* Choose the section to use for the constant rtx expression X that has |
2162 mode MODE. */ | 2182 mode MODE. */ |
2163 | 2183 |
2164 static section * | 2184 static section * |
2165 iq2000_select_rtx_section (enum machine_mode mode, rtx x ATTRIBUTE_UNUSED, | 2185 iq2000_select_rtx_section (enum machine_mode mode, rtx x ATTRIBUTE_UNUSED, |
2221 bool outgoing ATTRIBUTE_UNUSED) | 2241 bool outgoing ATTRIBUTE_UNUSED) |
2222 { | 2242 { |
2223 int reg = GP_RETURN; | 2243 int reg = GP_RETURN; |
2224 enum machine_mode mode = TYPE_MODE (valtype); | 2244 enum machine_mode mode = TYPE_MODE (valtype); |
2225 int unsignedp = TYPE_UNSIGNED (valtype); | 2245 int unsignedp = TYPE_UNSIGNED (valtype); |
2226 tree func = fn_decl_or_type; | 2246 const_tree func = fn_decl_or_type; |
2227 | 2247 |
2228 if (fn_decl_or_type | 2248 if (fn_decl_or_type |
2229 && !DECL_P (fn_decl_or_type)) | 2249 && !DECL_P (fn_decl_or_type)) |
2230 fn_decl_or_type = NULL; | 2250 fn_decl_or_type = NULL; |
2231 | 2251 |
2274 get double copies of any offsets generated for small structs | 2294 get double copies of any offsets generated for small structs |
2275 passed in registers. */ | 2295 passed in registers. */ |
2276 CUMULATIVE_ARGS temp; | 2296 CUMULATIVE_ARGS temp; |
2277 | 2297 |
2278 temp = *cum; | 2298 temp = *cum; |
2279 if (FUNCTION_ARG (temp, mode, type, named) != 0) | 2299 if (iq2000_function_arg (&temp, mode, type, named) != 0) |
2280 return 1; | 2300 return 1; |
2281 } | 2301 } |
2282 | 2302 |
2283 if (type == NULL_TREE || mode == DImode || mode == DFmode) | 2303 if (type == NULL_TREE || mode == DImode || mode == DFmode) |
2284 return 0; | 2304 return 0; |
2621 | 2641 |
2622 mode[0] = insn_data[icode].operand[0].mode; | 2642 mode[0] = insn_data[icode].operand[0].mode; |
2623 for (i = 0; i < argcount; i++) | 2643 for (i = 0; i < argcount; i++) |
2624 { | 2644 { |
2625 arg[i] = CALL_EXPR_ARG (exp, i); | 2645 arg[i] = CALL_EXPR_ARG (exp, i); |
2626 op[i] = expand_expr (arg[i], NULL_RTX, VOIDmode, 0); | 2646 op[i] = expand_normal (arg[i]); |
2627 mode[i] = insn_data[icode].operand[i].mode; | 2647 mode[i] = insn_data[icode].operand[i].mode; |
2628 if (code[i] == CONST_INT && GET_CODE (op[i]) != CONST_INT) | 2648 if (code[i] == CONST_INT && GET_CODE (op[i]) != CONST_INT) |
2629 error ("argument %qd is not a constant", i + 1); | 2649 error ("argument %qd is not a constant", i + 1); |
2630 if (code[i] == REG | 2650 if (code[i] == REG |
2631 && ! (*insn_data[icode].operand[i].predicate) (op[i], mode[i])) | 2651 && ! (*insn_data[icode].operand[i].predicate) (op[i], mode[i])) |
2922 | 2942 |
2923 /* A C compound statement to output to stdio stream STREAM the | 2943 /* A C compound statement to output to stdio stream STREAM the |
2924 assembler syntax for an instruction operand that is a memory | 2944 assembler syntax for an instruction operand that is a memory |
2925 reference whose address is ADDR. ADDR is an RTL expression. */ | 2945 reference whose address is ADDR. ADDR is an RTL expression. */ |
2926 | 2946 |
2927 void | 2947 static void |
2928 print_operand_address (FILE * file, rtx addr) | 2948 iq2000_print_operand_address (FILE * file, rtx addr) |
2929 { | 2949 { |
2930 if (!addr) | 2950 if (!addr) |
2931 error ("PRINT_OPERAND_ADDRESS, null pointer"); | 2951 error ("PRINT_OPERAND_ADDRESS, null pointer"); |
2932 | 2952 |
2933 else | 2953 else |
2948 if (GET_CODE (arg0) != REG) | 2968 if (GET_CODE (arg0) != REG) |
2949 abort_with_insn (addr, | 2969 abort_with_insn (addr, |
2950 "PRINT_OPERAND_ADDRESS, LO_SUM with #1 not REG."); | 2970 "PRINT_OPERAND_ADDRESS, LO_SUM with #1 not REG."); |
2951 | 2971 |
2952 fprintf (file, "%%lo("); | 2972 fprintf (file, "%%lo("); |
2953 print_operand_address (file, arg1); | 2973 iq2000_print_operand_address (file, arg1); |
2954 fprintf (file, ")(%s)", reg_names [REGNO (arg0)]); | 2974 fprintf (file, ")(%s)", reg_names [REGNO (arg0)]); |
2955 } | 2975 } |
2956 break; | 2976 break; |
2957 | 2977 |
2958 case PLUS: | 2978 case PLUS: |
3050 '@' Print the name of the assembler temporary register (at or $1). | 3070 '@' Print the name of the assembler temporary register (at or $1). |
3051 '.' Print the name of the register with a hard-wired zero (zero or $0). | 3071 '.' Print the name of the register with a hard-wired zero (zero or $0). |
3052 '$' Print the name of the stack pointer register (sp or $29). | 3072 '$' Print the name of the stack pointer register (sp or $29). |
3053 '+' Print the name of the gp register (gp or $28). */ | 3073 '+' Print the name of the gp register (gp or $28). */ |
3054 | 3074 |
3055 void | 3075 static void |
3056 print_operand (FILE *file, rtx op, int letter) | 3076 iq2000_print_operand (FILE *file, rtx op, int letter) |
3057 { | 3077 { |
3058 enum rtx_code code; | 3078 enum rtx_code code; |
3059 | 3079 |
3060 if (PRINT_OPERAND_PUNCT_VALID_P (letter)) | 3080 if (iq2000_print_operand_punct_valid_p (letter)) |
3061 { | 3081 { |
3062 switch (letter) | 3082 switch (letter) |
3063 { | 3083 { |
3064 case '?': | 3084 case '?': |
3065 if (iq2000_branch_likely) | 3085 if (iq2000_branch_likely) |
3168 { | 3188 { |
3169 int value; | 3189 int value; |
3170 if (code != CONST_INT | 3190 if (code != CONST_INT |
3171 || (value = exact_log2 (INTVAL (op))) < 0) | 3191 || (value = exact_log2 (INTVAL (op))) < 0) |
3172 output_operand_lossage ("invalid %%p value"); | 3192 output_operand_lossage ("invalid %%p value"); |
3173 fprintf (file, "%d", value); | 3193 else |
3194 fprintf (file, "%d", value); | |
3174 } | 3195 } |
3175 | 3196 |
3176 else if (letter == 'Z') | 3197 else if (letter == 'Z') |
3177 { | 3198 { |
3178 gcc_unreachable (); | 3199 gcc_unreachable (); |
3236 else if (letter == 't') | 3257 else if (letter == 't') |
3237 fputs (code == EQ ? "t" : "f", file); | 3258 fputs (code == EQ ? "t" : "f", file); |
3238 | 3259 |
3239 else if (code == CONST && GET_CODE (XEXP (op, 0)) == REG) | 3260 else if (code == CONST && GET_CODE (XEXP (op, 0)) == REG) |
3240 { | 3261 { |
3241 print_operand (file, XEXP (op, 0), letter); | 3262 iq2000_print_operand (file, XEXP (op, 0), letter); |
3242 } | 3263 } |
3243 | 3264 |
3244 else | 3265 else |
3245 output_addr_const (file, op); | 3266 output_addr_const (file, op); |
3246 } | 3267 } |
3247 | 3268 |
3269 static bool | |
3270 iq2000_print_operand_punct_valid_p (unsigned char code) | |
3271 { | |
3272 return iq2000_print_operand_punct[code]; | |
3273 } | |
3248 | 3274 |
3249 /* For the IQ2000, transform: | 3275 /* For the IQ2000, transform: |
3250 | 3276 |
3251 memory(X + <large int>) | 3277 memory(X + <large int>) |
3252 into: | 3278 into: |