Skip to content

Conversation

@amessier
Copy link
Contributor

This PR adds support for SysV ABI (which is used by Linux) to the x64 backend emitter. See #1339 and #803 for previous PRs related to this PR. While I reused some commits from those PRs, it was mainly for some of the trivial fixes. For the SysV ABI support itself, since there was issues in Release mode (as seen in #1339), I started from a clean page.

I decided to use a function that returns the register for a given index. That function is implemented differently per ABI (Windows or SysV) at compile time using defines.

Commit 2b9764d is similar to a change made in #1339 (bb9820a). Basically, for m128 values, clang would pass them by value in xmm registers, but the thunk expects arguments passed in general purpose registers (GPRs) only. By changing the functions to pass by reference, it forces clang to pass them in the GPRs.

As for the fixes in Release mode, there are two commits.

  • First, fe2b719 fixes stack corruption. I'm pretty sure the fix is valid, but would certainly require review from others.
  • As for a14ed35 this was required with GCC to ensure proper initialization of sequence_table before being used by the other files. I went with the method of including the other files in the main module, but I'm definitively open to other suggestions.

Finally the last commit in this PR (7a7d17e) is a fix for an issue in the filesystem code, seen when trying to start a .xex (now that we can get to that point).

With these changes, xenia-cpu-ppc-tests passes on Linux. Xenia also starts and you can try to start a .xex.

I tested those changes on Windows too by running xenia-cpu-ppc-tests only (can't start a game on that machine).

Copy link
Member

@gibbed gibbed left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please bump the copyright year in all of the files you've touched.

uytvbn and others added 10 commits May 24, 2022 00:36
va_list are not guarenteed to maintain their values after being used.
With clang on Linux, args is undefined after fetching length and will print
"(null)".
Copy args into another va_list before getting length to prevent this.
Add tests.
Instead of hardcoding the native registers used for the thunks, create a
function that will return, given an index, the corresponding native
register.

This will make it easier to support different native ABI.
Use offsets from the StackLayout::Thunk structure, instead of hardcoded
offset values.

No functional change.
Add support for the SysV ABI in the x64 emitter backend by using the
appropriate registers for argument passing.

Since the SysV ABI has less preserved registers than the Microsoft x64
ABI, reduce by 2 the number of General Purpose Registers (GPR) available
to the emitter, so they can be used for the Context and Membase saved
registers.
To access the stack at adresses higher than the stack pointer, it
must be moved down (subtracted) before the accesses. If not, the stack
pointer still points to the previous stack frame, corrupting it.

This fixes a crash on Linux when compiled in release mode with clang.
Clang passes m128 arguments in xmm registers, which breaks the guest to
host thunk assumption that arguments are only in general-purpose
registers (rsi/rdx/rcx).

Pass arguments by reference to make Clang generate code compatible with
the assumptions made in the thunk.
Currently, sequences are in separate compilation units, but their
constructors all share the same unordered_map, which is in one of the
compilation unit.

Due to that, when compiling using GCC with LTO enabled, the constructor of
some units is called before the constructor of the unit with the map, also
called 'Static Initialization Order Fiasco'
(see: https://en.cppreference.com/w/cpp/language/siof). Thus, the
map is not initialized, which causes a division-by-zero error (SIGFPE).

Fix this by converting the files that contain specific sequences to be
includable in the main file. This way all sequences are in the same
compilation unit and guarantees the map is initialized.
When listing all files in a folder, ignore hidden files (which start
with a dot). This prevents parsing ".." as a folder to enter, thus going
back one level and entering an infinite loop of folders to parse.
@amessier
Copy link
Contributor Author

Please bump the copyright year in all of the files you've touched.

I've edited the commits to update the copyright year where applicable.

I also forgot to mention in the original PR message that to support the different ABI, I chose to reduce the number of GPR available to the emitter, since in SysV there are fewer preserved registers available. I assume the emitter can handle the reduced number of registers. There is probably a better way to do this (one that has the same number of registers as on Windows) but for now this seems to work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants