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