| Index: runtime/vm/assembler_x64_test.cc
|
| ===================================================================
|
| --- runtime/vm/assembler_x64_test.cc (revision 41048)
|
| +++ runtime/vm/assembler_x64_test.cc (working copy)
|
| @@ -386,6 +386,21 @@
|
| }
|
|
|
|
|
| +ASSEMBLER_TEST_GENERATE(UnsignedMultiply, assembler) {
|
| + __ movl(RAX, Immediate(-1)); // RAX = 0xFFFFFFFF
|
| + __ movl(RCX, Immediate(16)); // RCX = 0x10
|
| + __ mull(RCX); // RDX:RAX = RAX * RCX = 0x0FFFFFFFF0
|
| + __ movq(RAX, RDX); // Return high32(0x0FFFFFFFF0) == 0x0F
|
| + __ ret();
|
| +}
|
| +
|
| +
|
| +ASSEMBLER_TEST_RUN(UnsignedMultiply, test) {
|
| + typedef int (*UnsignedMultiply)();
|
| + EXPECT_EQ(15, reinterpret_cast<UnsignedMultiply>(test->entry())());
|
| +}
|
| +
|
| +
|
| ASSEMBLER_TEST_GENERATE(SignedMultiply64, assembler) {
|
| __ pushq(R15); // Callee saved.
|
| __ movq(RAX, Immediate(2));
|
| @@ -508,6 +523,25 @@
|
| }
|
|
|
|
|
| +ASSEMBLER_TEST_GENERATE(UnsignedDivide, assembler) {
|
| + const int32_t low = 0;
|
| + const int32_t high = 0xf0000000;
|
| + const int32_t divisor = 0xffffffff;
|
| + __ movl(RAX, Immediate(low));
|
| + __ movl(RDX, Immediate(high));
|
| + __ movl(RCX, Immediate(divisor));
|
| + __ divl(RCX); // RAX = RDX:RAX / RCX =
|
| + // = 0xf000000000000000 / 0xffffffff = 0xf0000000
|
| + __ ret();
|
| +}
|
| +
|
| +
|
| +ASSEMBLER_TEST_RUN(UnsignedDivide, test) {
|
| + typedef uint32_t (*UnsignedDivide)();
|
| + EXPECT_EQ(0xf0000000, reinterpret_cast<UnsignedDivide>(test->entry())());
|
| +}
|
| +
|
| +
|
| ASSEMBLER_TEST_GENERATE(SignedDivideLong, assembler) {
|
| __ movq(RAX, Immediate(kLargeConstant));
|
| __ movq(RDX, Immediate(123));
|
| @@ -649,6 +683,126 @@
|
| }
|
|
|
|
|
| +ASSEMBLER_TEST_GENERATE(LongAddReg, assembler) {
|
| + __ pushq(CallingConventions::kArg2Reg);
|
| + __ pushq(CallingConventions::kArg1Reg);
|
| + __ movl(RAX, Address(RSP, 0)); // left low.
|
| + __ movl(RDX, Address(RSP, 4)); // left high.
|
| + __ movl(RCX, Address(RSP, 8)); // right low.
|
| + __ movl(RBX, Address(RSP, 12)); // right high
|
| + __ addl(RAX, RCX);
|
| + __ adcl(RDX, RBX);
|
| + // Result is in RAX/RDX.
|
| + __ movl(Address(RSP, 0), RAX); // result low.
|
| + __ movl(Address(RSP, 4), RDX); // result high.
|
| + __ popq(RAX);
|
| + __ popq(RDX);
|
| + __ ret();
|
| +}
|
| +
|
| +
|
| +ASSEMBLER_TEST_RUN(LongAddReg, test) {
|
| + typedef int64_t (*LongAddRegCode)(int64_t a, int64_t b);
|
| + int64_t a = 12;
|
| + int64_t b = 14;
|
| + int64_t res = reinterpret_cast<LongAddRegCode>(test->entry())(a, b);
|
| + EXPECT_EQ((a + b), res);
|
| + a = 2147483647;
|
| + b = 600000;
|
| + res = reinterpret_cast<LongAddRegCode>(test->entry())(a, b);
|
| + EXPECT_EQ((a + b), res);
|
| +}
|
| +
|
| +
|
| +ASSEMBLER_TEST_GENERATE(LongAddAddress, assembler) {
|
| + __ pushq(CallingConventions::kArg2Reg);
|
| + __ pushq(CallingConventions::kArg1Reg);
|
| + __ movl(RAX, Address(RSP, 0)); // left low.
|
| + __ movl(RDX, Address(RSP, 4)); // left high.
|
| + __ addl(RAX, Address(RSP, 8)); // low.
|
| + __ adcl(RDX, Address(RSP, 12)); // high.
|
| + // Result is in RAX/RDX.
|
| + __ movl(Address(RSP, 0), RAX); // result low.
|
| + __ movl(Address(RSP, 4), RDX); // result high.
|
| + __ popq(RAX);
|
| + __ popq(RDX);
|
| + __ ret();
|
| +}
|
| +
|
| +
|
| +ASSEMBLER_TEST_RUN(LongAddAddress, test) {
|
| + typedef int64_t (*LongAddAddressCode)(int64_t a, int64_t b);
|
| + int64_t a = 12;
|
| + int64_t b = 14;
|
| + int64_t res = reinterpret_cast<LongAddAddressCode>(test->entry())(a, b);
|
| + EXPECT_EQ((a + b), res);
|
| + a = 2147483647;
|
| + b = 600000;
|
| + res = reinterpret_cast<LongAddAddressCode>(test->entry())(a, b);
|
| + EXPECT_EQ((a + b), res);
|
| +}
|
| +
|
| +
|
| +ASSEMBLER_TEST_GENERATE(LongSubReg, assembler) {
|
| + __ pushq(CallingConventions::kArg2Reg);
|
| + __ pushq(CallingConventions::kArg1Reg);
|
| + __ movl(RAX, Address(RSP, 0)); // left low.
|
| + __ movl(RDX, Address(RSP, 4)); // left high.
|
| + __ movl(RCX, Address(RSP, 8)); // right low.
|
| + __ movl(RBX, Address(RSP, 12)); // right high
|
| + __ subl(RAX, RCX);
|
| + __ sbbl(RDX, RBX);
|
| + // Result is in RAX/RDX.
|
| + __ movl(Address(RSP, 0), RAX); // result low.
|
| + __ movl(Address(RSP, 4), RDX); // result high.
|
| + __ popq(RAX);
|
| + __ popq(RDX);
|
| + __ ret();
|
| +}
|
| +
|
| +
|
| +ASSEMBLER_TEST_RUN(LongSubReg, test) {
|
| + typedef int64_t (*LongSubRegCode)(int64_t a, int64_t b);
|
| + int64_t a = 12;
|
| + int64_t b = 14;
|
| + int64_t res = reinterpret_cast<LongSubRegCode>(test->entry())(a, b);
|
| + EXPECT_EQ((a - b), res);
|
| + a = 600000;
|
| + b = 2147483647;
|
| + res = reinterpret_cast<LongSubRegCode>(test->entry())(a, b);
|
| + EXPECT_EQ((a - b), res);
|
| +}
|
| +
|
| +
|
| +ASSEMBLER_TEST_GENERATE(LongSubAddress, assembler) {
|
| + __ pushq(CallingConventions::kArg2Reg);
|
| + __ pushq(CallingConventions::kArg1Reg);
|
| + __ movl(RAX, Address(RSP, 0)); // left low.
|
| + __ movl(RDX, Address(RSP, 4)); // left high.
|
| + __ subl(RAX, Address(RSP, 8)); // low.
|
| + __ sbbl(RDX, Address(RSP, 12)); // high.
|
| + // Result is in RAX/RDX.
|
| + __ movl(Address(RSP, 0), RAX); // result low.
|
| + __ movl(Address(RSP, 4), RDX); // result high.
|
| + __ popq(RAX);
|
| + __ popq(RDX);
|
| + __ ret();
|
| +}
|
| +
|
| +
|
| +ASSEMBLER_TEST_RUN(LongSubAddress, test) {
|
| + typedef int64_t (*LongSubAddressCode)(int64_t a, int64_t b);
|
| + int64_t a = 12;
|
| + int64_t b = 14;
|
| + int64_t res = reinterpret_cast<LongSubAddressCode>(test->entry())(a, b);
|
| + EXPECT_EQ((a - b), res);
|
| + a = 600000;
|
| + b = 2147483647;
|
| + res = reinterpret_cast<LongSubAddressCode>(test->entry())(a, b);
|
| + EXPECT_EQ((a - b), res);
|
| +}
|
| +
|
| +
|
| ASSEMBLER_TEST_GENERATE(Bitwise, assembler) {
|
| __ movl(RCX, Immediate(42));
|
| __ xorl(RCX, RCX);
|
| @@ -905,6 +1059,21 @@
|
| __ movl(Address(RAX, 0), RAX);
|
| __ Bind(&donetest13a);
|
|
|
| + Label donetest15a;
|
| + const int32_t left = 0xff000000;
|
| + const int32_t right = 0xffffffff;
|
| + const int32_t shifted = 0xf0000003;
|
| + __ movl(RDX, Immediate(left));
|
| + __ movl(RAX, Immediate(right));
|
| + __ movl(RCX, Immediate(2));
|
| + __ shll(RDX, RCX); // RDX = 0xff000000 << 2 == 0xfc000000
|
| + __ shldl(RDX, RAX, Immediate(2)); // RDX = high32(0xfc000000:0xffffffff << 2)
|
| + // = 0xf0000003
|
| + __ cmpl(RDX, Immediate(shifted));
|
| + __ j(EQUAL, &donetest15a);
|
| + __ int3();
|
| + __ Bind(&donetest15a);
|
| +
|
| __ movl(RAX, Immediate(0));
|
| __ ret();
|
| }
|
|
|