Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/v850/v850.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 for insn-output.c for NEC V850 series | 1 /* Subroutines for insn-output.c for NEC V850 series |
2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, | 2 Copyright (C) 1996-2017 Free Software Foundation, Inc. |
3 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. | |
4 Contributed by Jeff Law (law@cygnus.com). | 3 Contributed by Jeff Law (law@cygnus.com). |
5 | 4 |
6 This file is part of GCC. | 5 This file is part of GCC. |
7 | 6 |
8 GCC is free software; you can redistribute it and/or modify it | 7 GCC is free software; you can redistribute it and/or modify it |
20 <http://www.gnu.org/licenses/>. */ | 19 <http://www.gnu.org/licenses/>. */ |
21 | 20 |
22 #include "config.h" | 21 #include "config.h" |
23 #include "system.h" | 22 #include "system.h" |
24 #include "coretypes.h" | 23 #include "coretypes.h" |
25 #include "tm.h" | 24 #include "backend.h" |
25 #include "target.h" | |
26 #include "rtl.h" | |
26 #include "tree.h" | 27 #include "tree.h" |
27 #include "rtl.h" | 28 #include "df.h" |
29 #include "memmodel.h" | |
30 #include "tm_p.h" | |
31 #include "stringpool.h" | |
32 #include "attribs.h" | |
33 #include "insn-config.h" | |
28 #include "regs.h" | 34 #include "regs.h" |
29 #include "hard-reg-set.h" | 35 #include "emit-rtl.h" |
30 #include "insn-config.h" | 36 #include "recog.h" |
37 #include "diagnostic-core.h" | |
38 #include "stor-layout.h" | |
39 #include "varasm.h" | |
40 #include "calls.h" | |
31 #include "conditions.h" | 41 #include "conditions.h" |
32 #include "output.h" | 42 #include "output.h" |
33 #include "insn-attr.h" | 43 #include "insn-attr.h" |
34 #include "flags.h" | |
35 #include "recog.h" | |
36 #include "expr.h" | 44 #include "expr.h" |
37 #include "function.h" | 45 #include "cfgrtl.h" |
38 #include "diagnostic-core.h" | 46 #include "builtins.h" |
39 #include "ggc.h" | 47 |
40 #include "integrate.h" | 48 /* This file should be included last. */ |
41 #include "tm_p.h" | |
42 #include "target.h" | |
43 #include "target-def.h" | 49 #include "target-def.h" |
44 #include "df.h" | |
45 | 50 |
46 #ifndef streq | 51 #ifndef streq |
47 #define streq(a,b) (strcmp (a, b) == 0) | 52 #define streq(a,b) (strcmp (a, b) == 0) |
48 #endif | 53 #endif |
49 | 54 |
50 static void v850_print_operand_address (FILE *, rtx); | 55 static void v850_print_operand_address (FILE *, machine_mode, rtx); |
51 | |
52 /* Information about the various small memory areas. */ | |
53 struct small_memory_info small_memory[ (int)SMALL_MEMORY_max ] = | |
54 { | |
55 /* Name Max Physical max. */ | |
56 { "tda", 0, 256 }, | |
57 { "sda", 0, 65536 }, | |
58 { "zda", 0, 32768 }, | |
59 }; | |
60 | 56 |
61 /* Names of the various data areas used on the v850. */ | 57 /* Names of the various data areas used on the v850. */ |
62 tree GHS_default_section_names [(int) COUNT_OF_GHS_SECTION_KINDS]; | 58 const char * GHS_default_section_names [(int) COUNT_OF_GHS_SECTION_KINDS]; |
63 tree GHS_current_section_names [(int) COUNT_OF_GHS_SECTION_KINDS]; | 59 const char * GHS_current_section_names [(int) COUNT_OF_GHS_SECTION_KINDS]; |
64 | 60 |
65 /* Track the current data area set by the data area pragma (which | 61 /* Track the current data area set by the data area pragma (which |
66 can be nested). Tested by check_default_data_area. */ | 62 can be nested). Tested by check_default_data_area. */ |
67 data_area_stack_element * data_area_stack = NULL; | 63 data_area_stack_element * data_area_stack = NULL; |
68 | 64 |
79 static GTY(()) section * rozdata_section; | 75 static GTY(()) section * rozdata_section; |
80 static GTY(()) section * tdata_section; | 76 static GTY(()) section * tdata_section; |
81 static GTY(()) section * zdata_section; | 77 static GTY(()) section * zdata_section; |
82 static GTY(()) section * zbss_section; | 78 static GTY(()) section * zbss_section; |
83 | 79 |
84 /* Set the maximum size of small memory area TYPE to the value given | 80 /* We use this to wrap all emitted insns in the prologue. */ |
85 by VALUE. Return true if VALUE was syntactically correct. VALUE | 81 static rtx |
86 starts with the argument separator: either "-" or "=". */ | 82 F (rtx x) |
87 | 83 { |
88 static bool | 84 if (GET_CODE (x) != CLOBBER) |
89 v850_handle_memory_option (enum small_memory_type type, const char *value) | 85 RTX_FRAME_RELATED_P (x) = 1; |
90 { | 86 return x; |
91 int i, size; | 87 } |
92 | 88 |
93 if (*value != '-' && *value != '=') | 89 /* Mark all the subexpressions of the PARALLEL rtx PAR as |
94 return false; | 90 frame-related. Return PAR. |
95 | 91 |
96 value++; | 92 dwarf2out.c:dwarf2out_frame_debug_expr ignores sub-expressions of a |
97 for (i = 0; value[i]; i++) | 93 PARALLEL rtx other than the first if they do not have the |
98 if (!ISDIGIT (value[i])) | 94 FRAME_RELATED flag set on them. */ |
99 return false; | 95 |
100 | 96 static rtx |
101 size = atoi (value); | 97 v850_all_frame_related (rtx par) |
102 if (size > small_memory[type].physical_max) | 98 { |
103 error ("value passed to %<-m%s%> is too large", small_memory[type].name); | 99 int len = XVECLEN (par, 0); |
104 else | 100 int i; |
105 small_memory[type].max = size; | 101 |
106 return true; | 102 gcc_assert (GET_CODE (par) == PARALLEL); |
107 } | 103 for (i = 0; i < len; i++) |
108 | 104 F (XVECEXP (par, 0, i)); |
109 /* Implement TARGET_HANDLE_OPTION. */ | 105 |
110 | 106 return par; |
111 static bool | 107 } |
112 v850_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED) | |
113 { | |
114 switch (code) | |
115 { | |
116 case OPT_mspace: | |
117 target_flags |= MASK_EP | MASK_PROLOG_FUNCTION; | |
118 return true; | |
119 | |
120 case OPT_mv850: | |
121 target_flags &= ~(MASK_CPU ^ MASK_V850); | |
122 return true; | |
123 | |
124 case OPT_mv850e: | |
125 case OPT_mv850e1: | |
126 target_flags &= ~(MASK_CPU ^ MASK_V850E); | |
127 return true; | |
128 | |
129 case OPT_mtda: | |
130 return v850_handle_memory_option (SMALL_MEMORY_TDA, arg); | |
131 | |
132 case OPT_msda: | |
133 return v850_handle_memory_option (SMALL_MEMORY_SDA, arg); | |
134 | |
135 case OPT_mzda: | |
136 return v850_handle_memory_option (SMALL_MEMORY_ZDA, arg); | |
137 | |
138 default: | |
139 return true; | |
140 } | |
141 } | |
142 | |
143 /* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */ | |
144 | |
145 static const struct default_options v850_option_optimization_table[] = | |
146 { | |
147 { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 }, | |
148 /* Note - we no longer enable MASK_EP when optimizing. This is | |
149 because of a hardware bug which stops the SLD and SST instructions | |
150 from correctly detecting some hazards. If the user is sure that | |
151 their hardware is fixed or that their program will not encounter | |
152 the conditions that trigger the bug then they can enable -mep by | |
153 hand. */ | |
154 { OPT_LEVELS_1_PLUS, OPT_mprolog_function, NULL, 1 }, | |
155 { OPT_LEVELS_NONE, 0, NULL, 0 } | |
156 }; | |
157 | 108 |
158 /* Handle the TARGET_PASS_BY_REFERENCE target hook. | 109 /* Handle the TARGET_PASS_BY_REFERENCE target hook. |
159 Specify whether to pass the argument by reference. */ | 110 Specify whether to pass the argument by reference. */ |
160 | 111 |
161 static bool | 112 static bool |
162 v850_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED, | 113 v850_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED, |
163 enum machine_mode mode, const_tree type, | 114 machine_mode mode, const_tree type, |
164 bool named ATTRIBUTE_UNUSED) | 115 bool named ATTRIBUTE_UNUSED) |
165 { | 116 { |
166 unsigned HOST_WIDE_INT size; | 117 unsigned HOST_WIDE_INT size; |
118 | |
119 if (!TARGET_GCC_ABI) | |
120 return 0; | |
167 | 121 |
168 if (type) | 122 if (type) |
169 size = int_size_in_bytes (type); | 123 size = int_size_in_bytes (type); |
170 else | 124 else |
171 size = GET_MODE_SIZE (mode); | 125 size = GET_MODE_SIZE (mode); |
172 | 126 |
173 return size > 8; | 127 return size > 8; |
174 } | 128 } |
175 | 129 |
176 /* Implementing the Varargs Macros. */ | |
177 | |
178 static bool | |
179 v850_strict_argument_naming (CUMULATIVE_ARGS * ca ATTRIBUTE_UNUSED) | |
180 { | |
181 return !TARGET_GHS ? true : false; | |
182 } | |
183 | |
184 /* Return an RTX to represent where an argument with mode MODE | 130 /* Return an RTX to represent where an argument with mode MODE |
185 and type TYPE will be passed to a function. If the result | 131 and type TYPE will be passed to a function. If the result |
186 is NULL_RTX, the argument will be pushed. */ | 132 is NULL_RTX, the argument will be pushed. */ |
187 | 133 |
188 static rtx | 134 static rtx |
189 v850_function_arg (CUMULATIVE_ARGS * cum, enum machine_mode mode, | 135 v850_function_arg (cumulative_args_t cum_v, machine_mode mode, |
190 const_tree type, bool named) | 136 const_tree type, bool named) |
191 { | 137 { |
138 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); | |
192 rtx result = NULL_RTX; | 139 rtx result = NULL_RTX; |
193 int size, align; | 140 int size, align; |
194 | 141 |
195 if (!named) | 142 if (!named) |
196 return NULL_RTX; | 143 return NULL_RTX; |
207 /* Once we have stopped using argument registers, do not start up again. */ | 154 /* Once we have stopped using argument registers, do not start up again. */ |
208 cum->nbytes = 4 * UNITS_PER_WORD; | 155 cum->nbytes = 4 * UNITS_PER_WORD; |
209 return NULL_RTX; | 156 return NULL_RTX; |
210 } | 157 } |
211 | 158 |
212 if (size <= UNITS_PER_WORD && type) | 159 if (!TARGET_GCC_ABI) |
160 align = UNITS_PER_WORD; | |
161 else if (size <= UNITS_PER_WORD && type) | |
213 align = TYPE_ALIGN (type) / BITS_PER_UNIT; | 162 align = TYPE_ALIGN (type) / BITS_PER_UNIT; |
214 else | 163 else |
215 align = size; | 164 align = size; |
216 | 165 |
217 cum->nbytes = (cum->nbytes + align - 1) &~(align - 1); | 166 cum->nbytes = (cum->nbytes + align - 1) &~(align - 1); |
245 } | 194 } |
246 | 195 |
247 /* Return the number of bytes which must be put into registers | 196 /* Return the number of bytes which must be put into registers |
248 for values which are part in registers and part in memory. */ | 197 for values which are part in registers and part in memory. */ |
249 static int | 198 static int |
250 v850_arg_partial_bytes (CUMULATIVE_ARGS * cum, enum machine_mode mode, | 199 v850_arg_partial_bytes (cumulative_args_t cum_v, machine_mode mode, |
251 tree type, bool named) | 200 tree type, bool named) |
252 { | 201 { |
202 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); | |
253 int size, align; | 203 int size, align; |
254 | 204 |
255 if (TARGET_GHS && !named) | 205 if (!named) |
256 return 0; | 206 return 0; |
257 | 207 |
258 if (mode == BLKmode) | 208 if (mode == BLKmode) |
259 size = int_size_in_bytes (type); | 209 size = int_size_in_bytes (type); |
260 else | 210 else |
261 size = GET_MODE_SIZE (mode); | 211 size = GET_MODE_SIZE (mode); |
262 | 212 |
263 if (size < 1) | 213 if (size < 1) |
264 size = 1; | 214 size = 1; |
265 | 215 |
266 if (type) | 216 if (!TARGET_GCC_ABI) |
217 align = UNITS_PER_WORD; | |
218 else if (type) | |
267 align = TYPE_ALIGN (type) / BITS_PER_UNIT; | 219 align = TYPE_ALIGN (type) / BITS_PER_UNIT; |
268 else | 220 else |
269 align = size; | 221 align = size; |
270 | 222 |
271 cum->nbytes = (cum->nbytes + align - 1) & ~ (align - 1); | 223 cum->nbytes = (cum->nbytes + align - 1) & ~ (align - 1); |
286 /* Update the data in CUM to advance over an argument | 238 /* Update the data in CUM to advance over an argument |
287 of mode MODE and data type TYPE. | 239 of mode MODE and data type TYPE. |
288 (TYPE is null for libcalls where that information may not be available.) */ | 240 (TYPE is null for libcalls where that information may not be available.) */ |
289 | 241 |
290 static void | 242 static void |
291 v850_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, | 243 v850_function_arg_advance (cumulative_args_t cum_v, machine_mode mode, |
292 const_tree type, bool named ATTRIBUTE_UNUSED) | 244 const_tree type, bool named ATTRIBUTE_UNUSED) |
293 { | 245 { |
294 cum->nbytes += (((type && int_size_in_bytes (type) > 8 | 246 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); |
295 ? GET_MODE_SIZE (Pmode) | 247 |
296 : (mode != BLKmode | 248 if (!TARGET_GCC_ABI) |
297 ? GET_MODE_SIZE (mode) | 249 cum->nbytes += (((mode != BLKmode |
298 : int_size_in_bytes (type))) + UNITS_PER_WORD - 1) | 250 ? GET_MODE_SIZE (mode) |
299 & -UNITS_PER_WORD); | 251 : int_size_in_bytes (type)) + UNITS_PER_WORD - 1) |
252 & -UNITS_PER_WORD); | |
253 else | |
254 cum->nbytes += (((type && int_size_in_bytes (type) > 8 | |
255 ? GET_MODE_SIZE (Pmode) | |
256 : (mode != BLKmode | |
257 ? GET_MODE_SIZE (mode) | |
258 : int_size_in_bytes (type))) + UNITS_PER_WORD - 1) | |
259 & -UNITS_PER_WORD); | |
300 } | 260 } |
301 | 261 |
302 /* Return the high and low words of a CONST_DOUBLE */ | 262 /* Return the high and low words of a CONST_DOUBLE */ |
303 | 263 |
304 static void | 264 static void |
305 const_double_split (rtx x, HOST_WIDE_INT * p_high, HOST_WIDE_INT * p_low) | 265 const_double_split (rtx x, HOST_WIDE_INT * p_high, HOST_WIDE_INT * p_low) |
306 { | 266 { |
307 if (GET_CODE (x) == CONST_DOUBLE) | 267 if (GET_CODE (x) == CONST_DOUBLE) |
308 { | 268 { |
309 long t[2]; | 269 long t[2]; |
310 REAL_VALUE_TYPE rv; | |
311 | 270 |
312 switch (GET_MODE (x)) | 271 switch (GET_MODE (x)) |
313 { | 272 { |
314 case DFmode: | 273 case E_DFmode: |
315 REAL_VALUE_FROM_CONST_DOUBLE (rv, x); | 274 REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (x), t); |
316 REAL_VALUE_TO_TARGET_DOUBLE (rv, t); | |
317 *p_high = t[1]; /* since v850 is little endian */ | 275 *p_high = t[1]; /* since v850 is little endian */ |
318 *p_low = t[0]; /* high is second word */ | 276 *p_low = t[0]; /* high is second word */ |
319 return; | 277 return; |
320 | 278 |
321 case SFmode: | 279 case E_SFmode: |
322 REAL_VALUE_FROM_CONST_DOUBLE (rv, x); | 280 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), *p_high); |
323 REAL_VALUE_TO_TARGET_SINGLE (rv, *p_high); | |
324 *p_low = 0; | 281 *p_low = 0; |
325 return; | 282 return; |
326 | 283 |
327 case VOIDmode: | 284 case E_VOIDmode: |
328 case DImode: | 285 case E_DImode: |
329 *p_high = CONST_DOUBLE_HIGH (x); | 286 *p_high = CONST_DOUBLE_HIGH (x); |
330 *p_low = CONST_DOUBLE_LOW (x); | 287 *p_low = CONST_DOUBLE_LOW (x); |
331 return; | 288 return; |
332 | 289 |
333 default: | 290 default: |
383 return 4; | 340 return 4; |
384 } | 341 } |
385 } | 342 } |
386 | 343 |
387 static bool | 344 static bool |
388 v850_rtx_costs (rtx x, | 345 v850_rtx_costs (rtx x, machine_mode mode, int outer_code, |
389 int codearg, | 346 int opno ATTRIBUTE_UNUSED, int *total, bool speed) |
390 int outer_code ATTRIBUTE_UNUSED, | 347 { |
391 int * total, bool speed) | 348 enum rtx_code code = GET_CODE (x); |
392 { | |
393 enum rtx_code code = (enum rtx_code) codearg; | |
394 | 349 |
395 switch (code) | 350 switch (code) |
396 { | 351 { |
397 case CONST_INT: | 352 case CONST_INT: |
398 case CONST_DOUBLE: | 353 case CONST_DOUBLE: |
412 *total = 60; | 367 *total = 60; |
413 return true; | 368 return true; |
414 | 369 |
415 case MULT: | 370 case MULT: |
416 if (TARGET_V850E | 371 if (TARGET_V850E |
417 && ( GET_MODE (x) == SImode | 372 && (mode == SImode || mode == HImode || mode == QImode)) |
418 || GET_MODE (x) == HImode | |
419 || GET_MODE (x) == QImode)) | |
420 { | 373 { |
421 if (GET_CODE (XEXP (x, 1)) == REG) | 374 if (GET_CODE (XEXP (x, 1)) == REG) |
422 *total = 4; | 375 *total = 4; |
423 else if (GET_CODE (XEXP (x, 1)) == CONST_INT) | 376 else if (GET_CODE (XEXP (x, 1)) == CONST_INT) |
424 { | 377 { |
451 HOST_WIDE_INT high, low; | 404 HOST_WIDE_INT high, low; |
452 | 405 |
453 switch (code) | 406 switch (code) |
454 { | 407 { |
455 case 'c': | 408 case 'c': |
456 /* We use 'c' operands with symbols for .vtinherit */ | 409 /* We use 'c' operands with symbols for .vtinherit. */ |
457 if (GET_CODE (x) == SYMBOL_REF) | 410 if (GET_CODE (x) == SYMBOL_REF) |
458 { | 411 { |
459 output_addr_const(file, x); | 412 output_addr_const(file, x); |
460 break; | 413 break; |
461 } | 414 } |
462 /* fall through */ | 415 /* Fall through. */ |
463 case 'b': | 416 case 'b': |
464 case 'B': | 417 case 'B': |
465 case 'C': | 418 case 'C': |
466 switch ((code == 'B' || code == 'C') | 419 switch ((code == 'B' || code == 'C') |
467 ? reverse_condition (GET_CODE (x)) : GET_CODE (x)) | 420 ? reverse_condition (GET_CODE (x)) : GET_CODE (x)) |
504 break; | 457 break; |
505 default: | 458 default: |
506 gcc_unreachable (); | 459 gcc_unreachable (); |
507 } | 460 } |
508 break; | 461 break; |
509 case 'F': /* high word of CONST_DOUBLE */ | 462 case 'F': /* High word of CONST_DOUBLE. */ |
510 switch (GET_CODE (x)) | 463 switch (GET_CODE (x)) |
511 { | 464 { |
512 case CONST_INT: | 465 case CONST_INT: |
513 fprintf (file, "%d", (INTVAL (x) >= 0) ? 0 : -1); | 466 fprintf (file, "%d", (INTVAL (x) >= 0) ? 0 : -1); |
514 break; | 467 break; |
520 | 473 |
521 default: | 474 default: |
522 gcc_unreachable (); | 475 gcc_unreachable (); |
523 } | 476 } |
524 break; | 477 break; |
525 case 'G': /* low word of CONST_DOUBLE */ | 478 case 'G': /* Low word of CONST_DOUBLE. */ |
526 switch (GET_CODE (x)) | 479 switch (GET_CODE (x)) |
527 { | 480 { |
528 case CONST_INT: | 481 case CONST_INT: |
529 fprintf (file, "%ld", (long) INTVAL (x)); | 482 fprintf (file, "%ld", (long) INTVAL (x)); |
530 break; | 483 break; |
587 { | 540 { |
588 case REG: | 541 case REG: |
589 fprintf (file, reg_names[REGNO (x) + 1]); | 542 fprintf (file, reg_names[REGNO (x) + 1]); |
590 break; | 543 break; |
591 case MEM: | 544 case MEM: |
592 x = XEXP (adjust_address (x, SImode, 4), 0); | 545 { |
593 v850_print_operand_address (file, x); | 546 machine_mode mode = GET_MODE (x); |
594 if (GET_CODE (x) == CONST_INT) | 547 x = XEXP (adjust_address (x, SImode, 4), 0); |
595 fprintf (file, "[r0]"); | 548 v850_print_operand_address (file, mode, x); |
549 if (GET_CODE (x) == CONST_INT) | |
550 fprintf (file, "[r0]"); | |
551 } | |
596 break; | 552 break; |
597 | 553 |
554 case CONST_INT: | |
555 { | |
556 unsigned HOST_WIDE_INT v = INTVAL (x); | |
557 | |
558 /* Trickery to avoid problems with shifting | |
559 32-bits at a time on a 32-bit host. */ | |
560 v = v >> 16; | |
561 v = v >> 16; | |
562 fprintf (file, HOST_WIDE_INT_PRINT_HEX, v); | |
563 break; | |
564 } | |
565 | |
566 case CONST_DOUBLE: | |
567 fprintf (file, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_HIGH (x)); | |
568 break; | |
569 | |
598 default: | 570 default: |
599 break; | 571 debug_rtx (x); |
572 gcc_unreachable (); | |
600 } | 573 } |
601 break; | 574 break; |
602 case 'S': | 575 case 'S': |
603 { | 576 { |
604 /* If it's a reference to a TDA variable, use sst/sld vs. st/ld. */ | 577 /* If it's a reference to a TDA variable, use sst/sld vs. st/ld. */ |
613 if (GET_CODE (x) == MEM && ep_memory_operand (x, GET_MODE (x), TRUE)) | 586 if (GET_CODE (x) == MEM && ep_memory_operand (x, GET_MODE (x), TRUE)) |
614 fputs ("s", file); | 587 fputs ("s", file); |
615 | 588 |
616 break; | 589 break; |
617 } | 590 } |
618 case 'W': /* print the instruction suffix */ | 591 case 'W': /* Print the instruction suffix. */ |
619 switch (GET_MODE (x)) | 592 switch (GET_MODE (x)) |
620 { | 593 { |
621 default: | 594 default: |
622 gcc_unreachable (); | 595 gcc_unreachable (); |
623 | 596 |
624 case QImode: fputs (".b", file); break; | 597 case E_QImode: fputs (".b", file); break; |
625 case HImode: fputs (".h", file); break; | 598 case E_HImode: fputs (".h", file); break; |
626 case SImode: fputs (".w", file); break; | 599 case E_SImode: fputs (".w", file); break; |
627 case SFmode: fputs (".w", file); break; | 600 case E_SFmode: fputs (".w", file); break; |
628 } | 601 } |
629 break; | 602 break; |
630 case '.': /* register r0 */ | 603 case '.': /* Register r0. */ |
631 fputs (reg_names[0], file); | 604 fputs (reg_names[0], file); |
632 break; | 605 break; |
633 case 'z': /* reg or zero */ | 606 case 'z': /* Reg or zero. */ |
634 if (GET_CODE (x) == REG) | 607 if (REG_P (x)) |
635 fputs (reg_names[REGNO (x)], file); | 608 fputs (reg_names[REGNO (x)], file); |
636 else if ((GET_MODE(x) == SImode | 609 else if ((GET_MODE(x) == SImode |
637 || GET_MODE(x) == DFmode | 610 || GET_MODE(x) == DFmode |
638 || GET_MODE(x) == SFmode) | 611 || GET_MODE(x) == SFmode) |
639 && x == CONST0_RTX(GET_MODE(x))) | 612 && x == CONST0_RTX(GET_MODE(x))) |
647 default: | 620 default: |
648 switch (GET_CODE (x)) | 621 switch (GET_CODE (x)) |
649 { | 622 { |
650 case MEM: | 623 case MEM: |
651 if (GET_CODE (XEXP (x, 0)) == CONST_INT) | 624 if (GET_CODE (XEXP (x, 0)) == CONST_INT) |
652 output_address (gen_rtx_PLUS (SImode, gen_rtx_REG (SImode, 0), | 625 output_address (GET_MODE (x), |
626 gen_rtx_PLUS (SImode, gen_rtx_REG (SImode, 0), | |
653 XEXP (x, 0))); | 627 XEXP (x, 0))); |
654 else | 628 else |
655 output_address (XEXP (x, 0)); | 629 output_address (GET_MODE (x), XEXP (x, 0)); |
656 break; | 630 break; |
657 | 631 |
658 case REG: | 632 case REG: |
659 fputs (reg_names[REGNO (x)], file); | 633 fputs (reg_names[REGNO (x)], file); |
660 break; | 634 break; |
661 case SUBREG: | 635 case SUBREG: |
662 fputs (reg_names[subreg_regno (x)], file); | 636 fputs (reg_names[subreg_regno (x)], file); |
663 break; | 637 break; |
638 case CONST_DOUBLE: | |
639 fprintf (file, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (x)); | |
640 break; | |
641 | |
664 case CONST_INT: | 642 case CONST_INT: |
665 case SYMBOL_REF: | 643 case SYMBOL_REF: |
666 case CONST: | 644 case CONST: |
667 case LABEL_REF: | 645 case LABEL_REF: |
668 case CODE_LABEL: | 646 case CODE_LABEL: |
669 v850_print_operand_address (file, x); | 647 v850_print_operand_address (file, VOIDmode, x); |
670 break; | 648 break; |
671 default: | 649 default: |
672 gcc_unreachable (); | 650 gcc_unreachable (); |
673 } | 651 } |
674 break; | 652 break; |
678 | 656 |
679 | 657 |
680 /* Output assembly language output for the address ADDR to FILE. */ | 658 /* Output assembly language output for the address ADDR to FILE. */ |
681 | 659 |
682 static void | 660 static void |
683 v850_print_operand_address (FILE * file, rtx addr) | 661 v850_print_operand_address (FILE * file, machine_mode /*mode*/, rtx addr) |
684 { | 662 { |
685 switch (GET_CODE (addr)) | 663 switch (GET_CODE (addr)) |
686 { | 664 { |
687 case REG: | 665 case REG: |
688 fprintf (file, "0["); | 666 fprintf (file, "0["); |
793 table it can encounter (TRUNCATE:HI (MINUS:SI (LABEL_REF:SI) (LABEL_REF:SI))). | 771 table it can encounter (TRUNCATE:HI (MINUS:SI (LABEL_REF:SI) (LABEL_REF:SI))). |
794 output_addr_const will normally barf at this, but it is OK to omit | 772 output_addr_const will normally barf at this, but it is OK to omit |
795 the truncate and just emit the difference of the two labels. The | 773 the truncate and just emit the difference of the two labels. The |
796 .hword directive will automatically handle the truncation for us. | 774 .hword directive will automatically handle the truncation for us. |
797 | 775 |
798 Returns 1 if rtx was handled, 0 otherwise. */ | 776 Returns true if rtx was handled, false otherwise. */ |
799 | 777 |
800 int | 778 static bool |
801 v850_output_addr_const_extra (FILE * file, rtx x) | 779 v850_output_addr_const_extra (FILE * file, rtx x) |
802 { | 780 { |
803 if (GET_CODE (x) != TRUNCATE) | 781 if (GET_CODE (x) != TRUNCATE) |
804 return 0; | 782 return false; |
805 | 783 |
806 x = XEXP (x, 0); | 784 x = XEXP (x, 0); |
807 | 785 |
808 /* We must also handle the case where the switch table was passed a | 786 /* We must also handle the case where the switch table was passed a |
809 constant value and so has been collapsed. In this case the first | 787 constant value and so has been collapsed. In this case the first |
810 label will have been deleted. In such a case it is OK to emit | 788 label will have been deleted. In such a case it is OK to emit |
811 nothing, since the table will not be used. | 789 nothing, since the table will not be used. |
812 (cf gcc.c-torture/compile/990801-1.c). */ | 790 (cf gcc.c-torture/compile/990801-1.c). */ |
813 if (GET_CODE (x) == MINUS | 791 if (GET_CODE (x) == MINUS |
814 && GET_CODE (XEXP (x, 0)) == LABEL_REF | 792 && GET_CODE (XEXP (x, 0)) == LABEL_REF) |
815 && GET_CODE (XEXP (XEXP (x, 0), 0)) == CODE_LABEL | 793 { |
816 && INSN_DELETED_P (XEXP (XEXP (x, 0), 0))) | 794 rtx_code_label *label |
817 return 1; | 795 = dyn_cast<rtx_code_label *> (XEXP (XEXP (x, 0), 0)); |
796 if (label && label->deleted ()) | |
797 return true; | |
798 } | |
818 | 799 |
819 output_addr_const (file, x); | 800 output_addr_const (file, x); |
820 return 1; | 801 return true; |
821 } | 802 } |
822 | 803 |
823 /* Return appropriate code to load up a 1, 2, or 4 integer/floating | 804 /* Return appropriate code to load up a 1, 2, or 4 integer/floating |
824 point value. */ | 805 point value. */ |
825 | 806 |
846 | 827 |
847 else if (CONST_OK_FOR_L (value)) /* Upper 16 bits were set. */ | 828 else if (CONST_OK_FOR_L (value)) /* Upper 16 bits were set. */ |
848 return "movhi hi0(%1),%.,%0"; | 829 return "movhi hi0(%1),%.,%0"; |
849 | 830 |
850 /* A random constant. */ | 831 /* A random constant. */ |
851 else if (TARGET_V850E || TARGET_V850E2_ALL) | 832 else if (TARGET_V850E_UP) |
852 return "mov %1,%0"; | 833 return "mov %1,%0"; |
853 else | 834 else |
854 return "movhi hi(%1),%.,%0\n\tmovea lo(%1),%0,%0"; | 835 return "movhi hi(%1),%.,%0\n\tmovea lo(%1),%0,%0"; |
855 } | 836 } |
856 | 837 |
868 | 849 |
869 else if (CONST_OK_FOR_L (high)) /* Upper 16 bits were set. */ | 850 else if (CONST_OK_FOR_L (high)) /* Upper 16 bits were set. */ |
870 return "movhi hi0(%F1),%.,%0"; | 851 return "movhi hi0(%F1),%.,%0"; |
871 | 852 |
872 /* A random constant. */ | 853 /* A random constant. */ |
873 else if (TARGET_V850E || TARGET_V850E2_ALL) | 854 else if (TARGET_V850E_UP) |
874 return "mov %F1,%0"; | 855 return "mov %F1,%0"; |
875 | 856 |
876 else | 857 else |
877 return "movhi hi(%F1),%.,%0\n\tmovea lo(%F1),%0,%0"; | 858 return "movhi hi(%F1),%.,%0\n\tmovea lo(%F1),%0,%0"; |
878 } | 859 } |
885 | 866 |
886 else if (GET_CODE (src) == LABEL_REF | 867 else if (GET_CODE (src) == LABEL_REF |
887 || GET_CODE (src) == SYMBOL_REF | 868 || GET_CODE (src) == SYMBOL_REF |
888 || GET_CODE (src) == CONST) | 869 || GET_CODE (src) == CONST) |
889 { | 870 { |
890 if (TARGET_V850E || TARGET_V850E2_ALL) | 871 if (TARGET_V850E_UP) |
891 return "mov hilo(%1),%0"; | 872 return "mov hilo(%1),%0"; |
892 else | 873 else |
893 return "movhi hi(%1),%.,%0\n\tmovea lo(%1),%0,%0"; | 874 return "movhi hi(%1),%.,%0\n\tmovea lo(%1),%0,%0"; |
894 } | 875 } |
895 | 876 |
915 else if (GET_CODE (src) == CONST_DOUBLE | 896 else if (GET_CODE (src) == CONST_DOUBLE |
916 && CONST0_RTX (GET_MODE (dst)) == src) | 897 && CONST0_RTX (GET_MODE (dst)) == src) |
917 return "%S0st%W0 %.,%0"; | 898 return "%S0st%W0 %.,%0"; |
918 } | 899 } |
919 | 900 |
920 fatal_insn ("output_move_single:", gen_rtx_SET (VOIDmode, dst, src)); | 901 fatal_insn ("output_move_single:", gen_rtx_SET (dst, src)); |
921 return ""; | 902 return ""; |
922 } | 903 } |
923 | 904 |
924 /* Generate comparison code. */ | 905 machine_mode |
925 int | |
926 v850_float_z_comparison_operator (rtx op, enum machine_mode mode) | |
927 { | |
928 enum rtx_code code = GET_CODE (op); | |
929 | |
930 if (GET_RTX_CLASS (code) != RTX_COMPARE | |
931 && GET_RTX_CLASS (code) != RTX_COMM_COMPARE) | |
932 return 0; | |
933 | |
934 if (mode != GET_MODE (op) && mode != VOIDmode) | |
935 return 0; | |
936 | |
937 if ((GET_CODE (XEXP (op, 0)) != REG | |
938 || REGNO (XEXP (op, 0)) != CC_REGNUM) | |
939 || XEXP (op, 1) != const0_rtx) | |
940 return 0; | |
941 | |
942 if (GET_MODE (XEXP (op, 0)) == CC_FPU_LTmode) | |
943 return code == LT; | |
944 if (GET_MODE (XEXP (op, 0)) == CC_FPU_LEmode) | |
945 return code == LE; | |
946 if (GET_MODE (XEXP (op, 0)) == CC_FPU_EQmode) | |
947 return code == EQ; | |
948 | |
949 return 0; | |
950 } | |
951 | |
952 int | |
953 v850_float_nz_comparison_operator (rtx op, enum machine_mode mode) | |
954 { | |
955 enum rtx_code code = GET_CODE (op); | |
956 | |
957 if (GET_RTX_CLASS (code) != RTX_COMPARE | |
958 && GET_RTX_CLASS (code) != RTX_COMM_COMPARE) | |
959 return 0; | |
960 | |
961 if (mode != GET_MODE (op) && mode != VOIDmode) | |
962 return 0; | |
963 | |
964 if ((GET_CODE (XEXP (op, 0)) != REG | |
965 || REGNO (XEXP (op, 0)) != CC_REGNUM) | |
966 || XEXP (op, 1) != const0_rtx) | |
967 return 0; | |
968 | |
969 if (GET_MODE (XEXP (op, 0)) == CC_FPU_GTmode) | |
970 return code == GT; | |
971 if (GET_MODE (XEXP (op, 0)) == CC_FPU_GEmode) | |
972 return code == GE; | |
973 if (GET_MODE (XEXP (op, 0)) == CC_FPU_NEmode) | |
974 return code == NE; | |
975 | |
976 return 0; | |
977 } | |
978 | |
979 enum machine_mode | |
980 v850_select_cc_mode (enum rtx_code cond, rtx op0, rtx op1 ATTRIBUTE_UNUSED) | 906 v850_select_cc_mode (enum rtx_code cond, rtx op0, rtx op1 ATTRIBUTE_UNUSED) |
981 { | 907 { |
982 if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT) | 908 if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT) |
983 { | 909 { |
984 switch (cond) | 910 switch (cond) |
994 case EQ: | 920 case EQ: |
995 return CC_FPU_EQmode; | 921 return CC_FPU_EQmode; |
996 case NE: | 922 case NE: |
997 return CC_FPU_NEmode; | 923 return CC_FPU_NEmode; |
998 default: | 924 default: |
999 abort (); | 925 gcc_unreachable (); |
1000 } | 926 } |
1001 } | 927 } |
1002 return CCmode; | 928 return CCmode; |
1003 } | 929 } |
1004 | 930 |
1005 enum machine_mode | 931 machine_mode |
1006 v850_gen_float_compare (enum rtx_code cond, enum machine_mode mode ATTRIBUTE_UNUSED, rtx op0, rtx op1) | 932 v850_gen_float_compare (enum rtx_code cond, machine_mode mode ATTRIBUTE_UNUSED, rtx op0, rtx op1) |
1007 { | 933 { |
1008 if (GET_MODE(op0) == DFmode) | 934 if (GET_MODE (op0) == DFmode) |
1009 { | 935 { |
1010 switch (cond) | 936 switch (cond) |
1011 { | 937 { |
1012 case LE: | 938 case LE: |
1013 emit_insn (gen_cmpdf_le_insn (op0, op1)); | 939 emit_insn (gen_cmpdf_le_insn (op0, op1)); |
1019 emit_insn (gen_cmpdf_lt_insn (op0, op1)); | 945 emit_insn (gen_cmpdf_lt_insn (op0, op1)); |
1020 break; | 946 break; |
1021 case GT: | 947 case GT: |
1022 emit_insn (gen_cmpdf_gt_insn (op0, op1)); | 948 emit_insn (gen_cmpdf_gt_insn (op0, op1)); |
1023 break; | 949 break; |
950 case NE: | |
951 /* Note: There is no NE comparison operator. So we | |
952 perform an EQ comparison and invert the branch. | |
953 See v850_float_nz_comparison for how this is done. */ | |
1024 case EQ: | 954 case EQ: |
1025 emit_insn (gen_cmpdf_eq_insn (op0, op1)); | 955 emit_insn (gen_cmpdf_eq_insn (op0, op1)); |
1026 break; | 956 break; |
1027 case NE: | |
1028 emit_insn (gen_cmpdf_ne_insn (op0, op1)); | |
1029 break; | |
1030 default: | 957 default: |
1031 abort (); | 958 gcc_unreachable (); |
1032 } | 959 } |
1033 } | 960 } |
1034 else if (GET_MODE(v850_compare_op0) == SFmode) | 961 else if (GET_MODE (v850_compare_op0) == SFmode) |
1035 { | 962 { |
1036 switch (cond) | 963 switch (cond) |
1037 { | 964 { |
1038 case LE: | 965 case LE: |
1039 emit_insn (gen_cmpsf_le_insn(op0, op1)); | 966 emit_insn (gen_cmpsf_le_insn(op0, op1)); |
1045 emit_insn (gen_cmpsf_lt_insn(op0, op1)); | 972 emit_insn (gen_cmpsf_lt_insn(op0, op1)); |
1046 break; | 973 break; |
1047 case GT: | 974 case GT: |
1048 emit_insn (gen_cmpsf_gt_insn(op0, op1)); | 975 emit_insn (gen_cmpsf_gt_insn(op0, op1)); |
1049 break; | 976 break; |
977 case NE: | |
978 /* Note: There is no NE comparison operator. So we | |
979 perform an EQ comparison and invert the branch. | |
980 See v850_float_nz_comparison for how this is done. */ | |
1050 case EQ: | 981 case EQ: |
1051 emit_insn (gen_cmpsf_eq_insn(op0, op1)); | 982 emit_insn (gen_cmpsf_eq_insn(op0, op1)); |
1052 break; | 983 break; |
1053 case NE: | |
1054 emit_insn (gen_cmpsf_ne_insn(op0, op1)); | |
1055 break; | |
1056 default: | 984 default: |
1057 abort (); | 985 gcc_unreachable (); |
1058 } | 986 } |
1059 } | 987 } |
1060 else | 988 else |
1061 { | 989 gcc_unreachable (); |
1062 abort (); | |
1063 } | |
1064 | 990 |
1065 return v850_select_cc_mode (cond, op0, op1); | 991 return v850_select_cc_mode (cond, op0, op1); |
1066 } | 992 } |
1067 | 993 |
1068 rtx | 994 rtx |
1069 v850_gen_compare (enum rtx_code cond, enum machine_mode mode, rtx op0, rtx op1) | 995 v850_gen_compare (enum rtx_code cond, machine_mode mode, rtx op0, rtx op1) |
1070 { | 996 { |
1071 if (GET_MODE_CLASS(GET_MODE (op0)) != MODE_FLOAT) | 997 if (GET_MODE_CLASS(GET_MODE (op0)) != MODE_FLOAT) |
1072 { | 998 { |
1073 emit_insn (gen_cmpsi_insn (op0, op1)); | 999 emit_insn (gen_cmpsi_insn (op0, op1)); |
1074 return gen_rtx_fmt_ee (cond, mode, gen_rtx_REG(CCmode, CC_REGNUM), const0_rtx); | 1000 return gen_rtx_fmt_ee (cond, mode, gen_rtx_REG(CCmode, CC_REGNUM), const0_rtx); |
1076 else | 1002 else |
1077 { | 1003 { |
1078 rtx cc_reg; | 1004 rtx cc_reg; |
1079 mode = v850_gen_float_compare (cond, mode, op0, op1); | 1005 mode = v850_gen_float_compare (cond, mode, op0, op1); |
1080 cc_reg = gen_rtx_REG (mode, CC_REGNUM); | 1006 cc_reg = gen_rtx_REG (mode, CC_REGNUM); |
1081 emit_insn (gen_rtx_SET(mode, cc_reg, gen_rtx_REG (mode, FCC_REGNUM))); | 1007 emit_insn (gen_rtx_SET (cc_reg, gen_rtx_REG (mode, FCC_REGNUM))); |
1082 | 1008 |
1083 return gen_rtx_fmt_ee (cond, mode, cc_reg, const0_rtx); | 1009 return gen_rtx_fmt_ee (cond, mode, cc_reg, const0_rtx); |
1084 } | 1010 } |
1085 } | 1011 } |
1086 | 1012 |
1087 /* Return maximum offset supported for a short EP memory reference of mode | 1013 /* Return maximum offset supported for a short EP memory reference of mode |
1088 MODE and signedness UNSIGNEDP. */ | 1014 MODE and signedness UNSIGNEDP. */ |
1089 | 1015 |
1090 static int | 1016 static int |
1091 ep_memory_offset (enum machine_mode mode, int unsignedp ATTRIBUTE_UNUSED) | 1017 ep_memory_offset (machine_mode mode, int unsignedp ATTRIBUTE_UNUSED) |
1092 { | 1018 { |
1093 int max_offset = 0; | 1019 int max_offset = 0; |
1094 | 1020 |
1095 switch (mode) | 1021 switch (mode) |
1096 { | 1022 { |
1097 case QImode: | 1023 case E_QImode: |
1098 if (TARGET_SMALL_SLD) | 1024 if (TARGET_SMALL_SLD) |
1099 max_offset = (1 << 4); | 1025 max_offset = (1 << 4); |
1100 else if ((TARGET_V850E || TARGET_V850E2_ALL) | 1026 else if ((TARGET_V850E_UP) |
1101 && unsignedp) | 1027 && unsignedp) |
1102 max_offset = (1 << 4); | 1028 max_offset = (1 << 4); |
1103 else | 1029 else |
1104 max_offset = (1 << 7); | 1030 max_offset = (1 << 7); |
1105 break; | 1031 break; |
1106 | 1032 |
1107 case HImode: | 1033 case E_HImode: |
1108 if (TARGET_SMALL_SLD) | 1034 if (TARGET_SMALL_SLD) |
1109 max_offset = (1 << 5); | 1035 max_offset = (1 << 5); |
1110 else if ((TARGET_V850E || TARGET_V850E2_ALL) | 1036 else if ((TARGET_V850E_UP) |
1111 && unsignedp) | 1037 && unsignedp) |
1112 max_offset = (1 << 5); | 1038 max_offset = (1 << 5); |
1113 else | 1039 else |
1114 max_offset = (1 << 8); | 1040 max_offset = (1 << 8); |
1115 break; | 1041 break; |
1116 | 1042 |
1117 case SImode: | 1043 case E_SImode: |
1118 case SFmode: | 1044 case E_SFmode: |
1119 max_offset = (1 << 8); | 1045 max_offset = (1 << 8); |
1120 break; | 1046 break; |
1121 | 1047 |
1122 default: | 1048 default: |
1123 break; | 1049 break; |
1127 } | 1053 } |
1128 | 1054 |
1129 /* Return true if OP is a valid short EP memory reference */ | 1055 /* Return true if OP is a valid short EP memory reference */ |
1130 | 1056 |
1131 int | 1057 int |
1132 ep_memory_operand (rtx op, enum machine_mode mode, int unsigned_load) | 1058 ep_memory_operand (rtx op, machine_mode mode, int unsigned_load) |
1133 { | 1059 { |
1134 rtx addr, op0, op1; | 1060 rtx addr, op0, op1; |
1135 int max_offset; | 1061 int max_offset; |
1136 int mask; | 1062 int mask; |
1137 | 1063 |
1186 | 1112 |
1187 /* Substitute memory references involving a pointer, to use the ep pointer, | 1113 /* Substitute memory references involving a pointer, to use the ep pointer, |
1188 taking care to save and preserve the ep. */ | 1114 taking care to save and preserve the ep. */ |
1189 | 1115 |
1190 static void | 1116 static void |
1191 substitute_ep_register (rtx first_insn, | 1117 substitute_ep_register (rtx_insn *first_insn, |
1192 rtx last_insn, | 1118 rtx_insn *last_insn, |
1193 int uses, | 1119 int uses, |
1194 int regno, | 1120 int regno, |
1195 rtx * p_r1, | 1121 rtx * p_r1, |
1196 rtx * p_ep) | 1122 rtx * p_ep) |
1197 { | 1123 { |
1198 rtx reg = gen_rtx_REG (Pmode, regno); | 1124 rtx reg = gen_rtx_REG (Pmode, regno); |
1199 rtx insn; | 1125 rtx_insn *insn; |
1200 | 1126 |
1201 if (!*p_r1) | 1127 if (!*p_r1) |
1202 { | 1128 { |
1203 df_set_regs_ever_live (1, true); | 1129 df_set_regs_ever_live (1, true); |
1204 *p_r1 = gen_rtx_REG (Pmode, 1); | 1130 *p_r1 = gen_rtx_REG (Pmode, 1); |
1210 Saved %d bytes (%d uses of register %s) in function %s, starting as insn %d, ending at %d\n", | 1136 Saved %d bytes (%d uses of register %s) in function %s, starting as insn %d, ending at %d\n", |
1211 2 * (uses - 3), uses, reg_names[regno], | 1137 2 * (uses - 3), uses, reg_names[regno], |
1212 IDENTIFIER_POINTER (DECL_NAME (current_function_decl)), | 1138 IDENTIFIER_POINTER (DECL_NAME (current_function_decl)), |
1213 INSN_UID (first_insn), INSN_UID (last_insn)); | 1139 INSN_UID (first_insn), INSN_UID (last_insn)); |
1214 | 1140 |
1215 if (GET_CODE (first_insn) == NOTE) | 1141 if (NOTE_P (first_insn)) |
1216 first_insn = next_nonnote_insn (first_insn); | 1142 first_insn = next_nonnote_insn (first_insn); |
1217 | 1143 |
1218 last_insn = next_nonnote_insn (last_insn); | 1144 last_insn = next_nonnote_insn (last_insn); |
1219 for (insn = first_insn; insn && insn != last_insn; insn = NEXT_INSN (insn)) | 1145 for (insn = first_insn; insn && insn != last_insn; insn = NEXT_INSN (insn)) |
1220 { | 1146 { |
1221 if (GET_CODE (insn) == INSN) | 1147 if (NONJUMP_INSN_P (insn)) |
1222 { | 1148 { |
1223 rtx pattern = single_set (insn); | 1149 rtx pattern = single_set (insn); |
1224 | 1150 |
1225 /* Replace the memory references. */ | 1151 /* Replace the memory references. */ |
1226 if (pattern) | 1152 if (pattern) |
1276 } | 1202 } |
1277 } | 1203 } |
1278 | 1204 |
1279 /* Optimize back to back cases of ep <- r1 & r1 <- ep. */ | 1205 /* Optimize back to back cases of ep <- r1 & r1 <- ep. */ |
1280 insn = prev_nonnote_insn (first_insn); | 1206 insn = prev_nonnote_insn (first_insn); |
1281 if (insn && GET_CODE (insn) == INSN | 1207 if (insn && NONJUMP_INSN_P (insn) |
1282 && GET_CODE (PATTERN (insn)) == SET | 1208 && GET_CODE (PATTERN (insn)) == SET |
1283 && SET_DEST (PATTERN (insn)) == *p_ep | 1209 && SET_DEST (PATTERN (insn)) == *p_ep |
1284 && SET_SRC (PATTERN (insn)) == *p_r1) | 1210 && SET_SRC (PATTERN (insn)) == *p_r1) |
1285 delete_insn (insn); | 1211 delete_insn (insn); |
1286 else | 1212 else |
1287 emit_insn_before (gen_rtx_SET (Pmode, *p_r1, *p_ep), first_insn); | 1213 emit_insn_before (gen_rtx_SET (*p_r1, *p_ep), first_insn); |
1288 | 1214 |
1289 emit_insn_before (gen_rtx_SET (Pmode, *p_ep, reg), first_insn); | 1215 emit_insn_before (gen_rtx_SET (*p_ep, reg), first_insn); |
1290 emit_insn_before (gen_rtx_SET (Pmode, *p_ep, *p_r1), last_insn); | 1216 emit_insn_before (gen_rtx_SET (*p_ep, *p_r1), last_insn); |
1291 } | 1217 } |
1292 | 1218 |
1293 | 1219 |
1294 /* TARGET_MACHINE_DEPENDENT_REORG. On the 850, we use it to implement | 1220 /* TARGET_MACHINE_DEPENDENT_REORG. On the 850, we use it to implement |
1295 the -mep mode to copy heavily used pointers to ep to use the implicit | 1221 the -mep mode to copy heavily used pointers to ep to use the implicit |
1299 v850_reorg (void) | 1225 v850_reorg (void) |
1300 { | 1226 { |
1301 struct | 1227 struct |
1302 { | 1228 { |
1303 int uses; | 1229 int uses; |
1304 rtx first_insn; | 1230 rtx_insn *first_insn; |
1305 rtx last_insn; | 1231 rtx_insn *last_insn; |
1306 } | 1232 } |
1307 regs[FIRST_PSEUDO_REGISTER]; | 1233 regs[FIRST_PSEUDO_REGISTER]; |
1308 | 1234 |
1309 int i; | 1235 int i; |
1310 int use_ep = FALSE; | 1236 int use_ep = FALSE; |
1311 rtx r1 = NULL_RTX; | 1237 rtx r1 = NULL_RTX; |
1312 rtx ep = NULL_RTX; | 1238 rtx ep = NULL_RTX; |
1313 rtx insn; | 1239 rtx_insn *insn; |
1314 rtx pattern; | 1240 rtx pattern; |
1315 | 1241 |
1316 /* If not ep mode, just return now. */ | 1242 /* If not ep mode, just return now. */ |
1317 if (!TARGET_EP) | 1243 if (!TARGET_EP) |
1318 return; | 1244 return; |
1319 | 1245 |
1320 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) | 1246 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) |
1321 { | 1247 { |
1322 regs[i].uses = 0; | 1248 regs[i].uses = 0; |
1323 regs[i].first_insn = NULL_RTX; | 1249 regs[i].first_insn = NULL; |
1324 regs[i].last_insn = NULL_RTX; | 1250 regs[i].last_insn = NULL; |
1325 } | 1251 } |
1326 | 1252 |
1327 for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn)) | 1253 for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn)) |
1328 { | 1254 { |
1329 switch (GET_CODE (insn)) | 1255 switch (GET_CODE (insn)) |
1352 | 1278 |
1353 use_ep = FALSE; | 1279 use_ep = FALSE; |
1354 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) | 1280 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) |
1355 { | 1281 { |
1356 regs[i].uses = 0; | 1282 regs[i].uses = 0; |
1357 regs[i].first_insn = NULL_RTX; | 1283 regs[i].first_insn = NULL; |
1358 regs[i].last_insn = NULL_RTX; | 1284 regs[i].last_insn = NULL; |
1359 } | 1285 } |
1360 break; | 1286 break; |
1361 | 1287 |
1362 case NOTE: | 1288 case NOTE: |
1363 break; | 1289 break; |
1364 | 1290 |
1365 case INSN: | 1291 case INSN: |
1366 pattern = single_set (insn); | 1292 pattern = single_set (insn); |
1367 | 1293 |
1368 /* See if there are any memory references we can shorten */ | 1294 /* See if there are any memory references we can shorten. */ |
1369 if (pattern) | 1295 if (pattern) |
1370 { | 1296 { |
1371 rtx src = SET_SRC (pattern); | 1297 rtx src = SET_SRC (pattern); |
1372 rtx dest = SET_DEST (pattern); | 1298 rtx dest = SET_DEST (pattern); |
1373 rtx mem; | 1299 rtx mem; |
1377 /* We might have (SUBREG (MEM)) here, so just get rid of the | 1303 /* We might have (SUBREG (MEM)) here, so just get rid of the |
1378 subregs to make this code simpler. */ | 1304 subregs to make this code simpler. */ |
1379 if (GET_CODE (dest) == SUBREG | 1305 if (GET_CODE (dest) == SUBREG |
1380 && (GET_CODE (SUBREG_REG (dest)) == MEM | 1306 && (GET_CODE (SUBREG_REG (dest)) == MEM |
1381 || GET_CODE (SUBREG_REG (dest)) == REG)) | 1307 || GET_CODE (SUBREG_REG (dest)) == REG)) |
1382 alter_subreg (&dest); | 1308 alter_subreg (&dest, false); |
1383 if (GET_CODE (src) == SUBREG | 1309 if (GET_CODE (src) == SUBREG |
1384 && (GET_CODE (SUBREG_REG (src)) == MEM | 1310 && (GET_CODE (SUBREG_REG (src)) == MEM |
1385 || GET_CODE (SUBREG_REG (src)) == REG)) | 1311 || GET_CODE (SUBREG_REG (src)) == REG)) |
1386 alter_subreg (&src); | 1312 alter_subreg (&src, false); |
1387 | 1313 |
1388 if (GET_CODE (dest) == MEM && GET_CODE (src) == MEM) | 1314 if (GET_CODE (dest) == MEM && GET_CODE (src) == MEM) |
1389 mem = NULL_RTX; | 1315 mem = NULL_RTX; |
1390 | 1316 |
1391 else if (GET_CODE (dest) == MEM) | 1317 else if (GET_CODE (dest) == MEM) |
1448 | 1374 |
1449 /* Loading up a register in the basic block zaps any savings | 1375 /* Loading up a register in the basic block zaps any savings |
1450 for the register */ | 1376 for the register */ |
1451 if (GET_CODE (dest) == REG) | 1377 if (GET_CODE (dest) == REG) |
1452 { | 1378 { |
1453 enum machine_mode mode = GET_MODE (dest); | |
1454 int regno; | 1379 int regno; |
1455 int endregno; | 1380 int endregno; |
1456 | 1381 |
1457 regno = REGNO (dest); | 1382 regno = REGNO (dest); |
1458 endregno = regno + HARD_REGNO_NREGS (regno, mode); | 1383 endregno = END_REGNO (dest); |
1459 | 1384 |
1460 if (!use_ep) | 1385 if (!use_ep) |
1461 { | 1386 { |
1462 /* See if we can use the pointer before this | 1387 /* See if we can use the pointer before this |
1463 modification. */ | 1388 modification. */ |
1485 /* Since we made a substitution, zap all remembered | 1410 /* Since we made a substitution, zap all remembered |
1486 registers. */ | 1411 registers. */ |
1487 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) | 1412 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) |
1488 { | 1413 { |
1489 regs[i].uses = 0; | 1414 regs[i].uses = 0; |
1490 regs[i].first_insn = NULL_RTX; | 1415 regs[i].first_insn = NULL; |
1491 regs[i].last_insn = NULL_RTX; | 1416 regs[i].last_insn = NULL; |
1492 } | 1417 } |
1493 } | 1418 } |
1494 } | 1419 } |
1495 | 1420 |
1496 for (i = regno; i < endregno; i++) | 1421 for (i = regno; i < endregno; i++) |
1497 { | 1422 { |
1498 regs[i].uses = 0; | 1423 regs[i].uses = 0; |
1499 regs[i].first_insn = NULL_RTX; | 1424 regs[i].first_insn = NULL; |
1500 regs[i].last_insn = NULL_RTX; | 1425 regs[i].last_insn = NULL; |
1501 } | 1426 } |
1502 } | 1427 } |
1503 } | 1428 } |
1504 } | 1429 } |
1505 } | 1430 } |
1524 int i; | 1449 int i; |
1525 int interrupt_handler = v850_interrupt_function_p (current_function_decl); | 1450 int interrupt_handler = v850_interrupt_function_p (current_function_decl); |
1526 int call_p = df_regs_ever_live_p (LINK_POINTER_REGNUM); | 1451 int call_p = df_regs_ever_live_p (LINK_POINTER_REGNUM); |
1527 long reg_saved = 0; | 1452 long reg_saved = 0; |
1528 | 1453 |
1529 /* Count the return pointer if we need to save it. */ | |
1530 if (crtl->profile && !call_p) | |
1531 { | |
1532 df_set_regs_ever_live (LINK_POINTER_REGNUM, true); | |
1533 call_p = 1; | |
1534 } | |
1535 | |
1536 /* Count space for the register saves. */ | 1454 /* Count space for the register saves. */ |
1537 if (interrupt_handler) | 1455 if (interrupt_handler) |
1538 { | 1456 { |
1539 for (i = 0; i <= 31; i++) | 1457 for (i = 0; i <= 31; i++) |
1540 switch (i) | 1458 switch (i) |
1623 *p_reg_saved = reg_saved; | 1541 *p_reg_saved = reg_saved; |
1624 | 1542 |
1625 return size; | 1543 return size; |
1626 } | 1544 } |
1627 | 1545 |
1546 /* Typical stack layout should looks like this after the function's prologue: | |
1547 | |
1548 | | | |
1549 -- ^ | |
1550 | | \ | | |
1551 | | arguments saved | Increasing | |
1552 | | on the stack | addresses | |
1553 PARENT arg pointer -> | | / | |
1554 -------------------------- ---- ------------------- | |
1555 | | - space for argument split between regs & stack | |
1556 -- | |
1557 CHILD | | \ <-- (return address here) | |
1558 | | other call | |
1559 | | saved registers | |
1560 | | / | |
1561 -- | |
1562 frame pointer -> | | \ ___ | |
1563 | | local | | |
1564 | | variables |f | |
1565 | | / |r | |
1566 -- |a | |
1567 | | \ |m | |
1568 | | outgoing |e | |
1569 | | arguments | | Decreasing | |
1570 (hard) frame pointer | | / | | addresses | |
1571 and stack pointer -> | | / _|_ | | |
1572 -------------------------- ---- ------------------ V */ | |
1573 | |
1628 int | 1574 int |
1629 compute_frame_size (int size, long * p_reg_saved) | 1575 compute_frame_size (int size, long * p_reg_saved) |
1630 { | 1576 { |
1631 return (size | 1577 return (size |
1632 + compute_register_save_size (p_reg_saved) | 1578 + compute_register_save_size (p_reg_saved) |
1663 | 1609 |
1664 /* Don't bother checking if we don't actually save any space. | 1610 /* Don't bother checking if we don't actually save any space. |
1665 This happens for instance if one register is saved and additional | 1611 This happens for instance if one register is saved and additional |
1666 stack space is allocated. */ | 1612 stack space is allocated. */ |
1667 return ((save_func_len + restore_func_len) < (save_normal_len + restore_normal_len)); | 1613 return ((save_func_len + restore_func_len) < (save_normal_len + restore_normal_len)); |
1614 } | |
1615 | |
1616 static void | |
1617 increment_stack (signed int amount, bool in_prologue) | |
1618 { | |
1619 rtx inc; | |
1620 | |
1621 if (amount == 0) | |
1622 return; | |
1623 | |
1624 inc = GEN_INT (amount); | |
1625 | |
1626 if (! CONST_OK_FOR_K (amount)) | |
1627 { | |
1628 rtx reg = gen_rtx_REG (Pmode, 12); | |
1629 | |
1630 inc = emit_move_insn (reg, inc); | |
1631 if (in_prologue) | |
1632 F (inc); | |
1633 inc = reg; | |
1634 } | |
1635 | |
1636 inc = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, inc)); | |
1637 if (in_prologue) | |
1638 F (inc); | |
1668 } | 1639 } |
1669 | 1640 |
1670 void | 1641 void |
1671 expand_prologue (void) | 1642 expand_prologue (void) |
1672 { | 1643 { |
1681 int interrupt_handler = v850_interrupt_function_p (current_function_decl); | 1652 int interrupt_handler = v850_interrupt_function_p (current_function_decl); |
1682 long reg_saved = 0; | 1653 long reg_saved = 0; |
1683 | 1654 |
1684 actual_fsize = compute_frame_size (size, ®_saved); | 1655 actual_fsize = compute_frame_size (size, ®_saved); |
1685 | 1656 |
1657 if (flag_stack_usage_info) | |
1658 current_function_static_stack_size = actual_fsize; | |
1659 | |
1686 /* Save/setup global registers for interrupt functions right now. */ | 1660 /* Save/setup global registers for interrupt functions right now. */ |
1687 if (interrupt_handler) | 1661 if (interrupt_handler) |
1688 { | 1662 { |
1689 if (! TARGET_DISABLE_CALLT) | 1663 if (! TARGET_DISABLE_CALLT && (TARGET_V850E_UP)) |
1690 emit_insn (gen_callt_save_interrupt ()); | 1664 emit_insn (gen_callt_save_interrupt ()); |
1691 else | 1665 else |
1692 emit_insn (gen_save_interrupt ()); | 1666 emit_insn (gen_save_interrupt ()); |
1693 | 1667 |
1694 actual_fsize -= INTERRUPT_FIXED_SAVE_SIZE; | 1668 actual_fsize -= INTERRUPT_FIXED_SAVE_SIZE; |
1695 | 1669 |
1696 if (((1L << LINK_POINTER_REGNUM) & reg_saved) != 0) | 1670 if (((1L << LINK_POINTER_REGNUM) & reg_saved) != 0) |
1697 actual_fsize -= INTERRUPT_ALL_SAVE_SIZE; | 1671 actual_fsize -= INTERRUPT_ALL_SAVE_SIZE; |
1672 | |
1673 /* Interrupt functions are not passed arguments, so no need to | |
1674 allocate space for split structure arguments. */ | |
1675 gcc_assert (crtl->args.pretend_args_size == 0); | |
1698 } | 1676 } |
1699 | 1677 |
1700 /* Identify all of the saved registers. */ | 1678 /* Identify all of the saved registers. */ |
1701 num_save = 0; | 1679 num_save = 0; |
1702 for (i = 1; i < 32; i++) | 1680 for (i = 1; i < 32; i++) |
1703 { | 1681 { |
1704 if (((1L << i) & reg_saved) != 0) | 1682 if (((1L << i) & reg_saved) != 0) |
1705 save_regs[num_save++] = gen_rtx_REG (Pmode, i); | 1683 save_regs[num_save++] = gen_rtx_REG (Pmode, i); |
1706 } | 1684 } |
1707 | 1685 |
1686 if (crtl->args.pretend_args_size) | |
1687 { | |
1688 if (num_save == 0) | |
1689 { | |
1690 increment_stack (- (actual_fsize + crtl->args.pretend_args_size), true); | |
1691 actual_fsize = 0; | |
1692 } | |
1693 else | |
1694 increment_stack (- crtl->args.pretend_args_size, true); | |
1695 } | |
1696 | |
1708 /* See if we have an insn that allocates stack space and saves the particular | 1697 /* See if we have an insn that allocates stack space and saves the particular |
1709 registers we want to. */ | 1698 registers we want to. Note that the helpers won't |
1699 allocate additional space for registers GCC saves to complete a | |
1700 "split" structure argument. */ | |
1710 save_all = NULL_RTX; | 1701 save_all = NULL_RTX; |
1711 if (TARGET_PROLOG_FUNCTION && num_save > 0) | 1702 if (TARGET_PROLOG_FUNCTION |
1703 && !crtl->args.pretend_args_size | |
1704 && num_save > 0) | |
1712 { | 1705 { |
1713 if (use_prolog_function (num_save, actual_fsize)) | 1706 if (use_prolog_function (num_save, actual_fsize)) |
1714 { | 1707 { |
1715 int alloc_stack = 4 * num_save; | 1708 int alloc_stack = 4 * num_save; |
1716 int offset = 0; | 1709 int offset = 0; |
1719 (VOIDmode, | 1712 (VOIDmode, |
1720 rtvec_alloc (num_save + 1 | 1713 rtvec_alloc (num_save + 1 |
1721 + (TARGET_DISABLE_CALLT ? (TARGET_LONG_CALLS ? 2 : 1) : 0))); | 1714 + (TARGET_DISABLE_CALLT ? (TARGET_LONG_CALLS ? 2 : 1) : 0))); |
1722 | 1715 |
1723 XVECEXP (save_all, 0, 0) | 1716 XVECEXP (save_all, 0, 0) |
1724 = gen_rtx_SET (VOIDmode, | 1717 = gen_rtx_SET (stack_pointer_rtx, |
1725 stack_pointer_rtx, | |
1726 gen_rtx_PLUS (Pmode, | 1718 gen_rtx_PLUS (Pmode, |
1727 stack_pointer_rtx, | 1719 stack_pointer_rtx, |
1728 GEN_INT(-alloc_stack))); | 1720 GEN_INT(-alloc_stack))); |
1729 for (i = 0; i < num_save; i++) | 1721 for (i = 0; i < num_save; i++) |
1730 { | 1722 { |
1731 offset -= 4; | 1723 offset -= 4; |
1732 XVECEXP (save_all, 0, i+1) | 1724 XVECEXP (save_all, 0, i+1) |
1733 = gen_rtx_SET (VOIDmode, | 1725 = gen_rtx_SET (gen_rtx_MEM (Pmode, |
1734 gen_rtx_MEM (Pmode, | |
1735 gen_rtx_PLUS (Pmode, | 1726 gen_rtx_PLUS (Pmode, |
1736 stack_pointer_rtx, | 1727 stack_pointer_rtx, |
1737 GEN_INT(offset))), | 1728 GEN_INT(offset))), |
1738 save_regs[i]); | 1729 save_regs[i]); |
1739 } | 1730 } |
1746 if (TARGET_LONG_CALLS) | 1737 if (TARGET_LONG_CALLS) |
1747 XVECEXP (save_all, 0, num_save + 2) | 1738 XVECEXP (save_all, 0, num_save + 2) |
1748 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 11)); | 1739 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 11)); |
1749 } | 1740 } |
1750 | 1741 |
1751 code = recog (save_all, NULL_RTX, NULL); | 1742 v850_all_frame_related (save_all); |
1743 | |
1744 code = recog (save_all, NULL, NULL); | |
1752 if (code >= 0) | 1745 if (code >= 0) |
1753 { | 1746 { |
1754 rtx insn = emit_insn (save_all); | 1747 rtx insn = emit_insn (save_all); |
1755 INSN_CODE (insn) = code; | 1748 INSN_CODE (insn) = code; |
1756 actual_fsize -= alloc_stack; | 1749 actual_fsize -= alloc_stack; |
1766 if (!save_all) | 1759 if (!save_all) |
1767 { | 1760 { |
1768 /* Special case interrupt functions that save all registers for a call. */ | 1761 /* Special case interrupt functions that save all registers for a call. */ |
1769 if (interrupt_handler && ((1L << LINK_POINTER_REGNUM) & reg_saved) != 0) | 1762 if (interrupt_handler && ((1L << LINK_POINTER_REGNUM) & reg_saved) != 0) |
1770 { | 1763 { |
1771 if (! TARGET_DISABLE_CALLT) | 1764 if (! TARGET_DISABLE_CALLT && (TARGET_V850E_UP)) |
1772 emit_insn (gen_callt_save_all_interrupt ()); | 1765 emit_insn (gen_callt_save_all_interrupt ()); |
1773 else | 1766 else |
1774 emit_insn (gen_save_all_interrupt ()); | 1767 emit_insn (gen_save_all_interrupt ()); |
1775 } | 1768 } |
1776 else | 1769 else |
1786 | 1779 |
1787 /* Save registers at the beginning of the stack frame. */ | 1780 /* Save registers at the beginning of the stack frame. */ |
1788 offset = init_stack_alloc - 4; | 1781 offset = init_stack_alloc - 4; |
1789 | 1782 |
1790 if (init_stack_alloc) | 1783 if (init_stack_alloc) |
1791 emit_insn (gen_addsi3 (stack_pointer_rtx, | 1784 increment_stack (- (signed) init_stack_alloc, true); |
1792 stack_pointer_rtx, | |
1793 GEN_INT (- (signed) init_stack_alloc))); | |
1794 | 1785 |
1795 /* Save the return pointer first. */ | 1786 /* Save the return pointer first. */ |
1796 if (num_save > 0 && REGNO (save_regs[num_save-1]) == LINK_POINTER_REGNUM) | 1787 if (num_save > 0 && REGNO (save_regs[num_save-1]) == LINK_POINTER_REGNUM) |
1797 { | 1788 { |
1798 emit_move_insn (gen_rtx_MEM (SImode, | 1789 F (emit_move_insn (gen_rtx_MEM (SImode, |
1799 plus_constant (stack_pointer_rtx, | 1790 plus_constant (Pmode, |
1800 offset)), | 1791 stack_pointer_rtx, |
1801 save_regs[--num_save]); | 1792 offset)), |
1793 save_regs[--num_save])); | |
1802 offset -= 4; | 1794 offset -= 4; |
1803 } | 1795 } |
1804 | 1796 |
1805 for (i = 0; i < num_save; i++) | 1797 for (i = 0; i < num_save; i++) |
1806 { | 1798 { |
1807 emit_move_insn (gen_rtx_MEM (SImode, | 1799 F (emit_move_insn (gen_rtx_MEM (SImode, |
1808 plus_constant (stack_pointer_rtx, | 1800 plus_constant (Pmode, |
1809 offset)), | 1801 stack_pointer_rtx, |
1810 save_regs[i]); | 1802 offset)), |
1803 save_regs[i])); | |
1811 offset -= 4; | 1804 offset -= 4; |
1812 } | 1805 } |
1813 } | 1806 } |
1814 } | 1807 } |
1815 | 1808 |
1816 /* Allocate the rest of the stack that was not allocated above (either it is | 1809 /* Allocate the rest of the stack that was not allocated above (either it is |
1817 > 32K or we just called a function to save the registers and needed more | 1810 > 32K or we just called a function to save the registers and needed more |
1818 stack. */ | 1811 stack. */ |
1819 if (actual_fsize > init_stack_alloc) | 1812 if (actual_fsize > init_stack_alloc) |
1820 { | 1813 increment_stack (init_stack_alloc - actual_fsize, true); |
1821 int diff = actual_fsize - init_stack_alloc; | |
1822 if (CONST_OK_FOR_K (-diff)) | |
1823 emit_insn (gen_addsi3 (stack_pointer_rtx, | |
1824 stack_pointer_rtx, | |
1825 GEN_INT (-diff))); | |
1826 else | |
1827 { | |
1828 rtx reg = gen_rtx_REG (Pmode, 12); | |
1829 emit_move_insn (reg, GEN_INT (-diff)); | |
1830 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg)); | |
1831 } | |
1832 } | |
1833 | 1814 |
1834 /* If we need a frame pointer, set it up now. */ | 1815 /* If we need a frame pointer, set it up now. */ |
1835 if (frame_pointer_needed) | 1816 if (frame_pointer_needed) |
1836 emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx); | 1817 F (emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx)); |
1837 } | 1818 } |
1838 | 1819 |
1839 | 1820 |
1840 void | 1821 void |
1841 expand_epilogue (void) | 1822 expand_epilogue (void) |
1874 want to. */ | 1855 want to. */ |
1875 restore_all = NULL_RTX; | 1856 restore_all = NULL_RTX; |
1876 | 1857 |
1877 if (TARGET_PROLOG_FUNCTION | 1858 if (TARGET_PROLOG_FUNCTION |
1878 && num_restore > 0 | 1859 && num_restore > 0 |
1860 && !crtl->args.pretend_args_size | |
1879 && !interrupt_handler) | 1861 && !interrupt_handler) |
1880 { | 1862 { |
1881 int alloc_stack = (4 * num_restore); | 1863 int alloc_stack = (4 * num_restore); |
1882 | 1864 |
1883 /* Don't bother checking if we don't actually save any space. */ | 1865 /* Don't bother checking if we don't actually save any space. */ |
1884 if (use_prolog_function (num_restore, actual_fsize)) | 1866 if (use_prolog_function (num_restore, actual_fsize)) |
1885 { | 1867 { |
1886 int offset; | 1868 int offset; |
1887 restore_all = gen_rtx_PARALLEL (VOIDmode, | 1869 restore_all = gen_rtx_PARALLEL (VOIDmode, |
1888 rtvec_alloc (num_restore + 2)); | 1870 rtvec_alloc (num_restore + 2)); |
1889 XVECEXP (restore_all, 0, 0) = gen_rtx_RETURN (VOIDmode); | 1871 XVECEXP (restore_all, 0, 0) = ret_rtx; |
1890 XVECEXP (restore_all, 0, 1) | 1872 XVECEXP (restore_all, 0, 1) |
1891 = gen_rtx_SET (VOIDmode, stack_pointer_rtx, | 1873 = gen_rtx_SET (stack_pointer_rtx, |
1892 gen_rtx_PLUS (Pmode, | 1874 gen_rtx_PLUS (Pmode, |
1893 stack_pointer_rtx, | 1875 stack_pointer_rtx, |
1894 GEN_INT (alloc_stack))); | 1876 GEN_INT (alloc_stack))); |
1895 | 1877 |
1896 offset = alloc_stack - 4; | 1878 offset = alloc_stack - 4; |
1897 for (i = 0; i < num_restore; i++) | 1879 for (i = 0; i < num_restore; i++) |
1898 { | 1880 { |
1899 XVECEXP (restore_all, 0, i+2) | 1881 XVECEXP (restore_all, 0, i+2) |
1900 = gen_rtx_SET (VOIDmode, | 1882 = gen_rtx_SET (restore_regs[i], |
1901 restore_regs[i], | |
1902 gen_rtx_MEM (Pmode, | 1883 gen_rtx_MEM (Pmode, |
1903 gen_rtx_PLUS (Pmode, | 1884 gen_rtx_PLUS (Pmode, |
1904 stack_pointer_rtx, | 1885 stack_pointer_rtx, |
1905 GEN_INT(offset)))); | 1886 GEN_INT(offset)))); |
1906 offset -= 4; | 1887 offset -= 4; |
1907 } | 1888 } |
1908 | 1889 |
1909 code = recog (restore_all, NULL_RTX, NULL); | 1890 code = recog (restore_all, NULL, NULL); |
1910 | 1891 |
1911 if (code >= 0) | 1892 if (code >= 0) |
1912 { | 1893 { |
1913 rtx insn; | 1894 rtx insn; |
1914 | 1895 |
1915 actual_fsize -= alloc_stack; | 1896 actual_fsize -= alloc_stack; |
1916 if (actual_fsize) | 1897 increment_stack (actual_fsize, false); |
1917 { | |
1918 if (CONST_OK_FOR_K (actual_fsize)) | |
1919 emit_insn (gen_addsi3 (stack_pointer_rtx, | |
1920 stack_pointer_rtx, | |
1921 GEN_INT (actual_fsize))); | |
1922 else | |
1923 { | |
1924 rtx reg = gen_rtx_REG (Pmode, 12); | |
1925 emit_move_insn (reg, GEN_INT (actual_fsize)); | |
1926 emit_insn (gen_addsi3 (stack_pointer_rtx, | |
1927 stack_pointer_rtx, | |
1928 reg)); | |
1929 } | |
1930 } | |
1931 | 1898 |
1932 insn = emit_jump_insn (restore_all); | 1899 insn = emit_jump_insn (restore_all); |
1933 INSN_CODE (insn) = code; | 1900 INSN_CODE (insn) = code; |
1934 | |
1935 } | 1901 } |
1936 else | 1902 else |
1937 restore_all = NULL_RTX; | 1903 restore_all = NULL_RTX; |
1938 } | 1904 } |
1939 } | 1905 } |
1952 else | 1918 else |
1953 init_stack_free = (signed) actual_fsize; | 1919 init_stack_free = (signed) actual_fsize; |
1954 | 1920 |
1955 /* Deallocate the rest of the stack if it is > 32K. */ | 1921 /* Deallocate the rest of the stack if it is > 32K. */ |
1956 if ((unsigned int) actual_fsize > init_stack_free) | 1922 if ((unsigned int) actual_fsize > init_stack_free) |
1957 { | 1923 increment_stack (actual_fsize - init_stack_free, false); |
1958 int diff; | |
1959 | |
1960 diff = actual_fsize - init_stack_free; | |
1961 | |
1962 if (CONST_OK_FOR_K (diff)) | |
1963 emit_insn (gen_addsi3 (stack_pointer_rtx, | |
1964 stack_pointer_rtx, | |
1965 GEN_INT (diff))); | |
1966 else | |
1967 { | |
1968 rtx reg = gen_rtx_REG (Pmode, 12); | |
1969 emit_move_insn (reg, GEN_INT (diff)); | |
1970 emit_insn (gen_addsi3 (stack_pointer_rtx, | |
1971 stack_pointer_rtx, | |
1972 reg)); | |
1973 } | |
1974 } | |
1975 | 1924 |
1976 /* Special case interrupt functions that save all registers | 1925 /* Special case interrupt functions that save all registers |
1977 for a call. */ | 1926 for a call. */ |
1978 if (interrupt_handler && ((1L << LINK_POINTER_REGNUM) & reg_saved) != 0) | 1927 if (interrupt_handler && ((1L << LINK_POINTER_REGNUM) & reg_saved) != 0) |
1979 { | 1928 { |
1991 if (num_restore > 0 | 1940 if (num_restore > 0 |
1992 && REGNO (restore_regs [num_restore - 1]) == LINK_POINTER_REGNUM) | 1941 && REGNO (restore_regs [num_restore - 1]) == LINK_POINTER_REGNUM) |
1993 { | 1942 { |
1994 emit_move_insn (restore_regs[--num_restore], | 1943 emit_move_insn (restore_regs[--num_restore], |
1995 gen_rtx_MEM (SImode, | 1944 gen_rtx_MEM (SImode, |
1996 plus_constant (stack_pointer_rtx, | 1945 plus_constant (Pmode, |
1946 stack_pointer_rtx, | |
1997 offset))); | 1947 offset))); |
1998 offset -= 4; | 1948 offset -= 4; |
1999 } | 1949 } |
2000 | 1950 |
2001 for (i = 0; i < num_restore; i++) | 1951 for (i = 0; i < num_restore; i++) |
2002 { | 1952 { |
2003 emit_move_insn (restore_regs[i], | 1953 emit_move_insn (restore_regs[i], |
2004 gen_rtx_MEM (SImode, | 1954 gen_rtx_MEM (SImode, |
2005 plus_constant (stack_pointer_rtx, | 1955 plus_constant (Pmode, |
1956 stack_pointer_rtx, | |
2006 offset))); | 1957 offset))); |
2007 | 1958 |
2008 emit_use (restore_regs[i]); | 1959 emit_use (restore_regs[i]); |
2009 offset -= 4; | 1960 offset -= 4; |
2010 } | 1961 } |
2011 | 1962 |
2012 /* Cut back the remainder of the stack. */ | 1963 /* Cut back the remainder of the stack. */ |
2013 if (init_stack_free) | 1964 increment_stack (init_stack_free + crtl->args.pretend_args_size, |
2014 emit_insn (gen_addsi3 (stack_pointer_rtx, | 1965 false); |
2015 stack_pointer_rtx, | |
2016 GEN_INT (init_stack_free))); | |
2017 } | 1966 } |
2018 | 1967 |
2019 /* And return or use reti for interrupt handlers. */ | 1968 /* And return or use reti for interrupt handlers. */ |
2020 if (interrupt_handler) | 1969 if (interrupt_handler) |
2021 { | 1970 { |
2022 if (! TARGET_DISABLE_CALLT) | 1971 if (! TARGET_DISABLE_CALLT && (TARGET_V850E_UP)) |
2023 emit_insn (gen_callt_return_interrupt ()); | 1972 emit_insn (gen_callt_return_interrupt ()); |
2024 else | 1973 else |
2025 emit_jump_insn (gen_return_interrupt ()); | 1974 emit_jump_insn (gen_return_interrupt ()); |
2026 } | 1975 } |
2027 else if (actual_fsize) | 1976 else if (actual_fsize) |
2034 v850_interrupt_p = FALSE; | 1983 v850_interrupt_p = FALSE; |
2035 } | 1984 } |
2036 | 1985 |
2037 /* Update the condition code from the insn. */ | 1986 /* Update the condition code from the insn. */ |
2038 void | 1987 void |
2039 notice_update_cc (rtx body, rtx insn) | 1988 notice_update_cc (rtx body, rtx_insn *insn) |
2040 { | 1989 { |
2041 switch (get_attr_cc (insn)) | 1990 switch (get_attr_cc (insn)) |
2042 { | 1991 { |
2043 case CC_NONE: | 1992 case CC_NONE: |
2044 /* Insn does not affect CC at all. */ | 1993 /* Insn does not affect CC at all. */ |
2171 "data area attributes cannot be specified for " | 2120 "data area attributes cannot be specified for " |
2172 "local variables"); | 2121 "local variables"); |
2173 *no_add_attrs = true; | 2122 *no_add_attrs = true; |
2174 } | 2123 } |
2175 | 2124 |
2176 /* Drop through. */ | 2125 /* FALLTHRU */ |
2177 | 2126 |
2178 case FUNCTION_DECL: | 2127 case FUNCTION_DECL: |
2179 area = v850_get_data_area (decl); | 2128 area = v850_get_data_area (decl); |
2180 if (area != DATA_AREA_NORMAL && data_area != area) | 2129 if (area != DATA_AREA_NORMAL && data_area != area) |
2181 { | 2130 { |
2235 /* Map explicit sections into the appropriate attribute */ | 2184 /* Map explicit sections into the appropriate attribute */ |
2236 if (v850_get_data_area (decl) == DATA_AREA_NORMAL) | 2185 if (v850_get_data_area (decl) == DATA_AREA_NORMAL) |
2237 { | 2186 { |
2238 if (DECL_SECTION_NAME (decl)) | 2187 if (DECL_SECTION_NAME (decl)) |
2239 { | 2188 { |
2240 const char *name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl)); | 2189 const char *name = DECL_SECTION_NAME (decl); |
2241 | 2190 |
2242 if (streq (name, ".zdata") || streq (name, ".zbss")) | 2191 if (streq (name, ".zdata") || streq (name, ".zbss")) |
2243 v850_set_data_area (decl, DATA_AREA_ZDA); | 2192 v850_set_data_area (decl, DATA_AREA_ZDA); |
2244 | 2193 |
2245 else if (streq (name, ".sdata") || streq (name, ".sbss")) | 2194 else if (streq (name, ".sdata") || streq (name, ".sbss")) |
2254 { | 2203 { |
2255 int size = int_size_in_bytes (TREE_TYPE (decl)); | 2204 int size = int_size_in_bytes (TREE_TYPE (decl)); |
2256 if (size <= 0) | 2205 if (size <= 0) |
2257 ; | 2206 ; |
2258 | 2207 |
2259 else if (size <= small_memory [(int) SMALL_MEMORY_TDA].max) | 2208 else if (size <= small_memory_max [(int) SMALL_MEMORY_TDA]) |
2260 v850_set_data_area (decl, DATA_AREA_TDA); | 2209 v850_set_data_area (decl, DATA_AREA_TDA); |
2261 | 2210 |
2262 else if (size <= small_memory [(int) SMALL_MEMORY_SDA].max) | 2211 else if (size <= small_memory_max [(int) SMALL_MEMORY_SDA]) |
2263 v850_set_data_area (decl, DATA_AREA_SDA); | 2212 v850_set_data_area (decl, DATA_AREA_SDA); |
2264 | 2213 |
2265 else if (size <= small_memory [(int) SMALL_MEMORY_ZDA].max) | 2214 else if (size <= small_memory_max [(int) SMALL_MEMORY_ZDA]) |
2266 v850_set_data_area (decl, DATA_AREA_ZDA); | 2215 v850_set_data_area (decl, DATA_AREA_ZDA); |
2267 } | 2216 } |
2268 | 2217 |
2269 if (v850_get_data_area (decl) == DATA_AREA_NORMAL) | 2218 if (v850_get_data_area (decl) == DATA_AREA_NORMAL) |
2270 return; | 2219 return; |
2487 if (first == last) | 2436 if (first == last) |
2488 sprintf (name, "__save_%s", reg_names [first]); | 2437 sprintf (name, "__save_%s", reg_names [first]); |
2489 else | 2438 else |
2490 sprintf (name, "__save_%s_%s", reg_names [first], reg_names [last]); | 2439 sprintf (name, "__save_%s_%s", reg_names [first], reg_names [last]); |
2491 | 2440 |
2492 sprintf (buff, "movhi hi(%s), r0, r11\n\tmovea lo(%s), r11, r11\n\tjarl .+4, r10\n\tadd 4, r10\n\tjmp r11", | 2441 if (TARGET_V850E3V5_UP) |
2493 name, name); | 2442 sprintf (buff, "mov hilo(%s), r11\n\tjarl [r11], r10", name); |
2443 else | |
2444 sprintf (buff, "movhi hi(%s), r0, r11\n\tmovea lo(%s), r11, r11\n\tjarl .+4, r10\n\tadd 4, r10\n\tjmp r11", | |
2445 name, name); | |
2494 } | 2446 } |
2495 else | 2447 else |
2496 { | 2448 { |
2497 if (first == last) | 2449 if (first == last) |
2498 sprintf (buff, "jarl __save_%s, r10", reg_names [first]); | 2450 sprintf (buff, "jarl __save_%s, r10", reg_names [first]); |
2501 reg_names [last]); | 2453 reg_names [last]); |
2502 } | 2454 } |
2503 | 2455 |
2504 return buff; | 2456 return buff; |
2505 } | 2457 } |
2506 | |
2507 extern tree last_assemble_variable_decl; | |
2508 extern int size_directive_output; | |
2509 | 2458 |
2510 /* A version of asm_output_aligned_bss() that copes with the special | 2459 /* A version of asm_output_aligned_bss() that copes with the special |
2511 data areas of the v850. */ | 2460 data areas of the v850. */ |
2512 void | 2461 void |
2513 v850_output_aligned_bss (FILE * file, | 2462 v850_output_aligned_bss (FILE * file, |
2526 switch_to_section (sbss_section); | 2475 switch_to_section (sbss_section); |
2527 break; | 2476 break; |
2528 | 2477 |
2529 case DATA_AREA_TDA: | 2478 case DATA_AREA_TDA: |
2530 switch_to_section (tdata_section); | 2479 switch_to_section (tdata_section); |
2480 break; | |
2531 | 2481 |
2532 default: | 2482 default: |
2533 switch_to_section (bss_section); | 2483 switch_to_section (bss_section); |
2534 break; | 2484 break; |
2535 } | 2485 } |
2614 if this has not been done before. */ | 2564 if this has not been done before. */ |
2615 | 2565 |
2616 if (GHS_default_section_names [(int) GHS_SECTION_KIND_SDATA] == NULL) | 2566 if (GHS_default_section_names [(int) GHS_SECTION_KIND_SDATA] == NULL) |
2617 { | 2567 { |
2618 GHS_default_section_names [(int) GHS_SECTION_KIND_SDATA] | 2568 GHS_default_section_names [(int) GHS_SECTION_KIND_SDATA] |
2619 = build_string (sizeof (".sdata")-1, ".sdata"); | 2569 = ".sdata"; |
2620 | 2570 |
2621 GHS_default_section_names [(int) GHS_SECTION_KIND_ROSDATA] | 2571 GHS_default_section_names [(int) GHS_SECTION_KIND_ROSDATA] |
2622 = build_string (sizeof (".rosdata")-1, ".rosdata"); | 2572 = ".rosdata"; |
2623 | 2573 |
2624 GHS_default_section_names [(int) GHS_SECTION_KIND_TDATA] | 2574 GHS_default_section_names [(int) GHS_SECTION_KIND_TDATA] |
2625 = build_string (sizeof (".tdata")-1, ".tdata"); | 2575 = ".tdata"; |
2626 | 2576 |
2627 GHS_default_section_names [(int) GHS_SECTION_KIND_ZDATA] | 2577 GHS_default_section_names [(int) GHS_SECTION_KIND_ZDATA] |
2628 = build_string (sizeof (".zdata")-1, ".zdata"); | 2578 = ".zdata"; |
2629 | 2579 |
2630 GHS_default_section_names [(int) GHS_SECTION_KIND_ROZDATA] | 2580 GHS_default_section_names [(int) GHS_SECTION_KIND_ROZDATA] |
2631 = build_string (sizeof (".rozdata")-1, ".rozdata"); | 2581 = ".rozdata"; |
2632 } | 2582 } |
2633 | 2583 |
2634 if (current_function_decl == NULL_TREE | 2584 if (current_function_decl == NULL_TREE |
2635 && (TREE_CODE (decl) == VAR_DECL | 2585 && (TREE_CODE (decl) == VAR_DECL |
2636 || TREE_CODE (decl) == CONST_DECL | 2586 || TREE_CODE (decl) == CONST_DECL |
2637 || TREE_CODE (decl) == FUNCTION_DECL) | 2587 || TREE_CODE (decl) == FUNCTION_DECL) |
2638 && (!DECL_EXTERNAL (decl) || DECL_INITIAL (decl)) | 2588 && (!DECL_EXTERNAL (decl) || DECL_INITIAL (decl)) |
2639 && !DECL_SECTION_NAME (decl)) | 2589 && !DECL_SECTION_NAME (decl)) |
2640 { | 2590 { |
2641 enum GHS_section_kind kind = GHS_SECTION_KIND_DEFAULT; | 2591 enum GHS_section_kind kind = GHS_SECTION_KIND_DEFAULT; |
2642 tree chosen_section; | 2592 const char * chosen_section; |
2643 | 2593 |
2644 if (TREE_CODE (decl) == FUNCTION_DECL) | 2594 if (TREE_CODE (decl) == FUNCTION_DECL) |
2645 kind = GHS_SECTION_KIND_TEXT; | 2595 kind = GHS_SECTION_KIND_TEXT; |
2646 else | 2596 else |
2647 { | 2597 { |
2689 if (chosen_section) | 2639 if (chosen_section) |
2690 { | 2640 { |
2691 /* Only set the section name if specified by a pragma, because | 2641 /* Only set the section name if specified by a pragma, because |
2692 otherwise it will force those variables to get allocated storage | 2642 otherwise it will force those variables to get allocated storage |
2693 in this module, rather than by the linker. */ | 2643 in this module, rather than by the linker. */ |
2694 DECL_SECTION_NAME (decl) = chosen_section; | 2644 set_decl_section_name (decl, chosen_section); |
2695 } | 2645 } |
2696 } | 2646 } |
2697 } | 2647 } |
2698 | 2648 |
2699 /* Construct a DISPOSE instruction that is the equivalent of | 2649 /* Construct a DISPOSE instruction that is the equivalent of |
3018 /* Worker function for TARGET_FUNCTION_VALUE_REGNO_P. */ | 2968 /* Worker function for TARGET_FUNCTION_VALUE_REGNO_P. */ |
3019 | 2969 |
3020 static bool | 2970 static bool |
3021 v850_function_value_regno_p (const unsigned int regno) | 2971 v850_function_value_regno_p (const unsigned int regno) |
3022 { | 2972 { |
3023 return (regno == 10); | 2973 return (regno == RV_REGNUM); |
3024 } | 2974 } |
3025 | 2975 |
3026 /* Worker function for TARGET_RETURN_IN_MEMORY. */ | 2976 /* Worker function for TARGET_RETURN_IN_MEMORY. */ |
3027 | 2977 |
3028 static bool | 2978 static bool |
3029 v850_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) | 2979 v850_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) |
3030 { | 2980 { |
3031 /* Return values > 8 bytes in length in memory. */ | 2981 /* Return values > 8 bytes in length in memory. */ |
3032 return int_size_in_bytes (type) > 8 || TYPE_MODE (type) == BLKmode; | 2982 return int_size_in_bytes (type) > 8 |
2983 || TYPE_MODE (type) == BLKmode | |
2984 /* With the rh850 ABI return all aggregates in memory. */ | |
2985 || ((! TARGET_GCC_ABI) && AGGREGATE_TYPE_P (type)) | |
2986 ; | |
3033 } | 2987 } |
3034 | 2988 |
3035 /* Worker function for TARGET_FUNCTION_VALUE. */ | 2989 /* Worker function for TARGET_FUNCTION_VALUE. */ |
3036 | 2990 |
3037 static rtx | 2991 static rtx |
3038 v850_function_value (const_tree valtype, | 2992 v850_function_value (const_tree valtype, |
3039 const_tree fn_decl_or_type ATTRIBUTE_UNUSED, | 2993 const_tree fn_decl_or_type ATTRIBUTE_UNUSED, |
3040 bool outgoing ATTRIBUTE_UNUSED) | 2994 bool outgoing ATTRIBUTE_UNUSED) |
3041 { | 2995 { |
3042 return gen_rtx_REG (TYPE_MODE (valtype), 10); | 2996 return gen_rtx_REG (TYPE_MODE (valtype), RV_REGNUM); |
2997 } | |
2998 | |
2999 /* Implement TARGET_LIBCALL_VALUE. */ | |
3000 | |
3001 static rtx | |
3002 v850_libcall_value (machine_mode mode, | |
3003 const_rtx func ATTRIBUTE_UNUSED) | |
3004 { | |
3005 return gen_rtx_REG (mode, RV_REGNUM); | |
3043 } | 3006 } |
3044 | 3007 |
3045 | 3008 |
3046 /* Worker function for TARGET_SETUP_INCOMING_VARARGS. */ | |
3047 | |
3048 static void | |
3049 v850_setup_incoming_varargs (CUMULATIVE_ARGS *ca, | |
3050 enum machine_mode mode ATTRIBUTE_UNUSED, | |
3051 tree type ATTRIBUTE_UNUSED, | |
3052 int *pretend_arg_size ATTRIBUTE_UNUSED, | |
3053 int second_time ATTRIBUTE_UNUSED) | |
3054 { | |
3055 ca->anonymous_args = (!TARGET_GHS ? 1 : 0); | |
3056 } | |
3057 | |
3058 /* Worker function for TARGET_CAN_ELIMINATE. */ | 3009 /* Worker function for TARGET_CAN_ELIMINATE. */ |
3059 | 3010 |
3060 static bool | 3011 static bool |
3061 v850_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to) | 3012 v850_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to) |
3062 { | 3013 { |
3109 } | 3060 } |
3110 | 3061 |
3111 static int | 3062 static int |
3112 v850_issue_rate (void) | 3063 v850_issue_rate (void) |
3113 { | 3064 { |
3114 return (TARGET_V850E2_ALL? 2 : 1); | 3065 return (TARGET_V850E2_UP ? 2 : 1); |
3066 } | |
3067 | |
3068 /* Implement TARGET_LEGITIMATE_CONSTANT_P. */ | |
3069 | |
3070 static bool | |
3071 v850_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x) | |
3072 { | |
3073 return (GET_CODE (x) == CONST_DOUBLE | |
3074 || !(GET_CODE (x) == CONST | |
3075 && GET_CODE (XEXP (x, 0)) == PLUS | |
3076 && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF | |
3077 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT | |
3078 && !CONST_OK_FOR_K (INTVAL (XEXP (XEXP (x, 0), 1))))); | |
3079 } | |
3080 | |
3081 /* Helper function for `v850_legitimate_address_p'. */ | |
3082 | |
3083 static bool | |
3084 v850_reg_ok_for_base_p (const_rtx reg, bool strict_p) | |
3085 { | |
3086 if (strict_p) | |
3087 { | |
3088 return REGNO_OK_FOR_BASE_P (REGNO (reg)); | |
3089 } else { | |
3090 return true; | |
3091 } | |
3092 } | |
3093 | |
3094 /* Accept either REG or SUBREG where a register is valid. */ | |
3095 | |
3096 static bool | |
3097 v850_rtx_ok_for_base_p (const_rtx x, bool strict_p) | |
3098 { | |
3099 return ((REG_P (x) && v850_reg_ok_for_base_p (x, strict_p)) | |
3100 || (SUBREG_P (x) && REG_P (SUBREG_REG (x)) | |
3101 && v850_reg_ok_for_base_p (SUBREG_REG (x), strict_p))); | |
3102 } | |
3103 | |
3104 /* Implement TARGET_LEGITIMATE_ADDRESS_P. */ | |
3105 | |
3106 static bool | |
3107 v850_legitimate_address_p (machine_mode mode, rtx x, bool strict_p, | |
3108 addr_space_t as ATTRIBUTE_UNUSED) | |
3109 { | |
3110 gcc_assert (ADDR_SPACE_GENERIC_P (as)); | |
3111 | |
3112 if (v850_rtx_ok_for_base_p (x, strict_p)) | |
3113 return true; | |
3114 if (CONSTANT_ADDRESS_P (x) | |
3115 && (mode == QImode || INTVAL (x) % 2 == 0) | |
3116 && (GET_MODE_SIZE (mode) <= 4 || INTVAL (x) % 4 == 0)) | |
3117 return true; | |
3118 if (GET_CODE (x) == LO_SUM | |
3119 && REG_P (XEXP (x, 0)) | |
3120 && v850_reg_ok_for_base_p (XEXP (x, 0), strict_p) | |
3121 && CONSTANT_P (XEXP (x, 1)) | |
3122 && (!CONST_INT_P (XEXP (x, 1)) | |
3123 || ((mode == QImode || INTVAL (XEXP (x, 1)) % 2 == 0) | |
3124 && constraint_satisfied_p (XEXP (x, 1), CONSTRAINT_K))) | |
3125 && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (word_mode)) | |
3126 return true; | |
3127 if (special_symbolref_operand (x, mode) | |
3128 && (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (word_mode))) | |
3129 return true; | |
3130 if (GET_CODE (x) == PLUS | |
3131 && v850_rtx_ok_for_base_p (XEXP (x, 0), strict_p) | |
3132 && constraint_satisfied_p (XEXP (x,1), CONSTRAINT_K) | |
3133 && ((mode == QImode || INTVAL (XEXP (x, 1)) % 2 == 0) | |
3134 && CONST_OK_FOR_K (INTVAL (XEXP (x, 1)) | |
3135 + (GET_MODE_NUNITS (mode) * UNITS_PER_WORD)))) | |
3136 return true; | |
3137 | |
3138 return false; | |
3139 } | |
3140 | |
3141 static int | |
3142 v850_memory_move_cost (machine_mode mode, | |
3143 reg_class_t reg_class ATTRIBUTE_UNUSED, | |
3144 bool in) | |
3145 { | |
3146 switch (GET_MODE_SIZE (mode)) | |
3147 { | |
3148 case 0: | |
3149 return in ? 24 : 8; | |
3150 case 1: | |
3151 case 2: | |
3152 case 3: | |
3153 case 4: | |
3154 return in ? 6 : 2; | |
3155 default: | |
3156 return (GET_MODE_SIZE (mode) / 2) * (in ? 3 : 1); | |
3157 } | |
3158 } | |
3159 | |
3160 int | |
3161 v850_adjust_insn_length (rtx_insn *insn, int length) | |
3162 { | |
3163 if (TARGET_V850E3V5_UP) | |
3164 { | |
3165 if (CALL_P (insn)) | |
3166 { | |
3167 if (TARGET_LONG_CALLS) | |
3168 { | |
3169 /* call_internal_long, call_value_internal_long. */ | |
3170 if (length == 8) | |
3171 length = 4; | |
3172 if (length == 16) | |
3173 length = 10; | |
3174 } | |
3175 else | |
3176 { | |
3177 /* call_internal_short, call_value_internal_short. */ | |
3178 if (length == 8) | |
3179 length = 4; | |
3180 } | |
3181 } | |
3182 } | |
3183 return length; | |
3115 } | 3184 } |
3116 | 3185 |
3117 /* V850 specific attributes. */ | 3186 /* V850 specific attributes. */ |
3118 | 3187 |
3119 static const struct attribute_spec v850_attribute_table[] = | 3188 static const struct attribute_spec v850_attribute_table[] = |
3120 { | 3189 { |
3121 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ | 3190 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, |
3122 { "interrupt_handler", 0, 0, true, false, false, v850_handle_interrupt_attribute }, | 3191 affects_type_identity } */ |
3123 { "interrupt", 0, 0, true, false, false, v850_handle_interrupt_attribute }, | 3192 { "interrupt_handler", 0, 0, true, false, false, |
3124 { "sda", 0, 0, true, false, false, v850_handle_data_area_attribute }, | 3193 v850_handle_interrupt_attribute, false }, |
3125 { "tda", 0, 0, true, false, false, v850_handle_data_area_attribute }, | 3194 { "interrupt", 0, 0, true, false, false, |
3126 { "zda", 0, 0, true, false, false, v850_handle_data_area_attribute }, | 3195 v850_handle_interrupt_attribute, false }, |
3127 { NULL, 0, 0, false, false, false, NULL } | 3196 { "sda", 0, 0, true, false, false, |
3197 v850_handle_data_area_attribute, false }, | |
3198 { "tda", 0, 0, true, false, false, | |
3199 v850_handle_data_area_attribute, false }, | |
3200 { "zda", 0, 0, true, false, false, | |
3201 v850_handle_data_area_attribute, false }, | |
3202 { NULL, 0, 0, false, false, false, NULL, false } | |
3128 }; | 3203 }; |
3129 | 3204 |
3205 static void | |
3206 v850_option_override (void) | |
3207 { | |
3208 if (flag_exceptions || flag_non_call_exceptions) | |
3209 flag_omit_frame_pointer = 0; | |
3210 | |
3211 /* The RH850 ABI does not (currently) support the use of the CALLT instruction. */ | |
3212 if (! TARGET_GCC_ABI) | |
3213 target_flags |= MASK_DISABLE_CALLT; | |
3214 } | |
3215 | |
3216 const char * | |
3217 v850_gen_movdi (rtx * operands) | |
3218 { | |
3219 if (REG_P (operands[0])) | |
3220 { | |
3221 if (REG_P (operands[1])) | |
3222 { | |
3223 if (REGNO (operands[0]) == (REGNO (operands[1]) - 1)) | |
3224 return "mov %1, %0; mov %R1, %R0"; | |
3225 | |
3226 return "mov %R1, %R0; mov %1, %0"; | |
3227 } | |
3228 | |
3229 if (MEM_P (operands[1])) | |
3230 { | |
3231 if (REGNO (operands[0]) & 1) | |
3232 /* Use two load word instructions to synthesise a load double. */ | |
3233 return "ld.w %1, %0 ; ld.w %R1, %R0" ; | |
3234 | |
3235 return "ld.dw %1, %0"; | |
3236 } | |
3237 | |
3238 return "mov %1, %0; mov %R1, %R0"; | |
3239 } | |
3240 | |
3241 gcc_assert (REG_P (operands[1])); | |
3242 | |
3243 if (REGNO (operands[1]) & 1) | |
3244 /* Use two store word instructions to synthesise a store double. */ | |
3245 return "st.w %1, %0 ; st.w %R1, %R0 "; | |
3246 | |
3247 return "st.dw %1, %0"; | |
3248 } | |
3249 | |
3250 /* Implement TARGET_HARD_REGNO_MODE_OK. */ | |
3251 | |
3252 static bool | |
3253 v850_hard_regno_mode_ok (unsigned int regno, machine_mode mode) | |
3254 { | |
3255 return GET_MODE_SIZE (mode) <= 4 || ((regno & 1) == 0 && regno != 0); | |
3256 } | |
3257 | |
3258 /* Implement TARGET_MODES_TIEABLE_P. */ | |
3259 | |
3260 static bool | |
3261 v850_modes_tieable_p (machine_mode mode1, machine_mode mode2) | |
3262 { | |
3263 return (mode1 == mode2 | |
3264 || (GET_MODE_SIZE (mode1) <= 4 && GET_MODE_SIZE (mode2) <= 4)); | |
3265 } | |
3266 | |
3130 /* Initialize the GCC target structure. */ | 3267 /* Initialize the GCC target structure. */ |
3268 | |
3269 #undef TARGET_OPTION_OVERRIDE | |
3270 #define TARGET_OPTION_OVERRIDE v850_option_override | |
3271 | |
3272 #undef TARGET_MEMORY_MOVE_COST | |
3273 #define TARGET_MEMORY_MOVE_COST v850_memory_move_cost | |
3274 | |
3131 #undef TARGET_ASM_ALIGNED_HI_OP | 3275 #undef TARGET_ASM_ALIGNED_HI_OP |
3132 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t" | 3276 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t" |
3133 | 3277 |
3134 #undef TARGET_PRINT_OPERAND | 3278 #undef TARGET_PRINT_OPERAND |
3135 #define TARGET_PRINT_OPERAND v850_print_operand | 3279 #define TARGET_PRINT_OPERAND v850_print_operand |
3136 #undef TARGET_PRINT_OPERAND_ADDRESS | 3280 #undef TARGET_PRINT_OPERAND_ADDRESS |
3137 #define TARGET_PRINT_OPERAND_ADDRESS v850_print_operand_address | 3281 #define TARGET_PRINT_OPERAND_ADDRESS v850_print_operand_address |
3138 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P | 3282 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P |
3139 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P v850_print_operand_punct_valid_p | 3283 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P v850_print_operand_punct_valid_p |
3284 | |
3285 #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA | |
3286 #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA v850_output_addr_const_extra | |
3140 | 3287 |
3141 #undef TARGET_ATTRIBUTE_TABLE | 3288 #undef TARGET_ATTRIBUTE_TABLE |
3142 #define TARGET_ATTRIBUTE_TABLE v850_attribute_table | 3289 #define TARGET_ATTRIBUTE_TABLE v850_attribute_table |
3143 | 3290 |
3144 #undef TARGET_INSERT_ATTRIBUTES | 3291 #undef TARGET_INSERT_ATTRIBUTES |
3156 #define TARGET_ENCODE_SECTION_INFO v850_encode_section_info | 3303 #define TARGET_ENCODE_SECTION_INFO v850_encode_section_info |
3157 | 3304 |
3158 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE | 3305 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE |
3159 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true | 3306 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true |
3160 | 3307 |
3161 #undef TARGET_DEFAULT_TARGET_FLAGS | |
3162 #define TARGET_DEFAULT_TARGET_FLAGS (MASK_DEFAULT | MASK_APP_REGS) | |
3163 #undef TARGET_HANDLE_OPTION | |
3164 #define TARGET_HANDLE_OPTION v850_handle_option | |
3165 | |
3166 #undef TARGET_RTX_COSTS | 3308 #undef TARGET_RTX_COSTS |
3167 #define TARGET_RTX_COSTS v850_rtx_costs | 3309 #define TARGET_RTX_COSTS v850_rtx_costs |
3168 | 3310 |
3169 #undef TARGET_ADDRESS_COST | 3311 #undef TARGET_ADDRESS_COST |
3170 #define TARGET_ADDRESS_COST hook_int_rtx_bool_0 | 3312 #define TARGET_ADDRESS_COST hook_int_rtx_mode_as_bool_0 |
3171 | 3313 |
3172 #undef TARGET_MACHINE_DEPENDENT_REORG | 3314 #undef TARGET_MACHINE_DEPENDENT_REORG |
3173 #define TARGET_MACHINE_DEPENDENT_REORG v850_reorg | 3315 #define TARGET_MACHINE_DEPENDENT_REORG v850_reorg |
3174 | 3316 |
3175 #undef TARGET_SCHED_ISSUE_RATE | 3317 #undef TARGET_SCHED_ISSUE_RATE |
3177 | 3319 |
3178 #undef TARGET_FUNCTION_VALUE_REGNO_P | 3320 #undef TARGET_FUNCTION_VALUE_REGNO_P |
3179 #define TARGET_FUNCTION_VALUE_REGNO_P v850_function_value_regno_p | 3321 #define TARGET_FUNCTION_VALUE_REGNO_P v850_function_value_regno_p |
3180 #undef TARGET_FUNCTION_VALUE | 3322 #undef TARGET_FUNCTION_VALUE |
3181 #define TARGET_FUNCTION_VALUE v850_function_value | 3323 #define TARGET_FUNCTION_VALUE v850_function_value |
3324 #undef TARGET_LIBCALL_VALUE | |
3325 #define TARGET_LIBCALL_VALUE v850_libcall_value | |
3182 | 3326 |
3183 #undef TARGET_PROMOTE_PROTOTYPES | 3327 #undef TARGET_PROMOTE_PROTOTYPES |
3184 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true | 3328 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true |
3185 | 3329 |
3186 #undef TARGET_RETURN_IN_MEMORY | 3330 #undef TARGET_RETURN_IN_MEMORY |
3189 #undef TARGET_PASS_BY_REFERENCE | 3333 #undef TARGET_PASS_BY_REFERENCE |
3190 #define TARGET_PASS_BY_REFERENCE v850_pass_by_reference | 3334 #define TARGET_PASS_BY_REFERENCE v850_pass_by_reference |
3191 | 3335 |
3192 #undef TARGET_CALLEE_COPIES | 3336 #undef TARGET_CALLEE_COPIES |
3193 #define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true | 3337 #define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true |
3194 | |
3195 #undef TARGET_SETUP_INCOMING_VARARGS | |
3196 #define TARGET_SETUP_INCOMING_VARARGS v850_setup_incoming_varargs | |
3197 | 3338 |
3198 #undef TARGET_ARG_PARTIAL_BYTES | 3339 #undef TARGET_ARG_PARTIAL_BYTES |
3199 #define TARGET_ARG_PARTIAL_BYTES v850_arg_partial_bytes | 3340 #define TARGET_ARG_PARTIAL_BYTES v850_arg_partial_bytes |
3200 | 3341 |
3201 #undef TARGET_FUNCTION_ARG | 3342 #undef TARGET_FUNCTION_ARG |
3213 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE | 3354 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE |
3214 #define TARGET_ASM_TRAMPOLINE_TEMPLATE v850_asm_trampoline_template | 3355 #define TARGET_ASM_TRAMPOLINE_TEMPLATE v850_asm_trampoline_template |
3215 #undef TARGET_TRAMPOLINE_INIT | 3356 #undef TARGET_TRAMPOLINE_INIT |
3216 #define TARGET_TRAMPOLINE_INIT v850_trampoline_init | 3357 #define TARGET_TRAMPOLINE_INIT v850_trampoline_init |
3217 | 3358 |
3218 #undef TARGET_STRICT_ARGUMENT_NAMING | 3359 #undef TARGET_LEGITIMATE_CONSTANT_P |
3219 #define TARGET_STRICT_ARGUMENT_NAMING v850_strict_argument_naming | 3360 #define TARGET_LEGITIMATE_CONSTANT_P v850_legitimate_constant_p |
3220 | 3361 |
3221 #undef TARGET_OPTION_OPTIMIZATION_TABLE | 3362 #undef TARGET_LRA_P |
3222 #define TARGET_OPTION_OPTIMIZATION_TABLE v850_option_optimization_table | 3363 #define TARGET_LRA_P hook_bool_void_false |
3364 | |
3365 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P | |
3366 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P v850_legitimate_address_p | |
3367 | |
3368 #undef TARGET_CAN_USE_DOLOOP_P | |
3369 #define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost | |
3370 | |
3371 #undef TARGET_HARD_REGNO_MODE_OK | |
3372 #define TARGET_HARD_REGNO_MODE_OK v850_hard_regno_mode_ok | |
3373 | |
3374 #undef TARGET_MODES_TIEABLE_P | |
3375 #define TARGET_MODES_TIEABLE_P v850_modes_tieable_p | |
3223 | 3376 |
3224 struct gcc_target targetm = TARGET_INITIALIZER; | 3377 struct gcc_target targetm = TARGET_INITIALIZER; |
3225 | 3378 |
3226 #include "gt-v850.h" | 3379 #include "gt-v850.h" |