Lua: Refactor lots of stuff
[lsnes.git] / src / lua / bit.cpp
blobecd5e53fc934d3d8dfa2e9fbebc126a5dd370824
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)
9 namespace
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);
34 base &= mask;
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);
42 base &= mask;
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);
50 base <<= amount;
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);
57 base &= mask;
58 base >>= amount;
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);
65 base &= mask;
66 bool negative = ((base >> (bits - 1)) != 0);
67 base >>= amount;
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)
75 uint64_t ret = init;
76 while(P.more())
77 ret = combine(ret, P.arg<uint64_t>());
78 L.pushnumber(ret);
79 return 1;
82 template<uint64_t (*sh)(uint64_t base, uint64_t amount, uint64_t bits)>
83 int shift(lua::state& L, lua::parameters& P)
85 auto base = P.arg<uint64_t>();
86 auto amount = P.arg_opt<uint64_t>(1);
87 auto bits = P.arg_opt<uint64_t>(BITWISE_BITS);
88 L.pushnumber(sh(base, amount, bits));
89 return 1;
92 template<typename T>
93 int bswap(lua::state& L, lua::parameters& P)
95 T val = P.arg<T>();
96 serialization::swap_endian(val);
97 L.pushnumber(val);
98 return 1;
101 lua::fnptr2 lua_bextract(lua_func_bit, "bit.extract", [](lua::state& L, lua::parameters& P)
102 -> int {
103 uint64_t num = P.arg<uint64_t>();
104 uint64_t ret = 0;
105 for(size_t i = 0;; i++) {
106 if(P.is_boolean()) {
107 if(P.arg<bool>())
108 ret |= (1ULL << i);
109 } else if(P.is_number()) {
110 ret |= (((num >> P.arg<uint8_t>()) & 1) << i);
111 } else
112 break;
114 L.pushnumber(ret);
115 return 1;
118 lua::fnptr2 lua_bvalue(lua_func_bit, "bit.value", [](lua::state& L, lua::parameters& P) -> int {
119 uint64_t ret = 0;
120 for(size_t i = 0;; i++) {
121 if(P.is_number()) {
122 ret |= (1ULL << P.arg<uint8_t>());
123 } else if(P.is_nil()) {
124 } else
125 break;
127 L.pushnumber(ret);
128 return 1;
131 lua::fnptr2 lua_testany(lua_func_bit, "bit.test_any", [](lua::state& L, lua::parameters& P) -> int {
132 auto a = P.arg<uint64_t>();
133 auto b = P.arg<uint64_t>();
134 L.pushboolean((a & b) != 0);
135 return 1;
138 lua::fnptr2 lua_testall(lua_func_bit, "bit.test_all", [](lua::state& L, lua::parameters& P) -> int {
139 auto a = P.arg<uint64_t>();
140 auto b = P.arg<uint64_t>();
141 L.pushboolean((a & b) == b);
142 return 1;
145 int poptable[] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
147 int popcount(uint64_t x)
149 int c = 0;
150 for(unsigned i = 0; i < 16; i++) {
151 c += poptable[x & 15];
152 x >>= 4;
154 return c;
157 lua::fnptr2 lua_popcount(lua_func_bit, "bit.popcount", [](lua::state& L, lua::parameters& P) -> int {
158 auto a = P.arg<uint64_t>();
159 L.pushnumber(popcount(a));
160 return 1;
163 lua::fnptr2 lua_clshift(lua_func_bit, "bit.clshift", [](lua::state& L, lua::parameters& P) -> int {
164 auto a = P.arg<uint64_t>();
165 auto b = P.arg<uint64_t>();
166 auto amount = P.arg_opt<unsigned>(1);
167 auto bits = P.arg_opt<unsigned>(BITWISE_BITS);
168 uint64_t mask = ((1ULL << bits) - 1);
169 a &= mask;
170 b &= mask;
171 a <<= amount;
172 a &= mask;
173 a |= (b >> (bits - amount));
174 b <<= amount;
175 b &= mask;
176 L.pushnumber(a);
177 L.pushnumber(b);
178 return 2;
181 lua::fnptr2 lua_crshift(lua_func_bit, "bit.crshift", [](lua::state& L, lua::parameters& P) -> int {
182 auto a = P.arg<uint64_t>();
183 auto b = P.arg<uint64_t>();
184 auto amount = P.arg_opt<unsigned>(1);
185 auto bits = P.arg_opt<unsigned>(BITWISE_BITS);
186 uint64_t mask = ((1ULL << bits) - 1);
187 a &= mask;
188 b &= mask;
189 b >>= amount;
190 b |= (a << (bits - amount));
191 b &= mask;
192 a >>= amount;
193 L.pushnumber(a);
194 L.pushnumber(b);
195 return 2;
198 template<bool reverse>
199 int flagdecode_core(lua::state& L, lua::parameters& P)
201 auto a = P.arg<uint64_t>();
202 auto b = P.arg<uint64_t>();
203 auto on = P.arg_opt<std::string>("");
204 auto off = P.arg_opt<std::string>("");
205 size_t onl = on.length();
206 size_t offl = off.length();
207 char onc = onl ? on[onl - 1] : '*';
208 char offc = offl ? off[offl - 1] : '-';
209 char buffer[65];
210 unsigned i;
211 size_t bias = min(b, (uint64_t)64) - 1;
212 for(i = 0; i < 64 && i < b; i++) {
213 char onc2 = (i < onl) ? on[i] : onc;
214 char offc2 = (i < offl) ? off[i] : offc;
215 buffer[reverse ? (bias - i) : i] = ((a >> i) & 1) ? onc2 : offc2;
217 buffer[i] = '\0';
218 L.pushstring(buffer);
219 return 1;
222 lua::fnptr2 lua_flagdecode(lua_func_bit, "bit.flagdecode", flagdecode_core<false>);
223 lua::fnptr2 lua_rflagdecode(lua_func_bit, "bit.rflagdecode", flagdecode_core<true>);
224 lua::fnptr2 bit_none(lua_func_bit, "bit.none", fold<combine_none, BITWISE_MASK>);
225 lua::fnptr2 bit_any(lua_func_bit, "bit.any", fold<combine_any, 0>);
226 lua::fnptr2 bit_all(lua_func_bit, "bit.all", fold<combine_all, BITWISE_MASK>);
227 lua::fnptr2 bit_parity(lua_func_bit, "bit.parity", fold<combine_parity, 0>);
228 lua::fnptr2 bit_lrotate(lua_func_bit, "bit.lrotate", shift<shift_lrotate>);
229 lua::fnptr2 bit_rrotate(lua_func_bit, "bit.rrotate", shift<shift_rrotate>);
230 lua::fnptr2 bit_lshift(lua_func_bit, "bit.lshift", shift<shift_lshift>);
231 lua::fnptr2 bit_arshift(lua_func_bit, "bit.arshift", shift<shift_arshift>);
232 lua::fnptr2 bit_lrshift(lua_func_bit, "bit.lrshift", shift<shift_lrshift>);
233 lua::fnptr2 bit_swapword(lua_func_bit, "bit.swapword", bswap<uint16_t>);
234 lua::fnptr2 bit_swaphword(lua_func_bit, "bit.swaphword", bswap<ss_uint24_t>);
235 lua::fnptr2 bit_swapdword(lua_func_bit, "bit.swapdword", bswap<uint32_t>);
236 lua::fnptr2 bit_swapqword(lua_func_bit, "bit.swapqword", bswap<uint64_t>);
237 lua::fnptr2 bit_swapsword(lua_func_bit, "bit.swapsword", bswap<int16_t>);
238 lua::fnptr2 bit_swapshword(lua_func_bit, "bit.swapshword", bswap<ss_int24_t>);
239 lua::fnptr2 bit_swapsdword(lua_func_bit, "bit.swapsdword", bswap<int32_t>);
240 lua::fnptr2 bit_swapsqword(lua_func_bit, "bit.swapsqword", bswap<int64_t>);