xref: /openbsd/gnu/usr.bin/gcc/gcc/config/m88k/m88k.c (revision 264ca280)
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 GNU CC.
8 
9 GNU CC 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 GNU CC 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 GNU CC; see the file COPYING.  If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA.  */
23 
24 #include "config.h"
25 #include "system.h"
26 #include "rtl.h"
27 #include "regs.h"
28 #include "hard-reg-set.h"
29 #include "real.h"
30 #include "insn-config.h"
31 #include "conditions.h"
32 #include "output.h"
33 #include "insn-attr.h"
34 #include "tree.h"
35 #include "function.h"
36 #include "expr.h"
37 #include "libfuncs.h"
38 #include "c-tree.h"
39 #include "flags.h"
40 #include "recog.h"
41 #include "toplev.h"
42 #include "tm_p.h"
43 #include "target.h"
44 #include "target-def.h"
45 
46 #ifdef REGISTER_PREFIX
47 const char *m88k_register_prefix = REGISTER_PREFIX;
48 #else
49 const char *m88k_register_prefix = "";
50 #endif
51 char m88k_volatile_code;
52 
53 int m88k_fp_offset	= 0;	/* offset of frame pointer if used */
54 int m88k_stack_size	= 0;	/* size of allocated stack (including frame) */
55 int m88k_case_index;
56 
57 rtx m88k_compare_reg;		/* cmp output pseudo register */
58 rtx m88k_compare_op0;		/* cmpsi operand 0 */
59 rtx m88k_compare_op1;		/* cmpsi operand 1 */
60 
61 enum processor_type m88k_cpu;	/* target cpu */
62 
63 static void m88k_frame_related PARAMS ((rtx, rtx, HOST_WIDE_INT));
64 static void m88k_maybe_dead PARAMS ((rtx));
65 static void m88k_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
66 static int m88k_adjust_cost PARAMS ((rtx, rtx, rtx, int));
67 
68 /* Initialize the GCC target structure.  */
69 #if !defined(OBJECT_FORMAT_ELF)
70 #undef TARGET_ASM_BYTE_OP
71 #define TARGET_ASM_BYTE_OP "\tbyte\t"
72 #undef TARGET_ASM_ALIGNED_HI_OP
73 #define TARGET_ASM_ALIGNED_HI_OP "\thalf\t"
74 #undef TARGET_ASM_ALIGNED_SI_OP
75 #define TARGET_ASM_ALIGNED_SI_OP "\tword\t"
76 #undef TARGET_ASM_UNALIGNED_HI_OP
77 #define TARGET_ASM_UNALIGNED_HI_OP "\tuahalf\t"
78 #undef TARGET_ASM_UNALIGNED_SI_OP
79 #define TARGET_ASM_UNALIGNED_SI_OP "\tuaword\t"
80 #endif
81 
82 #undef TARGET_ASM_FUNCTION_EPILOGUE
83 #define TARGET_ASM_FUNCTION_EPILOGUE m88k_output_function_epilogue
84 
85 #undef TARGET_SCHED_ADJUST_COST
86 #define TARGET_SCHED_ADJUST_COST m88k_adjust_cost
87 
88 struct gcc_target targetm = TARGET_INITIALIZER;
89 
90 /* Determine what instructions are needed to manufacture the integer VALUE
91    in the given MODE.  */
92 
93 enum m88k_instruction
94 classify_integer (mode, value)
95      enum machine_mode mode;
96      register int value;
97 {
98   if (value == 0)
99     return m88k_zero;
100   else if (SMALL_INTVAL (value))
101     return m88k_or;
102   else if (SMALL_INTVAL (-value))
103     return m88k_subu;
104   else if (mode == HImode)
105     return m88k_or_lo16;
106   else if (mode == QImode)
107     return m88k_or_lo8;
108   else if (integer_ok_for_set (value))
109     return m88k_set;
110   else if ((value & 0xffff) == 0)
111     return m88k_oru_hi16;
112   else
113     return m88k_oru_or;
114 }
115 
116 /* Return the bit number in a compare word corresponding to CONDITION.  */
117 
118 int
119 condition_value (condition)
120      rtx condition;
121 {
122   switch (GET_CODE (condition))
123     {
124     case UNORDERED:
125       return 0;
126     case ORDERED:
127       return 1;
128     case EQ:
129       return 2;
130     case NE:
131       return 3;
132     case GT:
133       return 4;
134     case LE:
135       return 5;
136     case LT:
137       return 6;
138     case GE:
139       return 7;
140     case GTU:
141       return 8;
142     case LEU:
143       return 9;
144     case LTU:
145       return 10;
146     case GEU:
147       return 11;
148     default:
149       abort ();
150     }
151 }
152 
153 int
154 integer_ok_for_set (value)
155      register unsigned value;
156 {
157   /* All the "one" bits must be contiguous.  If so, MASK + 1 will be
158      a power of two or zero.  */
159   register unsigned mask = (value | (value - 1));
160   return (value && POWER_OF_2_or_0 (mask + 1));
161 }
162 
163 const char *
164 output_load_const_int (mode, operands)
165      enum machine_mode mode;
166      rtx *operands;
167 {
168   static const char *const patterns[] =
169     { "or %0,%#r0,0",
170       "or %0,%#r0,%1",
171       "subu %0,%#r0,%n1",
172       "or %0,%#r0,%h1",
173       "or %0,%#r0,%q1",
174       "set %0,%#r0,%s1",
175       "or.u %0,%#r0,%X1",
176       "or.u %0,%#r0,%X1\n\tor %0,%0,%x1",
177     };
178 
179   if (! REG_P (operands[0])
180       || GET_CODE (operands[1]) != CONST_INT)
181     abort ();
182   return patterns[classify_integer (mode, INTVAL (operands[1]))];
183 }
184 
185 /* These next two routines assume that floating point numbers are represented
186    in a manner which is consistent between host and target machines.  */
187 
188 const char *
189 output_load_const_float (operands)
190      rtx *operands;
191 {
192   /* These can return 0 under some circumstances when cross-compiling.  */
193   operands[0] = operand_subword (operands[0], 0, 0, SFmode);
194   operands[1] = operand_subword (operands[1], 0, 0, SFmode);
195 
196   return output_load_const_int (SImode, operands);
197 }
198 
199 const char *
200 output_load_const_double (operands)
201      rtx *operands;
202 {
203   rtx latehalf[2];
204 
205   /* These can return zero on some cross-compilers, but there's nothing
206      we can do about it.  */
207   latehalf[0] = operand_subword (operands[0], 1, 0, DFmode);
208   latehalf[1] = operand_subword (operands[1], 1, 0, DFmode);
209 
210   operands[0] = operand_subword (operands[0], 0, 0, DFmode);
211   operands[1] = operand_subword (operands[1], 0, 0, DFmode);
212 
213   output_asm_insn (output_load_const_int (SImode, operands), operands);
214 
215   operands[0] = latehalf[0];
216   operands[1] = latehalf[1];
217 
218   return output_load_const_int (SImode, operands);
219 }
220 
221 const char *
222 output_load_const_dimode (operands)
223      rtx *operands;
224 {
225   rtx latehalf[2];
226 
227   latehalf[0] = operand_subword (operands[0], 1, 0, DImode);
228   latehalf[1] = operand_subword (operands[1], 1, 0, DImode);
229 
230   operands[0] = operand_subword (operands[0], 0, 0, DImode);
231   operands[1] = operand_subword (operands[1], 0, 0, DImode);
232 
233   output_asm_insn (output_load_const_int (SImode, operands), operands);
234 
235   operands[0] = latehalf[0];
236   operands[1] = latehalf[1];
237 
238   return output_load_const_int (SImode, operands);
239 }
240 
241 /* Emit insns to move operands[1] into operands[0].
242 
243    Return 1 if we have written out everything that needs to be done to
244    do the move.  Otherwise, return 0 and the caller will emit the move
245    normally.
246 
247    SCRATCH if nonzero can be used as a scratch register for the move
248    operation.  It is provided by a SECONDARY_RELOAD_* macro if needed.  */
249 
250 int
251 emit_move_sequence (operands, mode, scratch)
252      rtx *operands;
253      enum machine_mode mode;
254      rtx scratch;
255 {
256   register rtx operand0 = operands[0];
257   register rtx operand1 = operands[1];
258 
259   if (CONSTANT_P (operand1) && flag_pic
260       && pic_address_needs_scratch (operand1))
261     operands[1] = operand1 = legitimize_address (1, operand1, 0, 0);
262 
263   /* Handle most common case first: storing into a register.  */
264   if (register_operand (operand0, mode))
265     {
266       if (register_operand (operand1, mode)
267 	  || (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1))
268 	  || GET_CODE (operand1) == HIGH
269 	  /* Only `general_operands' can come here, so MEM is ok.  */
270 	  || GET_CODE (operand1) == MEM)
271 	{
272 	  /* Run this case quickly.  */
273 	  emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
274 	  return 1;
275 	}
276     }
277   else if (GET_CODE (operand0) == MEM)
278     {
279       if (register_operand (operand1, mode)
280 	  || (operand1 == const0_rtx && GET_MODE_SIZE (mode) <= UNITS_PER_WORD))
281 	{
282 	  /* Run this case quickly.  */
283 	  emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
284 	  return 1;
285 	}
286       if (! reload_in_progress && ! reload_completed)
287 	{
288 	  operands[0] = validize_mem (operand0);
289 	  operands[1] = operand1 = force_reg (mode, operand1);
290 	}
291     }
292 
293   /* Simplify the source if we need to.  */
294   if (GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
295     {
296       if (GET_CODE (operand1) != CONST_INT
297 	  && GET_CODE (operand1) != CONST_DOUBLE)
298 	{
299 	  rtx temp = ((reload_in_progress || reload_completed)
300 		      ? operand0 : 0);
301 	  operands[1] = legitimize_address (flag_pic
302 					    && symbolic_address_p (operand1),
303 					    operand1, temp, scratch);
304 	  if (mode != SImode)
305 	    operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
306 	}
307     }
308 
309   /* Now have insn-emit do whatever it normally does.  */
310   return 0;
311 }
312 
313 /* Return a legitimate reference for ORIG (either an address or a MEM)
314    using the register REG.  If PIC and the address is already
315    position-independent, use ORIG.  Newly generated position-independent
316    addresses go into a reg.  This is REG if nonzero, otherwise we
317    allocate register(s) as necessary.  If this is called during reload,
318    and we need a second temp register, then we use SCRATCH, which is
319    provided via the SECONDARY_INPUT_RELOAD_CLASS mechanism.  */
320 
321 struct rtx_def *
322 legitimize_address (pic, orig, reg, scratch)
323      int pic;
324      rtx orig;
325      rtx reg;
326      rtx scratch;
327 {
328   rtx addr = (GET_CODE (orig) == MEM ? XEXP (orig, 0) : orig);
329   rtx new = orig;
330   rtx temp, insn;
331 
332   if (pic)
333     {
334       if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
335 	{
336 	  if (reg == 0)
337 	    {
338 	      if (reload_in_progress || reload_completed)
339 		abort ();
340 	      else
341 		reg = gen_reg_rtx (Pmode);
342 	    }
343 
344 	  if (flag_pic == 2)
345 	    {
346 	      /* If not during reload, allocate another temp reg here for
347 		 loading in the address, so that these instructions can be
348 		 optimized properly.  */
349 	      temp = ((reload_in_progress || reload_completed)
350 		      ? reg : gen_reg_rtx (Pmode));
351 
352 	      /* Must put the SYMBOL_REF inside an UNSPEC here so that cse
353 		 won't get confused into thinking that these two instructions
354 		 are loading in the true address of the symbol.  If in the
355 		 future a PIC rtx exists, that should be used instead.  */
356 	      emit_insn (gen_movsi_high_pic (temp, addr));
357 	      emit_insn (gen_movsi_lo_sum_pic (temp, temp, addr));
358 	      addr = temp;
359 	    }
360 
361 	  new = gen_rtx_MEM (Pmode,
362 			     gen_rtx_PLUS (SImode,
363 					   pic_offset_table_rtx, addr));
364 
365 	  current_function_uses_pic_offset_table = 1;
366 	  RTX_UNCHANGING_P (new) = 1;
367 	  insn = emit_move_insn (reg, new);
368 	  /* Put a REG_EQUAL note on this insn, so that it can be optimized
369 	     by loop.  */
370 	  REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig,
371 						REG_NOTES (insn));
372 	  new = reg;
373 	}
374       else if (GET_CODE (addr) == CONST)
375 	{
376 	  rtx base;
377 
378 	  if (GET_CODE (XEXP (addr, 0)) == PLUS
379 	      && XEXP (XEXP (addr, 0), 0) == pic_offset_table_rtx)
380 	    return orig;
381 
382 	  if (reg == 0)
383 	    {
384 	      if (reload_in_progress || reload_completed)
385 		abort ();
386 	      else
387 		reg = gen_reg_rtx (Pmode);
388 	    }
389 
390 	  if (GET_CODE (XEXP (addr, 0)) != PLUS) abort ();
391 
392 	  base = legitimize_address (1, XEXP (XEXP (addr, 0), 0), reg, 0);
393 	  addr = legitimize_address (1, XEXP (XEXP (addr, 0), 1),
394 				     base == reg ? 0 : reg, 0);
395 
396 	  if (GET_CODE (addr) == CONST_INT)
397 	    {
398 	      if (ADD_INT (addr))
399 		return plus_constant (base, INTVAL (addr));
400 	      else if (! reload_in_progress && ! reload_completed)
401 		addr = force_reg (Pmode, addr);
402 	      /* We can't create any new registers during reload, so use the
403 		 SCRATCH reg provided by the reload_insi pattern.  */
404 	      else if (scratch)
405 		{
406 		  emit_move_insn (scratch, addr);
407 		  addr = scratch;
408 		}
409 	      else
410 		/* If we reach here, then the SECONDARY_INPUT_RELOAD_CLASS
411 		   macro needs to be adjusted so that a scratch reg is provided
412 		   for this address.  */
413 		abort ();
414 	    }
415 	  new = gen_rtx_PLUS (SImode, base, addr);
416 	  /* Should we set special REG_NOTEs here?  */
417 	}
418     }
419   else
420     {
421       if (reg == 0)
422 	{
423 	  if (reload_in_progress || reload_completed)
424 	    abort ();
425 	  else
426 	    reg = gen_reg_rtx (Pmode);
427 	}
428 
429       emit_insn (gen_rtx_SET (VOIDmode,
430 			      reg, gen_rtx_HIGH (SImode, addr)));
431       new = gen_rtx_LO_SUM (SImode, reg, addr);
432     }
433 
434   if (GET_CODE (orig) == MEM)
435     {
436       new = gen_rtx_MEM (GET_MODE (orig), new);
437       MEM_COPY_ATTRIBUTES (new, orig);
438     }
439   return new;
440 }
441 
442 /* Support functions for code to emit a block move.  There are four methods
443    used to perform the block move:
444    + call memcpy
445    + call the looping library function, e.g. __movstrSI64n8
446    + call a non-looping library function, e.g. __movstrHI15x11
447    + produce an inline sequence of ld/st instructions
448 
449    The parameters below describe the library functions produced by
450    movstr-m88k.sh.  */
451 
452 #define MOVSTR_LOOP	64 /* __movstrSI64n68 .. __movstrSI64n8 */
453 #define MOVSTR_QI	16 /* __movstrQI16x16 .. __movstrQI16x2 */
454 #define MOVSTR_HI	48 /* __movstrHI48x48 .. __movstrHI48x4 */
455 #define MOVSTR_SI	96 /* __movstrSI96x96 .. __movstrSI96x8 */
456 #define MOVSTR_DI	96 /* __movstrDI96x96 .. __movstrDI96x16 */
457 #define MOVSTR_ODD_HI	16 /* __movstrHI15x15 .. __movstrHI15x5 */
458 #define MOVSTR_ODD_SI	48 /* __movstrSI47x47 .. __movstrSI47x11,
459 			      __movstrSI46x46 .. __movstrSI46x10,
460 			      __movstrSI45x45 .. __movstrSI45x9 */
461 #define MOVSTR_ODD_DI	48 /* __movstrDI47x47 .. __movstrDI47x23,
462 			      __movstrDI46x46 .. __movstrDI46x22,
463 			      __movstrDI45x45 .. __movstrDI45x21,
464 			      __movstrDI44x44 .. __movstrDI44x20,
465 			      __movstrDI43x43 .. __movstrDI43x19,
466 			      __movstrDI42x42 .. __movstrDI42x18,
467 			      __movstrDI41x41 .. __movstrDI41x17 */
468 
469 /* Limits for using the non-looping movstr functions.  For the m88100
470    processor, we assume the source and destination are word aligned.
471    The QImode and HImode limits are the break even points where memcpy
472    does just as well and beyond which memcpy does better.  For the
473    m88110, we tend to assume double word alignment, but also analyze
474    the word aligned cases.  The analysis is complicated because memcpy
475    may use the cache control instructions for better performance.  */
476 
477 #define MOVSTR_QI_LIMIT_88100   13
478 #define MOVSTR_HI_LIMIT_88100   38
479 #define MOVSTR_SI_LIMIT_88100   MOVSTR_SI
480 #define MOVSTR_DI_LIMIT_88100   MOVSTR_SI
481 
482 #define MOVSTR_QI_LIMIT_88000   16
483 #define MOVSTR_HI_LIMIT_88000   38
484 #define MOVSTR_SI_LIMIT_88000   72
485 #define MOVSTR_DI_LIMIT_88000   72
486 
487 #define MOVSTR_QI_LIMIT_88110   16
488 #define MOVSTR_HI_LIMIT_88110   38
489 #define MOVSTR_SI_LIMIT_88110   72
490 #define MOVSTR_DI_LIMIT_88110   72
491 
492 static const enum machine_mode mode_from_align[] =
493 			      {VOIDmode, QImode, HImode, VOIDmode, SImode,
494 			       VOIDmode, VOIDmode, VOIDmode, DImode};
495 static const int max_from_align[] = {0, MOVSTR_QI, MOVSTR_HI, 0, MOVSTR_SI,
496 				     0, 0, 0, MOVSTR_DI};
497 static const int all_from_align[] = {0, MOVSTR_QI, MOVSTR_ODD_HI, 0,
498 				     MOVSTR_ODD_SI, 0, 0, 0, MOVSTR_ODD_DI};
499 
500 static const int best_from_align[3][9] = {
501   {0, MOVSTR_QI_LIMIT_88100, MOVSTR_HI_LIMIT_88100, 0, MOVSTR_SI_LIMIT_88100,
502    0, 0, 0, MOVSTR_DI_LIMIT_88100},
503   {0, MOVSTR_QI_LIMIT_88110, MOVSTR_HI_LIMIT_88110, 0, MOVSTR_SI_LIMIT_88110,
504    0, 0, 0, MOVSTR_DI_LIMIT_88110},
505   {0, MOVSTR_QI_LIMIT_88000, MOVSTR_HI_LIMIT_88000, 0, MOVSTR_SI_LIMIT_88000,
506    0, 0, 0, MOVSTR_DI_LIMIT_88000}
507 };
508 
509 #if 0
510 static void block_move_loop PARAMS ((rtx, rtx, rtx, rtx, int, int));
511 static void block_move_no_loop PARAMS ((rtx, rtx, rtx, rtx, int, int));
512 #endif
513 static void block_move_sequence PARAMS ((rtx, rtx, rtx, rtx, int, int, int));
514 static void output_short_branch_defs PARAMS ((FILE *));
515 
516 /* Emit code to perform a block move.  Choose the best method.
517 
518    OPERANDS[0] is the destination.
519    OPERANDS[1] is the source.
520    OPERANDS[2] is the size.
521    OPERANDS[3] is the alignment safe to use.  */
522 
523 void
524 expand_block_move (dest_mem, src_mem, operands)
525      rtx dest_mem;
526      rtx src_mem;
527      rtx *operands;
528 {
529   int align = INTVAL (operands[3]);
530   int constp = (GET_CODE (operands[2]) == CONST_INT);
531   int bytes = (constp ? INTVAL (operands[2]) : 0);
532 #if 0
533   int target = (int) m88k_cpu;
534 #endif
535 
536   if (constp && bytes <= 0)
537     return;
538 
539   /* Determine machine mode to do move with.  */
540   if (align > 4 && !TARGET_88110)
541     align = 4;
542   else if (align <= 0 || align == 3)
543     abort ();	/* block move invalid alignment.  */
544 
545   if (constp && bytes <= 3 * align)
546     block_move_sequence (operands[0], dest_mem, operands[1], src_mem,
547 			 bytes, align, 0);
548 
549 #if 0
550   else if (constp && bytes <= best_from_align[target][align] && !TARGET_MEMCPY)
551     block_move_no_loop (operands[0], dest_mem, operands[1], src_mem,
552 			bytes, align);
553 
554   else if (constp && align == 4 && TARGET_88100 && !TARGET_MEMCPY)
555     block_move_loop (operands[0], dest_mem, operands[1], src_mem,
556 		     bytes, align);
557 #endif
558 
559   else
560     {
561 #ifdef TARGET_MEM_FUNCTIONS
562       emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "memcpy"), 0,
563 			 VOIDmode, 3,
564 			 operands[0], Pmode,
565 			 operands[1], Pmode,
566 			 convert_to_mode (TYPE_MODE (sizetype), operands[2],
567 					  TREE_UNSIGNED (sizetype)),
568 			 TYPE_MODE (sizetype));
569 #else
570       emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "bcopy"), 0,
571 			 VOIDmode, 3,
572 			 operands[1], Pmode,
573 			 operands[0], Pmode,
574 			 convert_to_mode (TYPE_MODE (integer_type_node),
575 					  operands[2],
576 					  TREE_UNSIGNED (integer_type_node)),
577 			 TYPE_MODE (integer_type_node));
578 #endif
579     }
580 }
581 
582 #if 0
583 /* Emit code to perform a block move by calling a looping movstr library
584    function.  SIZE and ALIGN are known constants.  DEST and SRC are
585    registers.  */
586 
587 static void
588 block_move_loop (dest, dest_mem, src, src_mem, size, align)
589      rtx dest, dest_mem;
590      rtx src, src_mem;
591      int size;
592      int align;
593 {
594   enum machine_mode mode;
595   int count;
596   int units;
597   int remainder;
598   rtx offset_rtx;
599   rtx value_rtx;
600   char entry[30];
601   tree entry_name;
602 
603   /* Determine machine mode to do move with.  */
604   if (align != 4)
605     abort ();
606 
607   /* Determine the structure of the loop.  */
608   count = size / MOVSTR_LOOP;
609   units = (size - count * MOVSTR_LOOP) / align;
610 
611   if (units < 2)
612     {
613       count--;
614       units += MOVSTR_LOOP / align;
615     }
616 
617   if (count <= 0)
618     {
619       block_move_no_loop (dest, dest_mem, src, src_mem, size, align);
620       return;
621     }
622 
623   remainder = size - count * MOVSTR_LOOP - units * align;
624 
625   mode = mode_from_align[align];
626   sprintf (entry, "__movstr%s%dn%d",
627 	   GET_MODE_NAME (mode), MOVSTR_LOOP, units * align);
628   entry_name = get_identifier (entry);
629 
630   offset_rtx = GEN_INT (MOVSTR_LOOP + (1 - units) * align);
631 
632   value_rtx = gen_rtx_MEM (MEM_IN_STRUCT_P (src_mem) ? mode : BLKmode,
633 			   gen_rtx_PLUS (Pmode,
634 					 gen_rtx_REG (Pmode, 3),
635 					 offset_rtx));
636   MEM_COPY_ATTRIBUTES (value_rtx, src_mem);
637 
638   emit_insn (gen_call_movstrsi_loop
639 	     (gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (entry_name)),
640 	      dest, src, offset_rtx, value_rtx,
641 	      gen_rtx_REG (mode, ((units & 1) ? 4 : 5)),
642 	      GEN_INT (count)));
643 
644   if (remainder)
645     block_move_sequence (gen_rtx_REG (Pmode, 2), dest_mem,
646 			 gen_rtx_REG (Pmode, 3), src_mem,
647 			 remainder, align, MOVSTR_LOOP + align);
648 }
649 
650 /* Emit code to perform a block move by calling a non-looping library
651    function.  SIZE and ALIGN are known constants.  DEST and SRC are
652    registers.  OFFSET is the known starting point for the output pattern.  */
653 
654 static void
655 block_move_no_loop (dest, dest_mem, src, src_mem, size, align)
656      rtx dest, dest_mem;
657      rtx src, src_mem;
658      int size;
659      int align;
660 {
661   enum machine_mode mode = mode_from_align[align];
662   int units = size / align;
663   int remainder = size - units * align;
664   int most;
665   int value_reg;
666   rtx offset_rtx;
667   rtx value_rtx;
668   char entry[30];
669   tree entry_name;
670 
671   if (remainder && size <= all_from_align[align])
672     {
673       most = all_from_align[align] - (align - remainder);
674       remainder = 0;
675     }
676   else
677     {
678       most = max_from_align[align];
679     }
680 
681   sprintf (entry, "__movstr%s%dx%d",
682 	   GET_MODE_NAME (mode), most, size - remainder);
683   entry_name = get_identifier (entry);
684 
685   offset_rtx = GEN_INT (most - (size - remainder));
686 
687   value_rtx = gen_rtx_MEM (MEM_IN_STRUCT_P (src_mem) ? mode : BLKmode,
688 			   gen_rtx_PLUS (Pmode,
689 					 gen_rtx_REG (Pmode, 3),
690 					 offset_rtx));
691 
692   MEM_COPY_ATTRIBUTES (value_rtx, src_mem);
693 
694   value_reg = ((((most - (size - remainder)) / align) & 1) == 0
695 	       ? (mode == DImode ? 6 : 5) : 4);
696 
697   if (mode == DImode)
698     {
699       emit_insn (gen_call_block_move_DI
700 		 (gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (entry_name)),
701 		  dest, src, offset_rtx, value_rtx,
702 		  gen_rtx_REG (mode, value_reg)));
703     }
704   else
705     {
706       emit_insn (gen_call_block_move
707 		 (gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (entry_name)),
708 		  dest, src, offset_rtx, value_rtx,
709 		  gen_rtx_REG (mode, value_reg)));
710     }
711 
712   if (remainder)
713     block_move_sequence (gen_rtx_REG (Pmode, 2), dest_mem,
714 			 gen_rtx_REG (Pmode, 3), src_mem,
715 			 remainder, align, most);
716 }
717 #endif
718 
719 /* Emit code to perform a block move with an offset sequence of ld/st
720    instructions (..., ld 0, st 1, ld 1, st 0, ...).  SIZE and ALIGN are
721    known constants.  DEST and SRC are registers.  OFFSET is the known
722    starting point for the output pattern.  */
723 
724 static void
725 block_move_sequence (dest, dest_mem, src, src_mem, size, align, offset)
726      rtx dest, dest_mem;
727      rtx src, src_mem;
728      int size;
729      int align;
730      int offset;
731 {
732   rtx temp[2];
733   enum machine_mode mode[2];
734   int amount[2];
735   int active[2];
736   int phase = 0;
737   int next;
738   int offset_ld = offset;
739   int offset_st = offset;
740 
741   active[0] = active[1] = FALSE;
742 
743   /* Establish parameters for the first load and for the second load if
744      it is known to be the same mode as the first.  */
745   amount[0] = amount[1] = align;
746   mode[0] = mode_from_align[align];
747   temp[0] = gen_reg_rtx (mode[0]);
748   if (size >= 2 * align)
749     {
750       mode[1] = mode[0];
751       temp[1] = gen_reg_rtx (mode[1]);
752     }
753 
754   do
755     {
756       next = phase;
757       phase = !phase;
758 
759       if (size > 0)
760 	{
761 	  /* Change modes as the sequence tails off.  */
762 	  if (size < amount[next])
763 	    {
764 	      amount[next] = (size >= 4 ? 4 : (size >= 2 ? 2 : 1));
765 	      mode[next] = mode_from_align[amount[next]];
766 	      temp[next] = gen_reg_rtx (mode[next]);
767 	    }
768 	  size -= amount[next];
769 	  emit_move_insn (temp[next],
770 			  adjust_address (src_mem, mode[next], offset_ld));
771 	  offset_ld += amount[next];
772 	  active[next] = TRUE;
773 	}
774 
775       if (active[phase])
776 	{
777 	  active[phase] = FALSE;
778 	  emit_move_insn (adjust_address (dest_mem, mode[phase], offset_st),
779 			  temp[phase]);
780 	  offset_st += amount[phase];
781 	}
782     }
783   while (active[next]);
784 }
785 
786 /* Emit the code to do an AND operation.  */
787 
788 const char *
789 output_and (operands)
790      rtx operands[];
791 {
792   unsigned int value;
793 
794   if (REG_P (operands[2]))
795     return "and %0,%1,%2";
796 
797   value = INTVAL (operands[2]);
798   if (SMALL_INTVAL (value))
799     return "mask %0,%1,%2";
800   else if ((value & 0xffff0000) == 0xffff0000)
801     return "and %0,%1,%x2";
802   else if ((value & 0xffff) == 0xffff)
803     return "and.u %0,%1,%X2";
804   else if ((value & 0xffff) == 0)
805     return "mask.u %0,%1,%X2";
806   else if (integer_ok_for_set (~value))
807     return "clr %0,%1,%S2";
808   else
809     return "and.u %0,%1,%X2\n\tand %0,%0,%x2";
810 }
811 
812 /* Emit the code to do an inclusive OR operation.  */
813 
814 const char *
815 output_ior (operands)
816      rtx operands[];
817 {
818   unsigned int value;
819 
820   if (REG_P (operands[2]))
821     return "or %0,%1,%2";
822 
823   value = INTVAL (operands[2]);
824   if (SMALL_INTVAL (value))
825     return "or %0,%1,%2";
826   else if ((value & 0xffff) == 0)
827     return "or.u %0,%1,%X2";
828   else if (integer_ok_for_set (value))
829     return "set %0,%1,%s2";
830   else
831     return "or.u %0,%1,%X2\n\tor %0,%0,%x2";
832 }
833 
834 /* Emit the instructions for doing an XOR.  */
835 
836 const char *
837 output_xor (operands)
838      rtx operands[];
839 {
840   unsigned int value;
841 
842   if (REG_P (operands[2]))
843     return "xor %0,%1,%2";
844 
845   value = INTVAL (operands[2]);
846   if (SMALL_INTVAL (value))
847     return "xor %0,%1,%2";
848   else if ((value & 0xffff) == 0)
849     return "xor.u %0,%1,%X2";
850   else
851     return "xor.u %0,%1,%X2\n\txor %0,%0,%x2";
852 }
853 
854 /* Output a call.  Normally this is just bsr or jsr, but this also deals with
855    accomplishing a branch after the call by incrementing r1.  This requires
856    that various assembler bugs be accommodated.  The 4.30 DG/UX assembler
857    requires that forward references not occur when computing the difference of
858    two labels.  The [version?] Motorola assembler computes a word difference.
859    No doubt there's more to come!
860 
861    It would seem the same idea could be used to tail call, but in this case,
862    the epilogue will be non-null.  */
863 
864 static rtx sb_name = 0;
865 static rtx sb_high = 0;
866 static rtx sb_low = 0;
867 
868 const char *
869 output_call (operands, addr)
870      rtx operands[];
871      rtx addr;
872 {
873   operands[0] = addr;
874   if (final_sequence)
875     {
876       rtx jump;
877       rtx seq_insn;
878 
879       /* This can be generalized, but there is currently no need.  */
880       if (XVECLEN (final_sequence, 0) != 2)
881 	abort ();
882 
883       /* The address of interior insns is not computed, so use the sequence.  */
884       seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
885       jump = XVECEXP (final_sequence, 0, 1);
886       if (GET_CODE (jump) == JUMP_INSN)
887 	{
888 #ifndef USE_GAS
889 	  rtx low, high;
890 #endif
891 	  const char *last;
892 	  rtx dest = XEXP (SET_SRC (PATTERN (jump)), 0);
893 	  int delta = 4 * (INSN_ADDRESSES (INSN_UID (dest))
894 			   - INSN_ADDRESSES (INSN_UID (seq_insn))
895 			   - 2);
896 
897 	  /* Delete the jump.  */
898 	  PUT_CODE (jump, NOTE);
899 	  NOTE_LINE_NUMBER (jump) = NOTE_INSN_DELETED;
900 	  NOTE_SOURCE_FILE (jump) = 0;
901 
902 	  /* We only do this optimization if -O2, modifying the value of
903 	     r1 in the delay slot confuses debuggers and profilers on some
904 	     systems.
905 
906 	     If we loose, we must use the non-delay form.  This is unlikely
907 	     to ever happen.  If it becomes a problem, claim that a call
908 	     has two delay slots and only the second can be filled with
909 	     a jump.
910 
911 	     The 88110 can lose when a jsr.n r1 is issued and a page fault
912 	     occurs accessing the delay slot.  So don't use jsr.n form when
913 	     jumping thru r1.
914 	   */
915 	  if (optimize < 2
916 	      || ! ADD_INTVAL (delta)
917 	      || (REG_P (addr) && REGNO (addr) == 1))
918 	    {
919 	      operands[1] = dest;
920 	      return (REG_P (addr)
921 		      ? "jsr %0\n\tbr %l1"
922 		      : (flag_pic
923 			 ? "bsr %0#plt\n\tbr %l1"
924 			 : "bsr %0\n\tbr %l1"));
925 	    }
926 
927 	  /* Output the short branch form.  */
928 	  output_asm_insn ((REG_P (addr)
929 			    ? "jsr.n %0"
930 			    : (flag_pic ? "bsr.n %0#plt" : "bsr.n %0")),
931 			   operands);
932 
933 #ifdef USE_GAS
934 	  last = (delta < 0
935 		  ? "subu %#r1,%#r1,.-%l0+4"
936 		  : "addu %#r1,%#r1,%l0-.-4");
937 	  operands[0] = dest;
938 #else
939 	  operands[0] = gen_label_rtx ();
940 	  operands[1] = gen_label_rtx ();
941 	  if (delta < 0)
942 	    {
943 	      low = dest;
944 	      high = operands[1];
945 	      last = "subu %#r1,%#r1,%l0\n%l1:";
946 	    }
947 	  else
948 	    {
949 	      low = operands[1];
950 	      high = dest;
951 	      last = "addu %#r1,%#r1,%l0\n%l1:";
952 	    }
953 
954 	  /* Record the values to be computed later as "def name,high-low".  */
955 	  sb_name = gen_rtx_EXPR_LIST (VOIDmode, operands[0], sb_name);
956 	  sb_high = gen_rtx_EXPR_LIST (VOIDmode, high, sb_high);
957 	  sb_low = gen_rtx_EXPR_LIST (VOIDmode, low, sb_low);
958 #endif /* Don't USE_GAS */
959 
960 	  return last;
961 	}
962     }
963   return (REG_P (addr)
964 	  ? "jsr%. %0"
965 	  : (flag_pic ? "bsr%. %0#plt" : "bsr%. %0"));
966 }
967 
968 static void
969 output_short_branch_defs (stream)
970      FILE *stream;
971 {
972   char name[256], high[256], low[256];
973 
974   for (; sb_name && sb_high && sb_low;
975        sb_name = XEXP (sb_name, 1),
976        sb_high = XEXP (sb_high, 1),
977        sb_low = XEXP (sb_low, 1))
978     {
979       ASM_GENERATE_INTERNAL_LABEL
980 	(name, "L", CODE_LABEL_NUMBER (XEXP (sb_name, 0)));
981       ASM_GENERATE_INTERNAL_LABEL
982 	(high, "L", CODE_LABEL_NUMBER (XEXP (sb_high, 0)));
983       ASM_GENERATE_INTERNAL_LABEL
984 	(low, "L", CODE_LABEL_NUMBER (XEXP (sb_low, 0)));
985       /* This will change as the assembler requirements become known.  */
986       fprintf (stream, "%s%s,%s-%s\n",
987 	       SET_ASM_OP, &name[1], &high[1], &low[1]);
988     }
989   if (sb_name || sb_high || sb_low)
990     abort ();
991 }
992 
993 /* Return truth value of the statement that this conditional branch is likely
994    to fall through.  CONDITION, is the condition that JUMP_INSN is testing.  */
995 
996 int
997 mostly_false_jump (jump_insn, condition)
998      rtx jump_insn, condition;
999 {
1000   rtx target_label = JUMP_LABEL (jump_insn);
1001   rtx insnt, insnj;
1002 
1003   /* Much of this isn't computed unless we're optimizing.  */
1004   if (optimize == 0)
1005     return 0;
1006 
1007   /* Determine if one path or the other leads to a return.  */
1008   for (insnt = NEXT_INSN (target_label);
1009        insnt;
1010        insnt = NEXT_INSN (insnt))
1011     {
1012       if (GET_CODE (insnt) == JUMP_INSN)
1013 	break;
1014       else if (GET_CODE (insnt) == INSN
1015 	       && GET_CODE (PATTERN (insnt)) == SEQUENCE
1016 	       && GET_CODE (XVECEXP (PATTERN (insnt), 0, 0)) == JUMP_INSN)
1017 	{
1018 	  insnt = XVECEXP (PATTERN (insnt), 0, 0);
1019 	  break;
1020 	}
1021     }
1022   if (insnt
1023       && (GET_CODE (PATTERN (insnt)) == RETURN
1024 	  || (GET_CODE (PATTERN (insnt)) == SET
1025 	      && GET_CODE (SET_SRC (PATTERN (insnt))) == REG
1026 	      && REGNO (SET_SRC (PATTERN (insnt))) == 1)))
1027     insnt = 0;
1028 
1029   for (insnj = NEXT_INSN (jump_insn);
1030        insnj;
1031        insnj = NEXT_INSN (insnj))
1032     {
1033       if (GET_CODE (insnj) == JUMP_INSN)
1034 	break;
1035       else if (GET_CODE (insnj) == INSN
1036 	       && GET_CODE (PATTERN (insnj)) == SEQUENCE
1037 	       && GET_CODE (XVECEXP (PATTERN (insnj), 0, 0)) == JUMP_INSN)
1038 	{
1039 	  insnj = XVECEXP (PATTERN (insnj), 0, 0);
1040 	  break;
1041 	}
1042     }
1043   if (insnj
1044       && (GET_CODE (PATTERN (insnj)) == RETURN
1045 	  || (GET_CODE (PATTERN (insnj)) == SET
1046 	      && GET_CODE (SET_SRC (PATTERN (insnj))) == REG
1047 	      && REGNO (SET_SRC (PATTERN (insnj))) == 1)))
1048     insnj = 0;
1049 
1050   /* Predict to not return.  */
1051   if ((insnt == 0) != (insnj == 0))
1052     return (insnt == 0);
1053 
1054   /* Predict loops to loop.  */
1055   for (insnt = PREV_INSN (target_label);
1056        insnt && GET_CODE (insnt) == NOTE;
1057        insnt = PREV_INSN (insnt))
1058     if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_END)
1059       return 1;
1060     else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_BEG)
1061       return 0;
1062     else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_CONT)
1063       return 0;
1064 
1065   /* Predict backward branches usually take.  */
1066   if (final_sequence)
1067     insnj = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
1068   else
1069     insnj = jump_insn;
1070   if (INSN_ADDRESSES (INSN_UID (insnj))
1071       > INSN_ADDRESSES (INSN_UID (target_label)))
1072     return 0;
1073 
1074   /* EQ tests are usually false and NE tests are usually true.  Also,
1075      most quantities are positive, so we can make the appropriate guesses
1076      about signed comparisons against zero.  Consider unsigned comparisons
1077      to be a range check and assume quantities to be in range.  */
1078   switch (GET_CODE (condition))
1079     {
1080     case CONST_INT:
1081       /* Unconditional branch.  */
1082       return 0;
1083     case EQ:
1084       return 1;
1085     case NE:
1086       return 0;
1087     case LE:
1088     case LT:
1089     case GEU:
1090     case GTU: /* Must get casesi right at least.  */
1091       if (XEXP (condition, 1) == const0_rtx)
1092         return 1;
1093       break;
1094     case GE:
1095     case GT:
1096     case LEU:
1097     case LTU:
1098       if (XEXP (condition, 1) == const0_rtx)
1099 	return 0;
1100       break;
1101     default:
1102       break;
1103     }
1104 
1105   return 0;
1106 }
1107 
1108 /* Return true if the operand is a power of two and is a floating
1109    point type (to optimize division by power of two into multiplication).  */
1110 
1111 int
1112 real_power_of_2_operand (op, mode)
1113      rtx op;
1114      enum machine_mode mode ATTRIBUTE_UNUSED;
1115 {
1116   REAL_VALUE_TYPE d;
1117   union {
1118     long l[2];
1119     struct {				/* IEEE double precision format */
1120       unsigned sign	 :  1;
1121       unsigned exponent  : 11;
1122       unsigned mantissa1 : 20;
1123       unsigned mantissa2;
1124     } s;
1125     struct {				/* IEEE double format to quick check */
1126       unsigned sign	 :  1;		/* if it fits in a float */
1127       unsigned exponent1 :  4;
1128       unsigned exponent2 :  7;
1129       unsigned mantissa1 : 20;
1130       unsigned mantissa2;
1131     } s2;
1132   } u;
1133 
1134   if (GET_MODE (op) != DFmode && GET_MODE (op) != SFmode)
1135     return 0;
1136 
1137   if (GET_CODE (op) != CONST_DOUBLE)
1138     return 0;
1139 
1140   REAL_VALUE_FROM_CONST_DOUBLE (d, op);
1141   REAL_VALUE_TO_TARGET_DOUBLE (d, u.l);
1142 
1143   if (u.s.mantissa1 != 0 || u.s.mantissa2 != 0	/* not a power of two */
1144       || u.s.exponent == 0			/* constant 0.0 */
1145       || u.s.exponent == 0x7ff			/* NAN */
1146       || (u.s2.exponent1 != 0x8 && u.s2.exponent1 != 0x7))
1147     return 0;					/* const won't fit in float */
1148 
1149   return 1;
1150 }
1151 
1152 /* Make OP legitimate for mode MODE.  Currently this only deals with DFmode
1153    operands, putting them in registers and making CONST_DOUBLE values
1154    SFmode where possible.  */
1155 
1156 struct rtx_def *
1157 legitimize_operand (op, mode)
1158      rtx op;
1159      enum machine_mode mode;
1160 {
1161   rtx temp;
1162   REAL_VALUE_TYPE r;
1163   union {
1164     long l[2];
1165     struct {				/* IEEE double precision format */
1166       unsigned sign	 :  1;
1167       unsigned exponent  : 11;
1168       unsigned mantissa1 : 20;
1169       unsigned mantissa2;
1170     } d;
1171     struct {				/* IEEE double format to quick check */
1172       unsigned sign	 :  1;		/* if it fits in a float */
1173       unsigned exponent1 :  4;
1174       unsigned exponent2 :  7;
1175       unsigned mantissa1 : 20;
1176       unsigned mantissa2;
1177     } s;
1178   } u;
1179 
1180   if (GET_CODE (op) == REG || mode != DFmode)
1181     return op;
1182 
1183   if (GET_CODE (op) == CONST_DOUBLE)
1184     {
1185       REAL_VALUE_FROM_CONST_DOUBLE (r, op);
1186       REAL_VALUE_TO_TARGET_DOUBLE (r, u.l);
1187       if (u.d.exponent != 0x7ff /* NaN */
1188 	  && u.d.mantissa2 == 0 /* Mantissa fits */
1189 	  && (u.s.exponent1 == 0x8 || u.s.exponent1 == 0x7) /* Exponent fits */
1190 	  && (temp = simplify_unary_operation (FLOAT_TRUNCATE, SFmode,
1191 					       op, mode)) != 0)
1192 	return gen_rtx_FLOAT_EXTEND (mode, force_reg (SFmode, temp));
1193     }
1194   else if (register_operand (op, mode))
1195     return op;
1196 
1197   return force_reg (mode, op);
1198 }
1199 
1200 /* Return true if OP is a suitable input for a move insn.  */
1201 
1202 int
1203 move_operand (op, mode)
1204      rtx op;
1205      enum machine_mode mode;
1206 {
1207   if (register_operand (op, mode))
1208     return 1;
1209   if (GET_CODE (op) == CONST_INT)
1210     return (classify_integer (mode, INTVAL (op)) < m88k_oru_hi16);
1211   if (GET_MODE (op) != mode)
1212     return 0;
1213   if (GET_CODE (op) == SUBREG)
1214     op = SUBREG_REG (op);
1215   if (GET_CODE (op) != MEM)
1216     return 0;
1217 
1218   op = XEXP (op, 0);
1219   if (GET_CODE (op) == LO_SUM)
1220     return (REG_P (XEXP (op, 0))
1221 	    && symbolic_address_p (XEXP (op, 1)));
1222   return memory_address_p (mode, op);
1223 }
1224 
1225 /* Return true if OP is suitable for a call insn.  */
1226 
1227 int
1228 call_address_operand (op, mode)
1229      rtx op;
1230      enum machine_mode mode ATTRIBUTE_UNUSED;
1231 {
1232   return (REG_P (op) || symbolic_address_p (op));
1233 }
1234 
1235 /* Returns true if OP is either a symbol reference or a sum of a symbol
1236    reference and a constant.  */
1237 
1238 int
1239 symbolic_address_p (op)
1240      register rtx op;
1241 {
1242   switch (GET_CODE (op))
1243     {
1244     case SYMBOL_REF:
1245     case LABEL_REF:
1246       return 1;
1247 
1248     case CONST:
1249       op = XEXP (op, 0);
1250       return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
1251 	       || GET_CODE (XEXP (op, 0)) == LABEL_REF)
1252 	      && GET_CODE (XEXP (op, 1)) == CONST_INT);
1253 
1254     default:
1255       return 0;
1256     }
1257 }
1258 
1259 /* Return true if OP is a register or const0_rtx.  */
1260 
1261 int
1262 reg_or_0_operand (op, mode)
1263      rtx op;
1264      enum machine_mode mode;
1265 {
1266   return (op == const0_rtx || register_operand (op, mode));
1267 }
1268 
1269 /* Nonzero if OP is a valid second operand for an arithmetic insn.  */
1270 
1271 int
1272 arith_operand (op, mode)
1273      rtx op;
1274      enum machine_mode mode;
1275 {
1276   return (register_operand (op, mode)
1277 	  || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
1278 }
1279 
1280 /* Return true if OP is a  register or 5 bit integer.  */
1281 
1282 int
1283 arith5_operand (op, mode)
1284      rtx op;
1285      enum machine_mode mode;
1286 {
1287   return (register_operand (op, mode)
1288 	  || (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32));
1289 }
1290 
1291 int
1292 arith32_operand (op, mode)
1293      rtx op;
1294      enum machine_mode mode;
1295 {
1296   return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
1297 }
1298 
1299 int
1300 arith64_operand (op, mode)
1301      rtx op;
1302      enum machine_mode mode;
1303 {
1304   return (register_operand (op, mode)
1305 	  || GET_CODE (op) == CONST_INT
1306 	  || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode));
1307 }
1308 
1309 int
1310 int5_operand (op, mode)
1311      rtx op;
1312      enum machine_mode mode ATTRIBUTE_UNUSED;
1313 {
1314   return (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32);
1315 }
1316 
1317 int
1318 int32_operand (op, mode)
1319      rtx op;
1320      enum machine_mode mode ATTRIBUTE_UNUSED;
1321 {
1322   return (GET_CODE (op) == CONST_INT);
1323 }
1324 
1325 /* Return true if OP is a register or a valid immediate operand for
1326    addu or subu.  */
1327 
1328 int
1329 add_operand (op, mode)
1330      rtx op;
1331      enum machine_mode mode;
1332 {
1333   return (register_operand (op, mode)
1334 	  || (GET_CODE (op) == CONST_INT && ADD_INT (op)));
1335 }
1336 
1337 /* Nonzero if this is a bitmask filling the bottom bits, for optimizing and +
1338    shift left combinations into a single mak instruction.  */
1339 
1340 int
1341 mak_mask_p (value)
1342      int value;
1343 {
1344   return (value && POWER_OF_2_or_0 (value + 1));
1345 }
1346 
1347 int
1348 reg_or_bbx_mask_operand (op, mode)
1349      rtx op;
1350      enum machine_mode mode;
1351 {
1352   int value;
1353   if (register_operand (op, mode))
1354     return 1;
1355   if (GET_CODE (op) != CONST_INT)
1356     return 0;
1357 
1358   value = INTVAL (op);
1359   if (POWER_OF_2 (value))
1360     return 1;
1361 
1362   return 0;
1363 }
1364 
1365 /* Return true if OP is valid to use in the context of a floating
1366    point operation.  Special case 0.0, since we can use r0.  */
1367 
1368 int
1369 real_or_0_operand (op, mode)
1370      rtx op;
1371      enum machine_mode mode;
1372 {
1373   if (mode != SFmode && mode != DFmode)
1374     return 0;
1375 
1376   return (register_operand (op, mode)
1377 	  || (GET_CODE (op) == CONST_DOUBLE
1378 	      && op == CONST0_RTX (mode)));
1379 }
1380 
1381 /* Return true if OP is valid to use in the context of logic arithmetic
1382    on condition codes. */
1383 
1384 int
1385 partial_ccmode_register_operand (op, mode)
1386      rtx op;
1387      enum machine_mode mode ATTRIBUTE_UNUSED;
1388 {
1389   return register_operand (op, CCmode) || register_operand (op, CCEVENmode);
1390 }
1391 
1392 /* Return true if OP is a relational operator.  */
1393 
1394 int
1395 relop (op, mode)
1396      rtx op;
1397      enum machine_mode mode ATTRIBUTE_UNUSED;
1398 {
1399   switch (GET_CODE (op))
1400     {
1401     case EQ:
1402     case NE:
1403     case LT:
1404     case LE:
1405     case GE:
1406     case GT:
1407     case LTU:
1408     case LEU:
1409     case GEU:
1410     case GTU:
1411       return 1;
1412     default:
1413       return 0;
1414     }
1415 }
1416 
1417 int
1418 even_relop (op, mode)
1419      rtx op;
1420      enum machine_mode mode ATTRIBUTE_UNUSED;
1421 {
1422   switch (GET_CODE (op))
1423     {
1424     case EQ:
1425     case LT:
1426     case GT:
1427     case LTU:
1428     case GTU:
1429       return 1;
1430     default:
1431       return 0;
1432     }
1433 }
1434 
1435 int
1436 odd_relop (op, mode)
1437      rtx op;
1438      enum machine_mode mode ATTRIBUTE_UNUSED;
1439 {
1440   switch (GET_CODE (op))
1441     {
1442     case NE:
1443     case LE:
1444     case GE:
1445     case LEU:
1446     case GEU:
1447       return 1;
1448     default:
1449       return 0;
1450     }
1451 }
1452 
1453 /* Return true if OP is a relational operator, and is not an unsigned
1454    relational operator.  */
1455 
1456 int
1457 relop_no_unsigned (op, mode)
1458      rtx op;
1459      enum machine_mode mode ATTRIBUTE_UNUSED;
1460 {
1461   switch (GET_CODE (op))
1462     {
1463     case EQ:
1464     case NE:
1465     case LT:
1466     case LE:
1467     case GE:
1468     case GT:
1469       /* @@ What is this test doing?  Why not use `mode'?  */
1470       if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
1471 	  || GET_MODE (op) == DImode
1472 	  || GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_FLOAT
1473 	  || GET_MODE (XEXP (op, 0)) == DImode
1474 	  || GET_MODE_CLASS (GET_MODE (XEXP (op, 1))) == MODE_FLOAT
1475 	  || GET_MODE (XEXP (op, 1)) == DImode)
1476 	return 0;
1477       return 1;
1478     default:
1479       return 0;
1480     }
1481 }
1482 
1483 /* Return true if the code of this rtx pattern is EQ or NE.  */
1484 
1485 int
1486 equality_op (op, mode)
1487      rtx op;
1488      enum machine_mode mode ATTRIBUTE_UNUSED;
1489 {
1490   return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
1491 }
1492 
1493 /* Return true if the code of this rtx pattern is pc or label_ref.  */
1494 
1495 int
1496 pc_or_label_ref (op, mode)
1497      rtx op;
1498      enum machine_mode mode ATTRIBUTE_UNUSED;
1499 {
1500   return (GET_CODE (op) == PC || GET_CODE (op) == LABEL_REF);
1501 }
1502 
1503 /* Output to FILE the start of the assembler file.  */
1504 
1505 void
1506 output_file_start (file)
1507      FILE *file;
1508 {
1509   if (TARGET_88110)
1510     fprintf (file, "%s\n", REQUIRES_88110_ASM_OP);
1511 
1512   output_file_directive (file, main_input_filename);
1513 }
1514 
1515 #ifndef OBJECT_FORMAT_ELF
1516 /* Output an ascii string.  */
1517 
1518 void
1519 output_ascii (file, opcode, max, p, size)
1520      FILE *file;
1521      const char *opcode;
1522      int max;
1523      const char *p;
1524      int size;
1525 {
1526   int i;
1527   int in_escape = 0;
1528 
1529   register int num = 0;
1530 
1531   fprintf (file, "%s\"", opcode);
1532   for (i = 0; i < size; i++)
1533     {
1534       register int c = (unsigned char) p[i];
1535 
1536       if (num > max)
1537 	{
1538 	  fprintf (file, "\"\n%s\"", opcode);
1539 	  num = 0;
1540 	}
1541 
1542       if (c == '\"' || c == '\\')
1543 	{
1544 	escape:
1545 	  putc ('\\', file);
1546 	  putc (c, file);
1547 	  num += 2;
1548 	  in_escape = 0;
1549 	}
1550       else if (in_escape && ISDIGIT (c))
1551 	{
1552 	  /* If a digit follows an octal-escape, the VAX assembler fails
1553 	     to stop reading the escape after three digits.  Continue to
1554 	     output the values as an octal-escape until a non-digit is
1555 	     found.  */
1556 	  fprintf (file, "\\%03o", c);
1557 	  num += 4;
1558 	}
1559       else if ((c >= ' ' && c < 0177) || (c == '\t'))
1560 	{
1561 	  putc (c, file);
1562 	  num++;
1563 	  in_escape = 0;
1564 	}
1565       else
1566 	{
1567 	  switch (c)
1568 	    {
1569 	      /* Some assemblers can't handle \a, \v, or \?.  */
1570 	    case '\f': c = 'f'; goto escape;
1571 	    case '\b': c = 'b'; goto escape;
1572 	    case '\r': c = 'r'; goto escape;
1573 	    case '\n': c = 'n'; goto escape;
1574 	    }
1575 
1576 	  fprintf (file, "\\%03o", c);
1577 	  num += 4;
1578 	  in_escape = 1;
1579 	}
1580     }
1581   fprintf (file, "\"\n");
1582 }
1583 #endif
1584 
1585 /* Output a label (allows insn-output.c to be compiled without including
1586    m88k.c or needing to include stdio.h).  */
1587 
1588 void
1589 output_label (label_number)
1590      int label_number;
1591 {
1592   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", label_number);
1593 }
1594 
1595 /* Generate the assembly code for function entry.
1596 
1597    The prologue is responsible for setting up the stack frame,
1598    initializing the frame pointer register, saving registers that must be
1599    saved, and allocating SIZE additional bytes of storage for the
1600    local variables.  SIZE is an integer.  FILE is a stdio
1601    stream to which the assembler code should be output.
1602 
1603    The label for the beginning of the function need not be output by this
1604    macro.  That has already been done when the macro is run.
1605 
1606    To determine which registers to save, the macro can refer to the array
1607    `regs_ever_live': element R is nonzero if hard register
1608    R is used anywhere within the function.  This implies the
1609    function prologue should save register R, but not if it is one
1610    of the call-used registers.
1611 
1612    On machines where functions may or may not have frame-pointers, the
1613    function entry code must vary accordingly; it must set up the frame
1614    pointer if one is wanted, and not otherwise.  To determine whether a
1615    frame pointer is in wanted, the macro can refer to the variable
1616    `frame_pointer_needed'.  The variable's value will be 1 at run
1617    time in a function that needs a frame pointer.
1618 
1619    On machines where an argument may be passed partly in registers and
1620    partly in memory, this macro must examine the variable
1621    `current_function_pretend_args_size', and allocate that many bytes
1622    of uninitialized space on the stack just underneath the first argument
1623    arriving on the stack.  (This may not be at the very end of the stack,
1624    if the calling sequence has pushed anything else since pushing the stack
1625    arguments.  But usually, on such machines, nothing else has been pushed
1626    yet, because the function prologue itself does all the pushing.)
1627 
1628    If `ACCUMULATE_OUTGOING_ARGS' is defined, the variable
1629    `current_function_outgoing_args_size' contains the size in bytes
1630    required for the outgoing arguments.  This macro must add that
1631    amount of uninitialized space to very bottom of the stack.
1632 
1633    The stack frame we use looks like this:
1634 
1635  caller                                                  callee
1636         |==============================================|
1637         |                caller's frame                |
1638         |==============================================|
1639         |     [caller's outgoing memory arguments]     |
1640   sp -> |==============================================| <- ap
1641         |            [local variable space]            |
1642         |----------------------------------------------|
1643         |            [return address (r1)]             |
1644         |----------------------------------------------|
1645         |        [previous frame pointer (r30)]        |
1646         |==============================================| <- fp
1647         |       [preserved registers (r25..r14)]       |
1648         |----------------------------------------------|
1649         |       [preserved registers (x29..x22)]       |
1650         |==============================================|
1651         |    [dynamically allocated space (alloca)]    |
1652         |==============================================|
1653         |     [callee's outgoing memory arguments]     |
1654         |==============================================| <- sp
1655 
1656   Notes:
1657 
1658   r1 and r30 must be saved if debugging.
1659 
1660   fp (if present) is located two words down from the local
1661   variable space.
1662   */
1663 
1664 static rtx emit_add PARAMS ((rtx, rtx, int));
1665 static void preserve_registers PARAMS ((int, int));
1666 static void emit_ldst PARAMS ((int, int, enum machine_mode, int));
1667 
1668 static int  nregs;
1669 static int  nxregs;
1670 static char save_regs[FIRST_PSEUDO_REGISTER];
1671 static int  frame_laid_out;
1672 static int  frame_size;
1673 
1674 #define STACK_UNIT_BOUNDARY (STACK_BOUNDARY / BITS_PER_UNIT)
1675 #define ROUND_CALL_BLOCK_SIZE(BYTES) \
1676   (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1))
1677 
1678 /* Establish the position of the FP relative to the SP.  This is done
1679    either during output_function_prologue() or by
1680    INITIAL_ELIMINATION_OFFSET.  */
1681 
1682 void
1683 m88k_layout_frame ()
1684 {
1685   int regno, sp_size;
1686 
1687   if (frame_laid_out && reload_completed)
1688     return;
1689 
1690   frame_laid_out = 1;
1691 
1692   memset ((char *) &save_regs[0], 0, sizeof (save_regs));
1693   sp_size = nregs = nxregs = 0;
1694   frame_size = get_frame_size ();
1695 
1696   /* Profiling requires a stack frame.  */
1697   if (current_function_profile)
1698     frame_pointer_needed = 1;
1699 
1700   /* If we are producing debug information, store r1 and r30 where the
1701      debugger wants to find them (r30 at r30+0, r1 at r30+4).  Space has
1702      already been reserved for r1/r30 in STARTING_FRAME_OFFSET.  */
1703   if (write_symbols != NO_DEBUG)
1704     save_regs[1] = 1;
1705 
1706   /* If we are producing PIC, save the addressing base register and r1.  */
1707   if (flag_pic && current_function_uses_pic_offset_table)
1708     {
1709       save_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
1710       nregs++;
1711     }
1712 
1713   /* If a frame is requested, save the previous FP, and the return
1714      address (r1), so that a traceback can be done without using tdesc
1715      information.  Otherwise, simply save the FP if it is used as
1716      a preserve register.  */
1717   if (frame_pointer_needed)
1718     save_regs[FRAME_POINTER_REGNUM] = save_regs[1] = 1;
1719   else
1720     {
1721       if (regs_ever_live[FRAME_POINTER_REGNUM])
1722 	save_regs[FRAME_POINTER_REGNUM] = 1;
1723       /* If there is a call, r1 needs to be saved as well.  */
1724       if (regs_ever_live[1])
1725 	save_regs[1] = 1;
1726     }
1727 
1728   /* Figure out which extended register(s) needs to be saved.  */
1729   for (regno = FIRST_EXTENDED_REGISTER + 1; regno < FIRST_PSEUDO_REGISTER;
1730        regno++)
1731     if (regs_ever_live[regno] && ! call_used_regs[regno])
1732       {
1733 	save_regs[regno] = 1;
1734 	nxregs++;
1735       }
1736 
1737   /* Figure out which normal register(s) needs to be saved.  */
1738   for (regno = 2; regno < FRAME_POINTER_REGNUM; regno++)
1739     if (regs_ever_live[regno] && ! call_used_regs[regno])
1740       {
1741 	save_regs[regno] = 1;
1742 	nregs++;
1743       }
1744 
1745   /* Achieve greatest use of double memory ops.  Either we end up saving
1746      r30 or we use that slot to align the registers we do save.  */
1747   if (nregs >= 2 && save_regs[1] && !save_regs[FRAME_POINTER_REGNUM])
1748     sp_size += 4;
1749 
1750   nregs += save_regs[1] + save_regs[FRAME_POINTER_REGNUM];
1751   /* if we need to align extended registers, add a word */
1752   if (nxregs > 0 && (nregs & 1) != 0)
1753     sp_size +=4;
1754   sp_size += 4 * nregs;
1755   sp_size += 8 * nxregs;
1756   sp_size += current_function_outgoing_args_size;
1757 
1758   /* The first two saved registers are placed above the new frame pointer
1759      if any.  In the only case this matters, they are r1 and r30. */
1760   if (frame_pointer_needed || sp_size)
1761     m88k_fp_offset = ROUND_CALL_BLOCK_SIZE (sp_size - STARTING_FRAME_OFFSET);
1762   else
1763     m88k_fp_offset = -STARTING_FRAME_OFFSET;
1764   m88k_stack_size = m88k_fp_offset + STARTING_FRAME_OFFSET;
1765 
1766   /* First, combine m88k_stack_size and size.  If m88k_stack_size is
1767      nonzero, align the frame size to 8 mod 16; otherwise align the
1768      frame size to 0 mod 16.  (If stacks are 8 byte aligned, this ends
1769      up as a NOP.  */
1770   {
1771     int need
1772       = ((m88k_stack_size ? STACK_UNIT_BOUNDARY - STARTING_FRAME_OFFSET : 0)
1773 	 - (frame_size % STACK_UNIT_BOUNDARY));
1774     if (need < 0)
1775       need += STACK_UNIT_BOUNDARY;
1776     m88k_stack_size
1777       = ROUND_CALL_BLOCK_SIZE (m88k_stack_size + frame_size + need
1778 			       + current_function_pretend_args_size);
1779   }
1780 }
1781 
1782 /* Return true if this function is known to have a null prologue.  */
1783 
1784 int
1785 null_prologue ()
1786 {
1787   if (! reload_completed)
1788     return 0;
1789   m88k_layout_frame ();
1790   return (! frame_pointer_needed
1791 	  && nregs == 0
1792 	  && nxregs == 0
1793 	  && m88k_stack_size == 0);
1794 }
1795 
1796 /* Add to 'insn' a note which is PATTERN (INSN) but with REG replaced
1797    with (plus:P (reg 31) VAL).  It would be nice if dwarf2out_frame_debug_expr
1798    could deduce these equivalences by itself so it wasn't necessary to hold
1799    its hand so much.  */
1800 
1801 static void
1802 m88k_frame_related (insn, reg, val)
1803      rtx insn;
1804      rtx reg;
1805      HOST_WIDE_INT val;
1806 {
1807   rtx real, temp;
1808 
1809   real = copy_rtx (PATTERN (insn));
1810 
1811   real = replace_rtx (real, reg,
1812 		      gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode,
1813 							STACK_POINTER_REGNUM),
1814 				    GEN_INT (val)));
1815 
1816   /* We expect that 'real' is a SET.  */
1817 
1818   if (GET_CODE (real) == SET)
1819     {
1820       rtx set = real;
1821 
1822       temp = simplify_rtx (SET_SRC (set));
1823       if (temp)
1824 	SET_SRC (set) = temp;
1825       temp = simplify_rtx (SET_DEST (set));
1826       if (temp)
1827 	SET_DEST (set) = temp;
1828       if (GET_CODE (SET_DEST (set)) == MEM)
1829 	{
1830 	  temp = simplify_rtx (XEXP (SET_DEST (set), 0));
1831 	  if (temp)
1832 	    XEXP (SET_DEST (set), 0) = temp;
1833 	}
1834     }
1835   else
1836     abort ();
1837 
1838   RTX_FRAME_RELATED_P (insn) = 1;
1839   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
1840 					real,
1841 					REG_NOTES (insn));
1842 }
1843 
1844 static void
1845 m88k_maybe_dead (insn)
1846      rtx insn;
1847 {
1848   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
1849 					const0_rtx,
1850 					REG_NOTES (insn));
1851 }
1852 
1853 void
1854 m88k_expand_prologue ()
1855 {
1856   rtx insn;
1857 
1858   m88k_layout_frame ();
1859 
1860   if (warn_stack_larger_than && m88k_stack_size > stack_larger_than_size)
1861     warning ("stack usage is %d bytes", m88k_stack_size);
1862 
1863   if (m88k_stack_size)
1864     {
1865       insn = emit_add (stack_pointer_rtx, stack_pointer_rtx, -m88k_stack_size);
1866       RTX_FRAME_RELATED_P (insn) = 1;
1867 
1868       /* If the stack pointer adjustment has required a temporary register,
1869 	 tell the DWARF code how to understand this sequence.  */
1870       if (! SMALL_INTVAL (m88k_stack_size))
1871 	REG_NOTES (insn)
1872 	  = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
1873 			       gen_rtx_SET (VOIDmode, stack_pointer_rtx,
1874 				     gen_rtx_PLUS (Pmode, stack_pointer_rtx,
1875 						   GEN_INT (-m88k_stack_size))),
1876 			       REG_NOTES(insn));
1877     }
1878 
1879   if (nregs || nxregs)
1880     preserve_registers (m88k_fp_offset + 4, 1);
1881 
1882   if (frame_pointer_needed)
1883     {
1884       insn = emit_add (frame_pointer_rtx, stack_pointer_rtx, m88k_fp_offset);
1885       RTX_FRAME_RELATED_P (insn) = 1;
1886     }
1887 
1888   if (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM])
1889     {
1890       rtx return_reg = gen_rtx_REG (SImode, 1);
1891       rtx label = gen_label_rtx ();
1892 #if 0
1893       rtx temp_reg = NULL_RTX;
1894       int save_r1 = regs_ever_live[1];
1895 
1896       if (save_r1)
1897 	{
1898 	  temp_reg = gen_rtx_REG (SImode, TEMP_REGNUM);
1899 	  emit_move_insn (temp_reg, return_reg);
1900 	}
1901 #endif
1902 
1903       m88k_maybe_dead (emit_insn (gen_locate1 (pic_offset_table_rtx, label)));
1904       m88k_maybe_dead (emit_insn (gen_locate2 (pic_offset_table_rtx, label)));
1905       m88k_maybe_dead (emit_insn (gen_addsi3 (pic_offset_table_rtx,
1906 					      pic_offset_table_rtx,
1907 					      return_reg)));
1908 
1909 #if 0
1910       if (save_r1)
1911 	emit_move_insn (return_reg, temp_reg);
1912 #endif
1913     }
1914   if (current_function_profile)
1915     emit_insn (gen_blockage ());
1916 }
1917 
1918 /* This function generates the assembly code for function exit,
1919    on machines that need it.
1920 
1921    The function epilogue should not depend on the current stack pointer!
1922    It should use the frame pointer only, if there is a frame pointer.
1923    This is mandatory because of alloca; we also take advantage of it to
1924    omit stack adjustments before returning.  */
1925 
1926 static void
1927 m88k_output_function_epilogue (stream, size)
1928      FILE *stream;
1929      HOST_WIDE_INT size ATTRIBUTE_UNUSED;
1930 {
1931   rtx insn = get_last_insn ();
1932 
1933   /* If the last insn isn't a BARRIER, we must write a return insn.  This
1934      should only happen if the function has no prologue and no body.  */
1935   if (GET_CODE (insn) == NOTE)
1936     insn = prev_nonnote_insn (insn);
1937   if (insn == 0 || GET_CODE (insn) != BARRIER)
1938     asm_fprintf (stream, "\tjmp\t %R%s\n", reg_names[1]);
1939 
1940   /* If the last insn is a barrier, and the insn before that is a call,
1941      then add a nop instruction so that tdesc can walk the stack correctly
1942      even though there is no epilogue. (Otherwise, the label for the
1943      end of the tdesc region ends up at the start of the next function. */
1944   if (insn && GET_CODE (insn) == BARRIER)
1945     {
1946       insn = prev_nonnote_insn (insn);
1947       if (insn && GET_CODE (insn) == CALL_INSN)
1948         asm_fprintf (stream, "\tor\t %R%s,%R%s,%R%s\n",
1949 		     reg_names[0], reg_names[0], reg_names[0]);
1950     }
1951 
1952   output_short_branch_defs (stream);
1953 
1954   fprintf (stream, "\n");
1955 
1956   frame_laid_out	= 0;
1957 }
1958 
1959 void
1960 m88k_expand_epilogue ()
1961 {
1962   if (frame_pointer_needed)
1963     emit_add (stack_pointer_rtx, frame_pointer_rtx, -m88k_fp_offset);
1964 
1965   if (nregs || nxregs)
1966     preserve_registers (m88k_fp_offset + 4, 0);
1967 
1968   if (m88k_stack_size)
1969     emit_add (stack_pointer_rtx, stack_pointer_rtx, m88k_stack_size);
1970 }
1971 
1972 /* Emit insns to set DSTREG to SRCREG + AMOUNT during the prologue or
1973    epilogue.  */
1974 
1975 static rtx
1976 emit_add (dstreg, srcreg, amount)
1977      rtx dstreg;
1978      rtx srcreg;
1979      int amount;
1980 {
1981   rtx incr = GEN_INT (abs (amount));
1982 
1983   if (! ADD_INTVAL (amount))
1984     {
1985       rtx temp = gen_rtx_REG (SImode, TEMP_REGNUM);
1986       emit_move_insn (temp, incr);
1987       incr = temp;
1988     }
1989   return emit_insn ((amount < 0 ? gen_subsi3 : gen_addsi3) (dstreg, srcreg,
1990 							    incr));
1991 }
1992 
1993 /* Save/restore the preserve registers.  base is the highest offset from
1994    r31 at which a register is stored.  store_p is true if stores are to
1995    be done; otherwise loads.  */
1996 
1997 static void
1998 preserve_registers (base, store_p)
1999      int base;
2000      int store_p;
2001 {
2002   int regno, offset;
2003   struct mem_op {
2004     int regno;
2005     int nregs;
2006     int offset;
2007   } mem_op[FIRST_PSEUDO_REGISTER];
2008   struct mem_op *mo_ptr = mem_op;
2009 
2010   /* The 88open OCS mandates that preserved registers be stored in
2011      increasing order.  For compatibility with current practice,
2012      the order is r1, r30, then the preserve registers.  */
2013 
2014   offset = base;
2015   if (save_regs[1])
2016     {
2017       /* An extra word is given in this case to make best use of double
2018 	 memory ops.  */
2019       if (nregs > 2 && !save_regs[FRAME_POINTER_REGNUM])
2020 	offset -= 4;
2021       /* Do not reload r1 in the epilogue unless really necessary */
2022       if (store_p || regs_ever_live[1]
2023 	  || (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM]))
2024 	emit_ldst (store_p, 1, SImode, offset);
2025       offset -= 4;
2026       base = offset;
2027     }
2028 
2029   /* Walk the registers to save recording all single memory operations.  */
2030   for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
2031     if (save_regs[regno])
2032       {
2033 	if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
2034 	  {
2035 	    mo_ptr->nregs = 1;
2036 	    mo_ptr->regno = regno;
2037 	    mo_ptr->offset = offset;
2038 	    mo_ptr++;
2039 	    offset -= 4;
2040 	  }
2041         else
2042 	  {
2043 	    regno--;
2044 	    offset -= 2*4;
2045 	  }
2046       }
2047 
2048   /* Walk the registers to save recording all double memory operations.
2049      This avoids a delay in the epilogue (ld.d/ld).  */
2050   offset = base;
2051   for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
2052     if (save_regs[regno])
2053       {
2054 	if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
2055 	  {
2056 	    offset -= 4;
2057 	  }
2058         else
2059 	  {
2060 	    mo_ptr->nregs = 2;
2061 	    mo_ptr->regno = regno-1;
2062 	    mo_ptr->offset = offset-4;
2063 	    mo_ptr++;
2064 	    regno--;
2065 	    offset -= 2*4;
2066 	  }
2067       }
2068 
2069   /* Walk the extended registers to record all memory operations.  */
2070   /*  Be sure the offset is double word aligned.  */
2071   offset = (offset - 1) & ~7;
2072   for (regno = FIRST_PSEUDO_REGISTER - 1; regno > FIRST_EXTENDED_REGISTER;
2073        regno--)
2074     if (save_regs[regno])
2075       {
2076 	mo_ptr->nregs = 2;
2077 	mo_ptr->regno = regno;
2078 	mo_ptr->offset = offset;
2079 	mo_ptr++;
2080 	offset -= 2*4;
2081       }
2082 
2083   mo_ptr->regno = 0;
2084 
2085   /* Output the memory operations.  */
2086   for (mo_ptr = mem_op; mo_ptr->regno; mo_ptr++)
2087     {
2088       if (mo_ptr->nregs)
2089 	emit_ldst (store_p, mo_ptr->regno,
2090 		   (mo_ptr->nregs > 1 ? DImode : SImode),
2091 		   mo_ptr->offset);
2092     }
2093 }
2094 
2095 static void
2096 emit_ldst (store_p, regno, mode, offset)
2097      int store_p;
2098      int regno;
2099      enum machine_mode mode;
2100      int offset;
2101 {
2102   rtx reg = gen_rtx_REG (mode, regno);
2103   rtx mem;
2104   rtx insn;
2105 
2106   if (SMALL_INTVAL (offset))
2107     {
2108       mem = gen_rtx_MEM (mode, plus_constant (stack_pointer_rtx, offset));
2109     }
2110   else
2111     {
2112       /* offset is too large for immediate index must use register */
2113 
2114       rtx disp = GEN_INT (offset);
2115       rtx temp = gen_rtx_REG (SImode, TEMP_REGNUM);
2116       rtx regi = gen_rtx_PLUS (SImode, stack_pointer_rtx, temp);
2117 
2118       emit_move_insn (temp, disp);
2119       mem = gen_rtx_MEM (mode, regi);
2120     }
2121 
2122   if (store_p)
2123     {
2124       insn = emit_move_insn (mem, reg);
2125       m88k_frame_related (insn, stack_pointer_rtx, offset);
2126     }
2127   else
2128     emit_move_insn (reg, mem);
2129 }
2130 
2131 /* Convert the address expression REG to a CFA offset.  */
2132 
2133 int
2134 m88k_debugger_offset (reg, offset)
2135      register rtx reg;
2136      register int offset;
2137 {
2138   if (GET_CODE (reg) == PLUS)
2139     {
2140       offset = INTVAL (XEXP (reg, 1));
2141       reg = XEXP (reg, 0);
2142     }
2143 
2144   /* Put the offset in terms of the CFA (arg pointer).  */
2145   if (reg == frame_pointer_rtx)
2146     offset += m88k_fp_offset - m88k_stack_size;
2147   else if (reg == stack_pointer_rtx)
2148     offset -= m88k_stack_size;
2149   else if (reg != arg_pointer_rtx)
2150     return 0;
2151 
2152   return offset;
2153 }
2154 
2155 /* Output assembler code to FILE to increment profiler label # LABELNO
2156    for profiling a function entry.  NAME is the mcount function name
2157    (varies).  */
2158 
2159 void
2160 output_function_profiler (file, labelno, name)
2161      FILE *file;
2162      int labelno;
2163      const char *name;
2164 {
2165   char label[256];
2166 
2167   /* Remember to update FUNCTION_PROFILER_LENGTH.  */
2168 
2169   asm_fprintf (file, "\tsubu\t %R%s,%R%s,32\n", reg_names[31], reg_names[31]);
2170   asm_fprintf (file, "\tst.d\t %R%s,%R%s,0\n", reg_names[2], reg_names[31]);
2171   asm_fprintf (file, "\tst.d\t %R%s,%R%s,8\n", reg_names[4], reg_names[31]);
2172   asm_fprintf (file, "\tst.d\t %R%s,%R%s,16\n", reg_names[6], reg_names[31]);
2173   asm_fprintf (file, "\tst.d\t %R%s,%R%s,24\n", reg_names[8], reg_names[31]);
2174 
2175   ASM_GENERATE_INTERNAL_LABEL (label, "LP", labelno);
2176   if (flag_pic == 2)
2177     {
2178       asm_fprintf (file, "\tor.u\t %R%s,%R%s,%Rhi16(%s#got_rel)\n",
2179 		   reg_names[2], reg_names[0], &label[1]);
2180       asm_fprintf (file, "\tor\t %R%s,%R%s,%Rlo16(%s#got_rel)\n",
2181 		   reg_names[2], reg_names[2], &label[1]);
2182       asm_fprintf (file, "\tbsr.n\t %s#plt\n", name);
2183       asm_fprintf (file, "\t ld\t %R%s,%R%s,%R%s\n", reg_names[2],
2184 		   reg_names[PIC_OFFSET_TABLE_REGNUM], reg_names[2]);
2185     }
2186   else if (flag_pic)
2187     {
2188       asm_fprintf (file, "\tbsr.n\t %s#plt\n", name);
2189       asm_fprintf (file, "\t ld\t %R%s,%R%s,%s#got_rel\n", reg_names[2],
2190 		   reg_names[PIC_OFFSET_TABLE_REGNUM], &label[1]);
2191     }
2192   else
2193     {
2194       asm_fprintf (file, "\tor.u\t %R%s,%R%s,%Rhi16(%s)\n",
2195 		   reg_names[2], reg_names[0], &label[1]);
2196       asm_fprintf (file, "\tbsr.n\t %s\n", name);
2197       asm_fprintf (file, "\t or\t %R%s,%R%s,%Rlo16(%s)\n",
2198 		   reg_names[2], reg_names[2], &label[1]);
2199     }
2200 
2201   asm_fprintf (file, "\tld.d\t %R%s,%R%s,0\n", reg_names[2], reg_names[31]);
2202   asm_fprintf (file, "\tld.d\t %R%s,%R%s,8\n", reg_names[4], reg_names[31]);
2203   asm_fprintf (file, "\tld.d\t %R%s,%R%s,16\n", reg_names[6], reg_names[31]);
2204   asm_fprintf (file, "\tld.d\t %R%s,%R%s,24\n", reg_names[8], reg_names[31]);
2205   asm_fprintf (file, "\taddu\t %R%s,%R%s,32\n", reg_names[31], reg_names[31]);
2206 }
2207 
2208 /* Determine whether a function argument is passed in a register, and
2209    which register.
2210 
2211    The arguments are CUM, which summarizes all the previous
2212    arguments; MODE, the machine mode of the argument; TYPE,
2213    the data type of the argument as a tree node or 0 if that is not known
2214    (which happens for C support library functions); and NAMED,
2215    which is 1 for an ordinary argument and 0 for nameless arguments that
2216    correspond to `...' in the called function's prototype.
2217 
2218    The value of the expression should either be a `reg' RTX for the
2219    hard register in which to pass the argument, or zero to pass the
2220    argument on the stack.
2221 
2222    On the m88000 the first eight words of args are normally in registers
2223    and the rest are pushed.  Double precision floating point must be
2224    double word aligned (and if in a register, starting on an even
2225    register). Structures and unions which are not 4 byte, and word
2226    aligned are passed in memory rather than registers, even if they
2227    would fit completely in the registers under OCS rules.
2228 
2229    Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different.
2230    For structures that are passed in memory, but could have been
2231    passed in registers, we first load the structure into the
2232    register, and then when the last argument is passed, we store
2233    the registers into the stack locations.  This fixes some bugs
2234    where GCC did not expect to have register arguments, followed
2235    by stack arguments, followed by register arguments.  */
2236 
2237 struct rtx_def *
2238 m88k_function_arg (args_so_far, mode, type, named)
2239      CUMULATIVE_ARGS args_so_far;
2240      enum machine_mode mode;
2241      tree type;
2242      int named ATTRIBUTE_UNUSED;
2243 {
2244   int bytes, words;
2245 
2246   if (type != 0 && AGGREGATE_TYPE_P (type)) /* undo putting struct in register */
2247     mode = BLKmode;
2248 
2249   if (type == 0 && mode == BLKmode)
2250     abort ();	/* m88k_function_arg argument `type' is NULL for BLKmode. */
2251 
2252   bytes = (mode != BLKmode) ? GET_MODE_SIZE (mode) : int_size_in_bytes (type);
2253 
2254   /* Variable-sized types get passed by reference, which can be passed
2255      in registers.  */
2256   if (bytes < 0)
2257     {
2258       if (args_so_far > 8 - (POINTER_SIZE / BITS_PER_WORD))
2259 	return (rtx) 0;
2260 
2261       return gen_rtx_REG (Pmode, 2 + args_so_far);
2262     }
2263 
2264   words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
2265 
2266   if ((args_so_far & 1) != 0
2267       && (mode == DImode || mode == DFmode
2268 	  || (type != 0 && TYPE_ALIGN (type) > BITS_PER_WORD)))
2269     args_so_far++;
2270 
2271   if (args_so_far + words > 8)
2272     return (rtx) 0;             /* args have exhausted registers */
2273 
2274   else if (mode == BLKmode
2275 	   && (TYPE_ALIGN (type) != BITS_PER_WORD || bytes != UNITS_PER_WORD))
2276     return (rtx) 0;
2277 
2278   return gen_rtx_REG (((mode == BLKmode) ? TYPE_MODE (type) : mode),
2279 		      2 + args_so_far);
2280 }
2281 
2282 /* Update the summarizer variable CUM to advance past an argument in
2283    the argument list.  The values MODE, TYPE and NAMED describe that
2284    argument.  Once this is done, the variable CUM is suitable for
2285    analyzing the *following* argument with `FUNCTION_ARG', etc.  (TYPE
2286    is null for libcalls where that information may not be available.)  */
2287 void
2288 m88k_function_arg_advance (args_so_far, mode, type, named)
2289      CUMULATIVE_ARGS *args_so_far;
2290      enum machine_mode mode;
2291      tree type;
2292      int named ATTRIBUTE_UNUSED;
2293 {
2294   int bytes, words;
2295   int asf;
2296 
2297   if (type != 0 && AGGREGATE_TYPE_P (type))
2298     mode = BLKmode;
2299 
2300   bytes = (mode != BLKmode) ? GET_MODE_SIZE (mode) : int_size_in_bytes (type);
2301   asf = *args_so_far;
2302 
2303   /* Variable-sized types get passed by reference, which can be passed
2304      in registers.  */
2305   if (bytes < 0)
2306     {
2307       if (asf <= 8 - (POINTER_SIZE / BITS_PER_WORD))
2308 	*args_so_far += POINTER_SIZE / BITS_PER_WORD;
2309 
2310       return;
2311     }
2312 
2313   words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
2314 
2315   /* Struct and unions which are not exactly the size of a register are to be
2316      passed on stack.  */
2317   if (mode == BLKmode
2318       && (TYPE_ALIGN (type) != BITS_PER_WORD || bytes != UNITS_PER_WORD))
2319     return;
2320 
2321   /* Align arguments requiring more than word alignment to a double-word
2322      boundary (or an even register number if the argument will get passed
2323      in registers).  */
2324   if ((asf & 1) != 0
2325       && (mode == DImode || mode == DFmode
2326 	  || (type != 0 && TYPE_ALIGN (type) > BITS_PER_WORD)))
2327     asf++;
2328 
2329   if (asf + words > 8)
2330     return;
2331 
2332   (*args_so_far) = asf + words;
2333 }
2334 
2335 /* A C expression that indicates when an argument must be passed by
2336    reference.  If nonzero for an argument, a copy of that argument is
2337    made in memory and a pointer to the argument is passed instead of
2338    the argument itself.  The pointer is passed in whatever way is
2339    appropriate for passing a pointer to that type.
2340 
2341    On m88k, only variable sized types are passed by reference.  */
2342 
2343 int
2344 m88k_function_arg_pass_by_reference (cum, mode, type, named)
2345      CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED;
2346      enum machine_mode mode ATTRIBUTE_UNUSED;
2347      tree type;
2348      int named ATTRIBUTE_UNUSED;
2349 {
2350   return type != 0 && int_size_in_bytes (type) < 0;
2351 }
2352 
2353 /* Perform any needed actions needed for a function that is receiving a
2354    variable number of arguments.
2355 
2356    CUM is a variable of type CUMULATIVE_ARGS which gives info about
2357     the preceding args and about the function being called.
2358 
2359    MODE and TYPE are the mode and type of the current parameter.
2360 
2361    PRETEND_SIZE is a variable that should be set to the amount of stack
2362    that must be pushed by the prolog to pretend that our caller pushed
2363    it.
2364 
2365    Normally, this macro will push all remaining incoming registers on the
2366    stack and set PRETEND_SIZE to the length of the registers pushed.  */
2367 
2368 void
2369 m88k_setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl)
2370      CUMULATIVE_ARGS *cum;
2371      enum machine_mode mode;
2372      tree type;
2373      int *pretend_size;
2374      int no_rtl;
2375 {
2376   CUMULATIVE_ARGS next_cum;
2377   tree fntype;
2378   int stdarg_p;
2379   int regcnt, delta;
2380 
2381   fntype = TREE_TYPE (current_function_decl);
2382   stdarg_p = (TYPE_ARG_TYPES (fntype) != 0
2383 	     && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2384 		 != void_type_node));
2385 
2386   /* For varargs, we do not want to skip the dummy va_dcl argument.
2387      For stdargs, we do want to skip the last named argument.  */
2388   next_cum = *cum;
2389   if (stdarg_p)
2390     m88k_function_arg_advance(&next_cum, mode, type, 1);
2391 
2392   regcnt = next_cum < 8 ? 8 - next_cum : 0;
2393   delta = regcnt & 1;
2394 
2395   if (! no_rtl && regcnt != 0)
2396     {
2397       rtx mem, dst;
2398       int set, regno, offs;
2399 
2400       set = get_varargs_alias_set ();
2401       mem = gen_rtx_MEM (BLKmode,
2402 			 plus_constant (virtual_incoming_args_rtx,
2403 					- (regcnt + delta) * UNITS_PER_WORD));
2404       set_mem_alias_set (mem, set);
2405 
2406       /* Now store the incoming registers.  */
2407       /* The following is equivalent to
2408 	 move_block_from_reg (2 + next_cum,
2409 			      adjust_address (mem, Pmode,
2410 					      delta * UNITS_PER_WORD),
2411 			      regcnt, UNITS_PER_WORD * regcnt);
2412 	 but using double store instruction since the stack is properly
2413 	 aligned.  */
2414       regno = 2 + next_cum;
2415       dst = mem;
2416 
2417       if (delta != 0)
2418 	{
2419 	  dst = adjust_address (dst, Pmode, UNITS_PER_WORD);
2420 	  emit_move_insn (operand_subword (dst, 0, 1, BLKmode),
2421 			  gen_rtx_REG (SImode, regno));
2422 	  regno++;
2423 	}
2424 
2425       offs = delta;
2426       while (regno < 10)
2427 	{
2428 	  emit_move_insn (adjust_address (dst, DImode, offs * UNITS_PER_WORD),
2429 			  gen_rtx_REG (DImode, regno));
2430 	  offs += 2;
2431 	  regno += 2;
2432         }
2433 
2434       *pretend_size = (regcnt + delta) * UNITS_PER_WORD;
2435     }
2436 }
2437 
2438 /* Define the `__builtin_va_list' type for the ABI.  */
2439 
2440 tree
2441 m88k_build_va_list ()
2442 {
2443   tree field_reg, field_stk, field_arg, int_ptr_type_node, record;
2444 
2445   int_ptr_type_node = build_pointer_type (integer_type_node);
2446 
2447   record = make_node (RECORD_TYPE);
2448 
2449   field_arg = build_decl (FIELD_DECL, get_identifier ("__va_arg"),
2450 			  integer_type_node);
2451   field_stk = build_decl (FIELD_DECL, get_identifier ("__va_stk"),
2452 			  int_ptr_type_node);
2453   field_reg = build_decl (FIELD_DECL, get_identifier ("__va_reg"),
2454 			  int_ptr_type_node);
2455 
2456   DECL_FIELD_CONTEXT (field_arg) = record;
2457   DECL_FIELD_CONTEXT (field_stk) = record;
2458   DECL_FIELD_CONTEXT (field_reg) = record;
2459 
2460   TYPE_FIELDS (record) = field_arg;
2461   TREE_CHAIN (field_arg) = field_stk;
2462   TREE_CHAIN (field_stk) = field_reg;
2463 
2464   layout_type (record);
2465   return record;
2466 }
2467 
2468 /* Implement `va_start' for varargs and stdarg.  */
2469 
2470 void
2471 m88k_va_start (valist, nextarg)
2472      tree valist;
2473      rtx nextarg ATTRIBUTE_UNUSED;
2474 {
2475   tree field_reg, field_stk, field_arg;
2476   tree reg, stk, arg, t;
2477   tree fntype;
2478   int stdarg_p;
2479   int offset;
2480 
2481   if (! CONSTANT_P (current_function_arg_offset_rtx))
2482     abort ();
2483 
2484   field_arg = TYPE_FIELDS (va_list_type_node);
2485   field_stk = TREE_CHAIN (field_arg);
2486   field_reg = TREE_CHAIN (field_stk);
2487 
2488   arg = build (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg);
2489   stk = build (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk);
2490   reg = build (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg);
2491 
2492   fntype = TREE_TYPE (current_function_decl);
2493   stdarg_p = (TYPE_ARG_TYPES (fntype) != 0
2494 	      && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2495 		  != void_type_node));
2496 
2497   /* Fill in the __va_arg member.  */
2498   t = build (MODIFY_EXPR, TREE_TYPE (arg), arg,
2499 	     build_int_2 (current_function_args_info, 0));
2500   TREE_SIDE_EFFECTS (t) = 1;
2501   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2502 
2503   /* Store the arg pointer in the __va_stk member.  */
2504   offset = XINT (current_function_arg_offset_rtx, 0);
2505   if (current_function_args_info >= 8 && ! stdarg_p)
2506     offset -= UNITS_PER_WORD;
2507   t = make_tree (TREE_TYPE (stk), virtual_incoming_args_rtx);
2508   t = build (PLUS_EXPR, TREE_TYPE (stk), t, build_int_2 (offset, 0));
2509   t = build (MODIFY_EXPR, TREE_TYPE (stk), stk, t);
2510   TREE_SIDE_EFFECTS (t) = 1;
2511   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2512 
2513   /* Setup __va_reg */
2514   t = make_tree (TREE_TYPE (reg), virtual_incoming_args_rtx);
2515   t = build (PLUS_EXPR, TREE_TYPE (reg), t,
2516 	     build_int_2 (-8 * UNITS_PER_WORD, -1));
2517   t = build (MODIFY_EXPR, TREE_TYPE (reg), reg, t);
2518   TREE_SIDE_EFFECTS (t) = 1;
2519   expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2520 }
2521 
2522 /* Implement `va_arg'.  */
2523 
2524 rtx
2525 m88k_va_arg (valist, type)
2526      tree valist, type;
2527 {
2528   tree field_reg, field_stk, field_arg;
2529   int indirect_p, size, wsize, align, reg_p;
2530   rtx addr_rtx;
2531   rtx lab_done;
2532 
2533   field_arg = TYPE_FIELDS (va_list_type_node);
2534   field_stk = TREE_CHAIN (field_arg);
2535   field_reg = TREE_CHAIN (field_stk);
2536 
2537   size = int_size_in_bytes (type);
2538   /* Variable sized types are passed by reference.  */
2539   if (size < 0)
2540     {
2541       indirect_p = 1;
2542       wsize = POINTER_SIZE / BITS_PER_WORD;
2543       type = 0;
2544       reg_p = 1;
2545     }
2546   else
2547     {
2548       indirect_p = 0;
2549       wsize = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
2550       reg_p = (AGGREGATE_TYPE_P (type)
2551 	       ? size == UNITS_PER_WORD && TYPE_ALIGN (type) == BITS_PER_WORD
2552 	       : size <= 2*UNITS_PER_WORD);
2553     }
2554 
2555   addr_rtx = gen_reg_rtx (Pmode);
2556   lab_done = gen_label_rtx ();
2557 
2558   /* Decide if we should read from stack or regs if the argument could have
2559      been passed in registers.  */
2560   if (reg_p) {
2561     tree arg, arg_align, reg;
2562     rtx lab_stack;
2563     tree t;
2564     rtx r;
2565 
2566     lab_stack = gen_label_rtx ();
2567 
2568     /* Align __va_arg to a doubleword boundary if necessary.  */
2569     arg = build (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg);
2570     align = type == 0 ? 0 : TYPE_ALIGN (type) / BITS_PER_WORD;
2571     if (align > 1)
2572       {
2573 	t = build (PLUS_EXPR, TREE_TYPE (arg), arg, build_int_2 (align - 1, 0));
2574 	arg_align = build (BIT_AND_EXPR, TREE_TYPE (t), t,
2575 			   build_int_2 (-align, -1));
2576 	arg_align = save_expr (arg_align);
2577       }
2578     else
2579       arg_align = arg;
2580 
2581     /* Make sure the argument fits within the remainder of the saved
2582        register area, and branch to the stack logic if not.  */
2583     r = expand_expr (arg_align, NULL_RTX, TYPE_MODE (TREE_TYPE (arg_align)),
2584 		     EXPAND_NORMAL);
2585     /* if (arg_align > 8 - wsize) goto lab_stack */
2586     emit_cmp_and_jump_insns (r, GEN_INT (8 - wsize), GTU,
2587 			     GEN_INT (UNITS_PER_WORD), GET_MODE (r), 1,
2588 			     lab_stack);
2589 
2590     /* Compute the argument address.  */
2591     reg = build (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg);
2592     t = build (MULT_EXPR, TREE_TYPE (reg), arg_align,
2593 	       build_int_2 (UNITS_PER_WORD, 0));
2594     t = build (PLUS_EXPR, TREE_TYPE (reg), reg, t);
2595     TREE_SIDE_EFFECTS (t) = 1;
2596 
2597     r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
2598     if (r != addr_rtx)
2599       emit_move_insn (addr_rtx, r);
2600 
2601     /* Increment __va_arg.  */
2602     t = build (PLUS_EXPR, TREE_TYPE (arg), arg_align, build_int_2 (wsize, 0));
2603     t = build (MODIFY_EXPR, TREE_TYPE (arg), arg, t);
2604     TREE_SIDE_EFFECTS (t) = 1;
2605     expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2606 
2607     emit_jump_insn (gen_jump (lab_done));
2608     emit_barrier ();
2609 
2610     emit_label (lab_stack);
2611   }
2612 
2613   {
2614     tree stk;
2615     tree t;
2616     rtx r;
2617 
2618     stk = build (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk);
2619 
2620     /* Align __va_stk to the type boundary if necessary.  */
2621     align = type == 0 ? 0 : TYPE_ALIGN (type) / BITS_PER_UNIT;
2622     if (align > UNITS_PER_WORD)
2623       {
2624         t = build (PLUS_EXPR, TREE_TYPE (stk), stk, build_int_2 (align - 1, 0));
2625         t = build (BIT_AND_EXPR, TREE_TYPE (t), t, build_int_2 (-align, -1));
2626 	TREE_SIDE_EFFECTS (t) = 1;
2627       }
2628     else
2629       t = stk;
2630 
2631     /* Compute the argument address.  */
2632     r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
2633     if (r != addr_rtx)
2634       emit_move_insn (addr_rtx, r);
2635 
2636     /* Increment __va_stk.  */
2637     t = build (PLUS_EXPR, TREE_TYPE (t), t,
2638 	       build_int_2 (wsize * UNITS_PER_WORD, 0));
2639     t = build (MODIFY_EXPR, TREE_TYPE (stk), stk, t);
2640     TREE_SIDE_EFFECTS (t) = 1;
2641     expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2642   }
2643 
2644   emit_label (lab_done);
2645 
2646   if (indirect_p)
2647     {
2648       rtx r = gen_rtx_MEM (Pmode, addr_rtx);
2649       set_mem_alias_set (r, get_varargs_alias_set ());
2650       emit_move_insn (addr_rtx, r);
2651     }
2652 
2653   return addr_rtx;
2654 }
2655 
2656 /* If cmpsi has not been generated, emit code to do the test.  Return the
2657    expression describing the test of operator OP.  */
2658 
2659 rtx
2660 emit_test (op, mode)
2661      enum rtx_code op;
2662      enum machine_mode mode;
2663 {
2664   if (m88k_compare_reg == 0)
2665     emit_insn (gen_test (m88k_compare_op0, m88k_compare_op1));
2666   return (gen_rtx (op, mode, m88k_compare_reg, const0_rtx));
2667 }
2668 
2669 /* Determine how to best perform cmpsi/bxx, where cmpsi has a constant
2670    operand.  All tests with zero (albeit swapped) and all equality tests
2671    with a constant are done with bcnd.  The remaining cases are swapped
2672    as needed.  */
2673 
2674 void
2675 emit_bcnd (op, label)
2676      enum rtx_code op;
2677      rtx label;
2678 {
2679   if (m88k_compare_op1 == const0_rtx)
2680     emit_jump_insn (gen_bcnd
2681 		    (gen_rtx (op, VOIDmode,m88k_compare_op0, const0_rtx),
2682 		     label));
2683   else if (m88k_compare_op0 == const0_rtx)
2684     emit_jump_insn (gen_bcnd
2685 		    (gen_rtx (swap_condition (op),
2686 			      VOIDmode, m88k_compare_op1, const0_rtx),
2687 		     label));
2688   else if (op != EQ && op != NE)
2689     emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2690   else
2691     {
2692       rtx zero = gen_reg_rtx (SImode);
2693       rtx reg, constant;
2694       int value;
2695 
2696       if (GET_CODE (m88k_compare_op1) == CONST_INT)
2697 	{
2698 	  reg = force_reg (SImode, m88k_compare_op0);
2699 	  constant = m88k_compare_op1;
2700 	}
2701       else
2702 	{
2703 	  reg = force_reg (SImode, m88k_compare_op1);
2704 	  constant = m88k_compare_op0;
2705 	}
2706       value = INTVAL (constant);
2707 
2708       /* Perform an arithmetic computation to make the compared-to value
2709 	 zero, but avoid loosing if the bcnd is later changed into sxx.  */
2710       if (SMALL_INTVAL (value))
2711 	emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2712       else
2713 	{
2714 	  if (SMALL_INTVAL (-value))
2715 	    emit_insn (gen_addsi3 (zero, reg,
2716 				   GEN_INT (-value)));
2717 	  else
2718 	    emit_insn (gen_xorsi3 (zero, reg, constant));
2719 
2720 	  emit_jump_insn (gen_bcnd (gen_rtx (op, VOIDmode,
2721 					     zero, const0_rtx),
2722 				    label));
2723 	}
2724     }
2725 }
2726 
2727 /* Print an operand.  Recognize special options, documented below.  */
2728 
2729 void
2730 print_operand (file, x, code)
2731     FILE *file;
2732     rtx x;
2733     int code;
2734 {
2735   enum rtx_code xc = (x ? GET_CODE (x) : UNKNOWN);
2736   register int value = (xc == CONST_INT ? INTVAL (x) : 0);
2737   static int sequencep;
2738   static int reversep;
2739 
2740   if (sequencep)
2741     {
2742       if (code < 'B' || code > 'E')
2743 	output_operand_lossage ("%%R not followed by %%B/C/D/E");
2744       if (reversep)
2745 	xc = reverse_condition (xc);
2746       sequencep = 0;
2747     }
2748 
2749   switch (code)
2750     {
2751     case '#': /* register prefix character (may be empty) */
2752       fputs (m88k_register_prefix, file);
2753       return;
2754 
2755     case 'V': /* Output a serializing instruction as needed if the operand
2756 		 (assumed to be a MEM) is a volatile load.  */
2757     case 'v': /* ditto for a volatile store.  */
2758       if (MEM_VOLATILE_P (x) && TARGET_SERIALIZE_VOLATILE)
2759 	{
2760 	  /* The m88110 implements two FIFO queues, one for loads and
2761 	     one for stores.  These queues mean that loads complete in
2762 	     their issue order as do stores.  An interaction between the
2763 	     history buffer and the store reservation station ensures
2764 	     that a store will not bypass load.  Finally, a load will not
2765 	     bypass store, but only when they reference the same address.
2766 
2767 	     To avoid this reordering (a load bypassing a store) for
2768 	     volatile references, a serializing instruction is output.
2769 	     We choose the fldcr instruction as it does not serialize on
2770 	     the m88100 so that -m88000 code will not be degraded.
2771 
2772 	     The mechanism below is completed by having CC_STATUS_INIT set
2773 	     the code to the unknown value.  */
2774 
2775 	  /*
2776 	     hassey 6/30/93
2777 	     A problem with 88110 4.1 & 4.2 makes the use of fldcr for
2778 	     this purpose undesirable.  Instead we will use tb1, this will
2779 	     cause serialization on the 88100 but such is life.
2780 	  */
2781 
2782 	  static rtx last_addr = 0;
2783 	  if (code == 'V' /* Only need to serialize before a load.  */
2784 	      && m88k_volatile_code != 'V' /* Loads complete in FIFO order.  */
2785 	      && !(m88k_volatile_code == 'v'
2786 		   && GET_CODE (XEXP (x, 0)) == LO_SUM
2787 		   && rtx_equal_p (XEXP (XEXP (x, 0), 1), last_addr)))
2788 	    asm_fprintf (file,
2789 #if 0
2790 #ifdef AS_BUG_FLDCR
2791 			 "fldcr\t %R%s,%Rcr63\n\t",
2792 #else
2793 			 "fldcr\t %R%s,%Rfcr63\n\t",
2794 #endif
2795 			 reg_names[0]);
2796 #else /* 0 */
2797 			 "tb1\t 1,%R%s,0xff\n\t", reg_names[0]);
2798 #endif /* 0 */
2799 	  m88k_volatile_code = code;
2800 	  last_addr = (GET_CODE (XEXP (x, 0)) == LO_SUM
2801 		       ? XEXP (XEXP (x, 0), 1) : 0);
2802 	}
2803       return;
2804 
2805     case 'X': /* print the upper 16 bits... */
2806       value >>= 16;
2807     case 'x': /* print the lower 16 bits of the integer constant in hex */
2808       if (xc != CONST_INT)
2809 	output_operand_lossage ("invalid %%x/X value");
2810       fprintf (file, "0x%x", value & 0xffff); return;
2811 
2812     case 'H': /* print the low 16 bits of the negated integer constant */
2813       if (xc != CONST_INT)
2814 	output_operand_lossage ("invalid %%H value");
2815       value = -value;
2816     case 'h': /* print the register or low 16 bits of the integer constant */
2817       if (xc == REG)
2818 	goto reg;
2819       if (xc != CONST_INT)
2820 	output_operand_lossage ("invalid %%h value");
2821       fprintf (file, "%d", value & 0xffff);
2822       return;
2823 
2824     case 'Q': /* print the low 8 bits of the negated integer constant */
2825       if (xc != CONST_INT)
2826 	output_operand_lossage ("invalid %%Q value");
2827       value = -value;
2828     case 'q': /* print the register or low 8 bits of the integer constant */
2829       if (xc == REG)
2830 	goto reg;
2831       if (xc != CONST_INT)
2832 	output_operand_lossage ("invalid %%q value");
2833       fprintf (file, "%d", value & 0xff);
2834       return;
2835 
2836     case 'p': /* print the logarithm of the integer constant */
2837       if (xc != CONST_INT
2838 	  || (value = exact_log2 (value)) < 0)
2839 	output_operand_lossage ("invalid %%p value");
2840       fprintf (file, "%d", value);
2841       return;
2842 
2843     case 'S': /* complement the value and then... */
2844       value = ~value;
2845     case 's': /* print the width and offset values forming the integer
2846 		 constant with a SET instruction.  See integer_ok_for_set. */
2847       {
2848 	register unsigned mask, uval = value;
2849 	register int top, bottom;
2850 
2851 	if (xc != CONST_INT)
2852 	  output_operand_lossage ("invalid %%s/S value");
2853 	/* All the "one" bits must be contiguous.  If so, MASK will be
2854 	   a power of two or zero.  */
2855 	mask = (uval | (uval - 1)) + 1;
2856 	if (!(uval && POWER_OF_2_or_0 (mask)))
2857 	  output_operand_lossage ("invalid %%s/S value");
2858 	top = mask ? exact_log2 (mask) : 32;
2859 	bottom = exact_log2 (uval & ~(uval - 1));
2860 	fprintf (file,"%d<%d>", top - bottom, bottom);
2861 	return;
2862       }
2863 
2864     case 'P': /* print nothing if pc_rtx; output label_ref */
2865       if (xc == LABEL_REF)
2866 	output_addr_const (file, x);
2867       else if (xc != PC)
2868 	output_operand_lossage ("invalid %%P operand");
2869       return;
2870 
2871     case 'L': /* print 0 or 1 if operand is label_ref and then...  */
2872       fputc (xc == LABEL_REF ? '1' : '0', file);
2873     case '.': /* print .n if delay slot is used */
2874       fputs ((final_sequence
2875 	      && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
2876 	     ? ".n\t" : "\t", file);
2877       return;
2878 
2879     case '!': /* Reverse the following condition. */
2880       sequencep++;
2881       reversep = 1;
2882       return;
2883     case 'R': /* reverse the condition of the next print_operand
2884 		 if operand is a label_ref.  */
2885       sequencep++;
2886       reversep = (xc == LABEL_REF);
2887       return;
2888 
2889     case 'B': /* bcnd branch values */
2890       if (0) /* SVR4 */
2891 	fputs (m88k_register_prefix, file);
2892       switch (xc)
2893 	{
2894 	case EQ: fputs ("eq0", file); return;
2895 	case NE: fputs ("ne0", file); return;
2896 	case GT: fputs ("gt0", file); return;
2897 	case LE: fputs ("le0", file); return;
2898 	case LT: fputs ("lt0", file); return;
2899 	case GE: fputs ("ge0", file); return;
2900 	default: output_operand_lossage ("invalid %%B value");
2901 	}
2902 
2903     case 'C': /* bb0/bb1 branch values for comparisons */
2904       if (0) /* SVR4 */
2905 	fputs (m88k_register_prefix, file);
2906       switch (xc)
2907 	{
2908 	case EQ:  fputs ("eq", file); return;
2909 	case NE:  fputs ("ne", file); return;
2910 	case GT:  fputs ("gt", file); return;
2911 	case LE:  fputs ("le", file); return;
2912 	case LT:  fputs ("lt", file); return;
2913 	case GE:  fputs ("ge", file); return;
2914 	case GTU: fputs ("hi", file); return;
2915 	case LEU: fputs ("ls", file); return;
2916 	case LTU: fputs ("lo", file); return;
2917 	case GEU: fputs ("hs", file); return;
2918 	default:  output_operand_lossage ("invalid %%C value");
2919 	}
2920 
2921     case 'D': /* bcnd branch values for float comparisons */
2922       switch (xc)
2923 	{
2924 	case EQ: fputs ("0xa", file); return;
2925 	case NE: fputs ("0x5", file); return;
2926 	case GT:
2927 	  if (0) /* SVR4 */
2928 	    fputs (m88k_register_prefix, file);
2929 	  fputs ("gt0", file);
2930 	  return;
2931 	case LE:
2932 	  if (0) /* SVR4 */
2933 	    fputs (m88k_register_prefix, file);
2934 	  fputs ("le0", file);
2935 	  return;
2936 	case LT: fputs ("0x4", file); return;
2937 	case GE: fputs ("0xb", file); return;
2938 	default: output_operand_lossage ("invalid %%D value");
2939 	}
2940 
2941     case 'E': /* bcnd branch values for special integers */
2942       switch (xc)
2943 	{
2944 	case EQ: fputs ("0x8", file); return;
2945 	case NE: fputs ("0x7", file); return;
2946 	default: output_operand_lossage ("invalid %%E value");
2947 	}
2948 
2949     case 'd': /* second register of a two register pair */
2950       if (xc != REG)
2951 	output_operand_lossage ("`%%d' operand isn't a register");
2952       asm_fprintf (file, "%R%s", reg_names[REGNO (x) + 1]);
2953       return;
2954 
2955     case 'r': /* an immediate 0 should be represented as `r0' */
2956       if (x == const0_rtx)
2957 	{
2958 	  asm_fprintf (file, "%R%s", reg_names[0]);
2959 	  return;
2960 	}
2961       else if (xc != REG)
2962 	output_operand_lossage ("invalid %%r value");
2963     case 0:
2964     name:
2965       if (xc == REG)
2966 	{
2967 	reg:
2968 	  if (REGNO (x) == ARG_POINTER_REGNUM)
2969 	    output_operand_lossage ("operand is r0");
2970 	  else
2971 	    asm_fprintf (file, "%R%s", reg_names[REGNO (x)]);
2972 	}
2973       else if (xc == PLUS)
2974 	output_address (x);
2975       else if (xc == MEM)
2976 	output_address (XEXP (x, 0));
2977       else if (flag_pic && xc == UNSPEC)
2978 	{
2979 	  output_addr_const (file, XVECEXP (x, 0, 0));
2980 	  fputs ("#got_rel", file);
2981 	}
2982       else if (xc == CONST_DOUBLE)
2983 	output_operand_lossage ("operand is const_double");
2984       else
2985 	output_addr_const (file, x);
2986       return;
2987 
2988     case 'g': /* append #got_rel as needed */
2989       if (flag_pic && (xc == SYMBOL_REF || xc == LABEL_REF))
2990 	{
2991 	  output_addr_const (file, x);
2992 	  fputs ("#got_rel", file);
2993 	  return;
2994 	}
2995       goto name;
2996 
2997     case 'a': /* (standard), assume operand is an address */
2998     case 'c': /* (standard), assume operand is an immediate value */
2999     case 'l': /* (standard), assume operand is a label_ref */
3000     case 'n': /* (standard), like %c, except negate first */
3001     default:
3002       output_operand_lossage ("invalid code");
3003     }
3004 }
3005 
3006 void
3007 print_operand_address (file, addr)
3008     FILE *file;
3009     rtx addr;
3010 {
3011   register rtx reg0, reg1;
3012 
3013   switch (GET_CODE (addr))
3014     {
3015     case REG:
3016       if (REGNO (addr) == ARG_POINTER_REGNUM)
3017 	abort ();
3018       else
3019 	asm_fprintf (file, "%R%s,%R%s", reg_names[0], reg_names [REGNO (addr)]);
3020       break;
3021 
3022     case LO_SUM:
3023       asm_fprintf (file, "%R%s,%Rlo16(",
3024 		   reg_names[REGNO (XEXP (addr, 0))]);
3025       output_addr_const (file, XEXP (addr, 1));
3026       fputc (')', file);
3027       break;
3028 
3029     case PLUS:
3030       reg0 = XEXP (addr, 0);
3031       reg1 = XEXP (addr, 1);
3032       if (GET_CODE (reg0) == MULT || GET_CODE (reg0) == CONST_INT)
3033 	{
3034 	  rtx tmp = reg0;
3035 	  reg0 = reg1;
3036 	  reg1 = tmp;
3037 	}
3038 
3039       if ((REG_P (reg0) && REGNO (reg0) == ARG_POINTER_REGNUM)
3040 	  || (REG_P (reg1) && REGNO (reg1) == ARG_POINTER_REGNUM))
3041 	abort ();
3042 
3043       else if (REG_P (reg0))
3044 	{
3045 	  if (REG_P (reg1))
3046 	    asm_fprintf (file, "%R%s,%R%s",
3047 			 reg_names [REGNO (reg0)], reg_names [REGNO (reg1)]);
3048 
3049 	  else if (GET_CODE (reg1) == CONST_INT)
3050 	    asm_fprintf (file, "%R%s,%d",
3051 			 reg_names [REGNO (reg0)], INTVAL (reg1));
3052 
3053 	  else if (GET_CODE (reg1) == MULT)
3054 	    {
3055 	      rtx mreg = XEXP (reg1, 0);
3056 	      if (REGNO (mreg) == ARG_POINTER_REGNUM)
3057 		abort ();
3058 
3059 	      asm_fprintf (file, "%R%s[%R%s]", reg_names[REGNO (reg0)],
3060 			   reg_names[REGNO (mreg)]);
3061 	    }
3062 
3063 	  else if (GET_CODE (reg1) == ZERO_EXTRACT)
3064 	    {
3065 	      asm_fprintf (file, "%R%s,%Rlo16(",
3066 			   reg_names[REGNO (reg0)]);
3067 	      output_addr_const (file, XEXP (reg1, 0));
3068 	      fputc (')', file);
3069 	    }
3070 
3071 	  else if (flag_pic)
3072 	    {
3073 	      asm_fprintf (file, "%R%s,", reg_names[REGNO (reg0)]);
3074 	      output_addr_const (file, reg1);
3075 	      fputs ("#got_rel", file);
3076 	    }
3077 	  else abort ();
3078 	}
3079 
3080       else
3081 	abort ();
3082       break;
3083 
3084     case MULT:
3085       if (REGNO (XEXP (addr, 0)) == ARG_POINTER_REGNUM)
3086 	abort ();
3087 
3088       asm_fprintf (file, "%R%s[%R%s]",
3089 		   reg_names[0], reg_names[REGNO (XEXP (addr, 0))]);
3090       break;
3091 
3092     case CONST_INT:
3093       asm_fprintf (file, "%R%s,%d", reg_names[0], INTVAL (addr));
3094       break;
3095 
3096     default:
3097       asm_fprintf (file, "%R%s,", reg_names[0]);
3098       output_addr_const (file, addr);
3099     }
3100 }
3101 
3102 /* Return true if X is an address which needs a temporary register when
3103    reloaded while generating PIC code.  */
3104 
3105 int
3106 pic_address_needs_scratch (x)
3107      rtx x;
3108 {
3109   /* An address which is a symbolic plus a non SMALL_INT needs a temp reg.  */
3110   if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
3111       && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
3112       && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
3113       && ! ADD_INT (XEXP (XEXP (x, 0), 1)))
3114     return 1;
3115 
3116   return 0;
3117 }
3118 
3119 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
3120    reference and a constant.  */
3121 
3122 int
3123 symbolic_operand (op, mode)
3124      register rtx op;
3125      enum machine_mode mode;
3126 {
3127   switch (GET_CODE (op))
3128     {
3129     case SYMBOL_REF:
3130     case LABEL_REF:
3131       return 1;
3132 
3133     case CONST:
3134       op = XEXP (op, 0);
3135       return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
3136                || GET_CODE (XEXP (op, 0)) == LABEL_REF)
3137               && GET_CODE (XEXP (op, 1)) == CONST_INT);
3138 
3139       /* ??? This clause seems to be irrelevant.  */
3140     case CONST_DOUBLE:
3141       return GET_MODE (op) == mode;
3142 
3143     default:
3144       return 0;
3145     }
3146 }
3147 
3148 /* Adjust the cost of INSN based on the relationship between INSN that
3149    is dependent on DEP_INSN through the dependence LINK.  The default
3150    is to make no adjustment to COST.
3151 
3152    On the m88k, ignore the cost of anti- and output-dependencies.  On
3153    the m88100, a store can issue two cycles before the value (not the
3154    address) has finished computing.  */
3155 
3156 static int
3157 m88k_adjust_cost (insn, link, dep, cost)
3158      rtx insn;
3159      rtx link;
3160      rtx dep;
3161      int cost;
3162 {
3163   if (REG_NOTE_KIND (link) != 0)
3164     return 0;  /* Anti or output dependence.  */
3165 
3166   if (! TARGET_88100
3167       && recog_memoized (insn) >= 0
3168       && get_attr_type (insn) == TYPE_STORE
3169       && SET_SRC (PATTERN (insn)) == SET_DEST (PATTERN (dep)))
3170     return cost - 4;  /* 88110 store reservation station.  */
3171 
3172   return cost;
3173 }
3174 
3175 void
3176 m88k_override_options ()
3177 {
3178   if ((target_flags & MASK_88000) == 0)
3179     target_flags |= CPU_DEFAULT;
3180 
3181   if (TARGET_88110)
3182     {
3183       target_flags |= MASK_USE_DIV;
3184       target_flags &= ~MASK_CHECK_ZERO_DIV;
3185     }
3186 
3187   m88k_cpu = (TARGET_88000 ? PROCESSOR_M88000
3188 	      : (TARGET_88100 ? PROCESSOR_M88100 : PROCESSOR_M88110));
3189 
3190   if ((target_flags & MASK_EITHER_LARGE_SHIFT) == MASK_EITHER_LARGE_SHIFT)
3191     error ("-mtrap-large-shift and -mhandle-large-shift are incompatible");
3192 
3193   if (TARGET_OMIT_LEAF_FRAME_POINTER)	/* keep nonleaf frame pointers */
3194     flag_omit_frame_pointer = 1;
3195 
3196   /* On the m88100, it is desirable to align functions to a cache line.
3197      The m88110 cache is small, so align to an 8 byte boundary.  */
3198   if (align_functions == 0)
3199     align_functions = TARGET_88100 ? 16 : 8;
3200 }
3201