|
|
1.1 root 1: /* Subroutines for insn-output.c for Convex.
2: Copyright (C) 1989 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 1, 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: /*
21: * set_cmp (left_rtx, right_rtx, [bhwlsd])
22: * gen_cmp (label_rtx, cmpop, [tf])
23: *
24: * set_cmp saves the operands of a "cmp" insn,
25: * along with the type character to be used in the compare instruction.
26: *
27: * gen_cmp finds out what comparison is to be performed and
28: * outputs the necessary instructions, eg,
29: * "eq.w a1,a2 ! jbra.t L5"
30: * for (cmpsi a1 a2) (beq L5)
31: */
32:
33: static rtx xop0, xop1;
34: static char typech, regch;
35:
36: char *
37: set_cmp (op0, op1, typechr)
38: rtx op0, op1;
39: char typechr;
40: {
41: xop0 = op0;
42: xop1 = op1;
43: typech = typechr;
44: if (GET_CODE (op0) == REG)
45: regch = REGNO_OK_FOR_BASE_P (REGNO (op0)) ? 'a' : 's';
46: else if (GET_CODE (op1) == REG)
47: regch = REGNO_OK_FOR_BASE_P (REGNO (op1)) ? 'a' : 's';
48: else abort ();
49: return "";
50: }
51:
52: char *
53: gen_cmp (label, cmpop, tf)
54: rtx label;
55: char *cmpop;
56: char tf;
57: {
58: char buf[80];
59: char revop[4];
60: rtx ops[3];
61:
62: ops[2] = label;
63:
64: /* constant must be first; swap operands if necessary
65: if lt, le, ltu, leu are swapped, change to le, lt, leu, ltu
66: and reverse the sense of the jump */
67:
68: if (CONSTANT_P (xop1) || GET_CODE (xop1) == CONST_DOUBLE)
69: {
70: ops[0] = xop1;
71: ops[1] = xop0;
72: if (cmpop[0] == 'l')
73: {
74: bcopy (cmpop, revop, 4);
75: revop[1] ^= 'e' ^ 't';
76: tf ^= 't' ^ 'f';
77: cmpop = revop;
78: }
79: }
80: else
81: {
82: ops[0] = xop0;
83: ops[1] = xop1;
84: }
85:
86: sprintf (buf, "%s.%c %%0,%%1\n\tjbr%c.%c %%l2", cmpop, typech, regch, tf);
87: output_asm_insn (buf, ops);
88: return "";
89: }
90:
91: /*
92: * pick target machine if not specified, the same as the host
93: */
94:
95: extern int target_flags;
96:
97: override_options ()
98: {
99: #ifdef convex
100: #include <sys/sysinfo.h>
101: if (! (TARGET_C1 || TARGET_C2))
102: {
103: struct system_information sysinfo;
104: getsysinfo (sizeof sysinfo, &sysinfo);
105: if (sysinfo.cpu_type >= SI_CPUTYPE_C2MP)
106: target_flags |= 2;
107: else
108: target_flags |= 1;
109: }
110: #endif
111: }
112:
113: /*
114: * Routines to look at CONST_DOUBLEs without sinful knowledge of
115: * what the inside of u.d looks like
116: *
117: * const_double_high_int -- high word of machine double or long long
118: * const_double_low_int -- low word
119: * const_double_float_int -- the word of a machine float
120: */
121:
122: static double frexp ();
123: static void float_extract ();
124:
125: int
126: const_double_high_int (x)
127: rtx x;
128: {
129: if (GET_MODE (x) == DImode)
130: return CONST_DOUBLE_HIGH (x);
131: else
132: {
133: int sign, expd, expf;
134: unsigned fracdh, fracdl, fracf;
135: float_extract (x, &sign, &expd, &fracdh, &fracdl, &expf, &fracf);
136:
137: if (fracdh == 0)
138: return 0;
139: if (expd < -01777 || expd > 01777)
140: return 1 << 31;
141: return sign << 31 | (expd + 02000) << 20 | fracdh - (1 << 20);
142: }
143: }
144:
145: int
146: const_double_low_int (x)
147: rtx x;
148: {
149: if (GET_MODE (x) == DImode)
150: return CONST_DOUBLE_LOW (x);
151: else
152: {
153: int sign, expd, expf;
154: unsigned fracdh, fracdl, fracf;
155: float_extract (x, &sign, &expd, &fracdh, &fracdl, &expf, &fracf);
156: return fracdl;
157: }
158: }
159:
160: int
161: const_double_float_int (x)
162: rtx x;
163: {
164: int sign, expd, expf;
165: unsigned fracdh, fracdl, fracf;
166: float_extract (x, &sign, &expd, &fracdh, &fracdl, &expf, &fracf);
167:
168: if (fracf == 0)
169: return 0;
170: if (expf < -0177 || expf > 0177)
171: return 1 << 31;
172: return sign << 31 | (expf + 0200) << 20 | fracf - (1 << 23);
173: }
174:
175: #define T21 ((double) (1 << 21))
176: #define T24 ((double) (1 << 24))
177: #define T53 ((double) (1 << 27) * (double) (1 << 26))
178:
179: static void
180: float_extract (x, sign, expd, fracdh, fracdl, expf, fracf)
181: rtx x;
182: int *sign, *expd, *expf;
183: unsigned *fracdh, *fracdl, *fracf;
184: {
185: int exp, round;
186: double d, r;
187: union real_extract u;
188:
189: bcopy (&CONST_DOUBLE_LOW (x), &u, sizeof u);
190:
191: /* Get sign and exponent. */
192:
193: if (*sign = u.d < 0)
194: u.d = -u.d;
195: d = frexp (u.d, &exp);
196:
197: /* Get 21 fraction bits for high word and 32 for low word. */
198:
199: for (round = 0; ; round = 1)
200: {
201: r = frexp (round ? d + 1.0 / T53 : d, expd);
202: *expd += exp;
203: *fracdh = r * T21;
204: *fracdl = (r - *fracdh / T21) * T53;
205: if (round || ((r - *fracdh / T21) - *fracdl / T53) < 0.5 * T53)
206: break;
207: }
208:
209: /* Get 24 bits for float fraction. */
210:
211: for (round = 0; ; round = 1)
212: {
213: r = frexp (round ? d + 1.0 / T24 : d, expf);
214: *expf += exp;
215: *fracf = r * T24;
216: if (round || (r - *fracf / T24) < 0.5 * T24)
217: break;
218: }
219: }
220:
221: static double
222: frexp (d, exp)
223: double d;
224: int *exp;
225: {
226: int e = 0;
227:
228: if (d > 0)
229: {
230: while (d < 0.5) d *= 2.0, e--;
231: while (d >= 1.0) d /= 2.0, e++;
232: }
233:
234: *exp = e;
235: return d;
236: }
237:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.