Bug 574969 - add LIR_qasd / LIR_dasq. r=edwsmith.

--HG--
extra : convert_revision : 06774ab0e7e002b4fe6f4091a5dd59904fb6b080
This commit is contained in:
Nicholas Nethercote 2010-07-20 21:04:21 -07:00
Родитель c2175829ad
Коммит b04ccdcbd5
14 изменённых файлов: 153 добавлений и 34 удалений

Просмотреть файл

@ -104,10 +104,12 @@ CL___( LOP_B_II, 3) // 57% LIR_eq, LIR_lt, etc
CL_64( LOP_B_QQ, 3) // 60% LIR_qeq, LIR_qlt, etc
CL___( LOP_B_DD, 3) // 63% LIR_feq, LIR_flt, etc
CL_64( LOP_Q_I, 2) // 65% LIR_i2q, LIR_u2q
CL___( LOP_D_I, 2) // 67% LIR_i2f, LIR_u2f
CL_64( LOP_I_Q, 1) // 68% LIR_q2i
CL___( LOP_I_D, 1) // 69% LIR_qlo, LIR_qhi, LIR_f2i
CL_64( LOP_Q_I, 1) // 64% LIR_i2q, LIR_u2q
CL___( LOP_D_I, 1) // 65% LIR_i2f, LIR_u2f
CL_64( LOP_I_Q, 1) // 66% LIR_q2i
CL___( LOP_I_D, 1) // 67% LIR_qlo, LIR_qhi, LIR_f2i
CL_64( LOP_Q_D, 1) // 68% LIR_dasq
CL_64( LOP_D_Q, 1) // 69% LIR_qasd
CL___( LOP_D_II, 1) // 70% LIR_qjoin
CL___( LLD_I, 3) // 73% LIR_ld, LIR_ldc, LIR_ld*b, LIR_ld*s

Просмотреть файл

@ -948,6 +948,8 @@ FragmentAssembler::assembleFragment(LirTokenStream &in, bool implicitBegin, cons
CASE64(LIR_q2i:)
CASE64(LIR_i2q:)
CASE64(LIR_ui2uq:)
CASE64(LIR_dasq:)
CASE64(LIR_qasd:)
case LIR_i2d:
case LIR_ui2d:
case LIR_d2i:
@ -970,6 +972,7 @@ FragmentAssembler::assembleFragment(LirTokenStream &in, bool implicitBegin, cons
case LIR_muld:
case LIR_divd:
CASE64(LIR_addq:)
CASE64(LIR_subq:)
case LIR_andi:
case LIR_ori:
case LIR_xori:
@ -1425,6 +1428,14 @@ FragmentAssembler::assembleRandomFragment(int nIns)
#endif
I_D_ops.push_back(LIR_d2i);
#ifdef NANOJIT_64BIT
vector<LOpcode> Q_D_ops;
Q_D_ops.push_back(LIR_dasq);
vector<LOpcode> D_Q_ops;
D_Q_ops.push_back(LIR_qasd);
#endif
vector<LOpcode> D_II_ops;
#if NJ_SOFTFLOAT_SUPPORTED
D_II_ops.push_back(LIR_ii2d);
@ -1776,6 +1787,24 @@ FragmentAssembler::assembleRandomFragment(int nIns)
#endif
break;
#if defined NANOJIT_X64
case LOP_Q_D:
if (!Ds.empty()) {
ins = mLir->ins1(rndPick(Q_D_ops), rndPick(Ds));
addOrReplace(Qs, ins);
n++;
}
break;
case LOP_D_Q:
if (!Qs.empty()) {
ins = mLir->ins1(rndPick(D_Q_ops), rndPick(Qs));
addOrReplace(Ds, ins);
n++;
}
break;
#endif
case LOP_D_II:
if (!Is.empty() && !D_II_ops.empty()) {
ins = mLir->ins2(rndPick(D_II_ops), rndPick(Is), rndPick(Is));
@ -2092,6 +2121,7 @@ usageAndQuit(const string& progname)
" --execute execute LIR\n"
" --[no-]optimize enable or disable optimization of the LIR (default=off)\n"
" --random [N] generate a random LIR block of size N (default=1000)\n"
" --word-size prints the word size (32 or 64) for this build of lirasm and exits\n"
" i386-specific options:\n"
" --sse use SSE2 instructions\n"
" ARM-specific options:\n"
@ -2166,6 +2196,10 @@ processCmdLine(int argc, char **argv, CmdLineOptions& opts)
}
}
}
else if (arg == "--word-size") {
cout << sizeof(void*) * 8 << "\n";
exit(0);
}
// Architecture-specific flags.
#if defined NANOJIT_IA32

