Bug 1403635 - MIPS: Add MIPS R1 support. r=bbouvier

Many tests fail on MIPS R1 boards because R2 instructions are emitted.
This patch adds architecture detection for R2, along existing one for
Loongson. Instruction sequences that are emitted for R1 instead of R2
instructions are added to macro assembler.
This commit is contained in:
Miran.Karic 2017-10-04 09:50:00 -04:00
parent 90add213ed
commit ee6e7153ed
9 changed files with 154 additions and 23 deletions

View File

@ -13,6 +13,7 @@
#define HWCAP_MIPS (1 << 28)
#define HWCAP_LOONGSON (1 << 27)
#define HWCAP_R2 (1 << 26)
#define HWCAP_FPU (1 << 0)
namespace js {
@ -25,6 +26,7 @@ get_mips_flags()
#if defined(JS_SIMULATOR_MIPS32) || defined(JS_SIMULATOR_MIPS64)
flags |= HWCAP_FPU;
flags |= HWCAP_R2;
#else
# ifdef __linux__
FILE* fp = fopen("/proc/cpuinfo", "r");
@ -39,6 +41,8 @@ get_mips_flags()
flags |= HWCAP_FPU;
if (strstr(buf, "Loongson"))
flags |= HWCAP_LOONGSON;
if (strstr(buf, "mips32r2") || strstr(buf, "mips64r2"))
flags |= HWCAP_R2;
# endif
#endif // JS_SIMULATOR_MIPS32 || JS_SIMULATOR_MIPS64
return flags;
@ -54,11 +58,17 @@ static bool check_loongson()
return mips_private::Flags & HWCAP_LOONGSON;
}
static bool check_r2()
{
return mips_private::Flags & HWCAP_R2;
}
namespace mips_private {
// Cache a local copy so we only have to read /proc/cpuinfo once.
uint32_t Flags = get_mips_flags();
bool hasFPU = check_fpu();;
bool isLoongson = check_loongson();
bool hasR2 = check_r2();
}
Registers::Code

View File

@ -314,11 +314,13 @@ namespace mips_private {
extern uint32_t Flags;
extern bool hasFPU;
extern bool isLoongson;
extern bool hasR2;
}
inline uint32_t GetMIPSFlags() { return mips_private::Flags; }
inline bool hasFPU() { return mips_private::hasFPU; }
inline bool isLoongson() { return mips_private::isLoongson; }
inline bool hasR2() { return mips_private::hasR2; }
// MIPS doesn't have double registers that can NOT be treated as float32.
inline bool

View File

