| 595 | void BTCpuProcessTerm(HANDLE Handle, BOOL After, ULONG Status) {} |
| 596 | |
| 597 | void BTCpuThreadInit() { |
| 598 | static constexpr size_t DefaultWow64CS {4}; |
| 599 | std::scoped_lock Lock(ThreadCreationMutex); |
| 600 | FEX::Windows::InitCRTThread(); |
| 601 | auto* Thread = CTX->CreateThread(0, 0); |
| 602 | |
| 603 | // Default segment setup. |
| 604 | auto Frame = Thread->CurrentFrame; |
| 605 | auto NewSegments = new FEXCore::Core::CPUState::gdt_segment[32](); |
| 606 | |
| 607 | // Setup initial code-segment GDT |
| 608 | auto& GDT = NewSegments[DefaultWow64CS]; |
| 609 | FEXCore::Core::CPUState::SetGDTBase(&GDT, 0); |
| 610 | FEXCore::Core::CPUState::SetGDTLimit(&GDT, 0xF'FFFFU); |
| 611 | GDT.L = 0; // L = Long Mode = 32-bit |
| 612 | GDT.D = 1; // D = Default Operand Size = 32-bit |
| 613 | |
| 614 | Frame->State.segment_arrays[FEXCore::Core::CPUState::SEGMENT_ARRAY_INDEX_GDT] = &NewSegments[0]; |
| 615 | // TODO: LDTs are currently unsupported, mirror them to GDT. |
| 616 | Frame->State.segment_arrays[FEXCore::Core::CPUState::SEGMENT_ARRAY_INDEX_LDT] = &NewSegments[0]; |
| 617 | |
| 618 | Frame->State.cs_idx = DefaultWow64CS << 3; |
| 619 | Frame->State.cs_cached = FEXCore::Core::CPUState::CalculateGDTBase(GDT); |
| 620 | |
| 621 | FEX::Windows::CallRetStack::InitializeThread(Thread); |
| 622 | |
| 623 | auto TLS = GetTLS(); |
| 624 | TLS.ThreadState() = Thread; |
| 625 | TLS.ControlWord().fetch_or(ControlBits::WOW_CPU_AREA_DIRTY, std::memory_order::relaxed); |
| 626 | |
| 627 | auto ThreadTID = GetCurrentThreadId(); |
| 628 | Threads.emplace(ThreadTID, Thread); |
| 629 | if (StatAllocHandler) { |
| 630 | Thread->ThreadStats = StatAllocHandler->AllocateSlot(ThreadTID); |
| 631 | } |
| 632 | } |
| 633 | |
| 634 | void BTCpuThreadTerm(HANDLE Thread, LONG ExitCode) { |
| 635 | if (!FEX::Windows::ValidateHandleAccess(Thread, THREAD_TERMINATE)) { |
nothing calls this directly
no test coverage detected