aboutsummaryrefslogtreecommitdiff
path: root/docs/j1eforth/j1.c
diff options
context:
space:
mode:
Diffstat (limited to 'docs/j1eforth/j1.c')
-rw-r--r--docs/j1eforth/j1.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/docs/j1eforth/j1.c b/docs/j1eforth/j1.c
new file mode 100644
index 0000000..926adb5
--- /dev/null
+++ b/docs/j1eforth/j1.c
@@ -0,0 +1,162 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/stat.h>
+#if defined(unix) || defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))
+#include <unistd.h>
+#include <termios.h>
+int getch(void) { /* reads from keypress, doesn't echo */
+ struct termios oldattr, newattr;
+ int ch;
+ tcgetattr( STDIN_FILENO, &oldattr );
+ newattr = oldattr;
+ // newattr.c_iflag &= ~( ICRNL );
+ newattr.c_lflag &= ~( ICANON | ECHO );
+ tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
+ ch = getchar();
+ tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
+ // printf("%d\n", ch);
+ if(ch==0x1b) exit(0);
+ return ch==127 ? 8 : ch;
+}
+int putch(int c) { /* output character to sstdout & flush */
+ int res=putchar(c);
+ fflush(stdout);
+ return res;
+}
+#endif
+int len = 0;
+static unsigned short t;
+static unsigned short s;
+static unsigned short d[0x20]; /* data stack */
+static unsigned short r[0x20]; /* return stack */
+static unsigned short pc; /* program counter, counts cells */
+static unsigned char dsp, rsp; /* point to top entry */
+static unsigned short* memory; /* ram */
+static int sx[4] = { 0, 1, -2, -1 }; /* 2-bit sign extension */
+
+static void push(int v) // push v on the data stack
+{
+ dsp = 0x1f & (dsp + 1);
+ d[dsp] = t;
+ t = v;
+}
+
+static int pop(void) // pop value from the data stack and return it
+{
+ int v = t;
+ t = d[dsp];
+ dsp = 0x1f & (dsp - 1);
+ return v;
+}
+
+static void execute(int entrypoint)
+{
+ int i = 0;
+ int j = 0;
+ int _pc, _t;
+ int insn = 0x4000 | entrypoint; // first insn: "call entrypoint"
+ do {
+ _pc = pc + 1;
+ if (insn & 0x8000) { // literal
+ push(insn & 0x7fff);
+ } else {
+ int target = insn & 0x1fff;
+ switch (insn >> 13) {
+ case 0: // jump
+ _pc = target;
+ break;
+ case 1: // conditional jump
+ if (pop() == 0)
+ _pc = target;
+ break;
+ case 2: // call
+ rsp = 31 & (rsp + 1);
+ r[rsp] = _pc << 1;
+ _pc = target;
+ break;
+ case 3: // alu
+ if (insn & 0x1000) {/* r->pc */
+ _pc = r[rsp] >> 1;
+ }
+ s = d[dsp];
+ switch ((insn >> 8) & 0xf) {
+ case 0: _t = t; break; /* noop */
+ case 1: _t = s; break; /* copy */
+ case 2: _t = t+s; break; /* + */
+ case 3: _t = t&s; break; /* and */
+ case 4: _t = t|s; break; /* or */
+ case 5: _t = t^s; break; /* xor */
+ case 6: _t = ~t; break; /* invert */
+ case 7: _t = -(t==s); break; /* = */
+ case 8: _t = -((signed short)s < (signed short)t); break; /* < */
+ case 9: _t = s>>t; break; /* rshift */
+ case 0xa: _t = t-1; break; /* 1- */
+ case 0xb: _t = r[rsp]; break; /* r@ */
+ case 0xc: switch (t) {
+ case 0x7001: _t = 1; break;
+ case 0x7000: _t = getch(); break;
+ default: _t = memory[t>>1]; break;
+ }
+ break; /* @ */
+ case 0xd: _t = s<<t; break; /* lshift */
+ case 0xe: _t = (rsp<<8) + dsp; break; /* dsp */
+ case 0xf: _t = -(s<t); break; /* u< */
+ }
+ dsp = 31 & (dsp + sx[insn & 3]); /* dstack+- */
+ rsp = 31 & (rsp + sx[(insn >> 2) & 3]); /* rstack+- */
+ if (insn & 0x80) /* t->s */
+ d[dsp] = t;
+ if (insn & 0x40) /* t->r */
+ r[rsp] = t;
+ if (insn & 0x20) /* s->[t] */
+ switch (t) {
+ case 0x7002: rsp = 0; break;
+ case 0x7000: putch(s); break;
+ default: memory[t>>1]=s; break; /* ! */
+ }
+ t = _t;
+ break;
+ }
+ }
+ pc = _pc;
+ insn = memory[pc];
+#if DEBUG
+ printf("%d: pc: %0.4x; sp: %0.4x\n", i, pc, t);
+ printf("\td:");
+ for (j = 0; j < dsp; j++) {
+ printf(" %0.4x", d[j]);
+ }
+ printf("\n\tr:");
+ for (j = 0; j < rsp; j++) {
+ printf(" %0.4x", r[j]);
+ }
+ printf("\n");
+#endif
+ i++;
+ } while (1);
+}
+/* end of cpu */
+
+/* start of i/o demo */
+
+
+int main(int argc , char *argv[])
+{
+ unsigned short m[0x4000]; /* 32kb or RAM */
+ FILE *f = fopen("j1.bin", "rb");
+ fread(m, 0x2000, sizeof(m[0]), f); /* 0kb - 16kb data and code */
+ fclose(f);
+ if (argc>1) { // program name is counted as one
+ struct stat st;
+ f = fopen(argv[1], "r");
+ stat(argv[1], &st);
+ (&m[0x2000])[0] = st.st_size; /* 16kb - 32kb memory mapped i/o */
+ fread(&m[0x2001], 0x2000, sizeof(m[0]), f);
+ fclose(f);
+ }
+ memory = m;
+ execute(0x00);
+ return 0;
+}