Bug 1313043 - wasm baseline: remove many ifdefs. r=h4writer
☠☠ backed out by 3c5bff02eebd ☠ ☠
authorLars T Hansen <lhansen@mozilla.com>
Wed, 26 Oct 2016 14:21:59 +0200
changeset 319818 2d72443b3ab664c1c7fe039d58e5dee1f3e672fa
parent 319817 e47ad07f2d527ca78a01f022c177df8437b03b6a
child 319819 6963f5ab0000e8bf6833dfed1efb04ce261f49bc
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)
reviewersh4writer
bugs1313043
milestone52.0a1
Bug 1313043 - wasm baseline: remove many ifdefs. r=h4writer
js/src/asmjs/WasmBaselineCompile.cpp
--- a/js/src/asmjs/WasmBaselineCompile.cpp
+++ b/js/src/asmjs/WasmBaselineCompile.cpp
@@ -946,26 +946,48 @@ class BaseCompiler
     RegI32 fromI64(RegI64 r) {
 #ifdef JS_PUNBOX64
         return RegI32(r.reg.reg);
 #else
         return RegI32(r.reg.low);
 #endif
     }
 
-    RegI64 fromI32(RegI32 r) {
+    RegI64 widenI32(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);
     }
 
@@ -2458,33 +2480,37 @@ class BaseCompiler
         return rv;
     }
 
     void returnCleanup() {
         popStackBeforeBranch(ctl_[0].framePushed);
         masm.jump(&returnLabel_);
     }
 
-    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);
+    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);
 #else
-        MOZ_CRASH("BaseCompiler platform hook: subtractI64");
+        pop2xI32(r0, r1);
 #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);
+    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);
 #else
-        MOZ_CRASH("BaseCompiler platform hook: multiplyI64");
+        pop2xI64(r0, r1);
 #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);
@@ -2594,164 +2620,62 @@ class BaseCompiler
         masm.movq(rdx, rax);
 # else
         MOZ_CRASH("BaseCompiler platform hook: remainderI64");
 # endif
         masm.bind(&done);
     }
 #endif
 
-    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);
+    void pop2xI32ForShiftOrRotate(RegI32* r0, RegI32* r1) {
+#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
+        *r1 = popI32(specific_ecx);
+        *r0 = popI32();
 #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
-        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);
+        pop2xI32(r0, r1);
 #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);
+    }
+
+    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();
 #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
-        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");
+        pop2xI64(r0, r1);
 #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");
+    void maskShiftCount32(RegI32 r) {
+#if defined(JS_CODEGEN_ARM)
+        masm.and32(Imm32(31), r.reg);
 #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));
@@ -3863,17 +3787,17 @@ BaseCompiler::emitSubtractI32()
     pushI32(r0);
 }
 
 void
 BaseCompiler::emitSubtractI64()
 {
     RegI64 r0, r1;
     pop2xI64(&r0, &r1);
-    subtractI64(r1, r0);
+    masm.sub64(r1.reg, r0.reg);
     freeI64(r1);
     pushI64(r0);
 }
 
 void
 BaseCompiler::emitSubtractF32()
 {
     RegF32 r0, r1;
@@ -3893,25 +3817,17 @@ BaseCompiler::emitSubtractF64()
     pushF64(r0);
 }
 
 void
 BaseCompiler::emitMultiplyI32()
 {
     // TODO / OPTIMIZE: Multiplication by constant is common (bug 1275442)
     RegI32 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
+    pop2xI32ForIntMulDiv(&r0, &r1);
     masm.mul32(r1.reg, r0.reg);
     freeI32(r1);
     pushI32(r0);
 }
 
 void
 BaseCompiler::emitMultiplyI64()
 {
@@ -3928,17 +3844,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
-    multiplyI64(r1, r0, temp);
+    masm.mul64(r1.reg, r0.reg, temp.reg);
     if (temp.reg != Register::Invalid())
         freeI32(temp);
     freeI64(r1);
     pushI64(r0);
 }
 
 void
 BaseCompiler::emitMultiplyF32()
