Remove support for DREX encoding
authorH. Peter Anvin <hpa@linux.intel.com>
Thu, 7 Jul 2011 23:58:22 +0000 (16:58 -0700)
committerH. Peter Anvin <hpa@linux.intel.com>
Thu, 7 Jul 2011 23:58:22 +0000 (16:58 -0700)
The DREX encoding never hit production silicon, and has been replaced
by VEX/XOP encoding, so remove support for it.

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

index ed5ef8e..17def3a 100644 (file)
  * \150..\153    - an immediate dword or signed byte for operand 0..3
  * \154..\157    - or 2 (s-field) into opcode byte if operand 0..3
  *                  is a signed byte rather than a dword.  Opcode byte follows.
- * \160..\163    - this instruction uses DREX rather than REX, with the
- *                 OC0 field set to 0, and the dest field taken from
- *                 operand 0..3.
- * \164..\167    - this instruction uses DREX rather than REX, with the
- *                 OC0 field set to 1, and the dest field taken from
- *                 operand 0..3.
- * \171          - placement of DREX suffix in the absence of an EA
  * \172\ab       - the register number from operand a in bits 7..4, with
  *                 the 4-bit immediate from operand b in bits 3..0.
  * \173\xab      - the register number from operand a in bits 7..4, with
@@ -908,21 +901,6 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
             length++;
             break;
 
-        case4(0160):
-            length++;
-            ins->rex |= REX_D;
-            ins->drexdst = regval(opx);
-            break;
-
-        case4(0164):
-            length++;
-            ins->rex |= REX_D|REX_OC;
-            ins->drexdst = regval(opx);
-            break;
-
-        case 0171:
-            break;
-
         case 0172:
         case 0173:
         case 0174:
@@ -940,14 +918,14 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
 
         case4(0260):
             ins->rex |= REX_V;
-            ins->drexdst = regval(opx);
+            ins->vexreg = regval(opx);
             ins->vex_cm = *codes++;
             ins->vex_wlp = *codes++;
             break;
 
         case 0270:
             ins->rex |= REX_V;
-            ins->drexdst = 0;
+            ins->vexreg = 0;
             ins->vex_cm = *codes++;
             ins->vex_wlp = *codes++;
             break;
@@ -1178,7 +1156,7 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
             break;
         }
 
