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