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.
This commit is contained in:
Mike Pall 2017-06-07 23:56:54 +02:00
parent 0e4a551809
commit a057a07ab7
13 changed files with 286 additions and 75 deletions

View File

@ -337,9 +337,6 @@
#define LJ_ARCH_BITS 32 #define LJ_ARCH_BITS 32
#define LJ_TARGET_MIPS32 1 #define LJ_TARGET_MIPS32 1
#else #else
#if LJ_ABI_SOFTFP || !LJ_ARCH_HASFPU
#define LJ_ARCH_NOJIT 1 /* NYI */
#endif
#define LJ_ARCH_BITS 64 #define LJ_ARCH_BITS 64
#define LJ_TARGET_MIPS64 1 #define LJ_TARGET_MIPS64 1
#define LJ_TARGET_GC64 1 #define LJ_TARGET_GC64 1
@ -512,6 +509,7 @@
#define LJ_ABI_SOFTFP 0 #define LJ_ABI_SOFTFP 0
#endif #endif
#define LJ_SOFTFP (!LJ_ARCH_HASFPU) #define LJ_SOFTFP (!LJ_ARCH_HASFPU)
#define LJ_SOFTFP32 (LJ_SOFTFP && LJ_32)
#if LJ_ARCH_ENDIAN == LUAJIT_BE #if LJ_ARCH_ENDIAN == LUAJIT_BE
#define LJ_LE 0 #define LJ_LE 0

View File