Просмотреть файл

@ -47,6 +47,15 @@ runtest "--random 1000000 --optimize"
# ---- Platform-specific tests and configurations. ----
# 64-bit platforms
if [[ $($LIRASM --word-size) == 64 ]]
then
for infile in "$TESTS_DIR"/64-bit/*.in
do
runtest $infile
done
fi
# ARM
if [[ $(uname -m) == arm* ]]
then

Просмотреть файл

@ -0,0 +1,8 @@
q = immq 12345
d = qasd q
q2 = dasq d
one = immd 1.0 ; do some intermediate stuff to make it less trivial
two = immd 2.0
three = addd one two
i2 = q2i q2
reti i2

Просмотреть файл

@ -0,0 +1 @@
Output is: 12345

Просмотреть файл

@ -0,0 +1,7 @@
one = immq 1
d = immd 123.45
q = dasq d
q2 = addq q one ; do some intermediate stuff just to complicate things
q3 = subq q2 one
d2 = qasd q3
retd d2

Просмотреть файл

@ -0,0 +1 @@
Output is: 123.45

Просмотреть файл

@ -1651,7 +1651,7 @@ namespace nanojit
countlir_alu();
ins->oprnd1()->setResultLive();
if (ins->isExtant()) {
asm_promote(ins);
asm_ui2uq(ins);
}
break;
@ -1662,6 +1662,22 @@ namespace nanojit
asm_q2i(ins);
}
break;
case LIR_dasq:
countlir_alu();
ins->oprnd1()->setResultLive();
if (ins->isExtant()) {
asm_dasq(ins);
}
break;
case LIR_qasd:
countlir_alu();
ins->oprnd1()->setResultLive();
if (ins->isExtant()) {
asm_qasd(ins);
}
break;
#endif
case LIR_sti2c:
case LIR_sti2s:

Просмотреть файл

@ -453,7 +453,9 @@ namespace nanojit
void asm_d2i(LIns* ins);
#ifdef NANOJIT_64BIT
void asm_q2i(LIns* ins);
void asm_promote(LIns *ins);
void asm_ui2uq(LIns *ins);
void asm_dasq(LIns *ins);
void asm_qasd(LIns *ins);
#endif
void asm_nongp_copy(Register r, Register s);
void asm_call(LIns*);

Просмотреть файл

@ -550,6 +550,14 @@ namespace nanojit
if (oprnd->isImmI())
return insImmQ(uint64_t(uint32_t(oprnd->immI())));
break;
case LIR_dasq:
if (oprnd->isop(LIR_qasd))
return oprnd->oprnd1();
break;
case LIR_qasd:
if (oprnd->isop(LIR_dasq))
return oprnd->oprnd1();
break;
#endif
#if NJ_SOFTFLOAT_SUPPORTED
case LIR_dlo2i:
@ -587,10 +595,13 @@ namespace nanojit
case LIR_i2d:
if (oprnd->isImmI())
return insImmD(oprnd->immI());
// Nb: i2d(d2i(x)) != x
break;
case LIR_d2i:
if (oprnd->isImmD())
return insImmI(int32_t(oprnd->immD()));
if (oprnd->isop(LIR_i2d))
return oprnd->oprnd1();
break;
case LIR_ui2d:
if (oprnd->isImmI())
@ -1393,6 +1404,8 @@ namespace nanojit
case LIR_ui2d:
CASE64(LIR_q2i:)
case LIR_d2i:
CASE64(LIR_dasq:)
CASE64(LIR_qasd:)
CASE86(LIR_modi:)
live.add(ins->oprnd1(), 0);
break;
@ -1812,6 +1825,8 @@ namespace nanojit
CASE64(LIR_ui2uq:)
CASE64(LIR_q2i:)
case LIR_d2i:
CASE64(LIR_dasq:)
CASE64(LIR_qasd:)
VMPI_snprintf(s, n, "%s = %s %s", formatRef(&b1, i), lirNames[op],
formatRef(&b2, i->oprnd1()));
break;
@ -2976,6 +2991,7 @@ namespace nanojit
break;
case LIR_q2i:
case LIR_qasd:
case LIR_retq:
case LIR_liveq:
formals[0] = LTy_Q;
@ -3007,6 +3023,7 @@ namespace nanojit
case LIR_retd:
case LIR_lived:
case LIR_d2i:
CASE64(LIR_dasq:)
formals[0] = LTy_D;
break;

Просмотреть файл

@ -294,50 +294,49 @@ OP___(modd, 105, Op2, D, 1) // modulo double
OP___(cmovi, 106, Op3, I, 1) // conditional move int
OP_64(cmovq, 107, Op3, Q, 1) // conditional move quad
OP_UN(108)
//---------------------------------------------------------------------------
// Conversions
//---------------------------------------------------------------------------
OP_64(i2q, 109, Op1, Q, 1) // sign-extend int to quad
OP_64(ui2uq, 110, Op1, Q, 1) // zero-extend unsigned int to unsigned quad
OP_64(q2i, 111, Op1, I, 1) // truncate quad to int (removes the high 32 bits)
OP_64(i2q, 108, Op1, Q, 1) // sign-extend int to quad
OP_64(ui2uq, 109, Op1, Q, 1) // zero-extend unsigned int to unsigned quad
OP_64(q2i, 110, Op1, I, 1) // truncate quad to int (removes the high 32 bits)
OP___(i2d, 112, Op1, D, 1) // convert int to double
OP___(ui2d, 113, Op1, D, 1) // convert unsigned int to double
OP___(d2i, 114, Op1, I, 1) // convert double to int (no exceptions raised, platform rounding rules)
OP___(i2d, 111, Op1, D, 1) // convert int to double
OP___(ui2d, 112, Op1, D, 1) // convert unsigned int to double
OP___(d2i, 113, Op1, I, 1) // convert double to int (no exceptions raised, platform rounding rules)
OP_64(dasq, 114, Op1, Q, 1) // interpret the bits of a double as a quad
OP_64(qasd, 115, Op1, D, 1) // interpret the bits of a quad as a double
//---------------------------------------------------------------------------
// Overflow arithmetic
//---------------------------------------------------------------------------
// These all exit if overflow occurred. The result is valid on either path.
OP___(addxovi, 115, Op3, I, 1) // add int and exit on overflow
OP___(subxovi, 116, Op3, I, 1) // subtract int and exit on overflow
OP___(mulxovi, 117, Op3, I, 1) // multiply int and exit on overflow
OP___(addxovi, 116, Op3, I, 1) // add int and exit on overflow
OP___(subxovi, 117, Op3, I, 1) // subtract int and exit on overflow
OP___(mulxovi, 118, Op3, I, 1) // multiply int and exit on overflow
// These all branch if overflow occurred. The result is valid on either path.
OP___(addjovi, 118, Op3, I, 1) // add int and branch on overflow
OP___(subjovi, 119, Op3, I, 1) // subtract int and branch on overflow
OP___(muljovi, 120, Op3, I, 1) // multiply int and branch on overflow
OP___(addjovi, 119, Op3, I, 1) // add int and branch on overflow
OP___(subjovi, 120, Op3, I, 1) // subtract int and branch on overflow
OP___(muljovi, 121, Op3, I, 1) // multiply int and branch on overflow
OP_64(addjovq, 121, Op3, Q, 1) // add quad and branch on overflow
OP_64(subjovq, 122, Op3, Q, 1) // subtract quad and branch on overflow
OP_64(addjovq, 122, Op3, Q, 1) // add quad and branch on overflow
OP_64(subjovq, 123, Op3, Q, 1) // subtract quad and branch on overflow
//---------------------------------------------------------------------------
// SoftFloat
//---------------------------------------------------------------------------
OP_SF(dlo2i, 123, Op1, I, 1) // get the low 32 bits of a double as an int
OP_SF(dhi2i, 124, Op1, I, 1) // get the high 32 bits of a double as an int
OP_SF(ii2d, 125, Op2, D, 1) // join two ints (1st arg is low bits, 2nd is high)
OP_SF(dlo2i, 124, Op1, I, 1) // get the low 32 bits of a double as an int
OP_SF(dhi2i, 125, Op1, I, 1) // get the high 32 bits of a double as an int
OP_SF(ii2d, 126, Op2, D, 1) // join two ints (1st arg is low bits, 2nd is high)
// LIR_hcalli is a hack that's only used on 32-bit platforms that use
// SoftFloat. Its operand is always a LIR_calli, but one that specifies a
// function that returns a double. It indicates that the double result is
// returned via two 32-bit integer registers. The result is always used as the
// second operand of a LIR_ii2d.
OP_SF(hcalli, 126, Op1, I, 1)
OP_UN(127)
OP_SF(hcalli, 127, Op1, I, 1)
#undef OP_UN
#undef OP_32

Просмотреть файл

@ -647,11 +647,11 @@ namespace nanojit
NanoAssert(0); // q2i shouldn't occur on 32-bit platforms
}
void Assembler::asm_promote(LIns *ins)
void Assembler::asm_ui2uq(LIns *ins)
{
USE(ins);
TODO(asm_promote);
TAG("asm_promote(ins=%p{%s})", ins, lirNames[ins->opcode()]);
TODO(asm_ui2uq);
TAG("asm_ui2uq(ins=%p{%s})", ins, lirNames[ins->opcode()]);
}
#endif

Просмотреть файл

@ -1023,14 +1023,14 @@ namespace nanojit
LWZ(rr, d+4, FP);
}
void Assembler::asm_promote(LIns *ins) {
void Assembler::asm_ui2uq(LIns *ins) {
LOpcode op = ins->opcode();
Register r = deprecated_prepResultReg(ins, GpRegs);
Register v = findRegFor(ins->oprnd1(), GpRegs);
switch (op) {
default:
debug_only(outputf("%s",lirNames[op]));
TODO(asm_promote);
TODO(asm_ui2uq);
case LIR_ui2uq:
CLRLDI(r, v, 32); // clears the top 32 bits
break;
@ -1039,6 +1039,15 @@ namespace nanojit
break;
}
}
void Assembler::asm_dasq(LIns *ins) {
TODO(asm_dasq);
}
void Assembler::asm_qasd(LIns *ins) {
TODO(asm_qasd);
}
#endif
#ifdef NANOJIT_64BIT

Просмотреть файл

@ -1039,7 +1039,7 @@ namespace nanojit
endOpRegs(ins, rr, ra);
}
void Assembler::asm_promote(LIns *ins) {
void Assembler::asm_ui2uq(LIns *ins) {
Register rr, ra;
beginOp1Regs(ins, GpRegs, rr, ra);
NanoAssert(IsGpReg(ra));
@ -1052,6 +1052,20 @@ namespace nanojit
endOpRegs(ins, rr, ra);
}
void Assembler::asm_dasq(LIns *ins) {
Register rr = prepareResultReg(ins, GpRegs);
Register ra = findRegFor(ins->oprnd1(), FpRegs);
asm_nongp_copy(rr, ra);
freeResourcesOf(ins);
}
void Assembler::asm_qasd(LIns *ins) {
Register rr = prepareResultReg(ins, FpRegs);
Register ra = findRegFor(ins->oprnd1(), GpRegs);
asm_nongp_copy(rr, ra);
freeResourcesOf(ins);
}
// The CVTSI2SD instruction only writes to the low 64bits of the target
// XMM register, which hinders register renaming and makes dependence
// chains longer. So we precede with XORPS to clear the target register.