xref: /csrg-svn/old/games.vax/compat/dofloat.c (revision 34084)
116441Smckusick #ifndef	lint
2*34084Sbostic static char sccsid[] = "	dofloat.c	4.3	88/04/24	";
316441Smckusick #endif
416441Smckusick 
516441Smckusick /* From Lou Salkind: compat/RCS/dofloat.c,v 1.2 84/01/31 13:33:53 */
616441Smckusick 
76797Srrh /*
816441Smckusick  * Partial PDP-11 floating-point simulator.  Always in double mode,
916441Smckusick  * chop mode.  All arithmetic done in double-precision. Storing longs
1016441Smckusick  * into or taking longs from general registers doesn't work.
1116441Smckusick  * Overflow is never detected.
126797Srrh  */
1316441Smckusick 
146797Srrh #include <stdio.h>
156797Srrh #include "defs.h"
1616441Smckusick 
1716441Smckusick #define TRUE 1
1816441Smckusick #define FALSE 0
1916441Smckusick 
2016441Smckusick #define ABSD	0170600
2116441Smckusick #define ADDD	0172000
2216441Smckusick #define CFCC	0170000
2316441Smckusick #define CLRD	0170400
2416441Smckusick #define CMPD	0173400
2516441Smckusick #define DIVD	0174400
2616441Smckusick #define LDCFD	0177400
2716441Smckusick #define LDCLD	0177000
2816441Smckusick #define LDD	0172400
2916441Smckusick #define LDEXP	0176400
3016441Smckusick #define MODD	0171400
3116441Smckusick #define MULD	0171000
3216441Smckusick #define NEGD	0170700
3316441Smckusick #define SETD	0170011
3416441Smckusick #define SETI	0170002
3516441Smckusick #define SETL	0170012
3616441Smckusick #define STCDL	0175400
3716441Smckusick #define STCDF	0176000
3816441Smckusick #define STD	0174000
3916441Smckusick #define STEXP	0175000
4016441Smckusick #define SUBD	0173000
4116441Smckusick #define TSTD	0170500
4216441Smckusick 
4316441Smckusick static struct {
4416441Smckusick 	unsigned fc :1;
4516441Smckusick 	unsigned fv :1;
4616441Smckusick 	unsigned fz :1;
4716441Smckusick 	unsigned fn :1;
4816441Smckusick 	unsigned fmm :1;
4916441Smckusick 	unsigned ft :1;
5016441Smckusick 	unsigned fl :1;
5116441Smckusick 	unsigned fd :1;
52*34084Sbostic } fps;
5316441Smckusick 
5416441Smckusick #define FZ fps.fz
5516441Smckusick #define FN fps.fn
5616441Smckusick #define FL fps.fl
5716441Smckusick #define FD fps.fd
5816441Smckusick 
5916441Smckusick #define LMODE FL
6016441Smckusick #define IMODE (!LMODE)
6116441Smckusick 
6216441Smckusick static double fregs[6];
6316441Smckusick 
dofloat(instr)6416441Smckusick dofloat(instr)
6516441Smckusick unsigned int instr;
6616441Smckusick {
6716441Smckusick 	int mode, reg, ac;
6816441Smckusick 	unsigned short * x, * resolve();
69*34084Sbostic 	long fliplong();
7016441Smckusick #define DOUBLE (*((double *)x))
7116441Smckusick #define FLOAT (*(float *)x)
7216441Smckusick #define LONG (*(long *)x)
7316441Smckusick #define SHORT (*(short *)x)
7416441Smckusick #define GETDOUBLE (x = resolve(mode, reg, 8, TRUE))
7516441Smckusick #define GETFLOAT (x = resolve(mode, reg, 4, TRUE))
7616441Smckusick #define GETLONG (x = resolve(mode, reg, 4, FALSE))
7716441Smckusick #define GETSHORT (x = resolve(mode, reg, 2, FALSE))
7816441Smckusick #define FREG fregs[ac]
7916441Smckusick 	double temp;
8016441Smckusick 	union {
8116441Smckusick 		double d;
8216441Smckusick 		short s;
8316441Smckusick 	} bits;
8416441Smckusick 
8516441Smckusick 	switch (instr & 0170000) {
8616441Smckusick 	case 0170000:
876797Srrh 		break;
886797Srrh 	default:
8916441Smckusick 		fprintf(stderr, "Unrecognized instr in dofloat %0o\n", instr);
9016441Smckusick 		return (-1);
9116441Smckusick 	}
9216441Smckusick 
9316441Smckusick 	switch (instr & 07000) {
9416441Smckusick 	case 0:
9516441Smckusick 		switch (instr & 0700) {
9616441Smckusick 		case 0:
9716441Smckusick 			switch (instr) {
9816441Smckusick 			case CFCC:
9916441Smckusick 				psl &= ~017;
10016441Smckusick 				if (FN) {
10116441Smckusick 					psl |= 010;
10216441Smckusick 				}
10316441Smckusick 				if (FZ) {
10416441Smckusick 					psl |= 04;
10516441Smckusick 				}
10616441Smckusick 				return (0);
10716441Smckusick 			case SETD:
10816441Smckusick 				FD = TRUE;
10916441Smckusick 				return (0);
11016441Smckusick 			case SETI:
11116441Smckusick 				FL = FALSE;
11216441Smckusick 				return (0);
11316441Smckusick 			case SETL:
11416441Smckusick 				FL = TRUE;
11516441Smckusick 				return (0);
11616441Smckusick 			default:
11716441Smckusick 				fprintf(stderr, "Unrecognized instr in dofloat %0o\n", instr);
11816441Smckusick 				return (-1);
11916441Smckusick 			}
1206797Srrh 		default:
1216797Srrh 			break;
1226797Srrh 		}
12316441Smckusick 
12416441Smckusick 		mode = (instr & 070) >> 3;
12516441Smckusick 		reg = instr & 07;
12616441Smckusick 
12716441Smckusick 		switch (instr & 0177700) {
12816441Smckusick 		case ABSD:
12916441Smckusick 			GETDOUBLE;
13016441Smckusick 			if (DOUBLE < 0.0) {
13116441Smckusick 				DOUBLE = -DOUBLE;
13216441Smckusick 			}
13316441Smckusick 			FZ = (DOUBLE == 0.0);
13416441Smckusick 			FN = (DOUBLE < 0.0);
13516441Smckusick 			return (0);
13616441Smckusick 		case CLRD:
13716441Smckusick 			GETDOUBLE;
13816441Smckusick 			DOUBLE = 0.0;
13916441Smckusick 			FZ = TRUE;
14016441Smckusick 			FN = FALSE;
14116441Smckusick 			return (0);
14216441Smckusick 		case NEGD:
14316441Smckusick 			GETDOUBLE;
14416441Smckusick 			DOUBLE = -DOUBLE;
14516441Smckusick 			FZ = (DOUBLE == 0.0);
14616441Smckusick 			FN = (DOUBLE < 0.0);
14716441Smckusick 			return (0);
14816441Smckusick 		case TSTD:
14916441Smckusick 			GETDOUBLE;
15016441Smckusick 			FZ = (DOUBLE == 0.0);
15116441Smckusick 			FN = (DOUBLE < 0.0);
15216441Smckusick 			return (0);
15316441Smckusick 		default:
15416441Smckusick 			fprintf(stderr, "Unrecognized instr in dofloat %0o\n", instr);
15516441Smckusick 			return (-1);
1566797Srrh 		}
15716441Smckusick 	default:
1586797Srrh 		break;
1596797Srrh 	}
16016441Smckusick 
16116441Smckusick 	ac = (instr & 0300) >> 6;
16216441Smckusick 	mode = (instr & 070) >> 3;
16316441Smckusick 	reg = instr & 07;
16416441Smckusick 
16516441Smckusick 	switch (instr & 0177400) {
16616441Smckusick 	case ADDD:
16716441Smckusick 		GETDOUBLE;
16816441Smckusick 		FREG += DOUBLE;
16916441Smckusick 		FZ = (FREG == 0.0);
17016441Smckusick 		FN = (FREG < 0.0);
17116441Smckusick 		return (0);
17216441Smckusick 	case CMPD:
17316441Smckusick 		GETDOUBLE;
17416441Smckusick 		FZ = (DOUBLE == FREG);
17516441Smckusick 		FN = (DOUBLE < FREG);
17616441Smckusick 		return (0);
17716441Smckusick 	case DIVD:
17816441Smckusick 		GETDOUBLE;
17916441Smckusick 		FREG /= DOUBLE;
18016441Smckusick 		FZ = (FREG == 0.0);
18116441Smckusick 		FN = (FREG < 0.0);
18216441Smckusick 		return (0);
18316441Smckusick 	case LDCFD:
18416441Smckusick 		GETFLOAT;
18516441Smckusick 		FREG = FLOAT;
18616441Smckusick 		FZ = (FREG == 0.0);
18716441Smckusick 		FN = (FREG < 0.0);
18816441Smckusick 		return (0);
18916441Smckusick 	case LDCLD:
19016441Smckusick 		if (IMODE) {
19116441Smckusick 			GETSHORT;
19216441Smckusick 			FREG = SHORT;
19316441Smckusick 		} else {
19416441Smckusick 			GETLONG;
19516441Smckusick 			FREG = fliplong(LONG);
1966797Srrh 		}
19716441Smckusick 		FZ = (FREG == 0.0);
19816441Smckusick 		FN = (FREG < 0.0);
19916441Smckusick 		return (0);
20016441Smckusick 	case LDD:
20116441Smckusick 		GETDOUBLE;
20216441Smckusick 		FREG = DOUBLE;
20316441Smckusick 		FZ = (FREG == 0.0);
20416441Smckusick 		FN = (FREG < 0.0);
20516441Smckusick 		return (0);
20616441Smckusick 	case LDEXP:
20716441Smckusick 		GETSHORT;
20816441Smckusick 		bits.d = FREG;
20916441Smckusick 		bits.s &= ~077600;
21016441Smckusick 		bits.s |= (SHORT + 0200) << 7;
21116441Smckusick 		FREG = bits.d;
21216441Smckusick 		FZ = (SHORT == 0);
21316441Smckusick 		FN = (FREG < 0.0);
21416441Smckusick 		return (0);
21516441Smckusick 	case MODD:
21616441Smckusick 		GETDOUBLE;
21716441Smckusick 		temp = FREG * DOUBLE;
21816441Smckusick 		fregs[ac|1] = (long) temp;
21916441Smckusick 		FREG = temp - (long) temp;
22016441Smckusick 		FZ = (FREG == 0.0);
22116441Smckusick 		FN = (FREG < 0.0);
22216441Smckusick 		return (0);
22316441Smckusick 	case MULD:
22416441Smckusick 		GETDOUBLE;
22516441Smckusick 		FREG = FREG * DOUBLE;
22616441Smckusick 		FZ = (FREG == 0.0);
22716441Smckusick 		FN = (FREG < 0.0);
22816441Smckusick 		return (0);
22916441Smckusick 	case STCDF:
23016441Smckusick 		GETFLOAT;
23116441Smckusick 		FLOAT = FREG;
23216441Smckusick 		FZ = (FREG == 0.0);
23316441Smckusick 		FN = (FREG < 0.0);
23416441Smckusick 		return (0);
23516441Smckusick 	case STCDL:
23616441Smckusick 		if (IMODE) {
23716441Smckusick 			GETSHORT;
23816441Smckusick 			SHORT = FREG;
2396797Srrh 			psl &= ~017;
24016441Smckusick 			if (SHORT == 0) {
24116441Smckusick 				psl |= 04;
2426797Srrh 			}
24316441Smckusick 			if (SHORT < 0) {
24416441Smckusick 				psl |= 010;
24516441Smckusick 			}
24616441Smckusick 		} else {
24716441Smckusick 			GETLONG;
24816441Smckusick 			LONG = fliplong((long) FREG);
24916441Smckusick 			psl &= ~017;
25016441Smckusick 			if (fliplong(LONG) == 0) {
25116441Smckusick 				psl |= 04;
25216441Smckusick 			}
25316441Smckusick 			if (fliplong(LONG) < 0) {
25416441Smckusick 				psl |= 010;
25516441Smckusick 			}
2566797Srrh 		}
25716441Smckusick 		FZ = (FREG == 0.0);
25816441Smckusick 		FN = (FREG < 0.0);
25916441Smckusick 		return (0);
26016441Smckusick 	case STD:
26116441Smckusick 		GETDOUBLE;
26216441Smckusick 		DOUBLE = FREG;
26316441Smckusick 		return (0);
26416441Smckusick 	case STEXP:
26516441Smckusick 		GETSHORT;
26616441Smckusick 		bits.d = FREG;
26716441Smckusick 		SHORT = ((bits.s & 077600) >> 7) - 0200;
26816441Smckusick 		FZ = (SHORT == 0);
26916441Smckusick 		FN = (SHORT < 0);
2706797Srrh 		psl &= ~017;
27116441Smckusick 		if (FZ) {
27216441Smckusick 			psl |= 04;
27316441Smckusick 		}
27416441Smckusick 		if (FN) {
27516441Smckusick 			psl |= 010;
27616441Smckusick 		}
27716441Smckusick 		return (0);
27816441Smckusick 	case SUBD:
27916441Smckusick 		GETDOUBLE;
28016441Smckusick 		FREG -= DOUBLE;
28116441Smckusick 		FZ = (FREG == 0.0);
28216441Smckusick 		FN = (FREG < 0.0);
28316441Smckusick 		return (0);
2846797Srrh 	default:
28516441Smckusick 		fprintf(stderr, "Unrecognized instr in dofloat %0o\n", instr);
28616441Smckusick 		return (-1);
2876797Srrh 	}
28816441Smckusick }
28916441Smckusick 
29016441Smckusick unsigned short *
resolve(mode,reg,bytes,floating)29116441Smckusick resolve(mode, reg, bytes, floating)
29216441Smckusick {
29316441Smckusick 	static unsigned short *x;
29416441Smckusick 	static union {
29516441Smckusick 		double d;
29616441Smckusick 		unsigned short s;
29716441Smckusick 	} bits;
29816441Smckusick 
29916441Smckusick 	switch (mode) {
30016441Smckusick 	case 0:
30116441Smckusick 		if (floating) {
30216441Smckusick 			if (bytes != 8) {
30316441Smckusick 				fprintf(stderr, "Bad length in dofloat\n");
30416441Smckusick 				return ((unsigned short *) -1);
30516441Smckusick 			}
30616441Smckusick 			x = (unsigned short *) &fregs[reg];
30716441Smckusick 		} else {
30816441Smckusick 			if (bytes != 2) {
30916441Smckusick 				fprintf(stderr, "Bad length in dofloat\n");
31016441Smckusick 				return ((unsigned short *) -1);
31116441Smckusick 			}
31216441Smckusick 			x = (unsigned short *) &regs[reg];
31316441Smckusick 		}
3146797Srrh 		break;
31516441Smckusick 	case 1:
31616441Smckusick 		x = (unsigned short *) regs[reg];
3176797Srrh 		break;
31816441Smckusick 	case 2:
31916441Smckusick 		if (reg == 7 && floating) {
32016441Smckusick 			bits.d = 0.0;
32116441Smckusick 			bits.s = *(unsigned short *) regs[7];
32216441Smckusick 			x = (unsigned short *) &bits;
32316441Smckusick 			regs[7] += 2;
32416441Smckusick 			pc = (unsigned short *) regs[7];
32516441Smckusick 		} else {
32616441Smckusick 			x = (unsigned short *) regs[reg];
32716441Smckusick 			regs[reg] += bytes;
32816441Smckusick 			if (reg == 7) {
32916441Smckusick 				if (bytes != 2) {
33016441Smckusick 					return((unsigned short *) -1);
33116441Smckusick 				}
33216441Smckusick 				pc = (unsigned short *) regs[7];
33316441Smckusick 			}
33416441Smckusick 		}
3356797Srrh 		break;
33616441Smckusick 	case 3:
33716441Smckusick 		x = (unsigned short *) regs[reg];
33816441Smckusick 		x = (unsigned short *) *x;
33916441Smckusick 		regs[reg] += 2;
34016441Smckusick 		if (reg == 7) {
34116441Smckusick 			pc = (unsigned short *) regs[7];
34216441Smckusick 		}
3436797Srrh 		break;
34416441Smckusick 	case 4:
34516441Smckusick 		regs[reg] -= bytes;
34616441Smckusick 		if (reg == 7) {
34716441Smckusick 			pc = (unsigned short *) regs[7];
34816441Smckusick 		}
34916441Smckusick 		x = (unsigned short *) regs[reg];
3506797Srrh 		break;
35116441Smckusick 	case 5:
35216441Smckusick 		regs[reg] -= 2;
35316441Smckusick 		if (reg == 7) {
35416441Smckusick 			pc = (unsigned short *) regs[7];
35516441Smckusick 		}
35616441Smckusick 		x = (unsigned short *) regs[reg];
35716441Smckusick 		x = (unsigned short *) *x;
3586797Srrh 		break;
35916441Smckusick 	case 6:
36016441Smckusick 		x = (unsigned short *) (unsigned short) (regs[reg] + *(pc++));
36116441Smckusick 		if (reg == 7) {
36216441Smckusick 			++x;
3636797Srrh 		}
3646797Srrh 		break;
36516441Smckusick 	case 7:
36616441Smckusick 		x = (unsigned short *) (unsigned short) (regs[reg] + *(pc++));
36716441Smckusick 		if (reg == 7) {
36816441Smckusick 			++x;
3696797Srrh 		}
37016441Smckusick 		x = (unsigned short *) *x;
3716797Srrh 		break;
3726797Srrh 	}
37316441Smckusick 
37416441Smckusick 	return (x);
3756797Srrh }
37616441Smckusick 
37716441Smckusick long
fliplong(l)37816441Smckusick fliplong(l)
37916441Smckusick long l;
38016441Smckusick {
38116441Smckusick 	union {
38216441Smckusick 		long l;
38316441Smckusick 		short s[2];
38416441Smckusick 	} bits[2];
38516441Smckusick 
38616441Smckusick 	bits[0].l = l;
38716441Smckusick 	bits[1].s[1] = bits[0].s[0];
38816441Smckusick 	bits[1].s[0] = bits[0].s[1];
38916441Smckusick 	return (bits[1].l);
3906797Srrh }
391