* target.h (asm_out.file_start, file_start_app_off,
[official-gcc.git] / gcc / config / vax / vax.c
blobfea970e0eda621618b3355f61b53ad4b0eeb7c48
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)
10 any later version.
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. */
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "rtl.h"
27 #include "tree.h"
28 #include "regs.h"
29 #include "hard-reg-set.h"
30 #include "real.h"
31 #include "insn-config.h"
32 #include "conditions.h"
33 #include "function.h"
34 #include "output.h"
35 #include "insn-attr.h"
36 #include "recog.h"
37 #include "expr.h"
38 #include "flags.h"
39 #include "debug.h"
40 #include "tm_p.h"
41 #include "target.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_file_start PARAMS ((void));
47 static void vax_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
48 HOST_WIDE_INT, tree));
49 static int vax_address_cost_1 PARAMS ((rtx));
50 static int vax_address_cost PARAMS ((rtx));
51 static int vax_rtx_costs_1 PARAMS ((rtx, enum rtx_code, enum rtx_code));
52 static bool vax_rtx_costs PARAMS ((rtx, int, int, int *));
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
61 #undef TARGET_ASM_FILE_START
62 #define TARGET_ASM_FILE_START vax_file_start
63 #undef TARGET_ASM_FILE_START_APP_OFF
64 #define TARGET_ASM_FILE_START_APP_OFF true
66 #undef TARGET_ASM_OUTPUT_MI_THUNK
67 #define TARGET_ASM_OUTPUT_MI_THUNK vax_output_mi_thunk
68 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
69 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
71 #undef TARGET_RTX_COSTS
72 #define TARGET_RTX_COSTS vax_rtx_costs
73 #undef TARGET_ADDRESS_COST
74 #define TARGET_ADDRESS_COST vax_address_cost
76 struct gcc_target targetm = TARGET_INITIALIZER;
78 /* Set global variables as needed for the options enabled. */
80 void
81 override_options ()
83 /* We're VAX floating point, not IEEE floating point. */
84 memset (real_format_for_mode, 0, sizeof real_format_for_mode);
85 real_format_for_mode[SFmode - QFmode] = &vax_f_format;
86 real_format_for_mode[DFmode - QFmode]
87 = (TARGET_G_FLOAT ? &vax_g_format : &vax_d_format);
90 /* Generate the assembly code for function entry. FILE is a stdio
91 stream to output the code to. SIZE is an int: how many units of
92 temporary storage to allocate.
94 Refer to the array `regs_ever_live' to determine which registers to
95 save; `regs_ever_live[I]' is nonzero if register number I is ever
96 used in the function. This function is responsible for knowing
97 which registers should not be saved even if used. */
99 static void
100 vax_output_function_prologue (file, size)
101 FILE * file;
102 HOST_WIDE_INT size;
104 register int regno;
105 register int mask = 0;
107 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
108 if (regs_ever_live[regno] && !call_used_regs[regno])
109 mask |= 1 << regno;
111 fprintf (file, "\t.word 0x%x\n", mask);
113 if (dwarf2out_do_frame ())
115 const char *label = dwarf2out_cfi_label ();
116 int offset = 0;
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;
129 if (size >= 64)
130 asm_fprintf (file, "\tmovab %wd(%Rsp),%Rsp\n", -size);
131 else if (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. */
138 static void
139 vax_file_start ()
141 default_file_start ();
143 if (write_symbols == DBX_DEBUG)
144 fprintf (asm_out_file, "___vax_%c_doubles:\n", ASM_DOUBLE_CHAR);
147 /* This is like nonimmediate_operand with a restriction on the type of MEM. */
149 void
150 split_quadword_operands (operands, low, n)
151 rtx *operands, *low;
152 int n ATTRIBUTE_UNUSED;
154 int i;
155 /* Split operands. */
157 low[0] = low[1] = low[2] = 0;
158 for (i = 0; i < 3; i++)
160 if (low[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);
173 else
175 low[i] = operand_subword (operands[i], 0, 0, DImode);
176 operands[i] = operand_subword (operands[i], 1, 0, DImode);
181 void
182 print_operand_address (file, addr)
183 FILE *file;
184 register rtx addr;
186 register rtx reg1, breg, ireg;
187 rtx offset;
189 retry:
190 switch (GET_CODE (addr))
192 case MEM:
193 fprintf (file, "*");
194 addr = XEXP (addr, 0);
195 goto retry;
197 case REG:
198 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
199 break;
201 case PRE_DEC:
202 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
203 break;
205 case POST_INC:
206 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
207 break;
209 case PLUS:
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,
217 put it into REG1. */
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);
253 else
254 abort ();
256 if (GET_CODE (addr) == REG)
258 if (reg1)
259 ireg = addr;
260 else
261 reg1 = addr;
263 else if (GET_CODE (addr) == MULT)
264 ireg = addr;
265 else if (GET_CODE (addr) == PLUS)
267 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
268 || GET_CODE (XEXP (addr, 0)) == MEM)
270 if (offset)
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)));
276 else
277 abort ();
279 offset = XEXP (addr, 0);
281 else if (GET_CODE (XEXP (addr, 0)) == REG)
283 if (reg1)
284 ireg = reg1, breg = XEXP (addr, 0), reg1 = 0;
285 else
286 reg1 = XEXP (addr, 0);
288 else if (GET_CODE (XEXP (addr, 0)) == MULT)
290 if (ireg)
291 abort ();
292 ireg = XEXP (addr, 0);
294 else
295 abort ();
297 if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
298 || GET_CODE (XEXP (addr, 1)) == MEM)
300 if (offset)
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)));
306 else
307 abort ();
309 offset = XEXP (addr, 1);
311 else if (GET_CODE (XEXP (addr, 1)) == REG)
313 if (reg1)
314 ireg = reg1, breg = XEXP (addr, 1), reg1 = 0;
315 else
316 reg1 = XEXP (addr, 1);
318 else if (GET_CODE (XEXP (addr, 1)) == MULT)
320 if (ireg)
321 abort ();
322 ireg = XEXP (addr, 1);
324 else
325 abort ();
327 else
328 abort ();
330 /* If REG1 is nonzero, figure out if it is a base or index register. */
331 if (reg1)
333 if (breg != 0 || (offset && GET_CODE (offset) == MEM))
335 if (ireg)
336 abort ();
337 ireg = reg1;
339 else
340 breg = reg1;
343 if (offset != 0)
344 output_address (offset);
346 if (breg != 0)
347 fprintf (file, "(%s)", reg_names[REGNO (breg)]);
349 if (ireg != 0)
351 if (GET_CODE (ireg) == MULT)
352 ireg = XEXP (ireg, 0);
353 if (GET_CODE (ireg) != REG)
354 abort ();
355 fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
357 break;
359 default:
360 output_addr_const (file, addr);
364 const char *
365 rev_cond_name (op)
366 rtx op;
368 switch (GET_CODE (op))
370 case EQ:
371 return "neq";
372 case NE:
373 return "eql";
374 case LT:
375 return "geq";
376 case LE:
377 return "gtr";
378 case GT:
379 return "leq";
380 case GE:
381 return "lss";
382 case LTU:
383 return "gequ";
384 case LEU:
385 return "gtru";
386 case GTU:
387 return "lequ";
388 case GEU:
389 return "lssu";
391 default:
392 abort ();
397 vax_float_literal(c)
398 register rtx c;
400 register enum machine_mode mode;
401 REAL_VALUE_TYPE r, s;
402 int i;
404 if (GET_CODE (c) != CONST_DOUBLE)
405 return 0;
407 mode = GET_MODE (c);
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])
412 return 1;
414 REAL_VALUE_FROM_CONST_DOUBLE (r, c);
416 for (i = 0; i < 7; i++)
418 int x = 1 << i;
419 REAL_VALUE_FROM_INT (s, x, 0, mode);
421 if (REAL_VALUES_EQUAL (r, s))
422 return 1;
423 if (!exact_real_inverse (mode, &s))
424 abort ();
425 if (REAL_VALUES_EQUAL (r, s))
426 return 1;
428 return 0;
432 /* Return the cost in cycles of a memory address, relative to register
433 indirect.
435 Each of the following adds the indicated number of cycles:
437 1 - symbolic address
438 1 - pre-decrement
439 1 - indexing and/or offset(register)
440 2 - indirect */
443 static int
444 vax_address_cost_1 (addr)
445 register rtx addr;
447 int reg = 0, indexed = 0, indir = 0, offset = 0, predec = 0;
448 rtx plus_op0 = 0, plus_op1 = 0;
449 restart:
450 switch (GET_CODE (addr))
452 case PRE_DEC:
453 predec = 1;
454 case REG:
455 case SUBREG:
456 case POST_INC:
457 reg = 1;
458 break;
459 case MULT:
460 indexed = 1; /* 2 on VAX 2 */
461 break;
462 case CONST_INT:
463 /* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */
464 if (offset == 0)
465 offset = (unsigned)(INTVAL(addr)+128) > 256;
466 break;
467 case CONST:
468 case SYMBOL_REF:
469 offset = 1; /* 2 on VAX 2 */
470 break;
471 case LABEL_REF: /* this is probably a byte offset from the pc */
472 if (offset == 0)
473 offset = 1;
474 break;
475 case PLUS:
476 if (plus_op0)
477 plus_op1 = XEXP (addr, 0);
478 else
479 plus_op0 = XEXP (addr, 0);
480 addr = XEXP (addr, 1);
481 goto restart;
482 case MEM:
483 indir = 2; /* 3 on VAX 2 */
484 addr = XEXP (addr, 0);
485 goto restart;
486 default:
487 break;
490 /* Up to 3 things can be added in an address. They are stored in
491 plus_op0, plus_op1, and addr. */
493 if (plus_op0)
495 addr = plus_op0;
496 plus_op0 = 0;
497 goto restart;
499 if (plus_op1)
501 addr = plus_op1;
502 plus_op1 = 0;
503 goto restart;
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;
512 static int
513 vax_address_cost (x)
514 rtx x;
516 return (1 + (GET_CODE (x) == REG ? 0 : vax_address_cost_1 (x)));
519 /* Cost of an expression on a VAX. This version has costs tuned for the
520 CVAX chip (found in the VAX 3 series) with comments for variations on
521 other models. */
523 static int
524 vax_rtx_costs_1 (x, code, outer_code)
525 register rtx x;
526 enum rtx_code code, outer_code;
528 enum machine_mode mode = GET_MODE (x);
529 register int c;
530 int i = 0; /* may be modified in switch */
531 const char *fmt = GET_RTX_FORMAT (code); /* may be modified in switch */
533 switch (code)
535 /* On a VAX, constants from 0..63 are cheap because they can use the
536 1 byte literal constant format. compare to -1 should be made cheap
537 so that decrement-and-branch insns can be formed more easily (if
538 the value -1 is copied to a register some decrement-and-branch
539 patterns will not match). */
540 case CONST_INT:
541 if (INTVAL (x) == 0)
542 return 0;
543 if (outer_code == AND)
544 return ((unsigned HOST_WIDE_INT) ~INTVAL (x) <= 077) ? 1 : 2;
545 if ((unsigned HOST_WIDE_INT) INTVAL (x) <= 077)
546 return 1;
547 if (outer_code == COMPARE && INTVAL (x) == -1)
548 return 1;
549 if (outer_code == PLUS && (unsigned HOST_WIDE_INT) -INTVAL (x) <= 077)
550 return 1;
551 /* FALLTHRU */
553 case CONST:
554 case LABEL_REF:
555 case SYMBOL_REF:
556 return 3;
558 case CONST_DOUBLE:
559 if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
560 return vax_float_literal (x) ? 5 : 8;
561 else
562 return (((CONST_DOUBLE_HIGH (x) == 0
563 && (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (x) < 64)
564 || (outer_code == PLUS
565 && CONST_DOUBLE_HIGH (x) == -1 \
566 && (unsigned HOST_WIDE_INT)-CONST_DOUBLE_LOW (x) < 64))
567 ? 2 : 5);
569 case POST_INC:
570 return 2;
571 case PRE_DEC:
572 return 3;
573 case MULT:
574 switch (mode)
576 case DFmode:
577 c = 16; /* 4 on VAX 9000 */
578 break;
579 case SFmode:
580 c = 9; /* 4 on VAX 9000, 12 on VAX 2 */
581 break;
582 case DImode:
583 c = 16; /* 6 on VAX 9000, 28 on VAX 2 */
584 break;
585 case SImode:
586 case HImode:
587 case QImode:
588 c = 10; /* 3-4 on VAX 9000, 20-28 on VAX 2 */
589 break;
590 default:
591 return MAX_COST; /* Mode is not supported. */
593 break;
594 case UDIV:
595 if (mode != SImode)
596 return MAX_COST; /* Mode is not supported. */
597 c = 17;
598 break;
599 case DIV:
600 if (mode == DImode)
601 c = 30; /* highly variable */
602 else if (mode == DFmode)
603 /* divide takes 28 cycles if the result is not zero, 13 otherwise */
604 c = 24;
605 else
606 c = 11; /* 25 on VAX 2 */
607 break;
608 case MOD:
609 c = 23;
610 break;
611 case UMOD:
612 if (mode != SImode)
613 return MAX_COST; /* Mode is not supported. */
614 c = 29;
615 break;
616 case FLOAT:
617 c = 6 + (mode == DFmode) + (GET_MODE (XEXP (x, 0)) != SImode);
618 /* 4 on VAX 9000 */
619 break;
620 case FIX:
621 c = 7; /* 17 on VAX 2 */
622 break;
623 case ASHIFT:
624 case LSHIFTRT:
625 case ASHIFTRT:
626 if (mode == DImode)
627 c = 12;
628 else
629 c = 10; /* 6 on VAX 9000 */
630 break;
631 case ROTATE:
632 case ROTATERT:
633 c = 6; /* 5 on VAX 2, 4 on VAX 9000 */
634 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
635 fmt = "e"; /* all constant rotate counts are short */
636 break;
637 case PLUS:
638 /* Check for small negative integer operand: subl2 can be used with
639 a short positive constant instead. */
640 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
641 if ((unsigned)(INTVAL (XEXP (x, 1)) + 63) < 127)
642 fmt = "e";
643 case MINUS:
644 c = (mode == DFmode) ? 13 : 8; /* 6/8 on VAX 9000, 16/15 on VAX 2 */
645 case IOR:
646 case XOR:
647 c = 3;
648 break;
649 case AND:
650 /* AND is special because the first operand is complemented. */
651 c = 3;
652 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
654 if ((unsigned)~INTVAL (XEXP (x, 0)) > 63)
655 c = 4;
656 fmt = "e";
657 i = 1;
659 break;
660 case NEG:
661 if (mode == DFmode)
662 return 9;
663 else if (mode == SFmode)
664 return 6;
665 else if (mode == DImode)
666 return 4;
667 case NOT:
668 return 2;
669 case ZERO_EXTRACT:
670 case SIGN_EXTRACT:
671 c = 15;
672 break;
673 case MEM:
674 if (mode == DImode || mode == DFmode)
675 c = 5; /* 7 on VAX 2 */
676 else
677 c = 3; /* 4 on VAX 2 */
678 x = XEXP (x, 0);
679 if (GET_CODE (x) == REG || GET_CODE (x) == POST_INC)
680 return c;
681 return c + vax_address_cost_1 (x);
682 default:
683 c = 3;
684 break;
687 /* Now look inside the expression. Operands which are not registers or
688 short constants add to the cost.
690 FMT and I may have been adjusted in the switch above for instructions
691 which require special handling */
693 while (*fmt++ == 'e')
695 register rtx op = XEXP (x, i++);
696 code = GET_CODE (op);
698 /* A NOT is likely to be found as the first operand of an AND
699 (in which case the relevant cost is of the operand inside
700 the not) and not likely to be found anywhere else. */
701 if (code == NOT)
702 op = XEXP (op, 0), code = GET_CODE (op);
704 switch (code)
706 case CONST_INT:
707 if ((unsigned)INTVAL (op) > 63 && GET_MODE (x) != QImode)
708 c += 1; /* 2 on VAX 2 */
709 break;
710 case CONST:
711 case LABEL_REF:
712 case SYMBOL_REF:
713 c += 1; /* 2 on VAX 2 */
714 break;
715 case CONST_DOUBLE:
716 if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT)
718 /* Registers are faster than floating point constants -- even
719 those constants which can be encoded in a single byte. */
720 if (vax_float_literal (op))
721 c++;
722 else
723 c += (GET_MODE (x) == DFmode) ? 3 : 2;
725 else
727 if (CONST_DOUBLE_HIGH (op) != 0
728 || (unsigned)CONST_DOUBLE_LOW (op) > 63)
729 c += 2;
731 break;
732 case MEM:
733 c += 1; /* 2 on VAX 2 */
734 if (GET_CODE (XEXP (op, 0)) != REG)
735 c += vax_address_cost_1 (XEXP (op, 0));
736 break;
737 case REG:
738 case SUBREG:
739 break;
740 default:
741 c += 1;
742 break;
745 return c;
748 static bool
749 vax_rtx_costs (x, code, outer_code, total)
750 rtx x;
751 int code, outer_code;
752 int *total;
754 *total = vax_rtx_costs_1 (x, code, outer_code);
755 return true;
758 /* Return 1 if insn A follows B. */
760 static int
761 follows_p (a, b)
762 rtx a, b;
764 register rtx p;
766 for (p = a; p != b; p = NEXT_INSN (p))
767 if (! p)
768 return 1;
770 return 0;
773 /* Returns 1 if we know operand OP was 0 before INSN. */
776 reg_was_0_p (insn, op)
777 rtx insn, op;
779 rtx link;
781 return ((link = find_reg_note (insn, REG_WAS_0, 0))
782 /* Make sure the insn that stored the 0 is still present
783 and doesn't follow INSN in the insn sequence. */
784 && ! INSN_DELETED_P (XEXP (link, 0))
785 && GET_CODE (XEXP (link, 0)) != NOTE
786 && ! follows_p (XEXP (link, 0), insn)
787 /* Make sure cross jumping didn't happen here. */
788 && no_labels_between_p (XEXP (link, 0), insn)
789 /* Make sure the reg hasn't been clobbered. */
790 && ! reg_set_between_p (op, XEXP (link, 0), insn));
793 /* Output code to add DELTA to the first argument, and then jump to FUNCTION.
794 Used for C++ multiple inheritance.
795 .mask ^m<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11> #conservative entry mask
796 addl2 $DELTA, 4(ap) #adjust first argument
797 jmp FUNCTION+2 #jump beyond FUNCTION's entry mask
800 static void
801 vax_output_mi_thunk (file, thunk, delta, vcall_offset, function)
802 FILE *file;
803 tree thunk ATTRIBUTE_UNUSED;
804 HOST_WIDE_INT delta;
805 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
806 tree function;
808 fprintf (file, "\t.word 0x0ffc\n\taddl2 $" HOST_WIDE_INT_PRINT_DEC, delta);
809 asm_fprintf (file, ",4(%Rap)\n");
810 fprintf (file, "\tjmp ");
811 assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
812 fprintf (file, "+2\n");