summaryrefslogtreecommitdiffstats
path: root/js/src/jit/mips64/MacroAssembler-mips64.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit/mips64/MacroAssembler-mips64.cpp')
-rw-r--r--js/src/jit/mips64/MacroAssembler-mips64.cpp302
1 files changed, 124 insertions, 178 deletions
diff --git a/js/src/jit/mips64/MacroAssembler-mips64.cpp b/js/src/jit/mips64/MacroAssembler-mips64.cpp
index f58184bca..424e04306 100644
--- a/js/src/jit/mips64/MacroAssembler-mips64.cpp
+++ b/js/src/jit/mips64/MacroAssembler-mips64.cpp
@@ -258,36 +258,45 @@ MacroAssemblerMIPS64::ma_li(Register dest, ImmWord imm)
{
int64_t value = imm.value;
- if (value >= INT16_MIN && value <= INT16_MAX) {
+ if (-1 == (value >> 15) || 0 == (value >> 15)) {
as_addiu(dest, zero, value);
- } else if (imm.value <= UINT16_MAX) {
- as_ori(dest, zero, Imm16::Lower(Imm32(value)).encode());
- } else if (value >= INT32_MIN && value <= INT32_MAX) {
- as_lui(dest, Imm16::Upper(Imm32(value)).encode());
- if (value & 0xffff)
- as_ori(dest, dest, Imm16::Lower(Imm32(value)).encode());
- } else if (imm.value <= UINT32_MAX) {
- as_lui(dest, Imm16::Upper(Imm32(value)).encode());
- if (value & 0xffff)
- as_ori(dest, dest, Imm16::Lower(Imm32(value)).encode());
+ return;
+ }
+ if (0 == (value >> 16)) {
+ as_ori(dest, zero, value);
+ return;
+ }
+
+ if (-1 == (value >> 31) || 0 == (value >> 31)) {
+ as_lui(dest, uint16_t(value >> 16));
+ } else if (0 == (value >> 32)) {
+ as_lui(dest, uint16_t(value >> 16));
+ as_dinsu(dest, zero, 32, 32);
+ } else if (-1 == (value >> 47) || 0 == (value >> 47)) {
+ as_lui(dest, uint16_t(value >> 32));
+ if (uint16_t(value >> 16))
+ as_ori(dest, dest, uint16_t(value >> 16));
+ as_dsll(dest, dest, 16);
+ } else if (0 == (value >> 48)) {
+ as_lui(dest, uint16_t(value >> 32));
as_dinsu(dest, zero, 32, 32);
+ if (uint16_t(value >> 16))
+ as_ori(dest, dest, uint16_t(value >> 16));
+ as_dsll(dest, dest, 16);
} else {
- uint64_t high = imm.value >> 32;
-
- if (imm.value >> 48) {
- as_lui(dest, Imm16::Upper(Imm32(high)).encode());
- if (high & 0xffff)
- as_ori(dest, dest, Imm16::Lower(Imm32(high)).encode());
+ as_lui(dest, uint16_t(value >> 48));
+ if (uint16_t(value >> 32))
+ as_ori(dest, dest, uint16_t(value >> 32));
+ if (uint16_t(value >> 16)) {
+ as_dsll(dest, dest, 16);
+ as_ori(dest, dest, uint16_t(value >> 16));
as_dsll(dest, dest, 16);
} else {
- as_lui(dest, Imm16::Lower(Imm32(high)).encode());
+ as_dsll32(dest, dest, 32);
}
- if ((imm.value >> 16) & 0xffff)
- as_ori(dest, dest, Imm16::Upper(Imm32(value)).encode());
- as_dsll(dest, dest, 16);
- if (value & 0xffff)
- as_ori(dest, dest, Imm16::Lower(Imm32(value)).encode());
}
+ if (uint16_t(value))
+ as_ori(dest, dest, uint16_t(value));
}
// This method generates lui, dsll and ori instruction block that can be modified
@@ -488,7 +497,7 @@ void
MacroAssemblerMIPS64::ma_addTestOverflow(Register rd, Register rs, Imm32 imm, L overflow)
{
// Check for signed range because of as_daddiu
- if (Imm16::IsInSignedRange(imm.value) && Imm16::IsInUnsignedRange(imm.value)) {
+ if (Imm16::IsInSignedRange(imm.value)) {
as_daddiu(SecondScratchReg, rs, imm.value);
as_addiu(rd, rs, imm.value);
ma_b(rd, SecondScratchReg, overflow, Assembler::NotEqual);
@@ -710,14 +719,8 @@ MacroAssemblerMIPS64::ma_push(Register r)
void
MacroAssemblerMIPS64::ma_b(Register lhs, ImmWord imm, Label* label, Condition c, JumpKind jumpKind)
{
- MOZ_ASSERT(c != Overflow);
- if (imm.value == 0) {
- if (c == Always || c == AboveOrEqual)
- ma_b(label, jumpKind);
- else if (c == Below)
- ; // This condition is always false. No branch required.
- else
- branchWithCode(getBranchCode(lhs, c), label, jumpKind);
+ if (imm.value <= INT32_MAX) {
+ ma_b(lhs, Imm32(uint32_t(imm.value)), label, c, jumpKind);
} else {
MOZ_ASSERT(lhs != ScratchRegister);
ma_li(ScratchRegister, imm);
@@ -748,127 +751,20 @@ MacroAssemblerMIPS64::ma_b(Address addr, ImmGCPtr imm, Label* label, Condition c
}
void
-MacroAssemblerMIPS64::ma_bal(Label* label, DelaySlotFill delaySlotFill)
-{
- if (label->bound()) {
- // Generate the long jump for calls because return address has to be
- // the address after the reserved block.
- addLongJump(nextOffset());
- ma_liPatchable(ScratchRegister, ImmWord(label->offset()));
- as_jalr(ScratchRegister);
- if (delaySlotFill == FillDelaySlot)
- as_nop();
- return;
- }
-
- // Second word holds a pointer to the next branch in label's chain.
- uint32_t nextInChain = label->used() ? label->offset() : LabelBase::INVALID_OFFSET;
-
- // Make the whole branch continous in the buffer. The '6'
- // instructions are writing at below (contain delay slot).
- m_buffer.ensureSpace(6 * sizeof(uint32_t));
-
- BufferOffset bo = writeInst(getBranchCode(BranchIsCall).encode());
- writeInst(nextInChain);
- if (!oom())
- label->use(bo.getOffset());
- // Leave space for long jump.
- as_nop();
- as_nop();
- as_nop();
- if (delaySlotFill == FillDelaySlot)
- as_nop();
-}
-
-void
-MacroAssemblerMIPS64::branchWithCode(InstImm code, Label* label, JumpKind jumpKind)
-{
- MOZ_ASSERT(code.encode() != InstImm(op_regimm, zero, rt_bgezal, BOffImm16(0)).encode());
- InstImm inst_beq = InstImm(op_beq, zero, zero, BOffImm16(0));
-
- if (label->bound()) {
- int32_t offset = label->offset() - m_buffer.nextOffset().getOffset();
-
- if (BOffImm16::IsInRange(offset))
- jumpKind = ShortJump;
-
- if (jumpKind == ShortJump) {
- MOZ_ASSERT(BOffImm16::IsInRange(offset));
- code.setBOffImm16(BOffImm16(offset));
- writeInst(code.encode());
- as_nop();
- return;
- }
-
- if (code.encode() == inst_beq.encode()) {
- // Handle long jump
- addLongJump(nextOffset());
- ma_liPatchable(ScratchRegister, ImmWord(label->offset()));
- as_jr(ScratchRegister);
- as_nop();
- return;
- }
-
- // Handle long conditional branch, the target offset is based on self,
- // point to next instruction of nop at below.
- writeInst(invertBranch(code, BOffImm16(7 * sizeof(uint32_t))).encode());
- // No need for a "nop" here because we can clobber scratch.
- addLongJump(nextOffset());
- ma_liPatchable(ScratchRegister, ImmWord(label->offset()));
- as_jr(ScratchRegister);
- as_nop();
- return;
- }
-
- // Generate open jump and link it to a label.
-
- // Second word holds a pointer to the next branch in label's chain.
- uint32_t nextInChain = label->used() ? label->offset() : LabelBase::INVALID_OFFSET;
-
- if (jumpKind == ShortJump) {
- // Make the whole branch continous in the buffer.
- m_buffer.ensureSpace(2 * sizeof(uint32_t));
-
- // Indicate that this is short jump with offset 4.
- code.setBOffImm16(BOffImm16(4));
- BufferOffset bo = writeInst(code.encode());
- writeInst(nextInChain);
- if (!oom())
- label->use(bo.getOffset());
- return;
- }
-
- bool conditional = code.encode() != inst_beq.encode();
-
- // Make the whole branch continous in the buffer. The '7'
- // instructions are writing at below (contain conditional nop).
- m_buffer.ensureSpace(7 * sizeof(uint32_t));
-
- BufferOffset bo = writeInst(code.encode());
- writeInst(nextInChain);
- if (!oom())
- label->use(bo.getOffset());
- // Leave space for potential long jump.
- as_nop();
- as_nop();
- as_nop();
- as_nop();
- if (conditional)
- as_nop();
-}
-
-void
MacroAssemblerMIPS64::ma_cmp_set(Register rd, Register rs, ImmWord imm, Condition c)
{
- ma_li(ScratchRegister, imm);
- ma_cmp_set(rd, rs, ScratchRegister, c);
+ if (imm.value <= INT32_MAX) {
+ ma_cmp_set(rd, rs, Imm32(uint32_t(imm.value)), c);
+ } else {
+ ma_li(ScratchRegister, imm);
+ ma_cmp_set(rd, rs, ScratchRegister, c);
+ }
}
void
MacroAssemblerMIPS64::ma_cmp_set(Register rd, Register rs, ImmPtr imm, Condition c)
{
- ma_li(ScratchRegister, ImmWord(uintptr_t(imm.value)));
- ma_cmp_set(rd, rs, ScratchRegister, c);
+ ma_cmp_set(rd, rs, ImmWord(uintptr_t(imm.value)), c);
}
// fp instructions
@@ -877,6 +773,10 @@ MacroAssemblerMIPS64::ma_lid(FloatRegister dest, double value)
{
ImmWord imm(mozilla::BitwiseCast<uint64_t>(value));
+ if (imm.value == 0) {
+ moveToDouble(zero, dest);
+ return;
+ }
ma_li(ScratchRegister, imm);
moveToDouble(ScratchRegister, dest);
}
@@ -1149,21 +1049,21 @@ MacroAssemblerMIPS64Compat::loadDouble(const BaseIndex& src, FloatRegister dest)
}
void
-MacroAssemblerMIPS64Compat::loadUnalignedDouble(const BaseIndex& src, Register temp,
- FloatRegister dest)
+MacroAssemblerMIPS64Compat::loadUnalignedDouble(const wasm::MemoryAccessDesc& access,
+ const BaseIndex& src, Register temp, FloatRegister dest)
{
computeScaledAddress(src, SecondScratchReg);
-
+ BufferOffset load;
if (Imm16::IsInSignedRange(src.offset) && Imm16::IsInSignedRange(src.offset + 7)) {
- as_ldl(temp, SecondScratchReg, src.offset + 7);
+ load = as_ldl(temp, SecondScratchReg, src.offset + 7);
as_ldr(temp, SecondScratchReg, src.offset);
} else {
ma_li(ScratchRegister, Imm32(src.offset));
as_daddu(ScratchRegister, SecondScratchReg, ScratchRegister);
- as_ldl(temp, ScratchRegister, 7);
+ load = as_ldl(temp, ScratchRegister, 7);
as_ldr(temp, ScratchRegister, 0);
}
-
+ append(access, load.getOffset(), asMasm().framePushed());
moveToDouble(temp, dest);
}
@@ -1195,21 +1095,21 @@ MacroAssemblerMIPS64Compat::loadFloat32(const BaseIndex& src, FloatRegister dest
}
void
-MacroAssemblerMIPS64Compat::loadUnalignedFloat32(const BaseIndex& src, Register temp,
- FloatRegister dest)
+MacroAssemblerMIPS64Compat::loadUnalignedFloat32(const wasm::MemoryAccessDesc& access,
+ const BaseIndex& src, Register temp, FloatRegister dest)
{
computeScaledAddress(src, SecondScratchReg);
-
+ BufferOffset load;
if (Imm16::IsInSignedRange(src.offset) && Imm16::IsInSignedRange(src.offset + 3)) {
- as_lwl(temp, SecondScratchReg, src.offset + 3);
+ load = as_lwl(temp, SecondScratchReg, src.offset + 3);
as_lwr(temp, SecondScratchReg, src.offset);
} else {
ma_li(ScratchRegister, Imm32(src.offset));
as_daddu(ScratchRegister, SecondScratchReg, ScratchRegister);
- as_lwl(temp, ScratchRegister, 3);
+ load = as_lwl(temp, ScratchRegister, 3);
as_lwr(temp, ScratchRegister, 0);
}
-
+ append(access, load.getOffset(), asMasm().framePushed());
moveToFloat32(temp, dest);
}
@@ -1279,6 +1179,10 @@ MacroAssemblerMIPS64Compat::store32(Register src, const Address& address)
void
MacroAssemblerMIPS64Compat::store32(Imm32 src, const Address& address)
{
+ if (src.value == 0) {
+ ma_store(zero, address, SizeWord);
+ return;
+ }
move32(src, SecondScratchReg);
ma_store(SecondScratchReg, address, SizeWord);
}
@@ -1347,39 +1251,42 @@ MacroAssemblerMIPS64Compat::storePtr(Register src, AbsoluteAddress dest)
}
void
-MacroAssemblerMIPS64Compat::storeUnalignedFloat32(FloatRegister src, Register temp,
- const BaseIndex& dest)
+MacroAssemblerMIPS64Compat::storeUnalignedFloat32(const wasm::MemoryAccessDesc& access,
+ FloatRegister src, Register temp, const BaseIndex& dest)
{
computeScaledAddress(dest, SecondScratchReg);
moveFromFloat32(src, temp);
-
+ BufferOffset store;
if (Imm16::IsInSignedRange(dest.offset) && Imm16::IsInSignedRange(dest.offset + 3)) {
- as_swl(temp, SecondScratchReg, dest.offset + 3);
+ store = as_swl(temp, SecondScratchReg, dest.offset + 3);
as_swr(temp, SecondScratchReg, dest.offset);
} else {
ma_li(ScratchRegister, Imm32(dest.offset));
as_daddu(ScratchRegister, SecondScratchReg, ScratchRegister);
- as_swl(temp, ScratchRegister, 3);
+ store = as_swl(temp, ScratchRegister, 3);
as_swr(temp, ScratchRegister, 0);
}
+ append(access, store.getOffset(), asMasm().framePushed());
}
void
-MacroAssemblerMIPS64Compat::storeUnalignedDouble(FloatRegister src, Register temp,
- const BaseIndex& dest)
+MacroAssemblerMIPS64Compat::storeUnalignedDouble(const wasm::MemoryAccessDesc& access,
+ FloatRegister src, Register temp, const BaseIndex& dest)
{
computeScaledAddress(dest, SecondScratchReg);
moveFromDouble(src, temp);
+ BufferOffset store;
if (Imm16::IsInSignedRange(dest.offset) && Imm16::IsInSignedRange(dest.offset + 7)) {
- as_sdl(temp, SecondScratchReg, dest.offset + 7);
+ store = as_sdl(temp, SecondScratchReg, dest.offset + 7);
as_sdr(temp, SecondScratchReg, dest.offset);
} else {
ma_li(ScratchRegister, Imm32(dest.offset));
as_daddu(ScratchRegister, SecondScratchReg, ScratchRegister);
- as_sdl(temp, ScratchRegister, 7);
+ store = as_sdl(temp, ScratchRegister, 7);
as_sdr(temp, ScratchRegister, 0);
}
+ append(access, store.getOffset(), asMasm().framePushed());
}
// Note: this function clobbers the input register.
@@ -1455,22 +1362,52 @@ MacroAssemblerMIPS64Compat::testUndefinedSet(Condition cond, const ValueOperand&
void
MacroAssemblerMIPS64Compat::unboxNonDouble(const ValueOperand& operand, Register dest)
{
+ Label isInt32, done;
+ Register tag = splitTagForTest(operand);
+ asMasm().branchTestInt32(Assembler::Equal, tag, &isInt32);
+
ma_dext(dest, operand.valueReg(), Imm32(0), Imm32(JSVAL_TAG_SHIFT));
+ jump(&done);
+
+ bind(&isInt32);
+ ma_sll(dest, operand.valueReg(), Imm32(0));
+
+ bind(&done);
}
void
MacroAssemblerMIPS64Compat::unboxNonDouble(const Address& src, Register dest)
{
+ Label isInt32, done;
loadPtr(Address(src.base, src.offset), dest);
+ splitTag(dest, SecondScratchReg);
+ asMasm().branchTestInt32(Assembler::Equal, SecondScratchReg, &isInt32);
+
ma_dext(dest, dest, Imm32(0), Imm32(JSVAL_TAG_SHIFT));
+ jump(&done);
+
+ bind(&isInt32);
+ ma_sll(dest, dest, Imm32(0));
+
+ bind(&done);
}
void
MacroAssemblerMIPS64Compat::unboxNonDouble(const BaseIndex& src, Register dest)
{
+ Label isInt32, done;
computeScaledAddress(src, SecondScratchReg);
loadPtr(Address(SecondScratchReg, src.offset), dest);
+ splitTag(dest, SecondScratchReg);
+ asMasm().branchTestInt32(Assembler::Equal, SecondScratchReg, &isInt32);
+
ma_dext(dest, dest, Imm32(0), Imm32(JSVAL_TAG_SHIFT));
+ jump(&done);
+
+ bind(&isInt32);
+ ma_sll(dest, dest, Imm32(0));
+
+ bind(&done);
}
void
@@ -1823,13 +1760,12 @@ MacroAssemblerMIPS64Compat::jumpWithPatch(RepatchLabel* label, Label* documentat
{
// Only one branch per label.
MOZ_ASSERT(!label->used());
- uint32_t dest = label->bound() ? label->offset() : LabelBase::INVALID_OFFSET;
BufferOffset bo = nextOffset();
label->use(bo.getOffset());
- addLongJump(bo);
- ma_liPatchable(ScratchRegister, ImmWord(dest));
- as_jr(ScratchRegister);
+ if (label->bound())
+ addMixedJump(bo, label->offset(), MixedJumpPatch::PATCHABLE);
+ as_j(JOffImm26(0));
as_nop();
return CodeOffsetJump(bo.getOffset());
}
@@ -1878,7 +1814,11 @@ MacroAssemblerMIPS64Compat::storeValue(JSValueType type, Register reg, Address d
ma_li(SecondScratchReg, ImmTag(JSVAL_TYPE_TO_TAG(type)));
ma_dsll(SecondScratchReg, SecondScratchReg, Imm32(JSVAL_TAG_SHIFT));
- ma_dins(SecondScratchReg, reg, Imm32(0), Imm32(JSVAL_TAG_SHIFT));
+ if (type == JSVAL_TYPE_INT32 || type == JSVAL_TYPE_BOOLEAN) {
+ ma_dins(SecondScratchReg, reg, Imm32(0), Imm32(32));
+ } else {
+ ma_dins(SecondScratchReg, reg, Imm32(0), Imm32(JSVAL_TAG_SHIFT));
+ }
storePtr(SecondScratchReg, Address(dest.base, dest.offset));
}
@@ -1925,8 +1865,13 @@ void
MacroAssemblerMIPS64Compat::tagValue(JSValueType type, Register payload, ValueOperand dest)
{
MOZ_ASSERT(dest.valueReg() != ScratchRegister);
- if (payload != dest.valueReg())
- ma_move(dest.valueReg(), payload);
+ if (type == JSVAL_TYPE_INT32 || type == JSVAL_TYPE_BOOLEAN) {
+ ma_dext(dest.valueReg(), payload, Imm32(0), Imm32(32));
+ } else {
+ if (payload != dest.valueReg()) {
+ ma_move(dest.valueReg(), payload);
+ }
+ }
ma_li(ScratchRegister, ImmTag(JSVAL_TYPE_TO_TAG(type)));
ma_dins(dest.valueReg(), ScratchRegister, Imm32(JSVAL_TAG_SHIFT), Imm32(64 - JSVAL_TAG_SHIFT));
}
@@ -2051,9 +1996,9 @@ MacroAssemblerMIPS64Compat::handleFailureWithHandlerTail(void* handler)
loadPtr(Address(StackPointer, offsetof(ResumeFromException, stackPointer)), StackPointer);
// We're going to be returning by the ion calling convention
- ma_pop(ra);
+ as_ld(ra, StackPointer, 0);
as_jr(ra);
- as_nop();
+ as_daddiu(StackPointer, StackPointer, sizeof(intptr_t)); // in delay slot.
// If we found a catch handler, this must be a baseline frame. Restore
// state and jump to the catch block.
@@ -2075,8 +2020,9 @@ MacroAssemblerMIPS64Compat::handleFailureWithHandlerTail(void* handler)
loadPtr(Address(sp, offsetof(ResumeFromException, stackPointer)), sp);
pushValue(BooleanValue(true));
- pushValue(exception);
- jump(a0);
+ as_daddiu(StackPointer, StackPointer, -sizeof(intptr_t));
+ as_jr(a0);
+ as_sd(exception.valueReg(), StackPointer, 0); // In delay slot
// Only used in debug mode. Return BaselineFrame->returnValue() to the
// caller.