1
0
mirror of https://github.com/prirun/p50em.git synced 2026-03-23 16:42:17 +00:00

1 Commits

Author SHA1 Message Date
Dennis Boone
2458dd7c2e Add T_REGS trace type. 2020-04-17 22:17:01 -04:00
20 changed files with 2646 additions and 4277 deletions

View File

@@ -1,15 +0,0 @@
# .editorconfig, Boone, 02/11/21
# Editor behavior settings
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[makefile]
indent_style = tab

View File

@@ -1,26 +0,0 @@
name: freebsdbuild
on: workflow_dispatch
jobs:
build:
runs-on: macos-latest
steps:
- uses: "actions/checkout@v2"
- uses: "vmactions/freebsd-vm@v0.1.3"
with:
usesh: true
prepare: pkg install -y curl git
run: |
make
- uses: "marvinpinto/action-automatic-releases@latest"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
automatic_release_tag: "latest"
prerelease: false
title: "Bleeding Edge Binary - FreeBSD"
files: |
LICENSE
README.md
em.1
em

View File

@@ -1,22 +0,0 @@
name: linuxbuild
on: workflow_dispatch
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: "actions/checkout@v2"
- name: make
run: make
- uses: "marvinpinto/action-automatic-releases@latest"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
automatic_release_tag: "latest"
prerelease: false
title: "Bleeding Edge Binary - Ubuntu"
files: |
LICENSE
README.md
em.1
em

View File

@@ -1,22 +0,0 @@
name: macbuild
on: workflow_dispatch
jobs:
build:
runs-on: macos-latest
steps:
- uses: "actions/checkout@v2"
- name: make
run: make
- uses: "marvinpinto/action-automatic-releases@latest"
with:
repo_token: "${{ secrets.GITHUB_TOKEN }}"
automatic_release_tag: "latest"
prerelease: false
title: "Bleeding Edge Binary - MacOS"
files: |
LICENSE
README.md
em.1
em

1
.gitignore vendored
View File

@@ -3,7 +3,6 @@
*.log *.log
*.swp *.swp
tags tags
cmraw
cscope.* cscope.*
em em
emlink emlink

View File

