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 *) ®s[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