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