mirror of
https://github.com/love2d/megasource.git
synced 2026-08-20 12:40:06 +02:00
Update LuaJIT to the latest 2.1.0 source (f3c8569)
This commit is contained in:
+143
-93
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
** MIPS IR assembler (SSA IR -> machine code).
|
||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
/* -- Register allocator extensions --------------------------------------- */
|
||||
@@ -64,19 +64,31 @@ static Reg ra_alloc2(ASMState *as, IRIns *ir, RegSet allow)
|
||||
/* Setup spare long-range jump slots per mcarea. */
|
||||
static void asm_sparejump_setup(ASMState *as)
|
||||
{
|
||||
MCode *mxp = as->mcbot;
|
||||
if (((uintptr_t)mxp & (LJ_PAGESIZE-1)) == sizeof(MCLink)) {
|
||||
MCode *mxp = as->mctop;
|
||||
if ((char *)mxp == (char *)as->J->mcarea + as->J->szmcarea) {
|
||||
mxp -= MIPS_SPAREJUMP*2;
|
||||
lj_assertA(MIPSI_NOP == 0, "bad NOP");
|
||||
memset(mxp, 0, MIPS_SPAREJUMP*2*sizeof(MCode));
|
||||
mxp += MIPS_SPAREJUMP*2;
|
||||
lj_assertA(mxp < as->mctop, "MIPS_SPAREJUMP too big");
|
||||
lj_mcode_sync(as->mcbot, mxp);
|
||||
lj_mcode_commitbot(as->J, mxp);
|
||||
as->mcbot = mxp;
|
||||
as->mclim = as->mcbot + MCLIM_REDZONE;
|
||||
as->mctop = mxp;
|
||||
}
|
||||
}
|
||||
|
||||
static MCode *asm_sparejump_use(MCode *mcarea, MCode tjump)
|
||||
{
|
||||
MCode *mxp = (MCode *)((char *)mcarea + ((MCLink *)mcarea)->size);
|
||||
int slot = MIPS_SPAREJUMP;
|
||||
while (slot--) {
|
||||
mxp -= 2;
|
||||
if (*mxp == tjump) {
|
||||
return mxp;
|
||||
} else if (*mxp == MIPSI_NOP) {
|
||||
*mxp = tjump;
|
||||
return mxp;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Setup exit stub after the end of each trace. */
|
||||
static void asm_exitstub_setup(ASMState *as)
|
||||
{
|
||||
@@ -181,6 +193,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow)
|
||||
return ra_allock(as, ofs-(int16_t)ofs, allow);
|
||||
}
|
||||
}
|
||||
} else if (ir->o == IR_TMPREF) {
|
||||
*ofsp = (int32_t)(offsetof(global_State, tmptv)-32768);
|
||||
return RID_JGL;
|
||||
}
|
||||
}
|
||||
*ofsp = 0;
|
||||
@@ -336,19 +351,15 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
|
||||
static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
|
||||
{
|
||||
RegSet drop = RSET_SCRATCH;
|
||||
#if LJ_32
|
||||
int hiop = ((ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t));
|
||||
#endif
|
||||
#if !LJ_SOFTFP
|
||||
if ((ci->flags & CCI_NOFPRCLOBBER))
|
||||
drop &= ~RSET_FPR;
|
||||
#endif
|
||||
if (ra_hasreg(ir->r))
|
||||
rset_clear(drop, ir->r); /* Dest reg handled below. */
|
||||
#if LJ_32
|
||||
if (hiop && ra_hasreg((ir+1)->r))
|
||||
rset_clear(drop, (ir+1)->r); /* Dest reg handled below. */
|
||||
#endif
|
||||
ra_evictset(as, drop); /* Evictions must be performed first. */
|
||||
if (ra_used(ir)) {
|
||||
lj_assertA(!irt_ispri(ir->t), "PRI dest");
|
||||
@@ -377,10 +388,8 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
|
||||
} else {
|
||||
ra_destreg(as, ir, RID_FPRET);
|
||||
}
|
||||
#if LJ_32
|
||||
} else if (hiop) {
|
||||
ra_destpair(as, ir);
|
||||
#endif
|
||||
} else {
|
||||
ra_destreg(as, ir, RID_RET);
|
||||
}
|
||||
@@ -450,6 +459,27 @@ static void asm_retf(ASMState *as, IRIns *ir)
|
||||
emit_tsi(as, MIPSI_AL, RID_TMP, base, -8);
|
||||
}
|
||||
|
||||
/* -- Buffer operations --------------------------------------------------- */
|
||||
|
||||
#if LJ_HASBUFFER
|
||||
static void asm_bufhdr_write(ASMState *as, Reg sb)
|
||||
{
|
||||
Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb));
|
||||
IRIns irgc;
|
||||
irgc.ot = IRT(0, IRT_PGC); /* GC type. */
|
||||
emit_storeofs(as, &irgc, RID_TMP, sb, offsetof(SBuf, L));
|
||||
if ((as->flags & JIT_F_MIPSXXR2)) {
|
||||
emit_tsml(as, LJ_64 ? MIPSI_DINS : MIPSI_INS, RID_TMP, tmp,
|
||||
lj_fls(SBUF_MASK_FLAG), 0);
|
||||
} else {
|
||||
emit_dst(as, MIPSI_OR, RID_TMP, RID_TMP, tmp);
|
||||
emit_tsi(as, MIPSI_ANDI, tmp, tmp, SBUF_MASK_FLAG);
|
||||
}
|
||||
emit_getgl(as, RID_TMP, cur_L);
|
||||
emit_loadofs(as, &irgc, tmp, sb, offsetof(SBuf, L));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* -- Type conversions ---------------------------------------------------- */
|
||||
|
||||
#if !LJ_SOFTFP
|
||||
@@ -739,7 +769,7 @@ static void asm_conv(ASMState *as, IRIns *ir)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (st64) {
|
||||
if (st64 && !(ir->op2 & IRCONV_NONE)) {
|
||||
/* This is either a 32 bit reg/reg mov which zeroes the hiword
|
||||
** or a load of the loword from a 64 bit address.
|
||||
*/
|
||||
@@ -827,34 +857,63 @@ static void asm_tvstore64(ASMState *as, Reg base, int32_t ofs, IRRef ref)
|
||||
#endif
|
||||
|
||||
/* Get pointer to TValue. */
|
||||
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref)
|
||||
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode)
|
||||
{
|
||||
IRIns *ir = IR(ref);
|
||||
if (irt_isnum(ir->t)) {
|
||||
if (irref_isk(ref)) /* Use the number constant itself as a TValue. */
|
||||
ra_allockreg(as, igcptr(ir_knum(ir)), dest);
|
||||
else /* Otherwise force a spill and use the spill slot. */
|
||||
emit_tsi(as, MIPSI_AADDIU, dest, RID_SP, ra_spill(as, ir));
|
||||
} else {
|
||||
/* Otherwise use g->tmptv to hold the TValue. */
|
||||
#if LJ_32
|
||||
RegSet allow = rset_exclude(RSET_GPR, dest);
|
||||
Reg type;
|
||||
emit_tsi(as, MIPSI_ADDIU, dest, RID_JGL, (int32_t)(offsetof(global_State, tmptv)-32768));
|
||||
if (!irt_ispri(ir->t)) {
|
||||
Reg src = ra_alloc1(as, ref, allow);
|
||||
emit_setgl(as, src, tmptv.gcr);
|
||||
}
|
||||
if (LJ_SOFTFP && (ir+1)->o == IR_HIOP)
|
||||
type = ra_alloc1(as, ref+1, allow);
|
||||
else
|
||||
type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow);
|
||||
emit_setgl(as, type, tmptv.it);
|
||||
int32_t tmpofs = (int32_t)(offsetof(global_State, tmptv)-32768);
|
||||
if ((mode & IRTMPREF_IN1)) {
|
||||
IRIns *ir = IR(ref);
|
||||
if (irt_isnum(ir->t)) {
|
||||
if ((mode & IRTMPREF_OUT1)) {
|
||||
#if LJ_SOFTFP
|
||||
emit_tsi(as, MIPSI_AADDIU, dest, RID_JGL, tmpofs);
|
||||
#if LJ_64
|
||||
emit_setgl(as, ra_alloc1(as, ref, RSET_GPR), tmptv.u64);
|
||||
#else
|
||||
asm_tvstore64(as, dest, 0, ref);
|
||||
emit_tsi(as, MIPSI_DADDIU, dest, RID_JGL,
|
||||
(int32_t)(offsetof(global_State, tmptv)-32768));
|
||||
lj_assertA(irref_isk(ref), "unsplit FP op");
|
||||
emit_setgl(as,
|
||||
ra_allock(as, (int32_t)ir_knum(ir)->u32.lo, RSET_GPR),
|
||||
tmptv.u32.lo);
|
||||
emit_setgl(as,
|
||||
ra_allock(as, (int32_t)ir_knum(ir)->u32.hi, RSET_GPR),
|
||||
tmptv.u32.hi);
|
||||
#endif
|
||||
#else
|
||||
Reg src = ra_alloc1(as, ref, RSET_FPR);
|
||||
emit_tsi(as, MIPSI_AADDIU, dest, RID_JGL, tmpofs);
|
||||
emit_tsi(as, MIPSI_SDC1, (src & 31), RID_JGL, tmpofs);
|
||||
#endif
|
||||
} else if (irref_isk(ref)) {
|
||||
/* Use the number constant itself as a TValue. */
|
||||
ra_allockreg(as, igcptr(ir_knum(ir)), dest);
|
||||
} else {
|
||||
#if LJ_SOFTFP32
|
||||
lj_assertA(0, "unsplit FP op");
|
||||
#else
|
||||
/* Otherwise force a spill and use the spill slot. */
|
||||
emit_tsi(as, MIPSI_AADDIU, dest, RID_SP, ra_spill(as, ir));
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
/* Otherwise use g->tmptv to hold the TValue. */
|
||||
#if LJ_32
|
||||
Reg type;
|
||||
emit_tsi(as, MIPSI_ADDIU, dest, RID_JGL, tmpofs);
|
||||
if (!irt_ispri(ir->t)) {
|
||||
Reg src = ra_alloc1(as, ref, RSET_GPR);
|
||||
emit_setgl(as, src, tmptv.gcr);
|
||||
}
|
||||
if (LJ_SOFTFP && (ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t))
|
||||
type = ra_alloc1(as, ref+1, RSET_GPR);
|
||||
else
|
||||
type = ra_allock(as, (int32_t)irt_toitype(ir->t), RSET_GPR);
|
||||
emit_setgl(as, type, tmptv.it);
|
||||
#else
|
||||
asm_tvstore64(as, dest, 0, ref);
|
||||
emit_tsi(as, MIPSI_DADDIU, dest, RID_JGL, tmpofs);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
emit_tsi(as, MIPSI_AADDIU, dest, RID_JGL, tmpofs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -909,11 +968,16 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
|
||||
MCLabel l_end, l_loop, l_next;
|
||||
|
||||
rset_clear(allow, tab);
|
||||
#if LJ_SOFTFP32
|
||||
if (!isk) {
|
||||
key = ra_alloc1(as, refkey, allow);
|
||||
rset_clear(allow, key);
|
||||
if (irkey[1].o == IR_HIOP) {
|
||||
if (!LJ_SOFTFP && irt_isnum(kt)) {
|
||||
key = ra_alloc1(as, refkey, RSET_FPR);
|
||||
tmpnum = ra_scratch(as, rset_exclude(RSET_FPR, key));
|
||||
} else {
|
||||
if (!irt_ispri(kt)) {
|
||||
key = ra_alloc1(as, refkey, allow);
|
||||
rset_clear(allow, key);
|
||||
}
|
||||
#if LJ_32
|
||||
if (LJ_SOFTFP && irkey[1].o == IR_HIOP) {
|
||||
if (ra_hasreg((irkey+1)->r)) {
|
||||
type = tmpnum = (irkey+1)->r;
|
||||
tmp1 = ra_scratch(as, allow);
|
||||
@@ -924,23 +988,11 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
|
||||
}
|
||||
rset_clear(allow, tmpnum);
|
||||
} else {
|
||||
type = ra_allock(as, (int32_t)irt_toitype(irkey->t), allow);
|
||||
type = ra_allock(as, (int32_t)irt_toitype(kt), allow);
|
||||
rset_clear(allow, type);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (!LJ_SOFTFP && irt_isnum(kt)) {
|
||||
key = ra_alloc1(as, refkey, RSET_FPR);
|
||||
tmpnum = ra_scratch(as, rset_exclude(RSET_FPR, key));
|
||||
} else if (!irt_ispri(kt)) {
|
||||
key = ra_alloc1(as, refkey, allow);
|
||||
rset_clear(allow, key);
|
||||
#if LJ_32
|
||||
type = ra_allock(as, (int32_t)irt_toitype(irkey->t), allow);
|
||||
rset_clear(allow, type);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
tmp2 = ra_scratch(as, allow);
|
||||
rset_clear(allow, tmp2);
|
||||
#if LJ_64
|
||||
@@ -953,10 +1005,10 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
|
||||
} else {
|
||||
int64_t k;
|
||||
if (isk && irt_isaddr(kt)) {
|
||||
k = ((int64_t)irt_toitype(irkey->t) << 47) | irkey[1].tv.u64;
|
||||
k = ((int64_t)irt_toitype(kt) << 47) | irkey[1].tv.u64;
|
||||
} else {
|
||||
lj_assertA(irt_ispri(kt) && !irt_isnil(kt), "bad HREF key type");
|
||||
k = ~((int64_t)~irt_toitype(ir->t) << 47);
|
||||
k = ~((int64_t)~irt_toitype(kt) << 47);
|
||||
}
|
||||
cmp64 = ra_allock(as, k, allow);
|
||||
rset_clear(allow, cmp64);
|
||||
@@ -1352,6 +1404,7 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
|
||||
#endif
|
||||
}
|
||||
idx = asm_fuseahuref(as, ir->op1, &ofs, allow);
|
||||
if (ir->o == IR_VLOAD) ofs += 8 * ir->op2;
|
||||
rset_clear(allow, idx);
|
||||
if (irt_isnum(t)) {
|
||||
asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO);
|
||||
@@ -2327,15 +2380,15 @@ static void asm_comp64eq(ASMState *as, IRIns *ir)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* -- Support for 64 bit ops in 32 bit mode ------------------------------- */
|
||||
/* -- Split register ops -------------------------------------------------- */
|
||||
|
||||
/* Hiword op of a split 64 bit op. Previous op must be the loword op. */
|
||||
/* Hiword op of a split 32/32 or 64/64 bit op. Previous op is the loword op. */
|
||||
static void asm_hiop(ASMState *as, IRIns *ir)
|
||||
{
|
||||
#if LJ_32 && (LJ_HASFFI || LJ_SOFTFP)
|
||||
/* HIOP is marked as a store because it needs its own DCE logic. */
|
||||
int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */
|
||||
if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1;
|
||||
#if LJ_32 && (LJ_HASFFI || LJ_SOFTFP)
|
||||
if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */
|
||||
as->curins--; /* Always skip the CONV. */
|
||||
#if LJ_HASFFI && !LJ_SOFTFP
|
||||
@@ -2382,38 +2435,33 @@ static void asm_hiop(ASMState *as, IRIns *ir)
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (!usehi) return; /* Skip unused hiword op for all remaining ops. */
|
||||
switch ((ir-1)->o) {
|
||||
#if LJ_HASFFI
|
||||
#if LJ_32 && LJ_HASFFI
|
||||
case IR_ADD: as->curins--; asm_add64(as, ir); break;
|
||||
case IR_SUB: as->curins--; asm_sub64(as, ir); break;
|
||||
case IR_NEG: as->curins--; asm_neg64(as, ir); break;
|
||||
case IR_CNEWI:
|
||||
/* Nothing to do here. Handled by lo op itself. */
|
||||
break;
|
||||
#endif
|
||||
#if LJ_SOFTFP
|
||||
#if LJ_32 && LJ_SOFTFP
|
||||
case IR_SLOAD: case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD:
|
||||
case IR_STRTO:
|
||||
if (!uselo)
|
||||
ra_allocref(as, ir->op1, RSET_GPR); /* Mark lo op as used. */
|
||||
break;
|
||||
case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: case IR_TMPREF:
|
||||
/* Nothing to do here. Handled by lo op itself. */
|
||||
break;
|
||||
#endif
|
||||
case IR_CALLN:
|
||||
case IR_CALLS:
|
||||
case IR_CALLXS:
|
||||
case IR_CALLN: case IR_CALLL: case IR_CALLS: case IR_CALLXS:
|
||||
if (!uselo)
|
||||
ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */
|
||||
break;
|
||||
#if LJ_SOFTFP
|
||||
case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR:
|
||||
#endif
|
||||
case IR_CNEWI:
|
||||
/* Nothing to do here. Handled by lo op itself. */
|
||||
break;
|
||||
default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break;
|
||||
}
|
||||
#else
|
||||
/* Unused on MIPS64 or without SOFTFP or FFI. */
|
||||
UNUSED(as); UNUSED(ir); lj_assertA(0, "unexpected HIOP");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* -- Profiling ----------------------------------------------------------- */
|
||||
@@ -2513,6 +2561,8 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
|
||||
} else if ((sn & SNAP_SOFTFPNUM)) {
|
||||
type = ra_alloc1(as, ref+1, rset_exclude(RSET_GPR, RID_BASE));
|
||||
#endif
|
||||
} else if ((sn & SNAP_KEYINDEX)) {
|
||||
type = ra_allock(as, (int32_t)LJ_KEYINDEX, allow);
|
||||
} else {
|
||||
type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow);
|
||||
}
|
||||
@@ -2575,6 +2625,12 @@ static void asm_loop_fixup(ASMState *as)
|
||||
}
|
||||
}
|
||||
|
||||
/* Fixup the tail of the loop. */
|
||||
static void asm_loop_tail_fixup(ASMState *as)
|
||||
{
|
||||
if (as->loopinv) as->mctop--;
|
||||
}
|
||||
|
||||
/* -- Head of trace ------------------------------------------------------- */
|
||||
|
||||
/* Coalesce BASE register for a root trace. */
|
||||
@@ -2582,7 +2638,6 @@ static void asm_head_root_base(ASMState *as)
|
||||
{
|
||||
IRIns *ir = IR(REF_BASE);
|
||||
Reg r = ir->r;
|
||||
if (as->loopinv) as->mctop--;
|
||||
if (ra_hasreg(r)) {
|
||||
ra_free(as, r);
|
||||
if (rset_test(as->modset, r) || irt_ismarked(ir->t))
|
||||
@@ -2597,7 +2652,6 @@ static RegSet asm_head_side_base(ASMState *as, IRIns *irp, RegSet allow)
|
||||
{
|
||||
IRIns *ir = IR(REF_BASE);
|
||||
Reg r = ir->r;
|
||||
if (as->loopinv) as->mctop--;
|
||||
if (ra_hasreg(r)) {
|
||||
ra_free(as, r);
|
||||
if (rset_test(as->modset, r) || irt_ismarked(ir->t))
|
||||
@@ -2704,21 +2758,17 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
|
||||
patchbranch:
|
||||
p[-1] = (p[-1] & 0xffff0000u) | (delta & 0xffffu);
|
||||
*p = MIPSI_NOP; /* Replace the load of the exit number. */
|
||||
cstop = p;
|
||||
cstop = p+1;
|
||||
if (!cstart) cstart = p-1;
|
||||
} else { /* Branch out of range. Use spare jump slot in mcarea. */
|
||||
int i;
|
||||
for (i = (int)(sizeof(MCLink)/sizeof(MCode));
|
||||
i < (int)(sizeof(MCLink)/sizeof(MCode)+MIPS_SPAREJUMP*2);
|
||||
i += 2) {
|
||||
if (mcarea[i] == tjump) {
|
||||
delta = mcarea+i - p;
|
||||
goto patchbranch;
|
||||
} else if (mcarea[i] == MIPSI_NOP) {
|
||||
mcarea[i] = tjump;
|
||||
cstart = mcarea+i;
|
||||
delta = mcarea+i - p;
|
||||
MCode *mcjump = asm_sparejump_use(mcarea, tjump);
|
||||
if (mcjump) {
|
||||
lj_mcode_sync(mcjump, mcjump+1);
|
||||
delta = mcjump - p;
|
||||
if (((delta + 0x8000) >> 16) == 0) {
|
||||
goto patchbranch;
|
||||
} else {
|
||||
lj_assertJ(0, "spare jump out of range: -Osizemcode too big");
|
||||
}
|
||||
}
|
||||
/* Ignore jump slot overflow. Child trace is simply not attached. */
|
||||
|
||||
Reference in New Issue
Block a user