emitter.h 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067
  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. typedef const u8* JumpTarget;
  284. class XEmitter
  285. {
  286. friend struct OpArg; // for Write8 etc
  287. private:
  288. u8 *code;
  289. bool flags_locked;
  290. void CheckFlags();
  291. void Rex(int w, int r, int x, int b);
  292. void WriteSimple1Byte(int bits, u8 byte, X64Reg reg);
  293. void WriteSimple2Byte(int bits, u8 byte1, u8 byte2, X64Reg reg);
  294. void WriteMulDivType(int bits, OpArg src, int ext);
  295. void WriteBitSearchType(int bits, X64Reg dest, OpArg src, u8 byte2, bool rep = false);
  296. void WriteShift(int bits, OpArg dest, OpArg &shift, int ext);
  297. void WriteBitTest(int bits, OpArg &dest, OpArg &index, int ext);
  298. void WriteMXCSR(OpArg arg, int ext);
  299. void WriteSSEOp(u8 opPrefix, u16 op, X64Reg regOp, OpArg arg, int extrabytes = 0);
  300. void WriteSSSE3Op(u8 opPrefix, u16 op, X64Reg regOp, OpArg arg, int extrabytes = 0);
  301. void WriteSSE41Op(u8 opPrefix, u16 op, X64Reg regOp, OpArg arg, int extrabytes = 0);
  302. void WriteAVXOp(u8 opPrefix, u16 op, X64Reg regOp, OpArg arg, int extrabytes = 0);
  303. void WriteAVXOp(u8 opPrefix, u16 op, X64Reg regOp1, X64Reg regOp2, OpArg arg, int extrabytes = 0);
  304. void WriteVEXOp(int size, u8 opPrefix, u16 op, X64Reg regOp1, X64Reg regOp2, OpArg arg, int extrabytes = 0);
  305. void WriteBMI1Op(int size, u8 opPrefix, u16 op, X64Reg regOp1, X64Reg regOp2, OpArg arg, int extrabytes = 0);
  306. void WriteBMI2Op(int size, u8 opPrefix, u16 op, X64Reg regOp1, X64Reg regOp2, OpArg arg, int extrabytes = 0);
  307. void WriteFloatLoadStore(int bits, FloatOp op, FloatOp op_80b, OpArg arg);
  308. void WriteNormalOp(XEmitter *emit, int bits, NormalOp op, const OpArg &a1, const OpArg &a2);
  309. void ABI_CalculateFrameSize(u32 mask, size_t rsp_alignment, size_t needed_frame_size, size_t* shadowp, size_t* subtractionp, size_t* xmm_offsetp);
  310. protected:
  311. inline void Write8(u8 value) {*code++ = value;}
  312. inline void Write16(u16 value) {*(u16*)code = (value); code += 2;}
  313. inline void Write32(u32 value) {*(u32*)code = (value); code += 4;}
  314. inline void Write64(u64 value) {*(u64*)code = (value); code += 8;}
  315. public:
  316. XEmitter() { code = nullptr; flags_locked = false; }
  317. XEmitter(u8 *code_ptr) { code = code_ptr; flags_locked = false; }
  318. virtual ~XEmitter() {}
  319. void WriteModRM(int mod, int rm, int reg);
  320. void WriteSIB(int scale, int index, int base);
  321. void SetCodePtr(u8 *ptr);
  322. void ReserveCodeSpace(int bytes);
  323. const u8 *AlignCode4();
  324. const u8 *AlignCode16();
  325. const u8 *AlignCodePage();
  326. const u8 *GetCodePtr() const;
  327. u8 *GetWritableCodePtr();
  328. void LockFlags() { flags_locked = true; }
  329. void UnlockFlags() { flags_locked = false; }
  330. // Looking for one of these? It's BANNED!! Some instructions are slow on modern CPU
  331. // INC, DEC, LOOP, LOOPNE, LOOPE, ENTER, LEAVE, XCHG, XLAT, REP MOVSB/MOVSD, REP SCASD + other string instr.,
  332. // INC and DEC are slow on Intel Core, but not on AMD. They create a
  333. // false flag dependency because they only update a subset of the flags.
  334. // XCHG is SLOW and should be avoided.
  335. // Debug breakpoint
  336. void INT3();
  337. // Do nothing
  338. void NOP(size_t count = 1);
  339. // Save energy in wait-loops on P4 only. Probably not too useful.
  340. void PAUSE();
  341. // Flag control
  342. void STC();
  343. void CLC();
  344. void CMC();
  345. // These two can not be executed in 64-bit mode on early Intel 64-bit CPU:s, only on Core2 and AMD!
  346. void LAHF(); // 3 cycle vector path
  347. void SAHF(); // direct path fast
  348. // Stack control
  349. void PUSH(X64Reg reg);
  350. void POP(X64Reg reg);
  351. void PUSH(int bits, const OpArg &reg);
  352. void POP(int bits, const OpArg &reg);
  353. void PUSHF();
  354. void POPF();
  355. // Flow control
  356. void RET();
  357. void RET_FAST();
  358. void UD2();
  359. FixupBranch J(bool force5bytes = false);
  360. void JMP(const u8 * addr, bool force5Bytes = false);
  361. void JMP(OpArg arg);
  362. void JMPptr(const OpArg &arg);
  363. void JMPself(); //infinite loop!
  364. #ifdef CALL
  365. #undef CALL
  366. #endif
  367. void CALL(const void *fnptr);
  368. void CALLptr(OpArg arg);
  369. FixupBranch J_CC(CCFlags conditionCode, bool force5bytes = false);
  370. //void J_CC(CCFlags conditionCode, JumpTarget target);
  371. void J_CC(CCFlags conditionCode, const u8 * addr, bool force5Bytes = false);
  372. void SetJumpTarget(const FixupBranch &branch);
  373. void SETcc(CCFlags flag, OpArg dest);
  374. // Note: CMOV brings small if any benefit on current cpus.
  375. void CMOVcc(int bits, X64Reg dest, OpArg src, CCFlags flag);
  376. // Fences
  377. void LFENCE();
  378. void MFENCE();
  379. void SFENCE();
  380. // Bit scan
  381. void BSF(int bits, X64Reg dest, OpArg src); //bottom bit to top bit
  382. void BSR(int bits, X64Reg dest, OpArg src); //top bit to bottom bit
  383. // Cache control
  384. enum PrefetchLevel
  385. {
  386. PF_NTA, //Non-temporal (data used once and only once)
  387. PF_T0, //All cache levels
  388. PF_T1, //Levels 2+ (aliased to T0 on AMD)
  389. PF_T2, //Levels 3+ (aliased to T0 on AMD)
  390. };
  391. void PREFETCH(PrefetchLevel level, OpArg arg);
  392. void MOVNTI(int bits, OpArg dest, X64Reg src);
  393. void MOVNTDQ(OpArg arg, X64Reg regOp);
  394. void MOVNTPS(OpArg arg, X64Reg regOp);
  395. void MOVNTPD(OpArg arg, X64Reg regOp);
  396. // Multiplication / division
  397. void MUL(int bits, OpArg src); //UNSIGNED
  398. void IMUL(int bits, OpArg src); //SIGNED
  399. void IMUL(int bits, X64Reg regOp, OpArg src);
  400. void IMUL(int bits, X64Reg regOp, OpArg src, OpArg imm);
  401. void DIV(int bits, OpArg src);
  402. void IDIV(int bits, OpArg src);
  403. // Shift
  404. void ROL(int bits, OpArg dest, OpArg shift);
  405. void ROR(int bits, OpArg dest, OpArg shift);
  406. void RCL(int bits, OpArg dest, OpArg shift);
  407. void RCR(int bits, OpArg dest, OpArg shift);
  408. void SHL(int bits, OpArg dest, OpArg shift);
  409. void SHR(int bits, OpArg dest, OpArg shift);
  410. void SAR(int bits, OpArg dest, OpArg shift);
  411. // Bit Test
  412. void BT(int bits, OpArg dest, OpArg index);
  413. void BTS(int bits, OpArg dest, OpArg index);
  414. void BTR(int bits, OpArg dest, OpArg index);
  415. void BTC(int bits, OpArg dest, OpArg index);
  416. // Double-Precision Shift
  417. void SHRD(int bits, OpArg dest, OpArg src, OpArg shift);
  418. void SHLD(int bits, OpArg dest, OpArg src, OpArg shift);
  419. // Extend EAX into EDX in various ways
  420. void CWD(int bits = 16);
  421. inline void CDQ() {CWD(32);}
  422. inline void CQO() {CWD(64);}
  423. void CBW(int bits = 8);
  424. inline void CWDE() {CBW(16);}
  425. inline void CDQE() {CBW(32);}
  426. // Load effective address
  427. void LEA(int bits, X64Reg dest, OpArg src);
  428. // Integer arithmetic
  429. void NEG (int bits, OpArg src);
  430. void ADD (int bits, const OpArg &a1, const OpArg &a2);
  431. void ADC (int bits, const OpArg &a1, const OpArg &a2);
  432. void SUB (int bits, const OpArg &a1, const OpArg &a2);
  433. void SBB (int bits, const OpArg &a1, const OpArg &a2);
  434. void AND (int bits, const OpArg &a1, const OpArg &a2);
  435. void CMP (int bits, const OpArg &a1, const OpArg &a2);
  436. // Bit operations
  437. void NOT (int bits, OpArg src);
  438. void OR (int bits, const OpArg &a1, const OpArg &a2);
  439. void XOR (int bits, const OpArg &a1, const OpArg &a2);
  440. void MOV (int bits, const OpArg &a1, const OpArg &a2);
  441. void TEST(int bits, const OpArg &a1, const OpArg &a2);
  442. // Are these useful at all? Consider removing.
  443. void XCHG(int bits, const OpArg &a1, const OpArg &a2);
  444. void XCHG_AHAL();
  445. // Byte swapping (32 and 64-bit only).
  446. void BSWAP(int bits, X64Reg reg);
  447. // Sign/zero extension
  448. void MOVSX(int dbits, int sbits, X64Reg dest, OpArg src); //automatically uses MOVSXD if necessary
  449. void MOVZX(int dbits, int sbits, X64Reg dest, OpArg src);
  450. // Available only on Atom or >= Haswell so far. Test with GetCPUCaps().movbe.
  451. void MOVBE(int dbits, const OpArg& dest, const OpArg& src);
  452. // Available only on AMD >= Phenom or Intel >= Haswell
  453. void LZCNT(int bits, X64Reg dest, OpArg src);
  454. // Note: this one is actually part of BMI1
  455. void TZCNT(int bits, X64Reg dest, OpArg src);
  456. // WARNING - These two take 11-13 cycles and are VectorPath! (AMD64)
  457. void STMXCSR(OpArg memloc);
  458. void LDMXCSR(OpArg memloc);
  459. // Prefixes
  460. void LOCK();
  461. void REP();
  462. void REPNE();
  463. void FSOverride();
  464. void GSOverride();
  465. // x87
  466. enum x87StatusWordBits {
  467. x87_InvalidOperation = 0x1,
  468. x87_DenormalizedOperand = 0x2,
  469. x87_DivisionByZero = 0x4,
  470. x87_Overflow = 0x8,
  471. x87_Underflow = 0x10,
  472. x87_Precision = 0x20,
  473. x87_StackFault = 0x40,
  474. x87_ErrorSummary = 0x80,
  475. x87_C0 = 0x100,
  476. x87_C1 = 0x200,
  477. x87_C2 = 0x400,
  478. x87_TopOfStack = 0x2000 | 0x1000 | 0x800,
  479. x87_C3 = 0x4000,
  480. x87_FPUBusy = 0x8000,
  481. };
  482. void FLD(int bits, OpArg src);
  483. void FST(int bits, OpArg dest);
  484. void FSTP(int bits, OpArg dest);
  485. void FNSTSW_AX();
  486. void FWAIT();
  487. // SSE/SSE2: Floating point arithmetic
  488. void ADDSS(X64Reg regOp, OpArg arg);
  489. void ADDSD(X64Reg regOp, OpArg arg);
  490. void SUBSS(X64Reg regOp, OpArg arg);
  491. void SUBSD(X64Reg regOp, OpArg arg);
  492. void MULSS(X64Reg regOp, OpArg arg);
  493. void MULSD(X64Reg regOp, OpArg arg);
  494. void DIVSS(X64Reg regOp, OpArg arg);
  495. void DIVSD(X64Reg regOp, OpArg arg);
  496. void MINSS(X64Reg regOp, OpArg arg);
  497. void MINSD(X64Reg regOp, OpArg arg);
  498. void MAXSS(X64Reg regOp, OpArg arg);
  499. void MAXSD(X64Reg regOp, OpArg arg);
  500. void SQRTSS(X64Reg regOp, OpArg arg);
  501. void SQRTSD(X64Reg regOp, OpArg arg);
  502. void RSQRTSS(X64Reg regOp, OpArg arg);
  503. // SSE/SSE2: Floating point bitwise (yes)
  504. void CMPSS(X64Reg regOp, OpArg arg, u8 compare);
  505. void CMPSD(X64Reg regOp, OpArg arg, u8 compare);
  506. inline void CMPEQSS(X64Reg regOp, OpArg arg) { CMPSS(regOp, arg, CMP_EQ); }
  507. inline void CMPLTSS(X64Reg regOp, OpArg arg) { CMPSS(regOp, arg, CMP_LT); }
  508. inline void CMPLESS(X64Reg regOp, OpArg arg) { CMPSS(regOp, arg, CMP_LE); }
  509. inline void CMPUNORDSS(X64Reg regOp, OpArg arg) { CMPSS(regOp, arg, CMP_UNORD); }
  510. inline void CMPNEQSS(X64Reg regOp, OpArg arg) { CMPSS(regOp, arg, CMP_NEQ); }
  511. inline void CMPNLTSS(X64Reg regOp, OpArg arg) { CMPSS(regOp, arg, CMP_NLT); }
  512. inline void CMPORDSS(X64Reg regOp, OpArg arg) { CMPSS(regOp, arg, CMP_ORD); }
  513. // SSE/SSE2: Floating point packed arithmetic (x4 for float, x2 for double)
  514. void ADDPS(X64Reg regOp, OpArg arg);
  515. void ADDPD(X64Reg regOp, OpArg arg);
  516. void SUBPS(X64Reg regOp, OpArg arg);
  517. void SUBPD(X64Reg regOp, OpArg arg);
  518. void CMPPS(X64Reg regOp, OpArg arg, u8 compare);
  519. void CMPPD(X64Reg regOp, OpArg arg, u8 compare);
  520. void MULPS(X64Reg regOp, OpArg arg);
  521. void MULPD(X64Reg regOp, OpArg arg);
  522. void DIVPS(X64Reg regOp, OpArg arg);
  523. void DIVPD(X64Reg regOp, OpArg arg);
  524. void MINPS(X64Reg regOp, OpArg arg);
  525. void MINPD(X64Reg regOp, OpArg arg);
  526. void MAXPS(X64Reg regOp, OpArg arg);
  527. void MAXPD(X64Reg regOp, OpArg arg);
  528. void SQRTPS(X64Reg regOp, OpArg arg);
  529. void SQRTPD(X64Reg regOp, OpArg arg);
  530. void RCPPS(X64Reg regOp, OpArg arg);
  531. void RSQRTPS(X64Reg regOp, OpArg arg);
  532. // SSE/SSE2: Floating point packed bitwise (x4 for float, x2 for double)
  533. void ANDPS(X64Reg regOp, OpArg arg);
  534. void ANDPD(X64Reg regOp, OpArg arg);
  535. void ANDNPS(X64Reg regOp, OpArg arg);
  536. void ANDNPD(X64Reg regOp, OpArg arg);
  537. void ORPS(X64Reg regOp, OpArg arg);
  538. void ORPD(X64Reg regOp, OpArg arg);
  539. void XORPS(X64Reg regOp, OpArg arg);
  540. void XORPD(X64Reg regOp, OpArg arg);
  541. // SSE/SSE2: Shuffle components. These are tricky - see Intel documentation.
  542. void SHUFPS(X64Reg regOp, OpArg arg, u8 shuffle);
  543. void SHUFPD(X64Reg regOp, OpArg arg, u8 shuffle);
  544. // SSE/SSE2: Useful alternative to shuffle in some cases.
  545. void MOVDDUP(X64Reg regOp, OpArg arg);
  546. // TODO: Actually implement
  547. #if 0
  548. // SSE3: Horizontal operations in SIMD registers. Could be useful for various VFPU things like dot products...
  549. void ADDSUBPS(X64Reg dest, OpArg src);
  550. void ADDSUBPD(X64Reg dest, OpArg src);
  551. void HADDPD(X64Reg dest, OpArg src);
  552. void HSUBPS(X64Reg dest, OpArg src);
  553. void HSUBPD(X64Reg dest, OpArg src);
  554. // SSE4: Further horizontal operations - dot products. These are weirdly flexible, the arg contains both a read mask and a write "mask".
  555. void DPPD(X64Reg dest, OpArg src, u8 arg);
  556. // These are probably useful for VFPU emulation.
  557. void INSERTPS(X64Reg dest, OpArg src, u8 arg);
  558. void EXTRACTPS(OpArg dest, X64Reg src, u8 arg);
  559. #endif
  560. // SSE3: Horizontal operations in SIMD registers. Very slow! shufps-based code beats it handily on Ivy.
  561. void HADDPS(X64Reg dest, OpArg src);
  562. // SSE4: Further horizontal operations - dot products. These are weirdly flexible, the arg contains both a read mask and a write "mask".
  563. void DPPS(X64Reg dest, OpArg src, u8 arg);
  564. void UNPCKLPS(X64Reg dest, OpArg src);
  565. void UNPCKHPS(X64Reg dest, OpArg src);
  566. void UNPCKLPD(X64Reg dest, OpArg src);
  567. void UNPCKHPD(X64Reg dest, OpArg src);
  568. // SSE/SSE2: Compares.
  569. void COMISS(X64Reg regOp, OpArg arg);
  570. void COMISD(X64Reg regOp, OpArg arg);
  571. void UCOMISS(X64Reg regOp, OpArg arg);
  572. void UCOMISD(X64Reg regOp, OpArg arg);
  573. // SSE/SSE2: Moves. Use the right data type for your data, in most cases.
  574. void MOVAPS(X64Reg regOp, OpArg arg);
  575. void MOVAPD(X64Reg regOp, OpArg arg);
  576. void MOVAPS(OpArg arg, X64Reg regOp);
  577. void MOVAPD(OpArg arg, X64Reg regOp);
  578. void MOVUPS(X64Reg regOp, OpArg arg);
  579. void MOVUPD(X64Reg regOp, OpArg arg);
  580. void MOVUPS(OpArg arg, X64Reg regOp);
  581. void MOVUPD(OpArg arg, X64Reg regOp);
  582. void MOVDQA(X64Reg regOp, OpArg arg);
  583. void MOVDQA(OpArg arg, X64Reg regOp);
  584. void MOVDQU(X64Reg regOp, OpArg arg);
  585. void MOVDQU(OpArg arg, X64Reg regOp);
  586. void MOVSS(X64Reg regOp, OpArg arg);
  587. void MOVSD(X64Reg regOp, OpArg arg);
  588. void MOVSS(OpArg arg, X64Reg regOp);
  589. void MOVSD(OpArg arg, X64Reg regOp);
  590. void MOVLPS(X64Reg regOp, OpArg arg);
  591. void MOVLPD(X64Reg regOp, OpArg arg);
  592. void MOVLPS(OpArg arg, X64Reg regOp);
  593. void MOVLPD(OpArg arg, X64Reg regOp);
  594. void MOVHPS(X64Reg regOp, OpArg arg);
  595. void MOVHPD(X64Reg regOp, OpArg arg);
  596. void MOVHPS(OpArg arg, X64Reg regOp);
  597. void MOVHPD(OpArg arg, X64Reg regOp);
  598. void MOVHLPS(X64Reg regOp1, X64Reg regOp2);
  599. void MOVLHPS(X64Reg regOp1, X64Reg regOp2);
  600. void MOVD_xmm(X64Reg dest, const OpArg &arg);
  601. void MOVQ_xmm(X64Reg dest, OpArg arg);
  602. void MOVD_xmm(const OpArg &arg, X64Reg src);
  603. void MOVQ_xmm(OpArg arg, X64Reg src);
  604. // SSE/SSE2: Generates a mask from the high bits of the components of the packed register in question.
  605. void MOVMSKPS(X64Reg dest, OpArg arg);
  606. void MOVMSKPD(X64Reg dest, OpArg arg);
  607. // SSE2: Selective byte store, mask in src register. EDI/RDI specifies store address. This is a weird one.
  608. void MASKMOVDQU(X64Reg dest, X64Reg src);
  609. void LDDQU(X64Reg dest, OpArg src);
  610. // SSE/SSE2: Data type conversions.
  611. void CVTPS2PD(X64Reg dest, OpArg src);
  612. void CVTPD2PS(X64Reg dest, OpArg src);
  613. void CVTSS2SD(X64Reg dest, OpArg src);
  614. void CVTSI2SS(X64Reg dest, OpArg src);
  615. void CVTSD2SS(X64Reg dest, OpArg src);
  616. void CVTSI2SD(X64Reg dest, OpArg src);
  617. void CVTDQ2PD(X64Reg regOp, OpArg arg);
  618. void CVTPD2DQ(X64Reg regOp, OpArg arg);
  619. void CVTDQ2PS(X64Reg regOp, OpArg arg);
  620. void CVTPS2DQ(X64Reg regOp, OpArg arg);
  621. void CVTTPS2DQ(X64Reg regOp, OpArg arg);
  622. void CVTTPD2DQ(X64Reg regOp, OpArg arg);
  623. // Destinations are X64 regs (rax, rbx, ...) for these instructions.
  624. void CVTSS2SI(X64Reg xregdest, OpArg src);
  625. void CVTSD2SI(X64Reg xregdest, OpArg src);
  626. void CVTTSS2SI(X64Reg xregdest, OpArg arg);
  627. void CVTTSD2SI(X64Reg xregdest, OpArg arg);
  628. // SSE2: Packed integer instructions
  629. void PACKSSDW(X64Reg dest, OpArg arg);
  630. void PACKSSWB(X64Reg dest, OpArg arg);
  631. void PACKUSDW(X64Reg dest, OpArg arg);
  632. void PACKUSWB(X64Reg dest, OpArg arg);
  633. void PUNPCKLBW(X64Reg dest, const OpArg &arg);
  634. void PUNPCKLWD(X64Reg dest, const OpArg &arg);
  635. void PUNPCKLDQ(X64Reg dest, const OpArg &arg);
  636. void PUNPCKLQDQ(X64Reg dest, const OpArg &arg);
  637. void PTEST(X64Reg dest, OpArg arg);
  638. void PAND(X64Reg dest, OpArg arg);
  639. void PANDN(X64Reg dest, OpArg arg);
  640. void PXOR(X64Reg dest, OpArg arg);
  641. void POR(X64Reg dest, OpArg arg);
  642. void PADDB(X64Reg dest, OpArg arg);
  643. void PADDW(X64Reg dest, OpArg arg);
  644. void PADDD(X64Reg dest, OpArg arg);
  645. void PADDQ(X64Reg dest, OpArg arg);
  646. void PADDSB(X64Reg dest, OpArg arg);
  647. void PADDSW(X64Reg dest, OpArg arg);
  648. void PADDUSB(X64Reg dest, OpArg arg);
  649. void PADDUSW(X64Reg dest, OpArg arg);
  650. void PSUBB(X64Reg dest, OpArg arg);
  651. void PSUBW(X64Reg dest, OpArg arg);
  652. void PSUBD(X64Reg dest, OpArg arg);
  653. void PSUBQ(X64Reg dest, OpArg arg);
  654. void PSUBSB(X64Reg dest, OpArg arg);
  655. void PSUBSW(X64Reg dest, OpArg arg);
  656. void PSUBUSB(X64Reg dest, OpArg arg);
  657. void PSUBUSW(X64Reg dest, OpArg arg);
  658. void PAVGB(X64Reg dest, OpArg arg);
  659. void PAVGW(X64Reg dest, OpArg arg);
  660. void PCMPEQB(X64Reg dest, OpArg arg);
  661. void PCMPEQW(X64Reg dest, OpArg arg);
  662. void PCMPEQD(X64Reg dest, OpArg arg);
  663. void PCMPGTB(X64Reg dest, OpArg arg);
  664. void PCMPGTW(X64Reg dest, OpArg arg);
  665. void PCMPGTD(X64Reg dest, OpArg arg);
  666. void PEXTRW(X64Reg dest, OpArg arg, u8 subreg);
  667. void PINSRW(X64Reg dest, OpArg arg, u8 subreg);
  668. void PMADDWD(X64Reg dest, OpArg arg);
  669. void PSADBW(X64Reg dest, OpArg arg);
  670. void PMAXSW(X64Reg dest, OpArg arg);
  671. void PMAXUB(X64Reg dest, OpArg arg);
  672. void PMINSW(X64Reg dest, OpArg arg);
  673. void PMINUB(X64Reg dest, OpArg arg);
  674. // SSE4: More MAX/MIN instructions.
  675. void PMINSB(X64Reg dest, OpArg arg);
  676. void PMINSD(X64Reg dest, OpArg arg);
  677. void PMINUW(X64Reg dest, OpArg arg);
  678. void PMINUD(X64Reg dest, OpArg arg);
  679. void PMAXSB(X64Reg dest, OpArg arg);
  680. void PMAXSD(X64Reg dest, OpArg arg);
  681. void PMAXUW(X64Reg dest, OpArg arg);
  682. void PMAXUD(X64Reg dest, OpArg arg);
  683. void PMOVMSKB(X64Reg dest, OpArg arg);
  684. void PSHUFD(X64Reg dest, OpArg arg, u8 shuffle);
  685. void PSHUFB(X64Reg dest, OpArg arg);
  686. void PSHUFLW(X64Reg dest, OpArg arg, u8 shuffle);
  687. void PSHUFHW(X64Reg dest, OpArg arg, u8 shuffle);
  688. void PSRLW(X64Reg reg, int shift);
  689. void PSRLD(X64Reg reg, int shift);
  690. void PSRLQ(X64Reg reg, int shift);
  691. void PSRLQ(X64Reg reg, OpArg arg);
  692. void PSRLDQ(X64Reg reg, int shift);
  693. void PSLLW(X64Reg reg, int shift);
  694. void PSLLD(X64Reg reg, int shift);
  695. void PSLLQ(X64Reg reg, int shift);
  696. void PSLLDQ(X64Reg reg, int shift);
  697. void PSRAW(X64Reg reg, int shift);
  698. void PSRAD(X64Reg reg, int shift);
  699. // SSE4: data type conversions
  700. void PMOVSXBW(X64Reg dest, OpArg arg);
  701. void PMOVSXBD(X64Reg dest, OpArg arg);
  702. void PMOVSXBQ(X64Reg dest, OpArg arg);
  703. void PMOVSXWD(X64Reg dest, OpArg arg);
  704. void PMOVSXWQ(X64Reg dest, OpArg arg);
  705. void PMOVSXDQ(X64Reg dest, OpArg arg);
  706. void PMOVZXBW(X64Reg dest, OpArg arg);
  707. void PMOVZXBD(X64Reg dest, OpArg arg);
  708. void PMOVZXBQ(X64Reg dest, OpArg arg);
  709. void PMOVZXWD(X64Reg dest, OpArg arg);
  710. void PMOVZXWQ(X64Reg dest, OpArg arg);
  711. void PMOVZXDQ(X64Reg dest, OpArg arg);
  712. // SSE4: variable blend instructions (xmm0 implicit argument)
  713. void PBLENDVB(X64Reg dest, OpArg arg);
  714. void BLENDVPS(X64Reg dest, OpArg arg);
  715. void BLENDVPD(X64Reg dest, OpArg arg);
  716. void BLENDPS(X64Reg dest, const OpArg& arg, u8 blend);
  717. void BLENDPD(X64Reg dest, const OpArg& arg, u8 blend);
  718. // SSE4: rounding (see FloatRound for mode or use ROUNDNEARSS, etc. helpers.)
  719. void ROUNDSS(X64Reg dest, OpArg arg, u8 mode);
  720. void ROUNDSD(X64Reg dest, OpArg arg, u8 mode);
  721. void ROUNDPS(X64Reg dest, OpArg arg, u8 mode);
  722. void ROUNDPD(X64Reg dest, OpArg arg, u8 mode);
  723. inline void ROUNDNEARSS(X64Reg dest, OpArg arg) { ROUNDSS(dest, arg, FROUND_NEAREST); }
  724. inline void ROUNDFLOORSS(X64Reg dest, OpArg arg) { ROUNDSS(dest, arg, FROUND_FLOOR); }
  725. inline void ROUNDCEILSS(X64Reg dest, OpArg arg) { ROUNDSS(dest, arg, FROUND_CEIL); }
  726. inline void ROUNDZEROSS(X64Reg dest, OpArg arg) { ROUNDSS(dest, arg, FROUND_ZERO); }
  727. inline void ROUNDNEARSD(X64Reg dest, OpArg arg) { ROUNDSD(dest, arg, FROUND_NEAREST); }
  728. inline void ROUNDFLOORSD(X64Reg dest, OpArg arg) { ROUNDSD(dest, arg, FROUND_FLOOR); }
  729. inline void ROUNDCEILSD(X64Reg dest, OpArg arg) { ROUNDSD(dest, arg, FROUND_CEIL); }
  730. inline void ROUNDZEROSD(X64Reg dest, OpArg arg) { ROUNDSD(dest, arg, FROUND_ZERO); }
  731. inline void ROUNDNEARPS(X64Reg dest, OpArg arg) { ROUNDPS(dest, arg, FROUND_NEAREST); }
  732. inline void ROUNDFLOORPS(X64Reg dest, OpArg arg) { ROUNDPS(dest, arg, FROUND_FLOOR); }
  733. inline void ROUNDCEILPS(X64Reg dest, OpArg arg) { ROUNDPS(dest, arg, FROUND_CEIL); }
  734. inline void ROUNDZEROPS(X64Reg dest, OpArg arg) { ROUNDPS(dest, arg, FROUND_ZERO); }
  735. inline void ROUNDNEARPD(X64Reg dest, OpArg arg) { ROUNDPD(dest, arg, FROUND_NEAREST); }
  736. inline void ROUNDFLOORPD(X64Reg dest, OpArg arg) { ROUNDPD(dest, arg, FROUND_FLOOR); }
  737. inline void ROUNDCEILPD(X64Reg dest, OpArg arg) { ROUNDPD(dest, arg, FROUND_CEIL); }
  738. inline void ROUNDZEROPD(X64Reg dest, OpArg arg) { ROUNDPD(dest, arg, FROUND_ZERO); }
  739. // AVX
  740. void VADDSD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  741. void VSUBSD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  742. void VMULSD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  743. void VDIVSD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  744. void VADDPD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  745. void VSUBPD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  746. void VMULPD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  747. void VDIVPD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  748. void VSQRTSD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  749. void VSHUFPD(X64Reg regOp1, X64Reg regOp2, OpArg arg, u8 shuffle);
  750. void VUNPCKLPD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  751. void VUNPCKHPD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  752. void VANDPS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  753. void VANDPD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  754. void VANDNPS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  755. void VANDNPD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  756. void VORPS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  757. void VORPD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  758. void VXORPS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  759. void VXORPD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  760. void VPAND(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  761. void VPANDN(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  762. void VPOR(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  763. void VPXOR(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  764. // FMA3
  765. void VFMADD132PS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  766. void VFMADD213PS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  767. void VFMADD231PS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  768. void VFMADD132PD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  769. void VFMADD213PD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  770. void VFMADD231PD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  771. void VFMADD132SS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  772. void VFMADD213SS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  773. void VFMADD231SS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  774. void VFMADD132SD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  775. void VFMADD213SD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  776. void VFMADD231SD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  777. void VFMSUB132PS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  778. void VFMSUB213PS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  779. void VFMSUB231PS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  780. void VFMSUB132PD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  781. void VFMSUB213PD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  782. void VFMSUB231PD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  783. void VFMSUB132SS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  784. void VFMSUB213SS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  785. void VFMSUB231SS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  786. void VFMSUB132SD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  787. void VFMSUB213SD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  788. void VFMSUB231SD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  789. void VFNMADD132PS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  790. void VFNMADD213PS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  791. void VFNMADD231PS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  792. void VFNMADD132PD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  793. void VFNMADD213PD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  794. void VFNMADD231PD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  795. void VFNMADD132SS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  796. void VFNMADD213SS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  797. void VFNMADD231SS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  798. void VFNMADD132SD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  799. void VFNMADD213SD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  800. void VFNMADD231SD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  801. void VFNMSUB132PS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  802. void VFNMSUB213PS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  803. void VFNMSUB231PS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  804. void VFNMSUB132PD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  805. void VFNMSUB213PD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  806. void VFNMSUB231PD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  807. void VFNMSUB132SS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  808. void VFNMSUB213SS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  809. void VFNMSUB231SS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  810. void VFNMSUB132SD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  811. void VFNMSUB213SD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  812. void VFNMSUB231SD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  813. void VFMADDSUB132PS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  814. void VFMADDSUB213PS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  815. void VFMADDSUB231PS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  816. void VFMADDSUB132PD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  817. void VFMADDSUB213PD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  818. void VFMADDSUB231PD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  819. void VFMSUBADD132PS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  820. void VFMSUBADD213PS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  821. void VFMSUBADD231PS(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  822. void VFMSUBADD132PD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  823. void VFMSUBADD213PD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  824. void VFMSUBADD231PD(X64Reg regOp1, X64Reg regOp2, OpArg arg);
  825. // VEX GPR instructions
  826. void SARX(int bits, X64Reg regOp1, OpArg arg, X64Reg regOp2);
  827. void SHLX(int bits, X64Reg regOp1, OpArg arg, X64Reg regOp2);
  828. void SHRX(int bits, X64Reg regOp1, OpArg arg, X64Reg regOp2);
  829. void RORX(int bits, X64Reg regOp, OpArg arg, u8 rotate);
  830. void PEXT(int bits, X64Reg regOp1, X64Reg regOp2, OpArg arg);
  831. void PDEP(int bits, X64Reg regOp1, X64Reg regOp2, OpArg arg);
  832. void MULX(int bits, X64Reg regOp1, X64Reg regOp2, OpArg arg);
  833. void BZHI(int bits, X64Reg regOp1, OpArg arg, X64Reg regOp2);
  834. void BLSR(int bits, X64Reg regOp, OpArg arg);
  835. void BLSMSK(int bits, X64Reg regOp, OpArg arg);
  836. void BLSI(int bits, X64Reg regOp, OpArg arg);
  837. void BEXTR(int bits, X64Reg regOp1, OpArg arg, X64Reg regOp2);
  838. void ANDN(int bits, X64Reg regOp1, X64Reg regOp2, OpArg arg);
  839. void RDTSC();
  840. // Utility functions
  841. // The difference between this and CALL is that this aligns the stack
  842. // where appropriate.
  843. void ABI_CallFunction(const void *func);
  844. template <typename T>
  845. void ABI_CallFunction(T (*func)()) {
  846. ABI_CallFunction((const void *)func);
  847. }
  848. void ABI_CallFunction(const u8 *func) {
  849. ABI_CallFunction((const void *)func);
  850. }
  851. void ABI_CallFunctionC16(const void *func, u16 param1);
  852. void ABI_CallFunctionCC16(const void *func, u32 param1, u16 param2);
  853. // These only support u32 parameters, but that's enough for a lot of uses.
  854. // These will destroy the 1 or 2 first "parameter regs".
  855. void ABI_CallFunctionC(const void *func, u32 param1);
  856. void ABI_CallFunctionCC(const void *func, u32 param1, u32 param2);
  857. void ABI_CallFunctionCCC(const void *func, u32 param1, u32 param2, u32 param3);
  858. void ABI_CallFunctionCCP(const void *func, u32 param1, u32 param2, void *param3);
  859. void ABI_CallFunctionCCCP(const void *func, u32 param1, u32 param2, u32 param3, void *param4);
  860. void ABI_CallFunctionP(const void *func, void *param1);
  861. void ABI_CallFunctionPA(const void *func, void *param1, const Gen::OpArg &arg2);
  862. void ABI_CallFunctionPAA(const void *func, void *param1, const Gen::OpArg &arg2, const Gen::OpArg &arg3);
  863. void ABI_CallFunctionPPC(const void *func, void *param1, void *param2, u32 param3);
  864. void ABI_CallFunctionAC(const void *func, const Gen::OpArg &arg1, u32 param2);
  865. void ABI_CallFunctionACC(const void *func, const Gen::OpArg &arg1, u32 param2, u32 param3);
  866. void ABI_CallFunctionA(const void *func, const Gen::OpArg &arg1);
  867. void ABI_CallFunctionAA(const void *func, const Gen::OpArg &arg1, const Gen::OpArg &arg2);
  868. // Pass a register as a parameter.
  869. void ABI_CallFunctionR(const void *func, X64Reg reg1);
  870. void ABI_CallFunctionRR(const void *func, X64Reg reg1, X64Reg reg2);
  871. template <typename Tr, typename T1>
  872. void ABI_CallFunctionC(Tr (*func)(T1), u32 param1) {
  873. ABI_CallFunctionC((const void *)func, param1);
  874. }
  875. // A function that doesn't have any control over what it will do to regs,
  876. // such as the dispatcher, should be surrounded by these.
  877. void ABI_PushAllCalleeSavedRegsAndAdjustStack();
  878. void ABI_PopAllCalleeSavedRegsAndAdjustStack();
  879. // A function that doesn't know anything about it's surroundings, should
  880. // be surrounded by these to establish a safe environment, where it can roam free.
  881. // An example is a backpatch injected function.
  882. void ABI_PushAllCallerSavedRegsAndAdjustStack();
  883. void ABI_PopAllCallerSavedRegsAndAdjustStack();
  884. unsigned int ABI_GetAlignedFrameSize(unsigned int frameSize);
  885. void ABI_AlignStack(unsigned int frameSize);
  886. void ABI_RestoreStack(unsigned int frameSize);
  887. // Sets up a __cdecl function.
  888. // Only x64 really needs the parameter count.
  889. void ABI_EmitPrologue(int maxCallParams);
  890. void ABI_EmitEpilogue(int maxCallParams);
  891. #ifdef _M_IX86
  892. inline int ABI_GetNumXMMRegs() { return 8; }
  893. #else
  894. inline int ABI_GetNumXMMRegs() { return 16; }
  895. #endif
  896. }; // class XEmitter
  897. // Everything that needs to generate X86 code should inherit from this.
  898. // You get memory management for free, plus, you can use all the MOV etc functions without
  899. // having to prefix them with gen-> or something similar.
  900. class XCodeBlock : public CodeBlock<XEmitter> {
  901. public:
  902. void PoisonMemory() override;
  903. };
  904. } // namespace