emitter.h 40 KB

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