Index: trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp	(revision 102784)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp	(revision 102785)
@@ -4985,8 +4985,26 @@
         case IEMMODE_32BIT:
         {
-            uint32_t u32Value;
-            rcStrict = iemMemStackPopU32Ex(pVCpu, &u32Value, &TmpRsp);
-            if (rcStrict == VINF_SUCCESS)
-                rcStrict = iemCImpl_LoadSRegWorker(pVCpu, iSegReg, (uint16_t)u32Value);
+            /* Modern Intel CPU only does a WORD sized access here, both as
+               segmentation and paging is concerned.  So, we have to emulate
+               this to make bs3-cpu-weird-1 happy. */
+            if (IEM_IS_GUEST_CPU_INTEL(pVCpu))
+            {
+                /* We don't have flexible enough stack primitives here, so just
+                   do a word pop and add two bytes to SP/RSP on success. */
+                uint16_t uSel;
+                rcStrict = iemMemStackPopU16Ex(pVCpu, &uSel, &TmpRsp);
+                if (rcStrict == VINF_SUCCESS)
+                {
+                    iemRegAddToRspEx(pVCpu, &TmpRsp, sizeof(uint32_t) - sizeof(uint16_t));
+                    rcStrict = iemCImpl_LoadSRegWorker(pVCpu, iSegReg, uSel);
+                }
+            }
+            else
+            {
+                uint32_t u32Value;
+                rcStrict = iemMemStackPopU32Ex(pVCpu, &u32Value, &TmpRsp);
+                if (rcStrict == VINF_SUCCESS)
+                    rcStrict = iemCImpl_LoadSRegWorker(pVCpu, iSegReg, (uint16_t)u32Value);
+            }
             break;
         }
@@ -4994,8 +5012,22 @@
         case IEMMODE_64BIT:
         {
-            uint64_t u64Value;
-            rcStrict = iemMemStackPopU64Ex(pVCpu, &u64Value, &TmpRsp);
-            if (rcStrict == VINF_SUCCESS)
-                rcStrict = iemCImpl_LoadSRegWorker(pVCpu, iSegReg, (uint16_t)u64Value);
+            /* Like for the 32-bit case above, intel only does a WORD access. */
+            if (IEM_IS_GUEST_CPU_INTEL(pVCpu))
+            {
+                uint16_t uSel;
+                rcStrict = iemMemStackPopU16Ex(pVCpu, &uSel, &TmpRsp);
+                if (rcStrict == VINF_SUCCESS)
+                {
+                    iemRegAddToRspEx(pVCpu, &TmpRsp, sizeof(uint64_t) - sizeof(uint16_t));
+                    rcStrict = iemCImpl_LoadSRegWorker(pVCpu, iSegReg, uSel);
+                }
+            }
+            else
+            {
+                uint64_t u64Value;
+                rcStrict = iemMemStackPopU64Ex(pVCpu, &u64Value, &TmpRsp);
+                if (rcStrict == VINF_SUCCESS)
+                    rcStrict = iemCImpl_LoadSRegWorker(pVCpu, iSegReg, (uint16_t)u64Value);
+            }
             break;
         }
Index: trunk/src/VBox/VMM/VMMAll/IEMAllMemRWTmpl.cpp.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllMemRWTmpl.cpp.h	(revision 102784)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllMemRWTmpl.cpp.h	(revision 102785)
@@ -489,21 +489,45 @@
 # endif
 
