VirtualBox

Changeset 93782 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Feb 16, 2022 9:09:02 AM (3 years ago)
Author:
vboxsync
Message:

VMM/IEM: Working on adding missing C version of IEMAllAImpl.asm functions. bugref:9898

File:
1 edited

Legend:

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

    r93762 r93782  
    11441144
    11451145
    1146 /* bit scan */
     1146/*
     1147 * BSF - first (least significant) bit set
     1148 */
    11471149
    11481150IEM_DECL_IMPL_DEF(void, iemAImpl_bsf_u64,(uint64_t *puDst, uint64_t uSrc, uint32_t *pfEFlags))
     
    11501152    /* Note! "undefined" flags: OF, SF, AF, PF, CF. */
    11511153    /** @todo check what real CPUs do. */
    1152     if (uSrc)
    1153     {
    1154         uint8_t  iBit;
    1155         uint32_t u32Src;
    1156         if (uSrc & UINT32_MAX)
    1157         {
    1158             iBit = 0;
    1159             u32Src = uSrc;
    1160         }
    1161         else
    1162         {
    1163             iBit = 32;
    1164             u32Src = uSrc >> 32;
    1165         }
    1166         if (!(u32Src & UINT16_MAX))
    1167         {
    1168             iBit += 16;
    1169             u32Src >>= 16;
    1170         }
    1171         if (!(u32Src & UINT8_MAX))
    1172         {
    1173             iBit += 8;
    1174             u32Src >>= 8;
    1175         }
    1176         if (!(u32Src & 0xf))
    1177         {
    1178             iBit += 4;
    1179             u32Src >>= 4;
    1180         }
    1181         if (!(u32Src & 0x3))
    1182         {
    1183             iBit += 2;
    1184             u32Src >>= 2;
    1185         }
    1186         if (!(u32Src & 1))
    1187         {
    1188             iBit += 1;
    1189             Assert(u32Src & 2);
    1190         }
    1191 
    1192         *puDst     = iBit;
     1154    unsigned iBit = ASMBitFirstSetU64(uSrc);
     1155    if (iBit)
     1156    {
     1157        *puDst     = iBit - 1;
    11931158        *pfEFlags &= ~X86_EFL_ZF;
    11941159    }
     
    11971162}
    11981163
    1199 IEM_DECL_IMPL_DEF(void, iemAImpl_bsr_u64,(uint64_t *puDst, uint64_t uSrc, uint32_t *pfEFlags))
     1164# if !defined(RT_ARCH_X86) || defined(IEM_WITHOUT_ASSEMBLY)
     1165
     1166IEM_DECL_IMPL_DEF(void, iemAImpl_bsf_u32,(uint32_t *puDst, uint32_t uSrc, uint32_t *pfEFlags))
    12001167{
    12011168    /* Note! "undefined" flags: OF, SF, AF, PF, CF. */
    12021169    /** @todo check what real CPUs do. */
     1170    unsigned iBit = ASMBitFirstSetU32(uSrc);
     1171    if (iBit)
     1172    {
     1173        *puDst     = iBit - 1;
     1174        *pfEFlags &= ~X86_EFL_ZF;
     1175    }
     1176    else
     1177        *pfEFlags |= X86_EFL_ZF;
     1178}
     1179
     1180
     1181IEM_DECL_IMPL_DEF(void, iemAImpl_bsf_u16,(uint16_t *puDst, uint16_t uSrc, uint32_t *pfEFlags))
     1182{
     1183    /* Note! "undefined" flags: OF, SF, AF, PF, CF. */
     1184    /** @todo check what real CPUs do. */
     1185    unsigned iBit = ASMBitFirstSetU16(uSrc);
     1186    if (iBit)
     1187    {
     1188        *puDst     = iBit - 1;
     1189        *pfEFlags &= ~X86_EFL_ZF;
     1190    }
     1191    else
     1192        *pfEFlags |= X86_EFL_ZF;
     1193}
     1194
     1195# endif /* !defined(RT_ARCH_X86) || defined(IEM_WITHOUT_ASSEMBLY) */
     1196
     1197/*
     1198 * BSR - last (most significant) bit set
     1199 */
     1200
     1201IEM_DECL_IMPL_DEF(void, iemAImpl_bsr_u64,(uint64_t *puDst, uint64_t uSrc, uint32_t *pfEFlags))
     1202{
     1203    /* Note! "undefined" flags: OF, SF, AF, PF, CF. */
     1204    /** @todo check what real CPUs do. */
     1205    unsigned iBit = ASMBitLastSetU64(uSrc);
    12031206    if (uSrc)
    12041207    {
    1205         uint8_t  iBit;
    1206         uint32_t u32Src;
    1207         if (uSrc & UINT64_C(0xffffffff00000000))
    1208         {
    1209             iBit = 63;
    1210             u32Src = uSrc >> 32;
    1211         }
    1212         else
    1213         {
    1214             iBit = 31;
    1215             u32Src = uSrc;
    1216         }
    1217         if (!(u32Src & UINT32_C(0xffff0000)))
    1218         {
    1219             iBit -= 16;
    1220             u32Src <<= 16;
    1221         }
    1222         if (!(u32Src & UINT32_C(0xff000000)))
    1223         {
    1224             iBit -= 8;
    1225             u32Src <<= 8;
    1226         }
    1227         if (!(u32Src & UINT32_C(0xf0000000)))
    1228         {
    1229             iBit -= 4;
    1230             u32Src <<= 4;
    1231         }
    1232         if (!(u32Src & UINT32_C(0xc0000000)))
    1233         {
    1234             iBit -= 2;
    1235             u32Src <<= 2;
    1236         }
    1237         if (!(u32Src & UINT32_C(0x80000000)))
    1238         {
    1239             iBit -= 1;
    1240             Assert(u32Src & RT_BIT(30));
    1241         }
    1242 
    1243         *puDst     = iBit;
     1208        *puDst     = iBit - 1;
    12441209        *pfEFlags &= ~X86_EFL_ZF;
    12451210    }
     
    12481213}
    12491214
    1250 
    1251 /* Unary operands. */
    1252 
    1253 IEM_DECL_IMPL_DEF(void, iemAImpl_inc_u64,(uint64_t  *puDst,  uint32_t *pfEFlags))
    1254 {
    1255     uint64_t uDst    = *puDst;
    1256     uint64_t uResult = uDst + 1;
    1257     *puDst = uResult;
    1258 
    1259     /*
    1260      * Calc EFLAGS.
    1261      * CF is NOT modified for hysterical raisins (allegedly for carrying and
    1262      * borrowing in arithmetic loops on intel 8008).
    1263      */
    1264     uint32_t fEfl = *pfEFlags & ~(X86_EFL_STATUS_BITS & ~X86_EFL_CF);
    1265     fEfl |= g_afParity[uResult & 0xff];
    1266     fEfl |= ((uint32_t)uResult ^ (uint32_t)uDst) & X86_EFL_AF;
    1267     fEfl |= X86_EFL_CALC_ZF(uResult);
    1268     fEfl |= X86_EFL_CALC_SF(uResult, 64);
    1269     fEfl |= (((uDst ^ RT_BIT_64(63)) & uResult) >> (64 - X86_EFL_OF_BIT)) & X86_EFL_OF;
    1270     *pfEFlags = fEfl;
    1271 }
    1272 
    1273 
    1274 IEM_DECL_IMPL_DEF(void, iemAImpl_dec_u64,(uint64_t  *puDst,  uint32_t *pfEFlags))
    1275 {
    1276     uint64_t uDst    = *puDst;
    1277     uint64_t uResult = uDst - 1;
    1278     *puDst = uResult;
    1279 
    1280     /*
    1281      * Calc EFLAGS.
    1282      * CF is NOT modified for hysterical raisins (allegedly for carrying and
    1283      * borrowing in arithmetic loops on intel 8008).
    1284      */
    1285     uint32_t fEfl = *pfEFlags & ~(X86_EFL_STATUS_BITS & ~X86_EFL_CF);
    1286     fEfl |= g_afParity[uResult & 0xff];
    1287     fEfl |= ((uint32_t)uResult ^ (uint32_t)uDst) & X86_EFL_AF;
    1288     fEfl |= X86_EFL_CALC_ZF(uResult);
    1289     fEfl |= X86_EFL_CALC_SF(uResult, 64);
    1290     fEfl |= ((uDst & (uResult ^ RT_BIT_64(63))) >> (64 - X86_EFL_OF_BIT)) & X86_EFL_OF;
    1291     *pfEFlags = fEfl;
    1292 }
    1293 
    1294 
    1295 IEM_DECL_IMPL_DEF(void, iemAImpl_not_u64,(uint64_t  *puDst,  uint32_t *pfEFlags))
    1296 {
    1297     uint64_t uDst    = *puDst;
    1298     uint64_t uResult = ~uDst;
    1299     *puDst = uResult;
    1300     /* EFLAGS are not modified. */
    1301     RT_NOREF_PV(pfEFlags);
    1302 }
    1303 
    1304 
    1305 IEM_DECL_IMPL_DEF(void, iemAImpl_neg_u64,(uint64_t  *puDst,  uint32_t *pfEFlags))
    1306 {
    1307     uint64_t uDst    = 0;
    1308     uint64_t uSrc    = *puDst;
    1309     uint64_t uResult = uDst - uSrc;
    1310     *puDst = uResult;
    1311 
    1312     /* Calc EFLAGS. */
    1313     uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS;
    1314     fEfl |= (uSrc != 0) << X86_EFL_CF_BIT;
    1315     fEfl |= g_afParity[uResult & 0xff];
    1316     fEfl |= ((uint32_t)uResult ^ (uint32_t)uDst) & X86_EFL_AF;
    1317     fEfl |= X86_EFL_CALC_ZF(uResult);
    1318     fEfl |= X86_EFL_CALC_SF(uResult, 64);
    1319     fEfl |= ((uSrc & uResult) >> (64 - X86_EFL_OF_BIT)) & X86_EFL_OF;
    1320     *pfEFlags = fEfl;
    1321 }
    1322 
    1323 
    1324 /** 64-bit locked unary operand operation. */
    1325 # define DO_LOCKED_UNARY_OP_U64(a_Mnemonic) \
    1326     do { \
    1327         uint64_t uOld = ASMAtomicReadU64(puDst); \
    1328         uint64_t uTmp; \
    1329         uint32_t fEflTmp; \
    1330         do \
    1331         { \
    1332             uTmp = uOld; \
    1333             fEflTmp = *pfEFlags; \
    1334             iemAImpl_ ## a_Mnemonic ## _u64(&uTmp, &fEflTmp); \
    1335         } while (!ASMAtomicCmpXchgExU64(puDst, uTmp, uOld, &uOld)); \
    1336         *pfEFlags = fEflTmp; \
    1337     } while (0)
    1338 
    1339 IEM_DECL_IMPL_DEF(void, iemAImpl_inc_u64_locked,(uint64_t  *puDst,  uint32_t *pfEFlags))
    1340 {
    1341     DO_LOCKED_UNARY_OP_U64(inc);
    1342 }
    1343 
    1344 
    1345 IEM_DECL_IMPL_DEF(void, iemAImpl_dec_u64_locked,(uint64_t  *puDst,  uint32_t *pfEFlags))
    1346 {
    1347     DO_LOCKED_UNARY_OP_U64(dec);
    1348 }
    1349 
    1350 
    1351 IEM_DECL_IMPL_DEF(void, iemAImpl_not_u64_locked,(uint64_t  *puDst,  uint32_t *pfEFlags))
    1352 {
    1353     DO_LOCKED_UNARY_OP_U64(not);
    1354 }
    1355 
    1356 
    1357 IEM_DECL_IMPL_DEF(void, iemAImpl_neg_u64_locked,(uint64_t  *puDst,  uint32_t *pfEFlags))
    1358 {
    1359     DO_LOCKED_UNARY_OP_U64(neg);
    1360 }
    1361 
    1362 
    1363 /* Shift and rotate. */
    1364 
    1365 IEM_DECL_IMPL_DEF(void, iemAImpl_rol_u64,(uint64_t *puDst, uint8_t cShift, uint32_t *pfEFlags))
    1366 {
    1367     cShift &= 63;
    1368     if (cShift)
    1369     {
    1370         uint64_t uDst = *puDst;
    1371         uint64_t uResult;
    1372         uResult  = uDst << cShift;
    1373         uResult |= uDst >> (64 - cShift);
    1374         *puDst = uResult;
    1375 
    1376         /* Calc EFLAGS.  The OF bit is undefined if cShift > 1, we implement
    1377            it the same way as for 1 bit shifts. */
    1378         AssertCompile(X86_EFL_CF_BIT == 0);
    1379         uint32_t fEfl   = *pfEFlags & ~(X86_EFL_CF | X86_EFL_OF);
    1380         uint32_t fCarry = (uResult & 1);
    1381         fEfl |= fCarry;
    1382         fEfl |= ((uResult >> 63) ^ fCarry) << X86_EFL_OF_BIT;
    1383         *pfEFlags = fEfl;
    1384     }
    1385 }
    1386 
    1387 
    1388 IEM_DECL_IMPL_DEF(void, iemAImpl_ror_u64,(uint64_t *puDst, uint8_t cShift, uint32_t *pfEFlags))
    1389 {
    1390     cShift &= 63;
    1391     if (cShift)
    1392     {
    1393         uint64_t uDst = *puDst;
    1394         uint64_t uResult;
    1395         uResult  = uDst >> cShift;
    1396         uResult |= uDst << (64 - cShift);
    1397         *puDst = uResult;
    1398 
    1399         /* Calc EFLAGS.  The OF bit is undefined if cShift > 1, we implement
    1400            it the same way as for 1 bit shifts (OF = OF XOR New-CF). */
    1401         AssertCompile(X86_EFL_CF_BIT == 0);
    1402         uint32_t fEfl   = *pfEFlags & ~(X86_EFL_CF | X86_EFL_OF);
    1403         uint32_t fCarry = (uResult >> 63) & X86_EFL_CF;
    1404         fEfl |= fCarry;
    1405         fEfl |= (((uResult >> 62) ^ fCarry) << X86_EFL_OF_BIT) & X86_EFL_OF;
    1406         *pfEFlags = fEfl;
    1407     }
    1408 }
    1409 
    1410 
    1411 IEM_DECL_IMPL_DEF(void, iemAImpl_rcl_u64,(uint64_t *puDst, uint8_t cShift, uint32_t *pfEFlags))
    1412 {
    1413     cShift &= 63;
    1414     if (cShift)
    1415     {
    1416         uint32_t fEfl = *pfEFlags;
    1417         uint64_t uDst = *puDst;
    1418         uint64_t uResult;
    1419         uResult = uDst << cShift;
    1420         AssertCompile(X86_EFL_CF_BIT == 0);
    1421         if (cShift > 1)
    1422             uResult |= uDst >> (65 - cShift);
    1423         uResult |= (uint64_t)(fEfl & X86_EFL_CF) << (cShift - 1);
    1424         *puDst = uResult;
    1425 
    1426         /* Calc EFLAGS.  The OF bit is undefined if cShift > 1, we implement
    1427            it the same way as for 1 bit shifts. */
    1428         uint32_t fCarry = (uDst >> (64 - cShift)) & X86_EFL_CF;
    1429         fEfl &= ~(X86_EFL_CF | X86_EFL_OF);
    1430         fEfl |= fCarry;
    1431         fEfl |= ((uResult >> 63) ^ fCarry) << X86_EFL_OF_BIT;
    1432         *pfEFlags = fEfl;
    1433     }
    1434 }
    1435 
    1436 
    1437 IEM_DECL_IMPL_DEF(void, iemAImpl_rcr_u64,(uint64_t *puDst, uint8_t cShift, uint32_t *pfEFlags))
    1438 {
    1439     cShift &= 63;
    1440     if (cShift)
    1441     {
    1442         uint32_t fEfl = *pfEFlags;
    1443         uint64_t uDst = *puDst;
    1444         uint64_t uResult;
    1445         uResult  = uDst >> cShift;
    1446         AssertCompile(X86_EFL_CF_BIT == 0);
    1447         if (cShift > 1)
    1448             uResult |= uDst << (65 - cShift);
    1449         uResult |= (uint64_t)(fEfl & X86_EFL_CF) << (64 - cShift);
    1450         *puDst = uResult;
    1451 
    1452         /* Calc EFLAGS.  The OF bit is undefined if cShift > 1, we implement
    1453            it the same way as for 1 bit shifts. */
    1454         uint32_t fCarry = (uDst >> (cShift - 1)) & X86_EFL_CF;
    1455         fEfl &= ~(X86_EFL_CF | X86_EFL_OF);
    1456         fEfl |= fCarry;
    1457         fEfl |= ((uResult >> 63) ^ fCarry) << X86_EFL_OF_BIT;
    1458         *pfEFlags = fEfl;
    1459     }
    1460 }
    1461 
    1462 
    1463 IEM_DECL_IMPL_DEF(void, iemAImpl_shl_u64,(uint64_t *puDst, uint8_t cShift, uint32_t *pfEFlags))
    1464 {
    1465     cShift &= 63;
    1466     if (cShift)
    1467     {
    1468         uint64_t uDst = *puDst;
    1469         uint64_t uResult = uDst << cShift;
    1470         *puDst = uResult;
    1471 
    1472         /* Calc EFLAGS.  The OF bit is undefined if cShift > 1, we implement
    1473            it the same way as for 1 bit shifts.  The AF bit is undefined, we
    1474            always set it to zero atm. */
    1475         AssertCompile(X86_EFL_CF_BIT == 0);
    1476         uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS;
    1477         uint32_t fCarry = (uDst >> (64 - cShift)) & X86_EFL_CF;
    1478         fEfl |= fCarry;
    1479         fEfl |= ((uResult >> 63) ^ fCarry) << X86_EFL_OF_BIT;
    1480         fEfl |= X86_EFL_CALC_SF(uResult, 64);
    1481         fEfl |= X86_EFL_CALC_ZF(uResult);
    1482         fEfl |= g_afParity[uResult & 0xff];
    1483         *pfEFlags = fEfl;
    1484     }
    1485 }
    1486 
    1487 
    1488 IEM_DECL_IMPL_DEF(void, iemAImpl_shr_u64,(uint64_t *puDst, uint8_t cShift, uint32_t *pfEFlags))
    1489 {
    1490     cShift &= 63;
    1491     if (cShift)
    1492     {
    1493         uint64_t uDst = *puDst;
    1494         uint64_t uResult = uDst >> cShift;
    1495         *puDst = uResult;
    1496 
    1497         /* Calc EFLAGS.  The OF bit is undefined if cShift > 1, we implement
    1498            it the same way as for 1 bit shifts.  The AF bit is undefined, we
    1499            always set it to zero atm. */
    1500         AssertCompile(X86_EFL_CF_BIT == 0);
    1501         uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS;
    1502         fEfl |= (uDst >> (cShift - 1)) & X86_EFL_CF;
    1503         fEfl |= (uDst >> 63) << X86_EFL_OF_BIT;
    1504         fEfl |= X86_EFL_CALC_SF(uResult, 64);
    1505         fEfl |= X86_EFL_CALC_ZF(uResult);
    1506         fEfl |= g_afParity[uResult & 0xff];
    1507         *pfEFlags = fEfl;
    1508     }
    1509 }
    1510 
    1511 
    1512 IEM_DECL_IMPL_DEF(void, iemAImpl_sar_u64,(uint64_t *puDst, uint8_t cShift, uint32_t *pfEFlags))
    1513 {
    1514     cShift &= 63;
    1515     if (cShift)
    1516     {
    1517         uint64_t uDst = *puDst;
    1518         uint64_t uResult = (int64_t)uDst >> cShift;
    1519         *puDst = uResult;
    1520 
    1521         /* Calc EFLAGS.  The OF bit is undefined if cShift > 1, we implement
    1522            it the same way as for 1 bit shifts (0).  The AF bit is undefined,
    1523            we always set it to zero atm. */
    1524         AssertCompile(X86_EFL_CF_BIT == 0);
    1525         uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS;
    1526         fEfl |= (uDst >> (cShift - 1)) & X86_EFL_CF;
    1527         fEfl |= X86_EFL_CALC_SF(uResult, 64);
    1528         fEfl |= X86_EFL_CALC_ZF(uResult);
    1529         fEfl |= g_afParity[uResult & 0xff];
    1530         *pfEFlags = fEfl;
    1531     }
    1532 }
    1533 
    1534 
    1535 IEM_DECL_IMPL_DEF(void, iemAImpl_shld_u64,(uint64_t *puDst, uint64_t uSrc, uint8_t cShift, uint32_t *pfEFlags))
    1536 {
    1537     cShift &= 63;
    1538     if (cShift)
    1539     {
    1540         uint64_t uDst = *puDst;
    1541         uint64_t uResult;
    1542         uResult  = uDst << cShift;
    1543         uResult |= uSrc >> (64 - cShift);
    1544         *puDst = uResult;
    1545 
    1546         /* Calc EFLAGS.  The OF bit is undefined if cShift > 1, we implement
    1547            it the same way as for 1 bit shifts.  The AF bit is undefined,
    1548            we always set it to zero atm. */
    1549         AssertCompile(X86_EFL_CF_BIT == 0);
    1550         uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS;
    1551         fEfl |= (uDst >> (64 - cShift)) & X86_EFL_CF;
    1552         fEfl |= (uint32_t)((uDst >> 63) ^ (uint32_t)(uResult >> 63)) << X86_EFL_OF_BIT;
    1553         fEfl |= X86_EFL_CALC_SF(uResult, 64);
    1554         fEfl |= X86_EFL_CALC_ZF(uResult);
    1555         fEfl |= g_afParity[uResult & 0xff];
    1556         *pfEFlags = fEfl;
    1557     }
    1558 }
    1559 
    1560 
    1561 IEM_DECL_IMPL_DEF(void, iemAImpl_shrd_u64,(uint64_t *puDst, uint64_t uSrc, uint8_t cShift, uint32_t *pfEFlags))
    1562 {
    1563     cShift &= 63;
    1564     if (cShift)
    1565     {
    1566         uint64_t uDst = *puDst;
    1567         uint64_t uResult;
    1568         uResult  = uDst >> cShift;
    1569         uResult |= uSrc << (64 - cShift);
    1570         *puDst = uResult;
    1571 
    1572         /* Calc EFLAGS.  The OF bit is undefined if cShift > 1, we implement
    1573            it the same way as for 1 bit shifts.  The AF bit is undefined,
    1574            we always set it to zero atm. */
    1575         AssertCompile(X86_EFL_CF_BIT == 0);
    1576         uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS;
    1577         fEfl |= (uDst >> (cShift - 1)) & X86_EFL_CF;
    1578         fEfl |= (uint32_t)((uDst >> 63) ^ (uint32_t)(uResult >> 63)) << X86_EFL_OF_BIT;
    1579         fEfl |= X86_EFL_CALC_SF(uResult, 64);
    1580         fEfl |= X86_EFL_CALC_ZF(uResult);
    1581         fEfl |= g_afParity[uResult & 0xff];
    1582         *pfEFlags = fEfl;
    1583     }
    1584 }
    1585 
    1586 
    1587 /* misc */
     1215# if !defined(RT_ARCH_X86) || defined(IEM_WITHOUT_ASSEMBLY)
     1216
     1217IEM_DECL_IMPL_DEF(void, iemAImpl_bsr_u32,(uint32_t *puDst, uint32_t uSrc, uint32_t *pfEFlags))
     1218{
     1219    /* Note! "undefined" flags: OF, SF, AF, PF, CF. */
     1220    /** @todo check what real CPUs do. */
     1221    unsigned iBit = ASMBitLastSetU32(uSrc);
     1222    if (uSrc)
     1223    {
     1224        *puDst     = iBit - 1;
     1225        *pfEFlags &= ~X86_EFL_ZF;
     1226    }
     1227    else
     1228        *pfEFlags |= X86_EFL_ZF;
     1229}
     1230
     1231
     1232IEM_DECL_IMPL_DEF(void, iemAImpl_bsr_u16,(uint16_t *puDst, uint16_t uSrc, uint32_t *pfEFlags))
     1233{
     1234    /* Note! "undefined" flags: OF, SF, AF, PF, CF. */
     1235    /** @todo check what real CPUs do. */
     1236    unsigned iBit = ASMBitLastSetU16(uSrc);
     1237    if (uSrc)
     1238    {
     1239        *puDst     = iBit - 1;
     1240        *pfEFlags &= ~X86_EFL_ZF;
     1241    }
     1242    else
     1243        *pfEFlags |= X86_EFL_ZF;
     1244}
     1245
     1246# endif /* !defined(RT_ARCH_X86) || defined(IEM_WITHOUT_ASSEMBLY) */
     1247
     1248
     1249/*
     1250 * XCHG
     1251 */
    15881252
    15891253IEM_DECL_IMPL_DEF(void, iemAImpl_xchg_u64,(uint64_t *puMem, uint64_t *puReg))
     
    17051369}
    17061370
    1707 # endif
    1708 
    1709 
    1710 #endif /* !RT_ARCH_AMD64 || IEM_WITHOUT_ASSEMBLY */
    1711 #if !defined(RT_ARCH_AMD64) || defined(IEM_WITHOUT_ASSEMBLY)
    1712 
    1713 /* multiplication and division */
    1714 
     1371# endif /* !defined(RT_ARCH_X86) || defined(IEM_WITHOUT_ASSEMBLY) */
     1372
     1373
     1374/*
     1375 * MUL
     1376 */
    17151377
    17161378IEM_DECL_IMPL_DEF(int, iemAImpl_mul_u64,(uint64_t *pu64RAX, uint64_t *pu64RDX, uint64_t u64Factor, uint32_t *pfEFlags))
     
    17311393}
    17321394
     1395
     1396/*
     1397 * IMUL
     1398 */
    17331399
    17341400IEM_DECL_IMPL_DEF(int, iemAImpl_imul_u64,(uint64_t *pu64RAX, uint64_t *pu64RDX, uint64_t u64Factor, uint32_t *pfEFlags))
     
    17891455
    17901456
     1457/*
     1458 * DIV
     1459 */
    17911460
    17921461IEM_DECL_IMPL_DEF(int, iemAImpl_div_u64,(uint64_t *pu64RAX, uint64_t *pu64RDX, uint64_t u64Divisor, uint32_t *pfEFlags))
     
    18261495}
    18271496
     1497
     1498/*
     1499 * IDIV
     1500 */
    18281501
    18291502IEM_DECL_IMPL_DEF(int, iemAImpl_idiv_u64,(uint64_t *pu64RAX, uint64_t *pu64RDX, uint64_t u64Divisor, uint32_t *pfEFlags))
     
    19131586
    19141587
     1588/*********************************************************************************************************************************
     1589*   Unary operations.                                                                                                            *
     1590*********************************************************************************************************************************/
     1591
     1592IEM_DECL_IMPL_DEF(void, iemAImpl_inc_u64,(uint64_t  *puDst,  uint32_t *pfEFlags))
     1593{
     1594    uint64_t uDst    = *puDst;
     1595    uint64_t uResult = uDst + 1;
     1596    *puDst = uResult;
     1597
     1598    /*
     1599     * Calc EFLAGS.
     1600     * CF is NOT modified for hysterical raisins (allegedly for carrying and
     1601     * borrowing in arithmetic loops on intel 8008).
     1602     */
     1603    uint32_t fEfl = *pfEFlags & ~(X86_EFL_STATUS_BITS & ~X86_EFL_CF);
     1604    fEfl |= g_afParity[uResult & 0xff];
     1605    fEfl |= ((uint32_t)uResult ^ (uint32_t)uDst) & X86_EFL_AF;
     1606    fEfl |= X86_EFL_CALC_ZF(uResult);
     1607    fEfl |= X86_EFL_CALC_SF(uResult, 64);
     1608    fEfl |= (((uDst ^ RT_BIT_64(63)) & uResult) >> (64 - X86_EFL_OF_BIT)) & X86_EFL_OF;
     1609    *pfEFlags = fEfl;
     1610}
     1611
     1612
     1613IEM_DECL_IMPL_DEF(void, iemAImpl_dec_u64,(uint64_t  *puDst,  uint32_t *pfEFlags))
     1614{
     1615    uint64_t uDst    = *puDst;
     1616    uint64_t uResult = uDst - 1;
     1617    *puDst = uResult;
     1618
     1619    /*
     1620     * Calc EFLAGS.
     1621     * CF is NOT modified for hysterical raisins (allegedly for carrying and
     1622     * borrowing in arithmetic loops on intel 8008).
     1623     */
     1624    uint32_t fEfl = *pfEFlags & ~(X86_EFL_STATUS_BITS & ~X86_EFL_CF);
     1625    fEfl |= g_afParity[uResult & 0xff];
     1626    fEfl |= ((uint32_t)uResult ^ (uint32_t)uDst) & X86_EFL_AF;
     1627    fEfl |= X86_EFL_CALC_ZF(uResult);
     1628    fEfl |= X86_EFL_CALC_SF(uResult, 64);
     1629    fEfl |= ((uDst & (uResult ^ RT_BIT_64(63))) >> (64 - X86_EFL_OF_BIT)) & X86_EFL_OF;
     1630    *pfEFlags = fEfl;
     1631}
     1632
     1633
     1634IEM_DECL_IMPL_DEF(void, iemAImpl_not_u64,(uint64_t  *puDst,  uint32_t *pfEFlags))
     1635{
     1636    uint64_t uDst    = *puDst;
     1637    uint64_t uResult = ~uDst;
     1638    *puDst = uResult;
     1639    /* EFLAGS are not modified. */
     1640    RT_NOREF_PV(pfEFlags);
     1641}
     1642
     1643
     1644IEM_DECL_IMPL_DEF(void, iemAImpl_neg_u64,(uint64_t  *puDst,  uint32_t *pfEFlags))
     1645{
     1646    uint64_t uDst    = 0;
     1647    uint64_t uSrc    = *puDst;
     1648    uint64_t uResult = uDst - uSrc;
     1649    *puDst = uResult;
     1650
     1651    /* Calc EFLAGS. */
     1652    uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS;
     1653    fEfl |= (uSrc != 0) << X86_EFL_CF_BIT;
     1654    fEfl |= g_afParity[uResult & 0xff];
     1655    fEfl |= ((uint32_t)uResult ^ (uint32_t)uDst) & X86_EFL_AF;
     1656    fEfl |= X86_EFL_CALC_ZF(uResult);
     1657    fEfl |= X86_EFL_CALC_SF(uResult, 64);
     1658    fEfl |= ((uSrc & uResult) >> (64 - X86_EFL_OF_BIT)) & X86_EFL_OF;
     1659    *pfEFlags = fEfl;
     1660}
     1661
     1662
     1663/** 64-bit locked unary operand operation. */
     1664# define DO_LOCKED_UNARY_OP_U64(a_Mnemonic) \
     1665    do { \
     1666        uint64_t uOld = ASMAtomicReadU64(puDst); \
     1667        uint64_t uTmp; \
     1668        uint32_t fEflTmp; \
     1669        do \
     1670        { \
     1671            uTmp = uOld; \
     1672            fEflTmp = *pfEFlags; \
     1673            iemAImpl_ ## a_Mnemonic ## _u64(&uTmp, &fEflTmp); \
     1674        } while (!ASMAtomicCmpXchgExU64(puDst, uTmp, uOld, &uOld)); \
     1675        *pfEFlags = fEflTmp; \
     1676    } while (0)
     1677
     1678IEM_DECL_IMPL_DEF(void, iemAImpl_inc_u64_locked,(uint64_t  *puDst,  uint32_t *pfEFlags))
     1679{
     1680    DO_LOCKED_UNARY_OP_U64(inc);
     1681}
     1682
     1683
     1684IEM_DECL_IMPL_DEF(void, iemAImpl_dec_u64_locked,(uint64_t  *puDst,  uint32_t *pfEFlags))
     1685{
     1686    DO_LOCKED_UNARY_OP_U64(dec);
     1687}
     1688
     1689
     1690IEM_DECL_IMPL_DEF(void, iemAImpl_not_u64_locked,(uint64_t  *puDst,  uint32_t *pfEFlags))
     1691{
     1692    DO_LOCKED_UNARY_OP_U64(not);
     1693}
     1694
     1695
     1696IEM_DECL_IMPL_DEF(void, iemAImpl_neg_u64_locked,(uint64_t  *puDst,  uint32_t *pfEFlags))
     1697{
     1698    DO_LOCKED_UNARY_OP_U64(neg);
     1699}
     1700
     1701
     1702/* Shift and rotate. */
     1703
     1704IEM_DECL_IMPL_DEF(void, iemAImpl_rol_u64,(uint64_t *puDst, uint8_t cShift, uint32_t *pfEFlags))
     1705{
     1706    cShift &= 63;
     1707    if (cShift)
     1708    {
     1709        uint64_t uDst = *puDst;
     1710        uint64_t uResult;
     1711        uResult  = uDst << cShift;
     1712        uResult |= uDst >> (64 - cShift);
     1713        *puDst = uResult;
     1714
     1715        /* Calc EFLAGS.  The OF bit is undefined if cShift > 1, we implement
     1716           it the same way as for 1 bit shifts. */
     1717        AssertCompile(X86_EFL_CF_BIT == 0);
     1718        uint32_t fEfl   = *pfEFlags & ~(X86_EFL_CF | X86_EFL_OF);
     1719        uint32_t fCarry = (uResult & 1);
     1720        fEfl |= fCarry;
     1721        fEfl |= ((uResult >> 63) ^ fCarry) << X86_EFL_OF_BIT;
     1722        *pfEFlags = fEfl;
     1723    }
     1724}
     1725
     1726
     1727IEM_DECL_IMPL_DEF(void, iemAImpl_ror_u64,(uint64_t *puDst, uint8_t cShift, uint32_t *pfEFlags))
     1728{
     1729    cShift &= 63;
     1730    if (cShift)
     1731    {
     1732        uint64_t uDst = *puDst;
     1733        uint64_t uResult;
     1734        uResult  = uDst >> cShift;
     1735        uResult |= uDst << (64 - cShift);
     1736        *puDst = uResult;
     1737
     1738        /* Calc EFLAGS.  The OF bit is undefined if cShift > 1, we implement
     1739           it the same way as for 1 bit shifts (OF = OF XOR New-CF). */
     1740        AssertCompile(X86_EFL_CF_BIT == 0);
     1741        uint32_t fEfl   = *pfEFlags & ~(X86_EFL_CF | X86_EFL_OF);
     1742        uint32_t fCarry = (uResult >> 63) & X86_EFL_CF;
     1743        fEfl |= fCarry;
     1744        fEfl |= (((uResult >> 62) ^ fCarry) << X86_EFL_OF_BIT) & X86_EFL_OF;
     1745        *pfEFlags = fEfl;
     1746    }
     1747}
     1748
     1749
     1750IEM_DECL_IMPL_DEF(void, iemAImpl_rcl_u64,(uint64_t *puDst, uint8_t cShift, uint32_t *pfEFlags))
     1751{
     1752    cShift &= 63;
     1753    if (cShift)
     1754    {
     1755        uint32_t fEfl = *pfEFlags;
     1756        uint64_t uDst = *puDst;
     1757        uint64_t uResult;
     1758        uResult = uDst << cShift;
     1759        AssertCompile(X86_EFL_CF_BIT == 0);
     1760        if (cShift > 1)
     1761            uResult |= uDst >> (65 - cShift);
     1762        uResult |= (uint64_t)(fEfl & X86_EFL_CF) << (cShift - 1);
     1763        *puDst = uResult;
     1764
     1765        /* Calc EFLAGS.  The OF bit is undefined if cShift > 1, we implement
     1766           it the same way as for 1 bit shifts. */
     1767        uint32_t fCarry = (uDst >> (64 - cShift)) & X86_EFL_CF;
     1768        fEfl &= ~(X86_EFL_CF | X86_EFL_OF);
     1769        fEfl |= fCarry;
     1770        fEfl |= ((uResult >> 63) ^ fCarry) << X86_EFL_OF_BIT;
     1771        *pfEFlags = fEfl;
     1772    }
     1773}
     1774
     1775
     1776IEM_DECL_IMPL_DEF(void, iemAImpl_rcr_u64,(uint64_t *puDst, uint8_t cShift, uint32_t *pfEFlags))
     1777{
     1778    cShift &= 63;
     1779    if (cShift)
     1780    {
     1781        uint32_t fEfl = *pfEFlags;
     1782        uint64_t uDst = *puDst;
     1783        uint64_t uResult;
     1784        uResult  = uDst >> cShift;
     1785        AssertCompile(X86_EFL_CF_BIT == 0);
     1786        if (cShift > 1)
     1787            uResult |= uDst << (65 - cShift);
     1788        uResult |= (uint64_t)(fEfl & X86_EFL_CF) << (64 - cShift);
     1789        *puDst = uResult;
     1790
     1791        /* Calc EFLAGS.  The OF bit is undefined if cShift > 1, we implement
     1792           it the same way as for 1 bit shifts. */
     1793        uint32_t fCarry = (uDst >> (cShift - 1)) & X86_EFL_CF;
     1794        fEfl &= ~(X86_EFL_CF | X86_EFL_OF);
     1795        fEfl |= fCarry;
     1796        fEfl |= ((uResult >> 63) ^ fCarry) << X86_EFL_OF_BIT;
     1797        *pfEFlags = fEfl;
     1798    }
     1799}
     1800
     1801
     1802IEM_DECL_IMPL_DEF(void, iemAImpl_shl_u64,(uint64_t *puDst, uint8_t cShift, uint32_t *pfEFlags))
     1803{
     1804    cShift &= 63;
     1805    if (cShift)
     1806    {
     1807        uint64_t uDst = *puDst;
     1808        uint64_t uResult = uDst << cShift;
     1809        *puDst = uResult;
     1810
     1811        /* Calc EFLAGS.  The OF bit is undefined if cShift > 1, we implement
     1812           it the same way as for 1 bit shifts.  The AF bit is undefined, we
     1813           always set it to zero atm. */
     1814        AssertCompile(X86_EFL_CF_BIT == 0);
     1815        uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS;
     1816        uint32_t fCarry = (uDst >> (64 - cShift)) & X86_EFL_CF;
     1817        fEfl |= fCarry;
     1818        fEfl |= ((uResult >> 63) ^ fCarry) << X86_EFL_OF_BIT;
     1819        fEfl |= X86_EFL_CALC_SF(uResult, 64);
     1820        fEfl |= X86_EFL_CALC_ZF(uResult);
     1821        fEfl |= g_afParity[uResult & 0xff];
     1822        *pfEFlags = fEfl;
     1823    }
     1824}
     1825
     1826
     1827IEM_DECL_IMPL_DEF(void, iemAImpl_shr_u64,(uint64_t *puDst, uint8_t cShift, uint32_t *pfEFlags))
     1828{
     1829    cShift &= 63;
     1830    if (cShift)
     1831    {
     1832        uint64_t uDst = *puDst;
     1833        uint64_t uResult = uDst >> cShift;
     1834        *puDst = uResult;
     1835
     1836        /* Calc EFLAGS.  The OF bit is undefined if cShift > 1, we implement
     1837           it the same way as for 1 bit shifts.  The AF bit is undefined, we
     1838           always set it to zero atm. */
     1839        AssertCompile(X86_EFL_CF_BIT == 0);
     1840        uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS;
     1841        fEfl |= (uDst >> (cShift - 1)) & X86_EFL_CF;
     1842        fEfl |= (uDst >> 63) << X86_EFL_OF_BIT;
     1843        fEfl |= X86_EFL_CALC_SF(uResult, 64);
     1844        fEfl |= X86_EFL_CALC_ZF(uResult);
     1845        fEfl |= g_afParity[uResult & 0xff];
     1846        *pfEFlags = fEfl;
     1847    }
     1848}
     1849
     1850
     1851IEM_DECL_IMPL_DEF(void, iemAImpl_sar_u64,(uint64_t *puDst, uint8_t cShift, uint32_t *pfEFlags))
     1852{
     1853    cShift &= 63;
     1854    if (cShift)
     1855    {
     1856        uint64_t uDst = *puDst;
     1857        uint64_t uResult = (int64_t)uDst >> cShift;
     1858        *puDst = uResult;
     1859
     1860        /* Calc EFLAGS.  The OF bit is undefined if cShift > 1, we implement
     1861           it the same way as for 1 bit shifts (0).  The AF bit is undefined,
     1862           we always set it to zero atm. */
     1863        AssertCompile(X86_EFL_CF_BIT == 0);
     1864        uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS;
     1865        fEfl |= (uDst >> (cShift - 1)) & X86_EFL_CF;
     1866        fEfl |= X86_EFL_CALC_SF(uResult, 64);
     1867        fEfl |= X86_EFL_CALC_ZF(uResult);
     1868        fEfl |= g_afParity[uResult & 0xff];
     1869        *pfEFlags = fEfl;
     1870    }
     1871}
     1872
     1873
     1874IEM_DECL_IMPL_DEF(void, iemAImpl_shld_u64,(uint64_t *puDst, uint64_t uSrc, uint8_t cShift, uint32_t *pfEFlags))
     1875{
     1876    cShift &= 63;
     1877    if (cShift)
     1878    {
     1879        uint64_t uDst = *puDst;
     1880        uint64_t uResult;
     1881        uResult  = uDst << cShift;
     1882        uResult |= uSrc >> (64 - cShift);
     1883        *puDst = uResult;
     1884
     1885        /* Calc EFLAGS.  The OF bit is undefined if cShift > 1, we implement
     1886           it the same way as for 1 bit shifts.  The AF bit is undefined,
     1887           we always set it to zero atm. */
     1888        AssertCompile(X86_EFL_CF_BIT == 0);
     1889        uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS;
     1890        fEfl |= (uDst >> (64 - cShift)) & X86_EFL_CF;
     1891        fEfl |= (uint32_t)((uDst >> 63) ^ (uint32_t)(uResult >> 63)) << X86_EFL_OF_BIT;
     1892        fEfl |= X86_EFL_CALC_SF(uResult, 64);
     1893        fEfl |= X86_EFL_CALC_ZF(uResult);
     1894        fEfl |= g_afParity[uResult & 0xff];
     1895        *pfEFlags = fEfl;
     1896    }
     1897}
     1898
     1899
     1900IEM_DECL_IMPL_DEF(void, iemAImpl_shrd_u64,(uint64_t *puDst, uint64_t uSrc, uint8_t cShift, uint32_t *pfEFlags))
     1901{
     1902    cShift &= 63;
     1903    if (cShift)
     1904    {
     1905        uint64_t uDst = *puDst;
     1906        uint64_t uResult;
     1907        uResult  = uDst >> cShift;
     1908        uResult |= uSrc << (64 - cShift);
     1909        *puDst = uResult;
     1910
     1911        /* Calc EFLAGS.  The OF bit is undefined if cShift > 1, we implement
     1912           it the same way as for 1 bit shifts.  The AF bit is undefined,
     1913           we always set it to zero atm. */
     1914        AssertCompile(X86_EFL_CF_BIT == 0);
     1915        uint32_t fEfl = *pfEFlags & ~X86_EFL_STATUS_BITS;
     1916        fEfl |= (uDst >> (cShift - 1)) & X86_EFL_CF;
     1917        fEfl |= (uint32_t)((uDst >> 63) ^ (uint32_t)(uResult >> 63)) << X86_EFL_OF_BIT;
     1918        fEfl |= X86_EFL_CALC_SF(uResult, 64);
     1919        fEfl |= X86_EFL_CALC_ZF(uResult);
     1920        fEfl |= g_afParity[uResult & 0xff];
     1921        *pfEFlags = fEfl;
     1922    }
     1923}
     1924
     1925
    19151926#endif /* !RT_ARCH_AMD64 || IEM_WITHOUT_ASSEMBLY */
    19161927
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