Index: /trunk/include/iprt/armv8.h
===================================================================
--- /trunk/include/iprt/armv8.h	(revision 104055)
+++ /trunk/include/iprt/armv8.h	(revision 104056)
@@ -3442,4 +3442,14 @@
 
 
+/** A64: Encodes an ASR instruction w/ immediate shift value.
+ * @see Armv8A64MkInstrBitfieldImm for parameter details.  */
+DECL_FORCE_INLINE(uint32_t) Armv8A64MkInstrAsrImm(uint32_t iRegResult, uint32_t iRegSrc, uint32_t cShift, bool f64Bit = true)
+{
+    uint32_t const cWidth = f64Bit ? 63 : 31;
+    Assert(cShift > 0); Assert(cShift <= cWidth);
+    return Armv8A64MkInstrBitfieldImm(0, iRegResult, iRegSrc, cShift, cWidth /*uImm6S*/, f64Bit, f64Bit);
+}
+
+
 /** A64: Encodes a BFM instruction.
  * @see Armv8A64MkInstrBitfieldImm for parameter details.  */
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllInstPython.py
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllInstPython.py	(revision 104055)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllInstPython.py	(revision 104056)
@@ -2956,12 +2956,12 @@
     'IEM_MC_ADD_GREG_U64_TO_LOCAL':                              (McBlock.parseMcGeneric,           False, False, False, ),
     'IEM_MC_ADD_GREG_U8_TO_LOCAL':                               (McBlock.parseMcGeneric,           False, False, False, ),
-    'IEM_MC_ADD_LOCAL_S16_TO_EFF_ADDR':                          (McBlock.parseMcGeneric,           True,  True,  False, ),
-    'IEM_MC_ADD_LOCAL_S32_TO_EFF_ADDR':                          (McBlock.parseMcGeneric,           True,  True,  False, ),
-    'IEM_MC_ADD_LOCAL_S64_TO_EFF_ADDR':                          (McBlock.parseMcGeneric,           True,  True,  False, ),
+    'IEM_MC_ADD_LOCAL_S16_TO_EFF_ADDR':                          (McBlock.parseMcGeneric,           True,  True,  True,  ),
+    'IEM_MC_ADD_LOCAL_S32_TO_EFF_ADDR':                          (McBlock.parseMcGeneric,           True,  True,  True,  ),
+    'IEM_MC_ADD_LOCAL_S64_TO_EFF_ADDR':                          (McBlock.parseMcGeneric,           True,  True,  True,  ),
     'IEM_MC_ADVANCE_RIP_AND_FINISH':                             (McBlock.parseMcGeneric,           True,  True,  True,  ),
     'IEM_MC_AND_2LOCS_U32':                                      (McBlock.parseMcGeneric,           False, False, False, ),
-    'IEM_MC_AND_ARG_U16':                                        (McBlock.parseMcGeneric,           False, False, False, ),
-    'IEM_MC_AND_ARG_U32':                                        (McBlock.parseMcGeneric,           False, False, False, ),
-    'IEM_MC_AND_ARG_U64':                                        (McBlock.parseMcGeneric,           False, False, False, ),
+    'IEM_MC_AND_ARG_U16':                                        (McBlock.parseMcGeneric,           False, False, True,  ),
+    'IEM_MC_AND_ARG_U32':                                        (McBlock.parseMcGeneric,           False, False, True,  ),
+    'IEM_MC_AND_ARG_U64':                                        (McBlock.parseMcGeneric,           False, False, True,  ),
     'IEM_MC_AND_GREG_U16':                                       (McBlock.parseMcGeneric,           True,  True,  True,  ),
     'IEM_MC_AND_GREG_U32':                                       (McBlock.parseMcGeneric,           True,  True,  True,  ),
