Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/iq2000/iq2000.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | f6334be47118 |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
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, 2010 | 2 Copyright (C) 2003-2017 Free Software Foundation, Inc. |
3 Free Software Foundation, Inc. | |
4 | 3 |
5 This file is part of GCC. | 4 This file is part of GCC. |
6 | 5 |
7 GCC is free software; you can redistribute it and/or modify | 6 GCC is free software; you can redistribute it and/or modify |
8 it under the terms of the GNU General Public License as published by | 7 it under the terms of the GNU General Public License as published by |
19 <http://www.gnu.org/licenses/>. */ | 18 <http://www.gnu.org/licenses/>. */ |
20 | 19 |
21 #include "config.h" | 20 #include "config.h" |
22 #include "system.h" | 21 #include "system.h" |
23 #include "coretypes.h" | 22 #include "coretypes.h" |
24 #include "tm.h" | 23 #include "backend.h" |
24 #include "target.h" | |
25 #include "rtl.h" | |
25 #include "tree.h" | 26 #include "tree.h" |
26 #include "rtl.h" | 27 #include "stringpool.h" |
28 #include "attribs.h" | |
29 #include "df.h" | |
30 #include "memmodel.h" | |
31 #include "tm_p.h" | |
32 #include "optabs.h" | |
27 #include "regs.h" | 33 #include "regs.h" |
28 #include "hard-reg-set.h" | 34 #include "emit-rtl.h" |
29 #include "insn-config.h" | 35 #include "recog.h" |
30 #include "conditions.h" | 36 #include "diagnostic-core.h" |
37 #include "stor-layout.h" | |
38 #include "calls.h" | |
39 #include "varasm.h" | |
31 #include "output.h" | 40 #include "output.h" |
32 #include "insn-attr.h" | 41 #include "insn-attr.h" |
33 #include "flags.h" | 42 #include "explow.h" |
34 #include "function.h" | |
35 #include "expr.h" | 43 #include "expr.h" |
36 #include "optabs.h" | 44 #include "langhooks.h" |
37 #include "libfuncs.h" | 45 #include "builtins.h" |
38 #include "recog.h" | 46 |
39 #include "diagnostic-core.h" | 47 /* This file should be included last. */ |
40 #include "reload.h" | |
41 #include "ggc.h" | |
42 #include "tm_p.h" | |
43 #include "debug.h" | |
44 #include "target.h" | |
45 #include "target-def.h" | 48 #include "target-def.h" |
46 #include "langhooks.h" | |
47 #include "df.h" | |
48 | 49 |
49 /* Enumeration for all of the relational tests, so that we can build | 50 /* 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 | 51 arrays indexed by the test type, and not worry about the order |
51 of EQ, NE, etc. */ | 52 of EQ, NE, etc. */ |
52 | 53 |
109 /* Global variables for machine-dependent things. */ | 110 /* Global variables for machine-dependent things. */ |
110 | 111 |
111 /* List of all IQ2000 punctuation characters used by iq2000_print_operand. */ | 112 /* List of all IQ2000 punctuation characters used by iq2000_print_operand. */ |
112 static char iq2000_print_operand_punct[256]; | 113 static char iq2000_print_operand_punct[256]; |
113 | 114 |
114 /* The target cpu for optimization and scheduling. */ | |
115 enum processor_type iq2000_tune; | |
116 | |
117 /* Which instruction set architecture to use. */ | 115 /* Which instruction set architecture to use. */ |
118 int iq2000_isa; | 116 int iq2000_isa; |
119 | 117 |
120 /* Local variables. */ | 118 /* Local variables. */ |
121 | 119 |
138 static rtx iq2000_load_reg2; | 136 static rtx iq2000_load_reg2; |
139 static rtx iq2000_load_reg3; | 137 static rtx iq2000_load_reg3; |
140 static rtx iq2000_load_reg4; | 138 static rtx iq2000_load_reg4; |
141 | 139 |
142 /* Mode used for saving/restoring general purpose registers. */ | 140 /* Mode used for saving/restoring general purpose registers. */ |
143 static enum machine_mode gpr_mode; | 141 static machine_mode gpr_mode; |
144 | 142 |
145 | 143 |
146 /* Initialize the GCC target structure. */ | 144 /* Initialize the GCC target structure. */ |
147 static struct machine_function* iq2000_init_machine_status (void); | 145 static struct machine_function* iq2000_init_machine_status (void); |
148 static bool iq2000_handle_option (size_t, const char *, int); | |
149 static void iq2000_option_override (void); | 146 static void iq2000_option_override (void); |
150 static section *iq2000_select_rtx_section (enum machine_mode, rtx, | 147 static section *iq2000_select_rtx_section (machine_mode, rtx, |
151 unsigned HOST_WIDE_INT); | 148 unsigned HOST_WIDE_INT); |
152 static void iq2000_init_builtins (void); | 149 static void iq2000_init_builtins (void); |
153 static rtx iq2000_expand_builtin (tree, rtx, rtx, enum machine_mode, int); | 150 static rtx iq2000_expand_builtin (tree, rtx, rtx, machine_mode, int); |
154 static bool iq2000_return_in_memory (const_tree, const_tree); | 151 static bool iq2000_return_in_memory (const_tree, const_tree); |
155 static void iq2000_setup_incoming_varargs (CUMULATIVE_ARGS *, | 152 static void iq2000_setup_incoming_varargs (cumulative_args_t, |
156 enum machine_mode, tree, int *, | 153 machine_mode, tree, int *, |
157 int); | 154 int); |
158 static bool iq2000_rtx_costs (rtx, int, int, int *, bool); | 155 static bool iq2000_rtx_costs (rtx, machine_mode, int, int, int *, bool); |
159 static int iq2000_address_cost (rtx, bool); | 156 static int iq2000_address_cost (rtx, machine_mode, addr_space_t, |
157 bool); | |
160 static section *iq2000_select_section (tree, int, unsigned HOST_WIDE_INT); | 158 static section *iq2000_select_section (tree, int, unsigned HOST_WIDE_INT); |
161 static rtx iq2000_legitimize_address (rtx, rtx, enum machine_mode); | 159 static rtx iq2000_legitimize_address (rtx, rtx, machine_mode); |
162 static bool iq2000_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode, | 160 static bool iq2000_pass_by_reference (cumulative_args_t, machine_mode, |
163 const_tree, bool); | 161 const_tree, bool); |
164 static int iq2000_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, | 162 static int iq2000_arg_partial_bytes (cumulative_args_t, machine_mode, |
165 tree, bool); | 163 tree, bool); |
166 static rtx iq2000_function_arg (CUMULATIVE_ARGS *, | 164 static rtx iq2000_function_arg (cumulative_args_t, |
167 enum machine_mode, const_tree, bool); | 165 machine_mode, const_tree, bool); |
168 static void iq2000_function_arg_advance (CUMULATIVE_ARGS *, | 166 static void iq2000_function_arg_advance (cumulative_args_t, |
169 enum machine_mode, const_tree, bool); | 167 machine_mode, const_tree, bool); |
170 static unsigned int iq2000_function_arg_boundary (enum machine_mode, | 168 static pad_direction iq2000_function_arg_padding (machine_mode, const_tree); |
169 static unsigned int iq2000_function_arg_boundary (machine_mode, | |
171 const_tree); | 170 const_tree); |
172 static void iq2000_va_start (tree, rtx); | 171 static void iq2000_va_start (tree, rtx); |
173 static bool iq2000_legitimate_address_p (enum machine_mode, rtx, bool); | 172 static bool iq2000_legitimate_address_p (machine_mode, rtx, bool); |
174 static bool iq2000_can_eliminate (const int, const int); | 173 static bool iq2000_can_eliminate (const int, const int); |
175 static void iq2000_asm_trampoline_template (FILE *); | 174 static void iq2000_asm_trampoline_template (FILE *); |
176 static void iq2000_trampoline_init (rtx, tree, rtx); | 175 static void iq2000_trampoline_init (rtx, tree, rtx); |
177 static rtx iq2000_function_value (const_tree, const_tree, bool); | 176 static rtx iq2000_function_value (const_tree, const_tree, bool); |
178 static rtx iq2000_libcall_value (enum machine_mode, const_rtx); | 177 static rtx iq2000_libcall_value (machine_mode, const_rtx); |
179 static void iq2000_print_operand (FILE *, rtx, int); | 178 static void iq2000_print_operand (FILE *, rtx, int); |
180 static void iq2000_print_operand_address (FILE *, rtx); | 179 static void iq2000_print_operand_address (FILE *, machine_mode, rtx); |
181 static bool iq2000_print_operand_punct_valid_p (unsigned char code); | 180 static bool iq2000_print_operand_punct_valid_p (unsigned char code); |
182 | 181 static bool iq2000_hard_regno_mode_ok (unsigned int, machine_mode); |
183 /* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */ | 182 static bool iq2000_modes_tieable_p (machine_mode, machine_mode); |
184 static const struct default_options iq2000_option_optimization_table[] = | 183 static HOST_WIDE_INT iq2000_constant_alignment (const_tree, HOST_WIDE_INT); |
185 { | 184 static HOST_WIDE_INT iq2000_starting_frame_offset (void); |
186 { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 }, | |
187 { OPT_LEVELS_NONE, 0, NULL, 0 } | |
188 }; | |
189 | 185 |
190 #undef TARGET_INIT_BUILTINS | 186 #undef TARGET_INIT_BUILTINS |
191 #define TARGET_INIT_BUILTINS iq2000_init_builtins | 187 #define TARGET_INIT_BUILTINS iq2000_init_builtins |
192 #undef TARGET_EXPAND_BUILTIN | 188 #undef TARGET_EXPAND_BUILTIN |
193 #define TARGET_EXPAND_BUILTIN iq2000_expand_builtin | 189 #define TARGET_EXPAND_BUILTIN iq2000_expand_builtin |
194 #undef TARGET_ASM_SELECT_RTX_SECTION | 190 #undef TARGET_ASM_SELECT_RTX_SECTION |
195 #define TARGET_ASM_SELECT_RTX_SECTION iq2000_select_rtx_section | 191 #define TARGET_ASM_SELECT_RTX_SECTION iq2000_select_rtx_section |
196 #undef TARGET_HANDLE_OPTION | |
197 #define TARGET_HANDLE_OPTION iq2000_handle_option | |
198 #undef TARGET_OPTION_OVERRIDE | 192 #undef TARGET_OPTION_OVERRIDE |
199 #define TARGET_OPTION_OVERRIDE iq2000_option_override | 193 #define TARGET_OPTION_OVERRIDE iq2000_option_override |
200 #undef TARGET_OPTION_OPTIMIZATION_TABLE | |
201 #define TARGET_OPTION_OPTIMIZATION_TABLE iq2000_option_optimization_table | |
202 #undef TARGET_RTX_COSTS | 194 #undef TARGET_RTX_COSTS |
203 #define TARGET_RTX_COSTS iq2000_rtx_costs | 195 #define TARGET_RTX_COSTS iq2000_rtx_costs |
204 #undef TARGET_ADDRESS_COST | 196 #undef TARGET_ADDRESS_COST |
205 #define TARGET_ADDRESS_COST iq2000_address_cost | 197 #define TARGET_ADDRESS_COST iq2000_address_cost |
206 #undef TARGET_ASM_SELECT_SECTION | 198 #undef TARGET_ASM_SELECT_SECTION |
240 #define TARGET_ARG_PARTIAL_BYTES iq2000_arg_partial_bytes | 232 #define TARGET_ARG_PARTIAL_BYTES iq2000_arg_partial_bytes |
241 #undef TARGET_FUNCTION_ARG | 233 #undef TARGET_FUNCTION_ARG |
242 #define TARGET_FUNCTION_ARG iq2000_function_arg | 234 #define TARGET_FUNCTION_ARG iq2000_function_arg |
243 #undef TARGET_FUNCTION_ARG_ADVANCE | 235 #undef TARGET_FUNCTION_ARG_ADVANCE |
244 #define TARGET_FUNCTION_ARG_ADVANCE iq2000_function_arg_advance | 236 #define TARGET_FUNCTION_ARG_ADVANCE iq2000_function_arg_advance |
237 #undef TARGET_FUNCTION_ARG_PADDING | |
238 #define TARGET_FUNCTION_ARG_PADDING iq2000_function_arg_padding | |
245 #undef TARGET_FUNCTION_ARG_BOUNDARY | 239 #undef TARGET_FUNCTION_ARG_BOUNDARY |
246 #define TARGET_FUNCTION_ARG_BOUNDARY iq2000_function_arg_boundary | 240 #define TARGET_FUNCTION_ARG_BOUNDARY iq2000_function_arg_boundary |
247 | 241 |
248 #undef TARGET_SETUP_INCOMING_VARARGS | 242 #undef TARGET_SETUP_INCOMING_VARARGS |
249 #define TARGET_SETUP_INCOMING_VARARGS iq2000_setup_incoming_varargs | 243 #define TARGET_SETUP_INCOMING_VARARGS iq2000_setup_incoming_varargs |
251 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true | 245 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true |
252 | 246 |
253 #undef TARGET_EXPAND_BUILTIN_VA_START | 247 #undef TARGET_EXPAND_BUILTIN_VA_START |
254 #define TARGET_EXPAND_BUILTIN_VA_START iq2000_va_start | 248 #define TARGET_EXPAND_BUILTIN_VA_START iq2000_va_start |
255 | 249 |
250 #undef TARGET_LRA_P | |
251 #define TARGET_LRA_P hook_bool_void_false | |
252 | |
256 #undef TARGET_LEGITIMATE_ADDRESS_P | 253 #undef TARGET_LEGITIMATE_ADDRESS_P |
257 #define TARGET_LEGITIMATE_ADDRESS_P iq2000_legitimate_address_p | 254 #define TARGET_LEGITIMATE_ADDRESS_P iq2000_legitimate_address_p |
258 | 255 |
259 #undef TARGET_CAN_ELIMINATE | 256 #undef TARGET_CAN_ELIMINATE |
260 #define TARGET_CAN_ELIMINATE iq2000_can_eliminate | 257 #define TARGET_CAN_ELIMINATE iq2000_can_eliminate |
262 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE | 259 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE |
263 #define TARGET_ASM_TRAMPOLINE_TEMPLATE iq2000_asm_trampoline_template | 260 #define TARGET_ASM_TRAMPOLINE_TEMPLATE iq2000_asm_trampoline_template |
264 #undef TARGET_TRAMPOLINE_INIT | 261 #undef TARGET_TRAMPOLINE_INIT |
265 #define TARGET_TRAMPOLINE_INIT iq2000_trampoline_init | 262 #define TARGET_TRAMPOLINE_INIT iq2000_trampoline_init |
266 | 263 |
264 #undef TARGET_HARD_REGNO_MODE_OK | |
265 #define TARGET_HARD_REGNO_MODE_OK iq2000_hard_regno_mode_ok | |
266 #undef TARGET_MODES_TIEABLE_P | |
267 #define TARGET_MODES_TIEABLE_P iq2000_modes_tieable_p | |
268 | |
269 #undef TARGET_CONSTANT_ALIGNMENT | |
270 #define TARGET_CONSTANT_ALIGNMENT iq2000_constant_alignment | |
271 | |
272 #undef TARGET_STARTING_FRAME_OFFSET | |
273 #define TARGET_STARTING_FRAME_OFFSET iq2000_starting_frame_offset | |
274 | |
267 struct gcc_target targetm = TARGET_INITIALIZER; | 275 struct gcc_target targetm = TARGET_INITIALIZER; |
268 | 276 |
269 /* Return nonzero if we split the address into high and low parts. */ | 277 /* Return nonzero if we split the address into high and low parts. */ |
270 | 278 |
271 int | 279 int |
272 iq2000_check_split (rtx address, enum machine_mode mode) | 280 iq2000_check_split (rtx address, machine_mode mode) |
273 { | 281 { |
274 /* This is the same check used in simple_memory_operand. | 282 /* This is the same check used in simple_memory_operand. |
275 We use it here because LO_SUM is not offsettable. */ | 283 We use it here because LO_SUM is not offsettable. */ |
276 if (GET_MODE_SIZE (mode) > (unsigned) UNITS_PER_WORD) | 284 if (GET_MODE_SIZE (mode) > (unsigned) UNITS_PER_WORD) |
277 return 0; | 285 return 0; |
287 | 295 |
288 /* Return nonzero if REG is valid for MODE. */ | 296 /* Return nonzero if REG is valid for MODE. */ |
289 | 297 |
290 int | 298 int |
291 iq2000_reg_mode_ok_for_base_p (rtx reg, | 299 iq2000_reg_mode_ok_for_base_p (rtx reg, |
292 enum machine_mode mode ATTRIBUTE_UNUSED, | 300 machine_mode mode ATTRIBUTE_UNUSED, |
293 int strict) | 301 int strict) |
294 { | 302 { |
295 return (strict | 303 return (strict |
296 ? REGNO_MODE_OK_FOR_BASE_P (REGNO (reg), mode) | 304 ? REGNO_MODE_OK_FOR_BASE_P (REGNO (reg), mode) |
297 : GP_REG_OR_PSEUDO_NONSTRICT_P (REGNO (reg), mode)); | 305 : GP_REG_OR_PSEUDO_NONSTRICT_P (REGNO (reg), mode)); |
300 /* Return a nonzero value if XINSN is a legitimate address for a | 308 /* Return a nonzero value if XINSN is a legitimate address for a |
301 memory operand of the indicated MODE. STRICT is nonzero if this | 309 memory operand of the indicated MODE. STRICT is nonzero if this |
302 function is called during reload. */ | 310 function is called during reload. */ |
303 | 311 |
304 bool | 312 bool |
305 iq2000_legitimate_address_p (enum machine_mode mode, rtx xinsn, bool strict) | 313 iq2000_legitimate_address_p (machine_mode mode, rtx xinsn, bool strict) |
306 { | 314 { |
307 if (TARGET_DEBUG_A_MODE) | 315 if (TARGET_DEBUG_A_MODE) |
308 { | 316 { |
309 GO_PRINTF2 ("\n========== legitimate_address_p, %sstrict\n", | 317 GO_PRINTF2 ("\n========== legitimate_address_p, %sstrict\n", |
310 strict ? "" : "not "); | 318 strict ? "" : "not "); |
361 return 1; | 369 return 1; |
362 } | 370 } |
363 } | 371 } |
364 | 372 |
365 if (TARGET_DEBUG_A_MODE) | 373 if (TARGET_DEBUG_A_MODE) |
366 GO_PRINTF ("Not a enum machine_mode mode, legitimate address\n"); | 374 GO_PRINTF ("Not a machine_mode mode, legitimate address\n"); |
367 | 375 |
368 /* The address was not legitimate. */ | 376 /* The address was not legitimate. */ |
369 return 0; | 377 return 0; |
370 } | 378 } |
371 | 379 |
378 to FINAL_PRESCAN_INSN, and we just set the global variables that | 386 to FINAL_PRESCAN_INSN, and we just set the global variables that |
379 it needs. */ | 387 it needs. */ |
380 | 388 |
381 const char * | 389 const char * |
382 iq2000_fill_delay_slot (const char *ret, enum delay_type type, rtx operands[], | 390 iq2000_fill_delay_slot (const char *ret, enum delay_type type, rtx operands[], |
383 rtx cur_insn) | 391 rtx_insn *cur_insn) |
384 { | 392 { |
385 rtx set_reg; | 393 rtx set_reg; |
386 enum machine_mode mode; | 394 machine_mode mode; |
387 rtx next_insn = cur_insn ? NEXT_INSN (cur_insn) : NULL_RTX; | 395 rtx_insn *next_insn = cur_insn ? NEXT_INSN (cur_insn) : NULL; |
388 int num_nops; | 396 int num_nops; |
389 | 397 |
390 if (type == DELAY_LOAD || type == DELAY_FCMP) | 398 if (type == DELAY_LOAD || type == DELAY_FCMP) |
391 num_nops = 1; | 399 num_nops = 1; |
392 | 400 |
394 num_nops = 0; | 402 num_nops = 0; |
395 | 403 |
396 /* Make sure that we don't put nop's after labels. */ | 404 /* Make sure that we don't put nop's after labels. */ |
397 next_insn = NEXT_INSN (cur_insn); | 405 next_insn = NEXT_INSN (cur_insn); |
398 while (next_insn != 0 | 406 while (next_insn != 0 |
399 && (GET_CODE (next_insn) == NOTE | 407 && (NOTE_P (next_insn) || LABEL_P (next_insn))) |
400 || GET_CODE (next_insn) == CODE_LABEL)) | |
401 next_insn = NEXT_INSN (next_insn); | 408 next_insn = NEXT_INSN (next_insn); |
402 | 409 |
403 dslots_load_total += num_nops; | 410 dslots_load_total += num_nops; |
404 if (TARGET_DEBUG_C_MODE | 411 if (TARGET_DEBUG_C_MODE |
405 || type == DELAY_NONE | 412 || type == DELAY_NONE |
406 || operands == 0 | 413 || operands == 0 |
407 || cur_insn == 0 | 414 || cur_insn == 0 |
408 || next_insn == 0 | 415 || next_insn == 0 |
409 || GET_CODE (next_insn) == CODE_LABEL | 416 || LABEL_P (next_insn) |
410 || (set_reg = operands[0]) == 0) | 417 || (set_reg = operands[0]) == 0) |
411 { | 418 { |
412 dslots_number_nops = 0; | 419 dslots_number_nops = 0; |
413 iq2000_load_reg = 0; | 420 iq2000_load_reg = 0; |
414 iq2000_load_reg2 = 0; | 421 iq2000_load_reg2 = 0; |
562 } | 569 } |
563 | 570 |
564 /* Return the appropriate instructions to move one operand to another. */ | 571 /* Return the appropriate instructions to move one operand to another. */ |
565 | 572 |
566 const char * | 573 const char * |
567 iq2000_move_1word (rtx operands[], rtx insn, int unsignedp) | 574 iq2000_move_1word (rtx operands[], rtx_insn *insn, int unsignedp) |
568 { | 575 { |
569 const char *ret = 0; | 576 const char *ret = 0; |
570 rtx op0 = operands[0]; | 577 rtx op0 = operands[0]; |
571 rtx op1 = operands[1]; | 578 rtx op1 = operands[1]; |
572 enum rtx_code code0 = GET_CODE (op0); | 579 enum rtx_code code0 = GET_CODE (op0); |
573 enum rtx_code code1 = GET_CODE (op1); | 580 enum rtx_code code1 = GET_CODE (op1); |
574 enum machine_mode mode = GET_MODE (op0); | 581 machine_mode mode = GET_MODE (op0); |
575 int subreg_offset0 = 0; | 582 int subreg_offset0 = 0; |
576 int subreg_offset1 = 0; | 583 int subreg_offset1 = 0; |
577 enum delay_type delay = DELAY_NONE; | 584 enum delay_type delay = DELAY_NONE; |
578 | 585 |
579 while (code0 == SUBREG) | 586 while (code0 == SUBREG) |
633 target, so zero/sign extend can use this code as well. */ | 640 target, so zero/sign extend can use this code as well. */ |
634 switch (GET_MODE (op1)) | 641 switch (GET_MODE (op1)) |
635 { | 642 { |
636 default: | 643 default: |
637 break; | 644 break; |
638 case SFmode: | 645 case E_SFmode: |
639 ret = "lw\t%0,%1"; | 646 ret = "lw\t%0,%1"; |
640 break; | 647 break; |
641 case SImode: | 648 case E_SImode: |
642 case CCmode: | 649 case E_CCmode: |
643 ret = "lw\t%0,%1"; | 650 ret = "lw\t%0,%1"; |
644 break; | 651 break; |
645 case HImode: | 652 case E_HImode: |
646 ret = (unsignedp) ? "lhu\t%0,%1" : "lh\t%0,%1"; | 653 ret = (unsignedp) ? "lhu\t%0,%1" : "lh\t%0,%1"; |
647 break; | 654 break; |
648 case QImode: | 655 case E_QImode: |
649 ret = (unsignedp) ? "lbu\t%0,%1" : "lb\t%0,%1"; | 656 ret = (unsignedp) ? "lbu\t%0,%1" : "lb\t%0,%1"; |
650 break; | 657 break; |
651 } | 658 } |
652 } | 659 } |
653 } | 660 } |
743 | 750 |
744 if (GP_REG_P (regno1)) | 751 if (GP_REG_P (regno1)) |
745 { | 752 { |
746 switch (mode) | 753 switch (mode) |
747 { | 754 { |
748 case SFmode: ret = "sw\t%1,%0"; break; | 755 case E_SFmode: ret = "sw\t%1,%0"; break; |
749 case SImode: ret = "sw\t%1,%0"; break; | 756 case E_SImode: ret = "sw\t%1,%0"; break; |
750 case HImode: ret = "sh\t%1,%0"; break; | 757 case E_HImode: ret = "sh\t%1,%0"; break; |
751 case QImode: ret = "sb\t%1,%0"; break; | 758 case E_QImode: ret = "sb\t%1,%0"; break; |
752 default: break; | 759 default: break; |
753 } | 760 } |
754 } | 761 } |
755 } | 762 } |
756 | 763 |
757 else if (code1 == CONST_INT && INTVAL (op1) == 0) | 764 else if (code1 == CONST_INT && INTVAL (op1) == 0) |
758 { | 765 { |
759 switch (mode) | 766 switch (mode) |
760 { | 767 { |
761 case SFmode: ret = "sw\t%z1,%0"; break; | 768 case E_SFmode: ret = "sw\t%z1,%0"; break; |
762 case SImode: ret = "sw\t%z1,%0"; break; | 769 case E_SImode: ret = "sw\t%z1,%0"; break; |
763 case HImode: ret = "sh\t%z1,%0"; break; | 770 case E_HImode: ret = "sh\t%z1,%0"; break; |
764 case QImode: ret = "sb\t%z1,%0"; break; | 771 case E_QImode: ret = "sb\t%z1,%0"; break; |
765 default: break; | 772 default: break; |
766 } | 773 } |
767 } | 774 } |
768 | 775 |
769 else if (code1 == CONST_DOUBLE && op1 == CONST0_RTX (mode)) | 776 else if (code1 == CONST_DOUBLE && op1 == CONST0_RTX (mode)) |
770 { | 777 { |
771 switch (mode) | 778 switch (mode) |
772 { | 779 { |
773 case SFmode: ret = "sw\t%.,%0"; break; | 780 case E_SFmode: ret = "sw\t%.,%0"; break; |
774 case SImode: ret = "sw\t%.,%0"; break; | 781 case E_SImode: ret = "sw\t%.,%0"; break; |
775 case HImode: ret = "sh\t%.,%0"; break; | 782 case E_HImode: ret = "sh\t%.,%0"; break; |
776 case QImode: ret = "sb\t%.,%0"; break; | 783 case E_QImode: ret = "sb\t%.,%0"; break; |
777 default: break; | 784 default: break; |
778 } | 785 } |
779 } | 786 } |
780 } | 787 } |
781 | 788 |
792 } | 799 } |
793 | 800 |
794 /* Provide the costs of an addressing mode that contains ADDR. */ | 801 /* Provide the costs of an addressing mode that contains ADDR. */ |
795 | 802 |
796 static int | 803 static int |
797 iq2000_address_cost (rtx addr, bool speed) | 804 iq2000_address_cost (rtx addr, machine_mode mode, addr_space_t as, |
805 bool speed) | |
798 { | 806 { |
799 switch (GET_CODE (addr)) | 807 switch (GET_CODE (addr)) |
800 { | 808 { |
801 case LO_SUM: | 809 case LO_SUM: |
802 return 1; | 810 return 1; |
843 case CONST: | 851 case CONST: |
844 case SYMBOL_REF: | 852 case SYMBOL_REF: |
845 case LABEL_REF: | 853 case LABEL_REF: |
846 case HIGH: | 854 case HIGH: |
847 case LO_SUM: | 855 case LO_SUM: |
848 return iq2000_address_cost (plus1, speed) + 1; | 856 return iq2000_address_cost (plus1, mode, as, speed) + 1; |
849 | 857 |
850 default: | 858 default: |
851 break; | 859 break; |
852 } | 860 } |
853 } | 861 } |
919 { LTU, -32768, 32767, 0, 0, 0, 0, 1 }, /* LTU */ | 927 { LTU, -32768, 32767, 0, 0, 0, 0, 1 }, /* LTU */ |
920 { LTU, -32769, 32766, 1, 1, 0, 1, 1 }, /* LEU */ | 928 { LTU, -32769, 32766, 1, 1, 0, 1, 1 }, /* LEU */ |
921 }; | 929 }; |
922 | 930 |
923 enum internal_test test; | 931 enum internal_test test; |
924 enum machine_mode mode; | 932 machine_mode mode; |
925 struct cmp_info *p_info; | 933 struct cmp_info *p_info; |
926 int branch_p; | 934 int branch_p; |
927 int eqne_p; | 935 int eqne_p; |
928 int invert; | 936 int invert; |
929 rtx reg; | 937 rtx reg; |
1053 /* Emit the common code for doing conditional branches. | 1061 /* Emit the common code for doing conditional branches. |
1054 operand[0] is the label to jump to. | 1062 operand[0] is the label to jump to. |
1055 The comparison operands are saved away by cmp{si,di,sf,df}. */ | 1063 The comparison operands are saved away by cmp{si,di,sf,df}. */ |
1056 | 1064 |
1057 void | 1065 void |
1058 gen_conditional_branch (rtx operands[], enum machine_mode mode) | 1066 gen_conditional_branch (rtx operands[], machine_mode mode) |
1059 { | 1067 { |
1060 enum rtx_code test_code = GET_CODE (operands[0]); | 1068 enum rtx_code test_code = GET_CODE (operands[0]); |
1061 rtx cmp0 = operands[1]; | 1069 rtx cmp0 = operands[1]; |
1062 rtx cmp1 = operands[2]; | 1070 rtx cmp1 = operands[2]; |
1063 rtx reg; | 1071 rtx reg; |
1086 { | 1094 { |
1087 label2 = label1; | 1095 label2 = label1; |
1088 label1 = pc_rtx; | 1096 label1 = pc_rtx; |
1089 } | 1097 } |
1090 | 1098 |
1091 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, | 1099 emit_jump_insn (gen_rtx_SET (pc_rtx, |
1092 gen_rtx_IF_THEN_ELSE (VOIDmode, | 1100 gen_rtx_IF_THEN_ELSE (VOIDmode, |
1093 gen_rtx_fmt_ee (test_code, | 1101 gen_rtx_fmt_ee (test_code, |
1094 mode, | 1102 VOIDmode, |
1095 cmp0, cmp1), | 1103 cmp0, cmp1), |
1096 label1, label2))); | 1104 label1, label2))); |
1097 } | 1105 } |
1098 | 1106 |
1099 /* Initialize CUM for a function FNTYPE. */ | 1107 /* Initialize CUM for a function FNTYPE. */ |
1117 else | 1125 else |
1118 { | 1126 { |
1119 tree ret_type = TREE_TYPE (fntype); | 1127 tree ret_type = TREE_TYPE (fntype); |
1120 | 1128 |
1121 fprintf (stderr, ", fntype code = %s, ret code = %s\n", | 1129 fprintf (stderr, ", fntype code = %s, ret code = %s\n", |
1122 tree_code_name[(int)TREE_CODE (fntype)], | 1130 get_tree_code_name (TREE_CODE (fntype)), |
1123 tree_code_name[(int)TREE_CODE (ret_type)]); | 1131 get_tree_code_name (TREE_CODE (ret_type))); |
1124 } | 1132 } |
1125 } | 1133 } |
1126 | 1134 |
1127 *cum = zero_cum; | 1135 *cum = zero_cum; |
1128 | 1136 |
1142 | 1150 |
1143 /* Advance the argument of type TYPE and mode MODE to the next argument | 1151 /* Advance the argument of type TYPE and mode MODE to the next argument |
1144 position in CUM. */ | 1152 position in CUM. */ |
1145 | 1153 |
1146 static void | 1154 static void |
1147 iq2000_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, | 1155 iq2000_function_arg_advance (cumulative_args_t cum_v, machine_mode mode, |
1148 const_tree type, bool named) | 1156 const_tree type, bool named) |
1149 { | 1157 { |
1158 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); | |
1159 | |
1150 if (TARGET_DEBUG_D_MODE) | 1160 if (TARGET_DEBUG_D_MODE) |
1151 { | 1161 { |
1152 fprintf (stderr, | 1162 fprintf (stderr, |
1153 "function_adv({gp reg found = %d, arg # = %2d, words = %2d}, %4s, ", | 1163 "function_adv({gp reg found = %d, arg # = %2d, words = %2d}, %4s, ", |
1154 cum->gp_reg_found, cum->arg_number, cum->arg_words, | 1164 cum->gp_reg_found, cum->arg_number, cum->arg_words, |
1155 GET_MODE_NAME (mode)); | 1165 GET_MODE_NAME (mode)); |
1156 fprintf (stderr, "%p", CONST_CAST2 (void *, const_tree, type)); | 1166 fprintf (stderr, "%p", (const void *) type); |
1157 fprintf (stderr, ", %d )\n\n", named); | 1167 fprintf (stderr, ", %d )\n\n", named); |
1158 } | 1168 } |
1159 | 1169 |
1160 cum->arg_number++; | 1170 cum->arg_number++; |
1161 switch (mode) | 1171 switch (mode) |
1162 { | 1172 { |
1163 case VOIDmode: | 1173 case E_VOIDmode: |
1164 break; | 1174 break; |
1165 | 1175 |
1166 default: | 1176 default: |
1167 gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT | 1177 gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT |
1168 || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT); | 1178 || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT); |
1170 cum->gp_reg_found = 1; | 1180 cum->gp_reg_found = 1; |
1171 cum->arg_words += ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) | 1181 cum->arg_words += ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) |
1172 / UNITS_PER_WORD); | 1182 / UNITS_PER_WORD); |
1173 break; | 1183 break; |
1174 | 1184 |
1175 case BLKmode: | 1185 case E_BLKmode: |
1176 cum->gp_reg_found = 1; | 1186 cum->gp_reg_found = 1; |
1177 cum->arg_words += ((int_size_in_bytes (type) + UNITS_PER_WORD - 1) | 1187 cum->arg_words += ((int_size_in_bytes (type) + UNITS_PER_WORD - 1) |
1178 / UNITS_PER_WORD); | 1188 / UNITS_PER_WORD); |
1179 break; | 1189 break; |
1180 | 1190 |
1181 case SFmode: | 1191 case E_SFmode: |
1182 cum->arg_words ++; | 1192 cum->arg_words ++; |
1183 if (! cum->gp_reg_found && cum->arg_number <= 2) | 1193 if (! cum->gp_reg_found && cum->arg_number <= 2) |
1184 cum->fp_code += 1 << ((cum->arg_number - 1) * 2); | 1194 cum->fp_code += 1 << ((cum->arg_number - 1) * 2); |
1185 break; | 1195 break; |
1186 | 1196 |
1187 case DFmode: | 1197 case E_DFmode: |
1188 cum->arg_words += 2; | 1198 cum->arg_words += 2; |
1189 if (! cum->gp_reg_found && cum->arg_number <= 2) | 1199 if (! cum->gp_reg_found && cum->arg_number <= 2) |
1190 cum->fp_code += 2 << ((cum->arg_number - 1) * 2); | 1200 cum->fp_code += 2 << ((cum->arg_number - 1) * 2); |
1191 break; | 1201 break; |
1192 | 1202 |
1193 case DImode: | 1203 case E_DImode: |
1194 cum->gp_reg_found = 1; | 1204 cum->gp_reg_found = 1; |
1195 cum->arg_words += 2; | 1205 cum->arg_words += 2; |
1196 break; | 1206 break; |
1197 | 1207 |
1198 case TImode: | 1208 case E_TImode: |
1199 cum->gp_reg_found = 1; | 1209 cum->gp_reg_found = 1; |
1200 cum->arg_words += 4; | 1210 cum->arg_words += 4; |
1201 break; | 1211 break; |
1202 | 1212 |
1203 case QImode: | 1213 case E_QImode: |
1204 case HImode: | 1214 case E_HImode: |
1205 case SImode: | 1215 case E_SImode: |
1206 cum->gp_reg_found = 1; | 1216 cum->gp_reg_found = 1; |
1207 cum->arg_words ++; | 1217 cum->arg_words ++; |
1208 break; | 1218 break; |
1209 } | 1219 } |
1210 } | 1220 } |
1211 | 1221 |
1212 /* Return an RTL expression containing the register for the given mode MODE | 1222 /* Return an RTL expression containing the register for the given mode MODE |
1213 and type TYPE in CUM, or 0 if the argument is to be passed on the stack. */ | 1223 and type TYPE in CUM, or 0 if the argument is to be passed on the stack. */ |
1214 | 1224 |
1215 static rtx | 1225 static rtx |
1216 iq2000_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, | 1226 iq2000_function_arg (cumulative_args_t cum_v, machine_mode mode, |
1217 const_tree type, bool named) | 1227 const_tree type, bool named) |
1218 { | 1228 { |
1229 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); | |
1219 rtx ret; | 1230 rtx ret; |
1220 int regbase = -1; | 1231 int regbase = -1; |
1221 int bias = 0; | 1232 int bias = 0; |
1222 unsigned int *arg_words = &cum->arg_words; | 1233 unsigned int *arg_words = &cum->arg_words; |
1223 int struct_p = (type != 0 | 1234 int struct_p = (type != 0 |
1237 | 1248 |
1238 | 1249 |
1239 cum->last_arg_fp = 0; | 1250 cum->last_arg_fp = 0; |
1240 switch (mode) | 1251 switch (mode) |
1241 { | 1252 { |
1242 case SFmode: | 1253 case E_SFmode: |
1243 regbase = GP_ARG_FIRST; | 1254 regbase = GP_ARG_FIRST; |
1244 break; | 1255 break; |
1245 | 1256 |
1246 case DFmode: | 1257 case E_DFmode: |
1247 cum->arg_words += cum->arg_words & 1; | 1258 cum->arg_words += cum->arg_words & 1; |
1248 | 1259 |
1249 regbase = GP_ARG_FIRST; | 1260 regbase = GP_ARG_FIRST; |
1250 break; | 1261 break; |
1251 | 1262 |
1252 default: | 1263 default: |
1253 gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT | 1264 gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT |
1254 || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT); | 1265 || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT); |
1255 | 1266 |
1256 /* Drops through. */ | 1267 /* FALLTHRU */ |
1257 case BLKmode: | 1268 case E_BLKmode: |
1258 if (type != NULL_TREE && TYPE_ALIGN (type) > (unsigned) BITS_PER_WORD) | 1269 if (type != NULL_TREE && TYPE_ALIGN (type) > (unsigned) BITS_PER_WORD) |
1259 cum->arg_words += (cum->arg_words & 1); | 1270 cum->arg_words += (cum->arg_words & 1); |
1260 regbase = GP_ARG_FIRST; | 1271 regbase = GP_ARG_FIRST; |
1261 break; | 1272 break; |
1262 | 1273 |
1263 case VOIDmode: | 1274 case E_VOIDmode: |
1264 case QImode: | 1275 case E_QImode: |
1265 case HImode: | 1276 case E_HImode: |
1266 case SImode: | 1277 case E_SImode: |
1267 regbase = GP_ARG_FIRST; | 1278 regbase = GP_ARG_FIRST; |
1268 break; | 1279 break; |
1269 | 1280 |
1270 case DImode: | 1281 case E_DImode: |
1271 cum->arg_words += (cum->arg_words & 1); | 1282 cum->arg_words += (cum->arg_words & 1); |
1272 regbase = GP_ARG_FIRST; | 1283 regbase = GP_ARG_FIRST; |
1273 break; | 1284 break; |
1274 | 1285 |
1275 case TImode: | 1286 case E_TImode: |
1276 cum->arg_words += (cum->arg_words & 3); | 1287 cum->arg_words += (cum->arg_words & 3); |
1277 regbase = GP_ARG_FIRST; | 1288 regbase = GP_ARG_FIRST; |
1278 break; | 1289 break; |
1279 } | 1290 } |
1280 | 1291 |
1289 { | 1300 { |
1290 gcc_assert (regbase != -1); | 1301 gcc_assert (regbase != -1); |
1291 | 1302 |
1292 if (! type || TREE_CODE (type) != RECORD_TYPE | 1303 if (! type || TREE_CODE (type) != RECORD_TYPE |
1293 || ! named || ! TYPE_SIZE_UNIT (type) | 1304 || ! named || ! TYPE_SIZE_UNIT (type) |
1294 || ! host_integerp (TYPE_SIZE_UNIT (type), 1)) | 1305 || ! tree_fits_uhwi_p (TYPE_SIZE_UNIT (type))) |
1295 ret = gen_rtx_REG (mode, regbase + *arg_words + bias); | 1306 ret = gen_rtx_REG (mode, regbase + *arg_words + bias); |
1296 else | 1307 else |
1297 { | 1308 { |
1298 tree field; | 1309 tree field; |
1299 | 1310 |
1300 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) | 1311 for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) |
1301 if (TREE_CODE (field) == FIELD_DECL | 1312 if (TREE_CODE (field) == FIELD_DECL |
1302 && TREE_CODE (TREE_TYPE (field)) == REAL_TYPE | 1313 && TREE_CODE (TREE_TYPE (field)) == REAL_TYPE |
1303 && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD | 1314 && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD |
1304 && host_integerp (bit_position (field), 0) | 1315 && tree_fits_shwi_p (bit_position (field)) |
1305 && int_bit_position (field) % BITS_PER_WORD == 0) | 1316 && int_bit_position (field) % BITS_PER_WORD == 0) |
1306 break; | 1317 break; |
1307 | 1318 |
1308 /* If the whole struct fits a DFmode register, | 1319 /* If the whole struct fits a DFmode register, |
1309 we don't need the PARALLEL. */ | 1320 we don't need the PARALLEL. */ |
1317 unsigned int i; | 1328 unsigned int i; |
1318 | 1329 |
1319 /* ??? If this is a packed structure, then the last hunk won't | 1330 /* ??? If this is a packed structure, then the last hunk won't |
1320 be 64 bits. */ | 1331 be 64 bits. */ |
1321 chunks | 1332 chunks |
1322 = tree_low_cst (TYPE_SIZE_UNIT (type), 1) / UNITS_PER_WORD; | 1333 = tree_to_uhwi (TYPE_SIZE_UNIT (type)) / UNITS_PER_WORD; |
1323 if (chunks + *arg_words + bias > (unsigned) MAX_ARGS_IN_REGISTERS) | 1334 if (chunks + *arg_words + bias > (unsigned) MAX_ARGS_IN_REGISTERS) |
1324 chunks = MAX_ARGS_IN_REGISTERS - *arg_words - bias; | 1335 chunks = MAX_ARGS_IN_REGISTERS - *arg_words - bias; |
1325 | 1336 |
1326 /* Assign_parms checks the mode of ENTRY_PARM, so we must | 1337 /* Assign_parms checks the mode of ENTRY_PARM, so we must |
1327 use the actual mode here. */ | 1338 use the actual mode here. */ |
1367 insn. If we need any shifts for small structures, return them in | 1378 insn. If we need any shifts for small structures, return them in |
1368 a PARALLEL. */ | 1379 a PARALLEL. */ |
1369 if (mode == VOIDmode) | 1380 if (mode == VOIDmode) |
1370 { | 1381 { |
1371 if (cum->num_adjusts > 0) | 1382 if (cum->num_adjusts > 0) |
1372 ret = gen_rtx_PARALLEL ((enum machine_mode) cum->fp_code, | 1383 ret = gen_rtx_PARALLEL ((machine_mode) cum->fp_code, |
1373 gen_rtvec_v (cum->num_adjusts, cum->adjust)); | 1384 gen_rtvec_v (cum->num_adjusts, cum->adjust)); |
1374 } | 1385 } |
1375 | 1386 |
1376 return ret; | 1387 return ret; |
1377 } | 1388 } |
1378 | 1389 |
1390 /* Implement TARGET_FUNCTION_ARG_PADDING. */ | |
1391 | |
1392 static pad_direction | |
1393 iq2000_function_arg_padding (machine_mode mode, const_tree type) | |
1394 { | |
1395 return (! BYTES_BIG_ENDIAN | |
1396 ? PAD_UPWARD | |
1397 : ((mode == BLKmode | |
1398 ? (type | |
1399 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST | |
1400 && int_size_in_bytes (type) < (PARM_BOUNDARY / BITS_PER_UNIT)) | |
1401 : (GET_MODE_BITSIZE (mode) < PARM_BOUNDARY | |
1402 && GET_MODE_CLASS (mode) == MODE_INT)) | |
1403 ? PAD_DOWNWARD : PAD_UPWARD)); | |
1404 } | |
1405 | |
1379 static unsigned int | 1406 static unsigned int |
1380 iq2000_function_arg_boundary (enum machine_mode mode, const_tree type) | 1407 iq2000_function_arg_boundary (machine_mode mode, const_tree type) |
1381 { | 1408 { |
1382 return (type != NULL_TREE | 1409 return (type != NULL_TREE |
1383 ? (TYPE_ALIGN (type) <= PARM_BOUNDARY | 1410 ? (TYPE_ALIGN (type) <= PARM_BOUNDARY |
1384 ? PARM_BOUNDARY | 1411 ? PARM_BOUNDARY |
1385 : TYPE_ALIGN (type)) | 1412 : TYPE_ALIGN (type)) |
1387 ? PARM_BOUNDARY | 1414 ? PARM_BOUNDARY |
1388 : GET_MODE_ALIGNMENT (mode))); | 1415 : GET_MODE_ALIGNMENT (mode))); |
1389 } | 1416 } |
1390 | 1417 |
1391 static int | 1418 static int |
1392 iq2000_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode, | 1419 iq2000_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode, |
1393 tree type ATTRIBUTE_UNUSED, | 1420 tree type ATTRIBUTE_UNUSED, |
1394 bool named ATTRIBUTE_UNUSED) | 1421 bool named ATTRIBUTE_UNUSED) |
1395 { | 1422 { |
1423 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); | |
1424 | |
1396 if (mode == DImode && cum->arg_words == MAX_ARGS_IN_REGISTERS - 1) | 1425 if (mode == DImode && cum->arg_words == MAX_ARGS_IN_REGISTERS - 1) |
1397 { | 1426 { |
1398 if (TARGET_DEBUG_D_MODE) | 1427 if (TARGET_DEBUG_D_MODE) |
1399 fprintf (stderr, "iq2000_arg_partial_bytes=%d\n", UNITS_PER_WORD); | 1428 fprintf (stderr, "iq2000_arg_partial_bytes=%d\n", UNITS_PER_WORD); |
1400 return UNITS_PER_WORD; | 1429 return UNITS_PER_WORD; |
1420 else | 1449 else |
1421 gpr_save_area_size = 0; | 1450 gpr_save_area_size = 0; |
1422 | 1451 |
1423 /* Everything is in the GPR save area, or in the overflow | 1452 /* Everything is in the GPR save area, or in the overflow |
1424 area which is contiguous with it. */ | 1453 area which is contiguous with it. */ |
1425 nextarg = plus_constant (nextarg, - gpr_save_area_size); | 1454 nextarg = plus_constant (Pmode, nextarg, - gpr_save_area_size); |
1426 std_expand_builtin_va_start (valist, nextarg); | 1455 std_expand_builtin_va_start (valist, nextarg); |
1427 } | 1456 } |
1428 | 1457 |
1429 /* Allocate a chunk of memory for per-function machine-dependent data. */ | 1458 /* Allocate a chunk of memory for per-function machine-dependent data. */ |
1430 | 1459 |
1431 static struct machine_function * | 1460 static struct machine_function * |
1432 iq2000_init_machine_status (void) | 1461 iq2000_init_machine_status (void) |
1433 { | 1462 { |
1434 return ggc_alloc_cleared_machine_function (); | 1463 return ggc_cleared_alloc<machine_function> (); |
1435 } | |
1436 | |
1437 /* Implement TARGET_HANDLE_OPTION. */ | |
1438 | |
1439 static bool | |
1440 iq2000_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED) | |
1441 { | |
1442 switch (code) | |
1443 { | |
1444 case OPT_mcpu_: | |
1445 if (strcmp (arg, "iq10") == 0) | |
1446 iq2000_tune = PROCESSOR_IQ10; | |
1447 else if (strcmp (arg, "iq2000") == 0) | |
1448 iq2000_tune = PROCESSOR_IQ2000; | |
1449 else | |
1450 return false; | |
1451 return true; | |
1452 | |
1453 case OPT_march_: | |
1454 /* This option has no effect at the moment. */ | |
1455 return (strcmp (arg, "default") == 0 | |
1456 || strcmp (arg, "DEFAULT") == 0 | |
1457 || strcmp (arg, "iq2000") == 0); | |
1458 | |
1459 default: | |
1460 return true; | |
1461 } | |
1462 } | 1464 } |
1463 | 1465 |
1464 /* Detect any conflicts in the switches. */ | 1466 /* Detect any conflicts in the switches. */ |
1465 | 1467 |
1466 static void | 1468 static void |
1538 | 1540 |
1539 We use it to check if the current insn needs a nop in front of it because | 1541 We use it to check if the current insn needs a nop in front of it because |
1540 of load delays, and also to update the delay slot statistics. */ | 1542 of load delays, and also to update the delay slot statistics. */ |
1541 | 1543 |
1542 void | 1544 void |
1543 final_prescan_insn (rtx insn, rtx opvec[] ATTRIBUTE_UNUSED, | 1545 final_prescan_insn (rtx_insn *insn, rtx opvec[] ATTRIBUTE_UNUSED, |
1544 int noperands ATTRIBUTE_UNUSED) | 1546 int noperands ATTRIBUTE_UNUSED) |
1545 { | 1547 { |
1546 if (dslots_number_nops > 0) | 1548 if (dslots_number_nops > 0) |
1547 { | 1549 { |
1548 rtx pattern = PATTERN (insn); | 1550 rtx pattern = PATTERN (insn); |
1567 iq2000_load_reg2 = 0; | 1569 iq2000_load_reg2 = 0; |
1568 iq2000_load_reg3 = 0; | 1570 iq2000_load_reg3 = 0; |
1569 iq2000_load_reg4 = 0; | 1571 iq2000_load_reg4 = 0; |
1570 } | 1572 } |
1571 | 1573 |
1572 if ( (GET_CODE (insn) == JUMP_INSN | 1574 if ( (JUMP_P (insn) |
1573 || GET_CODE (insn) == CALL_INSN | 1575 || CALL_P (insn) |
1574 || (GET_CODE (PATTERN (insn)) == RETURN)) | 1576 || (GET_CODE (PATTERN (insn)) == RETURN)) |
1575 && NEXT_INSN (PREV_INSN (insn)) == insn) | 1577 && NEXT_INSN (PREV_INSN (insn)) == insn) |
1576 { | 1578 { |
1577 rtx nop_insn = emit_insn_after (gen_nop (), insn); | 1579 rtx_insn *tmp = insn; |
1578 | 1580 while (NEXT_INSN (tmp) |
1581 && NOTE_P (NEXT_INSN (tmp)) | |
1582 && NOTE_KIND (NEXT_INSN (tmp)) == NOTE_INSN_CALL_ARG_LOCATION) | |
1583 tmp = NEXT_INSN (tmp); | |
1584 | |
1585 rtx_insn *nop_insn = emit_insn_after (gen_nop (), tmp); | |
1579 INSN_ADDRESSES_NEW (nop_insn, -1); | 1586 INSN_ADDRESSES_NEW (nop_insn, -1); |
1580 } | 1587 } |
1581 | 1588 |
1582 if (TARGET_STATS | 1589 if (TARGET_STATS |
1583 && (GET_CODE (insn) == JUMP_INSN || GET_CODE (insn) == CALL_INSN)) | 1590 && (JUMP_P (insn) || CALL_P (insn))) |
1584 dslots_jump_total ++; | 1591 dslots_jump_total ++; |
1585 } | 1592 } |
1586 | 1593 |
1587 /* Return the bytes needed to compute the frame pointer from the current | 1594 /* Return the bytes needed to compute the frame pointer from the current |
1588 stack pointer where SIZE is the # of var. bytes allocated. | 1595 stack pointer where SIZE is the # of var. bytes allocated. |
1804 | 1811 |
1805 /* Make INSN frame related and note that it performs the frame-related | 1812 /* Make INSN frame related and note that it performs the frame-related |
1806 operation DWARF_PATTERN. */ | 1813 operation DWARF_PATTERN. */ |
1807 | 1814 |
1808 static void | 1815 static void |
1809 iq2000_annotate_frame_insn (rtx insn, rtx dwarf_pattern) | 1816 iq2000_annotate_frame_insn (rtx_insn *insn, rtx dwarf_pattern) |
1810 { | 1817 { |
1811 RTX_FRAME_RELATED_P (insn) = 1; | 1818 RTX_FRAME_RELATED_P (insn) = 1; |
1812 REG_NOTES (insn) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR, | 1819 REG_NOTES (insn) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR, |
1813 dwarf_pattern, | 1820 dwarf_pattern, |
1814 REG_NOTES (insn)); | 1821 REG_NOTES (insn)); |
1818 frame related and note that it stores REG at (SP + OFFSET). */ | 1825 frame related and note that it stores REG at (SP + OFFSET). */ |
1819 | 1826 |
1820 static void | 1827 static void |
1821 iq2000_emit_frame_related_store (rtx mem, rtx reg, HOST_WIDE_INT offset) | 1828 iq2000_emit_frame_related_store (rtx mem, rtx reg, HOST_WIDE_INT offset) |
1822 { | 1829 { |
1823 rtx dwarf_address = plus_constant (stack_pointer_rtx, offset); | 1830 rtx dwarf_address = plus_constant (Pmode, stack_pointer_rtx, offset); |
1824 rtx dwarf_mem = gen_rtx_MEM (GET_MODE (reg), dwarf_address); | 1831 rtx dwarf_mem = gen_rtx_MEM (GET_MODE (reg), dwarf_address); |
1825 | 1832 |
1826 iq2000_annotate_frame_insn (emit_move_insn (mem, reg), | 1833 iq2000_annotate_frame_insn (emit_move_insn (mem, reg), |
1827 gen_rtx_SET (GET_MODE (reg), dwarf_mem, reg)); | 1834 gen_rtx_SET (dwarf_mem, reg)); |
1828 } | 1835 } |
1829 | 1836 |
1830 /* Emit instructions to save/restore registers, as determined by STORE_P. */ | 1837 /* Emit instructions to save/restore registers, as determined by STORE_P. */ |
1831 | 1838 |
1832 static void | 1839 static void |
1919 tree fnargs = DECL_ARGUMENTS (fndecl); | 1926 tree fnargs = DECL_ARGUMENTS (fndecl); |
1920 rtx next_arg_reg; | 1927 rtx next_arg_reg; |
1921 int i; | 1928 int i; |
1922 tree next_arg; | 1929 tree next_arg; |
1923 tree cur_arg; | 1930 tree cur_arg; |
1924 CUMULATIVE_ARGS args_so_far; | 1931 CUMULATIVE_ARGS args_so_far_v; |
1932 cumulative_args_t args_so_far; | |
1925 int store_args_on_stack = (iq2000_can_use_return_insn ()); | 1933 int store_args_on_stack = (iq2000_can_use_return_insn ()); |
1926 | 1934 |
1927 /* If struct value address is treated as the first argument. */ | 1935 /* If struct value address is treated as the first argument. */ |
1928 if (aggregate_value_p (DECL_RESULT (fndecl), fndecl) | 1936 if (aggregate_value_p (DECL_RESULT (fndecl), fndecl) |
1929 && !cfun->returns_pcc_struct | 1937 && !cfun->returns_pcc_struct |
1943 otherwise GP_ARG_LAST+1. Note also if the last argument is | 1951 otherwise GP_ARG_LAST+1. Note also if the last argument is |
1944 the varargs special argument, and treat it as part of the | 1952 the varargs special argument, and treat it as part of the |
1945 variable arguments. | 1953 variable arguments. |
1946 | 1954 |
1947 This is only needed if store_args_on_stack is true. */ | 1955 This is only needed if store_args_on_stack is true. */ |
1948 INIT_CUMULATIVE_ARGS (args_so_far, fntype, NULL_RTX, 0, 0); | 1956 INIT_CUMULATIVE_ARGS (args_so_far_v, fntype, NULL_RTX, 0, 0); |
1957 args_so_far = pack_cumulative_args (&args_so_far_v); | |
1949 regno = GP_ARG_FIRST; | 1958 regno = GP_ARG_FIRST; |
1950 | 1959 |
1951 for (cur_arg = fnargs; cur_arg != 0; cur_arg = next_arg) | 1960 for (cur_arg = fnargs; cur_arg != 0; cur_arg = next_arg) |
1952 { | 1961 { |
1953 tree passed_type = DECL_ARG_TYPE (cur_arg); | 1962 tree passed_type = DECL_ARG_TYPE (cur_arg); |
1954 enum machine_mode passed_mode = TYPE_MODE (passed_type); | 1963 machine_mode passed_mode = TYPE_MODE (passed_type); |
1955 rtx entry_parm; | 1964 rtx entry_parm; |
1956 | 1965 |
1957 if (TREE_ADDRESSABLE (passed_type)) | 1966 if (TREE_ADDRESSABLE (passed_type)) |
1958 { | 1967 { |
1959 passed_type = build_pointer_type (passed_type); | 1968 passed_type = build_pointer_type (passed_type); |
1960 passed_mode = Pmode; | 1969 passed_mode = Pmode; |
1961 } | 1970 } |
1962 | 1971 |
1963 entry_parm = iq2000_function_arg (&args_so_far, passed_mode, | 1972 entry_parm = iq2000_function_arg (args_so_far, passed_mode, |
1964 passed_type, true); | 1973 passed_type, true); |
1965 | 1974 |
1966 iq2000_function_arg_advance (&args_so_far, passed_mode, | 1975 iq2000_function_arg_advance (args_so_far, passed_mode, |
1967 passed_type, true); | 1976 passed_type, true); |
1968 next_arg = DECL_CHAIN (cur_arg); | 1977 next_arg = DECL_CHAIN (cur_arg); |
1969 | 1978 |
1970 if (entry_parm && store_args_on_stack) | 1979 if (entry_parm && store_args_on_stack) |
1971 { | 1980 { |
2004 /* In order to pass small structures by value in registers we need to | 2013 /* In order to pass small structures by value in registers we need to |
2005 shift the value into the high part of the register. | 2014 shift the value into the high part of the register. |
2006 iq2000_unction_arg has encoded a PARALLEL rtx, holding a vector of | 2015 iq2000_unction_arg has encoded a PARALLEL rtx, holding a vector of |
2007 adjustments to be made as the next_arg_reg variable, so we split up | 2016 adjustments to be made as the next_arg_reg variable, so we split up |
2008 the insns, and emit them separately. */ | 2017 the insns, and emit them separately. */ |
2009 next_arg_reg = iq2000_function_arg (&args_so_far, VOIDmode, | 2018 next_arg_reg = iq2000_function_arg (args_so_far, VOIDmode, |
2010 void_type_node, true); | 2019 void_type_node, true); |
2011 if (next_arg_reg != 0 && GET_CODE (next_arg_reg) == PARALLEL) | 2020 if (next_arg_reg != 0 && GET_CODE (next_arg_reg) == PARALLEL) |
2012 { | 2021 { |
2013 rtvec adjust = XVEC (next_arg_reg, 0); | 2022 rtvec adjust = XVEC (next_arg_reg, 0); |
2014 int num = GET_NUM_ELEM (adjust); | 2023 int num = GET_NUM_ELEM (adjust); |
2050 } | 2059 } |
2051 | 2060 |
2052 if (tsize > 0) | 2061 if (tsize > 0) |
2053 { | 2062 { |
2054 rtx tsize_rtx = GEN_INT (tsize); | 2063 rtx tsize_rtx = GEN_INT (tsize); |
2055 rtx adjustment_rtx, insn, dwarf_pattern; | 2064 rtx adjustment_rtx, dwarf_pattern; |
2065 rtx_insn *insn; | |
2056 | 2066 |
2057 if (tsize > 32767) | 2067 if (tsize > 32767) |
2058 { | 2068 { |
2059 adjustment_rtx = gen_rtx_REG (Pmode, IQ2000_TEMP1_REGNUM); | 2069 adjustment_rtx = gen_rtx_REG (Pmode, IQ2000_TEMP1_REGNUM); |
2060 emit_move_insn (adjustment_rtx, tsize_rtx); | 2070 emit_move_insn (adjustment_rtx, tsize_rtx); |
2063 adjustment_rtx = tsize_rtx; | 2073 adjustment_rtx = tsize_rtx; |
2064 | 2074 |
2065 insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, | 2075 insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, |
2066 adjustment_rtx)); | 2076 adjustment_rtx)); |
2067 | 2077 |
2068 dwarf_pattern = gen_rtx_SET (Pmode, stack_pointer_rtx, | 2078 dwarf_pattern = gen_rtx_SET (stack_pointer_rtx, |
2069 plus_constant (stack_pointer_rtx, -tsize)); | 2079 plus_constant (Pmode, stack_pointer_rtx, |
2080 -tsize)); | |
2070 | 2081 |
2071 iq2000_annotate_frame_insn (insn, dwarf_pattern); | 2082 iq2000_annotate_frame_insn (insn, dwarf_pattern); |
2072 | 2083 |
2073 save_restore_insns (1); | 2084 save_restore_insns (1); |
2074 | 2085 |
2075 if (frame_pointer_needed) | 2086 if (frame_pointer_needed) |
2076 { | 2087 { |
2077 rtx insn = 0; | 2088 rtx_insn *insn = 0; |
2078 | 2089 |
2079 insn = emit_insn (gen_movsi (hard_frame_pointer_rtx, | 2090 insn = emit_insn (gen_movsi (hard_frame_pointer_rtx, |
2080 stack_pointer_rtx)); | 2091 stack_pointer_rtx)); |
2081 | 2092 |
2082 if (insn) | 2093 if (insn) |
2083 RTX_FRAME_RELATED_P (insn) = 1; | 2094 RTX_FRAME_RELATED_P (insn) = 1; |
2084 } | 2095 } |
2085 } | 2096 } |
2097 | |
2098 if (flag_stack_usage_info) | |
2099 current_function_static_stack_size = cfun->machine->total_size; | |
2086 | 2100 |
2087 emit_insn (gen_blockage ()); | 2101 emit_insn (gen_blockage ()); |
2088 } | 2102 } |
2089 | 2103 |
2090 /* Expand the epilogue into a bunch of separate insns. */ | 2104 /* Expand the epilogue into a bunch of separate insns. */ |
2153 iq2000_expand_eh_return (rtx address) | 2167 iq2000_expand_eh_return (rtx address) |
2154 { | 2168 { |
2155 HOST_WIDE_INT gp_offset = cfun->machine->gp_sp_offset; | 2169 HOST_WIDE_INT gp_offset = cfun->machine->gp_sp_offset; |
2156 rtx scratch; | 2170 rtx scratch; |
2157 | 2171 |
2158 scratch = plus_constant (stack_pointer_rtx, gp_offset); | 2172 scratch = plus_constant (Pmode, stack_pointer_rtx, gp_offset); |
2159 emit_move_insn (gen_rtx_MEM (GET_MODE (address), scratch), address); | 2173 emit_move_insn (gen_rtx_MEM (GET_MODE (address), scratch), address); |
2160 } | 2174 } |
2161 | 2175 |
2162 /* Return nonzero if this function is known to have a null epilogue. | 2176 /* Return nonzero if this function is known to have a null epilogue. |
2163 This allows the optimizer to omit jumps to jumps if no stack | 2177 This allows the optimizer to omit jumps to jumps if no stack |
2180 | 2194 |
2181 /* Choose the section to use for the constant rtx expression X that has | 2195 /* Choose the section to use for the constant rtx expression X that has |
2182 mode MODE. */ | 2196 mode MODE. */ |
2183 | 2197 |
2184 static section * | 2198 static section * |
2185 iq2000_select_rtx_section (enum machine_mode mode, rtx x ATTRIBUTE_UNUSED, | 2199 iq2000_select_rtx_section (machine_mode mode, rtx x ATTRIBUTE_UNUSED, |
2186 unsigned HOST_WIDE_INT align) | 2200 unsigned HOST_WIDE_INT align) |
2187 { | 2201 { |
2188 /* For embedded applications, always put constants in read-only data, | 2202 /* For embedded applications, always put constants in read-only data, |
2189 in order to reduce RAM usage. */ | 2203 in order to reduce RAM usage. */ |
2190 return mergeable_constant_section (mode, align, 0); | 2204 return mergeable_constant_section (mode, align, 0); |
2239 iq2000_function_value (const_tree valtype, | 2253 iq2000_function_value (const_tree valtype, |
2240 const_tree fn_decl_or_type, | 2254 const_tree fn_decl_or_type, |
2241 bool outgoing ATTRIBUTE_UNUSED) | 2255 bool outgoing ATTRIBUTE_UNUSED) |
2242 { | 2256 { |
2243 int reg = GP_RETURN; | 2257 int reg = GP_RETURN; |
2244 enum machine_mode mode = TYPE_MODE (valtype); | 2258 machine_mode mode = TYPE_MODE (valtype); |
2245 int unsignedp = TYPE_UNSIGNED (valtype); | 2259 int unsignedp = TYPE_UNSIGNED (valtype); |
2246 const_tree func = fn_decl_or_type; | 2260 const_tree func = fn_decl_or_type; |
2247 | 2261 |
2248 if (fn_decl_or_type | 2262 if (fn_decl_or_type |
2249 && !DECL_P (fn_decl_or_type)) | 2263 && !DECL_P (fn_decl_or_type)) |
2256 } | 2270 } |
2257 | 2271 |
2258 /* Worker function for TARGET_LIBCALL_VALUE. */ | 2272 /* Worker function for TARGET_LIBCALL_VALUE. */ |
2259 | 2273 |
2260 static rtx | 2274 static rtx |
2261 iq2000_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED) | 2275 iq2000_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED) |
2262 { | 2276 { |
2263 return gen_rtx_REG (((GET_MODE_CLASS (mode) != MODE_INT | 2277 return gen_rtx_REG (((GET_MODE_CLASS (mode) != MODE_INT |
2264 || GET_MODE_SIZE (mode) >= 4) | 2278 || GET_MODE_SIZE (mode) >= 4) |
2265 ? mode : SImode), | 2279 ? mode : SImode), |
2266 GP_RETURN); | 2280 GP_RETURN); |
2278 | 2292 |
2279 | 2293 |
2280 /* Return true when an argument must be passed by reference. */ | 2294 /* Return true when an argument must be passed by reference. */ |
2281 | 2295 |
2282 static bool | 2296 static bool |
2283 iq2000_pass_by_reference (CUMULATIVE_ARGS *cum, enum machine_mode mode, | 2297 iq2000_pass_by_reference (cumulative_args_t cum_v, machine_mode mode, |
2284 const_tree type, bool named ATTRIBUTE_UNUSED) | 2298 const_tree type, bool named ATTRIBUTE_UNUSED) |
2285 { | 2299 { |
2300 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); | |
2286 int size; | 2301 int size; |
2287 | 2302 |
2288 /* We must pass by reference if we would be both passing in registers | 2303 /* We must pass by reference if we would be both passing in registers |
2289 and the stack. This is because any subsequent partial arg would be | 2304 and the stack. This is because any subsequent partial arg would be |
2290 handled incorrectly in this case. */ | 2305 handled incorrectly in this case. */ |
2294 get double copies of any offsets generated for small structs | 2309 get double copies of any offsets generated for small structs |
2295 passed in registers. */ | 2310 passed in registers. */ |
2296 CUMULATIVE_ARGS temp; | 2311 CUMULATIVE_ARGS temp; |
2297 | 2312 |
2298 temp = *cum; | 2313 temp = *cum; |
2299 if (iq2000_function_arg (&temp, mode, type, named) != 0) | 2314 if (iq2000_function_arg (pack_cumulative_args (&temp), mode, type, named) |
2315 != 0) | |
2300 return 1; | 2316 return 1; |
2301 } | 2317 } |
2302 | 2318 |
2303 if (type == NULL_TREE || mode == DImode || mode == DFmode) | 2319 if (type == NULL_TREE || mode == DImode || mode == DFmode) |
2304 return 0; | 2320 return 0; |
2309 | 2325 |
2310 /* Return the length of INSN. LENGTH is the initial length computed by | 2326 /* Return the length of INSN. LENGTH is the initial length computed by |
2311 attributes in the machine-description file. */ | 2327 attributes in the machine-description file. */ |
2312 | 2328 |
2313 int | 2329 int |
2314 iq2000_adjust_insn_length (rtx insn, int length) | 2330 iq2000_adjust_insn_length (rtx_insn *insn, int length) |
2315 { | 2331 { |
2316 /* A unconditional jump has an unfilled delay slot if it is not part | 2332 /* A unconditional jump has an unfilled delay slot if it is not part |
2317 of a sequence. A conditional jump normally has a delay slot. */ | 2333 of a sequence. A conditional jump normally has a delay slot. */ |
2318 if (simplejump_p (insn) | 2334 if (simplejump_p (insn) |
2319 || ( (GET_CODE (insn) == JUMP_INSN | 2335 || ( (JUMP_P (insn) |
2320 || GET_CODE (insn) == CALL_INSN))) | 2336 || CALL_P (insn)))) |
2321 length += 4; | 2337 length += 4; |
2322 | 2338 |
2323 return length; | 2339 return length; |
2324 } | 2340 } |
2325 | 2341 |
2337 LENGTH is the length (in bytes) of the sequence we are to generate. | 2353 LENGTH is the length (in bytes) of the sequence we are to generate. |
2338 That tells us whether to generate a simple conditional branch, or a | 2354 That tells us whether to generate a simple conditional branch, or a |
2339 reversed conditional branch around a `jr' instruction. */ | 2355 reversed conditional branch around a `jr' instruction. */ |
2340 | 2356 |
2341 char * | 2357 char * |
2342 iq2000_output_conditional_branch (rtx insn, rtx * operands, int two_operands_p, | 2358 iq2000_output_conditional_branch (rtx_insn *insn, rtx * operands, |
2343 int float_p, int inverted_p, int length) | 2359 int two_operands_p, int float_p, |
2360 int inverted_p, int length) | |
2344 { | 2361 { |
2345 static char buffer[200]; | 2362 static char buffer[200]; |
2346 /* The kind of comparison we are doing. */ | 2363 /* The kind of comparison we are doing. */ |
2347 enum rtx_code code = GET_CODE (operands[0]); | 2364 enum rtx_code code = GET_CODE (operands[0]); |
2348 /* Nonzero if the opcode for the comparison needs a `z' indicating | 2365 /* Nonzero if the opcode for the comparison needs a `z' indicating |
2497 NULL, NULL_TREE) | 2514 NULL, NULL_TREE) |
2498 | 2515 |
2499 static void | 2516 static void |
2500 iq2000_init_builtins (void) | 2517 iq2000_init_builtins (void) |
2501 { | 2518 { |
2502 tree endlink = void_list_node; | |
2503 tree void_ftype, void_ftype_int, void_ftype_int_int; | 2519 tree void_ftype, void_ftype_int, void_ftype_int_int; |
2504 tree void_ftype_int_int_int; | 2520 tree void_ftype_int_int_int; |
2505 tree int_ftype_int, int_ftype_int_int, int_ftype_int_int_int; | 2521 tree int_ftype_int, int_ftype_int_int, int_ftype_int_int_int; |
2506 tree int_ftype_int_int_int_int; | 2522 tree int_ftype_int_int_int_int; |
2507 | 2523 |
2508 /* func () */ | 2524 /* func () */ |
2509 void_ftype | 2525 void_ftype |
2510 = build_function_type (void_type_node, | 2526 = build_function_type_list (void_type_node, NULL_TREE); |
2511 tree_cons (NULL_TREE, void_type_node, endlink)); | |
2512 | 2527 |
2513 /* func (int) */ | 2528 /* func (int) */ |
2514 void_ftype_int | 2529 void_ftype_int |
2515 = build_function_type (void_type_node, | 2530 = build_function_type_list (void_type_node, integer_type_node, NULL_TREE); |
2516 tree_cons (NULL_TREE, integer_type_node, endlink)); | |
2517 | 2531 |
2518 /* void func (int, int) */ | 2532 /* void func (int, int) */ |
2519 void_ftype_int_int | 2533 void_ftype_int_int |
2520 = build_function_type (void_type_node, | 2534 = build_function_type_list (void_type_node, |
2521 tree_cons (NULL_TREE, integer_type_node, | 2535 integer_type_node, |
2522 tree_cons (NULL_TREE, integer_type_node, | 2536 integer_type_node, |
2523 endlink))); | 2537 NULL_TREE); |
2524 | 2538 |
2525 /* int func (int) */ | 2539 /* int func (int) */ |
2526 int_ftype_int | 2540 int_ftype_int |
2527 = build_function_type (integer_type_node, | 2541 = build_function_type_list (integer_type_node, |
2528 tree_cons (NULL_TREE, integer_type_node, endlink)); | 2542 integer_type_node, NULL_TREE); |
2529 | 2543 |
2530 /* int func (int, int) */ | 2544 /* int func (int, int) */ |
2531 int_ftype_int_int | 2545 int_ftype_int_int |
2532 = build_function_type (integer_type_node, | 2546 = build_function_type_list (integer_type_node, |
2533 tree_cons (NULL_TREE, integer_type_node, | 2547 integer_type_node, |
2534 tree_cons (NULL_TREE, integer_type_node, | 2548 integer_type_node, |
2535 endlink))); | 2549 NULL_TREE); |
2536 | 2550 |
2537 /* void func (int, int, int) */ | 2551 /* void func (int, int, int) */ |
2538 void_ftype_int_int_int | 2552 void_ftype_int_int_int |
2539 = build_function_type | 2553 = build_function_type_list (void_type_node, |
2540 (void_type_node, | 2554 integer_type_node, |
2541 tree_cons (NULL_TREE, integer_type_node, | 2555 integer_type_node, |
2542 tree_cons (NULL_TREE, integer_type_node, | 2556 integer_type_node, |
2543 tree_cons (NULL_TREE, | 2557 NULL_TREE); |
2544 integer_type_node, | 2558 |
2545 endlink)))); | 2559 /* int func (int, int, int) */ |
2560 int_ftype_int_int_int | |
2561 = build_function_type_list (integer_type_node, | |
2562 integer_type_node, | |
2563 integer_type_node, | |
2564 integer_type_node, | |
2565 NULL_TREE); | |
2546 | 2566 |
2547 /* int func (int, int, int, int) */ | 2567 /* int func (int, int, int, int) */ |
2548 int_ftype_int_int_int_int | 2568 int_ftype_int_int_int_int |
2549 = build_function_type | 2569 = build_function_type_list (integer_type_node, |
2550 (integer_type_node, | 2570 integer_type_node, |
2551 tree_cons (NULL_TREE, integer_type_node, | 2571 integer_type_node, |
2552 tree_cons (NULL_TREE, integer_type_node, | 2572 integer_type_node, |
2553 tree_cons (NULL_TREE, | 2573 integer_type_node, |
2554 integer_type_node, | 2574 NULL_TREE); |
2555 tree_cons (NULL_TREE, | |
2556 integer_type_node, | |
2557 endlink))))); | |
2558 | |
2559 /* int func (int, int, int) */ | |
2560 int_ftype_int_int_int | |
2561 = build_function_type | |
2562 (integer_type_node, | |
2563 tree_cons (NULL_TREE, integer_type_node, | |
2564 tree_cons (NULL_TREE, integer_type_node, | |
2565 tree_cons (NULL_TREE, | |
2566 integer_type_node, | |
2567 endlink)))); | |
2568 | |
2569 /* int func (int, int, int, int) */ | |
2570 int_ftype_int_int_int_int | |
2571 = build_function_type | |
2572 (integer_type_node, | |
2573 tree_cons (NULL_TREE, integer_type_node, | |
2574 tree_cons (NULL_TREE, integer_type_node, | |
2575 tree_cons (NULL_TREE, | |
2576 integer_type_node, | |
2577 tree_cons (NULL_TREE, | |
2578 integer_type_node, | |
2579 endlink))))); | |
2580 | 2575 |
2581 def_builtin ("__builtin_ado16", int_ftype_int_int, IQ2000_BUILTIN_ADO16); | 2576 def_builtin ("__builtin_ado16", int_ftype_int_int, IQ2000_BUILTIN_ADO16); |
2582 def_builtin ("__builtin_ram", int_ftype_int_int_int_int, IQ2000_BUILTIN_RAM); | 2577 def_builtin ("__builtin_ram", int_ftype_int_int_int_int, IQ2000_BUILTIN_RAM); |
2583 def_builtin ("__builtin_chkhdr", void_ftype_int_int, IQ2000_BUILTIN_CHKHDR); | 2578 def_builtin ("__builtin_chkhdr", void_ftype_int_int, IQ2000_BUILTIN_CHKHDR); |
2584 def_builtin ("__builtin_pkrl", void_ftype_int_int, IQ2000_BUILTIN_PKRL); | 2579 def_builtin ("__builtin_pkrl", void_ftype_int_int, IQ2000_BUILTIN_PKRL); |
2634 enum rtx_code *code, int argcount) | 2629 enum rtx_code *code, int argcount) |
2635 { | 2630 { |
2636 rtx pat; | 2631 rtx pat; |
2637 tree arg [5]; | 2632 tree arg [5]; |
2638 rtx op [5]; | 2633 rtx op [5]; |
2639 enum machine_mode mode [5]; | 2634 machine_mode mode [5]; |
2640 int i; | 2635 int i; |
2641 | 2636 |
2642 mode[0] = insn_data[icode].operand[0].mode; | 2637 mode[0] = insn_data[icode].operand[0].mode; |
2643 for (i = 0; i < argcount; i++) | 2638 for (i = 0; i < argcount; i++) |
2644 { | 2639 { |
2664 | 2659 |
2665 switch (argcount) | 2660 switch (argcount) |
2666 { | 2661 { |
2667 case 0: | 2662 case 0: |
2668 pat = GEN_FCN (icode) (target); | 2663 pat = GEN_FCN (icode) (target); |
2664 break; | |
2669 case 1: | 2665 case 1: |
2670 if (target) | 2666 if (target) |
2671 pat = GEN_FCN (icode) (target, op[0]); | 2667 pat = GEN_FCN (icode) (target, op[0]); |
2672 else | 2668 else |
2673 pat = GEN_FCN (icode) (op[0]); | 2669 pat = GEN_FCN (icode) (op[0]); |
2706 SUBTARGET may be used as the target for computing one of EXP's operands. | 2702 SUBTARGET may be used as the target for computing one of EXP's operands. |
2707 IGNORE is nonzero if the value is to be ignored. */ | 2703 IGNORE is nonzero if the value is to be ignored. */ |
2708 | 2704 |
2709 static rtx | 2705 static rtx |
2710 iq2000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, | 2706 iq2000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, |
2711 enum machine_mode mode ATTRIBUTE_UNUSED, | 2707 machine_mode mode ATTRIBUTE_UNUSED, |
2712 int ignore ATTRIBUTE_UNUSED) | 2708 int ignore ATTRIBUTE_UNUSED) |
2713 { | 2709 { |
2714 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); | 2710 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); |
2715 int fcode = DECL_FUNCTION_CODE (fndecl); | 2711 int fcode = DECL_FUNCTION_CODE (fndecl); |
2716 enum rtx_code code [5]; | 2712 enum rtx_code code [5]; |
2897 } | 2893 } |
2898 | 2894 |
2899 /* Worker function for TARGET_SETUP_INCOMING_VARARGS. */ | 2895 /* Worker function for TARGET_SETUP_INCOMING_VARARGS. */ |
2900 | 2896 |
2901 static void | 2897 static void |
2902 iq2000_setup_incoming_varargs (CUMULATIVE_ARGS *cum, | 2898 iq2000_setup_incoming_varargs (cumulative_args_t cum_v, |
2903 enum machine_mode mode ATTRIBUTE_UNUSED, | 2899 machine_mode mode ATTRIBUTE_UNUSED, |
2904 tree type ATTRIBUTE_UNUSED, int * pretend_size, | 2900 tree type ATTRIBUTE_UNUSED, int * pretend_size, |
2905 int no_rtl) | 2901 int no_rtl) |
2906 { | 2902 { |
2903 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); | |
2907 unsigned int iq2000_off = ! cum->last_arg_fp; | 2904 unsigned int iq2000_off = ! cum->last_arg_fp; |
2908 unsigned int iq2000_fp_off = cum->last_arg_fp; | 2905 unsigned int iq2000_fp_off = cum->last_arg_fp; |
2909 | 2906 |
2910 if ((cum->arg_words < MAX_ARGS_IN_REGISTERS - iq2000_off)) | 2907 if ((cum->arg_words < MAX_ARGS_IN_REGISTERS - iq2000_off)) |
2911 { | 2908 { |
2925 if (! (no_rtl)) | 2922 if (! (no_rtl)) |
2926 { | 2923 { |
2927 if (cum->arg_words < MAX_ARGS_IN_REGISTERS - iq2000_off) | 2924 if (cum->arg_words < MAX_ARGS_IN_REGISTERS - iq2000_off) |
2928 { | 2925 { |
2929 rtx ptr, mem; | 2926 rtx ptr, mem; |
2930 ptr = plus_constant (virtual_incoming_args_rtx, | 2927 ptr = plus_constant (Pmode, virtual_incoming_args_rtx, |
2931 - (iq2000_save_gp_regs | 2928 - (iq2000_save_gp_regs |
2932 * UNITS_PER_WORD)); | 2929 * UNITS_PER_WORD)); |
2933 mem = gen_rtx_MEM (BLKmode, ptr); | 2930 mem = gen_rtx_MEM (BLKmode, ptr); |
2934 move_block_from_reg | 2931 move_block_from_reg |
2935 (cum->arg_words + GP_ARG_FIRST + iq2000_off, | 2932 (cum->arg_words + GP_ARG_FIRST + iq2000_off, |
2936 mem, | 2933 mem, |
2937 iq2000_save_gp_regs); | 2934 iq2000_save_gp_regs); |
2943 /* A C compound statement to output to stdio stream STREAM the | 2940 /* A C compound statement to output to stdio stream STREAM the |
2944 assembler syntax for an instruction operand that is a memory | 2941 assembler syntax for an instruction operand that is a memory |
2945 reference whose address is ADDR. ADDR is an RTL expression. */ | 2942 reference whose address is ADDR. ADDR is an RTL expression. */ |
2946 | 2943 |
2947 static void | 2944 static void |
2948 iq2000_print_operand_address (FILE * file, rtx addr) | 2945 iq2000_print_operand_address (FILE * file, machine_mode mode, rtx addr) |
2949 { | 2946 { |
2950 if (!addr) | 2947 if (!addr) |
2951 error ("PRINT_OPERAND_ADDRESS, null pointer"); | 2948 error ("PRINT_OPERAND_ADDRESS, null pointer"); |
2952 | 2949 |
2953 else | 2950 else |
2968 if (GET_CODE (arg0) != REG) | 2965 if (GET_CODE (arg0) != REG) |
2969 abort_with_insn (addr, | 2966 abort_with_insn (addr, |
2970 "PRINT_OPERAND_ADDRESS, LO_SUM with #1 not REG."); | 2967 "PRINT_OPERAND_ADDRESS, LO_SUM with #1 not REG."); |
2971 | 2968 |
2972 fprintf (file, "%%lo("); | 2969 fprintf (file, "%%lo("); |
2973 iq2000_print_operand_address (file, arg1); | 2970 iq2000_print_operand_address (file, mode, arg1); |
2974 fprintf (file, ")(%s)", reg_names [REGNO (arg0)]); | 2971 fprintf (file, ")(%s)", reg_names [REGNO (arg0)]); |
2975 } | 2972 } |
2976 break; | 2973 break; |
2977 | 2974 |
2978 case PLUS: | 2975 case PLUS: |
3216 fprintf (file, "%s", reg_names[regnum]); | 3213 fprintf (file, "%s", reg_names[regnum]); |
3217 } | 3214 } |
3218 | 3215 |
3219 else if (code == MEM) | 3216 else if (code == MEM) |
3220 { | 3217 { |
3218 machine_mode mode = GET_MODE (op); | |
3219 | |
3221 if (letter == 'D') | 3220 if (letter == 'D') |
3222 output_address (plus_constant (XEXP (op, 0), 4)); | 3221 output_address (mode, plus_constant (Pmode, XEXP (op, 0), 4)); |
3223 else | 3222 else |
3224 output_address (XEXP (op, 0)); | 3223 output_address (mode, XEXP (op, 0)); |
3225 } | 3224 } |
3226 | 3225 |
3227 else if (code == CONST_DOUBLE | 3226 else if (code == CONST_DOUBLE |
3228 && GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT) | 3227 && GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT) |
3229 { | 3228 { |
3281 memory (Z + (<large int> & 0x7fff)); | 3280 memory (Z + (<large int> & 0x7fff)); |
3282 */ | 3281 */ |
3283 | 3282 |
3284 rtx | 3283 rtx |
3285 iq2000_legitimize_address (rtx xinsn, rtx old_x ATTRIBUTE_UNUSED, | 3284 iq2000_legitimize_address (rtx xinsn, rtx old_x ATTRIBUTE_UNUSED, |
3286 enum machine_mode mode) | 3285 machine_mode mode) |
3287 { | 3286 { |
3288 if (TARGET_DEBUG_B_MODE) | 3287 if (TARGET_DEBUG_B_MODE) |
3289 { | 3288 { |
3290 GO_PRINTF ("\n========== LEGITIMIZE_ADDRESS\n"); | 3289 GO_PRINTF ("\n========== LEGITIMIZE_ADDRESS\n"); |
3291 GO_DEBUG_RTX (xinsn); | 3290 GO_DEBUG_RTX (xinsn); |
3321 rtx ptr_reg = gen_reg_rtx (Pmode); | 3320 rtx ptr_reg = gen_reg_rtx (Pmode); |
3322 | 3321 |
3323 emit_move_insn (int_reg, | 3322 emit_move_insn (int_reg, |
3324 GEN_INT (INTVAL (xplus1) & ~ 0x7fff)); | 3323 GEN_INT (INTVAL (xplus1) & ~ 0x7fff)); |
3325 | 3324 |
3326 emit_insn (gen_rtx_SET (VOIDmode, | 3325 emit_insn (gen_rtx_SET (ptr_reg, |
3327 ptr_reg, | |
3328 gen_rtx_PLUS (Pmode, xplus0, int_reg))); | 3326 gen_rtx_PLUS (Pmode, xplus0, int_reg))); |
3329 | 3327 |
3330 return plus_constant (ptr_reg, INTVAL (xplus1) & 0x7fff); | 3328 return plus_constant (Pmode, ptr_reg, INTVAL (xplus1) & 0x7fff); |
3331 } | 3329 } |
3332 } | 3330 } |
3333 | 3331 |
3334 if (TARGET_DEBUG_B_MODE) | 3332 if (TARGET_DEBUG_B_MODE) |
3335 GO_PRINTF ("LEGITIMIZE_ADDRESS could not fix.\n"); | 3333 GO_PRINTF ("LEGITIMIZE_ADDRESS could not fix.\n"); |
3337 return xinsn; | 3335 return xinsn; |
3338 } | 3336 } |
3339 | 3337 |
3340 | 3338 |
3341 static bool | 3339 static bool |
3342 iq2000_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int * total, | 3340 iq2000_rtx_costs (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED, |
3341 int opno ATTRIBUTE_UNUSED, int * total, | |
3343 bool speed ATTRIBUTE_UNUSED) | 3342 bool speed ATTRIBUTE_UNUSED) |
3344 { | 3343 { |
3345 enum machine_mode mode = GET_MODE (x); | 3344 int code = GET_CODE (x); |
3346 | 3345 |
3347 switch (code) | 3346 switch (code) |
3348 { | 3347 { |
3349 case MEM: | 3348 case MEM: |
3350 { | 3349 { |
3351 int num_words = (GET_MODE_SIZE (mode) > UNITS_PER_WORD) ? 2 : 1; | 3350 int num_words = (GET_MODE_SIZE (mode) > UNITS_PER_WORD) ? 2 : 1; |
3352 | 3351 |
3353 if (simple_memory_operand (x, mode)) | 3352 if (simple_memory_operand (x, mode)) |
3354 return COSTS_N_INSNS (num_words); | 3353 return COSTS_N_INSNS (num_words) != 0; |
3355 | 3354 |
3356 * total = COSTS_N_INSNS (2 * num_words); | 3355 * total = COSTS_N_INSNS (2 * num_words); |
3357 break; | 3356 break; |
3358 } | 3357 } |
3359 | 3358 |
3518 mem = adjust_address (m_tramp, Pmode, | 3517 mem = adjust_address (m_tramp, Pmode, |
3519 TRAMPOLINE_CODE_SIZE + GET_MODE_SIZE (Pmode)); | 3518 TRAMPOLINE_CODE_SIZE + GET_MODE_SIZE (Pmode)); |
3520 emit_move_insn (mem, chain_value); | 3519 emit_move_insn (mem, chain_value); |
3521 } | 3520 } |
3522 | 3521 |
3522 /* Implement TARGET_HARD_REGNO_MODE_OK. */ | |
3523 | |
3524 static bool | |
3525 iq2000_hard_regno_mode_ok (unsigned int regno, machine_mode mode) | |
3526 { | |
3527 return (REGNO_REG_CLASS (regno) == GR_REGS | |
3528 ? (regno & 1) == 0 || GET_MODE_SIZE (mode) <= 4 | |
3529 : (regno & 1) == 0 || GET_MODE_SIZE (mode) == 4); | |
3530 } | |
3531 | |
3532 /* Implement TARGET_MODES_TIEABLE_P. */ | |
3533 | |
3534 static bool | |
3535 iq2000_modes_tieable_p (machine_mode mode1, machine_mode mode2) | |
3536 { | |
3537 return ((GET_MODE_CLASS (mode1) == MODE_FLOAT | |
3538 || GET_MODE_CLASS (mode1) == MODE_COMPLEX_FLOAT) | |
3539 == (GET_MODE_CLASS (mode2) == MODE_FLOAT | |
3540 || GET_MODE_CLASS (mode2) == MODE_COMPLEX_FLOAT)); | |
3541 } | |
3542 | |
3543 /* Implement TARGET_CONSTANT_ALIGNMENT. */ | |
3544 | |
3545 static HOST_WIDE_INT | |
3546 iq2000_constant_alignment (const_tree exp, HOST_WIDE_INT align) | |
3547 { | |
3548 if (TREE_CODE (exp) == STRING_CST || TREE_CODE (exp) == CONSTRUCTOR) | |
3549 return MAX (align, BITS_PER_WORD); | |
3550 return align; | |
3551 } | |
3552 | |
3553 /* Implement TARGET_STARTING_FRAME_OFFSET. */ | |
3554 | |
3555 static HOST_WIDE_INT | |
3556 iq2000_starting_frame_offset (void) | |
3557 { | |
3558 return crtl->outgoing_args_size; | |
3559 } | |
3560 | |
3523 #include "gt-iq2000.h" | 3561 #include "gt-iq2000.h" |