1
0
mirror of https://github.com/aap/pdp6.git synced 2026-01-11 23:53:31 +00:00
aap.pdp6/tools/pdp6common.c
2019-04-09 07:47:01 +02:00

665 lines
13 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <ctype.h>
#include "pdp6common.h"
word fw(hword l, hword r) { return ((word)right(l) << 18) | (word)right(r); }
word point(word pos, word sz, hword p) { return (pos<<30)|(sz<<24)|p; }
hword left(word w) { return (w >> 18) & 0777777; }
hword right(word w) { return w & 0777777; }
word negw(word w) { return (~w + 1) & 0777777777777; }
int isneg(word w) { return !!(w & 0400000000); }
/* write word in rim format */
void
writew(word w, FILE *fp)
{
int j;
w &= 0777777777777;
for(j = 5; j >= 0; j--)
putc(0200 | (w>>j*6)&077, fp);
}
word
readw(FILE *fp)
{
int i, b;
word w;
w = 0;
for(i = 0; i < 6; i++){
cont:
if(b = getc(fp), b == EOF)
return ~0;
if((b & 0200) == 0)
goto cont;
w = (w << 6) | (b & 077);
}
return w;
}
/* write word in backup format. This is what pdp10-ka expects. */
void
writewbak(word w, FILE *fp)
{
putc((w >> 29) & 0177, fp);
putc((w >> 22) & 0177, fp);
putc((w >> 15) & 0177, fp);
putc((w >> 8) & 0177, fp);
putc((w>>1) & 0177 | (w & 1) << 7, fp);
}
word
readwbak(FILE *fp)
{
char buf[5];
if(fread(buf, 1, 5, fp) != 5)
return ~0;
return (word)buf[0] << 29 |
(word)buf[1] << 22 |
(word)buf[2] << 15 |
(word)buf[3] << 8 |
((word)buf[4]&0177) << 1 |
((word)buf[4]&0200) >> 7;
}
static int prevbyte = -1;
static void
flush(FILE *fp)
{
if(prevbyte == 015)
putc(0356, fp);
else if(prevbyte == 0177)
putc(0357, fp);
prevbyte = -1;
}
static void
binword(word w, FILE *fp)
{
flush(fp);
putc(w>>32 & 017 | 0360, fp);
putc(w>>24 & 0377, fp);
putc(w>>16 & 0377, fp);
putc(w>>8 & 0377, fp);
putc(w & 0377, fp);
}
static void
asciiword(word w, FILE *fp)
{
int i;
char b, bytes[5];
bytes[0] = w>>29 & 0177;
bytes[1] = w>>22 & 0177;
bytes[2] = w>>15 & 0177;
bytes[3] = w>>8 & 0177;
bytes[4] = w>>1 & 0177;
for(i = 0; i < 5; i++){
b = bytes[i];
again:
if(prevbyte == 015){
prevbyte = -1;
if(b == 012)
putc(012, fp);
else{
putc(0356, fp);
goto again;
}
}else if(prevbyte == 0177){
prevbyte = -1;
switch(b){
case 7: putc(0177, fp); break;
case 012: putc(0215, fp); break;
case 015: putc(0212, fp); break;
case 0177: putc(0207, fp); break;
default:
if(b <= 0155)
putc(b + 0200, fp);
else{
putc(0357, fp);
goto again;
}
}
}else if(b == 015 || b == 0177)
prevbyte = b;
else if(b == 012)
putc(015, fp);
else
putc(b, fp);
}
}
/* write word in ITS evacuate format. */
void
writewits(word w, FILE *fp)
{
if(w == ~0){
flush(fp);
return;
}
if(w & 1)
binword(w, fp);
else
asciiword(w, fp);
}
/* read word in ITS evacuate format. */
static int leftover = -1;
word
readwits(FILE *fp)
{
#define PUSH(x) w = (w<<7) | ((x) & 0177); bits += 7
int o;
word w;
int bits;
if(fp == NULL || feof(fp)){
leftover = -1;
return ~0;
}
w = 0;
bits = 0;
if(leftover >= 0){
w = leftover;
bits = 7;
leftover = -1;
}
while(bits < 36){
o = getc(fp);
if(o == EOF)
if(bits == 0)
return ~0;
if(o == 012){
PUSH(015);
PUSH(012);
}else if(o == 015){
PUSH(012);
}else if(o <= 0176){
PUSH(o);
}else if(o == 0177){
PUSH(0177);
PUSH(7);
}else if(o == 0207){
PUSH(0177);
PUSH(0177);
}else if(o == 0212){
PUSH(0177);
PUSH(015);
}else if(o == 0215){
PUSH(0177);
PUSH(012);
}else if(o <= 0355){
PUSH(0177);
PUSH(o - 0200);
}else if(o == 0356){
PUSH(015);
}else if(o == 0357){
PUSH(0177);
}else{
if(bits != 0){
fprintf(stderr, "[error in 36-bit file format]\n");
exit(1);
}
w = o & 017;
w = (w << 8) | getc(fp);
w = (w << 8) | getc(fp);
w = (w << 8) | getc(fp);
w = (w << 8) | getc(fp);
bits = 36;
}
if(bits == 35){
w <<= 1;
bits++;
}else if(bits == 42){
leftover = w & 0177;
w >>= 7;
w <<= 1;
}
}
if(w > 0777777777777){
fprintf(stderr, "[error in 36-bit file format (word too large)]\n");
exit(1);
}
return w;
}
/* decompose a double into sign, exponent and mantissa */
void
decompdbl(double d, int *s, word *e, uint64_t *m)
{
uint64_t x;
union {
uint64_t i;
double d;
} u;
u.d = d; x = u.i;
*s = !!(x & 0x8000000000000000);
*e = (x >> 52) & 0x7FF;
*m = x & 0xFFFFFFFFFFFFF;
if(x != 0)
*m |= 0x10000000000000;
}
/* convert double to PDP-6 float */
word
dtopdp(double d)
{
uint64_t x, e, m;
int sign;
word f;
union {
uint64_t i;
double d;
} u;
sign = 0;
if(d < 0.0){
sign = 1;
d *= -1.0;
}
u.d = d; x = u.i;
/* sign is guaranteed to be 0 now */
e = (x >> 52) & 0x7FF;
m = x & 0xFFFFFFFFFFFFF;
e += 128-1023;
m >>= 25;
/* normalize */
if(x != 0){
m >>= 1;
m |= 0400000000;
e += 1;
}else
e = 0;
f = e << 27;
f |= m;
if(sign)
f = -f & 0777777777777;
return f;
}
/* convert PDP-6 float to double */
double
pdptod(word f)
{
uint64_t x, s, e, m;
union {
uint64_t i;
double d;
} u;
s = 0;
if(f & 0400000000000){
f = -f & 0777777777777;
s = 1;
}
e = (f >> 27) & 0377;
m = f & 0777777777;
e += 1023-128;
/* normalize */
if(m != 0){
m &= ~0400000000;
m <<= 1;
e -= 1;
}else
e = 0;
m <<= 25;
x = m;
x |= (e & 0x7FF) << 52;
x |= s << 63;
u.i = x;
return u.d;
}
/* map ascii to radix50/squoze, also map lower to upper case */
char
ascii2rad(char c)
{
static char tab[] = {
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
0, -1, -1, -1, 046, 047, -1, -1,
-1, -1, -1, -1, -1, -1, 045, -1,
001, 002, 003, 004, 005, 006, 007, 010,
011, 012, -1, -1, -1, -1, -1, -1,
-1, 013, 014, 015, 016, 017, 020, 021,
022, 023, 024, 025, 026, 027, 030, 031,
032, 033, 034, 035, 036, 037, 040, 041,
042, 043, 044, -1, -1, -1, -1, -1,
-1, 013, 014, 015, 016, 017, 020, 021,
022, 023, 024, 025, 026, 027, 030, 031,
032, 033, 034, 035, 036, 037, 040, 041,
042, 043, 044, -1, -1, -1, -1, -1,
};
return tab[c&0177];
}
static char rad50tab[] = {
' ', '0', '1', '2', '3', '4', '5', '6',
'7', '8', '9', 'A', 'B', 'C', 'D', 'E',
'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
'V', 'W', 'X', 'Y', 'Z', '.', '$', '%',
0
};
/* map radix50/squoze to ascii */
char
rad2ascii(char c)
{
return rad50tab[c%050];
}
int
israd50(char c)
{
return strchr(rad50tab, toupper(c)) != NULL;
}
/* convert ascii string + code to radix50 */
word
rad50(int n, const char *s)
{
word r;
char c;
int i;
r = 0;
i = 0;
for(i = 0; i < 6 && *s; i++){
c = ascii2rad(*s++);
if(c < 0)
break;
r = r*050 + c;
}
for(; i < 6; i++)
r = r*050;
r |= (word)(n&074) << 30;
return r;
}
/* get null-terminated ascii string and code from radix50 */
int
unrad50(word r, char *s)
{
int i;
int n;
n = r>>30 & 074;
r &= ~0740000000000;
s += 6;
*s-- = '\0';
for(i = 0; i < 6; i++){
*s-- = rad2ascii(r%050);
r /= 050;
}
return n;
}
/* map ascii to sixbit, also map lower to upper case */
char
ascii2sixbit(char c)
{
static char tab[] = {
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
000, 001, 002, 003, 004, 005, 006, 007,
010, 011, 012, 013, 014, 015, 016, 017,
020, 021, 022, 023, 024, 025, 026, 027,
030, 031, 032, 033, 034, 035, 036, 037,
040, 041, 042, 043, 044, 045, 046, 047,
050, 051, 052, 053, 054, 055, 056, 057,
060, 061, 062, 063, 064, 065, 066, 067,
070, 071, 072, 073, 074, 075, 076, 077,
040, 041, 042, 043, 044, 045, 046, 047,
050, 051, 052, 053, 054, 055, 056, 057,
060, 061, 062, 063, 064, 065, 066, 067,
070, 071, 072, 073, 074, 075, 076, 077,
};
return tab[c&0177];
}
static char sixbittab[] = {
' ', '!', '"', '#', '$', '%', '&', '\'',
'(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', ':', ';', '<', '=', '>', '?',
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
0
};
/* map sixbit to ascii */
char
sixbit2ascii(char c)
{
return sixbittab[c&077];
}
int
issixbit(char c)
{
return strchr(sixbittab, toupper(c)) != NULL;
}
/* convert ascii string to sixbit */
word
sixbit(const char *s)
{
word sx;
char c;
int i;
sx = 0;
i = 0;
for(i = 0; i < 6 && *s; i++){
c = ascii2sixbit(*s++);
if(c < 0)
break;
sx = (sx<<6) + c;
}
sx <<= 6*(6-i);
return sx;
}
/* get null-terminated ascii string from sixbit */
void
unsixbit(word sx, char *s)
{
int i;
s += 6;
*s-- = '\0';
for(i = 0; i < 6; i++){
*s-- = sixbit2ascii(sx&077);
sx >>= 6;
}
}
char *mnemonics[0700] = {
"UUO00", "UUO01", "UUO02", "UUO03",
"UUO04", "UUO05", "UUO06", "UUO07",
"UUO10", "UUO11", "UUO12", "UUO13",
"UUO14", "UUO15", "UUO16", "UUO17",
"UUO20", "UUO21", "UUO22", "UUO23",
"UUO24", "UUO25", "UUO26", "UUO27",
"UUO30", "UUO31", "UUO32", "UUO33",
"UUO34", "UUO35", "UUO36", "UUO37",
"UUO40", "UUO41", "UUO42", "UUO43",
"UUO44", "UUO45", "UUO46", "UUO47",
"UUO50", "UUO51", "UUO52", "UUO53",
"UUO54", "UUO55", "UUO56", "UUO57",
"UUO60", "UUO61", "UUO62", "UUO63",
"UUO64", "UUO65", "UUO66", "UUO67",
"UUO70", "UUO71", "UUO72", "UUO73",
"UUO74", "UUO75", "UUO76", "UUO77",
"XX100", "XX101", "XX102", "XX103",
"XX104", "XX105", "XX106", "XX107",
"XX110", "XX111", "XX112", "XX113",
"XX114", "XX115", "XX116", "XX117",
"XX120", "XX121", "XX122", "XX123",
"XX124", "XX125", "XX126", "XX127",
"XX130", "XX131", "FSC", "CAO",
"LDCI", "LDC", "DPCI", "DPC",
"FAD", "FADL", "FADM", "FADB",
"FADR", "FADLR", "FADMR", "FADBR",
"FSB", "FSBL", "FSBM", "FSBB",
"FSBR", "FSBLR", "FSBMR", "FSBBR",
"FMP", "FMPL", "FMPM", "FMPB",
"FMPR", "FMPLR", "FMPMR", "FMPBR",
"FDV", "FDVL", "FDVM", "FDVB",
"FDVR", "FDVLR", "FDVMR", "FDVBR",
"MOVE", "MOVEI", "MOVEM", "MOVES",
"MOVS", "MOVSI", "MOVSM", "MOVSS",
"MOVN", "MOVNI", "MOVNM", "MOVNS",
"MOVM", "MOVMI", "MOVMM", "MOVMS",
"IMUL", "IMULI", "IMULM", "IMULB",
"MUL", "MULI", "MULM", "MULB",
"IDIV", "IDIVI", "IDIVM", "IDIVB",
"DIV", "DIVI", "DIVM", "DIVB",
"ASH", "ROT", "LSH", "XX243",
"ASHC", "ROTC", "LSHC", "XX247",
"EXCH", "BLT", "AOBJP", "AOBJN",
"JRST", "JFCL", "XCT", "XX257",
"PUSHJ", "PUSH", "POP", "POPJ",
"JSR", "JSP", "JSA", "JRA",
"ADD", "ADDI", "ADDM", "ADDB",
"SUB", "SUBI", "SUBM", "SUBB",
"CAI", "CAIL", "CAIE", "CAILE",
"CAIA", "CAIGE", "CAIN", "CAIG",
"CAM", "CAML", "CAME", "CAMLE",
"CAMA", "CAMGE", "CAMN", "CAMG",
"JUMP", "JUMPL", "JUMPE", "JUMPLE",
"JUMPA", "JUMPGE", "JUMPN", "JUMPG",
"SKIP", "SKIPL", "SKIPE", "SKIPLE",
"SKIPA", "SKIPGE", "SKIPN", "SKIPG",
"AOJ", "AOJL", "AOJE", "AOJLE",
"AOJA", "AOJGE", "AOJN", "AOJG",
"AOS", "AOSL", "AOSE", "AOSLE",
"AOSA", "AOSGE", "AOSN", "AOSG",
"SOJ", "SOJL", "SOJE", "SOJLE",
"SOJA", "SOJGE", "SOJN", "SOJG",
"SOS", "SOSL", "SOSE", "SOSLE",
"SOSA", "SOSGE", "SOSN", "SOSG",
"SETZ", "SETZI", "SETZM", "SETZB",
"AND", "ANDI", "ANDM", "ANDB",
"ANDCA", "ANDCAI", "ANDCAM", "ANDCAB",
"SETM", "SETMI", "SETMM", "SETMB",
"ANDCM", "ANDCMI", "ANDCMM", "ANDCMB",
"SETA", "SETAI", "SETAM", "SETAB",
"XOR", "XORI", "XORM", "XORB",
"IOR", "IORI", "IORM", "IORB",
"ANDCB", "ANDCBI", "ANDCBM", "ANDCBB",
"EQV", "EQVI", "EQVM", "EQVB",
"SETCA", "SETCAI", "SETCAM", "SETCAB",
"ORCA", "ORCAI", "ORCAM", "ORCAB",
"SETCM", "SETCMI", "SETCMM", "SETCMB",
"ORCM", "ORCMI", "ORCMM", "ORCMB",
"ORCB", "ORCBI", "ORCBM", "ORCBB",
"SETO", "SETOI", "SETOM", "SETOB",
"HLL", "HLLI", "HLLM", "HLLS",
"HRL", "HRLI", "HRLM", "HRLS",
"HLLZ", "HLLZI", "HLLZM", "HLLZS",
"HRLZ", "HRLZI", "HRLZM", "HRLZS",
"HLLO", "HLLOI", "HLLOM", "HLLOS",
"HRLO", "HRLOI", "HRLOM", "HRLOS",
"HLLE", "HLLEI", "HLLEM", "HLLES",
"HRLE", "HRLEI", "HRLEM", "HRLES",
"HRR", "HRRI", "HRRM", "HRRS",
"HLR", "HLRI", "HLRM", "HLRS",
"HRRZ", "HRRZI", "HRRZM", "HRRZS",
"HLRZ", "HLRZI", "HLRZM", "HLRZS",
"HRRO", "HRROI", "HRROM", "HRROS",
"HLRO", "HLROI", "HLROM", "HLROS",
"HRRE", "HRREI", "HRREM", "HRRES",
"HLRE", "HLREI", "HLREM", "HLRES",
"TRN", "TLN", "TRNE", "TLNE",
"TRNA", "TLNA", "TRNN", "TLNN",
"TDN", "TSN", "TDNE", "TSNE",
"TDNA", "TSNA", "TDNN", "TSNN",
"TRZ", "TLZ", "TRZE", "TLZE",
"TRZA", "TLZA", "TRZN", "TLZN",
"TDZ", "TSZ", "TDZE", "TSZE",
"TDZA", "TSZA", "TDZN", "TSZN",
"TRC", "TLC", "TRCE", "TLCE",
"TRCA", "TLCA", "TRCN", "TLCN",
"TDC", "TSC", "TDCE", "TSCE",
"TDCA", "TSCA", "TDCN", "TSCN",
"TRO", "TLO", "TROE", "TLOE",
"TROA", "TLOA", "TRON", "TLON",
"TDO", "TSO", "TDOE", "TSOE",
"TDOA", "TSOA", "TDON", "TSON",
};
char *iomnemonics[] = {
"BLKI",
"DATAI",
"BLKO",
"DATAO",
"CONO",
"CONI",
"CONSZ",
"CONSO"
};
char*
disasm(word w)
{
static char s[100];
char *p;
hword i, x, y;
hword ac, dev;
hword op;
hword f;
y = w & 0777777;
x = (w >> 18) & 017;
i = (w >> 22) & 1;
ac = (w >> 23) & 017;
op = (w >> 27) & 0777;
dev = (w >> 24) & 0774;
f = ac & 07;
p = s;
if((op & 0700) == 0700){
p += sprintf(p, "%s ", iomnemonics[f]);
p += sprintf(p, "%o,", dev);
}else{
p += sprintf(p, "%s ", mnemonics[op]);
p += sprintf(p, "%o,", ac);
}
if(i)
p += sprintf(p, "@");
p += sprintf(p, "%o", y);
if(x)
p += sprintf(p, "(%o)", x);
return s;
}