@@ -3291,7 +3291,7 @@
     'IEM_MC_REL_JMP_S8_AND_FINISH':                              (McBlock.parseMcGeneric,           True,  True,  False, ),
     'IEM_MC_RETURN_ON_FAILURE':                                  (McBlock.parseMcGeneric,           False, False, False, ),
-    'IEM_MC_SAR_LOCAL_S16':                                      (McBlock.parseMcGeneric,           False, False, False, ),
-    'IEM_MC_SAR_LOCAL_S32':                                      (McBlock.parseMcGeneric,           False, False, False, ),
-    'IEM_MC_SAR_LOCAL_S64':                                      (McBlock.parseMcGeneric,           False, False, False, ),
+    'IEM_MC_SAR_LOCAL_S16':                                      (McBlock.parseMcGeneric,           False, False, True,  ),
+    'IEM_MC_SAR_LOCAL_S32':                                      (McBlock.parseMcGeneric,           False, False, True,  ),
+    'IEM_MC_SAR_LOCAL_S64':                                      (McBlock.parseMcGeneric,           False, False, True,  ),
     'IEM_MC_SET_EFL_BIT':                                        (McBlock.parseMcGeneric,           True,  True,  False, ),
     'IEM_MC_SET_FPU_RESULT':                                     (McBlock.parseMcGeneric,           True,  True,  False, ),
@@ -3299,7 +3299,7 @@
     'IEM_MC_SET_RIP_U32_AND_FINISH':                             (McBlock.parseMcGeneric,           True,  True,  False, ),
     'IEM_MC_SET_RIP_U64_AND_FINISH':                             (McBlock.parseMcGeneric,           True,  True,  False, ),
-    'IEM_MC_SHL_LOCAL_S16':                                      (McBlock.parseMcGeneric,           False, False, False, ),
-    'IEM_MC_SHL_LOCAL_S32':                                      (McBlock.parseMcGeneric,           False, False, False, ),
-    'IEM_MC_SHL_LOCAL_S64':                                      (McBlock.parseMcGeneric,           False, False, False, ),
+    'IEM_MC_SHL_LOCAL_S16':                                      (McBlock.parseMcGeneric,           False, False, True,  ),
+    'IEM_MC_SHL_LOCAL_S32':                                      (McBlock.parseMcGeneric,           False, False, True,  ),
+    'IEM_MC_SHL_LOCAL_S64':                                      (McBlock.parseMcGeneric,           False, False, True,  ),
     'IEM_MC_SHR_LOCAL_U8':                                       (McBlock.parseMcGeneric,           False, False, False, ),
     'IEM_MC_SSE_UPDATE_MXCSR':                                   (McBlock.parseMcGeneric,           True,  True,  g_fNativeSimd),
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompFuncs.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompFuncs.h	(revision 104055)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompFuncs.h	(revision 104056)
@@ -2068,4 +2068,7 @@
     uint8_t const a_Name = iemNativeVarAllocConst(pReNative, sizeof(a_Type), (a_Value))
 
+#define IEM_MC_LOCAL_ASSIGN(a_Type, a_Name, a_Value) \
+    uint8_t const a_Name = iemNativeVarAllocAssign(pReNative, &off, sizeof(a_Type), (a_Value))
+
 
 /**
@@ -3561,5 +3564,5 @@
 
 /*********************************************************************************************************************************
-*   Local variable manipulation (add, sub, and, or).                                                                             *
+*   Local/Argument variable manipulation (add, sub, and, or).                                                                             *
 *********************************************************************************************************************************/
 
@@ -3575,4 +3578,14 @@
 #define IEM_MC_AND_LOCAL_U64(a_u64Local, a_u64Mask) \
     off = iemNativeEmitAndLocal(pReNative, off, a_u64Local, a_u64Mask, sizeof(uint64_t))
