VirtualBox

Changeset 62371 in vbox for trunk/src/VBox/VMM/VMMAll


Ignore:
Timestamp:
Jul 20, 2016 5:18:10 PM (8 years ago)
Author:
vboxsync
Message:

IEMAllAImplC.cpp: Basic 64-bit division and multiplication for 32-bit hosts. Needs testing and EFLAGS work.

File:
1 edited

Legend:

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

    r62338 r62371  
    55
    66/*
    7  * Copyright (C) 2011-2015 Oracle Corporation
     7 * Copyright (C) 2011-2016 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2323#include <VBox/vmm/vm.h>
    2424#include <iprt/x86.h>
     25#ifdef RT_ARCH_X86
     26# include <iprt/uint128.h>
     27#endif
    2528
    2629
     
    11301133/* multiplication and division */
    11311134
     1135
     1136
    11321137IEM_DECL_IMPL_DEF(int, iemAImpl_mul_u64,(uint64_t *pu64RAX, uint64_t *pu64RDX, uint64_t u64Factor, uint32_t *pfEFlags))
    11331138{
    1134     AssertFailed();
     1139    RTUINT128U Result;
     1140    RTUInt128MulU64ByU64(&Result, *pu64RAX, u64Factor);
     1141    *pu64RAX = Result.s.Lo;
     1142    *pu64RDX = Result.s.Hi;
     1143    /** @todo research the undefined MUL flags. */
     1144    return 0;
     1145}
     1146
     1147
     1148IEM_DECL_IMPL_DEF(int, iemAImpl_imul_u64,(uint64_t *pu64RAX, uint64_t *pu64RDX, uint64_t u64Factor, uint32_t *pfEFlags))
     1149{
     1150/** @todo Testcase: IMUL 1 operand   */
     1151    RTUINT128U Result;
     1152    *pfEFlags &= ~(X86_EFL_SF | X86_EFL_CF | X86_EFL_OF);
     1153    if ((int64_t)*pu64RAX >= 0)
     1154    {
     1155        if ((int64_t)*pu64RDX >= 0)
     1156        {
     1157            RTUInt128MulU64ByU64(&Result, *pu64RAX, *pu64RDX);
     1158            *pu64RAX = Result.s.Lo;
     1159            *pu64RDX = Result.s.Hi;
     1160            if (Result.s.Hi != 0 || Result.s.Lo >= UINT64_C(0x8000000000000000))
     1161                *pfEFlags |= X86_EFL_CF | X86_EFL_OF;
     1162        }
     1163        else
     1164        {
     1165            RTUInt128MulU64ByU64(&Result, *pu64RAX, UINT64_C(0) - *pu64RDX);
     1166            if (Result.s.Hi != 0 || Result.s.Lo > UINT64_C(0x8000000000000000))
     1167                *pfEFlags |= X86_EFL_CF | X86_EFL_OF;
     1168            *pu64RAX = UINT64_C(0) - Result.s.Lo;
     1169            *pu64RDX = UINT64_C(0) - Result.s.Hi;
     1170        }
     1171    }
     1172    else
     1173    {
     1174        if ((int64_t)*pu64RDX >= 0)
     1175        {
     1176            RTUInt128MulU64ByU64(&Result, UINT64_C(0) - *pu64RAX, *pu64RDX);
     1177            if (Result.s.Hi != 0 || Result.s.Lo > UINT64_C(0x8000000000000000))
     1178                *pfEFlags |= X86_EFL_CF | X86_EFL_OF;
     1179            *pu64RAX = UINT64_C(0) - Result.s.Lo;
     1180            *pu64RDX = UINT64_C(0) - Result.s.Hi;
     1181        }
     1182        else
     1183        {
     1184            RTUInt128MulU64ByU64(&Result, UINT64_C(0) - *pu64RAX, UINT64_C(0) - *pu64RDX);
     1185            if (Result.s.Hi != 0 || Result.s.Lo >= UINT64_C(0x8000000000000000))
     1186                *pfEFlags |= X86_EFL_CF | X86_EFL_OF;
     1187            *pu64RAX = Result.s.Lo;
     1188            *pu64RDX = Result.s.Hi;
     1189        }
     1190    }
     1191    if (*pu64RAX & RT_BIT_64(63))
     1192        *pfEFlags |= X86_EFL_SF;
     1193
     1194    /** @todo research the undefined IMUL flags. */
     1195    return 0;
     1196}
     1197
     1198
     1199IEM_DECL_IMPL_DEF(void, iemAImpl_imul_two_u64,(uint64_t *puDst, uint64_t uSrc, uint32_t *pfEFlags))
     1200{
     1201/** @todo Testcase: IMUL 2 and 3 operands. */
     1202    uint64_t u64Ign;
     1203    iemAImpl_imul_u64(puDst, &u64Ign, uSrc, pfEFlags);
     1204}
     1205
     1206
     1207
     1208IEM_DECL_IMPL_DEF(int, iemAImpl_div_u64,(uint64_t *pu64RAX, uint64_t *pu64RDX, uint64_t u64Divisor, uint32_t *pfEFlags))
     1209{
     1210    if (   u64Divisor != 0
     1211        && *pu64RDX < u64Divisor)
     1212    {
     1213        RTUINT128U Dividend;
     1214        Dividend.s.Lo = *pu64RAX;
     1215        Dividend.s.Hi = *pu64RDX;
     1216
     1217        RTUINT128U Divisor;
     1218        Divisor.s.Lo = u64Divisor;
     1219        Divisor.s.Hi = 0;
     1220
     1221        RTUINT128U Remainder;
     1222        RTUINT128U Quotient;
     1223        RTUInt128DivRem(&Quotient, &Remainder, &Dividend, &Divisor);
     1224        Assert(Quotient.s.Hi == 0);
     1225        Assert(Remainder.s.Hi == 0);
     1226
     1227        *pu64RAX = Quotient.s.Lo;
     1228        *pu64RDX = Remainder.s.Lo;
     1229        /** @todo research the undefined DIV flags. */
     1230        return 0;
     1231
     1232    }
     1233    /* #DE */
    11351234    return VERR_IEM_ASPECT_NOT_IMPLEMENTED;
    11361235}
    11371236
    11381237
    1139 IEM_DECL_IMPL_DEF(int, iemAImpl_imul_u64,(uint64_t *pu64RAX, uint64_t *pu64RDX, uint64_t u64Factor, uint32_t *pfEFlags))
    1140 {
    1141     AssertFailed();
    1142     return VERR_IEM_ASPECT_NOT_IMPLEMENTED;
    1143 }
    1144 
    1145 
    1146 IEM_DECL_IMPL_DEF(void, iemAImpl_imul_two_u64,(uint64_t *puDst, uint64_t uSrc, uint32_t *pfEFlags))
    1147 {
    1148     AssertFailed();
    1149 }
    1150 
    1151 
    1152 
    1153 IEM_DECL_IMPL_DEF(int, iemAImpl_div_u64,(uint64_t *pu64RAX, uint64_t *pu64RDX, uint64_t u64Divisor, uint32_t *pfEFlags))
    1154 {
    1155     AssertFailed();
    1156     return VERR_IEM_ASPECT_NOT_IMPLEMENTED;
    1157 }
    1158 
    1159 
    11601238IEM_DECL_IMPL_DEF(int, iemAImpl_idiv_u64,(uint64_t *pu64RAX, uint64_t *pu64RDX, uint64_t u64Divisor, uint32_t *pfEFlags))
    11611239{
    1162     AssertFailed();
     1240    if (u64Divisor != 0)
     1241    {
     1242        /*
     1243         * Convert to unsigned division.
     1244         */
     1245        RTUINT128U Dividend;
     1246        Dividend.s.Hi = 0;
     1247        if ((int64_t)*pu64RDX >= 0)
     1248        {
     1249            Dividend.s.Lo = *pu64RAX;
     1250            Dividend.s.Hi = *pu64RDX;
     1251        }
     1252        else
     1253        {
     1254            Dividend.s.Lo = UINT64_C(0) - *pu64RAX;
     1255            Dividend.s.Hi = UINT64_C(0) - *pu64RDX;
     1256        }
     1257
     1258        RTUINT128U Divisor;
     1259        Divisor.s.Hi = 0;
     1260        if ((int64_t)u64Divisor >= 0)
     1261            Divisor.s.Lo = u64Divisor;
     1262        else
     1263            Divisor.s.Lo = UINT64_C(0) - u64Divisor;
     1264
     1265        RTUINT128U Remainder;
     1266        RTUINT128U Quotient;
     1267        RTUInt128DivRem(&Quotient, &Remainder, &Dividend, &Divisor);
     1268
     1269        /*
     1270         * Setup the result, checking for overflows.
     1271         */
     1272        if ((int64_t)u64Divisor >= 0)
     1273        {
     1274            if ((int64_t)*pu64RDX >= 0)
     1275            {
     1276                /* Positive divisor, positive dividend => result positive. */
     1277                if (Quotient.s.Hi == 0 && Quotient.s.Lo <= (uint64_t)INT64_MAX)
     1278                {
     1279                    *pu64RAX = Quotient.s.Lo;
     1280                    *pu64RDX = Remainder.s.Lo;
     1281                    return 0;
     1282                }
     1283            }
     1284            else
     1285            {
     1286                /* Positive divisor, positive dividend => result negative. */
     1287                if (Quotient.s.Hi == 0 && Quotient.s.Lo <= UINT64_C(0x8000000000000000))
     1288                {
     1289                    *pu64RAX = UINT64_C(0) - Quotient.s.Lo;
     1290                    *pu64RDX = UINT64_C(0) - Remainder.s.Lo;
     1291                    return 0;
     1292                }
     1293            }
     1294        }
     1295        else
     1296        {
     1297            if ((int64_t)*pu64RDX >= 0)
     1298            {
     1299                /* Negative divisor, positive dividend => negative quotient, positive remainder. */
     1300                if (Quotient.s.Hi == 0 && Quotient.s.Lo <= UINT64_C(0x8000000000000000))
     1301                {
     1302                    *pu64RAX = UINT64_C(0) - Quotient.s.Lo;
     1303                    *pu64RDX = Remainder.s.Lo;
     1304                    return 0;
     1305                }
     1306            }
     1307            else
     1308            {
     1309                /* Negative divisor, negative dividend => positive quotient, negative remainder. */
     1310                if (Quotient.s.Hi == 0 && Quotient.s.Lo <= (uint64_t)INT64_MAX)
     1311                {
     1312                    *pu64RAX = Quotient.s.Lo;
     1313                    *pu64RDX = UINT64_C(0) - Remainder.s.Lo;
     1314                    return 0;
     1315                }
     1316            }
     1317        }
     1318    }
     1319    /* #DE */
    11631320    return VERR_IEM_ASPECT_NOT_IMPLEMENTED;
    11641321}
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