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. |
*/ |