VirtualBox

Changeset 2000 in vbox for trunk


Ignore:
Timestamp:
Apr 10, 2007 8:02:14 AM (18 years ago)
Author:
vboxsync
Message:

Cleaned up instruction emulation. Got rid of duplicate code.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/EMAll.cpp

    r1999 r2000  
    4747#include <iprt/string.h>
    4848
     49/*******************************************************************************
     50*   Structures and Typedefs                                                    *
     51*******************************************************************************/
     52typedef EMDECL(uint32_t) PFN_EMULATE_PARAM2(uint32_t *pu32Param1, uint32_t val2);
     53typedef EMDECL(uint32_t) PFN_EMULATE_PARAM3(uint32_t *pu32Param1, uint32_t val2, uint32_t val3);
    4954
    5055/*******************************************************************************
     
    478483 * INC and DEC emulation.
    479484 */
    480 static int emInterpretIncDec(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
     485static int emInterpretIncDec(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize,
     486                             PFN_EMULATE_PARAM2 pfnEmulate)
    481487{
    482488    OP_PARAMVAL param1;
     
    518524            uint32_t eflags;
    519525
    520             if (pCpu->pCurInstr->opcode == OP_DEC)
    521                 eflags = EMEmulateDec(&valpar1, param1.size);
    522             else
    523                 eflags = EMEmulateInc(&valpar1, param1.size);
     526            eflags = pfnEmulate(&valpar1, param1.size);
    524527
    525528            /* Write result back */
     
    627630}
    628631
    629 /**
    630  * OR Emulation.
    631  */
    632 static int emInterpretOr(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
     632
     633/**
     634 * XOR/OR/AND Emulation.
     635 */
     636static int emInterpretOrXorAnd(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize,
     637                               PFN_EMULATE_PARAM3 pfnEmulate)
    633638{
    634639    OP_PARAMVAL param1, param2;
     
    641646        return VERR_EM_INTERPRETER;
    642647
     648#ifdef DEBUG
     649    char *pszInstr;
     650
     651    if (pCpu->pCurInstr->opcode == OP_XOR)
     652        pszInstr = "Xor";
     653    else
     654    if (pCpu->pCurInstr->opcode == OP_OR)
     655        pszInstr = "Or";
     656    else
     657    if (pCpu->pCurInstr->opcode == OP_AND)
     658        pszInstr = "And";
     659#endif
     660
    643661#ifdef IN_GC
    644662    if (TRPMHasTrap(pVM))
     
    654672                if (pCpu->param1.size < pCpu->param2.size)
    655673                {
    656                     AssertMsgFailed(("Or at %VGv parameter mismatch %d vs %d!!\n", pRegFrame->eip, pCpu->param1.size, pCpu->param2.size)); /* should never happen! */
     674                    AssertMsgFailed(("%s at %VGv parameter mismatch %d vs %d!!\n", pszInstr, pRegFrame->eip, pCpu->param1.size, pCpu->param2.size)); /* should never happen! */
    657675                    return VERR_EM_INTERPRETER;
    658676                }
     
    697715            }
    698716
    699             /* Data read, emulate OR. */
    700             uint32_t eflags = EMEmulateOr(&valpar1, valpar2, param2.size);
     717            /* Data read, emulate instruction. */
     718            uint32_t eflags = pfnEmulate(&valpar1, valpar2, param2.size);
    701719
    702720            /* Update guest's eflags and finish. */
    703721            pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
    704                                   | (eflags & (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
     722                                  | (eflags                & (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
    705723
    706724            /* And write it back */
     
    719737}
    720738
    721 /**
    722  * XOR Emulation.
    723  */
    724 static int emInterpretXor(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
     739
     740/**
     741 * ADD, ADC & SUB Emulation.
     742 */
     743static int emInterpretAddSub(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize,
     744                             PFN_EMULATE_PARAM3 pfnEmulate)
    725745{
    726746    OP_PARAMVAL param1, param2;
     
    733753        return VERR_EM_INTERPRETER;
    734754
     755#ifdef DEBUG
     756    char *pszInstr;
     757
     758    if (pCpu->pCurInstr->opcode == OP_SUB)
     759        pszInstr = "Sub";
     760    else
     761    if (pCpu->pCurInstr->opcode == OP_ADD)
     762        pszInstr = "Add";
     763    else
     764    if (pCpu->pCurInstr->opcode == OP_ADC)
     765        pszInstr = "Adc";
     766#endif
     767
    735768#ifdef IN_GC
    736769    if (TRPMHasTrap(pVM))
     
    746779                if (pCpu->param1.size < pCpu->param2.size)
    747780                {
    748                     AssertMsgFailed(("Xor at %VGv parameter mismatch %d vs %d!!\n", pRegFrame->eip, pCpu->param1.size, pCpu->param2.size)); /* should never happen! */
     781                    AssertMsgFailed(("%s at %VGv parameter mismatch %d vs %d!!\n", pszInstr, pRegFrame->eip, pCpu->param1.size, pCpu->param2.size)); /* should never happen! */
    749782                    return VERR_EM_INTERPRETER;
    750783                }
     
    773806            else
    774807            {
     808#ifndef DEBUG_bird
    775809                AssertFailed();
     810#endif
    776811                return VERR_EM_INTERPRETER;
    777812            }
     
    789824            }
    790825
    791             /* Data read, emulate XOR. */
    792             uint32_t eflags = EMEmulateXor(&valpar1, valpar2, param2.size);
     826            /* Data read, emulate instruction. */
     827            uint32_t eflags = pfnEmulate(&valpar1, valpar2, param2.size);
    793828
    794829            /* Update guest's eflags and finish. */
     
    812847
    813848/**
    814  * AND Emulation.
    815  */
    816 static int emInterpretAnd(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
     849 * ADC Emulation.
     850 */
     851static int emInterpretAdc(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
     852{
     853    if (pRegFrame->eflags.Bits.u1CF)
     854        return emInterpretAddSub(pVM, pCpu, pRegFrame, pvFault, pcbSize, EMEmulateAdcWithCarrySet);
     855    else
     856        return emInterpretAddSub(pVM, pCpu, pRegFrame, pvFault, pcbSize, EMEmulateAdd);
     857}
     858
     859/**
     860 * BTR/C/S Emulation.
     861 */
     862static int emInterpretBitTest(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize,
     863                              PFN_EMULATE_PARAM2 pfnEmulate)
    817864{
    818865    OP_PARAMVAL param1, param2;
     
    825872        return VERR_EM_INTERPRETER;
    826873
     874#ifdef DEBUG
     875    char *pszInstr;
     876
     877    if (pCpu->pCurInstr->opcode == OP_BTR)
     878        pszInstr = "Btr";
     879    else
     880    if (pCpu->pCurInstr->opcode == OP_BTS)
     881        pszInstr = "Bts";
     882    else
     883    if (pCpu->pCurInstr->opcode == OP_BTC)
     884        pszInstr = "Btc";
     885#endif
     886
    827887#ifdef IN_GC
    828888    if (TRPMHasTrap(pVM))
     
    832892#endif
    833893            RTGCPTR  pParam1;
    834             uint32_t valpar1, valpar2;
    835 
    836             if (pCpu->param1.size != pCpu->param2.size)
    837             {
    838                 if (pCpu->param1.size < pCpu->param2.size)
    839                 {
    840                     AssertMsgFailed(("And at %VGv parameter mismatch %d vs %d!!\n", pRegFrame->eip, pCpu->param1.size, pCpu->param2.size)); /* should never happen! */
    841                     return VERR_EM_INTERPRETER;
    842                 }
    843                 /* Or %Ev, Ib -> just a hack to save some space; the data width of the 1st parameter determines the real width */
    844                 pCpu->param2.size = pCpu->param1.size;
    845                 param2.size     = param1.size;
    846             }
     894            uint32_t valpar1 = 0, valpar2;
     895            uint32_t eflags;
    847896
    848897            /* The destination is always a virtual address */
    849             if (param1.type == PARMTYPE_ADDRESS)
    850             {
    851                 pParam1 = (RTGCPTR)param1.val.val32;
    852                 pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
    853 
    854 #ifdef IN_GC
    855                 /* Safety check (in theory it could cross a page boundary and fault there though) */
    856                 AssertMsgReturn(pParam1 == pvFault, ("pParam1 = %VGv pvFault = %VGv\n", pParam1, pvFault), VERR_EM_INTERPRETER);
    857 #endif
    858                 rc = emRamRead(pVM,  &valpar1, pParam1, param1.size);
    859                 if (VBOX_FAILURE(rc))
    860                 {
    861                     AssertMsgFailed(("emRamRead %VGv size=%d failed with %Vrc\n", pParam1, param1.size, rc));
    862                     return VERR_EM_INTERPRETER;
    863                 }
    864             }
    865             else
    866             {
    867 #ifndef DEBUG_bird
    868                 AssertFailed();
    869 #endif
    870                 return VERR_EM_INTERPRETER;
    871             }
     898            if (param1.type != PARMTYPE_ADDRESS)
     899                return VERR_EM_INTERPRETER;
     900
     901            pParam1 = (RTGCPTR)param1.val.val32;
     902            pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
    872903
    873904            /* Register or immediate data */
     
    883914            }
    884915
    885             /* Data read, emulate AND. */
    886             uint32_t eflags = EMEmulateAnd(&valpar1, valpar2, param2.size);
    887 
    888             /* Update guest's eflags and finish. */
    889             pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
    890                                   | (eflags                &  (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
    891 
    892             /* And write it back */
    893             rc = emRamWrite(pVM, pParam1, &valpar1, param1.size);
    894             if (VBOX_SUCCESS(rc))
    895             {
    896                 /* All done! */
    897                 *pcbSize = param2.size;
    898                 return VINF_SUCCESS;
    899             }
    900 #ifdef IN_GC
    901         }
    902     }
    903 #endif
    904     return VERR_EM_INTERPRETER;
    905 }
    906 
    907 /**
    908  * ADD Emulation.
    909  */
    910 static int emInterpretAdd(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    911 {
    912     OP_PARAMVAL param1, param2;
    913     int rc = DISQueryParamVal(pRegFrame, pCpu, &pCpu->param1, &param1, PARAM_DEST);
    914     if(VBOX_FAILURE(rc))
    915         return VERR_EM_INTERPRETER;
    916 
    917     rc = DISQueryParamVal(pRegFrame, pCpu, &pCpu->param2, &param2, PARAM_SOURCE);
    918     if(VBOX_FAILURE(rc))
    919         return VERR_EM_INTERPRETER;
    920 
    921 #ifdef IN_GC
    922     if (TRPMHasTrap(pVM))
    923     {
    924         if (TRPMGetErrorCode(pVM) & X86_TRAP_PF_RW)
    925         {
    926 #endif
    927             RTGCPTR  pParam1;
    928             uint32_t valpar1, valpar2;
    929 
    930             if (pCpu->param1.size != pCpu->param2.size)
    931             {
    932                 if (pCpu->param1.size < pCpu->param2.size)
    933                 {
    934                     AssertMsgFailed(("Add at %VGv parameter mismatch %d vs %d!!\n", pRegFrame->eip, pCpu->param1.size, pCpu->param2.size)); /* should never happen! */
    935                     return VERR_EM_INTERPRETER;
    936                 }
    937                 /* Or %Ev, Ib -> just a hack to save some space; the data width of the 1st parameter determines the real width */
    938                 pCpu->param2.size = pCpu->param1.size;
    939                 param2.size     = param1.size;
    940             }
    941 
    942             /* The destination is always a virtual address */
    943             if (param1.type == PARMTYPE_ADDRESS)
    944             {
    945                 pParam1 = (RTGCPTR)param1.val.val32;
    946                 pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
    947 
    948 #ifdef IN_GC
    949                 /* Safety check (in theory it could cross a page boundary and fault there though) */
    950                 AssertReturn(pParam1 == pvFault, VERR_EM_INTERPRETER);
    951 #endif
    952                 rc = emRamRead(pVM,  &valpar1, pParam1, param1.size);
    953                 if (VBOX_FAILURE(rc))
    954                 {
    955                     AssertMsgFailed(("emRamRead %VGv size=%d failed with %Vrc\n", pParam1, param1.size, rc));
    956                     return VERR_EM_INTERPRETER;
    957                 }
    958             }
    959             else
    960             {
    961 #ifndef DEBUG_bird
    962                 AssertFailed();
    963 #endif
    964                 return VERR_EM_INTERPRETER;
    965             }
    966 
    967             /* Register or immediate data */
    968             switch(param2.type)
    969             {
    970             case PARMTYPE_IMMEDIATE:    /* both immediate data and register (ugly) */
    971                 valpar2 = param2.val.val32;
    972                 break;
    973 
    974             default:
    975                 AssertFailed();
    976                 return VERR_EM_INTERPRETER;
    977             }
    978 
    979             /* Data read, emulate ADD. */
    980             uint32_t eflags = EMEmulateAdd(&valpar1, valpar2, param2.size);
    981 
    982             /* Update guest's eflags and finish. */
    983             pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
    984                                   | (eflags                &  (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
    985 
    986             /* And write it back */
    987             rc = emRamWrite(pVM, pParam1, &valpar1, param1.size);
    988             if (VBOX_SUCCESS(rc))
    989             {
    990                 /* All done! */
    991                 *pcbSize = param2.size;
    992                 return VINF_SUCCESS;
    993             }
    994 #ifdef IN_GC
    995         }
    996     }
    997 #endif
    998     return VERR_EM_INTERPRETER;
    999 }
    1000 
    1001 /**
    1002  * ADC Emulation.
    1003  * @todo combine with add
    1004  */
    1005 static int emInterpretAdc(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    1006 {
    1007     OP_PARAMVAL param1, param2;
    1008     int rc = DISQueryParamVal(pRegFrame, pCpu, &pCpu->param1, &param1, PARAM_DEST);
    1009     if(VBOX_FAILURE(rc))
    1010         return VERR_EM_INTERPRETER;
    1011 
    1012     rc = DISQueryParamVal(pRegFrame, pCpu, &pCpu->param2, &param2, PARAM_SOURCE);
    1013     if(VBOX_FAILURE(rc))
    1014         return VERR_EM_INTERPRETER;
    1015 
    1016 #ifdef IN_GC
    1017     if (TRPMHasTrap(pVM))
    1018     {
    1019         if (TRPMGetErrorCode(pVM) & X86_TRAP_PF_RW)
    1020         {
    1021 #endif
    1022             RTGCPTR  pParam1;
    1023             uint32_t valpar1, valpar2;
    1024 
    1025             if (pCpu->param1.size != pCpu->param2.size)
    1026             {
    1027                 if (pCpu->param1.size < pCpu->param2.size)
    1028                 {
    1029                     AssertMsgFailed(("Adc at %VGv parameter mismatch %d vs %d!!\n", pRegFrame->eip, pCpu->param1.size, pCpu->param2.size)); /* should never happen! */
    1030                     return VERR_EM_INTERPRETER;
    1031                 }
    1032                 /* Or %Ev, Ib -> just a hack to save some space; the data width of the 1st parameter determines the real width */
    1033                 pCpu->param2.size = pCpu->param1.size;
    1034                 param2.size     = param1.size;
    1035             }
    1036 
    1037             /* The destination is always a virtual address */
    1038             if (param1.type == PARMTYPE_ADDRESS)
    1039             {
    1040                 pParam1 = (RTGCPTR)param1.val.val32;
    1041                 pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
    1042 
    1043 #ifdef IN_GC
    1044                 /* Safety check (in theory it could cross a page boundary and fault there though) */
    1045                 AssertReturn(pParam1 == pvFault, VERR_EM_INTERPRETER);
    1046 #endif
    1047                 rc = emRamRead(pVM, &valpar1, pParam1, param1.size);
    1048                 if (VBOX_FAILURE(rc))
    1049                 {
    1050                     AssertMsgFailed(("emRamRead %VGv size=%d failed with %Vrc\n", pParam1, param1.size, rc));
    1051                     return VERR_EM_INTERPRETER;
    1052                 }
    1053             }
    1054             else
    1055             {
    1056 #ifndef DEBUG_bird
    1057                 AssertFailed();
    1058 #endif
    1059                 return VERR_EM_INTERPRETER;
    1060             }
    1061 
    1062             /* Register or immediate data */
    1063             switch(param2.type)
    1064             {
    1065             case PARMTYPE_IMMEDIATE:    /* both immediate data and register (ugly) */
    1066                 valpar2 = param2.val.val32;
    1067                 break;
    1068 
    1069             default:
    1070                 AssertFailed();
    1071                 return VERR_EM_INTERPRETER;
    1072             }
    1073 
    1074             /* Data read, emulate ADC. */
    1075             uint32_t eflags;
    1076 
    1077             if (pRegFrame->eflags.u32 & X86_EFL_CF)
    1078                 eflags = EMEmulateAdcWithCarrySet(&valpar1, valpar2, param2.size);
    1079             else
    1080                 eflags = EMEmulateAdd(&valpar1, valpar2, param2.size);
    1081 
    1082             /* Update guest's eflags and finish. */
    1083             pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
    1084                                   | (eflags                &  (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
    1085 
    1086             /* And write it back */
    1087             rc = emRamWrite(pVM, pParam1, &valpar1, param1.size);
    1088             if (VBOX_SUCCESS(rc))
    1089             {
    1090                 /* All done! */
    1091                 *pcbSize = param2.size;
    1092                 return VINF_SUCCESS;
    1093             }
    1094 #ifdef IN_GC
    1095         }
    1096     }
    1097 #endif
    1098     return VERR_EM_INTERPRETER;
    1099 }
    1100 
    1101 /**
    1102  * SUB Emulation.
    1103  */
    1104 static int emInterpretSub(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    1105 {
    1106     OP_PARAMVAL param1, param2;
    1107     int rc = DISQueryParamVal(pRegFrame, pCpu, &pCpu->param1, &param1, PARAM_DEST);
    1108     if(VBOX_FAILURE(rc))
    1109         return VERR_EM_INTERPRETER;
    1110 
    1111     rc = DISQueryParamVal(pRegFrame, pCpu, &pCpu->param2, &param2, PARAM_SOURCE);
    1112     if(VBOX_FAILURE(rc))
    1113         return VERR_EM_INTERPRETER;
    1114 
    1115 #ifdef IN_GC
    1116     if (TRPMHasTrap(pVM))
    1117     {
    1118         if (TRPMGetErrorCode(pVM) & X86_TRAP_PF_RW)
    1119         {
    1120 #endif
    1121             RTGCPTR  pParam1;
    1122             uint32_t valpar1, valpar2;
    1123 
    1124             if (pCpu->param1.size != pCpu->param2.size)
    1125             {
    1126                 if (pCpu->param1.size < pCpu->param2.size)
    1127                 {
    1128                     AssertMsgFailed(("Sub at %VGv parameter mismatch %d vs %d!!\n", pRegFrame->eip, pCpu->param1.size, pCpu->param2.size)); /* should never happen! */
    1129                     return VERR_EM_INTERPRETER;
    1130                 }
    1131                 /* Or %Ev, Ib -> just a hack to save some space; the data width of the 1st parameter determines the real width */
    1132                 pCpu->param2.size = pCpu->param1.size;
    1133                 param2.size     = param1.size;
    1134             }
    1135 
    1136             /* The destination is always a virtual address */
    1137             if (param1.type == PARMTYPE_ADDRESS)
    1138             {
    1139                 pParam1 = (RTGCPTR)param1.val.val32;
    1140                 pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
    1141 
    1142 #ifdef IN_GC
    1143                 /* Safety check (in theory it could cross a page boundary and fault there though) */
    1144                 AssertReturn(pParam1 == pvFault, VERR_EM_INTERPRETER);
    1145 #endif
    1146                 rc = emRamRead(pVM, &valpar1, pParam1, param1.size);
    1147                 if (VBOX_FAILURE(rc))
    1148                 {
    1149                     AssertMsgFailed(("emRamRead %VGv size=%d failed with %Vrc\n", pParam1, param1.size, rc));
    1150                     return VERR_EM_INTERPRETER;
    1151                 }
    1152             }
    1153             else
    1154             {
    1155 #ifndef DEBUG_bird
    1156                 AssertFailed();
    1157 #endif
    1158                 return VERR_EM_INTERPRETER;
    1159             }
    1160 
    1161             /* Register or immediate data */
    1162             switch(param2.type)
    1163             {
    1164             case PARMTYPE_IMMEDIATE:    /* both immediate data and register (ugly) */
    1165                 valpar2 = param2.val.val32;
    1166                 break;
    1167 
    1168             default:
    1169                 AssertFailed();
    1170                 return VERR_EM_INTERPRETER;
    1171             }
    1172 
    1173             /* Data read, emulate SUB. */
    1174             uint32_t eflags = EMEmulateSub(&valpar1, valpar2, param2.size);
    1175 
    1176             /* Update guest's eflags and finish. */
    1177             pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
    1178                                   | (eflags                &  (X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF));
    1179 
    1180             /* And write it back */
    1181             rc = emRamWrite(pVM, pParam1, &valpar1, param1.size);
    1182             if (VBOX_SUCCESS(rc))
    1183             {
    1184                 /* All done! */
    1185                 *pcbSize = param2.size;
    1186                 return VINF_SUCCESS;
    1187             }
    1188 #ifdef IN_GC
    1189         }
    1190     }
    1191 #endif
    1192     return VERR_EM_INTERPRETER;
    1193 }
    1194 
    1195 /**
    1196  * BTR/C/S Emulation.
    1197  */
    1198 static int emInterpretBitTest(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
    1199 {
    1200     OP_PARAMVAL param1, param2;
    1201     int rc = DISQueryParamVal(pRegFrame, pCpu, &pCpu->param1, &param1, PARAM_DEST);
    1202     if(VBOX_FAILURE(rc))
    1203         return VERR_EM_INTERPRETER;
    1204 
    1205     rc = DISQueryParamVal(pRegFrame, pCpu, &pCpu->param2, &param2, PARAM_SOURCE);
    1206     if(VBOX_FAILURE(rc))
    1207         return VERR_EM_INTERPRETER;
    1208 
    1209 #ifdef IN_GC
    1210     if (TRPMHasTrap(pVM))
    1211     {
    1212         if (TRPMGetErrorCode(pVM) & X86_TRAP_PF_RW)
    1213         {
    1214 #endif
    1215             RTGCPTR  pParam1;
    1216             uint32_t valpar1 = 0, valpar2;
    1217             uint32_t eflags;
    1218 
    1219             /* The destination is always a virtual address */
    1220             if (param1.type != PARMTYPE_ADDRESS)
    1221                 return VERR_EM_INTERPRETER;
    1222 
    1223             pParam1 = (RTGCPTR)param1.val.val32;
    1224             pParam1 = emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, pParam1);
    1225 
    1226             /* Register or immediate data */
    1227             switch(param2.type)
    1228             {
    1229             case PARMTYPE_IMMEDIATE:    /* both immediate data and register (ugly) */
    1230                 valpar2 = param2.val.val32;
    1231                 break;
    1232 
    1233             default:
    1234                 AssertFailed();
    1235                 return VERR_EM_INTERPRETER;
    1236             }
    1237 
    1238             Log2(("emInterpretBt%c: pvFault=%VGv pParam1=%VGv val2=%x\n", (pCpu->pCurInstr->opcode == OP_BTR) ? 'r' : ((pCpu->pCurInstr->opcode == OP_BTC) ? 'c' : 'r'),
    1239                   pvFault, pParam1, valpar2));
     916            Log2(("emInterpret%s: pvFault=%VGv pParam1=%VGv val2=%x\n", pszInstr, pvFault, pParam1, valpar2));
    1240917            pParam1 = (RTGCPTR)((RTGCUINTPTR)pParam1 + valpar2/8);
    1241918#ifdef IN_GC
     
    1252929            Log2(("emInterpretBtx: val=%x\n", valpar1));
    1253930            /* Data read, emulate bit test instruction. */
    1254             switch (pCpu->pCurInstr->opcode)
    1255             {
    1256             case OP_BTR:
    1257                 eflags = EMEmulateBtr(&valpar1, valpar2 & 0x7);
    1258                 break;
    1259             case OP_BTC:
    1260                 eflags = EMEmulateBtc(&valpar1, valpar2 & 0x7);
    1261                 break;
    1262             case OP_BTS:
    1263                 eflags = EMEmulateBts(&valpar1, valpar2 & 0x7);
    1264                 break;
    1265             default:
    1266                 AssertFailed();
    1267                 eflags = 0;
    1268                 break;
    1269             }
     931            eflags = pfnEmulate(&valpar1, valpar2 & 0x7);
     932
    1270933            Log2(("emInterpretBtx: val=%x CF=%d\n", valpar1, !!(eflags & X86_EFL_CF)));
    1271934
     
    20091672    switch (pCpu->pCurInstr->opcode)
    20101673    {
    2011 #define INTERPRET_CASE_EX(opcode,Instr,InstrFn) \
     1674#define INTERPRET_CASE_EX_PARAM3(opcode,Instr,InstrFn, pfnEmulate) \
    20121675        case opcode:\
    2013             rc = emInterpret##InstrFn(pVM, pCpu, pRegFrame, pvFault, pcbSize); \
     1676            rc = emInterpret##InstrFn(pVM, pCpu, pRegFrame, pvFault, pcbSize, pfnEmulate); \
    20141677            if (VBOX_SUCCESS(rc)) \
    20151678                STAM_COUNTER_INC(&pVM->em.s.CTXSUFF(pStats)->CTXMID(Stat,Instr)); \
     
    20171680                STAM_COUNTER_INC(&pVM->em.s.CTXSUFF(pStats)->CTXMID(Stat,Failed##Instr)); \
    20181681            return rc
    2019 #define INTERPRET_CASE(opcode,Instr) INTERPRET_CASE_EX(opcode,Instr,Instr)
     1682#define INTERPRET_CASE_EX_PARAM2(opcode,Instr,InstrFn, pfnEmulate) \
     1683        case opcode:\
     1684            rc = emInterpret##InstrFn(pVM, pCpu, pRegFrame, pvFault, pcbSize, pfnEmulate); \
     1685            if (VBOX_SUCCESS(rc)) \
     1686                STAM_COUNTER_INC(&pVM->em.s.CTXSUFF(pStats)->CTXMID(Stat,Instr)); \
     1687            else \
     1688                STAM_COUNTER_INC(&pVM->em.s.CTXSUFF(pStats)->CTXMID(Stat,Failed##Instr)); \
     1689            return rc
     1690#define INTERPRET_CASE(opcode,Instr) \
     1691        case opcode:\
     1692            rc = emInterpret##Instr(pVM, pCpu, pRegFrame, pvFault, pcbSize); \
     1693            if (VBOX_SUCCESS(rc)) \
     1694                STAM_COUNTER_INC(&pVM->em.s.CTXSUFF(pStats)->CTXMID(Stat,Instr)); \
     1695            else \
     1696                STAM_COUNTER_INC(&pVM->em.s.CTXSUFF(pStats)->CTXMID(Stat,Failed##Instr)); \
     1697            return rc
    20201698#define INTERPRET_STAT_CASE(opcode,Instr) \
    20211699        case opcode: STAM_COUNTER_INC(&pVM->em.s.CTXSUFF(pStats)->CTXMID(Stat,Failed##Instr)); return VERR_EM_INTERPRETER;
    20221700
    20231701        INTERPRET_CASE(OP_XCHG,Xchg);
    2024         INTERPRET_CASE_EX(OP_DEC,Dec,IncDec);
    2025         INTERPRET_CASE_EX(OP_INC,Inc,IncDec);
     1702        INTERPRET_CASE_EX_PARAM2(OP_DEC,Dec,IncDec,EMEmulateDec);
     1703        INTERPRET_CASE_EX_PARAM2(OP_INC,Inc,IncDec,EMEmulateInc);
    20261704        INTERPRET_CASE(OP_POP,Pop);
    2027         INTERPRET_CASE(OP_OR,Or);
    2028         INTERPRET_CASE(OP_XOR,Xor);
     1705        INTERPRET_CASE_EX_PARAM3(OP_OR, Or,  OrXorAnd, EMEmulateOr);
     1706        INTERPRET_CASE_EX_PARAM3(OP_XOR,Xor, OrXorAnd, EMEmulateXor);
     1707        INTERPRET_CASE_EX_PARAM3(OP_AND,And, OrXorAnd, EMEmulateAnd);
    20291708        INTERPRET_CASE(OP_MOV,Mov);
    2030         INTERPRET_CASE(OP_AND,And);
    20311709        INTERPRET_CASE(OP_INVLPG,InvlPg);
    20321710        INTERPRET_CASE(OP_CPUID,CpuId);
     
    20361714        INTERPRET_CASE(OP_MONITOR, Monitor);
    20371715        INTERPRET_CASE(OP_MWAIT, MWait);
    2038         INTERPRET_CASE(OP_ADD,Add);
     1716        INTERPRET_CASE_EX_PARAM3(OP_ADD,Add, AddSub, EMEmulateAdd);
     1717        INTERPRET_CASE_EX_PARAM3(OP_SUB,Sub, AddSub, EMEmulateSub);
    20391718        INTERPRET_CASE(OP_ADC,Adc);
    2040         INTERPRET_CASE(OP_SUB,Sub);
    2041         INTERPRET_CASE_EX(OP_BTR,Btr, BitTest);
    2042         INTERPRET_CASE_EX(OP_BTS,Bts, BitTest);
    2043         INTERPRET_CASE_EX(OP_BTC,Btc, BitTest);
     1719        INTERPRET_CASE_EX_PARAM2(OP_BTR,Btr, BitTest, EMEmulateBtr);
     1720        INTERPRET_CASE_EX_PARAM2(OP_BTS,Bts, BitTest, EMEmulateBts);
     1721        INTERPRET_CASE_EX_PARAM2(OP_BTC,Btc, BitTest, EMEmulateBtc);
    20441722#ifdef IN_GC
    20451723        INTERPRET_CASE(OP_RDTSC,Rdtsc);
     
    20581736            STAM_COUNTER_INC(&pVM->em.s.CTXSUFF(pStats)->CTXMID(Stat,FailedMisc));
    20591737            return VERR_EM_INTERPRETER;
     1738#undef INTERPRET_CASE_EX_PARAM2
    20601739#undef INTERPRET_STAT_CASE
     1740#undef INTERPRET_CASE_EX
    20611741#undef INTERPRET_CASE
    20621742    }
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette