2 ** Bit manipulation library.
3 ** Copyright (C) 2005-2025 Mike Pall. See Copyright Notice in luajit.h
16 #include "lj_strscan.h"
17 #include "lj_strfmt.h"
22 #include "lj_carith.h"
27 /* ------------------------------------------------------------------------ */
29 #define LJLIB_MODULE_bit
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
);
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
))) {
48 int32_t i
= lj_num2bit(numV(o
));
49 if (LJ_DUALNUM
) setintV(o
, i
);
55 LJLIB_ASM(bit_tobit
) LJLIB_REC(bit_tobit
)
59 setintV(L
->base
-1-LJ_FR2
, (int32_t)lj_carith_check64(L
, 1, &id
));
62 lj_lib_checknumber(L
, 1);
67 LJLIB_ASM(bit_bnot
) LJLIB_REC(bit_unary IR_BNOT
)
71 uint64_t x
= lj_carith_check64(L
, 1, &id
);
72 return id
? bit_result64(L
, id
, ~x
) : FFH_RETRY
;
74 lj_lib_checknumber(L
, 1);
79 LJLIB_ASM(bit_bswap
) LJLIB_REC(bit_unary IR_BSWAP
)
83 uint64_t x
= lj_carith_check64(L
, 1, &id
);
84 return id
? bit_result64(L
, id
, lj_bswap64(x
)) : FFH_RETRY
;
86 lj_lib_checknumber(L
, 1);
91 LJLIB_ASM(bit_lshift
) LJLIB_REC(bit_shift IR_BSHL
)
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
);
98 x
= lj_carith_shift64(x
, sh
, curr_func(L
)->c
.ffid
- (int)FF_bit_lshift
);
99 return bit_result64(L
, id
, x
);
101 setintV(L
->base
+1, sh
);
104 lj_lib_checknumber(L
, 1);
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
)
118 TValue
*o
= L
->base
, *top
= L
->top
;
120 do { lj_carith_check64(L
, ++i
, &id
); } while (++o
< top
);
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;
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
;
131 return bit_result64(L
, id
, y
);
136 do { lj_lib_checknumber(L
, ++i
); } while (L
->base
+i
< L
->top
);
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(.)
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
);
153 uint32_t b
= (uint32_t)bit_checkbit(L
, 1);
154 int32_t n
= L
->base
+1>=L
->top
? 8 : bit_checkbit(L
, 2);
156 SBuf
*sb
= lj_buf_tmp_(L
);
157 SFormat sf
= (STRFMT_UINT
|STRFMT_T_HEX
);
158 if (n
< 0) { n
= (int32_t)(~(uint32_t)n
+1u); sf
|= STRFMT_F_UPPER
; }
159 if ((uint32_t)n
> 254) n
= 254;
160 sf
|= ((SFormat
)((n
+1)&255) << STRFMT_SH_PREC
);
162 if (n
< 16) b
&= ((uint64_t)1 << 4*n
)-1;
164 if (n
< 8) b
&= (1u << 4*n
)-1;
166 sb
= lj_strfmt_putfxint(sb
, sf
, b
);
167 setstrV(L
, L
->top
-1, lj_buf_str(L
, sb
));
172 /* ------------------------------------------------------------------------ */
174 #include "lj_libdef.h"
176 LUALIB_API
int luaopen_bit(lua_State
*L
)
178 LJ_LIB_REG(L
, LUA_BITLIBNAME
, bit
);