@ -338,7 +338,7 @@ static Reg ra_rematk(ASMState *as, IRRef ref)
ra_modified(as, r); ra_modified(as, r);
ir->r = RID_INIT; /* Do not keep any hint. */ ir->r = RID_INIT; /* Do not keep any hint. */
RA_DBGX((as, "remat $i $r", ir, r)); RA_DBGX((as, "remat $i $r", ir, r));
#if !LJ_SOFTFP #if !LJ_SOFTFP32
if (ir->o == IR_KNUM) { if (ir->o == IR_KNUM) {
emit_loadk64(as, r, ir); emit_loadk64(as, r, ir);
} else } else
@ -1305,7 +1305,7 @@ static void asm_call(ASMState *as, IRIns *ir)
asm_gencall(as, ci, args); asm_gencall(as, ci, args);
} }
#if !LJ_SOFTFP #if !LJ_SOFTFP32
static void asm_fppow(ASMState *as, IRIns *ir, IRRef lref, IRRef rref) static void asm_fppow(ASMState *as, IRIns *ir, IRRef lref, IRRef rref)
{ {
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_pow]; 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_MUL: asm_mul(as, ir); break;
case IR_MOD: asm_mod(as, ir); break; case IR_MOD: asm_mod(as, ir); break;
case IR_NEG: asm_neg(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_DIV: case IR_POW: case IR_ABS:
case IR_ATAN2: case IR_LDEXP: case IR_FPMATH: case IR_TOBIT: 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; break;
#else #else
case IR_DIV: asm_div(as, ir); break; case IR_DIV: asm_div(as, ir); break;

View File

@ -290,7 +290,7 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
{ {
ra_leftov(as, gpr, ref); ra_leftov(as, gpr, ref);
gpr++; gpr++;
#if LJ_64 #if LJ_64 && !LJ_SOFTFP
fpr++; fpr++;
#endif #endif
} }
@ -301,7 +301,7 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
emit_spstore(as, ir, r, ofs); emit_spstore(as, ir, r, ofs);
ofs += irt_isnum(ir->t) ? 8 : 4; ofs += irt_isnum(ir->t) ? 8 : 4;
#else #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; ofs += 8;
#endif #endif
} }
@ -312,7 +312,7 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
#endif #endif
if (gpr <= REGARG_LASTGPR) { if (gpr <= REGARG_LASTGPR) {
gpr++; gpr++;
#if LJ_64 #if LJ_64 && !LJ_SOFTFP
fpr++; fpr++;
#endif #endif
} else { } else {
@ -461,12 +461,36 @@ static void asm_tobit(ASMState *as, IRIns *ir)
emit_tg(as, MIPSI_MFC1, dest, tmp); emit_tg(as, MIPSI_MFC1, dest, tmp);
emit_fgh(as, MIPSI_ADD_D, tmp, left, right); 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 #endif
static void asm_conv(ASMState *as, IRIns *ir) static void asm_conv(ASMState *as, IRIns *ir)
{ {
IRType st = (IRType)(ir->op2 & IRCONV_SRCMASK); IRType st = (IRType)(ir->op2 & IRCONV_SRCMASK);
#if !LJ_SOFTFP #if !LJ_SOFTFP32
int stfp = (st == IRT_NUM || st == IRT_FLOAT); int stfp = (st == IRT_NUM || st == IRT_FLOAT);
#endif #endif
#if LJ_64 #if LJ_64
@ -477,12 +501,13 @@ static void asm_conv(ASMState *as, IRIns *ir)
lua_assert(!(irt_isint64(ir->t) || lua_assert(!(irt_isint64(ir->t) ||
(st == IRT_I64 || st == IRT_U64))); /* Handled by SPLIT. */ (st == IRT_I64 || st == IRT_U64))); /* Handled by SPLIT. */
#endif #endif
#if LJ_32 && LJ_SOFTFP #if LJ_SOFTFP32
/* FP conversions are handled by SPLIT. */ /* FP conversions are handled by SPLIT. */
lua_assert(!irt_isfp(ir->t) && !(st == IRT_NUM || st == IRT_FLOAT)); 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. */ /* Can't check for same types: SPLIT uses CONV int.int + BXOR for sfp NEG. */
#else #else
lua_assert(irt_type(ir->t) != st); lua_assert(irt_type(ir->t) != st);
#if !LJ_SOFTFP
if (irt_isfp(ir->t)) { if (irt_isfp(ir->t)) {
Reg dest = ra_dest(as, ir, RSET_FPR); Reg dest = ra_dest(as, ir, RSET_FPR);
if (stfp) { /* FP to FP conversion. */ if (stfp) { /* FP to FP conversion. */
@ -608,6 +633,42 @@ static void asm_conv(ASMState *as, IRIns *ir)
} }
} }
} else } 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 #endif
{ {
Reg dest = ra_dest(as, ir, RSET_GPR); 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]; const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_strscan_num];
IRRef args[2]; IRRef args[2];
int32_t ofs = 0; int32_t ofs = 0;
#if LJ_SOFTFP #if LJ_SOFTFP32
ra_evictset(as, RSET_SCRATCH); ra_evictset(as, RSET_SCRATCH);
if (ra_used(ir)) { if (ra_used(ir)) {
if (ra_hasspill(ir->s) && ra_hasspill((ir+1)->s) && 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; MCLabel l_end, l_loop, l_next;
rset_clear(allow, tab); rset_clear(allow, tab);
#if LJ_32 && LJ_SOFTFP #if LJ_SOFTFP32
if (!isk) { if (!isk) {
key = ra_alloc1(as, refkey, allow); key = ra_alloc1(as, refkey, allow);
rset_clear(allow, key); rset_clear(allow, key);
@ -826,7 +887,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
} }
} }
#else #else
if (irt_isnum(kt)) { if (!LJ_SOFTFP && irt_isnum(kt)) {
key = ra_alloc1(as, refkey, RSET_FPR); key = ra_alloc1(as, refkey, RSET_FPR);
tmpnum = ra_scratch(as, rset_exclude(RSET_FPR, key)); tmpnum = ra_scratch(as, rset_exclude(RSET_FPR, key));
} else if (!irt_ispri(kt)) { } 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_dta(as, MIPSI_DSRA32, tmp1, tmp1, 15);
emit_tg(as, MIPSI_DMTC1, tmp1, tmpnum); emit_tg(as, MIPSI_DMTC1, tmp1, tmpnum);
emit_tsi(as, MIPSI_LD, tmp1, dest, (int32_t)offsetof(Node, key.u64)); 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)) { } else if (irt_isaddr(kt)) {
Reg refk = tmp2; Reg refk = tmp2;
if (isk) { 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); emit_dta(as, MIPSI_ROTR, dest, tmp1, (-HASH_ROT1)&31);
if (irt_isnum(kt)) { if (irt_isnum(kt)) {
emit_dst(as, MIPSI_ADDU, tmp1, tmp1, tmp1); 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); emit_dta(as, MIPSI_SLL, tmp2, LJ_SOFTFP ? key : tmp1, 0);
#if !LJ_SOFTFP #if !LJ_SOFTFP
emit_tg(as, MIPSI_DMFC1, tmp1, key); 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_U8: return MIPSI_LBU;
case IRT_I16: return MIPSI_LH; case IRT_I16: return MIPSI_LH;
case IRT_U16: return MIPSI_LHU; 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; case IRT_FLOAT: if (!LJ_SOFTFP) return MIPSI_LWC1;
default: return (LJ_64 && irt_is64(ir->t)) ? MIPSI_LD : MIPSI_LW; 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)) { switch (irt_type(ir->t)) {
case IRT_I8: case IRT_U8: return MIPSI_SB; case IRT_I8: case IRT_U8: return MIPSI_SB;
case IRT_I16: case IRT_U16: return MIPSI_SH; 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; case IRT_FLOAT: if (!LJ_SOFTFP) return MIPSI_SWC1;
default: return (LJ_64 && irt_is64(ir->t)) ? MIPSI_SD : MIPSI_SW; 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) 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; Reg dest = RID_NONE, type = RID_TMP, idx;
RegSet allow = RSET_GPR; RegSet allow = RSET_GPR;
int32_t ofs = 0; int32_t ofs = 0;
@ -1212,7 +1276,7 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
} }
} }
if (ra_used(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)); irt_isint(ir->t) || irt_isaddr(ir->t));
dest = ra_dest(as, ir, (!LJ_SOFTFP && irt_isnum(t)) ? RSET_FPR : allow); dest = ra_dest(as, ir, (!LJ_SOFTFP && irt_isnum(t)) ? RSET_FPR : allow);
rset_clear(allow, dest); rset_clear(allow, dest);
@ -1261,10 +1325,10 @@ static void asm_ahustore(ASMState *as, IRIns *ir)
int32_t ofs = 0; int32_t ofs = 0;
if (ir->r == RID_SINK) if (ir->r == RID_SINK)
return; return;
if (!LJ_SOFTFP && irt_isnum(ir->t)) { if (!LJ_SOFTFP32 && irt_isnum(ir->t)) {
src = ra_alloc1(as, ir->op2, RSET_FPR); src = ra_alloc1(as, ir->op2, LJ_SOFTFP ? RSET_GPR : RSET_FPR);
idx = asm_fuseahuref(as, ir->op1, &ofs, allow); 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 { } else {
#if LJ_32 #if LJ_32
if (!irt_ispri(ir->t)) { if (!irt_ispri(ir->t)) {
@ -1312,7 +1376,7 @@ static void asm_sload(ASMState *as, IRIns *ir)
IRType1 t = ir->t; IRType1 t = ir->t;
#if LJ_32 #if LJ_32
int32_t ofs = 8*((int32_t)ir->op1-1) + ((ir->op2 & IRSLOAD_FRAME) ? 4 : 0); 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) if (hiop)
t.irt = IRT_NUM; t.irt = IRT_NUM;
#else #else
@ -1320,7 +1384,7 @@ static void asm_sload(ASMState *as, IRIns *ir)
#endif #endif
lua_assert(!(ir->op2 & IRSLOAD_PARENT)); /* Handled by asm_head_side(). */ lua_assert(!(ir->op2 & IRSLOAD_PARENT)); /* Handled by asm_head_side(). */
lua_assert(irt_isguard(ir->t) || !(ir->op2 & IRSLOAD_TYPECHECK)); 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. */ lua_assert(!(ir->op2 & IRSLOAD_CONVERT)); /* Handled by LJ_SOFTFP SPLIT. */
if (hiop && ra_used(ir+1)) { if (hiop && ra_used(ir+1)) {
type = ra_dest(as, ir+1, allow); type = ra_dest(as, ir+1, allow);
@ -1328,29 +1392,44 @@ static void asm_sload(ASMState *as, IRIns *ir)
} }
#else #else
if ((ir->op2 & IRSLOAD_CONVERT) && irt_isguard(t) && irt_isint(t)) { 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); asm_tointg(as, ir, dest);
t.irt = IRT_NUM; /* Continue with a regular number type check. */ t.irt = IRT_NUM; /* Continue with a regular number type check. */
} else } else
#endif #endif
if (ra_used(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)); irt_isint(ir->t) || irt_isaddr(ir->t));
dest = ra_dest(as, ir, (!LJ_SOFTFP && irt_isnum(t)) ? RSET_FPR : allow); dest = ra_dest(as, ir, (!LJ_SOFTFP && irt_isnum(t)) ? RSET_FPR : allow);
rset_clear(allow, dest); rset_clear(allow, dest);
base = ra_alloc1(as, REF_BASE, allow); base = ra_alloc1(as, REF_BASE, allow);
rset_clear(allow, base); rset_clear(allow, base);
if (!LJ_SOFTFP && (ir->op2 & IRSLOAD_CONVERT)) { if (!LJ_SOFTFP32 && (ir->op2 & IRSLOAD_CONVERT)) {
if (irt_isint(t)) { 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_tg(as, MIPSI_MFC1, dest, tmp);
emit_fg(as, MIPSI_TRUNC_W_D, tmp, tmp); emit_fg(as, MIPSI_TRUNC_W_D, tmp, tmp);
#endif
dest = tmp; dest = tmp;
t.irt = IRT_NUM; /* Check for original type. */ t.irt = IRT_NUM; /* Check for original type. */
} else { } else {
Reg tmp = ra_scratch(as, RSET_GPR); 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_fg(as, MIPSI_CVT_D_W, dest, dest);
emit_tg(as, MIPSI_MTC1, tmp, dest); emit_tg(as, MIPSI_MTC1, tmp, dest);
#endif
dest = tmp; dest = tmp;
t.irt = IRT_INT; /* Check for original type. */ t.irt = IRT_INT; /* Check for original type. */
} }
@ -1399,7 +1478,7 @@ dotypecheck:
if (irt_isnum(t)) { if (irt_isnum(t)) {
asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO); asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO);
emit_tsi(as, MIPSI_SLTIU, RID_TMP, RID_TMP, (int32_t)LJ_TISNUM); 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); emit_hsi(as, MIPSI_LDC1, dest, base, ofs);
} else { } else {
asm_guard(as, MIPSI_BNE, RID_TMP, asm_guard(as, MIPSI_BNE, RID_TMP,
@ -1409,7 +1488,7 @@ dotypecheck:
} }
emit_tsi(as, MIPSI_LD, type, base, ofs); emit_tsi(as, MIPSI_LD, type, base, ofs);
} else if (ra_hasreg(dest)) { } else if (ra_hasreg(dest)) {
if (irt_isnum(t)) if (!LJ_SOFTFP && irt_isnum(t))
emit_hsi(as, MIPSI_LDC1, dest, base, ofs); emit_hsi(as, MIPSI_LDC1, dest, base, ofs);
else else
emit_tsi(as, irt_isint(t) ? MIPSI_LW : MIPSI_LD, dest, base, 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); Reg left = ra_hintalloc(as, ir->op1, dest, RSET_FPR);
emit_fg(as, mi, dest, left); emit_fg(as, mi, dest, left);
} }
#endif
#if !LJ_SOFTFP32
static void asm_fpmath(ASMState *as, IRIns *ir) static void asm_fpmath(ASMState *as, IRIns *ir)
{ {
if (ir->op2 == IRFPM_EXP2 && asm_fpjoin_pow(as, ir)) if (ir->op2 == IRFPM_EXP2 && asm_fpjoin_pow(as, ir))
return; return;
#if !LJ_SOFTFP
if (ir->op2 <= IRFPM_TRUNC) if (ir->op2 <= IRFPM_TRUNC)
asm_callround(as, ir, IRCALL_lj_vm_floor + ir->op2); asm_callround(as, ir, IRCALL_lj_vm_floor + ir->op2);
else if (ir->op2 == IRFPM_SQRT) else if (ir->op2 == IRFPM_SQRT)
asm_fpunary(as, ir, MIPSI_SQRT_D); asm_fpunary(as, ir, MIPSI_SQRT_D);
else else
#endif
asm_callid(as, ir, IRCALL_lj_vm_floor + ir->op2); asm_callid(as, ir, IRCALL_lj_vm_floor + ir->op2);
} }
#endif #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) static void asm_add(ASMState *as, IRIns *ir)
{ {
IRType1 t = ir->t; IRType1 t = ir->t;
#if !LJ_SOFTFP #if !LJ_SOFTFP32
if (irt_isnum(t)) { if (irt_isnum(t)) {
asm_fparith(as, ir, MIPSI_ADD_D); asm_fpadd(as, ir);
} else } else
#endif #endif
{ {
@ -1589,9 +1682,9 @@ static void asm_add(ASMState *as, IRIns *ir)
static void asm_sub(ASMState *as, IRIns *ir) static void asm_sub(ASMState *as, IRIns *ir)
{ {
#if !LJ_SOFTFP #if !LJ_SOFTFP32
if (irt_isnum(ir->t)) { if (irt_isnum(ir->t)) {
asm_fparith(as, ir, MIPSI_SUB_D); asm_fpsub(as, ir);
} else } else
#endif #endif
{ {
@ -1605,9 +1698,9 @@ static void asm_sub(ASMState *as, IRIns *ir)
static void asm_mul(ASMState *as, IRIns *ir) static void asm_mul(ASMState *as, IRIns *ir)
{ {
#if !LJ_SOFTFP #if !LJ_SOFTFP32
if (irt_isnum(ir->t)) { if (irt_isnum(ir->t)) {
asm_fparith(as, ir, MIPSI_MUL_D); asm_fpmul(as, ir);
} else } else
#endif #endif
{ {
@ -1634,7 +1727,7 @@ static void asm_mod(ASMState *as, IRIns *ir)
asm_callid(as, ir, IRCALL_lj_vm_modi); asm_callid(as, ir, IRCALL_lj_vm_modi);
} }
#if !LJ_SOFTFP #if !LJ_SOFTFP32
static void asm_pow(ASMState *as, IRIns *ir) static void asm_pow(ASMState *as, IRIns *ir)
{ {
#if LJ_64 && LJ_HASFFI #if LJ_64 && LJ_HASFFI
@ -1654,7 +1747,11 @@ static void asm_div(ASMState *as, IRIns *ir)
IRCALL_lj_carith_divu64); IRCALL_lj_carith_divu64);
else else
#endif #endif
#if !LJ_SOFTFP
asm_fparith(as, ir, MIPSI_DIV_D); asm_fparith(as, ir, MIPSI_DIV_D);
#else
asm_callid(as, ir, IRCALL_softfp_div);
#endif
} }
#endif #endif
@ -1664,6 +1761,13 @@ static void asm_neg(ASMState *as, IRIns *ir)
if (irt_isnum(ir->t)) { if (irt_isnum(ir->t)) {
asm_fpunary(as, ir, MIPSI_NEG_D); asm_fpunary(as, ir, MIPSI_NEG_D);
} else } 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 #endif
{ {
Reg dest = ra_dest(as, ir, RSET_GPR); 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) #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_atan2(as, ir) asm_callid(as, ir, IRCALL_atan2)
#define asm_ldexp(as, ir) asm_callid(as, ir, IRCALL_ldexp) #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) 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]; 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]; IRRef args[4];
args[0^LJ_BE] = ir->op1; args[0^LJ_BE] = ir->op1;
args[1^LJ_BE] = (ir+1)->op1; args[1^LJ_BE] = (ir+1)->op1;
args[2^LJ_BE] = ir->op2; args[2^LJ_BE] = ir->op2;
args[3^LJ_BE] = (ir+1)->op2; args[3^LJ_BE] = (ir+1)->op2;
#endif
asm_setupresult(as, ir, &ci); asm_setupresult(as, ir, &ci);
emit_call(as, (void *)ci.func, 0); emit_call(as, (void *)ci.func, 0);
ci.func = NULL; 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) 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 dest = ra_dest(as, ir, RSET_FPR);
Reg right, left = ra_alloc2(as, ir, RSET_FPR); Reg right, left = ra_alloc2(as, ir, RSET_FPR);
right = (left >> 8); left &= 255; 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); 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); emit_fgh(as, MIPSI_C_OLT_D, 0, ismax ? left : right, ismax ? right : left);
#endif
} else { } else {
Reg dest = ra_dest(as, ir, RSET_GPR); Reg dest = ra_dest(as, ir, RSET_GPR);
Reg right, left = ra_alloc2(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 --------------------------------------------------------- */ /* -- Comparisons --------------------------------------------------------- */
#if LJ_32 && LJ_SOFTFP #if LJ_SOFTFP
/* SFP comparisons. */ /* SFP comparisons. */
static void asm_sfpcomp(ASMState *as, IRIns *ir) static void asm_sfpcomp(ASMState *as, IRIns *ir)
{ {
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_softfp_cmp]; const CCallInfo *ci = &lj_ir_callinfo[IRCALL_softfp_cmp];
RegSet drop = RSET_SCRATCH; RegSet drop = RSET_SCRATCH;
Reg r; Reg r;
#if LJ_64
IRRef args[2];
args[0] = ir->op1;
args[1] = ir->op2;
#else
IRRef args[4]; IRRef args[4];
args[LJ_LE ? 0 : 1] = ir->op1; args[LJ_LE ? 1 : 0] = (ir+1)->op1; 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; 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) && if (!rset_test(as->freeset, r) &&
regcost_ref(as->cost[r]) == args[r-REGARG_FIRSTGPR]) regcost_ref(as->cost[r]) == args[r-REGARG_FIRSTGPR])
rset_clear(drop, r); 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. */ /* ORDER IR: LT GE LE GT ULT UGE ULE UGT. */
IROp op = ir->o; 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); Reg right, left = ra_alloc2(as, ir, RSET_FPR);
right = (left >> 8); left &= 255; right = (left >> 8); left &= 255;
asm_guard(as, (op&1) ? MIPSI_BC1T : MIPSI_BC1F, 0, 0); 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); emit_fgh(as, MIPSI_C_OLT_D + ((op&3) ^ ((op>>2)&1)), 0, left, right);
#endif
} else { } else {
Reg right, left = ra_alloc1(as, ir->op1, RSET_GPR); Reg right, left = ra_alloc1(as, ir->op1, RSET_GPR);
if (op == IR_ABC) op = IR_UGT; 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)) ? Reg right, left = ra_alloc2(as, ir, (!LJ_SOFTFP && irt_isnum(ir->t)) ?
RSET_FPR : RSET_GPR); RSET_FPR : RSET_GPR);
right = (left >> 8); left &= 255; 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); asm_guard(as, (ir->o & 1) ? MIPSI_BC1T : MIPSI_BC1F, 0, 0);
emit_fgh(as, MIPSI_C_EQ_D, 0, left, right); emit_fgh(as, MIPSI_C_EQ_D, 0, left, right);
#endif
} else { } else {
asm_guard(as, (ir->o & 1) ? MIPSI_BEQ : MIPSI_BNE, left, right); 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)) if ((sn & SNAP_NORESTORE))
continue; continue;
if (irt_isnum(ir->t)) { if (irt_isnum(ir->t)) {
#if LJ_SOFTFP #if LJ_SOFTFP32
Reg tmp; Reg tmp;
RegSet allow = rset_exclude(RSET_GPR, RID_BASE); RegSet allow = rset_exclude(RSET_GPR, RID_BASE);
lua_assert(irref_isk(ref)); /* LJ_SOFTFP: must be a number constant. */ 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); if (rset_test(as->freeset, tmp+1)) allow = RID2RSET(tmp+1);
tmp = ra_allock(as, (int32_t)ir_knum(ir)->u32.hi, allow); 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)); 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 #else
Reg src = ra_alloc1(as, ref, RSET_FPR); Reg src = ra_alloc1(as, ref, RSET_FPR);
emit_hsi(as, MIPSI_SDC1, src, RID_BASE, ofs); emit_hsi(as, MIPSI_SDC1, src, RID_BASE, ofs);

