diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_misc.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_misc.cc index 1689c9486..7222c5713 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_misc.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_misc.cc @@ -28,94 +28,28 @@ void KeEnableFpuExceptions_entry( kthread->fpu_exceptions_on = static_cast(ctx->r[3]) != 0; } DECLARE_XBOXKRNL_EXPORT1(KeEnableFpuExceptions, kNone, kStub); -#if 0 -struct __declspec(align(8)) fpucontext_ptr_t { - char unknown_data[158]; - __int16 field_9E; - char field_A0[2272]; - unsigned __int64 saved_FPSCR; - double saved_fpu_regs[32]; -}; -#pragma pack(push, 1) -struct __declspec(align(1)) r13_struct_t { - char field_0[6]; - __int16 field_6; - char field_8[2]; - char field_A; - char field_B[5]; - int field_10; - char field_14[315]; - char field_14F; - unsigned int field_150; - char field_154[427]; - char field_2FF; - char field_300; -}; -#pragma pack(pop) +void KeSaveFloatingPointState_entry(const ppc_context_t& ctx) { + // Probably we should use: thread_fpu_related to store/restore state + X_KTHREAD* kthread = ctx->TranslateVirtual( + ctx->TranslateVirtualGPR(ctx->r[13])->prcb_data.current_thread); -static uint64_t Do_mfmsr(ppc_context_t& ctx) { - auto frontend = ctx->thread_state->processor()->frontend(); - cpu::ppc::CheckGlobalLock( - ctx, reinterpret_cast(&xe::global_critical_region::mutex()), - reinterpret_cast(&frontend->builtins()->global_lock_count)); - return ctx->scratch; -} - -void KeSaveFloatingPointState_entry(ppc_context_t& ctx) { - xe::Memory* memory = ctx->thread_state->memory(); - unsigned int r13 = static_cast(ctx->r[13]); - - - - - r13_struct_t* st = memory->TranslateVirtual(r13); - /* - lwz r10, 0x150(r13) - lbz r11, 0xA(r13) - tweqi r10, 0 - twnei r11, 0 - */ - - unsigned int r10 = st->field_150; - unsigned char r11 = st->field_A; - - if (r10 == 0 || r11 != 0) { - //trap! + for (size_t i = 0; i < xe::countof(ctx->f); ++i) { + kthread->fpu_context[i] = ctx->f[i]; } - - //should do mfmsr here - - unsigned int r3 = xe::load_and_swap(&st->field_10); - - //too much work to do the mfmsr/mtmsr stuff right now - int to_store = -2049; - xe::store_and_swap(&st->field_10, (unsigned int)to_store); - xe::store_and_swap(&st->field_6, (short)to_store); - - - - if (r3 != ~0u) { - fpucontext_ptr_t* fpucontext = - memory->TranslateVirtual(r3); - xe::store_and_swap(&fpucontext->saved_FPSCR, ctx->fpscr.value); - - for (unsigned int i = 0; i < 32; ++i) { - xe::store_and_swap(&fpucontext->saved_fpu_regs[i], ctx->f[i]); - } - xe::store_and_swap(&fpucontext->field_9E, 0xD7FF); - } - ctx->processor->backend()->SetGuestRoundingMode(ctx.value(), 0); - ctx->fpscr.value = 0; - st->field_A = 1; - - xe::store_and_swap(&st->field_10, r13 + 0x300); - ctx->r[3] = r3; - } +DECLARE_XBOXKRNL_EXPORT1(KeSaveFloatingPointState, kNone, kSketchy); + +void KeRestoreFloatingPointState_entry(const ppc_context_t& ctx) { + const X_KTHREAD* kthread = ctx->TranslateVirtual( + ctx->TranslateVirtualGPR(ctx->r[13])->prcb_data.current_thread); + + for (size_t i = 0; i < xe::countof(ctx->f); ++i) { + ctx->f[i] = kthread->fpu_context[i]; + } +} +DECLARE_XBOXKRNL_EXPORT1(KeRestoreFloatingPointState, kNone, kSketchy); -DECLARE_XBOXKRNL_EXPORT1(KeSaveFloatingPointState, kNone, kImplemented); -#endif static qword_result_t KeQueryInterruptTime_entry(const ppc_context_t& ctx) { auto kstate = ctx->kernel_state; uint32_t ts_bundle = kstate->GetKeTimestampBundle(); diff --git a/src/xenia/kernel/xthread.cc b/src/xenia/kernel/xthread.cc index cc7d90c2e..2c20076b3 100644 --- a/src/xenia/kernel/xthread.cc +++ b/src/xenia/kernel/xthread.cc @@ -199,7 +199,7 @@ void XThread::InitializeGuestObject() { guest_thread->stack_limit = (this->stack_limit_); guest_thread->stack_kernel = (this->stack_base_ - 240); guest_thread->tls_address = (this->tls_dynamic_address_); - guest_thread->thread_state = 0; + guest_thread->thread_state = KTHREAD_STATE_INITIALIZED; uint32_t process_info_block_address = creation_params_.guest_process ? creation_params_.guest_process : this->kernel_state_->GetTitleProcess(); @@ -244,7 +244,8 @@ void XThread::InitializeGuestObject() { guest_thread->last_error = 0; guest_thread->unk_154.blink_ptr = v9 + 340; guest_thread->creation_flags = this->creation_params_.creation_flags; - guest_thread->unk_17C = 1; + // According to nukernel. + // guest_thread->host_xthread_stash = reinterpret_cast(this); /* * not doing this right at all! we're not using our threads context, because diff --git a/src/xenia/kernel/xthread.h b/src/xenia/kernel/xthread.h index 527e549c5..a40fe3b64 100644 --- a/src/xenia/kernel/xthread.h +++ b/src/xenia/kernel/xthread.h @@ -338,11 +338,33 @@ struct X_KTHREAD { xe::be fiber_ptr; // 0x164 uint8_t unk_168[0x4]; // 0x168 xe::be creation_flags; // 0x16C - uint8_t unk_170[0xC]; // 0x170 - xe::be unk_17C; // 0x17C - uint8_t unk_180[0x930]; // 0x180 - // This struct is actually quite long... so uh, not filling this out! + // we handle context differently from a native kernel, so we can stash extra + // data here! the first 8 bytes of vscr are unused anyway + union { + vec128_t vscr; // 0x170 + struct { + void* host_xthread_stash; + uintptr_t vscr_remainder; + }; + }; + + union { + // 2048 bytes + vec128_t vmx_context[128]; // 0x180 + struct { + // 1536 bytes + X_KWAIT_BLOCK scratch_waitblock_memory[65]; + // space for some more data! + uint32_t kernel_aux_stack_base_; + uint32_t kernel_aux_stack_current_; + uint32_t kernel_aux_stack_limit_; + }; + }; + xe::be fpscr; // 0x980 + xe::be fpu_context[32]; // 0x988 + + XAPC unk_A88; // 0xA88 }; static_assert_size(X_KTHREAD, 0xAB0);