[Kernel] Added KeSaveFloatingPointState and KeRestoreFloatingPointState from nukernel
This commit is contained in:
committed by
Radosław Gliński
parent
ec18a89da4
commit
80f2b535e9
@@ -28,94 +28,28 @@ void KeEnableFpuExceptions_entry(
|
|||||||
kthread->fpu_exceptions_on = static_cast<uint32_t>(ctx->r[3]) != 0;
|
kthread->fpu_exceptions_on = static_cast<uint32_t>(ctx->r[3]) != 0;
|
||||||
}
|
}
|
||||||
DECLARE_XBOXKRNL_EXPORT1(KeEnableFpuExceptions, kNone, kStub);
|
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<X_KPCR*>(ctx->r[13])->prcb_data.current_thread);
|
||||||
|
|
||||||
static uint64_t Do_mfmsr(ppc_context_t& ctx) {
|
for (size_t i = 0; i < xe::countof(ctx->f); ++i) {
|
||||||
auto frontend = ctx->thread_state->processor()->frontend();
|
kthread->fpu_context[i] = ctx->f[i];
|
||||||
cpu::ppc::CheckGlobalLock(
|
|
||||||
ctx, reinterpret_cast<void*>(&xe::global_critical_region::mutex()),
|
|
||||||
reinterpret_cast<void*>(&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<unsigned int>(ctx->r[13]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
r13_struct_t* st = memory->TranslateVirtual<r13_struct_t*>(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!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//should do mfmsr here
|
|
||||||
|
|
||||||
unsigned int r3 = xe::load_and_swap<unsigned int>(&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<fpucontext_ptr_t*>(r3);
|
|
||||||
xe::store_and_swap<uint64_t>(&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<unsigned short>(&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<X_KPCR*>(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) {
|
static qword_result_t KeQueryInterruptTime_entry(const ppc_context_t& ctx) {
|
||||||
auto kstate = ctx->kernel_state;
|
auto kstate = ctx->kernel_state;
|
||||||
uint32_t ts_bundle = kstate->GetKeTimestampBundle();
|
uint32_t ts_bundle = kstate->GetKeTimestampBundle();
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ void XThread::InitializeGuestObject() {
|
|||||||
guest_thread->stack_limit = (this->stack_limit_);
|
guest_thread->stack_limit = (this->stack_limit_);
|
||||||
guest_thread->stack_kernel = (this->stack_base_ - 240);
|
guest_thread->stack_kernel = (this->stack_base_ - 240);
|
||||||
guest_thread->tls_address = (this->tls_dynamic_address_);
|
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 =
|
uint32_t process_info_block_address =
|
||||||
creation_params_.guest_process ? creation_params_.guest_process
|
creation_params_.guest_process ? creation_params_.guest_process
|
||||||
: this->kernel_state_->GetTitleProcess();
|
: this->kernel_state_->GetTitleProcess();
|
||||||
@@ -244,7 +244,8 @@ void XThread::InitializeGuestObject() {
|
|||||||
guest_thread->last_error = 0;
|
guest_thread->last_error = 0;
|
||||||
guest_thread->unk_154.blink_ptr = v9 + 340;
|
guest_thread->unk_154.blink_ptr = v9 + 340;
|
||||||
guest_thread->creation_flags = this->creation_params_.creation_flags;
|
guest_thread->creation_flags = this->creation_params_.creation_flags;
|
||||||
guest_thread->unk_17C = 1;
|
// According to nukernel.
|
||||||
|
// guest_thread->host_xthread_stash = reinterpret_cast<void*>(this);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* not doing this right at all! we're not using our threads context, because
|
* not doing this right at all! we're not using our threads context, because
|
||||||
|
|||||||
@@ -338,11 +338,33 @@ struct X_KTHREAD {
|
|||||||
xe::be<uint32_t> fiber_ptr; // 0x164
|
xe::be<uint32_t> fiber_ptr; // 0x164
|
||||||
uint8_t unk_168[0x4]; // 0x168
|
uint8_t unk_168[0x4]; // 0x168
|
||||||
xe::be<uint32_t> creation_flags; // 0x16C
|
xe::be<uint32_t> creation_flags; // 0x16C
|
||||||
uint8_t unk_170[0xC]; // 0x170
|
|
||||||
xe::be<uint32_t> 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<double> fpscr; // 0x980
|
||||||
|
xe::be<double> fpu_context[32]; // 0x988
|
||||||
|
|
||||||
|
XAPC unk_A88; // 0xA88
|
||||||
};
|
};
|
||||||
static_assert_size(X_KTHREAD, 0xAB0);
|
static_assert_size(X_KTHREAD, 0xAB0);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user