]>
Commit | Line | Data |
---|---|---|
cceb575c | 1 | /* Target Code for moxie |
23a5b65a | 2 | Copyright (C) 2008-2014 Free Software Foundation, Inc. |
cceb575c AG |
3 | Contributed by Anthony Green. |
4 | ||
5 | This file is part of GCC. | |
6 | ||
7 | GCC is free software; you can redistribute it and/or modify it | |
8 | under the terms of the GNU General Public License as published | |
9 | by the Free Software Foundation; either version 3, or (at your | |
10 | option) any later version. | |
11 | ||
12 | GCC is distributed in the hope that it will be useful, but WITHOUT | |
13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
14 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public | |
15 | License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with GCC; see the file COPYING3. If not see | |
19 | <http://www.gnu.org/licenses/>. */ | |
20 | ||
21 | #include "config.h" | |
22 | #include "system.h" | |
23 | #include "coretypes.h" | |
24 | #include "tm.h" | |
25 | #include "rtl.h" | |
26 | #include "regs.h" | |
27 | #include "hard-reg-set.h" | |
cceb575c AG |
28 | #include "insn-config.h" |
29 | #include "conditions.h" | |
30 | #include "insn-flags.h" | |
31 | #include "output.h" | |
32 | #include "insn-attr.h" | |
33 | #include "flags.h" | |
34 | #include "recog.h" | |
35 | #include "reload.h" | |
718f9c0f | 36 | #include "diagnostic-core.h" |
cceb575c AG |
37 | #include "obstack.h" |
38 | #include "tree.h" | |
d8a2d370 DN |
39 | #include "stor-layout.h" |
40 | #include "varasm.h" | |
41 | #include "calls.h" | |
cceb575c AG |
42 | #include "expr.h" |
43 | #include "optabs.h" | |
44 | #include "except.h" | |
83685514 AM |
45 | #include "hashtab.h" |
46 | #include "hash-set.h" | |
47 | #include "vec.h" | |
48 | #include "machmode.h" | |
49 | #include "input.h" | |
cceb575c AG |
50 | #include "function.h" |
51 | #include "ggc.h" | |
52 | #include "target.h" | |
53 | #include "target-def.h" | |
54 | #include "tm_p.h" | |
55 | #include "langhooks.h" | |
60393bbc AM |
56 | #include "dominance.h" |
57 | #include "cfg.h" | |
58 | #include "cfgrtl.h" | |
59 | #include "cfganal.h" | |
60 | #include "lcm.h" | |
61 | #include "cfgbuild.h" | |
62 | #include "cfgcleanup.h" | |
63 | #include "predict.h" | |
64 | #include "basic-block.h" | |
cceb575c | 65 | #include "df.h" |
9b2b7279 | 66 | #include "builtins.h" |
cceb575c AG |
67 | |
68 | #define LOSE_AND_RETURN(msgid, x) \ | |
69 | do \ | |
70 | { \ | |
71 | moxie_operand_lossage (msgid, x); \ | |
72 | return; \ | |
73 | } while (0) | |
74 | ||
75 | /* Worker function for TARGET_RETURN_IN_MEMORY. */ | |
76 | ||
77 | static bool | |
78 | moxie_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) | |
79 | { | |
80 | const HOST_WIDE_INT size = int_size_in_bytes (type); | |
81 | return (size == -1 || size > 2 * UNITS_PER_WORD); | |
82 | } | |
83 | ||
84 | /* Define how to find the value returned by a function. | |
85 | VALTYPE is the data type of the value (as a tree). | |
86 | If the precise function being called is known, FUNC is its | |
87 | FUNCTION_DECL; otherwise, FUNC is 0. | |
88 | ||
89 | We always return values in register $r0 for moxie. */ | |
90 | ||
feab9982 | 91 | static rtx |
9fb374d6 AG |
92 | moxie_function_value (const_tree valtype, |
93 | const_tree fntype_or_decl ATTRIBUTE_UNUSED, | |
cceb575c AG |
94 | bool outgoing ATTRIBUTE_UNUSED) |
95 | { | |
96 | return gen_rtx_REG (TYPE_MODE (valtype), MOXIE_R0); | |
97 | } | |
98 | ||
feab9982 AS |
99 | /* Define how to find the value returned by a library function. |
100 | ||
101 | We always return values in register $r0 for moxie. */ | |
102 | ||
103 | static rtx | |
ef4bddc2 | 104 | moxie_libcall_value (machine_mode mode, |
feab9982 AS |
105 | const_rtx fun ATTRIBUTE_UNUSED) |
106 | { | |
107 | return gen_rtx_REG (mode, MOXIE_R0); | |
108 | } | |
109 | ||
110 | /* Handle TARGET_FUNCTION_VALUE_REGNO_P. | |
111 | ||
112 | We always return values in register $r0 for moxie. */ | |
113 | ||
114 | static bool | |
115 | moxie_function_value_regno_p (const unsigned int regno) | |
116 | { | |
117 | return (regno == MOXIE_R0); | |
118 | } | |
119 | ||
cceb575c AG |
120 | /* Emit an error message when we're in an asm, and a fatal error for |
121 | "normal" insns. Formatted output isn't easily implemented, since we | |
122 | use output_operand_lossage to output the actual message and handle the | |
123 | categorization of the error. */ | |
124 | ||
125 | static void | |
126 | moxie_operand_lossage (const char *msgid, rtx op) | |
127 | { | |
128 | debug_rtx (op); | |
129 | output_operand_lossage ("%s", msgid); | |
130 | } | |
131 | ||
132 | /* The PRINT_OPERAND_ADDRESS worker. */ | |
133 | ||
134 | void | |
135 | moxie_print_operand_address (FILE *file, rtx x) | |
136 | { | |
137 | switch (GET_CODE (x)) | |
138 | { | |
139 | case REG: | |
140 | fprintf (file, "(%s)", reg_names[REGNO (x)]); | |
141 | break; | |
142 | ||
143 | case PLUS: | |
144 | switch (GET_CODE (XEXP (x, 1))) | |
145 | { | |
146 | case CONST_INT: | |
147 | fprintf (file, "%ld(%s)", | |
148 | INTVAL(XEXP (x, 1)), reg_names[REGNO (XEXP (x, 0))]); | |
149 | break; | |
150 | case SYMBOL_REF: | |
151 | output_addr_const (file, XEXP (x, 1)); | |
152 | fprintf (file, "(%s)", reg_names[REGNO (XEXP (x, 0))]); | |
153 | break; | |
154 | case CONST: | |
155 | { | |
156 | rtx plus = XEXP (XEXP (x, 1), 0); | |
157 | if (GET_CODE (XEXP (plus, 0)) == SYMBOL_REF | |
158 | && CONST_INT_P (XEXP (plus, 1))) | |
159 | { | |
160 | output_addr_const(file, XEXP (plus, 0)); | |
161 | fprintf (file,"+%ld(%s)", INTVAL (XEXP (plus, 1)), | |
162 | reg_names[REGNO (XEXP (x, 0))]); | |
163 | } | |
164 | else | |
165 | abort(); | |
166 | } | |
167 | break; | |
168 | default: | |
169 | abort(); | |
170 | } | |
171 | break; | |
172 | ||
173 | default: | |
174 | output_addr_const (file, x); | |
175 | break; | |
176 | } | |
177 | } | |
178 | ||
179 | /* The PRINT_OPERAND worker. */ | |
180 | ||
181 | void | |
182 | moxie_print_operand (FILE *file, rtx x, int code) | |
183 | { | |
184 | rtx operand = x; | |
185 | ||
186 | /* New code entries should just be added to the switch below. If | |
187 | handling is finished, just return. If handling was just a | |
188 | modification of the operand, the modified operand should be put in | |
189 | "operand", and then do a break to let default handling | |
190 | (zero-modifier) output the operand. */ | |
191 | ||
192 | switch (code) | |
193 | { | |
194 | case 0: | |
195 | /* No code, print as usual. */ | |
196 | break; | |
197 | ||
198 | default: | |
199 | LOSE_AND_RETURN ("invalid operand modifier letter", x); | |
200 | } | |
201 | ||
202 | /* Print an operand as without a modifier letter. */ | |
203 | switch (GET_CODE (operand)) | |
204 | { | |
205 | case REG: | |
206 | if (REGNO (operand) > MOXIE_R13) | |
207 | internal_error ("internal error: bad register: %d", REGNO (operand)); | |
208 | fprintf (file, "%s", reg_names[REGNO (operand)]); | |
209 | return; | |
210 | ||
211 | case MEM: | |
212 | output_address (XEXP (operand, 0)); | |
213 | return; | |
214 | ||
215 | default: | |
216 | /* No need to handle all strange variants, let output_addr_const | |
217 | do it for us. */ | |
218 | if (CONSTANT_P (operand)) | |
219 | { | |
220 | output_addr_const (file, operand); | |
221 | return; | |
222 | } | |
223 | ||
224 | LOSE_AND_RETURN ("unexpected operand", x); | |
225 | } | |
226 | } | |
227 | ||
228 | /* Per-function machine data. */ | |
229 | struct GTY(()) machine_function | |
230 | { | |
231 | /* Number of bytes saved on the stack for callee saved registers. */ | |
232 | int callee_saved_reg_size; | |
233 | ||
234 | /* Number of bytes saved on the stack for local variables. */ | |
235 | int local_vars_size; | |
236 | ||
237 | /* The sum of 2 sizes: locals vars and padding byte for saving the | |
238 | * registers. Used in expand_prologue () and expand_epilogue(). */ | |
239 | int size_for_adjusting_sp; | |
240 | }; | |
241 | ||
242 | /* Zero initialization is OK for all current fields. */ | |
243 | ||
244 | static struct machine_function * | |
245 | moxie_init_machine_status (void) | |
246 | { | |
766090c2 | 247 | return ggc_cleared_alloc<machine_function> (); |
cceb575c AG |
248 | } |
249 | ||
250 | ||
c5387660 | 251 | /* The TARGET_OPTION_OVERRIDE worker. |
cceb575c | 252 | All this curently does is set init_machine_status. */ |
c5387660 JM |
253 | static void |
254 | moxie_option_override (void) | |
cceb575c AG |
255 | { |
256 | /* Set the per-function-data initializer. */ | |
257 | init_machine_status = moxie_init_machine_status; | |
258 | } | |
259 | ||
260 | /* Compute the size of the local area and the size to be adjusted by the | |
261 | * prologue and epilogue. */ | |
262 | ||
263 | static void | |
264 | moxie_compute_frame (void) | |
265 | { | |
266 | /* For aligning the local variables. */ | |
267 | int stack_alignment = STACK_BOUNDARY / BITS_PER_UNIT; | |
268 | int padding_locals; | |
269 | int regno; | |
270 | ||
271 | /* Padding needed for each element of the frame. */ | |
272 | cfun->machine->local_vars_size = get_frame_size (); | |
273 | ||
274 | /* Align to the stack alignment. */ | |
275 | padding_locals = cfun->machine->local_vars_size % stack_alignment; | |
276 | if (padding_locals) | |
277 | padding_locals = stack_alignment - padding_locals; | |
278 | ||
279 | cfun->machine->local_vars_size += padding_locals; | |
280 | ||
281 | cfun->machine->callee_saved_reg_size = 0; | |
282 | ||
283 | /* Save callee-saved registers. */ | |
284 | for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) | |
285 | if (df_regs_ever_live_p (regno) && (! call_used_regs[regno])) | |
286 | cfun->machine->callee_saved_reg_size += 4; | |
287 | ||
288 | cfun->machine->size_for_adjusting_sp = | |
289 | crtl->args.pretend_args_size | |
290 | + cfun->machine->local_vars_size | |
291 | + (ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0); | |
292 | } | |
293 | ||
294 | void | |
295 | moxie_expand_prologue (void) | |
296 | { | |
297 | int regno; | |
298 | rtx insn; | |
299 | ||
300 | moxie_compute_frame (); | |
301 | ||
650ae806 AG |
302 | if (flag_stack_usage_info) |
303 | current_function_static_stack_size = cfun->machine->size_for_adjusting_sp; | |
304 | ||
cceb575c AG |
305 | /* Save callee-saved registers. */ |
306 | for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) | |
307 | { | |
308 | if (!fixed_regs[regno] && df_regs_ever_live_p (regno) && !call_used_regs[regno]) | |
309 | { | |
310 | insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno))); | |
311 | RTX_FRAME_RELATED_P (insn) = 1; | |
312 | } | |
313 | } | |
314 | ||
315 | if (cfun->machine->size_for_adjusting_sp > 0) | |
316 | { | |
55a51460 AG |
317 | int i = cfun->machine->size_for_adjusting_sp; |
318 | while ((i >= 255) && (i <= 510)) | |
9df748c0 AG |
319 | { |
320 | insn = emit_insn (gen_subsi3 (stack_pointer_rtx, | |
321 | stack_pointer_rtx, | |
75cd1c8f | 322 | GEN_INT (255))); |
9df748c0 | 323 | RTX_FRAME_RELATED_P (insn) = 1; |
75cd1c8f | 324 | i -= 255; |
9df748c0 | 325 | } |
55a51460 | 326 | if (i <= 255) |
9df748c0 | 327 | { |
75cd1c8f | 328 | insn = emit_insn (gen_subsi3 (stack_pointer_rtx, |
9df748c0 | 329 | stack_pointer_rtx, |
75cd1c8f | 330 | GEN_INT (i))); |
9df748c0 | 331 | RTX_FRAME_RELATED_P (insn) = 1; |
75cd1c8f | 332 | } |
55a51460 AG |
333 | else |
334 | { | |
335 | rtx reg = gen_rtx_REG (SImode, MOXIE_R12); | |
336 | insn = emit_move_insn (reg, GEN_INT (i)); | |
337 | RTX_FRAME_RELATED_P (insn) = 1; | |
338 | insn = emit_insn (gen_subsi3 (stack_pointer_rtx, | |
339 | stack_pointer_rtx, | |
340 | reg)); | |
341 | RTX_FRAME_RELATED_P (insn) = 1; | |
342 | } | |
cceb575c AG |
343 | } |
344 | } | |
345 | ||
346 | void | |
347 | moxie_expand_epilogue (void) | |
348 | { | |
349 | int regno; | |
a8ea9484 | 350 | rtx reg; |
cceb575c AG |
351 | |
352 | if (cfun->machine->callee_saved_reg_size != 0) | |
353 | { | |
55a51460 | 354 | reg = gen_rtx_REG (Pmode, MOXIE_R12); |
9df748c0 AG |
355 | if (cfun->machine->callee_saved_reg_size <= 255) |
356 | { | |
357 | emit_move_insn (reg, hard_frame_pointer_rtx); | |
358 | emit_insn (gen_subsi3 | |
359 | (reg, reg, | |
360 | GEN_INT (cfun->machine->callee_saved_reg_size))); | |
361 | } | |
362 | else | |
363 | { | |
364 | emit_move_insn (reg, | |
365 | GEN_INT (-cfun->machine->callee_saved_reg_size)); | |
366 | emit_insn (gen_addsi3 (reg, reg, hard_frame_pointer_rtx)); | |
367 | } | |
cceb575c AG |
368 | for (regno = FIRST_PSEUDO_REGISTER; regno-- > 0; ) |
369 | if (!fixed_regs[regno] && !call_used_regs[regno] | |
370 | && df_regs_ever_live_p (regno)) | |
371 | { | |
9df748c0 | 372 | rtx preg = gen_rtx_REG (Pmode, regno); |
a8ea9484 | 373 | emit_insn (gen_movsi_pop (reg, preg)); |
cceb575c AG |
374 | } |
375 | } | |
376 | ||
377 | emit_jump_insn (gen_returner ()); | |
378 | } | |
379 | ||
380 | /* Implements the macro INITIAL_ELIMINATION_OFFSET, return the OFFSET. */ | |
381 | ||
382 | int | |
383 | moxie_initial_elimination_offset (int from, int to) | |
384 | { | |
385 | int ret; | |
386 | ||
387 | if ((from) == FRAME_POINTER_REGNUM && (to) == HARD_FRAME_POINTER_REGNUM) | |
388 | { | |
389 | /* Compute this since we need to use cfun->machine->local_vars_size. */ | |
390 | moxie_compute_frame (); | |
391 | ret = -cfun->machine->callee_saved_reg_size; | |
392 | } | |
393 | else if ((from) == ARG_POINTER_REGNUM && (to) == HARD_FRAME_POINTER_REGNUM) | |
394 | ret = 0x00; | |
395 | else | |
396 | abort (); | |
397 | ||
398 | return ret; | |
399 | } | |
400 | ||
401 | /* Worker function for TARGET_SETUP_INCOMING_VARARGS. */ | |
402 | ||
403 | static void | |
d5cc9181 | 404 | moxie_setup_incoming_varargs (cumulative_args_t cum_v, |
ef4bddc2 | 405 | machine_mode mode ATTRIBUTE_UNUSED, |
cceb575c AG |
406 | tree type ATTRIBUTE_UNUSED, |
407 | int *pretend_size, int no_rtl) | |
408 | { | |
d5cc9181 | 409 | CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); |
cceb575c | 410 | int regno; |
75cd1c8f | 411 | int regs = 8 - *cum; |
cceb575c AG |
412 | |
413 | *pretend_size = regs < 0 ? 0 : GET_MODE_SIZE (SImode) * regs; | |
414 | ||
415 | if (no_rtl) | |
416 | return; | |
417 | ||
75cd1c8f | 418 | for (regno = *cum; regno < 8; regno++) |
cceb575c AG |
419 | { |
420 | rtx reg = gen_rtx_REG (SImode, regno); | |
421 | rtx slot = gen_rtx_PLUS (Pmode, | |
422 | gen_rtx_REG (SImode, ARG_POINTER_REGNUM), | |
423 | GEN_INT (UNITS_PER_WORD * (3 + (regno-2)))); | |
424 | ||
425 | emit_move_insn (gen_rtx_MEM (SImode, slot), reg); | |
426 | } | |
427 | } | |
428 | ||
429 | ||
430 | /* Return the fixed registers used for condition codes. */ | |
431 | ||
432 | static bool | |
433 | moxie_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2) | |
434 | { | |
435 | *p1 = CC_REG; | |
436 | *p2 = INVALID_REGNUM; | |
437 | return true; | |
438 | } | |
439 | ||
440 | /* Return the next register to be used to hold a function argument or | |
441 | NULL_RTX if there's no more space. */ | |
442 | ||
4c05cbb2 | 443 | static rtx |
ef4bddc2 | 444 | moxie_function_arg (cumulative_args_t cum_v, machine_mode mode, |
4c05cbb2 NF |
445 | const_tree type ATTRIBUTE_UNUSED, |
446 | bool named ATTRIBUTE_UNUSED) | |
cceb575c | 447 | { |
d5cc9181 JR |
448 | CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); |
449 | ||
4c05cbb2 NF |
450 | if (*cum < 8) |
451 | return gen_rtx_REG (mode, *cum); | |
cceb575c AG |
452 | else |
453 | return NULL_RTX; | |
454 | } | |
455 | ||
4c05cbb2 NF |
456 | #define MOXIE_FUNCTION_ARG_SIZE(MODE, TYPE) \ |
457 | ((MODE) != BLKmode ? GET_MODE_SIZE (MODE) \ | |
458 | : (unsigned) int_size_in_bytes (TYPE)) | |
459 | ||
460 | static void | |
ef4bddc2 | 461 | moxie_function_arg_advance (cumulative_args_t cum_v, machine_mode mode, |
4c05cbb2 NF |
462 | const_tree type, bool named ATTRIBUTE_UNUSED) |
463 | { | |
d5cc9181 JR |
464 | CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); |
465 | ||
4c05cbb2 NF |
466 | *cum = (*cum < MOXIE_R6 |
467 | ? *cum + ((3 + MOXIE_FUNCTION_ARG_SIZE (mode, type)) / 4) | |
468 | : *cum); | |
469 | } | |
470 | ||
cceb575c AG |
471 | /* Return non-zero if the function argument described by TYPE is to be |
472 | passed by reference. */ | |
473 | ||
474 | static bool | |
d5cc9181 | 475 | moxie_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED, |
ef4bddc2 | 476 | machine_mode mode, const_tree type, |
cceb575c AG |
477 | bool named ATTRIBUTE_UNUSED) |
478 | { | |
479 | unsigned HOST_WIDE_INT size; | |
480 | ||
481 | if (type) | |
482 | { | |
483 | if (AGGREGATE_TYPE_P (type)) | |
484 | return true; | |
485 | size = int_size_in_bytes (type); | |
486 | } | |
487 | else | |
488 | size = GET_MODE_SIZE (mode); | |
489 | ||
75cd1c8f | 490 | return size > 4*6; |
cceb575c AG |
491 | } |
492 | ||
493 | /* Some function arguments will only partially fit in the registers | |
494 | that hold arguments. Given a new arg, return the number of bytes | |
495 | that fit in argument passing registers. */ | |
496 | ||
497 | static int | |
d5cc9181 | 498 | moxie_arg_partial_bytes (cumulative_args_t cum_v, |
ef4bddc2 | 499 | machine_mode mode, |
cceb575c AG |
500 | tree type, bool named) |
501 | { | |
d5cc9181 | 502 | CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); |
cceb575c AG |
503 | int bytes_left, size; |
504 | ||
75cd1c8f | 505 | if (*cum >= 8) |
cceb575c AG |
506 | return 0; |
507 | ||
d5cc9181 | 508 | if (moxie_pass_by_reference (cum_v, mode, type, named)) |
cceb575c AG |
509 | size = 4; |
510 | else if (type) | |
511 | { | |
512 | if (AGGREGATE_TYPE_P (type)) | |
513 | return 0; | |
514 | size = int_size_in_bytes (type); | |
515 | } | |
516 | else | |
517 | size = GET_MODE_SIZE (mode); | |
518 | ||
75cd1c8f | 519 | bytes_left = (4 * 6) - ((*cum - 2) * 4); |
cceb575c AG |
520 | |
521 | if (size > bytes_left) | |
522 | return bytes_left; | |
523 | else | |
524 | return 0; | |
525 | } | |
526 | ||
4601494d RH |
527 | /* Worker function for TARGET_STATIC_CHAIN. */ |
528 | ||
529 | static rtx | |
530 | moxie_static_chain (const_tree fndecl, bool incoming_p) | |
531 | { | |
532 | rtx addr, mem; | |
533 | ||
9f62cb92 | 534 | if (!DECL_STATIC_CHAIN (fndecl)) |
4601494d RH |
535 | return NULL; |
536 | ||
537 | if (incoming_p) | |
0a81f074 | 538 | addr = plus_constant (Pmode, arg_pointer_rtx, 2 * UNITS_PER_WORD); |
4601494d | 539 | else |
0a81f074 | 540 | addr = plus_constant (Pmode, stack_pointer_rtx, -UNITS_PER_WORD); |
4601494d RH |
541 | |
542 | mem = gen_rtx_MEM (Pmode, addr); | |
543 | MEM_NOTRAP_P (mem) = 1; | |
544 | ||
545 | return mem; | |
546 | } | |
547 | ||
548 | /* Worker function for TARGET_ASM_TRAMPOLINE_TEMPLATE. */ | |
549 | ||
550 | static void | |
551 | moxie_asm_trampoline_template (FILE *f) | |
552 | { | |
553 | fprintf (f, "\tpush $sp, $r0\n"); | |
554 | fprintf (f, "\tldi.l $r0, 0x0\n"); | |
555 | fprintf (f, "\tsto.l 0x8($fp), $r0\n"); | |
556 | fprintf (f, "\tpop $sp, $r0\n"); | |
693ee8cf | 557 | fprintf (f, "\tnop\n"); |
4601494d RH |
558 | fprintf (f, "\tjmpa 0x0\n"); |
559 | } | |
560 | ||
561 | /* Worker function for TARGET_TRAMPOLINE_INIT. */ | |
562 | ||
563 | static void | |
564 | moxie_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) | |
565 | { | |
566 | rtx mem, fnaddr = XEXP (DECL_RTL (fndecl), 0); | |
567 | ||
568 | emit_block_move (m_tramp, assemble_trampoline_template (), | |
569 | GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL); | |
570 | ||
571 | mem = adjust_address (m_tramp, SImode, 4); | |
572 | emit_move_insn (mem, chain_value); | |
693ee8cf | 573 | mem = adjust_address (m_tramp, SImode, 20); |
4601494d RH |
574 | emit_move_insn (mem, fnaddr); |
575 | } | |
576 | ||
cceb575c AG |
577 | /* The Global `targetm' Variable. */ |
578 | ||
579 | /* Initialize the GCC target structure. */ | |
580 | ||
581 | #undef TARGET_PROMOTE_PROTOTYPES | |
582 | #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true | |
583 | ||
584 | #undef TARGET_RETURN_IN_MEMORY | |
585 | #define TARGET_RETURN_IN_MEMORY moxie_return_in_memory | |
586 | #undef TARGET_MUST_PASS_IN_STACK | |
587 | #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size | |
588 | #undef TARGET_PASS_BY_REFERENCE | |
589 | #define TARGET_PASS_BY_REFERENCE moxie_pass_by_reference | |
590 | #undef TARGET_ARG_PARTIAL_BYTES | |
591 | #define TARGET_ARG_PARTIAL_BYTES moxie_arg_partial_bytes | |
4c05cbb2 NF |
592 | #undef TARGET_FUNCTION_ARG |
593 | #define TARGET_FUNCTION_ARG moxie_function_arg | |
594 | #undef TARGET_FUNCTION_ARG_ADVANCE | |
595 | #define TARGET_FUNCTION_ARG_ADVANCE moxie_function_arg_advance | |
cceb575c AG |
596 | |
597 | ||
598 | #undef TARGET_SETUP_INCOMING_VARARGS | |
599 | #define TARGET_SETUP_INCOMING_VARARGS moxie_setup_incoming_varargs | |
600 | ||
601 | #undef TARGET_FIXED_CONDITION_CODE_REGS | |
602 | #define TARGET_FIXED_CONDITION_CODE_REGS moxie_fixed_condition_code_regs | |
603 | ||
604 | /* Define this to return an RTX representing the place where a | |
605 | function returns or receives a value of data type RET_TYPE, a tree | |
606 | node node representing a data type. */ | |
607 | #undef TARGET_FUNCTION_VALUE | |
608 | #define TARGET_FUNCTION_VALUE moxie_function_value | |
feab9982 AS |
609 | #undef TARGET_LIBCALL_VALUE |
610 | #define TARGET_LIBCALL_VALUE moxie_libcall_value | |
611 | #undef TARGET_FUNCTION_VALUE_REGNO_P | |
612 | #define TARGET_FUNCTION_VALUE_REGNO_P moxie_function_value_regno_p | |
cceb575c | 613 | |
b52b1749 AS |
614 | #undef TARGET_FRAME_POINTER_REQUIRED |
615 | #define TARGET_FRAME_POINTER_REQUIRED hook_bool_void_true | |
616 | ||
4601494d RH |
617 | #undef TARGET_STATIC_CHAIN |
618 | #define TARGET_STATIC_CHAIN moxie_static_chain | |
619 | #undef TARGET_ASM_TRAMPOLINE_TEMPLATE | |
620 | #define TARGET_ASM_TRAMPOLINE_TEMPLATE moxie_asm_trampoline_template | |
621 | #undef TARGET_TRAMPOLINE_INIT | |
622 | #define TARGET_TRAMPOLINE_INIT moxie_trampoline_init | |
623 | ||
c5387660 JM |
624 | #undef TARGET_OPTION_OVERRIDE |
625 | #define TARGET_OPTION_OVERRIDE moxie_option_override | |
626 | ||
cceb575c AG |
627 | struct gcc_target targetm = TARGET_INITIALIZER; |
628 | ||
629 | #include "gt-moxie.h" |