Index: trunk/src/VBox/VMM/VMMAll/EMAll.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/EMAll.cpp	(revision 1938)
+++ trunk/src/VBox/VMM/VMMAll/EMAll.cpp	(revision 1939)
@@ -54,4 +54,6 @@
 DECLINLINE(int) emInterpretInstructionCPU(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize);
 
+/* Enable to allow segment prefix support */
+#define EM_ALLOW_SEG_PREFIX
 
 /**
@@ -107,5 +109,5 @@
 inline int emDisCoreOne(PVM pVM, DISCPUSTATE *pCpu, RTGCUINTPTR InstrGC, uint32_t *pOpsize)
 {
-    return DISCoreOneEx(InstrGC, pCpu->mode, EMReadBytes, pVM, pCpu, pOpsize);
+    return DISCoreOneEx(InstrGC, pCpu->mode, EMReadBytes, pVM, pCpu,  pOpsize);
 }
 
@@ -282,5 +284,5 @@
 
 
-inline int emRamRead(PVM pVM, void *pDest, RTGCPTR GCSrc, uint32_t cb)
+inline int emRamRead(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, void *pDest, RTGCPTR GCSrc, uint32_t cb)
 {
 #ifdef IN_GC
@@ -300,5 +302,5 @@
 }
 
-inline int emRamWrite(PVM pVM, RTGCPTR GCDest, void *pSrc, uint32_t cb)
+inline int emRamWrite(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, RTGCPTR GCDest, void *pSrc, uint32_t cb)
 {
 #ifdef IN_GC
@@ -317,4 +319,20 @@
 }
 
+/* Convert sel:addr to a flat GC address */
+static RTGCPTR emConvertToFlatAddr(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, POP_PARAMETER pParam, RTGCPTR pvAddr)
+{
+#ifdef EM_ALLOW_SEG_PREFIX
+    int   prefix_seg;
+    RTSEL sel = 0;
+    CPUMSELREGHID *pSelHidReg;
+    
+    prefix_seg = DISDetectSegReg(pCpu, pParam);
+    DISFetchRegSegEx(pRegFrame, prefix_seg, &sel, &pSelHidReg);
+    return SELMToFlat(pVM, pRegFrame->eflags, sel, pSelHidReg, pvAddr);
+#else
+    return pvAddr;
+#endif
+}
+
 /**
  * XCHG instruction emulation.
@@ -351,9 +369,10 @@
             case PARMTYPE_ADDRESS:
                 pParam1 = (RTGCPTR)param1.val.val32;
+                pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
 #ifdef IN_GC
                 /* Safety check (in theory it could cross a page boundary and fault there though) */
-                AssertReturn(pParam1 == (RTGCPTR)pvFault, VERR_EM_INTERPRETER);
-#endif
-                rc = emRamRead(pVM, &valpar1, pParam1, param1.size);
+                AssertReturn(pParam1 == pvFault, VERR_EM_INTERPRETER);
+#endif
+                rc = emRamRead(pVM, pRegFrame, pCpu, &valpar1, pParam1, param1.size);
                 if (VBOX_FAILURE(rc))
                 {
@@ -372,9 +391,10 @@
             case PARMTYPE_ADDRESS:
                 pParam2 = (RTGCPTR)param2.val.val32;
+                pParam2 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param2, pParam2);
 #ifdef IN_GC
                 /* Safety check (in theory it could cross a page boundary and fault there though) */
