Added macro 'testMMMode'
Macro 'testMMMode' checks whether opcode is an MM opcode.
diff --git a/ldebug.c b/ldebug.c
index aef52e1..6e16b0f 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -465,16 +465,14 @@
/*
-** try to find last instruction before 'lastpc' that modified register 'reg'
+** Try to find last instruction before 'lastpc' that modified register 'reg'.
*/
static int findsetreg (const Proto *p, int lastpc, int reg) {
int pc;
int setreg = -1; /* keep last instruction that changed 'reg' */
int jmptarget = 0; /* any code before this address is conditional */
- if (GET_OPCODE(p->code[lastpc]) == OP_MMBIN ||
- GET_OPCODE(p->code[lastpc]) == OP_MMBINI ||
- GET_OPCODE(p->code[lastpc]) == OP_MMBINK)
- lastpc--;
+ if (testMMMode(GET_OPCODE(p->code[lastpc])))
+ lastpc--; /* previous instruction was not actually executed */
for (pc = 0; pc < lastpc; pc++) {
Instruction i = p->code[pc];
OpCode op = GET_OPCODE(i);
diff --git a/lopcodes.c b/lopcodes.c
index aede93a..619592c 100644
--- a/lopcodes.c
+++ b/lopcodes.c
@@ -18,93 +18,93 @@
/* ORDER OP */
LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
-/* OT IT T A mode opcode */
- opmode(0, 0, 0, 1, iABC) /* OP_MOVE */
- ,opmode(0, 0, 0, 1, iAsBx) /* OP_LOADI */
- ,opmode(0, 0, 0, 1, iAsBx) /* OP_LOADF */
- ,opmode(0, 0, 0, 1, iABx) /* OP_LOADK */
- ,opmode(0, 0, 0, 1, iABx) /* OP_LOADKX */
- ,opmode(0, 0, 0, 1, iABC) /* OP_LOADBOOL */
- ,opmode(0, 0, 0, 1, iABC) /* OP_LOADNIL */
- ,opmode(0, 0, 0, 1, iABC) /* OP_GETUPVAL */
- ,opmode(0, 0, 0, 0, iABC) /* OP_SETUPVAL */
- ,opmode(0, 0, 0, 1, iABC) /* OP_GETTABUP */
- ,opmode(0, 0, 0, 1, iABC) /* OP_GETTABLE */
- ,opmode(0, 0, 0, 1, iABC) /* OP_GETI */
- ,opmode(0, 0, 0, 1, iABC) /* OP_GETFIELD */
- ,opmode(0, 0, 0, 0, iABC) /* OP_SETTABUP */
- ,opmode(0, 0, 0, 0, iABC) /* OP_SETTABLE */
- ,opmode(0, 0, 0, 0, iABC) /* OP_SETI */
- ,opmode(0, 0, 0, 0, iABC) /* OP_SETFIELD */
- ,opmode(0, 0, 0, 1, iABC) /* OP_NEWTABLE */
- ,opmode(0, 0, 0, 1, iABC) /* OP_SELF */
- ,opmode(0, 0, 0, 1, iABC) /* OP_ADDI */
- ,opmode(0, 0, 0, 1, iABC) /* OP_SUBI */
- ,opmode(0, 0, 0, 1, iABC) /* OP_MULI */
- ,opmode(0, 0, 0, 1, iABC) /* OP_MODI */
- ,opmode(0, 0, 0, 1, iABC) /* OP_POWI */
- ,opmode(0, 0, 0, 1, iABC) /* OP_DIVI */
- ,opmode(0, 0, 0, 1, iABC) /* OP_IDIVI */
- ,opmode(0, 0, 0, 1, iABC) /* OP_ADDK */
- ,opmode(0, 0, 0, 1, iABC) /* OP_SUBK */
- ,opmode(0, 0, 0, 1, iABC) /* OP_MULK */
- ,opmode(0, 0, 0, 1, iABC) /* OP_MODK */
- ,opmode(0, 0, 0, 1, iABC) /* OP_POWK */
- ,opmode(0, 0, 0, 1, iABC) /* OP_DIVK */
- ,opmode(0, 0, 0, 1, iABC) /* OP_IDIVK */
- ,opmode(0, 0, 0, 1, iABC) /* OP_BANDK */
- ,opmode(0, 0, 0, 1, iABC) /* OP_BORK */
- ,opmode(0, 0, 0, 1, iABC) /* OP_BXORK */
- ,opmode(0, 0, 0, 1, iABC) /* OP_SHRI */
- ,opmode(0, 0, 0, 1, iABC) /* OP_SHLI */
- ,opmode(0, 0, 0, 1, iABC) /* OP_ADD */
- ,opmode(0, 0, 0, 1, iABC) /* OP_SUB */
- ,opmode(0, 0, 0, 1, iABC) /* OP_MUL */
- ,opmode(0, 0, 0, 1, iABC) /* OP_MOD */
- ,opmode(0, 0, 0, 1, iABC) /* OP_POW */
- ,opmode(0, 0, 0, 1, iABC) /* OP_DIV */
- ,opmode(0, 0, 0, 1, iABC) /* OP_IDIV */
- ,opmode(0, 0, 0, 1, iABC) /* OP_BAND */
- ,opmode(0, 0, 0, 1, iABC) /* OP_BOR */
- ,opmode(0, 0, 0, 1, iABC) /* OP_BXOR */
- ,opmode(0, 0, 0, 1, iABC) /* OP_SHL */
- ,opmode(0, 0, 0, 1, iABC) /* OP_SHR */
- ,opmode(0, 0, 0, 0, iABC) /* OP_MMBIN */
- ,opmode(0, 0, 0, 0, iABC) /* OP_MMBINI*/
- ,opmode(0, 0, 0, 0, iABC) /* OP_MMBINK*/
- ,opmode(0, 0, 0, 1, iABC) /* OP_UNM */
- ,opmode(0, 0, 0, 1, iABC) /* OP_BNOT */
- ,opmode(0, 0, 0, 1, iABC) /* OP_NOT */
- ,opmode(0, 0, 0, 1, iABC) /* OP_LEN */
- ,opmode(0, 0, 0, 1, iABC) /* OP_CONCAT */
- ,opmode(0, 0, 0, 0, iABC) /* OP_CLOSE */
- ,opmode(0, 0, 0, 0, iABC) /* OP_TBC */
- ,opmode(0, 0, 0, 0, isJ) /* OP_JMP */
- ,opmode(0, 0, 1, 0, iABC) /* OP_EQ */
- ,opmode(0, 0, 1, 0, iABC) /* OP_LT */
- ,opmode(0, 0, 1, 0, iABC) /* OP_LE */
- ,opmode(0, 0, 1, 0, iABC) /* OP_EQK */
- ,opmode(0, 0, 1, 0, iABC) /* OP_EQI */
- ,opmode(0, 0, 1, 0, iABC) /* OP_LTI */
- ,opmode(0, 0, 1, 0, iABC) /* OP_LEI */
- ,opmode(0, 0, 1, 0, iABC) /* OP_GTI */
- ,opmode(0, 0, 1, 0, iABC) /* OP_GEI */
- ,opmode(0, 0, 1, 0, iABC) /* OP_TEST */
- ,opmode(0, 0, 1, 1, iABC) /* OP_TESTSET */
- ,opmode(1, 1, 0, 1, iABC) /* OP_CALL */
- ,opmode(1, 1, 0, 1, iABC) /* OP_TAILCALL */
- ,opmode(0, 1, 0, 0, iABC) /* OP_RETURN */
- ,opmode(0, 0, 0, 0, iABC) /* OP_RETURN0 */
- ,opmode(0, 0, 0, 0, iABC) /* OP_RETURN1 */
- ,opmode(0, 0, 0, 1, iABx) /* OP_FORLOOP */
- ,opmode(0, 0, 0, 1, iABx) /* OP_FORPREP */
- ,opmode(0, 0, 0, 0, iABx) /* OP_TFORPREP */
- ,opmode(0, 0, 0, 0, iABC) /* OP_TFORCALL */
- ,opmode(0, 0, 0, 1, iABx) /* OP_TFORLOOP */
- ,opmode(0, 1, 0, 0, iABC) /* OP_SETLIST */
- ,opmode(0, 0, 0, 1, iABx) /* OP_CLOSURE */
- ,opmode(1, 0, 0, 1, iABC) /* OP_VARARG */
- ,opmode(0, 1, 0, 1, iABC) /* OP_VARARGPREP */
- ,opmode(0, 0, 0, 0, iAx) /* OP_EXTRAARG */
+/* MM OT IT T A mode opcode */
+ opmode(0, 0, 0, 0, 1, iABC) /* OP_MOVE */
+ ,opmode(0, 0, 0, 0, 1, iAsBx) /* OP_LOADI */
+ ,opmode(0, 0, 0, 0, 1, iAsBx) /* OP_LOADF */
+ ,opmode(0, 0, 0, 0, 1, iABx) /* OP_LOADK */
+ ,opmode(0, 0, 0, 0, 1, iABx) /* OP_LOADKX */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_LOADBOOL */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_LOADNIL */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETUPVAL */
+ ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETUPVAL */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETTABUP */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETTABLE */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETI */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_GETFIELD */
+ ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETTABUP */
+ ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETTABLE */
+ ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETI */
+ ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETFIELD */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_NEWTABLE */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SELF */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_ADDI */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SUBI */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_MULI */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_MODI */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_POWI */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_DIVI */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_IDIVI */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_ADDK */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SUBK */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_MULK */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_MODK */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_POWK */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_DIVK */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_IDIVK */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BANDK */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BORK */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BXORK */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHRI */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHLI */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_ADD */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SUB */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_MUL */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_MOD */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_POW */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_DIV */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_IDIV */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BAND */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BOR */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BXOR */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHL */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHR */
+ ,opmode(1, 0, 0, 0, 0, iABC) /* OP_MMBIN */
+ ,opmode(1, 0, 0, 0, 0, iABC) /* OP_MMBINI*/
+ ,opmode(1, 0, 0, 0, 0, iABC) /* OP_MMBINK*/
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_UNM */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BNOT */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_NOT */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_LEN */
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_CONCAT */
+ ,opmode(0, 0, 0, 0, 0, iABC) /* OP_CLOSE */
+ ,opmode(0, 0, 0, 0, 0, iABC) /* OP_TBC */
+ ,opmode(0, 0, 0, 0, 0, isJ) /* OP_JMP */
+ ,opmode(0, 0, 0, 1, 0, iABC) /* OP_EQ */
+ ,opmode(0, 0, 0, 1, 0, iABC) /* OP_LT */
+ ,opmode(0, 0, 0, 1, 0, iABC) /* OP_LE */
+ ,opmode(0, 0, 0, 1, 0, iABC) /* OP_EQK */
+ ,opmode(0, 0, 0, 1, 0, iABC) /* OP_EQI */
+ ,opmode(0, 0, 0, 1, 0, iABC) /* OP_LTI */
+ ,opmode(0, 0, 0, 1, 0, iABC) /* OP_LEI */
+ ,opmode(0, 0, 0, 1, 0, iABC) /* OP_GTI */
+ ,opmode(0, 0, 0, 1, 0, iABC) /* OP_GEI */
+ ,opmode(0, 0, 0, 1, 0, iABC) /* OP_TEST */
+ ,opmode(0, 0, 0, 1, 1, iABC) /* OP_TESTSET */
+ ,opmode(0, 1, 1, 0, 1, iABC) /* OP_CALL */
+ ,opmode(0, 1, 1, 0, 1, iABC) /* OP_TAILCALL */
+ ,opmode(0, 0, 1, 0, 0, iABC) /* OP_RETURN */
+ ,opmode(0, 0, 0, 0, 0, iABC) /* OP_RETURN0 */
+ ,opmode(0, 0, 0, 0, 0, iABC) /* OP_RETURN1 */
+ ,opmode(0, 0, 0, 0, 1, iABx) /* OP_FORLOOP */
+ ,opmode(0, 0, 0, 0, 1, iABx) /* OP_FORPREP */
+ ,opmode(0, 0, 0, 0, 0, iABx) /* OP_TFORPREP */
+ ,opmode(0, 0, 0, 0, 0, iABC) /* OP_TFORCALL */
+ ,opmode(0, 0, 0, 0, 1, iABx) /* OP_TFORLOOP */
+ ,opmode(0, 0, 1, 0, 0, iABC) /* OP_SETLIST */
+ ,opmode(0, 0, 0, 0, 1, iABx) /* OP_CLOSURE */
+ ,opmode(0, 1, 0, 0, 1, iABC) /* OP_VARARG */
+ ,opmode(0, 0, 1, 0, 1, iABC) /* OP_VARARGPREP */
+ ,opmode(0, 0, 0, 0, 0, iAx) /* OP_EXTRAARG */
};
diff --git a/lopcodes.h b/lopcodes.h
index fd578c6..c5e9cf8 100644
--- a/lopcodes.h
+++ b/lopcodes.h
@@ -359,6 +359,7 @@
** bit 4: operator is a test (next instruction must be a jump)
** bit 5: instruction uses 'L->top' set by previous instruction (when B == 0)
** bit 6: instruction sets 'L->top' for next instruction (when C == 0)
+** bit 7: instruction is an MM instruction (call a metamethod)
*/
LUAI_DDEC(const lu_byte luaP_opmodes[NUM_OPCODES];)
@@ -368,6 +369,7 @@
#define testTMode(m) (luaP_opmodes[m] & (1 << 4))
#define testITMode(m) (luaP_opmodes[m] & (1 << 5))
#define testOTMode(m) (luaP_opmodes[m] & (1 << 6))
+#define testMMMode(m) (luaP_opmodes[m] & (1 << 7))
/* "out top" (set top for next instruction) */
#define isOT(i) \
@@ -377,7 +379,8 @@
/* "in top" (uses top from previous instruction) */
#define isIT(i) (testITMode(GET_OPCODE(i)) && GETARG_B(i) == 0)
-#define opmode(ot,it,t,a,m) (((ot)<<6) | ((it)<<5) | ((t)<<4) | ((a)<<3) | (m))
+#define opmode(mm,ot,it,t,a,m) \
+ (((mm) << 7) | ((ot) << 6) | ((it) << 5) | ((t) << 4) | ((a) << 3) | (m))
/* number of list items to accumulate before a SETLIST instruction */