Bug 1499536 - Implement CodeGeneratorARM64::visitShiftI and visitUrshD. r=mgaudet
authorSean Stangl <sstangl@mozilla.com>
Mon, 22 Oct 2018 14:00:00 -0400
changeset 490821 7884434cdddeaa4c763168db3524cd785486b10d
parent 490820 f4d8966d0af45c469399f46b93afaf635c09c9b0
child 490822 183d44a4925963f8d2b865bff5b94fa649d5661d
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
reviewersmgaudet
bugs1499536, 1000960
milestone65.0a1
Bug 1499536 - Implement CodeGeneratorARM64::visitShiftI and visitUrshD. r=mgaudet Fixes ion/bug1000960.js.
js/src/jit/arm64/CodeGenerator-arm64.cpp
--- a/js/src/jit/arm64/CodeGenerator-arm64.cpp
+++ b/js/src/jit/arm64/CodeGenerator-arm64.cpp
@@ -563,23 +563,92 @@ CodeGenerator::visitBitOpI(LBitOpI* ins)
       default:
         MOZ_CRASH("unexpected binary opcode");
     }
 }
 
 void
 CodeGenerator::visitShiftI(LShiftI* ins)
 {
-    MOZ_CRASH("visitShiftI");
+    const ARMRegister lhs = toWRegister(ins->lhs());
+    const LAllocation* rhs = ins->rhs();
+    const ARMRegister dest = toWRegister(ins->output());
+
+    if (rhs->isConstant()) {
+        int32_t shift = ToInt32(rhs) & 0x1F;
+        switch (ins->bitop()) {
+          case JSOP_LSH:
+            masm.Lsl(dest, lhs, shift);
+            break;
+          case JSOP_RSH:
+            masm.Asr(dest, lhs, shift);
+            break;
+          case JSOP_URSH:
+            if (shift) {
+                masm.Lsr(dest, lhs, shift);
+            } else if (ins->mir()->toUrsh()->fallible()) {
+                // x >>> 0 can overflow.
+                masm.Ands(dest, lhs, Operand(0xFFFFFFFF));
+                bailoutIf(Assembler::Signed, ins->snapshot());
+            } else {
+                masm.Mov(dest, lhs);
+            }
+            break;
+          default:
+            MOZ_CRASH("Unexpected shift op");
+        }
+    } else {
+        const ARMRegister rhsreg = toWRegister(rhs);
+        switch (ins->bitop()) {
+          case JSOP_LSH:
+            masm.Lsl(dest, lhs, rhsreg);
+            break;
+          case JSOP_RSH:
+            masm.Asr(dest, lhs, rhsreg);
+            break;
+          case JSOP_URSH:
+            masm.Lsr(dest, lhs, rhsreg);
+            if (ins->mir()->toUrsh()->fallible()) {
+                /// x >>> 0 can overflow.
+                Label nonzero;
+                masm.Cbnz(rhsreg, &nonzero);
+                masm.Cmp(dest, Operand(0));
+                bailoutIf(Assembler::LessThan, ins->snapshot());
+                masm.bind(&nonzero);
+            }
+            break;
+          default:
+            MOZ_CRASH("Unexpected shift op");
+        }
+    }
 }
 
 void
 CodeGenerator::visitUrshD(LUrshD* ins)
 {
-    MOZ_CRASH("visitUrshD");
+    const ARMRegister lhs = toWRegister(ins->lhs());
+    const LAllocation* rhs = ins->rhs();
+    const FloatRegister out = ToFloatRegister(ins->output());
+
+    const Register temp = ToRegister(ins->temp());
+    const ARMRegister temp32 = toWRegister(ins->temp());
+
+    if (rhs->isConstant()) {
+        int32_t shift = ToInt32(rhs) & 0x1F;
+        if (shift) {
+            masm.Lsr(temp32, lhs, shift);
+            masm.convertUInt32ToDouble(temp, out);
+        } else {
+            masm.convertUInt32ToDouble(ToRegister(ins->lhs()), out);
+        }
+    } else {
+        masm.And(temp32, toWRegister(rhs), Operand(0x1F));
+        masm.Lsr(temp32, lhs, temp32);
+        masm.convertUInt32ToDouble(temp, out);
+    }
 }
 
 void
 CodeGenerator::visitPowHalfD(LPowHalfD* ins)
 {
     MOZ_CRASH("visitPowHalfD");
 }