{"action":"created","issue":{"url":"https://api.github.com/repos/citra-emu/citra/issues/1088","labels_url":"https://api.github.com/repos/citra-emu/citra/issues/1088/labels{/name}","comments_url":"https://api.github.com/repos/citra-emu/citra/issues/1088/comments","events_url":"https://api.github.com/repos/citra-emu/citra/issues/1088/events","html_url":"https://github.com/citra-emu/citra/pull/1088","id":103906294,"number":1088,"title":"x64: Proper stack alignment in shader JIT function calls","user":{"login":"aroulin","id":5475997,"avatar_url":"https://avatars.githubusercontent.com/u/5475997?v=3","gravatar_id":"","url":"https://api.github.com/users/aroulin","html_url":"https://github.com/aroulin","followers_url":"https://api.github.com/users/aroulin/followers","following_url":"https://api.github.com/users/aroulin/following{/other_user}","gists_url":"https://api.github.com/users/aroulin/gists{/gist_id}","starred_url":"https://api.github.com/users/aroulin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aroulin/subscriptions","organizations_url":"https://api.github.com/users/aroulin/orgs","repos_url":"https://api.github.com/users/aroulin/repos","events_url":"https://api.github.com/users/aroulin/events{/privacy}","received_events_url":"https://api.github.com/users/aroulin/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":3,"created_at":"2015-08-30T07:48:20Z","updated_at":"2015-09-02T12:46:56Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/citra-emu/citra/pulls/1088","html_url":"https://github.com/citra-emu/citra/pull/1088","diff_url":"https://github.com/citra-emu/citra/pull/1088.diff","patch_url":"https://github.com/citra-emu/citra/pull/1088.patch"},"body":"Fixes misaligned stack when calling external functions from the shader JIT. Both the Win64 and the System V ABIs require a 16-byte aligned stack when calling a function.\r\n\r\n[Agner's Calling Conventions 5. Stack Alignment](http://www.agner.org/optimize/calling_conventions.pdf)\r\n    \r\n    The 64 bit systems keep the stack aligned by 16. The stack word size\r\n    is 8 bytes, but the stack must be aligned by 16 before any call instruction.\r\n    Consequently, the value of the stack pointer is always 8 modulo 16 at\r\n    the entry of a procedure.\r\n\r\n[System V ABI 3.2.2 The Stack Frame](http://www.x86-64.org/documentation/abi.pdf):\r\n\r\n    […], the value (%rsp + 8) is always a multiple of 16 when control \r\n    is transferred to the function entry point.\r\n\r\n[Win64 Software Conventions](https://msdn.microsoft.com/en-us/library/ew5tede7.aspx):\r\n\r\n    The stack will always be maintained 16-byte aligned, except \r\n    within the prolog (for example, after the return address is pushed)\r\n\r\nExternal functions are for the time being only used to emulate EX2 and LG2 instructions and these might be replaced in a near future with inline approximations. Nevertheless, it is certainly still useful to have a clean stack alignment system (and maybe geometry shader instructions will use external interpreter functions as a first step).\r\n\r\nThe list of registers to save is for now static. The next enhancement would be to have a register caching system that, additionally to cache registers, would keep track of which registers are currently in use and have to be saved.\r\n\r\nThe problem is fixed by using Dolphin's `ABI_{Push,Pop}RegistersAndAdjustStack` instead of `ABI_{Push,Pop}All{Caller,Callee}SavedRegsAndAdjustStack`. Dolphin's code is x64-only therefore the remaining x86 bits are removed from the ABI files.\r\n\r\nPrevious functions `ABI_{Push,Pop}All{Caller,Callee}SavedRegsAndAdjustStack` are removed because of multiple problems. One is that they don't make sure the stack is aligned as they just push **a hard-coded odd number of registers**. This can be misleading, for example the following will break the stack alignment:\r\n\r\n    // Function entry: stack pointer misaligned\r\n    ABI_PushAllCalleeSavedRegsAndAdjustStack();\r\n    // OK stack pointer is aligned\r\n    \r\n    // [...]\r\n    \r\n    // later we want to call a function so need to save caller-saved register\r\n    ABI_PushAllCallerSavedRegsAndAdjustStack();\r\n    // stack pointer is misaligned now !\r\n    CALL(myfunc); // calling with misaligned stack\r\n\r\nExample of a misaligned stack when emulating the EX2 shader instruction by calling `std::exp2` \r\n![misaligned_ex2_call](https://cloud.githubusercontent.com/assets/5475997/9566176/3f7b83d2-4efa-11e5-9aff-9ea9b0c2e470.png)"},"comment":{"url":"https://api.github.com/repos/citra-emu/citra/issues/comments/137062717","html_url":"https://github.com/citra-emu/citra/pull/1088#issuecomment-137062717","issue_url":"https://api.github.com/repos/citra-emu/citra/issues/1088","id":137062717,"user":{"login":"bunnei","id":6956688,"avatar_url":"https://avatars.githubusercontent.com/u/6956688?v=3","gravatar_id":"","url":"https://api.github.com/users/bunnei","html_url":"https://github.com/bunnei","followers_url":"https://api.github.com/users/bunnei/followers","following_url":"https://api.github.com/users/bunnei/following{/other_user}","gists_url":"https://api.github.com/users/bunnei/gists{/gist_id}","starred_url":"https://api.github.com/users/bunnei/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bunnei/subscriptions","organizations_url":"https://api.github.com/users/bunnei/orgs","repos_url":"https://api.github.com/users/bunnei/repos","events_url":"https://api.github.com/users/bunnei/events{/privacy}","received_events_url":"https://api.github.com/users/bunnei/received_events","type":"User","site_admin":false},"created_at":"2015-09-02T12:46:56Z","updated_at":"2015-09-02T12:46:56Z","body":"LGTM"}}