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)
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. */
28 #include "hard-reg-set.h"
30 #include "insn-config.h"
31 #include "conditions.h"
33 #include "insn-attr.h"
44 #include "target-def.h"
46 extern FILE *asm_out_file;
48 const char *m88k_pound_sign = ""; /* Either # for SVR4 or empty for SVR3 */
49 const char *m88k_short_data;
50 const char *m88k_version;
51 char m88k_volatile_code;
53 unsigned m88k_gp_threshold = 0;
54 int m88k_prologue_done = 0; /* Ln directives can now be emitted */
55 int m88k_function_number = 0; /* Counter unique to each function */
56 int m88k_fp_offset = 0; /* offset of frame pointer if used */
57 int m88k_stack_size = 0; /* size of allocated stack (including frame) */
60 rtx m88k_compare_reg; /* cmp output pseudo register */
61 rtx m88k_compare_op0; /* cmpsi operand 0 */
62 rtx m88k_compare_op1; /* cmpsi operand 1 */
64 enum processor_type m88k_cpu; /* target cpu */
66 static void m88k_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
67 static void m88k_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
68 static void m88k_output_function_end_prologue PARAMS ((FILE *));
69 static void m88k_output_function_begin_epilogue PARAMS ((FILE *));
70 #if defined (CTOR_LIST_BEGIN) && !defined (OBJECT_FORMAT_ELF)
71 static void m88k_svr3_asm_out_constructor PARAMS ((rtx, int));
72 static void m88k_svr3_asm_out_destructor PARAMS ((rtx, int));
74 static void m88k_select_section PARAMS ((tree, int, unsigned HOST_WIDE_INT));
75 static int m88k_adjust_cost PARAMS ((rtx, rtx, rtx, int));
76 static void m88k_encode_section_info PARAMS ((tree, int));
78 /* Initialize the GCC target structure. */
79 #undef TARGET_ASM_BYTE_OP
80 #define TARGET_ASM_BYTE_OP "\tbyte\t"
81 #undef TARGET_ASM_ALIGNED_HI_OP
82 #define TARGET_ASM_ALIGNED_HI_OP "\thalf\t"
83 #undef TARGET_ASM_ALIGNED_SI_OP
84 #define TARGET_ASM_ALIGNED_SI_OP "\tword\t"
85 #undef TARGET_ASM_UNALIGNED_HI_OP
86 #define TARGET_ASM_UNALIGNED_HI_OP "\tuahalf\t"
87 #undef TARGET_ASM_UNALIGNED_SI_OP
88 #define TARGET_ASM_UNALIGNED_SI_OP "\tuaword\t"
90 #undef TARGET_ASM_FUNCTION_PROLOGUE
91 #define TARGET_ASM_FUNCTION_PROLOGUE m88k_output_function_prologue
92 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
93 #define TARGET_ASM_FUNCTION_END_PROLOGUE m88k_output_function_end_prologue
94 #undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
95 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE m88k_output_function_begin_epilogue
96 #undef TARGET_ASM_FUNCTION_EPILOGUE
97 #define TARGET_ASM_FUNCTION_EPILOGUE m88k_output_function_epilogue
99 #undef TARGET_SCHED_ADJUST_COST
100 #define TARGET_SCHED_ADJUST_COST m88k_adjust_cost
102 #undef TARGET_ENCODE_SECTION_INFO
103 #define TARGET_ENCODE_SECTION_INFO m88k_encode_section_info
105 struct gcc_target targetm = TARGET_INITIALIZER;
107 /* Determine what instructions are needed to manufacture the integer VALUE
108 in the given MODE. */
110 enum m88k_instruction
111 classify_integer (mode, value)
112 enum machine_mode mode;
117 else if (SMALL_INTVAL (value))
119 else if (SMALL_INTVAL (-value))
121 else if (mode == HImode)
123 else if (mode == QImode)
125 else if ((value & 0xffff) == 0)
126 return m88k_oru_hi16;
127 else if (integer_ok_for_set (value))
133 /* Return the bit number in a compare word corresponding to CONDITION. */
136 condition_value (condition)
139 switch (GET_CODE (condition))
156 integer_ok_for_set (value)
157 register unsigned value;
159 /* All the "one" bits must be contiguous. If so, MASK + 1 will be
160 a power of two or zero. */
161 register unsigned mask = (value | (value - 1));
162 return (value && POWER_OF_2_or_0 (mask + 1));
166 output_load_const_int (mode, operands)
167 enum machine_mode mode;
170 static const char *const patterns[] =
178 "or.u %0,%#r0,%X1\n\tor %0,%0,%x1",
181 if (! REG_P (operands[0])
182 || GET_CODE (operands[1]) != CONST_INT)
184 return patterns[classify_integer (mode, INTVAL (operands[1]))];
187 /* These next two routines assume that floating point numbers are represented
188 in a manner which is consistent between host and target machines. */
191 output_load_const_float (operands)
194 /* These can return 0 under some circumstances when cross-compiling. */
195 operands[0] = operand_subword (operands[0], 0, 0, SFmode);
196 operands[1] = operand_subword (operands[1], 0, 0, SFmode);
198 return output_load_const_int (SImode, operands);
202 output_load_const_double (operands)
207 /* These can return zero on some cross-compilers, but there's nothing
208 we can do about it. */
209 latehalf[0] = operand_subword (operands[0], 1, 0, DFmode);
210 latehalf[1] = operand_subword (operands[1], 1, 0, DFmode);
212 operands[0] = operand_subword (operands[0], 0, 0, DFmode);
213 operands[1] = operand_subword (operands[1], 0, 0, DFmode);
215 output_asm_insn (output_load_const_int (SImode, operands), operands);
217 operands[0] = latehalf[0];
218 operands[1] = latehalf[1];
220 return output_load_const_int (SImode, operands);
224 output_load_const_dimode (operands)
229 latehalf[0] = operand_subword (operands[0], 1, 0, DImode);
230 latehalf[1] = operand_subword (operands[1], 1, 0, DImode);
232 operands[0] = operand_subword (operands[0], 0, 0, DImode);
233 operands[1] = operand_subword (operands[1], 0, 0, DImode);
235 output_asm_insn (output_load_const_int (SImode, operands), operands);
237 operands[0] = latehalf[0];
238 operands[1] = latehalf[1];
240 return output_load_const_int (SImode, operands);
243 /* Emit insns to move operands[1] into operands[0].
245 Return 1 if we have written out everything that needs to be done to
246 do the move. Otherwise, return 0 and the caller will emit the move
249 SCRATCH if non zero can be used as a scratch register for the move
250 operation. It is provided by a SECONDARY_RELOAD_* macro if needed. */
253 emit_move_sequence (operands, mode, scratch)
255 enum machine_mode mode;
258 register rtx operand0 = operands[0];
259 register rtx operand1 = operands[1];
261 if (CONSTANT_P (operand1) && flag_pic
262 && pic_address_needs_scratch (operand1))
263 operands[1] = operand1 = legitimize_address (1, operand1, 0, 0);
265 /* Handle most common case first: storing into a register. */
266 if (register_operand (operand0, mode))
268 if (register_operand (operand1, mode)
269 || (GET_CODE (operand1) == CONST_INT && SMALL_INT (operand1))
270 || GET_CODE (operand1) == HIGH
271 /* Only `general_operands' can come here, so MEM is ok. */
272 || GET_CODE (operand1) == MEM)
274 /* Run this case quickly. */
275 emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
279 else if (GET_CODE (operand0) == MEM)
281 if (register_operand (operand1, mode)
282 || (operand1 == const0_rtx && GET_MODE_SIZE (mode) <= UNITS_PER_WORD))
284 /* Run this case quickly. */
285 emit_insn (gen_rtx_SET (VOIDmode, operand0, operand1));
288 if (! reload_in_progress && ! reload_completed)
290 operands[0] = validize_mem (operand0);
291 operands[1] = operand1 = force_reg (mode, operand1);
295 /* Simplify the source if we need to. */
296 if (GET_CODE (operand1) != HIGH && immediate_operand (operand1, mode))
298 if (GET_CODE (operand1) != CONST_INT
299 && GET_CODE (operand1) != CONST_DOUBLE)
301 rtx temp = ((reload_in_progress || reload_completed)
303 operands[1] = legitimize_address (flag_pic
304 && symbolic_address_p (operand1),
305 operand1, temp, scratch);
307 operands[1] = gen_rtx_SUBREG (mode, operands[1], 0);
311 /* Now have insn-emit do whatever it normally does. */
315 /* Return a legitimate reference for ORIG (either an address or a MEM)
316 using the register REG. If PIC and the address is already
317 position-independent, use ORIG. Newly generated position-independent
318 addresses go into a reg. This is REG if non zero, otherwise we
319 allocate register(s) as necessary. If this is called during reload,
320 and we need a second temp register, then we use SCRATCH, which is
321 provided via the SECONDARY_INPUT_RELOAD_CLASS mechanism. */
324 legitimize_address (pic, orig, reg, scratch)
330 rtx addr = (GET_CODE (orig) == MEM ? XEXP (orig, 0) : orig);
336 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
340 if (reload_in_progress || reload_completed)
343 reg = gen_reg_rtx (Pmode);
348 /* If not during reload, allocate another temp reg here for
349 loading in the address, so that these instructions can be
350 optimized properly. */
351 temp = ((reload_in_progress || reload_completed)
352 ? reg : gen_reg_rtx (Pmode));
354 emit_insn (gen_rtx_SET
356 gen_rtx_HIGH (SImode,
357 gen_rtx_UNSPEC (SImode,
361 emit_insn (gen_rtx_SET
363 gen_rtx_LO_SUM (SImode, temp,
364 gen_rtx_UNSPEC (SImode,
370 new = gen_rtx_MEM (Pmode,
371 gen_rtx_PLUS (SImode,
372 pic_offset_table_rtx, addr));
374 current_function_uses_pic_offset_table = 1;
375 RTX_UNCHANGING_P (new) = 1;
376 insn = emit_move_insn (reg, new);
377 /* Put a REG_EQUAL note on this insn, so that it can be optimized
379 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig,
383 else if (GET_CODE (addr) == CONST)
387 if (GET_CODE (XEXP (addr, 0)) == PLUS
388 && XEXP (XEXP (addr, 0), 0) == pic_offset_table_rtx)
393 if (reload_in_progress || reload_completed)
396 reg = gen_reg_rtx (Pmode);
399 if (GET_CODE (XEXP (addr, 0)) != PLUS) abort ();
401 base = legitimize_address (1, XEXP (XEXP (addr, 0), 0), reg, 0);
402 addr = legitimize_address (1, XEXP (XEXP (addr, 0), 1),
403 base == reg ? 0 : reg, 0);
405 if (GET_CODE (addr) == CONST_INT)
408 return plus_constant (base, INTVAL (addr));
409 else if (! reload_in_progress && ! reload_completed)
410 addr = force_reg (Pmode, addr);
411 /* We can't create any new registers during reload, so use the
412 SCRATCH reg provided by the reload_insi pattern. */
415 emit_move_insn (scratch, addr);
419 /* If we reach here, then the SECONDARY_INPUT_RELOAD_CLASS
420 macro needs to be adjusted so that a scratch reg is provided
424 new = gen_rtx_PLUS (SImode, base, addr);
425 /* Should we set special REG_NOTEs here? */
428 else if (! SHORT_ADDRESS_P (addr, temp))
432 if (reload_in_progress || reload_completed)
435 reg = gen_reg_rtx (Pmode);
438 emit_insn (gen_rtx_SET (VOIDmode,
439 reg, gen_rtx_HIGH (SImode, addr)));
440 new = gen_rtx_LO_SUM (SImode, reg, addr);
444 && GET_CODE (orig) == MEM)
446 new = gen_rtx_MEM (GET_MODE (orig), new);
447 MEM_COPY_ATTRIBUTES (new, orig);
452 /* Support functions for code to emit a block move. There are four methods
453 used to perform the block move:
455 + call the looping library function, e.g. __movstrSI64n8
456 + call a non-looping library function, e.g. __movstrHI15x11
457 + produce an inline sequence of ld/st instructions
459 The parameters below describe the library functions produced by
462 #define MOVSTR_LOOP 64 /* __movstrSI64n68 .. __movstrSI64n8 */
463 #define MOVSTR_QI 16 /* __movstrQI16x16 .. __movstrQI16x2 */
464 #define MOVSTR_HI 48 /* __movstrHI48x48 .. __movstrHI48x4 */
465 #define MOVSTR_SI 96 /* __movstrSI96x96 .. __movstrSI96x8 */
466 #define MOVSTR_DI 96 /* __movstrDI96x96 .. __movstrDI96x16 */
467 #define MOVSTR_ODD_HI 16 /* __movstrHI15x15 .. __movstrHI15x5 */
468 #define MOVSTR_ODD_SI 48 /* __movstrSI47x47 .. __movstrSI47x11,
469 __movstrSI46x46 .. __movstrSI46x10,
470 __movstrSI45x45 .. __movstrSI45x9 */
471 #define MOVSTR_ODD_DI 48 /* __movstrDI47x47 .. __movstrDI47x23,
472 __movstrDI46x46 .. __movstrDI46x22,
473 __movstrDI45x45 .. __movstrDI45x21,
474 __movstrDI44x44 .. __movstrDI44x20,
475 __movstrDI43x43 .. __movstrDI43x19,
476 __movstrDI42x42 .. __movstrDI42x18,
477 __movstrDI41x41 .. __movstrDI41x17 */
479 /* Limits for using the non-looping movstr functions. For the m88100
480 processor, we assume the source and destination are word aligned.
481 The QImode and HImode limits are the break even points where memcpy
482 does just as well and beyond which memcpy does better. For the
483 m88110, we tend to assume double word alignment, but also analyze
484 the word aligned cases. The analysis is complicated because memcpy
485 may use the cache control instructions for better performance. */
487 #define MOVSTR_QI_LIMIT_88100 13
488 #define MOVSTR_HI_LIMIT_88100 38
489 #define MOVSTR_SI_LIMIT_88100 MOVSTR_SI
490 #define MOVSTR_DI_LIMIT_88100 MOVSTR_SI
492 #define MOVSTR_QI_LIMIT_88000 16
493 #define MOVSTR_HI_LIMIT_88000 38
494 #define MOVSTR_SI_LIMIT_88000 72
495 #define MOVSTR_DI_LIMIT_88000 72
497 #define MOVSTR_QI_LIMIT_88110 16
498 #define MOVSTR_HI_LIMIT_88110 38
499 #define MOVSTR_SI_LIMIT_88110 72
500 #define MOVSTR_DI_LIMIT_88110 72
502 static const enum machine_mode mode_from_align[] =
503 {VOIDmode, QImode, HImode, VOIDmode, SImode,
504 VOIDmode, VOIDmode, VOIDmode, DImode};
505 static const int max_from_align[] = {0, MOVSTR_QI, MOVSTR_HI, 0, MOVSTR_SI,
507 static const int all_from_align[] = {0, MOVSTR_QI, MOVSTR_ODD_HI, 0,
508 MOVSTR_ODD_SI, 0, 0, 0, MOVSTR_ODD_DI};
510 static const int best_from_align[3][9] = {
511 {0, MOVSTR_QI_LIMIT_88100, MOVSTR_HI_LIMIT_88100, 0, MOVSTR_SI_LIMIT_88100,
512 0, 0, 0, MOVSTR_DI_LIMIT_88100},
513 {0, MOVSTR_QI_LIMIT_88110, MOVSTR_HI_LIMIT_88110, 0, MOVSTR_SI_LIMIT_88110,
514 0, 0, 0, MOVSTR_DI_LIMIT_88110},
515 {0, MOVSTR_QI_LIMIT_88000, MOVSTR_HI_LIMIT_88000, 0, MOVSTR_SI_LIMIT_88000,
516 0, 0, 0, MOVSTR_DI_LIMIT_88000}
519 static void block_move_loop PARAMS ((rtx, rtx, rtx, rtx, int, int));
520 static void block_move_no_loop PARAMS ((rtx, rtx, rtx, rtx, int, int));
521 static void block_move_sequence PARAMS ((rtx, rtx, rtx, rtx, int, int, int));
522 static void output_short_branch_defs PARAMS ((FILE *));
523 static int output_option PARAMS ((FILE *, const char *, const char *,
524 const char *, const char *, int, int));
526 /* Emit code to perform a block move. Choose the best method.
528 OPERANDS[0] is the destination.
529 OPERANDS[1] is the source.
530 OPERANDS[2] is the size.
531 OPERANDS[3] is the alignment safe to use. */
534 expand_block_move (dest_mem, src_mem, operands)
539 int align = INTVAL (operands[3]);
540 int constp = (GET_CODE (operands[2]) == CONST_INT);
541 int bytes = (constp ? INTVAL (operands[2]) : 0);
542 int target = (int) m88k_cpu;
544 if (! (PROCESSOR_M88100 == 0
545 && PROCESSOR_M88110 == 1
546 && PROCESSOR_M88000 == 2))
549 if (constp && bytes <= 0)
552 /* Determine machine mode to do move with. */
553 if (align > 4 && !TARGET_88110)
555 else if (align <= 0 || align == 3)
556 abort (); /* block move invalid alignment. */
558 if (constp && bytes <= 3 * align)
559 block_move_sequence (operands[0], dest_mem, operands[1], src_mem,
562 else if (constp && bytes <= best_from_align[target][align])
563 block_move_no_loop (operands[0], dest_mem, operands[1], src_mem,
566 else if (constp && align == 4 && TARGET_88100)
567 block_move_loop (operands[0], dest_mem, operands[1], src_mem,
572 #ifdef TARGET_MEM_FUNCTIONS
573 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "memcpy"), 0,
577 convert_to_mode (TYPE_MODE (sizetype), operands[2],
578 TREE_UNSIGNED (sizetype)),
579 TYPE_MODE (sizetype));
581 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "bcopy"), 0,
585 convert_to_mode (TYPE_MODE (integer_type_node),
587 TREE_UNSIGNED (integer_type_node)),
588 TYPE_MODE (integer_type_node));
593 /* Emit code to perform a block move by calling a looping movstr library
594 function. SIZE and ALIGN are known constants. DEST and SRC are
598 block_move_loop (dest, dest_mem, src, src_mem, size, align)
604 enum machine_mode mode;
613 /* Determine machine mode to do move with. */
617 /* Determine the structure of the loop. */
618 count = size / MOVSTR_LOOP;
619 units = (size - count * MOVSTR_LOOP) / align;
624 units += MOVSTR_LOOP / align;
629 block_move_no_loop (dest, dest_mem, src, src_mem, size, align);
633 remainder = size - count * MOVSTR_LOOP - units * align;
635 mode = mode_from_align[align];
636 sprintf (entry, "__movstr%s%dn%d",
637 GET_MODE_NAME (mode), MOVSTR_LOOP, units * align);
638 entry_name = get_identifier (entry);
640 offset_rtx = GEN_INT (MOVSTR_LOOP + (1 - units) * align);
642 value_rtx = gen_rtx_MEM (MEM_IN_STRUCT_P (src_mem) ? mode : BLKmode,
644 gen_rtx_REG (Pmode, 3),
646 MEM_COPY_ATTRIBUTES (value_rtx, src_mem);
648 emit_insn (gen_call_movstrsi_loop
649 (gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (entry_name)),
650 dest, src, offset_rtx, value_rtx,
651 gen_rtx_REG (mode, ((units & 1) ? 4 : 5)),
655 block_move_sequence (gen_rtx_REG (Pmode, 2), dest_mem,
656 gen_rtx_REG (Pmode, 3), src_mem,
657 remainder, align, MOVSTR_LOOP + align);
660 /* Emit code to perform a block move by calling a non-looping library
661 function. SIZE and ALIGN are known constants. DEST and SRC are
662 registers. OFFSET is the known starting point for the output pattern. */
665 block_move_no_loop (dest, dest_mem, src, src_mem, size, align)
671 enum machine_mode mode = mode_from_align[align];
672 int units = size / align;
673 int remainder = size - units * align;
681 if (remainder && size <= all_from_align[align])
683 most = all_from_align[align] - (align - remainder);
688 most = max_from_align[align];
691 sprintf (entry, "__movstr%s%dx%d",
692 GET_MODE_NAME (mode), most, size - remainder);
693 entry_name = get_identifier (entry);
695 offset_rtx = GEN_INT (most - (size - remainder));
697 value_rtx = gen_rtx_MEM (MEM_IN_STRUCT_P (src_mem) ? mode : BLKmode,
699 gen_rtx_REG (Pmode, 3),
702 MEM_COPY_ATTRIBUTES (value_rtx, src_mem);
704 value_reg = ((((most - (size - remainder)) / align) & 1) == 0
705 ? (align == 8 ? 6 : 5) : 4);
707 emit_insn (gen_call_block_move
708 (gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (entry_name)),
709 dest, src, offset_rtx, value_rtx,
710 gen_rtx_REG (mode, value_reg)));
713 block_move_sequence (gen_rtx_REG (Pmode, 2), dest_mem,
714 gen_rtx_REG (Pmode, 3), src_mem,
715 remainder, align, most);
718 /* Emit code to perform a block move with an offset sequence of ld/st
719 instructions (..., ld 0, st 1, ld 1, st 0, ...). SIZE and ALIGN are
720 known constants. DEST and SRC are registers. OFFSET is the known
721 starting point for the output pattern. */
724 block_move_sequence (dest, dest_mem, src, src_mem, size, align, offset)
732 enum machine_mode mode[2];
737 int offset_ld = offset;
738 int offset_st = offset;
740 active[0] = active[1] = FALSE;
742 /* Establish parameters for the first load and for the second load if
743 it is known to be the same mode as the first. */
744 amount[0] = amount[1] = align;
745 mode[0] = mode_from_align[align];
746 temp[0] = gen_reg_rtx (mode[0]);
747 if (size >= 2 * align)
750 temp[1] = gen_reg_rtx (mode[1]);
761 /* Change modes as the sequence tails off. */
762 if (size < amount[next])
764 amount[next] = (size >= 4 ? 4 : (size >= 2 ? 2 : 1));
765 mode[next] = mode_from_align[amount[next]];
766 temp[next] = gen_reg_rtx (mode[next]);
768 size -= amount[next];
769 srcp = gen_rtx_MEM (MEM_IN_STRUCT_P (src_mem) ? mode[next] : BLKmode,
770 plus_constant (src, offset_ld));
772 MEM_COPY_ATTRIBUTES (srcp, src_mem);
773 emit_insn (gen_rtx_SET (VOIDmode, temp[next], srcp));
774 offset_ld += amount[next];
780 active[phase] = FALSE;
782 = gen_rtx_MEM (MEM_IN_STRUCT_P (dest_mem) ? mode[phase] : BLKmode,
783 plus_constant (dest, offset_st));
785 MEM_COPY_ATTRIBUTES (dstp, dest_mem);
786 emit_insn (gen_rtx_SET (VOIDmode, dstp, temp[phase]));
787 offset_st += amount[phase];
790 while (active[next]);
793 /* Emit the code to do an AND operation. */
796 output_and (operands)
801 if (REG_P (operands[2]))
802 return "and %0,%1,%2";
804 value = INTVAL (operands[2]);
805 if (SMALL_INTVAL (value))
806 return "mask %0,%1,%2";
807 else if ((value & 0xffff0000) == 0xffff0000)
808 return "and %0,%1,%x2";
809 else if ((value & 0xffff) == 0xffff)
810 return "and.u %0,%1,%X2";
811 else if ((value & 0xffff) == 0)
812 return "mask.u %0,%1,%X2";
813 else if (integer_ok_for_set (~value))
814 return "clr %0,%1,%S2";
816 return "and.u %0,%1,%X2\n\tand %0,%0,%x2";
819 /* Emit the code to do an inclusive OR operation. */
822 output_ior (operands)
827 if (REG_P (operands[2]))
828 return "or %0,%1,%2";
830 value = INTVAL (operands[2]);
831 if (SMALL_INTVAL (value))
832 return "or %0,%1,%2";
833 else if ((value & 0xffff) == 0)
834 return "or.u %0,%1,%X2";
835 else if (integer_ok_for_set (value))
836 return "set %0,%1,%s2";
838 return "or.u %0,%1,%X2\n\tor %0,%0,%x2";
841 /* Emit the instructions for doing an XOR. */
844 output_xor (operands)
849 if (REG_P (operands[2]))
850 return "xor %0,%1,%2";
852 value = INTVAL (operands[2]);
853 if (SMALL_INTVAL (value))
854 return "xor %0,%1,%2";
855 else if ((value & 0xffff) == 0)
856 return "xor.u %0,%1,%X2";
858 return "xor.u %0,%1,%X2\n\txor %0,%0,%x2";
861 /* Output a call. Normally this is just bsr or jsr, but this also deals with
862 accomplishing a branch after the call by incrementing r1. This requires
863 that various assembler bugs be accommodated. The 4.30 DG/UX assembler
864 requires that forward references not occur when computing the difference of
865 two labels. The [version?] Motorola assembler computes a word difference.
866 No doubt there's more to come!
868 It would seem the same idea could be used to tail call, but in this case,
869 the epilogue will be non-null. */
871 static rtx sb_name = 0;
872 static rtx sb_high = 0;
873 static rtx sb_low = 0;
876 output_call (operands, addr)
886 /* This can be generalized, but there is currently no need. */
887 if (XVECLEN (final_sequence, 0) != 2)
890 /* The address of interior insns is not computed, so use the sequence. */
891 seq_insn = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
892 jump = XVECEXP (final_sequence, 0, 1);
893 if (GET_CODE (jump) == JUMP_INSN)
897 rtx dest = XEXP (SET_SRC (PATTERN (jump)), 0);
898 int delta = 4 * (INSN_ADDRESSES (INSN_UID (dest))
899 - INSN_ADDRESSES (INSN_UID (seq_insn))
901 #if (MONITOR_GCC & 0x2) /* How often do long branches happen? */
902 if ((unsigned) (delta + 0x8000) >= 0x10000)
903 warning ("internal gcc monitor: short-branch(%x)", delta);
906 /* Delete the jump. */
907 PUT_CODE (jump, NOTE);
908 NOTE_LINE_NUMBER (jump) = NOTE_INSN_DELETED;
909 NOTE_SOURCE_FILE (jump) = 0;
911 /* We only do this optimization if -O2, modifying the value of
912 r1 in the delay slot confuses debuggers and profilers on some
915 If we loose, we must use the non-delay form. This is unlikely
916 to ever happen. If it becomes a problem, claim that a call
917 has two delay slots and only the second can be filled with
920 The 88110 can lose when a jsr.n r1 is issued and a page fault
921 occurs accessing the delay slot. So don't use jsr.n form when
924 #ifdef AS_BUG_IMMEDIATE_LABEL /* The assembler restricts immediate values. */
926 || ! ADD_INTVAL (delta * 2)
929 || ! ADD_INTVAL (delta)
931 || (REG_P (addr) && REGNO (addr) == 1))
937 ? "bsr %0#plt\n\tbr %l1"
938 : "bsr %0\n\tbr %l1"));
941 /* Output the short branch form. */
942 output_asm_insn ((REG_P (addr)
944 : (flag_pic ? "bsr.n %0#plt" : "bsr.n %0")),
949 ? "subu %#r1,%#r1,.-%l0+4"
950 : "addu %#r1,%#r1,%l0-.-4");
953 operands[0] = gen_label_rtx ();
954 operands[1] = gen_label_rtx ();
959 last = "subu %#r1,%#r1,%l0\n%l1:";
965 last = "addu %#r1,%#r1,%l0\n%l1:";
968 /* Record the values to be computed later as "def name,high-low". */
969 sb_name = gen_rtx_EXPR_LIST (VOIDmode, operands[0], sb_name);
970 sb_high = gen_rtx_EXPR_LIST (VOIDmode, high, sb_high);
971 sb_low = gen_rtx_EXPR_LIST (VOIDmode, low, sb_low);
972 #endif /* Don't USE_GAS */
979 : (flag_pic ? "bsr%. %0#plt" : "bsr%. %0"));
983 output_short_branch_defs (stream)
986 char name[256], high[256], low[256];
988 for (; sb_name && sb_high && sb_low;
989 sb_name = XEXP (sb_name, 1),
990 sb_high = XEXP (sb_high, 1),
991 sb_low = XEXP (sb_low, 1))
993 ASM_GENERATE_INTERNAL_LABEL
994 (name, "L", CODE_LABEL_NUMBER (XEXP (sb_name, 0)));
995 ASM_GENERATE_INTERNAL_LABEL
996 (high, "L", CODE_LABEL_NUMBER (XEXP (sb_high, 0)));
997 ASM_GENERATE_INTERNAL_LABEL
998 (low, "L", CODE_LABEL_NUMBER (XEXP (sb_low, 0)));
999 /* This will change as the assembler requirements become known. */
1000 fprintf (stream, "%s%s,%s-%s\n",
1001 SET_ASM_OP, &name[1], &high[1], &low[1]);
1003 if (sb_name || sb_high || sb_low)
1007 /* Return truth value of the statement that this conditional branch is likely
1008 to fall through. CONDITION, is the condition that JUMP_INSN is testing. */
1011 mostly_false_jump (jump_insn, condition)
1012 rtx jump_insn, condition;
1014 rtx target_label = JUMP_LABEL (jump_insn);
1017 /* Much of this isn't computed unless we're optimizing. */
1021 /* Determine if one path or the other leads to a return. */
1022 for (insnt = NEXT_INSN (target_label);
1024 insnt = NEXT_INSN (insnt))
1026 if (GET_CODE (insnt) == JUMP_INSN)
1028 else if (GET_CODE (insnt) == INSN
1029 && GET_CODE (PATTERN (insnt)) == SEQUENCE
1030 && GET_CODE (XVECEXP (PATTERN (insnt), 0, 0)) == JUMP_INSN)
1032 insnt = XVECEXP (PATTERN (insnt), 0, 0);
1037 && (GET_CODE (PATTERN (insnt)) == RETURN
1038 || (GET_CODE (PATTERN (insnt)) == SET
1039 && GET_CODE (SET_SRC (PATTERN (insnt))) == REG
1040 && REGNO (SET_SRC (PATTERN (insnt))) == 1)))
1043 for (insnj = NEXT_INSN (jump_insn);
1045 insnj = NEXT_INSN (insnj))
1047 if (GET_CODE (insnj) == JUMP_INSN)
1049 else if (GET_CODE (insnj) == INSN
1050 && GET_CODE (PATTERN (insnj)) == SEQUENCE
1051 && GET_CODE (XVECEXP (PATTERN (insnj), 0, 0)) == JUMP_INSN)
1053 insnj = XVECEXP (PATTERN (insnj), 0, 0);
1058 && (GET_CODE (PATTERN (insnj)) == RETURN
1059 || (GET_CODE (PATTERN (insnj)) == SET
1060 && GET_CODE (SET_SRC (PATTERN (insnj))) == REG
1061 && REGNO (SET_SRC (PATTERN (insnj))) == 1)))
1064 /* Predict to not return. */
1065 if ((insnt == 0) != (insnj == 0))
1066 return (insnt == 0);
1068 /* Predict loops to loop. */
1069 for (insnt = PREV_INSN (target_label);
1070 insnt && GET_CODE (insnt) == NOTE;
1071 insnt = PREV_INSN (insnt))
1072 if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_END)
1074 else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_BEG)
1076 else if (NOTE_LINE_NUMBER (insnt) == NOTE_INSN_LOOP_CONT)
1079 /* Predict backward branches usually take. */
1081 insnj = NEXT_INSN (PREV_INSN (XVECEXP (final_sequence, 0, 0)));
1084 if (INSN_ADDRESSES (INSN_UID (insnj))
1085 > INSN_ADDRESSES (INSN_UID (target_label)))
1088 /* EQ tests are usually false and NE tests are usually true. Also,
1089 most quantities are positive, so we can make the appropriate guesses
1090 about signed comparisons against zero. Consider unsigned comparisons
1091 to be a range check and assume quantities to be in range. */
1092 switch (GET_CODE (condition))
1095 /* Unconditional branch. */
1104 case GTU: /* Must get casesi right at least. */
1105 if (XEXP (condition, 1) == const0_rtx)
1112 if (XEXP (condition, 1) == const0_rtx)
1122 /* Return true if the operand is a power of two and is a floating
1123 point type (to optimize division by power of two into multiplication). */
1126 real_power_of_2_operand (op, mode)
1128 enum machine_mode mode ATTRIBUTE_UNUSED;
1133 struct { /* IEEE double precision format */
1135 unsigned exponent : 11;
1136 unsigned mantissa1 : 20;
1139 struct { /* IEEE double format to quick check */
1140 unsigned sign : 1; /* if it fits in a float */
1141 unsigned exponent1 : 4;
1142 unsigned exponent2 : 7;
1143 unsigned mantissa1 : 20;
1148 if (GET_MODE (op) != DFmode && GET_MODE (op) != SFmode)
1151 if (GET_CODE (op) != CONST_DOUBLE)
1154 REAL_VALUE_FROM_CONST_DOUBLE (d, op);
1155 REAL_VALUE_TO_TARGET_DOUBLE (d, u.l);
1157 if (u.s.mantissa1 != 0 || u.s.mantissa2 != 0 /* not a power of two */
1158 || u.s.exponent == 0 /* constant 0.0 */
1159 || u.s.exponent == 0x7ff /* NAN */
1160 || (u.s2.exponent1 != 0x8 && u.s2.exponent1 != 0x7))
1161 return 0; /* const won't fit in float */
1166 /* Make OP legitimate for mode MODE. Currently this only deals with DFmode
1167 operands, putting them in registers and making CONST_DOUBLE values
1168 SFmode where possible. */
1171 legitimize_operand (op, mode)
1173 enum machine_mode mode;
1179 struct { /* IEEE double precision format */
1181 unsigned exponent : 11;
1182 unsigned mantissa1 : 20;
1185 struct { /* IEEE double format to quick check */
1186 unsigned sign : 1; /* if it fits in a float */
1187 unsigned exponent1 : 4;
1188 unsigned exponent2 : 7;
1189 unsigned mantissa1 : 20;
1194 if (GET_CODE (op) == REG || mode != DFmode)
1197 if (GET_CODE (op) == CONST_DOUBLE)
1199 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
1200 REAL_VALUE_TO_TARGET_DOUBLE (r, u.l);
1201 if (u.d.exponent != 0x7ff /* NaN */
1202 && u.d.mantissa2 == 0 /* Mantissa fits */
1203 && (u.s.exponent1 == 0x8 || u.s.exponent1 == 0x7) /* Exponent fits */
1204 && (temp = simplify_unary_operation (FLOAT_TRUNCATE, SFmode,
1206 return gen_rtx_FLOAT_EXTEND (mode, force_reg (SFmode, temp));
1208 else if (register_operand (op, mode))
1211 return force_reg (mode, op);
1214 /* Return true if OP is a suitable input for a move insn. */
1217 move_operand (op, mode)
1219 enum machine_mode mode;
1221 if (register_operand (op, mode))
1223 if (GET_CODE (op) == CONST_INT)
1224 return (classify_integer (mode, INTVAL (op)) < m88k_oru_hi16);
1225 if (GET_MODE (op) != mode)
1227 if (GET_CODE (op) == SUBREG)
1228 op = SUBREG_REG (op);
1229 if (GET_CODE (op) != MEM)
1233 if (GET_CODE (op) == LO_SUM)
1234 return (REG_P (XEXP (op, 0))
1235 && symbolic_address_p (XEXP (op, 1)));
1236 return memory_address_p (mode, op);
1239 /* Return true if OP is suitable for a call insn. */
1242 call_address_operand (op, mode)
1244 enum machine_mode mode ATTRIBUTE_UNUSED;
1246 return (REG_P (op) || symbolic_address_p (op));
1249 /* Returns true if OP is either a symbol reference or a sum of a symbol
1250 reference and a constant. */
1253 symbolic_address_p (op)
1256 switch (GET_CODE (op))
1264 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
1265 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
1266 && GET_CODE (XEXP (op, 1)) == CONST_INT);
1273 /* Return true if OP is a register or const0_rtx. */
1276 reg_or_0_operand (op, mode)
1278 enum machine_mode mode;
1280 return (op == const0_rtx || register_operand (op, mode));
1283 /* Nonzero if OP is a valid second operand for an arithmetic insn. */
1286 arith_operand (op, mode)
1288 enum machine_mode mode;
1290 return (register_operand (op, mode)
1291 || (GET_CODE (op) == CONST_INT && SMALL_INT (op)));
1294 /* Return true if OP is a register or 5 bit integer. */
1297 arith5_operand (op, mode)
1299 enum machine_mode mode;
1301 return (register_operand (op, mode)
1302 || (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32));
1306 arith32_operand (op, mode)
1308 enum machine_mode mode;
1310 return (register_operand (op, mode) || GET_CODE (op) == CONST_INT);
1314 arith64_operand (op, mode)
1316 enum machine_mode mode;
1318 return (register_operand (op, mode)
1319 || GET_CODE (op) == CONST_INT
1320 || (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == VOIDmode));
1324 int5_operand (op, mode)
1326 enum machine_mode mode ATTRIBUTE_UNUSED;
1328 return (GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 32);
1332 int32_operand (op, mode)
1334 enum machine_mode mode ATTRIBUTE_UNUSED;
1336 return (GET_CODE (op) == CONST_INT);
1339 /* Return true if OP is a register or a valid immediate operand for
1343 add_operand (op, mode)
1345 enum machine_mode mode;
1347 return (register_operand (op, mode)
1348 || (GET_CODE (op) == CONST_INT && ADD_INT (op)));
1351 /* Nonzero if this is a bitmask filling the bottom bits, for optimizing and +
1352 shift left combinations into a single mak instruction. */
1358 return (value && POWER_OF_2_or_0 (value + 1));
1362 reg_or_bbx_mask_operand (op, mode)
1364 enum machine_mode mode;
1367 if (register_operand (op, mode))
1369 if (GET_CODE (op) != CONST_INT)
1372 value = INTVAL (op);
1373 if (POWER_OF_2 (value))
1379 /* Return true if OP is valid to use in the context of a floating
1380 point operation. Special case 0.0, since we can use r0. */
1383 real_or_0_operand (op, mode)
1385 enum machine_mode mode;
1387 if (mode != SFmode && mode != DFmode)
1390 return (register_operand (op, mode)
1391 || (GET_CODE (op) == CONST_DOUBLE
1392 && op == CONST0_RTX (mode)));
1395 /* Return true if OP is valid to use in the context of logic arithmetic
1396 on condition codes. */
1399 partial_ccmode_register_operand (op, mode)
1401 enum machine_mode mode ATTRIBUTE_UNUSED;
1403 return register_operand (op, CCmode) || register_operand (op, CCEVENmode);
1406 /* Return true if OP is a relational operator. */
1411 enum machine_mode mode ATTRIBUTE_UNUSED;
1413 switch (GET_CODE (op))
1432 even_relop (op, mode)
1434 enum machine_mode mode ATTRIBUTE_UNUSED;
1436 switch (GET_CODE (op))
1450 odd_relop (op, mode)
1452 enum machine_mode mode ATTRIBUTE_UNUSED;
1454 switch (GET_CODE (op))
1467 /* Return true if OP is a relational operator, and is not an unsigned
1468 relational operator. */
1471 relop_no_unsigned (op, mode)
1473 enum machine_mode mode ATTRIBUTE_UNUSED;
1475 switch (GET_CODE (op))
1483 /* @@ What is this test doing? Why not use `mode'? */
1484 if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
1485 || GET_MODE (op) == DImode
1486 || GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_FLOAT
1487 || GET_MODE (XEXP (op, 0)) == DImode
1488 || GET_MODE_CLASS (GET_MODE (XEXP (op, 1))) == MODE_FLOAT
1489 || GET_MODE (XEXP (op, 1)) == DImode)
1497 /* Return true if the code of this rtx pattern is EQ or NE. */
1500 equality_op (op, mode)
1502 enum machine_mode mode ATTRIBUTE_UNUSED;
1504 return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
1507 /* Return true if the code of this rtx pattern is pc or label_ref. */
1510 pc_or_label_ref (op, mode)
1512 enum machine_mode mode ATTRIBUTE_UNUSED;
1514 return (GET_CODE (op) == PC || GET_CODE (op) == LABEL_REF);
1517 /* Output to FILE the start of the assembler file. */
1519 /* This definition must match lang_independent_options from toplev.c. */
1520 struct m88k_lang_independent_options
1522 const char *const string;
1523 int *const variable;
1525 const char *const description;
1528 static void output_options PARAMS ((FILE *,
1529 const struct m88k_lang_independent_options *,
1531 const struct m88k_lang_independent_options *,
1532 int, int, int, const char *, const char *,
1536 output_option (file, sep, type, name, indent, pos, max)
1545 if ((long)(strlen (sep) + strlen (type) + strlen (name) + pos) > max)
1547 fprintf (file, indent);
1548 return fprintf (file, "%s%s", type, name);
1550 return pos + fprintf (file, "%s%s%s", sep, type, name);
1553 static const struct { const char *const name; const int value; } m_options[] =
1557 output_options (file, f_options, f_len, W_options, W_len,
1558 pos, max, sep, indent, term)
1560 const struct m88k_lang_independent_options *f_options;
1561 const struct m88k_lang_independent_options *W_options;
1572 pos = output_option (file, sep, "-O", "", indent, pos, max);
1573 if (write_symbols != NO_DEBUG)
1574 pos = output_option (file, sep, "-g", "", indent, pos, max);
1576 pos = output_option (file, sep, "-p", "", indent, pos, max);
1577 for (j = 0; j < f_len; j++)
1578 if (*f_options[j].variable == f_options[j].on_value)
1579 pos = output_option (file, sep, "-f", f_options[j].string,
1582 for (j = 0; j < W_len; j++)
1583 if (*W_options[j].variable == W_options[j].on_value)
1584 pos = output_option (file, sep, "-W", W_options[j].string,
1587 for (j = 0; j < (long) ARRAY_SIZE (m_options); j++)
1588 if (m_options[j].name[0] != '\0'
1589 && m_options[j].value > 0
1590 && ((m_options[j].value & target_flags)
1591 == m_options[j].value))
1592 pos = output_option (file, sep, "-m", m_options[j].name,
1595 if (m88k_short_data)
1596 pos = output_option (file, sep, "-mshort-data-", m88k_short_data,
1599 fprintf (file, term);
1603 output_file_start (file, f_options, f_len, W_options, W_len)
1605 const struct m88k_lang_independent_options *f_options;
1606 const struct m88k_lang_independent_options *W_options;
1611 ASM_FIRST_LINE (file);
1614 fprintf (file, "%s\n", REQUIRES_88110_ASM_OP);
1615 output_file_directive (file, main_input_filename);
1616 /* Switch to the data section so that the coffsem symbol
1617 isn't in the text section. */
1620 if (TARGET_IDENTIFY_REVISION)
1624 time_t now = time ((time_t *)0);
1625 sprintf (indent, "]\"\n%s\"@(#)%s [", IDENT_ASM_OP, main_input_filename);
1626 fprintf (file, indent+3);
1627 pos = fprintf (file, "gcc %s, %.24s,", version_string, ctime (&now));
1629 /* ??? It would be nice to call print_switch_values here (and thereby
1630 let us delete output_options) but this is kept in until it is known
1631 whether the change in content format matters. */
1632 output_options (file, f_options, f_len, W_options, W_len,
1633 pos, 150 - strlen (indent), " ", indent, "]\"\n\n");
1635 fprintf (file, "]\"\n");
1636 print_switch_values (file, 0, 150 - strlen (indent),
1637 indent + 3, " ", "]\"\n");
1642 /* Output an ascii string. */
1645 output_ascii (file, opcode, max, p, size)
1655 register int num = 0;
1657 fprintf (file, "%s\"", opcode);
1658 for (i = 0; i < size; i++)
1660 register int c = (unsigned char) p[i];
1664 fprintf (file, "\"\n%s\"", opcode);
1668 if (c == '\"' || c == '\\')
1676 else if (in_escape && ISDIGIT (c))
1678 /* If a digit follows an octal-escape, the VAX assembler fails
1679 to stop reading the escape after three digits. Continue to
1680 output the values as an octal-escape until a non-digit is
1682 fprintf (file, "\\%03o", c);
1685 else if ((c >= ' ' && c < 0177) || (c == '\t'))
1695 /* Some assemblers can't handle \a, \v, or \?. */
1696 case '\f': c = 'f'; goto escape;
1697 case '\b': c = 'b'; goto escape;
1698 case '\r': c = 'r'; goto escape;
1699 case '\n': c = 'n'; goto escape;
1702 fprintf (file, "\\%03o", c);
1707 fprintf (file, "\"\n");
1710 /* Output a label (allows insn-output.c to be compiled without including
1711 m88k.c or needing to include stdio.h). */
1714 output_label (label_number)
1717 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", label_number);
1720 /* Generate the assembly code for function entry.
1722 The prologue is responsible for setting up the stack frame,
1723 initializing the frame pointer register, saving registers that must be
1724 saved, and allocating SIZE additional bytes of storage for the
1725 local variables. SIZE is an integer. FILE is a stdio
1726 stream to which the assembler code should be output.
1728 The label for the beginning of the function need not be output by this
1729 macro. That has already been done when the macro is run.
1731 To determine which registers to save, the macro can refer to the array
1732 `regs_ever_live': element R is nonzero if hard register
1733 R is used anywhere within the function. This implies the
1734 function prologue should save register R, but not if it is one
1735 of the call-used registers.
1737 On machines where functions may or may not have frame-pointers, the
1738 function entry code must vary accordingly; it must set up the frame
1739 pointer if one is wanted, and not otherwise. To determine whether a
1740 frame pointer is in wanted, the macro can refer to the variable
1741 `frame_pointer_needed'. The variable's value will be 1 at run
1742 time in a function that needs a frame pointer.
1744 On machines where an argument may be passed partly in registers and
1745 partly in memory, this macro must examine the variable
1746 `current_function_pretend_args_size', and allocate that many bytes
1747 of uninitialized space on the stack just underneath the first argument
1748 arriving on the stack. (This may not be at the very end of the stack,
1749 if the calling sequence has pushed anything else since pushing the stack
1750 arguments. But usually, on such machines, nothing else has been pushed
1751 yet, because the function prologue itself does all the pushing.)
1753 If `ACCUMULATE_OUTGOING_ARGS' is defined, the variable
1754 `current_function_outgoing_args_size' contains the size in bytes
1755 required for the outgoing arguments. This macro must add that
1756 amount of uninitialized space to very bottom of the stack.
1758 The stack frame we use looks like this:
1761 |==============================================|
1763 |==============================================|
1764 | [caller's outgoing memory arguments] |
1765 |==============================================|
1766 | caller's outgoing argument area (32 bytes) |
1767 sp -> |==============================================| <- ap
1768 | [local variable space] |
1769 |----------------------------------------------|
1770 | [return address (r1)] |
1771 |----------------------------------------------|
1772 | [previous frame pointer (r30)] |
1773 |==============================================| <- fp
1774 | [preserved registers (r25..r14)] |
1775 |----------------------------------------------|
1776 | [preserved registers (x29..x22)] |
1777 |==============================================|
1778 | [dynamically allocated space (alloca)] |
1779 |==============================================|
1780 | [callee's outgoing memory arguments] |
1781 |==============================================|
1782 | [callee's outgoing argument area (32 bytes)] |
1783 |==============================================| <- sp
1787 r1 and r30 must be saved if debugging.
1789 fp (if present) is located two words down from the local
1793 static void emit_add PARAMS ((rtx, rtx, int));
1794 static void preserve_registers PARAMS ((int, int));
1795 static void emit_ldst PARAMS ((int, int, enum machine_mode, int));
1796 static void output_tdesc PARAMS ((FILE *, int));
1797 static int uses_arg_area_p PARAMS ((void));
1801 static char save_regs[FIRST_PSEUDO_REGISTER];
1802 static int frame_laid_out;
1803 static int frame_size;
1804 static int variable_args_p;
1805 static int epilogue_marked;
1806 static int prologue_marked;
1808 #define FIRST_OCS_PRESERVE_REGISTER 14
1809 #define LAST_OCS_PRESERVE_REGISTER 30
1811 #define FIRST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 22)
1812 #define LAST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 31)
1814 #define STACK_UNIT_BOUNDARY (STACK_BOUNDARY / BITS_PER_UNIT)
1815 #define ROUND_CALL_BLOCK_SIZE(BYTES) \
1816 (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1))
1818 /* Establish the position of the FP relative to the SP. This is done
1819 either during output_function_prologue() or by
1820 INITIAL_ELIMINATION_OFFSET. */
1823 m88k_layout_frame ()
1829 memset ((char *) &save_regs[0], 0, sizeof (save_regs));
1830 sp_size = nregs = nxregs = 0;
1831 frame_size = get_frame_size ();
1833 /* Since profiling requires a call, make sure r1 is saved. */
1834 if (current_function_profile)
1837 /* If we are producing debug information, store r1 and r30 where the
1838 debugger wants to find them (r30 at r30+0, r1 at r30+4). Space has
1839 already been reserved for r1/r30 in STARTING_FRAME_OFFSET. */
1840 if (write_symbols != NO_DEBUG && !TARGET_OCS_FRAME_POSITION)
1843 /* If there is a call, alloca is used, __builtin_alloca is used, or
1844 a dynamic-sized object is defined, add the 8 additional words
1845 for the callee's argument area. The common denominator is that the
1846 FP is required. may_call_alloca only gets calls to alloca;
1847 current_function_calls_alloca gets alloca and __builtin_alloca. */
1848 if (regs_ever_live[1] || frame_pointer_needed)
1851 sp_size += REG_PARM_STACK_SPACE (0);
1854 /* If we are producing PIC, save the addressing base register and r1. */
1855 if (flag_pic && current_function_uses_pic_offset_table)
1857 save_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
1861 /* If a frame is requested, save the previous FP, and the return
1862 address (r1), so that a traceback can be done without using tdesc
1863 information. Otherwise, simply save the FP if it is used as
1864 a preserve register. */
1865 if (frame_pointer_needed)
1866 save_regs[FRAME_POINTER_REGNUM] = save_regs[1] = 1;
1867 else if (regs_ever_live[FRAME_POINTER_REGNUM])
1868 save_regs[FRAME_POINTER_REGNUM] = 1;
1870 /* Figure out which extended register(s) needs to be saved. */
1871 for (regno = FIRST_EXTENDED_REGISTER + 1; regno < FIRST_PSEUDO_REGISTER;
1873 if (regs_ever_live[regno] && ! call_used_regs[regno])
1875 save_regs[regno] = 1;
1879 /* Figure out which normal register(s) needs to be saved. */
1880 for (regno = 2; regno < FRAME_POINTER_REGNUM; regno++)
1881 if (regs_ever_live[regno] && ! call_used_regs[regno])
1883 save_regs[regno] = 1;
1887 /* Achieve greatest use of double memory ops. Either we end up saving
1888 r30 or we use that slot to align the registers we do save. */
1889 if (nregs >= 2 && save_regs[1] && !save_regs[FRAME_POINTER_REGNUM])
1892 nregs += save_regs[1] + save_regs[FRAME_POINTER_REGNUM];
1893 /* if we need to align extended registers, add a word */
1894 if (nxregs > 0 && (nregs & 1) != 0)
1896 sp_size += 4 * nregs;
1897 sp_size += 8 * nxregs;
1898 sp_size += current_function_outgoing_args_size;
1900 /* The first two saved registers are placed above the new frame pointer
1901 if any. In the only case this matters, they are r1 and r30. */
1902 if (frame_pointer_needed || sp_size)
1903 m88k_fp_offset = ROUND_CALL_BLOCK_SIZE (sp_size - STARTING_FRAME_OFFSET);
1905 m88k_fp_offset = -STARTING_FRAME_OFFSET;
1906 m88k_stack_size = m88k_fp_offset + STARTING_FRAME_OFFSET;
1908 /* First, combine m88k_stack_size and size. If m88k_stack_size is
1909 non-zero, align the frame size to 8 mod 16; otherwise align the
1910 frame size to 0 mod 16. (If stacks are 8 byte aligned, this ends
1914 = ((m88k_stack_size ? STACK_UNIT_BOUNDARY - STARTING_FRAME_OFFSET : 0)
1915 - (frame_size % STACK_UNIT_BOUNDARY));
1917 need += STACK_UNIT_BOUNDARY;
1919 = ROUND_CALL_BLOCK_SIZE (m88k_stack_size + frame_size + need
1920 + current_function_pretend_args_size);
1924 /* Return true if this function is known to have a null prologue. */
1929 if (! reload_completed)
1931 if (! frame_laid_out)
1932 m88k_layout_frame ();
1933 return (! frame_pointer_needed
1936 && m88k_stack_size == 0);
1939 /* Determine if the current function has any references to the arg pointer.
1940 This is done indirectly by examining the DECL_ARGUMENTS' DECL_RTL.
1941 It is OK to return TRUE if there are no references, but FALSE must be
1949 if (current_function_decl == 0
1950 || current_function_varargs
1954 for (parm = DECL_ARGUMENTS (current_function_decl);
1956 parm = TREE_CHAIN (parm))
1958 if (DECL_RTL (parm) == 0
1959 || GET_CODE (DECL_RTL (parm)) == MEM)
1962 if (DECL_INCOMING_RTL (parm) == 0
1963 || GET_CODE (DECL_INCOMING_RTL (parm)) == MEM)
1970 m88k_output_function_prologue (stream, size)
1971 FILE *stream ATTRIBUTE_UNUSED;
1972 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
1974 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! quiet_flag && leaf_function_p ())
1975 fprintf (stderr, "$");
1977 m88k_prologue_done = 1; /* it's ok now to put out ln directives */
1981 m88k_output_function_end_prologue (stream)
1984 if (TARGET_OCS_DEBUG_INFO && !prologue_marked)
1986 PUT_OCS_FUNCTION_START (stream);
1987 prologue_marked = 1;
1989 /* If we've already passed the start of the epilogue, say that
1990 it starts here. This marks the function as having a null body,
1991 but at a point where the return address is in a known location.
1993 Originally, I thought this couldn't happen, but the pic prologue
1994 for leaf functions ends with the instruction that restores the
1995 return address from the temporary register. If the temporary
1996 register is never used, that instruction can float all the way
1997 to the end of the function. */
1998 if (epilogue_marked)
1999 PUT_OCS_FUNCTION_END (stream);
2004 m88k_expand_prologue ()
2006 m88k_layout_frame ();
2008 if (TARGET_OPTIMIZE_ARG_AREA
2010 && ! uses_arg_area_p ())
2012 /* The incoming argument area is used for stack space if it is not
2013 used (or if -mno-optimize-arg-area is given). */
2014 if ((m88k_stack_size -= REG_PARM_STACK_SPACE (0)) < 0)
2015 m88k_stack_size = 0;
2018 if (m88k_stack_size)
2019 emit_add (stack_pointer_rtx, stack_pointer_rtx, -m88k_stack_size);
2021 if (nregs || nxregs)
2022 preserve_registers (m88k_fp_offset + 4, 1);
2024 if (frame_pointer_needed)
2025 emit_add (frame_pointer_rtx, stack_pointer_rtx, m88k_fp_offset);
2027 if (flag_pic && save_regs[PIC_OFFSET_TABLE_REGNUM])
2029 rtx return_reg = gen_rtx_REG (SImode, 1);
2030 rtx label = gen_label_rtx ();
2031 rtx temp_reg = NULL_RTX;
2035 temp_reg = gen_rtx_REG (SImode, TEMP_REGNUM);
2036 emit_move_insn (temp_reg, return_reg);
2038 emit_insn (gen_locate1 (pic_offset_table_rtx, label));
2039 emit_insn (gen_locate2 (pic_offset_table_rtx, label));
2040 emit_insn (gen_addsi3 (pic_offset_table_rtx,
2041 pic_offset_table_rtx, return_reg));
2043 emit_move_insn (return_reg, temp_reg);
2045 if (current_function_profile)
2046 emit_insn (gen_blockage ());
2049 /* This function generates the assembly code for function exit,
2050 on machines that need it.
2052 The function epilogue should not depend on the current stack pointer!
2053 It should use the frame pointer only, if there is a frame pointer.
2054 This is mandatory because of alloca; we also take advantage of it to
2055 omit stack adjustments before returning. */
2058 m88k_output_function_begin_epilogue (stream)
2061 if (TARGET_OCS_DEBUG_INFO && !epilogue_marked && prologue_marked)
2063 PUT_OCS_FUNCTION_END (stream);
2065 epilogue_marked = 1;
2069 m88k_output_function_epilogue (stream, size)
2071 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
2073 rtx insn = get_last_insn ();
2075 if (TARGET_OCS_DEBUG_INFO && !epilogue_marked)
2076 PUT_OCS_FUNCTION_END (stream);
2078 /* If the last insn isn't a BARRIER, we must write a return insn. This
2079 should only happen if the function has no prologue and no body. */
2080 if (GET_CODE (insn) == NOTE)
2081 insn = prev_nonnote_insn (insn);
2082 if (insn == 0 || GET_CODE (insn) != BARRIER)
2083 fprintf (stream, "\tjmp\t %s\n", reg_names[1]);
2085 /* If the last insn is a barrier, and the insn before that is a call,
2086 then add a nop instruction so that tdesc can walk the stack correctly
2087 even though there is no epilogue. (Otherwise, the label for the
2088 end of the tdesc region ends up at the start of the next function. */
2089 if (insn && GET_CODE (insn) == BARRIER)
2091 insn = prev_nonnote_insn (insn);
2092 if (insn && GET_CODE (insn) == CALL_INSN)
2093 fprintf (stream, "\tor\t %s,%s,%s\n",reg_names[0],reg_names[0],reg_names[0]);
2096 output_short_branch_defs (stream);
2098 fprintf (stream, "\n");
2100 if (TARGET_OCS_DEBUG_INFO)
2101 output_tdesc (stream, m88k_fp_offset + 4);
2103 m88k_function_number++;
2104 m88k_prologue_done = 0; /* don't put out ln directives */
2105 variable_args_p = 0; /* has variable args */
2107 epilogue_marked = 0;
2108 prologue_marked = 0;
2112 m88k_expand_epilogue ()
2114 #if (MONITOR_GCC & 0x4) /* What are interesting prologue/epilogue values? */
2115 fprintf (stream, "; size = %d, m88k_fp_offset = %d, m88k_stack_size = %d\n",
2116 size, m88k_fp_offset, m88k_stack_size);
2119 if (frame_pointer_needed)
2120 emit_add (stack_pointer_rtx, frame_pointer_rtx, -m88k_fp_offset);
2122 if (nregs || nxregs)
2123 preserve_registers (m88k_fp_offset + 4, 0);
2125 if (m88k_stack_size)
2126 emit_add (stack_pointer_rtx, stack_pointer_rtx, m88k_stack_size);
2129 /* Emit insns to set DSTREG to SRCREG + AMOUNT during the prologue or
2133 emit_add (dstreg, srcreg, amount)
2138 rtx incr = GEN_INT (abs (amount));
2140 if (! ADD_INTVAL (amount))
2142 rtx temp = gen_rtx_REG (SImode, TEMP_REGNUM);
2143 emit_move_insn (temp, incr);
2146 emit_insn ((amount < 0 ? gen_subsi3 : gen_addsi3) (dstreg, srcreg, incr));
2149 /* Save/restore the preserve registers. base is the highest offset from
2150 r31 at which a register is stored. store_p is true if stores are to
2151 be done; otherwise loads. */
2154 preserve_registers (base, store_p)
2163 } mem_op[FIRST_PSEUDO_REGISTER];
2164 struct mem_op *mo_ptr = mem_op;
2166 /* The 88open OCS mandates that preserved registers be stored in
2167 increasing order. For compatibility with current practice,
2168 the order is r1, r30, then the preserve registers. */
2173 /* An extra word is given in this case to make best use of double
2175 if (nregs > 2 && !save_regs[FRAME_POINTER_REGNUM])
2177 emit_ldst (store_p, 1, SImode, offset);
2182 /* Walk the registers to save recording all single memory operations. */
2183 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
2184 if (save_regs[regno])
2186 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
2189 mo_ptr->regno = regno;
2190 mo_ptr->offset = offset;
2201 /* Walk the registers to save recording all double memory operations.
2202 This avoids a delay in the epilogue (ld.d/ld). */
2204 for (regno = FRAME_POINTER_REGNUM; regno > 1; regno--)
2205 if (save_regs[regno])
2207 if ((offset & 7) != 4 || (regno & 1) != 1 || !save_regs[regno-1])
2214 mo_ptr->regno = regno-1;
2215 mo_ptr->offset = offset-4;
2222 /* Walk the extended registers to record all memory operations. */
2223 /* Be sure the offset is double word aligned. */
2224 offset = (offset - 1) & ~7;
2225 for (regno = FIRST_PSEUDO_REGISTER - 1; regno > FIRST_EXTENDED_REGISTER;
2227 if (save_regs[regno])
2230 mo_ptr->regno = regno;
2231 mo_ptr->offset = offset;
2238 /* Output the memory operations. */
2239 for (mo_ptr = mem_op; mo_ptr->regno; mo_ptr++)
2242 emit_ldst (store_p, mo_ptr->regno,
2243 (mo_ptr->nregs > 1 ? DImode : SImode),
2249 emit_ldst (store_p, regno, mode, offset)
2252 enum machine_mode mode;
2255 rtx reg = gen_rtx_REG (mode, regno);
2258 if (SMALL_INTVAL (offset))
2260 mem = gen_rtx_MEM (mode, plus_constant (stack_pointer_rtx, offset));
2264 /* offset is too large for immediate index must use register */
2266 rtx disp = GEN_INT (offset);
2267 rtx temp = gen_rtx_REG (SImode, TEMP_REGNUM);
2268 rtx regi = gen_rtx_PLUS (SImode, stack_pointer_rtx, temp);
2270 emit_move_insn (temp, disp);
2271 mem = gen_rtx_MEM (mode, regi);
2275 emit_move_insn (mem, reg);
2277 emit_move_insn (reg, mem);
2280 /* Convert the address expression REG to a CFA offset. */
2283 m88k_debugger_offset (reg, offset)
2285 register int offset;
2287 if (GET_CODE (reg) == PLUS)
2289 offset = INTVAL (XEXP (reg, 1));
2290 reg = XEXP (reg, 0);
2293 /* Put the offset in terms of the CFA (arg pointer). */
2294 if (reg == frame_pointer_rtx)
2295 offset += m88k_fp_offset - m88k_stack_size;
2296 else if (reg == stack_pointer_rtx)
2297 offset -= m88k_stack_size;
2298 else if (reg != arg_pointer_rtx)
2300 #if (MONITOR_GCC & 0x10) /* Watch for suspicious symbolic locations. */
2301 if (! (GET_CODE (reg) == REG
2302 && REGNO (reg) >= FIRST_PSEUDO_REGISTER))
2303 warning ("internal gcc error: Can't express symbolic location");
2311 /* Output the 88open OCS proscribed text description information.
2314 0 22: info-byte-length (16 or 20 bytes)
2315 0 2: info-alignment (word 2)
2316 1 32: info-protocol (version 1 or 2(pic))
2317 2 32: starting-address (inclusive, not counting prologue)
2318 3 32: ending-address (exclusive, not counting epilog)
2319 4 8: info-variant (version 1 or 3(extended registers))
2320 4 17: register-save-mask (from register 14 to 30)
2322 4 1: return-address-info-discriminant
2323 4 5: frame-address-register
2324 5 32: frame-address-offset
2325 6 32: return-address-info
2326 7 32: register-save-offset
2327 8 16: extended-register-save-mask (x16 - x31)
2328 8 16: extended-register-save-offset (WORDS from register-save-offset) */
2331 output_tdesc (file, offset)
2336 long mask, return_address_info, register_save_offset;
2337 long xmask, xregister_save_offset;
2340 for (mask = 0, i = 0, regno = FIRST_OCS_PRESERVE_REGISTER;
2341 regno <= LAST_OCS_PRESERVE_REGISTER;
2345 if (save_regs[regno])
2352 for (xmask = 0, j = 0, regno = FIRST_OCS_EXTENDED_PRESERVE_REGISTER;
2353 regno <= LAST_OCS_EXTENDED_PRESERVE_REGISTER;
2357 if (save_regs[regno])
2366 if ((nxregs > 0 || nregs > 2) && !save_regs[FRAME_POINTER_REGNUM])
2368 return_address_info = - m88k_stack_size + offset;
2369 register_save_offset = return_address_info - i*4;
2373 return_address_info = 1;
2374 register_save_offset = - m88k_stack_size + offset + 4 - i*4;
2377 xregister_save_offset = - (j * 2 + ((register_save_offset >> 2) & 1));
2381 /* 8:0,22:(20 or 16),2:2 */
2382 fprintf (file, "%s%d,%d", integer_asm_op (4, TRUE),
2383 (((xmask != 0) ? 20 : 16) << 2) | 2,
2386 ASM_GENERATE_INTERNAL_LABEL (buf, OCS_START_PREFIX, m88k_function_number);
2387 fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : "");
2388 ASM_GENERATE_INTERNAL_LABEL (buf, OCS_END_PREFIX, m88k_function_number);
2389 fprintf (file, ",%s%s", buf+1, flag_pic ? "#rel" : "");
2391 fprintf (file, ",0x%x,0x%x,0x%lx,0x%lx",
2392 /* 8:1,17:0x%.3x,1:0,1:%d,5:%d */
2393 (int)(((xmask ? 3 : 1) << (17+1+1+5))
2395 | ((!!save_regs[1]) << 5)
2396 | (frame_pointer_needed
2397 ? FRAME_POINTER_REGNUM
2398 : STACK_POINTER_REGNUM)),
2399 (m88k_stack_size - (frame_pointer_needed ? m88k_fp_offset : 0)),
2400 return_address_info,
2401 register_save_offset);
2403 fprintf (file, ",0x%lx%04lx", xmask, (0xffff & xregister_save_offset));
2409 /* Output assembler code to FILE to increment profiler label # LABELNO
2410 for profiling a function entry. NAME is the mcount function name
2411 (varies), SAVEP indicates whether the parameter registers need to
2412 be saved and restored. */
2415 output_function_profiler (file, labelno, name, savep)
2423 const char *const temp = (savep ? reg_names[2] : reg_names[10]);
2425 /* Remember to update FUNCTION_PROFILER_LENGTH. */
2429 fprintf (file, "\tsubu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2430 fprintf (file, "\tst.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2431 fprintf (file, "\tst.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2432 fprintf (file, "\tst.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2433 fprintf (file, "\tst.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2436 ASM_GENERATE_INTERNAL_LABEL (label, "LP", labelno);
2439 fprintf (file, "\tor.u\t %s,%s,%shi16(%s#got_rel)\n",
2440 temp, reg_names[0], m88k_pound_sign, &label[1]);
2441 fprintf (file, "\tor\t %s,%s,%slo16(%s#got_rel)\n",
2442 temp, temp, m88k_pound_sign, &label[1]);
2443 sprintf (dbi, "\tld\t %s,%s,%s\n", temp,
2444 reg_names[PIC_OFFSET_TABLE_REGNUM], temp);
2448 sprintf (dbi, "\tld\t %s,%s,%s#got_rel\n", temp,
2449 reg_names[PIC_OFFSET_TABLE_REGNUM], &label[1]);
2453 fprintf (file, "\tor.u\t %s,%s,%shi16(%s)\n",
2454 temp, reg_names[0], m88k_pound_sign, &label[1]);
2455 sprintf (dbi, "\tor\t %s,%s,%slo16(%s)\n",
2456 temp, temp, m88k_pound_sign, &label[1]);
2460 fprintf (file, "\tbsr.n\t %s#plt\n", name);
2462 fprintf (file, "\tbsr.n\t %s\n", name);
2467 fprintf (file, "\tld.d\t %s,%s,32\n", reg_names[2], reg_names[31]);
2468 fprintf (file, "\tld.d\t %s,%s,40\n", reg_names[4], reg_names[31]);
2469 fprintf (file, "\tld.d\t %s,%s,48\n", reg_names[6], reg_names[31]);
2470 fprintf (file, "\tld.d\t %s,%s,56\n", reg_names[8], reg_names[31]);
2471 fprintf (file, "\taddu\t %s,%s,64\n", reg_names[31], reg_names[31]);
2475 /* Determine whether a function argument is passed in a register, and
2478 The arguments are CUM, which summarizes all the previous
2479 arguments; MODE, the machine mode of the argument; TYPE,
2480 the data type of the argument as a tree node or 0 if that is not known
2481 (which happens for C support library functions); and NAMED,
2482 which is 1 for an ordinary argument and 0 for nameless arguments that
2483 correspond to `...' in the called function's prototype.
2485 The value of the expression should either be a `reg' RTX for the
2486 hard register in which to pass the argument, or zero to pass the
2487 argument on the stack.
2489 On the m88000 the first eight words of args are normally in registers
2490 and the rest are pushed. Double precision floating point must be
2491 double word aligned (and if in a register, starting on an even
2492 register). Structures and unions which are not 4 byte, and word
2493 aligned are passed in memory rather than registers, even if they
2494 would fit completely in the registers under OCS rules.
2496 Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different.
2497 For structures that are passed in memory, but could have been
2498 passed in registers, we first load the structure into the
2499 register, and then when the last argument is passed, we store
2500 the registers into the stack locations. This fixes some bugs
2501 where GCC did not expect to have register arguments, followed
2502 by stack arguments, followed by register arguments. */
2505 m88k_function_arg (args_so_far, mode, type, named)
2506 CUMULATIVE_ARGS args_so_far;
2507 enum machine_mode mode;
2509 int named ATTRIBUTE_UNUSED;
2513 if (type != 0 /* undo putting struct in register */
2514 && (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE))
2517 if (mode == BLKmode && TARGET_WARN_PASS_STRUCT)
2518 warning ("argument #%d is a structure", args_so_far + 1);
2520 if ((args_so_far & 1) != 0
2521 && (mode == DImode || mode == DFmode
2522 || (type != 0 && TYPE_ALIGN (type) > 32)))
2527 return (rtx) 0; /* don't put args in registers */
2530 if (type == 0 && mode == BLKmode)
2531 abort (); /* m88k_function_arg argument `type' is NULL for BLKmode. */
2533 bytes = (mode != BLKmode) ? GET_MODE_SIZE (mode) : int_size_in_bytes (type);
2534 words = (bytes + 3) / 4;
2536 if (args_so_far + words > 8)
2537 return (rtx) 0; /* args have exhausted registers */
2539 else if (mode == BLKmode
2540 && (TYPE_ALIGN (type) != BITS_PER_WORD
2541 || bytes != UNITS_PER_WORD))
2544 return gen_rtx_REG (((mode == BLKmode) ? TYPE_MODE (type) : mode),
2548 /* Do what is necessary for `va_start'. We look at the current function
2549 to determine if stdargs or varargs is used and spill as necessary.
2550 We return a pointer to the spill area. */
2553 m88k_builtin_saveregs ()
2556 tree fntype = TREE_TYPE (current_function_decl);
2557 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
2558 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2559 != void_type_node)))
2560 ? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1;
2563 variable_args_p = 1;
2566 if (GET_CODE (current_function_arg_offset_rtx) == CONST_INT)
2567 fixed = ((INTVAL (current_function_arg_offset_rtx) + argadj)
2570 /* Allocate the register space, and store it as the __va_reg member. */
2571 addr = assign_stack_local (BLKmode, 8 * UNITS_PER_WORD, -1);
2572 set_mem_alias_set (addr, get_varargs_alias_set ());
2573 RTX_UNCHANGING_P (addr) = 1;
2574 RTX_UNCHANGING_P (XEXP (addr, 0)) = 1;
2576 /* Now store the incoming registers. */
2578 move_block_from_reg (2 + fixed,
2579 adjust_address (addr, Pmode, fixed * UNITS_PER_WORD),
2581 UNITS_PER_WORD * (8 - fixed));
2583 /* Return the address of the save area, but don't put it in a
2584 register. This fails when not optimizing and produces worse code
2586 return XEXP (addr, 0);
2589 /* Define the `__builtin_va_list' type for the ABI. */
2592 m88k_build_va_list ()
2594 tree field_reg, field_stk, field_arg, int_ptr_type_node, record;
2596 int_ptr_type_node = build_pointer_type (integer_type_node);
2598 record = make_node (RECORD_TYPE);
2600 field_arg = build_decl (FIELD_DECL, get_identifier ("__va_arg"),
2602 field_stk = build_decl (FIELD_DECL, get_identifier ("__va_stk"),
2604 field_reg = build_decl (FIELD_DECL, get_identifier ("__va_reg"),
2607 DECL_FIELD_CONTEXT (field_arg) = record;
2608 DECL_FIELD_CONTEXT (field_stk) = record;
2609 DECL_FIELD_CONTEXT (field_reg) = record;
2611 TYPE_FIELDS (record) = field_arg;
2612 TREE_CHAIN (field_arg) = field_stk;
2613 TREE_CHAIN (field_stk) = field_reg;
2615 layout_type (record);
2619 /* Implement `va_start' for varargs and stdarg. */
2622 m88k_va_start (stdarg_p, valist, nextarg)
2623 int stdarg_p ATTRIBUTE_UNUSED;
2625 rtx nextarg ATTRIBUTE_UNUSED;
2627 tree field_reg, field_stk, field_arg;
2628 tree reg, stk, arg, t;
2630 field_arg = TYPE_FIELDS (va_list_type_node);
2631 field_stk = TREE_CHAIN (field_arg);
2632 field_reg = TREE_CHAIN (field_stk);
2634 arg = build (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg);
2635 stk = build (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk);
2636 reg = build (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg);
2638 /* Fill in the ARG member. */
2640 tree fntype = TREE_TYPE (current_function_decl);
2641 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
2642 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
2643 != void_type_node)))
2644 ? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1;
2647 if (CONSTANT_P (current_function_arg_offset_rtx))
2649 int fixed = (INTVAL (current_function_arg_offset_rtx)
2650 + argadj) / UNITS_PER_WORD;
2652 argsize = build_int_2 (fixed, 0);
2656 argsize = make_tree (integer_type_node,
2657 current_function_arg_offset_rtx);
2658 argsize = fold (build (PLUS_EXPR, integer_type_node, argsize,
2659 build_int_2 (argadj, 0)));
2660 argsize = fold (build (RSHIFT_EXPR, integer_type_node, argsize,
2661 build_int_2 (2, 0)));
2664 t = build (MODIFY_EXPR, TREE_TYPE (arg), arg, argsize);
2665 TREE_SIDE_EFFECTS (t) = 1;
2666 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2669 /* Store the arg pointer in the __va_stk member. */
2670 t = make_tree (TREE_TYPE (stk), virtual_incoming_args_rtx);
2671 t = build (MODIFY_EXPR, TREE_TYPE (stk), stk, t);
2672 TREE_SIDE_EFFECTS (t) = 1;
2673 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2675 /* Tuck the return value from __builtin_saveregs into __va_reg. */
2676 t = make_tree (TREE_TYPE (reg), expand_builtin_saveregs ());
2677 t = build (MODIFY_EXPR, TREE_TYPE (reg), reg, t);
2678 TREE_SIDE_EFFECTS (t) = 1;
2679 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2682 /* Implement `va_arg'. */
2685 m88k_va_arg (valist, type)
2688 tree field_reg, field_stk, field_arg;
2689 tree reg, stk, arg, arg_align, base, t;
2690 int size, wsize, align, reg_p;
2693 field_arg = TYPE_FIELDS (va_list_type_node);
2694 field_stk = TREE_CHAIN (field_arg);
2695 field_reg = TREE_CHAIN (field_stk);
2697 arg = build (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg);
2698 stk = build (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk);
2699 reg = build (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg);
2701 size = int_size_in_bytes (type);
2702 wsize = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
2703 align = 1 << ((TYPE_ALIGN (type) / BITS_PER_UNIT) >> 3);
2704 reg_p = (AGGREGATE_TYPE_P (type)
2705 ? size == UNITS_PER_WORD && TYPE_ALIGN (type) == BITS_PER_WORD
2706 : size <= 2*UNITS_PER_WORD);
2708 /* Align __va_arg to the (doubleword?) boundary above. */
2709 t = build (PLUS_EXPR, TREE_TYPE (arg), arg, build_int_2 (align - 1, 0));
2710 arg_align = build (BIT_AND_EXPR, TREE_TYPE (t), t, build_int_2 (-align, -1));
2711 arg_align = save_expr (arg_align);
2713 /* Decide if we should read from stack or regs. */
2714 t = build (LT_EXPR, integer_type_node, arg_align, build_int_2 (8, 0));
2715 base = build (COND_EXPR, TREE_TYPE (reg), t, reg, stk);
2717 /* Find the final address. */
2718 t = build (PLUS_EXPR, TREE_TYPE (base), base, arg_align);
2719 addr_rtx = expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
2720 addr_rtx = copy_to_reg (addr_rtx);
2722 /* Increment __va_arg. */
2723 t = build (PLUS_EXPR, TREE_TYPE (arg), arg_align, build_int_2 (wsize, 0));
2724 t = build (MODIFY_EXPR, TREE_TYPE (arg), arg, t);
2725 TREE_SIDE_EFFECTS (t) = 1;
2726 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
2731 /* If cmpsi has not been generated, emit code to do the test. Return the
2732 expression describing the test of operator OP. */
2735 emit_test (op, mode)
2737 enum machine_mode mode;
2739 if (m88k_compare_reg == 0)
2740 emit_insn (gen_test (m88k_compare_op0, m88k_compare_op1));
2741 return (gen_rtx (op, mode, m88k_compare_reg, const0_rtx));
2744 /* Determine how to best perform cmpsi/bxx, where cmpsi has a constant
2745 operand. All tests with zero (albeit swapped) and all equality tests
2746 with a constant are done with bcnd. The remaining cases are swapped
2750 emit_bcnd (op, label)
2754 if (m88k_compare_op1 == const0_rtx)
2755 emit_jump_insn (gen_bcnd
2756 (gen_rtx (op, VOIDmode,m88k_compare_op0, const0_rtx),
2758 else if (m88k_compare_op0 == const0_rtx)
2759 emit_jump_insn (gen_bcnd
2760 (gen_rtx (swap_condition (op),
2761 VOIDmode, m88k_compare_op1, const0_rtx),
2763 else if (op != EQ && op != NE)
2764 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2767 rtx zero = gen_reg_rtx (SImode);
2771 if (GET_CODE (m88k_compare_op1) == CONST_INT)
2773 reg = force_reg (SImode, m88k_compare_op0);
2774 constant = m88k_compare_op1;
2778 reg = force_reg (SImode, m88k_compare_op1);
2779 constant = m88k_compare_op0;
2781 value = INTVAL (constant);
2783 /* Perform an arithmetic computation to make the compared-to value
2784 zero, but avoid loosing if the bcnd is later changed into sxx. */
2785 if (SMALL_INTVAL (value))
2786 emit_jump_insn (gen_bxx (emit_test (op, VOIDmode), label));
2789 if (SMALL_INTVAL (-value))
2790 emit_insn (gen_addsi3 (zero, reg,
2793 emit_insn (gen_xorsi3 (zero, reg, constant));
2795 emit_jump_insn (gen_bcnd (gen_rtx (op, VOIDmode,
2802 /* Print an operand. Recognize special options, documented below. */
2805 print_operand (file, x, code)
2810 enum rtx_code xc = (x ? GET_CODE (x) : UNKNOWN);
2811 register int value = (xc == CONST_INT ? INTVAL (x) : 0);
2812 static int sequencep;
2813 static int reversep;
2817 if (code < 'B' || code > 'E')
2818 output_operand_lossage ("%%R not followed by %%B/C/D/E");
2820 xc = reverse_condition (xc);
2826 case '*': /* addressing base register for PIC */
2827 fputs (reg_names[PIC_OFFSET_TABLE_REGNUM], file); return;
2829 case '#': /* SVR4 pound-sign syntax character (empty if SVR3) */
2830 fputs (m88k_pound_sign, file); return;
2832 case 'V': /* Output a serializing instruction as needed if the operand
2833 (assumed to be a MEM) is a volatile load. */
2834 case 'v': /* ditto for a volatile store. */
2835 if (MEM_VOLATILE_P (x) && TARGET_SERIALIZE_VOLATILE)
2837 /* The m88110 implements two FIFO queues, one for loads and
2838 one for stores. These queues mean that loads complete in
2839 their issue order as do stores. An interaction between the
2840 history buffer and the store reservation station ensures
2841 that a store will not bypass load. Finally, a load will not
2842 bypass store, but only when they reference the same address.
2844 To avoid this reordering (a load bypassing a store) for
2845 volatile references, a serializing instruction is output.
2846 We choose the fldcr instruction as it does not serialize on
2847 the m88100 so that -m88000 code will not be degraded.
2849 The mechanism below is completed by having CC_STATUS_INIT set
2850 the code to the unknown value. */
2854 A problem with 88110 4.1 & 4.2 makes the use of fldcr for
2855 this purpose undesirable. Instead we will use tb1, this will
2856 cause serialization on the 88100 but such is life.
2859 static rtx last_addr = 0;
2860 if (code == 'V' /* Only need to serialize before a load. */
2861 && m88k_volatile_code != 'V' /* Loads complete in FIFO order. */
2862 && !(m88k_volatile_code == 'v'
2863 && GET_CODE (XEXP (x, 0)) == LO_SUM
2864 && rtx_equal_p (XEXP (XEXP (x, 0), 1), last_addr)))
2868 "fldcr\t %s,%scr63\n\t",
2870 "fldcr\t %s,%sfcr63\n\t",
2872 reg_names[0], m88k_pound_sign);
2874 "tb1\t 1,%s,0xff\n\t", reg_names[0]);
2876 m88k_volatile_code = code;
2877 last_addr = (GET_CODE (XEXP (x, 0)) == LO_SUM
2878 ? XEXP (XEXP (x, 0), 1) : 0);
2882 case 'X': /* print the upper 16 bits... */
2884 case 'x': /* print the lower 16 bits of the integer constant in hex */
2885 if (xc != CONST_INT)
2886 output_operand_lossage ("invalid %%x/X value");
2887 fprintf (file, "0x%x", value & 0xffff); return;
2889 case 'H': /* print the low 16 bits of the negated integer constant */
2890 if (xc != CONST_INT)
2891 output_operand_lossage ("invalid %%H value");
2893 case 'h': /* print the register or low 16 bits of the integer constant */
2896 if (xc != CONST_INT)
2897 output_operand_lossage ("invalid %%h value");
2898 fprintf (file, "%d", value & 0xffff);
2901 case 'Q': /* print the low 8 bits of the negated integer constant */
2902 if (xc != CONST_INT)
2903 output_operand_lossage ("invalid %%Q value");
2905 case 'q': /* print the register or low 8 bits of the integer constant */
2908 if (xc != CONST_INT)
2909 output_operand_lossage ("invalid %%q value");
2910 fprintf (file, "%d", value & 0xff);
2913 case 'w': /* print the integer constant (X == 32 ? 0 : 32 - X) */
2914 if (xc != CONST_INT)
2915 output_operand_lossage ("invalid %%o value");
2916 fprintf (file, "%d", value == 32 ? 0 : 32 - value);
2919 case 'p': /* print the logarithm of the integer constant */
2921 || (value = exact_log2 (value)) < 0)
2922 output_operand_lossage ("invalid %%p value");
2923 fprintf (file, "%d", value);
2926 case 'S': /* compliment the value and then... */
2928 case 's': /* print the width and offset values forming the integer
2929 constant with a SET instruction. See integer_ok_for_set. */
2931 register unsigned mask, uval = value;
2932 register int top, bottom;
2934 if (xc != CONST_INT)
2935 output_operand_lossage ("invalid %%s/S value");
2936 /* All the "one" bits must be contiguous. If so, MASK will be
2937 a power of two or zero. */
2938 mask = (uval | (uval - 1)) + 1;
2939 if (!(uval && POWER_OF_2_or_0 (mask)))
2940 output_operand_lossage ("invalid %%s/S value");
2941 top = mask ? exact_log2 (mask) : 32;
2942 bottom = exact_log2 (uval & ~(uval - 1));
2943 fprintf (file,"%d<%d>", top - bottom, bottom);
2947 case 'P': /* print nothing if pc_rtx; output label_ref */
2948 if (xc == LABEL_REF)
2949 output_addr_const (file, x);
2951 output_operand_lossage ("invalid %%P operand");
2954 case 'L': /* print 0 or 1 if operand is label_ref and then... */
2955 fputc (xc == LABEL_REF ? '1' : '0', file);
2956 case '.': /* print .n if delay slot is used */
2957 fputs ((final_sequence
2958 && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
2959 ? ".n\t" : "\t", file);
2962 case '!': /* Reverse the following condition. */
2966 case 'R': /* reverse the condition of the next print_operand
2967 if operand is a label_ref. */
2969 reversep = (xc == LABEL_REF);
2972 case 'B': /* bcnd branch values */
2973 fputs (m88k_pound_sign, file);
2976 case EQ: fputs ("eq0", file); return;
2977 case NE: fputs ("ne0", file); return;
2978 case GT: fputs ("gt0", file); return;
2979 case LE: fputs ("le0", file); return;
2980 case LT: fputs ("lt0", file); return;
2981 case GE: fputs ("ge0", file); return;
2982 default: output_operand_lossage ("invalid %%B value");
2985 case 'C': /* bb0/bb1 branch values for comparisons */
2986 fputs (m88k_pound_sign, file);
2989 case EQ: fputs ("eq", file); return;
2990 case NE: fputs ("ne", file); return;
2991 case GT: fputs ("gt", file); return;
2992 case LE: fputs ("le", file); return;
2993 case LT: fputs ("lt", file); return;
2994 case GE: fputs ("ge", file); return;
2995 case GTU: fputs ("hi", file); return;
2996 case LEU: fputs ("ls", file); return;
2997 case LTU: fputs ("lo", file); return;
2998 case GEU: fputs ("hs", file); return;
2999 default: output_operand_lossage ("invalid %%C value");
3002 case 'D': /* bcnd branch values for float comparisons */
3005 case EQ: fputs ("0xa", file); return;
3006 case NE: fputs ("0x5", file); return;
3007 case GT: fputs (m88k_pound_sign, file);
3008 fputs ("gt0", file); return;
3009 case LE: fputs ("0xe", file); return;
3010 case LT: fputs ("0x4", file); return;
3011 case GE: fputs ("0xb", file); return;
3012 default: output_operand_lossage ("invalid %%D value");
3015 case 'E': /* bcnd branch values for special integers */
3018 case EQ: fputs ("0x8", file); return;
3019 case NE: fputs ("0x7", file); return;
3020 default: output_operand_lossage ("invalid %%E value");
3023 case 'd': /* second register of a two register pair */
3025 output_operand_lossage ("`%%d' operand isn't a register");
3026 fputs (reg_names[REGNO (x) + 1], file);
3029 case 'r': /* an immediate 0 should be represented as `r0' */
3030 if (x == const0_rtx)
3032 fputs (reg_names[0], file);
3036 output_operand_lossage ("invalid %%r value");
3042 if (REGNO (x) == ARG_POINTER_REGNUM)
3043 output_operand_lossage ("operand is r0");
3045 fputs (reg_names[REGNO (x)], file);
3047 else if (xc == PLUS)
3050 output_address (XEXP (x, 0));
3051 else if (flag_pic && xc == UNSPEC)
3053 output_addr_const (file, XVECEXP (x, 0, 0));
3054 fputs ("#got_rel", file);
3056 else if (xc == CONST_DOUBLE)
3057 output_operand_lossage ("operand is const_double");
3059 output_addr_const (file, x);
3062 case 'g': /* append #got_rel as needed */
3063 if (flag_pic && (xc == SYMBOL_REF || xc == LABEL_REF))
3065 output_addr_const (file, x);
3066 fputs ("#got_rel", file);
3071 case 'a': /* (standard), assume operand is an address */
3072 case 'c': /* (standard), assume operand is an immediate value */
3073 case 'l': /* (standard), assume operand is a label_ref */
3074 case 'n': /* (standard), like %c, except negate first */
3076 output_operand_lossage ("invalid code");
3081 print_operand_address (file, addr)
3085 register rtx reg0, reg1, temp;
3087 switch (GET_CODE (addr))
3090 if (REGNO (addr) == ARG_POINTER_REGNUM)
3093 fprintf (file, "%s,%s", reg_names[0], reg_names [REGNO (addr)]);
3097 fprintf (file, "%s,%slo16(",
3098 reg_names[REGNO (XEXP (addr, 0))], m88k_pound_sign);
3099 output_addr_const (file, XEXP (addr, 1));
3104 reg0 = XEXP (addr, 0);
3105 reg1 = XEXP (addr, 1);
3106 if (GET_CODE (reg0) == MULT || GET_CODE (reg0) == CONST_INT)
3113 if ((REG_P (reg0) && REGNO (reg0) == ARG_POINTER_REGNUM)
3114 || (REG_P (reg1) && REGNO (reg1) == ARG_POINTER_REGNUM))
3117 else if (REG_P (reg0))
3120 fprintf (file, "%s,%s",
3121 reg_names [REGNO (reg0)], reg_names [REGNO (reg1)]);
3123 else if (GET_CODE (reg1) == CONST_INT)
3124 fprintf (file, "%s,%d",
3125 reg_names [REGNO (reg0)], INTVAL (reg1));
3127 else if (GET_CODE (reg1) == MULT)
3129 rtx mreg = XEXP (reg1, 0);
3130 if (REGNO (mreg) == ARG_POINTER_REGNUM)
3133 fprintf (file, "%s[%s]", reg_names[REGNO (reg0)],
3134 reg_names[REGNO (mreg)]);
3137 else if (GET_CODE (reg1) == ZERO_EXTRACT)
3139 fprintf (file, "%s,%slo16(",
3140 reg_names[REGNO (reg0)], m88k_pound_sign);
3141 output_addr_const (file, XEXP (reg1, 0));
3147 fprintf (file, "%s,", reg_names[REGNO (reg0)]);
3148 output_addr_const (file, reg1);
3149 fputs ("#got_rel", file);
3159 if (REGNO (XEXP (addr, 0)) == ARG_POINTER_REGNUM)
3162 fprintf (file, "%s[%s]",
3163 reg_names[0], reg_names[REGNO (XEXP (addr, 0))]);
3167 fprintf (file, "%s,%d", reg_names[0], INTVAL (addr));
3171 fprintf (file, "%s,", reg_names[0]);
3172 if (SHORT_ADDRESS_P (addr, temp))
3174 fprintf (file, "%siw16(", m88k_pound_sign);
3175 output_addr_const (file, addr);
3179 output_addr_const (file, addr);
3183 /* Return true if X is an address which needs a temporary register when
3184 reloaded while generating PIC code. */
3187 pic_address_needs_scratch (x)
3190 /* An address which is a symbolic plus a non SMALL_INT needs a temp reg. */
3191 if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
3192 && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
3193 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
3194 && ! ADD_INT (XEXP (XEXP (x, 0), 1)))
3200 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
3201 reference and a constant. */
3204 symbolic_operand (op, mode)
3206 enum machine_mode mode;
3208 switch (GET_CODE (op))
3216 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
3217 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
3218 && GET_CODE (XEXP (op, 1)) == CONST_INT);
3220 /* ??? This clause seems to be irrelevant. */
3222 return GET_MODE (op) == mode;
3229 #if defined (CTOR_LIST_BEGIN) && !defined (OBJECT_FORMAT_ELF)
3231 m88k_svr3_asm_out_constructor (symbol, priority)
3233 int priority ATTRIBUTE_UNUSED;
3235 const char *name = XSTR (symbol, 0);
3238 fprintf (asm_out_file, "\tor.u\t r13,r0,hi16(");
3239 assemble_name (asm_out_file, name);
3240 fprintf (asm_out_file, ")\n\tor\t r13,r13,lo16(");
3241 assemble_name (asm_out_file, name);
3242 fprintf (asm_out_file, ")\n\tsubu\t r31,r31,%d\n\tst\t r13,r31,%d\n",
3243 STACK_BOUNDARY / BITS_PER_UNIT, REG_PARM_STACK_SPACE (0));
3247 m88k_svr3_asm_out_destructor (symbol, priority)
3249 int priority ATTRIBUTE_UNUSED;
3254 assemble_integer (symbol, UNITS_PER_WORD, BITS_PER_WORD, 1);
3255 for (i = 1; i < 4; i++)
3256 assemble_integer (constm1_rtx, UNITS_PER_WORD, BITS_PER_WORD, 1);
3258 #endif /* INIT_SECTION_ASM_OP && ! OBJECT_FORMAT_ELF */
3261 m88k_select_section (decl, reloc, align)
3264 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
3266 if (TREE_CODE (decl) == STRING_CST)
3268 if (! flag_writable_strings)
3269 readonly_data_section ();
3270 else if (TREE_STRING_LENGTH (decl) <= m88k_gp_threshold)
3275 else if (TREE_CODE (decl) == VAR_DECL)
3277 if (SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)))
3279 else if ((flag_pic && reloc)
3280 || !TREE_READONLY (decl) || TREE_SIDE_EFFECTS (decl)
3281 || !DECL_INITIAL (decl)
3282 || (DECL_INITIAL (decl) != error_mark_node
3283 && !TREE_CONSTANT (DECL_INITIAL (decl))))
3286 readonly_data_section ();
3289 readonly_data_section ();
3292 /* Adjust the cost of INSN based on the relationship between INSN that
3293 is dependent on DEP_INSN through the dependence LINK. The default
3294 is to make no adjustment to COST.
3296 On the m88k, ignore the cost of anti- and output-dependencies. On
3297 the m88100, a store can issue two cycles before the value (not the
3298 address) has finished computing. */
3301 m88k_adjust_cost (insn, link, dep, cost)
3307 if (REG_NOTE_KIND (link) != 0)
3308 return 0; /* Anti or output dependence. */
3311 && recog_memoized (insn) >= 0
3312 && get_attr_type (insn) == TYPE_STORE
3313 && SET_SRC (PATTERN (insn)) == SET_DEST (PATTERN (dep)))
3314 return cost - 4; /* 88110 store reservation station. */
3319 /* For the m88k, determine if the item should go in the global pool. */
3322 m88k_encode_section_info (decl, first)
3324 int first ATTRIBUTE_UNUSED;
3326 if (m88k_gp_threshold > 0)
3328 if (TREE_CODE (decl) == VAR_DECL)
3330 if (!TREE_READONLY (decl) || TREE_SIDE_EFFECTS (decl))
3332 int size = int_size_in_bytes (TREE_TYPE (decl));
3334 if (size > 0 && size <= m88k_gp_threshold)
3335 SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
3338 else if (TREE_CODE (decl) == STRING_CST
3339 && flag_writable_strings
3340 && TREE_STRING_LENGTH (decl) <= m88k_gp_threshold)
3341 SYMBOL_REF_FLAG (XEXP (TREE_CST_RTL (decl), 0)) = 1;