-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Support for SysV ABI in x64 emitter (and other fixes) #2018
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
gibbed
left a comment
There was a problem hiding this 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.
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.
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. |
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.
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).