mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 915833 - SpiderMonkey: Add support for immediate addresses on x64. r=sstangl
This commit is contained in:
parent
2f0a25f9b6
commit
f679cd4daa
@ -561,6 +561,13 @@ public:
|
|||||||
m_formatter.oneByteOp64(OP_ADD_GvEv, dst, base, offset);
|
m_formatter.oneByteOp64(OP_ADD_GvEv, dst, base, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addq_mr(const void* addr, RegisterID dst)
|
||||||
|
{
|
||||||
|
spew("addq %p, %s",
|
||||||
|
addr, nameIReg(8, dst));
|
||||||
|
m_formatter.oneByteOp64(OP_ADD_GvEv, dst, addr);
|
||||||
|
}
|
||||||
|
|
||||||
void addq_ir(int imm, RegisterID dst)
|
void addq_ir(int imm, RegisterID dst)
|
||||||
{
|
{
|
||||||
spew("addq $0x%x, %s", imm, nameIReg(8,dst));
|
spew("addq $0x%x, %s", imm, nameIReg(8,dst));
|
||||||
@ -585,10 +592,22 @@ public:
|
|||||||
m_formatter.immediate32(imm);
|
m_formatter.immediate32(imm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
|
void addq_im(int imm, const void* addr)
|
||||||
|
{
|
||||||
|
spew("addq %d, %p", imm, addr);
|
||||||
|
if (CAN_SIGN_EXTEND_8_32(imm)) {
|
||||||
|
m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_ADD, addr);
|
||||||
|
m_formatter.immediate8(imm);
|
||||||
|
} else {
|
||||||
|
m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_ADD, addr);
|
||||||
|
m_formatter.immediate32(imm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
void addl_im(int imm, const void* addr)
|
void addl_im(int imm, const void* addr)
|
||||||
{
|
{
|
||||||
FIXME_INSN_PRINTING;
|
spew("addl %d, %p", imm, addr);
|
||||||
if (CAN_SIGN_EXTEND_8_32(imm)) {
|
if (CAN_SIGN_EXTEND_8_32(imm)) {
|
||||||
m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, addr);
|
m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, addr);
|
||||||
m_formatter.immediate8(imm);
|
m_formatter.immediate8(imm);
|
||||||
@ -597,7 +616,6 @@ public:
|
|||||||
m_formatter.immediate32(imm);
|
m_formatter.immediate32(imm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void andl_rr(RegisterID src, RegisterID dst)
|
void andl_rr(RegisterID src, RegisterID dst)
|
||||||
{
|
{
|
||||||
@ -665,6 +683,13 @@ public:
|
|||||||
m_formatter.oneByteOp64(OP_OR_GvEv, dst, base, offset);
|
m_formatter.oneByteOp64(OP_OR_GvEv, dst, base, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void orq_mr(const void* addr, RegisterID dst)
|
||||||
|
{
|
||||||
|
spew("orq %p, %s",
|
||||||
|
addr, nameIReg(8, dst));
|
||||||
|
m_formatter.oneByteOp64(OP_OR_GvEv, dst, addr);
|
||||||
|
}
|
||||||
|
|
||||||
void andq_ir(int imm, RegisterID dst)
|
void andq_ir(int imm, RegisterID dst)
|
||||||
{
|
{
|
||||||
spew("andq $0x%x, %s", imm, nameIReg(8,dst));
|
spew("andq $0x%x, %s", imm, nameIReg(8,dst));
|
||||||
@ -878,6 +903,13 @@ public:
|
|||||||
m_formatter.oneByteOp64(OP_SUB_GvEv, dst, base, offset);
|
m_formatter.oneByteOp64(OP_SUB_GvEv, dst, base, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void subq_mr(const void* addr, RegisterID dst)
|
||||||
|
{
|
||||||
|
spew("subq %p, %s",
|
||||||
|
addr, nameIReg(8, dst));
|
||||||
|
m_formatter.oneByteOp64(OP_SUB_GvEv, dst, addr);
|
||||||
|
}
|
||||||
|
|
||||||
void subq_ir(int imm, RegisterID dst)
|
void subq_ir(int imm, RegisterID dst)
|
||||||
{
|
{
|
||||||
spew("subq $0x%x, %s", imm, nameIReg(8,dst));
|
spew("subq $0x%x, %s", imm, nameIReg(8,dst));
|
||||||
@ -1254,7 +1286,23 @@ public:
|
|||||||
m_formatter.immediate32(imm);
|
m_formatter.immediate32(imm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
void cmpq_im(int imm, const void* addr)
|
||||||
|
{
|
||||||
|
spew("cmpq $0x%x, %p", imm, addr);
|
||||||
|
if (CAN_SIGN_EXTEND_8_32(imm)) {
|
||||||
|
m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_CMP, addr);
|
||||||
|
m_formatter.immediate8(imm);
|
||||||
|
} else {
|
||||||
|
m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_CMP, addr);
|
||||||
|
m_formatter.immediate32(imm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void cmpq_rm(RegisterID reg, const void* addr)
|
||||||
|
{
|
||||||
|
spew("cmpq %s, %p", nameIReg(8, reg), addr);
|
||||||
|
m_formatter.oneByteOp64(OP_CMP_EvGv, reg, addr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
void cmpl_rm(RegisterID reg, const void* addr)
|
void cmpl_rm(RegisterID reg, const void* addr)
|
||||||
{
|
{
|
||||||
spew("cmpl %s, %p",
|
spew("cmpl %s, %p",
|
||||||
@ -1273,7 +1321,6 @@ public:
|
|||||||
m_formatter.immediate32(imm);
|
m_formatter.immediate32(imm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void cmpw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
|
void cmpw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
|
||||||
{
|
{
|
||||||
@ -1558,14 +1605,14 @@ public:
|
|||||||
m_formatter.oneByteOp_disp32(OP_MOV_GvEv, dst, base, offset);
|
m_formatter.oneByteOp_disp32(OP_MOV_GvEv, dst, base, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if WTF_CPU_X86
|
|
||||||
void movl_mr(const void* base, RegisterID index, int scale, RegisterID dst)
|
void movl_mr(const void* base, RegisterID index, int scale, RegisterID dst)
|
||||||
{
|
{
|
||||||
|
int32_t disp = addressImmediate(base);
|
||||||
|
|
||||||
spew("movl %d(,%s,%d), %s",
|
spew("movl %d(,%s,%d), %s",
|
||||||
int(base), nameIReg(index), scale, nameIReg(dst));
|
disp, nameIReg(index), scale, nameIReg(dst));
|
||||||
m_formatter.oneByteOp_disp32(OP_MOV_GvEv, dst, index, scale, int(base));
|
m_formatter.oneByteOp_disp32(OP_MOV_GvEv, dst, index, scale, disp);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void movl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
|
void movl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
|
||||||
{
|
{
|
||||||
@ -1574,7 +1621,6 @@ public:
|
|||||||
m_formatter.oneByteOp(OP_MOV_GvEv, dst, base, index, scale, offset);
|
m_formatter.oneByteOp(OP_MOV_GvEv, dst, base, index, scale, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !WTF_CPU_X86_64
|
|
||||||
void movl_mr(const void* addr, RegisterID dst)
|
void movl_mr(const void* addr, RegisterID dst)
|
||||||
{
|
{
|
||||||
spew("movl %p, %s",
|
spew("movl %p, %s",
|
||||||
@ -1584,7 +1630,6 @@ public:
|
|||||||
else
|
else
|
||||||
m_formatter.oneByteOp(OP_MOV_GvEv, dst, addr);
|
m_formatter.oneByteOp(OP_MOV_GvEv, dst, addr);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void movl_i32r(int imm, RegisterID dst)
|
void movl_i32r(int imm, RegisterID dst)
|
||||||
{
|
{
|
||||||
@ -1683,6 +1728,16 @@ public:
|
|||||||
m_formatter.oneByteOp64(OP_MOV_EvGv, src, base, index, scale, offset);
|
m_formatter.oneByteOp64(OP_MOV_EvGv, src, base, index, scale, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void movq_rm(RegisterID src, const void* addr)
|
||||||
|
{
|
||||||
|
spew("movq %s, %p",
|
||||||
|
nameIReg(8, src), addr);
|
||||||
|
if (src == X86Registers::eax)
|
||||||
|
movq_EAXm(addr);
|
||||||
|
else
|
||||||
|
m_formatter.oneByteOp64(OP_MOV_EvGv, src, addr);
|
||||||
|
}
|
||||||
|
|
||||||
void movq_mEAX(const void* addr)
|
void movq_mEAX(const void* addr)
|
||||||
{
|
{
|
||||||
FIXME_INSN_PRINTING;
|
FIXME_INSN_PRINTING;
|
||||||
@ -1717,6 +1772,16 @@ public:
|
|||||||
m_formatter.oneByteOp64(OP_MOV_GvEv, dst, base, index, scale, offset);
|
m_formatter.oneByteOp64(OP_MOV_GvEv, dst, base, index, scale, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void movq_mr(const void* addr, RegisterID dst)
|
||||||
|
{
|
||||||
|
spew("movq %p, %s",
|
||||||
|
addr, nameIReg(8, dst));
|
||||||
|
if (dst == X86Registers::eax)
|
||||||
|
movq_mEAX(addr);
|
||||||
|
else
|
||||||
|
m_formatter.oneByteOp64(OP_MOV_GvEv, dst, addr);
|
||||||
|
}
|
||||||
|
|
||||||
void leaq_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
|
void leaq_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
|
||||||
{
|
{
|
||||||
spew("leaq %d(%s,%s,%d), %s",
|
spew("leaq %d(%s,%s,%d), %s",
|
||||||
@ -1739,6 +1804,12 @@ public:
|
|||||||
m_formatter.oneByteOp64(OP_GROUP11_EvIz, GROUP11_MOV, base, index, scale, offset);
|
m_formatter.oneByteOp64(OP_GROUP11_EvIz, GROUP11_MOV, base, index, scale, offset);
|
||||||
m_formatter.immediate32(imm);
|
m_formatter.immediate32(imm);
|
||||||
}
|
}
|
||||||
|
void movq_i32m(int imm, const void* addr)
|
||||||
|
{
|
||||||
|
spew("movq %d, %p", imm, addr);
|
||||||
|
m_formatter.oneByteOp64(OP_GROUP11_EvIz, GROUP11_MOV, addr);
|
||||||
|
m_formatter.immediate32(imm);
|
||||||
|
}
|
||||||
|
|
||||||
// Note that this instruction sign-extends its 32-bit immediate field to 64
|
// Note that this instruction sign-extends its 32-bit immediate field to 64
|
||||||
// bits and loads the 64-bit value into a 64-bit register.
|
// bits and loads the 64-bit value into a 64-bit register.
|
||||||
@ -1791,7 +1862,7 @@ public:
|
|||||||
m_formatter.oneByteRipOp64(OP_MOV_GvEv, dst, 0);
|
m_formatter.oneByteRipOp64(OP_MOV_GvEv, dst, 0);
|
||||||
return JmpSrc(m_formatter.size());
|
return JmpSrc(m_formatter.size());
|
||||||
}
|
}
|
||||||
#else
|
#endif
|
||||||
void movl_rm(RegisterID src, const void* addr)
|
void movl_rm(RegisterID src, const void* addr)
|
||||||
{
|
{
|
||||||
spew("movl %s, %p",
|
spew("movl %s, %p",
|
||||||
@ -1804,11 +1875,10 @@ public:
|
|||||||
|
|
||||||
void movl_i32m(int imm, const void* addr)
|
void movl_i32m(int imm, const void* addr)
|
||||||
{
|
{
|
||||||
FIXME_INSN_PRINTING;
|
spew("movl %d, %p", imm, addr);
|
||||||
m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, addr);
|
m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, addr);
|
||||||
m_formatter.immediate32(imm);
|
m_formatter.immediate32(imm);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void movb_rm(RegisterID src, int offset, RegisterID base)
|
void movb_rm(RegisterID src, int offset, RegisterID base)
|
||||||
{
|
{
|
||||||
@ -2205,7 +2275,6 @@ public:
|
|||||||
m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, base, offset);
|
m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, base, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !WTF_CPU_X86_64
|
|
||||||
void addsd_mr(const void* address, XMMRegisterID dst)
|
void addsd_mr(const void* address, XMMRegisterID dst)
|
||||||
{
|
{
|
||||||
spew("addsd %p, %s",
|
spew("addsd %p, %s",
|
||||||
@ -2220,7 +2289,6 @@ public:
|
|||||||
m_formatter.prefix(PRE_SSE_F3);
|
m_formatter.prefix(PRE_SSE_F3);
|
||||||
m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, address);
|
m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, address);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void cvtss2sd_rr(XMMRegisterID src, XMMRegisterID dst)
|
void cvtss2sd_rr(XMMRegisterID src, XMMRegisterID dst)
|
||||||
{
|
{
|
||||||
@ -3144,6 +3212,26 @@ public:
|
|||||||
reinterpret_cast<const void**>(where)[-1] = value;
|
reinterpret_cast<const void**>(where)[-1] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test whether the given address will fit in an address immediate field.
|
||||||
|
// This is always true on x86, but on x64 it's only true for addreses
|
||||||
|
// which fit in the 32-bit immediate field.
|
||||||
|
static bool isAddressImmediate(const void *address) {
|
||||||
|
intptr_t value = reinterpret_cast<intptr_t>(address);
|
||||||
|
int32_t immediate = static_cast<int32_t>(value);
|
||||||
|
return value == immediate;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the given address to a 32-bit immediate field value. This is
|
||||||
|
// a no-op on x86, but on x64 it asserts that the address is actually
|
||||||
|
// a valid address immediate.
|
||||||
|
static int32_t addressImmediate(const void *address) {
|
||||||
|
#if WTF_CPU_X86_64
|
||||||
|
// x64's 64-bit addresses don't all fit in the 32-bit immediate.
|
||||||
|
ASSERT(isAddressImmediate(address));
|
||||||
|
#endif
|
||||||
|
return static_cast<int32_t>(reinterpret_cast<intptr_t>(address));
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static int32_t getInt32(void* where)
|
static int32_t getInt32(void* where)
|
||||||
@ -3237,14 +3325,13 @@ private:
|
|||||||
memoryModRM_disp32(reg, index, scale, offset);
|
memoryModRM_disp32(reg, index, scale, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !WTF_CPU_X86_64
|
|
||||||
void oneByteOp(OneByteOpcodeID opcode, int reg, const void* address)
|
void oneByteOp(OneByteOpcodeID opcode, int reg, const void* address)
|
||||||
{
|
{
|
||||||
m_buffer.ensureSpace(maxInstructionSize);
|
m_buffer.ensureSpace(maxInstructionSize);
|
||||||
m_buffer.putByteUnchecked(opcode);
|
m_buffer.putByteUnchecked(opcode);
|
||||||
memoryModRM(reg, address);
|
memoryModRM(reg, address);
|
||||||
}
|
}
|
||||||
#else
|
#if WTF_CPU_X86_64
|
||||||
void oneByteRipOp(OneByteOpcodeID opcode, int reg, int ripOffset)
|
void oneByteRipOp(OneByteOpcodeID opcode, int reg, int ripOffset)
|
||||||
{
|
{
|
||||||
m_buffer.ensureSpace(maxInstructionSize);
|
m_buffer.ensureSpace(maxInstructionSize);
|
||||||
@ -3317,7 +3404,6 @@ private:
|
|||||||
memoryModRM(reg, base, index, scale, offset);
|
memoryModRM(reg, base, index, scale, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !WTF_CPU_X86_64
|
|
||||||
void twoByteOp(TwoByteOpcodeID opcode, int reg, const void* address)
|
void twoByteOp(TwoByteOpcodeID opcode, int reg, const void* address)
|
||||||
{
|
{
|
||||||
m_buffer.ensureSpace(maxInstructionSize);
|
m_buffer.ensureSpace(maxInstructionSize);
|
||||||
@ -3325,7 +3411,6 @@ private:
|
|||||||
m_buffer.putByteUnchecked(opcode);
|
m_buffer.putByteUnchecked(opcode);
|
||||||
memoryModRM(reg, address);
|
memoryModRM(reg, address);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void threeByteOp(ThreeByteOpcodeID opcode, ThreeByteEscape escape, int reg, RegisterID rm)
|
void threeByteOp(ThreeByteOpcodeID opcode, ThreeByteEscape escape, int reg, RegisterID rm)
|
||||||
{
|
{
|
||||||
@ -3400,6 +3485,14 @@ private:
|
|||||||
memoryModRM(reg, base, index, scale, offset);
|
memoryModRM(reg, base, index, scale, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void oneByteOp64(OneByteOpcodeID opcode, int reg, const void* address)
|
||||||
|
{
|
||||||
|
m_buffer.ensureSpace(maxInstructionSize);
|
||||||
|
emitRexW(reg, 0, 0);
|
||||||
|
m_buffer.putByteUnchecked(opcode);
|
||||||
|
memoryModRM(reg, address);
|
||||||
|
}
|
||||||
|
|
||||||
void twoByteOp64(TwoByteOpcodeID opcode, int reg, RegisterID rm)
|
void twoByteOp64(TwoByteOpcodeID opcode, int reg, RegisterID rm)
|
||||||
{
|
{
|
||||||
m_buffer.ensureSpace(maxInstructionSize);
|
m_buffer.ensureSpace(maxInstructionSize);
|
||||||
@ -3766,14 +3859,19 @@ private:
|
|||||||
m_buffer.putIntUnchecked(offset);
|
m_buffer.putIntUnchecked(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !WTF_CPU_X86_64
|
|
||||||
void memoryModRM(int reg, const void* address)
|
void memoryModRM(int reg, const void* address)
|
||||||
{
|
{
|
||||||
|
int32_t disp = addressImmediate(address);
|
||||||
|
|
||||||
|
#if WTF_CPU_X86_64
|
||||||
|
// On x64-64, non-RIP-relative absolute mode requires a SIB.
|
||||||
|
putModRmSib(ModRmMemoryNoDisp, reg, noBase, noIndex, 0);
|
||||||
|
#else
|
||||||
// noBase + ModRmMemoryNoDisp means noBase + ModRmMemoryDisp32!
|
// noBase + ModRmMemoryNoDisp means noBase + ModRmMemoryDisp32!
|
||||||
putModRm(ModRmMemoryNoDisp, reg, noBase);
|
putModRm(ModRmMemoryNoDisp, reg, noBase);
|
||||||
m_buffer.putIntUnchecked(reinterpret_cast<int32_t>(address));
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
m_buffer.putIntUnchecked(disp);
|
||||||
|
}
|
||||||
|
|
||||||
AssemblerBuffer m_buffer;
|
AssemblerBuffer m_buffer;
|
||||||
} m_formatter;
|
} m_formatter;
|
||||||
|
@ -248,11 +248,9 @@ class AssemblerX86Shared
|
|||||||
case Operand::MEM_SCALE:
|
case Operand::MEM_SCALE:
|
||||||
masm.movl_mr(src.disp(), src.base(), src.index(), src.scale(), dest.code());
|
masm.movl_mr(src.disp(), src.base(), src.index(), src.scale(), dest.code());
|
||||||
break;
|
break;
|
||||||
#ifdef JS_CPU_X86
|
case Operand::MEM_ADDRESS32:
|
||||||
case Operand::MEM_ADDRESS:
|
|
||||||
masm.movl_mr(src.address(), dest.code());
|
masm.movl_mr(src.address(), dest.code());
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
default:
|
default:
|
||||||
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
||||||
}
|
}
|
||||||
@ -268,11 +266,9 @@ class AssemblerX86Shared
|
|||||||
case Operand::MEM_SCALE:
|
case Operand::MEM_SCALE:
|
||||||
masm.movl_rm(src.code(), dest.disp(), dest.base(), dest.index(), dest.scale());
|
masm.movl_rm(src.code(), dest.disp(), dest.base(), dest.index(), dest.scale());
|
||||||
break;
|
break;
|
||||||
#ifdef JS_CPU_X86
|
case Operand::MEM_ADDRESS32:
|
||||||
case Operand::MEM_ADDRESS:
|
|
||||||
masm.movl_rm(src.code(), dest.address());
|
masm.movl_rm(src.code(), dest.address());
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
default:
|
default:
|
||||||
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
||||||
}
|
}
|
||||||
@ -737,11 +733,9 @@ class AssemblerX86Shared
|
|||||||
case Operand::MEM_SCALE:
|
case Operand::MEM_SCALE:
|
||||||
masm.cmpl_im(imm.value, op.disp(), op.base(), op.index(), op.scale());
|
masm.cmpl_im(imm.value, op.disp(), op.base(), op.index(), op.scale());
|
||||||
break;
|
break;
|
||||||
#ifdef JS_CPU_X86
|
case Operand::MEM_ADDRESS32:
|
||||||
case Operand::MEM_ADDRESS:
|
|
||||||
masm.cmpl_im(imm.value, op.address());
|
masm.cmpl_im(imm.value, op.address());
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
default:
|
default:
|
||||||
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
||||||
}
|
}
|
||||||
@ -754,11 +748,9 @@ class AssemblerX86Shared
|
|||||||
case Operand::MEM_REG_DISP:
|
case Operand::MEM_REG_DISP:
|
||||||
masm.cmpl_rm(rhs.code(), lhs.disp(), lhs.base());
|
masm.cmpl_rm(rhs.code(), lhs.disp(), lhs.base());
|
||||||
break;
|
break;
|
||||||
#ifdef JS_CPU_X86
|
case Operand::MEM_ADDRESS32:
|
||||||
case Operand::MEM_ADDRESS:
|
|
||||||
masm.cmpl_rm(rhs.code(), lhs.address());
|
masm.cmpl_rm(rhs.code(), lhs.address());
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
default:
|
default:
|
||||||
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
||||||
}
|
}
|
||||||
@ -771,11 +763,9 @@ class AssemblerX86Shared
|
|||||||
case Operand::MEM_REG_DISP:
|
case Operand::MEM_REG_DISP:
|
||||||
masm.cmpl_im(imm.value, op.disp(), op.base());
|
masm.cmpl_im(imm.value, op.disp(), op.base());
|
||||||
break;
|
break;
|
||||||
#ifdef JS_CPU_X86
|
case Operand::MEM_ADDRESS32:
|
||||||
case Operand::MEM_ADDRESS:
|
|
||||||
masm.cmpl_im(imm.value, op.address());
|
masm.cmpl_im(imm.value, op.address());
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
default:
|
default:
|
||||||
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
||||||
}
|
}
|
||||||
@ -822,11 +812,9 @@ class AssemblerX86Shared
|
|||||||
case Operand::MEM_REG_DISP:
|
case Operand::MEM_REG_DISP:
|
||||||
masm.addl_im(imm.value, op.disp(), op.base());
|
masm.addl_im(imm.value, op.disp(), op.base());
|
||||||
break;
|
break;
|
||||||
#ifdef JS_CPU_X86
|
case Operand::MEM_ADDRESS32:
|
||||||
case Operand::MEM_ADDRESS:
|
|
||||||
masm.addl_im(imm.value, op.address());
|
masm.addl_im(imm.value, op.address());
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
default:
|
default:
|
||||||
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
||||||
}
|
}
|
||||||
@ -1227,11 +1215,9 @@ class AssemblerX86Shared
|
|||||||
case Operand::MEM_REG_DISP:
|
case Operand::MEM_REG_DISP:
|
||||||
masm.addsd_mr(src.disp(), src.base(), dest.code());
|
masm.addsd_mr(src.disp(), src.base(), dest.code());
|
||||||
break;
|
break;
|
||||||
#ifdef JS_CPU_X86
|
case Operand::MEM_ADDRESS32:
|
||||||
case Operand::MEM_ADDRESS:
|
|
||||||
masm.addsd_mr(src.address(), dest.code());
|
masm.addsd_mr(src.address(), dest.code());
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
default:
|
default:
|
||||||
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
||||||
}
|
}
|
||||||
@ -1245,11 +1231,9 @@ class AssemblerX86Shared
|
|||||||
case Operand::MEM_REG_DISP:
|
case Operand::MEM_REG_DISP:
|
||||||
masm.addss_mr(src.disp(), src.base(), dest.code());
|
masm.addss_mr(src.disp(), src.base(), dest.code());
|
||||||
break;
|
break;
|
||||||
#ifdef JS_CPU_X86
|
case Operand::MEM_ADDRESS32:
|
||||||
case Operand::MEM_ADDRESS:
|
|
||||||
masm.addss_mr(src.address(), dest.code());
|
masm.addss_mr(src.address(), dest.code());
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
default:
|
default:
|
||||||
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
||||||
}
|
}
|
||||||
|
@ -175,11 +175,12 @@ class Operand
|
|||||||
REG,
|
REG,
|
||||||
MEM_REG_DISP,
|
MEM_REG_DISP,
|
||||||
FPREG,
|
FPREG,
|
||||||
MEM_SCALE
|
MEM_SCALE,
|
||||||
|
MEM_ADDRESS32
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Kind kind_ : 3;
|
Kind kind_ : 4;
|
||||||
int32_t base_ : 5;
|
int32_t base_ : 5;
|
||||||
Scale scale_ : 3;
|
Scale scale_ : 3;
|
||||||
int32_t index_ : 5;
|
int32_t index_ : 5;
|
||||||
@ -218,6 +219,11 @@ class Operand
|
|||||||
base_(reg.code()),
|
base_(reg.code()),
|
||||||
disp_(disp)
|
disp_(disp)
|
||||||
{ }
|
{ }
|
||||||
|
explicit Operand(const AbsoluteAddress &address)
|
||||||
|
: kind_(MEM_ADDRESS32)
|
||||||
|
{
|
||||||
|
disp_ = JSC::X86Assembler::addressImmediate(address.addr);
|
||||||
|
}
|
||||||
|
|
||||||
Address toAddress() const {
|
Address toAddress() const {
|
||||||
JS_ASSERT(kind() == MEM_REG_DISP);
|
JS_ASSERT(kind() == MEM_REG_DISP);
|
||||||
@ -256,6 +262,10 @@ class Operand
|
|||||||
JS_ASSERT(kind() == MEM_REG_DISP || kind() == MEM_SCALE);
|
JS_ASSERT(kind() == MEM_REG_DISP || kind() == MEM_SCALE);
|
||||||
return disp_;
|
return disp_;
|
||||||
}
|
}
|
||||||
|
void *address() const {
|
||||||
|
JS_ASSERT(kind() == MEM_ADDRESS32);
|
||||||
|
return reinterpret_cast<void *>(intptr_t(disp_));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace jit
|
} // namespace jit
|
||||||
@ -410,6 +420,9 @@ class Assembler : public AssemblerX86Shared
|
|||||||
case Operand::MEM_SCALE:
|
case Operand::MEM_SCALE:
|
||||||
masm.movq_mr(src.disp(), src.base(), src.index(), src.scale(), dest.code());
|
masm.movq_mr(src.disp(), src.base(), src.index(), src.scale(), dest.code());
|
||||||
break;
|
break;
|
||||||
|
case Operand::MEM_ADDRESS32:
|
||||||
|
masm.movq_mr(src.address(), dest.code());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
||||||
}
|
}
|
||||||
@ -425,6 +438,9 @@ class Assembler : public AssemblerX86Shared
|
|||||||
case Operand::MEM_SCALE:
|
case Operand::MEM_SCALE:
|
||||||
masm.movq_rm(src.code(), dest.disp(), dest.base(), dest.index(), dest.scale());
|
masm.movq_rm(src.code(), dest.disp(), dest.base(), dest.index(), dest.scale());
|
||||||
break;
|
break;
|
||||||
|
case Operand::MEM_ADDRESS32:
|
||||||
|
masm.movq_rm(src.code(), dest.address());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
||||||
}
|
}
|
||||||
@ -440,6 +456,9 @@ class Assembler : public AssemblerX86Shared
|
|||||||
case Operand::MEM_SCALE:
|
case Operand::MEM_SCALE:
|
||||||
masm.movq_i32m(imm32.value, dest.disp(), dest.base(), dest.index(), dest.scale());
|
masm.movq_i32m(imm32.value, dest.disp(), dest.base(), dest.index(), dest.scale());
|
||||||
break;
|
break;
|
||||||
|
case Operand::MEM_ADDRESS32:
|
||||||
|
masm.movq_i32m(imm32.value, dest.address());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
||||||
}
|
}
|
||||||
@ -476,6 +495,9 @@ class Assembler : public AssemblerX86Shared
|
|||||||
case Operand::MEM_REG_DISP:
|
case Operand::MEM_REG_DISP:
|
||||||
masm.addq_im(imm.value, dest.disp(), dest.base());
|
masm.addq_im(imm.value, dest.disp(), dest.base());
|
||||||
break;
|
break;
|
||||||
|
case Operand::MEM_ADDRESS32:
|
||||||
|
masm.addq_im(imm.value, dest.address());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
||||||
}
|
}
|
||||||
@ -491,6 +513,9 @@ class Assembler : public AssemblerX86Shared
|
|||||||
case Operand::MEM_REG_DISP:
|
case Operand::MEM_REG_DISP:
|
||||||
masm.addq_mr(src.disp(), src.base(), dest.code());
|
masm.addq_mr(src.disp(), src.base(), dest.code());
|
||||||
break;
|
break;
|
||||||
|
case Operand::MEM_ADDRESS32:
|
||||||
|
masm.addq_mr(src.address(), dest.code());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
||||||
}
|
}
|
||||||
@ -510,6 +535,9 @@ class Assembler : public AssemblerX86Shared
|
|||||||
case Operand::MEM_REG_DISP:
|
case Operand::MEM_REG_DISP:
|
||||||
masm.subq_mr(src.disp(), src.base(), dest.code());
|
masm.subq_mr(src.disp(), src.base(), dest.code());
|
||||||
break;
|
break;
|
||||||
|
case Operand::MEM_ADDRESS32:
|
||||||
|
masm.subq_mr(src.address(), dest.code());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
||||||
}
|
}
|
||||||
@ -537,6 +565,9 @@ class Assembler : public AssemblerX86Shared
|
|||||||
case Operand::MEM_REG_DISP:
|
case Operand::MEM_REG_DISP:
|
||||||
masm.orq_mr(src.disp(), src.base(), dest.code());
|
masm.orq_mr(src.disp(), src.base(), dest.code());
|
||||||
break;
|
break;
|
||||||
|
case Operand::MEM_ADDRESS32:
|
||||||
|
masm.orq_mr(src.address(), dest.code());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
||||||
}
|
}
|
||||||
@ -622,6 +653,9 @@ class Assembler : public AssemblerX86Shared
|
|||||||
case Operand::MEM_REG_DISP:
|
case Operand::MEM_REG_DISP:
|
||||||
masm.cmpq_rm(rhs.code(), lhs.disp(), lhs.base());
|
masm.cmpq_rm(rhs.code(), lhs.disp(), lhs.base());
|
||||||
break;
|
break;
|
||||||
|
case Operand::MEM_ADDRESS32:
|
||||||
|
masm.cmpq_rm(rhs.code(), lhs.address());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
||||||
}
|
}
|
||||||
@ -634,6 +668,9 @@ class Assembler : public AssemblerX86Shared
|
|||||||
case Operand::MEM_REG_DISP:
|
case Operand::MEM_REG_DISP:
|
||||||
masm.cmpq_im(rhs.value, lhs.disp(), lhs.base());
|
masm.cmpq_im(rhs.value, lhs.disp(), lhs.base());
|
||||||
break;
|
break;
|
||||||
|
case Operand::MEM_ADDRESS32:
|
||||||
|
masm.cmpq_im(rhs.value, lhs.address());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
MOZ_ASSUME_UNREACHABLE("unexpected operand kind");
|
||||||
}
|
}
|
||||||
|
@ -509,20 +509,32 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
|
|||||||
}
|
}
|
||||||
|
|
||||||
void branch32(Condition cond, const AbsoluteAddress &lhs, Imm32 rhs, Label *label) {
|
void branch32(Condition cond, const AbsoluteAddress &lhs, Imm32 rhs, Label *label) {
|
||||||
|
if (JSC::X86Assembler::isAddressImmediate(lhs.addr)) {
|
||||||
|
branch32(cond, Operand(lhs), rhs, label);
|
||||||
|
} else {
|
||||||
mov(ImmPtr(lhs.addr), ScratchReg);
|
mov(ImmPtr(lhs.addr), ScratchReg);
|
||||||
branch32(cond, Address(ScratchReg, 0), rhs, label);
|
branch32(cond, Address(ScratchReg, 0), rhs, label);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
void branch32(Condition cond, const AbsoluteAddress &lhs, Register rhs, Label *label) {
|
void branch32(Condition cond, const AbsoluteAddress &lhs, Register rhs, Label *label) {
|
||||||
|
if (JSC::X86Assembler::isAddressImmediate(lhs.addr)) {
|
||||||
|
branch32(cond, Operand(lhs), rhs, label);
|
||||||
|
} else {
|
||||||
mov(ImmPtr(lhs.addr), ScratchReg);
|
mov(ImmPtr(lhs.addr), ScratchReg);
|
||||||
branch32(cond, Address(ScratchReg, 0), rhs, label);
|
branch32(cond, Address(ScratchReg, 0), rhs, label);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Specialization for AbsoluteAddress.
|
// Specialization for AbsoluteAddress.
|
||||||
void branchPtr(Condition cond, const AbsoluteAddress &addr, const Register &ptr, Label *label) {
|
void branchPtr(Condition cond, const AbsoluteAddress &addr, const Register &ptr, Label *label) {
|
||||||
JS_ASSERT(ptr != ScratchReg);
|
JS_ASSERT(ptr != ScratchReg);
|
||||||
|
if (JSC::X86Assembler::isAddressImmediate(addr.addr)) {
|
||||||
|
branchPtr(cond, Operand(addr), ptr, label);
|
||||||
|
} else {
|
||||||
mov(ImmPtr(addr.addr), ScratchReg);
|
mov(ImmPtr(addr.addr), ScratchReg);
|
||||||
branchPtr(cond, Operand(ScratchReg, 0x0), ptr, label);
|
branchPtr(cond, Operand(ScratchReg, 0x0), ptr, label);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void branchPrivatePtr(Condition cond, Address lhs, ImmPtr ptr, Label *label) {
|
void branchPrivatePtr(Condition cond, Address lhs, ImmPtr ptr, Label *label) {
|
||||||
branchPtr(cond, lhs, ImmWord(uintptr_t(ptr.value) >> 1), label);
|
branchPtr(cond, lhs, ImmWord(uintptr_t(ptr.value) >> 1), label);
|
||||||
@ -593,9 +605,13 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
|
|||||||
movq(imm, dest);
|
movq(imm, dest);
|
||||||
}
|
}
|
||||||
void loadPtr(const AbsoluteAddress &address, Register dest) {
|
void loadPtr(const AbsoluteAddress &address, Register dest) {
|
||||||
|
if (JSC::X86Assembler::isAddressImmediate(address.addr)) {
|
||||||
|
movq(Operand(address), dest);
|
||||||
|
} else {
|
||||||
mov(ImmPtr(address.addr), ScratchReg);
|
mov(ImmPtr(address.addr), ScratchReg);
|
||||||
movq(Operand(ScratchReg, 0x0), dest);
|
movq(Operand(ScratchReg, 0x0), dest);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
void loadPtr(const Address &address, Register dest) {
|
void loadPtr(const Address &address, Register dest) {
|
||||||
movq(Operand(address), dest);
|
movq(Operand(address), dest);
|
||||||
}
|
}
|
||||||
@ -631,9 +647,13 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
|
|||||||
movq(src, dest);
|
movq(src, dest);
|
||||||
}
|
}
|
||||||
void storePtr(const Register &src, const AbsoluteAddress &address) {
|
void storePtr(const Register &src, const AbsoluteAddress &address) {
|
||||||
|
if (JSC::X86Assembler::isAddressImmediate(address.addr)) {
|
||||||
|
movq(src, Operand(address));
|
||||||
|
} else {
|
||||||
mov(ImmPtr(address.addr), ScratchReg);
|
mov(ImmPtr(address.addr), ScratchReg);
|
||||||
movq(src, Operand(ScratchReg, 0x0));
|
movq(src, Operand(ScratchReg, 0x0));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
void rshiftPtr(Imm32 imm, Register dest) {
|
void rshiftPtr(Imm32 imm, Register dest) {
|
||||||
shrq(imm, dest);
|
shrq(imm, dest);
|
||||||
}
|
}
|
||||||
@ -1065,9 +1085,13 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
|
|||||||
}
|
}
|
||||||
|
|
||||||
void inc64(AbsoluteAddress dest) {
|
void inc64(AbsoluteAddress dest) {
|
||||||
|
if (JSC::X86Assembler::isAddressImmediate(dest.addr)) {
|
||||||
|
addPtr(Imm32(1), Operand(dest));
|
||||||
|
} else {
|
||||||
mov(ImmPtr(dest.addr), ScratchReg);
|
mov(ImmPtr(dest.addr), ScratchReg);
|
||||||
addPtr(Imm32(1), Address(ScratchReg, 0));
|
addPtr(Imm32(1), Address(ScratchReg, 0));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If source is a double, load it into dest. If source is int32,
|
// If source is a double, load it into dest. If source is int32,
|
||||||
// convert it to double. Else, branch to failure.
|
// convert it to double. Else, branch to failure.
|
||||||
|
@ -116,7 +116,7 @@ class Operand
|
|||||||
MEM_REG_DISP,
|
MEM_REG_DISP,
|
||||||
FPREG,
|
FPREG,
|
||||||
MEM_SCALE,
|
MEM_SCALE,
|
||||||
MEM_ADDRESS
|
MEM_ADDRESS32
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -160,11 +160,11 @@ class Operand
|
|||||||
disp_(disp)
|
disp_(disp)
|
||||||
{ }
|
{ }
|
||||||
explicit Operand(const AbsoluteAddress &address)
|
explicit Operand(const AbsoluteAddress &address)
|
||||||
: kind_(MEM_ADDRESS),
|
: kind_(MEM_ADDRESS32),
|
||||||
disp_(reinterpret_cast<int32_t>(address.addr))
|
disp_(reinterpret_cast<int32_t>(address.addr))
|
||||||
{ }
|
{ }
|
||||||
explicit Operand(const void *address)
|
explicit Operand(const void *address)
|
||||||
: kind_(MEM_ADDRESS),
|
: kind_(MEM_ADDRESS32),
|
||||||
disp_(reinterpret_cast<int32_t>(address))
|
disp_(reinterpret_cast<int32_t>(address))
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
@ -206,7 +206,7 @@ class Operand
|
|||||||
return disp_;
|
return disp_;
|
||||||
}
|
}
|
||||||
void *address() const {
|
void *address() const {
|
||||||
JS_ASSERT(kind() == MEM_ADDRESS);
|
JS_ASSERT(kind() == MEM_ADDRESS32);
|
||||||
return reinterpret_cast<void *>(disp_);
|
return reinterpret_cast<void *>(disp_);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -386,7 +386,7 @@ class Assembler : public AssemblerX86Shared
|
|||||||
masm.cmpl_im_force32(imm.value, op.disp(), op.base());
|
masm.cmpl_im_force32(imm.value, op.disp(), op.base());
|
||||||
writeDataRelocation(imm);
|
writeDataRelocation(imm);
|
||||||
break;
|
break;
|
||||||
case Operand::MEM_ADDRESS:
|
case Operand::MEM_ADDRESS32:
|
||||||
masm.cmpl_im(imm.value, op.address());
|
masm.cmpl_im(imm.value, op.address());
|
||||||
writeDataRelocation(imm);
|
writeDataRelocation(imm);
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user