Created
November 21, 2018 10:29
-
-
Save thedeemon/a1701a837ebe403eb7740dc32107038c to your computer and use it in GitHub Desktop.
bytecode VM targeted by Leo compiler
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module lvm2; | |
import std.stdio; | |
enum MODSHIFT = 8; | |
enum RRR = 0 << MODSHIFT; | |
enum RRP = 1 << MODSHIFT; | |
enum RRV = 2 << MODSHIFT; | |
enum RPR = 4 << MODSHIFT; | |
enum RPP = 5 << MODSHIFT; | |
enum RPV = 6 << MODSHIFT; | |
enum RVR = 8 << MODSHIFT; | |
enum RVP = 9 << MODSHIFT; | |
enum RVV = 10 << MODSHIFT; | |
enum PRR = 16 << MODSHIFT; | |
enum PRP = 17 << MODSHIFT; | |
enum PRV = 18 << MODSHIFT; | |
enum PPR = 20 << MODSHIFT; | |
enum PPP = 21 << MODSHIFT; | |
enum PPV = 22 << MODSHIFT; | |
enum PVR = 24 << MODSHIFT; | |
enum PVP = 25 << MODSHIFT; | |
enum PVV = 26 << MODSHIFT; | |
//#define CMDSHIFT 0 | |
//commands | |
enum ADD = 1; //d, a1, a2 : d = a1 + a2 b | |
enum MUL = 2; //d, a1, a2 : d = a1 * a2 c | |
enum MOD = 3; //d, a1, a2 : d = a1 % a2 d | |
enum SUB = 4; //d, a1, a2 : d = a1 - a2 e | |
enum DIV = 5; //d, a1, a2 : d = a1 / a2 f | |
enum XOR = 6; //d, a1, a2 : d = a1 ^ a2 g | |
enum MOV = 7; //d, a1 : d = a1 h | |
enum MOVB = 8; //d, a1 : d = a1 i | |
enum JMPLE = 9; //addr, a1, a2 : if a1 < a2 ip = addr j | |
enum JMPEQ = 10; //addr, a1, a2 : if a1 == a2 ip = addr k | |
enum JMP = 11; //addr : ip = addr l | |
enum PRINT = 12; //x, a1 : print a1 m | |
enum NEW = 13; //d, a1 : d = malloc= a) n | |
enum CALL = 14; //addr, a1 : fp += a1, call addr o | |
enum RET = 15; //: return from call p | |
enum ADD_RRR = 0; //d, a1, a2 :as ADD but all operands are regs a | |
enum JMPLE_RR = 17; //addr, a1, a2 : ~ r | |
enum ADD_RRV = 18; //d, a1, a2 : r = r + v s | |
enum MOV_RV = 19; //d, a1 : r = v t | |
enum MOV_RR = 20; //d, a1 : r = r u | |
enum INC = 21; //d, x, x : r++ v | |
enum INC4 = 22; //d, x, x : r += 4 w | |
enum PRCHAR = 23; //x, a1 : print a1 | |
enum POSTMSG = 24; //msg, a1, a2: PostMessage= hwnd=a1, msg, param=a2) | |
enum BR = 0 << MODSHIFT; | |
enum BP = 1 << MODSHIFT; | |
enum BV = 2 << MODSHIFT; | |
enum AR = 0 << MODSHIFT; | |
enum AP = 4 << MODSHIFT; | |
enum AV = 8 << MODSHIFT; | |
enum DR = 0 << MODSHIFT; | |
enum DP = 16 << MODSHIFT; | |
struct LVM2 { | |
struct context_t { | |
int ip, fp, hp; | |
}; | |
int[] frame; | |
ubyte[] heap; | |
context_t[] callstack; | |
void init(int stacksize, int heapsize) { | |
frame.length = stacksize / 4; | |
heap.length = heapsize; | |
callstack.length = 10000; | |
} | |
void Run(int[] code, void *params, string logname) { | |
int ip = 0, hp = 0, fp = 0, csp = 0; | |
frame[0] = cast(int)params; | |
File f;// = stdout;// | |
int *dest; int source1, source2; | |
const int codelen = code.length; | |
while(ip < codelen) { | |
const int cmd = code[ip]; | |
enum load_d = "if (cmd & DP) dest = cast(int*)frame[fp + code[ip+1]]; else dest = &frame[fp + code[ip+1]];"; | |
enum load_a1 = q{ | |
switch (cmd & (12<<MODSHIFT)) { | |
case AR: source1 = frame[fp + code[ip+2]]; break; | |
case AP: source1 = *cast(int*)frame[fp + code[ip+2]]; break; | |
case AV: source1 = code[ip+2]; break; | |
default: throw new Exception("LVM2: bad A1 value"); | |
} | |
}; | |
enum load_a2 = q{ | |
switch (cmd & (3 << MODSHIFT)) { | |
case BR: source2 = frame[fp + code[ip+3]]; break; | |
case BP: source2 = *cast(int*)frame[fp + code[ip+3]]; break; | |
case BV: source2 = code[ip+3]; break; | |
default: throw new Exception("LVM2: bad A2 value"); | |
} | |
}; | |
switch(cmd & 0xFF) { | |
case ADD: mixin(load_d); mixin(load_a1); mixin(load_a2); *dest = source1 + source2; ip += 4; break; | |
case MUL: mixin(load_d); mixin(load_a1); mixin(load_a2); *dest = source1 * source2; ip += 4; break; | |
case MOD: mixin(load_d); mixin(load_a1); mixin(load_a2); *dest = source1 % source2; ip += 4; break; | |
case SUB: mixin(load_d); mixin(load_a1); mixin(load_a2); *dest = source1 - source2; ip += 4; break; | |
case DIV: mixin(load_d); mixin(load_a1); mixin(load_a2); *dest = source1 / source2; ip += 4; break; | |
case XOR: mixin(load_d); mixin(load_a1); mixin(load_a2); *dest = source1 ^ source2; ip += 4; break; | |
case MOV: mixin(load_d); mixin(load_a1); *dest = source1; ip += 3; break; | |
case MOVB: mixin(load_d); mixin(load_a1); *cast(ubyte*)dest = cast(ubyte)source1; ip += 3; break; | |
case JMPLE: mixin(load_a1); mixin(load_a2); if (source1 < source2) ip = code[ip+1]; else ip += 4; break; | |
case JMPEQ: mixin(load_a1); mixin(load_a2); if (source1 == source2) ip = code[ip+1]; else ip += 4; break; | |
case JMP: ip = code[ip+1]; break; | |
case PRINT: if (!f.isOpen) f.open(logname,"a"); mixin(load_a1); f.writef("%d ", source1); ip += 3; break; | |
case PRCHAR: if (!f.isOpen) f.open(logname,"a"); mixin(load_a1); f.writef("%c" , cast(char)source1); ip += 3; break; | |
case NEW: mixin(load_d); mixin(load_a1); *dest = cast(int)&heap[hp]; hp += source1; ip += 3; break; | |
case CALL: | |
mixin(load_a1); | |
callstack[csp].fp = fp; | |
callstack[csp].hp = hp; | |
callstack[csp].ip = ip + 3; | |
csp++; | |
fp += source1; | |
ip = code[ip+1]; | |
break; | |
case RET: | |
if (csp<1) return; | |
csp--; | |
fp = callstack[csp].fp; | |
hp = callstack[csp].hp; | |
ip = callstack[csp].ip; | |
break; | |
case ADD_RRR: frame[fp + code[ip+1]] = frame[fp + code[ip+2]] + frame[fp + code[ip+3]]; ip += 4; break; | |
case ADD_RRV: frame[fp + code[ip+1]] = frame[fp + code[ip+2]] + code[ip+3]; ip += 4; break; | |
case MOV_RV: frame[fp + code[ip+1]] = code[ip+2]; ip += 3; break; | |
case MOV_RR: frame[fp + code[ip+1]] = frame[fp + code[ip+2]]; ip += 3; break; | |
case JMPLE_RR: if (frame[fp + code[ip+2]] < frame[fp + code[ip+3]]) ip = code[ip+1]; else ip += 4; break; | |
case INC: frame[fp + code[ip+1]]++; ip += 4; break; | |
case INC4: frame[fp + code[ip+1]] += 4; ip += 4; break; | |
default: ip++; | |
} | |
}//while | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment