| Index: third_party/yasm/patched-yasm/modules/arch/x86/x86id.c
|
| ===================================================================
|
| --- third_party/yasm/patched-yasm/modules/arch/x86/x86id.c (revision 165590)
|
| +++ third_party/yasm/patched-yasm/modules/arch/x86/x86id.c (working copy)
|
| @@ -26,7 +26,6 @@
|
| */
|
| #include <ctype.h>
|
| #include <util.h>
|
| -RCSID("$Id: x86id.c 2279 2010-01-19 07:57:43Z peter $");
|
|
|
| #include <libyasm.h>
|
| #include <libyasm/phash.h>
|
| @@ -111,7 +110,11 @@
|
| */
|
| OPT_MemrAX = 25,
|
| /* EAX memory operand only (EA) [special case for SVM skinit opcode] */
|
| - OPT_MemEAX = 26
|
| + OPT_MemEAX = 26,
|
| + /* XMM VSIB memory operand */
|
| + OPT_MemXMMIndex = 27,
|
| + /* YMM VSIB memory operand */
|
| + OPT_MemYMMIndex = 28
|
| };
|
|
|
| enum x86_operand_size {
|
| @@ -347,6 +350,37 @@
|
|
|
| #include "x86insns.c"
|
|
|
| +/* Looks for the first SIMD register match for the purposes of VSIB matching.
|
| + * Full legality checking is performed in EA code.
|
| + */
|
| +static int
|
| +x86_expr_contains_simd_cb(const yasm_expr__item *ei, void *d)
|
| +{
|
| + int ymm = *((int *)d);
|
| + if (ei->type != YASM_EXPR_REG)
|
| + return 0;
|
| + switch ((x86_expritem_reg_size)(ei->data.reg & ~0xFUL)) {
|
| + case X86_XMMREG:
|
| + if (!ymm)
|
| + return 1;
|
| + break;
|
| + case X86_YMMREG:
|
| + if (ymm)
|
| + return 1;
|
| + break;
|
| + default:
|
| + break;
|
| + }
|
| + return 0;
|
| +}
|
| +
|
| +static int
|
| +x86_expr_contains_simd(const yasm_expr *e, int ymm)
|
| +{
|
| + return yasm_expr__traverse_leaves_in_const(e, &ymm,
|
| + x86_expr_contains_simd_cb);
|
| +}
|
| +
|
| static void
|
| x86_finalize_common(x86_common *common, const x86_insn_info *info,
|
| unsigned int mode_bits)
|
| @@ -851,6 +885,16 @@
|
| mismatch = 1;
|
| break;
|
| }
|
| + case OPT_MemXMMIndex:
|
| + if (op->type != YASM_INSN__OPERAND_MEMORY ||
|
| + !x86_expr_contains_simd(op->data.ea->disp.abs, 0))
|
| + mismatch = 1;
|
| + break;
|
| + case OPT_MemYMMIndex:
|
| + if (op->type != YASM_INSN__OPERAND_MEMORY ||
|
| + !x86_expr_contains_simd(op->data.ea->disp.abs, 1))
|
| + mismatch = 1;
|
| + break;
|
| default:
|
| yasm_internal_error(N_("invalid operand type"));
|
| }
|
| @@ -1231,12 +1275,20 @@
|
| if (info_ops[i].type == OPT_MemOffs)
|
| /* Special-case for MOV MemOffs instruction */
|
| yasm_x86__ea_set_disponly(insn->x86_ea);
|
| - else if (id_insn->default_rel &&
|
| - !op->data.ea->not_pc_rel &&
|
| - op->data.ea->segreg != 0x6404 &&
|
| - op->data.ea->segreg != 0x6505 &&
|
| - !yasm_expr__contains(
|
| - op->data.ea->disp.abs, YASM_EXPR_REG))
|
| + else if (info_ops[i].type == OPT_MemXMMIndex) {
|
| + /* Remember VSIB mode */
|
| + insn->x86_ea->vsib_mode = 1;
|
| + insn->x86_ea->need_sib = 1;
|
| + } else if (info_ops[i].type == OPT_MemYMMIndex) {
|
| + /* Remember VSIB mode */
|
| + insn->x86_ea->vsib_mode = 2;
|
| + insn->x86_ea->need_sib = 1;
|
| + } else if (id_insn->default_rel &&
|
| + !op->data.ea->not_pc_rel &&
|
| + op->data.ea->segreg != 0x6404 &&
|
| + op->data.ea->segreg != 0x6505 &&
|
| + !yasm_expr__contains(
|
| + op->data.ea->disp.abs, YASM_EXPR_REG))
|
| /* Enable default PC-rel if no regs and segreg
|
| * is not FS or GS.
|
| */
|
|
|