MPX: Add MPX instructions
authorJin Kyu Song <jin.kyu.song@intel.com>
Wed, 16 Oct 2013 02:10:13 +0000 (19:10 -0700)
committerJin Kyu Song <jin.kyu.song@intel.com>
Wed, 20 Nov 2013 19:29:41 +0000 (11:29 -0800)
Added MPX instructions and corresponding parser and encoder.

ICC style mib - base + disp and index are separate - is supported.
E.g. bndstx [ebx+3], bnd2, edx -> ebx+3 : base+disp, edx : index

As a supplement to NASM style mib - split EA - parser,
omitted base+disp is now treated as 0 displacement.
E.g. bndstx [,edx], bnd2 -> bndstx [0,edx], bnd2

Signed-off-by: Jin Kyu Song <jin.kyu.song@intel.com>
assemble.c
insns.dat
insns.h
insns.pl
opflags.h
parser.c
regs.dat

index 57ef0cd..d913495 100644 (file)
@@ -42,6 +42,7 @@
  * \7            - add 4 to both the primary and the secondary operand number
  * \10..\13      - a literal byte follows in the code stream, to be added
  *                 to the register value of operand 0..3
+ * \14..\17      - the position of index register operand in MIB (BND insns)
  * \20..\23      - a byte immediate operand, from operand 0..3
  * \24..\27      - a zero-extended byte immediate operand, from operand 0..3
  * \30..\33      - a word immediate operand, from operand 0..3
@@ -852,6 +853,7 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
     enum ea_type eat;
     uint8_t hleok = 0;
     bool lockcheck = true;
+    enum reg_enum mib_index = R_none;   /* For a separate index MIB reg form */
 
     ins->rex = 0;               /* Ensure REX is reset */
     eat = EA_SCALAR;            /* Expect a scalar EA */
@@ -885,6 +887,11 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
             codes++, length++;
             break;
 
+        case4(014):
+            /* this is an index reg of MIB operand */
+            mib_index = opx->basereg;
+            break;
+
         case4(020):
         case4(024):
             length++;
@@ -1184,6 +1191,17 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
                     }
                 }
 
