Merge remote-tracking branch 'upstream/v2.1' into HEAD

This commit is contained in:
Gustavo Serra Scalet 2017-08-30 11:29:38 -03:00
commit 48c3bd676c
27 changed files with 1435 additions and 363 deletions

View File

@ -864,7 +864,7 @@ place of a type, you'd need to use <tt>ffi.typeof("int")</tt> instead.
<p> <p>
The main use for parameterized types are libraries implementing abstract The main use for parameterized types are libraries implementing abstract
data types data types
(<a href="http://www.freelists.org/post/luajit/ffi-type-of-pointer-to,8"><span class="ext">&raquo;</span>&nbsp;example</a>), (<a href="https://www.freelists.org/post/luajit/ffi-type-of-pointer-to,8">example</a>),
similar to what can be achieved with C++ template metaprogramming. similar to what can be achieved with C++ template metaprogramming.
Another use case are derived types of anonymous structs, which avoids Another use case are derived types of anonymous structs, which avoids
pollution of the global struct namespace. pollution of the global struct namespace.

View File

@ -209,7 +209,7 @@ TARGET_CC= $(STATIC_CC)
TARGET_STCC= $(STATIC_CC) TARGET_STCC= $(STATIC_CC)
TARGET_DYNCC= $(DYNAMIC_CC) TARGET_DYNCC= $(DYNAMIC_CC)
TARGET_LD= $(CROSS)$(CC) TARGET_LD= $(CROSS)$(CC)
TARGET_AR= $(CROSS)ar rcus 2>/dev/null TARGET_AR= $(CROSS)ar rcus
TARGET_STRIP= $(CROSS)strip TARGET_STRIP= $(CROSS)strip
TARGET_LIBPATH= $(or $(PREFIX),/usr/local)/$(or $(MULTILIB),lib) TARGET_LIBPATH= $(or $(PREFIX),/usr/local)/$(or $(MULTILIB),lib)
@ -308,6 +308,7 @@ ifeq (Windows,$(TARGET_SYS))
TARGET_XSHLDFLAGS= -shared TARGET_XSHLDFLAGS= -shared
TARGET_DYNXLDOPTS= TARGET_DYNXLDOPTS=
else else
TARGET_AR+= 2>/dev/null
ifeq (,$(shell $(TARGET_CC) -o /dev/null -c -x c /dev/null -fno-stack-protector 2>/dev/null || echo 1)) ifeq (,$(shell $(TARGET_CC) -o /dev/null -c -x c /dev/null -fno-stack-protector 2>/dev/null || echo 1))
TARGET_XCFLAGS+= -fno-stack-protector TARGET_XCFLAGS+= -fno-stack-protector
endif endif

View File

@ -347,7 +347,7 @@ void emit_asm(BuildCtx *ctx)
#if !(LJ_TARGET_PS3 || LJ_TARGET_PSVITA) #if !(LJ_TARGET_PS3 || LJ_TARGET_PSVITA)
fprintf(ctx->fp, "\t.section .note.GNU-stack,\"\"," ELFASM_PX "progbits\n"); fprintf(ctx->fp, "\t.section .note.GNU-stack,\"\"," ELFASM_PX "progbits\n");
#endif #endif
#if LJ_TARGET_PPC && !LJ_TARGET_PS3 #if LJ_TARGET_PPC && !LJ_TARGET_PS3 && !LJ_ABI_SOFTFP
/* Hard-float ABI. */ /* Hard-float ABI. */
fprintf(ctx->fp, "\t.gnu_attribute 4, 1\n"); fprintf(ctx->fp, "\t.gnu_attribute 4, 1\n");
#endif #endif

View File

@ -343,7 +343,7 @@ static void *CALL_MMAP(size_t size)
} }
#endif #endif
#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && !LJ_TARGET_PS4 #if LJ_64 && !LJ_GC64 && ((defined(__FreeBSD__) && __FreeBSD__ < 10) || defined(__FreeBSD_kernel__)) && !LJ_TARGET_PS4
#include <sys/resource.h> #include <sys/resource.h>

