Bug 915833 - SpiderMonkey: Add support for immediate addresses on x64. r=sstangl

This commit is contained in:
Dan Gohman 2013-09-12 15:31:44 -07:00
parent 2f0a25f9b6
commit f679cd4daa
5 changed files with 209 additions and 66 deletions

View File

@ -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;

View File

@ -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");
} }

View File

@ -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");
} }

View File

@ -509,19 +509,31 @@ 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) {
mov(ImmPtr(lhs.addr), ScratchReg); if (JSC::X86Assembler::isAddressImmediate(lhs.addr)) {
branch32(cond, Address(ScratchReg, 0), rhs, label); branch32(cond, Operand(lhs), rhs, label);
} else {
mov(ImmPtr(lhs.addr), ScratchReg);
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) {
mov(ImmPtr(lhs.addr), ScratchReg); if (JSC::X86Assembler::isAddressImmediate(lhs.addr)) {
branch32(cond, Address(ScratchReg, 0), rhs, label); branch32(cond, Operand(lhs), rhs, label);
} else {
mov(ImmPtr(lhs.addr), ScratchReg);
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);
mov(ImmPtr(addr.addr), ScratchReg); if (JSC::X86Assembler::isAddressImmediate(addr.addr)) {
branchPtr(cond, Operand(ScratchReg, 0x0), ptr, label); branchPtr(cond, Operand(addr), ptr, label);
} else {
mov(ImmPtr(addr.addr), ScratchReg);
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) {
@ -593,8 +605,12 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
movq(imm, dest); movq(imm, dest);
} }
void loadPtr(const AbsoluteAddress &address, Register dest) { void loadPtr(const AbsoluteAddress &address, Register dest) {
mov(ImmPtr(address.addr), ScratchReg); if (JSC::X86Assembler::isAddressImmediate(address.addr)) {
movq(Operand(ScratchReg, 0x0), dest); movq(Operand(address), dest);
} else {
mov(ImmPtr(address.addr), ScratchReg);
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,8 +647,12 @@ 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) {
mov(ImmPtr(address.addr), ScratchReg); if (JSC::X86Assembler::isAddressImmediate(address.addr)) {
movq(src, Operand(ScratchReg, 0x0)); movq(src, Operand(address));
} else {
mov(ImmPtr(address.addr), ScratchReg);
movq(src, Operand(ScratchReg, 0x0));
}
} }
void rshiftPtr(Imm32 imm, Register dest) { void rshiftPtr(Imm32 imm, Register dest) {
shrq(imm, dest); shrq(imm, dest);
@ -1065,8 +1085,12 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
} }
void inc64(AbsoluteAddress dest) { void inc64(AbsoluteAddress dest) {
mov(ImmPtr(dest.addr), ScratchReg); if (JSC::X86Assembler::isAddressImmediate(dest.addr)) {
addPtr(Imm32(1), Address(ScratchReg, 0)); addPtr(Imm32(1), Operand(dest));
} else {
mov(ImmPtr(dest.addr), ScratchReg);
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,

View File

@ -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;