1
0
mirror of https://github.com/prirun/p50em.git synced 2026-03-28 10:32:45 +00:00

Linux cleanup to remove demo/dongle code, remove PowerPC stuff, fix slow PNC I/O, fix a nasty devmt bug

This commit is contained in:
Jim
2020-02-24 23:55:03 -05:00
parent 4061b6adc9
commit a4cc429fad
11 changed files with 148 additions and 544 deletions

View File

@@ -172,15 +172,9 @@ AMLC status word (from AMLCT5):
int devamlc (int class, int func, int device) {
#ifdef DEMO
#define AMLCLINESPERBOARD 1
#define MAXLINES 2
#define MAXBOARDS 1
#else
#define AMLCLINESPERBOARD 16
#define MAXLINES 128
#define MAXBOARDS 8
#endif
#define AMLCLINESPERBOARD 16
#define MAXLINES 128
#define MAXBOARDS 8
/* check for 1 new connection every .1 seconds */
@@ -298,7 +292,6 @@ int devamlc (int class, int func, int device) {
switch (device) {
case 054: dx = 0; break;
#ifndef DEMO
case 053: dx = 1; break;
case 052: dx = 2; break;
case 035: dx = 3; break;
@@ -306,7 +299,6 @@ int devamlc (int class, int func, int device) {
case 016: dx = 5; break;
case 017: dx = 6; break;
case 032: dx = 7; break;
#endif
default:
fprintf(stderr, "devamlc: non-AMLC device id '%o ignored\n", device);
return -1;
@@ -562,10 +554,10 @@ int devamlc (int class, int func, int device) {
#define TIOCM_CD 0x0100
if (func == 00) { /* input Data Set Sense (carrier) */
#ifdef __APPLE__
if (dc[dx].serial) { /* any serial connections? */
if (--dc[dx].dsstime == 0) {
dc[dx].dsstime = DSSCOUNTDOWN;
#ifdef __APPLE__
for (lx = 0; lx < 16; lx++) { /* yes, poll them */
if (dc[dx].ctype[lx] == CT_SERIAL) {
int modemstate;
@@ -581,12 +573,12 @@ int devamlc (int class, int func, int device) {
}
}
}
#endif
}
}
//printf("devamlc: dss for device '%o = 0x%x\n", device, dc[dx].dss);
putcrs16(A, ~dc[dx].dss); /* to the outside world, 1 = no carrier */
IOSKIP;
#endif
} else if (func == 07) { /* input AMLC status */
dc[dx].interrupting = 0;
putcrs16(A, 040000 | (dc[dx].bufnum<<8) | (dc[dx].intenable<<5) | (1<<4));
@@ -972,7 +964,7 @@ int devamlc (int class, int func, int device) {
for (lx = 0; lx < 16; lx++) {
if (dc[dx].xmitenabled & BITMASK16(lx+1)) {
int n, maxn;
unsigned short qtop, qbot, qtemp,qseg, qmask, qents;
unsigned short qtop, qbot, qseg, qmask, qents;
ea_t qentea, qcbea;
n = 0;
qcbea = dc[dx].baseaddr + lx*4;

View File

@@ -259,11 +259,7 @@
#define MAXPNCBYTES MAXPNCWORDS*2 /* same in bytes */
#define MAXPKTBYTES (MAXPNCBYTES+4) /* adds 16-bit length word to each end */
#ifdef DEMOXXX
#define MAXNODEID 3 /* 0 is a dummy, 255 is broadcast */
#else
#define MAXNODEID 254 /* 0 is a dummy, 255 is broadcast */
#endif
#define MAXNODEID 254 /* 0 is a dummy, 255 is broadcast */
#define MAXHOSTLEN 64 /* max length of remote host name */
#define MAXUIDLEN 16 /* max length of unique id/password */
@@ -390,42 +386,39 @@ unsigned short pncdisc(nodeid) {
/* initialize a socket fd for PNC emulation */
pncinitfd(int fd) {
void pncinitfd(int fd) {
int optval, fdflags;
if ((fdflags = fcntl(fd, F_GETFL, 0)) == -1) {
perror("unable to get ts flags for PNC");
fatal(NULL);
}
#ifdef __APPLE__
optval = MAXPKTBYTES;
if (setsockopt(fd, SOL_SOCKET, SO_SNDLOWAT, &optval, sizeof(optval))) {
perror("setsockopt 2 failed for PNC");
fatal(NULL);
}
#ifdef __APPLE__
if (setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval))) {
perror("setsockopt 3 failed for PNC");
fatal(NULL);
}
#endif
#ifndef NOREGS
fdflags |= O_NONBLOCK;
#else
fdflags |= O_NONBLOCK+O_ASYNC;
#endif
if (fcntl(fd, F_SETFL, fdflags) == -1) {
perror("unable to set fdflags for PNC");
fatal(NULL);
}
if (fcntl(fd, F_SETOWN, getpid()) == -1) {
perror("unable to SETOWN for PNC");
fatal(NULL);
}
if ((fdflags = fcntl(fd, F_GETFL, 0)) == -1) {
perror("unable to get ts flags for PNC");
fatal(NULL);
}
fdflags |= O_NONBLOCK+O_ASYNC;
if (fcntl(fd, F_SETFL, fdflags) == -1) {
perror("unable to set fdflags for PNC");
fatal(NULL);
}
}
/* process a new incoming connection */
/* process a new incoming connection. This may require multiple calls
to pncaccept, hence the static variables for the accept state */
pncaccept(time_t timenow) {
void pncaccept(time_t timenow) {
static time_t accepttime = 0;
static int fd = -1;
static struct sockaddr_in addr;
@@ -499,6 +492,7 @@ pncaccept(time_t timenow) {
ni[i].cstate = PNCCSAUTH;
ni[i].rcvlen = 0;
ni[i].fd = fd;
pncinitfd(fd);
fd = -1;
return;
@@ -509,10 +503,9 @@ disc:
/* connect to a node, without blocking */
unsigned short pncconn1(nodeid, timenow) {
void pncconn1(nodeid, timenow) {
struct hostent* server;
struct sockaddr_in addr;
unsigned int addrlen;
int fd;
TRACE(T_RIO, "try connect to node %d\n", nodeid);
@@ -543,7 +536,7 @@ unsigned short pncconn1(nodeid, timenow) {
/* send authorization uid / password after a connect */
pncauth1(int nodeid, time_t timenow) {
void pncauth1(int nodeid, time_t timenow) {
int n;
n = write(ni[nodeid].fd, ni[myid].uid, MAXUIDLEN);
@@ -575,7 +568,7 @@ pncauth1(int nodeid, time_t timenow) {
MAXACCEPTTIME seconds. It's fine for the 5-6 node case though.
*/
pncconnect(time_t timenow) {
void pncconnect(time_t timenow) {
static int prevnode=MAXNODEID;
int nodeid;
@@ -603,7 +596,7 @@ pncconnect(time_t timenow) {
/* initialize a dma transfer */
pncinitdma(t_dma *iob, char *iotype) {
void pncinitdma(t_dma *iob, char *iotype) {
if (getcrs16(A) > 037)
fatal("PNC doesn't support chaining, DMC, or DMA reg > 037");
(*iob).dmachan = getcrs16(A);
@@ -677,7 +670,7 @@ unsigned short pncxmit(t_dma *iob) {
1 connection has a complete packet, then return that packet to the
Prime */
pncrecv() {
void pncrecv() {
static int prevnode=MAXNODEID;
static struct timeval timeout = {0, 0};
int nodeid, n, fd;
@@ -702,13 +695,13 @@ pncrecv() {
n = select(n+1, &fds, NULL, NULL, &timeout);
if (n == -1) {
if (errno == EINTR || errno == EAGAIN)
return 0;
return;
perror("unable to do read select on PNC fds");
fatal(NULL);
}
if (n == 0) {
TRACE(T_RIO, " pncrecv: no data\n");
return 0;
return;
}
nodeid = prevnode;
@@ -729,7 +722,7 @@ pncrecv() {
2. got the length, but have more to read
*/
pncrecv1(int nodeid) {
int pncrecv1(int nodeid) {
int pktlen, nw;
TRACE(T_RIO, " pncrecv1: read node %d\n", nodeid);
@@ -775,7 +768,7 @@ pncrecv1(int nodeid) {
/* read nbytes from a connection, return true if that many were read */
pncread (int nodeid, int nbytes) {
int pncread (int nodeid, int nbytes) {
int n;
n = read(ni[nodeid].fd, ni[nodeid].rcvpkt+ni[nodeid].rcvlen, nbytes);
@@ -800,8 +793,7 @@ int devpnc (int class, int func, int device) {
unsigned short dmaword;
time_t timenow;
struct sockaddr_in addr;
unsigned int addrlen;
int fd, optval, fdflags;
int optval;
struct timeval tv0,tv1;
double pollts;
@@ -820,9 +812,9 @@ int devpnc (int class, int func, int device) {
case -1: {
FILE *ringfile;
char *tok, buf[128], *p;
int n, linenum;
int tempid, tempport, cfgerrs;
char buf[128], *p;
int linenum;
int tempid, tempport;
char temphost[MAXHOSTLEN+1];
#define DELIM " \t\n"
@@ -945,16 +937,6 @@ int devpnc (int class, int func, int device) {
fatal(NULL);
}
fclose(ringfile);
#ifdef DEMOXXX
i = 0;
for (tempid=1; tempid<=MAXNODEID; tempid++)
if (ni[tempid].cstate != PNCCSNONE)
if (i == 0 && (strcasecmp(ni[tempid].host, "prirun.dyndns.org.") == 0) ||
(i == 1 && (strcasecmp(ni[tempid].host, "127.0.0.1") == 0)))
i += 1;
else
configured = 0;
#endif
} else
perror("error opening ring.cfg");
@@ -963,6 +945,13 @@ int devpnc (int class, int func, int device) {
return -1;
}
/* set async I/O signal handler */
if (signal(SIGIO, pnchavedata) == SIG_ERR) {
perror("installing SIGIO handler");
fatal(NULL);
}
/* start listening on the network port */
pncfd = socket(AF_INET, SOCK_STREAM, 0);
@@ -985,25 +974,17 @@ int devpnc (int class, int func, int device) {
addr.sin_family = AF_INET;
addr.sin_port = htons(nport);
addr.sin_addr.s_addr = INADDR_ANY;
if(bind(pncfd, (struct sockaddr *)&addr, sizeof(addr))) {
if (bind(pncfd, (struct sockaddr *)&addr, sizeof(addr))) {
perror("bind: unable to bind for PNC");
fatal(NULL);
}
if(listen(pncfd, 10)) {
if (listen(pncfd, 10)) {
perror("listen failed for PNC");
fatal(NULL);
}
TRACE(T_RIO, "PNC configured\n");
devpoll[device] = PNCPOLL*gvp->instpermsec;
/* can't use signals with NOREGS, so PNC I/O is very slow */
#ifdef NOREGS
if (signal(SIGIO, pnchavedata) == SIG_ERR) {
perror("installing SIGIO handler");
fatal(NULL);
}
#endif
if (gettimeofday(&tv0, NULL) != 0)
fatal("pnc gettimeofday 1 failed");
tv0ts = tv0.tv_sec + tv0.tv_usec/1000000.0;

View File

@@ -4,7 +4,6 @@ static inline ea_t ea32i (ea_t earp, unsigned short inst, unsigned int *immu32,
int tm, sr, br, ring;
unsigned short d;
int temp32;
ea_t ea, ip;
*immu32 = 0xAAAAAAAA;

View File

@@ -5,7 +5,6 @@ static inline ea_t ea64v (unsigned short inst, ea_t earp) {
ea_t ea; /* full seg/word va */
unsigned short ea_s; /* eff address segno */
unsigned short ea_r; /* eff address ring */
unsigned short ea_w; /* eff address wordno */
unsigned short br;
unsigned short i;

297
em.c
View File

@@ -1,5 +1,5 @@
/* Pr1me Computer emulator, Jim Wilcoxson (prirun@gmail.com), April 4, 2005
Copyright (C) 2005-2007, Jim Wilcoxson. All Rights Reserved.
Copyright (C) 2005-2019, Jim Wilcoxson. All Rights Reserved.
Emulates a Prime Computer system by:
- booting from a Prime disk image (normal usage)
@@ -320,23 +320,6 @@ static void macheck (unsigned short p300vec, unsigned short chkvec, unsigned int
#define BITMASK16(b) (0x8000 >> ((b)-1))
#define BITMASK32(b) ((unsigned int)(0x80000000) >> ((b)-1))
/* license data structure. Part is read from file "license" file:
- field 1: license id
- field 2: license server Internet name
- field 3: license server port (TCP)
*/
typedef struct {
int id;
char server[65];
int sport;
int sockfd;
struct hostent *rserver;
} license_t;
license_t license;
static int mypid;
#ifdef NOTRACE
#define TRACE(flags, formatargs...)
#define TRACEA(formatargs...)
@@ -583,19 +566,12 @@ typedef struct {
static gv_t gv;
#ifndef NOREGS
register gv_t *gvp asm ("r28");
register brp_t *eap asm ("r27"); /* effective address brp pointer */
#else
gv_t *gvp;
brp_t *eap;
#endif
static jmp_buf jmpbuf; /* for longjumps to the fetch loop */
static jmp_buf bootjmp; /* for longjumps to the fetch loop */
static unsigned long bootuid;
/* The standard Prime physical memory limit on early machines is 8MB.
Later machines have higher memory capacities, up to 1024MB, using
32-bit page tables.
@@ -740,67 +716,6 @@ char *brp_name() {
#include "stopwatch.h"
/* reads and parses the license file and sets the license global
variable structure. The license file is not used in the hobby
version. This routine also does the name->IP DNS lookup so that
errors can be detected early.
The first arg is non-zero for startup, meaning to print messages and
exit. If zero, no messages are printed and the return code is set.
Returns 1 if everything is okay, 0 if not (or exits if first is non-zero).
*/
int readlicense(int first) {
struct sockaddr_in raddr;
int raddrlen;
license_t newlicense;
FILE *licensefile;
char line[100];
newlicense.id = 0;
newlicense.server[0] = 0;
newlicense.sport = 0;
newlicense.sockfd = -1;
newlicense.rserver = NULL;
if (first)
license = newlicense;
#ifndef DEMO
if ((licensefile = fopen("license", "r")) == NULL) {
printf("em: no license file.\n");
return 0;
}
if (fgets(line, sizeof(line), licensefile) == NULL
|| sscanf(line, "%x %s %d", &newlicense.id, newlicense.server, &newlicense.sport) != 3) {
printf("em: unable to read license file. Format is: id server port\n");
fclose(licensefile);
return 0;
}
fclose(licensefile);
if (first)
license = newlicense;
/* lookup the license server's address */
newlicense.rserver = gethostbyname(newlicense.server);
if (newlicense.rserver == NULL) {
printf("em: can't lookup IP address for license server %s. Check license file or DNS.\n", newlicense.server);
return 0;
}
bcopy((char *)newlicense.rserver->h_addr, (char *)&raddr.sin_addr.s_addr, newlicense.rserver->h_length);
license = newlicense;
if (first)
printf("License id %08x, server %s [%s:%d]\n", license.id, license.server, (char *) inet_ntoa(raddr.sin_addr.s_addr), license.sport);
#endif
return 1;
}
/* returns an index to a symbol, based on an address and type
match; if the address isn't found exactly, the index returned
@@ -842,7 +757,7 @@ int findsym(ea_t addr, char type) {
}
addsym(char *sym, unsigned short seg, unsigned short word, char type) {
void addsym(char *sym, unsigned short seg, unsigned short word, char type) {
short symlen,ix,ix2;
ea_t addr;
@@ -862,7 +777,7 @@ addsym(char *sym, unsigned short seg, unsigned short word, char type) {
}
readloadmap(char *filename, int showerr) {
void readloadmap(char *filename, int showerr) {
FILE *mapf;
char line[100];
int lc,ix;
@@ -988,11 +903,18 @@ static pa_t mapva(ea_t ea, ea_t rp, short intacc, unsigned short *access) {
stopwatch_push(&sw_mapva);
#if 0
/* fault bit set on EA means an address trap, which should be
handled at a higher lever and never make it this far */
handled at a higher level and never make it this far
NOTE: this is commented out because if a stack frame is trashed
and stackroot gets its fault bit set, PRTN will cause this error,
halting the emulator. Without this check, an illegal segno or
access fault occurs. Thanks Dennis! */
if (ea & 0x80000000)
fatal("mapva: fault bit set on EA");
#endif
/* map virtual address if segmentation is enabled */
@@ -1118,7 +1040,7 @@ static pa_t mapva(ea_t ea, ea_t rp, short intacc, unsigned short *access) {
returned if not in mapped I/O mode), or a 2-bit segment number and
16-bit word number for mapped I/O. A physical address is returned. */
const static unsigned int mapio(ea_t ea) {
static unsigned int mapio(ea_t ea) {
int iotlbix;
ea &= 0x3FFFF;
@@ -1231,7 +1153,6 @@ static unsigned short get16trap(ea_t ea) {
}
static inline unsigned short get16t(ea_t ea) {
unsigned short access;
/* sign bit is set for live register access */
@@ -1264,7 +1185,6 @@ static unsigned short get16r(ea_t ea, ea_t rpring) {
/* get32m always uses the map and isn't inlined */
static unsigned int get32m(ea_t ea) {
pa_t pa;
unsigned short access;
#ifdef DBG
@@ -1288,8 +1208,6 @@ static unsigned int get32m(ea_t ea) {
/* get32 tries to use the cache and is inlined */
static inline unsigned int get32(ea_t ea) {
pa_t pa;
unsigned short access;
#ifdef DBG
if (ea & 0x80000000) {
@@ -1408,7 +1326,6 @@ unsigned short iget16t(ea_t ea) {
}
static inline unsigned short iget16(ea_t ea) {
unsigned short access;
if ((ea & 0x8FFFFC00) == (gvp->brp[RPBR].vpn & 0x0FFFFFFF))
return swap16(gvp->brp[RPBR].memp[ea & 0x3FF]);
@@ -1421,7 +1338,7 @@ static inline unsigned short iget16(ea_t ea) {
#define iget16t(ea) get16t((ea))
#endif
static inline put16(unsigned short value, ea_t ea) {
static inline void put16(unsigned short value, ea_t ea) {
unsigned short access;
#ifdef DBG
@@ -1456,7 +1373,7 @@ static inline put16(unsigned short value, ea_t ea) {
#endif
}
static put16r(unsigned short value, ea_t ea, ea_t rpring) {
static void put16r(unsigned short value, ea_t ea, ea_t rpring) {
unsigned short access;
#ifdef DBG
@@ -1468,15 +1385,17 @@ static put16r(unsigned short value, ea_t ea, ea_t rpring) {
/* if passed-in ring == RP ring, use put16 and maybe avoid mapva */
if (((rpring ^ RP) & RINGMASK32) == 0)
return put16(value, ea);
if (((rpring ^ RP) & RINGMASK32) == 0) {
put16(value, ea);
return;
}
put16mem(mapva(ea, rpring, WACC, &access), value);
}
/* put16trap handles stores that ARE address traps */
static put16trap(unsigned short value, ea_t ea) {
static void put16trap(unsigned short value, ea_t ea) {
ea = ea & 0xFFFF;
if (ea < 7)
@@ -1498,7 +1417,7 @@ static put16trap(unsigned short value, ea_t ea) {
/* put16t handles stores that MIGHT address trap */
static inline put16t(unsigned short value, ea_t ea) {
static inline void put16t(unsigned short value, ea_t ea) {
if (*(int *)&ea >= 0)
put16(value, ea);
@@ -1507,10 +1426,8 @@ static inline put16t(unsigned short value, ea_t ea) {
}
static put32(unsigned int value, ea_t ea) {
pa_t pa;
static void put32(unsigned int value, ea_t ea) {
unsigned short access;
unsigned short *m;
#ifdef DBG
if (ea & 0x80000000) {
@@ -1540,10 +1457,9 @@ static put32(unsigned int value, ea_t ea) {
}
}
static put32r(unsigned int value, ea_t ea, ea_t rpring) {
static void put32r(unsigned int value, ea_t ea, ea_t rpring) {
pa_t pa;
unsigned short access;
unsigned short *m;
#ifdef DBG
if (ea & 0x80000000) {
@@ -1554,8 +1470,10 @@ static put32r(unsigned int value, ea_t ea, ea_t rpring) {
/* if passed-in ring == RP ring, use put32 and maybe avoid mapva */
if (((rpring ^ RP) & RINGMASK32) == 0)
return put32(value, ea);
if (((rpring ^ RP) & RINGMASK32) == 0) {
put32(value, ea);
return;
}
pa = mapva(ea, rpring, WACC, &access);
if ((pa & 01777) <= 01776)
@@ -1566,10 +1484,9 @@ static put32r(unsigned int value, ea_t ea, ea_t rpring) {
}
}
static put64r(long long value, ea_t ea, ea_t rpring) {
static void put64r(long long value, ea_t ea, ea_t rpring) {
pa_t pa;
unsigned short access;
unsigned short *m;
/* check for live register access */
@@ -1669,7 +1586,7 @@ void macheck (unsigned short p300vec, unsigned short chkvec, unsigned int dswsta
static int rtq(ea_t qcbea, unsigned short *qent, ea_t rp) {
unsigned short qtop, qbot, qtemp;
unsigned short qtop, qbot;
unsigned short qseg, qmask;
ea_t qentea;
@@ -1723,7 +1640,7 @@ static int abq(ea_t qcbea, unsigned short qent, ea_t rp) {
static int rbq(ea_t qcbea, unsigned short *qent, ea_t rp) {
unsigned short qtop, qbot, qtemp;
unsigned short qtop, qbot;
unsigned short qseg, qmask;
ea_t qentea;
@@ -1779,29 +1696,7 @@ static int devpoll[64] = {0};
/* I/O device map table, containing function pointers to handle device I/O */
#ifdef DEMO
/* this is the "hobby system" controller configuration:
'04 = devasr: system console
'07 = devpnc: Primenet Node Controller aka PNC (Ringnet)
'14 = devmt: mag tape controller (1 drive)
'20 = devcp: clock / VCP / SOC
'26 = devdisk: 1st disk controller
'54 = devamlc: 1st AMLC (16 lines)
*/
static int (*devmap[64])(int, int, int) = {
/* '0x */ devnone,devnone,devnone,devnone,devasr,devnone,devnone,devpnc,
/* '1x */ devnone,devnone,devnone,devnone,devmt,devnone, devnone, devnone,
/* '2x */ devcp,devnone,devnone,devnone,devnone,devnone,devdisk,devnone,
/* '3x */ devnone,devnone,devnone,devnone,devnone,devnone,devnone,devnone,
/* '4x */ devnone,devnone,devnone,devnone,devnone,devnone,devnone,devnone,
/* '5x */ devnone,devnone,devnone,devnone,devamlc,devnone,devnone,devnone,
/* '6x */ devnone,devnone,devnone,devnone,devnone,devnone,devnone,devnone,
/* '7x */ devnone,devnone,devnone,devnone,devnone,devnone,devnone,devnone};
#elif 0
#if 0
/* this is the "full system" configuration supported by the emulator
@@ -1956,7 +1851,7 @@ static void fatal(char *msg) {
/* set new processor keys */
static newkeys (unsigned short new) {
static void newkeys (unsigned short new) {
switch ((new & 016000) >> 10) {
case 0: /* 16S */
@@ -2482,7 +2377,7 @@ static inline void mathexception(unsigned char extype, unsigned short fcode, ea_
#include "fp.h"
static dumpregs() {
static void dumpregs() {
int rs, i;
unsigned int val;
unsigned short v1, v2;
@@ -2501,7 +2396,7 @@ static dumpregs() {
/* XXX: doesn't handle both page map formats */
static dumpsegs() {
static void dumpsegs() {
short seg,nsegs,i,page,segno;
unsigned short pte,xxx;
unsigned int dtar,staddr,sdw,ptaddr,pmaddr;
@@ -2621,10 +2516,7 @@ static ea_t stex(unsigned int framesize) {
static inline void prtn() {
unsigned short stackroot;
ea_t newrp,newsb,newlb;
ea_t fpva;
unsigned short fpseg;
unsigned short keys;
int maxloop;
eap = &gvp->brp[SBBR];
stackroot = get16(getcrs32(SB)+1);
@@ -2742,13 +2634,12 @@ static inline ea_t pclea(unsigned short brsave[6], ea_t rp, unsigned short *bita
- LB is the caller's saved LB
*/
static argt() {
static void argt() {
unsigned short brsave[6];
unsigned short argsleft, argdisp, bit;
short lastarg, store;
unsigned int utempl;
unsigned short ecby; /* last offset where ecb temp ea was stored */
ea_t ea, stackfp, rp, ecbea;
ea_t ea, stackfp, rp;
unsigned short advancepb, advancey;
TRACE(T_PCL, "Entered ARGT\n");
@@ -2847,21 +2738,14 @@ static argt() {
}
static pcl (ea_t ecbea) {
static void pcl (ea_t ecbea) {
short i,j;
unsigned int utempl;
unsigned short access;
unsigned short ecb[9];
short bit; /* bit offset for args */
ea_t newrp; /* start of new proc */
ea_t ea;
ea_t rp; /* return pointer */
short stackrootseg, stackseg;
unsigned short framesize;
short store; /* true if store bit set on AP */
short storedargs; /* # of arguments that have been stored */
short lastarg; /* true if "last" bit seen in PCL arglist */
ea_t argp; /* where to store next arg in new frame */
ea_t stackfp; /* new stack frame pointer */
ea_t fpva; /* virtual address of the free pointer */
pa_t pa; /* physical address of ecb */
@@ -3201,7 +3085,7 @@ static void calf(ea_t ea) {
- adding "wait" arg and only saving base registers fixed Case 63
*/
static pxregsave(unsigned short wait) {
static void pxregsave(unsigned short wait) {
ea_t pcbp, regp;
int i;
unsigned short mask;
@@ -3246,9 +3130,9 @@ static pxregsave(unsigned short wait) {
NOTE: RP must be set by the caller since this happens whenever
a process is dispatched - not just when registers are loaded */
static pxregload (ea_t pcbp) {
static void pxregload (ea_t pcbp) {
ea_t regp;
unsigned short mask, modals;
unsigned short mask;
int i;
TRACE(T_PX, "pxregload loading registers for process %o/%o\n", pcbp>>16, pcbp&0xFFFF);
@@ -3275,7 +3159,7 @@ static pxregload (ea_t pcbp) {
/* selects a register set and sets modals and crs/crsl to that register set.
pcbw is OWNERL of the process that will use the register set. */
static ors(unsigned short pcbw) {
static void ors(unsigned short pcbw) {
static short regq[] = {0,1,2,3,4,5,6,7};
short i,rx;
unsigned short ownerl, currs, rs;
@@ -3360,7 +3244,7 @@ static ors(unsigned short pcbw) {
for an external interrupt.
*/
static dispatcher() {
static void dispatcher() {
ea_t pcbp, rlp;
unsigned short pcbw; /* pcb word address */
unsigned short rsnum;
@@ -3543,8 +3427,8 @@ idle:
passed in. The dispatcher should always be entered after this
routine. */
static unready (ea_t waitlist, unsigned short newlink) {
unsigned short level, bol, eol;
static void unready (ea_t waitlist, unsigned short newlink) {
unsigned short bol, eol;
unsigned int rl;
ea_t rlp, pcbp;
@@ -3600,7 +3484,7 @@ unready: I'm not first on the ready list
static unsigned short ready (ea_t pcbp, unsigned short begend) {
ea_t rlp;
ea_t xpcbp;
unsigned short bol,eol,pcbw,level,resched;
unsigned short pcbw,level,resched;
unsigned int rl;
if ((pcbp & 0xFFFF) == getcrs16(OWNERL))
@@ -3650,14 +3534,13 @@ static unsigned short ready (ea_t pcbp, unsigned short begend) {
}
static pwait() {
static void pwait() {
ea_t ea;
ea_t pcbp, prevpcbp;
unsigned int utempl;
unsigned int pcblevnext; /* pcb level and link */
unsigned short bol;
unsigned short pcblev;
unsigned short pcbnext;
unsigned short mylev;
short count;
@@ -3732,8 +3615,8 @@ owner=71600 DUMPCB, keys=14000, modals=77 */
- 001217 = INBC, notify to beg, CAI
*/
static nfy(unsigned short inst) {
unsigned short resched, begend, bol, rsnum;
static void nfy(unsigned short inst) {
unsigned short resched, begend, bol;
ea_t ea, pcbp;
unsigned int utempl;
short scount;
@@ -3793,7 +3676,7 @@ static nfy(unsigned short inst) {
}
static lpsw() {
static void lpsw() {
ea_t ea;
unsigned short m;
@@ -3865,7 +3748,7 @@ static lpsw() {
}
static sssn() {
static void sssn() {
#if 1
static char snbuf[] = "FN 123456 "; /* dummy serial number for DIAG */
#else
@@ -3948,7 +3831,7 @@ static inline unsigned short ldc(int n, unsigned short result) {
}
static inline stc(int n, unsigned short ch) {
static void inline stc(int n, unsigned short ch) {
unsigned int utempl;
unsigned short m;
unsigned int far, flr;
@@ -3991,7 +3874,7 @@ static inline stc(int n, unsigned short ch) {
/* add a bit offset, passed in "val", to field address register n */
static inline arfa(int n, int val) {
static void inline arfa(int n, int val) {
int utempl;
TRACE(T_FLOW, " before add, FAR=%o/%o, FLR=%o\n", getgr32(FAR0+2*n)>>16, getgr32(FAR0+2*n)&0xFFFF, getgr32(FLR0+2*n));
@@ -4265,7 +4148,7 @@ static int add16(unsigned short a1, unsigned short a2, unsigned short a3, ea_t e
}
static inline adlr(int dr) {
static void inline adlr(int dr) {
if (getcrs16(KEYS) & 020000)
putgr32(dr, add32(getgr32(dr), 1, 0, 0));
@@ -4276,7 +4159,7 @@ static inline adlr(int dr) {
}
static inline cgt(unsigned short n) {
static void inline cgt(unsigned short n) {
unsigned short utempa;
utempa = iget16(RP); /* get number of words */
@@ -4287,7 +4170,7 @@ static inline cgt(unsigned short n) {
}
static inline pimh(int dr) {
static void inline pimh(int dr) {
int templ, templ2;
templ = getgr32(dr);
@@ -4308,7 +4191,6 @@ static inline pimh(int dr) {
variable, based on the cpuid */
static int ldar(ea_t ea) {
unsigned short utempa;
unsigned int result;
if (ea & 040000) { /* absolute RF addressing */
@@ -4336,7 +4218,7 @@ static int ldar(ea_t ea) {
}
static star(unsigned int val32, ea_t ea) {
static void star(unsigned int val32, ea_t ea) {
if (ea & 040000) { /* absolute RF addressing */
RESTRICT();
@@ -4360,7 +4242,7 @@ static star(unsigned int val32, ea_t ea) {
word is passed in as an argument to handle EIO (Execute I/O) in
V/I modes. */
static pio(unsigned int inst) {
static void pio(unsigned int inst) {
int class;
int func;
int device;
@@ -4375,7 +4257,7 @@ static pio(unsigned int inst) {
stopwatch_pop(&sw_io);
}
main (int argc, char **argv) {
int main (int argc, char **argv) {
static short bootdiskctrl[4] = {026, 027, 022, 023};
@@ -4388,11 +4270,11 @@ main (int argc, char **argv) {
unsigned char boottaphdr[4];
short tempa,tempa1,tempa2;
unsigned short utempa,utempa1,utempa2;
unsigned short utempa;
int templ,templ1,templ2;
long long templl,templl1,templl2;
unsigned long long utempll, utempll1, utempll2;
unsigned int utempl,utempl1,utempl2,utempl3,utempl4;
unsigned long long utempll;
unsigned int utempl,utempl1,utempl2;
double tempd,tempd1,tempd2;
ea_t tempea;
ea_t ea; /* final MR effective address */
@@ -4404,20 +4286,16 @@ main (int argc, char **argv) {
unsigned short opcode, opix;
short i,j,x;
unsigned short savemask;
unsigned short class;
int nw,nw2;
unsigned short rvec[9]; /* SA, EA, P, A, B, X, keys, dummy, dummy */
unsigned short inst;
unsigned short m,m2;
unsigned short qtop,qbot,qseg,qmask,qtemp;
ea_t qea;
unsigned short m;
short scount; /* shift count */
unsigned short trapvalue;
ea_t trapaddr;
unsigned short access;
unsigned int immu32;
unsigned long long immu64;
short fcode;
unsigned short zresult, zclen1, zclen2, zaccess;
unsigned int zlen1, zlen2;
ea_t zea1, zea2;
@@ -4437,12 +4315,22 @@ main (int argc, char **argv) {
struct timezone tz;
printf("[Prime Emulator ver %s %s]\n", REV, __DATE__);
printf("[Copyright (C) 2005-2012 Prirun LLC prirun@gmail.com]\n");
printf("[Copyright (C) 2005-2019 Jim Wilcoxson prirun@gmail.com]\n");
if (argc > 1 && (strcmp(argv[1],"--version") == 0)) {
exit(0);
}
mypid = getpid();
/* don't let 2 emulators run in the same directory */
lockfd = open(".lock", O_WRONLY+O_CREAT, 0644);
if (lockfd == -1) {
fprintf(stderr, "Error opening .lock: %s\n", strerror(errno));
exit(1);
}
if (flock(lockfd, LOCK_EX+LOCK_NB) == -1) {
fprintf(stderr, "Already running\n");
exit(1);
}
/* re-open stderr as error.log */
@@ -4455,27 +4343,8 @@ main (int argc, char **argv) {
exit(1);
}
#if (!defined(DEMO) && (KEYID!=0))
lockfd = open("/tmp/em.lck", O_WRONLY+O_CREAT, 0644);
if (lockfd == -1) {
fprintf(stderr, "Error opening /tmp/em.lck: %s\n", strerror(errno));
exit(1);
}
if (flock(lockfd, LOCK_EX+LOCK_NB) == -1) {
fprintf(stderr, "Already running\n");
exit(1);
}
#endif
/* initialize global variables */
#ifndef NOREGS
if (sizeof(gv) > 16*1024) {
fprintf(stderr, "em: size of global vars = %lu\n", sizeof(gv));
fatal(NULL);
}
#endif
gvp = &gv;
gvp->physmem = physmem;
gvp->intvec = -1;
@@ -4508,10 +4377,8 @@ main (int argc, char **argv) {
/* on SIGTERM, shutdown the emulator with a Prime sensor check */
#ifdef NOREGS
signal (SIGTERM, sensorcheck);
signal (SIGQUIT, sigquit);
#endif
#ifndef NOTRACE
@@ -4577,10 +4444,6 @@ main (int argc, char **argv) {
tport = 0;
nport = 0;
/* read license file: id, server name, port; print error if it fails */
readlicense(1);
/* check args */
for (i=1; i<argc; i++) {
@@ -4948,16 +4811,6 @@ a filename, CPU registers and keys are loaded from the runfile header.\n\
fatal(NULL);
}
/* save boot file inode; this gets sent in security checks */
{
struct stat statbuf;
if ((i=fstat(bootfd, &statbuf)) == -1) {
perror("Error fstat on boot file");
fatal(NULL);
}
bootuid = statbuf.st_ino;
}
close(bootfd);
/* check we got it all */
@@ -5287,9 +5140,9 @@ xec:
#endif
#if 1
TRACE(T_FLOW, "\n #%u [%s %o] IT=%d SB: %o/%o LB: %o/%o %s XB: %o/%o\n%o/%o: %o A='%o/%u B='%o/%d L='%o/%d E='%o/%d X=%o/%d Y=%o/%d%s%s%s%s K=%o M=%o\n", gvp->instcount, searchloadmap(getcrs32(OWNER),'x'), getcrs16(OWNERL), getcrs16s(TIMERH), getcrs16(SBH), getcrs16(SBL), getcrs16(LBH), getcrs16(LBL), searchloadmap(getcrs32(LBH),'l'), getcrs16(XBH), getcrs16(XBL), RPH, RPL-1, inst, getcrs16(A), getcrs16s(A), getcrs16(B), getcrs16s(B), getcrs32(L), getcrs32s(L), getcrs32(E), getcrs32s(E), getcrs16(X), getcrs16s(X), getcrs16(Y), getcrs16s(Y), (getcrs16(KEYS)&0100000)?" C":"", (getcrs16(KEYS)&020000)?" L":"", (getcrs16(KEYS)&0200)?" LT":"", (getcrs16(KEYS)&0100)?" EQ":"", getcrs16(KEYS), getcrs16(MODALS));
TRACE(T_FLOW, "\n #%u [%s %o] IT=%d SB: %o/%o LB: %o/%o %s XB: %o/%o\n%o/%o: %o A='%o/%u B='%o/%d L='%o/%d E='%o/%d X='%o/%d Y='%o/%d%s%s%s%s K=%o M=%o\n", gvp->instcount, searchloadmap(getcrs32(OWNER),'x'), getcrs16(OWNERL), getcrs16s(TIMERH), getcrs16(SBH), getcrs16(SBL), getcrs16(LBH), getcrs16(LBL), searchloadmap(getcrs32(LBH),'l'), getcrs16(XBH), getcrs16(XBL), RPH, RPL-1, inst, getcrs16(A), getcrs16s(A), getcrs16(B), getcrs16s(B), getcrs32(L), getcrs32s(L), getcrs32(E), getcrs32s(E), getcrs16(X), getcrs16s(X), getcrs16(Y), getcrs16s(Y), (getcrs16(KEYS)&0100000)?" C":"", (getcrs16(KEYS)&020000)?" L":"", (getcrs16(KEYS)&0200)?" LT":"", (getcrs16(KEYS)&0100)?" EQ":"", getcrs16(KEYS), getcrs16(MODALS));
#else
TRACE(T_FLOW, "\n [%s %o] SB: %o/%o LB: %o/%o %s XB: %o/%o\n%o/%o: %o A='%o/%u B='%o/%d L='%o/%d E='%o/%d X=%o/%d Y=%o/%d%s%s%s%s K=%o M=%o\n", searchloadmap(getcrs32(OWNER),'x'), getcrs16(OWNERL), getcrs16(SBH), getcrs16(SBL), getcrs16(LBH), getcrs16(LBL), searchloadmap(getcrs32(LBH),'l'), getcrs16(XBH), getcrs16(XBL), RPH, RPL-1, inst, getcrs16(A), getcrs16s(A), getcrs16(B), getcrs16s(B), getcrs32(L), getcrs32s(L), getcrs32(E), getcrs32s(E), getcrs16(X), getcrs16s(X), getcrs16(Y), getcrs16s(Y), (getcrs16(KEYS)&0100000)?" C":"", (getcrs16(KEYS)&020000)?" L":"", (getcrs16(KEYS)&0200)?" LT":"", (getcrs16(KEYS)&0100)?" EQ":"", getcrs16(KEYS), getcrs16(MODALS) & 0177437);
TRACE(T_FLOW, "\n [%s %o] SB: %o/%o LB: %o/%o %s XB: %o/%o\n%o/%o: %o A='%o/%u B='%o/%d L='%o/%d E='%o/%d X='%o/%d Y='%o/%d%s%s%s%s K=%o M=%o\n", searchloadmap(getcrs32(OWNER),'x'), getcrs16(OWNERL), getcrs16(SBH), getcrs16(SBL), getcrs16(LBH), getcrs16(LBL), searchloadmap(getcrs32(LBH),'l'), getcrs16(XBH), getcrs16(XBL), RPH, RPL-1, inst, getcrs16(A), getcrs16s(A), getcrs16(B), getcrs16s(B), getcrs32(L), getcrs32s(L), getcrs32(E), getcrs32s(E), getcrs16(X), getcrs16s(X), getcrs16(Y), getcrs16s(Y), (getcrs16(KEYS)&0100000)?" C":"", (getcrs16(KEYS)&020000)?" L":"", (getcrs16(KEYS)&0200)?" LT":"", (getcrs16(KEYS)&0100)?" EQ":"", getcrs16(KEYS), getcrs16(MODALS) & 0177437);
#endif
/* begin instruction decode: generic? */

62
emdev.h
View File

@@ -1,24 +1,3 @@
/* this is to test what happens when gettimeofday is overridden. On
an idle machine, a little more than one second ticks every hour.
The dongle is still required but it does allow the emulator to run
w/o a license. However there are several bad time-related
side-effects. The worst seems to be that timeslicing doesn't work,
so a CPU-bound job more-or-less locks up the machine.
*/
#if 0
int ctr = 0;
int gettimeofday(struct timeval *tv, void *tz) {
tv->tv_sec = 0;
tv->tv_sec = 1342600000 + ctr/1000000;
tv->tv_usec = ctr % 1000000;
ctr++;
if (ctr % 1000000 == 0) printf("%d\n", ctr);
return 0;
}
#endif
/* emdev.h, Jim Wilcoxson (prirun@gmail.com), April 17, 2005
Device handlers for pio instructions. Use devnull as a template for
new handlers.
@@ -120,7 +99,6 @@ int gettimeofday(struct timeval *tv, void *tz) {
would support 4-8 physical drives, depending on the controller type.
*/
#include "secure.h"
/* this macro is used when I/O is successful. In VI modes, it sets
the EQ condition code bit. In SR modes, it does a skip */
@@ -305,7 +283,7 @@ int devasr (int class, int func, int device) {
#define MAXASRBUF 1024
static initialized = 0;
static int initialized = 0;
static FILE *conslog;
static int ttydev;
static int ttyflags;
@@ -967,13 +945,11 @@ int devmt (int class, int func, int device) {
unsigned short iobuf[MAXTAPEWORDS+4]; /* 16-bit WORDS! */
unsigned short *iobufp;
unsigned short dmxreg; /* DMA/C register address */
short dmxnch; /* number of DMX channels - 1 */
unsigned int dmxaddr;
unsigned int dmcpair;
short dmxnw, dmxtotnw;
int i,n;
char reclen[4];
unsigned short ioword;
switch (class) {
@@ -1239,6 +1215,7 @@ int devmt (int class, int func, int device) {
fatal("Tape write is too big");
for (i=0; i < dmxnw; i++) {
#if 0
unsigned short ioword;
ioword = get16io(dmxaddr+i);
if (i%10 == 0)
TRACE(T_TIO, "\n %04d: ", i);
@@ -1253,6 +1230,7 @@ int devmt (int class, int func, int device) {
dmxnw = dmxtotnw;
for (i=0; i < dmxnw; i++) {
#if 0
unsigned short ioword;
ioword = *iobufp++;
if (i%10 == 0)
TRACE(T_TIO, "\n %04d: ", i);
@@ -1266,7 +1244,7 @@ int devmt (int class, int func, int device) {
TRACE(T_TIO, " transferred %d words\n", dmxnw);
if (dmxchan & 0x0800) { /* if DMC... */
put16io(dmxaddr+dmxnw, dmxreg); /* update starting address */
} else { /* if DMA...
} else { /* if DMA... */
putar16(REGDMX16+dmxreg, getar16(REGDMX16+dmxreg) + (dmxnw<<4)); /* increment # words */
putar16(REGDMX16+dmxreg+1, getar16(REGDMX16+dmxreg+1) + dmxnw); /* increment address */
}
@@ -1416,9 +1394,9 @@ int devmt (int class, int func, int device) {
/* initclock sets Primos' real-time clock variable */
initclock(ea_t datnowea) {
void initclock(ea_t datnowea) {
short olddatnow;
int datnow, i;
int datnow;
time_t unixtime;
struct tm *tms;
@@ -1445,7 +1423,6 @@ int devcp (int class, int func, int device) {
static short clkpic = -947;
static float clkrate = 3.2;
static unsigned int ticks = -1;
static unsigned int absticks = -1;
static struct timeval start_tv;
static ea_t datnowea = 0;
static struct timeval prev_tv;
@@ -1453,7 +1430,6 @@ int devcp (int class, int func, int device) {
struct timeval tv;
unsigned int elapsedms,targetticks;
ea_t realrp;
int i;
#define SETCLKPOLL devpoll[device] = gvp->instpermsec*(-clkpic*clkrate)/1000;
@@ -1653,12 +1629,8 @@ int devcp (int class, int func, int device) {
#define IPMTIME 5000
realrp = RP;
if ((gvp->instcount < previnstcount) || (gvp->instcount-previnstcount > gvp->instpermsec*IPMTIME)) {
if (gvp->instcount-previnstcount > gvp->instpermsec*IPMTIME) {
#ifndef DEMO
RP = MAKEVA(07777, 0); /* set bad RP */
#endif
i = (gvp->instcount-previnstcount) /
((tv.tv_sec-prev_tv.tv_sec)*1000.0 + (tv.tv_usec-prev_tv.tv_usec)/1000.0);
if (i > 0) {
@@ -1668,10 +1640,6 @@ int devcp (int class, int func, int device) {
#ifdef NOIDLE
//printf("\ninstpermsec=%d\n", gvp->instpermsec);
#endif
/* call the security check code */
secure(tv, realrp);
}
previnstcount = gvp->instcount;
prev_tv = tv;
@@ -1738,8 +1706,6 @@ int globdisk (char *devfile, int size, int device, int unit) {
*/
#include "geomhash.h"
int devdisk (int class, int func, int device) {
#include "geom.h"
@@ -1785,7 +1751,7 @@ int devdisk (int class, int func, int device) {
unsigned short order;
unsigned short m,m1,m2;
short head, track, rec, recsize, nwords;
short head, track, rec, recsize;
unsigned short dmareg;
unsigned int dmaaddr;
unsigned char *hashp;
@@ -1793,15 +1759,11 @@ int devdisk (int class, int func, int device) {
unsigned short iobuf[1040]; /* local I/O buf (for mapped I/O) */
unsigned short *iobufp;
unsigned short access;
short dmanw, dmanw1, dmanw2;
unsigned int utempl;
short dmanw;
char ordertext[8];
int phyra;
int nb; /* number of bytes returned from read/write */
char devfile[16];
char rtfile[16]; /* read trace file name */
int rtnw; /* total number of words read (all channels) */
/* map device id to device context index
@@ -1811,7 +1773,6 @@ int devdisk (int class, int func, int device) {
switch (device) {
case 026: dx = 0; break;
#ifndef DEMO
case 027: dx = 1; break;
case 022: dx = 2; break;
case 023: dx = 3; break;
@@ -1819,7 +1780,6 @@ int devdisk (int class, int func, int device) {
case 025: dx = 5; break;
case 045: dx = 6; break;
case 046: dx = 7; break;
#endif
default:
fprintf(stderr, "devdisk: non-disk device id '%o ignored\n", device);
return -1;
@@ -1838,10 +1798,6 @@ int devdisk (int class, int func, int device) {
dc[dx].state = S_HALT;
dc[dx].status = 0100000;
dc[dx].usel = -1;
#ifdef DEMO
if (geomcksum != geomhash((char *)geom, sizeof(geom)))
RP=MAKEVA(01000,0);
#endif
for (u=0; u<MAXDRIVES; u++) {
dc[dx].unit[u].rtfd = -1;
dc[dx].unit[u].heads = -1;
@@ -2142,14 +2098,12 @@ int devdisk (int class, int func, int device) {
}
if (u == 1) u = 0;
else if (u == 2) u = 1;
#ifndef DEMO
else if (u == 4) u = 2;
else if (u == 8) u = 3;
else if (u == 16) u = 4;
else if (u == 32) u = 5;
else if (u == 64) u = 6;
else if (u == 128) u = 7;
#endif
else u = 99;
if (u >= MAXDRIVES) {
fprintf(stderr," Device '%o, bad select '%o\n", device, u);

2
fp.h
View File

@@ -38,7 +38,7 @@ http://tima-cmp.imag.fr/~guyot/Cours/Oparithm/english/Op_Ar2.htm
/* getdp unpacks a Prime DPFP into 48-bit sign + mantissa (left
justified in 64 bits) and a 32-bit signed exponent */
inline getdp (unsigned long long p, long long *frac64, int *exp32) {
inline void getdp (unsigned long long p, long long *frac64, int *exp32) {
*frac64 = p & 0xFFFFFFFFFFFF0000LL; /* unpack fraction */
*exp32 = (short) (p & 0xFFFFLL); /* unpack SIGNED exponent */

31
geom.h
View File

@@ -1,35 +1,5 @@
/* static structure for disk file suffixes and config data */
#ifdef DEMO
#define MAXDRIVES 2
#define MAXCTRL 1 /* 1 controller supported at device address '26 */
#define NUMGEOM 7
static struct {
short model;
char suffix[5];
short heads;
short spt;
short maxtrack;
} geom[NUMGEOM] = {
1, "80M", 5, 9, 823,
4, "68M", 3, 9, 1120,
5, "158M", 7, 9, 1120,
6, "160M", 10, 9, 822,
10, "84M", 5, 8, 1016, /* MODEL_4714 */
11, "60M", 4, 7, 1020, /* MODEL_4711 */
12, "120M", 8, 7, 1020, /* MODEL_4715 */
};
#ifdef __LITTLE_ENDIAN__
static int geomcksum = 0x15488c73;
#else
static int geomcksum = 0x156bbb96;
#endif
#else
#define NUMGEOM 25
#define MAXDRIVES 8
#define MAXCTRL 8
@@ -67,4 +37,3 @@
24, "1G", 31, 254, 65, /* MODEL_4734 */
25, "2G", 31, 254, 122, /* MODEL_4736 */
};
#endif

119
makefile
View File

@@ -1,132 +1,33 @@
# makefile to create various emulator builds
# Note: -arch ppc requires /Developer/SDKs/MacOSX10.4u.sdk
REV=${shell hg id -n}
# for Intel, registers can't be used
# for PPC, registers are faster but some features are disabled:
# - PNC can't use signals to interrupt, so it's much slower
# - SIGTERM and SIGQUIT can't be trapped and handled gracefully
# for PPC debug, don't use registers
REGS=-DNOREGS
REGS=
.PHONY: broken brokenp em emp debug debugp trace tracep vfy vfyp fixed fixedp demo demop demol dongleprog lmserver lmserverp magrst magsav parts smad smag mtread mtwrite
em: # production (Intel)
em: # Intel
rm -rf em.o
cc -arch i686 -DKEYID=${KEYID} -DREV=\"${REV}\" -DNOREGS -DNOTRACE -DFAST -DNOMEM -O -c em.c -fobey-inline -mdynamic-no-pic -Idongle/mx/Universal/API;g++ -arch i686 -o em em.o dongle/mx/Universal/API/10_6/libmxmac260.a -framework IOKit -framework CoreFoundation
strip em
rm em.o
cc -DREV=\"${REV}\" -DNOTRACE -DFAST -DNOMEM -O em.c -o em
emp: # production (PowerPC)
rm -rf em.o
cc -arch ppc -DKEYID=${KEYID} ${REGS} -DREV=\"${REV}\" -DNOTRACE -DFAST -DNOMEM -O -c em.c -fobey-inline -mdynamic-no-pic -Idongle/mx/Universal/API;g++ -arch ppc -o em em.o dongle/mx/Universal/API/10_6/libmxmac260.a -framework IOKit -framework CoreFoundation
strip em
rm em.o
debug: # gdb (Intel)
rm -rf em.o
cc -arch i686 -DKEYID=${KEYID} -DREV=\"${REV}\" -DNOREGS -g -O0 -DNOTRACE -DFAST -c em.c -fobey-inline -mdynamic-no-pic -Idongle/mx/Universal/API;g++ -arch i686 -o em em.o dongle/mx/Universal/API/10_6/libmxmac260.a -framework IOKit -framework CoreFoundation
rm em.o
debugp: # gdb (PowerPC)
rm -rf em.o
cc -arch ppc -DKEYID=${KEYID} -mmacosx-version-min=10.4 -DREV=\"${REV}\" -DNOREGS -g -O0 -DNOTRACE -DFAST -c em.c -fobey-inline -mdynamic-no-pic -Idongle/mx/Universal/API/10_6;g++ -arch ppc -o em em.o dongle/mx/Universal/API/10_6/libmxmac260.a -framework IOKit -framework CoreFoundation
rm em.o
cc -DREV=\"${REV}\" -DNOTRACE -DFAST -DNOMEM -g -O0 em.c -o em
trace: # tracing + gdb (Intel)
rm -rf em.o
cc -arch i686 -DKEYID=${KEYID} -DREV=\"${REV}\" -DNOREGS -g -O0 -DFAST -c em.c -fobey-inline -mdynamic-no-pic -Idongle/mx/Universal/API;g++ -arch i686 -o em em.o dongle/mx/Universal/API/10_6/libmxmac260.a -framework IOKit -framework CoreFoundation
rm -rf em.o
tracep: # tracing + gdb (PowerPC)
rm -rf em.o
cc -arch ppc -DKEYID=${KEYID} ${REGS} -DREV=\"${REV}\" -DFAST -O -c em.c -fobey-inline -mdynamic-no-pic -Idongle/mx/Universal/API;g++ -arch ppc -o em em.o dongle/mx/Universal/API/10_6/libmxmac260.a -framework IOKit -framework CoreFoundation
rm -rf em.o
vfy: # prod + tracing to verify em changes (Intel)
rm -rf em.o
cc -arch i686 -DREV=\"\" -O -DNOREGS -DFAST -c em.c -fobey-inline -mdynamic-no-pic -Idongle/mx/Universal/API;g++ -arch i686 -o em em.o dongle/mx/Universal/API/10_6/libmxmac260.a -framework IOKit -framework CoreFoundation
rm -rf em.o
vfyp: # prod + tracing to verify em changes (PowerPC)
rm -rf em.o
cc -arch ppc -mmacosx-version-min=10.4 -DREV=\"\" -O -DFAST -c em.c -fobey-inline -mdynamic-no-pic -Idongle/mx/Universal/API/10_6;g++ -arch ppc -o em em.o dongle/mx/Universal/API/10_6/libmxmac260.a -framework IOKit -framework CoreFoundation
rm -rf em.o
cc -DREV=\"${REV}\" -DFAST -DNOMEM -g -O0 em.c -o em
fixed: # fixed clock rate, gdb (Intel)
rm -rf em.o
cc -arch i686 -DREV=\"${REV}\" -DFIXEDCLOCK -DNOIDLE -DNOREGS -g -O0 -DFAST -c em.c -fobey-inline -mdynamic-no-pic -Idongle/mx/Universal/API;g++ -arch i686 -o em em.o dongle/mx/Universal/API/10_6/libmxmac260.a -framework IOKit -framework CoreFoundation
rm em.o
cc -DREV=\"${REV}\" -DFIXEDCLOCK -DNOIDLE -DNOTRACE -DFAST -DNOMEM -g -O0 em.c -o em
fixedp: # fixed clock rate, gdb (PowerPC)
rm -rf em.o
cc -arch ppc -mmacosx-version-min=10.4 -DREV=\"${REV}\" -DFIXEDCLOCK -DNOIDLE ${REGS} -g -O0 -DFAST -c em.c -fobey-inline -mdynamic-no-pic -Idongle/mx/Universal/API/10_6;g++ -arch ppc -o em em.o dongle/mx/Universal/API/10_6/libmxmac260.a -framework IOKit -framework CoreFoundation
rm em.o
demo: # demo (limited: 1-2 amlc, 2 disk drive up to 160MB) (Intel)
rm -rf em.o
cc -DREV=\"${REV}\" -DNOREGS -DDEMO -DNOTRACE -DFAST -D__LITTLE_ENDIAN__ -O em.c -o em
strip em
rm -rf em.o
demop: # demo (PowerPC)
rm -rf em.o
cc ${REGS} -mmacosx-version-min=10.4 -fno-stack-protector -arch ppc -DREV=\"${REV}\" -DDEMO -DNOTRACE -DFAST -O em.c -fobey-inline -mdynamic-no-pic -o em
strip em
rm -rf em.o
demol: # demo (limited: 1-2 amlc, 1 disk drive up to 160MB, one PNC node) (Intel, LLVM)
rm -rf em.o
llvm-gcc -DREV=\"${REV}\" -DNOREGS -DDEMO -DNOTRACE -DFAST -O em.c -fobey-inline -mdynamic-no-pic -o em
strip em
rm -rf em.o
dongleprog: # utility to program a dongle
cc -arch ppc -DREV=\"${REV}\" -c dongleprog.c -Idongle/mx/Universal/API/10_6;g++ -arch ppc -o dongleprog dongleprog.o dongle/mx/Universal/API/10_6/libmxmac260.a -framework IOKit -framework CoreFoundation
rm dongleprog.o
lmserver: # license server
rm -rf lmserver.o
cc -arch i686 -DREV=\"${REV}\" lmserver.c -o lmserver
rm -rf lmserver.o
lmserverp: # license server
rm -rf lmserver.o
cc -arch ppc -DREV=\"${REV}\" -c lmserver.c -Idongle/mx/Universal/API/10_6;g++ -arch ppc lmserver.o -o lmserver dongle/mx/Universal/API/10_6/libmxmac260.a -framework IOKit -framework CoreFoundation
rm lmserver.o
mtread: # Dump a tape to a .tap disk file (Linux only)
rm -rf mtread.o
@@ -166,13 +67,3 @@ smag: # Unix create Prime pdev
rm -rf smag.o
cc -arch ppc -DREV=\"${REV}\" -o smag smag.c
broken: # production (Intel)
rm -rf broken.o
cc -arch i686 -O -c broken.c -fobey-inline -mdynamic-no-pic -Idongle/mx/Universal/API;g++ -arch i686 -o broken broken.o dongle/mx/Universal/API/10_6/libmxmac260.a -framework IOKit -framework CoreFoundation
brokenp: # production (PPC)
rm -rf broken.o
cc -arch ppc -O -c broken.c -fobey-inline -mdynamic-no-pic -Idongle/mx/Universal/API;g++ -arch ppc -o brokenp broken.o dongle/mx/Universal/API/10_6/libmxmac260.a -framework IOKit -framework CoreFoundation

62
regs.h
View File

@@ -249,41 +249,6 @@ static union {
} sym;
} regs;
/* the Prime program counter (RP) and pointer to current register set (crsl)
can be either in a dedicated register or regular global variables.
Putting them in dedicated registers gives about an 11% performance boost
and reduces the code size from 146K to 136K */
#ifndef NOREGS
/* store RP and crsl in dedicated registers 29-30 (Power PC) */
static unsigned int grp; /* global RP for restore after longjmp */
register union {
struct {
#ifdef __BIG_ENDIAN__
unsigned short rph;
unsigned short rpl;
#else
unsigned short rpl;
unsigned short rph;
#endif
} s;
unsigned int ul;
} rpreg asm ("r29");
static unsigned int *gcrsl; /* global crs pointer for restore after longjmp */
register union {
short *i16;
unsigned short *u16;
int *i32;
unsigned int *u32;
long long *i64;
unsigned long long *u64;
} cr asm ("r30");
#else
union {
struct {
#ifdef __BIG_ENDIAN__
@@ -308,7 +273,6 @@ static union {
long long *i64;
unsigned long long *u64;
} cr;
#endif
#define crs cr.u16
#define crsl cr.u32
@@ -327,7 +291,7 @@ static inline uint16_t getcrs16(int offset) { \
/* store 16-bit unsigned at 16-bit offset */
//#define putcrs16(offset, val) crs[(offset)] = (val)
static inline uint16_t putcrs16(int offset, uint16_t val) { \
static inline void putcrs16(int offset, uint16_t val) { \
crs[(offset)] = swap16(val); \
}
@@ -347,13 +311,13 @@ static inline uint32_t getcrs32(int offset) { \
/* put 32-bit unsigned at 16-bit offset */
//#define putcrs32(offset, val) *(unsigned int *)(crs+(offset)) = (val)
static inline uint32_t putcrs32(int offset, uint32_t val) { \
static inline void putcrs32(int offset, uint32_t val) { \
*(unsigned int *)(crs+offset) = swap32(val); \
}
/* put 32-bit signed at 16-bit offset */
//#define putcrs32s(offset, val) *(int *)(crs+(offset)) = (val)
#define putcrs32s(offset, val) (int32_t) putcrs32((offset), (val))
#define putcrs32s(offset, val) putcrs32((offset), (val))
/* get 32-bit effective address at 16-bit offset */
//#define getcrs32ea(offset) *(ea_t *)(crs+(offset))
@@ -371,13 +335,13 @@ static inline int64_t getcrs64s(int offset) { \
/* put 64-bit signed at 16-bit offset */
//#define putcrs64s(offset, val) *(long long *)(crs+(offset)) = (val)
static inline int64_t putcrs64s(int offset, int64_t val) { \
static inline void putcrs64s(int offset, int64_t val) { \
*(long long *)(crs+offset) = swap64(val); \
}
/* put 64-bit double at 16-bit offset (remove later) */
//#define putcrs64d(offset, val) *(double *)(crs+(offset)) = (val)
static inline double putcrs64d(int offset, double val) { \
static inline void putcrs64d(int offset, double val) { \
*(unsigned long long *)(crs+offset) = swap64(*(uint64_t *)&val); \
}
@@ -387,7 +351,7 @@ static inline uint16_t getar16(int offset) { \
}
/* put 16-bit unsigned at 16-bit absolute register file address */
static inline uint16_t putar16(int offset, uint16_t val) { \
static inline void putar16(int offset, uint16_t val) { \
regs.u16[(offset)] = swap16(val); \
}
@@ -401,7 +365,7 @@ static inline uint16_t getgr16(int offset) { \
/* store 16-bit unsigned at 32-bit offset (in left halfword) */
//#define putgr16(offset, val) crs[(offset)*2] = (val)
static inline uint16_t putgr16(int offset, uint16_t val) { \
static inline void putgr16(int offset, uint16_t val) { \
crs[(offset)*2] = swap16(val); \
}
@@ -411,7 +375,7 @@ static inline uint16_t putgr16(int offset, uint16_t val) { \
/* store 16-bit signed at 32-bit offset (in left halfword) */
//#define putgr16s(offset, val) *(short *)(crs+(offset)*2) = (val)
#define putgr16s(offset, val) (short)putgr16((offset), (val))
#define putgr16s(offset, val) putgr16((offset), (val))
/* fetch 32-bit unsigned at 32-bit offset */
//#define getgr32(offset) crsl[(offset)]
@@ -421,7 +385,7 @@ static inline uint32_t getgr32(int offset) { \
/* store 32-bit unsigned at 32-bit offset */
//#define putgr32(offset, val) crsl[(offset)] = (val)
static inline uint32_t putgr32(int offset, uint32_t val) { \
static inline void putgr32(int offset, uint32_t val) { \
crsl[offset] = swap32(val); \
}
@@ -441,7 +405,7 @@ static inline int64_t getgr64s(int offset) { \
/* store 64-bit signed at 32-bit offset */
//#define putgr64s(offset, val) *(long long *)(crsl+(offset)) = (val)
static inline int64_t putgr64s(int offset, int64_t val) { \
static inline void putgr64s(int offset, int64_t val) { \
*(long long *)(crsl+offset) = swap64(val); \
}
@@ -455,7 +419,7 @@ static inline uint32_t getar32(int offset) { \
}
/* put 32-bit unsigned at 32-bit absolute register file address */
static inline uint32_t putar32(int offset, uint32_t val) { \
static inline void putar32(int offset, uint32_t val) { \
regs.u32[(offset)] = swap32(val); \
}
@@ -474,14 +438,14 @@ static inline uint64_t getfr64(int offset) { \
/* put 64-bit double in FP reg 0 or 1
For FP 0, offset=0; for FP 1, offset=2 */
//#define putfr64(offset, val)
static inline double putfr64(int offset, unsigned long long val) { \
static inline void putfr64(int offset, unsigned long long val) { \
*(unsigned long long *)(crsl+FAC0+offset) = swap64((val));
}
/* put 64-bit double in FP reg 0 or 1
For FP 0, offset=0; for FP 1, offset=2 */
//#define putfr64d(offset, val) *(double *)(crsl+FAC0+offset) = (val)
static inline double putfr64d(int offset, double val) { \
static inline void putfr64d(int offset, double val) { \
*(unsigned long long *)(crsl+FAC0+offset) = swap64(*(uint64_t *)&val); \
}

2
swap.h
View File

@@ -1,5 +1,7 @@
#include <stdint.h>
#define __LITTLE_ENDIAN__ 1
#if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)
# error Either __BIG_ENDIAN__ or __LITTLE_ENDIAN__ must be defined.
#endif