bcpl: tidy up problems with Z80 from changes, add split int/linker
authorAlan Cox <alan@linux.intel.com>
Sat, 3 Dec 2016 21:03:38 +0000 (21:03 +0000)
committerAlan Cox <alan@linux.intel.com>
Sat, 3 Dec 2016 21:03:38 +0000 (21:03 +0000)
Need to merge the split one and the paging logic

Applications/BCPL/Makefile
Applications/BCPL/blibv.c [new file with mode: 0644]
Applications/BCPL/icex.c [new file with mode: 0644]
Applications/BCPL/icint.c
Applications/BCPL/icintv.c [new file with mode: 0644]
Applications/BCPL/iclink.c [new file with mode: 0644]

index 283daa8..19e3d55 100644 (file)
@@ -6,23 +6,21 @@ FCC = fcc
 FCCOPTS = -O2 #--nostdio
 PLATFORM =
 
-SRC = icint.c blib.c
+SRC = icint.c iclink.c icex.c blib.c icintv.c blibv.c
 OBJ = $(SRC:.c=.rel) blibv.o icintv.o
 
 .SUFFIXES: .c .rel
 
-APPS = icint icintv run-time.i codegen.i b.i
+APPS = icint icintv icex iclink run-time.i codegen.i b.i
 
 all: $(APPS) sizes
 
-.c.rel:
-       $(FCC) $(PLATFORM) $(FCCOPTS) -c $<
+blibv.rel:blib.rel
 
-icintv.rel: icint.v
-       $(FCC) $(PLATFORM) $(FCCOPTS) -c icint.c
+icintv.rel:icint.rel
 
-blibv.rel: blib.c
-       $(FCC) $(PLATFORM) $(FCCOPTS) -c blib.c
+.c.rel:
+       $(FCC) $(PLATFORM) $(FCCOPTS) -c $<
 
 icint:  icint.rel blib.rel
        $(FCC) $(PLATFORM) $(FCCOPTS) -o $@ icint.rel  blib.rel
@@ -30,6 +28,12 @@ icint:  icint.rel blib.rel
 icintv: icintv.rel blibv.rel
        $(FCC) $(PLATFORM) $(FCCOPTS) -o $@ icintv.rel blibv.rel
 
+iclink:        iclink.rel blib.rel
+       $(FCC) $(PLATFORM) $(FCCOPTS) -o $@ icex.rel  blib.rel
+
+icex:  icex.rel blib.rel
+       $(FCC) --nostdio $(PLATFORM) $(FCCOPTS) -o $@ icex.rel  blib.rel
+
 sizes: $(APPS)
        ls -l $(APPS) > size.report
 
