The linkage_arm code of the new_dynarec on arm currently uses TEXTREL
to patch some addresses during dynamic linking. This is not to be
expected because the code is compiled as position independent code.
Instead the access of global variables must also be position
independent in this part of the code. But indirect access through the
global offset table would require extra memory loads and use additional
registers. Furtunately, GOT can be avoided here by using PC relative
addresses. This is possible because linkage_asm.S only accesses global
variables inside the current shared object. The linker can calculate
the relative positions during compile time and only a single extra
"add" instruction is required to calculate the final address from the
PC relative offset.
The linkage_arm code of the new_dynarec on arm currently uses TEXTREL
to patch some addresses during dynamic linking. This is not to be
expected because the code is compiled as position independent code.
Instead the access of global variables must also be position
independent in this part of the code. But indirect access through the
global offset table would require extra memory loads and use additional
registers. Furtunately, GOT can be avoided here by using PC relative
addresses. This is possible because linkage_asm.S only accesses global
variables inside the current shared object. The linker can calculate
the relative positions during compile time and only a single extra
"add" instruction is required to calculate the final address from the
PC relative offset.
cp1.c now contains update_x86_rounding_mode, which is used by CTC1 and
the code that loads saved states. The rounding_mode variable also gets
a new code comment explaining why it's there with the size it has.
This commit may make the Hacktarux JIT/x86, Hacktarux JIT/amd64 and
New Dynarec/x86 more compatible with games that often switch rounding
modes and require correct results, even after reloading a saved state.
This affects global variables 'round_mode' (not to be confused with
'rounding_mode', which is a variable containing the latest rounding
mode at run time), 'trunc_mode', 'floor_mode' and 'ceil_mode'. They
are placed into the following files instead:
* src/r4300/new_dynarec/x86/assem_x86.c (uses rounding_modes, which
already existed);
* src/r4300/x86/gcop1.c;
* src/r4300/x86-64/gcop1.c.
Using 'rounding_mode' has two main problems:
- 'rounding_mode' is used by the Hacktarux JIT for x86 and x86-64 and
is in the format expected by those processors. This creates coupling
between the interpreter and the Hacktarux JIT.
- 'rounding_mode' is updated by the CTC1 opcode, but not by loading a
saved state. If a saved state is loaded, and its FCR31 rounding mode
bits differ from those currently being used, it takes another CTC1
for 'rounding_mode' to be updated, but FCR31 is updated immediately.
This commit may make the interpreters more compatible with games that
often switch rounding modes and require correct results.
This fixes the performance regression which affects Gauntlet Legend
when played with the old dynarec. The regression has been introduced
in commit 36a1c4fff7.