Files
Xenia-Canary/src/xenia/cpu/ppc/ppc_context.h
chss95cs@gmail.com 457296850e Add OPCODE_NEGATED_MUL_ADD/OPCODE_NEGATED_MUL_SUB
Proper handling of nans for VMX max/min on x64 (minps/maxps has special behavior depending on the operand order that vmx does not have for vminfp/vmaxfp)
Add extremely unintrusive guest code profiler utilizing KUSER_SHARED systemtime. This profiler is disabled on platforms other than windows, and on windows is disabled by default by a cvar
Repurpose GUEST_SCRATCH64 stack offset to instead be for storing guest function profile times, define GUEST_SCRATCH as 0 instead, since thats already meant to be a scratch area
Fix xenia silently closing on config errors/other fatal errors by setting has_console_attached_'s default to false
Add alternative code path for guest clock that uses kusershared systemtime instead of QueryPerformanceCounter. This is way faster and I have tested it and found it to be working, but i have disabled it because i do not know how well it works on wine or on processors other than mine
Significantly reduce log spam by setting XELOGAPU and XELOGGPU to be LogLevel::Debug
Changed some LOGI to LOGD in places to reduce log spam
Mark VdSwap as kHighFrequency, it was spamming up logs
Make logging calls less intrusive for the caller by forcing the test of log level inline and moving the format/AppendLogLine stuff to an outlined cold function
Add swcache namespace for software cache operations like prefetches, streaming stores and streaming loads.
Add XE_MSVC_REORDER_BARRIER for preventing msvc from propagating a value too close to its store or from its load
Add xe_unlikely_mutex for locks we know have very little contention
add XE_HOST_CACHE_LINE_SIZE and XE_RESTRICT to platform.h
Microoptimization: Changed most uses of size_t to ring_size_t in RingBuffer, this reduces the size of the inlined ringbuffer operations slightly by eliminating rex prefixes, depending on register allocation
Add BeginPrefetchedRead to ringbuffer, which prefetches the second range if there is one according to the provided PrefetchTag
added inline_loadclock cvar, which will directly use the value of the guest clock from clock.cc in jitted guest code. off by default
change uses of GUEST_SCRATCH64 to GUEST_SCRATCH
Add fast vectorized xenos_half_to_float/xenos_float_to_half (currently resides in x64_seq_vector, move to gpu code maybe at some point)
Add fast x64 codegen for PackFloat16_4/UnpackFloat16_4. Same code can be used for Float16_2 in future commit. This should speed up some games that use these functions heavily
Remove cvar for toggling old float16 behavior
Add VRSAVE register, support mfspr/mtspr vrsave
Add cvar for toggling off codegen for trap instructions and set it to true by default.
Add specialized methods to CommandProcessor: WriteRegistersFromMem, WriteRegisterRangeFromRing, and WriteOneRegisterFromRing. These reduce the overall cost of WriteRegister
Use a fixed size vmem vector for upload ranges, realloc/memsetting on resize  in the inner loop of requestranges was showing up on the profiler (the search in requestranges itself needs work)
Rename fixed_vmem_vector to better fit xenia's naming convention
Only log unknown register writes in WriteRegister if DEBUG :/. We're stuck on MSVC with c++17 so we have no way of influencing the branch ordering for that function without profile guided optimization
Remove binding stride assert in shader_translator.cc, triangle told me its leftover ogl stuff
Mark xe::FatalError as noreturn
If a controller is not connected, delay by 1.1 seconds before checking if it has been reconnected. Asking Xinput about a controller slot that is unused is extremely slow, and XinputGetState/SetState were taking up
an enormous amount of time in profiles. this may have caused a bit of input lag
Protect accesses to input_system with a lock
Add proper handling for user_index>= 4 in XamInputGetState/SetState, properly return zeroed state in GetState
Add missing argument to NtQueryVirtualMemory_entry
Fixed RtlCompareMemoryUlong_entry, it actually does not care if the source is misaligned, and for length it aligns down
Fixed RtlUpperChar and RtlLowerChar, added a table that has their correct return values precomputed
2022-08-20 11:40:19 -07:00

445 lines
9.3 KiB
C++