+
+
+#define IEM_MC_AND_ARG_U16(a_u16Arg, a_u16Mask) \
+    off = iemNativeEmitAndLocal(pReNative, off, a_u16Arg, a_u16Mask, sizeof(uint16_t))
+
+#define IEM_MC_AND_ARG_U32(a_u32Arg, a_u32Mask) \
+    off = iemNativeEmitAndLocal(pReNative, off, a_u32Arg, a_u32Mask, sizeof(uint32_t))
+
+#define IEM_MC_AND_ARG_U64(a_u64Arg, a_u64Mask) \
+    off = iemNativeEmitAndLocal(pReNative, off, a_u64Arg, a_u64Mask, sizeof(uint64_t))
 
 /** Emits code for AND'ing a local and a constant value.   */
@@ -3668,4 +3681,124 @@
     }
 
+    iemNativeVarRegisterRelease(pReNative, idxVar);
+    return off;
+}
+
+
+#define IEM_MC_SHL_LOCAL_S16(a_i16Local, a_cShift) \
+    off = iemNativeEmitShlLocal(pReNative, off, a_i16Local, sizeof(int16_t), a_cShift)
+
+#define IEM_MC_SHL_LOCAL_S32(a_i32Local, a_cShift) \
+    off = iemNativeEmitShlLocal(pReNative, off, a_i32Local, sizeof(int32_t), a_cShift)
+
+#define IEM_MC_SHL_LOCAL_S64(a_i64Local, a_cShift) \
+    off = iemNativeEmitShlLocal(pReNative, off, a_i64Local, sizeof(int64_t), a_cShift)
+
+/** Emits code for shifting left a local value.   */
+DECL_INLINE_THROW(uint32_t)
+iemNativeEmitShlLocal(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxVar, uint8_t cbLocal, uint8_t cShift)
+{
+#ifdef VBOX_STRICT
+    switch (cbLocal)
+    {
+        case sizeof(uint8_t):  Assert(cShift < 8); break;
+        case sizeof(uint16_t): Assert(cShift < 16); break;
+        case sizeof(uint32_t): Assert(cShift < 32); break;
+        case sizeof(uint64_t): Assert(cShift < 64); break;
+        default: AssertFailedBreak();
+    }
+#endif
+
+    uint8_t const idxVarReg = iemNativeVarRegisterAcquire(pReNative, idxVar, &off, true /*fInitialized*/);
+    IEMNATIVE_ASSERT_VAR_SIZE(pReNative, idxVar, cbLocal);
+
+    if (cbLocal <= sizeof(uint32_t))
+        off = iemNativeEmitShiftGpr32Left(pReNative, off, idxVarReg, cShift);
+    else
+        off = iemNativeEmitShiftGprLeft(pReNative, off, idxVarReg, cShift);
+
+    iemNativeVarRegisterRelease(pReNative, idxVar);
+    return off;
+}
+
+
+#define IEM_MC_SAR_LOCAL_S16(a_i16Local, a_cShift) \
+    off = iemNativeEmitSarLocal(pReNative, off, a_i16Local, sizeof(int16_t), a_cShift)
+
+#define IEM_MC_SAR_LOCAL_S32(a_i32Local, a_cShift) \
+    off = iemNativeEmitSarLocal(pReNative, off, a_i32Local, sizeof(int32_t), a_cShift)
+
+#define IEM_MC_SAR_LOCAL_S64(a_i64Local, a_cShift) \
+    off = iemNativeEmitSarLocal(pReNative, off, a_i64Local, sizeof(int64_t), a_cShift)
+
+/** Emits code for shifting left a local value.   */
+DECL_INLINE_THROW(uint32_t)
+iemNativeEmitSarLocal(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxVar, uint8_t cbLocal, uint8_t cShift)
+{
+#ifdef VBOX_STRICT
+    switch (cbLocal)
+    {
+        case sizeof(int8_t):  Assert(cShift < 8); break;
+        case sizeof(int16_t): Assert(cShift < 16); break;
+        case sizeof(int32_t): Assert(cShift < 32); break;
+        case sizeof(int64_t): Assert(cShift < 64); break;
+        default: AssertFailedBreak();
+    }
+#endif
+
+    uint8_t const idxVarReg = iemNativeVarRegisterAcquire(pReNative, idxVar, &off, true /*fInitialized*/);
+    IEMNATIVE_ASSERT_VAR_SIZE(pReNative, idxVar, cbLocal);
+
+    if (cbLocal <= sizeof(uint32_t))
+        off = iemNativeEmitArithShiftGpr32Right(pReNative, off, idxVarReg, cShift);
+    else
+        off = iemNativeEmitArithShiftGprRight(pReNative, off, idxVarReg, cShift);
+
+    iemNativeVarRegisterRelease(pReNative, idxVar);
+    return off;
+}
+
+
+#define IEM_MC_ADD_LOCAL_S16_TO_EFF_ADDR(a_EffAddr, a_i16) \
+    off = iemNativeEmitAddLocalToEffAddr(pReNative, off, a_EffAddr, a_i16, sizeof(int16_t))
+
+#define IEM_MC_ADD_LOCAL_S32_TO_EFF_ADDR(a_EffAddr, a_i32) \
+    off = iemNativeEmitAddLocalToEffAddr(pReNative, off, a_EffAddr, a_i32, sizeof(int32_t))
+
+#define IEM_MC_ADD_LOCAL_S64_TO_EFF_ADDR(a_EffAddr, a_i64) \
+    off = iemNativeEmitAddLocalToEffAddr(pReNative, off, a_EffAddr, a_i64, sizeof(int64_t))
+
+/** Emits code for IEM_MC_ADD_LOCAL_S16_TO_EFF_ADDR/IEM_MC_ADD_LOCAL_S32_TO_EFF_ADDR/IEM_MC_ADD_LOCAL_S64_TO_EFF_ADDR.   */
+DECL_INLINE_THROW(uint32_t)
+iemNativeEmitAddLocalToEffAddr(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t idxVarEffAddr, uint8_t idxVar, uint8_t cbLocal)
+{
+    IEMNATIVE_ASSERT_VAR_IDX(pReNative, idxVarEffAddr);
+    IEMNATIVE_ASSERT_VAR_SIZE(pReNative, idxVarEffAddr, sizeof(RTGCPTR));
+    IEMNATIVE_ASSERT_VAR_IDX(pReNative, idxVar);
+    IEMNATIVE_ASSERT_VAR_SIZE(pReNative, idxVar, cbLocal); RT_NOREF(cbLocal);
+
+    uint8_t const idxVarReg        = iemNativeVarRegisterAcquire(pReNative, idxVar, &off, true /*fInitialized*/);
+    uint8_t const idxVarRegEffAddr = iemNativeVarRegisterAcquire(pReNative, idxVarEffAddr, &off, true /*fInitialized*/);
+
+    /* Need to sign extend the value. */
+    if (cbLocal <= sizeof(uint32_t))
+    {
+        uint8_t const idxRegTmp = iemNativeRegAllocTmp(pReNative, &off, idxVar);
+
+        switch (cbLocal)
+        {
+            case sizeof(int8_t):  off = iemNativeEmitLoadGprSignExtendedFromGpr8(pReNative, off, idxRegTmp, idxVarReg); break;
+            case sizeof(int16_t): off = iemNativeEmitLoadGprSignExtendedFromGpr16(pReNative, off, idxRegTmp, idxVarReg); break;
+            case sizeof(int32_t): off = iemNativeEmitLoadGprSignExtendedFromGpr32(pReNative, off, idxRegTmp, idxVarReg); break;
+            default: AssertFailed();
+        }
+
+        off = iemNativeEmitAddTwoGprs(pReNative, off, idxVarRegEffAddr, idxRegTmp);
+        iemNativeRegFreeTmp(pReNative, idxRegTmp);
+    }
+    else
+        off = iemNativeEmitAddTwoGprs(pReNative, off, idxVarRegEffAddr, idxVarReg);
+
+    iemNativeVarRegisterRelease(pReNative, idxVarEffAddr);
     iemNativeVarRegisterRelease(pReNative, idxVar);
     return off;
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp	(revision 104055)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp	(revision 104056)
@@ -8197,4 +8197,28 @@
     }
     iemNativeVarSetKindToConst(pReNative, idxVar, uValue);
