Coverage Report

Created: 2018-09-25 14:53

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