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