emitter.h 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048
  1. // Copyright (C) 2003 Dolphin Project.
  2. // This program is free software: you can redistribute it and/or modify
  3. // it under the terms of the GNU General Public License as published by
  4. // the Free Software Foundation, version 2.0 or later versions.
  5. // This program is distributed in the hope that it will be useful,
  6. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. // GNU General Public License 2.0 for more details.
  9. // A copy of the GPL 2.0 should have been included with the program.
  10. // If not, see http://www.gnu.org/licenses/
  11. // Official SVN repository and contact information can be found at
  12. // http://code.google.com/p/dolphin-emu/
  13. #pragma once
  14. #include <cstddef>
  15. #include "common/assert.h"
  16. #include "common/bit_set.h"
  17. #include "common/common_types.h"
  18. #include "common/code_block.h"
  19. #if defined(ARCHITECTURE_x86_64) && !defined(_ARCH_64)
  20. #define _ARCH_64
  21. #endif
  22. #ifdef _ARCH_64
  23. #define PTRBITS 64
  24. #else
  25. #define PTRBITS 32
  26. #endif
  27. namespace Gen
  28. {
  29. enum X64Reg
  30. {
  31. EAX = 0, EBX = 3, ECX = 1, EDX = 2,
  32. ESI = 6, EDI = 7, EBP = 5, ESP = 4,
  33. RAX = 0, RBX = 3, RCX = 1, RDX = 2,
  34. RSI = 6, RDI = 7, RBP = 5, RSP = 4,
  35. R8 = 8, R9 = 9, R10 = 10,R11 = 11,
  36. R12 = 12,R13 = 13,R14 = 14,R15 = 15,
  37. AL = 0, BL = 3, CL = 1, DL = 2,
  38. SIL = 6, DIL = 7, BPL = 5, SPL = 4,
  39. AH = 0x104, BH = 0x107, CH = 0x105, DH = 0x106,
  40. AX = 0, BX = 3, CX = 1, DX = 2,
  41. SI = 6, DI = 7, BP = 5, SP = 4,
  42. XMM0=0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
  43. XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15,
  44. YMM0=0, YMM1, YMM2, YMM3, YMM4, YMM5, YMM6, YMM7,
  45. YMM8, YMM9, YMM10, YMM11, YMM12, YMM13, YMM14, YMM15,
  46. INVALID_REG = 0xFFFFFFFF
  47. };
  48. enum CCFlags
  49. {
  50. CC_O = 0,
  51. CC_NO = 1,
  52. CC_B = 2, CC_C = 2, CC_NAE = 2,
  53. CC_NB = 3, CC_NC = 3, CC_AE = 3,
  54. CC_Z = 4, CC_E = 4,
  55. CC_NZ = 5, CC_NE = 5,
  56. CC_BE = 6, CC_NA = 6,
  57. CC_NBE = 7, CC_A = 7,
  58. CC_S = 8,
  59. CC_NS = 9,
  60. CC_P = 0xA, CC_PE = 0xA,
  61. CC_NP = 0xB, CC_PO = 0xB,
  62. CC_L = 0xC, CC_NGE = 0xC,
  63. CC_NL = 0xD, CC_GE = 0xD,
  64. CC_LE = 0xE, CC_NG = 0xE,
  65. CC_NLE = 0xF, CC_G = 0xF
  66. };
  67. enum
  68. {
  69. NUMGPRs = 16,
  70. NUMXMMs = 16,
  71. };
  72. enum
  73. {
  74. SCALE_NONE = 0,
  75. SCALE_1 = 1,
  76. SCALE_2 = 2,
  77. SCALE_4 = 4,
  78. SCALE_8 = 8,
  79. SCALE_ATREG = 16,
  80. //SCALE_NOBASE_1 is not supported and can be replaced with SCALE_ATREG
  81. SCALE_NOBASE_2 = 34,
  82. SCALE_NOBASE_4 = 36,
  83. SCALE_NOBASE_8 = 40,
  84. SCALE_RIP = 0xFF,
  85. SCALE_IMM8 = 0xF0,
  86. SCALE_IMM16 = 0xF1,
  87. SCALE_IMM32 = 0xF2,
  88. SCALE_IMM64 = 0xF3,
  89. };
  90. enum NormalOp {
  91. nrmADD,
  92. nrmADC,
  93. nrmSUB,
  94. nrmSBB,
  95. nrmAND,
  96. nrmOR ,
  97. nrmXOR,
  98. nrmMOV,
  99. nrmTEST,
  100. nrmCMP,
  101. nrmXCHG,
  102. };
  103. enum {
  104. CMP_EQ = 0,
  105. CMP_LT = 1,
  106. CMP_LE = 2,
  107. CMP_UNORD = 3,
  108. CMP_NEQ = 4,
  109. CMP_NLT = 5,
  110. CMP_NLE = 6,
  111. CMP_ORD = 7,
  112. };
  113. enum FloatOp {
  114. floatLD = 0,
  115. floatST = 2,
  116. floatSTP = 3,
  117. floatLD80 = 5,
  118. floatSTP80 = 7,
  119. floatINVALID = -1,
  120. };
  121. enum FloatRound {
  122. FROUND_NEAREST = 0,
  123. FROUND_FLOOR = 1,
  124. FROUND_CEIL = 2,
  125. FROUND_ZERO = 3,
  126. FROUND_MXCSR = 4,
  127. FROUND_RAISE_PRECISION = 0,
  128. FROUND_IGNORE_PRECISION = 8,
  129. };
  130. class XEmitter;
  131. // RIP addressing does not benefit from micro op fusion on Core arch
  132. struct OpArg
  133. {
  134. friend class XEmitter;
  135. constexpr OpArg() = default; // dummy op arg, used for storage
  136. constexpr OpArg(u64 offset_, int scale_, X64Reg rmReg = RAX, X64Reg scaledReg = RAX)
  137. : scale(static_cast<u8>(scale_))
  138. , offsetOrBaseReg(static_cast<u16>(rmReg))
  139. , indexReg(static_cast<u16>(scaledReg))
  140. , offset(offset_)
  141. {
  142. }
  143. constexpr bool operator==(const OpArg &b) const
  144. {
  145. return operandReg == b.operandReg &&
  146. scale == b.scale &&
  147. offsetOrBaseReg == b.offsetOrBaseReg &&
  148. indexReg == b.indexReg &&
  149. offset == b.offset;
  150. }
  151. void WriteRex(XEmitter *emit, int opBits, int bits, int customOp = -1) const;
  152. void WriteVex(XEmitter* emit, X64Reg regOp1, X64Reg regOp2, int L, int pp, int mmmmm, int W = 0) const;
  153. void WriteRest(XEmitter *emit, int extraBytes=0, X64Reg operandReg=INVALID_REG, bool warn_64bit_offset = true) const;
  154. void WriteSingleByteOp(XEmitter *emit, u8 op, X64Reg operandReg, int bits);
  155. void WriteNormalOp(XEmitter *emit, bool toRM, NormalOp op, const OpArg &operand, int bits) const;
  156. constexpr bool IsImm() const { return scale == SCALE_IMM8 || scale == SCALE_IMM16 || scale == SCALE_IMM32 || scale == SCALE_IMM64; }
  157. constexpr bool IsSimpleReg() const { return scale == SCALE_NONE; }
  158. constexpr bool IsSimpleReg(X64Reg reg) const
  159. {
  160. return IsSimpleReg() && GetSimpleReg() == reg;
  161. }
  162. int GetImmBits() const
  163. {
  164. switch (scale)
  165. {
  166. case SCALE_IMM8: return 8;
  167. case SCALE_IMM16: return 16;
  168. case SCALE_IMM32: return 32;
  169. case SCALE_IMM64: return 64;
  170. default: return -1;
  171. }
  172. }
  173. void SetImmBits(int bits) {
  174. switch (bits)
  175. {
  176. case 8: scale = SCALE_IMM8; break;
  177. case 16: scale = SCALE_IMM16; break;
  178. case 32: scale = SCALE_IMM32; break;
  179. case 64: scale = SCALE_IMM64; break;
  180. }
  181. }
  182. constexpr X64Reg GetSimpleReg() const
  183. {
  184. return scale == SCALE_NONE
  185. ? static_cast<X64Reg>(offsetOrBaseReg)
  186. : INVALID_REG;
  187. }
  188. constexpr u32 GetImmValue() const {
  189. return static_cast<u32>(offset);
  190. }
  191. // For loops.
  192. void IncreaseOffset(int sz) {
  193. offset += sz;
  194. }
  195. private:
  196. u8 scale = 0;
  197. u16 offsetOrBaseReg = 0;
  198. u16 indexReg = 0;
  199. u64 offset = 0; // use RIP-relative as much as possible - 64-bit immediates are not available.
  200. u16 operandReg = 0;
  201. };
  202. template <typename T>
  203. inline OpArg M(const T *ptr) { return OpArg(reinterpret_cast<u64>(ptr), static_cast<int>(SCALE_RIP)); }
  204. constexpr OpArg R(X64Reg value) { return OpArg(0, SCALE_NONE, value); }
  205. constexpr OpArg MatR(X64Reg value) { return OpArg(0, SCALE_ATREG, value); }
  206. constexpr OpArg MDisp(X64Reg value, int offset)
  207. {
  208. return OpArg(static_cast<u32>(offset), SCALE_ATREG, value);
  209. }
  210. constexpr OpArg MComplex(X64Reg base, X64Reg scaled, int scale, int offset)
  211. {
  212. return OpArg(offset, scale, base, scaled);
  213. }
  214. constexpr OpArg MScaled(X64Reg scaled, int scale, int offset)
  215. {
  216. return scale == SCALE_1
  217. ? OpArg(offset, SCALE_ATREG, scaled)
  218. : OpArg(offset, scale | 0x20, RAX, scaled);
  219. }
  220. constexpr OpArg MRegSum(X64Reg base, X64Reg offset)
  221. {
  222. return MComplex(base, offset, 1, 0);
  223. }
  224. constexpr OpArg Imm8 (u8 imm) { return OpArg(imm, SCALE_IMM8); }
  225. constexpr OpArg Imm16(u16 imm) { return OpArg(imm, SCALE_IMM16); } //rarely used
  226. constexpr OpArg Imm32(u32 imm) { return OpArg(imm, SCALE_IMM32); }
  227. constexpr OpArg Imm64(u64 imm) { return OpArg(imm, SCALE_IMM64); }
  228. constexpr OpArg UImmAuto(u32 imm) {
  229. return OpArg(imm, imm >= 128 ? SCALE_IMM32 : SCALE_IMM8);
  230. }
  231. constexpr OpArg SImmAuto(s32 imm) {
  232. return OpArg(imm, (imm >= 128 || imm < -128) ? SCALE_IMM32 : SCALE_IMM8);
  233. }
  234. template <typename T>
  235. OpArg ImmPtr(const T* imm)
  236. {
  237. #ifdef _ARCH_64
  238. return Imm64(reinterpret_cast<u64>(imm));
  239. #else
  240. return Imm32(reinterpret_cast<u32>(imm));
  241. #endif
  242. }
  243. inline u32 PtrOffset(const void* ptr, const void* base)
  244. {
  245. #ifdef _ARCH_64
  246. s64 distance = (s64)ptr-(s64)base;
  247. if (distance >= 0x80000000LL ||
  248. distance < -0x80000000LL)
  249. {
  250. ASSERT_MSG(0, "pointer offset out of range");
  251. return 0;
  252. }
  253. return (u32)distance;
  254. #else
  255. return (u32)ptr-(u32)base;
  256. #endif
  257. }
  258. //usage: int a[]; ARRAY_OFFSET(a,10)
  259. #define ARRAY_OFFSET(array,index) ((u32)((u64)&(array)[index]-(u64)&(array)[0]))
  260. //usage: struct {int e;} s; STRUCT_OFFSET(s,e)
  261. #define STRUCT_OFFSET(str,elem) ((u32)((u64)&(str).elem-(u64)&(str)))
  262. struct FixupBranch
  263. {
  264. u8 *ptr;
  265. int type; //0 = 8bit 1 = 32bit
  266. };
  267. enum SSECompare
  268. {
  269. EQ = 0,
  270. LT,
  271. LE,
  272. UNORD,
  273. NEQ,
  274. NLT,
  275. NLE,
  276. ORD,
  277. };
  278. class XEmitter
  279. {
  280. friend struct OpArg; // for Write8 etc
  281. private:
  282. u8 *code;
  283. bool flags_locked;
  284. void CheckFlags();
  285. void Rex(int w, int r, int x, int b);
  286. void WriteSimple1Byte(int bits, u8 byte, X64Reg reg);
  287. void WriteSimple2Byte(int bits, u8 byte1, u8 byte2, X64Reg reg);
  288. void WriteMulDivType(int bits, OpArg src, int ext);
  289. void WriteBitSearchType(int bits, X64Reg dest, OpArg src, u8 byte2, bool rep = false);
  290. void WriteShift(int bits, OpArg dest, const OpArg& shift, int ext);
  291. void WriteBitTest(int bits, const OpArg& dest, const OpArg& index, int ext);
  292. void WriteMXCSR(OpArg arg, int ext);
  293. void WriteSSEOp(u8 opPrefix, u16 op, X64Reg regOp, OpArg arg, int extrabytes = 0);
  294. void WriteSSSE3Op(u8 opPrefix, u16 op, X64Reg regOp, const OpArg& arg, int extrabytes = 0);
  295. void WriteSSE41Op(u8 opPrefix, u16 op, X64Reg regOp, const OpArg& arg, int extrabytes = 0);
  296. void WriteAVXOp(u8 opPrefix, u16 op, X64Reg regOp, const OpArg& arg, int extrabytes = 0);
  297. void WriteAVXOp(u8 opPrefix, u16 op, X64Reg regOp1, X64Reg regOp2, const OpArg& arg, int extrabytes = 0);
  298. void WriteVEXOp(int size, u8 opPrefix, u16 op, X64Reg regOp1, X64Reg regOp2, const OpArg& arg, int extrabytes = 0);
  299. void WriteBMI1Op(int size, u8 opPrefix, u16 op, X64Reg regOp1, X64Reg regOp2, const OpArg& arg, int extrabytes = 0);
  300. void WriteBMI2Op(int size, u8 opPrefix, u16 op, X64Reg regOp1, X64Reg regOp2, const OpArg& arg, int extrabytes = 0);
  301. void WriteFloatLoadStore(int bits, FloatOp op, FloatOp op_80b, const OpArg& arg);
  302. void WriteNormalOp(XEmitter *emit, int bits, NormalOp op, const OpArg& a1, const OpArg& a2);
  303. void ABI_CalculateFrameSize(BitSet32 mask, size_t rsp_alignment, size_t needed_frame_size, size_t* shadowp, size_t* subtractionp, size_t* xmm_offsetp);
  304. protected:
  305. void Write8(u8 value);
  306. void Write16(u16 value);
  307. void Write32(u32 value);
  308. void Write64(u64 value);
  309. public:
  310. XEmitter() { code = nullptr; flags_locked = false; }
  311. XEmitter(u8 *code_ptr) { code = code_ptr; flags_locked = false; }
  312. virtual ~XEmitter() {}
  313. void WriteModRM(int mod, int rm, int reg);
  314. void WriteSIB(int scale, int index, int base);
  315. void SetCodePtr(u8 *ptr);
  316. void ReserveCodeSpace(int bytes);
  317. const u8 *AlignCode4();
  318. const u8 *AlignCode16();
  319. const u8 *AlignCodePage();
  320. const u8 *GetCodePtr() const;
  321. u8 *GetWritableCodePtr();
  322. void LockFlags() { flags_locked = true; }
  323. void UnlockFlags() { flags_locked = false; }
  324. // Looking for one of these? It's BANNED!! Some instructions are slow on modern CPU
  325. // INC, DEC, LOOP, LOOPNE, LOOPE, ENTER, LEAVE, XCHG, XLAT, REP MOVSB/MOVSD, REP SCASD + other string instr.,
  326. // INC and DEC are slow on Intel Core, but not on AMD. They create a
  327. // false flag dependency because they only update a subset of the flags.
  328. // XCHG is SLOW and should be avoided.
  329. // Debug breakpoint
  330. void INT3();
  331. // Do nothing
  332. void NOP(size_t count = 1);
  333. // Save energy in wait-loops on P4 only. Probably not too useful.
  334. void PAUSE();
  335. // Flag control
  336. void STC();
  337. void CLC();
  338. void CMC();
  339. // These two can not be executed in 64-bit mode on early Intel 64-bit CPU:s, only on Core2 and AMD!
  340. void LAHF(); // 3 cycle vector path
  341. void SAHF(); // direct path fast
  342. // Stack control
  343. void PUSH(X64Reg reg);
  344. void POP(X64Reg reg);
  345. void PUSH(int bits, const OpArg& reg);
  346. void POP(int bits, const OpArg& reg);
  347. void PUSHF();
  348. void POPF();
  349. // Flow control
  350. void RET();
  351. void RET_FAST();
  352. void UD2();
  353. FixupBranch J(bool force5bytes = false);
  354. void JMP(const u8* addr, bool force5Bytes = false);
  355. void JMPptr(const OpArg& arg);
  356. void JMPself(); //infinite loop!
  357. #ifdef CALL
  358. #undef CALL
  359. #endif
  360. void CALL(const void* fnptr);
  361. FixupBranch CALL();
  362. void CALLptr(OpArg arg);
  363. FixupBranch J_CC(CCFlags conditionCode, bool force5bytes = false);
  364. void J_CC(CCFlags conditionCode, const u8* addr, bool force5Bytes = false);
  365. void SetJumpTarget(const FixupBranch& branch);
  366. void SetJumpTarget(const FixupBranch& branch, const u8* target);
  367. void SETcc(CCFlags flag, OpArg dest);
  368. // Note: CMOV brings small if any benefit on current cpus.
  369. void CMOVcc(int bits, X64Reg dest, OpArg src, CCFlags flag);
  370. // Fences
  371. void LFENCE();
  372. void MFENCE();
  373. void SFENCE();
  374. // Bit scan
  375. void BSF(int bits, X64Reg dest, const OpArg& src); // Bottom bit to top bit
  376. void BSR(int bits, X64Reg dest, const OpArg& src); // Top bit to bottom bit
  377. // Cache control
  378. enum PrefetchLevel
  379. {
  380. PF_NTA, //Non-temporal (data used once and only once)
  381. PF_T0, //All cache levels
  382. PF_T1, //Levels 2+ (aliased to T0 on AMD)
  383. PF_T2, //Levels 3+ (aliased to T0 on AMD)
  384. };
  385. void PREFETCH(PrefetchLevel level, OpArg arg);
  386. void MOVNTI(int bits, const OpArg& dest, X64Reg src);
  387. void MOVNTDQ(const OpArg& arg, X64Reg regOp);
  388. void MOVNTPS(const OpArg& arg, X64Reg regOp);
  389. void MOVNTPD(const OpArg& arg, X64Reg regOp);
  390. // Multiplication / division
  391. void MUL(int bits, const OpArg& src); //UNSIGNED
  392. void IMUL(int bits, const OpArg& src); //SIGNED
  393. void IMUL(int bits, X64Reg regOp, const OpArg& src);
  394. void IMUL(int bits, X64Reg regOp, const OpArg& src, const OpArg& imm);
  395. void DIV(int bits, const OpArg& src);
  396. void IDIV(int bits, const OpArg& src);
  397. // Shift
  398. void ROL(int bits, const OpArg& dest, const OpArg& shift);
  399. void ROR(int bits, const OpArg& dest, const OpArg& shift);
  400. void RCL(int bits, const OpArg& dest, const OpArg& shift);
  401. void RCR(int bits, const OpArg& dest, const OpArg& shift);
  402. void SHL(int bits, const OpArg& dest, const OpArg& shift);
  403. void SHR(int bits, const OpArg& dest, const OpArg& shift);
  404. void SAR(int bits, const OpArg& dest, const OpArg& shift);
  405. // Bit Test
  406. void BT(int bits, const OpArg& dest, const OpArg& index);
  407. void BTS(int bits, const OpArg& dest, const OpArg& index);
  408. void BTR(int bits, const OpArg& dest, const OpArg& index);
  409. void BTC(int bits, const OpArg& dest, const OpArg& index);
  410. // Double-Precision Shift
  411. void SHRD(int bits, const OpArg& dest, const OpArg& src, const OpArg& shift);
  412. void SHLD(int bits, const OpArg& dest, const OpArg& src, const OpArg& shift);
  413. // Extend EAX into EDX in various ways
  414. void CWD(int bits = 16);
  415. void CDQ() {CWD(32);}
  416. void CQO() {CWD(64);}
  417. void CBW(int bits = 8);
  418. void CWDE() {CBW(16);}
  419. void CDQE() {CBW(32);}
  420. // Load effective address
  421. void LEA(int bits, X64Reg dest, OpArg src);
  422. // Integer arithmetic
  423. void NEG(int bits, const OpArg& src);
  424. void ADD(int bits, const OpArg& a1, const OpArg& a2);
  425. void ADC(int bits, const OpArg& a1, const OpArg& a2);
  426. void SUB(int bits, const OpArg& a1, const OpArg& a2);
  427. void SBB(int bits, const OpArg& a1, const OpArg& a2);
  428. void AND(int bits, const OpArg& a1, const OpArg& a2);
  429. void CMP(int bits, const OpArg& a1, const OpArg& a2);
  430. // Bit operations
  431. void NOT (int bits, const OpArg& src);
  432. void OR(int bits, const OpArg& a1, const OpArg& a2);
  433. void XOR(int bits, const OpArg& a1, const OpArg& a2);
  434. void MOV(int bits, const OpArg& a1, const OpArg& a2);
  435. void TEST(int bits, const OpArg& a1, const OpArg& a2);
  436. // Are these useful at all? Consider removing.
  437. void XCHG(int bits, const OpArg& a1, const OpArg& a2);
  438. void XCHG_AHAL();
  439. // Byte swapping (32 and 64-bit only).
  440. void BSWAP(int bits, X64Reg reg);
  441. // Sign/zero extension
  442. void MOVSX(int dbits, int sbits, X64Reg dest, OpArg src); //automatically uses MOVSXD if necessary
  443. void MOVZX(int dbits, int sbits, X64Reg dest, OpArg src);
  444. // Available only on Atom or >= Haswell so far. Test with GetCPUCaps().movbe.
  445. void MOVBE(int dbits, const OpArg& dest, const OpArg& src);
  446. // Available only on AMD >= Phenom or Intel >= Haswell
  447. void LZCNT(int bits, X64Reg dest, const OpArg& src);
  448. // Note: this one is actually part of BMI1
  449. void TZCNT(int bits, X64Reg dest, const OpArg& src);
  450. // WARNING - These two take 11-13 cycles and are VectorPath! (AMD64)
  451. void STMXCSR(const OpArg& memloc);
  452. void LDMXCSR(const OpArg& memloc);
  453. // Prefixes
  454. void LOCK();
  455. void REP();
  456. void REPNE();
  457. void FSOverride();
  458. void GSOverride();
  459. // x87
  460. enum x87StatusWordBits {
  461. x87_InvalidOperation = 0x1,
  462. x87_DenormalizedOperand = 0x2,
  463. x87_DivisionByZero = 0x4,
  464. x87_Overflow = 0x8,
  465. x87_Underflow = 0x10,
  466. x87_Precision = 0x20,
  467. x87_StackFault = 0x40,
  468. x87_ErrorSummary = 0x80,
  469. x87_C0 = 0x100,
  470. x87_C1 = 0x200,
  471. x87_C2 = 0x400,
  472. x87_TopOfStack = 0x2000 | 0x1000 | 0x800,
  473. x87_C3 = 0x4000,
  474. x87_FPUBusy = 0x8000,
  475. };
  476. void FLD(int bits, const OpArg& src);
  477. void FST(int bits, const OpArg& dest);
  478. void FSTP(int bits, const OpArg& dest);
  479. void FNSTSW_AX();
  480. void FWAIT();
  481. // SSE/SSE2: Floating point arithmetic
  482. void ADDSS(X64Reg regOp, const OpArg& arg);
  483. void ADDSD(X64Reg regOp, const OpArg& arg);
  484. void SUBSS(X64Reg regOp, const OpArg& arg);
  485. void SUBSD(X64Reg regOp, const OpArg& arg);
  486. void MULSS(X64Reg regOp, const OpArg& arg);
  487. void MULSD(X64Reg regOp, const OpArg& arg);
  488. void DIVSS(X64Reg regOp, const OpArg& arg);
  489. void DIVSD(X64Reg regOp, const OpArg& arg);
  490. void MINSS(X64Reg regOp, const OpArg& arg);
  491. void MINSD(X64Reg regOp, const OpArg& arg);
  492. void MAXSS(X64Reg regOp, const OpArg& arg);
  493. void MAXSD(X64Reg regOp, const OpArg& arg);
  494. void SQRTSS(X64Reg regOp, const OpArg& arg);
  495. void SQRTSD(X64Reg regOp, const OpArg& arg);
  496. void RCPSS(X64Reg regOp, const OpArg& arg);
  497. void RSQRTSS(X64Reg regOp, const OpArg& arg);
  498. // SSE/SSE2: Floating point bitwise (yes)
  499. void CMPSS(X64Reg regOp, const OpArg& arg, u8 compare);
  500. void CMPSD(X64Reg regOp, const OpArg& arg, u8 compare);
  501. void CMPEQSS(X64Reg regOp, const OpArg& arg) { CMPSS(regOp, arg, CMP_EQ); }
  502. void CMPLTSS(X64Reg regOp, const OpArg& arg) { CMPSS(regOp, arg, CMP_LT); }
  503. void CMPLESS(X64Reg regOp, const OpArg& arg) { CMPSS(regOp, arg, CMP_LE); }
  504. void CMPUNORDSS(X64Reg regOp, const OpArg& arg) { CMPSS(regOp, arg, CMP_UNORD); }
  505. void CMPNEQSS(X64Reg regOp, const OpArg& arg) { CMPSS(regOp, arg, CMP_NEQ); }
  506. void CMPNLTSS(X64Reg regOp, const OpArg& arg) { CMPSS(regOp, arg, CMP_NLT); }
  507. void CMPORDSS(X64Reg regOp, const OpArg& arg) { CMPSS(regOp, arg, CMP_ORD); }
  508. // SSE/SSE2: Floating point packed arithmetic (x4 for float, x2 for double)
  509. void ADDPS(X64Reg regOp, const OpArg& arg);
  510. void ADDPD(X64Reg regOp, const OpArg& arg);
  511. void SUBPS(X64Reg regOp, const OpArg& arg);
  512. void SUBPD(X64Reg regOp, const OpArg& arg);
  513. void CMPPS(X64Reg regOp, const OpArg& arg, u8 compare);
  514. void CMPPD(X64Reg regOp, const OpArg& arg, u8 compare);
  515. void MULPS(X64Reg regOp, const OpArg& arg);
  516. void MULPD(X64Reg regOp, const OpArg& arg);
  517. void DIVPS(X64Reg regOp, const OpArg& arg);
  518. void DIVPD(X64Reg regOp, const OpArg& arg);
  519. void MINPS(X64Reg regOp, const OpArg& arg);
  520. void MINPD(X64Reg regOp, const OpArg& arg);
  521. void MAXPS(X64Reg regOp, const OpArg& arg);
  522. void MAXPD(X64Reg regOp, const OpArg& arg);
  523. void SQRTPS(X64Reg regOp, const OpArg& arg);
  524. void SQRTPD(X64Reg regOp, const OpArg& arg);
  525. void RCPPS(X64Reg regOp, const OpArg& arg);
  526. void RSQRTPS(X64Reg regOp, const OpArg& arg);
  527. // SSE/SSE2: Floating point packed bitwise (x4 for float, x2 for double)
  528. void ANDPS(X64Reg regOp, const OpArg& arg);
  529. void ANDPD(X64Reg regOp, const OpArg& arg);
  530. void ANDNPS(X64Reg regOp, const OpArg& arg);
  531. void ANDNPD(X64Reg regOp, const OpArg& arg);
  532. void ORPS(X64Reg regOp, const OpArg& arg);
  533. void ORPD(X64Reg regOp, const OpArg& arg);
  534. void XORPS(X64Reg regOp, const OpArg& arg);
  535. void XORPD(X64Reg regOp, const OpArg& arg);
  536. // SSE/SSE2: Shuffle components. These are tricky - see Intel documentation.
  537. void SHUFPS(X64Reg regOp, const OpArg& arg, u8 shuffle);
  538. void SHUFPD(X64Reg regOp, const OpArg& arg, u8 shuffle);
  539. // SSE/SSE2: Useful alternative to shuffle in some cases.
  540. void MOVDDUP(X64Reg regOp, const OpArg& arg);
  541. // SSE3: Horizontal operations in SIMD registers. Very slow! shufps-based code beats it handily on Ivy.
  542. void HADDPS(X64Reg dest, const OpArg& src);
  543. // SSE4: Further horizontal operations - dot products. These are weirdly flexible, the arg contains both a read mask and a write "mask".
  544. void DPPS(X64Reg dest, const OpArg& src, u8 arg);
  545. void UNPCKLPS(X64Reg dest, const OpArg& src);
  546. void UNPCKHPS(X64Reg dest, const OpArg& src);
  547. void UNPCKLPD(X64Reg dest, const OpArg& src);
  548. void UNPCKHPD(X64Reg dest, const OpArg& src);
  549. // SSE/SSE2: Compares.
  550. void COMISS(X64Reg regOp, const OpArg& arg);
  551. void COMISD(X64Reg regOp, const OpArg& arg);
  552. void UCOMISS(X64Reg regOp, const OpArg& arg);
  553. void UCOMISD(X64Reg regOp, const OpArg& arg);
  554. // SSE/SSE2: Moves. Use the right data type for your data, in most cases.
  555. void MOVAPS(X64Reg regOp, const OpArg& arg);
  556. void MOVAPD(X64Reg regOp, const OpArg& arg);
  557. void MOVAPS(const OpArg& arg, X64Reg regOp);
  558. void MOVAPD(const OpArg& arg, X64Reg regOp);
  559. void MOVUPS(X64Reg regOp, const OpArg& arg);
  560. void MOVUPD(X64Reg regOp, const OpArg& arg);
  561. void MOVUPS(const OpArg& arg, X64Reg regOp);
  562. void MOVUPD(const OpArg& arg, X64Reg regOp);
  563. void MOVDQA(X64Reg regOp, const OpArg& arg);
  564. void MOVDQA(const OpArg& arg, X64Reg regOp);
  565. void MOVDQU(X64Reg regOp, const OpArg& arg);
  566. void MOVDQU(const OpArg& arg, X64Reg regOp);
  567. void MOVSS(X64Reg regOp, const OpArg& arg);
  568. void MOVSD(X64Reg regOp, const OpArg& arg);
  569. void MOVSS(const OpArg& arg, X64Reg regOp);
  570. void MOVSD(const OpArg& arg, X64Reg regOp);
  571. void MOVLPS(X64Reg regOp, const OpArg& arg);
  572. void MOVLPD(X64Reg regOp, const OpArg& arg);
  573. void MOVLPS(const OpArg& arg, X64Reg regOp);
  574. void MOVLPD(const OpArg& arg, X64Reg regOp);
  575. void MOVHPS(X64Reg regOp, const OpArg& arg);
  576. void MOVHPD(X64Reg regOp, const OpArg& arg);
  577. void MOVHPS(const OpArg& arg, X64Reg regOp);
  578. void MOVHPD(const OpArg& arg, X64Reg regOp);
  579. void MOVHLPS(X64Reg regOp1, X64Reg regOp2);
  580. void MOVLHPS(X64Reg regOp1, X64Reg regOp2);
  581. void MOVD_xmm(X64Reg dest, const OpArg& arg);
  582. void MOVQ_xmm(X64Reg dest, OpArg arg);
  583. void MOVD_xmm(const OpArg& arg, X64Reg src);
  584. void MOVQ_xmm(OpArg arg, X64Reg src);
  585. // SSE/SSE2: Generates a mask from the high bits of the components of the packed register in question.
  586. void MOVMSKPS(X64Reg dest, const OpArg& arg);
  587. void MOVMSKPD(X64Reg dest, const OpArg& arg);
  588. // SSE2: Selective byte store, mask in src register. EDI/RDI specifies store address. This is a weird one.
  589. void MASKMOVDQU(X64Reg dest, X64Reg src);
  590. void LDDQU(X64Reg dest, const OpArg& src);
  591. // SSE/SSE2: Data type conversions.
  592. void CVTPS2PD(X64Reg dest, const OpArg& src);
  593. void CVTPD2PS(X64Reg dest, const OpArg& src);
  594. void CVTSS2SD(X64Reg dest, const OpArg& src);
  595. void CVTSI2SS(X64Reg dest, const OpArg& src);
  596. void CVTSD2SS(X64Reg dest, const OpArg& src);
  597. void CVTSI2SD(X64Reg dest, const OpArg& src);
  598. void CVTDQ2PD(X64Reg regOp, const OpArg& arg);
  599. void CVTPD2DQ(X64Reg regOp, const OpArg& arg);
  600. void CVTDQ2PS(X64Reg regOp, const OpArg& arg);
  601. void CVTPS2DQ(X64Reg regOp, const OpArg& arg);
  602. void CVTTPS2DQ(X64Reg regOp, const OpArg& arg);
  603. void CVTTPD2DQ(X64Reg regOp, const OpArg& arg);
  604. // Destinations are X64 regs (rax, rbx, ...) for these instructions.
  605. void CVTSS2SI(X64Reg xregdest, const OpArg& src);
  606. void CVTSD2SI(X64Reg xregdest, const OpArg& src);
  607. void CVTTSS2SI(X64Reg xregdest, const OpArg& arg);
  608. void CVTTSD2SI(X64Reg xregdest, const OpArg& arg);
  609. // SSE2: Packed integer instructions
  610. void PACKSSDW(X64Reg dest, const OpArg& arg);
  611. void PACKSSWB(X64Reg dest, const OpArg& arg);
  612. void PACKUSDW(X64Reg dest, const OpArg& arg);
  613. void PACKUSWB(X64Reg dest, const OpArg& arg);
  614. void PUNPCKLBW(X64Reg dest, const OpArg &arg);
  615. void PUNPCKLWD(X64Reg dest, const OpArg &arg);
  616. void PUNPCKLDQ(X64Reg dest, const OpArg &arg);
  617. void PUNPCKLQDQ(X64Reg dest, const OpArg &arg);
  618. void PTEST(X64Reg dest, const OpArg& arg);
  619. void PAND(X64Reg dest, const OpArg& arg);
  620. void PANDN(X64Reg dest, const OpArg& arg);
  621. void PXOR(X64Reg dest, const OpArg& arg);
  622. void POR(X64Reg dest, const OpArg& arg);
  623. void PADDB(X64Reg dest, const OpArg& arg);
  624. void PADDW(X64Reg dest, const OpArg& arg);
  625. void PADDD(X64Reg dest, const OpArg& arg);
  626. void PADDQ(X64Reg dest, const OpArg& arg);
  627. void PADDSB(X64Reg dest, const OpArg& arg);
  628. void PADDSW(X64Reg dest, const OpArg& arg);
  629. void PADDUSB(X64Reg dest, const OpArg& arg);
  630. void PADDUSW(X64Reg dest, const OpArg& arg);
  631. void PSUBB(X64Reg dest, const OpArg& arg);
  632. void PSUBW(X64Reg dest, const OpArg& arg);
  633. void PSUBD(X64Reg dest, const OpArg& arg);
  634. void PSUBQ(X64Reg dest, const OpArg& arg);
  635. void PSUBSB(X64Reg dest, const OpArg& arg);
  636. void PSUBSW(X64Reg dest, const OpArg& arg);
  637. void PSUBUSB(X64Reg dest, const OpArg& arg);
  638. void PSUBUSW(X64Reg dest, const OpArg& arg);
  639. void PAVGB(X64Reg dest, const OpArg& arg);
  640. void PAVGW(X64Reg dest, const OpArg& arg);
  641. void PCMPEQB(X64Reg dest, const OpArg& arg);
  642. void PCMPEQW(X64Reg dest, const OpArg& arg);
  643. void PCMPEQD(X64Reg dest, const OpArg& arg);
  644. void PCMPGTB(X64Reg dest, const OpArg& arg);
  645. void PCMPGTW(X64Reg dest, const OpArg& arg);
  646. void PCMPGTD(X64Reg dest, const OpArg& arg);
  647. void PEXTRW(X64Reg dest, const OpArg& arg, u8 subreg);
  648. void PINSRW(X64Reg dest, const OpArg& arg, u8 subreg);
  649. void PMADDWD(X64Reg dest, const OpArg& arg);
  650. void PSADBW(X64Reg dest, const OpArg& arg);
  651. void PMAXSW(X64Reg dest, const OpArg& arg);
  652. void PMAXUB(X64Reg dest, const OpArg& arg);
  653. void PMINSW(X64Reg dest, const OpArg& arg);
  654. void PMINUB(X64Reg dest, const OpArg& arg);
  655. // SSE4: More MAX/MIN instructions.
  656. void PMINSB(X64Reg dest, const OpArg& arg);
  657. void PMINSD(X64Reg dest, const OpArg& arg);
  658. void PMINUW(X64Reg dest, const OpArg& arg);
  659. void PMINUD(X64Reg dest, const OpArg& arg);
  660. void PMAXSB(X64Reg dest, const OpArg& arg);
  661. void PMAXSD(X64Reg dest, const OpArg& arg);
  662. void PMAXUW(X64Reg dest, const OpArg& arg);
  663. void PMAXUD(X64Reg dest, const OpArg& arg);
  664. void PMOVMSKB(X64Reg dest, const OpArg& arg);
  665. void PSHUFD(X64Reg dest, const OpArg& arg, u8 shuffle);
  666. void PSHUFB(X64Reg dest, const OpArg& arg);
  667. void PSHUFLW(X64Reg dest, const OpArg& arg, u8 shuffle);
  668. void PSHUFHW(X64Reg dest, const OpArg& arg, u8 shuffle);
  669. void PSRLW(X64Reg reg, int shift);
  670. void PSRLD(X64Reg reg, int shift);
  671. void PSRLQ(X64Reg reg, int shift);
  672. void PSRLQ(X64Reg reg, const OpArg& arg);
  673. void PSRLDQ(X64Reg reg, int shift);
  674. void PSLLW(X64Reg reg, int shift);
  675. void PSLLD(X64Reg reg, int shift);
  676. void PSLLQ(X64Reg reg, int shift);
  677. void PSLLDQ(X64Reg reg, int shift);
  678. void PSRAW(X64Reg reg, int shift);
  679. void PSRAD(X64Reg reg, int shift);
  680. // SSE4: data type conversions
  681. void PMOVSXBW(X64Reg dest, const OpArg& arg);
  682. void PMOVSXBD(X64Reg dest, const OpArg& arg);
  683. void PMOVSXBQ(X64Reg dest, const OpArg& arg);
  684. void PMOVSXWD(X64Reg dest, const OpArg& arg);
  685. void PMOVSXWQ(X64Reg dest, const OpArg& arg);
  686. void PMOVSXDQ(X64Reg dest, const OpArg& arg);
  687. void PMOVZXBW(X64Reg dest, const OpArg& arg);
  688. void PMOVZXBD(X64Reg dest, const OpArg& arg);
  689. void PMOVZXBQ(X64Reg dest, const OpArg& arg);
  690. void PMOVZXWD(X64Reg dest, const OpArg& arg);
  691. void PMOVZXWQ(X64Reg dest, const OpArg& arg);
  692. void PMOVZXDQ(X64Reg dest, const OpArg& arg);
  693. // SSE4: variable blend instructions (xmm0 implicit argument)
  694. void PBLENDVB(X64Reg dest, const OpArg& arg);
  695. void BLENDVPS(X64Reg dest, const OpArg& arg);
  696. void BLENDVPD(X64Reg dest, const OpArg& arg);
  697. void BLENDPS(X64Reg dest, const OpArg& arg, u8 blend);
  698. void BLENDPD(X64Reg dest, const OpArg& arg, u8 blend);
  699. // SSE4: rounding (see FloatRound for mode or use ROUNDNEARSS, etc. helpers.)
  700. void ROUNDSS(X64Reg dest, const OpArg& arg, u8 mode);
  701. void ROUNDSD(X64Reg dest, const OpArg& arg, u8 mode);
  702. void ROUNDPS(X64Reg dest, const OpArg& arg, u8 mode);
  703. void ROUNDPD(X64Reg dest, const OpArg& arg, u8 mode);
  704. void ROUNDNEARSS(X64Reg dest, const OpArg& arg) { ROUNDSS(dest, arg, FROUND_NEAREST); }
  705. void ROUNDFLOORSS(X64Reg dest, const OpArg& arg) { ROUNDSS(dest, arg, FROUND_FLOOR); }
  706. void ROUNDCEILSS(X64Reg dest, const OpArg& arg) { ROUNDSS(dest, arg, FROUND_CEIL); }
  707. void ROUNDZEROSS(X64Reg dest, const OpArg& arg) { ROUNDSS(dest, arg, FROUND_ZERO); }
  708. void ROUNDNEARSD(X64Reg dest, const OpArg& arg) { ROUNDSD(dest, arg, FROUND_NEAREST); }
  709. void ROUNDFLOORSD(X64Reg dest, const OpArg& arg) { ROUNDSD(dest, arg, FROUND_FLOOR); }
  710. void ROUNDCEILSD(X64Reg dest, const OpArg& arg) { ROUNDSD(dest, arg, FROUND_CEIL); }
  711. void ROUNDZEROSD(X64Reg dest, const OpArg& arg) { ROUNDSD(dest, arg, FROUND_ZERO); }
  712. void ROUNDNEARPS(X64Reg dest, const OpArg& arg) { ROUNDPS(dest, arg, FROUND_NEAREST); }
  713. void ROUNDFLOORPS(X64Reg dest, const OpArg& arg) { ROUNDPS(dest, arg, FROUND_FLOOR); }
  714. void ROUNDCEILPS(X64Reg dest, const OpArg& arg) { ROUNDPS(dest, arg, FROUND_CEIL); }
  715. void ROUNDZEROPS(X64Reg dest, const OpArg& arg) { ROUNDPS(dest, arg, FROUND_ZERO); }
  716. void ROUNDNEARPD(X64Reg dest, const OpArg& arg) { ROUNDPD(dest, arg, FROUND_NEAREST); }
  717. void ROUNDFLOORPD(X64Reg dest, const OpArg& arg) { ROUNDPD(dest, arg, FROUND_FLOOR); }
  718. void ROUNDCEILPD(X64Reg dest, const OpArg& arg) { ROUNDPD(dest, arg, FROUND_CEIL); }
  719. void ROUNDZEROPD(X64Reg dest, const OpArg& arg) { ROUNDPD(dest, arg, FROUND_ZERO); }
  720. // AVX
  721. void VADDSD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  722. void VSUBSD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  723. void VMULSD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  724. void VDIVSD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  725. void VADDPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  726. void VSUBPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  727. void VMULPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  728. void VDIVPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  729. void VSQRTSD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  730. void VSHUFPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg, u8 shuffle);
  731. void VUNPCKLPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  732. void VUNPCKHPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  733. void VANDPS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  734. void VANDPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  735. void VANDNPS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  736. void VANDNPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  737. void VORPS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  738. void VORPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  739. void VXORPS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  740. void VXORPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  741. void VPAND(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  742. void VPANDN(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  743. void VPOR(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  744. void VPXOR(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  745. // FMA3
  746. void VFMADD132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  747. void VFMADD213PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  748. void VFMADD231PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  749. void VFMADD132PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  750. void VFMADD213PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  751. void VFMADD231PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  752. void VFMADD132SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  753. void VFMADD213SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  754. void VFMADD231SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  755. void VFMADD132SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  756. void VFMADD213SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  757. void VFMADD231SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  758. void VFMSUB132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  759. void VFMSUB213PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  760. void VFMSUB231PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  761. void VFMSUB132PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  762. void VFMSUB213PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  763. void VFMSUB231PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  764. void VFMSUB132SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  765. void VFMSUB213SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  766. void VFMSUB231SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  767. void VFMSUB132SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  768. void VFMSUB213SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  769. void VFMSUB231SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  770. void VFNMADD132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  771. void VFNMADD213PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  772. void VFNMADD231PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  773. void VFNMADD132PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  774. void VFNMADD213PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  775. void VFNMADD231PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  776. void VFNMADD132SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  777. void VFNMADD213SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  778. void VFNMADD231SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  779. void VFNMADD132SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  780. void VFNMADD213SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  781. void VFNMADD231SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  782. void VFNMSUB132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  783. void VFNMSUB213PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  784. void VFNMSUB231PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  785. void VFNMSUB132PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  786. void VFNMSUB213PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  787. void VFNMSUB231PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  788. void VFNMSUB132SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  789. void VFNMSUB213SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  790. void VFNMSUB231SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  791. void VFNMSUB132SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  792. void VFNMSUB213SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  793. void VFNMSUB231SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  794. void VFMADDSUB132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  795. void VFMADDSUB213PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  796. void VFMADDSUB231PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  797. void VFMADDSUB132PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  798. void VFMADDSUB213PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  799. void VFMADDSUB231PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  800. void VFMSUBADD132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  801. void VFMSUBADD213PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  802. void VFMSUBADD231PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  803. void VFMSUBADD132PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  804. void VFMSUBADD213PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  805. void VFMSUBADD231PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  806. // VEX GPR instructions
  807. void SARX(int bits, X64Reg regOp1, const OpArg& arg, X64Reg regOp2);
  808. void SHLX(int bits, X64Reg regOp1, const OpArg& arg, X64Reg regOp2);
  809. void SHRX(int bits, X64Reg regOp1, const OpArg& arg, X64Reg regOp2);
  810. void RORX(int bits, X64Reg regOp, const OpArg& arg, u8 rotate);
  811. void PEXT(int bits, X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  812. void PDEP(int bits, X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  813. void MULX(int bits, X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  814. void BZHI(int bits, X64Reg regOp1, const OpArg& arg, X64Reg regOp2);
  815. void BLSR(int bits, X64Reg regOp, const OpArg& arg);
  816. void BLSMSK(int bits, X64Reg regOp, const OpArg& arg);
  817. void BLSI(int bits, X64Reg regOp, const OpArg& arg);
  818. void BEXTR(int bits, X64Reg regOp1, const OpArg& arg, X64Reg regOp2);
  819. void ANDN(int bits, X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  820. void RDTSC();
  821. // Utility functions
  822. // The difference between this and CALL is that this aligns the stack
  823. // where appropriate.
  824. void ABI_CallFunction(const void* func);
  825. template <typename T>
  826. void ABI_CallFunction(T (*func)()) {
  827. ABI_CallFunction((const void*)func);
  828. }
  829. void ABI_CallFunction(const u8* func) {
  830. ABI_CallFunction((const void*)func);
  831. }
  832. void ABI_CallFunctionC16(const void* func, u16 param1);
  833. void ABI_CallFunctionCC16(const void* func, u32 param1, u16 param2);
  834. // These only support u32 parameters, but that's enough for a lot of uses.
  835. // These will destroy the 1 or 2 first "parameter regs".
  836. void ABI_CallFunctionC(const void* func, u32 param1);
  837. void ABI_CallFunctionCC(const void* func, u32 param1, u32 param2);
  838. void ABI_CallFunctionCCC(const void* func, u32 param1, u32 param2, u32 param3);
  839. void ABI_CallFunctionCCP(const void* func, u32 param1, u32 param2, void* param3);
  840. void ABI_CallFunctionCCCP(const void* func, u32 param1, u32 param2, u32 param3, void* param4);
  841. void ABI_CallFunctionP(const void* func, void* param1);
  842. void ABI_CallFunctionPA(const void* func, void* param1, const OpArg& arg2);
  843. void ABI_CallFunctionPAA(const void* func, void* param1, const OpArg& arg2, const OpArg& arg3);
  844. void ABI_CallFunctionPPC(const void* func, void* param1, void* param2, u32 param3);
  845. void ABI_CallFunctionAC(const void* func, const OpArg& arg1, u32 param2);
  846. void ABI_CallFunctionACC(const void* func, const OpArg& arg1, u32 param2, u32 param3);
  847. void ABI_CallFunctionA(const void* func, const OpArg& arg1);
  848. void ABI_CallFunctionAA(const void* func, const OpArg& arg1, const OpArg& arg2);
  849. // Pass a register as a parameter.
  850. void ABI_CallFunctionR(const void* func, X64Reg reg1);
  851. void ABI_CallFunctionRR(const void* func, X64Reg reg1, X64Reg reg2);
  852. template <typename Tr, typename T1>
  853. void ABI_CallFunctionC(Tr (*func)(T1), u32 param1) {
  854. ABI_CallFunctionC((const void*)func, param1);
  855. }
  856. /**
  857. * Saves specified registers and adjusts the stack to be 16-byte aligned as required by the ABI
  858. *
  859. * @param mask Registers to push on the stack (high 16 bits are XMMs, low 16 bits are GPRs)
  860. * @param rsp_alignment Current alignment of the stack pointer, must be 0 or 8
  861. * @param needed_frame_size Additional space needed, e.g., for function arguments passed on the stack
  862. * @return Size of the shadow space, i.e., offset of the frame
  863. */
  864. size_t ABI_PushRegistersAndAdjustStack(BitSet32 mask, size_t rsp_alignment, size_t needed_frame_size = 0);
  865. /**
  866. * Restores specified registers and adjusts the stack to its original alignment, i.e., the alignment before
  867. * the matching PushRegistersAndAdjustStack.
  868. *
  869. * @param mask Registers to restores from the stack (high 16 bits are XMMs, low 16 bits are GPRs)
  870. * @param rsp_alignment Original alignment before the matching PushRegistersAndAdjustStack, must be 0 or 8
  871. * @param needed_frame_size Additional space that was needed
  872. * @warning Stack must be currently 16-byte aligned
  873. */
  874. void ABI_PopRegistersAndAdjustStack(BitSet32 mask, size_t rsp_alignment, size_t needed_frame_size = 0);
  875. #ifdef _M_IX86
  876. static int ABI_GetNumXMMRegs() { return 8; }
  877. #else
  878. static int ABI_GetNumXMMRegs() { return 16; }
  879. #endif
  880. }; // class XEmitter
  881. // Everything that needs to generate X86 code should inherit from this.
  882. // You get memory management for free, plus, you can use all the MOV etc functions without
  883. // having to prefix them with gen-> or something similar.
  884. class XCodeBlock : public CodeBlock<XEmitter> {
  885. public:
  886. void PoisonMemory() override;
  887. };
  888. } // namespace