* ChangeLog: Follow spelling conventions.
[official-gcc.git] / gcc / config / vax / vax.c
blobded7570f32da709b1f2a4a92df4fd897af760c6e
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)
10 any later version.
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. */
22 #include "config.h"
23 #include "system.h"
24 #include "rtl.h"
25 #include "tree.h"
26 #include "regs.h"
27 #include "hard-reg-set.h"
28 #include "real.h"
29 #include "insn-config.h"
30 #include "conditions.h"
31 #include "function.h"
32 #include "output.h"
33 #include "insn-attr.h"
34 #include "recog.h"
35 #include "expr.h"
36 #include "flags.h"
37 #include "tm_p.h"
38 #include "target.h"
39 #include "target-def.h"
41 static int follows_p PARAMS ((rtx, rtx));
42 static void vax_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
43 #if VMS_TARGET
44 static void vms_asm_out_constructor PARAMS ((rtx, int));
45 static void vms_asm_out_destructor PARAMS ((rtx, int));
46 static void vms_select_section PARAMS ((tree, int, unsigned HOST_WIDE_INT));
47 static void vms_encode_section_info PARAMS ((tree, int));
48 static void vms_globalize_label PARAMS ((FILE *, const char *));
49 #endif
51 /* Initialize the GCC target structure. */
52 #undef TARGET_ASM_ALIGNED_HI_OP
53 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
55 #undef TARGET_ASM_FUNCTION_PROLOGUE
56 #define TARGET_ASM_FUNCTION_PROLOGUE vax_output_function_prologue
58 #if VMS_TARGET
59 #undef TARGET_ASM_SELECT_SECTION
60 #define TARGET_ASM_SELECT_SECTION vms_select_section
61 #undef TARGET_ENCODE_SECTION_INFO
62 #define TARGET_ENCODE_SECTION_INFO vms_encode_section_info
63 #undef TARGET_ASM_GLOBALIZE_LABEL
64 #define TARGET_ASM_GLOBALIZE_LABEL vms_globalize_label
65 #endif
67 struct gcc_target targetm = TARGET_INITIALIZER;
69 /* Generate the assembly code for function entry. FILE is a stdio
70 stream to output the code to. SIZE is an int: how many units of
71 temporary storage to allocate.
73 Refer to the array `regs_ever_live' to determine which registers to
74 save; `regs_ever_live[I]' is nonzero if register number I is ever
75 used in the function. This function is responsible for knowing
76 which registers should not be saved even if used. */
78 static void
79 vax_output_function_prologue (file, size)
80 FILE * file;
81 HOST_WIDE_INT size;
83 register int regno;
84 register int mask = 0;
86 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
87 if (regs_ever_live[regno] && !call_used_regs[regno])
88 mask |= 1 << regno;
90 fprintf (file, "\t.word 0x%x\n", mask);
92 if (VMS_TARGET)
95 * This works for both gcc and g++. It first checks to see if
96 * the current routine is "main", which will only happen for
97 * GCC, and add the jsb if it is. If is not the case then try
98 * and see if __MAIN_NAME is part of current_function_name,
99 * which will only happen if we are running g++, and add the jsb
100 * if it is. In gcc there should never be a paren in the
101 * function name, and in g++ there is always a "(" in the
102 * function name, thus there should never be any confusion.
104 * Adjusting the stack pointer by 4 before calling C$MAIN_ARGS
105 * is required when linking with the VMS POSIX version of the C
106 * run-time library; using `subl2 $4,r0' is adequate but we use
107 * `clrl -(sp)' instead. The extra 4 bytes could be removed
108 * after the call because STARTING_FRAME_OFFSET's setting of -4
109 * will end up adding them right back again, but don't bother.
112 const char *p = current_function_name;
113 int is_main = strcmp ("main", p) == 0;
114 # define __MAIN_NAME " main("
116 while (!is_main && *p != '\0')
118 if (*p == *__MAIN_NAME
119 && strncmp (p, __MAIN_NAME, sizeof __MAIN_NAME - sizeof "") == 0)
120 is_main = 1;
121 else
122 p++;
125 if (is_main)
126 fprintf (file, "\tclrl -(%ssp)\n\tjsb _C$MAIN_ARGS\n",
127 REGISTER_PREFIX);
130 size -= STARTING_FRAME_OFFSET;
131 if (size >= 64)
132 fprintf (file, "\tmovab %d(%ssp),%ssp\n", -size, REGISTER_PREFIX,
133 REGISTER_PREFIX);
134 else if (size)
135 fprintf (file, "\tsubl2 $%d,%ssp\n", size, REGISTER_PREFIX);
138 /* This is like nonimmediate_operand with a restriction on the type of MEM. */
140 void
141 split_quadword_operands (operands, low, n)
142 rtx *operands, *low;
143 int n ATTRIBUTE_UNUSED;
145 int i;
146 /* Split operands. */
148 low[0] = low[1] = low[2] = 0;
149 for (i = 0; i < 3; i++)
151 if (low[i])
152 /* it's already been figured out */;
153 else if (GET_CODE (operands[i]) == MEM
154 && (GET_CODE (XEXP (operands[i], 0)) == POST_INC))
156 rtx addr = XEXP (operands[i], 0);
157 operands[i] = low[i] = gen_rtx_MEM (SImode, addr);
158 if (which_alternative == 0 && i == 0)
160 addr = XEXP (operands[i], 0);
161 operands[i+1] = low[i+1] = gen_rtx_MEM (SImode, addr);
164 else
166 low[i] = operand_subword (operands[i], 0, 0, DImode);
167 operands[i] = operand_subword (operands[i], 1, 0, DImode);
172 void
173 print_operand_address (file, addr)
174 FILE *file;
175 register rtx addr;
177 register rtx reg1, breg, ireg;
178 rtx offset;
180 retry:
181 switch (GET_CODE (addr))
183 case MEM:
184 fprintf (file, "*");
185 addr = XEXP (addr, 0);
186 goto retry;
188 case REG:
189 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
190 break;
192 case PRE_DEC:
193 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
194 break;
196 case POST_INC:
197 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
198 break;
200 case PLUS:
201 /* There can be either two or three things added here. One must be a
202 REG. One can be either a REG or a MULT of a REG and an appropriate
203 constant, and the third can only be a constant or a MEM.
205 We get these two or three things and put the constant or MEM in
206 OFFSET, the MULT or REG in IREG, and the REG in BREG. If we have
207 a register and can't tell yet if it is a base or index register,
208 put it into REG1. */
210 reg1 = 0; ireg = 0; breg = 0; offset = 0;
212 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
213 || GET_CODE (XEXP (addr, 0)) == MEM)
215 offset = XEXP (addr, 0);
216 addr = XEXP (addr, 1);
218 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
219 || GET_CODE (XEXP (addr, 1)) == MEM)
221 offset = XEXP (addr, 1);
222 addr = XEXP (addr, 0);
224 else if (GET_CODE (XEXP (addr, 1)) == MULT)
226 ireg = XEXP (addr, 1);
227 addr = XEXP (addr, 0);
229 else if (GET_CODE (XEXP (addr, 0)) == MULT)
231 ireg = XEXP (addr, 0);
232 addr = XEXP (addr, 1);
234 else if (GET_CODE (XEXP (addr, 1)) == REG)
236 reg1 = XEXP (addr, 1);
237 addr = XEXP (addr, 0);
239 else if (GET_CODE (XEXP (addr, 0)) == REG)
241 reg1 = XEXP (addr, 0);
242 addr = XEXP (addr, 1);
244 else
245 abort ();
247 if (GET_CODE (addr) == REG)
249 if (reg1)
250 ireg = addr;
251 else
252 reg1 = addr;
254 else if (GET_CODE (addr) == MULT)
255 ireg = addr;
256 else if (GET_CODE (addr) == PLUS)
258 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
259 || GET_CODE (XEXP (addr, 0)) == MEM)
261 if (offset)
263 if (GET_CODE (offset) == CONST_INT)
264 offset = plus_constant (XEXP (addr, 0), INTVAL (offset));
265 else if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
266 offset = plus_constant (offset, INTVAL (XEXP (addr, 0)));
267 else
268 abort ();
270 offset = XEXP (addr, 0);
272 else if (GET_CODE (XEXP (addr, 0)) == REG)
274 if (reg1)
275 ireg = reg1, breg = XEXP (addr, 0), reg1 = 0;
276 else
277 reg1 = XEXP (addr, 0);
279 else if (GET_CODE (XEXP (addr, 0)) == MULT)
281 if (ireg)
282 abort ();
283 ireg = XEXP (addr, 0);
285 else
286 abort ();
288 if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
289 || GET_CODE (XEXP (addr, 1)) == MEM)
291 if (offset)
293 if (GET_CODE (offset) == CONST_INT)
294 offset = plus_constant (XEXP (addr, 1), INTVAL (offset));
295 else if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
296 offset = plus_constant (offset, INTVAL (XEXP (addr, 1)));
297 else
298 abort ();
300 offset = XEXP (addr, 1);
302 else if (GET_CODE (XEXP (addr, 1)) == REG)
304 if (reg1)
305 ireg = reg1, breg = XEXP (addr, 1), reg1 = 0;
306 else
307 reg1 = XEXP (addr, 1);
309 else if (GET_CODE (XEXP (addr, 1)) == MULT)
311 if (ireg)
312 abort ();
313 ireg = XEXP (addr, 1);
315 else
316 abort ();
318 else
319 abort ();
321 /* If REG1 is non-zero, figure out if it is a base or index register. */
322 if (reg1)
324 if (breg != 0 || (offset && GET_CODE (offset) == MEM))
326 if (ireg)
327 abort ();
328 ireg = reg1;
330 else
331 breg = reg1;
334 if (offset != 0)
335 output_address (offset);
337 if (breg != 0)
338 fprintf (file, "(%s)", reg_names[REGNO (breg)]);
340 if (ireg != 0)
342 if (GET_CODE (ireg) == MULT)
343 ireg = XEXP (ireg, 0);
344 if (GET_CODE (ireg) != REG)
345 abort ();
346 fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
348 break;
350 default:
351 output_addr_const (file, addr);
355 const char *
356 rev_cond_name (op)
357 rtx op;
359 switch (GET_CODE (op))
361 case EQ:
362 return "neq";
363 case NE:
364 return "eql";
365 case LT:
366 return "geq";
367 case LE:
368 return "gtr";
369 case GT:
370 return "leq";
371 case GE:
372 return "lss";
373 case LTU:
374 return "gequ";
375 case LEU:
376 return "gtru";
377 case GTU:
378 return "lequ";
379 case GEU:
380 return "lssu";
382 default:
383 abort ();
388 vax_float_literal(c)
389 register rtx c;
391 register enum machine_mode mode;
392 REAL_VALUE_TYPE r, s;
393 int i;
395 if (GET_CODE (c) != CONST_DOUBLE)
396 return 0;
398 mode = GET_MODE (c);
400 if (c == const_tiny_rtx[(int) mode][0]
401 || c == const_tiny_rtx[(int) mode][1]
402 || c == const_tiny_rtx[(int) mode][2])
403 return 1;
405 REAL_VALUE_FROM_CONST_DOUBLE (r, c);
407 for (i = 0; i < 7; i++)
409 int x = 1 << i;
410 REAL_VALUE_FROM_INT (s, x, 0, mode);
412 if (REAL_VALUES_EQUAL (r, s))
413 return 1;
414 if (!exact_real_inverse (mode, &s))
415 abort ();
416 if (REAL_VALUES_EQUAL (r, s))
417 return 1;
419 return 0;
423 /* Return the cost in cycles of a memory address, relative to register
424 indirect.
426 Each of the following adds the indicated number of cycles:
428 1 - symbolic address
429 1 - pre-decrement
430 1 - indexing and/or offset(register)
431 2 - indirect */
435 vax_address_cost (addr)
436 register rtx addr;
438 int reg = 0, indexed = 0, indir = 0, offset = 0, predec = 0;
439 rtx plus_op0 = 0, plus_op1 = 0;
440 restart:
441 switch (GET_CODE (addr))
443 case PRE_DEC:
444 predec = 1;
445 case REG:
446 case SUBREG:
447 case POST_INC:
448 reg = 1;
449 break;
450 case MULT:
451 indexed = 1; /* 2 on VAX 2 */
452 break;
453 case CONST_INT:
454 /* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */
455 if (offset == 0)
456 offset = (unsigned)(INTVAL(addr)+128) > 256;
457 break;
458 case CONST:
459 case SYMBOL_REF:
460 offset = 1; /* 2 on VAX 2 */
461 break;
462 case LABEL_REF: /* this is probably a byte offset from the pc */
463 if (offset == 0)
464 offset = 1;
465 break;
466 case PLUS:
467 if (plus_op0)
468 plus_op1 = XEXP (addr, 0);
469 else
470 plus_op0 = XEXP (addr, 0);
471 addr = XEXP (addr, 1);
472 goto restart;
473 case MEM:
474 indir = 2; /* 3 on VAX 2 */
475 addr = XEXP (addr, 0);
476 goto restart;
477 default:
478 break;
481 /* Up to 3 things can be added in an address. They are stored in
482 plus_op0, plus_op1, and addr. */
484 if (plus_op0)
486 addr = plus_op0;
487 plus_op0 = 0;
488 goto restart;
490 if (plus_op1)
492 addr = plus_op1;
493 plus_op1 = 0;
494 goto restart;
496 /* Indexing and register+offset can both be used (except on a VAX 2)
497 without increasing execution time over either one alone. */
498 if (reg && indexed && offset)
499 return reg + indir + offset + predec;
500 return reg + indexed + indir + offset + predec;
504 /* Cost of an expression on a VAX. This version has costs tuned for the
505 CVAX chip (found in the VAX 3 series) with comments for variations on
506 other models. */
509 vax_rtx_cost (x)
510 register rtx x;
512 register enum rtx_code code = GET_CODE (x);
513 enum machine_mode mode = GET_MODE (x);
514 register int c;
515 int i = 0; /* may be modified in switch */
516 const char *fmt = GET_RTX_FORMAT (code); /* may be modified in switch */
518 switch (code)
520 case POST_INC:
521 return 2;
522 case PRE_DEC:
523 return 3;
524 case MULT:
525 switch (mode)
527 case DFmode:
528 c = 16; /* 4 on VAX 9000 */
529 break;
530 case SFmode:
531 c = 9; /* 4 on VAX 9000, 12 on VAX 2 */
532 break;
533 case DImode:
534 c = 16; /* 6 on VAX 9000, 28 on VAX 2 */
535 break;
536 case SImode:
537 case HImode:
538 case QImode:
539 c = 10; /* 3-4 on VAX 9000, 20-28 on VAX 2 */
540 break;
541 default:
542 return MAX_COST; /* Mode is not supported. */
544 break;
545 case UDIV:
546 if (mode != SImode)
547 return MAX_COST; /* Mode is not supported. */
548 c = 17;
549 break;
550 case DIV:
551 if (mode == DImode)
552 c = 30; /* highly variable */
553 else if (mode == DFmode)
554 /* divide takes 28 cycles if the result is not zero, 13 otherwise */
555 c = 24;
556 else
557 c = 11; /* 25 on VAX 2 */
558 break;
559 case MOD:
560 c = 23;
561 break;
562 case UMOD:
563 if (mode != SImode)
564 return MAX_COST; /* Mode is not supported. */
565 c = 29;
566 break;
567 case FLOAT:
568 c = 6 + (mode == DFmode) + (GET_MODE (XEXP (x, 0)) != SImode);
569 /* 4 on VAX 9000 */
570 break;
571 case FIX:
572 c = 7; /* 17 on VAX 2 */
573 break;
574 case ASHIFT:
575 case LSHIFTRT:
576 case ASHIFTRT:
577 if (mode == DImode)
578 c = 12;
579 else
580 c = 10; /* 6 on VAX 9000 */
581 break;
582 case ROTATE:
583 case ROTATERT:
584 c = 6; /* 5 on VAX 2, 4 on VAX 9000 */
585 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
586 fmt = "e"; /* all constant rotate counts are short */
587 break;
588 case PLUS:
589 /* Check for small negative integer operand: subl2 can be used with
590 a short positive constant instead. */
591 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
592 if ((unsigned)(INTVAL (XEXP (x, 1)) + 63) < 127)
593 fmt = "e";
594 case MINUS:
595 c = (mode == DFmode) ? 13 : 8; /* 6/8 on VAX 9000, 16/15 on VAX 2 */
596 case IOR:
597 case XOR:
598 c = 3;
599 break;
600 case AND:
601 /* AND is special because the first operand is complemented. */
602 c = 3;
603 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
605 if ((unsigned)~INTVAL (XEXP (x, 0)) > 63)
606 c = 4;
607 fmt = "e";
608 i = 1;
610 break;
611 case NEG:
612 if (mode == DFmode)
613 return 9;
614 else if (mode == SFmode)
615 return 6;
616 else if (mode == DImode)
617 return 4;
618 case NOT:
619 return 2;
620 case ZERO_EXTRACT:
621 case SIGN_EXTRACT:
622 c = 15;
623 break;
624 case MEM:
625 if (mode == DImode || mode == DFmode)
626 c = 5; /* 7 on VAX 2 */
627 else
628 c = 3; /* 4 on VAX 2 */
629 x = XEXP (x, 0);
630 if (GET_CODE (x) == REG || GET_CODE (x) == POST_INC)
631 return c;
632 return c + vax_address_cost (x);
633 default:
634 c = 3;
635 break;
639 /* Now look inside the expression. Operands which are not registers or
640 short constants add to the cost.
642 FMT and I may have been adjusted in the switch above for instructions
643 which require special handling */
645 while (*fmt++ == 'e')
647 register rtx op = XEXP (x, i++);
648 code = GET_CODE (op);
650 /* A NOT is likely to be found as the first operand of an AND
651 (in which case the relevant cost is of the operand inside
652 the not) and not likely to be found anywhere else. */
653 if (code == NOT)
654 op = XEXP (op, 0), code = GET_CODE (op);
656 switch (code)
658 case CONST_INT:
659 if ((unsigned)INTVAL (op) > 63 && GET_MODE (x) != QImode)
660 c += 1; /* 2 on VAX 2 */
661 break;
662 case CONST:
663 case LABEL_REF:
664 case SYMBOL_REF:
665 c += 1; /* 2 on VAX 2 */
666 break;
667 case CONST_DOUBLE:
668 if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT)
670 /* Registers are faster than floating point constants -- even
671 those constants which can be encoded in a single byte. */
672 if (vax_float_literal (op))
673 c++;
674 else
675 c += (GET_MODE (x) == DFmode) ? 3 : 2;
677 else
679 if (CONST_DOUBLE_HIGH (op) != 0
680 || (unsigned)CONST_DOUBLE_LOW (op) > 63)
681 c += 2;
683 break;
684 case MEM:
685 c += 1; /* 2 on VAX 2 */
686 if (GET_CODE (XEXP (op, 0)) != REG)
687 c += vax_address_cost (XEXP (op, 0));
688 break;
689 case REG:
690 case SUBREG:
691 break;
692 default:
693 c += 1;
694 break;
697 return c;
700 /* Check a `double' value for validity for a particular machine mode. */
702 static const char *const float_strings[] =
704 "1.70141173319264430e+38", /* 2^127 (2^24 - 1) / 2^24 */
705 "-1.70141173319264430e+38",
706 "2.93873587705571877e-39", /* 2^-128 */
707 "-2.93873587705571877e-39"
710 static REAL_VALUE_TYPE float_values[4];
712 static int inited_float_values = 0;
716 check_float_value (mode, d, overflow)
717 enum machine_mode mode;
718 REAL_VALUE_TYPE *d;
719 int overflow;
721 if (inited_float_values == 0)
723 int i;
724 for (i = 0; i < 4; i++)
726 float_values[i] = REAL_VALUE_ATOF (float_strings[i], DFmode);
729 inited_float_values = 1;
732 if (overflow)
734 memcpy (d, &float_values[0], sizeof (REAL_VALUE_TYPE));
735 return 1;
738 if ((mode) == SFmode)
740 REAL_VALUE_TYPE r;
741 memcpy (&r, d, sizeof (REAL_VALUE_TYPE));
742 if (REAL_VALUES_LESS (float_values[0], r))
744 memcpy (d, &float_values[0], sizeof (REAL_VALUE_TYPE));
745 return 1;
747 else if (REAL_VALUES_LESS (r, float_values[1]))
749 memcpy (d, &float_values[1], sizeof (REAL_VALUE_TYPE));
750 return 1;
752 else if (REAL_VALUES_LESS (dconst0, r)
753 && REAL_VALUES_LESS (r, float_values[2]))
755 memcpy (d, &dconst0, sizeof (REAL_VALUE_TYPE));
756 return 1;
758 else if (REAL_VALUES_LESS (r, dconst0)
759 && REAL_VALUES_LESS (float_values[3], r))
761 memcpy (d, &dconst0, sizeof (REAL_VALUE_TYPE));
762 return 1;
766 return 0;
769 #if VMS_TARGET
770 /* Additional support code for VMS target. */
772 /* Linked list of all externals that are to be emitted when optimizing
773 for the global pointer if they haven't been declared by the end of
774 the program with an appropriate .comm or initialization. */
776 static
777 struct extern_list {
778 struct extern_list *next; /* next external */
779 const char *name; /* name of the external */
780 int size; /* external's actual size */
781 int in_const; /* section type flag */
782 } *extern_head = 0, *pending_head = 0;
784 /* Check whether NAME is already on the external definition list. If not,
785 add it to either that list or the pending definition list. */
787 void
788 vms_check_external (decl, name, pending)
789 tree decl;
790 const char *name;
791 int pending;
793 register struct extern_list *p, *p0;
795 for (p = extern_head; p; p = p->next)
796 if (!strcmp (p->name, name))
797 return;
799 for (p = pending_head, p0 = 0; p; p0 = p, p = p->next)
800 if (!strcmp (p->name, name))
802 if (pending)
803 return;
805 /* Was pending, but has now been defined; move it to other list. */
806 if (p == pending_head)
807 pending_head = p->next;
808 else
809 p0->next = p->next;
810 p->next = extern_head;
811 extern_head = p;
812 return;
815 /* Not previously seen; create a new list entry. */
816 p = (struct extern_list *) xmalloc (sizeof (struct extern_list));
817 p->name = name;
819 if (pending)
821 /* Save the size and section type and link to `pending' list. */
822 p->size = (DECL_SIZE (decl) == 0) ? 0 :
823 TREE_INT_CST_LOW (size_binop (CEIL_DIV_EXPR, DECL_SIZE (decl),
824 size_int (BITS_PER_UNIT)));
825 p->in_const = (TREE_READONLY (decl) && ! TREE_THIS_VOLATILE (decl));
827 p->next = pending_head;
828 pending_head = p;
830 else
832 /* Size and section type don't matter; link to `declared' list. */
833 p->size = p->in_const = 0; /* arbitrary init */
835 p->next = extern_head;
836 extern_head = p;
838 return;
841 void
842 vms_flush_pending_externals (file)
843 FILE *file;
845 register struct extern_list *p;
847 while (pending_head)
849 /* Move next pending declaration to the "done" list. */
850 p = pending_head;
851 pending_head = p->next;
852 p->next = extern_head;
853 extern_head = p;
855 /* Now output the actual declaration. */
856 if (p->in_const)
857 const_section ();
858 else
859 data_section ();
860 fputs (".comm ", file);
861 assemble_name (file, p->name);
862 fprintf (file, ",%d\n", p->size);
866 static void
867 vms_asm_out_constructor (symbol, priority)
868 rtx symbol;
869 int priority ATTRIBUTE_UNUSED;
871 fprintf (asm_out_file,".globl $$PsectAttributes_NOOVR$$__gxx_init_1\n");
872 data_section();
873 fprintf (asm_out_file,"$$PsectAttributes_NOOVR$$__gxx_init_1:\n\t.long\t");
874 assemble_name (asm_out_file, XSTR (symbol, 0));
875 fputc ('\n', asm_out_file);
878 static void
879 vms_asm_out_destructor (symbol, priority)
880 rtx symbol;
881 int priority ATTRIBUTE_UNUSED;
883 fprintf (asm_out_file,".globl $$PsectAttributes_NOOVR$$__gxx_clean_1\n");
884 data_section();
885 fprintf (asm_out_file,"$$PsectAttributes_NOOVR$$__gxx_clean_1:\n\t.long\t");
886 assemble_name (asm_out_file, XSTR (symbol, 0));
887 fputc ('\n', asm_out_file);
890 static void
891 vms_select_section (exp, reloc, align)
892 tree exp;
893 int reloc ATTRIBUTE_UNUSED;
894 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
896 if (TREE_CODE (exp) == VAR_DECL)
898 if (TREE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp)
899 && DECL_INITIAL (exp)
900 && (DECL_INITIAL (exp) == error_mark_node
901 || TREE_CONSTANT (DECL_INITIAL (exp))))
903 if (TREE_PUBLIC (exp))
904 const_section ();
905 else
906 text_section ();
908 else
909 data_section ();
911 if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c')
913 if (TREE_CODE (exp) == STRING_CST && flag_writable_strings)
914 data_section ();
915 else
916 text_section ();
920 /* Make sure that external variables are correctly addressed. Under VMS
921 there is some brain damage in the linker that requires us to do this. */
923 static void
924 vms_encode_section_info (decl, first)
925 tree decl;
926 int first ATTRIBUTE_UNUSED;
928 if (DECL_EXTERNAL (decl) && TREE_PUBLIC (decl))
929 SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
932 /* This is how to output a command to make the user-level label named NAME
933 defined for reference from other files. */
934 static void
935 vms_globalize_label (stream, name)
936 FILE *stream;
937 const char *name;
939 default_globalize_label (stream, name);
940 vms_check_external (NULL_TREE, name, 0);
942 #endif /* VMS_TARGET */
944 /* Additional support code for VMS host. */
945 /* ??? This should really be in libiberty; vax.c is a target file. */
946 #ifdef QSORT_WORKAROUND
948 Do not use VAXCRTL's qsort() due to a severe bug: once you've
949 sorted something which has a size that's an exact multiple of 4
950 and is longword aligned, you cannot safely sort anything which
951 is either not a multiple of 4 in size or not longword aligned.
952 A static "move-by-longword" optimization flag inside qsort() is
953 never reset. This is known to affect VMS V4.6 through VMS V5.5-1,
954 and was finally fixed in VMS V5.5-2.
956 In this work-around an insertion sort is used for simplicity.
957 The qsort code from glibc should probably be used instead.
959 void
960 not_qsort (array, count, size, compare)
961 void *array;
962 unsigned count, size;
963 int (*compare)();
966 if (size == sizeof (short))
968 register int i;
969 register short *next, *prev;
970 short tmp, *base = array;
972 for (next = base, i = count - 1; i > 0; i--)
974 prev = next++;
975 if ((*compare)(next, prev) < 0)
977 tmp = *next;
978 do *(prev + 1) = *prev;
979 while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0);
980 *(prev + 1) = tmp;
984 else if (size == sizeof (long))
986 register int i;
987 register long *next, *prev;
988 long tmp, *base = array;
990 for (next = base, i = count - 1; i > 0; i--)
992 prev = next++;
993 if ((*compare)(next, prev) < 0)
995 tmp = *next;
996 do *(prev + 1) = *prev;
997 while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0);
998 *(prev + 1) = tmp;
1002 else /* arbitrary size */
1004 register int i;
1005 register char *next, *prev, *tmp = alloca (size), *base = array;
1007 for (next = base, i = count - 1; i > 0; i--)
1008 { /* count-1 forward iterations */
1009 prev = next, next += size; /* increment front pointer */
1010 if ((*compare)(next, prev) < 0)
1011 { /* found element out of order; move others up then re-insert */
1012 memcpy (tmp, next, size); /* save smaller element */
1013 do { memcpy (prev + size, prev, size); /* move larger elem. up */
1014 prev -= size; /* decrement back pointer */
1015 } while (prev >= base ? (*compare)(tmp, prev) < 0 : 0);
1016 memcpy (prev + size, tmp, size); /* restore small element */
1019 #ifdef USE_C_ALLOCA
1020 alloca (0);
1021 #endif
1024 return;
1026 #endif /* QSORT_WORKAROUND */
1028 /* Return 1 if insn A follows B. */
1030 static int
1031 follows_p (a, b)
1032 rtx a, b;
1034 register rtx p;
1036 for (p = a; p != b; p = NEXT_INSN (p))
1037 if (! p)
1038 return 1;
1040 return 0;
1043 /* Returns 1 if we know operand OP was 0 before INSN. */
1046 reg_was_0_p (insn, op)
1047 rtx insn, op;
1049 rtx link;
1051 return ((link = find_reg_note (insn, REG_WAS_0, 0))
1052 /* Make sure the insn that stored the 0 is still present
1053 and doesn't follow INSN in the insn sequence. */
1054 && ! INSN_DELETED_P (XEXP (link, 0))
1055 && GET_CODE (XEXP (link, 0)) != NOTE
1056 && ! follows_p (XEXP (link, 0), insn)
1057 /* Make sure cross jumping didn't happen here. */
1058 && no_labels_between_p (XEXP (link, 0), insn)
1059 /* Make sure the reg hasn't been clobbered. */
1060 && ! reg_set_between_p (op, XEXP (link, 0), insn));