Changeset 13561
- Timestamp:
- 10/24/08 18:27:26 (3 months ago)
- Files:
-
- trunk/include/VBox/em.h (modified) (1 diff)
- trunk/src/VBox/VMM/VMMAll/EMAll.cpp (modified) (4 diffs)
- trunk/src/VBox/VMM/VMMAll/EMAllA.asm (modified) (3 diffs)
- trunk/src/VBox/VMM/testcase/Makefile.kmk (modified) (5 diffs)
- trunk/src/VBox/VMM/testcase/tstInstrEmul.cpp (added)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/include/VBox/em.h
r13375 r13561 157 157 VMMDECL(uint32_t) EMEmulateCmpXchg(void *pvParam1, uint64_t *pu32Param2, uint64_t u32Param3, size_t cbSize); 158 158 VMMDECL(uint32_t) EMEmulateLockCmpXchg(void *pvParam1, uint64_t *pu64Param2, uint64_t u64Param3, size_t cbSize); 159 VMMDECL(uint32_t) EMEmulateCmpXchg8b 32(RTHCPTRpu32Param1, uint32_t *pEAX, uint32_t *pEDX, uint32_t uEBX, uint32_t uECX);160 VMMDECL(uint32_t) EMEmulateLockCmpXchg8b( RTHCPTRpu32Param1, uint32_t *pEAX, uint32_t *pEDX, uint32_t uEBX, uint32_t uECX);159 VMMDECL(uint32_t) EMEmulateCmpXchg8b(void *pu32Param1, uint32_t *pEAX, uint32_t *pEDX, uint32_t uEBX, uint32_t uECX); 160 VMMDECL(uint32_t) EMEmulateLockCmpXchg8b(void *pu32Param1, uint32_t *pEAX, uint32_t *pEDX, uint32_t uEBX, uint32_t uECX); 161 161 /** @} */ 162 162 trunk/src/VBox/VMM/VMMAll/EMAll.cpp
r13532 r13561 1482 1482 1483 1483 /* Update guest's eflags and finish. */ 1484 pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))1484 pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF)) 1485 1485 | (eflags & (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF)); 1486 1486 1487 1487 *pcbSize = param2.size; 1488 return VINF_SUCCESS; 1489 } 1490 1491 /* 1492 * [LOCK] CMPXCHG8B emulation. 1493 */ 1494 static int emInterpretCmpXchg8b(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize) 1495 { 1496 Assert(pCpu->mode != CPUMODE_64BIT); /** @todo check */ 1497 OP_PARAMVAL param1; 1498 1499 /* Source to make DISQueryParamVal read the register value - ugly hack */ 1500 int rc = DISQueryParamVal(pRegFrame, pCpu, &pCpu->param1, ¶m1, PARAM_SOURCE); 1501 if(VBOX_FAILURE(rc)) 1502 return VERR_EM_INTERPRETER; 1503 1504 RTGCPTR GCPtrPar1; 1505 void *pvParam1; 1506 uint64_t eflags; 1507 1508 AssertReturn(pCpu->param1.size == 8, VERR_EM_INTERPRETER); 1509 switch(param1.type) 1510 { 1511 case PARMTYPE_ADDRESS: 1512 GCPtrPar1 = param1.val.val64; 1513 GCPtrPar1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, GCPtrPar1); 1514 1515 rc = PGMPhysGCPtr2HCPtr(pVM, GCPtrPar1, &pvParam1); 1516 if (VBOX_FAILURE(rc)) 1517 { 1518 AssertRC(rc); 1519 return VERR_EM_INTERPRETER; 1520 } 1521 break; 1522 1523 default: 1524 return VERR_EM_INTERPRETER; 1525 } 1526 1527 LogFlow(("%s %VGv=%08x eax=%08x\n", emGetMnemonic(pCpu), pvParam1, pRegFrame->eax)); 1528 1529 if (pCpu->prefix & PREFIX_LOCK) 1530 eflags = EMEmulateLockCmpXchg8b(pvParam1, &pRegFrame->eax, &pRegFrame->edx, pRegFrame->ebx, pRegFrame->ecx); 1531 else 1532 eflags = EMEmulateCmpXchg8b(pvParam1, &pRegFrame->eax, &pRegFrame->edx, pRegFrame->ebx, pRegFrame->ecx); 1533 1534 LogFlow(("%s %VGv=%08x eax=%08x ZF=%d\n", emGetMnemonic(pCpu), pvParam1, pRegFrame->eax, !!(eflags & X86_EFL_ZF))); 1535 1536 /* Update guest's eflags and finish; note that *only* ZF is affected. */ 1537 pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_ZF)) 1538 | (eflags & (X86_EFL_ZF)); 1539 1540 *pcbSize = 8; 1488 1541 return VINF_SUCCESS; 1489 1542 } … … 2833 2886 && pCpu->pCurInstr->opcode != OP_OR 2834 2887 && pCpu->pCurInstr->opcode != OP_BTR 2888 && pCpu->pCurInstr->opcode != OP_CMPXCHG 2889 && pCpu->pCurInstr->opcode != OP_CMPXCHG8B 2835 2890 ) 2836 2891 ) … … 2930 2985 #ifdef IN_GC 2931 2986 INTERPRET_CASE(OP_STI,Sti); 2987 INTERPRET_CASE(OP_XADD, XAdd); 2988 #endif 2932 2989 INTERPRET_CASE(OP_CMPXCHG8B, CmpXchg8b); 2933 INTERPRET_CASE(OP_XADD, XAdd);2934 #endif2935 2990 INTERPRET_CASE(OP_HLT,Hlt); 2936 2991 INTERPRET_CASE(OP_IRET,Iret); … … 2938 2993 #ifdef VBOX_WITH_STATISTICS 2939 2994 #ifndef IN_GC 2940 INTERPRET_STAT_CASE(OP_CMPXCHG8B, CmpXchg8b);2941 2995 INTERPRET_STAT_CASE(OP_XADD, XAdd); 2942 2996 #endif trunk/src/VBox/VMM/VMMAll/EMAllA.asm
r12989 r13561 1026 1026 1027 1027 1028 %if 01029 ;; not tested!!1030 1031 1028 ;; 1032 1029 ; Emulate LOCK CMPXCHG8B instruction, CDECL calling conv. 1033 ; VMMDECL(uint32_t) EMEmulateLockCmpXchg8b( RTHCPTRpu32Param1, uint32_t *pEAX, uint32_t *pEDX, uint32_t uEBX, uint32_t uECX);1034 ; 1035 ; @returns EFLAGS after the operation, only arithmetic flags arevalid.1036 ; @param [esp + 04h] Param 1 - First parameter - pointer to first parameter1037 ; @param [esp + 08h] Param 2 - Address of the eax register1038 ; @param [esp + 0ch] Param 3 - Address of the edx register1039 ; @param [esp + 10h] Param 4 - EBX1040 ; @param [esp + 14h] Param 5 - ECX1030 ; VMMDECL(uint32_t) EMEmulateLockCmpXchg8b(void *pu32Param1, uint32_t *pEAX, uint32_t *pEDX, uint32_t uEBX, uint32_t uECX); 1031 ; 1032 ; @returns EFLAGS after the operation, only the ZF flag is valid. 1033 ; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to first parameter 1034 ; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - Address of the eax register 1035 ; @param [esp + 0ch] gcc:rdx msc:r8 Param 3 - Address of the edx register 1036 ; @param [esp + 10h] gcc:rcx msc:r9 Param 4 - EBX 1037 ; @param [esp + 14h] gcc:r8 msc:[rsp + 8] Param 5 - ECX 1041 1038 ; @uses eax, ecx, edx 1042 1039 ; 1043 1040 align 16 1044 1041 BEGINPROC EMEmulateLockCmpXchg8b 1045 push ebp 1046 push ebx 1042 push xBP 1043 push xBX 1044 %ifdef RT_ARCH_AMD64 1045 %ifdef RT_OS_WINDOWS 1046 mov rbp, rcx 1047 mov r10, rdx 1048 mov eax, dword [rdx] 1049 mov edx, dword [r8] 1050 mov rbx, r9 1051 mov ecx, [rsp + 28h + 16] 1052 %else 1053 mov rbp, rdi 1054 mov r10, rdx 1055 mov eax, dword [rsi] 1056 mov edx, dword [rdx] 1057 mov rbx, rcx 1058 mov rcx, r8 1059 %endif 1060 %else 1047 1061 mov ebp, [esp + 04h + 8] ; ebp = first parameter 1048 1062 mov eax, [esp + 08h + 8] ; &EAX … … 1052 1066 mov ebx, [esp + 10h + 8] ; EBX 1053 1067 mov ecx, [esp + 14h + 8] ; ECX 1054 1055 lock cmpxchg8b qword [ebp] ; do CMPXCHG8B 1068 %endif 1069 1070 lock cmpxchg8b qword [xBP] ; do CMPXCHG8B 1071 %ifdef RT_ARCH_AMD64 1072 %ifdef RT_OS_WINDOWS 1073 mov dword [r10], eax 1074 mov dword [r8], edx 1075 %else 1076 mov dword [rsi], eax 1077 mov dword [r10], edx 1078 %endif 1079 %else 1056 1080 mov ebx, dword [esp + 08h + 8] 1057 1081 mov dword [ebx], eax 1058 1082 mov ebx, dword [esp + 0ch + 8] 1059 1083 mov dword [ebx], edx 1060 1061 ; collect flags and return. 1062 pushf 1063 pop eax 1064 1065 pop ebx 1066 pop ebp 1067 retn 1068 1084 %endif 1085 ; collect flags and return. 1086 pushf 1087 pop MY_RET_REG 1088 1089 pop xBX 1090 pop xBP 1091 retn 1069 1092 ENDPROC EMEmulateLockCmpXchg8b 1070 1093 1071 1094 ;; 1072 1095 ; Emulate CMPXCHG8B instruction, CDECL calling conv. 1073 ; VMMDECL(uint32_t) EMEmulateCmpXchg8b( RTHCPTRpu32Param1, uint32_t *pEAX, uint32_t *pEDX, uint32_t uEBX, uint32_t uECX);1074 ; 1075 ; @returns EFLAGS after the operation, only arithmetic flags are valid. 1076 ; @param [esp + 04h] Param 1 - First parameter - pointer to first parameter1077 ; @param [esp + 08h] Param 2 - Address of the eax register1078 ; @param [esp + 0ch] Param 3 - Address of the edx register1079 ; @param [esp + 10h] Param 4 - EBX1080 ; @param [esp + 14h] Param 5 - ECX1096 ; VMMDECL(uint32_t) EMEmulateCmpXchg8b(void *pu32Param1, uint32_t *pEAX, uint32_t *pEDX, uint32_t uEBX, uint32_t uECX); 1097 ; 1098 ; @returns EFLAGS after the operation, only arithmetic flags are valid. 1099 ; @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - pointer to first parameter 1100 ; @param [esp + 08h] gcc:rsi msc:rdx Param 2 - Address of the eax register 1101 ; @param [esp + 0ch] gcc:rdx msc:r8 Param 3 - Address of the edx register 1102 ; @param [esp + 10h] gcc:rcx msc:r9 Param 4 - EBX 1103 ; @param [esp + 14h] gcc:r8 msc:[rsp + 8] Param 5 - ECX 1081 1104 ; @uses eax, ecx, edx 1082 1105 ; 1083 1106 align 16 1084 1107 BEGINPROC EMEmulateCmpXchg8b 1085 push ebp 1086 push ebx 1108 push xBP 1109 push xBX 1110 %ifdef RT_ARCH_AMD64 1111 %ifdef RT_OS_WINDOWS 1112 mov rbp, rcx 1113 mov r10, rdx 1114 mov eax, dword [rdx] 1115 mov edx, dword [r8] 1116 mov rbx, r9 1117 mov ecx, [rsp + 28h + 16] 1118 %else 1119 mov rbp, rdi 1120 mov r10, rdx 1121 mov eax, dword [rsi] 1122 mov edx, dword [rdx] 1123 mov rbx, rcx 1124 mov rcx, r8 1125 %endif 1126 %else 1087 1127 mov ebp, [esp + 04h + 8] ; ebp = first parameter 1088 1128 mov eax, [esp + 08h + 8] ; &EAX … … 1092 1132 mov ebx, [esp + 10h + 8] ; EBX 1093 1133 mov ecx, [esp + 14h + 8] ; ECX 1094 1095 cmpxchg8b qword [ebp] ; do CMPXCHG8B 1134 %endif 1135 1136 cmpxchg8b qword [xBP] ; do CMPXCHG8B 1137 1138 %ifdef RT_ARCH_AMD64 1139 %ifdef RT_OS_WINDOWS 1140 mov dword [r10], eax 1141 mov dword [r8], edx 1142 %else 1143 mov dword [rsi], eax 1144 mov dword [r10], edx 1145 %endif 1146 %else 1096 1147 mov ebx, dword [esp + 08h + 8] 1097 1148 mov dword [ebx], eax 1098 1149 mov ebx, dword [esp + 0ch + 8] 1099 1150 mov dword [ebx], edx 1100 1101 ; collect flags and return. 1102 pushf 1103 pop eax 1104 1105 pop ebx 1106 pop ebp 1151 %endif 1152 1153 ; collect flags and return. 1154 pushf 1155 pop MY_RET_REG 1156 1157 pop xBX 1158 pop xBP 1107 1159 retn 1108 1160 ENDPROC EMEmulateCmpXchg8b 1109 1161 1110 %endiftrunk/src/VBox/VMM/testcase/Makefile.kmk
r13375 r13561 26 26 # Target lists. 27 27 # 28 PROGRAMS += tstVMStructSize tstVMStructGC tstAsmStructs tstAsmStructsGC tstVMM tstVMM-HwAccm tstGlobalConfig 28 PROGRAMS += tstVMStructSize tstVMStructGC tstAsmStructs tstAsmStructsGC tstVMM tstVMM-HwAccm tstGlobalConfig tstInstrEmul 29 29 ifneq ($(KBUILD_TARGET),win) 30 30 PROGRAMS += tstVMMFork … … 54 54 OTHERS += \ 55 55 $(VBOX_VMM_TESTCASE_OUT_DIR)/tstAsmStructs.run \ 56 $(VBOX_VMM_TESTCASE_OUT_DIR)/tstVMStructSize.run 56 $(VBOX_VMM_TESTCASE_OUT_DIR)/tstVMStructSize.run \ 57 $(VBOX_VMM_TESTCASE_OUT_DIR)/tstInstrEmul.run 57 58 endif 58 59 endif … … 61 62 TESTING += \ 62 63 $(VBOX_VMM_TESTCASE_OUT_DIR)/tstAsmStructs.run \ 63 $(VBOX_VMM_TESTCASE_OUT_DIR)/tstVMStructSize.run 64 $(VBOX_VMM_TESTCASE_OUT_DIR)/tstVMStructSize.run \ 65 $(VBOX_VMM_TESTCASE_OUT_DIR)/tstInstrEmul.run 64 66 65 67 OTHER_CLEAN += \ 66 68 $(VBOX_VMM_TESTCASE_OUT_DIR)/tstAsmStructs.run \ 67 69 $(VBOX_VMM_TESTCASE_OUT_DIR)/tstVMStructSize.run \ 70 $(VBOX_VMM_TESTCASE_OUT_DIR)/tstInstrEmul.run \ 68 71 $(VBOX_VMM_TESTCASE_OUT_DIR)/tstAsmStructs.h \ 69 72 $(VBOX_VMM_TESTCASE_OUT_DIR)/tstAsmStructsAsm.o \ … … 135 138 tstSSM_SOURCES = tstSSM.cpp 136 139 tstSSM_LIBS = $(LIB_VMM) $(LIB_REM) $(LIB_RUNTIME) 140 141 tstInstrEmul_TEMPLATE = VBOXR3TSTEXE 142 tstInstrEmul_SOURCES = tstInstrEmul.cpp \ 143 ../VMMAll/EMAllA.asm 144 145 tstInstrEmul_LIBS = $(LIB_VMM) $(LIB_REM) $(LIB_RUNTIME) 137 146 138 147 tstCFGM_TEMPLATE = VBOXR3TSTEXE … … 321 330 run-struct-tests: $(VBOX_VMM_TESTCASE_OUT_DIR)/tstAsmStructs.run $(VBOX_VMM_TESTCASE_OUT_DIR)/tstVMStructSize.run 322 331 332 333 # 334 # Run rule for tstInstrEmul. 335 # 336 $(VBOX_VMM_TESTCASE_OUT_DIR)/tstInstrEmul.run: $$(INSTARGET_tstInstrEmul) 337 $(QUIET)$(RM) -f $@ 338 $(INSTARGET_tstInstrEmul) 339 $(QUIET)$(APPEND) "$@" "done"

