mirror of
https://github.com/prirun/p50em.git
synced 2026-03-04 18:14:16 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e61857e333 | ||
|
|
4771f09e1e | ||
|
|
6bf6e2ea48 | ||
|
|
edf7129651 | ||
|
|
543aa3f963 | ||
|
|
7d7504a02e | ||
|
|
43d2d863d7 | ||
|
|
80c1a57895 | ||
|
|
d566f42ea6 | ||
|
|
af1718f699 | ||
|
|
91bddd02c3 | ||
|
|
4def8fe397 | ||
|
|
43bbf3cd8f |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,6 +3,7 @@
|
||||
*.log
|
||||
*.swp
|
||||
tags
|
||||
cmraw
|
||||
cscope.*
|
||||
em
|
||||
emlink
|
||||
|
||||
216
devpnc.h
216
devpnc.h
@@ -77,7 +77,7 @@
|
||||
1: "Type" word.
|
||||
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 16 set = broadcast timer message
|
||||
Bit 16 set = broadcast timer message
|
||||
|
||||
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.
|
||||
@@ -121,15 +121,15 @@
|
||||
7: data 2
|
||||
|
||||
PNC diagnostic register:
|
||||
NORXTX EQU '100000 DISABLE TX AND RX
|
||||
TXDATER EQU '040000 FORCE RX CRC ERROR
|
||||
TXACKER EQU '020000 FORCE TX ACK ERROR
|
||||
RXACKER EQU '010000 FORCE RX ACK BYTE ERROR
|
||||
CABLE EQU '000001 LOOPBACK OVER CABLE
|
||||
ANALOG EQU '000002 LOOPBACK THRU ANALOG DEVICES
|
||||
SINGSTEP EQU '000004 LOOPBACK THRU SHIFT REG
|
||||
RETRY EQU '000000 ALLOW HARDWR RETRY
|
||||
NORETRY EQU '000010 NO HARDWR RETRY
|
||||
NORXTX EQU '100000 DISABLE TX AND RX
|
||||
TXDATER EQU '040000 FORCE RX CRC ERROR
|
||||
TXACKER EQU '020000 FORCE TX ACK ERROR
|
||||
RXACKER EQU '010000 FORCE RX ACK BYTE ERROR
|
||||
CABLE EQU '000001 LOOPBACK OVER CABLE
|
||||
ANALOG EQU '000002 LOOPBACK THRU ANALOG DEVICES
|
||||
SINGSTEP EQU '000004 LOOPBACK THRU SHIFT REG
|
||||
RETRY EQU '000000 ALLOW HARDWR RETRY
|
||||
NORETRY EQU '000010 NO HARDWR RETRY
|
||||
|
||||
Primos PNC usage:
|
||||
|
||||
@@ -439,7 +439,7 @@ void pncaccept(time_t timenow) {
|
||||
fd = accept(pncfd, (struct sockaddr *)&addr, &addrlen);
|
||||
if (fd == -1) {
|
||||
if (errno != EWOULDBLOCK && errno != EINTR && errno != EAGAIN)
|
||||
perror("accept error for PNC");
|
||||
perror("accept error for PNC");
|
||||
return;
|
||||
}
|
||||
if (!(pncstat & PNCNSCONNECTED)) {
|
||||
@@ -731,7 +731,7 @@ unsigned short pncxmit() {
|
||||
if (xmit.toid == 255) {
|
||||
for (nodeid=1; nodeid<=MAXNODEID; nodeid++)
|
||||
if (ni[nodeid].cstate != PNCCSNONE)
|
||||
xmitstat |= pncxmit1(nodeid);
|
||||
xmitstat |= pncxmit1(nodeid);
|
||||
} else {
|
||||
xmitstat |= pncxmit1(xmit.toid);
|
||||
}
|
||||
@@ -764,7 +764,7 @@ void pncrecv() {
|
||||
if (fd != -1)
|
||||
FD_SET(fd, &fds);
|
||||
if (fd > n)
|
||||
n = fd;
|
||||
n = fd;
|
||||
}
|
||||
n = select(n+1, &fds, NULL, NULL, &timeout);
|
||||
if (n == -1) {
|
||||
@@ -784,7 +784,7 @@ void pncrecv() {
|
||||
fd = ni[nodeid].fd;
|
||||
if (fd >= 0 && FD_ISSET(fd, &fds))
|
||||
if (pncrecv1(nodeid))
|
||||
break;
|
||||
break;
|
||||
} while (nodeid != prevnode); /* went round once? */
|
||||
prevnode = nodeid;
|
||||
}
|
||||
@@ -853,7 +853,7 @@ int pncread (int nodeid, int nbytes) {
|
||||
if (n == -1) {
|
||||
if (errno != EWOULDBLOCK && errno != EINTR && errno != EAGAIN) {
|
||||
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");
|
||||
}
|
||||
n = 0;
|
||||
@@ -925,92 +925,92 @@ int devpnc (int class, int func, int device) {
|
||||
where:
|
||||
nodeid = node's id (1-247) on my ring
|
||||
host = the remote emulator's TCP/IP address or name
|
||||
port = the remote emulator's TCP/IP PNC port
|
||||
NOTE: host:port may be - for incoming-only nodes
|
||||
uid = 16 byte password, no spaces
|
||||
NOTE: use od -h /dev/urandom|head to create a uid
|
||||
port = the remote emulator's TCP/IP PNC port
|
||||
NOTE: host:port may be - for incoming-only nodes
|
||||
uid = 16 byte password, no spaces
|
||||
NOTE: use od -h /dev/urandom|head to create a uid
|
||||
*/
|
||||
|
||||
linenum = 0;
|
||||
if ((ringfile=fopen("ring.cfg", "r")) != NULL) {
|
||||
while (fgets(buf, sizeof(buf), ringfile) != NULL) {
|
||||
len = strlen(buf);
|
||||
linenum++;
|
||||
if (buf[len-1] != '\n') {
|
||||
fprintf(stderr,"Line %d of ring.cfg ignored: line too long, can't parse file\n", linenum);
|
||||
return -1;
|
||||
}
|
||||
buf[len-1] = 0;
|
||||
if (strcmp(buf,"") == 0 || buf[0] == ';' || buf[0] == '#')
|
||||
continue;
|
||||
len = strlen(buf);
|
||||
linenum++;
|
||||
if (buf[len-1] != '\n') {
|
||||
fprintf(stderr,"Line %d of ring.cfg ignored: line too long, can't parse file\n", linenum);
|
||||
return -1;
|
||||
}
|
||||
buf[len-1] = 0;
|
||||
if (strcmp(buf,"") == 0 || buf[0] == ';' || buf[0] == '#')
|
||||
continue;
|
||||
|
||||
if ((p=strtok(buf, DELIM)) == NULL) {
|
||||
fprintf(stderr,"Line %d of ring.cfg ignored: node id missing\n", linenum);
|
||||
continue;
|
||||
}
|
||||
tempid = atoi(p);
|
||||
if (tempid < 1 || tempid > MAXNODEID) {
|
||||
fprintf(stderr,"Line %d of ring.cfg ignored: node id is out of range 1-%d\n", linenum, MAXNODEID);
|
||||
continue;
|
||||
}
|
||||
if (ni[tempid].cstate != PNCCSNONE) {
|
||||
fprintf(stderr,"Line %d of ring.cfg ignored: node id occurs more than once\n", linenum);
|
||||
continue;
|
||||
}
|
||||
if ((p=strtok(buf, DELIM)) == NULL) {
|
||||
fprintf(stderr,"Line %d of ring.cfg ignored: node id missing\n", linenum);
|
||||
continue;
|
||||
}
|
||||
tempid = atoi(p);
|
||||
if (tempid < 1 || tempid > MAXNODEID) {
|
||||
fprintf(stderr,"Line %d of ring.cfg ignored: node id is out of range 1-%d\n", linenum, MAXNODEID);
|
||||
continue;
|
||||
}
|
||||
if (ni[tempid].cstate != PNCCSNONE) {
|
||||
fprintf(stderr,"Line %d of ring.cfg ignored: node id occurs more than once\n", linenum);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((p=strtok(NULL, DELIM)) == NULL) {
|
||||
fprintf(stderr,"Line %d of ring.cfg ignored: host address missing\n", linenum);
|
||||
continue;
|
||||
}
|
||||
if (strlen(p) > MAXHOSTLEN) {
|
||||
fprintf(stderr,"Line %d of ring.cfg ignored: IP address too long\n", linenum);
|
||||
continue;
|
||||
}
|
||||
strncpy(temphost, p, MAXHOSTLEN);
|
||||
if ((p=strtok(NULL, DELIM)) == NULL) {
|
||||
fprintf(stderr,"Line %d of ring.cfg ignored: host address missing\n", linenum);
|
||||
continue;
|
||||
}
|
||||
if (strlen(p) > MAXHOSTLEN) {
|
||||
fprintf(stderr,"Line %d of ring.cfg ignored: IP address too long\n", linenum);
|
||||
continue;
|
||||
}
|
||||
strncpy(temphost, p, MAXHOSTLEN);
|
||||
|
||||
if ((p=strtok(NULL, DELIM)) == NULL) {
|
||||
fprintf(stderr,"Line %d of ring.cfg ignored: unique id/password missing\n", linenum);
|
||||
continue;
|
||||
}
|
||||
if (strlen(p) > MAXUIDLEN) {
|
||||
fprintf(stderr,"Line %d of ring.cfg ignored: unique id/password too long\n", linenum);
|
||||
continue;
|
||||
}
|
||||
bzero(ni[tempid].uid, sizeof(ni[tempid].uid));
|
||||
for (i=0; i<=MAXNODEID; i++)
|
||||
if (strcmp(p, ni[i].uid) == 0) {
|
||||
fprintf(stderr,"Line %d of ring.cfg ignored: unique id/password is not unique\n", linenum);
|
||||
break;
|
||||
}
|
||||
if ((p=strtok(NULL, DELIM)) == NULL) {
|
||||
fprintf(stderr,"Line %d of ring.cfg ignored: unique id/password missing\n", linenum);
|
||||
continue;
|
||||
}
|
||||
if (strlen(p) > MAXUIDLEN) {
|
||||
fprintf(stderr,"Line %d of ring.cfg ignored: unique id/password too long\n", linenum);
|
||||
continue;
|
||||
}
|
||||
bzero(ni[tempid].uid, sizeof(ni[tempid].uid));
|
||||
for (i=0; i<=MAXNODEID; i++)
|
||||
if (strcmp(p, ni[i].uid) == 0) {
|
||||
fprintf(stderr,"Line %d of ring.cfg ignored: unique id/password is not unique\n", linenum);
|
||||
break;
|
||||
}
|
||||
if (i <= MAXNODEID)
|
||||
continue;
|
||||
strncpy(ni[tempid].uid, p, MAXUIDLEN);
|
||||
continue;
|
||||
strncpy(ni[tempid].uid, p, MAXUIDLEN);
|
||||
|
||||
/* parse the port number from the IP address */
|
||||
/* parse the port number from the IP address */
|
||||
|
||||
tempport = 0;
|
||||
if (strcmp(temphost, "-") != 0) {
|
||||
if ((p=strtok(temphost, PDELIM)) != NULL) {
|
||||
strncpy(ni[tempid].host, p, MAXHOSTLEN);
|
||||
if ((p=strtok(NULL, PDELIM)) != NULL) {
|
||||
tempport = atoi(p);
|
||||
if (tempport < 1 || tempport > 65000)
|
||||
fprintf(stderr,"Line %d of ring.cfg ignored: port number out of range 1-65000\n", linenum);
|
||||
}
|
||||
}
|
||||
if (tempport <= 0) {
|
||||
fprintf(stderr, "Line %d of ring.cfg ignored: can't parse port number from %s\n", linenum, temphost);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ni[tempid].cstate = PNCCSDISC;
|
||||
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);
|
||||
configured = 1;
|
||||
tempport = 0;
|
||||
if (strcmp(temphost, "-") != 0) {
|
||||
if ((p=strtok(temphost, PDELIM)) != NULL) {
|
||||
strncpy(ni[tempid].host, p, MAXHOSTLEN);
|
||||
if ((p=strtok(NULL, PDELIM)) != NULL) {
|
||||
tempport = atoi(p);
|
||||
if (tempport < 1 || tempport > 65000)
|
||||
fprintf(stderr,"Line %d of ring.cfg ignored: port number out of range 1-65000\n", linenum);
|
||||
}
|
||||
}
|
||||
if (tempport <= 0) {
|
||||
fprintf(stderr, "Line %d of ring.cfg ignored: can't parse port number from %s\n", linenum, temphost);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ni[tempid].cstate = PNCCSDISC;
|
||||
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);
|
||||
configured = 1;
|
||||
}
|
||||
if (!feof(ringfile)) {
|
||||
perror(" error reading ring.cfg");
|
||||
fatal(NULL);
|
||||
perror(" error reading ring.cfg");
|
||||
fatal(NULL);
|
||||
}
|
||||
fclose(ringfile);
|
||||
} else
|
||||
@@ -1087,7 +1087,7 @@ int devpnc (int class, int func, int device) {
|
||||
if (func == 00) { /* OCP '0007 - disconnect */
|
||||
TRACE(T_INST|T_RIO, " OCP '%02o%02o - disconnect\n", func, device);
|
||||
for (i=0; i<=MAXNODEID; i++)
|
||||
pncdisc(i, "ring disconnect");
|
||||
pncdisc(i, "ring disconnect");
|
||||
rcv.state = PNCBSIDLE;
|
||||
rcvstat = PNCRSBUSY;
|
||||
xmitstat = PNCXSBUSY;
|
||||
@@ -1183,12 +1183,12 @@ int devpnc (int class, int func, int device) {
|
||||
IOSKIP;
|
||||
|
||||
/* these next two are mostly bogus: prmnt1 T&M wants them this
|
||||
way because it puts the PNC in diagnostic mode, disables
|
||||
transmit and receive, then does transmit and receive
|
||||
operations to see how the DMA registers are affected. I
|
||||
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
|
||||
hardware moves through. */
|
||||
way because it puts the PNC in diagnostic mode, disables
|
||||
transmit and receive, then does transmit and receive
|
||||
operations to see how the DMA registers are affected. I
|
||||
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
|
||||
hardware moves through. */
|
||||
|
||||
} 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);
|
||||
@@ -1228,11 +1228,11 @@ int devpnc (int class, int func, int device) {
|
||||
|
||||
} else if (func == 014) { /* initiate recv, dma chan in A */
|
||||
if (!(pncstat & PNCNSCONNECTED)) {
|
||||
break; /* yes, return and don't skip */
|
||||
break; /* yes, return and don't skip */
|
||||
}
|
||||
if (rcvstat & PNCRSBUSY) { /* already busy? */
|
||||
warn("pnc: recv when already busy ignored");
|
||||
break; /* yes, return and don't skip */
|
||||
warn("pnc: recv when already busy ignored");
|
||||
break; /* yes, return and don't skip */
|
||||
}
|
||||
IOSKIP;
|
||||
rcvstat = PNCRSBUSY; /* set receive busy */
|
||||
@@ -1241,11 +1241,11 @@ int devpnc (int class, int func, int device) {
|
||||
|
||||
} else if (func == 015) { /* initiate xmit, dma chan in A */
|
||||
if (!(pncstat & PNCNSCONNECTED)) {
|
||||
break; /* yes, return and don't skip */
|
||||
break; /* yes, return and don't skip */
|
||||
}
|
||||
if (xmitstat & PNCXSBUSY) { /* already busy? */
|
||||
warn("pnc: xmit when already busy ignored");
|
||||
break; /* yes, return and don't skip */
|
||||
warn("pnc: xmit when already busy ignored");
|
||||
break; /* yes, return and don't skip */
|
||||
}
|
||||
IOSKIP;
|
||||
pncxmit();
|
||||
@@ -1259,12 +1259,12 @@ int devpnc (int class, int func, int device) {
|
||||
} else if (func == 017) { /* set my node ID */
|
||||
myid = getcrs16(A) & 0xFF;
|
||||
if (myid > MAXNODEID) {
|
||||
printf("em: my nodeid %d > max nodeid %d; check Primenet config\n", myid, MAXNODEID);
|
||||
myid = 0;
|
||||
printf("em: my nodeid %d > max nodeid %d; check Primenet config\n", myid, MAXNODEID);
|
||||
myid = 0;
|
||||
}
|
||||
if (myid != 0 && ni[myid].cstate == PNCCSNONE) {
|
||||
printf("em: my nodeid %d not in ring.cfg; PNC disabled\n", myid);
|
||||
myid = 0;
|
||||
printf("em: my nodeid %d not in ring.cfg; PNC disabled\n", myid);
|
||||
myid = 0;
|
||||
}
|
||||
pncstat = (pncstat & 0xFF00) | myid;
|
||||
ni[myid].cstate = PNCCSAUTH;
|
||||
@@ -1303,10 +1303,10 @@ rcvexit:
|
||||
intrexit:
|
||||
if (enabled && ((pncstat & 0xC000) | intstat) != intstat) {
|
||||
if (gv.intvec == -1) {
|
||||
gv.intvec = pncvec;
|
||||
intstat |= (pncstat & 0xC000);
|
||||
gv.intvec = pncvec;
|
||||
intstat |= (pncstat & 0xC000);
|
||||
} else
|
||||
devpoll[device] = 100;
|
||||
devpoll[device] = 100;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
28
ea32i.h
28
ea32i.h
@@ -26,33 +26,33 @@ static inline ea_t ea32i (ea_t earp, unsigned short inst, unsigned int *immu32,
|
||||
d = iget16(RP);
|
||||
RPL++;
|
||||
if (sr == 0) /* imm type 1 */
|
||||
*immu32 = d << 16;
|
||||
*immu32 = d << 16;
|
||||
else /* imm type 2 */
|
||||
*(int *)immu32 = *(short *)&d;
|
||||
*(int *)immu32 = *(short *)&d;
|
||||
return IMM_EA;
|
||||
|
||||
case 2:
|
||||
switch (sr) {
|
||||
case 0: /* imm type 3 */
|
||||
d = iget16(RP);
|
||||
INCRP;
|
||||
*immu64 = (((long long)(d & 0xFF00)) << 48) | (d & 0xFF);
|
||||
return IMM_EA;
|
||||
d = iget16(RP);
|
||||
INCRP;
|
||||
*immu64 = (((long long)(d & 0xFF00)) << 48) | (d & 0xFF);
|
||||
return IMM_EA;
|
||||
case 1: /* FAC0 source */
|
||||
*immu64 = getgr64(FAC0);
|
||||
return IMM_EA;
|
||||
*immu64 = getgr64(FAC0);
|
||||
return IMM_EA;
|
||||
case 3: /* FAC1 source */
|
||||
*immu64 = getgr64(FAC1);
|
||||
return IMM_EA;
|
||||
*immu64 = getgr64(FAC1);
|
||||
return IMM_EA;
|
||||
case 2:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
fault(UIIFAULT, RPL, RP);
|
||||
fatal("ea32i: return from UII fault!");
|
||||
fault(UIIFAULT, RPL, RP);
|
||||
fatal("ea32i: return from UII fault!");
|
||||
default:
|
||||
fatal("ea32i: sr < 0 or > 7?");
|
||||
fatal("ea32i: sr < 0 or > 7?");
|
||||
}
|
||||
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);
|
||||
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)
|
||||
fault(POINTERFAULT, ea>>16, ea);
|
||||
fault(POINTERFAULT, ea>>16, ea);
|
||||
return ea | ring;
|
||||
|
||||
default:
|
||||
|
||||
32
ea64v.h
32
ea64v.h
@@ -55,18 +55,18 @@ static inline ea_t ea64v (unsigned short inst, ea_t earp) {
|
||||
|
||||
if (xok)
|
||||
if (ixy == 2 || ixy == 6)
|
||||
ea_w += getcrs16(X);
|
||||
ea_w += getcrs16(X);
|
||||
else if (ixy == 1 || ixy == 4)
|
||||
ea_w += getcrs16(Y);
|
||||
ea_w += getcrs16(Y);
|
||||
|
||||
#if 0
|
||||
/* if this is a PB% address, use RPBR instead if it's in range
|
||||
|
||||
NOTE: this has been disabled, because gcov showed it only
|
||||
occurred 0.5% of the time */
|
||||
NOTE: this has been disabled, because gcov showed it only
|
||||
occurred 0.5% of the time */
|
||||
|
||||
if (br == 0 && ((((ea_s & 0x8FFF) << 16) | (ea_w & 0xFC00)) == gv.brp[RPBR].vpn))
|
||||
eap = &gv.brp[RPBR];
|
||||
eap = &gv.brp[RPBR];
|
||||
#endif
|
||||
|
||||
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);
|
||||
m = get16(ea);
|
||||
if (m & 0x8000)
|
||||
fault(POINTERFAULT, m, ea);
|
||||
fault(POINTERFAULT, m, ea);
|
||||
ea_s = m | (ea_s & RINGMASK16);
|
||||
ea_w = get16(INCVA(ea,1));
|
||||
TRACE(T_EAV, " After indirect, ea_s=%o, ea_w=%o\n", ea_s, ea_w);
|
||||
|
||||
/* when passing stack variables, callee references will be
|
||||
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 */
|
||||
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 */
|
||||
|
||||
if ((((ea_s & 0x8FFF) << 16) | (ea_w & 0xFC00)) != (eap->vpn & 0x0FFFFFFF))
|
||||
eap = &gv.brp[UNBR];
|
||||
eap = &gv.brp[UNBR];
|
||||
|
||||
if (xok)
|
||||
if (ixy == 7) {
|
||||
TRACE(T_EAV, " Postindex, old ea_w=%o, X='%o/%d\n", ea_w, getcrs16(X), getcrs16s(X));
|
||||
ea_w += getcrs16(X);
|
||||
} else if (ixy == 5) {
|
||||
TRACE(T_EAV, " Postindex, old ea_w=%o, Y='%o/%d\n", ea_w, getcrs16(Y), getcrs16s(Y));
|
||||
ea_w += getcrs16(Y);
|
||||
}
|
||||
if (ixy == 7) {
|
||||
TRACE(T_EAV, " Postindex, old ea_w=%o, X='%o/%d\n", ea_w, getcrs16(X), getcrs16s(X));
|
||||
ea_w += getcrs16(X);
|
||||
} else if (ixy == 5) {
|
||||
TRACE(T_EAV, " Postindex, old ea_w=%o, Y='%o/%d\n", ea_w, getcrs16(Y), getcrs16s(Y));
|
||||
ea_w += getcrs16(Y);
|
||||
}
|
||||
}
|
||||
return MAKEVA(ea_s, ea_w);
|
||||
}
|
||||
|
||||
21
em.1
21
em.1
@@ -2,7 +2,7 @@
|
||||
.\" em.1, Boone, 03/13/20
|
||||
.\" Man page for Jim Wilcoxson's Prime 50-Series emulator
|
||||
.\" ---------------------------------------------------------------------------
|
||||
.TH em 1 "2020-03-14" "Jim Wilcoxson" "50-Series Emulator"
|
||||
.TH em 1 "2020-06-23" "Jim Wilcoxson" "50-Series Emulator"
|
||||
.\" ---------------------------------------------------------------------------
|
||||
.SH NAME
|
||||
em \- Emulator for Prime 50-Series systems
|
||||
@@ -35,6 +35,8 @@ a tape controller, 4 drives, using the .TAP format
|
||||
.IP \(bu
|
||||
a PNC controller emulating RingNet over TCP/IP
|
||||
.IP \(bu
|
||||
two sync serial controllers supporting up to 8 lines
|
||||
.IP \(bu
|
||||
a bypass for Primos system serial number checks
|
||||
.IP \(bu
|
||||
Unix utilities to read/write physical tapes & Magsav tapes
|
||||
@@ -163,6 +165,16 @@ Example:
|
||||
8 192.168.10.4:9000 # Outbound socket connection e.g. for spooler
|
||||
.EE
|
||||
.TP
|
||||
smlc.cfg
|
||||
Used to associate sync serial (MDLC or HSSMLC) lines with a destination
|
||||
IP address and port number. Optional. Comments work the same as
|
||||
amlc.cfg. Example:
|
||||
|
||||
.EX
|
||||
0 10.1.1.3:2554
|
||||
1 127.0.0.1:2554
|
||||
.EE
|
||||
.TP
|
||||
console.log
|
||||
All console output is also written to this file. It is overwritten
|
||||
at each invocation. Created by
|
||||
@@ -275,8 +287,10 @@ all|Everything
|
||||
flush|Flush trace file after each write
|
||||
tlb|STLB and IOTLB changes
|
||||
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
|
||||
|(may interact poorly with "off")
|
||||
process number|Execution of this user number
|
||||
.TE
|
||||
.\" ---------------------------------------------------------------------------
|
||||
@@ -360,7 +374,8 @@ CMD,1/3/5+1,Cartridge Module 32/64/96 MB
|
||||
.\" ---------------------------------------------------------------------------
|
||||
.SH AUTHOR
|
||||
.PP
|
||||
This emulator was written by Jim Wilcoxson. Man page by Dennis Boone.
|
||||
This emulator was written by Jim Wilcoxson. MDLC/HSSMLC support by
|
||||
Kevin Jordan. Man page by Dennis Boone.
|
||||
.\" ---------------------------------------------------------------------------
|
||||
.SH SEE ALSO
|
||||
This project is hosted at
|
||||
|
||||
40
fp.h
40
fp.h
@@ -70,7 +70,7 @@ int prieee8(unsigned long long dp, double *d) {
|
||||
if (frac64 == 0x8000000000000000LL) {
|
||||
exp32 += (1023-128);
|
||||
if (exp32 < 0 || exp32 > 0x7fe)
|
||||
return 0;
|
||||
return 0;
|
||||
frac64 |= ((long long)exp32 << 52);
|
||||
*d = *(double *)&frac64;
|
||||
return 1;
|
||||
@@ -142,11 +142,11 @@ retry:
|
||||
okay = 0;
|
||||
if (frac64 == 0)
|
||||
if (neg) {
|
||||
printf("em: +infinity in ieeepr8\n");
|
||||
d = DBL_MAX;
|
||||
printf("em: +infinity in ieeepr8\n");
|
||||
d = DBL_MAX;
|
||||
} else {
|
||||
printf("em: -infinity in ieeepr8\n");
|
||||
d = DBL_MIN;
|
||||
printf("em: -infinity in ieeepr8\n");
|
||||
d = DBL_MIN;
|
||||
}
|
||||
else {
|
||||
printf("em: NaN in ieeepr8\n");
|
||||
@@ -267,8 +267,8 @@ unsigned long long dfcm (unsigned long long dp, int *oflow) {
|
||||
} else {
|
||||
frac64 = -frac64; /* complement fraction */
|
||||
while ((frac64 ^ (frac64 << 1)) >= 0) {
|
||||
frac64 = frac64 << 1; /* normalize */
|
||||
exp32--;
|
||||
frac64 = frac64 << 1; /* normalize */
|
||||
exp32--;
|
||||
}
|
||||
}
|
||||
if (exp32 > 32767 || exp32 < -32768)
|
||||
@@ -322,10 +322,10 @@ unsigned long long frn(unsigned long long dp, int *oflow) {
|
||||
if (doround1 || doround2) {
|
||||
frac64 &= 0xFFFFFF0000000000LL;
|
||||
if (frac64 != 0x7FFFFF0000000000LL)
|
||||
frac64 += 0x10000000000LL;
|
||||
frac64 += 0x10000000000LL;
|
||||
else {
|
||||
frac64 = 0x4000000000000000LL;
|
||||
exp32++;
|
||||
frac64 = 0x4000000000000000LL;
|
||||
exp32++;
|
||||
}
|
||||
frac64 |= (exp32 & 0xFFFF);
|
||||
frac64 = norm(frac64, oflow);
|
||||
@@ -359,13 +359,13 @@ int fcs (unsigned long long fac, int fop) {
|
||||
if ((templ & 0x80000000) == (fop & 0x80000000)) { /* compare signs */
|
||||
if (facexp == fopexp) /* compare exponents */
|
||||
if (templ == fop) { /* compare fractions */
|
||||
SETEQ;
|
||||
return 1;
|
||||
SETEQ;
|
||||
return 1;
|
||||
} else if (templ < fop) { /* compare fractions */
|
||||
SETLT; /* FAC < operand */
|
||||
return 2;
|
||||
SETLT; /* FAC < operand */
|
||||
return 2;
|
||||
} else
|
||||
return 0; /* FAC > operand */
|
||||
return 0; /* FAC > operand */
|
||||
else if (facexp < fopexp) { /* compare exponents */
|
||||
SETLT; /* FAC < operand */
|
||||
return 2;
|
||||
@@ -410,13 +410,13 @@ int dfcs (unsigned long long fac, long long fop) {
|
||||
if ((templl & 0x8000000000000000LL) == (fop & 0x8000000000000000LL)) { /* compare signs */
|
||||
if (facexp == fopexp) /* compare exponents */
|
||||
if (templl == fop) { /* compare fractions */
|
||||
SETEQ;
|
||||
return 1;
|
||||
SETEQ;
|
||||
return 1;
|
||||
} else if (templl < fop) { /* compare fractions */
|
||||
SETLT; /* FAC < operand */
|
||||
return 2;
|
||||
SETLT; /* FAC < operand */
|
||||
return 2;
|
||||
} else
|
||||
return 0; /* FAC > operand */
|
||||
return 0; /* FAC > operand */
|
||||
else if (facexp < fopexp) { /* compare exponents */
|
||||
SETLT; /* FAC < operand */
|
||||
return 2;
|
||||
|
||||
2
makefile
2
makefile
@@ -7,7 +7,7 @@ all_deps = makefile
|
||||
em_objs = em.o em
|
||||
em_deps = \
|
||||
em.c regs.h emdev.h ea64v.h ea32i.h fp.h dispatch.h geom.h \
|
||||
devpnc.h devamlc.h swap.h
|
||||
devpnc.h devamlc.h devsmlc.h swap.h
|
||||
|
||||
CFLAGS =
|
||||
# Uncomment for building on SmartOS/Solaris:
|
||||
|
||||
96
regs.h
96
regs.h
@@ -167,51 +167,51 @@ static struct {
|
||||
/* this is the number of user register sets for this cpuid */
|
||||
|
||||
static short regsets[] = { \
|
||||
2, /* 00 P400 */
|
||||
2, /* 01 P400 (> REV A U-CODE) */
|
||||
2, /* 02 RESERVED */
|
||||
2, /* 03 P350 */
|
||||
2, /* 04 P450/P550 */
|
||||
2, /* 05 P750 */
|
||||
2, /* 06 P650 */
|
||||
2, /* 07 P150/P250 */
|
||||
2, /* 08 P850 */
|
||||
2, /* 09 MOLE/550 */
|
||||
2, /* 10 MOLE/650 */
|
||||
2, /* 11 P2250 */
|
||||
2, /* 12 P750Y */
|
||||
2, /* 13 P550Y */
|
||||
2, /* 14 P850Y */
|
||||
4, /* 15 P9950 */
|
||||
8, /* 16 P9650 */
|
||||
8, /* 17 P2550 */
|
||||
4, /* 18 P9955 */
|
||||
4, /* 19 P9750 */
|
||||
2, /* 20 TBD */
|
||||
8, /* 21 P2350 */
|
||||
8, /* 22 P2655 */
|
||||
8, /* 23 P9655 */
|
||||
4, /* 24 P9955-TIGGER */
|
||||
8, /* 25 P2450 */
|
||||
4, /* 26 P4050 */
|
||||
4, /* 27 P4150 */
|
||||
4, /* 28 P6350 */
|
||||
4, /* 29 P6550 */
|
||||
4, /* 30 P9955-II */
|
||||
8, /* 31 P2755 */
|
||||
8, /* 32 P2455 */
|
||||
4, /* 33 P5310 */
|
||||
4, /* 34 P9755 */
|
||||
4, /* 35 P2850 */
|
||||
4, /* 36 P2950 */
|
||||
4, /* 37 P5330 */
|
||||
4, /* 38 P4450 */
|
||||
4, /* 39 P5370 */
|
||||
4, /* 40 P6650 */
|
||||
4, /* 41 P6450 */
|
||||
4, /* 42 P6150 */
|
||||
4, /* 43 P5320 */
|
||||
4}; /* 44 P5340 */
|
||||
2, /* 00 P400 */
|
||||
2, /* 01 P400 (> REV A U-CODE) */
|
||||
2, /* 02 RESERVED */
|
||||
2, /* 03 P350 */
|
||||
2, /* 04 P450/P550 */
|
||||
2, /* 05 P750 */
|
||||
2, /* 06 P650 */
|
||||
2, /* 07 P150/P250 */
|
||||
2, /* 08 P850 */
|
||||
2, /* 09 MOLE/550 */
|
||||
2, /* 10 MOLE/650 */
|
||||
2, /* 11 P2250 */
|
||||
2, /* 12 P750Y */
|
||||
2, /* 13 P550Y */
|
||||
2, /* 14 P850Y */
|
||||
4, /* 15 P9950 */
|
||||
8, /* 16 P9650 */
|
||||
8, /* 17 P2550 */
|
||||
4, /* 18 P9955 */
|
||||
4, /* 19 P9750 */
|
||||
2, /* 20 TBD */
|
||||
8, /* 21 P2350 */
|
||||
8, /* 22 P2655 */
|
||||
8, /* 23 P9655 */
|
||||
4, /* 24 P9955-TIGGER */
|
||||
8, /* 25 P2450 */
|
||||
4, /* 26 P4050 */
|
||||
4, /* 27 P4150 */
|
||||
4, /* 28 P6350 */
|
||||
4, /* 29 P6550 */
|
||||
4, /* 30 P9955-II */
|
||||
8, /* 31 P2755 */
|
||||
8, /* 32 P2455 */
|
||||
4, /* 33 P5310 */
|
||||
4, /* 34 P9755 */
|
||||
4, /* 35 P2850 */
|
||||
4, /* 36 P2950 */
|
||||
4, /* 37 P5330 */
|
||||
4, /* 38 P4450 */
|
||||
4, /* 39 P5370 */
|
||||
4, /* 40 P6650 */
|
||||
4, /* 41 P6450 */
|
||||
4, /* 42 P6150 */
|
||||
4, /* 43 P5320 */
|
||||
4}; /* 44 P5340 */
|
||||
|
||||
static union {
|
||||
int rs[REGSETS][32];
|
||||
@@ -330,7 +330,7 @@ static inline void putcrs32(int offset, uint32_t val) { \
|
||||
/* get 64-bit signed at 16-bit offset */
|
||||
//#define getcrs64s(offset) *(long long *)(crs+(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 */
|
||||
@@ -342,7 +342,7 @@ static inline void putcrs64s(int offset, int64_t val) { \
|
||||
/* put 64-bit double at 16-bit offset (remove later) */
|
||||
//#define putcrs64d(offset, val) *(double *)(crs+(offset)) = (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 */
|
||||
@@ -446,7 +446,7 @@ static inline void putfr64(int offset, unsigned long long val) { \
|
||||
For FP 0, offset=0; for FP 1, offset=2 */
|
||||
//#define putfr64d(offset, val) *(double *)(crsl+FAC0+offset) = (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
|
||||
|
||||
35
util/cmraw.c
Normal file
35
util/cmraw.c
Normal file
@@ -0,0 +1,35 @@
|
||||
/* 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);
|
||||
}
|
||||
Reference in New Issue
Block a user