Backed out changeset 2d72443b3ab6 (bug 1313043) for arm bustage
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Thu, 27 Oct 2016 14:38:22 +0200
changeset 319823 3c5bff02eebd885997457c89706c02968fed23d7
parent 319822 ea0c3bb88db2e96a0d43023b6fca7a0792a8c536
child 319824 862a1036317f3c0ec5d5925a4366b2cbf442198a
push id20748
push userphilringnalda@gmail.com
push dateFri, 28 Oct 2016 03:39:55 +0000
treeherderfx-team@715360440695 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1313043
milestone52.0a1
backs out2d72443b3ab664c1c7fe039d58e5dee1f3e672fa
Backed out changeset 2d72443b3ab6 (bug 1313043) for arm bustage
js/src/asmjs/WasmBaselineCompile.cpp
--- a/js/src/asmjs/WasmBaselineCompile.cpp
+++ b/js/src/asmjs/WasmBaselineCompile.cpp
@@ -946,48 +946,26 @@ class BaseCompiler
     RegI32 fromI64(RegI64 r) {
 #ifdef JS_PUNBOX64
         return RegI32(r.reg.reg);
 #else
         return RegI32(r.reg.low);
 #endif
     }
 
-    RegI64 widenI32(RegI32 r) {
+    RegI64 fromI32(RegI32 r) {
         MOZ_ASSERT(!isAvailable(r.reg));
 #ifdef JS_PUNBOX64
         return RegI64(Register64(r.reg));
 #else
         RegI32 high = needI32();
         return RegI64(Register64(high.reg, r.reg));
 #endif
     }
 
-    Register lowPart(RegI64 r) {
-#ifdef JS_PUNBOX64
-        return r.reg.reg;
-#else
-        return r.reg.low;
-#endif
-    }
-
-    Register maybeHighPart(RegI64 r) {
-#ifdef JS_PUNBOX64
-        return Register::Invalid();
-#else
-        return r.reg.high;
-#endif
-    }
-
-    void maybeClearHighPart(RegI64 r) {
-#ifdef JS_NUNBOX32
-        masm.move32(Imm32(0), r.reg.high);
-#endif
-    }
-
     void freeI32(RegI32 r) {
         freeGPR(r.reg);
     }
 
     void freeI64(RegI64 r) {
         freeInt64(r.reg);
     }
 
@@ -2480,37 +2458,33 @@ class BaseCompiler
         return rv;
     }
 
     void returnCleanup() {
         popStackBeforeBranch(ctl_[0].framePushed);
         masm.jump(&returnLabel_);
     }
 
