2010-04-29  Oliver Hunt  <oliver@apple.com>

        Reviewed by Gavin Barraclough.

        Add codegen support for unsigned right shift
        https://bugs.webkit.org/show_bug.cgi?id=38375

        Expose unsigned right shift in the macro assembler, and make use of it
        from the jit.  Currently if the result is outside the range 0..2^31-1
        we simply fall back to the slow case, even in JSVALUE64 and JSVALUE32_64
        where technically we could still return an immediate value.

        * assembler/MacroAssemblerARM.h:
        (JSC::MacroAssemblerARM::urshift32):
        * assembler/MacroAssemblerARMv7.h:
        (JSC::MacroAssemblerARMv7::urshift32):
        * assembler/MacroAssemblerX86Common.h:
        (JSC::MacroAssemblerX86Common::urshift32):
        * assembler/X86Assembler.h:
        (JSC::X86Assembler::):
        (JSC::X86Assembler::shrl_i8r):
        (JSC::X86Assembler::shrl_CLr):
           Add unsigned right shift to the x86 assembler
        * jit/JIT.cpp:
        (JSC::JIT::privateCompileMainPass):
        (JSC::JIT::privateCompileSlowCases):
           op_rshift no longer simply get thrown to a stub function
        * jit/JIT.h:
        * jit/JITArithmetic.cpp:
        (JSC::JIT::emit_op_urshift):
        (JSC::JIT::emitSlow_op_urshift):
          JSVALUE32 and JSVALUE64 implementation.  Only supports
          double lhs in JSVALUE64.
        * jit/JITArithmetic32_64.cpp:
        (JSC::JIT::emit_op_rshift):
        (JSC::JIT::emitSlow_op_rshift):
        (JSC::JIT::emit_op_urshift):
        (JSC::JIT::emitSlow_op_urshift):
          Refactor right shift code to have shared implementation between signed
          and unsigned versions.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@58562 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog
index d19ff26..a8ee46f 100644
--- a/JavaScriptCore/ChangeLog
+++ b/JavaScriptCore/ChangeLog
@@ -2,6 +2,47 @@
 
         Reviewed by Gavin Barraclough.
 
+        Add codegen support for unsigned right shift
+        https://bugs.webkit.org/show_bug.cgi?id=38375
+
+        Expose unsigned right shift in the macro assembler, and make use of it
+        from the jit.  Currently if the result is outside the range 0..2^31-1
+        we simply fall back to the slow case, even in JSVALUE64 and JSVALUE32_64
+        where technically we could still return an immediate value.
+
+        * assembler/MacroAssemblerARM.h:
+        (JSC::MacroAssemblerARM::urshift32):
+        * assembler/MacroAssemblerARMv7.h:
+        (JSC::MacroAssemblerARMv7::urshift32):
+        * assembler/MacroAssemblerX86Common.h:
+        (JSC::MacroAssemblerX86Common::urshift32):
+        * assembler/X86Assembler.h:
+        (JSC::X86Assembler::):
+        (JSC::X86Assembler::shrl_i8r):
+        (JSC::X86Assembler::shrl_CLr):
+           Add unsigned right shift to the x86 assembler
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        (JSC::JIT::privateCompileSlowCases):
+           op_rshift no longer simply get thrown to a stub function
+        * jit/JIT.h:
+        * jit/JITArithmetic.cpp:
+        (JSC::JIT::emit_op_urshift):
+        (JSC::JIT::emitSlow_op_urshift):
+          JSVALUE32 and JSVALUE64 implementation.  Only supports
+          double lhs in JSVALUE64.
+        * jit/JITArithmetic32_64.cpp:
+        (JSC::JIT::emit_op_rshift):
+        (JSC::JIT::emitSlow_op_rshift):
+        (JSC::JIT::emit_op_urshift):
+        (JSC::JIT::emitSlow_op_urshift):
+          Refactor right shift code to have shared implementation between signed
+          and unsigned versions.
+
+2010-04-29  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Gavin Barraclough.
+
         Handle double on righthand side of a right shift
         https://bugs.webkit.org/show_bug.cgi?id=38363
 
