]> git.ipfire.org Git - thirdparty/LuaJIT.git/commitdiff
FFI: Split up 64 bit x^k helper into signed/unsigned.
authorMike Pall <mike>
Fri, 28 Jan 2011 01:15:30 +0000 (02:15 +0100)
committerMike Pall <mike>
Fri, 28 Jan 2011 01:15:30 +0000 (02:15 +0100)
src/lj_carith.c
src/lj_carith.h
src/lj_crecord.c
src/lj_ir.h

index a7d9298326f67294d96b7b4808ef9fde27b4a095..46f07be7f50f2e80b13188f3e1c906395b42601c 100644 (file)
@@ -184,7 +184,12 @@ static int carith_int64(lua_State *L, CTState *cts, CDArith *ca, MMS mm)
       else
        *up = u0 % u1;
       break;
-    case MM_pow: *up = lj_carith_powi64(u0, u1, (id == CTID_UINT64)); break;
+    case MM_pow:
+      if (id == CTID_INT64)
+       *up = (uint64_t)lj_carith_powi64((int64_t)u0, (int64_t)u1);
+      else
+       *up = lj_carith_powu64(u0, u1);
+      break;
     case MM_unm: *up = (uint64_t)-(int64_t)u0; break;
     default: lua_assert(0); break;
     }
@@ -225,24 +230,12 @@ int lj_carith_op(lua_State *L, MMS mm)
 
 /* -- 64 bit integer arithmetic helpers ----------------------------------- */
 
-/* 64 bit integer x^k. */
-uint64_t lj_carith_powi64(uint64_t x, uint64_t k, int isunsigned)
+/* Unsigned 64 bit x^k. */
+uint64_t lj_carith_powu64(uint64_t x, uint64_t k)
 {
-  uint64_t y = 0;
+  uint64_t y;
   if (k == 0)
     return 1;
-  if (!isunsigned) {
-    if ((int64_t)k < 0) {
-      if (x == 0)
-       return U64x(7fffffff,ffffffff);
-      else if (x == 1)
-       return 1;
-      else if ((int64_t)x == -1)
-       return (k & 1) ? -1 : 1;
-      else
-       return 0;
-    }
-  }
   for (; (k & 1) == 0; k >>= 1) x *= x;
   y = x;
   if ((k >>= 1) != 0) {
@@ -257,4 +250,22 @@ uint64_t lj_carith_powi64(uint64_t x, uint64_t k, int isunsigned)
   return y;
 }
 
+/* Signed 64 bit x^k. */
+int64_t lj_carith_powi64(int64_t x, int64_t k)
+{
+  if (k == 0)
+    return 1;
+  if (k < 0) {
+    if (x == 0)
+      return U64x(7fffffff,ffffffff);
+    else if (x == 1)
+      return 1;
+    else if (x == -1)
+      return (k & 1) ? -1 : 1;
+    else
+      return 0;
+  }
+  return (int64_t)lj_carith_powu64((uint64_t)x, (uint64_t)k);
+}
+
 #endif
index acb095db6c386846ab06307c6f48d72c8bfa41ee..6870172bba12c8e9cee1618109e92df1de950fc4 100644 (file)
@@ -12,7 +12,8 @@
 
 LJ_FUNC int lj_carith_op(lua_State *L, MMS mm);
 
-LJ_FUNC uint64_t lj_carith_powi64(uint64_t x, uint64_t k, int isunsigned);
+LJ_FUNC uint64_t lj_carith_powu64(uint64_t x, uint64_t k);
+LJ_FUNC int64_t lj_carith_powi64(int64_t x, int64_t k);
 
 #endif
 
index 647c464a99adbfa0abe76f6d0e0a4584f8bc0a58..86e9567995bea2338896d0004903544590c9bedc 100644 (file)
@@ -689,8 +689,8 @@ static TRef crec_arith_int64(jit_State *J, TRef *sp, CType **s, MMS mm)
       J->postproc = LJ_POST_FIXGUARD;
       return TREF_TRUE;
     } else if (mm == MM_pow) {
-      tr = lj_ir_call(J, IRCALL_lj_carith_powi64, sp[0], sp[1],
-                     lj_ir_kint(J, (int)dt-(int)IRT_I64));
+      tr = lj_ir_call(J, dt == IRT_I64 ? IRCALL_lj_carith_powi64 :
+                                        IRCALL_lj_carith_powu64, sp[0], sp[1]);
     } else {
       if (mm == MM_div || mm == MM_mod)
        return 0;  /* NYI: integer div, mod. */
index 6dee36c61cd91ab22c19d9169b8233ab208cb1b0..1cb3566e2e6b12cf48389e8dad8fd752f3e5ee41 100644 (file)
@@ -251,11 +251,13 @@ typedef struct CCallInfo {
 #define CCI_CASTU64            0x0200  /* Cast u64 result to number. */
 #define CCI_NOFPRCLOBBER       0x0400  /* Does not clobber any FPRs. */
 #define CCI_FASTCALL           0x0800  /* Fastcall convention. */
+#define CCI_STACK64            0x1000  /* Needs 64 bits per argument. */
 
 /* Function definitions for CALL* instructions. */
 #if LJ_HASFFI
 #define IRCALLDEF_FFI(_) \
-  _(lj_carith_powi64,  3,   N, U64, CCI_NOFPRCLOBBER)
+  _(lj_carith_powi64,  2,   N, I64, CCI_STACK64|CCI_NOFPRCLOBBER) \
+  _(lj_carith_powu64,  2,   N, U64, CCI_STACK64|CCI_NOFPRCLOBBER)
 #else
 #define IRCALLDEF_FFI(_)
 #endif