@ -714,6 +714,7 @@ AssemblerMIPSShared::as_rotr(Register rd, Register rt, uint16_t sa)
{
MOZ_ASSERT(sa < 32);
spew("rotr %3s,%3s, 0x%x", rd.name(), rt.name(), sa);
MOZ_ASSERT(hasR2());
return writeInst(InstReg(op_special, rs_one, rt, rd, sa, ff_srl).encode());
}
@ -722,6 +723,7 @@ AssemblerMIPSShared::as_drotr(Register rd, Register rt, uint16_t sa)
{
MOZ_ASSERT(sa < 32);
spew("drotr %3s,%3s, 0x%x", rd.name(), rt.name(), sa);
MOZ_ASSERT(hasR2());
return writeInst(InstReg(op_special, rs_one, rt, rd, sa, ff_dsrl).encode());
}
@ -730,6 +732,7 @@ AssemblerMIPSShared::as_drotr32(Register rd, Register rt, uint16_t sa)
{
MOZ_ASSERT(31 < sa && sa < 64);
spew("drotr32%3s,%3s, 0x%x", rd.name(), rt.name(), sa - 32);
MOZ_ASSERT(hasR2());
return writeInst(InstReg(op_special, rs_one, rt, rd, sa - 32, ff_dsrl32).encode());
}
@ -737,6 +740,7 @@ BufferOffset
AssemblerMIPSShared::as_rotrv(Register rd, Register rt, Register rs)
{
spew("rotrv %3s,%3s,%3s", rd.name(), rt.name(), rs.name());
MOZ_ASSERT(hasR2());
return writeInst(InstReg(op_special, rs, rt, rd, 1, ff_srlv).encode());
}
@ -744,6 +748,7 @@ BufferOffset
AssemblerMIPSShared::as_drotrv(Register rd, Register rt, Register rs)
{
spew("drotrv %3s,%3s,%3s", rd.name(), rt.name(), rs.name());
MOZ_ASSERT(hasR2());
return writeInst(InstReg(op_special, rs, rt, rd, 1, ff_dsrlv).encode());
}
@ -1076,6 +1081,7 @@ AssemblerMIPSShared::as_ins(Register rt, Register rs, uint16_t pos, uint16_t siz
Register rd;
rd = Register::FromCode(pos + size - 1);
spew("ins %3s,%3s, %d, %d", rt.name(), rs.name(), pos, size);
MOZ_ASSERT(hasR2());
return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_ins).encode());
}
@ -1086,6 +1092,7 @@ AssemblerMIPSShared::as_dins(Register rt, Register rs, uint16_t pos, uint16_t si
Register rd;
rd = Register::FromCode(pos + size - 1);
spew("dins %3s,%3s, %d, %d", rt.name(), rs.name(), pos, size);
MOZ_ASSERT(hasR2());
return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_dins).encode());
}
@ -1096,6 +1103,7 @@ AssemblerMIPSShared::as_dinsm(Register rt, Register rs, uint16_t pos, uint16_t s
Register rd;
rd = Register::FromCode(pos + size - 1 - 32);
spew("dinsm %3s,%3s, %d, %d", rt.name(), rs.name(), pos, size);
MOZ_ASSERT(hasR2());
return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_dinsm).encode());
}
@ -1106,6 +1114,7 @@ AssemblerMIPSShared::as_dinsu(Register rt, Register rs, uint16_t pos, uint16_t s
Register rd;
rd = Register::FromCode(pos + size - 1 - 32);
spew("dinsu %3s,%3s, %d, %d", rt.name(), rs.name(), pos, size);
MOZ_ASSERT(hasR2());
return writeInst(InstReg(op_special3, rs, rt, rd, pos - 32, ff_dinsu).encode());
}
@ -1116,6 +1125,7 @@ AssemblerMIPSShared::as_ext(Register rt, Register rs, uint16_t pos, uint16_t siz
Register rd;
rd = Register::FromCode(size - 1);
spew("ext %3s,%3s, %d, %d", rt.name(), rs.name(), pos, size);
MOZ_ASSERT(hasR2());
return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_ext).encode());
}
@ -1124,6 +1134,7 @@ BufferOffset
AssemblerMIPSShared::as_seb(Register rd, Register rt)
{
spew("seb %3s,%3s", rd.name(), rt.name());
MOZ_ASSERT(hasR2());
return writeInst(InstReg(op_special3, zero, rt, rd, 16, ff_bshfl).encode());
}
@ -1131,6 +1142,7 @@ BufferOffset
AssemblerMIPSShared::as_seh(Register rd, Register rt)
{
spew("seh %3s,%3s", rd.name(), rt.name());
MOZ_ASSERT(hasR2());
return writeInst(InstReg(op_special3, zero, rt, rd, 24, ff_bshfl).encode());
}
@ -1141,6 +1153,7 @@ AssemblerMIPSShared::as_dext(Register rt, Register rs, uint16_t pos, uint16_t si
Register rd;
rd = Register::FromCode(size - 1);
spew("dext %3s,%3s, %d, %d", rt.name(), rs.name(), pos, size);
MOZ_ASSERT(hasR2());
return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_dext).encode());
}
@ -1151,7 +1164,8 @@ AssemblerMIPSShared::as_dextm(Register rt, Register rs, uint16_t pos, uint16_t s
Register rd;
rd = Register::FromCode(size - 1 - 32);
spew("dextm %3s,%3s, %d, %d", rt.name(), rs.name(), pos, size);
return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_dextm).encode());
MOZ_ASSERT(hasR2());
return writeInst(InstReg(op_special3, rs, rt, rd, pos, ff_dextm).encode());
}
BufferOffset
@ -1161,6 +1175,7 @@ AssemblerMIPSShared::as_dextu(Register rt, Register rs, uint16_t pos, uint16_t s
Register rd;
rd = Register::FromCode(size - 1);
spew("dextu %3s,%3s, %d, %d", rt.name(), rs.name(), pos, size);
MOZ_ASSERT(hasR2());
return writeInst(InstReg(op_special3, rs, rt, rd, pos - 32, ff_dextu).encode());
}
@ -1412,6 +1427,7 @@ BufferOffset
AssemblerMIPSShared::as_truncls(FloatRegister fd, FloatRegister fs)
{
spew("trunc.l.s%3s,%3s", fd.name(), fs.name());
MOZ_ASSERT(hasR2());
return writeInst(InstReg(op_cop1, rs_s, zero, fs, fd, ff_trunc_l_fmt).encode());
}
@ -1447,6 +1463,7 @@ BufferOffset
AssemblerMIPSShared::as_truncld(FloatRegister fd, FloatRegister fs)
{
spew("trunc.l.d%3s,%3s", fd.name(), fs.name());
MOZ_ASSERT(hasR2());
return writeInst(InstReg(op_cop1, rs_d, zero, fs, fd, ff_trunc_l_fmt).encode());
}
@ -1454,6 +1471,7 @@ BufferOffset
AssemblerMIPSShared::as_cvtdl(FloatRegister fd, FloatRegister fs)
{
spew("cvt.d.l%3s,%3s", fd.name(), fs.name());
MOZ_ASSERT(hasR2());
return writeInst(InstReg(op_cop1, rs_l, zero, fs, fd, ff_cvt_d_fmt).encode());
}
@ -1482,6 +1500,7 @@ BufferOffset
AssemblerMIPSShared::as_cvtsl(FloatRegister fd, FloatRegister fs)
{
spew("cvt.s.l%3s,%3s", fd.name(), fs.name());
MOZ_ASSERT(hasR2());
return writeInst(InstReg(op_cop1, rs_l, zero, fs, fd, ff_cvt_s_fmt).encode());
}

