From c7ee7fe026aa2247377bdd7915089a8e0074de1a Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 4 Dec 2017 15:41:30 -0200 Subject: [PATCH] new opcodes OP_SHLI/OP_SHRI --- lcode.c | 69 +++++++++++++++++++++++++++++++++++++++++++----------- lopcodes.c | 6 ++++- lopcodes.h | 5 +++- lvm.c | 32 +++++++++++++++++++++++-- 4 files changed, 94 insertions(+), 18 deletions(-) diff --git a/lcode.c b/lcode.c index 56fd8522..a09731a7 100644 --- a/lcode.c +++ b/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 2.140 2017/11/30 13:29:18 roberto Exp roberto $ +** $Id: lcode.c,v 2.141 2017/11/30 15:37:16 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -1216,6 +1216,20 @@ static void codebinexpval (FuncState *fs, OpCode op, } +/* +** Code binary operators ('+', '-', ...) with immediate operands. +*/ +static void codebini (FuncState *fs, OpCode op, + expdesc *e1, expdesc *e2, int k, int line) { + int v2 = cast_int(e2->u.ival); /* immediate operand */ + int v1 = luaK_exp2anyreg(fs, e1); + freeexp(fs, e1); + e1->u.info = codeABsC(fs, op, 0, v1, v2, k); /* generate opcode */ + e1->k = VRELOCABLE; /* all those operations are relocatable */ + luaK_fixline(fs, line); +} + + /* ** Code arithmetic operators ('+', '-', ...). If second operand is a ** constant in the proper range, use variant opcodes with immediate @@ -1225,15 +1239,8 @@ static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2, int flip, int line) { if (!isSCint(e2)) codebinexpval(fs, op, e1, e2, line); /* use standard operators */ - else { /* use immediate operators */ - int v2 = cast_int(e2->u.ival); /* immediate operand */ - int v1 = luaK_exp2anyreg(fs, e1); - op = cast(OpCode, op - OP_ADD + OP_ADDI); - freeexp(fs, e1); - e1->u.info = codeABsC(fs, op, 0, v1, v2, flip); /* generate opcode */ - e1->k = VRELOCABLE; /* all those operations are relocatable */ - luaK_fixline(fs, line); - } + else /* use immediate operators */ + codebini(fs, cast(OpCode, op - OP_ADD + OP_ADDI), e1, e2, flip, line); } @@ -1257,12 +1264,31 @@ static void codecommutative (FuncState *fs, OpCode op, } +/* +** Code shift operators. If second operand is constant, use immediate +** operand (negating it if shift is in the other direction). +*/ +static void codeshift (FuncState *fs, OpCode op, + expdesc *e1, expdesc *e2, int line) { + if (isSCint(e2)) { + int changedir = 0; + if (op == OP_SHL) { + changedir = 1; + e2->u.ival = -(e2->u.ival); + } + codebini(fs, OP_SHRI, e1, e2, changedir, line); + } + else + codebinexpval(fs, op, e1, e2, line); +} + + /* ** Emit code for order comparisons. ** When the first operand is an integral value in the proper range, ** change (A < B) to (!(B <= A)) and (A <= B) to (!(B < A)) so that ** it can use an immediate operand. In this case, C indicates this -** change, for cases that cannot assume a total order (NaN and +** change, for cases that cannot assume a total order (NaN and ** metamethods). */ static void codeorder (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { @@ -1440,12 +1466,27 @@ void luaK_posfix (FuncState *fs, BinOpr opr, codearith(fs, cast(OpCode, opr + OP_ADD), e1, e2, 0, line); break; } - case OPR_BAND: case OPR_BOR: case OPR_BXOR: - case OPR_SHL: case OPR_SHR: { + case OPR_BAND: case OPR_BOR: case OPR_BXOR: { if (!constfolding(fs, opr + LUA_OPADD, e1, e2)) codebinexpval(fs, cast(OpCode, opr + OP_ADD), e1, e2, line); break; } + case OPR_SHL: { + if (!constfolding(fs, LUA_OPSHL, e1, e2)) { + if (isSCint(e1)) { + swapexps(e1, e2); + codebini(fs, OP_SHLI, e1, e2, 1, line); + } + else + codeshift(fs, OP_SHL, e1, e2, line); + } + break; + } + case OPR_SHR: { + if (!constfolding(fs, LUA_OPSHR, e1, e2)) + codeshift(fs, OP_SHR, e1, e2, line); + break; + } case OPR_EQ: case OPR_NE: { codeeq(fs, opr, e1, e2); break; @@ -1483,7 +1524,7 @@ void luaK_fixline (FuncState *fs, int line) { } else { fs->previousline -= f->lineinfo[fs->pc - 1]; /* undo previous info. */ - savelineinfo(fs, f, fs->pc - 1, line); /* redo it */ + savelineinfo(fs, f, fs->pc - 1, line); /* redo it */ } } diff --git a/lopcodes.c b/lopcodes.c index 1b081639..55b6050d 100644 --- a/lopcodes.c +++ b/lopcodes.c @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.c,v 1.70 2017/11/27 17:44:31 roberto Exp roberto $ +** $Id: lopcodes.c,v 1.71 2017/11/29 16:57:36 roberto Exp roberto $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -44,6 +44,8 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { "POWI", "DIVI", "IDIVI", + "SHRI", + "SHLI", "ADD", "SUB", "MUL", @@ -117,6 +119,8 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { ,opmode(0, 1, iABC) /* OP_POWI */ ,opmode(0, 1, iABC) /* OP_DIVI */ ,opmode(0, 1, iABC) /* OP_IDIVI */ + ,opmode(0, 1, iABC) /* OP_SHRI */ + ,opmode(0, 1, iABC) /* OP_SHLI */ ,opmode(0, 1, iABC) /* OP_ADD */ ,opmode(0, 1, iABC) /* OP_SUB */ ,opmode(0, 1, iABC) /* OP_MUL */ diff --git a/lopcodes.h b/lopcodes.h index 0d697c55..7468b9e3 100644 --- a/lopcodes.h +++ b/lopcodes.h @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.h,v 1.174 2017/11/30 12:03:00 roberto Exp roberto $ +** $Id: lopcodes.h,v 1.175 2017/11/30 13:16:43 roberto Exp roberto $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -217,6 +217,9 @@ OP_POWI,/* A B sC R(A) := R(B) ^ C */ OP_DIVI,/* A B sC R(A) := R(B) / C */ OP_IDIVI,/* A B sC R(A) := R(B) // C */ +OP_SHRI,/* A B C R(A) := R(B) >> C */ +OP_SHLI,/* A B C R(A) := C << R(B) */ + OP_ADD,/* A B C R(A) := R(B) + R(C) */ OP_SUB,/* A B C R(A) := R(B) - R(C) */ OP_MUL,/* A B C R(A) := R(B) * R(C) */ diff --git a/lvm.c b/lvm.c index 0ba78b3d..9cbba4a9 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.322 2017/11/29 16:57:36 roberto Exp roberto $ +** $Id: lvm.c,v 2.323 2017/11/30 13:29:18 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -687,7 +687,8 @@ void luaV_finishOp (lua_State *L) { case OP_MODI: case OP_POWI: case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_IDIV: - case OP_BAND: case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR: + case OP_BAND: case OP_BOR: case OP_BXOR: + case OP_SHRI: case OP_SHL: case OP_SHR: case OP_MOD: case OP_POW: case OP_UNM: case OP_BNOT: case OP_LEN: case OP_GETTABUP: case OP_GETTABLE: case OP_GETI: @@ -1214,6 +1215,33 @@ void luaV_execute (lua_State *L, CallInfo *ci) { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BXOR)); vmbreak; } + vmcase(OP_SHRI) { + TValue *rb = vRB(i); + int ic = GETARG_sC(i); + lua_Integer ib; + if (tointegerns(rb, &ib)) { + setivalue(vra, luaV_shiftl(ib, -ic)); + } + else { + TMS ev = TM_SHR; + if (TESTARG_k(i)) { + ic = -ic; ev = TM_SHL; + } + Protect(luaT_trybiniTM(L, rb, ic, 0, ra, ev)); + } + vmbreak; + } + vmcase(OP_SHLI) { + TValue *rb = vRB(i); + int ic = GETARG_sC(i); + lua_Integer ib; + if (tointegerns(rb, &ib)) { + setivalue(vra, luaV_shiftl(ic, ib)); + } + else + Protect(luaT_trybiniTM(L, rb, ic, 1, ra, TM_SHL)); + vmbreak; + } vmcase(OP_SHL) { TValue *rb = vRB(i); TValue *rc = vRC(i);