#include #include #include #include #include #if defined(unix) || defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)) #include #include 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<> 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; }