Fix regular expression at doc/rdsrc.pl
[platform/upstream/nasm.git] / parser.c
index 2ff6e36..2d8d4ff 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------- *
- *   
- *   Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ *
+ *   Copyright 1996-2013 The NASM Authors - All Rights Reserved
  *   See the file AUTHORS included with the NASM distribution for
  *   the specific copyright holders.
  *
@@ -14,7 +14,7 @@
  *     copyright notice, this list of conditions and the following
  *     disclaimer in the documentation and/or other materials provided
  *     with the distribution.
- *     
+ *
  *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 #include "tables.h"
 
 extern int in_abs_seg;          /* ABSOLUTE segment flag */
-extern int32_t abs_seg;            /* ABSOLUTE segment */
-extern int32_t abs_offset;         /* ABSOLUTE segment offset */
+extern int32_t abs_seg;         /* ABSOLUTE segment */
+extern int32_t abs_offset;      /* ABSOLUTE segment offset */
 
 static int is_comma_next(void);
 
 static int i;
 static struct tokenval tokval;
-static struct location *location;         /* Pointer to current line's segment,offset */
+static struct location *location;       /* Pointer to current line's segment,offset */
 
 void parser_global_info(struct location * locp)
 {
     location = locp;
 }
 
-static int prefix_slot(enum prefixes prefix)
+static int prefix_slot(int prefix)
 {
     switch (prefix) {
     case P_WAIT:
-       return PPS_WAIT;
+        return PPS_WAIT;
     case R_CS:
     case R_DS:
     case R_SS:
     case R_ES:
     case R_FS:
     case R_GS:
-       return PPS_SEG;
+        return PPS_SEG;
     case P_LOCK:
+        return PPS_LOCK;
     case P_REP:
     case P_REPE:
     case P_REPZ:
     case P_REPNE:
     case P_REPNZ:
-       return PPS_LREP;
+    case P_XACQUIRE:
+    case P_XRELEASE:
+    case P_BND:
+    case P_NOBND:
+        return PPS_REP;
     case P_O16:
     case P_O32:
     case P_O64:
     case P_OSP:
-       return PPS_OSIZE;
+        return PPS_OSIZE;
     case P_A16:
     case P_A32:
     case P_A64:
     case P_ASP:
-       return PPS_ASIZE;
+        return PPS_ASIZE;
+    case P_EVEX:
+    case P_VEX3:
+    case P_VEX2:
+        return PPS_VEX;
     default:
-       nasm_error(ERR_PANIC, "Invalid value %d passed to prefix_slot()", prefix);
-       return -1;
+        nasm_error(ERR_PANIC, "Invalid value %d passed to prefix_slot()", prefix);
+        return -1;
     }
 }
 
