/** ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** * Copyright 2022 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include "xenia/base/logging.h" #include "xenia/cpu/ppc/ppc_frontend.h" #include "xenia/cpu/processor.h" #include "xenia/kernel/kernel_state.h" #include "xenia/kernel/util/shim_utils.h" #include "xenia/kernel/xboxkrnl/xboxkrnl_private.h" #include "xenia/kernel/xthread.h" #include "xenia/xbox.h" namespace xe { namespace kernel { namespace xboxkrnl { void KeEnableFpuExceptions_entry( const ppc_context_t& ctx) { // dword_t enabled) { // TODO(benvanik): can we do anything about exceptions? // theres a lot more thats supposed to happen here, the floating point state // has to be saved to kthread, the irql changes, the machine state register is // changed to enable exceptions X_KTHREAD* kthread = ctx->TranslateVirtual( ctx->TranslateVirtualGPR(ctx->r[13])->prcb_data.current_thread); 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) 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! } //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, kImplemented); #endif static qword_result_t KeQueryInterruptTime_entry(const ppc_context_t& ctx) { auto kstate = ctx->kernel_state; uint32_t ts_bundle = kstate->GetKeTimestampBundle(); X_TIME_STAMP_BUNDLE* bundle = ctx->TranslateVirtual(ts_bundle); return xe::load_and_swap(&bundle->interrupt_time); } DECLARE_XBOXKRNL_EXPORT1(KeQueryInterruptTime, kNone, kImplemented); } // namespace xboxkrnl } // namespace kernel } // namespace xe DECLARE_XBOXKRNL_EMPTY_REGISTER_EXPORTS(Misc);