-    /* The intel docs talks about zero extending the selector register
-       value.  My actual intel CPU here might be zero extending the value
-       but it still only writes the lower word... */
-    /** @todo Test this on new HW and on AMD and in 64-bit mode.  Also test what
-     * happens when crossing an electric page boundrary, is the high word checked
-     * for write accessibility or not? Probably it is.  What about segment limits?
-     * It appears this behavior is also shared with trap error codes.
-     *
-     * Docs indicate the behavior changed maybe in Pentium or Pentium Pro. Check
-     * ancient hardware when it actually did change. */
-    uint8_t   bUnmapInfo;
-    uint16_t *puDst = (uint16_t *)iemMemMapJmp(pVCpu, &bUnmapInfo, sizeof(uint16_t), X86_SREG_SS, GCPtrMem,
-                                               IEM_ACCESS_STACK_W, sizeof(uint16_t) - 1); /** @todo 2 or 4 alignment check for PUSH SS? */
-    *puDst = (uint16_t)uValue;
-    iemMemCommitAndUnmapJmp(pVCpu, bUnmapInfo);
-
-    Log12(("IEM WR " TMPL_MEM_FMT_DESC " SS|%RGv: " TMPL_MEM_FMT_TYPE " [sreg]\n", GCPtrMem, uValue));
+    /* bs3-cpu-weird-1 explores this instruction. AMD 3990X does it by the book,
+      with a zero extended DWORD write.  While my Intel 10890XE goes all weird
+      in real mode where it will write a DWORD with the top word of EFLAGS in
+      the top half.  In all other modes it does a WORD access. */
+
+   /** @todo Docs indicate the behavior changed maybe in Pentium or Pentium Pro.
+    *  Check ancient hardware when it actually did change. */
+    uint8_t bUnmapInfo;
+    if (IEM_IS_GUEST_CPU_INTEL(pVCpu))
+    {
+        if (!IEM_IS_REAL_MODE(pVCpu))
+        {
+            /* WORD per intel specs. */
+            uint16_t *puDst = (uint16_t *)iemMemMapJmp(pVCpu, &bUnmapInfo, sizeof(uint16_t), X86_SREG_SS, GCPtrMem,
+                                                       IEM_ACCESS_STACK_W, sizeof(uint16_t) - 1); /** @todo 2 or 4 alignment check for PUSH SS? */
+            *puDst = (uint16_t)uValue;
+            iemMemCommitAndUnmapJmp(pVCpu, bUnmapInfo);
+            Log12(("IEM WR 'word' SS|%RGv: %#06x [sreg/i]\n", GCPtrMem, (uint16_t)uValue));
+        }
+        else
+        {
+            /* DWORD real mode weirness observed on 10980XE. */
+            /** @todo Check this on other intel CPUs and when pushing registers other
+             *        than FS (which all that bs3-cpu-weird-1 does atm).  (Maybe this is
+             *        something for the CPU profile... Hope not.) */
+            uint32_t *puDst = (uint32_t *)iemMemMapJmp(pVCpu, &bUnmapInfo, sizeof(uint32_t), X86_SREG_SS, GCPtrMem,
+                                                       IEM_ACCESS_STACK_W, sizeof(uint32_t) - 1);
+            *puDst = (uint16_t)uValue | (pVCpu->cpum.GstCtx.eflags.u & (UINT32_C(0xffff0000) & ~X86_EFL_RAZ_MASK));
+            iemMemCommitAndUnmapJmp(pVCpu, bUnmapInfo);
+             Log12(("IEM WR " TMPL_MEM_FMT_DESC " SS|%RGv: " TMPL_MEM_FMT_TYPE " [sreg/ir]\n", GCPtrMem, uValue));
+        }
+    }
+    else
+    {
+        /* DWORD per spec. */
+        uint32_t *puDst = (uint32_t *)iemMemMapJmp(pVCpu, &bUnmapInfo, sizeof(uint32_t), X86_SREG_SS, GCPtrMem,
+                                                   IEM_ACCESS_STACK_W, sizeof(uint32_t) - 1);
+        *puDst = uValue;
+        iemMemCommitAndUnmapJmp(pVCpu, bUnmapInfo);
+        Log12(("IEM WR " TMPL_MEM_FMT_DESC " SS|%RGv: " TMPL_MEM_FMT_TYPE " [sreg]\n", GCPtrMem, uValue));
+    }
 }
 #  endif /* TMPL_WITH_PUSH_SREG */