/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2020 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_CPU_PPC_PPC_CONTEXT_H_
#define XENIA_CPU_PPC_PPC_CONTEXT_H_
#include <cstdint>
#include <mutex>
#include <string>
#include "xenia/base/mutex.h"
#include "xenia/base/vec128.h"
namespace xe {
namespace cpu {
class Processor;
class ThreadState;
} // namespace cpu
namespace kernel {
class KernelState;
} // namespace kernel
} // namespace xe
namespace xe {
namespace cpu {
namespace ppc {
// Map:
// 0-31: GPR
// 32-63: FPR
// 64: LR
// 65: CTR
// 66: XER
// 67: FPSCR
// 68: VSCR
// 69-76: CR0-7
// 100: invalid
// 128-256: VR
enum class PPCRegister {
kR0 = 0,
kR1,
kR2,
kR3,
kR4,
kR5,
kR6,
kR7,
kR8,
kR9,
kR10,
kR11,
kR12,
kR13,
kR14,
kR15,
kR16,
kR17,
kR18,
kR19,
kR20,
kR21,
kR22,
kR23,
kR24,
kR25,
kR26,
kR27,
kR28,
kR29,
kR30,
kR31,
kFR0 = 32,
kFR1,
kFR2,
kFR3,
kFR4,
kFR5,
kFR6,
kFR7,
kFR8,
kFR9,
kFR10,
kFR11,
kFR12,
kFR13,
kFR14,
kFR15,
kFR16,
kFR17,
kFR18,
kFR19,
kFR20,
kFR21,
kFR22,
kFR23,
kFR24,
kFR25,
kFR26,
kFR27,
kFR28,
kFR29,
kFR30,
kFR31,
kVR0 = 64,
kVR1,
kVR2,
kVR3,
kVR4,
kVR5,
kVR6,
kVR7,
kVR8,
kVR9,
kVR10,
kVR11,
kVR12,
kVR13,
kVR14,
kVR15,
kVR16,
kVR17,
kVR18,
kVR19,
kVR20,
kVR21,
kVR22,
kVR23,
kVR24,
kVR25,
kVR26,
kVR27,
kVR28,
kVR29,
kVR30,
kVR31,
kVR32,
kVR33,
kVR34,
kVR35,
kVR36,
kVR37,
kVR38,
kVR39,
kVR40,
kVR41,
kVR42,
kVR43,
kVR44,
kVR45,
kVR46,
kVR47,
kVR48,
kVR49,
kVR50,
kVR51,
kVR52,
kVR53,
kVR54,
kVR55,
kVR56,
kVR57,
kVR58,
kVR59,
kVR60,
kVR61,
kVR62,
kVR63,
kVR64,
kVR65,
kVR66,
kVR67,
kVR68,
kVR69,
kVR70,
kVR71,
kVR72,
kVR73,
kVR74,
kVR75,
kVR76,
kVR77,
kVR78,
kVR79,
kVR80,
kVR81,
kVR82,
kVR83,
kVR84,
kVR85,
kVR86,
kVR87,
kVR88,
kVR89,
kVR90,
kVR91,
kVR92,
kVR93,
kVR94,
kVR95,
kVR96,
kVR97,
kVR98,
kVR99,
kVR100,
kVR101,
kVR102,
kVR103,
kVR104,
kVR105,
kVR106,
kVR107,
kVR108,
kVR109,
kVR110,
kVR111,
kVR112,
kVR113,
kVR114,
kVR115,
kVR116,
kVR117,
kVR118,
kVR119,
kVR120,
kVR121,
kVR122,
kVR123,
kVR124,
kVR125,
kVR126,
kVR127,
kVR128,
kLR,
kCTR,
kXER,
kFPSCR,
kVSCR,
kCR,
};
#pragma pack(push, 8)
typedef struct alignas(64) PPCContext_s {
union {
uint32_t value;
struct {
uint8_t cr0_lt; // Negative (LT) - result is negative
uint8_t cr0_gt; // Positive (GT) - result is positive (and not zero)
uint8_t cr0_eq; // Zero (EQ) - result is zero or a stwcx/stdcx completed
// successfully
uint8_t cr0_so; // Summary Overflow (SO) - copy of XER[SO]
};
} cr0; // 0xA24
union {
uint32_t value;
struct {
uint8_t cr1_fx; // FP exception summary - copy of FPSCR[FX]
uint8_t cr1_fex; // FP enabled exception summary - copy of FPSCR[FEX]
uint8_t
cr1_vx; // FP invalid operation exception summary - copy of FPSCR[VX]
uint8_t cr1_ox; // FP overflow exception - copy of FPSCR[OX]
};
} cr1;
union {
uint32_t value;
struct {
uint8_t cr2_0;
uint8_t cr2_1;
uint8_t cr2_2;
uint8_t cr2_3;
};
} cr2;
union {
uint32_t value;
struct {
uint8_t cr3_0;
uint8_t cr3_1;
uint8_t cr3_2;
uint8_t cr3_3;
};
} cr3;
union {
uint32_t value;
struct {
uint8_t cr4_0;
uint8_t cr4_1;
uint8_t cr4_2;
uint8_t cr4_3;
};
} cr4;
union {
uint32_t value;
struct {
uint8_t cr5_0;
uint8_t cr5_1;
uint8_t cr5_2;
uint8_t cr5_3;
};
} cr5;
union {
uint32_t value;
struct {
uint8_t cr6_all_equal;
uint8_t cr6_1;
uint8_t cr6_none_equal;
uint8_t cr6_3;
};
} cr6;
union {
uint32_t value;
struct {
uint8_t cr7_0;
uint8_t cr7_1;
uint8_t cr7_2;
uint8_t cr7_3;
};
} cr7;
union {
uint32_t value;
struct {
uint32_t rn : 2; // FP rounding control: 00 = nearest
// 01 = toward zero
// 10 = toward +infinity
// 11 = toward -infinity
uint32_t ni : 1; // Floating-point non-IEEE mode
uint32_t xe : 1; // IEEE floating-point inexact exception enable
uint32_t ze : 1; // IEEE floating-point zero divide exception enable
uint32_t ue : 1; // IEEE floating-point underflow exception enable
uint32_t oe : 1; // IEEE floating-point overflow exception enable
uint32_t ve : 1; // FP invalid op exception enable
uint32_t vxcvi : 1; // FP invalid op exception: invalid integer convert
// -- sticky
uint32_t vxsqrt : 1; // FP invalid op exception: invalid sqrt -- sticky
uint32_t vxsoft : 1; // FP invalid op exception: software request
// -- sticky
uint32_t reserved : 1;
uint32_t fprf_un : 1; // FP result unordered or NaN (FU or ?)
uint32_t fprf_eq : 1; // FP result equal or zero (FE or =)
uint32_t fprf_gt : 1; // FP result greater than or positive (FG or >)
uint32_t fprf_lt : 1; // FP result less than or negative (FL or <)
uint32_t fprf_c : 1; // FP result class
uint32_t fi : 1; // FP fraction inexact
uint32_t fr : 1; // FP fraction rounded
uint32_t vxvc : 1; // FP invalid op exception: invalid compare --
// sticky
uint32_t vximz : 1; // FP invalid op exception: infinity * 0 -- sticky
uint32_t vxzdz : 1; // FP invalid op exception: 0 / 0 -- sticky
uint32_t vxidi : 1; // FP invalid op exception: infinity / infinity
// -- sticky
uint32_t vxisi : 1; // FP invalid op exception: infinity - infinity
// -- sticky
uint32_t vxsnan : 1; // FP invalid op exception: SNaN -- sticky
uint32_t
xx : 1; // FP inexact exception -- sticky
uint32_t
zx : 1; // FP zero divide exception -- sticky
uint32_t
ux : 1; // FP underflow exception -- sticky
uint32_t
ox : 1; // FP overflow exception -- sticky
uint32_t vx : 1; // FP invalid operation exception summary
uint32_t fex : 1; // FP enabled exception summary
uint32_t
fx : 1; // FP exception summary -- sticky
} bits;
} fpscr; // Floating-point status and control register
// Most frequently used registers first.
uint64_t r[32]; // 0x20 General purpose registers
uint64_t ctr; // 0x18 Count register
uint64_t lr; // 0x10 Link register
double f[32]; // 0x120 Floating-point registers
vec128_t v[128]; // 0x220 VMX128 vector registers
vec128_t vscr_vec;
// XER register:
// Split to make it easier to do individual updates.
uint8_t xer_ca;
uint8_t xer_ov;
uint8_t xer_so;
// Condition registers:
// These are split to make it easier to do DCE on unused stores.
uint64_t cr() const;
void set_cr(uint64_t value);
// todo: remove, saturation should be represented by a vector
uint8_t vscr_sat;
uint32_t vrsave;
// uint32_t get_fprf() {
// return fpscr.value & 0x000F8000;
// }
// void set_fprf(const uint32_t v) {
// fpscr.value = (fpscr.value & ~0x000F8000) | v;
// }
// Thread ID assigned to this context.
uint32_t thread_id;
// Global interrupt lock, held while interrupts are disabled or interrupts are
// executing. This is shared among all threads and comes from the processor.
global_mutex_type* global_mutex;
// Used to shuttle data into externs. Contents volatile.
uint64_t scratch;
// Processor-specific data pointer. Used on callbacks to get access to the
// current runtime and its data.
Processor* processor;
// Shared kernel state, for easy access from kernel exports.
xe::kernel::KernelState* kernel_state;
uint8_t* physical_membase;
// Value of last reserved load
uint64_t reserved_val;
ThreadState* thread_state;
uint8_t* virtual_membase;
static std::string GetRegisterName(PPCRegister reg);
std::string GetStringFromValue(PPCRegister reg) const;
void SetValueFromString(PPCRegister reg, std::string value);
void SetRegFromString(const char* name, const char* value);
bool CompareRegWithString(const char* name, const char* value,
std::string& result) const;
} PPCContext;
#pragma pack(pop)
constexpr size_t ppcctx_size = sizeof(PPCContext);
static_assert(sizeof(PPCContext) % 64 == 0, "64b padded");
} // namespace ppc
} // namespace cpu
} // namespace xe
#endif // XENIA_CPU_PPC_PPC_CONTEXT_H_