Reconstructs an x64 context from the input thread's state, packed into a regular ARM64 context following the ARM64EC register mapping
| 458 | |
| 459 | // Reconstructs an x64 context from the input thread's state, packed into a regular ARM64 context following the ARM64EC register mapping |
| 460 | static ARM64_NT_CONTEXT StoreStateToPackedECContext(FEXCore::Core::InternalThreadState* Thread, uint32_t FPCR, uint32_t FPSR) { |
| 461 | ARM64_NT_CONTEXT ECContext {}; |
| 462 | |
| 463 | ECContext.ContextFlags = CONTEXT_ARM64_FULL; |
| 464 | if (CPUFeatures->IsFeaturePresent(PF_AVX2_INSTRUCTIONS_AVAILABLE)) { |
| 465 | // This is a FEX extension and requires corresponding wine-side patches to be of use, however it is harmless to set |
| 466 | // even if those patches are not used. |
| 467 | ECContext.ContextFlags |= CONTEXT_ARM64_FEX_YMMSTATE; |
| 468 | } |
| 469 | |
| 470 | auto& State = Thread->CurrentFrame->State; |
| 471 | |
| 472 | ECContext.X8 = State.gregs[FEXCore::X86State::REG_RAX]; |
| 473 | ECContext.X0 = State.gregs[FEXCore::X86State::REG_RCX]; |
| 474 | ECContext.X1 = State.gregs[FEXCore::X86State::REG_RDX]; |
| 475 | ECContext.X27 = State.gregs[FEXCore::X86State::REG_RBX]; |
| 476 | ECContext.Sp = State.gregs[FEXCore::X86State::REG_RSP]; |
| 477 | ECContext.Fp = State.gregs[FEXCore::X86State::REG_RBP]; |
| 478 | ECContext.X25 = State.gregs[FEXCore::X86State::REG_RSI]; |
| 479 | ECContext.X26 = State.gregs[FEXCore::X86State::REG_RDI]; |
| 480 | ECContext.X2 = State.gregs[FEXCore::X86State::REG_R8]; |
| 481 | ECContext.X3 = State.gregs[FEXCore::X86State::REG_R9]; |
| 482 | ECContext.X4 = State.gregs[FEXCore::X86State::REG_R10]; |
| 483 | ECContext.X5 = State.gregs[FEXCore::X86State::REG_R11]; |
| 484 | ECContext.X19 = State.gregs[FEXCore::X86State::REG_R12]; |
| 485 | ECContext.X20 = State.gregs[FEXCore::X86State::REG_R13]; |
| 486 | ECContext.X21 = State.gregs[FEXCore::X86State::REG_R14]; |
| 487 | ECContext.X22 = State.gregs[FEXCore::X86State::REG_R15]; |
| 488 | |
| 489 | ECContext.Pc = State.rip; |
| 490 | |
| 491 | CTX->ReconstructXMMRegisters(Thread, reinterpret_cast<__uint128_t*>(&ECContext.V[0]), reinterpret_cast<__uint128_t*>(&ECContext.V[16])); |
| 492 | |
| 493 | ECContext.Lr = State.mm[0][0]; |
| 494 | ECContext.X6 = State.mm[1][0]; |
| 495 | ECContext.X7 = State.mm[2][0]; |
| 496 | ECContext.X9 = State.mm[3][0]; |
| 497 | ECContext.X16 = (State.mm[3][1] & 0xffff) << 48 | (State.mm[2][1] & 0xffff) << 32 | (State.mm[1][1] & 0xffff) << 16 | (State.mm[0][1] & 0xffff); |
| 498 | ECContext.X10 = State.mm[4][0]; |
| 499 | ECContext.X11 = State.mm[5][0]; |
| 500 | ECContext.X12 = State.mm[6][0]; |
| 501 | ECContext.X15 = State.mm[7][0]; |
| 502 | ECContext.X17 = (State.mm[7][1] & 0xffff) << 48 | (State.mm[6][1] & 0xffff) << 32 | (State.mm[5][1] & 0xffff) << 16 | (State.mm[4][1] & 0xffff); |
| 503 | |
| 504 | // Zero all disallowed registers |
| 505 | ECContext.X13 = 0; |
| 506 | ECContext.X14 = 0; |
| 507 | ECContext.X18 = 0; |
| 508 | ECContext.X23 = 0; |
| 509 | ECContext.X24 = 0; |
| 510 | ECContext.X28 = 0; |
| 511 | |
| 512 | // NZCV+SS will be converted into EFlags by ntdll, the rest are lost during exception handling. |
| 513 | // See HandleGuestException |
| 514 | uint32_t EFlags = CTX->ReconstructCompactedEFLAGS(Thread, false, nullptr, 0); |
| 515 | ECContext.Cpsr = 0; |
| 516 | ECContext.Cpsr |= (EFlags & (1U << FEXCore::X86State::RFLAG_TF_RAW_LOC)) ? (1U << 21) : 0; |
| 517 | ECContext.Cpsr |= (EFlags & (1U << FEXCore::X86State::RFLAG_OF_RAW_LOC)) ? (1U << 28) : 0; |
no test coverage detected