From aea53cfd9ea85250578e7640e7193444c2e0e247 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Thu, 16 Aug 2007 05:50:59 +0000 Subject: [PATCH] Add support for the following AMD instructions added in their July 2007 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 | 2 + modules/arch/x86/tests/amd200707.asm | 31 ++++ modules/arch/x86/tests/amd200707.hex | 212 +++++++++++++++++++++++++++ modules/arch/x86/x86arch.h | 6 +- modules/arch/x86/x86bc.c | 65 ++++---- modules/arch/x86/x86id.c | 123 +++++++++++----- modules/arch/x86/x86parse.gap | 8 +- 7 files changed, 367 insertions(+), 80 deletions(-) create mode 100644 modules/arch/x86/tests/amd200707.asm create mode 100644 modules/arch/x86/tests/amd200707.hex diff --git a/modules/arch/x86/tests/Makefile.inc b/modules/arch/x86/tests/Makefile.inc index ad735995..3fc08dab 100644 --- a/modules/arch/x86/tests/Makefile.inc +++ b/modules/arch/x86/tests/Makefile.inc @@ -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 index 00000000..42c26a3c --- /dev/null +++ b/modules/arch/x86/tests/amd200707.asm @@ -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 index 00000000..28b58a12 --- /dev/null +++ b/modules/arch/x86/tests/amd200707.hex @@ -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 diff --git a/modules/arch/x86/x86arch.h b/modules/arch/x86/x86arch.h index 6d2fa050..cbe26f48 100644 --- a/modules/arch/x86/x86arch.h +++ b/modules/arch/x86/x86arch.h @@ -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); diff --git a/modules/arch/x86/x86bc.c b/modules/arch/x86/x86bc.c index 6dd31110..e574f935 100644 --- a/modules/arch/x86/x86bc.c +++ b/modules/arch/x86/x86bc.c @@ -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; } diff --git a/modules/arch/x86/x86id.c b/modules/arch/x86/x86id.c index 278cb2df..807e9d45 100644 --- a/modules/arch/x86/x86id.c +++ b/modules/arch/x86/x86id.c @@ -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 && inum_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 && inum_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. */ diff --git a/modules/arch/x86/x86parse.gap b/modules/arch/x86/x86parse.gap index c9d71411..b06a930d 100644 --- a/modules/arch/x86/x86parse.gap +++ b/modules/arch/x86/x86parse.gap @@ -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 -- 2.40.0