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