From 714e525b40bf74c6b44fe1387226e268f56a5e7c Mon Sep 17 00:00:00 2001 From: "whesse@chromium.org" Date: Thu, 30 Apr 2009 09:21:50 +0000 Subject: [PATCH] Improve register allocation of left shift operation. Add tests for all shift operations. Review URL: http://codereview.chromium.org/101016 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1825 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/ia32/codegen-ia32.cc | 37 ++--- test/mjsunit/smi-ops.js | 392 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 410 insertions(+), 19 deletions(-) diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc index a936b9f..8135e85 100644 --- a/src/ia32/codegen-ia32.cc +++ b/src/ia32/codegen-ia32.cc @@ -5902,10 +5902,10 @@ Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left, // Right operand must be in register cl because x86 likes it that way. if (right->reg().is(ecx)) { // Right is already in the right place. Left may be in the - // same register, which causes problems. Use answer instead. - if (left->reg().is(ecx)) { - *left = answer; - } + // same register, which causes problems. Always use answer + // instead of left, even if left is not ecx, since this avoids + // spilling left. + *left = answer; } else if (left->reg().is(ecx)) { generator()->frame()->Spill(left->reg()); __ mov(left->reg(), right->reg()); @@ -5919,6 +5919,9 @@ Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left, ASSERT(reg_ecx.is_valid()); __ mov(ecx, right->reg()); *right = reg_ecx; + // Answer and left both contain the left operand. Use answer, so + // left is not spilled. + *left = answer; } ASSERT(left->reg().is_valid()); ASSERT(!left->reg().is(ecx)); @@ -5968,16 +5971,10 @@ Result DeferredInlineBinaryOperation::GenerateInlineCode(Result* left, case Token::SHL: { __ shl(left->reg()); // Check that the *signed* result fits in a smi. - // - // TODO(207): Can reduce registers from 4 to 3 by - // preallocating ecx. JumpTarget result_ok(generator()); - Result smi_test_reg = generator()->allocator()->Allocate(); - ASSERT(smi_test_reg.is_valid()); - __ lea(smi_test_reg.reg(), Operand(left->reg(), 0x40000000)); - __ test(smi_test_reg.reg(), Immediate(0x80000000)); - smi_test_reg.Unuse(); - result_ok.Branch(zero, left, taken); + __ cmp(left->reg(), 0xc0000000); + result_ok.Branch(positive, left, taken); + __ shr(left->reg()); ASSERT(kSmiTag == 0); __ shl(left->reg(), kSmiTagSize); @@ -6277,11 +6274,15 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) { case Token::SHR: __ shr(eax); break; default: UNREACHABLE(); } - - // Check if result is non-negative and fits in a smi. - __ test(eax, Immediate(0xc0000000)); - __ j(not_zero, &non_smi_result); - + if (op_ == Token::SHR) { + // Check if result is non-negative and fits in a smi. + __ test(eax, Immediate(0xc0000000)); + __ j(not_zero, &non_smi_result); + } else { + // Check if result fits in a smi. + __ cmp(eax, 0xc0000000); + __ j(negative, &non_smi_result); + } // Tag smi result and return. ASSERT(kSmiTagSize == times_2); // adjust code if not the case __ lea(eax, Operand(eax, eax, times_1, kSmiTag)); diff --git a/test/mjsunit/smi-ops.js b/test/mjsunit/smi-ops.js index 80d2012..7e57136 100644 --- a/test/mjsunit/smi-ops.js +++ b/test/mjsunit/smi-ops.js @@ -34,7 +34,7 @@ const OBJ_42 = new (function() { this.valueOf = function() { return 42; }; })(); -assertEquals(42, OBJ_42.valueOf()); +assertEquals(42, OBJ_42.valueOf()); function Add1(x) { @@ -195,3 +195,393 @@ assertEquals(78, Xor100Reversed(OBJ_42)); var x = 0x23; var y = 0x35; assertEquals(0x16, x ^ y); + +// Test shift operators on non-smi inputs, giving smi and non-smi results. +function testShiftNonSmis() { + var pos_non_smi = 2000000000; + var neg_non_smi = -pos_non_smi; + var pos_smi = 1000000000; + var neg_smi = -pos_smi; + + // Begin block A + assertEquals(pos_non_smi, (pos_non_smi) >> 0); + assertEquals(pos_non_smi, (pos_non_smi) >>> 0); + assertEquals(pos_non_smi, (pos_non_smi) << 0); + assertEquals(neg_non_smi, (neg_non_smi) >> 0); + assertEquals(neg_non_smi + 0x100000000, (neg_non_smi) >>> 0); + assertEquals(neg_non_smi, (neg_non_smi) << 0); + assertEquals(pos_smi, (pos_smi) >> 0); + assertEquals(pos_smi, (pos_smi) >>> 0); + assertEquals(pos_smi, (pos_smi) << 0); + assertEquals(neg_smi, (neg_smi) >> 0); + assertEquals(neg_smi + 0x100000000, (neg_smi) >>> 0); + assertEquals(neg_smi, (neg_smi) << 0); + + assertEquals(pos_non_smi / 2, (pos_non_smi) >> 1); + assertEquals(pos_non_smi / 2, (pos_non_smi) >>> 1); + assertEquals(-0x1194D800, (pos_non_smi) << 1); + assertEquals(pos_non_smi / 8, (pos_non_smi) >> 3); + assertEquals(pos_non_smi / 8, (pos_non_smi) >>> 3); + assertEquals(-0x46536000, (pos_non_smi) << 3); + assertEquals(0x73594000, (pos_non_smi) << 4); + assertEquals(pos_non_smi, (pos_non_smi + 0.5) >> 0); + assertEquals(pos_non_smi, (pos_non_smi + 0.5) >>> 0); + assertEquals(pos_non_smi, (pos_non_smi + 0.5) << 0); + assertEquals(pos_non_smi / 2, (pos_non_smi + 0.5) >> 1); + assertEquals(pos_non_smi / 2, (pos_non_smi + 0.5) >>> 1); + assertEquals(-0x1194D800, (pos_non_smi + 0.5) << 1); + assertEquals(pos_non_smi / 8, (pos_non_smi + 0.5) >> 3); + assertEquals(pos_non_smi / 8, (pos_non_smi + 0.5) >>> 3); + assertEquals(-0x46536000, (pos_non_smi + 0.5) << 3); + assertEquals(0x73594000, (pos_non_smi + 0.5) << 4); + + assertEquals(neg_non_smi / 2, (neg_non_smi) >> 1); + assertEquals(neg_non_smi / 2 + 0x100000000 / 2, (neg_non_smi) >>> 1); + assertEquals(0x1194D800, (neg_non_smi) << 1); + assertEquals(neg_non_smi / 8, (neg_non_smi) >> 3); + assertEquals(neg_non_smi / 8 + 0x100000000 / 8, (neg_non_smi) >>> 3); + assertEquals(0x46536000, (neg_non_smi) << 3); + assertEquals(-0x73594000, (neg_non_smi) << 4); + assertEquals(neg_non_smi, (neg_non_smi - 0.5) >> 0); + assertEquals(neg_non_smi + 0x100000000, (neg_non_smi - 0.5) >>> 0); + assertEquals(neg_non_smi, (neg_non_smi - 0.5) << 0); + assertEquals(neg_non_smi / 2, (neg_non_smi - 0.5) >> 1); + assertEquals(neg_non_smi / 2 + 0x100000000 / 2, (neg_non_smi - 0.5) >>> 1); + assertEquals(0x1194D800, (neg_non_smi - 0.5) << 1); + assertEquals(neg_non_smi / 8, (neg_non_smi - 0.5) >> 3); + assertEquals(neg_non_smi / 8 + 0x100000000 / 8, (neg_non_smi - 0.5) >>> 3); + assertEquals(0x46536000, (neg_non_smi - 0.5) << 3); + assertEquals(-0x73594000, (neg_non_smi - 0.5) << 4); + + assertEquals(pos_smi / 2, (pos_smi) >> 1); + assertEquals(pos_smi / 2, (pos_smi) >>> 1); + assertEquals(pos_non_smi, (pos_smi) << 1); + assertEquals(pos_smi / 8, (pos_smi) >> 3); + assertEquals(pos_smi / 8, (pos_smi) >>> 3); + assertEquals(-0x2329b000, (pos_smi) << 3); + assertEquals(0x73594000, (pos_smi) << 5); + assertEquals(pos_smi, (pos_smi + 0.5) >> 0); + assertEquals(pos_smi, (pos_smi + 0.5) >>> 0); + assertEquals(pos_smi, (pos_smi + 0.5) << 0); + assertEquals(pos_smi / 2, (pos_smi + 0.5) >> 1); + assertEquals(pos_smi / 2, (pos_smi + 0.5) >>> 1); + assertEquals(pos_non_smi, (pos_smi + 0.5) << 1); + assertEquals(pos_smi / 8, (pos_smi + 0.5) >> 3); + assertEquals(pos_smi / 8, (pos_smi + 0.5) >>> 3); + assertEquals(-0x2329b000, (pos_smi + 0.5) << 3); + assertEquals(0x73594000, (pos_smi + 0.5) << 5); + + assertEquals(neg_smi / 2, (neg_smi) >> 1); + assertEquals(neg_smi / 2 + 0x100000000 / 2, (neg_smi) >>> 1); + assertEquals(neg_non_smi, (neg_smi) << 1); + assertEquals(neg_smi / 8, (neg_smi) >> 3); + assertEquals(neg_smi / 8 + 0x100000000 / 8, (neg_smi) >>> 3); + assertEquals(0x46536000, (neg_smi) << 4); + assertEquals(-0x73594000, (neg_smi) << 5); + assertEquals(neg_smi, (neg_smi - 0.5) >> 0); + assertEquals(neg_smi + 0x100000000, (neg_smi - 0.5) >>> 0); + assertEquals(neg_smi, (neg_smi - 0.5) << 0); + assertEquals(neg_smi / 2, (neg_smi - 0.5) >> 1); + assertEquals(neg_smi / 2 + 0x100000000 / 2, (neg_smi - 0.5) >>> 1); + assertEquals(neg_non_smi, (neg_smi - 0.5) << 1); + assertEquals(neg_smi / 8, (neg_smi - 0.5) >> 3); + assertEquals(neg_smi / 8 + 0x100000000 / 8, (neg_smi - 0.5) >>> 3); + assertEquals(0x46536000, (neg_smi - 0.5) << 4); + assertEquals(-0x73594000, (neg_smi - 0.5) << 5); + // End block A + + // Repeat block A with 2^32 added to positive numbers and + // 2^32 subtracted from negative numbers. + // Begin block A repeat 1 + var two_32 = 0x100000000; + var neg_32 = -two_32; + assertEquals(pos_non_smi, (two_32 + pos_non_smi) >> 0); + assertEquals(pos_non_smi, (two_32 + pos_non_smi) >>> 0); + assertEquals(pos_non_smi, (two_32 + pos_non_smi) << 0); + assertEquals(neg_non_smi, (neg_32 + neg_non_smi) >> 0); + assertEquals(neg_non_smi + 0x100000000, (neg_32 + neg_non_smi) >>> 0); + assertEquals(neg_non_smi, (neg_32 + neg_non_smi) << 0); + assertEquals(pos_smi, (two_32 + pos_smi) >> 0); + assertEquals(pos_smi, (two_32 + pos_smi) >>> 0); + assertEquals(pos_smi, (two_32 + pos_smi) << 0); + assertEquals(neg_smi, (neg_32 + neg_smi) >> 0); + assertEquals(neg_smi + 0x100000000, (neg_32 + neg_smi) >>> 0); + assertEquals(neg_smi, (neg_32 + neg_smi) << 0); + + assertEquals(pos_non_smi / 2, (two_32 + pos_non_smi) >> 1); + assertEquals(pos_non_smi / 2, (two_32 + pos_non_smi) >>> 1); + assertEquals(-0x1194D800, (two_32 + pos_non_smi) << 1); + assertEquals(pos_non_smi / 8, (two_32 + pos_non_smi) >> 3); + assertEquals(pos_non_smi / 8, (two_32 + pos_non_smi) >>> 3); + assertEquals(-0x46536000, (two_32 + pos_non_smi) << 3); + assertEquals(0x73594000, (two_32 + pos_non_smi) << 4); + assertEquals(pos_non_smi, (two_32 + pos_non_smi + 0.5) >> 0); + assertEquals(pos_non_smi, (two_32 + pos_non_smi + 0.5) >>> 0); + assertEquals(pos_non_smi, (two_32 + pos_non_smi + 0.5) << 0); + assertEquals(pos_non_smi / 2, (two_32 + pos_non_smi + 0.5) >> 1); + assertEquals(pos_non_smi / 2, (two_32 + pos_non_smi + 0.5) >>> 1); + assertEquals(-0x1194D800, (two_32 + pos_non_smi + 0.5) << 1); + assertEquals(pos_non_smi / 8, (two_32 + pos_non_smi + 0.5) >> 3); + assertEquals(pos_non_smi / 8, (two_32 + pos_non_smi + 0.5) >>> 3); + assertEquals(-0x46536000, (two_32 + pos_non_smi + 0.5) << 3); + assertEquals(0x73594000, (two_32 + pos_non_smi + 0.5) << 4); + + assertEquals(neg_non_smi / 2, (neg_32 + neg_non_smi) >> 1); + assertEquals(neg_non_smi / 2 + 0x100000000 / 2, (neg_32 + neg_non_smi) >>> 1); + assertEquals(0x1194D800, (neg_32 + neg_non_smi) << 1); + assertEquals(neg_non_smi / 8, (neg_32 + neg_non_smi) >> 3); + assertEquals(neg_non_smi / 8 + 0x100000000 / 8, (neg_32 + neg_non_smi) >>> 3); + assertEquals(0x46536000, (neg_32 + neg_non_smi) << 3); + assertEquals(-0x73594000, (neg_32 + neg_non_smi) << 4); + assertEquals(neg_non_smi, (neg_32 + neg_non_smi - 0.5) >> 0); + assertEquals(neg_non_smi + 0x100000000, (neg_32 + neg_non_smi - 0.5) >>> 0); + assertEquals(neg_non_smi, (neg_32 + neg_non_smi - 0.5) << 0); + assertEquals(neg_non_smi / 2, (neg_32 + neg_non_smi - 0.5) >> 1); + assertEquals(neg_non_smi / 2 + 0x100000000 / 2, (neg_32 + neg_non_smi - 0.5) + >>> 1); + assertEquals(0x1194D800, (neg_32 + neg_non_smi - 0.5) << 1); + assertEquals(neg_non_smi / 8, (neg_32 + neg_non_smi - 0.5) >> 3); + assertEquals(neg_non_smi / 8 + 0x100000000 / 8, (neg_32 + neg_non_smi - 0.5) + >>> 3); + assertEquals(0x46536000, (neg_32 + neg_non_smi - 0.5) << 3); + assertEquals(-0x73594000, (neg_32 + neg_non_smi - 0.5) << 4); + + assertEquals(pos_smi / 2, (two_32 + pos_smi) >> 1); + assertEquals(pos_smi / 2, (two_32 + pos_smi) >>> 1); + assertEquals(pos_non_smi, (two_32 + pos_smi) << 1); + assertEquals(pos_smi / 8, (two_32 + pos_smi) >> 3); + assertEquals(pos_smi / 8, (two_32 + pos_smi) >>> 3); + assertEquals(-0x2329b000, (two_32 + pos_smi) << 3); + assertEquals(0x73594000, (two_32 + pos_smi) << 5); + assertEquals(pos_smi, (two_32 + pos_smi + 0.5) >> 0); + assertEquals(pos_smi, (two_32 + pos_smi + 0.5) >>> 0); + assertEquals(pos_smi, (two_32 + pos_smi + 0.5) << 0); + assertEquals(pos_smi / 2, (two_32 + pos_smi + 0.5) >> 1); + assertEquals(pos_smi / 2, (two_32 + pos_smi + 0.5) >>> 1); + assertEquals(pos_non_smi, (two_32 + pos_smi + 0.5) << 1); + assertEquals(pos_smi / 8, (two_32 + pos_smi + 0.5) >> 3); + assertEquals(pos_smi / 8, (two_32 + pos_smi + 0.5) >>> 3); + assertEquals(-0x2329b000, (two_32 + pos_smi + 0.5) << 3); + assertEquals(0x73594000, (two_32 + pos_smi + 0.5) << 5); + + assertEquals(neg_smi / 2, (neg_32 + neg_smi) >> 1); + assertEquals(neg_smi / 2 + 0x100000000 / 2, (neg_32 + neg_smi) >>> 1); + assertEquals(neg_non_smi, (neg_32 + neg_smi) << 1); + assertEquals(neg_smi / 8, (neg_32 + neg_smi) >> 3); + assertEquals((neg_smi + 0x100000000) / 8, (neg_32 + neg_smi) >>> 3); + assertEquals(0x46536000, (neg_32 + neg_smi) << 4); + assertEquals(-0x73594000, (neg_32 + neg_smi) << 5); + assertEquals(neg_smi, (neg_32 + neg_smi - 0.5) >> 0); + assertEquals(neg_smi + 0x100000000, (neg_32 + neg_smi - 0.5) >>> 0); + assertEquals(neg_smi, (neg_32 + neg_smi - 0.5) << 0); + assertEquals(neg_smi / 2, (neg_32 + neg_smi - 0.5) >> 1); + assertEquals(neg_smi / 2 + 0x100000000 / 2, (neg_32 + neg_smi - 0.5) >>> 1); + assertEquals(neg_non_smi, (neg_32 + neg_smi - 0.5) << 1); + assertEquals(neg_smi / 8, (neg_32 + neg_smi - 0.5) >> 3); + assertEquals(neg_smi / 8 + 0x100000000 / 8, (neg_32 + neg_smi - 0.5) >>> 3); + assertEquals(0x46536000, (neg_32 + neg_smi - 0.5) << 4); + assertEquals(-0x73594000, (neg_32 + neg_smi - 0.5) << 5); + // End block A repeat 1 + // Repeat block A with shift amounts in variables intialized with + // a constant. + var zero = 0; + var one = 1; + var three = 3; + var four = 4; + var five = 5; + // Begin block A repeat 2 + assertEquals(pos_non_smi, (pos_non_smi) >> zero); + assertEquals(pos_non_smi, (pos_non_smi) >>> zero); + assertEquals(pos_non_smi, (pos_non_smi) << zero); + assertEquals(neg_non_smi, (neg_non_smi) >> zero); + assertEquals(neg_non_smi + 0x100000000, (neg_non_smi) >>> zero); + assertEquals(neg_non_smi, (neg_non_smi) << zero); + assertEquals(pos_smi, (pos_smi) >> zero); + assertEquals(pos_smi, (pos_smi) >>> zero); + assertEquals(pos_smi, (pos_smi) << zero); + assertEquals(neg_smi, (neg_smi) >> zero); + assertEquals(neg_smi + 0x100000000, (neg_smi) >>> zero); + assertEquals(neg_smi, (neg_smi) << zero); + + assertEquals(pos_non_smi / 2, (pos_non_smi) >> one); + assertEquals(pos_non_smi / 2, (pos_non_smi) >>> one); + assertEquals(-0x1194D800, (pos_non_smi) << one); + assertEquals(pos_non_smi / 8, (pos_non_smi) >> three); + assertEquals(pos_non_smi / 8, (pos_non_smi) >>> three); + assertEquals(-0x46536000, (pos_non_smi) << three); + assertEquals(0x73594000, (pos_non_smi) << four); + assertEquals(pos_non_smi, (pos_non_smi + 0.5) >> zero); + assertEquals(pos_non_smi, (pos_non_smi + 0.5) >>> zero); + assertEquals(pos_non_smi, (pos_non_smi + 0.5) << zero); + assertEquals(pos_non_smi / 2, (pos_non_smi + 0.5) >> one); + assertEquals(pos_non_smi / 2, (pos_non_smi + 0.5) >>> one); + assertEquals(-0x1194D800, (pos_non_smi + 0.5) << one); + assertEquals(pos_non_smi / 8, (pos_non_smi + 0.5) >> three); + assertEquals(pos_non_smi / 8, (pos_non_smi + 0.5) >>> three); + assertEquals(-0x46536000, (pos_non_smi + 0.5) << three); + assertEquals(0x73594000, (pos_non_smi + 0.5) << four); + + assertEquals(neg_non_smi / 2, (neg_non_smi) >> one); + assertEquals(neg_non_smi / 2 + 0x100000000 / 2, (neg_non_smi) >>> one); + assertEquals(0x1194D800, (neg_non_smi) << one); + assertEquals(neg_non_smi / 8, (neg_non_smi) >> three); + assertEquals(neg_non_smi / 8 + 0x100000000 / 8, (neg_non_smi) >>> three); + assertEquals(0x46536000, (neg_non_smi) << three); + assertEquals(-0x73594000, (neg_non_smi) << four); + assertEquals(neg_non_smi, (neg_non_smi - 0.5) >> zero); + assertEquals(neg_non_smi + 0x100000000, (neg_non_smi - 0.5) >>> zero); + assertEquals(neg_non_smi, (neg_non_smi - 0.5) << zero); + assertEquals(neg_non_smi / 2, (neg_non_smi - 0.5) >> one); + assertEquals(neg_non_smi / 2 + 0x100000000 / 2, (neg_non_smi - 0.5) >>> one); + assertEquals(0x1194D800, (neg_non_smi - 0.5) << one); + assertEquals(neg_non_smi / 8, (neg_non_smi - 0.5) >> three); + assertEquals(neg_non_smi / 8 + 0x100000000 / 8, (neg_non_smi - 0.5) + >>> three); + assertEquals(0x46536000, (neg_non_smi - 0.5) << three); + assertEquals(-0x73594000, (neg_non_smi - 0.5) << four); + + assertEquals(pos_smi / 2, (pos_smi) >> one); + assertEquals(pos_smi / 2, (pos_smi) >>> one); + assertEquals(pos_non_smi, (pos_smi) << one); + assertEquals(pos_smi / 8, (pos_smi) >> three); + assertEquals(pos_smi / 8, (pos_smi) >>> three); + assertEquals(-0x2329b000, (pos_smi) << three); + assertEquals(0x73594000, (pos_smi) << five); + assertEquals(pos_smi, (pos_smi + 0.5) >> zero); + assertEquals(pos_smi, (pos_smi + 0.5) >>> zero); + assertEquals(pos_smi, (pos_smi + 0.5) << zero); + assertEquals(pos_smi / 2, (pos_smi + 0.5) >> one); + assertEquals(pos_smi / 2, (pos_smi + 0.5) >>> one); + assertEquals(pos_non_smi, (pos_smi + 0.5) << one); + assertEquals(pos_smi / 8, (pos_smi + 0.5) >> three); + assertEquals(pos_smi / 8, (pos_smi + 0.5) >>> three); + assertEquals(-0x2329b000, (pos_smi + 0.5) << three); + assertEquals(0x73594000, (pos_smi + 0.5) << five); + + assertEquals(neg_smi / 2, (neg_smi) >> one); + assertEquals(neg_smi / 2 + 0x100000000 / 2, (neg_smi) >>> one); + assertEquals(neg_non_smi, (neg_smi) << one); + assertEquals(neg_smi / 8, (neg_smi) >> three); + assertEquals(neg_smi / 8 + 0x100000000 / 8, (neg_smi) >>> three); + assertEquals(0x46536000, (neg_smi) << four); + assertEquals(-0x73594000, (neg_smi) << five); + assertEquals(neg_smi, (neg_smi - 0.5) >> zero); + assertEquals(neg_smi + 0x100000000, (neg_smi - 0.5) >>> zero); + assertEquals(neg_smi, (neg_smi - 0.5) << zero); + assertEquals(neg_smi / 2, (neg_smi - 0.5) >> one); + assertEquals(neg_smi / 2 + 0x100000000 / 2, (neg_smi - 0.5) >>> one); + assertEquals(neg_non_smi, (neg_smi - 0.5) << one); + assertEquals(neg_smi / 8, (neg_smi - 0.5) >> three); + assertEquals(neg_smi / 8 + 0x100000000 / 8, (neg_smi - 0.5) >>> three); + assertEquals(0x46536000, (neg_smi - 0.5) << four); + assertEquals(-0x73594000, (neg_smi - 0.5) << five); + // End block A repeat 2 + + // Repeat previous block, with computed values in the shift variables. + five = 0; + while (five < 5 ) ++five; + four = five - one; + three = four - one; + one = four - three; + zero = one - one; + + // Begin block A repeat 3 + assertEquals(pos_non_smi, (pos_non_smi) >> zero); + assertEquals(pos_non_smi, (pos_non_smi) >>> zero); + assertEquals(pos_non_smi, (pos_non_smi) << zero); + assertEquals(neg_non_smi, (neg_non_smi) >> zero); + assertEquals(neg_non_smi + 0x100000000, (neg_non_smi) >>> zero); + assertEquals(neg_non_smi, (neg_non_smi) << zero); + assertEquals(pos_smi, (pos_smi) >> zero); + assertEquals(pos_smi, (pos_smi) >>> zero); + assertEquals(pos_smi, (pos_smi) << zero); + assertEquals(neg_smi, (neg_smi) >> zero); + assertEquals(neg_smi + 0x100000000, (neg_smi) >>> zero); + assertEquals(neg_smi, (neg_smi) << zero); + + assertEquals(pos_non_smi / 2, (pos_non_smi) >> one); + assertEquals(pos_non_smi / 2, (pos_non_smi) >>> one); + assertEquals(-0x1194D800, (pos_non_smi) << one); + assertEquals(pos_non_smi / 8, (pos_non_smi) >> three); + assertEquals(pos_non_smi / 8, (pos_non_smi) >>> three); + assertEquals(-0x46536000, (pos_non_smi) << three); + assertEquals(0x73594000, (pos_non_smi) << four); + assertEquals(pos_non_smi, (pos_non_smi + 0.5) >> zero); + assertEquals(pos_non_smi, (pos_non_smi + 0.5) >>> zero); + assertEquals(pos_non_smi, (pos_non_smi + 0.5) << zero); + assertEquals(pos_non_smi / 2, (pos_non_smi + 0.5) >> one); + assertEquals(pos_non_smi / 2, (pos_non_smi + 0.5) >>> one); + assertEquals(-0x1194D800, (pos_non_smi + 0.5) << one); + assertEquals(pos_non_smi / 8, (pos_non_smi + 0.5) >> three); + assertEquals(pos_non_smi / 8, (pos_non_smi + 0.5) >>> three); + assertEquals(-0x46536000, (pos_non_smi + 0.5) << three); + assertEquals(0x73594000, (pos_non_smi + 0.5) << four); + + assertEquals(neg_non_smi / 2, (neg_non_smi) >> one); + assertEquals(neg_non_smi / 2 + 0x100000000 / 2, (neg_non_smi) >>> one); + assertEquals(0x1194D800, (neg_non_smi) << one); + assertEquals(neg_non_smi / 8, (neg_non_smi) >> three); + assertEquals(neg_non_smi / 8 + 0x100000000 / 8, (neg_non_smi) >>> three); + assertEquals(0x46536000, (neg_non_smi) << three); + assertEquals(-0x73594000, (neg_non_smi) << four); + assertEquals(neg_non_smi, (neg_non_smi - 0.5) >> zero); + assertEquals(neg_non_smi + 0x100000000, (neg_non_smi - 0.5) >>> zero); + assertEquals(neg_non_smi, (neg_non_smi - 0.5) << zero); + assertEquals(neg_non_smi / 2, (neg_non_smi - 0.5) >> one); + assertEquals(neg_non_smi / 2 + 0x100000000 / 2, (neg_non_smi - 0.5) >>> one); + assertEquals(0x1194D800, (neg_non_smi - 0.5) << one); + assertEquals(neg_non_smi / 8, (neg_non_smi - 0.5) >> three); + assertEquals(neg_non_smi / 8 + 0x100000000 / 8, (neg_non_smi - 0.5) + >>> three); + assertEquals(0x46536000, (neg_non_smi - 0.5) << three); + assertEquals(-0x73594000, (neg_non_smi - 0.5) << four); + + assertEquals(pos_smi / 2, (pos_smi) >> one); + assertEquals(pos_smi / 2, (pos_smi) >>> one); + assertEquals(pos_non_smi, (pos_smi) << one); + assertEquals(pos_smi / 8, (pos_smi) >> three); + assertEquals(pos_smi / 8, (pos_smi) >>> three); + assertEquals(-0x2329b000, (pos_smi) << three); + assertEquals(0x73594000, (pos_smi) << five); + assertEquals(pos_smi, (pos_smi + 0.5) >> zero); + assertEquals(pos_smi, (pos_smi + 0.5) >>> zero); + assertEquals(pos_smi, (pos_smi + 0.5) << zero); + assertEquals(pos_smi / 2, (pos_smi + 0.5) >> one); + assertEquals(pos_smi / 2, (pos_smi + 0.5) >>> one); + assertEquals(pos_non_smi, (pos_smi + 0.5) << one); + assertEquals(pos_smi / 8, (pos_smi + 0.5) >> three); + assertEquals(pos_smi / 8, (pos_smi + 0.5) >>> three); + assertEquals(-0x2329b000, (pos_smi + 0.5) << three); + assertEquals(0x73594000, (pos_smi + 0.5) << five); + + assertEquals(neg_smi / 2, (neg_smi) >> one); + assertEquals(neg_smi / 2 + 0x100000000 / 2, (neg_smi) >>> one); + assertEquals(neg_non_smi, (neg_smi) << one); + assertEquals(neg_smi / 8, (neg_smi) >> three); + assertEquals(neg_smi / 8 + 0x100000000 / 8, (neg_smi) >>> three); + assertEquals(0x46536000, (neg_smi) << four); + assertEquals(-0x73594000, (neg_smi) << five); + assertEquals(neg_smi, (neg_smi - 0.5) >> zero); + assertEquals(neg_smi + 0x100000000, (neg_smi - 0.5) >>> zero); + assertEquals(neg_smi, (neg_smi - 0.5) << zero); + assertEquals(neg_smi / 2, (neg_smi - 0.5) >> one); + assertEquals(neg_smi / 2 + 0x100000000 / 2, (neg_smi - 0.5) >>> one); + assertEquals(neg_non_smi, (neg_smi - 0.5) << one); + assertEquals(neg_smi / 8, (neg_smi - 0.5) >> three); + assertEquals(neg_smi / 8 + 0x100000000 / 8, (neg_smi - 0.5) >>> three); + assertEquals(0x46536000, (neg_smi - 0.5) << four); + assertEquals(-0x73594000, (neg_smi - 0.5) << five); + // End block A repeat 3 + + // Test non-integer shift value + assertEquals(5, 20.5 >> 2.4); + assertEquals(5, 20.5 >> 2.7); + var shift = 2.4; + assertEquals(5, 20.5 >> shift); + assertEquals(5, 20.5 >> shift + 0.3); + shift = shift + zero; + assertEquals(5, 20.5 >> shift); + assertEquals(5, 20.5 >> shift + 0.3); +} + +testShiftNonSmis(); -- 2.7.4