@@ -3960,190 +3876,128 @@ BaseCompiler::emitMultiplyF64()
     pushF64(r0);
 }
 
 void
 BaseCompiler::emitQuotientI32()
 {
     // TODO / OPTIMIZE: Fast case if lhs >= 0 and rhs is power of two.
     RegI32 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
+    pop2xI32ForIntMulDiv(&r0, &r1);
 
     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;
-#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
+    pop2xI32ForIntMulDiv(&r0, &r1);
 
     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;
-#  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
+    pop2xI64ForIntDiv(&r0, &r1);
     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;
-#  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
+    pop2xI64ForIntDiv(&r0, &r1);
     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;
-#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
+    pop2xI32ForIntMulDiv(&r0, &r1);
 
     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;
-#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
+    pop2xI32ForIntMulDiv(&r0, &r1);
 
     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;
-#  ifdef JS_CODEGEN_X64
-    need2xI64(specific_rax, specific_rdx);
-    r1 = popI64();
-    r0 = popI64ToSpecific(specific_rax);
-    freeI64(specific_rdx);
-#  else
-    pop2xI64(&r0, &r1);
-#  endif
+    pop2xI64ForIntDiv(&r0, &r1);
     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;
-#  ifdef JS_CODEGEN_X64
-    need2xI64(specific_rax, specific_rdx);
-    r1 = popI64();
-    r0 = popI64ToSpecific(specific_rax);
-    freeI64(specific_rdx);
-#  else
-    pop2xI64(&r0, &r1);
-#  endif
+    pop2xI64ForIntDiv(&r0, &r1);
     remainderI64(r1, r0, IsUnsigned(true));
     freeI64(r1);
     pushI64(r0);
 # else
     MOZ_CRASH("BaseCompiler platform hook: emitRemainderU64");
 # endif
 }
 #endif
@@ -4315,17 +4169,17 @@ BaseCompiler::emitOrI32()
     pushI32(r0);
 }
 
 void
 BaseCompiler::emitOrI64()
 {
     RegI64 r0, r1;
     pop2xI64(&r0, &r1);
-    orI64(r1, r0);
+    masm.or64(r1.reg, r0.reg);
     freeI64(r1);
     pushI64(r0);
 }
 
 void
 BaseCompiler::emitAndI32()
 {
     RegI32 r0, r1;
@@ -4335,17 +4189,17 @@ BaseCompiler::emitAndI32()
     pushI32(r0);
 }
 
 void
 BaseCompiler::emitAndI64()
 {
     RegI64 r0, r1;
     pop2xI64(&r0, &r1);
-    andI64(r1, r0);
+    masm.and64(r1.reg, r0.reg);
     freeI64(r1);
     pushI64(r0);
 }
 
 void
 BaseCompiler::emitXorI32()
 {
     RegI32 r0, r1;
@@ -4355,205 +4209,148 @@ BaseCompiler::emitXorI32()
     pushI32(r0);
 }
 
 void
 BaseCompiler::emitXorI64()
 {
     RegI64 r0, r1;
     pop2xI64(&r0, &r1);
-    xorI64(r1, r0);
+    masm.xor64(r1.reg, r0.reg);
     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;
-#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
-        r1 = popI32(specific_ecx);
-        r0 = popI32();
-#else
-        pop2xI32(&r0, &r1);
-#endif
-        lshiftI32(r1, r0);
+        pop2xI32ForShiftOrRotate(&r0, &r1);
+        maskShiftCount32(r1);
+        masm.lshift32(r1.reg, r0.reg);
         freeI32(r1);
         pushI32(r0);
     }
 }
 
 void
 BaseCompiler::emitShlI64()
 {
     // TODO / OPTIMIZE: Constant rhs
     RegI64 r0, 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
-    lshiftI64(r1, r0);
+    pop2xI64ForShiftOrRotate(&r0, &r1);
+    masm.lshift64(lowPart(r1), r0.reg);
     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;
-#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
-        r1 = popI32(specific_ecx);
-        r0 = popI32();
-#else
-        pop2xI32(&r0, &r1);
-#endif
-        rshiftI32(r1, r0);
+        pop2xI32ForShiftOrRotate(&r0, &r1);
+        maskShiftCount32(r1);
+        masm.rshift32Arithmetic(r1.reg, r0.reg);
         freeI32(r1);
         pushI32(r0);
     }
 }
 
 void
 BaseCompiler::emitShrI64()
 {
     // TODO / OPTIMIZE: Constant rhs
     RegI64 r0, 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
-    rshiftI64(r1, r0);
+    pop2xI64ForShiftOrRotate(&r0, &r1);
+    masm.rshift64Arithmetic(lowPart(r1), r0.reg);
     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;
-#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
-        r1 = popI32(specific_ecx);
-        r0 = popI32();
-#else
-        pop2xI32(&r0, &r1);
-#endif
-        rshiftIU32(r1, r0);
+        pop2xI32ForShiftOrRotate(&r0, &r1);
+        maskShiftCount32(r1);
+        masm.rshift32(r1.reg, r0.reg);
         freeI32(r1);
         pushI32(r0);
     }
 }
 
 void
 BaseCompiler::emitShrU64()
 {
     // TODO / OPTIMIZE: Constant rhs
     RegI64 r0, 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
-    rshiftU64(r1, r0);
+    pop2xI64ForShiftOrRotate(&r0, &r1);
+    masm.rshift64(lowPart(r1), r0.reg);
     freeI64(r1);
     pushI64(r0);
 }
 
 void
 BaseCompiler::emitRotrI32()
 {
     // TODO / OPTIMIZE: Constant rhs
     RegI32 r0, r1;
-#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
-    r1 = popI32(specific_ecx);
-    r0 = popI32();
-#else
-    pop2xI32(&r0, &r1);
-#endif
+    pop2xI32ForShiftOrRotate(&r0, &r1);
     masm.rotateRight(r1.reg, r0.reg, r0.reg);
     freeI32(r1);
     pushI32(r0);
 }
 
 void
 BaseCompiler::emitRotrI64()
 {
     // TODO / OPTIMIZE: Constant rhs
     RegI64 r0, 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);
