From 421059c6897ad5fae3bfcba8e3db0844cf80ae4e Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Mon, 16 Aug 2010 14:56:33 -0700 Subject: [PATCH] assemble: handle vex.lig AVX version 7 introduces the concept of .lig, meaning VEX.L is ignored. Signed-off-by: H. Peter Anvin --- assemble.c | 12 ++++++++---- disasm.c | 12 +++++++----- insns.pl | 6 ++++-- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/assemble.c b/assemble.c index 76cf439..3776934 100644 --- a/assemble.c +++ b/assemble.c @@ -92,7 +92,11 @@ * * VEX/XOP prefixes are followed by the sequence: * \tmm\wlp where mm is the M field; and wlp is: - * 00 0ww lpp + * 00 wwl lpp + * [l0] ll = 0 for L = 0 (.128, .lz) + * [l1] ll = 1 for L = 1 (.256) + * [lig] ll = 2 for L don't care (always assembled as 0) + * * [w0] ww = 0 for W = 0 * [w1 ] ww = 1 for W = 1 * [wig] ww = 2 for W don't care (always assembled as 0) @@ -1130,16 +1134,16 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits, errfunc(ERR_NONFATAL, "cannot use high register in vex instruction"); return -1; } - switch (ins->vex_wlp & 030) { + switch (ins->vex_wlp & 060) { case 000: case 020: ins->rex &= ~REX_W; break; - case 010: + case 040: ins->rex |= REX_W; bad32 &= ~REX_W; break; - case 030: + case 060: /* Follow REX_W */ break; } diff --git a/disasm.c b/disasm.c index 561851a..588c832 100644 --- a/disasm.c +++ b/disasm.c @@ -678,6 +678,7 @@ static int matches(const struct itemplate *t, uint8_t *data, { int vexm = *r++; int vexwlp = *r++; + ins->rex |= REX_V; if ((prefix->rex & (REX_V|REX_D|REX_P)) != REX_V) return false; @@ -685,24 +686,25 @@ static int matches(const struct itemplate *t, uint8_t *data, if ((vexm & 0x1f) != prefix->vex_m) return false; - switch (vexwlp & 030) { + switch (vexwlp & 060) { case 000: if (prefix->rex & REX_W) return false; break; - case 010: + case 020: if (!(prefix->rex & REX_W)) return false; ins->rex &= ~REX_W; break; - case 020: /* VEX.W is a don't care */ + case 040: /* VEX.W is a don't care */ ins->rex &= ~REX_W; break; - case 030: + case 060: break; } - if ((vexwlp & 007) != prefix->vex_lp) + /* The 010 bit of vexwlp is set if VEX.L is ignored */ + if ((vexwlp ^ prefix->vex_lp) & ((vexwlp & 010) ? 03 : 07)) return false; opx->segment |= SEG_RMREG; diff --git a/insns.pl b/insns.pl index 616c175..3313a6c 100755 --- a/insns.pl +++ b/insns.pl @@ -761,10 +761,12 @@ sub byte_code_compile($$) { my @subops = split(/\./, $op); shift @subops; # Drop prefix foreach $oq (@subops) { - if ($oq eq '128' || $oq eq 'l0') { + if ($oq eq '128' || $oq eq 'l0' || $oq eq 'lz') { $l = 0; } elsif ($oq eq '256' || $oq eq 'l1') { $l = 1; + } elsif ($oq eq 'lig') { + $l = 2; } elsif ($oq eq 'w0') { $w = 0; } elsif ($oq eq 'w1') { @@ -805,7 +807,7 @@ sub byte_code_compile($$) { die "$fname: $line: 'v' operand without vex.nds or vex.ndd\n"; } push(@codes, defined($oppos{'v'}) ? 0260+($oppos{'v'} & 3) : 0270, - ($c << 6)+$m, ($w << 3)+($l << 2)+$p); + ($c << 6)+$m, ($w << 4)+($l << 2)+$p); $prefix_ok = 0; } elsif ($op =~ /^\/drex([01])$/) { my $oc0 = $1; -- 2.7.4