diff options
-rw-r--r-- | src/lopcodes.js | 15 | ||||
-rw-r--r-- | src/lstate.js | 34 | ||||
-rw-r--r-- | src/lundump.js | 1 | ||||
-rw-r--r-- | src/lvm.js | 133 |
4 files changed, 178 insertions, 5 deletions
diff --git a/src/lopcodes.js b/src/lopcodes.js index b7dfb0f..8df67a3 100644 --- a/src/lopcodes.js +++ b/src/lopcodes.js @@ -86,6 +86,16 @@ const MAXARG_A = ((1 << SIZE_A) - 1); const MAXARG_B = ((1 << SIZE_B) - 1); const MAXARG_C = ((1 << SIZE_C) - 1); +const BITRK = (1 << (SIZE_B - 1)); + +const ISK = function (x) { + return x & BITRK; +}; + +const INDEXK = function (r) { + return r & ~BITRK; +} + module.exports = { OpCodes: OpCodes, SIZE_C: SIZE_C, @@ -105,5 +115,8 @@ module.exports = { MAXARG_Ax: MAXARG_Ax, MAXARG_A: MAXARG_A, MAXARG_B: MAXARG_B, - MAXARG_C: MAXARG_C + MAXARG_C: MAXARG_C, + BITRK: BITRK, + ISK: ISK, + INDEXK: INDEXK };
\ No newline at end of file diff --git a/src/lstate.js b/src/lstate.js new file mode 100644 index 0000000..9c7eec3 --- /dev/null +++ b/src/lstate.js @@ -0,0 +1,34 @@ +/*jshint esversion: 6 */ +"use strict"; + + +class CallInfo { + + constructor(func, top, base, previous, next) { + this.func = func; + this.top = top; + this.base = base; + this.previous = previous; + this.next = next; + this.savedpc = []; + this.pcOff = 0; + } + +} + +class lua_State { + + constructor(cl) { + this.top = 1; + this.ci = [ + new CallInfo(0, 1, 1, null, null); + ]; + this.ci[0].savedpc = cl.p.code; + this.ciOff = 0; + this.stack = [ + closure + ]; + this.openupval = []; + } + +}
\ No newline at end of file diff --git a/src/lundump.js b/src/lundump.js index 07d86df..896fb31 100644 --- a/src/lundump.js +++ b/src/lundump.js @@ -78,6 +78,7 @@ class BytecodeParser { return number; } + // TODO: 8-bit clean strings readString(n) { let size = typeof n !== 'undefined' ? n : this.readByte() - 1; @@ -2,23 +2,148 @@ "use strict"; const BytecodeParser = require("./lundump.js"); +const OC = require('./lopcodes.js'); class LuaVM { - constructor(cl) { - this.cl = cl + constructor(L) { + this.L = L; + } + + RA(base, a) { + return base + a; + } + + RB(base, opcode, base, b) { + return base + b; + } + + RC(base, c) { + return base + c; + } + + RKB(base, k, b) { + return OC.ISK(b) ? k[OC.INDEXK(b)] : base + b; + } + + RKC(base, k, c) { + return OC.ISK(c) ? k[OC.INDEXK(c)] : base + c; } execute() { + let L = this.L; + let ci = L.ci[this.L.ciOff]; + newframe: + let cl = ci.func; + let k = cl.p.k; + let base = ci.base; + for (;;) { + let i = ci.savedpc[ci.pcOff++]; + let ra = this.RA(base, i.a); + switch (OC.OpCodes[i.opcode]) { + case "OP_MOVE": + break; + case "OP_LOADK": + break; + case "OP_LOADKX": + break; + case "OP_LOADBOOL": + break; + case "OP_LOADNIL": + break; + case "OP_GETUPVAL": + break; + case "OP_GETTABUP": + break; + case "OP_GETTABLE": + break; + case "OP_SETTABUP": + break; + case "OP_SETUPVAL": + break; + case "OP_SETTABLE": + break; + case "OP_NEWTABLE": + break; + case "OP_SELF": + break; + case "OP_ADD": + break; + case "OP_SUB": + break; + case "OP_MUL": + break; + case "OP_MOD": + break; + case "OP_POW": + break; + case "OP_DIV": + break; + case "OP_IDIV": + break; + case "OP_BAND": + break; + case "OP_BOR": + break; + case "OP_BXOR": + break; + case "OP_SHL": + break; + case "OP_SHR": + break; + case "OP_UNM": + break; + case "OP_BNOT": + break; + case "OP_NOT": + break; + case "OP_LEN": + break; + case "OP_CONCAT": + break; + case "OP_JMP": + break; + case "OP_EQ": + break; + case "OP_LT": + break; + case "OP_LE": + break; + case "OP_TEST": + break; + case "OP_TESTSET": + break; + case "OP_CALL": + break; + case "OP_TAILCALL": + break; + case "OP_RETURN": + break; + case "OP_FORLOOP": + break; + case "OP_FORPREP": + break; + case "OP_TFORCALL": + break; + case "OP_TFORLOOP": + break; + case "OP_SETLIST": + break; + case "OP_CLOSURE": + break; + case "OP_VARARG": + break; + case "OP_EXTRAARG": + break; + } } } } module.exports = { - LuaVM: LuaVM, - OpCodes: OpCodes + LuaVM: LuaVM };
\ No newline at end of file |