-    void pop2xI32ForIntMulDiv(RegI32* r0, RegI32* r1) {
-#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
-        // srcDest must be eax, and edx will be clobbered.
-        need2xI32(specific_eax, specific_edx);
-        *r1 = popI32();
-        *r0 = popI32ToSpecific(specific_eax);
-        freeI32(specific_edx);
+    void subtractI64(RegI64 rhs, RegI64 srcDest) {
+#if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM)
+        masm.sub64(rhs.reg, srcDest.reg);
 #else
-        pop2xI32(r0, r1);
-#endif
-    }
-
-    void pop2xI64ForIntDiv(RegI64* r0, RegI64* r1) {
-#ifdef JS_CODEGEN_X64
-        // srcDest must be rax, and rdx will be clobbered.
-        need2xI64(specific_rax, specific_rdx);
-        *r1 = popI64();
-        *r0 = popI64ToSpecific(specific_rax);
-        freeI64(specific_rdx);
+        MOZ_CRASH("BaseCompiler platform hook: subtractI64");
+#endif
+    }
+
+    void multiplyI64(RegI64 rhs, RegI64 srcDest, RegI32 temp) {
+#if defined(JS_CODEGEN_X64)
+        MOZ_ASSERT(srcDest.reg.reg == rax);
+        MOZ_ASSERT(isAvailable(rdx));
+        masm.mul64(rhs.reg, srcDest.reg, temp.reg);
+#elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM)
+        masm.mul64(rhs.reg, srcDest.reg, temp.reg);
 #else
-        pop2xI64(r0, r1);
+        MOZ_CRASH("BaseCompiler platform hook: multiplyI64");
 #endif
     }
 
     void checkDivideByZeroI32(RegI32 rhs, RegI32 srcDest, Label* done) {
         if (isCompilingAsmJS()) {
             // Truncated division by zero is zero (Infinity|0 == 0)
             Label notDivByZero;
             masm.branchTest32(Assembler::NonZero, rhs.reg, rhs.reg, &notDivByZero);
@@ -2620,62 +2594,164 @@ class BaseCompiler
         masm.movq(rdx, rax);
 # else
         MOZ_CRASH("BaseCompiler platform hook: remainderI64");
 # endif
         masm.bind(&done);
     }
 #endif
 
-    void pop2xI32ForShiftOrRotate(RegI32* r0, RegI32* r1) {
-#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
-        *r1 = popI32(specific_ecx);
-        *r0 = popI32();
+    void orI64(RegI64 rhs, RegI64 srcDest) {
+        masm.or64(rhs.reg, srcDest.reg);
+    }
+
+    void andI64(RegI64 rhs, RegI64 srcDest) {
+#if defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM)
+        masm.and64(rhs.reg, srcDest.reg);
+#else
+        MOZ_CRASH("BaseCompiler platform hook: andI64");
+#endif
+    }
+
+    void xorI64(RegI64 rhs, RegI64 srcDest) {
+        masm.xor64(rhs.reg, srcDest.reg);
+    }
+
+    // Note, may destroy RHS too.
+    void lshiftI32(RegI32 rhs, RegI32 srcDest) {
+#if defined(JS_CODEGEN_ARM)
+        masm.and32(Imm32(31), rhs.reg);
+#endif
+        masm.lshift32(rhs.reg, srcDest.reg);
+    }
+
+    void lshiftI64(RegI64 shift, RegI64 srcDest) {
+#if defined(JS_CODEGEN_X64)
+        masm.lshift64(shift.reg.reg, srcDest.reg);
+#elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM)
+        masm.lshift64(shift.reg.low, srcDest.reg);
 #else
-        pop2xI32(r0, r1);
-#endif
-    }
-
-    void pop2xI64ForShiftOrRotate(RegI64* r0, RegI64* r1) {
-#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
-        needI32(specific_ecx);
-        *r1 = widenI32(specific_ecx);
-        *r1 = popI64ToSpecific(*r1);
-        *r0 = popI64();
+        MOZ_CRASH("BaseCompiler platform hook: lshiftI64");
+#endif
+    }
+
+    // Note, may destroy RHS too.
+    void rshiftI32(RegI32 rhs, RegI32 srcDest) {
+#if defined(JS_CODEGEN_ARM)
+        masm.and32(Imm32(31), rhs.reg);
+#endif
+        masm.rshift32Arithmetic(rhs.reg, srcDest.reg);
+    }
+
+    // Note, may destroy RHS too.
+    void rshiftIU32(RegI32 rhs, RegI32 srcDest) {
+#if defined(JS_CODEGEN_ARM)
+        masm.and32(Imm32(31), rhs.reg);
+#endif
+        masm.rshift32(rhs.reg, srcDest.reg);
+    }
+
+    void rshiftI64(RegI64 shift, RegI64 srcDest) {
+#if defined(JS_CODEGEN_X64)
+        masm.rshift64Arithmetic(shift.reg.reg, srcDest.reg);
+#elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM)
+        masm.rshift64Arithmetic(shift.reg.low, srcDest.reg);
+#else
+        MOZ_CRASH("BaseCompiler platform hook: rshiftI64");
+#endif
+    }
+
+    void rshiftU64(RegI64 shift, RegI64 srcDest) {
+#if defined(JS_CODEGEN_X64)
+        masm.rshift64(shift.reg.reg, srcDest.reg);
+#elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM)
+        masm.rshift64(shift.reg.low, srcDest.reg);
 #else
-        pop2xI64(r0, r1);
-#endif
-    }
-
-    void maskShiftCount32(RegI32 r) {
-#if defined(JS_CODEGEN_ARM)
-        masm.and32(Imm32(31), r.reg);
+        MOZ_CRASH("BaseCompiler platform hook: rshiftU64");
+#endif
+    }
+
+    void rotateRightI64(RegI64 shift, RegI64 srcDest) {
+#if defined(JS_CODEGEN_X64)
+        masm.rotateRight64(shift.reg.reg, srcDest.reg, srcDest.reg, Register::Invalid());
+#elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM)
+        masm.rotateRight64(shift.reg.low, srcDest.reg, srcDest.reg, shift.reg.high);
+#else
+        MOZ_CRASH("BaseCompiler platform hook: rotateRightI64");
+#endif
+    }
+
+    void rotateLeftI64(RegI64 shift, RegI64 srcDest) {
+#if defined(JS_CODEGEN_X64)
+        masm.rotateLeft64(shift.reg.reg, srcDest.reg, srcDest.reg, Register::Invalid());
+#elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM)
+        masm.rotateLeft64(shift.reg.low, srcDest.reg, srcDest.reg, shift.reg.high);
+#else
+        MOZ_CRASH("BaseCompiler platform hook: rotateLeftI64");
+#endif
+    }
+
+    void clzI64(RegI64 srcDest) {
+#if defined(JS_CODEGEN_X64)
+        masm.clz64(srcDest.reg, srcDest.reg.reg);
+#elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM)
+        masm.clz64(srcDest.reg, srcDest.reg.low);
+        masm.move32(Imm32(0), srcDest.reg.high);
+#else
+        MOZ_CRASH("BaseCompiler platform hook: clzI64");
+#endif
+    }
+
+    void ctzI64(RegI64 srcDest) {
+#if defined(JS_CODEGEN_X64)
+        masm.ctz64(srcDest.reg, srcDest.reg.reg);
+#elif defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_ARM)
+        masm.ctz64(srcDest.reg, srcDest.reg.low);
+        masm.move32(Imm32(0), srcDest.reg.high);
+#else
+        MOZ_CRASH("BaseCompiler platform hook: ctzI64");
 #endif
     }
 
     bool popcnt32NeedsTemp() const {
 #if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
         return !AssemblerX86Shared::HasPOPCNT();
 #elif defined(JS_CODEGEN_ARM)
         return true;
 #else
         MOZ_CRASH("BaseCompiler platform hook: popcnt32NeedsTemp");
 #endif
     }
 
+    void popcntI32(RegI32 srcDest, RegI32 tmp) {
+#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_ARM)
+        masm.popcnt32(srcDest.reg, srcDest.reg, tmp.reg);
+#else
+        MOZ_CRASH("BaseCompiler platform hook: popcntI32");
+#endif
+    }
+
     bool popcnt64NeedsTemp() const {
 #if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
         return !AssemblerX86Shared::HasPOPCNT();
 #elif defined(JS_CODEGEN_ARM)
         return true;
 #else
         MOZ_CRASH("BaseCompiler platform hook: popcnt64NeedsTemp");
 #endif
     }
 
+    void popcntI64(RegI64 srcDest, RegI32 tmp) {
+#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64) || defined(JS_CODEGEN_ARM)
+        masm.popcnt64(srcDest.reg, srcDest.reg, tmp.reg);
+#else
+        MOZ_CRASH("BaseCompiler platform hook: popcntI64");
+#endif
+    }
+
     void reinterpretI64AsF64(RegI64 src, RegF64 dest) {
 #if defined(JS_CODEGEN_X64)
         masm.vmovq(src.reg.reg, dest.reg);
 #elif defined(JS_CODEGEN_X86)
         masm.Push(src.reg.high);
         masm.Push(src.reg.low);
         masm.vmovq(Operand(esp, 0), dest.reg);
         masm.freeStack(sizeof(uint64_t));
@@ -3787,17 +3863,17 @@ BaseCompiler::emitSubtractI32()
     pushI32(r0);
 }
 
 void
 BaseCompiler::emitSubtractI64()
 {
     RegI64 r0, r1;
     pop2xI64(&r0, &r1);
-    masm.sub64(r1.reg, r0.reg);
+    subtractI64(r1, r0);
     freeI64(r1);
     pushI64(r0);
 }
 
 void
 BaseCompiler::emitSubtractF32()
 {
     RegF32 r0, r1;
@@ -3817,17 +3893,25 @@ BaseCompiler::emitSubtractF64()
     pushF64(r0);
 }
 
 void
 BaseCompiler::emitMultiplyI32()
 {
     // TODO / OPTIMIZE: Multiplication by constant is common (bug 1275442)
     RegI32 r0, r1;
-    pop2xI32ForIntMulDiv(&r0, &r1);
+#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
+    // srcDest must be eax, and edx will be clobbered.
+    need2xI32(specific_eax, specific_edx);
+    r1 = popI32();
+    r0 = popI32ToSpecific(specific_eax);
+    freeI32(specific_edx);
+#else
+    pop2xI32(&r0, &r1);
+#endif
     masm.mul32(r1.reg, r0.reg);
     freeI32(r1);
     pushI32(r0);
 }
 
 void
 BaseCompiler::emitMultiplyI64()
 {
@@ -3844,17 +3928,17 @@ BaseCompiler::emitMultiplyI64()
     need2xI32(specific_eax, specific_edx);
     r1 = popI64();
     r0 = popI64ToSpecific(RegI64(Register64(specific_edx.reg, specific_eax.reg)));
     temp = needI32();
 #else
     pop2xI64(&r0, &r1);
     temp = needI32();
 #endif
-    masm.mul64(r1.reg, r0.reg, temp.reg);
+    multiplyI64(r1, r0, temp);
     if (temp.reg != Register::Invalid())
         freeI32(temp);
     freeI64(r1);
     pushI64(r0);
 }
 
 void
 BaseCompiler::emitMultiplyF32()
@@ -3876,128 +3960,190 @@ BaseCompiler::emitMultiplyF64()
     pushF64(r0);
 }
 
 void
 BaseCompiler::emitQuotientI32()
 {
     // TODO / OPTIMIZE: Fast case if lhs >= 0 and rhs is power of two.
     RegI32 r0, r1;
-    pop2xI32ForIntMulDiv(&r0, &r1);
+#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
+    // srcDest must be eax, and edx will be clobbered.
+    need2xI32(specific_eax, specific_edx);
+    r1 = popI32();
+    r0 = popI32ToSpecific(specific_eax);
+    freeI32(specific_edx);
+#else
+    pop2xI32(&r0, &r1);
+#endif
 
     Label done;
     checkDivideByZeroI32(r1, r0, &done);
     checkDivideSignedOverflowI32(r1, r0, &done, ZeroOnOverflow(false));
     masm.quotient32(r1.reg, r0.reg, IsUnsigned(false));
     masm.bind(&done);
 
     freeI32(r1);
     pushI32(r0);
 }
 
 void
 BaseCompiler::emitQuotientU32()
 {
     // TODO / OPTIMIZE: Fast case if lhs >= 0 and rhs is power of two.
     RegI32 r0, r1;
-    pop2xI32ForIntMulDiv(&r0, &r1);
+#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
+    // srcDest must be eax, and edx will be clobbered.
+    need2xI32(specific_eax, specific_edx);
+    r1 = popI32();
+    r0 = popI32ToSpecific(specific_eax);
+    freeI32(specific_edx);
+#else
+    pop2xI32(&r0, &r1);
+#endif
 
     Label done;
     checkDivideByZeroI32(r1, r0, &done);
     masm.quotient32(r1.reg, r0.reg, IsUnsigned(true));
     masm.bind(&done);
 
     freeI32(r1);
     pushI32(r0);
 }
 
 #ifndef QUOT_REM_I64_CALLOUT
 void
 BaseCompiler::emitQuotientI64()
 {
 # ifdef JS_PUNBOX64
     RegI64 r0, r1;
-    pop2xI64ForIntDiv(&r0, &r1);
+#  ifdef JS_CODEGEN_X64
+    // srcDest must be rax, and rdx will be clobbered.
+    need2xI64(specific_rax, specific_rdx);
+    r1 = popI64();
+    r0 = popI64ToSpecific(specific_rax);
+    freeI64(specific_rdx);
+#  else
+    pop2xI64(&r0, &r1);
+#  endif
     quotientI64(r1, r0, IsUnsigned(false));
     freeI64(r1);
     pushI64(r0);
 # else
     MOZ_CRASH("BaseCompiler platform hook: emitQuotientI64");
 # endif
 }
 
 void
 BaseCompiler::emitQuotientU64()
 {
 # ifdef JS_PUNBOX64
     RegI64 r0, r1;
-    pop2xI64ForIntDiv(&r0, &r1);
+#  ifdef JS_CODEGEN_X64
+    // srcDest must be rax, and rdx will be clobbered.
+    need2xI64(specific_rax, specific_rdx);
+    r1 = popI64();
+    r0 = popI64ToSpecific(specific_rax);
+    freeI64(specific_rdx);
+#  else
+    pop2xI64(&r0, &r1);
+#  endif
     quotientI64(r1, r0, IsUnsigned(true));
     freeI64(r1);
     pushI64(r0);
 # else
     MOZ_CRASH("BaseCompiler platform hook: emitQuotientU64");
 # endif
 }
 #endif
 
 void
 BaseCompiler::emitRemainderI32()
 {
     // TODO / OPTIMIZE: Fast case if lhs >= 0 and rhs is power of two.
     RegI32 r0, r1;
-    pop2xI32ForIntMulDiv(&r0, &r1);
+#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
+    // srcDest must be eax, and edx will be clobbered.
+    need2xI32(specific_eax, specific_edx);
+    r1 = popI32();
+    r0 = popI32ToSpecific(specific_eax);
+    freeI32(specific_edx);
+#else
+    pop2xI32(&r0, &r1);
+#endif
 
     Label done;
     checkDivideByZeroI32(r1, r0, &done);
     checkDivideSignedOverflowI32(r1, r0, &done, ZeroOnOverflow(true));
     masm.remainder32(r1.reg, r0.reg, IsUnsigned(false));
     masm.bind(&done);
 
     freeI32(r1);
     pushI32(r0);
 }
 
 void
 BaseCompiler::emitRemainderU32()
 {
     // TODO / OPTIMIZE: Fast case if lhs >= 0 and rhs is power of two.
     RegI32 r0, r1;
-    pop2xI32ForIntMulDiv(&r0, &r1);
+#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
+    // srcDest must be eax, and edx will be clobbered.
+    need2xI32(specific_eax, specific_edx);
+    r1 = popI32();
+    r0 = popI32ToSpecific(specific_eax);
+    freeI32(specific_edx);
+#else
+    pop2xI32(&r0, &r1);
+#endif
 
     Label done;
     checkDivideByZeroI32(r1, r0, &done);
     masm.remainder32(r1.reg, r0.reg, IsUnsigned(true));
     masm.bind(&done);
 
     freeI32(r1);
     pushI32(r0);
 }
 
 #ifndef QUOT_REM_I64_CALLOUT
 void
 BaseCompiler::emitRemainderI64()
 {
 # ifdef JS_PUNBOX64
     RegI64 r0, r1;
-    pop2xI64ForIntDiv(&r0, &r1);
+#  ifdef JS_CODEGEN_X64
+    need2xI64(specific_rax, specific_rdx);
+    r1 = popI64();
+    r0 = popI64ToSpecific(specific_rax);
+    freeI64(specific_rdx);
+#  else
+    pop2xI64(&r0, &r1);
+#  endif
     remainderI64(r1, r0, IsUnsigned(false));
     freeI64(r1);
     pushI64(r0);
 # else
     MOZ_CRASH("BaseCompiler platform hook: emitRemainderI64");
 # endif
 }
 
 void
 BaseCompiler::emitRemainderU64()
 {
 # ifdef JS_PUNBOX64
     RegI64 r0, r1;
-    pop2xI64ForIntDiv(&r0, &r1);
+#  ifdef JS_CODEGEN_X64
+    need2xI64(specific_rax, specific_rdx);
+    r1 = popI64();
+    r0 = popI64ToSpecific(specific_rax);
+    freeI64(specific_rdx);
+#  else
+    pop2xI64(&r0, &r1);
+#  endif
     remainderI64(r1, r0, IsUnsigned(true));
     freeI64(r1);
     pushI64(r0);
 # else
     MOZ_CRASH("BaseCompiler platform hook: emitRemainderU64");
 # endif
 }
 #endif
@@ -4169,17 +4315,17 @@ BaseCompiler::emitOrI32()
     pushI32(r0);
 }
 
 void
 BaseCompiler::emitOrI64()
 {
     RegI64 r0, r1;
     pop2xI64(&r0, &r1);
-    masm.or64(r1.reg, r0.reg);
+    orI64(r1, r0);
     freeI64(r1);
     pushI64(r0);
 }
 
 void
 BaseCompiler::emitAndI32()
 {
     RegI32 r0, r1;
@@ -4189,17 +4335,17 @@ BaseCompiler::emitAndI32()
     pushI32(r0);
 }
 
 void
 BaseCompiler::emitAndI64()
 {
     RegI64 r0, r1;
     pop2xI64(&r0, &r1);
-    masm.and64(r1.reg, r0.reg);
+    andI64(r1, r0);
     freeI64(r1);
     pushI64(r0);
 }
 
 void
 BaseCompiler::emitXorI32()
 {
     RegI32 r0, r1;
@@ -4209,148 +4355,205 @@ BaseCompiler::emitXorI32()
     pushI32(r0);
 }
 
 void
 BaseCompiler::emitXorI64()
 {
     RegI64 r0, r1;
     pop2xI64(&r0, &r1);
-    masm.xor64(r1.reg, r0.reg);
+    xorI64(r1, r0);
     freeI64(r1);
     pushI64(r0);
 }
 
 void
 BaseCompiler::emitShlI32()
 {
     int32_t c;
     if (popConstI32(c)) {
         RegI32 r = popI32();
         masm.lshift32(Imm32(c & 31), r.reg);
         pushI32(r);
     } else {
         RegI32 r0, r1;
-        pop2xI32ForShiftOrRotate(&r0, &r1);
-        maskShiftCount32(r1);
-        masm.lshift32(r1.reg, r0.reg);
+#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
+        r1 = popI32(specific_ecx);
+        r0 = popI32();
+#else
+        pop2xI32(&r0, &r1);
+#endif
+        lshiftI32(r1, r0);
         freeI32(r1);
         pushI32(r0);
     }
 }
 
 void
 BaseCompiler::emitShlI64()
 {
     // TODO / OPTIMIZE: Constant rhs
     RegI64 r0, r1;
-    pop2xI64ForShiftOrRotate(&r0, &r1);
-    masm.lshift64(lowPart(r1), r0.reg);
+#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
+    needI32(specific_ecx);
+    r1 = fromI32(specific_ecx);
+    r1 = popI64ToSpecific(r1);
+    r0 = popI64();
+#else
+    pop2xI64(&r0, &r1);
+#endif
+    lshiftI64(r1, r0);
     freeI64(r1);
     pushI64(r0);
 }
 
 void
 BaseCompiler::emitShrI32()
 {
     int32_t c;
     if (popConstI32(c)) {
         RegI32 r = popI32();
         masm.rshift32Arithmetic(Imm32(c & 31), r.reg);
         pushI32(r);
     } else {
         RegI32 r0, r1;
-        pop2xI32ForShiftOrRotate(&r0, &r1);
-        maskShiftCount32(r1);
-        masm.rshift32Arithmetic(r1.reg, r0.reg);
+#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
+        r1 = popI32(specific_ecx);
+        r0 = popI32();
+#else
+        pop2xI32(&r0, &r1);
+#endif
+        rshiftI32(r1, r0);
         freeI32(r1);
         pushI32(r0);
     }
 }
 
 void
 BaseCompiler::emitShrI64()
 {
     // TODO / OPTIMIZE: Constant rhs
     RegI64 r0, r1;
-    pop2xI64ForShiftOrRotate(&r0, &r1);
-    masm.rshift64Arithmetic(lowPart(r1), r0.reg);
+#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
+    needI32(specific_ecx);
+    r1 = fromI32(specific_ecx);
+    r1 = popI64ToSpecific(r1);
+    r0 = popI64();
+#else
+    pop2xI64(&r0, &r1);
+#endif
+    rshiftI64(r1, r0);
     freeI64(r1);
     pushI64(r0);
 }
 
 void
 BaseCompiler::emitShrU32()
 {
     int32_t c;
     if (popConstI32(c)) {
         RegI32 r = popI32();
         masm.rshift32(Imm32(c & 31), r.reg);
         pushI32(r);
     } else {
         RegI32 r0, r1;
-        pop2xI32ForShiftOrRotate(&r0, &r1);
-        maskShiftCount32(r1);
-        masm.rshift32(r1.reg, r0.reg);
+#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
+        r1 = popI32(specific_ecx);
+        r0 = popI32();
+#else
+        pop2xI32(&r0, &r1);
+#endif
+        rshiftIU32(r1, r0);
         freeI32(r1);
         pushI32(r0);
     }
 }
 
 void
 BaseCompiler::emitShrU64()
 {
     // TODO / OPTIMIZE: Constant rhs
     RegI64 r0, r1;
-    pop2xI64ForShiftOrRotate(&r0, &r1);
-    masm.rshift64(lowPart(r1), r0.reg);
+#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
+    needI32(specific_ecx);
+    r1 = fromI32(specific_ecx);
+    r1 = popI64ToSpecific(r1);
+    r0 = popI64();
+#else
+    pop2xI64(&r0, &r1);
+#endif
+    rshiftU64(r1, r0);
     freeI64(r1);
     pushI64(r0);
 }
 
 void
 BaseCompiler::emitRotrI32()
 {
     // TODO / OPTIMIZE: Constant rhs
     RegI32 r0, r1;
-    pop2xI32ForShiftOrRotate(&r0, &r1);
+#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
+    r1 = popI32(specific_ecx);
+    r0 = popI32();
+#else
+    pop2xI32(&r0, &r1);
+#endif
     masm.rotateRight(r1.reg, r0.reg, r0.reg);
     freeI32(r1);
     pushI32(r0);
 }
 
 void
 BaseCompiler::emitRotrI64()
 {
     // TODO / OPTIMIZE: Constant rhs
     RegI64 r0, r1;
-    pop2xI64ForShiftOrRotate(&r0, &r1);
-    masm.rotateRight64(lowPart(r1), r0.reg, r0.reg, maybeHighPart(r1));
+#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
+    needI32(specific_ecx);
+    r1 = fromI32(specific_ecx);
+    r1 = popI64ToSpecific(r1);
+    r0 = popI64();
+#else
+    pop2xI64(&r0, &r1);
+#endif
+    rotateRightI64(r1, r0);
     freeI64(r1);
     pushI64(r0);
 }
 
 void
 BaseCompiler::emitRotlI32()
 {
     // TODO / OPTIMIZE: Constant rhs
     RegI32 r0, r1;
-    pop2xI32ForShiftOrRotate(&r0, &r1);
+#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
+    r1 = popI32(specific_ecx);
+    r0 = popI32();
+#else
+    pop2xI32(&r0, &r1);
+#endif
     masm.rotateLeft(r1.reg, r0.reg, r0.reg);
     freeI32(r1);
     pushI32(r0);
 }
 
 void
 BaseCompiler::emitRotlI64()
 {
     // TODO / OPTIMIZE: Constant rhs
     RegI64 r0, r1;
-    pop2xI64ForShiftOrRotate(&r0, &r1);
-    masm.rotateLeft64(lowPart(r1), r0.reg, r0.reg, maybeHighPart(r1));
+#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
+    needI32(specific_ecx);
+    r1 = fromI32(specific_ecx);
+    r1 = popI64ToSpecific(r1);
+    r0 = popI64();
+#else
+    pop2xI64(&r0, &r1);
+#endif
+    rotateLeftI64(r1, r0);
     freeI64(r1);
     pushI64(r0);
 }
 
 void
 BaseCompiler::emitEqzI32()
 {
     // TODO / OPTIMIZE: Boolean evaluation for control
@@ -4381,62 +4584,60 @@ BaseCompiler::emitClzI32()
     masm.clz32(r0.reg, r0.reg, IsKnownNotZero(false));
     pushI32(r0);
 }
 
 void
 BaseCompiler::emitClzI64()
 {
     RegI64 r0 = popI64();
-    masm.clz64(r0.reg, lowPart(r0));
-    maybeClearHighPart(r0);
+    clzI64(r0);
     pushI64(r0);
 }
 
 void
 BaseCompiler::emitCtzI32()
 {
     RegI32 r0 = popI32();
     masm.ctz32(r0.reg, r0.reg, IsKnownNotZero(false));
     pushI32(r0);
 }
 
 void
 BaseCompiler::emitCtzI64()
 {
     RegI64 r0 = popI64();
-    masm.ctz64(r0.reg, lowPart(r0));
-    maybeClearHighPart(r0);
+    ctzI64(r0);
     pushI64(r0);
 }
 
 void
 BaseCompiler::emitPopcntI32()
 {
     RegI32 r0 = popI32();
     if (popcnt32NeedsTemp()) {
         RegI32 tmp = needI32();
-        masm.popcnt32(r0.reg, r0.reg, tmp.reg);
+        popcntI32(r0, tmp);
         freeI32(tmp);
     } else {
-        masm.popcnt32(r0.reg, r0.reg, invalidI32().reg);
+        popcntI32(r0, invalidI32());
     }
     pushI32(r0);
 }
 
 void
 BaseCompiler::emitPopcntI64()
 {
     RegI64 r0 = popI64();
     if (popcnt64NeedsTemp()) {
         RegI32 tmp = needI32();
-        masm.popcnt64(r0.reg, r0.reg, tmp.reg);
+        popcntI64(r0, tmp);
         freeI32(tmp);
     } else {
-        masm.popcnt64(r0.reg, r0.reg, invalidI32().reg);
+        popcntI64(r0, invalidI32());
     }
     pushI64(r0);
 }
 
 void
 BaseCompiler::emitBitNotI32()
 {
     RegI32 r0 = popI32();
@@ -4594,28 +4795,28 @@ void
 BaseCompiler::emitExtendI32ToI64()
 {
 #if defined(JS_CODEGEN_X86)
     need2xI32(specific_edx, specific_eax);
     RegI32 r0 = popI32ToSpecific(specific_eax);
     RegI64 x0 = RegI64(Register64(specific_edx.reg, specific_eax.reg));
 #else
     RegI32 r0 = popI32();
-    RegI64 x0 = widenI32(r0);
+    RegI64 x0 = fromI32(r0);
 #endif
     extendI32ToI64(r0, x0);
     pushI64(x0);
     // Note: no need to free r0, since it is part of x0
 }
 
 void
 BaseCompiler::emitExtendU32ToI64()
 {
     RegI32 r0 = popI32();
-    RegI64 x0 = widenI32(r0);
+    RegI64 x0 = fromI32(r0);
     extendU32ToI64(r0, x0);
     pushI64(x0);
     // Note: no need to free r0, since it is part of x0
 }
 
 void
 BaseCompiler::emitReinterpretF32AsI32()
 {