comparison gcc/config/iq2000/iq2000.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 /* Subroutines used for code generation on Vitesse IQ2000 processors 1 /* Subroutines used for code generation on Vitesse IQ2000 processors
2 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 2 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
3 Free Software Foundation, Inc. 3 Free Software Foundation, Inc.
4 4
5 This file is part of GCC. 5 This file is part of GCC.
6 6
7 GCC is free software; you can redistribute it and/or modify 7 GCC is free software; you can redistribute it and/or modify
87 long fp_sp_offset; /* Offset from new sp to store fp registers. */ 87 long fp_sp_offset; /* Offset from new sp to store fp registers. */
88 int initialized; /* != 0 if frame size already calculated. */ 88 int initialized; /* != 0 if frame size already calculated. */
89 int num_gp; /* Number of gp registers saved. */ 89 int num_gp; /* Number of gp registers saved. */
90 } iq2000_frame_info; 90 } iq2000_frame_info;
91 91
92 struct machine_function GTY(()) 92 struct GTY(()) machine_function
93 { 93 {
94 /* Current frame information, calculated by compute_frame_size. */ 94 /* Current frame information, calculated by compute_frame_size. */
95 long total_size; /* # bytes that the entire frame takes up. */ 95 long total_size; /* # bytes that the entire frame takes up. */
96 long var_size; /* # bytes that variables take up. */ 96 long var_size; /* # bytes that variables take up. */
97 long args_size; /* # bytes that outgoing arguments take up. */ 97 long args_size; /* # bytes that outgoing arguments take up. */
116 enum processor_type iq2000_tune; 116 enum processor_type iq2000_tune;
117 117
118 /* Which instruction set architecture to use. */ 118 /* Which instruction set architecture to use. */
119 int iq2000_isa; 119 int iq2000_isa;
120 120
121 /* Cached operands, and operator to compare for use in set/branch/trap
122 on condition codes. */
123 rtx branch_cmp[2];
124
125 /* What type of branch to use. */
126 enum cmp_type branch_type;
127
128 /* Local variables. */ 121 /* Local variables. */
129 122
130 /* The next branch instruction is a branch likely, not branch normal. */ 123 /* The next branch instruction is a branch likely, not branch normal. */
131 static int iq2000_branch_likely; 124 static int iq2000_branch_likely;
132 125
163 enum machine_mode, tree, int *, 156 enum machine_mode, tree, int *,
164 int); 157 int);
165 static bool iq2000_rtx_costs (rtx, int, int, int *, bool); 158 static bool iq2000_rtx_costs (rtx, int, int, int *, bool);
166 static int iq2000_address_cost (rtx, bool); 159 static int iq2000_address_cost (rtx, bool);
167 static section *iq2000_select_section (tree, int, unsigned HOST_WIDE_INT); 160 static section *iq2000_select_section (tree, int, unsigned HOST_WIDE_INT);
161 static rtx iq2000_legitimize_address (rtx, rtx, enum machine_mode);
168 static bool iq2000_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode, 162 static bool iq2000_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
169 const_tree, bool); 163 const_tree, bool);
170 static int iq2000_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, 164 static int iq2000_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
171 tree, bool); 165 tree, bool);
172 static void iq2000_va_start (tree, rtx); 166 static void iq2000_va_start (tree, rtx);
167 static bool iq2000_legitimate_address_p (enum machine_mode, rtx, bool);
168 static bool iq2000_can_eliminate (const int, const int);
169 static void iq2000_asm_trampoline_template (FILE *);
170 static void iq2000_trampoline_init (rtx, tree, rtx);
171 static rtx iq2000_function_value (const_tree, const_tree, bool);
172 static rtx iq2000_libcall_value (enum machine_mode, const_rtx);
173 173
174 #undef TARGET_INIT_BUILTINS 174 #undef TARGET_INIT_BUILTINS
175 #define TARGET_INIT_BUILTINS iq2000_init_builtins 175 #define TARGET_INIT_BUILTINS iq2000_init_builtins
176 #undef TARGET_EXPAND_BUILTIN 176 #undef TARGET_EXPAND_BUILTIN
177 #define TARGET_EXPAND_BUILTIN iq2000_expand_builtin 177 #define TARGET_EXPAND_BUILTIN iq2000_expand_builtin
184 #undef TARGET_ADDRESS_COST 184 #undef TARGET_ADDRESS_COST
185 #define TARGET_ADDRESS_COST iq2000_address_cost 185 #define TARGET_ADDRESS_COST iq2000_address_cost
186 #undef TARGET_ASM_SELECT_SECTION 186 #undef TARGET_ASM_SELECT_SECTION
187 #define TARGET_ASM_SELECT_SECTION iq2000_select_section 187 #define TARGET_ASM_SELECT_SECTION iq2000_select_section
188 188
189 #undef TARGET_LEGITIMIZE_ADDRESS
190 #define TARGET_LEGITIMIZE_ADDRESS iq2000_legitimize_address
191
189 /* The assembler supports switchable .bss sections, but 192 /* The assembler supports switchable .bss sections, but
190 iq2000_select_section doesn't yet make use of them. */ 193 iq2000_select_section doesn't yet make use of them. */
191 #undef TARGET_HAVE_SWITCHABLE_BSS_SECTIONS 194 #undef TARGET_HAVE_SWITCHABLE_BSS_SECTIONS
192 #define TARGET_HAVE_SWITCHABLE_BSS_SECTIONS false 195 #define TARGET_HAVE_SWITCHABLE_BSS_SECTIONS false
193 196
194 #undef TARGET_PROMOTE_FUNCTION_ARGS 197 #undef TARGET_PROMOTE_FUNCTION_MODE
195 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true 198 #define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
196 #undef TARGET_PROMOTE_FUNCTION_RETURN
197 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
198 #undef TARGET_PROMOTE_PROTOTYPES 199 #undef TARGET_PROMOTE_PROTOTYPES
199 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true 200 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
200 201
202 #undef TARGET_FUNCTION_VALUE
203 #define TARGET_FUNCTION_VALUE iq2000_function_value
204 #undef TARGET_LIBCALL_VALUE
205 #define TARGET_LIBCALL_VALUE iq2000_libcall_value
201 #undef TARGET_RETURN_IN_MEMORY 206 #undef TARGET_RETURN_IN_MEMORY
202 #define TARGET_RETURN_IN_MEMORY iq2000_return_in_memory 207 #define TARGET_RETURN_IN_MEMORY iq2000_return_in_memory
203 #undef TARGET_PASS_BY_REFERENCE 208 #undef TARGET_PASS_BY_REFERENCE
204 #define TARGET_PASS_BY_REFERENCE iq2000_pass_by_reference 209 #define TARGET_PASS_BY_REFERENCE iq2000_pass_by_reference
205 #undef TARGET_CALLEE_COPIES 210 #undef TARGET_CALLEE_COPIES
213 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true 218 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
214 219
215 #undef TARGET_EXPAND_BUILTIN_VA_START 220 #undef TARGET_EXPAND_BUILTIN_VA_START
216 #define TARGET_EXPAND_BUILTIN_VA_START iq2000_va_start 221 #define TARGET_EXPAND_BUILTIN_VA_START iq2000_va_start
217 222
223 #undef TARGET_LEGITIMATE_ADDRESS_P
224 #define TARGET_LEGITIMATE_ADDRESS_P iq2000_legitimate_address_p
225
226 #undef TARGET_CAN_ELIMINATE
227 #define TARGET_CAN_ELIMINATE iq2000_can_eliminate
228
229 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
230 #define TARGET_ASM_TRAMPOLINE_TEMPLATE iq2000_asm_trampoline_template
231 #undef TARGET_TRAMPOLINE_INIT
232 #define TARGET_TRAMPOLINE_INIT iq2000_trampoline_init
233
218 struct gcc_target targetm = TARGET_INITIALIZER; 234 struct gcc_target targetm = TARGET_INITIALIZER;
219 235
220 /* Return nonzero if we split the address into high and low parts. */ 236 /* Return nonzero if we split the address into high and low parts. */
221 237
222 int 238 int
250 266
251 /* Return a nonzero value if XINSN is a legitimate address for a 267 /* Return a nonzero value if XINSN is a legitimate address for a
252 memory operand of the indicated MODE. STRICT is nonzero if this 268 memory operand of the indicated MODE. STRICT is nonzero if this
253 function is called during reload. */ 269 function is called during reload. */
254 270
255 int 271 bool
256 iq2000_legitimate_address_p (enum machine_mode mode, rtx xinsn, int strict) 272 iq2000_legitimate_address_p (enum machine_mode mode, rtx xinsn, bool strict)
257 { 273 {
258 if (TARGET_DEBUG_A_MODE) 274 if (TARGET_DEBUG_A_MODE)
259 { 275 {
260 GO_PRINTF2 ("\n========== GO_IF_LEGITIMATE_ADDRESS, %sstrict\n", 276 GO_PRINTF2 ("\n========== legitimate_address_p, %sstrict\n",
261 strict ? "" : "not "); 277 strict ? "" : "not ");
262 GO_DEBUG_RTX (xinsn); 278 GO_DEBUG_RTX (xinsn);
263 } 279 }
264 280
265 /* Check for constant before stripping off SUBREG, so that we don't 281 /* Check for constant before stripping off SUBREG, so that we don't
312 return 1; 328 return 1;
313 } 329 }
314 } 330 }
315 331
316 if (TARGET_DEBUG_A_MODE) 332 if (TARGET_DEBUG_A_MODE)
317 GO_PRINTF ("Not a legitimate address\n"); 333 GO_PRINTF ("Not a enum machine_mode mode, legitimate address\n");
318 334
319 /* The address was not legitimate. */ 335 /* The address was not legitimate. */
320 return 0; 336 return 0;
321 } 337 }
322 338
1004 /* Emit the common code for doing conditional branches. 1020 /* Emit the common code for doing conditional branches.
1005 operand[0] is the label to jump to. 1021 operand[0] is the label to jump to.
1006 The comparison operands are saved away by cmp{si,di,sf,df}. */ 1022 The comparison operands are saved away by cmp{si,di,sf,df}. */
1007 1023
1008 void 1024 void
1009 gen_conditional_branch (rtx operands[], enum rtx_code test_code) 1025 gen_conditional_branch (rtx operands[], enum machine_mode mode)
1010 { 1026 {
1011 enum cmp_type type = branch_type; 1027 enum rtx_code test_code = GET_CODE (operands[0]);
1012 rtx cmp0 = branch_cmp[0]; 1028 rtx cmp0 = operands[1];
1013 rtx cmp1 = branch_cmp[1]; 1029 rtx cmp1 = operands[2];
1014 enum machine_mode mode;
1015 rtx reg; 1030 rtx reg;
1016 int invert; 1031 int invert;
1017 rtx label1, label2; 1032 rtx label1, label2;
1018 1033
1019 switch (type) 1034 invert = 0;
1020 { 1035 reg = gen_int_relational (test_code, NULL_RTX, cmp0, cmp1, &invert);
1021 case CMP_SI: 1036
1022 case CMP_DI: 1037 if (reg)
1023 mode = type == CMP_SI ? SImode : DImode; 1038 {
1024 invert = 0;
1025 reg = gen_int_relational (test_code, NULL_RTX, cmp0, cmp1, &invert);
1026
1027 if (reg)
1028 {
1029 cmp0 = reg;
1030 cmp1 = const0_rtx;
1031 test_code = NE;
1032 }
1033 else if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0)
1034 /* We don't want to build a comparison against a nonzero
1035 constant. */
1036 cmp1 = force_reg (mode, cmp1);
1037
1038 break;
1039
1040 case CMP_SF:
1041 case CMP_DF:
1042 reg = gen_reg_rtx (CCmode);
1043
1044 /* For cmp0 != cmp1, build cmp0 == cmp1, and test for result == 0. */
1045 emit_insn (gen_rtx_SET (VOIDmode, reg,
1046 gen_rtx_fmt_ee (test_code == NE ? EQ : test_code,
1047 CCmode, cmp0, cmp1)));
1048
1049 test_code = test_code == NE ? EQ : NE;
1050 mode = CCmode;
1051 cmp0 = reg; 1039 cmp0 = reg;
1052 cmp1 = const0_rtx; 1040 cmp1 = const0_rtx;
1053 invert = 0; 1041 test_code = NE;
1054 break; 1042 }
1055 1043 else if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0)
1056 default: 1044 /* We don't want to build a comparison against a nonzero
1057 abort_with_insn (gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1), 1045 constant. */
1058 "bad test"); 1046 cmp1 = force_reg (mode, cmp1);
1059 }
1060 1047
1061 /* Generate the branch. */ 1048 /* Generate the branch. */
1062 label1 = gen_rtx_LABEL_REF (VOIDmode, operands[0]); 1049 label1 = gen_rtx_LABEL_REF (VOIDmode, operands[3]);
1063 label2 = pc_rtx; 1050 label2 = pc_rtx;
1064 1051
1065 if (invert) 1052 if (invert)
1066 { 1053 {
1067 label2 = label1; 1054 label2 = label1;
1171 break; 1158 break;
1172 1159
1173 case DImode: 1160 case DImode:
1174 cum->gp_reg_found = 1; 1161 cum->gp_reg_found = 1;
1175 cum->arg_words += 2; 1162 cum->arg_words += 2;
1163 break;
1164
1165 case TImode:
1166 cum->gp_reg_found = 1;
1167 cum->arg_words += 4;
1176 break; 1168 break;
1177 1169
1178 case QImode: 1170 case QImode:
1179 case HImode: 1171 case HImode:
1180 case SImode: 1172 case SImode:
1243 break; 1235 break;
1244 1236
1245 case DImode: 1237 case DImode:
1246 cum->arg_words += (cum->arg_words & 1); 1238 cum->arg_words += (cum->arg_words & 1);
1247 regbase = GP_ARG_FIRST; 1239 regbase = GP_ARG_FIRST;
1240 break;
1241
1242 case TImode:
1243 cum->arg_words += (cum->arg_words & 3);
1244 regbase = GP_ARG_FIRST;
1245 break;
1248 } 1246 }
1249 1247
1250 if (*arg_words >= (unsigned) MAX_ARGS_IN_REGISTERS) 1248 if (*arg_words >= (unsigned) MAX_ARGS_IN_REGISTERS)
1251 { 1249 {
1252 if (TARGET_DEBUG_D_MODE) 1250 if (TARGET_DEBUG_D_MODE)
1695 1693
1696 /* Ok, we're done. */ 1694 /* Ok, we're done. */
1697 return total_size; 1695 return total_size;
1698 } 1696 }
1699 1697
1698
1699 /* We can always eliminate to the frame pointer. We can eliminate to the
1700 stack pointer unless a frame pointer is needed. */
1701
1702 bool
1703 iq2000_can_eliminate (const int from, const int to)
1704 {
1705 return (from == RETURN_ADDRESS_POINTER_REGNUM
1706 && (! leaf_function_p ()
1707 || (to == GP_REG_FIRST + 31 && leaf_function_p)))
1708 || (from != RETURN_ADDRESS_POINTER_REGNUM
1709 && (to == HARD_FRAME_POINTER_REGNUM
1710 || (to == STACK_POINTER_REGNUM
1711 && ! frame_pointer_needed)));
1712 }
1713
1700 /* Implement INITIAL_ELIMINATION_OFFSET. FROM is either the frame 1714 /* Implement INITIAL_ELIMINATION_OFFSET. FROM is either the frame
1701 pointer, argument pointer, or return address pointer. TO is either 1715 pointer, argument pointer, or return address pointer. TO is either
1702 the stack pointer or hard frame pointer. */ 1716 the stack pointer or hard frame pointer. */
1703 1717
1704 int 1718 int
1875 if (aggregate_value_p (DECL_RESULT (fndecl), fndecl) 1889 if (aggregate_value_p (DECL_RESULT (fndecl), fndecl)
1876 && !cfun->returns_pcc_struct 1890 && !cfun->returns_pcc_struct
1877 && targetm.calls.struct_value_rtx (TREE_TYPE (fndecl), 1) == 0) 1891 && targetm.calls.struct_value_rtx (TREE_TYPE (fndecl), 1) == 0)
1878 { 1892 {
1879 tree type = build_pointer_type (fntype); 1893 tree type = build_pointer_type (fntype);
1880 tree function_result_decl = build_decl (PARM_DECL, NULL_TREE, type); 1894 tree function_result_decl = build_decl (BUILTINS_LOCATION,
1895 PARM_DECL, NULL_TREE, type);
1881 1896
1882 DECL_ARG_TYPE (function_result_decl) = type; 1897 DECL_ARG_TYPE (function_result_decl) = type;
1883 TREE_CHAIN (function_result_decl) = fnargs; 1898 TREE_CHAIN (function_result_decl) = fnargs;
1884 fnargs = function_result_decl; 1899 fnargs = function_result_decl;
1885 } 1900 }
2199 } 2214 }
2200 } 2215 }
2201 /* Return register to use for a function return value with VALTYPE for function 2216 /* Return register to use for a function return value with VALTYPE for function
2202 FUNC. */ 2217 FUNC. */
2203 2218
2204 rtx 2219 static rtx
2205 iq2000_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED) 2220 iq2000_function_value (const_tree valtype,
2221 const_tree fn_decl_or_type,
2222 bool outgoing ATTRIBUTE_UNUSED)
2206 { 2223 {
2207 int reg = GP_RETURN; 2224 int reg = GP_RETURN;
2208 enum machine_mode mode = TYPE_MODE (valtype); 2225 enum machine_mode mode = TYPE_MODE (valtype);
2209 int unsignedp = TYPE_UNSIGNED (valtype); 2226 int unsignedp = TYPE_UNSIGNED (valtype);
2210 2227 tree func = fn_decl_or_type;
2211 /* Since we define TARGET_PROMOTE_FUNCTION_RETURN that returns true, 2228
2212 we must promote the mode just as PROMOTE_MODE does. */ 2229 if (fn_decl_or_type
2213 mode = promote_mode (valtype, mode, &unsignedp, 1); 2230 && !DECL_P (fn_decl_or_type))
2231 fn_decl_or_type = NULL;
2232
2233 /* Since we promote return types, we must promote the mode here too. */
2234 mode = promote_function_mode (valtype, mode, &unsignedp, func, 1);
2214 2235
2215 return gen_rtx_REG (mode, reg); 2236 return gen_rtx_REG (mode, reg);
2216 } 2237 }
2238
2239 /* Worker function for TARGET_LIBCALL_VALUE. */
2240
2241 static rtx
2242 iq2000_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
2243 {
2244 return gen_rtx_REG (((GET_MODE_CLASS (mode) != MODE_INT
2245 || GET_MODE_SIZE (mode) >= 4)
2246 ? mode : SImode),
2247 GP_RETURN);
2248 }
2249
2250 /* Worker function for FUNCTION_VALUE_REGNO_P.
2251
2252 On the IQ2000, R2 and R3 are the only register thus used. */
2253
2254 bool
2255 iq2000_function_value_regno_p (const unsigned int regno)
2256 {
2257 return (regno == GP_RETURN);
2258 }
2259
2217 2260
2218 /* Return true when an argument must be passed by reference. */ 2261 /* Return true when an argument must be passed by reference. */
2219 2262
2220 static bool 2263 static bool
2221 iq2000_pass_by_reference (CUMULATIVE_ARGS *cum, enum machine_mode mode, 2264 iq2000_pass_by_reference (CUMULATIVE_ARGS *cum, enum machine_mode mode,
3201 3244
3202 else 3245 else
3203 output_addr_const (file, op); 3246 output_addr_const (file, op);
3204 } 3247 }
3205 3248
3249
3250 /* For the IQ2000, transform:
3251
3252 memory(X + <large int>)
3253 into:
3254 Y = <large int> & ~0x7fff;
3255 Z = X + Y
3256 memory (Z + (<large int> & 0x7fff));
3257 */
3258
3259 rtx
3260 iq2000_legitimize_address (rtx xinsn, rtx old_x ATTRIBUTE_UNUSED,
3261 enum machine_mode mode)
3262 {
3263 if (TARGET_DEBUG_B_MODE)
3264 {
3265 GO_PRINTF ("\n========== LEGITIMIZE_ADDRESS\n");
3266 GO_DEBUG_RTX (xinsn);
3267 }
3268
3269 if (iq2000_check_split (xinsn, mode))
3270 {
3271 return gen_rtx_LO_SUM (Pmode,
3272 copy_to_mode_reg (Pmode,
3273 gen_rtx_HIGH (Pmode, xinsn)),
3274 xinsn);
3275 }
3276
3277 if (GET_CODE (xinsn) == PLUS)
3278 {
3279 rtx xplus0 = XEXP (xinsn, 0);
3280 rtx xplus1 = XEXP (xinsn, 1);
3281 enum rtx_code code0 = GET_CODE (xplus0);
3282 enum rtx_code code1 = GET_CODE (xplus1);
3283
3284 if (code0 != REG && code1 == REG)
3285 {
3286 xplus0 = XEXP (xinsn, 1);
3287 xplus1 = XEXP (xinsn, 0);
3288 code0 = GET_CODE (xplus0);
3289 code1 = GET_CODE (xplus1);
3290 }
3291
3292 if (code0 == REG && REG_MODE_OK_FOR_BASE_P (xplus0, mode)
3293 && code1 == CONST_INT && !SMALL_INT (xplus1))
3294 {
3295 rtx int_reg = gen_reg_rtx (Pmode);
3296 rtx ptr_reg = gen_reg_rtx (Pmode);
3297
3298 emit_move_insn (int_reg,
3299 GEN_INT (INTVAL (xplus1) & ~ 0x7fff));
3300
3301 emit_insn (gen_rtx_SET (VOIDmode,
3302 ptr_reg,
3303 gen_rtx_PLUS (Pmode, xplus0, int_reg)));
3304
3305 return plus_constant (ptr_reg, INTVAL (xplus1) & 0x7fff);
3306 }
3307 }
3308
3309 if (TARGET_DEBUG_B_MODE)
3310 GO_PRINTF ("LEGITIMIZE_ADDRESS could not fix.\n");
3311
3312 return xinsn;
3313 }
3314
3315
3206 static bool 3316 static bool
3207 iq2000_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int * total, 3317 iq2000_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int * total,
3208 bool speed ATTRIBUTE_UNUSED) 3318 bool speed ATTRIBUTE_UNUSED)
3209 { 3319 {
3210 enum machine_mode mode = GET_MODE (x); 3320 enum machine_mode mode = GET_MODE (x);
3340 return false; 3450 return false;
3341 } 3451 }
3342 return true; 3452 return true;
3343 } 3453 }
3344 3454
3455 /* Worker for TARGET_ASM_TRAMPOLINE_TEMPLATE. */
3456
3457 static void
3458 iq2000_asm_trampoline_template (FILE *f)
3459 {
3460 fprintf (f, "\t.word\t0x03e00821\t\t# move $1,$31\n");
3461 fprintf (f, "\t.word\t0x04110001\t\t# bgezal $0,.+8\n");
3462 fprintf (f, "\t.word\t0x00000000\t\t# nop\n");
3463 if (Pmode == DImode)
3464 {
3465 fprintf (f, "\t.word\t0xdfe30014\t\t# ld $3,20($31)\n");
3466 fprintf (f, "\t.word\t0xdfe2001c\t\t# ld $2,28($31)\n");
3467 }
3468 else
3469 {
3470 fprintf (f, "\t.word\t0x8fe30014\t\t# lw $3,20($31)\n");
3471 fprintf (f, "\t.word\t0x8fe20018\t\t# lw $2,24($31)\n");
3472 }
3473 fprintf (f, "\t.word\t0x0060c821\t\t# move $25,$3 (abicalls)\n");
3474 fprintf (f, "\t.word\t0x00600008\t\t# jr $3\n");
3475 fprintf (f, "\t.word\t0x0020f821\t\t# move $31,$1\n");
3476 fprintf (f, "\t.word\t0x00000000\t\t# <function address>\n");
3477 fprintf (f, "\t.word\t0x00000000\t\t# <static chain value>\n");
3478 }
3479
3480 /* Worker for TARGET_TRAMPOLINE_INIT. */
3481
3482 static void
3483 iq2000_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
3484 {
3485 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
3486 rtx mem;
3487
3488 emit_block_move (m_tramp, assemble_trampoline_template (),
3489 GEN_INT (TRAMPOLINE_CODE_SIZE), BLOCK_OP_NORMAL);
3490
3491 mem = adjust_address (m_tramp, Pmode, TRAMPOLINE_CODE_SIZE);
3492 emit_move_insn (mem, fnaddr);
3493 mem = adjust_address (m_tramp, Pmode,
3494 TRAMPOLINE_CODE_SIZE + GET_MODE_SIZE (Pmode));
3495 emit_move_insn (mem, chain_value);
3496 }
3497
3345 #include "gt-iq2000.h" 3498 #include "gt-iq2000.h"