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_FUNCTION_PROLOGUE
49 #define TARGET_ASM_FUNCTION_PROLOGUE vax_output_function_prologue
51 struct gcc_target targetm
= TARGET_INITIALIZER
;
53 /* Generate the assembly code for function entry. FILE is a stdio
54 stream to output the code to. SIZE is an int: how many units of
55 temporary storage to allocate.
57 Refer to the array `regs_ever_live' to determine which registers to
58 save; `regs_ever_live[I]' is nonzero if register number I is ever
59 used in the function. This function is responsible for knowing
60 which registers should not be saved even if used. */
63 vax_output_function_prologue (file
, size
)
68 register int mask
= 0;
69 extern char call_used_regs
[];
71 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
72 if (regs_ever_live
[regno
] && !call_used_regs
[regno
])
75 fprintf (file
, "\t.word 0x%x\n", mask
);
80 * This works for both gcc and g++. It first checks to see if
81 * the current routine is "main", which will only happen for
82 * GCC, and add the jsb if it is. If is not the case then try
83 * and see if __MAIN_NAME is part of current_function_name,
84 * which will only happen if we are running g++, and add the jsb
85 * if it is. In gcc there should never be a paren in the
86 * function name, and in g++ there is always a "(" in the
87 * function name, thus there should never be any confusion.
89 * Adjusting the stack pointer by 4 before calling C$MAIN_ARGS
90 * is required when linking with the VMS POSIX version of the C
91 * run-time library; using `subl2 $4,r0' is adequate but we use
92 * `clrl -(sp)' instead. The extra 4 bytes could be removed
93 * after the call because STARTING_FRAME_OFFSET's setting of -4
94 * will end up adding them right back again, but don't bother.
97 const char *p
= current_function_name
;
98 int is_main
= strcmp ("main", p
) == 0;
99 # define __MAIN_NAME " main("
101 while (!is_main
&& *p
!= '\0')
103 if (*p
== *__MAIN_NAME
104 && strncmp (p
, __MAIN_NAME
, sizeof __MAIN_NAME
- sizeof "") == 0)
111 fprintf (file
, "\t%s\n\t%s\n", "clrl -(sp)", "jsb _C$MAIN_ARGS");
114 size
-= STARTING_FRAME_OFFSET
;
116 fprintf (file
, "\tmovab %d(sp),sp\n", -size
);
118 fprintf (file
, "\tsubl2 $%d,sp\n", size
);
121 /* This is like nonimmediate_operand with a restriction on the type of MEM. */
124 split_quadword_operands (operands
, low
, n
)
126 int n ATTRIBUTE_UNUSED
;
129 /* Split operands. */
131 low
[0] = low
[1] = low
[2] = 0;
132 for (i
= 0; i
< 3; i
++)
135 /* it's already been figured out */;
136 else if (GET_CODE (operands
[i
]) == MEM
137 && (GET_CODE (XEXP (operands
[i
], 0)) == POST_INC
))
139 rtx addr
= XEXP (operands
[i
], 0);
140 operands
[i
] = low
[i
] = gen_rtx_MEM (SImode
, addr
);
141 if (which_alternative
== 0 && i
== 0)
143 addr
= XEXP (operands
[i
], 0);
144 operands
[i
+1] = low
[i
+1] = gen_rtx_MEM (SImode
, addr
);
149 low
[i
] = operand_subword (operands
[i
], 0, 0, DImode
);
150 operands
[i
] = operand_subword (operands
[i
], 1, 0, DImode
);
156 print_operand_address (file
, addr
)
160 register rtx reg1
, breg
, ireg
;
164 switch (GET_CODE (addr
))
168 addr
= XEXP (addr
, 0);
172 fprintf (file
, "(%s)", reg_names
[REGNO (addr
)]);
176 fprintf (file
, "-(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
180 fprintf (file
, "(%s)+", reg_names
[REGNO (XEXP (addr
, 0))]);
184 /* There can be either two or three things added here. One must be a
185 REG. One can be either a REG or a MULT of a REG and an appropriate
186 constant, and the third can only be a constant or a MEM.
188 We get these two or three things and put the constant or MEM in
189 OFFSET, the MULT or REG in IREG, and the REG in BREG. If we have
190 a register and can't tell yet if it is a base or index register,
193 reg1
= 0; ireg
= 0; breg
= 0; offset
= 0;
195 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0))
196 || GET_CODE (XEXP (addr
, 0)) == MEM
)
198 offset
= XEXP (addr
, 0);
199 addr
= XEXP (addr
, 1);
201 else if (CONSTANT_ADDRESS_P (XEXP (addr
, 1))
202 || GET_CODE (XEXP (addr
, 1)) == MEM
)
204 offset
= XEXP (addr
, 1);
205 addr
= XEXP (addr
, 0);
207 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
209 ireg
= XEXP (addr
, 1);
210 addr
= XEXP (addr
, 0);
212 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
214 ireg
= XEXP (addr
, 0);
215 addr
= XEXP (addr
, 1);
217 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
219 reg1
= XEXP (addr
, 1);
220 addr
= XEXP (addr
, 0);
222 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
224 reg1
= XEXP (addr
, 0);
225 addr
= XEXP (addr
, 1);
230 if (GET_CODE (addr
) == REG
)
237 else if (GET_CODE (addr
) == MULT
)
239 else if (GET_CODE (addr
) == PLUS
)
241 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0))
242 || GET_CODE (XEXP (addr
, 0)) == MEM
)
246 if (GET_CODE (offset
) == CONST_INT
)
247 offset
= plus_constant (XEXP (addr
, 0), INTVAL (offset
));
248 else if (GET_CODE (XEXP (addr
, 0)) == CONST_INT
)
249 offset
= plus_constant (offset
, INTVAL (XEXP (addr
, 0)));
253 offset
= XEXP (addr
, 0);
255 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
258 ireg
= reg1
, breg
= XEXP (addr
, 0), reg1
= 0;
260 reg1
= XEXP (addr
, 0);
262 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
266 ireg
= XEXP (addr
, 0);
271 if (CONSTANT_ADDRESS_P (XEXP (addr
, 1))
272 || GET_CODE (XEXP (addr
, 1)) == MEM
)
276 if (GET_CODE (offset
) == CONST_INT
)
277 offset
= plus_constant (XEXP (addr
, 1), INTVAL (offset
));
278 else if (GET_CODE (XEXP (addr
, 1)) == CONST_INT
)
279 offset
= plus_constant (offset
, INTVAL (XEXP (addr
, 1)));
283 offset
= XEXP (addr
, 1);
285 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
288 ireg
= reg1
, breg
= XEXP (addr
, 1), reg1
= 0;
290 reg1
= XEXP (addr
, 1);
292 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
296 ireg
= XEXP (addr
, 1);
304 /* If REG1 is non-zero, figure out if it is a base or index register. */
307 if (breg
!= 0 || (offset
&& GET_CODE (offset
) == MEM
))
318 output_address (offset
);
321 fprintf (file
, "(%s)", reg_names
[REGNO (breg
)]);
325 if (GET_CODE (ireg
) == MULT
)
326 ireg
= XEXP (ireg
, 0);
327 if (GET_CODE (ireg
) != REG
)
329 fprintf (file
, "[%s]", reg_names
[REGNO (ireg
)]);
334 output_addr_const (file
, addr
);
342 switch (GET_CODE (op
))
374 register enum machine_mode mode
;
375 #if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
377 union {double d
; int i
[2];} val
;
380 if (GET_CODE (c
) != CONST_DOUBLE
)
385 if (c
== const_tiny_rtx
[(int) mode
][0]
386 || c
== const_tiny_rtx
[(int) mode
][1]
387 || c
== const_tiny_rtx
[(int) mode
][2])
390 #if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
392 val
.i
[0] = CONST_DOUBLE_LOW (c
);
393 val
.i
[1] = CONST_DOUBLE_HIGH (c
);
395 for (i
= 0; i
< 7; i
++)
396 if (val
.d
== 1 << i
|| val
.d
== 1 / (1 << i
))
403 /* Return the cost in cycles of a memory address, relative to register
406 Each of the following adds the indicated number of cycles:
410 1 - indexing and/or offset(register)
415 vax_address_cost (addr
)
418 int reg
= 0, indexed
= 0, indir
= 0, offset
= 0, predec
= 0;
419 rtx plus_op0
= 0, plus_op1
= 0;
421 switch (GET_CODE (addr
))
431 indexed
= 1; /* 2 on VAX 2 */
434 /* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */
436 offset
= (unsigned)(INTVAL(addr
)+128) > 256;
440 offset
= 1; /* 2 on VAX 2 */
442 case LABEL_REF
: /* this is probably a byte offset from the pc */
448 plus_op1
= XEXP (addr
, 0);
450 plus_op0
= XEXP (addr
, 0);
451 addr
= XEXP (addr
, 1);
454 indir
= 2; /* 3 on VAX 2 */
455 addr
= XEXP (addr
, 0);
461 /* Up to 3 things can be added in an address. They are stored in
462 plus_op0, plus_op1, and addr. */
476 /* Indexing and register+offset can both be used (except on a VAX 2)
477 without increasing execution time over either one alone. */
478 if (reg
&& indexed
&& offset
)
479 return reg
+ indir
+ offset
+ predec
;
480 return reg
+ indexed
+ indir
+ offset
+ predec
;
484 /* Cost of an expression on a VAX. This version has costs tuned for the
485 CVAX chip (found in the VAX 3 series) with comments for variations on
492 register enum rtx_code code
= GET_CODE (x
);
493 enum machine_mode mode
= GET_MODE (x
);
495 int i
= 0; /* may be modified in switch */
496 const char *fmt
= GET_RTX_FORMAT (code
); /* may be modified in switch */
508 c
= 16; /* 4 on VAX 9000 */
511 c
= 9; /* 4 on VAX 9000, 12 on VAX 2 */
514 c
= 16; /* 6 on VAX 9000, 28 on VAX 2 */
519 c
= 10; /* 3-4 on VAX 9000, 20-28 on VAX 2 */
530 c
= 30; /* highly variable */
531 else if (mode
== DFmode
)
532 /* divide takes 28 cycles if the result is not zero, 13 otherwise */
535 c
= 11; /* 25 on VAX 2 */
544 c
= 6 + (mode
== DFmode
) + (GET_MODE (XEXP (x
, 0)) != SImode
);
548 c
= 7; /* 17 on VAX 2 */
556 c
= 10; /* 6 on VAX 9000 */
560 c
= 6; /* 5 on VAX 2, 4 on VAX 9000 */
561 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
562 fmt
= "e"; /* all constant rotate counts are short */
565 /* Check for small negative integer operand: subl2 can be used with
566 a short positive constant instead. */
567 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
568 if ((unsigned)(INTVAL (XEXP (x
, 1)) + 63) < 127)
571 c
= (mode
== DFmode
) ? 13 : 8; /* 6/8 on VAX 9000, 16/15 on VAX 2 */
577 /* AND is special because the first operand is complemented. */
579 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
581 if ((unsigned)~INTVAL (XEXP (x
, 0)) > 63)
590 else if (mode
== SFmode
)
592 else if (mode
== DImode
)
601 if (mode
== DImode
|| mode
== DFmode
)
602 c
= 5; /* 7 on VAX 2 */
604 c
= 3; /* 4 on VAX 2 */
606 if (GET_CODE (x
) == REG
|| GET_CODE (x
) == POST_INC
)
608 return c
+ vax_address_cost (x
);
615 /* Now look inside the expression. Operands which are not registers or
616 short constants add to the cost.
618 FMT and I may have been adjusted in the switch above for instructions
619 which require special handling */
621 while (*fmt
++ == 'e')
623 register rtx op
= XEXP (x
, i
++);
624 code
= GET_CODE (op
);
626 /* A NOT is likely to be found as the first operand of an AND
627 (in which case the relevant cost is of the operand inside
628 the not) and not likely to be found anywhere else. */
630 op
= XEXP (op
, 0), code
= GET_CODE (op
);
635 if ((unsigned)INTVAL (op
) > 63 && GET_MODE (x
) != QImode
)
636 c
+= 1; /* 2 on VAX 2 */
641 c
+= 1; /* 2 on VAX 2 */
644 if (GET_MODE_CLASS (GET_MODE (op
)) == MODE_FLOAT
)
646 /* Registers are faster than floating point constants -- even
647 those constants which can be encoded in a single byte. */
648 if (vax_float_literal (op
))
651 c
+= (GET_MODE (x
) == DFmode
) ? 3 : 2;
655 if (CONST_DOUBLE_HIGH (op
) != 0
656 || (unsigned)CONST_DOUBLE_LOW (op
) > 63)
661 c
+= 1; /* 2 on VAX 2 */
662 if (GET_CODE (XEXP (op
, 0)) != REG
)
663 c
+= vax_address_cost (XEXP (op
, 0));
676 /* Check a `double' value for validity for a particular machine mode. */
678 static const char *const float_strings
[] =
680 "1.70141173319264430e+38", /* 2^127 (2^24 - 1) / 2^24 */
681 "-1.70141173319264430e+38",
682 "2.93873587705571877e-39", /* 2^-128 */
683 "-2.93873587705571877e-39"
686 static REAL_VALUE_TYPE float_values
[4];
688 static int inited_float_values
= 0;
692 check_float_value (mode
, d
, overflow
)
693 enum machine_mode mode
;
697 if (inited_float_values
== 0)
700 for (i
= 0; i
< 4; i
++)
702 float_values
[i
] = REAL_VALUE_ATOF (float_strings
[i
], DFmode
);
705 inited_float_values
= 1;
710 memcpy (d
, &float_values
[0], sizeof (REAL_VALUE_TYPE
));
714 if ((mode
) == SFmode
)
717 memcpy (&r
, d
, sizeof (REAL_VALUE_TYPE
));
718 if (REAL_VALUES_LESS (float_values
[0], r
))
720 memcpy (d
, &float_values
[0], sizeof (REAL_VALUE_TYPE
));
723 else if (REAL_VALUES_LESS (r
, float_values
[1]))
725 memcpy (d
, &float_values
[1], sizeof (REAL_VALUE_TYPE
));
728 else if (REAL_VALUES_LESS (dconst0
, r
)
729 && REAL_VALUES_LESS (r
, float_values
[2]))
731 memcpy (d
, &dconst0
, sizeof (REAL_VALUE_TYPE
));
734 else if (REAL_VALUES_LESS (r
, dconst0
)
735 && REAL_VALUES_LESS (float_values
[3], r
))
737 memcpy (d
, &dconst0
, sizeof (REAL_VALUE_TYPE
));
746 /* Additional support code for VMS target. */
748 /* Linked list of all externals that are to be emitted when optimizing
749 for the global pointer if they haven't been declared by the end of
750 the program with an appropriate .comm or initialization. */
754 struct extern_list
*next
; /* next external */
755 const char *name
; /* name of the external */
756 int size
; /* external's actual size */
757 int in_const
; /* section type flag */
758 } *extern_head
= 0, *pending_head
= 0;
760 /* Check whether NAME is already on the external definition list. If not,
761 add it to either that list or the pending definition list. */
764 vms_check_external (decl
, name
, pending
)
769 register struct extern_list
*p
, *p0
;
771 for (p
= extern_head
; p
; p
= p
->next
)
772 if (!strcmp (p
->name
, name
))
775 for (p
= pending_head
, p0
= 0; p
; p0
= p
, p
= p
->next
)
776 if (!strcmp (p
->name
, name
))
781 /* Was pending, but has now been defined; move it to other list. */
782 if (p
== pending_head
)
783 pending_head
= p
->next
;
786 p
->next
= extern_head
;
791 /* Not previously seen; create a new list entry. */
792 p
= (struct extern_list
*)permalloc ((long) sizeof (struct extern_list
));
797 /* Save the size and section type and link to `pending' list. */
798 p
->size
= (DECL_SIZE (decl
) == 0) ? 0 :
799 TREE_INT_CST_LOW (size_binop (CEIL_DIV_EXPR
, DECL_SIZE (decl
),
800 size_int (BITS_PER_UNIT
)));
801 p
->in_const
= (TREE_READONLY (decl
) && ! TREE_THIS_VOLATILE (decl
));
803 p
->next
= pending_head
;
808 /* Size and section type don't matter; link to `declared' list. */
809 p
->size
= p
->in_const
= 0; /* arbitrary init */
811 p
->next
= extern_head
;
818 vms_flush_pending_externals (file
)
821 register struct extern_list
*p
;
825 /* Move next pending declaration to the "done" list. */
827 pending_head
= p
->next
;
828 p
->next
= extern_head
;
831 /* Now output the actual declaration. */
836 fputs (".comm ", file
);
837 assemble_name (file
, p
->name
);
838 fprintf (file
, ",%d\n", p
->size
);
843 vms_asm_out_constructor (symbol
, priority
)
845 int priority ATTRIBUTE_UNUSED
;
847 fprintf (asm_out_file
,".globl $$PsectAttributes_NOOVR$$__gxx_init_1\n");
849 fprintf (asm_out_file
,"$$PsectAttributes_NOOVR$$__gxx_init_1:\n\t.long\t");
850 assemble_name (asm_out_file
, XSTR (symbol
, 0));
851 fputc ('\n', asm_out_file
);
855 vms_asm_out_destructor (symbol
, priority
)
857 int priority ATTRIBUTE_UNUSED
;
859 fprintf (asm_out_file
,".globl $$PsectAttributes_NOOVR$$__gxx_clean_1\n");
861 fprintf (asm_out_file
,"$$PsectAttributes_NOOVR$$__gxx_clean_1:\n\t.long\t");
862 assemble_name (asm_out_file
, XSTR (symbol
, 0));
863 fputc ('\n', asm_out_file
);
865 #endif /* VMS_TARGET */
867 /* Additional support code for VMS host. */
868 /* ??? This should really be in libiberty; vax.c is a target file. */
869 #ifdef QSORT_WORKAROUND
871 Do not use VAXCRTL's qsort() due to a severe bug: once you've
872 sorted something which has a size that's an exact multiple of 4
873 and is longword aligned, you cannot safely sort anything which
874 is either not a multiple of 4 in size or not longword aligned.
875 A static "move-by-longword" optimization flag inside qsort() is
876 never reset. This is known to affect VMS V4.6 through VMS V5.5-1,
877 and was finally fixed in VMS V5.5-2.
879 In this work-around an insertion sort is used for simplicity.
880 The qsort code from glibc should probably be used instead.
883 not_qsort (array
, count
, size
, compare
)
885 unsigned count
, size
;
889 if (size
== sizeof (short))
892 register short *next
, *prev
;
893 short tmp
, *base
= array
;
895 for (next
= base
, i
= count
- 1; i
> 0; i
--)
898 if ((*compare
)(next
, prev
) < 0)
901 do *(prev
+ 1) = *prev
;
902 while (--prev
>= base
? (*compare
)(&tmp
, prev
) < 0 : 0);
907 else if (size
== sizeof (long))
910 register long *next
, *prev
;
911 long tmp
, *base
= array
;
913 for (next
= base
, i
= count
- 1; i
> 0; i
--)
916 if ((*compare
)(next
, prev
) < 0)
919 do *(prev
+ 1) = *prev
;
920 while (--prev
>= base
? (*compare
)(&tmp
, prev
) < 0 : 0);
925 else /* arbitrary size */
928 register char *next
, *prev
, *tmp
= alloca (size
), *base
= array
;
930 for (next
= base
, i
= count
- 1; i
> 0; i
--)
931 { /* count-1 forward iterations */
932 prev
= next
, next
+= size
; /* increment front pointer */
933 if ((*compare
)(next
, prev
) < 0)
934 { /* found element out of order; move others up then re-insert */
935 memcpy (tmp
, next
, size
); /* save smaller element */
936 do { memcpy (prev
+ size
, prev
, size
); /* move larger elem. up */
937 prev
-= size
; /* decrement back pointer */
938 } while (prev
>= base
? (*compare
)(tmp
, prev
) < 0 : 0);
939 memcpy (prev
+ size
, tmp
, size
); /* restore small element */
949 #endif /* QSORT_WORKAROUND */
951 /* Return 1 if insn A follows B. */
959 for (p
= a
; p
!= b
; p
= NEXT_INSN (p
))
966 /* Returns 1 if we know operand OP was 0 before INSN. */
969 reg_was_0_p (insn
, op
)
974 return ((link
= find_reg_note (insn
, REG_WAS_0
, 0))
975 /* Make sure the insn that stored the 0 is still present
976 and doesn't follow INSN in the insn sequence. */
977 && ! INSN_DELETED_P (XEXP (link
, 0))
978 && GET_CODE (XEXP (link
, 0)) != NOTE
979 && ! follows_p (XEXP (link
, 0), insn
)
980 /* Make sure cross jumping didn't happen here. */
981 && no_labels_between_p (XEXP (link
, 0), insn
)
982 /* Make sure the reg hasn't been clobbered. */
983 && ! reg_set_between_p (op
, XEXP (link
, 0), insn
));