ljx

FORK: LuaJIT with native 5.2 and 5.3 support
git clone https://git.neptards.moe/neptards/ljx.git
Log | Files | Refs | README

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