Index: trunk/src/VBox/VMM/EM.cpp
===================================================================
--- trunk/src/VBox/VMM/EM.cpp	(revision 7285)
+++ trunk/src/VBox/VMM/EM.cpp	(revision 7286)
@@ -201,4 +201,6 @@
     STAM_REG_USED(pVM, &pStats->StatGCCmpXchg,              STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/CmpXchg",   STAMUNIT_OCCURENCES,    "The number of times CMPXCHG was successfully interpreted.");
     STAM_REG_USED(pVM, &pStats->StatHCCmpXchg,              STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/CmpXchg",   STAMUNIT_OCCURENCES,    "The number of times CMPXCHG was successfully interpreted.");
+    STAM_REG_USED(pVM, &pStats->StatGCXAdd,                 STAMTYPE_COUNTER, "/EM/GC/Interpret/Success/XAdd",      STAMUNIT_OCCURENCES,    "The number of times XADD was successfully interpreted.");
+    STAM_REG_USED(pVM, &pStats->StatHCXAdd,                 STAMTYPE_COUNTER, "/EM/HC/Interpret/Success/XAdd",      STAMUNIT_OCCURENCES,    "The number of times XADD was successfully interpreted.");
 
     STAM_REG(pVM, &pStats->StatGCInterpretFailed,           STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed",            STAMUNIT_OCCURENCES,    "The number of times an instruction was not interpreted.");
@@ -260,4 +262,6 @@
     STAM_REG_USED(pVM, &pStats->StatGCFailedCmpXchg,        STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/CmpXchg",    STAMUNIT_OCCURENCES,    "The number of times CMPXCHG was not interpreted.");
     STAM_REG_USED(pVM, &pStats->StatHCFailedCmpXchg,        STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/CmpXchg",    STAMUNIT_OCCURENCES,    "The number of times CMPXCHG was not interpreted.");
+    STAM_REG_USED(pVM, &pStats->StatGCFailedXAdd,           STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/XAdd",       STAMUNIT_OCCURENCES,    "The number of times XADD was not interpreted.");
+    STAM_REG_USED(pVM, &pStats->StatHCFailedXAdd,           STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/XAdd",       STAMUNIT_OCCURENCES,    "The number of times XADD was not interpreted.");
     STAM_REG_USED(pVM, &pStats->StatGCFailedMovNTPS,        STAMTYPE_COUNTER, "/EM/GC/Interpret/Failed/MovNTPS",    STAMUNIT_OCCURENCES,    "The number of times MOVNTPS was not interpreted.");
     STAM_REG_USED(pVM, &pStats->StatHCFailedMovNTPS,        STAMTYPE_COUNTER, "/EM/HC/Interpret/Failed/MovNTPS",    STAMUNIT_OCCURENCES,    "The number of times MOVNTPS was not interpreted.");
Index: trunk/src/VBox/VMM/EMInternal.h
===================================================================
--- trunk/src/VBox/VMM/EMInternal.h	(revision 7285)
+++ trunk/src/VBox/VMM/EMInternal.h	(revision 7286)
@@ -131,4 +131,6 @@
     STAMCOUNTER             StatGCCmpXchg;
     STAMCOUNTER             StatHCCmpXchg;
+    STAMCOUNTER             StatGCXAdd;
+    STAMCOUNTER             StatHCXAdd;
     STAMCOUNTER             StatGCClts;
     STAMCOUNTER             StatHCClts;
@@ -190,4 +192,6 @@
     STAMCOUNTER             StatGCFailedCmpXchg;
     STAMCOUNTER             StatHCFailedCmpXchg;
+    STAMCOUNTER             StatGCFailedXAdd;
+    STAMCOUNTER             StatHCFailedXAdd;
     STAMCOUNTER             StatHCFailedMovNTPS;
     STAMCOUNTER             StatGCFailedMovNTPS;
Index: trunk/src/VBox/VMM/VMMAll/EMAll.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/EMAll.cpp	(revision 7285)
+++ trunk/src/VBox/VMM/VMMAll/EMAll.cpp	(revision 7286)
@@ -1237,4 +1237,7 @@
 }
 
+/*
+ * [LOCK] CMPXCHG emulation.
+ */
 #ifdef IN_GC
 static int emInterpretCmpXchg(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
@@ -1308,4 +1311,77 @@
 
             *pcbSize = param2.size;
+            return VINF_SUCCESS;
+        }
+    }
+    return VERR_EM_INTERPRETER;
+}
+#endif
+
+/*
+ * [LOCK] XADD emulation.
+ */
+#ifdef IN_GC
+static int emInterpretXAdd(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
+{
+    OP_PARAMVAL param1;
+    uint32_t *pParamReg2;
+    size_t cbSizeParamReg2;
+
+    /* Source to make DISQueryParamVal read the register value - ugly hack */
+    int rc = DISQueryParamVal(pRegFrame, pCpu, &pCpu->param1, &param1, PARAM_SOURCE);
+    if(VBOX_FAILURE(rc))
+        return VERR_EM_INTERPRETER;
+
+    rc = DISQueryParamRegPtr(pRegFrame, pCpu, &pCpu->param2, &pParamReg2, &cbSizeParamReg2);
+    if(VBOX_FAILURE(rc))
+        return VERR_EM_INTERPRETER;
+
+    if (TRPMHasTrap(pVM))
+    {
+        if (TRPMGetErrorCode(pVM) & X86_TRAP_PF_RW)
+        {
+            RTGCPTR pParam1;
+            uint32_t eflags;
+#ifdef VBOX_STRICT
+            uint32_t valpar1 = 0; /// @todo used uninitialized...
+#endif
+
+            AssertReturn(pCpu->param1.size == pCpu->param2.size, VERR_EM_INTERPRETER);
+            switch(param1.type)
+            {
+            case PARMTYPE_ADDRESS:
+                pParam1 = (RTGCPTR)param1.val.val32;
+                pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
+
+                /* Safety check (in theory it could cross a page boundary and fault there though) */
+                AssertMsgReturn(pParam1 == pvFault, ("eip=%VGv pParam1=%VGv pvFault=%VGv\n", pRegFrame->eip, pParam1, pvFault), VERR_EM_INTERPRETER);
+                break;
+
+            default:
+                return VERR_EM_INTERPRETER;
+            }
+
+            LogFlow(("XAdd %VGv=%08x reg=%08x\n", pParam1, *pParamReg2));
+
+            MMGCRamRegisterTrapHandler(pVM);
+            if (pCpu->prefix & PREFIX_LOCK)
+                rc = EMGCEmulateLockXAdd(pParam1, pParamReg2, cbSizeParamReg2, &eflags);
+            else
+                rc = EMGCEmulateXAdd(pParam1, pParamReg2, cbSizeParamReg2, &eflags);
+            MMGCRamDeregisterTrapHandler(pVM);
+
+            if (VBOX_FAILURE(rc))
+            {
+                Log(("XAdd %VGv=%08x reg=%08x -> emulation failed due to page fault!\n", pParam1, valpar1, pRegFrame->eax));
+                return VERR_EM_INTERPRETER;
+            }
+
+            LogFlow(("XAdd %VGv=%08x reg=%08x ZF=%d\n", pParam1, valpar1, pRegFrame->eax, !!(eflags & X86_EFL_ZF)));
+
+            /* Update guest's eflags and finish. */
+            pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
+                                  | (eflags                &  (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
+
+            *pcbSize = cbSizeParamReg2;
             return VINF_SUCCESS;
         }
@@ -1910,4 +1986,5 @@
         ||  (   (pCpu->prefix & PREFIX_LOCK)
              && pCpu->pCurInstr->opcode != OP_CMPXCHG
+             && pCpu->pCurInstr->opcode != OP_XADD
              && pCpu->pCurInstr->opcode != OP_OR
              && pCpu->pCurInstr->opcode != OP_BTR
@@ -1993,4 +2070,5 @@
         INTERPRET_CASE(OP_STI,Sti);
         INTERPRET_CASE(OP_CMPXCHG, CmpXchg);
+        INTERPRET_CASE(OP_XADD, XAdd);
 #endif
         INTERPRET_CASE(OP_HLT,Hlt);
@@ -1999,4 +2077,5 @@
 #ifndef IN_GC
         INTERPRET_STAT_CASE(OP_CMPXCHG,CmpXchg);
+        INTERPRET_STAT_CASE(OP_XADD, XAdd);
 #endif
         INTERPRET_STAT_CASE(OP_MOVNTPS,MovNTPS);
Index: trunk/src/VBox/VMM/VMMGC/EMGCA.asm
===================================================================
--- trunk/src/VBox/VMM/VMMGC/EMGCA.asm	(revision 7285)
+++ trunk/src/VBox/VMM/VMMGC/EMGCA.asm	(revision 7286)
@@ -26,5 +26,5 @@
 
 ;;
-; Emulate lock CMPXCHG instruction, CDECL calling conv.
+; Emulate LOCK CMPXCHG instruction, CDECL calling conv.
 ; EMGCDECL(uint32_t) EMGCEmulateLockCmpXchg(RTGCPTR pu32Param1, uint32_t *pu32Param2, uint32_t u32Param3, size_t cbSize, uint32_t *pEflags);
 ;
@@ -165,2 +165,133 @@
     ret
 ENDPROC     EMGCEmulateCmpXchg
+
+;;
+; Emulate LOCK XADD instruction, CDECL calling conv.
+; EMGCDECL(uint32_t) EMGCEmulateLockXAdd(RTGCPTR pu32Param1, uint32_t *pu32Param2, uint32_t u32Param3, size_t cbSize, uint32_t *pEflags);
+;
+; @returns eax=0 if data exchanged, other code - invalid access, #PF was generated.
+; @param    [esp + 04h]    Param 1 - First parameter - pointer to first parameter
+; @param    [esp + 08h]    Param 2 - Second parameter - pointer to second parameter (general register)
+; @param    [esp + 0ch]    Param 3 - Size of parameters, only 1/2/4 is valid.
+; @param    [esp + 10h]    Param 4 - Pointer to eflags (out)
+; @uses     eax, ecx, edx
+;
+align 16
+BEGINPROC   EMGCEmulateLockXAdd
+    push    ebx
+    mov     ecx, [esp + 04h + 4]        ; ecx = first parameter
+    mov     ebx, [esp + 08h + 4]        ; ebx = 2nd parameter
+    mov     eax, [esp + 0ch + 4]        ; eax = size of parameters
+
+    cmp     al, 4
+    je short .do_dword                  ; 4 bytes variant
+    cmp     al, 2
+    je short .do_word                   ; 2 byte variant
+    cmp     al, 1
+    je short .do_byte                   ; 1 bytes variant
+    int3
+
+.do_dword:
+    ; load 2nd parameter's value
+    mov     eax, dword [ebx]
+    lock xadd dword [ecx], eax              ; do 4 bytes XADD
+    mov     dword [ebx], eax
+    jmp     short .done
+
+.do_word:
+    ; load 2nd parameter's value
+    mov     eax, dword [ebx]
+    lock xadd word [ecx], ax                ; do 2 bytes XADD
+    mov     word [ebx], ax
+    jmp     short .done
+
+.do_byte:
+    ; load 2nd parameter's value
+    mov     eax, dword [ebx]
+    lock xadd byte [ecx], al                ; do 1 bytes XADD
+    mov     byte [ebx], al
+
+.done:
+    ; collect flags and return.
+    pushf
+    pop     eax
+
+    mov     edx, [esp + 10h + 4]            ; eflags pointer
+    mov     dword [edx], eax
+
+    pop     ebx
+    mov     eax, VINF_SUCCESS
+    retn
+
+; Read error - we will be here after our page fault handler.
+GLOBALNAME EMGCEmulateLockXAdd_Error
+    pop     ebx
+    mov     eax, VERR_ACCESS_DENIED
+    ret
+
+ENDPROC     EMGCEmulateLockXAdd
+
+;;
+; Emulate XADD instruction, CDECL calling conv.
+; EMGCDECL(uint32_t) EMGCEmulateXAdd(RTGCPTR pu32Param1, uint32_t *pu32Param2, uint32_t u32Param3, size_t cbSize, uint32_t *pEflags);
+;
+; @returns eax=0 if data written, other code - invalid access, #PF was generated.
+; @param    [esp + 04h]    Param 1 - First parameter - pointer to first parameter
+; @param    [esp + 08h]    Param 2 - Second parameter - pointer to second parameter (general register)
+; @param    [esp + 0ch]    Param 3 - Size of parameters, only 1/2/4 is valid.
+; @param    [esp + 10h]    Param 4 - Pointer to eflags (out)
+; @uses     eax, ecx, edx
+;
+align 16
+BEGINPROC   EMGCEmulateXAdd
+    push    ebx
+    mov     ecx, [esp + 04h + 4]        ; ecx = first parameter
+    mov     ebx, [esp + 08h + 4]        ; ebx = 2nd parameter (eax)
+    mov     eax, [esp + 0ch + 4]        ; eax = size of parameters
+
+    cmp     al, 4
+    je short .do_dword                  ; 4 bytes variant
+    cmp     al, 2
+    je short .do_word                   ; 2 byte variant
+    cmp     al, 1
+    je short .do_byte                   ; 1 bytes variant
+    int3
+
+.do_dword:
+    ; load 2nd parameter's value
+    mov     eax, dword [ebx]
+    xadd    dword [ecx], eax            ; do 4 bytes XADD
+    mov     dword [ebx], eax
+    jmp     short .done
+
+.do_word:
+    ; load 2nd parameter's value
+    mov     eax, dword [ebx]
+    xadd    word [ecx], ax              ; do 2 bytes XADD
+    mov     word [ebx], ax
+    jmp     short .done
+
+.do_byte:
+    ; load 2nd parameter's value
+    mov     eax, dword [ebx]
+    xadd    byte [ecx], al              ; do 1 bytes XADD
+    mov     byte [ebx], al
+
+.done:
+    ; collect flags and return.
+    pushf
+    pop     eax
+
+    mov     edx, [esp + 10h + 4]        ; eflags pointer
+    mov     dword [edx], eax
+
+    pop     ebx
+    mov     eax, VINF_SUCCESS
+    retn
+
+; Read error - we will be here after our page fault handler.
+GLOBALNAME EMGCEmulateXAdd_Error
+    pop     ebx
+    mov     eax, VERR_ACCESS_DENIED
+    ret
+ENDPROC     EMGCEmulateXAdd
Index: trunk/src/VBox/VMM/VMMGC/MMRamGC.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMGC/MMRamGC.cpp	(revision 7285)
+++ trunk/src/VBox/VMM/VMMGC/MMRamGC.cpp	(revision 7286)
@@ -45,4 +45,8 @@
 DECLASM(void) EMGCEmulateCmpXchg_EndProc(void);
 DECLASM(void) EMGCEmulateCmpXchg_Error(void);
+DECLASM(void) EMGCEmulateLockXAdd_EndProc(void);
+DECLASM(void) EMGCEmulateLockXAdd_Error(void);
+DECLASM(void) EMGCEmulateXAdd_EndProc(void);
+DECLASM(void) EMGCEmulateXAdd_Error(void);
 DECLASM(void) EMEmulateLockOr_EndProc(void);
 DECLASM(void) EMEmulateLockOr_Error(void);
@@ -184,4 +188,24 @@
 
     /*
+     * Page fault inside EMGCEmulateLockXAdd()? Resume at _Error.
+     */
+    if (    (uintptr_t)&EMGCEmulateLockXAdd < (uintptr_t)pRegFrame->eip
+        &&  (uintptr_t)pRegFrame->eip < (uintptr_t)&EMGCEmulateLockXAdd_EndProc)
+    {
+        pRegFrame->eip = (uintptr_t)&EMGCEmulateLockXAdd_Error;
+        return VINF_SUCCESS;
+    }
+
+    /*
+     * Page fault inside EMGCEmulateXAdd()? Resume at _Error.
+     */
+    if (    (uintptr_t)&EMGCEmulateXAdd < (uintptr_t)pRegFrame->eip
+        &&  (uintptr_t)pRegFrame->eip < (uintptr_t)&EMGCEmulateXAdd_EndProc)
+    {
+        pRegFrame->eip = (uintptr_t)&EMGCEmulateXAdd_Error;
+        return VINF_SUCCESS;
+    }
+
+    /*
      * Page fault inside EMEmulateLockOr()? Resume at *_Error.
      */