+    pop2xI64ForShiftOrRotate(&r0, &r1);
+    masm.rotateRight64(lowPart(r1), r0.reg, r0.reg, maybeHighPart(r1));
     freeI64(r1);
     pushI64(r0);
 }
 
 void
 BaseCompiler::emitRotlI32()
 {
     // TODO / OPTIMIZE: Constant rhs
     RegI32 r0, r1;
-#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
-    r1 = popI32(specific_ecx);
-    r0 = popI32();
-#else
-    pop2xI32(&r0, &r1);
-#endif
+    pop2xI32ForShiftOrRotate(&r0, &r1);
     masm.rotateLeft(r1.reg, r0.reg, r0.reg);
     freeI32(r1);
     pushI32(r0);
 }
 
 void
 BaseCompiler::emitRotlI64()
 {
     // TODO / OPTIMIZE: Constant rhs
     RegI64 r0, 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);
+    pop2xI64ForShiftOrRotate(&r0, &r1);
+    masm.rotateLeft64(lowPart(r1), r0.reg, r0.reg, maybeHighPart(r1));
     freeI64(r1);
     pushI64(r0);
 }
 
 void
 BaseCompiler::emitEqzI32()
 {
     // TODO / OPTIMIZE: Boolean evaluation for control
@@ -4584,60 +4381,62 @@ BaseCompiler::emitClzI32()
     masm.clz32(r0.reg, r0.reg, IsKnownNotZero(false));
     pushI32(r0);
 }
 
 void
 BaseCompiler::emitClzI64()
 {
     RegI64 r0 = popI64();
-    clzI64(r0);
+    masm.clz64(r0.reg, lowPart(r0));
+    maybeClearHighPart(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();
-    ctzI64(r0);
+    masm.ctz64(r0.reg, lowPart(r0));
+    maybeClearHighPart(r0);
     pushI64(r0);
 }
 
 void
 BaseCompiler::emitPopcntI32()
 {
     RegI32 r0 = popI32();
     if (popcnt32NeedsTemp()) {
         RegI32 tmp = needI32();
-        popcntI32(r0, tmp);
+        masm.popcnt32(r0.reg, r0.reg, tmp.reg);
         freeI32(tmp);
     } else {
-        popcntI32(r0, invalidI32());
+        masm.popcnt32(r0.reg, r0.reg, invalidI32().reg);
     }
     pushI32(r0);
 }
 
 void
 BaseCompiler::emitPopcntI64()
 {
     RegI64 r0 = popI64();
     if (popcnt64NeedsTemp()) {
         RegI32 tmp = needI32();
-        popcntI64(r0, tmp);
+        masm.popcnt64(r0.reg, r0.reg, tmp.reg);
         freeI32(tmp);
     } else {
-        popcntI64(r0, invalidI32());
+        masm.popcnt64(r0.reg, r0.reg, invalidI32().reg);
     }
     pushI64(r0);
 }
 
 void
 BaseCompiler::emitBitNotI32()
 {
     RegI32 r0 = popI32();
@@ -4795,28 +4594,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 = fromI32(r0);
+    RegI64 x0 = widenI32(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 = fromI32(r0);
+    RegI64 x0 = widenI32(r0);
     extendU32ToI64(r0, x0);
     pushI64(x0);
     // Note: no need to free r0, since it is part of x0
 }
 
 void
 BaseCompiler::emitReinterpretF32AsI32()
 {