1 /* Subroutines for insn-output.c for Vax.
2 Copyright (C) 1987, 1994, 1995, 1997, 1998 Free Software Foundation, Inc.
4 This file is part of GNU CC.
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
25 #include "hard-reg-set.h"
27 #include "insn-config.h"
28 #include "conditions.h"
29 #include "insn-flags.h"
32 #include "insn-attr.h"
37 /* This is like nonimmediate_operand with a restriction on the type of MEM. */
40 split_quadword_operands (operands
, low
, n
)
47 low
[0] = low
[1] = low
[2] = 0;
48 for (i
= 0; i
< 3; i
++)
51 /* it's already been figured out */;
52 else if (GET_CODE (operands
[i
]) == MEM
53 && (GET_CODE (XEXP (operands
[i
], 0)) == POST_INC
))
55 rtx addr
= XEXP (operands
[i
], 0);
56 operands
[i
] = low
[i
] = gen_rtx (MEM
, SImode
, addr
);
57 if (which_alternative
== 0 && i
== 0)
59 addr
= XEXP (operands
[i
], 0);
60 operands
[i
+1] = low
[i
+1] = gen_rtx (MEM
, SImode
, addr
);
65 low
[i
] = operand_subword (operands
[i
], 0, 0, DImode
);
66 operands
[i
] = operand_subword (operands
[i
], 1, 0, DImode
);
71 print_operand_address (file
, addr
)
75 register rtx reg1
, reg2
, breg
, ireg
;
79 switch (GET_CODE (addr
))
83 addr
= XEXP (addr
, 0);
87 fprintf (file
, "(%s)", reg_names
[REGNO (addr
)]);
91 fprintf (file
, "-(%s)", reg_names
[REGNO (XEXP (addr
, 0))]);
95 fprintf (file
, "(%s)+", reg_names
[REGNO (XEXP (addr
, 0))]);
99 /* There can be either two or three things added here. One must be a
100 REG. One can be either a REG or a MULT of a REG and an appropriate
101 constant, and the third can only be a constant or a MEM.
103 We get these two or three things and put the constant or MEM in
104 OFFSET, the MULT or REG in IREG, and the REG in BREG. If we have
105 a register and can't tell yet if it is a base or index register,
108 reg1
= 0; ireg
= 0; breg
= 0; offset
= 0;
110 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0))
111 || GET_CODE (XEXP (addr
, 0)) == MEM
)
113 offset
= XEXP (addr
, 0);
114 addr
= XEXP (addr
, 1);
116 else if (CONSTANT_ADDRESS_P (XEXP (addr
, 1))
117 || GET_CODE (XEXP (addr
, 1)) == MEM
)
119 offset
= XEXP (addr
, 1);
120 addr
= XEXP (addr
, 0);
122 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
124 ireg
= XEXP (addr
, 1);
125 addr
= XEXP (addr
, 0);
127 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
129 ireg
= XEXP (addr
, 0);
130 addr
= XEXP (addr
, 1);
132 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
134 reg1
= XEXP (addr
, 1);
135 addr
= XEXP (addr
, 0);
137 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
139 reg1
= XEXP (addr
, 0);
140 addr
= XEXP (addr
, 1);
145 if (GET_CODE (addr
) == REG
)
152 else if (GET_CODE (addr
) == MULT
)
154 else if (GET_CODE (addr
) == PLUS
)
156 if (CONSTANT_ADDRESS_P (XEXP (addr
, 0))
157 || GET_CODE (XEXP (addr
, 0)) == MEM
)
161 if (GET_CODE (offset
) == CONST_INT
)
162 offset
= plus_constant (XEXP (addr
, 0), INTVAL (offset
));
163 else if (GET_CODE (XEXP (addr
, 0)) == CONST_INT
)
164 offset
= plus_constant (offset
, INTVAL (XEXP (addr
, 0)));
168 offset
= XEXP (addr
, 0);
170 else if (GET_CODE (XEXP (addr
, 0)) == REG
)
173 ireg
= reg1
, breg
= XEXP (addr
, 0), reg1
= 0;
175 reg1
= XEXP (addr
, 0);
177 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
181 ireg
= XEXP (addr
, 0);
186 if (CONSTANT_ADDRESS_P (XEXP (addr
, 1))
187 || GET_CODE (XEXP (addr
, 1)) == MEM
)
191 if (GET_CODE (offset
) == CONST_INT
)
192 offset
= plus_constant (XEXP (addr
, 1), INTVAL (offset
));
193 else if (GET_CODE (XEXP (addr
, 1)) == CONST_INT
)
194 offset
= plus_constant (offset
, INTVAL (XEXP (addr
, 1)));
198 offset
= XEXP (addr
, 1);
200 else if (GET_CODE (XEXP (addr
, 1)) == REG
)
203 ireg
= reg1
, breg
= XEXP (addr
, 1), reg1
= 0;
205 reg1
= XEXP (addr
, 1);
207 else if (GET_CODE (XEXP (addr
, 1)) == MULT
)
211 ireg
= XEXP (addr
, 1);
219 /* If REG1 is non-zero, figure out if it is a base or index register. */
222 if (breg
!= 0 || (offset
&& GET_CODE (offset
) == MEM
))
233 output_address (offset
);
236 fprintf (file
, "(%s)", reg_names
[REGNO (breg
)]);
240 if (GET_CODE (ireg
) == MULT
)
241 ireg
= XEXP (ireg
, 0);
242 if (GET_CODE (ireg
) != REG
)
244 fprintf (file
, "[%s]", reg_names
[REGNO (ireg
)]);
249 output_addr_const (file
, addr
);
257 switch (GET_CODE (op
))
289 register enum machine_mode mode
;
291 union {double d
; int i
[2];} val
;
293 if (GET_CODE (c
) != CONST_DOUBLE
)
298 if (c
== const_tiny_rtx
[(int) mode
][0]
299 || c
== const_tiny_rtx
[(int) mode
][1]
300 || c
== const_tiny_rtx
[(int) mode
][2])
303 #if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
305 val
.i
[0] = CONST_DOUBLE_LOW (c
);
306 val
.i
[1] = CONST_DOUBLE_HIGH (c
);
308 for (i
= 0; i
< 7; i
++)
309 if (val
.d
== 1 << i
|| val
.d
== 1 / (1 << i
))
316 /* Return the cost in cycles of a memory address, relative to register
319 Each of the following adds the indicated number of cycles:
323 1 - indexing and/or offset(register)
327 int vax_address_cost(addr
)
330 int reg
= 0, indexed
= 0, indir
= 0, offset
= 0, predec
= 0;
331 rtx plus_op0
= 0, plus_op1
= 0;
333 switch (GET_CODE (addr
))
343 indexed
= 1; /* 2 on VAX 2 */
346 /* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */
348 offset
= (unsigned)(INTVAL(addr
)+128) > 256;
352 offset
= 1; /* 2 on VAX 2 */
354 case LABEL_REF
: /* this is probably a byte offset from the pc */
360 plus_op1
= XEXP (addr
, 0);
362 plus_op0
= XEXP (addr
, 0);
363 addr
= XEXP (addr
, 1);
366 indir
= 2; /* 3 on VAX 2 */
367 addr
= XEXP (addr
, 0);
371 /* Up to 3 things can be added in an address. They are stored in
372 plus_op0, plus_op1, and addr. */
386 /* Indexing and register+offset can both be used (except on a VAX 2)
387 without increasing execution time over either one alone. */
388 if (reg
&& indexed
&& offset
)
389 return reg
+ indir
+ offset
+ predec
;
390 return reg
+ indexed
+ indir
+ offset
+ predec
;
394 /* Cost of an expression on a VAX. This version has costs tuned for the
395 CVAX chip (found in the VAX 3 series) with comments for variations on
402 register enum rtx_code code
= GET_CODE (x
);
403 enum machine_mode mode
= GET_MODE (x
);
405 int i
= 0; /* may be modified in switch */
406 const char *fmt
= GET_RTX_FORMAT (code
); /* may be modified in switch */
418 c
= 16; /* 4 on VAX 9000 */
421 c
= 9; /* 4 on VAX 9000, 12 on VAX 2 */
424 c
= 16; /* 6 on VAX 9000, 28 on VAX 2 */
429 c
= 10; /* 3-4 on VAX 9000, 20-28 on VAX 2 */
438 c
= 30; /* highly variable */
439 else if (mode
== DFmode
)
440 /* divide takes 28 cycles if the result is not zero, 13 otherwise */
443 c
= 11; /* 25 on VAX 2 */
452 c
= 6 + (mode
== DFmode
) + (GET_MODE (XEXP (x
, 0)) != SImode
);
456 c
= 7; /* 17 on VAX 2 */
464 c
= 10; /* 6 on VAX 9000 */
468 c
= 6; /* 5 on VAX 2, 4 on VAX 9000 */
469 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
470 fmt
= "e"; /* all constant rotate counts are short */
473 /* Check for small negative integer operand: subl2 can be used with
474 a short positive constant instead. */
475 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
476 if ((unsigned)(INTVAL (XEXP (x
, 1)) + 63) < 127)
479 c
= (mode
== DFmode
) ? 13 : 8; /* 6/8 on VAX 9000, 16/15 on VAX 2 */
485 /* AND is special because the first operand is complemented. */
487 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
489 if ((unsigned)~INTVAL (XEXP (x
, 0)) > 63)
498 else if (mode
== SFmode
)
500 else if (mode
== DImode
)
509 if (mode
== DImode
|| mode
== DFmode
)
510 c
= 5; /* 7 on VAX 2 */
512 c
= 3; /* 4 on VAX 2 */
514 if (GET_CODE (x
) == REG
|| GET_CODE (x
) == POST_INC
)
516 return c
+ vax_address_cost (x
);
523 /* Now look inside the expression. Operands which are not registers or
524 short constants add to the cost.
526 FMT and I may have been adjusted in the switch above for instructions
527 which require special handling */
529 while (*fmt
++ == 'e')
531 register rtx op
= XEXP (x
, i
++);
532 code
= GET_CODE (op
);
534 /* A NOT is likely to be found as the first operand of an AND
535 (in which case the relevant cost is of the operand inside
536 the not) and not likely to be found anywhere else. */
538 op
= XEXP (op
, 0), code
= GET_CODE (op
);
543 if ((unsigned)INTVAL (op
) > 63 && GET_MODE (x
) != QImode
)
544 c
+= 1; /* 2 on VAX 2 */
549 c
+= 1; /* 2 on VAX 2 */
552 if (GET_MODE_CLASS (GET_MODE (op
)) == MODE_FLOAT
)
554 /* Registers are faster than floating point constants -- even
555 those constants which can be encoded in a single byte. */
556 if (vax_float_literal (op
))
559 c
+= (GET_MODE (x
) == DFmode
) ? 3 : 2;
563 if (CONST_DOUBLE_HIGH (op
) != 0
564 || (unsigned)CONST_DOUBLE_LOW (op
) > 63)
569 c
+= 1; /* 2 on VAX 2 */
570 if (GET_CODE (XEXP (op
, 0)) != REG
)
571 c
+= vax_address_cost (XEXP (op
, 0));
584 /* Check a `double' value for validity for a particular machine mode. */
586 static char *float_strings
[] =
588 "1.70141173319264430e+38", /* 2^127 (2^24 - 1) / 2^24 */
589 "-1.70141173319264430e+38",
590 "2.93873587705571877e-39", /* 2^-128 */
591 "-2.93873587705571877e-39"
594 static REAL_VALUE_TYPE float_values
[4];
596 static int inited_float_values
= 0;
600 check_float_value (mode
, d
, overflow
)
601 enum machine_mode mode
;
605 if (inited_float_values
== 0)
608 for (i
= 0; i
< 4; i
++)
610 float_values
[i
] = REAL_VALUE_ATOF (float_strings
[i
], DFmode
);
613 inited_float_values
= 1;
618 bcopy ((char *) &float_values
[0], (char *) d
, sizeof (REAL_VALUE_TYPE
));
622 if ((mode
) == SFmode
)
625 bcopy ((char *) d
, (char *) &r
, sizeof (REAL_VALUE_TYPE
));
626 if (REAL_VALUES_LESS (float_values
[0], r
))
628 bcopy ((char *) &float_values
[0], (char *) d
,
629 sizeof (REAL_VALUE_TYPE
));
632 else if (REAL_VALUES_LESS (r
, float_values
[1]))
634 bcopy ((char *) &float_values
[1], (char*) d
,
635 sizeof (REAL_VALUE_TYPE
));
638 else if (REAL_VALUES_LESS (dconst0
, r
)
639 && REAL_VALUES_LESS (r
, float_values
[2]))
641 bcopy ((char *) &dconst0
, (char *) d
, sizeof (REAL_VALUE_TYPE
));
644 else if (REAL_VALUES_LESS (r
, dconst0
)
645 && REAL_VALUES_LESS (float_values
[3], r
))
647 bcopy ((char *) &dconst0
, (char *) d
, sizeof (REAL_VALUE_TYPE
));
656 /* Additional support code for VMS target. */
658 /* Linked list of all externals that are to be emitted when optimizing
659 for the global pointer if they haven't been declared by the end of
660 the program with an appropriate .comm or initialization. */
664 struct extern_list
*next
; /* next external */
665 char *name
; /* name of the external */
666 int size
; /* external's actual size */
667 int in_const
; /* section type flag */
668 } *extern_head
= 0, *pending_head
= 0;
670 /* Check whether NAME is already on the external definition list. If not,
671 add it to either that list or the pending definition list. */
674 vms_check_external (decl
, name
, pending
)
679 register struct extern_list
*p
, *p0
;
681 for (p
= extern_head
; p
; p
= p
->next
)
682 if (!strcmp (p
->name
, name
))
685 for (p
= pending_head
, p0
= 0; p
; p0
= p
, p
= p
->next
)
686 if (!strcmp (p
->name
, name
))
691 /* Was pending, but has now been defined; move it to other list. */
692 if (p
== pending_head
)
693 pending_head
= p
->next
;
696 p
->next
= extern_head
;
701 /* Not previously seen; create a new list entry. */
702 p
= (struct extern_list
*)permalloc ((long) sizeof (struct extern_list
));
707 /* Save the size and section type and link to `pending' list. */
708 p
->size
= (DECL_SIZE (decl
) == 0) ? 0 :
709 TREE_INT_CST_LOW (size_binop (CEIL_DIV_EXPR
, DECL_SIZE (decl
),
710 size_int (BITS_PER_UNIT
)));
711 p
->in_const
= (TREE_READONLY (decl
) && ! TREE_THIS_VOLATILE (decl
));
713 p
->next
= pending_head
;
718 /* Size and section type don't matter; link to `declared' list. */
719 p
->size
= p
->in_const
= 0; /* arbitrary init */
721 p
->next
= extern_head
;
728 vms_flush_pending_externals (file
)
731 register struct extern_list
*p
;
735 /* Move next pending declaration to the "done" list. */
737 pending_head
= p
->next
;
738 p
->next
= extern_head
;
741 /* Now output the actual declaration. */
746 fputs (".comm ", file
);
747 assemble_name (file
, p
->name
);
748 fprintf (file
, ",%d\n", p
->size
);
751 #endif /* VMS_TARGET */
754 /* Additional support code for VMS host. */
756 #ifdef QSORT_WORKAROUND
758 Do not use VAXCRTL's qsort() due to a severe bug: once you've
759 sorted something which has a size that's an exact multiple of 4
760 and is longword aligned, you cannot safely sort anything which
761 is either not a multiple of 4 in size or not longword aligned.
762 A static "move-by-longword" optimization flag inside qsort() is
763 never reset. This is known of affect VMS V4.6 through VMS V5.5-1,
764 and was finally fixed in VMS V5.5-2.
766 In this work-around an insertion sort is used for simplicity.
767 The qsort code from glibc should probably be used instead.
770 not_qsort (array
, count
, size
, compare
)
772 unsigned count
, size
;
776 if (size
== sizeof (short))
779 register short *next
, *prev
;
780 short tmp
, *base
= array
;
782 for (next
= base
, i
= count
- 1; i
> 0; i
--)
785 if ((*compare
)(next
, prev
) < 0)
788 do *(prev
+ 1) = *prev
;
789 while (--prev
>= base
? (*compare
)(&tmp
, prev
) < 0 : 0);
794 else if (size
== sizeof (long))
797 register long *next
, *prev
;
798 long tmp
, *base
= array
;
800 for (next
= base
, i
= count
- 1; i
> 0; i
--)
803 if ((*compare
)(next
, prev
) < 0)
806 do *(prev
+ 1) = *prev
;
807 while (--prev
>= base
? (*compare
)(&tmp
, prev
) < 0 : 0);
812 else /* arbitrary size */
815 register char *next
, *prev
, *tmp
= alloca (size
), *base
= array
;
817 for (next
= base
, i
= count
- 1; i
> 0; i
--)
818 { /* count-1 forward iterations */
819 prev
= next
, next
+= size
; /* increment front pointer */
820 if ((*compare
)(next
, prev
) < 0)
821 { /* found element out of order; move others up then re-insert */
822 memcpy (tmp
, next
, size
); /* save smaller element */
823 do { memcpy (prev
+ size
, prev
, size
); /* move larger elem. up */
824 prev
-= size
; /* decrement back pointer */
825 } while (prev
>= base
? (*compare
)(tmp
, prev
) < 0 : 0);
826 memcpy (prev
+ size
, tmp
, size
); /* restore small element */
836 #endif /* QSORT_WORKAROUND */