|
|
1.1 root 1: /* Subroutines for insn-output.c for Vax.
2: Copyright (C) 1987 Free Software Foundation, Inc.
3:
4: This file is part of GNU CC.
5:
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)
9: any later version.
10:
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.
15:
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. */
19:
20: #include <stdio.h>
21: #include "config.h"
22: #include "rtl.h"
23: #include "regs.h"
24: #include "hard-reg-set.h"
25: #include "real.h"
26: #include "insn-config.h"
27: #include "conditions.h"
28: #include "insn-flags.h"
29: #include "output.h"
30: #include "insn-attr.h"
31:
32:
33: /* This is like nonimmediate_operand with a restriction on the type of MEM. */
34:
35: void
36: split_quadword_operands (operands, low, n)
37: rtx *operands, *low;
38: int n;
39: {
40: int i;
41: /* Split operands. */
42:
43: low[0] = low[1] = low[2] = 0;
44: for (i = 0; i < 3; i++)
45: {
46: if (low[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))
50: {
51: rtx addr = XEXP (operands[i], 0);
52: operands[i] = low[i] = gen_rtx (MEM, SImode, addr);
53: if (which_alternative == 0 && i == 0)
54: {
55: addr = XEXP (operands[i], 0);
56: operands[i+1] = low[i+1] = gen_rtx (MEM, SImode, addr);
57: }
58: }
59: else
60: {
61: low[i] = operand_subword (operands[i], 0, 0, DImode);
62: operands[i] = operand_subword (operands[i], 1, 0, DImode);
63: }
64: }
65: }
66:
67: print_operand_address (file, addr)
68: FILE *file;
69: register rtx addr;
70: {
71: register rtx reg1, reg2, breg, ireg;
72: rtx offset;
73:
74: retry:
75: switch (GET_CODE (addr))
76: {
77: case MEM:
78: fprintf (file, "*");
79: addr = XEXP (addr, 0);
80: goto retry;
81:
82: case REG:
83: fprintf (file, "(%s)", reg_names[REGNO (addr)]);
84: break;
85:
86: case PRE_DEC:
87: fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
88: break;
89:
90: case POST_INC:
91: fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
92: break;
93:
94: case PLUS:
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.
98:
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,
102: put it into REG1. */
103:
104: reg1 = 0; ireg = 0; breg = 0; offset = 0;
105:
106: if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
107: || GET_CODE (XEXP (addr, 0)) == MEM)
108: {
109: offset = XEXP (addr, 0);
110: addr = XEXP (addr, 1);
111: }
112: else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
113: || GET_CODE (XEXP (addr, 1)) == MEM)
114: {
115: offset = XEXP (addr, 1);
116: addr = XEXP (addr, 0);
117: }
118: else if (GET_CODE (XEXP (addr, 1)) == MULT)
119: {
120: ireg = XEXP (addr, 1);
121: addr = XEXP (addr, 0);
122: }
123: else if (GET_CODE (XEXP (addr, 0)) == MULT)
124: {
125: ireg = XEXP (addr, 0);
126: addr = XEXP (addr, 1);
127: }
128: else if (GET_CODE (XEXP (addr, 1)) == REG)
129: {
130: reg1 = XEXP (addr, 1);
131: addr = XEXP (addr, 0);
132: }
133: else if (GET_CODE (XEXP (addr, 0)) == REG)
134: {
135: reg1 = XEXP (addr, 0);
136: addr = XEXP (addr, 1);
137: }
138: else
139: abort ();
140:
141: if (GET_CODE (addr) == REG)
142: {
143: if (reg1)
144: ireg = addr;
145: else
146: reg1 = addr;
147: }
148: else if (GET_CODE (addr) == MULT)
149: ireg = addr;
150: else if (GET_CODE (addr) == PLUS)
151: {
152: if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
153: || GET_CODE (XEXP (addr, 0)) == MEM)
154: {
155: if (offset)
156: {
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)));
161: else
162: abort ();
163: }
164: offset = XEXP (addr, 0);
165: }
166: else if (GET_CODE (XEXP (addr, 0)) == REG)
167: {
168: if (reg1)
169: ireg = reg1, breg = XEXP (addr, 0), reg1 = 0;
170: else
171: reg1 = XEXP (addr, 0);
172: }
173: else if (GET_CODE (XEXP (addr, 0)) == MULT)
174: {
175: if (ireg)
176: abort ();
177: ireg = XEXP (addr, 0);
178: }
179: else
180: abort ();
181:
182: if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
183: || GET_CODE (XEXP (addr, 1)) == MEM)
184: {
185: if (offset)
186: {
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)));
191: else
192: abort ();
193: }
194: offset = XEXP (addr, 1);
195: }
196: else if (GET_CODE (XEXP (addr, 1)) == REG)
197: {
198: if (reg1)
199: ireg = reg1, breg = XEXP (addr, 1), reg1 = 0;
200: else
201: reg1 = XEXP (addr, 1);
202: }
203: else if (GET_CODE (XEXP (addr, 1)) == MULT)
204: {
205: if (ireg)
206: abort ();
207: ireg = XEXP (addr, 1);
208: }
209: else
210: abort ();
211: }
212: else
213: abort ();
214:
215: /* If REG1 is non-zero, figure out if it is a base or index register. */
216: if (reg1)
217: {
218: if (breg != 0 || (offset && GET_CODE (offset) == MEM))
219: {
220: if (ireg)
221: abort ();
222: ireg = reg1;
223: }
224: else
225: breg = reg1;
226: }
227:
228: if (offset != 0)
229: output_address (offset);
230:
231: if (breg != 0)
232: fprintf (file, "(%s)", reg_names[REGNO (breg)]);
233:
234: if (ireg != 0)
235: {
236: if (GET_CODE (ireg) == MULT)
237: ireg = XEXP (ireg, 0);
238: if (GET_CODE (ireg) != REG)
239: abort ();
240: fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
241: }
242: break;
243:
244: default:
245: output_addr_const (file, addr);
246: }
247: }
248:
249: char *
250: rev_cond_name (op)
251: rtx op;
252: {
253: switch (GET_CODE (op))
254: {
255: case EQ:
256: return "neq";
257: case NE:
258: return "eql";
259: case LT:
260: return "geq";
261: case LE:
262: return "gtr";
263: case GT:
264: return "leq";
265: case GE:
266: return "lss";
267: case LTU:
268: return "gequ";
269: case LEU:
270: return "gtru";
271: case GTU:
272: return "lequ";
273: case GEU:
274: return "lssu";
275:
276: default:
277: abort ();
278: }
279: }
280:
281: int
282: vax_float_literal(c)
283: register rtx c;
284: {
285: register enum machine_mode mode;
286: int i;
287: union {double d; int i[2];} val;
288:
289: if (GET_CODE (c) != CONST_DOUBLE)
290: return 0;
291:
292: mode = GET_MODE (c);
293:
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])
297: return 1;
298:
299: #if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
300:
301: val.i[0] = CONST_DOUBLE_LOW (c);
302: val.i[1] = CONST_DOUBLE_HIGH (c);
303:
304: for (i = 0; i < 7; i ++)
305: if (val.d == 1 << i || val.d == 1 / (1 << i))
306: return 1;
307: #endif
308: return 0;
309: }
310:
311:
312: /* Return the cost in cycles of a memory address, relative to register
313: indirect.
314:
315: Each of the following adds the indicated number of cycles:
316:
317: 1 - symbolic address
318: 1 - pre-decrement
319: 1 - indexing and/or offset(register)
320: 2 - indirect */
321:
322:
323: int vax_address_cost(addr)
324: register rtx addr;
325: {
326: int reg = 0, indexed = 0, indir = 0, offset = 0, predec = 0;
327: rtx plus_op0 = 0, plus_op1 = 0;
328: restart:
329: switch (GET_CODE (addr))
330: {
331: case PRE_DEC:
332: predec = 1;
333: case REG:
334: case SUBREG:
335: case POST_INC:
336: reg = 1;
337: break;
338: case MULT:
339: indexed = 1; /* 2 on VAX 2 */
340: break;
341: case CONST_INT:
342: /* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */
343: if (offset == 0)
344: offset = (unsigned)(INTVAL(addr)+128) > 256;
345: break;
346: case CONST:
347: case SYMBOL_REF:
348: offset = 1; /* 2 on VAX 2 */
349: break;
350: case LABEL_REF: /* this is probably a byte offset from the pc */
351: if (offset == 0)
352: offset = 1;
353: break;
354: case PLUS:
355: if (plus_op0)
356: plus_op1 = XEXP (addr, 0);
357: else
358: plus_op0 = XEXP (addr, 0);
359: addr = XEXP (addr, 1);
360: goto restart;
361: case MEM:
362: indir = 2; /* 3 on VAX 2 */
363: addr = XEXP (addr, 0);
364: goto restart;
365: }
366:
367: /* Up to 3 things can be added in an address. They are stored in
368: plus_op0, plus_op1, and addr. */
369:
370: if (plus_op0)
371: {
372: addr = plus_op0;
373: plus_op0 = 0;
374: goto restart;
375: }
376: if (plus_op1)
377: {
378: addr = plus_op1;
379: plus_op1 = 0;
380: goto restart;
381: }
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;
387: }
388:
389:
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
392: other models. */
393:
394: int
395: vax_rtx_cost (x)
396: register rtx x;
397: {
398: register enum rtx_code code = GET_CODE (x);
399: enum machine_mode mode = GET_MODE (x);
400: register int c;
401: int i = 0; /* may be modified in switch */
402: char *fmt = GET_RTX_FORMAT (code); /* may be modified in switch */
403:
404: switch (code)
405: {
406: case POST_INC:
407: return 2;
408: case PRE_DEC:
409: return 3;
410: case MULT:
411: switch (mode)
412: {
413: case DFmode:
414: c = 16; /* 4 on VAX 9000 */
415: break;
416: case SFmode:
417: c = 9; /* 4 on VAX 9000, 12 on VAX 2 */
418: break;
419: case DImode:
420: c = 16; /* 6 on VAX 9000, 28 on VAX 2 */
421: break;
422: case SImode:
423: case HImode:
424: case QImode:
425: c = 10; /* 3-4 on VAX 9000, 20-28 on VAX 2 */
426: break;
427: }
428: break;
429: case UDIV:
430: c = 17;
431: break;
432: case DIV:
433: if (mode == DImode)
434: c = 30; /* highly variable */
435: else if (mode == DFmode)
436: /* divide takes 28 cycles if the result is not zero, 13 otherwise */
437: c = 24;
438: else
439: c = 11; /* 25 on VAX 2 */
440: break;
441: case MOD:
442: c = 23;
443: break;
444: case UMOD:
445: c = 29;
446: break;
447: case FLOAT:
448: c = 6 + (mode == DFmode) + (GET_MODE (XEXP (x, 0)) != SImode);
449: /* 4 on VAX 9000 */
450: break;
451: case FIX:
452: c = 7; /* 17 on VAX 2 */
453: break;
454: case LSHIFT:
455: case ASHIFT:
456: case LSHIFTRT:
457: case ASHIFTRT:
458: if (mode == DImode)
459: c = 12;
460: else
461: c = 10; /* 6 on VAX 9000 */
462: break;
463: case ROTATE:
464: case ROTATERT:
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 */
468: break;
469: case PLUS:
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)
474: fmt = "e";
475: case MINUS:
476: c = (mode == DFmode) ? 13 : 8; /* 6/8 on VAX 9000, 16/15 on VAX 2 */
477: case IOR:
478: case XOR:
479: c = 3;
480: break;
481: case AND:
482: /* AND is special because the first operand is complemented. */
483: c = 3;
484: if (GET_CODE (XEXP (x, 0)) == CONST_INT)
485: {
486: if ((unsigned)~INTVAL (XEXP (x, 0)) > 63)
487: c = 4;
488: fmt = "e";
489: i = 1;
490: }
491: break;
492: case NEG:
493: if (mode == DFmode)
494: return 9;
495: else if (mode == SFmode)
496: return 6;
497: else if (mode == DImode)
498: return 4;
499: case NOT:
500: return 2;
501: case ZERO_EXTRACT:
502: case SIGN_EXTRACT:
503: c = 15;
504: break;
505: case MEM:
506: if (mode == DImode || mode == DFmode)
507: c = 5; /* 7 on VAX 2 */
508: else
509: c = 3; /* 4 on VAX 2 */
510: x = XEXP (x, 0);
511: if (GET_CODE (x) == REG || GET_CODE (x) == POST_INC)
512: return c;
513: return c + vax_address_cost (x);
514: default:
515: c = 3;
516: break;
517: }
518:
519:
520: /* Now look inside the expression. Operands which are not registers or
521: short constants add to the cost.
522:
523: FMT and I may have been adjusted in the switch above for instructions
524: which require special handling */
525:
526: while (*fmt++ == 'e')
527: {
528: register rtx op = XEXP (x, i++);
529: code = GET_CODE (op);
530:
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. */
534: if (code == NOT)
535: op = XEXP (op, 0), code = GET_CODE (op);
536:
537: switch (code)
538: {
539: case CONST_INT:
540: if ((unsigned)INTVAL (op) > 63 && GET_MODE (x) != QImode)
541: c += 1; /* 2 on VAX 2 */
542: break;
543: case CONST:
544: case LABEL_REF:
545: case SYMBOL_REF:
546: c += 1; /* 2 on VAX 2 */
547: break;
548: case CONST_DOUBLE:
549: if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT)
550: {
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))
554: c++;
555: else
556: c += (GET_MODE (x) == DFmode) ? 3 : 2;
557: }
558: else
559: {
560: if (CONST_DOUBLE_HIGH (op) != 0
561: || (unsigned)CONST_DOUBLE_LOW (op) > 63)
562: c += 2;
563: }
564: break;
565: case MEM:
566: c += 1; /* 2 on VAX 2 */
567: if (GET_CODE (XEXP (op, 0)) != REG)
568: c += vax_address_cost (XEXP (op, 0));
569: break;
570: case REG:
571: case SUBREG:
572: break;
573: default:
574: c += 1;
575: break;
576: }
577: }
578: return c;
579: }
580:
581: /* Check a `double' value for validity for a particular machine mode. */
582:
583: static char *float_strings[] =
584: {
585: "1.70141173319264430e+38", /* 2^127 (2^24 - 1) / 2^24 */
586: "-1.70141173319264430e+38",
587: "2.93873587705571877e-39", /* 2^-128 */
588: "-2.93873587705571877e-39"
589: };
590:
591: static REAL_VALUE_TYPE float_values[4];
592:
593: static int inited_float_values = 0;
594:
595:
596: void
597: check_float_value (mode, d)
598: enum machine_mode mode;
599: REAL_VALUE_TYPE *d;
600: {
601:
602: if (inited_float_values == 0)
603: {
604: int i;
605: for (i = 0; i < 4; i++)
606: {
607: float_values[i] = REAL_VALUE_ATOF (float_strings[i], DFmode);
608: }
609: inited_float_values = 1;
610: }
611:
612: if ((mode) == SFmode)
613: {
614: REAL_VALUE_TYPE r;
615: bcopy (d, &r, sizeof (REAL_VALUE_TYPE));
616: if (REAL_VALUES_LESS (float_values[0], r))
617: {
618: error ("magnitude of constant too large for `float'");
619: bcopy (&float_values[0], d, sizeof (REAL_VALUE_TYPE));
620: }
621: else if (REAL_VALUES_LESS (r, float_values[1]))
622: {
623: error ("magnitude of constant too large for `float'");
624: bcopy (&float_values[1], d, sizeof (REAL_VALUE_TYPE));
625: }
626: else if (REAL_VALUES_LESS (dconst0, r)
627: && REAL_VALUES_LESS (r, float_values[2]))
628: {
629: warning ("`float' constant truncated to zero");
630: bcopy (&dconst0, d, sizeof (REAL_VALUE_TYPE));
631: }
632: else if (REAL_VALUES_LESS (r, dconst0)
633: && REAL_VALUES_LESS (float_values[3], r))
634: {
635: warning ("`float' constant truncated to zero");
636: bcopy (&dconst0, d, sizeof (REAL_VALUE_TYPE));
637: }
638: }
639: }
640:
641: /* Linked list of all externals that are to be emitted when optimizing
642: for the global pointer if they haven't been declared by the end of
643: the program with an appropriate .comm or initialization. */
644:
645: struct extern_list {
646: struct extern_list *next; /* next external */
647: char *name; /* name of the external */
648: } *extern_head = 0;
649:
650: /* Return 1 if NAME has already had an external definition;
651: 0 if it has not (so caller should output one). */
652:
653: int
654: vms_check_external (name)
655: char *name;
656: {
657: register struct extern_list *p;
658:
659: for (p = extern_head; p; p = p->next)
660: if (!strcmp (p->name, name))
661: return 1;
662:
663: p = (struct extern_list *)permalloc ((long) sizeof (struct extern_list));
664: p->next = extern_head;
665: p->name = name;
666: extern_head = p;
667: return 0;
668: }
669:
670: #ifdef VMS
671: /* Additional support code for VMS. */
672:
673: #ifdef QSORT_WORKAROUND
674: /*
675: Do not use VAXCRTL's qsort() due to a severe bug: once you've
676: sorted something which has a size that's an exact multiple of 4
677: and is longword aligned, you cannot safely sort anything which
678: is either not a multiple of 4 in size or not longword aligned.
679: A static "move-by-longword" optimization flag inside qsort() is
680: never reset. This is known of affect VMS V4.6 through VMS V5.5-1.
681:
682: In this work-around an insertion sort is used for simplicity.
683: The qsort code from glibc should probably be used instead.
684: */
685: void
686: not_qsort (array, count, size, compare)
687: void *array;
688: unsigned count, size;
689: int (*compare)();
690: {
691:
692: if (size == sizeof (short))
693: {
694: register int i;
695: register short *next, *prev;
696: short tmp, *base = array;
697:
698: for (next = base, i = count - 1; i > 0; i--)
699: {
700: prev = next++;
701: if ((*compare)(next, prev) < 0)
702: {
703: tmp = *next;
704: do *(prev + 1) = *prev;
705: while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0);
706: *(prev + 1) = tmp;
707: }
708: }
709: }
710: else if (size == sizeof (long))
711: {
712: register int i;
713: register long *next, *prev;
714: long tmp, *base = array;
715:
716: for (next = base, i = count - 1; i > 0; i--)
717: {
718: prev = next++;
719: if ((*compare)(next, prev) < 0)
720: {
721: tmp = *next;
722: do *(prev + 1) = *prev;
723: while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0);
724: *(prev + 1) = tmp;
725: }
726: }
727: }
728: else /* arbitrary size */
729: {
730: #ifdef USE_C_ALLOCA
731: extern void *alloca ();
732: #endif
733: register int i;
734: register char *next, *prev, *tmp = alloca (size), *base = array;
735:
736: for (next = base, i = count - 1; i > 0; i--)
737: { /* count-1 forward iterations */
738: prev = next, next += size; /* increment front pointer */
739: if ((*compare)(next, prev) < 0)
740: { /* found element out of order; move others up then re-insert */
741: memcpy (tmp, next, size); /* save smaller element */
742: do { memcpy (prev + size, prev, size); /* move larger elem. up */
743: prev -= size; /* decrement back pointer */
744: } while (prev >= base ? (*compare)(tmp, prev) < 0 : 0);
745: memcpy (prev + size, tmp, size); /* restore small element */
746: }
747: }
748: #ifdef USE_C_ALLOCA
749: alloca (0);
750: #endif
751: }
752:
753: return;
754: }
755: #endif /* QSORT_WORKAROUND */
756:
757: #endif /* VMS */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.