[Qemu-devel] [GSOC] Support for AVX within TCG: Work Product Submission

2019-08-25 Thread Jan Bobek
Hi folks,

those of you who have been keeping up with Google Summer of Code
this year might know that it's nearly over -- meaning that it's
time for me to summarize all the work that I have done as a
participant. Without further ado, you can find the summary
attached below.

Huge thanks to everyone who made this possible!

Best,
-Jan Bobek



GSOC WORK PRODUCT SUBMISSION

TITLE: Support for AVX within TCG
DATE: 08/25/2019
AUTHOR: Jan Bobek 
MENTOR: Richard Henderson 

I. SUMMARY

The goal of this GSoC project was to implement support for AVX
instructions in the i386 TCG front-end. The project was effectively
split up into two parts:

  - extending RISU [1] with the ability to generate and test x86
instruction streams (to properly test the new AVX implementation);

  - the actual work on AVX instructions in the i386 TCG front-end.

II. RISU CHANGES

There have been two patch series with changes to RISU:

  - The first one [2] adds support for testing x86 instruction
sequences, and has been merged as early as June 7, 2019.

  - The second series [3] implements generation of x86 instruction
streams using vector instructions up to AVX2; its latest iteration
has not been merged yet due to several more or less minor issues
raised during code review.

Despite the second series not being merged yet, the implemented
functionality was considered sufficient and a decision was made to
proceed to the next stage of the project [4].

III. QEMU CHANGES

All QEMU changes related to this project are included in a single
extensive patch series [5]; previous iterations can be found at [6],
[7] and [8].

The series features:

  - brand-new infrastructure for instruction decoding;

  - support for decoding vector instructions up to AVX2.

Work that remains to be done includes:

  - rewrite of old ad-hoc helpers into gvec-style helpers;

  - implementation of helpers for previously unsupported AVX
instructions (e.g. VGATHER et al.)

IV. FINAL NOTES

Even though I could not completely finish the project in the allotted
time, I had a great time working on it, and I am planning to do the
rest of the work in my free time over the coming weeks. Needless to
say, I learned a lot in the process (especially about the x86 ISA),
and I am very thankful to the GSoC program for making it all possible.

Last but definitely not least, I would like to thank my mentor,
Richard Henderson, for his support and assistance throughout this
project. Your insights during code reviews have been indispensable,
and I would not have been able to make as much progress on this
project without your guidance.

Thank you, Richard!

REFERENCES

  1. http://git.linaro.org/people/peter.maydell/risu.git/
  2. https://lists.nongnu.org/archive/html/qemu-devel/2019-05/msg05720.html
  3. https://lists.nongnu.org/archive/html/qemu-devel/2019-07/msg02916.html
  4. https://lists.nongnu.org/archive/html/qemu-devel/2019-07/msg04758.html
  5. https://lists.nongnu.org/archive/html/qemu-devel/2019-08/msg04412.html
  6. https://lists.nongnu.org/archive/html/qemu-devel/2019-08/msg02616.html
  7. https://lists.nongnu.org/archive/html/qemu-devel/2019-08/msg01790.html
  8. https://lists.nongnu.org/archive/html/qemu-devel/2019-07/msg07041.html



signature.asc
Description: OpenPGP digital signature


[Qemu-devel] [RFC PATCH v4 64/75] target/i386: introduce AVX2 vector instructions to sse-opcode.inc.h

2019-08-21 Thread Jan Bobek
Add all the AVX2 vector instruction entries to sse-opcode.inc.h.

Signed-off-by: Jan Bobek 
---
 target/i386/sse-opcode.inc.h | 362 ++-
 1 file changed, 359 insertions(+), 3 deletions(-)

diff --git a/target/i386/sse-opcode.inc.h b/target/i386/sse-opcode.inc.h
index c3c0ec4f89..abbb0a15d7 100644
--- a/target/i386/sse-opcode.inc.h
+++ b/target/i386/sse-opcode.inc.h
@@ -855,6 +855,181 @@
  * VEX.128.66.0F.WIG 73 /3 ib  VPSRLDQ xmm1, xmm2, imm8
  * VEX.LZ.0F.WIG AE /2 VLDMXCSR m32
  * VEX.LZ.0F.WIG AE /3 VSTMXCSR m32
+ *
+ * AVX2 Instructions
+ * --
+ * VEX.256.66.0F.W0 D7 /r  VPMOVMSKB r32, ymm1
+ * VEX.256.66.0F.W1 D7 /r  VPMOVMSKB r64, ymm1
+ * VEX.256.66.0F.WIG FC /r VPADDB ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG FD /r VPADDW ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG FE /r VPADDD ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG D4 /r VPADDQ ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG EC /r VPADDSB ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG ED /r VPADDSW ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG DC /r VPADDUSB ymm1,ymm2,ymm3/m256
+ * VEX.256.66.0F.WIG DD /r VPADDUSW ymm1,ymm2,ymm3/m256
+ * VEX.256.66.0F38.WIG 01 /r   VPHADDW ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F38.WIG 02 /r   VPHADDD ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F38.WIG 03 /r   VPHADDSW ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG F8 /r VPSUBB ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG F9 /r VPSUBW ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG FA /r VPSUBD ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG FB /r VPSUBQ ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG E8 /r VPSUBSB ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG E9 /r VPSUBSW ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG D8 /r VPSUBUSB ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG D9 /r VPSUBUSW ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F38.WIG 05 /r   VPHSUBW ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F38.WIG 06 /r   VPHSUBD ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F38.WIG 07 /r   VPHSUBSW ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG D5 /r VPMULLW ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F38.WIG 40 /r   VPMULLD ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG E5 /r VPMULHW ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG E4 /r VPMULHUW ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F38.WIG 28 /r   VPMULDQ ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG F4 /r VPMULUDQ ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F38.WIG 0B /r   VPMULHRSW ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG F5 /r VPMADDWD ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F38.WIG 04 /r   VPMADDUBSW ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F DA /r VPMINUB ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F38 3A /r   VPMINUW ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F38.WIG 3B /r   VPMINUD ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F38 38 /r   VPMINSB ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F EA /r VPMINSW ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F38.WIG 39 /r   VPMINSD ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F DE /r VPMAXUB ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F38 3E /r   VPMAXUW ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F38.WIG 3F /r   VPMAXUD ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F38.WIG 3C /r   VPMAXSB ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG EE /r VPMAXSW ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F38.WIG 3D /r   VPMAXSD ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG E0 /r VPAVGB ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG E3 /r VPAVGW ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG F6 /r VPSADBW ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F3A.WIG 42 /r ibVMPSADBW ymm1, ymm2, ymm3/m256, imm8
+ * VEX.256.66.0F38.WIG 1C /r   VPABSB ymm1, ymm2/m256
+ * VEX.256.66.0F38.WIG 1D /r   VPABSW ymm1, ymm2/m256
+ * VEX.256.66.0F38.WIG 1E /r   VPABSD ymm1, ymm2/m256
+ * VEX.256.66.0F38.WIG 08 /r   VPSIGNB ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F38.WIG 09 /r   VPSIGNW ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F38.WIG 0A /r   VPSIGND ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG 74 /r VPCMPEQB ymm1,ymm2,ymm3/m256
+ * VEX.256.66.0F.WIG 75 /r VPCMPEQW ymm1,ymm2,ymm3/m256
+ * VEX.256.66.0F.WIG 76 /r VPCMPEQD ymm1,ymm2,ymm3/m256
+ * VEX.256.66.0F38.WIG 29 /r   VPCMPEQQ ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG 64 /r VPCMPGTB ymm1,ymm2,ymm3/m256
+ * VEX.256.66.0F.WIG 65 /r VPCMPGTW ymm1,ymm2,ymm3/m256
+ * VEX.256.66.0F.WIG 66 /r VPCMPGTD ymm1,ymm2,ymm3/m256
+ * VEX.256.66.0F38.WIG 37 /r   VPCMPGTQ ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG DB /r VPAND ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG DF /r VPANDN ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG EB /r VPOR ymm1, ymm2, ymm3/m256
+ * VEX.256.66.0F.WIG EF /r VPXOR ymm1, ymm2

[Qemu-devel] [RFC PATCH v4 63/75] target/i386: introduce AVX2 code generators

2019-08-21 Thread Jan Bobek
Introduce code generators required by AVX2 instructions.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 407 ++--
 1 file changed, 395 insertions(+), 12 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 3f4bb40932..3149989d68 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4946,6 +4946,11 @@ DEF_INSNOP_ALIAS(Mhq, M)
 DEF_INSNOP_ALIAS(Mdq, M)
 DEF_INSNOP_ALIAS(Mqq, M)
 
+DEF_INSNOP_ALIAS(MDdq, M)
+DEF_INSNOP_ALIAS(MDqq, M)
+DEF_INSNOP_ALIAS(MQdq, M)
+DEF_INSNOP_ALIAS(MQqq, M)
+
 /*
  * 32-bit general register operands
  */
@@ -5907,6 +5912,14 @@ GEN_INSN2(vpmovmskb, Gq, Udq)
 tcg_gen_extu_i32_i64(arg1, arg1_r32);
 tcg_temp_free_i32(arg1_r32);
 }
+DEF_GEN_INSN2_HELPER_DEP(vpmovmskb, pmovmskb_xmm, Gd, Uqq)
+GEN_INSN2(vpmovmskb, Gq, Uqq)
+{
+const TCGv_i32 arg1_r32 = tcg_temp_new_i32();
+gen_insn2(vpmovmskb, Gd, Uqq)(env, s, arg1_r32, arg2);
+tcg_gen_extu_i32_i64(arg1, arg1_r32);
+tcg_temp_free_i32(arg1_r32);
+}
 
 DEF_GEN_INSN2_HELPER_DEP(movmskps, movmskps, Gd, Udq)
 GEN_INSN2(movmskps, Gq, Udq)
@@ -6049,27 +6062,35 @@ GEN_INSN2(vmovddup, Vqq, Wqq)
 DEF_GEN_INSN3_GVEC(paddb, Pq, Pq, Qq, add, MM_OPRSZ, MM_MAXSZ, MO_8)
 DEF_GEN_INSN3_GVEC(paddb, Vdq, Vdq, Wdq, add, XMM_OPRSZ, XMM_MAXSZ, MO_8)
 DEF_GEN_INSN3_GVEC(vpaddb, Vdq, Hdq, Wdq, add, XMM_OPRSZ, XMM_MAXSZ, MO_8)
+DEF_GEN_INSN3_GVEC(vpaddb, Vqq, Hqq, Wqq, add, XMM_OPRSZ, XMM_MAXSZ, MO_8)
 DEF_GEN_INSN3_GVEC(paddw, Pq, Pq, Qq, add, MM_OPRSZ, MM_MAXSZ, MO_16)
 DEF_GEN_INSN3_GVEC(paddw, Vdq, Vdq, Wdq, add, XMM_OPRSZ, XMM_MAXSZ, MO_16)
 DEF_GEN_INSN3_GVEC(vpaddw, Vdq, Hdq, Wdq, add, XMM_OPRSZ, XMM_MAXSZ, MO_16)
+DEF_GEN_INSN3_GVEC(vpaddw, Vqq, Hqq, Wqq, add, XMM_OPRSZ, XMM_MAXSZ, MO_16)
 DEF_GEN_INSN3_GVEC(paddd, Pq, Pq, Qq, add, MM_OPRSZ, MM_MAXSZ, MO_32)
 DEF_GEN_INSN3_GVEC(paddd, Vdq, Vdq, Wdq, add, XMM_OPRSZ, XMM_MAXSZ, MO_32)
 DEF_GEN_INSN3_GVEC(vpaddd, Vdq, Hdq, Wdq, add, XMM_OPRSZ, XMM_MAXSZ, MO_32)
+DEF_GEN_INSN3_GVEC(vpaddd, Vqq, Hqq, Wqq, add, XMM_OPRSZ, XMM_MAXSZ, MO_32)
 DEF_GEN_INSN3_GVEC(paddq, Pq, Pq, Qq, add, MM_OPRSZ, MM_MAXSZ, MO_64)
 DEF_GEN_INSN3_GVEC(paddq, Vdq, Vdq, Wdq, add, XMM_OPRSZ, XMM_MAXSZ, MO_64)
 DEF_GEN_INSN3_GVEC(vpaddq, Vdq, Hdq, Wdq, add, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN3_GVEC(vpaddq, Vqq, Hqq, Wqq, add, XMM_OPRSZ, XMM_MAXSZ, MO_64)
 DEF_GEN_INSN3_GVEC(paddsb, Pq, Pq, Qq, ssadd, MM_OPRSZ, MM_MAXSZ, MO_8)
 DEF_GEN_INSN3_GVEC(paddsb, Vdq, Vdq, Wdq, ssadd, XMM_OPRSZ, XMM_MAXSZ, MO_8)
 DEF_GEN_INSN3_GVEC(vpaddsb, Vdq, Hdq, Wdq, ssadd, XMM_OPRSZ, XMM_MAXSZ, MO_8)
+DEF_GEN_INSN3_GVEC(vpaddsb, Vqq, Hqq, Wqq, ssadd, XMM_OPRSZ, XMM_MAXSZ, MO_8)
 DEF_GEN_INSN3_GVEC(paddsw, Pq, Pq, Qq, ssadd, MM_OPRSZ, MM_MAXSZ, MO_16)
 DEF_GEN_INSN3_GVEC(paddsw, Vdq, Vdq, Wdq, ssadd, XMM_OPRSZ, XMM_MAXSZ, MO_16)
 DEF_GEN_INSN3_GVEC(vpaddsw, Vdq, Hdq, Wdq, ssadd, XMM_OPRSZ, XMM_MAXSZ, MO_16)
+DEF_GEN_INSN3_GVEC(vpaddsw, Vqq, Hqq, Wqq, ssadd, XMM_OPRSZ, XMM_MAXSZ, MO_16)
 DEF_GEN_INSN3_GVEC(paddusb, Pq, Pq, Qq, usadd, MM_OPRSZ, MM_MAXSZ, MO_8)
 DEF_GEN_INSN3_GVEC(paddusb, Vdq, Vdq, Wdq, usadd, XMM_OPRSZ, XMM_MAXSZ, MO_8)
 DEF_GEN_INSN3_GVEC(vpaddusb, Vdq, Hdq, Wdq, usadd, XMM_OPRSZ, XMM_MAXSZ, MO_8)
+DEF_GEN_INSN3_GVEC(vpaddusb, Vqq, Hqq, Wqq, usadd, XMM_OPRSZ, XMM_MAXSZ, MO_8)
 DEF_GEN_INSN3_GVEC(paddusw, Pq, Pq, Qq, usadd, MM_OPRSZ, MM_MAXSZ, MO_16)
 DEF_GEN_INSN3_GVEC(paddusw, Vdq, Vdq, Wdq, usadd, XMM_OPRSZ, XMM_MAXSZ, MO_16)
 DEF_GEN_INSN3_GVEC(vpaddusw, Vdq, Hdq, Wdq, usadd, XMM_OPRSZ, XMM_MAXSZ, MO_16)
+DEF_GEN_INSN3_GVEC(vpaddusw, Vqq, Hqq, Wqq, usadd, XMM_OPRSZ, XMM_MAXSZ, MO_16)
 DEF_GEN_INSN3_HELPER_EPP(addps, addps, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(vaddps, addps, Vdq, Hdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(vaddps, addps, Vqq, Hqq, Wqq)
@@ -6083,12 +6104,15 @@ DEF_GEN_INSN3_HELPER_EPP(vaddsd, addsd, Vq, Hq, Wq)
 DEF_GEN_INSN3_HELPER_EPP(phaddw, phaddw_mmx, Pq, Pq, Qq)
 DEF_GEN_INSN3_HELPER_EPP(phaddw, phaddw_xmm, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(vphaddw, phaddw_xmm, Vdq, Hdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(vphaddw, phaddw_xmm, Vqq, Hqq, Wqq)
 DEF_GEN_INSN3_HELPER_EPP(phaddd, phaddd_mmx, Pq, Pq, Qq)
 DEF_GEN_INSN3_HELPER_EPP(phaddd, phaddd_xmm, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(vphaddd, phaddd_xmm, Vdq, Hdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(vphaddd, phaddd_xmm, Vqq, Hqq, Wqq)
 DEF_GEN_INSN3_HELPER_EPP(phaddsw, phaddsw_mmx, Pq, Pq, Qq)
 DEF_GEN_INSN3_HELPER_EPP(phaddsw, phaddsw_xmm, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(vphaddsw, phaddsw_xmm, Vdq, Hdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(vphaddsw, phaddsw_xmm, Vqq, Hqq, Wqq)
 DEF_GEN_INSN3_HELPER_EPP(haddps, haddps, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(vhaddps, haddps, Vdq, Hdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(vhaddps, haddps, Vqq, Hqq, Wqq)
@@ -6099,27 +6123,35 @@ DEF_GEN_INSN3_HELPER_EPP(vhaddpd, haddpd, Vqq, Hqq, Wqq)
 DEF_GEN_INSN3_GVEC(psubb, Pq, Pq, Qq, sub, MM_OPRSZ, MM_MAXSZ, MO_8)
 DEF_GEN_INSN3_GVEC(psubb, Vdq, Vdq, Wdq, sub

[Qemu-devel] [RFC PATCH v4 73/75] target/i386: remove obsoleted helper_mov(l, q)_mm_T0

2019-08-21 Thread Jan Bobek
This helper has been obsoleted by the new code.

Signed-off-by: Jan Bobek 
---
 target/i386/ops_sse.h| 19 ---
 target/i386/ops_sse_header.h |  4 
 target/i386/translate.c  | 33 -
 3 files changed, 56 deletions(-)

diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h
index b866ead1c8..8172324e34 100644
--- a/target/i386/ops_sse.h
+++ b/target/i386/ops_sse.h
@@ -550,25 +550,6 @@ void glue(helper_maskmov, SUFFIX)(CPUX86State *env, Reg 
*a, Reg *b,
 }
 }
 
-void glue(helper_movl_mm_T0, SUFFIX)(Reg *d, uint32_t val)
-{
-d->L(0) = val;
-d->L(1) = 0;
-#if SHIFT == 1
-d->Q(1) = 0;
-#endif
-}
-
-#ifdef TARGET_X86_64
-void glue(helper_movq_mm_T0, SUFFIX)(Reg *d, uint64_t val)
-{
-d->Q(0) = val;
-#if SHIFT == 1
-d->Q(1) = 0;
-#endif
-}
-#endif
-
 #if SHIFT == 0
 void glue(helper_pshufw, SUFFIX)(Reg *d, Reg *s, int order)
 {
diff --git a/target/i386/ops_sse_header.h b/target/i386/ops_sse_header.h
index ec7d1fc686..ee8bd4c1af 100644
--- a/target/i386/ops_sse_header.h
+++ b/target/i386/ops_sse_header.h
@@ -76,10 +76,6 @@ DEF_HELPER_4(glue(pmaddwd, SUFFIX), void, Reg, Reg, Reg, i32)
 
 DEF_HELPER_4(glue(psadbw, SUFFIX), void, Reg, Reg, Reg, i32)
 DEF_HELPER_4(glue(maskmov, SUFFIX), void, env, Reg, Reg, tl)
-DEF_HELPER_2(glue(movl_mm_T0, SUFFIX), void, Reg, i32)
-#ifdef TARGET_X86_64
-DEF_HELPER_2(glue(movq_mm_T0, SUFFIX), void, Reg, i64)
-#endif
 
 #if SHIFT == 0
 DEF_HELPER_3(glue(pshufw, SUFFIX), void, Reg, Reg, int)
diff --git a/target/i386/translate.c b/target/i386/translate.c
index 6bffbaee4c..3554086336 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -3079,39 +3079,6 @@ static void gen_sse(CPUX86State *env, DisasContext *s, 
int b)
 gen_op_st_v(s, MO_32, s->T0, s->A0);
 }
 break;
-case 0x6e: /* movd mm, ea */
-#ifdef TARGET_X86_64
-if (s->dflag == MO_64) {
-gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
-tcg_gen_st_tl(s->T0, cpu_env,
-  offsetof(CPUX86State, fpregs[reg].mmx));
-} else
-#endif
-{
-gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
-tcg_gen_addi_ptr(s->ptr0, cpu_env,
- offsetof(CPUX86State,fpregs[reg].mmx));
-tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
-gen_helper_movl_mm_T0_mmx(s->ptr0, s->tmp2_i32);
-}
-break;
-case 0x16e: /* movd xmm, ea */
-#ifdef TARGET_X86_64
-if (s->dflag == MO_64) {
-gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0);
-tcg_gen_addi_ptr(s->ptr0, cpu_env,
- offsetof(CPUX86State,xmm_regs[reg]));
-gen_helper_movq_mm_T0_xmm(s->ptr0, s->T0);
-} else
-#endif
-{
-gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0);
-tcg_gen_addi_ptr(s->ptr0, cpu_env,
- offsetof(CPUX86State,xmm_regs[reg]));
-tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
-gen_helper_movl_mm_T0_xmm(s->ptr0, s->tmp2_i32);
-}
-break;
 case 0x6f: /* movq mm, ea */
 if (mod != 3) {
 gen_lea_modrm(env, s, modrm);
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 72/75] target/i386: convert psadbw helper to gvec style

2019-08-21 Thread Jan Bobek
Make these helpers suitable for use with tcg_gen_gvec_* functions.

Signed-off-by: Jan Bobek 
---
 target/i386/ops_sse.h| 64 +++-
 target/i386/ops_sse_header.h |  2 +-
 target/i386/translate.c  |  9 +++--
 3 files changed, 32 insertions(+), 43 deletions(-)

diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h
index 384a835662..b866ead1c8 100644
--- a/target/i386/ops_sse.h
+++ b/target/i386/ops_sse.h
@@ -412,6 +412,15 @@ static inline int satsw(int x)
 }
 }
 
+static inline int abs1(int x)
+{
+if (x < 0) {
+return -x;
+} else {
+return x;
+}
+}
+
 #define FMULHRW(a, b) (((int16_t)(a) * (int16_t)(b) + 0x8000) >> 16)
 #endif
 
@@ -510,52 +519,33 @@ void glue(helper_pmaddwd, SUFFIX)(Reg *d, Reg *a, Reg *b, 
uint32_t desc)
 glue(clear_high, SUFFIX)(d, oprsz, maxsz);
 }
 
-#if SHIFT == 0
-static inline int abs1(int a)
+void glue(helper_psadbw, SUFFIX)(Reg *d, Reg *a, Reg *b, uint32_t desc)
 {
-if (a < 0) {
-return -a;
-} else {
-return a;
+const intptr_t oprsz = simd_oprsz(desc);
+const intptr_t maxsz = simd_maxsz(desc);
+
+for (intptr_t i = 0; i * sizeof(uint64_t) < oprsz; ++i) {
+const uint64_t t0 = abs1(a->B(8 * i + 0) - b->B(8 * i + 0));
+const uint64_t t1 = abs1(a->B(8 * i + 1) - b->B(8 * i + 1));
+const uint64_t t2 = abs1(a->B(8 * i + 2) - b->B(8 * i + 2));
+const uint64_t t3 = abs1(a->B(8 * i + 3) - b->B(8 * i + 3));
+const uint64_t t4 = abs1(a->B(8 * i + 4) - b->B(8 * i + 4));
+const uint64_t t5 = abs1(a->B(8 * i + 5) - b->B(8 * i + 5));
+const uint64_t t6 = abs1(a->B(8 * i + 6) - b->B(8 * i + 6));
+const uint64_t t7 = abs1(a->B(8 * i + 7) - b->B(8 * i + 7));
+d->Q(i) = t0 + t1 + t2 + t3 + t4 + t5 + t6 + t7;
 }
+glue(clear_high, SUFFIX)(d, oprsz, maxsz);
 }
-#endif
-void glue(helper_psadbw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
-{
-unsigned int val;
 
-val = 0;
-val += abs1(d->B(0) - s->B(0));
-val += abs1(d->B(1) - s->B(1));
-val += abs1(d->B(2) - s->B(2));
-val += abs1(d->B(3) - s->B(3));
-val += abs1(d->B(4) - s->B(4));
-val += abs1(d->B(5) - s->B(5));
-val += abs1(d->B(6) - s->B(6));
-val += abs1(d->B(7) - s->B(7));
-d->Q(0) = val;
-#if SHIFT == 1
-val = 0;
-val += abs1(d->B(8) - s->B(8));
-val += abs1(d->B(9) - s->B(9));
-val += abs1(d->B(10) - s->B(10));
-val += abs1(d->B(11) - s->B(11));
-val += abs1(d->B(12) - s->B(12));
-val += abs1(d->B(13) - s->B(13));
-val += abs1(d->B(14) - s->B(14));
-val += abs1(d->B(15) - s->B(15));
-d->Q(1) = val;
-#endif
-}
-
-void glue(helper_maskmov, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
+void glue(helper_maskmov, SUFFIX)(CPUX86State *env, Reg *a, Reg *b,
   target_ulong a0)
 {
 int i;
 
 for (i = 0; i < (8 << SHIFT); i++) {
-if (s->B(i) & 0x80) {
-cpu_stb_data_ra(env, a0 + i, d->B(i), GETPC());
+if (b->B(i) & 0x80) {
+cpu_stb_data_ra(env, a0 + i, a->B(i), GETPC());
 }
 }
 }
diff --git a/target/i386/ops_sse_header.h b/target/i386/ops_sse_header.h
index 18d39ca649..ec7d1fc686 100644
--- a/target/i386/ops_sse_header.h
+++ b/target/i386/ops_sse_header.h
@@ -74,7 +74,7 @@ DEF_HELPER_4(glue(pavgw, SUFFIX), void, Reg, Reg, Reg, i32)
 DEF_HELPER_4(glue(pmuludq, SUFFIX), void, Reg, Reg, Reg, i32)
 DEF_HELPER_4(glue(pmaddwd, SUFFIX), void, Reg, Reg, Reg, i32)
 
-DEF_HELPER_3(glue(psadbw, SUFFIX), void, env, Reg, Reg)
+DEF_HELPER_4(glue(psadbw, SUFFIX), void, Reg, Reg, Reg, i32)
 DEF_HELPER_4(glue(maskmov, SUFFIX), void, env, Reg, Reg, tl)
 DEF_HELPER_2(glue(movl_mm_T0, SUFFIX), void, Reg, i32)
 #ifdef TARGET_X86_64
diff --git a/target/i386/translate.c b/target/i386/translate.c
index 55607db09c..6bffbaee4c 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -2806,7 +2806,6 @@ static const SSEFunc_0_epp sse_op_table1[256][4] = {
 [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, 
gen_helper_cvtpd2dq },
 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL },  /* movntq, movntq */
 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
-[0xf6] = MMX_OP2(psadbw),
 [0xf7] = { (SSEFunc_0_epp)gen_helper_maskmov_mmx,
(SSEFunc_0_epp)gen_helper_maskmov_xmm }, /* XXX: casts */
 };
@@ -6256,10 +6255,10 @@ DEF_GEN_INSN3_GVEC(pavgw, Pq, Pq, Qq, 3_ool, MM_OPRSZ, 
MM_MAXSZ, pavgw_mmx)
 DEF_GEN_INSN3_GVEC(pavgw, Vdq, Vdq, Wdq, 3_ool, XMM_OPRSZ, XMM_MAXSZ, 
pavgw_xmm)
 DEF_GEN_INSN3_GVEC(vpavgw, Vdq, Hdq, Wdq, 3_ool, XMM_OPRSZ, XMM_MAXSZ, 
pavgw_xmm)
 DEF_GEN_INSN3_GVEC(vpavgw, Vqq, Hqq, Wqq, 3_ool, XMM_OPRSZ, XMM_MAXSZ, 
pavgw_xmm)
-DEF_GEN_INSN3_HELPER_EPP(psadbw, psadb

[Qemu-devel] [RFC PATCH v4 71/75] target/i386: convert pmuludq/pmaddwd helpers to gvec style

2019-08-21 Thread Jan Bobek
Make these helpers suitable for use with tcg_gen_gvec_* functions.
---
 target/i386/ops_sse.h| 27 +--
 target/i386/ops_sse_header.h |  4 ++--
 target/i386/translate.c  | 18 --
 3 files changed, 27 insertions(+), 22 deletions(-)

diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h
index 1661bd7c64..384a835662 100644
--- a/target/i386/ops_sse.h
+++ b/target/i386/ops_sse.h
@@ -485,22 +485,29 @@ void glue(helper_pavgw, SUFFIX)(Reg *d, Reg *a, Reg *b, 
uint32_t desc)
 glue(clear_high, SUFFIX)(d, oprsz, maxsz);
 }
 
-void glue(helper_pmuludq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
+void glue(helper_pmuludq, SUFFIX)(Reg *d, Reg *a, Reg *b, uint32_t desc)
 {
-d->Q(0) = (uint64_t)s->L(0) * (uint64_t)d->L(0);
-#if SHIFT == 1
-d->Q(1) = (uint64_t)s->L(2) * (uint64_t)d->L(2);
-#endif
+const intptr_t oprsz = simd_oprsz(desc);
+const intptr_t maxsz = simd_maxsz(desc);
+
+for (intptr_t i = 0; i * sizeof(uint64_t) < oprsz; ++i) {
+const uint64_t t = (uint64_t)a->L(2 * i) * (uint64_t)b->L(2 * i);
+d->Q(i) = t;
+}
+glue(clear_high, SUFFIX)(d, oprsz, maxsz);
 }
 
-void glue(helper_pmaddwd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
+void glue(helper_pmaddwd, SUFFIX)(Reg *d, Reg *a, Reg *b, uint32_t desc)
 {
-int i;
+const intptr_t oprsz = simd_oprsz(desc);
+const intptr_t maxsz = simd_maxsz(desc);
 
-for (i = 0; i < (2 << SHIFT); i++) {
-d->L(i) = (int16_t)s->W(2 * i) * (int16_t)d->W(2 * i) +
-(int16_t)s->W(2 * i + 1) * (int16_t)d->W(2 * i + 1);
+for (intptr_t i = 0; i * sizeof(uint32_t) < oprsz; ++i) {
+const int32_t t0 = (int32_t)a->W(2 * i + 0) * (int32_t)b->W(2 * i + 0);
+const int32_t t1 = (int32_t)a->W(2 * i + 1) * (int32_t)b->W(2 * i + 1);
+d->L(i) = t0 + t1;
 }
+glue(clear_high, SUFFIX)(d, oprsz, maxsz);
 }
 
 #if SHIFT == 0
diff --git a/target/i386/ops_sse_header.h b/target/i386/ops_sse_header.h
index b5e8aae897..18d39ca649 100644
--- a/target/i386/ops_sse_header.h
+++ b/target/i386/ops_sse_header.h
@@ -71,8 +71,8 @@ DEF_HELPER_3(glue(pavgusb, SUFFIX), void, env, Reg, Reg)
 #endif
 DEF_HELPER_4(glue(pavgw, SUFFIX), void, Reg, Reg, Reg, i32)
 
-DEF_HELPER_3(glue(pmuludq, SUFFIX), void, env, Reg, Reg)
-DEF_HELPER_3(glue(pmaddwd, SUFFIX), void, env, Reg, Reg)
+DEF_HELPER_4(glue(pmuludq, SUFFIX), void, Reg, Reg, Reg, i32)
+DEF_HELPER_4(glue(pmaddwd, SUFFIX), void, Reg, Reg, Reg, i32)
 
 DEF_HELPER_3(glue(psadbw, SUFFIX), void, env, Reg, Reg)
 DEF_HELPER_4(glue(maskmov, SUFFIX), void, env, Reg, Reg, tl)
diff --git a/target/i386/translate.c b/target/i386/translate.c
index 77b2e18f34..55607db09c 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -2806,8 +2806,6 @@ static const SSEFunc_0_epp sse_op_table1[256][4] = {
 [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, 
gen_helper_cvtpd2dq },
 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL },  /* movntq, movntq */
 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
-[0xf4] = MMX_OP2(pmuludq),
-[0xf5] = MMX_OP2(pmaddwd),
 [0xf6] = MMX_OP2(psadbw),
 [0xf7] = { (SSEFunc_0_epp)gen_helper_maskmov_mmx,
(SSEFunc_0_epp)gen_helper_maskmov_xmm }, /* XXX: casts */
@@ -6129,10 +6127,10 @@ DEF_GEN_INSN3_GVEC(vpmulhuw, Vqq, Hqq, Wqq, 3_ool, 
XMM_OPRSZ, XMM_MAXSZ, pmulhuw
 DEF_GEN_INSN3_HELPER_EPP(pmuldq, pmuldq_xmm, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(vpmuldq, pmuldq_xmm, Vdq, Hdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(vpmuldq, pmuldq_xmm, Vqq, Hqq, Wqq)
-DEF_GEN_INSN3_HELPER_EPP(pmuludq, pmuludq_mmx, Pq, Pq, Qq)
-DEF_GEN_INSN3_HELPER_EPP(pmuludq, pmuludq_xmm, Vdq, Vdq, Wdq)
-DEF_GEN_INSN3_HELPER_EPP(vpmuludq, pmuludq_xmm, Vdq, Hdq, Wdq)
-DEF_GEN_INSN3_HELPER_EPP(vpmuludq, pmuludq_xmm, Vqq, Hqq, Wqq)
+DEF_GEN_INSN3_GVEC(pmuludq, Pq, Pq, Qq, 3_ool, MM_OPRSZ, MM_MAXSZ, pmuludq_mmx)
+DEF_GEN_INSN3_GVEC(pmuludq, Vdq, Vdq, Wdq, 3_ool, XMM_OPRSZ, XMM_MAXSZ, 
pmuludq_xmm)
+DEF_GEN_INSN3_GVEC(vpmuludq, Vdq, Hdq, Wdq, 3_ool, XMM_OPRSZ, XMM_MAXSZ, 
pmuludq_xmm)
+DEF_GEN_INSN3_GVEC(vpmuludq, Vqq, Hqq, Wqq, 3_ool, XMM_OPRSZ, XMM_MAXSZ, 
pmuludq_xmm)
 DEF_GEN_INSN3_HELPER_EPP(pmulhrsw, pmulhrsw_mmx, Pq, Pq, Qq)
 DEF_GEN_INSN3_HELPER_EPP(pmulhrsw, pmulhrsw_xmm, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(vpmulhrsw, pmulhrsw_xmm, Vdq, Hdq, Wdq)
@@ -6147,10 +6145,10 @@ DEF_GEN_INSN3_HELPER_EPP(mulss, mulss, Vd, Vd, Wd)
 DEF_GEN_INSN3_HELPER_EPP(vmulss, mulss, Vd, Hd, Wd)
 DEF_GEN_INSN3_HELPER_EPP(mulsd, mulsd, Vq, Vq, Wq)
 DEF_GEN_INSN3_HELPER_EPP(vmulsd, mulsd, Vq, Hq, Wq)
-DEF_GEN_INSN3_HELPER_EPP(pmaddwd, pmaddwd_mmx, Pq, Pq, Qq)
-DEF_GEN_INSN3_HELPER_EPP(pmaddwd, pmaddwd_xmm, Vdq, Vdq, Wdq)
-DEF_GEN_INSN3_HELPER_EPP(vpmaddwd, pmaddwd_xmm, Vdq, Hdq, Wdq)
-DEF_GEN_INSN3_HELPER_EPP(vpmaddwd, pmaddwd_xmm, Vqq, Hqq, Wqq)
+DEF_GEN_INSN3_GVEC(pmaddwd, Pq, Pq, Qq, 3_ool, MM_OPRSZ, MM_MAXSZ, pmaddwd_mmx)
+DEF_GEN_INSN3_GVEC(pmaddwd, Vdq, Vdq, Wdq, 3_ool, XMM_OPRSZ, 

[Qemu-devel] [RFC PATCH v4 66/75] target/i386: cleanup leftovers in ops_sse_header.h

2019-08-21 Thread Jan Bobek
Get rid of unused macro definitions that have been left over after
removal of obsoleted helpers.
---
 target/i386/ops_sse_header.h | 28 ++--
 1 file changed, 6 insertions(+), 22 deletions(-)

diff --git a/target/i386/ops_sse_header.h b/target/i386/ops_sse_header.h
index d8e33dff6b..afa0ad0938 100644
--- a/target/i386/ops_sse_header.h
+++ b/target/i386/ops_sse_header.h
@@ -48,27 +48,15 @@ DEF_HELPER_3(glue(psrldq, SUFFIX), void, env, Reg, Reg)
 DEF_HELPER_3(glue(pslldq, SUFFIX), void, env, Reg, Reg)
 #endif
 
-#define SSE_HELPER_B(name, F)\
-DEF_HELPER_3(glue(name, SUFFIX), void, env, Reg, Reg)
-
-#define SSE_HELPER_W(name, F)\
-DEF_HELPER_3(glue(name, SUFFIX), void, env, Reg, Reg)
-
-#define SSE_HELPER_L(name, F)\
-DEF_HELPER_3(glue(name, SUFFIX), void, env, Reg, Reg)
-
-#define SSE_HELPER_Q(name, F)\
-DEF_HELPER_3(glue(name, SUFFIX), void, env, Reg, Reg)
-
-SSE_HELPER_W(pmullw, FMULLW)
+DEF_HELPER_3(glue(pmullw, SUFFIX), void, env, Reg, Reg)
 #if SHIFT == 0
-SSE_HELPER_W(pmulhrw, FMULHRW)
+DEF_HELPER_3(glue(pmulhrw, SUFFIX), void, env, Reg, Reg)
 #endif
-SSE_HELPER_W(pmulhuw, FMULHUW)
-SSE_HELPER_W(pmulhw, FMULHW)
+DEF_HELPER_3(glue(pmulhuw, SUFFIX), void, env, Reg, Reg)
+DEF_HELPER_3(glue(pmulhw, SUFFIX), void, env, Reg, Reg)
 
-SSE_HELPER_B(pavgb, FAVG)
-SSE_HELPER_W(pavgw, FAVG)
+DEF_HELPER_3(glue(pavgb, SUFFIX), void, env, Reg, Reg)
+DEF_HELPER_3(glue(pavgw, SUFFIX), void, env, Reg, Reg)
 
 DEF_HELPER_3(glue(pmuludq, SUFFIX), void, env, Reg, Reg)
 DEF_HELPER_3(glue(pmaddwd, SUFFIX), void, env, Reg, Reg)
@@ -311,10 +299,6 @@ DEF_HELPER_4(glue(pclmulqdq, SUFFIX), void, env, Reg, Reg, 
i32)
 #undef Reg
 #undef SUFFIX
 
-#undef SSE_HELPER_B
-#undef SSE_HELPER_W
-#undef SSE_HELPER_L
-#undef SSE_HELPER_Q
 #undef SSE_HELPER_S
 #undef SSE_HELPER_CMP
 #undef UNPCK_OP
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 61/75] target/i386: introduce AVX vector instructions to sse-opcode.inc.h

2019-08-21 Thread Jan Bobek
Add all the AVX vector instruction entries to sse-opcode.inc.h.

Signed-off-by: Jan Bobek 
---
 target/i386/sse-opcode.inc.h | 779 +++
 1 file changed, 779 insertions(+)

diff --git a/target/i386/sse-opcode.inc.h b/target/i386/sse-opcode.inc.h
index 1359508424..c3c0ec4f89 100644
--- a/target/i386/sse-opcode.inc.h
+++ b/target/i386/sse-opcode.inc.h
@@ -469,198 +469,767 @@
  * ---
  * 66 0F 3A 44 /r ib   PCLMULQDQ xmm1, xmm2/m128, imm8
  * VEX.128.66.0F3A.WIG 44 /r ibVPCLMULQDQ xmm1, xmm2, xmm3/m128, imm8
+ *
+ * AVX Instructions
+ * -
+ * VEX.128.66.0F.W0 6E /r  VMOVD xmm1,r32/m32
+ * VEX.128.66.0F.W0 7E /r  VMOVD r32/m32,xmm1
+ * VEX.128.66.0F.W1 6E /r  VMOVQ xmm1,r64/m64
+ * VEX.128.66.0F.W1 7E /r  VMOVQ r64/m64,xmm1
+ * VEX.128.F3.0F.WIG 7E /r VMOVQ xmm1, xmm2/m64
+ * VEX.128.66.0F.WIG D6 /r VMOVQ xmm1/m64, xmm2
+ * VEX.128.0F.WIG 28 /rVMOVAPS xmm1, xmm2/m128
+ * VEX.128.0F.WIG 29 /rVMOVAPS xmm2/m128, xmm1
+ * VEX.256.0F.WIG 28 /rVMOVAPS ymm1, ymm2/m256
+ * VEX.256.0F.WIG 29 /rVMOVAPS ymm2/m256, ymm1
+ * VEX.128.66.0F.WIG 28 /r VMOVAPD xmm1, xmm2/m128
+ * VEX.128.66.0F.WIG 29 /r VMOVAPD xmm2/m128, xmm1
+ * VEX.256.66.0F.WIG 28 /r VMOVAPD ymm1, ymm2/m256
+ * VEX.256.66.0F.WIG 29 /r VMOVAPD ymm2/m256, ymm1
+ * VEX.128.66.0F.WIG 6F /r VMOVDQA xmm1, xmm2/m128
+ * VEX.128.66.0F.WIG 7F /r VMOVDQA xmm2/m128, xmm1
+ * VEX.256.66.0F.WIG 6F /r VMOVDQA ymm1, ymm2/m256
+ * VEX.256.66.0F.WIG 7F /r VMOVDQA ymm2/m256, ymm1
+ * VEX.128.0F.WIG 10 /rVMOVUPS xmm1, xmm2/m128
+ * VEX.128.0F.WIG 11 /rVMOVUPS xmm2/m128, xmm1
+ * VEX.256.0F.WIG 10 /rVMOVUPS ymm1, ymm2/m256
+ * VEX.256.0F.WIG 11 /rVMOVUPS ymm2/m256, ymm1
+ * VEX.128.66.0F.WIG 10 /r VMOVUPD xmm1, xmm2/m128
+ * VEX.128.66.0F.WIG 11 /r VMOVUPD xmm2/m128, xmm1
+ * VEX.256.66.0F.WIG 10 /r VMOVUPD ymm1, ymm2/m256
+ * VEX.256.66.0F.WIG 11 /r VMOVUPD ymm2/m256, ymm1
+ * VEX.128.F3.0F.WIG 6F /r VMOVDQU xmm1,xmm2/m128
+ * VEX.128.F3.0F.WIG 7F /r VMOVDQU xmm2/m128,xmm1
+ * VEX.256.F3.0F.WIG 6F /r VMOVDQU ymm1,ymm2/m256
+ * VEX.256.F3.0F.WIG 7F /r VMOVDQU ymm2/m256,ymm1
+ * VEX.LIG.F3.0F.WIG 10 /r VMOVSS xmm1, xmm2, xmm3
+ * VEX.LIG.F3.0F.WIG 10 /r VMOVSS xmm1, m32
+ * VEX.LIG.F3.0F.WIG 11 /r VMOVSS xmm1, xmm2, xmm3
+ * VEX.LIG.F3.0F.WIG 11 /r VMOVSS m32, xmm1
+ * VEX.LIG.F2.0F.WIG 10 /r VMOVSD xmm1, xmm2, xmm3
+ * VEX.LIG.F2.0F.WIG 10 /r VMOVSD xmm1, m64
+ * VEX.LIG.F2.0F.WIG 11 /r VMOVSD xmm1, xmm2, xmm3
+ * VEX.LIG.F2.0F.WIG 11 /r VMOVSD m64, xmm1
+ * VEX.128.0F.WIG 12 /rVMOVHLPS xmm1, xmm2, xmm3
+ * VEX.128.0F.WIG 12 /rVMOVLPS xmm2, xmm1, m64
+ * VEX.128.0F.WIG 13 /rVMOVLPS m64, xmm1
+ * VEX.128.66.0F.WIG 12 /r VMOVLPD xmm2,xmm1,m64
+ * VEX.128.66.0F.WIG 13 /r VMOVLPD m64,xmm1
+ * VEX.128.0F.WIG 16 /rVMOVLHPS xmm1, xmm2, xmm3
+ * VEX.128.0F.WIG 16 /rVMOVHPS xmm2, xmm1, m64
+ * VEX.128.0F.WIG 17 /rVMOVHPS m64, xmm1
+ * VEX.128.66.0F.WIG 16 /r VMOVHPD xmm2, xmm1, m64
+ * VEX.128.66.0F.WIG 17 /r VMOVHPD m64, xmm1
+ * VEX.128.66.0F.W0 D7 /r  VPMOVMSKB r32, xmm1
+ * VEX.128.66.0F.W1 D7 /r  VPMOVMSKB r64, xmm1
+ * VEX.128.0F.W0 50 /r VMOVMSKPS r32, xmm2
+ * VEX.128.0F.W1 50 /r VMOVMSKPS r64, xmm2
+ * VEX.256.0F.W0 50 /r VMOVMSKPS r32, ymm2
+ * VEX.256.0F.W1 50 /r VMOVMSKPS r64, ymm2
+ * VEX.128.66.0F.W0 50 /r  VMOVMSKPD r32, xmm2
+ * VEX.128.66.0F.W1 50 /r  VMOVMSKPD r64, xmm2
+ * VEX.256.66.0F.W0 50 /r  VMOVMSKPD r32, ymm2
+ * VEX.256.66.0F.W1 50 /r  VMOVMSKPD r64, ymm2
+ * VEX.128.F2.0F.WIG F0 /r VLDDQU xmm1, m128
+ * VEX.256.F2.0F.WIG F0 /r VLDDQU ymm1, m256
+ * VEX.128.F3.0F.WIG 16 /r VMOVSHDUP xmm1, xmm2/m128
+ * VEX.256.F3.0F.WIG 16 /r VMOVSHDUP ymm1, ymm2/m256
+ * VEX.128.F3.0F.WIG 12 /r VMOVSLDUP xmm1, xmm2/m128
+ * VEX.256.F3.0F.WIG 12 /r VMOVSLDUP ymm1, ymm2/m256
+ * VEX.128.F2.0F.WIG 12 /r VMOVDDUP xmm1, xmm2/m64
+ * VEX.256.F2.0F.WIG 12 /r VMOVDDUP ymm1, ymm2/m256
+ * VEX.128.66.0F.WIG FC /r VPADDB xmm1, xmm2, xmm3/m128
+ * VEX.128.66.0F.WIG FD /r VPADDW xmm1, xmm2, xmm3/m128
+ * VEX.128.66.0F.WIG FE /r VPADDD xmm1, xmm2, xmm3/m128
+ * VEX.128.66.0F.WIG D4 /r VPADDQ xmm1, xmm2, xmm3/m128
+ * VEX.128.66.0F.WIG EC /r VPADDSB xmm1, xmm2, xmm3/m128
+ * VEX.128.66.0F.WIG ED /r VPADDSW xmm1, xmm2, xmm3/m128
+ * VEX.128.66.0F.WIG DC /r VPADDUSB xmm1,xmm2,xmm3/m128
+ * VEX.128.66.0F.WIG DD /r VPADDUSW xmm1,xmm2,xmm3/m128
+ * VEX

[Qemu-devel] [RFC PATCH v4 58/75] target/i386: introduce AES and PCLMULQDQ vector instructions to sse-opcode.inc.h

2019-08-21 Thread Jan Bobek
Add all the AES and PCLMULQDQ vector instruction entries to sse-opcode.inc.h.

Signed-off-by: Jan Bobek 
---
 target/i386/sse-opcode.inc.h | 34 ++
 1 file changed, 34 insertions(+)

diff --git a/target/i386/sse-opcode.inc.h b/target/i386/sse-opcode.inc.h
index f43436213e..1359508424 100644
--- a/target/i386/sse-opcode.inc.h
+++ b/target/i386/sse-opcode.inc.h
@@ -449,6 +449,26 @@
  * 66 0F 3A 61 /r imm8 PCMPESTRI xmm1, xmm2/m128, imm8
  * 66 0F 3A 62 /r imm8 PCMPISTRM xmm1, xmm2/m128, imm8
  * 66 0F 3A 63 /r imm8 PCMPISTRI xmm1, xmm2/m128, imm8
+ *
+ * AES Instructions
+ * -
+ * 66 0F 38 DE /r  AESDEC xmm1, xmm2/m128
+ * VEX.128.66.0F38.WIG DE /r   VAESDEC xmm1, xmm2, xmm3/m128
+ * 66 0F 38 DF /r  AESDECLAST xmm1, xmm2/m128
+ * VEX.128.66.0F38.WIG DF /r   VAESDECLAST xmm1, xmm2, xmm3/m128
+ * 66 0F 38 DC /r  AESENC xmm1, xmm2/m128
+ * VEX.128.66.0F38.WIG DC /r   VAESENC xmm1, xmm2, xmm3/m128
+ * 66 0F 38 DD /r  AESENCLAST xmm1, xmm2/m128
+ * VEX.128.66.0F38.WIG DD /r   VAESENCLAST xmm1, xmm2, xmm3/m128
+ * 66 0F 38 DB /r  AESIMC xmm1, xmm2/m128
+ * VEX.128.66.0F38.WIG DB /r   VAESIMC xmm1, xmm2/m128
+ * 66 0F 3A DF /r ib   AESKEYGENASSIST xmm1, xmm2/m128, imm8
+ * VEX.128.66.0F3A.WIG DF /r ibVAESKEYGENASSIST xmm1, xmm2/m128, imm8
+ *
+ * PCLMULQDQ Instructions
+ * ---
+ * 66 0F 3A 44 /r ib   PCLMULQDQ xmm1, xmm2/m128, imm8
+ * VEX.128.66.0F3A.WIG 44 /r ibVPCLMULQDQ xmm1, xmm2, xmm3/m128, imm8
  */
 
 OPCODE(movd, LEG(NP, 0F, 0, 0x6e), MMX, WR, Pq, Ed)
@@ -641,6 +661,20 @@ OPCODE(roundps, LEG(66, 0F3A, 0, 0x08), SSE4_1, WRR, Vdq, 
Wdq, Ib)
 OPCODE(roundpd, LEG(66, 0F3A, 0, 0x09), SSE4_1, WRR, Vdq, Wdq, Ib)
 OPCODE(roundss, LEG(66, 0F3A, 0, 0x0a), SSE4_1, WRR, Vd, Wd, Ib)
 OPCODE(roundsd, LEG(66, 0F3A, 0, 0x0b), SSE4_1, WRR, Vq, Wq, Ib)
+OPCODE(aesdec, LEG(66, 0F38, 0, 0xde), AES, WRR, Vdq, Vdq, Wdq)
+OPCODE(vaesdec, VEX(128, 66, 0F38, IG, 0xde), AES_AVX, WRR, Vdq, Hdq, Wdq)
+OPCODE(aesdeclast, LEG(66, 0F38, 0, 0xdf), AES, WRR, Vdq, Vdq, Wdq)
+OPCODE(vaesdeclast, VEX(128, 66, 0F38, IG, 0xdf), AES_AVX, WRR, Vdq, Hdq, Wdq)
+OPCODE(aesenc, LEG(66, 0F38, 0, 0xdc), AES, WRR, Vdq, Vdq, Wdq)
+OPCODE(vaesenc, VEX(128, 66, 0F38, IG, 0xdc), AES_AVX, WRR, Vdq, Hdq, Wdq)
+OPCODE(aesenclast, LEG(66, 0F38, 0, 0xdd), AES, WRR, Vdq, Vdq, Wdq)
+OPCODE(vaesenclast, VEX(128, 66, 0F38, IG, 0xdd), AES_AVX, WRR, Vdq, Hdq, Wdq)
+OPCODE(aesimc, LEG(66, 0F38, 0, 0xdb), AES, WR, Vdq, Wdq)
+OPCODE(vaesimc, VEX(128, 66, 0F38, IG, 0xdb), AES_AVX, WR, Vdq, Wdq)
+OPCODE(aeskeygenassist, LEG(66, 0F3A, 0, 0xdf), AES, WRR, Vdq, Wdq, Ib)
+OPCODE(vaeskeygenassist, VEX(128, 66, 0F3A, IG, 0xdf), AES_AVX, WRR, Vdq, Wdq, 
Ib)
+OPCODE(pclmulqdq, LEG(66, 0F3A, 0, 0x44), PCLMULQDQ, WRRR, Vdq, Vdq, Wdq, Ib)
+OPCODE(vpclmulqdq, VEX(128, 66, 0F3A, IG, 0x44), PCLMULQDQ_AVX, WRRR, Vdq, 
Hdq, Wdq, Ib)
 OPCODE(pcmpeqb, LEG(NP, 0F, 0, 0x74), MMX, WRR, Pq, Pq, Qq)
 OPCODE(pcmpeqb, LEG(66, 0F, 0, 0x74), SSE2, WRR, Vdq, Vdq, Wdq)
 OPCODE(pcmpeqw, LEG(NP, 0F, 0, 0x75), MMX, WRR, Pq, Pq, Qq)
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 68/75] target/i386: convert ps((l, r)l(w, d, q), ra(w, d)) to helpers to gvec style

2019-08-21 Thread Jan Bobek
Make these helpers suitable for use with tcg_gen_gvec_* functions.

Signed-off-by: Jan Bobek 
---
 target/i386/ops_sse.h| 357 +--
 target/i386/ops_sse_header.h |  30 ++-
 target/i386/translate.c  | 259 +++--
 3 files changed, 306 insertions(+), 340 deletions(-)

diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h
index aca6b50f23..168e581c0c 100644
--- a/target/i386/ops_sse.h
+++ b/target/i386/ops_sse.h
@@ -19,6 +19,7 @@
  */
 
 #include "crypto/aes.h"
+#include "tcg-gvec-desc.h"
 
 #if SHIFT == 0
 #define Reg MMXReg
@@ -38,199 +39,273 @@
 #define SUFFIX _xmm
 #endif
 
-void glue(helper_psrlw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
+static inline void glue(clear_high, SUFFIX)(Reg *d, intptr_t oprsz,
+intptr_t maxsz)
 {
-int shift;
+intptr_t i;
 
-if (s->Q(0) > 15) {
-d->Q(0) = 0;
-#if SHIFT == 1
-d->Q(1) = 0;
-#endif
-} else {
-shift = s->B(0);
-d->W(0) >>= shift;
-d->W(1) >>= shift;
-d->W(2) >>= shift;
-d->W(3) >>= shift;
-#if SHIFT == 1
-d->W(4) >>= shift;
-d->W(5) >>= shift;
-d->W(6) >>= shift;
-d->W(7) >>= shift;
-#endif
+assert(oprsz % sizeof(uint64_t) == 0);
+assert(maxsz % sizeof(uint64_t) == 0);
+
+if (oprsz < maxsz) {
+i = oprsz / sizeof(uint64_t);
+for (; i * sizeof(uint64_t) < maxsz; ++i) {
+d->Q(i) = 0;
+}
 }
 }
 
-void glue(helper_psraw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
+void glue(helper_psllw, SUFFIX)(Reg *d, Reg *a, Reg *b, uint32_t desc)
 {
-int shift;
+const uint64_t count = b->Q(0);
+const intptr_t oprsz = count > 15 ? 0 : simd_oprsz(desc);
+const intptr_t maxsz = simd_maxsz(desc);
 
-if (s->Q(0) > 15) {
-shift = 15;
-} else {
-shift = s->B(0);
+for (intptr_t i = 0; i * sizeof(uint16_t) < oprsz; ++i) {
+d->W(i) = a->W(i) << count;
 }
-d->W(0) = (int16_t)d->W(0) >> shift;
-d->W(1) = (int16_t)d->W(1) >> shift;
-d->W(2) = (int16_t)d->W(2) >> shift;
-d->W(3) = (int16_t)d->W(3) >> shift;
-#if SHIFT == 1
-d->W(4) = (int16_t)d->W(4) >> shift;
-d->W(5) = (int16_t)d->W(5) >> shift;
-d->W(6) = (int16_t)d->W(6) >> shift;
-d->W(7) = (int16_t)d->W(7) >> shift;
-#endif
+glue(clear_high, SUFFIX)(d, oprsz, maxsz);
 }
 
-void glue(helper_psllw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
+void glue(helper_pslld, SUFFIX)(Reg *d, Reg *a, Reg *b, uint32_t desc)
 {
-int shift;
+const uint64_t count = b->Q(0);
+const intptr_t oprsz = count > 31 ? 0 : simd_oprsz(desc);
+const intptr_t maxsz = simd_maxsz(desc);
 
-if (s->Q(0) > 15) {
-d->Q(0) = 0;
-#if SHIFT == 1
-d->Q(1) = 0;
-#endif
-} else {
-shift = s->B(0);
-d->W(0) <<= shift;
-d->W(1) <<= shift;
-d->W(2) <<= shift;
-d->W(3) <<= shift;
-#if SHIFT == 1
-d->W(4) <<= shift;
-d->W(5) <<= shift;
-d->W(6) <<= shift;
-d->W(7) <<= shift;
-#endif
+for (intptr_t i = 0; i * sizeof(uint32_t) < oprsz; ++i) {
+d->L(i) = a->L(i) << count;
 }
+glue(clear_high, SUFFIX)(d, oprsz, maxsz);
 }
 
-void glue(helper_psrld, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
+void glue(helper_psllq, SUFFIX)(Reg *d, Reg *a, Reg *b, uint32_t desc)
 {
-int shift;
+const uint64_t count = b->Q(0);
+const intptr_t oprsz = count > 63 ? 0 : simd_oprsz(desc);
+const intptr_t maxsz = simd_maxsz(desc);
 
-if (s->Q(0) > 31) {
-d->Q(0) = 0;
-#if SHIFT == 1
-d->Q(1) = 0;
-#endif
-} else {
-shift = s->B(0);
-d->L(0) >>= shift;
-d->L(1) >>= shift;
-#if SHIFT == 1
-d->L(2) >>= shift;
-d->L(3) >>= shift;
-#endif
+for (intptr_t i = 0; i * sizeof(uint64_t) < oprsz; ++i) {
+d->Q(i) = a->Q(i) << count;
 }
+glue(clear_high, SUFFIX)(d, oprsz, maxsz);
 }
 
-void glue(helper_psrad, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
+void glue(helper_psllwi, SUFFIX)(Reg *d, Reg *a, uint32_t desc)
 {
-int shift;
+const uint64_t count = simd_data(desc);
+const intptr_t oprsz = count > 15 ? 0 : simd_oprsz(desc);
+const intptr_t maxsz = simd_maxsz(desc);
 
-if (s->Q(0) > 31) {
-shift = 31;
-} else {
-shift = s->B(0);
+for (intptr_t i = 0; i * sizeof(uint16_t) < oprsz; ++i) {
+d->W(i) = a->W(i) << count;
 }
-d->L(0) = (int32_t)d->L

[Qemu-devel] [RFC PATCH v4 59/75] target/i386: introduce AVX translators

2019-08-21 Thread Jan Bobek
Use the translator macros to define translators required by AVX
instructions.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 48 +
 1 file changed, 48 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 14117c2993..9b9f0d4ed1 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -6708,10 +6708,12 @@ DEF_TRANSLATE_INSN2(Eq, Pq)
 DEF_TRANSLATE_INSN2(Eq, Vdq)
 DEF_TRANSLATE_INSN2(Gd, Nq)
 DEF_TRANSLATE_INSN2(Gd, Udq)
+DEF_TRANSLATE_INSN2(Gd, Uqq)
 DEF_TRANSLATE_INSN2(Gd, Wd)
 DEF_TRANSLATE_INSN2(Gd, Wq)
 DEF_TRANSLATE_INSN2(Gq, Nq)
 DEF_TRANSLATE_INSN2(Gq, Udq)
+DEF_TRANSLATE_INSN2(Gq, Uqq)
 DEF_TRANSLATE_INSN2(Gq, Wd)
 DEF_TRANSLATE_INSN2(Gq, Wq)
 DEF_TRANSLATE_INSN2(Md, Gd)
@@ -6720,6 +6722,7 @@ DEF_TRANSLATE_INSN2(Mq, Gq)
 DEF_TRANSLATE_INSN2(Mq, Pq)
 DEF_TRANSLATE_INSN2(Mq, Vdq)
 DEF_TRANSLATE_INSN2(Mq, Vq)
+DEF_TRANSLATE_INSN2(Mqq, Vqq)
 DEF_TRANSLATE_INSN2(Pq, Ed)
 DEF_TRANSLATE_INSN2(Pq, Eq)
 DEF_TRANSLATE_INSN2(Pq, Nq)
@@ -6735,6 +6738,7 @@ DEF_TRANSLATE_INSN2(Vd, Wd)
 DEF_TRANSLATE_INSN2(Vd, Wq)
 DEF_TRANSLATE_INSN2(Vdq, Ed)
 DEF_TRANSLATE_INSN2(Vdq, Eq)
+DEF_TRANSLATE_INSN2(Vdq, Md)
 DEF_TRANSLATE_INSN2(Vdq, Mdq)
 DEF_TRANSLATE_INSN2(Vdq, Nq)
 DEF_TRANSLATE_INSN2(Vdq, Qq)
@@ -6742,14 +6746,22 @@ DEF_TRANSLATE_INSN2(Vdq, Udq)
 DEF_TRANSLATE_INSN2(Vdq, Wd)
 DEF_TRANSLATE_INSN2(Vdq, Wdq)
 DEF_TRANSLATE_INSN2(Vdq, Wq)
+DEF_TRANSLATE_INSN2(Vdq, Wqq)
 DEF_TRANSLATE_INSN2(Vdq, Ww)
 DEF_TRANSLATE_INSN2(Vq, Ed)
 DEF_TRANSLATE_INSN2(Vq, Eq)
 DEF_TRANSLATE_INSN2(Vq, Wd)
 DEF_TRANSLATE_INSN2(Vq, Wq)
+DEF_TRANSLATE_INSN2(Vqq, Md)
+DEF_TRANSLATE_INSN2(Vqq, Mdq)
+DEF_TRANSLATE_INSN2(Vqq, Mq)
+DEF_TRANSLATE_INSN2(Vqq, Mqq)
+DEF_TRANSLATE_INSN2(Vqq, Wdq)
+DEF_TRANSLATE_INSN2(Vqq, Wqq)
 DEF_TRANSLATE_INSN2(Wd, Vd)
 DEF_TRANSLATE_INSN2(Wdq, Vdq)
 DEF_TRANSLATE_INSN2(Wq, Vq)
+DEF_TRANSLATE_INSN2(Wqq, Vqq)
 DEF_TRANSLATE_INSN2(modrm_mod, modrm)
 
 #define DEF_TRANSLATE_INSN3(opT1, opT2, opT3)   \
@@ -6796,6 +6808,9 @@ DEF_TRANSLATE_INSN3(Gd, Nq, Ib)
 DEF_TRANSLATE_INSN3(Gd, Udq, Ib)
 DEF_TRANSLATE_INSN3(Gq, Nq, Ib)
 DEF_TRANSLATE_INSN3(Gq, Udq, Ib)
+DEF_TRANSLATE_INSN3(Hdq, Udq, Ib)
+DEF_TRANSLATE_INSN3(Mdq, Hdq, Vdq)
+DEF_TRANSLATE_INSN3(Mqq, Hqq, Vqq)
 DEF_TRANSLATE_INSN3(Nq, Nq, Ib)
 DEF_TRANSLATE_INSN3(Pq, Pq, Qd)
 DEF_TRANSLATE_INSN3(Pq, Pq, Qq)
@@ -6803,17 +6818,34 @@ DEF_TRANSLATE_INSN3(Pq, Qq, Ib)
 DEF_TRANSLATE_INSN3(RdMb, Vdq, Ib)
 DEF_TRANSLATE_INSN3(RdMw, Vdq, Ib)
 DEF_TRANSLATE_INSN3(Udq, Udq, Ib)
+DEF_TRANSLATE_INSN3(Vd, Hd, Ed)
+DEF_TRANSLATE_INSN3(Vd, Hd, Eq)
+DEF_TRANSLATE_INSN3(Vd, Hd, Wd)
+DEF_TRANSLATE_INSN3(Vd, Hd, Wq)
 DEF_TRANSLATE_INSN3(Vd, Vd, Wd)
 DEF_TRANSLATE_INSN3(Vd, Wd, Ib)
+DEF_TRANSLATE_INSN3(Vdq, Hdq, Mdq)
+DEF_TRANSLATE_INSN3(Vdq, Hdq, Mq)
+DEF_TRANSLATE_INSN3(Vdq, Hdq, UdqMhq)
 DEF_TRANSLATE_INSN3(Vdq, Hdq, Wdq)
+DEF_TRANSLATE_INSN3(Vdq, Hq, Mq)
+DEF_TRANSLATE_INSN3(Vdq, Hq, Wq)
 DEF_TRANSLATE_INSN3(Vdq, Vdq, Mq)
 DEF_TRANSLATE_INSN3(Vdq, Vdq, UdqMhq)
 DEF_TRANSLATE_INSN3(Vdq, Vdq, Wdq)
 DEF_TRANSLATE_INSN3(Vdq, Vq, Mq)
 DEF_TRANSLATE_INSN3(Vdq, Vq, Wq)
 DEF_TRANSLATE_INSN3(Vdq, Wdq, Ib)
+DEF_TRANSLATE_INSN3(Vq, Hq, Ed)
+DEF_TRANSLATE_INSN3(Vq, Hq, Eq)
+DEF_TRANSLATE_INSN3(Vq, Hq, Wd)
+DEF_TRANSLATE_INSN3(Vq, Hq, Wq)
 DEF_TRANSLATE_INSN3(Vq, Vq, Wq)
 DEF_TRANSLATE_INSN3(Vq, Wq, Ib)
+DEF_TRANSLATE_INSN3(Vqq, Hqq, Mqq)
+DEF_TRANSLATE_INSN3(Vqq, Hqq, Wqq)
+DEF_TRANSLATE_INSN3(Vqq, Wqq, Ib)
+DEF_TRANSLATE_INSN3(Wdq, Vqq, Ib)
 
 #define DEF_TRANSLATE_INSN4(opT1, opT2, opT3, opT4) \
 static void translate_insn4(opT1, opT2, opT3, opT4)(\
@@ -6861,8 +6893,15 @@ DEF_TRANSLATE_INSN3(Vq, Wq, Ib)
 
 DEF_TRANSLATE_INSN4(Pq, Pq, Qq, Ib)
 DEF_TRANSLATE_INSN4(Pq, Pq, RdMw, Ib)
+DEF_TRANSLATE_INSN4(Vd, Hd, Wd, Ib)
 DEF_TRANSLATE_INSN4(Vd, Vd, Wd, Ib)
+DEF_TRANSLATE_INSN4(Vdq, Hdq, Ed, Ib)
+DEF_TRANSLATE_INSN4(Vdq, Hdq, Eq, Ib)
+DEF_TRANSLATE_INSN4(Vdq, Hdq, RdMb, Ib)
+DEF_TRANSLATE_INSN4(Vdq, Hdq, RdMw, Ib)
+DEF_TRANSLATE_INSN4(Vdq, Hdq, Wd, Ib)
 DEF_TRANSLATE_INSN4(Vdq, Hdq, Wdq, Ib)
+DEF_TRANSLATE_INSN4(Vdq, Hdq, Wdq, Ldq)
 DEF_TRANSLATE_INSN4(Vdq, Vdq, Ed, Ib)
 DEF_TRANSLATE_INSN4(Vdq, Vdq, Eq, Ib)
 DEF_TRANSLATE_INSN4(Vdq, Vdq, RdMb, Ib)
@@ -6871,7 +6910,11 @@ DEF_TRANSLATE_INSN4(Vdq, Vdq, Wd, Ib)
 DEF_TRANSLATE_INSN4(Vdq, Vdq, Wd, modrm_mod)
 DEF_TRANSLATE_INSN4(Vdq, Vdq, Wdq, Ib)
 DEF_TRANSLATE_INSN4(Vdq, Vdq, Wq, modrm_mod)
+DEF_TRANSLATE_INSN4(Vq, Hq, Wq, Ib)
 DEF_TRANSLATE_INSN4(Vq, Vq, Wq, Ib)
+DEF_TRANSLATE_INSN4(Vqq, Hqq, Wdq, Ib)
+DEF_TRANSLATE_INSN4(Vqq, Hqq, Wqq, Ib)
+DEF_TRANSLATE_INSN4(Vqq, Hqq, Wqq, Lqq)
 
 #define DEF_TRANSLATE_INSN5(opT1, opT2, opT3, opT4, opT5)   \
 static void translate_insn5(opT1, opT2, opT3, opT4, opT5)(  \
@@ -6924,6 +6967,11 @@ DEF_TRANSLATE_INSN4(Vq, Vq, Wq, Ib)
 }   \
 }
 
+DEF_TRANSLATE_INSN5(Vdq, Hdq

[Qemu-devel] [RFC PATCH v4 74/75] target/i386: convert pshuf(w, lw, hw, d), shuf(pd, ps) helpers to gvec style

2019-08-21 Thread Jan Bobek
Make these helpers suitable for use with tcg_gen_gvec_* functions.

Signed-off-by: Jan Bobek 
---
 target/i386/ops_sse.h| 141 ---
 target/i386/ops_sse_header.h |  12 +--
 target/i386/translate.c  |  34 -
 3 files changed, 119 insertions(+), 68 deletions(-)

diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h
index 8172324e34..2e50d91a25 100644
--- a/target/i386/ops_sse.h
+++ b/target/i386/ops_sse.h
@@ -551,70 +551,123 @@ void glue(helper_maskmov, SUFFIX)(CPUX86State *env, Reg 
*a, Reg *b,
 }
 
 #if SHIFT == 0
-void glue(helper_pshufw, SUFFIX)(Reg *d, Reg *s, int order)
+void glue(helper_pshufw, SUFFIX)(Reg *d, Reg *a, uint32_t desc)
 {
-Reg r;
+const intptr_t oprsz = simd_oprsz(desc);
+const intptr_t maxsz = simd_maxsz(desc);
+const uint8_t ctrl = simd_data(desc);
 
-r.W(0) = s->W(order & 3);
-r.W(1) = s->W((order >> 2) & 3);
-r.W(2) = s->W((order >> 4) & 3);
-r.W(3) = s->W((order >> 6) & 3);
-*d = r;
+for (intptr_t i = 0; 4 * i * sizeof(uint16_t) < oprsz; ++i) {
+const uint16_t t0 = a->W(4 * i + ((ctrl >> 0) & 3));
+const uint16_t t1 = a->W(4 * i + ((ctrl >> 2) & 3));
+const uint16_t t2 = a->W(4 * i + ((ctrl >> 4) & 3));
+const uint16_t t3 = a->W(4 * i + ((ctrl >> 6) & 3));
+
+d->W(4 * i + 0) = t0;
+d->W(4 * i + 1) = t1;
+d->W(4 * i + 2) = t2;
+d->W(4 * i + 3) = t3;
+}
+glue(clear_high, SUFFIX)(d, oprsz, maxsz);
 }
 #else
-void helper_shufps(Reg *d, Reg *s, int order)
+void glue(helper_pshuflw, SUFFIX)(Reg *d, Reg *a, uint32_t desc)
 {
-Reg r;
+const intptr_t oprsz = simd_oprsz(desc);
+const intptr_t maxsz = simd_maxsz(desc);
+const uint8_t ctrl = simd_data(desc);
 
-r.L(0) = d->L(order & 3);
-r.L(1) = d->L((order >> 2) & 3);
-r.L(2) = s->L((order >> 4) & 3);
-r.L(3) = s->L((order >> 6) & 3);
-*d = r;
+for (intptr_t i = 0; 8 * i * sizeof(uint16_t) < oprsz; ++i) {
+const uint16_t t0 = a->W(8 * i + ((ctrl >> 0) & 3));
+const uint16_t t1 = a->W(8 * i + ((ctrl >> 2) & 3));
+const uint16_t t2 = a->W(8 * i + ((ctrl >> 4) & 3));
+const uint16_t t3 = a->W(8 * i + ((ctrl >> 6) & 3));
+
+d->W(8 * i + 0) = t0;
+d->W(8 * i + 1) = t1;
+d->W(8 * i + 2) = t2;
+d->W(8 * i + 3) = t3;
+d->Q(2 * i + 1) = a->Q(2 * i + 1);
+}
+glue(clear_high, SUFFIX)(d, oprsz, maxsz);
 }
 
-void helper_shufpd(Reg *d, Reg *s, int order)
+void glue(helper_pshufhw, SUFFIX)(Reg *d, Reg *a, uint32_t desc)
 {
-Reg r;
+const intptr_t oprsz = simd_oprsz(desc);
+const intptr_t maxsz = simd_maxsz(desc);
+const uint8_t ctrl = simd_data(desc);
+
+for (intptr_t i = 0; 8 * i * sizeof(uint16_t) < oprsz; ++i) {
+const uint16_t t0 = a->W(8 * i + 4 + ((ctrl >> 0) & 3));
+const uint16_t t1 = a->W(8 * i + 4 + ((ctrl >> 2) & 3));
+const uint16_t t2 = a->W(8 * i + 4 + ((ctrl >> 4) & 3));
+const uint16_t t3 = a->W(8 * i + 4 + ((ctrl >> 6) & 3));
 
-r.Q(0) = d->Q(order & 1);
-r.Q(1) = s->Q((order >> 1) & 1);
-*d = r;
+d->Q(2 * i + 0) = a->Q(2 * i + 0);
+d->W(8 * i + 4) = t0;
+d->W(8 * i + 5) = t1;
+d->W(8 * i + 6) = t2;
+d->W(8 * i + 7) = t3;
+}
+glue(clear_high, SUFFIX)(d, oprsz, maxsz);
 }
 
-void glue(helper_pshufd, SUFFIX)(Reg *d, Reg *s, int order)
+void glue(helper_pshufd, SUFFIX)(Reg *d, Reg *a, uint32_t desc)
 {
-Reg r;
+const intptr_t oprsz = simd_oprsz(desc);
+const intptr_t maxsz = simd_maxsz(desc);
+const uint8_t ctrl = simd_data(desc);
+
+for (intptr_t i = 0; 4 * i * sizeof(uint32_t) < oprsz; ++i) {
+const uint32_t t0 = a->L(4 * i + ((ctrl >> 0) & 3));
+const uint32_t t1 = a->L(4 * i + ((ctrl >> 2) & 3));
+const uint32_t t2 = a->L(4 * i + ((ctrl >> 4) & 3));
+const uint32_t t3 = a->L(4 * i + ((ctrl >> 6) & 3));
+
+d->L(4 * i + 0) = t0;
+d->L(4 * i + 1) = t1;
+d->L(4 * i + 2) = t2;
+d->L(4 * i + 3) = t3;
 
-r.L(0) = s->L(order & 3);
-r.L(1) = s->L((order >> 2) & 3);
-r.L(2) = s->L((order >> 4) & 3);
-r.L(3) = s->L((order >> 6) & 3);
-*d = r;
+}
+glue(clear_high, SUFFIX)(d, oprsz, maxsz);
 }
 
-void glue(helper_pshuflw, SUFFIX)(Reg *d, Reg *s, int order)
+void glue(helper_shufps, SUFFIX)(Reg *d, Reg *a, Reg *b, uint32_t desc)
 {
-Reg r;
-
-r.W(0) = s->W(order & 3);
-r.W(1) = s->W((order 

[Qemu-devel] [RFC PATCH v4 43/75] target/i386: introduce SSE2 code generators

2019-08-21 Thread Jan Bobek
Introduce code generators required by SSE2 instructions.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 427 +++-
 1 file changed, 425 insertions(+), 2 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 43917edc76..3445b4cff1 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -5563,6 +5563,7 @@ INSNOP_LDST(xmm, Mhq)
 }
 
 GEN_INSN2(movq, Pq, Eq);/* forward declaration */
+GEN_INSN2(movq, Vdq, Eq);   /* forward declaration */
 GEN_INSN2(movd, Pq, Ed)
 {
 const insnop_arg_t(Eq) arg2_r64 = tcg_temp_new_i64();
@@ -5574,6 +5575,17 @@ GEN_INSN2(movd, Ed, Pq)
 {
 tcg_gen_ld_i32(arg1, cpu_env, arg2 + offsetof(MMXReg, MMX_L(0)));
 }
+GEN_INSN2(movd, Vdq, Ed)
+{
+const insnop_arg_t(Eq) arg2_r64 = tcg_temp_new_i64();
+tcg_gen_extu_i32_i64(arg2_r64, arg2);
+gen_insn2(movq, Vdq, Eq)(env, s, arg1, arg2_r64);
+tcg_temp_free_i64(arg2_r64);
+}
+GEN_INSN2(movd, Ed, Vdq)
+{
+tcg_gen_ld_i32(arg1, cpu_env, arg2 + offsetof(ZMMReg, ZMM_L(0)));
+}
 
 GEN_INSN2(movq, Pq, Eq)
 {
@@ -5583,13 +5595,45 @@ GEN_INSN2(movq, Eq, Pq)
 {
 tcg_gen_ld_i64(arg1, cpu_env, arg2 + offsetof(MMXReg, MMX_Q(0)));
 }
+GEN_INSN2(movq, Vdq, Eq)
+{
+const TCGv_i64 r64 = tcg_temp_new_i64();
+tcg_gen_st_i64(arg2, cpu_env, arg1 + offsetof(ZMMReg, ZMM_Q(0)));
+tcg_gen_movi_i64(r64, 0);
+tcg_gen_st_i64(r64, cpu_env, arg1 + offsetof(ZMMReg, ZMM_Q(1)));
+tcg_temp_free_i64(r64);
+}
+GEN_INSN2(movq, Eq, Vdq)
+{
+tcg_gen_ld_i64(arg1, cpu_env, arg2 + offsetof(ZMMReg, ZMM_Q(0)));
+}
 
 DEF_GEN_INSN2_GVEC(movq, Pq, Qq, mov, MM_OPRSZ, MM_MAXSZ, MO_64)
 DEF_GEN_INSN2_GVEC(movq, Qq, Pq, mov, MM_OPRSZ, MM_MAXSZ, MO_64)
+GEN_INSN2(movq, Vdq, Wq)
+{
+const TCGv_i64 r64 = tcg_temp_new_i64();
+tcg_gen_ld_i64(r64, cpu_env, arg2 + offsetof(ZMMReg, ZMM_Q(0)));
+gen_insn2(movq, Vdq, Eq)(env, s, arg1, r64);
+tcg_temp_free_i64(r64);
+}
+GEN_INSN2(movq, UdqMq, Vq)
+{
+gen_insn2(movq, Vdq, Wq)(env, s, arg1, arg2);
+}
+
 DEF_GEN_INSN2_GVEC(movaps, Vdq, Wdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
 DEF_GEN_INSN2_GVEC(movaps, Wdq, Vdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(movapd, Vdq, Wdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(movapd, Wdq, Vdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(movdqa, Vdq, Wdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(movdqa, Wdq, Vdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
 DEF_GEN_INSN2_GVEC(movups, Vdq, Wdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
 DEF_GEN_INSN2_GVEC(movups, Wdq, Vdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(movupd, Vdq, Wdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(movupd, Wdq, Vdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(movdqu, Vdq, Wdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(movdqu, Wdq, Vdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
 
 GEN_INSN4(movss, Vdq, Vdq, Wd, modrm_mod)
 {
@@ -5621,6 +5665,46 @@ GEN_INSN2(movss, Wd, Vd)
 gen_insn4(movss, Vdq, Vdq, Wd, modrm_mod)(env, s, arg1, arg1, arg2, 3);
 }
 
+GEN_INSN4(movsd, Vdq, Vdq, Wq, modrm_mod)
+{
+const TCGv_i64 r64 = tcg_temp_new_i64();
+tcg_gen_ld_i64(r64, cpu_env, arg3 + offsetof(ZMMReg, ZMM_Q(0)));
+tcg_gen_st_i64(r64, cpu_env, arg1 + offsetof(ZMMReg, ZMM_Q(0)));
+if (arg4 == 3) {
+/* merging movsd */
+if (arg1 != arg2) {
+tcg_gen_ld_i64(r64, cpu_env, arg2 + offsetof(ZMMReg, ZMM_Q(1)));
+tcg_gen_st_i64(r64, cpu_env, arg1 + offsetof(ZMMReg, ZMM_Q(1)));
+}
+} else {
+/* zero-extending movsd */
+tcg_gen_movi_i64(r64, 0);
+tcg_gen_st_i64(r64, cpu_env, arg1 + offsetof(ZMMReg, ZMM_Q(1)));
+}
+tcg_temp_free_i64(r64);
+}
+GEN_INSN2(movsd, Wq, Vq)
+{
+gen_insn4(movsd, Vdq, Vdq, Wq, modrm_mod)(env, s, arg1, arg1, arg2, 3);
+}
+
+GEN_INSN2(movq2dq, Vdq, Nq)
+{
+const insnop_arg_t(Vdq) dofs = offsetof(ZMMReg, ZMM_Q(0));
+const insnop_arg_t(Nq) aofs = offsetof(MMXReg, MMX_Q(0));
+gen_op_movq(s, arg1 + dofs, arg2 + aofs);
+
+const TCGv_i64 r64z = tcg_const_i64(0);
+tcg_gen_st_i64(r64z, cpu_env, arg1 + offsetof(ZMMReg, ZMM_Q(1)));
+tcg_temp_free_i64(r64z);
+}
+GEN_INSN2(movdq2q, Pq, Uq)
+{
+const insnop_arg_t(Pq) dofs = offsetof(MMXReg, MMX_Q(0));
+const insnop_arg_t(Uq) aofs = offsetof(ZMMReg, ZMM_Q(0));
+gen_op_movq(s, arg1 + dofs, arg2 + aofs);
+}
+
 GEN_INSN3(movhlps, Vdq, Vdq, UdqMhq)
 {
 const TCGv_i64 r64 = tcg_temp_new_i64();
@@ -5637,6 +5721,21 @@ GEN_INSN2(movlps, Mq, Vq)
 insnop_ldst(xmm, Mq)(env, s, 1, arg2, arg1);
 }
 
+GEN_INSN3(movlpd, Vdq, Vdq, Mq)
+{
+insnop_ldst(xmm, Mq)(env, s, 0, arg1, arg3);
+if (arg1 != arg2) {
+const TCGv_i64 r64 = tcg_temp_new_i64();
+tcg_gen_ld_i64(r64, cpu_env, arg2 + offsetof(ZMMReg, ZMM_Q(1)));
+tcg_gen_st_i64(r64, cpu_env, arg1 + offsetof(ZMMReg, ZMM_Q(1)));
+tcg_temp_free_i64(r64

[Qemu-devel] [RFC PATCH v4 55/75] target/i386: introduce SSE4.2 vector instructions to sse-opcode.inc.h

2019-08-21 Thread Jan Bobek
Add all the SSE4.2 vector instruction entries to sse-opcode.inc.h.

Signed-off-by: Jan Bobek 
---
 target/i386/sse-opcode.inc.h | 13 +
 1 file changed, 13 insertions(+)

diff --git a/target/i386/sse-opcode.inc.h b/target/i386/sse-opcode.inc.h
index 9682cce7ef..f43436213e 100644
--- a/target/i386/sse-opcode.inc.h
+++ b/target/i386/sse-opcode.inc.h
@@ -441,6 +441,14 @@
  * 66 0f 38 34 /r  PMOVZXWQ xmm1, xmm2/m32
  * 66 0f 38 35 /r  PMOVZXDQ xmm1, xmm2/m64
  * 66 0F 38 2A /r  MOVNTDQA xmm1, m128
+ *
+ * SSE4.2 Instructions
+ * 
+ * 66 0F 38 37 /r  PCMPGTQ xmm1,xmm2/m128
+ * 66 0F 3A 60 /r imm8 PCMPESTRM xmm1, xmm2/m128, imm8
+ * 66 0F 3A 61 /r imm8 PCMPESTRI xmm1, xmm2/m128, imm8
+ * 66 0F 3A 62 /r imm8 PCMPISTRM xmm1, xmm2/m128, imm8
+ * 66 0F 3A 63 /r imm8 PCMPISTRI xmm1, xmm2/m128, imm8
  */
 
 OPCODE(movd, LEG(NP, 0F, 0, 0x6e), MMX, WR, Pq, Ed)
@@ -646,6 +654,11 @@ OPCODE(pcmpgtw, LEG(NP, 0F, 0, 0x65), MMX, WRR, Pq, Pq, Qq)
 OPCODE(pcmpgtw, LEG(66, 0F, 0, 0x65), SSE2, WRR, Vdq, Vdq, Wdq)
 OPCODE(pcmpgtd, LEG(NP, 0F, 0, 0x66), MMX, WRR, Pq, Pq, Qq)
 OPCODE(pcmpgtd, LEG(66, 0F, 0, 0x66), SSE2, WRR, Vdq, Vdq, Wdq)
+OPCODE(pcmpgtq, LEG(66, 0F38, 0, 0x37), SSE4_2, WRR, Vdq, Vdq, Wdq)
+OPCODE(pcmpestrm, LEG(66, 0F3A, 0, 0x60), SSE4_2, RRR, Vdq, Wdq, Ib)
+OPCODE(pcmpestri, LEG(66, 0F3A, 0, 0x61), SSE4_2, RRR, Vdq, Wdq, Ib)
+OPCODE(pcmpistrm, LEG(66, 0F3A, 0, 0x62), SSE4_2, RRR, Vdq, Wdq, Ib)
+OPCODE(pcmpistri, LEG(66, 0F3A, 0, 0x63), SSE4_2, RRR, Vdq, Wdq, Ib)
 OPCODE(ptest, LEG(66, 0F38, 0, 0x17), SSE4_1, RR, Vdq, Wdq)
 OPCODE(cmpps, LEG(NP, 0F, 0, 0xc2), SSE, WRRR, Vdq, Vdq, Wdq, Ib)
 OPCODE(cmppd, LEG(66, 0F, 0, 0xc2), SSE2, WRRR, Vdq, Vdq, Wdq, Ib)
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 70/75] target/i386: convert pavgb/pavgw helpers to gvec style

2019-08-21 Thread Jan Bobek
Make these helpers suitable for use with tcg_gen_gvec_* functions.

Signed-off-by: Jan Bobek 
---
 target/i386/ops_sse.h| 33 +
 target/i386/ops_sse_header.h |  7 +--
 target/i386/translate.c  | 20 +---
 3 files changed, 43 insertions(+), 17 deletions(-)

diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h
index 6ec116573b..1661bd7c64 100644
--- a/target/i386/ops_sse.h
+++ b/target/i386/ops_sse.h
@@ -413,8 +413,6 @@ static inline int satsw(int x)
 }
 
 #define FMULHRW(a, b) (((int16_t)(a) * (int16_t)(b) + 0x8000) >> 16)
-
-#define FAVG(a, b) (((a) + (b) + 1) >> 1)
 #endif
 
 void glue(helper_pmullw, SUFFIX)(Reg *d, Reg *a, Reg *b, uint32_t desc)
@@ -457,8 +455,35 @@ void glue(helper_pmulhw, SUFFIX)(Reg *d, Reg *a, Reg *b, 
uint32_t desc)
 glue(clear_high, SUFFIX)(d, oprsz, maxsz);
 }
 
-SSE_HELPER_B(helper_pavgb, FAVG)
-SSE_HELPER_W(helper_pavgw, FAVG)
+void glue(helper_pavgb, SUFFIX)(Reg *d, Reg *a, Reg *b, uint32_t desc)
+{
+const intptr_t oprsz = simd_oprsz(desc);
+const intptr_t maxsz = simd_maxsz(desc);
+
+for (intptr_t i = 0; i * sizeof(uint8_t) < oprsz; ++i) {
+d->B(i) = (a->B(i) + b->B(i) + 1) >> 1;
+}
+glue(clear_high, SUFFIX)(d, oprsz, maxsz);
+}
+
+#if SHIFT == 0
+void glue(helper_pavgusb, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
+{
+const uint32_t desc = simd_desc(sizeof(Reg), sizeof(Reg), 0);
+glue(helper_pavgb, SUFFIX)(d, s, s, desc);
+}
+#endif
+
+void glue(helper_pavgw, SUFFIX)(Reg *d, Reg *a, Reg *b, uint32_t desc)
+{
+const intptr_t oprsz = simd_oprsz(desc);
+const intptr_t maxsz = simd_maxsz(desc);
+
+for (intptr_t i = 0; i * sizeof(uint16_t) < oprsz; ++i) {
+d->W(i) = (a->W(i) + b->W(i) + 1) >> 1;
+}
+glue(clear_high, SUFFIX)(d, oprsz, maxsz);
+}
 
 void glue(helper_pmuludq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
 {
diff --git a/target/i386/ops_sse_header.h b/target/i386/ops_sse_header.h
index 7e6411fc82..b5e8aae897 100644
--- a/target/i386/ops_sse_header.h
+++ b/target/i386/ops_sse_header.h
@@ -65,8 +65,11 @@ DEF_HELPER_3(glue(pmulhrw, SUFFIX), void, env, Reg, Reg)
 DEF_HELPER_4(glue(pmulhuw, SUFFIX), void, Reg, Reg, Reg, i32)
 DEF_HELPER_4(glue(pmulhw, SUFFIX), void, Reg, Reg, Reg, i32)
 
-DEF_HELPER_3(glue(pavgb, SUFFIX), void, env, Reg, Reg)
-DEF_HELPER_3(glue(pavgw, SUFFIX), void, env, Reg, Reg)
+DEF_HELPER_4(glue(pavgb, SUFFIX), void, Reg, Reg, Reg, i32)
+#if SHIFT == 0
+DEF_HELPER_3(glue(pavgusb, SUFFIX), void, env, Reg, Reg)
+#endif
+DEF_HELPER_4(glue(pavgw, SUFFIX), void, Reg, Reg, Reg, i32)
 
 DEF_HELPER_3(glue(pmuludq, SUFFIX), void, env, Reg, Reg)
 DEF_HELPER_3(glue(pmaddwd, SUFFIX), void, env, Reg, Reg)
diff --git a/target/i386/translate.c b/target/i386/translate.c
index 79f8c1ddac..77b2e18f34 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -2803,8 +2803,6 @@ static const SSEFunc_0_epp sse_op_table1[256][4] = {
 [0xd0] = { NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps },
 [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
 [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
-[0xe0] = MMX_OP2(pavgb),
-[0xe3] = MMX_OP2(pavgw),
 [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, 
gen_helper_cvtpd2dq },
 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL },  /* movntq, movntq */
 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
@@ -2878,7 +2876,7 @@ static const SSEFunc_0_epp sse_op_table5[256] = {
 [0xb6] = gen_helper_movq, /* pfrcpit2 */
 [0xb7] = gen_helper_pmulhrw_mmx,
 [0xbb] = gen_helper_pswapd,
-[0xbf] = gen_helper_pavgb_mmx /* pavgusb */
+[0xbf] = gen_helper_pavgusb_mmx
 };
 
 struct SSEOpHelper_epp {
@@ -6252,14 +6250,14 @@ DEF_GEN_INSN3_HELPER_EPP(maxss, maxss, Vd, Vd, Wd)
 DEF_GEN_INSN3_HELPER_EPP(vmaxss, maxss, Vd, Hd, Wd)
 DEF_GEN_INSN3_HELPER_EPP(maxsd, maxsd, Vq, Vq, Wq)
 DEF_GEN_INSN3_HELPER_EPP(vmaxsd, maxsd, Vq, Hq, Wq)
-DEF_GEN_INSN3_HELPER_EPP(pavgb, pavgb_mmx, Pq, Pq, Qq)
-DEF_GEN_INSN3_HELPER_EPP(pavgb, pavgb_xmm, Vdq, Vdq, Wdq)
-DEF_GEN_INSN3_HELPER_EPP(vpavgb, pavgb_xmm, Vdq, Hdq, Wdq)
-DEF_GEN_INSN3_HELPER_EPP(vpavgb, pavgb_xmm, Vqq, Hqq, Wqq)
-DEF_GEN_INSN3_HELPER_EPP(pavgw, pavgw_mmx, Pq, Pq, Qq)
-DEF_GEN_INSN3_HELPER_EPP(pavgw, pavgw_xmm, Vdq, Vdq, Wdq)
-DEF_GEN_INSN3_HELPER_EPP(vpavgw, pavgw_xmm, Vdq, Hdq, Wdq)
-DEF_GEN_INSN3_HELPER_EPP(vpavgw, pavgw_xmm, Vqq, Hqq, Wqq)
+DEF_GEN_INSN3_GVEC(pavgb, Pq, Pq, Qq, 3_ool, MM_OPRSZ, MM_MAXSZ, pavgb_mmx)
+DEF_GEN_INSN3_GVEC(pavgb, Vdq, Vdq, Wdq, 3_ool, XMM_OPRSZ, XMM_MAXSZ, 
pavgb_xmm)
+DEF_GEN_INSN3_GVEC(vpavgb, Vdq, Hdq, Wdq, 3_ool, XMM_OPRSZ, XMM_MAXSZ, 
pavgb_xmm)
+DEF_GEN_INSN3_GVEC(vpavgb, Vqq, Hqq, Wqq, 3_ool, XMM_OPRSZ, XMM_MAXSZ, 
pavgb_xmm)
+DEF_GEN_INSN3_GVEC(pavgw, Pq, Pq, Qq, 3_ool, MM_OPRSZ, MM_MAXSZ, pavgw_mmx)
+DEF_GEN_INSN3_GVEC(pavgw, Vdq, Vdq, Wdq, 3_ool, XMM_OPRSZ, XMM_MAXSZ, 
pavgw_xmm)
+DEF_GEN_INSN3_GVEC(vp

[Qemu-devel] [RFC PATCH v4 69/75] target/i386: convert pmullw/pmulhw/pmulhuw helpers to gvec style

2019-08-21 Thread Jan Bobek
Make these helpers suitable for use with tcg_gen_gvec_* functions.

Signed-off-by: Jan Bobek 
---
 target/i386/ops_sse.h| 42 ++--
 target/i386/ops_sse_header.h |  6 +++---
 target/i386/translate.c  | 27 +++
 3 files changed, 51 insertions(+), 24 deletions(-)

diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h
index 168e581c0c..6ec116573b 100644
--- a/target/i386/ops_sse.h
+++ b/target/i386/ops_sse.h
@@ -412,20 +412,50 @@ static inline int satsw(int x)
 }
 }
 
-#define FMULLW(a, b) ((a) * (b))
 #define FMULHRW(a, b) (((int16_t)(a) * (int16_t)(b) + 0x8000) >> 16)
-#define FMULHUW(a, b) ((a) * (b) >> 16)
-#define FMULHW(a, b) ((int16_t)(a) * (int16_t)(b) >> 16)
 
 #define FAVG(a, b) (((a) + (b) + 1) >> 1)
 #endif
 
-SSE_HELPER_W(helper_pmullw, FMULLW)
+void glue(helper_pmullw, SUFFIX)(Reg *d, Reg *a, Reg *b, uint32_t desc)
+{
+const intptr_t oprsz = simd_oprsz(desc);
+const intptr_t maxsz = simd_maxsz(desc);
+
+for (intptr_t i = 0; i * sizeof(uint16_t) < oprsz; ++i) {
+const uint32_t t = (uint32_t)a->W(i) * (uint32_t)b->W(i);
+d->W(i) = t;
+}
+glue(clear_high, SUFFIX)(d, oprsz, maxsz);
+}
+
 #if SHIFT == 0
 SSE_HELPER_W(helper_pmulhrw, FMULHRW)
 #endif
-SSE_HELPER_W(helper_pmulhuw, FMULHUW)
-SSE_HELPER_W(helper_pmulhw, FMULHW)
+
+void glue(helper_pmulhuw, SUFFIX)(Reg *d, Reg *a, Reg *b, uint32_t desc)
+{
+const intptr_t oprsz = simd_oprsz(desc);
+const intptr_t maxsz = simd_maxsz(desc);
+
+for (intptr_t i = 0; i * sizeof(uint16_t) < oprsz; ++i) {
+const uint32_t t = (uint32_t)a->W(i) * (uint32_t)b->W(i);
+d->W(i) = t >> 16;
+}
+glue(clear_high, SUFFIX)(d, oprsz, maxsz);
+}
+
+void glue(helper_pmulhw, SUFFIX)(Reg *d, Reg *a, Reg *b, uint32_t desc)
+{
+const intptr_t oprsz = simd_oprsz(desc);
+const intptr_t maxsz = simd_maxsz(desc);
+
+for (intptr_t i = 0; i * sizeof(uint16_t) < oprsz; ++i) {
+const int32_t t = (int32_t)a->W(i) * (int32_t)b->W(i);
+d->W(i) = t >> 16;
+}
+glue(clear_high, SUFFIX)(d, oprsz, maxsz);
+}
 
 SSE_HELPER_B(helper_pavgb, FAVG)
 SSE_HELPER_W(helper_pavgw, FAVG)
diff --git a/target/i386/ops_sse_header.h b/target/i386/ops_sse_header.h
index 724692a689..7e6411fc82 100644
--- a/target/i386/ops_sse_header.h
+++ b/target/i386/ops_sse_header.h
@@ -58,12 +58,12 @@ DEF_HELPER_3(glue(pslldqi, SUFFIX), void, Reg, Reg, i32)
 DEF_HELPER_3(glue(psrldqi, SUFFIX), void, Reg, Reg, i32)
 #endif
 
-DEF_HELPER_3(glue(pmullw, SUFFIX), void, env, Reg, Reg)
+DEF_HELPER_4(glue(pmullw, SUFFIX), void, Reg, Reg, Reg, i32)
 #if SHIFT == 0
 DEF_HELPER_3(glue(pmulhrw, SUFFIX), void, env, Reg, Reg)
 #endif
-DEF_HELPER_3(glue(pmulhuw, SUFFIX), void, env, Reg, Reg)
-DEF_HELPER_3(glue(pmulhw, SUFFIX), void, env, Reg, Reg)
+DEF_HELPER_4(glue(pmulhuw, SUFFIX), void, Reg, Reg, Reg, i32)
+DEF_HELPER_4(glue(pmulhw, SUFFIX), void, Reg, Reg, Reg, i32)
 
 DEF_HELPER_3(glue(pavgb, SUFFIX), void, env, Reg, Reg)
 DEF_HELPER_3(glue(pavgw, SUFFIX), void, env, Reg, Reg)
diff --git a/target/i386/translate.c b/target/i386/translate.c
index 03f7c6e450..79f8c1ddac 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -2801,13 +2801,10 @@ static const SSEFunc_0_epp sse_op_table1[256][4] = {
 [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */
 [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */
 [0xd0] = { NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps },
-[0xd5] = MMX_OP2(pmullw),
 [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL },
 [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */
 [0xe0] = MMX_OP2(pavgb),
 [0xe3] = MMX_OP2(pavgw),
-[0xe4] = MMX_OP2(pmulhuw),
-[0xe5] = MMX_OP2(pmulhw),
 [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, 
gen_helper_cvtpd2dq },
 [0xe7] = { SSE_SPECIAL , SSE_SPECIAL },  /* movntq, movntq */
 [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */
@@ -6116,21 +6113,21 @@ DEF_GEN_INSN3_HELPER_EPP(addsubpd, addsubpd, Vdq, Vdq, 
Wdq)
 DEF_GEN_INSN3_HELPER_EPP(vaddsubpd, addsubpd, Vdq, Hdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(vaddsubpd, addsubpd, Vqq, Hqq, Wqq)
 
-DEF_GEN_INSN3_HELPER_EPP(pmullw, pmullw_mmx, Pq, Pq, Qq)
-DEF_GEN_INSN3_HELPER_EPP(pmullw, pmullw_xmm, Vdq, Vdq, Wdq)
-DEF_GEN_INSN3_HELPER_EPP(vpmullw, pmullw_xmm, Vdq, Hdq, Wdq)
-DEF_GEN_INSN3_HELPER_EPP(vpmullw, pmullw_xmm, Vqq, Hqq, Wqq)
+DEF_GEN_INSN3_GVEC(pmullw, Pq, Pq, Qq, 3_ool, MM_OPRSZ, MM_MAXSZ, pmullw_mmx)
+DEF_GEN_INSN3_GVEC(pmullw, Vdq, Vdq, Wdq, 3_ool, XMM_OPRSZ, XMM_MAXSZ, 
pmullw_xmm)
+DEF_GEN_INSN3_GVEC(vpmullw, Vdq, Hdq, Wdq, 3_ool, XMM_OPRSZ, XMM_MAXSZ, 
pmullw_xmm)
+DEF_GEN_INSN3_GVEC(vpmullw, Vqq, Hqq, Wqq, 3_ool, XMM_OPRSZ, XMM_MAXSZ, 
pmullw_xmm)
 DEF_GEN_INSN3_HELPER_EPP(pmulld, pmulld_xmm, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(vpmulld, pmulld_xmm, Vdq, Hdq, Wdq)
 DEF_GEN_INSN3_

[Qemu-devel] [RFC PATCH v4 60/75] target/i386: introduce AVX code generators

2019-08-21 Thread Jan Bobek
Introduce code generators required by AVX instructions.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 954 
 1 file changed, 954 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 9b9f0d4ed1..50eab9181c 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -5586,6 +5586,14 @@ GEN_INSN2(movd, Ed, Vdq)
 {
 tcg_gen_ld_i32(arg1, cpu_env, arg2 + offsetof(ZMMReg, ZMM_L(0)));
 }
+GEN_INSN2(vmovd, Vdq, Ed)
+{
+gen_insn2(movd, Vdq, Ed)(env, s, arg1, arg2);
+}
+GEN_INSN2(vmovd, Ed, Vdq)
+{
+gen_insn2(movd, Ed, Vdq)(env, s, arg1, arg2);
+}
 
 GEN_INSN2(movq, Pq, Eq)
 {
@@ -5607,6 +5615,14 @@ GEN_INSN2(movq, Eq, Vdq)
 {
 tcg_gen_ld_i64(arg1, cpu_env, arg2 + offsetof(ZMMReg, ZMM_Q(0)));
 }
+GEN_INSN2(vmovq, Vdq, Eq)
+{
+gen_insn2(movq, Vdq, Eq)(env, s, arg1, arg2);
+}
+GEN_INSN2(vmovq, Eq, Vdq)
+{
+gen_insn2(movq, Eq, Vdq)(env, s, arg1, arg2);
+}
 
 DEF_GEN_INSN2_GVEC(movq, Pq, Qq, mov, MM_OPRSZ, MM_MAXSZ, MO_64)
 DEF_GEN_INSN2_GVEC(movq, Qq, Pq, mov, MM_OPRSZ, MM_MAXSZ, MO_64)
@@ -5621,19 +5637,51 @@ GEN_INSN2(movq, UdqMq, Vq)
 {
 gen_insn2(movq, Vdq, Wq)(env, s, arg1, arg2);
 }
+GEN_INSN2(vmovq, Vdq, Wq)
+{
+gen_insn2(movq, Vdq, Wq)(env, s, arg1, arg2);
+}
+GEN_INSN2(vmovq, UdqMq, Vq)
+{
+gen_insn2(movq, UdqMq, Vq)(env, s, arg1, arg2);
+}
 
 DEF_GEN_INSN2_GVEC(movaps, Vdq, Wdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
 DEF_GEN_INSN2_GVEC(movaps, Wdq, Vdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(vmovaps, Vdq, Wdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(vmovaps, Wdq, Vdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(vmovaps, Vqq, Wqq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(vmovaps, Wqq, Vqq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
 DEF_GEN_INSN2_GVEC(movapd, Vdq, Wdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
 DEF_GEN_INSN2_GVEC(movapd, Wdq, Vdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(vmovapd, Vdq, Wdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(vmovapd, Wdq, Vdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(vmovapd, Vqq, Wqq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(vmovapd, Wqq, Vqq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
 DEF_GEN_INSN2_GVEC(movdqa, Vdq, Wdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
 DEF_GEN_INSN2_GVEC(movdqa, Wdq, Vdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(vmovdqa, Vdq, Wdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(vmovdqa, Wdq, Vdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(vmovdqa, Vqq, Wqq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(vmovdqa, Wqq, Vqq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
 DEF_GEN_INSN2_GVEC(movups, Vdq, Wdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
 DEF_GEN_INSN2_GVEC(movups, Wdq, Vdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(vmovups, Vdq, Wdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(vmovups, Wdq, Vdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(vmovups, Vqq, Wqq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(vmovups, Wqq, Vqq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
 DEF_GEN_INSN2_GVEC(movupd, Vdq, Wdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
 DEF_GEN_INSN2_GVEC(movupd, Wdq, Vdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(vmovupd, Vdq, Wdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(vmovupd, Wdq, Vdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(vmovupd, Vqq, Wqq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(vmovupd, Wqq, Vqq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
 DEF_GEN_INSN2_GVEC(movdqu, Vdq, Wdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
 DEF_GEN_INSN2_GVEC(movdqu, Wdq, Vdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(vmovdqu, Vdq, Wdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(vmovdqu, Wdq, Vdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(vmovdqu, Vqq, Wqq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(vmovdqu, Wqq, Vqq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
 
 GEN_INSN4(movss, Vdq, Vdq, Wd, modrm_mod)
 {
@@ -5664,6 +5712,24 @@ GEN_INSN2(movss, Wd, Vd)
 {
 gen_insn4(movss, Vdq, Vdq, Wd, modrm_mod)(env, s, arg1, arg1, arg2, 3);
 }
+GEN_INSN5(vmovss, Vdq, Hdq, Wd, modrm_mod, vex_v)
+{
+if (arg4 == 3 || arg5 == 0) {
+gen_insn4(movss, Vdq, Vdq, Wd, modrm_mod)(env, s, arg1,
+  arg2, arg3, arg4);
+} else {
+gen_unknown_opcode(env, s);
+}
+}
+GEN_INSN5(vmovss, Wdq, Hdq, Vd, modrm_mod, vex_v)
+{
+if (arg4 == 3 || arg5 == 0) {
+gen_insn4(movss, Vdq, Vdq, Wd, modrm_mod)(env, s, arg1,
+  arg2, arg3, 3);
+} else {
+gen_unknown_opcode(env, s);
+}
+}
 
 GEN_INSN4(movsd, Vdq, Vdq, Wq, modrm_mod)
 {
@@ -5687,6 +5753,24 @@ GEN_INSN2(movsd, Wq, Vq)
 {
 gen_insn4(movsd, Vdq, Vdq, Wq, modrm_mod)(env, s, arg1, arg1, arg2, 3);
 }
+GEN_INSN5(vmovsd, Vdq, Hdq, Wq, modrm_mod, vex_v)
+{
+if (arg4

[Qemu-devel] [RFC PATCH v4 48/75] target/i386: introduce SSSE3 translators

2019-08-21 Thread Jan Bobek
Use the translator macros to define translators required by SSSE3
instructions.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index d449a64464..25d3b969b1 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -6695,6 +6695,7 @@ DEF_TRANSLATE_INSN3(Vq, Vq, Wq)
 }   \
 }
 
+DEF_TRANSLATE_INSN4(Pq, Pq, Qq, Ib)
 DEF_TRANSLATE_INSN4(Pq, Pq, RdMw, Ib)
 DEF_TRANSLATE_INSN4(Vd, Vd, Wd, Ib)
 DEF_TRANSLATE_INSN4(Vdq, Vdq, RdMw, Ib)
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 65/75] target/i386: remove obsoleted helpers

2019-08-21 Thread Jan Bobek
A number of helpers have been obsoleted by the use of tcg_gen_gvec_*
functions; remove all of them.

Signed-off-by: Jan Bobek 
---
 target/i386/ops_sse.h| 65 
 target/i386/ops_sse_header.h | 39 --
 target/i386/translate.c  | 38 -
 3 files changed, 142 deletions(-)

diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h
index ec1ec745d0..aca6b50f23 100644
--- a/target/i386/ops_sse.h
+++ b/target/i386/ops_sse.h
@@ -337,32 +337,6 @@ static inline int satsw(int x)
 }
 }
 
-#define FADD(a, b) ((a) + (b))
-#define FADDUB(a, b) satub((a) + (b))
-#define FADDUW(a, b) satuw((a) + (b))
-#define FADDSB(a, b) satsb((int8_t)(a) + (int8_t)(b))
-#define FADDSW(a, b) satsw((int16_t)(a) + (int16_t)(b))
-
-#define FSUB(a, b) ((a) - (b))
-#define FSUBUB(a, b) satub((a) - (b))
-#define FSUBUW(a, b) satuw((a) - (b))
-#define FSUBSB(a, b) satsb((int8_t)(a) - (int8_t)(b))
-#define FSUBSW(a, b) satsw((int16_t)(a) - (int16_t)(b))
-#define FMINUB(a, b) ((a) < (b)) ? (a) : (b)
-#define FMINSW(a, b) ((int16_t)(a) < (int16_t)(b)) ? (a) : (b)
-#define FMAXUB(a, b) ((a) > (b)) ? (a) : (b)
-#define FMAXSW(a, b) ((int16_t)(a) > (int16_t)(b)) ? (a) : (b)
-
-#define FAND(a, b) ((a) & (b))
-#define FANDN(a, b) ((~(a)) & (b))
-#define FOR(a, b) ((a) | (b))
-#define FXOR(a, b) ((a) ^ (b))
-
-#define FCMPGTB(a, b) ((int8_t)(a) > (int8_t)(b) ? -1 : 0)
-#define FCMPGTW(a, b) ((int16_t)(a) > (int16_t)(b) ? -1 : 0)
-#define FCMPGTL(a, b) ((int32_t)(a) > (int32_t)(b) ? -1 : 0)
-#define FCMPEQ(a, b) ((a) == (b) ? -1 : 0)
-
 #define FMULLW(a, b) ((a) * (b))
 #define FMULHRW(a, b) (((int16_t)(a) * (int16_t)(b) + 0x8000) >> 16)
 #define FMULHUW(a, b) ((a) * (b) >> 16)
@@ -371,45 +345,6 @@ static inline int satsw(int x)
 #define FAVG(a, b) (((a) + (b) + 1) >> 1)
 #endif
 
-SSE_HELPER_B(helper_paddb, FADD)
-SSE_HELPER_W(helper_paddw, FADD)
-SSE_HELPER_L(helper_paddl, FADD)
-SSE_HELPER_Q(helper_paddq, FADD)
-
-SSE_HELPER_B(helper_psubb, FSUB)
-SSE_HELPER_W(helper_psubw, FSUB)
-SSE_HELPER_L(helper_psubl, FSUB)
-SSE_HELPER_Q(helper_psubq, FSUB)
-
-SSE_HELPER_B(helper_paddusb, FADDUB)
-SSE_HELPER_B(helper_paddsb, FADDSB)
-SSE_HELPER_B(helper_psubusb, FSUBUB)
-SSE_HELPER_B(helper_psubsb, FSUBSB)
-
-SSE_HELPER_W(helper_paddusw, FADDUW)
-SSE_HELPER_W(helper_paddsw, FADDSW)
-SSE_HELPER_W(helper_psubusw, FSUBUW)
-SSE_HELPER_W(helper_psubsw, FSUBSW)
-
-SSE_HELPER_B(helper_pminub, FMINUB)
-SSE_HELPER_B(helper_pmaxub, FMAXUB)
-
-SSE_HELPER_W(helper_pminsw, FMINSW)
-SSE_HELPER_W(helper_pmaxsw, FMAXSW)
-
-SSE_HELPER_Q(helper_pand, FAND)
-SSE_HELPER_Q(helper_pandn, FANDN)
-SSE_HELPER_Q(helper_por, FOR)
-SSE_HELPER_Q(helper_pxor, FXOR)
-
-SSE_HELPER_B(helper_pcmpgtb, FCMPGTB)
-SSE_HELPER_W(helper_pcmpgtw, FCMPGTW)
-SSE_HELPER_L(helper_pcmpgtl, FCMPGTL)
-
-SSE_HELPER_B(helper_pcmpeqb, FCMPEQ)
-SSE_HELPER_W(helper_pcmpeqw, FCMPEQ)
-SSE_HELPER_L(helper_pcmpeql, FCMPEQ)
-
 SSE_HELPER_W(helper_pmullw, FMULLW)
 #if SHIFT == 0
 SSE_HELPER_W(helper_pmulhrw, FMULHRW)
diff --git a/target/i386/ops_sse_header.h b/target/i386/ops_sse_header.h
index 094aafc573..d8e33dff6b 100644
--- a/target/i386/ops_sse_header.h
+++ b/target/i386/ops_sse_header.h
@@ -60,45 +60,6 @@ DEF_HELPER_3(glue(pslldq, SUFFIX), void, env, Reg, Reg)
 #define SSE_HELPER_Q(name, F)\
 DEF_HELPER_3(glue(name, SUFFIX), void, env, Reg, Reg)
 
-SSE_HELPER_B(paddb, FADD)
-SSE_HELPER_W(paddw, FADD)
-SSE_HELPER_L(paddl, FADD)
-SSE_HELPER_Q(paddq, FADD)
-
-SSE_HELPER_B(psubb, FSUB)
-SSE_HELPER_W(psubw, FSUB)
-SSE_HELPER_L(psubl, FSUB)
-SSE_HELPER_Q(psubq, FSUB)
-
-SSE_HELPER_B(paddusb, FADDUB)
-SSE_HELPER_B(paddsb, FADDSB)
-SSE_HELPER_B(psubusb, FSUBUB)
-SSE_HELPER_B(psubsb, FSUBSB)
-
-SSE_HELPER_W(paddusw, FADDUW)
-SSE_HELPER_W(paddsw, FADDSW)
-SSE_HELPER_W(psubusw, FSUBUW)
-SSE_HELPER_W(psubsw, FSUBSW)
-
-SSE_HELPER_B(pminub, FMINUB)
-SSE_HELPER_B(pmaxub, FMAXUB)
-
-SSE_HELPER_W(pminsw, FMINSW)
-SSE_HELPER_W(pmaxsw, FMAXSW)
-
-SSE_HELPER_Q(pand, FAND)
-SSE_HELPER_Q(pandn, FANDN)
-SSE_HELPER_Q(por, FOR)
-SSE_HELPER_Q(pxor, FXOR)
-
-SSE_HELPER_B(pcmpgtb, FCMPGTB)
-SSE_HELPER_W(pcmpgtw, FCMPGTW)
-SSE_HELPER_L(pcmpgtl, FCMPGTL)
-
-SSE_HELPER_B(pcmpeqb, FCMPEQ)
-SSE_HELPER_W(pcmpeqw, FCMPEQ)
-SSE_HELPER_L(pcmpeql, FCMPEQ)
-
 SSE_HELPER_W(pmullw, FMULLW)
 #if SHIFT == 0
 SSE_HELPER_W(pmulhrw, FMULHRW)
diff --git a/target/i386/translate.c b/target/i386/translate.c
index 3149989d68..78c91a85c9 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -2756,19 +2756,11 @@ static const SSEFunc_0_epp sse_op_table1[256][4] = {
 [0x51] = SSE_FOP(sqrt),
 [0x52] = { gen_helper_rsqrtps, NULL, gen_helper_rsqrtss, NULL },
 [0x53] = { gen_helper_rcpps, NULL, gen_helper_rcpss, NULL },
-[0x54] = { gen_helper_pand_xmm, gen_helper_pand_xmm }, /* andps, andpd */
-[0x55] = { gen_helper_pandn_xmm, gen_helper_pandn_xmm }, /* andnps, andnpd 
*/
-[0x56] = { gen_help

[Qemu-devel] [RFC PATCH v4 62/75] target/i386: introduce AVX2 translators

2019-08-21 Thread Jan Bobek
Use the translator macros to define translators required by AVX2
instructions.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 19 ---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 50eab9181c..3f4bb40932 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -7692,11 +7692,11 @@ DEF_TRANSLATE_INSN2(Vd, Wd)
 DEF_TRANSLATE_INSN2(Vd, Wq)
 DEF_TRANSLATE_INSN2(Vdq, Ed)
 DEF_TRANSLATE_INSN2(Vdq, Eq)
-DEF_TRANSLATE_INSN2(Vdq, Md)
 DEF_TRANSLATE_INSN2(Vdq, Mdq)
 DEF_TRANSLATE_INSN2(Vdq, Nq)
 DEF_TRANSLATE_INSN2(Vdq, Qq)
 DEF_TRANSLATE_INSN2(Vdq, Udq)
+DEF_TRANSLATE_INSN2(Vdq, Wb)
 DEF_TRANSLATE_INSN2(Vdq, Wd)
 DEF_TRANSLATE_INSN2(Vdq, Wdq)
 DEF_TRANSLATE_INSN2(Vdq, Wq)
@@ -7706,12 +7706,14 @@ DEF_TRANSLATE_INSN2(Vq, Ed)
 DEF_TRANSLATE_INSN2(Vq, Eq)
 DEF_TRANSLATE_INSN2(Vq, Wd)
 DEF_TRANSLATE_INSN2(Vq, Wq)
-DEF_TRANSLATE_INSN2(Vqq, Md)
 DEF_TRANSLATE_INSN2(Vqq, Mdq)
-DEF_TRANSLATE_INSN2(Vqq, Mq)
 DEF_TRANSLATE_INSN2(Vqq, Mqq)
+DEF_TRANSLATE_INSN2(Vqq, Wb)
+DEF_TRANSLATE_INSN2(Vqq, Wd)
 DEF_TRANSLATE_INSN2(Vqq, Wdq)
+DEF_TRANSLATE_INSN2(Vqq, Wq)
 DEF_TRANSLATE_INSN2(Vqq, Wqq)
+DEF_TRANSLATE_INSN2(Vqq, Ww)
 DEF_TRANSLATE_INSN2(Wd, Vd)
 DEF_TRANSLATE_INSN2(Wdq, Vdq)
 DEF_TRANSLATE_INSN2(Wq, Vq)
@@ -7763,6 +7765,7 @@ DEF_TRANSLATE_INSN3(Gd, Udq, Ib)
 DEF_TRANSLATE_INSN3(Gq, Nq, Ib)
 DEF_TRANSLATE_INSN3(Gq, Udq, Ib)
 DEF_TRANSLATE_INSN3(Hdq, Udq, Ib)
+DEF_TRANSLATE_INSN3(Hqq, Uqq, Ib)
 DEF_TRANSLATE_INSN3(Mdq, Hdq, Vdq)
 DEF_TRANSLATE_INSN3(Mqq, Hqq, Vqq)
 DEF_TRANSLATE_INSN3(Nq, Nq, Ib)
@@ -7789,6 +7792,7 @@ DEF_TRANSLATE_INSN3(Vdq, Vdq, UdqMhq)
 DEF_TRANSLATE_INSN3(Vdq, Vdq, Wdq)
 DEF_TRANSLATE_INSN3(Vdq, Vq, Mq)
 DEF_TRANSLATE_INSN3(Vdq, Vq, Wq)
+DEF_TRANSLATE_INSN3(Vdq, Wd, modrm_mod)
 DEF_TRANSLATE_INSN3(Vdq, Wdq, Ib)
 DEF_TRANSLATE_INSN3(Vq, Hq, Ed)
 DEF_TRANSLATE_INSN3(Vq, Hq, Eq)
@@ -7797,7 +7801,10 @@ DEF_TRANSLATE_INSN3(Vq, Hq, Wq)
 DEF_TRANSLATE_INSN3(Vq, Vq, Wq)
 DEF_TRANSLATE_INSN3(Vq, Wq, Ib)
 DEF_TRANSLATE_INSN3(Vqq, Hqq, Mqq)
+DEF_TRANSLATE_INSN3(Vqq, Hqq, Wdq)
 DEF_TRANSLATE_INSN3(Vqq, Hqq, Wqq)
+DEF_TRANSLATE_INSN3(Vqq, Wd, modrm_mod)
+DEF_TRANSLATE_INSN3(Vqq, Wq, modrm_mod)
 DEF_TRANSLATE_INSN3(Vqq, Wqq, Ib)
 DEF_TRANSLATE_INSN3(Wdq, Vqq, Ib)
 
@@ -7921,8 +7928,14 @@ DEF_TRANSLATE_INSN4(Vqq, Hqq, Wqq, Lqq)
 }   \
 }
 
+DEF_TRANSLATE_INSN5(Vdq, Hdq, Vdq, MDdq, Hdq)
+DEF_TRANSLATE_INSN5(Vdq, Hdq, Vdq, MQdq, Hdq)
+DEF_TRANSLATE_INSN5(Vdq, Hdq, Vdq, MQqq, Hdq)
 DEF_TRANSLATE_INSN5(Vdq, Hdq, Wd, modrm_mod, vex_v)
 DEF_TRANSLATE_INSN5(Vdq, Hdq, Wq, modrm_mod, vex_v)
+DEF_TRANSLATE_INSN5(Vqq, Hqq, Vqq, MDdq, Hqq)
+DEF_TRANSLATE_INSN5(Vqq, Hqq, Vqq, MDqq, Hqq)
+DEF_TRANSLATE_INSN5(Vqq, Hqq, Vqq, MQqq, Hqq)
 DEF_TRANSLATE_INSN5(Wdq, Hdq, Vd, modrm_mod, vex_v)
 DEF_TRANSLATE_INSN5(Wdq, Hdq, Vq, modrm_mod, vex_v)
 
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 75/75] target/i386: convert pmovmskb/movmskps/movmskpd helpers to gvec style

2019-08-21 Thread Jan Bobek
Make these helpers suitable for use with tcg_gen_gvec_* functions.

Signed-off-by: Jan Bobek 
---
 target/i386/ops_sse.h|  74 ++--
 target/i386/ops_sse_header.h |   9 ++-
 target/i386/translate.c  | 132 ++-
 3 files changed, 65 insertions(+), 150 deletions(-)

diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h
index 2e50d91a25..82562c9473 100644
--- a/target/i386/ops_sse.h
+++ b/target/i386/ops_sse.h
@@ -1169,52 +1169,56 @@ void helper_comisd(CPUX86State *env, Reg *d, Reg *s)
 CC_SRC = comis_eflags[ret + 1];
 }
 
-uint32_t helper_movmskps(CPUX86State *env, Reg *s)
+uint32_t helper_movmskpsd(Reg *a, uint32_t desc)
 {
-int b0, b1, b2, b3;
+const intptr_t oprsz = simd_oprsz(desc);
 
-b0 = s->ZMM_L(0) >> 31;
-b1 = s->ZMM_L(1) >> 31;
-b2 = s->ZMM_L(2) >> 31;
-b3 = s->ZMM_L(3) >> 31;
-return b0 | (b1 << 1) | (b2 << 2) | (b3 << 3);
+uint32_t ret = 0;
+for (intptr_t i = 0; i * sizeof(uint32_t) < oprsz; ++i) {
+const uint32_t t = a->ZMM_L(i) & (1UL << 31);
+ret |= t >> (31 - i);
+}
+return ret;
 }
 
-uint32_t helper_movmskpd(CPUX86State *env, Reg *s)
+uint64_t helper_movmskpsq(Reg *a, uint32_t desc)
 {
-int b0, b1;
+return helper_movmskpsd(a, desc);
+}
+
+uint32_t helper_movmskpdd(Reg *a, uint32_t desc)
+{
+const intptr_t oprsz = simd_oprsz(desc);
 
-b0 = s->ZMM_L(1) >> 31;
-b1 = s->ZMM_L(3) >> 31;
-return b0 | (b1 << 1);
+uint32_t ret = 0;
+for (intptr_t i = 0; i * sizeof(uint64_t) < oprsz; ++i) {
+const uint64_t t = a->ZMM_Q(i) & (1ULL << 63);
+ret |= t >> (63 - i);
+}
+return ret;
 }
 
+uint64_t helper_movmskpdq(Reg *a, uint32_t desc)
+{
+return helper_movmskpdd(a, desc);
+}
 #endif
 
-uint32_t glue(helper_pmovmskb, SUFFIX)(CPUX86State *env, Reg *s)
+uint32_t glue(helper_pmovmskbd, SUFFIX)(Reg *a, uint32_t desc)
 {
-uint32_t val;
-
-val = 0;
-val |= (s->B(0) >> 7);
-val |= (s->B(1) >> 6) & 0x02;
-val |= (s->B(2) >> 5) & 0x04;
-val |= (s->B(3) >> 4) & 0x08;
-val |= (s->B(4) >> 3) & 0x10;
-val |= (s->B(5) >> 2) & 0x20;
-val |= (s->B(6) >> 1) & 0x40;
-val |= (s->B(7)) & 0x80;
-#if SHIFT == 1
-val |= (s->B(8) << 1) & 0x0100;
-val |= (s->B(9) << 2) & 0x0200;
-val |= (s->B(10) << 3) & 0x0400;
-val |= (s->B(11) << 4) & 0x0800;
-val |= (s->B(12) << 5) & 0x1000;
-val |= (s->B(13) << 6) & 0x2000;
-val |= (s->B(14) << 7) & 0x4000;
-val |= (s->B(15) << 8) & 0x8000;
-#endif
-return val;
+const intptr_t oprsz = simd_oprsz(desc);
+
+uint32_t ret = 0;
+for (intptr_t i = 0; i * sizeof(uint8_t) < oprsz; ++i) {
+const uint8_t t = a->B(i) & (1 << 7);
+ret |= i < 8 ? t >> (7 - i) : t << (i - 7);
+}
+return ret;
+}
+
+uint64_t glue(helper_pmovmskbq, SUFFIX)(Reg *a, uint32_t desc)
+{
+return glue(helper_pmovmskbd, SUFFIX)(a, desc);
 }
 
 void glue(helper_packsswb, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
diff --git a/target/i386/ops_sse_header.h b/target/i386/ops_sse_header.h
index 207d41e248..59ac1f28e3 100644
--- a/target/i386/ops_sse_header.h
+++ b/target/i386/ops_sse_header.h
@@ -178,11 +178,14 @@ DEF_HELPER_3(ucomiss, void, env, Reg, Reg)
 DEF_HELPER_3(comiss, void, env, Reg, Reg)
 DEF_HELPER_3(ucomisd, void, env, Reg, Reg)
 DEF_HELPER_3(comisd, void, env, Reg, Reg)
-DEF_HELPER_2(movmskps, i32, env, Reg)
-DEF_HELPER_2(movmskpd, i32, env, Reg)
+DEF_HELPER_2(movmskpsd, i32, Reg, i32)
+DEF_HELPER_2(movmskpsq, i64, Reg, i32)
+DEF_HELPER_2(movmskpdd, i32, Reg, i32)
+DEF_HELPER_2(movmskpdq, i64, Reg, i32)
 #endif
 
-DEF_HELPER_2(glue(pmovmskb, SUFFIX), i32, env, Reg)
+DEF_HELPER_2(glue(pmovmskbd, SUFFIX), i32, Reg, i32)
+DEF_HELPER_2(glue(pmovmskbq, SUFFIX), i64, Reg, i32)
 DEF_HELPER_3(glue(packsswb, SUFFIX), void, env, Reg, Reg)
 DEF_HELPER_3(glue(packuswb, SUFFIX), void, env, Reg, Reg)
 DEF_HELPER_3(glue(packssdw, SUFFIX), void, env, Reg, Reg)
diff --git a/target/i386/translate.c b/target/i386/translate.c
index bb4120a848..8f891b6e47 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -3339,20 +3339,6 @@ static void gen_sse(CPUX86State *env, DisasContext *s, 
int b)
 goto illegal_op;
 }
 break;
-case 0x050: /* movmskps */
-rm = (modrm & 7) | REX_B(s);
-tcg_gen_addi_ptr(s->ptr0, cpu_env,
- offsetof(CPUX86State,xmm_regs[rm]));
-gen_helper_movmskps(s->tmp2_i32, cpu_env, s->ptr0);
-tcg_gen_extu_i32_tl(cpu_regs[reg], s->tm

[Qemu-devel] [RFC PATCH v4 46/75] target/i386: introduce SSE3 code generators

2019-08-21 Thread Jan Bobek
Introduce code generators required by SSE3 instructions.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 61 +
 1 file changed, 61 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index a478f73c17..d449a64464 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -5802,6 +5802,60 @@ GEN_INSN2(movmskpd, Gq, Udq)
 tcg_temp_free_i32(arg1_r32);
 }
 
+GEN_INSN2(lddqu, Vdq, Mdq)
+{
+insnop_ldst(xmm, Mdq)(env, s, 0, arg1, arg2);
+}
+
+GEN_INSN2(movshdup, Vdq, Wdq)
+{
+const TCGv_i32 r32 = tcg_temp_new_i32();
+
+tcg_gen_ld_i32(r32, cpu_env, arg2 + offsetof(ZMMReg, ZMM_L(1)));
+tcg_gen_st_i32(r32, cpu_env, arg1 + offsetof(ZMMReg, ZMM_L(0)));
+if (arg1 != arg2) {
+tcg_gen_st_i32(r32, cpu_env, arg1 + offsetof(ZMMReg, ZMM_L(1)));
+}
+
+tcg_gen_ld_i32(r32, cpu_env, arg2 + offsetof(ZMMReg, ZMM_L(3)));
+tcg_gen_st_i32(r32, cpu_env, arg1 + offsetof(ZMMReg, ZMM_L(2)));
+if (arg1 != arg2) {
+tcg_gen_st_i32(r32, cpu_env, arg1 + offsetof(ZMMReg, ZMM_L(3)));
+}
+
+tcg_temp_free_i32(r32);
+}
+GEN_INSN2(movsldup, Vdq, Wdq)
+{
+const TCGv_i32 r32 = tcg_temp_new_i32();
+
+tcg_gen_ld_i32(r32, cpu_env, arg2 + offsetof(ZMMReg, ZMM_L(0)));
+if (arg1 != arg2) {
+tcg_gen_st_i32(r32, cpu_env, arg1 + offsetof(ZMMReg, ZMM_L(0)));
+}
+tcg_gen_st_i32(r32, cpu_env, arg1 + offsetof(ZMMReg, ZMM_L(1)));
+
+tcg_gen_ld_i32(r32, cpu_env, arg2 + offsetof(ZMMReg, ZMM_L(2)));
+if (arg1 != arg2) {
+tcg_gen_st_i32(r32, cpu_env, arg1 + offsetof(ZMMReg, ZMM_L(2)));
+}
+tcg_gen_st_i32(r32, cpu_env, arg1 + offsetof(ZMMReg, ZMM_L(3)));
+
+tcg_temp_free_i32(r32);
+}
+GEN_INSN2(movddup, Vdq, Wq)
+{
+const TCGv_i64 r64 = tcg_temp_new_i64();
+
+tcg_gen_ld_i64(r64, cpu_env, arg2 + offsetof(ZMMReg, ZMM_Q(0)));
+if (arg1 != arg2) {
+tcg_gen_st_i64(r64, cpu_env, arg1 + offsetof(ZMMReg, ZMM_Q(0)));
+}
+tcg_gen_st_i64(r64, cpu_env, arg1 + offsetof(ZMMReg, ZMM_Q(1)));
+
+tcg_temp_free_i64(r64);
+}
+
 DEF_GEN_INSN3_GVEC(paddb, Pq, Pq, Qq, add, MM_OPRSZ, MM_MAXSZ, MO_8)
 DEF_GEN_INSN3_GVEC(paddb, Vdq, Vdq, Wdq, add, XMM_OPRSZ, XMM_MAXSZ, MO_8)
 DEF_GEN_INSN3_GVEC(paddw, Pq, Pq, Qq, add, MM_OPRSZ, MM_MAXSZ, MO_16)
@@ -5822,6 +5876,8 @@ DEF_GEN_INSN3_HELPER_EPP(addps, addps, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(addpd, addpd, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(addss, addss, Vd, Vd, Wd)
 DEF_GEN_INSN3_HELPER_EPP(addsd, addsd, Vq, Vq, Wq)
+DEF_GEN_INSN3_HELPER_EPP(haddps, haddps, Vdq, Vdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(haddpd, haddpd, Vdq, Vdq, Wdq)
 
 DEF_GEN_INSN3_GVEC(psubb, Pq, Pq, Qq, sub, MM_OPRSZ, MM_MAXSZ, MO_8)
 DEF_GEN_INSN3_GVEC(psubb, Vdq, Vdq, Wdq, sub, XMM_OPRSZ, XMM_MAXSZ, MO_8)
@@ -5843,6 +5899,11 @@ DEF_GEN_INSN3_HELPER_EPP(subps, subps, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(subpd, subpd, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(subss, subss, Vd, Vd, Wd)
 DEF_GEN_INSN3_HELPER_EPP(subsd, subsd, Vq, Vq, Wq)
+DEF_GEN_INSN3_HELPER_EPP(hsubps, hsubps, Vdq, Vdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(hsubpd, hsubpd, Vdq, Vdq, Wdq)
+
+DEF_GEN_INSN3_HELPER_EPP(addsubps, addsubps, Vdq, Vdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(addsubpd, addsubpd, Vdq, Vdq, Wdq)
 
 DEF_GEN_INSN3_HELPER_EPP(pmullw, pmullw_mmx, Pq, Pq, Qq)
 DEF_GEN_INSN3_HELPER_EPP(pmullw, pmullw_xmm, Vdq, Vdq, Wdq)
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 67/75] target/i386: introduce aliases for helper-based tcg_gen_gvec_* functions

2019-08-21 Thread Jan Bobek
Expand our aliases for tcg_gen_gvec_* functions to also include those
that generate calls to out-of-line helpers. This allows us use them
via the DEF_GEN_INSN*_GVEC macros.
---
 target/i386/translate.c | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 78c91a85c9..c7e664e798 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4441,6 +4441,36 @@ static void gen_sse(CPUX86State *env, DisasContext *s, 
int b)
 }
 }
 
+#define gen_gvec_s1_ool(ret, aofs, oprsz, maxsz, data, helper)  \
+do {\
+const TCGv_ptr a0 = tcg_temp_new_ptr(); \
+const TCGv_i32 desc =   \
+  tcg_const_i32(simd_desc(oprsz, maxsz, 0));\
+\
+tcg_gen_addi_ptr(a0, cpu_env, aofs);\
+gen_helper_ ## helper(ret, a0, desc);   \
+\
+tcg_temp_free_ptr(a0);  \
+tcg_temp_free_i32(desc);\
+} while (0)
+
+/*
+ * We pass the immediate value via simd_data. The width is limited
+ * to SIMD_DATA_BITS, but we only use up to 8-bit immediates.
+ */
+#define gen_gvec_sd1_ool(ret, aofs, oprsz, maxsz, helper)   \
+gen_gvec_s1_ool(ret, aofs, oprsz, maxsz, 0, helper)
+#define gen_gvec_sq1_ool(ret, aofs, oprsz, maxsz, helper)   \
+gen_gvec_s1_ool(ret, aofs, oprsz, maxsz, 0, helper)
+#define gen_gvec_2_ool(aofs, bofs, oprsz, maxsz, helper)\
+tcg_gen_gvec_2_ool(aofs, bofs, oprsz, maxsz, 0, gen_helper_ ## helper)
+#define gen_gvec_2i_ool(aofs, bofs, c, oprsz, maxsz, helper)\
+tcg_gen_gvec_2_ool(aofs, bofs, oprsz, maxsz, c, gen_helper_ ## helper)
+#define gen_gvec_3_ool(aofs, bofs, cofs, oprsz, maxsz, helper)  \
+tcg_gen_gvec_3_ool(aofs, bofs, cofs, oprsz, maxsz, 0, gen_helper_ ## 
helper)
+#define gen_gvec_3i_ool(aofs, bofs, cofs, c, oprsz, maxsz, helper)  \
+tcg_gen_gvec_3_ool(aofs, bofs, cofs, oprsz, maxsz, c, gen_helper_ ## 
helper)
+
 #define gen_gvec_mov(dofs, aofs, oprsz, maxsz, vece)\
 tcg_gen_gvec_mov(vece, dofs, aofs, oprsz, maxsz)
 
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 57/75] target/i386: introduce AES and PCLMULQDQ code generators

2019-08-21 Thread Jan Bobek
Introduce code generators required by AES and PCLMULQDQ instructions.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 75b0a818f2..14117c2993 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -6004,6 +6004,21 @@ DEF_GEN_INSN3_HELPER_EPPI(roundpd, roundpd_xmm, Vdq, 
Wdq, Ib)
 DEF_GEN_INSN3_HELPER_EPPI(roundss, roundss_xmm, Vd, Wd, Ib)
 DEF_GEN_INSN3_HELPER_EPPI(roundsd, roundsd_xmm, Vq, Wq, Ib)
 
+DEF_GEN_INSN3_HELPER_EPP(aesdec, aesdec_xmm, Vdq, Vdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(vaesdec, aesdec_xmm, Vdq, Hdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(aesdeclast, aesdeclast_xmm, Vdq, Vdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(vaesdeclast, aesdeclast_xmm, Vdq, Hdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(aesenc, aesenc_xmm, Vdq, Vdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(vaesenc, aesenc_xmm, Vdq, Hdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(aesenclast, aesenclast_xmm, Vdq, Vdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(vaesenclast, aesenclast_xmm, Vdq, Hdq, Wdq)
+DEF_GEN_INSN2_HELPER_EPP(aesimc, aesimc_xmm, Vdq, Wdq)
+DEF_GEN_INSN2_HELPER_EPP(vaesimc, aesimc_xmm, Vdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPPI(aeskeygenassist, aeskeygenassist_xmm, Vdq, Wdq, Ib)
+DEF_GEN_INSN3_HELPER_EPPI(vaeskeygenassist, aeskeygenassist_xmm, Vdq, Wdq, Ib)
+DEF_GEN_INSN4_HELPER_EPPI(pclmulqdq, pclmulqdq_xmm, Vdq, Vdq, Wdq, Ib)
+DEF_GEN_INSN4_HELPER_EPPI(vpclmulqdq, pclmulqdq_xmm, Vdq, Hdq, Wdq, Ib)
+
 DEF_GEN_INSN3_GVEC(pcmpeqb, Pq, Pq, Qq, cmp, MM_OPRSZ, MM_MAXSZ, MO_8, 
TCG_COND_EQ)
 DEF_GEN_INSN3_GVEC(pcmpeqb, Vdq, Vdq, Wdq, cmp, XMM_OPRSZ, XMM_MAXSZ, MO_8, 
TCG_COND_EQ)
 DEF_GEN_INSN3_GVEC(pcmpeqw, Pq, Pq, Qq, cmp, MM_OPRSZ, MM_MAXSZ, MO_16, 
TCG_COND_EQ)
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 45/75] target/i386: introduce SSE3 translators

2019-08-21 Thread Jan Bobek
Use the translator macros to define translators required by SSE3
instructions.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 3445b4cff1..a478f73c17 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -6519,6 +6519,7 @@ DEF_TRANSLATE_INSN2(Vd, Wd)
 DEF_TRANSLATE_INSN2(Vd, Wq)
 DEF_TRANSLATE_INSN2(Vdq, Ed)
 DEF_TRANSLATE_INSN2(Vdq, Eq)
+DEF_TRANSLATE_INSN2(Vdq, Mdq)
 DEF_TRANSLATE_INSN2(Vdq, Nq)
 DEF_TRANSLATE_INSN2(Vdq, Qq)
 DEF_TRANSLATE_INSN2(Vdq, Udq)
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 47/75] target/i386: introduce SSE3 vector instructions to sse-opcode.inc.h

2019-08-21 Thread Jan Bobek
Add all the SSE3 vector instruction entries to sse-opcode.inc.h.

Signed-off-by: Jan Bobek 
---
 target/i386/sse-opcode.inc.h | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/target/i386/sse-opcode.inc.h b/target/i386/sse-opcode.inc.h
index 6df5fda010..84785a4e04 100644
--- a/target/i386/sse-opcode.inc.h
+++ b/target/i386/sse-opcode.inc.h
@@ -341,6 +341,19 @@
  * NP 0F AE /7  CLFLUSH m8
  * NP 0F AE /5  LFENCE
  * NP 0F AE /6  MFENCE
+ *
+ * SSE3 Instructions
+ * --
+ * F2 0F F0 /r  LDDQU xmm1, m128
+ * F3 0F 16 /r  MOVSHDUP xmm1, xmm2/m128
+ * F3 0F 12 /r  MOVSLDUP xmm1, xmm2/m128
+ * F2 0F 12 /r  MOVDDUP xmm1, xmm2/m64
+ * F2 0F 7C /r  HADDPS xmm1, xmm2/m128
+ * 66 0F 7C /r  HADDPD xmm1, xmm2/m128
+ * F2 0F 7D /r  HSUBPS xmm1, xmm2/m128
+ * 66 0F 7D /r  HSUBPD xmm1, xmm2/m128
+ * F2 0F D0 /r  ADDSUBPS xmm1, xmm2/m128
+ * 66 0F D0 /r  ADDSUBPD xmm1, xmm2/m128
  */
 
 OPCODE(movd, LEG(NP, 0F, 0, 0x6e), MMX, WR, Pq, Ed)
@@ -389,6 +402,10 @@ OPCODE(movmskps, LEG(NP, 0F, 0, 0x50), SSE, WR, Gd, Udq)
 OPCODE(movmskps, LEG(NP, 0F, 1, 0x50), SSE, WR, Gq, Udq)
 OPCODE(movmskpd, LEG(66, 0F, 0, 0x50), SSE2, WR, Gd, Udq)
 OPCODE(movmskpd, LEG(66, 0F, 1, 0x50), SSE2, WR, Gq, Udq)
+OPCODE(lddqu, LEG(F2, 0F, 0, 0xf0), SSE3, WR, Vdq, Mdq)
+OPCODE(movshdup, LEG(F3, 0F, 0, 0x16), SSE3, WR, Vdq, Wdq)
+OPCODE(movsldup, LEG(F3, 0F, 0, 0x12), SSE3, WR, Vdq, Wdq)
+OPCODE(movddup, LEG(F2, 0F, 0, 0x12), SSE3, WR, Vdq, Wq)
 OPCODE(paddb, LEG(NP, 0F, 0, 0xfc), MMX, WRR, Pq, Pq, Qq)
 OPCODE(paddb, LEG(66, 0F, 0, 0xfc), SSE2, WRR, Vdq, Vdq, Wdq)
 OPCODE(paddw, LEG(NP, 0F, 0, 0xfd), MMX, WRR, Pq, Pq, Qq)
@@ -409,6 +426,8 @@ OPCODE(addps, LEG(NP, 0F, 0, 0x58), SSE, WRR, Vdq, Vdq, Wdq)
 OPCODE(addpd, LEG(66, 0F, 0, 0x58), SSE2, WRR, Vdq, Vdq, Wdq)
 OPCODE(addss, LEG(F3, 0F, 0, 0x58), SSE, WRR, Vd, Vd, Wd)
 OPCODE(addsd, LEG(F2, 0F, 0, 0x58), SSE2, WRR, Vq, Vq, Wq)
+OPCODE(haddps, LEG(F2, 0F, 0, 0x7c), SSE3, WRR, Vdq, Vdq, Wdq)
+OPCODE(haddpd, LEG(66, 0F, 0, 0x7c), SSE3, WRR, Vdq, Vdq, Wdq)
 OPCODE(psubb, LEG(NP, 0F, 0, 0xf8), MMX, WRR, Pq, Pq, Qq)
 OPCODE(psubb, LEG(66, 0F, 0, 0xf8), SSE2, WRR, Vdq, Vdq, Wdq)
 OPCODE(psubw, LEG(NP, 0F, 0, 0xf9), MMX, WRR, Pq, Pq, Qq)
@@ -429,6 +448,10 @@ OPCODE(subps, LEG(NP, 0F, 0, 0x5c), SSE, WRR, Vdq, Vdq, 
Wdq)
 OPCODE(subpd, LEG(66, 0F, 0, 0x5c), SSE2, WRR, Vdq, Vdq, Wdq)
 OPCODE(subss, LEG(F3, 0F, 0, 0x5c), SSE, WRR, Vd, Vd, Wd)
 OPCODE(subsd, LEG(F2, 0F, 0, 0x5c), SSE2, WRR, Vq, Vq, Wq)
+OPCODE(hsubps, LEG(F2, 0F, 0, 0x7d), SSE3, WRR, Vdq, Vdq, Wdq)
+OPCODE(hsubpd, LEG(66, 0F, 0, 0x7d), SSE3, WRR, Vdq, Vdq, Wdq)
+OPCODE(addsubps, LEG(F2, 0F, 0, 0xd0), SSE3, WRR, Vdq, Vdq, Wdq)
+OPCODE(addsubpd, LEG(66, 0F, 0, 0xd0), SSE3, WRR, Vdq, Vdq, Wdq)
 OPCODE(pmullw, LEG(NP, 0F, 0, 0xd5), MMX, WRR, Pq, Pq, Qq)
 OPCODE(pmullw, LEG(66, 0F, 0, 0xd5), SSE2, WRR, Vdq, Vdq, Wdq)
 OPCODE(pmulhw, LEG(NP, 0F, 0, 0xe5), MMX, WRR, Pq, Pq, Qq)
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 49/75] target/i386: introduce SSSE3 code generators

2019-08-21 Thread Jan Bobek
Introduce code generators required by SSSE3 instructions.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 33 +
 1 file changed, 33 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 25d3b969b1..f43e9b1ba4 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -5876,6 +5876,12 @@ DEF_GEN_INSN3_HELPER_EPP(addps, addps, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(addpd, addpd, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(addss, addss, Vd, Vd, Wd)
 DEF_GEN_INSN3_HELPER_EPP(addsd, addsd, Vq, Vq, Wq)
+DEF_GEN_INSN3_HELPER_EPP(phaddw, phaddw_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(phaddw, phaddw_xmm, Vdq, Vdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(phaddd, phaddd_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(phaddd, phaddd_xmm, Vdq, Vdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(phaddsw, phaddsw_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(phaddsw, phaddsw_xmm, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(haddps, haddps, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(haddpd, haddpd, Vdq, Vdq, Wdq)
 
@@ -5899,6 +5905,12 @@ DEF_GEN_INSN3_HELPER_EPP(subps, subps, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(subpd, subpd, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(subss, subss, Vd, Vd, Wd)
 DEF_GEN_INSN3_HELPER_EPP(subsd, subsd, Vq, Vq, Wq)
+DEF_GEN_INSN3_HELPER_EPP(phsubw, phsubw_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(phsubw, phsubw_xmm, Vdq, Vdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(phsubd, phsubd_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(phsubd, phsubd_xmm, Vdq, Vdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(phsubsw, phsubsw_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(phsubsw, phsubsw_xmm, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(hsubps, hsubps, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(hsubpd, hsubpd, Vdq, Vdq, Wdq)
 
@@ -5913,12 +5925,16 @@ DEF_GEN_INSN3_HELPER_EPP(pmulhuw, pmulhuw_mmx, Pq, Pq, 
Qq)
 DEF_GEN_INSN3_HELPER_EPP(pmulhuw, pmulhuw_xmm, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(pmuludq, pmuludq_mmx, Pq, Pq, Qq)
 DEF_GEN_INSN3_HELPER_EPP(pmuludq, pmuludq_xmm, Vdq, Vdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(pmulhrsw, pmulhrsw_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(pmulhrsw, pmulhrsw_xmm, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(mulps, mulps, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(mulpd, mulpd, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(mulss, mulss, Vd, Vd, Wd)
 DEF_GEN_INSN3_HELPER_EPP(mulsd, mulsd, Vq, Vq, Wq)
 DEF_GEN_INSN3_HELPER_EPP(pmaddwd, pmaddwd_mmx, Pq, Pq, Qq)
 DEF_GEN_INSN3_HELPER_EPP(pmaddwd, pmaddwd_xmm, Vdq, Vdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(pmaddubsw, pmaddubsw_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(pmaddubsw, pmaddubsw_xmm, Vdq, Vdq, Wdq)
 
 DEF_GEN_INSN3_HELPER_EPP(divps, divps, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(divpd, divpd, Vdq, Vdq, Wdq)
@@ -5956,6 +5972,18 @@ DEF_GEN_INSN3_HELPER_EPP(pavgw, pavgw_mmx, Pq, Pq, Qq)
 DEF_GEN_INSN3_HELPER_EPP(pavgw, pavgw_xmm, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(psadbw, psadbw_mmx, Pq, Pq, Qq)
 DEF_GEN_INSN3_HELPER_EPP(psadbw, psadbw_xmm, Vdq, Vdq, Wdq)
+DEF_GEN_INSN2_HELPER_EPP(pabsb, pabsb_mmx, Pq, Qq)
+DEF_GEN_INSN2_HELPER_EPP(pabsb, pabsb_xmm, Vdq, Wdq)
+DEF_GEN_INSN2_HELPER_EPP(pabsw, pabsw_mmx, Pq, Qq)
+DEF_GEN_INSN2_HELPER_EPP(pabsw, pabsw_xmm, Vdq, Wdq)
+DEF_GEN_INSN2_HELPER_EPP(pabsd, pabsd_mmx, Pq, Qq)
+DEF_GEN_INSN2_HELPER_EPP(pabsd, pabsd_xmm, Vdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(psignb, psignb_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(psignb, psignb_xmm, Vdq, Vdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(psignw, psignw_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(psignw, psignw_xmm, Vdq, Vdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(psignd, psignd_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(psignd, psignd_xmm, Vdq, Vdq, Wdq)
 
 DEF_GEN_INSN3_GVEC(pcmpeqb, Pq, Pq, Qq, cmp, MM_OPRSZ, MM_MAXSZ, MO_8, 
TCG_COND_EQ)
 DEF_GEN_INSN3_GVEC(pcmpeqb, Vdq, Vdq, Wdq, cmp, XMM_OPRSZ, XMM_MAXSZ, MO_8, 
TCG_COND_EQ)
@@ -6216,6 +6244,9 @@ DEF_GEN_PSHIFT_IMM_XMM(psraw, Udq, Udq)
 DEF_GEN_PSHIFT_IMM_MM(psrad, Nq, Nq)
 DEF_GEN_PSHIFT_IMM_XMM(psrad, Udq, Udq)
 
+DEF_GEN_INSN4_HELPER_EPPI(palignr, palignr_mmx, Pq, Pq, Qq, Ib)
+DEF_GEN_INSN4_HELPER_EPPI(palignr, palignr_xmm, Vdq, Vdq, Wdq, Ib)
+
 DEF_GEN_INSN3_HELPER_EPP(packsswb, packsswb_mmx, Pq, Pq, Qq)
 DEF_GEN_INSN3_HELPER_EPP(packsswb, packsswb_xmm, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(packssdw, packssdw_mmx, Pq, Pq, Qq)
@@ -6242,6 +6273,8 @@ DEF_GEN_INSN3_HELPER_EPP(unpcklpd, punpcklqdq_xmm, Vdq, 
Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(unpckhps, punpckhdq_xmm, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(unpckhpd, punpckhqdq_xmm, Vdq, Vdq, Wdq)
 
+DEF_GEN_INSN3_HELPER_EPP(pshufb, pshufb_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(pshufb, pshufb_xmm, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_PPI(pshufw, pshufw_mmx, Pq, Qq, Ib)
 DEF_GEN_INSN3_HELPER_PPI(pshuflw, pshuflw_xmm, Vdq, Wdq, Ib)
 DEF_GEN_INSN3_HELPER_PPI(pshufhw, pshufhw_xmm, Vdq, Wdq, Ib)
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 53/75] target/i386: introduce SSE4.1 vector instructions to sse-opcode.inc.h

2019-08-21 Thread Jan Bobek
Add all the SSE4.1 vector instruction entries to sse-opcode.inc.h.

Signed-off-by: Jan Bobek 
---
 target/i386/sse-opcode.inc.h | 101 +++
 1 file changed, 101 insertions(+)

diff --git a/target/i386/sse-opcode.inc.h b/target/i386/sse-opcode.inc.h
index d8ea71aa6c..9682cce7ef 100644
--- a/target/i386/sse-opcode.inc.h
+++ b/target/i386/sse-opcode.inc.h
@@ -389,6 +389,58 @@
  * 66 0F 3A 0F /r ib   PALIGNR xmm1, xmm2/m128, imm8
  * NP 0F 38 00 /r  PSHUFB mm1, mm2/m64
  * 66 0F 38 00 /r  PSHUFB xmm1, xmm2/m128
+ *
+ * SSE4.1 Instructions
+ * 
+ * 66 0F 38 40 /r  PMULLD xmm1, xmm2/m128
+ * 66 0F 38 28 /r  PMULDQ xmm1, xmm2/m128
+ * 66 0F 38 3A /r  PMINUW xmm1, xmm2/m128
+ * 66 0F 38 3B /r  PMINUD xmm1, xmm2/m128
+ * 66 0F 38 38 /r  PMINSB xmm1, xmm2/m128
+ * 66 0F 38 39 /r  PMINSD xmm1, xmm2/m128
+ * 66 0F 38 41 /r  PHMINPOSUW xmm1, xmm2/m128
+ * 66 0F 38 3E /r  PMAXUW xmm1, xmm2/m128
+ * 66 0F 38 3F /r  PMAXUD xmm1, xmm2/m128
+ * 66 0F 38 3C /r  PMAXSB xmm1, xmm2/m128
+ * 66 0F 38 3D /r  PMAXSD xmm1, xmm2/m128
+ * 66 0F 3A 42 /r ib   MPSADBW xmm1, xmm2/m128, imm8
+ * 66 0F 3A 40 /r ib   DPPS xmm1, xmm2/m128, imm8
+ * 66 0F 3A 41 /r ib   DPPD xmm1, xmm2/m128, imm8
+ * 66 0F 3A 08 /r ib   ROUNDPS xmm1, xmm2/m128, imm8
+ * 66 0F 3A 09 /r ib   ROUNDPD xmm1, xmm2/m128, imm8
+ * 66 0F 3A 0A /r ib   ROUNDSS xmm1, xmm2/m32, imm8
+ * 66 0F 3A 0B /r ib   ROUNDSD xmm1, xmm2/m64, imm8
+ * 66 0F 38 29 /r  PCMPEQQ xmm1, xmm2/m128
+ * 66 0F 38 17 /r  PTEST xmm1, xmm2/m128
+ * 66 0F 38 2B /r  PACKUSDW xmm1, xmm2/m128
+ * 66 0F 3A 0C /r ib   BLENDPS xmm1, xmm2/m128, imm8
+ * 66 0F 3A 0D /r ib   BLENDPD xmm1, xmm2/m128, imm8
+ * 66 0F 38 14 /r  BLENDVPS xmm1, xmm2/m128, 
+ * 66 0F 38 15 /r  BLENDVPD xmm1, xmm2/m128 , 
+ * 66 0F 38 10 /r  PBLENDVB xmm1, xmm2/m128, 
+ * 66 0F 3A 0E /r ib   PBLENDW xmm1, xmm2/m128, imm8
+ * 66 0F 3A 21 /r ib   INSERTPS xmm1, xmm2/m32, imm8
+ * 66 0F 3A 20 /r ib   PINSRB xmm1,r32/m8,imm8
+ * 66 0F 3A 22 /r ib   PINSRD xmm1,r/m32,imm8
+ * 66 REX.W 0F 3A 22 /r ib PINSRQ xmm1,r/m64,imm8
+ * 66 0F 3A 17 /r ib   EXTRACTPS reg/m32, xmm1, imm8
+ * 66 0F 3A 14 /r ib   PEXTRB r32/m8,xmm2,imm8
+ * 66 0F 3A 15 /r ib   PEXTRW r32/m16, xmm, imm8
+ * 66 0F 3A 16 /r ib   PEXTRD r/m32,xmm2,imm8
+ * 66 REX.W 0F 3A 16 /r ib PEXTRQ r/m64,xmm2,imm8
+ * 66 0f 38 20 /r  PMOVSXBW xmm1, xmm2/m64
+ * 66 0f 38 21 /r  PMOVSXBD xmm1, xmm2/m32
+ * 66 0f 38 22 /r  PMOVSXBQ xmm1, xmm2/m16
+ * 66 0f 38 23 /r  PMOVSXWD xmm1, xmm2/m64
+ * 66 0f 38 24 /r  PMOVSXWQ xmm1, xmm2/m32
+ * 66 0f 38 25 /r  PMOVSXDQ xmm1, xmm2/m64
+ * 66 0f 38 30 /r  PMOVZXBW xmm1, xmm2/m64
+ * 66 0f 38 31 /r  PMOVZXBD xmm1, xmm2/m32
+ * 66 0f 38 32 /r  PMOVZXBQ xmm1, xmm2/m16
+ * 66 0f 38 33 /r  PMOVZXWD xmm1, xmm2/m64
+ * 66 0f 38 34 /r  PMOVZXWQ xmm1, xmm2/m32
+ * 66 0f 38 35 /r  PMOVZXDQ xmm1, xmm2/m64
+ * 66 0F 38 2A /r  MOVNTDQA xmm1, m128
  */
 
 OPCODE(movd, LEG(NP, 0F, 0, 0x6e), MMX, WR, Pq, Ed)
@@ -501,10 +553,12 @@ OPCODE(addsubps, LEG(F2, 0F, 0, 0xd0), SSE3, WRR, Vdq, 
Vdq, Wdq)
 OPCODE(addsubpd, LEG(66, 0F, 0, 0xd0), SSE3, WRR, Vdq, Vdq, Wdq)
 OPCODE(pmullw, LEG(NP, 0F, 0, 0xd5), MMX, WRR, Pq, Pq, Qq)
 OPCODE(pmullw, LEG(66, 0F, 0, 0xd5), SSE2, WRR, Vdq, Vdq, Wdq)
+OPCODE(pmulld, LEG(66, 0F38, 0, 0x40), SSE4_1, WRR, Vdq, Vdq, Wdq)
 OPCODE(pmulhw, LEG(NP, 0F, 0, 0xe5), MMX, WRR, Pq, Pq, Qq)
 OPCODE(pmulhw, LEG(66, 0F, 0, 0xe5), SSE2, WRR, Vdq, Vdq, Wdq)
 OPCODE(pmulhuw, LEG(NP, 0F, 0, 0xe4), SSE, WRR, Pq, Pq, Qq)
 OPCODE(pmulhuw, LEG(66, 0F, 0, 0xe4), SSE2, WRR, Vdq, Vdq, Wdq)
+OPCODE(pmuldq, LEG(66, 0F38, 0, 0x28), SSE4_1, WRR, Vdq, Vdq, Wdq)
 OPCODE(pmuludq, LEG(NP, 0F, 0, 0xf4), SSE2, WRR, Pq, Pq, Qq)
 OPCODE(pmuludq, LEG(66, 0F, 0, 0xf4), SSE2, WRR, Vdq, Vdq, Wdq)
 OPCODE(pmulhrsw, LEG(NP, 0F38, 0, 0x0b), SSSE3, WRR, Pq, Pq, Qq)
@@ -531,16 +585,25 @@ OPCODE(rsqrtps, LEG(NP, 0F, 0, 0x52), SSE, WR, Vdq, Wdq)
 OPCODE(rsqrtss, LEG(F3, 0F, 0, 0x52), SSE, WR, Vd, Wd)
 OPCODE(pminub, LEG(NP, 0F, 0, 0xda), SSE, WRR, Pq, Pq, Qq)
 OPCODE(pminub, LEG(66, 0F, 0, 0xda), SSE2, WRR, Vdq, Vdq, Wdq)
+OPCODE(pminuw, LEG(66, 0F38, 0, 0x3a), SSE4_1, WRR, Vdq, Vdq, Wdq)
+OPCODE(pminud, LEG(66, 0F38, 0, 0x3b), SSE4_1, WRR, Vdq, Vdq, Wdq)
+OPCODE(pminsb, LEG(66, 0F38, 0, 0x38), SSE4_1, WRR, Vdq, Vdq, Wdq)
 OPCODE(pminsw, LEG(NP, 0F, 0, 0xea), SSE, WRR, Pq, Pq, Qq)
 OPCODE(pminsw, LEG(66, 0F, 0, 0xea), SSE2, WRR, Vdq, Vdq, Wdq)
+OPCODE(pminsd, LEG(66, 0F38, 0, 0x39), SSE4_1, WRR, Vdq, Vdq, Wdq)
 OPCODE(minps, LEG(NP, 0F, 0, 0x5d), SSE, WRR, Vdq, Vdq, Wdq)
 OPCODE(minpd, LEG(66, 0F, 0, 0x5d), SSE2, WRR, Vdq, Vdq, Wdq)
 OPCODE(minss, LEG(F3, 0F, 0, 0x5d), SSE, WRR, Vd, Vd, Wd)
 OPCODE(minsd, LEG

[Qemu-devel] [RFC PATCH v4 51/75] target/i386: introduce SSE4.1 translators

2019-08-21 Thread Jan Bobek
Use the translator macros to define translators required by SSE4.1
instructions.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index f43e9b1ba4..110b963215 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -6617,8 +6617,10 @@ DEF_TRANSLATE_INSN2(Vdq, Mdq)
 DEF_TRANSLATE_INSN2(Vdq, Nq)
 DEF_TRANSLATE_INSN2(Vdq, Qq)
 DEF_TRANSLATE_INSN2(Vdq, Udq)
+DEF_TRANSLATE_INSN2(Vdq, Wd)
 DEF_TRANSLATE_INSN2(Vdq, Wdq)
 DEF_TRANSLATE_INSN2(Vdq, Wq)
+DEF_TRANSLATE_INSN2(Vdq, Ww)
 DEF_TRANSLATE_INSN2(Vq, Ed)
 DEF_TRANSLATE_INSN2(Vq, Eq)
 DEF_TRANSLATE_INSN2(Vq, Wd)
@@ -,6 +6668,8 @@ DEF_TRANSLATE_INSN2(modrm_mod, modrm)
 }   \
 }
 
+DEF_TRANSLATE_INSN3(Ed, Vdq, Ib)
+DEF_TRANSLATE_INSN3(Eq, Vdq, Ib)
 DEF_TRANSLATE_INSN3(Gd, Nq, Ib)
 DEF_TRANSLATE_INSN3(Gd, Udq, Ib)
 DEF_TRANSLATE_INSN3(Gq, Nq, Ib)
@@ -6674,8 +6678,11 @@ DEF_TRANSLATE_INSN3(Nq, Nq, Ib)
 DEF_TRANSLATE_INSN3(Pq, Pq, Qd)
 DEF_TRANSLATE_INSN3(Pq, Pq, Qq)
 DEF_TRANSLATE_INSN3(Pq, Qq, Ib)
+DEF_TRANSLATE_INSN3(RdMb, Vdq, Ib)
+DEF_TRANSLATE_INSN3(RdMw, Vdq, Ib)
 DEF_TRANSLATE_INSN3(Udq, Udq, Ib)
 DEF_TRANSLATE_INSN3(Vd, Vd, Wd)
+DEF_TRANSLATE_INSN3(Vd, Wd, Ib)
 DEF_TRANSLATE_INSN3(Vdq, Vdq, Mq)
 DEF_TRANSLATE_INSN3(Vdq, Vdq, UdqMhq)
 DEF_TRANSLATE_INSN3(Vdq, Vdq, Wdq)
@@ -6683,6 +6690,7 @@ DEF_TRANSLATE_INSN3(Vdq, Vq, Mq)
 DEF_TRANSLATE_INSN3(Vdq, Vq, Wq)
 DEF_TRANSLATE_INSN3(Vdq, Wdq, Ib)
 DEF_TRANSLATE_INSN3(Vq, Vq, Wq)
+DEF_TRANSLATE_INSN3(Vq, Wq, Ib)
 
 #define DEF_TRANSLATE_INSN4(opT1, opT2, opT3, opT4) \
 static void translate_insn4(opT1, opT2, opT3, opT4)(\
@@ -6731,7 +6739,11 @@ DEF_TRANSLATE_INSN3(Vq, Vq, Wq)
 DEF_TRANSLATE_INSN4(Pq, Pq, Qq, Ib)
 DEF_TRANSLATE_INSN4(Pq, Pq, RdMw, Ib)
 DEF_TRANSLATE_INSN4(Vd, Vd, Wd, Ib)
+DEF_TRANSLATE_INSN4(Vdq, Vdq, Ed, Ib)
+DEF_TRANSLATE_INSN4(Vdq, Vdq, Eq, Ib)
+DEF_TRANSLATE_INSN4(Vdq, Vdq, RdMb, Ib)
 DEF_TRANSLATE_INSN4(Vdq, Vdq, RdMw, Ib)
+DEF_TRANSLATE_INSN4(Vdq, Vdq, Wd, Ib)
 DEF_TRANSLATE_INSN4(Vdq, Vdq, Wd, modrm_mod)
 DEF_TRANSLATE_INSN4(Vdq, Vdq, Wdq, Ib)
 DEF_TRANSLATE_INSN4(Vdq, Vdq, Wq, modrm_mod)
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 38/75] target/i386: introduce MMX vector instructions to sse-opcode.inc.h

2019-08-21 Thread Jan Bobek
Add all MMX vector instruction entries to sse-opcode.inc.h.

Signed-off-by: Jan Bobek 
---
 target/i386/sse-opcode.inc.h | 136 +++
 1 file changed, 136 insertions(+)

diff --git a/target/i386/sse-opcode.inc.h b/target/i386/sse-opcode.inc.h
index 04d0c49168..e570d449fc 100644
--- a/target/i386/sse-opcode.inc.h
+++ b/target/i386/sse-opcode.inc.h
@@ -42,6 +42,142 @@
 #   define OPCODE_GRP_END(grpname)
 #endif /* OPCODE_GRP_END */
 
+/*
+ * MMX Instructions
+ * -
+ * NP 0F 6E /r  MOVD mm,r/m32
+ * NP 0F 7E /r  MOVD r/m32,mm
+ * NP REX.W + 0F 6E /r  MOVQ mm,r/m64
+ * NP REX.W + 0F 7E /r  MOVQ r/m64,mm
+ * NP 0F 6F /r  MOVQ mm, mm/m64
+ * NP 0F 7F /r  MOVQ mm/m64, mm
+ * NP 0F FC /r  PADDB mm, mm/m64
+ * NP 0F FD /r  PADDW mm, mm/m64
+ * NP 0F FE /r  PADDD mm, mm/m64
+ * NP 0F EC /r  PADDSB mm, mm/m64
+ * NP 0F ED /r  PADDSW mm, mm/m64
+ * NP 0F DC /r  PADDUSB mm,mm/m64
+ * NP 0F DD /r  PADDUSW mm,mm/m64
+ * NP 0F F8 /r  PSUBB mm, mm/m64
+ * NP 0F F9 /r  PSUBW mm, mm/m64
+ * NP 0F FA /r  PSUBD mm, mm/m64
+ * NP 0F E8 /r  PSUBSB mm, mm/m64
+ * NP 0F E9 /r  PSUBSW mm, mm/m64
+ * NP 0F D8 /r  PSUBUSB mm, mm/m64
+ * NP 0F D9 /r  PSUBUSW mm, mm/m64
+ * NP 0F D5 /r  PMULLW mm, mm/m64
+ * NP 0F E5 /r  PMULHW mm, mm/m64
+ * NP 0F F5 /r  PMADDWD mm, mm/m64
+ * NP 0F 74 /r  PCMPEQB mm,mm/m64
+ * NP 0F 75 /r  PCMPEQW mm,mm/m64
+ * NP 0F 76 /r  PCMPEQD mm,mm/m64
+ * NP 0F 64 /r  PCMPGTB mm,mm/m64
+ * NP 0F 65 /r  PCMPGTW mm,mm/m64
+ * NP 0F 66 /r  PCMPGTD mm,mm/m64
+ * NP 0F DB /r  PAND mm, mm/m64
+ * NP 0F DF /r  PANDN mm, mm/m64
+ * NP 0F EB /r  POR mm, mm/m64
+ * NP 0F EF /r  PXOR mm, mm/m64
+ * NP 0F F1 /r  PSLLW mm, mm/m64
+ * NP 0F F2 /r  PSLLD mm, mm/m64
+ * NP 0F F3 /r  PSLLQ mm, mm/m64
+ * NP 0F D1 /r  PSRLW mm, mm/m64
+ * NP 0F D2 /r  PSRLD mm, mm/m64
+ * NP 0F D3 /r  PSRLQ mm, mm/m64
+ * NP 0F E1 /r  PSRAW mm,mm/m64
+ * NP 0F E2 /r  PSRAD mm,mm/m64
+ * NP 0F 63 /r  PACKSSWB mm1, mm2/m64
+ * NP 0F 6B /r  PACKSSDW mm1, mm2/m64
+ * NP 0F 67 /r  PACKUSWB mm, mm/m64
+ * NP 0F 68 /r  PUNPCKHBW mm, mm/m64
+ * NP 0F 69 /r  PUNPCKHWD mm, mm/m64
+ * NP 0F 6A /r  PUNPCKHDQ mm, mm/m64
+ * NP 0F 60 /r  PUNPCKLBW mm, mm/m32
+ * NP 0F 61 /r  PUNPCKLWD mm, mm/m32
+ * NP 0F 62 /r  PUNPCKLDQ mm, mm/m32
+ * NP 0F 77 EMMS
+ * NP 0F 71 /6 ib   PSLLW mm1, imm8
+ * NP 0F 71 /2 ib   PSRLW mm, imm8
+ * NP 0F 71 /4 ib   PSRAW mm,imm8
+ * NP 0F 72 /6 ib   PSLLD mm, imm8
+ * NP 0F 72 /2 ib   PSRLD mm, imm8
+ * NP 0F 72 /4 ib   PSRAD mm,imm8
+ * NP 0F 73 /6 ib   PSLLQ mm, imm8
+ * NP 0F 73 /2 ib   PSRLQ mm, imm8
+ */
+
+OPCODE(movd, LEG(NP, 0F, 0, 0x6e), MMX, WR, Pq, Ed)
+OPCODE(movd, LEG(NP, 0F, 0, 0x7e), MMX, WR, Ed, Pq)
+OPCODE(movq, LEG(NP, 0F, 1, 0x6e), MMX, WR, Pq, Eq)
+OPCODE(movq, LEG(NP, 0F, 1, 0x7e), MMX, WR, Eq, Pq)
+OPCODE(movq, LEG(NP, 0F, 0, 0x6f), MMX, WR, Pq, Qq)
+OPCODE(movq, LEG(NP, 0F, 0, 0x7f), MMX, WR, Qq, Pq)
+OPCODE(paddb, LEG(NP, 0F, 0, 0xfc), MMX, WRR, Pq, Pq, Qq)
+OPCODE(paddw, LEG(NP, 0F, 0, 0xfd), MMX, WRR, Pq, Pq, Qq)
+OPCODE(paddd, LEG(NP, 0F, 0, 0xfe), MMX, WRR, Pq, Pq, Qq)
+OPCODE(paddsb, LEG(NP, 0F, 0, 0xec), MMX, WRR, Pq, Pq, Qq)
+OPCODE(paddsw, LEG(NP, 0F, 0, 0xed), MMX, WRR, Pq, Pq, Qq)
+OPCODE(paddusb, LEG(NP, 0F, 0, 0xdc), MMX, WRR, Pq, Pq, Qq)
+OPCODE(paddusw, LEG(NP, 0F, 0, 0xdd), MMX, WRR, Pq, Pq, Qq)
+OPCODE(psubb, LEG(NP, 0F, 0, 0xf8), MMX, WRR, Pq, Pq, Qq)
+OPCODE(psubw, LEG(NP, 0F, 0, 0xf9), MMX, WRR, Pq, Pq, Qq)
+OPCODE(psubd, LEG(NP, 0F, 0, 0xfa), MMX, WRR, Pq, Pq, Qq)
+OPCODE(psubsb, LEG(NP, 0F, 0, 0xe8), MMX, WRR, Pq, Pq, Qq)
+OPCODE(psubsw, LEG(NP, 0F, 0, 0xe9), MMX, WRR, Pq, Pq, Qq)
+OPCODE(psubusb, LEG(NP, 0F, 0, 0xd8), MMX, WRR, Pq, Pq, Qq)
+OPCODE(psubusw, LEG(NP, 0F, 0, 0xd9), MMX, WRR, Pq, Pq, Qq)
+OPCODE(pmullw, LEG(NP, 0F, 0, 0xd5), MMX, WRR, Pq, Pq, Qq)
+OPCODE(pmulhw, LEG(NP, 0F, 0, 0xe5), MMX, WRR, Pq, Pq, Qq)
+OPCODE(pmaddwd, LEG(NP, 0F, 0, 0xf5), MMX, WRR, Pq, Pq, Qq)
+OPCODE(pcmpeqb, LEG(NP, 0F, 0, 0x74), MMX, WRR, Pq, Pq, Qq)
+OPCODE(pcmpeqw, LEG(NP, 0F, 0, 0x75), MMX, WRR, Pq, Pq, Qq)
+OPCODE(pcmpeqd, LEG(NP, 0F, 0, 0x76), MMX, WRR, Pq, Pq, Qq)
+OPCODE(pcmpgtb, LEG(NP, 0F, 0, 0x64), MMX, WRR, Pq, Pq, Qq)
+OPCODE(pcmpgtw, LEG(NP, 0F, 0, 0x65), MMX, WRR, Pq, Pq, Qq)
+OPCODE(pcmpgtd, LEG(NP, 0F, 0, 0x66), MMX, WRR, Pq, Pq, Qq)
+OPCODE(pand, LEG(NP, 0F, 0, 0xdb), MMX, WRR, Pq, Pq, Qq)
+OPCODE(pandn, LEG(NP, 0F, 0, 0xdf), MMX, WRR, Pq, Pq, Qq)
+OPCODE(por, LEG(NP, 0F, 0, 0xeb), MMX, WRR, Pq, Pq, Qq)
+OPCODE(pxor, LEG(NP, 0F, 0, 0xef), MMX, WRR, Pq, Pq, Qq)
+OPCODE(psllw, LEG(NP, 0F, 0, 0xf1), MMX, WRR, Pq, Pq, Qq

[Qemu-devel] [RFC PATCH v4 50/75] target/i386: introduce SSSE3 vector instructions to sse-opcode.inc.h

2019-08-21 Thread Jan Bobek
Add all the SSSE3 vector instruction entries to sse-opcode.inc.h.

Signed-off-by: Jan Bobek 
---
 target/i386/sse-opcode.inc.h | 67 
 1 file changed, 67 insertions(+)

diff --git a/target/i386/sse-opcode.inc.h b/target/i386/sse-opcode.inc.h
index 84785a4e04..d8ea71aa6c 100644
--- a/target/i386/sse-opcode.inc.h
+++ b/target/i386/sse-opcode.inc.h
@@ -354,6 +354,41 @@
  * 66 0F 7D /r  HSUBPD xmm1, xmm2/m128
  * F2 0F D0 /r  ADDSUBPS xmm1, xmm2/m128
  * 66 0F D0 /r  ADDSUBPD xmm1, xmm2/m128
+ *
+ * SSSE3 Instructions
+ * ---
+ * NP 0F 38 01 /r  PHADDW mm1, mm2/m64
+ * 66 0F 38 01 /r  PHADDW xmm1, xmm2/m128
+ * NP 0F 38 02 /r  PHADDD mm1, mm2/m64
+ * 66 0F 38 02 /r  PHADDD xmm1, xmm2/m128
+ * NP 0F 38 03 /r  PHADDSW mm1, mm2/m64
+ * 66 0F 38 03 /r  PHADDSW xmm1, xmm2/m128
+ * NP 0F 38 05 /r  PHSUBW mm1, mm2/m64
+ * 66 0F 38 05 /r  PHSUBW xmm1, xmm2/m128
+ * NP 0F 38 06 /r  PHSUBD mm1, mm2/m64
+ * 66 0F 38 06 /r  PHSUBD xmm1, xmm2/m128
+ * NP 0F 38 07 /r  PHSUBSW mm1, mm2/m64
+ * 66 0F 38 07 /r  PHSUBSW xmm1, xmm2/m128
+ * NP 0F 38 0B /r  PMULHRSW mm1, mm2/m64
+ * 66 0F 38 0B /r  PMULHRSW xmm1, xmm2/m128
+ * NP 0F 38 04 /r  PMADDUBSW mm1, mm2/m64
+ * 66 0F 38 04 /r  PMADDUBSW xmm1, xmm2/m128
+ * NP 0F 38 1C /r  PABSB mm1, mm2/m64
+ * 66 0F 38 1C /r  PABSB xmm1, xmm2/m128
+ * NP 0F 38 1D /r  PABSW mm1, mm2/m64
+ * 66 0F 38 1D /r  PABSW xmm1, xmm2/m128
+ * NP 0F 38 1E /r  PABSD mm1, mm2/m64
+ * 66 0F 38 1E /r  PABSD xmm1, xmm2/m128
+ * NP 0F 38 08 /r  PSIGNB mm1, mm2/m64
+ * 66 0F 38 08 /r  PSIGNB xmm1, xmm2/m128
+ * NP 0F 38 09 /r  PSIGNW mm1, mm2/m64
+ * 66 0F 38 09 /r  PSIGNW xmm1, xmm2/m128
+ * NP 0F 38 0A /r  PSIGND mm1, mm2/m64
+ * 66 0F 38 0A /r  PSIGND xmm1, xmm2/m128
+ * NP 0F 3A 0F /r ib   PALIGNR mm1, mm2/m64, imm8
+ * 66 0F 3A 0F /r ib   PALIGNR xmm1, xmm2/m128, imm8
+ * NP 0F 38 00 /r  PSHUFB mm1, mm2/m64
+ * 66 0F 38 00 /r  PSHUFB xmm1, xmm2/m128
  */
 
 OPCODE(movd, LEG(NP, 0F, 0, 0x6e), MMX, WR, Pq, Ed)
@@ -426,6 +461,12 @@ OPCODE(addps, LEG(NP, 0F, 0, 0x58), SSE, WRR, Vdq, Vdq, 
Wdq)
 OPCODE(addpd, LEG(66, 0F, 0, 0x58), SSE2, WRR, Vdq, Vdq, Wdq)
 OPCODE(addss, LEG(F3, 0F, 0, 0x58), SSE, WRR, Vd, Vd, Wd)
 OPCODE(addsd, LEG(F2, 0F, 0, 0x58), SSE2, WRR, Vq, Vq, Wq)
+OPCODE(phaddw, LEG(NP, 0F38, 0, 0x01), SSSE3, WRR, Pq, Pq, Qq)
+OPCODE(phaddw, LEG(66, 0F38, 0, 0x01), SSSE3, WRR, Vdq, Vdq, Wdq)
+OPCODE(phaddd, LEG(NP, 0F38, 0, 0x02), SSSE3, WRR, Pq, Pq, Qq)
+OPCODE(phaddd, LEG(66, 0F38, 0, 0x02), SSSE3, WRR, Vdq, Vdq, Wdq)
+OPCODE(phaddsw, LEG(NP, 0F38, 0, 0x03), SSSE3, WRR, Pq, Pq, Qq)
+OPCODE(phaddsw, LEG(66, 0F38, 0, 0x03), SSSE3, WRR, Vdq, Vdq, Wdq)
 OPCODE(haddps, LEG(F2, 0F, 0, 0x7c), SSE3, WRR, Vdq, Vdq, Wdq)
 OPCODE(haddpd, LEG(66, 0F, 0, 0x7c), SSE3, WRR, Vdq, Vdq, Wdq)
 OPCODE(psubb, LEG(NP, 0F, 0, 0xf8), MMX, WRR, Pq, Pq, Qq)
@@ -448,6 +489,12 @@ OPCODE(subps, LEG(NP, 0F, 0, 0x5c), SSE, WRR, Vdq, Vdq, 
Wdq)
 OPCODE(subpd, LEG(66, 0F, 0, 0x5c), SSE2, WRR, Vdq, Vdq, Wdq)
 OPCODE(subss, LEG(F3, 0F, 0, 0x5c), SSE, WRR, Vd, Vd, Wd)
 OPCODE(subsd, LEG(F2, 0F, 0, 0x5c), SSE2, WRR, Vq, Vq, Wq)
+OPCODE(phsubw, LEG(NP, 0F38, 0, 0x05), SSSE3, WRR, Pq, Pq, Qq)
+OPCODE(phsubw, LEG(66, 0F38, 0, 0x05), SSSE3, WRR, Vdq, Vdq, Wdq)
+OPCODE(phsubd, LEG(NP, 0F38, 0, 0x06), SSSE3, WRR, Pq, Pq, Qq)
+OPCODE(phsubd, LEG(66, 0F38, 0, 0x06), SSSE3, WRR, Vdq, Vdq, Wdq)
+OPCODE(phsubsw, LEG(NP, 0F38, 0, 0x07), SSSE3, WRR, Pq, Pq, Qq)
+OPCODE(phsubsw, LEG(66, 0F38, 0, 0x07), SSSE3, WRR, Vdq, Vdq, Wdq)
 OPCODE(hsubps, LEG(F2, 0F, 0, 0x7d), SSE3, WRR, Vdq, Vdq, Wdq)
 OPCODE(hsubpd, LEG(66, 0F, 0, 0x7d), SSE3, WRR, Vdq, Vdq, Wdq)
 OPCODE(addsubps, LEG(F2, 0F, 0, 0xd0), SSE3, WRR, Vdq, Vdq, Wdq)
@@ -460,12 +507,16 @@ OPCODE(pmulhuw, LEG(NP, 0F, 0, 0xe4), SSE, WRR, Pq, Pq, 
Qq)
 OPCODE(pmulhuw, LEG(66, 0F, 0, 0xe4), SSE2, WRR, Vdq, Vdq, Wdq)
 OPCODE(pmuludq, LEG(NP, 0F, 0, 0xf4), SSE2, WRR, Pq, Pq, Qq)
 OPCODE(pmuludq, LEG(66, 0F, 0, 0xf4), SSE2, WRR, Vdq, Vdq, Wdq)
+OPCODE(pmulhrsw, LEG(NP, 0F38, 0, 0x0b), SSSE3, WRR, Pq, Pq, Qq)
+OPCODE(pmulhrsw, LEG(66, 0F38, 0, 0x0b), SSSE3, WRR, Vdq, Vdq, Wdq)
 OPCODE(mulps, LEG(NP, 0F, 0, 0x59), SSE, WRR, Vdq, Vdq, Wdq)
 OPCODE(mulpd, LEG(66, 0F, 0, 0x59), SSE2, WRR, Vdq, Vdq, Wdq)
 OPCODE(mulss, LEG(F3, 0F, 0, 0x59), SSE, WRR, Vd, Vd, Wd)
 OPCODE(mulsd, LEG(F2, 0F, 0, 0x59), SSE2, WRR, Vq, Vq, Wq)
 OPCODE(pmaddwd, LEG(NP, 0F, 0, 0xf5), MMX, WRR, Pq, Pq, Qq)
 OPCODE(pmaddwd, LEG(66, 0F, 0, 0xf5), SSE2, WRR, Vdq, Vdq, Wdq)
+OPCODE(pmaddubsw, LEG(NP, 0F38, 0, 0x04), SSSE3, WRR, Pq, Pq, Qq)
+OPCODE(pmaddubsw, LEG(66, 0F38, 0, 0x04), SSSE3, WRR, Vdq, Vdq, Wdq)
 OPCODE(divps, LEG(NP, 0F, 0, 0x5e), SSE, WRR, Vdq, Vdq, Wdq)
 OPCODE(divpd, LEG(66, 0F, 0, 0x5e), SSE2, WRR

[Qemu-devel] [RFC PATCH v4 52/75] target/i386: introduce SSE4.1 code generators

2019-08-21 Thread Jan Bobek
Introduce code generators required by SSE4.1 instructions.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 101 
 1 file changed, 101 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 110b963215..3ff063b701 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -5919,10 +5919,12 @@ DEF_GEN_INSN3_HELPER_EPP(addsubpd, addsubpd, Vdq, Vdq, 
Wdq)
 
 DEF_GEN_INSN3_HELPER_EPP(pmullw, pmullw_mmx, Pq, Pq, Qq)
 DEF_GEN_INSN3_HELPER_EPP(pmullw, pmullw_xmm, Vdq, Vdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(pmulld, pmulld_xmm, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(pmulhw, pmulhw_mmx, Pq, Pq, Qq)
 DEF_GEN_INSN3_HELPER_EPP(pmulhw, pmulhw_xmm, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(pmulhuw, pmulhuw_mmx, Pq, Pq, Qq)
 DEF_GEN_INSN3_HELPER_EPP(pmulhuw, pmulhuw_xmm, Vdq, Vdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(pmuldq, pmuldq_xmm, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(pmuludq, pmuludq_mmx, Pq, Pq, Qq)
 DEF_GEN_INSN3_HELPER_EPP(pmuludq, pmuludq_xmm, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(pmulhrsw, pmulhrsw_mmx, Pq, Pq, Qq)
@@ -5952,16 +5954,25 @@ DEF_GEN_INSN2_HELPER_EPP(rsqrtss, rsqrtss, Vd, Wd)
 
 DEF_GEN_INSN3_GVEC(pminub, Pq, Pq, Qq, umin, MM_OPRSZ, MM_MAXSZ, MO_8)
 DEF_GEN_INSN3_GVEC(pminub, Vdq, Vdq, Wdq, umin, XMM_OPRSZ, XMM_MAXSZ, MO_8)
+DEF_GEN_INSN3_GVEC(pminuw, Vdq, Vdq, Wdq, umin, XMM_OPRSZ, XMM_MAXSZ, MO_16)
+DEF_GEN_INSN3_GVEC(pminud, Vdq, Vdq, Wdq, umin, XMM_OPRSZ, XMM_MAXSZ, MO_32)
+DEF_GEN_INSN3_GVEC(pminsb, Vdq, Vdq, Wdq, smin, XMM_OPRSZ, XMM_MAXSZ, MO_8)
 DEF_GEN_INSN3_GVEC(pminsw, Pq, Pq, Qq, smin, MM_OPRSZ, MM_MAXSZ, MO_16)
 DEF_GEN_INSN3_GVEC(pminsw, Vdq, Vdq, Wdq, smin, XMM_OPRSZ, XMM_MAXSZ, MO_16)
+DEF_GEN_INSN3_GVEC(pminsd, Vdq, Vdq, Wdq, smin, XMM_OPRSZ, XMM_MAXSZ, MO_32)
 DEF_GEN_INSN3_HELPER_EPP(minps, minps, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(minpd, minpd, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(minss, minss, Vd, Vd, Wd)
 DEF_GEN_INSN3_HELPER_EPP(minsd, minsd, Vq, Vq, Wq)
+DEF_GEN_INSN2_HELPER_EPP(phminposuw, phminposuw_xmm, Vdq, Wdq)
 DEF_GEN_INSN3_GVEC(pmaxub, Pq, Pq, Qq, umax, MM_OPRSZ, MM_MAXSZ, MO_8)
 DEF_GEN_INSN3_GVEC(pmaxub, Vdq, Vdq, Wdq, umax, XMM_OPRSZ, XMM_MAXSZ, MO_8)
+DEF_GEN_INSN3_GVEC(pmaxuw, Vdq, Vdq, Wdq, umax, XMM_OPRSZ, XMM_MAXSZ, MO_16)
+DEF_GEN_INSN3_GVEC(pmaxud, Vdq, Vdq, Wdq, umax, XMM_OPRSZ, XMM_MAXSZ, MO_32)
+DEF_GEN_INSN3_GVEC(pmaxsb, Vdq, Vdq, Wdq, smax, XMM_OPRSZ, XMM_MAXSZ, MO_8)
 DEF_GEN_INSN3_GVEC(pmaxsw, Pq, Pq, Qq, smax, MM_OPRSZ, MM_MAXSZ, MO_16)
 DEF_GEN_INSN3_GVEC(pmaxsw, Vdq, Vdq, Wdq, smax, XMM_OPRSZ, XMM_MAXSZ, MO_16)
+DEF_GEN_INSN3_GVEC(pmaxsd, Vdq, Vdq, Wdq, smax, XMM_OPRSZ, XMM_MAXSZ, MO_32)
 DEF_GEN_INSN3_HELPER_EPP(maxps, maxps, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(maxpd, maxpd, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(maxss, maxss, Vd, Vd, Wd)
@@ -5972,6 +5983,7 @@ DEF_GEN_INSN3_HELPER_EPP(pavgw, pavgw_mmx, Pq, Pq, Qq)
 DEF_GEN_INSN3_HELPER_EPP(pavgw, pavgw_xmm, Vdq, Vdq, Wdq)
 DEF_GEN_INSN3_HELPER_EPP(psadbw, psadbw_mmx, Pq, Pq, Qq)
 DEF_GEN_INSN3_HELPER_EPP(psadbw, psadbw_xmm, Vdq, Vdq, Wdq)
+DEF_GEN_INSN4_HELPER_EPPI(mpsadbw, mpsadbw_xmm, Vdq, Vdq, Wdq, Ib)
 DEF_GEN_INSN2_HELPER_EPP(pabsb, pabsb_mmx, Pq, Qq)
 DEF_GEN_INSN2_HELPER_EPP(pabsb, pabsb_xmm, Vdq, Wdq)
 DEF_GEN_INSN2_HELPER_EPP(pabsw, pabsw_mmx, Pq, Qq)
@@ -5985,12 +5997,20 @@ DEF_GEN_INSN3_HELPER_EPP(psignw, psignw_xmm, Vdq, Vdq, 
Wdq)
 DEF_GEN_INSN3_HELPER_EPP(psignd, psignd_mmx, Pq, Pq, Qq)
 DEF_GEN_INSN3_HELPER_EPP(psignd, psignd_xmm, Vdq, Vdq, Wdq)
 
+DEF_GEN_INSN4_HELPER_EPPI(dpps, dpps_xmm, Vdq, Vdq, Wdq, Ib)
+DEF_GEN_INSN4_HELPER_EPPI(dppd, dppd_xmm, Vdq, Vdq, Wdq, Ib)
+DEF_GEN_INSN3_HELPER_EPPI(roundps, roundps_xmm, Vdq, Wdq, Ib)
+DEF_GEN_INSN3_HELPER_EPPI(roundpd, roundpd_xmm, Vdq, Wdq, Ib)
+DEF_GEN_INSN3_HELPER_EPPI(roundss, roundss_xmm, Vd, Wd, Ib)
+DEF_GEN_INSN3_HELPER_EPPI(roundsd, roundsd_xmm, Vq, Wq, Ib)
+
 DEF_GEN_INSN3_GVEC(pcmpeqb, Pq, Pq, Qq, cmp, MM_OPRSZ, MM_MAXSZ, MO_8, 
TCG_COND_EQ)
 DEF_GEN_INSN3_GVEC(pcmpeqb, Vdq, Vdq, Wdq, cmp, XMM_OPRSZ, XMM_MAXSZ, MO_8, 
TCG_COND_EQ)
 DEF_GEN_INSN3_GVEC(pcmpeqw, Pq, Pq, Qq, cmp, MM_OPRSZ, MM_MAXSZ, MO_16, 
TCG_COND_EQ)
 DEF_GEN_INSN3_GVEC(pcmpeqw, Vdq, Vdq, Wdq, cmp, XMM_OPRSZ, XMM_MAXSZ, MO_16, 
TCG_COND_EQ)
 DEF_GEN_INSN3_GVEC(pcmpeqd, Pq, Pq, Qq, cmp, MM_OPRSZ, MM_MAXSZ, MO_32, 
TCG_COND_EQ)
 DEF_GEN_INSN3_GVEC(pcmpeqd, Vdq, Vdq, Wdq, cmp, XMM_OPRSZ, XMM_MAXSZ, MO_32, 
TCG_COND_EQ)
+DEF_GEN_INSN3_GVEC(pcmpeqq, Vdq, Vdq, Wdq, cmp, XMM_OPRSZ, XMM_MAXSZ, MO_64, 
TCG_COND_EQ)
 DEF_GEN_INSN3_GVEC(pcmpgtb, Pq, Pq, Qq, cmp, MM_OPRSZ, MM_MAXSZ, MO_8, 
TCG_COND_GT)
 DEF_GEN_INSN3_GVEC(pcmpgtb, Vdq, Vdq, Wdq, cmp, XMM_OPRSZ, XMM_MAXSZ, MO_8, 
TCG_COND_GT)
 DEF_GEN_INSN3_GVEC(pcmpgtw, Pq, Pq, Qq, cmp, MM_OPRSZ, MM_MAXSZ, MO_16, 
TCG_COND_GT)
@@ -5998,6 +6018,8 @@ DEF_GEN_INSN3_GVEC(pcmpgtw, Vdq, Vdq, Wdq, cmp, 
XMM_OPRSZ, XMM_MAXSZ, MO_16, TCG
 DEF_GEN_INSN3_GVEC(pcmpgtd, Pq, Pq, Qq, cmp, MM_OPRSZ, MM_MAXSZ, MO_32, 
TCG_COND_GT

[Qemu-devel] [RFC PATCH v4 35/75] target/i386: introduce instruction translator macros

2019-08-21 Thread Jan Bobek
Instruction "translators" are responsible for decoding and loading
instruction operands, calling the passed-in code generator, and
storing the operands back (if applicable). Once a translator returns,
the instruction has been translated to TCG ops, hence the name.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 272 
 1 file changed, 272 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index eab36963c3..1c2502ff50 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -5562,6 +5562,262 @@ INSNOP_LDST(xmm, Mhq)
 gen_gvec_ ## gvec(arg1, arg2, arg3, arg4, ## __VA_ARGS__);  \
 }
 
+/*
+ * Instruction translators
+ */
+#define translate_insn(argc, ...)   \
+glue(translate_insn, argc)(__VA_ARGS__)
+#define translate_insn0()   \
+translate_insn_0
+#define translate_insn1(opT1)   \
+translate_insn_1 ## opT1
+#define translate_insn2(opT1, opT2) \
+translate_insn_2 ## opT1 ## opT2
+#define translate_insn3(opT1, opT2, opT3)   \
+translate_insn_3 ## opT1 ## opT2 ## opT3
+#define translate_insn4(opT1, opT2, opT3, opT4) \
+translate_insn_4 ## opT1 ## opT2 ## opT3 ## opT4
+#define translate_insn5(opT1, opT2, opT3, opT4, opT5)   \
+translate_insn_5 ## opT1 ## opT2 ## opT3 ## opT4 ## opT5
+#define translate_group(grpname)\
+translate_group_ ## grpname
+
+static void translate_insn0()(
+CPUX86State *env, DisasContext *s, int modrm,
+CheckCpuidFeat feat, unsigned int argc_wr,
+void (*gen_insn_fp)(CPUX86State *, DisasContext *))
+{
+if (!check_cpuid(env, s, feat)) {
+gen_illegal_opcode(s);
+return;
+}
+
+(*gen_insn_fp)(env, s);
+}
+
+#define DEF_TRANSLATE_INSN1(opT1)   \
+static void translate_insn1(opT1)(  \
+CPUX86State *env, DisasContext *s, int modrm,   \
+CheckCpuidFeat feat, unsigned int argc_wr,  \
+void (*gen_insn1_fp)(CPUX86State *, DisasContext *, \
+ insnop_arg_t(opT1)))   \
+{   \
+insnop_ctxt_t(opT1) ctxt1;  \
+\
+const bool is_write1 = (1 <= argc_wr);  \
+\
+if (check_cpuid(env, s, feat)   \
+&& insnop_init(opT1)(, env, s, modrm, is_write1)) {   \
+\
+const insnop_arg_t(opT1) arg1 = \
+insnop_prepare(opT1)(, env, s, modrm, is_write1); \
+\
+(*gen_insn1_fp)(env, s, arg1);  \
+\
+insnop_finalize(opT1)(, env, s, modrm, is_write1, arg1); \
+} else {\
+gen_illegal_opcode(s);  \
+}   \
+}
+
+#define DEF_TRANSLATE_INSN2(opT1, opT2) \
+static void translate_insn2(opT1, opT2)(\
+CPUX86State *env, DisasContext *s, int modrm,   \
+CheckCpuidFeat feat, unsigned int argc_wr,  \
+void (*gen_insn2_fp)(CPUX86State *, DisasContext *, \
+ insnop_arg_t(opT1), insnop_arg_t(opT2)))   \
+{   \
+insnop_ctxt_t(opT1) ctxt1;  \
+insnop_ctxt_t(opT2) ctxt2;  \
+\
+const bool is_write1 = (1 <= argc_wr);  \
+const bool is_write2 = (2 <= argc_wr);  \
+\
+if (check_cpuid(env, s, feat)   \
+&& insnop_init(opT1)(, env, s, modrm, is_write1)  \
+&& insnop_init(opT2)(, env, s, modrm, is_write2)) {   \
+\
+const insnop_arg_t(opT1) arg1 = \
+insnop_prepare(opT1)(, env, s, modrm, is_write1); \

[Qemu-devel] [RFC PATCH v4 54/75] target/i386: introduce SSE4.2 code generators

2019-08-21 Thread Jan Bobek
Introduce code generators required by SSE4.2 instructions.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 3ff063b701..f3b047c0df 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -6017,6 +6017,12 @@ DEF_GEN_INSN3_GVEC(pcmpgtw, Pq, Pq, Qq, cmp, MM_OPRSZ, 
MM_MAXSZ, MO_16, TCG_COND
 DEF_GEN_INSN3_GVEC(pcmpgtw, Vdq, Vdq, Wdq, cmp, XMM_OPRSZ, XMM_MAXSZ, MO_16, 
TCG_COND_GT)
 DEF_GEN_INSN3_GVEC(pcmpgtd, Pq, Pq, Qq, cmp, MM_OPRSZ, MM_MAXSZ, MO_32, 
TCG_COND_GT)
 DEF_GEN_INSN3_GVEC(pcmpgtd, Vdq, Vdq, Wdq, cmp, XMM_OPRSZ, XMM_MAXSZ, MO_32, 
TCG_COND_GT)
+DEF_GEN_INSN3_GVEC(pcmpgtq, Vdq, Vdq, Wdq, cmp, XMM_OPRSZ, XMM_MAXSZ, MO_64, 
TCG_COND_GT)
+
+DEF_GEN_INSN3_HELPER_EPPI(pcmpestrm, pcmpestrm_xmm, Vdq, Wdq, Ib)
+DEF_GEN_INSN3_HELPER_EPPI(pcmpestri, pcmpestri_xmm, Vdq, Wdq, Ib)
+DEF_GEN_INSN3_HELPER_EPPI(pcmpistrm, pcmpistrm_xmm, Vdq, Wdq, Ib)
+DEF_GEN_INSN3_HELPER_EPPI(pcmpistri, pcmpistri_xmm, Vdq, Wdq, Ib)
 
 DEF_GEN_INSN2_HELPER_EPP(ptest, ptest_xmm, Vdq, Wdq)
 
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 44/75] target/i386: introduce SSE2 vector instructions to sse-opcode.inc.h

2019-08-21 Thread Jan Bobek
Add all the SSE2 vector instruction entries to sse-opcode.inc.h.

Signed-off-by: Jan Bobek 
---
 target/i386/sse-opcode.inc.h | 326 ++-
 1 file changed, 325 insertions(+), 1 deletion(-)

diff --git a/target/i386/sse-opcode.inc.h b/target/i386/sse-opcode.inc.h
index 92581703cd..6df5fda010 100644
--- a/target/i386/sse-opcode.inc.h
+++ b/target/i386/sse-opcode.inc.h
@@ -183,127 +183,434 @@
  * 0F 18 /2 PREFETCHT1 m8
  * 0F 18 /3 PREFETCHT2 m8
  * 0F 18 /0 PREFETCHNTA m8
+ *
+ * SSE2 Instructions
+ * --
+ * 66 0F 6E /r  MOVD xmm,r/m32
+ * 66 0F 7E /r  MOVD r/m32,xmm
+ * 66 REX.W 0F 6E /rMOVQ xmm,r/m64
+ * 66 REX.W 0F 7E /rMOVQ r/m64,xmm
+ * F3 0F 7E /r  MOVQ xmm1, xmm2/m64
+ * 66 0F D6 /r  MOVQ xmm2/m64, xmm1
+ * 66 0F 28 /r  MOVAPD xmm1, xmm2/m128
+ * 66 0F 29 /r  MOVAPD xmm2/m128, xmm1
+ * 66 0F 6F /r  MOVDQA xmm1, xmm2/m128
+ * 66 0F 7F /r  MOVDQA xmm2/m128, xmm1
+ * 66 0F 10 /r  MOVUPD xmm1, xmm2/m128
+ * 66 0F 11 /r  MOVUPD xmm2/m128, xmm1
+ * F3 0F 6F /r  MOVDQU xmm1,xmm2/m128
+ * F3 0F 7F /r  MOVDQU xmm2/m128,xmm1
+ * F2 0F 10 /r  MOVSD xmm1, xmm2/m64
+ * F2 0F 11 /r  MOVSD xmm1/m64, xmm2
+ * F3 0F D6 /r  MOVQ2DQ xmm, mm
+ * F2 0F D6 /r  MOVDQ2Q mm, xmm
+ * 66 0F 12 /r  MOVLPD xmm1,m64
+ * 66 0F 13 /r  MOVLPD m64,xmm1
+ * 66 0F 16 /r  MOVHPD xmm1, m64
+ * 66 0F 17 /r  MOVHPD m64, xmm1
+ * 66 0F D7 /r  PMOVMSKB r32, xmm
+ * 66 REX.W 0F D7 /rPMOVMSKB r64, xmm
+ * 66 0F 50 /r  MOVMSKPD r32, xmm
+ * 66 REX.W 0F 50 /rMOVMSKPD r64, xmm
+ * 66 0F FC /r  PADDB xmm1, xmm2/m128
+ * 66 0F FD /r  PADDW xmm1, xmm2/m128
+ * 66 0F FE /r  PADDD xmm1, xmm2/m128
+ * NP 0F D4 /r  PADDQ mm, mm/m64
+ * 66 0F D4 /r  PADDQ xmm1, xmm2/m128
+ * 66 0F EC /r  PADDSB xmm1, xmm2/m128
+ * 66 0F ED /r  PADDSW xmm1, xmm2/m128
+ * 66 0F DC /r  PADDUSB xmm1,xmm2/m128
+ * 66 0F DD /r  PADDUSW xmm1,xmm2/m128
+ * 66 0F 58 /r  ADDPD xmm1, xmm2/m128
+ * F2 0F 58 /r  ADDSD xmm1, xmm2/m64
+ * 66 0F F8 /r  PSUBB xmm1, xmm2/m128
+ * 66 0F F9 /r  PSUBW xmm1, xmm2/m128
+ * 66 0F FA /r  PSUBD xmm1, xmm2/m128
+ * NP 0F FB /r  PSUBQ mm1, mm2/m64
+ * 66 0F FB /r  PSUBQ xmm1, xmm2/m128
+ * 66 0F E8 /r  PSUBSB xmm1, xmm2/m128
+ * 66 0F E9 /r  PSUBSW xmm1, xmm2/m128
+ * 66 0F D8 /r  PSUBUSB xmm1, xmm2/m128
+ * 66 0F D9 /r  PSUBUSW xmm1, xmm2/m128
+ * 66 0F 5C /r  SUBPD xmm1, xmm2/m128
+ * F2 0F 5C /r  SUBSD xmm1, xmm2/m64
+ * 66 0F D5 /r  PMULLW xmm1, xmm2/m128
+ * 66 0F E5 /r  PMULHW xmm1, xmm2/m128
+ * 66 0F E4 /r  PMULHUW xmm1, xmm2/m128
+ * NP 0F F4 /r  PMULUDQ mm1, mm2/m64
+ * 66 0F F4 /r  PMULUDQ xmm1, xmm2/m128
+ * 66 0F 59 /r  MULPD xmm1, xmm2/m128
+ * F2 0F 59 /r  MULSD xmm1,xmm2/m64
+ * 66 0F F5 /r  PMADDWD xmm1, xmm2/m128
+ * 66 0F 5E /r  DIVPD xmm1, xmm2/m128
+ * F2 0F 5E /r  DIVSD xmm1, xmm2/m64
+ * 66 0F 51 /r  SQRTPD xmm1, xmm2/m128
+ * F2 0F 51 /r  SQRTSD xmm1,xmm2/m64
+ * 66 0F DA /r  PMINUB xmm1, xmm2/m128
+ * 66 0F EA /r  PMINSW xmm1, xmm2/m128
+ * 66 0F 5D /r  MINPD xmm1, xmm2/m128
+ * F2 0F 5D /r  MINSD xmm1, xmm2/m64
+ * 66 0F DE /r  PMAXUB xmm1, xmm2/m128
+ * 66 0F EE /r  PMAXSW xmm1, xmm2/m128
+ * 66 0F 5F /r  MAXPD xmm1, xmm2/m128
+ * F2 0F 5F /r  MAXSD xmm1, xmm2/m64
+ * 66 0F E0 /r  PAVGB xmm1, xmm2/m128
+ * 66 0F E3 /r  PAVGW xmm1, xmm2/m128
+ * 66 0F F6 /r  PSADBW xmm1, xmm2/m128
+ * 66 0F 74 /r  PCMPEQB xmm1,xmm2/m128
+ * 66 0F 75 /r  PCMPEQW xmm1,xmm2/m128
+ * 66 0F 76 /r  PCMPEQD xmm1,xmm2/m128
+ * 66 0F 64 /r  PCMPGTB xmm1,xmm2/m128
+ * 66 0F 65 /r  PCMPGTW xmm1,xmm2/m128
+ * 66 0F 66 /r  PCMPGTD xmm1,xmm2/m128
+ * 66 0F C2 /r ib   CMPPD xmm1, xmm2/m128, imm8
+ * F2 0F C2 /r ib   CMPSD xmm1, xmm2/m64, imm8
+ * 66 0F 2E /r  UCOMISD xmm1, xmm2/m64
+ * 66 0F 2F /r  COMISD xmm1, xmm2/m64
+ * 66 0F DB /r  PAND xmm1, xmm2/m128
+ * 66 0F 54 /r  ANDPD xmm1, xmm2/m128
+ * 66 0F DF /r  PANDN xmm1, xmm2/m128
+ * 66 0F 55 /r  ANDNPD xmm1, xmm2/m128
+ * 66 0F EB /r  POR xmm1, xmm2/m128
+ * 66 0F 56 /r  ORPD xmm1, xmm2/m128
+ * 66 0F EF /r  PXOR xmm1, xmm2/m128
+ * 66 0F 57 /r  XORPD xmm1, xmm2/m128
+ * 66 0F F1 /r  PSLLW xmm1, xmm2/m128
+ * 66 0F F2 /r  PSLLD xmm1, xmm2/m128
+ * 66 0F F3 /r  PSLLQ xmm1, xmm2/m128
+ * 66 0F D1 /r  PSRLW xmm1, xmm2/m128
+ * 66 0F D2 /r  PSRLD xmm1, xmm2/m128
+ * 66 0F D3 /r  PSRLQ xmm1, xmm2/m128

[Qemu-devel] [RFC PATCH v4 36/75] target/i386: introduce MMX translators

2019-08-21 Thread Jan Bobek
Use the translator macros to define instruction translators required
by MMX instructions.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 1c2502ff50..96ba0f5704 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -5651,6 +5651,13 @@ static void translate_insn0()(
 }   \
 }
 
+DEF_TRANSLATE_INSN2(Ed, Pq)
+DEF_TRANSLATE_INSN2(Eq, Pq)
+DEF_TRANSLATE_INSN2(Pq, Ed)
+DEF_TRANSLATE_INSN2(Pq, Eq)
+DEF_TRANSLATE_INSN2(Pq, Qq)
+DEF_TRANSLATE_INSN2(Qq, Pq)
+
 #define DEF_TRANSLATE_INSN3(opT1, opT2, opT3)   \
 static void translate_insn3(opT1, opT2, opT3)(  \
 CPUX86State *env, DisasContext *s, int modrm,   \
@@ -5689,6 +5696,10 @@ static void translate_insn0()(
 }   \
 }
 
+DEF_TRANSLATE_INSN3(Nq, Nq, Ib)
+DEF_TRANSLATE_INSN3(Pq, Pq, Qd)
+DEF_TRANSLATE_INSN3(Pq, Pq, Qq)
+
 #define DEF_TRANSLATE_INSN4(opT1, opT2, opT3, opT4) \
 static void translate_insn4(opT1, opT2, opT3, opT4)(\
 CPUX86State *env, DisasContext *s, int modrm,   \
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 34/75] target/i386: introduce sse-opcode.inc.h

2019-08-21 Thread Jan Bobek
This header is intended to eventually list all supported instructions
along with some useful details (e.g. mnemonics, opcode, operands etc.)
It shall be used (along with some preprocessor magic) anytime we need
to automatically generate code for every instruction.

Signed-off-by: Jan Bobek 
---
 target/i386/sse-opcode.inc.h | 75 
 1 file changed, 75 insertions(+)
 create mode 100644 target/i386/sse-opcode.inc.h

diff --git a/target/i386/sse-opcode.inc.h b/target/i386/sse-opcode.inc.h
new file mode 100644
index 00..04d0c49168
--- /dev/null
+++ b/target/i386/sse-opcode.inc.h
@@ -0,0 +1,75 @@
+#define FMTI  (0, 0, 0, )
+#define FMTI__R__ (1, 1, 0, r)
+#define FMTI__RR__(2, 2, 0, rr)
+#define FMTI__RRR__   (3, 3, 0, rrr)
+#define FMTI__W__ (1, 0, 1, w)
+#define FMTI__WR__(2, 1, 1, wr)
+#define FMTI__WRR__   (3, 2, 1, wrr)
+#define FMTI__WRRR__  (4, 3, 1, wrrr)
+#define FMTI__W__ (5, 4, 1, w)
+#define FMTI__WWRRR__ (5, 3, 2, wwrrr)
+
+#define FMTI__(prop, fmti) FMTI_ ## prop ## __ fmti
+
+#define FMTI_ARGC__(argc, argc_rd, argc_wr, lower)argc
+#define FMTI_ARGC_RD__(argc, argc_rd, argc_wr, lower) argc_rd
+#define FMTI_ARGC_WR__(argc, argc_rd, argc_wr, lower) argc_wr
+#define FMTI_LOWER__(argc, argc_rd, argc_wr, lower)   lower
+
+#define FMT_ARGC(fmt)FMTI__(ARGC, FMTI__ ## fmt ## __)
+#define FMT_ARGC_RD(fmt) FMTI__(ARGC_RD, FMTI__ ## fmt ## __)
+#define FMT_ARGC_WR(fmt) FMTI__(ARGC_WR, FMTI__ ## fmt ## __)
+#define FMT_LOWER(fmt)   FMTI__(LOWER, FMTI__ ## fmt ## __)
+#define FMT_UPPER(fmt)   fmt
+
+#ifndef OPCODE
+#   define OPCODE(mnem, opcode, feat, fmt, ...)
+#endif /* OPCODE */
+
+#ifndef OPCODE_GRP
+#   define OPCODE_GRP(grpname, opcode)
+#endif /* OPCODE_GRP */
+
+#ifndef OPCODE_GRP_BEGIN
+#   define OPCODE_GRP_BEGIN(grpname)
+#endif /* OPCODE_GRP_BEGIN */
+
+#ifndef OPCODE_GRPMEMB
+#   define OPCODE_GRPMEMB(grpname, mnem, opcode, feat, fmt, ...)
+#endif /* OPCODE_GRPMEMB */
+
+#ifndef OPCODE_GRP_END
+#   define OPCODE_GRP_END(grpname)
+#endif /* OPCODE_GRP_END */
+
+#undef FMTI
+#undef FMTI__R__
+#undef FMTI__RR__
+#undef FMTI__RRR__
+#undef FMTI__W__
+#undef FMTI__WR__
+#undef FMTI__WRR__
+#undef FMTI__WRRR__
+#undef FMTI__W__
+#undef FMTI__WWRRR__
+
+#undef FMTI__
+
+#undef FMTI_ARGC__
+#undef FMTI_ARGC_RD__
+#undef FMTI_ARGC_WR__
+#undef FMTI_LOWER__
+
+#undef FMT_ARGC
+#undef FMT_ARGC_RD
+#undef FMT_ARGC_WR
+#undef FMT_LOWER
+#undef FMT_UPPER
+
+#undef LEG
+#undef VEX
+#undef OPCODE
+#undef OPCODE_GRP
+#undef OPCODE_GRP_BEGIN
+#undef OPCODE_GRPMEMB
+#undef OPCODE_GRP_END
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 31/75] target/i386: introduce code generators

2019-08-21 Thread Jan Bobek
In this context, "code generators" are functions that receive decoded
instruction operands and emit TCG ops implementing the correct
instruction functionality. Introduce the naming macros first, actual
generator macros will be added later.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 46 +
 1 file changed, 46 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 2e78bed78f..603a5b80a1 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -5331,6 +5331,52 @@ INSNOP_LDST(xmm, Mhq)
 tcg_temp_free_i64(r64);
 }
 
+/*
+ * Code generators
+ */
+#define gen_insn(mnem, argc, ...)   \
+glue(gen_insn, argc)(mnem, ## __VA_ARGS__)
+#define gen_insn0(mnem) \
+gen_ ## mnem ## _0
+#define gen_insn1(mnem, opT1)   \
+gen_ ## mnem ## _1 ## opT1
+#define gen_insn2(mnem, opT1, opT2) \
+gen_ ## mnem ## _2 ## opT1 ## opT2
+#define gen_insn3(mnem, opT1, opT2, opT3)   \
+gen_ ## mnem ## _3 ## opT1 ## opT2 ## opT3
+#define gen_insn4(mnem, opT1, opT2, opT3, opT4) \
+gen_ ## mnem ## _4 ## opT1 ## opT2 ## opT3 ## opT4
+#define gen_insn5(mnem, opT1, opT2, opT3, opT4, opT5)   \
+gen_ ## mnem ## _5 ## opT1 ## opT2 ## opT3 ## opT4 ## opT5
+
+#define GEN_INSN0(mnem) \
+static void gen_insn0(mnem)(\
+CPUX86State *env, DisasContext *s)
+#define GEN_INSN1(mnem, opT1)   \
+static void gen_insn1(mnem, opT1)(  \
+CPUX86State *env, DisasContext *s,  \
+insnop_arg_t(opT1) arg1)
+#define GEN_INSN2(mnem, opT1, opT2) \
+static void gen_insn2(mnem, opT1, opT2)(\
+CPUX86State *env, DisasContext *s,  \
+insnop_arg_t(opT1) arg1, insnop_arg_t(opT2) arg2)
+#define GEN_INSN3(mnem, opT1, opT2, opT3)   \
+static void gen_insn3(mnem, opT1, opT2, opT3)(  \
+CPUX86State *env, DisasContext *s,  \
+insnop_arg_t(opT1) arg1, insnop_arg_t(opT2) arg2,   \
+insnop_arg_t(opT3) arg3)
+#define GEN_INSN4(mnem, opT1, opT2, opT3, opT4) \
+static void gen_insn4(mnem, opT1, opT2, opT3, opT4)(\
+CPUX86State *env, DisasContext *s,  \
+insnop_arg_t(opT1) arg1, insnop_arg_t(opT2) arg2,   \
+insnop_arg_t(opT3) arg3, insnop_arg_t(opT4) arg4)
+#define GEN_INSN5(mnem, opT1, opT2, opT3, opT4, opT5)   \
+static void gen_insn5(mnem, opT1, opT2, opT3, opT4, opT5)(  \
+CPUX86State *env, DisasContext *s,  \
+insnop_arg_t(opT1) arg1, insnop_arg_t(opT2) arg2,   \
+insnop_arg_t(opT3) arg3, insnop_arg_t(opT4) arg4,   \
+insnop_arg_t(opT5) arg5)
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
 enum {
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 41/75] target/i386: introduce SSE vector instructions to sse-opcode.inc.h

2019-08-21 Thread Jan Bobek
Add all the SSE vector instruction entries to sse-opcode.inc.h.

Signed-off-by: Jan Bobek 
---
 target/i386/sse-opcode.inc.h | 161 +++
 1 file changed, 161 insertions(+)

diff --git a/target/i386/sse-opcode.inc.h b/target/i386/sse-opcode.inc.h
index e570d449fc..92581703cd 100644
--- a/target/i386/sse-opcode.inc.h
+++ b/target/i386/sse-opcode.inc.h
@@ -104,6 +104,85 @@
  * NP 0F 72 /4 ib   PSRAD mm,imm8
  * NP 0F 73 /6 ib   PSLLQ mm, imm8
  * NP 0F 73 /2 ib   PSRLQ mm, imm8
+ *
+ * SSE Instructions
+ * -
+ * NP 0F 28 /r  MOVAPS xmm1, xmm2/m128
+ * NP 0F 29 /r  MOVAPS xmm2/m128, xmm1
+ * NP 0F 10 /r  MOVUPS xmm1, xmm2/m128
+ * NP 0F 11 /r  MOVUPS xmm2/m128, xmm1
+ * F3 0F 10 /r  MOVSS xmm1, xmm2/m32
+ * F3 0F 11 /r  MOVSS xmm2/m32, xmm1
+ * NP 0F 12 /r  MOVHLPS xmm1, xmm2
+ * NP 0F 12 /r  MOVLPS xmm1, m64
+ * 0F 13 /r MOVLPS m64, xmm1
+ * NP 0F 16 /r  MOVLHPS xmm1, xmm2
+ * NP 0F 16 /r  MOVHPS xmm1, m64
+ * NP 0F 17 /r  MOVHPS m64, xmm1
+ * NP 0F D7 /r  PMOVMSKB r32, mm
+ * NP REX.W 0F D7 /rPMOVMSKB r64, mm
+ * NP 0F 50 /r  MOVMSKPS r32, xmm
+ * NP REX.W 0F 50 /rMOVMSKPS r64, xmm
+ * NP 0F 58 /r  ADDPS xmm1, xmm2/m128
+ * F3 0F 58 /r  ADDSS xmm1, xmm2/m32
+ * NP 0F 5C /r  SUBPS xmm1, xmm2/m128
+ * F3 0F 5C /r  SUBSS xmm1, xmm2/m32
+ * NP 0F E4 /r  PMULHUW mm1, mm2/m64
+ * NP 0F 59 /r  MULPS xmm1, xmm2/m128
+ * F3 0F 59 /r  MULSS xmm1,xmm2/m32
+ * NP 0F 5E /r  DIVPS xmm1, xmm2/m128
+ * F3 0F 5E /r  DIVSS xmm1, xmm2/m32
+ * NP 0F 53 /r  RCPPS xmm1, xmm2/m128
+ * F3 0F 53 /r  RCPSS xmm1, xmm2/m32
+ * NP 0F 51 /r  SQRTPS xmm1, xmm2/m128
+ * F3 0F 51 /r  SQRTSS xmm1, xmm2/m32
+ * NP 0F 52 /r  RSQRTPS xmm1, xmm2/m128
+ * F3 0F 52 /r  RSQRTSS xmm1, xmm2/m32
+ * NP 0F DA /r  PMINUB mm1, mm2/m64
+ * NP 0F EA /r  PMINSW mm1, mm2/m64
+ * NP 0F 5D /r  MINPS xmm1, xmm2/m128
+ * F3 0F 5D /r  MINSS xmm1,xmm2/m32
+ * NP 0F DE /r  PMAXUB mm1, mm2/m64
+ * NP 0F EE /r  PMAXSW mm1, mm2/m64
+ * NP 0F 5F /r  MAXPS xmm1, xmm2/m128
+ * F3 0F 5F /r  MAXSS xmm1, xmm2/m32
+ * NP 0F E0 /r  PAVGB mm1, mm2/m64
+ * NP 0F E3 /r  PAVGW mm1, mm2/m64
+ * NP 0F F6 /r  PSADBW mm1, mm2/m64
+ * NP 0F C2 /r ib   CMPPS xmm1, xmm2/m128, imm8
+ * F3 0F C2 /r ib   CMPSS xmm1, xmm2/m32, imm8
+ * NP 0F 2E /r  UCOMISS xmm1, xmm2/m32
+ * NP 0F 2F /r  COMISS xmm1, xmm2/m32
+ * NP 0F 54 /r  ANDPS xmm1, xmm2/m128
+ * NP 0F 55 /r  ANDNPS xmm1, xmm2/m128
+ * NP 0F 56 /r  ORPS xmm1, xmm2/m128
+ * NP 0F 57 /r  XORPS xmm1, xmm2/m128
+ * NP 0F 14 /r  UNPCKLPS xmm1, xmm2/m128
+ * NP 0F 15 /r  UNPCKHPS xmm1, xmm2/m128
+ * NP 0F 70 /r ib   PSHUFW mm1, mm2/m64, imm8
+ * NP 0F C6 /r ib   SHUFPS xmm1, xmm3/m128, imm8
+ * NP 0F C4 /r ib   PINSRW mm, r32/m16, imm8
+ * NP 0F C5 /r ib   PEXTRW r32, mm, imm8
+ * NP REX.W 0F C5 /r ib PEXTRW r64, mm, imm8
+ * NP 0F 2A /r  CVTPI2PS xmm, mm/m64
+ * F3 0F 2A /r  CVTSI2SS xmm1,r/m32
+ * F3 REX.W 0F 2A /rCVTSI2SS xmm1,r/m64
+ * NP 0F 2D /r  CVTPS2PI mm, xmm/m64
+ * F3 0F 2D /r  CVTSS2SI r32,xmm1/m32
+ * F3 REX.W 0F 2D /rCVTSS2SI r64,xmm1/m32
+ * NP 0F 2C /r  CVTTPS2PI mm, xmm/m64
+ * F3 0F 2C /r  CVTTSS2SI r32,xmm1/m32
+ * F3 REX.W 0F 2C /rCVTTSS2SI r64,xmm1/m32
+ * NP 0F F7 /r  MASKMOVQ mm1, mm2
+ * NP 0F 2B /r  MOVNTPS m128, xmm1
+ * NP 0F E7 /r  MOVNTQ m64, mm
+ * NP 0F AE /7  SFENCE
+ * NP 0F AE /2  LDMXCSR m32
+ * NP 0F AE /3  STMXCSR m32
+ * 0F 18 /1 PREFETCHT0 m8
+ * 0F 18 /2 PREFETCHT1 m8
+ * 0F 18 /3 PREFETCHT2 m8
+ * 0F 18 /0 PREFETCHNTA m8
  */
 
 OPCODE(movd, LEG(NP, 0F, 0, 0x6e), MMX, WR, Pq, Ed)
@@ -112,6 +191,20 @@ OPCODE(movq, LEG(NP, 0F, 1, 0x6e), MMX, WR, Pq, Eq)
 OPCODE(movq, LEG(NP, 0F, 1, 0x7e), MMX, WR, Eq, Pq)
 OPCODE(movq, LEG(NP, 0F, 0, 0x6f), MMX, WR, Pq, Qq)
 OPCODE(movq, LEG(NP, 0F, 0, 0x7f), MMX, WR, Qq, Pq)
+OPCODE(movaps, LEG(NP, 0F, 0, 0x28), SSE, WR, Vdq, Wdq)
+OPCODE(movaps, LEG(NP, 0F, 0, 0x29), SSE, WR, Wdq, Vdq)
+OPCODE(movups, LEG(NP, 0F, 0, 0x10), SSE, WR, Vdq, Wdq)
+OPCODE(movups, LEG(NP, 0F, 0, 0x11), SSE, WR, Wdq, Vdq)
+OPCODE(movss, LEG(F3, 0F, 0, 0x10), SSE, WRRR, Vdq, Vdq, Wd, modrm_mod)
+OPCODE(movss, LEG(F3, 0F, 0, 0x11), SSE, WR, Wd, Vd)
+OPCODE(movhlps, LEG(NP, 0F, 0, 0x12), SSE, WRR, Vdq, Vdq, UdqMhq)
+OPCODE(movlps, LEG(NP, 0F, 0, 0x13), SSE, WR, Mq, Vq)
+OPCODE(movlhps, LEG(NP, 0F, 0, 0x16), SSE, WRR, Vdq, Vq, Wq)
+OPCODE(movhps, LEG(NP, 0F, 0, 0x17), SSE, WR, Mq, Vdq)
+OPCODE(pmovmskb, LEG(NP, 0F, 0, 0xd7), SSE, WR, Gd, Nq)
+OPCODE(pmovmskb, LEG(NP, 0F, 1

[Qemu-devel] [RFC PATCH v4 29/75] target/i386: introduce H*, L*, V*, U*, W* (SSE/AVX) operands

2019-08-21 Thread Jan Bobek
These address the SSE/AVX-technology register file. Offset of the
entire corresponding register is passed as the operand value,
regardless of operand-size suffix.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 220 
 1 file changed, 220 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 815354f12b..23ba1d5edd 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4941,6 +4941,7 @@ DEF_INSNOP_ALIAS(Mb, M)
 DEF_INSNOP_ALIAS(Mw, M)
 DEF_INSNOP_ALIAS(Md, M)
 DEF_INSNOP_ALIAS(Mq, M)
+DEF_INSNOP_ALIAS(Mhq, M)
 DEF_INSNOP_ALIAS(Mdq, M)
 DEF_INSNOP_ALIAS(Mqq, M)
 
@@ -5112,6 +5113,225 @@ INSNOP_LDST(mm, Mq)
 tcg_temp_free_i64(r64);
 }
 
+/*
+ * vex_v
+ *
+ * Operand whose value is the  field of the VEX prefix.
+ */
+typedef int insnop_arg_t(vex_v);
+typedef struct {} insnop_ctxt_t(vex_v);
+
+INSNOP_INIT(vex_v)
+{
+return s->prefix & PREFIX_VEX;
+}
+INSNOP_PREPARE(vex_v)
+{
+return s->vex_v;
+}
+INSNOP_FINALIZE(vex_v)
+{
+}
+
+/*
+ * is4
+ *
+ * Upper 4 bits of the 8-bit immediate selector, used with the SSE/AVX
+ * register file in some instructions.
+ */
+typedef int insnop_arg_t(is4);
+typedef struct {
+insnop_ctxt_t(Ib) ctxt_Ib;
+insnop_arg_t(Ib) arg_Ib;
+} insnop_ctxt_t(is4);
+
+INSNOP_INIT(is4)
+{
+return insnop_init(Ib)(>ctxt_Ib, env, s, modrm, is_write);
+}
+INSNOP_PREPARE(is4)
+{
+ctxt->arg_Ib = insnop_prepare(Ib)(>ctxt_Ib, env, s, modrm, is_write);
+return (ctxt->arg_Ib >> 4) & 0xf;
+}
+INSNOP_FINALIZE(is4)
+{
+insnop_finalize(Ib)(>ctxt_Ib, env, s, modrm, is_write, ctxt->arg_Ib);
+}
+
+/*
+ * SSE/AVX-technology registers
+ */
+typedef unsigned int insnop_arg_t(xmm);
+typedef struct {} insnop_ctxt_t(xmm);
+
+INSNOP_INIT(xmm)
+{
+return true;
+}
+INSNOP_PREPARE(xmm)
+{
+return offsetof(CPUX86State, xmm_t0);
+}
+INSNOP_FINALIZE(xmm)
+{
+}
+
+#define DEF_INSNOP_XMM(opT, opTxmmid)   \
+typedef insnop_arg_t(xmm) insnop_arg_t(opT);\
+typedef struct {\
+insnop_ctxt_t(opTxmmid) xmmid;  \
+} insnop_ctxt_t(opT);   \
+\
+INSNOP_INIT(opT)\
+{   \
+return insnop_init(opTxmmid)(>xmmid, env, s, modrm, is_write); \
+}   \
+INSNOP_PREPARE(opT) \
+{   \
+const insnop_arg_t(opTxmmid) xmmid =\
+insnop_prepare(opTxmmid)(>xmmid, env, s, modrm, is_write); \
+const insnop_arg_t(opT) arg =   \
+offsetof(CPUX86State, xmm_regs[xmmid]); \
+insnop_finalize(opTxmmid)(>xmmid, env, s, \
+  modrm, is_write, xmmid);  \
+return arg; \
+}   \
+INSNOP_FINALIZE(opT)\
+{   \
+}
+
+DEF_INSNOP_XMM(V, modrm_reg)
+DEF_INSNOP_ALIAS(Vd, V)
+DEF_INSNOP_ALIAS(Vq, V)
+DEF_INSNOP_ALIAS(Vdq, V)
+DEF_INSNOP_ALIAS(Vqq, V)
+
+DEF_INSNOP_XMM(U, modrm_rm_direct)
+DEF_INSNOP_ALIAS(Ub, U)
+DEF_INSNOP_ALIAS(Uw, U)
+DEF_INSNOP_ALIAS(Ud, U)
+DEF_INSNOP_ALIAS(Uq, U)
+DEF_INSNOP_ALIAS(Udq, U)
+DEF_INSNOP_ALIAS(Uqq, U)
+
+DEF_INSNOP_XMM(H, vex_v)
+DEF_INSNOP_ALIAS(Hd, H)
+DEF_INSNOP_ALIAS(Hq, H)
+DEF_INSNOP_ALIAS(Hdq, H)
+DEF_INSNOP_ALIAS(Hqq, H)
+
+DEF_INSNOP_XMM(L, is4)
+DEF_INSNOP_ALIAS(Ldq, L)
+DEF_INSNOP_ALIAS(Lqq, L)
+
+DEF_INSNOP_LDST(MWb, xmm, Mb)
+DEF_INSNOP_LDST(MWw, xmm, Mw)
+DEF_INSNOP_LDST(MWd, xmm, Md)
+DEF_INSNOP_LDST(MWq, xmm, Mq)
+DEF_INSNOP_LDST(MWdq, xmm, Mdq)
+DEF_INSNOP_LDST(MWqq, xmm, Mqq)
+DEF_INSNOP_LDST(MUdqMhq, xmm, Mhq)
+DEF_INSNOP_EITHER(Wb, Ub, MWb)
+DEF_INSNOP_EITHER(Ww, Uw, MWw)
+DEF_INSNOP_EITHER(Wd, Ud, MWd)
+DEF_INSNOP_EITHER(Wq, Uq, MWq)
+DEF_INSNOP_EITHER(Wdq, Udq, MWdq)
+DEF_INSNOP_EITHER(Wqq, Uqq, MWqq)
+DEF_INSNOP_EITHER(UdqMq, Udq, MWq)
+DEF_INSNOP_EITHER(UdqMhq, Udq, MUdqMhq)
+
+INSNOP_LDST(xmm, Mb)
+{
+const insnop_arg_t(xmm) ofs = offsetof(ZMMReg, ZMM_B(0));
+const TCGv_i32 r32 = tcg_temp_new_i32();
+if (is_write) {
+tcg_gen_ld_i32(r32, cpu_env, arg + ofs);
+tcg_gen_qemu_st_i32(r32, ptr, s->mem_index, MO_UB);
+} else {
+tcg_gen_qemu_ld_i32(r32, ptr, s->mem_index, MO

[Qemu-devel] [RFC PATCH v4 33/75] target/i386: introduce gvec-based code generator macros

2019-08-21 Thread Jan Bobek
Code generators defined using these macros rely on a gvec operation
(i.e. tcg_gen_gvec_*).

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 046914578b..eab36963c3 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -24,6 +24,7 @@
 #include "exec/exec-all.h"
 #include "tcg-gvec-desc.h"
 #include "tcg-op.h"
+#include "tcg-op-gvec.h"
 #include "exec/cpu_ldst.h"
 #include "exec/translator.h"
 
@@ -5537,6 +5538,30 @@ INSNOP_LDST(xmm, Mhq)
 tcg_temp_free_i32(arg4_r32);\
 }
 
+#define MM_OPRSZ sizeof(MMXReg)
+#define MM_MAXSZ sizeof(MMXReg)
+#define XMM_OPRSZ (!(s->prefix & PREFIX_VEX) ? sizeof(XMMReg) : \
+   s->vex_l ? sizeof(XMMReg) :  \
+   sizeof(XMMReg))
+#define XMM_MAXSZ (!(s->prefix & PREFIX_VEX) ? sizeof(XMMReg) : \
+   sizeof(YMMReg))
+
+#define DEF_GEN_INSN2_GVEC(mnem, opT1, opT2, gvec, ...) \
+GEN_INSN2(mnem, opT1, opT2) \
+{   \
+gen_gvec_ ## gvec(arg1, arg2, ## __VA_ARGS__);  \
+}
+#define DEF_GEN_INSN3_GVEC(mnem, opT1, opT2, opT3, gvec, ...)   \
+GEN_INSN3(mnem, opT1, opT2, opT3)   \
+{   \
+gen_gvec_ ## gvec(arg1, arg2, arg3, ## __VA_ARGS__);\
+}
+#define DEF_GEN_INSN4_GVEC(mnem, opT1, opT2, opT3, opT4, gvec, ...) \
+GEN_INSN4(mnem, opT1, opT2, opT3, opT4) \
+{   \
+gen_gvec_ ## gvec(arg1, arg2, arg3, arg4, ## __VA_ARGS__);  \
+}
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
 enum {
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 26/75] target/i386: introduce M* (memptr) operands

2019-08-21 Thread Jan Bobek
The memory-pointer operand decodes the indirect form of ModR/M byte,
loads the effective address into a register and passes that register
as the operand.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 36 
 1 file changed, 36 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 9f02ea58d1..46c41cc3be 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4908,6 +4908,42 @@ INSNOP_FINALIZE(Ib)
 {
 }
 
+/*
+ * Memory-pointer operand
+ */
+typedef TCGv insnop_arg_t(M);
+typedef struct {} insnop_ctxt_t(M);
+
+INSNOP_INIT(M)
+{
+bool ret;
+insnop_ctxt_t(modrm_mod) modctxt;
+
+ret = insnop_init(modrm_mod)(, env, s, modrm, is_write);
+if (ret) {
+const int mod =
+insnop_prepare(modrm_mod)(, env, s, modrm, is_write);
+ret = (mod != 3);
+insnop_finalize(modrm_mod)(, env, s, modrm, is_write, mod);
+}
+return ret;
+}
+INSNOP_PREPARE(M)
+{
+gen_lea_modrm(env, s, modrm);
+return s->A0;
+}
+INSNOP_FINALIZE(M)
+{
+}
+
+DEF_INSNOP_ALIAS(Mb, M)
+DEF_INSNOP_ALIAS(Mw, M)
+DEF_INSNOP_ALIAS(Md, M)
+DEF_INSNOP_ALIAS(Mq, M)
+DEF_INSNOP_ALIAS(Mdq, M)
+DEF_INSNOP_ALIAS(Mqq, M)
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
 enum {
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 42/75] target/i386: introduce SSE2 translators

2019-08-21 Thread Jan Bobek
Use the translator macros to define translators required by SSE2
instructions.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 31 +++
 1 file changed, 31 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index d1537bc1b7..43917edc76 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -6064,14 +6064,20 @@ DEF_TRANSLATE_INSN1(Md)
 }
 
 DEF_TRANSLATE_INSN2(Ed, Pq)
+DEF_TRANSLATE_INSN2(Ed, Vdq)
 DEF_TRANSLATE_INSN2(Eq, Pq)
+DEF_TRANSLATE_INSN2(Eq, Vdq)
 DEF_TRANSLATE_INSN2(Gd, Nq)
 DEF_TRANSLATE_INSN2(Gd, Udq)
 DEF_TRANSLATE_INSN2(Gd, Wd)
+DEF_TRANSLATE_INSN2(Gd, Wq)
 DEF_TRANSLATE_INSN2(Gq, Nq)
 DEF_TRANSLATE_INSN2(Gq, Udq)
 DEF_TRANSLATE_INSN2(Gq, Wd)
+DEF_TRANSLATE_INSN2(Gq, Wq)
+DEF_TRANSLATE_INSN2(Md, Gd)
 DEF_TRANSLATE_INSN2(Mdq, Vdq)
+DEF_TRANSLATE_INSN2(Mq, Gq)
 DEF_TRANSLATE_INSN2(Mq, Pq)
 DEF_TRANSLATE_INSN2(Mq, Vdq)
 DEF_TRANSLATE_INSN2(Mq, Vq)
@@ -6079,15 +6085,30 @@ DEF_TRANSLATE_INSN2(Pq, Ed)
 DEF_TRANSLATE_INSN2(Pq, Eq)
 DEF_TRANSLATE_INSN2(Pq, Nq)
 DEF_TRANSLATE_INSN2(Pq, Qq)
+DEF_TRANSLATE_INSN2(Pq, Uq)
+DEF_TRANSLATE_INSN2(Pq, Wdq)
 DEF_TRANSLATE_INSN2(Pq, Wq)
 DEF_TRANSLATE_INSN2(Qq, Pq)
+DEF_TRANSLATE_INSN2(UdqMq, Vq)
 DEF_TRANSLATE_INSN2(Vd, Ed)
 DEF_TRANSLATE_INSN2(Vd, Eq)
 DEF_TRANSLATE_INSN2(Vd, Wd)
+DEF_TRANSLATE_INSN2(Vd, Wq)
+DEF_TRANSLATE_INSN2(Vdq, Ed)
+DEF_TRANSLATE_INSN2(Vdq, Eq)
+DEF_TRANSLATE_INSN2(Vdq, Nq)
 DEF_TRANSLATE_INSN2(Vdq, Qq)
+DEF_TRANSLATE_INSN2(Vdq, Udq)
 DEF_TRANSLATE_INSN2(Vdq, Wdq)
+DEF_TRANSLATE_INSN2(Vdq, Wq)
+DEF_TRANSLATE_INSN2(Vq, Ed)
+DEF_TRANSLATE_INSN2(Vq, Eq)
+DEF_TRANSLATE_INSN2(Vq, Wd)
+DEF_TRANSLATE_INSN2(Vq, Wq)
 DEF_TRANSLATE_INSN2(Wd, Vd)
 DEF_TRANSLATE_INSN2(Wdq, Vdq)
+DEF_TRANSLATE_INSN2(Wq, Vq)
+DEF_TRANSLATE_INSN2(modrm_mod, modrm)
 
 #define DEF_TRANSLATE_INSN3(opT1, opT2, opT3)   \
 static void translate_insn3(opT1, opT2, opT3)(  \
@@ -6128,15 +6149,22 @@ DEF_TRANSLATE_INSN2(Wdq, Vdq)
 }
 
 DEF_TRANSLATE_INSN3(Gd, Nq, Ib)
+DEF_TRANSLATE_INSN3(Gd, Udq, Ib)
 DEF_TRANSLATE_INSN3(Gq, Nq, Ib)
+DEF_TRANSLATE_INSN3(Gq, Udq, Ib)
 DEF_TRANSLATE_INSN3(Nq, Nq, Ib)
 DEF_TRANSLATE_INSN3(Pq, Pq, Qd)
 DEF_TRANSLATE_INSN3(Pq, Pq, Qq)
 DEF_TRANSLATE_INSN3(Pq, Qq, Ib)
+DEF_TRANSLATE_INSN3(Udq, Udq, Ib)
 DEF_TRANSLATE_INSN3(Vd, Vd, Wd)
+DEF_TRANSLATE_INSN3(Vdq, Vdq, Mq)
 DEF_TRANSLATE_INSN3(Vdq, Vdq, UdqMhq)
 DEF_TRANSLATE_INSN3(Vdq, Vdq, Wdq)
+DEF_TRANSLATE_INSN3(Vdq, Vq, Mq)
 DEF_TRANSLATE_INSN3(Vdq, Vq, Wq)
+DEF_TRANSLATE_INSN3(Vdq, Wdq, Ib)
+DEF_TRANSLATE_INSN3(Vq, Vq, Wq)
 
 #define DEF_TRANSLATE_INSN4(opT1, opT2, opT3, opT4) \
 static void translate_insn4(opT1, opT2, opT3, opT4)(\
@@ -6184,8 +6212,11 @@ DEF_TRANSLATE_INSN3(Vdq, Vq, Wq)
 
 DEF_TRANSLATE_INSN4(Pq, Pq, RdMw, Ib)
 DEF_TRANSLATE_INSN4(Vd, Vd, Wd, Ib)
+DEF_TRANSLATE_INSN4(Vdq, Vdq, RdMw, Ib)
 DEF_TRANSLATE_INSN4(Vdq, Vdq, Wd, modrm_mod)
 DEF_TRANSLATE_INSN4(Vdq, Vdq, Wdq, Ib)
+DEF_TRANSLATE_INSN4(Vdq, Vdq, Wq, modrm_mod)
+DEF_TRANSLATE_INSN4(Vq, Vq, Wq, Ib)
 
 #define DEF_TRANSLATE_INSN5(opT1, opT2, opT3, opT4, opT5)   \
 static void translate_insn5(opT1, opT2, opT3, opT4, opT5)(  \
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 28/75] target/i386: introduce P*, N*, Q* (MMX) operands

2019-08-21 Thread Jan Bobek
These address the MMX-technology register file; the corresponding
cpu_env offset is passed as the operand value. Notably, offset of the
entire register is pased at all times, regardless of the operand-size
suffix.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 80 +
 1 file changed, 80 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index d6d32c7f06..815354f12b 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -5032,6 +5032,86 @@ INSNOP_LDST(tcg_i64, Mq)
 }
 }
 
+/*
+ * MMX-technology register operands
+ */
+typedef unsigned int insnop_arg_t(mm);
+typedef struct {} insnop_ctxt_t(mm);
+
+INSNOP_INIT(mm)
+{
+return true;
+}
+INSNOP_PREPARE(mm)
+{
+return offsetof(CPUX86State, mmx_t0);
+}
+INSNOP_FINALIZE(mm)
+{
+}
+
+#define DEF_INSNOP_MM(opT, opTmmid) \
+typedef insnop_arg_t(mm) insnop_arg_t(opT); \
+typedef struct {\
+insnop_ctxt_t(opTmmid) mmid;\
+} insnop_ctxt_t(opT);   \
+\
+INSNOP_INIT(opT)\
+{   \
+return insnop_init(opTmmid)(>mmid, env, s, modrm, is_write); \
+}   \
+INSNOP_PREPARE(opT) \
+{   \
+const insnop_arg_t(opTmmid) mmid =  \
+insnop_prepare(opTmmid)(>mmid, env, s, modrm, is_write); \
+const insnop_arg_t(opT) arg =   \
+offsetof(CPUX86State, fpregs[mmid & 7].mmx);\
+insnop_finalize(opTmmid)(>mmid, env, s, modrm, is_write, mmid); \
+return arg; \
+}   \
+INSNOP_FINALIZE(opT)\
+{   \
+}
+
+DEF_INSNOP_MM(P, modrm_reg)
+DEF_INSNOP_ALIAS(Pq, P)
+
+DEF_INSNOP_MM(N, modrm_rm_direct)
+DEF_INSNOP_ALIAS(Nd, N)
+DEF_INSNOP_ALIAS(Nq, N)
+
+DEF_INSNOP_LDST(MQd, mm, Md)
+DEF_INSNOP_LDST(MQq, mm, Mq)
+DEF_INSNOP_EITHER(Qd, Nd, MQd)
+DEF_INSNOP_EITHER(Qq, Nq, MQq)
+
+INSNOP_LDST(mm, Md)
+{
+const insnop_arg_t(mm) ofs = offsetof(MMXReg, MMX_L(0));
+const TCGv_i32 r32 = tcg_temp_new_i32();
+if (is_write) {
+tcg_gen_ld_i32(r32, cpu_env, arg + ofs);
+tcg_gen_qemu_st_i32(r32, ptr, s->mem_index, MO_LEUL);
+} else {
+tcg_gen_qemu_ld_i32(r32, ptr, s->mem_index, MO_LEUL);
+tcg_gen_st_i32(r32, cpu_env, arg + ofs);
+}
+tcg_temp_free_i32(r32);
+}
+INSNOP_LDST(mm, Mq)
+{
+const insnop_arg_t(mm) ofs = offsetof(MMXReg, MMX_Q(0));
+const TCGv_i64 r64 = tcg_temp_new_i64();
+if (is_write) {
+tcg_gen_ld_i64(r64, cpu_env, arg + ofs);
+tcg_gen_qemu_st_i64(r64, ptr, s->mem_index, MO_LEQ);
+} else {
+tcg_gen_qemu_ld_i64(r64, ptr, s->mem_index, MO_LEQ);
+tcg_gen_st_i64(r64, cpu_env, arg + ofs);
+}
+tcg_temp_free_i64(r64);
+}
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
 enum {
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 30/75] target/i386: alias H* operands with the V* operands

2019-08-21 Thread Jan Bobek
This effectively means that all thee-operand VEX-encoded instructions
using the VEX.V field will be decoded as their non-VEX-encoded
two-operand equivalents. While this is incorrect, it is the old
behavior, which is useful during development.

Note: This changeset is intended for development only and shall not be
included in the final patch series.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 23ba1d5edd..2e78bed78f 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -5215,11 +5215,10 @@ DEF_INSNOP_ALIAS(Uq, U)
 DEF_INSNOP_ALIAS(Udq, U)
 DEF_INSNOP_ALIAS(Uqq, U)
 
-DEF_INSNOP_XMM(H, vex_v)
-DEF_INSNOP_ALIAS(Hd, H)
-DEF_INSNOP_ALIAS(Hq, H)
-DEF_INSNOP_ALIAS(Hdq, H)
-DEF_INSNOP_ALIAS(Hqq, H)
+DEF_INSNOP_ALIAS(Hd, Vd)
+DEF_INSNOP_ALIAS(Hq, Vq)
+DEF_INSNOP_ALIAS(Hdq, Vdq)
+DEF_INSNOP_ALIAS(Hqq, Vqq)
 
 DEF_INSNOP_XMM(L, is4)
 DEF_INSNOP_ALIAS(Ldq, L)
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 24/75] target/i386: introduce operand for direct-only r/m field

2019-08-21 Thread Jan Bobek
Many operands can only decode successfully if the ModR/M byte has the
direct form (i.e. MOD=3). Capture this common aspect by introducing a
special direct-only r/m field operand.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 37 +
 1 file changed, 37 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index b3b316d389..886f64a58f 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4853,6 +4853,43 @@ INSNOP_FINALIZE(modrm_rm)
 {
 }
 
+/*
+ * modrm_rm_direct
+ *
+ * Equivalent of modrm_rm, but only decodes successfully if
+ * the ModR/M byte has the direct form (i.e. MOD=3).
+ */
+typedef insnop_arg_t(modrm_rm) insnop_arg_t(modrm_rm_direct);
+typedef struct {
+insnop_ctxt_t(modrm_rm) rm;
+} insnop_ctxt_t(modrm_rm_direct);
+
+INSNOP_INIT(modrm_rm_direct)
+{
+bool ret;
+insnop_ctxt_t(modrm_mod) modctxt;
+
+ret = insnop_init(modrm_mod)(, env, s, modrm, 0);
+if (ret) {
+const int mod = insnop_prepare(modrm_mod)(, env, s, modrm, 0);
+if (mod == 3) {
+ret = insnop_init(modrm_rm)(>rm, env, s, modrm, is_write);
+} else {
+ret = false;
+}
+insnop_finalize(modrm_mod)(, env, s, modrm, 0, mod);
+}
+return ret;
+}
+INSNOP_PREPARE(modrm_rm_direct)
+{
+return insnop_prepare(modrm_rm)(>rm, env, s, modrm, is_write);
+}
+INSNOP_FINALIZE(modrm_rm_direct)
+{
+insnop_finalize(modrm_rm)(>rm, env, s, modrm, is_write, arg);
+}
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
 enum {
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 40/75] target/i386: introduce SSE code generators

2019-08-21 Thread Jan Bobek
Introduce code generators required by SSE instructions.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 309 
 1 file changed, 309 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index d77c08b7db..d1537bc1b7 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -5586,6 +5586,90 @@ GEN_INSN2(movq, Eq, Pq)
 
 DEF_GEN_INSN2_GVEC(movq, Pq, Qq, mov, MM_OPRSZ, MM_MAXSZ, MO_64)
 DEF_GEN_INSN2_GVEC(movq, Qq, Pq, mov, MM_OPRSZ, MM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(movaps, Vdq, Wdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(movaps, Wdq, Vdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(movups, Vdq, Wdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(movups, Wdq, Vdq, mov, XMM_OPRSZ, XMM_MAXSZ, MO_64)
+
+GEN_INSN4(movss, Vdq, Vdq, Wd, modrm_mod)
+{
+const TCGv_i32 r32 = tcg_temp_new_i32();
+const TCGv_i64 r64 = tcg_temp_new_i64();
+if (arg4 == 3) {
+/* merging movss */
+tcg_gen_ld_i32(r32, cpu_env, arg3 + offsetof(ZMMReg, ZMM_L(0)));
+tcg_gen_st_i32(r32, cpu_env, arg1 + offsetof(ZMMReg, ZMM_L(0)));
+if (arg1 != arg2) {
+tcg_gen_ld_i32(r32, cpu_env, arg2 + offsetof(ZMMReg, ZMM_L(1)));
+tcg_gen_st_i32(r32, cpu_env, arg1 + offsetof(ZMMReg, ZMM_L(1)));
+tcg_gen_ld_i64(r64, cpu_env, arg2 + offsetof(ZMMReg, ZMM_Q(1)));
+tcg_gen_st_i64(r64, cpu_env, arg1 + offsetof(ZMMReg, ZMM_Q(1)));
+}
+} else {
+/* zero-extending movss */
+tcg_gen_ld_i32(r32, cpu_env, arg3 + offsetof(ZMMReg, ZMM_L(0)));
+tcg_gen_extu_i32_i64(r64, r32);
+tcg_gen_st_i64(r64, cpu_env, arg1 + offsetof(ZMMReg, ZMM_Q(0)));
+tcg_gen_movi_i64(r64, 0);
+tcg_gen_st_i64(r64, cpu_env, arg1 + offsetof(ZMMReg, ZMM_Q(1)));
+}
+tcg_temp_free_i32(r32);
+tcg_temp_free_i64(r64);
+}
+GEN_INSN2(movss, Wd, Vd)
+{
+gen_insn4(movss, Vdq, Vdq, Wd, modrm_mod)(env, s, arg1, arg1, arg2, 3);
+}
+
+GEN_INSN3(movhlps, Vdq, Vdq, UdqMhq)
+{
+const TCGv_i64 r64 = tcg_temp_new_i64();
+tcg_gen_ld_i64(r64, cpu_env, arg3 + offsetof(ZMMReg, ZMM_Q(1)));
+tcg_gen_st_i64(r64, cpu_env, arg1 + offsetof(ZMMReg, ZMM_Q(0)));
+if (arg1 != arg2) {
+tcg_gen_ld_i64(r64, cpu_env, arg2 + offsetof(ZMMReg, ZMM_Q(1)));
+tcg_gen_st_i64(r64, cpu_env, arg1 + offsetof(ZMMReg, ZMM_Q(1)));
+}
+tcg_temp_free_i64(r64);
+}
+GEN_INSN2(movlps, Mq, Vq)
+{
+insnop_ldst(xmm, Mq)(env, s, 1, arg2, arg1);
+}
+
+GEN_INSN3(movlhps, Vdq, Vq, Wq)
+{
+const TCGv_i64 r64 = tcg_temp_new_i64();
+tcg_gen_ld_i64(r64, cpu_env, arg3 + offsetof(ZMMReg, ZMM_Q(0)));
+tcg_gen_st_i64(r64, cpu_env, arg1 + offsetof(ZMMReg, ZMM_Q(1)));
+if (arg1 != arg2) {
+tcg_gen_ld_i64(r64, cpu_env, arg2 + offsetof(ZMMReg, ZMM_Q(0)));
+tcg_gen_st_i64(r64, cpu_env, arg1 + offsetof(ZMMReg, ZMM_Q(0)));
+}
+tcg_temp_free_i64(r64);
+}
+GEN_INSN2(movhps, Mq, Vdq)
+{
+insnop_ldst(xmm, Mhq)(env, s, 1, arg2, arg1);
+}
+
+DEF_GEN_INSN2_HELPER_DEP(pmovmskb, pmovmskb_mmx, Gd, Nq)
+GEN_INSN2(pmovmskb, Gq, Nq)
+{
+const TCGv_i32 arg1_r32 = tcg_temp_new_i32();
+gen_insn2(pmovmskb, Gd, Nq)(env, s, arg1_r32, arg2);
+tcg_gen_extu_i32_i64(arg1, arg1_r32);
+tcg_temp_free_i32(arg1_r32);
+}
+
+DEF_GEN_INSN2_HELPER_DEP(movmskps, movmskps, Gd, Udq)
+GEN_INSN2(movmskps, Gq, Udq)
+{
+const TCGv_i32 arg1_r32 = tcg_temp_new_i32();
+gen_insn2(movmskps, Gd, Udq)(env, s, arg1_r32, arg2);
+tcg_gen_extu_i32_i64(arg1, arg1_r32);
+tcg_temp_free_i32(arg1_r32);
+}
 
 DEF_GEN_INSN3_GVEC(paddb, Pq, Pq, Qq, add, MM_OPRSZ, MM_MAXSZ, MO_8)
 DEF_GEN_INSN3_GVEC(paddw, Pq, Pq, Qq, add, MM_OPRSZ, MM_MAXSZ, MO_16)
@@ -5594,6 +5678,8 @@ DEF_GEN_INSN3_GVEC(paddsb, Pq, Pq, Qq, ssadd, MM_OPRSZ, 
MM_MAXSZ, MO_8)
 DEF_GEN_INSN3_GVEC(paddsw, Pq, Pq, Qq, ssadd, MM_OPRSZ, MM_MAXSZ, MO_16)
 DEF_GEN_INSN3_GVEC(paddusb, Pq, Pq, Qq, usadd, MM_OPRSZ, MM_MAXSZ, MO_8)
 DEF_GEN_INSN3_GVEC(paddusw, Pq, Pq, Qq, usadd, MM_OPRSZ, MM_MAXSZ, MO_16)
+DEF_GEN_INSN3_HELPER_EPP(addps, addps, Vdq, Vdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(addss, addss, Vd, Vd, Wd)
 
 DEF_GEN_INSN3_GVEC(psubb, Pq, Pq, Qq, sub, MM_OPRSZ, MM_MAXSZ, MO_8)
 DEF_GEN_INSN3_GVEC(psubw, Pq, Pq, Qq, sub, MM_OPRSZ, MM_MAXSZ, MO_16)
@@ -5602,11 +5688,38 @@ DEF_GEN_INSN3_GVEC(psubsb, Pq, Pq, Qq, sssub, MM_OPRSZ, 
MM_MAXSZ, MO_8)
 DEF_GEN_INSN3_GVEC(psubsw, Pq, Pq, Qq, sssub, MM_OPRSZ, MM_MAXSZ, MO_16)
 DEF_GEN_INSN3_GVEC(psubusb, Pq, Pq, Qq, ussub, MM_OPRSZ, MM_MAXSZ, MO_8)
 DEF_GEN_INSN3_GVEC(psubusw, Pq, Pq, Qq, ussub, MM_OPRSZ, MM_MAXSZ, MO_16)
+DEF_GEN_INSN3_HELPER_EPP(subps, subps, Vdq, Vdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(subss, subss, Vd, Vd, Wd)
 
 DEF_GEN_INSN3_HELPER_EPP(pmullw, pmullw_mmx, Pq, Pq, Qq)
 DEF_GEN_INSN3_HELPER_EPP(pmulhw, pmulhw_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(pmulhuw, pmulhuw_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(mulps

[Qemu-devel] [RFC PATCH v4 22/75] target/i386: introduce modrm operand

2019-08-21 Thread Jan Bobek
This permits the ModR/M byte to be passed raw into the code generator,
effectively allowing to short-circuit the operand decoding mechanism
and do the decoding work manually in the code generator.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 80cfb59978..a0a9f64ff3 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4771,6 +4771,26 @@ INSNOP_FINALIZE(tcg_i64)
 tcg_temp_free_i64(arg);
 }
 
+/*
+ * modrm
+ *
+ * Operand whose value is the ModR/M byte.
+ */
+typedef int insnop_arg_t(modrm);
+typedef struct {} insnop_ctxt_t(modrm);
+
+INSNOP_INIT(modrm)
+{
+return true;
+}
+INSNOP_PREPARE(modrm)
+{
+return modrm;
+}
+INSNOP_FINALIZE(modrm)
+{
+}
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
 enum {
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 23/75] target/i386: introduce operands for decoding modrm fields

2019-08-21 Thread Jan Bobek
The old code uses bitshifts and bitwise-and all over the place for
decoding ModR/M fields. Avoid doing that by introducing proper
decoding operands.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 62 +
 1 file changed, 62 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index a0a9f64ff3..b3b316d389 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4791,6 +4791,68 @@ INSNOP_FINALIZE(modrm)
 {
 }
 
+/*
+ * modrm_mod
+ *
+ * Operand whose value is the MOD field of the ModR/M byte.
+ */
+typedef int insnop_arg_t(modrm_mod);
+typedef struct {} insnop_ctxt_t(modrm_mod);
+
+INSNOP_INIT(modrm_mod)
+{
+return true;
+}
+INSNOP_PREPARE(modrm_mod)
+{
+return (modrm >> 6) & 3;
+}
+INSNOP_FINALIZE(modrm_mod)
+{
+}
+
+/*
+ * modrm_reg
+ *
+ * Operand whose value is the REG field of the ModR/M byte, extended
+ * with the REX.R bit if REX prefix is present.
+ */
+typedef int insnop_arg_t(modrm_reg);
+typedef struct {} insnop_ctxt_t(modrm_reg);
+
+INSNOP_INIT(modrm_reg)
+{
+return true;
+}
+INSNOP_PREPARE(modrm_reg)
+{
+return ((modrm >> 3) & 7) | REX_R(s);
+}
+INSNOP_FINALIZE(modrm_reg)
+{
+}
+
+/*
+ * modrm_rm
+ *
+ * Operand whose value is the RM field of the ModR/M byte, extended
+ * with the REX.B bit if REX prefix is present.
+ */
+typedef int insnop_arg_t(modrm_rm);
+typedef struct {} insnop_ctxt_t(modrm_rm);
+
+INSNOP_INIT(modrm_rm)
+{
+return true;
+}
+INSNOP_PREPARE(modrm_rm)
+{
+return (modrm & 7) | REX_B(s);
+}
+INSNOP_FINALIZE(modrm_rm)
+{
+}
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
 enum {
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 39/75] target/i386: introduce SSE translators

2019-08-21 Thread Jan Bobek
Use the translator macros to define translators required by SSE
instructions.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 34 ++
 1 file changed, 34 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index fdfca03071..d77c08b7db 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -5720,6 +5720,9 @@ static void translate_insn0()(
 }   \
 }
 
+DEF_TRANSLATE_INSN1(Mb)
+DEF_TRANSLATE_INSN1(Md)
+
 #define DEF_TRANSLATE_INSN2(opT1, opT2) \
 static void translate_insn2(opT1, opT2)(\
 CPUX86State *env, DisasContext *s, int modrm,   \
@@ -5753,10 +5756,29 @@ static void translate_insn0()(
 
 DEF_TRANSLATE_INSN2(Ed, Pq)
 DEF_TRANSLATE_INSN2(Eq, Pq)
+DEF_TRANSLATE_INSN2(Gd, Nq)
+DEF_TRANSLATE_INSN2(Gd, Udq)
+DEF_TRANSLATE_INSN2(Gd, Wd)
+DEF_TRANSLATE_INSN2(Gq, Nq)
+DEF_TRANSLATE_INSN2(Gq, Udq)
+DEF_TRANSLATE_INSN2(Gq, Wd)
+DEF_TRANSLATE_INSN2(Mdq, Vdq)
+DEF_TRANSLATE_INSN2(Mq, Pq)
+DEF_TRANSLATE_INSN2(Mq, Vdq)
+DEF_TRANSLATE_INSN2(Mq, Vq)
 DEF_TRANSLATE_INSN2(Pq, Ed)
 DEF_TRANSLATE_INSN2(Pq, Eq)
+DEF_TRANSLATE_INSN2(Pq, Nq)
 DEF_TRANSLATE_INSN2(Pq, Qq)
+DEF_TRANSLATE_INSN2(Pq, Wq)
 DEF_TRANSLATE_INSN2(Qq, Pq)
+DEF_TRANSLATE_INSN2(Vd, Ed)
+DEF_TRANSLATE_INSN2(Vd, Eq)
+DEF_TRANSLATE_INSN2(Vd, Wd)
+DEF_TRANSLATE_INSN2(Vdq, Qq)
+DEF_TRANSLATE_INSN2(Vdq, Wdq)
+DEF_TRANSLATE_INSN2(Wd, Vd)
+DEF_TRANSLATE_INSN2(Wdq, Vdq)
 
 #define DEF_TRANSLATE_INSN3(opT1, opT2, opT3)   \
 static void translate_insn3(opT1, opT2, opT3)(  \
@@ -5796,9 +5818,16 @@ DEF_TRANSLATE_INSN2(Qq, Pq)
 }   \
 }
 
+DEF_TRANSLATE_INSN3(Gd, Nq, Ib)
+DEF_TRANSLATE_INSN3(Gq, Nq, Ib)
 DEF_TRANSLATE_INSN3(Nq, Nq, Ib)
 DEF_TRANSLATE_INSN3(Pq, Pq, Qd)
 DEF_TRANSLATE_INSN3(Pq, Pq, Qq)
+DEF_TRANSLATE_INSN3(Pq, Qq, Ib)
+DEF_TRANSLATE_INSN3(Vd, Vd, Wd)
+DEF_TRANSLATE_INSN3(Vdq, Vdq, UdqMhq)
+DEF_TRANSLATE_INSN3(Vdq, Vdq, Wdq)
+DEF_TRANSLATE_INSN3(Vdq, Vq, Wq)
 
 #define DEF_TRANSLATE_INSN4(opT1, opT2, opT3, opT4) \
 static void translate_insn4(opT1, opT2, opT3, opT4)(\
@@ -5844,6 +5873,11 @@ DEF_TRANSLATE_INSN3(Pq, Pq, Qq)
 }   \
 }
 
+DEF_TRANSLATE_INSN4(Pq, Pq, RdMw, Ib)
+DEF_TRANSLATE_INSN4(Vd, Vd, Wd, Ib)
+DEF_TRANSLATE_INSN4(Vdq, Vdq, Wd, modrm_mod)
+DEF_TRANSLATE_INSN4(Vdq, Vdq, Wdq, Ib)
+
 #define DEF_TRANSLATE_INSN5(opT1, opT2, opT3, opT4, opT5)   \
 static void translate_insn5(opT1, opT2, opT3, opT4, opT5)(  \
 CPUX86State *env, DisasContext *s, int modrm,   \
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 20/75] target/i386: introduce generic load-store operand

2019-08-21 Thread Jan Bobek
This operand attempts to capture the "indirect" or "memory" operand in
a generic way. It significatly reduces the amount code that needs to
be written in order to read operands from memory to temporary storage
and write them back.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 57 +
 1 file changed, 57 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 68c6b7d16b..1be6176934 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4670,6 +4670,63 @@ static bool check_cpuid(CPUX86State *env, DisasContext 
*s, CheckCpuidFeat feat)
  env, s, modrm, is_write, arg));\
 }
 
+/*
+ * Generic load-store operand
+ */
+#define insnop_ldst(opTarg, opTptr) \
+insnop_ldst_ ## opTarg ## opTptr
+
+#define INSNOP_LDST(opTarg, opTptr) \
+static void insnop_ldst(opTarg, opTptr)(CPUX86State *env,   \
+DisasContext *s,\
+bool is_write,  \
+insnop_arg_t(opTarg) arg,   \
+insnop_arg_t(opTptr) ptr)
+
+#define DEF_INSNOP_LDST(opT, opTarg, opTptr)\
+typedef insnop_arg_t(opTarg) insnop_arg_t(opT); \
+typedef struct {\
+insnop_ctxt_t(opTarg) arg_ctxt; \
+insnop_ctxt_t(opTptr) ptr_ctxt; \
+insnop_arg_t(opTptr) ptr;   \
+} insnop_ctxt_t(opT);   \
+\
+/* forward declaration */   \
+INSNOP_LDST(opTarg, opTptr);\
+\
+INSNOP_INIT(opT)\
+{   \
+return insnop_init(opTarg)(>arg_ctxt, \
+   env, s, modrm, is_write) \
+&& insnop_init(opTptr)(>ptr_ctxt, \
+   env, s, modrm, is_write);\
+}   \
+INSNOP_PREPARE(opT) \
+{   \
+const insnop_arg_t(opTarg) arg =\
+insnop_prepare(opTarg)(>arg_ctxt, \
+   env, s, modrm, is_write);\
+ctxt->ptr = \
+insnop_prepare(opTptr)(>ptr_ctxt, \
+   env, s, modrm, is_write);\
+if (!is_write) {\
+insnop_ldst(opTarg, opTptr)(env, s, is_write,   \
+arg, ctxt->ptr);\
+}   \
+return arg; \
+}   \
+INSNOP_FINALIZE(opT)\
+{   \
+if (is_write) { \
+insnop_ldst(opTarg, opTptr)(env, s, is_write,   \
+arg, ctxt->ptr);\
+}   \
+insnop_finalize(opTptr)(>ptr_ctxt,\
+env, s, modrm, is_write, ctxt->ptr);\
+insnop_finalize(opTarg)(>arg_ctxt,\
+env, s, modrm, is_write, arg);  \
+}
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
 enum {
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 19/75] target/i386: introduce generic either-or operand

2019-08-21 Thread Jan Bobek
The either-or operand attempts to decode one operand, and if it fails,
it falls back to a second operand. It is unifying, meaning that
insnop_arg_t of the second operand must be implicitly castable to
insnop_arg_t of the first operand.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 44 +
 1 file changed, 44 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index a6f23bae4e..68c6b7d16b 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4626,6 +4626,50 @@ static bool check_cpuid(CPUX86State *env, DisasContext 
*s, CheckCpuidFeat feat)
 insnop_finalize(opT2)(ctxt, env, s, modrm, is_write, arg);  \
 }
 
+/*
+ * Generic unifying either-or operand
+ */
+#define DEF_INSNOP_EITHER(opT, opT1, opT2)  \
+typedef insnop_arg_t(opT1) insnop_arg_t(opT);   \
+typedef struct {\
+bool is_ ## opT1;   \
+union { \
+insnop_ctxt_t(opT1) ctxt_ ## opT1;  \
+insnop_ctxt_t(opT2) ctxt_ ## opT2;  \
+};  \
+} insnop_ctxt_t(opT);   \
+\
+INSNOP_INIT(opT)\
+{   \
+if (insnop_init(opT1)(>ctxt_ ## opT1, \
+  env, s, modrm, is_write)) {   \
+ctxt->is_ ## opT1 = true;   \
+return true;\
+}   \
+if (insnop_init(opT2)(>ctxt_ ## opT2, \
+  env, s, modrm, is_write)) {   \
+ctxt->is_ ## opT1 = false;  \
+return true;\
+}   \
+return false;   \
+}   \
+INSNOP_PREPARE(opT) \
+{   \
+return (ctxt->is_ ## opT1   \
+? insnop_prepare(opT1)(>ctxt_ ## opT1,\
+   env, s, modrm, is_write) \
+: insnop_prepare(opT2)(>ctxt_ ## opT2,\
+   env, s, modrm, is_write));   \
+}   \
+INSNOP_FINALIZE(opT)\
+{   \
+(ctxt->is_ ## opT1  \
+ ? insnop_finalize(opT1)(>ctxt_ ## opT1,  \
+ env, s, modrm, is_write, arg)  \
+ : insnop_finalize(opT2)(>ctxt_ ## opT2,  \
+ env, s, modrm, is_write, arg));\
+}
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
 enum {
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 16/75] target/i386: disable AVX/AVX2 cpuid bitchecks

2019-08-21 Thread Jan Bobek
Ignore the AVX/AVX2 cpuid bits when checking for availability of the
relevant instructions. This is clearly incorrect, but it preserves the
old behavior, which is useful during development.

Note: This changeset is intended for development only and shall not be
included in the final patch series.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 3e54443d99..e7c2ad41bf 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4564,15 +4564,15 @@ static bool check_cpuid(CPUX86State *env, DisasContext 
*s, CheckCpuidFeat feat)
 case CHECK_CPUID_PCLMULQDQ:
 return s->cpuid_ext_features & CPUID_EXT_PCLMULQDQ;
 case CHECK_CPUID_AVX:
-return s->cpuid_ext_features & CPUID_EXT_AVX;
+return true /* s->cpuid_ext_features & CPUID_EXT_AVX */;
 case CHECK_CPUID_AES_AVX:
-return (s->cpuid_ext_features & CPUID_EXT_AES)
-&& (s->cpuid_ext_features & CPUID_EXT_AVX);
+return s->cpuid_ext_features & CPUID_EXT_AES
+/* && (s->cpuid_ext_features & CPUID_EXT_AVX) */;
 case CHECK_CPUID_PCLMULQDQ_AVX:
-return (s->cpuid_ext_features & CPUID_EXT_PCLMULQDQ)
-&& (s->cpuid_ext_features & CPUID_EXT_AVX);
+return s->cpuid_ext_features & CPUID_EXT_PCLMULQDQ
+/* && (s->cpuid_ext_features & CPUID_EXT_AVX) */;
 case CHECK_CPUID_AVX2:
-return s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_AVX2;
+return true /* s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_AVX2 */;
 default:
 g_assert_not_reached();
 }
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 37/75] target/i386: introduce MMX code generators

2019-08-21 Thread Jan Bobek
Define code generators required for MMX instructions.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 100 
 1 file changed, 100 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 96ba0f5704..fdfca03071 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -5562,6 +5562,106 @@ INSNOP_LDST(xmm, Mhq)
 gen_gvec_ ## gvec(arg1, arg2, arg3, arg4, ## __VA_ARGS__);  \
 }
 
+GEN_INSN2(movq, Pq, Eq);/* forward declaration */
+GEN_INSN2(movd, Pq, Ed)
+{
+const insnop_arg_t(Eq) arg2_r64 = tcg_temp_new_i64();
+tcg_gen_extu_i32_i64(arg2_r64, arg2);
+gen_insn2(movq, Pq, Eq)(env, s, arg1, arg2_r64);
+tcg_temp_free_i64(arg2_r64);
+}
+GEN_INSN2(movd, Ed, Pq)
+{
+tcg_gen_ld_i32(arg1, cpu_env, arg2 + offsetof(MMXReg, MMX_L(0)));
+}
+
+GEN_INSN2(movq, Pq, Eq)
+{
+tcg_gen_st_i64(arg2, cpu_env, arg1 + offsetof(MMXReg, MMX_Q(0)));
+}
+GEN_INSN2(movq, Eq, Pq)
+{
+tcg_gen_ld_i64(arg1, cpu_env, arg2 + offsetof(MMXReg, MMX_Q(0)));
+}
+
+DEF_GEN_INSN2_GVEC(movq, Pq, Qq, mov, MM_OPRSZ, MM_MAXSZ, MO_64)
+DEF_GEN_INSN2_GVEC(movq, Qq, Pq, mov, MM_OPRSZ, MM_MAXSZ, MO_64)
+
+DEF_GEN_INSN3_GVEC(paddb, Pq, Pq, Qq, add, MM_OPRSZ, MM_MAXSZ, MO_8)
+DEF_GEN_INSN3_GVEC(paddw, Pq, Pq, Qq, add, MM_OPRSZ, MM_MAXSZ, MO_16)
+DEF_GEN_INSN3_GVEC(paddd, Pq, Pq, Qq, add, MM_OPRSZ, MM_MAXSZ, MO_32)
+DEF_GEN_INSN3_GVEC(paddsb, Pq, Pq, Qq, ssadd, MM_OPRSZ, MM_MAXSZ, MO_8)
+DEF_GEN_INSN3_GVEC(paddsw, Pq, Pq, Qq, ssadd, MM_OPRSZ, MM_MAXSZ, MO_16)
+DEF_GEN_INSN3_GVEC(paddusb, Pq, Pq, Qq, usadd, MM_OPRSZ, MM_MAXSZ, MO_8)
+DEF_GEN_INSN3_GVEC(paddusw, Pq, Pq, Qq, usadd, MM_OPRSZ, MM_MAXSZ, MO_16)
+
+DEF_GEN_INSN3_GVEC(psubb, Pq, Pq, Qq, sub, MM_OPRSZ, MM_MAXSZ, MO_8)
+DEF_GEN_INSN3_GVEC(psubw, Pq, Pq, Qq, sub, MM_OPRSZ, MM_MAXSZ, MO_16)
+DEF_GEN_INSN3_GVEC(psubd, Pq, Pq, Qq, sub, MM_OPRSZ, MM_MAXSZ, MO_32)
+DEF_GEN_INSN3_GVEC(psubsb, Pq, Pq, Qq, sssub, MM_OPRSZ, MM_MAXSZ, MO_8)
+DEF_GEN_INSN3_GVEC(psubsw, Pq, Pq, Qq, sssub, MM_OPRSZ, MM_MAXSZ, MO_16)
+DEF_GEN_INSN3_GVEC(psubusb, Pq, Pq, Qq, ussub, MM_OPRSZ, MM_MAXSZ, MO_8)
+DEF_GEN_INSN3_GVEC(psubusw, Pq, Pq, Qq, ussub, MM_OPRSZ, MM_MAXSZ, MO_16)
+
+DEF_GEN_INSN3_HELPER_EPP(pmullw, pmullw_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(pmulhw, pmulhw_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(pmaddwd, pmaddwd_mmx, Pq, Pq, Qq)
+
+DEF_GEN_INSN3_GVEC(pcmpeqb, Pq, Pq, Qq, cmp, MM_OPRSZ, MM_MAXSZ, MO_8, 
TCG_COND_EQ)
+DEF_GEN_INSN3_GVEC(pcmpeqw, Pq, Pq, Qq, cmp, MM_OPRSZ, MM_MAXSZ, MO_16, 
TCG_COND_EQ)
+DEF_GEN_INSN3_GVEC(pcmpeqd, Pq, Pq, Qq, cmp, MM_OPRSZ, MM_MAXSZ, MO_32, 
TCG_COND_EQ)
+DEF_GEN_INSN3_GVEC(pcmpgtb, Pq, Pq, Qq, cmp, MM_OPRSZ, MM_MAXSZ, MO_8, 
TCG_COND_GT)
+DEF_GEN_INSN3_GVEC(pcmpgtw, Pq, Pq, Qq, cmp, MM_OPRSZ, MM_MAXSZ, MO_16, 
TCG_COND_GT)
+DEF_GEN_INSN3_GVEC(pcmpgtd, Pq, Pq, Qq, cmp, MM_OPRSZ, MM_MAXSZ, MO_32, 
TCG_COND_GT)
+
+DEF_GEN_INSN3_GVEC(pand, Pq, Pq, Qq, and, MM_OPRSZ, MM_MAXSZ, MO_64)
+DEF_GEN_INSN3_GVEC(pandn, Pq, Pq, Qq, andn, MM_OPRSZ, MM_MAXSZ, MO_64)
+DEF_GEN_INSN3_GVEC(por, Pq, Pq, Qq, or, MM_OPRSZ, MM_MAXSZ, MO_64)
+DEF_GEN_INSN3_GVEC(pxor, Pq, Pq, Qq, xor, MM_OPRSZ, MM_MAXSZ, MO_64)
+
+DEF_GEN_INSN3_HELPER_EPP(psllw, psllw_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(pslld, pslld_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(psllq, psllq_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(psrlw, psrlw_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(psrld, psrld_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(psrlq, psrlq_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(psraw, psraw_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(psrad, psrad_mmx, Pq, Pq, Qq)
+
+#define DEF_GEN_PSHIFT_IMM_MM(mnem, opT1, opT2) \
+GEN_INSN3(mnem, opT1, opT2, Ib) \
+{   \
+const uint64_t arg3_ui64 = (uint8_t)arg3;   \
+const insnop_arg_t(Eq) arg3_r64 = s->tmp1_i64;  \
+const insnop_arg_t(Qq) arg3_mm =\
+offsetof(CPUX86State, mmx_t0.MMX_Q(0)); \
+\
+tcg_gen_movi_i64(arg3_r64, arg3_ui64);  \
+gen_insn2(movq, Pq, Eq)(env, s, arg3_mm, arg3_r64); \
+gen_insn3(mnem, Pq, Pq, Qq)(env, s, arg1, arg2, arg3_mm);   \
+}
+
+DEF_GEN_PSHIFT_IMM_MM(psllw, Nq, Nq)
+DEF_GEN_PSHIFT_IMM_MM(pslld, Nq, Nq)
+DEF_GEN_PSHIFT_IMM_MM(psllq, Nq, Nq)
+DEF_GEN_PSHIFT_IMM_MM(psrlw, Nq, Nq)
+DEF_GEN_PSHIFT_IMM_MM(psrld, Nq, Nq)
+DEF_GEN_PSHIFT_IMM_MM(psrlq, Nq, Nq)
+DEF_GEN_PSHIFT_IMM_MM(psraw, Nq, Nq)
+DEF_GEN_PSHIFT_IMM_MM(psrad, Nq, Nq)
+
+DEF_GEN_INSN3_HELPER_EPP(packsswb, packsswb_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(packssdw, packssdw_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(packuswb, packuswb_mmx, Pq, Pq,

[Qemu-devel] [RFC PATCH v4 18/75] target/i386: introduce generic operand alias

2019-08-21 Thread Jan Bobek
It turns out it is useful to be able to declare operand name
aliases. Introduce a macro to capture this functionality.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 78ef0e6608..a6f23bae4e 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4606,6 +4606,26 @@ static bool check_cpuid(CPUX86State *env, DisasContext 
*s, CheckCpuidFeat feat)
  int modrm, bool is_write,  \
  insnop_arg_t(opT) arg)
 
+/*
+ * Operand alias
+ */
+#define DEF_INSNOP_ALIAS(opT, opT2) \
+typedef insnop_arg_t(opT2) insnop_arg_t(opT);   \
+typedef insnop_ctxt_t(opT2) insnop_ctxt_t(opT); \
+\
+INSNOP_INIT(opT)\
+{   \
+return insnop_init(opT2)(ctxt, env, s, modrm, is_write);\
+}   \
+INSNOP_PREPARE(opT) \
+{   \
+return insnop_prepare(opT2)(ctxt, env, s, modrm, is_write); \
+}   \
+INSNOP_FINALIZE(opT)\
+{   \
+insnop_finalize(opT2)(ctxt, env, s, modrm, is_write, arg);  \
+}
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
 enum {
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 17/75] target/i386: introduce instruction operand infrastructure

2019-08-21 Thread Jan Bobek
insnop_arg_t, insnop_ctxt_t and init, prepare and finalize functions
form the basis of instruction operand decoding. Introduce macros for
defining a generic instruction operand; use cases for operand decoding
will be introduced later.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 28 
 1 file changed, 28 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index e7c2ad41bf..78ef0e6608 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4578,6 +4578,34 @@ static bool check_cpuid(CPUX86State *env, DisasContext 
*s, CheckCpuidFeat feat)
 }
 }
 
+/*
+ * Instruction operand
+ */
+#define insnop_arg_t(opT)insnop_ ## opT ## _arg_t
+#define insnop_ctxt_t(opT)   insnop_ ## opT ## _ctxt_t
+#define insnop_init(opT) insnop_ ## opT ## _init
+#define insnop_prepare(opT)  insnop_ ## opT ## _prepare
+#define insnop_finalize(opT) insnop_ ## opT ## _finalize
+
+#define INSNOP_INIT(opT)\
+static bool insnop_init(opT)(insnop_ctxt_t(opT) *ctxt,  \
+ CPUX86State *env,  \
+ DisasContext *s,   \
+ int modrm, bool is_write)
+
+#define INSNOP_PREPARE(opT) \
+static insnop_arg_t(opT) insnop_prepare(opT)(insnop_ctxt_t(opT) *ctxt, \
+ CPUX86State *env,  \
+ DisasContext *s,   \
+ int modrm, bool is_write)
+
+#define INSNOP_FINALIZE(opT)\
+static void insnop_finalize(opT)(insnop_ctxt_t(opT) *ctxt,  \
+ CPUX86State *env,  \
+ DisasContext *s,   \
+ int modrm, bool is_write,  \
+ insnop_arg_t(opT) arg)
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
 enum {
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 15/75] target/i386: introduce function check_cpuid

2019-08-21 Thread Jan Bobek
Introduce a helper function to take care of instruction CPUID checks.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 62 +
 1 file changed, 62 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 467ecf15ba..3e54443d99 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4516,6 +4516,68 @@ static void gen_sse(CPUX86State *env, DisasContext *s, 
int b)
 #define gen_gvec_cmp(dofs, aofs, bofs, oprsz, maxsz, vece, cond)\
 tcg_gen_gvec_cmp(cond, vece, dofs, aofs, bofs, oprsz, maxsz)
 
+typedef enum {
+CHECK_CPUID_MMX = 1,
+CHECK_CPUID_3DNOW,
+CHECK_CPUID_SSE,
+CHECK_CPUID_SSE2,
+CHECK_CPUID_CLFLUSH,
+CHECK_CPUID_SSE3,
+CHECK_CPUID_SSSE3,
+CHECK_CPUID_SSE4_1,
+CHECK_CPUID_SSE4_2,
+CHECK_CPUID_SSE4A,
+CHECK_CPUID_AES,
+CHECK_CPUID_PCLMULQDQ,
+CHECK_CPUID_AVX,
+CHECK_CPUID_AES_AVX,
+CHECK_CPUID_PCLMULQDQ_AVX,
+CHECK_CPUID_AVX2,
+} CheckCpuidFeat;
+
+static bool check_cpuid(CPUX86State *env, DisasContext *s, CheckCpuidFeat feat)
+{
+switch (feat) {
+case CHECK_CPUID_MMX:
+return (s->cpuid_features & CPUID_MMX)
+&& (s->cpuid_ext2_features & CPUID_EXT2_MMX);
+case CHECK_CPUID_3DNOW:
+return s->cpuid_ext2_features & CPUID_EXT2_3DNOW;
+case CHECK_CPUID_SSE:
+return s->cpuid_features & CPUID_SSE;
+case CHECK_CPUID_SSE2:
+return s->cpuid_features & CPUID_SSE2;
+case CHECK_CPUID_CLFLUSH:
+return s->cpuid_features & CPUID_CLFLUSH;
+case CHECK_CPUID_SSE3:
+return s->cpuid_ext_features & CPUID_EXT_SSE3;
+case CHECK_CPUID_SSSE3:
+return s->cpuid_ext_features & CPUID_EXT_SSSE3;
+case CHECK_CPUID_SSE4_1:
+return s->cpuid_ext_features & CPUID_EXT_SSE41;
+case CHECK_CPUID_SSE4_2:
+return s->cpuid_ext_features & CPUID_EXT_SSE42;
+case CHECK_CPUID_SSE4A:
+return s->cpuid_ext3_features & CPUID_EXT3_SSE4A;
+case CHECK_CPUID_AES:
+return s->cpuid_ext_features & CPUID_EXT_AES;
+case CHECK_CPUID_PCLMULQDQ:
+return s->cpuid_ext_features & CPUID_EXT_PCLMULQDQ;
+case CHECK_CPUID_AVX:
+return s->cpuid_ext_features & CPUID_EXT_AVX;
+case CHECK_CPUID_AES_AVX:
+return (s->cpuid_ext_features & CPUID_EXT_AES)
+&& (s->cpuid_ext_features & CPUID_EXT_AVX);
+case CHECK_CPUID_PCLMULQDQ_AVX:
+return (s->cpuid_ext_features & CPUID_EXT_PCLMULQDQ)
+&& (s->cpuid_ext_features & CPUID_EXT_AVX);
+case CHECK_CPUID_AVX2:
+return s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_AVX2;
+default:
+g_assert_not_reached();
+}
+}
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
 enum {
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 06/75] target/i386: Simplify gen_exception arguments

2019-08-21 Thread Jan Bobek
From: Richard Henderson 

We can compute cur_eip from values present within DisasContext.

Signed-off-by: Richard Henderson 
---
 target/i386/translate.c | 89 -
 1 file changed, 44 insertions(+), 45 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 410aa89c75..b067323962 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -1272,10 +1272,10 @@ static void gen_helper_fp_arith_STN_ST0(int op, int 
opreg)
 }
 }
 
-static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
+static void gen_exception(DisasContext *s, int trapno)
 {
 gen_update_cc_op(s);
-gen_jmp_im(s, cur_eip);
+gen_jmp_im(s, s->pc_start - s->cs_base);
 gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
 s->base.is_jmp = DISAS_NORETURN;
 }
@@ -1284,7 +1284,7 @@ static void gen_exception(DisasContext *s, int trapno, 
target_ulong cur_eip)
the instruction is known, but it isn't allowed in the current cpu mode.  */
 static void gen_illegal_opcode(DisasContext *s)
 {
-gen_exception(s, EXCP06_ILLOP, s->pc_start - s->cs_base);
+gen_exception(s, EXCP06_ILLOP);
 }
 
 /* if d == OR_TMP0, it means memory operand (address in A0) */
@@ -3040,8 +3040,7 @@ static const struct SSEOpHelper_eppi sse_op_table7[256] = 
{
 [0xdf] = AESNI_OP(aeskeygenassist),
 };
 
-static void gen_sse(CPUX86State *env, DisasContext *s, int b,
-target_ulong pc_start)
+static void gen_sse(CPUX86State *env, DisasContext *s, int b)
 {
 int b1, op1_offset, op2_offset, is_xmm, val;
 int modrm, mod, rm, reg;
@@ -3076,7 +3075,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, 
int b,
 }
 /* simple MMX/SSE operation */
 if (s->flags & HF_TS_MASK) {
-gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
+gen_exception(s, EXCP07_PREX);
 return;
 }
 if (s->flags & HF_EM_MASK) {
@@ -4669,7 +4668,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 
 s->pc_start = s->pc = pc_start;
 if (sigsetjmp(s->jmpbuf, 0) != 0) {
-gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
+gen_exception(s, EXCP0D_GPF);
 return s->pc;
 }
 
@@ -5868,7 +5867,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 if (s->flags & (HF_EM_MASK | HF_TS_MASK)) {
 /* if CR0.EM or CR0.TS are set, generate an FPU exception */
 /* XXX: what to do if illegal op ? */
-gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
+gen_exception(s, EXCP07_PREX);
 break;
 }
 modrm = x86_ldub_code(env, s);
@@ -6582,7 +6581,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 set_cc_op(s, CC_OP_EFLAGS);
 } else if (s->vm86) {
 if (s->iopl != 3) {
-gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
+gen_exception(s, EXCP0D_GPF);
 } else {
 gen_helper_iret_real(cpu_env, tcg_const_i32(s->dflag - 1));
 set_cc_op(s, CC_OP_EFLAGS);
@@ -6704,7 +6703,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 case 0x9c: /* pushf */
 gen_svm_check_intercept(s, pc_start, SVM_EXIT_PUSHF);
 if (s->vm86 && s->iopl != 3) {
-gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
+gen_exception(s, EXCP0D_GPF);
 } else {
 gen_update_cc_op(s);
 gen_helper_read_eflags(s->T0, cpu_env);
@@ -6714,7 +6713,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 case 0x9d: /* popf */
 gen_svm_check_intercept(s, pc_start, SVM_EXIT_POPF);
 if (s->vm86 && s->iopl != 3) {
-gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
+gen_exception(s, EXCP0D_GPF);
 } else {
 ot = gen_pop_T0(s);
 if (s->cpl == 0) {
@@ -7031,7 +7030,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 goto illegal_op;
 val = x86_ldub_code(env, s);
 if (val == 0) {
-gen_exception(s, EXCP00_DIVZ, pc_start - s->cs_base);
+gen_exception(s, EXCP00_DIVZ);
 } else {
 gen_helper_aam(cpu_env, tcg_const_i32(val));
 set_cc_op(s, CC_OP_LOGICB);
@@ -7065,7 +7064,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 case 0x9b: /* fwait */
 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
 (HF_MP_MASK | HF_TS_MASK)) {
-gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
+gen_exception(s, EXCP07_PREX);
 } else {
 gen_helper_fwait(cpu_env);
 }
@@ -7076,7 +7075,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 case 0xcd: /* int N */
 val = x86_ldub_code(env, s);
 if (s->vm86 && s->iopl != 3) {
-

[Qemu-devel] [RFC PATCH v4 32/75] target/i386: introduce helper-based code generator macros

2019-08-21 Thread Jan Bobek
Code generators defined using these macros rely on a helper function
(as emitted by gen_helper_*).

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 160 
 1 file changed, 160 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 603a5b80a1..046914578b 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -5377,6 +5377,166 @@ INSNOP_LDST(xmm, Mhq)
 insnop_arg_t(opT3) arg3, insnop_arg_t(opT4) arg4,   \
 insnop_arg_t(opT5) arg5)
 
+#define DEF_GEN_INSN0_HELPER(mnem, helper)  \
+GEN_INSN0(mnem) \
+{   \
+gen_helper_ ## helper(cpu_env); \
+}
+
+#define DEF_GEN_INSN2_HELPER_EPD(mnem, helper, opT1, opT2)  \
+GEN_INSN2(mnem, opT1, opT2) \
+{   \
+const TCGv_ptr arg1_ptr = tcg_temp_new_ptr();   \
+\
+tcg_gen_addi_ptr(arg1_ptr, cpu_env, arg1);  \
+gen_helper_ ## helper(cpu_env, arg1_ptr, arg2); \
+\
+tcg_temp_free_ptr(arg1_ptr);\
+}
+#define DEF_GEN_INSN2_HELPER_DEP(mnem, helper, opT1, opT2)  \
+GEN_INSN2(mnem, opT1, opT2) \
+{   \
+const TCGv_ptr arg2_ptr = tcg_temp_new_ptr();   \
+\
+tcg_gen_addi_ptr(arg2_ptr, cpu_env, arg2);  \
+gen_helper_ ## helper(arg1, cpu_env, arg2_ptr); \
+\
+tcg_temp_free_ptr(arg2_ptr);\
+}
+#ifdef TARGET_X86_64
+#define DEF_GEN_INSN2_HELPER_EPQ(mnem, helper, opT1, opT2)  \
+DEF_GEN_INSN2_HELPER_EPD(mnem, helper, opT1, opT2)
+#define DEF_GEN_INSN2_HELPER_QEP(mnem, helper, opT1, opT2)  \
+DEF_GEN_INSN2_HELPER_DEP(mnem, helper, opT1, opT2)
+#else /* !TARGET_X86_64 */
+#define DEF_GEN_INSN2_HELPER_EPQ(mnem, helper, opT1, opT2)  \
+GEN_INSN2(mnem, opT1, opT2) \
+{   \
+g_assert_not_reached(); \
+}
+#define DEF_GEN_INSN2_HELPER_QEP(mnem, helper, opT1, opT2)  \
+GEN_INSN2(mnem, opT1, opT2) \
+{   \
+g_assert_not_reached(); \
+}
+#endif /* !TARGET_X86_64 */
+#define DEF_GEN_INSN2_HELPER_EPP(mnem, helper, opT1, opT2)  \
+GEN_INSN2(mnem, opT1, opT2) \
+{   \
+const TCGv_ptr arg1_ptr = tcg_temp_new_ptr();   \
+const TCGv_ptr arg2_ptr = tcg_temp_new_ptr();   \
+\
+tcg_gen_addi_ptr(arg1_ptr, cpu_env, arg1);  \
+tcg_gen_addi_ptr(arg2_ptr, cpu_env, arg2);  \
+gen_helper_ ## helper(cpu_env, arg1_ptr, arg2_ptr); \
+\
+tcg_temp_free_ptr(arg1_ptr);\
+tcg_temp_free_ptr(arg2_ptr);\
+}
+
+#define DEF_GEN_INSN3_HELPER_EPD(mnem, helper, opT1, opT2, opT3)\
+GEN_INSN3(mnem, opT1, opT2, opT3)   \
+{   \
+const TCGv_ptr arg1_ptr = tcg_temp_new_ptr();   \
+\
+assert(arg1 == arg2);   \
+tcg_gen_addi_ptr(arg1_ptr, cpu_env, arg1);  \
+gen_helper_ ## helper(cpu_env, arg1_ptr, arg3); \
+\
+tcg_temp_free_ptr(arg1_ptr);\
+}
+#ifdef TARGET_X86_64
+#define DEF_GEN_INSN3_HELPER_EPQ(mnem, helper, opT1, opT2, opT3)\
+DEF_GEN_INSN3_HELPER_EPD(mnem, helper, opT1, opT2, opT3)
+#else /* !TARGET_X86_64 */
+#define DEF_GEN_INSN3_HELPER_EPQ(mnem, helper, opT1, opT2, opT3)\
+GEN_INSN3(mnem, opT1, opT2, opT3)   \
+{   \
+g_assert_not_reached(); \
+}
+#endif /* !TARGET_X86_64 */
+#define DEF_GEN_INSN3_HELPER_EPP(mnem, helper

[Qemu-devel] [RFC PATCH v4 07/75] target/i386: use pc_start from DisasContext

2019-08-21 Thread Jan Bobek
The variable pc_start is already a member of DisasContext. Remove the
superfluous local variable.

Reviewed-by: Richard Henderson 
Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 131 
 1 file changed, 65 insertions(+), 66 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index b067323962..62cce20735 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4664,9 +4664,8 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 TCGMemOp ot;
 int modrm, reg, rm, mod, op, opreg, val;
 target_ulong next_eip, tval;
-target_ulong pc_start = s->base.pc_next;
 
-s->pc_start = s->pc = pc_start;
+s->pc_start = s->pc = s->base.pc_next;
 if (sigsetjmp(s->jmpbuf, 0) != 0) {
 gen_exception(s, EXCP0D_GPF);
 return s->pc;
@@ -6371,7 +6370,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 case 0xa5:
 ot = mo_b_d(b, s->dflag);
 if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
-gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
+gen_repz_movs(s, ot, s->pc_start - s->cs_base, s->pc - s->cs_base);
 } else {
 gen_movs(s, ot);
 }
@@ -6381,7 +6380,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 case 0xab:
 ot = mo_b_d(b, s->dflag);
 if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
-gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
+gen_repz_stos(s, ot, s->pc_start - s->cs_base, s->pc - s->cs_base);
 } else {
 gen_stos(s, ot);
 }
@@ -6390,7 +6389,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 case 0xad:
 ot = mo_b_d(b, s->dflag);
 if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
-gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
+gen_repz_lods(s, ot, s->pc_start - s->cs_base, s->pc - s->cs_base);
 } else {
 gen_lods(s, ot);
 }
@@ -6399,9 +6398,9 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 case 0xaf:
 ot = mo_b_d(b, s->dflag);
 if (s->prefix & PREFIX_REPNZ) {
-gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
+gen_repz_scas(s, ot, s->pc_start - s->cs_base, s->pc - s->cs_base, 
1);
 } else if (s->prefix & PREFIX_REPZ) {
-gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
+gen_repz_scas(s, ot, s->pc_start - s->cs_base, s->pc - s->cs_base, 
0);
 } else {
 gen_scas(s, ot);
 }
@@ -6411,9 +6410,9 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 case 0xa7:
 ot = mo_b_d(b, s->dflag);
 if (s->prefix & PREFIX_REPNZ) {
-gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
+gen_repz_cmps(s, ot, s->pc_start - s->cs_base, s->pc - s->cs_base, 
1);
 } else if (s->prefix & PREFIX_REPZ) {
-gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
+gen_repz_cmps(s, ot, s->pc_start - s->cs_base, s->pc - s->cs_base, 
0);
 } else {
 gen_cmps(s, ot);
 }
@@ -6422,10 +6421,10 @@ static target_ulong disas_insn(DisasContext *s, 
CPUState *cpu)
 case 0x6d:
 ot = mo_b_d32(b, s->dflag);
 tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]);
-gen_check_io(s, ot, pc_start - s->cs_base, 
+gen_check_io(s, ot, s->pc_start - s->cs_base,
  SVM_IOIO_TYPE_MASK | svm_is_rep(s->prefix) | 4);
 if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
-gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
+gen_repz_ins(s, ot, s->pc_start - s->cs_base, s->pc - s->cs_base);
 } else {
 gen_ins(s, ot);
 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
@@ -6437,10 +6436,10 @@ static target_ulong disas_insn(DisasContext *s, 
CPUState *cpu)
 case 0x6f:
 ot = mo_b_d32(b, s->dflag);
 tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]);
-gen_check_io(s, ot, pc_start - s->cs_base,
+gen_check_io(s, ot, s->pc_start - s->cs_base,
  svm_is_rep(s->prefix) | 4);
 if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
-gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
+gen_repz_outs(s, ot, s->pc_start - s->cs_base, s->pc - s->cs_base);
 } else {
 gen_outs(s, ot);
 if (tb_cflags(s

[Qemu-devel] [RFC PATCH v4 13/75] target/i386: decode the 0F38/0F3A prefix in gen_sse_ng

2019-08-21 Thread Jan Bobek
In order to decode 0F38/0F3A-prefixed instructions, we need to load an
additional byte. This poses a problem if the instruction is not
implemented yet; implement a rewind in this (default) case.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 661010973b..bd9c62dc54 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4545,7 +4545,23 @@ static void gen_sse_ng(CPUX86State *env, DisasContext 
*s, int b)
 #define CASES_VEX_LIG(e, N, ...)  CASES_VEX_L128(e, N, ## __VA_ARGS__)  \
   CASES_VEX_L256(e, N, ## __VA_ARGS__)
 
+CASES(0x38, 3, W, IG, M, 0F, P, IG)
+CASES(0x38, 4, W, IG, M, 0F, P, IG, VEX_L, IG) {
+m = M_0F38;
+op = x86_ldub_code(env, s);
+} break;
+
+CASES(0x3a, 3, W, IG, M, 0F, P, IG)
+CASES(0x3a, 4, W, IG, M, 0F, P, IG, VEX_L, IG) {
+m = M_0F3A;
+op = x86_ldub_code(env, s);
+} break;
+
 default: {
+if (m == M_0F38 || m == M_0F3A) {
+/* rewind the advance_pc() x86_ldub_code() did */
+advance_pc(env, s, -1);
+}
 gen_sse(env, s, b);
 } return;
 
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 27/75] target/i386: introduce G*, R*, E* (general register) operands

2019-08-21 Thread Jan Bobek
These address the general-purpose register file. The corresponding
32-bit or 64-bit register is passed as the operand value.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 88 +
 1 file changed, 88 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 46c41cc3be..d6d32c7f06 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4944,6 +4944,94 @@ DEF_INSNOP_ALIAS(Mq, M)
 DEF_INSNOP_ALIAS(Mdq, M)
 DEF_INSNOP_ALIAS(Mqq, M)
 
+/*
+ * 32-bit general register operands
+ */
+DEF_INSNOP_LDST(Gd, tcg_i32, modrm_reg)
+DEF_INSNOP_LDST(Rd, tcg_i32, modrm_rm_direct)
+
+INSNOP_LDST(tcg_i32, modrm_reg)
+{
+assert(0 <= ptr && ptr < CPU_NB_REGS);
+if (is_write) {
+tcg_gen_extu_i32_tl(cpu_regs[ptr], arg);
+} else {
+tcg_gen_trunc_tl_i32(arg, cpu_regs[ptr]);
+}
+}
+INSNOP_LDST(tcg_i32, modrm_rm_direct)
+{
+insnop_ldst(tcg_i32, modrm_reg)(env, s, is_write, arg, ptr);
+}
+
+DEF_INSNOP_LDST(MEd, tcg_i32, Md)
+DEF_INSNOP_EITHER(Ed, Rd, MEd)
+DEF_INSNOP_LDST(MRdMw, tcg_i32, Mw)
+DEF_INSNOP_EITHER(RdMw, Rd, MRdMw)
+DEF_INSNOP_LDST(MRdMb, tcg_i32, Mb)
+DEF_INSNOP_EITHER(RdMb, Rd, MRdMb)
+
+INSNOP_LDST(tcg_i32, Md)
+{
+if (is_write) {
+tcg_gen_qemu_st_i32(arg, ptr, s->mem_index, MO_LEUL);
+} else {
+tcg_gen_qemu_ld_i32(arg, ptr, s->mem_index, MO_LEUL);
+}
+}
+INSNOP_LDST(tcg_i32, Mw)
+{
+if (is_write) {
+tcg_gen_qemu_st_i32(arg, ptr, s->mem_index, MO_LEUW);
+} else {
+tcg_gen_qemu_ld_i32(arg, ptr, s->mem_index, MO_LEUW);
+}
+}
+INSNOP_LDST(tcg_i32, Mb)
+{
+if (is_write) {
+tcg_gen_qemu_st_i32(arg, ptr, s->mem_index, MO_UB);
+} else {
+tcg_gen_qemu_ld_i32(arg, ptr, s->mem_index, MO_UB);
+}
+}
+
+/*
+ * 64-bit general register operands
+ */
+DEF_INSNOP_LDST(Gq, tcg_i64, modrm_reg)
+DEF_INSNOP_LDST(Rq, tcg_i64, modrm_rm_direct)
+
+INSNOP_LDST(tcg_i64, modrm_reg)
+{
+#ifdef TARGET_X86_64
+assert(0 <= ptr && ptr < CPU_NB_REGS);
+if (is_write) {
+tcg_gen_mov_i64(cpu_regs[ptr], arg);
+} else {
+tcg_gen_mov_i64(arg, cpu_regs[ptr]);
+}
+#else /* !TARGET_X86_64 */
+g_assert_not_reached();
+#endif /* !TARGET_X86_64 */
+}
+INSNOP_LDST(tcg_i64, modrm_rm_direct)
+{
+insnop_ldst(tcg_i64, modrm_reg)(env, s, is_write, arg, ptr);
+}
+
+DEF_INSNOP_LDST(MEq, tcg_i64, Mq)
+DEF_INSNOP_EITHER(Eq, Rq, MEq)
+
+INSNOP_LDST(tcg_i64, Mq)
+{
+if (is_write) {
+tcg_gen_qemu_st_i64(arg, ptr, s->mem_index, MO_LEQ);
+} else {
+tcg_gen_qemu_ld_i64(arg, ptr, s->mem_index, MO_LEQ);
+}
+}
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
 enum {
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 03/75] target/i386: use dflag from DisasContext

2019-08-21 Thread Jan Bobek
There already is a variable dflag in DisasContext, so use that one
rather than the identically-named local helper variable.

Suggested-by: Richard Henderson 
Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 180 
 1 file changed, 90 insertions(+), 90 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 9ec1c79371..7226c67d2e 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4682,7 +4682,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 op = (b >> 3) & 7;
 f = (b >> 1) & 3;
 
-ot = mo_b_d(b, dflag);
+ot = mo_b_d(b, s->dflag);
 
 switch(f) {
 case 0: /* OP Ev, Gv */
@@ -4740,7 +4740,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 {
 int val;
 
-ot = mo_b_d(b, dflag);
+ot = mo_b_d(b, s->dflag);
 
 modrm = x86_ldub_code(env, s);
 mod = (modrm >> 6) & 3;
@@ -4777,16 +4777,16 @@ static target_ulong disas_insn(DisasContext *s, 
CPUState *cpu)
 /**/
 /* inc, dec, and other misc arith */
 case 0x40 ... 0x47: /* inc Gv */
-ot = dflag;
+ot = s->dflag;
 gen_inc(s, ot, OR_EAX + (b & 7), 1);
 break;
 case 0x48 ... 0x4f: /* dec Gv */
-ot = dflag;
+ot = s->dflag;
 gen_inc(s, ot, OR_EAX + (b & 7), -1);
 break;
 case 0xf6: /* GRP3 */
 case 0xf7:
-ot = mo_b_d(b, dflag);
+ot = mo_b_d(b, s->dflag);
 
 modrm = x86_ldub_code(env, s);
 mod = (modrm >> 6) & 3;
@@ -5018,7 +5018,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 
 case 0xfe: /* GRP4 */
 case 0xff: /* GRP5 */
-ot = mo_b_d(b, dflag);
+ot = mo_b_d(b, s->dflag);
 
 modrm = x86_ldub_code(env, s);
 mod = (modrm >> 6) & 3;
@@ -5032,10 +5032,10 @@ static target_ulong disas_insn(DisasContext *s, 
CPUState *cpu)
 /* operand size for jumps is 64 bit */
 ot = MO_64;
 } else if (op == 3 || op == 5) {
-ot = dflag != MO_16 ? MO_32 + (REX_W(s) == 1) : MO_16;
+ot = s->dflag != MO_16 ? MO_32 + (REX_W(s) == 1) : MO_16;
 } else if (op == 6) {
 /* default push size is 64 bit */
-ot = mo_pushpop(s, dflag);
+ot = mo_pushpop(s, s->dflag);
 }
 }
 if (mod != 3) {
@@ -5063,7 +5063,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 break;
 case 2: /* call Ev */
 /* XXX: optimize if memory (no 'and' is necessary) */
-if (dflag == MO_16) {
+if (s->dflag == MO_16) {
 tcg_gen_ext16u_tl(s->T0, s->T0);
 }
 next_eip = s->pc - s->cs_base;
@@ -5081,19 +5081,19 @@ static target_ulong disas_insn(DisasContext *s, 
CPUState *cpu)
 if (s->pe && !s->vm86) {
 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
 gen_helper_lcall_protected(cpu_env, s->tmp2_i32, s->T1,
-   tcg_const_i32(dflag - 1),
+   tcg_const_i32(s->dflag - 1),
tcg_const_tl(s->pc - s->cs_base));
 } else {
 tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0);
 gen_helper_lcall_real(cpu_env, s->tmp2_i32, s->T1,
-  tcg_const_i32(dflag - 1),
+  tcg_const_i32(s->dflag - 1),
   tcg_const_i32(s->pc - s->cs_base));
 }
 tcg_gen_ld_tl(s->tmp4, cpu_env, offsetof(CPUX86State, eip));
 gen_jr(s, s->tmp4);
 break;
 case 4: /* jmp Ev */
-if (dflag == MO_16) {
+if (s->dflag == MO_16) {
 tcg_gen_ext16u_tl(s->T0, s->T0);
 }
 gen_op_jmp_v(s->T0);
@@ -5126,7 +5126,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 
 case 0x84: /* test Ev, Gv */
 case 0x85:
-ot = mo_b_d(b, dflag);
+ot = mo_b_d(b, s->dflag);
 
 modrm = x86_ldub_code(env, s);
 reg = ((modrm >> 3) & 7) | REX_R(s);
@@ -5139,7 +5139,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 
 case 0xa8: /* test eAX, Iv */
 case 0xa9:
-ot = mo_b_d(b, dflag);
+ot = mo_b_d(b, s->dflag);
 val = insn_get(env, s, ot);
 
 gen_op_mov_v_reg(s, ot, s->T0, OR_EAX);
@@ -5149,7 +5149,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
  

[Qemu-devel] [RFC PATCH v4 08/75] target/i386: make variable b1 const

2019-08-21 Thread Jan Bobek
The variable b1 does not change value once assigned. Make this fact
explicit by marking it const.

Reviewed-by: Richard Henderson 
Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 15 ++-
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 62cce20735..3be869a8e3 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -3042,7 +3042,7 @@ static const struct SSEOpHelper_eppi sse_op_table7[256] = 
{
 
 static void gen_sse(CPUX86State *env, DisasContext *s, int b)
 {
-int b1, op1_offset, op2_offset, is_xmm, val;
+int op1_offset, op2_offset, is_xmm, val;
 int modrm, mod, rm, reg;
 SSEFunc_0_epp sse_fn_epp;
 SSEFunc_0_eppi sse_fn_eppi;
@@ -3051,14 +3051,11 @@ static void gen_sse(CPUX86State *env, DisasContext *s, 
int b)
 TCGMemOp ot;
 
 b &= 0xff;
-if (s->prefix & PREFIX_DATA)
-b1 = 1;
-else if (s->prefix & PREFIX_REPZ)
-b1 = 2;
-else if (s->prefix & PREFIX_REPNZ)
-b1 = 3;
-else
-b1 = 0;
+const int b1 =
+s->prefix & PREFIX_DATA ? 1
+: s->prefix & PREFIX_REPZ ? 2
+: s->prefix & PREFIX_REPNZ ? 3
+: 0;
 sse_fn_epp = sse_op_table1[b][b1];
 if (!sse_fn_epp) {
 goto unknown_op;
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 12/75] target/i386: introduce CASES_* macros in gen_sse_ng

2019-08-21 Thread Jan Bobek
In case one or more fields should be ignored during instruction
disambiguation, we need to generate multiple case labels. Introduce
CASES_* macros for this purpose.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 54 +
 1 file changed, 54 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 8045ce3ce0..661010973b 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4513,10 +4513,64 @@ static void gen_sse_ng(CPUX86State *env, DisasContext 
*s, int b)
 while (1) {
 switch (p | m | w | op) {
 
+#define CASES_0(e) case (e):
+#define CASES_1(e, A, ...) CASES_ ## A(e, 0, ## __VA_ARGS__)
+#define CASES_2(e, A, ...) CASES_ ## A(e, 1, ## __VA_ARGS__)
+#define CASES_3(e, A, ...) CASES_ ## A(e, 2, ## __VA_ARGS__)
+#define CASES_4(e, A, ...) CASES_ ## A(e, 3, ## __VA_ARGS__)
+#define CASES(e, N, ...)   CASES_ ## N(e, ## __VA_ARGS__)
+
+#define CASES_P(e, N, p, ...) CASES_P ## p(e, N, ## __VA_ARGS__)
+#define CASES_PNP(e, N, ...)  CASES_ ## N(P_NP | e, ## __VA_ARGS__)
+#define CASES_P66(e, N, ...)  CASES_ ## N(P_66 | e, ## __VA_ARGS__)
+#define CASES_PF3(e, N, ...)  CASES_ ## N(P_F3 | e, ## __VA_ARGS__)
+#define CASES_PF2(e, N, ...)  CASES_ ## N(P_F2 | e, ## __VA_ARGS__)
+#define CASES_PIG(e, N, ...)  CASES_PNP(e, N, ## __VA_ARGS__)   \
+  CASES_P66(e, N, ## __VA_ARGS__)   \
+  CASES_PF3(e, N, ## __VA_ARGS__)   \
+  CASES_PF2(e, N, ## __VA_ARGS__)
+
+#define CASES_M(e, N, m, ...) CASES_ ## N(M_ ## m | e, ## __VA_ARGS__)
+
+#define CASES_W(e, N, w, ...) CASES_W ## w(e, N, ## __VA_ARGS__)
+#define CASES_W0(e, N, ...)   CASES_ ## N(W_0 | e, ## __VA_ARGS__)
+#define CASES_W1(e, N, ...)   CASES_ ## N(W_1 | e, ## __VA_ARGS__)
+#define CASES_WIG(e, N, ...)  CASES_W0(e, N, ## __VA_ARGS__)\
+  CASES_W1(e, N, ## __VA_ARGS__)
+
+#define CASES_VEX_L(e, N, l, ...) CASES_VEX_L ## l(e, N, ## __VA_ARGS__)
+#define CASES_VEX_L128(e, N, ...) CASES_ ## N(VEX_128 | e, ## __VA_ARGS__)
+#define CASES_VEX_L256(e, N, ...) CASES_ ## N(VEX_256 | e, ## __VA_ARGS__)
+#define CASES_VEX_LZ  CASES_VEX_L128
+#define CASES_VEX_LIG(e, N, ...)  CASES_VEX_L128(e, N, ## __VA_ARGS__)  \
+  CASES_VEX_L256(e, N, ## __VA_ARGS__)
+
 default: {
 gen_sse(env, s, b);
 } return;
 
+#undef CASES_0
+#undef CASES_1
+#undef CASES_2
+#undef CASES_3
+#undef CASES_4
+#undef CASES
+#undef CASES_P
+#undef CASES_PNP
+#undef CASES_P66
+#undef CASES_PF3
+#undef CASES_PF2
+#undef CASES_PIG
+#undef CASES_M
+#undef CASES_W
+#undef CASES_W0
+#undef CASES_W1
+#undef CASES_WIG
+#undef CASES_VEX_L
+#undef CASES_VEX_L128
+#undef CASES_VEX_L256
+#undef CASES_VEX_LZ
+#undef CASES_VEX_LIG
 }
 }
 }
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 25/75] target/i386: introduce Ib (immediate) operand

2019-08-21 Thread Jan Bobek
Introduce the immediate-byte operand, which loads a byte from the
instruction stream and passes its value as the operand.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 886f64a58f..9f02ea58d1 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4890,6 +4890,24 @@ INSNOP_FINALIZE(modrm_rm_direct)
 insnop_finalize(modrm_rm)(>rm, env, s, modrm, is_write, arg);
 }
 
+/*
+ * Immediate operand
+ */
+typedef uint8_t insnop_arg_t(Ib);
+typedef struct {} insnop_ctxt_t(Ib);
+
+INSNOP_INIT(Ib)
+{
+return true;
+}
+INSNOP_PREPARE(Ib)
+{
+return x86_ldub_code(env, s);
+}
+INSNOP_FINALIZE(Ib)
+{
+}
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
 enum {
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 05/75] target/i386: introduce disas_insn_prefix

2019-08-21 Thread Jan Bobek
Move the code for decoding an instruction prefix into a separate
function.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 48 +
 1 file changed, 34 insertions(+), 14 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 99a9097c49..410aa89c75 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4486,19 +4486,11 @@ static void gen_sse(CPUX86State *env, DisasContext *s, 
int b,
 }
 }
 
-/* convert one instruction. s->base.is_jmp is set if the translation must
-   be stopped. Return the next pc value */
-static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
+static int disas_insn_prefix(DisasContext *s, CPUX86State *env)
 {
-CPUX86State *env = cpu->env_ptr;
 int b, prefixes;
-int shift;
-TCGMemOp ot, aflag, dflag;
-int modrm, reg, rm, mod, op, opreg, val;
-target_ulong next_eip, tval;
-target_ulong pc_start = s->base.pc_next;
+TCGMemOp aflag, dflag;
 
-s->pc_start = s->pc = pc_start;
 s->override = -1;
 #ifdef TARGET_X86_64
 s->rex_x = 0;
@@ -4510,10 +4502,6 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 s->rip_offset = 0; /* for relative ip address */
 s->vex_l = 0;
 s->vex_v = 0;
-if (sigsetjmp(s->jmpbuf, 0) != 0) {
-gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
-return s->pc;
-}
 
 prefixes = 0;
 
@@ -4657,6 +4645,38 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 s->prefix = prefixes;
 s->aflag = aflag;
 s->dflag = dflag;
+return b;
+illegal_op:
+gen_illegal_opcode(s);
+return -1;
+unknown_op:
+gen_unknown_opcode(env, s);
+return -1;
+}
+
+/*
+ * convert one instruction. s->base.is_jmp is set if the translation must
+ * be stopped. Return the next pc value.
+ */
+static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
+{
+CPUX86State *env = cpu->env_ptr;
+int b, shift;
+TCGMemOp ot;
+int modrm, reg, rm, mod, op, opreg, val;
+target_ulong next_eip, tval;
+target_ulong pc_start = s->base.pc_next;
+
+s->pc_start = s->pc = pc_start;
+if (sigsetjmp(s->jmpbuf, 0) != 0) {
+gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
+return s->pc;
+}
+
+b = disas_insn_prefix(s, env);
+if (b < 0) {
+return s->pc;
+}
 
 /* now check op code */
  reswitch:
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 09/75] target/i386: make variable is_xmm const

2019-08-21 Thread Jan Bobek
The variable is_xmm does not change value after assignment, so make
this fact explicit by marking it const.

Reviewed-by: Richard Henderson 
Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 17 ++---
 1 file changed, 6 insertions(+), 11 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 3be869a8e3..44ad55f9ee 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -3042,7 +3042,7 @@ static const struct SSEOpHelper_eppi sse_op_table7[256] = 
{
 
 static void gen_sse(CPUX86State *env, DisasContext *s, int b)
 {
-int op1_offset, op2_offset, is_xmm, val;
+int op1_offset, op2_offset, val;
 int modrm, mod, rm, reg;
 SSEFunc_0_epp sse_fn_epp;
 SSEFunc_0_eppi sse_fn_eppi;
@@ -3056,20 +3056,15 @@ static void gen_sse(CPUX86State *env, DisasContext *s, 
int b)
 : s->prefix & PREFIX_REPZ ? 2
 : s->prefix & PREFIX_REPNZ ? 3
 : 0;
+const int is_xmm =
+(0x10 <= b && b <= 0x5f)
+|| b == 0xc6
+|| b == 0xc2
+|| !!b1;
 sse_fn_epp = sse_op_table1[b][b1];
 if (!sse_fn_epp) {
 goto unknown_op;
 }
-if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) {
-is_xmm = 1;
-} else {
-if (b1 == 0) {
-/* MMX case */
-is_xmm = 0;
-} else {
-is_xmm = 1;
-}
-}
 /* simple MMX/SSE operation */
 if (s->flags & HF_TS_MASK) {
 gen_exception(s, EXCP07_PREX);
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 21/75] target/i386: introduce tcg register operands

2019-08-21 Thread Jan Bobek
TCG operands allocate a 32-bit or 64-bit TCG temporary and later
automatically free it.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 44 +
 1 file changed, 44 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 1be6176934..80cfb59978 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4727,6 +4727,50 @@ static bool check_cpuid(CPUX86State *env, DisasContext 
*s, CheckCpuidFeat feat)
 env, s, modrm, is_write, arg);  \
 }
 
+/*
+ * tcg_i32
+ *
+ * Operand which allocates a 32-bit TCG temporary and frees it
+ * automatically after use.
+ */
+typedef TCGv_i32 insnop_arg_t(tcg_i32);
+typedef struct {} insnop_ctxt_t(tcg_i32);
+
+INSNOP_INIT(tcg_i32)
+{
+return true;
+}
+INSNOP_PREPARE(tcg_i32)
+{
+return tcg_temp_new_i32();
+}
+INSNOP_FINALIZE(tcg_i32)
+{
+tcg_temp_free_i32(arg);
+}
+
+/*
+ * tcg_i64
+ *
+ * Operand which allocates a 64-bit TCG temporary and frees it
+ * automatically after use.
+ */
+typedef TCGv_i64 insnop_arg_t(tcg_i64);
+typedef struct {} insnop_ctxt_t(tcg_i64);
+
+INSNOP_INIT(tcg_i64)
+{
+return true;
+}
+INSNOP_PREPARE(tcg_i64)
+{
+return tcg_temp_new_i64();
+}
+INSNOP_FINALIZE(tcg_i64)
+{
+tcg_temp_free_i64(arg);
+}
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
 enum {
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 11/75] target/i386: introduce gen_sse_ng

2019-08-21 Thread Jan Bobek
This function serves as the point-of-intercept for all newly
implemented instructions. If no new implementation exists, fall back
to gen_sse.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 46 -
 1 file changed, 45 insertions(+), 1 deletion(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 44ad55f9ee..8045ce3ce0 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4477,6 +4477,50 @@ static void gen_sse(CPUX86State *env, DisasContext *s, 
int b)
 }
 }
 
+static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
+{
+enum {
+P_NP = 0,
+P_66 = 1 << 8,
+P_F3 = 1 << 9,
+P_F2 = 1 << 10,
+
+M_NA   = 0,
+M_0F   = 1 << 11,
+M_0F38 = 1 << 12,
+M_0F3A = 1 << 13,
+
+W_0 = 0,
+W_1 = 1 << 14,
+
+VEX_128 = 1 << 15,
+VEX_256 = 1 << 16,
+};
+
+const int p =
+(s->prefix & PREFIX_DATA ? P_66 : 0)
+| (s->prefix & PREFIX_REPZ ? P_F3 : 0)
+| (s->prefix & PREFIX_REPNZ ? P_F2 : 0)
+| (!(s->prefix & PREFIX_VEX) ? 0 :
+   (s->vex_l ? VEX_256 : VEX_128));
+int m =
+M_0F;
+const int w =
+REX_W(s) > 0 ? W_1 : W_0;
+int op =
+b & 0xff;
+
+while (1) {
+switch (p | m | w | op) {
+
+default: {
+gen_sse(env, s, b);
+} return;
+
+}
+}
+}
+
 static int disas_insn_prefix(DisasContext *s, CPUX86State *env)
 {
 int b, prefixes;
@@ -8372,7 +8416,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 case 0x1c2:
 case 0x1c4 ... 0x1c6:
 case 0x1d0 ... 0x1fe:
-gen_sse(env, s, b);
+gen_sse_ng(env, s, b);
 break;
 default:
 goto unknown_op;
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 01/75] target/i386: Push rex_r into DisasContext

2019-08-21 Thread Jan Bobek
From: Richard Henderson 

Treat this value the same as we do for rex_b and rex_x.

Signed-off-by: Richard Henderson 
---
 target/i386/translate.c | 85 +
 1 file changed, 44 insertions(+), 41 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 5cd74ad639..3aac84e5b0 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -43,10 +43,12 @@
 #define CODE64(s) ((s)->code64)
 #define REX_X(s) ((s)->rex_x)
 #define REX_B(s) ((s)->rex_b)
+#define REX_R(s) ((s)->rex_r)
 #else
 #define CODE64(s) 0
 #define REX_X(s) 0
 #define REX_B(s) 0
+#define REX_R(s) 0
 #endif
 
 #ifdef TARGET_X86_64
@@ -98,7 +100,7 @@ typedef struct DisasContext {
 #ifdef TARGET_X86_64
 int lma;/* long mode active */
 int code64; /* 64 bit code segment */
-int rex_x, rex_b;
+int rex_x, rex_b, rex_r;
 #endif
 int vex_l;  /* vex vector length */
 int vex_v;  /* vex  register, without 1's complement.  */
@@ -3037,7 +3039,7 @@ static const struct SSEOpHelper_eppi sse_op_table7[256] = 
{
 };
 
 static void gen_sse(CPUX86State *env, DisasContext *s, int b,
-target_ulong pc_start, int rex_r)
+target_ulong pc_start)
 {
 int b1, op1_offset, op2_offset, is_xmm, val;
 int modrm, mod, rm, reg;
@@ -3107,8 +3109,9 @@ static void gen_sse(CPUX86State *env, DisasContext *s, 
int b,
 
 modrm = x86_ldub_code(env, s);
 reg = ((modrm >> 3) & 7);
-if (is_xmm)
-reg |= rex_r;
+if (is_xmm) {
+reg |= REX_R(s);
+}
 mod = (modrm >> 6) & 3;
 if (sse_fn_epp == SSE_SPECIAL) {
 b |= (b1 << 8);
@@ -3642,7 +3645,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, 
int b,
 tcg_gen_ld16u_tl(s->T0, cpu_env,
 
offsetof(CPUX86State,fpregs[rm].mmx.MMX_W(val)));
 }
-reg = ((modrm >> 3) & 7) | rex_r;
+reg = ((modrm >> 3) & 7) | REX_R(s);
 gen_op_mov_reg_v(s, ot, reg, s->T0);
 break;
 case 0x1d6: /* movq ea, xmm */
@@ -3686,7 +3689,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, 
int b,
  offsetof(CPUX86State, fpregs[rm].mmx));
 gen_helper_pmovmskb_mmx(s->tmp2_i32, cpu_env, s->ptr0);
 }
-reg = ((modrm >> 3) & 7) | rex_r;
+reg = ((modrm >> 3) & 7) | REX_R(s);
 tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32);
 break;
 
@@ -3698,7 +3701,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, 
int b,
 }
 modrm = x86_ldub_code(env, s);
 rm = modrm & 7;
-reg = ((modrm >> 3) & 7) | rex_r;
+reg = ((modrm >> 3) & 7) | REX_R(s);
 mod = (modrm >> 6) & 3;
 if (b1 >= 2) {
 goto unknown_op;
@@ -3774,7 +3777,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, 
int b,
 /* Various integer extensions at 0f 38 f[0-f].  */
 b = modrm | (b1 << 8);
 modrm = x86_ldub_code(env, s);
-reg = ((modrm >> 3) & 7) | rex_r;
+reg = ((modrm >> 3) & 7) | REX_R(s);
 
 switch (b) {
 case 0x3f0: /* crc32 Gd,Eb */
@@ -4128,7 +4131,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, 
int b,
 b = modrm;
 modrm = x86_ldub_code(env, s);
 rm = modrm & 7;
-reg = ((modrm >> 3) & 7) | rex_r;
+reg = ((modrm >> 3) & 7) | REX_R(s);
 mod = (modrm >> 6) & 3;
 if (b1 >= 2) {
 goto unknown_op;
@@ -4148,7 +4151,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, 
int b,
 rm = (modrm & 7) | REX_B(s);
 if (mod != 3)
 gen_lea_modrm(env, s, modrm);
-reg = ((modrm >> 3) & 7) | rex_r;
+reg = ((modrm >> 3) & 7) | REX_R(s);
 val = x86_ldub_code(env, s);
 switch (b) {
 case 0x14: /* pextrb */
@@ -4317,7 +4320,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, 
int b,
 /* Various integer extensions at 0f 3a f[0-f].  */
 b = modrm | (b1 << 8);
 modrm = x86_ldub_code(env, s);
-reg = ((modrm >> 3) & 7) | rex_r;
+reg = ((modrm >> 3) & 7) | REX_R(s);
 
 switch (b) {
 case 0x3f0: /* rorx Gy,Ey, Ib */
@@ -4491,14 +4494,15 @@ static target_ulong disas_insn(DisasContext *s, 
CPUState *cpu)
 TCGMemOp ot, aflag, dflag;
 int modrm, reg, rm, mod, op, opreg, val;
 target_ulong next_eip, tval;
-int rex_w, rex_r;
 target_ulong pc_start = s->base.pc_next;
+int rex_w;
 
 s->pc_start = s->pc = pc_start;
 s->override = -1;
 #ifdef TARGET_X86_64
 s->rex_x = 0;
 s->rex_b = 0;
+s->rex_r = 0;
 s->x86_64_hregs = false;
 #endif
 s->rip_offset = 

[Qemu-devel] [RFC PATCH v4 14/75] target/i386: introduce aliases for some tcg_gvec operations

2019-08-21 Thread Jan Bobek
The aliases create a thin layer above the raw tcg_gvec functions,
making room for us to permute the arguments, pass additional constant
values etc., which will prove highly useful later.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 39 +++
 1 file changed, 39 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index bd9c62dc54..467ecf15ba 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -22,6 +22,7 @@
 #include "cpu.h"
 #include "disas/disas.h"
 #include "exec/exec-all.h"
+#include "tcg-gvec-desc.h"
 #include "tcg-op.h"
 #include "exec/cpu_ldst.h"
 #include "exec/translator.h"
@@ -4477,6 +4478,44 @@ static void gen_sse(CPUX86State *env, DisasContext *s, 
int b)
 }
 }
 
+#define gen_gvec_mov(dofs, aofs, oprsz, maxsz, vece)\
+tcg_gen_gvec_mov(vece, dofs, aofs, oprsz, maxsz)
+
+#define gen_gvec_add(dofs, aofs, bofs, oprsz, maxsz, vece)  \
+tcg_gen_gvec_add(vece, dofs, aofs, bofs, oprsz, maxsz)
+#define gen_gvec_sub(dofs, aofs, bofs, oprsz, maxsz, vece)  \
+tcg_gen_gvec_sub(vece, dofs, aofs, bofs, oprsz, maxsz)
+
+#define gen_gvec_ssadd(dofs, aofs, bofs, oprsz, maxsz, vece)\
+tcg_gen_gvec_ssadd(vece, dofs, aofs, bofs, oprsz, maxsz)
+#define gen_gvec_sssub(dofs, aofs, bofs, oprsz, maxsz, vece)\
+tcg_gen_gvec_sssub(vece, dofs, aofs, bofs, oprsz, maxsz)
+#define gen_gvec_usadd(dofs, aofs, bofs, oprsz, maxsz, vece)\
+tcg_gen_gvec_usadd(vece, dofs, aofs, bofs, oprsz, maxsz)
+#define gen_gvec_ussub(dofs, aofs, bofs, oprsz, maxsz, vece)\
+tcg_gen_gvec_ussub(vece, dofs, aofs, bofs, oprsz, maxsz)
+
+#define gen_gvec_smin(dofs, aofs, bofs, oprsz, maxsz, vece) \
+tcg_gen_gvec_smin(vece, dofs, aofs, bofs, oprsz, maxsz)
+#define gen_gvec_umin(dofs, aofs, bofs, oprsz, maxsz, vece) \
+tcg_gen_gvec_umin(vece, dofs, aofs, bofs, oprsz, maxsz)
+#define gen_gvec_smax(dofs, aofs, bofs, oprsz, maxsz, vece) \
+tcg_gen_gvec_smax(vece, dofs, aofs, bofs, oprsz, maxsz)
+#define gen_gvec_umax(dofs, aofs, bofs, oprsz, maxsz, vece) \
+tcg_gen_gvec_umax(vece, dofs, aofs, bofs, oprsz, maxsz)
+
+#define gen_gvec_and(dofs, aofs, bofs, oprsz, maxsz, vece)  \
+tcg_gen_gvec_and(vece, dofs, aofs, bofs, oprsz, maxsz)
+#define gen_gvec_andn(dofs, aofs, bofs, oprsz, maxsz, vece) \
+tcg_gen_gvec_andc(vece, dofs, bofs, aofs, oprsz, maxsz)
+#define gen_gvec_or(dofs, aofs, bofs, oprsz, maxsz, vece)   \
+tcg_gen_gvec_or(vece, dofs, aofs, bofs, oprsz, maxsz)
+#define gen_gvec_xor(dofs, aofs, bofs, oprsz, maxsz, vece)  \
+tcg_gen_gvec_xor(vece, dofs, aofs, bofs, oprsz, maxsz)
+
+#define gen_gvec_cmp(dofs, aofs, bofs, oprsz, maxsz, vece, cond)\
+tcg_gen_gvec_cmp(cond, vece, dofs, aofs, bofs, oprsz, maxsz)
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
 enum {
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 04/75] target/i386: use prefix from DisasContext

2019-08-21 Thread Jan Bobek
Use prefix from DisasContext instead of the local helper variable
prefixes.

Suggested-by: Richard Henderson 
Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 110 
 1 file changed, 55 insertions(+), 55 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 7226c67d2e..99a9097c49 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -6351,7 +6351,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 case 0xa4: /* movsS */
 case 0xa5:
 ot = mo_b_d(b, s->dflag);
-if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
+if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
 gen_repz_movs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
 } else {
 gen_movs(s, ot);
@@ -6361,7 +6361,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 case 0xaa: /* stosS */
 case 0xab:
 ot = mo_b_d(b, s->dflag);
-if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
+if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
 gen_repz_stos(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
 } else {
 gen_stos(s, ot);
@@ -6370,7 +6370,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 case 0xac: /* lodsS */
 case 0xad:
 ot = mo_b_d(b, s->dflag);
-if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
+if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
 gen_repz_lods(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
 } else {
 gen_lods(s, ot);
@@ -6379,9 +6379,9 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 case 0xae: /* scasS */
 case 0xaf:
 ot = mo_b_d(b, s->dflag);
-if (prefixes & PREFIX_REPNZ) {
+if (s->prefix & PREFIX_REPNZ) {
 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
-} else if (prefixes & PREFIX_REPZ) {
+} else if (s->prefix & PREFIX_REPZ) {
 gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
 } else {
 gen_scas(s, ot);
@@ -6391,9 +6391,9 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 case 0xa6: /* cmpsS */
 case 0xa7:
 ot = mo_b_d(b, s->dflag);
-if (prefixes & PREFIX_REPNZ) {
+if (s->prefix & PREFIX_REPNZ) {
 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
-} else if (prefixes & PREFIX_REPZ) {
+} else if (s->prefix & PREFIX_REPZ) {
 gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
 } else {
 gen_cmps(s, ot);
@@ -6404,8 +6404,8 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 ot = mo_b_d32(b, s->dflag);
 tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]);
 gen_check_io(s, ot, pc_start - s->cs_base, 
- SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes) | 4);
-if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
+ SVM_IOIO_TYPE_MASK | svm_is_rep(s->prefix) | 4);
+if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
 gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
 } else {
 gen_ins(s, ot);
@@ -6419,8 +6419,8 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 ot = mo_b_d32(b, s->dflag);
 tcg_gen_ext16u_tl(s->T0, cpu_regs[R_EDX]);
 gen_check_io(s, ot, pc_start - s->cs_base,
- svm_is_rep(prefixes) | 4);
-if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
+ svm_is_rep(s->prefix) | 4);
+if (s->prefix & (PREFIX_REPZ | PREFIX_REPNZ)) {
 gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base);
 } else {
 gen_outs(s, ot);
@@ -6439,7 +6439,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 val = x86_ldub_code(env, s);
 tcg_gen_movi_tl(s->T0, val);
 gen_check_io(s, ot, pc_start - s->cs_base,
- SVM_IOIO_TYPE_MASK | svm_is_rep(prefixes));
+ SVM_IOIO_TYPE_MASK | svm_is_rep(s->prefix));
 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
 gen_io_start();
 }
@@ -6457,7 +6457,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 val = x86_ldub_code(env, s);
 tcg_gen_movi_tl(s->T0, val);
 gen_check_io(s, ot, pc_start - s->cs_base,
- svm_is_rep(prefixes));
+ svm_is_rep(s->prefix));
 gen_op_mov_v_reg(s, ot, s->T1, R_EAX);
 
 if (tb_cflags(s->bas

[Qemu-devel] [RFC PATCH v4 02/75] target/i386: Push rex_w into DisasContext

2019-08-21 Thread Jan Bobek
From: Richard Henderson 

Treat this the same as we already do for other rex bits.

Signed-off-by: Richard Henderson 
---
 target/i386/translate.c | 19 +++
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 3aac84e5b0..9ec1c79371 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -44,11 +44,13 @@
 #define REX_X(s) ((s)->rex_x)
 #define REX_B(s) ((s)->rex_b)
 #define REX_R(s) ((s)->rex_r)
+#define REX_W(s) ((s)->rex_w)
 #else
 #define CODE64(s) 0
 #define REX_X(s) 0
 #define REX_B(s) 0
 #define REX_R(s) 0
+#define REX_W(s) -1
 #endif
 
 #ifdef TARGET_X86_64
@@ -100,7 +102,7 @@ typedef struct DisasContext {
 #ifdef TARGET_X86_64
 int lma;/* long mode active */
 int code64; /* 64 bit code segment */
-int rex_x, rex_b, rex_r;
+int rex_x, rex_b, rex_r, rex_w;
 #endif
 int vex_l;  /* vex vector length */
 int vex_v;  /* vex  register, without 1's complement.  */
@@ -4495,7 +4497,6 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 int modrm, reg, rm, mod, op, opreg, val;
 target_ulong next_eip, tval;
 target_ulong pc_start = s->base.pc_next;
-int rex_w;
 
 s->pc_start = s->pc = pc_start;
 s->override = -1;
@@ -4503,6 +4504,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 s->rex_x = 0;
 s->rex_b = 0;
 s->rex_r = 0;
+s->rex_w = -1;
 s->x86_64_hregs = false;
 #endif
 s->rip_offset = 0; /* for relative ip address */
@@ -4514,7 +4516,6 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 }
 
 prefixes = 0;
-rex_w = -1;
 
  next_byte:
 b = x86_ldub_code(env, s);
@@ -4557,7 +4558,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 case 0x40 ... 0x4f:
 if (CODE64(s)) {
 /* REX prefix */
-rex_w = (b >> 3) & 1;
+s->rex_w = (b >> 3) & 1;
 s->rex_r = (b & 0x4) << 1;
 s->rex_x = (b & 0x2) << 2;
 s->rex_b = (b & 0x1) << 3;
@@ -4606,7 +4607,9 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 s->rex_b = (~vex2 >> 2) & 8;
 #endif
 vex3 = x86_ldub_code(env, s);
-rex_w = (vex3 >> 7) & 1;
+#ifdef TARGET_X86_64
+s->rex_w = (vex3 >> 7) & 1;
+#endif
 switch (vex2 & 0x1f) {
 case 0x01: /* Implied 0f leading opcode bytes.  */
 b = x86_ldub_code(env, s) | 0x100;
@@ -4631,9 +4634,9 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 /* Post-process prefixes.  */
 if (CODE64(s)) {
 /* In 64-bit mode, the default data size is 32-bit.  Select 64-bit
-   data with rex_w, and 16-bit data with 0x66; rex_w takes precedence
+   data with REX_W, and 16-bit data with 0x66; REX_W takes precedence
over 0x66 if both are present.  */
-dflag = (rex_w > 0 ? MO_64 : prefixes & PREFIX_DATA ? MO_16 : MO_32);
+dflag = (REX_W(s) > 0 ? MO_64 : prefixes & PREFIX_DATA ? MO_16 : 
MO_32);
 /* In 64-bit mode, 0x67 selects 32-bit addressing.  */
 aflag = (prefixes & PREFIX_ADR ? MO_32 : MO_64);
 } else {
@@ -5029,7 +5032,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState 
*cpu)
 /* operand size for jumps is 64 bit */
 ot = MO_64;
 } else if (op == 3 || op == 5) {
-ot = dflag != MO_16 ? MO_32 + (rex_w == 1) : MO_16;
+ot = dflag != MO_16 ? MO_32 + (REX_W(s) == 1) : MO_16;
 } else if (op == 6) {
 /* default push size is 64 bit */
 ot = mo_pushpop(s, dflag);
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 10/75] target/i386: add vector register file alignment constraints

2019-08-21 Thread Jan Bobek
gvec operations require that all vectors be aligned on 16-byte
boundary; make sure the MM/XMM/YMM/ZMM register file is aligned as
neccessary.

Reviewed-by: Richard Henderson 
Signed-off-by: Jan Bobek 
---
 target/i386/cpu.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 5f6e3a029a..f226e61724 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1202,9 +1202,9 @@ typedef struct CPUX86State {
 float_status mmx_status; /* for 3DNow! float ops */
 float_status sse_status;
 uint32_t mxcsr;
-ZMMReg xmm_regs[CPU_NB_REGS == 8 ? 8 : 32];
-ZMMReg xmm_t0;
-MMXReg mmx_t0;
+ZMMReg xmm_regs[CPU_NB_REGS == 8 ? 8 : 32] QEMU_ALIGNED(16);
+ZMMReg xmm_t0 QEMU_ALIGNED(16);
+MMXReg mmx_t0 QEMU_ALIGNED(8);
 
 XMMReg ymmh_regs[CPU_NB_REGS];
 
-- 
2.20.1




[Qemu-devel] [RFC PATCH v4 00/75] rewrite MMX/SSE*/AVX/AVX2 vector instruction translation

2019-08-21 Thread Jan Bobek
Here comes the next version of my patch series, this time v4; the
previous version can be found at [1].

This version can decode all vector instructions up to AVX2. However,
note that this does not mean all of these instructions are implemented
correctly: to achieve that, the old ad-hoc style helpers will need to
be rewritten into the style used by gvec helpers (initial effort
towards that goal can be seen in patches 65-75). There is also a
number of instructions which have not been previously implemented at
all, for which the helpers need to be written from scratch.

Cheers,
 -Jan

Changes from v3:
  - introduce disas_insn_prefix ([2])
  - rename ck_cpuid to check_cpuid ([3])
  - clarify this series deals with vector instructions only ([4])
  - add a list of instructions per each vector ISA extension ([5])
  - change return type of check_cpuid and insnop_init to bool ([6])

References:
  1. https://lists.nongnu.org/archive/html/qemu-devel/2019-08/msg02616.html
  2. https://lists.nongnu.org/archive/html/qemu-devel/2019-08/msg02686.html
  3. https://lists.nongnu.org/archive/html/qemu-devel/2019-08/msg04120.html
  4. https://lists.nongnu.org/archive/html/qemu-devel/2019-08/msg04119.html
  5. https://lists.nongnu.org/archive/html/qemu-devel/2019-08/msg02689.html
  6. https://lists.nongnu.org/archive/html/qemu-devel/2019-08/msg02701.html

Jan Bobek (72):
  target/i386: use dflag from DisasContext
  target/i386: use prefix from DisasContext
  target/i386: introduce disas_insn_prefix
  target/i386: use pc_start from DisasContext
  target/i386: make variable b1 const
  target/i386: make variable is_xmm const
  target/i386: add vector register file alignment constraints
  target/i386: introduce gen_sse_ng
  target/i386: introduce CASES_* macros in gen_sse_ng
  target/i386: decode the 0F38/0F3A prefix in gen_sse_ng
  target/i386: introduce aliases for some tcg_gvec operations
  target/i386: introduce function check_cpuid
  target/i386: disable AVX/AVX2 cpuid bitchecks
  target/i386: introduce instruction operand infrastructure
  target/i386: introduce generic operand alias
  target/i386: introduce generic either-or operand
  target/i386: introduce generic load-store operand
  target/i386: introduce tcg register operands
  target/i386: introduce modrm operand
  target/i386: introduce operands for decoding modrm fields
  target/i386: introduce operand for direct-only r/m field
  target/i386: introduce Ib (immediate) operand
  target/i386: introduce M* (memptr) operands
  target/i386: introduce G*, R*, E* (general register) operands
  target/i386: introduce P*, N*, Q* (MMX) operands
  target/i386: introduce H*, L*, V*, U*, W* (SSE/AVX) operands
  target/i386: alias H* operands with the V* operands
  target/i386: introduce code generators
  target/i386: introduce helper-based code generator macros
  target/i386: introduce gvec-based code generator macros
  target/i386: introduce sse-opcode.inc.h
  target/i386: introduce instruction translator macros
  target/i386: introduce MMX translators
  target/i386: introduce MMX code generators
  target/i386: introduce MMX vector instructions to sse-opcode.inc.h
  target/i386: introduce SSE translators
  target/i386: introduce SSE code generators
  target/i386: introduce SSE vector instructions to sse-opcode.inc.h
  target/i386: introduce SSE2 translators
  target/i386: introduce SSE2 code generators
  target/i386: introduce SSE2 vector instructions to sse-opcode.inc.h
  target/i386: introduce SSE3 translators
  target/i386: introduce SSE3 code generators
  target/i386: introduce SSE3 vector instructions to sse-opcode.inc.h
  target/i386: introduce SSSE3 translators
  target/i386: introduce SSSE3 code generators
  target/i386: introduce SSSE3 vector instructions to sse-opcode.inc.h
  target/i386: introduce SSE4.1 translators
  target/i386: introduce SSE4.1 code generators
  target/i386: introduce SSE4.1 vector instructions to sse-opcode.inc.h
  target/i386: introduce SSE4.2 code generators
  target/i386: introduce SSE4.2 vector instructions to sse-opcode.inc.h
  target/i386: introduce AES and PCLMULQDQ translators
  target/i386: introduce AES and PCLMULQDQ code generators
  target/i386: introduce AES and PCLMULQDQ vector instructions to
sse-opcode.inc.h
  target/i386: introduce AVX translators
  target/i386: introduce AVX code generators
  target/i386: introduce AVX vector instructions to sse-opcode.inc.h
  target/i386: introduce AVX2 translators
  target/i386: introduce AVX2 code generators
  target/i386: introduce AVX2 vector instructions to sse-opcode.inc.h
  target/i386: remove obsoleted helpers
  target/i386: cleanup leftovers in ops_sse_header.h
  target/i386: introduce aliases for helper-based tcg_gen_gvec_*
functions
  target/i386: convert ps((l,r)l(w,d,q),ra(w,d)) to helpers to gvec
style
  target/i386: convert pmullw/pmulhw/pmulhuw helpers to gvec style
  target/i386: convert pavgb/pavgw helpers to gvec style
  target/i386: convert pmuludq/pmaddwd helpers

Re: [Qemu-devel] [RFC PATCH v3 02/46] target/i386: Push rex_w into DisasContext

2019-08-20 Thread Jan Bobek
On 8/15/19 6:19 AM, Aleksandar Markovic wrote:
> 
> 15.08.2019. 11.55, "Richard Henderson"  <mailto:richard.hender...@linaro.org>> је написао/ла:
>>
>> On 8/15/19 8:30 AM, Aleksandar Markovic wrote:
>> >
>> > 15.08.2019. 04.13, "Jan Bobek" > > <mailto:jan.bo...@gmail.com>
>> > <mailto:jan.bo...@gmail.com <mailto:jan.bo...@gmail.com>>> је написао/ла:
>> >>
>> >> From: Richard Henderson mailto:r...@twiddle.net> 
>> >> <mailto:r...@twiddle.net <mailto:r...@twiddle.net>>>
>> >>
>> >> Treat this the same as we already do for other rex bits.
>> >>
>> >> Signed-off-by: Richard Henderson > >> <mailto:r...@twiddle.net> <mailto:r...@twiddle.net 
>> >> <mailto:r...@twiddle.net>>>
>> >> ---
>> >>  target/i386/translate.c | 19 +++
>> >>  1 file changed, 11 insertions(+), 8 deletions(-)
>> >>
>> >> diff --git a/target/i386/translate.c b/target/i386/translate.c
>> >> index d74dbfd585..c0866c2797 100644
>> >> --- a/target/i386/translate.c
>> >> +++ b/target/i386/translate.c
>> >> @@ -44,11 +44,13 @@
>> >>  #define REX_X(s) ((s)->rex_x)
>> >>  #define REX_B(s) ((s)->rex_b)
>> >>  #define REX_R(s) ((s)->rex_r)
>> >> +#define REX_W(s) ((s)->rex_w)
>> >>  #else
>> >>  #define CODE64(s) 0
>> >>  #define REX_X(s) 0
>> >>  #define REX_B(s) 0
>> >>  #define REX_R(s) 0
>> >> +#define REX_W(s) -1
>> >
>> > The commit message says "treat rex_w the same as other rex bits". Why is 
>> > then
>> > REX_W() treated differently here?
>>
>> "Treated the same" in terms of being referenced by a macro instead of a local
>> variable.  As for the -1, if you look at the rest of the patch you can 
>> clearly
>> see it preserves existing behaviour.
>>
> 
> That is exactly what I dislike about your commit messages: they often 
> introduce ambiguity, without any real need, and with really bad consequences 
> to the reader. Is adding "in terms of being referenced by a macro instead of 
> a local
> variable" to the commit message that hard?
> 
> When writing commit messages, you need to try to put yourself in the shoes of 
> the reader.

FWIW, personally I don't find it confusing. I think even just the
first couple of lines of the patch make it quite clear what's
going on. Just my 2 cents.

-Jan



signature.asc
Description: OpenPGP digital signature


Re: [Qemu-devel] [RFC PATCH v3 15/46] target/i386: introduce function ck_cpuid

2019-08-20 Thread Jan Bobek
On 8/15/19 11:01 AM, Aleksandar Markovic wrote:
> 
> 15.08.2019. 04.23, "Jan Bobek"  <mailto:jan.bo...@gmail.com>> је написао/ла:
>>
>> Introduce a helper function to take care of instruction CPUID checks.
>>
>> Signed-off-by: Jan Bobek mailto:jan.bo...@gmail.com>>
>> ---
> 
> Jan, what is the origin of "CK"? If it is a QEMU internal thing, perhaps use 
> "CHECK".
> 
> The function should be called check_cpuid(), imho. I know, Richard would like 
> c_ci(), or simpler cc(), better.

It was completely my initiative to name it like that. I'll rename
it to check_cpuid().

-Jan



signature.asc
Description: OpenPGP digital signature


Re: [Qemu-devel] [RFC PATCH v3 46/46] target/i386: introduce SSE3 instructions to sse-opcode.inc.h

2019-08-20 Thread Jan Bobek
On 8/15/19 6:07 AM, Aleksandar Markovic wrote:
> 
> 15.08.2019. 11.55, "Richard Henderson"  > је написао/ла:
>>
>> On 8/15/19 8:02 AM, Aleksandar Markovic wrote:
>> > A question for you: What about FISTTP, MONITOR, MWAIT, that belong to 
>> > SSE3, but
>> > are not mentioned in this patch?
>> >
>>
>> They are also not vector instructions, which is the subject of this patch 
>> set.
>>
> 
> The subject of the patch and the patch set says "SSE3", not "vector", read it 
> again.

Richard is right, I will clarify the series' subject and the
commit message.

-Jan



signature.asc
Description: OpenPGP digital signature


[Qemu-devel] [RFC PATCH v3 43/46] target/i386: introduce SSE2 instructions to sse-opcode.inc.h

2019-08-14 Thread Jan Bobek
Add all the SSE2 instruction entries to sse-opcode.inc.h.

Signed-off-by: Jan Bobek 
---
 target/i386/sse-opcode.inc.h | 323 ++-
 1 file changed, 322 insertions(+), 1 deletion(-)

diff --git a/target/i386/sse-opcode.inc.h b/target/i386/sse-opcode.inc.h
index 39947aeb51..efa67b7ce2 100644
--- a/target/i386/sse-opcode.inc.h
+++ b/target/i386/sse-opcode.inc.h
@@ -43,241 +43,535 @@
 OPCODE(movd, LEG(NP, 0F, 0, 0x6e), MMX, WR, Pq, Ed)
 /* NP 0F 7E /r: MOVD r/m32,mm */
 OPCODE(movd, LEG(NP, 0F, 0, 0x7e), MMX, WR, Ed, Pq)
+/* 66 0F 6E /r: MOVD xmm,r/m32 */
+OPCODE(movd, LEG(66, 0F, 0, 0x6e), SSE2, WR, Vdq, Ed)
+/* 66 0F 7E /r: MOVD r/m32,xmm */
+OPCODE(movd, LEG(66, 0F, 0, 0x7e), SSE2, WR, Ed, Vdq)
 /* NP REX.W + 0F 6E /r: MOVQ mm,r/m64 */
 OPCODE(movq, LEG(NP, 0F, 1, 0x6e), MMX, WR, Pq, Eq)
 /* NP REX.W + 0F 7E /r: MOVQ r/m64,mm */
 OPCODE(movq, LEG(NP, 0F, 1, 0x7e), MMX, WR, Eq, Pq)
+/* 66 REX.W 0F 6E /r: MOVQ xmm,r/m64 */
+OPCODE(movq, LEG(66, 0F, 1, 0x6e), SSE2, WR, Vdq, Eq)
+/* 66 REX.W 0F 7E /r: MOVQ r/m64,xmm */
+OPCODE(movq, LEG(66, 0F, 1, 0x7e), SSE2, WR, Eq, Vdq)
 /* NP 0F 6F /r: MOVQ mm, mm/m64 */
 OPCODE(movq, LEG(NP, 0F, 0, 0x6f), MMX, WR, Pq, Qq)
 /* NP 0F 7F /r: MOVQ mm/m64, mm */
 OPCODE(movq, LEG(NP, 0F, 0, 0x7f), MMX, WR, Qq, Pq)
+/* F3 0F 7E /r: MOVQ xmm1, xmm2/m64 */
+OPCODE(movq, LEG(F3, 0F, 0, 0x7e), SSE2, WR, Vdq, Wq)
+/* 66 0F D6 /r: MOVQ xmm2/m64, xmm1 */
+OPCODE(movq, LEG(66, 0F, 0, 0xd6), SSE2, WR, UdqMq, Vq)
 /* NP 0F 28 /r: MOVAPS xmm1, xmm2/m128 */
 OPCODE(movaps, LEG(NP, 0F, 0, 0x28), SSE, WR, Vdq, Wdq)
 /* NP 0F 29 /r: MOVAPS xmm2/m128, xmm1 */
 OPCODE(movaps, LEG(NP, 0F, 0, 0x29), SSE, WR, Wdq, Vdq)
+/* 66 0F 28 /r: MOVAPD xmm1, xmm2/m128 */
+OPCODE(movapd, LEG(66, 0F, 0, 0x28), SSE2, WR, Vdq, Wdq)
+/* 66 0F 29 /r: MOVAPD xmm2/m128, xmm1 */
+OPCODE(movapd, LEG(66, 0F, 0, 0x29), SSE2, WR, Wdq, Vdq)
+/* 66 0F 6F /r: MOVDQA xmm1, xmm2/m128 */
+OPCODE(movdqa, LEG(66, 0F, 0, 0x6f), SSE2, WR, Vdq, Wdq)
+/* 66 0F 7F /r: MOVDQA xmm2/m128, xmm1 */
+OPCODE(movdqa, LEG(66, 0F, 0, 0x7f), SSE2, WR, Wdq, Vdq)
 /* NP 0F 10 /r: MOVUPS xmm1, xmm2/m128 */
 OPCODE(movups, LEG(NP, 0F, 0, 0x10), SSE, WR, Vdq, Wdq)
 /* NP 0F 11 /r: MOVUPS xmm2/m128, xmm1 */
 OPCODE(movups, LEG(NP, 0F, 0, 0x11), SSE, WR, Wdq, Vdq)
+/* 66 0F 10 /r: MOVUPD xmm1, xmm2/m128 */
+OPCODE(movupd, LEG(66, 0F, 0, 0x10), SSE2, WR, Vdq, Wdq)
+/* 66 0F 11 /r: MOVUPD xmm2/m128, xmm1 */
+OPCODE(movupd, LEG(66, 0F, 0, 0x11), SSE2, WR, Wdq, Vdq)
+/* F3 0F 6F /r: MOVDQU xmm1,xmm2/m128 */
+OPCODE(movdqu, LEG(F3, 0F, 0, 0x6f), SSE2, WR, Vdq, Wdq)
+/* F3 0F 7F /r: MOVDQU xmm2/m128,xmm1 */
+OPCODE(movdqu, LEG(F3, 0F, 0, 0x7f), SSE2, WR, Wdq, Vdq)
 /* F3 0F 10 /r: MOVSS xmm1, xmm2/m32 */
 OPCODE(movss, LEG(F3, 0F, 0, 0x10), SSE, WRRR, Vdq, Vdq, Wd, modrm_mod)
 /* F3 0F 11 /r: MOVSS xmm2/m32, xmm1 */
 OPCODE(movss, LEG(F3, 0F, 0, 0x11), SSE, WR, Wd, Vd)
+/* F2 0F 10 /r: MOVSD xmm1, xmm2/m64 */
+OPCODE(movsd, LEG(F2, 0F, 0, 0x10), SSE2, WRRR, Vdq, Vdq, Wq, modrm_mod)
+/* F2 0F 11 /r: MOVSD xmm1/m64, xmm2 */
+OPCODE(movsd, LEG(F2, 0F, 0, 0x11), SSE2, WR, Wq, Vq)
+/* F3 0F D6 /r: MOVQ2DQ xmm, mm */
+OPCODE(movq2dq, LEG(F3, 0F, 0, 0xd6), SSE2, WR, Vdq, Nq)
+/* F2 0F D6 /r: MOVDQ2Q mm, xmm */
+OPCODE(movdq2q, LEG(F2, 0F, 0, 0xd6), SSE2, WR, Pq, Uq)
 /* NP 0F 12 /r: MOVHLPS xmm1, xmm2 */
 /* NP 0F 12 /r: MOVLPS xmm1, m64 */
 OPCODE(movhlps, LEG(NP, 0F, 0, 0x12), SSE, WR, Vq, UdqMhq)
 /* 0F 13 /r: MOVLPS m64, xmm1 */
 OPCODE(movlps, LEG(NP, 0F, 0, 0x13), SSE, WR, Mq, Vq)
+/* 66 0F 12 /r: MOVLPD xmm1,m64 */
+OPCODE(movlpd, LEG(66, 0F, 0, 0x12), SSE2, WR, Vq, Mq)
+/* 66 0F 13 /r: MOVLPD m64,xmm1 */
+OPCODE(movlpd, LEG(66, 0F, 0, 0x13), SSE2, WR, Mq, Vq)
 /* NP 0F 16 /r: MOVLHPS xmm1, xmm2 */
 /* NP 0F 16 /r: MOVHPS xmm1, m64 */
 OPCODE(movlhps, LEG(NP, 0F, 0, 0x16), SSE, WRR, Vdq, Vq, Wq)
 /* NP 0F 17 /r: MOVHPS m64, xmm1 */
 OPCODE(movhps, LEG(NP, 0F, 0, 0x17), SSE, WR, Mq, Vdq)
+/* 66 0F 16 /r: MOVHPD xmm1, m64 */
+OPCODE(movhpd, LEG(66, 0F, 0, 0x16), SSE2, WRR, Vdq, Vd, Mq)
+/* 66 0F 17 /r: MOVHPD m64, xmm1 */
+OPCODE(movhpd, LEG(66, 0F, 0, 0x17), SSE2, WR, Mq, Vdq)
 /* NP 0F D7 /r: PMOVMSKB r32, mm */
 OPCODE(pmovmskb, LEG(NP, 0F, 0, 0xd7), SSE, WR, Gd, Nq)
 /* NP REX.W 0F D7 /r: PMOVMSKB r64, mm */
 OPCODE(pmovmskb, LEG(NP, 0F, 1, 0xd7), SSE, WR, Gq, Nq)
+/* 66 0F D7 /r: PMOVMSKB r32, xmm */
+OPCODE(pmovmskb, LEG(66, 0F, 0, 0xd7), SSE2, WR, Gd, Udq)
+/* 66 REX.W 0F D7 /r: PMOVMSKB r64, xmm */
+OPCODE(pmovmskb, LEG(66, 0F, 1, 0xd7), SSE2, WR, Gq, Udq)
 /* NP 0F 50 /r: MOVMSKPS r32, xmm */
 OPCODE(movmskps, LEG(NP, 0F, 0, 0x50), SSE, WR, Gd, Udq)
 /* NP REX.W 0F 50 /r: MOVMSKPS r64, xmm */
 OPCODE(movmskps, LEG(NP, 0F, 1, 0x50), SSE, WR, Gq, Udq)
+/* 66 0F 50 /r: MOVMSKPD r32, xmm */
+OPCODE(movmskpd, LEG(66, 0F, 0, 0x50), SSE2, WR, Gd, Udq)
+/* 66 REX.W 0F 50 /r: MOVMSKPD r64, xmm */
+OPCODE(movmskpd, LEG(66, 0F, 1, 0x50), SSE2, WR, Gq, Udq)
 /* NP 0F FC /r: PADDB mm, mm/m64 */
 OPCODE(paddb, LEG(NP, 0F, 0, 0xfc

[Qemu-devel] [RFC PATCH v3 42/46] target/i386: introduce SSE2 code generators

2019-08-14 Thread Jan Bobek
Introduce code generators required by SSE2 instructions.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 444 +++-
 1 file changed, 442 insertions(+), 2 deletions(-)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 177bedd0ef..7ec082e79d 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -5391,6 +5391,21 @@ GEN_INSN2(movd, Ed, Pq)
 tcg_gen_ld_i32(arg1, cpu_env, arg2 + ofs);
 }
 
+GEN_INSN2(movq, Vdq, Eq);   /* forward declaration */
+GEN_INSN2(movd, Vdq, Ed)
+{
+const insnop_arg_t(Eq) arg2_r64 = tcg_temp_new_i64();
+tcg_gen_extu_i32_i64(arg2_r64, arg2);
+gen_insn2(movq, Vdq, Eq)(env, s, arg1, arg2_r64);
+tcg_temp_free_i64(arg2_r64);
+}
+
+GEN_INSN2(movd, Ed, Vdq)
+{
+const insnop_arg_t(Vdq) ofs = offsetof(ZMMReg, ZMM_L(0));
+tcg_gen_ld_i32(arg1, cpu_env, arg2 + ofs);
+}
+
 GEN_INSN2(movq, Pq, Eq)
 {
 const insnop_arg_t(Pq) ofs = offsetof(MMXReg, MMX_Q(0));
@@ -5403,12 +5418,53 @@ GEN_INSN2(movq, Eq, Pq)
 tcg_gen_ld_i64(arg1, cpu_env, arg2 + ofs);
 }
 
+GEN_INSN2(movq, Vdq, Eq)
+{
+const insnop_arg_t(Vdq) ofs0 = offsetof(ZMMReg, ZMM_Q(0));
+tcg_gen_st_i64(arg2, cpu_env, arg1 + ofs0);
+
+const insnop_arg_t(Vdq) ofs1 = offsetof(ZMMReg, ZMM_Q(1));
+tcg_gen_movi_i64(arg2, 0);
+tcg_gen_st_i64(arg2, cpu_env, arg1 + ofs1);
+}
+
+GEN_INSN2(movq, Eq, Vdq)
+{
+const insnop_arg_t(Vdq) ofs = offsetof(ZMMReg, ZMM_Q(0));
+tcg_gen_ld_i64(arg1, cpu_env, arg2 + ofs);
+}
+
 DEF_GEN_INSN2_GVEC_MM(movq, mov, Pq, Qq, MO_64)
 DEF_GEN_INSN2_GVEC_MM(movq, mov, Qq, Pq, MO_64)
+
+GEN_INSN2(movq, Vdq, Wq)
+{
+const insnop_arg_t(Vdq) dofs = offsetof(ZMMReg, ZMM_Q(0));
+const insnop_arg_t(Wq) aofs = offsetof(ZMMReg, ZMM_Q(0));
+gen_op_movq(s, arg1 + dofs, arg2 + aofs);
+
+const TCGv_i64 r64z = tcg_const_i64(0);
+tcg_gen_st_i64(r64z, cpu_env, arg1 + offsetof(ZMMReg, ZMM_Q(1)));
+tcg_temp_free_i64(r64z);
+}
+
+GEN_INSN2(movq, UdqMq, Vq)
+{
+gen_insn2(movq, Vdq, Wq)(env, s, arg1, arg2);
+}
+
 DEF_GEN_INSN2_GVEC_XMM(movaps, mov, Vdq, Wdq, MO_64)
 DEF_GEN_INSN2_GVEC_XMM(movaps, mov, Wdq, Vdq, MO_64)
+DEF_GEN_INSN2_GVEC_XMM(movapd, mov, Vdq, Wdq, MO_64)
+DEF_GEN_INSN2_GVEC_XMM(movapd, mov, Wdq, Vdq, MO_64)
+DEF_GEN_INSN2_GVEC_XMM(movdqa, mov, Vdq, Wdq, MO_64)
+DEF_GEN_INSN2_GVEC_XMM(movdqa, mov, Wdq, Vdq, MO_64)
 DEF_GEN_INSN2_GVEC_XMM(movups, mov, Vdq, Wdq, MO_64)
 DEF_GEN_INSN2_GVEC_XMM(movups, mov, Wdq, Vdq, MO_64)
+DEF_GEN_INSN2_GVEC_XMM(movupd, mov, Vdq, Wdq, MO_64)
+DEF_GEN_INSN2_GVEC_XMM(movupd, mov, Wdq, Vdq, MO_64)
+DEF_GEN_INSN2_GVEC_XMM(movdqu, mov, Vdq, Wdq, MO_64)
+DEF_GEN_INSN2_GVEC_XMM(movdqu, mov, Wdq, Vdq, MO_64)
 
 GEN_INSN2(movss, Wd, Vd);   /* forward declaration */
 GEN_INSN4(movss, Vdq, Vdq, Wd, modrm_mod)
@@ -5442,6 +5498,44 @@ GEN_INSN2(movss, Wd, Vd)
 gen_op_movl(s, arg1 + dofs, arg2 + aofs);
 }
 
+GEN_INSN2(movsd, Wq, Vq);   /* forward declaration */
+GEN_INSN4(movsd, Vdq, Vdq, Wq, modrm_mod)
+{
+assert(arg1 == arg2);
+
+if (arg4 == 3) {
+/* merging movsd */
+gen_insn2(movsd, Wq, Vq)(env, s, arg1, arg3);
+} else {
+/* zero-extending movsd */
+gen_insn2(movq, Vdq, Wq)(env, s, arg1, arg3);
+}
+}
+
+GEN_INSN2(movsd, Wq, Vq)
+{
+const size_t ofs = offsetof(ZMMReg, ZMM_Q(0));
+gen_op_movq(s, arg1 + ofs, arg2 + ofs);
+}
+
+GEN_INSN2(movq2dq, Vdq, Nq)
+{
+const insnop_arg_t(Vdq) dofs = offsetof(ZMMReg, ZMM_Q(0));
+const insnop_arg_t(Nq) aofs = offsetof(MMXReg, MMX_Q(0));
+gen_op_movq(s, arg1 + dofs, arg2 + aofs);
+
+const TCGv_i64 r64z = tcg_const_i64(0);
+tcg_gen_st_i64(r64z, cpu_env, arg1 + offsetof(ZMMReg, ZMM_Q(1)));
+tcg_temp_free_i64(r64z);
+}
+
+GEN_INSN2(movdq2q, Pq, Uq)
+{
+const insnop_arg_t(Pq) dofs = offsetof(MMXReg, MMX_Q(0));
+const insnop_arg_t(Uq) aofs = offsetof(ZMMReg, ZMM_Q(0));
+gen_op_movq(s, arg1 + dofs, arg2 + aofs);
+}
+
 GEN_INSN2(movhlps, Vq, UdqMhq)
 {
 const size_t dofs = offsetof(ZMMReg, ZMM_Q(0));
@@ -5455,6 +5549,17 @@ GEN_INSN2(movlps, Mq, Vq)
 gen_stq_env_A0(s, arg2 + offsetof(ZMMReg, ZMM_Q(0)));
 }
 
+GEN_INSN2(movlpd, Vq, Mq)
+{
+assert(arg2 == s->A0);
+gen_ldq_env_A0(s, arg1 + offsetof(ZMMReg, ZMM_Q(0)));
+}
+
+GEN_INSN2(movlpd, Mq, Vq)
+{
+gen_insn2(movlps, Mq, Vq)(env, s, arg1, arg2);
+}
+
 GEN_INSN3(movlhps, Vdq, Vq, Wq)
 {
 assert(arg1 == arg2);
@@ -5470,6 +5575,18 @@ GEN_INSN2(movhps, Mq, Vdq)
 gen_stq_env_A0(s, arg2 + offsetof(ZMMReg, ZMM_Q(1)));
 }
 
+GEN_INSN3(movhpd, Vdq, Vd, Mq)
+{
+assert(arg1 == arg2);
+assert(arg3 == s->A0);
+gen_ldq_env_A0(s, arg1 + offsetof(ZMMReg, ZMM_Q(1)));
+}
+
+GEN_INSN2(movhpd, Mq, Vdq)
+{
+gen_insn2(movhps, Mq, Vdq)(env, s, arg1, arg2);
+}
+
 DEF_GEN_INSN2_HELPER_DEP(pmovmskb, pmovmskb_mmx, Gd, Nq)
 
 GEN_INSN2(pmovmskb, Gq, Nq)
@@ -5480,6 +5597,16 @@ GEN_INSN2(pmovmskb, Gq, Nq)
 tcg_temp_free_i32(ar

[Qemu-devel] [RFC PATCH v3 44/46] target/i386: introduce SSE3 translators

2019-08-14 Thread Jan Bobek
Use the translator macros to define translators required by SSE3
instructions.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 7ec082e79d..c72138014a 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -6363,6 +6363,7 @@ DEF_TRANSLATE_INSN2(Vd, Wd)
 DEF_TRANSLATE_INSN2(Vd, Wq)
 DEF_TRANSLATE_INSN2(Vdq, Ed)
 DEF_TRANSLATE_INSN2(Vdq, Eq)
+DEF_TRANSLATE_INSN2(Vdq, Mdq)
 DEF_TRANSLATE_INSN2(Vdq, Nq)
 DEF_TRANSLATE_INSN2(Vdq, Qq)
 DEF_TRANSLATE_INSN2(Vdq, Udq)
-- 
2.20.1




[Qemu-devel] [RFC PATCH v3 38/46] target/i386: introduce SSE translators

2019-08-14 Thread Jan Bobek
Use the translator macros to define translators required by SSE
instructions.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index a02e9cd0d2..ef64fe606f 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -5533,6 +5533,9 @@ static void translate_insn0()(
 }   \
 }
 
+DEF_TRANSLATE_INSN1(Mb)
+DEF_TRANSLATE_INSN1(Md)
+
 #define DEF_TRANSLATE_INSN2(opT1, opT2) \
 static void translate_insn2(opT1, opT2)(\
 CPUX86State *env, DisasContext *s, int modrm,   \
@@ -5571,11 +5574,29 @@ static void translate_insn0()(
 DEF_TRANSLATE_INSN2(Ed, Pq)
 DEF_TRANSLATE_INSN2(Eq, Pq)
 DEF_TRANSLATE_INSN2(Gd, Nq)
+DEF_TRANSLATE_INSN2(Gd, Udq)
+DEF_TRANSLATE_INSN2(Gd, Wd)
 DEF_TRANSLATE_INSN2(Gq, Nq)
+DEF_TRANSLATE_INSN2(Gq, Udq)
+DEF_TRANSLATE_INSN2(Gq, Wd)
+DEF_TRANSLATE_INSN2(Mdq, Vdq)
+DEF_TRANSLATE_INSN2(Mq, Pq)
+DEF_TRANSLATE_INSN2(Mq, Vdq)
+DEF_TRANSLATE_INSN2(Mq, Vq)
 DEF_TRANSLATE_INSN2(Pq, Ed)
 DEF_TRANSLATE_INSN2(Pq, Eq)
+DEF_TRANSLATE_INSN2(Pq, Nq)
 DEF_TRANSLATE_INSN2(Pq, Qq)
+DEF_TRANSLATE_INSN2(Pq, Wq)
 DEF_TRANSLATE_INSN2(Qq, Pq)
+DEF_TRANSLATE_INSN2(Vd, Ed)
+DEF_TRANSLATE_INSN2(Vd, Eq)
+DEF_TRANSLATE_INSN2(Vd, Wd)
+DEF_TRANSLATE_INSN2(Vdq, Qq)
+DEF_TRANSLATE_INSN2(Vdq, Wdq)
+DEF_TRANSLATE_INSN2(Vq, UdqMhq)
+DEF_TRANSLATE_INSN2(Wd, Vd)
+DEF_TRANSLATE_INSN2(Wdq, Vdq)
 
 #define DEF_TRANSLATE_INSN3(opT1, opT2, opT3)   \
 static void translate_insn3(opT1, opT2, opT3)(  \
@@ -5627,6 +5648,9 @@ DEF_TRANSLATE_INSN3(Nq, Nq, Ib)
 DEF_TRANSLATE_INSN3(Pq, Pq, Qd)
 DEF_TRANSLATE_INSN3(Pq, Pq, Qq)
 DEF_TRANSLATE_INSN3(Pq, Qq, Ib)
+DEF_TRANSLATE_INSN3(Vd, Vd, Wd)
+DEF_TRANSLATE_INSN3(Vdq, Vdq, Wdq)
+DEF_TRANSLATE_INSN3(Vdq, Vq, Wq)
 
 #define DEF_TRANSLATE_INSN4(opT1, opT2, opT3, opT4) \
 static void translate_insn4(opT1, opT2, opT3, opT4)(\
@@ -5680,6 +5704,11 @@ DEF_TRANSLATE_INSN3(Pq, Qq, Ib)
 }   \
 }
 
+DEF_TRANSLATE_INSN4(Pq, Pq, RdMw, Ib)
+DEF_TRANSLATE_INSN4(Vd, Vd, Wd, Ib)
+DEF_TRANSLATE_INSN4(Vdq, Vdq, Wd, modrm_mod)
+DEF_TRANSLATE_INSN4(Vdq, Vdq, Wdq, Ib)
+
 #define OPCODE_GRP_BEGIN(grpname)   \
 static void translate_group(grpname)(   \
 CPUX86State *env, DisasContext *s, int modrm)   \
-- 
2.20.1




[Qemu-devel] [RFC PATCH v3 40/46] target/i386: introduce SSE instructions to sse-opcode.inc.h

2019-08-14 Thread Jan Bobek
Add all the SSE instruction entries to sse-opcode.inc.h.

Signed-off-by: Jan Bobek 
---
 target/i386/sse-opcode.inc.h | 158 +++
 1 file changed, 158 insertions(+)

diff --git a/target/i386/sse-opcode.inc.h b/target/i386/sse-opcode.inc.h
index 36963e5a7c..39947aeb51 100644
--- a/target/i386/sse-opcode.inc.h
+++ b/target/i386/sse-opcode.inc.h
@@ -51,6 +51,36 @@ OPCODE(movq, LEG(NP, 0F, 1, 0x7e), MMX, WR, Eq, Pq)
 OPCODE(movq, LEG(NP, 0F, 0, 0x6f), MMX, WR, Pq, Qq)
 /* NP 0F 7F /r: MOVQ mm/m64, mm */
 OPCODE(movq, LEG(NP, 0F, 0, 0x7f), MMX, WR, Qq, Pq)
+/* NP 0F 28 /r: MOVAPS xmm1, xmm2/m128 */
+OPCODE(movaps, LEG(NP, 0F, 0, 0x28), SSE, WR, Vdq, Wdq)
+/* NP 0F 29 /r: MOVAPS xmm2/m128, xmm1 */
+OPCODE(movaps, LEG(NP, 0F, 0, 0x29), SSE, WR, Wdq, Vdq)
+/* NP 0F 10 /r: MOVUPS xmm1, xmm2/m128 */
+OPCODE(movups, LEG(NP, 0F, 0, 0x10), SSE, WR, Vdq, Wdq)
+/* NP 0F 11 /r: MOVUPS xmm2/m128, xmm1 */
+OPCODE(movups, LEG(NP, 0F, 0, 0x11), SSE, WR, Wdq, Vdq)
+/* F3 0F 10 /r: MOVSS xmm1, xmm2/m32 */
+OPCODE(movss, LEG(F3, 0F, 0, 0x10), SSE, WRRR, Vdq, Vdq, Wd, modrm_mod)
+/* F3 0F 11 /r: MOVSS xmm2/m32, xmm1 */
+OPCODE(movss, LEG(F3, 0F, 0, 0x11), SSE, WR, Wd, Vd)
+/* NP 0F 12 /r: MOVHLPS xmm1, xmm2 */
+/* NP 0F 12 /r: MOVLPS xmm1, m64 */
+OPCODE(movhlps, LEG(NP, 0F, 0, 0x12), SSE, WR, Vq, UdqMhq)
+/* 0F 13 /r: MOVLPS m64, xmm1 */
+OPCODE(movlps, LEG(NP, 0F, 0, 0x13), SSE, WR, Mq, Vq)
+/* NP 0F 16 /r: MOVLHPS xmm1, xmm2 */
+/* NP 0F 16 /r: MOVHPS xmm1, m64 */
+OPCODE(movlhps, LEG(NP, 0F, 0, 0x16), SSE, WRR, Vdq, Vq, Wq)
+/* NP 0F 17 /r: MOVHPS m64, xmm1 */
+OPCODE(movhps, LEG(NP, 0F, 0, 0x17), SSE, WR, Mq, Vdq)
+/* NP 0F D7 /r: PMOVMSKB r32, mm */
+OPCODE(pmovmskb, LEG(NP, 0F, 0, 0xd7), SSE, WR, Gd, Nq)
+/* NP REX.W 0F D7 /r: PMOVMSKB r64, mm */
+OPCODE(pmovmskb, LEG(NP, 0F, 1, 0xd7), SSE, WR, Gq, Nq)
+/* NP 0F 50 /r: MOVMSKPS r32, xmm */
+OPCODE(movmskps, LEG(NP, 0F, 0, 0x50), SSE, WR, Gd, Udq)
+/* NP REX.W 0F 50 /r: MOVMSKPS r64, xmm */
+OPCODE(movmskps, LEG(NP, 0F, 1, 0x50), SSE, WR, Gq, Udq)
 /* NP 0F FC /r: PADDB mm, mm/m64 */
 OPCODE(paddb, LEG(NP, 0F, 0, 0xfc), MMX, WRR, Pq, Pq, Qq)
 /* NP 0F FD /r: PADDW mm, mm/m64 */
@@ -65,6 +95,10 @@ OPCODE(paddsw, LEG(NP, 0F, 0, 0xed), MMX, WRR, Pq, Pq, Qq)
 OPCODE(paddusb, LEG(NP, 0F, 0, 0xdc), MMX, WRR, Pq, Pq, Qq)
 /* NP 0F DD /r: PADDUSW mm,mm/m64 */
 OPCODE(paddusw, LEG(NP, 0F, 0, 0xdd), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F 58 /r: ADDPS xmm1, xmm2/m128 */
+OPCODE(addps, LEG(NP, 0F, 0, 0x58), SSE, WRR, Vdq, Vdq, Wdq)
+/* F3 0F 58 /r: ADDSS xmm1, xmm2/m32 */
+OPCODE(addss, LEG(F3, 0F, 0, 0x58), SSE, WRR, Vd, Vd, Wd)
 /* NP 0F F8 /r: PSUBB mm, mm/m64 */
 OPCODE(psubb, LEG(NP, 0F, 0, 0xf8), MMX, WRR, Pq, Pq, Qq)
 /* NP 0F F9 /r: PSUBW mm, mm/m64 */
@@ -79,12 +113,60 @@ OPCODE(psubsw, LEG(NP, 0F, 0, 0xe9), MMX, WRR, Pq, Pq, Qq)
 OPCODE(psubusb, LEG(NP, 0F, 0, 0xd8), MMX, WRR, Pq, Pq, Qq)
 /* NP 0F D9 /r: PSUBUSW mm, mm/m64 */
 OPCODE(psubusw, LEG(NP, 0F, 0, 0xd9), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F 5C /r: SUBPS xmm1, xmm2/m128 */
+OPCODE(subps, LEG(NP, 0F, 0, 0x5c), SSE, WRR, Vdq, Vdq, Wdq)
+/* F3 0F 5C /r: SUBSS xmm1, xmm2/m32 */
+OPCODE(subss, LEG(F3, 0F, 0, 0x5c), SSE, WRR, Vd, Vd, Wd)
 /* NP 0F D5 /r: PMULLW mm, mm/m64 */
 OPCODE(pmullw, LEG(NP, 0F, 0, 0xd5), MMX, WRR, Pq, Pq, Qq)
 /* NP 0F E5 /r: PMULHW mm, mm/m64 */
 OPCODE(pmulhw, LEG(NP, 0F, 0, 0xe5), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F E4 /r: PMULHUW mm1, mm2/m64 */
+OPCODE(pmulhuw, LEG(NP, 0F, 0, 0xe4), SSE, WRR, Pq, Pq, Qq)
+/* NP 0F 59 /r: MULPS xmm1, xmm2/m128 */
+OPCODE(mulps, LEG(NP, 0F, 0, 0x59), SSE, WRR, Vdq, Vdq, Wdq)
+/* F3 0F 59 /r: MULSS xmm1,xmm2/m32 */
+OPCODE(mulss, LEG(F3, 0F, 0, 0x59), SSE, WRR, Vd, Vd, Wd)
 /* NP 0F F5 /r: PMADDWD mm, mm/m64 */
 OPCODE(pmaddwd, LEG(NP, 0F, 0, 0xf5), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F 5E /r: DIVPS xmm1, xmm2/m128 */
+OPCODE(divps, LEG(NP, 0F, 0, 0x5e), SSE, WRR, Vdq, Vdq, Wdq)
+/* F3 0F 5E /r: DIVSS xmm1, xmm2/m32 */
+OPCODE(divss, LEG(F3, 0F, 0, 0x5e), SSE, WRR, Vd, Vd, Wd)
+/* NP 0F 53 /r: RCPPS xmm1, xmm2/m128 */
+OPCODE(rcpps, LEG(NP, 0F, 0, 0x53), SSE, WR, Vdq, Wdq)
+/* F3 0F 53 /r: RCPSS xmm1, xmm2/m32 */
+OPCODE(rcpss, LEG(F3, 0F, 0, 0x53), SSE, WR, Vd, Wd)
+/* NP 0F 51 /r: SQRTPS xmm1, xmm2/m128 */
+OPCODE(sqrtps, LEG(NP, 0F, 0, 0x51), SSE, WR, Vdq, Wdq)
+/* F3 0F 51 /r: SQRTSS xmm1, xmm2/m32 */
+OPCODE(sqrtss, LEG(F3, 0F, 0, 0x51), SSE, WR, Vd, Wd)
+/* NP 0F 52 /r: RSQRTPS xmm1, xmm2/m128 */
+OPCODE(rsqrtps, LEG(NP, 0F, 0, 0x52), SSE, WR, Vdq, Wdq)
+/* F3 0F 52 /r: RSQRTSS xmm1, xmm2/m32 */
+OPCODE(rsqrtss, LEG(F3, 0F, 0, 0x52), SSE, WR, Vd, Wd)
+/* NP 0F DA /r: PMINUB mm1, mm2/m64 */
+OPCODE(pminub, LEG(NP, 0F, 0, 0xda), SSE, WRR, Pq, Pq, Qq)
+/* NP 0F EA /r: PMINSW mm1, mm2/m64 */
+OPCODE(pminsw, LEG(NP, 0F, 0, 0xea), SSE, WRR, Pq, Pq, Qq)
+/* NP 0F 5D /r: MINPS xmm1, xmm2/m128 */
+OPCODE(minps, LEG(NP, 0F, 0, 0x5d), SSE, WRR, Vdq, Vdq, Wdq)
+/* F3 0F 5D /r: MINSS xmm1,xmm2/m32 */
+OPCODE(minss, LEG(F3, 0F, 0, 0x5d), SSE, WRR, Vd, Vd, Wd

[Qemu-devel] [RFC PATCH v3 41/46] target/i386: introduce SSE2 translators

2019-08-14 Thread Jan Bobek
Use the translator macros to define translators required by SSE2
instructions.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 33 +
 1 file changed, 33 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 3d526ee470..177bedd0ef 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -5891,14 +5891,20 @@ DEF_TRANSLATE_INSN1(Md)
 }
 
 DEF_TRANSLATE_INSN2(Ed, Pq)
+DEF_TRANSLATE_INSN2(Ed, Vdq)
 DEF_TRANSLATE_INSN2(Eq, Pq)
+DEF_TRANSLATE_INSN2(Eq, Vdq)
 DEF_TRANSLATE_INSN2(Gd, Nq)
 DEF_TRANSLATE_INSN2(Gd, Udq)
 DEF_TRANSLATE_INSN2(Gd, Wd)
+DEF_TRANSLATE_INSN2(Gd, Wq)
 DEF_TRANSLATE_INSN2(Gq, Nq)
 DEF_TRANSLATE_INSN2(Gq, Udq)
 DEF_TRANSLATE_INSN2(Gq, Wd)
+DEF_TRANSLATE_INSN2(Gq, Wq)
+DEF_TRANSLATE_INSN2(Md, Gd)
 DEF_TRANSLATE_INSN2(Mdq, Vdq)
+DEF_TRANSLATE_INSN2(Mq, Gq)
 DEF_TRANSLATE_INSN2(Mq, Pq)
 DEF_TRANSLATE_INSN2(Mq, Vdq)
 DEF_TRANSLATE_INSN2(Mq, Vq)
@@ -5906,16 +5912,33 @@ DEF_TRANSLATE_INSN2(Pq, Ed)
 DEF_TRANSLATE_INSN2(Pq, Eq)
 DEF_TRANSLATE_INSN2(Pq, Nq)
 DEF_TRANSLATE_INSN2(Pq, Qq)
+DEF_TRANSLATE_INSN2(Pq, Uq)
+DEF_TRANSLATE_INSN2(Pq, Wdq)
 DEF_TRANSLATE_INSN2(Pq, Wq)
 DEF_TRANSLATE_INSN2(Qq, Pq)
+DEF_TRANSLATE_INSN2(UdqMq, Vq)
 DEF_TRANSLATE_INSN2(Vd, Ed)
 DEF_TRANSLATE_INSN2(Vd, Eq)
 DEF_TRANSLATE_INSN2(Vd, Wd)
+DEF_TRANSLATE_INSN2(Vd, Wq)
+DEF_TRANSLATE_INSN2(Vdq, Ed)
+DEF_TRANSLATE_INSN2(Vdq, Eq)
+DEF_TRANSLATE_INSN2(Vdq, Nq)
 DEF_TRANSLATE_INSN2(Vdq, Qq)
+DEF_TRANSLATE_INSN2(Vdq, Udq)
 DEF_TRANSLATE_INSN2(Vdq, Wdq)
+DEF_TRANSLATE_INSN2(Vdq, Wq)
+DEF_TRANSLATE_INSN2(Vq, Ed)
+DEF_TRANSLATE_INSN2(Vq, Eq)
+DEF_TRANSLATE_INSN2(Vq, Mq)
 DEF_TRANSLATE_INSN2(Vq, UdqMhq)
+DEF_TRANSLATE_INSN2(Vq, Wd)
+DEF_TRANSLATE_INSN2(Vq, Wq)
 DEF_TRANSLATE_INSN2(Wd, Vd)
 DEF_TRANSLATE_INSN2(Wdq, Vdq)
+DEF_TRANSLATE_INSN2(Wq, Vq)
+DEF_TRANSLATE_INSN2(Wq, Wd)
+DEF_TRANSLATE_INSN2(modrm_mod, modrm)
 
 #define DEF_TRANSLATE_INSN3(opT1, opT2, opT3)   \
 static void translate_insn3(opT1, opT2, opT3)(  \
@@ -5962,14 +5985,21 @@ DEF_TRANSLATE_INSN2(Wdq, Vdq)
 }
 
 DEF_TRANSLATE_INSN3(Gd, Nq, Ib)
+DEF_TRANSLATE_INSN3(Gd, Udq, Ib)
 DEF_TRANSLATE_INSN3(Gq, Nq, Ib)
+DEF_TRANSLATE_INSN3(Gq, Udq, Ib)
 DEF_TRANSLATE_INSN3(Nq, Nq, Ib)
 DEF_TRANSLATE_INSN3(Pq, Pq, Qd)
 DEF_TRANSLATE_INSN3(Pq, Pq, Qq)
 DEF_TRANSLATE_INSN3(Pq, Qq, Ib)
+DEF_TRANSLATE_INSN3(Udq, Udq, Ib)
 DEF_TRANSLATE_INSN3(Vd, Vd, Wd)
+DEF_TRANSLATE_INSN3(Vdq, Vd, Mq)
+DEF_TRANSLATE_INSN3(Vdq, Vdq, Mq)
 DEF_TRANSLATE_INSN3(Vdq, Vdq, Wdq)
 DEF_TRANSLATE_INSN3(Vdq, Vq, Wq)
+DEF_TRANSLATE_INSN3(Vdq, Wdq, Ib)
+DEF_TRANSLATE_INSN3(Vq, Vq, Wq)
 
 #define DEF_TRANSLATE_INSN4(opT1, opT2, opT3, opT4) \
 static void translate_insn4(opT1, opT2, opT3, opT4)(\
@@ -6025,8 +6055,11 @@ DEF_TRANSLATE_INSN3(Vdq, Vq, Wq)
 
 DEF_TRANSLATE_INSN4(Pq, Pq, RdMw, Ib)
 DEF_TRANSLATE_INSN4(Vd, Vd, Wd, Ib)
+DEF_TRANSLATE_INSN4(Vdq, Vdq, RdMw, Ib)
 DEF_TRANSLATE_INSN4(Vdq, Vdq, Wd, modrm_mod)
 DEF_TRANSLATE_INSN4(Vdq, Vdq, Wdq, Ib)
+DEF_TRANSLATE_INSN4(Vdq, Vdq, Wq, modrm_mod)
+DEF_TRANSLATE_INSN4(Vq, Vq, Wq, Ib)
 
 #define OPCODE_GRP_BEGIN(grpname)   \
 static void translate_group(grpname)(   \
-- 
2.20.1




[Qemu-devel] [RFC PATCH v3 37/46] target/i386: introduce MMX instructions to sse-opcode.inc.h

2019-08-14 Thread Jan Bobek
Add all MMX instruction entries to sse-opcode.inc.h.

Signed-off-by: Jan Bobek 
---
 target/i386/sse-opcode.inc.h | 131 +++
 1 file changed, 131 insertions(+)

diff --git a/target/i386/sse-opcode.inc.h b/target/i386/sse-opcode.inc.h
index c5e81a6a80..36963e5a7c 100644
--- a/target/i386/sse-opcode.inc.h
+++ b/target/i386/sse-opcode.inc.h
@@ -39,6 +39,137 @@
 #   define OPCODE_GRP_END(grpname)
 #endif /* OPCODE_GRP_END */
 
+/* NP 0F 6E /r: MOVD mm,r/m32 */
+OPCODE(movd, LEG(NP, 0F, 0, 0x6e), MMX, WR, Pq, Ed)
+/* NP 0F 7E /r: MOVD r/m32,mm */
+OPCODE(movd, LEG(NP, 0F, 0, 0x7e), MMX, WR, Ed, Pq)
+/* NP REX.W + 0F 6E /r: MOVQ mm,r/m64 */
+OPCODE(movq, LEG(NP, 0F, 1, 0x6e), MMX, WR, Pq, Eq)
+/* NP REX.W + 0F 7E /r: MOVQ r/m64,mm */
+OPCODE(movq, LEG(NP, 0F, 1, 0x7e), MMX, WR, Eq, Pq)
+/* NP 0F 6F /r: MOVQ mm, mm/m64 */
+OPCODE(movq, LEG(NP, 0F, 0, 0x6f), MMX, WR, Pq, Qq)
+/* NP 0F 7F /r: MOVQ mm/m64, mm */
+OPCODE(movq, LEG(NP, 0F, 0, 0x7f), MMX, WR, Qq, Pq)
+/* NP 0F FC /r: PADDB mm, mm/m64 */
+OPCODE(paddb, LEG(NP, 0F, 0, 0xfc), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F FD /r: PADDW mm, mm/m64 */
+OPCODE(paddw, LEG(NP, 0F, 0, 0xfd), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F FE /r: PADDD mm, mm/m64 */
+OPCODE(paddd, LEG(NP, 0F, 0, 0xfe), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F EC /r: PADDSB mm, mm/m64 */
+OPCODE(paddsb, LEG(NP, 0F, 0, 0xec), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F ED /r: PADDSW mm, mm/m64 */
+OPCODE(paddsw, LEG(NP, 0F, 0, 0xed), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F DC /r: PADDUSB mm,mm/m64 */
+OPCODE(paddusb, LEG(NP, 0F, 0, 0xdc), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F DD /r: PADDUSW mm,mm/m64 */
+OPCODE(paddusw, LEG(NP, 0F, 0, 0xdd), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F F8 /r: PSUBB mm, mm/m64 */
+OPCODE(psubb, LEG(NP, 0F, 0, 0xf8), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F F9 /r: PSUBW mm, mm/m64 */
+OPCODE(psubw, LEG(NP, 0F, 0, 0xf9), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F FA /r: PSUBD mm, mm/m64 */
+OPCODE(psubd, LEG(NP, 0F, 0, 0xfa), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F E8 /r: PSUBSB mm, mm/m64 */
+OPCODE(psubsb, LEG(NP, 0F, 0, 0xe8), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F E9 /r: PSUBSW mm, mm/m64 */
+OPCODE(psubsw, LEG(NP, 0F, 0, 0xe9), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F D8 /r: PSUBUSB mm, mm/m64 */
+OPCODE(psubusb, LEG(NP, 0F, 0, 0xd8), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F D9 /r: PSUBUSW mm, mm/m64 */
+OPCODE(psubusw, LEG(NP, 0F, 0, 0xd9), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F D5 /r: PMULLW mm, mm/m64 */
+OPCODE(pmullw, LEG(NP, 0F, 0, 0xd5), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F E5 /r: PMULHW mm, mm/m64 */
+OPCODE(pmulhw, LEG(NP, 0F, 0, 0xe5), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F F5 /r: PMADDWD mm, mm/m64 */
+OPCODE(pmaddwd, LEG(NP, 0F, 0, 0xf5), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F 74 /r: PCMPEQB mm,mm/m64 */
+OPCODE(pcmpeqb, LEG(NP, 0F, 0, 0x74), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F 75 /r: PCMPEQW mm,mm/m64 */
+OPCODE(pcmpeqw, LEG(NP, 0F, 0, 0x75), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F 76 /r: PCMPEQD mm,mm/m64 */
+OPCODE(pcmpeqd, LEG(NP, 0F, 0, 0x76), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F 64 /r: PCMPGTB mm,mm/m64 */
+OPCODE(pcmpgtb, LEG(NP, 0F, 0, 0x64), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F 65 /r: PCMPGTW mm,mm/m64 */
+OPCODE(pcmpgtw, LEG(NP, 0F, 0, 0x65), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F 66 /r: PCMPGTD mm,mm/m64 */
+OPCODE(pcmpgtd, LEG(NP, 0F, 0, 0x66), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F DB /r: PAND mm, mm/m64 */
+OPCODE(pand, LEG(NP, 0F, 0, 0xdb), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F DF /r: PANDN mm, mm/m64 */
+OPCODE(pandn, LEG(NP, 0F, 0, 0xdf), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F EB /r: POR mm, mm/m64 */
+OPCODE(por, LEG(NP, 0F, 0, 0xeb), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F EF /r: PXOR mm, mm/m64 */
+OPCODE(pxor, LEG(NP, 0F, 0, 0xef), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F F1 /r: PSLLW mm, mm/m64 */
+OPCODE(psllw, LEG(NP, 0F, 0, 0xf1), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F F2 /r: PSLLD mm, mm/m64 */
+OPCODE(pslld, LEG(NP, 0F, 0, 0xf2), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F F3 /r: PSLLQ mm, mm/m64 */
+OPCODE(psllq, LEG(NP, 0F, 0, 0xf3), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F D1 /r: PSRLW mm, mm/m64 */
+OPCODE(psrlw, LEG(NP, 0F, 0, 0xd1), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F D2 /r: PSRLD mm, mm/m64 */
+OPCODE(psrld, LEG(NP, 0F, 0, 0xd2), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F D3 /r: PSRLQ mm, mm/m64 */
+OPCODE(psrlq, LEG(NP, 0F, 0, 0xd3), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F E1 /r: PSRAW mm,mm/m64 */
+OPCODE(psraw, LEG(NP, 0F, 0, 0xe1), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F E2 /r: PSRAD mm,mm/m64 */
+OPCODE(psrad, LEG(NP, 0F, 0, 0xe2), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F 63 /r: PACKSSWB mm1, mm2/m64 */
+OPCODE(packsswb, LEG(NP, 0F, 0, 0x63), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F 6B /r: PACKSSDW mm1, mm2/m64 */
+OPCODE(packssdw, LEG(NP, 0F, 0, 0x6b), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F 67 /r: PACKUSWB mm, mm/m64 */
+OPCODE(packuswb, LEG(NP, 0F, 0, 0x67), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F 68 /r: PUNPCKHBW mm, mm/m64 */
+OPCODE(punpckhbw, LEG(NP, 0F, 0, 0x68), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F 69 /r: PUNPCKHWD mm, mm/m64 */
+OPCODE(punpckhwd, LEG(NP, 0F, 0, 0x69), MMX, WRR, Pq, Pq, Qq)
+/* NP 0F 6A /r: PUNPCKHDQ mm, mm/m64 */
+OPCODE(punpckhdq, LEG(NP, 0F, 0, 0x6a

[Qemu-devel] [RFC PATCH v3 39/46] target/i386: introduce SSE code generators

2019-08-14 Thread Jan Bobek
Introduce code generators required by SSE instructions.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 319 
 1 file changed, 319 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index ef64fe606f..3d526ee470 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -5360,6 +5360,9 @@ INSNOP_LDST(xmm_t0, Mhq)
 #define DEF_GEN_INSN2_GVEC_MM(mnem, gvec, opT1, opT2, vece)   \
 DEF_GEN_INSN2_GVEC(mnem, gvec, opT1, opT2, vece,  \
sizeof(MMXReg), sizeof(MMXReg))
+#define DEF_GEN_INSN2_GVEC_XMM(mnem, gvec, opT1, opT2, vece)  \
+DEF_GEN_INSN2_GVEC(mnem, gvec, opT1, opT2, vece,  \
+   sizeof(XMMReg), sizeof(XMMReg))
 
 #define DEF_GEN_INSN3_GVEC(mnem, gvec, opT1, opT2, opT3, vece, oprsz, maxsz) \
 GEN_INSN3(mnem, opT1, opT2, opT3)   \
@@ -5369,6 +5372,9 @@ INSNOP_LDST(xmm_t0, Mhq)
 #define DEF_GEN_INSN3_GVEC_MM(mnem, gvec, opT1, opT2, opT3, vece)   \
 DEF_GEN_INSN3_GVEC(mnem, gvec, opT1, opT2, opT3, vece,  \
sizeof(MMXReg), sizeof(MMXReg))
+#define DEF_GEN_INSN3_GVEC_XMM(mnem, gvec, opT1, opT2, opT3, vece)  \
+DEF_GEN_INSN3_GVEC(mnem, gvec, opT1, opT2, opT3, vece,  \
+   sizeof(XMMReg), sizeof(XMMReg))
 
 GEN_INSN2(movq, Pq, Eq);/* forward declaration */
 GEN_INSN2(movd, Pq, Ed)
@@ -5399,6 +5405,90 @@ GEN_INSN2(movq, Eq, Pq)
 
 DEF_GEN_INSN2_GVEC_MM(movq, mov, Pq, Qq, MO_64)
 DEF_GEN_INSN2_GVEC_MM(movq, mov, Qq, Pq, MO_64)
+DEF_GEN_INSN2_GVEC_XMM(movaps, mov, Vdq, Wdq, MO_64)
+DEF_GEN_INSN2_GVEC_XMM(movaps, mov, Wdq, Vdq, MO_64)
+DEF_GEN_INSN2_GVEC_XMM(movups, mov, Vdq, Wdq, MO_64)
+DEF_GEN_INSN2_GVEC_XMM(movups, mov, Wdq, Vdq, MO_64)
+
+GEN_INSN2(movss, Wd, Vd);   /* forward declaration */
+GEN_INSN4(movss, Vdq, Vdq, Wd, modrm_mod)
+{
+assert(arg1 == arg2);
+
+if (arg4 == 3) {
+/* merging movss */
+gen_insn2(movss, Wd, Vd)(env, s, arg1, arg3);
+} else {
+/* zero-extending movss */
+const TCGv_i32 r32 = tcg_temp_new_i32();
+const TCGv_i64 r64 = tcg_temp_new_i64();
+
+tcg_gen_ld_i32(r32, cpu_env, arg3 + offsetof(ZMMReg, ZMM_L(0)));
+tcg_gen_extu_i32_i64(r64, r32);
+tcg_gen_st_i64(r64, cpu_env, arg1 + offsetof(ZMMReg, ZMM_Q(0)));
+
+tcg_gen_movi_i64(r64, 0);
+tcg_gen_st_i64(r64, cpu_env, arg1 + offsetof(ZMMReg, ZMM_Q(1)));
+
+tcg_temp_free_i32(r32);
+tcg_temp_free_i64(r64);
+}
+}
+
+GEN_INSN2(movss, Wd, Vd)
+{
+const insnop_arg_t(Wd) dofs = offsetof(ZMMReg, ZMM_L(0));
+const insnop_arg_t(Vd) aofs = offsetof(ZMMReg, ZMM_L(0));
+gen_op_movl(s, arg1 + dofs, arg2 + aofs);
+}
+
+GEN_INSN2(movhlps, Vq, UdqMhq)
+{
+const size_t dofs = offsetof(ZMMReg, ZMM_Q(0));
+const size_t aofs = offsetof(ZMMReg, ZMM_Q(1));
+gen_op_movq(s, arg1 + dofs, arg2 + aofs);
+}
+
+GEN_INSN2(movlps, Mq, Vq)
+{
+assert(arg1 == s->A0);
+gen_stq_env_A0(s, arg2 + offsetof(ZMMReg, ZMM_Q(0)));
+}
+
+GEN_INSN3(movlhps, Vdq, Vq, Wq)
+{
+assert(arg1 == arg2);
+
+const size_t dofs = offsetof(ZMMReg, ZMM_Q(1));
+const size_t aofs = offsetof(ZMMReg, ZMM_Q(0));
+gen_op_movq(s, arg1 + dofs, arg3 + aofs);
+}
+
+GEN_INSN2(movhps, Mq, Vdq)
+{
+assert(arg1 == s->A0);
+gen_stq_env_A0(s, arg2 + offsetof(ZMMReg, ZMM_Q(1)));
+}
+
+DEF_GEN_INSN2_HELPER_DEP(pmovmskb, pmovmskb_mmx, Gd, Nq)
+
+GEN_INSN2(pmovmskb, Gq, Nq)
+{
+const TCGv_i32 arg1_r32 = tcg_temp_new_i32();
+gen_insn2(pmovmskb, Gd, Nq)(env, s, arg1_r32, arg2);
+tcg_gen_extu_i32_i64(arg1, arg1_r32);
+tcg_temp_free_i32(arg1_r32);
+}
+
+DEF_GEN_INSN2_HELPER_DEP(movmskps, movmskps, Gd, Udq)
+
+GEN_INSN2(movmskps, Gq, Udq)
+{
+const TCGv_i32 arg1_r32 = tcg_temp_new_i32();
+gen_insn2(movmskps, Gd, Udq)(env, s, arg1_r32, arg2);
+tcg_gen_extu_i32_i64(arg1, arg1_r32);
+tcg_temp_free_i32(arg1_r32);
+}
 
 DEF_GEN_INSN3_GVEC_MM(paddb, add, Pq, Pq, Qq, MO_8)
 DEF_GEN_INSN3_GVEC_MM(paddw, add, Pq, Pq, Qq, MO_16)
@@ -5407,6 +5497,8 @@ DEF_GEN_INSN3_GVEC_MM(paddsb, ssadd, Pq, Pq, Qq, MO_8)
 DEF_GEN_INSN3_GVEC_MM(paddsw, ssadd, Pq, Pq, Qq, MO_16)
 DEF_GEN_INSN3_GVEC_MM(paddusb, usadd, Pq, Pq, Qq, MO_8)
 DEF_GEN_INSN3_GVEC_MM(paddusw, usadd, Pq, Pq, Qq, MO_16)
+DEF_GEN_INSN3_HELPER_EPP(addps, addps, Vdq, Vdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(addss, addss, Vd, Vd, Wd)
 
 DEF_GEN_INSN3_GVEC_MM(psubb, sub, Pq, Pq, Qq, MO_8)
 DEF_GEN_INSN3_GVEC_MM(psubw, sub, Pq, Pq, Qq, MO_16)
@@ -5415,11 +5507,38 @@ DEF_GEN_INSN3_GVEC_MM(psubsb, sssub, Pq, Pq, Qq, MO_8)
 DEF_GEN_INSN3_GVEC_MM(psubsw, sssub, Pq, Pq, Qq, MO_16)
 DEF_GEN_INSN3_GVEC_MM(psubusb, ussub, Pq, Pq, Qq, MO_8)
 DEF_GEN_INSN3_GVEC_MM(psubusw, ussub, Pq, Pq, Qq, MO_16)
+DEF_GEN_INSN3_HELPER_EPP(subps, subps, Vdq, Vdq, Wdq)
+DEF_GEN_INSN3_HELPER_EPP(subss, subss, Vd, 

[Qemu-devel] [RFC PATCH v3 32/46] target/i386: introduce gvec-based code generator macros

2019-08-14 Thread Jan Bobek
Code generators defined using these macros rely on a gvec operation
(i.e. tcg_gen_gvec_*).

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index b28d651b82..75652afb45 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -23,6 +23,7 @@
 #include "disas/disas.h"
 #include "exec/exec-all.h"
 #include "tcg-op.h"
+#include "tcg-op-gvec.h"
 #include "exec/cpu_ldst.h"
 #include "exec/translator.h"
 
@@ -5351,6 +5352,18 @@ INSNOP_LDST(xmm_t0, Mhq)
 tcg_temp_free_i32(arg4_r32);\
 }
 
+#define DEF_GEN_INSN2_GVEC(mnem, gvec, opT1, opT2, vece, oprsz, maxsz)  \
+GEN_INSN2(mnem, opT1, opT2) \
+{   \
+tcg_gen_gvec_ ## gvec(vece, arg1, arg2, oprsz, maxsz);  \
+}
+
+#define DEF_GEN_INSN3_GVEC(mnem, gvec, opT1, opT2, opT3, vece, oprsz, maxsz) \
+GEN_INSN3(mnem, opT1, opT2, opT3)   \
+{   \
+tcg_gen_gvec_ ## gvec(vece, arg1, arg2, arg3, oprsz, maxsz);\
+}
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
 enum {
-- 
2.20.1




[Qemu-devel] [RFC PATCH v3 36/46] target/i386: introduce MMX code generators

2019-08-14 Thread Jan Bobek
Define code generators required for MMX instructions.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 111 
 1 file changed, 111 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 4fecb0d240..a02e9cd0d2 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -5357,12 +5357,123 @@ INSNOP_LDST(xmm_t0, Mhq)
 {   \
 tcg_gen_gvec_ ## gvec(vece, arg1, arg2, oprsz, maxsz);  \
 }
+#define DEF_GEN_INSN2_GVEC_MM(mnem, gvec, opT1, opT2, vece)   \
+DEF_GEN_INSN2_GVEC(mnem, gvec, opT1, opT2, vece,  \
+   sizeof(MMXReg), sizeof(MMXReg))
 
 #define DEF_GEN_INSN3_GVEC(mnem, gvec, opT1, opT2, opT3, vece, oprsz, maxsz) \
 GEN_INSN3(mnem, opT1, opT2, opT3)   \
 {   \
 tcg_gen_gvec_ ## gvec(vece, arg1, arg2, arg3, oprsz, maxsz);\
 }
+#define DEF_GEN_INSN3_GVEC_MM(mnem, gvec, opT1, opT2, opT3, vece)   \
+DEF_GEN_INSN3_GVEC(mnem, gvec, opT1, opT2, opT3, vece,  \
+   sizeof(MMXReg), sizeof(MMXReg))
+
+GEN_INSN2(movq, Pq, Eq);/* forward declaration */
+GEN_INSN2(movd, Pq, Ed)
+{
+const insnop_arg_t(Eq) arg2_r64 = tcg_temp_new_i64();
+tcg_gen_extu_i32_i64(arg2_r64, arg2);
+gen_insn2(movq, Pq, Eq)(env, s, arg1, arg2_r64);
+tcg_temp_free_i64(arg2_r64);
+}
+
+GEN_INSN2(movd, Ed, Pq)
+{
+const insnop_arg_t(Pq) ofs = offsetof(MMXReg, MMX_L(0));
+tcg_gen_ld_i32(arg1, cpu_env, arg2 + ofs);
+}
+
+GEN_INSN2(movq, Pq, Eq)
+{
+const insnop_arg_t(Pq) ofs = offsetof(MMXReg, MMX_Q(0));
+tcg_gen_st_i64(arg2, cpu_env, arg1 + ofs);
+}
+
+GEN_INSN2(movq, Eq, Pq)
+{
+const insnop_arg_t(Pq) ofs = offsetof(MMXReg, MMX_Q(0));
+tcg_gen_ld_i64(arg1, cpu_env, arg2 + ofs);
+}
+
+DEF_GEN_INSN2_GVEC_MM(movq, mov, Pq, Qq, MO_64)
+DEF_GEN_INSN2_GVEC_MM(movq, mov, Qq, Pq, MO_64)
+
+DEF_GEN_INSN3_GVEC_MM(paddb, add, Pq, Pq, Qq, MO_8)
+DEF_GEN_INSN3_GVEC_MM(paddw, add, Pq, Pq, Qq, MO_16)
+DEF_GEN_INSN3_GVEC_MM(paddd, add, Pq, Pq, Qq, MO_32)
+DEF_GEN_INSN3_GVEC_MM(paddsb, ssadd, Pq, Pq, Qq, MO_8)
+DEF_GEN_INSN3_GVEC_MM(paddsw, ssadd, Pq, Pq, Qq, MO_16)
+DEF_GEN_INSN3_GVEC_MM(paddusb, usadd, Pq, Pq, Qq, MO_8)
+DEF_GEN_INSN3_GVEC_MM(paddusw, usadd, Pq, Pq, Qq, MO_16)
+
+DEF_GEN_INSN3_GVEC_MM(psubb, sub, Pq, Pq, Qq, MO_8)
+DEF_GEN_INSN3_GVEC_MM(psubw, sub, Pq, Pq, Qq, MO_16)
+DEF_GEN_INSN3_GVEC_MM(psubd, sub, Pq, Pq, Qq, MO_32)
+DEF_GEN_INSN3_GVEC_MM(psubsb, sssub, Pq, Pq, Qq, MO_8)
+DEF_GEN_INSN3_GVEC_MM(psubsw, sssub, Pq, Pq, Qq, MO_16)
+DEF_GEN_INSN3_GVEC_MM(psubusb, ussub, Pq, Pq, Qq, MO_8)
+DEF_GEN_INSN3_GVEC_MM(psubusw, ussub, Pq, Pq, Qq, MO_16)
+
+DEF_GEN_INSN3_HELPER_EPP(pmullw, pmullw_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(pmulhw, pmulhw_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(pmaddwd, pmaddwd_mmx, Pq, Pq, Qq)
+
+DEF_GEN_INSN3_GVEC_MM(pcmpeqb, cmpeq, Pq, Pq, Qq, MO_8)
+DEF_GEN_INSN3_GVEC_MM(pcmpeqw, cmpeq, Pq, Pq, Qq, MO_16)
+DEF_GEN_INSN3_GVEC_MM(pcmpeqd, cmpeq, Pq, Pq, Qq, MO_32)
+DEF_GEN_INSN3_GVEC_MM(pcmpgtb, cmpgt, Pq, Pq, Qq, MO_8)
+DEF_GEN_INSN3_GVEC_MM(pcmpgtw, cmpgt, Pq, Pq, Qq, MO_16)
+DEF_GEN_INSN3_GVEC_MM(pcmpgtd, cmpgt, Pq, Pq, Qq, MO_32)
+
+DEF_GEN_INSN3_GVEC_MM(pand, and, Pq, Pq, Qq, MO_64)
+DEF_GEN_INSN3_GVEC_MM(pandn, andn, Pq, Pq, Qq, MO_64)
+DEF_GEN_INSN3_GVEC_MM(por, or, Pq, Pq, Qq, MO_64)
+DEF_GEN_INSN3_GVEC_MM(pxor, xor, Pq, Pq, Qq, MO_64)
+
+DEF_GEN_INSN3_HELPER_EPP(psllw, psllw_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(pslld, pslld_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(psllq, psllq_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(psrlw, psrlw_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(psrld, psrld_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(psrlq, psrlq_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(psraw, psraw_mmx, Pq, Pq, Qq)
+DEF_GEN_INSN3_HELPER_EPP(psrad, psrad_mmx, Pq, Pq, Qq)
+
+#define DEF_GEN_PSHIFT_IMM_MM(mnem, opT1, opT2) \
+GEN_INSN3(mnem, opT1, opT2, Ib) \
+{   \
+const uint64_t arg3_ui64 = (uint8_t)arg3;   \
+const insnop_arg_t(Eq) arg3_r64 = s->tmp1_i64;  \
+const insnop_arg_t(Qq) arg3_mm =\
+offsetof(CPUX86State, mmx_t0.MMX_Q(0)); \
+\
+tcg_gen_movi_i64(arg3_r64, arg3_ui64);  \
+gen_insn2(movq, Pq, Eq)(env, s, arg3_mm, arg3_r64); \
+gen_insn3(mnem, Pq, Pq, Qq)(env, s, arg1, arg2, arg3_mm);   \
+}
+
+DEF_GEN_PSHIFT_IMM_MM(psllw, Nq, Nq)
+DEF_GEN_PSHIFT_IMM_MM(pslld, Nq, Nq)
+DEF_GEN_PSHIFT_IMM_MM(psllq, Nq,

[Qemu-devel] [RFC PATCH v3 31/46] target/i386: introduce helper-based code generator macros

2019-08-14 Thread Jan Bobek
Code generators defined using these macros rely on a helper function
(as emitted by gen_helper_*).

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 106 
 1 file changed, 106 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index b5f609e147..b28d651b82 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -5245,6 +5245,112 @@ INSNOP_LDST(xmm_t0, Mhq)
 insnop_arg_t(opT1) arg1, insnop_arg_t(opT2) arg2,   \
 insnop_arg_t(opT3) arg3, insnop_arg_t(opT4) arg4)
 
+#define DEF_GEN_INSN0_HELPER(mnem, helper)  \
+GEN_INSN0(mnem) \
+{   \
+gen_helper_ ## helper(cpu_env); \
+}
+
+#define DEF_GEN_INSN2_HELPER_EPD(mnem, helper, opT1, opT2)  \
+GEN_INSN2(mnem, opT1, opT2) \
+{   \
+const TCGv_ptr arg1_ptr = tcg_temp_new_ptr();   \
+\
+tcg_gen_addi_ptr(arg1_ptr, cpu_env, arg1);  \
+gen_helper_ ## helper(cpu_env, arg1_ptr, arg2); \
+\
+tcg_temp_free_ptr(arg1_ptr);\
+}
+#define DEF_GEN_INSN2_HELPER_DEP(mnem, helper, opT1, opT2)  \
+GEN_INSN2(mnem, opT1, opT2) \
+{   \
+const TCGv_ptr arg2_ptr = tcg_temp_new_ptr();   \
+\
+tcg_gen_addi_ptr(arg2_ptr, cpu_env, arg2);  \
+gen_helper_ ## helper(arg1, cpu_env, arg2_ptr); \
+\
+tcg_temp_free_ptr(arg2_ptr);\
+}
+#ifdef TARGET_X86_64
+#define DEF_GEN_INSN2_HELPER_EPQ(mnem, helper, opT1, opT2)  \
+DEF_GEN_INSN2_HELPER_EPD(mnem, helper, opT1, opT2)
+#define DEF_GEN_INSN2_HELPER_QEP(mnem, helper, opT1, opT2)  \
+DEF_GEN_INSN2_HELPER_DEP(mnem, helper, opT1, opT2)
+#else /* !TARGET_X86_64 */
+#define DEF_GEN_INSN2_HELPER_EPQ(mnem, helper, opT1, opT2)  \
+GEN_INSN2(mnem, opT1, opT2) \
+{   \
+g_assert_not_reached(); \
+}
+#define DEF_GEN_INSN2_HELPER_QEP(mnem, helper, opT1, opT2)  \
+GEN_INSN2(mnem, opT1, opT2) \
+{   \
+g_assert_not_reached(); \
+}
+#endif /* !TARGET_X86_64 */
+#define DEF_GEN_INSN2_HELPER_EPP(mnem, helper, opT1, opT2)  \
+GEN_INSN2(mnem, opT1, opT2) \
+{   \
+const TCGv_ptr arg1_ptr = tcg_temp_new_ptr();   \
+const TCGv_ptr arg2_ptr = tcg_temp_new_ptr();   \
+\
+tcg_gen_addi_ptr(arg1_ptr, cpu_env, arg1);  \
+tcg_gen_addi_ptr(arg2_ptr, cpu_env, arg2);  \
+gen_helper_ ## helper(cpu_env, arg1_ptr, arg2_ptr); \
+\
+tcg_temp_free_ptr(arg1_ptr);\
+tcg_temp_free_ptr(arg2_ptr);\
+}
+
+#define DEF_GEN_INSN3_HELPER_EPP(mnem, helper, opT1, opT2, opT3)\
+GEN_INSN3(mnem, opT1, opT2, opT3)   \
+{   \
+const TCGv_ptr arg1_ptr = tcg_temp_new_ptr();   \
+const TCGv_ptr arg3_ptr = tcg_temp_new_ptr();   \
+\
+assert(arg1 == arg2);   \
+tcg_gen_addi_ptr(arg1_ptr, cpu_env, arg1);  \
+tcg_gen_addi_ptr(arg3_ptr, cpu_env, arg3);  \
+gen_helper_ ## helper(cpu_env, arg1_ptr, arg3_ptr); \
+\
+tcg_temp_free_ptr(arg1_ptr);\
+tcg_temp_free_ptr(arg3_ptr);\
+}
+#define DEF_GEN_INSN3_HELPER_PPI(mnem, helper, opT1, opT2, opT3)\
+GEN_INSN3(mnem, opT1, opT2, opT3)   \
+{   \
+const TCGv_ptr arg1_ptr = tcg_temp_new_ptr();   \
+const

[Qemu-devel] [RFC PATCH v3 28/46] target/i386: introduce P*, N*, Q* (MMX) operands

2019-08-14 Thread Jan Bobek
These address the MMX-technology register file; the corresponding
cpu_env offset is passed as the operand value. Notably, offset of the
entire register is pased at all times, regardless of the operand-size
suffix.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 79 +
 1 file changed, 79 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 779b692942..bd3c7f9356 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -5011,6 +5011,85 @@ INSNOP_LDST(tcg_temp_i64, Mq)
 }
 }
 
+/*
+ * MMX-technology register operands
+ */
+#define DEF_INSNOP_MM(opT, opTmmid) \
+typedef unsigned int insnop_arg_t(opT); \
+typedef struct {\
+insnop_ctxt_t(opTmmid) mmid;\
+} insnop_ctxt_t(opT);   \
+\
+INSNOP_INIT(opT)\
+{   \
+return insnop_init(opTmmid)(>mmid, env, s, modrm, is_write); \
+}   \
+INSNOP_PREPARE(opT) \
+{   \
+const insnop_arg_t(opTmmid) mmid =  \
+insnop_prepare(opTmmid)(>mmid, env, s, modrm, is_write); \
+const insnop_arg_t(opT) arg =   \
+offsetof(CPUX86State, fpregs[mmid & 7].mmx);\
+insnop_finalize(opTmmid)(>mmid, env, s, modrm, is_write, mmid); \
+return arg; \
+}   \
+INSNOP_FINALIZE(opT)\
+{   \
+}
+
+typedef unsigned int insnop_arg_t(mm_t0);
+typedef struct {} insnop_ctxt_t(mm_t0);
+
+INSNOP_INIT(mm_t0)
+{
+return 0;
+}
+INSNOP_PREPARE(mm_t0)
+{
+return offsetof(CPUX86State, mmx_t0);
+}
+INSNOP_FINALIZE(mm_t0)
+{
+}
+
+DEF_INSNOP_MM(P, modrm_reg)
+DEF_INSNOP_ALIAS(Pd, P)
+DEF_INSNOP_ALIAS(Pq, P)
+
+DEF_INSNOP_MM(N, modrm_rm_direct)
+DEF_INSNOP_ALIAS(Nd, N)
+DEF_INSNOP_ALIAS(Nq, N)
+
+DEF_INSNOP_LDST(MQd, mm_t0, Md)
+DEF_INSNOP_LDST(MQq, mm_t0, Mq)
+DEF_INSNOP_EITHER(Qd, Nd, MQd)
+DEF_INSNOP_EITHER(Qq, Nq, MQq)
+
+INSNOP_LDST(mm_t0, Md)
+{
+const insnop_arg_t(mm_t0) ofs =
+offsetof(MMXReg, MMX_L(0));
+
+assert(ptr == s->A0);
+if (is_write) {
+gen_std_env_A0(s, arg + ofs);
+} else {
+gen_ldd_env_A0(s, arg + ofs);
+}
+}
+INSNOP_LDST(mm_t0, Mq)
+{
+const insnop_arg_t(mm_t0) ofs =
+offsetof(MMXReg, MMX_Q(0));
+
+assert(ptr == s->A0);
+if (is_write) {
+gen_stq_env_A0(s, arg + ofs);
+} else {
+gen_ldq_env_A0(s, arg + ofs);
+}
+}
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
 enum {
-- 
2.20.1




[Qemu-devel] [RFC PATCH v3 33/46] target/i386: introduce sse-opcode.inc.h

2019-08-14 Thread Jan Bobek
This header is intended to eventually list all supported instructions
along with some useful details (e.g. mnemonics, opcode, operands etc.)
It shall be used (along with some preprocessor magic) anytime we need
to automatically generate code for every instruction.

Signed-off-by: Jan Bobek 
---
 target/i386/sse-opcode.inc.h | 69 
 1 file changed, 69 insertions(+)
 create mode 100644 target/i386/sse-opcode.inc.h

diff --git a/target/i386/sse-opcode.inc.h b/target/i386/sse-opcode.inc.h
new file mode 100644
index 00..c5e81a6a80
--- /dev/null
+++ b/target/i386/sse-opcode.inc.h
@@ -0,0 +1,69 @@
+#define FMTI (0, 0, 0, )
+#define FMTI__R__(1, 1, 0, r)
+#define FMTI__RR__   (2, 2, 0, rr)
+#define FMTI__W__(1, 0, 1, w)
+#define FMTI__WR__   (2, 1, 1, wr)
+#define FMTI__WRR__  (3, 2, 1, wrr)
+#define FMTI__WRRR__ (4, 3, 1, wrrr)
+
+#define FMTI__(prop, fmti) FMTI_ ## prop ## __ fmti
+
+#define FMTI_ARGC__(argc, argc_rd, argc_wr, lower)argc
+#define FMTI_ARGC_RD__(argc, argc_rd, argc_wr, lower) argc_rd
+#define FMTI_ARGC_WR__(argc, argc_rd, argc_wr, lower) argc_wr
+#define FMTI_LOWER__(argc, argc_rd, argc_wr, lower)   lower
+
+#define FMT_ARGC(fmt)FMTI__(ARGC, FMTI__ ## fmt ## __)
+#define FMT_ARGC_RD(fmt) FMTI__(ARGC_RD, FMTI__ ## fmt ## __)
+#define FMT_ARGC_WR(fmt) FMTI__(ARGC_WR, FMTI__ ## fmt ## __)
+#define FMT_LOWER(fmt)   FMTI__(LOWER, FMTI__ ## fmt ## __)
+#define FMT_UPPER(fmt)   fmt
+
+#ifndef OPCODE
+#   define OPCODE(mnem, opcode, feat, fmt, ...)
+#endif /* OPCODE */
+
+#ifndef OPCODE_GRP
+#   define OPCODE_GRP(grpname, opcode)
+#endif /* OPCODE_GRP */
+
+#ifndef OPCODE_GRP_BEGIN
+#   define OPCODE_GRP_BEGIN(grpname)
+#endif /* OPCODE_GRP_BEGIN */
+
+#ifndef OPCODE_GRPMEMB
+#   define OPCODE_GRPMEMB(grpname, mnem, opcode, feat, fmt, ...)
+#endif /* OPCODE_GRPMEMB */
+
+#ifndef OPCODE_GRP_END
+#   define OPCODE_GRP_END(grpname)
+#endif /* OPCODE_GRP_END */
+
+#undef FMTI
+#undef FMTI__R__
+#undef FMTI__RR__
+#undef FMTI__W__
+#undef FMTI__WR__
+#undef FMTI__WRR__
+#undef FMTI__WRRR__
+
+#undef FMTI__
+
+#undef FMTI_ARGC__
+#undef FMTI_ARGC_RD__
+#undef FMTI_ARGC_WR__
+#undef FMTI_LOWER__
+
+#undef FMT_ARGC
+#undef FMT_ARGC_RD
+#undef FMT_ARGC_WR
+#undef FMT_LOWER
+#undef FMT_UPPER
+
+#undef LEG
+#undef VEX
+#undef OPCODE
+#undef OPCODE_GRP
+#undef OPCODE_GRP_BEGIN
+#undef OPCODE_GRPMEMB
+#undef OPCODE_GRP_END
-- 
2.20.1




[Qemu-devel] [RFC PATCH v3 34/46] target/i386: introduce instruction translator macros

2019-08-14 Thread Jan Bobek
Instruction "translators" are responsible for decoding and loading
instruction operands, calling the passed-in code generator, and
storing the operands back (if applicable). Once a translator returns,
the instruction has been translated to TCG ops, hence the name.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 237 
 1 file changed, 237 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 75652afb45..76c27d0380 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -5364,6 +5364,228 @@ INSNOP_LDST(xmm_t0, Mhq)
 tcg_gen_gvec_ ## gvec(vece, arg1, arg2, arg3, oprsz, maxsz);\
 }
 
+/*
+ * Instruction translators
+ */
+#define translate_insn(argc, ...)   \
+glue(translate_insn, argc)(__VA_ARGS__)
+#define translate_insn0()   \
+translate_insn_0
+#define translate_insn1(opT1)   \
+translate_insn_1 ## opT1
+#define translate_insn2(opT1, opT2) \
+translate_insn_2 ## opT1 ## opT2
+#define translate_insn3(opT1, opT2, opT3)   \
+translate_insn_3 ## opT1 ## opT2 ## opT3
+#define translate_insn4(opT1, opT2, opT3, opT4) \
+translate_insn_4 ## opT1 ## opT2 ## opT3 ## opT4
+#define translate_group(grpname)\
+translate_group_ ## grpname
+
+static void translate_insn0()(
+CPUX86State *env, DisasContext *s, int modrm,
+int ck_cpuid_feat, unsigned int argc_wr,
+void (*gen_insn_fp)(CPUX86State *, DisasContext *))
+{
+if (ck_cpuid(env, s, ck_cpuid_feat)) {
+gen_illegal_opcode(s);
+return;
+}
+
+(*gen_insn_fp)(env, s);
+}
+
+#define DEF_TRANSLATE_INSN1(opT1)   \
+static void translate_insn1(opT1)(  \
+CPUX86State *env, DisasContext *s, int modrm,   \
+int ck_cpuid_feat, unsigned int argc_wr,\
+void (*gen_insn1_fp)(CPUX86State *, DisasContext *, \
+ insnop_arg_t(opT1)))   \
+{   \
+insnop_ctxt_t(opT1) ctxt1;  \
+\
+const bool is_write1 = (1 <= argc_wr);  \
+\
+int ret = ck_cpuid(env, s, ck_cpuid_feat);  \
+if (!ret) { \
+ret = insnop_init(opT1)(, env, s, modrm, is_write1);  \
+}   \
+if (!ret) { \
+const insnop_arg_t(opT1) arg1 = \
+insnop_prepare(opT1)(, env, s, modrm, is_write1); \
+\
+(*gen_insn1_fp)(env, s, arg1);  \
+\
+insnop_finalize(opT1)(, env, s, modrm, is_write1, arg1); \
+} else {\
+gen_illegal_opcode(s);  \
+}   \
+}
+
+#define DEF_TRANSLATE_INSN2(opT1, opT2) \
+static void translate_insn2(opT1, opT2)(\
+CPUX86State *env, DisasContext *s, int modrm,   \
+int ck_cpuid_feat, unsigned int argc_wr,\
+void (*gen_insn2_fp)(CPUX86State *, DisasContext *, \
+ insnop_arg_t(opT1), insnop_arg_t(opT2)))   \
+{   \
+insnop_ctxt_t(opT1) ctxt1;  \
+insnop_ctxt_t(opT2) ctxt2;  \
+\
+const bool is_write1 = (1 <= argc_wr);  \
+const bool is_write2 = (2 <= argc_wr);  \
+\
+int ret = ck_cpuid(env, s, ck_cpuid_feat);  \
+if (!ret) { \
+ret = insnop_init(opT1)(, env, s, modrm, is_write1);  \
+}   \
+if (!ret) { \
+ret = insnop_init(opT2)(, env, 

[Qemu-devel] [RFC PATCH v3 29/46] target/i386: introduce H*, V*, U*, W* (SSE/AVX) operands

2019-08-14 Thread Jan Bobek
These address the SSE/AVX-technology register file. Offset of the
entire corresponding register is passed as the operand value,
regardless of operand-size suffix.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 117 
 1 file changed, 117 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index bd3c7f9356..69233fd0f8 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4930,6 +4930,7 @@ DEF_INSNOP_ALIAS(Mb, M)
 DEF_INSNOP_ALIAS(Mw, M)
 DEF_INSNOP_ALIAS(Md, M)
 DEF_INSNOP_ALIAS(Mq, M)
+DEF_INSNOP_ALIAS(Mhq, M)
 DEF_INSNOP_ALIAS(Mdq, M)
 DEF_INSNOP_ALIAS(Mqq, M)
 
@@ -5090,6 +5091,122 @@ INSNOP_LDST(mm_t0, Mq)
 }
 }
 
+/*
+ * SSE/AVX-technology registers
+ */
+#define DEF_INSNOP_XMM(opT, opTxmmid)   \
+typedef unsigned int insnop_arg_t(opT); \
+typedef struct {\
+insnop_ctxt_t(opTxmmid) xmmid;  \
+} insnop_ctxt_t(opT);   \
+\
+INSNOP_INIT(opT)\
+{   \
+return insnop_init(opTxmmid)(>xmmid, env, s, modrm, is_write); \
+}   \
+INSNOP_PREPARE(opT) \
+{   \
+const insnop_arg_t(opTxmmid) xmmid =\
+insnop_prepare(opTxmmid)(>xmmid, env, s, modrm, is_write); \
+const insnop_arg_t(opT) arg =   \
+offsetof(CPUX86State, xmm_regs[xmmid]); \
+insnop_finalize(opTxmmid)(>xmmid, env, s, \
+  modrm, is_write, xmmid);  \
+return arg; \
+}   \
+INSNOP_FINALIZE(opT)\
+{   \
+}
+
+typedef unsigned int insnop_arg_t(xmm_t0);
+typedef struct {} insnop_ctxt_t(xmm_t0);
+
+INSNOP_INIT(xmm_t0)
+{
+return 0;
+}
+INSNOP_PREPARE(xmm_t0)
+{
+return offsetof(CPUX86State, xmm_t0);
+}
+INSNOP_FINALIZE(xmm_t0)
+{
+}
+
+DEF_INSNOP_XMM(V, modrm_reg)
+DEF_INSNOP_ALIAS(Vd, V)
+DEF_INSNOP_ALIAS(Vq, V)
+DEF_INSNOP_ALIAS(Vdq, V)
+DEF_INSNOP_ALIAS(Vqq, V)
+
+DEF_INSNOP_XMM(U, modrm_rm_direct)
+DEF_INSNOP_ALIAS(Ud, U)
+DEF_INSNOP_ALIAS(Uq, U)
+DEF_INSNOP_ALIAS(Udq, U)
+DEF_INSNOP_ALIAS(Uqq, U)
+
+DEF_INSNOP_XMM(H, vex_v)
+DEF_INSNOP_ALIAS(Hd, H)
+DEF_INSNOP_ALIAS(Hq, H)
+DEF_INSNOP_ALIAS(Hdq, H)
+DEF_INSNOP_ALIAS(Hqq, H)
+
+DEF_INSNOP_LDST(MUd, xmm_t0, Md)
+DEF_INSNOP_LDST(MUq, xmm_t0, Mq)
+DEF_INSNOP_LDST(MWdq, xmm_t0, Mdq)
+DEF_INSNOP_LDST(MUdqMhq, xmm_t0, Mhq)
+DEF_INSNOP_EITHER(Wd, Ud, MUd)
+DEF_INSNOP_EITHER(Wq, Uq, MUq)
+DEF_INSNOP_EITHER(Wdq, Udq, MWdq)
+DEF_INSNOP_EITHER(UdqMq, Udq, MUq)
+DEF_INSNOP_EITHER(UdqMhq, Udq, MUdqMhq)
+
+INSNOP_LDST(xmm_t0, Md)
+{
+const insnop_arg_t(xmm_t0) ofs =
+offsetof(ZMMReg, ZMM_L(0));
+
+assert(ptr == s->A0);
+if (is_write) {
+gen_std_env_A0(s, arg + ofs);
+} else {
+gen_ldd_env_A0(s, arg + ofs);
+}
+}
+INSNOP_LDST(xmm_t0, Mq)
+{
+const insnop_arg_t(xmm_t0) ofs =
+offsetof(ZMMReg, ZMM_Q(0));
+
+assert(ptr == s->A0);
+if (is_write) {
+gen_stq_env_A0(s, arg + ofs);
+} else {
+gen_ldq_env_A0(s, arg + ofs);
+}
+}
+INSNOP_LDST(xmm_t0, Mdq)
+{
+assert(ptr == s->A0);
+if (is_write) {
+gen_sto_env_A0(s, arg);
+} else {
+gen_ldo_env_A0(s, arg);
+}
+}
+INSNOP_LDST(xmm_t0, Mhq)
+{
+const insnop_arg_t(xmm_t0) ofs =
+offsetof(ZMMReg, ZMM_Q(1));
+
+assert(ptr == s->A0);
+if (is_write) {
+gen_stq_env_A0(s, arg + ofs);
+} else {
+gen_ldq_env_A0(s, arg + ofs);
+}
+}
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
 enum {
-- 
2.20.1




[Qemu-devel] [RFC PATCH v3 27/46] target/i386: introduce G*, R*, E* (general register) operands

2019-08-14 Thread Jan Bobek
These address the general-purpose register file. The corresponding
32-bit or 64-bit register is passed as the operand value.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 78 +
 1 file changed, 78 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 2374876b38..779b692942 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4933,6 +4933,84 @@ DEF_INSNOP_ALIAS(Mq, M)
 DEF_INSNOP_ALIAS(Mdq, M)
 DEF_INSNOP_ALIAS(Mqq, M)
 
+/*
+ * 32-bit general register operands
+ */
+DEF_INSNOP_LDST(Gd, tcg_temp_i32, modrm_reg)
+DEF_INSNOP_LDST(Rd, tcg_temp_i32, modrm_rm_direct)
+
+INSNOP_LDST(tcg_temp_i32, modrm_reg)
+{
+assert(0 <= ptr && ptr < CPU_NB_REGS);
+if (is_write) {
+tcg_gen_extu_i32_tl(cpu_regs[ptr], arg);
+} else {
+tcg_gen_trunc_tl_i32(arg, cpu_regs[ptr]);
+}
+}
+INSNOP_LDST(tcg_temp_i32, modrm_rm_direct)
+{
+insnop_ldst(tcg_temp_i32, modrm_reg)(env, s, modrm, is_write, arg, ptr);
+}
+
+DEF_INSNOP_LDST(MEd, tcg_temp_i32, Md)
+DEF_INSNOP_EITHER(Ed, Rd, MEd)
+DEF_INSNOP_LDST(MRdMw, tcg_temp_i32, Mw)
+DEF_INSNOP_EITHER(RdMw, Rd, MRdMw)
+
+INSNOP_LDST(tcg_temp_i32, Md)
+{
+if (is_write) {
+tcg_gen_qemu_st_i32(arg, ptr, s->mem_index, MO_LEUL);
+} else {
+tcg_gen_qemu_ld_i32(arg, ptr, s->mem_index, MO_LEUL);
+}
+}
+INSNOP_LDST(tcg_temp_i32, Mw)
+{
+if (is_write) {
+tcg_gen_qemu_st_i32(arg, ptr, s->mem_index, MO_LEUW);
+} else {
+tcg_gen_qemu_ld_i32(arg, ptr, s->mem_index, MO_LEUW);
+}
+}
+
+/*
+ * 64-bit general register operands
+ */
+DEF_INSNOP_LDST(Gq, tcg_temp_i64, modrm_reg)
+DEF_INSNOP_LDST(Rq, tcg_temp_i64, modrm_rm_direct)
+
+INSNOP_LDST(tcg_temp_i64, modrm_reg)
+{
+#ifdef TARGET_X86_64
+assert(0 <= ptr && ptr < CPU_NB_REGS);
+if (is_write) {
+tcg_gen_mov_i64(cpu_regs[ptr], arg);
+} else {
+tcg_gen_mov_i64(arg, cpu_regs[ptr]);
+}
+#else /* !TARGET_X86_64 */
+g_assert_not_reached();
+#endif /* !TARGET_X86_64 */
+}
+INSNOP_LDST(tcg_temp_i64, modrm_rm_direct)
+{
+insnop_ldst(tcg_temp_i64, modrm_reg)(env, s, modrm, is_write, arg, ptr);
+}
+
+DEF_INSNOP_LDST(MEq, tcg_temp_i64, Mq)
+DEF_INSNOP_EITHER(Eq, Rq, MEq)
+
+INSNOP_LDST(tcg_temp_i64, Mq)
+{
+if (is_write) {
+tcg_gen_qemu_st_i64(arg, ptr, s->mem_index, MO_LEQ);
+} else {
+tcg_gen_qemu_ld_i64(arg, ptr, s->mem_index, MO_LEQ);
+}
+}
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
 enum {
-- 
2.20.1




[Qemu-devel] [RFC PATCH v3 26/46] target/i386: introduce M* (memptr) operands

2019-08-14 Thread Jan Bobek
The memory-pointer operand decodes the indirect form of ModR/M byte,
loads the effective address into a register and passes that register
as the operand.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 36 
 1 file changed, 36 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 78e8f7a212..2374876b38 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4897,6 +4897,42 @@ INSNOP_FINALIZE(Ib)
 {
 }
 
+/*
+ * Memory-pointer operand
+ */
+typedef TCGv insnop_arg_t(M);
+typedef struct {} insnop_ctxt_t(M);
+
+INSNOP_INIT(M)
+{
+int ret;
+insnop_ctxt_t(modrm_mod) modctxt;
+
+ret = insnop_init(modrm_mod)(, env, s, modrm, is_write);
+if (!ret) {
+const int mod =
+insnop_prepare(modrm_mod)(, env, s, modrm, is_write);
+ret = !(mod != 3);
+insnop_finalize(modrm_mod)(, env, s, modrm, is_write, mod);
+}
+return ret;
+}
+INSNOP_PREPARE(M)
+{
+gen_lea_modrm(env, s, modrm);
+return s->A0;
+}
+INSNOP_FINALIZE(M)
+{
+}
+
+DEF_INSNOP_ALIAS(Mb, M)
+DEF_INSNOP_ALIAS(Mw, M)
+DEF_INSNOP_ALIAS(Md, M)
+DEF_INSNOP_ALIAS(Mq, M)
+DEF_INSNOP_ALIAS(Mdq, M)
+DEF_INSNOP_ALIAS(Mqq, M)
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
 enum {
-- 
2.20.1




[Qemu-devel] [RFC PATCH v3 30/46] target/i386: introduce code generators

2019-08-14 Thread Jan Bobek
In this context, "code generators" are functions that receive decoded
instruction operands and emit TCG ops implementing the correct
instruction functionality. Introduce the naming macros first, actual
generator macros will be added later.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 38 ++
 1 file changed, 38 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 69233fd0f8..b5f609e147 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -5207,6 +5207,44 @@ INSNOP_LDST(xmm_t0, Mhq)
 }
 }
 
+/*
+ * Code generators
+ */
+#define gen_insn(mnem, argc, ...)   \
+glue(gen_insn, argc)(mnem, ## __VA_ARGS__)
+#define gen_insn0(mnem) \
+gen_ ## mnem ## _0
+#define gen_insn1(mnem, opT1)   \
+gen_ ## mnem ## _1 ## opT1
+#define gen_insn2(mnem, opT1, opT2) \
+gen_ ## mnem ## _2 ## opT1 ## opT2
+#define gen_insn3(mnem, opT1, opT2, opT3)   \
+gen_ ## mnem ## _3 ## opT1 ## opT2 ## opT3
+#define gen_insn4(mnem, opT1, opT2, opT3, opT4) \
+gen_ ## mnem ## _4 ## opT1 ## opT2 ## opT3 ## opT4
+
+#define GEN_INSN0(mnem) \
+static void gen_insn0(mnem)(\
+CPUX86State *env, DisasContext *s)
+#define GEN_INSN1(mnem, opT1)   \
+static void gen_insn1(mnem, opT1)(  \
+CPUX86State *env, DisasContext *s,  \
+insnop_arg_t(opT1) arg1)
+#define GEN_INSN2(mnem, opT1, opT2) \
+static void gen_insn2(mnem, opT1, opT2)(\
+CPUX86State *env, DisasContext *s,  \
+insnop_arg_t(opT1) arg1, insnop_arg_t(opT2) arg2)
+#define GEN_INSN3(mnem, opT1, opT2, opT3)   \
+static void gen_insn3(mnem, opT1, opT2, opT3)(  \
+CPUX86State *env, DisasContext *s,  \
+insnop_arg_t(opT1) arg1, insnop_arg_t(opT2) arg2,   \
+insnop_arg_t(opT3) arg3)
+#define GEN_INSN4(mnem, opT1, opT2, opT3, opT4) \
+static void gen_insn4(mnem, opT1, opT2, opT3, opT4)(\
+CPUX86State *env, DisasContext *s,  \
+insnop_arg_t(opT1) arg1, insnop_arg_t(opT2) arg2,   \
+insnop_arg_t(opT3) arg3, insnop_arg_t(opT4) arg4)
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
 enum {
-- 
2.20.1




[Qemu-devel] [RFC PATCH v3 25/46] target/i386: introduce Ib (immediate) operand

2019-08-14 Thread Jan Bobek
Introduce the immediate-byte operand, which loads a byte from the
instruction stream and passes its value as the operand.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index 4562a097fa..78e8f7a212 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4879,6 +4879,24 @@ INSNOP_FINALIZE(vex_v)
 {
 }
 
+/*
+ * Immediate operand
+ */
+typedef uint8_t insnop_arg_t(Ib);
+typedef struct {} insnop_ctxt_t(Ib);
+
+INSNOP_INIT(Ib)
+{
+return 0;
+}
+INSNOP_PREPARE(Ib)
+{
+return x86_ldub_code(env, s);
+}
+INSNOP_FINALIZE(Ib)
+{
+}
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
 enum {
-- 
2.20.1




[Qemu-devel] [RFC PATCH v3 19/46] target/i386: introduce generic load-store operand

2019-08-14 Thread Jan Bobek
This operand attempts to capture the "indirect" or "memory" operand in
a generic way. It significatly reduces the amount code that needs to
be written in order to read operands from memory to temporary storage
and write them back.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 54 +
 1 file changed, 54 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index a0b883c680..99f46be34e 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4642,6 +4642,60 @@ static int ck_cpuid(CPUX86State *env, DisasContext *s, 
CkCpuidFeat feat)
  env, s, modrm, is_write, arg));\
 }
 
+/*
+ * Generic load-store operand
+ */
+#define insnop_ldst(opTarg, opTptr) \
+insnop_ldst_ ## opTarg ## opTptr
+
+#define INSNOP_LDST(opTarg, opTptr) \
+static void insnop_ldst(opTarg, opTptr)(CPUX86State *env,   \
+DisasContext *s,\
+int modrm, bool is_write,   \
+insnop_arg_t(opTarg) arg,   \
+insnop_arg_t(opTptr) ptr)
+
+#define DEF_INSNOP_LDST(opT, opTarg, opTptr)\
+typedef insnop_arg_t(opTarg) insnop_arg_t(opT); \
+typedef struct {\
+insnop_ctxt_t(opTarg) arg;  \
+insnop_ctxt_t(opTptr) ptr;  \
+} insnop_ctxt_t(opT);   \
+\
+/* forward declaration */   \
+INSNOP_LDST(opTarg, opTptr);\
+\
+INSNOP_INIT(opT)\
+{   \
+int ret = insnop_init(opTarg)(>arg, env, s, modrm, is_write); \
+if (!ret) { \
+ret = insnop_init(opTptr)(>ptr, env, s, modrm, is_write); \
+}   \
+return ret; \
+}   \
+INSNOP_PREPARE(opT) \
+{   \
+const insnop_arg_t(opTarg) arg =\
+insnop_prepare(opTarg)(>arg, env, s, modrm, is_write); \
+if (!is_write) {\
+const insnop_arg_t(opTptr) ptr =\
+insnop_prepare(opTptr)(>ptr, env, s, modrm, is_write); \
+insnop_ldst(opTarg, opTptr)(env, s, modrm, is_write, arg, ptr); \
+insnop_finalize(opTptr)(>ptr, env, s, modrm, is_write, ptr); 
\
+}   \
+return arg; \
+}   \
+INSNOP_FINALIZE(opT)\
+{   \
+if (is_write) { \
+const insnop_arg_t(opTptr) ptr =\
+insnop_prepare(opTptr)(>ptr, env, s, modrm, is_write); \
+insnop_ldst(opTarg, opTptr)(env, s, modrm, is_write, arg, ptr); \
+insnop_finalize(opTptr)(>ptr, env, s, modrm, is_write, ptr); 
\
+}   \
+insnop_finalize(opTarg)(>arg, env, s, modrm, is_write, arg); \
+}
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
 enum {
-- 
2.20.1




[Qemu-devel] [RFC PATCH v3 24/46] target/i386: introduce operand vex_v

2019-08-14 Thread Jan Bobek
This operand yields value of the VEX. field.

Signed-off-by: Jan Bobek 
---
 target/i386/translate.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/target/i386/translate.c b/target/i386/translate.c
index c918065b96..4562a097fa 100644
--- a/target/i386/translate.c
+++ b/target/i386/translate.c
@@ -4859,6 +4859,26 @@ INSNOP_FINALIZE(modrm_rm_direct)
 insnop_finalize(modrm_rm)(>rm, env, s, modrm, is_write, arg);
 }
 
+/*
+ * vex_v
+ *
+ * Operand whose value is the  field of the VEX prefix.
+ */
+typedef int insnop_arg_t(vex_v);
+typedef struct {} insnop_ctxt_t(vex_v);
+
+INSNOP_INIT(vex_v)
+{
+return !(s->prefix & PREFIX_VEX);
+}
+INSNOP_PREPARE(vex_v)
+{
+return s->vex_v;
+}
+INSNOP_FINALIZE(vex_v)
+{
+}
+
 static void gen_sse_ng(CPUX86State *env, DisasContext *s, int b)
 {
 enum {
-- 
2.20.1




  1   2   3   4   >