1 /* Subroutines for insn-output.c for Motorola 88000.
2 Copyright (C) 1988, 92, 93, 94, 95, 16, 1997 Free Software Foundation, Inc.
3 Contributed by Michael Tiemann (tiemann@mcc.com)
4 Currently maintained by (gcc@dg-rtp.dg.com)
6 This file is part of GNU CC.
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 GNU CC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
24 #include <sys/types.h>
32 #include "hard-reg-set.h"
34 #include "insn-config.h"
35 #include "conditions.h"
36 #include "insn-flags.h"
38 #include "insn-attr.h"
44 extern char *version_string
;
45 extern time_t time ();
46 extern char *ctime ();
47 extern int flag_traditional
;
48 extern FILE *asm_out_file
;
50 static char out_rcs_id
[] = "$What: <@(#) m88k.c,v 1.8> $";
51 static char tm_rcs_id
[] = TM_RCS_ID
;
53 char *m88k_pound_sign
= ""; /* Either # for SVR4 or empty for SVR3 */
54 char *m88k_short_data
;
56 char m88k_volatile_code
;
58 unsigned m88k_gp_threshold
= 0;
59 int m88k_prologue_done
= 0; /* Ln directives can now be emitted */
60 int m88k_function_number
= 0; /* Counter unique to each function */
61 int m88k_fp_offset
= 0; /* offset of frame pointer if used */
62 int m88k_stack_size
= 0; /* size of allocated stack (including frame) */
65 rtx m88k_compare_reg
; /* cmp output pseudo register */
66 rtx m88k_compare_op0
; /* cmpsi operand 0 */
67 rtx m88k_compare_op1
; /* cmpsi operand 1 */
69 enum processor_type m88k_cpu
; /* target cpu */
71 /* Determine what instructions are needed to manufacture the integer VALUE
75 classify_integer (mode
, value
)
76 enum machine_mode mode
;
83 else if (SMALL_INTVAL (value
))
85 else if (SMALL_INTVAL (-value
))
87 else if (mode
== HImode
)
89 else if (mode
== QImode
)
91 else if ((value
& 0xffff) == 0)
93 else if (integer_ok_for_set (value
))
99 /* Return the bit number in a compare word corresponding to CONDITION. */
102 condition_value (condition
)
105 switch (GET_CODE (condition
))
122 integer_ok_for_set (value
)
123 register unsigned value
;
125 /* All the "one" bits must be contiguous. If so, MASK + 1 will be
126 a power of two or zero. */
127 register unsigned mask
= (value
| (value
- 1));
128 return (value
&& POWER_OF_2_or_0 (mask
+ 1));
132 output_load_const_int (mode
, operands
)
133 enum machine_mode mode
;
136 static char *patterns
[] =
144 "or.u %0,%#r0,%X1\n\tor %0,%0,%x1",
147 if (! REG_P (operands
[0])
148 || GET_CODE (operands
[1]) != CONST_INT
)
150 return patterns
[classify_integer (mode
, INTVAL (operands
[1]))];
153 /* These next two routines assume that floating point numbers are represented
154 in a manner which is consistent between host and target machines. */
157 output_load_const_float (operands
)
160 /* These can return 0 under some circumstances when cross-compiling. */
161 operands
[0] = operand_subword (operands
[0], 0, 0, SFmode
);
162 operands
[1] = operand_subword (operands
[1], 0, 0, SFmode
);
164 return output_load_const_int (SImode
, operands
);
168 output_load_const_double (operands
)
173 /* These can return zero on some cross-compilers, but there's nothing
174 we can do about it. */
175 latehalf
[0] = operand_subword (operands
[0], 1, 0, DFmode
);
176 latehalf
[1] = operand_subword (operands
[1], 1, 0, DFmode
);
178 operands
[0] = operand_subword (operands
[0], 0, 0, DFmode
);
179 operands
[1] = operand_subword (operands
[1], 0, 0, DFmode
);
181 output_asm_insn (output_load_const_int (SImode
, operands
), operands
);
183 operands
[0] = latehalf
[0];
184 operands
[1] = latehalf
[1];
186 return output_load_const_int (SImode
, operands
);
190 output_load_const_dimode (operands
)
195 latehalf
[0] = operand_subword (operands
[0], 1, 0, DImode
);
196 latehalf
[1] = operand_subword (operands
[1], 1, 0, DImode
);
198 operands
[0] = operand_subword (operands
[0], 0, 0, DImode
);
199 operands
[1] = operand_subword (operands
[1], 0, 0, DImode
);
201 output_asm_insn (output_load_const_int (SImode
, operands
), operands
);
203 operands
[0] = latehalf
[0];
204 operands
[1] = latehalf
[1];
206 return output_load_const_int (SImode
, operands
);
209 /* Emit insns to move operands[1] into operands[0].
211 Return 1 if we have written out everything that needs to be done to
212 do the move. Otherwise, return 0 and the caller will emit the move
215 SCRATCH if non zero can be used as a scratch register for the move
216 operation. It is provided by a SECONDARY_RELOAD_* macro if needed. */
219 emit_move_sequence (operands
, mode
, scratch
)
221 enum machine_mode mode
;
224 register rtx operand0
= operands
[0];
225 register rtx operand1
= operands
[1];
227 if (CONSTANT_P (operand1
) && flag_pic
228 && pic_address_needs_scratch (operand1
))
229 operands
[1] = operand1
= legitimize_address (1, operand1
, 0, 0);
231 /* Handle most common case first: storing into a register. */
232 if (register_operand (operand0
, mode
))
234 if (register_operand (operand1
, mode
)
235 || (GET_CODE (operand1
) == CONST_INT
&& SMALL_INT (operand1
))
236 || GET_CODE (operand1
) == HIGH
237 /* Only `general_operands' can come here, so MEM is ok. */
238 || GET_CODE (operand1
) == MEM
)
240 /* Run this case quickly. */
241 emit_insn (gen_rtx (SET
, VOIDmode
, operand0
, operand1
));
245 else if (GET_CODE (operand0
) == MEM
)
247 if (register_operand (operand1
, mode
)
248 || (operand1
== const0_rtx
&& GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
))
250 /* Run this case quickly. */
251 emit_insn (gen_rtx (SET
, VOIDmode
, operand0
, operand1
));
254 if (! reload_in_progress
&& ! reload_completed
)
256 operands
[0] = validize_mem (operand0
);
257 operands
[1] = operand1
= force_reg (mode
, operand1
);
261 /* Simplify the source if we need to. */
262 if (GET_CODE (operand1
) != HIGH
&& immediate_operand (operand1
, mode
))
264 if (GET_CODE (operand1
) != CONST_INT
265 && GET_CODE (operand1
) != CONST_DOUBLE
)
267 rtx temp
= ((reload_in_progress
|| reload_completed
)
269 operands
[1] = legitimize_address (flag_pic
270 && symbolic_address_p (operand1
),
271 operand1
, temp
, scratch
);
273 operands
[1] = gen_rtx (SUBREG
, mode
, operands
[1], 0);
277 /* Now have insn-emit do whatever it normally does. */
281 /* Return a legitimate reference for ORIG (either an address or a MEM)
282 using the register REG. If PIC and the address is already
283 position-independent, use ORIG. Newly generated position-independent
284 addresses go into a reg. This is REG if non zero, otherwise we
285 allocate register(s) as necessary. If this is called during reload,
286 and we need a second temp register, then we use SCRATCH, which is
287 provided via the SECONDARY_INPUT_RELOAD_CLASS mechanism. */
290 legitimize_address (pic
, orig
, reg
, scratch
)
296 rtx addr
= (GET_CODE (orig
) == MEM
? XEXP (orig
, 0) : orig
);
302 if (GET_CODE (addr
) == SYMBOL_REF
|| GET_CODE (addr
) == LABEL_REF
)
306 if (reload_in_progress
|| reload_completed
)
309 reg
= gen_reg_rtx (Pmode
);
314 /* If not during reload, allocate another temp reg here for
315 loading in the address, so that these instructions can be
316 optimized properly. */
317 temp
= ((reload_in_progress
|| reload_completed
)
318 ? reg
: gen_reg_rtx (Pmode
));
320 emit_insn (gen_rtx (SET
, VOIDmode
, temp
,
321 gen_rtx (HIGH
, SImode
,
322 gen_rtx (UNSPEC
, SImode
,
325 emit_insn (gen_rtx (SET
, VOIDmode
, temp
,
326 gen_rtx (LO_SUM
, SImode
, temp
,
327 gen_rtx (UNSPEC
, SImode
,
332 new = gen_rtx (MEM
, Pmode
,
333 gen_rtx (PLUS
, SImode
,
334 pic_offset_table_rtx
, addr
));
335 current_function_uses_pic_offset_table
= 1;
336 RTX_UNCHANGING_P (new) = 1;
337 insn
= emit_move_insn (reg
, new);
338 /* Put a REG_EQUAL note on this insn, so that it can be optimized
340 REG_NOTES (insn
) = gen_rtx (EXPR_LIST
, REG_EQUAL
, orig
,
344 else if (GET_CODE (addr
) == CONST
)
348 if (GET_CODE (XEXP (addr
, 0)) == PLUS
349 && XEXP (XEXP (addr
, 0), 0) == pic_offset_table_rtx
)
354 if (reload_in_progress
|| reload_completed
)
357 reg
= gen_reg_rtx (Pmode
);
360 if (GET_CODE (XEXP (addr
, 0)) != PLUS
) abort ();
362 base
= legitimize_address (1, XEXP (XEXP (addr
, 0), 0), reg
, 0);
363 addr
= legitimize_address (1, XEXP (XEXP (addr
, 0), 1),
364 base
== reg
? 0 : reg
, 0);
366 if (GET_CODE (addr
) == CONST_INT
)
369 return plus_constant_for_output (base
, INTVAL (addr
));
370 else if (! reload_in_progress
&& ! reload_completed
)
371 addr
= force_reg (Pmode
, addr
);
372 /* We can't create any new registers during reload, so use the
373 SCRATCH reg provided by the reload_insi pattern. */
376 emit_move_insn (scratch
, addr
);
380 /* If we reach here, then the SECONDARY_INPUT_RELOAD_CLASS
381 macro needs to be adjusted so that a scratch reg is provided
385 new = gen_rtx (PLUS
, SImode
, base
, addr
);
386 /* Should we set special REG_NOTEs here? */
389 else if (! SHORT_ADDRESS_P (addr
, temp
))
393 if (reload_in_progress
|| reload_completed
)
396 reg
= gen_reg_rtx (Pmode
);
399 emit_insn (gen_rtx (SET
, VOIDmode
,
400 reg
, gen_rtx (HIGH
, SImode
, addr
)));
401 new = gen_rtx (LO_SUM
, SImode
, reg
, addr
);
405 && GET_CODE (orig
) == MEM
)
407 new = gen_rtx (MEM
, GET_MODE (orig
), new);
408 RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (orig
);
409 MEM_VOLATILE_P (new) = MEM_VOLATILE_P (orig
);
410 MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (orig
);
415 /* Support functions for code to emit a block move. There are four methods
416 used to perform the block move:
418 + call the looping library function, e.g. __movstrSI64n8
419 + call a non-looping library function, e.g. __movstrHI15x11
420 + produce an inline sequence of ld/st instructions
422 The parameters below describe the library functions produced by
425 #define MOVSTR_LOOP 64 /* __movstrSI64n68 .. __movstrSI64n8 */
426 #define MOVSTR_QI 16 /* __movstrQI16x16 .. __movstrQI16x2 */
427 #define MOVSTR_HI 48 /* __movstrHI48x48 .. __movstrHI48x4 */
428 #define MOVSTR_SI 96 /* __movstrSI96x96 .. __movstrSI96x8 */
429 #define MOVSTR_DI 96 /* __movstrDI96x96 .. __movstrDI96x16 */
430 #define MOVSTR_ODD_HI 16 /* __movstrHI15x15 .. __movstrHI15x5 */
431 #define MOVSTR_ODD_SI 48 /* __movstrSI47x47 .. __movstrSI47x11,
432 __movstrSI46x46 .. __movstrSI46x10,
433 __movstrSI45x45 .. __movstrSI45x9 */
434 #define MOVSTR_ODD_DI 48 /* __movstrDI47x47 .. __movstrDI47x23,
435 __movstrDI46x46 .. __movstrDI46x22,
436 __movstrDI45x45 .. __movstrDI45x21,
437 __movstrDI44x44 .. __movstrDI44x20,
438 __movstrDI43x43 .. __movstrDI43x19,
439 __movstrDI42x42 .. __movstrDI42x18,
440 __movstrDI41x41 .. __movstrDI41x17 */
442 /* Limits for using the non-looping movstr functions. For the m88100
443 processor, we assume the source and destination are word aligned.
444 The QImode and HImode limits are the break even points where memcpy
445 does just as well and beyond which memcpy does better. For the
446 m88110, we tend to assume double word alignment, but also analyze
447 the word aligned cases. The analysis is complicated because memcpy
448 may use the cache control instructions for better performance. */
450 #define MOVSTR_QI_LIMIT_88100 13
451 #define MOVSTR_HI_LIMIT_88100 38
452 #define MOVSTR_SI_LIMIT_88100 MOVSTR_SI
453 #define MOVSTR_DI_LIMIT_88100 MOVSTR_SI
455 #define MOVSTR_QI_LIMIT_88000 16
456 #define MOVSTR_HI_LIMIT_88000 38
457 #define MOVSTR_SI_LIMIT_88000 72
458 #define MOVSTR_DI_LIMIT_88000 72
460 #define MOVSTR_QI_LIMIT_88110 16
461 #define MOVSTR_HI_LIMIT_88110 38
462 #define MOVSTR_SI_LIMIT_88110 72
463 #define MOVSTR_DI_LIMIT_88110 72
465 static enum machine_mode mode_from_align
[] =
466 {VOIDmode
, QImode
, HImode
, VOIDmode
, SImode
,
467 VOIDmode
, VOIDmode
, VOIDmode
, DImode
};
468 static int max_from_align
[] = {0, MOVSTR_QI
, MOVSTR_HI
, 0, MOVSTR_SI
,
470 static int all_from_align
[] = {0, MOVSTR_QI
, MOVSTR_ODD_HI
, 0, MOVSTR_ODD_SI
,
471 0, 0, 0, MOVSTR_ODD_DI
};
473 static int best_from_align
[3][9] =
474 {0, MOVSTR_QI_LIMIT_88100
, MOVSTR_HI_LIMIT_88100
, 0, MOVSTR_SI_LIMIT_88100
,
475 0, 0, 0, MOVSTR_DI_LIMIT_88100
,
476 0, MOVSTR_QI_LIMIT_88110
, MOVSTR_HI_LIMIT_88110
, 0, MOVSTR_SI_LIMIT_88110
,
477 0, 0, 0, MOVSTR_DI_LIMIT_88110
,
478 0, MOVSTR_QI_LIMIT_88000
, MOVSTR_HI_LIMIT_88000
, 0, MOVSTR_SI_LIMIT_88000
,
479 0, 0, 0, MOVSTR_DI_LIMIT_88000
};
481 static void block_move_loop ();
482 static void block_move_no_loop ();
483 static void block_move_sequence ();
485 /* Emit code to perform a block move. Choose the best method.
487 OPERANDS[0] is the destination.
488 OPERANDS[1] is the source.
489 OPERANDS[2] is the size.
490 OPERANDS[3] is the alignment safe to use. */
493 expand_block_move (dest_mem
, src_mem
, operands
)
498 int align
= INTVAL (operands
[3]);
499 int constp
= (GET_CODE (operands
[2]) == CONST_INT
);
500 int bytes
= (constp
? INTVAL (operands
[2]) : 0);
501 int target
= (int) m88k_cpu
;
503 assert (PROCESSOR_M88100
== 0);
504 assert (PROCESSOR_M88110
== 1);
505 assert (PROCESSOR_M88000
== 2);
507 if (constp
&& bytes
<= 0)
510 /* Determine machine mode to do move with. */
511 if (align
> 4 && !TARGET_88110
)
513 else if (align
<= 0 || align
== 3)
514 abort (); /* block move invalid alignment. */
516 if (constp
&& bytes
<= 3 * align
)
517 block_move_sequence (operands
[0], dest_mem
, operands
[1], src_mem
,
520 else if (constp
&& bytes
<= best_from_align
[target
][align
])
521 block_move_no_loop (operands
[0], dest_mem
, operands
[1], src_mem
,
524 else if (constp
&& align
== 4 && TARGET_88100
)
525 block_move_loop (operands
[0], dest_mem
, operands
[1], src_mem
,
530 #ifdef TARGET_MEM_FUNCTIONS
531 emit_library_call (gen_rtx (SYMBOL_REF
, Pmode
, "memcpy"), 0,
535 convert_to_mode (TYPE_MODE (sizetype
), operands
[2],
536 TREE_UNSIGNED (sizetype
)),
537 TYPE_MODE (sizetype
));
539 emit_library_call (gen_rtx (SYMBOL_REF
, Pmode
, "bcopy"), 0,
543 convert_to_mode (TYPE_MODE (integer_type_node
),
545 TREE_UNSIGNED (integer_type_node
)),
546 TYPE_MODE (integer_type_node
));
551 /* Emit code to perform a block move by calling a looping movstr library
552 function. SIZE and ALIGN are known constants. DEST and SRC are
556 block_move_loop (dest
, dest_mem
, src
, src_mem
, size
, align
)
562 enum machine_mode mode
;
571 /* Determine machine mode to do move with. */
575 /* Determine the structure of the loop. */
576 count
= size
/ MOVSTR_LOOP
;
577 units
= (size
- count
* MOVSTR_LOOP
) / align
;
582 units
+= MOVSTR_LOOP
/ align
;
587 block_move_no_loop (dest
, dest_mem
, src
, src_mem
, size
, align
);
591 remainder
= size
- count
* MOVSTR_LOOP
- units
* align
;
593 mode
= mode_from_align
[align
];
594 sprintf (entry
, "__movstr%s%dn%d",
595 GET_MODE_NAME (mode
), MOVSTR_LOOP
, units
* align
);
596 entry_name
= get_identifier (entry
);
598 offset_rtx
= gen_rtx (CONST_INT
, VOIDmode
,
599 MOVSTR_LOOP
+ (1 - units
) * align
);
601 value_rtx
= gen_rtx (MEM
, MEM_IN_STRUCT_P (src_mem
) ? mode
: BLKmode
,
602 gen_rtx (PLUS
, Pmode
,
603 gen_rtx (REG
, Pmode
, 3),
605 RTX_UNCHANGING_P (value_rtx
) = RTX_UNCHANGING_P (src_mem
);
606 MEM_VOLATILE_P (value_rtx
) = MEM_VOLATILE_P (src_mem
);
607 MEM_IN_STRUCT_P (value_rtx
) = MEM_IN_STRUCT_P (src_mem
);
609 emit_insn (gen_call_movstrsi_loop
610 (gen_rtx (SYMBOL_REF
, Pmode
, IDENTIFIER_POINTER (entry_name
)),
611 dest
, src
, offset_rtx
, value_rtx
,
612 gen_rtx (REG
, mode
, ((units
& 1) ? 4 : 5)),
613 gen_rtx (CONST_INT
, VOIDmode
, count
)));
616 block_move_sequence (gen_rtx (REG
, Pmode
, 2), dest_mem
,
617 gen_rtx (REG
, Pmode
, 3), src_mem
,
618 remainder
, align
, MOVSTR_LOOP
+ align
);
621 /* Emit code to perform a block move by calling a non-looping library
622 function. SIZE and ALIGN are known constants. DEST and SRC are
623 registers. OFFSET is the known starting point for the output pattern. */
626 block_move_no_loop (dest
, dest_mem
, src
, src_mem
, size
, align
)
632 enum machine_mode mode
= mode_from_align
[align
];
633 int units
= size
/ align
;
634 int remainder
= size
- units
* align
;
642 if (remainder
&& size
<= all_from_align
[align
])
644 most
= all_from_align
[align
] - (align
- remainder
);
649 most
= max_from_align
[align
];
652 sprintf (entry
, "__movstr%s%dx%d",
653 GET_MODE_NAME (mode
), most
, size
- remainder
);
654 entry_name
= get_identifier (entry
);
656 offset_rtx
= gen_rtx (CONST_INT
, VOIDmode
, most
- (size
- remainder
));
658 value_rtx
= gen_rtx (MEM
, MEM_IN_STRUCT_P (src_mem
) ? mode
: BLKmode
,
659 gen_rtx (PLUS
, Pmode
,
660 gen_rtx (REG
, Pmode
, 3),
662 RTX_UNCHANGING_P (value_rtx
) = RTX_UNCHANGING_P (src_mem
);
663 MEM_VOLATILE_P (value_rtx
) = MEM_VOLATILE_P (src_mem
);
664 MEM_IN_STRUCT_P (value_rtx
) = MEM_IN_STRUCT_P (src_mem
);
666 value_reg
= ((((most
- (size
- remainder
)) / align
) & 1) == 0
667 ? (align
== 8 ? 6 : 5) : 4);
669 emit_insn (gen_call_block_move
670 (gen_rtx (SYMBOL_REF
, Pmode
, IDENTIFIER_POINTER (entry_name
)),
671 dest
, src
, offset_rtx
, value_rtx
,
672 gen_rtx (REG
, mode
, value_reg
)));
675 block_move_sequence (gen_rtx (REG
, Pmode
, 2), dest_mem
,
676 gen_rtx (REG
, Pmode
, 3), src_mem
,
677 remainder
, align
, most
);
680 /* Emit code to perform a block move with an offset sequence of ld/st
681 instructions (..., ld 0, st 1, ld 1, st 0, ...). SIZE and ALIGN are
682 known constants. DEST and SRC are registers. OFFSET is the known
683 starting point for the output pattern. */
686 block_move_sequence (dest
, dest_mem
, src
, src_mem
, size
, align
, offset
)
694 enum machine_mode mode
[2];
699 int offset_ld
= offset
;
700 int offset_st
= offset
;
702 active
[0] = active
[1] = FALSE
;
704 /* Establish parameters for the first load and for the second load if
705 it is known to be the same mode as the first. */
706 amount
[0] = amount
[1] = align
;
707 mode
[0] = mode_from_align
[align
];
708 temp
[0] = gen_reg_rtx (mode
[0]);
709 if (size
>= 2 * align
)
712 temp
[1] = gen_reg_rtx (mode
[1]);
723 /* Change modes as the sequence tails off. */
724 if (size
< amount
[next
])
726 amount
[next
] = (size
>= 4 ? 4 : (size
>= 2 ? 2 : 1));
727 mode
[next
] = mode_from_align
[amount
[next
]];
728 temp
[next
] = gen_reg_rtx (mode
[next
]);
730 size
-= amount
[next
];
732 MEM_IN_STRUCT_P (src_mem
) ? mode
[next
] : BLKmode
,
733 gen_rtx (PLUS
, Pmode
, src
,
734 gen_rtx (CONST_INT
, SImode
, offset_ld
)));
735 RTX_UNCHANGING_P (srcp
) = RTX_UNCHANGING_P (src_mem
);
736 MEM_VOLATILE_P (srcp
) = MEM_VOLATILE_P (src_mem
);
737 MEM_IN_STRUCT_P (srcp
) = MEM_IN_STRUCT_P (src_mem
);
738 emit_insn (gen_rtx (SET
, VOIDmode
, temp
[next
], srcp
));
739 offset_ld
+= amount
[next
];
745 active
[phase
] = FALSE
;
747 MEM_IN_STRUCT_P (dest_mem
) ? mode
[phase
] : BLKmode
,
748 gen_rtx (PLUS
, Pmode
, dest
,
749 gen_rtx (CONST_INT
, SImode
, offset_st
)));
750 RTX_UNCHANGING_P (dstp
) = RTX_UNCHANGING_P (dest_mem
);
751 MEM_VOLATILE_P (dstp
) = MEM_VOLATILE_P (dest_mem
);
752 MEM_IN_STRUCT_P (dstp
) = MEM_IN_STRUCT_P (dest_mem
);
753 emit_insn (gen_rtx (SET
, VOIDmode
, dstp
, temp
[phase
]));
754 offset_st
+= amount
[phase
];
757 while (active
[next
]);
760 /* Emit the code to do an AND operation. */
763 output_and (operands
)
768 if (REG_P (operands
[2]))
769 return "and %0,%1,%2";
771 value
= INTVAL (operands
[2]);
772 if (SMALL_INTVAL (value
))
773 return "mask %0,%1,%2";
774 else if ((value
& 0xffff0000) == 0xffff0000)
775 return "and %0,%1,%x2";
776 else if ((value
& 0xffff) == 0xffff)
777 return "and.u %0,%1,%X2";
778 else if ((value
& 0xffff) == 0)
779 return "mask.u %0,%1,%X2";
780 else if (integer_ok_for_set (~value
))
781 return "clr %0,%1,%S2";
783 return "and.u %0,%1,%X2\n\tand %0,%0,%x2";
786 /* Emit the code to do an inclusive OR operation. */
789 output_ior (operands
)
794 if (REG_P (operands
[2]))
795 return "or %0,%1,%2";
797 value
= INTVAL (operands
[2]);
798 if (SMALL_INTVAL (value
))
799 return "or %0,%1,%2";
800 else if ((value
& 0xffff) == 0)
801 return "or.u %0,%1,%X2";
802 else if (integer_ok_for_set (value
))
803 return "set %0,%1,%s2";
805 return "or.u %0,%1,%X2\n\tor %0,%0,%x2";
808 /* Emit the instructions for doing an XOR. */
811 output_xor (operands
)
816 if (REG_P (operands
[2]))
817 return "xor %0,%1,%2";
819 value
= INTVAL (operands
[2]);
820 if (SMALL_INTVAL (value
))
821 return "xor %0,%1,%2";
822 else if ((value
& 0xffff) == 0)
823 return "xor.u %0,%1,%X2";
825 return "xor.u %0,%1,%X2\n\txor %0,%0,%x2";
828 /* Output a call. Normally this is just bsr or jsr, but this also deals with
829 accomplishing a branch after the call by incrementing r1. This requires
830 that various assembler bugs be accommodated. The 4.30 DG/UX assembler
831 requires that forward references not occur when computing the difference of
832 two labels. The [version?] Motorola assembler computes a word difference.
833 No doubt there's more to come!
835 It would seem the same idea could be used to tail call, but in this case,
836 the epilogue will be non-null. */
838 static rtx sb_name
= 0;
839 static rtx sb_high
= 0;
840 static rtx sb_low
= 0;
843 output_call (operands
, addr
)
853 /* This can be generalized, but there is currently no need. */
854 if (XVECLEN (final_sequence
, 0) != 2)
857 /* The address of interior insns is not computed, so use the sequence. */
858 seq_insn
= NEXT_INSN (PREV_INSN (XVECEXP (final_sequence
, 0, 0)));
859 jump
= XVECEXP (final_sequence
, 0, 1);
860 if (GET_CODE (jump
) == JUMP_INSN
)
864 rtx dest
= XEXP (SET_SRC (PATTERN (jump
)), 0);
865 int delta
= 4 * (insn_addresses
[INSN_UID (dest
)]
866 - insn_addresses
[INSN_UID (seq_insn
)]
868 #if (MONITOR_GCC & 0x2) /* How often do long branches happen? */
869 if ((unsigned) (delta
+ 0x8000) >= 0x10000)
870 warning ("Internal gcc monitor: short-branch(%x)", delta
);
873 /* Delete the jump. */
874 PUT_CODE (jump
, NOTE
);
875 NOTE_LINE_NUMBER (jump
) = NOTE_INSN_DELETED
;
876 NOTE_SOURCE_FILE (jump
) = 0;
878 /* We only do this optimization if -O2, modifying the value of
879 r1 in the delay slot confuses debuggers and profilers on some
882 If we loose, we must use the non-delay form. This is unlikely
883 to ever happen. If it becomes a problem, claim that a call
884 has two delay slots and only the second can be filled with
887 The 88110 can lose when a jsr.n r1 is issued and a page fault
888 occurs accessing the delay slot. So don't use jsr.n form when
891 #ifdef AS_BUG_IMMEDIATE_LABEL /* The assembler restricts immediate values. */
893 || ! ADD_INTVAL (delta
* 2)
896 || ! ADD_INTVAL (delta
)
898 || (REG_P (addr
) && REGNO (addr
) == 1))
904 ? "bsr %0#plt\n\tbr %l1"
905 : "bsr %0\n\tbr %l1"));
908 /* Output the short branch form. */
909 output_asm_insn ((REG_P (addr
)
911 : (flag_pic
? "bsr.n %0#plt" : "bsr.n %0")),
916 ? "subu %#r1,%#r1,.-%l0+4"
917 : "addu %#r1,%#r1,%l0-.-4");
920 operands
[0] = gen_label_rtx ();
921 operands
[1] = gen_label_rtx ();
926 last
= "subu %#r1,%#r1,%l0\n%l1:";
932 last
= "addu %#r1,%#r1,%l0\n%l1:";
935 /* Record the values to be computed later as "def name,high-low". */
936 sb_name
= gen_rtx (EXPR_LIST
, VOIDmode
, operands
[0], sb_name
);
937 sb_high
= gen_rtx (EXPR_LIST
, VOIDmode
, high
, sb_high
);
938 sb_low
= gen_rtx (EXPR_LIST
, VOIDmode
, low
, sb_low
);
939 #endif /* Don't USE_GAS */
946 : (flag_pic
? "bsr%. %0#plt" : "bsr%. %0"));
950 output_short_branch_defs (stream
)
953 char name
[256], high
[256], low
[256];
955 for (; sb_name
&& sb_high
&& sb_low
;
956 sb_name
= XEXP (sb_name
, 1),
957 sb_high
= XEXP (sb_high
, 1),
958 sb_low
= XEXP (sb_low
, 1))
960 ASM_GENERATE_INTERNAL_LABEL
961 (name
, "L", CODE_LABEL_NUMBER (XEXP (sb_name
, 0)));
962 ASM_GENERATE_INTERNAL_LABEL
963 (high
, "L", CODE_LABEL_NUMBER (XEXP (sb_high
, 0)));
964 ASM_GENERATE_INTERNAL_LABEL
965 (low
, "L", CODE_LABEL_NUMBER (XEXP (sb_low
, 0)));
966 /* This will change as the assembler requirements become known. */
967 fprintf (stream
, "\t%s\t %s,%s-%s\n",
968 SET_ASM_OP
, &name
[1], &high
[1], &low
[1]);
970 if (sb_name
|| sb_high
|| sb_low
)
974 /* Return truth value of the statement that this conditional branch is likely
975 to fall through. CONDITION, is the condition that JUMP_INSN is testing. */
978 mostly_false_jump (jump_insn
, condition
)
979 rtx jump_insn
, condition
;
981 rtx target_label
= JUMP_LABEL (jump_insn
);
984 /* Much of this isn't computed unless we're optimizing. */
988 /* Determine if one path or the other leads to a return. */
989 for (insnt
= NEXT_INSN (target_label
);
991 insnt
= NEXT_INSN (insnt
))
993 if (GET_CODE (insnt
) == JUMP_INSN
)
995 else if (GET_CODE (insnt
) == INSN
996 && GET_CODE (PATTERN (insnt
)) == SEQUENCE
997 && GET_CODE (XVECEXP (PATTERN (insnt
), 0, 0)) == JUMP_INSN
)
999 insnt
= XVECEXP (PATTERN (insnt
), 0, 0);
1004 && (GET_CODE (PATTERN (insnt
)) == RETURN
1005 || (GET_CODE (PATTERN (insnt
)) == SET
1006 && GET_CODE (SET_SRC (PATTERN (insnt
))) == REG
1007 && REGNO (SET_SRC (PATTERN (insnt
))) == 1)))
1010 for (insnj
= NEXT_INSN (jump_insn
);
1012 insnj
= NEXT_INSN (insnj
))
1014 if (GET_CODE (insnj
) == JUMP_INSN
)
1016 else if (GET_CODE (insnj
) == INSN
1017 && GET_CODE (PATTERN (insnj
)) == SEQUENCE
1018 && GET_CODE (XVECEXP (PATTERN (insnj
), 0, 0)) == JUMP_INSN
)
1020 insnj
= XVECEXP (PATTERN (insnj
), 0, 0);
1025 && (GET_CODE (PATTERN (insnj
)) == RETURN
1026 || (GET_CODE (PATTERN (insnj
)) == SET
1027 && GET_CODE (SET_SRC (PATTERN (insnj
))) == REG
1028 && REGNO (SET_SRC (PATTERN (insnj
))) == 1)))
1031 /* Predict to not return. */
1032 if ((insnt
== 0) != (insnj
== 0))
1033 return (insnt
== 0);
1035 /* Predict loops to loop. */
1036 for (insnt
= PREV_INSN (target_label
);
1037 insnt
&& GET_CODE (insnt
) == NOTE
;
1038 insnt
= PREV_INSN (insnt
))
1039 if (NOTE_LINE_NUMBER (insnt
) == NOTE_INSN_LOOP_END
)
1041 else if (NOTE_LINE_NUMBER (insnt
) == NOTE_INSN_LOOP_BEG
)
1043 else if (NOTE_LINE_NUMBER (insnt
) == NOTE_INSN_LOOP_CONT
)
1046 /* Predict backward branches usually take. */
1048 insnj
= NEXT_INSN (PREV_INSN (XVECEXP (final_sequence
, 0, 0)));
1051 if (insn_addresses
[INSN_UID (insnj
)]
1052 > insn_addresses
[INSN_UID (target_label
)])
1055 /* EQ tests are usually false and NE tests are usually true. Also,
1056 most quantities are positive, so we can make the appropriate guesses
1057 about signed comparisons against zero. Consider unsigned comparisons
1058 to be a range check and assume quantities to be in range. */
1059 switch (GET_CODE (condition
))
1062 /* Unconditional branch. */
1071 case GTU
: /* Must get casesi right at least. */
1072 if (XEXP (condition
, 1) == const0_rtx
)
1079 if (XEXP (condition
, 1) == const0_rtx
)
1087 /* Return true if the operand is a power of two and is a floating
1088 point type (to optimize division by power of two into multiplication). */
1091 real_power_of_2_operand (op
, mode
)
1093 enum machine_mode mode
;
1097 int i
[sizeof (REAL_VALUE_TYPE
) / sizeof (int)];
1098 struct { /* IEEE double precision format */
1100 unsigned exponent
: 11;
1101 unsigned mantissa1
: 20;
1104 struct { /* IEEE double format to quick check */
1105 unsigned sign
: 1; /* if it fits in a float */
1106 unsigned exponent1
: 4;
1107 unsigned exponent2
: 7;
1108 unsigned mantissa1
: 20;
1113 if (GET_MODE (op
) != DFmode
&& GET_MODE (op
) != SFmode
)
1116 if (GET_CODE (op
) != CONST_DOUBLE
)
1119 u
.i
[0] = CONST_DOUBLE_LOW (op
);
1120 u
.i
[1] = CONST_DOUBLE_HIGH (op
);
1122 if (u
.s
.mantissa1
!= 0 || u
.s
.mantissa2
!= 0 /* not a power of two */
1123 || u
.s
.exponent
== 0 /* constant 0.0 */
1124 || u
.s
.exponent
== 0x7ff /* NAN */
1125 || (u
.s2
.exponent1
!= 0x8 && u
.s2
.exponent1
!= 0x7))
1126 return 0; /* const won't fit in float */
1131 /* Make OP legitimate for mode MODE. Currently this only deals with DFmode
1132 operands, putting them in registers and making CONST_DOUBLE values
1133 SFmode where possible. */
1136 legitimize_operand (op
, mode
)
1138 enum machine_mode mode
;
1142 union real_extract r
;
1143 struct { /* IEEE double precision format */
1145 unsigned exponent
: 11;
1146 unsigned mantissa1
: 20;
1149 struct { /* IEEE double format to quick check */
1150 unsigned sign
: 1; /* if it fits in a float */
1151 unsigned exponent1
: 4;
1152 unsigned exponent2
: 7;
1153 unsigned mantissa1
: 20;
1158 if (GET_CODE (op
) == REG
|| mode
!= DFmode
)
1161 if (GET_CODE (op
) == CONST_DOUBLE
)
1163 bcopy (&CONST_DOUBLE_LOW (op
), &u
.r
, sizeof u
);
1164 if (u
.d
.exponent
!= 0x7ff /* NaN */
1165 && u
.d
.mantissa2
== 0 /* Mantissa fits */
1166 && (u
.s
.exponent1
== 0x8 || u
.s
.exponent1
== 0x7) /* Exponent fits */
1167 && (temp
= simplify_unary_operation (FLOAT_TRUNCATE
, SFmode
,
1169 return gen_rtx (FLOAT_EXTEND
, mode
, force_reg (SFmode
, temp
));
1171 else if (register_operand (op
, mode
))
1174 return force_reg (mode
, op
);
1177 /* Return true if OP is a suitable input for a move insn. */
1180 move_operand (op
, mode
)
1182 enum machine_mode mode
;
1184 if (register_operand (op
, mode
))
1186 if (GET_CODE (op
) == CONST_INT
)
1187 return (classify_integer (mode
, INTVAL (op
)) < m88k_oru_hi16
);
1188 if (GET_MODE (op
) != mode
)
1190 if (GET_CODE (op
) == SUBREG
)
1191 op
= SUBREG_REG (op
);
1192 if (GET_CODE (op
) != MEM
)
1196 if (GET_CODE (op
) == LO_SUM
)
1197 return (REG_P (XEXP (op
, 0))
1198 && symbolic_address_p (XEXP (op
, 1)));
1199 return memory_address_p (mode
, op
);
1202 /* Return true if OP is suitable for a call insn. */
1205 call_address_operand (op
, mode
)
1207 enum machine_mode mode
;
1209 return (REG_P (op
) || symbolic_address_p (op
));
1212 /* Returns true if OP is either a symbol reference or a sum of a symbol
1213 reference and a constant. */
1216 symbolic_address_p (op
)
1219 switch (GET_CODE (op
))
1227 return ((GET_CODE (XEXP (op
, 0)) == SYMBOL_REF
1228 || GET_CODE (XEXP (op
, 0)) == LABEL_REF
)
1229 && GET_CODE (XEXP (op
, 1)) == CONST_INT
);
1236 /* Return true if OP is a register or const0_rtx. */
1239 reg_or_0_operand (op
, mode
)
1241 enum machine_mode mode
;
1243 return (op
== const0_rtx
|| register_operand (op
, mode
));
1246 /* Nonzero if OP is a valid second operand for an arithmetic insn. */
1249 arith_operand (op
, mode
)
1251 enum machine_mode mode
;
1253 return (register_operand (op
, mode
)
1254 || (GET_CODE (op
) == CONST_INT
&& SMALL_INT (op
)));
1257 /* Return true if OP is a register or 5 bit integer. */
1260 arith5_operand (op
, mode
)
1262 enum machine_mode mode
;
1264 return (register_operand (op
, mode
)
1265 || (GET_CODE (op
) == CONST_INT
&& (unsigned) INTVAL (op
) < 32));
1269 arith32_operand (op
, mode
)
1271 enum machine_mode mode
;
1273 return (register_operand (op
, mode
) || GET_CODE (op
) == CONST_INT
);
1277 arith64_operand (op
, mode
)
1279 enum machine_mode mode
;
1281 return (register_operand (op
, mode
)
1282 || GET_CODE (op
) == CONST_INT
1283 || (GET_CODE (op
) == CONST_DOUBLE
&& GET_MODE (op
) == VOIDmode
));
1287 int5_operand (op
, mode
)
1289 enum machine_mode mode
;
1291 return (GET_CODE (op
) == CONST_INT
&& (unsigned) INTVAL (op
) < 32);
1295 int32_operand (op
, mode
)
1297 enum machine_mode mode
;
1299 return (GET_CODE (op
) == CONST_INT
);
1302 /* Return true if OP is a register or a valid immediate operand for
1306 add_operand (op
, mode
)
1308 enum machine_mode mode
;
1310 return (register_operand (op
, mode
)
1311 || (GET_CODE (op
) == CONST_INT
&& ADD_INT (op
)));
1314 /* Nonzero if this is a bitmask filling the bottom bits, for optimizing and +
1315 shift left combinations into a single mak instruction. */
1321 return (value
&& POWER_OF_2_or_0 (value
+ 1));
1325 reg_or_bbx_mask_operand (op
, mode
)
1327 enum machine_mode mode
;
1330 if (register_operand (op
, mode
))
1332 if (GET_CODE (op
) != CONST_INT
)
1335 value
= INTVAL (op
);
1336 if (POWER_OF_2 (value
))
1342 /* Return true if OP is valid to use in the context of a floating
1343 point operation. Special case 0.0, since we can use r0. */
1346 real_or_0_operand (op
, mode
)
1348 enum machine_mode mode
;
1350 if (mode
!= SFmode
&& mode
!= DFmode
)
1353 return (register_operand (op
, mode
)
1354 || (GET_CODE (op
) == CONST_DOUBLE
1355 && op
== CONST0_RTX (mode
)));
1358 /* Return true if OP is valid to use in the context of logic arithmetic
1359 on condition codes. */
1362 partial_ccmode_register_operand (op
, mode
)
1364 enum machine_mode mode
;
1366 return register_operand (op
, CCmode
) || register_operand (op
, CCEVENmode
);
1369 /* Return true if OP is a relational operator. */
1374 enum machine_mode mode
;
1376 switch (GET_CODE (op
))
1395 even_relop (op
, mode
)
1397 enum machine_mode mode
;
1399 switch (GET_CODE (op
))
1413 odd_relop (op
, mode
)
1415 enum machine_mode mode
;
1417 switch (GET_CODE (op
))
1430 /* Return true if OP is a relational operator, and is not an unsigned
1431 relational operator. */
1434 relop_no_unsigned (op
, mode
)
1436 enum machine_mode mode
;
1438 switch (GET_CODE (op
))
1446 /* @@ What is this test doing? Why not use `mode'? */
1447 if (GET_MODE_CLASS (GET_MODE (op
)) == MODE_FLOAT
1448 || GET_MODE (op
) == DImode
1449 || GET_MODE_CLASS (GET_MODE (XEXP (op
, 0))) == MODE_FLOAT
1450 || GET_MODE (XEXP (op
, 0)) == DImode
1451 || GET_MODE_CLASS (GET_MODE (XEXP (op
, 1))) == MODE_FLOAT
1452 || GET_MODE (XEXP (op
, 1)) == DImode
)
1460 /* Return true if the code of this rtx pattern is EQ or NE. */
1463 equality_op (op
, mode
)
1465 enum machine_mode mode
;
1467 return (GET_CODE (op
) == EQ
|| GET_CODE (op
) == NE
);
1470 /* Return true if the code of this rtx pattern is pc or label_ref. */
1473 pc_or_label_ref (op
, mode
)
1475 enum machine_mode mode
;
1477 return (GET_CODE (op
) == PC
|| GET_CODE (op
) == LABEL_REF
);
1480 /* Output to FILE the start of the assembler file. */
1490 output_option (file
, sep
, type
, name
, indent
, pos
, max
)
1499 if (strlen (sep
) + strlen (type
) + strlen (name
) + pos
> max
)
1501 fprintf (file
, indent
);
1502 return fprintf (file
, "%s%s", type
, name
);
1504 return pos
+ fprintf (file
, "%s%s%s", sep
, type
, name
);
1507 static struct { char *name
; int value
; } m_options
[] = TARGET_SWITCHES
;
1510 output_options (file
, f_options
, f_len
, W_options
, W_len
,
1511 pos
, max
, sep
, indent
, term
)
1513 struct options
*f_options
;
1514 struct options
*W_options
;
1524 pos
= output_option (file
, sep
, "-O", "", indent
, pos
, max
);
1525 if (write_symbols
!= NO_DEBUG
)
1526 pos
= output_option (file
, sep
, "-g", "", indent
, pos
, max
);
1527 if (flag_traditional
)
1528 pos
= output_option (file
, sep
, "-traditional", "", indent
, pos
, max
);
1530 pos
= output_option (file
, sep
, "-p", "", indent
, pos
, max
);
1531 if (profile_block_flag
)
1532 pos
= output_option (file
, sep
, "-a", "", indent
, pos
, max
);
1534 for (j
= 0; j
< f_len
; j
++)
1535 if (*f_options
[j
].variable
== f_options
[j
].on_value
)
1536 pos
= output_option (file
, sep
, "-f", f_options
[j
].string
,
1539 for (j
= 0; j
< W_len
; j
++)
1540 if (*W_options
[j
].variable
== W_options
[j
].on_value
)
1541 pos
= output_option (file
, sep
, "-W", W_options
[j
].string
,
1544 for (j
= 0; j
< sizeof m_options
/ sizeof m_options
[0]; j
++)
1545 if (m_options
[j
].name
[0] != '\0'
1546 && m_options
[j
].value
> 0
1547 && ((m_options
[j
].value
& target_flags
)
1548 == m_options
[j
].value
))
1549 pos
= output_option (file
, sep
, "-m", m_options
[j
].name
,
1552 if (m88k_short_data
)
1553 pos
= output_option (file
, sep
, "-mshort-data-", m88k_short_data
,
1556 fprintf (file
, term
);
1560 output_file_start (file
, f_options
, f_len
, W_options
, W_len
)
1562 struct options
*f_options
;
1563 struct options
*W_options
;
1568 ASM_FIRST_LINE (file
);
1571 fprintf (file
, "\t%s\n", REQUIRES_88110_ASM_OP
);
1572 output_file_directive (file
, main_input_filename
);
1573 /* Switch to the data section so that the coffsem symbol and the
1574 gcc2_compiled. symbol aren't in the text section. */
1578 if (TARGET_IDENTIFY_REVISION
)
1582 time_t now
= time ((time_t *)0);
1583 sprintf (indent
, "]\"\n\t%s\t \"@(#)%s [", IDENT_ASM_OP
, main_input_filename
);
1584 fprintf (file
, indent
+3);
1585 pos
= fprintf (file
, "gcc %s, %.24s,", VERSION_STRING
, ctime (&now
));
1587 /* ??? It would be nice to call print_switch_values here (and thereby
1588 let us delete output_options) but this is kept in until it is known
1589 whether the change in content format matters. */
1590 output_options (file
, f_options
, f_len
, W_options
, W_len
,
1591 pos
, 150 - strlen (indent
), " ", indent
, "]\"\n\n");
1593 fprintf (file
, "]\"\n");
1594 print_switch_values (file
, 0, 150 - strlen (indent
),
1595 indent
+ 3, " ", "]\"\n");
1600 /* Output an ascii string. */
1603 output_ascii (file
, opcode
, max
, p
, size
)
1613 register int num
= 0;
1615 fprintf (file
, "\t%s\t \"", opcode
);
1616 for (i
= 0; i
< size
; i
++)
1618 register int c
= p
[i
];
1622 fprintf (file
, "\"\n\t%s\t \"", opcode
);
1626 if (c
== '\"' || c
== '\\')
1634 else if (in_escape
&& c
>= '0' && c
<= '9')
1636 /* If a digit follows an octal-escape, the Vax assembler fails
1637 to stop reading the escape after three digits. Continue to
1638 output the values as an octal-escape until a non-digit is
1640 fprintf (file
, "\\%03o", c
);
1643 else if ((c
>= ' ' && c
< 0177) || (c
== '\t'))
1653 /* Some assemblers can't handle \a, \v, or \?. */
1654 case '\f': c
= 'f'; goto escape
;
1655 case '\b': c
= 'b'; goto escape
;
1656 case '\r': c
= 'r'; goto escape
;
1657 case '\n': c
= 'n'; goto escape
;
1660 fprintf (file
, "\\%03o", c
);
1665 fprintf (file
, "\"\n");
1668 /* Output a label (allows insn-output.c to be compiled without including
1669 m88k.c or needing to include stdio.h). */
1672 output_label (label_number
)
1675 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file
, "L", label_number
);
1678 /* Generate the assembly code for function entry.
1680 The prologue is responsible for setting up the stack frame,
1681 initializing the frame pointer register, saving registers that must be
1682 saved, and allocating SIZE additional bytes of storage for the
1683 local variables. SIZE is an integer. FILE is a stdio
1684 stream to which the assembler code should be output.
1686 The label for the beginning of the function need not be output by this
1687 macro. That has already been done when the macro is run.
1689 To determine which registers to save, the macro can refer to the array
1690 `regs_ever_live': element R is nonzero if hard register
1691 R is used anywhere within the function. This implies the
1692 function prologue should save register R, but not if it is one
1693 of the call-used registers.
1695 On machines where functions may or may not have frame-pointers, the
1696 function entry code must vary accordingly; it must set up the frame
1697 pointer if one is wanted, and not otherwise. To determine whether a
1698 frame pointer is in wanted, the macro can refer to the variable
1699 `frame_pointer_needed'. The variable's value will be 1 at run
1700 time in a function that needs a frame pointer.
1702 On machines where an argument may be passed partly in registers and
1703 partly in memory, this macro must examine the variable
1704 `current_function_pretend_args_size', and allocate that many bytes
1705 of uninitialized space on the stack just underneath the first argument
1706 arriving on the stack. (This may not be at the very end of the stack,
1707 if the calling sequence has pushed anything else since pushing the stack
1708 arguments. But usually, on such machines, nothing else has been pushed
1709 yet, because the function prologue itself does all the pushing.)
1711 If `ACCUMULATE_OUTGOING_ARGS' is defined, the variable
1712 `current_function_outgoing_args_size' contains the size in bytes
1713 required for the outgoing arguments. This macro must add that
1714 amount of uninitialized space to very bottom of the stack.
1716 The stack frame we use looks like this:
1719 |==============================================|
1721 |==============================================|
1722 | [caller's outgoing memory arguments] |
1723 |==============================================|
1724 | caller's outgoing argument area (32 bytes) |
1725 sp -> |==============================================| <- ap
1726 | [local variable space] |
1727 |----------------------------------------------|
1728 | [return address (r1)] |
1729 |----------------------------------------------|
1730 | [previous frame pointer (r30)] |
1731 |==============================================| <- fp
1732 | [preserved registers (r25..r14)] |
1733 |----------------------------------------------|
1734 | [preserved registers (x29..x22)] |
1735 |==============================================|
1736 | [dynamically allocated space (alloca)] |
1737 |==============================================|
1738 | [callee's outgoing memory arguments] |
1739 |==============================================|
1740 | [callee's outgoing argument area (32 bytes)] |
1741 |==============================================| <- sp
1745 r1 and r30 must be saved if debugging.
1747 fp (if present) is located two words down from the local
1751 static void emit_add ();
1752 static void preserve_registers ();
1753 static void emit_ldst ();
1754 static void output_tdesc ();
1758 static char save_regs
[FIRST_PSEUDO_REGISTER
];
1759 static int frame_laid_out
;
1760 static int frame_size
;
1761 static int variable_args_p
;
1762 static int epilogue_marked
;
1763 static int prologue_marked
;
1765 extern char call_used_regs
[];
1766 extern int current_function_pretend_args_size
;
1767 extern int current_function_outgoing_args_size
;
1768 extern int frame_pointer_needed
;
1770 #define FIRST_OCS_PRESERVE_REGISTER 14
1771 #define LAST_OCS_PRESERVE_REGISTER 30
1773 #define FIRST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 22)
1774 #define LAST_OCS_EXTENDED_PRESERVE_REGISTER (32 + 31)
1776 #define STACK_UNIT_BOUNDARY (STACK_BOUNDARY / BITS_PER_UNIT)
1777 #define ROUND_CALL_BLOCK_SIZE(BYTES) \
1778 (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1))
1780 /* Establish the position of the FP relative to the SP. This is done
1781 either during FUNCTION_PROLOGUE or by INITIAL_ELIMINATION_OFFSET. */
1784 m88k_layout_frame ()
1790 bzero ((char *) &save_regs
[0], sizeof (save_regs
));
1791 sp_size
= nregs
= nxregs
= 0;
1792 frame_size
= get_frame_size ();
1794 /* Since profiling requires a call, make sure r1 is saved. */
1795 if (profile_flag
|| profile_block_flag
)
1798 /* If we are producing debug information, store r1 and r30 where the
1799 debugger wants to find them (r30 at r30+0, r1 at r30+4). Space has
1800 already been reserved for r1/r30 in STARTING_FRAME_OFFSET. */
1801 if (write_symbols
!= NO_DEBUG
&& !TARGET_OCS_FRAME_POSITION
)
1804 /* If there is a call, alloca is used, __builtin_alloca is used, or
1805 a dynamic-sized object is defined, add the 8 additional words
1806 for the callee's argument area. The common denominator is that the
1807 FP is required. may_call_alloca only gets calls to alloca;
1808 current_function_calls_alloca gets alloca and __builtin_alloca. */
1809 if (regs_ever_live
[1] || frame_pointer_needed
)
1812 sp_size
+= REG_PARM_STACK_SPACE (0);
1815 /* If we are producing PIC, save the addressing base register and r1. */
1816 if (flag_pic
&& current_function_uses_pic_offset_table
)
1818 save_regs
[PIC_OFFSET_TABLE_REGNUM
] = 1;
1822 /* If a frame is requested, save the previous FP, and the return
1823 address (r1), so that a traceback can be done without using tdesc
1824 information. Otherwise, simply save the FP if it is used as
1825 a preserve register. */
1826 if (frame_pointer_needed
)
1827 save_regs
[FRAME_POINTER_REGNUM
] = save_regs
[1] = 1;
1828 else if (regs_ever_live
[FRAME_POINTER_REGNUM
])
1829 save_regs
[FRAME_POINTER_REGNUM
] = 1;
1831 /* Figure out which extended register(s) needs to be saved. */
1832 for (regno
= FIRST_EXTENDED_REGISTER
+ 1; regno
< FIRST_PSEUDO_REGISTER
;
1834 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
1836 save_regs
[regno
] = 1;
1840 /* Figure out which normal register(s) needs to be saved. */
1841 for (regno
= 2; regno
< FRAME_POINTER_REGNUM
; regno
++)
1842 if (regs_ever_live
[regno
] && ! call_used_regs
[regno
])
1844 save_regs
[regno
] = 1;
1848 /* Achieve greatest use of double memory ops. Either we end up saving
1849 r30 or we use that slot to align the registers we do save. */
1850 if (nregs
>= 2 && save_regs
[1] && !save_regs
[FRAME_POINTER_REGNUM
])
1853 nregs
+= save_regs
[1] + save_regs
[FRAME_POINTER_REGNUM
];
1854 /* if we need to align extended registers, add a word */
1855 if (nxregs
> 0 && (nregs
& 1) != 0)
1857 sp_size
+= 4 * nregs
;
1858 sp_size
+= 8 * nxregs
;
1859 sp_size
+= current_function_outgoing_args_size
;
1861 /* The first two saved registers are placed above the new frame pointer
1862 if any. In the only case this matters, they are r1 and r30. */
1863 if (frame_pointer_needed
|| sp_size
)
1864 m88k_fp_offset
= ROUND_CALL_BLOCK_SIZE (sp_size
- STARTING_FRAME_OFFSET
);
1866 m88k_fp_offset
= -STARTING_FRAME_OFFSET
;
1867 m88k_stack_size
= m88k_fp_offset
+ STARTING_FRAME_OFFSET
;
1869 /* First, combine m88k_stack_size and size. If m88k_stack_size is
1870 non-zero, align the frame size to 8 mod 16; otherwise align the
1871 frame size to 0 mod 16. (If stacks are 8 byte aligned, this ends
1875 = ((m88k_stack_size
? STACK_UNIT_BOUNDARY
- STARTING_FRAME_OFFSET
: 0)
1876 - (frame_size
% STACK_UNIT_BOUNDARY
));
1880 need
+= STACK_UNIT_BOUNDARY
;
1881 (void) assign_stack_local (BLKmode
, need
, BITS_PER_UNIT
);
1882 frame_size
= get_frame_size ();
1885 = ROUND_CALL_BLOCK_SIZE (m88k_stack_size
+ frame_size
1886 + current_function_pretend_args_size
);
1890 /* Return true if this function is known to have a null prologue. */
1895 if (! reload_completed
)
1897 if (! frame_laid_out
)
1898 m88k_layout_frame ();
1899 return (! frame_pointer_needed
1902 && m88k_stack_size
== 0);
1905 /* Determine if the current function has any references to the arg pointer.
1906 This is done indirectly by examining the DECL_ARGUMENTS' DECL_RTL.
1907 It is OK to return TRUE if there are no references, but FALSE must be
1915 if (current_function_decl
== 0
1916 || current_function_varargs
1920 for (parm
= DECL_ARGUMENTS (current_function_decl
);
1922 parm
= TREE_CHAIN (parm
))
1924 if (DECL_RTL (parm
) == 0
1925 || GET_CODE (DECL_RTL (parm
)) == MEM
)
1928 if (DECL_INCOMING_RTL (parm
) == 0
1929 || GET_CODE (DECL_INCOMING_RTL (parm
)) == MEM
)
1936 m88k_begin_prologue (stream
, size
)
1940 if (TARGET_OMIT_LEAF_FRAME_POINTER
&& ! quiet_flag
&& leaf_function_p ())
1941 fprintf (stderr
, "$");
1943 m88k_prologue_done
= 1; /* it's ok now to put out ln directives */
1947 m88k_end_prologue (stream
)
1950 if (TARGET_OCS_DEBUG_INFO
&& !prologue_marked
)
1952 PUT_OCS_FUNCTION_START (stream
);
1953 prologue_marked
= 1;
1955 /* If we've already passed the start of the epilogue, say that
1956 it starts here. This marks the function as having a null body,
1957 but at a point where the return address is in a known location.
1959 Originally, I thought this couldn't happen, but the pic prologue
1960 for leaf functions ends with the instruction that restores the
1961 return address from the temporary register. If the temporary
1962 register is never used, that instruction can float all the way
1963 to the end of the function. */
1964 if (epilogue_marked
)
1965 PUT_OCS_FUNCTION_END (stream
);
1970 m88k_expand_prologue ()
1972 m88k_layout_frame ();
1974 if (TARGET_OPTIMIZE_ARG_AREA
1976 && ! uses_arg_area_p ())
1978 /* The incoming argument area is used for stack space if it is not
1979 used (or if -mno-optimize-arg-area is given). */
1980 if ((m88k_stack_size
-= REG_PARM_STACK_SPACE (0)) < 0)
1981 m88k_stack_size
= 0;
1984 if (m88k_stack_size
)
1985 emit_add (stack_pointer_rtx
, stack_pointer_rtx
, -m88k_stack_size
);
1987 if (nregs
|| nxregs
)
1988 preserve_registers (m88k_fp_offset
+ 4, 1);
1990 if (frame_pointer_needed
)
1991 emit_add (frame_pointer_rtx
, stack_pointer_rtx
, m88k_fp_offset
);
1993 if (flag_pic
&& save_regs
[PIC_OFFSET_TABLE_REGNUM
])
1995 rtx return_reg
= gen_rtx (REG
, SImode
, 1);
1996 rtx label
= gen_label_rtx ();
2001 temp_reg
= gen_rtx (REG
, SImode
, TEMP_REGNUM
);
2002 emit_move_insn (temp_reg
, return_reg
);
2004 emit_insn (gen_locate1 (pic_offset_table_rtx
, label
));
2005 emit_insn (gen_locate2 (pic_offset_table_rtx
, label
));
2006 emit_insn (gen_addsi3 (pic_offset_table_rtx
,
2007 pic_offset_table_rtx
, return_reg
));
2009 emit_move_insn (return_reg
, temp_reg
);
2011 if (profile_flag
|| profile_block_flag
)
2012 emit_insn (gen_blockage ());
2015 /* This function generates the assembly code for function exit,
2016 on machines that need it. Args are same as for FUNCTION_PROLOGUE.
2018 The function epilogue should not depend on the current stack pointer!
2019 It should use the frame pointer only, if there is a frame pointer.
2020 This is mandatory because of alloca; we also take advantage of it to
2021 omit stack adjustments before returning. */
2024 m88k_begin_epilogue (stream
)
2027 if (TARGET_OCS_DEBUG_INFO
&& !epilogue_marked
&& prologue_marked
)
2029 PUT_OCS_FUNCTION_END (stream
);
2031 epilogue_marked
= 1;
2035 m88k_end_epilogue (stream
, size
)
2039 rtx insn
= get_last_insn ();
2041 if (TARGET_OCS_DEBUG_INFO
&& !epilogue_marked
)
2042 PUT_OCS_FUNCTION_END (stream
);
2044 /* If the last insn isn't a BARRIER, we must write a return insn. This
2045 should only happen if the function has no prologue and no body. */
2046 if (GET_CODE (insn
) == NOTE
)
2047 insn
= prev_nonnote_insn (insn
);
2048 if (insn
== 0 || GET_CODE (insn
) != BARRIER
)
2049 fprintf (stream
, "\tjmp\t %s\n", reg_names
[1]);
2051 /* If the last insn is a barrier, and the insn before that is a call,
2052 then add a nop instruction so that tdesc can walk the stack correctly
2053 even though there is no epilogue. (Otherwise, the label for the
2054 end of the tdesc region ends up at the start of the next function. */
2055 if (insn
&& GET_CODE (insn
) == BARRIER
)
2057 insn
= prev_nonnote_insn (insn
);
2058 if (insn
&& GET_CODE (insn
) == CALL_INSN
)
2059 fprintf (stream
, "\tor\t %s,%s,%s\n",reg_names
[0],reg_names
[0],reg_names
[0]);
2062 output_short_branch_defs (stream
);
2064 fprintf (stream
, "\n");
2066 if (TARGET_OCS_DEBUG_INFO
)
2067 output_tdesc (stream
, m88k_fp_offset
+ 4);
2069 m88k_function_number
++;
2070 m88k_prologue_done
= 0; /* don't put out ln directives */
2071 variable_args_p
= 0; /* has variable args */
2073 epilogue_marked
= 0;
2074 prologue_marked
= 0;
2078 m88k_expand_epilogue ()
2080 #if (MONITOR_GCC & 0x4) /* What are interesting prologue/epilogue values? */
2081 fprintf (stream
, "; size = %d, m88k_fp_offset = %d, m88k_stack_size = %d\n",
2082 size
, m88k_fp_offset
, m88k_stack_size
);
2085 if (frame_pointer_needed
)
2086 emit_add (stack_pointer_rtx
, frame_pointer_rtx
, -m88k_fp_offset
);
2088 if (nregs
|| nxregs
)
2089 preserve_registers (m88k_fp_offset
+ 4, 0);
2091 if (m88k_stack_size
)
2092 emit_add (stack_pointer_rtx
, stack_pointer_rtx
, m88k_stack_size
);
2095 /* Emit insns to set DSTREG to SRCREG + AMOUNT during the prologue or
2099 emit_add (dstreg
, srcreg
, amount
)
2104 rtx incr
= gen_rtx (CONST_INT
, VOIDmode
, abs (amount
));
2105 if (! ADD_INTVAL (amount
))
2107 rtx temp
= gen_rtx (REG
, SImode
, TEMP_REGNUM
);
2108 emit_move_insn (temp
, incr
);
2111 emit_insn ((amount
< 0 ? gen_subsi3
: gen_addsi3
) (dstreg
, srcreg
, incr
));
2114 /* Save/restore the preserve registers. base is the highest offset from
2115 r31 at which a register is stored. store_p is true if stores are to
2116 be done; otherwise loads. */
2119 preserve_registers (base
, store_p
)
2128 } mem_op
[FIRST_PSEUDO_REGISTER
];
2129 struct mem_op
*mo_ptr
= mem_op
;
2131 /* The 88open OCS mandates that preserved registers be stored in
2132 increasing order. For compatibility with current practice,
2133 the order is r1, r30, then the preserve registers. */
2138 /* An extra word is given in this case to make best use of double
2140 if (nregs
> 2 && !save_regs
[FRAME_POINTER_REGNUM
])
2142 emit_ldst (store_p
, 1, SImode
, offset
);
2147 /* Walk the registers to save recording all single memory operations. */
2148 for (regno
= FRAME_POINTER_REGNUM
; regno
> 1; regno
--)
2149 if (save_regs
[regno
])
2151 if ((offset
& 7) != 4 || (regno
& 1) != 1 || !save_regs
[regno
-1])
2154 mo_ptr
->regno
= regno
;
2155 mo_ptr
->offset
= offset
;
2166 /* Walk the registers to save recording all double memory operations.
2167 This avoids a delay in the epilogue (ld.d/ld). */
2169 for (regno
= FRAME_POINTER_REGNUM
; regno
> 1; regno
--)
2170 if (save_regs
[regno
])
2172 if ((offset
& 7) != 4 || (regno
& 1) != 1 || !save_regs
[regno
-1])
2179 mo_ptr
->regno
= regno
-1;
2180 mo_ptr
->offset
= offset
-4;
2187 /* Walk the extended registers to record all memory operations. */
2188 /* Be sure the offset is double word aligned. */
2189 offset
= (offset
- 1) & ~7;
2190 for (regno
= FIRST_PSEUDO_REGISTER
- 1; regno
> FIRST_EXTENDED_REGISTER
;
2192 if (save_regs
[regno
])
2195 mo_ptr
->regno
= regno
;
2196 mo_ptr
->offset
= offset
;
2203 /* Output the memory operations. */
2204 for (mo_ptr
= mem_op
; mo_ptr
->regno
; mo_ptr
++)
2207 emit_ldst (store_p
, mo_ptr
->regno
,
2208 (mo_ptr
->nregs
> 1 ? DImode
: SImode
),
2214 emit_ldst (store_p
, regno
, mode
, offset
)
2217 enum machine_mode mode
;
2220 rtx reg
= gen_rtx (REG
, mode
, regno
);
2223 if (SMALL_INTVAL (offset
))
2225 mem
= gen_rtx (MEM
, mode
, plus_constant (stack_pointer_rtx
, offset
));
2229 /* offset is too large for immediate index must use register */
2231 rtx disp
= gen_rtx (CONST_INT
, VOIDmode
, offset
);
2232 rtx temp
= gen_rtx (REG
, SImode
, TEMP_REGNUM
);
2233 rtx regi
= gen_rtx (PLUS
, SImode
, stack_pointer_rtx
, temp
);
2234 emit_move_insn (temp
, disp
);
2235 mem
= gen_rtx (MEM
, mode
, regi
);
2239 emit_move_insn (mem
, reg
);
2241 emit_move_insn (reg
, mem
);
2244 /* Convert the address expression REG to a CFA offset. */
2247 m88k_debugger_offset (reg
, offset
)
2249 register int offset
;
2251 if (GET_CODE (reg
) == PLUS
)
2253 offset
= INTVAL (XEXP (reg
, 1));
2254 reg
= XEXP (reg
, 0);
2257 /* Put the offset in terms of the CFA (arg pointer). */
2258 if (reg
== frame_pointer_rtx
)
2259 offset
+= m88k_fp_offset
- m88k_stack_size
;
2260 else if (reg
== stack_pointer_rtx
)
2261 offset
-= m88k_stack_size
;
2262 else if (reg
!= arg_pointer_rtx
)
2264 #if (MONITOR_GCC & 0x10) /* Watch for suspicious symbolic locations. */
2265 if (! (GET_CODE (reg
) == REG
2266 && REGNO (reg
) >= FIRST_PSEUDO_REGISTER
))
2267 warning ("Internal gcc error: Can't express symbolic location");
2275 /* Output the 88open OCS proscribed text description information.
2278 0 22: info-byte-length (16 or 20 bytes)
2279 0 2: info-alignment (word 2)
2280 1 32: info-protocol (version 1 or 2(pic))
2281 2 32: starting-address (inclusive, not counting prologue)
2282 3 32: ending-address (exclusive, not counting epilog)
2283 4 8: info-variant (version 1 or 3(extended registers))
2284 4 17: register-save-mask (from register 14 to 30)
2286 4 1: return-address-info-discriminant
2287 4 5: frame-address-register
2288 5 32: frame-address-offset
2289 6 32: return-address-info
2290 7 32: register-save-offset
2291 8 16: extended-register-save-mask (x16 - x31)
2292 8 16: extended-register-save-offset (WORDS from register-save-offset) */
2295 output_tdesc (file
, offset
)
2300 long mask
, return_address_info
, register_save_offset
;
2301 long xmask
, xregister_save_offset
;
2304 for (mask
= 0, i
= 0, regno
= FIRST_OCS_PRESERVE_REGISTER
;
2305 regno
<= LAST_OCS_PRESERVE_REGISTER
;
2309 if (save_regs
[regno
])
2316 for (xmask
= 0, j
= 0, regno
= FIRST_OCS_EXTENDED_PRESERVE_REGISTER
;
2317 regno
<= LAST_OCS_EXTENDED_PRESERVE_REGISTER
;
2321 if (save_regs
[regno
])
2330 if ((nxregs
> 0 || nregs
> 2) && !save_regs
[FRAME_POINTER_REGNUM
])
2332 return_address_info
= - m88k_stack_size
+ offset
;
2333 register_save_offset
= return_address_info
- i
*4;
2337 return_address_info
= 1;
2338 register_save_offset
= - m88k_stack_size
+ offset
+ 4 - i
*4;
2341 xregister_save_offset
= - (j
* 2 + ((register_save_offset
>> 2) & 1));
2345 fprintf (file
, "\t%s\t %d,%d", INT_ASM_OP
, /* 8:0,22:(20 or 16),2:2 */
2346 (((xmask
!= 0) ? 20 : 16) << 2) | 2,
2349 ASM_GENERATE_INTERNAL_LABEL (buf
, OCS_START_PREFIX
, m88k_function_number
);
2350 fprintf (file
, ",%s%s", buf
+1, flag_pic
? "#rel" : "");
2351 ASM_GENERATE_INTERNAL_LABEL (buf
, OCS_END_PREFIX
, m88k_function_number
);
2352 fprintf (file
, ",%s%s", buf
+1, flag_pic
? "#rel" : "");
2354 fprintf (file
, ",0x%x,0x%x,0x%x,0x%x",
2355 /* 8:1,17:0x%.3x,1:0,1:%d,5:%d */
2356 (((xmask
? 3 : 1) << (17+1+1+5))
2358 | ((!!save_regs
[1]) << 5)
2359 | (frame_pointer_needed
2360 ? FRAME_POINTER_REGNUM
2361 : STACK_POINTER_REGNUM
)),
2362 (m88k_stack_size
- (frame_pointer_needed
? m88k_fp_offset
: 0)),
2363 return_address_info
,
2364 register_save_offset
);
2366 fprintf (file
, ",0x%x%04x", xmask
, (0xffff & xregister_save_offset
));
2372 /* Output assembler code to FILE to increment profiler label # LABELNO
2373 for profiling a function entry. NAME is the mcount function name
2374 (varies), SAVEP indicates whether the parameter registers need to
2375 be saved and restored. */
2378 output_function_profiler (file
, labelno
, name
, savep
)
2386 char *temp
= (savep
? reg_names
[2] : reg_names
[10]);
2388 /* Remember to update FUNCTION_PROFILER_LENGTH. */
2392 fprintf (file
, "\tsubu\t %s,%s,64\n", reg_names
[31], reg_names
[31]);
2393 fprintf (file
, "\tst.d\t %s,%s,32\n", reg_names
[2], reg_names
[31]);
2394 fprintf (file
, "\tst.d\t %s,%s,40\n", reg_names
[4], reg_names
[31]);
2395 fprintf (file
, "\tst.d\t %s,%s,48\n", reg_names
[6], reg_names
[31]);
2396 fprintf (file
, "\tst.d\t %s,%s,56\n", reg_names
[8], reg_names
[31]);
2399 ASM_GENERATE_INTERNAL_LABEL (label
, "LP", labelno
);
2402 fprintf (file
, "\tor.u\t %s,%s,%shi16(%s#got_rel)\n",
2403 temp
, reg_names
[0], m88k_pound_sign
, &label
[1]);
2404 fprintf (file
, "\tor\t %s,%s,%slo16(%s#got_rel)\n",
2405 temp
, temp
, m88k_pound_sign
, &label
[1]);
2406 sprintf (dbi
, "\tld\t %s,%s,%s\n", temp
,
2407 reg_names
[PIC_OFFSET_TABLE_REGNUM
], temp
);
2411 sprintf (dbi
, "\tld\t %s,%s,%s#got_rel\n", temp
,
2412 reg_names
[PIC_OFFSET_TABLE_REGNUM
], &label
[1]);
2416 fprintf (file
, "\tor.u\t %s,%s,%shi16(%s)\n",
2417 temp
, reg_names
[0], m88k_pound_sign
, &label
[1]);
2418 sprintf (dbi
, "\tor\t %s,%s,%slo16(%s)\n",
2419 temp
, temp
, m88k_pound_sign
, &label
[1]);
2423 fprintf (file
, "\tbsr.n\t %s#plt\n", name
);
2425 fprintf (file
, "\tbsr.n\t %s\n", name
);
2430 fprintf (file
, "\tld.d\t %s,%s,32\n", reg_names
[2], reg_names
[31]);
2431 fprintf (file
, "\tld.d\t %s,%s,40\n", reg_names
[4], reg_names
[31]);
2432 fprintf (file
, "\tld.d\t %s,%s,48\n", reg_names
[6], reg_names
[31]);
2433 fprintf (file
, "\tld.d\t %s,%s,56\n", reg_names
[8], reg_names
[31]);
2434 fprintf (file
, "\taddu\t %s,%s,64\n", reg_names
[31], reg_names
[31]);
2438 /* Output assembler code to FILE to initialize basic-block profiling for
2439 the current module. LABELNO is unique to each instance. */
2442 output_function_block_profiler (file
, labelno
)
2449 /* Remember to update FUNCTION_BLOCK_PROFILER_LENGTH. */
2451 ASM_GENERATE_INTERNAL_LABEL (block
, "LPBX", 0);
2452 ASM_GENERATE_INTERNAL_LABEL (label
, "LPY", labelno
);
2454 /* @@ Need to deal with PIC. I'm not sure what the requirements are on
2455 register usage, so I used r26/r27 to be safe. */
2456 fprintf (file
, "\tor.u\t %s,%s,%shi16(%s)\n", reg_names
[27], reg_names
[0],
2457 m88k_pound_sign
, &block
[1]);
2458 fprintf (file
, "\tld\t %s,%s,%slo16(%s)\n", reg_names
[26], reg_names
[27],
2459 m88k_pound_sign
, &block
[1]);
2460 fprintf (file
, "\tbcnd\t %sne0,%s,%s\n",
2461 m88k_pound_sign
, reg_names
[26], &label
[1]);
2462 fprintf (file
, "\tsubu\t %s,%s,64\n", reg_names
[31], reg_names
[31]);
2463 fprintf (file
, "\tst.d\t %s,%s,32\n", reg_names
[2], reg_names
[31]);
2464 fprintf (file
, "\tst.d\t %s,%s,40\n", reg_names
[4], reg_names
[31]);
2465 fprintf (file
, "\tst.d\t %s,%s,48\n", reg_names
[6], reg_names
[31]);
2466 fprintf (file
, "\tst.d\t %s,%s,56\n", reg_names
[8], reg_names
[31]);
2467 fputs ("\tbsr.n\t ", file
);
2468 ASM_OUTPUT_LABELREF (file
, "__bb_init_func");
2470 fprintf (file
, "\tor\t %s,%s,%slo16(%s)\n", reg_names
[2], reg_names
[27],
2471 m88k_pound_sign
, &block
[1]);
2472 fprintf (file
, "\tld.d\t %s,%s,32\n", reg_names
[2], reg_names
[31]);
2473 fprintf (file
, "\tld.d\t %s,%s,40\n", reg_names
[4], reg_names
[31]);
2474 fprintf (file
, "\tld.d\t %s,%s,48\n", reg_names
[6], reg_names
[31]);
2475 fprintf (file
, "\tld.d\t %s,%s,56\n", reg_names
[8], reg_names
[31]);
2476 fprintf (file
, "\taddu\t %s,%s,64\n", reg_names
[31], reg_names
[31]);
2477 ASM_OUTPUT_INTERNAL_LABEL (file
, "LPY", labelno
);
2480 /* Output assembler code to FILE to increment the count associated with
2481 the basic block number BLOCKNO. */
2484 output_block_profiler (file
, blockno
)
2490 /* Remember to update BLOCK_PROFILER_LENGTH. */
2492 ASM_GENERATE_INTERNAL_LABEL (block
, "LPBX", 2);
2494 /* @@ Need to deal with PIC. I'm not sure what the requirements are on
2495 register usage, so I used r26/r27 to be safe. */
2496 fprintf (file
, "\tor.u\t %s,%s,%shi16(%s+%d)\n", reg_names
[27], reg_names
[0],
2497 m88k_pound_sign
, &block
[1], 4 * blockno
);
2498 fprintf (file
, "\tld\t %s,%s,%slo16(%s+%d)\n", reg_names
[26], reg_names
[27],
2499 m88k_pound_sign
, &block
[1], 4 * blockno
);
2500 fprintf (file
, "\taddu\t %s,%s,1\n", reg_names
[26], reg_names
[26]);
2501 fprintf (file
, "\tst\t %s,%s,%slo16(%s+%d)\n", reg_names
[26], reg_names
[27],
2502 m88k_pound_sign
, &block
[1], 4 * blockno
);
2505 /* Determine whether a function argument is passed in a register, and
2508 The arguments are CUM, which summarizes all the previous
2509 arguments; MODE, the machine mode of the argument; TYPE,
2510 the data type of the argument as a tree node or 0 if that is not known
2511 (which happens for C support library functions); and NAMED,
2512 which is 1 for an ordinary argument and 0 for nameless arguments that
2513 correspond to `...' in the called function's prototype.
2515 The value of the expression should either be a `reg' RTX for the
2516 hard register in which to pass the argument, or zero to pass the
2517 argument on the stack.
2519 On the m88000 the first eight words of args are normally in registers
2520 and the rest are pushed. Double precision floating point must be
2521 double word aligned (and if in a register, starting on an even
2522 register). Structures and unions which are not 4 byte, and word
2523 aligned are passed in memory rather than registers, even if they
2524 would fit completely in the registers under OCS rules.
2526 Note that FUNCTION_ARG and FUNCTION_INCOMING_ARG were different.
2527 For structures that are passed in memory, but could have been
2528 passed in registers, we first load the structure into the
2529 register, and then when the last argument is passed, we store
2530 the registers into the stack locations. This fixes some bugs
2531 where GCC did not expect to have register arguments, followed
2532 by stack arguments, followed by register arguments. */
2535 m88k_function_arg (args_so_far
, mode
, type
, named
)
2536 CUMULATIVE_ARGS args_so_far
;
2537 enum machine_mode mode
;
2543 if (type
!= 0 /* undo putting struct in register */
2544 && (TREE_CODE (type
) == RECORD_TYPE
|| TREE_CODE (type
) == UNION_TYPE
))
2547 if (mode
== BLKmode
&& TARGET_WARN_PASS_STRUCT
)
2548 warning ("argument #%d is a structure", args_so_far
+ 1);
2550 if ((args_so_far
& 1) != 0
2551 && (mode
== DImode
|| mode
== DFmode
2552 || (type
!= 0 && TYPE_ALIGN (type
) > 32)))
2557 return (rtx
) 0; /* don't put args in registers */
2560 if (type
== 0 && mode
== BLKmode
)
2561 abort (); /* m88k_function_arg argument `type' is NULL for BLKmode. */
2563 bytes
= (mode
!= BLKmode
) ? GET_MODE_SIZE (mode
) : int_size_in_bytes (type
);
2564 words
= (bytes
+ 3) / 4;
2566 if (args_so_far
+ words
> 8)
2567 return (rtx
) 0; /* args have exhausted registers */
2569 else if (mode
== BLKmode
2570 && (TYPE_ALIGN (type
) != BITS_PER_WORD
2571 || bytes
!= UNITS_PER_WORD
))
2574 return gen_rtx (REG
,
2575 ((mode
== BLKmode
) ? TYPE_MODE (type
) : mode
),
2579 /* Do what is necessary for `va_start'. The argument is ignored;
2580 We look at the current function to determine if stdargs or varargs
2581 is used and fill in an initial va_list. A pointer to this constructor
2585 m88k_builtin_saveregs (arglist
)
2588 rtx block
, addr
, argsize
, dest
;
2589 tree fntype
= TREE_TYPE (current_function_decl
);
2590 int argadj
= ((!(TYPE_ARG_TYPES (fntype
) != 0
2591 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype
)))
2592 != void_type_node
)))
2593 ? -UNITS_PER_WORD
: 0) + UNITS_PER_WORD
- 1;
2595 variable_args_p
= 1;
2597 if (CONSTANT_P (current_function_arg_offset_rtx
))
2599 fixed
= (XINT (current_function_arg_offset_rtx
, 0)
2600 + argadj
) / UNITS_PER_WORD
;
2601 argsize
= gen_rtx (CONST_INT
, VOIDmode
, fixed
);
2606 argsize
= plus_constant (current_function_arg_offset_rtx
, argadj
);
2607 argsize
= expand_shift (RSHIFT_EXPR
, Pmode
, argsize
,
2608 build_int_2 (2, 0), argsize
, 0);
2611 /* Allocate the va_list constructor */
2612 block
= assign_stack_local (BLKmode
, 3 * UNITS_PER_WORD
, BITS_PER_WORD
);
2613 MEM_IN_STRUCT_P (block
) = 1;
2614 RTX_UNCHANGING_P (block
) = 1;
2615 RTX_UNCHANGING_P (XEXP (block
, 0)) = 1;
2617 /* Store the argsize as the __va_arg member. */
2618 emit_move_insn (change_address (block
, SImode
, XEXP (block
, 0)),
2621 /* Store the arg pointer in the __va_stk member. */
2622 emit_move_insn (change_address (block
, Pmode
,
2623 plus_constant (XEXP (block
, 0),
2625 copy_to_reg (virtual_incoming_args_rtx
));
2627 /* Allocate the register space, and store it as the __va_reg member. */
2628 addr
= assign_stack_local (BLKmode
, 8 * UNITS_PER_WORD
, -1);
2629 MEM_IN_STRUCT_P (addr
) = 1;
2630 RTX_UNCHANGING_P (addr
) = 1;
2631 RTX_UNCHANGING_P (XEXP (addr
, 0)) = 1;
2632 emit_move_insn (change_address (block
, Pmode
,
2633 plus_constant (XEXP (block
, 0),
2634 2 * UNITS_PER_WORD
)),
2635 copy_to_reg (XEXP (addr
, 0)));
2637 /* Now store the incoming registers. */
2640 dest
= change_address (addr
, Pmode
,
2641 plus_constant (XEXP (addr
, 0),
2642 fixed
* UNITS_PER_WORD
));
2643 move_block_from_reg (2 + fixed
, dest
, 8 - fixed
,
2644 UNITS_PER_WORD
* (8 - fixed
));
2647 if (flag_check_memory_usage
)
2649 emit_library_call (chkr_set_right_libfunc
, 1, VOIDmode
, 3,
2651 GEN_INT (3 * UNITS_PER_WORD
), TYPE_MODE (sizetype
),
2652 GEN_INT (MEMORY_USE_RW
), QImode
);
2654 emit_library_call (chkr_set_right_libfunc
, 1, VOIDmode
, 3,
2656 GEN_INT (UNITS_PER_WORD
* (8 - fixed
)),
2657 TYPE_MODE (sizetype
),
2658 GEN_INT (MEMORY_USE_RW
), QImode
);
2661 /* Return the address of the va_list constructor, but don't put it in a
2662 register. This fails when not optimizing and produces worse code when
2664 return XEXP (block
, 0);
2667 /* If cmpsi has not been generated, emit code to do the test. Return the
2668 expression describing the test of operator OP. */
2671 emit_test (op
, mode
)
2673 enum machine_mode mode
;
2675 if (m88k_compare_reg
== 0)
2676 emit_insn (gen_test (m88k_compare_op0
, m88k_compare_op1
));
2677 return (gen_rtx (op
, mode
, m88k_compare_reg
, const0_rtx
));
2680 /* Determine how to best perform cmpsi/bxx, where cmpsi has a constant
2681 operand. All tests with zero (albeit swapped) and all equality tests
2682 with a constant are done with bcnd. The remaining cases are swapped
2686 emit_bcnd (op
, label
)
2690 if (m88k_compare_op1
== const0_rtx
)
2691 emit_jump_insn( gen_bcnd (
2692 gen_rtx (op
, VOIDmode
,m88k_compare_op0
, const0_rtx
),
2694 else if (m88k_compare_op0
== const0_rtx
)
2695 emit_jump_insn( gen_bcnd(
2697 swap_condition (op
),
2698 VOIDmode
, m88k_compare_op1
, const0_rtx
),
2700 else if (op
!= EQ
&& op
!= NE
)
2701 emit_jump_insn (gen_bxx (emit_test (op
, VOIDmode
), label
));
2704 rtx zero
= gen_reg_rtx (SImode
);
2708 if (GET_CODE (m88k_compare_op1
) == CONST_INT
)
2710 reg
= force_reg (SImode
, m88k_compare_op0
);
2711 constant
= m88k_compare_op1
;
2715 reg
= force_reg (SImode
, m88k_compare_op1
);
2716 constant
= m88k_compare_op0
;
2718 value
= INTVAL (constant
);
2720 /* Perform an arithmetic computation to make the compared-to value
2721 zero, but avoid loosing if the bcnd is later changed into sxx. */
2722 if (SMALL_INTVAL (value
))
2723 emit_jump_insn (gen_bxx (emit_test (op
, VOIDmode
), label
));
2726 if (SMALL_INTVAL (-value
))
2727 emit_insn (gen_addsi3 (zero
, reg
,
2728 gen_rtx (CONST_INT
, VOIDmode
, -value
)));
2730 emit_insn (gen_xorsi3 (zero
, reg
, constant
));
2732 emit_jump_insn (gen_bcnd (gen_rtx (op
, VOIDmode
,
2739 /* Print an operand. Recognize special options, documented below. */
2742 print_operand (file
, x
, code
)
2747 enum rtx_code xc
= (x
? GET_CODE (x
) : UNKNOWN
);
2748 register int value
= (xc
== CONST_INT
? INTVAL (x
) : 0);
2749 static int sequencep
;
2750 static int reversep
;
2754 if (code
< 'B' || code
> 'E')
2755 output_operand_lossage ("%R not followed by %B/C/D/E");
2757 xc
= reverse_condition (xc
);
2763 case '*': /* addressing base register for PIC */
2764 fputs (reg_names
[PIC_OFFSET_TABLE_REGNUM
], file
); return;
2766 case '#': /* SVR4 pound-sign syntax character (empty if SVR3) */
2767 fputs (m88k_pound_sign
, file
); return;
2769 case 'V': /* Output a serializing instruction as needed if the operand
2770 (assumed to be a MEM) is a volatile load. */
2771 case 'v': /* ditto for a volatile store. */
2772 if (MEM_VOLATILE_P (x
) && TARGET_SERIALIZE_VOLATILE
)
2774 /* The m88110 implements two FIFO queues, one for loads and
2775 one for stores. These queues mean that loads complete in
2776 their issue order as do stores. An interaction between the
2777 history buffer and the store reservation station ensures
2778 that a store will not bypass load. Finally, a load will not
2779 bypass store, but only when they reference the same address.
2781 To avoid this reordering (a load bypassing a store) for
2782 volatile references, a serializing instruction is output.
2783 We choose the fldcr instruction as it does not serialize on
2784 the m88100 so that -m88000 code will not be degraded.
2786 The mechanism below is completed by having CC_STATUS_INIT set
2787 the code to the unknown value. */
2791 A problem with 88110 4.1 & 4.2 makes the use of fldcr for
2792 this purpose undesirable. Instead we will use tb1, this will
2793 cause serialization on the 88100 but such is life.
2796 static rtx last_addr
= 0;
2797 if (code
== 'V' /* Only need to serialize before a load. */
2798 && m88k_volatile_code
!= 'V' /* Loads complete in FIFO order. */
2799 && !(m88k_volatile_code
== 'v'
2800 && GET_CODE (XEXP (x
, 0)) == LO_SUM
2801 && rtx_equal_p (XEXP (XEXP (x
, 0), 1), last_addr
)))
2805 "fldcr\t %s,%scr63\n\t",
2807 "fldcr\t %s,%sfcr63\n\t",
2809 reg_names
[0], m88k_pound_sign
);
2811 "tb1\t 1,%s,0xff\n\t", reg_names
[0]);
2813 m88k_volatile_code
= code
;
2814 last_addr
= (GET_CODE (XEXP (x
, 0)) == LO_SUM
2815 ? XEXP (XEXP (x
, 0), 1) : 0);
2819 case 'X': /* print the upper 16 bits... */
2821 case 'x': /* print the lower 16 bits of the integer constant in hex */
2822 if (xc
!= CONST_INT
)
2823 output_operand_lossage ("invalid %x/X value");
2824 fprintf (file
, "0x%x", value
& 0xffff); return;
2826 case 'H': /* print the low 16 bits of the negated integer constant */
2827 if (xc
!= CONST_INT
)
2828 output_operand_lossage ("invalid %H value");
2830 case 'h': /* print the register or low 16 bits of the integer constant */
2833 if (xc
!= CONST_INT
)
2834 output_operand_lossage ("invalid %h value");
2835 fprintf (file
, "%d", value
& 0xffff);
2838 case 'Q': /* print the low 8 bits of the negated integer constant */
2839 if (xc
!= CONST_INT
)
2840 output_operand_lossage ("invalid %Q value");
2842 case 'q': /* print the register or low 8 bits of the integer constant */
2845 if (xc
!= CONST_INT
)
2846 output_operand_lossage ("invalid %q value");
2847 fprintf (file
, "%d", value
& 0xff);
2850 case 'w': /* print the integer constant (X == 32 ? 0 : 32 - X) */
2851 if (xc
!= CONST_INT
)
2852 output_operand_lossage ("invalid %o value");
2853 fprintf (file
, "%d", value
== 32 ? 0 : 32 - value
);
2856 case 'p': /* print the logarithm of the integer constant */
2858 || (value
= exact_log2 (value
)) < 0)
2859 output_operand_lossage ("invalid %p value");
2860 fprintf (file
, "%d", value
);
2863 case 'S': /* compliment the value and then... */
2865 case 's': /* print the width and offset values forming the integer
2866 constant with a SET instruction. See integer_ok_for_set. */
2868 register unsigned mask
, uval
= value
;
2869 register int top
, bottom
;
2871 if (xc
!= CONST_INT
)
2872 output_operand_lossage ("invalid %s/S value");
2873 /* All the "one" bits must be contiguous. If so, MASK will be
2874 a power of two or zero. */
2875 mask
= (uval
| (uval
- 1)) + 1;
2876 if (!(uval
&& POWER_OF_2_or_0 (mask
)))
2877 output_operand_lossage ("invalid %s/S value");
2878 top
= mask
? exact_log2 (mask
) : 32;
2879 bottom
= exact_log2 (uval
& ~(uval
- 1));
2880 fprintf (file
,"%d<%d>", top
- bottom
, bottom
);
2884 case 'P': /* print nothing if pc_rtx; output label_ref */
2885 if (xc
== LABEL_REF
)
2886 output_addr_const (file
, x
);
2888 output_operand_lossage ("invalid %P operand");
2891 case 'L': /* print 0 or 1 if operand is label_ref and then... */
2892 fputc (xc
== LABEL_REF
? '1' : '0', file
);
2893 case '.': /* print .n if delay slot is used */
2894 fputs ((final_sequence
2895 && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence
, 0, 0)))
2896 ? ".n\t" : "\t", file
);
2899 case '!': /* Reverse the following condition. */
2903 case 'R': /* reverse the condition of the next print_operand
2904 if operand is a label_ref. */
2906 reversep
= (xc
== LABEL_REF
);
2909 case 'B': /* bcnd branch values */
2910 fputs (m88k_pound_sign
, file
);
2913 case EQ
: fputs ("eq0", file
); return;
2914 case NE
: fputs ("ne0", file
); return;
2915 case GT
: fputs ("gt0", file
); return;
2916 case LE
: fputs ("le0", file
); return;
2917 case LT
: fputs ("lt0", file
); return;
2918 case GE
: fputs ("ge0", file
); return;
2919 default: output_operand_lossage ("invalid %B value");
2922 case 'C': /* bb0/bb1 branch values for comparisons */
2923 fputs (m88k_pound_sign
, file
);
2926 case EQ
: fputs ("eq", file
); return;
2927 case NE
: fputs ("ne", file
); return;
2928 case GT
: fputs ("gt", file
); return;
2929 case LE
: fputs ("le", file
); return;
2930 case LT
: fputs ("lt", file
); return;
2931 case GE
: fputs ("ge", file
); return;
2932 case GTU
: fputs ("hi", file
); return;
2933 case LEU
: fputs ("ls", file
); return;
2934 case LTU
: fputs ("lo", file
); return;
2935 case GEU
: fputs ("hs", file
); return;
2936 default: output_operand_lossage ("invalid %C value");
2939 case 'D': /* bcnd branch values for float comparisons */
2942 case EQ
: fputs ("0xa", file
); return;
2943 case NE
: fputs ("0x5", file
); return;
2944 case GT
: fputs (m88k_pound_sign
, file
);
2945 fputs ("gt0", file
); return;
2946 case LE
: fputs ("0xe", file
); return;
2947 case LT
: fputs ("0x4", file
); return;
2948 case GE
: fputs ("0xb", file
); return;
2949 default: output_operand_lossage ("invalid %D value");
2952 case 'E': /* bcnd branch values for special integers */
2955 case EQ
: fputs ("0x8", file
); return;
2956 case NE
: fputs ("0x7", file
); return;
2957 default: output_operand_lossage ("invalid %E value");
2960 case 'd': /* second register of a two register pair */
2962 output_operand_lossage ("`%d' operand isn't a register");
2963 fputs (reg_names
[REGNO (x
) + 1], file
);
2966 case 'r': /* an immediate 0 should be represented as `r0' */
2967 if (x
== const0_rtx
)
2969 fputs (reg_names
[0], file
);
2973 output_operand_lossage ("invalid %r value");
2979 if (REGNO (x
) == ARG_POINTER_REGNUM
)
2980 output_operand_lossage ("operand is r0");
2982 fputs (reg_names
[REGNO (x
)], file
);
2984 else if (xc
== PLUS
)
2987 output_address (XEXP (x
, 0));
2988 else if (flag_pic
&& xc
== UNSPEC
)
2990 output_addr_const (file
, XVECEXP (x
, 0, 0));
2991 fputs ("#got_rel", file
);
2993 else if (xc
== CONST_DOUBLE
)
2994 output_operand_lossage ("operand is const_double");
2996 output_addr_const (file
, x
);
2999 case 'g': /* append #got_rel as needed */
3000 if (flag_pic
&& (xc
== SYMBOL_REF
|| xc
== LABEL_REF
))
3002 output_addr_const (file
, x
);
3003 fputs ("#got_rel", file
);
3008 case 'a': /* (standard), assume operand is an address */
3009 case 'c': /* (standard), assume operand is an immediate value */
3010 case 'l': /* (standard), assume operand is a label_ref */
3011 case 'n': /* (standard), like %c, except negate first */
3013 output_operand_lossage ("invalid code");
3018 print_operand_address (file
, addr
)
3022 register rtx reg0
, reg1
, temp
;
3024 switch (GET_CODE (addr
))
3027 if (REGNO (addr
) == ARG_POINTER_REGNUM
)
3030 fprintf (file
, "%s,%s", reg_names
[0], reg_names
[REGNO (addr
)]);
3034 fprintf (file
, "%s,%slo16(",
3035 reg_names
[REGNO (XEXP (addr
, 0))], m88k_pound_sign
);
3036 output_addr_const (file
, XEXP (addr
, 1));
3041 reg0
= XEXP (addr
, 0);
3042 reg1
= XEXP (addr
, 1);
3043 if (GET_CODE (reg0
) == MULT
|| GET_CODE (reg0
) == CONST_INT
)
3050 if ((REG_P (reg0
) && REGNO (reg0
) == ARG_POINTER_REGNUM
)
3051 || (REG_P (reg1
) && REGNO (reg1
) == ARG_POINTER_REGNUM
))
3054 else if (REG_P (reg0
))
3057 fprintf (file
, "%s,%s",
3058 reg_names
[REGNO (reg0
)], reg_names
[REGNO (reg1
)]);
3060 else if (GET_CODE (reg1
) == CONST_INT
)
3061 fprintf (file
, "%s,%d",
3062 reg_names
[REGNO (reg0
)], INTVAL (reg1
));
3064 else if (GET_CODE (reg1
) == MULT
)
3066 rtx mreg
= XEXP (reg1
, 0);
3067 if (REGNO (mreg
) == ARG_POINTER_REGNUM
)
3070 fprintf (file
, "%s[%s]", reg_names
[REGNO (reg0
)],
3071 reg_names
[REGNO (mreg
)]);
3074 else if (GET_CODE (reg1
) == ZERO_EXTRACT
)
3076 fprintf (file
, "%s,%slo16(",
3077 reg_names
[REGNO (reg0
)], m88k_pound_sign
);
3078 output_addr_const (file
, XEXP (reg1
, 0));
3084 fprintf (file
, "%s,", reg_names
[REGNO (reg0
)]);
3085 output_addr_const (file
, reg1
);
3086 fputs ("#got_rel", file
);
3096 if (REGNO (XEXP (addr
, 0)) == ARG_POINTER_REGNUM
)
3099 fprintf (file
, "%s[%s]",
3100 reg_names
[0], reg_names
[REGNO (XEXP (addr
, 0))]);
3104 fprintf (file
, "%s,%d", reg_names
[0], INTVAL (addr
));
3108 fprintf (file
, "%s,", reg_names
[0]);
3109 if (SHORT_ADDRESS_P (addr
, temp
))
3111 fprintf (file
, "%siw16(", m88k_pound_sign
);
3112 output_addr_const (file
, addr
);
3116 output_addr_const (file
, addr
);
3120 /* Return true if X is an address which needs a temporary register when
3121 reloaded while generating PIC code. */
3124 pic_address_needs_scratch (x
)
3127 /* An address which is a symbolic plus a non SMALL_INT needs a temp reg. */
3128 if (GET_CODE (x
) == CONST
&& GET_CODE (XEXP (x
, 0)) == PLUS
3129 && GET_CODE (XEXP (XEXP (x
, 0), 0)) == SYMBOL_REF
3130 && GET_CODE (XEXP (XEXP (x
, 0), 1)) == CONST_INT
3131 && ! ADD_INT (XEXP (XEXP (x
, 0), 1)))
3137 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
3138 reference and a constant. */
3141 symbolic_operand (op
, mode
)
3143 enum machine_mode mode
;
3145 switch (GET_CODE (op
))
3153 return ((GET_CODE (XEXP (op
, 0)) == SYMBOL_REF
3154 || GET_CODE (XEXP (op
, 0)) == LABEL_REF
)
3155 && GET_CODE (XEXP (op
, 1)) == CONST_INT
);
3157 /* ??? This clause seems to be irrelevant. */
3159 return GET_MODE (op
) == mode
;