]> granicus.if.org Git - yasm/commitdiff
Add support for the following AMD instructions added in their July 2007
authorPeter Johnson <peter@tortall.net>
Thu, 16 Aug 2007 05:50:59 +0000 (05:50 -0000)
committerPeter Johnson <peter@tortall.net>
Thu, 16 Aug 2007 05:50:59 +0000 (05:50 -0000)
documentation update:
 - LZCNT
 - POPCNT
 - EXTRQ
 - INSERTQ
 - MOVNTSD
 - MOVNTSS

This required some new tricks in the x86 code, as EXTRQ and INSERTQ have
two imm8 parameters (the first one of which goes into the EA field), and
INSERTQ has a *4* parameter version (xmm1, xmm2, imm8, imm8).  Instead of
globally making the structures 4 wide, we just special-case INSERTQ.

svn path=/trunk/yasm/; revision=1909

modules/arch/x86/tests/Makefile.inc
modules/arch/x86/tests/amd200707.asm [new file with mode: 0644]
modules/arch/x86/tests/amd200707.hex [new file with mode: 0644]
modules/arch/x86/x86arch.h
modules/arch/x86/x86bc.c
modules/arch/x86/x86id.c
modules/arch/x86/x86parse.gap

index ad735995edc20da03e019c9b4ed01daff0325f00..3fc08dab8ada979d01224bf4656e3a25fba274d7 100644 (file)
@@ -11,6 +11,8 @@ EXTRA_DIST += modules/arch/x86/tests/addrop.errwarn
 EXTRA_DIST += modules/arch/x86/tests/addrop.hex
 EXTRA_DIST += modules/arch/x86/tests/addrop-err.asm
 EXTRA_DIST += modules/arch/x86/tests/addrop-err.errwarn
+EXTRA_DIST += modules/arch/x86/tests/amd200707.asm
+EXTRA_DIST += modules/arch/x86/tests/amd200707.hex
 EXTRA_DIST += modules/arch/x86/tests/arithsmall.asm
 EXTRA_DIST += modules/arch/x86/tests/arithsmall.errwarn
 EXTRA_DIST += modules/arch/x86/tests/arithsmall.hex