diff --git a/JavaScriptCore/assembler/MacroAssemblerARM.h b/JavaScriptCore/assembler/MacroAssemblerARM.h
index 34e60c6..c9c70d1 100644
--- a/JavaScriptCore/assembler/MacroAssemblerARM.h
+++ b/JavaScriptCore/assembler/MacroAssemblerARM.h
@@ -178,6 +178,20 @@
     {
         m_assembler.movs_r(dest, m_assembler.asr(dest, imm.m_value & 0x1f));
     }
+    
+    void urshift32(RegisterID shift_amount, RegisterID dest)
+    {
+        ARMWord w = ARMAssembler::getOp2(0x1f);
+        ASSERT(w != ARMAssembler::INVALID_IMM);
+        m_assembler.and_r(ARMRegisters::S0, shift_amount, w);
+        
+        m_assembler.movs_r(dest, m_assembler.lsr_r(dest, ARMRegisters::S0));
+    }
+    
+    void urshift32(Imm32 imm, RegisterID dest)
+    {
+        m_assembler.movs_r(dest, m_assembler.lsr(dest, imm.m_value & 0x1f));
+    }
 
     void sub32(RegisterID src, RegisterID dest)
     {
diff --git a/JavaScriptCore/assembler/MacroAssemblerARMv7.h b/JavaScriptCore/assembler/MacroAssemblerARMv7.h
index 3c58b93..8b422ed 100644
--- a/JavaScriptCore/assembler/MacroAssemblerARMv7.h
+++ b/JavaScriptCore/assembler/MacroAssemblerARMv7.h
@@ -257,6 +257,21 @@
     {
         m_assembler.asr(dest, dest, imm.m_value & 0x1f);
     }
+    
+    void urshift32(RegisterID shift_amount, RegisterID dest)
+    {
+        // Clamp the shift to the range 0..31
+        ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(0x1f);
+        ASSERT(armImm.isValid());
+        m_assembler.ARM_and(dataTempRegister, shift_amount, armImm);
+        
+        m_assembler.lsr(dest, dest, dataTempRegister);
+    }
+    
+    void urshift32(Imm32 imm, RegisterID dest)
+    {
+        m_assembler.lsr(dest, dest, imm.m_value & 0x1f);
+    }
 
     void sub32(RegisterID src, RegisterID dest)
     {
diff --git a/JavaScriptCore/assembler/MacroAssemblerX86Common.h b/JavaScriptCore/assembler/MacroAssemblerX86Common.h
index 9522511..0b32e5d 100644
--- a/JavaScriptCore/assembler/MacroAssemblerX86Common.h
+++ b/JavaScriptCore/assembler/MacroAssemblerX86Common.h
@@ -249,6 +249,33 @@
     {
         m_assembler.sarl_i8r(imm.m_value, dest);
     }
+    
+    void urshift32(RegisterID shift_amount, RegisterID dest)
+    {
+        // On x86 we can only shift by ecx; if asked to shift by another register we'll
+        // need rejig the shift amount into ecx first, and restore the registers afterwards.
+        if (shift_amount != X86Registers::ecx) {
+            swap(shift_amount, X86Registers::ecx);
+            
+            // E.g. transform "shrl %eax, %eax" -> "xchgl %eax, %ecx; shrl %ecx, %ecx; xchgl %eax, %ecx"
+            if (dest == shift_amount)
+                m_assembler.shrl_CLr(X86Registers::ecx);
+            // E.g. transform "shrl %eax, %ecx" -> "xchgl %eax, %ecx; shrl %ecx, %eax; xchgl %eax, %ecx"
+            else if (dest == X86Registers::ecx)
+                m_assembler.shrl_CLr(shift_amount);
+            // E.g. transform "shrl %eax, %ebx" -> "xchgl %eax, %ecx; shrl %ecx, %ebx; xchgl %eax, %ecx"
+            else
+                m_assembler.shrl_CLr(dest);
+            
+            swap(shift_amount, X86Registers::ecx);
+        } else
+            m_assembler.shrl_CLr(dest);
+    }
+    
+    void urshift32(Imm32 imm, RegisterID dest)
+    {
+        m_assembler.shrl_i8r(imm.m_value, dest);
+    }
 
     void sub32(RegisterID src, RegisterID dest)
     {
diff --git a/JavaScriptCore/assembler/X86Assembler.h b/JavaScriptCore/assembler/X86Assembler.h
index c833bbc..20d72f5 100644
--- a/JavaScriptCore/assembler/X86Assembler.h
+++ b/JavaScriptCore/assembler/X86Assembler.h
@@ -201,6 +201,7 @@
         GROUP1A_OP_POP = 0,
 
         GROUP2_OP_SHL = 4,
+        GROUP2_OP_SHR = 5,
         GROUP2_OP_SAR = 7,
 
         GROUP3_OP_TEST = 0,
@@ -673,6 +674,21 @@
     {
         m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SAR, dst);
     }
+    
+    void shrl_i8r(int imm, RegisterID dst)
+    {
+        if (imm == 1)
+            m_formatter.oneByteOp(OP_GROUP2_Ev1, GROUP2_OP_SHR, dst);
+        else {
+            m_formatter.oneByteOp(OP_GROUP2_EvIb, GROUP2_OP_SHR, dst);
+            m_formatter.immediate8(imm);
+        }
+    }
+    
+    void shrl_CLr(RegisterID dst)
+    {
+        m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SHR, dst);
+    }
 
     void shll_i8r(int imm, RegisterID dst)
     {
diff --git a/JavaScriptCore/jit/JIT.cpp b/JavaScriptCore/jit/JIT.cpp
index ec23d8c..a5923f5 100644
--- a/JavaScriptCore/jit/JIT.cpp
+++ b/JavaScriptCore/jit/JIT.cpp
@@ -200,7 +200,6 @@
         DEFINE_BINARY_OP(op_in)
         DEFINE_BINARY_OP(op_less)
         DEFINE_BINARY_OP(op_lesseq)
-        DEFINE_BINARY_OP(op_urshift)
         DEFINE_UNARY_OP(op_is_boolean)
         DEFINE_UNARY_OP(op_is_function)
         DEFINE_UNARY_OP(op_is_number)
@@ -301,6 +300,7 @@
         DEFINE_OP(op_resolve_with_base)
         DEFINE_OP(op_ret)
         DEFINE_OP(op_rshift)
+        DEFINE_OP(op_urshift)
         DEFINE_OP(op_sret)
         DEFINE_OP(op_strcat)
         DEFINE_OP(op_stricteq)
@@ -427,6 +427,7 @@
         DEFINE_SLOWCASE_OP(op_resolve_global)
 #endif
         DEFINE_SLOWCASE_OP(op_rshift)
+        DEFINE_SLOWCASE_OP(op_urshift)
         DEFINE_SLOWCASE_OP(op_stricteq)
         DEFINE_SLOWCASE_OP(op_sub)
         DEFINE_SLOWCASE_OP(op_to_jsnumber)
diff --git a/JavaScriptCore/jit/JIT.h b/JavaScriptCore/jit/JIT.h
index 22e7aba..dbd311b 100644
--- a/JavaScriptCore/jit/JIT.h
+++ b/JavaScriptCore/jit/JIT.h
@@ -734,6 +734,7 @@
         void emit_op_to_jsnumber(Instruction*);
         void emit_op_to_primitive(Instruction*);
         void emit_op_unexpected_load(Instruction*);
+        void emit_op_urshift(Instruction*);
 #if ENABLE(JIT_OPTIMIZE_MOD)
         void softModulo();
 #endif
@@ -784,6 +785,11 @@
         void emitSlow_op_sub(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_to_jsnumber(Instruction*, Vector<SlowCaseEntry>::iterator&);
         void emitSlow_op_to_primitive(Instruction*, Vector<SlowCaseEntry>::iterator&);
+        void emitSlow_op_urshift(Instruction*, Vector<SlowCaseEntry>::iterator&);
+
+        
+        void emitRightShift(Instruction*, bool isUnsigned);
+        void emitRightShiftSlowCase(Instruction*, Vector<SlowCaseEntry>::iterator&, bool isUnsigned);
 
         /* These functions are deprecated: Please use JITStubCall instead. */
         void emitPutJITStubArg(RegisterID src, unsigned argumentNumber);
diff --git a/JavaScriptCore/jit/JITArithmetic.cpp b/JavaScriptCore/jit/JITArithmetic.cpp
index 61d0e1f..d45859e 100644
--- a/JavaScriptCore/jit/JITArithmetic.cpp
+++ b/JavaScriptCore/jit/JITArithmetic.cpp
@@ -187,6 +187,118 @@
     stubCall.call(result);
 }
 
+void JIT::emit_op_urshift(Instruction* currentInstruction)
+{
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned op1 = currentInstruction[2].u.operand;
+    unsigned op2 = currentInstruction[3].u.operand;
+
+    // Slow case of urshift makes assumptions about what registers hold the
+    // shift arguments, so any changes must be updated there as well.
+    if (isOperandConstantImmediateInt(op2)) {
+        emitGetVirtualRegister(op1, regT0);
+        emitJumpSlowCaseIfNotImmediateInteger(regT0);
+        emitFastArithImmToInt(regT0);
+        int shift = getConstantOperand(op2).asInt32();
+        if (shift)
+            urshift32(Imm32(shift & 0x1f), regT0);
+        // unsigned shift < 0 or shift = k*2^32 may result in (essentially)
+        // a toUint conversion, which can result in a value we can represent
+        // as an immediate int.
+        if (shift < 0 || !(shift & 31))
+            addSlowCase(branch32(LessThan, regT0, Imm32(0)));
+#if USE(JSVALUE32)
+        addSlowCase(branchAdd32(Overflow, regT0, regT0));
+        signExtend32ToPtr(regT0, regT0);
+#endif
+        emitFastArithReTagImmediate(regT0, regT0);
+        emitPutVirtualRegister(dst, regT0);
+        return;
+    }
+    emitGetVirtualRegisters(op1, regT0, op2, regT1);
+    if (!isOperandConstantImmediateInt(op1))
+        emitJumpSlowCaseIfNotImmediateInteger(regT0);
+    emitJumpSlowCaseIfNotImmediateInteger(regT1);
+    emitFastArithImmToInt(regT0);
+    emitFastArithImmToInt(regT1);
+    urshift32(regT1, regT0);
+    addSlowCase(branch32(LessThan, regT0, Imm32(0)));
+#if USE(JSVALUE32)
+    addSlowCase(branchAdd32(Overflow, regT0, regT0));
+    signExtend32ToPtr(regT0, regT0);
+#endif
+    emitFastArithReTagImmediate(regT0, regT0);
+    emitPutVirtualRegister(dst, regT0);
+}
+
+void JIT::emitSlow_op_urshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    unsigned dst = currentInstruction[1].u.operand;
+    unsigned op1 = currentInstruction[2].u.operand;
+    unsigned op2 = currentInstruction[3].u.operand;
+    if (isOperandConstantImmediateInt(op2)) {
+        int shift = getConstantOperand(op2).asInt32();
+        // op1 = regT0
+        linkSlowCase(iter); // int32 check
+#if USE(JSVALUE64)
+        if (supportsFloatingPointTruncate()) {
+            JumpList failures;
+            failures.append(emitJumpIfNotImmediateNumber(regT0)); // op1 is not a double
+            addPtr(tagTypeNumberRegister, regT0);
+            movePtrToDouble(regT0, fpRegT0);
+            failures.append(branchTruncateDoubleToInt32(fpRegT0, regT0));
+            if (shift)
+                urshift32(Imm32(shift & 0x1f), regT0);
+            if (shift < 0 || !(shift & 31))
+                failures.append(branch32(LessThan, regT0, Imm32(0)));
+            emitFastArithReTagImmediate(regT0, regT0);
+            emitPutVirtualRegister(dst, regT0);
+            emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift));
+            failures.link(this);
+        }
+#endif // JSVALUE64
+        if (shift < 0 || !(shift & 31))
+            linkSlowCase(iter); // failed to box in hot path
+#if USE(JSVALUE32)
+        linkSlowCase(iter); // Couldn't box result
+#endif
+    } else {
+        // op1 = regT0
+        // op2 = regT1
+        if (!isOperandConstantImmediateInt(op1)) {
+            linkSlowCase(iter); // int32 check -- op1 is not an int
+#if USE(JSVALUE64)
+            if (supportsFloatingPointTruncate()) {
+                JumpList failures;
+                failures.append(emitJumpIfNotImmediateNumber(regT0)); // op1 is not a double
+                addPtr(tagTypeNumberRegister, regT0);
+                movePtrToDouble(regT0, fpRegT0);
+                failures.append(branchTruncateDoubleToInt32(fpRegT0, regT0));
+                failures.append(emitJumpIfNotImmediateInteger(regT1)); // op2 is not an int
+                emitFastArithImmToInt(regT1);
+                urshift32(regT1, regT0);
+                failures.append(branch32(LessThan, regT0, Imm32(0)));
+                emitFastArithReTagImmediate(regT0, regT0);
+                emitPutVirtualRegister(dst, regT0);
+                emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift));
+                failures.link(this);
+            }
+#endif
+        }
+        
+        linkSlowCase(iter); // int32 check - op2 is not an int
+        linkSlowCase(iter); // Can't represent unsigned result as an immediate
+#if USE(JSVALUE32)
+        linkSlowCase(iter); // Couldn't box result
+#endif
+    }
+    
+    JITStubCall stubCall(this, cti_op_urshift);
+    stubCall.addArgument(op1, regT0);
+    stubCall.addArgument(op2, regT1);
+    stubCall.call(dst);
+}
+
 void JIT::emit_op_jnless(Instruction* currentInstruction)
 {
     unsigned op1 = currentInstruction[1].u.operand;
diff --git a/JavaScriptCore/jit/JITArithmetic32_64.cpp b/JavaScriptCore/jit/JITArithmetic32_64.cpp
index dab5e39..177f04c 100644
--- a/JavaScriptCore/jit/JITArithmetic32_64.cpp
+++ b/JavaScriptCore/jit/JITArithmetic32_64.cpp
@@ -314,9 +314,9 @@
     stubCall.call(dst);
 }
 
