diff options
Diffstat (limited to 'src/lib_bit.c')
-rw-r--r-- | src/lib_bit.c | 98 |
1 files changed, 92 insertions, 6 deletions
diff --git a/src/lib_bit.c b/src/lib_bit.c index 93fead92..85821b81 100644 --- a/src/lib_bit.c +++ b/src/lib_bit.c | |||
@@ -13,25 +13,82 @@ | |||
13 | #include "lj_obj.h" | 13 | #include "lj_obj.h" |
14 | #include "lj_err.h" | 14 | #include "lj_err.h" |
15 | #include "lj_str.h" | 15 | #include "lj_str.h" |
16 | #if LJ_HASFFI | ||
17 | #include "lj_ctype.h" | ||
18 | #include "lj_cdata.h" | ||
19 | #include "lj_cconv.h" | ||
20 | #include "lj_carith.h" | ||
21 | #endif | ||
22 | #include "lj_ff.h" | ||
16 | #include "lj_lib.h" | 23 | #include "lj_lib.h" |
17 | 24 | ||
18 | /* ------------------------------------------------------------------------ */ | 25 | /* ------------------------------------------------------------------------ */ |
19 | 26 | ||
20 | #define LJLIB_MODULE_bit | 27 | #define LJLIB_MODULE_bit |
21 | 28 | ||
22 | LJLIB_ASM(bit_tobit) LJLIB_REC(bit_unary IR_TOBIT) | 29 | #if LJ_HASFFI |
30 | static int bit_result64(lua_State *L, CTypeID id, uint64_t x) | ||
23 | { | 31 | { |
32 | GCcdata *cd = lj_cdata_new_(L, id, 8); | ||
33 | *(uint64_t *)cdataptr(cd) = x; | ||
34 | setcdataV(L, L->base-1, cd); | ||
35 | return FFH_RES(1); | ||
36 | } | ||
37 | #endif | ||
38 | |||
39 | LJLIB_ASM(bit_tobit) LJLIB_REC(bit_tobit) | ||
40 | { | ||
41 | #if LJ_HASFFI | ||
42 | CTypeID id = 0; | ||
43 | setintV(L->base-1, (int32_t)lj_carith_check64(L, 1, &id)); | ||
44 | return FFH_RES(1); | ||
45 | #else | ||
46 | lj_lib_checknumber(L, 1); | ||
47 | return FFH_RETRY; | ||
48 | #endif | ||
49 | } | ||
50 | |||
51 | LJLIB_ASM(bit_bnot) LJLIB_REC(bit_unary IR_BNOT) | ||
52 | { | ||
53 | #if LJ_HASFFI | ||
54 | CTypeID id = 0; | ||
55 | uint64_t x = lj_carith_check64(L, 1, &id); | ||
56 | return id ? bit_result64(L, id, ~x) : FFH_RETRY; | ||
57 | #else | ||
58 | lj_lib_checknumber(L, 1); | ||
59 | return FFH_RETRY; | ||
60 | #endif | ||
61 | } | ||
62 | |||
63 | LJLIB_ASM(bit_bswap) LJLIB_REC(bit_unary IR_BSWAP) | ||
64 | { | ||
65 | #if LJ_HASFFI | ||
66 | CTypeID id = 0; | ||
67 | uint64_t x = lj_carith_check64(L, 1, &id); | ||
68 | return id ? bit_result64(L, id, lj_bswap64(x)) : FFH_RETRY; | ||
69 | #else | ||
24 | lj_lib_checknumber(L, 1); | 70 | lj_lib_checknumber(L, 1); |
25 | return FFH_RETRY; | 71 | return FFH_RETRY; |
72 | #endif | ||
26 | } | 73 | } |
27 | LJLIB_ASM_(bit_bnot) LJLIB_REC(bit_unary IR_BNOT) | ||
28 | LJLIB_ASM_(bit_bswap) LJLIB_REC(bit_unary IR_BSWAP) | ||
29 | 74 | ||
30 | LJLIB_ASM(bit_lshift) LJLIB_REC(bit_shift IR_BSHL) | 75 | LJLIB_ASM(bit_lshift) LJLIB_REC(bit_shift IR_BSHL) |
31 | { | 76 | { |
77 | #if LJ_HASFFI | ||
78 | CTypeID id = 0, id2 = 0; | ||
79 | uint64_t x = lj_carith_check64(L, 1, &id); | ||
80 | int32_t sh = (int32_t)lj_carith_check64(L, 2, &id2); | ||
81 | if (id) { | ||
82 | x = lj_carith_shift64(x, sh, curr_func(L)->c.ffid - (int)FF_bit_lshift); | ||
83 | return bit_result64(L, id, x); | ||
84 | } | ||
85 | if (id2) setintV(L->base+1, sh); | ||
86 | return FFH_RETRY; | ||
87 | #else | ||
32 | lj_lib_checknumber(L, 1); | 88 | lj_lib_checknumber(L, 1); |
33 | lj_lib_checkbit(L, 2); | 89 | lj_lib_checkbit(L, 2); |
34 | return FFH_RETRY; | 90 | return FFH_RETRY; |
91 | #endif | ||
35 | } | 92 | } |
36 | LJLIB_ASM_(bit_rshift) LJLIB_REC(bit_shift IR_BSHR) | 93 | LJLIB_ASM_(bit_rshift) LJLIB_REC(bit_shift IR_BSHR) |
37 | LJLIB_ASM_(bit_arshift) LJLIB_REC(bit_shift IR_BSAR) | 94 | LJLIB_ASM_(bit_arshift) LJLIB_REC(bit_shift IR_BSAR) |
@@ -40,9 +97,29 @@ LJLIB_ASM_(bit_ror) LJLIB_REC(bit_shift IR_BROR) | |||
40 | 97 | ||
41 | LJLIB_ASM(bit_band) LJLIB_REC(bit_nary IR_BAND) | 98 | LJLIB_ASM(bit_band) LJLIB_REC(bit_nary IR_BAND) |
42 | { | 99 | { |
100 | #if LJ_HASFFI | ||
101 | CTypeID id = 0; | ||
102 | TValue *o = L->base, *top = L->top; | ||
103 | int i = 0; | ||
104 | do { lj_carith_check64(L, ++i, &id); } while (++o < top); | ||
105 | if (id) { | ||
106 | CTState *cts = ctype_cts(L); | ||
107 | CType *ct = ctype_get(cts, id); | ||
108 | int op = curr_func(L)->c.ffid - (int)FF_bit_bor; | ||
109 | uint64_t x, y = op >= 0 ? 0 : ~(uint64_t)0; | ||
110 | o = L->base; | ||
111 | do { | ||
112 | lj_cconv_ct_tv(cts, ct, (uint8_t *)&x, o, 0); | ||
113 | if (op < 0) y &= x; else if (op == 0) y |= x; else y ^= x; | ||
114 | } while (++o < top); | ||
115 | return bit_result64(L, id, y); | ||
116 | } | ||
117 | return FFH_RETRY; | ||
118 | #else | ||
43 | int i = 0; | 119 | int i = 0; |
44 | do { lj_lib_checknumber(L, ++i); } while (L->base+i < L->top); | 120 | do { lj_lib_checknumber(L, ++i); } while (L->base+i < L->top); |
45 | return FFH_RETRY; | 121 | return FFH_RETRY; |
122 | #endif | ||
46 | } | 123 | } |
47 | LJLIB_ASM_(bit_bor) LJLIB_REC(bit_nary IR_BOR) | 124 | LJLIB_ASM_(bit_bor) LJLIB_REC(bit_nary IR_BOR) |
48 | LJLIB_ASM_(bit_bxor) LJLIB_REC(bit_nary IR_BXOR) | 125 | LJLIB_ASM_(bit_bxor) LJLIB_REC(bit_nary IR_BXOR) |
@@ -51,12 +128,21 @@ LJLIB_ASM_(bit_bxor) LJLIB_REC(bit_nary IR_BXOR) | |||
51 | 128 | ||
52 | LJLIB_CF(bit_tohex) | 129 | LJLIB_CF(bit_tohex) |
53 | { | 130 | { |
131 | #if LJ_HASFFI | ||
132 | CTypeID id = 0, id2 = 0; | ||
133 | uint64_t b = lj_carith_check64(L, 1, &id); | ||
134 | int32_t i, dig = id ? 16 : 8; | ||
135 | int32_t n = L->base+1>=L->top ? dig : (int32_t)lj_carith_check64(L, 2, &id2); | ||
136 | char buf[16]; | ||
137 | #else | ||
54 | uint32_t b = (uint32_t)lj_lib_checkbit(L, 1); | 138 | uint32_t b = (uint32_t)lj_lib_checkbit(L, 1); |
55 | int32_t i, n = L->base+1 >= L->top ? 8 : lj_lib_checkbit(L, 2); | 139 | int32_t i, dig = 8; |
56 | const char *hexdigits = "0123456789abcdef"; | 140 | int32_t n = L->base+1>=L->top ? dig : lj_lib_checkbit(L, 2); |
57 | char buf[8]; | 141 | char buf[8]; |
142 | #endif | ||
143 | const char *hexdigits = "0123456789abcdef"; | ||
58 | if (n < 0) { n = -n; hexdigits = "0123456789ABCDEF"; } | 144 | if (n < 0) { n = -n; hexdigits = "0123456789ABCDEF"; } |
59 | if (n > 8) n = 8; | 145 | if (n > dig) n = dig; |
60 | for (i = n; --i >= 0; ) { buf[i] = hexdigits[b & 15]; b >>= 4; } | 146 | for (i = n; --i >= 0; ) { buf[i] = hexdigits[b & 15]; b >>= 4; } |
61 | lua_pushlstring(L, buf, (size_t)n); | 147 | lua_pushlstring(L, buf, (size_t)n); |
62 | return 1; | 148 | return 1; |