Index: lua-5.1.4/src/lcode.c =================================================================== --- lua-5.1.4.orig/src/lcode.c 2007-12-28 16:32:23.000000000 +0100 +++ lua-5.1.4/src/lcode.c 2009-01-27 21:15:39.000000000 +0100 @@ -650,6 +650,17 @@ case OP_POW: r = luai_numpow(v1, v2); break; case OP_UNM: r = luai_numunm(v1); break; case OP_LEN: return 0; /* no constant folding for 'len' */ +#if defined(LUA_BITWISE_OPERATORS) + case OP_BOR: luai_logor(r, v1, v2); break; + case OP_BAND: luai_logand(r, v1, v2); break; + case OP_BXOR: luai_logxor(r, v1, v2); break; + case OP_BLSHFT: luai_loglshft(r, v1, v2); break; + case OP_BRSHFT: luai_logrshft(r, v1, v2); break; + case OP_BNOT: luai_lognot(r, v1); break; + case OP_INTDIV: + if (v2 == 0) return 0; /* do not attempt to divide by 0 */ + r = luai_numintdiv(v1, v2); break; +#endif default: lua_assert(0); r = 0; break; } if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */ @@ -662,7 +673,11 @@ if (constfolding(op, e1, e2)) return; else { +#if defined(LUA_BITWISE_OPERATORS) + int o2 = (op != OP_UNM && op != OP_LEN && op != OP_BNOT) ? luaK_exp2RK(fs, e2) : 0; +#else int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; +#endif int o1 = luaK_exp2RK(fs, e1); if (o1 > o2) { freeexp(fs, e1); @@ -698,6 +713,14 @@ expdesc e2; e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; switch (op) { +#if defined(LUA_BITWISE_OPERATORS) + case OPR_BNOT: { + if (e->k == VK) + luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */ + codearith(fs, OP_BNOT, e, &e2); + break; + } +#endif case OPR_MINUS: { if (!isnumeral(e)) luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */ @@ -778,6 +801,14 @@ case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break; case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break; case OPR_POW: codearith(fs, OP_POW, e1, e2); break; +#if defined(LUA_BITWISE_OPERATORS) + case OPR_BOR: codearith(fs, OP_BOR, e1, e2); break; + case OPR_BAND: codearith(fs, OP_BAND, e1, e2); break; + case OPR_BXOR: codearith(fs, OP_BXOR, e1, e2); break; + case OPR_BLSHFT: codearith(fs, OP_BLSHFT, e1, e2); break; + case OPR_BRSHFT: codearith(fs, OP_BRSHFT, e1, e2); break; + case OPR_INTDIV: codearith(fs, OP_INTDIV, e1, e2); break; +#endif case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break; case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break; case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break; Index: lua-5.1.4/src/lcode.h =================================================================== --- lua-5.1.4.orig/src/lcode.h 2007-12-27 14:02:25.000000000 +0100 +++ lua-5.1.4/src/lcode.h 2009-01-27 21:15:39.000000000 +0100 @@ -25,6 +25,9 @@ */ typedef enum BinOpr { OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, +#if defined(LUA_BITWISE_OPERATORS) + OPR_BOR, OPR_BAND, OPR_BXOR, OPR_BLSHFT, OPR_BRSHFT, OPR_INTDIV, +#endif OPR_CONCAT, OPR_NE, OPR_EQ, OPR_LT, OPR_LE, OPR_GT, OPR_GE, @@ -33,8 +36,11 @@ } BinOpr; +#if defined(LUA_BITWISE_OPERATORS) +typedef enum UnOpr { OPR_BNOT, OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; +#else typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; - +#endif #define getcode(fs,e) ((fs)->f->code[(e)->u.s.info]) Index: lua-5.1.4/src/ldebug.c =================================================================== --- lua-5.1.4.orig/src/ldebug.c 2008-05-08 18:56:26.000000000 +0200 +++ lua-5.1.4/src/ldebug.c 2009-01-27 21:15:39.000000000 +0100 @@ -592,6 +592,16 @@ luaG_typeerror(L, p2, "perform arithmetic on"); } +#if defined (LUA_BITWISE_OPERATORS) +void luaG_logicerror (lua_State *L, const TValue *p1, const TValue *p2) { + TValue temp; + if (luaV_tonumber(p1, &temp) == NULL) + p2 = p1; /* first operand is wrong */ + luaG_typeerror(L, p2, "perform bitwise operation on"); +} +#endif + + int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { const char *t1 = luaT_typenames[ttype(p1)]; Index: lua-5.1.4/src/ldebug.h =================================================================== --- lua-5.1.4.orig/src/ldebug.h 2007-12-27 14:02:25.000000000 +0100 +++ lua-5.1.4/src/ldebug.h 2009-01-27 21:15:39.000000000 +0100 @@ -30,4 +30,9 @@ LUAI_FUNC int luaG_checkcode (const Proto *pt); LUAI_FUNC int luaG_checkopenop (Instruction i); +#if defined (LUA_BITWISE_OPERATORS) +LUAI_FUNC void luaG_logicerror (lua_State *L, const TValue *p1, + const TValue *p2); +#endif + #endif Index: lua-5.1.4/src/llex.c =================================================================== --- lua-5.1.4.orig/src/llex.c 2007-12-27 14:02:25.000000000 +0100 +++ lua-5.1.4/src/llex.c 2009-01-27 21:15:39.000000000 +0100 @@ -39,7 +39,11 @@ "end", "false", "for", "function", "if", "in", "local", "nil", "not", "or", "repeat", "return", "then", "true", "until", "while", +#if defined(LUA_BITWISE_OPERATORS) + "..", "...", "==", ">=", ">>", "<=", "<<", "^^", "~=", "!=" +#else "..", "...", "==", ">=", "<=", "~=", +#endif "", "", "", "", NULL }; @@ -371,6 +375,30 @@ if (ls->current != '=') return '='; else { next(ls); return TK_EQ; } } +#if defined(LUA_BITWISE_OPERATORS) + case '<': { + next(ls); + if (ls->current == '=') { next(ls); return TK_LE; } + else if (ls->current == '<') { next(ls); return TK_LSHFT; } + else return '<'; + } + case '>': { + next(ls); + if (ls->current == '=') { next(ls); return TK_GE; } + else if (ls->current == '>') { next(ls); return TK_RSHFT; } + else return '>'; + } + case '^': { + next(ls); + if (ls->current != '^') return '^'; + else { next(ls); return TK_XOR; } + } + case '!': { + next(ls); + if (ls->current != '=') return '!'; + else { next(ls); return TK_NE; } + } +#else case '<': { next(ls); if (ls->current != '=') return '<'; @@ -379,8 +407,9 @@ case '>': { next(ls); if (ls->current != '=') return '>'; - else { next(ls); return TK_GE; } + else { next(ls); return TK_GE; } } +#endif case '~': { next(ls); if (ls->current != '=') return '~'; Index: lua-5.1.4/src/llex.h =================================================================== --- lua-5.1.4.orig/src/llex.h 2007-12-27 14:02:25.000000000 +0100 +++ lua-5.1.4/src/llex.h 2009-01-27 21:15:39.000000000 +0100 @@ -28,7 +28,11 @@ TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, /* other terminal symbols */ +#if defined(LUA_BITWISE_OPERATORS) + TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LSHFT, TK_LE, TK_RSHFT, TK_XOR, TK_NE, TK_CNE, TK_NUMBER, +#else TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, +#endif TK_NAME, TK_STRING, TK_EOS }; Index: lua-5.1.4/src/lopcodes.c =================================================================== --- lua-5.1.4.orig/src/lopcodes.c 2007-12-27 14:02:25.000000000 +0100 +++ lua-5.1.4/src/lopcodes.c 2009-01-27 21:15:39.000000000 +0100 @@ -32,6 +32,15 @@ "DIV", "MOD", "POW", +#if defined(LUA_BITWISE_OPERATORS) + "BOR", + "BAND", + "OP_BXOR" + "BLSHFT", + "BRSHFT", + "BNOT", + "INTDIV", +#endif "UNM", "NOT", "LEN", @@ -78,6 +87,15 @@ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ +#if defined(LUA_BITWISE_OPERATORS) + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BOR */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BAND */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BXOR */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BLSHFT */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BRSHFT */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_BNOT */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_INTDIV */ +#endif ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ Index: lua-5.1.4/src/lopcodes.h =================================================================== --- lua-5.1.4.orig/src/lopcodes.h 2007-12-27 14:02:25.000000000 +0100 +++ lua-5.1.4/src/lopcodes.h 2009-01-27 21:15:39.000000000 +0100 @@ -174,10 +174,20 @@ OP_DIV,/* A B C R(A) := RK(B) / RK(C) */ OP_MOD,/* A B C R(A) := RK(B) % RK(C) */ OP_POW,/* A B C R(A) := RK(B) ^ RK(C) */ +#if defined(LUA_BITWISE_OPERATORS) +OP_BOR,/* A B C R(A) := RK(B) | RK(C) */ +OP_BAND,/* A B C R(A) := RK(B) & RK(C) */ +OP_BXOR,/* A B C R(A) := RK(B) ^| RK(C) */ +OP_BLSHFT,/* A B C R(A) := RK(B) << RK(C) */ +OP_BRSHFT,/* A B C R(A) := RK(B) >> RK(C) */ +OP_BNOT,/* A B R(A) := ~ R(B) */ +OP_INTDIV,/* A B C R(A) := RK(B) \ RK(C) */ +#endif OP_UNM,/* A B R(A) := -R(B) */ OP_NOT,/* A B R(A) := not R(B) */ OP_LEN,/* A B R(A) := length of R(B) */ + OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */ OP_JMP,/* sBx pc+=sBx */ @@ -186,8 +196,8 @@ OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ -OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ -OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ +OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ +OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ @@ -197,8 +207,8 @@ if R(A) =) R(A)*/ Index: lua-5.1.4/src/lparser.c =================================================================== --- lua-5.1.4.orig/src/lparser.c 2007-12-28 16:32:23.000000000 +0100 +++ lua-5.1.4/src/lparser.c 2009-01-27 21:15:39.000000000 +0100 @@ -780,6 +780,9 @@ case TK_NOT: return OPR_NOT; case '-': return OPR_MINUS; case '#': return OPR_LEN; +#if defined(LUA_BITWISE_OPERATORS) + case '~': return OPR_BNOT; +#endif default: return OPR_NOUNOPR; } } @@ -793,6 +796,14 @@ case '/': return OPR_DIV; case '%': return OPR_MOD; case '^': return OPR_POW; +#if defined(LUA_BITWISE_OPERATORS) + case '|': return OPR_BOR; + case '&': return OPR_BAND; + case TK_XOR: return OPR_BXOR; + case TK_LSHFT: return OPR_BLSHFT; + case TK_RSHFT: return OPR_BRSHFT; + case '\\': return OPR_INTDIV; +#endif case TK_CONCAT: return OPR_CONCAT; case TK_NE: return OPR_NE; case TK_EQ: return OPR_EQ; @@ -812,6 +823,9 @@ lu_byte right; /* right priority */ } priority[] = { /* ORDER OPR */ {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `/' `%' */ +#if defined(LUA_BITWISE_OPERATORS) + {6, 6}, {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `|' `&' `!' `<<' `>>' `\' */ +#endif {10, 9}, {5, 4}, /* power and concat (right associative) */ {3, 3}, {3, 3}, /* equality and inequality */ {3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */ Index: lua-5.1.4/src/ltm.c =================================================================== --- lua-5.1.4.orig/src/ltm.c 2007-12-27 14:02:25.000000000 +0100 +++ lua-5.1.4/src/ltm.c 2009-01-27 21:15:39.000000000 +0100 @@ -34,6 +34,9 @@ "__add", "__sub", "__mul", "__div", "__mod", "__pow", "__unm", "__len", "__lt", "__le", "__concat", "__call" +#if defined(LUA_BITWISE_OPERATORS) + ,"__or", "__and", "__xor", "__shl", "__shr", "__not", "__intdiv" +#endif }; int i; for (i=0; i> ~, arithmetic operator \ (integer division) and != as an alternative to ~= */ @@ -209,6 +210,12 @@ */ #define LUA_IDSIZE 60 +/* +@@ LUA_BITWISE_OPERATORS enable logical operators | & ^| >> << ~ on lua_Number +@* but also arithmetic operator \ (integer division) and != as an alernative to ~= +*/ +#define LUA_BITWISE_OPERATORS + /* ** {================================================================== @@ -216,6 +223,7 @@ ** =================================================================== */ + #if defined(lua_c) || defined(luaall_c) /* @@ -526,25 +534,6 @@ /* -@@ The luai_num* macros define the primitive operations over numbers. -*/ -#if defined(LUA_CORE) -#include -#define luai_numadd(a,b) ((a)+(b)) -#define luai_numsub(a,b) ((a)-(b)) -#define luai_nummul(a,b) ((a)*(b)) -#define luai_numdiv(a,b) ((a)/(b)) -#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) -#define luai_numpow(a,b) (pow(a,b)) -#define luai_numunm(a) (-(a)) -#define luai_numeq(a,b) ((a)==(b)) -#define luai_numlt(a,b) ((a)<(b)) -#define luai_numle(a,b) ((a)<=(b)) -#define luai_numisnan(a) (!luai_numeq((a), (a))) -#endif - - -/* @@ lua_number2int is a macro to convert lua_Number to int. @@ lua_number2integer is a macro to convert lua_Number to lua_Integer. ** CHANGE them if you know a faster way to convert a lua_Number to @@ -560,7 +549,7 @@ /* On a Microsoft compiler, use assembler */ #if defined(_MSC_VER) -#define lua_number2int(i,d) __asm fld d __asm fistp i +#define lua_number2int(i,d) { __asm fld d __asm fistp i } #define lua_number2integer(i,n) lua_number2int(i, n) /* the next trick should work on any Pentium, but sometimes clashes @@ -582,6 +571,38 @@ #endif + +/* +@@ The luai_num* macros define the primitive operations over numbers. +*/ +#if defined(LUA_CORE) +#include +#define luai_numadd(a,b) ((a)+(b)) +#define luai_numsub(a,b) ((a)-(b)) +#define luai_nummul(a,b) ((a)*(b)) +#define luai_numdiv(a,b) ((a)/(b)) +#ifdef LUA_BITWISE_OPERATORS +#define luai_numintdiv(a,b) (floor((a)/(b))) +#endif +#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) +#define luai_numpow(a,b) (pow(a,b)) +#define luai_numunm(a) (-(a)) +#define luai_numeq(a,b) ((a)==(b)) +#define luai_numlt(a,b) ((a)<(b)) +#define luai_numle(a,b) ((a)<=(b)) +#define luai_numisnan(a) (!luai_numeq((a), (a))) + +#if defined(LUA_BITWISE_OPERATORS) +#define luai_logor(r, a, b) { lua_Integer ai,bi; lua_number2int(ai,a); lua_number2int(bi,b); r = ai|bi; } +#define luai_logand(r, a,b) { lua_Integer ai,bi; lua_number2int(ai,a); lua_number2int(bi,b); r = ai&bi; } +#define luai_logxor(r, a,b) { lua_Integer ai,bi; lua_number2int(ai,a); lua_number2int(bi,b); r = ai^bi; } +#define luai_lognot(r,a) { lua_Integer ai; lua_number2int(ai,a); r = ~ai; } +#define luai_loglshft(r, a,b) { lua_Integer ai,bi; lua_number2int(ai,a); lua_number2int(bi,b); r = ai<>bi; } +#endif + +#endif + /* }================================================================== */ Index: lua-5.1.4/src/lvm.c =================================================================== --- lua-5.1.4.orig/src/lvm.c 2007-12-28 16:32:23.000000000 +0100 +++ lua-5.1.4/src/lvm.c 2009-01-27 21:15:39.000000000 +0100 @@ -325,6 +325,9 @@ case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break; case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break; case TM_UNM: setnvalue(ra, luai_numunm(nb)); break; +#if defined(LUA_BITWISE_OPERATORS) + case TM_INTDIV: setnvalue(ra, luai_numintdiv(nb, nc)); break; +#endif default: lua_assert(0); break; } } @@ -332,7 +335,30 @@ luaG_aritherror(L, rb, rc); } - +#if defined(LUA_BITWISE_OPERATORS) +static void Logic (lua_State *L, StkId ra, const TValue *rb, + const TValue *rc, TMS op) { + TValue tempb, tempc; + const TValue *b, *c; + if ((b = luaV_tonumber(rb, &tempb)) != NULL && + (c = luaV_tonumber(rc, &tempc)) != NULL) { + lua_Number nb = nvalue(b), nc = nvalue(c); + lua_Integer r; + switch (op) { + case TM_BLSHFT: luai_loglshft(r, nb, nc); break; + case TM_BRSHFT: luai_logrshft(r, nb, nc); break; + case TM_BOR: luai_logor(r, nb, nc); break; + case TM_BAND: luai_logand(r, nb, nc); break; + case TM_BXOR: luai_logxor(r, nb, nc); break; + case TM_BNOT: luai_lognot(r, nb); break; + default: lua_assert(0); r = 0; break; + } + setnvalue(ra, r); + } + else if (!call_binTM(L, rb, rc, ra, op)) + luaG_logicerror(L, rb, rc); +} +#endif /* ** some macros for common tasks in `luaV_execute' @@ -369,6 +395,22 @@ } +#if defined(LUA_BITWISE_OPERATORS) +#define logic_op(op,tm) { \ + TValue *rb = RKB(i); \ + TValue *rc = RKC(i); \ + if (ttisnumber(rb) && ttisnumber(rc)) { \ + lua_Integer r; \ + lua_Number nb = nvalue(rb), nc = nvalue(rc); \ + op(r, nb, nc); \ + setnvalue(ra, r); \ + } \ + else \ + Protect(Logic(L, ra, rb, rc, tm)); \ + } +#endif + + void luaV_execute (lua_State *L, int nexeccalls) { LClosure *cl; @@ -502,6 +544,45 @@ } continue; } +#if defined(LUA_BITWISE_OPERATORS) + case OP_BOR: { + logic_op(luai_logor, TM_BOR); + continue; + } + case OP_BAND: { + logic_op(luai_logand, TM_BAND); + continue; + } + case OP_BXOR: { + logic_op(luai_logxor, TM_BXOR); + continue; + } + case OP_BLSHFT: { + logic_op(luai_loglshft, TM_BLSHFT); + continue; + } + case OP_BRSHFT: { + logic_op(luai_logrshft, TM_BRSHFT); + continue; + } + case OP_BNOT: { + TValue *rb = RB(i); + if (ttisnumber(rb)) { + lua_Integer r; + lua_Number nb = nvalue(rb); + luai_lognot(r, nb); + setnvalue(ra, r); + } + else { + Protect(Logic(L, ra, rb, rb, TM_BNOT)); + } + continue; + } + case OP_INTDIV: { + arith_op(luai_numintdiv, TM_DIV); + continue; + } +#endif case OP_NOT: { int res = l_isfalse(RB(i)); /* next assignment may change this value */ setbvalue(ra, res); Index: lua-5.1.4/test/bitwisepatchtest.lua =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ lua-5.1.4/test/bitwisepatchtest.lua 2009-01-27 21:15:39.000000000 +0100 @@ -0,0 +1,24 @@ +hex=function (i) return "0x"..string.format("%X", i) end +print(hex(0x54|0x55)) +print(hex(0x54&0x66)) +print(hex(0x54^|0x66)) +print(hex(~0x54)) +print(hex(0xF<< 4)) +print(hex(0xF0>> 4)) +a,b=0x54,0x55 +print(hex(a),"|",hex(b), "=",hex(a|b)) +print(hex(a),"|","0x55", "=",hex(a|0x55)) +print(hex(a),"|","0x5|0x50 (", hex(0x5|0x50), ") =",hex(a|(0x5|0x50))) +a,b=0x54,0x66 +print(hex(a),"&",hex(b), "=",hex(a&b)) +print(hex(a),"&","0x66", "=",hex(a&0x66)) +print(hex(a),"^|",hex(b), "=",hex(a^|b)) +print(hex(a),"^|","0x66", "=",hex(a^|0x66)) +print("~"..hex(a),"=",hex(~a)) +a,b=0xF,0xF0 +print(hex(a).."<<4","=",hex(a<<4)) +print(hex(b)..">>4","=",hex(b>>4)) +a,b=0xF,4 +print(hex(a).."<<"..b,"=",hex(a<>"..b,"=",hex(a>>b))