OSDN Git Service

46835a637d51087c233cc4af843f80c41bcf777f
[pf3gnuchains/gcc-fork.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 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 favour 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 \f
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 \f
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
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
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
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
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
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
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           REAL_VALUE_TYPE d;
557           char str[30];
558
559           REAL_VALUE_FROM_CONST_DOUBLE (d, x);
560           REAL_VALUE_TO_DECIMAL (d, str, 8);
561           fputs (str, file);
562         }
563       return;
564       
565     case 0:
566       /* Handled below.  */
567       break;
568       
569     default:
570       fprintf (stderr, "unknown code = %x\n", code);
571       output_operand_lossage ("fr30_print_operand: unknown code");
572       return;
573     }
574
575   switch (GET_CODE (x))
576     {
577     case REG:
578       fputs (reg_names [REGNO (x)], file);
579       break;
580
581     case MEM:
582       x0 = XEXP (x,0);
583       
584       switch (GET_CODE (x0))
585         {
586         case REG:
587           if ((unsigned) REGNO (x0) >= ARRAY_SIZE (reg_names))
588             abort ();
589           fprintf (file, "@%s", reg_names [REGNO (x0)]);
590           break;
591
592         case PLUS:
593           if (GET_CODE (XEXP (x0, 0)) != REG
594               || REGNO (XEXP (x0, 0)) < FRAME_POINTER_REGNUM
595               || REGNO (XEXP (x0, 0)) > STACK_POINTER_REGNUM
596               || GET_CODE (XEXP (x0, 1)) != CONST_INT)
597             {
598               fprintf (stderr, "bad INDEXed address:");
599               debug_rtx (x);
600               output_operand_lossage ("fr30_print_operand: unhandled MEM");
601             }
602           else if (REGNO (XEXP (x0, 0)) == FRAME_POINTER_REGNUM)
603             {
604               HOST_WIDE_INT val = INTVAL (XEXP (x0, 1));
605               if (val < -(1 << 9) || val > ((1 << 9) - 4))
606                 {
607                   fprintf (stderr, "frame INDEX out of range:");
608                   debug_rtx (x);
609                   output_operand_lossage ("fr30_print_operand: unhandled MEM");
610                 }
611               fprintf (file, "@(r14, #%d)", val);
612             }
613           else
614             {
615               HOST_WIDE_INT val = INTVAL (XEXP (x0, 1));
616               if (val < 0 || val > ((1 << 6) - 4))
617                 {
618                   fprintf (stderr, "stack INDEX out of range:");
619                   debug_rtx (x);
620                   output_operand_lossage ("fr30_print_operand: unhandled MEM");
621                 }
622               fprintf (file, "@(r15, #%d)", val);
623             }
624           break;
625           
626         case SYMBOL_REF:
627           output_address (x0);
628           break;
629           
630         default:
631           fprintf (stderr, "bad MEM code = %x\n", GET_CODE (x0));
632           debug_rtx (x);
633           output_operand_lossage ("fr30_print_operand: unhandled MEM");
634           break;
635         }
636       break;
637       
638     case CONST_DOUBLE :
639       /* We handle SFmode constants here as output_addr_const doesn't.  */
640       if (GET_MODE (x) == SFmode)
641         {
642           REAL_VALUE_TYPE d;
643           long l;
644
645           REAL_VALUE_FROM_CONST_DOUBLE (d, x);
646           REAL_VALUE_TO_TARGET_SINGLE (d, l);
647           fprintf (file, "0x%08lx", l);
648           break;
649         }
650
651       /* Fall through.  Let output_addr_const deal with it.  */
652     default:
653       output_addr_const (file, x);
654       break;
655     }
656
657   return;
658 }
659
660 /*}}}*/
661 /*{{{  Function arguments */ 
662
663 /* Compute the number of word sized registers needed to hold a
664    function argument of mode INT_MODE and tree type TYPE.  */
665 int
666 fr30_num_arg_regs (int_mode, type)
667      int int_mode;
668      tree type;
669 {
670   enum machine_mode mode = (enum machine_mode) int_mode;
671   int size;
672
673   if (MUST_PASS_IN_STACK (mode, type))
674     return 0;
675
676   if (type && mode == BLKmode)
677     size = int_size_in_bytes (type);
678   else
679     size = GET_MODE_SIZE (mode);
680
681   return (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
682 }
683
684 /* Implements the FUNCTION_ARG_PARTIAL_NREGS macro.
685    Returns the number of argument registers required to hold *part* of
686    a parameter of machine mode MODE and tree type TYPE (which may be
687    NULL if the type is not known).  If the argument fits entirly in
688    the argument registers, or entirely on the stack, then 0 is returned.
689    CUM is the number of argument registers already used by earlier
690    parameters to the function.  */
691
692 int
693 fr30_function_arg_partial_nregs (cum, int_mode, type, named)
694      CUMULATIVE_ARGS cum;
695      int int_mode;
696      tree type;
697      int named;
698 {
699   /* Unnamed arguments, ie those that are prototyped as ...
700      are always passed on the stack.
701      Also check here to see if all the argument registers are full.  */
702   if (named == 0 || cum >= FR30_NUM_ARG_REGS)
703     return 0;
704
705   /* Work out how many argument registers would be needed if this
706      parameter were to be passed entirely in registers.  If there
707      are sufficient argument registers available (or if no registers
708      are needed because the parameter must be passed on the stack)
709      then return zero, as this parameter does not require partial
710      register, partial stack stack space.  */
711   if (cum + fr30_num_arg_regs (int_mode, type) <= FR30_NUM_ARG_REGS)
712     return 0;
713   
714   /* Otherwise return the number of registers that would be used.  */
715   return FR30_NUM_ARG_REGS - cum;
716 }
717
718 static rtx
719 fr30_pass_by_reference (valist, type)
720      tree valist;
721      tree type;
722 {
723   tree type_ptr;
724   tree type_ptr_ptr;
725   tree t;
726   
727   type_ptr     = build_pointer_type (type);
728   type_ptr_ptr = build_pointer_type (type_ptr);
729   
730   t = build (POSTINCREMENT_EXPR, va_list_type_node, valist, build_int_2 (UNITS_PER_WORD, 0));
731   TREE_SIDE_EFFECTS (t) = 1;
732   t = build1 (NOP_EXPR, type_ptr_ptr, t);
733   TREE_SIDE_EFFECTS (t) = 1;
734   t = build1 (INDIRECT_REF, type_ptr, t);
735   
736   return expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
737 }
738
739 static rtx
740 fr30_pass_by_value (valist, type)
741      tree valist;
742      tree type;
743 {
744   HOST_WIDE_INT size = int_size_in_bytes (type);
745   HOST_WIDE_INT rsize;
746   rtx addr_rtx;
747   tree t;
748
749   if ((size % UNITS_PER_WORD) == 0)
750     {
751       t = build (POSTINCREMENT_EXPR, va_list_type_node, valist, build_int_2 (size, 0));
752       TREE_SIDE_EFFECTS (t) = 1;
753       
754       return expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
755     }
756
757   rsize = (size + UNITS_PER_WORD - 1) & - UNITS_PER_WORD;
758       
759   /* Care for bigendian correction on the aligned address.  */
760   t = build (PLUS_EXPR, ptr_type_node, valist, build_int_2 (rsize - size, 0));
761   addr_rtx = expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
762   addr_rtx = copy_to_reg (addr_rtx);
763       
764   /* Increment AP.  */
765   t = build (PLUS_EXPR, va_list_type_node, valist, build_int_2 (rsize, 0));
766   t = build (MODIFY_EXPR, va_list_type_node, valist, t);
767   TREE_SIDE_EFFECTS (t) = 1;
768   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
769   
770   return addr_rtx;
771 }
772
773 /* Implement `va_arg'.  */
774
775 rtx
776 fr30_va_arg (valist, type)
777      tree valist;
778      tree type;
779 {
780   HOST_WIDE_INT size;
781   
782   if (AGGREGATE_TYPE_P (type))
783     return fr30_pass_by_reference (valist, type);
784   
785   size = int_size_in_bytes (type);
786
787   if ((size % sizeof (int)) == 0
788       || size < 4)
789     return fr30_pass_by_value (valist, type);
790
791   return fr30_pass_by_reference (valist, type);
792 }
793
794 /*}}}*/
795 /*{{{  Operand predicates */ 
796
797 #ifndef Mmode
798 #define Mmode enum machine_mode
799 #endif
800
801 /* Returns true if OPERAND is an integer value suitable for use in
802    an ADDSP instruction.  */
803 int
804 stack_add_operand (operand, mode)
805      rtx operand;
806      Mmode mode ATTRIBUTE_UNUSED;
807 {
808   return
809     (GET_CODE (operand) == CONST_INT
810      && INTVAL (operand) >= -512
811      && INTVAL (operand) <=  508
812      && ((INTVAL (operand) & 3) == 0));
813 }
814
815 /* Returns true if OPERAND is an integer value suitable for use in
816    an ADD por ADD2 instruction, or if it is a register.  */
817 int
818 add_immediate_operand (operand, mode)
819      rtx operand;
820      Mmode mode ATTRIBUTE_UNUSED;
821 {
822   return
823     (GET_CODE (operand) == REG
824      || (GET_CODE (operand) == CONST_INT
825          && INTVAL (operand) >= -16
826          && INTVAL (operand) <=  15));
827 }
828
829 /* Returns true if OPERAND is hard register in the range 8 - 15.  */
830 int
831 high_register_operand (operand, mode)
832      rtx operand;
833      Mmode mode ATTRIBUTE_UNUSED;
834 {
835   return
836     (GET_CODE (operand) == REG
837      && REGNO (operand) <= 15
838      && REGNO (operand) >= 8);
839 }
840
841 /* Returns true if OPERAND is hard register in the range 0 - 7.  */
842 int
843 low_register_operand (operand, mode)
844      rtx operand;
845      Mmode mode ATTRIBUTE_UNUSED;
846 {
847   return
848     (GET_CODE (operand) == REG
849      && REGNO (operand) <= 7);
850 }
851
852 /* Returns true if OPERAND is suitable for use in a CALL insn.  */
853 int
854 call_operand (operand, mode)
855      rtx operand;
856      Mmode mode ATTRIBUTE_UNUSED;
857 {
858   return (GET_CODE (operand) == MEM
859           && (GET_CODE (XEXP (operand, 0)) == SYMBOL_REF
860               || GET_CODE (XEXP (operand, 0)) == REG));
861 }
862
863 /* Returns TRUE if OP is a valid operand of a DImode operation.  */
864 int
865 di_operand (op, mode)
866      rtx op;
867      Mmode mode;
868 {
869   if (register_operand (op, mode))
870     return TRUE;
871
872   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && GET_MODE (op) != DImode)
873     return FALSE;
874
875   if (GET_CODE (op) == SUBREG)
876     op = SUBREG_REG (op);
877
878   switch (GET_CODE (op))
879     {
880     case CONST_DOUBLE:
881     case CONST_INT:
882       return TRUE;
883
884     case MEM:
885       return memory_address_p (DImode, XEXP (op, 0));
886
887     default:
888       return FALSE;
889     }
890 }
891
892 /* Returns TRUE if OP is a DImode register or MEM.  */
893 int
894 nonimmediate_di_operand (op, mode)
895      rtx op;
896      Mmode mode;
897 {
898   if (register_operand (op, mode))
899     return TRUE;
900
901   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && GET_MODE (op) != DImode)
902     return FALSE;
903
904   if (GET_CODE (op) == SUBREG)
905     op = SUBREG_REG (op);
906
907   if (GET_CODE (op) == MEM)
908     return memory_address_p (DImode, XEXP (op, 0));
909
910   return FALSE;
911 }
912
913 /* Returns true iff all the registers in the operands array
914    are in descending or ascending order.  */
915 int
916 fr30_check_multiple_regs (operands, num_operands, descending)
917      rtx * operands;
918      int   num_operands;
919      int   descending;
920 {
921   if (descending)
922     {
923       unsigned int prev_regno = 0;
924       
925       while (num_operands --)
926         {
927           if (GET_CODE (operands [num_operands]) != REG)
928             return 0;
929           
930           if (REGNO (operands [num_operands]) < prev_regno)
931             return 0;
932           
933           prev_regno = REGNO (operands [num_operands]);
934         }
935     }
936   else
937     {
938       unsigned int prev_regno = CONDITION_CODE_REGNUM;
939       
940       while (num_operands --)
941         {
942           if (GET_CODE (operands [num_operands]) != REG)
943             return 0;
944           
945           if (REGNO (operands [num_operands]) > prev_regno)
946             return 0;
947           
948           prev_regno = REGNO (operands [num_operands]);
949         }
950     }
951
952   return 1;
953 }
954
955 /*}}}*/
956 /*{{{  Instruction Output Routines  */
957
958 /* Output a double word move.
959    It must be REG<-REG, REG<-MEM, MEM<-REG or REG<-CONST.
960    On the FR30 we are contrained by the fact that it does not
961    support offsetable addresses, and so we have to load the
962    address of the secnd word into the second destination register
963    before we can use it.  */
964
965 rtx
966 fr30_move_double (operands)
967      rtx * operands;
968 {
969   rtx src  = operands[1];
970   rtx dest = operands[0];
971   enum rtx_code src_code = GET_CODE (src);
972   enum rtx_code dest_code = GET_CODE (dest);
973   enum machine_mode mode = GET_MODE (dest);
974   rtx val;
975
976   start_sequence ();
977
978   if (dest_code == REG)
979     {
980       if (src_code == REG)
981         {
982           int reverse = (REGNO (dest) == REGNO (src) + 1);
983           
984           /* We normally copy the low-numbered register first.  However, if
985              the first register of operand 0 is the same as the second register
986              of operand 1, we must copy in the opposite order.  */
987           emit_insn (gen_rtx_SET (VOIDmode,
988                                   operand_subword (dest, reverse, TRUE, mode),
989                                   operand_subword (src,  reverse, TRUE, mode)));
990           
991           emit_insn (gen_rtx_SET (VOIDmode,
992                               operand_subword (dest, !reverse, TRUE, mode),
993                               operand_subword (src,  !reverse, TRUE, mode)));
994         }
995       else if (src_code == MEM)
996         {
997           rtx addr = XEXP (src, 0);
998           int dregno = REGNO (dest);
999           rtx dest0;
1000           rtx dest1;
1001           rtx new_mem;
1002           
1003           /* If the high-address word is used in the address, we
1004              must load it last.  Otherwise, load it first.  */
1005           int reverse = (refers_to_regno_p (dregno, dregno + 1, addr, 0) != 0);
1006
1007           if (GET_CODE (addr) != REG)
1008             abort ();
1009           
1010           dest0 = operand_subword (dest, reverse, TRUE, mode);
1011           dest1 = operand_subword (dest, !reverse, TRUE, mode);
1012
1013           if (reverse)
1014             {
1015               emit_insn (gen_rtx_SET (VOIDmode, dest1,
1016                                       adjust_address (src, SImode, 0)));
1017               emit_insn (gen_rtx_SET (SImode, dest0,
1018                                       gen_rtx_REG (SImode, REGNO (addr))));
1019               emit_insn (gen_rtx_SET (SImode, dest0,
1020                                       plus_constant (dest0, UNITS_PER_WORD)));
1021
1022               new_mem = gen_rtx_MEM (SImode, dest0);
1023               MEM_COPY_ATTRIBUTES (new_mem, src);
1024               
1025               emit_insn (gen_rtx_SET (VOIDmode, dest0, new_mem));
1026             }
1027           else
1028             {
1029               emit_insn (gen_rtx_SET (VOIDmode, dest0,
1030                                       adjust_address (src, SImode, 0)));
1031               emit_insn (gen_rtx_SET (SImode, dest1,
1032                                       gen_rtx_REG (SImode, REGNO (addr))));
1033               emit_insn (gen_rtx_SET (SImode, dest1,
1034                                       plus_constant (dest1, UNITS_PER_WORD)));
1035
1036               new_mem = gen_rtx_MEM (SImode, dest1);
1037               MEM_COPY_ATTRIBUTES (new_mem, src);
1038               
1039               emit_insn (gen_rtx_SET (VOIDmode, dest1, new_mem));
1040             }
1041         }
1042       else if (src_code == CONST_INT || src_code == CONST_DOUBLE)
1043         {
1044           rtx words[2];
1045           split_double (src, &words[0], &words[1]);
1046           emit_insn (gen_rtx_SET (VOIDmode,
1047                                   operand_subword (dest, 0, TRUE, mode),
1048                                   words[0]));
1049       
1050           emit_insn (gen_rtx_SET (VOIDmode,
1051                                   operand_subword (dest, 1, TRUE, mode),
1052                                   words[1]));
1053         }
1054     }
1055   else if (src_code == REG && dest_code == MEM)
1056     {
1057       rtx addr = XEXP (dest, 0);
1058       rtx src0;
1059       rtx src1;
1060
1061       if (GET_CODE (addr) != REG)
1062         abort ();
1063       
1064       src0 = operand_subword (src, 0, TRUE, mode);
1065       src1 = operand_subword (src, 1, TRUE, mode);
1066       
1067       emit_insn (gen_rtx_SET (VOIDmode, adjust_address (dest, SImode, 0),
1068                               src0));
1069
1070       if (REGNO (addr) == STACK_POINTER_REGNUM
1071           || REGNO (addr) == FRAME_POINTER_REGNUM)
1072         emit_insn (gen_rtx_SET (VOIDmode,
1073                                 adjust_address (dest, SImode, UNITS_PER_WORD),
1074                                 src1));
1075       else
1076         {
1077           rtx new_mem;
1078           
1079           /* We need a scratch register to hold the value of 'address + 4'.
1080              We ought to allow gcc to find one for us, but for now, just
1081              push one of the source registers.  */
1082           emit_insn (gen_movsi_push (src0));
1083           emit_insn (gen_movsi_internal (src0, addr));
1084           emit_insn (gen_addsi_small_int (src0, src0, GEN_INT (UNITS_PER_WORD)));
1085           
1086           new_mem = gen_rtx_MEM (SImode, src0);
1087           MEM_COPY_ATTRIBUTES (new_mem, dest);
1088           
1089           emit_insn (gen_rtx_SET (VOIDmode, new_mem, src1));
1090           emit_insn (gen_movsi_pop (src0));
1091         }
1092     }
1093   else
1094     /* This should have been prevented by the constraints on movdi_insn.  */
1095     abort ();
1096   
1097   val = get_insns ();
1098   end_sequence ();
1099
1100   return val;
1101 }
1102 /*}}}*/
1103 /* Local Variables: */
1104 /* folded-file: t   */
1105 /* End:             */