View File

@ -254,6 +254,29 @@
#else #else
#define LJ_ARCH_BITS 32 #define LJ_ARCH_BITS 32
#define LJ_ARCH_NAME "ppc" #define LJ_ARCH_NAME "ppc"
#if !defined(LJ_ARCH_HASFPU)
#if defined(_SOFT_FLOAT) || defined(_SOFT_DOUBLE)
#define LJ_ARCH_HASFPU 0
#else
#define LJ_ARCH_HASFPU 1
#endif
#endif
#if !defined(LJ_ABI_SOFTFP)
#if defined(_SOFT_FLOAT) || defined(_SOFT_DOUBLE)
#define LJ_ABI_SOFTFP 1
#else
#define LJ_ABI_SOFTFP 0
#endif
#endif
#endif
#if LJ_ABI_SOFTFP
#define LJ_ARCH_NOJIT 1 /* NYI */
#define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL
#else
#define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL_SINGLE
#endif #endif
#define LJ_TARGET_PPC 1 #define LJ_TARGET_PPC 1
@ -262,7 +285,6 @@
#define LJ_TARGET_MASKSHIFT 0 #define LJ_TARGET_MASKSHIFT 0
#define LJ_TARGET_MASKROT 1 #define LJ_TARGET_MASKROT 1
#define LJ_TARGET_UNIFYROT 1 /* Want only IR_BROL. */ #define LJ_TARGET_UNIFYROT 1 /* Want only IR_BROL. */
#define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL_SINGLE
#if LJ_TARGET_CONSOLE #if LJ_TARGET_CONSOLE
#define LJ_ARCH_PPC32ON64 1 #define LJ_ARCH_PPC32ON64 1
@ -337,9 +359,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
@ -418,16 +437,13 @@
#error "No support for ILP32 model on ARM64" #error "No support for ILP32 model on ARM64"
#endif #endif
#elif LJ_TARGET_PPC #elif LJ_TARGET_PPC
#if defined(_SOFT_FLOAT) || defined(_SOFT_DOUBLE)
#error "No support for PowerPC CPUs without double-precision FPU"
#endif
#if !LJ_ARCH_PPC64 && LJ_ARCH_ENDIAN == LUAJIT_LE #if !LJ_ARCH_PPC64 && LJ_ARCH_ENDIAN == LUAJIT_LE
#error "No support for little-endian PPC32" #error "No support for little-endian PPC32"
#endif #endif
#if LJ_ARCH_PPC64 && LJ_ARCH_ENDIAN == LUAJIT_BE #if LJ_ARCH_PPC64 && LJ_ARCH_ENDIAN == LUAJIT_BE
#error "No support for big-endian PPC64" #error "No support for big-endian PPC64"
#endif #endif
#ifdef __NO_FPRS__ #if defined(__NO_FPRS__) && !defined(_SOFT_FLOAT)
#error "No support for PPC/e500 anymore (use LuaJIT 2.0)" #error "No support for PPC/e500 anymore (use LuaJIT 2.0)"
#endif #endif
#elif LJ_TARGET_MIPS32 #elif LJ_TARGET_MIPS32
@ -512,6 +528,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

