|
|
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:
1.1.1.2 root 33: /* This is like nonimmediate_operand with a restriction on the type of MEM. */
1.1 root 34:
35: void
36: split_quadword_operands (operands, low, n)
37: rtx *operands, *low;
1.1.1.4 ! root 38: int n;
1.1 root 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: }
1.1.1.2 root 133: else if (GET_CODE (XEXP (addr, 0)) == REG)
134: {
135: reg1 = XEXP (addr, 0);
136: addr = XEXP (addr, 1);
137: }
1.1 root 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: }
1.1.1.3 root 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: }
1.1.1.4 ! root 580:
! 581: #ifdef VMS
! 582: /* Additional support code for VMS. */
! 583:
! 584: #ifdef QSORT_WORKAROUND
! 585: /*
! 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.
! 592:
! 593: In this work-around an insertion sort is used for simplicity.
! 594: The qsort code from glibc should probably be used instead.
! 595: */
! 596: void
! 597: not_qsort (array, count, size, compare)
! 598: void *array;
! 599: unsigned count, size;
! 600: int (*compare)();
! 601: {
! 602:
! 603: if (size == sizeof (short))
! 604: {
! 605: register int i;
! 606: register short *next, *prev;
! 607: short tmp, *base = array;
! 608:
! 609: for (next = base, i = count - 1; i > 0; i--)
! 610: {
! 611: prev = next++;
! 612: if ((*compare)(next, prev) < 0)
! 613: {
! 614: tmp = *next;
! 615: do *(prev + 1) = *prev;
! 616: while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0);
! 617: *(prev + 1) = tmp;
! 618: }
! 619: }
! 620: }
! 621: else if (size == sizeof (long))
! 622: {
! 623: register int i;
! 624: register long *next, *prev;
! 625: long tmp, *base = array;
! 626:
! 627: for (next = base, i = count - 1; i > 0; i--)
! 628: {
! 629: prev = next++;
! 630: if ((*compare)(next, prev) < 0)
! 631: {
! 632: tmp = *next;
! 633: do *(prev + 1) = *prev;
! 634: while (--prev >= base ? (*compare)(&tmp, prev) < 0 : 0);
! 635: *(prev + 1) = tmp;
! 636: }
! 637: }
! 638: }
! 639: else /* arbitrary size */
! 640: {
! 641: #ifdef USE_C_ALLOCA
! 642: extern void *alloca ();
! 643: #endif
! 644: register int i;
! 645: register char *next, *prev, *tmp = alloca (size), *base = array;
! 646:
! 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 */
! 657: }
! 658: }
! 659: #ifdef USE_C_ALLOCA
! 660: alloca (0);
! 661: #endif
! 662: }
! 663:
! 664: return;
! 665: }
! 666: #endif /* QSORT_WORKAROUND */
! 667:
! 668: #endif /* VMS */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.