1 /* Subroutines used for code generation on ROMP.
2 Copyright (C) 1990, 1991 Free Software Foundation, Inc.
3 Contributed by Richard Kenner (kenner@nyu.edu)
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
26 #include "hard-reg-set.h"
28 #include "insn-config.h"
29 #include "conditions.h"
30 #include "insn-flags.h"
32 #include "insn-attr.h"
39 #define min(A,B) ((A) < (B) ? (A) : (B))
40 #define max(A,B) ((A) > (B) ? (A) : (B))
42 static int unsigned_comparisons_p ();
43 static void output_loadsave_fpregs ();
44 static void output_fpops ();
45 static void init_fpops ();
47 /* Return 1 if the insn using CC0 set by INSN does not contain
48 any unsigned tests applied to the condition codes.
50 Based on `next_insn_tests_no_inequality' in recog.c. */
53 next_insn_tests_no_unsigned (insn
)
56 register rtx next
= next_cc0_user (insn
);
60 if (find_reg_note (insn
, REG_UNUSED
, cc0_rtx
))
66 return ((GET_CODE (next
) == JUMP_INSN
67 || GET_CODE (next
) == INSN
68 || GET_CODE (next
) == CALL_INSN
)
69 && ! unsigned_comparisons_p (PATTERN (next
)));
73 unsigned_comparisons_p (x
)
78 register enum rtx_code code
= GET_CODE (x
);
96 return (XEXP (x
, 0) == cc0_rtx
|| XEXP (x
, 1) == cc0_rtx
);
99 len
= GET_RTX_LENGTH (code
);
100 fmt
= GET_RTX_FORMAT (code
);
102 for (i
= 0; i
< len
; i
++)
106 if (unsigned_comparisons_p (XEXP (x
, i
)))
109 else if (fmt
[i
] == 'E')
112 for (j
= XVECLEN (x
, i
) - 1; j
>= 0; j
--)
113 if (unsigned_comparisons_p (XVECEXP (x
, i
, j
)))
121 /* Update the condition code from the insn. Look mostly at the first
122 byte of the machine-specific insn description information.
124 cc_state.value[12] refer to two possible values that might correspond
125 to the CC. We only store register values. */
127 update_cc (body
, insn
)
131 switch (get_attr_cc (insn
))
134 /* Insn does not affect the CC at all. */
138 /* Insn doesn't affect the CC but does modify operand[0], known to be
140 if (cc_status
.value1
!= 0
141 && reg_overlap_mentioned_p (recog_operand
[0], cc_status
.value1
))
142 cc_status
.value1
= 0;
144 if (cc_status
.value2
!= 0
145 && reg_overlap_mentioned_p (recog_operand
[0], cc_status
.value2
))
146 cc_status
.value2
= 0;
151 /* Insn copies operand[1] to operand[0], both registers, but doesn't
153 if (cc_status
.value1
!= 0
154 && reg_overlap_mentioned_p (recog_operand
[0], cc_status
.value1
))
155 cc_status
.value1
= 0;
157 if (cc_status
.value2
!= 0
158 && reg_overlap_mentioned_p (recog_operand
[0], cc_status
.value2
))
159 cc_status
.value2
= 0;
161 if (cc_status
.value1
!= 0
162 && rtx_equal_p (cc_status
.value1
, recog_operand
[1]))
163 cc_status
.value2
= recog_operand
[0];
165 if (cc_status
.value2
!= 0
166 && rtx_equal_p (cc_status
.value2
, recog_operand
[1]))
167 cc_status
.value1
= recog_operand
[0];
172 /* Insn clobbers CC. */
177 /* Insn sets CC to recog_operand[0], but overflow is impossible. */
179 cc_status
.flags
|= CC_NO_OVERFLOW
;
180 cc_status
.value1
= recog_operand
[0];
184 /* Insn is a compare which sets the CC fully. Update CC_STATUS for this
185 compare and mark whether the test will be signed or unsigned. */
187 register rtx p
= PATTERN (insn
);
191 if (GET_CODE (p
) == PARALLEL
)
192 p
= XVECEXP (p
, 0, 0);
193 cc_status
.value1
= SET_SRC (p
);
195 if (GET_CODE (SET_SRC (p
)) == REG
)
196 cc_status
.flags
|= CC_NO_OVERFLOW
;
197 if (! next_insn_tests_no_unsigned (insn
))
198 cc_status
.flags
|= CC_UNSIGNED
;
203 /* Insn sets T bit if result is non-zero. Next insn must be branch. */
205 cc_status
.flags
= CC_IN_TB
| CC_NOT_NEGATIVE
;
213 /* Return 1 if a previous compare needs to be re-issued. This will happen
214 if two compares tested the same objects, but one was signed and the
215 other unsigned. OP is the comparison operation being performed. */
218 restore_compare_p (op
)
221 enum rtx_code code
= GET_CODE (op
);
223 return (((code
== GEU
|| code
== LEU
|| code
== GTU
|| code
== LTU
)
224 && ! (cc_status
.flags
& CC_UNSIGNED
))
225 || ((code
== GE
|| code
== LE
|| code
== GT
|| code
== LT
)
226 && (cc_status
.flags
& CC_UNSIGNED
)));
229 /* Generate the (long) string corresponding to an inline multiply insn.
230 Note that `r10' does not refer to the register r10, but rather to the
231 SCR used as the MQ. */
233 output_in_line_mul ()
235 static char insns
[200];
238 strcpy (insns
, "s %0,%0\n");
239 strcat (insns
, "\tmts r10,%1\n");
240 for (i
= 0; i
< 16; i
++)
241 strcat (insns
, "\tm %0,%2\n");
242 strcat (insns
, "\tmfs r10,%0");
247 /* Returns 1 if OP is a memory reference with an offset from a register within
248 the range specified. The offset must also be a multiple of the size of the
252 memory_offset_in_range_p (op
, mode
, low
, high
)
254 enum machine_mode mode
;
259 if (! memory_operand (op
, mode
))
262 while (GET_CODE (op
) == SUBREG
)
264 offset
+= SUBREG_WORD (op
) * UNITS_PER_WORD
;
266 offset
-= (min (UNITS_PER_WORD
, GET_MODE_SIZE (GET_MODE (op
)))
267 - min (UNITS_PER_WORD
,
268 GET_MODE_SIZE (GET_MODE (SUBREG_REG (op
)))));
270 op
= SUBREG_REG (op
);
273 /* We must now have either (mem (reg (x)), (mem (plus (reg (x)) (c))),
274 or a constant pool address. */
275 if (GET_CODE (op
) != MEM
)
278 /* Now use the actual mode and get the address. */
279 mode
= GET_MODE (op
);
281 if (GET_CODE (op
) == SYMBOL_REF
&& CONSTANT_POOL_ADDRESS_P (op
))
282 offset
= get_pool_offset (op
) + 12;
283 else if (GET_CODE (op
) == PLUS
)
285 if (GET_CODE (XEXP (op
, 1)) != CONST_INT
286 || ! register_operand (XEXP (op
, 0), Pmode
))
289 offset
+= INTVAL (XEXP (op
, 1));
292 else if (! register_operand (op
, Pmode
))
295 return (offset
>= low
&& offset
<= high
296 && (offset
% GET_MODE_SIZE (mode
) == 0));
299 /* Return 1 if OP is a valid operand for a memory reference insn that can
300 only reference indirect through a register. */
303 zero_memory_operand (op
, mode
)
305 enum machine_mode mode
;
307 return memory_offset_in_range_p (op
, mode
, 0, 0);
310 /* Return 1 if OP is a valid operand for a `short' memory reference insn. */
313 short_memory_operand (op
, mode
)
315 enum machine_mode mode
;
317 if (mode
== VOIDmode
)
318 mode
= GET_MODE (op
);
320 return memory_offset_in_range_p (op
, mode
, 0,
321 15 * min (UNITS_PER_WORD
,
322 GET_MODE_SIZE (mode
)));
325 /* Returns 1 if OP is a memory reference involving a symbolic constant
326 that is not in the constant pool. */
329 symbolic_memory_operand (op
, mode
)
331 enum machine_mode mode
;
333 if (! memory_operand (op
, mode
))
336 while (GET_CODE (op
) == SUBREG
)
337 op
= SUBREG_REG (op
);
339 if (GET_CODE (op
) != MEM
)
343 if (constant_pool_address_operand (op
, VOIDmode
))
346 return romp_symbolic_operand (op
, Pmode
)
347 || (GET_CODE (op
) == PLUS
&& register_operand (XEXP (op
, 0), Pmode
)
348 && romp_symbolic_operand (XEXP (op
, 1), Pmode
));
352 /* Returns 1 if OP is a constant pool reference to the current function. */
355 current_function_operand (op
, mode
)
357 enum machine_mode mode
;
359 if (GET_CODE (op
) != MEM
|| GET_CODE (XEXP (op
, 0)) != SYMBOL_REF
360 || ! CONSTANT_POOL_ADDRESS_P (XEXP (op
, 0)))
363 op
= get_pool_constant (XEXP (op
, 0));
364 return (GET_CODE (op
) == SYMBOL_REF
365 && ! strcmp (current_function_name
, XSTR (op
, 0)));
368 /* Return non-zero if this function is known to have a null epilogue. */
373 return (reload_completed
374 && first_reg_to_save () == 16
375 && ! romp_pushes_stack ());
378 /* Returns 1 if OP is the address of a location in the constant pool. */
381 constant_pool_address_operand (op
, mode
)
383 enum machine_mode mode
;
385 return ((GET_CODE (op
) == SYMBOL_REF
&& CONSTANT_POOL_ADDRESS_P (op
))
386 || (GET_CODE (op
) == CONST
&& GET_CODE (XEXP (op
, 0)) == PLUS
387 && GET_CODE (XEXP (XEXP (op
, 0), 1)) == CONST_INT
388 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == SYMBOL_REF
389 && CONSTANT_POOL_ADDRESS_P (XEXP (XEXP (op
, 0), 0))));
392 /* Returns 1 if OP is either a symbol reference or a sum of a symbol
393 reference and a constant. */
396 romp_symbolic_operand (op
, mode
)
398 enum machine_mode mode
;
400 switch (GET_CODE (op
))
404 return ! op
->integrated
;
408 return (GET_CODE (XEXP (op
, 0)) == SYMBOL_REF
409 || GET_CODE (XEXP (op
, 0)) == LABEL_REF
)
410 && GET_CODE (XEXP (op
, 1)) == CONST_INT
;
417 /* Returns 1 if OP is a valid constant for the ROMP. */
420 constant_operand (op
, mode
)
422 enum machine_mode mode
;
424 switch (GET_CODE (op
))
430 return romp_symbolic_operand (op
,mode
);
433 return (unsigned int) (INTVAL (op
) + 0x8000) < 0x10000
434 || (INTVAL (op
) & 0xffff) == 0 || (INTVAL (op
) & 0xffff0000) == 0;
441 /* Returns 1 if OP is either a constant integer valid for the ROMP or a
442 register. If a register, it must be in the proper mode unless MODE is
446 reg_or_cint_operand (op
, mode
)
448 enum machine_mode mode
;
450 if (GET_CODE (op
) == CONST_INT
)
451 return constant_operand (op
, mode
);
453 return register_operand (op
, mode
);
456 /* Return 1 is the operand is either a register or ANY constant integer. */
459 reg_or_any_cint_operand (op
, mode
)
461 enum machine_mode mode
;
463 return GET_CODE (op
) == CONST_INT
|| register_operand (op
, mode
);
466 /* Return 1 if the operand is either a register or a valid D-type operand. */
469 reg_or_D_operand (op
, mode
)
471 enum machine_mode mode
;
473 if (GET_CODE (op
) == CONST_INT
)
474 return (unsigned) (INTVAL (op
) + 0x8000) < 0x10000;
476 return register_operand (op
, mode
);
479 /* Return 1 if the operand is either a register or an item that can be
480 used as the operand of an SI add insn. */
483 reg_or_add_operand (op
, mode
)
485 enum machine_mode mode
;
487 return reg_or_D_operand (op
, mode
) || romp_symbolic_operand (op
, mode
)
488 || (GET_CODE (op
) == CONST_INT
&& (INTVAL (op
) & 0xffff) == 0);
491 /* Return 1 if the operand is either a register or an item that can be
492 used as the operand of a ROMP logical AND insn. */
495 reg_or_and_operand (op
, mode
)
497 enum machine_mode mode
;
499 if (reg_or_cint_operand (op
, mode
))
502 if (GET_CODE (op
) != CONST_INT
)
505 return (INTVAL (op
) & 0xffff) == 0xffff
506 || (INTVAL (op
) & 0xffff0000) == 0xffff0000;
509 /* Return 1 if the operand is a register or memory operand. */
512 reg_or_mem_operand (op
, mode
)
514 register enum machine_mode mode
;
516 return register_operand (op
, mode
) || memory_operand (op
, mode
);
519 /* Return 1 if the operand is either a register or a memory operand that is
523 reg_or_nonsymb_mem_operand (op
, mode
)
525 enum machine_mode mode
;
527 if (register_operand (op
, mode
))
530 if (memory_operand (op
, mode
) && ! symbolic_memory_operand (op
, mode
))
536 /* Return 1 if this operand is valid for the ROMP. This is any operand except
537 certain constant integers. */
540 romp_operand (op
, mode
)
542 enum machine_mode mode
;
544 if (GET_CODE (op
) == CONST_INT
)
545 return constant_operand (op
, mode
);
547 return general_operand (op
, mode
);
550 /* Return 1 if the operand is (reg:mode 0). */
553 reg_0_operand (op
, mode
)
555 enum machine_mode mode
;
557 return ((mode
== VOIDmode
|| mode
== GET_MODE (op
))
558 && GET_CODE (op
) == REG
&& REGNO (op
) == 0);
561 /* Return 1 if the operand is (reg:mode 15). */
564 reg_15_operand (op
, mode
)
566 enum machine_mode mode
;
568 return ((mode
== VOIDmode
|| mode
== GET_MODE (op
))
569 && GET_CODE (op
) == REG
&& REGNO (op
) == 15);
572 /* Return 1 if this is a binary floating-point operation. */
575 float_binary (op
, mode
)
577 enum machine_mode mode
;
579 if (mode
!= VOIDmode
&& mode
!= GET_MODE (op
))
582 if (GET_MODE (op
) != SFmode
&& GET_MODE (op
) != DFmode
)
585 switch (GET_CODE (op
))
591 return GET_MODE (XEXP (op
, 0)) == GET_MODE (op
)
592 && GET_MODE (XEXP (op
, 1)) == GET_MODE (op
);
599 /* Return 1 if this is a unary floating-point operation. */
602 float_unary (op
, mode
)
604 enum machine_mode mode
;
606 if (mode
!= VOIDmode
&& mode
!= GET_MODE (op
))
609 if (GET_MODE (op
) != SFmode
&& GET_MODE (op
) != DFmode
)
612 return (GET_CODE (op
) == NEG
|| GET_CODE (op
) == ABS
)
613 && GET_MODE (XEXP (op
, 0)) == GET_MODE (op
);
616 /* Return 1 if this is a valid floating-point conversion that can be done
617 as part of an operation by the RT floating-point routines. */
620 float_conversion (op
, mode
)
622 enum machine_mode mode
;
624 if (mode
!= VOIDmode
&& mode
!= GET_MODE (op
))
627 switch (GET_CODE (op
))
630 return GET_MODE (op
) == SFmode
&& GET_MODE (XEXP (op
, 0)) == DFmode
;
633 return GET_MODE (op
) == DFmode
&& GET_MODE (XEXP (op
, 0)) == SFmode
;
636 return ((GET_MODE (XEXP (op
, 0)) == SImode
637 || GET_CODE (XEXP (op
, 0)) == CONST_INT
)
638 && (GET_MODE (op
) == SFmode
|| GET_MODE (op
) == DFmode
));
641 return ((GET_MODE (op
) == SImode
642 || GET_CODE (XEXP (op
, 0)) == CONST_INT
)
643 && (GET_MODE (XEXP (op
, 0)) == SFmode
644 || GET_MODE (XEXP (op
, 0)) == DFmode
));
651 /* Print an operand. Recognize special options, documented below. */
654 print_operand (file
, x
, code
)
664 /* Byte number (const/8) */
665 if (GET_CODE (x
) != CONST_INT
)
666 output_operand_lossage ("invalid %%B value");
668 fprintf (file
, "%d", INTVAL (x
) / 8);
672 /* Low order 16 bits of constant. */
673 if (GET_CODE (x
) != CONST_INT
)
674 output_operand_lossage ("invalid %%L value");
676 fprintf (file
, "%d", INTVAL (x
) & 0xffff);
680 /* Null or "16" depending on whether the constant is greater than 16. */
681 if (GET_CODE (x
) != CONST_INT
)
682 output_operand_lossage ("invalid %%s value");
684 if (INTVAL (x
) >= 16)
685 fprintf (file
, "16");
690 /* For shifts: 's' will have given the half. Just give the amount
692 if (GET_CODE (x
) != CONST_INT
)
693 output_operand_lossage ("invalid %%S value");
695 fprintf (file
, "%d", INTVAL (x
) & 15);
699 /* The number of a single bit set or cleared, mod 16. Note that the ROMP
700 numbers bits with the high-order bit 31. */
701 if (GET_CODE (x
) != CONST_INT
)
702 output_operand_lossage ("invalid %%b value");
704 if ((i
= exact_log2 (INTVAL (x
))) >= 0)
705 fprintf (file
, "%d", (31 - i
) % 16);
706 else if ((i
= exact_log2 (~ INTVAL (x
))) >= 0)
707 fprintf (file
, "%d", (31 - i
) % 16);
709 output_operand_lossage ("invalid %%b value");
714 /* "l" or "u" depending on which half of the constant is zero. */
715 if (GET_CODE (x
) != CONST_INT
)
716 output_operand_lossage ("invalid %%h value");
718 if ((INTVAL (x
) & 0xffff0000) == 0)
720 else if ((INTVAL (x
) & 0xffff) == 0)
723 output_operand_lossage ("invalid %%h value");
728 /* Upper or lower half, depending on which half is zero. */
729 if (GET_CODE (x
) != CONST_INT
)
730 output_operand_lossage ("invalid %%H value");
732 if ((INTVAL (x
) & 0xffff0000) == 0)
733 fprintf (file
, "%d", INTVAL (x
) & 0xffff);
734 else if ((INTVAL (x
) & 0xffff) == 0)
735 fprintf (file
, "%d", (INTVAL (x
) >> 16) & 0xffff);
737 output_operand_lossage ("invalid %%H value");
742 /* Write two characters:
743 'lo' if the high order part is all ones
744 'lz' if the high order part is all zeros
745 'uo' if the low order part is all ones
746 'uz' if the low order part is all zeros
748 if (GET_CODE (x
) != CONST_INT
)
749 output_operand_lossage ("invalid %%z value");
751 if ((INTVAL (x
) & 0xffff0000) == 0)
752 fprintf (file
, "lz");
753 else if ((INTVAL (x
) & 0xffff0000) == 0xffff0000)
754 fprintf (file
, "lo");
755 else if ((INTVAL (x
) & 0xffff) == 0)
756 fprintf (file
, "uz");
757 else if ((INTVAL (x
) & 0xffff) == 0xffff)
758 fprintf (file
, "uo");
760 output_operand_lossage ("invalid %%z value");
765 /* Upper or lower half, depending on which is non-zero or not
766 all ones. Must be consistent with 'z' above. */
767 if (GET_CODE (x
) != CONST_INT
)
768 output_operand_lossage ("invalid %%Z value");
770 if ((INTVAL (x
) & 0xffff0000) == 0
771 || (INTVAL (x
) & 0xffff0000) == 0xffff0000)
772 fprintf (file
, "%d", INTVAL (x
) & 0xffff);
773 else if ((INTVAL (x
) & 0xffff) == 0 || (INTVAL (x
) & 0xffff) == 0xffff)
774 fprintf (file
, "%d", (INTVAL (x
) >> 16) & 0xffff);
776 output_operand_lossage ("invalid %%Z value");
781 /* Same as 'z', except the trailing 'o' or 'z' is not written. */
782 if (GET_CODE (x
) != CONST_INT
)
783 output_operand_lossage ("invalid %%k value");
785 if ((INTVAL (x
) & 0xffff0000) == 0
786 || (INTVAL (x
) & 0xffff0000) == 0xffff0000)
788 else if ((INTVAL (x
) & 0xffff) == 0
789 || (INTVAL (x
) & 0xffff) == 0xffff)
792 output_operand_lossage ("invalid %%k value");
797 /* Similar to 's', except that we write 'h' or 'u'. */
798 if (GET_CODE (x
) != CONST_INT
)
799 output_operand_lossage ("invalid %%k value");
808 /* For memory operations, write 's' if the operand is a short
810 if (short_memory_operand (x
, VOIDmode
))
815 /* Like 'M', but check for zero memory offset. */
816 if (zero_memory_operand (x
, VOIDmode
))
821 /* Write low-order part of DImode or DFmode. Supported for MEM
823 if (GET_CODE (x
) == REG
)
824 fprintf (file
, "%s", reg_names
[REGNO (x
) + 1]);
825 else if (GET_CODE (x
) == MEM
)
826 print_operand (file
, gen_rtx (MEM
, GET_MODE (x
),
827 plus_constant (XEXP (x
, 0), 4)), 0);
833 /* Offset in constant pool for constant pool address. */
834 if (! constant_pool_address_operand (x
, VOIDmode
))
836 if (GET_CODE (x
) == SYMBOL_REF
)
837 fprintf (file
, "%d", get_pool_offset (x
) + 12);
839 /* Must be (const (plus (symbol_ref) (const_int))) */
841 (get_pool_offset (XEXP (XEXP (x
, 0), 0)) + 12
842 + INTVAL (XEXP (XEXP (x
, 0), 1))));
846 /* Branch opcode. Check for condition in test bit for eq/ne. */
847 switch (GET_CODE (x
))
850 if (cc_status
.flags
& CC_IN_TB
)
851 fprintf (file
, "ntb");
853 fprintf (file
, "eq");
857 if (cc_status
.flags
& CC_IN_TB
)
858 fprintf (file
, "tb");
860 fprintf (file
, "ne");
875 fprintf (file
, "he");
880 fprintf (file
, "le");
884 output_operand_lossage ("invalid %%j value");
889 /* Reversed branch opcode. */
890 switch (GET_CODE (x
))
893 if (cc_status
.flags
& CC_IN_TB
)
894 fprintf (file
, "tb");
896 fprintf (file
, "ne");
900 if (cc_status
.flags
& CC_IN_TB
)
901 fprintf (file
, "ntb");
903 fprintf (file
, "eq");
908 fprintf (file
, "le");
913 fprintf (file
, "he");
927 output_operand_lossage ("invalid %%j value");
932 /* Output nothing. Used as delimiter in, e.g., "mc%B1%.3 " */
936 /* Output 'x' if this insn has a delay slot, else nothing. */
937 if (dbr_sequence_length ())
942 if (GET_CODE (x
) == REG
)
943 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
944 else if (GET_CODE (x
) == MEM
)
946 if (GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
947 && current_function_operand (x
, Pmode
))
948 fprintf (file
, "r14");
950 output_address (XEXP (x
, 0));
953 output_addr_const (file
, x
);
957 output_operand_lossage ("invalid %%xn code");
961 /* This page contains routines that are used to determine what the function
962 prologue and epilogue code will do and write them out. */
964 /* Return the first register that is required to be saved. 16 if none. */
971 /* Find lowest numbered live register. */
972 for (first_reg
= 6; first_reg
<= 15; first_reg
++)
973 if (regs_ever_live
[first_reg
])
976 /* If we think that we do not have to save r14, see if it will be used
978 if (first_reg
> 14 && romp_using_r14 ())
984 /* Compute the size of the save area in the stack, including the space for
985 the first four incoming arguments. */
993 /* We have the 4 words corresponding to the arguments passed in registers,
994 4 reserved words, space for static chain, general register save area,
995 and floating-point save area. */
996 size
= 4 + 4 + 1 + (16 - first_reg_to_save ());
998 /* The documentation says we have to leave 18 words in the save area if
999 any floating-point registers at all are saved, not the three words
1000 per register you might otherwise expect. */
1001 for (i
= 2 + (TARGET_FP_REGS
!= 0); i
<= 7; i
++)
1002 if (regs_ever_live
[i
+ 17])
1011 /* Return non-zero if this function makes calls or has fp operations
1012 (which are really calls). */
1019 for (insn
= get_insns (); insn
; insn
= next_insn (insn
))
1021 if (GET_CODE (insn
) == CALL_INSN
)
1023 else if (GET_CODE (insn
) == INSN
)
1025 rtx body
= PATTERN (insn
);
1027 if (GET_CODE (body
) != USE
&& GET_CODE (body
) != CLOBBER
1028 && GET_CODE (body
) != ADDR_VEC
1029 && GET_CODE (body
) != ADDR_DIFF_VEC
1030 && get_attr_type (insn
) == TYPE_FP
)
1038 /* Return non-zero if this function will use r14 as a pointer to its
1044 /* If we are debugging, profiling, have a non-empty constant pool, or
1045 call a function, we need r14. */
1046 return (write_symbols
!= NO_DEBUG
|| profile_flag
|| get_pool_size () != 0
1047 || romp_makes_calls ());
1050 /* Return non-zero if this function needs to push space on the stack. */
1053 romp_pushes_stack ()
1055 /* We need to push the stack if a frame pointer is needed (because the
1056 stack might be dynamically adjusted), if we are debugging, if the
1057 total required size is more than 100 bytes, or if we make calls. */
1059 return (frame_pointer_needed
|| write_symbols
!= NO_DEBUG
1060 || (romp_sa_size () + get_frame_size ()) > 100
1061 || romp_makes_calls ());
1064 /* Write function prologue.
1066 We compute the size of the fixed area required as follows:
1068 We always allocate 4 words for incoming arguments, 4 word reserved, 1
1069 word for static link, as many words as required for general register
1070 save area, plus 2 words for each FP reg 2-7 that must be saved. */
1073 output_prolog (file
, size
)
1078 int reg_save_offset
;
1080 int fp_save
= size
+ current_function_outgoing_args_size
;
1084 /* Add in fixed size plus output argument area. */
1085 size
+= romp_sa_size () + current_function_outgoing_args_size
;
1087 /* Compute first register to save and perform the save operation if anything
1088 needs to be saved. */
1089 first_reg
= first_reg_to_save();
1090 reg_save_offset
= - (4 + 4 + 1 + (16 - first_reg
)) * 4;
1091 if (first_reg
== 15)
1092 fprintf (file
, "\tst r15,%d(r1)\n", reg_save_offset
);
1093 else if (first_reg
< 16)
1094 fprintf (file
, "\tstm r%d,%d(r1)\n", first_reg
, reg_save_offset
);
1096 /* Set up pointer to data area if it is needed. */
1097 if (romp_using_r14 ())
1098 fprintf (file
, "\tcas r14,r0,r0\n");
1100 /* Set up frame pointer if needed. */
1101 if (frame_pointer_needed
)
1102 fprintf (file
, "\tcal r13,-%d(r1)\n", romp_sa_size () + 64);
1104 /* Push stack if neeeded. There are a couple of ways of doing this. */
1105 if (romp_pushes_stack ())
1111 fprintf (file
, "\tcau r0,%d(r0)\n", size
>> 16);
1112 fprintf (file
, "\toil r0,r0,%d\n", size
& 0xffff);
1115 fprintf (file
, "\tcal16 r0,%d(r0)\n", size
);
1116 fprintf (file
, "\ts r1,r0\n");
1119 fprintf (file
, "\tcal r1,-%d(r1)\n", size
);
1122 /* Save floating-point registers. */
1123 output_loadsave_fpregs (file
, USE
,
1124 plus_constant (stack_pointer_rtx
, fp_save
));
1127 /* Write function epilogue. */
1130 output_epilog (file
, size
)
1134 int first_reg
= first_reg_to_save();
1135 int pushes_stack
= romp_pushes_stack ();
1136 int reg_save_offset
= - ((16 - first_reg
) + 1 + 4 + 4) * 4;
1137 int total_size
= (size
+ romp_sa_size ()
1138 + current_function_outgoing_args_size
);
1139 int fp_save
= size
+ current_function_outgoing_args_size
;
1140 int long_frame
= total_size
>= 32768;
1141 rtx insn
= get_last_insn ();
1144 int nargs
= 0; /* words of arguments */
1147 for (argptr
= DECL_ARGUMENTS (current_function_decl
);
1148 argptr
; argptr
= TREE_CHAIN (argptr
))
1149 nargs
+= ((TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (argptr
)))
1150 + BITS_PER_WORD
- 1) / BITS_PER_WORD
);
1152 /* If the last insn was a BARRIER, we don't have to write anything except
1154 if (GET_CODE (insn
) == NOTE
)
1155 insn
= prev_nonnote_insn (insn
);
1156 if (insn
&& GET_CODE (insn
) == BARRIER
)
1159 /* Restore floating-point registers. */
1161 output_loadsave_fpregs (file
, CLOBBER
,
1162 gen_rtx (PLUS
, Pmode
, gen_rtx (REG
, Pmode
, 1),
1163 gen_rtx (CONST_INT
, VOIDmode
, fp_save
)));
1165 /* If we push the stack and do not have size > 32K, adjust the register
1166 save location to the current position of sp. Otherwise, if long frame,
1167 restore sp from fp. */
1168 if (pushes_stack
&& ! long_frame
)
1169 reg_save_offset
+= total_size
;
1170 else if (long_frame
&& write_code
)
1171 fprintf (file
, "\tcal r1,%d(r13)\n", romp_sa_size () + 64);
1173 /* Restore registers. */
1174 if (first_reg
== 15 && write_code
)
1175 fprintf (file
, "\tl r15,%d(r1)\n", reg_save_offset
);
1176 else if (first_reg
< 16 && write_code
)
1177 fprintf (file
, "\tlm r%d,%d(r1)\n", first_reg
, reg_save_offset
);
1178 if (first_reg
== 16) first_reg
= 0;
1180 /* Handle popping stack, if needed and write debug table entry. */
1186 fprintf (file
, "\tbr r15\n");
1188 fprintf (file
, "\tbrx r15\n\tcal r1,%d(r1)\n", total_size
);
1190 fprintf (file
, "\t.long 0x%x\n", 0xdf07df08 + first_reg
* 0x10);
1192 if (nargs
> 15) nargs
= 15;
1193 if (frame_pointer_needed
)
1194 fprintf (file
, "\t.byte 0x%xd, 53\n", nargs
);
1196 fprintf (file
, "\t.short 0x%x100\n", nargs
);
1201 fprintf (file
, "\tbr r15\n");
1202 fprintf (file
, "\t.long 0xdf02df00\n");
1205 /* Output any pending floating-point operations. */
1207 output_fpops (file
);
1210 /* For the ROMP we need to make new SYMBOL_REFs for the actual name of a
1211 called routine. To keep them unique we maintain a hash table of all
1212 that have been created so far. */
1214 struct symref_hashent
{
1215 rtx symref
; /* Created SYMBOL_REF rtx. */
1216 struct symref_hashent
*next
; /* Next with same hash code. */
1219 #define SYMHASHSIZE 151
1220 #define HASHBITS 65535
1222 /* Define the hash table itself. */
1224 static struct symref_hashent
*symref_hash_table
[SYMHASHSIZE
];
1226 /* Given a name (allocatable in temporary storage), return a SYMBOL_REF
1227 for the name. The rtx is allocated from the current rtl_obstack, while
1228 the name string is allocated from the permanent obstack. */
1231 register char *name
;
1233 extern struct obstack permanent_obstack
;
1234 register char *sp
= name
;
1235 unsigned int hash
= 0;
1236 struct symref_hashent
*p
, **last_p
;
1238 /* Compute the hash code for the string. */
1240 hash
= (hash
<< 4) + *sp
++;
1242 /* Search for a matching entry in the hash table, keeping track of the
1243 insertion location as we do so. */
1244 hash
= (hash
& HASHBITS
) % SYMHASHSIZE
;
1245 for (last_p
= &symref_hash_table
[hash
], p
= *last_p
;
1246 p
; last_p
= &p
->next
, p
= *last_p
)
1247 if (strcmp (name
, XSTR (p
->symref
, 0)) == 0)
1250 /* If couldn't find matching SYMBOL_REF, make a new one. */
1253 /* Ensure SYMBOL_REF will stay around. */
1254 end_temporary_allocation ();
1255 p
= *last_p
= (struct symref_hashent
*)
1256 permalloc (sizeof (struct symref_hashent
));
1257 p
->symref
= gen_rtx (SYMBOL_REF
, Pmode
,
1258 obstack_copy0 (&permanent_obstack
,
1259 name
, strlen (name
)));
1261 resume_temporary_allocation ();
1267 /* Validate the precision of a floating-point operation.
1269 We merge conversions from integers and between floating-point modes into
1270 the insn. However, this must not effect the desired precision of the
1271 insn. The RT floating-point system uses the widest of the operand modes.
1272 If this should be a double-precision insn, ensure that one operand
1273 passed to the floating-point processor has double mode.
1275 Note that since we don't check anything if the mode is single precision,
1276 it, strictly speaking, isn't necessary to call this for those insns.
1277 However, we do so in case something else needs to be checked in the
1280 This routine returns 1 if the operation is OK. */
1283 check_precision (opmode
, op1
, op2
)
1284 enum machine_mode opmode
;
1287 if (opmode
== SFmode
)
1290 /* If operand is not a conversion from an integer mode or an extension from
1291 single-precision, it must be a double-precision value. */
1292 if (GET_CODE (op1
) != FLOAT
&& GET_CODE (op1
) != FLOAT_EXTEND
)
1295 if (op2
&& GET_CODE (op2
) != FLOAT
&& GET_CODE (op2
) != FLOAT_EXTEND
)
1301 /* Floating-point on the RT is done by creating an operation block in the data
1302 area that describes the operation. If two floating-point operations are the
1303 same in a single function, they can use the same block.
1305 These routines are responsible for managing these blocks. */
1307 /* Structure to describe a floating-point operation. */
1310 struct fp_op
*next_same_hash
; /* Next op with same hash code. */
1311 struct fp_op
*next_in_mem
; /* Next op in memory. */
1312 int mem_offset
; /* Offset from data area. */
1313 short size
; /* Size of block in bytes. */
1314 short noperands
; /* Number of operands in block. */
1315 rtx ops
[3]; /* RTL for operands. */
1316 enum rtx_code opcode
; /* Operation being performed. */
1319 /* Size of hash table. */
1320 #define FP_HASH_SIZE 101
1322 /* Hash table of floating-point operation blocks. */
1323 static struct fp_op
*fp_hash_table
[FP_HASH_SIZE
];
1325 /* First floating-point block in data area. */
1326 static struct fp_op
*first_fpop
;
1328 /* Last block in data area so far. */
1329 static struct fp_op
*last_fpop_in_mem
;
1331 /* Subroutine number in file, to get unique "LF" labels. */
1332 static int subr_number
= 0;
1334 /* Current word offset in data area (includes header and any constant pool). */
1337 /* Compute hash code for an RTX used in floating-point. */
1343 register unsigned int hash
= (((int) GET_CODE (x
) << 10)
1344 + ((int) GET_MODE (x
) << 20));
1346 register char *fmt
= GET_RTX_FORMAT (GET_CODE (x
));
1348 for (i
= 0; i
< GET_RTX_LENGTH (GET_CODE (x
)); i
++)
1350 hash
+= hash_rtx (XEXP (x
, i
));
1351 else if (fmt
[i
] == 'u')
1352 hash
+= (int) XEXP (x
, i
);
1353 else if (fmt
[i
] == 'i')
1354 hash
+= XINT (x
, i
);
1355 else if (fmt
[i
] == 's')
1356 hash
+= (int) XSTR (x
, i
);
1361 /* Given an operation code and up to three operands, return a character string
1362 corresponding to the code to emit to branch to a floating-point operation
1363 block. INSN is provided to see if the delay slot has been filled or not.
1365 A new floating-point operation block is created if this operation has not
1366 been seen before. */
1369 output_fpop (code
, op0
, op1
, op2
, insn
)
1374 static char outbuf
[40];
1375 unsigned int hash
, hash0
, hash1
, hash2
;
1377 register struct fp_op
*fpop
, *last_fpop
;
1378 int dyadic
= (op2
!= 0);
1379 enum machine_mode opmode
;
1382 unsigned int tem_hash
;
1385 /* Compute hash code for each operand. If the operation is commutative,
1386 put the one with the smaller hash code first. This will make us see
1387 more operations as identical. */
1388 hash0
= op0
? hash_rtx (op0
) : 0;
1389 hash1
= op1
? hash_rtx (op1
) : 0;
1390 hash2
= op2
? hash_rtx (op2
) : 0;
1392 if (hash0
> hash1
&& code
== EQ
)
1394 tem
= op0
; op0
= op1
; op1
= tem
;
1395 tem_hash
= hash0
; hash0
= hash1
; hash1
= tem_hash
;
1397 else if (hash1
> hash2
&& (code
== PLUS
|| code
== MULT
))
1399 tem
= op1
; op1
= op2
; op2
= tem
;
1400 tem_hash
= hash1
; hash1
= hash2
; hash2
= tem_hash
;
1403 /* If operation is commutative and the first and third operands are equal,
1404 swap the second and third operands. Note that we must consider two
1405 operands equal if they are the same register even if different modes. */
1406 if (op2
&& (code
== PLUS
|| code
== MULT
)
1407 && (rtx_equal_p (op0
, op2
)
1408 || (GET_CODE (op0
) == REG
&& GET_CODE (op2
) == REG
1409 && REGNO (op0
) == REGNO (op2
))))
1411 tem
= op1
; op1
= op2
; op2
= tem
;
1412 tem_hash
= hash1
; hash1
= hash2
; hash2
= tem_hash
;
1415 /* If the first and second operands are the same, merge them. Don't do this
1416 for SFmode or SImode in general registers because this triggers a bug in
1418 if (op1
&& rtx_equal_p (op0
, op1
)
1419 && code
!= EQ
&& code
!= GE
&& code
!= SET
1420 && ((GET_MODE (op1
) != SFmode
&& GET_MODE (op1
) != SImode
)
1421 || GET_CODE (op0
) != REG
|| FP_REGNO_P (REGNO (op0
))))
1427 noperands
= 1 + (op1
!= 0) + (op2
!= 0);
1429 /* Compute hash code for entire expression and see if operation block
1431 hash
= ((int) code
<< 13) + (hash0
<< 2) + (hash1
<< 1) + hash2
;
1433 hash
%= FP_HASH_SIZE
;
1434 for (fpop
= fp_hash_table
[hash
], last_fpop
= 0;
1436 last_fpop
= fpop
, fpop
= fpop
->next_same_hash
)
1437 if (fpop
->opcode
== code
&& noperands
== fpop
->noperands
1438 && (op0
== 0 || rtx_equal_p (op0
, fpop
->ops
[0]))
1439 && (op1
== 0 || rtx_equal_p (op1
, fpop
->ops
[1]))
1440 && (op2
== 0 || rtx_equal_p (op2
, fpop
->ops
[2])))
1443 /* We have never seen this operation before. */
1444 fpop
= (struct fp_op
*) oballoc (sizeof (struct fp_op
));
1445 fpop
->mem_offset
= data_offset
;
1446 fpop
->opcode
= code
;
1447 fpop
->noperands
= noperands
;
1452 /* Compute the size using the rules in Appendix A of the RT Linkage
1453 Convention (4.3/RT-PSD:5) manual. These rules are a bit ambiguous,
1454 but if we guess wrong, it will effect only efficiency, not correctness. */
1456 /* Size = 24 + 32 for each non-fp (or fr7) */
1458 if (op0
&& (GET_CODE (op0
) != REG
1459 || ! FP_REGNO_P (REGNO (op0
)) || REGNO (op0
) == 23))
1462 if (op1
&& (GET_CODE (op1
) != REG
1463 || ! FP_REGNO_P (REGNO (op1
)) || REGNO (op1
) == 23))
1466 if (op2
&& (GET_CODE (op2
) != REG
1467 || ! FP_REGNO_P (REGNO (op2
)) || REGNO (op2
) == 23))
1470 /* Size + 12 for each conversion. First get operation mode. */
1471 if ((op0
&& GET_MODE (op0
) == DFmode
)
1472 || (op1
&& GET_MODE (op1
) == DFmode
)
1473 || (op2
&& GET_MODE (op2
) == DFmode
))
1478 if (op0
&& GET_MODE (op0
) != opmode
)
1480 if (op1
&& GET_MODE (op1
) != opmode
)
1482 if (op2
&& GET_MODE (op2
) != opmode
)
1485 /* 12 more if first and third operand types not the same. */
1486 if (op2
&& GET_MODE (op0
) != GET_MODE (op2
))
1489 /* CMP and CMPT need additional. Also, compute size of save/restore here. */
1492 else if (code
== GE
)
1494 else if (code
== USE
|| code
== CLOBBER
)
1496 /* 34 + 24 for each additional register plus 8 if fr7 saved. (We
1497 call it 36 because we need to keep the block length a multiple
1500 for (i
= 0; i
<= 7; i
++)
1501 if (INTVAL (op0
) & (1 << (7-i
)))
1502 size
+= 24 + 8 * (i
== 7);
1505 /* We provide no general-purpose scratch registers. */
1508 /* No floating-point scratch registers are provided. Compute extra
1509 length due to this. This logic is that shown in the referenced
1513 if (op0
&& GET_CODE (op0
) == REG
&& FP_REGNO_P (REGNO (op0
)))
1515 if (op1
&& GET_CODE (op1
) == REG
&& FP_REGNO_P (REGNO (op1
)))
1517 if (op2
&& GET_CODE (op2
) == REG
&& FP_REGNO_P (REGNO (op2
)))
1520 if ((op0
== 0 || GET_CODE (op0
) != REG
|| REGNO(op0
) != 17)
1521 && (op1
== 0 || GET_CODE (op1
) != REG
|| REGNO(op1
) != 17)
1522 && (op2
== 0 || GET_CODE (op2
) != REG
|| REGNO(op2
) != 17))
1528 size
+= fr0_avail
? 64 : 112;
1529 else if (fpop
->noperands
== 2 && i
== 1)
1530 size
+= fr0_avail
? 0 : 64;
1531 else if (fpop
->noperands
== 3)
1533 if (GET_CODE (op0
) == REG
&& FP_REGNO_P (REGNO (op0
))
1534 && GET_CODE (op2
) == REG
&& FP_REGNO_P (REGNO (op2
)))
1536 if (REGNO (op0
) == REGNO (op2
))
1538 /* This triggers a bug on the RT. */
1541 size
+= fr0_avail
? 0 : 64;
1547 if (GET_CODE (op0
) == REG
&& FP_REGNO_P (REGNO (op0
)))
1549 if (GET_CODE (op2
) == REG
&& FP_REGNO_P (REGNO (op2
)))
1552 size
+= fr0_avail
? 64 : 112;
1554 size
+= fr0_avail
? 0 : 64;
1558 else if (code
!= USE
&& code
!= CLOBBER
1559 && (GET_CODE (op0
) != REG
|| ! FP_REGNO_P (REGNO (op0
))))
1562 if (! TARGET_FULL_FP_BLOCKS
)
1564 /* If we are not to pad the blocks, just compute its actual length. */
1565 size
= 12; /* Header + opcode */
1566 if (code
== USE
|| code
== CLOBBER
)
1575 /* If in the middle of a word, round. */
1576 if (size
% UNITS_PER_WORD
)
1579 /* Handle any immediates. */
1580 if (code
!= USE
&& code
!= CLOBBER
&& op0
&& GET_CODE (op0
) != REG
)
1582 if (op1
&& GET_CODE (op1
) != REG
)
1584 if (op2
&& GET_CODE (op2
) != REG
)
1587 if (code
!= USE
&& code
!= CLOBBER
&&
1588 op0
&& GET_CODE (op0
) == CONST_DOUBLE
&& GET_MODE (op0
) == DFmode
)
1590 if (op1
&& GET_CODE (op1
) == CONST_DOUBLE
&& GET_MODE (op1
) == DFmode
)
1592 if (op2
&& GET_CODE (op2
) == CONST_DOUBLE
&& GET_MODE (op2
) == DFmode
)
1596 /* Done with size computation! Chain this in. */
1598 data_offset
+= size
/ UNITS_PER_WORD
;
1599 fpop
->next_in_mem
= 0;
1600 fpop
->next_same_hash
= 0;
1602 if (last_fpop_in_mem
)
1603 last_fpop_in_mem
->next_in_mem
= fpop
;
1606 last_fpop_in_mem
= fpop
;
1609 last_fpop
->next_same_hash
= fpop
;
1611 fp_hash_table
[hash
] = fpop
;
1614 /* FPOP describes the operation to be performed. Return a string to branch
1616 if (fpop
->mem_offset
< 32768 / UNITS_PER_WORD
)
1617 sprintf (outbuf
, "cal r15,%d(r14)\n\tbalr%s r15,r15",
1618 fpop
->mem_offset
* UNITS_PER_WORD
,
1619 dbr_sequence_length () ? "x" : "");
1621 sprintf (outbuf
, "get r15,$L%dF%d\n\tbalr%s r15,r15",
1622 subr_number
, fpop
->mem_offset
* UNITS_PER_WORD
,
1623 dbr_sequence_length () ? "x" : "");
1627 /* If necessary, output a floating-point operation to save or restore all
1628 floating-point registers.
1630 file is the file to write the operation to, CODE is USE for save, CLOBBER
1631 for restore, and ADDR is the address of the same area, as RTL. */
1634 output_loadsave_fpregs (file
, code
, addr
)
1640 register int mask
= 0;
1642 for (i
= 2 + (TARGET_FP_REGS
!= 0); i
<= 7; i
++)
1643 if (regs_ever_live
[i
+ 17])
1644 mask
|= 1 << (7 - i
);
1647 fprintf (file
, "\t%s\n",
1648 output_fpop (code
, gen_rtx (CONST_INT
, VOIDmode
, mask
),
1649 gen_rtx (MEM
, Pmode
, addr
),
1654 /* Output any floating-point operations at the end of the routine. */
1660 register struct fp_op
*fpop
;
1661 register int size_so_far
;
1665 if (first_fpop
== 0)
1670 ASM_OUTPUT_ALIGN (file
, 2);
1672 for (fpop
= first_fpop
; fpop
; fpop
= fpop
->next_in_mem
)
1674 if (fpop
->mem_offset
< 32768 / UNITS_PER_WORD
)
1675 fprintf (file
, "# data area offset = %d\n",
1676 fpop
->mem_offset
* UNITS_PER_WORD
);
1678 fprintf (file
, "L%dF%d:\n",
1679 subr_number
, fpop
->mem_offset
* UNITS_PER_WORD
);
1681 fprintf (file
, "\tcas r0,r15,r0\n");
1682 fprintf (file
, "\t.long FPGLUE\n");
1683 switch (fpop
->opcode
)
1686 fprintf (file
, "\t.byte 0x1d\t# STOREM\n");
1689 fprintf (file
, "\t.byte 0x0f\t# LOADM\n");
1692 fprintf (file
, "\t.byte 0x00\t# ABS\n");
1695 fprintf (file
, "\t.byte 0x02\t# ADD\n");
1698 fprintf (file
, "\t.byte 0x07\t# CMP\n");
1701 fprintf (file
, "\t.byte 0x08\t# CMPT\n");
1704 fprintf (file
, "\t.byte 0x0c\t# DIV\n");
1707 fprintf (file
, "\t.byte 0x14\t# MOVE\n");
1710 fprintf (file
, "\t.byte 0x15\t# MUL\n");
1713 fprintf (file
, "\t.byte 0x16\t# NEG\n");
1716 fprintf (file
, "\t.byte 0x1c\t# SQRT\n");
1719 fprintf (file
, "\t.byte 0x1e\t# SUB\n");
1725 fprintf (file
, "\t.byte %d\n", fpop
->noperands
);
1726 fprintf (file
, "\t.short 0x8001\n");
1728 if ((fpop
->ops
[0] == 0
1729 || GET_CODE (fpop
->ops
[0]) != REG
|| REGNO(fpop
->ops
[0]) != 17)
1730 && (fpop
->ops
[1] == 0 || GET_CODE (fpop
->ops
[1]) != REG
1731 || REGNO(fpop
->ops
[1]) != 17)
1732 && (fpop
->ops
[2] == 0 || GET_CODE (fpop
->ops
[2]) != REG
1733 || REGNO(fpop
->ops
[2]) != 17))
1734 fprintf (file
, "\t.byte %d, 0x80\n", fpop
->size
);
1736 fprintf (file
, "\t.byte %d, 0\n", fpop
->size
);
1738 for (i
= 0; i
< fpop
->noperands
; i
++)
1741 register int opbyte
;
1742 register char *desc0
;
1746 switch (GET_MODE (fpop
->ops
[i
]))
1765 switch (GET_CODE (fpop
->ops
[i
]))
1768 strcpy(desc1
, reg_names
[REGNO (fpop
->ops
[i
])]);
1769 if (FP_REGNO_P (REGNO (fpop
->ops
[i
])))
1772 opbyte
= REGNO (fpop
->ops
[i
]) - 17;
1777 opbyte
= REGNO (fpop
->ops
[i
]);
1779 opbyte
= (opbyte
<< 4) + opbyte
+ 1;
1785 if (GET_CODE (XEXP (fpop
->ops
[i
], 0)) == PLUS
)
1787 immed
[i
] = XEXP (XEXP (fpop
->ops
[i
], 0), 1);
1788 opbyte
= REGNO (XEXP (XEXP (fpop
->ops
[i
], 0), 0));
1789 if (GET_CODE (immed
[i
]) == CONST_INT
)
1790 sprintf (desc1
, "%d(%s)", INTVAL (immed
[i
]),
1793 sprintf (desc1
, "<memory> (%s)", reg_names
[opbyte
]);
1795 else if (GET_CODE (XEXP (fpop
->ops
[i
], 0)) == REG
)
1797 opbyte
= REGNO (XEXP (fpop
->ops
[i
], 0));
1798 immed
[i
] = const0_rtx
;
1799 sprintf (desc1
, "(%s)", reg_names
[opbyte
]);
1803 immed
[i
] = XEXP (fpop
->ops
[i
], 0);
1805 sprintf(desc1
, "<memory>");
1814 immed
[i
] = fpop
->ops
[i
];
1823 /* Save/restore is special. */
1824 if (i
== 0 && (fpop
->opcode
== USE
|| fpop
->opcode
== CLOBBER
))
1825 type
= 0xff, opbyte
= INTVAL (fpop
->ops
[0]), immed
[i
] = 0;
1827 fprintf (file
, "\t.byte 0x%x,0x%x # (%s) %s\n",
1828 type
, opbyte
, desc0
, desc1
);
1833 /* If in the middle of a word, round. */
1834 if (size_so_far
% UNITS_PER_WORD
)
1836 fprintf (file
, "\t.space 2\n");
1840 for (i
= 0; i
< fpop
->noperands
; i
++)
1842 switch (GET_MODE (immed
[i
]))
1847 fprintf (file
, "\t.long ");
1848 output_addr_const (file
, immed
[i
]);
1849 fprintf (file
, "\n");
1856 if (GET_CODE (immed
[i
]) == CONST_DOUBLE
)
1858 union real_extract u
;
1860 bcopy (&CONST_DOUBLE_LOW (immed
[i
]), &u
, sizeof u
);
1861 if (GET_MODE (immed
[i
]) == DFmode
)
1862 ASM_OUTPUT_DOUBLE (file
, u
.d
);
1864 ASM_OUTPUT_FLOAT (file
, u
.d
);
1874 if (size_so_far
!= fpop
->size
)
1876 if (TARGET_FULL_FP_BLOCKS
)
1877 fprintf (file
, "\t.space %d\n", fpop
->size
- size_so_far
);
1883 /* Update for next subroutine. */
1888 /* Initialize floating-point operation table. */
1895 first_fpop
= last_fpop_in_mem
= 0;
1896 for (i
= 0; i
< FP_HASH_SIZE
; i
++)
1897 fp_hash_table
[i
] = 0;