1 /* FR30 specific functions.
2 Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3 Contributed by Cygnus Solutions.
4
5 This file is part of GNU CC.
6
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 /*{{{ Includes */
23
24 #include "config.h"
25 #include "system.h"
26 #include "rtl.h"
27 #include "regs.h"
28 #include "hard-reg-set.h"
29 #include "real.h"
30 #include "insn-config.h"
31 #include "conditions.h"
32 #include "insn-attr.h"
33 #include "flags.h"
34 #include "recog.h"
35 #include "tree.h"
36 #include "output.h"
37 #include "expr.h"
38 #include "obstack.h"
39 #include "except.h"
40 #include "function.h"
41 #include "tm_p.h"
42 #include "target.h"
43 #include "target-def.h"
44
45 /*}}}*/
46 /*{{{ Function Prologues & Epilogues */
47
48 /* Define the information needed to generate branch and scc insns. This is
49 stored from the compare operation. */
50
51 struct rtx_def * fr30_compare_op0;
52 struct rtx_def * fr30_compare_op1;
53
54 /* The FR30 stack looks like this:
55
56 Before call After call
57 FP ->| | | |
58 +-----------------------+ +-----------------------+ high
59 | | | | memory
60 | local variables, | | local variables, |
61 | reg save area, etc. | | reg save area, etc. |
62 | | | |
63 +-----------------------+ +-----------------------+
64 | | | |
65 | args to the func that | | args to this func. |
66 | is being called that | | |
67 SP ->| do not fit in regs | | |
68 +-----------------------+ +-----------------------+
69 | args that used to be | \
70 | in regs; only created | | pretend_size
71 AP-> | for vararg funcs | /
72 +-----------------------+
73 | | \
74 | register save area | |
75 | | |
76 +-----------------------+ | reg_size
77 | return address | |
78 +-----------------------+ |
79 FP ->| previous frame ptr | /
80 +-----------------------+
81 | | \
82 | local variables | | var_size
83 | | /
84 +-----------------------+
85 | | \
86 low | room for args to | |
87 memory | other funcs called | | args_size
88 | from this one | |
89 SP ->| | /
90 +-----------------------+
91
92 Note, AP is a fake hard register. It will be eliminated in favor of
93 SP or FP as appropriate.
94
95 Note, Some or all of the stack sections above may be omitted if they
96 are not needed. */
97
98 /* Structure to be filled in by fr30_compute_frame_size() with register
99 save masks, and offsets for the current function. */
100 struct fr30_frame_info
101 {
102 unsigned int total_size; /* # Bytes that the entire frame takes up. */
103 unsigned int pretend_size; /* # Bytes we push and pretend caller did. */
104 unsigned int args_size; /* # Bytes that outgoing arguments take up. */
105 unsigned int reg_size; /* # Bytes needed to store regs. */
106 unsigned int var_size; /* # Bytes that variables take up. */
107 unsigned int frame_size; /* # Bytes in current frame. */
108 unsigned int gmask; /* Mask of saved registers. */
109 unsigned int save_fp; /* Nonzero if frame pointer must be saved. */
110 unsigned int save_rp; /* Nonzero if return popinter must be saved. */
111 int initialised; /* Nonzero if frame size already calculated. */
112 };
113
114 /* Current frame information calculated by fr30_compute_frame_size(). */
115 static struct fr30_frame_info current_frame_info;
116
117 /* Zero structure to initialize current_frame_info. */
118 static struct fr30_frame_info zero_frame_info;
119
120 static rtx fr30_pass_by_reference PARAMS ((tree, tree));
121 static rtx fr30_pass_by_value PARAMS ((tree, tree));
122
123 #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
124 #define RETURN_POINTER_MASK (1 << (RETURN_POINTER_REGNUM))
125
126 /* Tell prologue and epilogue if register REGNO should be saved / restored.
127 The return address and frame pointer are treated separately.
128 Don't consider them here. */
129 #define MUST_SAVE_REGISTER(regno) \
130 ( (regno) != RETURN_POINTER_REGNUM \
131 && (regno) != FRAME_POINTER_REGNUM \
132 && regs_ever_live [regno] \
133 && ! call_used_regs [regno] )
134
135 #define MUST_SAVE_FRAME_POINTER (regs_ever_live [FRAME_POINTER_REGNUM] || frame_pointer_needed)
136 #define MUST_SAVE_RETURN_POINTER (regs_ever_live [RETURN_POINTER_REGNUM] || current_function_profile)
137
138 #if UNITS_PER_WORD == 4
139 #define WORD_ALIGN(SIZE) (((SIZE) + 3) & ~3)
140 #endif
141
142 /* Initialize the GCC target structure. */
143 #undef TARGET_ASM_ALIGNED_HI_OP
144 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
145 #undef TARGET_ASM_ALIGNED_SI_OP
146 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
147
148 struct gcc_target targetm = TARGET_INITIALIZER;
149
150 /* Returns the number of bytes offset between FROM_REG and TO_REG
151 for the current function. As a side effect it fills in the
152 current_frame_info structure, if the data is available. */
153 unsigned int
fr30_compute_frame_size(from_reg,to_reg)154 fr30_compute_frame_size (from_reg, to_reg)
155 int from_reg;
156 int to_reg;
157 {
158 int regno;
159 unsigned int return_value;
160 unsigned int var_size;
161 unsigned int args_size;
162 unsigned int pretend_size;
163 unsigned int reg_size;
164 unsigned int gmask;
165
166 var_size = WORD_ALIGN (get_frame_size ());
167 args_size = WORD_ALIGN (current_function_outgoing_args_size);
168 pretend_size = current_function_pretend_args_size;
169
170 reg_size = 0;
171 gmask = 0;
172
173 /* Calculate space needed for registers. */
174 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno ++)
175 {
176 if (MUST_SAVE_REGISTER (regno))
177 {
178 reg_size += UNITS_PER_WORD;
179 gmask |= 1 << regno;
180 }
181 }
182
183 current_frame_info.save_fp = MUST_SAVE_FRAME_POINTER;
184 current_frame_info.save_rp = MUST_SAVE_RETURN_POINTER;
185
186 reg_size += (current_frame_info.save_fp + current_frame_info.save_rp)
187 * UNITS_PER_WORD;
188
189 /* Save computed information. */
190 current_frame_info.pretend_size = pretend_size;
191 current_frame_info.var_size = var_size;
192 current_frame_info.args_size = args_size;
193 current_frame_info.reg_size = reg_size;
194 current_frame_info.frame_size = args_size + var_size;
195 current_frame_info.total_size = args_size + var_size + reg_size + pretend_size;
196 current_frame_info.gmask = gmask;
197 current_frame_info.initialised = reload_completed;
198
199 /* Calculate the required distance. */
200 return_value = 0;
201
202 if (to_reg == STACK_POINTER_REGNUM)
203 return_value += args_size + var_size;
204
205 if (from_reg == ARG_POINTER_REGNUM)
206 return_value += reg_size;
207
208 return return_value;
209 }
210
211 /* Called after register allocation to add any instructions needed for the
212 prologue. Using a prologue insn is favored compared to putting all of the
213 instructions in output_function_prologue(), since it allows the scheduler
214 to intermix instructions with the saves of the caller saved registers. In
215 some cases, it might be necessary to emit a barrier instruction as the last
216 insn to prevent such scheduling. */
217
218 void
fr30_expand_prologue()219 fr30_expand_prologue ()
220 {
221 int regno;
222 rtx insn;
223
224 if (! current_frame_info.initialised)
225 fr30_compute_frame_size (0, 0);
226
227 /* This cases shouldn't happen. Catch it now. */
228 if (current_frame_info.total_size == 0
229 && current_frame_info.gmask)
230 abort ();
231
232 /* Allocate space for register arguments if this is a variadic function. */
233 if (current_frame_info.pretend_size)
234 {
235 int regs_to_save = current_frame_info.pretend_size / UNITS_PER_WORD;
236
237 /* Push argument registers into the pretend arg area. */
238 for (regno = FIRST_ARG_REGNUM + FR30_NUM_ARG_REGS; regno --, regs_to_save --;)
239 {
240 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno)));
241 RTX_FRAME_RELATED_P (insn) = 1;
242 }
243 }
244
245 if (current_frame_info.gmask)
246 {
247 /* Save any needed call-saved regs. */
248 for (regno = STACK_POINTER_REGNUM; regno--;)
249 {
250 if ((current_frame_info.gmask & (1 << regno)) != 0)
251 {
252 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode, regno)));
253 RTX_FRAME_RELATED_P (insn) = 1;
254 }
255 }
256 }
257
258 /* Save return address if necessary. */
259 if (current_frame_info.save_rp)
260 {
261 insn = emit_insn (gen_movsi_push (gen_rtx_REG (Pmode,
262 RETURN_POINTER_REGNUM)));
263 RTX_FRAME_RELATED_P (insn) = 1;
264 }
265
266 /* Save old frame pointer and create new one, if necessary. */
267 if (current_frame_info.save_fp)
268 {
269 if (current_frame_info.frame_size < ((1 << 10) - UNITS_PER_WORD))
270 {
271 int enter_size = current_frame_info.frame_size + UNITS_PER_WORD;
272 rtx pattern;
273
274 insn = emit_insn (gen_enter_func (GEN_INT (enter_size)));
275 RTX_FRAME_RELATED_P (insn) = 1;
276
277 pattern = PATTERN (insn);
278
279 /* Also mark all 3 subexpressions as RTX_FRAME_RELATED_P. */
280 if (GET_CODE (pattern) == PARALLEL)
281 {
282 int x;
283 for (x = XVECLEN (pattern, 0); x--;)
284 {
285 rtx part = XVECEXP (pattern, 0, x);
286
287 /* One of the insns in the ENTER pattern updates the
288 frame pointer. If we do not actually need the frame
289 pointer in this function then this is a side effect
290 rather than a desired effect, so we do not mark that
291 insn as being related to the frame set up. Doing this
292 allows us to compile the crash66.C test file in the
293 G++ testsuite. */
294 if (! frame_pointer_needed
295 && GET_CODE (part) == SET
296 && REGNO (SET_DEST (part)) == HARD_FRAME_POINTER_REGNUM)
297 RTX_FRAME_RELATED_P (part) = 0;
298 else
299 RTX_FRAME_RELATED_P (part) = 1;
300 }
301 }
302 }
303 else
304 {
305 insn = emit_insn (gen_movsi_push (frame_pointer_rtx));
306 RTX_FRAME_RELATED_P (insn) = 1;
307
308 if (frame_pointer_needed)
309 {
310 insn = emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
311 RTX_FRAME_RELATED_P (insn) = 1;
312 }
313 }
314 }
315
316 /* Allocate the stack frame. */
317 if (current_frame_info.frame_size == 0)
318 ; /* Nothing to do. */
319 else if (current_frame_info.save_fp
320 && current_frame_info.frame_size < ((1 << 10) - UNITS_PER_WORD))
321 ; /* Nothing to do. */
322 else if (current_frame_info.frame_size <= 512)
323 {
324 insn = emit_insn (gen_add_to_stack (GEN_INT (- current_frame_info.frame_size)));
325 RTX_FRAME_RELATED_P (insn) = 1;
326 }
327 else
328 {
329 rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
330 insn = emit_insn (gen_movsi (tmp, GEN_INT (current_frame_info.frame_size)));
331 RTX_FRAME_RELATED_P (insn) = 1;
332 insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
333 RTX_FRAME_RELATED_P (insn) = 1;
334 }
335
336 if (current_function_profile)
337 emit_insn (gen_blockage ());
338 }
339
340 /* Called after register allocation to add any instructions needed for the
341 epilogue. Using an epilogue insn is favored compared to putting all of the
342 instructions in output_function_epilogue(), since it allows the scheduler
343 to intermix instructions with the restores of the caller saved registers.
344 In some cases, it might be necessary to emit a barrier instruction as the
345 first insn to prevent such scheduling. */
346 void
fr30_expand_epilogue()347 fr30_expand_epilogue ()
348 {
349 int regno;
350
351 /* Perform the inversion operations of the prologue. */
352 if (! current_frame_info.initialised)
353 abort ();
354
355 /* Pop local variables and arguments off the stack.
356 If frame_pointer_needed is TRUE then the frame pointer register
357 has actually been used as a frame pointer, and we can recover
358 the stack pointer from it, otherwise we must unwind the stack
359 manually. */
360 if (current_frame_info.frame_size > 0)
361 {
362 if (current_frame_info.save_fp && frame_pointer_needed)
363 {
364 emit_insn (gen_leave_func ());
365 current_frame_info.save_fp = 0;
366 }
367 else if (current_frame_info.frame_size <= 508)
368 emit_insn (gen_add_to_stack
369 (GEN_INT (current_frame_info.frame_size)));
370 else
371 {
372 rtx tmp = gen_rtx_REG (Pmode, PROLOGUE_TMP_REGNUM);
373 emit_insn (gen_movsi (tmp, GEN_INT (current_frame_info.frame_size)));
374 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, tmp));
375 }
376 }
377
378 if (current_frame_info.save_fp)
379 emit_insn (gen_movsi_pop (frame_pointer_rtx));
380
381 /* Pop all the registers that were pushed. */
382 if (current_frame_info.save_rp)
383 emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, RETURN_POINTER_REGNUM)));
384
385 for (regno = 0; regno < STACK_POINTER_REGNUM; regno ++)
386 if (current_frame_info.gmask & (1 << regno))
387 emit_insn (gen_movsi_pop (gen_rtx_REG (Pmode, regno)));
388
389 if (current_frame_info.pretend_size)
390 emit_insn (gen_add_to_stack (GEN_INT (current_frame_info.pretend_size)));
391
392 /* Reset state info for each function. */
393 current_frame_info = zero_frame_info;
394
395 emit_jump_insn (gen_return_from_func ());
396 }
397
398 /* Do any needed setup for a variadic function. We must create a register
399 parameter block, and then copy any anonymous arguments, plus the last
400 named argument, from registers into memory. * copying actually done in
401 fr30_expand_prologue().
402
403 ARG_REGS_USED_SO_FAR has *not* been updated for the last named argument
404 which has type TYPE and mode MODE, and we rely on this fact. */
405 void
fr30_setup_incoming_varargs(arg_regs_used_so_far,int_mode,type,pretend_size)406 fr30_setup_incoming_varargs (arg_regs_used_so_far, int_mode, type, pretend_size)
407 CUMULATIVE_ARGS arg_regs_used_so_far;
408 int int_mode;
409 tree type ATTRIBUTE_UNUSED;
410 int * pretend_size;
411 {
412 enum machine_mode mode = (enum machine_mode)int_mode;
413 int size;
414
415
416 /* All BLKmode values are passed by reference. */
417 if (mode == BLKmode)
418 abort ();
419
420 #if STRICT_ARGUMENT_NAMING
421 /* If STRICT_ARGUMENT_NAMING is true then the last named
422 arg must not be treated as an anonymous arg. */
423 arg_regs_used_so_far += fr30_num_arg_regs (int_mode, type);
424 #endif
425
426 size = FR30_NUM_ARG_REGS - arg_regs_used_so_far;
427
428 if (size <= 0)
429 return;
430
431 * pretend_size = (size * UNITS_PER_WORD);
432 }
433
434 /*}}}*/
435 /*{{{ Printing operands */
436
437 /* Print a memory address as an operand to reference that memory location. */
438
439 void
fr30_print_operand_address(stream,address)440 fr30_print_operand_address (stream, address)
441 FILE * stream;
442 rtx address;
443 {
444 switch (GET_CODE (address))
445 {
446 case SYMBOL_REF:
447 output_addr_const (stream, address);
448 break;
449
450 default:
451 fprintf (stderr, "code = %x\n", GET_CODE (address));
452 debug_rtx (address);
453 output_operand_lossage ("fr30_print_operand_address: unhandled address");
454 break;
455 }
456 }
457
458 /* Print an operand. */
459
460 void
fr30_print_operand(file,x,code)461 fr30_print_operand (file, x, code)
462 FILE * file;
463 rtx x;
464 int code;
465 {
466 rtx x0;
467
468 switch (code)
469 {
470 case '#':
471 /* Output a :D if this instruction is delayed. */
472 if (dbr_sequence_length () != 0)
473 fputs (":D", file);
474 return;
475
476 case 'p':
477 /* Compute the register name of the second register in a hi/lo
478 register pair. */
479 if (GET_CODE (x) != REG)
480 output_operand_lossage ("fr30_print_operand: unrecognized %%p code");
481 else
482 fprintf (file, "r%d", REGNO (x) + 1);
483 return;
484
485 case 'b':
486 /* Convert GCC's comparison operators into FR30 comparison codes. */
487 switch (GET_CODE (x))
488 {
489 case EQ: fprintf (file, "eq"); break;
490 case NE: fprintf (file, "ne"); break;
491 case LT: fprintf (file, "lt"); break;
492 case LE: fprintf (file, "le"); break;
493 case GT: fprintf (file, "gt"); break;
494 case GE: fprintf (file, "ge"); break;
495 case LTU: fprintf (file, "c"); break;
496 case LEU: fprintf (file, "ls"); break;
497 case GTU: fprintf (file, "hi"); break;
498 case GEU: fprintf (file, "nc"); break;
499 default:
500 output_operand_lossage ("fr30_print_operand: unrecognized %%b code");
501 break;
502 }
503 return;
504
505 case 'B':
506 /* Convert GCC's comparison operators into the complimentary FR30
507 comparison codes. */
508 switch (GET_CODE (x))
509 {
510 case EQ: fprintf (file, "ne"); break;
511 case NE: fprintf (file, "eq"); break;
512 case LT: fprintf (file, "ge"); break;
513 case LE: fprintf (file, "gt"); break;
514 case GT: fprintf (file, "le"); break;
515 case GE: fprintf (file, "lt"); break;
516 case LTU: fprintf (file, "nc"); break;
517 case LEU: fprintf (file, "hi"); break;
518 case GTU: fprintf (file, "ls"); break;
519 case GEU: fprintf (file, "c"); break;
520 default:
521 output_operand_lossage ("fr30_print_operand: unrecognized %%B code");
522 break;
523 }
524 return;
525
526 case 'A':
527 /* Print a signed byte value as an unsigned value. */
528 if (GET_CODE (x) != CONST_INT)
529 output_operand_lossage ("fr30_print_operand: invalid operand to %%A code");
530 else
531 {
532 HOST_WIDE_INT val;
533
534 val = INTVAL (x);
535
536 val &= 0xff;
537
538 fprintf (file, "%d", val);
539 }
540 return;
541
542 case 'x':
543 if (GET_CODE (x) != CONST_INT
544 || INTVAL (x) < 16
545 || INTVAL (x) > 32)
546 output_operand_lossage ("fr30_print_operand: invalid %%x code");
547 else
548 fprintf (file, "%d", INTVAL (x) - 16);
549 return;
550
551 case 'F':
552 if (GET_CODE (x) != CONST_DOUBLE)
553 output_operand_lossage ("fr30_print_operand: invalid %%F code");
554 else
555 {
556 char str[30];
557
558 real_to_decimal (str, CONST_DOUBLE_REAL_VALUE (x),
559 sizeof (str), 0, 1);
560 fputs (str, file);
561 }
562 return;
563
564 case 0:
565 /* Handled below. */
566 break;
567
568 default:
569 fprintf (stderr, "unknown code = %x\n", code);
570 output_operand_lossage ("fr30_print_operand: unknown code");
571 return;
572 }
573
574 switch (GET_CODE (x))
575 {
576 case REG:
577 fputs (reg_names [REGNO (x)], file);
578 break;
579
580 case MEM:
581 x0 = XEXP (x,0);
582
583 switch (GET_CODE (x0))
584 {
585 case REG:
586 if ((unsigned) REGNO (x0) >= ARRAY_SIZE (reg_names))
587 abort ();
588 fprintf (file, "@%s", reg_names [REGNO (x0)]);
589 break;
590
591 case PLUS:
592 if (GET_CODE (XEXP (x0, 0)) != REG
593 || REGNO (XEXP (x0, 0)) < FRAME_POINTER_REGNUM
594 || REGNO (XEXP (x0, 0)) > STACK_POINTER_REGNUM
595 || GET_CODE (XEXP (x0, 1)) != CONST_INT)
596 {
597 fprintf (stderr, "bad INDEXed address:");
598 debug_rtx (x);
599 output_operand_lossage ("fr30_print_operand: unhandled MEM");
600 }
601 else if (REGNO (XEXP (x0, 0)) == FRAME_POINTER_REGNUM)
602 {
603 HOST_WIDE_INT val = INTVAL (XEXP (x0, 1));
604 if (val < -(1 << 9) || val > ((1 << 9) - 4))
605 {
606 fprintf (stderr, "frame INDEX out of range:");
607 debug_rtx (x);
608 output_operand_lossage ("fr30_print_operand: unhandled MEM");
609 }
610 fprintf (file, "@(r14, #%d)", val);
611 }
612 else
613 {
614 HOST_WIDE_INT val = INTVAL (XEXP (x0, 1));
615 if (val < 0 || val > ((1 << 6) - 4))
616 {
617 fprintf (stderr, "stack INDEX out of range:");
618 debug_rtx (x);
619 output_operand_lossage ("fr30_print_operand: unhandled MEM");
620 }
621 fprintf (file, "@(r15, #%d)", val);
622 }
623 break;
624
625 case SYMBOL_REF:
626 output_address (x0);
627 break;
628
629 default:
630 fprintf (stderr, "bad MEM code = %x\n", GET_CODE (x0));
631 debug_rtx (x);
632 output_operand_lossage ("fr30_print_operand: unhandled MEM");
633 break;
634 }
635 break;
636
637 case CONST_DOUBLE :
638 /* We handle SFmode constants here as output_addr_const doesn't. */
639 if (GET_MODE (x) == SFmode)
640 {
641 REAL_VALUE_TYPE d;
642 long l;
643
644 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
645 REAL_VALUE_TO_TARGET_SINGLE (d, l);
646 fprintf (file, "0x%08lx", l);
647 break;
648 }
649
650 /* Fall through. Let output_addr_const deal with it. */
651 default:
652 output_addr_const (file, x);
653 break;
654 }
655
656 return;
657 }
658
659 /*}}}*/
660 /*{{{ Function arguments */
661
662 /* Compute the number of word sized registers needed to hold a
663 function argument of mode INT_MODE and tree type TYPE. */
664 int
fr30_num_arg_regs(int_mode,type)665 fr30_num_arg_regs (int_mode, type)
666 int int_mode;
667 tree type;
668 {
669 enum machine_mode mode = (enum machine_mode) int_mode;
670 int size;
671
672 if (MUST_PASS_IN_STACK (mode, type))
673 return 0;
674
675 if (type && mode == BLKmode)
676 size = int_size_in_bytes (type);
677 else
678 size = GET_MODE_SIZE (mode);
679
680 return (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
681 }
682
683 /* Implements the FUNCTION_ARG_PARTIAL_NREGS macro.
684 Returns the number of argument registers required to hold *part* of
685 a parameter of machine mode MODE and tree type TYPE (which may be
686 NULL if the type is not known). If the argument fits entirly in
687 the argument registers, or entirely on the stack, then 0 is returned.
688 CUM is the number of argument registers already used by earlier
689 parameters to the function. */
690
691 int
fr30_function_arg_partial_nregs(cum,int_mode,type,named)692 fr30_function_arg_partial_nregs (cum, int_mode, type, named)
693 CUMULATIVE_ARGS cum;
694 int int_mode;
695 tree type;
696 int named;
697 {
698 /* Unnamed arguments, ie those that are prototyped as ...
699 are always passed on the stack.
700 Also check here to see if all the argument registers are full. */
701 if (named == 0 || cum >= FR30_NUM_ARG_REGS)
702 return 0;
703
704 /* Work out how many argument registers would be needed if this
705 parameter were to be passed entirely in registers. If there
706 are sufficient argument registers available (or if no registers
707 are needed because the parameter must be passed on the stack)
708 then return zero, as this parameter does not require partial
709 register, partial stack stack space. */
710 if (cum + fr30_num_arg_regs (int_mode, type) <= FR30_NUM_ARG_REGS)
711 return 0;
712
713 /* Otherwise return the number of registers that would be used. */
714 return FR30_NUM_ARG_REGS - cum;
715 }
716
717 static rtx
fr30_pass_by_reference(valist,type)718 fr30_pass_by_reference (valist, type)
719 tree valist;
720 tree type;
721 {
722 tree type_ptr;
723 tree type_ptr_ptr;
724 tree t;
725
726 type_ptr = build_pointer_type (type);
727 type_ptr_ptr = build_pointer_type (type_ptr);
728
729 t = build (POSTINCREMENT_EXPR, va_list_type_node, valist, build_int_2 (UNITS_PER_WORD, 0));
730 TREE_SIDE_EFFECTS (t) = 1;
731 t = build1 (NOP_EXPR, type_ptr_ptr, t);
732 TREE_SIDE_EFFECTS (t) = 1;
733 t = build1 (INDIRECT_REF, type_ptr, t);
734
735 return expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
736 }
737
738 static rtx
fr30_pass_by_value(valist,type)739 fr30_pass_by_value (valist, type)
740 tree valist;
741 tree type;
742 {
743 HOST_WIDE_INT size = int_size_in_bytes (type);
744 HOST_WIDE_INT rsize;
745 rtx addr_rtx;
746 tree t;
747
748 if ((size % UNITS_PER_WORD) == 0)
749 {
750 t = build (POSTINCREMENT_EXPR, va_list_type_node, valist, build_int_2 (size, 0));
751 TREE_SIDE_EFFECTS (t) = 1;
752
753 return expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
754 }
755
756 rsize = (size + UNITS_PER_WORD - 1) & - UNITS_PER_WORD;
757
758 /* Care for bigendian correction on the aligned address. */
759 t = build (PLUS_EXPR, ptr_type_node, valist, build_int_2 (rsize - size, 0));
760 addr_rtx = expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
761 addr_rtx = copy_to_reg (addr_rtx);
762
763 /* Increment AP. */
764 t = build (PLUS_EXPR, va_list_type_node, valist, build_int_2 (rsize, 0));
765 t = build (MODIFY_EXPR, va_list_type_node, valist, t);
766 TREE_SIDE_EFFECTS (t) = 1;
767 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
768
769 return addr_rtx;
770 }
771
772 /* Implement `va_arg'. */
773
774 rtx
fr30_va_arg(valist,type)775 fr30_va_arg (valist, type)
776 tree valist;
777 tree type;
778 {
779 HOST_WIDE_INT size;
780
781 if (AGGREGATE_TYPE_P (type))
782 return fr30_pass_by_reference (valist, type);
783
784 size = int_size_in_bytes (type);
785
786 if ((size % sizeof (int)) == 0
787 || size < 4)
788 return fr30_pass_by_value (valist, type);
789
790 return fr30_pass_by_reference (valist, type);
791 }
792
793 /*}}}*/
794 /*{{{ Operand predicates */
795
796 #ifndef Mmode
797 #define Mmode enum machine_mode
798 #endif
799
800 /* Returns true if OPERAND is an integer value suitable for use in
801 an ADDSP instruction. */
802 int
stack_add_operand(operand,mode)803 stack_add_operand (operand, mode)
804 rtx operand;
805 Mmode mode ATTRIBUTE_UNUSED;
806 {
807 return
808 (GET_CODE (operand) == CONST_INT
809 && INTVAL (operand) >= -512
810 && INTVAL (operand) <= 508
811 && ((INTVAL (operand) & 3) == 0));
812 }
813
814 /* Returns true if OPERAND is an integer value suitable for use in
815 an ADD por ADD2 instruction, or if it is a register. */
816 int
add_immediate_operand(operand,mode)817 add_immediate_operand (operand, mode)
818 rtx operand;
819 Mmode mode ATTRIBUTE_UNUSED;
820 {
821 return
822 (GET_CODE (operand) == REG
823 || (GET_CODE (operand) == CONST_INT
824 && INTVAL (operand) >= -16
825 && INTVAL (operand) <= 15));
826 }
827
828 /* Returns true if OPERAND is hard register in the range 8 - 15. */
829 int
high_register_operand(operand,mode)830 high_register_operand (operand, mode)
831 rtx operand;
832 Mmode mode ATTRIBUTE_UNUSED;
833 {
834 return
835 (GET_CODE (operand) == REG
836 && REGNO (operand) <= 15
837 && REGNO (operand) >= 8);
838 }
839
840 /* Returns true if OPERAND is hard register in the range 0 - 7. */
841 int
low_register_operand(operand,mode)842 low_register_operand (operand, mode)
843 rtx operand;
844 Mmode mode ATTRIBUTE_UNUSED;
845 {
846 return
847 (GET_CODE (operand) == REG
848 && REGNO (operand) <= 7);
849 }
850
851 /* Returns true if OPERAND is suitable for use in a CALL insn. */
852 int
call_operand(operand,mode)853 call_operand (operand, mode)
854 rtx operand;
855 Mmode mode ATTRIBUTE_UNUSED;
856 {
857 return (GET_CODE (operand) == MEM
858 && (GET_CODE (XEXP (operand, 0)) == SYMBOL_REF
859 || GET_CODE (XEXP (operand, 0)) == REG));
860 }
861
862 /* Returns TRUE if OP is a valid operand of a DImode operation. */
863 int
di_operand(op,mode)864 di_operand (op, mode)
865 rtx op;
866 Mmode mode;
867 {
868 if (register_operand (op, mode))
869 return TRUE;
870
871 if (mode != VOIDmode && GET_MODE (op) != VOIDmode && GET_MODE (op) != DImode)
872 return FALSE;
873
874 if (GET_CODE (op) == SUBREG)
875 op = SUBREG_REG (op);
876
877 switch (GET_CODE (op))
878 {
879 case CONST_DOUBLE:
880 case CONST_INT:
881 return TRUE;
882
883 case MEM:
884 return memory_address_p (DImode, XEXP (op, 0));
885
886 default:
887 return FALSE;
888 }
889 }
890
891 /* Returns TRUE if OP is a DImode register or MEM. */
892 int
nonimmediate_di_operand(op,mode)893 nonimmediate_di_operand (op, mode)
894 rtx op;
895 Mmode mode;
896 {
897 if (register_operand (op, mode))
898 return TRUE;
899
900 if (mode != VOIDmode && GET_MODE (op) != VOIDmode && GET_MODE (op) != DImode)
901 return FALSE;
902
903 if (GET_CODE (op) == SUBREG)
904 op = SUBREG_REG (op);
905
906 if (GET_CODE (op) == MEM)
907 return memory_address_p (DImode, XEXP (op, 0));
908
909 return FALSE;
910 }
911
912 /* Returns true iff all the registers in the operands array
913 are in descending or ascending order. */
914 int
fr30_check_multiple_regs(operands,num_operands,descending)915 fr30_check_multiple_regs (operands, num_operands, descending)
916 rtx * operands;
917 int num_operands;
918 int descending;
919 {
920 if (descending)
921 {
922 unsigned int prev_regno = 0;
923
924 while (num_operands --)
925 {
926 if (GET_CODE (operands [num_operands]) != REG)
927 return 0;
928
929 if (REGNO (operands [num_operands]) < prev_regno)
930 return 0;
931
932 prev_regno = REGNO (operands [num_operands]);
933 }
934 }
935 else
936 {
937 unsigned int prev_regno = CONDITION_CODE_REGNUM;
938
939 while (num_operands --)
940 {
941 if (GET_CODE (operands [num_operands]) != REG)
942 return 0;
943
944 if (REGNO (operands [num_operands]) > prev_regno)
945 return 0;
946
947 prev_regno = REGNO (operands [num_operands]);
948 }
949 }
950
951 return 1;
952 }
953
954 int
fr30_const_double_is_zero(operand)955 fr30_const_double_is_zero (operand)
956 rtx operand;
957 {
958 REAL_VALUE_TYPE d;
959
960 if (operand == NULL || GET_CODE (operand) != CONST_DOUBLE)
961 return 0;
962
963 REAL_VALUE_FROM_CONST_DOUBLE (d, operand);
964
965 return REAL_VALUES_EQUAL (d, dconst0);
966 }
967
968 /*}}}*/
969 /*{{{ Instruction Output Routines */
970
971 /* Output a double word move.
972 It must be REG<-REG, REG<-MEM, MEM<-REG or REG<-CONST.
973 On the FR30 we are contrained by the fact that it does not
974 support offsetable addresses, and so we have to load the
975 address of the secnd word into the second destination register
976 before we can use it. */
977
978 rtx
fr30_move_double(operands)979 fr30_move_double (operands)
980 rtx * operands;
981 {
982 rtx src = operands[1];
983 rtx dest = operands[0];
984 enum rtx_code src_code = GET_CODE (src);
985 enum rtx_code dest_code = GET_CODE (dest);
986 enum machine_mode mode = GET_MODE (dest);
987 rtx val;
988
989 start_sequence ();
990
991 if (dest_code == REG)
992 {
993 if (src_code == REG)
994 {
995 int reverse = (REGNO (dest) == REGNO (src) + 1);
996
997 /* We normally copy the low-numbered register first. However, if
998 the first register of operand 0 is the same as the second register
999 of operand 1, we must copy in the opposite order. */
1000 emit_insn (gen_rtx_SET (VOIDmode,
1001 operand_subword (dest, reverse, TRUE, mode),
1002 operand_subword (src, reverse, TRUE, mode)));
1003
1004 emit_insn (gen_rtx_SET (VOIDmode,
1005 operand_subword (dest, !reverse, TRUE, mode),
1006 operand_subword (src, !reverse, TRUE, mode)));
1007 }
1008 else if (src_code == MEM)
1009 {
1010 rtx addr = XEXP (src, 0);
1011 int dregno = REGNO (dest);
1012 rtx dest0;
1013 rtx dest1;
1014 rtx new_mem;
1015
1016 /* If the high-address word is used in the address, we
1017 must load it last. Otherwise, load it first. */
1018 int reverse = (refers_to_regno_p (dregno, dregno + 1, addr, 0) != 0);
1019
1020 if (GET_CODE (addr) != REG)
1021 abort ();
1022
1023 dest0 = operand_subword (dest, reverse, TRUE, mode);
1024 dest1 = operand_subword (dest, !reverse, TRUE, mode);
1025
1026 if (reverse)
1027 {
1028 emit_insn (gen_rtx_SET (VOIDmode, dest1,
1029 adjust_address (src, SImode, 0)));
1030 emit_insn (gen_rtx_SET (SImode, dest0,
1031 gen_rtx_REG (SImode, REGNO (addr))));
1032 emit_insn (gen_rtx_SET (SImode, dest0,
1033 plus_constant (dest0, UNITS_PER_WORD)));
1034
1035 new_mem = gen_rtx_MEM (SImode, dest0);
1036 MEM_COPY_ATTRIBUTES (new_mem, src);
1037
1038 emit_insn (gen_rtx_SET (VOIDmode, dest0, new_mem));
1039 }
1040 else
1041 {
1042 emit_insn (gen_rtx_SET (VOIDmode, dest0,
1043 adjust_address (src, SImode, 0)));
1044 emit_insn (gen_rtx_SET (SImode, dest1,
1045 gen_rtx_REG (SImode, REGNO (addr))));
1046 emit_insn (gen_rtx_SET (SImode, dest1,
1047 plus_constant (dest1, UNITS_PER_WORD)));
1048
1049 new_mem = gen_rtx_MEM (SImode, dest1);
1050 MEM_COPY_ATTRIBUTES (new_mem, src);
1051
1052 emit_insn (gen_rtx_SET (VOIDmode, dest1, new_mem));
1053 }
1054 }
1055 else if (src_code == CONST_INT || src_code == CONST_DOUBLE)
1056 {
1057 rtx words[2];
1058 split_double (src, &words[0], &words[1]);
1059 emit_insn (gen_rtx_SET (VOIDmode,
1060 operand_subword (dest, 0, TRUE, mode),
1061 words[0]));
1062
1063 emit_insn (gen_rtx_SET (VOIDmode,
1064 operand_subword (dest, 1, TRUE, mode),
1065 words[1]));
1066 }
1067 }
1068 else if (src_code == REG && dest_code == MEM)
1069 {
1070 rtx addr = XEXP (dest, 0);
1071 rtx src0;
1072 rtx src1;
1073
1074 if (GET_CODE (addr) != REG)
1075 abort ();
1076
1077 src0 = operand_subword (src, 0, TRUE, mode);
1078 src1 = operand_subword (src, 1, TRUE, mode);
1079
1080 emit_insn (gen_rtx_SET (VOIDmode, adjust_address (dest, SImode, 0),
1081 src0));
1082
1083 if (REGNO (addr) == STACK_POINTER_REGNUM
1084 || REGNO (addr) == FRAME_POINTER_REGNUM)
1085 emit_insn (gen_rtx_SET (VOIDmode,
1086 adjust_address (dest, SImode, UNITS_PER_WORD),
1087 src1));
1088 else
1089 {
1090 rtx new_mem;
1091
1092 /* We need a scratch register to hold the value of 'address + 4'.
1093 We ought to allow gcc to find one for us, but for now, just
1094 push one of the source registers. */
1095 emit_insn (gen_movsi_push (src0));
1096 emit_insn (gen_movsi_internal (src0, addr));
1097 emit_insn (gen_addsi_small_int (src0, src0, GEN_INT (UNITS_PER_WORD)));
1098
1099 new_mem = gen_rtx_MEM (SImode, src0);
1100 MEM_COPY_ATTRIBUTES (new_mem, dest);
1101
1102 emit_insn (gen_rtx_SET (VOIDmode, new_mem, src1));
1103 emit_insn (gen_movsi_pop (src0));
1104 }
1105 }
1106 else
1107 /* This should have been prevented by the constraints on movdi_insn. */
1108 abort ();
1109
1110 val = get_insns ();
1111 end_sequence ();
1112
1113 return val;
1114 }
1115 /*}}}*/
1116 /* Local Variables: */
1117 /* folded-file: t */
1118 /* End: */
1119