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
dofloat(instr)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 *
resolve(mode,reg,bytes,floating)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
fliplong(l)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