View File

@ -1580,7 +1580,7 @@ CodeGeneratorMIPSShared::visitCopySignF(LCopySignF* ins)
masm.moveFromFloat32(rhs, rhsi);
// Combine.
masm.as_ins(rhsi, lhsi, 0, 31);
masm.ma_ins(rhsi, lhsi, 0, 31);
masm.moveToFloat32(rhsi, output);
}
@ -1600,7 +1600,7 @@ CodeGeneratorMIPSShared::visitCopySignD(LCopySignD* ins)
masm.moveFromDoubleHi(rhs, rhsi);
// Combine.
masm.as_ins(rhsi, lhsi, 0, 31);
masm.ma_ins(rhsi, lhsi, 0, 31);
masm.moveToDoubleHi(rhsi, output);
}

View File

@ -29,13 +29,13 @@ MacroAssembler::moveGPRToFloat32(Register src, FloatRegister dest)
void
MacroAssembler::move8SignExtend(Register src, Register dest)
{
as_seb(dest, src);
ma_seb(dest, src);
}
void
MacroAssembler::move16SignExtend(Register src, Register dest)
{
as_seh(dest, src);
ma_seh(dest, src);
}
// ===============================================================

View File

@ -71,13 +71,27 @@ MacroAssemblerMIPSShared::ma_sra(Register rd, Register rt, Imm32 shift)
void
MacroAssemblerMIPSShared::ma_ror(Register rd, Register rt, Imm32 shift)
{
as_rotr(rd, rt, shift.value % 32);
if (hasR2()) {
as_rotr(rd, rt, shift.value % 32);
} else {
ScratchRegisterScope scratch(asMasm());
as_srl(scratch, rt, shift.value % 32);
as_sll(rd, rt, (32 - (shift.value % 32)) % 32);
as_or(rd, rd, scratch);
}
}
void
MacroAssemblerMIPSShared::ma_rol(Register rd, Register rt, Imm32 shift)
{
as_rotr(rd, rt, 32 - (shift.value % 32));
if (hasR2()) {
as_rotr(rd, rt, (32 - (shift.value % 32)) % 32);
} else {
ScratchRegisterScope scratch(asMasm());
as_srl(scratch, rt, (32 - (shift.value % 32)) % 32);
as_sll(rd, rt, shift.value % 32);
as_or(rd, rd, scratch);
}
}
void
@ -101,14 +115,29 @@ MacroAssemblerMIPSShared::ma_sra(Register rd, Register rt, Register shift)
void
MacroAssemblerMIPSShared::ma_ror(Register rd, Register rt, Register shift)
{
as_rotrv(rd, rt, shift);
if (hasR2()) {
as_rotrv(rd, rt, shift);
} else {
ScratchRegisterScope scratch(asMasm());
ma_negu(scratch, shift);
as_sllv(scratch, rt, scratch);
as_srlv(rd, rt, shift);
as_or(rd, rd, scratch);
}
}
void
MacroAssemblerMIPSShared::ma_rol(Register rd, Register rt, Register shift)
{
ma_negu(ScratchRegister, shift);
as_rotrv(rd, rt, ScratchRegister);
ScratchRegisterScope scratch(asMasm());
ma_negu(scratch, shift);
if (hasR2()) {
as_rotrv(rd, rt, scratch);
} else {
as_srlv(rd, rt, scratch);
as_sllv(scratch, rt, shift);
as_or(rd, rd, scratch);
}
}
void
@ -123,6 +152,69 @@ MacroAssemblerMIPSShared::ma_not(Register rd, Register rs)
as_nor(rd, rs, zero);
}
// Bit extract/insert
void
MacroAssemblerMIPSShared::ma_ext(Register rt, Register rs, uint16_t pos, uint16_t size) {
MOZ_ASSERT(pos < 32);
MOZ_ASSERT(pos + size < 33);
if (hasR2()) {
as_ext(rt, rs, pos, size);
} else {
int shift_left = 32 - (pos + size);
as_sll(rt, rs, shift_left);
int shift_right = 32 - size;
if (shift_right > 0) {
as_srl(rt, rt, shift_right);
}
}
}
void
MacroAssemblerMIPSShared::ma_ins(Register rt, Register rs, uint16_t pos, uint16_t size) {
MOZ_ASSERT(pos < 32);
MOZ_ASSERT(pos + size <= 32);
MOZ_ASSERT(size != 0);
if (hasR2()) {
as_ins(rt, rs, pos, size);
} else {
ScratchRegisterScope scratch(asMasm());
SecondScratchRegisterScope scratch2(asMasm());
ma_subu(scratch, zero, Imm32(1));
as_srl(scratch, scratch, 32 - size);
as_and(scratch2, rs, scratch);
as_sll(scratch2, scratch2, pos);
as_sll(scratch, scratch, pos);
as_nor(scratch, scratch, zero);
as_and(scratch, rt, scratch);
as_or(rt, scratch2, scratch);
}
}
// Sign extend
void
MacroAssemblerMIPSShared::ma_seb(Register rd, Register rt)
{
if (hasR2()) {
as_seb(rd, rt);
} else {
as_sll(rd, rt, 24);
as_sra(rd, rd, 24);
}
}
void
MacroAssemblerMIPSShared::ma_seh(Register rd, Register rt)
{
if (hasR2()) {
as_seh(rd, rt);
} else {
as_sll(rd, rt, 16);
as_sra(rd, rd, 16);
}
}
// And.
void
MacroAssemblerMIPSShared::ma_and(Register rd, Register rs)
@ -484,7 +576,7 @@ MacroAssemblerMIPSShared::ma_load_unaligned(Register dest, const BaseIndex& src,
as_lbu(temp, base, hiOffset);
else
as_lb(temp, base, hiOffset);
as_ins(dest, temp, 8, 24);
ma_ins(dest, temp, 8, 24);
break;
case SizeWord:
as_lwl(dest, base, hiOffset);
@ -627,7 +719,7 @@ MacroAssemblerMIPSShared::ma_store_unaligned(Register data, const BaseIndex& des
switch (size) {
case SizeHalfWord:
as_sb(data, base, lowOffset);
as_ext(temp, data, 8, 8);
ma_ext(temp, data, 8, 8);
as_sb(temp, base, hiOffset);
break;
case SizeWord:
@ -1243,10 +1335,10 @@ MacroAssemblerMIPSShared::atomicFetchOpMIPSr2(int nbytes, bool signExtend, Atomi
if (signExtend) {
switch (nbytes) {
case 1:
as_seb(output, output);
ma_seb(output, output);
break;
case 2:
as_seh(output, output);
ma_seh(output, output);
break;
case 4:
break;
@ -1418,10 +1510,10 @@ MacroAssemblerMIPSShared::compareExchangeMIPSr2(int nbytes, bool signExtend, con
if (signExtend) {
switch (nbytes) {
case 1:
as_seb(output, output);
ma_seb(output, output);
break;
case 2:
as_seh(output, output);
ma_seh(output, output);
break;
case 4:
break;
@ -1769,7 +1861,7 @@ MacroAssembler::wasmTruncateDoubleToInt32(FloatRegister input, Register output,
as_truncwd(ScratchFloat32Reg, input);
as_cfc1(ScratchRegister, Assembler::FCSR);
moveFromFloat32(ScratchFloat32Reg, output);
as_ext(ScratchRegister, ScratchRegister, 6, 1);
ma_ext(ScratchRegister, ScratchRegister, 6, 1);
ma_b(ScratchRegister, Imm32(0), oolEntry, Assembler::NotEqual);
}
@ -1780,7 +1872,7 @@ MacroAssembler::wasmTruncateFloat32ToInt32(FloatRegister input, Register output,
as_truncws(ScratchFloat32Reg, input);
as_cfc1(ScratchRegister, Assembler::FCSR);
moveFromFloat32(ScratchFloat32Reg, output);
as_ext(ScratchRegister, ScratchRegister, 6, 1);
ma_ext(ScratchRegister, ScratchRegister, 6, 1);
ma_b(ScratchRegister, Imm32(0), oolEntry, Assembler::NotEqual);
}

View File

@ -85,6 +85,14 @@ class MacroAssemblerMIPSShared : public Assembler
void ma_not(Register rd, Register rs);
// Bit extract/insert
void ma_ext(Register rt, Register rs, uint16_t pos, uint16_t size);
void ma_ins(Register rt, Register rs, uint16_t pos, uint16_t size);
// Sign extend
void ma_seb(Register rd, Register rt);
void ma_seh(Register rd, Register rt);
// and
void ma_and(Register rd, Register rs);
void ma_and(Register rd, Imm32 imm);

View File

@ -683,7 +683,7 @@ CodeGeneratorMIPS64::visitWasmTruncateToInt64(LWasmTruncateToInt64* lir)
masm.moveFromDouble(ScratchDoubleReg, output);
masm.as_cfc1(ScratchRegister, Assembler::FCSR);
// extract invalid operation flag (bit 6) from FCSR
masm.as_ext(ScratchRegister, ScratchRegister, 6, 1);
masm.ma_ext(ScratchRegister, ScratchRegister, 6, 1);
masm.ma_dsrl(SecondScratchReg, output, Imm32(63));
masm.ma_or(SecondScratchReg, ScratchRegister);
masm.ma_b(SecondScratchReg, Imm32(0), ool->entry(), Assembler::NotEqual);
@ -703,7 +703,7 @@ CodeGeneratorMIPS64::visitWasmTruncateToInt64(LWasmTruncateToInt64* lir)
// Check that the result is in the uint64_t range.
masm.moveFromDouble(ScratchDoubleReg, output);
masm.as_cfc1(ScratchRegister, Assembler::FCSR);
masm.as_ext(ScratchRegister, ScratchRegister, 6, 1);
masm.ma_ext(ScratchRegister, ScratchRegister, 6, 1);
masm.ma_dsrl(SecondScratchReg, output, Imm32(63));
masm.ma_or(SecondScratchReg, ScratchRegister);
masm.ma_b(SecondScratchReg, Imm32(0), ool->entry(), Assembler::NotEqual);
@ -724,7 +724,7 @@ CodeGeneratorMIPS64::visitWasmTruncateToInt64(LWasmTruncateToInt64* lir)
// Check that the result is in the int64_t range.
masm.as_cfc1(output, Assembler::FCSR);
masm.as_ext(output, output, 6, 1);
masm.ma_ext(output, output, 6, 1);
masm.ma_b(output, Imm32(0), ool->entry(), Assembler::NotEqual);
masm.bind(ool->rejoin());

View File

@ -2578,7 +2578,7 @@ MacroAssembler::wasmTruncateDoubleToUInt32(FloatRegister input, Register output,
as_truncld(ScratchDoubleReg, input);
moveFromDoubleHi(ScratchDoubleReg, output);
as_cfc1(ScratchRegister, Assembler::FCSR);
as_ext(ScratchRegister, ScratchRegister, 6, 1);
ma_ext(ScratchRegister, ScratchRegister, 6, 1);
ma_or(ScratchRegister, output);
moveFromFloat32(ScratchDoubleReg, output);
ma_b(ScratchRegister, Imm32(0), oolEntry, Assembler::NotEqual);
@ -2592,7 +2592,7 @@ MacroAssembler::wasmTruncateFloat32ToUInt32(FloatRegister input, Register output
as_truncls(ScratchDoubleReg, input);
moveFromDoubleHi(ScratchDoubleReg, output);
as_cfc1(ScratchRegister, Assembler::FCSR);
as_ext(ScratchRegister, ScratchRegister, 6, 1);
ma_ext(ScratchRegister, ScratchRegister, 6, 1);
ma_or(ScratchRegister, output);
moveFromFloat32(ScratchDoubleReg, output);
ma_b(ScratchRegister, Imm32(0), oolEntry, Assembler::NotEqual);