Browse Source
Common/x64: remove legacy emitter and abi (#2504)
Common/x64: remove legacy emitter and abi (#2504)
These are not used any more since we moved shader JIT to xbyak.nce_cpp
committed by
Yuri Kunde Schlesner
6 changed files with 1 additions and 4202 deletions
-
5src/common/CMakeLists.txt
-
350src/common/x64/abi.cpp
-
58src/common/x64/abi.h
-
2583src/common/x64/emitter.cpp
-
1206src/common/x64/emitter.h
-
1src/video_core/shader/shader_jit_x64_compiler.h
@ -1,350 +0,0 @@ |
|||||
// Copyright (C) 2003 Dolphin Project.
|
|
||||
|
|
||||
// This program is free software: you can redistribute it and/or modify
|
|
||||
// it under the terms of the GNU General Public License as published by
|
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
|
||||
|
|
||||
// This program is distributed in the hope that it will be useful,
|
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||
// GNU General Public License 2.0 for more details.
|
|
||||
|
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
|
||||
// If not, see http://www.gnu.org/licenses/
|
|
||||
|
|
||||
// Official SVN repository and contact information can be found at
|
|
||||
// http://code.google.com/p/dolphin-emu/
|
|
||||
|
|
||||
#include "abi.h"
|
|
||||
#include "emitter.h"
|
|
||||
|
|
||||
using namespace Gen; |
|
||||
|
|
||||
// Shared code between Win64 and Unix64
|
|
||||
|
|
||||
void XEmitter::ABI_CalculateFrameSize(BitSet32 mask, size_t rsp_alignment, size_t needed_frame_size, |
|
||||
size_t* shadowp, size_t* subtractionp, size_t* xmm_offsetp) { |
|
||||
size_t shadow = 0; |
|
||||
#if defined(_WIN32)
|
|
||||
shadow = 0x20; |
|
||||
#endif
|
|
||||
|
|
||||
int count = (mask & ABI_ALL_GPRS).Count(); |
|
||||
rsp_alignment -= count * 8; |
|
||||
size_t subtraction = 0; |
|
||||
int fpr_count = (mask & ABI_ALL_FPRS).Count(); |
|
||||
if (fpr_count) { |
|
||||
// If we have any XMMs to save, we must align the stack here.
|
|
||||
subtraction = rsp_alignment & 0xf; |
|
||||
} |
|
||||
subtraction += 16 * fpr_count; |
|
||||
size_t xmm_base_subtraction = subtraction; |
|
||||
subtraction += needed_frame_size; |
|
||||
subtraction += shadow; |
|
||||
// Final alignment.
|
|
||||
rsp_alignment -= subtraction; |
|
||||
subtraction += rsp_alignment & 0xf; |
|
||||
|
|
||||
*shadowp = shadow; |
|
||||
*subtractionp = subtraction; |
|
||||
*xmm_offsetp = subtraction - xmm_base_subtraction; |
|
||||
} |
|
||||
|
|
||||
size_t XEmitter::ABI_PushRegistersAndAdjustStack(BitSet32 mask, size_t rsp_alignment, |
|
||||
size_t needed_frame_size) { |
|
||||
size_t shadow, subtraction, xmm_offset; |
|
||||
ABI_CalculateFrameSize(mask, rsp_alignment, needed_frame_size, &shadow, &subtraction, |
|
||||
&xmm_offset); |
|
||||
|
|
||||
for (int r : mask& ABI_ALL_GPRS) |
|
||||
PUSH((X64Reg)r); |
|
||||
|
|
||||
if (subtraction) |
|
||||
SUB(64, R(RSP), subtraction >= 0x80 ? Imm32((u32)subtraction) : Imm8((u8)subtraction)); |
|
||||
|
|
||||
for (int x : mask& ABI_ALL_FPRS) { |
|
||||
MOVAPD(MDisp(RSP, (int)xmm_offset), (X64Reg)(x - 16)); |
|
||||
xmm_offset += 16; |
|
||||
} |
|
||||
|
|
||||
return shadow; |
|
||||
} |
|
||||
|
|
||||
void XEmitter::ABI_PopRegistersAndAdjustStack(BitSet32 mask, size_t rsp_alignment, |
|
||||
size_t needed_frame_size) { |
|
||||
size_t shadow, subtraction, xmm_offset; |
|
||||
ABI_CalculateFrameSize(mask, rsp_alignment, needed_frame_size, &shadow, &subtraction, |
|
||||
&xmm_offset); |
|
||||
|
|
||||
for (int x : mask& ABI_ALL_FPRS) { |
|
||||
MOVAPD((X64Reg)(x - 16), MDisp(RSP, (int)xmm_offset)); |
|
||||
xmm_offset += 16; |
|
||||
} |
|
||||
|
|
||||
if (subtraction) |
|
||||
ADD(64, R(RSP), subtraction >= 0x80 ? Imm32((u32)subtraction) : Imm8((u8)subtraction)); |
|
||||
|
|
||||
for (int r = 15; r >= 0; r--) { |
|
||||
if (mask[r]) |
|
||||
POP((X64Reg)r); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// Common functions
|
|
||||
void XEmitter::ABI_CallFunction(const void* func) { |
|
||||
u64 distance = u64(func) - (u64(code) + 5); |
|
||||
if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) { |
|
||||
// Far call
|
|
||||
MOV(64, R(RAX), ImmPtr(func)); |
|
||||
CALLptr(R(RAX)); |
|
||||
} else { |
|
||||
CALL(func); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void XEmitter::ABI_CallFunctionC16(const void* func, u16 param1) { |
|
||||
MOV(32, R(ABI_PARAM1), Imm32((u32)param1)); |
|
||||
u64 distance = u64(func) - (u64(code) + 5); |
|
||||
if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) { |
|
||||
// Far call
|
|
||||
MOV(64, R(RAX), ImmPtr(func)); |
|
||||
CALLptr(R(RAX)); |
|
||||
} else { |
|
||||
CALL(func); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void XEmitter::ABI_CallFunctionCC16(const void* func, u32 param1, u16 param2) { |
|
||||
MOV(32, R(ABI_PARAM1), Imm32(param1)); |
|
||||
MOV(32, R(ABI_PARAM2), Imm32((u32)param2)); |
|
||||
u64 distance = u64(func) - (u64(code) + 5); |
|
||||
if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) { |
|
||||
// Far call
|
|
||||
MOV(64, R(RAX), ImmPtr(func)); |
|
||||
CALLptr(R(RAX)); |
|
||||
} else { |
|
||||
CALL(func); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void XEmitter::ABI_CallFunctionC(const void* func, u32 param1) { |
|
||||
MOV(32, R(ABI_PARAM1), Imm32(param1)); |
|
||||
u64 distance = u64(func) - (u64(code) + 5); |
|
||||
if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) { |
|
||||
// Far call
|
|
||||
MOV(64, R(RAX), ImmPtr(func)); |
|
||||
CALLptr(R(RAX)); |
|
||||
} else { |
|
||||
CALL(func); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void XEmitter::ABI_CallFunctionCC(const void* func, u32 param1, u32 param2) { |
|
||||
MOV(32, R(ABI_PARAM1), Imm32(param1)); |
|
||||
MOV(32, R(ABI_PARAM2), Imm32(param2)); |
|
||||
u64 distance = u64(func) - (u64(code) + 5); |
|
||||
if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) { |
|
||||
// Far call
|
|
||||
MOV(64, R(RAX), ImmPtr(func)); |
|
||||
CALLptr(R(RAX)); |
|
||||
} else { |
|
||||
CALL(func); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void XEmitter::ABI_CallFunctionCCC(const void* func, u32 param1, u32 param2, u32 param3) { |
|
||||
MOV(32, R(ABI_PARAM1), Imm32(param1)); |
|
||||
MOV(32, R(ABI_PARAM2), Imm32(param2)); |
|
||||
MOV(32, R(ABI_PARAM3), Imm32(param3)); |
|
||||
u64 distance = u64(func) - (u64(code) + 5); |
|
||||
if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) { |
|
||||
// Far call
|
|
||||
MOV(64, R(RAX), ImmPtr(func)); |
|
||||
CALLptr(R(RAX)); |
|
||||
} else { |
|
||||
CALL(func); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void XEmitter::ABI_CallFunctionCCP(const void* func, u32 param1, u32 param2, void* param3) { |
|
||||
MOV(32, R(ABI_PARAM1), Imm32(param1)); |
|
||||
MOV(32, R(ABI_PARAM2), Imm32(param2)); |
|
||||
MOV(64, R(ABI_PARAM3), ImmPtr(param3)); |
|
||||
u64 distance = u64(func) - (u64(code) + 5); |
|
||||
if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) { |
|
||||
// Far call
|
|
||||
MOV(64, R(RAX), ImmPtr(func)); |
|
||||
CALLptr(R(RAX)); |
|
||||
} else { |
|
||||
CALL(func); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void XEmitter::ABI_CallFunctionCCCP(const void* func, u32 param1, u32 param2, u32 param3, |
|
||||
void* param4) { |
|
||||
MOV(32, R(ABI_PARAM1), Imm32(param1)); |
|
||||
MOV(32, R(ABI_PARAM2), Imm32(param2)); |
|
||||
MOV(32, R(ABI_PARAM3), Imm32(param3)); |
|
||||
MOV(64, R(ABI_PARAM4), ImmPtr(param4)); |
|
||||
u64 distance = u64(func) - (u64(code) + 5); |
|
||||
if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) { |
|
||||
// Far call
|
|
||||
MOV(64, R(RAX), ImmPtr(func)); |
|
||||
CALLptr(R(RAX)); |
|
||||
} else { |
|
||||
CALL(func); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void XEmitter::ABI_CallFunctionP(const void* func, void* param1) { |
|
||||
MOV(64, R(ABI_PARAM1), ImmPtr(param1)); |
|
||||
u64 distance = u64(func) - (u64(code) + 5); |
|
||||
if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) { |
|
||||
// Far call
|
|
||||
MOV(64, R(RAX), ImmPtr(func)); |
|
||||
CALLptr(R(RAX)); |
|
||||
} else { |
|
||||
CALL(func); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void XEmitter::ABI_CallFunctionPA(const void* func, void* param1, const Gen::OpArg& arg2) { |
|
||||
MOV(64, R(ABI_PARAM1), ImmPtr(param1)); |
|
||||
if (!arg2.IsSimpleReg(ABI_PARAM2)) |
|
||||
MOV(32, R(ABI_PARAM2), arg2); |
|
||||
u64 distance = u64(func) - (u64(code) + 5); |
|
||||
if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) { |
|
||||
// Far call
|
|
||||
MOV(64, R(RAX), ImmPtr(func)); |
|
||||
CALLptr(R(RAX)); |
|
||||
} else { |
|
||||
CALL(func); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void XEmitter::ABI_CallFunctionPAA(const void* func, void* param1, const Gen::OpArg& arg2, |
|
||||
const Gen::OpArg& arg3) { |
|
||||
MOV(64, R(ABI_PARAM1), ImmPtr(param1)); |
|
||||
if (!arg2.IsSimpleReg(ABI_PARAM2)) |
|
||||
MOV(32, R(ABI_PARAM2), arg2); |
|
||||
if (!arg3.IsSimpleReg(ABI_PARAM3)) |
|
||||
MOV(32, R(ABI_PARAM3), arg3); |
|
||||
u64 distance = u64(func) - (u64(code) + 5); |
|
||||
if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) { |
|
||||
// Far call
|
|
||||
MOV(64, R(RAX), ImmPtr(func)); |
|
||||
CALLptr(R(RAX)); |
|
||||
} else { |
|
||||
CALL(func); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void XEmitter::ABI_CallFunctionPPC(const void* func, void* param1, void* param2, u32 param3) { |
|
||||
MOV(64, R(ABI_PARAM1), ImmPtr(param1)); |
|
||||
MOV(64, R(ABI_PARAM2), ImmPtr(param2)); |
|
||||
MOV(32, R(ABI_PARAM3), Imm32(param3)); |
|
||||
u64 distance = u64(func) - (u64(code) + 5); |
|
||||
if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) { |
|
||||
// Far call
|
|
||||
MOV(64, R(RAX), ImmPtr(func)); |
|
||||
CALLptr(R(RAX)); |
|
||||
} else { |
|
||||
CALL(func); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// Pass a register as a parameter.
|
|
||||
void XEmitter::ABI_CallFunctionR(const void* func, X64Reg reg1) { |
|
||||
if (reg1 != ABI_PARAM1) |
|
||||
MOV(32, R(ABI_PARAM1), R(reg1)); |
|
||||
u64 distance = u64(func) - (u64(code) + 5); |
|
||||
if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) { |
|
||||
// Far call
|
|
||||
MOV(64, R(RAX), ImmPtr(func)); |
|
||||
CALLptr(R(RAX)); |
|
||||
} else { |
|
||||
CALL(func); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// Pass two registers as parameters.
|
|
||||
void XEmitter::ABI_CallFunctionRR(const void* func, X64Reg reg1, X64Reg reg2) { |
|
||||
if (reg2 != ABI_PARAM1) { |
|
||||
if (reg1 != ABI_PARAM1) |
|
||||
MOV(64, R(ABI_PARAM1), R(reg1)); |
|
||||
if (reg2 != ABI_PARAM2) |
|
||||
MOV(64, R(ABI_PARAM2), R(reg2)); |
|
||||
} else { |
|
||||
if (reg2 != ABI_PARAM2) |
|
||||
MOV(64, R(ABI_PARAM2), R(reg2)); |
|
||||
if (reg1 != ABI_PARAM1) |
|
||||
MOV(64, R(ABI_PARAM1), R(reg1)); |
|
||||
} |
|
||||
u64 distance = u64(func) - (u64(code) + 5); |
|
||||
if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) { |
|
||||
// Far call
|
|
||||
MOV(64, R(RAX), ImmPtr(func)); |
|
||||
CALLptr(R(RAX)); |
|
||||
} else { |
|
||||
CALL(func); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void XEmitter::ABI_CallFunctionAC(const void* func, const Gen::OpArg& arg1, u32 param2) { |
|
||||
if (!arg1.IsSimpleReg(ABI_PARAM1)) |
|
||||
MOV(32, R(ABI_PARAM1), arg1); |
|
||||
MOV(32, R(ABI_PARAM2), Imm32(param2)); |
|
||||
u64 distance = u64(func) - (u64(code) + 5); |
|
||||
if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) { |
|
||||
// Far call
|
|
||||
MOV(64, R(RAX), ImmPtr(func)); |
|
||||
CALLptr(R(RAX)); |
|
||||
} else { |
|
||||
CALL(func); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void XEmitter::ABI_CallFunctionACC(const void* func, const Gen::OpArg& arg1, u32 param2, |
|
||||
u32 param3) { |
|
||||
if (!arg1.IsSimpleReg(ABI_PARAM1)) |
|
||||
MOV(32, R(ABI_PARAM1), arg1); |
|
||||
MOV(32, R(ABI_PARAM2), Imm32(param2)); |
|
||||
MOV(64, R(ABI_PARAM3), Imm64(param3)); |
|
||||
u64 distance = u64(func) - (u64(code) + 5); |
|
||||
if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) { |
|
||||
// Far call
|
|
||||
MOV(64, R(RAX), ImmPtr(func)); |
|
||||
CALLptr(R(RAX)); |
|
||||
} else { |
|
||||
CALL(func); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void XEmitter::ABI_CallFunctionA(const void* func, const Gen::OpArg& arg1) { |
|
||||
if (!arg1.IsSimpleReg(ABI_PARAM1)) |
|
||||
MOV(32, R(ABI_PARAM1), arg1); |
|
||||
u64 distance = u64(func) - (u64(code) + 5); |
|
||||
if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) { |
|
||||
// Far call
|
|
||||
MOV(64, R(RAX), ImmPtr(func)); |
|
||||
CALLptr(R(RAX)); |
|
||||
} else { |
|
||||
CALL(func); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void XEmitter::ABI_CallFunctionAA(const void* func, const Gen::OpArg& arg1, |
|
||||
const Gen::OpArg& arg2) { |
|
||||
if (!arg1.IsSimpleReg(ABI_PARAM1)) |
|
||||
MOV(32, R(ABI_PARAM1), arg1); |
|
||||
if (!arg2.IsSimpleReg(ABI_PARAM2)) |
|
||||
MOV(32, R(ABI_PARAM2), arg2); |
|
||||
u64 distance = u64(func) - (u64(code) + 5); |
|
||||
if (distance >= 0x0000000080000000ULL && distance < 0xFFFFFFFF80000000ULL) { |
|
||||
// Far call
|
|
||||
MOV(64, R(RAX), ImmPtr(func)); |
|
||||
CALLptr(R(RAX)); |
|
||||
} else { |
|
||||
CALL(func); |
|
||||
} |
|
||||
} |
|
||||
@ -1,58 +0,0 @@ |
|||||
// Copyright 2008 Dolphin Emulator Project |
|
||||
// Licensed under GPLv2+ |
|
||||
// Refer to the license.txt file included. |
|
||||
|
|
||||
#pragma once |
|
||||
|
|
||||
#include "common/bit_set.h" |
|
||||
#include "emitter.h" |
|
||||
|
|
||||
// x64 ABI:s, and helpers to help follow them when JIT-ing code. |
|
||||
// All convensions return values in EAX (+ possibly EDX). |
|
||||
|
|
||||
// Windows 64-bit |
|
||||
// * 4-reg "fastcall" variant, very new-skool stack handling |
|
||||
// * Callee moves stack pointer, to make room for shadow regs for the biggest function _it itself |
|
||||
// calls_ |
|
||||
// * Parameters passed in RCX, RDX, ... further parameters are MOVed into the allocated stack space. |
|
||||
// Scratch: RAX RCX RDX R8 R9 R10 R11 |
|
||||
// Callee-save: RBX RSI RDI RBP R12 R13 R14 R15 |
|
||||
// Parameters: RCX RDX R8 R9, further MOV-ed |
|
||||
|
|
||||
// Linux 64-bit |
|
||||
// * 6-reg "fastcall" variant, old skool stack handling (parameters are pushed) |
|
||||
// Scratch: RAX RCX RDX RSI RDI R8 R9 R10 R11 |
|
||||
// Callee-save: RBX RBP R12 R13 R14 R15 |
|
||||
// Parameters: RDI RSI RDX RCX R8 R9 |
|
||||
|
|
||||
#define ABI_ALL_FPRS BitSet32(0xffff0000) |
|
||||
#define ABI_ALL_GPRS BitSet32(0x0000ffff) |
|
||||
|
|
||||
#ifdef _WIN32 // 64-bit Windows - the really exotic calling convention |
|
||||
|
|
||||
#define ABI_PARAM1 RCX |
|
||||
#define ABI_PARAM2 RDX |
|
||||
#define ABI_PARAM3 R8 |
|
||||
#define ABI_PARAM4 R9 |
|
||||
|
|
||||
// xmm0-xmm15 use the upper 16 bits in the functions that push/pop registers. |
|
||||
#define ABI_ALL_CALLER_SAVED \ |
|
||||
(BitSet32{RAX, RCX, RDX, R8, R9, R10, R11, XMM0 + 16, XMM1 + 16, XMM2 + 16, XMM3 + 16, \ |
|
||||
XMM4 + 16, XMM5 + 16}) |
|
||||
#else // 64-bit Unix / OS X |
|
||||
|
|
||||
#define ABI_PARAM1 RDI |
|
||||
#define ABI_PARAM2 RSI |
|
||||
#define ABI_PARAM3 RDX |
|
||||
#define ABI_PARAM4 RCX |
|
||||
#define ABI_PARAM5 R8 |
|
||||
#define ABI_PARAM6 R9 |
|
||||
|
|
||||
// TODO: Avoid pushing all 16 XMM registers when possible. Most functions we call probably |
|
||||
// don't actually clobber them. |
|
||||
#define ABI_ALL_CALLER_SAVED (BitSet32{RAX, RCX, RDX, RDI, RSI, R8, R9, R10, R11} | ABI_ALL_FPRS) |
|
||||
#endif // WIN32 |
|
||||
|
|
||||
#define ABI_ALL_CALLEE_SAVED (~ABI_ALL_CALLER_SAVED) |
|
||||
|
|
||||
#define ABI_RETURN RAX |
|
||||
2583
src/common/x64/emitter.cpp
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1206
src/common/x64/emitter.h
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
Write
Preview
Loading…
Cancel
Save
Reference in new issue