@ -65,10 +65,9 @@ static Reg ra_alloc2(ASMState *as, IRIns *ir, RegSet allow)
static void asm_sparejump_setup(ASMState *as) static void asm_sparejump_setup(ASMState *as)
{ {
MCode *mxp = as->mcbot; MCode *mxp = as->mcbot;
/* Assumes sizeof(MCLink) == 8. */ if (((uintptr_t)mxp & (LJ_PAGESIZE-1)) == sizeof(MCLink)) {
if (((uintptr_t)mxp & (LJ_PAGESIZE-1)) == 8) {
lua_assert(MIPSI_NOP == 0); lua_assert(MIPSI_NOP == 0);
memset(mxp+2, 0, MIPS_SPAREJUMP*8); memset(mxp, 0, MIPS_SPAREJUMP*2*sizeof(MCode));
mxp += MIPS_SPAREJUMP*2; mxp += MIPS_SPAREJUMP*2;
lua_assert(mxp < as->mctop); lua_assert(mxp < as->mctop);
lj_mcode_sync(as->mcbot, mxp); lj_mcode_sync(as->mcbot, mxp);
@ -291,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
} }
@ -302,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
} }
@ -313,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 {
@ -462,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
@ -478,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. */
@ -609,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);
@ -666,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) &&
@ -807,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);
@ -827,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)) {
@ -883,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) {
@ -961,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);
@ -1124,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;
} }
@ -1135,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;
} }
@ -1200,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;
@ -1213,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);
@ -1262,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)) {
@ -1313,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
@ -1321,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);
@ -1329,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. */
} }
@ -1400,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,
@ -1410,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,
@ -1549,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
{ {
@ -1590,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
{ {
@ -1606,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
{ {
@ -1635,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
@ -1655,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
@ -1665,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);
@ -1674,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)
@ -1919,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;
@ -1937,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;
@ -1948,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);
@ -1968,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);
@ -2033,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;
@ -2069,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);
} }
@ -2264,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. */
@ -2273,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);
@ -2466,7 +2606,11 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
MCode tjump = MIPSI_J|(((uintptr_t)target>>2)&0x03ffffffu); MCode tjump = MIPSI_J|(((uintptr_t)target>>2)&0x03ffffffu);
for (p++; p < pe; p++) { for (p++; p < pe; p++) {
if (*p == exitload) { /* Look for load of exit number. */ if (*p == exitload) { /* Look for load of exit number. */
if (((p[-1] ^ (px-p)) & 0xffffu) == 0) { /* Look for exitstub branch. */ /* Look for exitstub branch. Yes, this covers all used branch variants. */
if (((p[-1] ^ (px-p)) & 0xffffu) == 0 &&
((p[-1] & 0xf0000000u) == MIPSI_BEQ ||
(p[-1] & 0xfc1e0000u) == MIPSI_BLTZ ||
(p[-1] & 0xffe00000u) == MIPSI_BC1F)) {
ptrdiff_t delta = target - p; ptrdiff_t delta = target - p;
if (((delta + 0x8000) >> 16) == 0) { /* Patch in-range branch. */ if (((delta + 0x8000) >> 16) == 0) { /* Patch in-range branch. */
patchbranch: patchbranch:
@ -2476,7 +2620,9 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
if (!cstart) cstart = p-1; if (!cstart) cstart = p-1;
} else { /* Branch out of range. Use spare jump slot in mcarea. */ } else { /* Branch out of range. Use spare jump slot in mcarea. */
int i; int i;
for (i = 2; i < 2+MIPS_SPAREJUMP*2; i += 2) { for (i = (int)(sizeof(MCLink)/sizeof(MCode));
i < (int)(sizeof(MCLink)/sizeof(MCode)+MIPS_SPAREJUMP*2);
i += 2) {
if (mcarea[i] == tjump) { if (mcarea[i] == tjump) {
delta = mcarea+i - p; delta = mcarea+i - p;
goto patchbranch; goto patchbranch;

View File

@ -387,6 +387,7 @@ static Reg asm_fuseloadk64(ASMState *as, IRIns *ir)
ir->i = (int32_t)(as->mctop - as->mcbot); ir->i = (int32_t)(as->mctop - as->mcbot);
as->mcbot += 8; as->mcbot += 8;
as->mclim = as->mcbot + MCLIM_REDZONE; as->mclim = as->mcbot + MCLIM_REDZONE;
lj_mcode_commitbot(as->J, as->mcbot);
} }
as->mrm.ofs = (int32_t)mcpofs(as, as->mctop - ir->i); as->mrm.ofs = (int32_t)mcpofs(as, as->mctop - ir->i);
as->mrm.base = RID_RIP; as->mrm.base = RID_RIP;

View File

@ -387,6 +387,21 @@
#define CCALL_HANDLE_COMPLEXARG \ #define CCALL_HANDLE_COMPLEXARG \
/* Pass complex by value in 2 or 4 GPRs. */ /* Pass complex by value in 2 or 4 GPRs. */
#define CCALL_HANDLE_GPR \
/* Try to pass argument in GPRs. */ \
if (n > 1) { \
lua_assert(n == 2 || n == 4); /* int64_t or complex (float). */ \
if (ctype_isinteger(d->info) || ctype_isfp(d->info)) \
ngpr = (ngpr + 1u) & ~1u; /* Align int64_t to regpair. */ \
else if (ngpr + n > maxgpr) \
ngpr = maxgpr; /* Prevent reordering. */ \
} \
if (ngpr + n <= maxgpr) { \
dp = &cc->gpr[ngpr]; \
ngpr += n; \
goto done; \
} \
#if LJ_ARCH_PPC64 #if LJ_ARCH_PPC64
#define CCALL_HANDLE_REGARG \ #define CCALL_HANDLE_REGARG \
if (isva) { /* only GPRs will be used on C ellipsis operator */ \ if (isva) { /* only GPRs will be used on C ellipsis operator */ \
@ -408,21 +423,13 @@
} \ } \
} else { /* Try to pass argument in GPRs. */ \ } else { /* Try to pass argument in GPRs. */ \
gpr: \ gpr: \
if (n > 1) { \ CCALL_HANDLE_GPR \
lua_assert(n == 2 || n == 4); /* int64_t or complex (float). */ \
if (ctype_isinteger(d->info)) \
ngpr = (ngpr + 1u) & ~1u; /* Align int64_t to regpair. */ \
else if (ngpr + n > maxgpr) \
ngpr = maxgpr; /* Prevent reordering. */ \
} \
if (ngpr + n <= maxgpr) { \
dp = &cc->gpr[ngpr]; \
ngpr += n; \
goto done; \
} \
} \ } \
} }
#else /* 32 bits */ #else /* 32 bits */
#if LJ_ABI_SOFTFP
#define CCALL_HANDLE_REGARG CCALL_HANDLE_GPR
#else
#define CCALL_HANDLE_REGARG \ #define CCALL_HANDLE_REGARG \
if (isfp) { /* Try to pass argument in FPRs. */ \ if (isfp) { /* Try to pass argument in FPRs. */ \
if (nfpr + 1 <= CCALL_NARG_FPR) { \ if (nfpr + 1 <= CCALL_NARG_FPR) { \
@ -431,25 +438,17 @@
d = ctype_get(cts, CTID_DOUBLE); /* FPRs always hold doubles. */ \ d = ctype_get(cts, CTID_DOUBLE); /* FPRs always hold doubles. */ \
goto done; \ goto done; \
} \ } \
} else { /* Try to pass argument in GPRs. */ \ } else { \
if (n > 1) { \ CCALL_HANDLE_GPR \
lua_assert(n == 2 || n == 4); /* int64_t or complex (float). */ \
if (ctype_isinteger(d->info)) \
ngpr = (ngpr + 1u) & ~1u; /* Align int64_t to regpair. */ \
else if (ngpr + n > maxgpr) \
ngpr = maxgpr; /* Prevent reordering. */ \
} \
if (ngpr + n <= maxgpr) { \
dp = &cc->gpr[ngpr]; \
ngpr += n; \
goto done; \
} \
} }
#endif #endif /* LJ_ABI_SOFTFP */
#endif /* LJ_ARCH_PPC64 */
#if !LJ_ABI_SOFTFP
#define CCALL_HANDLE_RET \ #define CCALL_HANDLE_RET \
if (ctype_isfp(ctr->info) && ctr->size == sizeof(float)) \ if (ctype_isfp(ctr->info) && ctr->size == sizeof(float)) \
ctr = ctype_get(cts, CTID_DOUBLE); /* FPRs always hold doubles. */ ctr = ctype_get(cts, CTID_DOUBLE); /* FPRs always hold doubles. */
#endif
#elif LJ_TARGET_MIPS32 #elif LJ_TARGET_MIPS32
/* -- MIPS o32 calling conventions ---------------------------------------- */ /* -- MIPS o32 calling conventions ---------------------------------------- */
@ -1117,7 +1116,7 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
} }
if (fid) lj_err_caller(L, LJ_ERR_FFI_NUMARG); /* Too few arguments. */ if (fid) lj_err_caller(L, LJ_ERR_FFI_NUMARG); /* Too few arguments. */
#if LJ_TARGET_X64 || LJ_TARGET_PPC #if LJ_TARGET_X64 || (LJ_TARGET_PPC && !LJ_ABI_SOFTFP)
cc->nfpr = nfpr; /* Required for vararg functions. */ cc->nfpr = nfpr; /* Required for vararg functions. */
#endif #endif
cc->nsp = nsp; cc->nsp = nsp;

View File

@ -94,9 +94,9 @@ typedef union FPRArg {
#define CCALL_SPS_FREE 0 #define CCALL_SPS_FREE 0
#else #else
#define CCALL_NARG_GPR 8 #define CCALL_NARG_GPR 8
#define CCALL_NARG_FPR 8 #define CCALL_NARG_FPR (LJ_ABI_SOFTFP ? 0 : 8)
#define CCALL_NRET_GPR 4 /* For complex double. */ #define CCALL_NRET_GPR 4 /* For complex double. */
#define CCALL_NRET_FPR 1 #define CCALL_NRET_FPR (LJ_ABI_SOFTFP ? 0 : 1)
#define CCALL_SPS_EXTRA 4 #define CCALL_SPS_EXTRA 4
#define CCALL_SPS_FREE 0 #define CCALL_SPS_FREE 0
#endif #endif

View File

@ -434,6 +434,23 @@ void lj_ccallback_mcode_free(CTState *cts)
#elif LJ_TARGET_PPC #elif LJ_TARGET_PPC
#define CALLBACK_HANDLE_GPR \
if (n > 1) { \
lua_assert(((LJ_ABI_SOFTFP && ctype_isnum(cta->info)) || /* double. */ \
ctype_isinteger(cta->info)) && n == 2); /* int64_t. */ \
ngpr = (ngpr + 1u) & ~1u; /* Align int64_t to regpair. */ \
} \
if (ngpr + n <= maxgpr) { \
sp = &cts->cb.gpr[ngpr]; \
ngpr += n; \
goto done; \
}
#if LJ_ABI_SOFTFP
#define CALLBACK_HANDLE_REGARG \
CALLBACK_HANDLE_GPR \
UNUSED(isfp);
#else
#define CALLBACK_HANDLE_REGARG \ #define CALLBACK_HANDLE_REGARG \
if (isfp) { \ if (isfp) { \
if (nfpr + 1 <= CCALL_NARG_FPR) { \ if (nfpr + 1 <= CCALL_NARG_FPR) { \
@ -442,20 +459,15 @@ void lj_ccallback_mcode_free(CTState *cts)
goto done; \ goto done; \
} \ } \
} else { /* Try to pass argument in GPRs. */ \ } else { /* Try to pass argument in GPRs. */ \
if (n > 1) { \ CALLBACK_HANDLE_GPR \
lua_assert(ctype_isinteger(cta->info) && n == 2); /* int64_t. */ \
ngpr = (ngpr + 1u) & ~1u; /* Align int64_t to regpair. */ \
} \
if (ngpr + n <= maxgpr) { \
sp = &cts->cb.gpr[ngpr]; \
ngpr += n; \
goto done; \
} \
} }
#endif
#if !LJ_ABI_SOFTFP
#define CALLBACK_HANDLE_RET \ #define CALLBACK_HANDLE_RET \
if (ctype_isfp(ctr->info) && ctr->size == sizeof(float)) \ if (ctype_isfp(ctr->info) && ctr->size == sizeof(float)) \
*(double *)dp = *(float *)dp; /* FPRs always hold doubles. */ *(double *)dp = *(float *)dp; /* FPRs always hold doubles. */
#endif
#elif LJ_TARGET_MIPS32 #elif LJ_TARGET_MIPS32

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

@ -80,7 +80,6 @@ typedef unsigned int uintptr_t;
#define LJ_MIN_SBUF 32 /* Min. string buffer length. */ #define LJ_MIN_SBUF 32 /* Min. string buffer length. */
#define LJ_MIN_VECSZ 8 /* Min. size for growable vectors. */ #define LJ_MIN_VECSZ 8 /* Min. size for growable vectors. */
#define LJ_MIN_IRSZ 32 /* Min. size for growable IR. */ #define LJ_MIN_IRSZ 32 /* Min. size for growable IR. */
#define LJ_MIN_K64SZ 16 /* Min. size for chained K64Array. */
/* JIT compiler limits. */ /* JIT compiler limits. */
#define LJ_MAX_JSLOTS 250 /* Max. # of stack slots for a trace. */ #define LJ_MAX_JSLOTS 250 /* Max. # of stack slots for a trace. */

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

@ -343,9 +343,27 @@ static void emit_rma(ASMState *as, x86Op xo, Reg rr, const void *addr)
emit_rmro(as, xo, rr, RID_DISPATCH, (int32_t)dispofs(as, addr)); emit_rmro(as, xo, rr, RID_DISPATCH, (int32_t)dispofs(as, addr));
} else if (checki32(mcpofs(as, addr)) && checki32(mctopofs(as, addr))) { } else if (checki32(mcpofs(as, addr)) && checki32(mctopofs(as, addr))) {
emit_rmro(as, xo, rr, RID_RIP, (int32_t)mcpofs(as, addr)); emit_rmro(as, xo, rr, RID_RIP, (int32_t)mcpofs(as, addr));
} else if (!checki32((intptr_t)addr) && (xo == XO_MOV || xo == XO_MOVSD)) { } else if (!checki32((intptr_t)addr)) {
emit_rmro(as, xo, rr, rr, 0); Reg ra = (rr & 15);
emit_loadu64(as, rr, (uintptr_t)addr); if (xo != XO_MOV) {
/* We can't allocate a register here. Use and restore DISPATCH. Ugly. */
uint64_t dispaddr = (uintptr_t)J2GG(as->J)->dispatch;
uint8_t i8 = xo == XO_GROUP3b ? *as->mcp++ : 0;
ra = RID_DISPATCH;
if (checku32(dispaddr)) {
emit_loadi(as, ra, (int32_t)dispaddr);
} else { /* Full-size 64 bit load. */
MCode *p = as->mcp;
*(uint64_t *)(p-8) = dispaddr;
p[-9] = (MCode)(XI_MOVri+(ra&7));
p[-10] = 0x48 + ((ra>>3)&1);
p -= 10;
as->mcp = p;
}
if (xo == XO_GROUP3b) emit_i8(as, i8);
}
emit_rmro(as, xo, rr, ra, 0);
emit_loadu64(as, ra, (uintptr_t)addr);
} else } else
#endif #endif
{ {

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

@ -235,7 +235,7 @@ enum { LJ_CONT_TAILCALL, LJ_CONT_FFI_CALLBACK }; /* Special continuations. */
#define CFRAME_OFS_L 36 #define CFRAME_OFS_L 36
#define CFRAME_OFS_PC 32 #define CFRAME_OFS_PC 32
#define CFRAME_OFS_MULTRES 28 #define CFRAME_OFS_MULTRES 28
#define CFRAME_SIZE 272 #define CFRAME_SIZE (LJ_ARCH_HASFPU ? 272 : 128)
#define CFRAME_SHIFT_MULTRES 3 #define CFRAME_SHIFT_MULTRES 3
#endif #endif
#elif LJ_TARGET_MIPS32 #elif LJ_TARGET_MIPS32

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) \
@ -272,7 +287,7 @@ LJ_DATA const CCallInfo lj_ir_callinfo[IRCALL__MAX+1];
#define fp64_f2l __aeabi_f2lz #define fp64_f2l __aeabi_f2lz
#define fp64_f2ul __aeabi_f2ulz #define fp64_f2ul __aeabi_f2ulz
#endif #endif
#elif LJ_TARGET_MIPS #elif LJ_TARGET_MIPS || LJ_TARGET_PPC
#define softfp_add __adddf3 #define softfp_add __adddf3
#define softfp_sub __subdf3 #define softfp_sub __subdf3
#define softfp_mul __muldf3 #define softfp_mul __muldf3

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

@ -158,6 +158,12 @@ typedef uint8_t MCode;
typedef uint32_t MCode; typedef uint32_t MCode;
#endif #endif
/* Linked list of MCode areas. */
typedef struct MCLink {
MCode *next; /* Next area. */
size_t size; /* Size of current area. */
} MCLink;
/* Stack snapshot header. */ /* Stack snapshot header. */
typedef struct SnapShot { typedef struct SnapShot {
uint16_t mapofs; /* Offset into snapshot map. */ uint16_t mapofs; /* Offset into snapshot map. */
@ -368,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
@ -431,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

@ -272,12 +272,6 @@ static void *mcode_alloc(jit_State *J, size_t sz)
/* -- MCode area management ----------------------------------------------- */ /* -- MCode area management ----------------------------------------------- */
/* Linked list of MCode areas. */
typedef struct MCLink {
MCode *next; /* Next area. */
size_t size; /* Size of current area. */
} MCLink;
/* Allocate a new MCode area. */ /* Allocate a new MCode area. */
static void mcode_allocarea(jit_State *J) static void mcode_allocarea(jit_State *J)
{ {

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

@ -87,9 +87,9 @@ static void rec_check_slots(jit_State *J)
BCReg s, nslots = J->baseslot + J->maxslot; BCReg s, nslots = J->baseslot + J->maxslot;
int32_t depth = 0; int32_t depth = 0;
cTValue *base = J->L->base - J->baseslot; cTValue *base = J->L->base - J->baseslot;
lua_assert(J->baseslot >= 1+LJ_FR2 && J->baseslot < LJ_MAX_JSLOTS); lua_assert(J->baseslot >= 1+LJ_FR2);
lua_assert(J->baseslot == 1+LJ_FR2 || (J->slot[J->baseslot-1] & TREF_FRAME)); lua_assert(J->baseslot == 1+LJ_FR2 || (J->slot[J->baseslot-1] & TREF_FRAME));
lua_assert(nslots < LJ_MAX_JSLOTS); lua_assert(nslots <= LJ_MAX_JSLOTS);
for (s = 0; s < nslots; s++) { for (s = 0; s < nslots; s++) {
TRef tr = J->slot[s]; TRef tr = J->slot[s];
if (tr) { if (tr) {
@ -731,6 +731,8 @@ void lj_record_call(jit_State *J, BCReg func, ptrdiff_t nargs)
J->framedepth++; J->framedepth++;
J->base += func+1+LJ_FR2; J->base += func+1+LJ_FR2;
J->baseslot += func+1+LJ_FR2; J->baseslot += func+1+LJ_FR2;
if (J->baseslot + J->maxslot >= LJ_MAX_JSLOTS)
lj_trace_err(J, LJ_TRERR_STACKOV);
} }
/* Record tail call. */ /* Record tail call. */

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 --------------------------------------------
|//----------------------------------------------------------------------- |//-----------------------------------------------------------------------

File diff suppressed because it is too large Load Diff