зеркало из https://github.com/mozilla/gecko-dev.git
Bug 540368 - nanojit: split LIR_qlo, LIR_live and LIR_ret into two opcodes each to faciliate LIR type-checking (NJ-specific part). r=edwsmith.
--HG-- extra : convert_revision : 54cf6d39a21dc1e209d3e0e48bb6c2b61ab5f909
This commit is contained in:
Родитель
feb28e66a5
Коммит
e563ce0389
|
@ -96,8 +96,8 @@ CLASS( LOP_B_FF, 0, 3) // 63% LIR_feq, LIR_flt, etc
|
|||
|
||||
CLASS( LOP_Q_I, 1, 2) // 65% LIR_i2q, LIR_u2q
|
||||
CLASS( LOP_F_I, 0, 2) // 67% LIR_i2f, LIR_u2f
|
||||
|
||||
CLASS( LOP_I_F, 0, 2) // 69% LIR_qlo, LIR_qhi, LIR_f2i
|
||||
CLASS( LOP_I_Q, 1, 1) // 68% LIR_q2i
|
||||
CLASS( LOP_I_F, 0, 1) // 69% LIR_qlo, LIR_qhi, LIR_f2i
|
||||
CLASS( LOP_F_II, 0, 1) // 70% LIR_qjoin
|
||||
|
||||
CLASS( LLD_I, 0, 3) // 73% LIR_ld, LIR_ldc, LIR_ld*b, LIR_ld*s
|
||||
|
|
|
@ -892,12 +892,14 @@ FragmentAssembler::assembleFragment(LirTokenStream &in, bool implicitBegin, cons
|
|||
break;
|
||||
|
||||
case LIR_live:
|
||||
case LIR_qlive:
|
||||
case LIR_flive:
|
||||
case LIR_neg:
|
||||
case LIR_fneg:
|
||||
case LIR_not:
|
||||
case LIR_qlo:
|
||||
case LIR_qhi:
|
||||
case LIR_q2i:
|
||||
case LIR_ov:
|
||||
case LIR_i2q:
|
||||
case LIR_u2q:
|
||||
|
@ -1086,6 +1088,7 @@ FragmentAssembler::assembleFragment(LirTokenStream &in, bool implicitBegin, cons
|
|||
case LIR_line:
|
||||
case LIR_xtbl:
|
||||
case LIR_jtbl:
|
||||
case LIR_qret:
|
||||
nyi(op);
|
||||
break;
|
||||
|
||||
|
@ -1260,19 +1263,20 @@ const CallInfo ci_N_IQF = CI(f_N_IQF, argMask(I32, 1, 3) |
|
|||
// sufficiently big that it's spread across multiple chunks.
|
||||
//
|
||||
// The following instructions aren't generated yet:
|
||||
// - iparam/qparam (hard to test beyond what is auto-generated in fragment
|
||||
// - LIR_iparam/LIR_qparam (hard to test beyond what is auto-generated in fragment
|
||||
// prologues)
|
||||
// - live/flive
|
||||
// - callh
|
||||
// - x/xt/xf/xtbl (hard to test without having multiple fragments; when we
|
||||
// only have one fragment we don't really want to leave it early)
|
||||
// - ret/fret (hard to test without having multiple fragments)
|
||||
// - j/jt/jf/ji/label (ji is not implemented in NJ)
|
||||
// - ov (takes an arithmetic (int or FP) value as operand, and must
|
||||
// - LIR_live/LIR_qlive/LIR_flive
|
||||
// - LIR_callh
|
||||
// - LIR_x/LIR_xt/LIR_xf/LIR_xtbl (hard to test without having multiple
|
||||
// fragments; when we only have one fragment we don't really want to leave
|
||||
// it early)
|
||||
// - LIR_ret/LIR_qret/LIR_fret (hard to test without having multiple fragments)
|
||||
// - LIR_j/LIR_jt/LIR_jf/LIR_jtbl/LIR_label
|
||||
// - LIR_ov (takes an arithmetic (int or FP) value as operand, and must
|
||||
// immediately follow it to be safe... not that that really matters in
|
||||
// randomly generated code)
|
||||
// - file/line (#ifdef VTUNE only)
|
||||
// - fmod (not implemented in NJ)
|
||||
// - LIR_file/LIR_line (#ifdef VTUNE only)
|
||||
// - LIR_fmod (not implemented in NJ backends)
|
||||
//
|
||||
void
|
||||
FragmentAssembler::assembleRandomFragment(int nIns)
|
||||
|
@ -1368,6 +1372,9 @@ FragmentAssembler::assembleRandomFragment(int nIns)
|
|||
Q_I_ops.push_back(LIR_i2q);
|
||||
Q_I_ops.push_back(LIR_u2q);
|
||||
|
||||
vector<LOpcode> I_Q_ops;
|
||||
I_Q_ops.push_back(LIR_q2i);
|
||||
|
||||
vector<LOpcode> F_I_ops;
|
||||
F_I_ops.push_back(LIR_i2f);
|
||||
F_I_ops.push_back(LIR_u2f);
|
||||
|
@ -1707,6 +1714,14 @@ FragmentAssembler::assembleRandomFragment(int nIns)
|
|||
}
|
||||
break;
|
||||
|
||||
case LOP_I_Q:
|
||||
if (!Qs.empty()) {
|
||||
ins = mLir->ins1(rndPick(I_Q_ops), rndPick(Qs));
|
||||
addOrReplace(Is, ins);
|
||||
n++;
|
||||
}
|
||||
break;
|
||||
|
||||
case LOP_I_F:
|
||||
// XXX: NativeX64 doesn't implement qhi yet (and it may not need to).
|
||||
#if !defined NANOJIT_X64
|
||||
|
|
|
@ -1199,13 +1199,15 @@ namespace nanojit
|
|||
{
|
||||
NanoAssert(_thisfrag->nStaticExits == 0);
|
||||
|
||||
// trace must end with LIR_x, LIR_[f]ret, LIR_xtbl, or LIR_[f]live
|
||||
NanoAssert(reader->pos()->isop(LIR_x) ||
|
||||
reader->pos()->isop(LIR_ret) ||
|
||||
reader->pos()->isop(LIR_fret) ||
|
||||
reader->pos()->isop(LIR_xtbl) ||
|
||||
reader->pos()->isop(LIR_flive) ||
|
||||
reader->pos()->isop(LIR_live));
|
||||
// The trace must end with one of these opcodes.
|
||||
NanoAssert(reader->pos()->isop(LIR_x) ||
|
||||
reader->pos()->isop(LIR_xtbl) ||
|
||||
reader->pos()->isop(LIR_ret) ||
|
||||
reader->pos()->isop(LIR_qret) ||
|
||||
reader->pos()->isop(LIR_fret) ||
|
||||
reader->pos()->isop(LIR_live) ||
|
||||
reader->pos()->isop(LIR_qlive) ||
|
||||
reader->pos()->isop(LIR_flive));
|
||||
|
||||
InsList pending_lives(alloc);
|
||||
|
||||
|
@ -1286,8 +1288,9 @@ namespace nanojit
|
|||
evictAllActiveRegs();
|
||||
break;
|
||||
|
||||
case LIR_flive:
|
||||
case LIR_live: {
|
||||
case LIR_live:
|
||||
case LIR_qlive:
|
||||
case LIR_flive: {
|
||||
countlir_live();
|
||||
LInsp op1 = ins->oprnd1();
|
||||
// alloca's are meant to live until the point of the LIR_live instruction, marking
|
||||
|
@ -1305,8 +1308,9 @@ namespace nanojit
|
|||
break;
|
||||
}
|
||||
|
||||
case LIR_fret:
|
||||
case LIR_ret: {
|
||||
case LIR_ret:
|
||||
case LIR_qret:
|
||||
case LIR_fret: {
|
||||
countlir_ret();
|
||||
asm_ret(ins);
|
||||
break;
|
||||
|
@ -1355,6 +1359,12 @@ namespace nanojit
|
|||
asm_param(ins);
|
||||
break;
|
||||
}
|
||||
case LIR_q2i:
|
||||
{
|
||||
countlir_alu();
|
||||
asm_q2i(ins);
|
||||
break;
|
||||
}
|
||||
case LIR_qlo:
|
||||
{
|
||||
countlir_qlo();
|
||||
|
@ -1866,9 +1876,9 @@ namespace nanojit
|
|||
// ensure that exprs spanning the loop are marked live at the end of the loop
|
||||
reserveSavedRegs();
|
||||
for (Seq<LIns*> *p = pending_lives.get(); p != NULL; p = p->tail) {
|
||||
LIns *i = p->head;
|
||||
NanoAssert(i->isop(LIR_live) || i->isop(LIR_flive));
|
||||
LIns *op1 = i->oprnd1();
|
||||
LIns *ins = p->head;
|
||||
NanoAssert(ins->isop(LIR_live) || ins->isop(LIR_qlive) || ins->isop(LIR_flive));
|
||||
LIns *op1 = ins->oprnd1();
|
||||
// must findMemFor even if we're going to findRegFor; loop-carried
|
||||
// operands may spill on another edge, and we need them to always
|
||||
// spill to the same place.
|
||||
|
@ -1881,7 +1891,7 @@ namespace nanojit
|
|||
findMemFor(op1);
|
||||
}
|
||||
if (! (op1->isconst() || op1->isconstf() || op1->isconstq()))
|
||||
findRegFor(op1, i->isop(LIR_flive) ? FpRegs : GpRegs);
|
||||
findRegFor(op1, ins->isop(LIR_flive) ? FpRegs : GpRegs);
|
||||
}
|
||||
|
||||
// clear this list since we have now dealt with those lifetimes. extending
|
||||
|
|
|
@ -435,6 +435,7 @@ namespace nanojit
|
|||
void asm_i2f(LInsp ins);
|
||||
void asm_u2f(LInsp ins);
|
||||
void asm_f2i(LInsp ins);
|
||||
void asm_q2i(LInsp ins);
|
||||
void asm_promote(LIns *ins);
|
||||
void asm_nongp_copy(Register r, Register s);
|
||||
void asm_call(LInsp);
|
||||
|
|
|
@ -443,57 +443,61 @@ namespace nanojit
|
|||
return false;
|
||||
}
|
||||
|
||||
LIns* ExprFilter::ins1(LOpcode v, LIns* i)
|
||||
LIns* ExprFilter::ins1(LOpcode v, LIns* oprnd)
|
||||
{
|
||||
switch (v) {
|
||||
case LIR_q2i:
|
||||
if (oprnd->isconstq())
|
||||
return insImm(oprnd->imm64_0());
|
||||
break;
|
||||
case LIR_qlo:
|
||||
if (i->isconstq())
|
||||
return insImm(i->imm64_0());
|
||||
if (i->isop(LIR_qjoin))
|
||||
return i->oprnd1();
|
||||
if (oprnd->isconstq())
|
||||
return insImm(oprnd->imm64_0());
|
||||
if (oprnd->isop(LIR_qjoin))
|
||||
return oprnd->oprnd1();
|
||||
break;
|
||||
case LIR_qhi:
|
||||
if (i->isconstq())
|
||||
return insImm(i->imm64_1());
|
||||
if (i->isop(LIR_qjoin))
|
||||
return i->oprnd2();
|
||||
if (oprnd->isconstq())
|
||||
return insImm(oprnd->imm64_1());
|
||||
if (oprnd->isop(LIR_qjoin))
|
||||
return oprnd->oprnd2();
|
||||
break;
|
||||
case LIR_not:
|
||||
if (i->isconst())
|
||||
return insImm(~i->imm32());
|
||||
if (oprnd->isconst())
|
||||
return insImm(~oprnd->imm32());
|
||||
involution:
|
||||
if (v == i->opcode())
|
||||
return i->oprnd1();
|
||||
if (v == oprnd->opcode())
|
||||
return oprnd->oprnd1();
|
||||
break;
|
||||
case LIR_neg:
|
||||
if (i->isconst())
|
||||
return insImm(-i->imm32());
|
||||
if (i->isop(LIR_sub)) // -(a-b) = b-a
|
||||
return out->ins2(LIR_sub, i->oprnd2(), i->oprnd1());
|
||||
if (oprnd->isconst())
|
||||
return insImm(-oprnd->imm32());
|
||||
if (oprnd->isop(LIR_sub)) // -(a-b) = b-a
|
||||
return out->ins2(LIR_sub, oprnd->oprnd2(), oprnd->oprnd1());
|
||||
goto involution;
|
||||
case LIR_fneg:
|
||||
if (i->isconstq())
|
||||
return insImmf(-i->imm64f());
|
||||
if (i->isop(LIR_fsub))
|
||||
return out->ins2(LIR_fsub, i->oprnd2(), i->oprnd1());
|
||||
if (oprnd->isconstq())
|
||||
return insImmf(-oprnd->imm64f());
|
||||
if (oprnd->isop(LIR_fsub))
|
||||
return out->ins2(LIR_fsub, oprnd->oprnd2(), oprnd->oprnd1());
|
||||
goto involution;
|
||||
case LIR_i2f:
|
||||
if (i->isconst())
|
||||
return insImmf(i->imm32());
|
||||
if (oprnd->isconst())
|
||||
return insImmf(oprnd->imm32());
|
||||
break;
|
||||
case LIR_f2i:
|
||||
if (i->isconstq())
|
||||
return insImm(int32_t(i->imm64f()));
|
||||
if (oprnd->isconstq())
|
||||
return insImm(int32_t(oprnd->imm64f()));
|
||||
break;
|
||||
case LIR_u2f:
|
||||
if (i->isconst())
|
||||
return insImmf(uint32_t(i->imm32()));
|
||||
if (oprnd->isconst())
|
||||
return insImmf(uint32_t(oprnd->imm32()));
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
return out->ins1(v, i);
|
||||
return out->ins1(v, oprnd);
|
||||
}
|
||||
|
||||
// This is an ugly workaround for an apparent compiler
|
||||
|
@ -1521,8 +1525,10 @@ namespace nanojit
|
|||
case LIR_ld32f:
|
||||
case LIR_ldc32f:
|
||||
case LIR_ret:
|
||||
case LIR_qret:
|
||||
case LIR_fret:
|
||||
case LIR_live:
|
||||
case LIR_qlive:
|
||||
case LIR_flive:
|
||||
case LIR_xt:
|
||||
case LIR_xf:
|
||||
|
@ -1540,6 +1546,7 @@ namespace nanojit
|
|||
case LIR_u2q:
|
||||
case LIR_i2f:
|
||||
case LIR_u2f:
|
||||
case LIR_q2i:
|
||||
case LIR_f2i:
|
||||
case LIR_mod:
|
||||
live.add(ins->oprnd1(), ins);
|
||||
|
@ -1848,7 +1855,10 @@ namespace nanojit
|
|||
break;
|
||||
|
||||
case LIR_live:
|
||||
case LIR_flive:
|
||||
case LIR_qlive:
|
||||
case LIR_ret:
|
||||
case LIR_qret:
|
||||
case LIR_fret:
|
||||
VMPI_sprintf(s, "%s %s", lirNames[op], formatRef(i->oprnd1()));
|
||||
break;
|
||||
|
@ -1865,6 +1875,7 @@ namespace nanojit
|
|||
case LIR_mod:
|
||||
case LIR_i2q:
|
||||
case LIR_u2q:
|
||||
case LIR_q2i:
|
||||
case LIR_f2i:
|
||||
VMPI_sprintf(s, "%s = %s %s", formatRef(i), lirNames[op], formatRef(i->oprnd1()));
|
||||
break;
|
||||
|
@ -2315,7 +2326,7 @@ namespace nanojit
|
|||
void ValidateWriter::errorStructureShouldBe(LOpcode op, const char* argDesc, int argN,
|
||||
LIns* arg, const char* shouldBeDesc)
|
||||
{
|
||||
fprintf(stderr,
|
||||
NanoAssertMsgf(0,
|
||||
"\n\n"
|
||||
" LIR structure error (%s):\n"
|
||||
" in instruction with opcode: %s\n"
|
||||
|
@ -2499,16 +2510,9 @@ namespace nanojit
|
|||
case LIR_not:
|
||||
case LIR_i2f:
|
||||
case LIR_u2f:
|
||||
formals[0] = LTy_I32;
|
||||
break;
|
||||
|
||||
case LIR_live:
|
||||
case LIR_ret:
|
||||
// XXX: LIR_ret is used in TM as if it takes a 32-bit integer
|
||||
// argument, but it is used in TR as if it takes a word-sized
|
||||
// integer argument. We should split it into LIR_ret and LIR_qret
|
||||
// for clarity and consistency with all the other cases, and have
|
||||
// LIR_pret as a synonym. Don't type-check for now.
|
||||
nArgs = 0;
|
||||
formals[0] = LTy_I32;
|
||||
break;
|
||||
|
||||
case LIR_i2q:
|
||||
|
@ -2530,15 +2534,14 @@ namespace nanojit
|
|||
formals[0] = LTy_I32;
|
||||
break;
|
||||
|
||||
case LIR_qlo:
|
||||
// XXX: LIR_qlo currently has two distinct uses. One is in
|
||||
// combination with LIR_qhi and LIR_qjoin, for splitting/joining
|
||||
// F64s. The other is for truncating I64s. Because these have
|
||||
// different operand types we can't check it here. See bug
|
||||
// 540368.
|
||||
nArgs = 0;
|
||||
case LIR_q2i:
|
||||
case LIR_qret:
|
||||
case LIR_qlive:
|
||||
checkIs64BitPlatform(op);
|
||||
formals[0] = LTy_I64;
|
||||
break;
|
||||
|
||||
case LIR_qlo:
|
||||
case LIR_qhi:
|
||||
checkIs32BitPlatform(op);
|
||||
formals[0] = LTy_F64;
|
||||
|
@ -2551,13 +2554,6 @@ namespace nanojit
|
|||
formals[0] = LTy_F64;
|
||||
break;
|
||||
|
||||
case LIR_live:
|
||||
// XXX: should be a unary LTy_I32, but LIR_live is currently also
|
||||
// used for LTy_I64 values because we don't have LIR_qlive. So
|
||||
// we can't check it for now. See bug 540368.
|
||||
nArgs = 0;
|
||||
break;
|
||||
|
||||
case LIR_callh:
|
||||
checkLInsHasOpcode(op, 1, a, LIR_fcall);
|
||||
formals[0] = LTy_F64;
|
||||
|
|
|
@ -84,7 +84,9 @@ namespace nanojit
|
|||
LIR_puge = PTR_SIZE(LIR_uge, LIR_quge),
|
||||
LIR_alloc = PTR_SIZE(LIR_ialloc, LIR_qalloc),
|
||||
LIR_pcall = PTR_SIZE(LIR_icall, LIR_qcall),
|
||||
LIR_param = PTR_SIZE(LIR_iparam, LIR_qparam)
|
||||
LIR_param = PTR_SIZE(LIR_iparam, LIR_qparam),
|
||||
LIR_plive = PTR_SIZE(LIR_live, LIR_qlive),
|
||||
LIR_pret = PTR_SIZE(LIR_ret, LIR_qret)
|
||||
};
|
||||
|
||||
struct GuardRecord;
|
||||
|
@ -172,7 +174,7 @@ namespace nanojit
|
|||
(op >= LIR_quad && op <= LIR_quge);
|
||||
}
|
||||
inline bool isRetOpcode(LOpcode op) {
|
||||
return op == LIR_ret || op == LIR_fret;
|
||||
return op == LIR_ret || op == LIR_qret || op == LIR_fret;
|
||||
}
|
||||
LOpcode f64arith_to_i32arith(LOpcode op);
|
||||
LOpcode i32cmp_to_i64cmp(LOpcode op);
|
||||
|
|
|
@ -79,8 +79,8 @@ OPDEF(ld, 10, Ld, I32) // 32-bit integer load
|
|||
OPDEF(ialloc, 11, I, I32) // alloc some stack space (value is 32bit address)
|
||||
OPDEF(sti, 12, Sti, Void) // 32-bit integer store
|
||||
OPDEF(ret, 13, Op1, Void) // return a 32-bit integer
|
||||
OPDEF(live, 14, Op1, Void) // extend live range of reference
|
||||
OPDEF(flive, 15, Op1, Void) // extend live range of a floating point value reference
|
||||
OPDEF(live, 14, Op1, Void) // extend live range of a 32-bit integer
|
||||
OPDEF(flive, 15, Op1, Void) // extend live range of a 64-bit float
|
||||
OPDEF(icall, 16, C, I32) // subroutine call returning a 32-bit value
|
||||
OPDEF(sts, 17, Sti, Void) // 16-bit integer store
|
||||
|
||||
|
@ -190,7 +190,7 @@ OPDEF(line, 66, Op1, Void) // source line number for debug symbols
|
|||
OPDEF(xbarrier, 67, Op2, Void) // memory barrier; doesn't exit, but flushes all values to the stack
|
||||
OPDEF(xtbl, 68, Op2, Void) // exit via indirect jump
|
||||
|
||||
OPDEF(__69, 69, None, Void)
|
||||
OPDEF(qlive, 69, Op1, Void) // extend live range of a 64-bit integer
|
||||
OPDEF(__70, 70, None, Void)
|
||||
OPDEF(qaddp, 71, Op2, I64) // integer addition for temp pointer calculations (64bit only)
|
||||
OPDEF(qparam, 72, P, I64) // load a parameter (64bit register or stk location)
|
||||
|
@ -201,17 +201,17 @@ OPDEF(ldq, 74, Ld, I64) // 64-bit integer load
|
|||
OPDEF(qalloc, 75, I, I64) // allocate some stack space (value is 64bit address)
|
||||
|
||||
OPDEF(stqi, 76, Sti, Void) // 64-bit integer store
|
||||
OPDEF(fret, 77, Op1, Void) // return a 64-bit float
|
||||
|
||||
OPDEF(st32f, 78, Sti, Void) // store 64-bit float as a 32-bit float (dropping precision)
|
||||
OPDEF(ld32f, 79, Ld, F64) // load 32-bit float and widen to 64-bit float
|
||||
OPDEF(st32f, 77, Sti, Void) // store 64-bit float as a 32-bit float (dropping precision)
|
||||
OPDEF(ld32f, 78, Ld, F64) // load 32-bit float and widen to 64-bit float
|
||||
|
||||
OPDEF(fcall, 80, C, F64) // subroutine call returning 64-bit (quad) double value
|
||||
OPDEF(qcall, 81, C, I64) // subroutine call returning 64-bit (quad) integer value
|
||||
OPDEF(fcall, 79, C, F64) // subroutine call returning 64-bit (quad) double value
|
||||
OPDEF(qcall, 80, C, I64) // subroutine call returning 64-bit (quad) integer value
|
||||
|
||||
OPDEF(stfi, 82, Sti, Void) // 64-bit float store
|
||||
OPDEF(stfi, 81, Sti, Void) // 64-bit float store
|
||||
|
||||
OPDEF(__83, 83, None, Void)
|
||||
OPDEF(fret, 82, Op1, Void) // return a 64-bit float
|
||||
OPDEF(qret, 83, Op1, Void) // return a 64-bit integer
|
||||
OPDEF(__84, 84, None, Void)
|
||||
OPDEF(__85, 85, None, Void)
|
||||
OPDEF(__86, 86, None, Void)
|
||||
|
@ -256,7 +256,7 @@ OPDEF(qiadd, 112, Op2, I64) // 64-bit bitwise ADD
|
|||
|
||||
OPDEF(ldc32f, 113, Ld, F64) // non-volatile load 32-bit float and widen to 64-bit float
|
||||
OPDEF(qjoin, 114, Op2, F64) // join two 32-bit values (1st arg is low bits, 2nd is high)
|
||||
OPDEF(__115, 115, None, Void)
|
||||
OPDEF(q2i, 115, Op1, I32) // truncate i64 to i32
|
||||
OPDEF(__116, 116, None, Void)
|
||||
OPDEF(__117, 117, None, Void)
|
||||
OPDEF(float, 118, N64, F64) // 64-bit float constant value
|
||||
|
|
|
@ -2754,13 +2754,15 @@ Assembler::asm_ret(LIns *ins)
|
|||
}
|
||||
|
||||
void
|
||||
Assembler::asm_promote(LIns *ins)
|
||||
Assembler::asm_q2i(LIns *)
|
||||
{
|
||||
/* The LIR opcodes that result in a call to asm_promote are only generated
|
||||
* if NANOJIT_64BIT is #define'd, which it never is for ARM.
|
||||
*/
|
||||
(void)ins;
|
||||
NanoAssert(0);
|
||||
NanoAssert(0); // q2i shouldn't occur on 32-bit platforms
|
||||
}
|
||||
|
||||
void
|
||||
Assembler::asm_promote(LIns *)
|
||||
{
|
||||
NanoAssert(0); // i2q and u2q shouldn't occur on 32-bit platforms
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -637,7 +637,7 @@ namespace nanojit
|
|||
releaseRegisters();
|
||||
assignSavedRegs();
|
||||
LIns *value = ins->oprnd1();
|
||||
Register r = ins->isop(LIR_ret) ? R3 : F1;
|
||||
Register r = ins->isop(LIR_fret) ? F1 : R3;
|
||||
findSpecificRegFor(value, r);
|
||||
}
|
||||
|
||||
|
@ -1036,6 +1036,13 @@ namespace nanojit
|
|||
NanoAssertMsg(0, "NJ_F2I_SUPPORTED not yet supported for this architecture");
|
||||
}
|
||||
|
||||
// XXX: this is sub-optimal, see https://bugzilla.mozilla.org/show_bug.cgi?id=540368#c7.
|
||||
void Assembler::asm_q2i(LIns *ins) {
|
||||
Register rr = deprecated_prepResultReg(ins, GpRegs);
|
||||
int d = findMemFor(ins->oprnd1());
|
||||
LWZ(rr, d+4, FP);
|
||||
}
|
||||
|
||||
void Assembler::asm_promote(LIns *ins) {
|
||||
LOpcode op = ins->opcode();
|
||||
Register r = deprecated_prepResultReg(ins, GpRegs);
|
||||
|
|
|
@ -1075,13 +1075,17 @@ namespace nanojit
|
|||
if (ins->isop(LIR_ret)) {
|
||||
findSpecificRegFor(val, retRegs[0]);
|
||||
} else {
|
||||
NanoAssert(ins->isop(LIR_fret));
|
||||
findSpecificRegFor(val, F0);
|
||||
}
|
||||
}
|
||||
|
||||
void Assembler::asm_q2i(LIns *) {
|
||||
NanoAssert(0); // q2i shouldn't occur on 32-bit platforms
|
||||
}
|
||||
|
||||
void Assembler::asm_promote(LIns *) {
|
||||
// i2q or u2q
|
||||
TODO(asm_promote);
|
||||
NanoAssert(0); // i2q and u2q shouldn't occur on 32-bit platforms
|
||||
}
|
||||
|
||||
void Assembler::swapCodeChunks() {
|
||||
|
|
|
@ -61,8 +61,6 @@ better code
|
|||
- stack based LIR_param
|
||||
|
||||
tracing
|
||||
- asm_qjoin
|
||||
- asm_qhi
|
||||
- nFragExit
|
||||
|
||||
*/
|
||||
|
@ -979,6 +977,13 @@ namespace nanojit
|
|||
}
|
||||
}
|
||||
|
||||
void Assembler::asm_q2i(LIns *ins) {
|
||||
Register rr, ra;
|
||||
regalloc_unary(ins, GpRegs, rr, ra);
|
||||
NanoAssert(IsGpReg(ra));
|
||||
MOVLR(rr, ra); // 32bit mov zeros the upper 32bits of the target
|
||||
}
|
||||
|
||||
void Assembler::asm_promote(LIns *ins) {
|
||||
Register rr, ra;
|
||||
regalloc_unary(ins, GpRegs, rr, ra);
|
||||
|
@ -1366,7 +1371,7 @@ namespace nanojit
|
|||
releaseRegisters();
|
||||
assignSavedRegs();
|
||||
LIns *value = ins->oprnd1();
|
||||
Register r = ins->isop(LIR_ret) ? RAX : XMM0;
|
||||
Register r = ins->isop(LIR_fret) ? XMM0 : RAX;
|
||||
findSpecificRegFor(value, r);
|
||||
}
|
||||
|
||||
|
@ -1567,7 +1572,7 @@ namespace nanojit
|
|||
}
|
||||
|
||||
void Assembler::asm_qjoin(LIns*) {
|
||||
TODO(asm_qjoin);
|
||||
NanoAssert(0); // qjoin shouldn't occur on non-SoftFloat platforms
|
||||
}
|
||||
|
||||
void Assembler::asm_param(LIns *ins) {
|
||||
|
@ -1633,14 +1638,11 @@ namespace nanojit
|
|||
}
|
||||
|
||||
void Assembler::asm_qhi(LIns*) {
|
||||
TODO(asm_qhi);
|
||||
NanoAssert(0); // qhi shouldn't occur on non-SoftFloat platforms
|
||||
}
|
||||
|
||||
void Assembler::asm_qlo(LIns *ins) {
|
||||
Register rr, ra;
|
||||
regalloc_unary(ins, GpRegs, rr, ra);
|
||||
NanoAssert(IsGpReg(ra));
|
||||
MOVLR(rr, ra); // 32bit mov zeros the upper 32bits of the target
|
||||
void Assembler::asm_qlo(LIns *) {
|
||||
NanoAssert(0); // qlo shouldn't occur on non-SoftFloat platforms
|
||||
}
|
||||
|
||||
void Assembler::asm_spill(Register rr, int d, bool /*pop*/, bool quad) {
|
||||
|
|
|
@ -2088,14 +2088,18 @@ namespace nanojit
|
|||
if (ins->isop(LIR_ret)) {
|
||||
findSpecificRegFor(val, retRegs[0]);
|
||||
} else {
|
||||
NanoAssert(ins->isop(LIR_fret));
|
||||
findSpecificRegFor(val, FST0);
|
||||
fpu_pop();
|
||||
}
|
||||
}
|
||||
|
||||
void Assembler::asm_q2i(LIns *) {
|
||||
NanoAssert(0); // q2i shouldn't occur on 32-bit platforms
|
||||
}
|
||||
|
||||
void Assembler::asm_promote(LIns *) {
|
||||
// i2q or u2q
|
||||
TODO(asm_promote);
|
||||
NanoAssert(0); // i2q and u2q shouldn't occur on 32-bit platforms
|
||||
}
|
||||
|
||||
void Assembler::swapCodeChunks() {
|
||||
|
|
Загрузка…
Ссылка в новой задаче