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