summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2010-08-16 14:56:33 -0700
committerH. Peter Anvin <hpa@linux.intel.com>2010-08-16 14:56:33 -0700
commit421059c6897ad5fae3bfcba8e3db0844cf80ae4e (patch)
treef5ca82d1c7521badeb78d8ef7b2f2cee5d253111
parent978c2170fc22224bec916c692c627c88b53b829f (diff)
downloadnasm-421059c6897ad5fae3bfcba8e3db0844cf80ae4e.tar.gz
assemble: handle vex.lig
AVX version 7 introduces the concept of .lig, meaning VEX.L is ignored. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r--assemble.c12
-rw-r--r--disasm.c12
-rwxr-xr-xinsns.pl6
3 files changed, 19 insertions, 11 deletions
diff --git a/assemble.c b/assemble.c
index 76cf4393..37769340 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 561851ab..588c8328 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 616c1755..3313a6c2 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;