OSDN Git Service

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