OSDN Git Service

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