diff --git a/Source/Core/Common/x64ABI.cpp b/Source/Core/Common/x64ABI.cpp index d8ed88010f..0f958a4a6d 100644 --- a/Source/Core/Common/x64ABI.cpp +++ b/Source/Core/Common/x64ABI.cpp @@ -100,7 +100,7 @@ void XEmitter::ABI_PopRegistersAndAdjustStack(u32 mask, size_t rsp_alignment, si } // Common functions -void XEmitter::ABI_CallFunction(void *func) +void XEmitter::ABI_CallFunction(const void *func) { u64 distance = u64(func) - (u64(code) + 5); if (distance >= 0x0000000080000000ULL && @@ -116,7 +116,7 @@ void XEmitter::ABI_CallFunction(void *func) } } -void XEmitter::ABI_CallFunctionC16(void *func, u16 param1) +void XEmitter::ABI_CallFunctionC16(const void *func, u16 param1) { MOV(32, R(ABI_PARAM1), Imm32((u32)param1)); u64 distance = u64(func) - (u64(code) + 5); @@ -133,7 +133,7 @@ void XEmitter::ABI_CallFunctionC16(void *func, u16 param1) } } -void XEmitter::ABI_CallFunctionCC16(void *func, u32 param1, u16 param2) +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)); @@ -151,7 +151,7 @@ void XEmitter::ABI_CallFunctionCC16(void *func, u32 param1, u16 param2) } } -void XEmitter::ABI_CallFunctionC(void *func, u32 param1) +void XEmitter::ABI_CallFunctionC(const void *func, u32 param1) { MOV(32, R(ABI_PARAM1), Imm32(param1)); u64 distance = u64(func) - (u64(code) + 5); @@ -168,7 +168,7 @@ void XEmitter::ABI_CallFunctionC(void *func, u32 param1) } } -void XEmitter::ABI_CallFunctionCC(void *func, u32 param1, u32 param2) +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)); @@ -186,7 +186,7 @@ void XEmitter::ABI_CallFunctionCC(void *func, u32 param1, u32 param2) } } -void XEmitter::ABI_CallFunctionCP(void *func, u32 param1, void *param2) +void XEmitter::ABI_CallFunctionCP(const void *func, u32 param1, void *param2) { MOV(32, R(ABI_PARAM1), Imm32(param1)); MOV(64, R(ABI_PARAM2), Imm64((u64)param2)); @@ -204,7 +204,7 @@ void XEmitter::ABI_CallFunctionCP(void *func, u32 param1, void *param2) } } -void XEmitter::ABI_CallFunctionCCC(void *func, u32 param1, u32 param2, u32 param3) +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)); @@ -223,7 +223,7 @@ void XEmitter::ABI_CallFunctionCCC(void *func, u32 param1, u32 param2, u32 param } } -void XEmitter::ABI_CallFunctionCCP(void *func, u32 param1, u32 param2, void *param3) +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)); @@ -242,7 +242,7 @@ void XEmitter::ABI_CallFunctionCCP(void *func, u32 param1, u32 param2, void *par } } -void XEmitter::ABI_CallFunctionCCCP(void *func, u32 param1, u32 param2, u32 param3, void *param4) +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)); @@ -262,7 +262,7 @@ void XEmitter::ABI_CallFunctionCCCP(void *func, u32 param1, u32 param2, u32 para } } -void XEmitter::ABI_CallFunctionPC(void *func, void *param1, u32 param2) +void XEmitter::ABI_CallFunctionPC(const void *func, void *param1, u32 param2) { MOV(64, R(ABI_PARAM1), Imm64((u64)param1)); MOV(32, R(ABI_PARAM2), Imm32(param2)); @@ -280,7 +280,7 @@ void XEmitter::ABI_CallFunctionPC(void *func, void *param1, u32 param2) } } -void XEmitter::ABI_CallFunctionPPC(void *func, void *param1, void *param2, u32 param3) +void XEmitter::ABI_CallFunctionPPC(const void *func, void *param1, void *param2, u32 param3) { MOV(64, R(ABI_PARAM1), Imm64((u64)param1)); MOV(64, R(ABI_PARAM2), Imm64((u64)param2)); @@ -300,7 +300,7 @@ void XEmitter::ABI_CallFunctionPPC(void *func, void *param1, void *param2, u32 p } // Pass a register as a parameter. -void XEmitter::ABI_CallFunctionR(void *func, X64Reg reg1) +void XEmitter::ABI_CallFunctionR(const void *func, X64Reg reg1) { if (reg1 != ABI_PARAM1) MOV(32, R(ABI_PARAM1), R(reg1)); @@ -319,7 +319,7 @@ void XEmitter::ABI_CallFunctionR(void *func, X64Reg reg1) } // Pass two registers as parameters. -void XEmitter::ABI_CallFunctionRR(void *func, X64Reg reg1, X64Reg reg2) +void XEmitter::ABI_CallFunctionRR(const void *func, X64Reg reg1, X64Reg reg2) { MOVTwo(64, ABI_PARAM1, reg1, ABI_PARAM2, reg2); u64 distance = u64(func) - (u64(code) + 5); @@ -358,7 +358,7 @@ void XEmitter::MOVTwo(int bits, Gen::X64Reg dst1, Gen::X64Reg src1, Gen::X64Reg } } -void XEmitter::ABI_CallFunctionAC(void *func, const Gen::OpArg &arg1, u32 param2) +void XEmitter::ABI_CallFunctionAC(const void *func, const Gen::OpArg &arg1, u32 param2) { if (!arg1.IsSimpleReg(ABI_PARAM1)) MOV(32, R(ABI_PARAM1), arg1); @@ -377,7 +377,7 @@ void XEmitter::ABI_CallFunctionAC(void *func, const Gen::OpArg &arg1, u32 param2 } } -void XEmitter::ABI_CallFunctionA(void *func, const Gen::OpArg &arg1) +void XEmitter::ABI_CallFunctionA(const void *func, const Gen::OpArg &arg1) { if (!arg1.IsSimpleReg(ABI_PARAM1)) MOV(32, R(ABI_PARAM1), arg1); diff --git a/Source/Core/Common/x64Emitter.cpp b/Source/Core/Common/x64Emitter.cpp index 7693236a62..bda0cc0faf 100644 --- a/Source/Core/Common/x64Emitter.cpp +++ b/Source/Core/Common/x64Emitter.cpp @@ -66,6 +66,8 @@ enum NormalSSEOps sseMOVHPDtoRM = 0x17, sseMOVHLPS = 0x12, sseMOVLHPS = 0x16, + sseMOVDQfromRM = 0x6F, + sseMOVDQtoRM = 0x7F, sseMASKMOVDQU = 0xF7, sseLDDQU = 0xF0, sseSHUF = 0xC6, @@ -1540,6 +1542,11 @@ void XEmitter::MOVUPD(X64Reg regOp, OpArg arg) {WriteSSEOp(0x66, sseMOVUPfromRM void XEmitter::MOVUPS(OpArg arg, X64Reg regOp) {WriteSSEOp(0x00, sseMOVUPtoRM, regOp, arg);} void XEmitter::MOVUPD(OpArg arg, X64Reg regOp) {WriteSSEOp(0x66, sseMOVUPtoRM, regOp, arg);} +void XEmitter::MOVDQA(X64Reg regOp, OpArg arg) {WriteSSEOp(0x66, sseMOVDQfromRM, regOp, arg);} +void XEmitter::MOVDQA(OpArg arg, X64Reg regOp) {WriteSSEOp(0x66, sseMOVDQtoRM, regOp, arg);} +void XEmitter::MOVDQU(X64Reg regOp, OpArg arg) {WriteSSEOp(0xF3, sseMOVDQfromRM, regOp, arg);} +void XEmitter::MOVDQU(OpArg arg, X64Reg regOp) {WriteSSEOp(0xF3, sseMOVDQtoRM, regOp, arg);} + void XEmitter::MOVSS(X64Reg regOp, OpArg arg) {WriteSSEOp(0xF3, sseMOVUPfromRM, regOp, arg);} void XEmitter::MOVSD(X64Reg regOp, OpArg arg) {WriteSSEOp(0xF2, sseMOVUPfromRM, regOp, arg);} void XEmitter::MOVSS(OpArg arg, X64Reg regOp) {WriteSSEOp(0xF3, sseMOVUPtoRM, regOp, arg);} @@ -1636,6 +1643,12 @@ void XEmitter::PSRLQ(X64Reg reg, OpArg arg) WriteSSEOp(0x66, 0xd3, reg, arg); } +void XEmitter::PSRLDQ(X64Reg reg, int shift) +{ + WriteSSEOp(0x66, 0x73, (X64Reg)3, R(reg)); + Write8(shift); +} + void XEmitter::PSLLW(X64Reg reg, int shift) { WriteSSEOp(0x66, 0x71, (X64Reg)6, R(reg)); @@ -1654,6 +1667,13 @@ void XEmitter::PSLLQ(X64Reg reg, int shift) Write8(shift); } +void XEmitter::PSLLDQ(X64Reg reg, int shift) +{ + WriteSSEOp(0x66, 0x73, (X64Reg)7, R(reg)); + Write8(shift); +} + + // WARNING not REX compatible void XEmitter::PSRAW(X64Reg reg, int shift) { @@ -1761,8 +1781,9 @@ void XEmitter::PMINSW(X64Reg dest, OpArg arg) {WriteSSEOp(0x66, 0xEA, dest, ar void XEmitter::PMINUB(X64Reg dest, OpArg arg) {WriteSSEOp(0x66, 0xDA, dest, arg); } void XEmitter::PMOVMSKB(X64Reg dest, OpArg arg) {WriteSSEOp(0x66, 0xD7, dest, arg); } - +void XEmitter::PSHUFD(X64Reg regOp, OpArg arg, u8 shuffle) {WriteSSEOp(0x66, 0x70, regOp, arg, 1); Write8(shuffle);} void XEmitter::PSHUFLW(X64Reg regOp, OpArg arg, u8 shuffle) {WriteSSEOp(0xF2, 0x70, regOp, arg, 1); Write8(shuffle);} +void XEmitter::PSHUFHW(X64Reg regOp, OpArg arg, u8 shuffle) {WriteSSEOp(0xF3, 0x70, regOp, arg, 1); Write8(shuffle);} // VEX void XEmitter::VADDSD(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(0xF2, sseADD, regOp1, regOp2, arg);} diff --git a/Source/Core/Common/x64Emitter.h b/Source/Core/Common/x64Emitter.h index 9f41194edc..8af38431a1 100644 --- a/Source/Core/Common/x64Emitter.h +++ b/Source/Core/Common/x64Emitter.h @@ -101,6 +101,17 @@ enum NormalOp { nrmXCHG, }; +enum { + CMP_EQ = 0, + CMP_LT = 1, + CMP_LE = 2, + CMP_UNORD = 3, + CMP_NEQ = 4, + CMP_NLT = 5, + CMP_NLE = 6, + CMP_ORD = 7, +}; + enum FloatOp { floatLD = 0, floatST = 2, @@ -183,6 +194,8 @@ private: }; inline OpArg M(const void *ptr) {return OpArg((u64)ptr, (int)SCALE_RIP);} +template +inline OpArg M(const T *ptr) {return OpArg((u64)(const void *)ptr, (int)SCALE_RIP);} inline OpArg R(X64Reg value) {return OpArg(0, SCALE_NONE, value);} inline OpArg MatR(X64Reg value) {return OpArg(0, SCALE_ATREG, value);} @@ -219,7 +232,7 @@ inline OpArg ImmPtr(const void* imm) {return Imm64((u64)imm);} inline OpArg ImmPtr(const void* imm) {return Imm32((u32)imm);} #endif -inline u32 PtrOffset(void* ptr, void* base) +inline u32 PtrOffset(const void* ptr, const void* base) { #ifdef _ARCH_64 s64 distance = (s64)ptr-(s64)base; @@ -526,6 +539,14 @@ public: void CMPSS(X64Reg regOp, OpArg arg, u8 compare); void CMPSD(X64Reg regOp, OpArg arg, u8 compare); + inline void CMPEQSS(X64Reg regOp, OpArg arg) { CMPSS(regOp, arg, CMP_EQ); } + inline void CMPLTSS(X64Reg regOp, OpArg arg) { CMPSS(regOp, arg, CMP_LT); } + inline void CMPLESS(X64Reg regOp, OpArg arg) { CMPSS(regOp, arg, CMP_LE); } + inline void CMPUNORDSS(X64Reg regOp, OpArg arg) { CMPSS(regOp, arg, CMP_UNORD); } + inline void CMPNEQSS(X64Reg regOp, OpArg arg) { CMPSS(regOp, arg, CMP_NEQ); } + inline void CMPNLTSS(X64Reg regOp, OpArg arg) { CMPSS(regOp, arg, CMP_NLT); } + inline void CMPORDSS(X64Reg regOp, OpArg arg) { CMPSS(regOp, arg, CMP_ORD); } + // SSE/SSE2: Floating point packed arithmetic (x4 for float, x2 for double) void ADDPS(X64Reg regOp, OpArg arg); void ADDPD(X64Reg regOp, OpArg arg); @@ -584,6 +605,11 @@ public: void MOVUPS(OpArg arg, X64Reg regOp); void MOVUPD(OpArg arg, X64Reg regOp); + void MOVDQA(X64Reg regOp, OpArg arg); + void MOVDQA(OpArg arg, X64Reg regOp); + void MOVDQU(X64Reg regOp, OpArg arg); + void MOVDQU(OpArg arg, X64Reg regOp); + void MOVSS(X64Reg regOp, OpArg arg); void MOVSD(X64Reg regOp, OpArg arg); void MOVSS(OpArg arg, X64Reg regOp); @@ -690,18 +716,22 @@ public: void PMINUB(X64Reg dest, OpArg arg); void PMOVMSKB(X64Reg dest, OpArg arg); + void PSHUFD(X64Reg dest, OpArg arg, u8 shuffle); void PSHUFB(X64Reg dest, OpArg arg); void PSHUFLW(X64Reg dest, OpArg arg, u8 shuffle); + void PSHUFHW(X64Reg dest, OpArg arg, u8 shuffle); void PSRLW(X64Reg reg, int shift); void PSRLD(X64Reg reg, int shift); void PSRLQ(X64Reg reg, int shift); void PSRLQ(X64Reg reg, OpArg arg); + void PSRLDQ(X64Reg reg, int shift); void PSLLW(X64Reg reg, int shift); void PSLLD(X64Reg reg, int shift); void PSLLQ(X64Reg reg, int shift); + void PSLLDQ(X64Reg reg, int shift); void PSRAW(X64Reg reg, int shift); void PSRAD(X64Reg reg, int shift); @@ -763,27 +793,27 @@ public: // Utility functions // The difference between this and CALL is that this aligns the stack // where appropriate. - void ABI_CallFunction(void *func); + void ABI_CallFunction(const void *func); - void ABI_CallFunctionC16(void *func, u16 param1); - void ABI_CallFunctionCC16(void *func, u32 param1, u16 param2); + void ABI_CallFunctionC16(const void *func, u16 param1); + void ABI_CallFunctionCC16(const void *func, u32 param1, u16 param2); // These only support u32 parameters, but that's enough for a lot of uses. // These will destroy the 1 or 2 first "parameter regs". - void ABI_CallFunctionC(void *func, u32 param1); - void ABI_CallFunctionCC(void *func, u32 param1, u32 param2); - void ABI_CallFunctionCP(void *func, u32 param1, void *param2); - void ABI_CallFunctionCCC(void *func, u32 param1, u32 param2, u32 param3); - void ABI_CallFunctionCCP(void *func, u32 param1, u32 param2, void *param3); - void ABI_CallFunctionCCCP(void *func, u32 param1, u32 param2,u32 param3, void *param4); - void ABI_CallFunctionPC(void *func, void *param1, u32 param2); - void ABI_CallFunctionPPC(void *func, void *param1, void *param2,u32 param3); - void ABI_CallFunctionAC(void *func, const OpArg &arg1, u32 param2); - void ABI_CallFunctionA(void *func, const OpArg &arg1); + void ABI_CallFunctionC(const void *func, u32 param1); + void ABI_CallFunctionCC(const void *func, u32 param1, u32 param2); + void ABI_CallFunctionCP(const void *func, u32 param1, void *param2); + void ABI_CallFunctionCCC(const void *func, u32 param1, u32 param2, u32 param3); + void ABI_CallFunctionCCP(const void *func, u32 param1, u32 param2, void *param3); + void ABI_CallFunctionCCCP(const void *func, u32 param1, u32 param2,u32 param3, void *param4); + void ABI_CallFunctionPC(const void *func, void *param1, u32 param2); + void ABI_CallFunctionPPC(const void *func, void *param1, void *param2, u32 param3); + void ABI_CallFunctionAC(const void *func, const OpArg &arg1, u32 param2); + void ABI_CallFunctionA(const void *func, const OpArg &arg1); // Pass a register as a parameter. - void ABI_CallFunctionR(void *func, X64Reg reg1); - void ABI_CallFunctionRR(void *func, X64Reg reg1, X64Reg reg2); + void ABI_CallFunctionR(const void *func, X64Reg reg1); + void ABI_CallFunctionRR(const void *func, X64Reg reg1, X64Reg reg2); // Helper method for the above, or can be used separately. void MOVTwo(int bits, Gen::X64Reg dst1, Gen::X64Reg src1, Gen::X64Reg dst2, Gen::X64Reg src2);