@@ -1246,6 +1246,117 @@ intx::uint512 LLILEmulator::EvalExpr(const LowLevelILInstruction& expr)
12461246 case LLIL_LOW_PART :
12471247 return MaskToSize (EvalExpr (expr.GetRawOperandAsExpr (0 )), sz);
12481248
1249+ // --- Bit operations ---
1250+ case LLIL_BSWAP :
1251+ {
1252+ // Reverse the byte order of the sz-byte value.
1253+ intx::uint512 val = MaskToSize (EvalExpr (expr.GetRawOperandAsExpr (0 )), sz);
1254+ intx::uint512 result (0 );
1255+ for (size_t i = 0 ; i < sz; i++)
1256+ {
1257+ intx::uint512 byte = (val >> (8 * i)) & intx::uint512 (0xff );
1258+ result |= byte << (8 * (sz - 1 - i));
1259+ }
1260+ return result;
1261+ }
1262+
1263+ case LLIL_POPCNT :
1264+ {
1265+ intx::uint512 val = MaskToSize (EvalExpr (expr.GetRawOperandAsExpr (0 )), sz);
1266+ uint64_t count = 0 ;
1267+ for (size_t i = 0 ; i < sz * 8 ; i++)
1268+ if (((val >> i) & intx::uint512 (1 )) != 0 )
1269+ count++;
1270+ return intx::uint512 (count);
1271+ }
1272+
1273+ case LLIL_CLZ :
1274+ {
1275+ // Count leading zero bits; clz(0) == 8 * size.
1276+ intx::uint512 val = MaskToSize (EvalExpr (expr.GetRawOperandAsExpr (0 )), sz);
1277+ size_t bits = sz * 8 ;
1278+ uint64_t count = 0 ;
1279+ for (size_t i = bits; i-- > 0 ;)
1280+ {
1281+ if (((val >> i) & intx::uint512 (1 )) != 0 )
1282+ break ;
1283+ count++;
1284+ }
1285+ return intx::uint512 (count);
1286+ }
1287+
1288+ case LLIL_CTZ :
1289+ {
1290+ // Count trailing zero bits; ctz(0) == 8 * size.
1291+ intx::uint512 val = MaskToSize (EvalExpr (expr.GetRawOperandAsExpr (0 )), sz);
1292+ size_t bits = sz * 8 ;
1293+ uint64_t count = 0 ;
1294+ for (size_t i = 0 ; i < bits; i++)
1295+ {
1296+ if (((val >> i) & intx::uint512 (1 )) != 0 )
1297+ break ;
1298+ count++;
1299+ }
1300+ return intx::uint512 (count);
1301+ }
1302+
1303+ case LLIL_RBIT :
1304+ {
1305+ // Reverse the bit order of the sz-byte value.
1306+ intx::uint512 val = MaskToSize (EvalExpr (expr.GetRawOperandAsExpr (0 )), sz);
1307+ size_t bits = sz * 8 ;
1308+ intx::uint512 result (0 );
1309+ for (size_t i = 0 ; i < bits; i++)
1310+ if (((val >> i) & intx::uint512 (1 )) != 0 )
1311+ result |= intx::uint512 (1 ) << (bits - 1 - i);
1312+ return result;
1313+ }
1314+
1315+ case LLIL_CLS :
1316+ {
1317+ // Count leading sign bits: number of bits below the sign bit that match it.
1318+ intx::uint512 val = MaskToSize (EvalExpr (expr.GetRawOperandAsExpr (0 )), sz);
1319+ size_t bits = sz * 8 ;
1320+ intx::uint512 sign = (val >> (bits - 1 )) & intx::uint512 (1 );
1321+ uint64_t count = 0 ;
1322+ for (size_t i = bits - 1 ; i-- > 0 ;)
1323+ {
1324+ if (((val >> i) & intx::uint512 (1 )) != sign)
1325+ break ;
1326+ count++;
1327+ }
1328+ return intx::uint512 (count);
1329+ }
1330+
1331+ case LLIL_ABS :
1332+ {
1333+ // Signed absolute value; abs(INT_MIN) == INT_MIN.
1334+ intx::uint512 val = MaskToSize (EvalExpr (expr.GetRawOperandAsExpr (0 )), sz);
1335+ size_t bits = sz * 8 ;
1336+ bool neg = ((val >> (bits - 1 )) & intx::uint512 (1 )) != 0 ;
1337+ return neg ? MaskToSize (~val + 1 , sz) : val;
1338+ }
1339+
1340+ case LLIL_MINS :
1341+ case LLIL_MAXS :
1342+ {
1343+ intx::uint512 left = MaskToSize (EvalExpr (expr.GetRawOperandAsExpr (0 )), sz);
1344+ intx::uint512 right = MaskToSize (EvalExpr (expr.GetRawOperandAsExpr (1 )), sz);
1345+ int64_t sl = static_cast <int64_t >(static_cast <uint64_t >(SignExtend (left, sz, 8 )));
1346+ int64_t sr = static_cast <int64_t >(static_cast <uint64_t >(SignExtend (right, sz, 8 )));
1347+ bool leftWins = (expr.operation == LLIL_MINS ) ? (sl <= sr) : (sl >= sr);
1348+ return leftWins ? left : right;
1349+ }
1350+
1351+ case LLIL_MINU :
1352+ case LLIL_MAXU :
1353+ {
1354+ intx::uint512 left = MaskToSize (EvalExpr (expr.GetRawOperandAsExpr (0 )), sz);
1355+ intx::uint512 right = MaskToSize (EvalExpr (expr.GetRawOperandAsExpr (1 )), sz);
1356+ bool leftWins = (expr.operation == LLIL_MINU ) ? (left <= right) : (left >= right);
1357+ return leftWins ? left : right;
1358+ }
1359+
12491360 // --- Comparisons ---
12501361 case LLIL_CMP_E :
12511362 {
0 commit comments