|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)float2.c 1.1 86/02/03 Copyr 1985 Sun Micro";
3: #endif
4:
5: /*
6: * Copyright (c) 1985 by Sun Microsystems, Inc.
7: */
8:
9: /*
10: * float2.c
11: */
12:
13: #include "cpass2.h"
14: #include "sky.h"
15: #define iscnode(x) (x->tn.op==REG && iscreg(x->tn.rval))
16:
17: static skyused = 0;
18: int skybase = 0;
19:
20:
21: #define FADD 0
22: #define FADDS 1
23: #define FSUB 2
24: #define FSUBS 3
25: #define FMUL 4
26: #define FMULS 5
27: #define FDIV 6
28: #define FDIVS 7
29: #define FMOD 8
30: #define FMODS 9
31: #define FITOD 10
32: #define FITOS 11
33: #define FSTOD 12
34: #define FDTOS 13
35: #define FSTOI 14
36: #define FDTOI 15
37: #define FCMP 16
38: #define FCMPS 17
39: #define FPVT 18
40: #define FPVTS 19
41:
42: extern NODE * double_conv();
43:
44: ezsconv( p )
45: register NODE *p;
46: {
47: /* return 1 if *p is an SCONV that does not require run-time support */
48:
49: if (use68881)
50: return(1);
51: switch (p->in.type){
52: case FLOAT:
53: case DOUBLE:
54: return 0;
55: default:
56: switch (p->in.left->in.type){
57: case FLOAT:
58: /* ???p->in.left = double_conv( p->in.left ); */
59: /* fall through */
60: case DOUBLE:
61: return 0;
62: default: return 1;
63: }
64: }
65: }
66:
67: static void
68: rightreg( l, r, d)
69: NODE *l, *r, *d;
70: {
71: if (usesky) return;
72: if (l->in.op!=REG || (r && r->in.type==FLOAT && r->in.op!=REG))
73: cerror("misplaced floating argument\n");
74: if (l->tn.rval != D0){
75: if (r && r->in.op==REG && r->tn.rval == D0){
76: if (l->tn.rval == D1){
77: print_str(" exg d0,d1\n");
78: l->tn.rval = D0;
79: r->tn.rval = D1;
80: return;
81: } else {
82: r->in.rall = MUSTDO|D1;
83: order( r, INTAREG );
84: }
85: }
86: l->in.rall = MUSTDO|D0;
87: order( l, INTAREG );
88: }
89: if (r && r->in.type==FLOAT && r->tn.rval != D1 ){
90: r->in.rall = MUSTDO|D1;
91: order( r, INTAREG );
92: } else if (r && r->in.type==DOUBLE)
93: if (tshape( r, SNAME|SOREG|SCON|STARNM))
94: expand( r, FOREFF, " lea A.,a0\n" );
95: else {
96: /* must be *dp++ or *--dp. Horrors!! */
97: if ((l=r->in.left)->in.op == ASG MINUS)
98: expand( l->in.left, FOREFF, " subqw #8,A.\n");
99: expand( l->in.left, INTBREG, " movl A.,a0\n");
100: if (l->in.op == INCR)
101: expand( l->in.left, FOREFF, " addqw #8,A.\n");
102: }
103: if (d!=NULL){
104: /* must be d0 */
105: if (d->in.op!=REG || d->tn.rval!=D0)
106: cerror("misplaced floating argument\n");
107: }
108: }
109:
110: struct fopnames {
111: char *opcode;
112: char *fvroutine;
113: } fopnames[] = {
114: "fabs", "abs",
115: "fcos", "cos",
116: "fsin", "sin",
117: "ftan", "tan",
118: "facos", "acos",
119: "fasin", "asin",
120: "fatan", "atan",
121: "fcosh", "cosh",
122: "fsinh", "sinh",
123: "ftanh", "tanh",
124: "fetox", "exp",
125: "ftentox", "pow10",
126: "ftwotox", "pow2",
127: "flogn", "log",
128: "flog10", "log10",
129: "flog2", "log2",
130: "", "sqr",
131: "fsqrt", "sqrt",
132: "fintrz", "aint",
133: "", "anint",
134: "", "nint",
135: };
136:
137: char
138: floatprefix()
139: {
140: extern usesky, usefpa, use68881, useswitch;
141:
142: if (usefpa) return 'W';
143: if (use68881) return 'M';
144: if (useswitch) return 'V';
145: if (usesky) return 'S';
146: return 'F';
147: }
148:
149: /*
150: * load floating point result register A1 with operand q.
151: * opcode is the mnemonic for a 68881 instruction that
152: * accepts a memory, d-reg, or fp-reg source operand.
153: */
154: fpload(q, cookie, opcode)
155: register NODE *q;
156: char *opcode;
157: {
158: if ( q->in.op == REG && q->in.type == DOUBLE
159: && isareg(q->tn.rval) ) {
160: /* register pair */
161: expand(q, cookie,
162: " movl U.,sp@-\n movl A.,sp@-\n");
163: printf(" %s", opcode);
164: expand(q, cookie, "ZF sp@+,A1\n");
165: } else {
166: printf(" %s", opcode);
167: expand(q, cookie, "ZF A.,A1\n");
168: }
169: }
170:
171: floatcode( p, cookie )
172: register NODE *p;
173: {
174: /*
175: * we mean to emit floating-point code. figure out what we want to do,
176: * figure out who we are, and do the right thing.
177: */
178: register o, ty;
179: register NODE *q, *r;
180: NODE *d;
181: NODE *x;
182: int temp, m;
183: int fname;
184:
185: ty = p->in.type;
186: q = p->in.left;
187: r = p->in.right;
188: o = p->in.op;
189:
190: d = &resc[0];
191: x = NIL;
192: switch (o){
193: case ASG PLUS: d = q;
194: case PLUS: fname = FADD;
195: if (usesky && r->in.op == MUL) {
196: fname = FPVT;
197: x = q;
198: q = r->in.left;
199: r = r->in.right;
200: }
201: goto asop;
202: case ASG MINUS: d = q;
203: case MINUS: fname = FSUB;
204: goto asop;
205: case ASG MUL: d = q;
206: case MUL: fname = FMUL;
207: goto asop;
208: case ASG MOD: d = q;
209: case MOD: fname = FMOD;
210: goto asop;
211: case ASG DIV: d = q;
212: case DIV: fname = FDIV;
213: asop:
214: /* d0 op= d1 */
215: /* d0 op= *a0 */
216: /* and, for sky case */
217: /* AWD op= AWD */
218: /* or
219: /* AWD = AWD op AWD */
220: if (p->in.type == FLOAT )
221: fname += 1;
222: rightreg( q, r, d );
223: floatop( fname, r, q, x, d );
224: return;
225:
226: case REG:
227: case NAME:
228: case FCON:
229: case OREG:
230: case UNARY MUL:
231: if (cookie&FORARG) {
232: /* float FORARG -- must convert */
233: #ifdef FLOATMATH
234: if (FLOATMATH>1 && ty == FLOAT){
235: if (o == REG && iscreg(p->tn.rval)) {
236: /* 68881 coprocessor register */
237: expand( p, FORARG," fmoves AR,Z-\n");
238: } else {
239: expand( p, FORARG," movl AR,Z-\n");
240: }
241: return;
242: }
243: #endif FLOATMATH
244: if (o == FCON) {
245: p->in.type = DOUBLE;
246: } else {
247: p = double_conv(p);
248: }
249: order( p, FORARG );
250: /* expand( p, FORARG," movl UR,Z-\n movl AR,Z-\n"); */
251: return;
252: }
253:
254: /* FORCC */
255: m = getlab() ;
256: expand( p, cookie, " cmpl #0x80000000,AL\n");
257: print_str_d_nl( " jeq L", m );
258: q = (o == UNARY MUL? q : p );
259: if ( q->in.op == REG && isbreg(q->tn.rval) && !use68020 ) {
260: /* can't tst an a-register with last year's model */
261: expand( p, cookie, " cmpw #0,AL\n");
262: } else {
263: expand( p, cookie, " tstl AL\n");
264: }
265: if ( ty == DOUBLE ){
266: temp = m; m = getlab();
267: printf( " jne L%d\nL%d:", m, temp);
268: expand( p, cookie, " tstl UL\n");
269: }
270: print_label(m);
271: return;
272: /* end of case EA */
273:
274: case UNARY MINUS:
275: /* negation of a floating-point (or double) quantity */
276: /* expand( p, cookie, " eorl #0x80000000, AL\n" ); */
277: expand( p, cookie, (q->tn.op==REG)? " bchg #31,AL\n"
278: : " bchg #7,AL\n" );
279: return;
280: case LT:
281: case LE:
282: case GT:
283: case GE:
284: case EQ:
285: case NE:
286: fname = FCMP;
287: if (q->in.type==FLOAT)
288: fname += 1;
289: rightreg( q, r, NULL );
290: floatop( fname, r, q, NIL, NIL );
291: return;
292:
293: /* fortran intrinsics -- only unary ops for now */
294: case FABS:
295: case FCOS:
296: case FSIN:
297: case FTAN:
298: case FACOS:
299: case FASIN:
300: case FATAN:
301: case FCOSH:
302: case FSINH:
303: case FTANH:
304: case FEXP:
305: case F10TOX:
306: case F2TOX:
307: case FLOG10:
308: case FLOG2:
309: case FAINT:
310: /*
311: * source in memory, d-regs, or fp-regs
312: * result in fp-reg A1
313: */
314: if (use68881) {
315: /* done in a single instruction by the 68881 */
316: fpload(q, cookie, fopnames[o-FABS].opcode);
317: return;
318: }
319: goto call_intrinsic;
320:
321: case FSQR: /* sqr(x) = x*x */
322: /*
323: * source in memory, d-regs, or fp-regs
324: * result in fp-reg A1
325: */
326: if (use68881) {
327: fpload(q, cookie, "fmove");
328: expand(q, cookie, " fmulx A1,A1\n");
329: return;
330: }
331: goto call_intrinsic;
332:
333: case FANINT: /* float biased round towards zero */
334: /*
335: * source in memory, d-regs, or fp-regs
336: * result in fp-reg A1
337: */
338: if (use68881) {
339: fpload(q, cookie, "fmove");
340: p->in.op = PLUS; /* just so getlr will work */
341: r = talloc();
342: p->in.right = r;
343: r->in.op = FCON;
344: r->fpn.type = q->in.type;
345: r->fpn.dval = 0.5;
346: expand(p, cookie, " ftestx A1\n");
347: expand(p, cookie, " fjlt 1f\n");
348: expand(p, cookie, " faddZF ZK,A1\n");
349: expand(p, cookie, " jra 2f\n");
350: expand(p, cookie, "1: fsubZF ZK,A1\n");
351: expand(q, cookie, "2: fintrzx A1,A1\n");
352: return;
353: }
354: goto call_intrinsic;
355:
356: case FNINT: /* int biased round towards zero */
357: /*
358: * This one is different:
359: * source in fp-reg, result in d-reg A1
360: */
361: if (use68881) {
362: if (!istnode(q) || !iscreg(q->tn.rval)) {
363: order(q, INTCREG);
364: }
365: p->in.op = PLUS; /* just so getlr will work */
366: r = talloc();
367: p->in.right = r;
368: r->in.op = FCON;
369: r->fpn.type = q->in.type;
370: r->fpn.dval = 0.5;
371: expand(p, cookie, " ftestx AL\n");
372: expand(p, cookie, " fjlt 1f\n");
373: expand(p, cookie, " faddZF ZK,AL\n");
374: expand(p, cookie, " jra 2f\n");
375: expand(p, cookie, "1: fsubZF ZK,AL\n");
376: expand(q, cookie, "2: fintrzx AL,AL\n");
377: expand(p, cookie, " fmovel AL,A1\n");
378: return;
379: }
380: goto call_intrinsic;
381:
382: case FLOGN:
383: /*
384: * KLUDGE to work around a bug in the A79J (RevC) mask set.
385: * In the first production masks of the 68881, flogn does
386: * not work correctly for (0.5 <= x <= 1.0). The following
387: * work-around is required as long as some of the defective
388: * chips are in the field:
389: */
390: if (use68881) {
391: fpload(q, cookie, "fmove");
392: expand(q, cookie, " fcmps #0r0.5,A1\n");
393: expand(q, cookie, " fjule 1f\n");
394: expand(q, cookie, " fsubl #1,A1\n");
395: expand(q, cookie, " flognp1x A1,A1\n");
396: expand(q, cookie, " jra 2f\n");
397: expand(q, cookie, "1: flognx A1,A1\n");
398: expand(q, cookie, "2:");
399: return;
400: }
401: goto call_intrinsic;
402:
403: case FSQRT:
404: /*
405: * KLUDGE to work around a bug in the A79J (RevC) mask set.
406: * In the first production masks of the 68881, fsqrt fpx,fpy
407: * does not work reliably when fpx and fpy are different
408: * registers.
409: */
410: if (use68881) {
411: if (q->in.op == REG && iscreg(q->tn.rval)
412: && q->tn.rval != resc[0].tn.rval) {
413: fpload(q, cookie, "fmove");
414: expand(q, cookie, " fsqrtx A1,A1\n");
415: } else {
416: fpload(q, cookie, "fsqrt");
417: }
418: return;
419: }
420: goto call_intrinsic;
421:
422: call_intrinsic:
423: rightreg(q, NULL, NULL);
424: printf(" jsr %c%s%c\n",
425: floatprefix(),
426: fopnames[o-FABS].fvroutine,
427: (q->in.type == FLOAT ? 's' : 'd'));
428: return;
429:
430: default:
431: huh:
432: print_str("HEY! cookie = ");
433: prcook( cookie);
434: putchar('\n');
435: fwalk( p, eprint, 0);
436: cerror("floatcode got a tree it didn't expect");
437: }
438:
439: }
440:
441:
442:
443: floatconv( p, c, cookie )
444: register NODE *p;
445: char c;
446: {
447: int ty = p->in.type;
448: NODE *q = p->in.left;
449: register t2 = q->in.type;
450: int fname;
451:
452: switch( ty ){
453: case FLOAT:
454: switch (t2){
455: case FLOAT: return;
456: case DOUBLE: fname = FDTOS; break;
457: default: fname = FITOS; makeint( q, cookie ); break;
458: }
459: break;
460: case DOUBLE:
461: switch (t2){
462: case DOUBLE: return;
463: case FLOAT: fname = FSTOD; break;
464: default: fname = FITOD; makeint( q, cookie ); break;
465: }
466: break;
467: default:
468: switch(t2){
469: case DOUBLE: fname = FDTOI; break;
470: case FLOAT: fname = FSTOI; break;
471: default: return;
472: }
473: }
474: rightreg( q, NULL, NULL );
475: floatop( fname, NIL, q, NIL, &resc[0] );
476:
477: }
478:
479: makeint( p, cookie )
480: NODE *p;
481: {
482: switch( p->tn.type ){
483: case UCHAR:
484: expand( p, cookie, " andl #0xff,AL\n" );
485: return;
486: case USHORT:
487: expand( p, cookie, " andl #0xffff,AL\n" );
488: return;
489: case CHAR:
490: expand( p, cookie, " extw AL\n" );
491: /* fall through */
492: case SHORT:
493: expand( p, cookie, " extl AL\n" );
494: return;
495: default:
496: ;
497: }
498: }
499:
500: /*
501: * Note: the names below are INCOMPATIBLE with pre-3.0 libraries
502: */
503: struct finfo {
504: char * fname;
505: short skycode;
506: char nlsource; /* source from left */
507: char nrsource; /* source from right */
508: char nxsource; /* 3rd source, from wherever */
509: char ndest; /* size of sink */
510: char delay; /* need busy-wait loop before collecting results? */
511: } finfo [] = {
512: { "addd", S_DADD3, 2, 2, 0, 2, 1}, /* fadd */
513: { "adds", S_SADD3, 1, 1, 0, 1, 0}, /* fadds */
514: { "subd", S_DSUB3, 2, 2, 0, 2, 1}, /* fsub */
515: { "subs", S_SSUB3, 1, 1, 0, 1, 0}, /* fsubs */
516: { "muld", S_DMUL3, 2, 2, 0, 2, 1}, /* fmul */
517: { "muls", S_SMUL3, 1, 1, 0, 1, 0}, /* fmuls */
518: { "divd", S_DDIV3, 2, 2, 0, 2, 1}, /* fdiv */
519: { "divs", S_SDIV3, 1, 1, 0, 1, 1}, /* fdivs */
520: { "modd", 0 }, /* fmod */
521: { "mods", 0 }, /* fmods */
522: { "fltd", S_ITOD, 1, 0, 0, 2, 0}, /* fitod */
523: { "flts", S_ITOS, 1, 0, 0, 1, 0}, /* fitos */
524: { "stod", S_STOD,1, 0, 0, 2, 0}, /* fstod */
525: { "dtos", S_DTOS,2, 0, 0, 1, 0}, /* fdtos */
526: { "ints", S_STOI, 1, 0, 0, 1, 0}, /* fstoi */
527: { "intd", S_DTOI, 2, 0, 0, 1, 0}, /* fdtoi */
528: { "cmpd", S_DCMP3, 2, 2, 0,-1, 0}, /* fcmp */
529: { "cmps", S_SCMP3, 1, 1, 0,-1, 0}, /* fcmps */
530: { "", S_DPVT3, 2, 2, 2, 2, 1}, /* fpvt */
531: { "", S_SPVT3, 1, 1, 1, 1, 1}, /* fpvts */
532: };
533:
534: static void
535: move_to_sky( p, n, skybreg )
536: register NODE *p;
537: int n;
538: char *skybreg;
539: {
540: /* special hackery for *--dp */
541: if ( n==2 && p->in.op==UNARY MUL && p->in.left->in.op==ASG MINUS ){
542: /* do --, rewrite as oreg */
543: NODE *q; NODE *l;
544: l = p->in.left; /* ASG MINUS node */
545: q = l->in.left;
546: expand( q, INBREG|INTBREG, " subqw #8,A.\n" );
547: *p = *q;
548: p->in.op = OREG;
549: l->in.op = FREE;
550: l->in.right->in.op = FREE;
551: q->in.op = FREE;
552: }
553: expand( p, FOREFF, " movl A.,");
554: printf( "%s@\n", skybreg );
555: if (n >1) {
556: expand( p, FOREFF, " movl U.,");
557: printf( "%s@\n", skybreg );
558: }
559: }
560:
561: /* #define READY 1:tstw SKYBASE@(-OPERAND+STATUS) ; bges 1b
562: /* STATUS = 2
563: /* OPERAND = 4
564: */
565:
566: floatop( f, r, l, x, d ) register f; NODE *r, *l, *x, *d;
567: {
568: register j;
569: register char *skybreg;
570: if (usesky && (j=finfo[f].skycode)){
571: if (skybase) {
572: /* reg reserved by optimizer; use it */
573: if (!isbreg(skybase)) {
574: /* not an a-register, must move it */
575: printf( " movl %s,a1\n" );
576: skybreg = "a1";
577: } else {
578: /* reg ok as is */
579: skybreg = rnames[skybase];
580: }
581: } else {
582: /* must load __skybase into a1 */
583: printf( " movl __skybase,a1\n" );
584: skybreg = "a1";
585: }
586: printf( " movw #%#X,%s@(-4)\n", j, skybreg);
587: if (j=finfo[f].nlsource)
588: move_to_sky( l, j, skybreg );
589: if (j=finfo[f].nrsource)
590: move_to_sky( r, j, skybreg );
591: if (j=finfo[f].nxsource)
592: move_to_sky( x, j, skybreg );
593: if (finfo[f].delay){
594: printf( "1: tstw %s@(-2)\n", skybreg );
595: printf( " bges 1b\n" );
596: }
597: j = finfo[f].ndest;
598: if (j < 0){
599: printf( " movw %s@,cc\n", skybreg );
600: #ifndef IEEECCODES
601: printf( " andb #0xfd,cc\n");
602: #endif IEEECCODES
603: } else {
604: printf( " movl %s@,", skybreg );
605: expand( d, FOREFF, "A.\n" );
606: if (j >1) {
607: printf( " movl %s@,", skybreg );
608: expand( d, FOREFF, "U.\n" );
609: }
610: }
611: skyused++;
612: } else {
613: printf( " jsr %c%s\n", floatprefix(), finfo[f].fname);
614: if (d && (d->tn.op!=REG || d->tn.rval!=D0) && (j=finfo[f].ndest)>0){
615: /* must rewrite destination as advertised */
616: expand( d, FOREFF, " movl d0,A.\n" );
617: if (j >1)
618: expand( d, FOREFF, " movl d1,U.\n" );
619: }
620: }
621: }
622:
623:
624: floatnote()
625: {
626: /* printf( " .globl ieeeused\n" ); *//* troublemaker */
627: if (skyused)
628: printf(" .globl fsky_used\n" );
629: else if (use68881)
630: printf(" .globl f68881_used\n" );
631: else if (usefpa)
632: printf(" .globl ffpa_used\n" );
633: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.