Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
3 : * This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef jit_x86_shared_MacroAssembler_x86_shared_inl_h
8 : #define jit_x86_shared_MacroAssembler_x86_shared_inl_h
9 :
10 : #include "jit/x86-shared/MacroAssembler-x86-shared.h"
11 :
12 : namespace js {
13 : namespace jit {
14 :
15 : //{{{ check_macroassembler_style
16 : // ===============================================================
17 : // Move instructions
18 :
19 : void
20 0 : MacroAssembler::moveFloat32ToGPR(FloatRegister src, Register dest)
21 : {
22 0 : vmovd(src, dest);
23 0 : }
24 :
25 : void
26 0 : MacroAssembler::moveGPRToFloat32(Register src, FloatRegister dest)
27 : {
28 0 : vmovd(src, dest);
29 0 : }
30 :
31 : void
32 0 : MacroAssembler::move8SignExtend(Register src, Register dest)
33 : {
34 0 : movsbl(src, dest);
35 0 : }
36 :
37 : void
38 0 : MacroAssembler::move16SignExtend(Register src, Register dest)
39 : {
40 0 : movswl(src, dest);
41 0 : }
42 :
43 : // ===============================================================
44 : // Logical instructions
45 :
46 : void
47 0 : MacroAssembler::not32(Register reg)
48 : {
49 0 : notl(reg);
50 0 : }
51 :
52 : void
53 164 : MacroAssembler::and32(Register src, Register dest)
54 : {
55 164 : andl(src, dest);
56 164 : }
57 :
58 : void
59 192 : MacroAssembler::and32(Imm32 imm, Register dest)
60 : {
61 192 : andl(imm, dest);
62 192 : }
63 :
64 : void
65 0 : MacroAssembler::and32(Imm32 imm, const Address& dest)
66 : {
67 0 : andl(imm, Operand(dest));
68 0 : }
69 :
70 : void
71 4 : MacroAssembler::and32(const Address& src, Register dest)
72 : {
73 4 : andl(Operand(src), dest);
74 4 : }
75 :
76 : void
77 0 : MacroAssembler::or32(Register src, Register dest)
78 : {
79 0 : orl(src, dest);
80 0 : }
81 :
82 : void
83 0 : MacroAssembler::or32(Imm32 imm, Register dest)
84 : {
85 0 : orl(imm, dest);
86 0 : }
87 :
88 : void
89 185 : MacroAssembler::or32(Imm32 imm, const Address& dest)
90 : {
91 185 : orl(imm, Operand(dest));
92 185 : }
93 :
94 : void
95 0 : MacroAssembler::xor32(Register src, Register dest)
96 : {
97 0 : xorl(src, dest);
98 0 : }
99 :
100 : void
101 37 : MacroAssembler::xor32(Imm32 imm, Register dest)
102 : {
103 37 : xorl(imm, dest);
104 37 : }
105 :
106 : void
107 0 : MacroAssembler::clz32(Register src, Register dest, bool knownNotZero)
108 : {
109 : // On very recent chips (Haswell and newer?) there is actually an
110 : // LZCNT instruction that does all of this.
111 :
112 0 : bsrl(src, dest);
113 0 : if (!knownNotZero) {
114 : // If the source is zero then bsrl leaves garbage in the destination.
115 0 : Label nonzero;
116 0 : j(Assembler::NonZero, &nonzero);
117 0 : movl(Imm32(0x3F), dest);
118 0 : bind(&nonzero);
119 : }
120 0 : xorl(Imm32(0x1F), dest);
121 0 : }
122 :
123 : void
124 0 : MacroAssembler::ctz32(Register src, Register dest, bool knownNotZero)
125 : {
126 0 : bsfl(src, dest);
127 0 : if (!knownNotZero) {
128 0 : Label nonzero;
129 0 : j(Assembler::NonZero, &nonzero);
130 0 : movl(Imm32(32), dest);
131 0 : bind(&nonzero);
132 : }
133 0 : }
134 :
135 : void
136 0 : MacroAssembler::popcnt32(Register input, Register output, Register tmp)
137 : {
138 0 : if (AssemblerX86Shared::HasPOPCNT()) {
139 0 : popcntl(input, output);
140 0 : return;
141 : }
142 :
143 0 : MOZ_ASSERT(tmp != InvalidReg);
144 :
145 : // Equivalent to mozilla::CountPopulation32()
146 :
147 0 : movl(input, tmp);
148 0 : if (input != output)
149 0 : movl(input, output);
150 0 : shrl(Imm32(1), output);
151 0 : andl(Imm32(0x55555555), output);
152 0 : subl(output, tmp);
153 0 : movl(tmp, output);
154 0 : andl(Imm32(0x33333333), output);
155 0 : shrl(Imm32(2), tmp);
156 0 : andl(Imm32(0x33333333), tmp);
157 0 : addl(output, tmp);
158 0 : movl(tmp, output);
159 0 : shrl(Imm32(4), output);
160 0 : addl(tmp, output);
161 0 : andl(Imm32(0xF0F0F0F), output);
162 0 : imull(Imm32(0x1010101), output, output);
163 0 : shrl(Imm32(24), output);
164 : }
165 :
166 : // ===============================================================
167 : // Arithmetic instructions
168 :
169 : void
170 4 : MacroAssembler::add32(Register src, Register dest)
171 : {
172 4 : addl(src, dest);
173 4 : }
174 :
175 : void
176 1147 : MacroAssembler::add32(Imm32 imm, Register dest)
177 : {
178 1147 : addl(imm, dest);
179 1147 : }
180 :
181 : void
182 8 : MacroAssembler::add32(Imm32 imm, const Address& dest)
183 : {
184 8 : addl(imm, Operand(dest));
185 8 : }
186 :
187 : void
188 : MacroAssembler::add32(Imm32 imm, const AbsoluteAddress& dest)
189 : {
190 : addl(imm, Operand(dest));
191 : }
192 :
193 : void
194 0 : MacroAssembler::addFloat32(FloatRegister src, FloatRegister dest)
195 : {
196 0 : vaddss(src, dest, dest);
197 0 : }
198 :
199 : void
200 0 : MacroAssembler::addDouble(FloatRegister src, FloatRegister dest)
201 : {
202 0 : vaddsd(src, dest, dest);
203 0 : }
204 :
205 : void
206 6 : MacroAssembler::sub32(Register src, Register dest)
207 : {
208 6 : subl(src, dest);
209 6 : }
210 :
211 : void
212 453 : MacroAssembler::sub32(Imm32 imm, Register dest)
213 : {
214 453 : subl(imm, dest);
215 453 : }
216 :
217 : void
218 0 : MacroAssembler::sub32(const Address& src, Register dest)
219 : {
220 0 : subl(Operand(src), dest);
221 0 : }
222 :
223 : void
224 0 : MacroAssembler::subDouble(FloatRegister src, FloatRegister dest)
225 : {
226 0 : vsubsd(src, dest, dest);
227 0 : }
228 :
229 : void
230 0 : MacroAssembler::subFloat32(FloatRegister src, FloatRegister dest)
231 : {
232 0 : vsubss(src, dest, dest);
233 0 : }
234 :
235 : void
236 0 : MacroAssembler::mul32(Register rhs, Register srcDest)
237 : {
238 0 : MOZ_ASSERT(srcDest == eax);
239 0 : imull(rhs, srcDest); // Clobbers edx
240 0 : }
241 :
242 : void
243 0 : MacroAssembler::mulFloat32(FloatRegister src, FloatRegister dest)
244 : {
245 0 : vmulss(src, dest, dest);
246 0 : }
247 :
248 : void
249 0 : MacroAssembler::mulDouble(FloatRegister src, FloatRegister dest)
250 : {
251 0 : vmulsd(src, dest, dest);
252 0 : }
253 :
254 : void
255 0 : MacroAssembler::quotient32(Register rhs, Register srcDest, bool isUnsigned)
256 : {
257 0 : MOZ_ASSERT(srcDest == eax);
258 :
259 : // Sign extend eax into edx to make (edx:eax): idiv/udiv are 64-bit.
260 0 : if (isUnsigned) {
261 0 : mov(ImmWord(0), edx);
262 0 : udiv(rhs);
263 : } else {
264 0 : cdq();
265 0 : idiv(rhs);
266 : }
267 0 : }
268 :
269 : void
270 0 : MacroAssembler::remainder32(Register rhs, Register srcDest, bool isUnsigned)
271 : {
272 0 : MOZ_ASSERT(srcDest == eax);
273 :
274 : // Sign extend eax into edx to make (edx:eax): idiv/udiv are 64-bit.
275 0 : if (isUnsigned) {
276 0 : mov(ImmWord(0), edx);
277 0 : udiv(rhs);
278 : } else {
279 0 : cdq();
280 0 : idiv(rhs);
281 : }
282 0 : mov(edx, eax);
283 0 : }
284 :
285 : void
286 0 : MacroAssembler::divFloat32(FloatRegister src, FloatRegister dest)
287 : {
288 0 : vdivss(src, dest, dest);
289 0 : }
290 :
291 : void
292 1 : MacroAssembler::divDouble(FloatRegister src, FloatRegister dest)
293 : {
294 1 : vdivsd(src, dest, dest);
295 1 : }
296 :
297 : void
298 0 : MacroAssembler::neg32(Register reg)
299 : {
300 0 : negl(reg);
301 0 : }
302 :
303 : void
304 0 : MacroAssembler::negateFloat(FloatRegister reg)
305 : {
306 0 : ScratchFloat32Scope scratch(*this);
307 0 : vpcmpeqw(Operand(scratch), scratch, scratch);
308 0 : vpsllq(Imm32(31), scratch, scratch);
309 :
310 : // XOR the float in a float register with -0.0.
311 0 : vxorps(scratch, reg, reg); // s ^ 0x80000000
312 0 : }
313 :
314 : void
315 0 : MacroAssembler::negateDouble(FloatRegister reg)
316 : {
317 : // From MacroAssemblerX86Shared::maybeInlineDouble
318 0 : ScratchDoubleScope scratch(*this);
319 0 : vpcmpeqw(Operand(scratch), scratch, scratch);
320 0 : vpsllq(Imm32(63), scratch, scratch);
321 :
322 : // XOR the float in a float register with -0.0.
323 0 : vxorpd(scratch, reg, reg); // s ^ 0x80000000000000
324 0 : }
325 :
326 : void
327 0 : MacroAssembler::absFloat32(FloatRegister src, FloatRegister dest)
328 : {
329 0 : ScratchFloat32Scope scratch(*this);
330 0 : loadConstantFloat32(mozilla::SpecificNaN<float>(0, mozilla::FloatingPoint<float>::kSignificandBits), scratch);
331 0 : vandps(scratch, src, dest);
332 0 : }
333 :
334 : void
335 0 : MacroAssembler::absDouble(FloatRegister src, FloatRegister dest)
336 : {
337 0 : ScratchDoubleScope scratch(*this);
338 0 : loadConstantDouble(mozilla::SpecificNaN<double>(0, mozilla::FloatingPoint<double>::kSignificandBits), scratch);
339 0 : vandpd(scratch, src, dest);
340 0 : }
341 :
342 : void
343 0 : MacroAssembler::sqrtFloat32(FloatRegister src, FloatRegister dest)
344 : {
345 0 : vsqrtss(src, src, dest);
346 0 : }
347 :
348 : void
349 0 : MacroAssembler::sqrtDouble(FloatRegister src, FloatRegister dest)
350 : {
351 0 : vsqrtsd(src, src, dest);
352 0 : }
353 :
354 : void
355 0 : MacroAssembler::minFloat32(FloatRegister other, FloatRegister srcDest, bool handleNaN)
356 : {
357 0 : minMaxFloat32(srcDest, other, handleNaN, false);
358 0 : }
359 :
360 : void
361 0 : MacroAssembler::minDouble(FloatRegister other, FloatRegister srcDest, bool handleNaN)
362 : {
363 0 : minMaxDouble(srcDest, other, handleNaN, false);
364 0 : }
365 :
366 : void
367 0 : MacroAssembler::maxFloat32(FloatRegister other, FloatRegister srcDest, bool handleNaN)
368 : {
369 0 : minMaxFloat32(srcDest, other, handleNaN, true);
370 0 : }
371 :
372 : void
373 0 : MacroAssembler::maxDouble(FloatRegister other, FloatRegister srcDest, bool handleNaN)
374 : {
375 0 : minMaxDouble(srcDest, other, handleNaN, true);
376 0 : }
377 :
378 : // ===============================================================
379 : // Rotation instructions
380 : void
381 0 : MacroAssembler::rotateLeft(Imm32 count, Register input, Register dest)
382 : {
383 0 : MOZ_ASSERT(input == dest, "defineReuseInput");
384 0 : count.value &= 0x1f;
385 0 : if (count.value)
386 0 : roll(count, input);
387 0 : }
388 :
389 : void
390 0 : MacroAssembler::rotateLeft(Register count, Register input, Register dest)
391 : {
392 0 : MOZ_ASSERT(input == dest, "defineReuseInput");
393 0 : MOZ_ASSERT(count == ecx, "defineFixed(ecx)");
394 0 : roll_cl(input);
395 0 : }
396 :
397 : void
398 0 : MacroAssembler::rotateRight(Imm32 count, Register input, Register dest)
399 : {
400 0 : MOZ_ASSERT(input == dest, "defineReuseInput");
401 0 : count.value &= 0x1f;
402 0 : if (count.value)
403 0 : rorl(count, input);
404 0 : }
405 :
406 : void
407 0 : MacroAssembler::rotateRight(Register count, Register input, Register dest)
408 : {
409 0 : MOZ_ASSERT(input == dest, "defineReuseInput");
410 0 : MOZ_ASSERT(count == ecx, "defineFixed(ecx)");
411 0 : rorl_cl(input);
412 0 : }
413 :
414 : // ===============================================================
415 : // Shift instructions
416 :
417 : void
418 0 : MacroAssembler::lshift32(Register shift, Register srcDest)
419 : {
420 0 : MOZ_ASSERT(shift == ecx);
421 0 : shll_cl(srcDest);
422 0 : }
423 :
424 : void
425 0 : MacroAssembler::rshift32(Register shift, Register srcDest)
426 : {
427 0 : MOZ_ASSERT(shift == ecx);
428 0 : shrl_cl(srcDest);
429 0 : }
430 :
431 : void
432 0 : MacroAssembler::rshift32Arithmetic(Register shift, Register srcDest)
433 : {
434 0 : MOZ_ASSERT(shift == ecx);
435 0 : sarl_cl(srcDest);
436 0 : }
437 :
438 : void
439 0 : MacroAssembler::lshift32(Imm32 shift, Register srcDest)
440 : {
441 0 : shll(shift, srcDest);
442 0 : }
443 :
444 : void
445 2 : MacroAssembler::rshift32(Imm32 shift, Register srcDest)
446 : {
447 2 : shrl(shift, srcDest);
448 2 : }
449 :
450 : void
451 0 : MacroAssembler::rshift32Arithmetic(Imm32 shift, Register srcDest)
452 : {
453 0 : sarl(shift, srcDest);
454 0 : }
455 :
456 : // ===============================================================
457 : // Condition functions
458 :
459 : template <typename T1, typename T2>
460 : void
461 2 : MacroAssembler::cmp32Set(Condition cond, T1 lhs, T2 rhs, Register dest)
462 : {
463 2 : cmp32(lhs, rhs);
464 2 : emitSet(cond, dest);
465 2 : }
466 :
467 : // ===============================================================
468 : // Branch instructions
469 :
470 : template <class L>
471 : void
472 78 : MacroAssembler::branch32(Condition cond, Register lhs, Register rhs, L label)
473 : {
474 78 : cmp32(lhs, rhs);
475 78 : j(cond, label);
476 78 : }
477 :
478 : template <class L>
479 : void
480 2067 : MacroAssembler::branch32(Condition cond, Register lhs, Imm32 rhs, L label)
481 : {
482 2067 : cmp32(lhs, rhs);
483 2067 : j(cond, label);
484 2067 : }
485 :
486 : void
487 101 : MacroAssembler::branch32(Condition cond, const Address& lhs, Register rhs, Label* label)
488 : {
489 101 : cmp32(Operand(lhs), rhs);
490 101 : j(cond, label);
491 101 : }
492 :
493 : void
494 1601 : MacroAssembler::branch32(Condition cond, const Address& lhs, Imm32 rhs, Label* label)
495 : {
496 1601 : cmp32(Operand(lhs), rhs);
497 1601 : j(cond, label);
498 1601 : }
499 :
500 : void
501 : MacroAssembler::branch32(Condition cond, const BaseIndex& lhs, Register rhs, Label* label)
502 : {
503 : cmp32(Operand(lhs), rhs);
504 : j(cond, label);
505 : }
506 :
507 : void
508 0 : MacroAssembler::branch32(Condition cond, const BaseIndex& lhs, Imm32 rhs, Label* label)
509 : {
510 0 : cmp32(Operand(lhs), rhs);
511 0 : j(cond, label);
512 0 : }
513 :
514 : void
515 : MacroAssembler::branch32(Condition cond, const Operand& lhs, Register rhs, Label* label)
516 : {
517 : cmp32(lhs, rhs);
518 : j(cond, label);
519 : }
520 :
521 : void
522 0 : MacroAssembler::branch32(Condition cond, const Operand& lhs, Imm32 rhs, Label* label)
523 : {
524 0 : cmp32(lhs, rhs);
525 0 : j(cond, label);
526 0 : }
527 :
528 : template <class L>
529 : void
530 305 : MacroAssembler::branchPtr(Condition cond, Register lhs, Register rhs, L label)
531 : {
532 305 : cmpPtr(lhs, rhs);
533 305 : j(cond, label);
534 305 : }
535 :
536 : void
537 1329 : MacroAssembler::branchPtr(Condition cond, Register lhs, Imm32 rhs, Label* label)
538 : {
539 1329 : branchPtrImpl(cond, lhs, rhs, label);
540 1329 : }
541 :
542 : void
543 70 : MacroAssembler::branchPtr(Condition cond, Register lhs, ImmPtr rhs, Label* label)
544 : {
545 70 : branchPtrImpl(cond, lhs, rhs, label);
546 70 : }
547 :
548 : void
549 101 : MacroAssembler::branchPtr(Condition cond, Register lhs, ImmGCPtr rhs, Label* label)
550 : {
551 101 : branchPtrImpl(cond, lhs, rhs, label);
552 101 : }
553 :
554 : void
555 311 : MacroAssembler::branchPtr(Condition cond, Register lhs, ImmWord rhs, Label* label)
556 : {
557 311 : branchPtrImpl(cond, lhs, rhs, label);
558 311 : }
559 :
560 : template <class L>
561 : void
562 1633 : MacroAssembler::branchPtr(Condition cond, const Address& lhs, Register rhs, L label)
563 : {
564 1633 : branchPtrImpl(cond, lhs, rhs, label);
565 1633 : }
566 :
567 : void
568 945 : MacroAssembler::branchPtr(Condition cond, const Address& lhs, ImmPtr rhs, Label* label)
569 : {
570 945 : branchPtrImpl(cond, lhs, rhs, label);
571 945 : }
572 :
573 : void
574 25 : MacroAssembler::branchPtr(Condition cond, const Address& lhs, ImmGCPtr rhs, Label* label)
575 : {
576 25 : branchPtrImpl(cond, lhs, rhs, label);
577 25 : }
578 :
579 : void
580 92 : MacroAssembler::branchPtr(Condition cond, const Address& lhs, ImmWord rhs, Label* label)
581 : {
582 92 : branchPtrImpl(cond, lhs, rhs, label);
583 92 : }
584 :
585 : void
586 7 : MacroAssembler::branchPtr(Condition cond, const BaseIndex& lhs, ImmWord rhs, Label* label)
587 : {
588 7 : branchPtrImpl(cond, lhs, rhs, label);
589 7 : }
590 :
591 : template <typename T, typename S, typename L>
592 : void
593 4686 : MacroAssembler::branchPtrImpl(Condition cond, const T& lhs, const S& rhs, L label)
594 : {
595 4686 : cmpPtr(Operand(lhs), rhs);
596 4686 : j(cond, label);
597 4686 : }
598 :
599 : template <typename T>
600 : CodeOffsetJump
601 : MacroAssembler::branchPtrWithPatch(Condition cond, Register lhs, T rhs, RepatchLabel* label)
602 : {
603 : cmpPtr(lhs, rhs);
604 : return jumpWithPatch(label, cond);
605 : }
606 :
607 : template <typename T>
608 : CodeOffsetJump
609 : MacroAssembler::branchPtrWithPatch(Condition cond, Address lhs, T rhs, RepatchLabel* label)
610 : {
611 : cmpPtr(lhs, rhs);
612 : return jumpWithPatch(label, cond);
613 : }
614 :
615 : void
616 0 : MacroAssembler::branchFloat(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs,
617 : Label* label)
618 : {
619 0 : compareFloat(cond, lhs, rhs);
620 :
621 0 : if (cond == DoubleEqual) {
622 0 : Label unordered;
623 0 : j(Parity, &unordered);
624 0 : j(Equal, label);
625 0 : bind(&unordered);
626 0 : return;
627 : }
628 :
629 0 : if (cond == DoubleNotEqualOrUnordered) {
630 0 : j(NotEqual, label);
631 0 : j(Parity, label);
632 0 : return;
633 : }
634 :
635 0 : MOZ_ASSERT(!(cond & DoubleConditionBitSpecial));
636 0 : j(ConditionFromDoubleCondition(cond), label);
637 : }
638 :
639 : void
640 0 : MacroAssembler::branchDouble(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs,
641 : Label* label)
642 : {
643 0 : compareDouble(cond, lhs, rhs);
644 :
645 0 : if (cond == DoubleEqual) {
646 0 : Label unordered;
647 0 : j(Parity, &unordered);
648 0 : j(Equal, label);
649 0 : bind(&unordered);
650 0 : return;
651 : }
652 0 : if (cond == DoubleNotEqualOrUnordered) {
653 0 : j(NotEqual, label);
654 0 : j(Parity, label);
655 0 : return;
656 : }
657 :
658 0 : MOZ_ASSERT(!(cond & DoubleConditionBitSpecial));
659 0 : j(ConditionFromDoubleCondition(cond), label);
660 : }
661 :
662 : template <typename T, typename L>
663 : void
664 0 : MacroAssembler::branchAdd32(Condition cond, T src, Register dest, L label)
665 : {
666 0 : addl(src, dest);
667 0 : j(cond, label);
668 0 : }
669 :
670 : template <typename T>
671 : void
672 201 : MacroAssembler::branchSub32(Condition cond, T src, Register dest, Label* label)
673 : {
674 201 : subl(src, dest);
675 201 : j(cond, label);
676 201 : }
677 :
678 : void
679 0 : MacroAssembler::decBranchPtr(Condition cond, Register lhs, Imm32 rhs, Label* label)
680 : {
681 0 : subPtr(rhs, lhs);
682 0 : j(cond, label);
683 0 : }
684 :
685 : template <class L>
686 : void
687 551 : MacroAssembler::branchTest32(Condition cond, Register lhs, Register rhs, L label)
688 : {
689 551 : MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
690 551 : test32(lhs, rhs);
691 551 : j(cond, label);
692 551 : }
693 :
694 : template <class L>
695 : void
696 199 : MacroAssembler::branchTest32(Condition cond, Register lhs, Imm32 rhs, L label)
697 : {
698 199 : MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
699 199 : test32(lhs, rhs);
700 199 : j(cond, label);
701 199 : }
702 :
703 : void
704 7713 : MacroAssembler::branchTest32(Condition cond, const Address& lhs, Imm32 rhs, Label* label)
705 : {
706 7713 : MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
707 7713 : test32(Operand(lhs), rhs);
708 7713 : j(cond, label);
709 7713 : }
710 :
711 : template <class L>
712 : void
713 357 : MacroAssembler::branchTestPtr(Condition cond, Register lhs, Register rhs, L label)
714 : {
715 357 : testPtr(lhs, rhs);
716 357 : j(cond, label);
717 357 : }
718 :
719 : void
720 13390 : MacroAssembler::branchTestPtr(Condition cond, Register lhs, Imm32 rhs, Label* label)
721 : {
722 13390 : testPtr(lhs, rhs);
723 13390 : j(cond, label);
724 13390 : }
725 :
726 : void
727 57 : MacroAssembler::branchTestPtr(Condition cond, const Address& lhs, Imm32 rhs, Label* label)
728 : {
729 57 : testPtr(Operand(lhs), rhs);
730 57 : j(cond, label);
731 57 : }
732 :
733 : void
734 105 : MacroAssembler::branchTestUndefined(Condition cond, Register tag, Label* label)
735 : {
736 105 : branchTestUndefinedImpl(cond, tag, label);
737 105 : }
738 :
739 : void
740 0 : MacroAssembler::branchTestUndefined(Condition cond, const Address& address, Label* label)
741 : {
742 0 : branchTestUndefinedImpl(cond, address, label);
743 0 : }
744 :
745 : void
746 : MacroAssembler::branchTestUndefined(Condition cond, const BaseIndex& address, Label* label)
747 : {
748 : branchTestUndefinedImpl(cond, address, label);
749 : }
750 :
751 : void
752 339 : MacroAssembler::branchTestUndefined(Condition cond, const ValueOperand& value, Label* label)
753 : {
754 339 : branchTestUndefinedImpl(cond, value, label);
755 339 : }
756 :
757 : template <typename T>
758 : void
759 444 : MacroAssembler::branchTestUndefinedImpl(Condition cond, const T& t, Label* label)
760 : {
761 444 : cond = testUndefined(cond, t);
762 444 : j(cond, label);
763 444 : }
764 :
765 : void
766 34 : MacroAssembler::branchTestInt32(Condition cond, Register tag, Label* label)
767 : {
768 34 : branchTestInt32Impl(cond, tag, label);
769 34 : }
770 :
771 : void
772 32 : MacroAssembler::branchTestInt32(Condition cond, const Address& address, Label* label)
773 : {
774 32 : branchTestInt32Impl(cond, address, label);
775 32 : }
776 :
777 : void
778 0 : MacroAssembler::branchTestInt32(Condition cond, const BaseIndex& address, Label* label)
779 : {
780 0 : branchTestInt32Impl(cond, address, label);
781 0 : }
782 :
783 : void
784 560 : MacroAssembler::branchTestInt32(Condition cond, const ValueOperand& value, Label* label)
785 : {
786 560 : branchTestInt32Impl(cond, value, label);
787 560 : }
788 :
789 : template <typename T>
790 : void
791 626 : MacroAssembler::branchTestInt32Impl(Condition cond, const T& t, Label* label)
792 : {
793 626 : cond = testInt32(cond, t);
794 626 : j(cond, label);
795 626 : }
796 :
797 : void
798 11 : MacroAssembler::branchTestInt32Truthy(bool truthy, const ValueOperand& value, Label* label)
799 : {
800 11 : Condition cond = testInt32Truthy(truthy, value);
801 11 : j(cond, label);
802 11 : }
803 :
804 : void
805 24 : MacroAssembler::branchTestDouble(Condition cond, Register tag, Label* label)
806 : {
807 24 : branchTestDoubleImpl(cond, tag, label);
808 24 : }
809 :
810 : void
811 0 : MacroAssembler::branchTestDouble(Condition cond, const Address& address, Label* label)
812 : {
813 0 : branchTestDoubleImpl(cond, address, label);
814 0 : }
815 :
816 : void
817 : MacroAssembler::branchTestDouble(Condition cond, const BaseIndex& address, Label* label)
818 : {
819 : branchTestDoubleImpl(cond, address, label);
820 : }
821 :
822 : void
823 27 : MacroAssembler::branchTestDouble(Condition cond, const ValueOperand& value, Label* label)
824 : {
825 27 : branchTestDoubleImpl(cond, value, label);
826 27 : }
827 :
828 : template <typename T>
829 : void
830 51 : MacroAssembler::branchTestDoubleImpl(Condition cond, const T& t, Label* label)
831 : {
832 51 : cond = testDouble(cond, t);
833 51 : j(cond, label);
834 51 : }
835 :
836 : void
837 1 : MacroAssembler::branchTestDoubleTruthy(bool truthy, FloatRegister reg, Label* label)
838 : {
839 1 : Condition cond = testDoubleTruthy(truthy, reg);
840 1 : j(cond, label);
841 1 : }
842 :
843 : void
844 1 : MacroAssembler::branchTestNumber(Condition cond, Register tag, Label* label)
845 : {
846 1 : branchTestNumberImpl(cond, tag, label);
847 1 : }
848 :
849 : void
850 173 : MacroAssembler::branchTestNumber(Condition cond, const ValueOperand& value, Label* label)
851 : {
852 173 : branchTestNumberImpl(cond, value, label);
853 173 : }
854 :
855 : template <typename T>
856 : void
857 174 : MacroAssembler::branchTestNumberImpl(Condition cond, const T& t, Label* label)
858 : {
859 174 : cond = testNumber(cond, t);
860 174 : j(cond, label);
861 174 : }
862 :
863 : void
864 52 : MacroAssembler::branchTestBoolean(Condition cond, Register tag, Label* label)
865 : {
866 52 : branchTestBooleanImpl(cond, tag, label);
867 52 : }
868 :
869 : void
870 0 : MacroAssembler::branchTestBoolean(Condition cond, const Address& address, Label* label)
871 : {
872 0 : branchTestBooleanImpl(cond, address, label);
873 0 : }
874 :
875 : void
876 : MacroAssembler::branchTestBoolean(Condition cond, const BaseIndex& address, Label* label)
877 : {
878 : branchTestBooleanImpl(cond, address, label);
879 : }
880 :
881 : void
882 1613 : MacroAssembler::branchTestBoolean(Condition cond, const ValueOperand& value, Label* label)
883 : {
884 1613 : branchTestBooleanImpl(cond, value, label);
885 1613 : }
886 :
887 : template <typename T>
888 : void
889 1665 : MacroAssembler::branchTestBooleanImpl(Condition cond, const T& t, Label* label)
890 : {
891 1665 : cond = testBoolean(cond, t);
892 1665 : j(cond, label);
893 1665 : }
894 :
895 : void
896 25 : MacroAssembler::branchTestString(Condition cond, Register tag, Label* label)
897 : {
898 25 : branchTestStringImpl(cond, tag, label);
899 25 : }
900 :
901 : void
902 : MacroAssembler::branchTestString(Condition cond, const BaseIndex& address, Label* label)
903 : {
904 : branchTestStringImpl(cond, address, label);
905 : }
906 :
907 : void
908 312 : MacroAssembler::branchTestString(Condition cond, const ValueOperand& value, Label* label)
909 : {
910 312 : branchTestStringImpl(cond, value, label);
911 312 : }
912 :
913 : template <typename T>
914 : void
915 337 : MacroAssembler::branchTestStringImpl(Condition cond, const T& t, Label* label)
916 : {
917 337 : cond = testString(cond, t);
918 337 : j(cond, label);
919 337 : }
920 :
921 : void
922 21 : MacroAssembler::branchTestStringTruthy(bool truthy, const ValueOperand& value, Label* label)
923 : {
924 21 : Condition cond = testStringTruthy(truthy, value);
925 21 : j(cond, label);
926 21 : }
927 :
928 : void
929 0 : MacroAssembler::branchTestSymbol(Condition cond, Register tag, Label* label)
930 : {
931 0 : branchTestSymbolImpl(cond, tag, label);
932 0 : }
933 :
934 : void
935 : MacroAssembler::branchTestSymbol(Condition cond, const BaseIndex& address, Label* label)
936 : {
937 : branchTestSymbolImpl(cond, address, label);
938 : }
939 :
940 : void
941 21 : MacroAssembler::branchTestSymbol(Condition cond, const ValueOperand& value, Label* label)
942 : {
943 21 : branchTestSymbolImpl(cond, value, label);
944 21 : }
945 :
946 : template <typename T>
947 : void
948 21 : MacroAssembler::branchTestSymbolImpl(Condition cond, const T& t, Label* label)
949 : {
950 21 : cond = testSymbol(cond, t);
951 21 : j(cond, label);
952 21 : }
953 :
954 : void
955 3 : MacroAssembler::branchTestNull(Condition cond, Register tag, Label* label)
956 : {
957 3 : branchTestNullImpl(cond, tag, label);
958 3 : }
959 :
960 : void
961 4 : MacroAssembler::branchTestNull(Condition cond, const Address& address, Label* label)
962 : {
963 4 : branchTestNullImpl(cond, address, label);
964 4 : }
965 :
966 : void
967 : MacroAssembler::branchTestNull(Condition cond, const BaseIndex& address, Label* label)
968 : {
969 : branchTestNullImpl(cond, address, label);
970 : }
971 :
972 : void
973 243 : MacroAssembler::branchTestNull(Condition cond, const ValueOperand& value, Label* label)
974 : {
975 243 : branchTestNullImpl(cond, value, label);
976 243 : }
977 :
978 : template <typename T>
979 : void
980 250 : MacroAssembler::branchTestNullImpl(Condition cond, const T& t, Label* label)
981 : {
982 250 : cond = testNull(cond, t);
983 250 : j(cond, label);
984 250 : }
985 :
986 : void
987 38 : MacroAssembler::branchTestObject(Condition cond, Register tag, Label* label)
988 : {
989 38 : branchTestObjectImpl(cond, tag, label);
990 38 : }
991 :
992 : void
993 24 : MacroAssembler::branchTestObject(Condition cond, const Address& address, Label* label)
994 : {
995 24 : branchTestObjectImpl(cond, address, label);
996 24 : }
997 :
998 : void
999 2 : MacroAssembler::branchTestObject(Condition cond, const BaseIndex& address, Label* label)
1000 : {
1001 2 : branchTestObjectImpl(cond, address, label);
1002 2 : }
1003 :
1004 : void
1005 1605 : MacroAssembler::branchTestObject(Condition cond, const ValueOperand& value, Label* label)
1006 : {
1007 1605 : branchTestObjectImpl(cond, value, label);
1008 1605 : }
1009 :
1010 : template <typename T>
1011 : void
1012 1669 : MacroAssembler::branchTestObjectImpl(Condition cond, const T& t, Label* label)
1013 : {
1014 1669 : cond = testObject(cond, t);
1015 1669 : j(cond, label);
1016 1669 : }
1017 :
1018 : void
1019 190 : MacroAssembler::branchTestGCThing(Condition cond, const Address& address, Label* label)
1020 : {
1021 190 : branchTestGCThingImpl(cond, address, label);
1022 190 : }
1023 :
1024 : void
1025 17 : MacroAssembler::branchTestGCThing(Condition cond, const BaseIndex& address, Label* label)
1026 : {
1027 17 : branchTestGCThingImpl(cond, address, label);
1028 17 : }
1029 :
1030 : template <typename T>
1031 : void
1032 207 : MacroAssembler::branchTestGCThingImpl(Condition cond, const T& t, Label* label)
1033 : {
1034 207 : cond = testGCThing(cond, t);
1035 207 : j(cond, label);
1036 207 : }
1037 :
1038 : void
1039 : MacroAssembler::branchTestPrimitive(Condition cond, Register tag, Label* label)
1040 : {
1041 : branchTestPrimitiveImpl(cond, tag, label);
1042 : }
1043 :
1044 : void
1045 4 : MacroAssembler::branchTestPrimitive(Condition cond, const ValueOperand& value, Label* label)
1046 : {
1047 4 : branchTestPrimitiveImpl(cond, value, label);
1048 4 : }
1049 :
1050 : template <typename T>
1051 : void
1052 4 : MacroAssembler::branchTestPrimitiveImpl(Condition cond, const T& t, Label* label)
1053 : {
1054 4 : cond = testPrimitive(cond, t);
1055 4 : j(cond, label);
1056 4 : }
1057 :
1058 : void
1059 0 : MacroAssembler::branchTestMagic(Condition cond, Register tag, Label* label)
1060 : {
1061 0 : branchTestMagicImpl(cond, tag, label);
1062 0 : }
1063 :
1064 : void
1065 28 : MacroAssembler::branchTestMagic(Condition cond, const Address& address, Label* label)
1066 : {
1067 28 : branchTestMagicImpl(cond, address, label);
1068 28 : }
1069 :
1070 : void
1071 21 : MacroAssembler::branchTestMagic(Condition cond, const BaseIndex& address, Label* label)
1072 : {
1073 21 : branchTestMagicImpl(cond, address, label);
1074 21 : }
1075 :
1076 : template <class L>
1077 : void
1078 12 : MacroAssembler::branchTestMagic(Condition cond, const ValueOperand& value, L label)
1079 : {
1080 12 : branchTestMagicImpl(cond, value, label);
1081 12 : }
1082 :
1083 : template <typename T, class L>
1084 : void
1085 61 : MacroAssembler::branchTestMagicImpl(Condition cond, const T& t, L label)
1086 : {
1087 61 : cond = testMagic(cond, t);
1088 61 : j(cond, label);
1089 61 : }
1090 :
1091 : // ========================================================================
1092 : // Canonicalization primitives.
1093 : void
1094 : MacroAssembler::canonicalizeFloat32x4(FloatRegister reg, FloatRegister scratch)
1095 : {
1096 : ScratchSimd128Scope scratch2(*this);
1097 :
1098 : MOZ_ASSERT(scratch.asSimd128() != scratch2.asSimd128());
1099 : MOZ_ASSERT(reg.asSimd128() != scratch2.asSimd128());
1100 : MOZ_ASSERT(reg.asSimd128() != scratch.asSimd128());
1101 :
1102 : FloatRegister mask = scratch;
1103 : vcmpordps(Operand(reg), reg, mask);
1104 :
1105 : FloatRegister ifFalse = scratch2;
1106 : float nanf = float(JS::GenericNaN());
1107 : loadConstantSimd128Float(SimdConstant::SplatX4(nanf), ifFalse);
1108 :
1109 : bitwiseAndSimd128(Operand(mask), reg);
1110 : bitwiseAndNotSimd128(Operand(ifFalse), mask);
1111 : bitwiseOrSimd128(Operand(mask), reg);
1112 : }
1113 :
1114 : // ========================================================================
1115 : // Memory access primitives.
1116 : void
1117 6 : MacroAssembler::storeUncanonicalizedDouble(FloatRegister src, const Address& dest)
1118 : {
1119 6 : vmovsd(src, dest);
1120 6 : }
1121 : void
1122 0 : MacroAssembler::storeUncanonicalizedDouble(FloatRegister src, const BaseIndex& dest)
1123 : {
1124 0 : vmovsd(src, dest);
1125 0 : }
1126 : void
1127 0 : MacroAssembler::storeUncanonicalizedDouble(FloatRegister src, const Operand& dest)
1128 : {
1129 0 : switch (dest.kind()) {
1130 : case Operand::MEM_REG_DISP:
1131 0 : storeUncanonicalizedDouble(src, dest.toAddress());
1132 0 : break;
1133 : case Operand::MEM_SCALE:
1134 0 : storeUncanonicalizedDouble(src, dest.toBaseIndex());
1135 0 : break;
1136 : default:
1137 0 : MOZ_CRASH("unexpected operand kind");
1138 : }
1139 0 : }
1140 :
1141 : template void MacroAssembler::storeDouble(FloatRegister src, const Operand& dest);
1142 :
1143 : void
1144 0 : MacroAssembler::storeUncanonicalizedFloat32(FloatRegister src, const Address& dest)
1145 : {
1146 0 : vmovss(src, dest);
1147 0 : }
1148 : void
1149 0 : MacroAssembler::storeUncanonicalizedFloat32(FloatRegister src, const BaseIndex& dest)
1150 : {
1151 0 : vmovss(src, dest);
1152 0 : }
1153 : void
1154 0 : MacroAssembler::storeUncanonicalizedFloat32(FloatRegister src, const Operand& dest)
1155 : {
1156 0 : switch (dest.kind()) {
1157 : case Operand::MEM_REG_DISP:
1158 0 : storeUncanonicalizedFloat32(src, dest.toAddress());
1159 0 : break;
1160 : case Operand::MEM_SCALE:
1161 0 : storeUncanonicalizedFloat32(src, dest.toBaseIndex());
1162 0 : break;
1163 : default:
1164 0 : MOZ_CRASH("unexpected operand kind");
1165 : }
1166 0 : }
1167 :
1168 : template void MacroAssembler::storeFloat32(FloatRegister src, const Operand& dest);
1169 :
1170 : void
1171 0 : MacroAssembler::storeFloat32x3(FloatRegister src, const Address& dest)
1172 : {
1173 0 : Address destZ(dest);
1174 0 : destZ.offset += 2 * sizeof(int32_t);
1175 0 : storeDouble(src, dest);
1176 0 : ScratchSimd128Scope scratch(*this);
1177 0 : vmovhlps(src, scratch, scratch);
1178 0 : storeFloat32(scratch, destZ);
1179 0 : }
1180 : void
1181 0 : MacroAssembler::storeFloat32x3(FloatRegister src, const BaseIndex& dest)
1182 : {
1183 0 : BaseIndex destZ(dest);
1184 0 : destZ.offset += 2 * sizeof(int32_t);
1185 0 : storeDouble(src, dest);
1186 0 : ScratchSimd128Scope scratch(*this);
1187 0 : vmovhlps(src, scratch, scratch);
1188 0 : storeFloat32(scratch, destZ);
1189 0 : }
1190 :
1191 : void
1192 0 : MacroAssembler::memoryBarrier(MemoryBarrierBits barrier)
1193 : {
1194 0 : if (barrier & MembarStoreLoad)
1195 0 : storeLoadFence();
1196 0 : }
1197 :
1198 : // ========================================================================
1199 : // Truncate floating point.
1200 :
1201 : void
1202 : MacroAssembler::truncateFloat32ToInt64(Address src, Address dest, Register temp)
1203 : {
1204 : if (Assembler::HasSSE3()) {
1205 : fld32(Operand(src));
1206 : fisttp(Operand(dest));
1207 : return;
1208 : }
1209 :
1210 : if (src.base == esp)
1211 : src.offset += 2 * sizeof(int32_t);
1212 : if (dest.base == esp)
1213 : dest.offset += 2 * sizeof(int32_t);
1214 :
1215 : reserveStack(2 * sizeof(int32_t));
1216 :
1217 : // Set conversion to truncation.
1218 : fnstcw(Operand(esp, 0));
1219 : load32(Operand(esp, 0), temp);
1220 : andl(Imm32(~0xFF00), temp);
1221 : orl(Imm32(0xCFF), temp);
1222 : store32(temp, Address(esp, sizeof(int32_t)));
1223 : fldcw(Operand(esp, sizeof(int32_t)));
1224 :
1225 : // Load double on fp stack, convert and load regular stack.
1226 : fld32(Operand(src));
1227 : fistp(Operand(dest));
1228 :
1229 : // Reset the conversion flag.
1230 : fldcw(Operand(esp, 0));
1231 :
1232 : freeStack(2 * sizeof(int32_t));
1233 : }
1234 : void
1235 : MacroAssembler::truncateDoubleToInt64(Address src, Address dest, Register temp)
1236 : {
1237 : if (Assembler::HasSSE3()) {
1238 : fld(Operand(src));
1239 : fisttp(Operand(dest));
1240 : return;
1241 : }
1242 :
1243 : if (src.base == esp)
1244 : src.offset += 2*sizeof(int32_t);
1245 : if (dest.base == esp)
1246 : dest.offset += 2*sizeof(int32_t);
1247 :
1248 : reserveStack(2*sizeof(int32_t));
1249 :
1250 : // Set conversion to truncation.
1251 : fnstcw(Operand(esp, 0));
1252 : load32(Operand(esp, 0), temp);
1253 : andl(Imm32(~0xFF00), temp);
1254 : orl(Imm32(0xCFF), temp);
1255 : store32(temp, Address(esp, 1*sizeof(int32_t)));
1256 : fldcw(Operand(esp, 1*sizeof(int32_t)));
1257 :
1258 : // Load double on fp stack, convert and load regular stack.
1259 : fld(Operand(src));
1260 : fistp(Operand(dest));
1261 :
1262 : // Reset the conversion flag.
1263 : fldcw(Operand(esp, 0));
1264 :
1265 : freeStack(2*sizeof(int32_t));
1266 : }
1267 :
1268 : // ===============================================================
1269 : // Clamping functions.
1270 :
1271 : void
1272 0 : MacroAssembler::clampIntToUint8(Register reg)
1273 : {
1274 0 : Label inRange;
1275 0 : branchTest32(Assembler::Zero, reg, Imm32(0xffffff00), &inRange);
1276 : {
1277 0 : sarl(Imm32(31), reg);
1278 0 : notl(reg);
1279 0 : andl(Imm32(255), reg);
1280 : }
1281 0 : bind(&inRange);
1282 0 : }
1283 :
1284 : //}}} check_macroassembler_style
1285 : // ===============================================================
1286 :
1287 : } // namespace jit
1288 : } // namespace js
1289 :
1290 : #endif /* jit_x86_shared_MacroAssembler_x86_shared_inl_h */
|