1 #include "lua/internal.hpp"
2 #include "library/minmax.hpp"
3 #include "library/int24.hpp"
4 #include "library/serialization.hpp"
6 #define BITWISE_BITS 48
7 #define BITWISE_MASK ((1ULL << (BITWISE_BITS)) - 1)
11 uint64_t combine_none(uint64_t chain
, uint64_t arg
)
13 return (chain
& ~arg
) & BITWISE_MASK
;
16 uint64_t combine_any(uint64_t chain
, uint64_t arg
)
18 return (chain
| arg
) & BITWISE_MASK
;
21 uint64_t combine_all(uint64_t chain
, uint64_t arg
)
23 return (chain
& arg
) & BITWISE_MASK
;
26 uint64_t combine_parity(uint64_t chain
, uint64_t arg
)
28 return (chain
^ arg
) & BITWISE_MASK
;
31 uint64_t shift_lrotate(uint64_t base
, uint64_t amount
, uint64_t bits
)
33 uint64_t mask
= ((1ULL << bits
) - 1);
35 base
= (base
<< amount
) | (base
>> (bits
- amount
));
36 return base
& mask
& BITWISE_MASK
;
39 uint64_t shift_rrotate(uint64_t base
, uint64_t amount
, uint64_t bits
)
41 uint64_t mask
= ((1ULL << bits
) - 1);
43 base
= (base
>> amount
) | (base
<< (bits
- amount
));
44 return base
& mask
& BITWISE_MASK
;
47 uint64_t shift_lshift(uint64_t base
, uint64_t amount
, uint64_t bits
)
49 uint64_t mask
= ((1ULL << bits
) - 1);
51 return base
& mask
& BITWISE_MASK
;
54 uint64_t shift_lrshift(uint64_t base
, uint64_t amount
, uint64_t bits
)
56 uint64_t mask
= ((1ULL << bits
) - 1);
59 return base
& BITWISE_MASK
;
62 uint64_t shift_arshift(uint64_t base
, uint64_t amount
, uint64_t bits
)
64 uint64_t mask
= ((1ULL << bits
) - 1);
66 bool negative
= ((base
>> (bits
- 1)) != 0);
68 base
|= ((negative
? BITWISE_MASK
: 0) << (bits
- amount
));
69 return base
& mask
& BITWISE_MASK
;
72 template<uint64_t (*combine
)(uint64_t chain
, uint64_t arg
), uint64_t init
>
73 int fold(lua::state
& L
, lua::parameters
& P
)
77 ret
= combine(ret
, P
.arg
<uint64_t>());
82 template<uint64_t (*sh
)(uint64_t base
, uint64_t amount
, uint64_t bits
)>
83 int shift(lua::state
& L
, lua::parameters
& P
)
85 uint64_t base
, amount
, bits
;
87 P(base
, P
.optional(amount
, 1), P
.optional(bits
, BITWISE_BITS
));
89 L
.pushnumber(sh(base
, amount
, bits
));
94 int bswap(lua::state
& L
, lua::parameters
& P
)
100 serialization::swap_endian(val
);
105 int bit_extract(lua::state
& L
, lua::parameters
& P
)
112 for(size_t i
= 0;; i
++) {
116 } else if(P
.is_number()) {
117 ret
|= (((num
>> P
.arg
<uint8_t>()) & 1) << i
);
125 int bit_value(lua::state
& L
, lua::parameters
& P
)
128 for(size_t i
= 0;; i
++) {
130 ret
|= (1ULL << P
.arg
<uint8_t>());
131 } else if(P
.is_nil()) {
140 int bit_test(lua::state
& L
, lua::parameters
& P
)
147 bool c
= all
? (t
== b
) : (t
!= 0);
152 template<bool complement
>
153 int bit_test2(lua::state
& L
, lua::parameters
& P
)
159 uint64_t t
= a
& (1ULL << b
);
160 L
.pushboolean((t
!= 0) != complement
);
164 const int CONST_poptable
[] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
166 int popcount(uint64_t x
)
169 for(unsigned i
= 0; i
< 16; i
++) {
170 c
+= CONST_poptable
[x
& 15];
176 int bit_popcount(lua::state
& L
, lua::parameters
& P
)
182 L
.pushnumber(popcount(a
));
187 int bit_cshift(lua::state
& L
, lua::parameters
& P
)
190 unsigned amount
, bits
;
192 P(a
, b
, P
.optional(amount
, 1), P
.optional(bits
, BITWISE_BITS
));
194 uint64_t mask
= ((1ULL << bits
) - 1);
199 b
|= (a
<< (bits
- amount
));
205 a
|= (b
>> (bits
- amount
));
214 template<bool reverse
>
215 int flagdecode_core(lua::state
& L
, lua::parameters
& P
)
220 P(a
, b
, P
.optional(on
, ""), P
.optional(off
, ""));
222 size_t onl
= on
.length();
223 size_t offl
= off
.length();
224 char onc
= onl
? on
[onl
- 1] : '*';
225 char offc
= offl
? off
[offl
- 1] : '-';
228 size_t bias
= min(b
, (uint64_t)64) - 1;
229 for(i
= 0; i
< 64 && i
< b
; i
++) {
230 char onc2
= (i
< onl
) ? on
[i
] : onc
;
231 char offc2
= (i
< offl
) ? off
[i
] : offc
;
232 buffer
[reverse
? (bias
- i
) : i
] = ((a
>> i
) & 1) ? onc2
: offc2
;
235 L
.pushstring(buffer
);
239 int bit_compose(lua::state
& L
, lua::parameters
& P
)
253 template<typename T
, bool littleendian
>
254 int bit_ldbinarynumber(lua::state
& L
, lua::parameters
& P
)
260 str
= L
.tolstring(P
.skip(), len
);
263 if(pos
+ sizeof(T
) > len
)
264 throw std::runtime_error(P
.get_fname() + ": Offset out of range");
266 L
.pushnumber(serialization::read_endian
<T
>(str
+ pos
, littleendian
? -1 : 1));
270 template<typename T
, bool littleendian
>
271 int bit_stbinarynumber(lua::state
& L
, lua::parameters
& P
)
274 char buffer
[sizeof(T
)];
278 serialization::write_endian
<T
>(buffer
, val
, littleendian
? -1 : 1);
279 L
.pushlstring(buffer
, sizeof(T
));
283 int bit_quotent(lua::state
& L
, lua::parameters
& P
)
293 int bit_multidiv(lua::state
& L
, lua::parameters
& P
)
296 unsigned values
= L
.gettop();
300 for(unsigned i
= 1; i
< values
; i
++) {
311 int bit_mul32(lua::state
& L
, lua::parameters
& P
)
319 L
.pushnumber(c
& 0xFFFFFFFFU
);
320 L
.pushnumber(c
>> 32);
324 lua::functions
LUA_bitops_fn(lua_func_bit
, "bit", {
325 {"flagdecode", flagdecode_core
<false>},
326 {"rflagdecode", flagdecode_core
<true>},
327 {"none", fold
<combine_none
, BITWISE_MASK
>},
328 {"any", fold
<combine_any
, 0>},
329 {"all", fold
<combine_all
, BITWISE_MASK
>},
330 {"parity", fold
<combine_parity
, 0>},
331 {"bnot", fold
<combine_none
, BITWISE_MASK
>},
332 {"bor", fold
<combine_any
, 0>},
333 {"band", fold
<combine_all
, BITWISE_MASK
>},
334 {"bxor", fold
<combine_parity
, 0>},
335 {"lrotate", shift
<shift_lrotate
>},
336 {"rrotate", shift
<shift_rrotate
>},
337 {"lshift", shift
<shift_lshift
>},
338 {"arshift", shift
<shift_arshift
>},
339 {"lrshift", shift
<shift_lrshift
>},
340 {"swapword", bswap
<uint16_t>},
341 {"swaphword", bswap
<ss_uint24_t
>},
342 {"swapdword", bswap
<uint32_t>},
343 {"swapqword", bswap
<uint64_t>},
344 {"swapsword", bswap
<int16_t>},
345 {"swapshword", bswap
<ss_int24_t
>},
346 {"swapsdword", bswap
<int32_t>},
347 {"swapsqword", bswap
<int64_t>},
348 {"extract", bit_extract
},
349 {"value", bit_value
},
350 {"test_any", bit_test
<false>},
351 {"test_all", bit_test
<true>},
352 {"test", bit_test2
<false>},
353 {"testn", bit_test2
<true>},
354 {"popcount", bit_popcount
},
355 {"clshift", bit_cshift
<false>},
356 {"crshift", bit_cshift
<true>},
357 {"compose", bit_compose
},
358 {"quotent", bit_quotent
},
359 {"multidiv", bit_multidiv
},
360 {"mul32", bit_mul32
},
361 {"binary_ld_u8be", bit_ldbinarynumber
<uint8_t, false>},
362 {"binary_ld_s8be", bit_ldbinarynumber
<int8_t, false>},
363 {"binary_ld_u16be", bit_ldbinarynumber
<uint16_t, false>},
364 {"binary_ld_s16be", bit_ldbinarynumber
<int16_t, false>},
365 {"binary_ld_u24be", bit_ldbinarynumber
<ss_uint24_t
, false>},
366 {"binary_ld_s24be", bit_ldbinarynumber
<ss_int24_t
, false>},
367 {"binary_ld_u32be", bit_ldbinarynumber
<uint32_t, false>},
368 {"binary_ld_s32be", bit_ldbinarynumber
<int32_t, false>},
369 {"binary_ld_u64be", bit_ldbinarynumber
<uint64_t, false>},
370 {"binary_ld_s64be", bit_ldbinarynumber
<int64_t, false>},
371 {"binary_ld_floatbe", bit_ldbinarynumber
<float, false>},
372 {"binary_ld_doublebe", bit_ldbinarynumber
<double, false>},
373 {"binary_ld_u8le", bit_ldbinarynumber
<uint8_t, true>},
374 {"binary_ld_s8le", bit_ldbinarynumber
<int8_t, true>},
375 {"binary_ld_u16le", bit_ldbinarynumber
<uint16_t, true>},
376 {"binary_ld_s16le", bit_ldbinarynumber
<int16_t, true>},
377 {"binary_ld_u24le", bit_ldbinarynumber
<ss_uint24_t
, true>},
378 {"binary_ld_s24le", bit_ldbinarynumber
<ss_int24_t
, true>},
379 {"binary_ld_u32le", bit_ldbinarynumber
<uint32_t, true>},
380 {"binary_ld_s32le", bit_ldbinarynumber
<int32_t, true>},
381 {"binary_ld_u64le", bit_ldbinarynumber
<uint64_t, true>},
382 {"binary_ld_s64le", bit_ldbinarynumber
<int64_t, true>},
383 {"binary_ld_floatle", bit_ldbinarynumber
<float, true>},
384 {"binary_ld_doublele", bit_ldbinarynumber
<double, true>},
385 {"binary_st_u8be", bit_stbinarynumber
<uint8_t, false>},
386 {"binary_st_s8be", bit_stbinarynumber
<int8_t, false>},
387 {"binary_st_u16be", bit_stbinarynumber
<uint16_t, false>},
388 {"binary_st_s16be", bit_stbinarynumber
<int16_t, false>},
389 {"binary_st_u24be", bit_stbinarynumber
<ss_uint24_t
, false>},
390 {"binary_st_s24be", bit_stbinarynumber
<ss_int24_t
, false>},
391 {"binary_st_u32be", bit_stbinarynumber
<uint32_t, false>},
392 {"binary_st_s32be", bit_stbinarynumber
<int32_t, false>},
393 {"binary_st_u64be", bit_stbinarynumber
<uint64_t, false>},
394 {"binary_st_s64be", bit_stbinarynumber
<int64_t, false>},
395 {"binary_st_floatbe", bit_stbinarynumber
<float, false>},
396 {"binary_st_doublebe", bit_stbinarynumber
<double, false>},
397 {"binary_st_u8le", bit_stbinarynumber
<uint8_t, true>},
398 {"binary_st_s8le", bit_stbinarynumber
<int8_t, true>},
399 {"binary_st_u16le", bit_stbinarynumber
<uint16_t, true>},
400 {"binary_st_s16le", bit_stbinarynumber
<int16_t, true>},
401 {"binary_st_u24le", bit_stbinarynumber
<ss_uint24_t
, true>},
402 {"binary_st_s24le", bit_stbinarynumber
<ss_int24_t
, true>},
403 {"binary_st_u32le", bit_stbinarynumber
<uint32_t, true>},
404 {"binary_st_s32le", bit_stbinarynumber
<int32_t, true>},
405 {"binary_st_u64le", bit_stbinarynumber
<uint64_t, true>},
406 {"binary_st_s64le", bit_stbinarynumber
<int64_t, true>},
407 {"binary_st_floatle", bit_stbinarynumber
<float, true>},
408 {"binary_st_doublele", bit_stbinarynumber
<double, true>},