/*************************************************************** crc's _ _ (_) | ___ | | |/ _ \ a tiny virtual computer | | | (_) | 64kw RAM, 32-bit, Dual Stack, MISC |_|_|\___/ ilo.c (c) charles childers **************************************************************/ /* cc -lpthread ilo-pthread.c -o ilo */ #include #include #include #include #include int ip, sp, rp, data[33], address[257], memory[65536]; int a, b, t, fp, block, buffer, src, dest, len; char *blocks, *rom, iob[2]; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; #define T data[sp] #define N data[sp-1] #define R address[rp] #define V void int pop() { return data[(--sp) + 1]; } V push(int value) { data[++sp] = value; } V prepare_vm() { ip = sp = rp = 0; } V load_image() { fp = open(rom, O_RDONLY, 0666); if (!fp) { return; }; read(fp, &memory, 65536 * 4); close(fp); prepare_vm(); } V save_image() { fp = open(rom, O_WRONLY, 0666); write(fp, &memory, 65536 * 4); close(fp); } V read_block() { buffer = pop(); block = pop(); fp = open(blocks, O_RDONLY, 0666); lseek(fp, 4096 * block, SEEK_SET); read(fp, memory + buffer, 4096); close(fp); } V write_block() { buffer = pop(); block = pop(); fp = open(blocks, O_WRONLY, 0666); lseek(fp, 4096 * block, SEEK_SET); write(fp, memory + buffer, 4096); close(fp); } V li() { ip++; push(memory[ip]); } V du() { push(T); } V dr() { data[sp] = 0; sp--; } V sw() { a = T; T = N; N = a; } V pu() { rp++; R = pop(); } V po() { push(R); rp--; } V ju() { ip = pop() - 1; } V ca() { rp++; R = ip; ip = pop() - 1; } V cc() { t = pop(); if (pop()) { rp++; R = ip; ip = t - 1; } } V cj() { t = pop(); if (pop()) { ip = t - 1; } } V re() { ip = R; rp--; } V eq() { N = (N == T) ? -1 : 0; sp--; } V ne() { N = (N != T) ? -1 : 0; sp--; } V lt() { N = (N < T) ? -1 : 0; sp--; } V gt() { N = (N > T) ? -1 : 0; sp--; } V fe() { T = memory[T]; } V st() { memory[T] = N; sp--; sp--; } V ad() { N += T; sp--; } V su() { N -= T; sp--; } V mu() { N *= T; sp--; } V di() { a = T; b = N; T = b / a; N = b % a; } V an() { N = T & N; sp--; } V or() { N = T | N; sp--; } V xo() { N = T ^ N; sp--; } V sl() { N = N << T; sp--; } V sr() { N = N >> T; sp--; } V cp() { len = pop(); dest = pop(); src = pop(); push(-1); while (len) { if (memory[dest] != memory[src]) T = 0; len -= 1; src += 1; dest += 1; } } V cy() { len = pop(); dest = pop(); src = pop(); while (len) { memory[dest] = memory[src]; len -= 1; src += 1; dest += 1; } } V io() { switch (pop()) { case 0: iob[0] = pop(); write(1, &iob, 1); break; case 1: push(getchar()); break; case 2: read_block(); break; case 3: write_block(); break; case 4: save_image(); break; case 5: load_image(); ip = -1; break; case 6: ip = 65536; exit(0); break; case 7: push(sp); push(rp); break; default: break; } } V process(int o) { switch (o) { case 0: break; case 1: li(); break; case 2: du(); break; case 3: dr(); break; case 4: sw(); break; case 5: pu(); break; case 6: po(); break; case 7: ju(); break; case 8: ca(); break; case 9: cc(); break; case 10: cj(); break; case 11: re(); break; case 12: eq(); break; case 13: ne(); break; case 14: lt(); break; case 15: gt(); break; case 16: fe(); break; case 17: st(); break; case 18: ad(); break; case 19: su(); break; case 20: mu(); break; case 21: di(); break; case 22: an(); break; case 23: or(); break; case 24: xo(); break; case 25: sl(); break; case 26: sr(); break; case 27: cp(); break; case 28: cy(); break; case 29: io(); break; default: break; } } V process_bundle(int opcode) { process(opcode & 0xFF); process((opcode >> 8) & 0xFF); process((opcode >> 16) & 0xFF); process((opcode >> 24) & 0xFF); } V *execute(V *unused) { while (ip < 65536) { pthread_mutex_lock(&mutex); process_bundle(memory[ip]); ip++; pthread_mutex_unlock(&mutex); pthread_yield(); } return 0; } V *guard(V *unused) { while (1) { if (sp < 0) { printf("E: data stack underflow\n"); exit(1); } if (sp > 31) { printf("E: data stack overflow\n"); exit(2); } if (rp < 0) { printf("E: address stack underflow\n"); exit(3); } if (rp > 255) { printf("E: address stack overflow\n"); exit(4); } pthread_yield(); } return 0; } int main(int argc, char **argv) { blocks = (argc > 1) ? argv[1] : "ilo.blocks"; rom = (argc > 2) ? argv[2] : "ilo.rom"; load_image(); pthread_t cpu, stack_guard; int e1 = pthread_create(&cpu, NULL, execute, NULL); int e2 = pthread_create(&stack_guard, NULL, guard, NULL); // while(1) {pthread_yield();}; if (!e2) { pthread_join(stack_guard, NULL); pthread_join(cpu, NULL); } }