1 /* Subroutines for insn-output.c for Vax.
2 Copyright (C) 1987, 1994 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
24 #include "hard-reg-set.h"
26 #include "insn-config.h"
27 #include "conditions.h"
28 #include "insn-flags.h"
30 #include "insn-attr.h"
33 /* This is like nonimmediate_operand with a restriction on the type of MEM. */
36 split_quadword_operands (operands, low, n)
43 low[0] = low[1] = low[2] = 0;
44 for (i = 0; i < 3; i++)
47 /* it's already been figured out */;
48 else if (GET_CODE (operands[i]) == MEM
49 && (GET_CODE (XEXP (operands[i], 0)) == POST_INC))
51 rtx addr = XEXP (operands[i], 0);
52 operands[i] = low[i] = gen_rtx (MEM, SImode, addr);
53 if (which_alternative == 0 && i == 0)
55 addr = XEXP (operands[i], 0);
56 operands[i+1] = low[i+1] = gen_rtx (MEM, SImode, addr);
61 low[i] = operand_subword (operands[i], 0, 0, DImode);
62 operands[i] = operand_subword (operands[i], 1, 0, DImode);
67 print_operand_address (file, addr)
71 register rtx reg1, reg2, breg, ireg;
75 switch (GET_CODE (addr))
79 addr = XEXP (addr, 0);
83 fprintf (file, "(%s)", reg_names[REGNO (addr)]);
87 fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
91 fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
95 /* There can be either two or three things added here. One must be a
96 REG. One can be either a REG or a MULT of a REG and an appropriate
97 constant, and the third can only be a constant or a MEM.
99 We get these two or three things and put the constant or MEM in
100 OFFSET, the MULT or REG in IREG, and the REG in BREG. If we have
101 a register and can't tell yet if it is a base or index register,
104 reg1 = 0; ireg = 0; breg = 0; offset = 0;
106 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
107 || GET_CODE (XEXP (addr, 0)) == MEM)
109 offset = XEXP (addr, 0);
110 addr = XEXP (addr, 1);
112 else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
113 || GET_CODE (XEXP (addr, 1)) == MEM)
115 offset = XEXP (addr, 1);
116 addr = XEXP (addr, 0);
118 else if (GET_CODE (XEXP (addr, 1)) == MULT)
120 ireg = XEXP (addr, 1);
121 addr = XEXP (addr, 0);
123 else if (GET_CODE (XEXP (addr, 0)) == MULT)
125 ireg = XEXP (addr, 0);
126 addr = XEXP (addr, 1);
128 else if (GET_CODE (XEXP (addr, 1)) == REG)
130 reg1 = XEXP (addr, 1);
131 addr = XEXP (addr, 0);
133 else if (GET_CODE (XEXP (addr, 0)) == REG)
135 reg1 = XEXP (addr, 0);
136 addr = XEXP (addr, 1);
141 if (GET_CODE (addr) == REG)
148 else if (GET_CODE (addr) == MULT)
150 else if (GET_CODE (addr) == PLUS)
152 if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
153 || GET_CODE (XEXP (addr, 0)) == MEM)
157 if (GET_CODE (offset) == CONST_INT)
158 offset = plus_constant (XEXP (addr, 0), INTVAL (offset));
159 else if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
160 offset = plus_constant (offset, INTVAL (XEXP (addr, 0)));
164 offset = XEXP (addr, 0);
166 else if (GET_CODE (XEXP (addr, 0)) == REG)
169 ireg = reg1, breg = XEXP (addr, 0), reg1 = 0;
171 reg1 = XEXP (addr, 0);
173 else if (GET_CODE (XEXP (addr, 0)) == MULT)
177 ireg = XEXP (addr, 0);
182 if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
183 || GET_CODE (XEXP (addr, 1)) == MEM)
187 if (GET_CODE (offset) == CONST_INT)
188 offset = plus_constant (XEXP (addr, 1), INTVAL (offset));
189 else if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
190 offset = plus_constant (offset, INTVAL (XEXP (addr, 1)));
194 offset = XEXP (addr, 1);
196 else if (GET_CODE (XEXP (addr, 1)) == REG)
199 ireg = reg1, breg = XEXP (addr, 1), reg1 = 0;
201 reg1 = XEXP (addr, 1);
203 else if (GET_CODE (XEXP (addr, 1)) == MULT)
207 ireg = XEXP (addr, 1);
215 /* If REG1 is non-zero, figure out if it is a base or index register. */
218 if (breg != 0 || (offset && GET_CODE (offset) == MEM))
229 output_address (offset);
232 fprintf (file, "(%s)", reg_names[REGNO (breg)]);
236 if (GET_CODE (ireg) == MULT)
237 ireg = XEXP (ireg, 0);
238 if (GET_CODE (ireg) != REG)
240 fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
245 output_addr_const (file, addr);
253 switch (GET_CODE (op))
285 register enum machine_mode mode;
287 union {double d; int i[2];} val;
289 if (GET_CODE (c) != CONST_DOUBLE)
294 if (c == const_tiny_rtx[(int) mode][0]
295 || c == const_tiny_rtx[(int) mode][1]
296 || c == const_tiny_rtx[(int) mode][2])
299 #if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
301 val.i[0] = CONST_DOUBLE_LOW (c);
302 val.i[1] = CONST_DOUBLE_HIGH (c);
304 for (i = 0; i < 7; i ++)
305 if (val.d == 1 << i || val.d == 1 / (1 << i))
312 /* Return the cost in cycles of a memory address, relative to register
315 Each of the following adds the indicated number of cycles:
319 1 - indexing and/or offset(register)
323 int vax_address_cost(addr)
326 int reg = 0, indexed = 0, indir = 0, offset = 0, predec = 0;
327 rtx plus_op0 = 0, plus_op1 = 0;
329 switch (GET_CODE (addr))
339 indexed = 1; /* 2 on VAX 2 */
342 /* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */
344 offset = (unsigned)(INTVAL(addr)+128) > 256;
348 offset = 1; /* 2 on VAX 2 */
350 case LABEL_REF: /* this is probably a byte offset from the pc */
356 plus_op1 = XEXP (addr, 0);
358 plus_op0 = XEXP (addr, 0);
359 addr = XEXP (addr, 1);
362 indir = 2; /* 3 on VAX 2 */
363 addr = XEXP (addr, 0);
367 /* Up to 3 things can be added in an address. They are stored in
368 plus_op0, plus_op1, and addr. */
382 /* Indexing and register+offset can both be used (except on a VAX 2)
383 without increasing execution time over either one alone. */
384 if (reg && indexed && offset)
385 return reg + indir + offset + predec;
386 return reg + indexed + indir + offset + predec;
390 /* Cost of an expression on a VAX. This version has costs tuned for the
391 CVAX chip (found in the VAX 3 series) with comments for variations on
398 register enum rtx_code code = GET_CODE (x);
399 enum machine_mode mode = GET_MODE (x);
401 int i = 0; /* may be modified in switch */
402 char *fmt = GET_RTX_FORMAT (code); /* may be modified in switch */
414 c = 16; /* 4 on VAX 9000 */
417 c = 9; /* 4 on VAX 9000, 12 on VAX 2 */
420 c = 16; /* 6 on VAX 9000, 28 on VAX 2 */
425 c = 10; /* 3-4 on VAX 9000, 20-28 on VAX 2 */
434 c = 30; /* highly variable */
435 else if (mode == DFmode)
436 /* divide takes 28 cycles if the result is not zero, 13 otherwise */
439 c = 11; /* 25 on VAX 2 */
448 c = 6 + (mode == DFmode) + (GET_MODE (XEXP (x, 0)) != SImode);
452 c = 7; /* 17 on VAX 2 */
460 c = 10; /* 6 on VAX 9000 */
464 c = 6; /* 5 on VAX 2, 4 on VAX 9000 */
465 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
466 fmt = "e"; /* all constant rotate counts are short */
469 /* Check for small negative integer operand: subl2 can be used with
470 a short positive constant instead. */
471 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
472 if ((unsigned)(INTVAL (XEXP (x, 1)) + 63) < 127)
475 c = (mode == DFmode) ? 13 : 8; /* 6/8 on VAX 9000, 16/15 on VAX 2 */
481 /* AND is special because the first operand is complemented. */
483 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
485 if ((unsigned)~INTVAL (XEXP (x, 0)) > 63)
494 else if (mode == SFmode)
496 else if (mode == DImode)
505 if (mode == DImode || mode == DFmode)
506 c = 5; /* 7 on VAX 2 */
508 c = 3; /* 4 on VAX 2 */
510 if (GET_CODE (x) == REG || GET_CODE (x) == POST_INC)
512 return c + vax_address_cost (x);
519 /* Now look inside the expression. Operands which are not registers or
520 short constants add to the cost.
522 FMT and I may have been adjusted in the switch above for instructions
523 which require special handling */
525 while (*fmt++ == 'e')
527 register rtx op = XEXP (x, i++);
528 code = GET_CODE (op);
530 /* A NOT is likely to be found as the first operand of an AND
531 (in which case the relevant cost is of the operand inside
532 the not) and not likely to be found anywhere else. */
534 op = XEXP (op, 0), code = GET_CODE (op);
539 if ((unsigned)INTVAL (op) > 63 && GET_MODE (x) != QImode)
540 c += 1; /* 2 on VAX 2 */
545 c += 1; /* 2 on VAX 2 */
548 if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT)
550 /* Registers are faster than floating point constants -- even
551 those constants which can be encoded in a single byte. */
552 if (vax_float_literal (op))
555 c += (GET_MODE (x) == DFmode) ? 3 : 2;
559 if (CONST_DOUBLE_HIGH (op) != 0
560 || (unsigned)CONST_DOUBLE_LOW (op) > 63)
565 c += 1; /* 2 on VAX 2 */
566 if (GET_CODE (XEXP (op, 0)) != REG)
567 c += vax_address_cost (XEXP (op, 0));
580 /* Check a `double' value for validity for a particular machine mode. */
582 static char *float_strings[] =
584 "1.70141173319264430e+38", /* 2^127 (2^24 - 1) / 2^24 */
585 "-1.70141173319264430e+38",
586 "2.93873587705571877e-39", /* 2^-128 */
587 "-2.93873587705571877e-39"
590 static REAL_VALUE_TYPE float_values[4];
592 static int inited_float_values = 0;
596 check_float_value (mode, d, overflow)
597 enum machine_mode mode;
601 if (inited_float_values == 0)
604 for (i = 0; i < 4; i++)
606 float_values[i] = REAL_VALUE_ATOF (float_strings[i], DFmode);
609 inited_float_values = 1;
614 bcopy (&float_values[0], d, sizeof (REAL_VALUE_TYPE));
618 if ((mode) == SFmode)
621 bcopy (d, &r, sizeof (REAL_VALUE_TYPE));
622 if (REAL_VALUES_LESS (float_values[0], r))
624 bcopy (&float_values[0], d, sizeof (REAL_VALUE_TYPE));
627 else if (REAL_VALUES_LESS (r, float_values[1]))
629 bcopy (&float_values[1], d, sizeof (REAL_VALUE_TYPE));
632 else if (REAL_VALUES_LESS (dconst0, r)
633 && REAL_VALUES_LESS (r, float_values[2]))
635 bcopy (&dconst0, d, sizeof (REAL_VALUE_TYPE));
638 else if (REAL_VALUES_LESS (r, dconst0)
639 && REAL_VALUES_LESS (float_values[3], r))
641 bcopy (&dconst0, d, sizeof (REAL_VALUE_TYPE));
649 /* Linked list of all externals that are to be emitted when optimizing
650 for the global pointer if they haven't been declared by the end of
651 the program with an appropriate .comm or initialization. */
654 struct extern_list *next; /* next external */
655 char *name; /* name of the external */
658 /* Return 1 if NAME has already had an external definition;
659 0 if it has not (so caller should output one). */
662 vms_check_external (name)
665 register struct extern_list *p;
667 for (p = extern_head; p; p = p->next)
668 if (!strcmp (p->name, name))
671 p = (struct extern_list *)permalloc ((long) sizeof (struct extern_list));
672 p->next = extern_head;
679 /* Additional support code for VMS. */
681 #ifdef QSORT_WORKAROUND
683 Do not use VAXCRTL's qsort() due to a severe bug: once you've
684 sorted something which has a size that's an exact multiple of 4
685 and is longword aligned, you cannot safely sort anything which
686 is either not a multiple of 4 in size or not longword aligned.
687 A static "move-by-longword" optimization flag inside qsort() is
688 never reset. This is known of affect VMS V4.6 through VMS V5.5-1.
690 In this work-around an insertion sort is used for simplicity.
691 The qsort code from glibc should probably be used instead.
694 not_qsort (array, count, size, compare)
696 unsigned count, size;
700 if (size == sizeof (short))
703 register short *next, *prev;
704 short tmp, *base = array;
706 for (next = base, i = count - 1; i > 0; i--)
709 if ((*compare)(next, prev) < 0)
712 do *(prev + 1) = *prev;
713 while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0);
718 else if (size == sizeof (long))
721 register long *next, *prev;
722 long tmp, *base = array;
724 for (next = base, i = count - 1; i > 0; i--)
727 if ((*compare)(next, prev) < 0)
730 do *(prev + 1) = *prev;
731 while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0);
736 else /* arbitrary size */
739 extern void *alloca ();
742 register char *next, *prev, *tmp = alloca (size), *base = array;
744 for (next = base, i = count - 1; i > 0; i--)
745 { /* count-1 forward iterations */
746 prev = next, next += size; /* increment front pointer */
747 if ((*compare)(next, prev) < 0)
748 { /* found element out of order; move others up then re-insert */
749 memcpy (tmp, next, size); /* save smaller element */
750 do { memcpy (prev + size, prev, size); /* move larger elem. up */
751 prev -= size; /* decrement back pointer */
752 } while (prev >= base ? (*compare)(tmp, prev) < 0 : 0);
753 memcpy (prev + size, tmp, size); /* restore small element */
763 #endif /* QSORT_WORKAROUND */