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