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