beta-0.89.2
[luatex.git] / source / libs / luajit / LuaJIT-src / src / lib_bit.c
blob55cb2a845a89c93365e74c467c81acd98db21029
1 /*
2 ** Bit manipulation library.
3 ** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
4 */
6 #define lib_bit_c
7 #define LUA_LIB
9 #include "lua.h"
10 #include "lauxlib.h"
11 #include "lualib.h"
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"
27 /* ------------------------------------------------------------------------ */
29 #define LJLIB_MODULE_bit
31 #if LJ_HASFFI
32 static int bit_result64(lua_State *L, CTypeID id, uint64_t x)
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);
39 #else
40 static int32_t bit_checkbit(lua_State *L, int narg)
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;
53 #endif
55 LJLIB_ASM(bit_tobit) LJLIB_REC(bit_tobit)
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
67 LJLIB_ASM(bit_bnot) LJLIB_REC(bit_unary IR_BNOT)
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
79 LJLIB_ASM(bit_bswap) LJLIB_REC(bit_unary IR_BSWAP)
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
91 LJLIB_ASM(bit_lshift) LJLIB_REC(bit_shift IR_BSHL)
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);
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
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)
114 LJLIB_ASM(bit_band) LJLIB_REC(bit_nary IR_BAND)
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);
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
140 LJLIB_ASM_(bit_bor) LJLIB_REC(bit_nary IR_BOR)
141 LJLIB_ASM_(bit_bxor) LJLIB_REC(bit_nary IR_BXOR)
143 /* ------------------------------------------------------------------------ */
145 LJLIB_CF(bit_tohex) LJLIB_REC(.)
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;
171 /* ------------------------------------------------------------------------ */
173 #include "lj_libdef.h"
175 LUALIB_API int luaopen_bit(lua_State *L)
177 LJ_LIB_REG(L, LUA_BITLIBNAME, bit);
178 return 1;