diff --git a/modules/arch/x86/tests/amd200707.asm b/modules/arch/x86/tests/amd200707.asm
new file mode 100644 (file)
index 0000000..42c26a3
--- /dev/null
@@ -0,0 +1,31 @@
+bits 64
+extrq xmm0, 5, 4
+extrq xmm6, 0, 7
+extrq xmm2, xmm3
+insertq xmm0, xmm1, 5, 4
+insertq xmm5, xmm6, 0, 7
+insertq xmm2, xmm3
+movntsd [0], xmm1
+movntsd qword [0], xmm5
+movntss [0], xmm3
+movntss dword [0], xmm7
+
+lzcnt ax, bx
+lzcnt cx, word [0]
+lzcnt dx, [0]
+lzcnt eax, ebx
+lzcnt ecx, dword [0]
+lzcnt edx, [0]
+lzcnt rax, rbx
+lzcnt rcx, qword [0]
+lzcnt rdx, [0]
+
+popcnt ax, bx
+popcnt cx, word [0]
+popcnt dx, [0]
+popcnt eax, ebx
+popcnt ecx, dword [0]
+popcnt edx, [0]
+popcnt rax, rbx
+popcnt rcx, qword [0]
+popcnt rdx, [0]
diff --git a/modules/arch/x86/tests/amd200707.hex b/modules/arch/x86/tests/amd200707.hex
new file mode 100644 (file)
index 0000000..28b58a1
--- /dev/null
@@ -0,0 +1,212 @@
+66 
+0f 
+78 
+c0 
+05 
+04 
+66 
+0f 
+78 
+c6 
+00 
+07 
+66 
+0f 
+79 
+d3 
+f2 
+0f 
+78 
+c1 
+05 
+04 
+f2 
+0f 
+78 
+ee 
+00 
+07 
+f2 
+0f 
+79 
+d3 
+f2 
+0f 
+2b 
+0c 
+25 
+00 
+00 
+00 
+00 
+f2 
+0f 
+2b 
+2c 
+25 
+00 
+00 
+00 
+00 
+f3 
+0f 
+2b 
+1c 
+25 
+00 
+00 
+00 
+00 
+f3 
+0f 
+2b 
+3c 
+25 
+00 
+00 
+00 
+00 
+66 
+f3 
+0f 
+bd 
+c3 
+66 
+f3 
+0f 
+bd 
+0c 
+25 
+00 
+00 
+00 
+00 
+66 
+f3 
+0f 
+bd 
+14 
+25 
+00 
+00 
+00 
+00 
+f3 
+0f 
+bd 
+c3 
+f3 
+0f 
+bd 
+0c 
+25 
+00 
+00 
+00 
+00 
+f3 
+0f 
+bd 
+14 
+25 
+00 
+00 
+00 
+00 
+f3 
+48 
+0f 
+bd 
+c3 
+f3 
+48 
+0f 
+bd 
+0c 
+25 
+00 
+00 
+00 
+00 
+f3 
+48 
+0f 
+bd 
+14 
+25 
+00 
+00 
+00 
+00 
+66 
+f3 
+0f 
+b8 
+c3 
+66 
+f3 
+0f 
+b8 
+0c 
+25 
+00 
+00 
+00 
+00 
+66 
+f3 
+0f 
+b8 
+14 
+25 
+00 
+00 
+00 
+00 
+f3 
+0f 
+b8 
+c3 
+f3 
+0f 
+b8 
+0c 
+25 
+00 
+00 
+00 
+00 
+f3 
+0f 
+b8 
+14 
+25 
+00 
+00 
+00 
+00 
+f3 
+48 
+0f 
+b8 
+c3 
+f3 
+48 
+0f 
+b8 
+0c 
+25 
+00 
+00 
+00 
+00 
+f3 
+48 
+0f 
+b8 
+14 
+25 
+00 
+00 
+00 
+00 
index 6d2fa050bb76dee527dca98ae6e8148c14d031f0..cbe26f48541b29aa88df5943a4bca1272f4ab68b 100644 (file)
@@ -163,10 +163,10 @@ void yasm_x86__ea_init(x86_effaddr *x86_ea, unsigned int spare,
                        yasm_bytecode *precbc);
 
 void yasm_x86__ea_set_disponly(x86_effaddr *x86_ea);
-x86_effaddr *yasm_x86__ea_create_reg(unsigned long reg, unsigned char *rex,
-                                     unsigned int bits);
+x86_effaddr *yasm_x86__ea_create_reg(x86_effaddr *x86_ea, unsigned long reg,
+                                     unsigned char *rex, unsigned int bits);
 x86_effaddr *yasm_x86__ea_create_imm
-    (/*@keep@*/ yasm_expr *imm, unsigned int im_len);
+    (x86_effaddr *x86_ea, /*@keep@*/ yasm_expr *imm, unsigned int im_len);
 yasm_effaddr *yasm_x86__ea_create_expr(yasm_arch *arch,
                                        /*@keep@*/ yasm_expr *e);
 void yasm_x86__ea_destroy(yasm_effaddr *ea);
index 6dd31110993b46b67c542e0adb3ac128c502511c..e574f9353a80a599ef566f192beef07b2cf1ad60 100644 (file)
@@ -172,17 +172,10 @@ yasm_x86__ea_set_disponly(x86_effaddr *x86_ea)
     x86_ea->need_sib = 0;
 }
 
