1 #ifndef lint 2 static char sccsid[] = " dofloat.c 4.3 88/04/24 "; 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; 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 long fliplong(); 70 #define DOUBLE (*((double *)x)) 71 #define FLOAT (*(float *)x) 72 #define LONG (*(long *)x) 73 #define SHORT (*(short *)x) 74 #define GETDOUBLE (x = resolve(mode, reg, 8, TRUE)) 75 #define GETFLOAT (x = resolve(mode, reg, 4, TRUE)) 76 #define GETLONG (x = resolve(mode, reg, 4, FALSE)) 77 #define GETSHORT (x = resolve(mode, reg, 2, FALSE)) 78 #define FREG fregs[ac] 79 double temp; 80 union { 81 double d; 82 short s; 83 } bits; 84 85 switch (instr & 0170000) { 86 case 0170000: 87 break; 88 default: 89 fprintf(stderr, "Unrecognized instr in dofloat %0o\n", instr); 90 return (-1); 91 } 92 93 switch (instr & 07000) { 94 case 0: 95 switch (instr & 0700) { 96 case 0: 97 switch (instr) { 98 case CFCC: 99 psl &= ~017; 100 if (FN) { 101 psl |= 010; 102 } 103 if (FZ) { 104 psl |= 04; 105 } 106 return (0); 107 case SETD: 108 FD = TRUE; 109 return (0); 110 case SETI: 111 FL = FALSE; 112 return (0); 113 case SETL: 114 FL = TRUE; 115 return (0); 116 default: 117 fprintf(stderr, "Unrecognized instr in dofloat %0o\n", instr); 118 return (-1); 119 } 120 default: 121 break; 122 } 123 124 mode = (instr & 070) >> 3; 125 reg = instr & 07; 126 127 switch (instr & 0177700) { 128 case ABSD: 129 GETDOUBLE; 130 if (DOUBLE < 0.0) { 131 DOUBLE = -DOUBLE; 132 } 133 FZ = (DOUBLE == 0.0); 134 FN = (DOUBLE < 0.0); 135 return (0); 136 case CLRD: 137 GETDOUBLE; 138 DOUBLE = 0.0; 139 FZ = TRUE; 140 FN = FALSE; 141 return (0); 142 case NEGD: 143 GETDOUBLE; 144 DOUBLE = -DOUBLE; 145 FZ = (DOUBLE == 0.0); 146 FN = (DOUBLE < 0.0); 147 return (0); 148 case TSTD: 149 GETDOUBLE; 150 FZ = (DOUBLE == 0.0); 151 FN = (DOUBLE < 0.0); 152 return (0); 153 default: 154 fprintf(stderr, "Unrecognized instr in dofloat %0o\n", instr); 155 return (-1); 156 } 157 default: 158 break; 159 } 160 161 ac = (instr & 0300) >> 6; 162 mode = (instr & 070) >> 3; 163 reg = instr & 07; 164 165 switch (instr & 0177400) { 166 case ADDD: 167 GETDOUBLE; 168 FREG += DOUBLE; 169 FZ = (FREG == 0.0); 170 FN = (FREG < 0.0); 171 return (0); 172 case CMPD: 173 GETDOUBLE; 174 FZ = (DOUBLE == FREG); 175 FN = (DOUBLE < FREG); 176 return (0); 177 case DIVD: 178 GETDOUBLE; 179 FREG /= DOUBLE; 180 FZ = (FREG == 0.0); 181 FN = (FREG < 0.0); 182 return (0); 183 case LDCFD: 184 GETFLOAT; 185 FREG = FLOAT; 186 FZ = (FREG == 0.0); 187 FN = (FREG < 0.0); 188 return (0); 189 case LDCLD: 190 if (IMODE) { 191 GETSHORT; 192 FREG = SHORT; 193 } else { 194 GETLONG; 195 FREG = fliplong(LONG); 196 } 197 FZ = (FREG == 0.0); 198 FN = (FREG < 0.0); 199 return (0); 200 case LDD: 201 GETDOUBLE; 202 FREG = DOUBLE; 203 FZ = (FREG == 0.0); 204 FN = (FREG < 0.0); 205 return (0); 206 case LDEXP: 207 GETSHORT; 208 bits.d = FREG; 209 bits.s &= ~077600; 210 bits.s |= (SHORT + 0200) << 7; 211 FREG = bits.d; 212 FZ = (SHORT == 0); 213 FN = (FREG < 0.0); 214 return (0); 215 case MODD: 216 GETDOUBLE; 217 temp = FREG * DOUBLE; 218 fregs[ac|1] = (long) temp; 219 FREG = temp - (long) temp; 220 FZ = (FREG == 0.0); 221 FN = (FREG < 0.0); 222 return (0); 223 case MULD: 224 GETDOUBLE; 225 FREG = FREG * DOUBLE; 226 FZ = (FREG == 0.0); 227 FN = (FREG < 0.0); 228 return (0); 229 case STCDF: 230 GETFLOAT; 231 FLOAT = FREG; 232 FZ = (FREG == 0.0); 233 FN = (FREG < 0.0); 234 return (0); 235 case STCDL: 236 if (IMODE) { 237 GETSHORT; 238 SHORT = FREG; 239 psl &= ~017; 240 if (SHORT == 0) { 241 psl |= 04; 242 } 243 if (SHORT < 0) { 244 psl |= 010; 245 } 246 } else { 247 GETLONG; 248 LONG = fliplong((long) FREG); 249 psl &= ~017; 250 if (fliplong(LONG) == 0) { 251 psl |= 04; 252 } 253 if (fliplong(LONG) < 0) { 254 psl |= 010; 255 } 256 } 257 FZ = (FREG == 0.0); 258 FN = (FREG < 0.0); 259 return (0); 260 case STD: 261 GETDOUBLE; 262 DOUBLE = FREG; 263 return (0); 264 case STEXP: 265 GETSHORT; 266 bits.d = FREG; 267 SHORT = ((bits.s & 077600) >> 7) - 0200; 268 FZ = (SHORT == 0); 269 FN = (SHORT < 0); 270 psl &= ~017; 271 if (FZ) { 272 psl |= 04; 273 } 274 if (FN) { 275 psl |= 010; 276 } 277 return (0); 278 case SUBD: 279 GETDOUBLE; 280 FREG -= DOUBLE; 281 FZ = (FREG == 0.0); 282 FN = (FREG < 0.0); 283 return (0); 284 default: 285 fprintf(stderr, "Unrecognized instr in dofloat %0o\n", instr); 286 return (-1); 287 } 288 } 289 290 unsigned short * 291 resolve(mode, reg, bytes, floating) 292 { 293 static unsigned short *x; 294 static union { 295 double d; 296 unsigned short s; 297 } bits; 298 299 switch (mode) { 300 case 0: 301 if (floating) { 302 if (bytes != 8) { 303 fprintf(stderr, "Bad length in dofloat\n"); 304 return ((unsigned short *) -1); 305 } 306 x = (unsigned short *) &fregs[reg]; 307 } else { 308 if (bytes != 2) { 309 fprintf(stderr, "Bad length in dofloat\n"); 310 return ((unsigned short *) -1); 311 } 312 x = (unsigned short *) ®s[reg]; 313 } 314 break; 315 case 1: 316 x = (unsigned short *) regs[reg]; 317 break; 318 case 2: 319 if (reg == 7 && floating) { 320 bits.d = 0.0; 321 bits.s = *(unsigned short *) regs[7]; 322 x = (unsigned short *) &bits; 323 regs[7] += 2; 324 pc = (unsigned short *) regs[7]; 325 } else { 326 x = (unsigned short *) regs[reg]; 327 regs[reg] += bytes; 328 if (reg == 7) { 329 if (bytes != 2) { 330 return((unsigned short *) -1); 331 } 332 pc = (unsigned short *) regs[7]; 333 } 334 } 335 break; 336 case 3: 337 x = (unsigned short *) regs[reg]; 338 x = (unsigned short *) *x; 339 regs[reg] += 2; 340 if (reg == 7) { 341 pc = (unsigned short *) regs[7]; 342 } 343 break; 344 case 4: 345 regs[reg] -= bytes; 346 if (reg == 7) { 347 pc = (unsigned short *) regs[7]; 348 } 349 x = (unsigned short *) regs[reg]; 350 break; 351 case 5: 352 regs[reg] -= 2; 353 if (reg == 7) { 354 pc = (unsigned short *) regs[7]; 355 } 356 x = (unsigned short *) regs[reg]; 357 x = (unsigned short *) *x; 358 break; 359 case 6: 360 x = (unsigned short *) (unsigned short) (regs[reg] + *(pc++)); 361 if (reg == 7) { 362 ++x; 363 } 364 break; 365 case 7: 366 x = (unsigned short *) (unsigned short) (regs[reg] + *(pc++)); 367 if (reg == 7) { 368 ++x; 369 } 370 x = (unsigned short *) *x; 371 break; 372 } 373 374 return (x); 375 } 376 377 long 378 fliplong(l) 379 long l; 380 { 381 union { 382 long l; 383 short s[2]; 384 } bits[2]; 385 386 bits[0].l = l; 387 bits[1].s[1] = bits[0].s[0]; 388 bits[1].s[0] = bits[0].s[1]; 389 return (bits[1].l); 390 } 391