1 /* Subroutines for insn-output.c for Motorola 88000.
2    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3    2001, 2002 Free Software Foundation, Inc.
4    Contributed by Michael Tiemann (tiemann@mcc.com)
5    Currently maintained by (gcc@dg-rtp.dg.com)
6 
7 This file is part of GCC.
8 
9 GCC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13 
14 GCC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING.  If not, write to
21 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, USA.  */
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 "output.h"
35 #include "insn-attr.h"
36 #include "tree.h"
37 #include "function.h"
38 #include "expr.h"
39 #include "libfuncs.h"
40 #include "c-tree.h"
41 #include "flags.h"
42 #include "recog.h"
43 #include "toplev.h"
44 #include "tm_p.h"
45 #include "target.h"
46 #include "target-def.h"
47 #include "tree-gimple.h"
48 
49 #ifdef REGISTER_PREFIX
50 const char *m88k_register_prefix = REGISTER_PREFIX;
51 #else
52 const char *m88k_register_prefix = "";
53 #endif
54 char m88k_volatile_code;
55 
56 int m88k_fp_offset	= 0;	/* offset of frame pointer if used */
57 int m88k_stack_size	= 0;	/* size of allocated stack (including frame) */
58 int m88k_case_index;
59 
60 rtx m88k_compare_reg;		/* cmp output pseudo register */
61 rtx m88k_compare_op0;		/* cmpsi operand 0 */
62 rtx m88k_compare_op1;		/* cmpsi operand 1 */
63 
64 enum processor_type m88k_cpu;	/* target cpu */
65 
66 static void m88k_maybe_dead (rtx);
67 static void m88k_output_function_epilogue (FILE *, HOST_WIDE_INT);
68 static rtx m88k_struct_value_rtx (tree, int);
69 static int m88k_adjust_cost (rtx, rtx, rtx, int);
70 static bool m88k_handle_option (size_t, const char *, int);
71 static bool m88k_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
72 				    tree, bool);
73 static bool m88k_return_in_memory (tree, tree);
74 static void m88k_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
75 					 tree, int *, int);
76 static tree m88k_build_va_list (void);
77 static tree m88k_gimplify_va_arg (tree, tree, tree *, tree *);
78 static bool m88k_rtx_costs (rtx, int, int, int *);
79 static int m88k_address_cost (rtx);
80 static void m88k_output_file_start (void);
81 
82 /* Initialize the GCC target structure.  */
83 #if !defined(OBJECT_FORMAT_ELF)
84 #undef TARGET_ASM_BYTE_OP
85 #define TARGET_ASM_BYTE_OP "\tbyte\t"
86 #undef TARGET_ASM_ALIGNED_HI_OP
87 #define TARGET_ASM_ALIGNED_HI_OP "\thalf\t"
88 #undef TARGET_ASM_ALIGNED_SI_OP
89 #define TARGET_ASM_ALIGNED_SI_OP "\tword\t"
90 #undef TARGET_ASM_UNALIGNED_HI_OP
91 #define TARGET_ASM_UNALIGNED_HI_OP "\tuahalf\t"
92 #undef TARGET_ASM_UNALIGNED_SI_OP
93 #define TARGET_ASM_UNALIGNED_SI_OP "\tuaword\t"
94 #endif
95 
96 #undef TARGET_ASM_FUNCTION_EPILOGUE
97 #define TARGET_ASM_FUNCTION_EPILOGUE m88k_output_function_epilogue
98 
99 #undef TARGET_SCHED_ADJUST_COST
100 #define TARGET_SCHED_ADJUST_COST m88k_adjust_cost
101 
102 #undef TARGET_HANDLE_OPTION
103 #define TARGET_HANDLE_OPTION m88k_handle_option
104 
105 #undef TARGET_STRUCT_VALUE_RTX
106 #define TARGET_STRUCT_VALUE_RTX m88k_struct_value_rtx
107 
108 #undef TARGET_PASS_BY_REFERENCE
109 #define TARGET_PASS_BY_REFERENCE m88k_pass_by_reference
110 
111 #undef TARGET_RETURN_IN_MEMORY
112 #define TARGET_RETURN_IN_MEMORY m88k_return_in_memory
113 
114 #undef TARGET_PROMOTE_PROTOTYPES
115 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
116 
117 #undef TARGET_PROMOTE_FUNCTION_ARGS
118 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
119 
120 #undef TARGET_PROMOTE_FUNCTION_RETURN
121 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
122 
123 #undef TARGET_SETUP_INCOMING_VARARGS
124 #define TARGET_SETUP_INCOMING_VARARGS m88k_setup_incoming_varargs
125 
126 #undef TARGET_BUILD_BUILTIN_VA_LIST
127 #define TARGET_BUILD_BUILTIN_VA_LIST m88k_build_va_list
128 
129 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
130 #define TARGET_GIMPLIFY_VA_ARG_EXPR m88k_gimplify_va_arg
131 
132 #undef TARGET_RTX_COSTS
133 #define TARGET_RTX_COSTS m88k_rtx_costs
134 
135 #undef TARGET_ADDRESS_COST
136 #define TARGET_ADDRESS_COST m88k_address_cost
137 
138 #undef TARGET_ASM_FILE_START
139 #define TARGET_ASM_FILE_START m88k_output_file_start
140 /* from elfos.h
141 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
142 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
143 */
144 
145 struct gcc_target targetm = TARGET_INITIALIZER;
146 
147 /* Worker function for TARGET_STRUCT_VALUE_RTX.  */
148 
149 static rtx
m88k_struct_value_rtx(tree fntype ATTRIBUTE_UNUSED,int incoming ATTRIBUTE_UNUSED)150 m88k_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
151 		       int incoming ATTRIBUTE_UNUSED)
152 {
153   return gen_rtx_REG (Pmode, M88K_STRUCT_VALUE_REGNUM);
154 }
155 
156 /* Determine what instructions are needed to manufacture the integer VALUE
157    in the given MODE.  */
158 
159 enum m88k_instruction
classify_integer(enum machine_mode mode,int value)160 classify_integer (enum machine_mode mode, int value)
161 {
162   if (value == 0)
163     return m88k_zero;
164   else if (SMALL_INTVAL (value))
165     return m88k_or;
166   else if (SMALL_INTVAL (-value))
167     return m88k_subu;
168   else if (mode == HImode)
169     return m88k_or_lo16;
170   else if (mode == QImode)
171     return m88k_or_lo8;
172   else if (integer_ok_for_set (value))
173     return m88k_set;
174   else if ((value & 0xffff) == 0)
175     return m88k_oru_hi16;
176   else
177     return m88k_oru_or;
178 }
179 
180 /* Return the bit number in a compare word corresponding to CONDITION.  */
181 
182 int
condition_value(rtx condition)183 condition_value (rtx condition)
184 {
185   switch (GET_CODE (condition))
186     {
187     case UNORDERED:
188       return 0;
189     case ORDERED:
190       return 1;
191     case EQ:
192       return 2;
193     case NE:
194       return 3;
195     case GT:
196       return 4;
197     case LE:
198       return 5;
199     case LT:
200       return 6;
201     case GE:
202       return 7;
203     case GTU:
204       return 8;
205     case LEU:
206       return 9;
207     case LTU:
208       return 10;
209     case GEU:
210       return 11;
211     default:
212       gcc_unreachable ();
213     }
214 }
215 
216 bool
integer_ok_for_set(unsigned int value)217 integer_ok_for_set (unsigned int value)
218 {
219   unsigned int mask;
220 
221   if (value == 0)
222     return false;
223   /* All the "one" bits must be contiguous.  If so, MASK + 1 will be
224      a power of two or zero.  */
225   mask = value | (value - 1);
226   return POWER_OF_2_or_0 (mask + 1);
227 }
228 
229 const char *
output_load_const_int(enum machine_mode mode,rtx * operands)230 output_load_const_int (enum machine_mode mode, rtx *operands)
231 {
232   static const char *const patterns[] =
233     {
234       "or %0,%#r0,0",
235       "or %0,%#r0,%1",
236       "subu %0,%#r0,%n1",
237       "or %0,%#r0,%h1",
238       "or %0,%#r0,%q1",
239       "set %0,%#r0,%s1",
240       "or.u %0,%#r0,%X1",
241       "or.u %0,%#r0,%X1\n\tor %0,%0,%x1",
242     };
243 
244   gcc_assert (REG_P (operands[0])
245 	      && GET_CODE (operands[1]) == CONST_INT);
246   return patterns[classify_integer (mode, INTVAL (operands[1]))];
247 }
248 
249 /* These next two routines assume that floating point numbers are represented
250    in a manner which is consistent between host and target machines.  */
251 
252 const char *
output_load_const_float(rtx * operands)253 output_load_const_float (rtx *operands)
254 {
255   /* These can return 0 under some circumstances when cross-compiling.  */
256   operands[0] = operand_subword (operands[0], 0, 0, SFmode);
257   operands[1] = operand_subword (operands[1], 0, 0, SFmode);
258 
259   return output_load_const_int (SImode, operands);
260 }
261 
262 const char *
output_load_const_double(rtx * operands)263 output_load_const_double (rtx *operands)
264 {
265   rtx latehalf[2];
266 
267   /* These can return zero on some cross-compilers, but there's nothing
268      we can do about it.  */
269   latehalf[0] = operand_subword (operands[0], 1, 0, DFmode);
270   latehalf[1] = operand_subword (operands[1], 1, 0, DFmode);
271 
272   operands[0] = operand_subword (operands[0], 0, 0, DFmode);
273   operands[1] = operand_subword (operands[1], 0, 0, DFmode);
274 
275   output_asm_insn (output_load_const_int (SImode, operands), operands);
276 
277   operands[0] = latehalf[0];
278   operands[1] = latehalf[1];
279 
280   return output_load_const_int (SImode, operands);
281 }
282 
283 const char *
output_load_const_dimode(rtx * operands)284 output_load_const_dimode (rtx *operands)
285 {
286   rtx latehalf[2];
287 
288   latehalf[0] = operand_subword (operands[0], 1, 0, DImode);
289   latehalf[1] = operand_subword (operands[1], 1, 0, DImode);
290 
291   operands[0] = operand_subword (operands[0], 0, 0, DImode);
292   operands[1] = operand_subword (operands[1], 0, 0, DImode);
293 
294   output_asm_insn (output_load_const_int (SImode, operands), operands);
295 
296   operands[0] = latehalf[0];
297   operands[1] = latehalf[1];
298 
299   return output_load_const_int (SImode, operands);
300 }
301 
302 /* Emit insns to move operands[1] into operands[0].
303 
304    Return 1 if we have written out everything that needs to be done to
305    do the move.  Otherwise, return 0 and the caller will emit the move
306    normally.
307 
308    SCRATCH if nonzero can be used as a scratch register for the move
309    operation.  It is provided by a SECONDARY_RELOAD_* macro if needed.  */
310 
311 int
emit_move_sequence(rtx * operands,enum machine_mode mode,rtx scratch)312 emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch)
313 {
314   rtx operand0 = operands[0];
315   rtx operand1 = operands[1];
316 
317   if (CONSTANT_P (operand1) && flag_pic
318       && pic_address_needs_scratch (operand1))
319     operands[1] = operand1 = legitimize_address (1, operand1, NULL_RTX,
320 						 NULL_RTX);
321 
322   /* Handle most common case first: storing into a register.  */
323   if (register_operand (operand0, mode))
324     {
325       if (register_operand (operand1, mode)
326 	  || (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1))
327 	  || GET_CODE (operand1) == HIGH
328 	  /* Only `general_operands' can come here, so MEM is ok.  */
329 	  || GET_CODE (operand1) == MEM)
330 	{
331 	  /* Run this case quickly.  */
332 	  emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
333 	  return 1;
334 	}
335     }
336   else if (GET_CODE (operand0) == MEM)
337     {
338       if (register_operand (operand1, mode)
339 	  || (operand1 == const0_rtx && GET_MODE_SIZE (mode) <= UNITS_PER_WORD))
340 	{
341 	  /* Run this case quickly.  */
342 	  emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
343 	  return 1;
344 	}
345       if (! reload_in_progress && ! reload_completed)
346 	{
347 	  operands[0] = validize_mem (operand0);
348 	  operands[1] = operand1 = force_reg (mode, operand1);
349 	}
350     }
351 
352   /* Simplify the source if we need to.  */
353   if (GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
354     {
355       if (GET_CODE (operand1) != CONST_INT
356 	  && GET_CODE (operand1) != CONST_DOUBLE)
357 	{
358 	  rtx temp = ((reload_in_progress || reload_completed)
359 		      ? operand0 : NULL_RTX);
360 	  operands[1] = legitimize_address (flag_pic
361 					    && symbolic_address_p (operand1),
362 					    operand1, temp, scratch);
363 	  if (mode != SImode)
364 	    operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
365 	}
366     }
367 
368   /* Now have insn-emit do whatever it normally does.  */
369   return 0;
370 }
371 
372 /* Return a legitimate reference for ORIG (either an address or a MEM)
373    using the register REG.  If PIC and the address is already
374    position-independent, use ORIG.  Newly generated position-independent
375    addresses go into a reg.  This is REG if nonzero, otherwise we
376    allocate register(s) as necessary.  If this is called during reload,
377    and we need a second temp register, then we use SCRATCH, which is
378    provided via the SECONDARY_INPUT_RELOAD_CLASS mechanism.  */
379 
380 struct rtx_def *
legitimize_address(int pic,rtx orig,rtx reg,rtx scratch)381 legitimize_address (int pic, rtx orig, rtx reg, rtx scratch)
382 {
383   rtx addr = (GET_CODE (orig) == MEM ? XEXP (orig, 0) : orig);
384   rtx new = orig;
385   rtx temp, insn;
386 
387   if (pic)
388     {
389       if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
390 	{
391 	  if (reg == NULL_RTX)
392 	    {
393 	      gcc_assert (!reload_in_progress && !reload_completed);
394 	      reg = gen_reg_rtx (Pmode);
395 	    }
396 
397 	  if (flag_pic == 2)
398 	    {
399 	      /* If not during reload, allocate another temp reg here for
400 		 loading in the address, so that these instructions can be
401 		 optimized properly.  */
402 	      temp = ((reload_in_progress || reload_completed)
403 		      ? reg : gen_reg_rtx (Pmode));
404 
405 	      /* Must put the SYMBOL_REF inside an UNSPEC here so that cse
406 		 won't get confused into thinking that these two instructions
407 		 are loading in the true address of the symbol.  If in the
408 		 future a PIC rtx exists, that should be used instead.  */
409 	      emit_insn (gen_movsi_high_pic (temp, addr));
410 	      emit_insn (gen_movsi_lo_sum_pic (temp, temp, addr));
411 	      addr = temp;
412 	    }
413 
414 	  new = gen_rtx_MEM (Pmode,
415 			     gen_rtx_PLUS (SImode,
416 					   pic_offset_table_rtx, addr));
417 
418 	  current_function_uses_pic_offset_table = 1;
419 	  MEM_READONLY_P (new) = 1;
420 	  insn = emit_move_insn (reg, new);
421 	  /* Put a REG_EQUAL note on this insn, so that it can be optimized
422 	     by loop.  */
423 	  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig,
424 						REG_NOTES (insn));
425 	  new = reg;
426 	}
427       else if (GET_CODE (addr) == CONST)
428 	{
429 	  rtx base;
430 
431 	  if (GET_CODE (XEXP (addr, 0)) == PLUS
432 	      && XEXP (XEXP (addr, 0), 0) == pic_offset_table_rtx)
433 	    return orig;
434 
435 	  if (reg == NULL_RTX)
436 	    {
437 	      gcc_assert (!reload_in_progress && !reload_completed);
438 	      reg = gen_reg_rtx (Pmode);
439 	    }
440 
441 	  gcc_assert (GET_CODE (XEXP (addr, 0)) == PLUS);
442 
443 	  base = legitimize_address (1, XEXP (XEXP (addr, 0), 0), reg,
444 				     NULL_RTX);
445 	  addr = legitimize_address (1, XEXP (XEXP (addr, 0), 1),
446 				     base == reg ? NULL_RTX : reg, NULL_RTX);
447 
448 	  if (GET_CODE (addr) == CONST_INT)
449 	    {
450 	      if (ADD_INT (addr))
451 		return plus_constant (base, INTVAL (addr));
452 	      else if (! reload_in_progress && ! reload_completed)
453 		addr = force_reg (Pmode, addr);
454 	      /* We can't create any new registers during reload, so use the
455 		 SCRATCH reg provided by the reload_insi pattern.  */
456 	      else if (scratch)
457 		{
458 		  emit_move_insn (scratch, addr);
459 		  addr = scratch;
460 		}
461 	      else
462 		/* If we reach here, then the SECONDARY_INPUT_RELOAD_CLASS
463 		   macro needs to be adjusted so that a scratch reg is provided
464 		   for this address.  */
465 		gcc_unreachable ();
466 	    }
467 	  new = gen_rtx_PLUS (SImode, base, addr);
468 	  /* Should we set special REG_NOTEs here?  */
469 	}
470     }
471   else
472     {
473       if (reg == NULL_RTX)
474 	{
475 	  gcc_assert (!reload_in_progress && !reload_completed);
476 	  reg = gen_reg_rtx (Pmode);
477 	}
478 
479       emit_insn (gen_rtx_SET (VOIDmode,
480 			      reg, gen_rtx_HIGH (SImode, addr)));
481       new = gen_rtx_LO_SUM (SImode, reg, addr);
482     }
483 
484   if (GET_CODE (orig) == MEM)
485     {
486       new = gen_rtx_MEM (GET_MODE (orig), new);
487       MEM_COPY_ATTRIBUTES (new, orig);
488     }
489   return new;
490 }
491 
492 /* Support functions for code to emit a block move.  There are two methods
493    used to perform the block move:
494    + call memcpy
495    + produce an inline sequence of ld/st instructions
496  */
497 
498 static const enum machine_mode mode_from_align[] =
499 			      {VOIDmode, QImode, HImode, VOIDmode, SImode,
500 			       VOIDmode, VOIDmode, VOIDmode, DImode};
501 
502 static void block_move_sequence (rtx, rtx, rtx, rtx, int, int);
503 
504 /* Emit code to perform a block move.  Choose the best method.
505 
506    OPERANDS[0] is the destination.
507    OPERANDS[1] is the source.
508    OPERANDS[2] is the size.
509    OPERANDS[3] is the alignment safe to use.  */
510 
511 void
expand_block_move(rtx dest_mem,rtx src_mem,rtx * operands)512 expand_block_move (rtx dest_mem, rtx src_mem, rtx *operands)
513 {
514   int align = INTVAL (operands[3]);
515   int constp = (GET_CODE (operands[2]) == CONST_INT);
516   int bytes = (constp ? INTVAL (operands[2]) : 0);
517 
518   if (constp && bytes <= 0)
519     return;
520 
521   /* Determine machine mode to do move with.  */
522   if (align > 4 && !TARGET_88110)
523     align = 4;
524   else
525     gcc_assert (align > 0 && align != 3); /* block move invalid alignment.  */
526 
527   if (constp && bytes <= 3 * align)
528     block_move_sequence (operands[0], dest_mem, operands[1], src_mem,
529 			 bytes, align);
530 
531   else
532     {
533       emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "memcpy"), 0,
534 			 VOIDmode, 3,
535 			 operands[0], Pmode,
536 			 operands[1], Pmode,
537 			 convert_to_mode (TYPE_MODE (sizetype), operands[2],
538 					  TYPE_UNSIGNED (sizetype)),
539 			 TYPE_MODE (sizetype));
540     }
541 }
542 
543 /* Emit code to perform a block move with an offset sequence of ld/st
544    instructions (..., ld 0, st 1, ld 1, st 0, ...).  SIZE and ALIGN are
545    known constants.  DEST and SRC are registers.  */
546 
547 static void
block_move_sequence(rtx dest,rtx dest_mem,rtx src,rtx src_mem,int size,int align)548 block_move_sequence (rtx dest, rtx dest_mem, rtx src, rtx src_mem, int size,
549 		     int align)
550 {
551   rtx temp[2];
552   enum machine_mode mode[2];
553   int amount[2];
554   int active[2];
555   int phase = 0;
556   int next;
557   int offset_ld = 0;
558   int offset_st = 0;
559 
560   active[0] = active[1] = FALSE;
561 
562   /* Establish parameters for the first load and for the second load if
563      it is known to be the same mode as the first.  */
564   amount[0] = amount[1] = align;
565   mode[0] = mode_from_align[align];
566   temp[0] = gen_reg_rtx (mode[0]);
567   if (size >= 2 * align)
568     {
569       mode[1] = mode[0];
570       temp[1] = gen_reg_rtx (mode[1]);
571     }
572 
573   do
574     {
575       next = phase;
576       phase = !phase;
577 
578       if (size > 0)
579 	{
580 	  /* Change modes as the sequence tails off.  */
581 	  if (size < amount[next])
582 	    {
583 	      amount[next] = (size >= 4 ? 4 : (size >= 2 ? 2 : 1));
584 	      mode[next] = mode_from_align[amount[next]];
585 	      temp[next] = gen_reg_rtx (mode[next]);
586 	    }
587 	  size -= amount[next];
588 	  emit_move_insn (temp[next],
589 			  adjust_address (src_mem, mode[next], offset_ld));
590 	  offset_ld += amount[next];
591 	  active[next] = TRUE;
592 	}
593 
594       if (active[phase])
595 	{
596 	  active[phase] = FALSE;
597 	  emit_move_insn (adjust_address (dest_mem, mode[phase], offset_st),
598 			  temp[phase]);
599 	  offset_st += amount[phase];
600 	}
601     }
602   while (active[next]);
603 }
604 
605 /* Emit the code to do an AND operation.  */
606 
607 const char *
output_and(rtx operands[])608 output_and (rtx operands[])
609 {
610   unsigned int value;
611 
612   if (REG_P (operands[2]))
613     return "and %0,%1,%2";
614 
615   value = INTVAL (operands[2]);
616   if (SMALL_INTVAL (value))
617     return "mask %0,%1,%2";
618   else if ((value & 0xffff0000) == 0xffff0000)
619     return "and %0,%1,%x2";
620   else if ((value & 0xffff) == 0xffff)
621     return "and.u %0,%1,%X2";
622   else if ((value & 0xffff) == 0)
623     return "mask.u %0,%1,%X2";
624   else if (integer_ok_for_set (~value))
625     return "clr %0,%1,%S2";
626   else
627     return "and.u %0,%1,%X2\n\tand %0,%0,%x2";
628 }
629 
630 /* Emit the code to do an inclusive OR operation.  */
631 
632 const char *
output_ior(rtx operands[])633 output_ior (rtx operands[])
634 {
635   unsigned int value;
636 
637   if (REG_P (operands[2]))
638     return "or %0,%1,%2";
639 
640   value = INTVAL (operands[2]);
641   if (SMALL_INTVAL (value))
642     return "or %0,%1,%2";
643   else if ((value & 0xffff) == 0)
644     return "or.u %0,%1,%X2";
645   else if (integer_ok_for_set (value))
646     return "set %0,%1,%s2";
647   else
648     return "or.u %0,%1,%X2\n\tor %0,%0,%x2";
649 }
650 
651 /* Emit the instructions for doing an XOR.  */
652 
653 const char *
output_xor(rtx operands[])654 output_xor (rtx operands[])
655 {
656   unsigned int value;
657 
658   if (REG_P (operands[2]))
659     return "xor %0,%1,%2";
660 
661   value = INTVAL (operands[2]);
662   if (SMALL_INTVAL (value))
663     return "xor %0,%1,%2";
664   else if ((value & 0xffff) == 0)
665     return "xor.u %0,%1,%X2";
666   else
667     return "xor.u %0,%1,%X2\n\txor %0,%0,%x2";
668 }
669 
670 /* Output a call.  Normally this is just bsr or jsr, but this also deals with
671    accomplishing a branch after the call by incrementing r1.
672 
673    It would seem the same idea could be used to tail call, but in this case,
674    the epilogue will be non-null.  */
675 
676 const char *
output_call(rtx operands[],rtx addr)677 output_call (rtx operands[], rtx addr)
678 {
679   operands[0] = addr;
680   if (final_sequence)
681     {
682       rtx jump;
683       rtx seq_insn;
684 
685       /* This can be generalized, but there is currently no need.  */
686       gcc_assert (XVECLEN (final_sequence, 0) == 2);
687 
688       /* The address of interior insns is not computed, so use the sequence.  */
689       seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
690       jump = XVECEXP (final_sequence, 0, 1);
691       if (GET_CODE (jump) == JUMP_INSN)
692 	{
693 	  const char *last;
694 	  rtx dest = XEXP (SET_SRC (PATTERN (jump)), 0);
695 	  int delta = 4 * (INSN_ADDRESSES (INSN_UID (dest))
696 			   - INSN_ADDRESSES (INSN_UID (seq_insn))
697 			   - 2);
698 
699 	  /* Delete the jump.  */
700 	  PUT_CODE (jump, NOTE);
701 	  NOTE_LINE_NUMBER (jump) = NOTE_INSN_DELETED;
702 	  NOTE_SOURCE_FILE (jump) = 0;
703 
704 	  /* We only do this optimization if -O2, modifying the value of
705 	     r1 in the delay slot confuses debuggers and profilers on some
706 	     systems.
707 
708 	     If we loose, we must use the non-delay form.  This is unlikely
709 	     to ever happen.  If it becomes a problem, claim that a call
710 	     has two delay slots and only the second can be filled with
711 	     a jump.
712 
713 	     The 88110 can lose when a jsr.n r1 is issued and a page fault
714 	     occurs accessing the delay slot.  So don't use jsr.n form when
715 	     jumping thru r1.
716 	   */
717 	  if (optimize < 2
718 	      || ! ADD_INTVAL (delta)
719 	      || (REG_P (addr) && REGNO (addr) == 1))
720 	    {
721 	      operands[1] = dest;
722 	      return (REG_P (addr)
723 		      ? "jsr %0\n\tbr %l1"
724 		      : (flag_pic
725 			 ? "bsr %0#plt\n\tbr %l1"
726 			 : "bsr %0\n\tbr %l1"));
727 	    }
728 
729 	  /* Output the short branch form.  */
730 	  output_asm_insn ((REG_P (addr)
731 			    ? "jsr.n %0"
732 			    : (flag_pic ? "bsr.n %0#plt" : "bsr.n %0")),
733 			   operands);
734 
735 	  last = (delta < 0
736 		  ? "subu %#r1,%#r1,.-%l0+4"
737 		  : "addu %#r1,%#r1,%l0-.-4");
738 	  operands[0] = dest;
739 
740 	  return last;
741 	}
742     }
743   return (REG_P (addr)
744 	  ? "jsr%. %0"
745 	  : (flag_pic ? "bsr%. %0#plt" : "bsr%. %0"));
746 }
747 
748 /* Return truth value of the statement that this conditional branch is likely
749    to fall through.  CONDITION, is the condition that JUMP_INSN is testing.  */
750 
751 bool
mostly_false_jump(rtx jump_insn,rtx condition)752 mostly_false_jump (rtx jump_insn, rtx condition)
753 {
754   rtx target_label = JUMP_LABEL (jump_insn);
755   rtx insnt, insnj;
756 
757   /* Much of this isn't computed unless we're optimizing.  */
758   if (optimize == 0)
759     return false;
760 
761   /* Determine if one path or the other leads to a return.  */
762   for (insnt = NEXT_INSN (target_label);
763        insnt;
764        insnt = NEXT_INSN (insnt))
765     {
766       if (GET_CODE (insnt) == JUMP_INSN)
767 	break;
768       else if (GET_CODE (insnt) == INSN
769 	       && GET_CODE (PATTERN (insnt)) == SEQUENCE
770 	       && GET_CODE (XVECEXP (PATTERN (insnt), 0, 0)) == JUMP_INSN)
771 	{
772 	  insnt = XVECEXP (PATTERN (insnt), 0, 0);
773 	  break;
774 	}
775     }
776   if (insnt
777       && (GET_CODE (PATTERN (insnt)) == RETURN
778 	  || (GET_CODE (PATTERN (insnt)) == SET
779 	      && GET_CODE (SET_SRC (PATTERN (insnt))) == REG
780 	      && REGNO (SET_SRC (PATTERN (insnt))) == 1)))
781     insnt = NULL_RTX;
782 
783   for (insnj = NEXT_INSN (jump_insn);
784        insnj;
785        insnj = NEXT_INSN (insnj))
786     {
787       if (GET_CODE (insnj) == JUMP_INSN)
788 	break;
789       else if (GET_CODE (insnj) == INSN
790 	       && GET_CODE (PATTERN (insnj)) == SEQUENCE
791 	       && GET_CODE (XVECEXP (PATTERN (insnj), 0, 0)) == JUMP_INSN)
792 	{
793 	  insnj = XVECEXP (PATTERN (insnj), 0, 0);
794 	  break;
795 	}
796     }
797   if (insnj
798       && (GET_CODE (PATTERN (insnj)) == RETURN
799 	  || (GET_CODE (PATTERN (insnj)) == SET
800 	      && GET_CODE (SET_SRC (PATTERN (insnj))) == REG
801 	      && REGNO (SET_SRC (PATTERN (insnj))) == 1)))
802     insnj = NULL_RTX;
803 
804   /* Predict to not return.  */
805   if ((insnt == NULL_RTX) != (insnj == NULL_RTX))
806     return (insnt == NULL_RTX);
807 
808   /* Predict loops to loop.  */
809   for (insnt = PREV_INSN (target_label);
810        insnt && GET_CODE (insnt) == NOTE;
811        insnt = PREV_INSN (insnt))
812     if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_END)
813       return true;
814     else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_BEG)
815       return false;
816 
817   /* Predict backward branches usually take.  */
818   if (final_sequence)
819     insnj = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
820   else
821     insnj = jump_insn;
822   if (INSN_ADDRESSES (INSN_UID (insnj))
823       > INSN_ADDRESSES (INSN_UID (target_label)))
824     return false;
825 
826   /* EQ tests are usually false and NE tests are usually true.  Also,
827      most quantities are positive, so we can make the appropriate guesses
828      about signed comparisons against zero.  Consider unsigned comparisons
829      to be a range check and assume quantities to be in range.  */
830   switch (GET_CODE (condition))
831     {
832     case CONST_INT:
833       /* Unconditional branch.  */
834       return false;
835     case EQ:
836       return true;
837     case NE:
838       return false;
839     case LE:
840     case LT:
841     case GEU:
842     case GTU: /* Must get casesi right at least.  */
843       if (XEXP (condition, 1) == const0_rtx)
844         return true;
845       break;
846     case GE:
847     case GT:
848     case LEU:
849     case LTU:
850       if (XEXP (condition, 1) == const0_rtx)
851 	return false;
852       break;
853     default:
854       break;
855     }
856 
857   return false;
858 }
859 
860 /* Return true if the operand is a power of two and is a floating
861    point type (to optimize division by power of two into multiplication).  */
862 
863 bool
real_power_of_2_operand(rtx op)864 real_power_of_2_operand (rtx op)
865 {
866   REAL_VALUE_TYPE d;
867   union {
868     long l[2];
869     struct {				/* IEEE double precision format */
870       unsigned sign	 :  1;
871       unsigned exponent  : 11;
872       unsigned mantissa1 : 20;
873       unsigned mantissa2;
874     } s;
875     struct {				/* IEEE double format to quick check */
876       unsigned sign	 :  1;		/* if it fits in a float */
877       unsigned exponent1 :  4;
878       unsigned exponent2 :  7;
879       unsigned mantissa1 : 20;
880       unsigned mantissa2;
881     } s2;
882   } u;
883 
884   if (GET_MODE (op) != DFmode && GET_MODE (op) != SFmode)
885     return false;
886 
887   if (GET_CODE (op) != CONST_DOUBLE)
888     return false;
889 
890   REAL_VALUE_FROM_CONST_DOUBLE (d, op);
891   REAL_VALUE_TO_TARGET_DOUBLE (d, u.l);
892 
893   if (u.s.mantissa1 != 0 || u.s.mantissa2 != 0	/* not a power of two */
894       || u.s.exponent == 0			/* constant 0.0 */
895       || u.s.exponent == 0x7ff			/* NaN */
896       || (u.s2.exponent1 != 0x8 && u.s2.exponent1 != 0x7))
897     return false;				/* const won't fit in float */
898 
899   return true;
900 }
901 
902 /* Make OP legitimate for mode MODE.  Currently this only deals with DFmode
903    operands, putting them in registers and making CONST_DOUBLE values
904    SFmode where possible.  */
905 
906 struct rtx_def *
legitimize_operand(rtx op,enum machine_mode mode)907 legitimize_operand (rtx op, enum machine_mode mode)
908 {
909   rtx temp;
910   REAL_VALUE_TYPE d;
911   union {
912     long l[2];
913     struct {				/* IEEE double precision format */
914       unsigned sign	 :  1;
915       unsigned exponent  : 11;
916       unsigned mantissa1 : 20;
917       unsigned mantissa2;
918     } s;
919     struct {				/* IEEE double format to quick check */
920       unsigned sign	 :  1;		/* if it fits in a float */
921       unsigned exponent1 :  4;
922       unsigned exponent2 :  7;
923       unsigned mantissa1 : 20;
924       unsigned mantissa2;
925     } s2;
926   } u;
927 
928   if (GET_CODE (op) == REG || mode != DFmode)
929     return op;
930 
931   if (GET_CODE (op) == CONST_DOUBLE)
932     {
933       REAL_VALUE_FROM_CONST_DOUBLE (d, op);
934       REAL_VALUE_TO_TARGET_DOUBLE (d, u.l);
935       if (u.s.exponent != 0x7ff /* NaN */
936 	  && u.s.mantissa2 == 0 /* Mantissa fits */
937 	  && (u.s2.exponent1 == 0x8 || u.s2.exponent1 == 0x7) /* Exponent fits */
938 	  && (temp = simplify_unary_operation (FLOAT_TRUNCATE, SFmode,
939 					       op, mode)) != 0)
940 	return gen_rtx_FLOAT_EXTEND (mode, force_reg (SFmode, temp));
941     }
942   else if (register_operand (op, mode))
943     return op;
944 
945   return force_reg (mode, op);
946 }
947 
948 /* Returns true if OP is either a symbol reference or a sum of a symbol
949    reference and a constant.  */
950 
951 bool
symbolic_address_p(rtx op)952 symbolic_address_p (rtx op)
953 {
954   switch (GET_CODE (op))
955     {
956     case SYMBOL_REF:
957     case LABEL_REF:
958       return true;
959 
960     case CONST:
961       op = XEXP (op, 0);
962       return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
963 	       || GET_CODE (XEXP (op, 0)) == LABEL_REF)
964 	      && GET_CODE (XEXP (op, 1)) == CONST_INT);
965 
966     default:
967       return false;
968     }
969 }
970 
971 /* Nonzero if this is a bitmask filling the bottom bits, for optimizing and +
972    shift left combinations into a single mak instruction.  */
973 
974 bool
mak_mask_p(int value)975 mak_mask_p (int value)
976 {
977   return (value && POWER_OF_2_or_0 (value + 1));
978 }
979 
980 /* Output to FILE the start of the assembler file.  */
981 
982 static void
m88k_output_file_start(void)983 m88k_output_file_start (void)
984 {
985   if (TARGET_88110)
986     fprintf (asm_out_file, "%s\n", REQUIRES_88110_ASM_OP);
987 
988   default_file_start ();
989 }
990 
991 /* Generate the assembly code for function entry.
992 
993    The prologue is responsible for setting up the stack frame,
994    initializing the frame pointer register, saving registers that must be
995    saved, and allocating SIZE additional bytes of storage for the
996    local variables.  SIZE is an integer.  FILE is a stdio
997    stream to which the assembler code should be output.
998 
999    The label for the beginning of the function need not be output by this
1000    macro.  That has already been done when the macro is run.
1001 
1002    To determine which registers to save, the macro can refer to the array
1003    `regs_ever_live': element R is nonzero if hard register
1004    R is used anywhere within the function.  This implies the
1005    function prologue should save register R, but not if it is one
1006    of the call-used registers.
1007 
1008    On machines where functions may or may not have frame-pointers, the
1009    function entry code must vary accordingly; it must set up the frame
1010    pointer if one is wanted, and not otherwise.  To determine whether a
1011    frame pointer is in wanted, the macro can refer to the variable
1012    `frame_pointer_needed'.  The variable's value will be 1 at run
1013    time in a function that needs a frame pointer.
1014 
1015    On machines where an argument may be passed partly in registers and
1016    partly in memory, this macro must examine the variable
1017    `current_function_pretend_args_size', and allocate that many bytes
1018    of uninitialized space on the stack just underneath the first argument
1019    arriving on the stack.  (This may not be at the very end of the stack,
1020    if the calling sequence has pushed anything else since pushing the stack
1021    arguments.  But usually, on such machines, nothing else has been pushed
1022    yet, because the function prologue itself does all the pushing.)
1023 
1024    If `ACCUMULATE_OUTGOING_ARGS' is defined, the variable
1025    `current_function_outgoing_args_size' contains the size in bytes
1026    required for the outgoing arguments.  This macro must add that
1027    amount of uninitialized space to very bottom of the stack.
1028 
1029    The stack frame we use looks like this:
1030 
1031  caller                                                  callee
1032         |==============================================|
1033         |                caller's frame                |
1034         |==============================================|
1035         |     [caller's outgoing memory arguments]     |
1036   sp -> |==============================================| <- ap
1037         |            [local variable space]            |
1038         |----------------------------------------------|
1039         |            [return address (r1)]             |
1040         |----------------------------------------------|
1041         |        [previous frame pointer (r30)]        |
1042         |==============================================| <- fp
1043         |       [preserved registers (r25..r14)]       |
1044         |----------------------------------------------|
1045         |       [preserved registers (x29..x22)]       |
1046         |==============================================|
1047         |    [dynamically allocated space (alloca)]    |
1048         |==============================================|
1049         |     [callee's outgoing memory arguments]     |
1050         |==============================================| <- sp
1051 
1052   Notes:
1053 
1054   r1 and r30 must be saved if debugging.
1055 
1056   fp (if present) is located two words down from the local
1057   variable space.
1058   */
1059 
1060 static rtx emit_add (rtx, rtx, int);
1061 static void preserve_registers (int, int);
1062 static void emit_ldst (int, int, enum machine_mode, int);
1063 
1064 static int  nregs;
1065 static int  nxregs;
1066 static char save_regs[FIRST_PSEUDO_REGISTER];
1067 static int  frame_laid_out;
1068 static int  frame_size;
1069 
1070 #define STACK_UNIT_BOUNDARY (STACK_BOUNDARY / BITS_PER_UNIT)
1071 #define ROUND_CALL_BLOCK_SIZE(BYTES) \
1072   (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1))
1073 
1074 /* Establish the position of the FP relative to the SP.  This is done
1075    either during output_function_prologue() or by
1076    INITIAL_ELIMINATION_OFFSET.  */
1077 
1078 void
m88k_layout_frame(void)1079 m88k_layout_frame (void)
1080 {
1081   int regno, sp_size;
1082 
1083   if (frame_laid_out && reload_completed)
1084     return;
1085 
1086   frame_laid_out = 1;
1087 
1088   memset ((char *) &save_regs[0], 0, sizeof (save_regs));
1089   sp_size = nregs = nxregs = 0;
1090   frame_size = get_frame_size ();
1091 
1092   /* Profiling requires a stack frame.  */
1093   if (current_function_profile)
1094     frame_pointer_needed = 1;
1095 
1096   /* If we are producing debug information, store r1 and r30 where the
1097      debugger wants to find them (r30 at r30+0, r1 at r30+4).  Space has
1098      already been reserved for r1/r30 in STARTING_FRAME_OFFSET.  */
1099   if (write_symbols != NO_DEBUG)
1100     save_regs[1] = 1;
1101 
1102   /* If we are producing PIC, save the addressing base register and r1.  */
1103   if (flag_pic && current_function_uses_pic_offset_table)
1104     {
1105       save_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
1106       nregs++;
1107     }
1108 
1109   /* If a frame is requested, save the previous FP, and the return
1110      address (r1), so that a traceback can be done without using tdesc
1111      information.  Otherwise, simply save the FP if it is used as
1112      a preserve register.  */
1113   if (frame_pointer_needed)
1114     save_regs[FRAME_POINTER_REGNUM] = save_regs[1] = 1;
1115   else
1116     {
1117       if (regs_ever_live[FRAME_POINTER_REGNUM])
1118 	save_regs[FRAME_POINTER_REGNUM] = 1;
1119       /* If there is a call, r1 needs to be saved as well.  */
1120       if (regs_ever_live[1])
1121 	save_regs[1] = 1;
1122     }
1123 
1124   /* Figure out which extended register(s) needs to be saved.  */
1125   for (regno = FIRST_EXTENDED_REGISTER + 1; regno < FIRST_PSEUDO_REGISTER;
1126        regno++)
1127     if (regs_ever_live[regno] && ! call_used_regs[regno])
1128       {
1129 	save_regs[regno] = 1;
1130 	nxregs++;
1131       }
1132 
1133   /* Figure out which normal register(s) needs to be saved.  */
1134   for (regno = 2; regno < FRAME_POINTER_REGNUM; regno++)
1135     if (regs_ever_live[regno] && ! call_used_regs[regno])
1136       {
1137 	save_regs[regno] = 1;
1138 	nregs++;
1139       }
1140 
1141   /* Achieve greatest use of double memory ops.  Either we end up saving
1142      r30 or we use that slot to align the registers we do save.  */
1143   if (nregs >= 2 && save_regs[1] && !save_regs[FRAME_POINTER_REGNUM])
1144     sp_size += 4;
1145 
1146   nregs += save_regs[1] + save_regs[FRAME_POINTER_REGNUM];
1147   /* if we need to align extended registers, add a word */
1148   if (nxregs > 0 && (nregs & 1) != 0)
1149     sp_size +=4;
1150   sp_size += 4 * nregs;
1151   sp_size += 8 * nxregs;
1152   sp_size += current_function_outgoing_args_size;
1153 
1154   /* The first two saved registers are placed above the new frame pointer
1155      if any.  In the only case this matters, they are r1 and r30. */
1156   if (frame_pointer_needed || sp_size)
1157     m88k_fp_offset = ROUND_CALL_BLOCK_SIZE (sp_size - STARTING_FRAME_OFFSET);
1158   else
1159     m88k_fp_offset = -STARTING_FRAME_OFFSET;
1160   m88k_stack_size = m88k_fp_offset + STARTING_FRAME_OFFSET;
1161 
1162   /* First, combine m88k_stack_size and size.  If m88k_stack_size is
1163      nonzero, align the frame size to 8 mod 16; otherwise align the
1164      frame size to 0 mod 16.  (If stacks are 8 byte aligned, this ends
1165      up as a NOP.  */
1166   {
1167     int need
1168       = ((m88k_stack_size ? STACK_UNIT_BOUNDARY - STARTING_FRAME_OFFSET : 0)
1169 	 - (frame_size % STACK_UNIT_BOUNDARY));
1170     if (need < 0)
1171       need += STACK_UNIT_BOUNDARY;
1172     m88k_stack_size
1173       = ROUND_CALL_BLOCK_SIZE (m88k_stack_size + frame_size + need
1174 			       + current_function_pretend_args_size);
1175   }
1176 }
1177 
1178 /* Return true if this function is known to have a null prologue.  */
1179 
1180 bool
null_prologue(void)1181 null_prologue (void)
1182 {
1183   if (! reload_completed)
1184     return false;
1185   m88k_layout_frame ();
1186   return (! frame_pointer_needed
1187 	  && nregs == 0
1188 	  && nxregs == 0
1189 	  && m88k_stack_size == 0);
1190 }
1191 
1192 static void
m88k_maybe_dead(rtx insn)1193 m88k_maybe_dead (rtx insn)
1194 {
1195   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
1196 					const0_rtx,
1197 					REG_NOTES (insn));
1198 }
1199 
1200 void
m88k_expand_prologue(void)1201 m88k_expand_prologue (void)
1202 {
1203   rtx insn;
1204 
1205   m88k_layout_frame ();
1206 
1207   if (warn_stack_larger_than && m88k_stack_size > stack_larger_than_size)
1208     warning (0, "stack usage is %d bytes", m88k_stack_size);
1209 
1210   if (m88k_stack_size)
1211     {
1212       insn = emit_add (stack_pointer_rtx, stack_pointer_rtx, -m88k_stack_size);
1213       RTX_FRAME_RELATED_P (insn) = 1;
1214 
1215       /* If the stack pointer adjustment has required a temporary register,
1216 	 tell the DWARF code how to understand this sequence.  */
1217       if (! ADD_INTVAL (m88k_stack_size))
1218 	REG_NOTES (insn)
1219 	  = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
1220 			       gen_rtx_SET (VOIDmode, stack_pointer_rtx,
1221 				     gen_rtx_PLUS (Pmode, stack_pointer_rtx,
1222 						   GEN_INT (-m88k_stack_size))),
1223 			       REG_NOTES(insn));
1224     }
1225 
1226   if (nregs || nxregs)
1227     preserve_registers (m88k_fp_offset + 4, 1);
1228 
1229   if (frame_pointer_needed)
1230     {
1231       /* Be sure to emit this instruction after all register saves, DWARF
1232 	 information depends on this.  */
1233       emit_insn (gen_blockage ());
1234       insn = emit_add (frame_pointer_rtx, stack_pointer_rtx, m88k_fp_offset);
1235       RTX_FRAME_RELATED_P (insn) = 1;
1236     }
1237 
1238   if (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM])
1239     {
1240       rtx return_reg = gen_rtx_REG (SImode, 1);
1241       rtx label = gen_label_rtx ();
1242 
1243       m88k_maybe_dead (emit_insn (gen_locate1 (pic_offset_table_rtx, label)));
1244       m88k_maybe_dead (emit_insn (gen_locate2 (pic_offset_table_rtx, label)));
1245       m88k_maybe_dead (emit_insn (gen_addsi3 (pic_offset_table_rtx,
1246 					      pic_offset_table_rtx,
1247 					      return_reg)));
1248     }
1249   if (current_function_profile)
1250     emit_insn (gen_blockage ());
1251 }
1252 
1253 /* This function generates the assembly code for function exit,
1254    on machines that need it.
1255 
1256    The function epilogue should not depend on the current stack pointer!
1257    It should use the frame pointer only, if there is a frame pointer.
1258    This is mandatory because of alloca; we also take advantage of it to
1259    omit stack adjustments before returning.  */
1260 
1261 static void
m88k_output_function_epilogue(FILE * stream,HOST_WIDE_INT size ATTRIBUTE_UNUSED)1262 m88k_output_function_epilogue (FILE *stream,
1263 			       HOST_WIDE_INT size ATTRIBUTE_UNUSED)
1264 {
1265   frame_laid_out = 0;
1266 }
1267 
1268 void
m88k_expand_epilogue(void)1269 m88k_expand_epilogue (void)
1270 {
1271   if (frame_pointer_needed)
1272     {
1273       emit_insn (gen_blockage ());
1274       emit_add (stack_pointer_rtx, frame_pointer_rtx, -m88k_fp_offset);
1275     }
1276 
1277   if (nregs || nxregs)
1278     preserve_registers (m88k_fp_offset + 4, 0);
1279 
1280   emit_insn (gen_blockage ());
1281 
1282   if (m88k_stack_size)
1283     {
1284       emit_add (stack_pointer_rtx, stack_pointer_rtx, m88k_stack_size);
1285     }
1286 
1287   emit_insn (gen_indirect_jump (INCOMING_RETURN_ADDR_RTX));
1288 
1289   emit_insn (gen_blockage ());
1290 }
1291 
1292 /* Emit insns to set DSTREG to SRCREG + AMOUNT during the prologue or
1293    epilogue.  */
1294 
1295 static rtx
emit_add(rtx dstreg,rtx srcreg,int amount)1296 emit_add (rtx dstreg, rtx srcreg, int amount)
1297 {
1298   rtx incr = GEN_INT (abs (amount));
1299 
1300   if (! ADD_INTVAL (amount))
1301     {
1302       rtx temp = gen_rtx_REG (SImode, TEMP_REGNUM);
1303       emit_move_insn (temp, incr);
1304       incr = temp;
1305     }
1306   return emit_insn ((amount < 0 ? gen_subsi3 : gen_addsi3) (dstreg, srcreg,
1307 							    incr));
1308 }
1309 
1310 /* Save/restore the preserve registers.  base is the highest offset from
1311    r31 at which a register is stored.  store_p is true if stores are to
1312    be done; otherwise loads.  */
1313 
1314 static void
preserve_registers(int base,int store_p)1315 preserve_registers (int base, int store_p)
1316 {
1317   int regno, offset;
1318   struct mem_op {
1319     int regno;
1320     int nregs;
1321     int offset;
1322   } mem_op[FIRST_PSEUDO_REGISTER];
1323   struct mem_op *mo_ptr = mem_op;
1324 
1325   /* The 88open OCS mandates that preserved registers be stored in
1326      increasing order.  For compatibility with current practice,
1327      the order is r1, r30, then the preserve registers.  */
1328 
1329   offset = base;
1330   if (save_regs[1])
1331     {
1332       /* An extra word is given in this case to make best use of double
1333 	 memory ops.  */
1334       if (nregs > 2 && !save_regs[FRAME_POINTER_REGNUM])
1335 	offset -= 4;
1336       /* Do not reload r1 in the epilogue unless really necessary */
1337       if (store_p || regs_ever_live[1]
1338 	  || (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM]))
1339 	emit_ldst (store_p, 1, SImode, offset);
1340       offset -= 4;
1341       base = offset;
1342     }
1343 
1344   /* Walk the registers to save recording all single memory operations.  */
1345   for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
1346     if (save_regs[regno])
1347       {
1348 	if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
1349 	  {
1350 	    mo_ptr->nregs = 1;
1351 	    mo_ptr->regno = regno;
1352 	    mo_ptr->offset = offset;
1353 	    mo_ptr++;
1354 	    offset -= 4;
1355 	  }
1356         else
1357 	  {
1358 	    regno--;
1359 	    offset -= 2*4;
1360 	  }
1361       }
1362 
1363   /* Walk the registers to save recording all double memory operations.
1364      This avoids a delay in the epilogue (ld.d/ld).  */
1365   offset = base;
1366   for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
1367     if (save_regs[regno])
1368       {
1369 	if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
1370 	  {
1371 	    offset -= 4;
1372 	  }
1373         else
1374 	  {
1375 	    mo_ptr->nregs = 2;
1376 	    mo_ptr->regno = regno-1;
1377 	    mo_ptr->offset = offset-4;
1378 	    mo_ptr++;
1379 	    regno--;
1380 	    offset -= 2*4;
1381 	  }
1382       }
1383 
1384   /* Walk the extended registers to record all memory operations.  */
1385   /*  Be sure the offset is double word aligned.  */
1386   offset = (offset - 1) & ~7;
1387   for (regno = FIRST_PSEUDO_REGISTER - 1; regno > FIRST_EXTENDED_REGISTER;
1388        regno--)
1389     if (save_regs[regno])
1390       {
1391 	mo_ptr->nregs = 2;
1392 	mo_ptr->regno = regno;
1393 	mo_ptr->offset = offset;
1394 	mo_ptr++;
1395 	offset -= 2*4;
1396       }
1397 
1398   mo_ptr->regno = 0;
1399 
1400   /* Output the memory operations.  */
1401   for (mo_ptr = mem_op; mo_ptr->regno; mo_ptr++)
1402     {
1403       if (mo_ptr->nregs)
1404 	emit_ldst (store_p, mo_ptr->regno,
1405 		   (mo_ptr->nregs > 1 ? DImode : SImode),
1406 		   mo_ptr->offset);
1407     }
1408 }
1409 
1410 static void
emit_ldst(int store_p,int regno,enum machine_mode mode,int offset)1411 emit_ldst (int store_p, int regno, enum machine_mode mode, int offset)
1412 {
1413   rtx reg = gen_rtx_REG (mode, regno);
1414   rtx mem;
1415   rtx insn;
1416 
1417   if (SMALL_INTVAL (offset))
1418     {
1419       mem = gen_rtx_MEM (mode, plus_constant (stack_pointer_rtx, offset));
1420     }
1421   else
1422     {
1423       /* offset is too large for immediate index must use register */
1424 
1425       rtx disp = GEN_INT (offset);
1426       rtx temp = gen_rtx_REG (SImode, TEMP_REGNUM);
1427       rtx regi = gen_rtx_PLUS (SImode, stack_pointer_rtx, temp);
1428 
1429       emit_move_insn (temp, disp);
1430       mem = gen_rtx_MEM (mode, regi);
1431     }
1432 
1433   if (store_p)
1434     {
1435       insn = emit_move_insn (mem, reg);
1436       RTX_FRAME_RELATED_P (insn) = 1;
1437     }
1438   else
1439     emit_move_insn (reg, mem);
1440 }
1441 
1442 /* Convert the address expression REG to a CFA offset.  */
1443 
1444 int
m88k_debugger_offset(rtx reg,int offset)1445 m88k_debugger_offset (rtx reg, int offset)
1446 {
1447   if (GET_CODE (reg) == PLUS)
1448     {
1449       offset = INTVAL (XEXP (reg, 1));
1450       reg = XEXP (reg, 0);
1451     }
1452 
1453   /* Put the offset in terms of the CFA (arg pointer).  */
1454   if (reg == frame_pointer_rtx)
1455     offset += m88k_fp_offset - m88k_stack_size;
1456   else if (reg == stack_pointer_rtx)
1457     offset -= m88k_stack_size;
1458   else if (reg != arg_pointer_rtx)
1459     return 0;
1460 
1461   return offset;
1462 }
1463 
1464 /* Output assembler code to FILE to increment profiler label # LABELNO
1465    for profiling a function entry.  NAME is the mcount function name
1466    (varies).  */
1467 
1468 void
output_function_profiler(FILE * file,int labelno,const char * name)1469 output_function_profiler (FILE *file, int labelno, const char *name)
1470 {
1471   char label[256];
1472 
1473   /* Remember to update FUNCTION_PROFILER_LENGTH.  */
1474 
1475   asm_fprintf (file, "\tsubu\t %R%s,%R%s,32\n", reg_names[31], reg_names[31]);
1476   asm_fprintf (file, "\tst.d\t %R%s,%R%s,0\n", reg_names[2], reg_names[31]);
1477   asm_fprintf (file, "\tst.d\t %R%s,%R%s,8\n", reg_names[4], reg_names[31]);
1478   asm_fprintf (file, "\tst.d\t %R%s,%R%s,16\n", reg_names[6], reg_names[31]);
1479   asm_fprintf (file, "\tst.d\t %R%s,%R%s,24\n", reg_names[8], reg_names[31]);
1480 
1481   ASM_GENERATE_INTERNAL_LABEL (label, "LP", labelno);
1482   if (flag_pic == 2)
1483     {
1484       asm_fprintf (file, "\tor.u\t %R%s,%R%s,%Rhi16(%s#got_rel)\n",
1485 		   reg_names[2], reg_names[0], &label[1]);
1486       asm_fprintf (file, "\tor\t %R%s,%R%s,%Rlo16(%s#got_rel)\n",
1487 		   reg_names[2], reg_names[2], &label[1]);
1488       asm_fprintf (file, "\tbsr.n\t %s#plt\n", name);
1489       asm_fprintf (file, "\t ld\t %R%s,%R%s,%R%s\n", reg_names[2],
1490 		   reg_names[PIC_OFFSET_TABLE_REGNUM], reg_names[2]);
1491     }
1492   else if (flag_pic)
1493     {
1494       asm_fprintf (file, "\tbsr.n\t %s#plt\n", name);
1495       asm_fprintf (file, "\t ld\t %R%s,%R%s,%s#got_rel\n", reg_names[2],
1496 		   reg_names[PIC_OFFSET_TABLE_REGNUM], &label[1]);
1497     }
1498   else
1499     {
1500       asm_fprintf (file, "\tor.u\t %R%s,%R%s,%Rhi16(%s)\n",
1501 		   reg_names[2], reg_names[0], &label[1]);
1502       asm_fprintf (file, "\tbsr.n\t %s\n", name);
1503       asm_fprintf (file, "\t or\t %R%s,%R%s,%Rlo16(%s)\n",
1504 		   reg_names[2], reg_names[2], &label[1]);
1505     }
1506 
1507   asm_fprintf (file, "\tld.d\t %R%s,%R%s,0\n", reg_names[2], reg_names[31]);
1508   asm_fprintf (file, "\tld.d\t %R%s,%R%s,8\n", reg_names[4], reg_names[31]);
1509   asm_fprintf (file, "\tld.d\t %R%s,%R%s,16\n", reg_names[6], reg_names[31]);
1510   asm_fprintf (file, "\tld.d\t %R%s,%R%s,24\n", reg_names[8], reg_names[31]);
1511   asm_fprintf (file, "\taddu\t %R%s,%R%s,32\n", reg_names[31], reg_names[31]);
1512 }
1513 
1514 /* Determine whether a function argument is passed in a register, and
1515    which register.
1516 
1517    The arguments are CUM, which summarizes all the previous
1518    arguments; MODE, the machine mode of the argument; TYPE,
1519    the data type of the argument as a tree node or 0 if that is not known
1520    (which happens for C support library functions); and NAMED,
1521    which is 1 for an ordinary argument and 0 for nameless arguments that
1522    correspond to `...' in the called function's prototype.
1523 
1524    The value of the expression should either be a `reg' RTX for the
1525    hard register in which to pass the argument, or zero to pass the
1526    argument on the stack.
1527 
1528    On the m88000 the first eight words of args are normally in registers
1529    and the rest are pushed.  Double precision floating point must be
1530    double word aligned (and if in a register, starting on an even
1531    register). Structures and unions which are not 4 byte, and word
1532    aligned are passed in memory rather than registers, even if they
1533    would fit completely in the registers under OCS rules.
1534 
1535    Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different.
1536    For structures that are passed in memory, but could have been
1537    passed in registers, we first load the structure into the
1538    register, and then when the last argument is passed, we store
1539    the registers into the stack locations.  This fixes some bugs
1540    where GCC did not expect to have register arguments, followed
1541    by stack arguments, followed by register arguments.  */
1542 
1543 struct rtx_def *
m88k_function_arg(CUMULATIVE_ARGS args_so_far,enum machine_mode mode,tree type,int named ATTRIBUTE_UNUSED)1544 m88k_function_arg (CUMULATIVE_ARGS args_so_far, enum machine_mode mode,
1545 		   tree type, int named ATTRIBUTE_UNUSED)
1546 {
1547   int bytes, words;
1548 
1549   /* undo putting struct in register */
1550   if (type != NULL_TREE && AGGREGATE_TYPE_P (type))
1551     mode = BLKmode;
1552 
1553   /* m88k_function_arg argument `type' is NULL for BLKmode. */
1554   gcc_assert (type != NULL_TREE || mode != BLKmode);
1555 
1556   bytes = (mode != BLKmode) ? GET_MODE_SIZE (mode) : int_size_in_bytes (type);
1557 
1558   /* Variable-sized types get passed by reference, which can be passed
1559      in registers.  */
1560   if (bytes < 0)
1561     {
1562       if (args_so_far > 8 - (POINTER_SIZE / BITS_PER_WORD))
1563 	return NULL_RTX;
1564 
1565       return gen_rtx_REG (Pmode, 2 + args_so_far);
1566     }
1567 
1568   words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1569 
1570   if ((args_so_far & 1) != 0
1571       && (mode == DImode || mode == DFmode
1572 	  || (type != NULL_TREE && TYPE_ALIGN (type) > BITS_PER_WORD)))
1573     args_so_far++;
1574 
1575   if (args_so_far + words > 8)
1576     return NULL_RTX;			/* args have exhausted registers */
1577 
1578   else if (mode == BLKmode
1579 	   && (TYPE_ALIGN (type) != BITS_PER_WORD || bytes != UNITS_PER_WORD))
1580     return NULL_RTX;
1581 
1582   return gen_rtx_REG (((mode == BLKmode) ? TYPE_MODE (type) : mode),
1583 		      2 + args_so_far);
1584 }
1585 
1586 /* Update the summarizer variable CUM to advance past an argument in
1587    the argument list.  The values MODE, TYPE and NAMED describe that
1588    argument.  Once this is done, the variable CUM is suitable for
1589    analyzing the *following* argument with `FUNCTION_ARG', etc.  (TYPE
1590    is null for libcalls where that information may not be available.)  */
1591 void
m88k_function_arg_advance(CUMULATIVE_ARGS * args_so_far,enum machine_mode mode,tree type,int named ATTRIBUTE_UNUSED)1592 m88k_function_arg_advance (CUMULATIVE_ARGS *args_so_far, enum machine_mode mode,
1593 			   tree type, int named ATTRIBUTE_UNUSED)
1594 {
1595   int bytes, words;
1596   int asf;
1597 
1598   if (type != NULL_TREE && AGGREGATE_TYPE_P (type))
1599     mode = BLKmode;
1600 
1601   bytes = (mode != BLKmode) ? GET_MODE_SIZE (mode) : int_size_in_bytes (type);
1602   asf = *args_so_far;
1603 
1604   /* Variable-sized types get passed by reference, which can be passed
1605      in registers.  */
1606   if (bytes < 0)
1607     {
1608       if (asf <= 8 - (POINTER_SIZE / BITS_PER_WORD))
1609 	*args_so_far += POINTER_SIZE / BITS_PER_WORD;
1610 
1611       return;
1612     }
1613 
1614   words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1615 
1616   /* Struct and unions which are not exactly the size of a register are to be
1617      passed on stack.  */
1618   if (mode == BLKmode
1619       && (TYPE_ALIGN (type) != BITS_PER_WORD || bytes != UNITS_PER_WORD))
1620     return;
1621 
1622   /* Align arguments requiring more than word alignment to a double-word
1623      boundary (or an even register number if the argument will get passed
1624      in registers).  */
1625   if ((asf & 1) != 0
1626       && (mode == DImode || mode == DFmode
1627 	  || (type != NULL_TREE && TYPE_ALIGN (type) > BITS_PER_WORD)))
1628     asf++;
1629 
1630   if (asf + words > 8)
1631     return;
1632 
1633   (*args_so_far) = asf + words;
1634 }
1635 
1636 /* A C expression that indicates when an argument must be passed by
1637    reference.  If nonzero for an argument, a copy of that argument is
1638    made in memory and a pointer to the argument is passed instead of
1639    the argument itself.  The pointer is passed in whatever way is
1640    appropriate for passing a pointer to that type.
1641 
1642    On m88k, only variable sized types are passed by reference.  */
1643 
1644 static bool
m88k_pass_by_reference(CUMULATIVE_ARGS * cum ATTRIBUTE_UNUSED,enum machine_mode mode ATTRIBUTE_UNUSED,tree type,bool named ATTRIBUTE_UNUSED)1645 m88k_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
1646 			enum machine_mode mode ATTRIBUTE_UNUSED,
1647 			tree type, bool named ATTRIBUTE_UNUSED)
1648 {
1649   return type != NULL_TREE && int_size_in_bytes (type) < 0;
1650 }
1651 
1652 /* Disable the promotion of some structures and unions to registers.
1653    Note that this matches FUNCTION_ARG behaviour.  */
1654 static bool
m88k_return_in_memory(tree type,tree fndecl ATTRIBUTE_UNUSED)1655 m88k_return_in_memory (tree type, tree fndecl ATTRIBUTE_UNUSED)
1656 {
1657   switch (TYPE_MODE (type))
1658     {
1659       case BLKmode:
1660 	return true;
1661       default:
1662 	if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE)
1663 	    && (TYPE_ALIGN (type) != BITS_PER_WORD
1664 		|| GET_MODE_SIZE (TYPE_MODE (type)) != UNITS_PER_WORD))
1665 	  return true;
1666 	return false;
1667     }
1668 }
1669 
1670 /* Perform any needed actions needed for a function that is receiving a
1671    variable number of arguments.
1672 
1673    CUM is a variable of type CUMULATIVE_ARGS which gives info about
1674     the preceding args and about the function being called.
1675 
1676    MODE and TYPE are the mode and type of the current parameter.
1677 
1678    PRETEND_SIZE is a variable that should be set to the amount of stack
1679    that must be pushed by the prolog to pretend that our caller pushed
1680    it.
1681 
1682    Normally, this macro will push all remaining incoming registers on the
1683    stack and set PRETEND_SIZE to the length of the registers pushed.  */
1684 
1685 void
m88k_setup_incoming_varargs(CUMULATIVE_ARGS * cum,enum machine_mode mode,tree type,int * pretend_size,int no_rtl)1686 m88k_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1687 			     tree type, int *pretend_size, int no_rtl)
1688 {
1689   CUMULATIVE_ARGS next_cum;
1690   tree fntype;
1691   int stdarg_p;
1692   int regcnt, delta;
1693 
1694   fntype = TREE_TYPE (current_function_decl);
1695   stdarg_p = (TYPE_ARG_TYPES (fntype) != NULL_TREE
1696 	     && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1697 		 != void_type_node));
1698 
1699   /* For varargs, we do not want to skip the dummy va_dcl argument.
1700      For stdargs, we do want to skip the last named argument.  */
1701   next_cum = *cum;
1702   if (stdarg_p)
1703     m88k_function_arg_advance(&next_cum, mode, type, 1);
1704 
1705   regcnt = next_cum < 8 ? 8 - next_cum : 0;
1706   delta = regcnt & 1;
1707 
1708   if (! no_rtl && regcnt != 0)
1709     {
1710       rtx mem, dst;
1711       int set, regno, offs;
1712 
1713       set = get_varargs_alias_set ();
1714       mem = gen_rtx_MEM (BLKmode,
1715 			 plus_constant (virtual_incoming_args_rtx,
1716 					- (regcnt + delta) * UNITS_PER_WORD));
1717       MEM_NOTRAP_P (mem) = 1;
1718       set_mem_alias_set (mem, set);
1719 
1720       /* Now store the incoming registers.  */
1721       /* The following is equivalent to
1722 	 move_block_from_reg (2 + next_cum,
1723 			      adjust_address (mem, Pmode,
1724 					      delta * UNITS_PER_WORD),
1725 			      regcnt, UNITS_PER_WORD * regcnt);
1726 	 but using double store instruction since the stack is properly
1727 	 aligned.  */
1728       regno = 2 + next_cum;
1729       dst = mem;
1730 
1731       if (delta != 0)
1732 	{
1733 	  dst = adjust_address (dst, Pmode, UNITS_PER_WORD);
1734 	  emit_move_insn (operand_subword (dst, 0, 1, BLKmode),
1735 			  gen_rtx_REG (SImode, regno));
1736 	  regno++;
1737 	}
1738 
1739       offs = delta;
1740       while (regno < 10)
1741 	{
1742 	  emit_move_insn (adjust_address (dst, DImode, offs * UNITS_PER_WORD),
1743 			  gen_rtx_REG (DImode, regno));
1744 	  offs += 2;
1745 	  regno += 2;
1746         }
1747 
1748       *pretend_size = (regcnt + delta) * UNITS_PER_WORD;
1749     }
1750 }
1751 
1752 /* Define the `__builtin_va_list' type for the ABI.  */
1753 
1754 static tree
m88k_build_va_list(void)1755 m88k_build_va_list (void)
1756 {
1757   tree field_reg, field_stk, field_arg, int_ptr_type_node, record;
1758 
1759   int_ptr_type_node = build_pointer_type (integer_type_node);
1760 
1761   record = make_node (RECORD_TYPE);
1762 
1763   field_arg = build_decl (FIELD_DECL, get_identifier ("__va_arg"),
1764 			  integer_type_node);
1765   field_stk = build_decl (FIELD_DECL, get_identifier ("__va_stk"),
1766 			  int_ptr_type_node);
1767   field_reg = build_decl (FIELD_DECL, get_identifier ("__va_reg"),
1768 			  int_ptr_type_node);
1769 
1770   DECL_FIELD_CONTEXT (field_arg) = record;
1771   DECL_FIELD_CONTEXT (field_stk) = record;
1772   DECL_FIELD_CONTEXT (field_reg) = record;
1773 
1774   TYPE_FIELDS (record) = field_arg;
1775   TREE_CHAIN (field_arg) = field_stk;
1776   TREE_CHAIN (field_stk) = field_reg;
1777 
1778   layout_type (record);
1779   return record;
1780 }
1781 
1782 /* Implement `va_start' for varargs and stdarg.  */
1783 
1784 void
m88k_va_start(tree valist,rtx nextarg ATTRIBUTE_UNUSED)1785 m88k_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
1786 {
1787   tree field_reg, field_stk, field_arg;
1788   tree reg, stk, arg, t;
1789   tree fntype;
1790   int stdarg_p;
1791   int offset;
1792 
1793   gcc_assert (CONSTANT_P (current_function_arg_offset_rtx));
1794 
1795   field_arg = TYPE_FIELDS (va_list_type_node);
1796   field_stk = TREE_CHAIN (field_arg);
1797   field_reg = TREE_CHAIN (field_stk);
1798 
1799   arg = build3 (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg,
1800 		NULL_TREE);
1801   stk = build3 (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk,
1802 		NULL_TREE);
1803   reg = build3 (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg,
1804 		NULL_TREE);
1805 
1806   fntype = TREE_TYPE (current_function_decl);
1807   stdarg_p = (TYPE_ARG_TYPES (fntype) != NULL_TREE
1808 	      && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1809 		  != void_type_node));
1810 
1811   /* Fill in the __va_arg member.  */
1812   t = build2 (MODIFY_EXPR, TREE_TYPE (arg), arg,
1813 	     size_int (current_function_args_info));
1814   TREE_SIDE_EFFECTS (t) = 1;
1815   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
1816 
1817   /* Store the arg pointer in the __va_stk member.  */
1818   offset = XINT (current_function_arg_offset_rtx, 0);
1819   if (current_function_args_info >= 8 && ! stdarg_p)
1820     offset -= UNITS_PER_WORD;
1821   t = make_tree (TREE_TYPE (stk), virtual_incoming_args_rtx);
1822   t = build2 (PLUS_EXPR, TREE_TYPE (stk), t, size_int (offset));
1823   t = build2 (MODIFY_EXPR, TREE_TYPE (stk), stk, t);
1824   TREE_SIDE_EFFECTS (t) = 1;
1825   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
1826 
1827   /* Setup __va_reg */
1828   t = make_tree (TREE_TYPE (reg), virtual_incoming_args_rtx);
1829   t = build2 (PLUS_EXPR, TREE_TYPE (reg), t,
1830 	     build_int_cst (NULL_TREE, -8 * UNITS_PER_WORD));
1831   t = build2 (MODIFY_EXPR, TREE_TYPE (reg), reg, t);
1832   TREE_SIDE_EFFECTS (t) = 1;
1833   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
1834 }
1835 
1836 /* Implement `va_arg'.  */
1837 
1838 tree
m88k_gimplify_va_arg(tree valist,tree type,tree * pre_p,tree * post_p)1839 m88k_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
1840 {
1841   tree field_reg, field_stk, field_arg;
1842   int size, wsize, align;
1843   bool reg_p;
1844   tree ptrtype = build_pointer_type (type);
1845   tree lab_done;
1846   tree addr;
1847   tree t;
1848 
1849   if (pass_by_reference (NULL, TYPE_MODE (type), type, false))
1850     {
1851       t = m88k_gimplify_va_arg (valist, ptrtype, pre_p, post_p);
1852       return build_va_arg_indirect_ref (t);
1853     }
1854 
1855   field_arg = TYPE_FIELDS (va_list_type_node);
1856   field_stk = TREE_CHAIN (field_arg);
1857   field_reg = TREE_CHAIN (field_stk);
1858 
1859   size = int_size_in_bytes (type);
1860   wsize = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1861   reg_p = (AGGREGATE_TYPE_P (type)
1862 	   ? size == UNITS_PER_WORD && TYPE_ALIGN (type) == BITS_PER_WORD
1863 	   : size <= 2*UNITS_PER_WORD);
1864 
1865   addr = create_tmp_var (ptr_type_node, "addr");
1866   DECL_POINTER_ALIAS_SET (addr) = get_varargs_alias_set ();
1867   lab_done = NULL;
1868 
1869   /* Decide if we should read from stack or regs if the argument could have
1870      been passed in registers.  */
1871   if (reg_p) {
1872     tree arg, arg_align, reg;
1873     tree lab_stack;
1874     tree u;
1875 
1876     lab_stack = create_artificial_label ();
1877     lab_done = create_artificial_label ();
1878 
1879     /* Align __va_arg to a doubleword boundary if necessary.  */
1880     arg = build3 (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg,
1881 		  NULL_TREE);
1882     align = type == NULL_TREE ? 0 : TYPE_ALIGN (type) / BITS_PER_WORD;
1883     if (align > 1)
1884       {
1885 	t = build2 (PLUS_EXPR, TREE_TYPE (arg), arg, size_int (align - 1));
1886 	arg_align = build2 (BIT_AND_EXPR, TREE_TYPE (t), t,
1887 			    build_int_cst (NULL_TREE, -align));
1888 	gimplify_expr (&arg_align, pre_p, NULL, is_gimple_val, fb_rvalue);
1889       }
1890     else
1891       arg_align = arg;
1892 
1893     /* Make sure the argument fits within the remainder of the saved
1894        register area, and branch to the stack logic if not.  */
1895     u = fold_convert (TREE_TYPE (arg), arg_align);
1896     /* if (arg_align > 8 - wsize) goto lab_stack */
1897     t = fold_convert (TREE_TYPE (arg), size_int (8 - wsize));
1898     t = build2 (GT_EXPR, boolean_type_node, u, t);
1899     u = build1 (GOTO_EXPR, void_type_node, lab_stack);
1900     t = build3 (COND_EXPR, void_type_node, t, u, NULL_TREE);
1901     gimplify_and_add (t, pre_p);
1902 
1903     /* Compute the argument address.  */
1904     reg = build3 (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg,
1905 		  NULL_TREE);
1906     t = build2 (MULT_EXPR, TREE_TYPE (reg), arg_align,
1907 	       size_int (UNITS_PER_WORD));
1908     t = build2 (PLUS_EXPR, TREE_TYPE (reg), reg, t);
1909 
1910     t = build2 (MODIFY_EXPR, void_type_node, addr, t);
1911     gimplify_and_add (t, pre_p);
1912 
1913     /* Increment __va_arg.  */
1914     t = build2 (PLUS_EXPR, TREE_TYPE (arg), arg_align, size_int (wsize));
1915     t = build2 (MODIFY_EXPR, TREE_TYPE (arg), arg, t);
1916     gimplify_and_add (t, pre_p);
1917 
1918     t = build1 (GOTO_EXPR, void_type_node, lab_done);
1919     gimplify_and_add (t, pre_p);
1920 
1921     t = build1 (LABEL_EXPR, void_type_node, lab_stack);
1922     append_to_statement_list (t, pre_p);
1923   }
1924 
1925   {
1926     tree stk;
1927     tree u;
1928 
1929     stk = build3 (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk,
1930 		  NULL_TREE);
1931 
1932     /* Align __va_stk to the type boundary if necessary.  */
1933     align = type == NULL_TREE ? 0 : TYPE_ALIGN (type) / BITS_PER_UNIT;
1934     if (align > UNITS_PER_WORD)
1935       {
1936         t = build2 (PLUS_EXPR, TREE_TYPE (stk), stk, size_int (align - 1));
1937         t = build2 (BIT_AND_EXPR, TREE_TYPE (t), t,
1938 		    build_int_cst (NULL_TREE, -align));
1939 	gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue);
1940       }
1941     else
1942       t = stk;
1943 
1944     /* Compute the argument address.  */
1945     u = build2 (MODIFY_EXPR, void_type_node, addr, t);
1946     gimplify_and_add (u, pre_p);
1947 
1948     /* Increment __va_stk.  */
1949     t = build2 (PLUS_EXPR, TREE_TYPE (t), t, size_int (wsize * UNITS_PER_WORD));
1950     t = build2 (MODIFY_EXPR, TREE_TYPE (stk), stk, t);
1951     gimplify_and_add (t, pre_p);
1952   }
1953 
1954   if (lab_done)
1955     {
1956       t = build1 (LABEL_EXPR, void_type_node, lab_done);
1957       append_to_statement_list (t, pre_p);
1958     }
1959 
1960   addr = fold_convert (ptrtype, addr);
1961   return build_va_arg_indirect_ref (addr);
1962 }
1963 
1964 /* If cmpsi has not been generated, emit code to do the test.  Return the
1965    expression describing the test of operator OP.  */
1966 
1967 rtx
emit_test(enum rtx_code op,enum machine_mode mode)1968 emit_test (enum rtx_code op, enum machine_mode mode)
1969 {
1970   if (m88k_compare_reg == NULL_RTX)
1971     emit_insn (gen_test (m88k_compare_op0, m88k_compare_op1));
1972   return (gen_rtx_fmt_ee (op, mode, m88k_compare_reg, const0_rtx));
1973 }
1974 
1975 /* Determine how to best perform cmpsi/bxx, where cmpsi has a constant
1976    operand.  All tests with zero (albeit swapped) and all equality tests
1977    with a constant are done with bcnd.  The remaining cases are swapped
1978    as needed.  */
1979 
1980 void
emit_bcnd(enum rtx_code op,rtx label)1981 emit_bcnd (enum rtx_code op, rtx label)
1982 {
1983   if (m88k_compare_op1 == const0_rtx)
1984     emit_jump_insn (gen_bcnd
1985 		    (gen_rtx_fmt_ee (op, VOIDmode, m88k_compare_op0, const0_rtx),
1986 		     label));
1987   else if (m88k_compare_op0 == const0_rtx)
1988     emit_jump_insn (gen_bcnd
1989 		    (gen_rtx_fmt_ee (swap_condition (op),
1990 				     VOIDmode, m88k_compare_op1, const0_rtx),
1991 		     label));
1992   else if (op != EQ && op != NE)
1993     emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
1994   else
1995     {
1996       rtx zero = gen_reg_rtx (SImode);
1997       rtx reg, constant;
1998       int value;
1999 
2000       if (GET_CODE (m88k_compare_op1) == CONST_INT)
2001 	{
2002 	  reg = force_reg (SImode, m88k_compare_op0);
2003 	  constant = m88k_compare_op1;
2004 	}
2005       else
2006 	{
2007 	  reg = force_reg (SImode, m88k_compare_op1);
2008 	  constant = m88k_compare_op0;
2009 	}
2010       value = INTVAL (constant);
2011 
2012       /* Perform an arithmetic computation to make the compared-to value
2013 	 zero, but avoid loosing if the bcnd is later changed into sxx.  */
2014       if (SMALL_INTVAL (value))
2015 	emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2016       else
2017 	{
2018 	  if (SMALL_INTVAL (-value))
2019 	    emit_insn (gen_addsi3 (zero, reg,
2020 				   GEN_INT (-value)));
2021 	  else
2022 	    emit_insn (gen_xorsi3 (zero, reg, constant));
2023 
2024 	  emit_jump_insn (gen_bcnd (gen_rtx_fmt_ee (op, VOIDmode,
2025 						    zero, const0_rtx),
2026 				    label));
2027 	}
2028     }
2029 }
2030 
2031 /* Print an operand.  Recognize special options, documented below.  */
2032 
2033 void
print_operand(FILE * file,rtx x,int code)2034 print_operand (FILE *file, rtx x, int code)
2035 {
2036   enum rtx_code xc = (x ? GET_CODE (x) : UNKNOWN);
2037   int value = (xc == CONST_INT ? INTVAL (x) : 0);
2038   static int sequencep;
2039   static int reversep;
2040 
2041   if (sequencep)
2042     {
2043       if (code < 'B' || code > 'E')
2044 	output_operand_lossage ("%%R not followed by %%B/C/D/E");
2045       if (reversep)
2046 	xc = reverse_condition (xc);
2047       sequencep = 0;
2048     }
2049 
2050   switch (code)
2051     {
2052     case '#': /* register prefix character (may be empty) */
2053       fputs (m88k_register_prefix, file);
2054       return;
2055 
2056     case 'V': /* Output a serializing instruction as needed if the operand
2057 		 (assumed to be a MEM) is a volatile load.  */
2058     case 'v': /* ditto for a volatile store.  */
2059       if (MEM_VOLATILE_P (x) && TARGET_SERIALIZE_VOLATILE)
2060 	{
2061 	  /* The m88110 implements two FIFO queues, one for loads and
2062 	     one for stores.  These queues mean that loads complete in
2063 	     their issue order as do stores.  An interaction between the
2064 	     history buffer and the store reservation station ensures
2065 	     that a store will not bypass load.  Finally, a load will not
2066 	     bypass store, but only when they reference the same address.
2067 
2068 	     To avoid this reordering (a load bypassing a store) for
2069 	     volatile references, a serializing instruction is output.
2070 	     We choose the fldcr instruction as it does not serialize on
2071 	     the m88100 so that -m88000 code will not be degraded.
2072 
2073 	     The mechanism below is completed by having CC_STATUS_INIT set
2074 	     the code to the unknown value.  */
2075 
2076 	  /*
2077 	     hassey 6/30/93
2078 	     A problem with 88110 4.1 & 4.2 makes the use of fldcr for
2079 	     this purpose undesirable.  Instead we will use tb1, this will
2080 	     cause serialization on the 88100 but such is life.
2081 	  */
2082 
2083 	  static rtx last_addr = NULL_RTX;
2084 	  if (code == 'V' /* Only need to serialize before a load.  */
2085 	      && m88k_volatile_code != 'V' /* Loads complete in FIFO order.  */
2086 	      && !(m88k_volatile_code == 'v'
2087 		   && GET_CODE (XEXP (x, 0)) == LO_SUM
2088 		   && rtx_equal_p (XEXP (XEXP (x, 0), 1), last_addr)))
2089 	    asm_fprintf (file,
2090 #if 0
2091 			 "fldcr\t %R%s,%Rfcr63\n\t",
2092 #else /* 0 */
2093 			 "tb1\t 1,%R%s,0xff\n\t",
2094 #endif /* 0 */
2095 			 reg_names[0]);
2096 	  m88k_volatile_code = code;
2097 	  last_addr = (GET_CODE (XEXP (x, 0)) == LO_SUM
2098 		       ? XEXP (XEXP (x, 0), 1) : 0);
2099 	}
2100       return;
2101 
2102     case 'X': /* print the upper 16 bits... */
2103       value >>= 16;
2104     case 'x': /* print the lower 16 bits of the integer constant in hex */
2105       if (xc != CONST_INT)
2106 	output_operand_lossage ("invalid %%x/X value");
2107       fprintf (file, "0x%x", value & 0xffff); return;
2108 
2109     case 'H': /* print the low 16 bits of the negated integer constant */
2110       if (xc != CONST_INT)
2111 	output_operand_lossage ("invalid %%H value");
2112       value = -value;
2113     case 'h': /* print the register or low 16 bits of the integer constant */
2114       if (xc == REG)
2115 	goto reg;
2116       if (xc != CONST_INT)
2117 	output_operand_lossage ("invalid %%h value");
2118       fprintf (file, "%d", value & 0xffff);
2119       return;
2120 
2121     case 'Q': /* print the low 8 bits of the negated integer constant */
2122       if (xc != CONST_INT)
2123 	output_operand_lossage ("invalid %%Q value");
2124       value = -value;
2125     case 'q': /* print the register or low 8 bits of the integer constant */
2126       if (xc == REG)
2127 	goto reg;
2128       if (xc != CONST_INT)
2129 	output_operand_lossage ("invalid %%q value");
2130       fprintf (file, "%d", value & 0xff);
2131       return;
2132 
2133     case 'p': /* print the logarithm of the integer constant */
2134       if (xc != CONST_INT
2135 	  || (value = exact_log2 (value)) < 0)
2136 	output_operand_lossage ("invalid %%p value");
2137       fprintf (file, "%d", value);
2138       return;
2139 
2140     case 'S': /* complement the value and then... */
2141       value = ~value;
2142     case 's': /* print the width and offset values forming the integer
2143 		 constant with a SET instruction.  See integer_ok_for_set. */
2144       {
2145 	unsigned mask, uval = value;
2146 	int top, bottom;
2147 
2148 	if (xc != CONST_INT)
2149 	  output_operand_lossage ("invalid %%s/S value");
2150 	/* All the "one" bits must be contiguous.  If so, MASK will be
2151 	   a power of two or zero.  */
2152 	mask = (uval | (uval - 1)) + 1;
2153 	if (!(uval && POWER_OF_2_or_0 (mask)))
2154 	  output_operand_lossage ("invalid %%s/S value");
2155 	top = mask ? exact_log2 (mask) : 32;
2156 	bottom = exact_log2 (uval & ~(uval - 1));
2157 	fprintf (file,"%d<%d>", top - bottom, bottom);
2158 	return;
2159       }
2160 
2161     case 'P': /* print nothing if pc_rtx; output label_ref */
2162       if (xc == LABEL_REF)
2163 	output_addr_const (file, x);
2164       else if (xc != PC)
2165 	output_operand_lossage ("invalid %%P operand");
2166       return;
2167 
2168     case 'L': /* print 0 or 1 if operand is label_ref and then...  */
2169       fputc (xc == LABEL_REF ? '1' : '0', file);
2170     case '.': /* print .n if delay slot is used */
2171       fputs ((final_sequence
2172 	      && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
2173 	     ? ".n\t" : "\t", file);
2174       return;
2175 
2176     case '!': /* Reverse the following condition. */
2177       sequencep++;
2178       reversep = 1;
2179       return;
2180     case 'R': /* reverse the condition of the next print_operand
2181 		 if operand is a label_ref.  */
2182       sequencep++;
2183       reversep = (xc == LABEL_REF);
2184       return;
2185 
2186     case 'B': /* bcnd branch values */
2187       if (0) /* SVR4 */
2188 	fputs (m88k_register_prefix, file);
2189       switch (xc)
2190 	{
2191 	case EQ: fputs ("eq0", file); return;
2192 	case NE: fputs ("ne0", file); return;
2193 	case GT: fputs ("gt0", file); return;
2194 	case LE: fputs ("le0", file); return;
2195 	case LT: fputs ("lt0", file); return;
2196 	case GE: fputs ("ge0", file); return;
2197 	default: output_operand_lossage ("invalid %%B value");
2198 	}
2199 
2200     case 'C': /* bb0/bb1 branch values for comparisons */
2201       if (0) /* SVR4 */
2202 	fputs (m88k_register_prefix, file);
2203       switch (xc)
2204 	{
2205 	case EQ:  fputs ("eq", file); return;
2206 	case NE:  fputs ("ne", file); return;
2207 	case GT:  fputs ("gt", file); return;
2208 	case LE:  fputs ("le", file); return;
2209 	case LT:  fputs ("lt", file); return;
2210 	case GE:  fputs ("ge", file); return;
2211 	case GTU: fputs ("hi", file); return;
2212 	case LEU: fputs ("ls", file); return;
2213 	case LTU: fputs ("lo", file); return;
2214 	case GEU: fputs ("hs", file); return;
2215 	default:  output_operand_lossage ("invalid %%C value");
2216 	}
2217 
2218     case 'D': /* bcnd branch values for float comparisons */
2219       switch (xc)
2220 	{
2221 	case EQ: fputs ("0xa", file); return;
2222 	case NE: fputs ("0x5", file); return;
2223 	case GT:
2224 	  if (0) /* SVR4 */
2225 	    fputs (m88k_register_prefix, file);
2226 	  fputs ("gt0", file);
2227 	  return;
2228 	case LE:
2229 	  if (0) /* SVR4 */
2230 	    fputs (m88k_register_prefix, file);
2231 	  fputs ("le0", file);
2232 	  return;
2233 	case LT: fputs ("0x4", file); return;
2234 	case GE: fputs ("0xb", file); return;
2235 	default: output_operand_lossage ("invalid %%D value");
2236 	}
2237 
2238     case 'E': /* bcnd branch values for special integers */
2239       switch (xc)
2240 	{
2241 	case EQ: fputs ("0x8", file); return;
2242 	case NE: fputs ("0x7", file); return;
2243 	default: output_operand_lossage ("invalid %%E value");
2244 	}
2245 
2246     case 'd': /* second register of a two register pair */
2247       if (xc != REG)
2248 	output_operand_lossage ("`%%d' operand isn't a register");
2249       asm_fprintf (file, "%R%s", reg_names[REGNO (x) + 1]);
2250       return;
2251 
2252     case 'r': /* an immediate 0 should be represented as `r0' */
2253       if (x == const0_rtx)
2254 	{
2255 	  asm_fprintf (file, "%R%s", reg_names[0]);
2256 	  return;
2257 	}
2258       else if (xc != REG)
2259 	output_operand_lossage ("invalid %%r value");
2260     case 0:
2261     name:
2262       if (xc == REG)
2263 	{
2264 	reg:
2265 	  if (REGNO (x) == ARG_POINTER_REGNUM)
2266 	    output_operand_lossage ("operand is r0");
2267 	  else
2268 	    asm_fprintf (file, "%R%s", reg_names[REGNO (x)]);
2269 	}
2270       else if (xc == PLUS)
2271 	output_address (x);
2272       else if (xc == MEM)
2273 	output_address (XEXP (x, 0));
2274       else if (flag_pic && xc == UNSPEC)
2275 	{
2276 	  output_addr_const (file, XVECEXP (x, 0, 0));
2277 	  fputs ("#got_rel", file);
2278 	}
2279       else if (xc == CONST_DOUBLE)
2280 	output_operand_lossage ("operand is const_double");
2281       else
2282 	output_addr_const (file, x);
2283       return;
2284 
2285     case 'g': /* append #got_rel as needed */
2286       if (flag_pic && (xc == SYMBOL_REF || xc == LABEL_REF))
2287 	{
2288 	  output_addr_const (file, x);
2289 	  fputs ("#got_rel", file);
2290 	  return;
2291 	}
2292       goto name;
2293 
2294     case 'a': /* (standard), assume operand is an address */
2295     case 'c': /* (standard), assume operand is an immediate value */
2296     case 'l': /* (standard), assume operand is a label_ref */
2297     case 'n': /* (standard), like %c, except negate first */
2298     default:
2299       output_operand_lossage ("invalid code");
2300     }
2301 }
2302 
2303 void
print_operand_address(FILE * file,rtx addr)2304 print_operand_address (FILE *file, rtx addr)
2305 {
2306   rtx reg0, reg1;
2307 
2308   switch (GET_CODE (addr))
2309     {
2310     case REG:
2311       gcc_assert (REGNO (addr) != ARG_POINTER_REGNUM);
2312       asm_fprintf (file, "%R%s,%R%s", reg_names[0], reg_names [REGNO (addr)]);
2313       break;
2314 
2315     case LO_SUM:
2316       asm_fprintf (file, "%R%s,%Rlo16(",
2317 		   reg_names[REGNO (XEXP (addr, 0))]);
2318       output_addr_const (file, XEXP (addr, 1));
2319       fputc (')', file);
2320       break;
2321 
2322     case PLUS:
2323       reg0 = XEXP (addr, 0);
2324       reg1 = XEXP (addr, 1);
2325       if (GET_CODE (reg0) == MULT || GET_CODE (reg0) == CONST_INT)
2326 	{
2327 	  rtx tmp = reg0;
2328 	  reg0 = reg1;
2329 	  reg1 = tmp;
2330 	}
2331 
2332       gcc_assert ((!REG_P (reg0) || REGNO (reg0) != ARG_POINTER_REGNUM)
2333 		  && (!REG_P (reg1) || REGNO (reg1) != ARG_POINTER_REGNUM));
2334 
2335       if (REG_P (reg0))
2336 	{
2337 	  if (REG_P (reg1))
2338 	    asm_fprintf (file, "%R%s,%R%s",
2339 			 reg_names [REGNO (reg0)], reg_names [REGNO (reg1)]);
2340 
2341 	  else if (GET_CODE (reg1) == CONST_INT)
2342 	    asm_fprintf (file, "%R%s,%d",
2343 			 reg_names [REGNO (reg0)], INTVAL (reg1));
2344 
2345 	  else if (GET_CODE (reg1) == MULT)
2346 	    {
2347 	      rtx mreg = XEXP (reg1, 0);
2348 	      gcc_assert (REGNO (mreg) != ARG_POINTER_REGNUM);
2349 
2350 	      asm_fprintf (file, "%R%s[%R%s]", reg_names[REGNO (reg0)],
2351 			   reg_names[REGNO (mreg)]);
2352 	    }
2353 
2354 	  else if (GET_CODE (reg1) == ZERO_EXTRACT)
2355 	    {
2356 	      asm_fprintf (file, "%R%s,%Rlo16(",
2357 			   reg_names[REGNO (reg0)]);
2358 	      output_addr_const (file, XEXP (reg1, 0));
2359 	      fputc (')', file);
2360 	    }
2361 
2362 	  else if (flag_pic)
2363 	    {
2364 	      asm_fprintf (file, "%R%s,", reg_names[REGNO (reg0)]);
2365 	      output_addr_const (file, reg1);
2366 	      fputs ("#got_rel", file);
2367 	    }
2368 	  else
2369 	    gcc_unreachable ();
2370 	}
2371 
2372       else
2373 	gcc_unreachable ();
2374       break;
2375 
2376     case MULT:
2377       gcc_assert (REGNO (XEXP (addr, 0)) != ARG_POINTER_REGNUM);
2378       asm_fprintf (file, "%R%s[%R%s]",
2379 		   reg_names[0], reg_names[REGNO (XEXP (addr, 0))]);
2380       break;
2381 
2382     case CONST_INT:
2383       asm_fprintf (file, "%R%s,%d", reg_names[0], INTVAL (addr));
2384       break;
2385 
2386     default:
2387       asm_fprintf (file, "%R%s,", reg_names[0]);
2388       output_addr_const (file, addr);
2389     }
2390 }
2391 
2392 /* Return true if X is an address which needs a temporary register when
2393    reloaded while generating PIC code.  */
2394 
2395 bool
pic_address_needs_scratch(rtx x)2396 pic_address_needs_scratch (rtx x)
2397 {
2398   /* An address which is a symbolic plus a non SMALL_INT needs a temp reg.  */
2399   if (GET_CODE (x) == CONST)
2400     {
2401       x = XEXP (x, 0);
2402       if (GET_CODE (x) == PLUS)
2403 	{
2404 	  if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
2405 	      && GET_CODE (XEXP (x, 1)) == CONST_INT
2406 	      && ! ADD_INT (XEXP (x, 1)))
2407 	    return true;
2408 	}
2409     }
2410 
2411   return false;
2412 }
2413 
2414 /* Adjust the cost of INSN based on the relationship between INSN that
2415    is dependent on DEP_INSN through the dependence LINK.  The default
2416    is to make no adjustment to COST.
2417 
2418    On the m88k, ignore the cost of anti- and output-dependencies.  On
2419    the m88100, a store can issue two cycles before the value (not the
2420    address) has finished computing.  */
2421 
2422 static int
m88k_adjust_cost(rtx insn,rtx link,rtx dep,int cost)2423 m88k_adjust_cost (rtx insn, rtx link, rtx dep, int cost)
2424 {
2425   if (REG_NOTE_KIND (link) != REG_DEP_TRUE)
2426     return 0;  /* Anti or output dependence.  */
2427 
2428   if (TARGET_88110
2429       && recog_memoized (insn) >= 0
2430       && get_attr_type (insn) == TYPE_STORE
2431       && SET_SRC (PATTERN (insn)) == SET_DEST (PATTERN (dep)))
2432     return cost - 4;  /* 88110 store reservation station.  */
2433 
2434   return cost;
2435 }
2436 
2437 /* Return cost of address expression X.
2438    Expect that X is properly formed address reference.  */
2439 
2440 static int
m88k_address_cost(rtx x)2441 m88k_address_cost (rtx x)
2442 {
2443    /* REG+REG is made slightly more expensive because it might keep
2444       a register live for longer than we might like.  */
2445   switch (GET_CODE (x))
2446     {
2447     case REG:
2448     case LO_SUM:
2449     case MULT:
2450       return 1;
2451     case HIGH:
2452       return 2;
2453     case PLUS:
2454       return (REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1))) ? 2 : 1;
2455     default:
2456       return 4;
2457     }
2458 }
2459 
2460 /* Compute the cost of computing a constant rtl expression x
2461    whose rtx-code is code.  */
2462 static bool
m88k_rtx_costs(rtx x,int code,int outer_code,int * total)2463 m88k_rtx_costs (rtx x, int code, int outer_code, int *total)
2464 {
2465   switch (code)
2466     {
2467     case CONST_INT:
2468       /* We assume that any 16 bit integer can easily be recreated, so we
2469 	 indicate 0 cost, in an attempt to get GCC not to optimize things
2470 	 like comparison against a constant.  */
2471       if (SMALL_INT (x))
2472         *total = 0;
2473       else if (SMALL_INTVAL (- INTVAL (x)))
2474         *total = 2;
2475       else if (classify_integer (SImode, INTVAL (x)) != m88k_oru_or)
2476         *total = 4;
2477       *total = 7;
2478       return true;
2479 
2480     case HIGH:
2481       *total = 2;
2482       return true;
2483 
2484     case CONST:
2485     case LABEL_REF:
2486     case SYMBOL_REF:
2487       if (flag_pic)
2488         *total = (flag_pic == 2) ? 11 : 8;
2489       else
2490         *total = 5;
2491       return true;
2492 
2493       /* The cost of CONST_DOUBLE is zero (if it can be placed in an insn,
2494 	 it is as good as a register; since it can't be placed in any insn,
2495 	 it won't do anything in cse, but it will cause expand_binop to
2496 	 pass the constant to the define_expands).  */
2497     case CONST_DOUBLE:
2498       *total = 0;
2499       return true;
2500 
2501     case MEM:
2502       *total = COSTS_N_INSNS (2);
2503       return true;
2504 
2505     case MULT:
2506       *total = COSTS_N_INSNS (3);
2507       return true;
2508 
2509     case DIV:
2510     case UDIV:
2511     case MOD:
2512     case UMOD:
2513       *total = COSTS_N_INSNS (38);
2514       return true;
2515 
2516     default:
2517       return false;
2518     }
2519 }
2520 
2521 static bool
m88k_handle_option(size_t code,const char * arg,int value)2522 m88k_handle_option (size_t code, const char *arg, int value)
2523 {
2524   switch (code)
2525     {
2526     case OPT_m88000:
2527       /* make the cpu type nonzero; will be reset in m88k_override_options() */
2528       target_flags |= MASK_88100 | MASK_88110;
2529       return true;
2530 
2531     case OPT_m88100:
2532       target_flags &= ~MASK_88110;
2533       target_flags |= MASK_88100;
2534       return true;
2535 
2536     case OPT_m88110:
2537       target_flags &= ~MASK_88100;
2538       target_flags |= MASK_88110;
2539       return true;
2540 
2541     default:
2542       return true;
2543     }
2544 }
2545 
2546 void
m88k_override_options(void)2547 m88k_override_options (void)
2548 {
2549   if (!TARGET_88100 && !TARGET_88110)
2550     target_flags |= CPU_DEFAULT;
2551 
2552   if (TARGET_88100 && TARGET_88110)
2553     target_flags &= ~(MASK_88100 | MASK_88110);
2554 
2555   if (TARGET_88110)
2556     {
2557       target_flags |= MASK_USE_DIV;
2558       target_flags &= ~MASK_CHECK_ZERO_DIV;
2559     }
2560 
2561   m88k_cpu = (TARGET_88110 ? PROCESSOR_M88100
2562 	      : (TARGET_88100 ? PROCESSOR_M88100 : PROCESSOR_M88000));
2563 
2564   if (TARGET_TRAP_LARGE_SHIFT && TARGET_HANDLE_LARGE_SHIFT)
2565     error ("-mtrap-large-shift and -mhandle-large-shift are incompatible");
2566 
2567   if (TARGET_OMIT_LEAF_FRAME_POINTER)	/* keep nonleaf frame pointers */
2568     flag_omit_frame_pointer = 1;
2569 
2570   /* On the m88100, it is desirable to align functions to a cache line.
2571      The m88110 cache is small, so align to an 8 byte boundary.  */
2572   if (align_functions == 0)
2573     align_functions = TARGET_88100 ? 16 : 8;
2574 
2575 #if 1 /* XXX breaks -freorder-blocks and even without it, tree-cfg.c */
2576   flag_delayed_branch = 0;
2577 #endif
2578 
2579   /* XXX -freorder-blocks (enabled at -O2) does not work with -fdelayed-branch
2580      yet.  */
2581   if (flag_delayed_branch)
2582     {
2583       flag_reorder_blocks = flag_reorder_blocks_and_partition = 0;
2584     }
2585 }
2586