1 /* Subroutines for insn-output.c for VAX.
2 Copyright (C) 1987, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002
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. */
27 #include "hard-reg-set.h"
29 #include "insn-config.h"
30 #include "conditions.h"
33 #include "insn-attr.h"
39 #include "target-def.h"
41 static int follows_p
PARAMS ((rtx
, rtx
));
42 static void vax_output_function_prologue
PARAMS ((FILE *, HOST_WIDE_INT
));
44 static void vms_asm_out_constructor
PARAMS ((rtx
, int));
45 static void vms_asm_out_destructor
PARAMS ((rtx
, int));
46 static void vms_select_section
PARAMS ((tree
, int, unsigned HOST_WIDE_INT
));
47 static void vms_encode_section_info
PARAMS ((tree
, int));
48 static void vms_globalize_label
PARAMS ((FILE *, const char *));
51 /* Initialize the GCC target structure. */
52 #undef TARGET_ASM_ALIGNED_HI_OP
53 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
55 #undef TARGET_ASM_FUNCTION_PROLOGUE
56 #define TARGET_ASM_FUNCTION_PROLOGUE vax_output_function_prologue
59 #undef TARGET_ASM_SELECT_SECTION
60 #define TARGET_ASM_SELECT_SECTION vms_select_section
61 #undef TARGET_ENCODE_SECTION_INFO
62 #define TARGET_ENCODE_SECTION_INFO vms_encode_section_info
63 #undef TARGET_ASM_GLOBALIZE_LABEL
64 #define TARGET_ASM_GLOBALIZE_LABEL vms_globalize_label
67 struct gcc_target targetm
= TARGET_INITIALIZER
;
69 /* Set global variables as needed for the options enabled. */
74 /* We're VAX floating point, not IEEE floating point. */
75 memset (real_format_for_mode
, 0, sizeof real_format_for_mode
);
76 real_format_for_mode
[SFmode
- QFmode
] = &vax_f_format
;
77 real_format_for_mode
[DFmode
- QFmode
]
78 = (TARGET_G_FLOAT
? &vax_g_format
: &vax_d_format
);
81 /* Generate the assembly code for function entry. FILE is a stdio
82 stream to output the code to. SIZE is an int: how many units of
83 temporary storage to allocate.
85 Refer to the array `regs_ever_live' to determine which registers to
86 save; `regs_ever_live[I]' is nonzero if register number I is ever
87 used in the function. This function is responsible for knowing
88 which registers should not be saved even if used. */
91 vax_output_function_prologue (file
, size
)
96 register int mask
= 0;
98 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
99 if (regs_ever_live
[regno
] && !call_used_regs
[regno
])
102 fprintf (file
, "\t.word 0x%x\n", mask
);
107 * This works for both gcc and g++. It first checks to see if
108 * the current routine is "main", which will only happen for
109 * GCC, and add the jsb if it is. If is not the case then try
110 * and see if __MAIN_NAME is part of current_function_name,
111 * which will only happen if we are running g++, and add the jsb
112 * if it is. In gcc there should never be a paren in the
113 * function name, and in g++ there is always a "(" in the
114 * function name, thus there should never be any confusion.
116 * Adjusting the stack pointer by 4 before calling C$MAIN_ARGS
117 * is required when linking with the VMS POSIX version of the C
118 * run-time library; using `subl2 $4,r0' is adequate but we use
119 * `clrl -(sp)' instead. The extra 4 bytes could be removed
120 * after the call because STARTING_FRAME_OFFSET's setting of -4
121 * will end up adding them right back again, but don't bother.
124 const char *p
= current_function_name
;
125 int is_main
= strcmp ("main", p
) == 0;
126 # define __MAIN_NAME " main("
128 while (!is_main
&& *p
!= '\0')
130 if (*p
== *__MAIN_NAME
131 && strncmp (p
, __MAIN_NAME
, sizeof __MAIN_NAME
- sizeof "") == 0)
138 fprintf (file
, "\tclrl -(%ssp)\n\tjsb _C$MAIN_ARGS\n",
142 size
-= STARTING_FRAME_OFFSET
;
144 fprintf (file
, "\tmovab %d(%ssp),%ssp\n", -size
, REGISTER_PREFIX
,
147 fprintf (file
, "\tsubl2 $%d,%ssp\n", size
, REGISTER_PREFIX
);
150 /* This is like nonimmediate_operand with a restriction on the type of MEM. */
153 split_quadword_operands (operands
, low
, n
)
155 int n ATTRIBUTE_UNUSED
;
158 /* Split operands. */
160 low
[0] = low
[1] = low
[2] = 0;
161 for (i
= 0; i
< 3; i
++)
164 /* it's already been figured out */;
165 else if (GET_CODE (operands
[i
]) == MEM
166 && (GET_CODE (XEXP (operands
[i
], 0)) == POST_INC
))
168 rtx addr
= XEXP (operands
[i
], 0);
169 operands
[i
] = low
[i
] = gen_rtx_MEM (SImode
, addr
);
170 if (which_alternative
== 0 && i
== 0)
172 addr
= XEXP (operands
[i
], 0);
173 operands
[i
+1] = low
[i
+1] = gen_rtx_MEM (SImode
, addr
);
178 low
[i
] = operand_subword (operands
[i
], 0, 0, DImode
);
179 operands
[i
] = operand_subword (operands
[i
], 1, 0, DImode
);
185 print_operand_address (file
, addr
)
189 register rtx reg1
, breg
, ireg
;
193 switch (GET_CODE (addr
))
197 addr
= XEXP (addr
, 0);
201 fprintf (file
, "(%s)", reg_names
[REGNO (addr
)]);
205 fprintf (file
, "-(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
209 fprintf (file
, "(%s)+", reg_names
[REGNO (XEXP (addr
, 0))]);
213 /* There can be either two or three things added here. One must be a
214 REG. One can be either a REG or a MULT of a REG and an appropriate
215 constant, and the third can only be a constant or a MEM.
217 We get these two or three things and put the constant or MEM in
218 OFFSET, the MULT or REG in IREG, and the REG in BREG. If we have
219 a register and can't tell yet if it is a base or index register,
222 reg1
= 0; ireg
= 0; breg
= 0; offset
= 0;
224 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0))
225 || GET_CODE (XEXP (addr
, 0)) == MEM
)
227 offset
= XEXP (addr
, 0);
228 addr
= XEXP (addr
, 1);
230 else if (CONSTANT_ADDRESS_P (XEXP (addr
, 1))
231 || GET_CODE (XEXP (addr
, 1)) == MEM
)
233 offset
= XEXP (addr
, 1);
234 addr
= XEXP (addr
, 0);
236 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
238 ireg
= XEXP (addr
, 1);
239 addr
= XEXP (addr
, 0);
241 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
243 ireg
= XEXP (addr
, 0);
244 addr
= XEXP (addr
, 1);
246 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
248 reg1
= XEXP (addr
, 1);
249 addr
= XEXP (addr
, 0);
251 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
253 reg1
= XEXP (addr
, 0);
254 addr
= XEXP (addr
, 1);
259 if (GET_CODE (addr
) == REG
)
266 else if (GET_CODE (addr
) == MULT
)
268 else if (GET_CODE (addr
) == PLUS
)
270 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0))
271 || GET_CODE (XEXP (addr
, 0)) == MEM
)
275 if (GET_CODE (offset
) == CONST_INT
)
276 offset
= plus_constant (XEXP (addr
, 0), INTVAL (offset
));
277 else if (GET_CODE (XEXP (addr
, 0)) == CONST_INT
)
278 offset
= plus_constant (offset
, INTVAL (XEXP (addr
, 0)));
282 offset
= XEXP (addr
, 0);
284 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
287 ireg
= reg1
, breg
= XEXP (addr
, 0), reg1
= 0;
289 reg1
= XEXP (addr
, 0);
291 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
295 ireg
= XEXP (addr
, 0);
300 if (CONSTANT_ADDRESS_P (XEXP (addr
, 1))
301 || GET_CODE (XEXP (addr
, 1)) == MEM
)
305 if (GET_CODE (offset
) == CONST_INT
)
306 offset
= plus_constant (XEXP (addr
, 1), INTVAL (offset
));
307 else if (GET_CODE (XEXP (addr
, 1)) == CONST_INT
)
308 offset
= plus_constant (offset
, INTVAL (XEXP (addr
, 1)));
312 offset
= XEXP (addr
, 1);
314 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
317 ireg
= reg1
, breg
= XEXP (addr
, 1), reg1
= 0;
319 reg1
= XEXP (addr
, 1);
321 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
325 ireg
= XEXP (addr
, 1);
333 /* If REG1 is nonzero, figure out if it is a base or index register. */
336 if (breg
!= 0 || (offset
&& GET_CODE (offset
) == MEM
))
347 output_address (offset
);
350 fprintf (file
, "(%s)", reg_names
[REGNO (breg
)]);
354 if (GET_CODE (ireg
) == MULT
)
355 ireg
= XEXP (ireg
, 0);
356 if (GET_CODE (ireg
) != REG
)
358 fprintf (file
, "[%s]", reg_names
[REGNO (ireg
)]);
363 output_addr_const (file
, addr
);
371 switch (GET_CODE (op
))
403 register enum machine_mode mode
;
404 REAL_VALUE_TYPE r
, s
;
407 if (GET_CODE (c
) != CONST_DOUBLE
)
412 if (c
== const_tiny_rtx
[(int) mode
][0]
413 || c
== const_tiny_rtx
[(int) mode
][1]
414 || c
== const_tiny_rtx
[(int) mode
][2])
417 REAL_VALUE_FROM_CONST_DOUBLE (r
, c
);
419 for (i
= 0; i
< 7; i
++)
422 REAL_VALUE_FROM_INT (s
, x
, 0, mode
);
424 if (REAL_VALUES_EQUAL (r
, s
))
426 if (!exact_real_inverse (mode
, &s
))
428 if (REAL_VALUES_EQUAL (r
, s
))
435 /* Return the cost in cycles of a memory address, relative to register
438 Each of the following adds the indicated number of cycles:
442 1 - indexing and/or offset(register)
447 vax_address_cost (addr
)
450 int reg
= 0, indexed
= 0, indir
= 0, offset
= 0, predec
= 0;
451 rtx plus_op0
= 0, plus_op1
= 0;
453 switch (GET_CODE (addr
))
463 indexed
= 1; /* 2 on VAX 2 */
466 /* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */
468 offset
= (unsigned)(INTVAL(addr
)+128) > 256;
472 offset
= 1; /* 2 on VAX 2 */
474 case LABEL_REF
: /* this is probably a byte offset from the pc */
480 plus_op1
= XEXP (addr
, 0);
482 plus_op0
= XEXP (addr
, 0);
483 addr
= XEXP (addr
, 1);
486 indir
= 2; /* 3 on VAX 2 */
487 addr
= XEXP (addr
, 0);
493 /* Up to 3 things can be added in an address. They are stored in
494 plus_op0, plus_op1, and addr. */
508 /* Indexing and register+offset can both be used (except on a VAX 2)
509 without increasing execution time over either one alone. */
510 if (reg
&& indexed
&& offset
)
511 return reg
+ indir
+ offset
+ predec
;
512 return reg
+ indexed
+ indir
+ offset
+ predec
;
516 /* Cost of an expression on a VAX. This version has costs tuned for the
517 CVAX chip (found in the VAX 3 series) with comments for variations on
524 register enum rtx_code code
= GET_CODE (x
);
525 enum machine_mode mode
= GET_MODE (x
);
527 int i
= 0; /* may be modified in switch */
528 const char *fmt
= GET_RTX_FORMAT (code
); /* may be modified in switch */
540 c
= 16; /* 4 on VAX 9000 */
543 c
= 9; /* 4 on VAX 9000, 12 on VAX 2 */
546 c
= 16; /* 6 on VAX 9000, 28 on VAX 2 */
551 c
= 10; /* 3-4 on VAX 9000, 20-28 on VAX 2 */
554 return MAX_COST
; /* Mode is not supported. */
559 return MAX_COST
; /* Mode is not supported. */
564 c
= 30; /* highly variable */
565 else if (mode
== DFmode
)
566 /* divide takes 28 cycles if the result is not zero, 13 otherwise */
569 c
= 11; /* 25 on VAX 2 */
576 return MAX_COST
; /* Mode is not supported. */
580 c
= 6 + (mode
== DFmode
) + (GET_MODE (XEXP (x
, 0)) != SImode
);
584 c
= 7; /* 17 on VAX 2 */
592 c
= 10; /* 6 on VAX 9000 */
596 c
= 6; /* 5 on VAX 2, 4 on VAX 9000 */
597 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
598 fmt
= "e"; /* all constant rotate counts are short */
601 /* Check for small negative integer operand: subl2 can be used with
602 a short positive constant instead. */
603 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
604 if ((unsigned)(INTVAL (XEXP (x
, 1)) + 63) < 127)
607 c
= (mode
== DFmode
) ? 13 : 8; /* 6/8 on VAX 9000, 16/15 on VAX 2 */
613 /* AND is special because the first operand is complemented. */
615 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
617 if ((unsigned)~INTVAL (XEXP (x
, 0)) > 63)
626 else if (mode
== SFmode
)
628 else if (mode
== DImode
)
637 if (mode
== DImode
|| mode
== DFmode
)
638 c
= 5; /* 7 on VAX 2 */
640 c
= 3; /* 4 on VAX 2 */
642 if (GET_CODE (x
) == REG
|| GET_CODE (x
) == POST_INC
)
644 return c
+ vax_address_cost (x
);
651 /* Now look inside the expression. Operands which are not registers or
652 short constants add to the cost.
654 FMT and I may have been adjusted in the switch above for instructions
655 which require special handling */
657 while (*fmt
++ == 'e')
659 register rtx op
= XEXP (x
, i
++);
660 code
= GET_CODE (op
);
662 /* A NOT is likely to be found as the first operand of an AND
663 (in which case the relevant cost is of the operand inside
664 the not) and not likely to be found anywhere else. */
666 op
= XEXP (op
, 0), code
= GET_CODE (op
);
671 if ((unsigned)INTVAL (op
) > 63 && GET_MODE (x
) != QImode
)
672 c
+= 1; /* 2 on VAX 2 */
677 c
+= 1; /* 2 on VAX 2 */
680 if (GET_MODE_CLASS (GET_MODE (op
)) == MODE_FLOAT
)
682 /* Registers are faster than floating point constants -- even
683 those constants which can be encoded in a single byte. */
684 if (vax_float_literal (op
))
687 c
+= (GET_MODE (x
) == DFmode
) ? 3 : 2;
691 if (CONST_DOUBLE_HIGH (op
) != 0
692 || (unsigned)CONST_DOUBLE_LOW (op
) > 63)
697 c
+= 1; /* 2 on VAX 2 */
698 if (GET_CODE (XEXP (op
, 0)) != REG
)
699 c
+= vax_address_cost (XEXP (op
, 0));
713 /* Additional support code for VMS target. */
715 /* Linked list of all externals that are to be emitted when optimizing
716 for the global pointer if they haven't been declared by the end of
717 the program with an appropriate .comm or initialization. */
721 struct extern_list
*next
; /* next external */
722 const char *name
; /* name of the external */
723 int size
; /* external's actual size */
724 int in_const
; /* section type flag */
725 } *extern_head
= 0, *pending_head
= 0;
727 /* Check whether NAME is already on the external definition list. If not,
728 add it to either that list or the pending definition list. */
731 vms_check_external (decl
, name
, pending
)
736 register struct extern_list
*p
, *p0
;
738 for (p
= extern_head
; p
; p
= p
->next
)
739 if (!strcmp (p
->name
, name
))
742 for (p
= pending_head
, p0
= 0; p
; p0
= p
, p
= p
->next
)
743 if (!strcmp (p
->name
, name
))
748 /* Was pending, but has now been defined; move it to other list. */
749 if (p
== pending_head
)
750 pending_head
= p
->next
;
753 p
->next
= extern_head
;
758 /* Not previously seen; create a new list entry. */
759 p
= (struct extern_list
*) xmalloc (sizeof (struct extern_list
));
764 /* Save the size and section type and link to `pending' list. */
765 p
->size
= (DECL_SIZE (decl
) == 0) ? 0 :
766 TREE_INT_CST_LOW (size_binop (CEIL_DIV_EXPR
, DECL_SIZE (decl
),
767 size_int (BITS_PER_UNIT
)));
768 p
->in_const
= (TREE_READONLY (decl
) && ! TREE_THIS_VOLATILE (decl
));
770 p
->next
= pending_head
;
775 /* Size and section type don't matter; link to `declared' list. */
776 p
->size
= p
->in_const
= 0; /* arbitrary init */
778 p
->next
= extern_head
;
785 vms_flush_pending_externals (file
)
788 register struct extern_list
*p
;
792 /* Move next pending declaration to the "done" list. */
794 pending_head
= p
->next
;
795 p
->next
= extern_head
;
798 /* Now output the actual declaration. */
803 fputs (".comm ", file
);
804 assemble_name (file
, p
->name
);
805 fprintf (file
, ",%d\n", p
->size
);
810 vms_asm_out_constructor (symbol
, priority
)
812 int priority ATTRIBUTE_UNUSED
;
814 fprintf (asm_out_file
,".globl $$PsectAttributes_NOOVR$$__gxx_init_1\n");
816 fprintf (asm_out_file
,"$$PsectAttributes_NOOVR$$__gxx_init_1:\n\t.long\t");
817 assemble_name (asm_out_file
, XSTR (symbol
, 0));
818 fputc ('\n', asm_out_file
);
822 vms_asm_out_destructor (symbol
, priority
)
824 int priority ATTRIBUTE_UNUSED
;
826 fprintf (asm_out_file
,".globl $$PsectAttributes_NOOVR$$__gxx_clean_1\n");
828 fprintf (asm_out_file
,"$$PsectAttributes_NOOVR$$__gxx_clean_1:\n\t.long\t");
829 assemble_name (asm_out_file
, XSTR (symbol
, 0));
830 fputc ('\n', asm_out_file
);
834 vms_select_section (exp
, reloc
, align
)
836 int reloc ATTRIBUTE_UNUSED
;
837 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED
;
839 if (TREE_CODE (exp
) == VAR_DECL
)
841 if (TREE_READONLY (exp
) && ! TREE_THIS_VOLATILE (exp
)
842 && DECL_INITIAL (exp
)
843 && (DECL_INITIAL (exp
) == error_mark_node
844 || TREE_CONSTANT (DECL_INITIAL (exp
))))
846 if (TREE_PUBLIC (exp
))
854 if (TREE_CODE_CLASS (TREE_CODE (exp
)) == 'c')
856 if (TREE_CODE (exp
) == STRING_CST
&& flag_writable_strings
)
863 /* Make sure that external variables are correctly addressed. Under VMS
864 there is some brain damage in the linker that requires us to do this. */
867 vms_encode_section_info (decl
, first
)
869 int first ATTRIBUTE_UNUSED
;
871 if (DECL_EXTERNAL (decl
) && TREE_PUBLIC (decl
))
872 SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl
), 0)) = 1;
875 /* This is how to output a command to make the user-level label named NAME
876 defined for reference from other files. */
878 vms_globalize_label (stream
, name
)
882 default_globalize_label (stream
, name
);
883 vms_check_external (NULL_TREE
, name
, 0);
885 #endif /* VMS_TARGET */
887 /* Additional support code for VMS host. */
888 /* ??? This should really be in libiberty; vax.c is a target file. */
889 #ifdef QSORT_WORKAROUND
891 Do not use VAXCRTL's qsort() due to a severe bug: once you've
892 sorted something which has a size that's an exact multiple of 4
893 and is longword aligned, you cannot safely sort anything which
894 is either not a multiple of 4 in size or not longword aligned.
895 A static "move-by-longword" optimization flag inside qsort() is
896 never reset. This is known to affect VMS V4.6 through VMS V5.5-1,
897 and was finally fixed in VMS V5.5-2.
899 In this work-around an insertion sort is used for simplicity.
900 The qsort code from glibc should probably be used instead.
903 not_qsort (array
, count
, size
, compare
)
905 unsigned count
, size
;
909 if (size
== sizeof (short))
912 register short *next
, *prev
;
913 short tmp
, *base
= array
;
915 for (next
= base
, i
= count
- 1; i
> 0; i
--)
918 if ((*compare
)(next
, prev
) < 0)
921 do *(prev
+ 1) = *prev
;
922 while (--prev
>= base
? (*compare
)(&tmp
, prev
) < 0 : 0);
927 else if (size
== sizeof (long))
930 register long *next
, *prev
;
931 long tmp
, *base
= array
;
933 for (next
= base
, i
= count
- 1; i
> 0; i
--)
936 if ((*compare
)(next
, prev
) < 0)
939 do *(prev
+ 1) = *prev
;
940 while (--prev
>= base
? (*compare
)(&tmp
, prev
) < 0 : 0);
945 else /* arbitrary size */
948 register char *next
, *prev
, *tmp
= alloca (size
), *base
= array
;
950 for (next
= base
, i
= count
- 1; i
> 0; i
--)
951 { /* count-1 forward iterations */
952 prev
= next
, next
+= size
; /* increment front pointer */
953 if ((*compare
)(next
, prev
) < 0)
954 { /* found element out of order; move others up then re-insert */
955 memcpy (tmp
, next
, size
); /* save smaller element */
956 do { memcpy (prev
+ size
, prev
, size
); /* move larger elem. up */
957 prev
-= size
; /* decrement back pointer */
958 } while (prev
>= base
? (*compare
)(tmp
, prev
) < 0 : 0);
959 memcpy (prev
+ size
, tmp
, size
); /* restore small element */
969 #endif /* QSORT_WORKAROUND */
971 /* Return 1 if insn A follows B. */
979 for (p
= a
; p
!= b
; p
= NEXT_INSN (p
))
986 /* Returns 1 if we know operand OP was 0 before INSN. */
989 reg_was_0_p (insn
, op
)
994 return ((link
= find_reg_note (insn
, REG_WAS_0
, 0))
995 /* Make sure the insn that stored the 0 is still present
996 and doesn't follow INSN in the insn sequence. */
997 && ! INSN_DELETED_P (XEXP (link
, 0))
998 && GET_CODE (XEXP (link
, 0)) != NOTE
999 && ! follows_p (XEXP (link
, 0), insn
)
1000 /* Make sure cross jumping didn't happen here. */
1001 && no_labels_between_p (XEXP (link
, 0), insn
)
1002 /* Make sure the reg hasn't been clobbered. */
1003 && ! reg_set_between_p (op
, XEXP (link
, 0), insn
));