@@ -22,9 +22,6 @@ the host processor having a large set of general-purpose registers.
Coming soon, we swear! There is a unix man page included in this Coming soon, we swear! There is a unix man page included in this
repository. repository.
Github discussions are now enabled for this repository, and can be
used to ask for help.
## Public Systems ## Public Systems
There are a set of emulators available for public use. These may be There are a set of emulators available for public use. These may be
@@ -55,7 +52,7 @@ business unit ceased to exist. A reformatted copy is available
A growing collection of Prime and related documentation is available A growing collection of Prime and related documentation is available
at [sysovl.info](https://sysovl.info/reference_prime.html). at [sysovl.info](https://sysovl.info/reference_prime.html).
A howto on installing PRIMOS in the emulator is A howto on installing PRIMOS in the emulator is
[here](https://sysovl.info/reference_prime_drb_installoview.html). [here](https://sysovl.info/reference_prime_drb_installing_primos.html).
Discussion of adapting these instructions to Discussion of adapting these instructions to
22.1.4 has been occurring on the [cctalk mailing 22.1.4 has been occurring on the [cctalk mailing
list](http://classiccmp.org/pipermail/cctalk/2020-March/052126.html). list](http://classiccmp.org/pipermail/cctalk/2020-March/052126.html).
@@ -78,19 +75,6 @@ are available from Bitsavers:
* [Rev 22.1.4 repacked](https://yagi.h-net.org/m2214repack.tar.gz) [use this instead, resaved with Rev. 22 magsav] * [Rev 22.1.4 repacked](https://yagi.h-net.org/m2214repack.tar.gz) [use this instead, resaved with Rev. 22 magsav]
* [Rev 19.?](http://bitsavers.org/bits/Prime/pps/03_log.tape_I=boot_II=iptpal.tap.gz) [a backup from an installed system] * [Rev 19.?](http://bitsavers.org/bits/Prime/pps/03_log.tape_I=boot_II=iptpal.tap.gz) [a backup from an installed system]
## Pre-compiled binaries
We'd prefer that you build your own from the source tree, but if that's
not possible, a set of pre-compiled binaries is available. Included are:
* Linux i386
* Linux amd64
* Linux armhf (RasPi / BeagleBone)
* FreeBSD amd64
* Solaris amd64
[download](https://sysovl.info/pages/blobs/emulator/embinaries.20200504.tar.gz)
## Sample System Images ## Sample System Images
A set of sample system images derived from the public emulators can A set of sample system images derived from the public emulators can

1369
devamlc.h

File diff suppressed because it is too large Load Diff

220
devpnc.h
View File

@@ -77,7 +77,7 @@
1: "Type" word. 1: "Type" word.
Bit 1 set = odd number of bytes (if set, last word is only 1 byte) Bit 1 set = odd number of bytes (if set, last word is only 1 byte)
Bit 7 set = normal data messages (otherwise, a timer message) Bit 7 set = normal data messages (otherwise, a timer message)
Bit 16 set = broadcast timer message Bit 16 set = broadcast timer message
NOTE: at the hardware level, there are many other fields associated NOTE: at the hardware level, there are many other fields associated
with a ring packet on the wire, for example, a CRC, ack byte, etc. with a ring packet on the wire, for example, a CRC, ack byte, etc.
@@ -121,15 +121,15 @@
7: data 2 7: data 2
PNC diagnostic register: PNC diagnostic register:
NORXTX EQU '100000 DISABLE TX AND RX NORXTX EQU '100000 DISABLE TX AND RX
TXDATER EQU '040000 FORCE RX CRC ERROR TXDATER EQU '040000 FORCE RX CRC ERROR
TXACKER EQU '020000 FORCE TX ACK ERROR TXACKER EQU '020000 FORCE TX ACK ERROR
RXACKER EQU '010000 FORCE RX ACK BYTE ERROR RXACKER EQU '010000 FORCE RX ACK BYTE ERROR
CABLE EQU '000001 LOOPBACK OVER CABLE CABLE EQU '000001 LOOPBACK OVER CABLE
ANALOG EQU '000002 LOOPBACK THRU ANALOG DEVICES ANALOG EQU '000002 LOOPBACK THRU ANALOG DEVICES
SINGSTEP EQU '000004 LOOPBACK THRU SHIFT REG SINGSTEP EQU '000004 LOOPBACK THRU SHIFT REG
RETRY EQU '000000 ALLOW HARDWR RETRY RETRY EQU '000000 ALLOW HARDWR RETRY
NORETRY EQU '000010 NO HARDWR RETRY NORETRY EQU '000010 NO HARDWR RETRY
Primos PNC usage: Primos PNC usage:
@@ -406,11 +406,7 @@ void pncinitfd(int fd) {
perror("unable to get ts flags for PNC"); perror("unable to get ts flags for PNC");
fatal(NULL); fatal(NULL);
} }
#ifdef __sun__
fdflags |= O_NONBLOCK;
#else
fdflags |= O_NONBLOCK+O_ASYNC; fdflags |= O_NONBLOCK+O_ASYNC;
#endif
if (fcntl(fd, F_SETFL, fdflags) == -1) { if (fcntl(fd, F_SETFL, fdflags) == -1) {
perror("unable to set fdflags for PNC"); perror("unable to set fdflags for PNC");
fatal(NULL); fatal(NULL);
@@ -439,7 +435,7 @@ void pncaccept(time_t timenow) {
fd = accept(pncfd, (struct sockaddr *)&addr, &addrlen); fd = accept(pncfd, (struct sockaddr *)&addr, &addrlen);
if (fd == -1) { if (fd == -1) {
if (errno != EWOULDBLOCK && errno != EINTR && errno != EAGAIN) if (errno != EWOULDBLOCK && errno != EINTR && errno != EAGAIN)
perror("accept error for PNC"); perror("accept error for PNC");
return; return;
} }
if (!(pncstat & PNCNSCONNECTED)) { if (!(pncstat & PNCNSCONNECTED)) {
@@ -731,7 +727,7 @@ unsigned short pncxmit() {
if (xmit.toid == 255) { if (xmit.toid == 255) {
for (nodeid=1; nodeid<=MAXNODEID; nodeid++) for (nodeid=1; nodeid<=MAXNODEID; nodeid++)
if (ni[nodeid].cstate != PNCCSNONE) if (ni[nodeid].cstate != PNCCSNONE)
xmitstat |= pncxmit1(nodeid); xmitstat |= pncxmit1(nodeid);
} else { } else {
xmitstat |= pncxmit1(xmit.toid); xmitstat |= pncxmit1(xmit.toid);
} }
@@ -764,7 +760,7 @@ void pncrecv() {
if (fd != -1) if (fd != -1)
FD_SET(fd, &fds); FD_SET(fd, &fds);
if (fd > n) if (fd > n)
n = fd; n = fd;
} }
n = select(n+1, &fds, NULL, NULL, &timeout); n = select(n+1, &fds, NULL, NULL, &timeout);
if (n == -1) { if (n == -1) {
@@ -784,7 +780,7 @@ void pncrecv() {
fd = ni[nodeid].fd; fd = ni[nodeid].fd;
if (fd >= 0 && FD_ISSET(fd, &fds)) if (fd >= 0 && FD_ISSET(fd, &fds))
if (pncrecv1(nodeid)) if (pncrecv1(nodeid))
break; break;
} while (nodeid != prevnode); /* went round once? */ } while (nodeid != prevnode); /* went round once? */
prevnode = nodeid; prevnode = nodeid;
} }
@@ -853,7 +849,7 @@ int pncread (int nodeid, int nbytes) {
if (n == -1) { if (n == -1) {
if (errno != EWOULDBLOCK && errno != EINTR && errno != EAGAIN) { if (errno != EWOULDBLOCK && errno != EINTR && errno != EAGAIN) {
if (errno != EPIPE) if (errno != EPIPE)
fprintf(stderr, "error reading %d bytes from node %d: %s\n", nbytes, nodeid, strerror(errno)); fprintf(stderr, "error reading %d bytes from node %d: %s\n", nbytes, nodeid, strerror(errno));
pncdisc(nodeid, "error reading packet"); pncdisc(nodeid, "error reading packet");
} }
n = 0; n = 0;
@@ -925,92 +921,92 @@ int devpnc (int class, int func, int device) {
where: where:
nodeid = node's id (1-247) on my ring nodeid = node's id (1-247) on my ring
host = the remote emulator's TCP/IP address or name host = the remote emulator's TCP/IP address or name
port = the remote emulator's TCP/IP PNC port port = the remote emulator's TCP/IP PNC port
NOTE: host:port may be - for incoming-only nodes NOTE: host:port may be - for incoming-only nodes
uid = 16 byte password, no spaces uid = 16 byte password, no spaces
NOTE: use od -h /dev/urandom|head to create a uid NOTE: use od -h /dev/urandom|head to create a uid
*/ */
linenum = 0; linenum = 0;
if ((ringfile=fopen("ring.cfg", "r")) != NULL) { if ((ringfile=fopen("ring.cfg", "r")) != NULL) {
while (fgets(buf, sizeof(buf), ringfile) != NULL) { while (fgets(buf, sizeof(buf), ringfile) != NULL) {
len = strlen(buf); len = strlen(buf);
linenum++; linenum++;
if (buf[len-1] != '\n') { if (buf[len-1] != '\n') {
fprintf(stderr,"Line %d of ring.cfg ignored: line too long, can't parse file\n", linenum); fprintf(stderr,"Line %d of ring.cfg ignored: line too long, can't parse file\n", linenum);
return -1; return -1;
} }
buf[len-1] = 0; buf[len-1] = 0;
if (strcmp(buf,"") == 0 || buf[0] == ';' || buf[0] == '#') if (strcmp(buf,"") == 0 || buf[0] == ';' || buf[0] == '#')
continue; continue;
if ((p=strtok(buf, DELIM)) == NULL) { if ((p=strtok(buf, DELIM)) == NULL) {
fprintf(stderr,"Line %d of ring.cfg ignored: node id missing\n", linenum); fprintf(stderr,"Line %d of ring.cfg ignored: node id missing\n", linenum);
continue; continue;
} }
tempid = atoi(p); tempid = atoi(p);
if (tempid < 1 || tempid > MAXNODEID) { if (tempid < 1 || tempid > MAXNODEID) {
fprintf(stderr,"Line %d of ring.cfg ignored: node id is out of range 1-%d\n", linenum, MAXNODEID); fprintf(stderr,"Line %d of ring.cfg ignored: node id is out of range 1-%d\n", linenum, MAXNODEID);
continue; continue;
} }
if (ni[tempid].cstate != PNCCSNONE) { if (ni[tempid].cstate != PNCCSNONE) {
fprintf(stderr,"Line %d of ring.cfg ignored: node id occurs more than once\n", linenum); fprintf(stderr,"Line %d of ring.cfg ignored: node id occurs more than once\n", linenum);
continue; continue;
} }
if ((p=strtok(NULL, DELIM)) == NULL) { if ((p=strtok(NULL, DELIM)) == NULL) {
fprintf(stderr,"Line %d of ring.cfg ignored: host address missing\n", linenum); fprintf(stderr,"Line %d of ring.cfg ignored: host address missing\n", linenum);
continue; continue;
} }
if (strlen(p) > MAXHOSTLEN) { if (strlen(p) > MAXHOSTLEN) {
fprintf(stderr,"Line %d of ring.cfg ignored: IP address too long\n", linenum); fprintf(stderr,"Line %d of ring.cfg ignored: IP address too long\n", linenum);
continue; continue;
} }
strncpy(temphost, p, MAXHOSTLEN); strncpy(temphost, p, MAXHOSTLEN);
if ((p=strtok(NULL, DELIM)) == NULL) { if ((p=strtok(NULL, DELIM)) == NULL) {
fprintf(stderr,"Line %d of ring.cfg ignored: unique id/password missing\n", linenum); fprintf(stderr,"Line %d of ring.cfg ignored: unique id/password missing\n", linenum);
continue; continue;
} }
if (strlen(p) > MAXUIDLEN) { if (strlen(p) > MAXUIDLEN) {
fprintf(stderr,"Line %d of ring.cfg ignored: unique id/password too long\n", linenum); fprintf(stderr,"Line %d of ring.cfg ignored: unique id/password too long\n", linenum);
continue; continue;
} }
bzero(ni[tempid].uid, sizeof(ni[tempid].uid)); bzero(ni[tempid].uid, sizeof(ni[tempid].uid));
for (i=0; i<=MAXNODEID; i++) for (i=0; i<=MAXNODEID; i++)
if (strcmp(p, ni[i].uid) == 0) { if (strcmp(p, ni[i].uid) == 0) {
fprintf(stderr,"Line %d of ring.cfg ignored: unique id/password is not unique\n", linenum); fprintf(stderr,"Line %d of ring.cfg ignored: unique id/password is not unique\n", linenum);
break; break;
} }
if (i <= MAXNODEID) if (i <= MAXNODEID)
continue; continue;
strncpy(ni[tempid].uid, p, MAXUIDLEN); strncpy(ni[tempid].uid, p, MAXUIDLEN);
/* parse the port number from the IP address */ /* parse the port number from the IP address */
tempport = 0; tempport = 0;
if (strcmp(temphost, "-") != 0) { if (strcmp(temphost, "-") != 0) {
if ((p=strtok(temphost, PDELIM)) != NULL) { if ((p=strtok(temphost, PDELIM)) != NULL) {
strncpy(ni[tempid].host, p, MAXHOSTLEN); strncpy(ni[tempid].host, p, MAXHOSTLEN);
if ((p=strtok(NULL, PDELIM)) != NULL) { if ((p=strtok(NULL, PDELIM)) != NULL) {
tempport = atoi(p); tempport = atoi(p);
if (tempport < 1 || tempport > 65000) if (tempport < 1 || tempport > 65000)
fprintf(stderr,"Line %d of ring.cfg ignored: port number out of range 1-65000\n", linenum); fprintf(stderr,"Line %d of ring.cfg ignored: port number out of range 1-65000\n", linenum);
} }
} }
if (tempport <= 0) { if (tempport <= 0) {
fprintf(stderr, "Line %d of ring.cfg ignored: can't parse port number from %s\n", linenum, temphost); fprintf(stderr, "Line %d of ring.cfg ignored: can't parse port number from %s\n", linenum, temphost);
continue; continue;
} }
} }
ni[tempid].cstate = PNCCSDISC; ni[tempid].cstate = PNCCSDISC;
ni[tempid].port = tempport; ni[tempid].port = tempport;
TRACE(T_RIO, "Line %d: id=%d, host=\"%s\", port=%d, uid=%s\n", linenum, tempid, temphost, tempport, ni[tempid].uid); TRACE(T_RIO, "Line %d: id=%d, host=\"%s\", port=%d, uid=%s\n", linenum, tempid, temphost, tempport, ni[tempid].uid);
configured = 1; configured = 1;
} }
if (!feof(ringfile)) { if (!feof(ringfile)) {
perror(" error reading ring.cfg"); perror(" error reading ring.cfg");
fatal(NULL); fatal(NULL);
} }
fclose(ringfile); fclose(ringfile);
} else } else
@@ -1087,7 +1083,7 @@ int devpnc (int class, int func, int device) {
if (func == 00) { /* OCP '0007 - disconnect */ if (func == 00) { /* OCP '0007 - disconnect */
TRACE(T_INST|T_RIO, " OCP '%02o%02o - disconnect\n", func, device); TRACE(T_INST|T_RIO, " OCP '%02o%02o - disconnect\n", func, device);
for (i=0; i<=MAXNODEID; i++) for (i=0; i<=MAXNODEID; i++)
pncdisc(i, "ring disconnect"); pncdisc(i, "ring disconnect");
rcv.state = PNCBSIDLE; rcv.state = PNCBSIDLE;
rcvstat = PNCRSBUSY; rcvstat = PNCRSBUSY;
xmitstat = PNCXSBUSY; xmitstat = PNCXSBUSY;
@@ -1183,12 +1179,12 @@ int devpnc (int class, int func, int device) {
IOSKIP; IOSKIP;
/* these next two are mostly bogus: prmnt1 T&M wants them this /* these next two are mostly bogus: prmnt1 T&M wants them this
way because it puts the PNC in diagnostic mode, disables way because it puts the PNC in diagnostic mode, disables
transmit and receive, then does transmit and receive transmit and receive, then does transmit and receive
operations to see how the DMA registers are affected. I operations to see how the DMA registers are affected. I
couldn't get very far with this T&M (couldn't complete test couldn't get very far with this T&M (couldn't complete test
1) because it is so specific to the exact states the PNC 1) because it is so specific to the exact states the PNC
hardware moves through. */ hardware moves through. */
} else if (func == 014) { /* read recv DMX channel */ } else if (func == 014) { /* read recv DMX channel */
TRACE(T_INST|T_RIO, " INA '%02o%02o - get recv DMX chan '%o 0x%04x\n", func, device, rcv.dmachan, rcv.dmachan); TRACE(T_INST|T_RIO, " INA '%02o%02o - get recv DMX chan '%o 0x%04x\n", func, device, rcv.dmachan, rcv.dmachan);
@@ -1228,11 +1224,11 @@ int devpnc (int class, int func, int device) {
} else if (func == 014) { /* initiate recv, dma chan in A */ } else if (func == 014) { /* initiate recv, dma chan in A */
if (!(pncstat & PNCNSCONNECTED)) { if (!(pncstat & PNCNSCONNECTED)) {
break; /* yes, return and don't skip */ break; /* yes, return and don't skip */
} }
if (rcvstat & PNCRSBUSY) { /* already busy? */ if (rcvstat & PNCRSBUSY) { /* already busy? */
warn("pnc: recv when already busy ignored"); warn("pnc: recv when already busy ignored");
break; /* yes, return and don't skip */ break; /* yes, return and don't skip */
} }
IOSKIP; IOSKIP;
rcvstat = PNCRSBUSY; /* set receive busy */ rcvstat = PNCRSBUSY; /* set receive busy */
@@ -1241,11 +1237,11 @@ int devpnc (int class, int func, int device) {
} else if (func == 015) { /* initiate xmit, dma chan in A */ } else if (func == 015) { /* initiate xmit, dma chan in A */
if (!(pncstat & PNCNSCONNECTED)) { if (!(pncstat & PNCNSCONNECTED)) {
break; /* yes, return and don't skip */ break; /* yes, return and don't skip */
} }
if (xmitstat & PNCXSBUSY) { /* already busy? */ if (xmitstat & PNCXSBUSY) { /* already busy? */
warn("pnc: xmit when already busy ignored"); warn("pnc: xmit when already busy ignored");
break; /* yes, return and don't skip */ break; /* yes, return and don't skip */
} }
IOSKIP; IOSKIP;
pncxmit(); pncxmit();
@@ -1259,12 +1255,12 @@ int devpnc (int class, int func, int device) {
} else if (func == 017) { /* set my node ID */ } else if (func == 017) { /* set my node ID */
myid = getcrs16(A) & 0xFF; myid = getcrs16(A) & 0xFF;
if (myid > MAXNODEID) { if (myid > MAXNODEID) {
printf("em: my nodeid %d > max nodeid %d; check Primenet config\n", myid, MAXNODEID); printf("em: my nodeid %d > max nodeid %d; check Primenet config\n", myid, MAXNODEID);
myid = 0; myid = 0;
} }
if (myid != 0 && ni[myid].cstate == PNCCSNONE) { if (myid != 0 && ni[myid].cstate == PNCCSNONE) {
printf("em: my nodeid %d not in ring.cfg; PNC disabled\n", myid); printf("em: my nodeid %d not in ring.cfg; PNC disabled\n", myid);
myid = 0; myid = 0;
} }
pncstat = (pncstat & 0xFF00) | myid; pncstat = (pncstat & 0xFF00) | myid;
ni[myid].cstate = PNCCSAUTH; ni[myid].cstate = PNCCSAUTH;
@@ -1303,10 +1299,10 @@ rcvexit:
intrexit: intrexit:
if (enabled && ((pncstat & 0xC000) | intstat) != intstat) { if (enabled && ((pncstat & 0xC000) | intstat) != intstat) {
if (gv.intvec == -1) { if (gv.intvec == -1) {
gv.intvec = pncvec; gv.intvec = pncvec;
intstat |= (pncstat & 0xC000); intstat |= (pncstat & 0xC000);
} else } else
devpoll[device] = 100; devpoll[device] = 100;
} }
break; break;

1292
devsmlc.h

File diff suppressed because it is too large Load Diff

28
ea32i.h
View File

@@ -26,33 +26,33 @@ static inline ea_t ea32i (ea_t earp, unsigned short inst, unsigned int *immu32,
d = iget16(RP); d = iget16(RP);
RPL++; RPL++;
if (sr == 0) /* imm type 1 */ if (sr == 0) /* imm type 1 */
*immu32 = d << 16; *immu32 = d << 16;
else /* imm type 2 */ else /* imm type 2 */
*(int *)immu32 = *(short *)&d; *(int *)immu32 = *(short *)&d;
return IMM_EA; return IMM_EA;
case 2: case 2:
switch (sr) { switch (sr) {
case 0: /* imm type 3 */ case 0: /* imm type 3 */
d = iget16(RP); d = iget16(RP);
INCRP; INCRP;
*immu64 = (((long long)(d & 0xFF00)) << 48) | (d & 0xFF); *immu64 = (((long long)(d & 0xFF00)) << 48) | (d & 0xFF);
return IMM_EA; return IMM_EA;
case 1: /* FAC0 source */ case 1: /* FAC0 source */
*immu64 = getgr64(FAC0); *immu64 = getgr64(FAC0);
return IMM_EA; return IMM_EA;
case 3: /* FAC1 source */ case 3: /* FAC1 source */
*immu64 = getgr64(FAC1); *immu64 = getgr64(FAC1);
return IMM_EA; return IMM_EA;
case 2: case 2:
case 4: case 4:
case 5: case 5:
case 6: case 6:
case 7: case 7:
fault(UIIFAULT, RPL, RP); fault(UIIFAULT, RPL, RP);
fatal("ea32i: return from UII fault!"); fatal("ea32i: return from UII fault!");
default: default:
fatal("ea32i: sr < 0 or > 7?"); fatal("ea32i: sr < 0 or > 7?");
} }
fatal("ea32i: case tm=0 br=2 fall-through"); fatal("ea32i: case tm=0 br=2 fall-through");
@@ -62,7 +62,7 @@ static inline ea_t ea32i (ea_t earp, unsigned short inst, unsigned int *immu32,
ea = (getgr32(sr) & 0xFFFF0000) | ((getgr32(sr) + d) & 0xFFFF); ea = (getgr32(sr) & 0xFFFF0000) | ((getgr32(sr) + d) & 0xFFFF);
TRACE(T_EAI, " GRR, d=%x, [sr]=%o/%o, ea=%o/%o\n", d, getgr32(sr)>>16, getgr32(sr)&0xFFFF, ea>>16, ea&0xFFFF); TRACE(T_EAI, " GRR, d=%x, [sr]=%o/%o, ea=%o/%o\n", d, getgr32(sr)>>16, getgr32(sr)&0xFFFF, ea>>16, ea&0xFFFF);
if (ea & 0x80000000) if (ea & 0x80000000)
fault(POINTERFAULT, ea>>16, ea); fault(POINTERFAULT, ea>>16, ea);
return ea | ring; return ea | ring;
default: default:

32
ea64v.h
View File

@@ -55,18 +55,18 @@ static inline ea_t ea64v (unsigned short inst, ea_t earp) {
if (xok) if (xok)
if (ixy == 2 || ixy == 6) if (ixy == 2 || ixy == 6)
ea_w += getcrs16(X); ea_w += getcrs16(X);
else if (ixy == 1 || ixy == 4) else if (ixy == 1 || ixy == 4)
ea_w += getcrs16(Y); ea_w += getcrs16(Y);
#if 0 #if 0
/* if this is a PB% address, use RPBR instead if it's in range /* if this is a PB% address, use RPBR instead if it's in range
NOTE: this has been disabled, because gcov showed it only NOTE: this has been disabled, because gcov showed it only
occurred 0.5% of the time */ occurred 0.5% of the time */
if (br == 0 && ((((ea_s & 0x8FFF) << 16) | (ea_w & 0xFC00)) == gv.brp[RPBR].vpn)) if (br == 0 && ((((ea_s & 0x8FFF) << 16) | (ea_w & 0xFC00)) == gv.brp[RPBR].vpn))
eap = &gv.brp[RPBR]; eap = &gv.brp[RPBR];
#endif #endif
if (ixy >= 3) { if (ixy >= 3) {
@@ -74,26 +74,26 @@ static inline ea_t ea64v (unsigned short inst, ea_t earp) {
TRACE(T_EAV, " Long indirect, ea=%o/%o, ea_s=%o, ea_w=%o\n", ea>>16, ea&0xFFFF, ea_s, ea_w); TRACE(T_EAV, " Long indirect, ea=%o/%o, ea_s=%o, ea_w=%o\n", ea>>16, ea&0xFFFF, ea_s, ea_w);
m = get16(ea); m = get16(ea);
if (m & 0x8000) if (m & 0x8000)
fault(POINTERFAULT, m, ea); fault(POINTERFAULT, m, ea);
ea_s = m | (ea_s & RINGMASK16); ea_s = m | (ea_s & RINGMASK16);
ea_w = get16(INCVA(ea,1)); ea_w = get16(INCVA(ea,1));
TRACE(T_EAV, " After indirect, ea_s=%o, ea_w=%o\n", ea_s, ea_w); TRACE(T_EAV, " After indirect, ea_s=%o, ea_w=%o\n", ea_s, ea_w);
/* when passing stack variables, callee references will be /* when passing stack variables, callee references will be
SB%+20,*, which may still be in the same page. Don't switch to SB%+20,*, which may still be in the same page. Don't switch to
UNBR if the new ea is still in the current page */ UNBR if the new ea is still in the current page */
if ((((ea_s & 0x8FFF) << 16) | (ea_w & 0xFC00)) != (eap->vpn & 0x0FFFFFFF)) if ((((ea_s & 0x8FFF) << 16) | (ea_w & 0xFC00)) != (eap->vpn & 0x0FFFFFFF))
eap = &gv.brp[UNBR]; eap = &gv.brp[UNBR];
if (xok) if (xok)
if (ixy == 7) { if (ixy == 7) {
TRACE(T_EAV, " Postindex, old ea_w=%o, X='%o/%d\n", ea_w, getcrs16(X), getcrs16s(X)); TRACE(T_EAV, " Postindex, old ea_w=%o, X='%o/%d\n", ea_w, getcrs16(X), getcrs16s(X));
ea_w += getcrs16(X); ea_w += getcrs16(X);
} else if (ixy == 5) { } else if (ixy == 5) {
TRACE(T_EAV, " Postindex, old ea_w=%o, Y='%o/%d\n", ea_w, getcrs16(Y), getcrs16s(Y)); TRACE(T_EAV, " Postindex, old ea_w=%o, Y='%o/%d\n", ea_w, getcrs16(Y), getcrs16s(Y));
ea_w += getcrs16(Y); ea_w += getcrs16(Y);
} }
} }
return MAKEVA(ea_s, ea_w); return MAKEVA(ea_s, ea_w);
} }

33
em.1
View File

@@ -2,7 +2,7 @@
.\" em.1, Boone, 03/13/20 .\" em.1, Boone, 03/13/20
.\" Man page for Jim Wilcoxson's Prime 50-Series emulator .\" Man page for Jim Wilcoxson's Prime 50-Series emulator
.\" --------------------------------------------------------------------------- .\" ---------------------------------------------------------------------------
.TH em 1 "2020-06-23" "Jim Wilcoxson" "50-Series Emulator" .TH em 1 "2020-03-14" "Jim Wilcoxson" "50-Series Emulator"
.\" --------------------------------------------------------------------------- .\" ---------------------------------------------------------------------------
.SH NAME .SH NAME
em \- Emulator for Prime 50-Series systems em \- Emulator for Prime 50-Series systems
@@ -35,8 +35,6 @@ a tape controller, 4 drives, using the .TAP format
.IP \(bu .IP \(bu
a PNC controller emulating RingNet over TCP/IP a PNC controller emulating RingNet over TCP/IP
.IP \(bu .IP \(bu
two sync serial controllers supporting up to 8 lines
.IP \(bu
a bypass for Primos system serial number checks a bypass for Primos system serial number checks
.IP \(bu .IP \(bu
Unix utilities to read/write physical tapes & Magsav tapes Unix utilities to read/write physical tapes & Magsav tapes
@@ -145,15 +143,6 @@ on the host. Multiple trace types may be listed, separated by
spaces. Tracing may be initially turned off by including the spaces. Tracing may be initially turned off by including the
.I off .I off
trace type. trace type.
.PP
\fB-dolineclear\fR
.IP
Inject an XON (DC1, 0221) character and a line kill character into the
input buffers each time an AMLC line receives an incoming connection.
The system's configured line kill character is fetched from the
DEFKIL field of FIGCOM, at address 14(0)/705. This behavior helps
counteract lines which have been blocked by internet vulnerability
scanners injecting non-telnet data streams.
.\" --------------------------------------------------------------------------- .\" ---------------------------------------------------------------------------
.SH FILES .SH FILES
.TP .TP
@@ -174,18 +163,6 @@ Example:
8 192.168.10.4:9000 # Outbound socket connection e.g. for spooler 8 192.168.10.4:9000 # Outbound socket connection e.g. for spooler
.EE .EE
.TP .TP
smlc.cfg
Used to associate outbound sync serial (MDLC or HSSMLC) lines with destination
IP addresses and port numbers, or to associate inbound sync serial lines
with port numbers. An outbound line corresponds to an RJE site defined as a
SLAVE site, and an inbound line corresponds to an RJE site defined as a MASTER
site. Optional. Comments work the same as amlc.cfg. Example:
.EX
0 10.1.1.3:2554 # Connect to TCP port 2554 of host 10.1.1.3 for outbound line 0
1 9951 # Listen on TCP port 9951 for inbound line 1
.EE
.TP
console.log console.log
All console output is also written to this file. It is overwritten All console output is also written to this file. It is overwritten
at each invocation. Created by at each invocation. Created by
@@ -297,12 +274,9 @@ off|Start with tracing disabled
all|Everything all|Everything
flush|Flush trace file after each write flush|Flush trace file after each write
tlb|STLB and IOTLB changes tlb|STLB and IOTLB changes
smlc|MDLC/HSSMLC device I/O
OWNERL|Execution of this PCB OWNERL|Execution of this PCB
#instruction count|Begin after specified number of instructions instruction count|Begin after specified number of instructions
|(the leading # is literal)
octal segno|Execution in the given segment number octal segno|Execution in the given segment number
|(may interact poorly with "off")
process number|Execution of this user number process number|Execution of this user number
.TE .TE
.\" --------------------------------------------------------------------------- .\" ---------------------------------------------------------------------------
@@ -386,8 +360,7 @@ CMD,1/3/5+1,Cartridge Module 32/64/96 MB
.\" --------------------------------------------------------------------------- .\" ---------------------------------------------------------------------------
.SH AUTHOR .SH AUTHOR
.PP .PP
This emulator was written by Jim Wilcoxson. MDLC/HSSMLC support by This emulator was written by Jim Wilcoxson. Man page by Dennis Boone.
Kevin Jordan. Man page by Dennis Boone.
.\" --------------------------------------------------------------------------- .\" ---------------------------------------------------------------------------
.SH SEE ALSO .SH SEE ALSO
This project is hosted at This project is hosted at

2233
em.c

File diff suppressed because it is too large Load Diff

1328
emdev.h

File diff suppressed because it is too large Load Diff

124
fp.h
View File

@@ -40,7 +40,6 @@ http://tima-cmp.imag.fr/~guyot/Cours/Oparithm/english/Op_Ar2.htm
inline void getdp (unsigned long long p, long long *frac64, int *exp32) { inline void getdp (unsigned long long p, long long *frac64, int *exp32) {
TRACE(T_FP, " getdp(%016llx)\n", p);
*frac64 = p & 0xFFFFFFFFFFFF0000LL; /* unpack fraction */ *frac64 = p & 0xFFFFFFFFFFFF0000LL; /* unpack fraction */
*exp32 = (short) (p & 0xFFFFLL); /* unpack SIGNED exponent */ *exp32 = (short) (p & 0xFFFFLL); /* unpack SIGNED exponent */
} }
@@ -60,29 +59,22 @@ int prieee8(unsigned long long dp, double *d) {
/* unpack Prime DPFP */ /* unpack Prime DPFP */
getdp (dp, &frac64, &exp32); getdp (dp, &frac64, &exp32);
TRACE(T_FP, " prieee8: unpacked frac %016llx exp %08x\n", frac64, exp32);
/* if negative, change to sign-magnitude */ /* if negative, change to sign-magnitude */
sign = 0; sign = 0;
if (frac64 < 0) { if (frac64 < 0) {
TRACE(T_FP, " prieee8: changing to sign-magnitude\n");
/* special case: negative power of 2 */ /* special case: negative power of 2 */
if (frac64 == 0x8000000000000000LL) { if (frac64 == 0x8000000000000000LL) {
TRACE(T_FP, " prieee8: frac is negative power of 2\n");
exp32 += (1023-128); exp32 += (1023-128);
if (exp32 < 0 || exp32 > 0x7fe) if (exp32 < 0 || exp32 > 0x7fe)
{ return 0;
TRACE(T_FP, " prieee8: exp %x out of range\n", exp32);
return 0;
}
frac64 |= ((long long)exp32 << 52); frac64 |= ((long long)exp32 << 52);
*d = *(double *)&frac64; *d = *(double *)&frac64;
return 1; return 1;
} else { } else {
TRACE(T_FP, " prieee8: frac is just negative\n");
sign = 0x8000000000000000LL; sign = 0x8000000000000000LL;
frac64 = -frac64; frac64 = -frac64;
} }
@@ -90,15 +82,13 @@ int prieee8(unsigned long long dp, double *d) {
/* special case: zero */ /* special case: zero */
} else if (frac64 == 0) { } else if (frac64 == 0) {
TRACE(T_FP, " prieee8: frac is 0\n");
*d = 0.0; *d = 0.0;
return 1; return 1;
} }
/* normalize positive fraction until bit 2 is 1 */ /* normalize positive fraction until bit 2 is 1 */
while ((frac64 & 0x4000000000000000LL) == 0) { while ((frac64 & 0x4000000000000000LL) == 0) {
TRACE(T_FP, " prieee8: normalizing positive fraction\n");
frac64 = frac64 << 1; frac64 = frac64 << 1;
exp32--; exp32--;
} }
@@ -108,10 +98,7 @@ int prieee8(unsigned long long dp, double *d) {
exp32 += (1023-128) - 1; exp32 += (1023-128) - 1;
#if 1 #if 1
if (exp32 < 0 || exp32 > 0x7fe) if (exp32 < 0 || exp32 > 0x7fe)
{
TRACE(T_FP, " prieee8: exponent %x out of range\n", exp32);
return 0; return 0;
}
#else #else
if (exp32 < 0) { if (exp32 < 0) {
*d = 0.0; *d = 0.0;
@@ -126,7 +113,6 @@ int prieee8(unsigned long long dp, double *d) {
/* pack into an IEEE DPFP, losing the leading 1 bit in the process */ /* pack into an IEEE DPFP, losing the leading 1 bit in the process */
frac64 = sign | ((long long)exp32 << 52) | ((frac64 >> 10) & 0xfffffffffffffLL); frac64 = sign | ((long long)exp32 << 52) | ((frac64 >> 10) & 0xfffffffffffffLL);
TRACE(T_FP, " prieee8: packed ieee dpfp %016llx\n", frac64);
*d = *(double *)&frac64; *d = *(double *)&frac64;
return 1; return 1;
} }
@@ -148,7 +134,7 @@ retry:
neg = frac64 < 0; neg = frac64 < 0;
exp32 = (frac64 >> 52) & 0x7ff; exp32 = (frac64 >> 52) & 0x7ff;
frac64 &= 0xfffffffffffffLL; frac64 &= 0xfffffffffffffLL;
TRACE(T_FP, "d=%016llx, neg=%x, frac64=%016llx, exp32=%08x, \n", (long long)d, neg, frac64, exp32); //printf("dp=%llx, neg=%d, frac64=%llx, exp32=%d, \n", *(long long *)dp, neg, frac64, exp32);
/* special case: NaN & +-infinity */ /* special case: NaN & +-infinity */
@@ -156,11 +142,11 @@ retry:
okay = 0; okay = 0;
if (frac64 == 0) if (frac64 == 0)
if (neg) { if (neg) {
printf("em: +infinity in ieeepr8\n"); printf("em: +infinity in ieeepr8\n");
d = DBL_MAX; d = DBL_MAX;
} else { } else {
printf("em: -infinity in ieeepr8\n"); printf("em: -infinity in ieeepr8\n");
d = DBL_MIN; d = DBL_MIN;
} }
else { else {
printf("em: NaN in ieeepr8\n"); printf("em: NaN in ieeepr8\n");
@@ -173,21 +159,12 @@ retry:
and subnormal */ and subnormal */
if (exp32 != 0) /* typical IEEE normalized */ if (exp32 != 0) /* typical IEEE normalized */
{
TRACE(T_FP, " ieeepr8: is normalized\n");
frac64 |= 0x10000000000000LL; frac64 |= 0x10000000000000LL;
} else if (frac64 == 0) { /* IEEE +-0.0 (zero exp+frac) */
else if (frac64 == 0) /* IEEE +-0.0 (zero exp+frac) */
{
TRACE(T_FP, " ieeepr8: zero exp and frac\n");
*p = 0; /* IEEE and Prime zero are the same */ *p = 0; /* IEEE and Prime zero are the same */
return okay; return okay;
} } else
else
{
TRACE(T_FP, " ieeepr8: subnormal value\n");
; /* subnormal: no hidden 1 bit */ ; /* subnormal: no hidden 1 bit */
}
/* adjust exponent, change sign-magnitude to 2's complement, /* adjust exponent, change sign-magnitude to 2's complement,
and shift fraction into Prime placement (high 48 bits) */ and shift fraction into Prime placement (high 48 bits) */
@@ -196,14 +173,12 @@ retry:
if (neg) if (neg)
frac64 = -frac64; frac64 = -frac64;
frac64 <<= 10; frac64 <<= 10;
TRACE(T_FP, " ieeepr8: de-biased prime-ised frac %016llx exp %08x\n", frac64, exp32);
/* normalize Prime DPFP */ /* normalize Prime DPFP */
while ((frac64 ^ (frac64 << 1)) >= 0) { while ((frac64 ^ (frac64 << 1)) >= 0) {
frac64 = frac64 << 1; frac64 = frac64 << 1;
exp32--; exp32--;
TRACE(T_FP, " ieeepr8: normalized prime frac %016llx exp %08x\n", frac64, exp32);
} }
#if 0 #if 0
@@ -229,11 +204,8 @@ retry:
if (round) if (round)
if ((frac64 & 0x8000) && ((frac64 & 0x7fffffffffff0000LL) != 0x7fffffffffff0000LL)) if ((frac64 & 0x8000) && ((frac64 & 0x7fffffffffff0000LL) != 0x7fffffffffff0000LL))
{
/* XXX: should this be a subtract for negative numbers? */ /* XXX: should this be a subtract for negative numbers? */
frac64 += 0x10000; frac64 += 0x10000;
TRACE(T_FP, " ieeepr8: rounded frac %016llx\n", frac64);
}
*p = swap64((frac64 & 0xffffffffffff0000LL) | (exp32 & 0xffff)); *p = swap64((frac64 & 0xffffffffffff0000LL) | (exp32 & 0xffff));
return okay; return okay;
@@ -288,7 +260,6 @@ unsigned long long dfcm (unsigned long long dp, int *oflow) {
CLEARC; CLEARC;
*oflow = 0; *oflow = 0;
getdp(dp, &frac64, &exp32); getdp(dp, &frac64, &exp32);
TRACE(T_FP, " dfcm: unpacked frac %016llx exp %08x\n", frac64, exp32);
if (frac64 != 0) { /* can't normalize zero */ if (frac64 != 0) { /* can't normalize zero */
if (frac64 == 0x8000000000000000LL) { /* overflow case? */ if (frac64 == 0x8000000000000000LL) { /* overflow case? */
frac64 = 0x4000000000000000LL; /* complement power of 2 */ frac64 = 0x4000000000000000LL; /* complement power of 2 */
@@ -296,8 +267,8 @@ unsigned long long dfcm (unsigned long long dp, int *oflow) {
} else { } else {
frac64 = -frac64; /* complement fraction */ frac64 = -frac64; /* complement fraction */
while ((frac64 ^ (frac64 << 1)) >= 0) { while ((frac64 ^ (frac64 << 1)) >= 0) {
frac64 = frac64 << 1; /* normalize */ frac64 = frac64 << 1; /* normalize */
exp32--; exp32--;
} }
} }
if (exp32 > 32767 || exp32 < -32768) if (exp32 > 32767 || exp32 < -32768)
@@ -319,7 +290,6 @@ unsigned long long norm(unsigned long long dp, int *oflow) {
*oflow = 0; *oflow = 0;
getdp(dp, &frac64, &exp32); getdp(dp, &frac64, &exp32);
TRACE(T_FP, " norm: unpacked frac %016llx exp %08x\n", frac64, exp32);
while ((frac64 ^ (frac64 << 1)) >= 0) { while ((frac64 ^ (frac64 << 1)) >= 0) {
frac64 = frac64 << 1; frac64 = frac64 << 1;
exp32--; exp32--;
@@ -344,30 +314,23 @@ unsigned long long frn(unsigned long long dp, int *oflow) {
*oflow = 0; *oflow = 0;
getdp(dp, &frac64, &exp32); getdp(dp, &frac64, &exp32);
TRACE(T_FP, " frn: unpacked frac %016llx exp %08x\n", frac64, exp32);
if (frac64 == 0) if (frac64 == 0)
{
TRACE(T_FP, " frn: returning 0\n");
return 0; return 0;
}
else { else {
doround1 = ((frac64 & 0x18000000000LL) != 0); doround1 = ((frac64 & 0x18000000000LL) != 0);
doround2 = ((frac64 & 0x8000000000LL) != 0) && ((frac64 & 0x7FFFFF0000LL) != 0); doround2 = ((frac64 & 0x8000000000LL) != 0) && ((frac64 & 0x7FFFFF0000LL) != 0);
TRACE(T_FP, " frn: doround1 %x doround2 %x\n", doround1, doround2);
if (doround1 || doround2) { if (doround1 || doround2) {
frac64 &= 0xFFFFFF0000000000LL; frac64 &= 0xFFFFFF0000000000LL;
if (frac64 != 0x7FFFFF0000000000LL) if (frac64 != 0x7FFFFF0000000000LL)
frac64 += 0x10000000000LL; frac64 += 0x10000000000LL;
else { else {
frac64 = 0x4000000000000000LL; frac64 = 0x4000000000000000LL;
exp32++; exp32++;
} }
frac64 |= (exp32 & 0xFFFF); frac64 |= (exp32 & 0xFFFF);
frac64 = norm(frac64, oflow); frac64 = norm(frac64, oflow);
TRACE(T_FP, " frn: rounded frac %016llx\n", frac64);
return frac64; return frac64;
} }
TRACE(T_FP, " frn: dp %016llx\n", dp);
return dp; return dp;
} }
} }
@@ -393,37 +356,26 @@ int fcs (unsigned long long fac, int fop) {
fop = fop & 0xffffff00; fop = fop & 0xffffff00;
if (fop == 0) /* fix dirty zero */ if (fop == 0) /* fix dirty zero */
fopexp = 0; fopexp = 0;
TRACE(T_FP, " fcs: FAC: %016llx %04x; op: %016llx %04x\n", templ, facexp, fop, fopexp);
if ((templ & 0x80000000) == (fop & 0x80000000)) { /* compare signs */ if ((templ & 0x80000000) == (fop & 0x80000000)) { /* compare signs */
if (facexp == fopexp) /* compare exponents */ if (facexp == fopexp) /* compare exponents */
if (templ == fop) { /* compare fractions */ if (templ == fop) { /* compare fractions */
TRACE(T_FP, " fcs: frac cmp returning eq / skip 1\n"); SETEQ;
SETEQ; return 1;
return 1;
} else if (templ < fop) { /* compare fractions */ } else if (templ < fop) { /* compare fractions */
TRACE(T_FP, " fcs: frac cmp returning lt / skip 2\n"); SETLT; /* FAC < operand */
SETLT; /* FAC < operand */ return 2;
return 2; } else
} else { return 0; /* FAC > operand */
TRACE(T_FP, " fcs: frac cmp returning gt / skip 0\n");
return 0; /* FAC > operand */
}
else if (facexp < fopexp) { /* compare exponents */ else if (facexp < fopexp) { /* compare exponents */
TRACE(T_FP, " fcs: exp cmp returning lt / skip 2\n");
SETLT; /* FAC < operand */ SETLT; /* FAC < operand */
return 2; return 2;
} else { } else
TRACE(T_FP, " fcs: exp cmp returning gt / skip 0\n");
return 0; return 0;
}
} else if (templ & 0x80000000) { } else if (templ & 0x80000000) {
TRACE(T_FP, " fcs: sign cmp returning lt / skip 2\n");
SETLT; /* FAC < operand */ SETLT; /* FAC < operand */
return 2; return 2;
} else { } else
TRACE(T_FP, " fcs: sign cmp returning gt / skip 0\n");
return 0; /* FAC > operand */ return 0; /* FAC > operand */
}
} }
@@ -434,7 +386,7 @@ int fcs (unsigned long long fac, int fop) {
NOTE: This code doesn't pass Prime diagnostics for higher model NOTE: This code doesn't pass Prime diagnostics for higher model
CPU's, I'm guessing because comparison is implemented as subtract, CPU's, I'm guessing because comparison is implemented as subtract,
and we can't do that because numbers with huge exponents (and and we can't do that because numbers with huge exponents (and
Prime ASCII characters in the DAC) won't convert to IEEE. Prime ASCII characters in the DAC) won't convert to IEEE.
*/ */
@@ -452,35 +404,27 @@ int dfcs (unsigned long long fac, long long fop) {
fop = fop & 0xffffffffffff0000LL; fop = fop & 0xffffffffffff0000LL;
if (fop == 0) /* fix dirty zero */ if (fop == 0) /* fix dirty zero */
fopexp = 0; fopexp = 0;
TRACE(T_FP, " dfcs: FAC: %016llx %04x; op: %016llx %04x\n", templl, facexp, fop, fopexp); #if 0
printf("dfcs: FAC: %016llx %04x; op: %016llx %04x\n", templl, facexp, fop, fopexp);
#endif
if ((templl & 0x8000000000000000LL) == (fop & 0x8000000000000000LL)) { /* compare signs */ if ((templl & 0x8000000000000000LL) == (fop & 0x8000000000000000LL)) { /* compare signs */
if (facexp == fopexp) /* compare exponents */ if (facexp == fopexp) /* compare exponents */
if (templl == fop) { /* compare fractions */ if (templl == fop) { /* compare fractions */
TRACE(T_FP, " dfcs: frac cmp returning eq / skip 1\n"); SETEQ;
SETEQ; return 1;
return 1;
} else if (templl < fop) { /* compare fractions */ } else if (templl < fop) { /* compare fractions */
TRACE(T_FP, " dfcs: frac cmp returning lt / skip 2\n"); SETLT; /* FAC < operand */
SETLT; /* FAC < operand */ return 2;
return 2; } else
} else { return 0; /* FAC > operand */
TRACE(T_FP, " dfcs: frac cmp returning gt / skip 0\n");
return 0; /* FAC > operand */
}
else if (facexp < fopexp) { /* compare exponents */ else if (facexp < fopexp) { /* compare exponents */
TRACE(T_FP, " dfcs: exp cmp returning lt / skip 2\n");
SETLT; /* FAC < operand */ SETLT; /* FAC < operand */
return 2; return 2;
} else { } else
TRACE(T_FP, " dfcs: exp cmp returning eq / skip 1\n");
return 0; return 0;
}
} else if (templl & 0x8000000000000000LL) { } else if (templl & 0x8000000000000000LL) {
TRACE(T_FP, " dfcs: sign cmp returning lt / skip 2\n");
SETLT; /* FAC < operand */ SETLT; /* FAC < operand */
return 2; return 2;
} else { } else
TRACE(T_FP, " dfcs: sign cmp returning gt / skip 0\n");
return 0; /* FAC > operand */ return 0; /* FAC > operand */
}
} }

View File

@@ -7,29 +7,25 @@ all_deps = makefile
em_objs = em.o em em_objs = em.o em
em_deps = \ em_deps = \
em.c regs.h emdev.h ea64v.h ea32i.h fp.h dispatch.h geom.h \ em.c regs.h emdev.h ea64v.h ea32i.h fp.h dispatch.h geom.h \
devpnc.h devamlc.h devsmlc.h swap.h devpnc.h devamlc.h swap.h
CFLAGS =
# Uncomment for building on SmartOS/Solaris:
# CFLAGS += -lsocket -lnsl
.PHONY: emwarn debug trace fixed .PHONY: emwarn debug trace fixed
# normal # normal
em: $(em_deps) $(all_deps) em: $(em_deps) $(all_deps)
$(CC) -DREV=\"${REV}\" ${CFLAGS} -DNOTRACE -DFAST -O -Winline -Wno-return-type em.c -o em $(CC) -DREV=\"${REV}\" -DNOTRACE -DFAST -O -Winline -Wno-return-type em.c -o em
# lots of compiler warnings # lots of compiler warnings
emwarn: $(em_deps) $(all_deps) emwarn: $(em_deps) $(all_deps)
$(CC) -DREV=\"${REV}\" ${CFLAGS} -DNOTRACE -DFAST -O -Wall -Wextra -pedantic -Wconversion em.c -o em $(CC) -DREV=\"${REV}\" -DNOTRACE -DFAST -O -Wall -Wextra -pedantic -Wconversion em.c -o em
# gdb # gdb
debug: $(em_deps) $(all_deps) debug: $(em_deps) $(all_deps)
$(CC) -DREV=\"${REV}\" ${CFLAGS} -DNOTRACE -DFAST -g -O0 em.c -o em $(CC) -DREV=\"${REV}\" -DNOTRACE -DFAST -g -O0 em.c -o em
# tracing # tracing
trace: $(em_deps) $(all_deps) trace: $(em_deps) $(all_deps)
$(CC) -DREV=\"${REV}\" ${CFLAGS} -DFAST -O em.c -o em $(CC) -DREV=\"${REV}\" -DFAST -O em.c -o em
# the fixed clock rate build is useful for making problems reproduceable. # the fixed clock rate build is useful for making problems reproduceable.
# #
@@ -39,7 +35,7 @@ trace: $(em_deps) $(all_deps)
# fixed clock rate # fixed clock rate
fixed: $(em_deps) $(all_deps) fixed: $(em_deps) $(all_deps)
$(CC) -DREV=\"${REV}\" ${CFLAGS} -DFIXEDCLOCK -DNOIDLE -DFAST -O em.c -o em $(CC) -DREV=\"${REV}\" -DFIXEDCLOCK -DNOIDLE -DFAST -O em.c -o em
clean: clean:
rm -f $(em_objs) rm -f $(em_objs)

101
regs.h
View File

@@ -6,6 +6,8 @@
#define REGSETS 10 #define REGSETS 10
#define T_REGS 0x00100000
/* these are 16-bit absolute offsets into the register file */ /* these are 16-bit absolute offsets into the register file */
#define PSWKEYS16 031*2 #define PSWKEYS16 031*2
@@ -167,51 +169,51 @@ static struct {
/* this is the number of user register sets for this cpuid */ /* this is the number of user register sets for this cpuid */
static short regsets[] = { \ static short regsets[] = { \
2, /* 00 P400 */ 2, /* 00 P400 */
2, /* 01 P400 (> REV A U-CODE) */ 2, /* 01 P400 (> REV A U-CODE) */
2, /* 02 RESERVED */ 2, /* 02 RESERVED */
2, /* 03 P350 */ 2, /* 03 P350 */
2, /* 04 P450/P550 */ 2, /* 04 P450/P550 */
2, /* 05 P750 */ 2, /* 05 P750 */
2, /* 06 P650 */ 2, /* 06 P650 */
2, /* 07 P150/P250 */ 2, /* 07 P150/P250 */
2, /* 08 P850 */ 2, /* 08 P850 */
2, /* 09 MOLE/550 */ 2, /* 09 MOLE/550 */
2, /* 10 MOLE/650 */ 2, /* 10 MOLE/650 */
2, /* 11 P2250 */ 2, /* 11 P2250 */
2, /* 12 P750Y */ 2, /* 12 P750Y */
2, /* 13 P550Y */ 2, /* 13 P550Y */
2, /* 14 P850Y */ 2, /* 14 P850Y */
4, /* 15 P9950 */ 4, /* 15 P9950 */
8, /* 16 P9650 */ 8, /* 16 P9650 */
8, /* 17 P2550 */ 8, /* 17 P2550 */
4, /* 18 P9955 */ 4, /* 18 P9955 */
4, /* 19 P9750 */ 4, /* 19 P9750 */
2, /* 20 TBD */ 2, /* 20 TBD */
8, /* 21 P2350 */ 8, /* 21 P2350 */
8, /* 22 P2655 */ 8, /* 22 P2655 */
8, /* 23 P9655 */ 8, /* 23 P9655 */
4, /* 24 P9955-TIGGER */ 4, /* 24 P9955-TIGGER */
8, /* 25 P2450 */ 8, /* 25 P2450 */
4, /* 26 P4050 */ 4, /* 26 P4050 */
4, /* 27 P4150 */ 4, /* 27 P4150 */
4, /* 28 P6350 */ 4, /* 28 P6350 */
4, /* 29 P6550 */ 4, /* 29 P6550 */
4, /* 30 P9955-II */ 4, /* 30 P9955-II */
8, /* 31 P2755 */ 8, /* 31 P2755 */
8, /* 32 P2455 */ 8, /* 32 P2455 */
4, /* 33 P5310 */ 4, /* 33 P5310 */
4, /* 34 P9755 */ 4, /* 34 P9755 */
4, /* 35 P2850 */ 4, /* 35 P2850 */
4, /* 36 P2950 */ 4, /* 36 P2950 */
4, /* 37 P5330 */ 4, /* 37 P5330 */
4, /* 38 P4450 */ 4, /* 38 P4450 */
4, /* 39 P5370 */ 4, /* 39 P5370 */
4, /* 40 P6650 */ 4, /* 40 P6650 */
4, /* 41 P6450 */ 4, /* 41 P6450 */
4, /* 42 P6150 */ 4, /* 42 P6150 */
4, /* 43 P5320 */ 4, /* 43 P5320 */
4}; /* 44 P5340 */ 4}; /* 44 P5340 */
static union { static union {
int rs[REGSETS][32]; int rs[REGSETS][32];
@@ -292,6 +294,7 @@ static inline uint16_t getcrs16(int offset) { \
/* store 16-bit unsigned at 16-bit offset */ /* store 16-bit unsigned at 16-bit offset */
//#define putcrs16(offset, val) crs[(offset)] = (val) //#define putcrs16(offset, val) crs[(offset)] = (val)
static inline void putcrs16(int offset, uint16_t val) { \ static inline void putcrs16(int offset, uint16_t val) { \
TRACE(T_REGS, " putcrs16: offset %d val %06o\n", offset, val);
crs[(offset)] = swap16(val); \ crs[(offset)] = swap16(val); \
} }
@@ -312,6 +315,7 @@ static inline uint32_t getcrs32(int offset) { \
/* put 32-bit unsigned at 16-bit offset */ /* put 32-bit unsigned at 16-bit offset */
//#define putcrs32(offset, val) *(unsigned int *)(crs+(offset)) = (val) //#define putcrs32(offset, val) *(unsigned int *)(crs+(offset)) = (val)
static inline void putcrs32(int offset, uint32_t val) { \ static inline void putcrs32(int offset, uint32_t val) { \
TRACE(T_REGS, " putcrs32: offset %d val %012lo\n", offset, val);
*(unsigned int *)(crs+offset) = swap32(val); \ *(unsigned int *)(crs+offset) = swap32(val); \
} }
@@ -330,7 +334,7 @@ static inline void putcrs32(int offset, uint32_t val) { \
/* get 64-bit signed at 16-bit offset */ /* get 64-bit signed at 16-bit offset */
//#define getcrs64s(offset) *(long long *)(crs+(offset)) //#define getcrs64s(offset) *(long long *)(crs+(offset))
static inline int64_t getcrs64s(int offset) { \ static inline int64_t getcrs64s(int offset) { \
return (long long)swap64(*(long long *)(crs+(offset))); \ return (long long)swap64(*(long long *)(crs+(offset))); \
} }
/* put 64-bit signed at 16-bit offset */ /* put 64-bit signed at 16-bit offset */
@@ -342,7 +346,7 @@ static inline void putcrs64s(int offset, int64_t val) { \
/* put 64-bit double at 16-bit offset (remove later) */ /* put 64-bit double at 16-bit offset (remove later) */
//#define putcrs64d(offset, val) *(double *)(crs+(offset)) = (val) //#define putcrs64d(offset, val) *(double *)(crs+(offset)) = (val)
static inline void putcrs64d(int offset, double val) { \ static inline void putcrs64d(int offset, double val) { \
*(unsigned long long *)(crs+offset) = swap64(*(uint64_t *)&val); \ *(unsigned long long *)(crs+offset) = swap64(*(uint64_t *)&val); \
} }
/* get 16-bit unsigned at 16-bit absolute register file address */ /* get 16-bit unsigned at 16-bit absolute register file address */
@@ -352,6 +356,7 @@ static inline uint16_t getar16(int offset) { \
/* put 16-bit unsigned at 16-bit absolute register file address */ /* put 16-bit unsigned at 16-bit absolute register file address */
static inline void putar16(int offset, uint16_t val) { \ static inline void putar16(int offset, uint16_t val) { \
TRACE(T_REGS, " putar16: offset %d val %06o\n", offset, val);
regs.u16[(offset)] = swap16(val); \ regs.u16[(offset)] = swap16(val); \
} }
@@ -446,7 +451,7 @@ static inline void putfr64(int offset, unsigned long long val) { \
For FP 0, offset=0; for FP 1, offset=2 */ For FP 0, offset=0; for FP 1, offset=2 */
//#define putfr64d(offset, val) *(double *)(crsl+FAC0+offset) = (val) //#define putfr64d(offset, val) *(double *)(crsl+FAC0+offset) = (val)
static inline void putfr64d(int offset, double val) { \ static inline void putfr64d(int offset, double val) { \
*(unsigned long long *)(crsl+FAC0+offset) = swap64(*(uint64_t *)&val); \ *(unsigned long long *)(crsl+FAC0+offset) = swap64(*(uint64_t *)&val); \
} }
#define PCBLEV 0 #define PCBLEV 0

View File

@@ -1,35 +0,0 @@
/* Show approximate minimum clock resolution
Derived from the example in the linux man page for clock_gettime() */
#define _XOPEN_SOURCE 600
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
static void displayClock(clockid_t clock, char *name)
{
struct timespec ts;
time_t oldsec;
long oldnsec;
clock_gettime(clock, &ts);
oldsec = ts.tv_sec;
oldnsec = ts.tv_nsec;
while (ts.tv_sec == oldsec && ts.tv_nsec == oldnsec)
{
if (clock_gettime(clock, &ts) == -1) {
perror("clock_gettime");
exit(EXIT_FAILURE);
}
}
printf("%-15s: %10ld sec %09ld nsec\n", name,
(long) ts.tv_sec - oldsec, ts.tv_nsec - oldnsec);
}
int main(int argc, char *argv[])
{
displayClock(CLOCK_MONOTONIC_RAW, "CLOCK_MONOTONIC_RAW");
exit(0);
}

View File

@@ -2,7 +2,7 @@ default: emlink intsize magrst magsav mtread mtwrite ptextu strip8 \
untap untap16 untap_vin utextp untap untap16 untap_vin utextp
# Unix version of Prime's magrst # Unix version of Prime's magrst
magrst: magrst.c istext.c magrst: magrst.c istext.c
# Unix version of Prime's magsav # Unix version of Prime's magsav
magsav: magsav.c istext.c magsav: magsav.c istext.c

View File

@@ -1,5 +1,5 @@
/* utextp.c, Jim Wilcoxson, March 16, 2005 /* utextp.c, Jim Wilcoxson, March 16, 2005
Reads a Unix text file and converts it to a compressed Prime text file. Reads a Unix text file and converts it to a compressed Prime text file.
This means: This means:
- turn high bit on - turn high bit on
- expand Unix tabs to spaces - expand Unix tabs to spaces
@@ -29,7 +29,7 @@ main () {
else { /* not a space character */ else { /* not a space character */
while (space) { /* dump held-back spaces first */ while (space) { /* dump held-back spaces first */
if (space < 3) { /* write regular spaces */ if (space < 3) { /* write regular spaces */
putchar(0240); putchar(' ');
space--; space--;
n++; n++;
} else { /* write compressed spaces */ } else { /* write compressed spaces */