-x86_effaddr *
-yasm_x86__ea_create_reg(unsigned long reg, unsigned char *rex,
-                        unsigned int bits)
+static x86_effaddr *
+ea_create(void)
 {
-    x86_effaddr *x86_ea;
-    unsigned char rm;
-
-    if (yasm_x86__set_rex_from_reg(rex, &rm, reg, bits, X86_REX_B))
-        return NULL;
-
-    x86_ea = yasm_xmalloc(sizeof(x86_effaddr));
+    x86_effaddr *x86_ea = yasm_xmalloc(sizeof(x86_effaddr));
 
     yasm_value_initialize(&x86_ea->ea.disp, NULL, 0);
     x86_ea->ea.need_nonzero_len = 0;
@@ -190,9 +183,9 @@ yasm_x86__ea_create_reg(unsigned long reg, unsigned char *rex,
     x86_ea->ea.nosplit = 0;
     x86_ea->ea.strong = 0;
     x86_ea->ea.segreg = 0;
-    x86_ea->modrm = 0xC0 | rm;  /* Mod=11, R/M=Reg, Reg=0 */
-    x86_ea->valid_modrm = 1;
-    x86_ea->need_modrm = 1;
+    x86_ea->modrm = 0;
+    x86_ea->valid_modrm = 0;
+    x86_ea->need_modrm = 0;
     x86_ea->sib = 0;
     x86_ea->valid_sib = 0;
     x86_ea->need_sib = 0;
@@ -200,13 +193,31 @@ yasm_x86__ea_create_reg(unsigned long reg, unsigned char *rex,
     return x86_ea;
 }
 
+x86_effaddr *
+yasm_x86__ea_create_reg(x86_effaddr *x86_ea, unsigned long reg,
+                        unsigned char *rex, unsigned int bits)
+{
+    unsigned char rm;
+
+    if (yasm_x86__set_rex_from_reg(rex, &rm, reg, bits, X86_REX_B))
+        return NULL;
+
+    if (!x86_ea)
+        x86_ea = ea_create();
+    x86_ea->modrm = 0xC0 | rm;  /* Mod=11, R/M=Reg, Reg=0 */
+    x86_ea->valid_modrm = 1;
+    x86_ea->need_modrm = 1;
+
+    return x86_ea;
+}
+
 yasm_effaddr *
 yasm_x86__ea_create_expr(yasm_arch *arch, yasm_expr *e)
 {
     yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;
     x86_effaddr *x86_ea;
 
-    x86_ea = yasm_xmalloc(sizeof(x86_effaddr));
+    x86_ea = ea_create();
 
     if (arch_x86->parser == X86_PARSER_GAS) {
         /* Need to change foo+rip into foo wrt rip.
@@ -224,16 +235,8 @@ yasm_x86__ea_create_expr(yasm_arch *arch, yasm_expr *e)
         }
     }
     yasm_value_initialize(&x86_ea->ea.disp, e, 0);
-    x86_ea->ea.need_nonzero_len = 0;
     x86_ea->ea.need_disp = 1;
-    x86_ea->ea.nosplit = 0;
-    x86_ea->ea.strong = 0;
-    x86_ea->ea.segreg = 0;
-    x86_ea->modrm = 0;
-    x86_ea->valid_modrm = 0;
     x86_ea->need_modrm = 1;
-    x86_ea->sib = 0;
-    x86_ea->valid_sib = 0;
     /* We won't know whether we need an SIB until we know more about expr and
      * the BITS/address override setting.
      */
@@ -244,23 +247,13 @@ yasm_x86__ea_create_expr(yasm_arch *arch, yasm_expr *e)
 
 /*@-compmempass@*/
 x86_effaddr *
-yasm_x86__ea_create_imm(yasm_expr *imm, unsigned int im_len)
+yasm_x86__ea_create_imm(x86_effaddr *x86_ea, yasm_expr *imm,
+                        unsigned int im_len)
 {
-    x86_effaddr *x86_ea;
-
-    x86_ea = yasm_xmalloc(sizeof(x86_effaddr));
-
+    if (!x86_ea)
+        x86_ea = ea_create();
     yasm_value_initialize(&x86_ea->ea.disp, imm, im_len);
     x86_ea->ea.need_disp = 1;
-    x86_ea->ea.nosplit = 0;
-    x86_ea->ea.strong = 0;
-    x86_ea->ea.segreg = 0;
-    x86_ea->modrm = 0;
-    x86_ea->valid_modrm = 0;
-    x86_ea->need_modrm = 0;
-    x86_ea->sib = 0;
-    x86_ea->valid_sib = 0;
-    x86_ea->need_sib = 0;
 
     return x86_ea;
 }
index 278cb2dfc91a1b6f2e3d10415feff88bf2a4ad9a..807e9d451f9b2fc55c98f2daa52dec99c0a2dddd 100644 (file)
@@ -2210,15 +2210,43 @@ static const x86_insn_info sse4m16_insn[] = {
       {OPT_SIMDReg|OPS_128|OPA_Spare, OPT_SIMDReg|OPS_128|OPA_EA, 0} }
 };
 
-static const x86_insn_info popcnt_insn[] = {
-    { CPU_SSE42, MOD_GasSufW, 16, 0, 0xF3, 2, {0x0F, 0xB8, 0}, 0, 2,
+static const x86_insn_info cnt_insn[] = {
+    { CPU_SSE42, MOD_Op1Add|MOD_GasSufW, 16, 0, 0xF3, 2, {0x0F, 0x00, 0}, 0, 2,
       {OPT_Reg|OPS_16|OPA_Spare, OPT_RM|OPS_16|OPS_Relaxed|OPA_EA, 0} },
-    { CPU_SSE42, MOD_GasSufL, 32, 0, 0xF3, 2, {0x0F, 0xB8, 0}, 0, 2,
+    { CPU_SSE42, MOD_Op1Add|MOD_GasSufL, 32, 0, 0xF3, 2, {0x0F, 0x00, 0}, 0, 2,
       {OPT_Reg|OPS_32|OPA_Spare, OPT_RM|OPS_32|OPS_Relaxed|OPA_EA, 0} },
-    { CPU_SSE42|CPU_64, MOD_GasSufQ, 64, 0, 0xF3, 2, {0x0F, 0xB8, 0}, 0, 2,
+    { CPU_SSE42|CPU_64, MOD_Op1Add|MOD_GasSufQ, 64, 0, 0xF3, 2,
+      {0x0F, 0x00, 0}, 0, 2,
       {OPT_Reg|OPS_64|OPA_Spare, OPT_RM|OPS_64|OPS_Relaxed|OPA_EA, 0} }
 };
 
+static const x86_insn_info extrq_insn[] = {
+    { CPU_SSE41, 0, 0, 0, 0x66, 2, {0x0F, 0x78, 0}, 0, 3,
+      {OPT_SIMDReg|OPS_128|OPA_EA, OPT_Imm|OPS_8|OPS_Relaxed|OPA_EA,
+       OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm} },
+    { CPU_SSE41, 0, 0, 0, 0x66, 2, {0x0F, 0x79, 0}, 0, 2,
+      {OPT_SIMDReg|OPS_128|OPA_Spare, OPT_SIMDReg|OPS_128|OPA_EA, 0} }
+};
+
+static const unsigned long insertq_4operands[] =
+    {OPT_SIMDReg|OPS_128|OPA_Spare, OPT_SIMDReg|OPS_128|OPA_EA,
+     OPT_Imm|OPS_8|OPS_Relaxed|OPA_EA, OPT_Imm|OPS_8|OPS_Relaxed|OPA_Imm};
+static const x86_insn_info insertq_insn[] = {
+    { CPU_SSE41, 0, 0, 0, 0xF2, 2, {0x0F, 0x78, 0}, 0, 4, {0, 0, 0} },
+    { CPU_SSE41, 0, 0, 0, 0xF2, 2, {0x0F, 0x79, 0}, 0, 2,
+      {OPT_SIMDReg|OPS_128|OPA_Spare, OPT_SIMDReg|OPS_128|OPA_EA, 0} }
+};
+
+static const x86_insn_info movntsd_insn[] = {
+    { CPU_SSE41, 0, 0, 0, 0xF2, 2, {0x0F, 0x2B, 0}, 0, 2,
+      {OPT_Mem|OPS_64|OPS_Relaxed|OPA_EA, OPT_SIMDReg|OPS_128|OPA_Spare, 0} }
+};
+
+static const x86_insn_info movntss_insn[] = {
+    { CPU_SSE41, 0, 0, 0, 0xF3, 2, {0x0F, 0x2B, 0}, 0, 2,
+      {OPT_Mem|OPS_32|OPS_Relaxed|OPA_EA, OPT_SIMDReg|OPS_128|OPA_Spare, 0} }
+};
+
 /* AMD 3DNow! instructions */
 static const x86_insn_info now3d_insn[] = {
     { CPU_3DNow, MOD_Imm8, 0, 0, 0, 2, {0x0F, 0x0F, 0}, 0, 2,
@@ -2525,6 +2553,7 @@ x86_find_match(x86_id_insn *id_insn, yasm_insn_operand **ops,
      */
     for (; num_info>0 && !found; num_info--, info++) {
         yasm_insn_operand *op, **use_ops;
+        const unsigned long *info_ops = info->operands;
         unsigned long icpu;
         unsigned int size;
         int mismatch = 0;
@@ -2570,11 +2599,15 @@ x86_find_match(x86_id_insn *id_insn, yasm_insn_operand **ops,
             break;
         }
 
+        /* 4-operand special case for insertq */
+        if (info->num_operands > 3)
+            info_ops = insertq_4operands;
+
         /* Match each operand type and size */
         for (i = 0, op = use_ops[0]; op && i<info->num_operands && !mismatch;
              op = use_ops[++i]) {
             /* Check operand type */
-            switch ((int)(info->operands[i] & OPT_MASK)) {
+            switch ((int)(info_ops[i] & OPT_MASK)) {
                 case OPT_Imm:
                     if (op->type != YASM_INSN__OPERAND_IMM)
                         mismatch = 1;
@@ -2649,40 +2682,40 @@ x86_find_match(x86_id_insn *id_insn, yasm_insn_operand **ops,
                     break;
                 case OPT_Areg:
                     if (op->type != YASM_INSN__OPERAND_REG ||
-                        ((info->operands[i] & OPS_MASK) == OPS_8 &&
+                        ((info_ops[i] & OPS_MASK) == OPS_8 &&
                          op->data.reg != (X86_REG8 | 0) &&
                          op->data.reg != (X86_REG8X | 0)) ||
-                        ((info->operands[i] & OPS_MASK) == OPS_16 &&
+                        ((info_ops[i] & OPS_MASK) == OPS_16 &&
                          op->data.reg != (X86_REG16 | 0)) ||
-                        ((info->operands[i] & OPS_MASK) == OPS_32 &&
+                        ((info_ops[i] & OPS_MASK) == OPS_32 &&
                          op->data.reg != (X86_REG32 | 0)) ||
-                        ((info->operands[i] & OPS_MASK) == OPS_64 &&
+                        ((info_ops[i] & OPS_MASK) == OPS_64 &&
                          op->data.reg != (X86_REG64 | 0)))
                         mismatch = 1;
                     break;
                 case OPT_Creg:
                     if (op->type != YASM_INSN__OPERAND_REG ||
-                        ((info->operands[i] & OPS_MASK) == OPS_8 &&
+                        ((info_ops[i] & OPS_MASK) == OPS_8 &&
                          op->data.reg != (X86_REG8 | 1) &&
                          op->data.reg != (X86_REG8X | 1)) ||
-                        ((info->operands[i] & OPS_MASK) == OPS_16 &&
+                        ((info_ops[i] & OPS_MASK) == OPS_16 &&
                          op->data.reg != (X86_REG16 | 1)) ||
-                        ((info->operands[i] & OPS_MASK) == OPS_32 &&
+                        ((info_ops[i] & OPS_MASK) == OPS_32 &&
                          op->data.reg != (X86_REG32 | 1)) ||
-                        ((info->operands[i] & OPS_MASK) == OPS_64 &&
+                        ((info_ops[i] & OPS_MASK) == OPS_64 &&
                          op->data.reg != (X86_REG64 | 1)))
                         mismatch = 1;
                     break;
                 case OPT_Dreg:
                     if (op->type != YASM_INSN__OPERAND_REG ||
-                        ((info->operands[i] & OPS_MASK) == OPS_8 &&
+                        ((info_ops[i] & OPS_MASK) == OPS_8 &&
                          op->data.reg != (X86_REG8 | 2) &&
                          op->data.reg != (X86_REG8X | 2)) ||
-                        ((info->operands[i] & OPS_MASK) == OPS_16 &&
+                        ((info_ops[i] & OPS_MASK) == OPS_16 &&
                          op->data.reg != (X86_REG16 | 2)) ||
-                        ((info->operands[i] & OPS_MASK) == OPS_32 &&
+                        ((info_ops[i] & OPS_MASK) == OPS_32 &&
                          op->data.reg != (X86_REG32 | 2)) ||
-                        ((info->operands[i] & OPS_MASK) == OPS_64 &&
+                        ((info_ops[i] & OPS_MASK) == OPS_64 &&
                          op->data.reg != (X86_REG64 | 2)))
                         mismatch = 1;
                     break;
@@ -2773,7 +2806,7 @@ x86_find_match(x86_id_insn *id_insn, yasm_insn_operand **ops,
                 break;
 
             /* Check operand size */
-            size = size_lookup[(info->operands[i] & OPS_MASK)>>OPS_SHIFT];
+            size = size_lookup[(info_ops[i] & OPS_MASK)>>OPS_SHIFT];
             if (suffix != 0) {
                 /* Require relaxed operands for GAS mode (don't allow
                  * per-operand sizing).
@@ -2782,11 +2815,11 @@ x86_find_match(x86_id_insn *id_insn, yasm_insn_operand **ops,
                     /* Register size must exactly match */
                     if (yasm_x86__get_reg_size(op->data.reg) != size)
                         mismatch = 1;
-                } else if (((info->operands[i] & OPT_MASK) == OPT_Imm
-                            || (info->operands[i] & OPT_MASK) == OPT_ImmNotSegOff
-                            || (info->operands[i] & OPT_MASK) == OPT_Imm1)
-                    && (info->operands[i] & OPS_RMASK) != OPS_Relaxed
-                    && (info->operands[i] & OPA_MASK) != OPA_JmpRel)
+                } else if (((info_ops[i] & OPT_MASK) == OPT_Imm
+                            || (info_ops[i] & OPT_MASK) == OPT_ImmNotSegOff
+                            || (info_ops[i] & OPT_MASK) == OPT_Imm1)
+                    && (info_ops[i] & OPS_RMASK) != OPS_Relaxed
+                    && (info_ops[i] & OPA_MASK) != OPA_JmpRel)
                     mismatch = 1;
             } else {
                 if (op->type == YASM_INSN__OPERAND_REG && op->size == 0) {
@@ -2800,7 +2833,7 @@ x86_find_match(x86_id_insn *id_insn, yasm_insn_operand **ops,
                     if ((bypass == 1 && i == 0) || (bypass == 2 && i == 1)
                         || (bypass == 3 && i == 3))
                         ;
-                    else if ((info->operands[i] & OPS_RMASK) == OPS_Relaxed) {
+                    else if ((info_ops[i] & OPS_RMASK) == OPS_Relaxed) {
                         /* Relaxed checking */
                         if (size != 0 && op->size != size && op->size != 0)
                             mismatch = 1;
@@ -2817,7 +2850,7 @@ x86_find_match(x86_id_insn *id_insn, yasm_insn_operand **ops,
 
             /* Check for 64-bit effective address size in NASM mode */
             if (suffix == 0 && op->type == YASM_INSN__OPERAND_MEMORY) {
-                if ((info->operands[i] & OPEAS_MASK) == OPEAS_64) {
+                if ((info_ops[i] & OPEAS_MASK) == OPEAS_64) {
                     if (op->data.ea->disp.size != 64)
                         mismatch = 1;
                 } else if (op->data.ea->disp.size == 64)
@@ -2828,7 +2861,7 @@ x86_find_match(x86_id_insn *id_insn, yasm_insn_operand **ops,
                 break;
 
             /* Check target modifier */
-            switch ((int)(info->operands[i] & OPTM_MASK)) {
+            switch ((int)(info_ops[i] & OPTM_MASK)) {
                 case OPTM_None:
                     if (op->targetmod != 0)
                         mismatch = 1;
@@ -2944,7 +2977,9 @@ x86_id_insn_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
     /* Build local array of operands from list, since we know we have a max
      * of 3 operands.
      */
-    if (id_insn->insn.num_operands > 3) {
+    if (id_insn->insn.num_operands == 4 && info == insertq_insn)
+        ;
+    else if (id_insn->insn.num_operands > 3) {
         yasm_error_set(YASM_ERROR_TYPE, N_("too many operands"));
         return;
     }
@@ -3085,15 +3120,20 @@ x86_id_insn_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
     /* Go through operands and assign */
     if (id_insn->insn.num_operands > 0) {
         yasm_insn_operand **use_ops = ops;
+        const unsigned long *info_ops = info->operands;
 
         /* Use reversed operands in GAS mode if not otherwise specified */
         if (id_insn->parser == X86_PARSER_GAS
             && !(info->modifiers & MOD_GasNoRev))
             use_ops = rev_ops;
 
+        /* 4-operand special case for insertq */
+        if (info->num_operands > 3)
+            info_ops = insertq_4operands;
+
         for (i = 0, op = use_ops[0]; op && i<info->num_operands;
              op = use_ops[++i]) {
-            switch ((int)(info->operands[i] & OPA_MASK)) {
+            switch ((int)(info_ops[i] & OPA_MASK)) {
                 case OPA_None:
                     /* Throw away the operand contents */
                     switch (op->type) {
@@ -3111,23 +3151,25 @@ x86_id_insn_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
                 case OPA_EA:
                     switch (op->type) {
                         case YASM_INSN__OPERAND_REG:
-                            insn->x86_ea = yasm_x86__ea_create_reg(
-                                (unsigned long)op->data.reg, &insn->rex,
-                                mode_bits);
+                            insn->x86_ea =
+                                yasm_x86__ea_create_reg(insn->x86_ea,
+                                    (unsigned long)op->data.reg, &insn->rex,
+                                    mode_bits);
                             break;
                         case YASM_INSN__OPERAND_SEGREG:
                             yasm_internal_error(
                                 N_("invalid operand conversion"));
                         case YASM_INSN__OPERAND_MEMORY:
                             insn->x86_ea = (x86_effaddr *)op->data.ea;
-                            if ((info->operands[i] & OPT_MASK) == OPT_MemOffs)
+                            if ((info_ops[i] & OPT_MASK) == OPT_MemOffs)
                                 /* Special-case for MOV MemOffs instruction */
                                 yasm_x86__ea_set_disponly(insn->x86_ea);
                             break;
                         case YASM_INSN__OPERAND_IMM:
                             insn->x86_ea =
-                                yasm_x86__ea_create_imm(op->data.val,
-                                    size_lookup[(info->operands[i] &
+                                yasm_x86__ea_create_imm(insn->x86_ea,
+                                    op->data.val,
+                                    size_lookup[(info_ops[i] &
                                                 OPS_MASK)>>OPS_SHIFT]);
                             break;
                     }
@@ -3135,7 +3177,7 @@ x86_id_insn_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
                 case OPA_Imm:
                     if (op->type == YASM_INSN__OPERAND_IMM) {
                         imm = op->data.val;
-                        im_len = size_lookup[(info->operands[i] &
+                        im_len = size_lookup[(info_ops[i] &
                                               OPS_MASK)>>OPS_SHIFT];
                     } else
                         yasm_internal_error(N_("invalid operand conversion"));
@@ -3143,7 +3185,7 @@ x86_id_insn_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
                 case OPA_SImm:
                     if (op->type == YASM_INSN__OPERAND_IMM) {
                         imm = op->data.val;
-                        im_len = size_lookup[(info->operands[i] &
+                        im_len = size_lookup[(info_ops[i] &
                                               OPS_MASK)>>OPS_SHIFT];
                         im_sign = 1;
                     } else
@@ -3182,7 +3224,8 @@ x86_id_insn_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
                 case OPA_SpareEA:
                     if (op->type == YASM_INSN__OPERAND_REG) {
                         insn->x86_ea =
-                            yasm_x86__ea_create_reg((unsigned long)op->data.reg,
+                            yasm_x86__ea_create_reg(insn->x86_ea,
+                                                    (unsigned long)op->data.reg,
                                                     &insn->rex, mode_bits);
                         if (!insn->x86_ea ||
                             yasm_x86__set_rex_from_reg(&insn->rex, &spare,
@@ -3223,10 +3266,10 @@ x86_id_insn_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
                     yasm_internal_error(N_("unknown operand action"));
             }
 
-            if ((info->operands[i] & OPS_MASK) == OPS_BITS)
+            if ((info_ops[i] & OPS_MASK) == OPS_BITS)
                 insn->common.opersize = (unsigned char)mode_bits;
 
-            switch ((int)(info->operands[i] & OPAP_MASK)) {
+            switch ((int)(info_ops[i] & OPAP_MASK)) {
                 case OPAP_None:
                     break;
                 case OPAP_SImm8:
@@ -3326,7 +3369,7 @@ x86_id_insn_finalize(yasm_bytecode *bc, yasm_bytecode *prev_bc)
                 /* Build ModRM EA - CAUTION: this depends on
                  * opcode 0 being a mov instruction!
                  */
-                insn->x86_ea = yasm_x86__ea_create_reg(
+                insn->x86_ea = yasm_x86__ea_create_reg(insn->x86_ea,
                     (unsigned long)insn->opcode.opcode[0]-0xB8, &rex_temp, 64);
 
                 /* Make the imm32s form permanent. */
index c9d714111c677fc05eefb4052922bc0b22b4e7b4..b06a930d68f51455d747cc207e1a50a5be851a7f 100644 (file)
@@ -809,12 +809,17 @@ INSN      -       pmovzxwq NONE   sse4m32         0x34    CPU_SSE41
 INSN   -       pmovzxdq NONE   sse4m64         0x35    CPU_SSE41
 INSN   -       pmuldq  NONE    sse4            0x28    CPU_SSE41
 INSN   -       pmulld  NONE    sse4            0x40    CPU_SSE41
-INSN   -       popcnt  "wlq"   popcnt          0       CPU_SSE42
+INSN   -       popcnt  "wlq"   cnt             0xB8    CPU_SSE42
 INSN   -       ptest   NONE    sse4            0x17    CPU_SSE41
 INSN   -       roundpd NONE    sse4imm         0x09    CPU_SSE41
 INSN   -       roundps NONE    sse4imm         0x08    CPU_SSE41
 INSN   -       roundsd NONE    sse4imm         0x0B    CPU_SSE41
 INSN   -       roundss NONE    sse4imm         0x0A    CPU_SSE41
+# AMD SSE4.1 instructions
+INSN   -       extrq   NONE    extrq           0       CPU_SSE41
+INSN   -       insertq NONE    insertq         0       CPU_SSE41
+INSN   -       movntsd NONE    movntsd         0       CPU_SSE41
+INSN   -       movntss NONE    movntss         0       CPU_SSE41
 # AMD 3DNow! instructions
 INSN   -       prefetch NONE   twobytemem  0x000F0D    CPU_3DNow
 INSN   -       prefetchw NONE  twobytemem  0x010F0D    CPU_3DNow
@@ -846,6 +851,7 @@ INSN        -       pswapd  NONE    now3d   0xBB            CPU_Athlon|CPU_3DNow
 # AMD extensions
 INSN   -       syscall NONE    twobyte 0x0F05          CPU_686|CPU_AMD
 INSN   -       sysret  "lq"    twobyte 0x0F07          CPU_686|CPU_AMD|CPU_Priv
+INSN   -       lzcnt   "wlq"   cnt             0xBD    CPU_686|CPU_AMD
 # AMD x86-64 extensions
 INSN   -       swapgs  NONE    threebyte   0x0F01F8    CPU_Hammer|CPU_64
 INSN   -       rdtscp  NONE    threebyte   0x0F01F9    CPU_686|CPU_AMD|CPU_Priv