OSDN Git Service

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