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