assemble: handle vex.lig
authorH. Peter Anvin <hpa@linux.intel.com>
Mon, 16 Aug 2010 21:56:33 +0000 (14:56 -0700)
committerH. Peter Anvin <hpa@linux.intel.com>
Mon, 16 Aug 2010 21:56:33 +0000 (14:56 -0700)
AVX version 7 introduces the concept of .lig, meaning VEX.L is
ignored.

Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
assemble.c
disasm.c
insns.pl

index 76cf439..3776934 100644 (file)
  *
  * 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;
         }
index 561851a..588c832 100644 (file)
--- 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;
index 616c175..3313a6c 100755 (executable)
--- 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;