View File

@ -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].trval = emitir(IRT(IR_XLOAD, ml[i].tp), trsptr, 0);
ml[i].trofs = trofs; ml[i].trofs = trofs;
i++; 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. */ if (rwin >= CREC_COPY_REGWIN || i >= mlp) { /* Flush buffered stores. */
rwin = 0; rwin = 0;
for ( ; j < i; j++) { for ( ; j < i; j++) {
@ -1130,7 +1130,7 @@ static TRef crec_call_args(jit_State *J, RecordFFData *rd,
else else
tr = emitconv(tr, IRT_INT, d->size==1 ? IRT_I8 : IRT_I16,IRCONV_SEXT); 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); lj_needsplit(J);
} }
#if LJ_TARGET_X86 #if LJ_TARGET_X86

View File

@ -12,6 +12,8 @@ static intptr_t get_k64val(IRIns *ir)
return (intptr_t)ir_kgc(ir); return (intptr_t)ir_kgc(ir);
} else if (ir->o == IR_KPTR || ir->o == IR_KKPTR) { } else if (ir->o == IR_KPTR || ir->o == IR_KKPTR) {
return (intptr_t)ir_kptr(ir); return (intptr_t)ir_kptr(ir);
} else if (LJ_SOFTFP && ir->o == IR_KNUM) {
return (intptr_t)ir_knum(ir)->u64;
} else { } else {
lua_assert(ir->o == IR_KINT || ir->o == IR_KNULL); lua_assert(ir->o == IR_KINT || ir->o == IR_KNULL);
return ir->i; /* Sign-extended. */ return ir->i; /* Sign-extended. */

View File

@ -1012,7 +1012,7 @@ static void LJ_FASTCALL recff_string_format(jit_State *J, RecordFFData *rd)
handle_num: handle_num:
tra = lj_ir_tonum(J, tra); tra = lj_ir_tonum(J, tra);
tr = lj_ir_call(J, id, tr, trsf, tra); tr = lj_ir_call(J, id, tr, trsf, tra);
if (LJ_SOFTFP) lj_needsplit(J); if (LJ_SOFTFP32) lj_needsplit(J);
break; break;
case STRFMT_STR: case STRFMT_STR:
if (!tref_isstr(tra)) { if (!tref_isstr(tra)) {

View File

@ -51,7 +51,7 @@ typedef struct CCallInfo {
#define CCI_XARGS(ci) (((ci)->flags >> CCI_XARGS_SHIFT) & 3) #define CCI_XARGS(ci) (((ci)->flags >> CCI_XARGS_SHIFT) & 3)
#define CCI_XA (1u << CCI_XARGS_SHIFT) #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))) #define CCI_XNARGS(ci) (CCI_NARGS((ci)) + CCI_XARGS((ci)))
#else #else
#define CCI_XNARGS(ci) CCI_NARGS((ci)) #define CCI_XNARGS(ci) CCI_NARGS((ci))
@ -78,13 +78,19 @@ typedef struct CCallInfo {
#define IRCALLCOND_SOFTFP_FFI(x) NULL #define IRCALLCOND_SOFTFP_FFI(x) NULL
#endif #endif
#if LJ_SOFTFP && LJ_TARGET_MIPS32 #if LJ_SOFTFP && LJ_TARGET_MIPS
#define IRCALLCOND_SOFTFP_MIPS(x) x #define IRCALLCOND_SOFTFP_MIPS(x) x
#else #else
#define IRCALLCOND_SOFTFP_MIPS(x) NULL #define IRCALLCOND_SOFTFP_MIPS(x) NULL
#endif #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) #if LJ_HASFFI && (LJ_SOFTFP || LJ_NEED_FP64)
#define IRCALLCOND_FP64_FFI(x) x #define IRCALLCOND_FP64_FFI(x) x
@ -112,6 +118,14 @@ typedef struct CCallInfo {
#define XA2_FP 0 #define XA2_FP 0
#endif #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 #if LJ_32
#define XA_64 CCI_XA #define XA_64 CCI_XA
#define XA2_64 (CCI_XA+CCI_XA) #define XA2_64 (CCI_XA+CCI_XA)
@ -181,20 +195,21 @@ typedef struct CCallInfo {
_(ANY, pow, 2, N, NUM, XA2_FP) \ _(ANY, pow, 2, N, NUM, XA2_FP) \
_(ANY, atan2, 2, N, NUM, XA2_FP) \ _(ANY, atan2, 2, N, NUM, XA2_FP) \
_(ANY, ldexp, 2, N, NUM, XA_FP) \ _(ANY, ldexp, 2, N, NUM, XA_FP) \
_(SOFTFP, lj_vm_tobit, 2, N, INT, 0) \ _(SOFTFP, lj_vm_tobit, 1, N, INT, XA_FP32) \
_(SOFTFP, softfp_add, 4, N, NUM, 0) \ _(SOFTFP, softfp_add, 2, N, NUM, XA2_FP32) \
_(SOFTFP, softfp_sub, 4, N, NUM, 0) \ _(SOFTFP, softfp_sub, 2, N, NUM, XA2_FP32) \
_(SOFTFP, softfp_mul, 4, N, NUM, 0) \ _(SOFTFP, softfp_mul, 2, N, NUM, XA2_FP32) \
_(SOFTFP, softfp_div, 4, N, NUM, 0) \ _(SOFTFP, softfp_div, 2, N, NUM, XA2_FP32) \
_(SOFTFP, softfp_cmp, 4, N, NIL, 0) \ _(SOFTFP, softfp_cmp, 2, N, NIL, XA2_FP32) \
_(SOFTFP, softfp_i2d, 1, N, NUM, 0) \ _(SOFTFP, softfp_i2d, 1, N, NUM, 0) \
_(SOFTFP, softfp_d2i, 2, N, INT, 0) \ _(SOFTFP, softfp_d2i, 1, N, INT, XA_FP32) \
_(SOFTFP_MIPS, lj_vm_sfmin, 4, N, NUM, 0) \ _(SOFTFP_MIPS, lj_vm_sfmin, 2, N, NUM, XA2_FP32) \
_(SOFTFP_MIPS, lj_vm_sfmax, 4, N, NUM, 0) \ _(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_ui2d, 1, N, NUM, 0) \
_(SOFTFP_FFI, softfp_f2d, 1, N, NUM, 0) \ _(SOFTFP_FFI, softfp_f2d, 1, N, NUM, 0) \
_(SOFTFP_FFI, softfp_d2ui, 2, N, INT, 0) \ _(SOFTFP_FFI, softfp_d2ui, 1, N, INT, XA_FP32) \
_(SOFTFP_FFI, softfp_d2f, 2, N, FLOAT, 0) \ _(SOFTFP_FFI, softfp_d2f, 1, N, FLOAT, XA_FP32) \
_(SOFTFP_FFI, softfp_i2f, 1, N, FLOAT, 0) \ _(SOFTFP_FFI, softfp_i2f, 1, N, FLOAT, 0) \
_(SOFTFP_FFI, softfp_ui2f, 1, N, FLOAT, 0) \ _(SOFTFP_FFI, softfp_ui2f, 1, N, FLOAT, 0) \
_(SOFTFP_FFI, softfp_f2i, 1, N, INT, 0) \ _(SOFTFP_FFI, softfp_f2i, 1, N, INT, 0) \

View File

@ -150,7 +150,7 @@ LJ_FUNC IRType lj_opt_narrow_forl(jit_State *J, cTValue *forbase);
/* Optimization passes. */ /* Optimization passes. */
LJ_FUNC void lj_opt_dce(jit_State *J); LJ_FUNC void lj_opt_dce(jit_State *J);
LJ_FUNC int lj_opt_loop(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); LJ_FUNC void lj_opt_split(jit_State *J);
#else #else
#define lj_opt_split(J) UNUSED(J) #define lj_opt_split(J) UNUSED(J)

View File

@ -374,7 +374,7 @@ enum {
((TValue *)(((intptr_t)&J->ksimd[2*(n)] + 15) & ~(intptr_t)15)) ((TValue *)(((intptr_t)&J->ksimd[2*(n)] + 15) & ~(intptr_t)15))
/* Set/reset flag to activate the SPLIT pass for the current trace. */ /* 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_needsplit(J) (J->needsplit = 1)
#define lj_resetsplit(J) (J->needsplit = 0) #define lj_resetsplit(J) (J->needsplit = 0)
#else #else
@ -437,7 +437,7 @@ typedef struct jit_State {
MSize sizesnapmap; /* Size of temp. snapshot map buffer. */ MSize sizesnapmap; /* Size of temp. snapshot map buffer. */
PostProc postproc; /* Required post-processing after execution. */ 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. */ uint8_t needsplit; /* Need SPLIT pass. */
#endif #endif
uint8_t retryrec; /* Retry recording. */ uint8_t retryrec; /* Retry recording. */

View File

@ -924,6 +924,9 @@ static LJ_AINLINE void copyTV(lua_State *L, TValue *o1, const TValue *o2)
#if LJ_SOFTFP #if LJ_SOFTFP
LJ_ASMF int32_t lj_vm_tobit(double x); LJ_ASMF int32_t lj_vm_tobit(double x);
#if LJ_TARGET_MIPS64
LJ_ASMF int32_t lj_vm_tointg(double x);
#endif
#endif #endif
static LJ_AINLINE int32_t lj_num2bit(lua_Number n) static LJ_AINLINE int32_t lj_num2bit(lua_Number n)

View File

@ -8,7 +8,7 @@
#include "lj_obj.h" #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_err.h"
#include "lj_buf.h" #include "lj_buf.h"

View File

@ -93,7 +93,7 @@ static MSize snapshot_slots(jit_State *J, SnapEntry *map, BCReg nslots)
(ir->op2 & (IRSLOAD_READONLY|IRSLOAD_PARENT)) != IRSLOAD_PARENT) (ir->op2 & (IRSLOAD_READONLY|IRSLOAD_PARENT)) != IRSLOAD_PARENT)
sn |= SNAP_NORESTORE; sn |= SNAP_NORESTORE;
} }
if (LJ_SOFTFP && irt_isnum(ir->t)) if (LJ_SOFTFP32 && irt_isnum(ir->t))
sn |= SNAP_SOFTFPNUM; sn |= SNAP_SOFTFPNUM;
map[n++] = sn; map[n++] = sn;
} }
@ -374,7 +374,7 @@ IRIns *lj_snap_regspmap(GCtrace *T, SnapNo snapno, IRIns *ir)
break; break;
} }
} }
} else if (LJ_SOFTFP && ir->o == IR_HIOP) { } else if (LJ_SOFTFP32 && ir->o == IR_HIOP) {
ref++; ref++;
} else if (ir->o == IR_PVAL) { } else if (ir->o == IR_PVAL) {
ref = ir->op1 + REF_BIAS; ref = ir->op1 + REF_BIAS;
@ -486,7 +486,7 @@ void lj_snap_replay(jit_State *J, GCtrace *T)
} else { } else {
IRType t = irt_type(ir->t); IRType t = irt_type(ir->t);
uint32_t mode = IRSLOAD_INHERIT|IRSLOAD_PARENT; 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); if (ir->o == IR_SLOAD) mode |= (ir->op2 & IRSLOAD_READONLY);
tr = emitir_raw(IRT(IR_SLOAD, t), s, mode); 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 (irs->r == RID_SINK && snap_sunk_store(T, ir, irs)) {
if (snap_pref(J, T, map, nent, seen, irs->op2) == 0) if (snap_pref(J, T, map, nent, seen, irs->op2) == 0)
snap_pref(J, T, map, nent, seen, T->ir[irs->op2].op1); 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) irs+1 < irlast && (irs+1)->o == IR_HIOP)
snap_pref(J, T, map, nent, seen, (irs+1)->op2); 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); lua_assert(irc->o == IR_CONV && irc->op2 == IRCONV_NUM_INT);
val = snap_pref(J, T, map, nent, seen, irc->op1); val = snap_pref(J, T, map, nent, seen, irc->op1);
val = emitir(IRTN(IR_CONV), val, IRCONV_NUM_INT); 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) { irs+1 < irlast && (irs+1)->o == IR_HIOP) {
IRType t = IRT_I64; 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; t = IRT_NUM;
lj_needsplit(J); lj_needsplit(J);
if (irref_isk(irs->op2) && irref_isk((irs+1)->op2)) { 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)]; int32_t *sps = &ex->spill[regsp_spill(rs)];
if (irt_isinteger(t)) { if (irt_isinteger(t)) {
setintV(o, *sps); setintV(o, *sps);
#if !LJ_SOFTFP #if !LJ_SOFTFP32
} else if (irt_isnum(t)) { } else if (irt_isnum(t)) {
o->u64 = *(uint64_t *)sps; o->u64 = *(uint64_t *)sps;
#endif #endif
@ -660,6 +660,9 @@ static void snap_restoreval(jit_State *J, GCtrace *T, ExitState *ex,
#if !LJ_SOFTFP #if !LJ_SOFTFP
} else if (irt_isnum(t)) { } else if (irt_isnum(t)) {
setnumV(o, ex->fpr[r-RID_MIN_FPR]); 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 #endif
#if LJ_64 && !LJ_GC64 #if LJ_64 && !LJ_GC64
} else if (irt_is64(t)) { } 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); val = lj_tab_set(J->L, t, &tmp);
/* NOBARRIER: The table is new (marked white). */ /* NOBARRIER: The table is new (marked white). */
snap_restoreval(J, T, ex, snapno, rfilt, irs->op2, val); 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); snap_restoreval(J, T, ex, snapno, rfilt, (irs+1)->op2, &tmp);
val->u32.hi = tmp.u32.lo; val->u32.hi = tmp.u32.lo;
} }
@ -874,7 +877,7 @@ const BCIns *lj_snap_restore(jit_State *J, void *exptr)
continue; continue;
} }
snap_restoreval(J, T, ex, snapno, rfilt, ref, o); 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; TValue tmp;
snap_restoreval(J, T, ex, snapno, rfilt, ref+1, &tmp); snap_restoreval(J, T, ex, snapno, rfilt, ref+1, &tmp);
o->u32.hi = tmp.u32.lo; o->u32.hi = tmp.u32.lo;

View File

@ -1980,6 +1980,38 @@ static void build_subroutines(BuildCtx *ctx)
|1: |1:
| jr ra | jr ra
|. move CRET1, r0 |. 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 |.endif
| |
|.macro .ffunc_bit, name |.macro .ffunc_bit, name
@ -2665,6 +2697,23 @@ static void build_subroutines(BuildCtx *ctx)
|. li CRET1, 0 |. li CRET1, 0
|.endif |.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 -------------------------------------------- |//-- Miscellaneous functions --------------------------------------------
|//----------------------------------------------------------------------- |//-----------------------------------------------------------------------