Chromium Code Reviews| Index: src/IceAssemblerX86Base.h |
| diff --git a/src/IceAssemblerX86Base.h b/src/IceAssemblerX86Base.h |
| index 1db270ab20af84ff7d7f07670930fb124b280e37..36de87a324b511af47d2a802aa7887cefc39c99a 100644 |
| --- a/src/IceAssemblerX86Base.h |
| +++ b/src/IceAssemblerX86Base.h |
| @@ -314,7 +314,7 @@ public: |
| */ |
| void call(typename Traits::GPRRegister reg); |
| void call(const typename Traits::Address &address); |
| - void call(const ConstantRelocatable *label); |
| + void call(const ConstantRelocatable *label); // not testable. |
| void call(const Immediate &abs_address); |
| static const intptr_t kCallExternalLabelSize = 5; |
| @@ -324,7 +324,11 @@ public: |
| void popl(typename Traits::GPRRegister reg); |
| void popl(const typename Traits::Address &address); |
| + template <typename T = Traits, |
| + typename = typename std::enable_if<T::HasPusha>::type> |
| void pushal(); |
| + template <typename T = Traits, |
| + typename = typename std::enable_if<T::HasPopa>::type> |
| void popal(); |
| void setcc(typename Traits::Cond::BrCond condition, |
| @@ -332,7 +336,6 @@ public: |
| void setcc(typename Traits::Cond::BrCond condition, |
| const typename Traits::Address &address); |
| - // All mov() overloads are tested. |
| void mov(Type Ty, typename Traits::GPRRegister dst, const Immediate &src); |
| void mov(Type Ty, typename Traits::GPRRegister dst, |
| typename Traits::GPRRegister src); |
| @@ -342,6 +345,8 @@ public: |
| typename Traits::GPRRegister src); |
| void mov(Type Ty, const typename Traits::Address &dst, const Immediate &imm); |
| + void movFromAh(const typename Traits::GPRRegister dst); |
| + |
| void movzx(Type Ty, typename Traits::GPRRegister dst, |
| typename Traits::GPRRegister src); |
| void movzx(Type Ty, typename Traits::GPRRegister dst, |
| @@ -503,6 +508,7 @@ public: |
| void sqrtps(typename Traits::XmmRegister dst); |
| void rsqrtps(typename Traits::XmmRegister dst); |
| void reciprocalps(typename Traits::XmmRegister dst); |
| + |
| void movhlps(typename Traits::XmmRegister dst, |
| typename Traits::XmmRegister src); |
| void movlhps(typename Traits::XmmRegister dst, |
| @@ -518,14 +524,13 @@ public: |
| void set1ps(typename Traits::XmmRegister dst, |
| typename Traits::GPRRegister tmp, const Immediate &imm); |
| - void shufps(typename Traits::XmmRegister dst, |
| - typename Traits::XmmRegister src, const Immediate &mask); |
| void minpd(typename Traits::XmmRegister dst, |
| typename Traits::XmmRegister src); |
| void maxpd(typename Traits::XmmRegister dst, |
| typename Traits::XmmRegister src); |
| void sqrtpd(typename Traits::XmmRegister dst); |
| + |
| void shufpd(typename Traits::XmmRegister dst, |
| typename Traits::XmmRegister src, const Immediate &mask); |
| @@ -533,6 +538,8 @@ public: |
| typename Traits::XmmRegister src, const Immediate &mask); |
| void pshufd(Type Ty, typename Traits::XmmRegister dst, |
| const typename Traits::Address &src, const Immediate &mask); |
| + void shufps(typename Traits::XmmRegister dst, |
| + typename Traits::XmmRegister src, const Immediate &mask); |
| void shufps(Type Ty, typename Traits::XmmRegister dst, |
| typename Traits::XmmRegister src, const Immediate &mask); |
| void shufps(Type Ty, typename Traits::XmmRegister dst, |
| @@ -606,6 +613,7 @@ public: |
| void pextr(Type Ty, typename Traits::GPRRegister dst, |
| typename Traits::XmmRegister src, const Immediate &imm); |
| + // The following overload is not implemented. |
| void pextr(Type Ty, typename Traits::GPRRegister dst, |
| const typename Traits::Address &src, const Immediate &imm); |
| @@ -630,19 +638,49 @@ public: |
| void roundsd(typename Traits::XmmRegister dst, |
| typename Traits::XmmRegister src, RoundingMode mode); |
| - void fld(Type Ty, const typename Traits::Address &src); |
| - void fstp(Type Ty, const typename Traits::Address &dst); |
| - void fstp(typename Traits::X87STRegister st); |
| - |
| - void fnstcw(const typename Traits::Address &dst); |
| - void fldcw(const typename Traits::Address &src); |
| - |
| - void fistpl(const typename Traits::Address &dst); |
| - void fistps(const typename Traits::Address &dst); |
| - void fildl(const typename Traits::Address &src); |
| - void filds(const typename Traits::Address &src); |
| - |
| + //---------------------------------------------------------------------------- |
| + // |
| + // Begin: X87 instructions. Only available when Traits::UsesX87. |
| + // |
| + //---------------------------------------------------------------------------- |
| + template <typename T = Traits, |
| + typename = typename std::enable_if<T::UsesX87>::type> |
| + void fld(Type Ty, const typename T::Address &src); |
| + template <typename T = Traits, |
| + typename = typename std::enable_if<T::UsesX87>::type> |
| + void fstp(Type Ty, const typename T::Address &dst); |
| + template <typename T = Traits, |
| + typename = typename std::enable_if<T::UsesX87>::type> |
| + void fstp(typename T::X87STRegister st); |
| + |
| + template <typename T = Traits, |
| + typename = typename std::enable_if<T::UsesX87>::type> |
| + void fnstcw(const typename T::Address &dst); |
| + template <typename T = Traits, |
| + typename = typename std::enable_if<T::UsesX87>::type> |
| + void fldcw(const typename T::Address &src); |
| + |
| + template <typename T = Traits, |
| + typename = typename std::enable_if<T::UsesX87>::type> |
| + void fistpl(const typename T::Address &dst); |
| + template <typename T = Traits, |
| + typename = typename std::enable_if<T::UsesX87>::type> |
| + void fistps(const typename T::Address &dst); |
| + template <typename T = Traits, |
| + typename = typename std::enable_if<T::UsesX87>::type> |
| + void fildl(const typename T::Address &src); |
| + template <typename T = Traits, |
| + typename = typename std::enable_if<T::UsesX87>::type> |
| + void filds(const typename T::Address &src); |
| + |
| + template <typename T = Traits, |
| + typename = typename std::enable_if<T::UsesX87>::type> |
| void fincstp(); |
| + //---------------------------------------------------------------------------- |
| + // |
| + // End: X87 instructions. |
| + // |
| + //---------------------------------------------------------------------------- |
| void cmp(Type Ty, typename Traits::GPRRegister reg0, |
| typename Traits::GPRRegister reg1); |
| @@ -754,9 +792,13 @@ public: |
| void mul(Type Ty, typename Traits::GPRRegister reg); |
| void mul(Type Ty, const typename Traits::Address &address); |
| + template <class T = Traits, |
| + typename = typename std::enable_if<!T::Is64Bit>::type> |
| void incl(typename Traits::GPRRegister reg); |
| void incl(const typename Traits::Address &address); |
| + template <class T = Traits, |
| + typename = typename std::enable_if<!T::Is64Bit>::type> |
| void decl(typename Traits::GPRRegister reg); |
| void decl(const typename Traits::Address &address); |
| @@ -825,16 +867,14 @@ public: |
| void ud2(); |
| // j(Label) is fully tested. |
| - // j(ConstantRelocatable) is not tested as the test can not easily create such |
| - // an argument. |
| void j(typename Traits::Cond::BrCond condition, Label *label, |
| bool near = kFarJump); |
| void j(typename Traits::Cond::BrCond condition, |
| - const ConstantRelocatable *label); |
| + const ConstantRelocatable *label); // not testable. |
| void jmp(typename Traits::GPRRegister reg); |
| void jmp(Label *label, bool near = kFarJump); |
| - void jmp(const ConstantRelocatable *label); |
| + void jmp(const ConstantRelocatable *label); // not testable. |
| void mfence(); |
| @@ -855,12 +895,15 @@ public: |
| intptr_t CodeSize() const { return Buffer.size(); } |
| -private: |
| +protected: |
| inline void emitUint8(uint8_t value); |
| + |
| +private: |
| inline void emitInt16(int16_t value); |
| inline void emitInt32(int32_t value); |
| inline void emitRegisterOperand(int rm, int reg); |
| - inline void emitXmmRegisterOperand(int rm, typename Traits::XmmRegister reg); |
| + template <typename RegType, typename RmType> |
| + inline void emitXmmRegisterOperand(RegType reg, RmType rm); |
| inline void emitFixup(AssemblerFixup *fixup); |
| inline void emitOperandSizeOverride(); |
| @@ -910,6 +953,76 @@ private: |
| template <uint32_t Tag> |
| void arith_int(Type Ty, const typename Traits::Address &address, |
| const Immediate &imm); |
| + |
| + // gprEncoding returns Reg encoding for operand emission. For x86-64 we mask |
| + // out the 4th bit as it is encoded in the REX.[RXB] bits. No other bits are |
| + // touched because we don't want to mask errors. |
| + template <typename RegType, typename T = Traits> |
| + typename std::enable_if<T::Is64Bit, typename T::GPRRegister>::type |
| + gprEncoding(const RegType Reg) { |
| + static_assert( |
| + &AssemblerX86Base<Machine>::gprEncoding<RegType> != |
| + &T::Assembler::template gprEncoding<RegType>, |
| + "You need to define the gprEncoding() template in your assembler."); |
| + return static_cast<typename T::Assembler *>(this)->gprEncoding(Reg); |
| + } |
| + |
| + template <typename RegType, typename T = Traits> |
| + typename std::enable_if<!T::Is64Bit, typename T::GPRRegister>::type |
| + gprEncoding(const RegType Reg) { |
| + return static_cast<typename T::GPRRegister>(Reg); |
| + } |
| + |
| + // emitRex is used for emitting a Rex prefix for an address and a GPR. The |
|
Jim Stichnoth
2015/07/26 15:31:11
Did you swap the description of emitRex and emitRe
John
2015/07/27 20:35:58
Yes I did. Done.
On a related note, I changed thi
|
| + // address may contain zero, one, or two registers. |
| + template <typename RegType, typename RmType, typename T = Traits> |
| + typename std::enable_if<T::Is64Bit, void>::type |
| + emitRexRB(const Type Ty, const RegType Reg, const RmType Rm) { |
| + static_assert( |
| + &AssemblerX86Base<Machine>::emitRexRB<RegType, RmType> != |
| + &T::Assembler::template emitRexRB<RegType, RmType>, |
| + "You need to define the emitRexRB() template in your assembler."); |
| + static_cast<typename T::Assembler *>(this)->emitRexRB(Ty, Reg, Rm); |
| + } |
| + |
| + template <typename RegType, typename RmType, typename T = Traits> |
| + typename std::enable_if<!T::Is64Bit, void>::type |
| + emitRexRB(const Type, const RegType, const RmType) {} |
| + |
| + // emitRexB is used for emitting a Rex prefix if one is needed on encoding the |
| + // Reg field in an x86 instruction. It is invoked by the template when Reg is |
| + // the single register operand in the instruction (e.g., push Reg.) |
| + template <typename RmType, typename T = Traits> |
| + typename std::enable_if<T::Is64Bit, void>::type emitRexB(const Type Ty, |
| + const RmType Rm) { |
| + static_assert( |
| + &AssemblerX86Base<Machine>::emitRexB<RmType> != |
| + &T::Assembler::template emitRexB<RmType>, |
| + "You need to define the emitRexB() template in your assembler."); |
| + static_cast<typename T::Assembler *>(this)->emitRexB(Ty, Rm); |
| + } |
| + |
| + template <typename RmType, typename T = Traits> |
| + typename std::enable_if<!T::Is64Bit, void>::type emitRexB(const Type, |
| + const RmType) {} |
| + |
| + // emitRexRB is used for emitting a Rex prefix instructions with two explicit |
| + // register operands in its mod-rm byte. |
| + template <typename RegType, typename T = Traits> |
| + typename std::enable_if<T::Is64Bit, void>::type |
| + emitRex(const Type Ty, const typename Traits::Address &Addr, |
| + const RegType Reg) { |
| + static_assert( |
| + &AssemblerX86Base<Machine>::emitRex<RegType> != |
| + &T::Assembler::template emitRex<RegType>, |
| + "You need to define the emitRex() template in your assembler."); |
| + static_cast<typename T::Assembler *>(this) |
| + ->emitRex(Ty, Addr, static_cast<typename Traits::GPRRegister>(Reg)); |
| + } |
| + |
| + template <typename RegType, typename T = Traits> |
| + typename std::enable_if<!T::Is64Bit, void>::type |
| + emitRex(const Type, const typename Traits::Address &, const RegType) {} |
| }; |
| template <class Machine> |
| @@ -928,15 +1041,17 @@ inline void AssemblerX86Base<Machine>::emitInt32(int32_t value) { |
| } |
| template <class Machine> |
| -inline void AssemblerX86Base<Machine>::emitRegisterOperand(int rm, int reg) { |
| +inline void AssemblerX86Base<Machine>::emitRegisterOperand(int reg, int rm) { |
| + assert(reg >= 0 && reg < 8); |
| assert(rm >= 0 && rm < 8); |
| - Buffer.emit<uint8_t>(0xC0 + (rm << 3) + reg); |
| + Buffer.emit<uint8_t>(0xC0 + (reg << 3) + rm); |
| } |
| template <class Machine> |
| -inline void AssemblerX86Base<Machine>::emitXmmRegisterOperand( |
| - int rm, typename Traits::XmmRegister reg) { |
| - emitRegisterOperand(rm, static_cast<typename Traits::GPRRegister>(reg)); |
| +template <typename RegType, typename RmType> |
| +inline void AssemblerX86Base<Machine>::emitXmmRegisterOperand(RegType reg, |
| + RmType rm) { |
| + emitRegisterOperand(gprEncoding(reg), gprEncoding(rm)); |
| } |
| template <class Machine> |