SoftFPU.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. /*
  2. * Copyright (c) 2021, Leon Albrecht <leon2002.la@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include "Report.h"
  8. #include <AK/Concepts.h>
  9. #include <AK/SIMD.h>
  10. #include <LibX86/Instruction.h>
  11. #include <LibX86/Interpreter.h>
  12. #include <math.h>
  13. #include <string.h>
  14. namespace UserspaceEmulator {
  15. using namespace AK::SIMD;
  16. class Emulator;
  17. class SoftCPU;
  18. union MMX {
  19. u64 raw;
  20. c8x8 v8;
  21. i16x4 v16;
  22. i32x2 v32;
  23. u16x4 v16u;
  24. u32x2 v32u;
  25. };
  26. static_assert(AssertSize<MMX, sizeof(u64)>());
  27. class SoftFPU final {
  28. public:
  29. SoftFPU(Emulator& emulator, SoftCPU& cpu)
  30. : m_emulator(emulator)
  31. , m_cpu(cpu)
  32. {
  33. }
  34. ALWAYS_INLINE bool c0() const { return m_fpu_c0; }
  35. ALWAYS_INLINE bool c1() const { return m_fpu_c1; }
  36. ALWAYS_INLINE bool c2() const { return m_fpu_c2; }
  37. ALWAYS_INLINE bool c3() const { return m_fpu_c3; }
  38. ALWAYS_INLINE void set_c0(bool val) { m_fpu_c0 = val; }
  39. ALWAYS_INLINE void set_c1(bool val) { m_fpu_c1 = val; }
  40. ALWAYS_INLINE void set_c2(bool val) { m_fpu_c2 = val; }
  41. ALWAYS_INLINE void set_c3(bool val) { m_fpu_c3 = val; }
  42. long double fpu_get(u8 index) const;
  43. void fpu_push(long double value);
  44. long double fpu_pop();
  45. void fpu_set_absolute(u8 index, long double value);
  46. void fpu_set(u8 index, long double value);
  47. MMX mmx_get(u8 index) const;
  48. void mmx_set(u8 index, MMX value);
  49. private:
  50. friend class SoftCPU;
  51. Emulator& m_emulator;
  52. SoftCPU& m_cpu;
  53. enum class FPU_Exception : u8 {
  54. InvalidOperation,
  55. DenormalizedOperand,
  56. ZeroDivide,
  57. Overflow,
  58. Underflow,
  59. Precision,
  60. StackFault,
  61. };
  62. enum class FPU_Tag : u8 {
  63. Valid = 0b00,
  64. Zero = 0b01,
  65. Special = 0b10,
  66. Empty = 0b11
  67. };
  68. enum class RoundingMode : u8 {
  69. NEAREST = 0b00,
  70. DOWN = 0b01,
  71. UP = 0b10,
  72. TRUNC = 0b11
  73. };
  74. void fpu_dump_env()
  75. {
  76. reportln("Exceptions: #I:{} #D:{} #Z:{} #O:{} #U:{} #P:{} #SF:{} Summary:{}",
  77. m_fpu_error_invalid,
  78. m_fpu_error_denorm,
  79. m_fpu_error_zero_div,
  80. m_fpu_error_overflow,
  81. m_fpu_error_underflow,
  82. m_fpu_error_precision,
  83. m_fpu_error_stackfault,
  84. m_fpu_error_summary);
  85. reportln("Masks: #I:{} #D:{} #Z:{} #O:{} #U:{} #P:{}",
  86. m_fpu_mask_invalid,
  87. m_fpu_mask_denorm,
  88. m_fpu_mask_zero_div,
  89. m_fpu_mask_overflow,
  90. m_fpu_mask_underflow,
  91. m_fpu_mask_precision);
  92. reportln("C0:{} C1:{} C2:{} C3:{}", c0(), c1(), c2(), c3());
  93. reportln("fpu-stacktop: {}", m_fpu_stack_top);
  94. reportln("fpu-stack /w stacktop (real):");
  95. for (u8 i = 0; i < 8; ++i) {
  96. reportln("\t{} ({}): fp {} ({}), mmx (:x016)", i, (u8)((m_fpu_stack_top + i) % 8), m_storage[(m_fpu_stack_top + i) % 8].fp, fpu_is_set(i) ? "set" : "free", m_storage[(m_fpu_stack_top + i) % 8].mmx.raw);
  97. }
  98. }
  99. String fpu_exception_string(FPU_Exception ex)
  100. {
  101. switch (ex) {
  102. case FPU_Exception::StackFault:
  103. return "Stackfault";
  104. case FPU_Exception::InvalidOperation:
  105. return "Invalid Operation";
  106. case FPU_Exception::DenormalizedOperand:
  107. return "Denormalized Operand";
  108. case FPU_Exception::ZeroDivide:
  109. return "Divide by Zero";
  110. case FPU_Exception::Overflow:
  111. return "Overflow";
  112. case FPU_Exception::Underflow:
  113. return "Underflow";
  114. case FPU_Exception::Precision:
  115. return "Precision";
  116. }
  117. VERIFY_NOT_REACHED();
  118. }
  119. // FIXME: Technically we should check for exceptions after each insn, too,
  120. // this might be important for FLDENV, but otherwise it should
  121. // be fine this way
  122. void fpu_set_exception(FPU_Exception ex);
  123. ALWAYS_INLINE void fpu_set_stack_overflow()
  124. {
  125. reportln("Stack Overflow");
  126. set_c1(1);
  127. fpu_set_exception(FPU_Exception::StackFault);
  128. }
  129. ALWAYS_INLINE void fpu_set_stack_underflow()
  130. {
  131. reportln("Stack Underflow");
  132. set_c1(0);
  133. fpu_set_exception(FPU_Exception::StackFault);
  134. }
  135. constexpr FPU_Tag fpu_get_tag_absolute(u8 index) const
  136. {
  137. switch (index) {
  138. case 0:
  139. return FPU_Tag(m_fpu_status_0);
  140. case 1:
  141. return FPU_Tag(m_fpu_status_1);
  142. case 2:
  143. return FPU_Tag(m_fpu_status_2);
  144. case 3:
  145. return FPU_Tag(m_fpu_status_3);
  146. case 4:
  147. return FPU_Tag(m_fpu_status_4);
  148. case 5:
  149. return FPU_Tag(m_fpu_status_5);
  150. case 6:
  151. return FPU_Tag(m_fpu_status_6);
  152. case 7:
  153. return FPU_Tag(m_fpu_status_7);
  154. default:
  155. VERIFY_NOT_REACHED();
  156. }
  157. }
  158. constexpr FPU_Tag fpu_get_tag(u8 index) const
  159. {
  160. VERIFY(index < 8);
  161. return fpu_get_tag_absolute((m_fpu_stack_top + index) % 8);
  162. }
  163. ALWAYS_INLINE void fpu_set_tag_absolute(u8 index, FPU_Tag tag)
  164. {
  165. switch (index) {
  166. case 0:
  167. m_fpu_status_0 = (u8)tag;
  168. break;
  169. case 1:
  170. m_fpu_status_1 = (u8)tag;
  171. break;
  172. case 2:
  173. m_fpu_status_2 = (u8)tag;
  174. break;
  175. case 3:
  176. m_fpu_status_3 = (u8)tag;
  177. break;
  178. case 4:
  179. m_fpu_status_4 = (u8)tag;
  180. break;
  181. case 5:
  182. m_fpu_status_5 = (u8)tag;
  183. break;
  184. case 6:
  185. m_fpu_status_6 = (u8)tag;
  186. break;
  187. case 7:
  188. m_fpu_status_7 = (u8)tag;
  189. break;
  190. default:
  191. VERIFY_NOT_REACHED();
  192. }
  193. }
  194. ALWAYS_INLINE void fpu_set_tag(u8 index, FPU_Tag tag)
  195. {
  196. VERIFY(index < 8);
  197. fpu_set_tag_absolute((m_fpu_stack_top + index) % 8, tag);
  198. }
  199. ALWAYS_INLINE void set_tag_from_value_absolute(u8 index, long double val)
  200. {
  201. switch (fpclassify(val)) {
  202. case FP_ZERO:
  203. fpu_set_tag_absolute(index, FPU_Tag::Zero);
  204. break;
  205. case FP_NAN:
  206. case FP_INFINITE:
  207. case FP_SUBNORMAL:
  208. fpu_set_tag_absolute(index, FPU_Tag::Special);
  209. break;
  210. case FP_NORMAL:
  211. fpu_set_tag_absolute(index, FPU_Tag::Valid);
  212. break;
  213. default:
  214. VERIFY_NOT_REACHED();
  215. }
  216. }
  217. ALWAYS_INLINE void set_tag_from_value(u8 index, long double val)
  218. {
  219. set_tag_from_value_absolute((m_fpu_stack_top + index) % 8, val);
  220. }
  221. ALWAYS_INLINE bool fpu_isnan(u8 index) const
  222. {
  223. return isnan(fpu_get(index));
  224. }
  225. ALWAYS_INLINE bool fpu_is_set(u8 index) const
  226. {
  227. return fpu_get_tag_absolute((m_fpu_stack_top + index) % 8) != FPU_Tag::Empty;
  228. }
  229. ALWAYS_INLINE RoundingMode fpu_get_round_mode() const
  230. {
  231. return RoundingMode(m_fpu_round_mode);
  232. }
  233. template<Arithmetic T>
  234. T fpu_round(long double) const;
  235. template<Arithmetic T>
  236. T fpu_round_checked(long double);
  237. template<FloatingPoint T>
  238. T fpu_convert(long double) const;
  239. template<FloatingPoint T>
  240. T fpu_convert_checked(long double);
  241. ALWAYS_INLINE void fpu_set_unordered()
  242. {
  243. set_c0(1);
  244. set_c2(1);
  245. set_c3(1);
  246. }
  247. void warn_if_mmx_absolute(u8 index) const;
  248. void warn_if_fpu_absolute(u8 index) const;
  249. void warn_if_fpu_not_set_absolute(u8 index) const;
  250. void mmx_common() { m_fpu_tw = 0; }
  251. bool m_reg_is_mmx[8] { false };
  252. union {
  253. long double fp;
  254. struct {
  255. MMX mmx;
  256. u16 __high;
  257. };
  258. } m_storage[8];
  259. union {
  260. u16 m_fpu_cw { 0x037F };
  261. struct {
  262. u16 m_fpu_mask_invalid : 1;
  263. u16 m_fpu_mask_denorm : 1;
  264. u16 m_fpu_mask_zero_div : 1;
  265. u16 m_fpu_mask_overflow : 1;
  266. u16 m_fpu_mask_underflow : 1;
  267. u16 m_fpu_mask_precision : 1;
  268. u16 : 2; // unused
  269. u16 m_fpu_precission : 2;
  270. u16 m_fpu_round_mode : 2;
  271. u16 m_fpu_infinity_control : 1;
  272. u16 : 3; // unused
  273. };
  274. };
  275. union {
  276. u16 m_fpu_sw { 0 };
  277. struct {
  278. u16 m_fpu_error_invalid : 1; // pre | IE -> #I (#IS, #IA)
  279. u16 m_fpu_error_denorm : 1; // pre | DE -> #D
  280. u16 m_fpu_error_zero_div : 1; // pre | ZE -> #Z
  281. u16 m_fpu_error_overflow : 1; // post| OE -> #O
  282. u16 m_fpu_error_underflow : 1; // post| UE -> #U
  283. u16 m_fpu_error_precision : 1; // post| PE -> #P
  284. u16 m_fpu_error_stackfault : 1; // SF
  285. u16 m_fpu_error_summary : 1;
  286. u16 m_fpu_c0 : 1;
  287. u16 m_fpu_c1 : 1;
  288. u16 m_fpu_c2 : 1;
  289. u16 m_fpu_stack_top : 3;
  290. u16 m_fpu_c3 : 1;
  291. u16 m_fpu_busy : 1;
  292. };
  293. };
  294. union {
  295. u16 m_fpu_tw { 0xFFFF };
  296. struct {
  297. u16 m_fpu_status_0 : 2;
  298. u16 m_fpu_status_1 : 2;
  299. u16 m_fpu_status_2 : 2;
  300. u16 m_fpu_status_3 : 2;
  301. u16 m_fpu_status_4 : 2;
  302. u16 m_fpu_status_5 : 2;
  303. u16 m_fpu_status_6 : 2;
  304. u16 m_fpu_status_7 : 2;
  305. };
  306. };
  307. u32 m_fpu_ip { 0 };
  308. u16 m_fpu_cs { 0 };
  309. u32 m_fpu_dp { 0 };
  310. u16 m_fpu_ds { 0 };
  311. u16 m_fpu_iop { 0 };
  312. // Instructions
  313. // DATA TRANSFER
  314. void FLD_RM32(const X86::Instruction&);
  315. void FLD_RM64(const X86::Instruction&);
  316. void FLD_RM80(const X86::Instruction&);
  317. void FST_RM32(const X86::Instruction&);
  318. void FST_RM64(const X86::Instruction&);
  319. void FSTP_RM32(const X86::Instruction&);
  320. void FSTP_RM64(const X86::Instruction&);
  321. void FSTP_RM80(const X86::Instruction&);
  322. void FILD_RM32(const X86::Instruction&);
  323. void FILD_RM16(const X86::Instruction&);
  324. void FILD_RM64(const X86::Instruction&);
  325. void FIST_RM16(const X86::Instruction&);
  326. void FIST_RM32(const X86::Instruction&);
  327. void FISTP_RM16(const X86::Instruction&);
  328. void FISTP_RM32(const X86::Instruction&);
  329. void FISTP_RM64(const X86::Instruction&);
  330. void FISTTP_RM16(const X86::Instruction&);
  331. void FISTTP_RM32(const X86::Instruction&);
  332. void FISTTP_RM64(const X86::Instruction&);
  333. void FBLD_M80(const X86::Instruction&);
  334. void FBSTP_M80(const X86::Instruction&);
  335. void FXCH(const X86::Instruction&);
  336. void FCMOVE(const X86::Instruction&);
  337. void FCMOVNE(const X86::Instruction&);
  338. void FCMOVB(const X86::Instruction&);
  339. void FCMOVBE(const X86::Instruction&);
  340. void FCMOVNB(const X86::Instruction&);
  341. void FCMOVNBE(const X86::Instruction&);
  342. void FCMOVU(const X86::Instruction&);
  343. void FCMOVNU(const X86::Instruction&);
  344. // BASIC ARITHMETIC
  345. void FADD_RM32(const X86::Instruction&);
  346. void FADD_RM64(const X86::Instruction&);
  347. void FADDP(const X86::Instruction&);
  348. void FIADD_RM16(const X86::Instruction&);
  349. void FIADD_RM32(const X86::Instruction&);
  350. void FSUB_RM32(const X86::Instruction&);
  351. void FSUB_RM64(const X86::Instruction&);
  352. void FSUBP(const X86::Instruction&);
  353. void FSUBR_RM32(const X86::Instruction&);
  354. void FSUBR_RM64(const X86::Instruction&);
  355. void FSUBRP(const X86::Instruction&);
  356. void FISUB_RM16(const X86::Instruction&);
  357. void FISUB_RM32(const X86::Instruction&);
  358. void FISUBR_RM16(const X86::Instruction&);
  359. void FISUBR_RM32(const X86::Instruction&);
  360. void FMUL_RM32(const X86::Instruction&);
  361. void FMUL_RM64(const X86::Instruction&);
  362. void FMULP(const X86::Instruction&);
  363. void FIMUL_RM16(const X86::Instruction&);
  364. void FIMUL_RM32(const X86::Instruction&);
  365. void FDIV_RM32(const X86::Instruction&);
  366. void FDIV_RM64(const X86::Instruction&);
  367. void FDIVP(const X86::Instruction&);
  368. void FDIVR_RM32(const X86::Instruction&);
  369. void FDIVR_RM64(const X86::Instruction&);
  370. void FDIVRP(const X86::Instruction&);
  371. void FIDIV_RM16(const X86::Instruction&);
  372. void FIDIV_RM32(const X86::Instruction&);
  373. void FIDIVR_RM16(const X86::Instruction&);
  374. void FIDIVR_RM32(const X86::Instruction&);
  375. void FPREM(const X86::Instruction&);
  376. void FPREM1(const X86::Instruction&);
  377. void FABS(const X86::Instruction&);
  378. void FCHS(const X86::Instruction&);
  379. void FRNDINT(const X86::Instruction&);
  380. void FSCALE(const X86::Instruction&);
  381. void FSQRT(const X86::Instruction&);
  382. void FXTRACT(const X86::Instruction&);
  383. // COMPARISON
  384. void FCOM_RM32(const X86::Instruction&);
  385. void FCOM_RM64(const X86::Instruction&);
  386. void FCOMP_RM32(const X86::Instruction&);
  387. void FCOMP_RM64(const X86::Instruction&);
  388. void FCOMPP(const X86::Instruction&);
  389. void FCOMI(const X86::Instruction&);
  390. void FCOMIP(const X86::Instruction&);
  391. void FUCOM(const X86::Instruction&);
  392. void FUCOMP(const X86::Instruction&);
  393. void FUCOMPP(const X86::Instruction&);
  394. void FUCOMI(const X86::Instruction&);
  395. void FUCOMIP(const X86::Instruction&);
  396. void FICOM_RM16(const X86::Instruction&);
  397. void FICOM_RM32(const X86::Instruction&);
  398. void FICOMP_RM16(const X86::Instruction&);
  399. void FICOMP_RM32(const X86::Instruction&);
  400. void FTST(const X86::Instruction&);
  401. void FXAM(const X86::Instruction&);
  402. // TRANSCENDENTAL
  403. void FSIN(const X86::Instruction&);
  404. void FCOS(const X86::Instruction&);
  405. void FSINCOS(const X86::Instruction&);
  406. void FPTAN(const X86::Instruction&);
  407. void FPATAN(const X86::Instruction&);
  408. void F2XM1(const X86::Instruction&);
  409. void FYL2X(const X86::Instruction&);
  410. void FYL2XP1(const X86::Instruction&);
  411. // CONSTANT LOAD
  412. void FLD1(const X86::Instruction&);
  413. void FLDZ(const X86::Instruction&);
  414. void FLDPI(const X86::Instruction&);
  415. void FLDL2E(const X86::Instruction&);
  416. void FLDLN2(const X86::Instruction&);
  417. void FLDL2T(const X86::Instruction&);
  418. void FLDLG2(const X86::Instruction&);
  419. // CONTROL
  420. void FINCSTP(const X86::Instruction&);
  421. void FDECSTP(const X86::Instruction&);
  422. void FFREE(const X86::Instruction&);
  423. void FFREEP(const X86::Instruction&); // undocumented
  424. // FIXME: Non N- versions?
  425. void FNINIT(const X86::Instruction&);
  426. void FNCLEX(const X86::Instruction&);
  427. void FNSTCW(const X86::Instruction&);
  428. void FLDCW(const X86::Instruction&);
  429. void FNSTENV(const X86::Instruction&);
  430. void FLDENV(const X86::Instruction&);
  431. void FNSAVE(const X86::Instruction&);
  432. void FRSTOR(const X86::Instruction&);
  433. void FNSTSW(const X86::Instruction&);
  434. void FNSTSW_AX(const X86::Instruction&);
  435. // FIXME: WAIT && FWAIT
  436. void FNOP(const X86::Instruction&);
  437. // FPU & SIMD MANAGEMENT
  438. // FIXME: FXSAVE && FXRSTOR
  439. // DO NOTHING?
  440. // FIXME: FENI, FDISI, FSETPM
  441. void FNENI(const X86::Instruction&);
  442. void FNDISI(const X86::Instruction&);
  443. void FNSETPM(const X86::Instruction&);
  444. // MMX
  445. // ARITHMETIC
  446. void PADDB_mm1_mm2m64(const X86::Instruction&);
  447. void PADDW_mm1_mm2m64(const X86::Instruction&);
  448. void PADDD_mm1_mm2m64(const X86::Instruction&);
  449. void PADDSB_mm1_mm2m64(const X86::Instruction&);
  450. void PADDSW_mm1_mm2m64(const X86::Instruction&);
  451. void PADDUSB_mm1_mm2m64(const X86::Instruction&);
  452. void PADDUSW_mm1_mm2m64(const X86::Instruction&);
  453. void PSUBB_mm1_mm2m64(const X86::Instruction&);
  454. void PSUBW_mm1_mm2m64(const X86::Instruction&);
  455. void PSUBD_mm1_mm2m64(const X86::Instruction&);
  456. void PSUBSB_mm1_mm2m64(const X86::Instruction&);
  457. void PSUBSW_mm1_mm2m64(const X86::Instruction&);
  458. void PSUBUSB_mm1_mm2m64(const X86::Instruction&);
  459. void PSUBUSW_mm1_mm2m64(const X86::Instruction&);
  460. void PMULHW_mm1_mm2m64(const X86::Instruction&);
  461. void PMULLW_mm1_mm2m64(const X86::Instruction&);
  462. void PMADDWD_mm1_mm2m64(const X86::Instruction&);
  463. // COMPARISON
  464. void PCMPEQB_mm1_mm2m64(const X86::Instruction&);
  465. void PCMPEQW_mm1_mm2m64(const X86::Instruction&);
  466. void PCMPEQD_mm1_mm2m64(const X86::Instruction&);
  467. void PCMPGTB_mm1_mm2m64(const X86::Instruction&);
  468. void PCMPGTW_mm1_mm2m64(const X86::Instruction&);
  469. void PCMPGTD_mm1_mm2m64(const X86::Instruction&);
  470. // CONVERSION
  471. void PACKSSDW_mm1_mm2m64(const X86::Instruction&);
  472. void PACKSSWB_mm1_mm2m64(const X86::Instruction&);
  473. void PACKUSWB_mm1_mm2m64(const X86::Instruction&);
  474. // UNPACK
  475. void PUNPCKHBW_mm1_mm2m64(const X86::Instruction&);
  476. void PUNPCKHWD_mm1_mm2m64(const X86::Instruction&);
  477. void PUNPCKHDQ_mm1_mm2m64(const X86::Instruction&);
  478. void PUNPCKLBW_mm1_mm2m32(const X86::Instruction&);
  479. void PUNPCKLWD_mm1_mm2m32(const X86::Instruction&);
  480. void PUNPCKLDQ_mm1_mm2m32(const X86::Instruction&);
  481. // LOGICAL
  482. void PAND_mm1_mm2m64(const X86::Instruction&);
  483. void PANDN_mm1_mm2m64(const X86::Instruction&);
  484. void POR_mm1_mm2m64(const X86::Instruction&);
  485. void PXOR_mm1_mm2m64(const X86::Instruction&);
  486. // SHIFT
  487. void PSLLW_mm1_mm2m64(const X86::Instruction&);
  488. void PSLLW_mm1_imm8(const X86::Instruction&);
  489. void PSLLD_mm1_mm2m64(const X86::Instruction&);
  490. void PSLLD_mm1_imm8(const X86::Instruction&);
  491. void PSLLQ_mm1_mm2m64(const X86::Instruction&);
  492. void PSLLQ_mm1_imm8(const X86::Instruction&);
  493. void PSRAW_mm1_mm2m64(const X86::Instruction&);
  494. void PSRAW_mm1_imm8(const X86::Instruction&);
  495. void PSRAD_mm1_mm2m64(const X86::Instruction&);
  496. void PSRAD_mm1_imm8(const X86::Instruction&);
  497. void PSRLW_mm1_mm2m64(const X86::Instruction&);
  498. void PSRLW_mm1_imm8(const X86::Instruction&);
  499. void PSRLD_mm1_mm2m64(const X86::Instruction&);
  500. void PSRLD_mm1_imm8(const X86::Instruction&);
  501. void PSRLQ_mm1_mm2m64(const X86::Instruction&);
  502. void PSRLQ_mm1_imm8(const X86::Instruction&);
  503. // DATA TRANSFER
  504. void MOVD_mm1_rm32(const X86::Instruction&);
  505. void MOVD_rm32_mm2(const X86::Instruction&);
  506. void MOVQ_mm1_mm2m64(const X86::Instruction&);
  507. void MOVQ_mm1m64_mm2(const X86::Instruction&);
  508. void MOVQ_mm1_rm64(const X86::Instruction&); // long mode
  509. void MOVQ_rm64_mm2(const X86::Instruction&); // long mode
  510. // EMPTY MMX STATE
  511. void EMMS(const X86::Instruction&);
  512. };
  513. }