1 /* Subroutines for insn-output.c for Vax.
2 Copyright (C) 1987 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 */
461 c = 10; /* 6 on VAX 9000 */
465 c = 6; /* 5 on VAX 2, 4 on VAX 9000 */
466 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
467 fmt = "e"; /* all constant rotate counts are short */
470 /* Check for small negative integer operand: subl2 can be used with
471 a short positive constant instead. */
472 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
473 if ((unsigned)(INTVAL (XEXP (x, 1)) + 63) < 127)
476 c = (mode == DFmode) ? 13 : 8; /* 6/8 on VAX 9000, 16/15 on VAX 2 */
482 /* AND is special because the first operand is complemented. */
484 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
486 if ((unsigned)~INTVAL (XEXP (x, 0)) > 63)
495 else if (mode == SFmode)
497 else if (mode == DImode)
506 if (mode == DImode || mode == DFmode)
507 c = 5; /* 7 on VAX 2 */
509 c = 3; /* 4 on VAX 2 */
511 if (GET_CODE (x) == REG || GET_CODE (x) == POST_INC)
513 return c + vax_address_cost (x);
520 /* Now look inside the expression. Operands which are not registers or
521 short constants add to the cost.
523 FMT and I may have been adjusted in the switch above for instructions
524 which require special handling */
526 while (*fmt++ == 'e')
528 register rtx op = XEXP (x, i++);
529 code = GET_CODE (op);
531 /* A NOT is likely to be found as the first operand of an AND
532 (in which case the relevant cost is of the operand inside
533 the not) and not likely to be found anywhere else. */
535 op = XEXP (op, 0), code = GET_CODE (op);
540 if ((unsigned)INTVAL (op) > 63 && GET_MODE (x) != QImode)
541 c += 1; /* 2 on VAX 2 */
546 c += 1; /* 2 on VAX 2 */
549 if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT)
551 /* Registers are faster than floating point constants -- even
552 those constants which can be encoded in a single byte. */
553 if (vax_float_literal (op))
556 c += (GET_MODE (x) == DFmode) ? 3 : 2;
560 if (CONST_DOUBLE_HIGH (op) != 0
561 || (unsigned)CONST_DOUBLE_LOW (op) > 63)
566 c += 1; /* 2 on VAX 2 */
567 if (GET_CODE (XEXP (op, 0)) != REG)
568 c += vax_address_cost (XEXP (op, 0));
582 /* Additional support code for VMS. */
584 #ifdef QSORT_WORKAROUND
586 Do not use VAXCRTL's qsort() due to a severe bug: once you've
587 sorted something which has a size that's an exact multiple of 4
588 and is longword aligned, you cannot safely sort anything which
589 is either not a multiple of 4 in size or not longword aligned.
590 A static "move-by-longword" optimization flag inside qsort() is
591 never reset. This is known of affect VMS V4.6 through VMS V5.5-1.
593 In this work-around an insertion sort is used for simplicity.
594 The qsort code from glibc should probably be used instead.
597 not_qsort (array, count, size, compare)
599 unsigned count, size;
603 if (size == sizeof (short))
606 register short *next, *prev;
607 short tmp, *base = array;
609 for (next = base, i = count - 1; i > 0; i--)
612 if ((*compare)(next, prev) < 0)
615 do *(prev + 1) = *prev;
616 while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0);
621 else if (size == sizeof (long))
624 register long *next, *prev;
625 long tmp, *base = array;
627 for (next = base, i = count - 1; i > 0; i--)
630 if ((*compare)(next, prev) < 0)
633 do *(prev + 1) = *prev;
634 while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0);
639 else /* arbitrary size */
642 extern void *alloca ();
645 register char *next, *prev, *tmp = alloca (size), *base = array;
647 for (next = base, i = count - 1; i > 0; i--)
648 { /* count-1 forward iterations */
649 prev = next, next += size; /* increment front pointer */
650 if ((*compare)(next, prev) < 0)
651 { /* found element out of order; move others up then re-insert */
652 memcpy (tmp, next, size); /* save smaller element */
653 do { memcpy (prev + size, prev, size); /* move larger elem. up */
654 prev -= size; /* decrement back pointer */
655 } while (prev >= base ? (*compare)(tmp, prev) < 0 : 0);
656 memcpy (prev + size, tmp, size); /* restore small element */
666 #endif /* QSORT_WORKAROUND */