LCOV - code coverage report
Current view: top level - js/src/jit/x86-shared - Assembler-x86-shared.h (source / functions) Hit Total Coverage
Test: output.info Lines: 428 2260 18.9 %
Date: 2017-07-14 16:53:18 Functions: 109 416 26.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef jit_x86_shared_Assembler_x86_shared_h
       8             : #define jit_x86_shared_Assembler_x86_shared_h
       9             : 
      10             : #include <cstddef>
      11             : 
      12             : #include "jit/shared/Assembler-shared.h"
      13             : 
      14             : #if defined(JS_CODEGEN_X86)
      15             : # include "jit/x86/BaseAssembler-x86.h"
      16             : #elif defined(JS_CODEGEN_X64)
      17             : # include "jit/x64/BaseAssembler-x64.h"
      18             : #else
      19             : # error "Unknown architecture!"
      20             : #endif
      21             : 
      22             : namespace js {
      23             : namespace jit {
      24             : 
      25           0 : struct ScratchFloat32Scope : public AutoFloatRegisterScope
      26             : {
      27           0 :     explicit ScratchFloat32Scope(MacroAssembler& masm)
      28           0 :       : AutoFloatRegisterScope(masm, ScratchFloat32Reg)
      29           0 :     { }
      30             : };
      31             : 
      32          28 : struct ScratchDoubleScope : public AutoFloatRegisterScope
      33             : {
      34          28 :     explicit ScratchDoubleScope(MacroAssembler& masm)
      35          28 :       : AutoFloatRegisterScope(masm, ScratchDoubleReg)
      36          28 :     { }
      37             : };
      38             : 
      39           0 : struct ScratchSimd128Scope : public AutoFloatRegisterScope
      40             : {
      41           0 :     explicit ScratchSimd128Scope(MacroAssembler& masm)
      42           0 :       : AutoFloatRegisterScope(masm, ScratchSimd128Reg)
      43           0 :     { }
      44             : };
      45             : 
      46             : class Operand
      47             : {
      48             :   public:
      49             :     enum Kind {
      50             :         REG,
      51             :         MEM_REG_DISP,
      52             :         FPREG,
      53             :         MEM_SCALE,
      54             :         MEM_ADDRESS32
      55             :     };
      56             : 
      57             :   private:
      58             :     Kind kind_ : 4;
      59             :     // Used as a Register::Encoding and a FloatRegister::Encoding.
      60             :     uint32_t base_ : 5;
      61             :     Scale scale_ : 3;
      62             :     // We don't use all 8 bits, of course, but GCC complains if the size of
      63             :     // this field is smaller than the size of Register::Encoding.
      64             :     Register::Encoding index_ : 8;
      65             :     int32_t disp_;
      66             : 
      67             :   public:
      68       19031 :     explicit Operand(Register reg)
      69       19031 :       : kind_(REG),
      70       19031 :         base_(reg.encoding()),
      71             :         scale_(TimesOne),
      72             :         index_(Registers::Invalid),
      73       38062 :         disp_(0)
      74       19031 :     { }
      75           0 :     explicit Operand(FloatRegister reg)
      76           0 :       : kind_(FPREG),
      77           0 :         base_(reg.encoding()),
      78             :         scale_(TimesOne),
      79             :         index_(Registers::Invalid),
      80           0 :         disp_(0)
      81           0 :     { }
      82      427731 :     explicit Operand(const Address& address)
      83      427731 :       : kind_(MEM_REG_DISP),
      84      427731 :         base_(address.base.encoding()),
      85             :         scale_(TimesOne),
      86             :         index_(Registers::Invalid),
      87      855465 :         disp_(address.offset)
      88      427734 :     { }
      89        1166 :     explicit Operand(const BaseIndex& address)
      90        1166 :       : kind_(MEM_SCALE),
      91        1166 :         base_(address.base.encoding()),
      92        1166 :         scale_(address.scale),
      93        1166 :         index_(address.index.encoding()),
      94        4664 :         disp_(address.offset)
      95        1166 :     { }
      96          28 :     Operand(Register base, Register index, Scale scale, int32_t disp = 0)
      97          28 :       : kind_(MEM_SCALE),
      98          28 :         base_(base.encoding()),
      99             :         scale_(scale),
     100          28 :         index_(index.encoding()),
     101          84 :         disp_(disp)
     102          28 :     { }
     103       24427 :     Operand(Register reg, int32_t disp)
     104       24427 :       : kind_(MEM_REG_DISP),
     105       24427 :         base_(reg.encoding()),
     106             :         scale_(TimesOne),
     107             :         index_(Registers::Invalid),
     108       48854 :         disp_(disp)
     109       24427 :     { }
     110           0 :     explicit Operand(AbsoluteAddress address)
     111           0 :       : kind_(MEM_ADDRESS32),
     112             :         base_(Registers::Invalid),
     113             :         scale_(TimesOne),
     114             :         index_(Registers::Invalid),
     115           0 :         disp_(X86Encoding::AddressImmediate(address.addr))
     116           0 :     { }
     117             :     explicit Operand(PatchedAbsoluteAddress address)
     118             :       : kind_(MEM_ADDRESS32),
     119             :         base_(Registers::Invalid),
     120             :         scale_(TimesOne),
     121             :         index_(Registers::Invalid),
     122             :         disp_(X86Encoding::AddressImmediate(address.addr))
     123             :     { }
     124             : 
     125           0 :     Address toAddress() const {
     126           0 :         MOZ_ASSERT(kind() == MEM_REG_DISP);
     127           0 :         return Address(Register::FromCode(base()), disp());
     128             :     }
     129             : 
     130           0 :     BaseIndex toBaseIndex() const {
     131           0 :         MOZ_ASSERT(kind() == MEM_SCALE);
     132           0 :         return BaseIndex(Register::FromCode(base()), Register::FromCode(index()), scale(), disp());
     133             :     }
     134             : 
     135     1404363 :     Kind kind() const {
     136     1404363 :         return kind_;
     137             :     }
     138       19165 :     Register::Encoding reg() const {
     139       19165 :         MOZ_ASSERT(kind() == REG);
     140       19165 :         return Register::Encoding(base_);
     141             :     }
     142      453885 :     Register::Encoding base() const {
     143      453885 :         MOZ_ASSERT(kind() == MEM_REG_DISP || kind() == MEM_SCALE);
     144      453872 :         return Register::Encoding(base_);
     145             :     }
     146        1195 :     Register::Encoding index() const {
     147        1195 :         MOZ_ASSERT(kind() == MEM_SCALE);
     148        1195 :         return index_;
     149             :     }
     150        1194 :     Scale scale() const {
     151        1194 :         MOZ_ASSERT(kind() == MEM_SCALE);
     152        1194 :         return scale_;
     153             :     }
     154           0 :     FloatRegister::Encoding fpu() const {
     155           0 :         MOZ_ASSERT(kind() == FPREG);
     156           0 :         return FloatRegister::Encoding(base_);
     157             :     }
     158      453369 :     int32_t disp() const {
     159      453369 :         MOZ_ASSERT(kind() == MEM_REG_DISP || kind() == MEM_SCALE);
     160      453355 :         return disp_;
     161             :     }
     162           0 :     void* address() const {
     163           0 :         MOZ_ASSERT(kind() == MEM_ADDRESS32);
     164           0 :         return reinterpret_cast<void*>(disp_);
     165             :     }
     166             : 
     167         665 :     bool containsReg(Register r) const {
     168         665 :         switch (kind()) {
     169         155 :           case REG:          return r.encoding() == reg();
     170         507 :           case MEM_REG_DISP: return r.encoding() == base();
     171           3 :           case MEM_SCALE:    return r.encoding() == base() || r.encoding() == index();
     172           0 :           default:           return false;
     173             :         }
     174             :     }
     175             : };
     176             : 
     177             : inline Imm32
     178             : Imm64::firstHalf() const
     179             : {
     180             :     return low();
     181             : }
     182             : 
     183             : inline Imm32
     184             : Imm64::secondHalf() const
     185             : {
     186             :     return hi();
     187             : }
     188             : 
     189             : class CPUInfo
     190             : {
     191             :   public:
     192             :     // As the SSE's were introduced in order, the presence of a later SSE implies
     193             :     // the presence of an earlier SSE. For example, SSE4_2 support implies SSE2 support.
     194             :     enum SSEVersion {
     195             :         UnknownSSE = 0,
     196             :         NoSSE = 1,
     197             :         SSE = 2,
     198             :         SSE2 = 3,
     199             :         SSE3 = 4,
     200             :         SSSE3 = 5,
     201             :         SSE4_1 = 6,
     202             :         SSE4_2 = 7
     203             :     };
     204             : 
     205           0 :     static SSEVersion GetSSEVersion() {
     206           0 :         if (maxSSEVersion == UnknownSSE)
     207           0 :             SetSSEVersion();
     208             : 
     209           0 :         MOZ_ASSERT(maxSSEVersion != UnknownSSE);
     210           0 :         MOZ_ASSERT_IF(maxEnabledSSEVersion != UnknownSSE, maxSSEVersion <= maxEnabledSSEVersion);
     211           0 :         return maxSSEVersion;
     212             :     }
     213             : 
     214        4503 :     static bool IsAVXPresent() {
     215        4503 :         if (MOZ_UNLIKELY(maxSSEVersion == UnknownSSE))
     216           3 :             SetSSEVersion();
     217             : 
     218        4503 :         MOZ_ASSERT_IF(!avxEnabled, !avxPresent);
     219        4503 :         return avxPresent;
     220             :     }
     221             : 
     222             :   private:
     223             :     static SSEVersion maxSSEVersion;
     224             :     static SSEVersion maxEnabledSSEVersion;
     225             :     static bool avxPresent;
     226             :     static bool avxEnabled;
     227             :     static bool popcntPresent;
     228             :     static bool needAmdBugWorkaround;
     229             : 
     230             :     static void SetSSEVersion();
     231             : 
     232             :   public:
     233      355998 :     static bool IsSSE2Present() {
     234             : #ifdef JS_CODEGEN_X64
     235      355998 :         return true;
     236             : #else
     237             :         return GetSSEVersion() >= SSE2;
     238             : #endif
     239             :     }
     240           0 :     static bool IsSSE3Present()  { return GetSSEVersion() >= SSE3; }
     241           0 :     static bool IsSSSE3Present() { return GetSSEVersion() >= SSSE3; }
     242           0 :     static bool IsSSE41Present() { return GetSSEVersion() >= SSE4_1; }
     243             :     static bool IsSSE42Present() { return GetSSEVersion() >= SSE4_2; }
     244           0 :     static bool IsPOPCNTPresent() { return popcntPresent; }
     245         375 :     static bool NeedAmdBugWorkaround() { return needAmdBugWorkaround; }
     246             : 
     247             :     static void SetSSE3Disabled() { maxEnabledSSEVersion = SSE2; avxEnabled = false; }
     248             :     static void SetSSE4Disabled() { maxEnabledSSEVersion = SSSE3; avxEnabled = false; }
     249             :     static void SetAVXEnabled() { avxEnabled = true; }
     250             : };
     251             : 
     252        4503 : class AssemblerX86Shared : public AssemblerShared
     253             : {
     254             :   protected:
     255             :     struct RelativePatch {
     256             :         int32_t offset;
     257             :         void* target;
     258             :         Relocation::Kind kind;
     259             : 
     260       19650 :         RelativePatch(int32_t offset, void* target, Relocation::Kind kind)
     261       19650 :           : offset(offset),
     262             :             target(target),
     263       19650 :             kind(kind)
     264       19650 :         { }
     265             :     };
     266             : 
     267             :     Vector<RelativePatch, 8, SystemAllocPolicy> jumps_;
     268             :     CompactBufferWriter jumpRelocations_;
     269             :     CompactBufferWriter dataRelocations_;
     270             : 
     271        4213 :     void writeDataRelocation(ImmGCPtr ptr) {
     272        4213 :         if (ptr.value) {
     273        4213 :             if (gc::IsInsideNursery(ptr.value))
     274           0 :                 embedsNurseryPointers_ = true;
     275        4213 :             dataRelocations_.writeUnsigned(masm.currentOffset());
     276             :         }
     277        4213 :     }
     278             : 
     279             :   protected:
     280             :     X86Encoding::BaseAssemblerSpecific masm;
     281             : 
     282             :     typedef X86Encoding::JmpSrc JmpSrc;
     283             :     typedef X86Encoding::JmpDst JmpDst;
     284             : 
     285             :   public:
     286        4503 :     AssemblerX86Shared()
     287        4503 :     {
     288        4503 :         if (!HasAVX())
     289        4503 :             masm.disableVEX();
     290        4503 :     }
     291             : 
     292             :     enum Condition {
     293             :         Equal = X86Encoding::ConditionE,
     294             :         NotEqual = X86Encoding::ConditionNE,
     295             :         Above = X86Encoding::ConditionA,
     296             :         AboveOrEqual = X86Encoding::ConditionAE,
     297             :         Below = X86Encoding::ConditionB,
     298             :         BelowOrEqual = X86Encoding::ConditionBE,
     299             :         GreaterThan = X86Encoding::ConditionG,
     300             :         GreaterThanOrEqual = X86Encoding::ConditionGE,
     301             :         LessThan = X86Encoding::ConditionL,
     302             :         LessThanOrEqual = X86Encoding::ConditionLE,
     303             :         Overflow = X86Encoding::ConditionO,
     304             :         CarrySet = X86Encoding::ConditionC,
     305             :         CarryClear = X86Encoding::ConditionNC,
     306             :         Signed = X86Encoding::ConditionS,
     307             :         NotSigned = X86Encoding::ConditionNS,
     308             :         Zero = X86Encoding::ConditionE,
     309             :         NonZero = X86Encoding::ConditionNE,
     310             :         Parity = X86Encoding::ConditionP,
     311             :         NoParity = X86Encoding::ConditionNP
     312             :     };
     313             : 
     314             :     // If this bit is set, the vucomisd operands have to be inverted.
     315             :     static const int DoubleConditionBitInvert = 0x10;
     316             : 
     317             :     // Bit set when a DoubleCondition does not map to a single x86 condition.
     318             :     // The macro assembler has to special-case these conditions.
     319             :     static const int DoubleConditionBitSpecial = 0x20;
     320             :     static const int DoubleConditionBits = DoubleConditionBitInvert | DoubleConditionBitSpecial;
     321             : 
     322             :     enum DoubleCondition {
     323             :         // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN.
     324             :         DoubleOrdered = NoParity,
     325             :         DoubleEqual = Equal | DoubleConditionBitSpecial,
     326             :         DoubleNotEqual = NotEqual,
     327             :         DoubleGreaterThan = Above,
     328             :         DoubleGreaterThanOrEqual = AboveOrEqual,
     329             :         DoubleLessThan = Above | DoubleConditionBitInvert,
     330             :         DoubleLessThanOrEqual = AboveOrEqual | DoubleConditionBitInvert,
     331             :         // If either operand is NaN, these conditions always evaluate to true.
     332             :         DoubleUnordered = Parity,
     333             :         DoubleEqualOrUnordered = Equal,
     334             :         DoubleNotEqualOrUnordered = NotEqual | DoubleConditionBitSpecial,
     335             :         DoubleGreaterThanOrUnordered = Below | DoubleConditionBitInvert,
     336             :         DoubleGreaterThanOrEqualOrUnordered = BelowOrEqual | DoubleConditionBitInvert,
     337             :         DoubleLessThanOrUnordered = Below,
     338             :         DoubleLessThanOrEqualOrUnordered = BelowOrEqual
     339             :     };
     340             : 
     341             :     enum NaNCond {
     342             :         NaN_HandledByCond,
     343             :         NaN_IsTrue,
     344             :         NaN_IsFalse
     345             :     };
     346             : 
     347             :     // If the primary condition returned by ConditionFromDoubleCondition doesn't
     348             :     // handle NaNs properly, return NaN_IsFalse if the comparison should be
     349             :     // overridden to return false on NaN, NaN_IsTrue if it should be overridden
     350             :     // to return true on NaN, or NaN_HandledByCond if no secondary check is
     351             :     // needed.
     352          11 :     static inline NaNCond NaNCondFromDoubleCondition(DoubleCondition cond) {
     353          11 :         switch (cond) {
     354             :           case DoubleOrdered:
     355             :           case DoubleNotEqual:
     356             :           case DoubleGreaterThan:
     357             :           case DoubleGreaterThanOrEqual:
     358             :           case DoubleLessThan:
     359             :           case DoubleLessThanOrEqual:
     360             :           case DoubleUnordered:
     361             :           case DoubleEqualOrUnordered:
     362             :           case DoubleGreaterThanOrUnordered:
     363             :           case DoubleGreaterThanOrEqualOrUnordered:
     364             :           case DoubleLessThanOrUnordered:
     365             :           case DoubleLessThanOrEqualOrUnordered:
     366           5 :             return NaN_HandledByCond;
     367             :           case DoubleEqual:
     368           3 :             return NaN_IsFalse;
     369             :           case DoubleNotEqualOrUnordered:
     370           3 :             return NaN_IsTrue;
     371             :         }
     372             : 
     373           0 :         MOZ_CRASH("Unknown double condition");
     374             :     }
     375             : 
     376             :     static void StaticAsserts() {
     377             :         // DoubleConditionBits should not interfere with x86 condition codes.
     378             :         JS_STATIC_ASSERT(!((Equal | NotEqual | Above | AboveOrEqual | Below |
     379             :                             BelowOrEqual | Parity | NoParity) & DoubleConditionBits));
     380             :     }
     381             : 
     382             :     static Condition InvertCondition(Condition cond);
     383             :     static Condition UnsignedCondition(Condition cond);
     384             :     static Condition ConditionWithoutEqual(Condition cond);
     385             : 
     386             :     static DoubleCondition InvertCondition(DoubleCondition cond);
     387             : 
     388             :     // Return the primary condition to test. Some primary conditions may not
     389             :     // handle NaNs properly and may therefore require a secondary condition.
     390             :     // Use NaNCondFromDoubleCondition to determine what else is needed.
     391          11 :     static inline Condition ConditionFromDoubleCondition(DoubleCondition cond) {
     392          11 :         return static_cast<Condition>(cond & ~DoubleConditionBits);
     393             :     }
     394             : 
     395             :     static void TraceDataRelocations(JSTracer* trc, JitCode* code, CompactBufferReader& reader);
     396             : 
     397             :     // MacroAssemblers hold onto gcthings, so they are traced by the GC.
     398             :     void trace(JSTracer* trc);
     399             : 
     400       36937 :     bool oom() const {
     401       73874 :         return AssemblerShared::oom() ||
     402       73874 :                masm.oom() ||
     403      110811 :                jumpRelocations_.oom() ||
     404       73874 :                dataRelocations_.oom();
     405             :     }
     406             : 
     407           0 :     void disableProtection() { masm.disableProtection(); }
     408             :     void enableProtection() { masm.enableProtection(); }
     409             :     void setLowerBoundForProtection(size_t size) {
     410             :         masm.setLowerBoundForProtection(size);
     411             :     }
     412             :     void unprotectRegion(unsigned char* first, size_t size) {
     413             :         masm.unprotectRegion(first, size);
     414             :     }
     415             :     void reprotectRegion(unsigned char* first, size_t size) {
     416             :         masm.reprotectRegion(first, size);
     417             :     }
     418             : 
     419           0 :     void setPrinter(Sprinter* sp) {
     420           0 :         masm.setPrinter(sp);
     421           0 :     }
     422             : 
     423       53055 :     static const Register getStackPointer() {
     424       53055 :         return StackPointer;
     425             :     }
     426             : 
     427             :     void executableCopy(void* buffer);
     428           0 :     bool asmMergeWith(const AssemblerX86Shared& other) {
     429           0 :         MOZ_ASSERT(other.jumps_.length() == 0);
     430           0 :         if (!AssemblerShared::asmMergeWith(masm.size(), other))
     431           0 :             return false;
     432           0 :         return masm.appendBuffer(other.masm);
     433             :     }
     434             :     void processCodeLabels(uint8_t* rawCode);
     435             :     void copyJumpRelocationTable(uint8_t* dest);
     436             :     void copyDataRelocationTable(uint8_t* dest);
     437             : 
     438             :     // Size of the instruction stream, in bytes.
     439       28667 :     size_t size() const {
     440       28667 :         return masm.size();
     441             :     }
     442             :     // Size of the jump relocation table, in bytes.
     443        9038 :     size_t jumpRelocationTableBytes() const {
     444        9038 :         return jumpRelocations_.length();
     445             :     }
     446        9038 :     size_t dataRelocationTableBytes() const {
     447        9038 :         return dataRelocations_.length();
     448             :     }
     449             :     // Size of the data table, in bytes.
     450        4539 :     size_t bytesNeeded() const {
     451        9078 :         return size() +
     452        4539 :                jumpRelocationTableBytes() +
     453        4539 :                dataRelocationTableBytes();
     454             :     }
     455             : 
     456             :   public:
     457           0 :     void haltingAlign(int alignment) {
     458           0 :         masm.haltingAlign(alignment);
     459           0 :     }
     460           0 :     void nopAlign(int alignment) {
     461           0 :         masm.nopAlign(alignment);
     462           0 :     }
     463           0 :     void writeCodePointer(CodeOffset* label) {
     464             :         // A CodeOffset only has one use, bake in the "end of list" value.
     465           0 :         masm.jumpTablePointer(LabelBase::INVALID_OFFSET);
     466           0 :         label->bind(masm.size());
     467           0 :     }
     468           0 :     void cmovz(const Operand& src, Register dest) {
     469           0 :         switch (src.kind()) {
     470             :           case Operand::REG:
     471           0 :             masm.cmovz_rr(src.reg(), dest.encoding());
     472           0 :             break;
     473             :           case Operand::MEM_REG_DISP:
     474           0 :             masm.cmovz_mr(src.disp(), src.base(), dest.encoding());
     475           0 :             break;
     476             :           case Operand::MEM_SCALE:
     477           0 :             masm.cmovz_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
     478           0 :             break;
     479             :           default:
     480           0 :             MOZ_CRASH("unexpected operand kind");
     481             :         }
     482           0 :     }
     483           0 :     void movl(Imm32 imm32, Register dest) {
     484           0 :         masm.movl_i32r(imm32.value, dest.encoding());
     485           0 :     }
     486         391 :     void movl(Register src, Register dest) {
     487         391 :         masm.movl_rr(src.encoding(), dest.encoding());
     488         391 :     }
     489        1747 :     void movl(const Operand& src, Register dest) {
     490        1747 :         switch (src.kind()) {
     491             :           case Operand::REG:
     492          26 :             masm.movl_rr(src.reg(), dest.encoding());
     493          26 :             break;
     494             :           case Operand::MEM_REG_DISP:
     495        1670 :             masm.movl_mr(src.disp(), src.base(), dest.encoding());
     496        1670 :             break;
     497             :           case Operand::MEM_SCALE:
     498          51 :             masm.movl_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
     499          51 :             break;
     500             :           case Operand::MEM_ADDRESS32:
     501           0 :             masm.movl_mr(src.address(), dest.encoding());
     502           0 :             break;
     503             :           default:
     504           0 :             MOZ_CRASH("unexpected operand kind");
     505             :         }
     506        1747 :     }
     507        2601 :     void movl(Register src, const Operand& dest) {
     508        2601 :         switch (dest.kind()) {
     509             :           case Operand::REG:
     510           3 :             masm.movl_rr(src.encoding(), dest.reg());
     511           3 :             break;
     512             :           case Operand::MEM_REG_DISP:
     513        2598 :             masm.movl_rm(src.encoding(), dest.disp(), dest.base());
     514        2598 :             break;
     515             :           case Operand::MEM_SCALE:
     516           0 :             masm.movl_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
     517           0 :             break;
     518             :           case Operand::MEM_ADDRESS32:
     519           0 :             masm.movl_rm(src.encoding(), dest.address());
     520           0 :             break;
     521             :           default:
     522           0 :             MOZ_CRASH("unexpected operand kind");
     523             :         }
     524        2601 :     }
     525        4123 :     void movl(Imm32 imm32, const Operand& dest) {
     526        4123 :         switch (dest.kind()) {
     527             :           case Operand::REG:
     528           0 :             masm.movl_i32r(imm32.value, dest.reg());
     529           0 :             break;
     530             :           case Operand::MEM_REG_DISP:
     531        4123 :             masm.movl_i32m(imm32.value, dest.disp(), dest.base());
     532        4123 :             break;
     533             :           case Operand::MEM_SCALE:
     534           0 :             masm.movl_i32m(imm32.value, dest.disp(), dest.base(), dest.index(), dest.scale());
     535           0 :             break;
     536             :           case Operand::MEM_ADDRESS32:
     537           0 :             masm.movl_i32m(imm32.value, dest.address());
     538           0 :             break;
     539             :           default:
     540           0 :             MOZ_CRASH("unexpected operand kind");
     541             :         }
     542        4123 :     }
     543             : 
     544             :     void xchgl(Register src, Register dest) {
     545             :         masm.xchgl_rr(src.encoding(), dest.encoding());
     546             :     }
     547             : 
     548             :     // Eventually vmovapd should be overloaded to support loads and
     549             :     // stores too.
     550           0 :     void vmovapd(FloatRegister src, FloatRegister dest) {
     551           0 :         MOZ_ASSERT(HasSSE2());
     552           0 :         masm.vmovapd_rr(src.encoding(), dest.encoding());
     553           0 :     }
     554             : 
     555           0 :     void vmovaps(FloatRegister src, FloatRegister dest) {
     556           0 :         MOZ_ASSERT(HasSSE2());
     557           0 :         masm.vmovaps_rr(src.encoding(), dest.encoding());
     558           0 :     }
     559           0 :     void vmovaps(const Operand& src, FloatRegister dest) {
     560           0 :         MOZ_ASSERT(HasSSE2());
     561           0 :         switch (src.kind()) {
     562             :           case Operand::MEM_REG_DISP:
     563           0 :             masm.vmovaps_mr(src.disp(), src.base(), dest.encoding());
     564           0 :             break;
     565             :           case Operand::MEM_SCALE:
     566           0 :             masm.vmovaps_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
     567           0 :             break;
     568             :           case Operand::FPREG:
     569           0 :             masm.vmovaps_rr(src.fpu(), dest.encoding());
     570           0 :             break;
     571             :           default:
     572           0 :             MOZ_CRASH("unexpected operand kind");
     573             :         }
     574           0 :     }
     575           0 :     void vmovaps(FloatRegister src, const Operand& dest) {
     576           0 :         MOZ_ASSERT(HasSSE2());
     577           0 :         switch (dest.kind()) {
     578             :           case Operand::MEM_REG_DISP:
     579           0 :             masm.vmovaps_rm(src.encoding(), dest.disp(), dest.base());
     580           0 :             break;
     581             :           case Operand::MEM_SCALE:
     582           0 :             masm.vmovaps_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
     583           0 :             break;
     584             :           default:
     585           0 :             MOZ_CRASH("unexpected operand kind");
     586             :         }
     587           0 :     }
     588      165543 :     void vmovups(const Operand& src, FloatRegister dest) {
     589      165543 :         MOZ_ASSERT(HasSSE2());
     590      165543 :         switch (src.kind()) {
     591             :           case Operand::MEM_REG_DISP:
     592      165543 :             masm.vmovups_mr(src.disp(), src.base(), dest.encoding());
     593      165522 :             break;
     594             :           case Operand::MEM_SCALE:
     595           0 :             masm.vmovups_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
     596           0 :             break;
     597             :           default:
     598           0 :             MOZ_CRASH("unexpected operand kind");
     599             :         }
     600      165522 :     }
     601      165673 :     void vmovups(FloatRegister src, const Operand& dest) {
     602      165673 :         MOZ_ASSERT(HasSSE2());
     603      165673 :         switch (dest.kind()) {
     604             :           case Operand::MEM_REG_DISP:
     605      165673 :             masm.vmovups_rm(src.encoding(), dest.disp(), dest.base());
     606      165663 :             break;
     607             :           case Operand::MEM_SCALE:
     608           0 :             masm.vmovups_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
     609           0 :             break;
     610             :           default:
     611           0 :             MOZ_CRASH("unexpected operand kind");
     612             :         }
     613      165663 :     }
     614             : 
     615             :     // vmovsd is only provided in load/store form since the
     616             :     // register-to-register form has different semantics (it doesn't clobber
     617             :     // the whole output register) and isn't needed currently.
     618          16 :     void vmovsd(const Address& src, FloatRegister dest) {
     619          16 :         masm.vmovsd_mr(src.offset, src.base.encoding(), dest.encoding());
     620          16 :     }
     621           0 :     void vmovsd(const BaseIndex& src, FloatRegister dest) {
     622           0 :         masm.vmovsd_mr(src.offset, src.base.encoding(), src.index.encoding(), src.scale, dest.encoding());
     623           0 :     }
     624           7 :     void vmovsd(FloatRegister src, const Address& dest) {
     625           7 :         masm.vmovsd_rm(src.encoding(), dest.offset, dest.base.encoding());
     626           7 :     }
     627           0 :     void vmovsd(FloatRegister src, const BaseIndex& dest) {
     628           0 :         masm.vmovsd_rm(src.encoding(), dest.offset, dest.base.encoding(), dest.index.encoding(), dest.scale);
     629           0 :     }
     630             :     // Although vmovss is not only provided in load/store form (for the same
     631             :     // reasons as vmovsd above), the register to register form should be only
     632             :     // used in contexts where we care about not clearing the higher lanes of
     633             :     // the FloatRegister.
     634           0 :     void vmovss(const Address& src, FloatRegister dest) {
     635           0 :         masm.vmovss_mr(src.offset, src.base.encoding(), dest.encoding());
     636           0 :     }
     637           0 :     void vmovss(const BaseIndex& src, FloatRegister dest) {
     638           0 :         masm.vmovss_mr(src.offset, src.base.encoding(), src.index.encoding(), src.scale, dest.encoding());
     639           0 :     }
     640           0 :     void vmovss(FloatRegister src, const Address& dest) {
     641           0 :         masm.vmovss_rm(src.encoding(), dest.offset, dest.base.encoding());
     642           0 :     }
     643           0 :     void vmovss(FloatRegister src, const BaseIndex& dest) {
     644           0 :         masm.vmovss_rm(src.encoding(), dest.offset, dest.base.encoding(), dest.index.encoding(), dest.scale);
     645           0 :     }
     646           0 :     void vmovss(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
     647           0 :         masm.vmovss_rr(src1.encoding(), src0.encoding(), dest.encoding());
     648           0 :     }
     649           0 :     void vmovdqu(const Operand& src, FloatRegister dest) {
     650           0 :         MOZ_ASSERT(HasSSE2());
     651           0 :         switch (src.kind()) {
     652             :           case Operand::MEM_REG_DISP:
     653           0 :             masm.vmovdqu_mr(src.disp(), src.base(), dest.encoding());
     654           0 :             break;
     655             :           case Operand::MEM_SCALE:
     656           0 :             masm.vmovdqu_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
     657           0 :             break;
     658             :           default:
     659           0 :             MOZ_CRASH("unexpected operand kind");
     660             :         }
     661           0 :     }
     662           0 :     void vmovdqu(FloatRegister src, const Operand& dest) {
     663           0 :         MOZ_ASSERT(HasSSE2());
     664           0 :         switch (dest.kind()) {
     665             :           case Operand::MEM_REG_DISP:
     666           0 :             masm.vmovdqu_rm(src.encoding(), dest.disp(), dest.base());
     667           0 :             break;
     668             :           case Operand::MEM_SCALE:
     669           0 :             masm.vmovdqu_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
     670           0 :             break;
     671             :           default:
     672           0 :             MOZ_CRASH("unexpected operand kind");
     673             :         }
     674           0 :     }
     675           0 :     void vmovdqa(const Operand& src, FloatRegister dest) {
     676           0 :         MOZ_ASSERT(HasSSE2());
     677           0 :         switch (src.kind()) {
     678             :           case Operand::FPREG:
     679           0 :             masm.vmovdqa_rr(src.fpu(), dest.encoding());
     680           0 :             break;
     681             :           case Operand::MEM_REG_DISP:
     682           0 :             masm.vmovdqa_mr(src.disp(), src.base(), dest.encoding());
     683           0 :             break;
     684             :           case Operand::MEM_SCALE:
     685           0 :             masm.vmovdqa_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
     686           0 :             break;
     687             :           default:
     688           0 :             MOZ_CRASH("unexpected operand kind");
     689             :         }
     690           0 :     }
     691           0 :     void vmovdqa(FloatRegister src, const Operand& dest) {
     692           0 :         MOZ_ASSERT(HasSSE2());
     693           0 :         switch (dest.kind()) {
     694             :           case Operand::MEM_REG_DISP:
     695           0 :             masm.vmovdqa_rm(src.encoding(), dest.disp(), dest.base());
     696           0 :             break;
     697             :           case Operand::MEM_SCALE:
     698           0 :             masm.vmovdqa_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
     699           0 :             break;
     700             :           default:
     701           0 :             MOZ_CRASH("unexpected operand kind");
     702             :         }
     703           0 :     }
     704           0 :     void vmovdqa(FloatRegister src, FloatRegister dest) {
     705           0 :         MOZ_ASSERT(HasSSE2());
     706           0 :         masm.vmovdqa_rr(src.encoding(), dest.encoding());
     707           0 :     }
     708           0 :     void vcvtss2sd(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
     709           0 :         MOZ_ASSERT(HasSSE2());
     710           0 :         masm.vcvtss2sd_rr(src1.encoding(), src0.encoding(), dest.encoding());
     711           0 :     }
     712           0 :     void vcvtsd2ss(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
     713           0 :         MOZ_ASSERT(HasSSE2());
     714           0 :         masm.vcvtsd2ss_rr(src1.encoding(), src0.encoding(), dest.encoding());
     715           0 :     }
     716         656 :     void movzbl(const Operand& src, Register dest) {
     717         656 :         switch (src.kind()) {
     718             :           case Operand::MEM_REG_DISP:
     719         124 :             masm.movzbl_mr(src.disp(), src.base(), dest.encoding());
     720         124 :             break;
     721             :           case Operand::MEM_SCALE:
     722         532 :             masm.movzbl_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
     723         532 :             break;
     724             :           default:
     725           0 :             MOZ_CRASH("unexpected operand kind");
     726             :         }
     727         656 :     }
     728           0 :     void movsbl(Register src, Register dest) {
     729           0 :         masm.movsbl_rr(src.encoding(), dest.encoding());
     730           0 :     }
     731           0 :     void movsbl(const Operand& src, Register dest) {
     732           0 :         switch (src.kind()) {
     733             :           case Operand::MEM_REG_DISP:
     734           0 :             masm.movsbl_mr(src.disp(), src.base(), dest.encoding());
     735           0 :             break;
     736             :           case Operand::MEM_SCALE:
     737           0 :             masm.movsbl_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
     738           0 :             break;
     739             :           default:
     740           0 :             MOZ_CRASH("unexpected operand kind");
     741             :         }
     742           0 :     }
     743           0 :     void movb(const Operand& src, Register dest) {
     744           0 :         switch (src.kind()) {
     745             :           case Operand::MEM_REG_DISP:
     746           0 :             masm.movb_mr(src.disp(), src.base(), dest.encoding());
     747           0 :             break;
     748             :           case Operand::MEM_SCALE:
     749           0 :             masm.movb_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
     750           0 :             break;
     751             :           default:
     752           0 :             MOZ_CRASH("unexpected operand kind");
     753             :         }
     754           0 :     }
     755           0 :     void movb(Imm32 src, Register dest) {
     756           0 :         masm.movb_ir(src.value & 255, dest.encoding());
     757           0 :     }
     758          11 :     void movb(Register src, const Operand& dest) {
     759          11 :         switch (dest.kind()) {
     760             :           case Operand::MEM_REG_DISP:
     761           8 :             masm.movb_rm(src.encoding(), dest.disp(), dest.base());
     762           8 :             break;
     763             :           case Operand::MEM_SCALE:
     764           3 :             masm.movb_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
     765           3 :             break;
     766             :           default:
     767           0 :             MOZ_CRASH("unexpected operand kind");
     768             :         }
     769          11 :     }
     770           4 :     void movb(Imm32 src, const Operand& dest) {
     771           4 :         switch (dest.kind()) {
     772             :           case Operand::MEM_REG_DISP:
     773           4 :             masm.movb_im(src.value, dest.disp(), dest.base());
     774           4 :             break;
     775             :           case Operand::MEM_SCALE:
     776           0 :             masm.movb_im(src.value, dest.disp(), dest.base(), dest.index(), dest.scale());
     777           0 :             break;
     778             :           default:
     779           0 :             MOZ_CRASH("unexpected operand kind");
     780             :         }
     781           4 :     }
     782         203 :     void movzwl(const Operand& src, Register dest) {
     783         203 :         switch (src.kind()) {
     784             :           case Operand::REG:
     785           0 :             masm.movzwl_rr(src.reg(), dest.encoding());
     786           0 :             break;
     787             :           case Operand::MEM_REG_DISP:
     788         130 :             masm.movzwl_mr(src.disp(), src.base(), dest.encoding());
     789         130 :             break;
     790             :           case Operand::MEM_SCALE:
     791          73 :             masm.movzwl_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
     792          73 :             break;
     793             :           default:
     794           0 :             MOZ_CRASH("unexpected operand kind");
     795             :         }
     796         203 :     }
     797           0 :     void movzwl(Register src, Register dest) {
     798           0 :         masm.movzwl_rr(src.encoding(), dest.encoding());
     799           0 :     }
     800           0 :     void movw(const Operand& src, Register dest) {
     801           0 :         masm.prefix_16_for_32();
     802           0 :         movl(src, dest);
     803           0 :     }
     804             :     void movw(Imm32 src, Register dest) {
     805             :         masm.prefix_16_for_32();
     806             :         movl(src, dest);
     807             :     }
     808          36 :     void movw(Register src, const Operand& dest) {
     809          36 :         switch (dest.kind()) {
     810             :           case Operand::MEM_REG_DISP:
     811          36 :             masm.movw_rm(src.encoding(), dest.disp(), dest.base());
     812          36 :             break;
     813             :           case Operand::MEM_SCALE:
     814           0 :             masm.movw_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
     815           0 :             break;
     816             :           default:
     817           0 :             MOZ_CRASH("unexpected operand kind");
     818             :         }
     819          36 :     }
     820           4 :     void movw(Imm32 src, const Operand& dest) {
     821           4 :         switch (dest.kind()) {
     822             :           case Operand::MEM_REG_DISP:
     823           4 :             masm.movw_im(src.value, dest.disp(), dest.base());
     824           4 :             break;
     825             :           case Operand::MEM_SCALE:
     826           0 :             masm.movw_im(src.value, dest.disp(), dest.base(), dest.index(), dest.scale());
     827           0 :             break;
     828             :           default:
     829           0 :             MOZ_CRASH("unexpected operand kind");
     830             :         }
     831           4 :     }
     832           0 :     void movswl(Register src, Register dest) {
     833           0 :         masm.movswl_rr(src.encoding(), dest.encoding());
     834           0 :     }
     835           0 :     void movswl(const Operand& src, Register dest) {
     836           0 :         switch (src.kind()) {
     837             :           case Operand::MEM_REG_DISP:
     838           0 :             masm.movswl_mr(src.disp(), src.base(), dest.encoding());
     839           0 :             break;
     840             :           case Operand::MEM_SCALE:
     841           0 :             masm.movswl_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
     842           0 :             break;
     843             :           default:
     844           0 :             MOZ_CRASH("unexpected operand kind");
     845             :         }
     846           0 :     }
     847           0 :     void leal(const Operand& src, Register dest) {
     848           0 :         switch (src.kind()) {
     849             :           case Operand::MEM_REG_DISP:
     850           0 :             masm.leal_mr(src.disp(), src.base(), dest.encoding());
     851           0 :             break;
     852             :           case Operand::MEM_SCALE:
     853           0 :             masm.leal_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
     854           0 :             break;
     855             :           default:
     856           0 :             MOZ_CRASH("unexpected operand kind");
     857             :         }
     858           0 :     }
     859             : 
     860             :   protected:
     861       40904 :     void jSrc(Condition cond, Label* label) {
     862       40904 :         if (label->bound()) {
     863             :             // The jump can be immediately encoded to the correct destination.
     864         535 :             masm.jCC_i(static_cast<X86Encoding::Condition>(cond), JmpDst(label->offset()));
     865             :         } else {
     866             :             // Thread the jump list through the unpatched jump targets.
     867       40369 :             JmpSrc j = masm.jCC(static_cast<X86Encoding::Condition>(cond));
     868       40368 :             JmpSrc prev = JmpSrc(label->use(j.offset()));
     869       40368 :             masm.setNextJump(j, prev);
     870             :         }
     871       40903 :     }
     872        7280 :     void jmpSrc(Label* label) {
     873        7280 :         if (label->bound()) {
     874             :             // The jump can be immediately encoded to the correct destination.
     875         695 :             masm.jmp_i(JmpDst(label->offset()));
     876             :         } else {
     877             :             // Thread the jump list through the unpatched jump targets.
     878        6585 :             JmpSrc j = masm.jmp();
     879        6585 :             JmpSrc prev = JmpSrc(label->use(j.offset()));
     880        6585 :             masm.setNextJump(j, prev);
     881             :         }
     882        7280 :     }
     883             : 
     884             :     // Comparison of EAX against the address given by a Label.
     885             :     JmpSrc cmpSrc(Label* label) {
     886             :         JmpSrc j = masm.cmp_eax();
     887             :         if (label->bound()) {
     888             :             // The jump can be immediately patched to the correct destination.
     889             :             masm.linkJump(j, JmpDst(label->offset()));
     890             :         } else {
     891             :             // Thread the jump list through the unpatched jump targets.
     892             :             JmpSrc prev = JmpSrc(label->use(j.offset()));
     893             :             masm.setNextJump(j, prev);
     894             :         }
     895             :         return j;
     896             :     }
     897             : 
     898           0 :     JmpSrc jSrc(Condition cond, RepatchLabel* label) {
     899           0 :         JmpSrc j = masm.jCC(static_cast<X86Encoding::Condition>(cond));
     900           0 :         if (label->bound()) {
     901             :             // The jump can be immediately patched to the correct destination.
     902           0 :             masm.linkJump(j, JmpDst(label->offset()));
     903             :         } else {
     904           0 :             label->use(j.offset());
     905             :         }
     906           0 :         return j;
     907             :     }
     908          21 :     JmpSrc jmpSrc(RepatchLabel* label) {
     909          21 :         JmpSrc j = masm.jmp();
     910          21 :         if (label->bound()) {
     911             :             // The jump can be immediately patched to the correct destination.
     912           0 :             masm.linkJump(j, JmpDst(label->offset()));
     913             :         } else {
     914             :             // Thread the jump list through the unpatched jump targets.
     915          21 :             label->use(j.offset());
     916             :         }
     917          21 :         return j;
     918             :     }
     919             : 
     920             :   public:
     921          64 :     void nop() { masm.nop(); }
     922           0 :     void nop(size_t n) { masm.insert_nop(n); }
     923       40904 :     void j(Condition cond, Label* label) { jSrc(cond, label); }
     924        7280 :     void jmp(Label* label) { jmpSrc(label); }
     925             :     void j(Condition cond, RepatchLabel* label) { jSrc(cond, label); }
     926             :     void jmp(RepatchLabel* label) { jmpSrc(label); }
     927             : 
     928           0 :     void j(Condition cond, wasm::TrapDesc target) {
     929           0 :         Label l;
     930           0 :         j(cond, &l);
     931           0 :         bindLater(&l, target);
     932           0 :     }
     933           0 :     void jmp(wasm::TrapDesc target) {
     934           0 :         Label l;
     935           0 :         jmp(&l);
     936           0 :         bindLater(&l, target);
     937           0 :     }
     938             : 
     939        2583 :     void jmp(const Operand& op) {
     940        2583 :         switch (op.kind()) {
     941             :           case Operand::MEM_REG_DISP:
     942        2384 :             masm.jmp_m(op.disp(), op.base());
     943        2384 :             break;
     944             :           case Operand::MEM_SCALE:
     945           0 :             masm.jmp_m(op.disp(), op.base(), op.index(), op.scale());
     946           0 :             break;
     947             :           case Operand::REG:
     948         199 :             masm.jmp_r(op.reg());
     949         199 :             break;
     950             :           default:
     951           0 :             MOZ_CRASH("unexpected operand kind");
     952             :         }
     953        2583 :     }
     954             :     void cmpEAX(Label* label) { cmpSrc(label); }
     955      114023 :     void bind(Label* label) {
     956      114023 :         JmpDst dst(masm.label());
     957      114025 :         if (label->used()) {
     958             :             bool more;
     959       40344 :             JmpSrc jmp(label->offset());
     960       47324 :             do {
     961       47323 :                 JmpSrc next;
     962       47323 :                 more = masm.nextJump(jmp, &next);
     963       47323 :                 masm.linkJump(jmp, dst);
     964       47324 :                 jmp = next;
     965             :             } while (more);
     966             :         }
     967      114025 :         label->bind(dst.offset());
     968      114025 :     }
     969           0 :     void bindLater(Label* label, wasm::TrapDesc target) {
     970           0 :         if (label->used()) {
     971           0 :             JmpSrc jmp(label->offset());
     972           0 :             do {
     973           0 :                 append(wasm::TrapSite(target, jmp.offset()));
     974           0 :             } while (masm.nextJump(jmp, &jmp));
     975             :         }
     976           0 :         label->reset();
     977           0 :     }
     978          21 :     void bind(RepatchLabel* label) {
     979          21 :         JmpDst dst(masm.label());
     980          21 :         if (label->used()) {
     981          21 :             JmpSrc jmp(label->offset());
     982          21 :             masm.linkJump(jmp, dst);
     983             :         }
     984          21 :         label->bind(dst.offset());
     985          21 :     }
     986          17 :     void use(CodeOffset* label) {
     987          17 :         label->bind(currentOffset());
     988          17 :     }
     989       86849 :     uint32_t currentOffset() {
     990       86849 :         return masm.label().offset();
     991             :     }
     992             : 
     993             :     // Re-routes pending jumps to a new label.
     994         279 :     void retarget(Label* label, Label* target) {
     995         279 :         if (!label->used())
     996           0 :             return;
     997             :         bool more;
     998         279 :         JmpSrc jmp(label->offset());
     999         305 :         do {
    1000         305 :             JmpSrc next;
    1001         305 :             more = masm.nextJump(jmp, &next);
    1002         305 :             if (target->bound()) {
    1003             :                 // The jump can be immediately patched to the correct destination.
    1004           0 :                 masm.linkJump(jmp, JmpDst(target->offset()));
    1005             :             } else {
    1006             :                 // Thread the jump list through the unpatched jump targets.
    1007         305 :                 JmpSrc prev(target->use(jmp.offset()));
    1008         305 :                 masm.setNextJump(jmp, prev);
    1009             :             }
    1010         305 :             jmp = JmpSrc(next.offset());
    1011             :         } while (more);
    1012         279 :         label->reset();
    1013             :     }
    1014             : 
    1015          14 :     static void Bind(uint8_t* raw, CodeOffset* label, const void* address) {
    1016          14 :         if (label->bound()) {
    1017          14 :             intptr_t offset = label->offset();
    1018          14 :             X86Encoding::SetPointer(raw + offset, address);
    1019             :         }
    1020          14 :     }
    1021             : 
    1022             :     // See Bind and X86Encoding::setPointer.
    1023           0 :     size_t labelToPatchOffset(CodeOffset label) {
    1024           0 :         return label.offset() - sizeof(void*);
    1025             :     }
    1026             : 
    1027        3552 :     void ret() {
    1028        3552 :         masm.ret();
    1029        3552 :     }
    1030        1036 :     void retn(Imm32 n) {
    1031             :         // Remove the size of the return address which is included in the frame.
    1032        1036 :         masm.ret_i(n.value - sizeof(void*));
    1033        1036 :     }
    1034         373 :     CodeOffset call(Label* label) {
    1035         373 :         if (label->bound()) {
    1036           0 :             masm.linkJump(masm.call(), JmpDst(label->offset()));
    1037             :         } else {
    1038         373 :             JmpSrc j = masm.call();
    1039         373 :             JmpSrc prev = JmpSrc(label->use(j.offset()));
    1040         373 :             masm.setNextJump(j, prev);
    1041             :         }
    1042         373 :         return CodeOffset(masm.currentOffset());
    1043             :     }
    1044          94 :     CodeOffset call(Register reg) {
    1045          94 :         masm.call_r(reg.encoding());
    1046          94 :         return CodeOffset(masm.currentOffset());
    1047             :     }
    1048       19474 :     void call(const Operand& op) {
    1049       19474 :         switch (op.kind()) {
    1050             :           case Operand::REG:
    1051           0 :             masm.call_r(op.reg());
    1052           0 :             break;
    1053             :           case Operand::MEM_REG_DISP:
    1054       19474 :             masm.call_m(op.disp(), op.base());
    1055       19474 :             break;
    1056             :           default:
    1057           0 :             MOZ_CRASH("unexpected operand kind");
    1058             :         }
    1059       19474 :     }
    1060             : 
    1061           0 :     CodeOffset callWithPatch() {
    1062           0 :         return CodeOffset(masm.call().offset());
    1063             :     }
    1064             : 
    1065           0 :     void patchCall(uint32_t callerOffset, uint32_t calleeOffset) {
    1066           0 :         unsigned char* code = masm.data();
    1067           0 :         X86Encoding::SetRel32(code + callerOffset, code + calleeOffset);
    1068           0 :     }
    1069           0 :     CodeOffset farJumpWithPatch() {
    1070           0 :         return CodeOffset(masm.jmp().offset());
    1071             :     }
    1072           0 :     void patchFarJump(CodeOffset farJump, uint32_t targetOffset) {
    1073           0 :         unsigned char* code = masm.data();
    1074           0 :         X86Encoding::SetRel32(code + farJump.offset(), code + targetOffset);
    1075           0 :     }
    1076           0 :     static void repatchFarJump(uint8_t* code, uint32_t farJumpOffset, uint32_t targetOffset) {
    1077           0 :         X86Encoding::SetRel32(code + farJumpOffset, code + targetOffset);
    1078           0 :     }
    1079             : 
    1080             :     // This is for patching during code generation, not after.
    1081             :     void patchAddl(CodeOffset offset, int32_t n) {
    1082             :         unsigned char* code = masm.data();
    1083             :         X86Encoding::SetInt32(code + offset.offset(), n);
    1084             :     }
    1085             : 
    1086           0 :     CodeOffset twoByteNop() {
    1087           0 :         return CodeOffset(masm.twoByteNop().offset());
    1088             :     }
    1089           0 :     static void patchTwoByteNopToJump(uint8_t* jump, uint8_t* target) {
    1090           0 :         X86Encoding::BaseAssembler::patchTwoByteNopToJump(jump, target);
    1091           0 :     }
    1092           0 :     static void patchJumpToTwoByteNop(uint8_t* jump) {
    1093           0 :         X86Encoding::BaseAssembler::patchJumpToTwoByteNop(jump);
    1094           0 :     }
    1095             : 
    1096           0 :     static void patchFiveByteNopToCall(uint8_t* callsite, uint8_t* target) {
    1097           0 :         X86Encoding::BaseAssembler::patchFiveByteNopToCall(callsite, target);
    1098           0 :     }
    1099           0 :     static void patchCallToFiveByteNop(uint8_t* callsite) {
    1100           0 :         X86Encoding::BaseAssembler::patchCallToFiveByteNop(callsite);
    1101           0 :     }
    1102             : 
    1103       21541 :     void breakpoint() {
    1104       21541 :         masm.int3();
    1105       21541 :     }
    1106             : 
    1107      331376 :     static bool HasSSE2() { return CPUInfo::IsSSE2Present(); }
    1108           0 :     static bool HasSSE3() { return CPUInfo::IsSSE3Present(); }
    1109           0 :     static bool HasSSSE3() { return CPUInfo::IsSSSE3Present(); }
    1110           0 :     static bool HasSSE41() { return CPUInfo::IsSSE41Present(); }
    1111           0 :     static bool HasPOPCNT() { return CPUInfo::IsPOPCNTPresent(); }
    1112           4 :     static bool SupportsFloatingPoint() { return CPUInfo::IsSSE2Present(); }
    1113           4 :     static bool SupportsUnalignedAccesses() { return true; }
    1114       24627 :     static bool SupportsSimd() { return CPUInfo::IsSSE2Present(); }
    1115        4503 :     static bool HasAVX() { return CPUInfo::IsAVXPresent(); }
    1116             : 
    1117           0 :     static bool HasRoundInstruction(RoundingMode mode) {
    1118           0 :         switch (mode) {
    1119             :           case RoundingMode::Up:
    1120             :           case RoundingMode::Down:
    1121             :           case RoundingMode::NearestTiesToEven:
    1122             :           case RoundingMode::TowardsZero:
    1123           0 :             return CPUInfo::IsSSE41Present();
    1124             :         }
    1125           0 :         MOZ_CRASH("unexpected mode");
    1126             :     }
    1127             : 
    1128         221 :     void cmpl(Register rhs, Register lhs) {
    1129         221 :         masm.cmpl_rr(rhs.encoding(), lhs.encoding());
    1130         221 :     }
    1131           8 :     void cmpl(const Operand& rhs, Register lhs) {
    1132           8 :         switch (rhs.kind()) {
    1133             :           case Operand::REG:
    1134           5 :             masm.cmpl_rr(rhs.reg(), lhs.encoding());
    1135           5 :             break;
    1136             :           case Operand::MEM_REG_DISP:
    1137           3 :             masm.cmpl_mr(rhs.disp(), rhs.base(), lhs.encoding());
    1138           3 :             break;
    1139             :           case Operand::MEM_ADDRESS32:
    1140           0 :             masm.cmpl_mr(rhs.address(), lhs.encoding());
    1141           0 :             break;
    1142             :           default:
    1143           0 :             MOZ_CRASH("unexpected operand kind");
    1144             :         }
    1145           8 :     }
    1146         101 :     void cmpl(Register rhs, const Operand& lhs) {
    1147         101 :         switch (lhs.kind()) {
    1148             :           case Operand::REG:
    1149           0 :             masm.cmpl_rr(rhs.encoding(), lhs.reg());
    1150           0 :             break;
    1151             :           case Operand::MEM_REG_DISP:
    1152         101 :             masm.cmpl_rm(rhs.encoding(), lhs.disp(), lhs.base());
    1153         101 :             break;
    1154             :           case Operand::MEM_ADDRESS32:
    1155           0 :             masm.cmpl_rm(rhs.encoding(), lhs.address());
    1156           0 :             break;
    1157             :           default:
    1158           0 :             MOZ_CRASH("unexpected operand kind");
    1159             :         }
    1160         101 :     }
    1161        7659 :     void cmpl(Imm32 rhs, Register lhs) {
    1162        7659 :         masm.cmpl_ir(rhs.value, lhs.encoding());
    1163        7659 :     }
    1164        1658 :     void cmpl(Imm32 rhs, const Operand& lhs) {
    1165        1658 :         switch (lhs.kind()) {
    1166             :           case Operand::REG:
    1167           0 :             masm.cmpl_ir(rhs.value, lhs.reg());
    1168           0 :             break;
    1169             :           case Operand::MEM_REG_DISP:
    1170        1658 :             masm.cmpl_im(rhs.value, lhs.disp(), lhs.base());
    1171        1658 :             break;
    1172             :           case Operand::MEM_SCALE:
    1173           0 :             masm.cmpl_im(rhs.value, lhs.disp(), lhs.base(), lhs.index(), lhs.scale());
    1174           0 :             break;
    1175             :           case Operand::MEM_ADDRESS32:
    1176           0 :             masm.cmpl_im(rhs.value, lhs.address());
    1177           0 :             break;
    1178             :           default:
    1179           0 :             MOZ_CRASH("unexpected operand kind");
    1180             :         }
    1181        1658 :     }
    1182             :     CodeOffset cmplWithPatch(Imm32 rhs, Register lhs) {
    1183             :         masm.cmpl_i32r(rhs.value, lhs.encoding());
    1184             :         return CodeOffset(masm.currentOffset());
    1185             :     }
    1186             :     void cmpw(Register rhs, Register lhs) {
    1187             :         masm.cmpw_rr(rhs.encoding(), lhs.encoding());
    1188             :     }
    1189         186 :     void setCC(Condition cond, Register r) {
    1190         186 :         masm.setCC_r(static_cast<X86Encoding::Condition>(cond), r.encoding());
    1191         186 :     }
    1192         796 :     void testb(Register rhs, Register lhs) {
    1193         796 :         MOZ_ASSERT(AllocatableGeneralRegisterSet(Registers::SingleByteRegs).has(rhs));
    1194         796 :         MOZ_ASSERT(AllocatableGeneralRegisterSet(Registers::SingleByteRegs).has(lhs));
    1195         796 :         masm.testb_rr(rhs.encoding(), lhs.encoding());
    1196         796 :     }
    1197             :     void testw(Register rhs, Register lhs) {
    1198             :         masm.testw_rr(lhs.encoding(), rhs.encoding());
    1199             :     }
    1200        3248 :     void testl(Register rhs, Register lhs) {
    1201        3248 :         masm.testl_rr(lhs.encoding(), rhs.encoding());
    1202        3248 :     }
    1203         199 :     void testl(Imm32 rhs, Register lhs) {
    1204         199 :         masm.testl_ir(rhs.value, lhs.encoding());
    1205         199 :     }
    1206        7960 :     void testl(Imm32 rhs, const Operand& lhs) {
    1207        7960 :         switch (lhs.kind()) {
    1208             :           case Operand::REG:
    1209           0 :             masm.testl_ir(rhs.value, lhs.reg());
    1210           0 :             break;
    1211             :           case Operand::MEM_REG_DISP:
    1212        7960 :             masm.testl_i32m(rhs.value, lhs.disp(), lhs.base());
    1213        7960 :             break;
    1214             :           case Operand::MEM_ADDRESS32:
    1215           0 :             masm.testl_i32m(rhs.value, lhs.address());
    1216           0 :             break;
    1217             :           default:
    1218           0 :             MOZ_CRASH("unexpected operand kind");
    1219             :             break;
    1220             :         }
    1221        7960 :     }
    1222             : 
    1223        1155 :     void addl(Imm32 imm, Register dest) {
    1224        1155 :         masm.addl_ir(imm.value, dest.encoding());
    1225        1155 :     }
    1226             :     CodeOffset addlWithPatch(Imm32 imm, Register dest) {
    1227             :         masm.addl_i32r(imm.value, dest.encoding());
    1228             :         return CodeOffset(masm.currentOffset());
    1229             :     }
    1230          16 :     void addl(Imm32 imm, const Operand& op) {
    1231          16 :         switch (op.kind()) {
    1232             :           case Operand::REG:
    1233           8 :             masm.addl_ir(imm.value, op.reg());
    1234           8 :             break;
    1235             :           case Operand::MEM_REG_DISP:
    1236           8 :             masm.addl_im(imm.value, op.disp(), op.base());
    1237           8 :             break;
    1238             :           case Operand::MEM_ADDRESS32:
    1239           0 :             masm.addl_im(imm.value, op.address());
    1240           0 :             break;
    1241             :           case Operand::MEM_SCALE:
    1242           0 :             masm.addl_im(imm.value, op.disp(), op.base(), op.index(), op.scale());
    1243           0 :             break;
    1244             :           default:
    1245           0 :             MOZ_CRASH("unexpected operand kind");
    1246             :         }
    1247          16 :     }
    1248           0 :     void addw(Imm32 imm, const Operand& op) {
    1249           0 :         switch (op.kind()) {
    1250             :           case Operand::REG:
    1251           0 :             masm.addw_ir(imm.value, op.reg());
    1252           0 :             break;
    1253             :           case Operand::MEM_REG_DISP:
    1254           0 :             masm.addw_im(imm.value, op.disp(), op.base());
    1255           0 :             break;
    1256             :           case Operand::MEM_ADDRESS32:
    1257           0 :             masm.addw_im(imm.value, op.address());
    1258           0 :             break;
    1259             :           case Operand::MEM_SCALE:
    1260           0 :             masm.addw_im(imm.value, op.disp(), op.base(), op.index(), op.scale());
    1261           0 :             break;
    1262             :           default:
    1263           0 :             MOZ_CRASH("unexpected operand kind");
    1264             :         }
    1265           0 :     }
    1266         663 :     void subl(Imm32 imm, Register dest) {
    1267         663 :         masm.subl_ir(imm.value, dest.encoding());
    1268         663 :     }
    1269           0 :     void subl(Imm32 imm, const Operand& op) {
    1270           0 :         switch (op.kind()) {
    1271             :           case Operand::REG:
    1272           0 :             masm.subl_ir(imm.value, op.reg());
    1273           0 :             break;
    1274             :           case Operand::MEM_REG_DISP:
    1275           0 :             masm.subl_im(imm.value, op.disp(), op.base());
    1276           0 :             break;
    1277             :           case Operand::MEM_SCALE:
    1278           0 :             masm.subl_im(imm.value, op.disp(), op.base(), op.index(), op.scale());
    1279           0 :             break;
    1280             :           default:
    1281           0 :             MOZ_CRASH("unexpected operand kind");
    1282             :         }
    1283           0 :     }
    1284           0 :     void subw(Imm32 imm, const Operand& op) {
    1285           0 :         switch (op.kind()) {
    1286             :           case Operand::REG:
    1287           0 :             masm.subw_ir(imm.value, op.reg());
    1288           0 :             break;
    1289             :           case Operand::MEM_REG_DISP:
    1290           0 :             masm.subw_im(imm.value, op.disp(), op.base());
    1291           0 :             break;
    1292             :           case Operand::MEM_SCALE:
    1293           0 :             masm.subw_im(imm.value, op.disp(), op.base(), op.index(), op.scale());
    1294           0 :             break;
    1295             :           default:
    1296           0 :             MOZ_CRASH("unexpected operand kind");
    1297             :         }
    1298           0 :     }
    1299          47 :     void addl(Register src, Register dest) {
    1300          47 :         masm.addl_rr(src.encoding(), dest.encoding());
    1301          47 :     }
    1302           0 :     void addl(Register src, const Operand& dest) {
    1303           0 :         switch (dest.kind()) {
    1304             :           case Operand::REG:
    1305           0 :             masm.addl_rr(src.encoding(), dest.reg());
    1306           0 :             break;
    1307             :           case Operand::MEM_REG_DISP:
    1308           0 :             masm.addl_rm(src.encoding(), dest.disp(), dest.base());
    1309           0 :             break;
    1310             :           case Operand::MEM_SCALE:
    1311           0 :             masm.addl_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
    1312           0 :             break;
    1313             :           default:
    1314           0 :             MOZ_CRASH("unexpected operand kind");
    1315             :         }
    1316           0 :     }
    1317           0 :     void addw(Register src, const Operand& dest) {
    1318           0 :         switch (dest.kind()) {
    1319             :           case Operand::REG:
    1320           0 :             masm.addw_rr(src.encoding(), dest.reg());
    1321           0 :             break;
    1322             :           case Operand::MEM_REG_DISP:
    1323           0 :             masm.addw_rm(src.encoding(), dest.disp(), dest.base());
    1324           0 :             break;
    1325             :           case Operand::MEM_SCALE:
    1326           0 :             masm.addw_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
    1327           0 :             break;
    1328             :           default:
    1329           0 :             MOZ_CRASH("unexpected operand kind");
    1330             :         }
    1331           0 :     }
    1332          15 :     void subl(Register src, Register dest) {
    1333          15 :         masm.subl_rr(src.encoding(), dest.encoding());
    1334          15 :     }
    1335           0 :     void subl(const Operand& src, Register dest) {
    1336           0 :         switch (src.kind()) {
    1337             :           case Operand::REG:
    1338           0 :             masm.subl_rr(src.reg(), dest.encoding());
    1339           0 :             break;
    1340             :           case Operand::MEM_REG_DISP:
    1341           0 :             masm.subl_mr(src.disp(), src.base(), dest.encoding());
    1342           0 :             break;
    1343             :           default:
    1344           0 :             MOZ_CRASH("unexpected operand kind");
    1345             :         }
    1346           0 :     }
    1347           0 :     void subl(Register src, const Operand& dest) {
    1348           0 :         switch (dest.kind()) {
    1349             :           case Operand::REG:
    1350           0 :             masm.subl_rr(src.encoding(), dest.reg());
    1351           0 :             break;
    1352             :           case Operand::MEM_REG_DISP:
    1353           0 :             masm.subl_rm(src.encoding(), dest.disp(), dest.base());
    1354           0 :             break;
    1355             :           case Operand::MEM_SCALE:
    1356           0 :             masm.subl_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
    1357           0 :             break;
    1358             :           default:
    1359           0 :             MOZ_CRASH("unexpected operand kind");
    1360             :         }
    1361           0 :     }
    1362           0 :     void subw(Register src, const Operand& dest) {
    1363           0 :         switch (dest.kind()) {
    1364             :           case Operand::REG:
    1365           0 :             masm.subw_rr(src.encoding(), dest.reg());
    1366           0 :             break;
    1367             :           case Operand::MEM_REG_DISP:
    1368           0 :             masm.subw_rm(src.encoding(), dest.disp(), dest.base());
    1369           0 :             break;
    1370             :           case Operand::MEM_SCALE:
    1371           0 :             masm.subw_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
    1372           0 :             break;
    1373             :           default:
    1374           0 :             MOZ_CRASH("unexpected operand kind");
    1375             :         }
    1376           0 :     }
    1377           0 :     void orl(Register reg, Register dest) {
    1378           0 :         masm.orl_rr(reg.encoding(), dest.encoding());
    1379           0 :     }
    1380           0 :     void orl(Register src, const Operand& dest) {
    1381           0 :         switch (dest.kind()) {
    1382             :           case Operand::REG:
    1383           0 :             masm.orl_rr(src.encoding(), dest.reg());
    1384           0 :             break;
    1385             :           case Operand::MEM_REG_DISP:
    1386           0 :             masm.orl_rm(src.encoding(), dest.disp(), dest.base());
    1387           0 :             break;
    1388             :           case Operand::MEM_SCALE:
    1389           0 :             masm.orl_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
    1390           0 :             break;
    1391             :           default:
    1392           0 :             MOZ_CRASH("unexpected operand kind");
    1393             :         }
    1394           0 :     }
    1395           0 :     void orw(Register src, const Operand& dest) {
    1396           0 :         switch (dest.kind()) {
    1397             :           case Operand::REG:
    1398           0 :             masm.orw_rr(src.encoding(), dest.reg());
    1399           0 :             break;
    1400             :           case Operand::MEM_REG_DISP:
    1401           0 :             masm.orw_rm(src.encoding(), dest.disp(), dest.base());
    1402           0 :             break;
    1403             :           case Operand::MEM_SCALE:
    1404           0 :             masm.orw_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
    1405           0 :             break;
    1406             :           default:
    1407           0 :             MOZ_CRASH("unexpected operand kind");
    1408             :         }
    1409           0 :     }
    1410           0 :     void orl(Imm32 imm, Register reg) {
    1411           0 :         masm.orl_ir(imm.value, reg.encoding());
    1412           0 :     }
    1413         185 :     void orl(Imm32 imm, const Operand& op) {
    1414         185 :         switch (op.kind()) {
    1415             :           case Operand::REG:
    1416           0 :             masm.orl_ir(imm.value, op.reg());
    1417           0 :             break;
    1418             :           case Operand::MEM_REG_DISP:
    1419         185 :             masm.orl_im(imm.value, op.disp(), op.base());
    1420         185 :             break;
    1421             :           case Operand::MEM_SCALE:
    1422           0 :             masm.orl_im(imm.value, op.disp(), op.base(), op.index(), op.scale());
    1423           0 :             break;
    1424             :           default:
    1425           0 :             MOZ_CRASH("unexpected operand kind");
    1426             :         }
    1427         185 :     }
    1428           0 :     void orw(Imm32 imm, const Operand& op) {
    1429           0 :         switch (op.kind()) {
    1430             :           case Operand::REG:
    1431           0 :             masm.orw_ir(imm.value, op.reg());
    1432           0 :             break;
    1433             :           case Operand::MEM_REG_DISP:
    1434           0 :             masm.orw_im(imm.value, op.disp(), op.base());
    1435           0 :             break;
    1436             :           case Operand::MEM_SCALE:
    1437           0 :             masm.orw_im(imm.value, op.disp(), op.base(), op.index(), op.scale());
    1438           0 :             break;
    1439             :           default:
    1440           0 :             MOZ_CRASH("unexpected operand kind");
    1441             :         }
    1442           0 :     }
    1443        1199 :     void xorl(Register src, Register dest) {
    1444        1199 :         masm.xorl_rr(src.encoding(), dest.encoding());
    1445        1199 :     }
    1446           0 :     void xorl(Register src, const Operand& dest) {
    1447           0 :         switch (dest.kind()) {
    1448             :           case Operand::REG:
    1449           0 :             masm.xorl_rr(src.encoding(), dest.reg());
    1450           0 :             break;
    1451             :           case Operand::MEM_REG_DISP:
    1452           0 :             masm.xorl_rm(src.encoding(), dest.disp(), dest.base());
    1453           0 :             break;
    1454             :           case Operand::MEM_SCALE:
    1455           0 :             masm.xorl_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
    1456           0 :             break;
    1457             :           default:
    1458           0 :             MOZ_CRASH("unexpected operand kind");
    1459             :         }
    1460           0 :     }
    1461           0 :     void xorw(Register src, const Operand& dest) {
    1462           0 :         switch (dest.kind()) {
    1463             :           case Operand::REG:
    1464           0 :             masm.xorw_rr(src.encoding(), dest.reg());
    1465           0 :             break;
    1466             :           case Operand::MEM_REG_DISP:
    1467           0 :             masm.xorw_rm(src.encoding(), dest.disp(), dest.base());
    1468           0 :             break;
    1469             :           case Operand::MEM_SCALE:
    1470           0 :             masm.xorw_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
    1471           0 :             break;
    1472             :           default:
    1473           0 :             MOZ_CRASH("unexpected operand kind");
    1474             :         }
    1475           0 :     }
    1476          37 :     void xorl(Imm32 imm, Register reg) {
    1477          37 :         masm.xorl_ir(imm.value, reg.encoding());
    1478          37 :     }
    1479           0 :     void xorl(Imm32 imm, const Operand& op) {
    1480           0 :         switch (op.kind()) {
    1481             :           case Operand::REG:
    1482           0 :             masm.xorl_ir(imm.value, op.reg());
    1483           0 :             break;
    1484             :           case Operand::MEM_REG_DISP:
    1485           0 :             masm.xorl_im(imm.value, op.disp(), op.base());
    1486           0 :             break;
    1487             :           case Operand::MEM_SCALE:
    1488           0 :             masm.xorl_im(imm.value, op.disp(), op.base(), op.index(), op.scale());
    1489           0 :             break;
    1490             :           default:
    1491           0 :             MOZ_CRASH("unexpected operand kind");
    1492             :         }
    1493           0 :     }
    1494           0 :     void xorw(Imm32 imm, const Operand& op) {
    1495           0 :         switch (op.kind()) {
    1496             :           case Operand::REG:
    1497           0 :             masm.xorw_ir(imm.value, op.reg());
    1498           0 :             break;
    1499             :           case Operand::MEM_REG_DISP:
    1500           0 :             masm.xorw_im(imm.value, op.disp(), op.base());
    1501           0 :             break;
    1502             :           case Operand::MEM_SCALE:
    1503           0 :             masm.xorw_im(imm.value, op.disp(), op.base(), op.index(), op.scale());
    1504           0 :             break;
    1505             :           default:
    1506           0 :             MOZ_CRASH("unexpected operand kind");
    1507             :         }
    1508           0 :     }
    1509         164 :     void andl(Register src, Register dest) {
    1510         164 :         masm.andl_rr(src.encoding(), dest.encoding());
    1511         164 :     }
    1512           0 :     void andl(Register src, const Operand& dest) {
    1513           0 :         switch (dest.kind()) {
    1514             :           case Operand::REG:
    1515           0 :             masm.andl_rr(src.encoding(), dest.reg());
    1516           0 :             break;
    1517             :           case Operand::MEM_REG_DISP:
    1518           0 :             masm.andl_rm(src.encoding(), dest.disp(), dest.base());
    1519           0 :             break;
    1520             :           case Operand::MEM_SCALE:
    1521           0 :             masm.andl_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
    1522           0 :             break;
    1523             :           default:
    1524           0 :             MOZ_CRASH("unexpected operand kind");
    1525             :         }
    1526           0 :     }
    1527           0 :     void andw(Register src, const Operand& dest) {
    1528           0 :         switch (dest.kind()) {
    1529             :           case Operand::REG:
    1530           0 :             masm.andw_rr(src.encoding(), dest.reg());
    1531           0 :             break;
    1532             :           case Operand::MEM_REG_DISP:
    1533           0 :             masm.andw_rm(src.encoding(), dest.disp(), dest.base());
    1534           0 :             break;
    1535             :           case Operand::MEM_SCALE:
    1536           0 :             masm.andw_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
    1537           0 :             break;
    1538             :           default:
    1539           0 :             MOZ_CRASH("unexpected operand kind");
    1540             :         }
    1541           0 :     }
    1542         204 :     void andl(Imm32 imm, Register dest) {
    1543         204 :         masm.andl_ir(imm.value, dest.encoding());
    1544         204 :     }
    1545           0 :     void andl(Imm32 imm, const Operand& op) {
    1546           0 :         switch (op.kind()) {
    1547             :           case Operand::REG:
    1548           0 :             masm.andl_ir(imm.value, op.reg());
    1549           0 :             break;
    1550             :           case Operand::MEM_REG_DISP:
    1551           0 :             masm.andl_im(imm.value, op.disp(), op.base());
    1552           0 :             break;
    1553             :           case Operand::MEM_SCALE:
    1554           0 :             masm.andl_im(imm.value, op.disp(), op.base(), op.index(), op.scale());
    1555           0 :             break;
    1556             :           default:
    1557           0 :             MOZ_CRASH("unexpected operand kind");
    1558             :         }
    1559           0 :     }
    1560           0 :     void andw(Imm32 imm, const Operand& op) {
    1561           0 :         switch (op.kind()) {
    1562             :           case Operand::REG:
    1563           0 :             masm.andw_ir(imm.value, op.reg());
    1564           0 :             break;
    1565             :           case Operand::MEM_REG_DISP:
    1566           0 :             masm.andw_im(imm.value, op.disp(), op.base());
    1567           0 :             break;
    1568             :           case Operand::MEM_SCALE:
    1569           0 :             masm.andw_im(imm.value, op.disp(), op.base(), op.index(), op.scale());
    1570           0 :             break;
    1571             :           default:
    1572           0 :             MOZ_CRASH("unexpected operand kind");
    1573             :         }
    1574           0 :     }
    1575           0 :     void addl(const Operand& src, Register dest) {
    1576           0 :         switch (src.kind()) {
    1577             :           case Operand::REG:
    1578           0 :             masm.addl_rr(src.reg(), dest.encoding());
    1579           0 :             break;
    1580             :           case Operand::MEM_REG_DISP:
    1581           0 :             masm.addl_mr(src.disp(), src.base(), dest.encoding());
    1582           0 :             break;
    1583             :           default:
    1584           0 :             MOZ_CRASH("unexpected operand kind");
    1585             :         }
    1586           0 :     }
    1587           0 :     void orl(const Operand& src, Register dest) {
    1588           0 :         switch (src.kind()) {
    1589             :           case Operand::REG:
    1590           0 :             masm.orl_rr(src.reg(), dest.encoding());
    1591           0 :             break;
    1592             :           case Operand::MEM_REG_DISP:
    1593           0 :             masm.orl_mr(src.disp(), src.base(), dest.encoding());
    1594           0 :             break;
    1595             :           default:
    1596           0 :             MOZ_CRASH("unexpected operand kind");
    1597             :         }
    1598           0 :     }
    1599           0 :     void xorl(const Operand& src, Register dest) {
    1600           0 :         switch (src.kind()) {
    1601             :           case Operand::REG:
    1602           0 :             masm.xorl_rr(src.reg(), dest.encoding());
    1603           0 :             break;
    1604             :           case Operand::MEM_REG_DISP:
    1605           0 :             masm.xorl_mr(src.disp(), src.base(), dest.encoding());
    1606           0 :             break;
    1607             :           default:
    1608           0 :             MOZ_CRASH("unexpected operand kind");
    1609             :         }
    1610           0 :     }
    1611           4 :     void andl(const Operand& src, Register dest) {
    1612           4 :         switch (src.kind()) {
    1613             :           case Operand::REG:
    1614           0 :             masm.andl_rr(src.reg(), dest.encoding());
    1615           0 :             break;
    1616             :           case Operand::MEM_REG_DISP:
    1617           4 :             masm.andl_mr(src.disp(), src.base(), dest.encoding());
    1618           4 :             break;
    1619             :           default:
    1620           0 :             MOZ_CRASH("unexpected operand kind");
    1621             :         }
    1622           4 :     }
    1623           0 :     void bsrl(const Register& src, const Register& dest) {
    1624           0 :         masm.bsrl_rr(src.encoding(), dest.encoding());
    1625           0 :     }
    1626           0 :     void bsfl(const Register& src, const Register& dest) {
    1627           0 :         masm.bsfl_rr(src.encoding(), dest.encoding());
    1628           0 :     }
    1629           0 :     void popcntl(const Register& src, const Register& dest) {
    1630           0 :         masm.popcntl_rr(src.encoding(), dest.encoding());
    1631           0 :     }
    1632           0 :     void imull(Register multiplier) {
    1633           0 :         masm.imull_r(multiplier.encoding());
    1634           0 :     }
    1635           0 :     void umull(Register multiplier) {
    1636           0 :         masm.mull_r(multiplier.encoding());
    1637           0 :     }
    1638           0 :     void imull(Imm32 imm, Register dest) {
    1639           0 :         masm.imull_ir(imm.value, dest.encoding(), dest.encoding());
    1640           0 :     }
    1641           0 :     void imull(Register src, Register dest) {
    1642           0 :         masm.imull_rr(src.encoding(), dest.encoding());
    1643           0 :     }
    1644           0 :     void imull(Imm32 imm, Register src, Register dest) {
    1645           0 :         masm.imull_ir(imm.value, src.encoding(), dest.encoding());
    1646           0 :     }
    1647           0 :     void imull(const Operand& src, Register dest) {
    1648           0 :         switch (src.kind()) {
    1649             :           case Operand::REG:
    1650           0 :             masm.imull_rr(src.reg(), dest.encoding());
    1651           0 :             break;
    1652             :           case Operand::MEM_REG_DISP:
    1653           0 :             masm.imull_mr(src.disp(), src.base(), dest.encoding());
    1654           0 :             break;
    1655             :           default:
    1656           0 :             MOZ_CRASH("unexpected operand kind");
    1657             :         }
    1658           0 :     }
    1659           0 :     void negl(const Operand& src) {
    1660           0 :         switch (src.kind()) {
    1661             :           case Operand::REG:
    1662           0 :             masm.negl_r(src.reg());
    1663           0 :             break;
    1664             :           case Operand::MEM_REG_DISP:
    1665           0 :             masm.negl_m(src.disp(), src.base());
    1666           0 :             break;
    1667             :           default:
    1668           0 :             MOZ_CRASH("unexpected operand kind");
    1669             :         }
    1670           0 :     }
    1671           0 :     void negl(Register reg) {
    1672           0 :         masm.negl_r(reg.encoding());
    1673           0 :     }
    1674           0 :     void notl(const Operand& src) {
    1675           0 :         switch (src.kind()) {
    1676             :           case Operand::REG:
    1677           0 :             masm.notl_r(src.reg());
    1678           0 :             break;
    1679             :           case Operand::MEM_REG_DISP:
    1680           0 :             masm.notl_m(src.disp(), src.base());
    1681           0 :             break;
    1682             :           default:
    1683           0 :             MOZ_CRASH("unexpected operand kind");
    1684             :         }
    1685           0 :     }
    1686           1 :     void notl(Register reg) {
    1687           1 :         masm.notl_r(reg.encoding());
    1688           1 :     }
    1689           2 :     void shrl(const Imm32 imm, Register dest) {
    1690           2 :         masm.shrl_ir(imm.value, dest.encoding());
    1691           2 :     }
    1692          12 :     void shll(const Imm32 imm, Register dest) {
    1693          12 :         masm.shll_ir(imm.value, dest.encoding());
    1694          12 :     }
    1695           0 :     void sarl(const Imm32 imm, Register dest) {
    1696           0 :         masm.sarl_ir(imm.value, dest.encoding());
    1697           0 :     }
    1698           0 :     void shrl_cl(Register dest) {
    1699           0 :         masm.shrl_CLr(dest.encoding());
    1700           0 :     }
    1701           0 :     void shll_cl(Register dest) {
    1702           0 :         masm.shll_CLr(dest.encoding());
    1703           0 :     }
    1704           0 :     void sarl_cl(Register dest) {
    1705           0 :         masm.sarl_CLr(dest.encoding());
    1706           0 :     }
    1707             :     void shrdl_cl(Register src, Register dest) {
    1708             :         masm.shrdl_CLr(src.encoding(), dest.encoding());
    1709             :     }
    1710             :     void shldl_cl(Register src, Register dest) {
    1711             :         masm.shldl_CLr(src.encoding(), dest.encoding());
    1712             :     }
    1713             : 
    1714           0 :     void roll(const Imm32 imm, Register dest) {
    1715           0 :         masm.roll_ir(imm.value, dest.encoding());
    1716           0 :     }
    1717           0 :     void roll_cl(Register dest) {
    1718           0 :         masm.roll_CLr(dest.encoding());
    1719           0 :     }
    1720           0 :     void rorl(const Imm32 imm, Register dest) {
    1721           0 :         masm.rorl_ir(imm.value, dest.encoding());
    1722           0 :     }
    1723           0 :     void rorl_cl(Register dest) {
    1724           0 :         masm.rorl_CLr(dest.encoding());
    1725           0 :     }
    1726             : 
    1727             :     void incl(const Operand& op) {
    1728             :         switch (op.kind()) {
    1729             :           case Operand::MEM_REG_DISP:
    1730             :             masm.incl_m32(op.disp(), op.base());
    1731             :             break;
    1732             :           default:
    1733             :             MOZ_CRASH("unexpected operand kind");
    1734             :         }
    1735             :     }
    1736             :     void lock_incl(const Operand& op) {
    1737             :         masm.prefix_lock();
    1738             :         incl(op);
    1739             :     }
    1740             : 
    1741             :     void decl(const Operand& op) {
    1742             :         switch (op.kind()) {
    1743             :           case Operand::MEM_REG_DISP:
    1744             :             masm.decl_m32(op.disp(), op.base());
    1745             :             break;
    1746             :           default:
    1747             :             MOZ_CRASH("unexpected operand kind");
    1748             :         }
    1749             :     }
    1750             :     void lock_decl(const Operand& op) {
    1751             :         masm.prefix_lock();
    1752             :         decl(op);
    1753             :     }
    1754             : 
    1755           0 :     void addb(Imm32 imm, const Operand& op) {
    1756           0 :         switch (op.kind()) {
    1757             :           case Operand::MEM_REG_DISP:
    1758           0 :             masm.addb_im(imm.value, op.disp(), op.base());
    1759           0 :             break;
    1760             :           case Operand::MEM_SCALE:
    1761           0 :             masm.addb_im(imm.value, op.disp(), op.base(), op.index(), op.scale());
    1762           0 :             break;
    1763             :           default:
    1764           0 :             MOZ_CRASH("unexpected operand kind");
    1765             :             break;
    1766             :         }
    1767           0 :     }
    1768           0 :     void addb(Register src, const Operand& op) {
    1769           0 :         switch (op.kind()) {
    1770             :           case Operand::MEM_REG_DISP:
    1771           0 :             masm.addb_rm(src.encoding(), op.disp(), op.base());
    1772           0 :             break;
    1773             :           case Operand::MEM_SCALE:
    1774           0 :             masm.addb_rm(src.encoding(), op.disp(), op.base(), op.index(), op.scale());
    1775           0 :             break;
    1776             :           default:
    1777           0 :             MOZ_CRASH("unexpected operand kind");
    1778             :             break;
    1779             :         }
    1780           0 :     }
    1781             : 
    1782           0 :     void subb(Imm32 imm, const Operand& op) {
    1783           0 :         switch (op.kind()) {
    1784             :           case Operand::MEM_REG_DISP:
    1785           0 :             masm.subb_im(imm.value, op.disp(), op.base());
    1786           0 :             break;
    1787             :           case Operand::MEM_SCALE:
    1788           0 :             masm.subb_im(imm.value, op.disp(), op.base(), op.index(), op.scale());
    1789           0 :             break;
    1790             :           default:
    1791           0 :             MOZ_CRASH("unexpected operand kind");
    1792             :             break;
    1793             :         }
    1794           0 :     }
    1795           0 :     void subb(Register src, const Operand& op) {
    1796           0 :         switch (op.kind()) {
    1797             :           case Operand::MEM_REG_DISP:
    1798           0 :             masm.subb_rm(src.encoding(), op.disp(), op.base());
    1799           0 :             break;
    1800             :           case Operand::MEM_SCALE:
    1801           0 :             masm.subb_rm(src.encoding(), op.disp(), op.base(), op.index(), op.scale());
    1802           0 :             break;
    1803             :           default:
    1804           0 :             MOZ_CRASH("unexpected operand kind");
    1805             :             break;
    1806             :         }
    1807           0 :     }
    1808             : 
    1809           0 :     void andb(Imm32 imm, const Operand& op) {
    1810           0 :         switch (op.kind()) {
    1811             :           case Operand::MEM_REG_DISP:
    1812           0 :             masm.andb_im(imm.value, op.disp(), op.base());
    1813           0 :             break;
    1814             :           case Operand::MEM_SCALE:
    1815           0 :             masm.andb_im(imm.value, op.disp(), op.base(), op.index(), op.scale());
    1816           0 :             break;
    1817             :           default:
    1818           0 :             MOZ_CRASH("unexpected operand kind");
    1819             :             break;
    1820             :         }
    1821           0 :     }
    1822           0 :     void andb(Register src, const Operand& op) {
    1823           0 :         switch (op.kind()) {
    1824             :           case Operand::MEM_REG_DISP:
    1825           0 :             masm.andb_rm(src.encoding(), op.disp(), op.base());
    1826           0 :             break;
    1827             :           case Operand::MEM_SCALE:
    1828           0 :             masm.andb_rm(src.encoding(), op.disp(), op.base(), op.index(), op.scale());
    1829           0 :             break;
    1830             :           default:
    1831           0 :             MOZ_CRASH("unexpected operand kind");
    1832             :             break;
    1833             :         }
    1834           0 :     }
    1835             : 
    1836           0 :     void orb(Imm32 imm, const Operand& op) {
    1837           0 :         switch (op.kind()) {
    1838             :           case Operand::MEM_REG_DISP:
    1839           0 :             masm.orb_im(imm.value, op.disp(), op.base());
    1840           0 :             break;
    1841             :           case Operand::MEM_SCALE:
    1842           0 :             masm.orb_im(imm.value, op.disp(), op.base(), op.index(), op.scale());
    1843           0 :             break;
    1844             :           default:
    1845           0 :             MOZ_CRASH("unexpected operand kind");
    1846             :             break;
    1847             :         }
    1848           0 :     }
    1849           0 :     void orb(Register src, const Operand& op) {
    1850           0 :         switch (op.kind()) {
    1851             :           case Operand::MEM_REG_DISP:
    1852           0 :             masm.orb_rm(src.encoding(), op.disp(), op.base());
    1853           0 :             break;
    1854             :           case Operand::MEM_SCALE:
    1855           0 :             masm.orb_rm(src.encoding(), op.disp(), op.base(), op.index(), op.scale());
    1856           0 :             break;
    1857             :           default:
    1858           0 :             MOZ_CRASH("unexpected operand kind");
    1859             :             break;
    1860             :         }
    1861           0 :     }
    1862             : 
    1863           0 :     void xorb(Imm32 imm, const Operand& op) {
    1864           0 :         switch (op.kind()) {
    1865             :           case Operand::MEM_REG_DISP:
    1866           0 :             masm.xorb_im(imm.value, op.disp(), op.base());
    1867           0 :             break;
    1868             :           case Operand::MEM_SCALE:
    1869           0 :             masm.xorb_im(imm.value, op.disp(), op.base(), op.index(), op.scale());
    1870           0 :             break;
    1871             :           default:
    1872           0 :             MOZ_CRASH("unexpected operand kind");
    1873             :             break;
    1874             :         }
    1875           0 :     }
    1876           0 :     void xorb(Register src, const Operand& op) {
    1877           0 :         switch (op.kind()) {
    1878             :           case Operand::MEM_REG_DISP:
    1879           0 :             masm.xorb_rm(src.encoding(), op.disp(), op.base());
    1880           0 :             break;
    1881             :           case Operand::MEM_SCALE:
    1882           0 :             masm.xorb_rm(src.encoding(), op.disp(), op.base(), op.index(), op.scale());
    1883           0 :             break;
    1884             :           default:
    1885           0 :             MOZ_CRASH("unexpected operand kind");
    1886             :             break;
    1887             :         }
    1888           0 :     }
    1889             : 
    1890             :     template<typename T>
    1891           0 :     void lock_addb(T src, const Operand& op) {
    1892           0 :         masm.prefix_lock();
    1893           0 :         addb(src, op);
    1894           0 :     }
    1895             :     template<typename T>
    1896           0 :     void lock_subb(T src, const Operand& op) {
    1897           0 :         masm.prefix_lock();
    1898           0 :         subb(src, op);
    1899           0 :     }
    1900             :     template<typename T>
    1901           0 :     void lock_andb(T src, const Operand& op) {
    1902           0 :         masm.prefix_lock();
    1903           0 :         andb(src, op);
    1904           0 :     }
    1905             :     template<typename T>
    1906           0 :     void lock_orb(T src, const Operand& op) {
    1907           0 :         masm.prefix_lock();
    1908           0 :         orb(src, op);
    1909           0 :     }
    1910             :     template<typename T>
    1911           0 :     void lock_xorb(T src, const Operand& op) {
    1912           0 :         masm.prefix_lock();
    1913           0 :         xorb(src, op);
    1914           0 :     }
    1915             : 
    1916             :     template<typename T>
    1917           0 :     void lock_addw(T src, const Operand& op) {
    1918           0 :         masm.prefix_lock();
    1919           0 :         addw(src, op);
    1920           0 :     }
    1921             :     template<typename T>
    1922           0 :     void lock_subw(T src, const Operand& op) {
    1923           0 :         masm.prefix_lock();
    1924           0 :         subw(src, op);
    1925           0 :     }
    1926             :     template<typename T>
    1927           0 :     void lock_andw(T src, const Operand& op) {
    1928           0 :         masm.prefix_lock();
    1929           0 :         andw(src, op);
    1930           0 :     }
    1931             :     template<typename T>
    1932           0 :     void lock_orw(T src, const Operand& op) {
    1933           0 :         masm.prefix_lock();
    1934           0 :         orw(src, op);
    1935           0 :     }
    1936             :     template<typename T>
    1937           0 :     void lock_xorw(T src, const Operand& op) {
    1938           0 :         masm.prefix_lock();
    1939           0 :         xorw(src, op);
    1940           0 :     }
    1941             : 
    1942             :     // Note, lock_addl(imm, op) is used for a memory barrier on non-SSE2 systems,
    1943             :     // among other things.  Do not optimize, replace by XADDL, or similar.
    1944             :     template<typename T>
    1945           0 :     void lock_addl(T src, const Operand& op) {
    1946           0 :         masm.prefix_lock();
    1947           0 :         addl(src, op);
    1948           0 :     }
    1949             :     template<typename T>
    1950           0 :     void lock_subl(T src, const Operand& op) {
    1951           0 :         masm.prefix_lock();
    1952           0 :         subl(src, op);
    1953           0 :     }
    1954             :     template<typename T>
    1955           0 :     void lock_andl(T src, const Operand& op) {
    1956           0 :         masm.prefix_lock();
    1957           0 :         andl(src, op);
    1958           0 :     }
    1959             :     template<typename T>
    1960           0 :     void lock_orl(T src, const Operand& op) {
    1961           0 :         masm.prefix_lock();
    1962           0 :         orl(src, op);
    1963           0 :     }
    1964             :     template<typename T>
    1965           0 :     void lock_xorl(T src, const Operand& op) {
    1966           0 :         masm.prefix_lock();
    1967           0 :         xorl(src, op);
    1968           0 :     }
    1969             : 
    1970           0 :     void lock_cmpxchgb(Register src, const Operand& mem) {
    1971           0 :         masm.prefix_lock();
    1972           0 :         switch (mem.kind()) {
    1973             :           case Operand::MEM_REG_DISP:
    1974           0 :             masm.cmpxchgb(src.encoding(), mem.disp(), mem.base());
    1975           0 :             break;
    1976             :           case Operand::MEM_SCALE:
    1977           0 :             masm.cmpxchgb(src.encoding(), mem.disp(), mem.base(), mem.index(), mem.scale());
    1978           0 :             break;
    1979             :           default:
    1980           0 :             MOZ_CRASH("unexpected operand kind");
    1981             :         }
    1982           0 :     }
    1983           0 :     void lock_cmpxchgw(Register src, const Operand& mem) {
    1984           0 :         masm.prefix_lock();
    1985           0 :         switch (mem.kind()) {
    1986             :           case Operand::MEM_REG_DISP:
    1987           0 :             masm.cmpxchgw(src.encoding(), mem.disp(), mem.base());
    1988           0 :             break;
    1989             :           case Operand::MEM_SCALE:
    1990           0 :             masm.cmpxchgw(src.encoding(), mem.disp(), mem.base(), mem.index(), mem.scale());
    1991           0 :             break;
    1992             :           default:
    1993           0 :             MOZ_CRASH("unexpected operand kind");
    1994             :         }
    1995           0 :     }
    1996           0 :     void lock_cmpxchgl(Register src, const Operand& mem) {
    1997           0 :         masm.prefix_lock();
    1998           0 :         switch (mem.kind()) {
    1999             :           case Operand::MEM_REG_DISP:
    2000           0 :             masm.cmpxchgl(src.encoding(), mem.disp(), mem.base());
    2001           0 :             break;
    2002             :           case Operand::MEM_SCALE:
    2003           0 :             masm.cmpxchgl(src.encoding(), mem.disp(), mem.base(), mem.index(), mem.scale());
    2004           0 :             break;
    2005             :           default:
    2006           0 :             MOZ_CRASH("unexpected operand kind");
    2007             :         }
    2008           0 :     }
    2009             : 
    2010           0 :     void xchgb(Register src, const Operand& mem) {
    2011           0 :         switch (mem.kind()) {
    2012             :           case Operand::MEM_REG_DISP:
    2013           0 :             masm.xchgb_rm(src.encoding(), mem.disp(), mem.base());
    2014           0 :             break;
    2015             :           case Operand::MEM_SCALE:
    2016           0 :             masm.xchgb_rm(src.encoding(), mem.disp(), mem.base(), mem.index(), mem.scale());
    2017           0 :             break;
    2018             :           default:
    2019           0 :             MOZ_CRASH("unexpected operand kind");
    2020             :         }
    2021           0 :     }
    2022           0 :     void xchgw(Register src, const Operand& mem) {
    2023           0 :         switch (mem.kind()) {
    2024             :           case Operand::MEM_REG_DISP:
    2025           0 :             masm.xchgw_rm(src.encoding(), mem.disp(), mem.base());
    2026           0 :             break;
    2027             :           case Operand::MEM_SCALE:
    2028           0 :             masm.xchgw_rm(src.encoding(), mem.disp(), mem.base(), mem.index(), mem.scale());
    2029           0 :             break;
    2030             :           default:
    2031           0 :             MOZ_CRASH("unexpected operand kind");
    2032             :         }
    2033           0 :     }
    2034           0 :     void xchgl(Register src, const Operand& mem) {
    2035           0 :         switch (mem.kind()) {
    2036             :           case Operand::MEM_REG_DISP:
    2037           0 :             masm.xchgl_rm(src.encoding(), mem.disp(), mem.base());
    2038           0 :             break;
    2039             :           case Operand::MEM_SCALE:
    2040           0 :             masm.xchgl_rm(src.encoding(), mem.disp(), mem.base(), mem.index(), mem.scale());
    2041           0 :             break;
    2042             :           default:
    2043           0 :             MOZ_CRASH("unexpected operand kind");
    2044             :         }
    2045           0 :     }
    2046             : 
    2047           0 :     void lock_xaddb(Register srcdest, const Operand& mem) {
    2048           0 :         switch (mem.kind()) {
    2049             :           case Operand::MEM_REG_DISP:
    2050           0 :             masm.lock_xaddb_rm(srcdest.encoding(), mem.disp(), mem.base());
    2051           0 :             break;
    2052             :           case Operand::MEM_SCALE:
    2053           0 :             masm.lock_xaddb_rm(srcdest.encoding(), mem.disp(), mem.base(), mem.index(), mem.scale());
    2054           0 :             break;
    2055             :           default:
    2056           0 :             MOZ_CRASH("unexpected operand kind");
    2057             :         }
    2058           0 :     }
    2059           0 :     void lock_xaddw(Register srcdest, const Operand& mem) {
    2060           0 :         masm.prefix_16_for_32();
    2061           0 :         lock_xaddl(srcdest, mem);
    2062           0 :     }
    2063           0 :     void lock_xaddl(Register srcdest, const Operand& mem) {
    2064           0 :         switch (mem.kind()) {
    2065             :           case Operand::MEM_REG_DISP:
    2066           0 :             masm.lock_xaddl_rm(srcdest.encoding(), mem.disp(), mem.base());
    2067           0 :             break;
    2068             :           case Operand::MEM_SCALE:
    2069           0 :             masm.lock_xaddl_rm(srcdest.encoding(), mem.disp(), mem.base(), mem.index(), mem.scale());
    2070           0 :             break;
    2071             :           default:
    2072           0 :             MOZ_CRASH("unexpected operand kind");
    2073             :         }
    2074           0 :     }
    2075             : 
    2076        6210 :     void push(const Imm32 imm) {
    2077        6210 :         masm.push_i(imm.value);
    2078        6210 :     }
    2079             : 
    2080        4030 :     void push(const Operand& src) {
    2081        4030 :         switch (src.kind()) {
    2082             :           case Operand::REG:
    2083           0 :             masm.push_r(src.reg());
    2084           0 :             break;
    2085             :           case Operand::MEM_REG_DISP:
    2086        4030 :             masm.push_m(src.disp(), src.base());
    2087        4030 :             break;
    2088             :           default:
    2089           0 :             MOZ_CRASH("unexpected operand kind");
    2090             :         }
    2091        4030 :     }
    2092      143086 :     void push(Register src) {
    2093      143086 :         masm.push_r(src.encoding());
    2094      143090 :     }
    2095          24 :     void push(const Address& src) {
    2096          24 :         masm.push_m(src.offset, src.base.encoding());
    2097          24 :     }
    2098             : 
    2099         665 :     void pop(const Operand& src) {
    2100         665 :         switch (src.kind()) {
    2101             :           case Operand::REG:
    2102           0 :             masm.pop_r(src.reg());
    2103           0 :             break;
    2104             :           case Operand::MEM_REG_DISP:
    2105         665 :             masm.pop_m(src.disp(), src.base());
    2106         665 :             break;
    2107             :           default:
    2108           0 :             MOZ_CRASH("unexpected operand kind");
    2109             :         }
    2110         665 :     }
    2111      117823 :     void pop(Register src) {
    2112      117823 :         masm.pop_r(src.encoding());
    2113      117824 :     }
    2114             :     void pop(const Address& src) {
    2115             :         masm.pop_m(src.offset, src.base.encoding());
    2116             :     }
    2117             : 
    2118           0 :     void pushFlags() {
    2119           0 :         masm.push_flags();
    2120           0 :     }
    2121           0 :     void popFlags() {
    2122           0 :         masm.pop_flags();
    2123           0 :     }
    2124             : 
    2125             : #ifdef JS_CODEGEN_X86
    2126             :     void pushAllRegs() {
    2127             :         masm.pusha();
    2128             :     }
    2129             :     void popAllRegs() {
    2130             :         masm.popa();
    2131             :     }
    2132             : #endif
    2133             : 
    2134             :     // Zero-extend byte to 32-bit integer.
    2135          61 :     void movzbl(Register src, Register dest) {
    2136          61 :         masm.movzbl_rr(src.encoding(), dest.encoding());
    2137          61 :     }
    2138             : 
    2139           0 :     void cdq() {
    2140           0 :         masm.cdq();
    2141           0 :     }
    2142           0 :     void idiv(Register divisor) {
    2143           0 :         masm.idivl_r(divisor.encoding());
    2144           0 :     }
    2145           0 :     void udiv(Register divisor) {
    2146           0 :         masm.divl_r(divisor.encoding());
    2147           0 :     }
    2148             : 
    2149           0 :     void vpinsrb(unsigned lane, Register src1, FloatRegister src0, FloatRegister dest) {
    2150           0 :         MOZ_ASSERT(HasSSE41());
    2151           0 :         masm.vpinsrb_irr(lane, src1.encoding(), src0.encoding(), dest.encoding());
    2152           0 :     }
    2153           0 :     void vpinsrw(unsigned lane, Register src1, FloatRegister src0, FloatRegister dest) {
    2154           0 :         masm.vpinsrw_irr(lane, src1.encoding(), src0.encoding(), dest.encoding());
    2155           0 :     }
    2156             : 
    2157           0 :     void vpinsrd(unsigned lane, Register src1, FloatRegister src0, FloatRegister dest) {
    2158           0 :         MOZ_ASSERT(HasSSE41());
    2159           0 :         masm.vpinsrd_irr(lane, src1.encoding(), src0.encoding(), dest.encoding());
    2160           0 :     }
    2161             : 
    2162           0 :     void vpextrb(unsigned lane, FloatRegister src, Register dest) {
    2163           0 :         MOZ_ASSERT(HasSSE41());
    2164           0 :         masm.vpextrb_irr(lane, src.encoding(), dest.encoding());
    2165           0 :     }
    2166           0 :     void vpextrw(unsigned lane, FloatRegister src, Register dest) {
    2167           0 :         masm.vpextrw_irr(lane, src.encoding(), dest.encoding());
    2168           0 :     }
    2169           0 :     void vpextrd(unsigned lane, FloatRegister src, Register dest) {
    2170           0 :         MOZ_ASSERT(HasSSE41());
    2171           0 :         masm.vpextrd_irr(lane, src.encoding(), dest.encoding());
    2172           0 :     }
    2173             :     void vpsrldq(Imm32 shift, FloatRegister src0, FloatRegister dest) {
    2174             :         MOZ_ASSERT(HasSSE2());
    2175             :         masm.vpsrldq_ir(shift.value, src0.encoding(), dest.encoding());
    2176             :     }
    2177           0 :     void vpsllq(Imm32 shift, FloatRegister src0, FloatRegister dest) {
    2178           0 :         MOZ_ASSERT(HasSSE2());
    2179           0 :         masm.vpsllq_ir(shift.value, src0.encoding(), dest.encoding());
    2180           0 :     }
    2181             :     void vpsrlq(Imm32 shift, FloatRegister src0, FloatRegister dest) {
    2182             :         MOZ_ASSERT(HasSSE2());
    2183             :         masm.vpsrlq_ir(shift.value, src0.encoding(), dest.encoding());
    2184             :     }
    2185           0 :     void vpslld(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    2186           0 :         MOZ_ASSERT(HasSSE2());
    2187           0 :         masm.vpslld_rr(src1.encoding(), src0.encoding(), dest.encoding());
    2188           0 :     }
    2189           0 :     void vpslld(Imm32 count, FloatRegister src0, FloatRegister dest) {
    2190           0 :         MOZ_ASSERT(HasSSE2());
    2191           0 :         masm.vpslld_ir(count.value, src0.encoding(), dest.encoding());
    2192           0 :     }
    2193           0 :     void vpsrad(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    2194           0 :         MOZ_ASSERT(HasSSE2());
    2195           0 :         masm.vpsrad_rr(src1.encoding(), src0.encoding(), dest.encoding());
    2196           0 :     }
    2197           0 :     void vpsrad(Imm32 count, FloatRegister src0, FloatRegister dest) {
    2198           0 :         MOZ_ASSERT(HasSSE2());
    2199           0 :         masm.vpsrad_ir(count.value, src0.encoding(), dest.encoding());
    2200           0 :     }
    2201           0 :     void vpsrld(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    2202           0 :         MOZ_ASSERT(HasSSE2());
    2203           0 :         masm.vpsrld_rr(src1.encoding(), src0.encoding(), dest.encoding());
    2204           0 :     }
    2205           0 :     void vpsrld(Imm32 count, FloatRegister src0, FloatRegister dest) {
    2206           0 :         MOZ_ASSERT(HasSSE2());
    2207           0 :         masm.vpsrld_ir(count.value, src0.encoding(), dest.encoding());
    2208           0 :     }
    2209             : 
    2210           0 :     void vpsllw(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    2211           0 :         MOZ_ASSERT(HasSSE2());
    2212           0 :         masm.vpsllw_rr(src1.encoding(), src0.encoding(), dest.encoding());
    2213           0 :     }
    2214           0 :     void vpsllw(Imm32 count, FloatRegister src0, FloatRegister dest) {
    2215           0 :         MOZ_ASSERT(HasSSE2());
    2216           0 :         masm.vpsllw_ir(count.value, src0.encoding(), dest.encoding());
    2217           0 :     }
    2218           0 :     void vpsraw(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    2219           0 :         MOZ_ASSERT(HasSSE2());
    2220           0 :         masm.vpsraw_rr(src1.encoding(), src0.encoding(), dest.encoding());
    2221           0 :     }
    2222           0 :     void vpsraw(Imm32 count, FloatRegister src0, FloatRegister dest) {
    2223           0 :         MOZ_ASSERT(HasSSE2());
    2224           0 :         masm.vpsraw_ir(count.value, src0.encoding(), dest.encoding());
    2225           0 :     }
    2226           0 :     void vpsrlw(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    2227           0 :         MOZ_ASSERT(HasSSE2());
    2228           0 :         masm.vpsrlw_rr(src1.encoding(), src0.encoding(), dest.encoding());
    2229           0 :     }
    2230           0 :     void vpsrlw(Imm32 count, FloatRegister src0, FloatRegister dest) {
    2231           0 :         MOZ_ASSERT(HasSSE2());
    2232           0 :         masm.vpsrlw_ir(count.value, src0.encoding(), dest.encoding());
    2233           0 :     }
    2234             : 
    2235           0 :     void vcvtsi2sd(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2236           0 :         MOZ_ASSERT(HasSSE2());
    2237           0 :         switch (src1.kind()) {
    2238             :           case Operand::REG:
    2239           0 :             masm.vcvtsi2sd_rr(src1.reg(), src0.encoding(), dest.encoding());
    2240           0 :             break;
    2241             :           case Operand::MEM_REG_DISP:
    2242           0 :             masm.vcvtsi2sd_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2243           0 :             break;
    2244             :           case Operand::MEM_SCALE:
    2245           0 :             masm.vcvtsi2sd_mr(src1.disp(), src1.base(), src1.index(), src1.scale(), src0.encoding(), dest.encoding());
    2246           0 :             break;
    2247             :           default:
    2248           0 :             MOZ_CRASH("unexpected operand kind");
    2249             :         }
    2250           0 :     }
    2251          26 :     void vcvttsd2si(FloatRegister src, Register dest) {
    2252          26 :         MOZ_ASSERT(HasSSE2());
    2253          26 :         masm.vcvttsd2si_rr(src.encoding(), dest.encoding());
    2254          26 :     }
    2255           0 :     void vcvttss2si(FloatRegister src, Register dest) {
    2256           0 :         MOZ_ASSERT(HasSSE2());
    2257           0 :         masm.vcvttss2si_rr(src.encoding(), dest.encoding());
    2258           0 :     }
    2259             :     void vcvtsi2ss(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2260             :         MOZ_ASSERT(HasSSE2());
    2261             :         switch (src1.kind()) {
    2262             :           case Operand::REG:
    2263             :             masm.vcvtsi2ss_rr(src1.reg(), src0.encoding(), dest.encoding());
    2264             :             break;
    2265             :           case Operand::MEM_REG_DISP:
    2266             :             masm.vcvtsi2ss_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2267             :             break;
    2268             :           case Operand::MEM_SCALE:
    2269             :             masm.vcvtsi2ss_mr(src1.disp(), src1.base(), src1.index(), src1.scale(), src0.encoding(), dest.encoding());
    2270             :             break;
    2271             :           default:
    2272             :             MOZ_CRASH("unexpected operand kind");
    2273             :         }
    2274             :     }
    2275           0 :     void vcvtsi2ss(Register src1, FloatRegister src0, FloatRegister dest) {
    2276           0 :         MOZ_ASSERT(HasSSE2());
    2277           0 :         masm.vcvtsi2ss_rr(src1.encoding(), src0.encoding(), dest.encoding());
    2278           0 :     }
    2279          58 :     void vcvtsi2sd(Register src1, FloatRegister src0, FloatRegister dest) {
    2280          58 :         MOZ_ASSERT(HasSSE2());
    2281          58 :         masm.vcvtsi2sd_rr(src1.encoding(), src0.encoding(), dest.encoding());
    2282          58 :     }
    2283           0 :     void vcvttps2dq(FloatRegister src, FloatRegister dest) {
    2284           0 :         MOZ_ASSERT(HasSSE2());
    2285           0 :         masm.vcvttps2dq_rr(src.encoding(), dest.encoding());
    2286           0 :     }
    2287           0 :     void vcvtdq2ps(FloatRegister src, FloatRegister dest) {
    2288           0 :         MOZ_ASSERT(HasSSE2());
    2289           0 :         masm.vcvtdq2ps_rr(src.encoding(), dest.encoding());
    2290           0 :     }
    2291           0 :     void vmovmskpd(FloatRegister src, Register dest) {
    2292           0 :         MOZ_ASSERT(HasSSE2());
    2293           0 :         masm.vmovmskpd_rr(src.encoding(), dest.encoding());
    2294           0 :     }
    2295           0 :     void vmovmskps(FloatRegister src, Register dest) {
    2296           0 :         MOZ_ASSERT(HasSSE2());
    2297           0 :         masm.vmovmskps_rr(src.encoding(), dest.encoding());
    2298           0 :     }
    2299           0 :     void vpmovmskb(FloatRegister src, Register dest) {
    2300           0 :         MOZ_ASSERT(HasSSE2());
    2301           0 :         masm.vpmovmskb_rr(src.encoding(), dest.encoding());
    2302           0 :     }
    2303             :     void vptest(FloatRegister rhs, FloatRegister lhs) {
    2304             :         MOZ_ASSERT(HasSSE41());
    2305             :         masm.vptest_rr(rhs.encoding(), lhs.encoding());
    2306             :     }
    2307          38 :     void vucomisd(FloatRegister rhs, FloatRegister lhs) {
    2308          38 :         MOZ_ASSERT(HasSSE2());
    2309          38 :         masm.vucomisd_rr(rhs.encoding(), lhs.encoding());
    2310          38 :     }
    2311           0 :     void vucomiss(FloatRegister rhs, FloatRegister lhs) {
    2312           0 :         MOZ_ASSERT(HasSSE2());
    2313           0 :         masm.vucomiss_rr(rhs.encoding(), lhs.encoding());
    2314           0 :     }
    2315             : 
    2316           0 :     void vpcmpeqb(const Operand& rhs, FloatRegister lhs, FloatRegister dest) {
    2317           0 :         MOZ_ASSERT(HasSSE2());
    2318           0 :         switch (rhs.kind()) {
    2319             :           case Operand::FPREG:
    2320           0 :             masm.vpcmpeqb_rr(rhs.fpu(), lhs.encoding(), dest.encoding());
    2321           0 :             break;
    2322             :           case Operand::MEM_REG_DISP:
    2323           0 :             masm.vpcmpeqb_mr(rhs.disp(), rhs.base(), lhs.encoding(), dest.encoding());
    2324           0 :             break;
    2325             :           case Operand::MEM_ADDRESS32:
    2326           0 :             masm.vpcmpeqb_mr(rhs.address(), lhs.encoding(), dest.encoding());
    2327           0 :             break;
    2328             :           default:
    2329           0 :             MOZ_CRASH("unexpected operand kind");
    2330             :         }
    2331           0 :     }
    2332           0 :     void vpcmpgtb(const Operand& rhs, FloatRegister lhs, FloatRegister dest) {
    2333           0 :         MOZ_ASSERT(HasSSE2());
    2334           0 :         switch (rhs.kind()) {
    2335             :           case Operand::FPREG:
    2336           0 :             masm.vpcmpgtb_rr(rhs.fpu(), lhs.encoding(), dest.encoding());
    2337           0 :             break;
    2338             :           case Operand::MEM_REG_DISP:
    2339           0 :             masm.vpcmpgtb_mr(rhs.disp(), rhs.base(), lhs.encoding(), dest.encoding());
    2340           0 :             break;
    2341             :           case Operand::MEM_ADDRESS32:
    2342           0 :             masm.vpcmpgtb_mr(rhs.address(), lhs.encoding(), dest.encoding());
    2343           0 :             break;
    2344             :           default:
    2345           0 :             MOZ_CRASH("unexpected operand kind");
    2346             :         }
    2347           0 :     }
    2348             : 
    2349           0 :     void vpcmpeqw(const Operand& rhs, FloatRegister lhs, FloatRegister dest) {
    2350           0 :         MOZ_ASSERT(HasSSE2());
    2351           0 :         switch (rhs.kind()) {
    2352             :           case Operand::FPREG:
    2353           0 :             masm.vpcmpeqw_rr(rhs.fpu(), lhs.encoding(), dest.encoding());
    2354           0 :             break;
    2355             :           case Operand::MEM_REG_DISP:
    2356           0 :             masm.vpcmpeqw_mr(rhs.disp(), rhs.base(), lhs.encoding(), dest.encoding());
    2357           0 :             break;
    2358             :           case Operand::MEM_ADDRESS32:
    2359           0 :             masm.vpcmpeqw_mr(rhs.address(), lhs.encoding(), dest.encoding());
    2360           0 :             break;
    2361             :           default:
    2362           0 :             MOZ_CRASH("unexpected operand kind");
    2363             :         }
    2364           0 :     }
    2365           0 :     void vpcmpgtw(const Operand& rhs, FloatRegister lhs, FloatRegister dest) {
    2366           0 :         MOZ_ASSERT(HasSSE2());
    2367           0 :         switch (rhs.kind()) {
    2368             :           case Operand::FPREG:
    2369           0 :             masm.vpcmpgtw_rr(rhs.fpu(), lhs.encoding(), dest.encoding());
    2370           0 :             break;
    2371             :           case Operand::MEM_REG_DISP:
    2372           0 :             masm.vpcmpgtw_mr(rhs.disp(), rhs.base(), lhs.encoding(), dest.encoding());
    2373           0 :             break;
    2374             :           case Operand::MEM_ADDRESS32:
    2375           0 :             masm.vpcmpgtw_mr(rhs.address(), lhs.encoding(), dest.encoding());
    2376           0 :             break;
    2377             :           default:
    2378           0 :             MOZ_CRASH("unexpected operand kind");
    2379             :         }
    2380           0 :     }
    2381             : 
    2382           0 :     void vpcmpeqd(const Operand& rhs, FloatRegister lhs, FloatRegister dest) {
    2383           0 :         MOZ_ASSERT(HasSSE2());
    2384           0 :         switch (rhs.kind()) {
    2385             :           case Operand::FPREG:
    2386           0 :             masm.vpcmpeqd_rr(rhs.fpu(), lhs.encoding(), dest.encoding());
    2387           0 :             break;
    2388             :           case Operand::MEM_REG_DISP:
    2389           0 :             masm.vpcmpeqd_mr(rhs.disp(), rhs.base(), lhs.encoding(), dest.encoding());
    2390           0 :             break;
    2391             :           case Operand::MEM_ADDRESS32:
    2392           0 :             masm.vpcmpeqd_mr(rhs.address(), lhs.encoding(), dest.encoding());
    2393           0 :             break;
    2394             :           default:
    2395           0 :             MOZ_CRASH("unexpected operand kind");
    2396             :         }
    2397           0 :     }
    2398           0 :     void vpcmpgtd(const Operand& rhs, FloatRegister lhs, FloatRegister dest) {
    2399           0 :         MOZ_ASSERT(HasSSE2());
    2400           0 :         switch (rhs.kind()) {
    2401             :           case Operand::FPREG:
    2402           0 :             masm.vpcmpgtd_rr(rhs.fpu(), lhs.encoding(), dest.encoding());
    2403           0 :             break;
    2404             :           case Operand::MEM_REG_DISP:
    2405           0 :             masm.vpcmpgtd_mr(rhs.disp(), rhs.base(), lhs.encoding(), dest.encoding());
    2406           0 :             break;
    2407             :           case Operand::MEM_ADDRESS32:
    2408           0 :             masm.vpcmpgtd_mr(rhs.address(), lhs.encoding(), dest.encoding());
    2409           0 :             break;
    2410             :           default:
    2411           0 :             MOZ_CRASH("unexpected operand kind");
    2412             :         }
    2413           0 :     }
    2414             : 
    2415           0 :     void vcmpps(uint8_t order, Operand src1, FloatRegister src0, FloatRegister dest) {
    2416           0 :         MOZ_ASSERT(HasSSE2());
    2417             :         // :TODO: (Bug 1132894) See LIRGeneratorX86Shared::lowerForFPU
    2418             :         // FIXME: This logic belongs in the MacroAssembler.
    2419           0 :         if (!HasAVX() && !src0.aliases(dest)) {
    2420           0 :             if (src1.kind() == Operand::FPREG &&
    2421           0 :                 dest.aliases(FloatRegister::FromCode(src1.fpu())))
    2422             :             {
    2423           0 :                 vmovdqa(src1, ScratchSimd128Reg);
    2424           0 :                 src1 = Operand(ScratchSimd128Reg);
    2425             :             }
    2426           0 :             vmovdqa(src0, dest);
    2427           0 :             src0 = dest;
    2428             :         }
    2429           0 :         switch (src1.kind()) {
    2430             :           case Operand::FPREG:
    2431           0 :             masm.vcmpps_rr(order, src1.fpu(), src0.encoding(), dest.encoding());
    2432           0 :             break;
    2433             :           case Operand::MEM_REG_DISP:
    2434           0 :             masm.vcmpps_mr(order, src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2435           0 :             break;
    2436             :           case Operand::MEM_ADDRESS32:
    2437           0 :             masm.vcmpps_mr(order, src1.address(), src0.encoding(), dest.encoding());
    2438           0 :             break;
    2439             :           default:
    2440           0 :             MOZ_CRASH("unexpected operand kind");
    2441             :         }
    2442           0 :     }
    2443           0 :     void vcmpeqps(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2444           0 :         vcmpps(X86Encoding::ConditionCmp_EQ, src1, src0, dest);
    2445           0 :     }
    2446           0 :     void vcmpltps(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2447           0 :         vcmpps(X86Encoding::ConditionCmp_LT, src1, src0, dest);
    2448           0 :     }
    2449           0 :     void vcmpleps(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2450           0 :         vcmpps(X86Encoding::ConditionCmp_LE, src1, src0, dest);
    2451           0 :     }
    2452           0 :     void vcmpunordps(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2453           0 :         vcmpps(X86Encoding::ConditionCmp_UNORD, src1, src0, dest);
    2454           0 :     }
    2455           0 :     void vcmpneqps(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2456           0 :         vcmpps(X86Encoding::ConditionCmp_NEQ, src1, src0, dest);
    2457           0 :     }
    2458             :     void vcmpordps(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2459             :         vcmpps(X86Encoding::ConditionCmp_ORD, src1, src0, dest);
    2460             :     }
    2461           0 :     void vrcpps(const Operand& src, FloatRegister dest) {
    2462           0 :         MOZ_ASSERT(HasSSE2());
    2463           0 :         switch (src.kind()) {
    2464             :           case Operand::FPREG:
    2465           0 :             masm.vrcpps_rr(src.fpu(), dest.encoding());
    2466           0 :             break;
    2467             :           case Operand::MEM_REG_DISP:
    2468           0 :             masm.vrcpps_mr(src.disp(), src.base(), dest.encoding());
    2469           0 :             break;
    2470             :           case Operand::MEM_ADDRESS32:
    2471           0 :             masm.vrcpps_mr(src.address(), dest.encoding());
    2472           0 :             break;
    2473             :           default:
    2474           0 :             MOZ_CRASH("unexpected operand kind");
    2475             :         }
    2476           0 :     }
    2477           0 :     void vsqrtps(const Operand& src, FloatRegister dest) {
    2478           0 :         MOZ_ASSERT(HasSSE2());
    2479           0 :         switch (src.kind()) {
    2480             :           case Operand::FPREG:
    2481           0 :             masm.vsqrtps_rr(src.fpu(), dest.encoding());
    2482           0 :             break;
    2483             :           case Operand::MEM_REG_DISP:
    2484           0 :             masm.vsqrtps_mr(src.disp(), src.base(), dest.encoding());
    2485           0 :             break;
    2486             :           case Operand::MEM_ADDRESS32:
    2487           0 :             masm.vsqrtps_mr(src.address(), dest.encoding());
    2488           0 :             break;
    2489             :           default:
    2490           0 :             MOZ_CRASH("unexpected operand kind");
    2491             :         }
    2492           0 :     }
    2493           0 :     void vrsqrtps(const Operand& src, FloatRegister dest) {
    2494           0 :         MOZ_ASSERT(HasSSE2());
    2495           0 :         switch (src.kind()) {
    2496             :           case Operand::FPREG:
    2497           0 :             masm.vrsqrtps_rr(src.fpu(), dest.encoding());
    2498           0 :             break;
    2499             :           case Operand::MEM_REG_DISP:
    2500           0 :             masm.vrsqrtps_mr(src.disp(), src.base(), dest.encoding());
    2501           0 :             break;
    2502             :           case Operand::MEM_ADDRESS32:
    2503           0 :             masm.vrsqrtps_mr(src.address(), dest.encoding());
    2504           0 :             break;
    2505             :           default:
    2506           0 :             MOZ_CRASH("unexpected operand kind");
    2507             :         }
    2508           0 :     }
    2509           0 :     void vmovd(Register src, FloatRegister dest) {
    2510           0 :         MOZ_ASSERT(HasSSE2());
    2511           0 :         masm.vmovd_rr(src.encoding(), dest.encoding());
    2512           0 :     }
    2513           0 :     void vmovd(FloatRegister src, Register dest) {
    2514           0 :         MOZ_ASSERT(HasSSE2());
    2515           0 :         masm.vmovd_rr(src.encoding(), dest.encoding());
    2516           0 :     }
    2517           0 :     void vmovd(const Operand& src, FloatRegister dest) {
    2518           0 :         MOZ_ASSERT(HasSSE2());
    2519           0 :         switch (src.kind()) {
    2520             :           case Operand::MEM_REG_DISP:
    2521           0 :             masm.vmovd_mr(src.disp(), src.base(), dest.encoding());
    2522           0 :             break;
    2523             :           case Operand::MEM_SCALE:
    2524           0 :             masm.vmovd_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
    2525           0 :             break;
    2526             :           default:
    2527           0 :             MOZ_CRASH("unexpected operand kind");
    2528             :         }
    2529           0 :     }
    2530           0 :     void vmovd(FloatRegister src, const Operand& dest) {
    2531           0 :         MOZ_ASSERT(HasSSE2());
    2532           0 :         switch (dest.kind()) {
    2533             :           case Operand::MEM_REG_DISP:
    2534           0 :             masm.vmovd_rm(src.encoding(), dest.disp(), dest.base());
    2535           0 :             break;
    2536             :           case Operand::MEM_SCALE:
    2537           0 :             masm.vmovd_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
    2538           0 :             break;
    2539             :           case Operand::MEM_ADDRESS32:
    2540           0 :             masm.vmovq_rm(src.encoding(), dest.address());
    2541           0 :             break;
    2542             :           default:
    2543           0 :             MOZ_CRASH("unexpected operand kind");
    2544             :         }
    2545           0 :     }
    2546           0 :     void vmovq(const Operand& src, FloatRegister dest) {
    2547           0 :         MOZ_ASSERT(HasSSE2());
    2548           0 :         switch (src.kind()) {
    2549             :           case Operand::MEM_REG_DISP:
    2550           0 :             masm.vmovq_mr(src.disp(), src.base(), dest.encoding());
    2551           0 :             break;
    2552             :           case Operand::MEM_SCALE:
    2553           0 :             masm.vmovq_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
    2554           0 :             break;
    2555             :           case Operand::MEM_ADDRESS32:
    2556           0 :             masm.vmovq_mr(src.address(), dest.encoding());
    2557           0 :             break;
    2558             :           default:
    2559           0 :             MOZ_CRASH("unexpected operand kind");
    2560             :         }
    2561           0 :     }
    2562           0 :     void vmovq(FloatRegister src, const Operand& dest) {
    2563           0 :         MOZ_ASSERT(HasSSE2());
    2564           0 :         switch (dest.kind()) {
    2565             :           case Operand::MEM_REG_DISP:
    2566           0 :             masm.vmovq_rm(src.encoding(), dest.disp(), dest.base());
    2567           0 :             break;
    2568             :           case Operand::MEM_SCALE:
    2569           0 :             masm.vmovq_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
    2570           0 :             break;
    2571             :           default:
    2572           0 :             MOZ_CRASH("unexpected operand kind");
    2573             :         }
    2574           0 :     }
    2575           0 :     void vpaddb(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2576           0 :         MOZ_ASSERT(HasSSE2());
    2577           0 :         switch (src1.kind()) {
    2578             :           case Operand::FPREG:
    2579           0 :             masm.vpaddb_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2580           0 :             break;
    2581             :           case Operand::MEM_REG_DISP:
    2582           0 :             masm.vpaddb_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2583           0 :             break;
    2584             :           case Operand::MEM_ADDRESS32:
    2585           0 :             masm.vpaddb_mr(src1.address(), src0.encoding(), dest.encoding());
    2586           0 :             break;
    2587             :           default:
    2588           0 :             MOZ_CRASH("unexpected operand kind");
    2589             :         }
    2590           0 :     }
    2591           0 :     void vpsubb(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2592           0 :         MOZ_ASSERT(HasSSE2());
    2593           0 :         switch (src1.kind()) {
    2594             :           case Operand::FPREG:
    2595           0 :             masm.vpsubb_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2596           0 :             break;
    2597             :           case Operand::MEM_REG_DISP:
    2598           0 :             masm.vpsubb_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2599           0 :             break;
    2600             :           case Operand::MEM_ADDRESS32:
    2601           0 :             masm.vpsubb_mr(src1.address(), src0.encoding(), dest.encoding());
    2602           0 :             break;
    2603             :           default:
    2604           0 :             MOZ_CRASH("unexpected operand kind");
    2605             :         }
    2606           0 :     }
    2607           0 :     void vpaddsb(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2608           0 :         MOZ_ASSERT(HasSSE2());
    2609           0 :         switch (src1.kind()) {
    2610             :           case Operand::FPREG:
    2611           0 :             masm.vpaddsb_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2612           0 :             break;
    2613             :           case Operand::MEM_REG_DISP:
    2614           0 :             masm.vpaddsb_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2615           0 :             break;
    2616             :           case Operand::MEM_ADDRESS32:
    2617           0 :             masm.vpaddsb_mr(src1.address(), src0.encoding(), dest.encoding());
    2618           0 :             break;
    2619             :           default:
    2620           0 :             MOZ_CRASH("unexpected operand kind");
    2621             :         }
    2622           0 :     }
    2623           0 :     void vpaddusb(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2624           0 :         MOZ_ASSERT(HasSSE2());
    2625           0 :         switch (src1.kind()) {
    2626             :           case Operand::FPREG:
    2627           0 :             masm.vpaddusb_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2628           0 :             break;
    2629             :           case Operand::MEM_REG_DISP:
    2630           0 :             masm.vpaddusb_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2631           0 :             break;
    2632             :           case Operand::MEM_ADDRESS32:
    2633           0 :             masm.vpaddusb_mr(src1.address(), src0.encoding(), dest.encoding());
    2634           0 :             break;
    2635             :           default:
    2636           0 :             MOZ_CRASH("unexpected operand kind");
    2637             :         }
    2638           0 :     }
    2639           0 :     void vpsubsb(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2640           0 :         MOZ_ASSERT(HasSSE2());
    2641           0 :         switch (src1.kind()) {
    2642             :           case Operand::FPREG:
    2643           0 :             masm.vpsubsb_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2644           0 :             break;
    2645             :           case Operand::MEM_REG_DISP:
    2646           0 :             masm.vpsubsb_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2647           0 :             break;
    2648             :           case Operand::MEM_ADDRESS32:
    2649           0 :             masm.vpsubsb_mr(src1.address(), src0.encoding(), dest.encoding());
    2650           0 :             break;
    2651             :           default:
    2652           0 :             MOZ_CRASH("unexpected operand kind");
    2653             :         }
    2654           0 :     }
    2655           0 :     void vpsubusb(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2656           0 :         MOZ_ASSERT(HasSSE2());
    2657           0 :         switch (src1.kind()) {
    2658             :           case Operand::FPREG:
    2659           0 :             masm.vpsubusb_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2660           0 :             break;
    2661             :           case Operand::MEM_REG_DISP:
    2662           0 :             masm.vpsubusb_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2663           0 :             break;
    2664             :           case Operand::MEM_ADDRESS32:
    2665           0 :             masm.vpsubusb_mr(src1.address(), src0.encoding(), dest.encoding());
    2666           0 :             break;
    2667             :           default:
    2668           0 :             MOZ_CRASH("unexpected operand kind");
    2669             :         }
    2670           0 :     }
    2671           0 :     void vpaddw(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2672           0 :         MOZ_ASSERT(HasSSE2());
    2673           0 :         switch (src1.kind()) {
    2674             :           case Operand::FPREG:
    2675           0 :             masm.vpaddw_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2676           0 :             break;
    2677             :           case Operand::MEM_REG_DISP:
    2678           0 :             masm.vpaddw_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2679           0 :             break;
    2680             :           case Operand::MEM_ADDRESS32:
    2681           0 :             masm.vpaddw_mr(src1.address(), src0.encoding(), dest.encoding());
    2682           0 :             break;
    2683             :           default:
    2684           0 :             MOZ_CRASH("unexpected operand kind");
    2685             :         }
    2686           0 :     }
    2687           0 :     void vpsubw(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2688           0 :         MOZ_ASSERT(HasSSE2());
    2689           0 :         switch (src1.kind()) {
    2690             :           case Operand::FPREG:
    2691           0 :             masm.vpsubw_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2692           0 :             break;
    2693             :           case Operand::MEM_REG_DISP:
    2694           0 :             masm.vpsubw_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2695           0 :             break;
    2696             :           case Operand::MEM_ADDRESS32:
    2697           0 :             masm.vpsubw_mr(src1.address(), src0.encoding(), dest.encoding());
    2698           0 :             break;
    2699             :           default:
    2700           0 :             MOZ_CRASH("unexpected operand kind");
    2701             :         }
    2702           0 :     }
    2703           0 :     void vpaddsw(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2704           0 :         MOZ_ASSERT(HasSSE2());
    2705           0 :         switch (src1.kind()) {
    2706             :           case Operand::FPREG:
    2707           0 :             masm.vpaddsw_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2708           0 :             break;
    2709             :           case Operand::MEM_REG_DISP:
    2710           0 :             masm.vpaddsw_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2711           0 :             break;
    2712             :           case Operand::MEM_ADDRESS32:
    2713           0 :             masm.vpaddsw_mr(src1.address(), src0.encoding(), dest.encoding());
    2714           0 :             break;
    2715             :           default:
    2716           0 :             MOZ_CRASH("unexpected operand kind");
    2717             :         }
    2718           0 :     }
    2719           0 :     void vpaddusw(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2720           0 :         MOZ_ASSERT(HasSSE2());
    2721           0 :         switch (src1.kind()) {
    2722             :           case Operand::FPREG:
    2723           0 :             masm.vpaddusw_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2724           0 :             break;
    2725             :           case Operand::MEM_REG_DISP:
    2726           0 :             masm.vpaddusw_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2727           0 :             break;
    2728             :           case Operand::MEM_ADDRESS32:
    2729           0 :             masm.vpaddusw_mr(src1.address(), src0.encoding(), dest.encoding());
    2730           0 :             break;
    2731             :           default:
    2732           0 :             MOZ_CRASH("unexpected operand kind");
    2733             :         }
    2734           0 :     }
    2735           0 :     void vpsubsw(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2736           0 :         MOZ_ASSERT(HasSSE2());
    2737           0 :         switch (src1.kind()) {
    2738             :           case Operand::FPREG:
    2739           0 :             masm.vpsubsw_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2740           0 :             break;
    2741             :           case Operand::MEM_REG_DISP:
    2742           0 :             masm.vpsubsw_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2743           0 :             break;
    2744             :           case Operand::MEM_ADDRESS32:
    2745           0 :             masm.vpsubsw_mr(src1.address(), src0.encoding(), dest.encoding());
    2746           0 :             break;
    2747             :           default:
    2748           0 :             MOZ_CRASH("unexpected operand kind");
    2749             :         }
    2750           0 :     }
    2751           0 :     void vpsubusw(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2752           0 :         MOZ_ASSERT(HasSSE2());
    2753           0 :         switch (src1.kind()) {
    2754             :           case Operand::FPREG:
    2755           0 :             masm.vpsubusw_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2756           0 :             break;
    2757             :           case Operand::MEM_REG_DISP:
    2758           0 :             masm.vpsubusw_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2759           0 :             break;
    2760             :           case Operand::MEM_ADDRESS32:
    2761           0 :             masm.vpsubusw_mr(src1.address(), src0.encoding(), dest.encoding());
    2762           0 :             break;
    2763             :           default:
    2764           0 :             MOZ_CRASH("unexpected operand kind");
    2765             :         }
    2766           0 :     }
    2767           0 :     void vpaddd(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2768           0 :         MOZ_ASSERT(HasSSE2());
    2769           0 :         switch (src1.kind()) {
    2770             :           case Operand::FPREG:
    2771           0 :             masm.vpaddd_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2772           0 :             break;
    2773             :           case Operand::MEM_REG_DISP:
    2774           0 :             masm.vpaddd_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2775           0 :             break;
    2776             :           case Operand::MEM_ADDRESS32:
    2777           0 :             masm.vpaddd_mr(src1.address(), src0.encoding(), dest.encoding());
    2778           0 :             break;
    2779             :           default:
    2780           0 :             MOZ_CRASH("unexpected operand kind");
    2781             :         }
    2782           0 :     }
    2783           0 :     void vpsubd(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2784           0 :         MOZ_ASSERT(HasSSE2());
    2785           0 :         switch (src1.kind()) {
    2786             :           case Operand::FPREG:
    2787           0 :             masm.vpsubd_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2788           0 :             break;
    2789             :           case Operand::MEM_REG_DISP:
    2790           0 :             masm.vpsubd_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2791           0 :             break;
    2792             :           case Operand::MEM_ADDRESS32:
    2793           0 :             masm.vpsubd_mr(src1.address(), src0.encoding(), dest.encoding());
    2794           0 :             break;
    2795             :           default:
    2796           0 :             MOZ_CRASH("unexpected operand kind");
    2797             :         }
    2798           0 :     }
    2799           0 :     void vpmuludq(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    2800           0 :         MOZ_ASSERT(HasSSE2());
    2801           0 :         masm.vpmuludq_rr(src1.encoding(), src0.encoding(), dest.encoding());
    2802           0 :     }
    2803             :     void vpmuludq(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2804             :         MOZ_ASSERT(HasSSE2());
    2805             :         switch (src1.kind()) {
    2806             :           case Operand::FPREG:
    2807             :             masm.vpmuludq_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2808             :             break;
    2809             :           case Operand::MEM_REG_DISP:
    2810             :             masm.vpmuludq_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2811             :             break;
    2812             :           default:
    2813             :             MOZ_CRASH("unexpected operand kind");
    2814             :         }
    2815             :     }
    2816           0 :     void vpmullw(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2817           0 :         MOZ_ASSERT(HasSSE2());
    2818           0 :         switch (src1.kind()) {
    2819             :           case Operand::FPREG:
    2820           0 :             masm.vpmullw_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2821           0 :             break;
    2822             :           case Operand::MEM_REG_DISP:
    2823           0 :             masm.vpmullw_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2824           0 :             break;
    2825             :           default:
    2826           0 :             MOZ_CRASH("unexpected operand kind");
    2827             :         }
    2828           0 :     }
    2829           0 :     void vpmulld(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2830           0 :         MOZ_ASSERT(HasSSE41());
    2831           0 :         switch (src1.kind()) {
    2832             :           case Operand::FPREG:
    2833           0 :             masm.vpmulld_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2834           0 :             break;
    2835             :           case Operand::MEM_REG_DISP:
    2836           0 :             masm.vpmulld_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2837           0 :             break;
    2838             :           case Operand::MEM_ADDRESS32:
    2839           0 :             masm.vpmulld_mr(src1.address(), src0.encoding(), dest.encoding());
    2840           0 :             break;
    2841             :           default:
    2842           0 :             MOZ_CRASH("unexpected operand kind");
    2843             :         }
    2844           0 :     }
    2845           0 :     void vaddps(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2846           0 :         MOZ_ASSERT(HasSSE2());
    2847           0 :         switch (src1.kind()) {
    2848             :           case Operand::FPREG:
    2849           0 :             masm.vaddps_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2850           0 :             break;
    2851             :           case Operand::MEM_REG_DISP:
    2852           0 :             masm.vaddps_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2853           0 :             break;
    2854             :           case Operand::MEM_ADDRESS32:
    2855           0 :             masm.vaddps_mr(src1.address(), src0.encoding(), dest.encoding());
    2856           0 :             break;
    2857             :           default:
    2858           0 :             MOZ_CRASH("unexpected operand kind");
    2859             :         }
    2860           0 :     }
    2861           0 :     void vsubps(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2862           0 :         MOZ_ASSERT(HasSSE2());
    2863           0 :         switch (src1.kind()) {
    2864             :           case Operand::FPREG:
    2865           0 :             masm.vsubps_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2866           0 :             break;
    2867             :           case Operand::MEM_REG_DISP:
    2868           0 :             masm.vsubps_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2869           0 :             break;
    2870             :           case Operand::MEM_ADDRESS32:
    2871           0 :             masm.vsubps_mr(src1.address(), src0.encoding(), dest.encoding());
    2872           0 :             break;
    2873             :           default:
    2874           0 :             MOZ_CRASH("unexpected operand kind");
    2875             :         }
    2876           0 :     }
    2877           0 :     void vmulps(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2878           0 :         MOZ_ASSERT(HasSSE2());
    2879           0 :         switch (src1.kind()) {
    2880             :           case Operand::FPREG:
    2881           0 :             masm.vmulps_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2882           0 :             break;
    2883             :           case Operand::MEM_REG_DISP:
    2884           0 :             masm.vmulps_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2885           0 :             break;
    2886             :           case Operand::MEM_ADDRESS32:
    2887           0 :             masm.vmulps_mr(src1.address(), src0.encoding(), dest.encoding());
    2888           0 :             break;
    2889             :           default:
    2890           0 :             MOZ_CRASH("unexpected operand kind");
    2891             :         }
    2892           0 :     }
    2893           0 :     void vdivps(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2894           0 :         MOZ_ASSERT(HasSSE2());
    2895           0 :         switch (src1.kind()) {
    2896             :           case Operand::FPREG:
    2897           0 :             masm.vdivps_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2898           0 :             break;
    2899             :           case Operand::MEM_REG_DISP:
    2900           0 :             masm.vdivps_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2901           0 :             break;
    2902             :           case Operand::MEM_ADDRESS32:
    2903           0 :             masm.vdivps_mr(src1.address(), src0.encoding(), dest.encoding());
    2904           0 :             break;
    2905             :           default:
    2906           0 :             MOZ_CRASH("unexpected operand kind");
    2907             :         }
    2908           0 :     }
    2909           0 :     void vmaxps(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2910           0 :         MOZ_ASSERT(HasSSE2());
    2911           0 :         switch (src1.kind()) {
    2912             :           case Operand::FPREG:
    2913           0 :             masm.vmaxps_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2914           0 :             break;
    2915             :           case Operand::MEM_REG_DISP:
    2916           0 :             masm.vmaxps_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2917           0 :             break;
    2918             :           case Operand::MEM_ADDRESS32:
    2919           0 :             masm.vmaxps_mr(src1.address(), src0.encoding(), dest.encoding());
    2920           0 :             break;
    2921             :           default:
    2922           0 :             MOZ_CRASH("unexpected operand kind");
    2923             :         }
    2924           0 :     }
    2925           0 :     void vminps(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2926           0 :         MOZ_ASSERT(HasSSE2());
    2927           0 :         switch (src1.kind()) {
    2928             :           case Operand::FPREG:
    2929           0 :             masm.vminps_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2930           0 :             break;
    2931             :           case Operand::MEM_REG_DISP:
    2932           0 :             masm.vminps_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2933           0 :             break;
    2934             :           case Operand::MEM_ADDRESS32:
    2935           0 :             masm.vminps_mr(src1.address(), src0.encoding(), dest.encoding());
    2936           0 :             break;
    2937             :           default:
    2938           0 :             MOZ_CRASH("unexpected operand kind");
    2939             :         }
    2940           0 :     }
    2941           0 :     void vandps(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2942           0 :         MOZ_ASSERT(HasSSE2());
    2943           0 :         switch (src1.kind()) {
    2944             :           case Operand::FPREG:
    2945           0 :             masm.vandps_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2946           0 :             break;
    2947             :           case Operand::MEM_REG_DISP:
    2948           0 :             masm.vandps_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2949           0 :             break;
    2950             :           case Operand::MEM_ADDRESS32:
    2951           0 :             masm.vandps_mr(src1.address(), src0.encoding(), dest.encoding());
    2952           0 :             break;
    2953             :           default:
    2954           0 :             MOZ_CRASH("unexpected operand kind");
    2955             :         }
    2956           0 :     }
    2957           0 :     void vandnps(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2958             :         // Negates bits of dest and then applies AND
    2959           0 :         MOZ_ASSERT(HasSSE2());
    2960           0 :         switch (src1.kind()) {
    2961             :           case Operand::FPREG:
    2962           0 :             masm.vandnps_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2963           0 :             break;
    2964             :           case Operand::MEM_REG_DISP:
    2965           0 :             masm.vandnps_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2966           0 :             break;
    2967             :           case Operand::MEM_ADDRESS32:
    2968           0 :             masm.vandnps_mr(src1.address(), src0.encoding(), dest.encoding());
    2969           0 :             break;
    2970             :           default:
    2971           0 :             MOZ_CRASH("unexpected operand kind");
    2972             :         }
    2973           0 :     }
    2974           0 :     void vorps(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2975           0 :         MOZ_ASSERT(HasSSE2());
    2976           0 :         switch (src1.kind()) {
    2977             :           case Operand::FPREG:
    2978           0 :             masm.vorps_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2979           0 :             break;
    2980             :           case Operand::MEM_REG_DISP:
    2981           0 :             masm.vorps_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2982           0 :             break;
    2983             :           case Operand::MEM_ADDRESS32:
    2984           0 :             masm.vorps_mr(src1.address(), src0.encoding(), dest.encoding());
    2985           0 :             break;
    2986             :           default:
    2987           0 :             MOZ_CRASH("unexpected operand kind");
    2988             :         }
    2989           0 :     }
    2990           0 :     void vxorps(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    2991           0 :         MOZ_ASSERT(HasSSE2());
    2992           0 :         switch (src1.kind()) {
    2993             :           case Operand::FPREG:
    2994           0 :             masm.vxorps_rr(src1.fpu(), src0.encoding(), dest.encoding());
    2995           0 :             break;
    2996             :           case Operand::MEM_REG_DISP:
    2997           0 :             masm.vxorps_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    2998           0 :             break;
    2999             :           case Operand::MEM_ADDRESS32:
    3000           0 :             masm.vxorps_mr(src1.address(), src0.encoding(), dest.encoding());
    3001           0 :             break;
    3002             :           default:
    3003           0 :             MOZ_CRASH("unexpected operand kind");
    3004             :         }
    3005           0 :     }
    3006             :     void vpand(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3007             :         MOZ_ASSERT(HasSSE2());
    3008             :         masm.vpand_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3009             :     }
    3010           0 :     void vpand(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    3011           0 :         MOZ_ASSERT(HasSSE2());
    3012           0 :         switch (src1.kind()) {
    3013             :           case Operand::FPREG:
    3014           0 :             masm.vpand_rr(src1.fpu(), src0.encoding(), dest.encoding());
    3015           0 :             break;
    3016             :           case Operand::MEM_REG_DISP:
    3017           0 :             masm.vpand_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    3018           0 :             break;
    3019             :           case Operand::MEM_ADDRESS32:
    3020           0 :             masm.vpand_mr(src1.address(), src0.encoding(), dest.encoding());
    3021           0 :             break;
    3022             :           default:
    3023           0 :             MOZ_CRASH("unexpected operand kind");
    3024             :         }
    3025           0 :     }
    3026           0 :     void vpor(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3027           0 :         MOZ_ASSERT(HasSSE2());
    3028           0 :         masm.vpor_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3029           0 :     }
    3030           0 :     void vpor(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    3031           0 :         MOZ_ASSERT(HasSSE2());
    3032           0 :         switch (src1.kind()) {
    3033             :           case Operand::FPREG:
    3034           0 :             masm.vpor_rr(src1.fpu(), src0.encoding(), dest.encoding());
    3035           0 :             break;
    3036             :           case Operand::MEM_REG_DISP:
    3037           0 :             masm.vpor_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    3038           0 :             break;
    3039             :           case Operand::MEM_ADDRESS32:
    3040           0 :             masm.vpor_mr(src1.address(), src0.encoding(), dest.encoding());
    3041           0 :             break;
    3042             :           default:
    3043           0 :             MOZ_CRASH("unexpected operand kind");
    3044             :         }
    3045           0 :     }
    3046           0 :     void vpxor(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3047           0 :         MOZ_ASSERT(HasSSE2());
    3048           0 :         masm.vpxor_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3049           0 :     }
    3050           0 :     void vpxor(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    3051           0 :         MOZ_ASSERT(HasSSE2());
    3052           0 :         switch (src1.kind()) {
    3053             :           case Operand::FPREG:
    3054           0 :             masm.vpxor_rr(src1.fpu(), src0.encoding(), dest.encoding());
    3055           0 :             break;
    3056             :           case Operand::MEM_REG_DISP:
    3057           0 :             masm.vpxor_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    3058           0 :             break;
    3059             :           case Operand::MEM_ADDRESS32:
    3060           0 :             masm.vpxor_mr(src1.address(), src0.encoding(), dest.encoding());
    3061           0 :             break;
    3062             :           default:
    3063           0 :             MOZ_CRASH("unexpected operand kind");
    3064             :         }
    3065           0 :     }
    3066             :     void vpandn(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3067             :         MOZ_ASSERT(HasSSE2());
    3068             :         masm.vpandn_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3069             :     }
    3070             :     void vpandn(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    3071             :         MOZ_ASSERT(HasSSE2());
    3072             :         switch (src1.kind()) {
    3073             :           case Operand::FPREG:
    3074             :             masm.vpandn_rr(src1.fpu(), src0.encoding(), dest.encoding());
    3075             :             break;
    3076             :           case Operand::MEM_REG_DISP:
    3077             :             masm.vpandn_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    3078             :             break;
    3079             :           case Operand::MEM_ADDRESS32:
    3080             :             masm.vpandn_mr(src1.address(), src0.encoding(), dest.encoding());
    3081             :             break;
    3082             :           default:
    3083             :             MOZ_CRASH("unexpected operand kind");
    3084             :         }
    3085             :     }
    3086             : 
    3087           0 :     void vpshufd(uint32_t mask, FloatRegister src, FloatRegister dest) {
    3088           0 :         MOZ_ASSERT(HasSSE2());
    3089           0 :         masm.vpshufd_irr(mask, src.encoding(), dest.encoding());
    3090           0 :     }
    3091           0 :     void vpshufd(uint32_t mask, const Operand& src1, FloatRegister dest) {
    3092           0 :         MOZ_ASSERT(HasSSE2());
    3093           0 :         switch (src1.kind()) {
    3094             :           case Operand::FPREG:
    3095           0 :             masm.vpshufd_irr(mask, src1.fpu(), dest.encoding());
    3096           0 :             break;
    3097             :           case Operand::MEM_REG_DISP:
    3098           0 :             masm.vpshufd_imr(mask, src1.disp(), src1.base(), dest.encoding());
    3099           0 :             break;
    3100             :           case Operand::MEM_ADDRESS32:
    3101           0 :             masm.vpshufd_imr(mask, src1.address(), dest.encoding());
    3102           0 :             break;
    3103             :           default:
    3104           0 :             MOZ_CRASH("unexpected operand kind");
    3105             :         }
    3106           0 :     }
    3107             : 
    3108           0 :     void vpshuflw(uint32_t mask, FloatRegister src, FloatRegister dest) {
    3109           0 :         MOZ_ASSERT(HasSSE2());
    3110           0 :         masm.vpshuflw_irr(mask, src.encoding(), dest.encoding());
    3111           0 :     }
    3112             :     void vpshufhw(uint32_t mask, FloatRegister src, FloatRegister dest) {
    3113             :         MOZ_ASSERT(HasSSE2());
    3114             :         masm.vpshufhw_irr(mask, src.encoding(), dest.encoding());
    3115             :     }
    3116           0 :     void vpshufb(FloatRegister mask, FloatRegister src, FloatRegister dest) {
    3117           0 :         MOZ_ASSERT(HasSSSE3());
    3118           0 :         masm.vpshufb_rr(mask.encoding(), src.encoding(), dest.encoding());
    3119           0 :     }
    3120           0 :     void vmovddup(FloatRegister src, FloatRegister dest) {
    3121           0 :         MOZ_ASSERT(HasSSE3());
    3122           0 :         masm.vmovddup_rr(src.encoding(), dest.encoding());
    3123           0 :     }
    3124           0 :     void vmovhlps(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3125           0 :         MOZ_ASSERT(HasSSE2());
    3126           0 :         masm.vmovhlps_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3127           0 :     }
    3128           0 :     void vmovlhps(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3129           0 :         MOZ_ASSERT(HasSSE2());
    3130           0 :         masm.vmovlhps_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3131           0 :     }
    3132           0 :     void vunpcklps(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3133           0 :         MOZ_ASSERT(HasSSE2());
    3134           0 :         masm.vunpcklps_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3135           0 :     }
    3136           0 :     void vunpcklps(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    3137           0 :         MOZ_ASSERT(HasSSE2());
    3138           0 :         switch (src1.kind()) {
    3139             :           case Operand::FPREG:
    3140           0 :             masm.vunpcklps_rr(src1.fpu(), src0.encoding(), dest.encoding());
    3141           0 :             break;
    3142             :           case Operand::MEM_REG_DISP:
    3143           0 :             masm.vunpcklps_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    3144           0 :             break;
    3145             :           case Operand::MEM_ADDRESS32:
    3146           0 :             masm.vunpcklps_mr(src1.address(), src0.encoding(), dest.encoding());
    3147           0 :             break;
    3148             :           default:
    3149           0 :             MOZ_CRASH("unexpected operand kind");
    3150             :         }
    3151           0 :     }
    3152           0 :     void vunpckhps(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3153           0 :         MOZ_ASSERT(HasSSE2());
    3154           0 :         masm.vunpckhps_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3155           0 :     }
    3156           0 :     void vunpckhps(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    3157           0 :         MOZ_ASSERT(HasSSE2());
    3158           0 :         switch (src1.kind()) {
    3159             :           case Operand::FPREG:
    3160           0 :             masm.vunpckhps_rr(src1.fpu(), src0.encoding(), dest.encoding());
    3161           0 :             break;
    3162             :           case Operand::MEM_REG_DISP:
    3163           0 :             masm.vunpckhps_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    3164           0 :             break;
    3165             :           case Operand::MEM_ADDRESS32:
    3166           0 :             masm.vunpckhps_mr(src1.address(), src0.encoding(), dest.encoding());
    3167           0 :             break;
    3168             :           default:
    3169           0 :             MOZ_CRASH("unexpected operand kind");
    3170             :         }
    3171           0 :     }
    3172           0 :     void vshufps(uint32_t mask, FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3173           0 :         MOZ_ASSERT(HasSSE2());
    3174           0 :         masm.vshufps_irr(mask, src1.encoding(), src0.encoding(), dest.encoding());
    3175           0 :     }
    3176           0 :     void vshufps(uint32_t mask, const Operand& src1, FloatRegister src0, FloatRegister dest) {
    3177           0 :         MOZ_ASSERT(HasSSE2());
    3178           0 :         switch (src1.kind()) {
    3179             :           case Operand::FPREG:
    3180           0 :             masm.vshufps_irr(mask, src1.fpu(), src0.encoding(), dest.encoding());
    3181           0 :             break;
    3182             :           case Operand::MEM_REG_DISP:
    3183           0 :             masm.vshufps_imr(mask, src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    3184           0 :             break;
    3185             :           case Operand::MEM_ADDRESS32:
    3186           0 :             masm.vshufps_imr(mask, src1.address(), src0.encoding(), dest.encoding());
    3187           0 :             break;
    3188             :           default:
    3189           0 :             MOZ_CRASH("unexpected operand kind");
    3190             :         }
    3191           0 :     }
    3192           0 :     void vaddsd(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3193           0 :         MOZ_ASSERT(HasSSE2());
    3194           0 :         masm.vaddsd_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3195           0 :     }
    3196           0 :     void vaddss(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3197           0 :         MOZ_ASSERT(HasSSE2());
    3198           0 :         masm.vaddss_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3199           0 :     }
    3200           0 :     void vaddsd(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    3201           0 :         MOZ_ASSERT(HasSSE2());
    3202           0 :         switch (src1.kind()) {
    3203             :           case Operand::FPREG:
    3204           0 :             masm.vaddsd_rr(src1.fpu(), src0.encoding(), dest.encoding());
    3205           0 :             break;
    3206             :           case Operand::MEM_REG_DISP:
    3207           0 :             masm.vaddsd_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    3208           0 :             break;
    3209             :           case Operand::MEM_ADDRESS32:
    3210           0 :             masm.vaddsd_mr(src1.address(), src0.encoding(), dest.encoding());
    3211           0 :             break;
    3212             :           default:
    3213           0 :             MOZ_CRASH("unexpected operand kind");
    3214             :         }
    3215           0 :     }
    3216           0 :     void vaddss(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    3217           0 :         MOZ_ASSERT(HasSSE2());
    3218           0 :         switch (src1.kind()) {
    3219             :           case Operand::FPREG:
    3220           0 :             masm.vaddss_rr(src1.fpu(), src0.encoding(), dest.encoding());
    3221           0 :             break;
    3222             :           case Operand::MEM_REG_DISP:
    3223           0 :             masm.vaddss_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    3224           0 :             break;
    3225             :           case Operand::MEM_ADDRESS32:
    3226           0 :             masm.vaddss_mr(src1.address(), src0.encoding(), dest.encoding());
    3227           0 :             break;
    3228             :           default:
    3229           0 :             MOZ_CRASH("unexpected operand kind");
    3230             :         }
    3231           0 :     }
    3232           0 :     void vsubsd(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3233           0 :         MOZ_ASSERT(HasSSE2());
    3234           0 :         masm.vsubsd_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3235           0 :     }
    3236           0 :     void vsubss(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3237           0 :         MOZ_ASSERT(HasSSE2());
    3238           0 :         masm.vsubss_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3239           0 :     }
    3240           0 :     void vsubsd(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    3241           0 :         MOZ_ASSERT(HasSSE2());
    3242           0 :         switch (src1.kind()) {
    3243             :           case Operand::FPREG:
    3244           0 :             masm.vsubsd_rr(src1.fpu(), src0.encoding(), dest.encoding());
    3245           0 :             break;
    3246             :           case Operand::MEM_REG_DISP:
    3247           0 :             masm.vsubsd_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    3248           0 :             break;
    3249             :           default:
    3250           0 :             MOZ_CRASH("unexpected operand kind");
    3251             :         }
    3252           0 :     }
    3253           0 :     void vsubss(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    3254           0 :         MOZ_ASSERT(HasSSE2());
    3255           0 :         switch (src1.kind()) {
    3256             :           case Operand::FPREG:
    3257           0 :             masm.vsubss_rr(src1.fpu(), src0.encoding(), dest.encoding());
    3258           0 :             break;
    3259             :           case Operand::MEM_REG_DISP:
    3260           0 :             masm.vsubss_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    3261           0 :             break;
    3262             :           default:
    3263           0 :             MOZ_CRASH("unexpected operand kind");
    3264             :         }
    3265           0 :     }
    3266           0 :     void vmulsd(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3267           0 :         MOZ_ASSERT(HasSSE2());
    3268           0 :         masm.vmulsd_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3269           0 :     }
    3270           0 :     void vmulsd(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    3271           0 :         MOZ_ASSERT(HasSSE2());
    3272           0 :         switch (src1.kind()) {
    3273             :           case Operand::FPREG:
    3274           0 :             masm.vmulsd_rr(src1.fpu(), src0.encoding(), dest.encoding());
    3275           0 :             break;
    3276             :           case Operand::MEM_REG_DISP:
    3277           0 :             masm.vmulsd_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    3278           0 :             break;
    3279             :           default:
    3280           0 :             MOZ_CRASH("unexpected operand kind");
    3281             :         }
    3282           0 :     }
    3283           0 :     void vmulss(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    3284           0 :         MOZ_ASSERT(HasSSE2());
    3285           0 :         switch (src1.kind()) {
    3286             :           case Operand::FPREG:
    3287           0 :             masm.vmulss_rr(src1.fpu(), src0.encoding(), dest.encoding());
    3288           0 :             break;
    3289             :           case Operand::MEM_REG_DISP:
    3290           0 :             masm.vmulss_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    3291           0 :             break;
    3292             :           default:
    3293           0 :             MOZ_CRASH("unexpected operand kind");
    3294             :         }
    3295           0 :     }
    3296           0 :     void vmulss(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3297           0 :         MOZ_ASSERT(HasSSE2());
    3298           0 :         masm.vmulss_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3299           0 :     }
    3300           1 :     void vdivsd(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3301           1 :         MOZ_ASSERT(HasSSE2());
    3302           1 :         masm.vdivsd_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3303           1 :     }
    3304           0 :     void vdivss(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3305           0 :         MOZ_ASSERT(HasSSE2());
    3306           0 :         masm.vdivss_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3307           0 :     }
    3308           0 :     void vdivsd(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    3309           0 :         MOZ_ASSERT(HasSSE2());
    3310           0 :         switch (src1.kind()) {
    3311             :           case Operand::FPREG:
    3312           0 :             masm.vdivsd_rr(src1.fpu(), src0.encoding(), dest.encoding());
    3313           0 :             break;
    3314             :           case Operand::MEM_REG_DISP:
    3315           0 :             masm.vdivsd_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    3316           0 :             break;
    3317             :           default:
    3318           0 :             MOZ_CRASH("unexpected operand kind");
    3319             :         }
    3320           0 :     }
    3321           0 :     void vdivss(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    3322           0 :         MOZ_ASSERT(HasSSE2());
    3323           0 :         switch (src1.kind()) {
    3324             :           case Operand::FPREG:
    3325           0 :             masm.vdivss_rr(src1.fpu(), src0.encoding(), dest.encoding());
    3326           0 :             break;
    3327             :           case Operand::MEM_REG_DISP:
    3328           0 :             masm.vdivss_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    3329           0 :             break;
    3330             :           default:
    3331           0 :             MOZ_CRASH("unexpected operand kind");
    3332             :         }
    3333           0 :     }
    3334          59 :     void vxorpd(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3335          59 :         MOZ_ASSERT(HasSSE2());
    3336          59 :         masm.vxorpd_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3337          59 :     }
    3338           0 :     void vxorps(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3339           0 :         MOZ_ASSERT(HasSSE2());
    3340           0 :         masm.vxorps_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3341           0 :     }
    3342           0 :     void vorpd(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3343           0 :         MOZ_ASSERT(HasSSE2());
    3344           0 :         masm.vorpd_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3345           0 :     }
    3346           0 :     void vorps(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3347           0 :         MOZ_ASSERT(HasSSE2());
    3348           0 :         masm.vorps_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3349           0 :     }
    3350           0 :     void vandpd(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3351           0 :         MOZ_ASSERT(HasSSE2());
    3352           0 :         masm.vandpd_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3353           0 :     }
    3354           0 :     void vandps(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3355           0 :         MOZ_ASSERT(HasSSE2());
    3356           0 :         masm.vandps_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3357           0 :     }
    3358           0 :     void vsqrtsd(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3359           0 :         MOZ_ASSERT(HasSSE2());
    3360           0 :         masm.vsqrtsd_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3361           0 :     }
    3362           0 :     void vsqrtss(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3363           0 :         MOZ_ASSERT(HasSSE2());
    3364           0 :         masm.vsqrtss_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3365           0 :     }
    3366             : 
    3367             :     static X86Encoding::RoundingMode
    3368           0 :     ToX86RoundingMode(RoundingMode mode) {
    3369           0 :         switch (mode) {
    3370             :           case RoundingMode::Up:
    3371           0 :             return X86Encoding::RoundUp;
    3372             :           case RoundingMode::Down:
    3373           0 :             return X86Encoding::RoundDown;
    3374             :           case RoundingMode::NearestTiesToEven:
    3375           0 :             return X86Encoding::RoundToNearest;
    3376             :           case RoundingMode::TowardsZero:
    3377           0 :             return X86Encoding::RoundToZero;
    3378             :         }
    3379           0 :         MOZ_CRASH("unexpected mode");
    3380             :     }
    3381           0 :     void vroundsd(X86Encoding::RoundingMode mode, FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3382           0 :         MOZ_ASSERT(HasSSE41());
    3383           0 :         masm.vroundsd_irr(mode, src1.encoding(), src0.encoding(), dest.encoding());
    3384           0 :     }
    3385           0 :     void vroundss(X86Encoding::RoundingMode mode, FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3386           0 :         MOZ_ASSERT(HasSSE41());
    3387           0 :         masm.vroundss_irr(mode, src1.encoding(), src0.encoding(), dest.encoding());
    3388           0 :     }
    3389             : 
    3390           0 :     unsigned vinsertpsMask(unsigned sourceLane, unsigned destLane, unsigned zeroMask = 0)
    3391             :     {
    3392             :         // Note that the sourceLane bits are ignored in the case of a source
    3393             :         // memory operand, and the source is the given 32-bits memory location.
    3394           0 :         MOZ_ASSERT(zeroMask < 16);
    3395           0 :         unsigned ret = zeroMask ;
    3396           0 :         ret |= destLane << 4;
    3397           0 :         ret |= sourceLane << 6;
    3398           0 :         MOZ_ASSERT(ret < 256);
    3399           0 :         return ret;
    3400             :     }
    3401           0 :     void vinsertps(uint32_t mask, FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3402           0 :         MOZ_ASSERT(HasSSE41());
    3403           0 :         masm.vinsertps_irr(mask, src1.encoding(), src0.encoding(), dest.encoding());
    3404           0 :     }
    3405           0 :     void vinsertps(uint32_t mask, const Operand& src1, FloatRegister src0, FloatRegister dest) {
    3406           0 :         MOZ_ASSERT(HasSSE41());
    3407           0 :         switch (src1.kind()) {
    3408             :           case Operand::FPREG:
    3409           0 :             masm.vinsertps_irr(mask, src1.fpu(), src0.encoding(), dest.encoding());
    3410           0 :             break;
    3411             :           case Operand::MEM_REG_DISP:
    3412           0 :             masm.vinsertps_imr(mask, src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    3413           0 :             break;
    3414             :           default:
    3415           0 :             MOZ_CRASH("unexpected operand kind");
    3416             :         }
    3417           0 :     }
    3418           0 :     unsigned blendpsMask(bool x, bool y, bool z, bool w) {
    3419           0 :         return (x << 0) | (y << 1) | (z << 2) | (w << 3);
    3420             :     }
    3421             :     void vblendps(unsigned mask, FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3422             :         MOZ_ASSERT(HasSSE41());
    3423             :         masm.vblendps_irr(mask, src1.encoding(), src0.encoding(), dest.encoding());
    3424             :     }
    3425           0 :     void vblendps(unsigned mask, const Operand& src1, FloatRegister src0, FloatRegister dest) {
    3426           0 :         MOZ_ASSERT(HasSSE41());
    3427           0 :         switch (src1.kind()) {
    3428             :           case Operand::FPREG:
    3429           0 :             masm.vblendps_irr(mask, src1.fpu(), src0.encoding(), dest.encoding());
    3430           0 :             break;
    3431             :           case Operand::MEM_REG_DISP:
    3432           0 :             masm.vblendps_imr(mask, src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    3433           0 :             break;
    3434             :           default:
    3435           0 :             MOZ_CRASH("unexpected operand kind");
    3436             :         }
    3437           0 :     }
    3438           0 :     void vblendvps(FloatRegister mask, FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3439           0 :         MOZ_ASSERT(HasSSE41());
    3440           0 :         masm.vblendvps_rr(mask.encoding(), src1.encoding(), src0.encoding(), dest.encoding());
    3441           0 :     }
    3442             :     void vblendvps(FloatRegister mask, const Operand& src1, FloatRegister src0, FloatRegister dest) {
    3443             :         MOZ_ASSERT(HasSSE41());
    3444             :         switch (src1.kind()) {
    3445             :           case Operand::FPREG:
    3446             :             masm.vblendvps_rr(mask.encoding(), src1.fpu(), src0.encoding(), dest.encoding());
    3447             :             break;
    3448             :           case Operand::MEM_REG_DISP:
    3449             :             masm.vblendvps_mr(mask.encoding(), src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    3450             :             break;
    3451             :           default:
    3452             :             MOZ_CRASH("unexpected operand kind");
    3453             :         }
    3454             :     }
    3455           0 :     void vmovsldup(FloatRegister src, FloatRegister dest) {
    3456           0 :         MOZ_ASSERT(HasSSE3());
    3457           0 :         masm.vmovsldup_rr(src.encoding(), dest.encoding());
    3458           0 :     }
    3459             :     void vmovsldup(const Operand& src, FloatRegister dest) {
    3460             :         MOZ_ASSERT(HasSSE3());
    3461             :         switch (src.kind()) {
    3462             :           case Operand::FPREG:
    3463             :             masm.vmovsldup_rr(src.fpu(), dest.encoding());
    3464             :             break;
    3465             :           case Operand::MEM_REG_DISP:
    3466             :             masm.vmovsldup_mr(src.disp(), src.base(), dest.encoding());
    3467             :             break;
    3468             :           default:
    3469             :             MOZ_CRASH("unexpected operand kind");
    3470             :         }
    3471             :     }
    3472           0 :     void vmovshdup(FloatRegister src, FloatRegister dest) {
    3473           0 :         MOZ_ASSERT(HasSSE3());
    3474           0 :         masm.vmovshdup_rr(src.encoding(), dest.encoding());
    3475           0 :     }
    3476             :     void vmovshdup(const Operand& src, FloatRegister dest) {
    3477             :         MOZ_ASSERT(HasSSE3());
    3478             :         switch (src.kind()) {
    3479             :           case Operand::FPREG:
    3480             :             masm.vmovshdup_rr(src.fpu(), dest.encoding());
    3481             :             break;
    3482             :           case Operand::MEM_REG_DISP:
    3483             :             masm.vmovshdup_mr(src.disp(), src.base(), dest.encoding());
    3484             :             break;
    3485             :           default:
    3486             :             MOZ_CRASH("unexpected operand kind");
    3487             :         }
    3488             :     }
    3489           0 :     void vminsd(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3490           0 :         MOZ_ASSERT(HasSSE2());
    3491           0 :         masm.vminsd_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3492           0 :     }
    3493             :     void vminsd(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    3494             :         MOZ_ASSERT(HasSSE2());
    3495             :         switch (src1.kind()) {
    3496             :           case Operand::FPREG:
    3497             :             masm.vminsd_rr(src1.fpu(), src0.encoding(), dest.encoding());
    3498             :             break;
    3499             :           case Operand::MEM_REG_DISP:
    3500             :             masm.vminsd_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    3501             :             break;
    3502             :           default:
    3503             :             MOZ_CRASH("unexpected operand kind");
    3504             :         }
    3505             :     }
    3506           0 :     void vminss(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3507           0 :         MOZ_ASSERT(HasSSE2());
    3508           0 :         masm.vminss_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3509           0 :     }
    3510           0 :     void vmaxsd(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3511           0 :         MOZ_ASSERT(HasSSE2());
    3512           0 :         masm.vmaxsd_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3513           0 :     }
    3514             :     void vmaxsd(const Operand& src1, FloatRegister src0, FloatRegister dest) {
    3515             :         MOZ_ASSERT(HasSSE2());
    3516             :         switch (src1.kind()) {
    3517             :           case Operand::FPREG:
    3518             :             masm.vmaxsd_rr(src1.fpu(), src0.encoding(), dest.encoding());
    3519             :             break;
    3520             :           case Operand::MEM_REG_DISP:
    3521             :             masm.vmaxsd_mr(src1.disp(), src1.base(), src0.encoding(), dest.encoding());
    3522             :             break;
    3523             :           default:
    3524             :             MOZ_CRASH("unexpected operand kind");
    3525             :         }
    3526             :     }
    3527           0 :     void vmaxss(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
    3528           0 :         MOZ_ASSERT(HasSSE2());
    3529           0 :         masm.vmaxss_rr(src1.encoding(), src0.encoding(), dest.encoding());
    3530           0 :     }
    3531             :     void fisttp(const Operand& dest) {
    3532             :         MOZ_ASSERT(HasSSE3());
    3533             :         switch (dest.kind()) {
    3534             :           case Operand::MEM_REG_DISP:
    3535             :             masm.fisttp_m(dest.disp(), dest.base());
    3536             :             break;
    3537             :           default:
    3538             :             MOZ_CRASH("unexpected operand kind");
    3539             :         }
    3540             :     }
    3541             :     void fistp(const Operand& dest) {
    3542             :         switch (dest.kind()) {
    3543             :           case Operand::MEM_REG_DISP:
    3544             :             masm.fistp_m(dest.disp(), dest.base());
    3545             :             break;
    3546             :           default:
    3547             :             MOZ_CRASH("unexpected operand kind");
    3548             :         }
    3549             :     }
    3550             :     void fnstcw(const Operand& dest) {
    3551             :         switch (dest.kind()) {
    3552             :           case Operand::MEM_REG_DISP:
    3553             :             masm.fnstcw_m(dest.disp(), dest.base());
    3554             :             break;
    3555             :           default:
    3556             :             MOZ_CRASH("unexpected operand kind");
    3557             :         }
    3558             :     }
    3559             :     void fldcw(const Operand& dest) {
    3560             :         switch (dest.kind()) {
    3561             :           case Operand::MEM_REG_DISP:
    3562             :             masm.fldcw_m(dest.disp(), dest.base());
    3563             :             break;
    3564             :           default:
    3565             :             MOZ_CRASH("unexpected operand kind");
    3566             :         }
    3567             :     }
    3568             :     void fnstsw(const Operand& dest) {
    3569             :         switch (dest.kind()) {
    3570             :           case Operand::MEM_REG_DISP:
    3571             :             masm.fnstsw_m(dest.disp(), dest.base());
    3572             :             break;
    3573             :           default:
    3574             :             MOZ_CRASH("unexpected operand kind");
    3575             :         }
    3576             :     }
    3577             :     void fld(const Operand& dest) {
    3578             :         switch (dest.kind()) {
    3579             :           case Operand::MEM_REG_DISP:
    3580             :             masm.fld_m(dest.disp(), dest.base());
    3581             :             break;
    3582             :           default:
    3583             :             MOZ_CRASH("unexpected operand kind");
    3584             :         }
    3585             :     }
    3586             :     void fld32(const Operand& dest) {
    3587             :         switch (dest.kind()) {
    3588             :           case Operand::MEM_REG_DISP:
    3589             :             masm.fld32_m(dest.disp(), dest.base());
    3590             :             break;
    3591             :           default:
    3592             :             MOZ_CRASH("unexpected operand kind");
    3593             :         }
    3594             :     }
    3595             :     void fstp(const Operand& src) {
    3596             :         switch (src.kind()) {
    3597             :           case Operand::MEM_REG_DISP:
    3598             :             masm.fstp_m(src.disp(), src.base());
    3599             :             break;
    3600             :           default:
    3601             :             MOZ_CRASH("unexpected operand kind");
    3602             :         }
    3603             :     }
    3604             :     void fstp32(const Operand& src) {
    3605             :         switch (src.kind()) {
    3606             :           case Operand::MEM_REG_DISP:
    3607             :             masm.fstp32_m(src.disp(), src.base());
    3608             :             break;
    3609             :           default:
    3610             :             MOZ_CRASH("unexpected operand kind");
    3611             :         }
    3612             :     }
    3613             : 
    3614             :     // Defined for compatibility with ARM's assembler
    3615          21 :     uint32_t actualIndex(uint32_t x) {
    3616          21 :         return x;
    3617             :     }
    3618             : 
    3619          19 :     void flushBuffer() {
    3620          19 :     }
    3621             : 
    3622             :     // Patching.
    3623             : 
    3624        9508 :     static size_t PatchWrite_NearCallSize() {
    3625        9508 :         return 5;
    3626             :     }
    3627           0 :     static uintptr_t GetPointer(uint8_t* instPtr) {
    3628           0 :         uintptr_t* ptr = ((uintptr_t*) instPtr) - 1;
    3629           0 :         return *ptr;
    3630             :     }
    3631             :     // Write a relative call at the start location |dataLabel|.
    3632             :     // Note that this DOES NOT patch data that comes before |label|.
    3633           0 :     static void PatchWrite_NearCall(CodeLocationLabel startLabel, CodeLocationLabel target) {
    3634           0 :         uint8_t* start = startLabel.raw();
    3635           0 :         *start = 0xE8;
    3636           0 :         ptrdiff_t offset = target - startLabel - PatchWrite_NearCallSize();
    3637           0 :         MOZ_ASSERT(int32_t(offset) == offset);
    3638           0 :         *((int32_t*) (start + 1)) = offset;
    3639           0 :     }
    3640             : 
    3641           0 :     static void PatchWrite_Imm32(CodeLocationLabel dataLabel, Imm32 toWrite) {
    3642           0 :         *((int32_t*) dataLabel.raw() - 1) = toWrite.value;
    3643           0 :     }
    3644             : 
    3645       20756 :     static void PatchDataWithValueCheck(CodeLocationLabel data, PatchedImmPtr newData,
    3646             :                                         PatchedImmPtr expectedData) {
    3647             :         // The pointer given is a pointer to *after* the data.
    3648       20756 :         uintptr_t* ptr = ((uintptr_t*) data.raw()) - 1;
    3649       20756 :         MOZ_ASSERT(*ptr == (uintptr_t)expectedData.value);
    3650       20756 :         *ptr = (uintptr_t)newData.value;
    3651       20756 :     }
    3652       20756 :     static void PatchDataWithValueCheck(CodeLocationLabel data, ImmPtr newData, ImmPtr expectedData) {
    3653       20756 :         PatchDataWithValueCheck(data, PatchedImmPtr(newData.value), PatchedImmPtr(expectedData.value));
    3654       20756 :     }
    3655             : 
    3656           0 :     static void PatchInstructionImmediate(uint8_t* code, PatchedImmPtr imm) {
    3657           0 :         MOZ_CRASH("Unused.");
    3658             :     }
    3659             : 
    3660          64 :     static uint32_t NopSize() {
    3661          64 :         return 1;
    3662             :     }
    3663             :     static uint8_t* NextInstruction(uint8_t* cur, uint32_t* count) {
    3664             :         MOZ_CRASH("nextInstruction NYI on x86");
    3665             :     }
    3666             : 
    3667             :     // Toggle a jmp or cmp emitted by toggledJump().
    3668           0 :     static void ToggleToJmp(CodeLocationLabel inst) {
    3669           0 :         uint8_t* ptr = (uint8_t*)inst.raw();
    3670           0 :         MOZ_ASSERT(*ptr == 0x3D);
    3671           0 :         *ptr = 0xE9;
    3672           0 :     }
    3673           0 :     static void ToggleToCmp(CodeLocationLabel inst) {
    3674           0 :         uint8_t* ptr = (uint8_t*)inst.raw();
    3675           0 :         MOZ_ASSERT(*ptr == 0xE9);
    3676           0 :         *ptr = 0x3D;
    3677           0 :     }
    3678           0 :     static void ToggleCall(CodeLocationLabel inst, bool enabled) {
    3679           0 :         uint8_t* ptr = (uint8_t*)inst.raw();
    3680           0 :         MOZ_ASSERT(*ptr == 0x3D || // CMP
    3681             :                    *ptr == 0xE8);  // CALL
    3682           0 :         *ptr = enabled ? 0xE8 : 0x3D;
    3683           0 :     }
    3684             : 
    3685             :     MOZ_COLD void verifyHeapAccessDisassembly(uint32_t begin, uint32_t end,
    3686             :                                               const Disassembler::HeapAccess& heapAccess);
    3687             : };
    3688             : 
    3689             : } // namespace jit
    3690             : } // namespace js
    3691             : 
    3692             : #endif /* jit_x86_shared_Assembler_x86_shared_h */

Generated by: LCOV version 1.13