xref: /csrg-svn/old/games.vax/compat/dofloat.c (revision 16441)
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 *) &regs[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