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