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