Index: trunk/src/VBox/VMM/VMMAll/IEMAllMemRWTmplInline.cpp.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllMemRWTmplInline.cpp.h	(revision 102784)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllMemRWTmplInline.cpp.h	(revision 102785)
@@ -1097,4 +1097,8 @@
 {
 #  if defined(IEM_WITH_DATA_TLB) && defined(IN_RING3) && !defined(TMPL_MEM_NO_INLINE)
+    /* See fallback for details on this weirdness: */
+    bool const    fIsIntel = IEM_IS_GUEST_CPU_INTEL(pVCpu);
+    uint8_t const cbAccess = fIsIntel && !IEM_IS_REAL_MODE(pVCpu) ? sizeof(uint16_t) : sizeof(TMPL_MEM_TYPE);
+
     /*
      * Decrement the stack pointer (prep), apply segmentation and check that
@@ -1103,8 +1107,10 @@
     uint64_t      uNewRsp;
     RTGCPTR const GCPtrTop = iemRegGetRspForPush(pVCpu, sizeof(TMPL_MEM_TYPE), &uNewRsp);
-    RTGCPTR const GCPtrEff = iemMemApplySegmentToWriteJmp(pVCpu, X86_SREG_SS, sizeof(TMPL_MEM_TYPE), GCPtrTop);
-#  if TMPL_MEM_TYPE_SIZE > 1
-    if (RT_LIKELY(   !(GCPtrEff & (sizeof(uint16_t) - 1U))
-                  || TMPL_MEM_CHECK_UNALIGNED_WITHIN_PAGE_OK(pVCpu, GCPtrEff, uint16_t) ))
+    RTGCPTR const GCPtrEff = iemMemApplySegmentToWriteJmp(pVCpu, X86_SREG_SS, cbAccess, GCPtrTop);
+#  if TMPL_MEM_TYPE_SIZE > 1
+    if (RT_LIKELY(   !(GCPtrEff & (cbAccess - 1U))
+                  || (   cbAccess == sizeof(uint16_t)
+                      ? TMPL_MEM_CHECK_UNALIGNED_WITHIN_PAGE_OK(pVCpu, GCPtrEff, uint16_t)
+                      : TMPL_MEM_CHECK_UNALIGNED_WITHIN_PAGE_OK(pVCpu, GCPtrEff, TMPL_MEM_TYPE) ) ))
 #  endif
     {
@@ -1133,7 +1139,25 @@
                 Assert(pTlbe->pbMappingR3); /* (Only ever cleared by the owning EMT.) */
                 Assert(!((uintptr_t)pTlbe->pbMappingR3 & GUEST_PAGE_OFFSET_MASK));
-                Log11Ex(LOG_GROUP_IEM_MEM,("IEM WR " TMPL_MEM_FMT_DESC " SS|%RGv (%RX64->%RX64): " TMPL_MEM_FMT_TYPE " [sreg]\n",
-                                           GCPtrEff, pVCpu->cpum.GstCtx.rsp, uNewRsp, uValue));
-                *(uint16_t *)&pTlbe->pbMappingR3[GCPtrEff & GUEST_PAGE_OFFSET_MASK] = (uint16_t)uValue;
+                if (cbAccess == sizeof(uint16_t))
+                {
+                    Log11Ex(LOG_GROUP_IEM_MEM,("IEM WR 'word' SS|%RGv (%RX64->%RX64): %#06x [sreg/i]\n",
+                                               GCPtrEff, pVCpu->cpum.GstCtx.rsp, uNewRsp, (uint16_t)uValue));
+                    *(uint16_t *)&pTlbe->pbMappingR3[GCPtrEff & GUEST_PAGE_OFFSET_MASK] = (uint16_t)uValue;
+                }
+                else
+                {
+                    TMPL_MEM_TYPE * const puSlot = (TMPL_MEM_TYPE *)&pTlbe->pbMappingR3[GCPtrEff & GUEST_PAGE_OFFSET_MASK];
+                    if (fIsIntel)
+                    {
+                        Assert(IEM_IS_REAL_MODE(pVCpu));
+                        uValue = (uint16_t)uValue | (pVCpu->cpum.GstCtx.eflags.u & (UINT32_C(0xffff0000) & ~X86_EFL_RAZ_MASK));
+                        Log11Ex(LOG_GROUP_IEM_MEM,("IEM WR " TMPL_MEM_FMT_DESC " SS|%RGv (%RX64->%RX64): " TMPL_MEM_FMT_TYPE " [sreg/ir]\n",
+                                                   GCPtrEff, pVCpu->cpum.GstCtx.rsp, uNewRsp, uValue));
+                    }
+                    else
+                        Log11Ex(LOG_GROUP_IEM_MEM,("IEM WR " TMPL_MEM_FMT_DESC " SS|%RGv (%RX64->%RX64): " TMPL_MEM_FMT_TYPE " [sreg]\n",
+                                                   GCPtrEff, pVCpu->cpum.GstCtx.rsp, uNewRsp, uValue));
+                    *puSlot = uValue;
+                }
                 pVCpu->cpum.GstCtx.rsp = uNewRsp;
                 return;
@@ -1287,10 +1311,16 @@
 {
 #  if defined(IEM_WITH_DATA_TLB) && defined(IN_RING3) && !defined(TMPL_MEM_NO_INLINE)
+    /* See fallback for details on this weirdness: */
+    bool const    fIsIntel = IEM_IS_GUEST_CPU_INTEL(pVCpu);
+    uint8_t const cbAccess = fIsIntel && !IEM_IS_REAL_MODE(pVCpu) ? sizeof(uint16_t) : sizeof(TMPL_MEM_TYPE);
+
     /*
      * Calculate the new stack pointer and check that the item doesn't cross a page boundrary.
      */
     uint32_t const uNewEsp = pVCpu->cpum.GstCtx.esp - sizeof(TMPL_MEM_TYPE);
-    if (RT_LIKELY(   !(uNewEsp & (sizeof(uint16_t) - 1))
-                  || TMPL_MEM_CHECK_UNALIGNED_WITHIN_PAGE_OK(pVCpu, uNewEsp, uint16_t) ))
+    if (RT_LIKELY(   !(uNewEsp & (cbAccess - 1))
+                  || (cbAccess == sizeof(uint16_t)
+                      ? TMPL_MEM_CHECK_UNALIGNED_WITHIN_PAGE_OK(pVCpu, uNewEsp, uint16_t)
+                      : TMPL_MEM_CHECK_UNALIGNED_WITHIN_PAGE_OK(pVCpu, uNewEsp, TMPL_MEM_TYPE))  ))
     {
         /*
@@ -1318,7 +1348,25 @@
                 Assert(pTlbe->pbMappingR3); /* (Only ever cleared by the owning EMT.) */
                 Assert(!((uintptr_t)pTlbe->pbMappingR3 & GUEST_PAGE_OFFSET_MASK));
-                Log11Ex(LOG_GROUP_IEM_MEM,("IEM WR " TMPL_MEM_FMT_DESC " SS|%RX32 (<-%RX32): " TMPL_MEM_FMT_TYPE " [sreg]\n",
-                                           uNewEsp, pVCpu->cpum.GstCtx.esp, uValue));
-                *(uint16_t *)&pTlbe->pbMappingR3[uNewEsp & GUEST_PAGE_OFFSET_MASK] = (uint16_t)uValue;
+                if (cbAccess == sizeof(uint16_t))
+                {
+                    Log11Ex(LOG_GROUP_IEM_MEM,("IEM WR 'word' SS|%RX32 (<-%RX32): %#06x [sreg/i]\n",
+                                               uNewEsp, pVCpu->cpum.GstCtx.esp, (uint16_t)uValue));
+                    *(uint16_t *)&pTlbe->pbMappingR3[uNewEsp & GUEST_PAGE_OFFSET_MASK] = (uint16_t)uValue;
+                }
+                else
+                {
+                    TMPL_MEM_TYPE * const puSlot = (TMPL_MEM_TYPE *)&pTlbe->pbMappingR3[uNewEsp & GUEST_PAGE_OFFSET_MASK];
+                    if (fIsIntel)
+                    {
+                        Assert(IEM_IS_REAL_MODE(pVCpu));
+                        uValue = (uint16_t)uValue | (pVCpu->cpum.GstCtx.eflags.u & (UINT32_C(0xffff0000) & ~X86_EFL_RAZ_MASK));
+                        Log11Ex(LOG_GROUP_IEM_MEM,("IEM WR " TMPL_MEM_FMT_DESC " SS|%RX32 (<-RX32): " TMPL_MEM_FMT_TYPE " [sreg/ir]\n",
+                                                   uNewEsp, pVCpu->cpum.GstCtx.esp, uValue));
+                    }
+                    else
+                        Log11Ex(LOG_GROUP_IEM_MEM,("IEM WR " TMPL_MEM_FMT_DESC " SS|%RX32 (<-RX32): " TMPL_MEM_FMT_TYPE " [sreg]\n",
+                                                   uNewEsp, pVCpu->cpum.GstCtx.esp, uValue));
+                    *puSlot = uValue;
+                }
                 pVCpu->cpum.GstCtx.rsp = uNewEsp;
                 return;
Index: trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp	(revision 102784)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllN8veRecompiler.cpp	(revision 102785)
@@ -2589,4 +2589,7 @@
         pReNative->cDbgInfoAlloc  = _16K;
 #endif
+
+        /* Other constant stuff: */
+        pReNative->pVCpu          = pVCpu;
 
         /*
@@ -11578,6 +11581,9 @@
      */
     uint8_t const cbMem       = RT_BYTE1(cBitsVarAndFlat) / 8;
+    bool const    fIsSegReg   = RT_BYTE3(cBitsVarAndFlat) != 0;
+    bool const    fIsIntelSeg = fIsSegReg && IEM_IS_GUEST_CPU_INTEL(pReNative->pVCpu);
+    uint8_t const cbMemAccess = !fIsIntelSeg || (pReNative->fExec & IEM_F_MODE_MASK) == IEM_F_MODE_X86_16BIT
+                              ? cbMem : sizeof(uint16_t);
     uint8_t const cBitsFlat   = RT_BYTE2(cBitsVarAndFlat);      RT_NOREF(cBitsFlat);
-    bool const    fIsSegReg   = RT_BYTE3(cBitsVarAndFlat) != 0; RT_NOREF(fIsSegReg);
     uint8_t const idxRegRsp   = iemNativeRegAllocTmpForGuestReg(pReNative, &off, IEMNATIVEGSTREG_GPR(X86_GREG_xSP),
                                                                 kIemNativeGstRegUse_ForUpdate, true /*fNoVolatileRegs*/);
@@ -11627,5 +11633,5 @@
      */
     uint8_t const  iSegReg           = cBitsFlat != 0 ? UINT8_MAX : X86_SREG_SS;
-    IEMNATIVEEMITTLBSTATE const TlbState(pReNative, idxRegEffSp, &off, iSegReg, cbMem);
+    IEMNATIVEEMITTLBSTATE const TlbState(pReNative, idxRegEffSp, &off, iSegReg, cbMemAccess);
     uint16_t const uTlbSeqNo         = pReNative->uTlbSeqNo++;
     uint32_t const idxLabelTlbMiss   = iemNativeLabelCreate(pReNative, kIemNativeLabelType_TlbMiss, UINT32_MAX, uTlbSeqNo);
@@ -11733,5 +11739,5 @@
          * TlbLookup:
          */
-        off = iemNativeEmitTlbLookup(pReNative, off, &TlbState, iSegReg, cbMem, cbMem - 1, IEM_ACCESS_TYPE_WRITE,
+        off = iemNativeEmitTlbLookup(pReNative, off, &TlbState, iSegReg, cbMemAccess, cbMemAccess - 1, IEM_ACCESS_TYPE_WRITE,
                                      idxLabelTlbLookup, idxLabelTlbMiss, idxRegMemResult);
 
@@ -11742,5 +11748,5 @@
         if (idxRegValue != UINT8_MAX)
         {
-            switch (cbMem)
+            switch (cbMemAccess)
             {
                 case 2:
@@ -11748,8 +11754,37 @@
                     break;
                 case 4:
-                    if (!fIsSegReg)
+                    if (!fIsIntelSeg)
                         off = iemNativeEmitStoreGpr32ByGprEx(pCodeBuf, off, idxRegValue, idxRegMemResult);
                     else
-                        off = iemNativeEmitStoreGpr16ByGprEx(pCodeBuf, off, idxRegValue, idxRegMemResult);
+                    {
+                        /* intel real mode segment push. 10890XE adds the 2nd of half EFLAGS to a
+                           PUSH FS in real mode, so we have to try emulate that here.
+                           We borrow the now unused idxReg1 from the TLB lookup code here. */
+                        uint8_t idxRegEfl = iemNativeRegAllocTmpForGuestRegIfAlreadyPresent(pReNative, &off,
+                                                                                            kIemNativeGstReg_EFlags);
+                        if (idxRegEfl != UINT8_MAX)
+                        {
+#ifdef ARCH_AMD64
+                            off = iemNativeEmitLoadGprFromGpr32(pReNative, off, TlbState.idxReg1, idxRegEfl);
+                            off = iemNativeEmitAndGpr32ByImm(pReNative, off, TlbState.idxReg1,
+                                                             UINT32_C(0xffff0000) & ~X86_EFL_RAZ_MASK);
+#else
+                            off = iemNativeEmitGpr32EqGprAndImmEx(iemNativeInstrBufEnsure(pReNative, off, 3),
+                                                                  off, TlbState.idxReg1, idxRegEfl,
+                                                                  UINT32_C(0xffff0000) & ~X86_EFL_RAZ_MASK);
+#endif
+                            iemNativeRegFreeTmp(pReNative, idxRegEfl);
+                        }
+                        else
+                        {
+                            off = iemNativeEmitLoadGprFromVCpuU32(pReNative, off, TlbState.idxReg1,
+                                                                  RT_UOFFSETOF(VMCPUCC, cpum.GstCtx.eflags));
+                            off = iemNativeEmitAndGpr32ByImm(pReNative, off, TlbState.idxReg1,
+                                                             UINT32_C(0xffff0000) & ~X86_EFL_RAZ_MASK);
+                        }
+                        /* ASSUMES the upper half of idxRegValue is ZERO. */
+                        off = iemNativeEmitOrGpr32ByGpr(pReNative, off, TlbState.idxReg1, idxRegValue);
+                        off = iemNativeEmitStoreGpr32ByGprEx(pCodeBuf, off, TlbState.idxReg1, idxRegMemResult);
+                    }
                     break;
                 case 8:
@@ -11762,5 +11797,5 @@
         else
         {
-            switch (cbMem)
+            switch (cbMemAccess)
             {
                 case 2:
@@ -11854,5 +11889,5 @@
                == (  cBitsVarAndFlat == RT_MAKE_U32_FROM_U8(16, 32, 0, 0) ? (uintptr_t)iemNativeHlpStackFlat32PopGRegU16
                    : cBitsVarAndFlat == RT_MAKE_U32_FROM_U8(32, 32, 0, 0) ? (uintptr_t)iemNativeHlpStackFlat32PopGRegU32
-                   : cBitsVarAndFlat == RT_MAKE_U32_FROM_U8(64, 16, 0, 0) ? (uintptr_t)iemNativeHlpStackFlat64PopGRegU16
+                   : cBitsVarAndFlat == RT_MAKE_U32_FROM_U8(16, 64, 0, 0) ? (uintptr_t)iemNativeHlpStackFlat64PopGRegU16
                    : cBitsVarAndFlat == RT_MAKE_U32_FROM_U8(64, 64, 0, 0) ? (uintptr_t)iemNativeHlpStackFlat64PopGRegU64
                    : UINT64_C(0xc000b000a0009000) ));
Index: trunk/src/VBox/VMM/include/IEMN8veRecompiler.h
===================================================================
--- trunk/src/VBox/VMM/include/IEMN8veRecompiler.h	(revision 102784)
+++ trunk/src/VBox/VMM/include/IEMN8veRecompiler.h	(revision 102785)
@@ -683,4 +683,6 @@
     /** The translation block being recompiled. */
     PCIEMTB                     pTbOrg;
+    /** The VMCPU structure of the EMT. */
+    PVMCPUCC                    pVCpu;
 
     /** Condition sequence number (for generating unique labels). */
Index: trunk/src/VBox/VMM/include/IEMN8veRecompilerEmit.h
===================================================================
--- trunk/src/VBox/VMM/include/IEMN8veRecompilerEmit.h	(revision 102784)
+++ trunk/src/VBox/VMM/include/IEMN8veRecompilerEmit.h	(revision 102785)
@@ -3912,5 +3912,5 @@
  * Emits code for OR'ing two 64-bit GPRs.
  */
-DECL_INLINE_THROW(uint32_t)
+DECL_FORCE_INLINE(uint32_t)
 iemNativeEmitOrGprByGprEx(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGprDst, uint8_t iGprSrc)
 {
@@ -3927,4 +3927,47 @@
 # error "Port me"
 #endif
+    return off;
+}
+
+
+/**
+ * Emits code for OR'ing two 32-bit GPRs.
+ * @note Bits 63:32 of the destination GPR will be cleared.
+ */
+DECL_FORCE_INLINE(uint32_t)
+iemNativeEmitOrGpr32ByGprEx(PIEMNATIVEINSTR pCodeBuf, uint32_t off, uint8_t iGprDst, uint8_t iGprSrc)
+{
+#if defined(RT_ARCH_AMD64)
+    /* or Gv, Ev */
+    if (iGprDst >= 8 || iGprSrc >= 8)
+        pCodeBuf[off++] = (iGprDst < 8 ? 0 : X86_OP_REX_R) | (iGprSrc < 8 ? 0 : X86_OP_REX_B);
+    pCodeBuf[off++] = 0x0b;
+    pCodeBuf[off++] = X86_MODRM_MAKE(X86_MOD_REG, iGprDst & 7, iGprSrc & 7);
+
+#elif defined(RT_ARCH_ARM64)
+    pCodeBuf[off++] = Armv8A64MkInstrOrr(iGprDst, iGprDst, iGprSrc, false /*f64Bit*/);
+
+#else
+# error "Port me"
+#endif
+    return off;
+}
+
+
+/**
+ * Emits code for OR'ing two 32-bit GPRs.
+ * @note Bits 63:32 of the destination GPR will be cleared.
+ */
+DECL_INLINE_THROW(uint32_t)
+iemNativeEmitOrGpr32ByGpr(PIEMRECOMPILERSTATE pReNative, uint32_t off, uint8_t iGprDst, uint8_t iGprSrc)
+{
+#if defined(RT_ARCH_AMD64)
+    off = iemNativeEmitOrGpr32ByGprEx(iemNativeInstrBufEnsure(pReNative, off, 3), off, iGprDst, iGprSrc);
+#elif defined(RT_ARCH_ARM64)
+    off = iemNativeEmitOrGpr32ByGprEx(iemNativeInstrBufEnsure(pReNative, off, 1), off, iGprDst, iGprSrc);
+#else
+# error "Port me"
+#endif
+    IEMNATIVE_ASSERT_INSTR_BUF_ENSURE(pReNative, off);
     return off;
 }
