emitter.h 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046
  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/common_types.h"
  16. #include "common/code_block.h"
  17. #if defined(ARCHITECTURE_x86_64) && !defined(_ARCH_64)
  18. #define _ARCH_64
  19. #endif
  20. #ifdef _ARCH_64
  21. #define PTRBITS 64
  22. #else
  23. #define PTRBITS 32
  24. #endif
  25. namespace Gen
  26. {
  27. enum X64Reg
  28. {
  29. EAX = 0, EBX = 3, ECX = 1, EDX = 2,
  30. ESI = 6, EDI = 7, EBP = 5, ESP = 4,
  31. RAX = 0, RBX = 3, RCX = 1, RDX = 2,
  32. RSI = 6, RDI = 7, RBP = 5, RSP = 4,
  33. R8 = 8, R9 = 9, R10 = 10,R11 = 11,
  34. R12 = 12,R13 = 13,R14 = 14,R15 = 15,
  35. AL = 0, BL = 3, CL = 1, DL = 2,
  36. SIL = 6, DIL = 7, BPL = 5, SPL = 4,
  37. AH = 0x104, BH = 0x107, CH = 0x105, DH = 0x106,
  38. AX = 0, BX = 3, CX = 1, DX = 2,
  39. SI = 6, DI = 7, BP = 5, SP = 4,
  40. XMM0=0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
  41. XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15,
  42. YMM0=0, YMM1, YMM2, YMM3, YMM4, YMM5, YMM6, YMM7,
  43. YMM8, YMM9, YMM10, YMM11, YMM12, YMM13, YMM14, YMM15,
  44. INVALID_REG = 0xFFFFFFFF
  45. };
  46. enum CCFlags
  47. {
  48. CC_O = 0,
  49. CC_NO = 1,
  50. CC_B = 2, CC_C = 2, CC_NAE = 2,
  51. CC_NB = 3, CC_NC = 3, CC_AE = 3,
  52. CC_Z = 4, CC_E = 4,
  53. CC_NZ = 5, CC_NE = 5,
  54. CC_BE = 6, CC_NA = 6,
  55. CC_NBE = 7, CC_A = 7,
  56. CC_S = 8,
  57. CC_NS = 9,
  58. CC_P = 0xA, CC_PE = 0xA,
  59. CC_NP = 0xB, CC_PO = 0xB,
  60. CC_L = 0xC, CC_NGE = 0xC,
  61. CC_NL = 0xD, CC_GE = 0xD,
  62. CC_LE = 0xE, CC_NG = 0xE,
  63. CC_NLE = 0xF, CC_G = 0xF
  64. };
  65. enum
  66. {
  67. NUMGPRs = 16,
  68. NUMXMMs = 16,
  69. };
  70. enum
  71. {
  72. SCALE_NONE = 0,
  73. SCALE_1 = 1,
  74. SCALE_2 = 2,
  75. SCALE_4 = 4,
  76. SCALE_8 = 8,
  77. SCALE_ATREG = 16,
  78. //SCALE_NOBASE_1 is not supported and can be replaced with SCALE_ATREG
  79. SCALE_NOBASE_2 = 34,
  80. SCALE_NOBASE_4 = 36,
  81. SCALE_NOBASE_8 = 40,
  82. SCALE_RIP = 0xFF,
  83. SCALE_IMM8 = 0xF0,
  84. SCALE_IMM16 = 0xF1,
  85. SCALE_IMM32 = 0xF2,
  86. SCALE_IMM64 = 0xF3,
  87. };
  88. enum NormalOp {
  89. nrmADD,
  90. nrmADC,
  91. nrmSUB,
  92. nrmSBB,
  93. nrmAND,
  94. nrmOR ,
  95. nrmXOR,
  96. nrmMOV,
  97. nrmTEST,
  98. nrmCMP,
  99. nrmXCHG,
  100. };
  101. enum {
  102. CMP_EQ = 0,
  103. CMP_LT = 1,
  104. CMP_LE = 2,
  105. CMP_UNORD = 3,
  106. CMP_NEQ = 4,
  107. CMP_NLT = 5,
  108. CMP_NLE = 6,
  109. CMP_ORD = 7,
  110. };
  111. enum FloatOp {
  112. floatLD = 0,
  113. floatST = 2,
  114. floatSTP = 3,
  115. floatLD80 = 5,
  116. floatSTP80 = 7,
  117. floatINVALID = -1,
  118. };
  119. enum FloatRound {
  120. FROUND_NEAREST = 0,
  121. FROUND_FLOOR = 1,
  122. FROUND_CEIL = 2,
  123. FROUND_ZERO = 3,
  124. FROUND_MXCSR = 4,
  125. FROUND_RAISE_PRECISION = 0,
  126. FROUND_IGNORE_PRECISION = 8,
  127. };
  128. class XEmitter;
  129. // RIP addressing does not benefit from micro op fusion on Core arch
  130. struct OpArg
  131. {
  132. OpArg() {} // dummy op arg, used for storage
  133. OpArg(u64 _offset, int _scale, X64Reg rmReg = RAX, X64Reg scaledReg = RAX)
  134. {
  135. operandReg = 0;
  136. scale = (u8)_scale;
  137. offsetOrBaseReg = (u16)rmReg;
  138. indexReg = (u16)scaledReg;
  139. //if scale == 0 never mind offsetting
  140. offset = _offset;
  141. }
  142. bool operator==(const OpArg &b) const
  143. {
  144. return operandReg == b.operandReg && scale == b.scale && offsetOrBaseReg == b.offsetOrBaseReg &&
  145. indexReg == b.indexReg && offset == b.offset;
  146. }
  147. void WriteRex(XEmitter *emit, int opBits, int bits, int customOp = -1) const;
  148. void WriteVex(XEmitter* emit, X64Reg regOp1, X64Reg regOp2, int L, int pp, int mmmmm, int W = 0) const;
  149. void WriteRest(XEmitter *emit, int extraBytes=0, X64Reg operandReg=INVALID_REG, bool warn_64bit_offset = true) const;
  150. void WriteFloatModRM(XEmitter *emit, FloatOp op);
  151. void WriteSingleByteOp(XEmitter *emit, u8 op, X64Reg operandReg, int bits);
  152. // This one is public - must be written to
  153. u64 offset; // use RIP-relative as much as possible - 64-bit immediates are not available.
  154. u16 operandReg;
  155. void WriteNormalOp(XEmitter *emit, bool toRM, NormalOp op, const OpArg &operand, int bits) const;
  156. bool IsImm() const {return scale == SCALE_IMM8 || scale == SCALE_IMM16 || scale == SCALE_IMM32 || scale == SCALE_IMM64;}
  157. bool IsSimpleReg() const {return scale == SCALE_NONE;}
  158. bool IsSimpleReg(X64Reg reg) const
  159. {
  160. if (!IsSimpleReg())
  161. return false;
  162. return GetSimpleReg() == reg;
  163. }
  164. bool CanDoOpWith(const OpArg &other) const
  165. {
  166. if (IsSimpleReg()) return true;
  167. if (!IsSimpleReg() && !other.IsSimpleReg() && !other.IsImm()) return false;
  168. return true;
  169. }
  170. int GetImmBits() const
  171. {
  172. switch (scale)
  173. {
  174. case SCALE_IMM8: return 8;
  175. case SCALE_IMM16: return 16;
  176. case SCALE_IMM32: return 32;
  177. case SCALE_IMM64: return 64;
  178. default: return -1;
  179. }
  180. }
  181. void SetImmBits(int bits) {
  182. switch (bits)
  183. {
  184. case 8: scale = SCALE_IMM8; break;
  185. case 16: scale = SCALE_IMM16; break;
  186. case 32: scale = SCALE_IMM32; break;
  187. case 64: scale = SCALE_IMM64; break;
  188. }
  189. }
  190. X64Reg GetSimpleReg() const
  191. {
  192. if (scale == SCALE_NONE)
  193. return (X64Reg)offsetOrBaseReg;
  194. else
  195. return INVALID_REG;
  196. }
  197. u32 GetImmValue() const {
  198. return (u32)offset;
  199. }
  200. // For loops.
  201. void IncreaseOffset(int sz) {
  202. offset += sz;
  203. }
  204. private:
  205. u8 scale;
  206. u16 offsetOrBaseReg;
  207. u16 indexReg;
  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(u32 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 RSQRTSS(X64Reg regOp, const OpArg& arg);
  500. // SSE/SSE2: Floating point bitwise (yes)
  501. void CMPSS(X64Reg regOp, const OpArg& arg, u8 compare);
  502. void CMPSD(X64Reg regOp, const OpArg& arg, u8 compare);
  503. void CMPEQSS(X64Reg regOp, const OpArg& arg) { CMPSS(regOp, arg, CMP_EQ); }
  504. void CMPLTSS(X64Reg regOp, const OpArg& arg) { CMPSS(regOp, arg, CMP_LT); }
  505. void CMPLESS(X64Reg regOp, const OpArg& arg) { CMPSS(regOp, arg, CMP_LE); }
  506. void CMPUNORDSS(X64Reg regOp, const OpArg& arg) { CMPSS(regOp, arg, CMP_UNORD); }
  507. void CMPNEQSS(X64Reg regOp, const OpArg& arg) { CMPSS(regOp, arg, CMP_NEQ); }
  508. void CMPNLTSS(X64Reg regOp, const OpArg& arg) { CMPSS(regOp, arg, CMP_NLT); }
  509. void CMPORDSS(X64Reg regOp, const OpArg& arg) { CMPSS(regOp, arg, CMP_ORD); }
  510. // SSE/SSE2: Floating point packed arithmetic (x4 for float, x2 for double)
  511. void ADDPS(X64Reg regOp, const OpArg& arg);
  512. void ADDPD(X64Reg regOp, const OpArg& arg);
  513. void SUBPS(X64Reg regOp, const OpArg& arg);
  514. void SUBPD(X64Reg regOp, const OpArg& arg);
  515. void CMPPS(X64Reg regOp, const OpArg& arg, u8 compare);
  516. void CMPPD(X64Reg regOp, const OpArg& arg, u8 compare);
  517. void MULPS(X64Reg regOp, const OpArg& arg);
  518. void MULPD(X64Reg regOp, const OpArg& arg);
  519. void DIVPS(X64Reg regOp, const OpArg& arg);
  520. void DIVPD(X64Reg regOp, const OpArg& arg);
  521. void MINPS(X64Reg regOp, const OpArg& arg);
  522. void MINPD(X64Reg regOp, const OpArg& arg);
  523. void MAXPS(X64Reg regOp, const OpArg& arg);
  524. void MAXPD(X64Reg regOp, const OpArg& arg);
  525. void SQRTPS(X64Reg regOp, const OpArg& arg);
  526. void SQRTPD(X64Reg regOp, const OpArg& arg);
  527. void RCPPS(X64Reg regOp, const OpArg& arg);
  528. void RSQRTPS(X64Reg regOp, const OpArg& arg);
  529. // SSE/SSE2: Floating point packed bitwise (x4 for float, x2 for double)
  530. void ANDPS(X64Reg regOp, const OpArg& arg);
  531. void ANDPD(X64Reg regOp, const OpArg& arg);
  532. void ANDNPS(X64Reg regOp, const OpArg& arg);
  533. void ANDNPD(X64Reg regOp, const OpArg& arg);
  534. void ORPS(X64Reg regOp, const OpArg& arg);
  535. void ORPD(X64Reg regOp, const OpArg& arg);
  536. void XORPS(X64Reg regOp, const OpArg& arg);
  537. void XORPD(X64Reg regOp, const OpArg& arg);
  538. // SSE/SSE2: Shuffle components. These are tricky - see Intel documentation.
  539. void SHUFPS(X64Reg regOp, const OpArg& arg, u8 shuffle);
  540. void SHUFPD(X64Reg regOp, const OpArg& arg, u8 shuffle);
  541. // SSE/SSE2: Useful alternative to shuffle in some cases.
  542. void MOVDDUP(X64Reg regOp, const OpArg& arg);
  543. // SSE3: Horizontal operations in SIMD registers. Very slow! shufps-based code beats it handily on Ivy.
  544. void HADDPS(X64Reg dest, const OpArg& src);
  545. // SSE4: Further horizontal operations - dot products. These are weirdly flexible, the arg contains both a read mask and a write "mask".
  546. void DPPS(X64Reg dest, const OpArg& src, u8 arg);
  547. void UNPCKLPS(X64Reg dest, const OpArg& src);
  548. void UNPCKHPS(X64Reg dest, const OpArg& src);
  549. void UNPCKLPD(X64Reg dest, const OpArg& src);
  550. void UNPCKHPD(X64Reg dest, const OpArg& src);
  551. // SSE/SSE2: Compares.
  552. void COMISS(X64Reg regOp, const OpArg& arg);
  553. void COMISD(X64Reg regOp, const OpArg& arg);
  554. void UCOMISS(X64Reg regOp, const OpArg& arg);
  555. void UCOMISD(X64Reg regOp, const OpArg& arg);
  556. // SSE/SSE2: Moves. Use the right data type for your data, in most cases.
  557. void MOVAPS(X64Reg regOp, const OpArg& arg);
  558. void MOVAPD(X64Reg regOp, const OpArg& arg);
  559. void MOVAPS(const OpArg& arg, X64Reg regOp);
  560. void MOVAPD(const OpArg& arg, X64Reg regOp);
  561. void MOVUPS(X64Reg regOp, const OpArg& arg);
  562. void MOVUPD(X64Reg regOp, const OpArg& arg);
  563. void MOVUPS(const OpArg& arg, X64Reg regOp);
  564. void MOVUPD(const OpArg& arg, X64Reg regOp);
  565. void MOVDQA(X64Reg regOp, const OpArg& arg);
  566. void MOVDQA(const OpArg& arg, X64Reg regOp);
  567. void MOVDQU(X64Reg regOp, const OpArg& arg);
  568. void MOVDQU(const OpArg& arg, X64Reg regOp);
  569. void MOVSS(X64Reg regOp, const OpArg& arg);
  570. void MOVSD(X64Reg regOp, const OpArg& arg);
  571. void MOVSS(const OpArg& arg, X64Reg regOp);
  572. void MOVSD(const OpArg& arg, X64Reg regOp);
  573. void MOVLPS(X64Reg regOp, const OpArg& arg);
  574. void MOVLPD(X64Reg regOp, const OpArg& arg);
  575. void MOVLPS(const OpArg& arg, X64Reg regOp);
  576. void MOVLPD(const OpArg& arg, X64Reg regOp);
  577. void MOVHPS(X64Reg regOp, const OpArg& arg);
  578. void MOVHPD(X64Reg regOp, const OpArg& arg);
  579. void MOVHPS(const OpArg& arg, X64Reg regOp);
  580. void MOVHPD(const OpArg& arg, X64Reg regOp);
  581. void MOVHLPS(X64Reg regOp1, X64Reg regOp2);
  582. void MOVLHPS(X64Reg regOp1, X64Reg regOp2);
  583. void MOVD_xmm(X64Reg dest, const OpArg& arg);
  584. void MOVQ_xmm(X64Reg dest, OpArg arg);
  585. void MOVD_xmm(const OpArg& arg, X64Reg src);
  586. void MOVQ_xmm(OpArg arg, X64Reg src);
  587. // SSE/SSE2: Generates a mask from the high bits of the components of the packed register in question.
  588. void MOVMSKPS(X64Reg dest, const OpArg& arg);
  589. void MOVMSKPD(X64Reg dest, const OpArg& arg);
  590. // SSE2: Selective byte store, mask in src register. EDI/RDI specifies store address. This is a weird one.
  591. void MASKMOVDQU(X64Reg dest, X64Reg src);
  592. void LDDQU(X64Reg dest, const OpArg& src);
  593. // SSE/SSE2: Data type conversions.
  594. void CVTPS2PD(X64Reg dest, const OpArg& src);
  595. void CVTPD2PS(X64Reg dest, const OpArg& src);
  596. void CVTSS2SD(X64Reg dest, const OpArg& src);
  597. void CVTSI2SS(X64Reg dest, const OpArg& src);
  598. void CVTSD2SS(X64Reg dest, const OpArg& src);
  599. void CVTSI2SD(X64Reg dest, const OpArg& src);
  600. void CVTDQ2PD(X64Reg regOp, const OpArg& arg);
  601. void CVTPD2DQ(X64Reg regOp, const OpArg& arg);
  602. void CVTDQ2PS(X64Reg regOp, const OpArg& arg);
  603. void CVTPS2DQ(X64Reg regOp, const OpArg& arg);
  604. void CVTTPS2DQ(X64Reg regOp, const OpArg& arg);
  605. void CVTTPD2DQ(X64Reg regOp, const OpArg& arg);
  606. // Destinations are X64 regs (rax, rbx, ...) for these instructions.
  607. void CVTSS2SI(X64Reg xregdest, const OpArg& src);
  608. void CVTSD2SI(X64Reg xregdest, const OpArg& src);
  609. void CVTTSS2SI(X64Reg xregdest, const OpArg& arg);
  610. void CVTTSD2SI(X64Reg xregdest, const OpArg& arg);
  611. // SSE2: Packed integer instructions
  612. void PACKSSDW(X64Reg dest, const OpArg& arg);
  613. void PACKSSWB(X64Reg dest, const OpArg& arg);
  614. void PACKUSDW(X64Reg dest, const OpArg& arg);
  615. void PACKUSWB(X64Reg dest, const OpArg& arg);
  616. void PUNPCKLBW(X64Reg dest, const OpArg &arg);
  617. void PUNPCKLWD(X64Reg dest, const OpArg &arg);
  618. void PUNPCKLDQ(X64Reg dest, const OpArg &arg);
  619. void PUNPCKLQDQ(X64Reg dest, const OpArg &arg);
  620. void PTEST(X64Reg dest, const OpArg& arg);
  621. void PAND(X64Reg dest, const OpArg& arg);
  622. void PANDN(X64Reg dest, const OpArg& arg);
  623. void PXOR(X64Reg dest, const OpArg& arg);
  624. void POR(X64Reg dest, const OpArg& arg);
  625. void PADDB(X64Reg dest, const OpArg& arg);
  626. void PADDW(X64Reg dest, const OpArg& arg);
  627. void PADDD(X64Reg dest, const OpArg& arg);
  628. void PADDQ(X64Reg dest, const OpArg& arg);
  629. void PADDSB(X64Reg dest, const OpArg& arg);
  630. void PADDSW(X64Reg dest, const OpArg& arg);
  631. void PADDUSB(X64Reg dest, const OpArg& arg);
  632. void PADDUSW(X64Reg dest, const OpArg& arg);
  633. void PSUBB(X64Reg dest, const OpArg& arg);
  634. void PSUBW(X64Reg dest, const OpArg& arg);
  635. void PSUBD(X64Reg dest, const OpArg& arg);
  636. void PSUBQ(X64Reg dest, const OpArg& arg);
  637. void PSUBSB(X64Reg dest, const OpArg& arg);
  638. void PSUBSW(X64Reg dest, const OpArg& arg);
  639. void PSUBUSB(X64Reg dest, const OpArg& arg);
  640. void PSUBUSW(X64Reg dest, const OpArg& arg);
  641. void PAVGB(X64Reg dest, const OpArg& arg);
  642. void PAVGW(X64Reg dest, const OpArg& arg);
  643. void PCMPEQB(X64Reg dest, const OpArg& arg);
  644. void PCMPEQW(X64Reg dest, const OpArg& arg);
  645. void PCMPEQD(X64Reg dest, const OpArg& arg);
  646. void PCMPGTB(X64Reg dest, const OpArg& arg);
  647. void PCMPGTW(X64Reg dest, const OpArg& arg);
  648. void PCMPGTD(X64Reg dest, const OpArg& arg);
  649. void PEXTRW(X64Reg dest, const OpArg& arg, u8 subreg);
  650. void PINSRW(X64Reg dest, const OpArg& arg, u8 subreg);
  651. void PMADDWD(X64Reg dest, const OpArg& arg);
  652. void PSADBW(X64Reg dest, const OpArg& arg);
  653. void PMAXSW(X64Reg dest, const OpArg& arg);
  654. void PMAXUB(X64Reg dest, const OpArg& arg);
  655. void PMINSW(X64Reg dest, const OpArg& arg);
  656. void PMINUB(X64Reg dest, const OpArg& arg);
  657. // SSE4: More MAX/MIN instructions.
  658. void PMINSB(X64Reg dest, const OpArg& arg);
  659. void PMINSD(X64Reg dest, const OpArg& arg);
  660. void PMINUW(X64Reg dest, const OpArg& arg);
  661. void PMINUD(X64Reg dest, const OpArg& arg);
  662. void PMAXSB(X64Reg dest, const OpArg& arg);
  663. void PMAXSD(X64Reg dest, const OpArg& arg);
  664. void PMAXUW(X64Reg dest, const OpArg& arg);
  665. void PMAXUD(X64Reg dest, const OpArg& arg);
  666. void PMOVMSKB(X64Reg dest, const OpArg& arg);
  667. void PSHUFD(X64Reg dest, const OpArg& arg, u8 shuffle);
  668. void PSHUFB(X64Reg dest, const OpArg& arg);
  669. void PSHUFLW(X64Reg dest, const OpArg& arg, u8 shuffle);
  670. void PSHUFHW(X64Reg dest, const OpArg& arg, u8 shuffle);
  671. void PSRLW(X64Reg reg, int shift);
  672. void PSRLD(X64Reg reg, int shift);
  673. void PSRLQ(X64Reg reg, int shift);
  674. void PSRLQ(X64Reg reg, const OpArg& arg);
  675. void PSRLDQ(X64Reg reg, int shift);
  676. void PSLLW(X64Reg reg, int shift);
  677. void PSLLD(X64Reg reg, int shift);
  678. void PSLLQ(X64Reg reg, int shift);
  679. void PSLLDQ(X64Reg reg, int shift);
  680. void PSRAW(X64Reg reg, int shift);
  681. void PSRAD(X64Reg reg, int shift);
  682. // SSE4: data type conversions
  683. void PMOVSXBW(X64Reg dest, const OpArg& arg);
  684. void PMOVSXBD(X64Reg dest, const OpArg& arg);
  685. void PMOVSXBQ(X64Reg dest, const OpArg& arg);
  686. void PMOVSXWD(X64Reg dest, const OpArg& arg);
  687. void PMOVSXWQ(X64Reg dest, const OpArg& arg);
  688. void PMOVSXDQ(X64Reg dest, const OpArg& arg);
  689. void PMOVZXBW(X64Reg dest, const OpArg& arg);
  690. void PMOVZXBD(X64Reg dest, const OpArg& arg);
  691. void PMOVZXBQ(X64Reg dest, const OpArg& arg);
  692. void PMOVZXWD(X64Reg dest, const OpArg& arg);
  693. void PMOVZXWQ(X64Reg dest, const OpArg& arg);
  694. void PMOVZXDQ(X64Reg dest, const OpArg& arg);
  695. // SSE4: variable blend instructions (xmm0 implicit argument)
  696. void PBLENDVB(X64Reg dest, const OpArg& arg);
  697. void BLENDVPS(X64Reg dest, const OpArg& arg);
  698. void BLENDVPD(X64Reg dest, const OpArg& arg);
  699. void BLENDPS(X64Reg dest, const OpArg& arg, u8 blend);
  700. void BLENDPD(X64Reg dest, const OpArg& arg, u8 blend);
  701. // SSE4: rounding (see FloatRound for mode or use ROUNDNEARSS, etc. helpers.)
  702. void ROUNDSS(X64Reg dest, const OpArg& arg, u8 mode);
  703. void ROUNDSD(X64Reg dest, const OpArg& arg, u8 mode);
  704. void ROUNDPS(X64Reg dest, const OpArg& arg, u8 mode);
  705. void ROUNDPD(X64Reg dest, const OpArg& arg, u8 mode);
  706. void ROUNDNEARSS(X64Reg dest, const OpArg& arg) { ROUNDSS(dest, arg, FROUND_NEAREST); }
  707. void ROUNDFLOORSS(X64Reg dest, const OpArg& arg) { ROUNDSS(dest, arg, FROUND_FLOOR); }
  708. void ROUNDCEILSS(X64Reg dest, const OpArg& arg) { ROUNDSS(dest, arg, FROUND_CEIL); }
  709. void ROUNDZEROSS(X64Reg dest, const OpArg& arg) { ROUNDSS(dest, arg, FROUND_ZERO); }
  710. void ROUNDNEARSD(X64Reg dest, const OpArg& arg) { ROUNDSD(dest, arg, FROUND_NEAREST); }
  711. void ROUNDFLOORSD(X64Reg dest, const OpArg& arg) { ROUNDSD(dest, arg, FROUND_FLOOR); }
  712. void ROUNDCEILSD(X64Reg dest, const OpArg& arg) { ROUNDSD(dest, arg, FROUND_CEIL); }
  713. void ROUNDZEROSD(X64Reg dest, const OpArg& arg) { ROUNDSD(dest, arg, FROUND_ZERO); }
  714. void ROUNDNEARPS(X64Reg dest, const OpArg& arg) { ROUNDPS(dest, arg, FROUND_NEAREST); }
  715. void ROUNDFLOORPS(X64Reg dest, const OpArg& arg) { ROUNDPS(dest, arg, FROUND_FLOOR); }
  716. void ROUNDCEILPS(X64Reg dest, const OpArg& arg) { ROUNDPS(dest, arg, FROUND_CEIL); }
  717. void ROUNDZEROPS(X64Reg dest, const OpArg& arg) { ROUNDPS(dest, arg, FROUND_ZERO); }
  718. void ROUNDNEARPD(X64Reg dest, const OpArg& arg) { ROUNDPD(dest, arg, FROUND_NEAREST); }
  719. void ROUNDFLOORPD(X64Reg dest, const OpArg& arg) { ROUNDPD(dest, arg, FROUND_FLOOR); }
  720. void ROUNDCEILPD(X64Reg dest, const OpArg& arg) { ROUNDPD(dest, arg, FROUND_CEIL); }
  721. void ROUNDZEROPD(X64Reg dest, const OpArg& arg) { ROUNDPD(dest, arg, FROUND_ZERO); }
  722. // AVX
  723. void VADDSD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  724. void VSUBSD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  725. void VMULSD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  726. void VDIVSD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  727. void VADDPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  728. void VSUBPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  729. void VMULPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  730. void VDIVPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  731. void VSQRTSD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  732. void VSHUFPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg, u8 shuffle);
  733. void VUNPCKLPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  734. void VUNPCKHPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  735. void VANDPS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  736. void VANDPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  737. void VANDNPS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  738. void VANDNPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  739. void VORPS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  740. void VORPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  741. void VXORPS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  742. void VXORPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  743. void VPAND(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  744. void VPANDN(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  745. void VPOR(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  746. void VPXOR(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  747. // FMA3
  748. void VFMADD132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  749. void VFMADD213PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  750. void VFMADD231PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  751. void VFMADD132PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  752. void VFMADD213PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  753. void VFMADD231PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  754. void VFMADD132SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  755. void VFMADD213SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  756. void VFMADD231SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  757. void VFMADD132SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  758. void VFMADD213SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  759. void VFMADD231SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  760. void VFMSUB132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  761. void VFMSUB213PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  762. void VFMSUB231PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  763. void VFMSUB132PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  764. void VFMSUB213PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  765. void VFMSUB231PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  766. void VFMSUB132SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  767. void VFMSUB213SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  768. void VFMSUB231SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  769. void VFMSUB132SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  770. void VFMSUB213SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  771. void VFMSUB231SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  772. void VFNMADD132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  773. void VFNMADD213PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  774. void VFNMADD231PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  775. void VFNMADD132PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  776. void VFNMADD213PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  777. void VFNMADD231PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  778. void VFNMADD132SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  779. void VFNMADD213SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  780. void VFNMADD231SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  781. void VFNMADD132SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  782. void VFNMADD213SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  783. void VFNMADD231SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  784. void VFNMSUB132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  785. void VFNMSUB213PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  786. void VFNMSUB231PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  787. void VFNMSUB132PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  788. void VFNMSUB213PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  789. void VFNMSUB231PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  790. void VFNMSUB132SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  791. void VFNMSUB213SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  792. void VFNMSUB231SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  793. void VFNMSUB132SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  794. void VFNMSUB213SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  795. void VFNMSUB231SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  796. void VFMADDSUB132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  797. void VFMADDSUB213PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  798. void VFMADDSUB231PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  799. void VFMADDSUB132PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  800. void VFMADDSUB213PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  801. void VFMADDSUB231PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  802. void VFMSUBADD132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  803. void VFMSUBADD213PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  804. void VFMSUBADD231PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  805. void VFMSUBADD132PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  806. void VFMSUBADD213PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  807. void VFMSUBADD231PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  808. // VEX GPR instructions
  809. void SARX(int bits, X64Reg regOp1, const OpArg& arg, X64Reg regOp2);
  810. void SHLX(int bits, X64Reg regOp1, const OpArg& arg, X64Reg regOp2);
  811. void SHRX(int bits, X64Reg regOp1, const OpArg& arg, X64Reg regOp2);
  812. void RORX(int bits, X64Reg regOp, const OpArg& arg, u8 rotate);
  813. void PEXT(int bits, X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  814. void PDEP(int bits, X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  815. void MULX(int bits, X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  816. void BZHI(int bits, X64Reg regOp1, const OpArg& arg, X64Reg regOp2);
  817. void BLSR(int bits, X64Reg regOp, const OpArg& arg);
  818. void BLSMSK(int bits, X64Reg regOp, const OpArg& arg);
  819. void BLSI(int bits, X64Reg regOp, const OpArg& arg);
  820. void BEXTR(int bits, X64Reg regOp1, const OpArg& arg, X64Reg regOp2);
  821. void ANDN(int bits, X64Reg regOp1, X64Reg regOp2, const OpArg& arg);
  822. void RDTSC();
  823. // Utility functions
  824. // The difference between this and CALL is that this aligns the stack
  825. // where appropriate.
  826. void ABI_CallFunction(const void* func);
  827. template <typename T>
  828. void ABI_CallFunction(T (*func)()) {
  829. ABI_CallFunction((const void*)func);
  830. }
  831. void ABI_CallFunction(const u8* func) {
  832. ABI_CallFunction((const void*)func);
  833. }
  834. void ABI_CallFunctionC16(const void* func, u16 param1);
  835. void ABI_CallFunctionCC16(const void* func, u32 param1, u16 param2);
  836. // These only support u32 parameters, but that's enough for a lot of uses.
  837. // These will destroy the 1 or 2 first "parameter regs".
  838. void ABI_CallFunctionC(const void* func, u32 param1);
  839. void ABI_CallFunctionCC(const void* func, u32 param1, u32 param2);
  840. void ABI_CallFunctionCCC(const void* func, u32 param1, u32 param2, u32 param3);
  841. void ABI_CallFunctionCCP(const void* func, u32 param1, u32 param2, void* param3);
  842. void ABI_CallFunctionCCCP(const void* func, u32 param1, u32 param2, u32 param3, void* param4);
  843. void ABI_CallFunctionP(const void* func, void* param1);
  844. void ABI_CallFunctionPA(const void* func, void* param1, const OpArg& arg2);
  845. void ABI_CallFunctionPAA(const void* func, void* param1, const OpArg& arg2, const OpArg& arg3);
  846. void ABI_CallFunctionPPC(const void* func, void* param1, void* param2, u32 param3);
  847. void ABI_CallFunctionAC(const void* func, const OpArg& arg1, u32 param2);
  848. void ABI_CallFunctionACC(const void* func, const OpArg& arg1, u32 param2, u32 param3);
  849. void ABI_CallFunctionA(const void* func, const OpArg& arg1);
  850. void ABI_CallFunctionAA(const void* func, const OpArg& arg1, const OpArg& arg2);
  851. // Pass a register as a parameter.
  852. void ABI_CallFunctionR(const void* func, X64Reg reg1);
  853. void ABI_CallFunctionRR(const void* func, X64Reg reg1, X64Reg reg2);
  854. template <typename Tr, typename T1>
  855. void ABI_CallFunctionC(Tr (*func)(T1), u32 param1) {
  856. ABI_CallFunctionC((const void*)func, param1);
  857. }
  858. // A function that doesn't have any control over what it will do to regs,
  859. // such as the dispatcher, should be surrounded by these.
  860. void ABI_PushAllCalleeSavedRegsAndAdjustStack();
  861. void ABI_PopAllCalleeSavedRegsAndAdjustStack();
  862. // A function that doesn't know anything about it's surroundings, should
  863. // be surrounded by these to establish a safe environment, where it can roam free.
  864. // An example is a backpatch injected function.
  865. void ABI_PushAllCallerSavedRegsAndAdjustStack();
  866. void ABI_PopAllCallerSavedRegsAndAdjustStack();
  867. unsigned int ABI_GetAlignedFrameSize(unsigned int frameSize);
  868. void ABI_AlignStack(unsigned int frameSize);
  869. void ABI_RestoreStack(unsigned int frameSize);
  870. // Sets up a __cdecl function.
  871. // Only x64 really needs the parameter count.
  872. void ABI_EmitPrologue(int maxCallParams);
  873. void ABI_EmitEpilogue(int maxCallParams);
  874. #ifdef _M_IX86
  875. static int ABI_GetNumXMMRegs() { return 8; }
  876. #else
  877. static int ABI_GetNumXMMRegs() { return 16; }
  878. #endif
  879. }; // class XEmitter
  880. // Everything that needs to generate X86 code should inherit from this.
  881. // You get memory management for free, plus, you can use all the MOV etc functions without
  882. // having to prefix them with gen-> or something similar.
  883. class XCodeBlock : public CodeBlock<XEmitter> {
  884. public:
  885. void PoisonMemory() override;
  886. };
  887. } // namespace