| 1302 | } |
| 1303 | |
| 1304 | void Decoder::DecodeInstructionsAtEntry(FEXCore::Core::InternalThreadState *Thread, const uint8_t* _InstStream, uint64_t PC, uint64_t MaxInst) { |
| 1305 | FEXCORE_PROFILE_SCOPED("DecodeInstructions"); |
| 1306 | BlockInfo.TotalInstructionCount = 0; |
| 1307 | BlockInfo.Blocks.clear(); |
| 1308 | VisitedBlocks.clear(); |
| 1309 | // Reset internal state management |
| 1310 | DecodedSize = 0; |
| 1311 | MaxCondBranchForward = 0; |
| 1312 | MaxCondBranchBackwards = ~0ULL; |
| 1313 | DecodedBuffer = PoolObject.ReownOrClaimBuffer(); |
| 1314 | |
| 1315 | // Decode operating mode from thread's CS segment. |
| 1316 | const auto CSSegment = Core::CPUState::GetSegmentFromIndex(Thread->CurrentFrame->State, Thread->CurrentFrame->State.cs_idx); |
| 1317 | BlockInfo.Is64BitMode = CSSegment->L == 1; |
| 1318 | LOGMAN_THROW_A_FMT(BlockInfo.Is64BitMode == CTX->Config.Is64BitMode, "Expected operating mode to not change at runtime!"); |
| 1319 | |
| 1320 | // XXX: Load symbol data |
| 1321 | SymbolAvailable = false; |
| 1322 | EntryPoint = PC; |
| 1323 | BlockInfo.EntryPoints = {PC}; |
| 1324 | InstStream = _InstStream; |
| 1325 | |
| 1326 | uint64_t TotalInstructions {}; |
| 1327 | |
| 1328 | // If we don't have symbols available then we become a bit optimistic about multiblock ranges |
| 1329 | if (!SymbolAvailable) { |
| 1330 | // If we don't have a symbol available then assume all branches are valid for multiblock |
| 1331 | SymbolMaxAddress = SectionMaxAddress; |
| 1332 | SymbolMinAddress = EntryPoint; |
| 1333 | } |
| 1334 | |
| 1335 | DecodedMinAddress = EntryPoint; |
| 1336 | DecodedMaxAddress = EntryPoint; |
| 1337 | |
| 1338 | // Entry is a jump target |
| 1339 | BlocksToDecode = {PC}; |
| 1340 | |
| 1341 | uint64_t CurrentCodePage = PC & FEXCore::Utils::FEX_PAGE_MASK; |
| 1342 | |
| 1343 | BlockInfo.CodePages = {CurrentCodePage}; |
| 1344 | |
| 1345 | if (MaxInst == 0) { |
| 1346 | MaxInst = CTX->Config.MaxInstPerBlock; |
| 1347 | } |
| 1348 | |
| 1349 | bool EntryBlock {true}; |
| 1350 | bool FinalInstruction {false}; |
| 1351 | |
| 1352 | while (!FinalInstruction && !BlocksToDecode.empty()) { |
| 1353 | auto BlockDecodeIt = BlocksToDecode.begin(); |
| 1354 | uint64_t RIPToDecode = *BlockDecodeIt; |
| 1355 | BlocksToDecode.erase(BlockDecodeIt); |
| 1356 | VisitedBlocks.emplace(RIPToDecode); |
| 1357 | |
| 1358 | auto BlockSuccIt = std::lower_bound(BlockInfo.Blocks.begin(), BlockInfo.Blocks.end(), RIPToDecode, |
| 1359 | [](const auto& a, uint64_t Address) { return a.Entry < Address; }); |
| 1360 | |
| 1361 | LOGMAN_THROW_A_FMT(BlockSuccIt == BlockInfo.Blocks.end() || BlockSuccIt->Entry != RIPToDecode, "unexpected"); |
no test coverage detected