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