|
|
1.1 ! root 1: # ! 2: static char sccsid[] = " dofloat.c 4.1 82/05/12 "; ! 3: /* ! 4: * Simulate pdp11 floating point for compatability mode programs. ! 5: * Quick and dirty with no big effort at speed since it takes so ! 6: * much overhead to get here in the first place. ! 7: * I make no claims on the completeness of this simulation. ! 8: * Art Wetzel 3/16/80 ! 9: */ ! 10: #ifndef NOFPSIM ! 11: #ifdef DEBUG ! 12: #include <stdio.h> ! 13: #endif ! 14: #include "defs.h" ! 15: /* output codes */ ! 16: #define NONE 0 ! 17: #define SHORT 01 ! 18: #define LONG 02 ! 19: #define FLOAT 04 ! 20: #define DOUBLE 010 ! 21: #define OUTPUT 020 ! 22: /* parts of fps */ ! 23: #define FD 0200 ! 24: #define FL 0100 ! 25: #define FN 010 ! 26: #define FZ 04 ! 27: #define FV 02 ! 28: #define FC 01 ! 29: /* fis instructions */ ! 30: #define FADD 075000 ! 31: #define FSUB 075010 ! 32: #define FMUL 075020 ! 33: #define FDIV 075030 ! 34: /* fpu instructions */ ! 35: #define ABSD 0170600 ! 36: #define ABSF 0170600 ! 37: #define ADDD 0172000 ! 38: #define ADDF 0172000 ! 39: #define CFCC 0170000 ! 40: #define CLRD 0170400 ! 41: #define CLRF 0170400 ! 42: #define CMPD 0173400 ! 43: #define CMPF 0173400 ! 44: #define DIVD 0174400 ! 45: #define DIVF 0174400 ! 46: #define LDCFD 0177400 ! 47: #define LDCFF 0177400 ! 48: #define LDCLD 0177000 ! 49: #define LDCLF 0177000 ! 50: #define LDCIF 0177000 ! 51: #define LDCID 0177000 ! 52: #define LDEXP 0176400 ! 53: #define LDD 0172400 ! 54: #define LDF 0172400 ! 55: #define LDFPS 0170100 ! 56: #define MODD 0171400 ! 57: #define MODF 0171400 ! 58: #define MULD 0171000 ! 59: #define MULF 0171000 ! 60: #define NEGD 0170700 ! 61: #define NEGF 0170700 ! 62: #define SETF 0170001 ! 63: #define SETD 0170011 ! 64: #define SETI 0170002 ! 65: #define SETL 0170012 ! 66: #define STCDF 0176000 ! 67: #define STCFD 0176000 ! 68: #define STCDL 0175400 ! 69: #define STCDI 0175400 ! 70: #define STCFL 0175400 ! 71: #define STCFI 0175400 ! 72: #define STEXP 0175000 ! 73: #define STD 0174000 ! 74: #define STF 0174000 ! 75: #define STFPS 0170200 ! 76: #define STST 0170300 ! 77: #define SUBD 0173000 ! 78: #define SUBF 0173000 ! 79: #define TSTD 0170500 ! 80: #define TSTF 0170500 ! 81: union alltypes { ! 82: double d; ! 83: float f; ! 84: long l; ! 85: short s; ! 86: unsigned short p[4]; ! 87: }; ! 88: /* static storage for floating registers */ ! 89: static union alltypes fregs[6]; ! 90: static union alltypes srcdst; ! 91: int fps = FD|FL; ! 92: int dbl = 0; ! 93: int lng = 0; ! 94: #endif ! 95: dofloat(instr) unsigned int instr; { ! 96: #ifdef NOFPSIM ! 97: return(-1); ! 98: #else ! 99: register unsigned short *wptr; ! 100: register unsigned int opcode, ac, mode, fac, adjust, output, ccset; ! 101: unsigned short *locate(); ! 102: /* indicate what condition codes will be changed by op - assume none */ ! 103: ccset = 0; ! 104: /* type of memory output - assume none */ ! 105: output = NONE; ! 106: /* default adjust to type */ ! 107: if(dbl) ! 108: adjust = DOUBLE; ! 109: else ! 110: adjust = FLOAT; ! 111: /* chop up instruction to get relevent parts */ ! 112: opcode = instr & 0177700; ! 113: fac = (instr>>6) & 03; ! 114: mode = (instr>>3) & 07; ! 115: ac = instr & 07; ! 116: /* if the instruction uses a src/dst construct ptr and fetch */ ! 117: switch(opcode) { ! 118: case FADD: ! 119: case CFCC: ! 120: break; ! 121: default: ! 122: wptr = locate(mode, ac); ! 123: /* special case for mode 0 */ ! 124: if(mode == 0) switch(opcode & 0177400) { ! 125: /* special instructions to use cpu regs */ ! 126: case LDEXP: ! 127: case STEXP: ! 128: wptr = ®s[ac]; ! 129: break; ! 130: case STCDL: ! 131: wptr = ®s[ac]; ! 132: default: ! 133: break; ! 134: } ! 135: if(dbl) ! 136: srcdst.d = *(double *)wptr; ! 137: else ! 138: srcdst.f = *(float *)wptr; ! 139: /* immediate fetches are 16 bits */ ! 140: if(ac == 7 && (mode == 2)) { ! 141: srcdst.p[1] = 0; ! 142: srcdst.p[2] = 0; ! 143: srcdst.p[3] = 0; ! 144: } ! 145: break; ! 146: } ! 147: #ifdef DEBUG ! 148: fprintf(stderr,"pc %o sp %o instr %o srcdst %o mode %o reg %o fac %o\n", pc-1,regs[6],instr,srcdst.s,mode,ac,fac); ! 149: #endif ! 150: switch(opcode) { ! 151: case FADD: ! 152: /* catches all fis instructions */ ! 153: /* last 3 bits are stack pointer register */ ! 154: ac = instr & 07; ! 155: /* get pointer to stack words */ ! 156: wptr = (unsigned short *)regs[ac]; ! 157: /* getch floating value from stack */ ! 158: srcdst.f = *(float *)wptr; ! 159: /* shorten stack */ ! 160: wptr += 2; ! 161: /* do appropriate operation */ ! 162: switch(instr & 0177770) { ! 163: case FADD: ! 164: srcdst.f += *(float *)wptr; ! 165: break; ! 166: case FSUB: ! 167: srcdst.f = *(float *)wptr - srcdst.f; ! 168: break; ! 169: case FMUL: ! 170: srcdst.f *= *(float *)wptr; ! 171: break; ! 172: case FDIV: ! 173: srcdst.f = *(float *)wptr / srcdst.f; ! 174: break; ! 175: default: ! 176: return(-1); ! 177: } ! 178: /* copy out result */ ! 179: *(float *)wptr = srcdst.f; ! 180: /* set up condition codes */ ! 181: psl &= ~017; ! 182: if(srcdst.f == 0.) psl |= FZ; ! 183: if(srcdst.f < 0.) psl |= FN; ! 184: /* adjust register to reflect stack change */ ! 185: regs[ac] = (unsigned short)(int)wptr; ! 186: return(0); ! 187: case CFCC: ! 188: switch(instr) { ! 189: case SETF: ! 190: dbl = 0; ! 191: break; ! 192: case SETD: ! 193: dbl = 1; ! 194: break; ! 195: case SETI: ! 196: lng = 0; ! 197: break; ! 198: case SETL: ! 199: lng = 1; ! 200: break; ! 201: case CFCC: ! 202: psl &= ~017; ! 203: psl |= (fps & 017); ! 204: #ifdef DEBUG ! 205: fprintf(stderr,"CFCC %o\n",psl); ! 206: #endif ! 207: break; ! 208: default: ! 209: return(-1); ! 210: } ! 211: return(0); ! 212: case ABSD: ! 213: if(srcdst.d < 0.0 ) srcdst.d = -srcdst.d; ! 214: ccset = FZ; ! 215: if(dbl) ! 216: output = DOUBLE; ! 217: else ! 218: output = FLOAT; ! 219: break; ! 220: case CLRD: ! 221: srcdst.d =0.0; ! 222: ccset = FZ; ! 223: if(dbl) ! 224: output = DOUBLE; ! 225: else ! 226: output = FLOAT; ! 227: break; ! 228: case LDFPS: ! 229: adjust = SHORT; ! 230: fps = srcdst.s; ! 231: if(fps & FD) ! 232: dbl = 1; ! 233: else ! 234: dbl = 0; ! 235: if(fps & FL ) ! 236: lng = 1; ! 237: else ! 238: lng = 0; ! 239: break; ! 240: case NEGD: ! 241: srcdst.d = -srcdst.d; ! 242: ccset = FZ|FN; ! 243: if(dbl) ! 244: output = DOUBLE; ! 245: else ! 246: output = FLOAT; ! 247: break; ! 248: case STFPS: ! 249: srcdst.s = fps; ! 250: adjust = output = SHORT; ! 251: break; ! 252: case STST: ! 253: return(0); ! 254: break; ! 255: case TSTD: ! 256: ccset = FZ|FN; ! 257: break; ! 258: default: ! 259: opcode = instr & 0177400; ! 260: switch(opcode) { ! 261: case STD: ! 262: srcdst.d = fregs[fac].d; ! 263: #ifdef DEBUG ! 264: fprintf(stderr,"STD %o\n",srcdst.s); ! 265: #endif ! 266: if(dbl) ! 267: output = DOUBLE; ! 268: else ! 269: output = FLOAT; ! 270: break; ! 271: case LDD: ! 272: #ifdef DEBUG ! 273: fprintf(stderr,"LDD %o\n",srcdst.s); ! 274: #endif ! 275: fregs[fac].d = srcdst.d; ! 276: ccset = FZ|FN; ! 277: break; ! 278: case ADDD: ! 279: fregs[fac].d += srcdst.d; ! 280: ccset = FZ|FN; ! 281: break; ! 282: case SUBD: ! 283: fregs[fac].d -= srcdst.d; ! 284: ccset = FZ|FN; ! 285: break; ! 286: case MULD: ! 287: fregs[fac].d *= srcdst.d; ! 288: ccset = FZ|FN; ! 289: break; ! 290: case DIVD: ! 291: #ifdef DEBUG ! 292: fprintf(stderr,"DIVD %f by %f gives ",fregs[fac].d,srcdst.d); ! 293: #endif ! 294: fregs[fac].d /= srcdst.d; ! 295: #ifdef DEBUG ! 296: fprintf(stderr,"-> %f\n",fregs[fac].d); ! 297: #endif ! 298: ccset = FZ|FN; ! 299: break; ! 300: case STCDF: ! 301: adjust = output = FLOAT; ! 302: ccset = FZ|FN; ! 303: break; ! 304: case LDCFD: ! 305: adjust = FLOAT; ! 306: ccset = FZ|FN; ! 307: break; ! 308: case LDCLD: ! 309: if(lng) { ! 310: adjust = LONG; ! 311: srcdst.d = srcdst.l; ! 312: } else { ! 313: adjust = SHORT; ! 314: srcdst.d = srcdst.s; ! 315: } ! 316: ccset = FZ|FN; ! 317: break; ! 318: case CMPD: ! 319: srcdst.d -= fregs[fac].d; ! 320: ccset = FZ|FN; ! 321: break; ! 322: case LDEXP: ! 323: srcdst.d = 0.0; ! 324: srcdst.s = *wptr; ! 325: srcdst.s <<= 7; ! 326: srcdst.s += 0200; ! 327: adjust = SHORT; ! 328: ccset = FZ|FN; ! 329: #ifdef DEBUG ! 330: fprintf(stderr,"LDEXP %o gives %o\n",*wptr,srcdst.s); ! 331: #endif ! 332: break; ! 333: case MODD: ! 334: srcdst.d *= fregs[fac].d; ! 335: fregs[fac].d = (double)(long)srcdst.d; ! 336: if(~fac & 1) fregs[fac + 1].d = fregs[fac].d; ! 337: srcdst.d -= fregs[fac].d; ! 338: ccset = FN|FZ; ! 339: fregs[fac].d = srcdst.d; ! 340: #ifdef DEBUG ! 341: fprintf(stderr,"MODD %o %o\n",fregs[fac].s,fregs[fac+1].s); ! 342: #endif ! 343: break; ! 344: case STCDL: ! 345: if(lng) ! 346: adjust = output = LONG; ! 347: else ! 348: adjust = output = SHORT; ! 349: if(mode == 0) output = SHORT; ! 350: srcdst.l = fregs[fac].d; ! 351: #ifdef DEBUG ! 352: fprintf(stderr,"STCDL %o\n",srcdst.l); ! 353: #endif ! 354: ccset = FZ|FN; ! 355: break; ! 356: case STEXP: ! 357: #ifdef DEBUG ! 358: fprintf(stderr,"STEXP of %o gives ",srcdst.s); ! 359: #endif ! 360: srcdst.s &= 077600; ! 361: srcdst.s >>= 7; ! 362: srcdst.s -= 0200; ! 363: adjust = output = SHORT; ! 364: ccset = FZ|FN; ! 365: #ifdef DEBUG ! 366: fprintf(stderr,"%o\n",srcdst.s); ! 367: #endif ! 368: break; ! 369: default: ! 370: return(-1); ! 371: } ! 372: } ! 373: if(ccset & FZ) { ! 374: fps &= ~FZ; ! 375: if(srcdst.d == 0.0) fps |= FZ; ! 376: if(!dbl && srcdst.f == 0.0) fps |= FZ; ! 377: } ! 378: if(ccset & FN) { ! 379: fps &= ~FN; ! 380: if(srcdst.f < 0.0) fps |= FN; ! 381: } ! 382: switch(instr & 0177400) { ! 383: case STCDL: ! 384: case STEXP: ! 385: psl &= ~017; ! 386: psl |= (fps & 017); ! 387: break; ! 388: default: ! 389: break; ! 390: } ! 391: switch(output) { ! 392: case NONE: ! 393: break; ! 394: case SHORT: ! 395: *((short *)wptr) = srcdst.s; ! 396: srcdst.d = 0.0; ! 397: break; ! 398: case LONG: ! 399: if(mode == 4) wptr--; ! 400: *((long *)wptr) = longrev(srcdst.l); ! 401: break; ! 402: case FLOAT: ! 403: if(mode == 4) wptr--; ! 404: *((float *)wptr) = srcdst.f; ! 405: break; ! 406: case DOUBLE: ! 407: if(mode == 4) wptr -= 3; ! 408: *((double *)wptr) = srcdst.d; ! 409: break; ! 410: } ! 411: switch(mode) { ! 412: case 0: ! 413: case 1: ! 414: break; ! 415: case 2: ! 416: switch(adjust) { ! 417: case SHORT: ! 418: regs[ac] += 2; ! 419: break; ! 420: case LONG: ! 421: case FLOAT: ! 422: regs[ac] += 4; ! 423: break; ! 424: case DOUBLE: ! 425: regs[ac] += 8; ! 426: break; ! 427: case NONE: ! 428: break; ! 429: } ! 430: if(ac == 7) pc++; ! 431: break; ! 432: case 3: ! 433: regs[ac] += 2; ! 434: if(ac == 7) pc++; ! 435: break; ! 436: case 4: ! 437: switch(adjust) { ! 438: case SHORT: ! 439: regs[ac] -= 2; ! 440: break; ! 441: case LONG: ! 442: case FLOAT: ! 443: regs[ac] -= 4; ! 444: break; ! 445: case DOUBLE: ! 446: regs[ac] -= 8; ! 447: break; ! 448: case NONE: ! 449: break; ! 450: } ! 451: break; ! 452: case 5: ! 453: regs[ac] -= 2; ! 454: break; ! 455: case 6: ! 456: case 7: ! 457: pc++; ! 458: break; ! 459: } ! 460: return(0); ! 461: #endif ! 462: } ! 463: #ifndef NOFPSIM ! 464: unsigned short *locate(mode, ac) { ! 465: register unsigned short *wptr; ! 466: switch(mode) { ! 467: case 0: ! 468: /* mode 0 normally implies fregs */ ! 469: wptr = (unsigned short *)&fregs[ac]; ! 470: break; ! 471: case 1: ! 472: break; ! 473: case 2: ! 474: wptr = (unsigned short *)(int)regs[ac]; ! 475: break; ! 476: case 3: ! 477: wptr = (unsigned short *)regs[ac]; ! 478: wptr = (unsigned short *)*wptr; ! 479: break; ! 480: case 4: ! 481: wptr = (unsigned short *)regs[ac]; ! 482: wptr--; ! 483: break; ! 484: case 5: ! 485: wptr = (unsigned short *)regs[ac]; ! 486: wptr--; ! 487: wptr = (unsigned short *)*wptr; ! 488: break; ! 489: case 6: ! 490: wptr = (unsigned short *)((regs[ac] + *pc) & 0177776); ! 491: if(ac == 7) wptr++; ! 492: break; ! 493: case 7: ! 494: wptr = (unsigned short *)((regs[ac] + *pc) & 0177776); ! 495: if(ac == 7) wptr++; ! 496: wptr = (unsigned short *)*wptr; ! 497: break; ! 498: } ! 499: return(wptr); ! 500: } ! 501: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.