-static void process_size_override(insn * result, int operand)
+static void process_size_override(insn *result, operand *op)
 {
     if (tasm_compatible_mode) {
-       switch ((int)tokval.t_integer) {
-           /* For TASM compatibility a size override inside the
-            * brackets changes the size of the operand, not the
-            * address type of the operand as it does in standard
-            * NASM syntax. Hence:
-            *
-            *  mov     eax,[DWORD val]
-            *
-            * is valid syntax in TASM compatibility mode. Note that
-            * you lose the ability to override the default address
-            * type for the instruction, but we never use anything
-            * but 32-bit flat model addressing in our code.
-            */
-       case S_BYTE:
-           result->oprs[operand].type |= BITS8;
-           break;
-       case S_WORD:
-           result->oprs[operand].type |= BITS16;
-           break;
-       case S_DWORD:
-       case S_LONG:
-           result->oprs[operand].type |= BITS32;
-           break;
-       case S_QWORD:
-           result->oprs[operand].type |= BITS64;
-           break;
-       case S_TWORD:
-           result->oprs[operand].type |= BITS80;
-           break;
-       case S_OWORD:
-           result->oprs[operand].type |= BITS128;
-           break;
-       default:
-           nasm_error(ERR_NONFATAL,
-                 "invalid operand size specification");
-           break;
-       }
+        switch ((int)tokval.t_integer) {
+            /* For TASM compatibility a size override inside the
+             * brackets changes the size of the operand, not the
+             * address type of the operand as it does in standard
+             * NASM syntax. Hence:
+             *
+             *  mov     eax,[DWORD val]
+             *
+             * is valid syntax in TASM compatibility mode. Note that
+             * you lose the ability to override the default address
+             * type for the instruction, but we never use anything
+             * but 32-bit flat model addressing in our code.
+             */
+        case S_BYTE:
+            op->type |= BITS8;
+            break;
+        case S_WORD:
+            op->type |= BITS16;
+            break;
+        case S_DWORD:
+        case S_LONG:
+            op->type |= BITS32;
+            break;
+        case S_QWORD:
+            op->type |= BITS64;
+            break;
+        case S_TWORD:
+            op->type |= BITS80;
+            break;
+        case S_OWORD:
+            op->type |= BITS128;
+            break;
+        default:
+            nasm_error(ERR_NONFATAL,
+                       "invalid operand size specification");
+            break;
+        }
+    } else {
+        /* Standard NASM compatible syntax */
+        switch ((int)tokval.t_integer) {
+        case S_NOSPLIT:
+            op->eaflags |= EAF_TIMESTWO;
+            break;
+        case S_REL:
+            op->eaflags |= EAF_REL;
+            break;
+        case S_ABS:
+            op->eaflags |= EAF_ABS;
+            break;
+        case S_BYTE:
+            op->disp_size = 8;
+            op->eaflags |= EAF_BYTEOFFS;
+            break;
+        case P_A16:
+        case P_A32:
+        case P_A64:
+            if (result->prefixes[PPS_ASIZE] &&
+                result->prefixes[PPS_ASIZE] != tokval.t_integer)
+                nasm_error(ERR_NONFATAL,
+                           "conflicting address size specifications");
+            else
+                result->prefixes[PPS_ASIZE] = tokval.t_integer;
+            break;
+        case S_WORD:
+            op->disp_size = 16;
+            op->eaflags |= EAF_WORDOFFS;
+            break;
+        case S_DWORD:
+        case S_LONG:
+            op->disp_size = 32;
+            op->eaflags |= EAF_WORDOFFS;
+            break;
+        case S_QWORD:
+            op->disp_size = 64;
+            op->eaflags |= EAF_WORDOFFS;
+            break;
+        default:
+            nasm_error(ERR_NONFATAL, "invalid size specification in"
+                       " effective address");
+            break;
+        }
+    }
+}
+
+/*
+ * when two or more decorators follow a register operand,
+ * consecutive decorators are parsed here.
+ * opmask and zeroing decorators can be placed in any order.
+ * e.g. zmm1 {k2}{z} or zmm2 {z}{k3}
+ * decorator(s) are placed at the end of an operand.
+ */
+static bool parse_braces(decoflags_t *decoflags)
+{
+    int i;
+    bool recover = false;
+
+    i = tokval.t_type;
+    do {
+        if (i == TOKEN_OPMASK) {
+            if (*decoflags & OPMASK_MASK) {
+                nasm_error(ERR_NONFATAL, "opmask k%"PRIu64" is already set",
+                           *decoflags & OPMASK_MASK);
+                *decoflags &= ~OPMASK_MASK;
+            }
+            *decoflags |= VAL_OPMASK(nasm_regvals[tokval.t_integer]);
+        } else if (i == TOKEN_DECORATOR) {
+            switch (tokval.t_integer) {
+            case BRC_Z:
+                /*
+                 * according to AVX512 spec, only zeroing/merging decorator
+                 * is supported with opmask
+                 */
+                *decoflags |= GEN_Z(0);
+                break;
+            default:
+                nasm_error(ERR_NONFATAL, "{%s} is not an expected decorator",
+                                         tokval.t_charptr);
+                break;
+            }
+        } else if (i == ',' || i == TOKEN_EOS){
+            break;
+        } else {
+            nasm_error(ERR_NONFATAL, "only a series of valid decorators"
+                                     " expected");
+            recover = true;
+            break;
+        }
+        i = stdscan(NULL, &tokval);
+    } while(1);
+
+    return recover;
+}
+
+static int parse_mref(operand *op, const expr *e)
+{
+    int b, i, s;        /* basereg, indexreg, scale */
+    int64_t o;          /* offset */
+
+    b = i = -1;
+    o = s = 0;
+
+    if (e->type && e->type <= EXPR_REG_END) {   /* this bit's a register */
+        bool is_gpr = is_class(REG_GPR,nasm_reg_flags[e->type]);
+
+        if (is_gpr && e->value == 1)
+            b = e->type;       /* It can be basereg */
+        else                   /* No, it has to be indexreg */
+            i = e->type, s = e->value;
+        e++;
+    }
+    if (e->type && e->type <= EXPR_REG_END) {   /* it's a 2nd register */
+        bool is_gpr = is_class(REG_GPR,nasm_reg_flags[e->type]);
+
+        if (b != -1)    /* If the first was the base, ... */
+            i = e->type, s = e->value;  /* second has to be indexreg */
+
+        else if (!is_gpr || e->value != 1) {
+            /* If both want to be index */
+            nasm_error(ERR_NONFATAL,
+                       "invalid effective address: two index registers");
+            return -1;
+        } else
+            b = e->type;
+        e++;
+    }
+    if (e->type != 0) { /* is there an offset? */
+        if (e->type <= EXPR_REG_END) {  /* in fact, is there an error? */
+            nasm_error(ERR_NONFATAL,
+                       "beroset-p-603-invalid effective address");
+            return -1;
+        } else {
+            if (e->type == EXPR_UNKNOWN) {
+                op->opflags |= OPFLAG_UNKNOWN;
+                o = 0;  /* doesn't matter what */
+                op->wrt = NO_SEG;     /* nor this */
+                op->segment = NO_SEG; /* or this */
+                while (e->type)
+                    e++;        /* go to the end of the line */
+            } else {
+                if (e->type == EXPR_SIMPLE) {
+                    o = e->value;
+                    e++;
+                }
+                if (e->type == EXPR_WRT) {
+                    op->wrt = e->value;
+                    e++;
+                } else
+                    op->wrt = NO_SEG;
+                /*
+                 * Look for a segment base type.
+                 */
+                if (e->type && e->type < EXPR_SEGBASE) {
+                    nasm_error(ERR_NONFATAL,
+                               "beroset-p-630-invalid effective address");
+                    return -1;
+                }
+                while (e->type && e->value == 0)
+                    e++;
+                if (e->type && e->value != 1) {
+                    nasm_error(ERR_NONFATAL,
+                               "beroset-p-637-invalid effective address");
+                    return -1;
+                }
+                if (e->type) {
+                    op->segment = e->type - EXPR_SEGBASE;
+                    e++;
+                } else
+                    op->segment = NO_SEG;
+                while (e->type && e->value == 0)
+                    e++;
+                if (e->type) {
+                    nasm_error(ERR_NONFATAL,
+                               "beroset-p-650-invalid effective address");
+                    return -1;
+                }
+            }
+        }
     } else {
-       /* Standard NASM compatible syntax */
-       switch ((int)tokval.t_integer) {
-       case S_NOSPLIT:
-           result->oprs[operand].eaflags |= EAF_TIMESTWO;
-           break;
-       case S_REL:
-           result->oprs[operand].eaflags |= EAF_REL;
-           break;
-       case S_ABS:
-           result->oprs[operand].eaflags |= EAF_ABS;
-           break;
-       case S_BYTE:
-           result->oprs[operand].disp_size = 8;
-           result->oprs[operand].eaflags |= EAF_BYTEOFFS;
-           break;
-       case P_A16:
-       case P_A32:
-       case P_A64:
-           if (result->prefixes[PPS_ASIZE] &&
-               result->prefixes[PPS_ASIZE] != tokval.t_integer)
-               nasm_error(ERR_NONFATAL,
-                     "conflicting address size specifications");
-           else
-               result->prefixes[PPS_ASIZE] = tokval.t_integer;
-           break;
-       case S_WORD:
-           result->oprs[operand].disp_size = 16;
-           result->oprs[operand].eaflags |= EAF_WORDOFFS;
-           break;
-       case S_DWORD:
-       case S_LONG:
-           result->oprs[operand].disp_size = 32;
-           result->oprs[operand].eaflags |= EAF_WORDOFFS;
-           break;
-       case S_QWORD:
-           result->oprs[operand].disp_size = 64;
-           result->oprs[operand].eaflags |= EAF_WORDOFFS;
-           break;
-       default:
-           nasm_error(ERR_NONFATAL, "invalid size specification in"
-                 " effective address");
-           break;
-       }
+        o = 0;
+        op->wrt = NO_SEG;
+        op->segment = NO_SEG;
+    }
+
+    if (e->type != 0) { /* there'd better be nothing left! */
+        nasm_error(ERR_NONFATAL,
+                   "beroset-p-663-invalid effective address");
+        return -1;
+    }
+
+    op->basereg = b;
+    op->indexreg = i;
+    op->scale = s;
+    op->offset = o;
+    return 0;
+}
+
+static void mref_set_optype(operand *op)
+{
+    int b = op->basereg;
+    int i = op->indexreg;
+    int s = op->scale;
+
+    /* It is memory, but it can match any r/m operand */
+    op->type |= MEMORY_ANY;
+
+    if (b == -1 && (i == -1 || s == 0)) {
+        int is_rel = globalbits == 64 &&
+            !(op->eaflags & EAF_ABS) &&
+            ((globalrel &&
+              !(op->eaflags & EAF_FSGS)) ||
+             (op->eaflags & EAF_REL));
+
+        op->type |= is_rel ? IP_REL : MEM_OFFS;
+    }
+
+    if (i != -1) {
+        opflags_t iclass = nasm_reg_flags[i];
+
+        if (is_class(XMMREG,iclass))
+            op->type |= XMEM;
+        else if (is_class(YMMREG,iclass))
+            op->type |= YMEM;
+        else if (is_class(ZMMREG,iclass))
+            op->type |= ZMEM;
     }
 }
 
 insn *parse_line(int pass, char *buffer, insn *result, ldfunc ldef)
 {
-    int operand;
-    int critical;
+    bool insn_is_label = false;
     struct eval_hints hints;
-    int j;
+    int opnum;
+    int critical;
     bool first;
-    bool insn_is_label = false;
     bool recover;
 
 restart_parse:
-    first = true;
-    result->forw_ref = false;
+    first               = true;
+    result->forw_ref    = false;
 
     stdscan_reset();
-    stdscan_bufptr = buffer;
+    stdscan_set(buffer);
     i = stdscan(NULL, &tokval);
 
-    result->label = NULL;       /* Assume no label */
-    result->eops = NULL;        /* must do this, whatever happens */
-    result->operands = 0;       /* must initialize this */
-
-    if (i == 0) {               /* blank line - ignore */
-        result->opcode = -1;    /* and no instruction either */
-        return result;
-    }
-    if (i != TOKEN_ID && i != TOKEN_INSN && i != TOKEN_PREFIX &&
-        (i != TOKEN_REG || (REG_SREG & ~nasm_reg_flags[tokval.t_integer]))) {
-        nasm_error(ERR_NONFATAL, "label or instruction expected"
-              " at start of line");
-        result->opcode = -1;
-        return result;
+    result->label       = NULL; /* Assume no label */
+    result->eops        = NULL; /* must do this, whatever happens */
+    result->operands    = 0;    /* must initialize this */
+    result->evex_rm     = 0;    /* Ensure EVEX rounding mode is reset */
+    result->evex_brerop = -1;   /* Reset EVEX broadcasting/ER op position */
+
+    /* Ignore blank lines */
+    if (i == TOKEN_EOS)
+        goto fail;
+
+    if (i != TOKEN_ID       &&
+        i != TOKEN_INSN     &&
+        i != TOKEN_PREFIX   &&
+        (i != TOKEN_REG || !IS_SREG(tokval.t_integer))) {
+        nasm_error(ERR_NONFATAL,
+                   "label or instruction expected at start of line");
+        goto fail;
     }
 
     if (i == TOKEN_ID || (insn_is_label && i == TOKEN_INSN)) {
         /* there's a label here */
-       first = false;
+        first = false;
         result->label = tokval.t_charptr;
         i = stdscan(NULL, &tokval);
         if (i == ':') {         /* skip over the optional colon */
@@ -248,19 +442,17 @@ restart_parse:
         }
     }
 
-    if (i == 0) {
-        result->opcode = -1;    /* this line contains just a label */
-        return result;
-    }
+    /* Just a label here */
+    if (i == TOKEN_EOS)
+        goto fail;
 
-    for (j = 0; j < MAXPREFIX; j++)
-       result->prefixes[j] = P_none;
+    nasm_build_assert(P_none != 0);
+    memset(result->prefixes, P_none, sizeof(result->prefixes));
     result->times = 1L;
 
     while (i == TOKEN_PREFIX ||
-           (i == TOKEN_REG && !(REG_SREG & ~nasm_reg_flags[tokval.t_integer])))
-    {
-       first = false;
+           (i == TOKEN_REG && IS_SREG(tokval.t_integer))) {
+        first = false;
 
         /*
          * Handle special case: the TIMES prefix.
@@ -269,13 +461,10 @@ restart_parse:
             expr *value;
 
             i = stdscan(NULL, &tokval);
-            value =
-                evaluate(stdscan, NULL, &tokval, NULL, pass0, nasm_error, NULL);
+            value = evaluate(stdscan, NULL, &tokval, NULL, pass0, nasm_error, NULL);
             i = tokval.t_type;
-            if (!value) {       /* but, error in evaluator */
-                result->opcode = -1;    /* unrecoverable parse error: */
-                return result;  /* ignore this instruction */
-            }
+            if (!value)                  /* Error in evaluator */
+                goto fail;
             if (!is_simple(value)) {
                 nasm_error(ERR_NONFATAL,
                       "non-constant argument supplied to TIMES");
@@ -283,33 +472,34 @@ restart_parse:
             } else {
                 result->times = value->value;
                 if (value->value < 0 && pass0 == 2) {
-                    nasm_error(ERR_NONFATAL, "TIMES value %d is negative",
+                    nasm_error(ERR_NONFATAL, "TIMES value %"PRId64" is negative",
                           value->value);
                     result->times = 0;
                 }
             }
         } else {
-           int slot = prefix_slot(tokval.t_integer);
-           if (result->prefixes[slot]) {
+            int slot = prefix_slot(tokval.t_integer);
+            if (result->prefixes[slot]) {
                if (result->prefixes[slot] == tokval.t_integer)
-                   nasm_error(ERR_WARNING,
-                     "instruction has redundant prefixes");
+                    nasm_error(ERR_WARNING | ERR_PASS1,
+                               "instruction has redundant prefixes");
                else
-                   nasm_error(ERR_NONFATAL,
-                     "instruction has conflicting prefixes");
-           }
-           result->prefixes[slot] = tokval.t_integer;
+                    nasm_error(ERR_NONFATAL,
+                               "instruction has conflicting prefixes");
+            }
+            result->prefixes[slot] = tokval.t_integer;
             i = stdscan(NULL, &tokval);
         }
     }
 
     if (i != TOKEN_INSN) {
-       int j;
-       enum prefixes pfx;
+        int j;
+        enum prefixes pfx;
 
-       for (j = 0; j < MAXPREFIX; j++)
-           if ((pfx = result->prefixes[j]) != P_none)
-               break;
+        for (j = 0; j < MAXPREFIX; j++) {
+            if ((pfx = result->prefixes[j]) != P_none)
+                break;
+        }
 
         if (i == 0 && pfx != P_none) {
             /*
@@ -317,16 +507,15 @@ restart_parse:
              * instruction. This is allowed: at this point we
              * invent a notional instruction of RESB 0.
              */
-            result->opcode = I_RESB;
-            result->operands = 1;
-            result->oprs[0].type = IMMEDIATE;
-            result->oprs[0].offset = 0L;
+            result->opcode          = I_RESB;
+            result->operands        = 1;
+            result->oprs[0].type    = IMMEDIATE;
+            result->oprs[0].offset  = 0L;
             result->oprs[0].segment = result->oprs[0].wrt = NO_SEG;
             return result;
         } else {
             nasm_error(ERR_NONFATAL, "parser: instruction expected");
-            result->opcode = -1;
-            return result;
+            goto fail;
         }
     }
 
@@ -349,146 +538,128 @@ restart_parse:
     if (result->opcode == I_DB || result->opcode == I_DW ||
         result->opcode == I_DD || result->opcode == I_DQ ||
         result->opcode == I_DT || result->opcode == I_DO ||
-       result->opcode == I_DY || result->opcode == I_INCBIN) {
+        result->opcode == I_DY || result->opcode == I_DZ ||
+        result->opcode == I_INCBIN) {
         extop *eop, **tail = &result->eops, **fixptr;
         int oper_num = 0;
-       int32_t sign;
+        int32_t sign;
 
         result->eops_float = false;
 
         /*
-         * Begin to read the DB/DW/DD/DQ/DT/DO/INCBIN operands.
+         * Begin to read the DB/DW/DD/DQ/DT/DO/DY/DZ/INCBIN operands.
          */
         while (1) {
             i = stdscan(NULL, &tokval);
-            if (i == 0)
+            if (i == TOKEN_EOS)
                 break;
-           else if (first && i == ':') {
-               insn_is_label = true;
-               goto restart_parse;
-           }
-           first = false;
+            else if (first && i == ':') {
+                insn_is_label = true;
+                goto restart_parse;
+            }
+            first = false;
             fixptr = tail;
             eop = *tail = nasm_malloc(sizeof(extop));
             tail = &eop->next;
             eop->next = NULL;
             eop->type = EOT_NOTHING;
             oper_num++;
-           sign = +1;
+            sign = +1;
 
-           /* is_comma_next() here is to distinguish this from
-              a string used as part of an expression... */
+            /*
+             * is_comma_next() here is to distinguish this from
+             * a string used as part of an expression...
+             */
             if (i == TOKEN_STR && is_comma_next()) {
-                eop->type = EOT_DB_STRING;
-                eop->stringval = tokval.t_charptr;
-                eop->stringlen = tokval.t_inttwo;
+                eop->type       = EOT_DB_STRING;
+                eop->stringval  = tokval.t_charptr;
+                eop->stringlen  = tokval.t_inttwo;
                 i = stdscan(NULL, &tokval);     /* eat the comma */
-           } else if (i == TOKEN_STRFUNC) {
-               bool parens = false;
-               const char *funcname = tokval.t_charptr;
-               enum strfunc func = tokval.t_integer;
-               i = stdscan(NULL, &tokval);
-               if (i == '(') {
-                   parens = true;
-                   i = stdscan(NULL, &tokval);
-               }
-               if (i != TOKEN_STR) {
-                   nasm_error(ERR_NONFATAL,
-                         "%s must be followed by a string constant",
-                         funcname);
-                       eop->type = EOT_NOTHING;
-               } else {
-                   eop->type = EOT_DB_STRING_FREE;
-                   eop->stringlen =
-                       string_transform(tokval.t_charptr, tokval.t_inttwo,
-                                        &eop->stringval, func);
-                   if (eop->stringlen == (size_t)-1) {
-                       nasm_error(ERR_NONFATAL, "invalid string for transform");
-                       eop->type = EOT_NOTHING;
-                   }
-               }
-               if (parens && i && i != ')') {
-                   i = stdscan(NULL, &tokval);
-                   if (i != ')') {
-                       nasm_error(ERR_NONFATAL, "unterminated %s function",
-                             funcname);
-                   }
-               }
-               if (i && i != ',')
-                   i = stdscan(NULL, &tokval);
-           } else if (i == '-' || i == '+') {
-               char *save = stdscan_bufptr;
-               int token = i;
-               sign = (i == '-') ? -1 : 1;
-               i = stdscan(NULL, &tokval);
-               if (i != TOKEN_FLOAT) {
-                   stdscan_bufptr = save;
-                   i = tokval.t_type = token;
-                   goto is_expression;
-               } else {
-                   goto is_float;
-               }
+            } else if (i == TOKEN_STRFUNC) {
+                bool parens = false;
+                const char *funcname = tokval.t_charptr;
+                enum strfunc func = tokval.t_integer;
+                i = stdscan(NULL, &tokval);
+                if (i == '(') {
+                    parens = true;
+                    i = stdscan(NULL, &tokval);
+                }
+                if (i != TOKEN_STR) {
+                    nasm_error(ERR_NONFATAL,
+                               "%s must be followed by a string constant",
+                               funcname);
+                        eop->type = EOT_NOTHING;
+                } else {
+                    eop->type = EOT_DB_STRING_FREE;
+                    eop->stringlen =
+                        string_transform(tokval.t_charptr, tokval.t_inttwo,
+                                         &eop->stringval, func);
+                    if (eop->stringlen == (size_t)-1) {
+                        nasm_error(ERR_NONFATAL, "invalid string for transform");
+                        eop->type = EOT_NOTHING;
+                    }
+                }
+                if (parens && i && i != ')') {
+                    i = stdscan(NULL, &tokval);
+                    if (i != ')') {
+                        nasm_error(ERR_NONFATAL, "unterminated %s function",
+                                   funcname);
+                    }
+                }
+                if (i && i != ',')
+                    i = stdscan(NULL, &tokval);
+            } else if (i == '-' || i == '+') {
+                char *save = stdscan_get();
+                int token = i;
+                sign = (i == '-') ? -1 : 1;
+                i = stdscan(NULL, &tokval);
+                if (i != TOKEN_FLOAT) {
+                    stdscan_set(save);
+                    i = tokval.t_type = token;
+                    goto is_expression;
+                } else {
+                    goto is_float;
+                }
             } else if (i == TOKEN_FLOAT) {
-           is_float:
-               eop->type = EOT_DB_STRING;
-               result->eops_float = true;
-               switch (result->opcode) {
-               case I_DB:
-                   eop->stringlen = 1;
-                   break;
-               case I_DW:
-                   eop->stringlen = 2;
-                   break;
-               case I_DD:
-                   eop->stringlen = 4;
-                   break;
-               case I_DQ:
-                   eop->stringlen = 8;
-                   break;
-               case I_DT:
-                   eop->stringlen = 10;
-                   break;
-               case I_DO:
-                   eop->stringlen = 16;
-                   break;
-               case I_DY:
-                   nasm_error(ERR_NONFATAL, "floating-point constant"
-                         " encountered in DY instruction");
-                   eop->stringlen = 0;
-                   break;
-               default:
-                   nasm_error(ERR_NONFATAL, "floating-point constant"
-                         " encountered in unknown instruction");
-                   /*
-                    * fix suggested by Pedro Gimeno... original line
-                    * was:
-                    * eop->type = EOT_NOTHING;
-                    */
-                   eop->stringlen = 0;
-                   break;
-               }
-               eop = nasm_realloc(eop, sizeof(extop) + eop->stringlen);
-               tail = &eop->next;
-               *fixptr = eop;
-               eop->stringval = (char *)eop + sizeof(extop);
-               if (!eop->stringlen ||
-                   !float_const(tokval.t_charptr, sign,
-                                (uint8_t *)eop->stringval,
-                                eop->stringlen, nasm_error))
-                   eop->type = EOT_NOTHING;
-               i = stdscan(NULL, &tokval); /* eat the comma */
-           } else {
-               /* anything else, assume it is an expression */
+is_float:
+                eop->type = EOT_DB_STRING;
+                result->eops_float = true;
+
+                eop->stringlen = idata_bytes(result->opcode);
+                if (eop->stringlen > 16) {
+                    nasm_error(ERR_NONFATAL, "floating-point constant"
+                               " encountered in DY or DZ instruction");
+                    eop->stringlen = 0;
+                } else if (eop->stringlen < 1) {
+                    nasm_error(ERR_NONFATAL, "floating-point constant"
+                               " encountered in unknown instruction");
+                    /*
+                     * fix suggested by Pedro Gimeno... original line was:
+                     * eop->type = EOT_NOTHING;
+                     */
+                    eop->stringlen = 0;
+                }
+
+                eop = nasm_realloc(eop, sizeof(extop) + eop->stringlen);
+                tail = &eop->next;
+                *fixptr = eop;
+                eop->stringval = (char *)eop + sizeof(extop);
+                if (!eop->stringlen ||
+                    !float_const(tokval.t_charptr, sign,
+                                 (uint8_t *)eop->stringval,
+                                 eop->stringlen, nasm_error))
+                    eop->type = EOT_NOTHING;
+                i = stdscan(NULL, &tokval); /* eat the comma */
+            } else {
+                /* anything else, assume it is an expression */
                 expr *value;
 
-           is_expression:
+is_expression:
                 value = evaluate(stdscan, NULL, &tokval, NULL,
                                  critical, nasm_error, NULL);
                 i = tokval.t_type;
-                if (!value) {   /* error in evaluator */
-                    result->opcode = -1;        /* unrecoverable parse error: */
-                    return result;      /* ignore this instruction */
-                }
+                if (!value)                  /* Error in evaluator */
+                    goto fail;
                 if (is_unknown(value)) {
                     eop->type = EOT_DB_NUMBER;
                     eop->offset = 0;    /* doesn't matter what we put */
@@ -511,13 +682,12 @@ restart_parse:
              * arguments. However, we'd better check first that it
              * _is_ a comma.
              */
-            if (i == 0)         /* also could be EOL */
+            if (i == TOKEN_EOS) /* also could be EOL */
                 break;
             if (i != ',') {
                 nasm_error(ERR_NONFATAL, "comma expected after operand %d",
-                      oper_num);
-                result->opcode = -1;    /* unrecoverable parse error: */
-                return result;  /* ignore this instruction */
+                           oper_num);
+                goto fail;
             }
         }
 
@@ -531,24 +701,23 @@ restart_parse:
                 nasm_error(ERR_NONFATAL, "`incbin' expects a file name");
             else if (result->eops->next &&
                      result->eops->next->type != EOT_DB_NUMBER)
-                nasm_error(ERR_NONFATAL, "`incbin': second parameter is",
-                      " non-numeric");
+                nasm_error(ERR_NONFATAL, "`incbin': second parameter is"
+                           " non-numeric");
             else if (result->eops->next && result->eops->next->next &&
                      result->eops->next->next->type != EOT_DB_NUMBER)
-                nasm_error(ERR_NONFATAL, "`incbin': third parameter is",
-                      " non-numeric");
+                nasm_error(ERR_NONFATAL, "`incbin': third parameter is"
+                           " non-numeric");
             else if (result->eops->next && result->eops->next->next &&
                      result->eops->next->next->next)
                 nasm_error(ERR_NONFATAL,
-                      "`incbin': more than three parameters");
+                           "`incbin': more than three parameters");
             else
                 return result;
             /*
              * If we reach here, one of the above errors happened.
              * Throw the instruction away.
              */
-            result->opcode = -1;
-            return result;
+            goto fail;
         } else /* DB ... */ if (oper_num == 0)
             nasm_error(ERR_WARNING | ERR_PASS1,
                   "no operand for data declaration");
@@ -558,80 +727,91 @@ restart_parse:
         return result;
     }
 