-// RightShift (>>)
+// RightShift (>>) and UnsignedRightShift (>>>) helper
 
-void JIT::emit_op_rshift(Instruction* currentInstruction)
+void JIT::emitRightShift(Instruction* currentInstruction, bool isUnsigned)
 {
     unsigned dst = currentInstruction[1].u.operand;
     unsigned op1 = currentInstruction[2].u.operand;
@@ -327,7 +327,18 @@
     if (isOperandConstantImmediateInt(op2)) {
         emitLoad(op1, regT1, regT0);
         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
-        rshift32(Imm32(getConstantOperand(op2).asInt32()), regT0);
+        int shift = getConstantOperand(op2).asInt32();
+        if (isUnsigned) {
+            if (shift)
+                urshift32(Imm32(shift & 0x1f), regT0);
+            // unsigned shift < 0 or shift = k*2^32 may result in (essentially)
+            // a toUint conversion, which can result in a value we can represent
+            // as an immediate int.
+            if (shift < 0 || !(shift & 31))
+                addSlowCase(branch32(LessThan, regT0, Imm32(0)));
+        } else if (shift) { // signed right shift by zero is simply toInt conversion
+            rshift32(Imm32(shift & 0x1f), regT0);
+        }
         emitStoreInt32(dst, regT0, dst == op1);
         return;
     }
@@ -336,28 +347,41 @@
     if (!isOperandConstantImmediateInt(op1))
         addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)));
     addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)));
