diff --git a/LIVM.c b/LIVM.c new file mode 100644 index 0000000..01c7293 --- /dev/null +++ b/LIVM.c @@ -0,0 +1,163 @@ +uint64_t pc, cc; +void* ram; + +uint8_t* ramu8; +uint16_t* ramu16; +uint32_t* ramu32; +uint64_t* ramu64; +int8_t* ram8; +int16_t* ram16; +int32_t* ram32; +int64_t* ram64; +float* ramf; +double* ramd; + + +#include "device.c" + + +void allocLIVM(uint64_t size) { + ram = malloc(size); + ramu8 = (uint8_t*)ram, ramu16 = (uint16_t*)ram, + ramu32 = (uint32_t*)ram, ramu64 = (uint64_t*)ram; + ram8 = (int8_t*)ram, ram16 = (int16_t*)ram, + ram32 = (int32_t*)ram, ram64 = (int64_t*)ram; + ramf = (float*)ram, ramd = (double*)ram; +} + +enum opcode { + NOP, END, // 2 + LDA, LDB, LDC, // 3 + ULA, ULB, ULC, // 3 + CST, SSM, // 2 + JMP, IVE, SLE, SIP, // 4 + SUB, SUM, MUL, DIV, MOD, POW, // 6 + INC, DEC, // 2 + AND, BOR, XOR, NOT, // 4 + EQU, LTH, GTH, // 3 + OFR, WAI, OUT, GET, // 4 + ALC, RLC, FRE, CPY, ADD, CAT, // 6 + PRC // 1 + /* + TODO: PRC + PRC - process + PRC 0 - create a new process with id = a + PRC 1 - kill process with id = a + PRC 2 - set offset = b for process with id = a + */ +}; + +void print_ullram() { + for (int i = 0; i < 100; i++) printf("%llu ", ramu64[i]); + printf("\n"); +} + +void run() { + register uint_least64_t ip = 0; + register uint_least64_t a = 0, b = 0, c = 0, s = 0, op, arg; + register uint8_t running = 1, mode_int = 1, size_mode = 1; + + while (running) { + switch (size_mode) { + case 0: + running = 0; + break; + case 1: + while (mode_int) { + #define xtype uint8_t + #define xram ramu8 + #include "xcase.c" + #undef xtype + #undef xram + } + break; + case 2: + while (mode_int) { + #define xtype int8_t + #define xram ram8 + #include "xcase.c" + #undef xtype + #undef xram + } + break; + case 3: + while (mode_int) { + #define xtype uint16_t + #define xram ramu16 + #include "xcase.c" + #undef xtype + #undef xram + } + break; + case 4: + while (mode_int) { + #define xtype int16_t + #define xram ram16 + #include "xcase.c" + #undef xtype + #undef xram + } + break; + case 5: + while (mode_int) { + #define xtype uint32_t + #define xram ramu32 + #include "xcase.c" + #undef xtype + #undef xram + } + break; + case 6: + while (mode_int) { + #define xtype int32_t + #define xram ram32 + #include "xcase.c" + #undef xtype + #undef xram + } + break; + case 7: + while (mode_int) { + #define xtype uint64_t + #define xram ramu64 + #include "xcase.c" + #undef xtype + #undef xram + } + break; + case 8: + while (mode_int) { + #define xtype int64_t + #define xram ram64 + #include "xcase.c" + #undef xtype + #undef xram + } + break; + case 9: + while (mode_int) { + #define xtype float + #define xram ramf + #include "xfcase.c" + #undef xtype + #undef xram + } + break; + case 10: + while (mode_int) { + #define xtype double + #define xram ramd + #include "xfcase.c" + #undef xtype + #undef xram + } + break; + } + mode_int = 1; + } + free(ram); +} + +void loadBIOS(uint64_t length, uint64_t* data) { + for (register uint64_t i = 0; i < length; ++i) ramu64[i] = data[i]; +} diff --git a/device.c b/device.c new file mode 100644 index 0000000..89c047c --- /dev/null +++ b/device.c @@ -0,0 +1,111 @@ +#define opargs uint64_t a, uint64_t b, uint64_t c + typedef void opfunc(opargs); + typedef uint64_t rdfunc(opargs); + + struct Device { + uint64_t* buffer; + uint64_t* data; + uint64_t* rdata; + opfunc* offer; + opfunc* wait; + opfunc* out; + rdfunc* read; + }; + + void d_null_writef(opargs) {} + uint64_t d_null_readf(opargs) {} + + struct Device d_null = { + .buffer = NULL, + .data = NULL, + .rdata = NULL, + .offer = d_null_writef, + .wait = d_null_writef, + .out = d_null_writef, + .read = d_null_readf + }; + + void d_clock_offer(opargs) {} + void d_clock_out(opargs) {} + void d_clock_wait(opargs) { + usleep(a * 1000); + } + uint64_t d_clock_read(opargs) { + return (uint64_t)clock(); + } + + struct Device d_clock = { + .buffer = NULL, + .data = NULL, + .rdata = NULL, + .offer = d_clock_offer, + .wait = d_clock_wait, + .out = d_clock_out, + .read = d_clock_read + }; + + # ifdef CONSOLE_D + void d_console_offer(opargs); + void d_console_out(opargs); + void d_console_wait(opargs); + uint64_t d_console_read(opargs); + + struct Device d_console = { + .buffer = (uint64_t[1024]){ [0 ... 1023] = 0 }, + .data = (uint64_t[800]){ [0 ... 799] = 0 }, + .rdata = (uint64_t[1]){ 0 }, + .offer = d_console_offer, + .wait = d_console_wait, + .out = d_console_out, + .read = d_console_read + }; + + void d_console_offer(opargs) { + if (a == 0) return; + uint64_t* cursor = d_console.buffer; + uint8_t* data = (uint8_t*)(d_console.buffer + 1); + if (c == 1) { + (*cursor) = a; + return; + } + if (*cursor >= 3200) return; + if (a == 1) + data[*cursor++] = b; + else { + if ((*cursor + a) >= 3200) return; + for (uint64_t i = 0; i < a; i++) + data[(*cursor)++] = ramu8[b + i]; + } + } + void d_console_out(opargs) { + uint8_t* _data = (uint8_t*)(d_console.buffer + 1); + uint64_t* _data64 = (uint64_t*)_data; + for (uint64_t i = 0; i < 400; i++) + d_console.data[i] = _data64[i]; + d_console.buffer[0] = 0; + printf("\e[H"); + for (uint64_t i = 0; i < 40; i++) { + for (uint64_t j = 0; j < 80; j++) { + if (((uint8_t*)d_console.data)[j + i * 80]) + putchar(((uint8_t*)d_console.data)[j + i * 80]); + else putchar(' '); + } + putchar('\n'); + } + } + void d_console_wait(opargs) { + d_console.rdata[0] = getchar(); + } + uint64_t d_console_read(opargs) { + return d_console.rdata[0]; + } + # else + # define d_console d_null + # endif + + struct Device* vm_dev[2] = { &d_clock, &d_console }; + + # ifdef d_console + # undef d_console + # endif +#undef opargs diff --git a/xcase.c b/xcase.c new file mode 100644 index 0000000..f2cae8b --- /dev/null +++ b/xcase.c @@ -0,0 +1,66 @@ +// what is a template/generic? +op = ramu64[ip], arg = ramu64[ip + 1]; +//printf("%d | %d %d: a[%d] b[%d] c[%d]\n", ip / 2 + 1, op, arg, a, b, c); +//uint8_t dx = getchar(); +switch (op) { + case NOP: break; + case END: break; + case LDA: a = xram[arg]; break; + case LDB: b = xram[arg]; break; + case LDC: c = xram[arg]; break; + case ULA: xram[arg] = (xtype) a; break; + case ULB: xram[arg] = (xtype) b; break; + case ULC: xram[arg] = (xtype) c; break; + case CST: + switch (arg) { + case 0: break; + case 1: a = (uint8_t) a; break; + case 2: a = (int8_t) a; break; + case 3: a = (uint16_t) a; break; + case 4: a = (int16_t) a; break; + case 5: a = (uint32_t) a; break; + case 6: a = (int32_t) a; break; + case 7: a = (uint64_t) a; break; + case 8: a = (int64_t) a; break; + case 9: a = (float) a; break; + case 10: a = (double) a; break; + }; + break; + case SSM: size_mode = arg; mode_int = 0; break; + case JMP: ip = a; break; + case IVE: if (c) ip = a; break; + case SLE: if (!c) ip = a; break; + case SIP: a = ip; break; + case SUB: a -= b; break; + case SUM: a += b; break; + case MUL: a *= b; break; + case DIV: a /= b; break; + case MOD: a %= b; break; + case POW: a = pow(a, b); break; + case INC: a++; break; + case DEC: a--; break; + case AND: a &= b; break; + case BOR: a |= b; break; + case XOR: a ^= b; break; + case NOT: a = !a; break; + case EQU: a = a == b; break; + case LTH: a = a < b; break; + case GTH: a = a > b; break; + case OFR: vm_dev[arg]->offer(a, b, c); break; + case WAI: vm_dev[arg]->wait(a, b, c); break; + case OUT: vm_dev[arg]->out(a, b, c); break; + case REA: a = vm_dev[arg]->read(a, b, c); break; + case ALC: break; + case RLC: break; + case FRE: break; + case CPY: break; + case ADD: break; + case CAT: break; + case PRC: break; +} +ip += 2; +/*if (dx == '?') { + getchar(); + for(uint64_t i = 0; i < 50; i++) printf("%u ", ((uint8_t*)d_console.buffer)[i]); + puts(""); +}*/ diff --git a/xfcase.c b/xfcase.c new file mode 100644 index 0000000..ceac4c1 --- /dev/null +++ b/xfcase.c @@ -0,0 +1,58 @@ +// what is a template/generic? +switch (op) { + case NOP: break; + case END: break; + case LDA: a = xram[arg]; break; + case LDB: b = xram[arg]; break; + case LDC: c = xram[arg]; break; + case ULA: xram[arg] = (xtype) a; break; + case ULB: xram[arg] = (xtype) b; break; + case ULC: xram[arg] = (xtype) c; break; + case CST: + switch (arg) { + case 0: break; + case 1: a = (uint8_t) a; break; + case 2: a = (int8_t) a; break; + case 3: a = (uint16_t) a; break; + case 4: a = (int16_t) a; break; + case 5: a = (uint32_t) a; break; + case 6: a = (int32_t) a; break; + case 7: a = (uint64_t) a; break; + case 8: a = (int64_t) a; break; + case 9: a = (float) a; break; + case 10: a = (double) a; break; + }; + break; + case SSM: size_mode = arg; mode_int = 0; break; + case JMP: ip = a; break; + case IVE: if (c) ip = arg; break; + case SLE: if (!c) ip = arg; break; + case SIP: a = ip; break; + case SUB: a -= b; break; + case SUM: a += b; break; + case MUL: a *= b; break; + case DIV: a /= b; break; + case MOD: a %= b; break; + case POW: a = pow(a, b); break; + case INC: c++; break; + case DEC: c--; break; + case AND: a &= b; break; + case BOR: a |= b; break; + case XOR: a ^= b; break; + case NOT: a = !a; break; + case EQU: a = a == b; break; + case LTH: a = a < b; break; + case GTH: a = a > b; break; + case OFR: vm_dev[arg]->offer(a, b, c); break; + case WAI: vm_dev[arg]->wait(a, b, c); break; + case OUT: vm_dev[arg]->out(a, b, c); break; + case REA: a = vm_dev[arg]->read(a, b, c); break; + case ALC: break; + case RLC: break; + case FRE: break; + case CPY: break; + case ADD: break; + case CAT: break; + case PRC: break; +} +ip += 2;