diff --git a/Applications/BCPL/blibv.c b/Applications/BCPL/blibv.c
new file mode 100644 (file)
index 0000000..75e522e
--- /dev/null
@@ -0,0 +1,2 @@
+#define PAGEDMEM
+#include "blib.c"
diff --git a/Applications/BCPL/icex.c b/Applications/BCPL/icex.c
new file mode 100644 (file)
index 0000000..bb33e88
--- /dev/null
@@ -0,0 +1,209 @@
+/* Copyright (c) 2004 Robert Nordier.  All rights reserved. */
+
+/* $Id: icint.c,v 1.6 2004/12/11 12:01:53 rn Exp $ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "blib.h"
+
+#define FALSE 0
+#define TRUE 1
+
+#define FSHIFT 13
+#define IBIT 010000
+#define PBIT 04000
+#define GBIT 02000
+#define DBIT 01000
+#define ABITS 0777
+#define WORDSIZE 16
+#define BYTESIZE 8
+
+#define LIG1 0012001
+#define K2 0140002
+#define X22 0160026
+
+#if 1
+#define itrace(x)
+#define itrace2(x,y)
+#define itrace3(x,y,z)
+#define itrace4(x,y,z, a)
+#else
+#define itrace(x)              fprintf(stderr, x)
+#define itrace2(x,y)           fprintf(stderr, x, y)
+#define itrace3(x,y,z)         fprintf(stderr, x, y, z)
+#define itrace4(x,y,z,a)       fprintf(stderr, x, y, z, a)
+#endif
+
+#define VSIZE (20 * 1024)
+uint16_t M[VSIZE];
+int fp;
+
+static uint16_t G;
+static uint16_t P;
+static int Ch;
+static int16_t *Labv;
+static int Cp;
+static uint16_t A;
+static uint16_t B;
+static uint16_t C;
+static uint16_t D;
+static uint16_t W;
+
+static void stw(uint16_t);
+static void stc(uint16_t);
+static void rch(void);
+static int16_t rdn(void);
+static int16_t interpret(void);
+static int16_t icgetbyte(uint16_t, uint16_t);
+static void icputbyte(uint16_t, uint16_t, uint16_t);
+
+static void writes(const char *p) {
+ write(1, p, strlen(p));
+}
+
+#ifdef __linux__
+static const char *_itoa(int v)
+{
+ static char buf[16];
+ sprintf(buf, "%d", v);
+ return buf;
+}
+#endif
+
+
+static int16_t interpret(void)
+{
+fetch:
+    itrace2("%d = ", C);
+
+    if (C >= VSIZE || P >= VSIZE || C == 0) {
+     writes("\nFAULT ");
+     writes(_itoa(C));
+     writes(" ");
+     writes(_itoa(P));
+     writes("\n");
+     exit(1);
+    }
+    W = M[C++];
+    if ((W & DBIT) == 0)
+        D = W & ABITS;
+    else
+        D = M[C++];
+
+    itrace3("OP %d, D %d ", W >> FSHIFT, D);
+
+    if ((W & PBIT) != 0) { D += P; itrace("+P"); }
+    if ((W & GBIT) != 0) { D += G; itrace("+G"); }
+    if ((W & IBIT) != 0) { D = M[D]; itrace("[]"); }
+    
+    itrace4("->%d [A%dB%d]\n", D, A, B);
+
+    switch (W >> FSHIFT) {
+    error: default: writes("\nINTCODE ERROR AT C = ");
+                    writes(_itoa(C-1));
+                    writes("\n");
+        return -1;
+    case 0: B = A; A = D; goto fetch;
+    case 1: M[D] = A; goto fetch;
+    case 2: A = A + D; goto fetch;
+    case 3: C = D; goto fetch;
+    case 4: A = !A;
+    case 5: if (!A) C = D; goto fetch;
+    case 6: D += P;
+        M[D] = P; M[D + 1] = C;
+        P = D; C = A;
+        goto fetch;
+    case 7: switch (D) {
+        default: goto error;
+        case 1: A = M[A]; goto fetch;
+        case 2: A = -A; goto fetch;
+        case 3: A = ~A; goto fetch;
+        case 4: C = M[P + 1];
+            P = M[P];
+            goto fetch;
+        case 5: A = (int16_t)B * (int16_t)A; goto fetch;
+        case 6: A = (int16_t)B / (int16_t)A; goto fetch;
+        case 7: A = (int16_t)B % (int16_t)A; goto fetch;
+        case 8: A = (int16_t)B + (int16_t)A; goto fetch;
+        case 9: A = (int16_t)B - (int16_t)A; goto fetch;
+        case 10: A = B == A ? ~0 : 0; goto fetch;
+        case 11: A = B != A ? ~0 : 0; goto fetch;
+        case 12: A = (int16_t)B < (int16_t)A  ? ~0 : 0; goto fetch;
+        case 13: A = (int16_t)B >= (int16_t)A ? ~0 : 0; goto fetch;
+        case 14: A = (int16_t)B > (int16_t)A ? ~0 : 0; goto fetch;
+        case 15: A = (int16_t)B <= (int16_t)A ? ~0 : 0; goto fetch;
+        case 16: A = B << A; goto fetch;
+        case 17: A = B >> A; goto fetch;
+        case 18: A = B & A; goto fetch;
+        case 19: A = B | A; goto fetch;
+        case 20: A = B ^ A; goto fetch;
+        case 21: A = B ^ ~A; goto fetch;
+        case 22: return 0;
+        case 23: B = M[C]; D = M[C + 1];
+            while (B != 0) {
+                B--; C += 2;
+                if (A == M[C]) { D = M[C + 1]; break; }
+            }
+            C = D;
+            goto fetch;
+
+        case 24: selectinput(A); goto fetch;
+        case 25: selectoutput(A); goto fetch;
+        case 26: A = rdch(); goto fetch;
+        case 27: wrch(A); goto fetch;
+        case 28: A = findinput(A); goto fetch;
+        case 29: A = findoutput(A); goto fetch;
+        case 30: return A;
+        case 31: A = M[P]; goto fetch;
+        case 32: P = A; C = B; goto fetch;
+        case 33: endread(); goto fetch;
+        case 34: endwrite(); goto fetch;
+        case 35: D = P + B + 1;
+                 M[D] = M[P];
+                 M[D + 1] = M[P + 1];
+                 M[D + 2] = P;
+                 M[D + 3] = B;
+                 P = D;
+                 C = A;
+                 goto fetch;
+        case 36: A = getbyte(A, B); goto fetch;
+        case 37: putbyte(A, B, M[P + 4]); goto fetch;
+        case 38: A = input(); goto fetch;
+        case 39: A = output(); goto fetch;
+        }
+    }
+}
+
+static uint16_t hdr[5];
+
+int main(int argc, char *argv[])
+{
+
+    if (argc != 2) {
+        write(2, "usage: icex file\n",18);
+        return 1;
+    }
+    fp = open(argv[1], O_RDONLY);
+    if (fp == -1) {
+        perror(argv[1]);
+        return 0;
+    }
+    read(fp, hdr, sizeof(hdr));
+    
+    G = hdr[1];
+    C = hdr[2];
+    P = hdr[3];
+
+    if (P >= 16384) {
+     read(fp, M, 32766);
+     read(fp, M + 16383, P - 32766);
+    } else 
+     read(fp, M, P * sizeof(uint16_t));
+    close(fp);
+    initio();
+    return interpret();
+}
index 6c43494..1352c57 100644 (file)
@@ -141,12 +141,10 @@ int translations = 0;
 int swaps = 0;
 int pfp;
 
-static int pagein(uint16_t page);
-
 /* Given a virtual page number that is not mapped, map it. Take care of
    any disk read/write.
 */
