Added opcodes for arithmetic with K operands

Added opcodes for all seven arithmetic operators with K operands
(that is, operands that are numbers in the array of constants of
the function). They cover the cases of constant float operands
(e.g., 'x + .0.0', 'x^0.5') and large integer operands (e.g.,
'x % 10000').
This commit is contained in:
Roberto Ierusalimschy
2018-11-23 12:23:45 -02:00
parent 35296e1fde
commit 84e32ad2eb
11 changed files with 234 additions and 93 deletions

61
lvm.c
View File

@@ -855,6 +855,39 @@ void luaV_finishOp (lua_State *L) {
else op_arithf_aux(L, v1, v2, fop, tm); }
/*
** Arithmetic operations with K operands.
*/
#define op_arithK(L,iop,fop,tm,flip) { \
TValue *v1 = vRB(i); \
TValue *v2 = KC(i); \
if (ttisinteger(v1) && ttisinteger(v2)) { \
lua_Integer i1 = ivalue(v1); lua_Integer i2 = ivalue(v2); \
setivalue(s2v(ra), iop(L, i1, i2)); \
} \
else { \
lua_Number n1; lua_Number n2; \
if (tonumberns(v1, n1) && tonumberns(v2, n2)) { \
setfltvalue(s2v(ra), fop(L, n1, n2)); \
} \
else \
Protect(luaT_trybinassocTM(L, v1, v2, ra, flip, tm)); } }
/*
** Arithmetic operations with K operands for floats.
*/
#define op_arithfK(L,fop,tm) { \
TValue *v1 = vRB(i); \
TValue *v2 = KC(i); \
lua_Number n1; lua_Number n2; \
if (tonumberns(v1, n1) && tonumberns(v2, n2)) { \
setfltvalue(s2v(ra), fop(L, n1, n2)); \
} \
else \
Protect(luaT_trybinTM(L, v1, v2, ra, tm)); }
/*
** Bitwise operations with constant operand.
*/
@@ -1219,6 +1252,34 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
op_arithI(L, luaV_idiv, luai_numidiv, TM_IDIV, 0);
vmbreak;
}
vmcase(OP_ADDK) {
op_arithK(L, l_addi, luai_numadd, TM_ADD, GETARG_k(i));
vmbreak;
}
vmcase(OP_SUBK) {
op_arithK(L, l_subi, luai_numsub, TM_SUB, 0);
vmbreak;
}
vmcase(OP_MULK) {
op_arithK(L, l_muli, luai_nummul, TM_MUL, GETARG_k(i));
vmbreak;
}
vmcase(OP_MODK) {
op_arithK(L, luaV_mod, luaV_modf, TM_MOD, 0);
vmbreak;
}
vmcase(OP_POWK) {
op_arithfK(L, luai_numpow, TM_POW);
vmbreak;
}
vmcase(OP_DIVK) {
op_arithfK(L, luai_numdiv, TM_DIV);
vmbreak;
}
vmcase(OP_IDIVK) {
op_arithK(L, luaV_idiv, luai_numidiv, TM_IDIV, 0);
vmbreak;
}
vmcase(OP_ADD) {
op_arith(L, l_addi, luai_numadd, TM_ADD);
vmbreak;