aboutsummaryrefslogtreecommitdiff
path: root/src/lj_carith.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_carith.c')
-rw-r--r--src/lj_carith.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/src/lj_carith.c b/src/lj_carith.c
index c34596ca..1c050eba 100644
--- a/src/lj_carith.c
+++ b/src/lj_carith.c
@@ -11,10 +11,12 @@
11#include "lj_err.h" 11#include "lj_err.h"
12#include "lj_tab.h" 12#include "lj_tab.h"
13#include "lj_meta.h" 13#include "lj_meta.h"
14#include "lj_ir.h"
14#include "lj_ctype.h" 15#include "lj_ctype.h"
15#include "lj_cconv.h" 16#include "lj_cconv.h"
16#include "lj_cdata.h" 17#include "lj_cdata.h"
17#include "lj_carith.h" 18#include "lj_carith.h"
19#include "lj_strscan.h"
18 20
19/* -- C data arithmetic --------------------------------------------------- */ 21/* -- C data arithmetic --------------------------------------------------- */
20 22
@@ -281,6 +283,79 @@ int lj_carith_len(lua_State *L)
281 return lj_carith_meta(L, cts, &ca, MM_len); 283 return lj_carith_meta(L, cts, &ca, MM_len);
282} 284}
283 285
286/* -- 64 bit bit operations helpers --------------------------------------- */
287
288#if LJ_64
289#define B64DEF(name) \
290 static LJ_AINLINE uint64_t lj_carith_##name(uint64_t x, int32_t sh)
291#else
292/* Not inlined on 32 bit archs, since some of these are quite lengthy. */
293#define B64DEF(name) \
294 uint64_t LJ_NOINLINE lj_carith_##name(uint64_t x, int32_t sh)
295#endif
296
297B64DEF(shl64) { return x << (sh&63); }
298B64DEF(shr64) { return x >> (sh&63); }
299B64DEF(sar64) { return (uint64_t)((int64_t)x >> (sh&63)); }
300B64DEF(rol64) { return lj_rol(x, (sh&63)); }
301B64DEF(ror64) { return lj_ror(x, (sh&63)); }
302
303#undef B64DEF
304
305uint64_t lj_carith_shift64(uint64_t x, int32_t sh, int op)
306{
307 switch (op) {
308 case IR_BSHL-IR_BSHL: x = lj_carith_shl64(x, sh); break;
309 case IR_BSHR-IR_BSHL: x = lj_carith_shr64(x, sh); break;
310 case IR_BSAR-IR_BSHL: x = lj_carith_sar64(x, sh); break;
311 case IR_BROL-IR_BSHL: x = lj_carith_rol64(x, sh); break;
312 case IR_BROR-IR_BSHL: x = lj_carith_ror64(x, sh); break;
313 default: lua_assert(0); break;
314 }
315 return x;
316}
317
318/* Equivalent to lj_lib_checkbit(), but handles cdata. */
319uint64_t lj_carith_check64(lua_State *L, int narg, CTypeID *id)
320{
321 TValue *o = L->base + narg-1;
322 if (o >= L->top) {
323 err:
324 lj_err_argt(L, narg, LUA_TNUMBER);
325 } else if (LJ_LIKELY(tvisnumber(o))) {
326 /* Handled below. */
327 } else if (tviscdata(o)) {
328 CTState *cts = ctype_cts(L);
329 uint8_t *sp = (uint8_t *)cdataptr(cdataV(o));
330 CTypeID sid = cdataV(o)->ctypeid;
331 CType *s = ctype_get(cts, sid);
332 uint64_t x;
333 if (ctype_isref(s->info)) {
334 sp = *(void **)sp;
335 sid = ctype_cid(s->info);
336 }
337 s = ctype_raw(cts, sid);
338 if (ctype_isenum(s->info)) s = ctype_child(cts, s);
339 if ((s->info & (CTMASK_NUM|CTF_BOOL|CTF_FP|CTF_UNSIGNED)) ==
340 CTINFO(CT_NUM, CTF_UNSIGNED) && s->size == 8)
341 *id = CTID_UINT64; /* Use uint64_t, since it has the highest rank. */
342 else if (!*id)
343 *id = CTID_INT64; /* Use int64_t, unless already set. */
344 lj_cconv_ct_ct(cts, ctype_get(cts, *id), s,
345 (uint8_t *)&x, sp, CCF_ARG(narg));
346 return x;
347 } else if (!(tvisstr(o) && lj_strscan_number(strV(o), o))) {
348 goto err;
349 }
350 if (LJ_LIKELY(tvisint(o))) {
351 return (uint32_t)intV(o);
352 } else {
353 int32_t i = lj_num2bit(numV(o));
354 if (LJ_DUALNUM) setintV(o, i);
355 return (uint32_t)i;
356 }
357}
358
284/* -- 64 bit integer arithmetic helpers ----------------------------------- */ 359/* -- 64 bit integer arithmetic helpers ----------------------------------- */
285 360
286#if LJ_32 && LJ_HASJIT 361#if LJ_32 && LJ_HASJIT