+    return idxVar;
+}
+
+
+DECL_HIDDEN_THROW(uint8_t)  iemNativeVarAllocAssign(PIEMRECOMPILERSTATE pReNative, uint32_t *poff, uint8_t cbType, uint8_t idxVarOther)
+{
+    uint8_t const idxVar = IEMNATIVE_VAR_IDX_PACK(iemNativeVarAllocInt(pReNative, cbType));
+    iemNativeVarSetKindToStack(pReNative, IEMNATIVE_VAR_IDX_PACK(idxVar));
+
+    uint8_t const idxVarOtherReg = iemNativeVarRegisterAcquire(pReNative, idxVarOther, poff, true /*fInitialized*/);
+    uint8_t const idxVarReg = iemNativeVarRegisterAcquire(pReNative, idxVar, poff);
+
+    *poff = iemNativeEmitLoadGprFromGpr(pReNative, *poff, idxVarReg, idxVarOtherReg);
+
+    /* Truncate the value to this variables size. */
+    switch (cbType)
+    {
+        case sizeof(uint8_t):   *poff = iemNativeEmitAndGpr32ByImm(pReNative, *poff, idxVarReg, UINT64_C(0xff)); break;
+        case sizeof(uint16_t):  *poff = iemNativeEmitAndGpr32ByImm(pReNative, *poff, idxVarReg, UINT64_C(0xffff)); break;
+        case sizeof(uint32_t):  *poff = iemNativeEmitAndGpr32ByImm(pReNative, *poff, idxVarReg, UINT64_C(0xffffffff)); break;
+    }
+
+    iemNativeVarRegisterRelease(pReNative, idxVarOther);
+    iemNativeVarRegisterRelease(pReNative, idxVar);
     return idxVar;
 }
