1*16441Smckusick #ifndef lint 2*16441Smckusick static char sccsid[] = " dofloat.c 4.2 84/05/05 "; 3*16441Smckusick #endif 4*16441Smckusick 5*16441Smckusick /* From Lou Salkind: compat/RCS/dofloat.c,v 1.2 84/01/31 13:33:53 */ 6*16441Smckusick 76797Srrh /* 8*16441Smckusick * Partial PDP-11 floating-point simulator. Always in double mode, 9*16441Smckusick * chop mode. All arithmetic done in double-precision. Storing longs 10*16441Smckusick * into or taking longs from general registers doesn't work. 11*16441Smckusick * Overflow is never detected. 126797Srrh */ 13*16441Smckusick 146797Srrh #include <stdio.h> 156797Srrh #include "defs.h" 16*16441Smckusick 17*16441Smckusick #define TRUE 1 18*16441Smckusick #define FALSE 0 19*16441Smckusick 20*16441Smckusick #define ABSD 0170600 21*16441Smckusick #define ADDD 0172000 22*16441Smckusick #define CFCC 0170000 23*16441Smckusick #define CLRD 0170400 24*16441Smckusick #define CMPD 0173400 25*16441Smckusick #define DIVD 0174400 26*16441Smckusick #define LDCFD 0177400 27*16441Smckusick #define LDCLD 0177000 28*16441Smckusick #define LDD 0172400 29*16441Smckusick #define LDEXP 0176400 30*16441Smckusick #define MODD 0171400 31*16441Smckusick #define MULD 0171000 32*16441Smckusick #define NEGD 0170700 33*16441Smckusick #define SETD 0170011 34*16441Smckusick #define SETI 0170002 35*16441Smckusick #define SETL 0170012 36*16441Smckusick #define STCDL 0175400 37*16441Smckusick #define STCDF 0176000 38*16441Smckusick #define STD 0174000 39*16441Smckusick #define STEXP 0175000 40*16441Smckusick #define SUBD 0173000 41*16441Smckusick #define TSTD 0170500 42*16441Smckusick 43*16441Smckusick static struct { 44*16441Smckusick unsigned fc :1; 45*16441Smckusick unsigned fv :1; 46*16441Smckusick unsigned fz :1; 47*16441Smckusick unsigned fn :1; 48*16441Smckusick unsigned fmm :1; 49*16441Smckusick unsigned ft :1; 50*16441Smckusick unsigned fl :1; 51*16441Smckusick unsigned fd :1; 52*16441Smckusick } fps = FALSE; 53*16441Smckusick 54*16441Smckusick #define FZ fps.fz 55*16441Smckusick #define FN fps.fn 56*16441Smckusick #define FL fps.fl 57*16441Smckusick #define FD fps.fd 58*16441Smckusick 59*16441Smckusick #define LMODE FL 60*16441Smckusick #define IMODE (!LMODE) 61*16441Smckusick 62*16441Smckusick static double fregs[6]; 63*16441Smckusick 64*16441Smckusick dofloat(instr) 65*16441Smckusick unsigned int instr; 66*16441Smckusick { 67*16441Smckusick int mode, reg, ac; 68*16441Smckusick unsigned short * x, * resolve(); 69*16441Smckusick #define DOUBLE (*((double *)x)) 70*16441Smckusick #define FLOAT (*(float *)x) 71*16441Smckusick #define LONG (*(long *)x) 72*16441Smckusick #define SHORT (*(short *)x) 73*16441Smckusick #define GETDOUBLE (x = resolve(mode, reg, 8, TRUE)) 74*16441Smckusick #define GETFLOAT (x = resolve(mode, reg, 4, TRUE)) 75*16441Smckusick #define GETLONG (x = resolve(mode, reg, 4, FALSE)) 76*16441Smckusick #define GETSHORT (x = resolve(mode, reg, 2, FALSE)) 77*16441Smckusick #define FREG fregs[ac] 78*16441Smckusick double temp; 79*16441Smckusick union { 80*16441Smckusick double d; 81*16441Smckusick short s; 82*16441Smckusick } bits; 83*16441Smckusick 84*16441Smckusick switch (instr & 0170000) { 85*16441Smckusick case 0170000: 866797Srrh break; 876797Srrh default: 88*16441Smckusick fprintf(stderr, "Unrecognized instr in dofloat %0o\n", instr); 89*16441Smckusick return (-1); 90*16441Smckusick } 91*16441Smckusick 92*16441Smckusick switch (instr & 07000) { 93*16441Smckusick case 0: 94*16441Smckusick switch (instr & 0700) { 95*16441Smckusick case 0: 96*16441Smckusick switch (instr) { 97*16441Smckusick case CFCC: 98*16441Smckusick psl &= ~017; 99*16441Smckusick if (FN) { 100*16441Smckusick psl |= 010; 101*16441Smckusick } 102*16441Smckusick if (FZ) { 103*16441Smckusick psl |= 04; 104*16441Smckusick } 105*16441Smckusick return (0); 106*16441Smckusick case SETD: 107*16441Smckusick FD = TRUE; 108*16441Smckusick return (0); 109*16441Smckusick case SETI: 110*16441Smckusick FL = FALSE; 111*16441Smckusick return (0); 112*16441Smckusick case SETL: 113*16441Smckusick FL = TRUE; 114*16441Smckusick return (0); 115*16441Smckusick default: 116*16441Smckusick fprintf(stderr, "Unrecognized instr in dofloat %0o\n", instr); 117*16441Smckusick return (-1); 118*16441Smckusick } 1196797Srrh default: 1206797Srrh break; 1216797Srrh } 122*16441Smckusick 123*16441Smckusick mode = (instr & 070) >> 3; 124*16441Smckusick reg = instr & 07; 125*16441Smckusick 126*16441Smckusick switch (instr & 0177700) { 127*16441Smckusick case ABSD: 128*16441Smckusick GETDOUBLE; 129*16441Smckusick if (DOUBLE < 0.0) { 130*16441Smckusick DOUBLE = -DOUBLE; 131*16441Smckusick } 132*16441Smckusick FZ = (DOUBLE == 0.0); 133*16441Smckusick FN = (DOUBLE < 0.0); 134*16441Smckusick return (0); 135*16441Smckusick case CLRD: 136*16441Smckusick GETDOUBLE; 137*16441Smckusick DOUBLE = 0.0; 138*16441Smckusick FZ = TRUE; 139*16441Smckusick FN = FALSE; 140*16441Smckusick return (0); 141*16441Smckusick case NEGD: 142*16441Smckusick GETDOUBLE; 143*16441Smckusick DOUBLE = -DOUBLE; 144*16441Smckusick FZ = (DOUBLE == 0.0); 145*16441Smckusick FN = (DOUBLE < 0.0); 146*16441Smckusick return (0); 147*16441Smckusick case TSTD: 148*16441Smckusick GETDOUBLE; 149*16441Smckusick FZ = (DOUBLE == 0.0); 150*16441Smckusick FN = (DOUBLE < 0.0); 151*16441Smckusick return (0); 152*16441Smckusick default: 153*16441Smckusick fprintf(stderr, "Unrecognized instr in dofloat %0o\n", instr); 154*16441Smckusick return (-1); 1556797Srrh } 156*16441Smckusick default: 1576797Srrh break; 1586797Srrh } 159*16441Smckusick 160*16441Smckusick ac = (instr & 0300) >> 6; 161*16441Smckusick mode = (instr & 070) >> 3; 162*16441Smckusick reg = instr & 07; 163*16441Smckusick 164*16441Smckusick switch (instr & 0177400) { 165*16441Smckusick case ADDD: 166*16441Smckusick GETDOUBLE; 167*16441Smckusick FREG += DOUBLE; 168*16441Smckusick FZ = (FREG == 0.0); 169*16441Smckusick FN = (FREG < 0.0); 170*16441Smckusick return (0); 171*16441Smckusick case CMPD: 172*16441Smckusick GETDOUBLE; 173*16441Smckusick FZ = (DOUBLE == FREG); 174*16441Smckusick FN = (DOUBLE < FREG); 175*16441Smckusick return (0); 176*16441Smckusick case DIVD: 177*16441Smckusick GETDOUBLE; 178*16441Smckusick FREG /= DOUBLE; 179*16441Smckusick FZ = (FREG == 0.0); 180*16441Smckusick FN = (FREG < 0.0); 181*16441Smckusick return (0); 182*16441Smckusick case LDCFD: 183*16441Smckusick GETFLOAT; 184*16441Smckusick FREG = FLOAT; 185*16441Smckusick FZ = (FREG == 0.0); 186*16441Smckusick FN = (FREG < 0.0); 187*16441Smckusick return (0); 188*16441Smckusick case LDCLD: 189*16441Smckusick if (IMODE) { 190*16441Smckusick GETSHORT; 191*16441Smckusick FREG = SHORT; 192*16441Smckusick } else { 193*16441Smckusick GETLONG; 194*16441Smckusick FREG = fliplong(LONG); 1956797Srrh } 196*16441Smckusick FZ = (FREG == 0.0); 197*16441Smckusick FN = (FREG < 0.0); 198*16441Smckusick return (0); 199*16441Smckusick case LDD: 200*16441Smckusick GETDOUBLE; 201*16441Smckusick FREG = DOUBLE; 202*16441Smckusick FZ = (FREG == 0.0); 203*16441Smckusick FN = (FREG < 0.0); 204*16441Smckusick return (0); 205*16441Smckusick case LDEXP: 206*16441Smckusick GETSHORT; 207*16441Smckusick bits.d = FREG; 208*16441Smckusick bits.s &= ~077600; 209*16441Smckusick bits.s |= (SHORT + 0200) << 7; 210*16441Smckusick FREG = bits.d; 211*16441Smckusick FZ = (SHORT == 0); 212*16441Smckusick FN = (FREG < 0.0); 213*16441Smckusick return (0); 214*16441Smckusick case MODD: 215*16441Smckusick GETDOUBLE; 216*16441Smckusick temp = FREG * DOUBLE; 217*16441Smckusick fregs[ac|1] = (long) temp; 218*16441Smckusick FREG = temp - (long) temp; 219*16441Smckusick FZ = (FREG == 0.0); 220*16441Smckusick FN = (FREG < 0.0); 221*16441Smckusick return (0); 222*16441Smckusick case MULD: 223*16441Smckusick GETDOUBLE; 224*16441Smckusick FREG = FREG * DOUBLE; 225*16441Smckusick FZ = (FREG == 0.0); 226*16441Smckusick FN = (FREG < 0.0); 227*16441Smckusick return (0); 228*16441Smckusick case STCDF: 229*16441Smckusick GETFLOAT; 230*16441Smckusick FLOAT = FREG; 231*16441Smckusick FZ = (FREG == 0.0); 232*16441Smckusick FN = (FREG < 0.0); 233*16441Smckusick return (0); 234*16441Smckusick case STCDL: 235*16441Smckusick if (IMODE) { 236*16441Smckusick GETSHORT; 237*16441Smckusick SHORT = FREG; 2386797Srrh psl &= ~017; 239*16441Smckusick if (SHORT == 0) { 240*16441Smckusick psl |= 04; 2416797Srrh } 242*16441Smckusick if (SHORT < 0) { 243*16441Smckusick psl |= 010; 244*16441Smckusick } 245*16441Smckusick } else { 246*16441Smckusick GETLONG; 247*16441Smckusick LONG = fliplong((long) FREG); 248*16441Smckusick psl &= ~017; 249*16441Smckusick if (fliplong(LONG) == 0) { 250*16441Smckusick psl |= 04; 251*16441Smckusick } 252*16441Smckusick if (fliplong(LONG) < 0) { 253*16441Smckusick psl |= 010; 254*16441Smckusick } 2556797Srrh } 256*16441Smckusick FZ = (FREG == 0.0); 257*16441Smckusick FN = (FREG < 0.0); 258*16441Smckusick return (0); 259*16441Smckusick case STD: 260*16441Smckusick GETDOUBLE; 261*16441Smckusick DOUBLE = FREG; 262*16441Smckusick return (0); 263*16441Smckusick case STEXP: 264*16441Smckusick GETSHORT; 265*16441Smckusick bits.d = FREG; 266*16441Smckusick SHORT = ((bits.s & 077600) >> 7) - 0200; 267*16441Smckusick FZ = (SHORT == 0); 268*16441Smckusick FN = (SHORT < 0); 2696797Srrh psl &= ~017; 270*16441Smckusick if (FZ) { 271*16441Smckusick psl |= 04; 272*16441Smckusick } 273*16441Smckusick if (FN) { 274*16441Smckusick psl |= 010; 275*16441Smckusick } 276*16441Smckusick return (0); 277*16441Smckusick case SUBD: 278*16441Smckusick GETDOUBLE; 279*16441Smckusick FREG -= DOUBLE; 280*16441Smckusick FZ = (FREG == 0.0); 281*16441Smckusick FN = (FREG < 0.0); 282*16441Smckusick return (0); 2836797Srrh default: 284*16441Smckusick fprintf(stderr, "Unrecognized instr in dofloat %0o\n", instr); 285*16441Smckusick return (-1); 2866797Srrh } 287*16441Smckusick } 288*16441Smckusick 289*16441Smckusick unsigned short * 290*16441Smckusick resolve(mode, reg, bytes, floating) 291*16441Smckusick { 292*16441Smckusick static unsigned short *x; 293*16441Smckusick static union { 294*16441Smckusick double d; 295*16441Smckusick unsigned short s; 296*16441Smckusick } bits; 297*16441Smckusick 298*16441Smckusick switch (mode) { 299*16441Smckusick case 0: 300*16441Smckusick if (floating) { 301*16441Smckusick if (bytes != 8) { 302*16441Smckusick fprintf(stderr, "Bad length in dofloat\n"); 303*16441Smckusick return ((unsigned short *) -1); 304*16441Smckusick } 305*16441Smckusick x = (unsigned short *) &fregs[reg]; 306*16441Smckusick } else { 307*16441Smckusick if (bytes != 2) { 308*16441Smckusick fprintf(stderr, "Bad length in dofloat\n"); 309*16441Smckusick return ((unsigned short *) -1); 310*16441Smckusick } 311*16441Smckusick x = (unsigned short *) ®s[reg]; 312*16441Smckusick } 3136797Srrh break; 314*16441Smckusick case 1: 315*16441Smckusick x = (unsigned short *) regs[reg]; 3166797Srrh break; 317*16441Smckusick case 2: 318*16441Smckusick if (reg == 7 && floating) { 319*16441Smckusick bits.d = 0.0; 320*16441Smckusick bits.s = *(unsigned short *) regs[7]; 321*16441Smckusick x = (unsigned short *) &bits; 322*16441Smckusick regs[7] += 2; 323*16441Smckusick pc = (unsigned short *) regs[7]; 324*16441Smckusick } else { 325*16441Smckusick x = (unsigned short *) regs[reg]; 326*16441Smckusick regs[reg] += bytes; 327*16441Smckusick if (reg == 7) { 328*16441Smckusick if (bytes != 2) { 329*16441Smckusick return((unsigned short *) -1); 330*16441Smckusick } 331*16441Smckusick pc = (unsigned short *) regs[7]; 332*16441Smckusick } 333*16441Smckusick } 3346797Srrh break; 335*16441Smckusick case 3: 336*16441Smckusick x = (unsigned short *) regs[reg]; 337*16441Smckusick x = (unsigned short *) *x; 338*16441Smckusick regs[reg] += 2; 339*16441Smckusick if (reg == 7) { 340*16441Smckusick pc = (unsigned short *) regs[7]; 341*16441Smckusick } 3426797Srrh break; 343*16441Smckusick case 4: 344*16441Smckusick regs[reg] -= bytes; 345*16441Smckusick if (reg == 7) { 346*16441Smckusick pc = (unsigned short *) regs[7]; 347*16441Smckusick } 348*16441Smckusick x = (unsigned short *) regs[reg]; 3496797Srrh break; 350*16441Smckusick case 5: 351*16441Smckusick regs[reg] -= 2; 352*16441Smckusick if (reg == 7) { 353*16441Smckusick pc = (unsigned short *) regs[7]; 354*16441Smckusick } 355*16441Smckusick x = (unsigned short *) regs[reg]; 356*16441Smckusick x = (unsigned short *) *x; 3576797Srrh break; 358*16441Smckusick case 6: 359*16441Smckusick x = (unsigned short *) (unsigned short) (regs[reg] + *(pc++)); 360*16441Smckusick if (reg == 7) { 361*16441Smckusick ++x; 3626797Srrh } 3636797Srrh break; 364*16441Smckusick case 7: 365*16441Smckusick x = (unsigned short *) (unsigned short) (regs[reg] + *(pc++)); 366*16441Smckusick if (reg == 7) { 367*16441Smckusick ++x; 3686797Srrh } 369*16441Smckusick x = (unsigned short *) *x; 3706797Srrh break; 3716797Srrh } 372*16441Smckusick 373*16441Smckusick return (x); 3746797Srrh } 375*16441Smckusick 376*16441Smckusick long 377*16441Smckusick fliplong(l) 378*16441Smckusick long l; 379*16441Smckusick { 380*16441Smckusick union { 381*16441Smckusick long l; 382*16441Smckusick short s[2]; 383*16441Smckusick } bits[2]; 384*16441Smckusick 385*16441Smckusick bits[0].l = l; 386*16441Smckusick bits[1].s[1] = bits[0].s[0]; 387*16441Smckusick bits[1].s[0] = bits[0].s[1]; 388*16441Smckusick return (bits[1].l); 3896797Srrh } 390