Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/m68hc11/m68hc11.c @ 67:f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 22 Mar 2011 17:18:12 +0900 |
parents | b7f97abdc517 |
children |
comparison
equal
deleted
inserted
replaced
65:65488c3d617d | 67:f6334be47118 |
---|---|
1 /* Subroutines for code generation on Motorola 68HC11 and 68HC12. | 1 /* Subroutines for code generation on Motorola 68HC11 and 68HC12. |
2 Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, | 2 Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, |
3 2009 Free Software Foundation, Inc. | 3 2009, 2010 Free Software Foundation, Inc. |
4 Contributed by Stephane Carrez (stcarrez@nerim.fr) | 4 Contributed by Stephane Carrez (stcarrez@nerim.fr) |
5 | 5 |
6 This file is part of GCC. | 6 This file is part of GCC. |
7 | 7 |
8 GCC is free software; you can redistribute it and/or modify | 8 GCC is free software; you can redistribute it and/or modify |
30 | 30 |
31 ftp.unina.it/pub/electronics/motorola/68hc11/gcc/gcc-6811-fsf.tar.gz | 31 ftp.unina.it/pub/electronics/motorola/68hc11/gcc/gcc-6811-fsf.tar.gz |
32 | 32 |
33 */ | 33 */ |
34 | 34 |
35 #include <stdio.h> | |
36 #include "config.h" | 35 #include "config.h" |
37 #include "system.h" | 36 #include "system.h" |
38 #include "coretypes.h" | 37 #include "coretypes.h" |
39 #include "tm.h" | 38 #include "tm.h" |
40 #include "rtl.h" | 39 #include "rtl.h" |
49 #include "insn-attr.h" | 48 #include "insn-attr.h" |
50 #include "flags.h" | 49 #include "flags.h" |
51 #include "recog.h" | 50 #include "recog.h" |
52 #include "expr.h" | 51 #include "expr.h" |
53 #include "libfuncs.h" | 52 #include "libfuncs.h" |
54 #include "toplev.h" | 53 #include "diagnostic-core.h" |
55 #include "basic-block.h" | 54 #include "basic-block.h" |
56 #include "function.h" | 55 #include "function.h" |
57 #include "ggc.h" | 56 #include "ggc.h" |
58 #include "reload.h" | 57 #include "reload.h" |
59 #include "target.h" | 58 #include "target.h" |
60 #include "target-def.h" | 59 #include "target-def.h" |
61 #include "df.h" | 60 #include "df.h" |
62 | 61 |
62 static void m68hc11_option_override (void); | |
63 static void emit_move_after_reload (rtx, rtx, rtx); | 63 static void emit_move_after_reload (rtx, rtx, rtx); |
64 static rtx simplify_logical (enum machine_mode, int, rtx, rtx *); | 64 static rtx simplify_logical (enum machine_mode, int, rtx, rtx *); |
65 static void m68hc11_emit_logical (enum machine_mode, enum rtx_code, rtx *); | 65 static void m68hc11_emit_logical (enum machine_mode, enum rtx_code, rtx *); |
66 static void m68hc11_reorg (void); | 66 static void m68hc11_reorg (void); |
67 static bool m68hc11_legitimate_address_p_1 (enum machine_mode, rtx, bool); | 67 static bool m68hc11_legitimate_address_p_1 (enum machine_mode, rtx, bool); |
72 static int m68hc11_shift_cost (enum machine_mode, rtx, int); | 72 static int m68hc11_shift_cost (enum machine_mode, rtx, int); |
73 static int m68hc11_rtx_costs_1 (rtx, enum rtx_code, enum rtx_code); | 73 static int m68hc11_rtx_costs_1 (rtx, enum rtx_code, enum rtx_code); |
74 static bool m68hc11_rtx_costs (rtx, int, int, int *, bool); | 74 static bool m68hc11_rtx_costs (rtx, int, int, int *, bool); |
75 static tree m68hc11_handle_fntype_attribute (tree *, tree, tree, int, bool *); | 75 static tree m68hc11_handle_fntype_attribute (tree *, tree, tree, int, bool *); |
76 static tree m68hc11_handle_page0_attribute (tree *, tree, tree, int, bool *); | 76 static tree m68hc11_handle_page0_attribute (tree *, tree, tree, int, bool *); |
77 static bool m68hc11_class_likely_spilled_p (reg_class_t); | |
77 | 78 |
78 void create_regs_rtx (void); | 79 void create_regs_rtx (void); |
79 | 80 |
80 static void asm_print_register (FILE *, int); | 81 static void asm_print_register (FILE *, int); |
82 static void m68hc11_print_operand (FILE *, rtx, int); | |
83 static void m68hc11_print_operand_address (FILE *, rtx); | |
81 static void m68hc11_output_function_epilogue (FILE *, HOST_WIDE_INT); | 84 static void m68hc11_output_function_epilogue (FILE *, HOST_WIDE_INT); |
82 static void m68hc11_asm_out_constructor (rtx, int); | 85 static void m68hc11_asm_out_constructor (rtx, int); |
83 static void m68hc11_asm_out_destructor (rtx, int); | 86 static void m68hc11_asm_out_destructor (rtx, int); |
84 static void m68hc11_file_start (void); | 87 static void m68hc11_file_start (void); |
85 static void m68hc11_encode_section_info (tree, rtx, int); | 88 static void m68hc11_encode_section_info (tree, rtx, int); |
89 static int m68hc11_make_autoinc_notes (rtx *, void *); | 92 static int m68hc11_make_autoinc_notes (rtx *, void *); |
90 static void m68hc11_init_libfuncs (void); | 93 static void m68hc11_init_libfuncs (void); |
91 static rtx m68hc11_struct_value_rtx (tree, int); | 94 static rtx m68hc11_struct_value_rtx (tree, int); |
92 static bool m68hc11_return_in_memory (const_tree, const_tree); | 95 static bool m68hc11_return_in_memory (const_tree, const_tree); |
93 static bool m68hc11_can_eliminate (const int, const int); | 96 static bool m68hc11_can_eliminate (const int, const int); |
97 static void m68hc11_conditional_register_usage (void); | |
94 static void m68hc11_trampoline_init (rtx, tree, rtx); | 98 static void m68hc11_trampoline_init (rtx, tree, rtx); |
99 | |
100 static rtx m68hc11_function_arg (CUMULATIVE_ARGS*, enum machine_mode, | |
101 const_tree, bool); | |
102 static void m68hc11_function_arg_advance (CUMULATIVE_ARGS*, enum machine_mode, | |
103 const_tree, bool); | |
95 | 104 |
96 /* Must be set to 1 to produce debug messages. */ | 105 /* Must be set to 1 to produce debug messages. */ |
97 int debug_m6811 = 0; | 106 int debug_m6811 = 0; |
98 | 107 |
99 extern FILE *asm_out_file; | 108 extern FILE *asm_out_file; |
236 #define TARGET_ATTRIBUTE_TABLE m68hc11_attribute_table | 245 #define TARGET_ATTRIBUTE_TABLE m68hc11_attribute_table |
237 | 246 |
238 #undef TARGET_ASM_ALIGNED_HI_OP | 247 #undef TARGET_ASM_ALIGNED_HI_OP |
239 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t" | 248 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t" |
240 | 249 |
250 #undef TARGET_PRINT_OPERAND | |
251 #define TARGET_PRINT_OPERAND m68hc11_print_operand | |
252 #undef TARGET_PRINT_OPERAND_ADDRESS | |
253 #define TARGET_PRINT_OPERAND_ADDRESS m68hc11_print_operand_address | |
254 | |
241 #undef TARGET_ASM_FUNCTION_EPILOGUE | 255 #undef TARGET_ASM_FUNCTION_EPILOGUE |
242 #define TARGET_ASM_FUNCTION_EPILOGUE m68hc11_output_function_epilogue | 256 #define TARGET_ASM_FUNCTION_EPILOGUE m68hc11_output_function_epilogue |
243 | 257 |
244 #undef TARGET_ASM_FILE_START | 258 #undef TARGET_ASM_FILE_START |
245 #define TARGET_ASM_FILE_START m68hc11_file_start | 259 #define TARGET_ASM_FILE_START m68hc11_file_start |
263 #undef TARGET_MACHINE_DEPENDENT_REORG | 277 #undef TARGET_MACHINE_DEPENDENT_REORG |
264 #define TARGET_MACHINE_DEPENDENT_REORG m68hc11_reorg | 278 #define TARGET_MACHINE_DEPENDENT_REORG m68hc11_reorg |
265 | 279 |
266 #undef TARGET_INIT_LIBFUNCS | 280 #undef TARGET_INIT_LIBFUNCS |
267 #define TARGET_INIT_LIBFUNCS m68hc11_init_libfuncs | 281 #define TARGET_INIT_LIBFUNCS m68hc11_init_libfuncs |
282 | |
283 #undef TARGET_FUNCTION_ARG | |
284 #define TARGET_FUNCTION_ARG m68hc11_function_arg | |
285 #undef TARGET_FUNCTION_ARG_ADVANCE | |
286 #define TARGET_FUNCTION_ARG_ADVANCE m68hc11_function_arg_advance | |
268 | 287 |
269 #undef TARGET_STRUCT_VALUE_RTX | 288 #undef TARGET_STRUCT_VALUE_RTX |
270 #define TARGET_STRUCT_VALUE_RTX m68hc11_struct_value_rtx | 289 #define TARGET_STRUCT_VALUE_RTX m68hc11_struct_value_rtx |
271 #undef TARGET_RETURN_IN_MEMORY | 290 #undef TARGET_RETURN_IN_MEMORY |
272 #define TARGET_RETURN_IN_MEMORY m68hc11_return_in_memory | 291 #define TARGET_RETURN_IN_MEMORY m68hc11_return_in_memory |
280 #define TARGET_LEGITIMATE_ADDRESS_P m68hc11_legitimate_address_p | 299 #define TARGET_LEGITIMATE_ADDRESS_P m68hc11_legitimate_address_p |
281 | 300 |
282 #undef TARGET_CAN_ELIMINATE | 301 #undef TARGET_CAN_ELIMINATE |
283 #define TARGET_CAN_ELIMINATE m68hc11_can_eliminate | 302 #define TARGET_CAN_ELIMINATE m68hc11_can_eliminate |
284 | 303 |
304 #undef TARGET_CONDITIONAL_REGISTER_USAGE | |
305 #define TARGET_CONDITIONAL_REGISTER_USAGE m68hc11_conditional_register_usage | |
306 | |
307 #undef TARGET_CLASS_LIKELY_SPILLED_P | |
308 #define TARGET_CLASS_LIKELY_SPILLED_P m68hc11_class_likely_spilled_p | |
309 | |
285 #undef TARGET_TRAMPOLINE_INIT | 310 #undef TARGET_TRAMPOLINE_INIT |
286 #define TARGET_TRAMPOLINE_INIT m68hc11_trampoline_init | 311 #define TARGET_TRAMPOLINE_INIT m68hc11_trampoline_init |
287 | 312 |
313 #undef TARGET_OPTION_OVERRIDE | |
314 #define TARGET_OPTION_OVERRIDE m68hc11_option_override | |
315 | |
288 struct gcc_target targetm = TARGET_INITIALIZER; | 316 struct gcc_target targetm = TARGET_INITIALIZER; |
289 | 317 |
290 int | 318 static void |
291 m68hc11_override_options (void) | 319 m68hc11_option_override (void) |
292 { | 320 { |
293 memset (m68hc11_reg_valid_for_index, 0, | 321 memset (m68hc11_reg_valid_for_index, 0, |
294 sizeof (m68hc11_reg_valid_for_index)); | 322 sizeof (m68hc11_reg_valid_for_index)); |
295 memset (m68hc11_reg_valid_for_base, 0, sizeof (m68hc11_reg_valid_for_base)); | 323 memset (m68hc11_reg_valid_for_base, 0, sizeof (m68hc11_reg_valid_for_base)); |
296 | 324 |
351 m68hc11_soft_reg_count = 0; | 379 m68hc11_soft_reg_count = 0; |
352 | 380 |
353 if (TARGET_LONG_CALLS) | 381 if (TARGET_LONG_CALLS) |
354 current_function_far = 1; | 382 current_function_far = 1; |
355 } | 383 } |
356 return 0; | 384 } |
357 } | 385 |
358 | 386 |
359 | 387 /* The soft-registers are disabled or enabled according to the |
360 void | 388 -msoft-reg-count=<n> option. */ |
389 | |
390 static void | |
361 m68hc11_conditional_register_usage (void) | 391 m68hc11_conditional_register_usage (void) |
362 { | 392 { |
363 int i; | 393 int i; |
364 | 394 |
365 if (m68hc11_soft_reg_count > SOFT_REG_LAST - SOFT_REG_FIRST) | 395 if (m68hc11_soft_reg_count > SOFT_REG_LAST - SOFT_REG_FIRST) |
568 } | 598 } |
569 | 599 |
570 return rclass; | 600 return rclass; |
571 } | 601 } |
572 | 602 |
603 /* Implement TARGET_CLASS_LIKELY_SPILLED_P. */ | |
604 | |
605 static bool | |
606 m68hc11_class_likely_spilled_p (reg_class_t rclass) | |
607 { | |
608 switch (rclass) | |
609 { | |
610 case D_REGS: | |
611 case X_REGS: | |
612 case Y_REGS: | |
613 case A_REGS: | |
614 case SP_REGS: | |
615 case D_OR_X_REGS: | |
616 case D_OR_Y_REGS: | |
617 case X_OR_SP_REGS: | |
618 case Y_OR_SP_REGS: | |
619 case D_OR_SP_REGS: | |
620 return true; | |
621 | |
622 default: | |
623 break; | |
624 } | |
625 | |
626 return false; | |
627 } | |
628 | |
573 /* Return 1 if the operand is a valid indexed addressing mode. | 629 /* Return 1 if the operand is a valid indexed addressing mode. |
574 For 68hc11: n,r with n in [0..255] and r in A_REGS class | 630 For 68hc11: n,r with n in [0..255] and r in A_REGS class |
575 For 68hc12: n,r no constraint on the constant, r in A_REGS class. */ | 631 For 68hc12: n,r no constraint on the constant, r in A_REGS class. */ |
576 int | 632 int |
577 m68hc11_valid_addressing_p (rtx operand, enum machine_mode mode, int addr_mode) | 633 m68hc11_valid_addressing_p (rtx operand, enum machine_mode mode, int addr_mode) |
1434 | 1490 |
1435 /* Update the data in CUM to advance over an argument | 1491 /* Update the data in CUM to advance over an argument |
1436 of mode MODE and data type TYPE. | 1492 of mode MODE and data type TYPE. |
1437 (TYPE is null for libcalls where that information may not be available.) */ | 1493 (TYPE is null for libcalls where that information may not be available.) */ |
1438 | 1494 |
1439 void | 1495 static void |
1440 m68hc11_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, | 1496 m68hc11_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, |
1441 tree type, int named ATTRIBUTE_UNUSED) | 1497 const_tree type, bool named ATTRIBUTE_UNUSED) |
1442 { | 1498 { |
1443 if (mode != BLKmode) | 1499 if (mode != BLKmode) |
1444 { | 1500 { |
1445 if (cum->words == 0 && GET_MODE_SIZE (mode) == 4) | 1501 if (cum->words == 0 && GET_MODE_SIZE (mode) == 4) |
1446 { | 1502 { |
1472 CUM is a variable of type CUMULATIVE_ARGS which gives info about | 1528 CUM is a variable of type CUMULATIVE_ARGS which gives info about |
1473 the preceding args and about the function being called. | 1529 the preceding args and about the function being called. |
1474 NAMED is nonzero if this argument is a named parameter | 1530 NAMED is nonzero if this argument is a named parameter |
1475 (otherwise it is an extra parameter matching an ellipsis). */ | 1531 (otherwise it is an extra parameter matching an ellipsis). */ |
1476 | 1532 |
1477 struct rtx_def * | 1533 static rtx |
1478 m68hc11_function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode, | 1534 m68hc11_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, |
1479 tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED) | 1535 const_tree type ATTRIBUTE_UNUSED, |
1536 bool named ATTRIBUTE_UNUSED) | |
1480 { | 1537 { |
1481 if (cum->words != 0) | 1538 if (cum->words != 0) |
1482 { | 1539 { |
1483 return NULL_RTX; | 1540 return NULL_RTX; |
1484 } | 1541 } |
1945 { | 2002 { |
1946 return gen_int_mode (val >> 16, HImode); | 2003 return gen_int_mode (val >> 16, HImode); |
1947 } | 2004 } |
1948 else if (mode == SImode) | 2005 else if (mode == SImode) |
1949 { | 2006 { |
1950 return gen_int_mode (val >> 32, SImode); | 2007 return gen_int_mode ((val >> 16) >> 16, SImode); |
1951 } | 2008 } |
1952 } | 2009 } |
1953 if (mode == QImode && D_REG_P (x)) | 2010 if (mode == QImode && D_REG_P (x)) |
1954 return gen_rtx_REG (mode, HARD_A_REGNUM); | 2011 return gen_rtx_REG (mode, HARD_A_REGNUM); |
1955 | 2012 |
2121 't' generate the temporary scratch register. The operand is | 2178 't' generate the temporary scratch register. The operand is |
2122 ignored. | 2179 ignored. |
2123 'T' generate the low-part temporary scratch register. The operand is | 2180 'T' generate the low-part temporary scratch register. The operand is |
2124 ignored. */ | 2181 ignored. */ |
2125 | 2182 |
2126 void | 2183 static void |
2127 print_operand (FILE *file, rtx op, int letter) | 2184 m68hc11_print_operand (FILE *file, rtx op, int letter) |
2128 { | 2185 { |
2129 if (letter == 't') | 2186 if (letter == 't') |
2130 { | 2187 { |
2131 asm_print_register (file, SOFT_TMP_REGNUM); | 2188 asm_print_register (file, SOFT_TMP_REGNUM); |
2132 return; | 2189 return; |
2218 break; | 2275 break; |
2219 | 2276 |
2220 case MEM: | 2277 case MEM: |
2221 gcc_assert (TARGET_M6812); | 2278 gcc_assert (TARGET_M6812); |
2222 fprintf (file, "["); | 2279 fprintf (file, "["); |
2223 print_operand_address (file, XEXP (base, 0)); | 2280 m68hc11_print_operand_address (file, XEXP (base, 0)); |
2224 fprintf (file, "]"); | 2281 fprintf (file, "]"); |
2225 break; | 2282 break; |
2226 | 2283 |
2227 default: | 2284 default: |
2228 if (m68hc11_page0_symbol_p (base)) | 2285 if (m68hc11_page0_symbol_p (base)) |
2314 | 2371 |
2315 /* A C compound statement to output to stdio stream STREAM the | 2372 /* A C compound statement to output to stdio stream STREAM the |
2316 assembler syntax for an instruction operand that is a memory | 2373 assembler syntax for an instruction operand that is a memory |
2317 reference whose address is ADDR. ADDR is an RTL expression. */ | 2374 reference whose address is ADDR. ADDR is an RTL expression. */ |
2318 | 2375 |
2319 void | 2376 static void |
2320 print_operand_address (FILE *file, rtx addr) | 2377 m68hc11_print_operand_address (FILE *file, rtx addr) |
2321 { | 2378 { |
2322 rtx base; | 2379 rtx base; |
2323 rtx offset; | 2380 rtx offset; |
2324 int need_parenthesis = 0; | 2381 int need_parenthesis = 0; |
2325 | 2382 |
2913 emit_move_insn (operands[0], result); | 2970 emit_move_insn (operands[0], result); |
2914 } | 2971 } |
2915 } | 2972 } |
2916 else if (operands[1] != 0 && operands[2] != 0) | 2973 else if (operands[1] != 0 && operands[2] != 0) |
2917 { | 2974 { |
2918 rtx insn; | |
2919 | |
2920 if (!H_REG_P (operands[0]) && operands[3]) | 2975 if (!H_REG_P (operands[0]) && operands[3]) |
2921 { | 2976 { |
2922 emit_move_insn (operands[3], operands[1]); | 2977 emit_move_insn (operands[3], operands[1]); |
2923 emit_insn (gen_rtx_SET (mode, | 2978 emit_insn (gen_rtx_SET (mode, |
2924 operands[3], | 2979 operands[3], |
2925 gen_rtx_fmt_ee (code, mode, | 2980 gen_rtx_fmt_ee (code, mode, |
2926 operands[3], operands[2]))); | 2981 operands[3], operands[2]))); |
2927 insn = emit_move_insn (operands[0], operands[3]); | 2982 emit_move_insn (operands[0], operands[3]); |
2928 } | 2983 } |
2929 else | 2984 else |
2930 { | 2985 { |
2931 insn = emit_insn (gen_rtx_SET (mode, | 2986 emit_insn (gen_rtx_SET (mode, operands[0], |
2932 operands[0], | 2987 gen_rtx_fmt_ee (code, mode, |
2933 gen_rtx_fmt_ee (code, mode, | 2988 operands[0], operands[2]))); |
2934 operands[0], | |
2935 operands[2]))); | |
2936 } | 2989 } |
2937 } | 2990 } |
2938 | 2991 |
2939 /* The logical operation is similar to a copy. */ | 2992 /* The logical operation is similar to a copy. */ |
2940 else if (need_copy) | 2993 else if (need_copy) |
4603 } | 4656 } |
4604 return 1; | 4657 return 1; |
4605 } | 4658 } |
4606 if (GET_CODE (body) == CLOBBER) | 4659 if (GET_CODE (body) == CLOBBER) |
4607 { | 4660 { |
4661 rtx dst = XEXP (body, 0); | |
4662 | |
4663 this_insn_uses_ix = reg_mentioned_p (ix_reg, dst); | |
4664 this_insn_uses_iy = reg_mentioned_p (iy_reg, dst); | |
4608 | 4665 |
4609 /* IX and IY are used at the same time, we have to restore | 4666 /* IX and IY are used at the same time, we have to restore |
4610 the value of the scratch register before this insn. */ | 4667 the value of the scratch register before this insn. */ |
4611 if (this_insn_uses_ix && this_insn_uses_iy) | 4668 if (this_insn_uses_ix && this_insn_uses_iy) |
4612 { | 4669 { |