OSDN Git Service

70c63e4821b1dde2f93d77f331f01376da0513db
[pf3gnuchains/gcc-fork.git] / gcc / config / vax / vax.c
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.
4
5 This file is part of GCC.
6
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.
11
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.
16
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.  */
21
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"
43
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 *));
52 \f
53 /* Initialize the GCC target structure.  */
54 #undef TARGET_ASM_ALIGNED_HI_OP
55 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
56
57 #undef TARGET_ASM_FUNCTION_PROLOGUE
58 #define TARGET_ASM_FUNCTION_PROLOGUE vax_output_function_prologue
59
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
64
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
69
70 struct gcc_target targetm = TARGET_INITIALIZER;
71 \f
72 /* Set global variables as needed for the options enabled.  */
73
74 void
75 override_options ()
76 {
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);
82 }
83
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.
87
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.  */
92
93 static void
94 vax_output_function_prologue (file, size)
95      FILE * file;
96      HOST_WIDE_INT size;
97 {
98   register int regno;
99   register int mask = 0;
100
101   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
102     if (regs_ever_live[regno] && !call_used_regs[regno])
103       mask |= 1 << regno;
104
105   fprintf (file, "\t.word 0x%x\n", mask);
106
107   if (dwarf2out_do_frame ())
108     {
109       const char *label = dwarf2out_cfi_label ();
110       int offset = 0;
111
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);
115
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));
120     }
121
122   size -= STARTING_FRAME_OFFSET;
123   if (size >= 64)
124     asm_fprintf (file, "\tmovab %d(%Rsp),%Rsp\n", -size);
125   else if (size)
126     asm_fprintf (file, "\tsubl2 $%d,%Rsp\n", size);
127 }
128
129 /* This is like nonimmediate_operand with a restriction on the type of MEM.  */
130
131 void
132 split_quadword_operands (operands, low, n)
133      rtx *operands, *low;
134      int n ATTRIBUTE_UNUSED;
135 {
136   int i;
137   /* Split operands.  */
138
139   low[0] = low[1] = low[2] = 0;
140   for (i = 0; i < 3; i++)
141     {
142       if (low[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))
146         {
147           rtx addr = XEXP (operands[i], 0);
148           operands[i] = low[i] = gen_rtx_MEM (SImode, addr);
149           if (which_alternative == 0 && i == 0)
150             {
151               addr = XEXP (operands[i], 0);
152               operands[i+1] = low[i+1] = gen_rtx_MEM (SImode, addr);
153             }
154         }
155       else
156         {
157           low[i] = operand_subword (operands[i], 0, 0, DImode);
158           operands[i] = operand_subword (operands[i], 1, 0, DImode);
159         }
160     }
161 }
162 \f
163 void
164 print_operand_address (file, addr)
165      FILE *file;
166      register rtx addr;
167 {
168   register rtx reg1, breg, ireg;
169   rtx offset;
170
171  retry:
172   switch (GET_CODE (addr))
173     {
174     case MEM:
175       fprintf (file, "*");
176       addr = XEXP (addr, 0);
177       goto retry;
178
179     case REG:
180       fprintf (file, "(%s)", reg_names[REGNO (addr)]);
181       break;
182
183     case PRE_DEC:
184       fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
185       break;
186
187     case POST_INC:
188       fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
189       break;
190
191     case PLUS:
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.
195
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,
199          put it into REG1.  */
200
201       reg1 = 0; ireg = 0; breg = 0; offset = 0;
202
203       if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
204           || GET_CODE (XEXP (addr, 0)) == MEM)
205         {
206           offset = XEXP (addr, 0);
207           addr = XEXP (addr, 1);
208         }
209       else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
210                || GET_CODE (XEXP (addr, 1)) == MEM)
211         {
212           offset = XEXP (addr, 1);
213           addr = XEXP (addr, 0);
214         }
215       else if (GET_CODE (XEXP (addr, 1)) == MULT)
216         {
217           ireg = XEXP (addr, 1);
218           addr = XEXP (addr, 0);
219         }
220       else if (GET_CODE (XEXP (addr, 0)) == MULT)
221         {
222           ireg = XEXP (addr, 0);
223           addr = XEXP (addr, 1);
224         }
225       else if (GET_CODE (XEXP (addr, 1)) == REG)
226         {
227           reg1 = XEXP (addr, 1);
228           addr = XEXP (addr, 0);
229         }
230       else if (GET_CODE (XEXP (addr, 0)) == REG)
231         {
232           reg1 = XEXP (addr, 0);
233           addr = XEXP (addr, 1);
234         }
235       else
236         abort ();
237
238       if (GET_CODE (addr) == REG)
239         {
240           if (reg1)
241             ireg = addr;
242           else
243             reg1 = addr;
244         }
245       else if (GET_CODE (addr) == MULT)
246         ireg = addr;
247       else if (GET_CODE (addr) == PLUS)
248         {
249           if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
250               || GET_CODE (XEXP (addr, 0)) == MEM)
251             {
252               if (offset)
253                 {
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)));
258                   else
259                     abort ();
260                 }
261               offset = XEXP (addr, 0);
262             }
263           else if (GET_CODE (XEXP (addr, 0)) == REG)
264             {
265               if (reg1)
266                 ireg = reg1, breg = XEXP (addr, 0), reg1 = 0;
267               else
268                 reg1 = XEXP (addr, 0);
269             }
270           else if (GET_CODE (XEXP (addr, 0)) == MULT)
271             {
272               if (ireg)
273                 abort ();
274               ireg = XEXP (addr, 0);
275             }
276           else
277             abort ();
278
279           if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
280               || GET_CODE (XEXP (addr, 1)) == MEM)
281             {
282               if (offset)
283                 {
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)));
288                   else
289                     abort ();
290                 }
291               offset = XEXP (addr, 1);
292             }
293           else if (GET_CODE (XEXP (addr, 1)) == REG)
294             {
295               if (reg1)
296                 ireg = reg1, breg = XEXP (addr, 1), reg1 = 0;
297               else
298                 reg1 = XEXP (addr, 1);
299             }
300           else if (GET_CODE (XEXP (addr, 1)) == MULT)
301             {
302               if (ireg)
303                 abort ();
304               ireg = XEXP (addr, 1);
305             }
306           else
307             abort ();
308         }
309       else
310         abort ();
311
312       /* If REG1 is nonzero, figure out if it is a base or index register.  */
313       if (reg1)
314         {
315           if (breg != 0 || (offset && GET_CODE (offset) == MEM))
316             {
317               if (ireg)
318                 abort ();
319               ireg = reg1;
320             }
321           else
322             breg = reg1;
323         }
324
325       if (offset != 0)
326         output_address (offset);
327
328       if (breg != 0)
329         fprintf (file, "(%s)", reg_names[REGNO (breg)]);
330
331       if (ireg != 0)
332         {
333           if (GET_CODE (ireg) == MULT)
334             ireg = XEXP (ireg, 0);
335           if (GET_CODE (ireg) != REG)
336             abort ();
337           fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
338         }
339       break;
340
341     default:
342       output_addr_const (file, addr);
343     }
344 }
345 \f
346 const char *
347 rev_cond_name (op)
348      rtx op;
349 {
350   switch (GET_CODE (op))
351     {
352     case EQ:
353       return "neq";
354     case NE:
355       return "eql";
356     case LT:
357       return "geq";
358     case LE:
359       return "gtr";
360     case GT:
361       return "leq";
362     case GE:
363       return "lss";
364     case LTU:
365       return "gequ";
366     case LEU:
367       return "gtru";
368     case GTU:
369       return "lequ";
370     case GEU:
371       return "lssu";
372
373     default:
374       abort ();
375     }
376 }
377
378 int
379 vax_float_literal(c)
380     register rtx c;
381 {
382   register enum machine_mode mode;
383   REAL_VALUE_TYPE r, s;
384   int i;
385
386   if (GET_CODE (c) != CONST_DOUBLE)
387     return 0;
388
389   mode = GET_MODE (c);
390
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])
394     return 1;
395
396   REAL_VALUE_FROM_CONST_DOUBLE (r, c);
397
398   for (i = 0; i < 7; i++)
399     {
400       int x = 1 << i;
401       REAL_VALUE_FROM_INT (s, x, 0, mode);
402
403       if (REAL_VALUES_EQUAL (r, s))
404         return 1;
405       if (!exact_real_inverse (mode, &s))
406         abort ();
407       if (REAL_VALUES_EQUAL (r, s))
408         return 1;
409     }
410   return 0;
411 }
412
413
414 /* Return the cost in cycles of a memory address, relative to register
415    indirect.
416
417    Each of the following adds the indicated number of cycles:
418
419    1 - symbolic address
420    1 - pre-decrement
421    1 - indexing and/or offset(register)
422    2 - indirect */
423
424
425 static int
426 vax_address_cost_1 (addr)
427     register rtx addr;
428 {
429   int reg = 0, indexed = 0, indir = 0, offset = 0, predec = 0;
430   rtx plus_op0 = 0, plus_op1 = 0;
431  restart:
432   switch (GET_CODE (addr))
433     {
434     case PRE_DEC:
435       predec = 1;
436     case REG:
437     case SUBREG:
438     case POST_INC:
439       reg = 1;
440       break;
441     case MULT:
442       indexed = 1;      /* 2 on VAX 2 */
443       break;
444     case CONST_INT:
445       /* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */
446       if (offset == 0)
447         offset = (unsigned)(INTVAL(addr)+128) > 256;
448       break;
449     case CONST:
450     case SYMBOL_REF:
451       offset = 1;       /* 2 on VAX 2 */
452       break;
453     case LABEL_REF:     /* this is probably a byte offset from the pc */
454       if (offset == 0)
455         offset = 1;
456       break;
457     case PLUS:
458       if (plus_op0)
459         plus_op1 = XEXP (addr, 0);
460       else
461         plus_op0 = XEXP (addr, 0);
462       addr = XEXP (addr, 1);
463       goto restart;
464     case MEM:
465       indir = 2;        /* 3 on VAX 2 */
466       addr = XEXP (addr, 0);
467       goto restart;
468     default:
469       break;
470     }
471
472   /* Up to 3 things can be added in an address.  They are stored in
473      plus_op0, plus_op1, and addr.  */
474
475   if (plus_op0)
476     {
477       addr = plus_op0;
478       plus_op0 = 0;
479       goto restart;
480     }
481   if (plus_op1)
482     {
483       addr = plus_op1;
484       plus_op1 = 0;
485       goto restart;
486     }
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;
492 }
493
494 static int
495 vax_address_cost (x)
496      rtx x;
497 {
498   return (1 + (GET_CODE (x) == REG ? 0 : vax_address_cost_1 (x)));
499 }
500
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
503    other models.  */
504
505 static int
506 vax_rtx_costs_1 (x, code, outer_code)
507     register rtx x;
508     enum rtx_code code, outer_code;
509 {
510   enum machine_mode mode = GET_MODE (x);
511   register int c;
512   int i = 0;                            /* may be modified in switch */
513   const char *fmt = GET_RTX_FORMAT (code); /* may be modified in switch */
514
515   switch (code)
516     {
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).  */
522     case CONST_INT:
523       if (INTVAL (x) == 0)
524         return 0;
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)
528         return 1;
529       if (outer_code == COMPARE && INTVAL (x) == -1)
530         return 1;
531       if (outer_code == PLUS && (unsigned HOST_WIDE_INT) -INTVAL (x) <= 077)
532         return 1;
533       /* FALLTHRU */
534
535     case CONST:
536     case LABEL_REF:
537     case SYMBOL_REF:
538       return 3;
539
540     case CONST_DOUBLE:
541       if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
542         return vax_float_literal (x) ? 5 : 8;
543       else
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))
549                 ? 2 : 5);
550  
551     case POST_INC:
552       return 2;
553     case PRE_DEC:
554       return 3;
555     case MULT:
556       switch (mode)
557         {
558         case DFmode:
559           c = 16;               /* 4 on VAX 9000 */
560           break;
561         case SFmode:
562           c = 9;                /* 4 on VAX 9000, 12 on VAX 2 */
563           break;
564         case DImode:
565           c = 16;               /* 6 on VAX 9000, 28 on VAX 2 */
566           break;
567         case SImode:
568         case HImode:
569         case QImode:
570           c = 10;               /* 3-4 on VAX 9000, 20-28 on VAX 2 */
571           break;
572         default:
573           return MAX_COST;      /* Mode is not supported.  */
574         }
575       break;
576     case UDIV:
577       if (mode != SImode)
578         return MAX_COST;        /* Mode is not supported.  */
579       c = 17;
580       break;
581     case DIV:
582       if (mode == DImode)
583         c = 30; /* highly variable */
584       else if (mode == DFmode)
585         /* divide takes 28 cycles if the result is not zero, 13 otherwise */
586         c = 24;
587       else
588         c = 11;                 /* 25 on VAX 2 */
589       break;
590     case MOD:
591       c = 23;
592       break;
593     case UMOD:
594       if (mode != SImode)
595         return MAX_COST;        /* Mode is not supported.  */
596       c = 29;
597       break;
598     case FLOAT:
599       c = 6 + (mode == DFmode) + (GET_MODE (XEXP (x, 0)) != SImode);
600       /* 4 on VAX 9000 */
601       break;
602     case FIX:
603       c = 7;                    /* 17 on VAX 2 */
604       break;
605     case ASHIFT:
606     case LSHIFTRT:
607     case ASHIFTRT:
608       if (mode == DImode)
609         c = 12;
610       else
611         c = 10;                 /* 6 on VAX 9000 */
612       break;
613     case ROTATE:
614     case ROTATERT:
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 */
618       break;
619     case PLUS:
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)
624           fmt = "e";
625     case MINUS:
626       c = (mode == DFmode) ? 13 : 8;    /* 6/8 on VAX 9000, 16/15 on VAX 2 */
627     case IOR:
628     case XOR:
629       c = 3;
630       break;
631     case AND:
632       /* AND is special because the first operand is complemented.  */
633       c = 3;
634       if (GET_CODE (XEXP (x, 0)) == CONST_INT)
635         {
636           if ((unsigned)~INTVAL (XEXP (x, 0)) > 63)
637             c = 4;
638           fmt = "e";
639           i = 1;
640         }
641       break;
642     case NEG:
643       if (mode == DFmode)
644         return 9;
645       else if (mode == SFmode)
646         return 6;
647       else if (mode == DImode)
648         return 4;
649     case NOT:
650       return 2;
651     case ZERO_EXTRACT:
652     case SIGN_EXTRACT:
653       c = 15;
654       break;
655     case MEM:
656       if (mode == DImode || mode == DFmode)
657         c = 5;                          /* 7 on VAX 2 */
658       else
659         c = 3;                          /* 4 on VAX 2 */
660       x = XEXP (x, 0);
661       if (GET_CODE (x) == REG || GET_CODE (x) == POST_INC)
662         return c;
663       return c + vax_address_cost_1 (x);
664     default:
665       c = 3;
666       break;
667     }
668
669   /* Now look inside the expression.  Operands which are not registers or
670      short constants add to the cost.
671
672      FMT and I may have been adjusted in the switch above for instructions
673      which require special handling */
674
675   while (*fmt++ == 'e')
676     {
677       register rtx op = XEXP (x, i++);
678       code = GET_CODE (op);
679
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.  */
683       if (code == NOT)
684         op = XEXP (op, 0), code = GET_CODE (op);
685
686       switch (code)
687         {
688         case CONST_INT:
689           if ((unsigned)INTVAL (op) > 63 && GET_MODE (x) != QImode)
690             c += 1;             /* 2 on VAX 2 */
691           break;
692         case CONST:
693         case LABEL_REF:
694         case SYMBOL_REF:
695           c += 1;               /* 2 on VAX 2 */
696           break;
697         case CONST_DOUBLE:
698           if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT)
699             {
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))
703                 c++;
704               else
705                 c += (GET_MODE (x) == DFmode) ? 3 : 2;
706             }
707           else
708             {
709               if (CONST_DOUBLE_HIGH (op) != 0
710                   || (unsigned)CONST_DOUBLE_LOW (op) > 63)
711                 c += 2;
712             }
713           break;
714         case MEM:
715           c += 1;               /* 2 on VAX 2 */
716           if (GET_CODE (XEXP (op, 0)) != REG)
717             c += vax_address_cost_1 (XEXP (op, 0));
718           break;
719         case REG:
720         case SUBREG:
721           break;
722         default:
723           c += 1;
724           break;
725         }
726     }
727   return c;
728 }
729
730 static bool
731 vax_rtx_costs (x, code, outer_code, total)
732     rtx x;
733     int code, outer_code;
734     int *total;
735 {
736   *total = vax_rtx_costs_1 (x, code, outer_code);
737   return true;
738 }
739 \f
740 /* Return 1 if insn A follows B.  */
741
742 static int
743 follows_p (a, b)
744      rtx a, b;
745 {
746   register rtx p;
747
748   for (p = a; p != b; p = NEXT_INSN (p))
749     if (! p)
750       return 1;
751
752   return 0;
753 }
754
755 /* Returns 1 if we know operand OP was 0 before INSN.  */
756
757 int
758 reg_was_0_p (insn, op)
759      rtx insn, op;
760 {
761   rtx link;
762
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));
773 }
774
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
780 */
781
782 static void
783 vax_output_mi_thunk (file, thunk, delta, vcall_offset, function)
784      FILE *file;
785      tree thunk ATTRIBUTE_UNUSED;
786      HOST_WIDE_INT delta;
787      HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
788      tree function;
789 {
790   fprintf (file, "\t.word 0x0ffc\n\taddl2 $" HOST_WIDE_INT_PRINT_DEC, delta);
791   asm_fprintf (file, ",4(%Rap)\n");
792   fprintf (file, "\tjmp ");                                             
793   assemble_name (file,  XSTR (XEXP (DECL_RTL (function), 0), 0));       
794   fprintf (file, "+2\n");                                               
795 }