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 GCC.
7 GCC 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 GCC 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 GCC; 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"
43 #include "target-def.h"
45 static void vax_output_function_prologue (FILE *, HOST_WIDE_INT
);
46 static void vax_file_start (void);
47 static void vax_init_libfuncs (void);
48 static void vax_output_mi_thunk (FILE *, tree
, HOST_WIDE_INT
,
50 static int vax_address_cost_1 (rtx
);
51 static int vax_address_cost (rtx
);
52 static int vax_rtx_costs_1 (rtx
, enum rtx_code
, enum rtx_code
);
53 static bool vax_rtx_costs (rtx
, int, int, int *);
55 /* Initialize the GCC target structure. */
56 #undef TARGET_ASM_ALIGNED_HI_OP
57 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
59 #undef TARGET_ASM_FUNCTION_PROLOGUE
60 #define TARGET_ASM_FUNCTION_PROLOGUE vax_output_function_prologue
62 #undef TARGET_ASM_FILE_START
63 #define TARGET_ASM_FILE_START vax_file_start
64 #undef TARGET_ASM_FILE_START_APP_OFF
65 #define TARGET_ASM_FILE_START_APP_OFF true
67 #undef TARGET_INIT_LIBFUNCS
68 #define TARGET_INIT_LIBFUNCS vax_init_libfuncs
70 #undef TARGET_ASM_OUTPUT_MI_THUNK
71 #define TARGET_ASM_OUTPUT_MI_THUNK vax_output_mi_thunk
72 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
73 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
75 #undef TARGET_RTX_COSTS
76 #define TARGET_RTX_COSTS vax_rtx_costs
77 #undef TARGET_ADDRESS_COST
78 #define TARGET_ADDRESS_COST vax_address_cost
80 struct gcc_target targetm
= TARGET_INITIALIZER
;
82 /* Set global variables as needed for the options enabled. */
85 override_options (void)
87 /* We're VAX floating point, not IEEE floating point. */
89 REAL_MODE_FORMAT (DFmode
) = &vax_g_format
;
92 /* Generate the assembly code for function entry. FILE is a stdio
93 stream to output the code to. SIZE is an int: how many units of
94 temporary storage to allocate.
96 Refer to the array `regs_ever_live' to determine which registers to
97 save; `regs_ever_live[I]' is nonzero if register number I is ever
98 used in the function. This function is responsible for knowing
99 which registers should not be saved even if used. */
102 vax_output_function_prologue (FILE * file
, HOST_WIDE_INT size
)
105 register int mask
= 0;
107 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
108 if (regs_ever_live
[regno
] && !call_used_regs
[regno
])
111 fprintf (file
, "\t.word 0x%x\n", mask
);
113 if (dwarf2out_do_frame ())
115 const char *label
= dwarf2out_cfi_label ();
118 for (regno
= FIRST_PSEUDO_REGISTER
-1; regno
>= 0; --regno
)
119 if (regs_ever_live
[regno
] && !call_used_regs
[regno
])
120 dwarf2out_reg_save (label
, regno
, offset
-= 4);
122 dwarf2out_reg_save (label
, PC_REGNUM
, offset
-= 4);
123 dwarf2out_reg_save (label
, FRAME_POINTER_REGNUM
, offset
-= 4);
124 dwarf2out_reg_save (label
, ARG_POINTER_REGNUM
, offset
-= 4);
125 dwarf2out_def_cfa (label
, FRAME_POINTER_REGNUM
, -(offset
- 4));
128 size
-= STARTING_FRAME_OFFSET
;
130 asm_fprintf (file
, "\tmovab %wd(%Rsp),%Rsp\n", -size
);
132 asm_fprintf (file
, "\tsubl2 $%wd,%Rsp\n", size
);
135 /* When debugging with stabs, we want to output an extra dummy label
136 so that gas can distinguish between D_float and G_float prior to
137 processing the .stabs directive identifying type double. */
139 vax_file_start (void)
141 default_file_start ();
143 if (write_symbols
== DBX_DEBUG
)
144 fprintf (asm_out_file
, "___vax_%c_doubles:\n", ASM_DOUBLE_CHAR
);
147 /* We can use the BSD C library routines for the libgcc calls that are
148 still generated, since that's what they boil down to anyways. When
149 ELF, avoid the user's namespace. */
152 vax_init_libfuncs (void)
154 set_optab_libfunc (udiv_optab
, SImode
, TARGET_ELF
? "*__udiv" : "*udiv");
155 set_optab_libfunc (umod_optab
, SImode
, TARGET_ELF
? "*__umod" : "*umod");
158 /* This is like nonimmediate_operand with a restriction on the type of MEM. */
161 split_quadword_operands (rtx
* operands
, rtx
* low
, int n ATTRIBUTE_UNUSED
)
164 /* Split operands. */
166 low
[0] = low
[1] = low
[2] = 0;
167 for (i
= 0; i
< 3; i
++)
170 /* it's already been figured out */;
171 else if (GET_CODE (operands
[i
]) == MEM
172 && (GET_CODE (XEXP (operands
[i
], 0)) == POST_INC
))
174 rtx addr
= XEXP (operands
[i
], 0);
175 operands
[i
] = low
[i
] = gen_rtx_MEM (SImode
, addr
);
176 if (which_alternative
== 0 && i
== 0)
178 addr
= XEXP (operands
[i
], 0);
179 operands
[i
+1] = low
[i
+1] = gen_rtx_MEM (SImode
, addr
);
184 low
[i
] = operand_subword (operands
[i
], 0, 0, DImode
);
185 operands
[i
] = operand_subword (operands
[i
], 1, 0, DImode
);
191 print_operand_address (FILE * file
, register rtx addr
)
193 register rtx reg1
, breg
, ireg
;
197 switch (GET_CODE (addr
))
201 addr
= XEXP (addr
, 0);
205 fprintf (file
, "(%s)", reg_names
[REGNO (addr
)]);
209 fprintf (file
, "-(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
213 fprintf (file
, "(%s)+", reg_names
[REGNO (XEXP (addr
, 0))]);
217 /* There can be either two or three things added here. One must be a
218 REG. One can be either a REG or a MULT of a REG and an appropriate
219 constant, and the third can only be a constant or a MEM.
221 We get these two or three things and put the constant or MEM in
222 OFFSET, the MULT or REG in IREG, and the REG in BREG. If we have
223 a register and can't tell yet if it is a base or index register,
226 reg1
= 0; ireg
= 0; breg
= 0; offset
= 0;
228 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0))
229 || GET_CODE (XEXP (addr
, 0)) == MEM
)
231 offset
= XEXP (addr
, 0);
232 addr
= XEXP (addr
, 1);
234 else if (CONSTANT_ADDRESS_P (XEXP (addr
, 1))
235 || GET_CODE (XEXP (addr
, 1)) == MEM
)
237 offset
= XEXP (addr
, 1);
238 addr
= XEXP (addr
, 0);
240 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
242 ireg
= XEXP (addr
, 1);
243 addr
= XEXP (addr
, 0);
245 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
247 ireg
= XEXP (addr
, 0);
248 addr
= XEXP (addr
, 1);
250 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
252 reg1
= XEXP (addr
, 1);
253 addr
= XEXP (addr
, 0);
255 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
257 reg1
= XEXP (addr
, 0);
258 addr
= XEXP (addr
, 1);
263 if (GET_CODE (addr
) == REG
)
270 else if (GET_CODE (addr
) == MULT
)
272 else if (GET_CODE (addr
) == PLUS
)
274 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0))
275 || GET_CODE (XEXP (addr
, 0)) == MEM
)
279 if (GET_CODE (offset
) == CONST_INT
)
280 offset
= plus_constant (XEXP (addr
, 0), INTVAL (offset
));
281 else if (GET_CODE (XEXP (addr
, 0)) == CONST_INT
)
282 offset
= plus_constant (offset
, INTVAL (XEXP (addr
, 0)));
286 offset
= XEXP (addr
, 0);
288 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
291 ireg
= reg1
, breg
= XEXP (addr
, 0), reg1
= 0;
293 reg1
= XEXP (addr
, 0);
295 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
299 ireg
= XEXP (addr
, 0);
304 if (CONSTANT_ADDRESS_P (XEXP (addr
, 1))
305 || GET_CODE (XEXP (addr
, 1)) == MEM
)
309 if (GET_CODE (offset
) == CONST_INT
)
310 offset
= plus_constant (XEXP (addr
, 1), INTVAL (offset
));
311 else if (GET_CODE (XEXP (addr
, 1)) == CONST_INT
)
312 offset
= plus_constant (offset
, INTVAL (XEXP (addr
, 1)));
316 offset
= XEXP (addr
, 1);
318 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
321 ireg
= reg1
, breg
= XEXP (addr
, 1), reg1
= 0;
323 reg1
= XEXP (addr
, 1);
325 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
329 ireg
= XEXP (addr
, 1);
337 /* If REG1 is nonzero, figure out if it is a base or index register. */
340 if (breg
!= 0 || (offset
&& GET_CODE (offset
) == MEM
))
351 output_address (offset
);
354 fprintf (file
, "(%s)", reg_names
[REGNO (breg
)]);
358 if (GET_CODE (ireg
) == MULT
)
359 ireg
= XEXP (ireg
, 0);
360 if (GET_CODE (ireg
) != REG
)
362 fprintf (file
, "[%s]", reg_names
[REGNO (ireg
)]);
367 output_addr_const (file
, addr
);
372 rev_cond_name (rtx op
)
374 switch (GET_CODE (op
))
403 vax_float_literal(register rtx c
)
405 register enum machine_mode mode
;
406 REAL_VALUE_TYPE r
, s
;
409 if (GET_CODE (c
) != CONST_DOUBLE
)
414 if (c
== const_tiny_rtx
[(int) mode
][0]
415 || c
== const_tiny_rtx
[(int) mode
][1]
416 || c
== const_tiny_rtx
[(int) mode
][2])
419 REAL_VALUE_FROM_CONST_DOUBLE (r
, c
);
421 for (i
= 0; i
< 7; i
++)
424 REAL_VALUE_FROM_INT (s
, x
, 0, mode
);
426 if (REAL_VALUES_EQUAL (r
, s
))
428 if (!exact_real_inverse (mode
, &s
))
430 if (REAL_VALUES_EQUAL (r
, s
))
437 /* Return the cost in cycles of a memory address, relative to register
440 Each of the following adds the indicated number of cycles:
444 1 - indexing and/or offset(register)
449 vax_address_cost_1 (register rtx addr
)
451 int reg
= 0, indexed
= 0, indir
= 0, offset
= 0, predec
= 0;
452 rtx plus_op0
= 0, plus_op1
= 0;
454 switch (GET_CODE (addr
))
464 indexed
= 1; /* 2 on VAX 2 */
467 /* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */
469 offset
= (unsigned)(INTVAL(addr
)+128) > 256;
473 offset
= 1; /* 2 on VAX 2 */
475 case LABEL_REF
: /* this is probably a byte offset from the pc */
481 plus_op1
= XEXP (addr
, 0);
483 plus_op0
= XEXP (addr
, 0);
484 addr
= XEXP (addr
, 1);
487 indir
= 2; /* 3 on VAX 2 */
488 addr
= XEXP (addr
, 0);
494 /* Up to 3 things can be added in an address. They are stored in
495 plus_op0, plus_op1, and addr. */
509 /* Indexing and register+offset can both be used (except on a VAX 2)
510 without increasing execution time over either one alone. */
511 if (reg
&& indexed
&& offset
)
512 return reg
+ indir
+ offset
+ predec
;
513 return reg
+ indexed
+ indir
+ offset
+ predec
;
517 vax_address_cost (rtx x
)
519 return (1 + (GET_CODE (x
) == REG
? 0 : vax_address_cost_1 (x
)));
522 /* Cost of an expression on a VAX. This version has costs tuned for the
523 CVAX chip (found in the VAX 3 series) with comments for variations on
527 vax_rtx_costs_1 (register rtx x
, enum rtx_code code
, enum rtx_code outer_code
)
529 enum machine_mode mode
= GET_MODE (x
);
531 int i
= 0; /* may be modified in switch */
532 const char *fmt
= GET_RTX_FORMAT (code
); /* may be modified in switch */
536 /* On a VAX, constants from 0..63 are cheap because they can use the
537 1 byte literal constant format. compare to -1 should be made cheap
538 so that decrement-and-branch insns can be formed more easily (if
539 the value -1 is copied to a register some decrement-and-branch
540 patterns will not match). */
544 if (outer_code
== AND
)
545 return ((unsigned HOST_WIDE_INT
) ~INTVAL (x
) <= 077) ? 1 : 2;
546 if ((unsigned HOST_WIDE_INT
) INTVAL (x
) <= 077)
548 if (outer_code
== COMPARE
&& INTVAL (x
) == -1)
550 if (outer_code
== PLUS
&& (unsigned HOST_WIDE_INT
) -INTVAL (x
) <= 077)
560 if (GET_MODE_CLASS (GET_MODE (x
)) == MODE_FLOAT
)
561 return vax_float_literal (x
) ? 5 : 8;
563 return (((CONST_DOUBLE_HIGH (x
) == 0
564 && (unsigned HOST_WIDE_INT
) CONST_DOUBLE_LOW (x
) < 64)
565 || (outer_code
== PLUS
566 && CONST_DOUBLE_HIGH (x
) == -1 \
567 && (unsigned HOST_WIDE_INT
)-CONST_DOUBLE_LOW (x
) < 64))
578 c
= 16; /* 4 on VAX 9000 */
581 c
= 9; /* 4 on VAX 9000, 12 on VAX 2 */
584 c
= 16; /* 6 on VAX 9000, 28 on VAX 2 */
589 c
= 10; /* 3-4 on VAX 9000, 20-28 on VAX 2 */
592 return MAX_COST
; /* Mode is not supported. */
597 return MAX_COST
; /* Mode is not supported. */
602 c
= 30; /* highly variable */
603 else if (mode
== DFmode
)
604 /* divide takes 28 cycles if the result is not zero, 13 otherwise */
607 c
= 11; /* 25 on VAX 2 */
614 return MAX_COST
; /* Mode is not supported. */
618 c
= 6 + (mode
== DFmode
) + (GET_MODE (XEXP (x
, 0)) != SImode
);
622 c
= 7; /* 17 on VAX 2 */
630 c
= 10; /* 6 on VAX 9000 */
634 c
= 6; /* 5 on VAX 2, 4 on VAX 9000 */
635 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
636 fmt
= "e"; /* all constant rotate counts are short */
639 /* Check for small negative integer operand: subl2 can be used with
640 a short positive constant instead. */
641 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
642 if ((unsigned)(INTVAL (XEXP (x
, 1)) + 63) < 127)
645 c
= (mode
== DFmode
) ? 13 : 8; /* 6/8 on VAX 9000, 16/15 on VAX 2 */
651 /* AND is special because the first operand is complemented. */
653 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
655 if ((unsigned)~INTVAL (XEXP (x
, 0)) > 63)
664 else if (mode
== SFmode
)
666 else if (mode
== DImode
)
675 if (mode
== DImode
|| mode
== DFmode
)
676 c
= 5; /* 7 on VAX 2 */
678 c
= 3; /* 4 on VAX 2 */
680 if (GET_CODE (x
) == REG
|| GET_CODE (x
) == POST_INC
)
682 return c
+ vax_address_cost_1 (x
);
688 /* Now look inside the expression. Operands which are not registers or
689 short constants add to the cost.
691 FMT and I may have been adjusted in the switch above for instructions
692 which require special handling */
694 while (*fmt
++ == 'e')
696 register rtx op
= XEXP (x
, i
++);
697 code
= GET_CODE (op
);
699 /* A NOT is likely to be found as the first operand of an AND
700 (in which case the relevant cost is of the operand inside
701 the not) and not likely to be found anywhere else. */
703 op
= XEXP (op
, 0), code
= GET_CODE (op
);
708 if ((unsigned)INTVAL (op
) > 63 && GET_MODE (x
) != QImode
)
709 c
+= 1; /* 2 on VAX 2 */
714 c
+= 1; /* 2 on VAX 2 */
717 if (GET_MODE_CLASS (GET_MODE (op
)) == MODE_FLOAT
)
719 /* Registers are faster than floating point constants -- even
720 those constants which can be encoded in a single byte. */
721 if (vax_float_literal (op
))
724 c
+= (GET_MODE (x
) == DFmode
) ? 3 : 2;
728 if (CONST_DOUBLE_HIGH (op
) != 0
729 || (unsigned)CONST_DOUBLE_LOW (op
) > 63)
734 c
+= 1; /* 2 on VAX 2 */
735 if (GET_CODE (XEXP (op
, 0)) != REG
)
736 c
+= vax_address_cost_1 (XEXP (op
, 0));
750 vax_rtx_costs (rtx x
, int code
, int outer_code
, int * total
)
752 *total
= vax_rtx_costs_1 (x
, code
, outer_code
);
756 /* Output code to add DELTA to the first argument, and then jump to FUNCTION.
757 Used for C++ multiple inheritance.
758 .mask ^m<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11> #conservative entry mask
759 addl2 $DELTA, 4(ap) #adjust first argument
760 jmp FUNCTION+2 #jump beyond FUNCTION's entry mask
764 vax_output_mi_thunk (FILE * file
,
765 tree thunk ATTRIBUTE_UNUSED
,
767 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED
,
770 fprintf (file
, "\t.word 0x0ffc\n\taddl2 $" HOST_WIDE_INT_PRINT_DEC
, delta
);
771 asm_fprintf (file
, ",4(%Rap)\n");
772 fprintf (file
, "\tjmp ");
773 assemble_name (file
, XSTR (XEXP (DECL_RTL (function
), 0), 0));
774 fprintf (file
, "+2\n");