-    /* right. Now we begin to parse the operands. There may be up to four
-     * of these, separated by commas, and terminated by a zero token. */
+    /*
+     * Now we begin to parse the operands. There may be up to four
+     * of these, separated by commas, and terminated by a zero token.
+     */
 
-    for (operand = 0; operand < MAX_OPERANDS; operand++) {
-       expr *value;            /* used most of the time */
-        int mref;               /* is this going to be a memory ref? */
-        int bracket;            /* is it a [] mref, or a & mref? */
+    for (opnum = 0; opnum < MAX_OPERANDS; opnum++) {
+        operand *op = &result->oprs[opnum];
+        expr *value;            /* used most of the time */
+        bool mref;              /* is this going to be a memory ref? */
+        bool bracket;           /* is it a [] mref, or a & mref? */
+        bool mib;               /* compound (mib) mref? */
         int setsize = 0;
+        decoflags_t brace_flags = 0;    /* flags for decorators in braces */
 
-        result->oprs[operand].disp_size = 0;    /* have to zero this whatever */
-        result->oprs[operand].eaflags = 0;      /* and this */
-        result->oprs[operand].opflags = 0;
+        op->disp_size = 0;    /* have to zero this whatever */
+        op->eaflags   = 0;    /* and this */
+        op->opflags   = 0;
+        op->decoflags = 0;
 
         i = stdscan(NULL, &tokval);
-        if (i == 0)
+        if (i == TOKEN_EOS)
             break;              /* end of operands: get out of here */
-       else if (first && i == ':') {
-           insn_is_label = true;
-           goto restart_parse;
-       }
-       first = false;
-        result->oprs[operand].type = 0; /* so far, no override */
+        else if (first && i == ':') {
+            insn_is_label = true;
+            goto restart_parse;
+        }
+        first = false;
+        op->type = 0; /* so far, no override */
         while (i == TOKEN_SPECIAL) {    /* size specifiers */
             switch ((int)tokval.t_integer) {
             case S_BYTE:
                 if (!setsize)   /* we want to use only the first */
-                    result->oprs[operand].type |= BITS8;
+                    op->type |= BITS8;
                 setsize = 1;
                 break;
             case S_WORD:
                 if (!setsize)
-                    result->oprs[operand].type |= BITS16;
+                    op->type |= BITS16;
                 setsize = 1;
                 break;
             case S_DWORD:
             case S_LONG:
                 if (!setsize)
-                    result->oprs[operand].type |= BITS32;
+                    op->type |= BITS32;
                 setsize = 1;
                 break;
             case S_QWORD:
                 if (!setsize)
-                    result->oprs[operand].type |= BITS64;
+                    op->type |= BITS64;
                 setsize = 1;
                 break;
             case S_TWORD:
                 if (!setsize)
-                    result->oprs[operand].type |= BITS80;
+                    op->type |= BITS80;
                 setsize = 1;
                 break;
             case S_OWORD:
                 if (!setsize)
-                    result->oprs[operand].type |= BITS128;
+                    op->type |= BITS128;
                 setsize = 1;
                 break;
             case S_YWORD:
                 if (!setsize)
-                    result->oprs[operand].type |= BITS256;
+                    op->type |= BITS256;
+                setsize = 1;
+                break;
+            case S_ZWORD:
+                if (!setsize)
+                    op->type |= BITS512;
                 setsize = 1;
                 break;
             case S_TO:
-                result->oprs[operand].type |= TO;
+                op->type |= TO;
                 break;
             case S_STRICT:
-                result->oprs[operand].type |= STRICT;
+                op->type |= STRICT;
                 break;
             case S_FAR:
-                result->oprs[operand].type |= FAR;
+                op->type |= FAR;
                 break;
             case S_NEAR:
-                result->oprs[operand].type |= NEAR;
+                op->type |= NEAR;
                 break;
             case S_SHORT:
-                result->oprs[operand].type |= SHORT;
+                op->type |= SHORT;
                 break;
             default:
                 nasm_error(ERR_NONFATAL, "invalid operand size specification");
@@ -644,63 +824,117 @@ restart_parse:
             bracket = (i == '[');
             i = stdscan(NULL, &tokval); /* then skip the colon */
             while (i == TOKEN_SPECIAL || i == TOKEN_PREFIX) {
-               process_size_override(result, operand);
+                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 */
         }
 
-        if ((result->oprs[operand].type & FAR) && !mref &&
+        if ((op->type & FAR) && !mref &&
             result->opcode != I_JMP && result->opcode != I_CALL) {
             nasm_error(ERR_NONFATAL, "invalid use of FAR operand specifier");
         }
 
         value = evaluate(stdscan, NULL, &tokval,
-                         &result->oprs[operand].opflags,
+                         &op->opflags,
                          critical, nasm_error, &hints);
         i = tokval.t_type;
-        if (result->oprs[operand].opflags & OPFLAG_FORWARD) {
+        if (op->opflags & OPFLAG_FORWARD) {
             result->forw_ref = true;
         }
-        if (!value) {           /* nasm_error in evaluator */
-            result->opcode = -1;        /* unrecoverable parse error: */
-            return result;      /* ignore this instruction */
-        }
+        if (!value)                  /* Error in evaluator */
+            goto fail;
         if (i == ':' && mref) { /* it was seg:offset */
             /*
              * Process the segment override.
              */
-            if (value[1].type != 0 || value->value != 1 ||
-                REG_SREG & ~nasm_reg_flags[value->type])
+            if (value[1].type   != 0    ||
+                value->value    != 1    ||
+                !IS_SREG(value->type))
                 nasm_error(ERR_NONFATAL, "invalid segment override");
             else if (result->prefixes[PPS_SEG])
                 nasm_error(ERR_NONFATAL,
                       "instruction has conflicting segment overrides");
             else {
-               result->prefixes[PPS_SEG] = value->type;
-               if (!(REG_FSGS & ~nasm_reg_flags[value->type]))
-                   result->oprs[operand].eaflags |= EAF_FSGS;
-           }
+                result->prefixes[PPS_SEG] = value->type;
+                if (IS_FSGS(value->type))
+                    op->eaflags |= EAF_FSGS;
+            }
 
             i = stdscan(NULL, &tokval); /* then skip the colon */
             while (i == TOKEN_SPECIAL || i == TOKEN_PREFIX) {
-               process_size_override(result, operand);
+                process_size_override(result, op);
                 i = stdscan(NULL, &tokval);
             }
             value = evaluate(stdscan, NULL, &tokval,
-                             &result->oprs[operand].opflags,
+                             &op->opflags,
                              critical, nasm_error, &hints);
             i = tokval.t_type;
-            if (result->oprs[operand].opflags & OPFLAG_FORWARD) {
+            if (op->opflags & OPFLAG_FORWARD) {
                 result->forw_ref = true;
             }
             /* and get the offset */
-            if (!value) {       /* but, error in evaluator */
-                result->opcode = -1;    /* unrecoverable parse error: */
-                return result;  /* ignore this instruction */
+            if (!value)                  /* Error in evaluator */
+                goto fail;
+        }
+
+        mib = false;
+        if (mref && bracket && i == ',') {
+            /* [seg:base+offset,index*scale] syntax (mib) */
+
+            operand o1, o2;     /* Partial operands */
+
+            if (parse_mref(&o1, value))
+                goto fail;
+
+            i = stdscan(NULL, &tokval); /* Eat comma */
+            value = evaluate(stdscan, NULL, &tokval, &op->opflags,
+                             critical, nasm_error, &hints);
+            i = tokval.t_type;
+
+            if (parse_mref(&o2, value))
+                goto fail;
+
+            if (o2.basereg != -1 && o2.indexreg == -1) {
+                o2.indexreg = o2.basereg;
+                o2.scale = 1;
+                o2.basereg = -1;
+            }
+
+            if (o1.indexreg != -1 || o2.basereg != -1 || o2.offset != 0 ||
+                o2.segment != NO_SEG || o2.wrt != NO_SEG) {
+                nasm_error(ERR_NONFATAL, "invalid mib expression");
+                goto fail;
+            }
+
+            op->basereg = o1.basereg;
+            op->indexreg = o2.indexreg;
+            op->scale = o2.scale;
+            op->offset = o1.offset;
+            op->segment = o1.segment;
+            op->wrt = o1.wrt;
+
+            if (op->basereg != -1) {
+                op->hintbase = op->basereg;
+                op->hinttype = EAH_MAKEBASE;
+            } else if (op->indexreg != -1) {
+                op->hintbase = op->indexreg;
+                op->hinttype = EAH_NOTBASE;
+            } else {
+                op->hintbase = -1;
+                op->hinttype = EAH_NOHINT;
             }
+
+            mib = true;
         }
 
         recover = false;
@@ -710,17 +944,41 @@ restart_parse:
                 recover = true;
             } else {            /* we got the required ] */
                 i = stdscan(NULL, &tokval);
+                if ((i == TOKEN_DECORATOR) || (i == TOKEN_OPMASK)) {
+                    /*
+                     * according to AVX512 spec, broacast or opmask decorator
+                     * is expected for memory reference operands
+                     */
+                    if (tokval.t_flag & TFLAG_BRDCAST) {
+                        brace_flags |= GEN_BRDCAST(0) |
+                                       VAL_BRNUM(tokval.t_integer - BRC_1TO8);
+                        i = stdscan(NULL, &tokval);
+                    } else if (i == TOKEN_OPMASK) {
+                        brace_flags |= VAL_OPMASK(nasm_regvals[tokval.t_integer]);
+                        i = stdscan(NULL, &tokval);
+                    } else {
+                        nasm_error(ERR_NONFATAL, "broadcast or opmask "
+                                   "decorator expected inside braces");
+                        recover = true;
+                    }
+                }
+
                 if (i != 0 && i != ',') {
                     nasm_error(ERR_NONFATAL, "comma or end of line expected");
                     recover = true;
                 }
             }
         } else {                /* immediate operand */
-            if (i != 0 && i != ',' && i != ':') {
-                nasm_error(ERR_NONFATAL, "comma, colon or end of line expected");
+            if (i != 0 && i != ',' && i != ':' &&
+                i != TOKEN_DECORATOR && i != TOKEN_OPMASK) {
+                nasm_error(ERR_NONFATAL, "comma, colon, decorator or end of "
+                                         "line expected after operand");
                 recover = true;
             } else if (i == ':') {
-                result->oprs[operand].type |= COLON;
+                op->type |= COLON;
+            } else if (i == TOKEN_DECORATOR || i == TOKEN_OPMASK) {
+                /* parse opmask (and zeroing) after an operand */
+                recover = parse_braces(&brace_flags);
             }
         }
         if (recover) {
@@ -729,166 +987,82 @@ restart_parse:
             } while (i != 0 && i != ',');
         }
 
-        /* now convert the exprs returned from evaluate() into operand
-         * descriptions... */
+        /*
+         * now convert the exprs returned from evaluate()
+         * into operand descriptions...
+         */
+        op->decoflags |= brace_flags;
 
         if (mref) {             /* it's a memory reference */
-            expr *e = value;
-            int b, i, s;        /* basereg, indexreg, scale */
-            int64_t o;             /* offset */
-
-            b = i = -1, o = s = 0;
-            result->oprs[operand].hintbase = hints.base;
-            result->oprs[operand].hinttype = hints.type;
-
-            if (e->type && e->type <= EXPR_REG_END) {   /* this bit's a register */
-                if (e->value == 1)      /* in fact it can be basereg */
-                    b = e->type;
-                else            /* no, it has to be indexreg */
-                    i = e->type, s = e->value;
-                e++;
+            /* A mib reference was fully parsed already */
+            if (!mib) {
+                if (parse_mref(op, value))
+                    goto fail;
+                op->hintbase = hints.base;
+                op->hinttype = hints.type;
             }
-            if (e->type && e->type <= EXPR_REG_END) {   /* it's a 2nd register */
-                if (b != -1)    /* If the first was the base, ... */
-                    i = e->type, s = e->value;  /* second has to be indexreg */
-
-                else if (e->value != 1) {       /* If both want to be index */
-                    nasm_error(ERR_NONFATAL,
-                          "beroset-p-592-invalid effective address");
-                    result->opcode = -1;
-                    return result;
-                } else
-                    b = e->type;
-                e++;
-            }
-            if (e->type != 0) { /* is there an offset? */
-                if (e->type <= EXPR_REG_END) {  /* in fact, is there an error? */
-                    nasm_error(ERR_NONFATAL,
-                          "beroset-p-603-invalid effective address");
-                    result->opcode = -1;
-                    return result;
-                } else {
-                    if (e->type == EXPR_UNKNOWN) {
-                        result->oprs[operand].opflags |= OPFLAG_UNKNOWN;
-                        o = 0;  /* doesn't matter what */
-                        result->oprs[operand].wrt = NO_SEG;     /* nor this */
-                        result->oprs[operand].segment = NO_SEG; /* or this */
-                        while (e->type)
-                            e++;        /* go to the end of the line */
-                    } else {
-                        if (e->type == EXPR_SIMPLE) {
-                            o = e->value;
-                            e++;
-                        }
-                        if (e->type == EXPR_WRT) {
-                            result->oprs[operand].wrt = e->value;
-                            e++;
-                        } else
-                            result->oprs[operand].wrt = NO_SEG;
-                        /*
-                         * Look for a segment base type.
-                         */
-                        if (e->type && e->type < EXPR_SEGBASE) {
-                            nasm_error(ERR_NONFATAL,
-                                  "beroset-p-630-invalid effective address");
-                            result->opcode = -1;
-                            return result;
-                        }
-                        while (e->type && e->value == 0)
-                            e++;
-                        if (e->type && e->value != 1) {
-                            nasm_error(ERR_NONFATAL,
-                                  "beroset-p-637-invalid effective address");
-                            result->opcode = -1;
-                            return result;
-                        }
-                        if (e->type) {
-                            result->oprs[operand].segment =
-                                e->type - EXPR_SEGBASE;
-                            e++;
-                        } else
-                            result->oprs[operand].segment = NO_SEG;
-                        while (e->type && e->value == 0)
-                            e++;
-                        if (e->type) {
-                            nasm_error(ERR_NONFATAL,
-                                  "beroset-p-650-invalid effective address");
-                            result->opcode = -1;
-                            return result;
-                        }
-                    }
-                }
-            } else {
-                o = 0;
-                result->oprs[operand].wrt = NO_SEG;
-                result->oprs[operand].segment = NO_SEG;
-            }
-
-            if (e->type != 0) { /* there'd better be nothing left! */
-                nasm_error(ERR_NONFATAL,
-                      "beroset-p-663-invalid effective address");
-                result->opcode = -1;
-                return result;
-            }
-
-           /* It is memory, but it can match any r/m operand */
-            result->oprs[operand].type |= MEMORY_ANY;
-
-           if (b == -1 && (i == -1 || s == 0)) {
-               int is_rel = globalbits == 64 &&
-                   !(result->oprs[operand].eaflags & EAF_ABS) &&
-                   ((globalrel &&
-                     !(result->oprs[operand].eaflags & EAF_FSGS)) ||
-                    (result->oprs[operand].eaflags & EAF_REL));
-
-               result->oprs[operand].type |= is_rel ? IP_REL : MEM_OFFS;
-           }
-            result->oprs[operand].basereg = b;
-            result->oprs[operand].indexreg = i;
-            result->oprs[operand].scale = s;
-            result->oprs[operand].offset = o;
+            mref_set_optype(op);
         } else {                /* it's not a memory reference */
             if (is_just_unknown(value)) {       /* it's immediate but unknown */
-                result->oprs[operand].type |= IMMEDIATE;
-                result->oprs[operand].opflags |= OPFLAG_UNKNOWN;
-                result->oprs[operand].offset = 0;       /* don't care */
-                result->oprs[operand].segment = NO_SEG; /* don't care again */
-                result->oprs[operand].wrt = NO_SEG;     /* still don't care */
-
-                if(optimizing >= 0 && !(result->oprs[operand].type & STRICT))
-                {
+                op->type      |= IMMEDIATE;
+                op->opflags   |= OPFLAG_UNKNOWN;
+                op->offset    = 0;        /* don't care */
+                op->segment   = NO_SEG;   /* don't care again */
+                op->wrt       = NO_SEG;   /* still don't care */
+
+                if(optimizing >= 0 && !(op->type & STRICT)) {
                     /* Be optimistic */
-                    result->oprs[operand].type |= SBYTE16 | SBYTE32 | SBYTE64;
+                    op->type |=
+                        UNITY | SBYTEWORD | SBYTEDWORD | UDWORD | SDWORD;
                 }
             } else if (is_reloc(value)) {       /* it's immediate */
-                result->oprs[operand].type |= IMMEDIATE;
-                result->oprs[operand].offset = reloc_value(value);
-                result->oprs[operand].segment = reloc_seg(value);
-                result->oprs[operand].wrt = reloc_wrt(value);
+                op->type      |= IMMEDIATE;
+                op->offset    = reloc_value(value);
+                op->segment   = reloc_seg(value);
+                op->wrt       = reloc_wrt(value);
+
                 if (is_simple(value)) {
-                    if (reloc_value(value) == 1)
-                        result->oprs[operand].type |= UNITY;
+                    uint64_t n = reloc_value(value);
+                    if (n == 1)
+                        op->type |= UNITY;
                     if (optimizing >= 0 &&
-                        !(result->oprs[operand].type & STRICT)) {
-                       int64_t v64 = reloc_value(value);
-                       int32_t v32 = (int32_t)v64;
-                       int16_t v16 = (int16_t)v32;
-
-                       if (v64 >= -128 && v64 <= 127)
-                            result->oprs[operand].type |= SBYTE64;
-                       if (v32 >= -128 && v32 <= 127)
-                            result->oprs[operand].type |= SBYTE32;
-                       if (v16 >= -128 && v16 <= 127)
-                            result->oprs[operand].type |= SBYTE16;
+                        !(op->type & STRICT)) {
+                        if ((uint32_t) (n + 128) <= 255)
+                            op->type |= SBYTEDWORD;
+                        if ((uint16_t) (n + 128) <= 255)
+                            op->type |= SBYTEWORD;
+                        if (n <= 0xFFFFFFFF)
+                            op->type |= UDWORD;
+                        if (n + 0x80000000 <= 0xFFFFFFFF)
+                            op->type |= SDWORD;
                     }
                 }
+            } else if(value->type == EXPR_RDSAE) {
+                /*
+                 * it's not an operand but a rounding or SAE decorator.
+                 * put the decorator information in the (opflag_t) type field
+                 * of previous operand.
+                 */
+                opnum--; op--;
+                switch (value->value) {
+                case BRC_RN:
+                case BRC_RU:
+                case BRC_RD:
+                case BRC_RZ:
+                case BRC_SAE:
+                    op->decoflags |= (value->value == BRC_SAE ? SAE : ER);
+                    result->evex_rm = value->value;
+                    break;
+                default:
+                    nasm_error(ERR_NONFATAL, "invalid decorator");
+                    break;
+                }
             } else {            /* it's a register */
-               unsigned int rs;
+                opflags_t rs;
 
                 if (value->type >= EXPR_SIMPLE || value->value != 1) {
                     nasm_error(ERR_NONFATAL, "invalid operand type");
-                    result->opcode = -1;
-                    return result;
+                    goto fail;
                 }
 
                 /*
@@ -897,40 +1071,44 @@ restart_parse:
                 for (i = 1; value[i].type; i++)
                     if (value[i].value) {
                         nasm_error(ERR_NONFATAL, "invalid operand type");
-                        result->opcode = -1;
-                        return result;
+                        goto fail;
                     }
 
                 /* clear overrides, except TO which applies to FPU regs */
-                if (result->oprs[operand].type & ~TO) {
+                if (op->type & ~TO) {
                     /*
                      * we want to produce a warning iff the specified size
                      * is different from the register size
                      */
-                    rs = result->oprs[operand].type & SIZE_MASK;
+                    rs = op->type & SIZE_MASK;
                 } else
                     rs = 0;
 
-                result->oprs[operand].type &= TO;
-                result->oprs[operand].type |= REGISTER;
-                result->oprs[operand].type |= nasm_reg_flags[value->type];
-                result->oprs[operand].basereg = value->type;
+                op->type      &= TO;
+                op->type      |= REGISTER;
+                op->type      |= nasm_reg_flags[value->type];
+                op->decoflags |= brace_flags;
+                op->basereg   = value->type;
 
-                if (rs && (result->oprs[operand].type & SIZE_MASK) != rs)
+                if (rs && (op->type & SIZE_MASK) != rs)
                     nasm_error(ERR_WARNING | ERR_PASS1,
                           "register size specification ignored");
             }
         }
+
+        /* remember the position of operand having broadcasting/ER mode */
+        if (op->decoflags & (BRDCAST_MASK | ER | SAE))
+            result->evex_brerop = opnum;
     }
 
-    result->operands = operand; /* set operand count */
+    result->operands = opnum; /* set operand count */
 
-/* clear remaining operands */
-while (operand < MAX_OPERANDS)
-    result->oprs[operand++].type = 0;
+    /* clear remaining operands */
+    while (opnum < MAX_OPERANDS)
+        result->oprs[opnum++].type = 0;
 
     /*
-     * Transform RESW, RESD, RESQ, REST, RESO, RESY into RESB.
+     * Transform RESW, RESD, RESQ, REST, RESO, RESY, RESZ into RESB.
      */
     switch (result->opcode) {
     case I_RESW:
@@ -957,22 +1135,31 @@ while (operand < MAX_OPERANDS)
         result->opcode = I_RESB;
         result->oprs[0].offset *= 32;
         break;
+    case I_RESZ:
+        result->opcode = I_RESB;
+        result->oprs[0].offset *= 64;
+        break;
     default:
-       break;
+        break;
     }
 
     return result;
+
+fail:
+    result->opcode = I_none;
+    return result;
 }
 
 static int is_comma_next(void)
 {
+    struct tokenval tv;
     char *p;
     int i;
-    struct tokenval tv;
 
-    p = stdscan_bufptr;
+    p = stdscan_get();
     i = stdscan(NULL, &tv);
-    stdscan_bufptr = p;
+    stdscan_set(p);
+
     return (i == ',' || i == ';' || !i);
 }
 
@@ -982,8 +1169,8 @@ void cleanup_insn(insn * i)
 
     while ((e = i->eops)) {
         i->eops = e->next;
-       if (e->type == EOT_DB_STRING_FREE)
-           nasm_free(e->stringval);
+        if (e->type == EOT_DB_STRING_FREE)
+            nasm_free(e->stringval);
         nasm_free(e);
     }
 }