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"
40 #include "target-def.h"
42 static int follows_p
PARAMS ((rtx
, rtx
));
43 static void vax_output_function_prologue
PARAMS ((FILE *, HOST_WIDE_INT
));
45 static void vms_asm_out_constructor
PARAMS ((rtx
, int));
46 static void vms_asm_out_destructor
PARAMS ((rtx
, int));
47 static void vms_select_section
PARAMS ((tree
, int, unsigned HOST_WIDE_INT
));
48 static void vms_encode_section_info
PARAMS ((tree
, int));
49 static void vms_globalize_label
PARAMS ((FILE *, const char *));
51 static void vax_output_mi_thunk
PARAMS ((FILE *, tree
, HOST_WIDE_INT
,
52 HOST_WIDE_INT
, tree
));
54 /* Initialize the GCC target structure. */
55 #undef TARGET_ASM_ALIGNED_HI_OP
56 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
58 #undef TARGET_ASM_FUNCTION_PROLOGUE
59 #define TARGET_ASM_FUNCTION_PROLOGUE vax_output_function_prologue
62 #undef TARGET_ASM_SELECT_SECTION
63 #define TARGET_ASM_SELECT_SECTION vms_select_section
64 #undef TARGET_ENCODE_SECTION_INFO
65 #define TARGET_ENCODE_SECTION_INFO vms_encode_section_info
66 #undef TARGET_ASM_GLOBALIZE_LABEL
67 #define TARGET_ASM_GLOBALIZE_LABEL vms_globalize_label
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 struct gcc_target targetm
= TARGET_INITIALIZER
;
77 /* Set global variables as needed for the options enabled. */
82 /* We're VAX floating point, not IEEE floating point. */
83 memset (real_format_for_mode
, 0, sizeof real_format_for_mode
);
84 real_format_for_mode
[SFmode
- QFmode
] = &vax_f_format
;
85 real_format_for_mode
[DFmode
- QFmode
]
86 = (TARGET_G_FLOAT
? &vax_g_format
: &vax_d_format
);
89 /* Generate the assembly code for function entry. FILE is a stdio
90 stream to output the code to. SIZE is an int: how many units of
91 temporary storage to allocate.
93 Refer to the array `regs_ever_live' to determine which registers to
94 save; `regs_ever_live[I]' is nonzero if register number I is ever
95 used in the function. This function is responsible for knowing
96 which registers should not be saved even if used. */
99 vax_output_function_prologue (file
, size
)
104 register int mask
= 0;
106 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
107 if (regs_ever_live
[regno
] && !call_used_regs
[regno
])
110 fprintf (file
, "\t.word 0x%x\n", mask
);
112 if (dwarf2out_do_frame ())
114 const char *label
= dwarf2out_cfi_label ();
117 for (regno
= FIRST_PSEUDO_REGISTER
-1; regno
>= 0; --regno
)
118 if (regs_ever_live
[regno
] && !call_used_regs
[regno
])
119 dwarf2out_reg_save (label
, regno
, offset
-= 4);
121 dwarf2out_reg_save (label
, PC_REGNUM
, offset
-= 4);
122 dwarf2out_reg_save (label
, FRAME_POINTER_REGNUM
, offset
-= 4);
123 dwarf2out_reg_save (label
, ARG_POINTER_REGNUM
, offset
-= 4);
124 dwarf2out_def_cfa (label
, FRAME_POINTER_REGNUM
, -(offset
- 4));
129 /* Adjusting the stack pointer by 4 before calling C$MAIN_ARGS
130 is required when linking with the VMS POSIX version of the C
131 run-time library; using `subl2 $4,r0' is adequate but we use
132 `clrl -(sp)' instead. The extra 4 bytes could be removed
133 after the call because STARTING_FRAME_OFFSET's setting of -4
134 will end up adding them right back again, but don't bother. */
136 if (MAIN_NAME_P (DECL_NAME (current_function_decl
)))
137 asm_fprintf (file
, "\tclrl -(%Rsp)\n\tjsb _C$MAIN_ARGS\n");
140 size
-= STARTING_FRAME_OFFSET
;
142 asm_fprintf (file
, "\tmovab %d(%Rsp),%Rsp\n", -size
);
144 asm_fprintf (file
, "\tsubl2 $%d,%Rsp\n", size
);
147 /* This is like nonimmediate_operand with a restriction on the type of MEM. */
150 split_quadword_operands (operands
, low
, n
)
152 int n ATTRIBUTE_UNUSED
;
155 /* Split operands. */
157 low
[0] = low
[1] = low
[2] = 0;
158 for (i
= 0; i
< 3; i
++)
161 /* it's already been figured out */;
162 else if (GET_CODE (operands
[i
]) == MEM
163 && (GET_CODE (XEXP (operands
[i
], 0)) == POST_INC
))
165 rtx addr
= XEXP (operands
[i
], 0);
166 operands
[i
] = low
[i
] = gen_rtx_MEM (SImode
, addr
);
167 if (which_alternative
== 0 && i
== 0)
169 addr
= XEXP (operands
[i
], 0);
170 operands
[i
+1] = low
[i
+1] = gen_rtx_MEM (SImode
, addr
);
175 low
[i
] = operand_subword (operands
[i
], 0, 0, DImode
);
176 operands
[i
] = operand_subword (operands
[i
], 1, 0, DImode
);
182 print_operand_address (file
, addr
)
186 register rtx reg1
, breg
, ireg
;
190 switch (GET_CODE (addr
))
194 addr
= XEXP (addr
, 0);
198 fprintf (file
, "(%s)", reg_names
[REGNO (addr
)]);
202 fprintf (file
, "-(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
206 fprintf (file
, "(%s)+", reg_names
[REGNO (XEXP (addr
, 0))]);
210 /* There can be either two or three things added here. One must be a
211 REG. One can be either a REG or a MULT of a REG and an appropriate
212 constant, and the third can only be a constant or a MEM.
214 We get these two or three things and put the constant or MEM in
215 OFFSET, the MULT or REG in IREG, and the REG in BREG. If we have
216 a register and can't tell yet if it is a base or index register,
219 reg1
= 0; ireg
= 0; breg
= 0; offset
= 0;
221 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0))
222 || GET_CODE (XEXP (addr
, 0)) == MEM
)
224 offset
= XEXP (addr
, 0);
225 addr
= XEXP (addr
, 1);
227 else if (CONSTANT_ADDRESS_P (XEXP (addr
, 1))
228 || GET_CODE (XEXP (addr
, 1)) == MEM
)
230 offset
= XEXP (addr
, 1);
231 addr
= XEXP (addr
, 0);
233 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
235 ireg
= XEXP (addr
, 1);
236 addr
= XEXP (addr
, 0);
238 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
240 ireg
= XEXP (addr
, 0);
241 addr
= XEXP (addr
, 1);
243 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
245 reg1
= XEXP (addr
, 1);
246 addr
= XEXP (addr
, 0);
248 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
250 reg1
= XEXP (addr
, 0);
251 addr
= XEXP (addr
, 1);
256 if (GET_CODE (addr
) == REG
)
263 else if (GET_CODE (addr
) == MULT
)
265 else if (GET_CODE (addr
) == PLUS
)
267 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0))
268 || GET_CODE (XEXP (addr
, 0)) == MEM
)
272 if (GET_CODE (offset
) == CONST_INT
)
273 offset
= plus_constant (XEXP (addr
, 0), INTVAL (offset
));
274 else if (GET_CODE (XEXP (addr
, 0)) == CONST_INT
)
275 offset
= plus_constant (offset
, INTVAL (XEXP (addr
, 0)));
279 offset
= XEXP (addr
, 0);
281 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
284 ireg
= reg1
, breg
= XEXP (addr
, 0), reg1
= 0;
286 reg1
= XEXP (addr
, 0);
288 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
292 ireg
= XEXP (addr
, 0);
297 if (CONSTANT_ADDRESS_P (XEXP (addr
, 1))
298 || GET_CODE (XEXP (addr
, 1)) == MEM
)
302 if (GET_CODE (offset
) == CONST_INT
)
303 offset
= plus_constant (XEXP (addr
, 1), INTVAL (offset
));
304 else if (GET_CODE (XEXP (addr
, 1)) == CONST_INT
)
305 offset
= plus_constant (offset
, INTVAL (XEXP (addr
, 1)));
309 offset
= XEXP (addr
, 1);
311 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
314 ireg
= reg1
, breg
= XEXP (addr
, 1), reg1
= 0;
316 reg1
= XEXP (addr
, 1);
318 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
322 ireg
= XEXP (addr
, 1);
330 /* If REG1 is nonzero, figure out if it is a base or index register. */
333 if (breg
!= 0 || (offset
&& GET_CODE (offset
) == MEM
))
344 output_address (offset
);
347 fprintf (file
, "(%s)", reg_names
[REGNO (breg
)]);
351 if (GET_CODE (ireg
) == MULT
)
352 ireg
= XEXP (ireg
, 0);
353 if (GET_CODE (ireg
) != REG
)
355 fprintf (file
, "[%s]", reg_names
[REGNO (ireg
)]);
360 output_addr_const (file
, addr
);
368 switch (GET_CODE (op
))
400 register enum machine_mode mode
;
401 REAL_VALUE_TYPE r
, s
;
404 if (GET_CODE (c
) != CONST_DOUBLE
)
409 if (c
== const_tiny_rtx
[(int) mode
][0]
410 || c
== const_tiny_rtx
[(int) mode
][1]
411 || c
== const_tiny_rtx
[(int) mode
][2])
414 REAL_VALUE_FROM_CONST_DOUBLE (r
, c
);
416 for (i
= 0; i
< 7; i
++)
419 REAL_VALUE_FROM_INT (s
, x
, 0, mode
);
421 if (REAL_VALUES_EQUAL (r
, s
))
423 if (!exact_real_inverse (mode
, &s
))
425 if (REAL_VALUES_EQUAL (r
, s
))
432 /* Return the cost in cycles of a memory address, relative to register
435 Each of the following adds the indicated number of cycles:
439 1 - indexing and/or offset(register)
444 vax_address_cost (addr
)
447 int reg
= 0, indexed
= 0, indir
= 0, offset
= 0, predec
= 0;
448 rtx plus_op0
= 0, plus_op1
= 0;
450 switch (GET_CODE (addr
))
460 indexed
= 1; /* 2 on VAX 2 */
463 /* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */
465 offset
= (unsigned)(INTVAL(addr
)+128) > 256;
469 offset
= 1; /* 2 on VAX 2 */
471 case LABEL_REF
: /* this is probably a byte offset from the pc */
477 plus_op1
= XEXP (addr
, 0);
479 plus_op0
= XEXP (addr
, 0);
480 addr
= XEXP (addr
, 1);
483 indir
= 2; /* 3 on VAX 2 */
484 addr
= XEXP (addr
, 0);
490 /* Up to 3 things can be added in an address. They are stored in
491 plus_op0, plus_op1, and addr. */
505 /* Indexing and register+offset can both be used (except on a VAX 2)
506 without increasing execution time over either one alone. */
507 if (reg
&& indexed
&& offset
)
508 return reg
+ indir
+ offset
+ predec
;
509 return reg
+ indexed
+ indir
+ offset
+ predec
;
513 /* Cost of an expression on a VAX. This version has costs tuned for the
514 CVAX chip (found in the VAX 3 series) with comments for variations on
521 register enum rtx_code code
= GET_CODE (x
);
522 enum machine_mode mode
= GET_MODE (x
);
524 int i
= 0; /* may be modified in switch */
525 const char *fmt
= GET_RTX_FORMAT (code
); /* may be modified in switch */
537 c
= 16; /* 4 on VAX 9000 */
540 c
= 9; /* 4 on VAX 9000, 12 on VAX 2 */
543 c
= 16; /* 6 on VAX 9000, 28 on VAX 2 */
548 c
= 10; /* 3-4 on VAX 9000, 20-28 on VAX 2 */
551 return MAX_COST
; /* Mode is not supported. */
556 return MAX_COST
; /* Mode is not supported. */
561 c
= 30; /* highly variable */
562 else if (mode
== DFmode
)
563 /* divide takes 28 cycles if the result is not zero, 13 otherwise */
566 c
= 11; /* 25 on VAX 2 */
573 return MAX_COST
; /* Mode is not supported. */
577 c
= 6 + (mode
== DFmode
) + (GET_MODE (XEXP (x
, 0)) != SImode
);
581 c
= 7; /* 17 on VAX 2 */
589 c
= 10; /* 6 on VAX 9000 */
593 c
= 6; /* 5 on VAX 2, 4 on VAX 9000 */
594 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
595 fmt
= "e"; /* all constant rotate counts are short */
598 /* Check for small negative integer operand: subl2 can be used with
599 a short positive constant instead. */
600 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
601 if ((unsigned)(INTVAL (XEXP (x
, 1)) + 63) < 127)
604 c
= (mode
== DFmode
) ? 13 : 8; /* 6/8 on VAX 9000, 16/15 on VAX 2 */
610 /* AND is special because the first operand is complemented. */
612 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
614 if ((unsigned)~INTVAL (XEXP (x
, 0)) > 63)
623 else if (mode
== SFmode
)
625 else if (mode
== DImode
)
634 if (mode
== DImode
|| mode
== DFmode
)
635 c
= 5; /* 7 on VAX 2 */
637 c
= 3; /* 4 on VAX 2 */
639 if (GET_CODE (x
) == REG
|| GET_CODE (x
) == POST_INC
)
641 return c
+ vax_address_cost (x
);
648 /* Now look inside the expression. Operands which are not registers or
649 short constants add to the cost.
651 FMT and I may have been adjusted in the switch above for instructions
652 which require special handling */
654 while (*fmt
++ == 'e')
656 register rtx op
= XEXP (x
, i
++);
657 code
= GET_CODE (op
);
659 /* A NOT is likely to be found as the first operand of an AND
660 (in which case the relevant cost is of the operand inside
661 the not) and not likely to be found anywhere else. */
663 op
= XEXP (op
, 0), code
= GET_CODE (op
);
668 if ((unsigned)INTVAL (op
) > 63 && GET_MODE (x
) != QImode
)
669 c
+= 1; /* 2 on VAX 2 */
674 c
+= 1; /* 2 on VAX 2 */
677 if (GET_MODE_CLASS (GET_MODE (op
)) == MODE_FLOAT
)
679 /* Registers are faster than floating point constants -- even
680 those constants which can be encoded in a single byte. */
681 if (vax_float_literal (op
))
684 c
+= (GET_MODE (x
) == DFmode
) ? 3 : 2;
688 if (CONST_DOUBLE_HIGH (op
) != 0
689 || (unsigned)CONST_DOUBLE_LOW (op
) > 63)
694 c
+= 1; /* 2 on VAX 2 */
695 if (GET_CODE (XEXP (op
, 0)) != REG
)
696 c
+= vax_address_cost (XEXP (op
, 0));
710 /* Additional support code for VMS target. */
712 /* Linked list of all externals that are to be emitted when optimizing
713 for the global pointer if they haven't been declared by the end of
714 the program with an appropriate .comm or initialization. */
718 struct extern_list
*next
; /* next external */
719 const char *name
; /* name of the external */
720 int size
; /* external's actual size */
721 int in_const
; /* section type flag */
722 } *extern_head
= 0, *pending_head
= 0;
724 /* Check whether NAME is already on the external definition list. If not,
725 add it to either that list or the pending definition list. */
728 vms_check_external (decl
, name
, pending
)
733 register struct extern_list
*p
, *p0
;
735 for (p
= extern_head
; p
; p
= p
->next
)
736 if (!strcmp (p
->name
, name
))
739 for (p
= pending_head
, p0
= 0; p
; p0
= p
, p
= p
->next
)
740 if (!strcmp (p
->name
, name
))
745 /* Was pending, but has now been defined; move it to other list. */
746 if (p
== pending_head
)
747 pending_head
= p
->next
;
750 p
->next
= extern_head
;
755 /* Not previously seen; create a new list entry. */
756 p
= (struct extern_list
*) xmalloc (sizeof (struct extern_list
));
761 /* Save the size and section type and link to `pending' list. */
762 p
->size
= (DECL_SIZE (decl
) == 0) ? 0 :
763 TREE_INT_CST_LOW (size_binop (CEIL_DIV_EXPR
, DECL_SIZE (decl
),
764 size_int (BITS_PER_UNIT
)));
765 p
->in_const
= (TREE_READONLY (decl
) && ! TREE_THIS_VOLATILE (decl
));
767 p
->next
= pending_head
;
772 /* Size and section type don't matter; link to `declared' list. */
773 p
->size
= p
->in_const
= 0; /* arbitrary init */
775 p
->next
= extern_head
;
782 vms_flush_pending_externals (file
)
785 register struct extern_list
*p
;
789 /* Move next pending declaration to the "done" list. */
791 pending_head
= p
->next
;
792 p
->next
= extern_head
;
795 /* Now output the actual declaration. */
800 fputs (".comm ", file
);
801 assemble_name (file
, p
->name
);
802 fprintf (file
, ",%d\n", p
->size
);
807 vms_asm_out_constructor (symbol
, priority
)
809 int priority ATTRIBUTE_UNUSED
;
811 fprintf (asm_out_file
,".globl $$PsectAttributes_NOOVR$$__gxx_init_1\n");
813 fprintf (asm_out_file
,"$$PsectAttributes_NOOVR$$__gxx_init_1:\n\t.long\t");
814 assemble_name (asm_out_file
, XSTR (symbol
, 0));
815 fputc ('\n', asm_out_file
);
819 vms_asm_out_destructor (symbol
, priority
)
821 int priority ATTRIBUTE_UNUSED
;
823 fprintf (asm_out_file
,".globl $$PsectAttributes_NOOVR$$__gxx_clean_1\n");
825 fprintf (asm_out_file
,"$$PsectAttributes_NOOVR$$__gxx_clean_1:\n\t.long\t");
826 assemble_name (asm_out_file
, XSTR (symbol
, 0));
827 fputc ('\n', asm_out_file
);
831 vms_select_section (exp
, reloc
, align
)
833 int reloc ATTRIBUTE_UNUSED
;
834 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED
;
836 if (TREE_CODE (exp
) == VAR_DECL
)
838 if (TREE_READONLY (exp
) && ! TREE_THIS_VOLATILE (exp
)
839 && DECL_INITIAL (exp
)
840 && (DECL_INITIAL (exp
) == error_mark_node
841 || TREE_CONSTANT (DECL_INITIAL (exp
))))
843 if (TREE_PUBLIC (exp
))
851 if (TREE_CODE_CLASS (TREE_CODE (exp
)) == 'c')
853 if (TREE_CODE (exp
) == STRING_CST
&& flag_writable_strings
)
860 /* Make sure that external variables are correctly addressed. Under VMS
861 there is some brain damage in the linker that requires us to do this. */
864 vms_encode_section_info (decl
, first
)
866 int first ATTRIBUTE_UNUSED
;
868 if (DECL_EXTERNAL (decl
) && TREE_PUBLIC (decl
))
869 SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl
), 0)) = 1;
872 /* This is how to output a command to make the user-level label named NAME
873 defined for reference from other files. */
875 vms_globalize_label (stream
, name
)
879 default_globalize_label (stream
, name
);
880 vms_check_external (NULL_TREE
, name
, 0);
882 #endif /* VMS_TARGET */
884 /* Additional support code for VMS host. */
885 /* ??? This should really be in libiberty; vax.c is a target file. */
886 #ifdef QSORT_WORKAROUND
888 Do not use VAXCRTL's qsort() due to a severe bug: once you've
889 sorted something which has a size that's an exact multiple of 4
890 and is longword aligned, you cannot safely sort anything which
891 is either not a multiple of 4 in size or not longword aligned.
892 A static "move-by-longword" optimization flag inside qsort() is
893 never reset. This is known to affect VMS V4.6 through VMS V5.5-1,
894 and was finally fixed in VMS V5.5-2.
896 In this work-around an insertion sort is used for simplicity.
897 The qsort code from glibc should probably be used instead.
900 not_qsort (array
, count
, size
, compare
)
902 unsigned count
, size
;
906 if (size
== sizeof (short))
909 register short *next
, *prev
;
910 short tmp
, *base
= array
;
912 for (next
= base
, i
= count
- 1; i
> 0; i
--)
915 if ((*compare
)(next
, prev
) < 0)
918 do *(prev
+ 1) = *prev
;
919 while (--prev
>= base
? (*compare
)(&tmp
, prev
) < 0 : 0);
924 else if (size
== sizeof (long))
927 register long *next
, *prev
;
928 long tmp
, *base
= array
;
930 for (next
= base
, i
= count
- 1; i
> 0; i
--)
933 if ((*compare
)(next
, prev
) < 0)
936 do *(prev
+ 1) = *prev
;
937 while (--prev
>= base
? (*compare
)(&tmp
, prev
) < 0 : 0);
942 else /* arbitrary size */
945 register char *next
, *prev
, *tmp
= alloca (size
), *base
= array
;
947 for (next
= base
, i
= count
- 1; i
> 0; i
--)
948 { /* count-1 forward iterations */
949 prev
= next
, next
+= size
; /* increment front pointer */
950 if ((*compare
)(next
, prev
) < 0)
951 { /* found element out of order; move others up then re-insert */
952 memcpy (tmp
, next
, size
); /* save smaller element */
953 do { memcpy (prev
+ size
, prev
, size
); /* move larger elem. up */
954 prev
-= size
; /* decrement back pointer */
955 } while (prev
>= base
? (*compare
)(tmp
, prev
) < 0 : 0);
956 memcpy (prev
+ size
, tmp
, size
); /* restore small element */
966 #endif /* QSORT_WORKAROUND */
968 /* Return 1 if insn A follows B. */
976 for (p
= a
; p
!= b
; p
= NEXT_INSN (p
))
983 /* Returns 1 if we know operand OP was 0 before INSN. */
986 reg_was_0_p (insn
, op
)
991 return ((link
= find_reg_note (insn
, REG_WAS_0
, 0))
992 /* Make sure the insn that stored the 0 is still present
993 and doesn't follow INSN in the insn sequence. */
994 && ! INSN_DELETED_P (XEXP (link
, 0))
995 && GET_CODE (XEXP (link
, 0)) != NOTE
996 && ! follows_p (XEXP (link
, 0), insn
)
997 /* Make sure cross jumping didn't happen here. */
998 && no_labels_between_p (XEXP (link
, 0), insn
)
999 /* Make sure the reg hasn't been clobbered. */
1000 && ! reg_set_between_p (op
, XEXP (link
, 0), insn
));
1004 vax_output_mi_thunk (file
, thunk
, delta
, vcall_offset
, function
)
1006 tree thunk ATTRIBUTE_UNUSED
;
1007 HOST_WIDE_INT delta
;
1008 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED
;
1011 fprintf (file
, "\t.word 0x0ffc\n");
1012 fprintf (file
, "\taddl2 $");
1013 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, delta
);
1014 asm_fprintf (file
, ",4(%Rap)\n");
1015 fprintf (file
, "\tjmp ");
1016 assemble_name (file
, XSTR (XEXP (DECL_RTL (function
), 0), 0));
1017 fprintf (file
, "+2\n");