1 /* Subroutines for insn-output.c for VAX.
2 Copyright (C) 1987, 1994, 1995, 1997, 1998, 1999, 2000
3 Free Software Foundation, Inc.
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, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
26 #include "hard-reg-set.h"
28 #include "insn-config.h"
29 #include "conditions.h"
32 #include "insn-attr.h"
38 #include "target-def.h"
40 static int follows_p
PARAMS ((rtx
, rtx
));
41 static void vax_output_function_prologue
PARAMS ((FILE *, HOST_WIDE_INT
));
43 static void vms_asm_out_constructor
PARAMS ((rtx
, int));
44 static void vms_asm_out_destructor
PARAMS ((rtx
, int));
47 /* Initialize the GCC target structure. */
48 #undef TARGET_ASM_ALIGNED_HI_OP
49 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
51 #undef TARGET_ASM_FUNCTION_PROLOGUE
52 #define TARGET_ASM_FUNCTION_PROLOGUE vax_output_function_prologue
54 struct gcc_target targetm
= TARGET_INITIALIZER
;
56 /* Generate the assembly code for function entry. FILE is a stdio
57 stream to output the code to. SIZE is an int: how many units of
58 temporary storage to allocate.
60 Refer to the array `regs_ever_live' to determine which registers to
61 save; `regs_ever_live[I]' is nonzero if register number I is ever
62 used in the function. This function is responsible for knowing
63 which registers should not be saved even if used. */
66 vax_output_function_prologue (file
, size
)
71 register int mask
= 0;
72 extern char call_used_regs
[];
74 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
75 if (regs_ever_live
[regno
] && !call_used_regs
[regno
])
78 fprintf (file
, "\t.word 0x%x\n", mask
);
83 * This works for both gcc and g++. It first checks to see if
84 * the current routine is "main", which will only happen for
85 * GCC, and add the jsb if it is. If is not the case then try
86 * and see if __MAIN_NAME is part of current_function_name,
87 * which will only happen if we are running g++, and add the jsb
88 * if it is. In gcc there should never be a paren in the
89 * function name, and in g++ there is always a "(" in the
90 * function name, thus there should never be any confusion.
92 * Adjusting the stack pointer by 4 before calling C$MAIN_ARGS
93 * is required when linking with the VMS POSIX version of the C
94 * run-time library; using `subl2 $4,r0' is adequate but we use
95 * `clrl -(sp)' instead. The extra 4 bytes could be removed
96 * after the call because STARTING_FRAME_OFFSET's setting of -4
97 * will end up adding them right back again, but don't bother.
100 const char *p
= current_function_name
;
101 int is_main
= strcmp ("main", p
) == 0;
102 # define __MAIN_NAME " main("
104 while (!is_main
&& *p
!= '\0')
106 if (*p
== *__MAIN_NAME
107 && strncmp (p
, __MAIN_NAME
, sizeof __MAIN_NAME
- sizeof "") == 0)
114 fprintf (file
, "\t%s\n\t%s\n", "clrl -(sp)", "jsb _C$MAIN_ARGS");
117 size
-= STARTING_FRAME_OFFSET
;
119 fprintf (file
, "\tmovab %d(sp),sp\n", -size
);
121 fprintf (file
, "\tsubl2 $%d,sp\n", size
);
124 /* This is like nonimmediate_operand with a restriction on the type of MEM. */
127 split_quadword_operands (operands
, low
, n
)
129 int n ATTRIBUTE_UNUSED
;
132 /* Split operands. */
134 low
[0] = low
[1] = low
[2] = 0;
135 for (i
= 0; i
< 3; i
++)
138 /* it's already been figured out */;
139 else if (GET_CODE (operands
[i
]) == MEM
140 && (GET_CODE (XEXP (operands
[i
], 0)) == POST_INC
))
142 rtx addr
= XEXP (operands
[i
], 0);
143 operands
[i
] = low
[i
] = gen_rtx_MEM (SImode
, addr
);
144 if (which_alternative
== 0 && i
== 0)
146 addr
= XEXP (operands
[i
], 0);
147 operands
[i
+1] = low
[i
+1] = gen_rtx_MEM (SImode
, addr
);
152 low
[i
] = operand_subword (operands
[i
], 0, 0, DImode
);
153 operands
[i
] = operand_subword (operands
[i
], 1, 0, DImode
);
159 print_operand_address (file
, addr
)
163 register rtx reg1
, breg
, ireg
;
167 switch (GET_CODE (addr
))
171 addr
= XEXP (addr
, 0);
175 fprintf (file
, "(%s)", reg_names
[REGNO (addr
)]);
179 fprintf (file
, "-(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
183 fprintf (file
, "(%s)+", reg_names
[REGNO (XEXP (addr
, 0))]);
187 /* There can be either two or three things added here. One must be a
188 REG. One can be either a REG or a MULT of a REG and an appropriate
189 constant, and the third can only be a constant or a MEM.
191 We get these two or three things and put the constant or MEM in
192 OFFSET, the MULT or REG in IREG, and the REG in BREG. If we have
193 a register and can't tell yet if it is a base or index register,
196 reg1
= 0; ireg
= 0; breg
= 0; offset
= 0;
198 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0))
199 || GET_CODE (XEXP (addr
, 0)) == MEM
)
201 offset
= XEXP (addr
, 0);
202 addr
= XEXP (addr
, 1);
204 else if (CONSTANT_ADDRESS_P (XEXP (addr
, 1))
205 || GET_CODE (XEXP (addr
, 1)) == MEM
)
207 offset
= XEXP (addr
, 1);
208 addr
= XEXP (addr
, 0);
210 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
212 ireg
= XEXP (addr
, 1);
213 addr
= XEXP (addr
, 0);
215 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
217 ireg
= XEXP (addr
, 0);
218 addr
= XEXP (addr
, 1);
220 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
222 reg1
= XEXP (addr
, 1);
223 addr
= XEXP (addr
, 0);
225 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
227 reg1
= XEXP (addr
, 0);
228 addr
= XEXP (addr
, 1);
233 if (GET_CODE (addr
) == REG
)
240 else if (GET_CODE (addr
) == MULT
)
242 else if (GET_CODE (addr
) == PLUS
)
244 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0))
245 || GET_CODE (XEXP (addr
, 0)) == MEM
)
249 if (GET_CODE (offset
) == CONST_INT
)
250 offset
= plus_constant (XEXP (addr
, 0), INTVAL (offset
));
251 else if (GET_CODE (XEXP (addr
, 0)) == CONST_INT
)
252 offset
= plus_constant (offset
, INTVAL (XEXP (addr
, 0)));
256 offset
= XEXP (addr
, 0);
258 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
261 ireg
= reg1
, breg
= XEXP (addr
, 0), reg1
= 0;
263 reg1
= XEXP (addr
, 0);
265 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
269 ireg
= XEXP (addr
, 0);
274 if (CONSTANT_ADDRESS_P (XEXP (addr
, 1))
275 || GET_CODE (XEXP (addr
, 1)) == MEM
)
279 if (GET_CODE (offset
) == CONST_INT
)
280 offset
= plus_constant (XEXP (addr
, 1), INTVAL (offset
));
281 else if (GET_CODE (XEXP (addr
, 1)) == CONST_INT
)
282 offset
= plus_constant (offset
, INTVAL (XEXP (addr
, 1)));
286 offset
= XEXP (addr
, 1);
288 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
291 ireg
= reg1
, breg
= XEXP (addr
, 1), reg1
= 0;
293 reg1
= XEXP (addr
, 1);
295 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
299 ireg
= XEXP (addr
, 1);
307 /* If REG1 is non-zero, figure out if it is a base or index register. */
310 if (breg
!= 0 || (offset
&& GET_CODE (offset
) == MEM
))
321 output_address (offset
);
324 fprintf (file
, "(%s)", reg_names
[REGNO (breg
)]);
328 if (GET_CODE (ireg
) == MULT
)
329 ireg
= XEXP (ireg
, 0);
330 if (GET_CODE (ireg
) != REG
)
332 fprintf (file
, "[%s]", reg_names
[REGNO (ireg
)]);
337 output_addr_const (file
, addr
);
345 switch (GET_CODE (op
))
377 register enum machine_mode mode
;
378 #if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
380 union {double d
; int i
[2];} val
;
383 if (GET_CODE (c
) != CONST_DOUBLE
)
388 if (c
== const_tiny_rtx
[(int) mode
][0]
389 || c
== const_tiny_rtx
[(int) mode
][1]
390 || c
== const_tiny_rtx
[(int) mode
][2])
393 #if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
395 val
.i
[0] = CONST_DOUBLE_LOW (c
);
396 val
.i
[1] = CONST_DOUBLE_HIGH (c
);
398 for (i
= 0; i
< 7; i
++)
399 if (val
.d
== 1 << i
|| val
.d
== 1 / (1 << i
))
406 /* Return the cost in cycles of a memory address, relative to register
409 Each of the following adds the indicated number of cycles:
413 1 - indexing and/or offset(register)
418 vax_address_cost (addr
)
421 int reg
= 0, indexed
= 0, indir
= 0, offset
= 0, predec
= 0;
422 rtx plus_op0
= 0, plus_op1
= 0;
424 switch (GET_CODE (addr
))
434 indexed
= 1; /* 2 on VAX 2 */
437 /* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */
439 offset
= (unsigned)(INTVAL(addr
)+128) > 256;
443 offset
= 1; /* 2 on VAX 2 */
445 case LABEL_REF
: /* this is probably a byte offset from the pc */
451 plus_op1
= XEXP (addr
, 0);
453 plus_op0
= XEXP (addr
, 0);
454 addr
= XEXP (addr
, 1);
457 indir
= 2; /* 3 on VAX 2 */
458 addr
= XEXP (addr
, 0);
464 /* Up to 3 things can be added in an address. They are stored in
465 plus_op0, plus_op1, and addr. */
479 /* Indexing and register+offset can both be used (except on a VAX 2)
480 without increasing execution time over either one alone. */
481 if (reg
&& indexed
&& offset
)
482 return reg
+ indir
+ offset
+ predec
;
483 return reg
+ indexed
+ indir
+ offset
+ predec
;
487 /* Cost of an expression on a VAX. This version has costs tuned for the
488 CVAX chip (found in the VAX 3 series) with comments for variations on
495 register enum rtx_code code
= GET_CODE (x
);
496 enum machine_mode mode
= GET_MODE (x
);
498 int i
= 0; /* may be modified in switch */
499 const char *fmt
= GET_RTX_FORMAT (code
); /* may be modified in switch */
511 c
= 16; /* 4 on VAX 9000 */
514 c
= 9; /* 4 on VAX 9000, 12 on VAX 2 */
517 c
= 16; /* 6 on VAX 9000, 28 on VAX 2 */
522 c
= 10; /* 3-4 on VAX 9000, 20-28 on VAX 2 */
533 c
= 30; /* highly variable */
534 else if (mode
== DFmode
)
535 /* divide takes 28 cycles if the result is not zero, 13 otherwise */
538 c
= 11; /* 25 on VAX 2 */
547 c
= 6 + (mode
== DFmode
) + (GET_MODE (XEXP (x
, 0)) != SImode
);
551 c
= 7; /* 17 on VAX 2 */
559 c
= 10; /* 6 on VAX 9000 */
563 c
= 6; /* 5 on VAX 2, 4 on VAX 9000 */
564 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
565 fmt
= "e"; /* all constant rotate counts are short */
568 /* Check for small negative integer operand: subl2 can be used with
569 a short positive constant instead. */
570 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
571 if ((unsigned)(INTVAL (XEXP (x
, 1)) + 63) < 127)
574 c
= (mode
== DFmode
) ? 13 : 8; /* 6/8 on VAX 9000, 16/15 on VAX 2 */
580 /* AND is special because the first operand is complemented. */
582 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
584 if ((unsigned)~INTVAL (XEXP (x
, 0)) > 63)
593 else if (mode
== SFmode
)
595 else if (mode
== DImode
)
604 if (mode
== DImode
|| mode
== DFmode
)
605 c
= 5; /* 7 on VAX 2 */
607 c
= 3; /* 4 on VAX 2 */
609 if (GET_CODE (x
) == REG
|| GET_CODE (x
) == POST_INC
)
611 return c
+ vax_address_cost (x
);
618 /* Now look inside the expression. Operands which are not registers or
619 short constants add to the cost.
621 FMT and I may have been adjusted in the switch above for instructions
622 which require special handling */
624 while (*fmt
++ == 'e')
626 register rtx op
= XEXP (x
, i
++);
627 code
= GET_CODE (op
);
629 /* A NOT is likely to be found as the first operand of an AND
630 (in which case the relevant cost is of the operand inside
631 the not) and not likely to be found anywhere else. */
633 op
= XEXP (op
, 0), code
= GET_CODE (op
);
638 if ((unsigned)INTVAL (op
) > 63 && GET_MODE (x
) != QImode
)
639 c
+= 1; /* 2 on VAX 2 */
644 c
+= 1; /* 2 on VAX 2 */
647 if (GET_MODE_CLASS (GET_MODE (op
)) == MODE_FLOAT
)
649 /* Registers are faster than floating point constants -- even
650 those constants which can be encoded in a single byte. */
651 if (vax_float_literal (op
))
654 c
+= (GET_MODE (x
) == DFmode
) ? 3 : 2;
658 if (CONST_DOUBLE_HIGH (op
) != 0
659 || (unsigned)CONST_DOUBLE_LOW (op
) > 63)
664 c
+= 1; /* 2 on VAX 2 */
665 if (GET_CODE (XEXP (op
, 0)) != REG
)
666 c
+= vax_address_cost (XEXP (op
, 0));
679 /* Check a `double' value for validity for a particular machine mode. */
681 static const char *const float_strings
[] =
683 "1.70141173319264430e+38", /* 2^127 (2^24 - 1) / 2^24 */
684 "-1.70141173319264430e+38",
685 "2.93873587705571877e-39", /* 2^-128 */
686 "-2.93873587705571877e-39"
689 static REAL_VALUE_TYPE float_values
[4];
691 static int inited_float_values
= 0;
695 check_float_value (mode
, d
, overflow
)
696 enum machine_mode mode
;
700 if (inited_float_values
== 0)
703 for (i
= 0; i
< 4; i
++)
705 float_values
[i
] = REAL_VALUE_ATOF (float_strings
[i
], DFmode
);
708 inited_float_values
= 1;
713 memcpy (d
, &float_values
[0], sizeof (REAL_VALUE_TYPE
));
717 if ((mode
) == SFmode
)
720 memcpy (&r
, d
, sizeof (REAL_VALUE_TYPE
));
721 if (REAL_VALUES_LESS (float_values
[0], r
))
723 memcpy (d
, &float_values
[0], sizeof (REAL_VALUE_TYPE
));
726 else if (REAL_VALUES_LESS (r
, float_values
[1]))
728 memcpy (d
, &float_values
[1], sizeof (REAL_VALUE_TYPE
));
731 else if (REAL_VALUES_LESS (dconst0
, r
)
732 && REAL_VALUES_LESS (r
, float_values
[2]))
734 memcpy (d
, &dconst0
, sizeof (REAL_VALUE_TYPE
));
737 else if (REAL_VALUES_LESS (r
, dconst0
)
738 && REAL_VALUES_LESS (float_values
[3], r
))
740 memcpy (d
, &dconst0
, sizeof (REAL_VALUE_TYPE
));
749 /* Additional support code for VMS target. */
751 /* Linked list of all externals that are to be emitted when optimizing
752 for the global pointer if they haven't been declared by the end of
753 the program with an appropriate .comm or initialization. */
757 struct extern_list
*next
; /* next external */
758 const char *name
; /* name of the external */
759 int size
; /* external's actual size */
760 int in_const
; /* section type flag */
761 } *extern_head
= 0, *pending_head
= 0;
763 /* Check whether NAME is already on the external definition list. If not,
764 add it to either that list or the pending definition list. */
767 vms_check_external (decl
, name
, pending
)
772 register struct extern_list
*p
, *p0
;
774 for (p
= extern_head
; p
; p
= p
->next
)
775 if (!strcmp (p
->name
, name
))
778 for (p
= pending_head
, p0
= 0; p
; p0
= p
, p
= p
->next
)
779 if (!strcmp (p
->name
, name
))
784 /* Was pending, but has now been defined; move it to other list. */
785 if (p
== pending_head
)
786 pending_head
= p
->next
;
789 p
->next
= extern_head
;
794 /* Not previously seen; create a new list entry. */
795 p
= (struct extern_list
*)permalloc ((long) sizeof (struct extern_list
));
800 /* Save the size and section type and link to `pending' list. */
801 p
->size
= (DECL_SIZE (decl
) == 0) ? 0 :
802 TREE_INT_CST_LOW (size_binop (CEIL_DIV_EXPR
, DECL_SIZE (decl
),
803 size_int (BITS_PER_UNIT
)));
804 p
->in_const
= (TREE_READONLY (decl
) && ! TREE_THIS_VOLATILE (decl
));
806 p
->next
= pending_head
;
811 /* Size and section type don't matter; link to `declared' list. */
812 p
->size
= p
->in_const
= 0; /* arbitrary init */
814 p
->next
= extern_head
;
821 vms_flush_pending_externals (file
)
824 register struct extern_list
*p
;
828 /* Move next pending declaration to the "done" list. */
830 pending_head
= p
->next
;
831 p
->next
= extern_head
;
834 /* Now output the actual declaration. */
839 fputs (".comm ", file
);
840 assemble_name (file
, p
->name
);
841 fprintf (file
, ",%d\n", p
->size
);
846 vms_asm_out_constructor (symbol
, priority
)
848 int priority ATTRIBUTE_UNUSED
;
850 fprintf (asm_out_file
,".globl $$PsectAttributes_NOOVR$$__gxx_init_1\n");
852 fprintf (asm_out_file
,"$$PsectAttributes_NOOVR$$__gxx_init_1:\n\t.long\t");
853 assemble_name (asm_out_file
, XSTR (symbol
, 0));
854 fputc ('\n', asm_out_file
);
858 vms_asm_out_destructor (symbol
, priority
)
860 int priority ATTRIBUTE_UNUSED
;
862 fprintf (asm_out_file
,".globl $$PsectAttributes_NOOVR$$__gxx_clean_1\n");
864 fprintf (asm_out_file
,"$$PsectAttributes_NOOVR$$__gxx_clean_1:\n\t.long\t");
865 assemble_name (asm_out_file
, XSTR (symbol
, 0));
866 fputc ('\n', asm_out_file
);
868 #endif /* VMS_TARGET */
870 /* Additional support code for VMS host. */
871 /* ??? This should really be in libiberty; vax.c is a target file. */
872 #ifdef QSORT_WORKAROUND
874 Do not use VAXCRTL's qsort() due to a severe bug: once you've
875 sorted something which has a size that's an exact multiple of 4
876 and is longword aligned, you cannot safely sort anything which
877 is either not a multiple of 4 in size or not longword aligned.
878 A static "move-by-longword" optimization flag inside qsort() is
879 never reset. This is known to affect VMS V4.6 through VMS V5.5-1,
880 and was finally fixed in VMS V5.5-2.
882 In this work-around an insertion sort is used for simplicity.
883 The qsort code from glibc should probably be used instead.
886 not_qsort (array
, count
, size
, compare
)
888 unsigned count
, size
;
892 if (size
== sizeof (short))
895 register short *next
, *prev
;
896 short tmp
, *base
= array
;
898 for (next
= base
, i
= count
- 1; i
> 0; i
--)
901 if ((*compare
)(next
, prev
) < 0)
904 do *(prev
+ 1) = *prev
;
905 while (--prev
>= base
? (*compare
)(&tmp
, prev
) < 0 : 0);
910 else if (size
== sizeof (long))
913 register long *next
, *prev
;
914 long tmp
, *base
= array
;
916 for (next
= base
, i
= count
- 1; i
> 0; i
--)
919 if ((*compare
)(next
, prev
) < 0)
922 do *(prev
+ 1) = *prev
;
923 while (--prev
>= base
? (*compare
)(&tmp
, prev
) < 0 : 0);
928 else /* arbitrary size */
931 register char *next
, *prev
, *tmp
= alloca (size
), *base
= array
;
933 for (next
= base
, i
= count
- 1; i
> 0; i
--)
934 { /* count-1 forward iterations */
935 prev
= next
, next
+= size
; /* increment front pointer */
936 if ((*compare
)(next
, prev
) < 0)
937 { /* found element out of order; move others up then re-insert */
938 memcpy (tmp
, next
, size
); /* save smaller element */
939 do { memcpy (prev
+ size
, prev
, size
); /* move larger elem. up */
940 prev
-= size
; /* decrement back pointer */
941 } while (prev
>= base
? (*compare
)(tmp
, prev
) < 0 : 0);
942 memcpy (prev
+ size
, tmp
, size
); /* restore small element */
952 #endif /* QSORT_WORKAROUND */
954 /* Return 1 if insn A follows B. */
962 for (p
= a
; p
!= b
; p
= NEXT_INSN (p
))
969 /* Returns 1 if we know operand OP was 0 before INSN. */
972 reg_was_0_p (insn
, op
)
977 return ((link
= find_reg_note (insn
, REG_WAS_0
, 0))
978 /* Make sure the insn that stored the 0 is still present
979 and doesn't follow INSN in the insn sequence. */
980 && ! INSN_DELETED_P (XEXP (link
, 0))
981 && GET_CODE (XEXP (link
, 0)) != NOTE
982 && ! follows_p (XEXP (link
, 0), insn
)
983 /* Make sure cross jumping didn't happen here. */
984 && no_labels_between_p (XEXP (link
, 0), insn
)
985 /* Make sure the reg hasn't been clobbered. */
986 && ! reg_set_between_p (op
, XEXP (link
, 0), insn
));