OSDN Git Service

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