Index: /trunk/src/VBox/VMM/include/IEMN8veRecompiler.h
===================================================================
--- /trunk/src/VBox/VMM/include/IEMN8veRecompiler.h	(revision 104055)
+++ /trunk/src/VBox/VMM/include/IEMN8veRecompiler.h	(revision 104056)
@@ -1617,4 +1617,5 @@
 DECL_HIDDEN_THROW(uint8_t)  iemNativeVarAlloc(PIEMRECOMPILERSTATE pReNative, uint8_t cbType);
 DECL_HIDDEN_THROW(uint8_t)  iemNativeVarAllocConst(PIEMRECOMPILERSTATE pReNative, uint8_t cbType, uint64_t uValue);
+DECL_HIDDEN_THROW(uint8_t)  iemNativeVarAllocAssign(PIEMRECOMPILERSTATE pReNative, uint32_t *poff, uint8_t cbType, uint8_t idxVarOther);
 DECL_HIDDEN_THROW(void)     iemNativeVarSetKindToStack(PIEMRECOMPILERSTATE pReNative, uint8_t idxVar);
 DECL_HIDDEN_THROW(void)     iemNativeVarSetKindToConst(PIEMRECOMPILERSTATE pReNative, uint8_t idxVar, uint64_t uValue);
Index: /trunk/src/VBox/VMM/include/IEMN8veRecompilerEmit.h
===================================================================
--- /trunk/src/VBox/VMM/include/IEMN8veRecompilerEmit.h	(revision 104055)
+++ /trunk/src/VBox/VMM/include/IEMN8veRecompilerEmit.h	(revision 104056)
@@ -5670,4 +5670,107 @@
 
 /**
+ * Emits code for (signed) shifting a GPR a fixed number of bits to the right.
+ */
+DECL_FORCE_INLINE(uint32_t)
+iemNativeEmitArithShiftGprRightEx(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGprDst, uint8_t cShift)
+{
+    Assert(cShift > 0 && cShift < 64);
+
+#if defined(RT_ARCH_AMD64)
+    /* sar dst, cShift */
+    pCodeBuf[off++] = iGprDst < 8 ? X86_OP_REX_W : X86_OP_REX_W | X86_OP_REX_B;
+    if (cShift != 1)
+    {
+        pCodeBuf[off++] = 0xc1;
+        pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 7, iGprDst & 7);
+        pCodeBuf[off++] = cShift;
+    }
+    else
+    {
+        pCodeBuf[off++] = 0xd1;
+        pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 7, iGprDst & 7);
+    }
+
+#elif defined(RT_ARCH_ARM64)
+    pCodeBuf[off++] = Armv8A64MkInstrAsrImm(iGprDst, iGprDst, cShift);
+
+#else
+# error "Port me"
+#endif
+    return off;
+}
+
+
+/**
+ * Emits code for (signed) shifting a GPR a fixed number of bits to the right.
+ */
+DECL_INLINE_THROW(uint32_t)
+iemNativeEmitArithShiftGprRight(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprDst, uint8_t cShift)
+{
+#if defined(RT_ARCH_AMD64)
+    off = iemNativeEmitArithShiftGprRightEx(iemNativeInstrBufEnsure(pReNative, off, 4), off, iGprDst, cShift);
+#elif defined(RT_ARCH_ARM64)
+    off = iemNativeEmitArithShiftGprRightEx(iemNativeInstrBufEnsure(pReNative, off, 1), off, iGprDst, cShift);
+#else
+# error "Port me"
+#endif
+    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
+    return off;
+}
+
+
+/**
+ * Emits code for (signed) shifting a 32-bit GPR a fixed number of bits to the right.
+ */
+DECL_FORCE_INLINE(uint32_t)
+iemNativeEmitArithShiftGpr32RightEx(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGprDst, uint8_t cShift)
+{
+    Assert(cShift > 0 && cShift < 64);
+
+#if defined(RT_ARCH_AMD64)
+    /* sar dst, cShift */
+    if (iGprDst >= 8)
+        pCodeBuf[off++] = X86_OP_REX_B;
+    if (cShift != 1)
+    {
+        pCodeBuf[off++] = 0xc1;
+        pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 7, iGprDst & 7);
+        pCodeBuf[off++] = cShift;
+    }
+    else
+    {
+        pCodeBuf[off++] = 0xd1;
+        pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, 7, iGprDst & 7);
+    }
+
+#elif defined(RT_ARCH_ARM64)
+    pCodeBuf[off++] = Armv8A64MkInstrAsrImm(iGprDst, iGprDst, cShift, false /*f64Bit*/);
+
+#else
+# error "Port me"
+#endif
+    return off;
+}
+
+
+/**
+ * Emits code for (signed) shifting a GPR a fixed number of bits to the right.
+ */
+DECL_INLINE_THROW(uint32_t)
+iemNativeEmitArithShiftGpr32Right(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprDst, uint8_t cShift)
+{
+#if defined(RT_ARCH_AMD64)
+    off = iemNativeEmitArithShiftGpr32RightEx(iemNativeInstrBufEnsure(pReNative, off, 4), off, iGprDst, cShift);
+#elif defined(RT_ARCH_ARM64)
+    off = iemNativeEmitArithShiftGpr32RightEx(iemNativeInstrBufEnsure(pReNative, off, 1), off, iGprDst, cShift);
+#else
+# error "Port me"
+#endif
+    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
+    return off;
+}
+
+
+/**
  * Emits code for rotating a GPR a fixed number of bits to the left.
  */
