]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/vax/vax.c
* Makefile.in (BUILD_RTL): Replace $(BUILD_PREFIX)insn-modes.o
[thirdparty/gcc.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 "optabs.h"
39 #include "flags.h"
40 #include "debug.h"
41 #include "tm_p.h"
42 #include "target.h"
43 #include "target-def.h"
44
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,
49 HOST_WIDE_INT, tree);
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 *);
54 \f
55 /* Initialize the GCC target structure. */
56 #undef TARGET_ASM_ALIGNED_HI_OP
57 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
58
59 #undef TARGET_ASM_FUNCTION_PROLOGUE
60 #define TARGET_ASM_FUNCTION_PROLOGUE vax_output_function_prologue
61
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
66
67 #undef TARGET_INIT_LIBFUNCS
68 #define TARGET_INIT_LIBFUNCS vax_init_libfuncs
69
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
74
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
79
80 struct gcc_target targetm = TARGET_INITIALIZER;
81 \f
82 /* Set global variables as needed for the options enabled. */
83
84 void
85 override_options (void)
86 {
87 /* We're VAX floating point, not IEEE floating point. */
88 if (TARGET_G_FLOAT)
89 REAL_MODE_FORMAT (DFmode) = &vax_g_format;
90 }
91
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.
95
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. */
100
101 static void
102 vax_output_function_prologue (FILE * file, HOST_WIDE_INT size)
103 {
104 register int regno;
105 register int mask = 0;
106
107 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
108 if (regs_ever_live[regno] && !call_used_regs[regno])
109 mask |= 1 << regno;
110
111 fprintf (file, "\t.word 0x%x\n", mask);
112
113 if (dwarf2out_do_frame ())
114 {
115 const char *label = dwarf2out_cfi_label ();
116 int offset = 0;
117
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);
121
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));
126 }
127
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);
133 }
134
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 (void)
140 {
141 default_file_start ();
142
143 if (write_symbols == DBX_DEBUG)
144 fprintf (asm_out_file, "___vax_%c_doubles:\n", ASM_DOUBLE_CHAR);
145 }
146
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. */
150
151 static void
152 vax_init_libfuncs (void)
153 {
154 set_optab_libfunc (udiv_optab, SImode, TARGET_ELF ? "*__udiv" : "*udiv");
155 set_optab_libfunc (umod_optab, SImode, TARGET_ELF ? "*__umod" : "*umod");
156 }
157
158 /* This is like nonimmediate_operand with a restriction on the type of MEM. */
159
160 void
161 split_quadword_operands (rtx * operands, rtx * low, int n ATTRIBUTE_UNUSED)
162 {
163 int i;
164 /* Split operands. */
165
166 low[0] = low[1] = low[2] = 0;
167 for (i = 0; i < 3; i++)
168 {
169 if (low[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))
173 {
174 rtx addr = XEXP (operands[i], 0);
175 operands[i] = low[i] = gen_rtx_MEM (SImode, addr);
176 if (which_alternative == 0 && i == 0)
177 {
178 addr = XEXP (operands[i], 0);
179 operands[i+1] = low[i+1] = gen_rtx_MEM (SImode, addr);
180 }
181 }
182 else
183 {
184 low[i] = operand_subword (operands[i], 0, 0, DImode);
185 operands[i] = operand_subword (operands[i], 1, 0, DImode);
186 }
187 }
188 }
189 \f
190 void
191 print_operand_address (FILE * file, register rtx addr)
192 {
193 register rtx reg1, breg, ireg;
194 rtx offset;
195
196 retry:
197 switch (GET_CODE (addr))
198 {
199 case MEM:
200 fprintf (file, "*");
201 addr = XEXP (addr, 0);
202 goto retry;
203
204 case REG:
205 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
206 break;
207
208 case PRE_DEC:
209 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
210 break;
211
212 case POST_INC:
213 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
214 break;
215
216 case PLUS:
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.
220
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,
224 put it into REG1. */
225
226 reg1 = 0; ireg = 0; breg = 0; offset = 0;
227
228 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
229 || GET_CODE (XEXP (addr, 0)) == MEM)
230 {
231 offset = XEXP (addr, 0);
232 addr = XEXP (addr, 1);
233 }
234 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
235 || GET_CODE (XEXP (addr, 1)) == MEM)
236 {
237 offset = XEXP (addr, 1);
238 addr = XEXP (addr, 0);
239 }
240 else if (GET_CODE (XEXP (addr, 1)) == MULT)
241 {
242 ireg = XEXP (addr, 1);
243 addr = XEXP (addr, 0);
244 }
245 else if (GET_CODE (XEXP (addr, 0)) == MULT)
246 {
247 ireg = XEXP (addr, 0);
248 addr = XEXP (addr, 1);
249 }
250 else if (GET_CODE (XEXP (addr, 1)) == REG)
251 {
252 reg1 = XEXP (addr, 1);
253 addr = XEXP (addr, 0);
254 }
255 else if (GET_CODE (XEXP (addr, 0)) == REG)
256 {
257 reg1 = XEXP (addr, 0);
258 addr = XEXP (addr, 1);
259 }
260 else
261 abort ();
262
263 if (GET_CODE (addr) == REG)
264 {
265 if (reg1)
266 ireg = addr;
267 else
268 reg1 = addr;
269 }
270 else if (GET_CODE (addr) == MULT)
271 ireg = addr;
272 else if (GET_CODE (addr) == PLUS)
273 {
274 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
275 || GET_CODE (XEXP (addr, 0)) == MEM)
276 {
277 if (offset)
278 {
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)));
283 else
284 abort ();
285 }
286 offset = XEXP (addr, 0);
287 }
288 else if (GET_CODE (XEXP (addr, 0)) == REG)
289 {
290 if (reg1)
291 ireg = reg1, breg = XEXP (addr, 0), reg1 = 0;
292 else
293 reg1 = XEXP (addr, 0);
294 }
295 else if (GET_CODE (XEXP (addr, 0)) == MULT)
296 {
297 if (ireg)
298 abort ();
299 ireg = XEXP (addr, 0);
300 }
301 else
302 abort ();
303
304 if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
305 || GET_CODE (XEXP (addr, 1)) == MEM)
306 {
307 if (offset)
308 {
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)));
313 else
314 abort ();
315 }
316 offset = XEXP (addr, 1);
317 }
318 else if (GET_CODE (XEXP (addr, 1)) == REG)
319 {
320 if (reg1)
321 ireg = reg1, breg = XEXP (addr, 1), reg1 = 0;
322 else
323 reg1 = XEXP (addr, 1);
324 }
325 else if (GET_CODE (XEXP (addr, 1)) == MULT)
326 {
327 if (ireg)
328 abort ();
329 ireg = XEXP (addr, 1);
330 }
331 else
332 abort ();
333 }
334 else
335 abort ();
336
337 /* If REG1 is nonzero, figure out if it is a base or index register. */
338 if (reg1)
339 {
340 if (breg != 0 || (offset && GET_CODE (offset) == MEM))
341 {
342 if (ireg)
343 abort ();
344 ireg = reg1;
345 }
346 else
347 breg = reg1;
348 }
349
350 if (offset != 0)
351 output_address (offset);
352
353 if (breg != 0)
354 fprintf (file, "(%s)", reg_names[REGNO (breg)]);
355
356 if (ireg != 0)
357 {
358 if (GET_CODE (ireg) == MULT)
359 ireg = XEXP (ireg, 0);
360 if (GET_CODE (ireg) != REG)
361 abort ();
362 fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
363 }
364 break;
365
366 default:
367 output_addr_const (file, addr);
368 }
369 }
370 \f
371 const char *
372 rev_cond_name (rtx op)
373 {
374 switch (GET_CODE (op))
375 {
376 case EQ:
377 return "neq";
378 case NE:
379 return "eql";
380 case LT:
381 return "geq";
382 case LE:
383 return "gtr";
384 case GT:
385 return "leq";
386 case GE:
387 return "lss";
388 case LTU:
389 return "gequ";
390 case LEU:
391 return "gtru";
392 case GTU:
393 return "lequ";
394 case GEU:
395 return "lssu";
396
397 default:
398 abort ();
399 }
400 }
401
402 int
403 vax_float_literal(register rtx c)
404 {
405 register enum machine_mode mode;
406 REAL_VALUE_TYPE r, s;
407 int i;
408
409 if (GET_CODE (c) != CONST_DOUBLE)
410 return 0;
411
412 mode = GET_MODE (c);
413
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])
417 return 1;
418
419 REAL_VALUE_FROM_CONST_DOUBLE (r, c);
420
421 for (i = 0; i < 7; i++)
422 {
423 int x = 1 << i;
424 REAL_VALUE_FROM_INT (s, x, 0, mode);
425
426 if (REAL_VALUES_EQUAL (r, s))
427 return 1;
428 if (!exact_real_inverse (mode, &s))
429 abort ();
430 if (REAL_VALUES_EQUAL (r, s))
431 return 1;
432 }
433 return 0;
434 }
435
436
437 /* Return the cost in cycles of a memory address, relative to register
438 indirect.
439
440 Each of the following adds the indicated number of cycles:
441
442 1 - symbolic address
443 1 - pre-decrement
444 1 - indexing and/or offset(register)
445 2 - indirect */
446
447
448 static int
449 vax_address_cost_1 (register rtx addr)
450 {
451 int reg = 0, indexed = 0, indir = 0, offset = 0, predec = 0;
452 rtx plus_op0 = 0, plus_op1 = 0;
453 restart:
454 switch (GET_CODE (addr))
455 {
456 case PRE_DEC:
457 predec = 1;
458 case REG:
459 case SUBREG:
460 case POST_INC:
461 reg = 1;
462 break;
463 case MULT:
464 indexed = 1; /* 2 on VAX 2 */
465 break;
466 case CONST_INT:
467 /* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */
468 if (offset == 0)
469 offset = (unsigned)(INTVAL(addr)+128) > 256;
470 break;
471 case CONST:
472 case SYMBOL_REF:
473 offset = 1; /* 2 on VAX 2 */
474 break;
475 case LABEL_REF: /* this is probably a byte offset from the pc */
476 if (offset == 0)
477 offset = 1;
478 break;
479 case PLUS:
480 if (plus_op0)
481 plus_op1 = XEXP (addr, 0);
482 else
483 plus_op0 = XEXP (addr, 0);
484 addr = XEXP (addr, 1);
485 goto restart;
486 case MEM:
487 indir = 2; /* 3 on VAX 2 */
488 addr = XEXP (addr, 0);
489 goto restart;
490 default:
491 break;
492 }
493
494 /* Up to 3 things can be added in an address. They are stored in
495 plus_op0, plus_op1, and addr. */
496
497 if (plus_op0)
498 {
499 addr = plus_op0;
500 plus_op0 = 0;
501 goto restart;
502 }
503 if (plus_op1)
504 {
505 addr = plus_op1;
506 plus_op1 = 0;
507 goto restart;
508 }
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;
514 }
515
516 static int
517 vax_address_cost (rtx x)
518 {
519 return (1 + (GET_CODE (x) == REG ? 0 : vax_address_cost_1 (x)));
520 }
521
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
524 other models. */
525
526 static int
527 vax_rtx_costs_1 (register rtx x, enum rtx_code code, enum rtx_code outer_code)
528 {
529 enum machine_mode mode = GET_MODE (x);
530 register int c;
531 int i = 0; /* may be modified in switch */
532 const char *fmt = GET_RTX_FORMAT (code); /* may be modified in switch */
533
534 switch (code)
535 {
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). */
541 case CONST_INT:
542 if (INTVAL (x) == 0)
543 return 0;
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)
547 return 1;
548 if (outer_code == COMPARE && INTVAL (x) == -1)
549 return 1;
550 if (outer_code == PLUS && (unsigned HOST_WIDE_INT) -INTVAL (x) <= 077)
551 return 1;
552 /* FALLTHRU */
553
554 case CONST:
555 case LABEL_REF:
556 case SYMBOL_REF:
557 return 3;
558
559 case CONST_DOUBLE:
560 if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
561 return vax_float_literal (x) ? 5 : 8;
562 else
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))
568 ? 2 : 5);
569
570 case POST_INC:
571 return 2;
572 case PRE_DEC:
573 return 3;
574 case MULT:
575 switch (mode)
576 {
577 case DFmode:
578 c = 16; /* 4 on VAX 9000 */
579 break;
580 case SFmode:
581 c = 9; /* 4 on VAX 9000, 12 on VAX 2 */
582 break;
583 case DImode:
584 c = 16; /* 6 on VAX 9000, 28 on VAX 2 */
585 break;
586 case SImode:
587 case HImode:
588 case QImode:
589 c = 10; /* 3-4 on VAX 9000, 20-28 on VAX 2 */
590 break;
591 default:
592 return MAX_COST; /* Mode is not supported. */
593 }
594 break;
595 case UDIV:
596 if (mode != SImode)
597 return MAX_COST; /* Mode is not supported. */
598 c = 17;
599 break;
600 case DIV:
601 if (mode == DImode)
602 c = 30; /* highly variable */
603 else if (mode == DFmode)
604 /* divide takes 28 cycles if the result is not zero, 13 otherwise */
605 c = 24;
606 else
607 c = 11; /* 25 on VAX 2 */
608 break;
609 case MOD:
610 c = 23;
611 break;
612 case UMOD:
613 if (mode != SImode)
614 return MAX_COST; /* Mode is not supported. */
615 c = 29;
616 break;
617 case FLOAT:
618 c = 6 + (mode == DFmode) + (GET_MODE (XEXP (x, 0)) != SImode);
619 /* 4 on VAX 9000 */
620 break;
621 case FIX:
622 c = 7; /* 17 on VAX 2 */
623 break;
624 case ASHIFT:
625 case LSHIFTRT:
626 case ASHIFTRT:
627 if (mode == DImode)
628 c = 12;
629 else
630 c = 10; /* 6 on VAX 9000 */
631 break;
632 case ROTATE:
633 case ROTATERT:
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 */
637 break;
638 case PLUS:
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)
643 fmt = "e";
644 case MINUS:
645 c = (mode == DFmode) ? 13 : 8; /* 6/8 on VAX 9000, 16/15 on VAX 2 */
646 case IOR:
647 case XOR:
648 c = 3;
649 break;
650 case AND:
651 /* AND is special because the first operand is complemented. */
652 c = 3;
653 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
654 {
655 if ((unsigned)~INTVAL (XEXP (x, 0)) > 63)
656 c = 4;
657 fmt = "e";
658 i = 1;
659 }
660 break;
661 case NEG:
662 if (mode == DFmode)
663 return 9;
664 else if (mode == SFmode)
665 return 6;
666 else if (mode == DImode)
667 return 4;
668 case NOT:
669 return 2;
670 case ZERO_EXTRACT:
671 case SIGN_EXTRACT:
672 c = 15;
673 break;
674 case MEM:
675 if (mode == DImode || mode == DFmode)
676 c = 5; /* 7 on VAX 2 */
677 else
678 c = 3; /* 4 on VAX 2 */
679 x = XEXP (x, 0);
680 if (GET_CODE (x) == REG || GET_CODE (x) == POST_INC)
681 return c;
682 return c + vax_address_cost_1 (x);
683 default:
684 c = 3;
685 break;
686 }
687
688 /* Now look inside the expression. Operands which are not registers or
689 short constants add to the cost.
690
691 FMT and I may have been adjusted in the switch above for instructions
692 which require special handling */
693
694 while (*fmt++ == 'e')
695 {
696 register rtx op = XEXP (x, i++);
697 code = GET_CODE (op);
698
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. */
702 if (code == NOT)
703 op = XEXP (op, 0), code = GET_CODE (op);
704
705 switch (code)
706 {
707 case CONST_INT:
708 if ((unsigned)INTVAL (op) > 63 && GET_MODE (x) != QImode)
709 c += 1; /* 2 on VAX 2 */
710 break;
711 case CONST:
712 case LABEL_REF:
713 case SYMBOL_REF:
714 c += 1; /* 2 on VAX 2 */
715 break;
716 case CONST_DOUBLE:
717 if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT)
718 {
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))
722 c++;
723 else
724 c += (GET_MODE (x) == DFmode) ? 3 : 2;
725 }
726 else
727 {
728 if (CONST_DOUBLE_HIGH (op) != 0
729 || (unsigned)CONST_DOUBLE_LOW (op) > 63)
730 c += 2;
731 }
732 break;
733 case MEM:
734 c += 1; /* 2 on VAX 2 */
735 if (GET_CODE (XEXP (op, 0)) != REG)
736 c += vax_address_cost_1 (XEXP (op, 0));
737 break;
738 case REG:
739 case SUBREG:
740 break;
741 default:
742 c += 1;
743 break;
744 }
745 }
746 return c;
747 }
748
749 static bool
750 vax_rtx_costs (rtx x, int code, int outer_code, int * total)
751 {
752 *total = vax_rtx_costs_1 (x, code, outer_code);
753 return true;
754 }
755 \f
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
761 */
762
763 static void
764 vax_output_mi_thunk (FILE * file,
765 tree thunk ATTRIBUTE_UNUSED,
766 HOST_WIDE_INT delta,
767 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
768 tree function)
769 {
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");
775 }