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
));
49 /* Initialize the GCC target structure. */
50 #undef TARGET_ASM_ALIGNED_HI_OP
51 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
53 #undef TARGET_ASM_FUNCTION_PROLOGUE
54 #define TARGET_ASM_FUNCTION_PROLOGUE vax_output_function_prologue
56 #undef TARGET_ASM_OUTPUT_MI_THUNK
57 #define TARGET_ASM_OUTPUT_MI_THUNK vax_output_mi_thunk
58 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
59 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
61 struct gcc_target targetm
= TARGET_INITIALIZER
;
63 /* Set global variables as needed for the options enabled. */
68 /* We're VAX floating point, not IEEE floating point. */
69 memset (real_format_for_mode
, 0, sizeof real_format_for_mode
);
70 real_format_for_mode
[SFmode
- QFmode
] = &vax_f_format
;
71 real_format_for_mode
[DFmode
- QFmode
]
72 = (TARGET_G_FLOAT
? &vax_g_format
: &vax_d_format
);
75 /* Generate the assembly code for function entry. FILE is a stdio
76 stream to output the code to. SIZE is an int: how many units of
77 temporary storage to allocate.
79 Refer to the array `regs_ever_live' to determine which registers to
80 save; `regs_ever_live[I]' is nonzero if register number I is ever
81 used in the function. This function is responsible for knowing
82 which registers should not be saved even if used. */
85 vax_output_function_prologue (file
, size
)
90 register int mask
= 0;
92 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
93 if (regs_ever_live
[regno
] && !call_used_regs
[regno
])
96 fprintf (file
, "\t.word 0x%x\n", mask
);
98 if (dwarf2out_do_frame ())
100 const char *label
= dwarf2out_cfi_label ();
103 for (regno
= FIRST_PSEUDO_REGISTER
-1; regno
>= 0; --regno
)
104 if (regs_ever_live
[regno
] && !call_used_regs
[regno
])
105 dwarf2out_reg_save (label
, regno
, offset
-= 4);
107 dwarf2out_reg_save (label
, PC_REGNUM
, offset
-= 4);
108 dwarf2out_reg_save (label
, FRAME_POINTER_REGNUM
, offset
-= 4);
109 dwarf2out_reg_save (label
, ARG_POINTER_REGNUM
, offset
-= 4);
110 dwarf2out_def_cfa (label
, FRAME_POINTER_REGNUM
, -(offset
- 4));
113 size
-= STARTING_FRAME_OFFSET
;
115 asm_fprintf (file
, "\tmovab %d(%Rsp),%Rsp\n", -size
);
117 asm_fprintf (file
, "\tsubl2 $%d,%Rsp\n", size
);
120 /* This is like nonimmediate_operand with a restriction on the type of MEM. */
123 split_quadword_operands (operands
, low
, n
)
125 int n ATTRIBUTE_UNUSED
;
128 /* Split operands. */
130 low
[0] = low
[1] = low
[2] = 0;
131 for (i
= 0; i
< 3; i
++)
134 /* it's already been figured out */;
135 else if (GET_CODE (operands
[i
]) == MEM
136 && (GET_CODE (XEXP (operands
[i
], 0)) == POST_INC
))
138 rtx addr
= XEXP (operands
[i
], 0);
139 operands
[i
] = low
[i
] = gen_rtx_MEM (SImode
, addr
);
140 if (which_alternative
== 0 && i
== 0)
142 addr
= XEXP (operands
[i
], 0);
143 operands
[i
+1] = low
[i
+1] = gen_rtx_MEM (SImode
, addr
);
148 low
[i
] = operand_subword (operands
[i
], 0, 0, DImode
);
149 operands
[i
] = operand_subword (operands
[i
], 1, 0, DImode
);
155 print_operand_address (file
, addr
)
159 register rtx reg1
, breg
, ireg
;
163 switch (GET_CODE (addr
))
167 addr
= XEXP (addr
, 0);
171 fprintf (file
, "(%s)", reg_names
[REGNO (addr
)]);
175 fprintf (file
, "-(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
179 fprintf (file
, "(%s)+", reg_names
[REGNO (XEXP (addr
, 0))]);
183 /* There can be either two or three things added here. One must be a
184 REG. One can be either a REG or a MULT of a REG and an appropriate
185 constant, and the third can only be a constant or a MEM.
187 We get these two or three things and put the constant or MEM in
188 OFFSET, the MULT or REG in IREG, and the REG in BREG. If we have
189 a register and can't tell yet if it is a base or index register,
192 reg1
= 0; ireg
= 0; breg
= 0; offset
= 0;
194 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0))
195 || GET_CODE (XEXP (addr
, 0)) == MEM
)
197 offset
= XEXP (addr
, 0);
198 addr
= XEXP (addr
, 1);
200 else if (CONSTANT_ADDRESS_P (XEXP (addr
, 1))
201 || GET_CODE (XEXP (addr
, 1)) == MEM
)
203 offset
= XEXP (addr
, 1);
204 addr
= XEXP (addr
, 0);
206 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
208 ireg
= XEXP (addr
, 1);
209 addr
= XEXP (addr
, 0);
211 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
213 ireg
= XEXP (addr
, 0);
214 addr
= XEXP (addr
, 1);
216 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
218 reg1
= XEXP (addr
, 1);
219 addr
= XEXP (addr
, 0);
221 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
223 reg1
= XEXP (addr
, 0);
224 addr
= XEXP (addr
, 1);
229 if (GET_CODE (addr
) == REG
)
236 else if (GET_CODE (addr
) == MULT
)
238 else if (GET_CODE (addr
) == PLUS
)
240 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0))
241 || GET_CODE (XEXP (addr
, 0)) == MEM
)
245 if (GET_CODE (offset
) == CONST_INT
)
246 offset
= plus_constant (XEXP (addr
, 0), INTVAL (offset
));
247 else if (GET_CODE (XEXP (addr
, 0)) == CONST_INT
)
248 offset
= plus_constant (offset
, INTVAL (XEXP (addr
, 0)));
252 offset
= XEXP (addr
, 0);
254 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
257 ireg
= reg1
, breg
= XEXP (addr
, 0), reg1
= 0;
259 reg1
= XEXP (addr
, 0);
261 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
265 ireg
= XEXP (addr
, 0);
270 if (CONSTANT_ADDRESS_P (XEXP (addr
, 1))
271 || GET_CODE (XEXP (addr
, 1)) == MEM
)
275 if (GET_CODE (offset
) == CONST_INT
)
276 offset
= plus_constant (XEXP (addr
, 1), INTVAL (offset
));
277 else if (GET_CODE (XEXP (addr
, 1)) == CONST_INT
)
278 offset
= plus_constant (offset
, INTVAL (XEXP (addr
, 1)));
282 offset
= XEXP (addr
, 1);
284 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
287 ireg
= reg1
, breg
= XEXP (addr
, 1), reg1
= 0;
289 reg1
= XEXP (addr
, 1);
291 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
295 ireg
= XEXP (addr
, 1);
303 /* If REG1 is nonzero, figure out if it is a base or index register. */
306 if (breg
!= 0 || (offset
&& GET_CODE (offset
) == MEM
))
317 output_address (offset
);
320 fprintf (file
, "(%s)", reg_names
[REGNO (breg
)]);
324 if (GET_CODE (ireg
) == MULT
)
325 ireg
= XEXP (ireg
, 0);
326 if (GET_CODE (ireg
) != REG
)
328 fprintf (file
, "[%s]", reg_names
[REGNO (ireg
)]);
333 output_addr_const (file
, addr
);
341 switch (GET_CODE (op
))
373 register enum machine_mode mode
;
374 REAL_VALUE_TYPE r
, s
;
377 if (GET_CODE (c
) != CONST_DOUBLE
)
382 if (c
== const_tiny_rtx
[(int) mode
][0]
383 || c
== const_tiny_rtx
[(int) mode
][1]
384 || c
== const_tiny_rtx
[(int) mode
][2])
387 REAL_VALUE_FROM_CONST_DOUBLE (r
, c
);
389 for (i
= 0; i
< 7; i
++)
392 REAL_VALUE_FROM_INT (s
, x
, 0, mode
);
394 if (REAL_VALUES_EQUAL (r
, s
))
396 if (!exact_real_inverse (mode
, &s
))
398 if (REAL_VALUES_EQUAL (r
, s
))
405 /* Return the cost in cycles of a memory address, relative to register
408 Each of the following adds the indicated number of cycles:
412 1 - indexing and/or offset(register)
417 vax_address_cost (addr
)
420 int reg
= 0, indexed
= 0, indir
= 0, offset
= 0, predec
= 0;
421 rtx plus_op0
= 0, plus_op1
= 0;
423 switch (GET_CODE (addr
))
433 indexed
= 1; /* 2 on VAX 2 */
436 /* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */
438 offset
= (unsigned)(INTVAL(addr
)+128) > 256;
442 offset
= 1; /* 2 on VAX 2 */
444 case LABEL_REF
: /* this is probably a byte offset from the pc */
450 plus_op1
= XEXP (addr
, 0);
452 plus_op0
= XEXP (addr
, 0);
453 addr
= XEXP (addr
, 1);
456 indir
= 2; /* 3 on VAX 2 */
457 addr
= XEXP (addr
, 0);
463 /* Up to 3 things can be added in an address. They are stored in
464 plus_op0, plus_op1, and addr. */
478 /* Indexing and register+offset can both be used (except on a VAX 2)
479 without increasing execution time over either one alone. */
480 if (reg
&& indexed
&& offset
)
481 return reg
+ indir
+ offset
+ predec
;
482 return reg
+ indexed
+ indir
+ offset
+ predec
;
486 /* Cost of an expression on a VAX. This version has costs tuned for the
487 CVAX chip (found in the VAX 3 series) with comments for variations on
494 register enum rtx_code code
= GET_CODE (x
);
495 enum machine_mode mode
= GET_MODE (x
);
497 int i
= 0; /* may be modified in switch */
498 const char *fmt
= GET_RTX_FORMAT (code
); /* may be modified in switch */
510 c
= 16; /* 4 on VAX 9000 */
513 c
= 9; /* 4 on VAX 9000, 12 on VAX 2 */
516 c
= 16; /* 6 on VAX 9000, 28 on VAX 2 */
521 c
= 10; /* 3-4 on VAX 9000, 20-28 on VAX 2 */
524 return MAX_COST
; /* Mode is not supported. */
529 return MAX_COST
; /* Mode is not supported. */
534 c
= 30; /* highly variable */
535 else if (mode
== DFmode
)
536 /* divide takes 28 cycles if the result is not zero, 13 otherwise */
539 c
= 11; /* 25 on VAX 2 */
546 return MAX_COST
; /* Mode is not supported. */
550 c
= 6 + (mode
== DFmode
) + (GET_MODE (XEXP (x
, 0)) != SImode
);
554 c
= 7; /* 17 on VAX 2 */
562 c
= 10; /* 6 on VAX 9000 */
566 c
= 6; /* 5 on VAX 2, 4 on VAX 9000 */
567 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
568 fmt
= "e"; /* all constant rotate counts are short */
571 /* Check for small negative integer operand: subl2 can be used with
572 a short positive constant instead. */
573 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
574 if ((unsigned)(INTVAL (XEXP (x
, 1)) + 63) < 127)
577 c
= (mode
== DFmode
) ? 13 : 8; /* 6/8 on VAX 9000, 16/15 on VAX 2 */
583 /* AND is special because the first operand is complemented. */
585 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
587 if ((unsigned)~INTVAL (XEXP (x
, 0)) > 63)
596 else if (mode
== SFmode
)
598 else if (mode
== DImode
)
607 if (mode
== DImode
|| mode
== DFmode
)
608 c
= 5; /* 7 on VAX 2 */
610 c
= 3; /* 4 on VAX 2 */
612 if (GET_CODE (x
) == REG
|| GET_CODE (x
) == POST_INC
)
614 return c
+ vax_address_cost (x
);
621 /* Now look inside the expression. Operands which are not registers or
622 short constants add to the cost.
624 FMT and I may have been adjusted in the switch above for instructions
625 which require special handling */
627 while (*fmt
++ == 'e')
629 register rtx op
= XEXP (x
, i
++);
630 code
= GET_CODE (op
);
632 /* A NOT is likely to be found as the first operand of an AND
633 (in which case the relevant cost is of the operand inside
634 the not) and not likely to be found anywhere else. */
636 op
= XEXP (op
, 0), code
= GET_CODE (op
);
641 if ((unsigned)INTVAL (op
) > 63 && GET_MODE (x
) != QImode
)
642 c
+= 1; /* 2 on VAX 2 */
647 c
+= 1; /* 2 on VAX 2 */
650 if (GET_MODE_CLASS (GET_MODE (op
)) == MODE_FLOAT
)
652 /* Registers are faster than floating point constants -- even
653 those constants which can be encoded in a single byte. */
654 if (vax_float_literal (op
))
657 c
+= (GET_MODE (x
) == DFmode
) ? 3 : 2;
661 if (CONST_DOUBLE_HIGH (op
) != 0
662 || (unsigned)CONST_DOUBLE_LOW (op
) > 63)
667 c
+= 1; /* 2 on VAX 2 */
668 if (GET_CODE (XEXP (op
, 0)) != REG
)
669 c
+= vax_address_cost (XEXP (op
, 0));
682 /* Return 1 if insn A follows B. */
690 for (p
= a
; p
!= b
; p
= NEXT_INSN (p
))
697 /* Returns 1 if we know operand OP was 0 before INSN. */
700 reg_was_0_p (insn
, op
)
705 return ((link
= find_reg_note (insn
, REG_WAS_0
, 0))
706 /* Make sure the insn that stored the 0 is still present
707 and doesn't follow INSN in the insn sequence. */
708 && ! INSN_DELETED_P (XEXP (link
, 0))
709 && GET_CODE (XEXP (link
, 0)) != NOTE
710 && ! follows_p (XEXP (link
, 0), insn
)
711 /* Make sure cross jumping didn't happen here. */
712 && no_labels_between_p (XEXP (link
, 0), insn
)
713 /* Make sure the reg hasn't been clobbered. */
714 && ! reg_set_between_p (op
, XEXP (link
, 0), insn
));
718 vax_output_mi_thunk (file
, thunk
, delta
, vcall_offset
, function
)
720 tree thunk ATTRIBUTE_UNUSED
;
722 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED
;
725 fprintf (file
, "\t.word 0x0ffc\n");
726 fprintf (file
, "\taddl2 $");
727 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, delta
);
728 asm_fprintf (file
, ",4(%Rap)\n");
729 fprintf (file
, "\tjmp ");
730 assemble_name (file
, XSTR (XEXP (DECL_RTL (function
), 0), 0));
731 fprintf (file
, "+2\n");