From d4055d119b8db9937d17d43b6234c10057ba30b2 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Sat, 6 Jan 2018 20:15:55 +0100 Subject: add J1eForth --- j1eforth/j1.c | 186 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 j1eforth/j1.c (limited to 'j1eforth/j1.c') diff --git a/j1eforth/j1.c b/j1eforth/j1.c new file mode 100644 index 0000000..511d7cf --- /dev/null +++ b/j1eforth/j1.c @@ -0,0 +1,186 @@ +#include +#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 pcap_t* handle = NULL; +static void pcapdev_init(void) { + char errbuf[PCAP_ERRBUF_SIZE]; + pcap_if_t* devices; + if (pcap_findalldevs(&devices, errbuf) == -1) { + fprintf(stderr, "error pcap_findalldevs: %s\n", errbuf); + return; + } + pcap_if_t* device; + for(device = devices; device; device = device->next) { + if (device->description) { + printf(" (%s)\n", device->description); + } + else { + fprintf(stderr, "no device\n"); + return; + } + } + device = devices->next->next; + if (NULL == (handle= pcap_open_live(device->name + , 65536, 1, 10 , errbuf))) { + fprintf(stderr, "\nUnable to open the adapter. %s is not supported by WinPcap\n"); + pcap_freealldevs(devices); + return; + } + pcap_freealldevs(devices); +} +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; +} +char eth_poll() { + const u_char* packet; + struct pcap_pkthdr* header; + int res = 0; + while (res == 0) + { + res = pcap_next_ex(handle, &header, &packet); + } + len = (int)header->len; + memcpy(&memory[0x2000], packet, len); + return len; +} +void eth_transmit(void) { + if ((pcap_sendpacket(handle, (char *)(&memory[0x2000]), len) == -1)) + { + printf("sorry send error\n"); + exit(1); + } +} + +static void execute(int entrypoint) +{ + int _pc, _t; + int insn = 0x4000 | entrypoint; // first insn: "call entrypoint" + pcapdev_init(); + 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: _t = (t==0xf008)?eth_poll():(t==0xf001)?1:(t==0xf000)?getch():memory[t>>1]; 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] */ + (t==0xf008)?eth_transmit(): (t==0xf002)?(rsp=0):(t==0xf000)?putch(s):(memory[t>>1]=s); /* ! */ + t = _t; + break; + } + } + pc = _pc; + insn = memory[pc]; + } 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; +} -- cgit v1.2.3