OSDN Git Service

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