xref: /openbsd/gnu/usr.bin/gcc/gcc/config/vax/vax.c (revision 404b540a)
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 GNU CC.
6 
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.
11 
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.
16 
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.  */
21 
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 "debug.h"
38 #include "tm_p.h"
39 #include "target.h"
40 #include "target-def.h"
41 
42 static int follows_p PARAMS ((rtx, rtx));
43 static void vax_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
44 #if VMS_TARGET
45 static void vms_asm_out_constructor PARAMS ((rtx, int));
46 static void vms_asm_out_destructor PARAMS ((rtx, int));
47 static void vms_select_section PARAMS ((tree, int, unsigned HOST_WIDE_INT));
48 static void vms_encode_section_info PARAMS ((tree, int));
49 static void vms_globalize_label PARAMS ((FILE *, const char *));
50 #endif
51 static void vax_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
52 					 HOST_WIDE_INT, tree));
53 
54 /* Initialize the GCC target structure.  */
55 #undef TARGET_ASM_ALIGNED_HI_OP
56 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
57 
58 #undef TARGET_ASM_FUNCTION_PROLOGUE
59 #define TARGET_ASM_FUNCTION_PROLOGUE vax_output_function_prologue
60 
61 #if VMS_TARGET
62 #undef TARGET_ASM_SELECT_SECTION
63 #define TARGET_ASM_SELECT_SECTION vms_select_section
64 #undef TARGET_ENCODE_SECTION_INFO
65 #define TARGET_ENCODE_SECTION_INFO vms_encode_section_info
66 #undef TARGET_ASM_GLOBALIZE_LABEL
67 #define TARGET_ASM_GLOBALIZE_LABEL vms_globalize_label
68 #endif
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 struct gcc_target targetm = TARGET_INITIALIZER;
76 
77 /* Set global variables as needed for the options enabled.  */
78 
79 void
80 override_options ()
81 {
82   /* We're VAX floating point, not IEEE floating point.  */
83   memset (real_format_for_mode, 0, sizeof real_format_for_mode);
84   real_format_for_mode[SFmode - QFmode] = &vax_f_format;
85   real_format_for_mode[DFmode - QFmode]
86     = (TARGET_G_FLOAT ? &vax_g_format : &vax_d_format);
87 }
88 
89 /* Generate the assembly code for function entry.  FILE is a stdio
90    stream to output the code to.  SIZE is an int: how many units of
91    temporary storage to allocate.
92 
93    Refer to the array `regs_ever_live' to determine which registers to
94    save; `regs_ever_live[I]' is nonzero if register number I is ever
95    used in the function.  This function is responsible for knowing
96    which registers should not be saved even if used.  */
97 
98 static void
99 vax_output_function_prologue (file, size)
100      FILE * file;
101      HOST_WIDE_INT size;
102 {
103   register int regno;
104   register int mask = 0;
105 
106   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
107     if (regs_ever_live[regno] && !call_used_regs[regno])
108       mask |= 1 << regno;
109 
110   fprintf (file, "\t.word 0x%x\n", mask);
111 
112   if (dwarf2out_do_frame ())
113     {
114       const char *label = dwarf2out_cfi_label ();
115       int offset = 0;
116 
117       for (regno = FIRST_PSEUDO_REGISTER-1; regno >= 0; --regno)
118 	if (regs_ever_live[regno] && !call_used_regs[regno])
119 	  dwarf2out_reg_save (label, regno, offset -= 4);
120 
121       dwarf2out_reg_save (label, PC_REGNUM, offset -= 4);
122       dwarf2out_reg_save (label, FRAME_POINTER_REGNUM, offset -= 4);
123       dwarf2out_reg_save (label, ARG_POINTER_REGNUM, offset -= 4);
124       dwarf2out_def_cfa (label, FRAME_POINTER_REGNUM, -(offset - 4));
125     }
126 
127   if (VMS_TARGET)
128     {
129       /* Adjusting the stack pointer by 4 before calling C$MAIN_ARGS
130 	 is required when linking with the VMS POSIX version of the C
131 	 run-time library; using `subl2 $4,r0' is adequate but we use
132 	 `clrl -(sp)' instead.  The extra 4 bytes could be removed
133 	 after the call because STARTING_FRAME_OFFSET's setting of -4
134 	 will end up adding them right back again, but don't bother.  */
135 
136       if (MAIN_NAME_P (DECL_NAME (current_function_decl)))
137 	asm_fprintf (file, "\tclrl -(%Rsp)\n\tjsb _C$MAIN_ARGS\n");
138     }
139 
140   size -= STARTING_FRAME_OFFSET;
141   if (size >= 64)
142     asm_fprintf (file, "\tmovab %d(%Rsp),%Rsp\n", -size);
143   else if (size)
144     asm_fprintf (file, "\tsubl2 $%d,%Rsp\n", size);
145 }
146 
147 /* This is like nonimmediate_operand with a restriction on the type of MEM.  */
148 
149 void
150 split_quadword_operands (operands, low, n)
151      rtx *operands, *low;
152      int n ATTRIBUTE_UNUSED;
153 {
154   int i;
155   /* Split operands.  */
156 
157   low[0] = low[1] = low[2] = 0;
158   for (i = 0; i < 3; i++)
159     {
160       if (low[i])
161 	/* it's already been figured out */;
162       else if (GET_CODE (operands[i]) == MEM
163 	       && (GET_CODE (XEXP (operands[i], 0)) == POST_INC))
164 	{
165 	  rtx addr = XEXP (operands[i], 0);
166 	  operands[i] = low[i] = gen_rtx_MEM (SImode, addr);
167 	  if (which_alternative == 0 && i == 0)
168 	    {
169 	      addr = XEXP (operands[i], 0);
170 	      operands[i+1] = low[i+1] = gen_rtx_MEM (SImode, addr);
171 	    }
172 	}
173       else
174 	{
175 	  low[i] = operand_subword (operands[i], 0, 0, DImode);
176 	  operands[i] = operand_subword (operands[i], 1, 0, DImode);
177 	}
178     }
179 }
180 
181 void
182 print_operand_address (file, addr)
183      FILE *file;
184      register rtx addr;
185 {
186   register rtx reg1, breg, ireg;
187   rtx offset;
188 
189  retry:
190   switch (GET_CODE (addr))
191     {
192     case MEM:
193       fprintf (file, "*");
194       addr = XEXP (addr, 0);
195       goto retry;
196 
197     case REG:
198       fprintf (file, "(%s)", reg_names[REGNO (addr)]);
199       break;
200 
201     case PRE_DEC:
202       fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
203       break;
204 
205     case POST_INC:
206       fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
207       break;
208 
209     case PLUS:
210       /* There can be either two or three things added here.  One must be a
211 	 REG.  One can be either a REG or a MULT of a REG and an appropriate
212 	 constant, and the third can only be a constant or a MEM.
213 
214 	 We get these two or three things and put the constant or MEM in
215 	 OFFSET, the MULT or REG in IREG, and the REG in BREG.  If we have
216 	 a register and can't tell yet if it is a base or index register,
217 	 put it into REG1.  */
218 
219       reg1 = 0; ireg = 0; breg = 0; offset = 0;
220 
221       if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
222 	  || GET_CODE (XEXP (addr, 0)) == MEM)
223 	{
224 	  offset = XEXP (addr, 0);
225 	  addr = XEXP (addr, 1);
226 	}
227       else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
228 	       || GET_CODE (XEXP (addr, 1)) == MEM)
229 	{
230 	  offset = XEXP (addr, 1);
231 	  addr = XEXP (addr, 0);
232 	}
233       else if (GET_CODE (XEXP (addr, 1)) == MULT)
234 	{
235 	  ireg = XEXP (addr, 1);
236 	  addr = XEXP (addr, 0);
237 	}
238       else if (GET_CODE (XEXP (addr, 0)) == MULT)
239 	{
240 	  ireg = XEXP (addr, 0);
241 	  addr = XEXP (addr, 1);
242 	}
243       else if (GET_CODE (XEXP (addr, 1)) == REG)
244 	{
245 	  reg1 = XEXP (addr, 1);
246 	  addr = XEXP (addr, 0);
247 	}
248       else if (GET_CODE (XEXP (addr, 0)) == REG)
249 	{
250 	  reg1 = XEXP (addr, 0);
251 	  addr = XEXP (addr, 1);
252 	}
253       else
254 	abort ();
255 
256       if (GET_CODE (addr) == REG)
257 	{
258 	  if (reg1)
259 	    ireg = addr;
260 	  else
261 	    reg1 = addr;
262 	}
263       else if (GET_CODE (addr) == MULT)
264 	ireg = addr;
265       else if (GET_CODE (addr) == PLUS)
266 	{
267 	  if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
268 	      || GET_CODE (XEXP (addr, 0)) == MEM)
269 	    {
270 	      if (offset)
271 		{
272 		  if (GET_CODE (offset) == CONST_INT)
273 		    offset = plus_constant (XEXP (addr, 0), INTVAL (offset));
274 		  else if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
275 		    offset = plus_constant (offset, INTVAL (XEXP (addr, 0)));
276 		  else
277 		    abort ();
278 		}
279 	      offset = XEXP (addr, 0);
280 	    }
281 	  else if (GET_CODE (XEXP (addr, 0)) == REG)
282 	    {
283 	      if (reg1)
284 		ireg = reg1, breg = XEXP (addr, 0), reg1 = 0;
285 	      else
286 		reg1 = XEXP (addr, 0);
287 	    }
288 	  else if (GET_CODE (XEXP (addr, 0)) == MULT)
289 	    {
290 	      if (ireg)
291 		abort ();
292 	      ireg = XEXP (addr, 0);
293 	    }
294 	  else
295 	    abort ();
296 
297 	  if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
298 	      || GET_CODE (XEXP (addr, 1)) == MEM)
299 	    {
300 	      if (offset)
301 		{
302 		  if (GET_CODE (offset) == CONST_INT)
303 		    offset = plus_constant (XEXP (addr, 1), INTVAL (offset));
304 		  else if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
305 		    offset = plus_constant (offset, INTVAL (XEXP (addr, 1)));
306 		  else
307 		    abort ();
308 		}
309 	      offset = XEXP (addr, 1);
310 	    }
311 	  else if (GET_CODE (XEXP (addr, 1)) == REG)
312 	    {
313 	      if (reg1)
314 		ireg = reg1, breg = XEXP (addr, 1), reg1 = 0;
315 	      else
316 		reg1 = XEXP (addr, 1);
317 	    }
318 	  else if (GET_CODE (XEXP (addr, 1)) == MULT)
319 	    {
320 	      if (ireg)
321 		abort ();
322 	      ireg = XEXP (addr, 1);
323 	    }
324 	  else
325 	    abort ();
326 	}
327       else
328 	abort ();
329 
330       /* If REG1 is nonzero, figure out if it is a base or index register.  */
331       if (reg1)
332 	{
333 	  if (breg != 0 || (offset && GET_CODE (offset) == MEM))
334 	    {
335 	      if (ireg)
336 		abort ();
337 	      ireg = reg1;
338 	    }
339 	  else
340 	    breg = reg1;
341 	}
342 
343       if (offset != 0)
344 	output_address (offset);
345 
346       if (breg != 0)
347 	fprintf (file, "(%s)", reg_names[REGNO (breg)]);
348 
349       if (ireg != 0)
350 	{
351 	  if (GET_CODE (ireg) == MULT)
352 	    ireg = XEXP (ireg, 0);
353 	  if (GET_CODE (ireg) != REG)
354 	    abort ();
355 	  fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
356 	}
357       break;
358 
359     default:
360       output_addr_const (file, addr);
361     }
362 }
363 
364 const char *
365 rev_cond_name (op)
366      rtx op;
367 {
368   switch (GET_CODE (op))
369     {
370     case EQ:
371       return "neq";
372     case NE:
373       return "eql";
374     case LT:
375       return "geq";
376     case LE:
377       return "gtr";
378     case GT:
379       return "leq";
380     case GE:
381       return "lss";
382     case LTU:
383       return "gequ";
384     case LEU:
385       return "gtru";
386     case GTU:
387       return "lequ";
388     case GEU:
389       return "lssu";
390 
391     default:
392       abort ();
393     }
394 }
395 
396 int
397 vax_float_literal(c)
398     register rtx c;
399 {
400   register enum machine_mode mode;
401   REAL_VALUE_TYPE r, s;
402   int i;
403 
404   if (GET_CODE (c) != CONST_DOUBLE)
405     return 0;
406 
407   mode = GET_MODE (c);
408 
409   if (c == const_tiny_rtx[(int) mode][0]
410       || c == const_tiny_rtx[(int) mode][1]
411       || c == const_tiny_rtx[(int) mode][2])
412     return 1;
413 
414   REAL_VALUE_FROM_CONST_DOUBLE (r, c);
415 
416   for (i = 0; i < 7; i++)
417     {
418       int x = 1 << i;
419       REAL_VALUE_FROM_INT (s, x, 0, mode);
420 
421       if (REAL_VALUES_EQUAL (r, s))
422 	return 1;
423       if (!exact_real_inverse (mode, &s))
424 	abort ();
425       if (REAL_VALUES_EQUAL (r, s))
426 	return 1;
427     }
428   return 0;
429 }
430 
431 
432 /* Return the cost in cycles of a memory address, relative to register
433    indirect.
434 
435    Each of the following adds the indicated number of cycles:
436 
437    1 - symbolic address
438    1 - pre-decrement
439    1 - indexing and/or offset(register)
440    2 - indirect */
441 
442 
443 int
444 vax_address_cost (addr)
445     register rtx addr;
446 {
447   int reg = 0, indexed = 0, indir = 0, offset = 0, predec = 0;
448   rtx plus_op0 = 0, plus_op1 = 0;
449  restart:
450   switch (GET_CODE (addr))
451     {
452     case PRE_DEC:
453       predec = 1;
454     case REG:
455     case SUBREG:
456     case POST_INC:
457       reg = 1;
458       break;
459     case MULT:
460       indexed = 1;	/* 2 on VAX 2 */
461       break;
462     case CONST_INT:
463       /* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */
464       if (offset == 0)
465 	offset = (unsigned)(INTVAL(addr)+128) > 256;
466       break;
467     case CONST:
468     case SYMBOL_REF:
469       offset = 1;	/* 2 on VAX 2 */
470       break;
471     case LABEL_REF:	/* this is probably a byte offset from the pc */
472       if (offset == 0)
473 	offset = 1;
474       break;
475     case PLUS:
476       if (plus_op0)
477 	plus_op1 = XEXP (addr, 0);
478       else
479 	plus_op0 = XEXP (addr, 0);
480       addr = XEXP (addr, 1);
481       goto restart;
482     case MEM:
483       indir = 2;	/* 3 on VAX 2 */
484       addr = XEXP (addr, 0);
485       goto restart;
486     default:
487       break;
488     }
489 
490   /* Up to 3 things can be added in an address.  They are stored in
491      plus_op0, plus_op1, and addr.  */
492 
493   if (plus_op0)
494     {
495       addr = plus_op0;
496       plus_op0 = 0;
497       goto restart;
498     }
499   if (plus_op1)
500     {
501       addr = plus_op1;
502       plus_op1 = 0;
503       goto restart;
504     }
505   /* Indexing and register+offset can both be used (except on a VAX 2)
506      without increasing execution time over either one alone.  */
507   if (reg && indexed && offset)
508     return reg + indir + offset + predec;
509   return reg + indexed + indir + offset + predec;
510 }
511 
512 
513 /* Cost of an expression on a VAX.  This version has costs tuned for the
514    CVAX chip (found in the VAX 3 series) with comments for variations on
515    other models.  */
516 
517 int
518 vax_rtx_cost (x)
519     register rtx x;
520 {
521   register enum rtx_code code = GET_CODE (x);
522   enum machine_mode mode = GET_MODE (x);
523   register int c;
524   int i = 0;				/* may be modified in switch */
525   const char *fmt = GET_RTX_FORMAT (code); /* may be modified in switch */
526 
527   switch (code)
528     {
529     case POST_INC:
530       return 2;
531     case PRE_DEC:
532       return 3;
533     case MULT:
534       switch (mode)
535 	{
536 	case DFmode:
537 	  c = 16;		/* 4 on VAX 9000 */
538 	  break;
539 	case SFmode:
540 	  c = 9;		/* 4 on VAX 9000, 12 on VAX 2 */
541 	  break;
542 	case DImode:
543 	  c = 16;		/* 6 on VAX 9000, 28 on VAX 2 */
544 	  break;
545 	case SImode:
546 	case HImode:
547 	case QImode:
548 	  c = 10;		/* 3-4 on VAX 9000, 20-28 on VAX 2 */
549 	  break;
550 	default:
551 	  return MAX_COST;	/* Mode is not supported.  */
552 	}
553       break;
554     case UDIV:
555       if (mode != SImode)
556 	return MAX_COST;	/* Mode is not supported.  */
557       c = 17;
558       break;
559     case DIV:
560       if (mode == DImode)
561 	c = 30;	/* highly variable */
562       else if (mode == DFmode)
563 	/* divide takes 28 cycles if the result is not zero, 13 otherwise */
564 	c = 24;
565       else
566 	c = 11;			/* 25 on VAX 2 */
567       break;
568     case MOD:
569       c = 23;
570       break;
571     case UMOD:
572       if (mode != SImode)
573 	return MAX_COST;	/* Mode is not supported.  */
574       c = 29;
575       break;
576     case FLOAT:
577       c = 6 + (mode == DFmode) + (GET_MODE (XEXP (x, 0)) != SImode);
578       /* 4 on VAX 9000 */
579       break;
580     case FIX:
581       c = 7;			/* 17 on VAX 2 */
582       break;
583     case ASHIFT:
584     case LSHIFTRT:
585     case ASHIFTRT:
586       if (mode == DImode)
587 	c = 12;
588       else
589 	c = 10;			/* 6 on VAX 9000 */
590       break;
591     case ROTATE:
592     case ROTATERT:
593       c = 6;			/* 5 on VAX 2, 4 on VAX 9000 */
594       if (GET_CODE (XEXP (x, 1)) == CONST_INT)
595 	fmt = "e";	/* all constant rotate counts are short */
596       break;
597     case PLUS:
598       /* Check for small negative integer operand: subl2 can be used with
599 	 a short positive constant instead.  */
600       if (GET_CODE (XEXP (x, 1)) == CONST_INT)
601 	if ((unsigned)(INTVAL (XEXP (x, 1)) + 63) < 127)
602 	  fmt = "e";
603     case MINUS:
604       c = (mode == DFmode) ? 13 : 8;	/* 6/8 on VAX 9000, 16/15 on VAX 2 */
605     case IOR:
606     case XOR:
607       c = 3;
608       break;
609     case AND:
610       /* AND is special because the first operand is complemented.  */
611       c = 3;
612       if (GET_CODE (XEXP (x, 0)) == CONST_INT)
613 	{
614 	  if ((unsigned)~INTVAL (XEXP (x, 0)) > 63)
615 	    c = 4;
616 	  fmt = "e";
617 	  i = 1;
618 	}
619       break;
620     case NEG:
621       if (mode == DFmode)
622 	return 9;
623       else if (mode == SFmode)
624 	return 6;
625       else if (mode == DImode)
626 	return 4;
627     case NOT:
628       return 2;
629     case ZERO_EXTRACT:
630     case SIGN_EXTRACT:
631       c = 15;
632       break;
633     case MEM:
634       if (mode == DImode || mode == DFmode)
635 	c = 5;				/* 7 on VAX 2 */
636       else
637 	c = 3;				/* 4 on VAX 2 */
638       x = XEXP (x, 0);
639       if (GET_CODE (x) == REG || GET_CODE (x) == POST_INC)
640 	return c;
641       return c + vax_address_cost (x);
642     default:
643       c = 3;
644       break;
645     }
646 
647 
648   /* Now look inside the expression.  Operands which are not registers or
649      short constants add to the cost.
650 
651      FMT and I may have been adjusted in the switch above for instructions
652      which require special handling */
653 
654   while (*fmt++ == 'e')
655     {
656       register rtx op = XEXP (x, i++);
657       code = GET_CODE (op);
658 
659       /* A NOT is likely to be found as the first operand of an AND
660 	 (in which case the relevant cost is of the operand inside
661 	 the not) and not likely to be found anywhere else.  */
662       if (code == NOT)
663 	op = XEXP (op, 0), code = GET_CODE (op);
664 
665       switch (code)
666 	{
667 	case CONST_INT:
668 	  if ((unsigned)INTVAL (op) > 63 && GET_MODE (x) != QImode)
669 	    c += 1;		/* 2 on VAX 2 */
670 	  break;
671 	case CONST:
672 	case LABEL_REF:
673 	case SYMBOL_REF:
674 	  c += 1;		/* 2 on VAX 2 */
675 	  break;
676 	case CONST_DOUBLE:
677 	  if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT)
678 	    {
679 	      /* Registers are faster than floating point constants -- even
680 		 those constants which can be encoded in a single byte.  */
681 	      if (vax_float_literal (op))
682 		c++;
683 	      else
684 		c += (GET_MODE (x) == DFmode) ? 3 : 2;
685 	    }
686 	  else
687 	    {
688 	      if (CONST_DOUBLE_HIGH (op) != 0
689 		  || (unsigned)CONST_DOUBLE_LOW (op) > 63)
690 		c += 2;
691 	    }
692 	  break;
693 	case MEM:
694 	  c += 1;		/* 2 on VAX 2 */
695 	  if (GET_CODE (XEXP (op, 0)) != REG)
696 	    c += vax_address_cost (XEXP (op, 0));
697 	  break;
698 	case REG:
699 	case SUBREG:
700 	  break;
701 	default:
702 	  c += 1;
703 	  break;
704 	}
705     }
706   return c;
707 }
708 
709 #if VMS_TARGET
710 /* Additional support code for VMS target.  */
711 
712 /* Linked list of all externals that are to be emitted when optimizing
713    for the global pointer if they haven't been declared by the end of
714    the program with an appropriate .comm or initialization.  */
715 
716 static
717 struct extern_list {
718   struct extern_list *next;	/* next external */
719   const char *name;		/* name of the external */
720   int size;			/* external's actual size */
721   int in_const;			/* section type flag */
722 } *extern_head = 0, *pending_head = 0;
723 
724 /* Check whether NAME is already on the external definition list.  If not,
725    add it to either that list or the pending definition list.  */
726 
727 void
728 vms_check_external (decl, name, pending)
729      tree decl;
730      const char *name;
731      int pending;
732 {
733   register struct extern_list *p, *p0;
734 
735   for (p = extern_head; p; p = p->next)
736     if (!strcmp (p->name, name))
737       return;
738 
739   for (p = pending_head, p0 = 0; p; p0 = p, p = p->next)
740     if (!strcmp (p->name, name))
741       {
742 	if (pending)
743 	  return;
744 
745 	/* Was pending, but has now been defined; move it to other list.  */
746 	if (p == pending_head)
747 	  pending_head = p->next;
748 	else
749 	  p0->next = p->next;
750 	p->next = extern_head;
751 	extern_head = p;
752 	return;
753       }
754 
755   /* Not previously seen; create a new list entry.  */
756   p = (struct extern_list *) xmalloc (sizeof (struct extern_list));
757   p->name = name;
758 
759   if (pending)
760     {
761       /* Save the size and section type and link to `pending' list.  */
762       p->size = (DECL_SIZE (decl) == 0) ? 0 :
763 	TREE_INT_CST_LOW (size_binop (CEIL_DIV_EXPR, DECL_SIZE (decl),
764 				      size_int (BITS_PER_UNIT)));
765       p->in_const = (TREE_READONLY (decl) && ! TREE_THIS_VOLATILE (decl));
766 
767       p->next = pending_head;
768       pending_head = p;
769     }
770   else
771     {
772       /* Size and section type don't matter; link to `declared' list.  */
773       p->size = p->in_const = 0;        /* arbitrary init */
774 
775       p->next = extern_head;
776       extern_head = p;
777     }
778   return;
779 }
780 
781 void
782 vms_flush_pending_externals (file)
783      FILE *file;
784 {
785   register struct extern_list *p;
786 
787   while (pending_head)
788     {
789       /* Move next pending declaration to the "done" list.  */
790       p = pending_head;
791       pending_head = p->next;
792       p->next = extern_head;
793       extern_head = p;
794 
795       /* Now output the actual declaration.  */
796       if (p->in_const)
797 	const_section ();
798       else
799 	data_section ();
800       fputs (".comm ", file);
801       assemble_name (file, p->name);
802       fprintf (file, ",%d\n", p->size);
803     }
804 }
805 
806 static void
807 vms_asm_out_constructor (symbol, priority)
808      rtx symbol;
809      int priority ATTRIBUTE_UNUSED;
810 {
811   fprintf (asm_out_file,".globl $$PsectAttributes_NOOVR$$__gxx_init_1\n");
812   data_section();
813   fprintf (asm_out_file,"$$PsectAttributes_NOOVR$$__gxx_init_1:\n\t.long\t");
814   assemble_name (asm_out_file, XSTR (symbol, 0));
815   fputc ('\n', asm_out_file);
816 }
817 
818 static void
819 vms_asm_out_destructor (symbol, priority)
820      rtx symbol;
821      int priority ATTRIBUTE_UNUSED;
822 {
823   fprintf (asm_out_file,".globl $$PsectAttributes_NOOVR$$__gxx_clean_1\n");
824   data_section();
825   fprintf (asm_out_file,"$$PsectAttributes_NOOVR$$__gxx_clean_1:\n\t.long\t");
826   assemble_name (asm_out_file, XSTR (symbol, 0));
827   fputc ('\n', asm_out_file);
828 }
829 
830 static void
831 vms_select_section (exp, reloc, align)
832      tree exp;
833      int reloc ATTRIBUTE_UNUSED;
834      unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
835 {
836   if (TREE_CODE (exp) == VAR_DECL)
837     {
838       if (TREE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp)
839 	  && DECL_INITIAL (exp)
840 	  && (DECL_INITIAL (exp) == error_mark_node
841 	      || TREE_CONSTANT (DECL_INITIAL (exp))))
842 	{
843 	  if (TREE_PUBLIC (exp))
844 	    const_section ();
845 	  else
846 	    text_section ();
847 	}
848       else
849 	data_section ();
850     }
851   if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c')
852     {
853       if (TREE_CODE (exp) == STRING_CST && flag_writable_strings)
854 	data_section ();
855       else
856 	text_section ();
857     }
858 }
859 
860 /* Make sure that external variables are correctly addressed.  Under VMS
861    there is some brain damage in the linker that requires us to do this.  */
862 
863 static void
864 vms_encode_section_info (decl, first)
865      tree decl;
866      int first ATTRIBUTE_UNUSED;
867 {
868   if (DECL_EXTERNAL (decl) && TREE_PUBLIC (decl))
869     SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
870 }
871 
872 /* This is how to output a command to make the user-level label named NAME
873    defined for reference from other files.  */
874 static void
875 vms_globalize_label (stream, name)
876      FILE *stream;
877      const char *name;
878 {
879   default_globalize_label (stream, name);
880   vms_check_external (NULL_TREE, name, 0);
881 }
882 #endif /* VMS_TARGET */
883 
884 /* Additional support code for VMS host.  */
885 /* ??? This should really be in libiberty; vax.c is a target file.  */
886 #ifdef QSORT_WORKAROUND
887   /*
888 	Do not use VAXCRTL's qsort() due to a severe bug:  once you've
889 	sorted something which has a size that's an exact multiple of 4
890 	and is longword aligned, you cannot safely sort anything which
891 	is either not a multiple of 4 in size or not longword aligned.
892 	A static "move-by-longword" optimization flag inside qsort() is
893 	never reset.  This is known to affect VMS V4.6 through VMS V5.5-1,
894 	and was finally fixed in VMS V5.5-2.
895 
896 	In this work-around an insertion sort is used for simplicity.
897 	The qsort code from glibc should probably be used instead.
898    */
899 void
900 not_qsort (array, count, size, compare)
901      void *array;
902      unsigned count, size;
903      int (*compare)();
904 {
905 
906   if (size == sizeof (short))
907     {
908       register int i;
909       register short *next, *prev;
910       short tmp, *base = array;
911 
912       for (next = base, i = count - 1; i > 0; i--)
913 	{
914 	  prev = next++;
915 	  if ((*compare)(next, prev) < 0)
916 	    {
917 	      tmp = *next;
918 	      do  *(prev + 1) = *prev;
919 		while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0);
920 	      *(prev + 1) = tmp;
921 	    }
922 	}
923     }
924   else if (size == sizeof (long))
925     {
926       register int i;
927       register long *next, *prev;
928       long tmp, *base = array;
929 
930       for (next = base, i = count - 1; i > 0; i--)
931 	{
932 	  prev = next++;
933 	  if ((*compare)(next, prev) < 0)
934 	    {
935 	      tmp = *next;
936 	      do  *(prev + 1) = *prev;
937 		while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0);
938 	      *(prev + 1) = tmp;
939 	    }
940 	}
941     }
942   else  /* arbitrary size */
943     {
944       register int i;
945       register char *next, *prev, *tmp = alloca (size), *base = array;
946 
947       for (next = base, i = count - 1; i > 0; i--)
948 	{   /* count-1 forward iterations */
949 	  prev = next,  next += size;		/* increment front pointer */
950 	  if ((*compare)(next, prev) < 0)
951 	    {	/* found element out of order; move others up then re-insert */
952 	      memcpy (tmp, next, size);		/* save smaller element */
953 	      do { memcpy (prev + size, prev, size); /* move larger elem. up */
954 		   prev -= size;		/* decrement back pointer */
955 		 } while (prev >= base ? (*compare)(tmp, prev) < 0 : 0);
956 	      memcpy (prev + size, tmp, size);	/* restore small element */
957 	    }
958 	}
959 #ifdef USE_C_ALLOCA
960       alloca (0);
961 #endif
962     }
963 
964   return;
965 }
966 #endif /* QSORT_WORKAROUND */
967 
968 /* Return 1 if insn A follows B.  */
969 
970 static int
971 follows_p (a, b)
972      rtx a, b;
973 {
974   register rtx p;
975 
976   for (p = a; p != b; p = NEXT_INSN (p))
977     if (! p)
978       return 1;
979 
980   return 0;
981 }
982 
983 /* Returns 1 if we know operand OP was 0 before INSN.  */
984 
985 int
986 reg_was_0_p (insn, op)
987      rtx insn, op;
988 {
989   rtx link;
990 
991   return ((link = find_reg_note (insn, REG_WAS_0, 0))
992 	  /* Make sure the insn that stored the 0 is still present
993 	     and doesn't follow INSN in the insn sequence.  */
994 	  && ! INSN_DELETED_P (XEXP (link, 0))
995 	  && GET_CODE (XEXP (link, 0)) != NOTE
996 	  && ! follows_p (XEXP (link, 0), insn)
997 	  /* Make sure cross jumping didn't happen here.  */
998 	  && no_labels_between_p (XEXP (link, 0), insn)
999 	  /* Make sure the reg hasn't been clobbered.  */
1000 	  && ! reg_set_between_p (op, XEXP (link, 0), insn));
1001 }
1002 
1003 static void
1004 vax_output_mi_thunk (file, thunk, delta, vcall_offset, function)
1005      FILE *file;
1006      tree thunk ATTRIBUTE_UNUSED;
1007      HOST_WIDE_INT delta;
1008      HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED;
1009      tree function;
1010 {
1011   fprintf (file, "\t.word 0x0ffc\n");
1012   fprintf (file, "\taddl2 $");
1013   fprintf (file, HOST_WIDE_INT_PRINT_DEC, delta);
1014   asm_fprintf (file, ",4(%Rap)\n");
1015   fprintf (file, "\tjmp ");
1016   assemble_name (file,  XSTR (XEXP (DECL_RTL (function), 0), 0));
1017   fprintf (file, "+2\n");
1018 }
1019