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