-    rshift32(regT2, regT0);
+    if (isUnsigned) {
+        urshift32(regT2, regT0);
+        addSlowCase(branch32(LessThan, regT0, Imm32(0)));
+    } else
+        rshift32(regT2, regT0);
     emitStoreInt32(dst, regT0, dst == op1 || dst == op2);
 }
 
-void JIT::emitSlow_op_rshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+void JIT::emitRightShiftSlowCase(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter, bool isUnsigned)
 {
     unsigned dst = currentInstruction[1].u.operand;
     unsigned op1 = currentInstruction[2].u.operand;
     unsigned op2 = currentInstruction[3].u.operand;
     if (isOperandConstantImmediateInt(op2)) {
+        int shift = getConstantOperand(op2).asInt32();
         // op1 = regT1:regT0
         linkSlowCase(iter); // int32 check
         if (supportsFloatingPointTruncate()) {
-            Jump notDouble = branch32(AboveOrEqual, regT1, Imm32(JSValue::LowestTag));
+            JumpList failures;
+            failures.append(branch32(AboveOrEqual, regT1, Imm32(JSValue::LowestTag)));
             emitLoadDouble(op1, fpRegT0);
-            Jump truncationFailed = branchTruncateDoubleToInt32(fpRegT0, regT0);
-            rshift32(Imm32(getConstantOperand(op2).asInt32()), regT0);
+            failures.append(branchTruncateDoubleToInt32(fpRegT0, regT0));
+            if (isUnsigned) {
+                if (shift)
+                    urshift32(Imm32(shift & 0x1f), regT0);
+                if (shift < 0 || !(shift & 31))
+                    failures.append(branch32(LessThan, regT0, Imm32(0)));
+            } else if (shift)
+                rshift32(Imm32(shift & 0x1f), regT0);
             emitStoreInt32(dst, regT0, dst == op1 || dst == op2);
             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift));
-            notDouble.link(this);
-            truncationFailed.link(this);
+            failures.link(this);
         }
