lib_bit.c (5720B)
1 /* 2 ** Bit manipulation library. 3 ** Copyright (C) 2005-2016 Mike Pall. See Copyright Notice in luajit.h 4 */ 5 6 #define lib_bit_c 7 #define LUA_LIB 8 9 #include "lua.h" 10 #include "lauxlib.h" 11 #include "lualib.h" 12 13 #include "lj_obj.h" 14 #include "lj_err.h" 15 #include "lj_buf.h" 16 #include "lj_strscan.h" 17 #include "lj_strfmt.h" 18 #if LJ_HASFFI 19 #include "lj_ctype.h" 20 #include "lj_cdata.h" 21 #include "lj_cconv.h" 22 #include "lj_carith.h" 23 #endif 24 #include "lj_ff.h" 25 #include "lj_lib.h" 26 27 /* ------------------------------------------------------------------------ */ 28 29 #define LJLIB_MODULE_bit 30 31 #if LJ_HASFFI 32 static int bit_result64(lua_State *L, CTypeID id, uint64_t x) 33 { 34 GCcdata *cd = lj_cdata_new_(L, id, 8); 35 *(uint64_t *)cdataptr(cd) = x; 36 setcdataV(L, L->base-1-LJ_FR2, cd); 37 return FFH_RES(1); 38 } 39 #else 40 static int32_t bit_checkbit(lua_State *L, int narg) 41 { 42 TValue *o = L->base + narg-1; 43 if (!(o < L->top && lj_strscan_numberobj(o))) 44 lj_err_argt(L, narg, LUA_TNUMBER); 45 if (LJ_LIKELY(tvisint(o))) { 46 return intV(o); 47 } else { 48 int32_t i = lj_num2bit(numV(o)); 49 if (LJ_DUALNUM) setintV(o, i); 50 return i; 51 } 52 } 53 #endif 54 55 LJLIB_ASM(bit_tobit) LJLIB_REC(bit_tobit) 56 { 57 #if LJ_HASFFI 58 CTypeID id = 0; 59 setintV(L->base-1-LJ_FR2, (int32_t)lj_carith_check64(L, 1, &id)); 60 return FFH_RES(1); 61 #else 62 lj_lib_checknumber(L, 1); 63 return FFH_RETRY; 64 #endif 65 } 66 67 LJLIB_ASM(bit_bnot) LJLIB_REC(bit_unary IR_BNOT) 68 { 69 #if LJ_HASFFI 70 CTypeID id = 0; 71 uint64_t x = lj_carith_check64(L, 1, &id); 72 return id ? bit_result64(L, id, ~x) : FFH_RETRY; 73 #else 74 lj_lib_checknumber(L, 1); 75 return FFH_RETRY; 76 #endif 77 } 78 79 LJLIB_ASM(bit_bswap) LJLIB_REC(bit_unary IR_BSWAP) 80 { 81 #if LJ_HASFFI 82 CTypeID id = 0; 83 uint64_t x = lj_carith_check64(L, 1, &id); 84 return id ? bit_result64(L, id, lj_bswap64(x)) : FFH_RETRY; 85 #else 86 lj_lib_checknumber(L, 1); 87 return FFH_RETRY; 88 #endif 89 } 90 91 LJLIB_ASM(bit_lshift) LJLIB_REC(bit_shift IR_BSHL) /* ORDER BITLIB BSHL */ 92 { 93 #if LJ_HASFFI 94 CTypeID id = 0, id2 = 0; 95 uint64_t x = lj_carith_check64(L, 1, &id); 96 int32_t sh = (int32_t)lj_carith_check64(L, 2, &id2); 97 if (id) { 98 x = lj_carith_shift64(x, sh, curr_func(L)->c.ffid - (int)FF_bit_lshift); 99 return bit_result64(L, id, x); 100 } 101 if (id2) setintV(L->base+1, sh); 102 return FFH_RETRY; 103 #else 104 lj_lib_checknumber(L, 1); 105 bit_checkbit(L, 2); 106 return FFH_RETRY; 107 #endif 108 } 109 LJLIB_ASM_(bit_rshift) LJLIB_REC(bit_shift IR_BSHR) 110 LJLIB_ASM_(bit_arshift) LJLIB_REC(bit_shift IR_BSAR) 111 LJLIB_ASM_(bit_rol) LJLIB_REC(bit_shift IR_BROL) 112 LJLIB_ASM_(bit_ror) LJLIB_REC(bit_shift IR_BROR) 113 114 LJLIB_ASM(bit_band) LJLIB_REC(bit_nary IR_BAND) /* ORDER BITLIB BAND */ 115 { 116 #if LJ_HASFFI 117 CTypeID id = 0; 118 TValue *o = L->base, *top = L->top; 119 int i = 0; 120 do { lj_carith_check64(L, ++i, &id); } while (++o < top); 121 if (id) { 122 CTState *cts = ctype_cts(L); 123 CType *ct = ctype_get(cts, id); 124 int op = curr_func(L)->c.ffid - (int)FF_bit_bor; 125 uint64_t x, y = op >= 0 ? 0 : ~(uint64_t)0; 126 o = L->base; 127 do { 128 lj_cconv_ct_tv(cts, ct, (uint8_t *)&x, o, 0); 129 if (op < 0) y &= x; else if (op == 0) y |= x; else y ^= x; 130 } while (++o < top); 131 return bit_result64(L, id, y); 132 } 133 return FFH_RETRY; 134 #else 135 int i = 0; 136 do { lj_lib_checknumber(L, ++i); } while (L->base+i < L->top); 137 return FFH_RETRY; 138 #endif 139 } 140 LJLIB_ASM_(bit_bor) LJLIB_REC(bit_nary IR_BOR) 141 LJLIB_ASM_(bit_bxor) LJLIB_REC(bit_nary IR_BXOR) 142 143 /* ------------------------------------------------------------------------ */ 144 145 LJLIB_CF(bit_tohex) LJLIB_REC(.) 146 { 147 #if LJ_HASFFI 148 CTypeID id = 0, id2 = 0; 149 uint64_t b = lj_carith_check64(L, 1, &id); 150 int32_t n = L->base+1>=L->top ? (id ? 16 : 8) : 151 (int32_t)lj_carith_check64(L, 2, &id2); 152 #else 153 uint32_t b = (uint32_t)bit_checkbit(L, 1); 154 int32_t n = L->base+1>=L->top ? 8 : bit_checkbit(L, 2); 155 #endif 156 SBuf *sb = lj_buf_tmp_(L); 157 SFormat sf = (STRFMT_UINT|STRFMT_T_HEX); 158 if (n < 0) { n = -n; sf |= STRFMT_F_UPPER; } 159 sf |= ((SFormat)((n+1)&255) << STRFMT_SH_PREC); 160 #if LJ_HASFFI 161 if (n < 16) b &= ((uint64_t)1 << 4*n)-1; 162 #else 163 if (n < 8) b &= (1u << 4*n)-1; 164 #endif 165 sb = lj_strfmt_putfxint(sb, sf, b); 166 setstrV(L, L->top-1, lj_buf_str(L, sb)); 167 lj_gc_check(L); 168 return 1; 169 } 170 171 #if !LJ_51 172 #if !defined(LUA_NBITS) 173 #define LUA_NBITS 32 174 #endif 175 #define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1)) 176 /* macro to trim extra bits */ 177 #define trim(x) ((x) & ALLONES) 178 #define mask(n) (~((ALLONES << 1) << ((n) - 1))) 179 static int fieldargs (lua_State *L, int farg, int *width) { 180 int f = luaL_checkint(L, farg); 181 int w = luaL_optint(L, farg + 1, 1); 182 luaL_argcheck(L, 0 <= f, farg, "field cannot be negative"); 183 luaL_argcheck(L, 0 < w, farg + 1, "width must be positive"); 184 if (f + w > LUA_NBITS) 185 luaL_error(L, "trying to access non-existent bits"); 186 *width = w; 187 return f; 188 } 189 LJLIB_CF(bit_extract) 190 { 191 int w; 192 lua_Unsigned r = luaL_checkunsigned(L, 1); 193 int f = fieldargs(L, 2, &w); 194 r = (r >> f) & mask(w); 195 lua_pushunsigned(L, r); 196 return 1; 197 } 198 LJLIB_CF(bit_replace) { 199 int w; 200 lua_Unsigned r = luaL_checkunsigned(L, 1); 201 lua_Unsigned v = luaL_checkunsigned(L, 2); 202 int f = fieldargs(L, 3, &w); 203 int m = mask(w); 204 v &= m; /* erase bits outside given width */ 205 r = (r & ~(m << f)) | (v << f); 206 lua_pushunsigned(L, r); 207 return 1; 208 } 209 #endif 210 211 /* ------------------------------------------------------------------------ */ 212 213 #include "lj_libdef.h" 214 LUALIB_API int luaopen_bit32(lua_State *L) 215 { 216 #if !LJ_51 217 LJ_LIB_REG(L, LUA_BIT32LIBNAME, bit); 218 #define RENAME(x,y) lua_getfield(L, -1, #x); lua_setfield(L, -2, #y); 219 RENAME(rol,lrotate); 220 RENAME(ror,rrotate); 221 #undef RENAME 222 return 1; 223 #endif 224 } 225 226 LUALIB_API int luaopen_bit(lua_State *L) 227 { 228 LJ_LIB_REG(L, LUA_BITLIBNAME, bit); 229 return 1; 230 } 231