+                /*
+                 * if a separate form of MIB (ICC style) is used,
+                 * the index reg info is merged into mem operand
+                 */
+                if (mib_index != R_none) {
+                    opy->indexreg = mib_index;
+                    opy->scale = 1;
+                    opy->hintbase = mib_index;
+                    opy->hinttype = EAH_NOTBASE;
+                }
+
                 if (process_ea(opy, &ea_data, bits,
                                rfield, rflags, ins) != eat) {
                     errfunc(ERR_NONFATAL, "invalid effective address");
@@ -1336,6 +1354,9 @@ static void gencode(int32_t segment, int64_t offset, int bits,
             offset += 1;
             break;
 
+        case4(014):
+            break;
+
         case4(020):
             if (opx->offset < -256 || opx->offset > 255) {
                 errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
@@ -2545,7 +2566,7 @@ static enum ea_type process_ea(operand *input, ea *output, int bits,
                 }
                 if (bt == it)     /* convert EAX+2*EAX to 3*EAX */
                     bt = -1, bx = 0, s++;
-                if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE)) {
+                if (bt == -1 && s == 1 && !(hb == i && ht == EAH_NOTBASE)) {
                     /* make single reg base, unless hint */
                     bt = it, bx = ix, it = -1, ix = 0;
                 }
index 52aeff5..b1a1aac 100644 (file)
--- a/insns.dat
+++ b/insns.dat
@@ -4095,6 +4095,27 @@ VSCATTERPF1QPD  zmem64|mask  [m:t1s:    vsibz evex.512.66.0f38.w1 c7 /6 ]  AVX51
 VSCATTERPF1QPS  zmem32|mask  [m:t1s:    vsibz evex.512.66.0f38.w0 c7 /6 ]  AVX512PF,FUTURE
 PREFETCHWT1     mem8         [m:                               0f 0d /2 ]  FUTURE
 
+; MPX instructions
+BNDMK       bndreg,mem32           [rm:     o32 f3 0f 1b /r ]  MPX,SD,FUTURE
+BNDMK       bndreg,mem64           [rm:   o64nw f3 0f 1b /r ]  MPX,SQ,FUTURE
+BNDCL       bndreg,rm32            [rm:     o32 f3 0f 1a /r ]  MPX,SD,FUTURE
+BNDCL       bndreg,rm64            [rm:   o64nw f3 0f 1a /r ]  MPX,SQ,FUTURE
+BNDCU       bndreg,rm32            [rm:     o32 f2 0f 1a /r ]  MPX,SD,FUTURE
+BNDCU       bndreg,rm64            [rm:   o64nw f2 0f 1a /r ]  MPX,SQ,FUTURE
+BNDCN       bndreg,rm32            [rm:     o32 f2 0f 1b /r ]  MPX,SD,FUTURE
+BNDCN       bndreg,rm64            [rm:   o64nw f2 0f 1b /r ]  MPX,SQ,FUTURE
+BNDMOV      bndreg,bndrm64         [rm:         66 0f 1a /r ]  MPX,SQ,FUTURE
+BNDMOV      bndreg,bndrm128        [rm:         66 0f 1a /r ]  MPX,SO,FUTURE
+BNDMOV      bndrm64,bndreg         [mr:         66 0f 1b /r ]  MPX,SQ,FUTURE
+BNDMOV      bndrm128,bndreg        [mr:         66 0f 1b /r ]  MPX,SO,FUTURE
+BNDLDX      bndreg,mem128          [rm:            0f 1a /r ]  MPX,MIB,FUTURE
+BNDLDX      bndreg,mem128,reg64    [rmx:           0f 1a /r ]  MPX,MIB,FUTURE
+BNDSTX      mem64,bndreg           [mr:            0f 1b /r ]  MPX,MIB,SQ,FUTURE
+BNDSTX      mem64,reg32,bndreg     [mxr:           0f 1b /r ]  MPX,MIB,FUTURE
+BNDSTX      mem64,bndreg,reg32     [mrx:           0f 1b /r ]  MPX,MIB,FUTURE
+BNDSTX      mem128,bndreg          [mr:            0f 1b /r ]  MPX,MIB,SO,FUTURE
+BNDSTX      mem128,reg64,bndreg    [mxr:           0f 1b /r ]  MPX,MIB,FUTURE
+BNDSTX      mem128,bndreg,reg64    [mrx:           0f 1b /r ]  MPX,MIB,FUTURE
 
 ;# Systematic names for the hinting nop instructions
 ; These should be last in the file
diff --git a/insns.h b/insns.h
index 61b04cc..6e94f3d 100644 (file)
--- a/insns.h
+++ b/insns.h
@@ -132,6 +132,7 @@ extern const uint8_t nasm_bytecodes[];
 #define IF_AVX512CD     (0x1600000000UL|IF_AVX512) /* AVX-512 Conflict Detection insns */
 #define IF_AVX512ER     (0x1700000000UL|IF_AVX512) /* AVX-512 Exponential and Reciprocal */
 #define IF_AVX512PF     (0x1800000000UL|IF_AVX512) /* AVX-512 Prefetch instructions */
+#define IF_MPX          0x1900000000UL    /* MPX instructions */
 #define IF_INSMASK      0xFF00000000UL    /* the mask for instruction set types */
 #define IF_PMASK        0xFF000000UL    /* the mask for processor types */
 #define IF_PLEVEL       0x0F000000UL    /* the mask for processor instr. level */
index 8d1f0ee..8bd76ab 100755 (executable)
--- a/insns.pl
+++ b/insns.pl
@@ -704,6 +704,7 @@ sub tupletype($) {
 # i = immediate
 # s = register field of is4/imz2 field
 # - = implicit (unencoded) operand
+# x = indeX register of mib. 014..017 bytecodes are used.
 #
 # For an operand that should be filled into more than one field,
 # enter it as e.g. "r+v".
@@ -843,6 +844,8 @@ sub byte_code_compile($$) {
             $opex = (($oppos{'m'} & 4) ? 06 : 0) |
                 (($oppos{'r'} & 4) ? 05 : 0);
             push(@codes, $opex) if ($opex);
+            # if mib is composed with two separate operands - ICC style
+            push(@codes, 014 + ($oppos{'x'} & 3)) if (defined($oppos{'x'}));
             push(@codes, 0100 + (($oppos{'m'} & 3) << 3) + ($oppos{'r'} & 3));
             $prefix_ok = 0;
         } elsif ($op =~ m:^/([0-7])$:) {
index 014abe8..16c65cb 100644 (file)
--- a/opflags.h
+++ b/opflags.h
 #define REG_CLASS_RM_YMM        GEN_REG_CLASS(6)
 #define REG_CLASS_RM_ZMM        GEN_REG_CLASS(7)
 #define REG_CLASS_OPMASK        GEN_REG_CLASS(8)
+#define REG_CLASS_BND           GEN_REG_CLASS(9)
 
 #define is_class(class, op)         (!((opflags_t)(class) & ~(opflags_t)(op)))
 #define is_reg_class(class, reg)    is_class((class), nasm_reg_flags[(reg)])
 #define OPMASK0                 (GEN_SUBCLASS(1) | REG_CLASS_OPMASK           | REGMEM | REGISTER)      /* Opmask register zero (k0) */
 #define RM_K                    RM_OPMASK
 #define KREG                    OPMASKREG
+#define RM_BND                  (                  REG_CLASS_BND              | REGMEM)                 /* Bounds operand */
+#define BNDREG                  (                  REG_CLASS_BND              | REGMEM | REGISTER)      /* Bounds register */
 #define REG_CDT                 (                  REG_CLASS_CDT    | BITS32           | REGISTER)      /* CRn, DRn and TRn */
 #define REG_CREG                (GEN_SUBCLASS(1) | REG_CLASS_CDT    | BITS32           | REGISTER)      /* CRn */
 #define REG_DREG                (GEN_SUBCLASS(2) | REG_CLASS_CDT    | BITS32           | REGISTER)      /* DRn */
 #define ZMEM                    (GEN_SUBCLASS(5) | MEMORY)      /* 512-bit vector SIB */
 
 /* memory which matches any type of r/m operand */
-#define MEMORY_ANY              (MEMORY | RM_GPR | RM_MMX | RM_XMM | RM_YMM | RM_ZMM | RM_OPMASK)
+#define MEMORY_ANY              (MEMORY | RM_GPR | RM_MMX | RM_XMM | RM_YMM | RM_ZMM | RM_OPMASK | RM_BND)
 
 /* special immediate values */
 #define UNITY                   (GEN_SUBCLASS(0) | IMMEDIATE)   /* operand equals 1 */
index bb56924..0068ca3 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -821,6 +821,13 @@ is_expression:
                 process_size_override(result, op);
                 i = stdscan(NULL, &tokval);
             }
+            /* when a comma follows an opening bracket - [ , eax*4] */
+            if (i == ',') {
+                /* treat as if there is a zero displacement virtually */
+                tokval.t_type = TOKEN_NUM;
+                tokval.t_integer = 0;
+                stdscan_set(stdscan_get() - 1);     /* rewind the comma */
+            }
         } else {                /* immediate operand, or register */
             mref = false;
             bracket = false;    /* placate optimisers */
index 7861119..46d5409 100644 (file)
--- a/regs.dat
+++ b/regs.dat
@@ -130,3 +130,6 @@ zmm1-31     ZMMREG          zmmreg          1
 # Opmask registers
 k0     OPMASK0         opmaskreg       0
 k1-7   OPMASKREG       opmaskreg       1   TFLAG_BRC_OPT
+
+# Bounds registers
+bnd0-3 BNDREG          bndreg          0