1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #include "jit/IonAnalysis.h"
9 #include "jit/Linker.h"
10 #include "jit/MacroAssembler.h"
11 #include "jit/MIRGenerator.h"
12 #include "jit/MIRGraph.h"
13 #include "jit/ValueNumbering.h"
16 #include "jsapi-tests/tests.h"
17 #include "jsapi-tests/testsJit.h"
19 #include "jit/MacroAssembler-inl.h"
22 using namespace js::jit
;
24 using mozilla::NegativeInfinity
;
25 using mozilla::PositiveInfinity
;
27 #if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
29 BEGIN_TEST(testJitMacroAssembler_flexibleDivMod
) {
30 StackMacroAssembler
masm(cx
);
31 AutoCreatedBy
acb(masm
, __func__
);
35 // Test case divides 9/2;
36 const uintptr_t quotient_result
= 4;
37 const uintptr_t remainder_result
= 1;
38 const uintptr_t dividend
= 9;
39 const uintptr_t divisor
= 2;
41 AllocatableGeneralRegisterSet
leftOutputHandSides(GeneralRegisterSet::All());
43 while (!leftOutputHandSides
.empty()) {
44 Register lhsOutput
= leftOutputHandSides
.takeAny();
46 AllocatableGeneralRegisterSet
rightHandSides(GeneralRegisterSet::All());
47 while (!rightHandSides
.empty()) {
48 Register rhs
= rightHandSides
.takeAny();
50 AllocatableGeneralRegisterSet
remainders(GeneralRegisterSet::All());
51 while (!remainders
.empty()) {
52 Register remainderOutput
= remainders
.takeAny();
53 if (lhsOutput
== rhs
|| lhsOutput
== remainderOutput
||
54 rhs
== remainderOutput
) {
58 AllocatableRegisterSet
regs(RegisterSet::Volatile());
59 LiveRegisterSet
save(regs
.asLiveSet());
62 masm
.mov(ImmWord(dividend
), lhsOutput
);
63 masm
.mov(ImmWord(divisor
), rhs
);
64 masm
.flexibleDivMod32(rhs
, lhsOutput
, remainderOutput
, false, save
);
65 masm
.branch32(Assembler::NotEqual
, AbsoluteAddress("ient_result
),
67 masm
.branch32(Assembler::NotEqual
, AbsoluteAddress(&remainder_result
),
68 remainderOutput
, &fail
);
69 // Ensure RHS was not clobbered
70 masm
.branch32(Assembler::NotEqual
, AbsoluteAddress(&divisor
), rhs
,
74 masm
.printf("Failed");
82 return ExecuteJit(cx
, masm
);
84 END_TEST(testJitMacroAssembler_flexibleDivMod
)
86 BEGIN_TEST(testJitMacroAssembler_flexibleRemainder
) {
87 StackMacroAssembler
masm(cx
);
88 AutoCreatedBy
acb(masm
, __func__
);
92 // Test case divides 9/2;
93 const uintptr_t dividend
= 9;
94 const uintptr_t divisor
= 2;
95 const uintptr_t remainder_result
= 1;
97 AllocatableGeneralRegisterSet
leftOutputHandSides(GeneralRegisterSet::All());
99 while (!leftOutputHandSides
.empty()) {
100 Register lhsOutput
= leftOutputHandSides
.takeAny();
102 AllocatableGeneralRegisterSet
rightHandSides(GeneralRegisterSet::All());
103 while (!rightHandSides
.empty()) {
104 Register rhs
= rightHandSides
.takeAny();
106 if (lhsOutput
== rhs
) {
110 AllocatableRegisterSet
regs(RegisterSet::Volatile());
111 LiveRegisterSet
save(regs
.asLiveSet());
114 masm
.mov(ImmWord(dividend
), lhsOutput
);
115 masm
.mov(ImmWord(divisor
), rhs
);
116 masm
.flexibleRemainder32(rhs
, lhsOutput
, false, save
);
117 masm
.branch32(Assembler::NotEqual
, AbsoluteAddress(&remainder_result
),
119 // Ensure RHS was not clobbered
120 masm
.branch32(Assembler::NotEqual
, AbsoluteAddress(&divisor
), rhs
, &fail
);
123 masm
.printf("Failed\n");
130 return ExecuteJit(cx
, masm
);
132 END_TEST(testJitMacroAssembler_flexibleRemainder
)
134 BEGIN_TEST(testJitMacroAssembler_flexibleQuotient
) {
135 StackMacroAssembler
masm(cx
);
136 AutoCreatedBy
acb(masm
, __func__
);
140 // Test case divides 9/2;
141 const uintptr_t dividend
= 9;
142 const uintptr_t divisor
= 2;
143 const uintptr_t quotient_result
= 4;
145 AllocatableGeneralRegisterSet
leftOutputHandSides(GeneralRegisterSet::All());
147 while (!leftOutputHandSides
.empty()) {
148 Register lhsOutput
= leftOutputHandSides
.takeAny();
150 AllocatableGeneralRegisterSet
rightHandSides(GeneralRegisterSet::All());
151 while (!rightHandSides
.empty()) {
152 Register rhs
= rightHandSides
.takeAny();
154 if (lhsOutput
== rhs
) {
158 AllocatableRegisterSet
regs(RegisterSet::Volatile());
159 LiveRegisterSet
save(regs
.asLiveSet());
162 masm
.mov(ImmWord(dividend
), lhsOutput
);
163 masm
.mov(ImmWord(divisor
), rhs
);
164 masm
.flexibleQuotient32(rhs
, lhsOutput
, false, save
);
165 masm
.branch32(Assembler::NotEqual
, AbsoluteAddress("ient_result
),
167 // Ensure RHS was not clobbered
168 masm
.branch32(Assembler::NotEqual
, AbsoluteAddress(&divisor
), rhs
, &fail
);
171 masm
.printf("Failed\n");
178 return ExecuteJit(cx
, masm
);
180 END_TEST(testJitMacroAssembler_flexibleQuotient
)
182 // To make sure ecx isn't being clobbered; globally scoped to ensure it has the
184 const uintptr_t guardEcx
= 0xfeedbad;
186 bool shiftTest(JSContext
* cx
, const char* name
,
187 void (*operation
)(StackMacroAssembler
& masm
, Register
, Register
),
188 const uintptr_t* lhsInput
, const uintptr_t* rhsInput
,
189 const uintptr_t* result
) {
190 StackMacroAssembler
masm(cx
);
191 AutoCreatedBy
acb(masm
, __func__
);
195 JS::AutoSuppressGCAnalysis suppress
;
196 AllocatableGeneralRegisterSet
leftOutputHandSides(GeneralRegisterSet::All());
198 while (!leftOutputHandSides
.empty()) {
199 Register lhsOutput
= leftOutputHandSides
.takeAny();
201 AllocatableGeneralRegisterSet
rightHandSides(GeneralRegisterSet::All());
202 while (!rightHandSides
.empty()) {
203 Register rhs
= rightHandSides
.takeAny();
205 // You can only use shift as the same reg if the values are the same
206 if (lhsOutput
== rhs
&& *lhsInput
!= *rhsInput
) {
210 Label next
, outputFail
, clobberRhs
, clobberEcx
, dump
;
211 masm
.mov(ImmWord(guardEcx
), ecx
);
212 masm
.mov(ImmWord(*lhsInput
), lhsOutput
);
213 masm
.mov(ImmWord(*rhsInput
), rhs
);
215 operation(masm
, rhs
, lhsOutput
);
217 // Ensure Result is correct
218 masm
.branch32(Assembler::NotEqual
, AbsoluteAddress(result
), lhsOutput
,
221 // Ensure RHS was not clobbered, unless it's also the output register.
222 if (lhsOutput
!= rhs
) {
223 masm
.branch32(Assembler::NotEqual
, AbsoluteAddress(rhsInput
), rhs
,
227 if (lhsOutput
!= ecx
&& rhs
!= ecx
) {
228 // If neither lhsOutput nor rhs is ecx, make sure ecx has been
229 // preserved, otherwise it's expected to be covered by the RHS clobber
230 // check above, or intentionally clobbered as the output.
231 masm
.branch32(Assembler::NotEqual
, AbsoluteAddress(&guardEcx
), ecx
,
237 masm
.bind(&outputFail
);
238 masm
.printf("Incorrect output (got %d) ", lhsOutput
);
241 masm
.bind(&clobberRhs
);
242 masm
.printf("rhs clobbered %d", rhs
);
245 masm
.bind(&clobberEcx
);
246 masm
.printf("ecx clobbered");
250 masm
.mov(ImmPtr(lhsOutput
.name()), lhsOutput
);
251 masm
.printf("(lhsOutput/srcDest) %s ", lhsOutput
);
252 masm
.mov(ImmPtr(name
), lhsOutput
);
253 masm
.printf("%s ", lhsOutput
);
254 masm
.mov(ImmPtr(rhs
.name()), lhsOutput
);
255 masm
.printf("(shift/rhs) %s \n", lhsOutput
);
256 // Breakpoint to force test failure.
262 return ExecuteJit(cx
, masm
);
265 BEGIN_TEST(testJitMacroAssembler_flexibleRshift
) {
267 // Test case 16 >> 2 == 4;
268 const uintptr_t lhsInput
= 16;
269 const uintptr_t rhsInput
= 2;
270 const uintptr_t result
= 4;
272 bool res
= shiftTest(
273 cx
, "flexibleRshift32",
274 [](StackMacroAssembler
& masm
, Register rhs
, Register lhsOutput
) {
275 masm
.flexibleRshift32(rhs
, lhsOutput
);
277 &lhsInput
, &rhsInput
, &result
);
284 // Test case 16 >> 16 == 0 -- this helps cover the case where the same
285 // register can be passed for source and dest.
286 const uintptr_t lhsInput
= 16;
287 const uintptr_t rhsInput
= 16;
288 const uintptr_t result
= 0;
290 bool res
= shiftTest(
291 cx
, "flexibleRshift32",
292 [](StackMacroAssembler
& masm
, Register rhs
, Register lhsOutput
) {
293 masm
.flexibleRshift32(rhs
, lhsOutput
);
295 &lhsInput
, &rhsInput
, &result
);
303 END_TEST(testJitMacroAssembler_flexibleRshift
)
305 BEGIN_TEST(testJitMacroAssembler_flexibleRshiftArithmetic
) {
307 // Test case 4294967295 >> 2 == 4294967295;
308 const uintptr_t lhsInput
= 4294967295;
309 const uintptr_t rhsInput
= 2;
310 const uintptr_t result
= 4294967295;
311 bool res
= shiftTest(
312 cx
, "flexibleRshift32Arithmetic",
313 [](StackMacroAssembler
& masm
, Register rhs
, Register lhsOutput
) {
314 masm
.flexibleRshift32Arithmetic(rhs
, lhsOutput
);
316 &lhsInput
, &rhsInput
, &result
);
323 // Test case 16 >> 16 == 0 -- this helps cover the case where the same
324 // register can be passed for source and dest.
325 const uintptr_t lhsInput
= 16;
326 const uintptr_t rhsInput
= 16;
327 const uintptr_t result
= 0;
329 bool res
= shiftTest(
330 cx
, "flexibleRshift32Arithmetic",
331 [](StackMacroAssembler
& masm
, Register rhs
, Register lhsOutput
) {
332 masm
.flexibleRshift32Arithmetic(rhs
, lhsOutput
);
334 &lhsInput
, &rhsInput
, &result
);
342 END_TEST(testJitMacroAssembler_flexibleRshiftArithmetic
)
344 BEGIN_TEST(testJitMacroAssembler_flexibleLshift
) {
346 // Test case 16 << 2 == 64;
347 const uintptr_t lhsInput
= 16;
348 const uintptr_t rhsInput
= 2;
349 const uintptr_t result
= 64;
351 bool res
= shiftTest(
352 cx
, "flexibleLshift32",
353 [](StackMacroAssembler
& masm
, Register rhs
, Register lhsOutput
) {
354 masm
.flexibleLshift32(rhs
, lhsOutput
);
356 &lhsInput
, &rhsInput
, &result
);
363 // Test case 4 << 4 == 64; duplicated input case
364 const uintptr_t lhsInput
= 4;
365 const uintptr_t rhsInput
= 4;
366 const uintptr_t result
= 64;
368 bool res
= shiftTest(
369 cx
, "flexibleLshift32",
370 [](StackMacroAssembler
& masm
, Register rhs
, Register lhsOutput
) {
371 masm
.flexibleLshift32(rhs
, lhsOutput
);
373 &lhsInput
, &rhsInput
, &result
);
381 END_TEST(testJitMacroAssembler_flexibleLshift
)
383 BEGIN_TEST(testJitMacroAssembler_truncateDoubleToInt64
) {
384 StackMacroAssembler
masm(cx
);
385 AutoCreatedBy
acb(masm
, __func__
);
389 AllocatableGeneralRegisterSet
allRegs(GeneralRegisterSet::All());
390 AllocatableFloatRegisterSet
allFloatRegs(FloatRegisterSet::All());
391 FloatRegister input
= allFloatRegs
.takeAny();
393 Register64
output(allRegs
.takeAny(), allRegs
.takeAny());
395 Register64
output(allRegs
.takeAny());
397 Register temp
= allRegs
.takeAny();
399 masm
.reserveStack(sizeof(int32_t));
401 # define TEST(INPUT, OUTPUT) \
404 masm.loadConstantDouble(double(INPUT), input); \
405 masm.storeDouble(input, Operand(esp, 0)); \
406 masm.truncateDoubleToInt64(Address(esp, 0), Address(esp, 0), temp); \
407 masm.branch64(Assembler::Equal, Address(esp, 0), Imm64(OUTPUT), &next); \
408 masm.printf("truncateDoubleToInt64(" #INPUT ") failed\n"); \
416 TEST(9223372036854774784.0, 9223372036854774784);
417 TEST(-9223372036854775808.0, 0x8000000000000000);
418 TEST(9223372036854775808.0, 0x8000000000000000);
419 TEST(JS::GenericNaN(), 0x8000000000000000);
420 TEST(PositiveInfinity
<double>(), 0x8000000000000000);
421 TEST(NegativeInfinity
<double>(), 0x8000000000000000);
424 masm
.freeStack(sizeof(int32_t));
426 return ExecuteJit(cx
, masm
);
428 END_TEST(testJitMacroAssembler_truncateDoubleToInt64
)
430 BEGIN_TEST(testJitMacroAssembler_truncateDoubleToUInt64
) {
431 StackMacroAssembler
masm(cx
);
432 AutoCreatedBy
acb(masm
, __func__
);
436 AllocatableGeneralRegisterSet
allRegs(GeneralRegisterSet::All());
437 AllocatableFloatRegisterSet
allFloatRegs(FloatRegisterSet::All());
438 FloatRegister input
= allFloatRegs
.takeAny();
439 FloatRegister floatTemp
= allFloatRegs
.takeAny();
441 Register64
output(allRegs
.takeAny(), allRegs
.takeAny());
443 Register64
output(allRegs
.takeAny());
445 Register temp
= allRegs
.takeAny();
447 masm
.reserveStack(sizeof(int32_t));
449 # define TEST(INPUT, OUTPUT) \
452 masm.loadConstantDouble(double(INPUT), input); \
453 masm.storeDouble(input, Operand(esp, 0)); \
454 masm.truncateDoubleToUInt64(Address(esp, 0), Address(esp, 0), temp, \
456 masm.branch64(Assembler::Equal, Address(esp, 0), Imm64(OUTPUT), &next); \
457 masm.printf("truncateDoubleToUInt64(" #INPUT ") failed\n"); \
464 TEST(9223372036854774784.0, 9223372036854774784);
465 TEST((uint64_t)0x8000000000000000, 0x8000000000000000);
466 TEST((uint64_t)0x8000000000000001, 0x8000000000000000);
467 TEST((uint64_t)0x8006004000000001, 0x8006004000000000);
471 TEST(JS::GenericNaN(), 0x8000000000000000);
472 TEST(PositiveInfinity
<double>(), 0x8000000000000000);
473 TEST(NegativeInfinity
<double>(), 0x8000000000000000);
476 masm
.freeStack(sizeof(int32_t));
478 return ExecuteJit(cx
, masm
);
480 END_TEST(testJitMacroAssembler_truncateDoubleToUInt64
)
482 BEGIN_TEST(testJitMacroAssembler_branchDoubleNotInInt64Range
) {
483 StackMacroAssembler
masm(cx
);
484 AutoCreatedBy
acb(masm
, __func__
);
488 AllocatableGeneralRegisterSet
allRegs(GeneralRegisterSet::All());
489 AllocatableFloatRegisterSet
allFloatRegs(FloatRegisterSet::All());
490 FloatRegister input
= allFloatRegs
.takeAny();
492 Register64
output(allRegs
.takeAny(), allRegs
.takeAny());
494 Register64
output(allRegs
.takeAny());
496 Register temp
= allRegs
.takeAny();
498 masm
.reserveStack(sizeof(int32_t));
500 # define TEST(INPUT, OUTPUT) \
503 masm.loadConstantDouble(double(INPUT), input); \
504 masm.storeDouble(input, Operand(esp, 0)); \
506 masm.branchDoubleNotInInt64Range(Address(esp, 0), temp, &next); \
509 masm.branchDoubleNotInInt64Range(Address(esp, 0), temp, &fail); \
513 masm.printf("branchDoubleNotInInt64Range(" #INPUT ") failed\n"); \
521 TEST(9223372036854774784.0, false);
522 TEST(-9223372036854775808.0, true);
523 TEST(9223372036854775808.0, true);
524 TEST(JS::GenericNaN(), true);
525 TEST(PositiveInfinity
<double>(), true);
526 TEST(NegativeInfinity
<double>(), true);
529 masm
.freeStack(sizeof(int32_t));
531 return ExecuteJit(cx
, masm
);
533 END_TEST(testJitMacroAssembler_branchDoubleNotInInt64Range
)
535 BEGIN_TEST(testJitMacroAssembler_branchDoubleNotInUInt64Range
) {
536 StackMacroAssembler
masm(cx
);
537 AutoCreatedBy
acb(masm
, __func__
);
541 AllocatableGeneralRegisterSet
allRegs(GeneralRegisterSet::All());
542 AllocatableFloatRegisterSet
allFloatRegs(FloatRegisterSet::All());
543 FloatRegister input
= allFloatRegs
.takeAny();
545 Register64
output(allRegs
.takeAny(), allRegs
.takeAny());
547 Register64
output(allRegs
.takeAny());
549 Register temp
= allRegs
.takeAny();
551 masm
.reserveStack(sizeof(int32_t));
553 # define TEST(INPUT, OUTPUT) \
556 masm.loadConstantDouble(double(INPUT), input); \
557 masm.storeDouble(input, Operand(esp, 0)); \
559 masm.branchDoubleNotInUInt64Range(Address(esp, 0), temp, &next); \
562 masm.branchDoubleNotInUInt64Range(Address(esp, 0), temp, &fail); \
566 masm.printf("branchDoubleNotInUInt64Range(" #INPUT ") failed\n"); \
573 TEST(9223372036854774784.0, false);
574 TEST((uint64_t)0x8000000000000000, false);
575 TEST((uint64_t)0x8000000000000001, false);
576 TEST((uint64_t)0x8006004000000001, false);
580 TEST(JS::GenericNaN(), true);
581 TEST(PositiveInfinity
<double>(), true);
582 TEST(NegativeInfinity
<double>(), true);
585 masm
.freeStack(sizeof(int32_t));
587 return ExecuteJit(cx
, masm
);
589 END_TEST(testJitMacroAssembler_branchDoubleNotInUInt64Range
)
591 BEGIN_TEST(testJitMacroAssembler_lshift64
) {
592 StackMacroAssembler
masm(cx
);
593 AutoCreatedBy
acb(masm
, __func__
);
597 AllocatableGeneralRegisterSet
allRegs(GeneralRegisterSet::All());
598 AllocatableFloatRegisterSet
allFloatRegs(FloatRegisterSet::All());
599 # if defined(JS_CODEGEN_X86)
600 Register shift
= ecx
;
602 # elif defined(JS_CODEGEN_X64)
603 Register shift
= rcx
;
606 Register shift
= allRegs
.takeAny();
610 Register64
input(allRegs
.takeAny(), allRegs
.takeAny());
612 Register64
input(allRegs
.takeAny());
615 masm
.reserveStack(sizeof(int32_t));
617 # define TEST(SHIFT, INPUT, OUTPUT) \
620 masm.move64(Imm64(INPUT), input); \
621 masm.move32(Imm32(SHIFT), shift); \
622 masm.lshift64(shift, input); \
623 masm.branch64(Assembler::Equal, input, Imm64(OUTPUT), &next); \
624 masm.printf("lshift64(" #SHIFT ", " #INPUT ") failed\n"); \
630 masm.move64(Imm64(INPUT), input); \
631 masm.lshift64(Imm32(SHIFT & 0x3f), input); \
632 masm.branch64(Assembler::Equal, input, Imm64(OUTPUT), &next); \
633 masm.printf("lshift64(Imm32(" #SHIFT "&0x3f), " #INPUT ") failed\n"); \
641 TEST(32, 1, 0x0000000100000000);
642 TEST(33, 1, 0x0000000200000000);
643 TEST(0, -1, 0xffffffffffffffff);
644 TEST(1, -1, 0xfffffffffffffffe);
645 TEST(2, -1, 0xfffffffffffffffc);
646 TEST(32, -1, 0xffffffff00000000);
647 TEST(0xffffffff, 1, 0x8000000000000000);
648 TEST(0xfffffffe, 1, 0x4000000000000000);
649 TEST(0xfffffffd, 1, 0x2000000000000000);
650 TEST(0x80000001, 1, 2);
653 masm
.freeStack(sizeof(int32_t));
655 return ExecuteJit(cx
, masm
);
657 END_TEST(testJitMacroAssembler_lshift64
)
659 BEGIN_TEST(testJitMacroAssembler_rshift64Arithmetic
) {
660 StackMacroAssembler
masm(cx
);
661 AutoCreatedBy
acb(masm
, __func__
);
665 AllocatableGeneralRegisterSet
allRegs(GeneralRegisterSet::All());
666 AllocatableFloatRegisterSet
allFloatRegs(FloatRegisterSet::All());
667 # if defined(JS_CODEGEN_X86)
668 Register shift
= ecx
;
670 # elif defined(JS_CODEGEN_X64)
671 Register shift
= rcx
;
674 Register shift
= allRegs
.takeAny();
678 Register64
input(allRegs
.takeAny(), allRegs
.takeAny());
680 Register64
input(allRegs
.takeAny());
683 masm
.reserveStack(sizeof(int32_t));
685 # define TEST(SHIFT, INPUT, OUTPUT) \
688 masm.move64(Imm64(INPUT), input); \
689 masm.move32(Imm32(SHIFT), shift); \
690 masm.rshift64Arithmetic(shift, input); \
691 masm.branch64(Assembler::Equal, input, Imm64(OUTPUT), &next); \
692 masm.printf("rshift64Arithmetic(" #SHIFT ", " #INPUT ") failed\n"); \
698 masm.move64(Imm64(INPUT), input); \
699 masm.rshift64Arithmetic(Imm32(SHIFT & 0x3f), input); \
700 masm.branch64(Assembler::Equal, input, Imm64(OUTPUT), &next); \
701 masm.printf("rshift64Arithmetic(Imm32(" #SHIFT "&0x3f), " #INPUT \
707 TEST(0, 0x4000000000000000, 0x4000000000000000);
708 TEST(1, 0x4000000000000000, 0x2000000000000000);
709 TEST(2, 0x4000000000000000, 0x1000000000000000);
710 TEST(32, 0x4000000000000000, 0x0000000040000000);
711 TEST(0, 0x8000000000000000, 0x8000000000000000);
712 TEST(1, 0x8000000000000000, 0xc000000000000000);
713 TEST(2, 0x8000000000000000, 0xe000000000000000);
714 TEST(32, 0x8000000000000000, 0xffffffff80000000);
715 TEST(0xffffffff, 0x8000000000000000, 0xffffffffffffffff);
716 TEST(0xfffffffe, 0x8000000000000000, 0xfffffffffffffffe);
717 TEST(0xfffffffd, 0x8000000000000000, 0xfffffffffffffffc);
718 TEST(0x80000001, 0x8000000000000000, 0xc000000000000000);
721 masm
.freeStack(sizeof(int32_t));
723 return ExecuteJit(cx
, masm
);
725 END_TEST(testJitMacroAssembler_rshift64Arithmetic
)
727 BEGIN_TEST(testJitMacroAssembler_rshift64
) {
728 StackMacroAssembler
masm(cx
);
729 AutoCreatedBy
acb(masm
, __func__
);
733 AllocatableGeneralRegisterSet
allRegs(GeneralRegisterSet::All());
734 AllocatableFloatRegisterSet
allFloatRegs(FloatRegisterSet::All());
735 # if defined(JS_CODEGEN_X86)
736 Register shift
= ecx
;
738 # elif defined(JS_CODEGEN_X64)
739 Register shift
= rcx
;
742 Register shift
= allRegs
.takeAny();
746 Register64
input(allRegs
.takeAny(), allRegs
.takeAny());
748 Register64
input(allRegs
.takeAny());
751 masm
.reserveStack(sizeof(int32_t));
753 # define TEST(SHIFT, INPUT, OUTPUT) \
756 masm.move64(Imm64(INPUT), input); \
757 masm.move32(Imm32(SHIFT), shift); \
758 masm.rshift64(shift, input); \
759 masm.branch64(Assembler::Equal, input, Imm64(OUTPUT), &next); \
760 masm.printf("rshift64(" #SHIFT ", " #INPUT ") failed\n"); \
766 masm.move64(Imm64(INPUT), input); \
767 masm.rshift64(Imm32(SHIFT & 0x3f), input); \
768 masm.branch64(Assembler::Equal, input, Imm64(OUTPUT), &next); \
769 masm.printf("rshift64(Imm32(" #SHIFT "&0x3f), " #INPUT ") failed\n"); \
774 TEST(0, 0x4000000000000000, 0x4000000000000000);
775 TEST(1, 0x4000000000000000, 0x2000000000000000);
776 TEST(2, 0x4000000000000000, 0x1000000000000000);
777 TEST(32, 0x4000000000000000, 0x0000000040000000);
778 TEST(0, 0x8000000000000000, 0x8000000000000000);
779 TEST(1, 0x8000000000000000, 0x4000000000000000);
780 TEST(2, 0x8000000000000000, 0x2000000000000000);
781 TEST(32, 0x8000000000000000, 0x0000000080000000);
782 TEST(0xffffffff, 0x8000000000000000, 0x0000000000000001);
783 TEST(0xfffffffe, 0x8000000000000000, 0x0000000000000002);
784 TEST(0xfffffffd, 0x8000000000000000, 0x0000000000000004);
785 TEST(0x80000001, 0x8000000000000000, 0x4000000000000000);
788 masm
.freeStack(sizeof(int32_t));
790 return ExecuteJit(cx
, masm
);
792 END_TEST(testJitMacroAssembler_rshift64
)