PDP-11 Compatability Mode on VAXen
utzoo!decvax!ucbvax!unix-wizards
utzoo!decvax!ucbvax!unix-wizards
Thu Sep 17 13:42:36 AEST 1981
>From allegra!jdd at Berkeley Thu Sep 17 12:43:20 1981
In reply to my message of 15 Sep 1981 13:32:48-PDT on bugs in the PDP-11
compatability mode package on the VAX, I received a request for the specific
changes. Well, since I'm not on the Arpanet, I can't send to individuals,
only to mailing lists, so, everybody, here are some changes. I apologize
for their length.
To (partially) fix the problem of stack frames being created prematurely
when signals are caught while in compatability mode, one should change files
unixtraps.c and dosig.c . In unixtraps.c, add the line:
int interrupt;
in the external declarations at the top. Add the line:
interrupt = 0
as the first executable statement of routine dotrap(). Add the line:
if (interrupt) dosig(interrupt, pc);
as the last executable statement in routine dotrap().
In dosig.c, add the line:
extern int interrupt;
in the external declarations at the top. Change the first call to
dosig(signum, pc) in routine sigcatch() to the line:
interrupt = signum;
These changes help the problem, but they do not solve it. First, they do
not handle multiple signals caught while in native mode; only one is
remembered. Secondly, there are numerous timing problems which could mess
things up, but this is much hairier to solve, mostly since signals are so
hard to use (although easier under Berkeley Unix).
As for the floating-point package, it's at the end of this note. It is not
a complete package in that it does not simulate all of the hardware
features, but it seems to be close enough for C programs and the run-time
library.
Cheers,
John DeTreville
------------------------------dofloat.c-------------------------------
/* Partial PDP-11 floating-point simulator. Always in double mode,
chop mode. All arithmetic done in double-precision. Storing longs
into or taking longs from general registers doesn't work.
Overflow is never detected. Other things are wrong too. */
#include <stdio.h>
#include "defs.h"
#define TRUE 1
#define FALSE 0
#define ABSD 0170600
#define ADDD 0172000
#define CFCC 0170000
#define CLRD 0170400
#define CMPD 0173400
#define DIVD 0174400
#define LDCFD 0177400
#define LDCLD 0177000
#define LDD 0172400
#define LDEXP 0176400
#define MODD 0171400
#define MULD 0171000
#define NEGD 0170700
#define SETD 0170011
#define SETI 0170002
#define SETL 0170012
#define STCDL 0175400
#define STCDF 0176000
#define STD 0174000
#define STEXP 0175000
#define SUBD 0173000
#define TSTD 0170500
static struct {
unsigned fc :1;
unsigned fv :1;
unsigned fz :1;
unsigned fn :1;
unsigned fmm :1;
unsigned ft :1;
unsigned fl :1;
unsigned fd :1;
} fps = FALSE;
#define FZ fps.fz
#define FN fps.fn
#define FL fps.fl
#define FD fps.fd
#define LMODE FL
#define IMODE (!LMODE)
static double fregs[6];
dofloat(instr)
unsigned int instr;
{
int mode, reg, ac;
unsigned short * x, * resolve();
#define DOUBLE (*((double *)x))
#define FLOAT (*(float *)x)
#define LONG (*(long *)x)
#define SHORT (*(short *)x)
#define GETDOUBLE (x = resolve(mode, reg, 8, TRUE))
#define GETFLOAT (x = resolve(mode, reg, 4, TRUE))
#define GETLONG (x = resolve(mode, reg, 4, FALSE))
#define GETSHORT (x = resolve(mode, reg, 2, FALSE))
#define FREG fregs[ac]
double temp;
union {
double d;
short s;
} bits;
switch (instr & 0170000) {
case 0170000:
break;
default:
fprintf(stderr, "Unrecognized instr in dofloat %0o\n", instr);
return (-1);
}
switch (instr & 07000) {
case 0:
switch (instr & 0700) {
case 0:
switch (instr) {
case CFCC:
psl &= ~017;
if (FN) {
psl |= 010;
}
if (FZ) {
psl |= 04;
}
return (0);
case SETD:
FD = TRUE;
return (0);
case SETI:
FL = FALSE;
return (0);
case SETL:
FL = TRUE;
return (0);
default:
fprintf(stderr, "Unrecognized instr in dofloat %0o\n", instr);
return (-1);
}
default:
break;
}
mode = (instr & 070) >> 3;
reg = instr & 07;
switch (instr & 0177700) {
case ABSD:
GETDOUBLE;
if (DOUBLE < 0.0) {
DOUBLE = -DOUBLE;
}
FZ = (DOUBLE == 0.0);
FN = (DOUBLE < 0.0);
return (0);
case CLRD:
GETDOUBLE;
DOUBLE = 0.0;
FZ = TRUE;
FN = FALSE;
return (0);
case NEGD:
GETDOUBLE;
DOUBLE = -DOUBLE;
FZ = (DOUBLE == 0.0);
FN = (DOUBLE < 0.0);
return (0);
case TSTD:
GETDOUBLE;
FZ = (DOUBLE == 0.0);
FN = (DOUBLE < 0.0);
return (0);
default:
fprintf(stderr, "Unrecognized instr in dofloat %0o\n", instr);
return (-1);
}
default:
break;
}
ac = (instr & 0300) >> 6;
mode = (instr & 070) >> 3;
reg = instr & 07;
switch (instr & 0177400) {
case ADDD:
GETDOUBLE;
FREG += DOUBLE;
FZ = (FREG == 0.0);
FN = (FREG < 0.0);
return (0);
case CMPD:
GETDOUBLE;
FZ = (DOUBLE == FREG);
FN = (DOUBLE < FREG);
return (0);
case DIVD:
GETDOUBLE;
FREG /= DOUBLE;
FZ = (FREG == 0.0);
FN = (FREG < 0.0);
return (0);
case LDCFD:
GETFLOAT;
FREG = FLOAT;
FZ = (FREG == 0.0);
FN = (FREG < 0.0);
return (0);
case LDCLD:
if (IMODE) {
GETSHORT;
FREG = SHORT;
} else {
GETLONG;
FREG = fliplong(LONG);
}
FZ = (FREG == 0 .0);
FN = (FREG < 0.0);
return (0);
case LDD:
GETDOUBLE;
FREG = DOUBLE;
FZ = (FREG == 0.0);
FN = (FREG < 0.0);
return (0);
case LDEXP:
GETSHORT;
bits.d = FREG;
bits.s &= ~077600;
bits.s |= (SHORT + 0200) << 7;
FREG = bits.d;
FZ = (SHORT == 0);
FN = (FREG < 0.0);
return (0);
case MODD:
GETDOUBLE;
temp = FREG * DOUBLE;
fregs[ac|1] = (long) temp;
FREG = temp - (long) temp;
FZ = (FREG == 0.0);
FN = (FREG < 0.0);
return (0);
case MULD:
GETDOUBLE;
FREG = FREG * DOUBLE;
FZ = (FREG == 0.0);
FN = (FREG < 0.0);
return (0);
case STCDF:
GETFLOAT;
FLOAT = FREG;
FZ = (FREG == 0.0);
FN = (FREG < 0.0);
return (0);
case STCDL:
if (IMODE) {
GETSHORT;
SHORT = FREG;
psl &= ~017;
if (SHORT == 0) {
psl |= 04;
}
if (SHORT < 0) {
psl |= 010;
}
} else {
GETLONG;
LONG = fliplong((long) FREG);
psl &= ~017;
if (fliplong(LONG) == 0) {
psl |= 04;
}
if (fliplong(LONG) < 0) {
psl |= 010;
}
}
FZ = (FREG == 0.0);
FN = (FREG < 0.0);
return (0);
case STD:
GETDOUBLE;
DOUBLE = FREG;
return (0);
case STEXP:
GETSHORT;
bits.d = FREG;
SHORT = ((bits.s & 077600) >> 7) - 0200;
FZ = (SHORT == 0);
FN = (SHORT < 0);
psl &= ~017;
if (FZ) {
psl |= 04;
}
if (FN) {
psl |= 010;
}
return (0);
case SUBD:
GETDOUBLE;
FREG -= DOUBLE;
FZ = (FREG == 0.0);
FN = (FREG < 0.0);
return (0);
default:
fprintf(stderr, "Unrecognized instr in dofloat %0o\n", instr);
return (-1);
}
}
unsigned short *
resolve(mode, reg, bytes, floating)
{
static unsigned short *x;
static union {
double d;
unsigned short s;
} bits;
switch (mode) {
case 0:
if (floating) {
if (bytes != 8) {
fprintf(stderr, "Bad length in dofloat\n");
return ((unsigned short *) -1);
}
x = (unsigned short *) &fregs[reg];
} else {
if (bytes != 2) {
fprintf(stderr, "Bad length in dofloat\n");
return ((unsigned short *) -1);
}
x = (unsigned short *) ®s[reg];
}
break;
case 1:
x = (unsigned short *) regs[reg];
break;
case 2:
if (reg == 7 && floating) {
bits.d = 0.0;
bits.s = *(unsigned short *) regs[7];
x = (unsigned short *) &bits;
regs[7] += 2;
pc = (unsigned short *) regs[7];
} else {
x = (unsigned short *) regs[reg];
regs[reg] += bytes;
if (reg == 7) {
if (bytes != 2) {
return((unsigned short *) -1);
}
pc = (unsigned short *) regs[7];
}
}
break;
case 3:
x = (unsigned short *) regs[reg];
x = (unsigned short *) *x;
regs[reg] += 2;
if (reg == 7) {
pc = (unsigned short *) regs[7];
}
break;
case 4:
regs[reg] -= bytes;
if (reg == 7) {
pc = (unsigned short *) regs[7];
}
x = (unsigned short *) regs[reg];
break;
case 5:
regs[reg] -= 2;
if (reg == 7) {
pc = (unsigned short *) regs[7];
}
x = (unsigned short *) regs[reg];
x = (unsigned short *) *x;
break;
case 6:
x = (unsigned short *) (unsigned short) (regs[reg] + *(pc++));
if (reg == 7) {
++x;
}
break;
case 7:
x = (unsigned short *) (unsigned short) (regs[reg] + *(pc++));
if (reg == 7) {
++x;
}
x = (unsigned short *) *x;
break;
}
return (x);
}
long
fliplong(l)
long l;
{
union {
long l;
short s[2];
} bits[2];
bits[0].l = l;
bits[1].s[1] = bits[0].s[0];
bits[1].s[0] = bits[0].s[1];
return (bits[1].l);
}
/*-----------------------------the end------------------------------*/
More information about the Comp.unix.wizards
mailing list