This function in both JITs is only ever called by passing the JIT's code
buffer into it. Given this is already accessible, since the functions
are part of the respective JIT class, we can just remove this parameter.
This also cleans up accesses with the new code buffer, as we don't need
to do janky looking dereference-then-index expressions.
This class effectively acted as a "discount vector", that would simply
allocate memory and then delete it in the destructor when it goes out of
scope.
We can just use a std::vector directly to reduce this boilerplate.
PowerPC.h at this point is pretty much a general glob of stuff, and it's
unfortunate, since it means pulling in a lot of unrelated header
dependencies and a bunch of other things that don't need to be seen by
things that just want to read memory.
Breaking this out into its own header keeps all the MMU-related stuff
together and also limits the amount of header dependencies being
included (the primary motivation for this being the former reason).
Paired single (ps) instructions can call asm_routines that try to update
PowerPC::ppcState.pc. At the time the asm_routine is built, emulation has
not started and the PC is invalid (0). If the ps instruction causes an
exception (e.g. DSI), SRR0 gets clobbered with the invalid PC.
This change makes the relevant ps instructions store PC before calling out
to asm_routines, and prevents the asm_routine from trying to store PC
itself.
Moves the codebuffer access variables closer to their first use, and
gets rid of multiple indexing expressions. We already know which op
we're accessing in particular, so just make a reference to it and access
it instead of duplicating the expression all over the place.
If we don't flush the values, they persist in the register cache,
potentially resulting in the values being out of sync with PPCSTATE.
This was causing random crashes in games, mainly booting, when certain
JIT instructions were disabled, or forced to fall back to interpreter.
Gets rid of the need to construct UReg_MSR values around the the actual
member in order to query information from it (without using shifts and
masks). This makes it more concise in some areas, while helping with
readability in some other places (such as copying the ILE bit to the LE
bit in the exception checking functions).
The game Go Vacation (SGVEAF) currently stutters a lot because it keeps
overflowing the far code cache and all code needs to be re-jitted.
Logging this warning gives a useful hint as to what is causing the
stuttering.
These are bit manipulation functions, so they belong within BitUtils.
This also gets rid of duplicated code and avoids relying on compiler
reserved names existing or not existing to determine whether or not we
define a set of functions.
Optimizers are smart enough in GCC and clang to transform the code to a
ROR or ROL instruction in the respective functions.
ori can be used as a NOP if the two register operands are the same, and
the immediate is zero, not only if the two register operands are r0.
Also removes the check for !inst.Rc, as ori only has one encoding, and
said encoding doesn't even have a record bit in it.
With this, JitAsm code doesn't have any reliance on the JIT global
variable. This means the core JIT64 code no longer relies on said
global at all. The Jit64 common code, however, still has some offenders.
Notably, EmuCodeBlock and Jit64AsmCommon are the remaining places in the
common code that make use of the global variable.
Within Cleanup(), it is called at *every* end of the block. This generates bigger code,
but it is the only way to handle blocks with multiple exit nodes.
to get bigger, breaking an optimization. This forces the emitter to use a
32bit pointer instead of an 8bit one, fixing the issue at the expense of
efficiency.
struct GekkoOPTemplate was implemented differently in different
compilation units, which breaks the ODR and could end up causing issues
as symbols exported from one compilation unit could end up being used by
another even if they have different implementations.
This puts them in an anonymous namespace, restricting any generated
symbols to the single compilation unit.