+        if (isUnsigned && (shift < 0 || !(shift & 31)))
+            linkSlowCase(iter); // failed to box in hot path
     } else {
         // op1 = regT1:regT0
         // op2 = regT3:regT2
@@ -368,7 +392,10 @@
                 emitLoadDouble(op1, fpRegT0);
                 Jump notInt = branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag)); // op2 is not an int
                 Jump cantTruncate = branchTruncateDoubleToInt32(fpRegT0, regT0);
-                rshift32(regT2, regT0);
+                if (isUnsigned)
+                    urshift32(regT2, regT0);
+                else
+                    rshift32(regT2, regT0);
                 emitStoreInt32(dst, regT0, dst == op1 || dst == op2);
                 emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift));
                 notDouble.link(this);
@@ -378,14 +405,40 @@
         }
 
         linkSlowCase(iter); // int32 check - op2 is not an int
+        if (isUnsigned)
+            linkSlowCase(iter); // Can't represent unsigned result as an immediate
     }
 
-    JITStubCall stubCall(this, cti_op_rshift);
+    JITStubCall stubCall(this, isUnsigned ? cti_op_urshift : cti_op_rshift);
     stubCall.addArgument(op1);
     stubCall.addArgument(op2);
     stubCall.call(dst);
 }
 
+// RightShift (>>)
+
+void JIT::emit_op_rshift(Instruction* currentInstruction)
+{
+    emitRightShift(currentInstruction, false);
+}
+
+void JIT::emitSlow_op_rshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    emitRightShiftSlowCase(currentInstruction, iter, false);
+}
+
+// UnsignedRightShift (>>>)
+
+void JIT::emit_op_urshift(Instruction* currentInstruction)
+{
+    emitRightShift(currentInstruction, true);
+}
+
+void JIT::emitSlow_op_urshift(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter)
+{
+    emitRightShiftSlowCase(currentInstruction, iter, true);
+}
+
 // BitAnd (&)
 
 void JIT::emit_op_bitand(Instruction* currentInstruction)