Mercurial > hg > CbC > CbC_gcc
comparison gcc/config/cris/cris.c @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | a06113de4d67 |
children | b7f97abdc517 |
comparison
equal
deleted
inserted
replaced
52:c156f1bd5cd9 | 55:77e2b8dfacca |
---|---|
1 /* Definitions for GCC. Part of the machine description for CRIS. | 1 /* Definitions for GCC. Part of the machine description for CRIS. |
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, | 2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, |
3 2008 Free Software Foundation, Inc. | 3 2008, 2009 Free Software Foundation, Inc. |
4 Contributed by Axis Communications. Written by Hans-Peter Nilsson. | 4 Contributed by Axis Communications. Written by Hans-Peter Nilsson. |
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 |
61 | 61 |
62 enum cris_retinsn_type | 62 enum cris_retinsn_type |
63 { CRIS_RETINSN_UNKNOWN = 0, CRIS_RETINSN_RET, CRIS_RETINSN_JUMP }; | 63 { CRIS_RETINSN_UNKNOWN = 0, CRIS_RETINSN_RET, CRIS_RETINSN_JUMP }; |
64 | 64 |
65 /* Per-function machine data. */ | 65 /* Per-function machine data. */ |
66 struct machine_function GTY(()) | 66 struct GTY(()) machine_function |
67 { | 67 { |
68 int needs_return_address_on_stack; | 68 int needs_return_address_on_stack; |
69 | 69 |
70 /* This is the number of registers we save in the prologue due to | 70 /* This is the number of registers we save in the prologue due to |
71 stdarg. */ | 71 stdarg. */ |
82 goes in code or in a static initializer. */ | 82 goes in code or in a static initializer. */ |
83 static int in_code = 0; | 83 static int in_code = 0; |
84 | 84 |
85 /* Fix for reg_overlap_mentioned_p. */ | 85 /* Fix for reg_overlap_mentioned_p. */ |
86 static int cris_reg_overlap_mentioned_p (rtx, rtx); | 86 static int cris_reg_overlap_mentioned_p (rtx, rtx); |
87 | |
88 static enum machine_mode cris_promote_function_mode (const_tree, enum machine_mode, | |
89 int *, const_tree, int); | |
87 | 90 |
88 static void cris_print_base (rtx, FILE *); | 91 static void cris_print_base (rtx, FILE *); |
89 | 92 |
90 static void cris_print_index (rtx, FILE *); | 93 static void cris_print_index (rtx, FILE *); |
91 | 94 |
120 tree, bool); | 123 tree, bool); |
121 static tree cris_md_asm_clobbers (tree, tree, tree); | 124 static tree cris_md_asm_clobbers (tree, tree, tree); |
122 | 125 |
123 static bool cris_handle_option (size_t, const char *, int); | 126 static bool cris_handle_option (size_t, const char *, int); |
124 | 127 |
128 static bool cris_frame_pointer_required (void); | |
129 | |
130 static void cris_asm_trampoline_template (FILE *); | |
131 static void cris_trampoline_init (rtx, tree, rtx); | |
132 | |
133 static rtx cris_function_value(const_tree, const_tree, bool); | |
134 static rtx cris_libcall_value (enum machine_mode, const_rtx); | |
135 | |
125 /* This is the parsed result of the "-max-stack-stackframe=" option. If | 136 /* This is the parsed result of the "-max-stack-stackframe=" option. If |
126 it (still) is zero, then there was no such option given. */ | 137 it (still) is zero, then there was no such option given. */ |
127 int cris_max_stackframe = 0; | 138 int cris_max_stackframe = 0; |
128 | 139 |
129 /* This is the parsed result of the "-march=" option, if given. */ | 140 /* This is the parsed result of the "-march=" option, if given. */ |
162 #undef TARGET_RTX_COSTS | 173 #undef TARGET_RTX_COSTS |
163 #define TARGET_RTX_COSTS cris_rtx_costs | 174 #define TARGET_RTX_COSTS cris_rtx_costs |
164 #undef TARGET_ADDRESS_COST | 175 #undef TARGET_ADDRESS_COST |
165 #define TARGET_ADDRESS_COST cris_address_cost | 176 #define TARGET_ADDRESS_COST cris_address_cost |
166 | 177 |
167 #undef TARGET_PROMOTE_FUNCTION_ARGS | 178 #undef TARGET_PROMOTE_FUNCTION_MODE |
168 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true | 179 #define TARGET_PROMOTE_FUNCTION_MODE cris_promote_function_mode |
180 | |
169 #undef TARGET_STRUCT_VALUE_RTX | 181 #undef TARGET_STRUCT_VALUE_RTX |
170 #define TARGET_STRUCT_VALUE_RTX cris_struct_value_rtx | 182 #define TARGET_STRUCT_VALUE_RTX cris_struct_value_rtx |
171 #undef TARGET_SETUP_INCOMING_VARARGS | 183 #undef TARGET_SETUP_INCOMING_VARARGS |
172 #define TARGET_SETUP_INCOMING_VARARGS cris_setup_incoming_varargs | 184 #define TARGET_SETUP_INCOMING_VARARGS cris_setup_incoming_varargs |
173 #undef TARGET_PASS_BY_REFERENCE | 185 #undef TARGET_PASS_BY_REFERENCE |
178 #define TARGET_MD_ASM_CLOBBERS cris_md_asm_clobbers | 190 #define TARGET_MD_ASM_CLOBBERS cris_md_asm_clobbers |
179 #undef TARGET_DEFAULT_TARGET_FLAGS | 191 #undef TARGET_DEFAULT_TARGET_FLAGS |
180 #define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT | CRIS_SUBTARGET_DEFAULT) | 192 #define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT | CRIS_SUBTARGET_DEFAULT) |
181 #undef TARGET_HANDLE_OPTION | 193 #undef TARGET_HANDLE_OPTION |
182 #define TARGET_HANDLE_OPTION cris_handle_option | 194 #define TARGET_HANDLE_OPTION cris_handle_option |
195 #undef TARGET_FRAME_POINTER_REQUIRED | |
196 #define TARGET_FRAME_POINTER_REQUIRED cris_frame_pointer_required | |
197 | |
198 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE | |
199 #define TARGET_ASM_TRAMPOLINE_TEMPLATE cris_asm_trampoline_template | |
200 #undef TARGET_TRAMPOLINE_INIT | |
201 #define TARGET_TRAMPOLINE_INIT cris_trampoline_init | |
202 | |
203 #undef TARGET_FUNCTION_VALUE | |
204 #define TARGET_FUNCTION_VALUE cris_function_value | |
205 #undef TARGET_LIBCALL_VALUE | |
206 #define TARGET_LIBCALL_VALUE cris_libcall_value | |
183 | 207 |
184 struct gcc_target targetm = TARGET_INITIALIZER; | 208 struct gcc_target targetm = TARGET_INITIALIZER; |
185 | 209 |
186 /* Helper for cris_load_multiple_op and cris_ret_movem_op. */ | 210 /* Helper for cris_load_multiple_op and cris_ret_movem_op. */ |
187 | 211 |
1429 /* Record CC0 changes, so we do not have to output multiple | 1453 /* Record CC0 changes, so we do not have to output multiple |
1430 test insns. */ | 1454 test insns. */ |
1431 if (SET_DEST (exp) == cc0_rtx) | 1455 if (SET_DEST (exp) == cc0_rtx) |
1432 { | 1456 { |
1433 CC_STATUS_INIT; | 1457 CC_STATUS_INIT; |
1434 cc_status.value1 = SET_SRC (exp); | 1458 |
1435 | 1459 if (GET_CODE (SET_SRC (exp)) == COMPARE |
1436 /* Handle flags for the special btstq on one bit. */ | 1460 && XEXP (SET_SRC (exp), 1) == const0_rtx) |
1437 if (GET_CODE (SET_SRC (exp)) == ZERO_EXTRACT | 1461 cc_status.value1 = XEXP (SET_SRC (exp), 0); |
1438 && XEXP (SET_SRC (exp), 1) == const1_rtx) | 1462 else |
1463 cc_status.value1 = SET_SRC (exp); | |
1464 | |
1465 /* Handle flags for the special btstq on one bit. */ | |
1466 if (GET_CODE (cc_status.value1) == ZERO_EXTRACT | |
1467 && XEXP (cc_status.value1, 1) == const1_rtx) | |
1439 { | 1468 { |
1440 if (CONST_INT_P (XEXP (SET_SRC (exp), 0))) | 1469 if (CONST_INT_P (XEXP (cc_status.value1, 0))) |
1441 /* Using cmpq. */ | 1470 /* Using cmpq. */ |
1442 cc_status.flags = CC_INVERTED; | 1471 cc_status.flags = CC_INVERTED; |
1443 else | 1472 else |
1444 /* A one-bit btstq. */ | 1473 /* A one-bit btstq. */ |
1445 cc_status.flags = CC_Z_IN_NOT_N; | 1474 cc_status.flags = CC_Z_IN_NOT_N; |
1446 } | 1475 } |
1447 | 1476 |
1448 if (GET_CODE (SET_SRC (exp)) == COMPARE) | 1477 else if (GET_CODE (SET_SRC (exp)) == COMPARE) |
1449 { | 1478 { |
1450 if (!REG_P (XEXP (SET_SRC (exp), 0)) | 1479 if (!REG_P (XEXP (SET_SRC (exp), 0)) |
1451 && XEXP (SET_SRC (exp), 1) != const0_rtx) | 1480 && XEXP (SET_SRC (exp), 1) != const0_rtx) |
1452 /* For some reason gcc will not canonicalize compare | 1481 /* For some reason gcc will not canonicalize compare |
1453 operations, reversing the sign by itself if | 1482 operations, reversing the sign by itself if |
1852 *total = (rtx_cost (XEXP (x, 0), outer_code, speed) + 2 | 1881 *total = (rtx_cost (XEXP (x, 0), outer_code, speed) + 2 |
1853 + 2 * GET_MODE_NUNITS (GET_MODE (XEXP (x, 0)))); | 1882 + 2 * GET_MODE_NUNITS (GET_MODE (XEXP (x, 0)))); |
1854 return true; | 1883 return true; |
1855 } | 1884 } |
1856 return false; | 1885 return false; |
1886 | |
1887 case ZERO_EXTRACT: | |
1888 if (outer_code != COMPARE) | |
1889 return false; | |
1890 /* fall through */ | |
1857 | 1891 |
1858 case ZERO_EXTEND: case SIGN_EXTEND: | 1892 case ZERO_EXTEND: case SIGN_EXTEND: |
1859 *total = rtx_cost (XEXP (x, 0), outer_code, speed); | 1893 *total = rtx_cost (XEXP (x, 0), outer_code, speed); |
1860 return true; | 1894 return true; |
1861 | 1895 |
3737 { | 3771 { |
3738 return (targetm.calls.must_pass_in_stack (mode, type) | 3772 return (targetm.calls.must_pass_in_stack (mode, type) |
3739 || CRIS_FUNCTION_ARG_SIZE (mode, type) > 8); | 3773 || CRIS_FUNCTION_ARG_SIZE (mode, type) > 8); |
3740 } | 3774 } |
3741 | 3775 |
3776 /* A combination of defining TARGET_PROMOTE_FUNCTION_MODE, promoting arguments | |
3777 and *not* defining TARGET_PROMOTE_PROTOTYPES or PROMOTE_MODE gives the | |
3778 best code size and speed for gcc, ipps and products in gcc-2.7.2. */ | |
3779 | |
3780 enum machine_mode | |
3781 cris_promote_function_mode (const_tree type ATTRIBUTE_UNUSED, | |
3782 enum machine_mode mode, | |
3783 int *punsignedp ATTRIBUTE_UNUSED, | |
3784 const_tree fntype ATTRIBUTE_UNUSED, | |
3785 int for_return) | |
3786 { | |
3787 /* Defining PROMOTE_FUNCTION_RETURN in gcc-2.7.2 uncovered bug 981110 (even | |
3788 when modifying TARGET_FUNCTION_VALUE to return the promoted mode). | |
3789 Maybe pointless as of now, but let's keep the old behavior. */ | |
3790 if (for_return == 1) | |
3791 return mode; | |
3792 return CRIS_PROMOTED_MODE (mode, *punsignedp, type); | |
3793 } | |
3794 | |
3795 /* Let's assume all functions return in r[CRIS_FIRST_ARG_REG] for the | |
3796 time being. */ | |
3797 | |
3798 static rtx | |
3799 cris_function_value(const_tree type, | |
3800 const_tree func ATTRIBUTE_UNUSED, | |
3801 bool outgoing ATTRIBUTE_UNUSED) | |
3802 { | |
3803 return gen_rtx_REG (TYPE_MODE (type), CRIS_FIRST_ARG_REG); | |
3804 } | |
3805 | |
3806 /* Let's assume all functions return in r[CRIS_FIRST_ARG_REG] for the | |
3807 time being. */ | |
3808 | |
3809 static rtx | |
3810 cris_libcall_value (enum machine_mode mode, | |
3811 const_rtx fun ATTRIBUTE_UNUSED) | |
3812 { | |
3813 return gen_rtx_REG (mode, CRIS_FIRST_ARG_REG); | |
3814 } | |
3815 | |
3816 /* Let's assume all functions return in r[CRIS_FIRST_ARG_REG] for the | |
3817 time being. */ | |
3818 | |
3819 bool | |
3820 cris_function_value_regno_p (const unsigned int regno) | |
3821 { | |
3822 return (regno == CRIS_FIRST_ARG_REG); | |
3823 } | |
3742 | 3824 |
3743 static int | 3825 static int |
3744 cris_arg_partial_bytes (CUMULATIVE_ARGS *ca, enum machine_mode mode, | 3826 cris_arg_partial_bytes (CUMULATIVE_ARGS *ca, enum machine_mode mode, |
3745 tree type, bool named ATTRIBUTE_UNUSED) | 3827 tree type, bool named ATTRIBUTE_UNUSED) |
3746 { | 3828 { |
3802 build_string (strlen (reg_names[CRIS_MOF_REGNUM]), | 3884 build_string (strlen (reg_names[CRIS_MOF_REGNUM]), |
3803 reg_names[CRIS_MOF_REGNUM]), | 3885 reg_names[CRIS_MOF_REGNUM]), |
3804 clobbers); | 3886 clobbers); |
3805 } | 3887 } |
3806 | 3888 |
3889 /* Implement TARGET_FRAME_POINTER_REQUIRED. | |
3890 | |
3891 Really only needed if the stack frame has variable length (alloca | |
3892 or variable sized local arguments (GNU C extension). See PR39499 and | |
3893 PR38609 for the reason this isn't just 0. */ | |
3894 | |
3895 bool | |
3896 cris_frame_pointer_required (void) | |
3897 { | |
3898 return !current_function_sp_is_unchanging; | |
3899 } | |
3900 | |
3901 /* Implement TARGET_ASM_TRAMPOLINE_TEMPLATE. | |
3902 | |
3903 This looks too complicated, and it is. I assigned r7 to be the | |
3904 static chain register, but it is call-saved, so we have to save it, | |
3905 and come back to restore it after the call, so we have to save srp... | |
3906 Anyway, trampolines are rare enough that we can cope with this | |
3907 somewhat lack of elegance. | |
3908 (Do not be tempted to "straighten up" whitespace in the asms; the | |
3909 assembler #NO_APP state mandates strict spacing). */ | |
3910 /* ??? See the i386 regparm=3 implementation that pushes the static | |
3911 chain value to the stack in the trampoline, and uses a call-saved | |
3912 register when called directly. */ | |
3913 | |
3914 static void | |
3915 cris_asm_trampoline_template (FILE *f) | |
3916 { | |
3917 if (TARGET_V32) | |
3918 { | |
3919 /* This normally-unused nop insn acts as an instruction to | |
3920 the simulator to flush its instruction cache. None of | |
3921 the other instructions in the trampoline template suits | |
3922 as a trigger for V32. The pc-relative addressing mode | |
3923 works nicely as a trigger for V10. | |
3924 FIXME: Have specific V32 template (possibly avoiding the | |
3925 use of a special instruction). */ | |
3926 fprintf (f, "\tclearf x\n"); | |
3927 /* We have to use a register as an intermediate, choosing | |
3928 semi-randomly R1 (which has to not be the STATIC_CHAIN_REGNUM), | |
3929 so we can use it for address indirection and jsr target. */ | |
3930 fprintf (f, "\tmove $r1,$mof\n"); | |
3931 /* +4 */ | |
3932 fprintf (f, "\tmove.d 0,$r1\n"); | |
3933 fprintf (f, "\tmove.d $%s,[$r1]\n", reg_names[STATIC_CHAIN_REGNUM]); | |
3934 fprintf (f, "\taddq 6,$r1\n"); | |
3935 fprintf (f, "\tmove $mof,[$r1]\n"); | |
3936 fprintf (f, "\taddq 6,$r1\n"); | |
3937 fprintf (f, "\tmove $srp,[$r1]\n"); | |
3938 /* +20 */ | |
3939 fprintf (f, "\tmove.d 0,$%s\n", reg_names[STATIC_CHAIN_REGNUM]); | |
3940 /* +26 */ | |
3941 fprintf (f, "\tmove.d 0,$r1\n"); | |
3942 fprintf (f, "\tjsr $r1\n"); | |
3943 fprintf (f, "\tsetf\n"); | |
3944 /* +36 */ | |
3945 fprintf (f, "\tmove.d 0,$%s\n", reg_names[STATIC_CHAIN_REGNUM]); | |
3946 /* +42 */ | |
3947 fprintf (f, "\tmove.d 0,$r1\n"); | |
3948 /* +48 */ | |
3949 fprintf (f, "\tmove.d 0,$r9\n"); | |
3950 fprintf (f, "\tjump $r9\n"); | |
3951 fprintf (f, "\tsetf\n"); | |
3952 } | |
3953 else | |
3954 { | |
3955 fprintf (f, "\tmove.d $%s,[$pc+20]\n", reg_names[STATIC_CHAIN_REGNUM]); | |
3956 fprintf (f, "\tmove $srp,[$pc+22]\n"); | |
3957 fprintf (f, "\tmove.d 0,$%s\n", reg_names[STATIC_CHAIN_REGNUM]); | |
3958 fprintf (f, "\tjsr 0\n"); | |
3959 fprintf (f, "\tmove.d 0,$%s\n", reg_names[STATIC_CHAIN_REGNUM]); | |
3960 fprintf (f, "\tjump 0\n"); | |
3961 } | |
3962 } | |
3963 | |
3964 /* Implement TARGET_TRAMPOLINE_INIT. */ | |
3965 | |
3966 static void | |
3967 cris_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) | |
3968 { | |
3969 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0); | |
3970 rtx tramp = XEXP (m_tramp, 0); | |
3971 rtx mem; | |
3972 | |
3973 emit_block_move (m_tramp, assemble_trampoline_template (), | |
3974 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL); | |
3975 | |
3976 if (TARGET_V32) | |
3977 { | |
3978 mem = adjust_address (m_tramp, SImode, 6); | |
3979 emit_move_insn (mem, plus_constant (tramp, 38)); | |
3980 mem = adjust_address (m_tramp, SImode, 22); | |
3981 emit_move_insn (mem, chain_value); | |
3982 mem = adjust_address (m_tramp, SImode, 28); | |
3983 emit_move_insn (mem, fnaddr); | |
3984 } | |
3985 else | |
3986 { | |
3987 mem = adjust_address (m_tramp, SImode, 10); | |
3988 emit_move_insn (mem, chain_value); | |
3989 mem = adjust_address (m_tramp, SImode, 16); | |
3990 emit_move_insn (mem, fnaddr); | |
3991 } | |
3992 | |
3993 /* Note that there is no need to do anything with the cache for | |
3994 sake of a trampoline. */ | |
3995 } | |
3996 | |
3997 | |
3807 #if 0 | 3998 #if 0 |
3808 /* Various small functions to replace macros. Only called from a | 3999 /* Various small functions to replace macros. Only called from a |
3809 debugger. They might collide with gcc functions or system functions, | 4000 debugger. They might collide with gcc functions or system functions, |
3810 so only emit them when '#if 1' above. */ | 4001 so only emit them when '#if 1' above. */ |
3811 | 4002 |