* target.h (encode_section_info): Add new argument carrying
[official-gcc.git] / gcc / config / m88k / m88k.c
blob33818a9095e6e34c1252b1bd5c9e8059b11d9ac8
1 /* Subroutines for insn-output.c for Motorola 88000.
2 Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3 2001, 2002 Free Software Foundation, Inc.
4 Contributed by Michael Tiemann (tiemann@mcc.com)
5 Currently maintained by (gcc@dg-rtp.dg.com)
7 This file is part of GNU CC.
9 GNU CC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
14 GNU CC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with GNU CC; see the file COPYING. If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "tm.h"
28 #include "rtl.h"
29 #include "regs.h"
30 #include "hard-reg-set.h"
31 #include "real.h"
32 #include "insn-config.h"
33 #include "conditions.h"
34 #include "output.h"
35 #include "insn-attr.h"
36 #include "tree.h"
37 #include "function.h"
38 #include "expr.h"
39 #include "libfuncs.h"
40 #include "c-tree.h"
41 #include "flags.h"
42 #include "recog.h"
43 #include "toplev.h"
44 #include "tm_p.h"
45 #include "target.h"
46 #include "target-def.h"
48 extern FILE *asm_out_file;
50 const char *m88k_pound_sign = ""; /* Either # for SVR4 or empty for SVR3 */
51 const char *m88k_short_data;
52 const char *m88k_version;
53 char m88k_volatile_code;
55 unsigned m88k_gp_threshold = 0;
56 int m88k_prologue_done = 0; /* Ln directives can now be emitted */
57 int m88k_function_number = 0; /* Counter unique to each function */
58 int m88k_fp_offset = 0; /* offset of frame pointer if used */
59 int m88k_stack_size = 0; /* size of allocated stack (including frame) */
60 int m88k_case_index;
62 rtx m88k_compare_reg; /* cmp output pseudo register */
63 rtx m88k_compare_op0; /* cmpsi operand 0 */
64 rtx m88k_compare_op1; /* cmpsi operand 1 */
66 enum processor_type m88k_cpu; /* target cpu */
68 static void m88k_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
69 static void m88k_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
70 static void m88k_output_function_end_prologue PARAMS ((FILE *));
71 static void m88k_output_function_begin_epilogue PARAMS ((FILE *));
72 #if defined (CTOR_LIST_BEGIN) && !defined (OBJECT_FORMAT_ELF)
73 static void m88k_svr3_asm_out_constructor PARAMS ((rtx, int));
74 static void m88k_svr3_asm_out_destructor PARAMS ((rtx, int));
75 #endif
76 static void m88k_select_section PARAMS ((tree, int, unsigned HOST_WIDE_INT));
77 static int m88k_adjust_cost PARAMS ((rtx, rtx, rtx, int));
78 static void m88k_encode_section_info PARAMS ((tree, rtx, int));
79 #ifdef AS_BUG_DOT_LABELS
80 static void m88k_internal_label PARAMS ((FILE *, const char *, unsigned long));
81 #endif
82 static bool m88k_rtx_costs PARAMS ((rtx, int, int, int *));
83 static int m88k_address_cost PARAMS ((rtx));
85 /* Initialize the GCC target structure. */
86 #undef TARGET_ASM_BYTE_OP
87 #define TARGET_ASM_BYTE_OP "\tbyte\t"
88 #undef TARGET_ASM_ALIGNED_HI_OP
89 #define TARGET_ASM_ALIGNED_HI_OP "\thalf\t"
90 #undef TARGET_ASM_ALIGNED_SI_OP
91 #define TARGET_ASM_ALIGNED_SI_OP "\tword\t"
92 #undef TARGET_ASM_UNALIGNED_HI_OP
93 #define TARGET_ASM_UNALIGNED_HI_OP "\tuahalf\t"
94 #undef TARGET_ASM_UNALIGNED_SI_OP
95 #define TARGET_ASM_UNALIGNED_SI_OP "\tuaword\t"
97 #undef TARGET_ASM_FUNCTION_PROLOGUE
98 #define TARGET_ASM_FUNCTION_PROLOGUE m88k_output_function_prologue
99 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
100 #define TARGET_ASM_FUNCTION_END_PROLOGUE m88k_output_function_end_prologue
101 #undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
102 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE m88k_output_function_begin_epilogue
103 #undef TARGET_ASM_FUNCTION_EPILOGUE
104 #define TARGET_ASM_FUNCTION_EPILOGUE m88k_output_function_epilogue
106 #undef TARGET_SCHED_ADJUST_COST
107 #define TARGET_SCHED_ADJUST_COST m88k_adjust_cost
109 #undef TARGET_ENCODE_SECTION_INFO
110 #define TARGET_ENCODE_SECTION_INFO m88k_encode_section_info
111 #ifdef AS_BUG_DOT_LABELS
112 #undef TARGET_ASM_INTERNAL_LABEL
113 #define TARGET_ASM_INTERNAL_LABEL m88k_internal_label
114 #endif
116 #undef TARGET_RTX_COSTS
117 #define TARGET_RTX_COSTS m88k_rtx_costs
118 #undef TARGET_ADDRESS_COST
119 #define TARGET_ADDRESS_COST m88k_address_cost
121 struct gcc_target targetm = TARGET_INITIALIZER;
123 /* Determine what instructions are needed to manufacture the integer VALUE
124 in the given MODE. */
126 enum m88k_instruction
127 classify_integer (mode, value)
128 enum machine_mode mode;
129 register int value;
131 if (value == 0)
132 return m88k_zero;
133 else if (SMALL_INTVAL (value))
134 return m88k_or;
135 else if (SMALL_INTVAL (-value))
136 return m88k_subu;
137 else if (mode == HImode)
138 return m88k_or_lo16;
139 else if (mode == QImode)
140 return m88k_or_lo8;
141 else if ((value & 0xffff) == 0)
142 return m88k_oru_hi16;
143 else if (integer_ok_for_set (value))
144 return m88k_set;
145 else
146 return m88k_oru_or;
149 /* Return the bit number in a compare word corresponding to CONDITION. */
152 condition_value (condition)
153 rtx condition;
155 switch (GET_CODE (condition))
157 case EQ: return 2;
158 case NE: return 3;
159 case GT: return 4;
160 case LE: return 5;
161 case LT: return 6;
162 case GE: return 7;
163 case GTU: return 8;
164 case LEU: return 9;
165 case LTU: return 10;
166 case GEU: return 11;
167 default: abort ();
172 integer_ok_for_set (value)
173 register unsigned value;
175 /* All the "one" bits must be contiguous. If so, MASK + 1 will be
176 a power of two or zero. */
177 register unsigned mask = (value | (value - 1));
178 return (value && POWER_OF_2_or_0 (mask + 1));
181 const char *
182 output_load_const_int (mode, operands)
183 enum machine_mode mode;
184 rtx *operands;
186 static const char *const patterns[] =
187 { "or %0,%#r0,0",
188 "or %0,%#r0,%1",
189 "subu %0,%#r0,%n1",
190 "or %0,%#r0,%h1",
191 "or %0,%#r0,%q1",
192 "set %0,%#r0,%s1",
193 "or.u %0,%#r0,%X1",
194 "or.u %0,%#r0,%X1\n\tor %0,%0,%x1",
197 if (! REG_P (operands[0])
198 || GET_CODE (operands[1]) != CONST_INT)
199 abort ();
200 return patterns[classify_integer (mode, INTVAL (operands[1]))];
203 /* These next two routines assume that floating point numbers are represented
204 in a manner which is consistent between host and target machines. */
206 const char *
207 output_load_const_float (operands)
208 rtx *operands;
210 /* These can return 0 under some circumstances when cross-compiling. */
211 operands[0] = operand_subword (operands[0], 0, 0, SFmode);
212 operands[1] = operand_subword (operands[1], 0, 0, SFmode);
214 return output_load_const_int (SImode, operands);
217 const char *
218 output_load_const_double (operands)
219 rtx *operands;
221 rtx latehalf[2];
223 /* These can return zero on some cross-compilers, but there's nothing
224 we can do about it. */
225 latehalf[0] = operand_subword (operands[0], 1, 0, DFmode);
226 latehalf[1] = operand_subword (operands[1], 1, 0, DFmode);
228 operands[0] = operand_subword (operands[0], 0, 0, DFmode);
229 operands[1] = operand_subword (operands[1], 0, 0, DFmode);
231 output_asm_insn (output_load_const_int (SImode, operands), operands);
233 operands[0] = latehalf[0];
234 operands[1] = latehalf[1];
236 return output_load_const_int (SImode, operands);
239 const char *
240 output_load_const_dimode (operands)
241 rtx *operands;
243 rtx latehalf[2];
245 latehalf[0] = operand_subword (operands[0], 1, 0, DImode);
246 latehalf[1] = operand_subword (operands[1], 1, 0, DImode);
248 operands[0] = operand_subword (operands[0], 0, 0, DImode);
249 operands[1] = operand_subword (operands[1], 0, 0, DImode);
251 output_asm_insn (output_load_const_int (SImode, operands), operands);
253 operands[0] = latehalf[0];
254 operands[1] = latehalf[1];
256 return output_load_const_int (SImode, operands);
259 /* Emit insns to move operands[1] into operands[0].
261 Return 1 if we have written out everything that needs to be done to
262 do the move. Otherwise, return 0 and the caller will emit the move
263 normally.
265 SCRATCH if nonzero can be used as a scratch register for the move
266 operation. It is provided by a SECONDARY_RELOAD_* macro if needed. */
269 emit_move_sequence (operands, mode, scratch)
270 rtx *operands;
271 enum machine_mode mode;
272 rtx scratch;
274 register rtx operand0 = operands[0];
275 register rtx operand1 = operands[1];
277 if (CONSTANT_P (operand1) && flag_pic
278 && pic_address_needs_scratch (operand1))
279 operands[1] = operand1 = legitimize_address (1, operand1, 0, 0);
281 /* Handle most common case first: storing into a register. */
282 if (register_operand (operand0, mode))
284 if (register_operand (operand1, mode)
285 || (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1))
286 || GET_CODE (operand1) == HIGH
287 /* Only `general_operands' can come here, so MEM is ok. */
288 || GET_CODE (operand1) == MEM)
290 /* Run this case quickly. */
291 emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
292 return 1;
295 else if (GET_CODE (operand0) == MEM)
297 if (register_operand (operand1, mode)
298 || (operand1 == const0_rtx && GET_MODE_SIZE (mode) <= UNITS_PER_WORD))
300 /* Run this case quickly. */
301 emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
302 return 1;
304 if (! reload_in_progress && ! reload_completed)
306 operands[0] = validize_mem (operand0);
307 operands[1] = operand1 = force_reg (mode, operand1);
311 /* Simplify the source if we need to. */
312 if (GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
314 if (GET_CODE (operand1) != CONST_INT
315 && GET_CODE (operand1) != CONST_DOUBLE)
317 rtx temp = ((reload_in_progress || reload_completed)
318 ? operand0 : 0);
319 operands[1] = legitimize_address (flag_pic
320 && symbolic_address_p (operand1),
321 operand1, temp, scratch);
322 if (mode != SImode)
323 operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
327 /* Now have insn-emit do whatever it normally does. */
328 return 0;
331 /* Return a legitimate reference for ORIG (either an address or a MEM)
332 using the register REG. If PIC and the address is already
333 position-independent, use ORIG. Newly generated position-independent
334 addresses go into a reg. This is REG if nonzero, otherwise we
335 allocate register(s) as necessary. If this is called during reload,
336 and we need a second temp register, then we use SCRATCH, which is
337 provided via the SECONDARY_INPUT_RELOAD_CLASS mechanism. */
339 struct rtx_def *
340 legitimize_address (pic, orig, reg, scratch)
341 int pic;
342 rtx orig;
343 rtx reg;
344 rtx scratch;
346 rtx addr = (GET_CODE (orig) == MEM ? XEXP (orig, 0) : orig);
347 rtx new = orig;
348 rtx temp, insn;
350 if (pic)
352 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
354 if (reg == 0)
356 if (reload_in_progress || reload_completed)
357 abort ();
358 else
359 reg = gen_reg_rtx (Pmode);
362 if (flag_pic == 2)
364 /* If not during reload, allocate another temp reg here for
365 loading in the address, so that these instructions can be
366 optimized properly. */
367 temp = ((reload_in_progress || reload_completed)
368 ? reg : gen_reg_rtx (Pmode));
370 emit_insn (gen_rtx_SET
371 (VOIDmode, temp,
372 gen_rtx_HIGH (SImode,
373 gen_rtx_UNSPEC (SImode,
374 gen_rtvec (1, addr),
375 0))));
377 emit_insn (gen_rtx_SET
378 (VOIDmode, temp,
379 gen_rtx_LO_SUM (SImode, temp,
380 gen_rtx_UNSPEC (SImode,
381 gen_rtvec (1, addr),
382 0))));
383 addr = temp;
386 new = gen_rtx_MEM (Pmode,
387 gen_rtx_PLUS (SImode,
388 pic_offset_table_rtx, addr));
390 current_function_uses_pic_offset_table = 1;
391 RTX_UNCHANGING_P (new) = 1;
392 insn = emit_move_insn (reg, new);
393 /* Put a REG_EQUAL note on this insn, so that it can be optimized
394 by loop. */
395 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig,
396 REG_NOTES (insn));
397 new = reg;
399 else if (GET_CODE (addr) == CONST)
401 rtx base;
403 if (GET_CODE (XEXP (addr, 0)) == PLUS
404 && XEXP (XEXP (addr, 0), 0) == pic_offset_table_rtx)
405 return orig;
407 if (reg == 0)
409 if (reload_in_progress || reload_completed)
410 abort ();
411 else
412 reg = gen_reg_rtx (Pmode);
415 if (GET_CODE (XEXP (addr, 0)) != PLUS) abort ();
417 base = legitimize_address (1, XEXP (XEXP (addr, 0), 0), reg, 0);
418 addr = legitimize_address (1, XEXP (XEXP (addr, 0), 1),
419 base == reg ? 0 : reg, 0);
421 if (GET_CODE (addr) == CONST_INT)
423 if (ADD_INT (addr))
424 return plus_constant (base, INTVAL (addr));
425 else if (! reload_in_progress && ! reload_completed)
426 addr = force_reg (Pmode, addr);
427 /* We can't create any new registers during reload, so use the
428 SCRATCH reg provided by the reload_insi pattern. */
429 else if (scratch)
431 emit_move_insn (scratch, addr);
432 addr = scratch;
434 else
435 /* If we reach here, then the SECONDARY_INPUT_RELOAD_CLASS
436 macro needs to be adjusted so that a scratch reg is provided
437 for this address. */
438 abort ();
440 new = gen_rtx_PLUS (SImode, base, addr);
441 /* Should we set special REG_NOTEs here? */
444 else if (! SHORT_ADDRESS_P (addr, temp))
446 if (reg == 0)
448 if (reload_in_progress || reload_completed)
449 abort ();
450 else
451 reg = gen_reg_rtx (Pmode);
454 emit_insn (gen_rtx_SET (VOIDmode,
455 reg, gen_rtx_HIGH (SImode, addr)));
456 new = gen_rtx_LO_SUM (SImode, reg, addr);
459 if (new != orig
460 && GET_CODE (orig) == MEM)
462 new = gen_rtx_MEM (GET_MODE (orig), new);
463 MEM_COPY_ATTRIBUTES (new, orig);
465 return new;
468 /* Support functions for code to emit a block move. There are four methods
469 used to perform the block move:
470 + call memcpy
471 + call the looping library function, e.g. __movstrSI64n8
472 + call a non-looping library function, e.g. __movstrHI15x11
473 + produce an inline sequence of ld/st instructions
475 The parameters below describe the library functions produced by
476 movstr-m88k.sh. */
478 #define MOVSTR_LOOP 64 /* __movstrSI64n68 .. __movstrSI64n8 */
479 #define MOVSTR_QI 16 /* __movstrQI16x16 .. __movstrQI16x2 */
480 #define MOVSTR_HI 48 /* __movstrHI48x48 .. __movstrHI48x4 */
481 #define MOVSTR_SI 96 /* __movstrSI96x96 .. __movstrSI96x8 */
482 #define MOVSTR_DI 96 /* __movstrDI96x96 .. __movstrDI96x16 */
483 #define MOVSTR_ODD_HI 16 /* __movstrHI15x15 .. __movstrHI15x5 */
484 #define MOVSTR_ODD_SI 48 /* __movstrSI47x47 .. __movstrSI47x11,
485 __movstrSI46x46 .. __movstrSI46x10,
486 __movstrSI45x45 .. __movstrSI45x9 */
487 #define MOVSTR_ODD_DI 48 /* __movstrDI47x47 .. __movstrDI47x23,
488 __movstrDI46x46 .. __movstrDI46x22,
489 __movstrDI45x45 .. __movstrDI45x21,
490 __movstrDI44x44 .. __movstrDI44x20,
491 __movstrDI43x43 .. __movstrDI43x19,
492 __movstrDI42x42 .. __movstrDI42x18,
493 __movstrDI41x41 .. __movstrDI41x17 */
495 /* Limits for using the non-looping movstr functions. For the m88100
496 processor, we assume the source and destination are word aligned.
497 The QImode and HImode limits are the break even points where memcpy
498 does just as well and beyond which memcpy does better. For the
499 m88110, we tend to assume double word alignment, but also analyze
500 the word aligned cases. The analysis is complicated because memcpy
501 may use the cache control instructions for better performance. */
503 #define MOVSTR_QI_LIMIT_88100 13
504 #define MOVSTR_HI_LIMIT_88100 38
505 #define MOVSTR_SI_LIMIT_88100 MOVSTR_SI
506 #define MOVSTR_DI_LIMIT_88100 MOVSTR_SI
508 #define MOVSTR_QI_LIMIT_88000 16
509 #define MOVSTR_HI_LIMIT_88000 38
510 #define MOVSTR_SI_LIMIT_88000 72
511 #define MOVSTR_DI_LIMIT_88000 72
513 #define MOVSTR_QI_LIMIT_88110 16
514 #define MOVSTR_HI_LIMIT_88110 38
515 #define MOVSTR_SI_LIMIT_88110 72
516 #define MOVSTR_DI_LIMIT_88110 72
518 static const enum machine_mode mode_from_align[] =
519 {VOIDmode, QImode, HImode, VOIDmode, SImode,
520 VOIDmode, VOIDmode, VOIDmode, DImode};
521 static const int max_from_align[] = {0, MOVSTR_QI, MOVSTR_HI, 0, MOVSTR_SI,
522 0, 0, 0, MOVSTR_DI};
523 static const int all_from_align[] = {0, MOVSTR_QI, MOVSTR_ODD_HI, 0,
524 MOVSTR_ODD_SI, 0, 0, 0, MOVSTR_ODD_DI};
526 static const int best_from_align[3][9] = {
527 {0, MOVSTR_QI_LIMIT_88100, MOVSTR_HI_LIMIT_88100, 0, MOVSTR_SI_LIMIT_88100,
528 0, 0, 0, MOVSTR_DI_LIMIT_88100},
529 {0, MOVSTR_QI_LIMIT_88110, MOVSTR_HI_LIMIT_88110, 0, MOVSTR_SI_LIMIT_88110,
530 0, 0, 0, MOVSTR_DI_LIMIT_88110},
531 {0, MOVSTR_QI_LIMIT_88000, MOVSTR_HI_LIMIT_88000, 0, MOVSTR_SI_LIMIT_88000,
532 0, 0, 0, MOVSTR_DI_LIMIT_88000}
535 static void block_move_loop PARAMS ((rtx, rtx, rtx, rtx, int, int));
536 static void block_move_no_loop PARAMS ((rtx, rtx, rtx, rtx, int, int));
537 static void block_move_sequence PARAMS ((rtx, rtx, rtx, rtx, int, int, int));
538 static void output_short_branch_defs PARAMS ((FILE *));
539 static int output_option PARAMS ((FILE *, const char *, const char *,
540 const char *, const char *, int, int));
542 /* Emit code to perform a block move. Choose the best method.
544 OPERANDS[0] is the destination.
545 OPERANDS[1] is the source.
546 OPERANDS[2] is the size.
547 OPERANDS[3] is the alignment safe to use. */
549 void
550 expand_block_move (dest_mem, src_mem, operands)
551 rtx dest_mem;
552 rtx src_mem;
553 rtx *operands;
555 int align = INTVAL (operands[3]);
556 int constp = (GET_CODE (operands[2]) == CONST_INT);
557 int bytes = (constp ? INTVAL (operands[2]) : 0);
558 int target = (int) m88k_cpu;
560 if (! (PROCESSOR_M88100 == 0
561 && PROCESSOR_M88110 == 1
562 && PROCESSOR_M88000 == 2))
563 abort ();
565 if (constp && bytes <= 0)
566 return;
568 /* Determine machine mode to do move with. */
569 if (align > 4 && !TARGET_88110)
570 align = 4;
571 else if (align <= 0 || align == 3)
572 abort (); /* block move invalid alignment. */
574 if (constp && bytes <= 3 * align)
575 block_move_sequence (operands[0], dest_mem, operands[1], src_mem,
576 bytes, align, 0);
578 else if (constp && bytes <= best_from_align[target][align])
579 block_move_no_loop (operands[0], dest_mem, operands[1], src_mem,
580 bytes, align);
582 else if (constp && align == 4 && TARGET_88100)
583 block_move_loop (operands[0], dest_mem, operands[1], src_mem,
584 bytes, align);
586 else
588 #ifdef TARGET_MEM_FUNCTIONS
589 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "memcpy"), 0,
590 VOIDmode, 3,
591 operands[0], Pmode,
592 operands[1], Pmode,
593 convert_to_mode (TYPE_MODE (sizetype), operands[2],
594 TREE_UNSIGNED (sizetype)),
595 TYPE_MODE (sizetype));
596 #else
597 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "bcopy"), 0,
598 VOIDmode, 3,
599 operands[1], Pmode,
600 operands[0], Pmode,
601 convert_to_mode (TYPE_MODE (integer_type_node),
602 operands[2],
603 TREE_UNSIGNED (integer_type_node)),
604 TYPE_MODE (integer_type_node));
605 #endif
609 /* Emit code to perform a block move by calling a looping movstr library
610 function. SIZE and ALIGN are known constants. DEST and SRC are
611 registers. */
613 static void
614 block_move_loop (dest, dest_mem, src, src_mem, size, align)
615 rtx dest, dest_mem;
616 rtx src, src_mem;
617 int size;
618 int align;
620 enum machine_mode mode;
621 int count;
622 int units;
623 int remainder;
624 rtx offset_rtx;
625 rtx value_rtx;
626 char entry[30];
627 tree entry_name;
629 /* Determine machine mode to do move with. */
630 if (align != 4)
631 abort ();
633 /* Determine the structure of the loop. */
634 count = size / MOVSTR_LOOP;
635 units = (size - count * MOVSTR_LOOP) / align;
637 if (units < 2)
639 count--;
640 units += MOVSTR_LOOP / align;
643 if (count <= 0)
645 block_move_no_loop (dest, dest_mem, src, src_mem, size, align);
646 return;
649 remainder = size - count * MOVSTR_LOOP - units * align;
651 mode = mode_from_align[align];
652 sprintf (entry, "__movstr%s%dn%d",
653 GET_MODE_NAME (mode), MOVSTR_LOOP, units * align);
654 entry_name = get_identifier (entry);
656 offset_rtx = GEN_INT (MOVSTR_LOOP + (1 - units) * align);
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 MEM_COPY_ATTRIBUTES (value_rtx, src_mem);
664 emit_insn (gen_call_movstrsi_loop
665 (gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (entry_name)),
666 dest, src, offset_rtx, value_rtx,
667 gen_rtx_REG (mode, ((units & 1) ? 4 : 5)),
668 GEN_INT (count)));
670 if (remainder)
671 block_move_sequence (gen_rtx_REG (Pmode, 2), dest_mem,
672 gen_rtx_REG (Pmode, 3), src_mem,
673 remainder, align, MOVSTR_LOOP + align);
676 /* Emit code to perform a block move by calling a non-looping library
677 function. SIZE and ALIGN are known constants. DEST and SRC are
678 registers. OFFSET is the known starting point for the output pattern. */
680 static void
681 block_move_no_loop (dest, dest_mem, src, src_mem, size, align)
682 rtx dest, dest_mem;
683 rtx src, src_mem;
684 int size;
685 int align;
687 enum machine_mode mode = mode_from_align[align];
688 int units = size / align;
689 int remainder = size - units * align;
690 int most;
691 int value_reg;
692 rtx offset_rtx;
693 rtx value_rtx;
694 char entry[30];
695 tree entry_name;
697 if (remainder && size <= all_from_align[align])
699 most = all_from_align[align] - (align - remainder);
700 remainder = 0;
702 else
704 most = max_from_align[align];
707 sprintf (entry, "__movstr%s%dx%d",
708 GET_MODE_NAME (mode), most, size - remainder);
709 entry_name = get_identifier (entry);
711 offset_rtx = GEN_INT (most - (size - remainder));
713 value_rtx = gen_rtx_MEM (MEM_IN_STRUCT_P (src_mem) ? mode : BLKmode,
714 gen_rtx_PLUS (Pmode,
715 gen_rtx_REG (Pmode, 3),
716 offset_rtx));
718 MEM_COPY_ATTRIBUTES (value_rtx, src_mem);
720 value_reg = ((((most - (size - remainder)) / align) & 1) == 0
721 ? (align == 8 ? 6 : 5) : 4);
723 emit_insn (gen_call_block_move
724 (gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (entry_name)),
725 dest, src, offset_rtx, value_rtx,
726 gen_rtx_REG (mode, value_reg)));
728 if (remainder)
729 block_move_sequence (gen_rtx_REG (Pmode, 2), dest_mem,
730 gen_rtx_REG (Pmode, 3), src_mem,
731 remainder, align, most);
734 /* Emit code to perform a block move with an offset sequence of ld/st
735 instructions (..., ld 0, st 1, ld 1, st 0, ...). SIZE and ALIGN are
736 known constants. DEST and SRC are registers. OFFSET is the known
737 starting point for the output pattern. */
739 static void
740 block_move_sequence (dest, dest_mem, src, src_mem, size, align, offset)
741 rtx dest, dest_mem;
742 rtx src, src_mem;
743 int size;
744 int align;
745 int offset;
747 rtx temp[2];
748 enum machine_mode mode[2];
749 int amount[2];
750 int active[2];
751 int phase = 0;
752 int next;
753 int offset_ld = offset;
754 int offset_st = offset;
756 active[0] = active[1] = FALSE;
758 /* Establish parameters for the first load and for the second load if
759 it is known to be the same mode as the first. */
760 amount[0] = amount[1] = align;
761 mode[0] = mode_from_align[align];
762 temp[0] = gen_reg_rtx (mode[0]);
763 if (size >= 2 * align)
765 mode[1] = mode[0];
766 temp[1] = gen_reg_rtx (mode[1]);
771 rtx srcp, dstp;
772 next = phase;
773 phase = !phase;
775 if (size > 0)
777 /* Change modes as the sequence tails off. */
778 if (size < amount[next])
780 amount[next] = (size >= 4 ? 4 : (size >= 2 ? 2 : 1));
781 mode[next] = mode_from_align[amount[next]];
782 temp[next] = gen_reg_rtx (mode[next]);
784 size -= amount[next];
785 srcp = gen_rtx_MEM (MEM_IN_STRUCT_P (src_mem) ? mode[next] : BLKmode,
786 plus_constant (src, offset_ld));
788 MEM_COPY_ATTRIBUTES (srcp, src_mem);
789 emit_insn (gen_rtx_SET (VOIDmode, temp[next], srcp));
790 offset_ld += amount[next];
791 active[next] = TRUE;
794 if (active[phase])
796 active[phase] = FALSE;
797 dstp
798 = gen_rtx_MEM (MEM_IN_STRUCT_P (dest_mem) ? mode[phase] : BLKmode,
799 plus_constant (dest, offset_st));
801 MEM_COPY_ATTRIBUTES (dstp, dest_mem);
802 emit_insn (gen_rtx_SET (VOIDmode, dstp, temp[phase]));
803 offset_st += amount[phase];
806 while (active[next]);
809 /* Emit the code to do an AND operation. */
811 const char *
812 output_and (operands)
813 rtx operands[];
815 unsigned int value;
817 if (REG_P (operands[2]))
818 return "and %0,%1,%2";
820 value = INTVAL (operands[2]);
821 if (SMALL_INTVAL (value))
822 return "mask %0,%1,%2";
823 else if ((value & 0xffff0000) == 0xffff0000)
824 return "and %0,%1,%x2";
825 else if ((value & 0xffff) == 0xffff)
826 return "and.u %0,%1,%X2";
827 else if ((value & 0xffff) == 0)
828 return "mask.u %0,%1,%X2";
829 else if (integer_ok_for_set (~value))
830 return "clr %0,%1,%S2";
831 else
832 return "and.u %0,%1,%X2\n\tand %0,%0,%x2";
835 /* Emit the code to do an inclusive OR operation. */
837 const char *
838 output_ior (operands)
839 rtx operands[];
841 unsigned int value;
843 if (REG_P (operands[2]))
844 return "or %0,%1,%2";
846 value = INTVAL (operands[2]);
847 if (SMALL_INTVAL (value))
848 return "or %0,%1,%2";
849 else if ((value & 0xffff) == 0)
850 return "or.u %0,%1,%X2";
851 else if (integer_ok_for_set (value))
852 return "set %0,%1,%s2";
853 else
854 return "or.u %0,%1,%X2\n\tor %0,%0,%x2";
857 /* Emit the instructions for doing an XOR. */
859 const char *
860 output_xor (operands)
861 rtx operands[];
863 unsigned int value;
865 if (REG_P (operands[2]))
866 return "xor %0,%1,%2";
868 value = INTVAL (operands[2]);
869 if (SMALL_INTVAL (value))
870 return "xor %0,%1,%2";
871 else if ((value & 0xffff) == 0)
872 return "xor.u %0,%1,%X2";
873 else
874 return "xor.u %0,%1,%X2\n\txor %0,%0,%x2";
877 /* Output a call. Normally this is just bsr or jsr, but this also deals with
878 accomplishing a branch after the call by incrementing r1. This requires
879 that various assembler bugs be accommodated. The 4.30 DG/UX assembler
880 requires that forward references not occur when computing the difference of
881 two labels. The [version?] Motorola assembler computes a word difference.
882 No doubt there's more to come!
884 It would seem the same idea could be used to tail call, but in this case,
885 the epilogue will be non-null. */
887 static rtx sb_name = 0;
888 static rtx sb_high = 0;
889 static rtx sb_low = 0;
891 const char *
892 output_call (operands, addr)
893 rtx operands[];
894 rtx addr;
896 operands[0] = addr;
897 if (final_sequence)
899 rtx jump;
900 rtx seq_insn;
902 /* This can be generalized, but there is currently no need. */
903 if (XVECLEN (final_sequence, 0) != 2)
904 abort ();
906 /* The address of interior insns is not computed, so use the sequence. */
907 seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
908 jump = XVECEXP (final_sequence, 0, 1);
909 if (GET_CODE (jump) == JUMP_INSN)
911 #ifndef USE_GAS
912 rtx low, high;
913 #endif
914 const char *last;
915 rtx dest = XEXP (SET_SRC (PATTERN (jump)), 0);
916 int delta = 4 * (INSN_ADDRESSES (INSN_UID (dest))
917 - INSN_ADDRESSES (INSN_UID (seq_insn))
918 - 2);
919 #if (MONITOR_GCC & 0x2) /* How often do long branches happen? */
920 if ((unsigned) (delta + 0x8000) >= 0x10000)
921 warning ("internal gcc monitor: short-branch(%x)", delta);
922 #endif
924 /* Delete the jump. */
925 PUT_CODE (jump, NOTE);
926 NOTE_LINE_NUMBER (jump) = NOTE_INSN_DELETED;
927 NOTE_SOURCE_FILE (jump) = 0;
929 /* We only do this optimization if -O2, modifying the value of
930 r1 in the delay slot confuses debuggers and profilers on some
931 systems.
933 If we loose, we must use the non-delay form. This is unlikely
934 to ever happen. If it becomes a problem, claim that a call
935 has two delay slots and only the second can be filled with
936 a jump.
938 The 88110 can lose when a jsr.n r1 is issued and a page fault
939 occurs accessing the delay slot. So don't use jsr.n form when
940 jumping thru r1.
942 #ifdef AS_BUG_IMMEDIATE_LABEL /* The assembler restricts immediate values. */
943 if (optimize < 2
944 || ! ADD_INTVAL (delta * 2)
945 #else
946 if (optimize < 2
947 || ! ADD_INTVAL (delta)
948 #endif
949 || (REG_P (addr) && REGNO (addr) == 1))
951 operands[1] = dest;
952 return (REG_P (addr)
953 ? "jsr %0\n\tbr %l1"
954 : (flag_pic
955 ? "bsr %0#plt\n\tbr %l1"
956 : "bsr %0\n\tbr %l1"));
959 /* Output the short branch form. */
960 output_asm_insn ((REG_P (addr)
961 ? "jsr.n %0"
962 : (flag_pic ? "bsr.n %0#plt" : "bsr.n %0")),
963 operands);
965 #ifdef USE_GAS
966 last = (delta < 0
967 ? "subu %#r1,%#r1,.-%l0+4"
968 : "addu %#r1,%#r1,%l0-.-4");
969 operands[0] = dest;
970 #else
971 operands[0] = gen_label_rtx ();
972 operands[1] = gen_label_rtx ();
973 if (delta < 0)
975 low = dest;
976 high = operands[1];
977 last = "subu %#r1,%#r1,%l0\n%l1:";
979 else
981 low = operands[1];
982 high = dest;
983 last = "addu %#r1,%#r1,%l0\n%l1:";
986 /* Record the values to be computed later as "def name,high-low". */
987 sb_name = gen_rtx_EXPR_LIST (VOIDmode, operands[0], sb_name);
988 sb_high = gen_rtx_EXPR_LIST (VOIDmode, high, sb_high);
989 sb_low = gen_rtx_EXPR_LIST (VOIDmode, low, sb_low);
990 #endif /* Don't USE_GAS */
992 return last;
995 return (REG_P (addr)
996 ? "jsr%. %0"
997 : (flag_pic ? "bsr%. %0#plt" : "bsr%. %0"));
1000 static void
1001 output_short_branch_defs (stream)
1002 FILE *stream;
1004 char name[256], high[256], low[256];
1006 for (; sb_name && sb_high && sb_low;
1007 sb_name = XEXP (sb_name, 1),
1008 sb_high = XEXP (sb_high, 1),
1009 sb_low = XEXP (sb_low, 1))
1011 ASM_GENERATE_INTERNAL_LABEL
1012 (name, "L", CODE_LABEL_NUMBER (XEXP (sb_name, 0)));
1013 ASM_GENERATE_INTERNAL_LABEL
1014 (high, "L", CODE_LABEL_NUMBER (XEXP (sb_high, 0)));
1015 ASM_GENERATE_INTERNAL_LABEL
1016 (low, "L", CODE_LABEL_NUMBER (XEXP (sb_low, 0)));
1017 /* This will change as the assembler requirements become known. */
1018 fprintf (stream, "%s%s,%s-%s\n",
1019 SET_ASM_OP, &name[1], &high[1], &low[1]);
1021 if (sb_name || sb_high || sb_low)
1022 abort ();
1025 /* Return truth value of the statement that this conditional branch is likely
1026 to fall through. CONDITION, is the condition that JUMP_INSN is testing. */
1029 mostly_false_jump (jump_insn, condition)
1030 rtx jump_insn, condition;
1032 rtx target_label = JUMP_LABEL (jump_insn);
1033 rtx insnt, insnj;
1035 /* Much of this isn't computed unless we're optimizing. */
1036 if (optimize == 0)
1037 return 0;
1039 /* Determine if one path or the other leads to a return. */
1040 for (insnt = NEXT_INSN (target_label);
1041 insnt;
1042 insnt = NEXT_INSN (insnt))
1044 if (GET_CODE (insnt) == JUMP_INSN)
1045 break;
1046 else if (GET_CODE (insnt) == INSN
1047 && GET_CODE (PATTERN (insnt)) == SEQUENCE
1048 && GET_CODE (XVECEXP (PATTERN (insnt), 0, 0)) == JUMP_INSN)
1050 insnt = XVECEXP (PATTERN (insnt), 0, 0);
1051 break;
1054 if (insnt
1055 && (GET_CODE (PATTERN (insnt)) == RETURN
1056 || (GET_CODE (PATTERN (insnt)) == SET
1057 && GET_CODE (SET_SRC (PATTERN (insnt))) == REG
1058 && REGNO (SET_SRC (PATTERN (insnt))) == 1)))
1059 insnt = 0;
1061 for (insnj = NEXT_INSN (jump_insn);
1062 insnj;
1063 insnj = NEXT_INSN (insnj))
1065 if (GET_CODE (insnj) == JUMP_INSN)
1066 break;
1067 else if (GET_CODE (insnj) == INSN
1068 && GET_CODE (PATTERN (insnj)) == SEQUENCE
1069 && GET_CODE (XVECEXP (PATTERN (insnj), 0, 0)) == JUMP_INSN)
1071 insnj = XVECEXP (PATTERN (insnj), 0, 0);
1072 break;
1075 if (insnj
1076 && (GET_CODE (PATTERN (insnj)) == RETURN
1077 || (GET_CODE (PATTERN (insnj)) == SET
1078 && GET_CODE (SET_SRC (PATTERN (insnj))) == REG
1079 && REGNO (SET_SRC (PATTERN (insnj))) == 1)))
1080 insnj = 0;
1082 /* Predict to not return. */
1083 if ((insnt == 0) != (insnj == 0))
1084 return (insnt == 0);
1086 /* Predict loops to loop. */
1087 for (insnt = PREV_INSN (target_label);
1088 insnt && GET_CODE (insnt) == NOTE;
1089 insnt = PREV_INSN (insnt))
1090 if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_END)
1091 return 1;
1092 else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_BEG)
1093 return 0;
1094 else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_CONT)
1095 return 0;
1097 /* Predict backward branches usually take. */
1098 if (final_sequence)
1099 insnj = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
1100 else
1101 insnj = jump_insn;
1102 if (INSN_ADDRESSES (INSN_UID (insnj))
1103 > INSN_ADDRESSES (INSN_UID (target_label)))
1104 return 0;
1106 /* EQ tests are usually false and NE tests are usually true. Also,
1107 most quantities are positive, so we can make the appropriate guesses
1108 about signed comparisons against zero. Consider unsigned comparisons
1109 to be a range check and assume quantities to be in range. */
1110 switch (GET_CODE (condition))
1112 case CONST_INT:
1113 /* Unconditional branch. */
1114 return 0;
1115 case EQ:
1116 return 1;
1117 case NE:
1118 return 0;
1119 case LE:
1120 case LT:
1121 case GEU:
1122 case GTU: /* Must get casesi right at least. */
1123 if (XEXP (condition, 1) == const0_rtx)
1124 return 1;
1125 break;
1126 case GE:
1127 case GT:
1128 case LEU:
1129 case LTU:
1130 if (XEXP (condition, 1) == const0_rtx)
1131 return 0;
1132 break;
1133 default:
1134 break;
1137 return 0;
1140 /* Return true if the operand is a power of two and is a floating
1141 point type (to optimize division by power of two into multiplication). */
1144 real_power_of_2_operand (op, mode)
1145 rtx op;
1146 enum machine_mode mode ATTRIBUTE_UNUSED;
1148 REAL_VALUE_TYPE d;
1149 union {
1150 long l[2];
1151 struct { /* IEEE double precision format */
1152 unsigned sign : 1;
1153 unsigned exponent : 11;
1154 unsigned mantissa1 : 20;
1155 unsigned mantissa2;
1156 } s;
1157 struct { /* IEEE double format to quick check */
1158 unsigned sign : 1; /* if it fits in a float */
1159 unsigned exponent1 : 4;
1160 unsigned exponent2 : 7;
1161 unsigned mantissa1 : 20;
1162 unsigned mantissa2;
1163 } s2;
1164 } u;
1166 if (GET_MODE (op) != DFmode && GET_MODE (op) != SFmode)
1167 return 0;
1169 if (GET_CODE (op) != CONST_DOUBLE)
1170 return 0;
1172 REAL_VALUE_FROM_CONST_DOUBLE (d, op);
1173 REAL_VALUE_TO_TARGET_DOUBLE (d, u.l);
1175 if (u.s.mantissa1 != 0 || u.s.mantissa2 != 0 /* not a power of two */
1176 || u.s.exponent == 0 /* constant 0.0 */
1177 || u.s.exponent == 0x7ff /* NAN */
1178 || (u.s2.exponent1 != 0x8 && u.s2.exponent1 != 0x7))
1179 return 0; /* const won't fit in float */
1181 return 1;
1184 /* Make OP legitimate for mode MODE. Currently this only deals with DFmode
1185 operands, putting them in registers and making CONST_DOUBLE values
1186 SFmode where possible. */
1188 struct rtx_def *
1189 legitimize_operand (op, mode)
1190 rtx op;
1191 enum machine_mode mode;
1193 rtx temp;
1194 REAL_VALUE_TYPE r;
1195 union {
1196 long l[2];
1197 struct { /* IEEE double precision format */
1198 unsigned sign : 1;
1199 unsigned exponent : 11;
1200 unsigned mantissa1 : 20;
1201 unsigned mantissa2;
1202 } d;
1203 struct { /* IEEE double format to quick check */
1204 unsigned sign : 1; /* if it fits in a float */
1205 unsigned exponent1 : 4;
1206 unsigned exponent2 : 7;
1207 unsigned mantissa1 : 20;
1208 unsigned mantissa2;
1209 } s;
1210 } u;
1212 if (GET_CODE (op) == REG || mode != DFmode)
1213 return op;
1215 if (GET_CODE (op) == CONST_DOUBLE)
1217 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
1218 REAL_VALUE_TO_TARGET_DOUBLE (r, u.l);
1219 if (u.d.exponent != 0x7ff /* NaN */
1220 && u.d.mantissa2 == 0 /* Mantissa fits */
1221 && (u.s.exponent1 == 0x8 || u.s.exponent1 == 0x7) /* Exponent fits */
1222 && (temp = simplify_unary_operation (FLOAT_TRUNCATE, SFmode,
1223 op, mode)) != 0)
1224 return gen_rtx_FLOAT_EXTEND (mode, force_reg (SFmode, temp));
1226 else if (register_operand (op, mode))
1227 return op;
1229 return force_reg (mode, op);
1232 /* Return true if OP is a suitable input for a move insn. */
1235 move_operand (op, mode)
1236 rtx op;
1237 enum machine_mode mode;
1239 if (register_operand (op, mode))
1240 return 1;
1241 if (GET_CODE (op) == CONST_INT)
1242 return (classify_integer (mode, INTVAL (op)) < m88k_oru_hi16);
1243 if (GET_MODE (op) != mode)
1244 return 0;
1245 if (GET_CODE (op) == SUBREG)
1246 op = SUBREG_REG (op);
1247 if (GET_CODE (op) != MEM)
1248 return 0;
1250 op = XEXP (op, 0);
1251 if (GET_CODE (op) == LO_SUM)
1252 return (REG_P (XEXP (op, 0))
1253 && symbolic_address_p (XEXP (op, 1)));
1254 return memory_address_p (mode, op);
1257 /* Return true if OP is suitable for a call insn. */
1260 call_address_operand (op, mode)
1261 rtx op;
1262 enum machine_mode mode ATTRIBUTE_UNUSED;
1264 return (REG_P (op) || symbolic_address_p (op));
1267 /* Returns true if OP is either a symbol reference or a sum of a symbol
1268 reference and a constant. */
1271 symbolic_address_p (op)
1272 register rtx op;
1274 switch (GET_CODE (op))
1276 case SYMBOL_REF:
1277 case LABEL_REF:
1278 return 1;
1280 case CONST:
1281 op = XEXP (op, 0);
1282 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
1283 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
1284 && GET_CODE (XEXP (op, 1)) == CONST_INT);
1286 default:
1287 return 0;
1291 /* Return true if OP is a register or const0_rtx. */
1294 reg_or_0_operand (op, mode)
1295 rtx op;
1296 enum machine_mode mode;
1298 return (op == const0_rtx || register_operand (op, mode));
1301 /* Nonzero if OP is a valid second operand for an arithmetic insn. */
1304 arith_operand (op, mode)
1305 rtx op;
1306 enum machine_mode mode;
1308 return (register_operand (op, mode)
1309 || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
1312 /* Return true if OP is a register or 5 bit integer. */
1315 arith5_operand (op, mode)
1316 rtx op;
1317 enum machine_mode mode;
1319 return (register_operand (op, mode)
1320 || (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32));
1324 arith32_operand (op, mode)
1325 rtx op;
1326 enum machine_mode mode;
1328 return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
1332 arith64_operand (op, mode)
1333 rtx op;
1334 enum machine_mode mode;
1336 return (register_operand (op, mode)
1337 || GET_CODE (op) == CONST_INT
1338 || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode));
1342 int5_operand (op, mode)
1343 rtx op;
1344 enum machine_mode mode ATTRIBUTE_UNUSED;
1346 return (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32);
1350 int32_operand (op, mode)
1351 rtx op;
1352 enum machine_mode mode ATTRIBUTE_UNUSED;
1354 return (GET_CODE (op) == CONST_INT);
1357 /* Return true if OP is a register or a valid immediate operand for
1358 addu or subu. */
1361 add_operand (op, mode)
1362 rtx op;
1363 enum machine_mode mode;
1365 return (register_operand (op, mode)
1366 || (GET_CODE (op) == CONST_INT && ADD_INT (op)));
1369 /* Nonzero if this is a bitmask filling the bottom bits, for optimizing and +
1370 shift left combinations into a single mak instruction. */
1373 mak_mask_p (value)
1374 int value;
1376 return (value && POWER_OF_2_or_0 (value + 1));
1380 reg_or_bbx_mask_operand (op, mode)
1381 rtx op;
1382 enum machine_mode mode;
1384 int value;
1385 if (register_operand (op, mode))
1386 return 1;
1387 if (GET_CODE (op) != CONST_INT)
1388 return 0;
1390 value = INTVAL (op);
1391 if (POWER_OF_2 (value))
1392 return 1;
1394 return 0;
1397 /* Return true if OP is valid to use in the context of a floating
1398 point operation. Special case 0.0, since we can use r0. */
1401 real_or_0_operand (op, mode)
1402 rtx op;
1403 enum machine_mode mode;
1405 if (mode != SFmode && mode != DFmode)
1406 return 0;
1408 return (register_operand (op, mode)
1409 || (GET_CODE (op) == CONST_DOUBLE
1410 && op == CONST0_RTX (mode)));
1413 /* Return true if OP is valid to use in the context of logic arithmetic
1414 on condition codes. */
1417 partial_ccmode_register_operand (op, mode)
1418 rtx op;
1419 enum machine_mode mode ATTRIBUTE_UNUSED;
1421 return register_operand (op, CCmode) || register_operand (op, CCEVENmode);
1424 /* Return true if OP is a relational operator. */
1427 relop (op, mode)
1428 rtx op;
1429 enum machine_mode mode ATTRIBUTE_UNUSED;
1431 switch (GET_CODE (op))
1433 case EQ:
1434 case NE:
1435 case LT:
1436 case LE:
1437 case GE:
1438 case GT:
1439 case LTU:
1440 case LEU:
1441 case GEU:
1442 case GTU:
1443 return 1;
1444 default:
1445 return 0;
1450 even_relop (op, mode)
1451 rtx op;
1452 enum machine_mode mode ATTRIBUTE_UNUSED;
1454 switch (GET_CODE (op))
1456 case EQ:
1457 case LT:
1458 case GT:
1459 case LTU:
1460 case GTU:
1461 return 1;
1462 default:
1463 return 0;
1468 odd_relop (op, mode)
1469 rtx op;
1470 enum machine_mode mode ATTRIBUTE_UNUSED;
1472 switch (GET_CODE (op))
1474 case NE:
1475 case LE:
1476 case GE:
1477 case LEU:
1478 case GEU:
1479 return 1;
1480 default:
1481 return 0;
1485 /* Return true if OP is a relational operator, and is not an unsigned
1486 relational operator. */
1489 relop_no_unsigned (op, mode)
1490 rtx op;
1491 enum machine_mode mode ATTRIBUTE_UNUSED;
1493 switch (GET_CODE (op))
1495 case EQ:
1496 case NE:
1497 case LT:
1498 case LE:
1499 case GE:
1500 case GT:
1501 /* @@ What is this test doing? Why not use `mode'? */
1502 if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
1503 || GET_MODE (op) == DImode
1504 || GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_FLOAT
1505 || GET_MODE (XEXP (op, 0)) == DImode
1506 || GET_MODE_CLASS (GET_MODE (XEXP (op, 1))) == MODE_FLOAT
1507 || GET_MODE (XEXP (op, 1)) == DImode)
1508 return 0;
1509 return 1;
1510 default:
1511 return 0;
1515 /* Return true if the code of this rtx pattern is EQ or NE. */
1518 equality_op (op, mode)
1519 rtx op;
1520 enum machine_mode mode ATTRIBUTE_UNUSED;
1522 return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
1525 /* Return true if the code of this rtx pattern is pc or label_ref. */
1528 pc_or_label_ref (op, mode)
1529 rtx op;
1530 enum machine_mode mode ATTRIBUTE_UNUSED;
1532 return (GET_CODE (op) == PC || GET_CODE (op) == LABEL_REF);
1535 /* Output to FILE the start of the assembler file. */
1537 /* This definition must match lang_independent_options from toplev.c. */
1538 struct m88k_lang_independent_options
1540 const char *const string;
1541 int *const variable;
1542 const int on_value;
1543 const char *const description;
1546 static void output_options PARAMS ((FILE *,
1547 const struct m88k_lang_independent_options *,
1548 int,
1549 const struct m88k_lang_independent_options *,
1550 int, int, int, const char *, const char *,
1551 const char *));
1553 static int
1554 output_option (file, sep, type, name, indent, pos, max)
1555 FILE *file;
1556 const char *sep;
1557 const char *type;
1558 const char *name;
1559 const char *indent;
1560 int pos;
1561 int max;
1563 if ((long)(strlen (sep) + strlen (type) + strlen (name) + pos) > max)
1565 fprintf (file, indent);
1566 return fprintf (file, "%s%s", type, name);
1568 return pos + fprintf (file, "%s%s%s", sep, type, name);
1571 static const struct { const char *const name; const int value; } m_options[] =
1572 TARGET_SWITCHES;
1574 static void
1575 output_options (file, f_options, f_len, W_options, W_len,
1576 pos, max, sep, indent, term)
1577 FILE *file;
1578 const struct m88k_lang_independent_options *f_options;
1579 const struct m88k_lang_independent_options *W_options;
1580 int f_len, W_len;
1581 int pos;
1582 int max;
1583 const char *sep;
1584 const char *indent;
1585 const char *term;
1587 register int j;
1589 if (optimize)
1590 pos = output_option (file, sep, "-O", "", indent, pos, max);
1591 if (write_symbols != NO_DEBUG)
1592 pos = output_option (file, sep, "-g", "", indent, pos, max);
1593 if (profile_flag)
1594 pos = output_option (file, sep, "-p", "", indent, pos, max);
1595 for (j = 0; j < f_len; j++)
1596 if (*f_options[j].variable == f_options[j].on_value)
1597 pos = output_option (file, sep, "-f", f_options[j].string,
1598 indent, pos, max);
1600 for (j = 0; j < W_len; j++)
1601 if (*W_options[j].variable == W_options[j].on_value)
1602 pos = output_option (file, sep, "-W", W_options[j].string,
1603 indent, pos, max);
1605 for (j = 0; j < (long) ARRAY_SIZE (m_options); j++)
1606 if (m_options[j].name[0] != '\0'
1607 && m_options[j].value > 0
1608 && ((m_options[j].value & target_flags)
1609 == m_options[j].value))
1610 pos = output_option (file, sep, "-m", m_options[j].name,
1611 indent, pos, max);
1613 if (m88k_short_data)
1614 pos = output_option (file, sep, "-mshort-data-", m88k_short_data,
1615 indent, pos, max);
1617 fprintf (file, term);
1620 void
1621 output_file_start (file, f_options, f_len, W_options, W_len)
1622 FILE *file;
1623 const struct m88k_lang_independent_options *f_options;
1624 const struct m88k_lang_independent_options *W_options;
1625 int f_len, W_len;
1627 register int pos;
1629 ASM_FIRST_LINE (file);
1630 if (TARGET_88110
1631 && TARGET_SVR4)
1632 fprintf (file, "%s\n", REQUIRES_88110_ASM_OP);
1633 output_file_directive (file, main_input_filename);
1634 /* Switch to the data section so that the coffsem symbol
1635 isn't in the text section. */
1636 ASM_COFFSEM (file);
1638 if (TARGET_IDENTIFY_REVISION)
1640 char indent[256];
1642 time_t now = time ((time_t *)0);
1643 sprintf (indent, "]\"\n%s\"@(#)%s [", IDENT_ASM_OP, main_input_filename);
1644 fprintf (file, indent+3);
1645 pos = fprintf (file, "gcc %s, %.24s,", version_string, ctime (&now));
1646 #if 1
1647 /* ??? It would be nice to call print_switch_values here (and thereby
1648 let us delete output_options) but this is kept in until it is known
1649 whether the change in content format matters. */
1650 output_options (file, f_options, f_len, W_options, W_len,
1651 pos, 150 - strlen (indent), " ", indent, "]\"\n\n");
1652 #else
1653 fprintf (file, "]\"\n");
1654 print_switch_values (file, 0, 150 - strlen (indent),
1655 indent + 3, " ", "]\"\n");
1656 #endif
1660 /* Output an ascii string. */
1662 void
1663 output_ascii (file, opcode, max, p, size)
1664 FILE *file;
1665 const char *opcode;
1666 int max;
1667 const char *p;
1668 int size;
1670 int i;
1671 int in_escape = 0;
1673 register int num = 0;
1675 fprintf (file, "%s\"", opcode);
1676 for (i = 0; i < size; i++)
1678 register int c = (unsigned char) p[i];
1680 if (num > max)
1682 fprintf (file, "\"\n%s\"", opcode);
1683 num = 0;
1686 if (c == '\"' || c == '\\')
1688 escape:
1689 putc ('\\', file);
1690 putc (c, file);
1691 num += 2;
1692 in_escape = 0;
1694 else if (in_escape && ISDIGIT (c))
1696 /* If a digit follows an octal-escape, the VAX assembler fails
1697 to stop reading the escape after three digits. Continue to
1698 output the values as an octal-escape until a non-digit is
1699 found. */
1700 fprintf (file, "\\%03o", c);
1701 num += 4;
1703 else if ((c >= ' ' && c < 0177) || (c == '\t'))
1705 putc (c, file);
1706 num++;
1707 in_escape = 0;
1709 else
1711 switch (c)
1713 /* Some assemblers can't handle \a, \v, or \?. */
1714 case '\f': c = 'f'; goto escape;
1715 case '\b': c = 'b'; goto escape;
1716 case '\r': c = 'r'; goto escape;
1717 case '\n': c = 'n'; goto escape;
1720 fprintf (file, "\\%03o", c);
1721 num += 4;
1722 in_escape = 1;
1725 fprintf (file, "\"\n");
1728 /* Output a label (allows insn-output.c to be compiled without including
1729 m88k.c or needing to include stdio.h). */
1731 void
1732 output_label (label_number)
1733 int label_number;
1735 (*targetm.asm_out.internal_label) (asm_out_file, "L", label_number);
1738 /* Generate the assembly code for function entry.
1740 The prologue is responsible for setting up the stack frame,
1741 initializing the frame pointer register, saving registers that must be
1742 saved, and allocating SIZE additional bytes of storage for the
1743 local variables. SIZE is an integer. FILE is a stdio
1744 stream to which the assembler code should be output.
1746 The label for the beginning of the function need not be output by this
1747 macro. That has already been done when the macro is run.
1749 To determine which registers to save, the macro can refer to the array
1750 `regs_ever_live': element R is nonzero if hard register
1751 R is used anywhere within the function. This implies the
1752 function prologue should save register R, but not if it is one
1753 of the call-used registers.
1755 On machines where functions may or may not have frame-pointers, the
1756 function entry code must vary accordingly; it must set up the frame
1757 pointer if one is wanted, and not otherwise. To determine whether a
1758 frame pointer is in wanted, the macro can refer to the variable
1759 `frame_pointer_needed'. The variable's value will be 1 at run
1760 time in a function that needs a frame pointer.
1762 On machines where an argument may be passed partly in registers and
1763 partly in memory, this macro must examine the variable
1764 `current_function_pretend_args_size', and allocate that many bytes
1765 of uninitialized space on the stack just underneath the first argument
1766 arriving on the stack. (This may not be at the very end of the stack,
1767 if the calling sequence has pushed anything else since pushing the stack
1768 arguments. But usually, on such machines, nothing else has been pushed
1769 yet, because the function prologue itself does all the pushing.)
1771 If `ACCUMULATE_OUTGOING_ARGS' is defined, the variable
1772 `current_function_outgoing_args_size' contains the size in bytes
1773 required for the outgoing arguments. This macro must add that
1774 amount of uninitialized space to very bottom of the stack.
1776 The stack frame we use looks like this:
1778 caller callee
1779 |==============================================|
1780 | caller's frame |
1781 |==============================================|
1782 | [caller's outgoing memory arguments] |
1783 |==============================================|
1784 | caller's outgoing argument area (32 bytes) |
1785 sp -> |==============================================| <- ap
1786 | [local variable space] |
1787 |----------------------------------------------|
1788 | [return address (r1)] |
1789 |----------------------------------------------|
1790 | [previous frame pointer (r30)] |
1791 |==============================================| <- fp
1792 | [preserved registers (r25..r14)] |
1793 |----------------------------------------------|
1794 | [preserved registers (x29..x22)] |
1795 |==============================================|
1796 | [dynamically allocated space (alloca)] |
1797 |==============================================|
1798 | [callee's outgoing memory arguments] |
1799 |==============================================|
1800 | [callee's outgoing argument area (32 bytes)] |
1801 |==============================================| <- sp
1803 Notes:
1805 r1 and r30 must be saved if debugging.
1807 fp (if present) is located two words down from the local
1808 variable space.
1811 static void emit_add PARAMS ((rtx, rtx, int));
1812 static void preserve_registers PARAMS ((int, int));
1813 static void emit_ldst PARAMS ((int, int, enum machine_mode, int));
1814 static void output_tdesc PARAMS ((FILE *, int));
1815 static int uses_arg_area_p PARAMS ((void));
1817 static int nregs;
1818 static int nxregs;
1819 static char save_regs[FIRST_PSEUDO_REGISTER];
1820 static int frame_laid_out;
1821 static int frame_size;
1822 static int variable_args_p;
1823 static int epilogue_marked;
1824 static int prologue_marked;
1826 #define FIRST_OCS_PRESERVE_REGISTER 14
1827 #define LAST_OCS_PRESERVE_REGISTER 30
1829 #define FIRST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 22)
1830 #define LAST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 31)
1832 #define STACK_UNIT_BOUNDARY (STACK_BOUNDARY / BITS_PER_UNIT)
1833 #define ROUND_CALL_BLOCK_SIZE(BYTES) \
1834 (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1))
1836 /* Establish the position of the FP relative to the SP. This is done
1837 either during output_function_prologue() or by
1838 INITIAL_ELIMINATION_OFFSET. */
1840 void
1841 m88k_layout_frame ()
1843 int regno, sp_size;
1845 frame_laid_out++;
1847 memset ((char *) &save_regs[0], 0, sizeof (save_regs));
1848 sp_size = nregs = nxregs = 0;
1849 frame_size = get_frame_size ();
1851 /* Since profiling requires a call, make sure r1 is saved. */
1852 if (current_function_profile)
1853 save_regs[1] = 1;
1855 /* If we are producing debug information, store r1 and r30 where the
1856 debugger wants to find them (r30 at r30+0, r1 at r30+4). Space has
1857 already been reserved for r1/r30 in STARTING_FRAME_OFFSET. */
1858 if (write_symbols != NO_DEBUG && !TARGET_OCS_FRAME_POSITION)
1859 save_regs[1] = 1;
1861 /* If there is a call, alloca is used, __builtin_alloca is used, or
1862 a dynamic-sized object is defined, add the 8 additional words
1863 for the callee's argument area. The common denominator is that the
1864 FP is required. may_call_alloca only gets calls to alloca;
1865 current_function_calls_alloca gets alloca and __builtin_alloca. */
1866 if (regs_ever_live[1] || frame_pointer_needed)
1868 save_regs[1] = 1;
1869 sp_size += REG_PARM_STACK_SPACE (0);
1872 /* If we are producing PIC, save the addressing base register and r1. */
1873 if (flag_pic && current_function_uses_pic_offset_table)
1875 save_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
1876 nregs++;
1879 /* If a frame is requested, save the previous FP, and the return
1880 address (r1), so that a traceback can be done without using tdesc
1881 information. Otherwise, simply save the FP if it is used as
1882 a preserve register. */
1883 if (frame_pointer_needed)
1884 save_regs[FRAME_POINTER_REGNUM] = save_regs[1] = 1;
1885 else if (regs_ever_live[FRAME_POINTER_REGNUM])
1886 save_regs[FRAME_POINTER_REGNUM] = 1;
1888 /* Figure out which extended register(s) needs to be saved. */
1889 for (regno = FIRST_EXTENDED_REGISTER + 1; regno < FIRST_PSEUDO_REGISTER;
1890 regno++)
1891 if (regs_ever_live[regno] && ! call_used_regs[regno])
1893 save_regs[regno] = 1;
1894 nxregs++;
1897 /* Figure out which normal register(s) needs to be saved. */
1898 for (regno = 2; regno < FRAME_POINTER_REGNUM; regno++)
1899 if (regs_ever_live[regno] && ! call_used_regs[regno])
1901 save_regs[regno] = 1;
1902 nregs++;
1905 /* Achieve greatest use of double memory ops. Either we end up saving
1906 r30 or we use that slot to align the registers we do save. */
1907 if (nregs >= 2 && save_regs[1] && !save_regs[FRAME_POINTER_REGNUM])
1908 sp_size += 4;
1910 nregs += save_regs[1] + save_regs[FRAME_POINTER_REGNUM];
1911 /* if we need to align extended registers, add a word */
1912 if (nxregs > 0 && (nregs & 1) != 0)
1913 sp_size +=4;
1914 sp_size += 4 * nregs;
1915 sp_size += 8 * nxregs;
1916 sp_size += current_function_outgoing_args_size;
1918 /* The first two saved registers are placed above the new frame pointer
1919 if any. In the only case this matters, they are r1 and r30. */
1920 if (frame_pointer_needed || sp_size)
1921 m88k_fp_offset = ROUND_CALL_BLOCK_SIZE (sp_size - STARTING_FRAME_OFFSET);
1922 else
1923 m88k_fp_offset = -STARTING_FRAME_OFFSET;
1924 m88k_stack_size = m88k_fp_offset + STARTING_FRAME_OFFSET;
1926 /* First, combine m88k_stack_size and size. If m88k_stack_size is
1927 nonzero, align the frame size to 8 mod 16; otherwise align the
1928 frame size to 0 mod 16. (If stacks are 8 byte aligned, this ends
1929 up as a NOP. */
1931 int need
1932 = ((m88k_stack_size ? STACK_UNIT_BOUNDARY - STARTING_FRAME_OFFSET : 0)
1933 - (frame_size % STACK_UNIT_BOUNDARY));
1934 if (need < 0)
1935 need += STACK_UNIT_BOUNDARY;
1936 m88k_stack_size
1937 = ROUND_CALL_BLOCK_SIZE (m88k_stack_size + frame_size + need
1938 + current_function_pretend_args_size);
1942 /* Return true if this function is known to have a null prologue. */
1945 null_prologue ()
1947 if (! reload_completed)
1948 return 0;
1949 if (! frame_laid_out)
1950 m88k_layout_frame ();
1951 return (! frame_pointer_needed
1952 && nregs == 0
1953 && nxregs == 0
1954 && m88k_stack_size == 0);
1957 /* Determine if the current function has any references to the arg pointer.
1958 This is done indirectly by examining the DECL_ARGUMENTS' DECL_RTL.
1959 It is OK to return TRUE if there are no references, but FALSE must be
1960 correct. */
1962 static int
1963 uses_arg_area_p ()
1965 register tree parm;
1967 if (current_function_decl == 0
1968 || variable_args_p)
1969 return 1;
1971 for (parm = DECL_ARGUMENTS (current_function_decl);
1972 parm;
1973 parm = TREE_CHAIN (parm))
1975 if (DECL_RTL (parm) == 0
1976 || GET_CODE (DECL_RTL (parm)) == MEM)
1977 return 1;
1979 if (DECL_INCOMING_RTL (parm) == 0
1980 || GET_CODE (DECL_INCOMING_RTL (parm)) == MEM)
1981 return 1;
1983 return 0;
1986 static void
1987 m88k_output_function_prologue (stream, size)
1988 FILE *stream ATTRIBUTE_UNUSED;
1989 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
1991 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! quiet_flag && leaf_function_p ())
1992 fprintf (stderr, "$");
1994 m88k_prologue_done = 1; /* it's ok now to put out ln directives */
1997 static void
1998 m88k_output_function_end_prologue (stream)
1999 FILE *stream;
2001 if (TARGET_OCS_DEBUG_INFO && !prologue_marked)
2003 PUT_OCS_FUNCTION_START (stream);
2004 prologue_marked = 1;
2006 /* If we've already passed the start of the epilogue, say that
2007 it starts here. This marks the function as having a null body,
2008 but at a point where the return address is in a known location.
2010 Originally, I thought this couldn't happen, but the pic prologue
2011 for leaf functions ends with the instruction that restores the
2012 return address from the temporary register. If the temporary
2013 register is never used, that instruction can float all the way
2014 to the end of the function. */
2015 if (epilogue_marked)
2016 PUT_OCS_FUNCTION_END (stream);
2020 void
2021 m88k_expand_prologue ()
2023 m88k_layout_frame ();
2025 if (TARGET_OPTIMIZE_ARG_AREA
2026 && m88k_stack_size
2027 && ! uses_arg_area_p ())
2029 /* The incoming argument area is used for stack space if it is not
2030 used (or if -mno-optimize-arg-area is given). */
2031 if ((m88k_stack_size -= REG_PARM_STACK_SPACE (0)) < 0)
2032 m88k_stack_size = 0;
2035 if (m88k_stack_size)
2036 emit_add (stack_pointer_rtx, stack_pointer_rtx, -m88k_stack_size);
2038 if (nregs || nxregs)
2039 preserve_registers (m88k_fp_offset + 4, 1);
2041 if (frame_pointer_needed)
2042 emit_add (frame_pointer_rtx, stack_pointer_rtx, m88k_fp_offset);
2044 if (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM])
2046 rtx return_reg = gen_rtx_REG (SImode, 1);
2047 rtx label = gen_label_rtx ();
2048 rtx temp_reg = NULL_RTX;
2050 if (! save_regs[1])
2052 temp_reg = gen_rtx_REG (SImode, TEMP_REGNUM);
2053 emit_move_insn (temp_reg, return_reg);
2055 emit_insn (gen_locate1 (pic_offset_table_rtx, label));
2056 emit_insn (gen_locate2 (pic_offset_table_rtx, label));
2057 emit_insn (gen_addsi3 (pic_offset_table_rtx,
2058 pic_offset_table_rtx, return_reg));
2059 if (! save_regs[1])
2060 emit_move_insn (return_reg, temp_reg);
2062 if (current_function_profile)
2063 emit_insn (gen_blockage ());
2066 /* This function generates the assembly code for function exit,
2067 on machines that need it.
2069 The function epilogue should not depend on the current stack pointer!
2070 It should use the frame pointer only, if there is a frame pointer.
2071 This is mandatory because of alloca; we also take advantage of it to
2072 omit stack adjustments before returning. */
2074 static void
2075 m88k_output_function_begin_epilogue (stream)
2076 FILE *stream;
2078 if (TARGET_OCS_DEBUG_INFO && !epilogue_marked && prologue_marked)
2080 PUT_OCS_FUNCTION_END (stream);
2082 epilogue_marked = 1;
2085 static void
2086 m88k_output_function_epilogue (stream, size)
2087 FILE *stream;
2088 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
2090 rtx insn = get_last_insn ();
2092 if (TARGET_OCS_DEBUG_INFO && !epilogue_marked)
2093 PUT_OCS_FUNCTION_END (stream);
2095 /* If the last insn isn't a BARRIER, we must write a return insn. This
2096 should only happen if the function has no prologue and no body. */
2097 if (GET_CODE (insn) == NOTE)
2098 insn = prev_nonnote_insn (insn);
2099 if (insn == 0 || GET_CODE (insn) != BARRIER)
2100 fprintf (stream, "\tjmp\t %s\n", reg_names[1]);
2102 /* If the last insn is a barrier, and the insn before that is a call,
2103 then add a nop instruction so that tdesc can walk the stack correctly
2104 even though there is no epilogue. (Otherwise, the label for the
2105 end of the tdesc region ends up at the start of the next function. */
2106 if (insn && GET_CODE (insn) == BARRIER)
2108 insn = prev_nonnote_insn (insn);
2109 if (insn && GET_CODE (insn) == CALL_INSN)
2110 fprintf (stream, "\tor\t %s,%s,%s\n",reg_names[0],reg_names[0],reg_names[0]);
2113 output_short_branch_defs (stream);
2115 fprintf (stream, "\n");
2117 if (TARGET_OCS_DEBUG_INFO)
2118 output_tdesc (stream, m88k_fp_offset + 4);
2120 m88k_function_number++;
2121 m88k_prologue_done = 0; /* don't put out ln directives */
2122 variable_args_p = 0; /* has variable args */
2123 frame_laid_out = 0;
2124 epilogue_marked = 0;
2125 prologue_marked = 0;
2128 void
2129 m88k_expand_epilogue ()
2131 #if (MONITOR_GCC & 0x4) /* What are interesting prologue/epilogue values? */
2132 fprintf (stream, "; size = %d, m88k_fp_offset = %d, m88k_stack_size = %d\n",
2133 size, m88k_fp_offset, m88k_stack_size);
2134 #endif
2136 if (frame_pointer_needed)
2137 emit_add (stack_pointer_rtx, frame_pointer_rtx, -m88k_fp_offset);
2139 if (nregs || nxregs)
2140 preserve_registers (m88k_fp_offset + 4, 0);
2142 if (m88k_stack_size)
2143 emit_add (stack_pointer_rtx, stack_pointer_rtx, m88k_stack_size);
2146 /* Emit insns to set DSTREG to SRCREG + AMOUNT during the prologue or
2147 epilogue. */
2149 static void
2150 emit_add (dstreg, srcreg, amount)
2151 rtx dstreg;
2152 rtx srcreg;
2153 int amount;
2155 rtx incr = GEN_INT (abs (amount));
2157 if (! ADD_INTVAL (amount))
2159 rtx temp = gen_rtx_REG (SImode, TEMP_REGNUM);
2160 emit_move_insn (temp, incr);
2161 incr = temp;
2163 emit_insn ((amount < 0 ? gen_subsi3 : gen_addsi3) (dstreg, srcreg, incr));
2166 /* Save/restore the preserve registers. base is the highest offset from
2167 r31 at which a register is stored. store_p is true if stores are to
2168 be done; otherwise loads. */
2170 static void
2171 preserve_registers (base, store_p)
2172 int base;
2173 int store_p;
2175 int regno, offset;
2176 struct mem_op {
2177 int regno;
2178 int nregs;
2179 int offset;
2180 } mem_op[FIRST_PSEUDO_REGISTER];
2181 struct mem_op *mo_ptr = mem_op;
2183 /* The 88open OCS mandates that preserved registers be stored in
2184 increasing order. For compatibility with current practice,
2185 the order is r1, r30, then the preserve registers. */
2187 offset = base;
2188 if (save_regs[1])
2190 /* An extra word is given in this case to make best use of double
2191 memory ops. */
2192 if (nregs > 2 && !save_regs[FRAME_POINTER_REGNUM])
2193 offset -= 4;
2194 emit_ldst (store_p, 1, SImode, offset);
2195 offset -= 4;
2196 base = offset;
2199 /* Walk the registers to save recording all single memory operations. */
2200 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
2201 if (save_regs[regno])
2203 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
2205 mo_ptr->nregs = 1;
2206 mo_ptr->regno = regno;
2207 mo_ptr->offset = offset;
2208 mo_ptr++;
2209 offset -= 4;
2211 else
2213 regno--;
2214 offset -= 2*4;
2218 /* Walk the registers to save recording all double memory operations.
2219 This avoids a delay in the epilogue (ld.d/ld). */
2220 offset = base;
2221 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
2222 if (save_regs[regno])
2224 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
2226 offset -= 4;
2228 else
2230 mo_ptr->nregs = 2;
2231 mo_ptr->regno = regno-1;
2232 mo_ptr->offset = offset-4;
2233 mo_ptr++;
2234 regno--;
2235 offset -= 2*4;
2239 /* Walk the extended registers to record all memory operations. */
2240 /* Be sure the offset is double word aligned. */
2241 offset = (offset - 1) & ~7;
2242 for (regno = FIRST_PSEUDO_REGISTER - 1; regno > FIRST_EXTENDED_REGISTER;
2243 regno--)
2244 if (save_regs[regno])
2246 mo_ptr->nregs = 2;
2247 mo_ptr->regno = regno;
2248 mo_ptr->offset = offset;
2249 mo_ptr++;
2250 offset -= 2*4;
2253 mo_ptr->regno = 0;
2255 /* Output the memory operations. */
2256 for (mo_ptr = mem_op; mo_ptr->regno; mo_ptr++)
2258 if (mo_ptr->nregs)
2259 emit_ldst (store_p, mo_ptr->regno,
2260 (mo_ptr->nregs > 1 ? DImode : SImode),
2261 mo_ptr->offset);
2265 static void
2266 emit_ldst (store_p, regno, mode, offset)
2267 int store_p;
2268 int regno;
2269 enum machine_mode mode;
2270 int offset;
2272 rtx reg = gen_rtx_REG (mode, regno);
2273 rtx mem;
2275 if (SMALL_INTVAL (offset))
2277 mem = gen_rtx_MEM (mode, plus_constant (stack_pointer_rtx, offset));
2279 else
2281 /* offset is too large for immediate index must use register */
2283 rtx disp = GEN_INT (offset);
2284 rtx temp = gen_rtx_REG (SImode, TEMP_REGNUM);
2285 rtx regi = gen_rtx_PLUS (SImode, stack_pointer_rtx, temp);
2287 emit_move_insn (temp, disp);
2288 mem = gen_rtx_MEM (mode, regi);
2291 if (store_p)
2292 emit_move_insn (mem, reg);
2293 else
2294 emit_move_insn (reg, mem);
2297 /* Convert the address expression REG to a CFA offset. */
2300 m88k_debugger_offset (reg, offset)
2301 register rtx reg;
2302 register int offset;
2304 if (GET_CODE (reg) == PLUS)
2306 offset = INTVAL (XEXP (reg, 1));
2307 reg = XEXP (reg, 0);
2310 /* Put the offset in terms of the CFA (arg pointer). */
2311 if (reg == frame_pointer_rtx)
2312 offset += m88k_fp_offset - m88k_stack_size;
2313 else if (reg == stack_pointer_rtx)
2314 offset -= m88k_stack_size;
2315 else if (reg != arg_pointer_rtx)
2317 #if (MONITOR_GCC & 0x10) /* Watch for suspicious symbolic locations. */
2318 if (! (GET_CODE (reg) == REG
2319 && REGNO (reg) >= FIRST_PSEUDO_REGISTER))
2320 warning ("internal gcc error: Can't express symbolic location");
2321 #endif
2322 return 0;
2325 return offset;
2328 /* Output the 88open OCS proscribed text description information.
2329 The information is:
2330 0 8: zero
2331 0 22: info-byte-length (16 or 20 bytes)
2332 0 2: info-alignment (word 2)
2333 1 32: info-protocol (version 1 or 2(pic))
2334 2 32: starting-address (inclusive, not counting prologue)
2335 3 32: ending-address (exclusive, not counting epilog)
2336 4 8: info-variant (version 1 or 3(extended registers))
2337 4 17: register-save-mask (from register 14 to 30)
2338 4 1: zero
2339 4 1: return-address-info-discriminant
2340 4 5: frame-address-register
2341 5 32: frame-address-offset
2342 6 32: return-address-info
2343 7 32: register-save-offset
2344 8 16: extended-register-save-mask (x16 - x31)
2345 8 16: extended-register-save-offset (WORDS from register-save-offset) */
2347 static void
2348 output_tdesc (file, offset)
2349 FILE *file;
2350 int offset;
2352 int regno, i, j;
2353 long mask, return_address_info, register_save_offset;
2354 long xmask, xregister_save_offset;
2355 char buf[256];
2357 for (mask = 0, i = 0, regno = FIRST_OCS_PRESERVE_REGISTER;
2358 regno <= LAST_OCS_PRESERVE_REGISTER;
2359 regno++)
2361 mask <<= 1;
2362 if (save_regs[regno])
2364 mask |= 1;
2365 i++;
2369 for (xmask = 0, j = 0, regno = FIRST_OCS_EXTENDED_PRESERVE_REGISTER;
2370 regno <= LAST_OCS_EXTENDED_PRESERVE_REGISTER;
2371 regno++)
2373 xmask <<= 1;
2374 if (save_regs[regno])
2376 xmask |= 1;
2377 j++;
2381 if (save_regs[1])
2383 if ((nxregs > 0 || nregs > 2) && !save_regs[FRAME_POINTER_REGNUM])
2384 offset -= 4;
2385 return_address_info = - m88k_stack_size + offset;
2386 register_save_offset = return_address_info - i*4;
2388 else
2390 return_address_info = 1;
2391 register_save_offset = - m88k_stack_size + offset + 4 - i*4;
2394 xregister_save_offset = - (j * 2 + ((register_save_offset >> 2) & 1));
2396 tdesc_section ();
2398 /* 8:0,22:(20 or 16),2:2 */
2399 fprintf (file, "%s%d,%d", integer_asm_op (4, TRUE),
2400 (((xmask != 0) ? 20 : 16) << 2) | 2,
2401 flag_pic ? 2 : 1);
2403 ASM_GENERATE_INTERNAL_LABEL (buf, OCS_START_PREFIX, m88k_function_number);
2404 fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : "");
2405 ASM_GENERATE_INTERNAL_LABEL (buf, OCS_END_PREFIX, m88k_function_number);
2406 fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : "");
2408 fprintf (file, ",0x%x,0x%x,0x%lx,0x%lx",
2409 /* 8:1,17:0x%.3x,1:0,1:%d,5:%d */
2410 (int)(((xmask ? 3 : 1) << (17+1+1+5))
2411 | (mask << (1+1+5))
2412 | ((!!save_regs[1]) << 5)
2413 | (frame_pointer_needed
2414 ? FRAME_POINTER_REGNUM
2415 : STACK_POINTER_REGNUM)),
2416 (m88k_stack_size - (frame_pointer_needed ? m88k_fp_offset : 0)),
2417 return_address_info,
2418 register_save_offset);
2419 if (xmask)
2420 fprintf (file, ",0x%lx%04lx", xmask, (0xffff & xregister_save_offset));
2421 fputc ('\n', file);
2423 text_section ();
2426 /* Output assembler code to FILE to increment profiler label # LABELNO
2427 for profiling a function entry. NAME is the mcount function name
2428 (varies), SAVEP indicates whether the parameter registers need to
2429 be saved and restored. */
2431 void
2432 output_function_profiler (file, labelno, name, savep)
2433 FILE *file;
2434 int labelno;
2435 const char *name;
2436 int savep;
2438 char label[256];
2439 char dbi[256];
2440 const char *const temp = (savep ? reg_names[2] : reg_names[10]);
2442 /* Remember to update FUNCTION_PROFILER_LENGTH. */
2444 if (savep)
2446 fprintf (file, "\tsubu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2447 fprintf (file, "\tst.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2448 fprintf (file, "\tst.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2449 fprintf (file, "\tst.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2450 fprintf (file, "\tst.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2453 ASM_GENERATE_INTERNAL_LABEL (label, "LP", labelno);
2454 if (flag_pic == 2)
2456 fprintf (file, "\tor.u\t %s,%s,%shi16(%s#got_rel)\n",
2457 temp, reg_names[0], m88k_pound_sign, &label[1]);
2458 fprintf (file, "\tor\t %s,%s,%slo16(%s#got_rel)\n",
2459 temp, temp, m88k_pound_sign, &label[1]);
2460 sprintf (dbi, "\tld\t %s,%s,%s\n", temp,
2461 reg_names[PIC_OFFSET_TABLE_REGNUM], temp);
2463 else if (flag_pic)
2465 sprintf (dbi, "\tld\t %s,%s,%s#got_rel\n", temp,
2466 reg_names[PIC_OFFSET_TABLE_REGNUM], &label[1]);
2468 else
2470 fprintf (file, "\tor.u\t %s,%s,%shi16(%s)\n",
2471 temp, reg_names[0], m88k_pound_sign, &label[1]);
2472 sprintf (dbi, "\tor\t %s,%s,%slo16(%s)\n",
2473 temp, temp, m88k_pound_sign, &label[1]);
2476 if (flag_pic)
2477 fprintf (file, "\tbsr.n\t %s#plt\n", name);
2478 else
2479 fprintf (file, "\tbsr.n\t %s\n", name);
2480 fputs (dbi, file);
2482 if (savep)
2484 fprintf (file, "\tld.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2485 fprintf (file, "\tld.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2486 fprintf (file, "\tld.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2487 fprintf (file, "\tld.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2488 fprintf (file, "\taddu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2492 /* Determine whether a function argument is passed in a register, and
2493 which register.
2495 The arguments are CUM, which summarizes all the previous
2496 arguments; MODE, the machine mode of the argument; TYPE,
2497 the data type of the argument as a tree node or 0 if that is not known
2498 (which happens for C support library functions); and NAMED,
2499 which is 1 for an ordinary argument and 0 for nameless arguments that
2500 correspond to `...' in the called function's prototype.
2502 The value of the expression should either be a `reg' RTX for the
2503 hard register in which to pass the argument, or zero to pass the
2504 argument on the stack.
2506 On the m88000 the first eight words of args are normally in registers
2507 and the rest are pushed. Double precision floating point must be
2508 double word aligned (and if in a register, starting on an even
2509 register). Structures and unions which are not 4 byte, and word
2510 aligned are passed in memory rather than registers, even if they
2511 would fit completely in the registers under OCS rules.
2513 Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different.
2514 For structures that are passed in memory, but could have been
2515 passed in registers, we first load the structure into the
2516 register, and then when the last argument is passed, we store
2517 the registers into the stack locations. This fixes some bugs
2518 where GCC did not expect to have register arguments, followed
2519 by stack arguments, followed by register arguments. */
2521 struct rtx_def *
2522 m88k_function_arg (args_so_far, mode, type, named)
2523 CUMULATIVE_ARGS args_so_far;
2524 enum machine_mode mode;
2525 tree type;
2526 int named ATTRIBUTE_UNUSED;
2528 int bytes, words;
2530 if (type != 0 /* undo putting struct in register */
2531 && (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE))
2532 mode = BLKmode;
2534 if (mode == BLKmode && TARGET_WARN_PASS_STRUCT)
2535 warning ("argument #%d is a structure", args_so_far + 1);
2537 if ((args_so_far & 1) != 0
2538 && (mode == DImode || mode == DFmode
2539 || (type != 0 && TYPE_ALIGN (type) > 32)))
2540 args_so_far++;
2542 #ifdef ESKIT
2543 if (no_reg_params)
2544 return (rtx) 0; /* don't put args in registers */
2545 #endif
2547 if (type == 0 && mode == BLKmode)
2548 abort (); /* m88k_function_arg argument `type' is NULL for BLKmode. */
2550 bytes = (mode != BLKmode) ? GET_MODE_SIZE (mode) : int_size_in_bytes (type);
2551 words = (bytes + 3) / 4;
2553 if (args_so_far + words > 8)
2554 return (rtx) 0; /* args have exhausted registers */
2556 else if (mode == BLKmode
2557 && (TYPE_ALIGN (type) != BITS_PER_WORD
2558 || bytes != UNITS_PER_WORD))
2559 return (rtx) 0;
2561 return gen_rtx_REG (((mode == BLKmode) ? TYPE_MODE (type) : mode),
2562 2 + args_so_far);
2565 /* Do what is necessary for `va_start'. We look at the current function
2566 to determine if stdargs or varargs is used and spill as necessary.
2567 We return a pointer to the spill area. */
2569 struct rtx_def *
2570 m88k_builtin_saveregs ()
2572 rtx addr;
2573 tree fntype = TREE_TYPE (current_function_decl);
2574 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
2575 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2576 != void_type_node)))
2577 ? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1;
2578 int fixed;
2580 variable_args_p = 1;
2582 fixed = 0;
2583 if (GET_CODE (current_function_arg_offset_rtx) == CONST_INT)
2584 fixed = ((INTVAL (current_function_arg_offset_rtx) + argadj)
2585 / UNITS_PER_WORD);
2587 /* Allocate the register space, and store it as the __va_reg member. */
2588 addr = assign_stack_local (BLKmode, 8 * UNITS_PER_WORD, -1);
2589 set_mem_alias_set (addr, get_varargs_alias_set ());
2590 RTX_UNCHANGING_P (addr) = 1;
2591 RTX_UNCHANGING_P (XEXP (addr, 0)) = 1;
2593 /* Now store the incoming registers. */
2594 if (fixed < 8)
2595 move_block_from_reg (2 + fixed,
2596 adjust_address (addr, Pmode, fixed * UNITS_PER_WORD),
2597 8 - fixed,
2598 UNITS_PER_WORD * (8 - fixed));
2600 /* Return the address of the save area, but don't put it in a
2601 register. This fails when not optimizing and produces worse code
2602 when optimizing. */
2603 return XEXP (addr, 0);
2606 /* Define the `__builtin_va_list' type for the ABI. */
2608 tree
2609 m88k_build_va_list ()
2611 tree field_reg, field_stk, field_arg, int_ptr_type_node, record;
2613 int_ptr_type_node = build_pointer_type (integer_type_node);
2615 record = make_node (RECORD_TYPE);
2617 field_arg = build_decl (FIELD_DECL, get_identifier ("__va_arg"),
2618 integer_type_node);
2619 field_stk = build_decl (FIELD_DECL, get_identifier ("__va_stk"),
2620 int_ptr_type_node);
2621 field_reg = build_decl (FIELD_DECL, get_identifier ("__va_reg"),
2622 int_ptr_type_node);
2624 DECL_FIELD_CONTEXT (field_arg) = record;
2625 DECL_FIELD_CONTEXT (field_stk) = record;
2626 DECL_FIELD_CONTEXT (field_reg) = record;
2628 TYPE_FIELDS (record) = field_arg;
2629 TREE_CHAIN (field_arg) = field_stk;
2630 TREE_CHAIN (field_stk) = field_reg;
2632 layout_type (record);
2633 return record;
2636 /* Implement `va_start' for varargs and stdarg. */
2638 void
2639 m88k_va_start (valist, nextarg)
2640 tree valist;
2641 rtx nextarg ATTRIBUTE_UNUSED;
2643 tree field_reg, field_stk, field_arg;
2644 tree reg, stk, arg, t;
2646 field_arg = TYPE_FIELDS (va_list_type_node);
2647 field_stk = TREE_CHAIN (field_arg);
2648 field_reg = TREE_CHAIN (field_stk);
2650 arg = build (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg);
2651 stk = build (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk);
2652 reg = build (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg);
2654 /* Fill in the ARG member. */
2656 tree fntype = TREE_TYPE (current_function_decl);
2657 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
2658 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2659 != void_type_node)))
2660 ? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1;
2661 tree argsize;
2663 if (CONSTANT_P (current_function_arg_offset_rtx))
2665 int fixed = (INTVAL (current_function_arg_offset_rtx)
2666 + argadj) / UNITS_PER_WORD;
2668 argsize = build_int_2 (fixed, 0);
2670 else
2672 argsize = make_tree (integer_type_node,
2673 current_function_arg_offset_rtx);
2674 argsize = fold (build (PLUS_EXPR, integer_type_node, argsize,
2675 build_int_2 (argadj, 0)));
2676 argsize = fold (build (RSHIFT_EXPR, integer_type_node, argsize,
2677 build_int_2 (2, 0)));
2680 t = build (MODIFY_EXPR, TREE_TYPE (arg), arg, argsize);
2681 TREE_SIDE_EFFECTS (t) = 1;
2682 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2685 /* Store the arg pointer in the __va_stk member. */
2686 t = make_tree (TREE_TYPE (stk), virtual_incoming_args_rtx);
2687 t = build (MODIFY_EXPR, TREE_TYPE (stk), stk, t);
2688 TREE_SIDE_EFFECTS (t) = 1;
2689 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2691 /* Tuck the return value from __builtin_saveregs into __va_reg. */
2692 t = make_tree (TREE_TYPE (reg), expand_builtin_saveregs ());
2693 t = build (MODIFY_EXPR, TREE_TYPE (reg), reg, t);
2694 TREE_SIDE_EFFECTS (t) = 1;
2695 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2698 /* Implement `va_arg'. */
2701 m88k_va_arg (valist, type)
2702 tree valist, type;
2704 tree field_reg, field_stk, field_arg;
2705 tree reg, stk, arg, arg_align, base, t;
2706 int size, wsize, align, reg_p;
2707 rtx addr_rtx;
2709 field_arg = TYPE_FIELDS (va_list_type_node);
2710 field_stk = TREE_CHAIN (field_arg);
2711 field_reg = TREE_CHAIN (field_stk);
2713 arg = build (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg);
2714 stk = build (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk);
2715 reg = build (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg);
2717 size = int_size_in_bytes (type);
2718 wsize = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
2719 align = 1 << ((TYPE_ALIGN (type) / BITS_PER_UNIT) >> 3);
2720 reg_p = (AGGREGATE_TYPE_P (type)
2721 ? size == UNITS_PER_WORD && TYPE_ALIGN (type) == BITS_PER_WORD
2722 : size <= 2*UNITS_PER_WORD);
2724 /* Align __va_arg to the (doubleword?) boundary above. */
2725 t = build (PLUS_EXPR, TREE_TYPE (arg), arg, build_int_2 (align - 1, 0));
2726 arg_align = build (BIT_AND_EXPR, TREE_TYPE (t), t, build_int_2 (-align, -1));
2727 arg_align = save_expr (arg_align);
2729 /* Decide if we should read from stack or regs. */
2730 t = build (LT_EXPR, integer_type_node, arg_align, build_int_2 (8, 0));
2731 base = build (COND_EXPR, TREE_TYPE (reg), t, reg, stk);
2733 /* Find the final address. */
2734 t = build (PLUS_EXPR, TREE_TYPE (base), base, arg_align);
2735 addr_rtx = expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
2736 addr_rtx = copy_to_reg (addr_rtx);
2738 /* Increment __va_arg. */
2739 t = build (PLUS_EXPR, TREE_TYPE (arg), arg_align, build_int_2 (wsize, 0));
2740 t = build (MODIFY_EXPR, TREE_TYPE (arg), arg, t);
2741 TREE_SIDE_EFFECTS (t) = 1;
2742 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2744 return addr_rtx;
2747 /* If cmpsi has not been generated, emit code to do the test. Return the
2748 expression describing the test of operator OP. */
2751 emit_test (op, mode)
2752 enum rtx_code op;
2753 enum machine_mode mode;
2755 if (m88k_compare_reg == 0)
2756 emit_insn (gen_test (m88k_compare_op0, m88k_compare_op1));
2757 return (gen_rtx (op, mode, m88k_compare_reg, const0_rtx));
2760 /* Determine how to best perform cmpsi/bxx, where cmpsi has a constant
2761 operand. All tests with zero (albeit swapped) and all equality tests
2762 with a constant are done with bcnd. The remaining cases are swapped
2763 as needed. */
2765 void
2766 emit_bcnd (op, label)
2767 enum rtx_code op;
2768 rtx label;
2770 if (m88k_compare_op1 == const0_rtx)
2771 emit_jump_insn (gen_bcnd
2772 (gen_rtx (op, VOIDmode,m88k_compare_op0, const0_rtx),
2773 label));
2774 else if (m88k_compare_op0 == const0_rtx)
2775 emit_jump_insn (gen_bcnd
2776 (gen_rtx (swap_condition (op),
2777 VOIDmode, m88k_compare_op1, const0_rtx),
2778 label));
2779 else if (op != EQ && op != NE)
2780 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2781 else
2783 rtx zero = gen_reg_rtx (SImode);
2784 rtx reg, constant;
2785 int value;
2787 if (GET_CODE (m88k_compare_op1) == CONST_INT)
2789 reg = force_reg (SImode, m88k_compare_op0);
2790 constant = m88k_compare_op1;
2792 else
2794 reg = force_reg (SImode, m88k_compare_op1);
2795 constant = m88k_compare_op0;
2797 value = INTVAL (constant);
2799 /* Perform an arithmetic computation to make the compared-to value
2800 zero, but avoid loosing if the bcnd is later changed into sxx. */
2801 if (SMALL_INTVAL (value))
2802 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2803 else
2805 if (SMALL_INTVAL (-value))
2806 emit_insn (gen_addsi3 (zero, reg,
2807 GEN_INT (-value)));
2808 else
2809 emit_insn (gen_xorsi3 (zero, reg, constant));
2811 emit_jump_insn (gen_bcnd (gen_rtx (op, VOIDmode,
2812 zero, const0_rtx),
2813 label));
2818 /* Print an operand. Recognize special options, documented below. */
2820 void
2821 print_operand (file, x, code)
2822 FILE *file;
2823 rtx x;
2824 int code;
2826 enum rtx_code xc = (x ? GET_CODE (x) : UNKNOWN);
2827 register int value = (xc == CONST_INT ? INTVAL (x) : 0);
2828 static int sequencep;
2829 static int reversep;
2831 if (sequencep)
2833 if (code < 'B' || code > 'E')
2834 output_operand_lossage ("%%R not followed by %%B/C/D/E");
2835 if (reversep)
2836 xc = reverse_condition (xc);
2837 sequencep = 0;
2840 switch (code)
2842 case '*': /* addressing base register for PIC */
2843 fputs (reg_names[PIC_OFFSET_TABLE_REGNUM], file); return;
2845 case '#': /* SVR4 pound-sign syntax character (empty if SVR3) */
2846 fputs (m88k_pound_sign, file); return;
2848 case 'V': /* Output a serializing instruction as needed if the operand
2849 (assumed to be a MEM) is a volatile load. */
2850 case 'v': /* ditto for a volatile store. */
2851 if (MEM_VOLATILE_P (x) && TARGET_SERIALIZE_VOLATILE)
2853 /* The m88110 implements two FIFO queues, one for loads and
2854 one for stores. These queues mean that loads complete in
2855 their issue order as do stores. An interaction between the
2856 history buffer and the store reservation station ensures
2857 that a store will not bypass load. Finally, a load will not
2858 bypass store, but only when they reference the same address.
2860 To avoid this reordering (a load bypassing a store) for
2861 volatile references, a serializing instruction is output.
2862 We choose the fldcr instruction as it does not serialize on
2863 the m88100 so that -m88000 code will not be degraded.
2865 The mechanism below is completed by having CC_STATUS_INIT set
2866 the code to the unknown value. */
2869 hassey 6/30/93
2870 A problem with 88110 4.1 & 4.2 makes the use of fldcr for
2871 this purpose undesirable. Instead we will use tb1, this will
2872 cause serialization on the 88100 but such is life.
2875 static rtx last_addr = 0;
2876 if (code == 'V' /* Only need to serialize before a load. */
2877 && m88k_volatile_code != 'V' /* Loads complete in FIFO order. */
2878 && !(m88k_volatile_code == 'v'
2879 && GET_CODE (XEXP (x, 0)) == LO_SUM
2880 && rtx_equal_p (XEXP (XEXP (x, 0), 1), last_addr)))
2881 fprintf (file,
2882 #if 0
2883 #ifdef AS_BUG_FLDCR
2884 "fldcr\t %s,%scr63\n\t",
2885 #else
2886 "fldcr\t %s,%sfcr63\n\t",
2887 #endif
2888 reg_names[0], m88k_pound_sign);
2889 #else /* 0 */
2890 "tb1\t 1,%s,0xff\n\t", reg_names[0]);
2891 #endif /* 0 */
2892 m88k_volatile_code = code;
2893 last_addr = (GET_CODE (XEXP (x, 0)) == LO_SUM
2894 ? XEXP (XEXP (x, 0), 1) : 0);
2896 return;
2898 case 'X': /* print the upper 16 bits... */
2899 value >>= 16;
2900 case 'x': /* print the lower 16 bits of the integer constant in hex */
2901 if (xc != CONST_INT)
2902 output_operand_lossage ("invalid %%x/X value");
2903 fprintf (file, "0x%x", value & 0xffff); return;
2905 case 'H': /* print the low 16 bits of the negated integer constant */
2906 if (xc != CONST_INT)
2907 output_operand_lossage ("invalid %%H value");
2908 value = -value;
2909 case 'h': /* print the register or low 16 bits of the integer constant */
2910 if (xc == REG)
2911 goto reg;
2912 if (xc != CONST_INT)
2913 output_operand_lossage ("invalid %%h value");
2914 fprintf (file, "%d", value & 0xffff);
2915 return;
2917 case 'Q': /* print the low 8 bits of the negated integer constant */
2918 if (xc != CONST_INT)
2919 output_operand_lossage ("invalid %%Q value");
2920 value = -value;
2921 case 'q': /* print the register or low 8 bits of the integer constant */
2922 if (xc == REG)
2923 goto reg;
2924 if (xc != CONST_INT)
2925 output_operand_lossage ("invalid %%q value");
2926 fprintf (file, "%d", value & 0xff);
2927 return;
2929 case 'w': /* print the integer constant (X == 32 ? 0 : 32 - X) */
2930 if (xc != CONST_INT)
2931 output_operand_lossage ("invalid %%o value");
2932 fprintf (file, "%d", value == 32 ? 0 : 32 - value);
2933 return;
2935 case 'p': /* print the logarithm of the integer constant */
2936 if (xc != CONST_INT
2937 || (value = exact_log2 (value)) < 0)
2938 output_operand_lossage ("invalid %%p value");
2939 fprintf (file, "%d", value);
2940 return;
2942 case 'S': /* complement the value and then... */
2943 value = ~value;
2944 case 's': /* print the width and offset values forming the integer
2945 constant with a SET instruction. See integer_ok_for_set. */
2947 register unsigned mask, uval = value;
2948 register int top, bottom;
2950 if (xc != CONST_INT)
2951 output_operand_lossage ("invalid %%s/S value");
2952 /* All the "one" bits must be contiguous. If so, MASK will be
2953 a power of two or zero. */
2954 mask = (uval | (uval - 1)) + 1;
2955 if (!(uval && POWER_OF_2_or_0 (mask)))
2956 output_operand_lossage ("invalid %%s/S value");
2957 top = mask ? exact_log2 (mask) : 32;
2958 bottom = exact_log2 (uval & ~(uval - 1));
2959 fprintf (file,"%d<%d>", top - bottom, bottom);
2960 return;
2963 case 'P': /* print nothing if pc_rtx; output label_ref */
2964 if (xc == LABEL_REF)
2965 output_addr_const (file, x);
2966 else if (xc != PC)
2967 output_operand_lossage ("invalid %%P operand");
2968 return;
2970 case 'L': /* print 0 or 1 if operand is label_ref and then... */
2971 fputc (xc == LABEL_REF ? '1' : '0', file);
2972 case '.': /* print .n if delay slot is used */
2973 fputs ((final_sequence
2974 && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
2975 ? ".n\t" : "\t", file);
2976 return;
2978 case '!': /* Reverse the following condition. */
2979 sequencep++;
2980 reversep = 1;
2981 return;
2982 case 'R': /* reverse the condition of the next print_operand
2983 if operand is a label_ref. */
2984 sequencep++;
2985 reversep = (xc == LABEL_REF);
2986 return;
2988 case 'B': /* bcnd branch values */
2989 fputs (m88k_pound_sign, file);
2990 switch (xc)
2992 case EQ: fputs ("eq0", file); return;
2993 case NE: fputs ("ne0", file); return;
2994 case GT: fputs ("gt0", file); return;
2995 case LE: fputs ("le0", file); return;
2996 case LT: fputs ("lt0", file); return;
2997 case GE: fputs ("ge0", file); return;
2998 default: output_operand_lossage ("invalid %%B value");
3001 case 'C': /* bb0/bb1 branch values for comparisons */
3002 fputs (m88k_pound_sign, file);
3003 switch (xc)
3005 case EQ: fputs ("eq", file); return;
3006 case NE: fputs ("ne", file); return;
3007 case GT: fputs ("gt", file); return;
3008 case LE: fputs ("le", file); return;
3009 case LT: fputs ("lt", file); return;
3010 case GE: fputs ("ge", file); return;
3011 case GTU: fputs ("hi", file); return;
3012 case LEU: fputs ("ls", file); return;
3013 case LTU: fputs ("lo", file); return;
3014 case GEU: fputs ("hs", file); return;
3015 default: output_operand_lossage ("invalid %%C value");
3018 case 'D': /* bcnd branch values for float comparisons */
3019 switch (xc)
3021 case EQ: fputs ("0xa", file); return;
3022 case NE: fputs ("0x5", file); return;
3023 case GT: fputs (m88k_pound_sign, file);
3024 fputs ("gt0", file); return;
3025 case LE: fputs ("0xe", file); return;
3026 case LT: fputs ("0x4", file); return;
3027 case GE: fputs ("0xb", file); return;
3028 default: output_operand_lossage ("invalid %%D value");
3031 case 'E': /* bcnd branch values for special integers */
3032 switch (xc)
3034 case EQ: fputs ("0x8", file); return;
3035 case NE: fputs ("0x7", file); return;
3036 default: output_operand_lossage ("invalid %%E value");
3039 case 'd': /* second register of a two register pair */
3040 if (xc != REG)
3041 output_operand_lossage ("`%%d' operand isn't a register");
3042 fputs (reg_names[REGNO (x) + 1], file);
3043 return;
3045 case 'r': /* an immediate 0 should be represented as `r0' */
3046 if (x == const0_rtx)
3048 fputs (reg_names[0], file);
3049 return;
3051 else if (xc != REG)
3052 output_operand_lossage ("invalid %%r value");
3053 case 0:
3054 name:
3055 if (xc == REG)
3057 reg:
3058 if (REGNO (x) == ARG_POINTER_REGNUM)
3059 output_operand_lossage ("operand is r0");
3060 else
3061 fputs (reg_names[REGNO (x)], file);
3063 else if (xc == PLUS)
3064 output_address (x);
3065 else if (xc == MEM)
3066 output_address (XEXP (x, 0));
3067 else if (flag_pic && xc == UNSPEC)
3069 output_addr_const (file, XVECEXP (x, 0, 0));
3070 fputs ("#got_rel", file);
3072 else if (xc == CONST_DOUBLE)
3073 output_operand_lossage ("operand is const_double");
3074 else
3075 output_addr_const (file, x);
3076 return;
3078 case 'g': /* append #got_rel as needed */
3079 if (flag_pic && (xc == SYMBOL_REF || xc == LABEL_REF))
3081 output_addr_const (file, x);
3082 fputs ("#got_rel", file);
3083 return;
3085 goto name;
3087 case 'a': /* (standard), assume operand is an address */
3088 case 'c': /* (standard), assume operand is an immediate value */
3089 case 'l': /* (standard), assume operand is a label_ref */
3090 case 'n': /* (standard), like %c, except negate first */
3091 default:
3092 output_operand_lossage ("invalid code");
3096 void
3097 print_operand_address (file, addr)
3098 FILE *file;
3099 rtx addr;
3101 register rtx reg0, reg1, temp;
3103 switch (GET_CODE (addr))
3105 case REG:
3106 if (REGNO (addr) == ARG_POINTER_REGNUM)
3107 abort ();
3108 else
3109 fprintf (file, "%s,%s", reg_names[0], reg_names [REGNO (addr)]);
3110 break;
3112 case LO_SUM:
3113 fprintf (file, "%s,%slo16(",
3114 reg_names[REGNO (XEXP (addr, 0))], m88k_pound_sign);
3115 output_addr_const (file, XEXP (addr, 1));
3116 fputc (')', file);
3117 break;
3119 case PLUS:
3120 reg0 = XEXP (addr, 0);
3121 reg1 = XEXP (addr, 1);
3122 if (GET_CODE (reg0) == MULT || GET_CODE (reg0) == CONST_INT)
3124 rtx tmp = reg0;
3125 reg0 = reg1;
3126 reg1 = tmp;
3129 if ((REG_P (reg0) && REGNO (reg0) == ARG_POINTER_REGNUM)
3130 || (REG_P (reg1) && REGNO (reg1) == ARG_POINTER_REGNUM))
3131 abort ();
3133 else if (REG_P (reg0))
3135 if (REG_P (reg1))
3136 fprintf (file, "%s,%s",
3137 reg_names [REGNO (reg0)], reg_names [REGNO (reg1)]);
3139 else if (GET_CODE (reg1) == CONST_INT)
3140 fprintf (file, "%s,%d",
3141 reg_names [REGNO (reg0)], INTVAL (reg1));
3143 else if (GET_CODE (reg1) == MULT)
3145 rtx mreg = XEXP (reg1, 0);
3146 if (REGNO (mreg) == ARG_POINTER_REGNUM)
3147 abort ();
3149 fprintf (file, "%s[%s]", reg_names[REGNO (reg0)],
3150 reg_names[REGNO (mreg)]);
3153 else if (GET_CODE (reg1) == ZERO_EXTRACT)
3155 fprintf (file, "%s,%slo16(",
3156 reg_names[REGNO (reg0)], m88k_pound_sign);
3157 output_addr_const (file, XEXP (reg1, 0));
3158 fputc (')', file);
3161 else if (flag_pic)
3163 fprintf (file, "%s,", reg_names[REGNO (reg0)]);
3164 output_addr_const (file, reg1);
3165 fputs ("#got_rel", file);
3167 else abort ();
3170 else
3171 abort ();
3172 break;
3174 case MULT:
3175 if (REGNO (XEXP (addr, 0)) == ARG_POINTER_REGNUM)
3176 abort ();
3178 fprintf (file, "%s[%s]",
3179 reg_names[0], reg_names[REGNO (XEXP (addr, 0))]);
3180 break;
3182 case CONST_INT:
3183 fprintf (file, "%s,%d", reg_names[0], INTVAL (addr));
3184 break;
3186 default:
3187 fprintf (file, "%s,", reg_names[0]);
3188 if (SHORT_ADDRESS_P (addr, temp))
3190 fprintf (file, "%siw16(", m88k_pound_sign);
3191 output_addr_const (file, addr);
3192 fputc (')', file);
3194 else
3195 output_addr_const (file, addr);
3199 /* Return true if X is an address which needs a temporary register when
3200 reloaded while generating PIC code. */
3203 pic_address_needs_scratch (x)
3204 rtx x;
3206 /* An address which is a symbolic plus a non SMALL_INT needs a temp reg. */
3207 if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
3208 && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
3209 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
3210 && ! ADD_INT (XEXP (XEXP (x, 0), 1)))
3211 return 1;
3213 return 0;
3216 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
3217 reference and a constant. */
3220 symbolic_operand (op, mode)
3221 register rtx op;
3222 enum machine_mode mode;
3224 switch (GET_CODE (op))
3226 case SYMBOL_REF:
3227 case LABEL_REF:
3228 return 1;
3230 case CONST:
3231 op = XEXP (op, 0);
3232 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
3233 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
3234 && GET_CODE (XEXP (op, 1)) == CONST_INT);
3236 /* ??? This clause seems to be irrelevant. */
3237 case CONST_DOUBLE:
3238 return GET_MODE (op) == mode;
3240 default:
3241 return 0;
3245 #if defined (CTOR_LIST_BEGIN) && !defined (OBJECT_FORMAT_ELF)
3246 static void
3247 m88k_svr3_asm_out_constructor (symbol, priority)
3248 rtx symbol;
3249 int priority ATTRIBUTE_UNUSED;
3251 const char *name = XSTR (symbol, 0);
3253 init_section ();
3254 fprintf (asm_out_file, "\tor.u\t r13,r0,hi16(");
3255 assemble_name (asm_out_file, name);
3256 fprintf (asm_out_file, ")\n\tor\t r13,r13,lo16(");
3257 assemble_name (asm_out_file, name);
3258 fprintf (asm_out_file, ")\n\tsubu\t r31,r31,%d\n\tst\t r13,r31,%d\n",
3259 STACK_BOUNDARY / BITS_PER_UNIT, REG_PARM_STACK_SPACE (0));
3262 static void
3263 m88k_svr3_asm_out_destructor (symbol, priority)
3264 rtx symbol;
3265 int priority ATTRIBUTE_UNUSED;
3267 int i;
3269 fini_section ();
3270 assemble_integer (symbol, UNITS_PER_WORD, BITS_PER_WORD, 1);
3271 for (i = 1; i < 4; i++)
3272 assemble_integer (constm1_rtx, UNITS_PER_WORD, BITS_PER_WORD, 1);
3274 #endif /* INIT_SECTION_ASM_OP && ! OBJECT_FORMAT_ELF */
3276 static void
3277 m88k_select_section (decl, reloc, align)
3278 tree decl;
3279 int reloc;
3280 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
3282 if (TREE_CODE (decl) == STRING_CST)
3284 if (! flag_writable_strings)
3285 readonly_data_section ();
3286 else if (TREE_STRING_LENGTH (decl) <= m88k_gp_threshold)
3287 sdata_section ();
3288 else
3289 data_section ();
3291 else if (TREE_CODE (decl) == VAR_DECL)
3293 if (SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)))
3294 sdata_section ();
3295 else if ((flag_pic && reloc)
3296 || !TREE_READONLY (decl) || TREE_SIDE_EFFECTS (decl)
3297 || !DECL_INITIAL (decl)
3298 || (DECL_INITIAL (decl) != error_mark_node
3299 && !TREE_CONSTANT (DECL_INITIAL (decl))))
3300 data_section ();
3301 else
3302 readonly_data_section ();
3304 else
3305 readonly_data_section ();
3308 /* Adjust the cost of INSN based on the relationship between INSN that
3309 is dependent on DEP_INSN through the dependence LINK. The default
3310 is to make no adjustment to COST.
3312 On the m88k, ignore the cost of anti- and output-dependencies. On
3313 the m88100, a store can issue two cycles before the value (not the
3314 address) has finished computing. */
3316 static int
3317 m88k_adjust_cost (insn, link, dep, cost)
3318 rtx insn;
3319 rtx link;
3320 rtx dep;
3321 int cost;
3323 if (REG_NOTE_KIND (link) != 0)
3324 return 0; /* Anti or output dependence. */
3326 if (! TARGET_88100
3327 && recog_memoized (insn) >= 0
3328 && get_attr_type (insn) == TYPE_STORE
3329 && SET_SRC (PATTERN (insn)) == SET_DEST (PATTERN (dep)))
3330 return cost - 4; /* 88110 store reservation station. */
3332 return cost;
3335 /* For the m88k, determine if the item should go in the global pool. */
3337 static void
3338 m88k_encode_section_info (decl, rtl, first)
3339 tree decl;
3340 rtx rtl;
3341 int first ATTRIBUTE_UNUSED;
3343 if (m88k_gp_threshold > 0)
3345 if (TREE_CODE (decl) == VAR_DECL)
3347 if (!TREE_READONLY (decl) || TREE_SIDE_EFFECTS (decl))
3349 int size = int_size_in_bytes (TREE_TYPE (decl));
3351 if (size > 0 && size <= m88k_gp_threshold)
3352 SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
3355 else if (TREE_CODE (decl) == STRING_CST
3356 && flag_writable_strings
3357 && TREE_STRING_LENGTH (decl) <= m88k_gp_threshold)
3358 SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
3362 #ifdef AS_BUG_DOT_LABELS /* The assembler requires a declaration of local. */
3363 static void
3364 m88k_internal_label (stream, prefix, labelno)
3365 FILE *stream;
3366 const char *prefix;
3367 unsigned long labelno;
3369 fprintf (stream, TARGET_SVR4 ? ".%s%lu:\n%s.%s%lu\n" : "@%s%ld:\n",
3370 prefix, labelno, INTERNAL_ASM_OP, prefix, labelno);
3372 #endif
3374 static bool
3375 m88k_rtx_costs (x, code, outer_code, total)
3376 rtx x;
3377 int code, outer_code;
3378 int *total;
3380 switch (code)
3382 /* We assume that any 16 bit integer can easily be recreated, so we
3383 indicate 0 cost, in an attempt to get GCC not to optimize things
3384 like comparison against a constant. */
3385 case CONST_INT:
3386 if (SMALL_INT (x))
3387 *total = 0;
3388 else if (SMALL_INTVAL (- INTVAL (x)))
3389 *total = 2;
3390 else if (classify_integer (SImode, INTVAL (x)) != m88k_oru_or)
3391 *total = 4;
3392 else
3393 *total = 7;
3394 return true;
3396 case HIGH:
3397 *total = 2;
3398 return true;
3400 case CONST:
3401 case LABEL_REF:
3402 case SYMBOL_REF:
3403 if (flag_pic)
3404 *total = (flag_pic == 2) ? 11 : 8;
3405 else
3406 *total = 5;
3407 return true;
3409 /* The cost of CONST_DOUBLE is zero (if it can be placed in an insn, it
3410 is as good as a register; since it can't be placed in any insn, it
3411 won't do anything in cse, but it will cause expand_binop to pass the
3412 constant to the define_expands). */
3413 case CONST_DOUBLE:
3414 *total = 0;
3415 return true;
3417 case MEM:
3418 *total = COSTS_N_INSNS (2);
3419 return true;
3421 case MULT:
3422 *total = COSTS_N_INSNS (3);
3423 return true;
3425 case DIV:
3426 case UDIV:
3427 case MOD:
3428 case UMOD:
3429 *total = COSTS_N_INSNS (38);
3430 return true;
3432 default:
3433 return false;
3437 /* Provide the costs of an addressing mode that contains ADDR.
3438 If ADDR is not a valid address, its cost is irrelevant.
3439 REG+REG is made slightly more expensive because it might keep
3440 a register live for longer than we might like. */
3441 static int
3442 m88k_address_cost (x)
3443 rtx x;
3445 switch (GET_CODE (x))
3447 case REG:
3448 case LO_SUM:
3449 case MULT:
3450 return 1;
3451 case HIGH:
3452 return 2;
3453 case PLUS:
3454 return (REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1))) ? 2 : 1;
3455 default:
3456 return 4;