xref: /original-bsd/old/games.vax/compat/dofloat.c (revision 71c9af4b)
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 *) &regs[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