Fix regular expression at doc/rdsrc.pl
[platform/upstream/nasm.git] / assemble.c
index 6ea8be6..ff3cea7 100644 (file)
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------- *
  *
- *   Copyright 1996-2013 The NASM Authors - All Rights Reserved
+ *   Copyright 1996-2014 The NASM Authors - All Rights Reserved
  *   See the file AUTHORS included with the NASM distribution for
  *   the specific copyright holders.
  *
@@ -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
 #include "assemble.h"
 #include "insns.h"
 #include "tables.h"
+#include "disp8.h"
 
 enum match_result {
     /*
@@ -188,10 +190,13 @@ enum match_result {
     MERR_INVALOP,
     MERR_OPSIZEMISSING,
     MERR_OPSIZEMISMATCH,
+    MERR_BRNUMMISMATCH,
     MERR_BADCPU,
     MERR_BADMODE,
     MERR_BADHLE,
     MERR_ENCMISMATCH,
+    MERR_BADBND,
+    MERR_BADREPNE,
     /*
      * Matching success; the conditional ones first
      */
@@ -214,7 +219,7 @@ typedef struct {
 #define GEN_MODRM(mod, reg, rm)                     \
         (((mod) << 6) | (((reg) & 7) << 3) | ((rm) & 7))
 
-static iflags_t cpu;            /* cpu level received from nasm.c */
+static iflag_t cpu;             /* cpu level received from nasm.c */
 static efunc errfunc;
 static struct ofmt *outfmt;
 static ListGen *list;
@@ -357,6 +362,7 @@ static bool jmp_match(int32_t segment, int64_t offset, int bits,
     int64_t isize;
     const uint8_t *code = temp->code;
     uint8_t c = code[0];
+    bool is_byte;
 
     if (((c & ~1) != 0370) || (ins->oprs[0].type & STRICT))
         return false;
@@ -375,10 +381,19 @@ static bool jmp_match(int32_t segment, int64_t offset, int bits,
         return false;
 
     isize = ins->oprs[0].offset - offset - isize; /* isize is delta */
-    return (isize >= -128 && isize <= 127); /* is it byte size? */
+    is_byte = (isize >= -128 && isize <= 127); /* is it byte size? */
+
+    if (is_byte && c == 0371 && ins->prefixes[PPS_REP] == P_BND) {
+        /* jmp short (opcode eb) cannot be used with bnd prefix. */
+        ins->prefixes[PPS_REP] = P_none;
+        errfunc(ERR_WARNING | ERR_WARN_BND | ERR_PASS2 ,
+                "jmp short does not init bnd regs - bnd prefix dropped.");
+    }
+
+    return is_byte;
 }
 
-int64_t assemble(int32_t segment, int64_t offset, int bits, iflags_t cp,
+int64_t assemble(int32_t segment, int64_t offset, int bits, iflag_t cp,
                  insn * instruction, struct ofmt *output, efunc error,
                  ListGen * listgen)
 {
@@ -546,6 +561,7 @@ int64_t assemble(int32_t segment, int64_t offset, int bits, iflags_t cp,
                     case P_REPNE:
                     case P_REPNZ:
                     case P_XACQUIRE:
+                    case P_BND:
                         c = 0xF2;
                         break;
                     case P_REPE:
@@ -629,6 +645,10 @@ int64_t assemble(int32_t segment, int64_t offset, int bits, iflags_t cp,
                     case P_OSP:
                         c = 0x66;
                         break;
+                    case P_EVEX:
+                    case P_VEX3:
+                    case P_VEX2:
+                    case P_NOBND:
                     case P_none:
                         break;
                     default:
@@ -665,6 +685,10 @@ int64_t assemble(int32_t segment, int64_t offset, int bits, iflags_t cp,
         case MERR_OPSIZEMISMATCH:
             error(ERR_NONFATAL, "mismatch in operand sizes");
             break;
+        case MERR_BRNUMMISMATCH:
+            error(ERR_NONFATAL,
+                  "mismatch in the number of broadcasting elements");
+            break;
         case MERR_BADCPU:
             error(ERR_NONFATAL, "no instruction for this cpu level");
             break;
@@ -672,6 +696,17 @@ int64_t assemble(int32_t segment, int64_t offset, int bits, iflags_t cp,
             error(ERR_NONFATAL, "instruction not supported in %d-bit mode",
                   bits);
             break;
+        case MERR_ENCMISMATCH:
+            error(ERR_NONFATAL, "specific encoding scheme not available");
+            break;
+        case MERR_BADBND:
+            error(ERR_NONFATAL, "bnd prefix is not allowed");
+            break;
+        case MERR_BADREPNE:
+            error(ERR_NONFATAL, "%s prefix is not allowed",
+                  (has_prefix(instruction, PPS_REP, P_REPNE) ?
+                   "repne" : "repnz"));
+            break;
         default:
             error(ERR_NONFATAL,
                   "invalid combination of opcode and operands");
@@ -681,7 +716,7 @@ int64_t assemble(int32_t segment, int64_t offset, int bits, iflags_t cp,
     return 0;
 }
 
-int64_t insn_size(int32_t segment, int64_t offset, int bits, iflags_t cp,
+int64_t insn_size(int32_t segment, int64_t offset, int bits, iflag_t cp,
                   insn * instruction, efunc error)
 {
     const struct itemplate *temp;
@@ -783,6 +818,10 @@ int64_t insn_size(int32_t segment, int64_t offset, int bits, iflags_t cp,
                 break;
             case P_A64:
             case P_O64:
+            case P_EVEX:
+            case P_VEX3:
+            case P_VEX2:
+            case P_NOBND:
             case P_none:
                 break;
             default:
@@ -852,6 +891,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 +925,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++;
@@ -1114,7 +1159,8 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
             length++;
             break;
 
-        case3(0370):
+        case 0370:
+        case 0371:
             break;
 
         case 0373:
@@ -1167,20 +1213,38 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
                 op_er_sae = (ins->evex_brerop >= 0 ?
                              &ins->oprs[ins->evex_brerop] : NULL);
 
-                if (op_er_sae && (op_er_sae->decoflags & ER)) {
-                    /* set EVEX.RC (rounding control) and b */
-                    ins->evex_p[2] |= (((ins->evex_rm - BRC_RN) << 5) & EVEX_P2LL) |
-                                      EVEX_P2B;
+                if (op_er_sae && (op_er_sae->decoflags & (ER | SAE))) {
+                    /* set EVEX.b */
+                    ins->evex_p[2] |= EVEX_P2B;
+                    if (op_er_sae->decoflags & ER) {
+                        /* set EVEX.RC (rounding control) */
+                        ins->evex_p[2] |= ((ins->evex_rm - BRC_RN) << 5)
+                                          & EVEX_P2RC;
+                    }
                 } else {
                     /* set EVEX.L'L (vector length) */
                     ins->evex_p[2] |= ((ins->vex_wlp << (5 - 2)) & EVEX_P2LL);
-                    if ((op_er_sae && (op_er_sae->decoflags & SAE)) ||
-                        (opy->decoflags & BRDCAST_MASK)) {
+                    ins->evex_p[1] |= ((ins->vex_wlp << (7 - 4)) & EVEX_P1W);
+                    if (opy->decoflags & BRDCAST_MASK) {
                         /* set EVEX.b */
                         ins->evex_p[2] |= EVEX_P2B;
                     }
                 }
 
+                if (itemp_has(temp, IF_MIB)) {
+                    opy->eaflags |= EAF_MIB;
+                    /*
+                     * 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");
@@ -1209,6 +1273,20 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
         ins->rex &= ~REX_P;        /* Don't force REX prefix due to high reg */
     }
 
+    switch (ins->prefixes[PPS_VEX]) {
+    case P_EVEX:
+        if (!(ins->rex & REX_EV))
+            return -1;
+        break;
+    case P_VEX3:
+    case P_VEX2:
+        if (!(ins->rex & REX_V))
+            return -1;
+        break;
+    default:
+        break;
+    }
+
     if (ins->rex & (REX_V | REX_EV)) {
         int bad32 = REX_R|REX_W|REX_X|REX_B;
 
@@ -1240,7 +1318,8 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
         }
         if (ins->rex & REX_EV)
             length += 4;
-        else if (ins->vex_cm != 1 || (ins->rex & (REX_W|REX_X|REX_B)))
+        else if (ins->vex_cm != 1 || (ins->rex & (REX_W|REX_X|REX_B)) ||
+                 ins->prefixes[PPS_VEX] == P_VEX3)
             length += 3;
         else
             length += 2;
@@ -1252,7 +1331,7 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
             length++;
         } else if ((ins->rex & REX_L) &&
                    !(ins->rex & (REX_P|REX_W|REX_X|REX_B)) &&
-                   cpu >= IF_X86_64) {
+                   iflag_ffs(&cpu) >= IF_X86_64) {
             /* LOCK-as-REX.R */
             assert_no_prefix(ins, PPS_LOCK);
             lockcheck = false;  /* Already errored, no need for warning */
@@ -1264,23 +1343,34 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
     }
 
     if (has_prefix(ins, PPS_LOCK, P_LOCK) && lockcheck &&
-        (!(temp->flags & IF_LOCK) || !is_class(MEMORY, ins->oprs[0].type))) {
+        (!itemp_has(temp,IF_LOCK) || !is_class(MEMORY, ins->oprs[0].type))) {
         errfunc(ERR_WARNING | ERR_WARN_LOCK | ERR_PASS2 ,
                 "instruction is not lockable");
     }
 
     bad_hle_warn(ins, hleok);
 
+    /*
+     * when BND prefix is set by DEFAULT directive,
+     * BND prefix is added to every appropriate instruction line
+     * unless it is overridden by NOBND prefix.
+     */
+    if (globalbnd &&
+        (itemp_has(temp, IF_BND) && !has_prefix(ins, PPS_REP, P_NOBND)))
+            ins->prefixes[PPS_REP] = P_BND;
+
     return length;
 }
 
 static inline unsigned int emit_rex(insn *ins, int32_t segment, int64_t offset, int bits)
 {
     if (bits == 64) {
-        if ((ins->rex & REX_REAL) && !(ins->rex & (REX_V | REX_EV))) {
-            ins->rex = (ins->rex & REX_REAL) | REX_P;
-            out(offset, segment, &ins->rex, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
-            ins->rex = 0;
+        if ((ins->rex & REX_REAL) &&
+            !(ins->rex & (REX_V | REX_EV)) &&
+            !ins->rex_done) {
+            int rex = (ins->rex & REX_REAL) | REX_P;
+            out(offset, segment, &rex, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
+            ins->rex_done = true;
             return 1;
         }
     }
@@ -1302,6 +1392,8 @@ static void gencode(int32_t segment, int64_t offset, int bits,
     uint8_t opex = 0;
     enum ea_type eat = EA_SCALAR;
 
+    ins->rex_done = false;
+
     while (*codes) {
         c = *codes++;
         op1 = (c & 3) + ((opex & 1) << 2);
@@ -1333,6 +1425,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,
@@ -1522,9 +1617,9 @@ static void gencode(int32_t segment, int64_t offset, int bits,
             ins->evex_p[2] ^= EVEX_P2VP;        /* 1's complement */
             bytes[0] = 0x62;
             /* EVEX.X can be set by either REX or EVEX for different reasons */
-            bytes[1] = (~(((ins->rex & 7) << 5) |
-                          (ins->evex_p[0] & (EVEX_P0X | EVEX_P0RP))) & 0xf0) |
-                        (ins->vex_cm & 3);
+            bytes[1] = ((((ins->rex & 7) << 5) |
+                         (ins->evex_p[0] & (EVEX_P0X | EVEX_P0RP))) ^ 0xf0) |
+                       (ins->vex_cm & 3);
             bytes[2] = ((ins->rex & REX_W) << (7 - 3)) |
                        ((~ins->vexreg & 15) << 3) |
                        (1 << 2) | (ins->vex_wlp & 3);
@@ -1536,7 +1631,8 @@ static void gencode(int32_t segment, int64_t offset, int bits,
         case4(0260):
         case 0270:
             codes += 2;
-            if (ins->vex_cm != 1 || (ins->rex & (REX_W|REX_X|REX_B))) {
+            if (ins->vex_cm != 1 || (ins->rex & (REX_W|REX_X|REX_B)) ||
+                ins->prefixes[PPS_VEX] == P_VEX3) {
                 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)) |
@@ -1715,8 +1811,7 @@ static void gencode(int32_t segment, int64_t offset, int bits,
             offset += 1;
             break;
 
-        case 0370:
-        case 0371:
+        case3(0370):
             break;
 
         case 0373:
@@ -1869,7 +1964,7 @@ static int rexflags(int val, opflags_t flags, int mask)
 {
     int rex = 0;
 
-    if (val >= 8)
+    if (val >= 0 && (val & 8))
         rex |= REX_B|REX_X|REX_R;
     if (flags & BITS64)
         rex |= REX_W;
@@ -1886,13 +1981,13 @@ static int evexflags(int val, decoflags_t deco,
 {
     int evex = 0;
 
-    switch(byte) {
+    switch (byte) {
     case 0:
-        if (val >= 16)
+        if (val >= 0 && (val & 16))
             evex |= (EVEX_P0RP | EVEX_P0X);
         break;
     case 2:
-        if (val >= 16)
+        if (val >= 0 && (val & 16))
             evex |= EVEX_P2VP;
         if (deco & Z)
             evex |= EVEX_P2Z;
@@ -1907,9 +2002,6 @@ static int op_evexflags(const operand * o, int mask, uint8_t byte)
 {
     int val;
 
-    if (!is_register(o->basereg))
-        errfunc(ERR_PANIC, "invalid operand passed to op_evexflags()");
-
     val = nasm_regvals[o->basereg];
 
     return evexflags(val, o->decoflags, mask, byte);
@@ -1943,8 +2035,7 @@ static enum match_result find_match(const struct itemplate **tempp,
                 m = MOK_GOOD;
             else
                 m = MERR_INVALOP;
-        } else if (m == MERR_OPSIZEMISSING &&
-                   (temp->flags & IF_SMASK) != IF_SX) {
+        } else if (m == MERR_OPSIZEMISSING && !itemp_has(temp, IF_SX)) {
             /*
              * Missing operand size and a candidate for fuzzy matching...
              */
@@ -1978,10 +2069,13 @@ static enum match_result find_match(const struct itemplate **tempp,
         if ((xsizeflags[i] & (xsizeflags[i]-1)))
             goto done;                /* No luck */
 
-        if (i == broadcast)
+        if (i == broadcast) {
             instruction->oprs[i].decoflags |= xsizeflags[i];
-        else
+            instruction->oprs[i].type |= (xsizeflags[i] == BR_BITS32 ?
+                                          BITS32 : BITS64);
+        } else {
             instruction->oprs[i].type |= xsizeflags[i]; /* Set the size */
+        }
     }
 
     /* Try matching again... */
@@ -2027,10 +2121,27 @@ static enum match_result matches(const struct itemplate *itemp,
     /*
      * Is it legal?
      */
-    if (!(optimizing > 0) && (itemp->flags & IF_OPT))
+    if (!(optimizing > 0) && itemp_has(itemp, IF_OPT))
        return MERR_INVALOP;
 
     /*
+     * {evex} available?
+     */
+    switch (instruction->prefixes[PPS_VEX]) {
+    case P_EVEX:
+        if (!itemp_has(itemp, IF_EVEX))
+            return MERR_ENCMISMATCH;
+        break;
+    case P_VEX3:
+    case P_VEX2:
+        if (!itemp_has(itemp, IF_VEX))
+            return MERR_ENCMISMATCH;
+        break;
+    default:
+        break;
+    }
+
+    /*
      * Check that no spurious colons or TOs are present
      */
     for (i = 0; i < itemp->operands; i++)
@@ -2040,29 +2151,29 @@ static enum match_result matches(const struct itemplate *itemp,
     /*
      * Process size flags
      */
-    switch (itemp->flags & IF_SMASK) {
-    case IF_SB:
+    switch (itemp_smask(itemp)) {
+    case IF_GENBIT(IF_SB):
         asize = BITS8;
         break;
-    case IF_SW:
+    case IF_GENBIT(IF_SW):
         asize = BITS16;
         break;
-    case IF_SD:
+    case IF_GENBIT(IF_SD):
         asize = BITS32;
         break;
-    case IF_SQ:
+    case IF_GENBIT(IF_SQ):
         asize = BITS64;
         break;
-    case IF_SO:
+    case IF_GENBIT(IF_SO):
         asize = BITS128;
         break;
-    case IF_SY:
+    case IF_GENBIT(IF_SY):
         asize = BITS256;
         break;
-    case IF_SZ:
+    case IF_GENBIT(IF_SZ):
         asize = BITS512;
         break;
-    case IF_SIZE:
+    case IF_GENBIT(IF_SIZE):
         switch (bits) {
         case 16:
             asize = BITS16;
@@ -2083,9 +2194,9 @@ static enum match_result matches(const struct itemplate *itemp,
         break;
     }
 
-    if (itemp->flags & IF_ARMASK) {
+    if (itemp_armask(itemp)) {
         /* S- flags only apply to a specific operand */
-        i = ((itemp->flags & IF_ARMASK) >> IF_ARSHFT) - 1;
+        i = itemp_arg(itemp);
         memset(size, 0, sizeof size);
         size[i] = asize;
     } else {
@@ -2117,36 +2228,59 @@ static enum match_result matches(const struct itemplate *itemp,
     for (i = 0; i < itemp->operands; i++) {
         opflags_t type = instruction->oprs[i].type;
         decoflags_t deco = instruction->oprs[i].decoflags;
+        bool is_broadcast = deco & BRDCAST_MASK;
+        uint8_t brcast_num = 0;
+        opflags_t template_opsize, insn_opsize;
+
         if (!(type & SIZE_MASK))
             type |= size[i];
 
+        insn_opsize     = type & SIZE_MASK;
+        if (!is_broadcast) {
+            template_opsize = itemp->opd[i] & SIZE_MASK;
+        } else {
+            decoflags_t deco_brsize = itemp->deco[i] & BRSIZE_MASK;
+            /*
+             * when broadcasting, the element size depends on
+             * the instruction type. decorator flag should match.
+             */
+
+            if (deco_brsize) {
+                template_opsize = (deco_brsize == BR_BITS32 ? BITS32 : BITS64);
+                /* calculate the proper number : {1to<brcast_num>} */
+                brcast_num = (itemp->opd[i] & SIZE_MASK) / BITS128 *
+                                BITS64 / template_opsize * 2;
+            } else {
+                template_opsize = 0;
+            }
+        }
+
         if ((itemp->opd[i] & ~type & ~SIZE_MASK) ||
-            (itemp->deco[i] & deco) != deco) {
+            (deco & ~itemp->deco[i] & ~BRNUM_MASK)) {
             return MERR_INVALOP;
-        } else if ((itemp->opd[i] & SIZE_MASK) &&
-                   (itemp->opd[i] & SIZE_MASK) != (type & SIZE_MASK)) {
-            if (type & SIZE_MASK) {
-                /*
-                 * when broadcasting, the element size depends on
-                 * the instruction type. decorator flag should match.
-                 */
-#define MATCH_BRSZ(bits) (((type & SIZE_MASK) == BITS##bits) &&             \
-                          ((itemp->deco[i] & BRSIZE_MASK) == BR_BITS##bits))
-                if (!((deco & BRDCAST_MASK) &&
-                      (MATCH_BRSZ(32) || MATCH_BRSZ(64)))) {
+        } else if (template_opsize) {
+            if (template_opsize != insn_opsize) {
+                if (insn_opsize) {
                     return MERR_INVALOP;
+                } else if (!is_class(REGISTER, type)) {
+                    /*
+                     * Note: we don't honor extrinsic operand sizes for registers,
+                     * so "missing operand size" for a register should be
+                     * considered a wildcard match rather than an error.
+                     */
+                    opsizemissing = true;
                 }
-            } else if (!is_class(REGISTER, type)) {
+            } else if (is_broadcast &&
+                       (brcast_num !=
+                        (8U << ((deco & BRNUM_MASK) >> BRNUM_SHIFT)))) {
                 /*
-                 * Note: we don't honor extrinsic operand sizes for registers,
-                 * so "missing operand size" for a register should be
-                 * considered a wildcard match rather than an error.
+                 * broadcasting opsize matches but the number of repeated memory
+                 * element does not match.
+                 * if 64b double precision float is broadcasted to zmm (512b),
+                 * broadcasting decorator must be {1to8}.
                  */
-                opsizemissing = true;
+                return MERR_BRNUMMISMATCH;
             }
-        } else if (nasm_regvals[instruction->oprs[i].basereg] >= 16 &&
-                   (itemp->flags & IF_INSMASK) != IF_AVX512) {
-            return MERR_ENCMISMATCH;
         }
     }
 
@@ -2156,8 +2290,8 @@ static enum match_result matches(const struct itemplate *itemp,
     /*
      * Check operand sizes
      */
-    if (itemp->flags & (IF_SM | IF_SM2)) {
-        oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
+    if (itemp_has(itemp, IF_SM) || itemp_has(itemp, IF_SM2)) {
+        oprs = (itemp_has(itemp, IF_SM2) ? 2 : itemp->operands);
         for (i = 0; i < oprs; i++) {
             asize = itemp->opd[i] & SIZE_MASK;
             if (asize) {
@@ -2179,19 +2313,19 @@ static enum match_result matches(const struct itemplate *itemp,
     /*
      * Check template is okay at the set cpu level
      */
-    if (((itemp->flags & IF_PLEVEL) > cpu))
+    if (iflag_cmp_cpu_level(&insns_flags[itemp->iflag_idx], &cpu) > 0)
         return MERR_BADCPU;
 
     /*
      * Verify the appropriate long mode flag.
      */
-    if ((itemp->flags & (bits == 64 ? IF_NOLONG : IF_LONG)))
+    if (itemp_has(itemp, (bits == 64 ? IF_NOLONG : IF_LONG)))
         return MERR_BADMODE;
 
     /*
      * If we have a HLE prefix, look for the NOHLE flag
      */
-    if ((itemp->flags & IF_NOHLE) &&
+    if (itemp_has(itemp, IF_NOHLE) &&
         (has_prefix(instruction, PPS_REP, P_XACQUIRE) ||
          has_prefix(instruction, PPS_REP, P_XRELEASE)))
         return MERR_BADHLE;
@@ -2202,90 +2336,20 @@ static enum match_result matches(const struct itemplate *itemp,
     if ((itemp->code[0] & ~1) == 0370)
         return MOK_JUMP;
 
-    return MOK_GOOD;
-}
-
-/*
- * Check if offset is a multiple of N with corresponding tuple type
- * if Disp8*N is available, compressed displacement is stored in compdisp
- */
-static bool is_disp8n(operand *input, insn *ins, int8_t *compdisp)
-{
-    const uint8_t fv_n[2][2][VLMAX] = {{{16, 32, 64}, {4, 4, 4}},
-                                       {{16, 32, 64}, {8, 8, 8}}};
-    const uint8_t hv_n[2][VLMAX]    =  {{8, 16, 32}, {4, 4, 4}};
-    const uint8_t dup_n[VLMAX]      =   {8, 32, 64};
-
-    bool evex_b           = input->decoflags & BRDCAST_MASK;
-    enum ttypes   tuple   = ins->evex_tuple;
-    /* vex_wlp composed as [wwllpp] */
-    enum vectlens vectlen = (ins->vex_wlp & 0x0c) >> 2;
-    /* wig(=2) is treated as w0(=0) */
-    bool evex_w           = (ins->vex_wlp & 0x10) >> 4;
-    int32_t off           = input->offset;
-    uint8_t n = 0;
-    int32_t disp8;
-
-    switch(tuple) {
-    case FV:
-        n = fv_n[evex_w][evex_b][vectlen];
-        break;
-    case HV:
-        n = hv_n[evex_b][vectlen];
-        break;
-
-    case FVM:
-        /* 16, 32, 64 for VL 128, 256, 512 respectively*/
-        n = 1 << (vectlen + 4);
-        break;
-    case T1S8:  /* N = 1 */
-    case T1S16: /* N = 2 */
-        n = tuple - T1S8 + 1;
-        break;
-    case T1S:
-        /* N = 4 for 32bit, 8 for 64bit */
-        n = evex_w ? 8 : 4;
-        break;
-    case T1F32:
-    case T1F64:
-        /* N = 4 for 32bit, 8 for 64bit */
-        n = (tuple == T1F32 ? 4 : 8);
-        break;
-    case T2:
-    case T4:
-    case T8:
-        if (vectlen + 7 <= (evex_w + 5) + (tuple - T2 + 1))
-            n = 0;
-        else
-            n = 1 << (tuple - T2 + evex_w + 3);
-        break;
-    case HVM:
-    case QVM:
-    case OVM:
-        n = 1 << (OVM - tuple + vectlen + 1);
-        break;
-    case M128:
-        n = 16;
-        break;
-    case DUP:
-        n = dup_n[vectlen];
-        break;
-
-    default:
-        break;
-    }
-
-    if (n && !(off & (n - 1))) {
-        disp8 = off / n;
-        /* if it fits in Disp8 */
-        if (disp8 >= -128 && disp8 <= 127) {
-            *compdisp = disp8;
-            return true;
-        }
-    }
+    /*
+     * Check if BND prefix is allowed.
+     * Other 0xF2 (REPNE/REPNZ) prefix is prohibited.
+     */
+    if (!itemp_has(itemp, IF_BND) &&
+        (has_prefix(instruction, PPS_REP, P_BND) ||
+         has_prefix(instruction, PPS_REP, P_NOBND)))
+        return MERR_BADBND;
+    else if (itemp_has(itemp, IF_BND) &&
+             (has_prefix(instruction, PPS_REP, P_REPNE) ||
+              has_prefix(instruction, PPS_REP, P_REPNZ)))
+        return MERR_BADREPNE;
 
-    *compdisp = 0;
-    return false;
+    return MOK_GOOD;
 }
 
 /*
@@ -2307,9 +2371,11 @@ static enum ea_type process_ea(operand *input, ea *output, int bits,
 {
     bool forw_ref = !!(input->opflags & OPFLAG_UNKNOWN);
     int addrbits = ins->addr_size;
+    int eaflags = input->eaflags;
 
     output->type    = EA_SCALAR;
     output->rip     = false;
+    output->disp8   = 0;
 
     /* REX flags for the rfield operand */
     output->rex     |= rexflags(rfield, rflags, REX_R | REX_P | REX_W | REX_H);
@@ -2361,8 +2427,14 @@ static enum ea_type process_ea(operand *input, ea *output, int bits,
                 input->type |= MEMORY;
             }
 
-            if (input->eaflags & EAF_BYTEOFFS ||
-                (input->eaflags & EAF_WORDOFFS &&
+            if (bits == 64 &&
+                !(IP_REL & ~input->type) && (eaflags & EAF_MIB)) {
+                nasm_error(ERR_NONFATAL, "RIP-relative addressing is prohibited for mib.");
+                return -1;
+            }
+
+            if (eaflags & EAF_BYTEOFFS ||
+                (eaflags & EAF_WORDOFFS &&
                  input->disp_size != (addrbits != 16 ? 32 : 16))) {
                 nasm_error(ERR_WARNING | ERR_PASS1, "displacement size ignored on absolute address");
             }
@@ -2483,7 +2555,7 @@ static enum ea_type process_ea(operand *input, ea *output, int bits,
                     base = (bt & 7);
                     if (base != REG_NUM_EBP && o == 0 &&
                         seg == NO_SEG && !forw_ref &&
-                        !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
+                        !(eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
                         mod = 0;
                     else if (IS_MOD_01())
                         mod = 1;
@@ -2538,19 +2610,41 @@ static enum ea_type process_ea(operand *input, ea *output, int bits,
                     t = bt, bt = it, it = t;
                     x = bx, bx = ix, ix = x;
                 }
-                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;
                 }
-                if (((s == 2 && it != REG_NUM_ESP && !(input->eaflags & EAF_TIMESTWO)) ||
-                      s == 3 || s == 5 || s == 9) && bt == -1)
-                    bt = it, bx = ix, s--; /* convert 3*EAX to EAX+2*EAX */
-                if (it == -1 && (bt & 7) != REG_NUM_ESP &&
-                    (input->eaflags & EAF_TIMESTWO))
-                    it = bt, ix = bx, bt = -1, bx = 0, s = 1;
-                /* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
+                if (eaflags & EAF_MIB) {
+                    /* only for mib operands */
+                    if (it == -1 && (hb == b && ht == EAH_NOTBASE)) {
+                        /*
+                         * make a single reg index [reg*1].
+                         * gas uses this form for an explicit index register.
+                         */
+                        it = bt, ix = bx, bt = -1, bx = 0, s = 1;
+                    }
+                    if ((ht == EAH_SUMMED) && bt == -1) {
+                        /* separate once summed index into [base, index] */
+                        bt = it, bx = ix, s--;
+                    }
+                } else {
+                    if (((s == 2 && it != REG_NUM_ESP &&
+                          (!(eaflags & EAF_TIMESTWO) || (ht == EAH_SUMMED))) ||
+                         s == 3 || s == 5 || s == 9) && bt == -1) {
+                        /* convert 3*EAX to EAX+2*EAX */
+                        bt = it, bx = ix, s--;
+                    }
+                    if (it == -1 && (bt & 7) != REG_NUM_ESP &&
+                        (eaflags & EAF_TIMESTWO) &&
+                        (hb == b && ht == EAH_NOTBASE)) {
+                        /*
+                         * convert [NOSPLIT EAX*1]
+                         * to sib format with 0x0 displacement - [EAX*1+0].
+                         */
+                        it = bt, ix = bx, bt = -1, bx = 0, s = 1;
+                    }
+                }
                 if (s == 1 && it == REG_NUM_ESP) {
                     /* swap ESP into base if scale is 1 */
                     t = it, it = bt, bt = t;
@@ -2574,7 +2668,7 @@ static enum ea_type process_ea(operand *input, ea *output, int bits,
                         rm = (bt & 7);
                         if (rm != REG_NUM_EBP && o == 0 &&
                             seg == NO_SEG && !forw_ref &&
-                            !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
+                            !(eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
                             mod = 0;
                         else if (IS_MOD_01())
                             mod = 1;
@@ -2618,7 +2712,7 @@ static enum ea_type process_ea(operand *input, ea *output, int bits,
                         base = (bt & 7);
                         if (base != REG_NUM_EBP && o == 0 &&
                             seg == NO_SEG && !forw_ref &&
-                            !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
+                            !(eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
                             mod = 0;
                         else if (IS_MOD_01())
                             mod = 1;
@@ -2703,7 +2797,7 @@ static enum ea_type process_ea(operand *input, ea *output, int bits,
                     goto err;        /* so panic if it does */
 
                 if (o == 0 && seg == NO_SEG && !forw_ref && rm != 6 &&
-                    !(input->eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
+                    !(eaflags & (EAF_BYTEOFFS | EAF_WORDOFFS)))
                     mod = 0;
                 else if (IS_MOD_01())
                     mod = 1;