-static int
+static void
 pagein(uint16_t page)
 {
     int i;
@@ -564,6 +562,11 @@ fetch:
 
 int main(int argc, char *argv[])
 {
+#ifdef PAGEDMEM
+    int i, status;
+    char * buf;
+#endif
+
     if (argc != 2) {
         write(2, "usage: icint file\n",18);
         return 1;
@@ -575,9 +578,6 @@ int main(int argc, char *argv[])
     }
 
 #ifdef PAGEDMEM
-    int i, status;
-    char * buf;
-
     for (i=0; i<PBLKS; i++) {
         pmap[i] = -1; /* start with no physical buffers assigned */
     }
@@ -590,12 +590,12 @@ int main(int argc, char *argv[])
     }
 
     /* create page file */
-    pfp = open("icintv.pag", O_RDWR, 0600);
+    pfp = open("icintv.pag", O_RDWR|O_CREAT|O_TRUNC, 0600);
     if (pfp == -1) {
         perror("icintv.pag");
         return 0;
     }
-    buf = (char *)pgvec;
+    buf = (char *)M;
     for (i=0; i<VBLKS; i++) {
         if (2*BLKSIZE != write(pfp, buf, 2*BLKSIZE)) {
             perror("creating empty page file");
diff --git a/Applications/BCPL/icintv.c b/Applications/BCPL/icintv.c
new file mode 100644 (file)
index 0000000..a3c20ba
--- /dev/null
@@ -0,0 +1,2 @@
+#define PAGEDMEM
+#include "icint.c"
\ No newline at end of file
diff --git a/Applications/BCPL/iclink.c b/Applications/BCPL/iclink.c
new file mode 100644 (file)
index 0000000..ee817ba
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ *     Linker for BCPL modules. We pre-link to keep the interpreter size
+ *     much tighter and to up the speed        
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "blib.h"
+
+#define VSIZE 15000
+#define MGLOB 1
+#define MPROG 402
+
+#define FALSE 0
+#define TRUE 1
+
+#define FSHIFT 13
+#define IBIT 010000
+#define PBIT 04000
+#define GBIT 02000
+#define DBIT 01000
+#define ABITS 0777
+#define WORDSIZE 16
+#define BYTESIZE 8
+
+#define LIG1 0012001
+#define K2 0140002
+#define X22 0160026
+
+#if 1
+#define itrace(x)
+#define itrace2(x,y)
+#define itrace3(x,y,z)
+#define itrace4(x,y,z, a)
+#else
+#define itrace(x)              fprintf(stderr, x)
+#define itrace2(x,y)           fprintf(stderr, x, y)
+#define itrace3(x,y,z)         fprintf(stderr, x, y, z)
+#define itrace4(x,y,z,a)       fprintf(stderr, x, y, z, a)
+#endif
+
+uint16_t *M;
+int fp;
+
+static uint16_t G;
+static uint16_t P;
+static int Ch;
+static int16_t *Labv;
+static int Cp;
+static uint16_t A;
+static uint16_t B;
+static uint16_t C;
+static uint16_t D;
+static uint16_t W;
+
+static void assemble(void);
+static void stw(uint16_t);
+static void stc(uint16_t);
+static void rch(void);
+static int16_t rdn(void);
+static void setlab(int);
+static void labref(int16_t, uint16_t);
+static int16_t interpret(void);
+static int16_t icgetbyte(uint16_t, uint16_t);
+static void icputbyte(uint16_t, uint16_t, uint16_t);
+
+static void writes(const char *p) {
+ write(1, p, strlen(p));
+}
+
+#ifdef __linux__
+static const char *_itoa(int v)
+{
+ static char buf[16];
+ sprintf(buf, "%d", v);
+ return buf;
+}
+#endif
+
+static void
+assemble(void)
+{
+    int16_t v[501];
+    uint16_t f = 0;
+    uint16_t i;
+
+    Labv = v;
+clear:
+    for (i = 0; i <= 500; i++) Labv[i] = 0;
+    Cp = 0;
+next:
+    rch();
+sw:
+    switch (Ch) {
+
+    default: if (Ch == EOF) return;
+        printf("\nBAD CH %c AT P = %d\n", Ch, P);
+        goto next;
+
+    case '0': case '1': case '2': case '3': case '4':
+    case '5': case '6': case '7': case '8': case '9':
+        setlab(rdn());
+        Cp = 0;
+        goto sw;
+
+    case '$': case ' ': case '\n': goto next;
+
+    case 'L': f = 0; break;
+    case 'S': f = 1; break;
+    case 'A': f = 2; break;
+    case 'J': f = 3; break;
+    case 'T': f = 4; break;
+    case 'F': f = 5; break;
+    case 'K': f = 6; break;
+    case 'X': f = 7; break;
+
+    case 'C': rch(); stc(rdn()); goto sw;
+
+    case 'D': rch();
+        if (Ch == 'L') {
+            rch();
+            stw(0);
+            labref(rdn(), P - 1);
+        } else
+            stw(rdn());
+        goto sw;
+
+    case 'G': rch();
+        A = rdn() + G;
+        if (Ch == 'L') rch();
+        else printf("\nBAD CODE AT P = %d\n", P);
+        M[A] = 0;
+        labref(rdn(), A);
+        goto sw;
+    case 'Z': for (i = 0; i <= 500; i++)
+        if (Labv[i] > 0) printf("L%d UNSET\n", i);
+        goto clear;
+    }
+    W = f << FSHIFT;
+    rch();
+    if (Ch == 'I') { W = W + IBIT; rch(); }
+    if (Ch == 'P') { W = W + PBIT; rch(); }
+    if (Ch == 'G') { W = W + GBIT; rch(); }
+
+    if (Ch == 'L') {
+        rch();
+        stw(W + DBIT);
+        stw(0);
+        labref(rdn(), P - 1);
+    } else {
+        uint16_t a = rdn();
+        if ((a & ABITS) == a)
+            stw(W + a);
+        else { stw(W + DBIT); stw(a); }
+    }
+    goto sw;
+}
+
+static void
+stw(uint16_t w)
+{
+    if (P >= VSIZE) {
+     printf("\nProgram code too large\n");
+     exit(1);
+    }
+    M[P++] = w;
+    Cp = 0;
+}
+
+static void
+stc(uint16_t c)
+{
+    if (Cp == 0) { stw(0); Cp = WORDSIZE; }
+    Cp -= BYTESIZE;
+    M[P - 1] += c << Cp;
+}
+
+static char buf[128];
+static char *rcp = buf;
+static char *rce = buf;
+
+static int16_t rchget(void)
+{
+ rcp = buf;
+ rce = buf + read(fp, buf, 128);
+ if (rce <= rcp)
+  return -1;
+ return 0;
+}
+
+static void
+rch(void)
+{
+    /* FIXME: blows up on EOF */
+    for (;;) {
+        if (rcp == rce)
+          if (rchget()) {
+           Ch = -1;
+           return;
+          }
+        Ch = *rcp++;
+        if (Ch != '/') return;
+        do {
+         if (rcp == rce)
+          if (rchget()) {
+            Ch = -1;
+            return;
+          }
+          Ch = *rcp++;
+       } while (Ch != '\n');
+    }
+}
+
+static int16_t
+rdn(void)
+{
+    int a = 0, b = FALSE;
+    if (Ch == '-') { b = TRUE; rch(); }
+    while ('0' <= Ch && Ch <= '9') { a = 10 * a + Ch - '0'; rch(); }
+    if (b) a = -a;
+    return a;
+}
+
+static void
+setlab(int n)
+{
+    int16_t k = Labv[n];
+    if (k < 0) printf("L%d ALREADY SET TO %d AT P = %d\n", n, -k, P);
+    while (k > 0) {
+       uint16_t kp = k;
+        uint16_t nv = M[kp];
+        /* Removing this debug check breaks under SDCC - FIXME check if
+           compiler bug ! */
+        if (n == 9499)fprintf(stderr, "setlab %d to %d\n", (unsigned int)kp, (unsigned int)P);
+        M[kp] = P;
+        k = nv;
+    }
+    Labv[n] = -P;
+}
+
+static void
+labref(int16_t n, uint16_t a)
+{
+    int16_t k = Labv[n];
+//    if (n == 499)
+//     fprintf(stderr, "Labref %d = %d\n", n, (int)k);
+    if (k < 0) k = -k; else Labv[n] = a;
+//    if (n == 499)
+//    fprintf(stderr, "Mod %d by %d from %d\n", (unsigned int)a, (int)k, (unsigned int)M[a]);
+    M[a] += k;
+}
+
+uint16_t pgvec[VSIZE];
+
+static uint16_t hdr[5] = { 0xBC0D, 0, 0, 0, 0};
+
+int main(int argc, char *argv[])
+{
+
+    if (argc != 3) {
+        write(2, "usage: iclink cintcode binary\n",30);
+        return 1;
+    }
+    fp = open(argv[1], O_RDONLY);
+    if (fp == -1) {
+        perror(argv[1]);
+        return 1;
+    }
+    M = pgvec;
+    G = MGLOB;
+    P = MPROG;
+    M[P++] = LIG1;
+    M[P++] = K2;
+    M[P++] = X22;
+    assemble();
+    close(fp);
+    
+    fp = open(argv[2], O_WRONLY|O_CREAT|O_TRUNC);
+    if (fp == -1 ) {
+     perror(argv[2]);
+     return 1;
+    }
+    hdr[1] = MGLOB;
+    hdr[2] = MPROG;
+    hdr[3] = P;
+    write(fp, hdr, sizeof(hdr));
+    if (P >= 16384) {
+     write(fp, M, 32766);
+     M+= 16383;
+     P-= 16383;
+    }
+    write(fp, M, P * sizeof(uint16_t));
+    close(fp);
+    return 0;
+}