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. */
24 #include "coretypes.h"
29 #include "hard-reg-set.h"
31 #include "insn-config.h"
32 #include "conditions.h"
35 #include "insn-attr.h"
42 #include "target-def.h"
44 static int follows_p
PARAMS ((rtx
, rtx
));
45 static void vax_output_function_prologue
PARAMS ((FILE *, HOST_WIDE_INT
));
46 static void vax_output_mi_thunk
PARAMS ((FILE *, tree
, HOST_WIDE_INT
,
47 HOST_WIDE_INT
, tree
));
48 static int vax_address_cost_1
PARAMS ((rtx
));
49 static int vax_address_cost
PARAMS ((rtx
));
50 static int vax_rtx_costs_1
PARAMS ((rtx
, enum rtx_code
, enum rtx_code
));
51 static bool vax_rtx_costs
PARAMS ((rtx
, int, int, int *));
53 /* Initialize the GCC target structure. */
54 #undef TARGET_ASM_ALIGNED_HI_OP
55 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
57 #undef TARGET_ASM_FUNCTION_PROLOGUE
58 #define TARGET_ASM_FUNCTION_PROLOGUE vax_output_function_prologue
60 #undef TARGET_ASM_OUTPUT_MI_THUNK
61 #define TARGET_ASM_OUTPUT_MI_THUNK vax_output_mi_thunk
62 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
63 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
65 #undef TARGET_RTX_COSTS
66 #define TARGET_RTX_COSTS vax_rtx_costs
67 #undef TARGET_ADDRESS_COST
68 #define TARGET_ADDRESS_COST vax_address_cost
70 struct gcc_target targetm
= TARGET_INITIALIZER
;
72 /* Set global variables as needed for the options enabled. */
77 /* We're VAX floating point, not IEEE floating point. */
78 memset (real_format_for_mode
, 0, sizeof real_format_for_mode
);
79 real_format_for_mode
[SFmode
- QFmode
] = &vax_f_format
;
80 real_format_for_mode
[DFmode
- QFmode
]
81 = (TARGET_G_FLOAT
? &vax_g_format
: &vax_d_format
);
84 /* Generate the assembly code for function entry. FILE is a stdio
85 stream to output the code to. SIZE is an int: how many units of
86 temporary storage to allocate.
88 Refer to the array `regs_ever_live' to determine which registers to
89 save; `regs_ever_live[I]' is nonzero if register number I is ever
90 used in the function. This function is responsible for knowing
91 which registers should not be saved even if used. */
94 vax_output_function_prologue (file
, size
)
99 register int mask
= 0;
101 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
102 if (regs_ever_live
[regno
] && !call_used_regs
[regno
])
105 fprintf (file
, "\t.word 0x%x\n", mask
);
107 if (dwarf2out_do_frame ())
109 const char *label
= dwarf2out_cfi_label ();
112 for (regno
= FIRST_PSEUDO_REGISTER
-1; regno
>= 0; --regno
)
113 if (regs_ever_live
[regno
] && !call_used_regs
[regno
])
114 dwarf2out_reg_save (label
, regno
, offset
-= 4);
116 dwarf2out_reg_save (label
, PC_REGNUM
, offset
-= 4);
117 dwarf2out_reg_save (label
, FRAME_POINTER_REGNUM
, offset
-= 4);
118 dwarf2out_reg_save (label
, ARG_POINTER_REGNUM
, offset
-= 4);
119 dwarf2out_def_cfa (label
, FRAME_POINTER_REGNUM
, -(offset
- 4));
122 size
-= STARTING_FRAME_OFFSET
;
124 asm_fprintf (file
, "\tmovab %d(%Rsp),%Rsp\n", -size
);
126 asm_fprintf (file
, "\tsubl2 $%d,%Rsp\n", size
);
129 /* This is like nonimmediate_operand with a restriction on the type of MEM. */
132 split_quadword_operands (operands
, low
, n
)
134 int n ATTRIBUTE_UNUSED
;
137 /* Split operands. */
139 low
[0] = low
[1] = low
[2] = 0;
140 for (i
= 0; i
< 3; i
++)
143 /* it's already been figured out */;
144 else if (GET_CODE (operands
[i
]) == MEM
145 && (GET_CODE (XEXP (operands
[i
], 0)) == POST_INC
))
147 rtx addr
= XEXP (operands
[i
], 0);
148 operands
[i
] = low
[i
] = gen_rtx_MEM (SImode
, addr
);
149 if (which_alternative
== 0 && i
== 0)
151 addr
= XEXP (operands
[i
], 0);
152 operands
[i
+1] = low
[i
+1] = gen_rtx_MEM (SImode
, addr
);
157 low
[i
] = operand_subword (operands
[i
], 0, 0, DImode
);
158 operands
[i
] = operand_subword (operands
[i
], 1, 0, DImode
);
164 print_operand_address (file
, addr
)
168 register rtx reg1
, breg
, ireg
;
172 switch (GET_CODE (addr
))
176 addr
= XEXP (addr
, 0);
180 fprintf (file
, "(%s)", reg_names
[REGNO (addr
)]);
184 fprintf (file
, "-(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
188 fprintf (file
, "(%s)+", reg_names
[REGNO (XEXP (addr
, 0))]);
192 /* There can be either two or three things added here. One must be a
193 REG. One can be either a REG or a MULT of a REG and an appropriate
194 constant, and the third can only be a constant or a MEM.
196 We get these two or three things and put the constant or MEM in
197 OFFSET, the MULT or REG in IREG, and the REG in BREG. If we have
198 a register and can't tell yet if it is a base or index register,
201 reg1
= 0; ireg
= 0; breg
= 0; offset
= 0;
203 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0))
204 || GET_CODE (XEXP (addr
, 0)) == MEM
)
206 offset
= XEXP (addr
, 0);
207 addr
= XEXP (addr
, 1);
209 else if (CONSTANT_ADDRESS_P (XEXP (addr
, 1))
210 || GET_CODE (XEXP (addr
, 1)) == MEM
)
212 offset
= XEXP (addr
, 1);
213 addr
= XEXP (addr
, 0);
215 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
217 ireg
= XEXP (addr
, 1);
218 addr
= XEXP (addr
, 0);
220 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
222 ireg
= XEXP (addr
, 0);
223 addr
= XEXP (addr
, 1);
225 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
227 reg1
= XEXP (addr
, 1);
228 addr
= XEXP (addr
, 0);
230 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
232 reg1
= XEXP (addr
, 0);
233 addr
= XEXP (addr
, 1);
238 if (GET_CODE (addr
) == REG
)
245 else if (GET_CODE (addr
) == MULT
)
247 else if (GET_CODE (addr
) == PLUS
)
249 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0))
250 || GET_CODE (XEXP (addr
, 0)) == MEM
)
254 if (GET_CODE (offset
) == CONST_INT
)
255 offset
= plus_constant (XEXP (addr
, 0), INTVAL (offset
));
256 else if (GET_CODE (XEXP (addr
, 0)) == CONST_INT
)
257 offset
= plus_constant (offset
, INTVAL (XEXP (addr
, 0)));
261 offset
= XEXP (addr
, 0);
263 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
266 ireg
= reg1
, breg
= XEXP (addr
, 0), reg1
= 0;
268 reg1
= XEXP (addr
, 0);
270 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
274 ireg
= XEXP (addr
, 0);
279 if (CONSTANT_ADDRESS_P (XEXP (addr
, 1))
280 || GET_CODE (XEXP (addr
, 1)) == MEM
)
284 if (GET_CODE (offset
) == CONST_INT
)
285 offset
= plus_constant (XEXP (addr
, 1), INTVAL (offset
));
286 else if (GET_CODE (XEXP (addr
, 1)) == CONST_INT
)
287 offset
= plus_constant (offset
, INTVAL (XEXP (addr
, 1)));
291 offset
= XEXP (addr
, 1);
293 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
296 ireg
= reg1
, breg
= XEXP (addr
, 1), reg1
= 0;
298 reg1
= XEXP (addr
, 1);
300 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
304 ireg
= XEXP (addr
, 1);
312 /* If REG1 is nonzero, figure out if it is a base or index register. */
315 if (breg
!= 0 || (offset
&& GET_CODE (offset
) == MEM
))
326 output_address (offset
);
329 fprintf (file
, "(%s)", reg_names
[REGNO (breg
)]);
333 if (GET_CODE (ireg
) == MULT
)
334 ireg
= XEXP (ireg
, 0);
335 if (GET_CODE (ireg
) != REG
)
337 fprintf (file
, "[%s]", reg_names
[REGNO (ireg
)]);
342 output_addr_const (file
, addr
);
350 switch (GET_CODE (op
))
382 register enum machine_mode mode
;
383 REAL_VALUE_TYPE r
, s
;
386 if (GET_CODE (c
) != CONST_DOUBLE
)
391 if (c
== const_tiny_rtx
[(int) mode
][0]
392 || c
== const_tiny_rtx
[(int) mode
][1]
393 || c
== const_tiny_rtx
[(int) mode
][2])
396 REAL_VALUE_FROM_CONST_DOUBLE (r
, c
);
398 for (i
= 0; i
< 7; i
++)
401 REAL_VALUE_FROM_INT (s
, x
, 0, mode
);
403 if (REAL_VALUES_EQUAL (r
, s
))
405 if (!exact_real_inverse (mode
, &s
))
407 if (REAL_VALUES_EQUAL (r
, s
))
414 /* Return the cost in cycles of a memory address, relative to register
417 Each of the following adds the indicated number of cycles:
421 1 - indexing and/or offset(register)
426 vax_address_cost_1 (addr
)
429 int reg
= 0, indexed
= 0, indir
= 0, offset
= 0, predec
= 0;
430 rtx plus_op0
= 0, plus_op1
= 0;
432 switch (GET_CODE (addr
))
442 indexed
= 1; /* 2 on VAX 2 */
445 /* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */
447 offset
= (unsigned)(INTVAL(addr
)+128) > 256;
451 offset
= 1; /* 2 on VAX 2 */
453 case LABEL_REF
: /* this is probably a byte offset from the pc */
459 plus_op1
= XEXP (addr
, 0);
461 plus_op0
= XEXP (addr
, 0);
462 addr
= XEXP (addr
, 1);
465 indir
= 2; /* 3 on VAX 2 */
466 addr
= XEXP (addr
, 0);
472 /* Up to 3 things can be added in an address. They are stored in
473 plus_op0, plus_op1, and addr. */
487 /* Indexing and register+offset can both be used (except on a VAX 2)
488 without increasing execution time over either one alone. */
489 if (reg
&& indexed
&& offset
)
490 return reg
+ indir
+ offset
+ predec
;
491 return reg
+ indexed
+ indir
+ offset
+ predec
;
498 return (1 + (GET_CODE (x
) == REG
? 0 : vax_address_cost_1 (x
)));
501 /* Cost of an expression on a VAX. This version has costs tuned for the
502 CVAX chip (found in the VAX 3 series) with comments for variations on
506 vax_rtx_costs_1 (x
, code
, outer_code
)
508 enum rtx_code code
, outer_code
;
510 enum machine_mode mode
= GET_MODE (x
);
512 int i
= 0; /* may be modified in switch */
513 const char *fmt
= GET_RTX_FORMAT (code
); /* may be modified in switch */
517 /* On a VAX, constants from 0..63 are cheap because they can use the
518 1 byte literal constant format. compare to -1 should be made cheap
519 so that decrement-and-branch insns can be formed more easily (if
520 the value -1 is copied to a register some decrement-and-branch
521 patterns will not match). */
525 if (outer_code
== AND
)
526 return ((unsigned HOST_WIDE_INT
) ~INTVAL (x
) <= 077) ? 1 : 2;
527 if ((unsigned HOST_WIDE_INT
) INTVAL (x
) <= 077)
529 if (outer_code
== COMPARE
&& INTVAL (x
) == -1)
531 if (outer_code
== PLUS
&& (unsigned HOST_WIDE_INT
) -INTVAL (x
) <= 077)
541 if (GET_MODE_CLASS (GET_MODE (x
)) == MODE_FLOAT
)
542 return vax_float_literal (x
) ? 5 : 8;
544 return (((CONST_DOUBLE_HIGH (x
) == 0
545 && (unsigned HOST_WIDE_INT
) CONST_DOUBLE_LOW (x
) < 64)
546 || (outer_code
== PLUS
547 && CONST_DOUBLE_HIGH (x
) == -1 \
548 && (unsigned HOST_WIDE_INT
)-CONST_DOUBLE_LOW (x
) < 64))
559 c
= 16; /* 4 on VAX 9000 */
562 c
= 9; /* 4 on VAX 9000, 12 on VAX 2 */
565 c
= 16; /* 6 on VAX 9000, 28 on VAX 2 */
570 c
= 10; /* 3-4 on VAX 9000, 20-28 on VAX 2 */
573 return MAX_COST
; /* Mode is not supported. */
578 return MAX_COST
; /* Mode is not supported. */
583 c
= 30; /* highly variable */
584 else if (mode
== DFmode
)
585 /* divide takes 28 cycles if the result is not zero, 13 otherwise */
588 c
= 11; /* 25 on VAX 2 */
595 return MAX_COST
; /* Mode is not supported. */
599 c
= 6 + (mode
== DFmode
) + (GET_MODE (XEXP (x
, 0)) != SImode
);
603 c
= 7; /* 17 on VAX 2 */
611 c
= 10; /* 6 on VAX 9000 */
615 c
= 6; /* 5 on VAX 2, 4 on VAX 9000 */
616 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
617 fmt
= "e"; /* all constant rotate counts are short */
620 /* Check for small negative integer operand: subl2 can be used with
621 a short positive constant instead. */
622 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
623 if ((unsigned)(INTVAL (XEXP (x
, 1)) + 63) < 127)
626 c
= (mode
== DFmode
) ? 13 : 8; /* 6/8 on VAX 9000, 16/15 on VAX 2 */
632 /* AND is special because the first operand is complemented. */
634 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
636 if ((unsigned)~INTVAL (XEXP (x
, 0)) > 63)
645 else if (mode
== SFmode
)
647 else if (mode
== DImode
)
656 if (mode
== DImode
|| mode
== DFmode
)
657 c
= 5; /* 7 on VAX 2 */
659 c
= 3; /* 4 on VAX 2 */
661 if (GET_CODE (x
) == REG
|| GET_CODE (x
) == POST_INC
)
663 return c
+ vax_address_cost_1 (x
);
669 /* Now look inside the expression. Operands which are not registers or
670 short constants add to the cost.
672 FMT and I may have been adjusted in the switch above for instructions
673 which require special handling */
675 while (*fmt
++ == 'e')
677 register rtx op
= XEXP (x
, i
++);
678 code
= GET_CODE (op
);
680 /* A NOT is likely to be found as the first operand of an AND
681 (in which case the relevant cost is of the operand inside
682 the not) and not likely to be found anywhere else. */
684 op
= XEXP (op
, 0), code
= GET_CODE (op
);
689 if ((unsigned)INTVAL (op
) > 63 && GET_MODE (x
) != QImode
)
690 c
+= 1; /* 2 on VAX 2 */
695 c
+= 1; /* 2 on VAX 2 */
698 if (GET_MODE_CLASS (GET_MODE (op
)) == MODE_FLOAT
)
700 /* Registers are faster than floating point constants -- even
701 those constants which can be encoded in a single byte. */
702 if (vax_float_literal (op
))
705 c
+= (GET_MODE (x
) == DFmode
) ? 3 : 2;
709 if (CONST_DOUBLE_HIGH (op
) != 0
710 || (unsigned)CONST_DOUBLE_LOW (op
) > 63)
715 c
+= 1; /* 2 on VAX 2 */
716 if (GET_CODE (XEXP (op
, 0)) != REG
)
717 c
+= vax_address_cost_1 (XEXP (op
, 0));
731 vax_rtx_costs (x
, code
, outer_code
, total
)
733 int code
, outer_code
;
736 *total
= vax_rtx_costs_1 (x
, code
, outer_code
);
740 /* Return 1 if insn A follows B. */
748 for (p
= a
; p
!= b
; p
= NEXT_INSN (p
))
755 /* Returns 1 if we know operand OP was 0 before INSN. */
758 reg_was_0_p (insn
, op
)
763 return ((link
= find_reg_note (insn
, REG_WAS_0
, 0))
764 /* Make sure the insn that stored the 0 is still present
765 and doesn't follow INSN in the insn sequence. */
766 && ! INSN_DELETED_P (XEXP (link
, 0))
767 && GET_CODE (XEXP (link
, 0)) != NOTE
768 && ! follows_p (XEXP (link
, 0), insn
)
769 /* Make sure cross jumping didn't happen here. */
770 && no_labels_between_p (XEXP (link
, 0), insn
)
771 /* Make sure the reg hasn't been clobbered. */
772 && ! reg_set_between_p (op
, XEXP (link
, 0), insn
));
775 /* Output code to add DELTA to the first argument, and then jump to FUNCTION.
776 Used for C++ multiple inheritance.
777 .mask ^m<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11> #conservative entry mask
778 addl2 $DELTA, 4(ap) #adjust first argument
779 jmp FUNCTION+2 #jump beyond FUNCTION's entry mask
783 vax_output_mi_thunk (file
, thunk
, delta
, vcall_offset
, function
)
785 tree thunk ATTRIBUTE_UNUSED
;
787 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED
;
790 fprintf (file
, "\t.word 0x0ffc\n");
791 fprintf (file
, "\taddl2 $");
792 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, delta
);
793 asm_fprintf (file
, ",4(%Rap)\n");
794 fprintf (file
, "\tjmp ");
795 assemble_name (file
, XSTR (XEXP (DECL_RTL (function
), 0), 0));
796 fprintf (file
, "+2\n");