|
|
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;
38: {
39: int i;
40: /* Split operands. */
41:
42: low[0] = low[1] = low[2] = 0;
43: for (i = 0; i < 3; i++)
44: {
45: if (low[i])
46: /* it's already been figured out */;
47: else if (GET_CODE (operands[i]) == MEM
48: && (GET_CODE (XEXP (operands[i], 0)) == POST_INC))
49: {
50: rtx addr = XEXP (operands[i], 0);
51: operands[i] = low[i] = gen_rtx (MEM, SImode, addr);
52: if (which_alternative == 0 && i == 0)
53: {
54: addr = XEXP (operands[i], 0);
55: operands[i+1] = low[i+1] = gen_rtx (MEM, SImode, addr);
56: }
57: }
58: else
59: {
60: low[i] = operand_subword (operands[i], 0, 0, DImode);
61: operands[i] = operand_subword (operands[i], 1, 0, DImode);
62: }
63: }
64: }
65:
66: print_operand_address (file, addr)
67: FILE *file;
68: register rtx addr;
69: {
70: register rtx reg1, reg2, breg, ireg;
71: rtx offset;
72:
73: retry:
74: switch (GET_CODE (addr))
75: {
76: case MEM:
77: fprintf (file, "*");
78: addr = XEXP (addr, 0);
79: goto retry;
80:
81: case REG:
82: fprintf (file, "(%s)", reg_names[REGNO (addr)]);
83: break;
84:
85: case PRE_DEC:
86: fprintf (file, "-(%s)", reg_names[REGNO (XEXP (addr, 0))]);
87: break;
88:
89: case POST_INC:
90: fprintf (file, "(%s)+", reg_names[REGNO (XEXP (addr, 0))]);
91: break;
92:
93: case PLUS:
94: /* There can be either two or three things added here. One must be a
95: REG. One can be either a REG or a MULT of a REG and an appropriate
96: constant, and the third can only be a constant or a MEM.
97:
98: We get these two or three things and put the constant or MEM in
99: OFFSET, the MULT or REG in IREG, and the REG in BREG. If we have
100: a register and can't tell yet if it is a base or index register,
101: put it into REG1. */
102:
103: reg1 = 0; ireg = 0; breg = 0; offset = 0;
104:
105: if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
106: || GET_CODE (XEXP (addr, 0)) == MEM)
107: {
108: offset = XEXP (addr, 0);
109: addr = XEXP (addr, 1);
110: }
111: else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
112: || GET_CODE (XEXP (addr, 1)) == MEM)
113: {
114: offset = XEXP (addr, 1);
115: addr = XEXP (addr, 0);
116: }
117: else if (GET_CODE (XEXP (addr, 1)) == MULT)
118: {
119: ireg = XEXP (addr, 1);
120: addr = XEXP (addr, 0);
121: }
122: else if (GET_CODE (XEXP (addr, 0)) == MULT)
123: {
124: ireg = XEXP (addr, 0);
125: addr = XEXP (addr, 1);
126: }
127: else if (GET_CODE (XEXP (addr, 1)) == REG)
128: {
129: reg1 = XEXP (addr, 1);
130: addr = XEXP (addr, 0);
131: }
1.1.1.2 root 132: else if (GET_CODE (XEXP (addr, 0)) == REG)
133: {
134: reg1 = XEXP (addr, 0);
135: addr = XEXP (addr, 1);
136: }
1.1 root 137: else
138: abort ();
139:
140: if (GET_CODE (addr) == REG)
141: {
142: if (reg1)
143: ireg = addr;
144: else
145: reg1 = addr;
146: }
147: else if (GET_CODE (addr) == MULT)
148: ireg = addr;
149: else if (GET_CODE (addr) == PLUS)
150: {
151: if (CONSTANT_ADDRESS_P (XEXP (addr, 0))
152: || GET_CODE (XEXP (addr, 0)) == MEM)
153: {
154: if (offset)
155: {
156: if (GET_CODE (offset) == CONST_INT)
157: offset = plus_constant (XEXP (addr, 0), INTVAL (offset));
158: else if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
159: offset = plus_constant (offset, INTVAL (XEXP (addr, 0)));
160: else
161: abort ();
162: }
163: offset = XEXP (addr, 0);
164: }
165: else if (GET_CODE (XEXP (addr, 0)) == REG)
166: {
167: if (reg1)
168: ireg = reg1, breg = XEXP (addr, 0), reg1 = 0;
169: else
170: reg1 = XEXP (addr, 0);
171: }
172: else if (GET_CODE (XEXP (addr, 0)) == MULT)
173: {
174: if (ireg)
175: abort ();
176: ireg = XEXP (addr, 0);
177: }
178: else
179: abort ();
180:
181: if (CONSTANT_ADDRESS_P (XEXP (addr, 1))
182: || GET_CODE (XEXP (addr, 1)) == MEM)
183: {
184: if (offset)
185: {
186: if (GET_CODE (offset) == CONST_INT)
187: offset = plus_constant (XEXP (addr, 1), INTVAL (offset));
188: else if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
189: offset = plus_constant (offset, INTVAL (XEXP (addr, 1)));
190: else
191: abort ();
192: }
193: offset = XEXP (addr, 1);
194: }
195: else if (GET_CODE (XEXP (addr, 1)) == REG)
196: {
197: if (reg1)
198: ireg = reg1, breg = XEXP (addr, 1), reg1 = 0;
199: else
200: reg1 = XEXP (addr, 1);
201: }
202: else if (GET_CODE (XEXP (addr, 1)) == MULT)
203: {
204: if (ireg)
205: abort ();
206: ireg = XEXP (addr, 1);
207: }
208: else
209: abort ();
210: }
211: else
212: abort ();
213:
214: /* If REG1 is non-zero, figure out if it is a base or index register. */
215: if (reg1)
216: {
217: if (breg != 0 || (offset && GET_CODE (offset) == MEM))
218: {
219: if (ireg)
220: abort ();
221: ireg = reg1;
222: }
223: else
224: breg = reg1;
225: }
226:
227: if (offset != 0)
228: output_address (offset);
229:
230: if (breg != 0)
231: fprintf (file, "(%s)", reg_names[REGNO (breg)]);
232:
233: if (ireg != 0)
234: {
235: if (GET_CODE (ireg) == MULT)
236: ireg = XEXP (ireg, 0);
237: if (GET_CODE (ireg) != REG)
238: abort ();
239: fprintf (file, "[%s]", reg_names[REGNO (ireg)]);
240: }
241: break;
242:
243: default:
244: output_addr_const (file, addr);
245: }
246: }
247:
248: char *
249: rev_cond_name (op)
250: rtx op;
251: {
252: switch (GET_CODE (op))
253: {
254: case EQ:
255: return "neq";
256: case NE:
257: return "eql";
258: case LT:
259: return "geq";
260: case LE:
261: return "gtr";
262: case GT:
263: return "leq";
264: case GE:
265: return "lss";
266: case LTU:
267: return "gequ";
268: case LEU:
269: return "gtru";
270: case GTU:
271: return "lequ";
272: case GEU:
273: return "lssu";
274:
275: default:
276: abort ();
277: }
278: }
1.1.1.3 ! root 279:
! 280: int
! 281: vax_float_literal(c)
! 282: register rtx c;
! 283: {
! 284: register enum machine_mode mode;
! 285: int i;
! 286: union {double d; int i[2];} val;
! 287:
! 288: if (GET_CODE (c) != CONST_DOUBLE)
! 289: return 0;
! 290:
! 291: mode = GET_MODE (c);
! 292:
! 293: if (c == const_tiny_rtx[(int) mode][0]
! 294: || c == const_tiny_rtx[(int) mode][1]
! 295: || c == const_tiny_rtx[(int) mode][2])
! 296: return 1;
! 297:
! 298: #if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
! 299:
! 300: val.i[0] = CONST_DOUBLE_LOW (c);
! 301: val.i[1] = CONST_DOUBLE_HIGH (c);
! 302:
! 303: for (i = 0; i < 7; i ++)
! 304: if (val.d == 1 << i || val.d == 1 / (1 << i))
! 305: return 1;
! 306: #endif
! 307: return 0;
! 308: }
! 309:
! 310:
! 311: /* Return the cost in cycles of a memory address, relative to register
! 312: indirect.
! 313:
! 314: Each of the following adds the indicated number of cycles:
! 315:
! 316: 1 - symbolic address
! 317: 1 - pre-decrement
! 318: 1 - indexing and/or offset(register)
! 319: 2 - indirect */
! 320:
! 321:
! 322: int vax_address_cost(addr)
! 323: register rtx addr;
! 324: {
! 325: int reg = 0, indexed = 0, indir = 0, offset = 0, predec = 0;
! 326: rtx plus_op0 = 0, plus_op1 = 0;
! 327: restart:
! 328: switch (GET_CODE (addr))
! 329: {
! 330: case PRE_DEC:
! 331: predec = 1;
! 332: case REG:
! 333: case SUBREG:
! 334: case POST_INC:
! 335: reg = 1;
! 336: break;
! 337: case MULT:
! 338: indexed = 1; /* 2 on VAX 2 */
! 339: break;
! 340: case CONST_INT:
! 341: /* byte offsets cost nothing (on a VAX 2, they cost 1 cycle) */
! 342: if (offset == 0)
! 343: offset = (unsigned)(INTVAL(addr)+128) > 256;
! 344: break;
! 345: case CONST:
! 346: case SYMBOL_REF:
! 347: offset = 1; /* 2 on VAX 2 */
! 348: break;
! 349: case LABEL_REF: /* this is probably a byte offset from the pc */
! 350: if (offset == 0)
! 351: offset = 1;
! 352: break;
! 353: case PLUS:
! 354: if (plus_op0)
! 355: plus_op1 = XEXP (addr, 0);
! 356: else
! 357: plus_op0 = XEXP (addr, 0);
! 358: addr = XEXP (addr, 1);
! 359: goto restart;
! 360: case MEM:
! 361: indir = 2; /* 3 on VAX 2 */
! 362: addr = XEXP (addr, 0);
! 363: goto restart;
! 364: }
! 365:
! 366: /* Up to 3 things can be added in an address. They are stored in
! 367: plus_op0, plus_op1, and addr. */
! 368:
! 369: if (plus_op0)
! 370: {
! 371: addr = plus_op0;
! 372: plus_op0 = 0;
! 373: goto restart;
! 374: }
! 375: if (plus_op1)
! 376: {
! 377: addr = plus_op1;
! 378: plus_op1 = 0;
! 379: goto restart;
! 380: }
! 381: /* Indexing and register+offset can both be used (except on a VAX 2)
! 382: without increasing execution time over either one alone. */
! 383: if (reg && indexed && offset)
! 384: return reg + indir + offset + predec;
! 385: return reg + indexed + indir + offset + predec;
! 386: }
! 387:
! 388:
! 389: /* Cost of an expression on a VAX. This version has costs tuned for the
! 390: CVAX chip (found in the VAX 3 series) with comments for variations on
! 391: other models. */
! 392:
! 393: int
! 394: vax_rtx_cost (x)
! 395: register rtx x;
! 396: {
! 397: register enum rtx_code code = GET_CODE (x);
! 398: enum machine_mode mode = GET_MODE (x);
! 399: register int c;
! 400: int i = 0; /* may be modified in switch */
! 401: char *fmt = GET_RTX_FORMAT (code); /* may be modified in switch */
! 402:
! 403: switch (code)
! 404: {
! 405: case POST_INC:
! 406: return 2;
! 407: case PRE_DEC:
! 408: return 3;
! 409: case MULT:
! 410: switch (mode)
! 411: {
! 412: case DFmode:
! 413: c = 16; /* 4 on VAX 9000 */
! 414: break;
! 415: case SFmode:
! 416: c = 9; /* 4 on VAX 9000, 12 on VAX 2 */
! 417: break;
! 418: case DImode:
! 419: c = 16; /* 6 on VAX 9000, 28 on VAX 2 */
! 420: break;
! 421: case SImode:
! 422: case HImode:
! 423: case QImode:
! 424: c = 10; /* 3-4 on VAX 9000, 20-28 on VAX 2 */
! 425: break;
! 426: }
! 427: break;
! 428: case UDIV:
! 429: c = 17;
! 430: break;
! 431: case DIV:
! 432: if (mode == DImode)
! 433: c = 30; /* highly variable */
! 434: else if (mode == DFmode)
! 435: /* divide takes 28 cycles if the result is not zero, 13 otherwise */
! 436: c = 24;
! 437: else
! 438: c = 11; /* 25 on VAX 2 */
! 439: break;
! 440: case MOD:
! 441: c = 23;
! 442: break;
! 443: case UMOD:
! 444: c = 29;
! 445: break;
! 446: case FLOAT:
! 447: c = 6 + (mode == DFmode) + (GET_MODE (XEXP (x, 0)) != SImode);
! 448: /* 4 on VAX 9000 */
! 449: break;
! 450: case FIX:
! 451: c = 7; /* 17 on VAX 2 */
! 452: break;
! 453: case LSHIFT:
! 454: case ASHIFT:
! 455: case LSHIFTRT:
! 456: case ASHIFTRT:
! 457: if (mode == DImode)
! 458: c = 12;
! 459: else
! 460: c = 10; /* 6 on VAX 9000 */
! 461: break;
! 462: case ROTATE:
! 463: case ROTATERT:
! 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 */
! 467: break;
! 468: case PLUS:
! 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)
! 473: fmt = "e";
! 474: case MINUS:
! 475: c = (mode == DFmode) ? 13 : 8; /* 6/8 on VAX 9000, 16/15 on VAX 2 */
! 476: case IOR:
! 477: case XOR:
! 478: c = 3;
! 479: break;
! 480: case AND:
! 481: /* AND is special because the first operand is complemented. */
! 482: c = 3;
! 483: if (GET_CODE (XEXP (x, 0)) == CONST_INT)
! 484: {
! 485: if ((unsigned)~INTVAL (XEXP (x, 0)) > 63)
! 486: c = 4;
! 487: fmt = "e";
! 488: i = 1;
! 489: }
! 490: break;
! 491: case NEG:
! 492: if (mode == DFmode)
! 493: return 9;
! 494: else if (mode == SFmode)
! 495: return 6;
! 496: else if (mode == DImode)
! 497: return 4;
! 498: case NOT:
! 499: return 2;
! 500: case ZERO_EXTRACT:
! 501: case SIGN_EXTRACT:
! 502: c = 15;
! 503: break;
! 504: case MEM:
! 505: if (mode == DImode || mode == DFmode)
! 506: c = 5; /* 7 on VAX 2 */
! 507: else
! 508: c = 3; /* 4 on VAX 2 */
! 509: x = XEXP (x, 0);
! 510: if (GET_CODE (x) == REG || GET_CODE (x) == POST_INC)
! 511: return c;
! 512: return c + vax_address_cost (x);
! 513: default:
! 514: c = 3;
! 515: break;
! 516: }
! 517:
! 518:
! 519: /* Now look inside the expression. Operands which are not registers or
! 520: short constants add to the cost.
! 521:
! 522: FMT and I may have been adjusted in the switch above for instructions
! 523: which require special handling */
! 524:
! 525: while (*fmt++ == 'e')
! 526: {
! 527: register rtx op = XEXP (x, i++);
! 528: code = GET_CODE (op);
! 529:
! 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. */
! 533: if (code == NOT)
! 534: op = XEXP (op, 0), code = GET_CODE (op);
! 535:
! 536: switch (code)
! 537: {
! 538: case CONST_INT:
! 539: if ((unsigned)INTVAL (op) > 63 && GET_MODE (x) != QImode)
! 540: c += 1; /* 2 on VAX 2 */
! 541: break;
! 542: case CONST:
! 543: case LABEL_REF:
! 544: case SYMBOL_REF:
! 545: c += 1; /* 2 on VAX 2 */
! 546: break;
! 547: case CONST_DOUBLE:
! 548: if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT)
! 549: {
! 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))
! 553: c++;
! 554: else
! 555: c += (GET_MODE (x) == DFmode) ? 3 : 2;
! 556: }
! 557: else
! 558: {
! 559: if (CONST_DOUBLE_HIGH (op) != 0
! 560: || (unsigned)CONST_DOUBLE_LOW (op) > 63)
! 561: c += 2;
! 562: }
! 563: break;
! 564: case MEM:
! 565: c += 1; /* 2 on VAX 2 */
! 566: if (GET_CODE (XEXP (op, 0)) != REG)
! 567: c += vax_address_cost (XEXP (op, 0));
! 568: break;
! 569: case REG:
! 570: case SUBREG:
! 571: break;
! 572: default:
! 573: c += 1;
! 574: break;
! 575: }
! 576: }
! 577: return c;
! 578: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.