1
0
mirror of https://github.com/prirun/p50em.git synced 2026-03-13 21:39:36 +00:00

1 Commits

Author SHA1 Message Date
Dennis Boone
7059340ad4 Support for booting DOS pre-Rev20
PRIMOS2 was built to be relocated after being loaded by BOOT.
The build process rewrote the RVEC in the save file.  The SA was anded
with :160000; the result was subtracted from SA and EA in the RVEC,
and stored into RA in the RVEC.  The BOOT program knew to add the RA
value during the load process.

This change causes the emulator to recognize such an RVEC when booting
an R-mode executable from unix disk, and to adjust the RVEC before
actually loading the program.  This fixes failure to boot *DOS64 from
19.2.9, for example.

The code only makes this adjustment if RA is non-zero, and RP is not
between SA and EA.
2020-05-26 23:42:13 -04:00
14 changed files with 2249 additions and 3705 deletions

1
.gitignore vendored
View File

@@ -3,7 +3,6 @@
*.log
*.swp
tags
cmraw
cscope.*
em
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
repository.
Github discussions are now enabled for this repository, and can be
used to ask for help.
## Public Systems
There are a set of emulators available for public use. These may be

1334
devamlc.h

File diff suppressed because it is too large Load Diff

216
devpnc.h
View File

@@ -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;

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);
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
View File

@@ -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);
}

33
em.1
View File

@@ -2,7 +2,7 @@
.\" em.1, Boone, 03/13/20
.\" 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
em \- Emulator for Prime 50-Series systems
@@ -35,8 +35,6 @@ 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
@@ -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
.I off
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
.TP
@@ -174,18 +163,6 @@ Example:
8 192.168.10.4:9000 # Outbound socket connection e.g. for spooler
.EE
.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
All console output is also written to this file. It is overwritten
at each invocation. Created by
@@ -297,12 +274,9 @@ off|Start with tracing disabled
all|Everything
flush|Flush trace file after each write
tlb|STLB and IOTLB changes
smlc|MDLC/HSSMLC device I/O
OWNERL|Execution of this PCB
#instruction count|Begin after specified number of instructions
|(the leading # is literal)
instruction count|Begin after specified number of instructions
octal segno|Execution in the given segment number
|(may interact poorly with "off")
process number|Execution of this user number
.TE
.\" ---------------------------------------------------------------------------
@@ -386,8 +360,7 @@ CMD,1/3/5+1,Cartridge Module 32/64/96 MB
.\" ---------------------------------------------------------------------------
.SH AUTHOR
.PP
This emulator was written by Jim Wilcoxson. MDLC/HSSMLC support by
Kevin Jordan. Man page by Dennis Boone.
This emulator was written by Jim Wilcoxson. Man page by Dennis Boone.
.\" ---------------------------------------------------------------------------
.SH SEE ALSO
This project is hosted at

1552
em.c

File diff suppressed because it is too large Load Diff

1290
emdev.h

File diff suppressed because it is too large Load Diff

40
fp.h
View File

@@ -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;

View File

@@ -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 devsmlc.h swap.h
devpnc.h devamlc.h swap.h
CFLAGS =
# Uncomment for building on SmartOS/Solaris:

96
regs.h
View File

@@ -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

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);
}