real.c (real_to_decimal): Accept BUF_SIZE and CROP_TRAILING_ZEROS as arguments.
[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 GNU CC.
6
7    GNU CC is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2, or (at your option)
10    any later version.
11
12    GNU CC is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GNU CC; see the file COPYING.  If not, write to
19    the Free Software Foundation, 59 Temple Place - Suite 330,
20    Boston, MA 02111-1307, USA.  */
21
22 /*{{{  Includes */ 
23
24 #include "config.h"
25 #include "system.h"
26 #include "rtl.h"
27 #include "regs.h"
28 #include "hard-reg-set.h"
29 #include "real.h"
30 #include "insn-config.h"
31 #include "conditions.h"
32 #include "insn-attr.h"
33 #include "flags.h"
34 #include "recog.h"
35 #include "tree.h"
36 #include "output.h"
37 #include "expr.h"
38 #include "obstack.h"
39 #include "except.h"
40 #include "function.h"
41 #include "tm_p.h"
42 #include "target.h"
43 #include "target-def.h"
44
45 /*}}}*/
46 /*{{{  Function Prologues & Epilogues */ 
47
48 /* Define the information needed to generate branch and scc insns.  This is
49    stored from the compare operation.  */
50
51 struct rtx_def * fr30_compare_op0;
52 struct rtx_def * fr30_compare_op1;
53
54 /* The FR30 stack looks like this:
55
56              Before call                       After call
57    FP ->|                       |       |                       |
58         +-----------------------+       +-----------------------+       high 
59         |                       |       |                       |       memory
60         |  local variables,     |       |  local variables,     |
61         |  reg save area, etc.  |       |  reg save area, etc.  |
62         |                       |       |                       |
63         +-----------------------+       +-----------------------+
64         |                       |       |                       |
65         | args to the func that |       |  args to this func.   |
66         | is being called that  |       |                       |
67    SP ->| do not fit in regs    |       |                       |
68         +-----------------------+       +-----------------------+
69                                         |  args that used to be |  \
70                                         | in regs; only created |   |  pretend_size 
71                                    AP-> |   for vararg funcs    |  /  
72                                         +-----------------------+    
73                                         |                       |  \  
74                                         |  register save area   |   |
75                                         |                       |   |
76                                         +-----------------------+   |  reg_size
77                                         |    return address     |   | 
78                                         +-----------------------+   |
79                                    FP ->|   previous frame ptr  |  /
80                                         +-----------------------+    
81                                         |                       |  \   
82                                         |  local variables      |   |  var_size 
83                                         |                       |  /  
84                                         +-----------------------+    
85                                         |                       |  \       
86      low                                |  room for args to     |   |
87      memory                             |  other funcs called   |   |  args_size     
88                                         |  from this one        |   |
89                                    SP ->|                       |  /  
90                                         +-----------------------+    
91    
92    Note, AP is a fake hard register.  It will be eliminated in favor of
93    SP or FP as appropriate.
94
95    Note, Some or all of the stack sections above may be omitted if they 
96    are not needed.  */
97
98 /* Structure to be filled in by fr30_compute_frame_size() with register
99    save masks, and offsets for the current function.  */
100 struct fr30_frame_info
101 {
102   unsigned int total_size;      /* # Bytes that the entire frame takes up. */
103   unsigned int pretend_size;    /* # Bytes we push and pretend caller did. */
104   unsigned int args_size;       /* # Bytes that outgoing arguments take up. */
105   unsigned int reg_size;        /* # Bytes needed to store regs. */
106   unsigned int var_size;        /* # Bytes that variables take up. */
107   unsigned int frame_size;      /* # Bytes in current frame.  */
108   unsigned int gmask;           /* Mask of saved registers. */
109   unsigned int save_fp;         /* Nonzero if frame pointer must be saved. */
110   unsigned int save_rp;         /* Nonzero if return popinter must be saved. */
111   int          initialised;     /* Nonzero if frame size already calculated. */
112 };
113
114 /* Current frame information calculated by fr30_compute_frame_size().  */
115 static struct fr30_frame_info   current_frame_info;
116
117 /* Zero structure to initialize current_frame_info.  */
118 static struct fr30_frame_info   zero_frame_info;
119
120 static rtx fr30_pass_by_reference PARAMS ((tree, tree));
121 static rtx fr30_pass_by_value PARAMS ((tree, tree));
122
123 #define FRAME_POINTER_MASK      (1 << (FRAME_POINTER_REGNUM))
124 #define RETURN_POINTER_MASK     (1 << (RETURN_POINTER_REGNUM))
125
126 /* Tell prologue and epilogue if register REGNO should be saved / restored.
127    The return address and frame pointer are treated separately.
128    Don't consider them here.  */
129 #define MUST_SAVE_REGISTER(regno)      \
130   (   (regno) != RETURN_POINTER_REGNUM \
131    && (regno) != FRAME_POINTER_REGNUM  \
132    &&   regs_ever_live [regno]         \
133    && ! call_used_regs [regno]         )
134
135 #define MUST_SAVE_FRAME_POINTER  (regs_ever_live [FRAME_POINTER_REGNUM]  || frame_pointer_needed)
136 #define MUST_SAVE_RETURN_POINTER (regs_ever_live [RETURN_POINTER_REGNUM] || current_function_profile)
137
138 #if UNITS_PER_WORD == 4
139 #define WORD_ALIGN(SIZE) (((SIZE) + 3) & ~3)
140 #endif
141 \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           char str[30];
557
558           real_to_decimal (str, CONST_DOUBLE_REAL_VALUE (x),
559                            sizeof (str), 0, 1);
560           fputs (str, file);
561         }
562       return;
563       
564     case 0:
565       /* Handled below.  */
566       break;
567       
568     default:
569       fprintf (stderr, "unknown code = %x\n", code);
570       output_operand_lossage ("fr30_print_operand: unknown code");
571       return;
572     }
573
574   switch (GET_CODE (x))
575     {
576     case REG:
577       fputs (reg_names [REGNO (x)], file);
578       break;
579
580     case MEM:
581       x0 = XEXP (x,0);
582       
583       switch (GET_CODE (x0))
584         {
585         case REG:
586           if ((unsigned) REGNO (x0) >= ARRAY_SIZE (reg_names))
587             abort ();
588           fprintf (file, "@%s", reg_names [REGNO (x0)]);
589           break;
590
591         case PLUS:
592           if (GET_CODE (XEXP (x0, 0)) != REG
593               || REGNO (XEXP (x0, 0)) < FRAME_POINTER_REGNUM
594               || REGNO (XEXP (x0, 0)) > STACK_POINTER_REGNUM
595               || GET_CODE (XEXP (x0, 1)) != CONST_INT)
596             {
597               fprintf (stderr, "bad INDEXed address:");
598               debug_rtx (x);
599               output_operand_lossage ("fr30_print_operand: unhandled MEM");
600             }
601           else if (REGNO (XEXP (x0, 0)) == FRAME_POINTER_REGNUM)
602             {
603               HOST_WIDE_INT val = INTVAL (XEXP (x0, 1));
604               if (val < -(1 << 9) || val > ((1 << 9) - 4))
605                 {
606                   fprintf (stderr, "frame INDEX out of range:");
607                   debug_rtx (x);
608                   output_operand_lossage ("fr30_print_operand: unhandled MEM");
609                 }
610               fprintf (file, "@(r14, #%d)", val);
611             }
612           else
613             {
614               HOST_WIDE_INT val = INTVAL (XEXP (x0, 1));
615               if (val < 0 || val > ((1 << 6) - 4))
616                 {
617                   fprintf (stderr, "stack INDEX out of range:");
618                   debug_rtx (x);
619                   output_operand_lossage ("fr30_print_operand: unhandled MEM");
620                 }
621               fprintf (file, "@(r15, #%d)", val);
622             }
623           break;
624           
625         case SYMBOL_REF:
626           output_address (x0);
627           break;
628           
629         default:
630           fprintf (stderr, "bad MEM code = %x\n", GET_CODE (x0));
631           debug_rtx (x);
632           output_operand_lossage ("fr30_print_operand: unhandled MEM");
633           break;
634         }
635       break;
636       
637     case CONST_DOUBLE :
638       /* We handle SFmode constants here as output_addr_const doesn't.  */
639       if (GET_MODE (x) == SFmode)
640         {
641           REAL_VALUE_TYPE d;
642           long l;
643
644           REAL_VALUE_FROM_CONST_DOUBLE (d, x);
645           REAL_VALUE_TO_TARGET_SINGLE (d, l);
646           fprintf (file, "0x%08lx", l);
647           break;
648         }
649
650       /* Fall through.  Let output_addr_const deal with it.  */
651     default:
652       output_addr_const (file, x);
653       break;
654     }
655
656   return;
657 }
658
659 /*}}}*/
660 /*{{{  Function arguments */ 
661
662 /* Compute the number of word sized registers needed to hold a
663    function argument of mode INT_MODE and tree type TYPE.  */
664 int
665 fr30_num_arg_regs (int_mode, type)
666      int int_mode;
667      tree type;
668 {
669   enum machine_mode mode = (enum machine_mode) int_mode;
670   int size;
671
672   if (MUST_PASS_IN_STACK (mode, type))
673     return 0;
674
675   if (type && mode == BLKmode)
676     size = int_size_in_bytes (type);
677   else
678     size = GET_MODE_SIZE (mode);
679
680   return (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
681 }
682
683 /* Implements the FUNCTION_ARG_PARTIAL_NREGS macro.
684    Returns the number of argument registers required to hold *part* of
685    a parameter of machine mode MODE and tree type TYPE (which may be
686    NULL if the type is not known).  If the argument fits entirly in
687    the argument registers, or entirely on the stack, then 0 is returned.
688    CUM is the number of argument registers already used by earlier
689    parameters to the function.  */
690
691 int
692 fr30_function_arg_partial_nregs (cum, int_mode, type, named)
693      CUMULATIVE_ARGS cum;
694      int int_mode;
695      tree type;
696      int named;
697 {
698   /* Unnamed arguments, ie those that are prototyped as ...
699      are always passed on the stack.
700      Also check here to see if all the argument registers are full.  */
701   if (named == 0 || cum >= FR30_NUM_ARG_REGS)
702     return 0;
703
704   /* Work out how many argument registers would be needed if this
705      parameter were to be passed entirely in registers.  If there
706      are sufficient argument registers available (or if no registers
707      are needed because the parameter must be passed on the stack)
708      then return zero, as this parameter does not require partial
709      register, partial stack stack space.  */
710   if (cum + fr30_num_arg_regs (int_mode, type) <= FR30_NUM_ARG_REGS)
711     return 0;
712   
713   /* Otherwise return the number of registers that would be used.  */
714   return FR30_NUM_ARG_REGS - cum;
715 }
716
717 static rtx
718 fr30_pass_by_reference (valist, type)
719      tree valist;
720      tree type;
721 {
722   tree type_ptr;
723   tree type_ptr_ptr;
724   tree t;
725   
726   type_ptr     = build_pointer_type (type);
727   type_ptr_ptr = build_pointer_type (type_ptr);
728   
729   t = build (POSTINCREMENT_EXPR, va_list_type_node, valist, build_int_2 (UNITS_PER_WORD, 0));
730   TREE_SIDE_EFFECTS (t) = 1;
731   t = build1 (NOP_EXPR, type_ptr_ptr, t);
732   TREE_SIDE_EFFECTS (t) = 1;
733   t = build1 (INDIRECT_REF, type_ptr, t);
734   
735   return expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
736 }
737
738 static rtx
739 fr30_pass_by_value (valist, type)
740      tree valist;
741      tree type;
742 {
743   HOST_WIDE_INT size = int_size_in_bytes (type);
744   HOST_WIDE_INT rsize;
745   rtx addr_rtx;
746   tree t;
747
748   if ((size % UNITS_PER_WORD) == 0)
749     {
750       t = build (POSTINCREMENT_EXPR, va_list_type_node, valist, build_int_2 (size, 0));
751       TREE_SIDE_EFFECTS (t) = 1;
752       
753       return expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
754     }
755
756   rsize = (size + UNITS_PER_WORD - 1) & - UNITS_PER_WORD;
757       
758   /* Care for bigendian correction on the aligned address.  */
759   t = build (PLUS_EXPR, ptr_type_node, valist, build_int_2 (rsize - size, 0));
760   addr_rtx = expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
761   addr_rtx = copy_to_reg (addr_rtx);
762       
763   /* Increment AP.  */
764   t = build (PLUS_EXPR, va_list_type_node, valist, build_int_2 (rsize, 0));
765   t = build (MODIFY_EXPR, va_list_type_node, valist, t);
766   TREE_SIDE_EFFECTS (t) = 1;
767   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
768   
769   return addr_rtx;
770 }
771
772 /* Implement `va_arg'.  */
773
774 rtx
775 fr30_va_arg (valist, type)
776      tree valist;
777      tree type;
778 {
779   HOST_WIDE_INT size;
780   
781   if (AGGREGATE_TYPE_P (type))
782     return fr30_pass_by_reference (valist, type);
783   
784   size = int_size_in_bytes (type);
785
786   if ((size % sizeof (int)) == 0
787       || size < 4)
788     return fr30_pass_by_value (valist, type);
789
790   return fr30_pass_by_reference (valist, type);
791 }
792
793 /*}}}*/
794 /*{{{  Operand predicates */ 
795
796 #ifndef Mmode
797 #define Mmode enum machine_mode
798 #endif
799
800 /* Returns true if OPERAND is an integer value suitable for use in
801    an ADDSP instruction.  */
802 int
803 stack_add_operand (operand, mode)
804      rtx operand;
805      Mmode mode ATTRIBUTE_UNUSED;
806 {
807   return
808     (GET_CODE (operand) == CONST_INT
809      && INTVAL (operand) >= -512
810      && INTVAL (operand) <=  508
811      && ((INTVAL (operand) & 3) == 0));
812 }
813
814 /* Returns true if OPERAND is an integer value suitable for use in
815    an ADD por ADD2 instruction, or if it is a register.  */
816 int
817 add_immediate_operand (operand, mode)
818      rtx operand;
819      Mmode mode ATTRIBUTE_UNUSED;
820 {
821   return
822     (GET_CODE (operand) == REG
823      || (GET_CODE (operand) == CONST_INT
824          && INTVAL (operand) >= -16
825          && INTVAL (operand) <=  15));
826 }
827
828 /* Returns true if OPERAND is hard register in the range 8 - 15.  */
829 int
830 high_register_operand (operand, mode)
831      rtx operand;
832      Mmode mode ATTRIBUTE_UNUSED;
833 {
834   return
835     (GET_CODE (operand) == REG
836      && REGNO (operand) <= 15
837      && REGNO (operand) >= 8);
838 }
839
840 /* Returns true if OPERAND is hard register in the range 0 - 7.  */
841 int
842 low_register_operand (operand, mode)
843      rtx operand;
844      Mmode mode ATTRIBUTE_UNUSED;
845 {
846   return
847     (GET_CODE (operand) == REG
848      && REGNO (operand) <= 7);
849 }
850
851 /* Returns true if OPERAND is suitable for use in a CALL insn.  */
852 int
853 call_operand (operand, mode)
854      rtx operand;
855      Mmode mode ATTRIBUTE_UNUSED;
856 {
857   return (GET_CODE (operand) == MEM
858           && (GET_CODE (XEXP (operand, 0)) == SYMBOL_REF
859               || GET_CODE (XEXP (operand, 0)) == REG));
860 }
861
862 /* Returns TRUE if OP is a valid operand of a DImode operation.  */
863 int
864 di_operand (op, mode)
865      rtx op;
866      Mmode mode;
867 {
868   if (register_operand (op, mode))
869     return TRUE;
870
871   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && GET_MODE (op) != DImode)
872     return FALSE;
873
874   if (GET_CODE (op) == SUBREG)
875     op = SUBREG_REG (op);
876
877   switch (GET_CODE (op))
878     {
879     case CONST_DOUBLE:
880     case CONST_INT:
881       return TRUE;
882
883     case MEM:
884       return memory_address_p (DImode, XEXP (op, 0));
885
886     default:
887       return FALSE;
888     }
889 }
890
891 /* Returns TRUE if OP is a DImode register or MEM.  */
892 int
893 nonimmediate_di_operand (op, mode)
894      rtx op;
895      Mmode mode;
896 {
897   if (register_operand (op, mode))
898     return TRUE;
899
900   if (mode != VOIDmode && GET_MODE (op) != VOIDmode && GET_MODE (op) != DImode)
901     return FALSE;
902
903   if (GET_CODE (op) == SUBREG)
904     op = SUBREG_REG (op);
905
906   if (GET_CODE (op) == MEM)
907     return memory_address_p (DImode, XEXP (op, 0));
908
909   return FALSE;
910 }
911
912 /* Returns true iff all the registers in the operands array
913    are in descending or ascending order.  */
914 int
915 fr30_check_multiple_regs (operands, num_operands, descending)
916      rtx * operands;
917      int   num_operands;
918      int   descending;
919 {
920   if (descending)
921     {
922       unsigned int prev_regno = 0;
923       
924       while (num_operands --)
925         {
926           if (GET_CODE (operands [num_operands]) != REG)
927             return 0;
928           
929           if (REGNO (operands [num_operands]) < prev_regno)
930             return 0;
931           
932           prev_regno = REGNO (operands [num_operands]);
933         }
934     }
935   else
936     {
937       unsigned int prev_regno = CONDITION_CODE_REGNUM;
938       
939       while (num_operands --)
940         {
941           if (GET_CODE (operands [num_operands]) != REG)
942             return 0;
943           
944           if (REGNO (operands [num_operands]) > prev_regno)
945             return 0;
946           
947           prev_regno = REGNO (operands [num_operands]);
948         }
949     }
950
951   return 1;
952 }
953
954 /*}}}*/
955 /*{{{  Instruction Output Routines  */
956
957 /* Output a double word move.
958    It must be REG<-REG, REG<-MEM, MEM<-REG or REG<-CONST.
959    On the FR30 we are contrained by the fact that it does not
960    support offsetable addresses, and so we have to load the
961    address of the secnd word into the second destination register
962    before we can use it.  */
963
964 rtx
965 fr30_move_double (operands)
966      rtx * operands;
967 {
968   rtx src  = operands[1];
969   rtx dest = operands[0];
970   enum rtx_code src_code = GET_CODE (src);
971   enum rtx_code dest_code = GET_CODE (dest);
972   enum machine_mode mode = GET_MODE (dest);
973   rtx val;
974
975   start_sequence ();
976
977   if (dest_code == REG)
978     {
979       if (src_code == REG)
980         {
981           int reverse = (REGNO (dest) == REGNO (src) + 1);
982           
983           /* We normally copy the low-numbered register first.  However, if
984              the first register of operand 0 is the same as the second register
985              of operand 1, we must copy in the opposite order.  */
986           emit_insn (gen_rtx_SET (VOIDmode,
987                                   operand_subword (dest, reverse, TRUE, mode),
988                                   operand_subword (src,  reverse, TRUE, mode)));
989           
990           emit_insn (gen_rtx_SET (VOIDmode,
991                               operand_subword (dest, !reverse, TRUE, mode),
992                               operand_subword (src,  !reverse, TRUE, mode)));
993         }
994       else if (src_code == MEM)
995         {
996           rtx addr = XEXP (src, 0);
997           int dregno = REGNO (dest);
998           rtx dest0;
999           rtx dest1;
1000           rtx new_mem;
1001           
1002           /* If the high-address word is used in the address, we
1003              must load it last.  Otherwise, load it first.  */
1004           int reverse = (refers_to_regno_p (dregno, dregno + 1, addr, 0) != 0);
1005
1006           if (GET_CODE (addr) != REG)
1007             abort ();
1008           
1009           dest0 = operand_subword (dest, reverse, TRUE, mode);
1010           dest1 = operand_subword (dest, !reverse, TRUE, mode);
1011
1012           if (reverse)
1013             {
1014               emit_insn (gen_rtx_SET (VOIDmode, dest1,
1015                                       adjust_address (src, SImode, 0)));
1016               emit_insn (gen_rtx_SET (SImode, dest0,
1017                                       gen_rtx_REG (SImode, REGNO (addr))));
1018               emit_insn (gen_rtx_SET (SImode, dest0,
1019                                       plus_constant (dest0, UNITS_PER_WORD)));
1020
1021               new_mem = gen_rtx_MEM (SImode, dest0);
1022               MEM_COPY_ATTRIBUTES (new_mem, src);
1023               
1024               emit_insn (gen_rtx_SET (VOIDmode, dest0, new_mem));
1025             }
1026           else
1027             {
1028               emit_insn (gen_rtx_SET (VOIDmode, dest0,
1029                                       adjust_address (src, SImode, 0)));
1030               emit_insn (gen_rtx_SET (SImode, dest1,
1031                                       gen_rtx_REG (SImode, REGNO (addr))));
1032               emit_insn (gen_rtx_SET (SImode, dest1,
1033                                       plus_constant (dest1, UNITS_PER_WORD)));
1034
1035               new_mem = gen_rtx_MEM (SImode, dest1);
1036               MEM_COPY_ATTRIBUTES (new_mem, src);
1037               
1038               emit_insn (gen_rtx_SET (VOIDmode, dest1, new_mem));
1039             }
1040         }
1041       else if (src_code == CONST_INT || src_code == CONST_DOUBLE)
1042         {
1043           rtx words[2];
1044           split_double (src, &words[0], &words[1]);
1045           emit_insn (gen_rtx_SET (VOIDmode,
1046                                   operand_subword (dest, 0, TRUE, mode),
1047                                   words[0]));
1048       
1049           emit_insn (gen_rtx_SET (VOIDmode,
1050                                   operand_subword (dest, 1, TRUE, mode),
1051                                   words[1]));
1052         }
1053     }
1054   else if (src_code == REG && dest_code == MEM)
1055     {
1056       rtx addr = XEXP (dest, 0);
1057       rtx src0;
1058       rtx src1;
1059
1060       if (GET_CODE (addr) != REG)
1061         abort ();
1062       
1063       src0 = operand_subword (src, 0, TRUE, mode);
1064       src1 = operand_subword (src, 1, TRUE, mode);
1065       
1066       emit_insn (gen_rtx_SET (VOIDmode, adjust_address (dest, SImode, 0),
1067                               src0));
1068
1069       if (REGNO (addr) == STACK_POINTER_REGNUM
1070           || REGNO (addr) == FRAME_POINTER_REGNUM)
1071         emit_insn (gen_rtx_SET (VOIDmode,
1072                                 adjust_address (dest, SImode, UNITS_PER_WORD),
1073                                 src1));
1074       else
1075         {
1076           rtx new_mem;
1077           
1078           /* We need a scratch register to hold the value of 'address + 4'.
1079              We ought to allow gcc to find one for us, but for now, just
1080              push one of the source registers.  */
1081           emit_insn (gen_movsi_push (src0));
1082           emit_insn (gen_movsi_internal (src0, addr));
1083           emit_insn (gen_addsi_small_int (src0, src0, GEN_INT (UNITS_PER_WORD)));
1084           
1085           new_mem = gen_rtx_MEM (SImode, src0);
1086           MEM_COPY_ATTRIBUTES (new_mem, dest);
1087           
1088           emit_insn (gen_rtx_SET (VOIDmode, new_mem, src1));
1089           emit_insn (gen_movsi_pop (src0));
1090         }
1091     }
1092   else
1093     /* This should have been prevented by the constraints on movdi_insn.  */
1094     abort ();
1095   
1096   val = get_insns ();
1097   end_sequence ();
1098
1099   return val;
1100 }
1101 /*}}}*/
1102 /* Local Variables: */
1103 /* folded-file: t   */
1104 /* End:             */