-        if (bits != 64 && ((ins->rex & bad32) || ins->drexdst > 7)) {
+        if (bits != 64 && ((ins->rex & bad32) || ins->vexreg > 7)) {
             errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
             return -1;
         }
@@ -1186,17 +1164,6 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
             length += 3;
         else
             length += 2;
-    } else if (ins->rex & REX_D) {
-        if (ins->rex & REX_H) {
-            errfunc(ERR_NONFATAL, "cannot use high register in drex instruction");
-            return -1;
-        }
-        if (bits != 64 && ((ins->rex & (REX_R|REX_W|REX_X|REX_B)) ||
-                           ins->drexdst > 7)) {
-            errfunc(ERR_NONFATAL, "invalid operands in non-64-bit mode");
-            return -1;
-        }
-        length++;
     } else if (ins->rex & REX_REAL) {
         if (ins->rex & REX_H) {
             errfunc(ERR_NONFATAL, "cannot use high register in rex instruction");
@@ -1219,7 +1186,7 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
 }
 
 #define EMIT_REX()                                                              \
-    if (!(ins->rex & (REX_D|REX_V)) && (ins->rex & REX_REAL) && (bits == 64)) { \
+    if (!(ins->rex & REX_V) && (ins->rex & REX_REAL) && (bits == 64)) { \
         ins->rex = (ins->rex & REX_REAL)|REX_P;                                 \
         out(offset, segment, &ins->rex, OUT_RAWDATA, 1, NO_SEG, NO_SEG);        \
         ins->rex = 0;                                                           \
@@ -1499,20 +1466,6 @@ static void gencode(int32_t segment, int64_t offset, int bits,
             offset++;
             break;
 
-        case4(0160):
-        case4(0164):
-            break;
-
-        case 0171:
-            bytes[0] =
-                (ins->drexdst << 4) |
-                (ins->rex & REX_OC ? 0x08 : 0) |
-                (ins->rex & (REX_R|REX_X|REX_B));
-            ins->rex = 0;
-            out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
-            offset++;
-            break;
-
         case 0172:
             c = *codes++;
             opx = &ins->oprs[c >> 3];
@@ -1588,13 +1541,13 @@ static void gencode(int32_t segment, int64_t offset, int bits,
                 bytes[0] = (ins->vex_cm >> 6) ? 0x8f : 0xc4;
                 bytes[1] = (ins->vex_cm & 31) | ((~ins->rex & 7) << 5);
                 bytes[2] = ((ins->rex & REX_W) << (7-3)) |
-                    ((~ins->drexdst & 15)<< 3) | (ins->vex_wlp & 07);
+                    ((~ins->vexreg & 15)<< 3) | (ins->vex_wlp & 07);
                 out(offset, segment, &bytes, OUT_RAWDATA, 3, NO_SEG, NO_SEG);
                 offset += 3;
             } else {
                 bytes[0] = 0xc5;
                 bytes[1] = ((~ins->rex & REX_R) << (7-2)) |
-                    ((~ins->drexdst & 15) << 3) | (ins->vex_wlp & 07);
+                    ((~ins->vexreg & 15) << 3) | (ins->vex_wlp & 07);
                 out(offset, segment, &bytes, OUT_RAWDATA, 2, NO_SEG, NO_SEG);
                 offset += 2;
             }
@@ -1858,14 +1811,6 @@ static void gencode(int32_t segment, int64_t offset, int bits,
                 if (ea_data.sib_present)
                     *p++ = ea_data.sib;
 
-                /* DREX suffixes come between the SIB and the displacement */
-                if (ins->rex & REX_D) {
-                    *p++ = (ins->drexdst << 4) |
-                           (ins->rex & REX_OC ? 0x08 : 0) |
-                           (ins->rex & (REX_R|REX_X|REX_B));
-                    ins->rex = 0;
-                }
-
                 s = p - bytes;
                 out(offset, segment, bytes, OUT_RAWDATA, s, NO_SEG, NO_SEG);
 
index 5943966..5c9d6db 100644 (file)
--- a/disasm.c
+++ b/disasm.c
@@ -197,24 +197,6 @@ static enum reg_enum whichreg(opflags_t regflags, int regval, int rex)
 }
 
 /*
- * Process a DREX suffix
- */
-static uint8_t *do_drex(uint8_t *data, insn *ins)
-{
-    uint8_t drex = *data++;
-    operand *dst = &ins->oprs[ins->drexdst];
-
-    if ((drex & 8) != ((ins->rex & REX_OC) ? 8 : 0))
-       return NULL;    /* OC0 mismatch */
-    ins->rex = (ins->rex & ~7) | (drex & 7);
-
-    dst->segment = SEG_RMREG;
-    dst->basereg = drex >> 4;
-    return data;
-}
-
-
-/*
  * Process an effective address (ModRM) specification.
  */
 static uint8_t *do_ea(uint8_t *data, int modrm, int asize,
@@ -231,11 +213,6 @@ static uint8_t *do_ea(uint8_t *data, int modrm, int asize,
     if (mod != 3 && asize != 16 && rm == 4)
        sib = *data++;
 
-    if (ins->rex & REX_D) {
-       data = do_drex(data, ins);
-       if (!data)
-           return NULL;
-    }
     rex = ins->rex;
 
     if (mod == 3) {             /* pure register version */
@@ -621,22 +598,6 @@ static int matches(const struct itemplate *t, uint8_t *data,
            }
            break;
 
-       case4(0160):
-           ins->rex |= REX_D;
-           ins->drexdst = op1;
-           break;
-
-       case4(0164):
-           ins->rex |= REX_D|REX_OC;
-           ins->drexdst = op1;
-           break;
-
-       case 0171:
-           data = do_drex(data, ins);
-           if (!data)
-               return false;
-           break;
-
        case 0172:
        {
            uint8_t ximm = *data++;
@@ -705,7 +666,7 @@ static int matches(const struct itemplate *t, uint8_t *data,
            int vexwlp = *r++;
 
            ins->rex |= REX_V;
-           if ((prefix->rex & (REX_V|REX_D|REX_P)) != REX_V)
+           if ((prefix->rex & (REX_V|REX_P)) != REX_V)
                return false;
 
            if ((vexm & 0x1f) != prefix->vex_m)
@@ -945,8 +906,8 @@ static int matches(const struct itemplate *t, uint8_t *data,
     if (!vex_ok && (ins->rex & REX_V))
        return false;
 
-    /* REX cannot be combined with DREX or VEX */
-    if ((ins->rex & (REX_D|REX_V)) && (prefix->rex & REX_P))
+    /* REX cannot be combined with VEX */
+    if ((ins->rex & REX_V) && (prefix->rex & REX_P))
        return false;
 
     /*
index 0b29757..6db1c82 100755 (executable)
--- a/insns.pl
+++ b/insns.pl
@@ -649,7 +649,6 @@ sub startseq($$) {
 # r = register field in the modr/m
 # m = modr/m
 # v = VEX "v" field
-# d = DREX "dst" field
 # i = immediate
 # s = register field of is4/imz2 field
 # - = implicit (unencoded) operand
@@ -811,19 +810,6 @@ sub byte_code_compile($$) {
             push(@codes, defined($oppos{'v'}) ? 0260+($oppos{'v'} & 3) : 0270,
                  ($c << 6)+$m, ($w << 4)+($l << 2)+$p);
             $prefix_ok = 0;
-        } elsif ($op =~ /^\/drex([01])$/) {
-            my $oc0 = $1;
-            if (!defined($oppos{'d'})) {
-                die "$fname: $line: DREX without a 'd' operand\n";
-            }
-            # Note the use of *unshift* here, as opposed to *push*.
-            # This is because NASM want this byte code at the start of
-            # the instruction sequence, but the AMD documentation puts
-            # this at (roughly) the position of the drex byte itself.
-            # This allows us to match the AMD documentation and still
-            # do the right thing.
-            unshift(@codes, 0160+($oppos{'d'} & 3)+($oc0 ? 4 : 0));
-            unshift(@codes, 05) if ($oppos{'d'} & 4);
         } elsif ($op =~ /^(ib\,s|ib|ibx|ib\,w|iw|iwd|id|idx|iwdq|rel|rel8|rel16|rel32|iq|seg|ibw|ibd|ibd,s)$/) {
             if (!defined($oppos{'i'})) {
                 die "$fname: $line: $op without 'i' operand\n";
diff --git a/nasm.h b/nasm.h
index 453a57c..f8f62be 100644 (file)
--- a/nasm.h
+++ b/nasm.h
@@ -439,10 +439,8 @@ enum ccode {                       /* condition code names */
 #define REX_L          0x20    /* Use LOCK prefix instead of REX.R */
 #define REX_P          0x40    /* REX prefix present/required */
 #define REX_H          0x80    /* High register present, REX forbidden */
-#define REX_D          0x0100  /* Instruction uses DREX instead of REX */
-#define REX_OC         0x0200  /* DREX suffix has the OC0 bit set */
-#define REX_V          0x0400  /* Instruction uses VEX/XOP instead of REX */
-#define REX_NH         0x0800  /* Instruction which doesn't use high regs */
+#define REX_V          0x0100  /* Instruction uses VEX/XOP instead of REX */
+#define REX_NH         0x0200  /* Instruction which doesn't use high regs */
 
 /*
  * REX_V "classes" (prefixes which behave like VEX)
@@ -558,7 +556,7 @@ typedef struct insn {               /* an instruction itself */
     int32_t times;              /* repeat count (TIMES prefix) */
     bool forw_ref;              /* is there a forward reference? */
     int rex;                   /* Special REX Prefix */
-    int drexdst;               /* Destination register for DREX/VEX suffix */
+    int vexreg;                        /* Register encoded in VEX prefix */
     int vex_cm;                        /* Class and M field for VEX prefix */
     int vex_wlp;               /* W, P and L information for VEX prefix */
 } insn;