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. */
26 #include "coretypes.h"
30 #include "hard-reg-set.h"
32 #include "insn-config.h"
33 #include "conditions.h"
35 #include "insn-attr.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) */
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));
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));
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
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
;
133 else if (SMALL_INTVAL (value
))
135 else if (SMALL_INTVAL (-value
))
137 else if (mode
== HImode
)
139 else if (mode
== QImode
)
141 else if ((value
& 0xffff) == 0)
142 return m88k_oru_hi16
;
143 else if (integer_ok_for_set (value
))
149 /* Return the bit number in a compare word corresponding to CONDITION. */
152 condition_value (condition
)
155 switch (GET_CODE (condition
))
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));
182 output_load_const_int (mode
, operands
)
183 enum machine_mode mode
;
186 static const char *const patterns
[] =
194 "or.u %0,%#r0,%X1\n\tor %0,%0,%x1",
197 if (! REG_P (operands
[0])
198 || GET_CODE (operands
[1]) != CONST_INT
)
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. */
207 output_load_const_float (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
);
218 output_load_const_double (operands
)
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
);
240 output_load_const_dimode (operands
)
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
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
)
271 enum machine_mode mode
;
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
));
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
));
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
)
319 operands
[1] = legitimize_address (flag_pic
320 && symbolic_address_p (operand1
),
321 operand1
, temp
, scratch
);
323 operands
[1] = gen_rtx_SUBREG (mode
, operands
[1], 0);
327 /* Now have insn-emit do whatever it normally does. */
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. */
340 legitimize_address (pic
, orig
, reg
, scratch
)
346 rtx addr
= (GET_CODE (orig
) == MEM
? XEXP (orig
, 0) : orig
);
352 if (GET_CODE (addr
) == SYMBOL_REF
|| GET_CODE (addr
) == LABEL_REF
)
356 if (reload_in_progress
|| reload_completed
)
359 reg
= gen_reg_rtx (Pmode
);
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
372 gen_rtx_HIGH (SImode
,
373 gen_rtx_UNSPEC (SImode
,
377 emit_insn (gen_rtx_SET
379 gen_rtx_LO_SUM (SImode
, temp
,
380 gen_rtx_UNSPEC (SImode
,
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
395 REG_NOTES (insn
) = gen_rtx_EXPR_LIST (REG_EQUAL
, orig
,
399 else if (GET_CODE (addr
) == CONST
)
403 if (GET_CODE (XEXP (addr
, 0)) == PLUS
404 && XEXP (XEXP (addr
, 0), 0) == pic_offset_table_rtx
)
409 if (reload_in_progress
|| reload_completed
)
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
)
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. */
431 emit_move_insn (scratch
, addr
);
435 /* If we reach here, then the SECONDARY_INPUT_RELOAD_CLASS
436 macro needs to be adjusted so that a scratch reg is provided
440 new = gen_rtx_PLUS (SImode
, base
, addr
);
441 /* Should we set special REG_NOTEs here? */
444 else if (! SHORT_ADDRESS_P (addr
, temp
))
448 if (reload_in_progress
|| reload_completed
)
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
);
460 && GET_CODE (orig
) == MEM
)
462 new = gen_rtx_MEM (GET_MODE (orig
), new);
463 MEM_COPY_ATTRIBUTES (new, orig
);
468 /* Support functions for code to emit a block move. There are four methods
469 used to perform the block move:
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
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
,
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. */
550 expand_block_move (dest_mem
, src_mem
, 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))
565 if (constp
&& bytes
<= 0)
568 /* Determine machine mode to do move with. */
569 if (align
> 4 && !TARGET_88110
)
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
,
578 else if (constp
&& bytes
<= best_from_align
[target
][align
])
579 block_move_no_loop (operands
[0], dest_mem
, operands
[1], src_mem
,
582 else if (constp
&& align
== 4 && TARGET_88100
)
583 block_move_loop (operands
[0], dest_mem
, operands
[1], src_mem
,
588 #ifdef TARGET_MEM_FUNCTIONS
589 emit_library_call (gen_rtx_SYMBOL_REF (Pmode
, "memcpy"), 0,
593 convert_to_mode (TYPE_MODE (sizetype
), operands
[2],
594 TREE_UNSIGNED (sizetype
)),
595 TYPE_MODE (sizetype
));
597 emit_library_call (gen_rtx_SYMBOL_REF (Pmode
, "bcopy"), 0,
601 convert_to_mode (TYPE_MODE (integer_type_node
),
603 TREE_UNSIGNED (integer_type_node
)),
604 TYPE_MODE (integer_type_node
));
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
614 block_move_loop (dest
, dest_mem
, src
, src_mem
, size
, align
)
620 enum machine_mode mode
;
629 /* Determine machine mode to do move with. */
633 /* Determine the structure of the loop. */
634 count
= size
/ MOVSTR_LOOP
;
635 units
= (size
- count
* MOVSTR_LOOP
) / align
;
640 units
+= MOVSTR_LOOP
/ align
;
645 block_move_no_loop (dest
, dest_mem
, src
, src_mem
, size
, align
);
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
,
660 gen_rtx_REG (Pmode
, 3),
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)),
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. */
681 block_move_no_loop (dest
, dest_mem
, src
, src_mem
, size
, align
)
687 enum machine_mode mode
= mode_from_align
[align
];
688 int units
= size
/ align
;
689 int remainder
= size
- units
* align
;
697 if (remainder
&& size
<= all_from_align
[align
])
699 most
= all_from_align
[align
] - (align
- remainder
);
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
,
715 gen_rtx_REG (Pmode
, 3),
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
)));
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. */
740 block_move_sequence (dest
, dest_mem
, src
, src_mem
, size
, align
, offset
)
748 enum machine_mode mode
[2];
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
)
766 temp
[1] = gen_reg_rtx (mode
[1]);
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
];
796 active
[phase
] = FALSE
;
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. */
812 output_and (operands
)
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";
832 return "and.u %0,%1,%X2\n\tand %0,%0,%x2";
835 /* Emit the code to do an inclusive OR operation. */
838 output_ior (operands
)
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";
854 return "or.u %0,%1,%X2\n\tor %0,%0,%x2";
857 /* Emit the instructions for doing an XOR. */
860 output_xor (operands
)
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";
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;
892 output_call (operands
, addr
)
902 /* This can be generalized, but there is currently no need. */
903 if (XVECLEN (final_sequence
, 0) != 2)
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
)
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
))
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
);
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
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
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
942 #ifdef AS_BUG_IMMEDIATE_LABEL /* The assembler restricts immediate values. */
944 || ! ADD_INTVAL (delta
* 2)
947 || ! ADD_INTVAL (delta
)
949 || (REG_P (addr
) && REGNO (addr
) == 1))
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
)
962 : (flag_pic
? "bsr.n %0#plt" : "bsr.n %0")),
967 ? "subu %#r1,%#r1,.-%l0+4"
968 : "addu %#r1,%#r1,%l0-.-4");
971 operands
[0] = gen_label_rtx ();
972 operands
[1] = gen_label_rtx ();
977 last
= "subu %#r1,%#r1,%l0\n%l1:";
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 */
997 : (flag_pic
? "bsr%. %0#plt" : "bsr%. %0"));
1001 output_short_branch_defs (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
)
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
);
1035 /* Much of this isn't computed unless we're optimizing. */
1039 /* Determine if one path or the other leads to a return. */
1040 for (insnt
= NEXT_INSN (target_label
);
1042 insnt
= NEXT_INSN (insnt
))
1044 if (GET_CODE (insnt
) == JUMP_INSN
)
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);
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)))
1061 for (insnj
= NEXT_INSN (jump_insn
);
1063 insnj
= NEXT_INSN (insnj
))
1065 if (GET_CODE (insnj
) == JUMP_INSN
)
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);
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)))
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
)
1092 else if (NOTE_LINE_NUMBER (insnt
) == NOTE_INSN_LOOP_BEG
)
1094 else if (NOTE_LINE_NUMBER (insnt
) == NOTE_INSN_LOOP_CONT
)
1097 /* Predict backward branches usually take. */
1099 insnj
= NEXT_INSN (PREV_INSN (XVECEXP (final_sequence
, 0, 0)));
1102 if (INSN_ADDRESSES (INSN_UID (insnj
))
1103 > INSN_ADDRESSES (INSN_UID (target_label
)))
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
))
1113 /* Unconditional branch. */
1122 case GTU
: /* Must get casesi right at least. */
1123 if (XEXP (condition
, 1) == const0_rtx
)
1130 if (XEXP (condition
, 1) == const0_rtx
)
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
)
1146 enum machine_mode mode ATTRIBUTE_UNUSED
;
1151 struct { /* IEEE double precision format */
1153 unsigned exponent
: 11;
1154 unsigned mantissa1
: 20;
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;
1166 if (GET_MODE (op
) != DFmode
&& GET_MODE (op
) != SFmode
)
1169 if (GET_CODE (op
) != CONST_DOUBLE
)
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 */
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. */
1189 legitimize_operand (op
, mode
)
1191 enum machine_mode mode
;
1197 struct { /* IEEE double precision format */
1199 unsigned exponent
: 11;
1200 unsigned mantissa1
: 20;
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;
1212 if (GET_CODE (op
) == REG
|| mode
!= DFmode
)
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
,
1224 return gen_rtx_FLOAT_EXTEND (mode
, force_reg (SFmode
, temp
));
1226 else if (register_operand (op
, mode
))
1229 return force_reg (mode
, op
);
1232 /* Return true if OP is a suitable input for a move insn. */
1235 move_operand (op
, mode
)
1237 enum machine_mode mode
;
1239 if (register_operand (op
, mode
))
1241 if (GET_CODE (op
) == CONST_INT
)
1242 return (classify_integer (mode
, INTVAL (op
)) < m88k_oru_hi16
);
1243 if (GET_MODE (op
) != mode
)
1245 if (GET_CODE (op
) == SUBREG
)
1246 op
= SUBREG_REG (op
);
1247 if (GET_CODE (op
) != MEM
)
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
)
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
)
1274 switch (GET_CODE (op
))
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
);
1291 /* Return true if OP is a register or const0_rtx. */
1294 reg_or_0_operand (op
, mode
)
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
)
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
)
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
)
1326 enum machine_mode mode
;
1328 return (register_operand (op
, mode
) || GET_CODE (op
) == CONST_INT
);
1332 arith64_operand (op
, mode
)
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
)
1344 enum machine_mode mode ATTRIBUTE_UNUSED
;
1346 return (GET_CODE (op
) == CONST_INT
&& (unsigned) INTVAL (op
) < 32);
1350 int32_operand (op
, mode
)
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
1361 add_operand (op
, mode
)
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. */
1376 return (value
&& POWER_OF_2_or_0 (value
+ 1));
1380 reg_or_bbx_mask_operand (op
, mode
)
1382 enum machine_mode mode
;
1385 if (register_operand (op
, mode
))
1387 if (GET_CODE (op
) != CONST_INT
)
1390 value
= INTVAL (op
);
1391 if (POWER_OF_2 (value
))
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
)
1403 enum machine_mode mode
;
1405 if (mode
!= SFmode
&& mode
!= DFmode
)
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
)
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. */
1429 enum machine_mode mode ATTRIBUTE_UNUSED
;
1431 switch (GET_CODE (op
))
1450 even_relop (op
, mode
)
1452 enum machine_mode mode ATTRIBUTE_UNUSED
;
1454 switch (GET_CODE (op
))
1468 odd_relop (op
, mode
)
1470 enum machine_mode mode ATTRIBUTE_UNUSED
;
1472 switch (GET_CODE (op
))
1485 /* Return true if OP is a relational operator, and is not an unsigned
1486 relational operator. */
1489 relop_no_unsigned (op
, mode
)
1491 enum machine_mode mode ATTRIBUTE_UNUSED
;
1493 switch (GET_CODE (op
))
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
)
1515 /* Return true if the code of this rtx pattern is EQ or NE. */
1518 equality_op (op
, mode
)
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
)
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
;
1543 const char *const description
;
1546 static void output_options
PARAMS ((FILE *,
1547 const struct m88k_lang_independent_options
*,
1549 const struct m88k_lang_independent_options
*,
1550 int, int, int, const char *, const char *,
1554 output_option (file
, sep
, type
, name
, indent
, pos
, 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
[] =
1575 output_options (file
, f_options
, f_len
, W_options
, W_len
,
1576 pos
, max
, sep
, indent
, term
)
1578 const struct m88k_lang_independent_options
*f_options
;
1579 const struct m88k_lang_independent_options
*W_options
;
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
);
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
,
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
,
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
,
1613 if (m88k_short_data
)
1614 pos
= output_option (file
, sep
, "-mshort-data-", m88k_short_data
,
1617 fprintf (file
, term
);
1621 output_file_start (file
, f_options
, f_len
, W_options
, W_len
)
1623 const struct m88k_lang_independent_options
*f_options
;
1624 const struct m88k_lang_independent_options
*W_options
;
1629 ASM_FIRST_LINE (file
);
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. */
1638 if (TARGET_IDENTIFY_REVISION
)
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
));
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");
1653 fprintf (file
, "]\"\n");
1654 print_switch_values (file
, 0, 150 - strlen (indent
),
1655 indent
+ 3, " ", "]\"\n");
1660 /* Output an ascii string. */
1663 output_ascii (file
, opcode
, max
, p
, size
)
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
];
1682 fprintf (file
, "\"\n%s\"", opcode
);
1686 if (c
== '\"' || c
== '\\')
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
1700 fprintf (file
, "\\%03o", c
);
1703 else if ((c
>= ' ' && c
< 0177) || (c
== '\t'))
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
);
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). */
1732 output_label (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:
1779 |==============================================|
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
1805 r1 and r30 must be saved if debugging.
1807 fp (if present) is located two words down from the local
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));
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. */
1841 m88k_layout_frame ()
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
)
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
)
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
)
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;
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
;
1891 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
1893 save_regs
[regno
] = 1;
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;
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
])
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)
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
);
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
1932 = ((m88k_stack_size
? STACK_UNIT_BOUNDARY
- STARTING_FRAME_OFFSET
: 0)
1933 - (frame_size
% STACK_UNIT_BOUNDARY
));
1935 need
+= STACK_UNIT_BOUNDARY
;
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. */
1947 if (! reload_completed
)
1949 if (! frame_laid_out
)
1950 m88k_layout_frame ();
1951 return (! frame_pointer_needed
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
1967 if (current_function_decl
== 0
1971 for (parm
= DECL_ARGUMENTS (current_function_decl
);
1973 parm
= TREE_CHAIN (parm
))
1975 if (DECL_RTL (parm
) == 0
1976 || GET_CODE (DECL_RTL (parm
)) == MEM
)
1979 if (DECL_INCOMING_RTL (parm
) == 0
1980 || GET_CODE (DECL_INCOMING_RTL (parm
)) == MEM
)
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 */
1998 m88k_output_function_end_prologue (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
);
2021 m88k_expand_prologue ()
2023 m88k_layout_frame ();
2025 if (TARGET_OPTIMIZE_ARG_AREA
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
;
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
));
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. */
2075 m88k_output_function_begin_epilogue (stream
)
2078 if (TARGET_OCS_DEBUG_INFO
&& !epilogue_marked
&& prologue_marked
)
2080 PUT_OCS_FUNCTION_END (stream
);
2082 epilogue_marked
= 1;
2086 m88k_output_function_epilogue (stream
, size
)
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 */
2124 epilogue_marked
= 0;
2125 prologue_marked
= 0;
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
);
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
2150 emit_add (dstreg
, srcreg
, 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
);
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. */
2171 preserve_registers (base
, store_p
)
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. */
2190 /* An extra word is given in this case to make best use of double
2192 if (nregs
> 2 && !save_regs
[FRAME_POINTER_REGNUM
])
2194 emit_ldst (store_p
, 1, SImode
, 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])
2206 mo_ptr
->regno
= regno
;
2207 mo_ptr
->offset
= offset
;
2218 /* Walk the registers to save recording all double memory operations.
2219 This avoids a delay in the epilogue (ld.d/ld). */
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])
2231 mo_ptr
->regno
= regno
-1;
2232 mo_ptr
->offset
= offset
-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
;
2244 if (save_regs
[regno
])
2247 mo_ptr
->regno
= regno
;
2248 mo_ptr
->offset
= offset
;
2255 /* Output the memory operations. */
2256 for (mo_ptr
= mem_op
; mo_ptr
->regno
; mo_ptr
++)
2259 emit_ldst (store_p
, mo_ptr
->regno
,
2260 (mo_ptr
->nregs
> 1 ? DImode
: SImode
),
2266 emit_ldst (store_p
, regno
, mode
, offset
)
2269 enum machine_mode mode
;
2272 rtx reg
= gen_rtx_REG (mode
, regno
);
2275 if (SMALL_INTVAL (offset
))
2277 mem
= gen_rtx_MEM (mode
, plus_constant (stack_pointer_rtx
, offset
));
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
);
2292 emit_move_insn (mem
, reg
);
2294 emit_move_insn (reg
, mem
);
2297 /* Convert the address expression REG to a CFA offset. */
2300 m88k_debugger_offset (reg
, offset
)
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");
2328 /* Output the 88open OCS proscribed text description information.
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)
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) */
2348 output_tdesc (file
, offset
)
2353 long mask
, return_address_info
, register_save_offset
;
2354 long xmask
, xregister_save_offset
;
2357 for (mask
= 0, i
= 0, regno
= FIRST_OCS_PRESERVE_REGISTER
;
2358 regno
<= LAST_OCS_PRESERVE_REGISTER
;
2362 if (save_regs
[regno
])
2369 for (xmask
= 0, j
= 0, regno
= FIRST_OCS_EXTENDED_PRESERVE_REGISTER
;
2370 regno
<= LAST_OCS_EXTENDED_PRESERVE_REGISTER
;
2374 if (save_regs
[regno
])
2383 if ((nxregs
> 0 || nregs
> 2) && !save_regs
[FRAME_POINTER_REGNUM
])
2385 return_address_info
= - m88k_stack_size
+ offset
;
2386 register_save_offset
= return_address_info
- i
*4;
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));
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,
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))
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
);
2420 fprintf (file
, ",0x%lx%04lx", xmask
, (0xffff & xregister_save_offset
));
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. */
2432 output_function_profiler (file
, labelno
, name
, savep
)
2440 const char *const temp
= (savep
? reg_names
[2] : reg_names
[10]);
2442 /* Remember to update FUNCTION_PROFILER_LENGTH. */
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
);
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
);
2465 sprintf (dbi
, "\tld\t %s,%s,%s#got_rel\n", temp
,
2466 reg_names
[PIC_OFFSET_TABLE_REGNUM
], &label
[1]);
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]);
2477 fprintf (file
, "\tbsr.n\t %s#plt\n", name
);
2479 fprintf (file
, "\tbsr.n\t %s\n", name
);
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
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. */
2522 m88k_function_arg (args_so_far
, mode
, type
, named
)
2523 CUMULATIVE_ARGS args_so_far
;
2524 enum machine_mode mode
;
2526 int named ATTRIBUTE_UNUSED
;
2530 if (type
!= 0 /* undo putting struct in register */
2531 && (TREE_CODE (type
) == RECORD_TYPE
|| TREE_CODE (type
) == UNION_TYPE
))
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)))
2544 return (rtx
) 0; /* don't put args in registers */
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
))
2561 return gen_rtx_REG (((mode
== BLKmode
) ? TYPE_MODE (type
) : mode
),
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. */
2570 m88k_builtin_saveregs ()
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;
2580 variable_args_p
= 1;
2583 if (GET_CODE (current_function_arg_offset_rtx
) == CONST_INT
)
2584 fixed
= ((INTVAL (current_function_arg_offset_rtx
) + argadj
)
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. */
2595 move_block_from_reg (2 + fixed
,
2596 adjust_address (addr
, Pmode
, fixed
* UNITS_PER_WORD
),
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
2603 return XEXP (addr
, 0);
2606 /* Define the `__builtin_va_list' type for the ABI. */
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"),
2619 field_stk
= build_decl (FIELD_DECL
, get_identifier ("__va_stk"),
2621 field_reg
= build_decl (FIELD_DECL
, get_identifier ("__va_reg"),
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
);
2636 /* Implement `va_start' for varargs and stdarg. */
2639 m88k_va_start (valist
, nextarg
)
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;
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);
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
)
2704 tree field_reg
, field_stk
, field_arg
;
2705 tree reg
, stk
, arg
, arg_align
, base
, t
;
2706 int size
, wsize
, align
, reg_p
;
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
);
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
)
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
2766 emit_bcnd (op
, label
)
2770 if (m88k_compare_op1
== const0_rtx
)
2771 emit_jump_insn (gen_bcnd
2772 (gen_rtx (op
, VOIDmode
,m88k_compare_op0
, const0_rtx
),
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
),
2779 else if (op
!= EQ
&& op
!= NE
)
2780 emit_jump_insn (gen_bxx (emit_test (op
, VOIDmode
), label
));
2783 rtx zero
= gen_reg_rtx (SImode
);
2787 if (GET_CODE (m88k_compare_op1
) == CONST_INT
)
2789 reg
= force_reg (SImode
, m88k_compare_op0
);
2790 constant
= m88k_compare_op1
;
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
));
2805 if (SMALL_INTVAL (-value
))
2806 emit_insn (gen_addsi3 (zero
, reg
,
2809 emit_insn (gen_xorsi3 (zero
, reg
, constant
));
2811 emit_jump_insn (gen_bcnd (gen_rtx (op
, VOIDmode
,
2818 /* Print an operand. Recognize special options, documented below. */
2821 print_operand (file
, x
, 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
;
2833 if (code
< 'B' || code
> 'E')
2834 output_operand_lossage ("%%R not followed by %%B/C/D/E");
2836 xc
= reverse_condition (xc
);
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. */
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
)))
2884 "fldcr\t %s,%scr63\n\t",
2886 "fldcr\t %s,%sfcr63\n\t",
2888 reg_names
[0], m88k_pound_sign
);
2890 "tb1\t 1,%s,0xff\n\t", reg_names
[0]);
2892 m88k_volatile_code
= code
;
2893 last_addr
= (GET_CODE (XEXP (x
, 0)) == LO_SUM
2894 ? XEXP (XEXP (x
, 0), 1) : 0);
2898 case 'X': /* print the upper 16 bits... */
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");
2909 case 'h': /* print the register or low 16 bits of the integer constant */
2912 if (xc
!= CONST_INT
)
2913 output_operand_lossage ("invalid %%h value");
2914 fprintf (file
, "%d", value
& 0xffff);
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");
2921 case 'q': /* print the register or low 8 bits of the integer constant */
2924 if (xc
!= CONST_INT
)
2925 output_operand_lossage ("invalid %%q value");
2926 fprintf (file
, "%d", value
& 0xff);
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
);
2935 case 'p': /* print the logarithm of the integer constant */
2937 || (value
= exact_log2 (value
)) < 0)
2938 output_operand_lossage ("invalid %%p value");
2939 fprintf (file
, "%d", value
);
2942 case 'S': /* complement the value and then... */
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
);
2963 case 'P': /* print nothing if pc_rtx; output label_ref */
2964 if (xc
== LABEL_REF
)
2965 output_addr_const (file
, x
);
2967 output_operand_lossage ("invalid %%P operand");
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
);
2978 case '!': /* Reverse the following condition. */
2982 case 'R': /* reverse the condition of the next print_operand
2983 if operand is a label_ref. */
2985 reversep
= (xc
== LABEL_REF
);
2988 case 'B': /* bcnd branch values */
2989 fputs (m88k_pound_sign
, file
);
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
);
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 */
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 */
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 */
3041 output_operand_lossage ("`%%d' operand isn't a register");
3042 fputs (reg_names
[REGNO (x
) + 1], file
);
3045 case 'r': /* an immediate 0 should be represented as `r0' */
3046 if (x
== const0_rtx
)
3048 fputs (reg_names
[0], file
);
3052 output_operand_lossage ("invalid %%r value");
3058 if (REGNO (x
) == ARG_POINTER_REGNUM
)
3059 output_operand_lossage ("operand is r0");
3061 fputs (reg_names
[REGNO (x
)], file
);
3063 else if (xc
== PLUS
)
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");
3075 output_addr_const (file
, x
);
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
);
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 */
3092 output_operand_lossage ("invalid code");
3097 print_operand_address (file
, addr
)
3101 register rtx reg0
, reg1
, temp
;
3103 switch (GET_CODE (addr
))
3106 if (REGNO (addr
) == ARG_POINTER_REGNUM
)
3109 fprintf (file
, "%s,%s", reg_names
[0], reg_names
[REGNO (addr
)]);
3113 fprintf (file
, "%s,%slo16(",
3114 reg_names
[REGNO (XEXP (addr
, 0))], m88k_pound_sign
);
3115 output_addr_const (file
, XEXP (addr
, 1));
3120 reg0
= XEXP (addr
, 0);
3121 reg1
= XEXP (addr
, 1);
3122 if (GET_CODE (reg0
) == MULT
|| GET_CODE (reg0
) == CONST_INT
)
3129 if ((REG_P (reg0
) && REGNO (reg0
) == ARG_POINTER_REGNUM
)
3130 || (REG_P (reg1
) && REGNO (reg1
) == ARG_POINTER_REGNUM
))
3133 else if (REG_P (reg0
))
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
)
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));
3163 fprintf (file
, "%s,", reg_names
[REGNO (reg0
)]);
3164 output_addr_const (file
, reg1
);
3165 fputs ("#got_rel", file
);
3175 if (REGNO (XEXP (addr
, 0)) == ARG_POINTER_REGNUM
)
3178 fprintf (file
, "%s[%s]",
3179 reg_names
[0], reg_names
[REGNO (XEXP (addr
, 0))]);
3183 fprintf (file
, "%s,%d", reg_names
[0], INTVAL (addr
));
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
);
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
)
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)))
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
)
3222 enum machine_mode mode
;
3224 switch (GET_CODE (op
))
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. */
3238 return GET_MODE (op
) == mode
;
3245 #if defined (CTOR_LIST_BEGIN) && !defined (OBJECT_FORMAT_ELF)
3247 m88k_svr3_asm_out_constructor (symbol
, priority
)
3249 int priority ATTRIBUTE_UNUSED
;
3251 const char *name
= XSTR (symbol
, 0);
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));
3263 m88k_svr3_asm_out_destructor (symbol
, priority
)
3265 int priority ATTRIBUTE_UNUSED
;
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 */
3277 m88k_select_section (decl
, reloc
, align
)
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
)
3291 else if (TREE_CODE (decl
) == VAR_DECL
)
3293 if (SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl
), 0)))
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
))))
3302 readonly_data_section ();
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. */
3317 m88k_adjust_cost (insn
, link
, dep
, cost
)
3323 if (REG_NOTE_KIND (link
) != 0)
3324 return 0; /* Anti or output dependence. */
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. */
3335 /* For the m88k, determine if the item should go in the global pool. */
3338 m88k_encode_section_info (decl
, rtl
, first
)
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. */
3364 m88k_internal_label (stream
, prefix
, labelno
)
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
);
3375 m88k_rtx_costs (x
, code
, outer_code
, total
)
3377 int code
, outer_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. */
3388 else if (SMALL_INTVAL (- INTVAL (x
)))
3390 else if (classify_integer (SImode
, INTVAL (x
)) != m88k_oru_or
)
3404 *total
= (flag_pic
== 2) ? 11 : 8;
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). */
3418 *total
= COSTS_N_INSNS (2);
3422 *total
= COSTS_N_INSNS (3);
3429 *total
= COSTS_N_INSNS (38);
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. */
3442 m88k_address_cost (x
)
3445 switch (GET_CODE (x
))
3454 return (REG_P (XEXP (x
, 0)) && REG_P (XEXP (x
, 1))) ? 2 : 1;