-                AssertReturn(pParam2 == (RTGCPTR)pvFault, VERR_EM_INTERPRETER);
-#endif
-                rc = emRamRead(pVM, &valpar2, pParam2, param2.size);
+                AssertReturn(pParam2 == pvFault, VERR_EM_INTERPRETER);
+#endif
+                rc = emRamRead(pVM, pRegFrame, pCpu,  &valpar2, pParam2, param2.size);
                 if (VBOX_FAILURE(rc))
                 {
@@ -409,5 +429,5 @@
             else
             {
-                rc = emRamWrite(pVM, pParam1, &valpar2, param1.size);
+                rc = emRamWrite(pVM, pRegFrame, pCpu, pParam1, &valpar2, param1.size);
                 if (VBOX_FAILURE(rc))
                 {
@@ -434,5 +454,5 @@
             else
             {
-                rc = emRamWrite(pVM, pParam2, &valpar1, param2.size);
+                rc = emRamWrite(pVM, pRegFrame, pCpu, pParam2, &valpar1, param2.size);
                 if (VBOX_FAILURE(rc))
                 {
@@ -475,9 +495,10 @@
             {
                 pParam1 = (RTGCPTR)param1.val.val32;
+                pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
 #ifdef IN_GC
                 /* Safety check (in theory it could cross a page boundary and fault there though) */
-                AssertReturn(pParam1 == (RTGCPTR)pvFault, VERR_EM_INTERPRETER);
-#endif
-                rc = emRamRead(pVM, &valpar1, pParam1, param1.size);
+                AssertReturn(pParam1 == pvFault, VERR_EM_INTERPRETER);
+#endif
+                rc = emRamRead(pVM, pRegFrame, pCpu,  &valpar1, pParam1, param1.size);
                 if (VBOX_FAILURE(rc))
                 {
@@ -500,5 +521,5 @@
 
             /* Write result back */
-            rc = emRamWrite(pVM, pParam1, &valpar1, param1.size);
+            rc = emRamWrite(pVM, pRegFrame, pCpu, pParam1, &valpar1, param1.size);
             if (VBOX_FAILURE(rc))
             {
@@ -550,5 +571,5 @@
                 return VERR_EM_INTERPRETER;
 
-            rc = emRamRead(pVM, &valpar1, pStackVal, param1.size);
+            rc = emRamRead(pVM, pRegFrame, pCpu,  &valpar1, pStackVal, param1.size);
             if (VBOX_FAILURE(rc))
             {
@@ -568,10 +589,12 @@
                    )
                    pParam1 = (RTGCPTR)((RTGCUINTPTR)pParam1 + param1.size);
+
+                pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
                 
 #ifdef IN_GC
                 /* Safety check (in theory it could cross a page boundary and fault there though) */
-                AssertMsgReturn(pParam1 == (RTGCPTR)pvFault, ("%VGv != %VGv\n", pParam1, pvFault), VERR_EM_INTERPRETER);
-#endif
-                rc = emRamWrite(pVM, pParam1, &valpar1, param1.size);
+                AssertMsgReturn(pParam1 == pvFault || (RTGCPTR)pRegFrame->esp == pvFault, ("%VGv != %VGv ss:esp=%04X:%VGv\n", pParam1, pvFault, pRegFrame->ss, pRegFrame->esp), VERR_EM_INTERPRETER);
+#endif
+                rc = emRamWrite(pVM, pRegFrame, pCpu, pParam1, &valpar1, param1.size);
                 if (VBOX_FAILURE(rc))
                 {
@@ -640,10 +663,11 @@
             {
                 pParam1 = (RTGCPTR)param1.val.val32;
+                pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
 
 #ifdef IN_GC
                 /* Safety check (in theory it could cross a page boundary and fault there though) */
-                AssertReturn(pParam1 == (RTGCPTR)pvFault, VERR_EM_INTERPRETER);
-#endif
-                rc = emRamRead(pVM, &valpar1, pParam1, param1.size);
+                AssertReturn(pParam1 == pvFault, VERR_EM_INTERPRETER);
+#endif
+                rc = emRamRead(pVM, pRegFrame, pCpu,  &valpar1, pParam1, param1.size);
                 if (VBOX_FAILURE(rc))
                 {
@@ -678,5 +702,5 @@
 
             /* And write it back */
-            rc = emRamWrite(pVM, pParam1, &valpar1, param1.size);
+            rc = emRamWrite(pVM, pRegFrame, pCpu, pParam1, &valpar1, param1.size);
             if (VBOX_SUCCESS(rc))
             {
@@ -731,10 +755,11 @@
             {
                 pParam1 = (RTGCPTR)param1.val.val32;
+                pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
 
 #ifdef IN_GC
                 /* Safety check (in theory it could cross a page boundary and fault there though) */
-                AssertReturn(pParam1 == (RTGCPTR)pvFault, VERR_EM_INTERPRETER);
-#endif
-                rc = emRamRead(pVM, &valpar1, pParam1, param1.size);
+                AssertReturn(pParam1 == pvFault, VERR_EM_INTERPRETER);
+#endif
+                rc = emRamRead(pVM, pRegFrame, pCpu,  &valpar1, pParam1, param1.size);
                 if (VBOX_FAILURE(rc))
                 {
@@ -769,5 +794,5 @@
 
             /* And write it back */
-            rc = emRamWrite(pVM, pParam1, &valpar1, param1.size);
+            rc = emRamWrite(pVM, pRegFrame, pCpu, pParam1, &valpar1, param1.size);
             if (VBOX_SUCCESS(rc))
             {
@@ -822,4 +847,5 @@
             {
                 pParam1 = (RTGCPTR)param1.val.val32;
+                pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
 
 #ifdef IN_GC
@@ -827,5 +853,5 @@
                 AssertMsgReturn(pParam1 == pvFault, ("pParam1 = %VGv pvFault = %VGv\n", pParam1, pvFault), VERR_EM_INTERPRETER);
 #endif
-                rc = emRamRead(pVM, &valpar1, pParam1, param1.size);
+                rc = emRamRead(pVM, pRegFrame, pCpu,  &valpar1, pParam1, param1.size);
                 if (VBOX_FAILURE(rc))
                 {
@@ -862,5 +888,5 @@
 
             /* And write it back */
-            rc = emRamWrite(pVM, pParam1, &valpar1, param1.size);
+            rc = emRamWrite(pVM, pRegFrame, pCpu, pParam1, &valpar1, param1.size);
             if (VBOX_SUCCESS(rc))
             {
@@ -915,10 +941,11 @@
             {
                 pParam1 = (RTGCPTR)param1.val.val32;
+                pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
 
 #ifdef IN_GC
                 /* Safety check (in theory it could cross a page boundary and fault there though) */
-                AssertReturn(pParam1 == (RTGCPTR)pvFault, VERR_EM_INTERPRETER);
-#endif
-                rc = emRamRead(pVM, &valpar1, pParam1, param1.size);
+                AssertReturn(pParam1 == pvFault, VERR_EM_INTERPRETER);
+#endif
+                rc = emRamRead(pVM, pRegFrame, pCpu,  &valpar1, pParam1, param1.size);
                 if (VBOX_FAILURE(rc))
                 {
@@ -955,5 +982,5 @@
 
             /* And write it back */
-            rc = emRamWrite(pVM, pParam1, &valpar1, param1.size);
+            rc = emRamWrite(pVM, pRegFrame, pCpu, pParam1, &valpar1, param1.size);
             if (VBOX_SUCCESS(rc))
             {
@@ -1009,10 +1036,11 @@
             {
                 pParam1 = (RTGCPTR)param1.val.val32;
+                pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
 
 #ifdef IN_GC
                 /* Safety check (in theory it could cross a page boundary and fault there though) */
-                AssertReturn(pParam1 == (RTGCPTR)pvFault, VERR_EM_INTERPRETER);
-#endif
-                rc = emRamRead(pVM, &valpar1, pParam1, param1.size);
+                AssertReturn(pParam1 == pvFault, VERR_EM_INTERPRETER);
+#endif
+                rc = emRamRead(pVM, pRegFrame, pCpu, &valpar1, pParam1, param1.size);
                 if (VBOX_FAILURE(rc))
                 {
@@ -1054,5 +1082,5 @@
 
             /* And write it back */
-            rc = emRamWrite(pVM, pParam1, &valpar1, param1.size);
+            rc = emRamWrite(pVM, pRegFrame, pCpu, pParam1, &valpar1, param1.size);
             if (VBOX_SUCCESS(rc))
             {
@@ -1107,10 +1135,11 @@
             {
                 pParam1 = (RTGCPTR)param1.val.val32;
+                pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
 
 #ifdef IN_GC
                 /* Safety check (in theory it could cross a page boundary and fault there though) */
-                AssertReturn(pParam1 == (RTGCPTR)pvFault, VERR_EM_INTERPRETER);
-#endif
-                rc = emRamRead(pVM, &valpar1, pParam1, param1.size);
+                AssertReturn(pParam1 == pvFault, VERR_EM_INTERPRETER);
+#endif
+                rc = emRamRead(pVM, pRegFrame, pCpu, &valpar1, pParam1, param1.size);
                 if (VBOX_FAILURE(rc))
                 {
@@ -1147,5 +1176,5 @@
 
             /* And write it back */
-            rc = emRamWrite(pVM, pParam1, &valpar1, param1.size);
+            rc = emRamWrite(pVM, pRegFrame, pCpu, pParam1, &valpar1, param1.size);
             if (VBOX_SUCCESS(rc))
             {
@@ -1197,4 +1226,5 @@
             case PARMTYPE_ADDRESS:
                 pDest = (RTGCPTR)param1.val.val32;
+                pDest = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pDest);
                 break;
 
@@ -1218,5 +1248,9 @@
             Assert(param2.size <= 4 && param2.size > 0);
 
-            rc = emRamWrite(pVM, pDest, &val32, param2.size);
+#ifdef IN_GC
+            /* Safety check (in theory it could cross a page boundary and fault there though) */
+            AssertReturn(pDest == pvFault, VERR_EM_INTERPRETER);
+#endif
+            rc = emRamWrite(pVM, pRegFrame, pCpu, pDest, &val32, param2.size);
             if (VBOX_FAILURE(rc))
                 return VERR_EM_INTERPRETER;
@@ -1239,4 +1273,5 @@
             case PARMTYPE_ADDRESS:
                 pSrc = (RTGCPTR)param2.val.val32;
+                pSrc = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param2, pSrc);
                 break;
 
@@ -1246,5 +1281,9 @@
 
             Assert(param1.size <= 4 && param1.size > 0);
-            rc = emRamRead(pVM, &val32, pSrc, param1.size);
+#ifdef IN_GC
+            /* Safety check (in theory it could cross a page boundary and fault there though) */
+            AssertReturn(pSrc == pvFault, VERR_EM_INTERPRETER);
+#endif
+            rc = emRamRead(pVM, pRegFrame, pCpu, &val32, pSrc, param1.size);
             if (VBOX_FAILURE(rc))
                 return VERR_EM_INTERPRETER;
@@ -1293,16 +1332,16 @@
     int         rc;
 
-    rc  = emRamRead(pVM, &eip,      (RTGCPTR)pIretStack    , 4);
-    rc |= emRamRead(pVM, &cs,       (RTGCPTR)(pIretStack + 4), 4);
-    rc |= emRamRead(pVM, &eflags,   (RTGCPTR)(pIretStack + 8), 4);
+    rc  = emRamRead(pVM, NULL, NULL, &eip,      (RTGCPTR)pIretStack      , 4);
+    rc |= emRamRead(pVM, NULL, NULL, &cs,       (RTGCPTR)(pIretStack + 4), 4);
+    rc |= emRamRead(pVM, NULL, NULL, &eflags,   (RTGCPTR)(pIretStack + 8), 4);
     AssertRCReturn(rc, VERR_EM_INTERPRETER);
     AssertReturn(eflags & X86_EFL_VM, VERR_EM_INTERPRETER);
 
-    rc |= emRamRead(pVM, &esp,      (RTGCPTR)(pIretStack + 12), 4);
-    rc |= emRamRead(pVM, &ss,       (RTGCPTR)(pIretStack + 16), 4);
-    rc |= emRamRead(pVM, &es,       (RTGCPTR)(pIretStack + 20), 4);
-    rc |= emRamRead(pVM, &ds,       (RTGCPTR)(pIretStack + 24), 4);
-    rc |= emRamRead(pVM, &fs,       (RTGCPTR)(pIretStack + 28), 4);
-    rc |= emRamRead(pVM, &gs,       (RTGCPTR)(pIretStack + 32), 4);
+    rc |= emRamRead(pVM, NULL, NULL, &esp,      (RTGCPTR)(pIretStack + 12), 4);
+    rc |= emRamRead(pVM, NULL, NULL, &ss,       (RTGCPTR)(pIretStack + 16), 4);
+    rc |= emRamRead(pVM, NULL, NULL, &es,       (RTGCPTR)(pIretStack + 20), 4);
+    rc |= emRamRead(pVM, NULL, NULL, &ds,       (RTGCPTR)(pIretStack + 24), 4);
+    rc |= emRamRead(pVM, NULL, NULL, &fs,       (RTGCPTR)(pIretStack + 28), 4);
+    rc |= emRamRead(pVM, NULL, NULL, &gs,       (RTGCPTR)(pIretStack + 32), 4);
     AssertRCReturn(rc, VERR_EM_INTERPRETER);
 
@@ -1853,11 +1892,13 @@
     }
 
+#ifdef EM_ALLOW_SEG_PREFIX
+    if (pCpu->prefix & (PREFIX_REPNE | PREFIX_REP | PREFIX_LOCK))
+#else
     /* Out emulation above can't cope with 16 bits code yet. */
     if (!SELMIsSelector32Bit(pVM, pRegFrame->eflags, pRegFrame->cs, &pRegFrame->csHid))
         return VERR_EM_INTERPRETER;
 
-    /** @note we could ignore PREFIX_LOCK here. Need to take special precautions when/if we support SMP in the guest.
-     */
     if (pCpu->prefix & (PREFIX_REPNE | PREFIX_REP | PREFIX_SEG | PREFIX_LOCK))
+#endif
     {
         //Log(("EMInterpretInstruction: wrong prefix!!\n"));
