(in m32rx patch): Replace "." with "@." when preceeded by a capital letter
[official-gcc.git] / gcc / config / vax / vax.c
blob1e6820ae26624158aa8c36595319bc5adf8fc506
1 /* Subroutines for insn-output.c for VAX.
2 Copyright (C) 1987, 1994, 1995, 1997, 1998, 1999, 2000
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 "regs.h"
26 #include "hard-reg-set.h"
27 #include "real.h"
28 #include "insn-config.h"
29 #include "conditions.h"
30 #include "function.h"
31 #include "output.h"
32 #include "insn-attr.h"
33 #include "tree.h"
34 #include "recog.h"
35 #include "expr.h"
36 #include "tm_p.h"
37 #include "target.h"
38 #include "target-def.h"
40 static int follows_p PARAMS ((rtx, rtx));
41 static void vax_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
42 #if VMS_TARGET
43 static void vms_asm_out_constructor PARAMS ((rtx, int));
44 static void vms_asm_out_destructor PARAMS ((rtx, int));
45 #endif
47 /* Initialize the GCC target structure. */
48 #undef TARGET_ASM_FUNCTION_PROLOGUE
49 #define TARGET_ASM_FUNCTION_PROLOGUE vax_output_function_prologue
51 struct gcc_target targetm = TARGET_INITIALIZER;
53 /* Generate the assembly code for function entry. FILE is a stdio
54 stream to output the code to. SIZE is an int: how many units of
55 temporary storage to allocate.
57 Refer to the array `regs_ever_live' to determine which registers to
58 save; `regs_ever_live[I]' is nonzero if register number I is ever
59 used in the function. This function is responsible for knowing
60 which registers should not be saved even if used. */
62 static void
63 vax_output_function_prologue (file, size)
64 FILE * file;
65 HOST_WIDE_INT size;
67 register int regno;
68 register int mask = 0;
69 extern char call_used_regs[];
71 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
72 if (regs_ever_live[regno] && !call_used_regs[regno])
73 mask |= 1 << regno;
75 fprintf (file, "\t.word 0x%x\n", mask);
77 if (VMS_TARGET)
80 * This works for both gcc and g++. It first checks to see if
81 * the current routine is "main", which will only happen for
82 * GCC, and add the jsb if it is. If is not the case then try
83 * and see if __MAIN_NAME is part of current_function_name,
84 * which will only happen if we are running g++, and add the jsb
85 * if it is. In gcc there should never be a paren in the
86 * function name, and in g++ there is always a "(" in the
87 * function name, thus there should never be any confusion.
89 * Adjusting the stack pointer by 4 before calling C$MAIN_ARGS
90 * is required when linking with the VMS POSIX version of the C
91 * run-time library; using `subl2 $4,r0' is adequate but we use
92 * `clrl -(sp)' instead. The extra 4 bytes could be removed
93 * after the call because STARTING_FRAME_OFFSET's setting of -4
94 * will end up adding them right back again, but don't bother.
97 const char *p = current_function_name;
98 int is_main = strcmp ("main", p) == 0;
99 # define __MAIN_NAME " main("
101 while (!is_main && *p != '\0')
103 if (*p == *__MAIN_NAME
104 && strncmp (p, __MAIN_NAME, sizeof __MAIN_NAME - sizeof "") == 0)
105 is_main = 1;
106 else
107 p++;
110 if (is_main)
111 fprintf (file, "\t%s\n\t%s\n", "clrl -(sp)", "jsb _C$MAIN_ARGS");
114 size -= STARTING_FRAME_OFFSET;
115 if (size >= 64)
116 fprintf (file, "\tmovab %d(sp),sp\n", -size);
117 else if (size)
118 fprintf (file, "\tsubl2 $%d,sp\n", size);
121 /* This is like nonimmediate_operand with a restriction on the type of MEM. */
123 void
124 split_quadword_operands (operands, low, n)
125 rtx *operands, *low;
126 int n ATTRIBUTE_UNUSED;
128 int i;
129 /* Split operands. */
131 low[0] = low[1] = low[2] = 0;
132 for (i = 0; i < 3; i++)
134 if (low[i])
135 /* it's already been figured out */;
136 else if (GET_CODE (operands[i]) == MEM
137 && (GET_CODE (XEXP (operands[i], 0)) == POST_INC))
139 rtx addr = XEXP (operands[i], 0);
140 operands[i] = low[i] = gen_rtx_MEM (SImode, addr);
141 if (which_alternative == 0 && i == 0)
143 addr = XEXP (operands[i], 0);
144 operands[i+1] = low[i+1] = gen_rtx_MEM (SImode, addr);
147 else
149 low[i] = operand_subword (operands[i], 0, 0, DImode);
150 operands[i] = operand_subword (operands[i], 1, 0, DImode);
155 void
156 print_operand_address (file, addr)
157 FILE *file;
158 register rtx addr;
160 register rtx reg1, breg, ireg;
161 rtx offset;
163 retry:
164 switch (GET_CODE (addr))
166 case MEM:
167 fprintf (file, "*");
168 addr = XEXP (addr, 0);
169 goto retry;
171 case REG:
172 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
173 break;
175 case PRE_DEC:
176 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
177 break;
179 case POST_INC:
180 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
181 break;
183 case PLUS:
184 /* There can be either two or three things added here. One must be a
185 REG. One can be either a REG or a MULT of a REG and an appropriate
186 constant, and the third can only be a constant or a MEM.
188 We get these two or three things and put the constant or MEM in
189 OFFSET, the MULT or REG in IREG, and the REG in BREG. If we have
190 a register and can't tell yet if it is a base or index register,
191 put it into REG1. */
193 reg1 = 0; ireg = 0; breg = 0; offset = 0;
195 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
196 || GET_CODE (XEXP (addr, 0)) == MEM)
198 offset = XEXP (addr, 0);
199 addr = XEXP (addr, 1);
201 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
202 || GET_CODE (XEXP (addr, 1)) == MEM)
204 offset = XEXP (addr, 1);
205 addr = XEXP (addr, 0);
207 else if (GET_CODE (XEXP (addr, 1)) == MULT)
209 ireg = XEXP (addr, 1);
210 addr = XEXP (addr, 0);
212 else if (GET_CODE (XEXP (addr, 0)) == MULT)
214 ireg = XEXP (addr, 0);
215 addr = XEXP (addr, 1);
217 else if (GET_CODE (XEXP (addr, 1)) == REG)
219 reg1 = XEXP (addr, 1);
220 addr = XEXP (addr, 0);
222 else if (GET_CODE (XEXP (addr, 0)) == REG)
224 reg1 = XEXP (addr, 0);
225 addr = XEXP (addr, 1);
227 else
228 abort ();
230 if (GET_CODE (addr) == REG)
232 if (reg1)
233 ireg = addr;
234 else
235 reg1 = addr;
237 else if (GET_CODE (addr) == MULT)
238 ireg = addr;
239 else if (GET_CODE (addr) == PLUS)
241 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
242 || GET_CODE (XEXP (addr, 0)) == MEM)
244 if (offset)
246 if (GET_CODE (offset) == CONST_INT)
247 offset = plus_constant (XEXP (addr, 0), INTVAL (offset));
248 else if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
249 offset = plus_constant (offset, INTVAL (XEXP (addr, 0)));
250 else
251 abort ();
253 offset = XEXP (addr, 0);
255 else if (GET_CODE (XEXP (addr, 0)) == REG)
257 if (reg1)
258 ireg = reg1, breg = XEXP (addr, 0), reg1 = 0;
259 else
260 reg1 = XEXP (addr, 0);
262 else if (GET_CODE (XEXP (addr, 0)) == MULT)
264 if (ireg)
265 abort ();
266 ireg = XEXP (addr, 0);
268 else
269 abort ();
271 if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
272 || GET_CODE (XEXP (addr, 1)) == MEM)
274 if (offset)
276 if (GET_CODE (offset) == CONST_INT)
277 offset = plus_constant (XEXP (addr, 1), INTVAL (offset));
278 else if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
279 offset = plus_constant (offset, INTVAL (XEXP (addr, 1)));
280 else
281 abort ();
283 offset = XEXP (addr, 1);
285 else if (GET_CODE (XEXP (addr, 1)) == REG)
287 if (reg1)
288 ireg = reg1, breg = XEXP (addr, 1), reg1 = 0;
289 else
290 reg1 = XEXP (addr, 1);
292 else if (GET_CODE (XEXP (addr, 1)) == MULT)
294 if (ireg)
295 abort ();
296 ireg = XEXP (addr, 1);
298 else
299 abort ();
301 else
302 abort ();
304 /* If REG1 is non-zero, figure out if it is a base or index register. */
305 if (reg1)
307 if (breg != 0 || (offset && GET_CODE (offset) == MEM))
309 if (ireg)
310 abort ();
311 ireg = reg1;
313 else
314 breg = reg1;
317 if (offset != 0)
318 output_address (offset);
320 if (breg != 0)
321 fprintf (file, "(%s)", reg_names[REGNO (breg)]);
323 if (ireg != 0)
325 if (GET_CODE (ireg) == MULT)
326 ireg = XEXP (ireg, 0);
327 if (GET_CODE (ireg) != REG)
328 abort ();
329 fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
331 break;
333 default:
334 output_addr_const (file, addr);
338 const char *
339 rev_cond_name (op)
340 rtx op;
342 switch (GET_CODE (op))
344 case EQ:
345 return "neq";
346 case NE:
347 return "eql";
348 case LT:
349 return "geq";
350 case LE:
351 return "gtr";
352 case GT:
353 return "leq";
354 case GE:
355 return "lss";
356 case LTU:
357 return "gequ";
358 case LEU:
359 return "gtru";
360 case GTU:
361 return "lequ";
362 case GEU:
363 return "lssu";
365 default:
366 abort ();
371 vax_float_literal(c)
372 register rtx c;
374 register enum machine_mode mode;
375 #if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
376 int i;
377 union {double d; int i[2];} val;
378 #endif
380 if (GET_CODE (c) != CONST_DOUBLE)
381 return 0;
383 mode = GET_MODE (c);
385 if (c == const_tiny_rtx[(int) mode][0]
386 || c == const_tiny_rtx[(int) mode][1]
387 || c == const_tiny_rtx[(int) mode][2])
388 return 1;
390 #if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
392 val.i[0] = CONST_DOUBLE_LOW (c);
393 val.i[1] = CONST_DOUBLE_HIGH (c);
395 for (i = 0; i < 7; i ++)
396 if (val.d == 1 << i || val.d == 1 / (1 << i))
397 return 1;
398 #endif
399 return 0;
403 /* Return the cost in cycles of a memory address, relative to register
404 indirect.
406 Each of the following adds the indicated number of cycles:
408 1 - symbolic address
409 1 - pre-decrement
410 1 - indexing and/or offset(register)
411 2 - indirect */
415 vax_address_cost (addr)
416 register rtx addr;
418 int reg = 0, indexed = 0, indir = 0, offset = 0, predec = 0;
419 rtx plus_op0 = 0, plus_op1 = 0;
420 restart:
421 switch (GET_CODE (addr))
423 case PRE_DEC:
424 predec = 1;
425 case REG:
426 case SUBREG:
427 case POST_INC:
428 reg = 1;
429 break;
430 case MULT:
431 indexed = 1; /* 2 on VAX 2 */
432 break;
433 case CONST_INT:
434 /* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */
435 if (offset == 0)
436 offset = (unsigned)(INTVAL(addr)+128) > 256;
437 break;
438 case CONST:
439 case SYMBOL_REF:
440 offset = 1; /* 2 on VAX 2 */
441 break;
442 case LABEL_REF: /* this is probably a byte offset from the pc */
443 if (offset == 0)
444 offset = 1;
445 break;
446 case PLUS:
447 if (plus_op0)
448 plus_op1 = XEXP (addr, 0);
449 else
450 plus_op0 = XEXP (addr, 0);
451 addr = XEXP (addr, 1);
452 goto restart;
453 case MEM:
454 indir = 2; /* 3 on VAX 2 */
455 addr = XEXP (addr, 0);
456 goto restart;
457 default:
458 break;
461 /* Up to 3 things can be added in an address. They are stored in
462 plus_op0, plus_op1, and addr. */
464 if (plus_op0)
466 addr = plus_op0;
467 plus_op0 = 0;
468 goto restart;
470 if (plus_op1)
472 addr = plus_op1;
473 plus_op1 = 0;
474 goto restart;
476 /* Indexing and register+offset can both be used (except on a VAX 2)
477 without increasing execution time over either one alone. */
478 if (reg && indexed && offset)
479 return reg + indir + offset + predec;
480 return reg + indexed + indir + offset + predec;
484 /* Cost of an expression on a VAX. This version has costs tuned for the
485 CVAX chip (found in the VAX 3 series) with comments for variations on
486 other models. */
489 vax_rtx_cost (x)
490 register rtx x;
492 register enum rtx_code code = GET_CODE (x);
493 enum machine_mode mode = GET_MODE (x);
494 register int c;
495 int i = 0; /* may be modified in switch */
496 const char *fmt = GET_RTX_FORMAT (code); /* may be modified in switch */
498 switch (code)
500 case POST_INC:
501 return 2;
502 case PRE_DEC:
503 return 3;
504 case MULT:
505 switch (mode)
507 case DFmode:
508 c = 16; /* 4 on VAX 9000 */
509 break;
510 case SFmode:
511 c = 9; /* 4 on VAX 9000, 12 on VAX 2 */
512 break;
513 case DImode:
514 c = 16; /* 6 on VAX 9000, 28 on VAX 2 */
515 break;
516 case SImode:
517 case HImode:
518 case QImode:
519 c = 10; /* 3-4 on VAX 9000, 20-28 on VAX 2 */
520 break;
521 default:
522 abort ();
524 break;
525 case UDIV:
526 c = 17;
527 break;
528 case DIV:
529 if (mode == DImode)
530 c = 30; /* highly variable */
531 else if (mode == DFmode)
532 /* divide takes 28 cycles if the result is not zero, 13 otherwise */
533 c = 24;
534 else
535 c = 11; /* 25 on VAX 2 */
536 break;
537 case MOD:
538 c = 23;
539 break;
540 case UMOD:
541 c = 29;
542 break;
543 case FLOAT:
544 c = 6 + (mode == DFmode) + (GET_MODE (XEXP (x, 0)) != SImode);
545 /* 4 on VAX 9000 */
546 break;
547 case FIX:
548 c = 7; /* 17 on VAX 2 */
549 break;
550 case ASHIFT:
551 case LSHIFTRT:
552 case ASHIFTRT:
553 if (mode == DImode)
554 c = 12;
555 else
556 c = 10; /* 6 on VAX 9000 */
557 break;
558 case ROTATE:
559 case ROTATERT:
560 c = 6; /* 5 on VAX 2, 4 on VAX 9000 */
561 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
562 fmt = "e"; /* all constant rotate counts are short */
563 break;
564 case PLUS:
565 /* Check for small negative integer operand: subl2 can be used with
566 a short positive constant instead. */
567 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
568 if ((unsigned)(INTVAL (XEXP (x, 1)) + 63) < 127)
569 fmt = "e";
570 case MINUS:
571 c = (mode == DFmode) ? 13 : 8; /* 6/8 on VAX 9000, 16/15 on VAX 2 */
572 case IOR:
573 case XOR:
574 c = 3;
575 break;
576 case AND:
577 /* AND is special because the first operand is complemented. */
578 c = 3;
579 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
581 if ((unsigned)~INTVAL (XEXP (x, 0)) > 63)
582 c = 4;
583 fmt = "e";
584 i = 1;
586 break;
587 case NEG:
588 if (mode == DFmode)
589 return 9;
590 else if (mode == SFmode)
591 return 6;
592 else if (mode == DImode)
593 return 4;
594 case NOT:
595 return 2;
596 case ZERO_EXTRACT:
597 case SIGN_EXTRACT:
598 c = 15;
599 break;
600 case MEM:
601 if (mode == DImode || mode == DFmode)
602 c = 5; /* 7 on VAX 2 */
603 else
604 c = 3; /* 4 on VAX 2 */
605 x = XEXP (x, 0);
606 if (GET_CODE (x) == REG || GET_CODE (x) == POST_INC)
607 return c;
608 return c + vax_address_cost (x);
609 default:
610 c = 3;
611 break;
615 /* Now look inside the expression. Operands which are not registers or
616 short constants add to the cost.
618 FMT and I may have been adjusted in the switch above for instructions
619 which require special handling */
621 while (*fmt++ == 'e')
623 register rtx op = XEXP (x, i++);
624 code = GET_CODE (op);
626 /* A NOT is likely to be found as the first operand of an AND
627 (in which case the relevant cost is of the operand inside
628 the not) and not likely to be found anywhere else. */
629 if (code == NOT)
630 op = XEXP (op, 0), code = GET_CODE (op);
632 switch (code)
634 case CONST_INT:
635 if ((unsigned)INTVAL (op) > 63 && GET_MODE (x) != QImode)
636 c += 1; /* 2 on VAX 2 */
637 break;
638 case CONST:
639 case LABEL_REF:
640 case SYMBOL_REF:
641 c += 1; /* 2 on VAX 2 */
642 break;
643 case CONST_DOUBLE:
644 if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT)
646 /* Registers are faster than floating point constants -- even
647 those constants which can be encoded in a single byte. */
648 if (vax_float_literal (op))
649 c++;
650 else
651 c += (GET_MODE (x) == DFmode) ? 3 : 2;
653 else
655 if (CONST_DOUBLE_HIGH (op) != 0
656 || (unsigned)CONST_DOUBLE_LOW (op) > 63)
657 c += 2;
659 break;
660 case MEM:
661 c += 1; /* 2 on VAX 2 */
662 if (GET_CODE (XEXP (op, 0)) != REG)
663 c += vax_address_cost (XEXP (op, 0));
664 break;
665 case REG:
666 case SUBREG:
667 break;
668 default:
669 c += 1;
670 break;
673 return c;
676 /* Check a `double' value for validity for a particular machine mode. */
678 static const char *const float_strings[] =
680 "1.70141173319264430e+38", /* 2^127 (2^24 - 1) / 2^24 */
681 "-1.70141173319264430e+38",
682 "2.93873587705571877e-39", /* 2^-128 */
683 "-2.93873587705571877e-39"
686 static REAL_VALUE_TYPE float_values[4];
688 static int inited_float_values = 0;
692 check_float_value (mode, d, overflow)
693 enum machine_mode mode;
694 REAL_VALUE_TYPE *d;
695 int overflow;
697 if (inited_float_values == 0)
699 int i;
700 for (i = 0; i < 4; i++)
702 float_values[i] = REAL_VALUE_ATOF (float_strings[i], DFmode);
705 inited_float_values = 1;
708 if (overflow)
710 memcpy (d, &float_values[0], sizeof (REAL_VALUE_TYPE));
711 return 1;
714 if ((mode) == SFmode)
716 REAL_VALUE_TYPE r;
717 memcpy (&r, d, sizeof (REAL_VALUE_TYPE));
718 if (REAL_VALUES_LESS (float_values[0], r))
720 memcpy (d, &float_values[0], sizeof (REAL_VALUE_TYPE));
721 return 1;
723 else if (REAL_VALUES_LESS (r, float_values[1]))
725 memcpy (d, &float_values[1], sizeof (REAL_VALUE_TYPE));
726 return 1;
728 else if (REAL_VALUES_LESS (dconst0, r)
729 && REAL_VALUES_LESS (r, float_values[2]))
731 memcpy (d, &dconst0, sizeof (REAL_VALUE_TYPE));
732 return 1;
734 else if (REAL_VALUES_LESS (r, dconst0)
735 && REAL_VALUES_LESS (float_values[3], r))
737 memcpy (d, &dconst0, sizeof (REAL_VALUE_TYPE));
738 return 1;
742 return 0;
745 #if VMS_TARGET
746 /* Additional support code for VMS target. */
748 /* Linked list of all externals that are to be emitted when optimizing
749 for the global pointer if they haven't been declared by the end of
750 the program with an appropriate .comm or initialization. */
752 static
753 struct extern_list {
754 struct extern_list *next; /* next external */
755 const char *name; /* name of the external */
756 int size; /* external's actual size */
757 int in_const; /* section type flag */
758 } *extern_head = 0, *pending_head = 0;
760 /* Check whether NAME is already on the external definition list. If not,
761 add it to either that list or the pending definition list. */
763 void
764 vms_check_external (decl, name, pending)
765 tree decl;
766 const char *name;
767 int pending;
769 register struct extern_list *p, *p0;
771 for (p = extern_head; p; p = p->next)
772 if (!strcmp (p->name, name))
773 return;
775 for (p = pending_head, p0 = 0; p; p0 = p, p = p->next)
776 if (!strcmp (p->name, name))
778 if (pending)
779 return;
781 /* Was pending, but has now been defined; move it to other list. */
782 if (p == pending_head)
783 pending_head = p->next;
784 else
785 p0->next = p->next;
786 p->next = extern_head;
787 extern_head = p;
788 return;
791 /* Not previously seen; create a new list entry. */
792 p = (struct extern_list *)permalloc ((long) sizeof (struct extern_list));
793 p->name = name;
795 if (pending)
797 /* Save the size and section type and link to `pending' list. */
798 p->size = (DECL_SIZE (decl) == 0) ? 0 :
799 TREE_INT_CST_LOW (size_binop (CEIL_DIV_EXPR, DECL_SIZE (decl),
800 size_int (BITS_PER_UNIT)));
801 p->in_const = (TREE_READONLY (decl) && ! TREE_THIS_VOLATILE (decl));
803 p->next = pending_head;
804 pending_head = p;
806 else
808 /* Size and section type don't matter; link to `declared' list. */
809 p->size = p->in_const = 0; /* arbitrary init */
811 p->next = extern_head;
812 extern_head = p;
814 return;
817 void
818 vms_flush_pending_externals (file)
819 FILE *file;
821 register struct extern_list *p;
823 while (pending_head)
825 /* Move next pending declaration to the "done" list. */
826 p = pending_head;
827 pending_head = p->next;
828 p->next = extern_head;
829 extern_head = p;
831 /* Now output the actual declaration. */
832 if (p->in_const)
833 const_section ();
834 else
835 data_section ();
836 fputs (".comm ", file);
837 assemble_name (file, p->name);
838 fprintf (file, ",%d\n", p->size);
842 static void
843 vms_asm_out_constructor (symbol, priority)
844 rtx symbol;
845 int priority ATTRIBUTE_UNUSED;
847 fprintf (asm_out_file,".globl $$PsectAttributes_NOOVR$$__gxx_init_1\n");
848 data_section();
849 fprintf (asm_out_file,"$$PsectAttributes_NOOVR$$__gxx_init_1:\n\t.long\t");
850 assemble_name (asm_out_file, XSTR (symbol, 0));
851 fputc ('\n', asm_out_file);
854 static void
855 vms_asm_out_destructor (symbol, priority)
856 rtx symbol;
857 int priority ATTRIBUTE_UNUSED;
859 fprintf (asm_out_file,".globl $$PsectAttributes_NOOVR$$__gxx_clean_1\n");
860 data_section();
861 fprintf (asm_out_file,"$$PsectAttributes_NOOVR$$__gxx_clean_1:\n\t.long\t");
862 assemble_name (asm_out_file, XSTR (symbol, 0));
863 fputc ('\n', asm_out_file);
865 #endif /* VMS_TARGET */
867 /* Additional support code for VMS host. */
868 /* ??? This should really be in libiberty; vax.c is a target file. */
869 #ifdef QSORT_WORKAROUND
871 Do not use VAXCRTL's qsort() due to a severe bug: once you've
872 sorted something which has a size that's an exact multiple of 4
873 and is longword aligned, you cannot safely sort anything which
874 is either not a multiple of 4 in size or not longword aligned.
875 A static "move-by-longword" optimization flag inside qsort() is
876 never reset. This is known to affect VMS V4.6 through VMS V5.5-1,
877 and was finally fixed in VMS V5.5-2.
879 In this work-around an insertion sort is used for simplicity.
880 The qsort code from glibc should probably be used instead.
882 void
883 not_qsort (array, count, size, compare)
884 void *array;
885 unsigned count, size;
886 int (*compare)();
889 if (size == sizeof (short))
891 register int i;
892 register short *next, *prev;
893 short tmp, *base = array;
895 for (next = base, i = count - 1; i > 0; i--)
897 prev = next++;
898 if ((*compare)(next, prev) < 0)
900 tmp = *next;
901 do *(prev + 1) = *prev;
902 while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0);
903 *(prev + 1) = tmp;
907 else if (size == sizeof (long))
909 register int i;
910 register long *next, *prev;
911 long tmp, *base = array;
913 for (next = base, i = count - 1; i > 0; i--)
915 prev = next++;
916 if ((*compare)(next, prev) < 0)
918 tmp = *next;
919 do *(prev + 1) = *prev;
920 while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0);
921 *(prev + 1) = tmp;
925 else /* arbitrary size */
927 register int i;
928 register char *next, *prev, *tmp = alloca (size), *base = array;
930 for (next = base, i = count - 1; i > 0; i--)
931 { /* count-1 forward iterations */
932 prev = next, next += size; /* increment front pointer */
933 if ((*compare)(next, prev) < 0)
934 { /* found element out of order; move others up then re-insert */
935 memcpy (tmp, next, size); /* save smaller element */
936 do { memcpy (prev + size, prev, size); /* move larger elem. up */
937 prev -= size; /* decrement back pointer */
938 } while (prev >= base ? (*compare)(tmp, prev) < 0 : 0);
939 memcpy (prev + size, tmp, size); /* restore small element */
942 #ifdef USE_C_ALLOCA
943 alloca (0);
944 #endif
947 return;
949 #endif /* QSORT_WORKAROUND */
951 /* Return 1 if insn A follows B. */
953 static int
954 follows_p (a, b)
955 rtx a, b;
957 register rtx p;
959 for (p = a; p != b; p = NEXT_INSN (p))
960 if (! p)
961 return 1;
963 return 0;
966 /* Returns 1 if we know operand OP was 0 before INSN. */
969 reg_was_0_p (insn, op)
970 rtx insn, op;
972 rtx link;
974 return ((link = find_reg_note (insn, REG_WAS_0, 0))
975 /* Make sure the insn that stored the 0 is still present
976 and doesn't follow INSN in the insn sequence. */
977 && ! INSN_DELETED_P (XEXP (link, 0))
978 && GET_CODE (XEXP (link, 0)) != NOTE
979 && ! follows_p (XEXP (link, 0), insn)
980 /* Make sure cross jumping didn't happen here. */
981 && no_labels_between_p (XEXP (link, 0), insn)
982 /* Make sure the reg hasn't been clobbered. */
983 && ! reg_set_between_p (op, XEXP (link, 0), insn));