control: tags -1 patch pending

Hello maintainer, I'm uploading in deferred/5 the following debdiff, based on 
the patch in the upstream 
pull request.
I had to cherry-pick another fix to make it appliable completely without issues.

let me know if I can speed it up or I have to cancel it!

thanks

G.
diff -Nru luajit-2.1.0~beta3+dfsg/debian/changelog 
luajit-2.1.0~beta3+dfsg/debian/changelog
--- luajit-2.1.0~beta3+dfsg/debian/changelog    2017-10-11 10:48:09.000000000 
+0200
+++ luajit-2.1.0~beta3+dfsg/debian/changelog    2017-10-25 11:24:21.000000000 
+0200
@@ -1,3 +1,13 @@
+luajit (2.1.0~beta3+dfsg-5.1) unstable; urgency=medium
+
+  * Non-maintainer upload.
+  * debian/patches/362.patch:
+    - fix from James Cowgill for mips64el miscompilation (Closes: #878817)
+  * debian/patches/a057a07ab702e225e21848d4f918886c5b0ac06b.patch
+    - align the soft-float patch to make 362 applicable
+
+ -- Gianfranco Costamagna <locutusofb...@debian.org>  Wed, 25 Oct 2017 
11:24:21 +0200
+
 luajit (2.1.0~beta3+dfsg-5) unstable; urgency=medium
 
   * Make ccall_copy_struct static to unpollute global library namespace
diff -Nru luajit-2.1.0~beta3+dfsg/debian/patches/362.patch 
luajit-2.1.0~beta3+dfsg/debian/patches/362.patch
--- luajit-2.1.0~beta3+dfsg/debian/patches/362.patch    1970-01-01 
01:00:00.000000000 +0100
+++ luajit-2.1.0~beta3+dfsg/debian/patches/362.patch    2017-10-25 
11:24:21.000000000 +0200
@@ -0,0 +1,88 @@
+From 82cb28fa4e8da605cb31fdca02386027ed65cede Mon Sep 17 00:00:00 2001
+From: James Cowgill <jcowg...@debian.org>
+Date: Fri, 20 Oct 2017 14:31:44 +0100
+Subject: [PATCH] MIPS64: Fix HREF evicting a register in a branch delay slot
+
+If asm_href is called in 64-bit mode to search for a string constant (for
+example), and if the HREF is merged with an EQ guard, then it is
+possible for a constant register to be evicted by a call to ra_allock
+inside a branch delay slot. This causes the instruction loading into RID_TMP
+which was supposed to be in the delay slot, to be moved after the branch and
+not executed if the branch was taken. With the wrong value in RID_TMP,
+lj_vm_exit_handler will later load a garbage exit number and luajit will later
+crash.
+
+Fix by moving the constant register allocations above the main
+instruction emitting code in asm_href.
+---
+ src/lj_asm_mips.h | 42 +++++++++++++++++++++++++-----------------
+ 1 file changed, 25 insertions(+), 17 deletions(-)
+
+diff --git a/src/lj_asm_mips.h b/src/lj_asm_mips.h
+index 1406a873..c8abe6ff 100644
+--- a/src/lj_asm_mips.h
++++ b/src/lj_asm_mips.h
+@@ -865,6 +865,9 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
+   IRType1 kt = irkey->t;
+   uint32_t khash;
+   MCLabel l_end, l_loop, l_next;
++#if LJ_64
++  Reg cmp64;
++#endif
+ 
+   rset_clear(allow, tab);
+ #if LJ_SOFTFP32
+@@ -901,6 +904,26 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
+ #endif
+   tmp2 = ra_scratch(as, allow);
+   rset_clear(allow, tmp2);
++#if LJ_64
++  if (LJ_SOFTFP || !irt_isnum(kt)) {
++    /* Allocate cmp64 register used for 64-bit comparisons */
++    if (LJ_SOFTFP && irt_isnum(kt)) {
++      cmp64 = key;
++    } else if (!isk && irt_isaddr(kt)) {
++      cmp64 = tmp2;
++    } else {
++      int64_t k;
++      if (isk && irt_isaddr(kt)) {
++        k = ((int64_t)irt_toitype(irkey->t) << 47) | irkey[1].tv.u64;
++      } else {
++        lua_assert(irt_ispri(kt) && !irt_isnil(kt));
++        k = ~((int64_t)~irt_toitype(ir->t) << 47);
++      }
++      cmp64 = ra_allock(as, k, allow);
++      rset_clear(allow, cmp64);
++    }
++  }
++#endif
+ 
+   /* Key not found in chain: jump to exit (if merged) or load niltv. */
+   l_end = emit_label(as);
+@@ -943,24 +966,9 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
+     emit_dta(as, MIPSI_DSRA32, tmp1, tmp1, 15);
+     emit_tg(as, MIPSI_DMTC1, tmp1, tmpnum);
+     emit_tsi(as, MIPSI_LD, tmp1, dest, (int32_t)offsetof(Node, key.u64));
+-  } else if (LJ_SOFTFP && irt_isnum(kt)) {
+-    emit_branch(as, MIPSI_BEQ, tmp1, key, l_end);
+-    emit_tsi(as, MIPSI_LD, tmp1, dest, (int32_t)offsetof(Node, key.u64));
+-  } else if (irt_isaddr(kt)) {
+-    Reg refk = tmp2;
+-    if (isk) {
+-      int64_t k = ((int64_t)irt_toitype(irkey->t) << 47) | irkey[1].tv.u64;
+-      refk = ra_allock(as, k, allow);
+-      rset_clear(allow, refk);
+-    }
+-    emit_branch(as, MIPSI_BEQ, tmp1, refk, l_end);
+-    emit_tsi(as, MIPSI_LD, tmp1, dest, offsetof(Node, key));
+   } else {
+-    Reg pri = ra_allock(as, ~((int64_t)~irt_toitype(ir->t) << 47), allow);
+-    rset_clear(allow, pri);
+-    lua_assert(irt_ispri(kt) && !irt_isnil(kt));
+-    emit_branch(as, MIPSI_BEQ, tmp1, pri, l_end);
+-    emit_tsi(as, MIPSI_LD, tmp1, dest, offsetof(Node, key));
++    emit_branch(as, MIPSI_BEQ, tmp1, cmp64, l_end);
++    emit_tsi(as, MIPSI_LD, tmp1, dest, (int32_t)offsetof(Node, key.u64));
+   }
+   *l_loop = MIPSI_BNE | MIPSF_S(tmp1) | ((as->mcp-l_loop-1) & 0xffffu);
+   if (!isk && irt_isaddr(kt)) {
diff -Nru 
luajit-2.1.0~beta3+dfsg/debian/patches/a057a07ab702e225e21848d4f918886c5b0ac06b.patch
 
luajit-2.1.0~beta3+dfsg/debian/patches/a057a07ab702e225e21848d4f918886c5b0ac06b.patch
--- 
luajit-2.1.0~beta3+dfsg/debian/patches/a057a07ab702e225e21848d4f918886c5b0ac06b.patch
       1970-01-01 01:00:00.000000000 +0100
+++ 
luajit-2.1.0~beta3+dfsg/debian/patches/a057a07ab702e225e21848d4f918886c5b0ac06b.patch
       2017-10-25 11:24:21.000000000 +0200
@@ -0,0 +1,979 @@
+From a057a07ab702e225e21848d4f918886c5b0ac06b Mon Sep 17 00:00:00 2001
+From: Mike Pall <mike>
+Date: Wed, 7 Jun 2017 23:56:54 +0200
+Subject: [PATCH] MIPS64: Add soft-float support to JIT compiler backend.
+
+Contributed by Djordje Kovacevic and Stefan Pejic from RT-RK.com.
+Sponsored by Cisco Systems, Inc.
+---
+ src/lj_arch.h      |   4 +-
+ src/lj_asm.c       |   8 +-
+ src/lj_asm_mips.h  | 217 +++++++++++++++++++++++++++++++++++++++++++----------
+ src/lj_crecord.c   |   4 +-
+ src/lj_emit_mips.h |   2 +
+ src/lj_ffrecord.c  |   2 +-
+ src/lj_ircall.h    |  43 +++++++----
+ src/lj_iropt.h     |   2 +-
+ src/lj_jit.h       |   4 +-
+ src/lj_obj.h       |   3 +
+ src/lj_opt_split.c |   2 +-
+ src/lj_snap.c      |  21 +++---
+ src/vm_mips64.dasc |  49 ++++++++++++
+ 13 files changed, 286 insertions(+), 75 deletions(-)
+
+diff --git a/src/lj_arch.h b/src/lj_arch.h
+index c8d7138e..b7705642 100644
+--- a/src/lj_arch.h
++++ b/src/lj_arch.h
+@@ -337,9 +337,6 @@
+ #define LJ_ARCH_BITS          32
+ #define LJ_TARGET_MIPS32      1
+ #else
+-#if LJ_ABI_SOFTFP || !LJ_ARCH_HASFPU
+-#define LJ_ARCH_NOJIT         1       /* NYI */
+-#endif
+ #define LJ_ARCH_BITS          64
+ #define LJ_TARGET_MIPS64      1
+ #define LJ_TARGET_GC64                1
+@@ -512,6 +509,7 @@
+ #define LJ_ABI_SOFTFP         0
+ #endif
+ #define LJ_SOFTFP             (!LJ_ARCH_HASFPU)
++#define LJ_SOFTFP32           (LJ_SOFTFP && LJ_32)
+ 
+ #if LJ_ARCH_ENDIAN == LUAJIT_BE
+ #define LJ_LE                 0
+diff --git a/src/lj_asm.c b/src/lj_asm.c
+index c2cf5a95..bed2268e 100644
+--- a/src/lj_asm.c
++++ b/src/lj_asm.c
+@@ -338,7 +338,7 @@ static Reg ra_rematk(ASMState *as, IRRef ref)
+   ra_modified(as, r);
+   ir->r = RID_INIT;  /* Do not keep any hint. */
+   RA_DBGX((as, "remat     $i $r", ir, r));
+-#if !LJ_SOFTFP
++#if !LJ_SOFTFP32
+   if (ir->o == IR_KNUM) {
+     emit_loadk64(as, r, ir);
+   } else
+@@ -1305,7 +1305,7 @@ static void asm_call(ASMState *as, IRIns *ir)
+   asm_gencall(as, ci, args);
+ }
+ 
+-#if !LJ_SOFTFP
++#if !LJ_SOFTFP32
+ static void asm_fppow(ASMState *as, IRIns *ir, IRRef lref, IRRef rref)
+ {
+   const CCallInfo *ci = &lj_ir_callinfo[IRCALL_pow];
+@@ -1652,10 +1652,10 @@ static void asm_ir(ASMState *as, IRIns *ir)
+   case IR_MUL: asm_mul(as, ir); break;
+   case IR_MOD: asm_mod(as, ir); break;
+   case IR_NEG: asm_neg(as, ir); break;
+-#if LJ_SOFTFP
++#if LJ_SOFTFP32
+   case IR_DIV: case IR_POW: case IR_ABS:
+   case IR_ATAN2: case IR_LDEXP: case IR_FPMATH: case IR_TOBIT:
+-    lua_assert(0);  /* Unused for LJ_SOFTFP. */
++    lua_assert(0);  /* Unused for LJ_SOFTFP32. */
+     break;
+ #else
+   case IR_DIV: asm_div(as, ir); break;
+diff --git a/src/lj_asm_mips.h b/src/lj_asm_mips.h
+index 05af3d09..1406a873 100644
+--- a/src/lj_asm_mips.h
++++ b/src/lj_asm_mips.h
+@@ -290,7 +290,7 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, 
IRRef *args)
+         {
+           ra_leftov(as, gpr, ref);
+           gpr++;
+-#if LJ_64
++#if LJ_64 && !LJ_SOFTFP
+           fpr++;
+ #endif
+         }
+@@ -301,7 +301,7 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, 
IRRef *args)
+         emit_spstore(as, ir, r, ofs);
+         ofs += irt_isnum(ir->t) ? 8 : 4;
+ #else
+-        emit_spstore(as, ir, r, ofs + ((LJ_BE && (LJ_SOFTFP || r < 
RID_MAX_GPR) && !irt_is64(ir->t)) ? 4 : 0));
++        emit_spstore(as, ir, r, ofs + ((LJ_BE && !irt_isfp(ir->t) && 
!irt_is64(ir->t)) ? 4 : 0));
+         ofs += 8;
+ #endif
+       }
+@@ -312,7 +312,7 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, 
IRRef *args)
+ #endif
+       if (gpr <= REGARG_LASTGPR) {
+       gpr++;
+-#if LJ_64
++#if LJ_64 && !LJ_SOFTFP
+       fpr++;
+ #endif
+       } else {
+@@ -461,12 +461,36 @@ static void asm_tobit(ASMState *as, IRIns *ir)
+   emit_tg(as, MIPSI_MFC1, dest, tmp);
+   emit_fgh(as, MIPSI_ADD_D, tmp, left, right);
+ }
++#elif LJ_64  /* && LJ_SOFTFP */
++static void asm_tointg(ASMState *as, IRIns *ir, Reg r)
++{
++  /* The modified regs must match with the *.dasc implementation. */
++  RegSet drop = 
RID2RSET(REGARG_FIRSTGPR)|RID2RSET(RID_RET)|RID2RSET(RID_RET+1)|
++              RID2RSET(RID_R1)|RID2RSET(RID_R12);
++  if (ra_hasreg(ir->r)) rset_clear(drop, ir->r);
++  ra_evictset(as, drop);
++  /* Return values are in RID_RET (converted value) and RID_RET+1 (status). */
++  ra_destreg(as, ir, RID_RET);
++  asm_guard(as, MIPSI_BNE, RID_RET+1, RID_ZERO);
++  emit_call(as, (void *)lj_ir_callinfo[IRCALL_lj_vm_tointg].func, 0);
++  if (r == RID_NONE)
++    ra_leftov(as, REGARG_FIRSTGPR, ir->op1);
++  else if (r != REGARG_FIRSTGPR)
++    emit_move(as, REGARG_FIRSTGPR, r);
++}
++
++static void asm_tobit(ASMState *as, IRIns *ir)
++{
++  Reg dest = ra_dest(as, ir, RSET_GPR);
++  emit_dta(as, MIPSI_SLL, dest, dest, 0);
++  asm_callid(as, ir, IRCALL_lj_vm_tobit);
++}
+ #endif
+ 
+ static void asm_conv(ASMState *as, IRIns *ir)
+ {
+   IRType st = (IRType)(ir->op2 & IRCONV_SRCMASK);
+-#if !LJ_SOFTFP
++#if !LJ_SOFTFP32
+   int stfp = (st == IRT_NUM || st == IRT_FLOAT);
+ #endif
+ #if LJ_64
+@@ -477,12 +501,13 @@ static void asm_conv(ASMState *as, IRIns *ir)
+   lua_assert(!(irt_isint64(ir->t) ||
+              (st == IRT_I64 || st == IRT_U64))); /* Handled by SPLIT. */
+ #endif
+-#if LJ_32 && LJ_SOFTFP
++#if LJ_SOFTFP32
+   /* FP conversions are handled by SPLIT. */
+   lua_assert(!irt_isfp(ir->t) && !(st == IRT_NUM || st == IRT_FLOAT));
+   /* Can't check for same types: SPLIT uses CONV int.int + BXOR for sfp NEG. 
*/
+ #else
+   lua_assert(irt_type(ir->t) != st);
++#if !LJ_SOFTFP
+   if (irt_isfp(ir->t)) {
+     Reg dest = ra_dest(as, ir, RSET_FPR);
+     if (stfp) {  /* FP to FP conversion. */
+@@ -608,6 +633,42 @@ static void asm_conv(ASMState *as, IRIns *ir)
+       }
+     }
+   } else
++#else
++  if (irt_isfp(ir->t)) {
++#if LJ_64 && LJ_HASFFI
++    if (stfp) {  /* FP to FP conversion. */
++      asm_callid(as, ir, irt_isnum(ir->t) ? IRCALL_softfp_f2d :
++                                          IRCALL_softfp_d2f);
++    } else {  /* Integer to FP conversion. */
++      IRCallID cid = ((IRT_IS64 >> st) & 1) ?
++      (irt_isnum(ir->t) ?
++       (st == IRT_I64 ? IRCALL_fp64_l2d : IRCALL_fp64_ul2d) :
++       (st == IRT_I64 ? IRCALL_fp64_l2f : IRCALL_fp64_ul2f)) :
++      (irt_isnum(ir->t) ?
++       (st == IRT_INT ? IRCALL_softfp_i2d : IRCALL_softfp_ui2d) :
++       (st == IRT_INT ? IRCALL_softfp_i2f : IRCALL_softfp_ui2f));
++      asm_callid(as, ir, cid);
++    }
++#else
++    asm_callid(as, ir, IRCALL_softfp_i2d);
++#endif
++  } else if (stfp) {  /* FP to integer conversion. */
++    if (irt_isguard(ir->t)) {
++      /* Checked conversions are only supported from number to int. */
++      lua_assert(irt_isint(ir->t) && st == IRT_NUM);
++      asm_tointg(as, ir, RID_NONE);
++    } else {
++      IRCallID cid = irt_is64(ir->t) ?
++      ((st == IRT_NUM) ?
++       (irt_isi64(ir->t) ? IRCALL_fp64_d2l : IRCALL_fp64_d2ul) :
++       (irt_isi64(ir->t) ? IRCALL_fp64_f2l : IRCALL_fp64_f2ul)) :
++      ((st == IRT_NUM) ?
++       (irt_isint(ir->t) ? IRCALL_softfp_d2i : IRCALL_softfp_d2ui) :
++       (irt_isint(ir->t) ? IRCALL_softfp_f2i : IRCALL_softfp_f2ui));
++      asm_callid(as, ir, cid);
++    }
++  } else
++#endif
+ #endif
+   {
+     Reg dest = ra_dest(as, ir, RSET_GPR);
+@@ -665,7 +726,7 @@ static void asm_strto(ASMState *as, IRIns *ir)
+   const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_strscan_num];
+   IRRef args[2];
+   int32_t ofs = 0;
+-#if LJ_SOFTFP
++#if LJ_SOFTFP32
+   ra_evictset(as, RSET_SCRATCH);
+   if (ra_used(ir)) {
+     if (ra_hasspill(ir->s) && ra_hasspill((ir+1)->s) &&
+@@ -806,7 +867,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
+   MCLabel l_end, l_loop, l_next;
+ 
+   rset_clear(allow, tab);
+-#if LJ_32 && LJ_SOFTFP
++#if LJ_SOFTFP32
+   if (!isk) {
+     key = ra_alloc1(as, refkey, allow);
+     rset_clear(allow, key);
+@@ -826,7 +887,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
+     }
+   }
+ #else
+-  if (irt_isnum(kt)) {
++  if (!LJ_SOFTFP && irt_isnum(kt)) {
+     key = ra_alloc1(as, refkey, RSET_FPR);
+     tmpnum = ra_scratch(as, rset_exclude(RSET_FPR, key));
+   } else if (!irt_ispri(kt)) {
+@@ -882,6 +943,9 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
+     emit_dta(as, MIPSI_DSRA32, tmp1, tmp1, 15);
+     emit_tg(as, MIPSI_DMTC1, tmp1, tmpnum);
+     emit_tsi(as, MIPSI_LD, tmp1, dest, (int32_t)offsetof(Node, key.u64));
++  } else if (LJ_SOFTFP && irt_isnum(kt)) {
++    emit_branch(as, MIPSI_BEQ, tmp1, key, l_end);
++    emit_tsi(as, MIPSI_LD, tmp1, dest, (int32_t)offsetof(Node, key.u64));
+   } else if (irt_isaddr(kt)) {
+     Reg refk = tmp2;
+     if (isk) {
+@@ -960,7 +1024,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
+       emit_dta(as, MIPSI_ROTR, dest, tmp1, (-HASH_ROT1)&31);
+       if (irt_isnum(kt)) {
+       emit_dst(as, MIPSI_ADDU, tmp1, tmp1, tmp1);
+-      emit_dta(as, MIPSI_DSRA32, tmp1, tmp1, 0);
++      emit_dta(as, MIPSI_DSRA32, tmp1, LJ_SOFTFP ? key : tmp1, 0);
+       emit_dta(as, MIPSI_SLL, tmp2, LJ_SOFTFP ? key : tmp1, 0);
+ #if !LJ_SOFTFP
+       emit_tg(as, MIPSI_DMFC1, tmp1, key);
+@@ -1123,7 +1187,7 @@ static MIPSIns asm_fxloadins(IRIns *ir)
+   case IRT_U8: return MIPSI_LBU;
+   case IRT_I16: return MIPSI_LH;
+   case IRT_U16: return MIPSI_LHU;
+-  case IRT_NUM: lua_assert(!LJ_SOFTFP); return MIPSI_LDC1;
++  case IRT_NUM: lua_assert(!LJ_SOFTFP32); if (!LJ_SOFTFP) return MIPSI_LDC1;
+   case IRT_FLOAT: if (!LJ_SOFTFP) return MIPSI_LWC1;
+   default: return (LJ_64 && irt_is64(ir->t)) ? MIPSI_LD : MIPSI_LW;
+   }
+@@ -1134,7 +1198,7 @@ static MIPSIns asm_fxstoreins(IRIns *ir)
+   switch (irt_type(ir->t)) {
+   case IRT_I8: case IRT_U8: return MIPSI_SB;
+   case IRT_I16: case IRT_U16: return MIPSI_SH;
+-  case IRT_NUM: lua_assert(!LJ_SOFTFP); return MIPSI_SDC1;
++  case IRT_NUM: lua_assert(!LJ_SOFTFP32); if (!LJ_SOFTFP) return MIPSI_SDC1;
+   case IRT_FLOAT: if (!LJ_SOFTFP) return MIPSI_SWC1;
+   default: return (LJ_64 && irt_is64(ir->t)) ? MIPSI_SD : MIPSI_SW;
+   }
+@@ -1199,7 +1263,7 @@ static void asm_xstore_(ASMState *as, IRIns *ir, int32_t 
ofs)
+ 
+ static void asm_ahuvload(ASMState *as, IRIns *ir)
+ {
+-  int hiop = (LJ_32 && LJ_SOFTFP && (ir+1)->o == IR_HIOP);
++  int hiop = (LJ_SOFTFP32 && (ir+1)->o == IR_HIOP);
+   Reg dest = RID_NONE, type = RID_TMP, idx;
+   RegSet allow = RSET_GPR;
+   int32_t ofs = 0;
+@@ -1212,7 +1276,7 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
+     }
+   }
+   if (ra_used(ir)) {
+-    lua_assert((LJ_SOFTFP ? 0 : irt_isnum(ir->t)) ||
++    lua_assert((LJ_SOFTFP32 ? 0 : irt_isnum(ir->t)) ||
+              irt_isint(ir->t) || irt_isaddr(ir->t));
+     dest = ra_dest(as, ir, (!LJ_SOFTFP && irt_isnum(t)) ? RSET_FPR : allow);
+     rset_clear(allow, dest);
+@@ -1261,10 +1325,10 @@ static void asm_ahustore(ASMState *as, IRIns *ir)
+   int32_t ofs = 0;
+   if (ir->r == RID_SINK)
+     return;
+-  if (!LJ_SOFTFP && irt_isnum(ir->t)) {
+-    src = ra_alloc1(as, ir->op2, RSET_FPR);
++  if (!LJ_SOFTFP32 && irt_isnum(ir->t)) {
++    src = ra_alloc1(as, ir->op2, LJ_SOFTFP ? RSET_GPR : RSET_FPR);
+     idx = asm_fuseahuref(as, ir->op1, &ofs, allow);
+-    emit_hsi(as, MIPSI_SDC1, src, idx, ofs);
++    emit_hsi(as, LJ_SOFTFP ? MIPSI_SD : MIPSI_SDC1, src, idx, ofs);
+   } else {
+ #if LJ_32
+     if (!irt_ispri(ir->t)) {
+@@ -1312,7 +1376,7 @@ static void asm_sload(ASMState *as, IRIns *ir)
+   IRType1 t = ir->t;
+ #if LJ_32
+   int32_t ofs = 8*((int32_t)ir->op1-1) + ((ir->op2 & IRSLOAD_FRAME) ? 4 : 0);
+-  int hiop = (LJ_32 && LJ_SOFTFP && (ir+1)->o == IR_HIOP);
++  int hiop = (LJ_SOFTFP32 && (ir+1)->o == IR_HIOP);
+   if (hiop)
+     t.irt = IRT_NUM;
+ #else
+@@ -1320,7 +1384,7 @@ static void asm_sload(ASMState *as, IRIns *ir)
+ #endif
+   lua_assert(!(ir->op2 & IRSLOAD_PARENT));  /* Handled by asm_head_side(). */
+   lua_assert(irt_isguard(ir->t) || !(ir->op2 & IRSLOAD_TYPECHECK));
+-#if LJ_32 && LJ_SOFTFP
++#if LJ_SOFTFP32
+   lua_assert(!(ir->op2 & IRSLOAD_CONVERT));  /* Handled by LJ_SOFTFP SPLIT. */
+   if (hiop && ra_used(ir+1)) {
+     type = ra_dest(as, ir+1, allow);
+@@ -1328,29 +1392,44 @@ static void asm_sload(ASMState *as, IRIns *ir)
+   }
+ #else
+   if ((ir->op2 & IRSLOAD_CONVERT) && irt_isguard(t) && irt_isint(t)) {
+-    dest = ra_scratch(as, RSET_FPR);
++    dest = ra_scratch(as, LJ_SOFTFP ? allow : RSET_FPR);
+     asm_tointg(as, ir, dest);
+     t.irt = IRT_NUM;  /* Continue with a regular number type check. */
+   } else
+ #endif
+   if (ra_used(ir)) {
+-    lua_assert((LJ_SOFTFP ? 0 : irt_isnum(ir->t)) ||
++    lua_assert((LJ_SOFTFP32 ? 0 : irt_isnum(ir->t)) ||
+              irt_isint(ir->t) || irt_isaddr(ir->t));
+     dest = ra_dest(as, ir, (!LJ_SOFTFP && irt_isnum(t)) ? RSET_FPR : allow);
+     rset_clear(allow, dest);
+     base = ra_alloc1(as, REF_BASE, allow);
+     rset_clear(allow, base);
+-    if (!LJ_SOFTFP && (ir->op2 & IRSLOAD_CONVERT)) {
++    if (!LJ_SOFTFP32 && (ir->op2 & IRSLOAD_CONVERT)) {
+       if (irt_isint(t)) {
+-      Reg tmp = ra_scratch(as, RSET_FPR);
++      Reg tmp = ra_scratch(as, LJ_SOFTFP ? RSET_GPR : RSET_FPR);
++#if LJ_SOFTFP
++      ra_evictset(as, rset_exclude(RSET_SCRATCH, dest));
++      ra_destreg(as, ir, RID_RET);
++      emit_call(as, (void *)lj_ir_callinfo[IRCALL_softfp_d2i].func, 0);
++      if (tmp != REGARG_FIRSTGPR)
++        emit_move(as, REGARG_FIRSTGPR, tmp);
++#else
+       emit_tg(as, MIPSI_MFC1, dest, tmp);
+       emit_fg(as, MIPSI_TRUNC_W_D, tmp, tmp);
++#endif
+       dest = tmp;
+       t.irt = IRT_NUM;  /* Check for original type. */
+       } else {
+       Reg tmp = ra_scratch(as, RSET_GPR);
++#if LJ_SOFTFP
++      ra_evictset(as, rset_exclude(RSET_SCRATCH, dest));
++      ra_destreg(as, ir, RID_RET);
++      emit_call(as, (void *)lj_ir_callinfo[IRCALL_softfp_i2d].func, 0);
++      emit_dta(as, MIPSI_SLL, REGARG_FIRSTGPR, tmp, 0);
++#else
+       emit_fg(as, MIPSI_CVT_D_W, dest, dest);
+       emit_tg(as, MIPSI_MTC1, tmp, dest);
++#endif
+       dest = tmp;
+       t.irt = IRT_INT;  /* Check for original type. */
+       }
+@@ -1399,7 +1478,7 @@ static void asm_sload(ASMState *as, IRIns *ir)
+       if (irt_isnum(t)) {
+       asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO);
+       emit_tsi(as, MIPSI_SLTIU, RID_TMP, RID_TMP, (int32_t)LJ_TISNUM);
+-      if (ra_hasreg(dest))
++      if (!LJ_SOFTFP && ra_hasreg(dest))
+         emit_hsi(as, MIPSI_LDC1, dest, base, ofs);
+       } else {
+       asm_guard(as, MIPSI_BNE, RID_TMP,
+@@ -1409,7 +1488,7 @@ static void asm_sload(ASMState *as, IRIns *ir)
+     }
+     emit_tsi(as, MIPSI_LD, type, base, ofs);
+   } else if (ra_hasreg(dest)) {
+-    if (irt_isnum(t))
++    if (!LJ_SOFTFP && irt_isnum(t))
+       emit_hsi(as, MIPSI_LDC1, dest, base, ofs);
+     else
+       emit_tsi(as, irt_isint(t) ? MIPSI_LW : MIPSI_LD, dest, base,
+@@ -1548,26 +1627,40 @@ static void asm_fpunary(ASMState *as, IRIns *ir, 
MIPSIns mi)
+   Reg left = ra_hintalloc(as, ir->op1, dest, RSET_FPR);
+   emit_fg(as, mi, dest, left);
+ }
++#endif
+ 
++#if !LJ_SOFTFP32
+ static void asm_fpmath(ASMState *as, IRIns *ir)
+ {
+   if (ir->op2 == IRFPM_EXP2 && asm_fpjoin_pow(as, ir))
+     return;
++#if !LJ_SOFTFP
+   if (ir->op2 <= IRFPM_TRUNC)
+     asm_callround(as, ir, IRCALL_lj_vm_floor + ir->op2);
+   else if (ir->op2 == IRFPM_SQRT)
+     asm_fpunary(as, ir, MIPSI_SQRT_D);
+   else
++#endif
+     asm_callid(as, ir, IRCALL_lj_vm_floor + ir->op2);
+ }
+ #endif
+ 
++#if !LJ_SOFTFP
++#define asm_fpadd(as, ir)     asm_fparith(as, ir, MIPSI_ADD_D)
++#define asm_fpsub(as, ir)     asm_fparith(as, ir, MIPSI_SUB_D)
++#define asm_fpmul(as, ir)     asm_fparith(as, ir, MIPSI_MUL_D)
++#elif LJ_64  /* && LJ_SOFTFP */
++#define asm_fpadd(as, ir)     asm_callid(as, ir, IRCALL_softfp_add)
++#define asm_fpsub(as, ir)     asm_callid(as, ir, IRCALL_softfp_sub)
++#define asm_fpmul(as, ir)     asm_callid(as, ir, IRCALL_softfp_mul)
++#endif
++
+ static void asm_add(ASMState *as, IRIns *ir)
+ {
+   IRType1 t = ir->t;
+-#if !LJ_SOFTFP
++#if !LJ_SOFTFP32
+   if (irt_isnum(t)) {
+-    asm_fparith(as, ir, MIPSI_ADD_D);
++    asm_fpadd(as, ir);
+   } else
+ #endif
+   {
+@@ -1589,9 +1682,9 @@ static void asm_add(ASMState *as, IRIns *ir)
+ 
+ static void asm_sub(ASMState *as, IRIns *ir)
+ {
+-#if !LJ_SOFTFP
++#if !LJ_SOFTFP32
+   if (irt_isnum(ir->t)) {
+-    asm_fparith(as, ir, MIPSI_SUB_D);
++    asm_fpsub(as, ir);
+   } else
+ #endif
+   {
+@@ -1605,9 +1698,9 @@ static void asm_sub(ASMState *as, IRIns *ir)
+ 
+ static void asm_mul(ASMState *as, IRIns *ir)
+ {
+-#if !LJ_SOFTFP
++#if !LJ_SOFTFP32
+   if (irt_isnum(ir->t)) {
+-    asm_fparith(as, ir, MIPSI_MUL_D);
++    asm_fpmul(as, ir);
+   } else
+ #endif
+   {
+@@ -1634,7 +1727,7 @@ static void asm_mod(ASMState *as, IRIns *ir)
+     asm_callid(as, ir, IRCALL_lj_vm_modi);
+ }
+ 
+-#if !LJ_SOFTFP
++#if !LJ_SOFTFP32
+ static void asm_pow(ASMState *as, IRIns *ir)
+ {
+ #if LJ_64 && LJ_HASFFI
+@@ -1654,7 +1747,11 @@ static void asm_div(ASMState *as, IRIns *ir)
+                                         IRCALL_lj_carith_divu64);
+   else
+ #endif
++#if !LJ_SOFTFP
+     asm_fparith(as, ir, MIPSI_DIV_D);
++#else
++  asm_callid(as, ir, IRCALL_softfp_div);
++#endif
+ }
+ #endif
+ 
+@@ -1664,6 +1761,13 @@ static void asm_neg(ASMState *as, IRIns *ir)
+   if (irt_isnum(ir->t)) {
+     asm_fpunary(as, ir, MIPSI_NEG_D);
+   } else
++#elif LJ_64  /* && LJ_SOFTFP */
++  if (irt_isnum(ir->t)) {
++    Reg dest = ra_dest(as, ir, RSET_GPR);
++    Reg left = ra_hintalloc(as, ir->op1, dest, RSET_GPR);
++    emit_dst(as, MIPSI_XOR, dest, left,
++          ra_allock(as, 0x8000000000000000ll, rset_exclude(RSET_GPR, dest)));
++  } else
+ #endif
+   {
+     Reg dest = ra_dest(as, ir, RSET_GPR);
+@@ -1673,7 +1777,17 @@ static void asm_neg(ASMState *as, IRIns *ir)
+   }
+ }
+ 
++#if !LJ_SOFTFP
+ #define asm_abs(as, ir)               asm_fpunary(as, ir, MIPSI_ABS_D)
++#elif LJ_64   /* && LJ_SOFTFP */
++static void asm_abs(ASMState *as, IRIns *ir)
++{
++  Reg dest = ra_dest(as, ir, RSET_GPR);
++  Reg left = ra_alloc1(as, ir->op1, RSET_GPR);
++  emit_tsml(as, MIPSI_DEXTM, dest, left, 30, 0);
++}
++#endif
++
+ #define asm_atan2(as, ir)     asm_callid(as, ir, IRCALL_atan2)
+ #define asm_ldexp(as, ir)     asm_callid(as, ir, IRCALL_ldexp)
+ 
+@@ -1918,15 +2032,21 @@ static void asm_bror(ASMState *as, IRIns *ir)
+   }
+ }
+ 
+-#if LJ_32 && LJ_SOFTFP
++#if LJ_SOFTFP
+ static void asm_sfpmin_max(ASMState *as, IRIns *ir)
+ {
+   CCallInfo ci = lj_ir_callinfo[(IROp)ir->o == IR_MIN ? IRCALL_lj_vm_sfmin : 
IRCALL_lj_vm_sfmax];
++#if LJ_64
++  IRRef args[2];
++  args[0] = ir->op1;
++  args[1] = ir->op2;
++#else
+   IRRef args[4];
+   args[0^LJ_BE] = ir->op1;
+   args[1^LJ_BE] = (ir+1)->op1;
+   args[2^LJ_BE] = ir->op2;
+   args[3^LJ_BE] = (ir+1)->op2;
++#endif
+   asm_setupresult(as, ir, &ci);
+   emit_call(as, (void *)ci.func, 0);
+   ci.func = NULL;
+@@ -1936,7 +2056,10 @@ static void asm_sfpmin_max(ASMState *as, IRIns *ir)
+ 
+ static void asm_min_max(ASMState *as, IRIns *ir, int ismax)
+ {
+-  if (!LJ_SOFTFP && irt_isnum(ir->t)) {
++  if (!LJ_SOFTFP32 && irt_isnum(ir->t)) {
++#if LJ_SOFTFP
++    asm_sfpmin_max(as, ir);
++#else
+     Reg dest = ra_dest(as, ir, RSET_FPR);
+     Reg right, left = ra_alloc2(as, ir, RSET_FPR);
+     right = (left >> 8); left &= 255;
+@@ -1947,6 +2070,7 @@ static void asm_min_max(ASMState *as, IRIns *ir, int 
ismax)
+       if (dest != right) emit_fg(as, MIPSI_MOV_D, dest, right);
+     }
+     emit_fgh(as, MIPSI_C_OLT_D, 0, ismax ? left : right, ismax ? right : 
left);
++#endif
+   } else {
+     Reg dest = ra_dest(as, ir, RSET_GPR);
+     Reg right, left = ra_alloc2(as, ir, RSET_GPR);
+@@ -1967,18 +2091,24 @@ static void asm_min_max(ASMState *as, IRIns *ir, int 
ismax)
+ 
+ /* -- Comparisons --------------------------------------------------------- */
+ 
+-#if LJ_32 && LJ_SOFTFP
++#if LJ_SOFTFP
+ /* SFP comparisons. */
+ static void asm_sfpcomp(ASMState *as, IRIns *ir)
+ {
+   const CCallInfo *ci = &lj_ir_callinfo[IRCALL_softfp_cmp];
+   RegSet drop = RSET_SCRATCH;
+   Reg r;
++#if LJ_64
++  IRRef args[2];
++  args[0] = ir->op1;
++  args[1] = ir->op2;
++#else
+   IRRef args[4];
+   args[LJ_LE ? 0 : 1] = ir->op1; args[LJ_LE ? 1 : 0] = (ir+1)->op1;
+   args[LJ_LE ? 2 : 3] = ir->op2; args[LJ_LE ? 3 : 2] = (ir+1)->op2;
++#endif
+ 
+-  for (r = REGARG_FIRSTGPR; r <= REGARG_FIRSTGPR+3; r++) {
++  for (r = REGARG_FIRSTGPR; r <= REGARG_FIRSTGPR+(LJ_64?1:3); r++) {
+     if (!rset_test(as->freeset, r) &&
+       regcost_ref(as->cost[r]) == args[r-REGARG_FIRSTGPR])
+       rset_clear(drop, r);
+@@ -2032,11 +2162,15 @@ static void asm_comp(ASMState *as, IRIns *ir)
+ {
+   /* ORDER IR: LT GE LE GT  ULT UGE ULE UGT. */
+   IROp op = ir->o;
+-  if (!LJ_SOFTFP && irt_isnum(ir->t)) {
++  if (!LJ_SOFTFP32 && irt_isnum(ir->t)) {
++#if LJ_SOFTFP
++    asm_sfpcomp(as, ir);
++#else
+     Reg right, left = ra_alloc2(as, ir, RSET_FPR);
+     right = (left >> 8); left &= 255;
+     asm_guard(as, (op&1) ? MIPSI_BC1T : MIPSI_BC1F, 0, 0);
+     emit_fgh(as, MIPSI_C_OLT_D + ((op&3) ^ ((op>>2)&1)), 0, left, right);
++#endif
+   } else {
+     Reg right, left = ra_alloc1(as, ir->op1, RSET_GPR);
+     if (op == IR_ABC) op = IR_UGT;
+@@ -2068,9 +2202,13 @@ static void asm_equal(ASMState *as, IRIns *ir)
+   Reg right, left = ra_alloc2(as, ir, (!LJ_SOFTFP && irt_isnum(ir->t)) ?
+                                      RSET_FPR : RSET_GPR);
+   right = (left >> 8); left &= 255;
+-  if (!LJ_SOFTFP && irt_isnum(ir->t)) {
++  if (!LJ_SOFTFP32 && irt_isnum(ir->t)) {
++#if LJ_SOFTFP
++    asm_sfpcomp(as, ir);
++#else
+     asm_guard(as, (ir->o & 1) ? MIPSI_BC1T : MIPSI_BC1F, 0, 0);
+     emit_fgh(as, MIPSI_C_EQ_D, 0, left, right);
++#endif
+   } else {
+     asm_guard(as, (ir->o & 1) ? MIPSI_BEQ : MIPSI_BNE, left, right);
+   }
+@@ -2263,7 +2401,7 @@ static void asm_stack_restore(ASMState *as, SnapShot 
*snap)
+     if ((sn & SNAP_NORESTORE))
+       continue;
+     if (irt_isnum(ir->t)) {
+-#if LJ_SOFTFP
++#if LJ_SOFTFP32
+       Reg tmp;
+       RegSet allow = rset_exclude(RSET_GPR, RID_BASE);
+       lua_assert(irref_isk(ref));  /* LJ_SOFTFP: must be a number constant. */
+@@ -2272,6 +2410,9 @@ static void asm_stack_restore(ASMState *as, SnapShot 
*snap)
+       if (rset_test(as->freeset, tmp+1)) allow = RID2RSET(tmp+1);
+       tmp = ra_allock(as, (int32_t)ir_knum(ir)->u32.hi, allow);
+       emit_tsi(as, MIPSI_SW, tmp, RID_BASE, ofs+(LJ_BE?0:4));
++#elif LJ_SOFTFP  /* && LJ_64 */
++      Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, RID_BASE));
++      emit_tsi(as, MIPSI_SD, src, RID_BASE, ofs);
+ #else
+       Reg src = ra_alloc1(as, ref, RSET_FPR);
+       emit_hsi(as, MIPSI_SDC1, src, RID_BASE, ofs);
+diff --git a/src/lj_crecord.c b/src/lj_crecord.c
+index e32ae23e..fd59e281 100644
+--- a/src/lj_crecord.c
++++ b/src/lj_crecord.c
+@@ -212,7 +212,7 @@ static void crec_copy_emit(jit_State *J, CRecMemList *ml, 
MSize mlp,
+     ml[i].trval = emitir(IRT(IR_XLOAD, ml[i].tp), trsptr, 0);
+     ml[i].trofs = trofs;
+     i++;
+-    rwin += (LJ_SOFTFP && ml[i].tp == IRT_NUM) ? 2 : 1;
++    rwin += (LJ_SOFTFP32 && ml[i].tp == IRT_NUM) ? 2 : 1;
+     if (rwin >= CREC_COPY_REGWIN || i >= mlp) {  /* Flush buffered stores. */
+       rwin = 0;
+       for ( ; j < i; j++) {
+@@ -1130,7 +1130,7 @@ static TRef crec_call_args(jit_State *J, RecordFFData 
*rd,
+       else
+         tr = emitconv(tr, IRT_INT, d->size==1 ? IRT_I8 : IRT_I16,IRCONV_SEXT);
+       }
+-    } else if (LJ_SOFTFP && ctype_isfp(d->info) && d->size > 4) {
++    } else if (LJ_SOFTFP32 && ctype_isfp(d->info) && d->size > 4) {
+       lj_needsplit(J);
+     }
+ #if LJ_TARGET_X86
+diff --git a/src/lj_emit_mips.h b/src/lj_emit_mips.h
+index 8a9ee24d..bb6593ae 100644
+--- a/src/lj_emit_mips.h
++++ b/src/lj_emit_mips.h
+@@ -12,6 +12,8 @@ static intptr_t get_k64val(IRIns *ir)
+     return (intptr_t)ir_kgc(ir);
+   } else if (ir->o == IR_KPTR || ir->o == IR_KKPTR) {
+     return (intptr_t)ir_kptr(ir);
++  } else if (LJ_SOFTFP && ir->o == IR_KNUM) {
++    return (intptr_t)ir_knum(ir)->u64;
+   } else {
+     lua_assert(ir->o == IR_KINT || ir->o == IR_KNULL);
+     return ir->i;  /* Sign-extended. */
+diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c
+index dfdee2db..849d7a27 100644
+--- a/src/lj_ffrecord.c
++++ b/src/lj_ffrecord.c
+@@ -1012,7 +1012,7 @@ static void LJ_FASTCALL recff_string_format(jit_State 
*J, RecordFFData *rd)
+     handle_num:
+       tra = lj_ir_tonum(J, tra);
+       tr = lj_ir_call(J, id, tr, trsf, tra);
+-      if (LJ_SOFTFP) lj_needsplit(J);
++      if (LJ_SOFTFP32) lj_needsplit(J);
+       break;
+     case STRFMT_STR:
+       if (!tref_isstr(tra)) {
+diff --git a/src/lj_ircall.h b/src/lj_ircall.h
+index 973c36e6..73120065 100644
+--- a/src/lj_ircall.h
++++ b/src/lj_ircall.h
+@@ -51,7 +51,7 @@ typedef struct CCallInfo {
+ #define CCI_XARGS(ci)         (((ci)->flags >> CCI_XARGS_SHIFT) & 3)
+ #define CCI_XA                        (1u << CCI_XARGS_SHIFT)
+ 
+-#if LJ_SOFTFP || (LJ_32 && LJ_HASFFI)
++#if LJ_SOFTFP32 || (LJ_32 && LJ_HASFFI)
+ #define CCI_XNARGS(ci)                (CCI_NARGS((ci)) + CCI_XARGS((ci)))
+ #else
+ #define CCI_XNARGS(ci)                CCI_NARGS((ci))
+@@ -78,13 +78,19 @@ typedef struct CCallInfo {
+ #define IRCALLCOND_SOFTFP_FFI(x)      NULL
+ #endif
+ 
+-#if LJ_SOFTFP && LJ_TARGET_MIPS32
++#if LJ_SOFTFP && LJ_TARGET_MIPS
+ #define IRCALLCOND_SOFTFP_MIPS(x)     x
+ #else
+ #define IRCALLCOND_SOFTFP_MIPS(x)     NULL
+ #endif
+ 
+-#define LJ_NEED_FP64  (LJ_TARGET_ARM || LJ_TARGET_PPC || LJ_TARGET_MIPS32)
++#if LJ_SOFTFP && LJ_TARGET_MIPS64
++#define IRCALLCOND_SOFTFP_MIPS64(x)   x
++#else
++#define IRCALLCOND_SOFTFP_MIPS64(x)   NULL
++#endif
++
++#define LJ_NEED_FP64  (LJ_TARGET_ARM || LJ_TARGET_PPC || LJ_TARGET_MIPS)
+ 
+ #if LJ_HASFFI && (LJ_SOFTFP || LJ_NEED_FP64)
+ #define IRCALLCOND_FP64_FFI(x)                x
+@@ -112,6 +118,14 @@ typedef struct CCallInfo {
+ #define XA2_FP                0
+ #endif
+ 
++#if LJ_SOFTFP32
++#define XA_FP32               CCI_XA
++#define XA2_FP32      (CCI_XA+CCI_XA)
++#else
++#define XA_FP32               0
++#define XA2_FP32      0
++#endif
++
+ #if LJ_32
+ #define XA_64         CCI_XA
+ #define XA2_64                (CCI_XA+CCI_XA)
+@@ -181,20 +195,21 @@ typedef struct CCallInfo {
+   _(ANY,      pow,                    2,   N, NUM, XA2_FP) \
+   _(ANY,      atan2,                  2,   N, NUM, XA2_FP) \
+   _(ANY,      ldexp,                  2,   N, NUM, XA_FP) \
+-  _(SOFTFP,   lj_vm_tobit,            2,   N, INT, 0) \
+-  _(SOFTFP,   softfp_add,             4,   N, NUM, 0) \
+-  _(SOFTFP,   softfp_sub,             4,   N, NUM, 0) \
+-  _(SOFTFP,   softfp_mul,             4,   N, NUM, 0) \
+-  _(SOFTFP,   softfp_div,             4,   N, NUM, 0) \
+-  _(SOFTFP,   softfp_cmp,             4,   N, NIL, 0) \
++  _(SOFTFP,   lj_vm_tobit,            1,   N, INT, XA_FP32) \
++  _(SOFTFP,   softfp_add,             2,   N, NUM, XA2_FP32) \
++  _(SOFTFP,   softfp_sub,             2,   N, NUM, XA2_FP32) \
++  _(SOFTFP,   softfp_mul,             2,   N, NUM, XA2_FP32) \
++  _(SOFTFP,   softfp_div,             2,   N, NUM, XA2_FP32) \
++  _(SOFTFP,   softfp_cmp,             2,   N, NIL, XA2_FP32) \
+   _(SOFTFP,   softfp_i2d,             1,   N, NUM, 0) \
+-  _(SOFTFP,   softfp_d2i,             2,   N, INT, 0) \
+-  _(SOFTFP_MIPS, lj_vm_sfmin,         4,   N, NUM, 0) \
+-  _(SOFTFP_MIPS, lj_vm_sfmax,         4,   N, NUM, 0) \
++  _(SOFTFP,   softfp_d2i,             1,   N, INT, XA_FP32) \
++  _(SOFTFP_MIPS, lj_vm_sfmin,         2,   N, NUM, XA2_FP32) \
++  _(SOFTFP_MIPS, lj_vm_sfmax,         2,   N, NUM, XA2_FP32) \
++  _(SOFTFP_MIPS64, lj_vm_tointg,      1,   N, INT, 0) \
+   _(SOFTFP_FFI,       softfp_ui2d,            1,   N, NUM, 0) \
+   _(SOFTFP_FFI,       softfp_f2d,             1,   N, NUM, 0) \
+-  _(SOFTFP_FFI,       softfp_d2ui,            2,   N, INT, 0) \
+-  _(SOFTFP_FFI,       softfp_d2f,             2,   N, FLOAT, 0) \
++  _(SOFTFP_FFI,       softfp_d2ui,            1,   N, INT, XA_FP32) \
++  _(SOFTFP_FFI,       softfp_d2f,             1,   N, FLOAT, XA_FP32) \
+   _(SOFTFP_FFI,       softfp_i2f,             1,   N, FLOAT, 0) \
+   _(SOFTFP_FFI,       softfp_ui2f,            1,   N, FLOAT, 0) \
+   _(SOFTFP_FFI,       softfp_f2i,             1,   N, INT, 0) \
+diff --git a/src/lj_iropt.h b/src/lj_iropt.h
+index 73aef0ef..a59ba3f4 100644
+--- a/src/lj_iropt.h
++++ b/src/lj_iropt.h
+@@ -150,7 +150,7 @@ LJ_FUNC IRType lj_opt_narrow_forl(jit_State *J, cTValue 
*forbase);
+ /* Optimization passes. */
+ LJ_FUNC void lj_opt_dce(jit_State *J);
+ LJ_FUNC int lj_opt_loop(jit_State *J);
+-#if LJ_SOFTFP || (LJ_32 && LJ_HASFFI)
++#if LJ_SOFTFP32 || (LJ_32 && LJ_HASFFI)
+ LJ_FUNC void lj_opt_split(jit_State *J);
+ #else
+ #define lj_opt_split(J)               UNUSED(J)
+diff --git a/src/lj_jit.h b/src/lj_jit.h
+index 2fa8efc4..f37e7927 100644
+--- a/src/lj_jit.h
++++ b/src/lj_jit.h
+@@ -374,7 +374,7 @@ enum {
+   ((TValue *)(((intptr_t)&J->ksimd[2*(n)] + 15) & ~(intptr_t)15))
+ 
+ /* Set/reset flag to activate the SPLIT pass for the current trace. */
+-#if LJ_SOFTFP || (LJ_32 && LJ_HASFFI)
++#if LJ_SOFTFP32 || (LJ_32 && LJ_HASFFI)
+ #define lj_needsplit(J)               (J->needsplit = 1)
+ #define lj_resetsplit(J)      (J->needsplit = 0)
+ #else
+@@ -437,7 +437,7 @@ typedef struct jit_State {
+   MSize sizesnapmap;  /* Size of temp. snapshot map buffer. */
+ 
+   PostProc postproc;  /* Required post-processing after execution. */
+-#if LJ_SOFTFP || (LJ_32 && LJ_HASFFI)
++#if LJ_SOFTFP32 || (LJ_32 && LJ_HASFFI)
+   uint8_t needsplit;  /* Need SPLIT pass. */
+ #endif
+   uint8_t retryrec;   /* Retry recording. */
+diff --git a/src/lj_obj.h b/src/lj_obj.h
+index 52372c3e..c7e47422 100644
+--- a/src/lj_obj.h
++++ b/src/lj_obj.h
+@@ -924,6 +924,9 @@ static LJ_AINLINE void copyTV(lua_State *L, TValue *o1, 
const TValue *o2)
+ 
+ #if LJ_SOFTFP
+ LJ_ASMF int32_t lj_vm_tobit(double x);
++#if LJ_TARGET_MIPS64
++LJ_ASMF int32_t lj_vm_tointg(double x);
++#endif
+ #endif
+ 
+ static LJ_AINLINE int32_t lj_num2bit(lua_Number n)
+diff --git a/src/lj_opt_split.c b/src/lj_opt_split.c
+index fc935204..79ac3cce 100644
+--- a/src/lj_opt_split.c
++++ b/src/lj_opt_split.c
+@@ -8,7 +8,7 @@
+ 
+ #include "lj_obj.h"
+ 
+-#if LJ_HASJIT && (LJ_SOFTFP || (LJ_32 && LJ_HASFFI))
++#if LJ_HASJIT && (LJ_SOFTFP32 || (LJ_32 && LJ_HASFFI))
+ 
+ #include "lj_err.h"
+ #include "lj_buf.h"
+diff --git a/src/lj_snap.c b/src/lj_snap.c
+index bb063c2b..44fa379f 100644
+--- a/src/lj_snap.c
++++ b/src/lj_snap.c
+@@ -93,7 +93,7 @@ static MSize snapshot_slots(jit_State *J, SnapEntry *map, 
BCReg nslots)
+           (ir->op2 & (IRSLOAD_READONLY|IRSLOAD_PARENT)) != IRSLOAD_PARENT)
+         sn |= SNAP_NORESTORE;
+       }
+-      if (LJ_SOFTFP && irt_isnum(ir->t))
++      if (LJ_SOFTFP32 && irt_isnum(ir->t))
+       sn |= SNAP_SOFTFPNUM;
+       map[n++] = sn;
+     }
+@@ -374,7 +374,7 @@ IRIns *lj_snap_regspmap(GCtrace *T, SnapNo snapno, IRIns 
*ir)
+         break;
+       }
+       }
+-    } else if (LJ_SOFTFP && ir->o == IR_HIOP) {
++    } else if (LJ_SOFTFP32 && ir->o == IR_HIOP) {
+       ref++;
+     } else if (ir->o == IR_PVAL) {
+       ref = ir->op1 + REF_BIAS;
+@@ -486,7 +486,7 @@ void lj_snap_replay(jit_State *J, GCtrace *T)
+     } else {
+       IRType t = irt_type(ir->t);
+       uint32_t mode = IRSLOAD_INHERIT|IRSLOAD_PARENT;
+-      if (LJ_SOFTFP && (sn & SNAP_SOFTFPNUM)) t = IRT_NUM;
++      if (LJ_SOFTFP32 && (sn & SNAP_SOFTFPNUM)) t = IRT_NUM;
+       if (ir->o == IR_SLOAD) mode |= (ir->op2 & IRSLOAD_READONLY);
+       tr = emitir_raw(IRT(IR_SLOAD, t), s, mode);
+     }
+@@ -520,7 +520,7 @@ void lj_snap_replay(jit_State *J, GCtrace *T)
+           if (irs->r == RID_SINK && snap_sunk_store(T, ir, irs)) {
+             if (snap_pref(J, T, map, nent, seen, irs->op2) == 0)
+               snap_pref(J, T, map, nent, seen, T->ir[irs->op2].op1);
+-            else if ((LJ_SOFTFP || (LJ_32 && LJ_HASFFI)) &&
++            else if ((LJ_SOFTFP32 || (LJ_32 && LJ_HASFFI)) &&
+                      irs+1 < irlast && (irs+1)->o == IR_HIOP)
+               snap_pref(J, T, map, nent, seen, (irs+1)->op2);
+           }
+@@ -579,10 +579,10 @@ void lj_snap_replay(jit_State *J, GCtrace *T)
+               lua_assert(irc->o == IR_CONV && irc->op2 == IRCONV_NUM_INT);
+               val = snap_pref(J, T, map, nent, seen, irc->op1);
+               val = emitir(IRTN(IR_CONV), val, IRCONV_NUM_INT);
+-            } else if ((LJ_SOFTFP || (LJ_32 && LJ_HASFFI)) &&
++            } else if ((LJ_SOFTFP32 || (LJ_32 && LJ_HASFFI)) &&
+                        irs+1 < irlast && (irs+1)->o == IR_HIOP) {
+               IRType t = IRT_I64;
+-              if (LJ_SOFTFP && irt_type((irs+1)->t) == IRT_SOFTFP)
++              if (LJ_SOFTFP32 && irt_type((irs+1)->t) == IRT_SOFTFP)
+                 t = IRT_NUM;
+               lj_needsplit(J);
+               if (irref_isk(irs->op2) && irref_isk((irs+1)->op2)) {
+@@ -635,7 +635,7 @@ static void snap_restoreval(jit_State *J, GCtrace *T, 
ExitState *ex,
+     int32_t *sps = &ex->spill[regsp_spill(rs)];
+     if (irt_isinteger(t)) {
+       setintV(o, *sps);
+-#if !LJ_SOFTFP
++#if !LJ_SOFTFP32
+     } else if (irt_isnum(t)) {
+       o->u64 = *(uint64_t *)sps;
+ #endif
+@@ -660,6 +660,9 @@ static void snap_restoreval(jit_State *J, GCtrace *T, 
ExitState *ex,
+ #if !LJ_SOFTFP
+     } else if (irt_isnum(t)) {
+       setnumV(o, ex->fpr[r-RID_MIN_FPR]);
++#elif LJ_64  /* && LJ_SOFTFP */
++    } else if (irt_isnum(t)) {
++      o->u64 = ex->gpr[r-RID_MIN_GPR];
+ #endif
+ #if LJ_64 && !LJ_GC64
+     } else if (irt_is64(t)) {
+@@ -813,7 +816,7 @@ static void snap_unsink(jit_State *J, GCtrace *T, 
ExitState *ex,
+         val = lj_tab_set(J->L, t, &tmp);
+         /* NOBARRIER: The table is new (marked white). */
+         snap_restoreval(J, T, ex, snapno, rfilt, irs->op2, val);
+-        if (LJ_SOFTFP && irs+1 < T->ir + T->nins && (irs+1)->o == IR_HIOP) {
++        if (LJ_SOFTFP32 && irs+1 < T->ir + T->nins && (irs+1)->o == IR_HIOP) {
+           snap_restoreval(J, T, ex, snapno, rfilt, (irs+1)->op2, &tmp);
+           val->u32.hi = tmp.u32.lo;
+         }
+@@ -874,7 +877,7 @@ const BCIns *lj_snap_restore(jit_State *J, void *exptr)
+       continue;
+       }
+       snap_restoreval(J, T, ex, snapno, rfilt, ref, o);
+-      if (LJ_SOFTFP && (sn & SNAP_SOFTFPNUM) && tvisint(o)) {
++      if (LJ_SOFTFP32 && (sn & SNAP_SOFTFPNUM) && tvisint(o)) {
+       TValue tmp;
+       snap_restoreval(J, T, ex, snapno, rfilt, ref+1, &tmp);
+       o->u32.hi = tmp.u32.lo;
+diff --git a/src/vm_mips64.dasc b/src/vm_mips64.dasc
+index c06270a0..75b38dee 100644
+--- a/src/vm_mips64.dasc
++++ b/src/vm_mips64.dasc
+@@ -1980,6 +1980,38 @@ static void build_subroutines(BuildCtx *ctx)
+   |1:
+   |  jr ra
+   |.  move CRET1, r0
++  |
++  |// FP number to int conversion with a check for soft-float.
++  |// Modifies CARG1, CRET1, CRET2, TMP0, AT.
++  |->vm_tointg:
++  |.if JIT
++  |  dsll CRET2, CARG1, 1
++  |  beqz CRET2, >2
++  |.  li TMP0, 1076
++  |  dsrl AT, CRET2, 53
++  |  dsubu TMP0, TMP0, AT
++  |  sltiu AT, TMP0, 54
++  |  beqz AT, >1
++  |.  dextm CRET2, CRET2, 0, 20
++  |  dinsu CRET2, AT, 21, 21
++  |  slt AT, CARG1, r0
++  |  dsrlv CRET1, CRET2, TMP0
++  |  dsubu CARG1, r0, CRET1
++  |  movn CRET1, CARG1, AT
++  |  li CARG1, 64
++  |  subu TMP0, CARG1, TMP0
++  |  dsllv CRET2, CRET2, TMP0 // Integer check.
++  |  sextw AT, CRET1
++  |  xor AT, CRET1, AT                // Range check.
++  |  jr ra
++  |.  movz CRET2, AT, CRET2
++  |1:
++  |  jr ra
++  |.  li CRET2, 1
++  |2:
++  |  jr ra
++  |.  move CRET1, r0
++  |.endif
+   |.endif
+   |
+   |.macro .ffunc_bit, name
+@@ -2665,6 +2697,23 @@ static void build_subroutines(BuildCtx *ctx)
+   |.  li CRET1, 0
+   |.endif
+   |
++  |.macro sfmin_max, name, intins
++  |->vm_sf .. name:
++  |.if JIT and not FPU
++  |  move TMP2, ra
++  |  bal ->vm_sfcmpolt
++  |.  nop
++  |  move ra, TMP2
++  |  move TMP0, CRET1
++  |  move CRET1, CARG1
++  |  jr ra
++  |.  intins CRET1, CARG2, TMP0
++  |.endif
++  |.endmacro
++  |
++  |  sfmin_max min, movz
++  |  sfmin_max max, movn
++  |
+   |//-----------------------------------------------------------------------
+   |//-- Miscellaneous functions --------------------------------------------
+   |//-----------------------------------------------------------------------
diff -Nru luajit-2.1.0~beta3+dfsg/debian/patches/series 
luajit-2.1.0~beta3+dfsg/debian/patches/series
--- luajit-2.1.0~beta3+dfsg/debian/patches/series       2017-10-11 
10:48:09.000000000 +0200
+++ luajit-2.1.0~beta3+dfsg/debian/patches/series       2017-10-25 
11:24:21.000000000 +0200
@@ -4,3 +4,5 @@
 0004-Add-ppc64-support-based-on-koriakin-GitHub-patchset.patch
 0005-Make-ccall_copy_struct-static-to-unpollute-global-li.patch
 0006-Fix-register-allocation-bug-in-arm64.patch
+a057a07ab702e225e21848d4f918886c5b0ac06b.patch
+362.patch

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to