mirror of
https://github.com/prirun/p50em.git
synced 2026-04-15 23:51:06 +00:00
added table of generic instructions to ignore & log
initial disk controller support began FP instruction work
This commit is contained in:
313
emdev.h
313
emdev.h
@@ -6,50 +6,95 @@
|
||||
OCP instructions never skip
|
||||
SKS instructions skip on specified conditions
|
||||
INA/OTA instructions skip if they succeed (data was read/written)
|
||||
|
||||
Device numbers:
|
||||
'01 = paper tape reader
|
||||
'02 = paper tape punch
|
||||
'03 = 1st MPC (line printer/card reader/card punch)
|
||||
'04 = SOC board (system console/user terminal)
|
||||
'05 = 2nd MPC (line printer/card reader/card punch)
|
||||
'06 = card punch? (RTOS User Guide, A-1) / IPC (Engr Handbook p.101)
|
||||
'07 = PNC
|
||||
'12 = diskette
|
||||
'13 = 2nd magtape controller
|
||||
'14 = 1st magtape controller
|
||||
'20 = control panel / real-time clock
|
||||
'21 = 1st 4002 disk controller
|
||||
'22 = obsolete: fixed head disk
|
||||
'23 = obsolete: 30MB disk
|
||||
'24 = tag monitor (tmain.pma) / writable control store
|
||||
'25 = obsolete: moving head disk
|
||||
'26 = 1st disk controller
|
||||
'27 = 2nd disk controller
|
||||
'30-32 = BPIOC #1-3 (RTOS User Guide, A-1)
|
||||
'33 = 1st Versatec (verdim)
|
||||
'34 = 2nd Versatec
|
||||
'35 = 4th AMLC
|
||||
'36-37 = ELFBUS #1 & 2
|
||||
'40 = A/D converter type 6000
|
||||
'41 = digital input type 6020
|
||||
'42 = digital input #2
|
||||
'43 = digital output type 6040
|
||||
'44 = digital output #2
|
||||
'45 = D/A converter type 6060 (analog output)
|
||||
'50 = 1st HSSMLC (cs/slcdim.pma)
|
||||
'51 = 2nd HSSMLC
|
||||
'52 = 3rd AMLC
|
||||
'53 = 2nd AMLC
|
||||
'54 = 1st AMLC
|
||||
'55 = MACI autocall unit
|
||||
'56 = old SMLC (RTOS User Guide, A-1)
|
||||
'60-67 = reserved for user devices
|
||||
'70-'73 = Megatek graphics terminals
|
||||
|
||||
Devices emulated by Primos in ks/ptrap.ftn:
|
||||
'04 = console, '01 = paper tape reader, '02 = paper tape punch,
|
||||
'20 = control panel
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void devnull (short class, short func, short device) {
|
||||
|
||||
switch (class) {
|
||||
|
||||
case 0:
|
||||
fprintf(stderr," OCP '%2#0o%2#0o\n", func, device);
|
||||
fprintf(stderr," OCP '%02o%02o\n", func, device);
|
||||
if (func == 0) {
|
||||
;
|
||||
} else {
|
||||
fprintf(stderr," unimplemented OCP device %2#0o function\n", device);
|
||||
fprintf(stderr," unimplemented OCP device '%02o function\n", device);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
fprintf(stderr," SKS '%2#0o%2#0o\n", func, device);
|
||||
fprintf(stderr," SKS '%02o%02o\n", func, device);
|
||||
if (func == 0)
|
||||
mem[P]++; /* assume it's always ready */
|
||||
else {
|
||||
fprintf(stderr," unimplemented SKS device %2#0o function\n", device);
|
||||
fprintf(stderr," unimplemented SKS device '%02o function\n", device);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
fprintf(stderr," INA '%2#0o%2#0o\n", func, device);
|
||||
fprintf(stderr," INA '%02o%02o\n", func, device);
|
||||
if (func == 0) {
|
||||
;
|
||||
} else {
|
||||
fprintf(stderr," unimplemented INA device %2#0o function\n", device);
|
||||
fprintf(stderr," unimplemented INA device '%02o function\n", device);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
fprintf(stderr," OTA '%2#0o%2#0o\n", func, device);
|
||||
fprintf(stderr," OTA '%02o%02o\n", func, device);
|
||||
if (func == 0 | func == 1) {
|
||||
mem[P]++; /* OTA '0004 always works on Unix */
|
||||
} else {
|
||||
fprintf(stderr," unimplemented OTA device %2#0o function\n", device);
|
||||
fprintf(stderr," unimplemented OTA device '%02o function\n", device);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
@@ -87,11 +132,11 @@ void devasr (short class, short func, short device) {
|
||||
switch (class) {
|
||||
|
||||
case 0:
|
||||
fprintf(stderr," OCP '%2#0o%2#0o\n", func, device);
|
||||
fprintf(stderr," OCP '%02o%02o\n", func, device);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
fprintf(stderr," SKS '%2#0o%2#0o\n", func, device);
|
||||
fprintf(stderr," SKS '%02o%02o\n", func, device);
|
||||
if (func <= 7)
|
||||
mem[P]++; /* assume it's always ready */
|
||||
else {
|
||||
@@ -101,7 +146,7 @@ void devasr (short class, short func, short device) {
|
||||
break;
|
||||
|
||||
case 2:
|
||||
fprintf(stderr," INA '%2#0o%2#0o\n", func, device);
|
||||
fprintf(stderr," INA '%02o%02o\n", func, device);
|
||||
if (func == 0 || func == 010) {
|
||||
if (fcntl(ttydev, F_GETFL, ttyflags) == -1) {
|
||||
perror(" unable to get tty flags");
|
||||
@@ -143,7 +188,7 @@ void devasr (short class, short func, short device) {
|
||||
break;
|
||||
|
||||
case 3:
|
||||
fprintf(stderr," OTA '%2#0o%2#0o\n", func, device);
|
||||
fprintf(stderr," OTA '%02o%02o\n", func, device);
|
||||
if (func == 0) {
|
||||
fprintf(stderr," char to write=%o\n", mem[A]);
|
||||
putchar(mem[A] & 0x7f);
|
||||
@@ -162,6 +207,40 @@ void devasr (short class, short func, short device) {
|
||||
|
||||
|
||||
|
||||
/* Device '14 - magtape controller #1
|
||||
*/
|
||||
|
||||
void devmt (short class, short func, short device) {
|
||||
|
||||
switch (class) {
|
||||
|
||||
case 0:
|
||||
fprintf(stderr," OCP '%02o%02o\n", func, device);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
fprintf(stderr," SKS '%02o%02o\n", func, device);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
fprintf(stderr," INA '%02o%02o\n", func, device);
|
||||
if (mem[mem[P]] == 03776) { /* JMP *-1 -> blocking read */
|
||||
fprintf(stderr," Device not supported, so I/O hangs\n");
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
fprintf(stderr," OTA '%02o%02o\n", func, device);
|
||||
if (mem[mem[P]] == 03776) { /* JMP *-1 -> blocking read */
|
||||
fprintf(stderr," Device not supported, so I/O hangs\n");
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Device '20: control panel switches and lights
|
||||
|
||||
OTA '1720 = write to lights (sets CP fetch address)
|
||||
@@ -174,33 +253,34 @@ void devcp (short class, short func, short device) {
|
||||
switch (class) {
|
||||
|
||||
case 0:
|
||||
fprintf(stderr," OCP '%2#0o%2#0o\n", func, device);
|
||||
fprintf(stderr," unimplemented OCP device %2#0o function\n", device);
|
||||
fprintf(stderr," OCP '%02o%02o\n", func, device);
|
||||
fprintf(stderr," unimplemented OCP device '%02o function\n", device);
|
||||
exit(1);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
fprintf(stderr," SKS '%2#0o%2#0o\n", func, device);
|
||||
fprintf(stderr," unimplemented SKS device %2#0o function\n", device);
|
||||
fprintf(stderr," SKS '%02o%02o\n", func, device);
|
||||
fprintf(stderr," unimplemented SKS device '%02o function\n", device);
|
||||
exit(1);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
fprintf(stderr," INA '%2#0o%2#0o\n", func, device);
|
||||
fprintf(stderr," INA '%02o%02o\n", func, device);
|
||||
if (func == 016) {
|
||||
mem[A] = 014114;
|
||||
mem[A] = 0;
|
||||
} else {
|
||||
fprintf(stderr," unimplemented INA device %2#0o function\n", device);
|
||||
fprintf(stderr," unimplemented INA device '%02o function\n", device);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
fprintf(stderr," OTA '%2#0o%2#0o\n", func, device);
|
||||
fprintf(stderr," OTA '%02o%02o\n", func, device);
|
||||
if (func == 017) { /* write lights */
|
||||
mem[P]++;
|
||||
} else {
|
||||
fprintf(stderr," unimplemented OTA device %2#0o function\n", device);
|
||||
fprintf(stderr," unimplemented OTA device '%02o function\n", device);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
@@ -208,3 +288,196 @@ void devcp (short class, short func, short device) {
|
||||
}
|
||||
|
||||
|
||||
/* disk controller at '26 and '27
|
||||
|
||||
NOTES:
|
||||
- in the DSEL disk channel program command, unit number is a 4-bit field,
|
||||
with these binary values:
|
||||
0001 = unit 0 (pdev 460/461)
|
||||
0010 = unit 1 (pdev 462/463)
|
||||
0100 = unit 2 (pdev 464/465)
|
||||
1000 = unit 3 (pdev 466/467)
|
||||
|
||||
OCP '1626 = reset interrupt
|
||||
OCP '1726 = reset controller
|
||||
|
||||
INA '1126 = input ID, don't clear A first, fails if no controller
|
||||
INA '1726 = read status (or something), fails if controller busy
|
||||
|
||||
OTA '1726 = load OAR (Order Address Register), ie, run channel
|
||||
program, address is in A
|
||||
|
||||
*/
|
||||
|
||||
void devdisk (short class, short func, short device) {
|
||||
unsigned short oar;
|
||||
unsigned short status; /* actual status */
|
||||
unsigned short teststatus; /* status for order testing */
|
||||
unsigned short memaddr;
|
||||
unsigned short order;
|
||||
short halt;
|
||||
short unit;
|
||||
short head, track, rec, recsize, nwords;
|
||||
unsigned short dmachan, dmanch, dmaaddr;
|
||||
short dmanw;
|
||||
char ordertext[8];
|
||||
char devfile[8];
|
||||
char devopened[8]; /* device file that is open on devfd */
|
||||
static int devfd=-1; /* device file descriptor */
|
||||
int theads, spt, phyra;
|
||||
switch (class) {
|
||||
|
||||
case 0:
|
||||
fprintf(stderr," OCP '%2o%2o\n", func, device);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
fprintf(stderr," SKS '%2o%2o\n", func, device);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
fprintf(stderr," INA '%2o%2o\n", func, device);
|
||||
if (func == 01) /* read device id, clear A first */
|
||||
mem[A] = device;
|
||||
else if (func == 011) /* read device id, don't clear A */
|
||||
mem[A] |= device;
|
||||
else if (func == 017) /* read status */
|
||||
mem[A] = 0100000;
|
||||
mem[P]++;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
fprintf(stderr," OTA '%02o%02o\n", func, device);
|
||||
if (func == 017) { /* set OAR (order address register) */
|
||||
oar = mem[A];
|
||||
halt = 0;
|
||||
status = 0100000;
|
||||
unit = -1;
|
||||
while (!halt) {
|
||||
order = mem[oar]>>12;
|
||||
fprintf(stderr,"\n %o: %o %o %o\n", oar, mem[oar], mem[oar+1], mem[oar+2]);
|
||||
if (mem[oar] & 04000) { /* "execute if ..." */
|
||||
if (order == 2 || order == 5 || order == 6)
|
||||
oar += 3;
|
||||
else
|
||||
oar += 2;
|
||||
continue;
|
||||
}
|
||||
switch (order) {
|
||||
case 0: /* DHLT = Halt */
|
||||
halt = 1;
|
||||
fprintf(stderr," channel program halt at '%o\n", oar);
|
||||
break;
|
||||
case 2: /* SFORM = Format */
|
||||
case 5: /* SREAD = Read */
|
||||
case 6: /* SWRITE = Write */
|
||||
recsize = mem[oar] & 017;
|
||||
track = mem[oar+1] & 01777;
|
||||
rec = mem[oar+2] >> 8; /* # records for format, rec # for R/W */
|
||||
head = mem[oar+2] & 077;
|
||||
if (order == 2)
|
||||
strcpy(ordertext,"Format");
|
||||
else if (order == 5)
|
||||
strcpy(ordertext,"Read");
|
||||
else if (order == 6)
|
||||
strcpy(ordertext,"Write");
|
||||
fprintf(stderr," %s, head=%d, track=%d, rec=%d, recsize=%d\n", ordertext, head, track, rec, recsize);
|
||||
dmanw = mem[dmachan];
|
||||
dmanw = -(dmanw>>4);
|
||||
dmaaddr = mem[dmachan+1];
|
||||
fprintf(stderr, " DMA channels: nch-1=%d, ['%o]='%o, ['%o]='%o, nwords=%d\n", dmanch, dmachan, mem[dmachan], dmachan+1, mem[dmachan+1], dmanw);
|
||||
if (devfd == -1) {
|
||||
fprintf(stderr," Unit not selected or not ready\n");
|
||||
status = 0100001;
|
||||
} else if (order == 2)
|
||||
fprintf(stderr," Format order not implemented\n");
|
||||
else if (order == 5) {
|
||||
|
||||
/* translate head/track/sector to drive record address */
|
||||
|
||||
theads = 40; /* should get total heads from a config file */
|
||||
spt = 9; /* and sectors per track too */
|
||||
phyra = (track*theads*spt) + head*9 + rec;
|
||||
fprintf(stderr, " phyra=%d, byte offset=%d\n", phyra, phyra*2080);
|
||||
if (lseek(devfd, phyra*2080, SEEK_SET) == -1) {
|
||||
perror("Unable to seek drive file");
|
||||
exit(1);
|
||||
}
|
||||
if (read(devfd, mem+dmaaddr, dmanw*2) != dmanw*2) {
|
||||
perror("Unable to read drive file");
|
||||
exit(1);
|
||||
}
|
||||
mem[dmachan] = 0;
|
||||
mem[dmachan+1] += dmanw;
|
||||
|
||||
} else if (order == 6)
|
||||
fprintf(stderr," Write order not implemented\n");
|
||||
oar += 3;
|
||||
break;
|
||||
case 3: /* SSEEK = Seek */
|
||||
track = mem[oar+1] & 01777;
|
||||
fprintf(stderr," seek track %d, restore=%d, clear=%d\n", track, (mem[oar+1] & 0100000) != 0, (mem[oar+1] & 040000) != 0);
|
||||
oar += 2;
|
||||
break;
|
||||
case 4: /* DSEL = Select unit */
|
||||
unit = (mem[oar+1] & 017) >> 1; /* unit = 0/1/2/4 */
|
||||
if (unit == 4) unit = 3; /* unit = 0/1/2/3 */
|
||||
snprintf(devfile,sizeof(devfile),"dev%ou%d", device, unit);
|
||||
fprintf(stderr," select unit %d, filename %s\n", unit, devfile);
|
||||
if (strcmp(devfile,devopened) != 0 || devfd == -1) {
|
||||
if (devfd != -1) {
|
||||
close(devfd);
|
||||
devfd = -1;
|
||||
}
|
||||
if ((devfd = open(devfile, O_RDONLY, 0)) == -1)
|
||||
status = 0100001; /* not ready */
|
||||
else
|
||||
strcpy(devopened, devfile);
|
||||
}
|
||||
oar += 2;
|
||||
break;
|
||||
case 7: /* DSTALL = Stall */
|
||||
fprintf(stderr," stall\n");
|
||||
oar += 2;
|
||||
break;
|
||||
case 9: /* DSTAT = Store status to memory */
|
||||
memaddr = mem[oar+1];
|
||||
fprintf(stderr, " store status to '%o\n", memaddr);
|
||||
mem[memaddr] = status;
|
||||
oar += 2;
|
||||
break;
|
||||
case 11: /* DOAR = Store OAR to memory (2 words) */
|
||||
memaddr = mem[oar+1];
|
||||
fprintf(stderr, " store OAR to '%o\n", memaddr);
|
||||
mem[memaddr] = oar;
|
||||
oar += 2;
|
||||
break;
|
||||
case 13: /* SDMA = select DMA channel(s) to use */
|
||||
dmanch = mem[oar] & 017;
|
||||
dmachan = mem[oar+1];
|
||||
fprintf(stderr, " set DMA channels, nch-1=%d, channel='%o\n", dmanch, dmachan);
|
||||
oar += 2;
|
||||
break;
|
||||
case 14: /* DINT = generate interrupt through vector address */
|
||||
memaddr = mem[oar+1];
|
||||
fprintf(stderr, " interrupt through '%o\n", memaddr);
|
||||
exit(1);
|
||||
oar += 2;
|
||||
break;
|
||||
case 15: /* DTRAN = channel program jump */
|
||||
oar = mem[oar+1];
|
||||
fprintf(stderr, " jump to '%o\n", oar);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, " unrecognized channel order = %d\n", order);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
mem[P]++;
|
||||
} else {
|
||||
fprintf(stderr," unimplemented OTA device '%02o function\n", device);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
304
fp.c
Normal file
304
fp.c
Normal file
@@ -0,0 +1,304 @@
|
||||
/* ** general conversion doc here, or (referenced) above. ***************** */
|
||||
/* doc exponent details here: (-1 & bin pt. placement by prieee) vs.
|
||||
vs. (-2 by ieeepr()): note that
|
||||
IEEE denormalized bin pxxxxxxx prime (relative to the 23 bits);
|
||||
in ieeepr the trick is to treat normalized #'s as the special case. */
|
||||
|
||||
|
||||
void prieee4(xlongp) /* ****** convert from Prime to IEEE. ****** */
|
||||
long *xlongp;
|
||||
{
|
||||
long xlong;
|
||||
long sign; /* sign */
|
||||
long mant; /* mantissa: note this is signed: mant = -mant below */
|
||||
long exp; /* exponent */
|
||||
|
||||
/* note: when converting form Prime to IEEE, we need to check for exponent
|
||||
underflow, but not for overflow. */
|
||||
|
||||
xlong = *xlongp;
|
||||
mant = xlong & 0xffffff00; /* 24 bits: includes sign bit */
|
||||
sign = mant & 0x80000000;
|
||||
mant >>= 8; /* ok to trash upper byte, which will get masked out. */
|
||||
if (sign)
|
||||
mant = - mant;
|
||||
/* now have 24 bit # w/ leading 0. */
|
||||
|
||||
exp = (xlong & 0x000000ff) - 1; /* exp now in excess 127 (IEEE) form. */
|
||||
|
||||
if (exp < 0) {
|
||||
mant >>= 1; /* tiny tiny #; will get shifted once more below. */
|
||||
++exp; /* Bring exp back up to 0. */
|
||||
}
|
||||
else /* *** normalize the mantissa. If input Prime mantissa was already
|
||||
noramalized, this loop will still execute once, unless input #
|
||||
was -(2**n) in which case it will execute 0 times. This is
|
||||
because Prime mantissas are 2's compliment, and powers of 2
|
||||
normalize differently when negated. Note no loop for 0 exp. */
|
||||
while (exp && !(mant & 0x00800000)) {
|
||||
mant <<= 1;
|
||||
--exp;
|
||||
}
|
||||
|
||||
/* we now have a 24 bit unsigned # w/ a leading 1. If the exponent is > 0,
|
||||
we are all set: the resulting IEEE number will be normalized. This
|
||||
leading (hidden) IEEE 1 will be masked out below. */
|
||||
if ( ! exp) /* result must be denormalized: shift 1 further to */
|
||||
mant >>= 1; /* include IEEE leading bit, which may be 0 or 1. */
|
||||
|
||||
mant &= 0x007fffff;
|
||||
exp <<= 23;
|
||||
*xlongp = sign | exp | mant;
|
||||
}
|
||||
|
||||
|
||||
void ieeepr4(xlongp) /* ****** convert from IEEE to Prime. ****** */
|
||||
long *xlongp;
|
||||
{
|
||||
long xlong;
|
||||
long sign; /* sign */
|
||||
long mant; /* mantissa: note this is signed: mant = -mant below */
|
||||
long exp; /* exponent */
|
||||
long templ;
|
||||
|
||||
/* note: when converting form Prime to IEEE, we need to check for exponent
|
||||
overflow, but not for underflow. */
|
||||
xlong = *xlongp;
|
||||
|
||||
if ( ! (xlong & 0x7fffffff))
|
||||
*xlongp = 0; /* +0 or -0 */
|
||||
else {
|
||||
sign = xlong & 0x80000000;
|
||||
mant = (xlong & 0x007fffff) << 8; /* assume denormalized, adjust below */
|
||||
exp = (xlong & 0x7f800000) >> 23; /* still in excess 127 (IEEE) form. */
|
||||
if (exp == 0xff) { /* NaN (not a number) or +/- infinity? */
|
||||
if (mant == 0) {
|
||||
/* +/- infinity. */
|
||||
if (sign == 0)
|
||||
*xlongp = 0x7fffffff; /* largest Prime # in for +infinity. */
|
||||
else /* note: 0x800000ff cant be negated; */
|
||||
*xlongp = 0x800001ff; /* use - 0x7fffffff for -infinity. */
|
||||
}
|
||||
else {
|
||||
/* NaN (not a number) */
|
||||
if (sign == 0)
|
||||
*xlongp = 0x539733ff; /* use 1.11111e+38 for NaN, since */
|
||||
else /* it stands out if printed. */
|
||||
*xlongp = 0xac68cdff; /* use -1.11111e+38 for -NaN. */
|
||||
}
|
||||
}
|
||||
else { /* actual number */
|
||||
if (exp != 0) {
|
||||
if(mant != 0x7fffff00)/* Special case of mantissa value of all 1s*/
|
||||
mant = (mant >> 1) + 0x40000080; /* ieee normalized number: */
|
||||
/* shift to make room for */
|
||||
/* hidden leading 1 bit, 'or'*/
|
||||
/* it in and round truncated */
|
||||
/* LSBit up. */
|
||||
mant &= 0xffffff00;
|
||||
}
|
||||
exp += 2; /* exp now in excess 128 (Prime) form. */
|
||||
|
||||
if (sign != 0) /* sign bit of mant will be 0 at this point. */
|
||||
mant = - mant;
|
||||
/* mant is now a 24 bit signed mantissa (shifted to Prime position) */
|
||||
|
||||
/* *** normalize the number. In most cases, the number will already
|
||||
be normalized. Negative powers of 2 will be shifted once, since
|
||||
they normalize differently. IEEE denormalized numbers can be
|
||||
adjusted at most 2 bits, due to the excess 127 vs. 128 exponent and
|
||||
binary point position differences (cant negate exponent). *** */
|
||||
while (exp && ((~(mant^(mant<<1))) & 0x80000000)) {
|
||||
mant <<= 1; /* sign and next most significant */
|
||||
--exp; /* bit are equal: normalize. */
|
||||
}
|
||||
if (exp > 0xff) {
|
||||
if ( ! sign)
|
||||
*xlongp = 0x7fffffff; /* largest Prime # in for +infinity. */
|
||||
else /* note: 0x800000ff cant be negated; */
|
||||
*xlongp = 0x800001ff; /* use - 0x7fffffff for -infinity. */
|
||||
}
|
||||
else
|
||||
*xlongp = mant | exp; /* mant is signed; */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define l1 0
|
||||
#define l0 1
|
||||
|
||||
/* ** general conversion doc here, or (referenced) above. ***************** */
|
||||
/* doc exponent details here: (-1 & bin pt. placement by prieee) vs.
|
||||
vs. (-2 by ieeepr()): note that
|
||||
IEEE denormalized bin pxxxxxxx prime (relative to the 23 bits);
|
||||
in ieeepr the trick is to treat normalized #'s as the special case. */
|
||||
|
||||
|
||||
void prieee8(xlongp) /* ****** convert from Prime to IEEE. ****** */
|
||||
long *xlongp;
|
||||
{
|
||||
long xlong1,xlong0;
|
||||
long mant1,mant0; /* mantissa: these are signed: mant = -mant below */
|
||||
long sign; /* sign */
|
||||
long exp; /* exponent */
|
||||
|
||||
/* note: when converting REAL*8 form Prime to IEEE, we need to check for both
|
||||
exponent underflow, and overflow. */
|
||||
|
||||
xlong1 = xlongp[l1]; /* high 4 bytes */
|
||||
xlong0 = xlongp[l0]; /* low 4 bytes */
|
||||
sign = xlong1 & 0x80000000;
|
||||
mant1 = xlong1 >> 11; /* 48 bits, includes */
|
||||
mant0 = (xlong1 << 21) | ((xlong0 >> 11) & 0xfffe0); /* includes sign bit */
|
||||
|
||||
if ( ! mant0 && ! mant1) { /* zero (dirty or otherwise)? */
|
||||
xlongp[l1] = xlongp[l0] = 0;
|
||||
return; /* return ****** */
|
||||
}
|
||||
if (sign) { /* 2's comp mant1/mant0 pair */
|
||||
mant0 = - mant0;
|
||||
mant1 = ~ mant1;
|
||||
if ( ! mant0)
|
||||
++ mant1; /* mant0==0: have a carry fr. mant0 to mant1. */
|
||||
}
|
||||
|
||||
/* now have 48 bit # w/ leading 0. */
|
||||
|
||||
exp = (xlong0 & 0xffff) - 0x80; /* convert 16 bit */
|
||||
if (exp & 0x8000) /* Prime exponent */
|
||||
exp |= 0xffff0000; /* from "excess 128" */
|
||||
else /* form to 2's */
|
||||
exp &= 0x0000ffff; /* complement form. */
|
||||
exp += 0x3ff; /* exp now in excess 1023 (IEEE) form. */
|
||||
|
||||
if (exp < -50) { /* Prime exp too small? */
|
||||
xlongp[l1] = xlongp[l0] = 0; /* closest IEEE is 0. */
|
||||
return; /* return ****** */
|
||||
}
|
||||
|
||||
if (exp < 0) {
|
||||
/* note: can still get 0, iff have leading (non sign bit) 0's */
|
||||
mant0 = (mant1 << 32+exp) | (mant0 >> -exp); /* mant >>= -exp; */
|
||||
mant1 >>= -exp; /* tiny tiny #; will get shifted once more below. */
|
||||
++mant0; /* lsb will get lost below, since # is denormalized; round */
|
||||
if ( ! mant0)
|
||||
++mant1;
|
||||
exp = 0; /* exp += -exp. */
|
||||
}
|
||||
else /* *** normalize the mantissa. */
|
||||
while (exp && !(mant1 & 0x00100000)) {
|
||||
mant1 <<= 1;
|
||||
if (mant0 & 0x80000000)
|
||||
mant1 |= 1;
|
||||
mant0 <<= 1;
|
||||
--exp;
|
||||
}
|
||||
|
||||
if (exp > 0x7fe) {
|
||||
xlongp[l1] = sign | 0x7fefffff; /* Prime exp too big; closest */
|
||||
xlongp[l0] = 0xffffffff; /* closest IEEE is (+/-) max. */
|
||||
}
|
||||
else {
|
||||
/* we now have a 48 bit unsigned # w/ a leading 1. If the exponent is
|
||||
> 0, we are all set: the resulting IEEE number will be normalized.
|
||||
This leading (hidden) IEEE 1 will be masked out below. */
|
||||
if ( ! exp) { /* result must be denormalized: shift 1 further to */
|
||||
mant0 >>= 1; /* include IEEE leading bit, which may be 0 or 1. */
|
||||
if (mant1 & 1)
|
||||
mant0 |= 0x80000000;
|
||||
mant1 >>= 1;
|
||||
}
|
||||
mant1 &= 0x000fffff;
|
||||
exp <<= 20;
|
||||
xlongp[l1] = sign | exp | mant1;
|
||||
xlongp[l0] = mant0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ieeepr8(xlongp) /* ****** convert from IEEE to Prime. ****** */
|
||||
long *xlongp;
|
||||
{
|
||||
long xlong1,xlong0;
|
||||
long mant1,mant0; /* mantissa: these are signed: mant = -mant below */
|
||||
long sign; /* sign */
|
||||
long exp; /* exponent */
|
||||
|
||||
/* note: when converting REAL*8 form Prime to IEEE, we dont need to check for
|
||||
exponent overflow, or underflow. */
|
||||
xlong1 = xlongp[l1]; /* high 4 bytes */
|
||||
xlong0 = xlongp[l0]; /* low 4 bytes */
|
||||
|
||||
if ((xlong1 & 0x7fffffff) == 0 && xlong0 == 0) {
|
||||
xlongp[l1] = xlongp[l0] = 0; /* +0 or -0 */
|
||||
return; /* return ****** */
|
||||
}
|
||||
sign = xlong1 & 0x80000000;
|
||||
exp = (xlong1 & 0x7ff00000) >> 20; /* still in excess 1023 (IEEE) form. */
|
||||
mant1 = ((xlong1 & 0xfffff) << 11) | ((xlong0 >> 21) & 0x7ff);
|
||||
mant0 = xlong0 << 11; /* assume denormalized, adjust below */
|
||||
if (exp == 0x7ff) { /* NaN (not a number) or +/- infinity? */
|
||||
if (mant1 == 0 && mant0 == 0) {
|
||||
/* +/- infinity. */
|
||||
if (sign == 0) {
|
||||
xlongp[l1] = 0x7fffffff; /* largest Prime # in for +infinity. */
|
||||
xlongp[l0] = 0xffffffff;
|
||||
}
|
||||
else { /* note: 0x80000000 0000ffff cant be */
|
||||
xlongp[l1] = 0x80000000; /* negated, use -0x7fffffff ffffffff */
|
||||
xlongp[l0] = 0x0001ffff; /* -infinity. */
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* NaN (not a number) */
|
||||
if (sign == 0) {
|
||||
xlongp[l1] = 0x7fffffff; /* For now, use +/- infinity values */
|
||||
xlongp[l0] = 0xffffffff; /* for +/- NaN. */
|
||||
}
|
||||
else {
|
||||
xlongp[l1] = 0x80000000;
|
||||
xlongp[l0] = 0x0001ffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
else { /* actual number */
|
||||
if (exp != 0) {
|
||||
/* ieee normalized number: shift mantissa to make room for hidden */
|
||||
mant0 >>= 1; /* leading 1 bit and 'or' it in. */
|
||||
if (mant1 & 1)
|
||||
mant0 |= 0x80000000;
|
||||
else
|
||||
mant0 &= 0x7fffffff;
|
||||
mant1 >>= 1;
|
||||
mant1 |= 0x40000000;
|
||||
}
|
||||
exp -= 894; /* exp now in 'excess 128' (Prime) form. */
|
||||
|
||||
mant0 &= 0xffff0000;
|
||||
if (sign) { /* sign bit of mant will be 0 at this point. */
|
||||
mant0 |= 0xffff; /* 2's comp mant1/mant0 pair */
|
||||
mant0 = - mant0;
|
||||
mant1 = ~ mant1;
|
||||
if ( ! mant0)
|
||||
++ mant1; /* mant0==0: have a carry fr. mant0 to mant1. */
|
||||
}
|
||||
/* mant is now a 48 bit signed mantissa (shifted to Prime position) */
|
||||
|
||||
/* *** normalize the number. In most cases, the number will already
|
||||
be normalized. Negative powers of 2 will be shifted once, since
|
||||
they normalize differently. IEEE denormalized numbers can be
|
||||
adjusted at most 2 bits, due to the excess 127 vs. 128 exponent and
|
||||
binary point position differences (cant negate exponent). *** */
|
||||
while (exp && ((~(mant1^(mant1<<1))) & 0x80000000)) {
|
||||
mant1 <<= 1; /* sign and next most significant */
|
||||
if (mant0 & 0x80000000) /* bit are equal: normalize. */
|
||||
mant1 |= 1;
|
||||
mant0 <<= 1;
|
||||
--exp;
|
||||
}
|
||||
mant0 &= 0xffff0000;
|
||||
xlongp[l1] = mant1; /* mant is signed; no sign to 'or' in. */
|
||||
xlongp[l0] = mant0 | exp;
|
||||
}
|
||||
}
|
||||
6
os.c
6
os.c
@@ -125,6 +125,7 @@ os_rdtk$$(short *key, short *info, char *buf, short *buflen, short *code) {
|
||||
}
|
||||
|
||||
os_t1ou(short *charg) {
|
||||
fprintf(stderr," Character is '%o/%d, Prime is '%o/%d, (%c)\n", *charg, *charg, *charg & 0x7f, *charg & 0x7f, *charg & 0x7f);
|
||||
putchar(*charg & 0x7f);
|
||||
fflush(stdout);
|
||||
}
|
||||
@@ -156,8 +157,13 @@ os_timdat(short *userbuf, short *n) {
|
||||
tod = time(NULL);
|
||||
localtime_r(&tod, &tms);
|
||||
strncpy(timbuf.mmddyy,"042105",6);
|
||||
#if 0
|
||||
timbuf.timemins = tms.tm_hour*60 + tms.tm_min;
|
||||
timbuf.timesecs = tms.tm_sec;
|
||||
#else
|
||||
timbuf.timemins = 0;
|
||||
timbuf.timesecs = 0;
|
||||
#endif
|
||||
timbuf.timeticks = 0;
|
||||
timbuf.cpusecs = timbuf.cputicks = timbuf.iosecs = timbuf.ioticks = 0;
|
||||
timbuf.tickspersec = 330;
|
||||
|
||||
Reference in New Issue
Block a user