|
|
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.