AVX-512: Remember the position of operand with broadcast or embedded rounding
authorJin Kyu Song <jin.kyu.song@intel.com>
Thu, 29 Aug 2013 02:15:23 +0000 (19:15 -0700)
committerCyrill Gorcunov <gorcunov@gmail.com>
Thu, 29 Aug 2013 06:03:02 +0000 (10:03 +0400)
It was not so straight forward to find the postion of operand that has
a broadcasting, embedded rounding mode or SAE (Suppress All Exceptions)
decorator out from operands types or bytecode.
Remebering the postion of the operand of interest in the parser reduces
the burden that assembler looks through the operands.

Signed-off-by: Jin Kyu Song <jin.kyu.song@intel.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
assemble.c
nasm.h
parser.c

index b0d4571..d847d37 100644 (file)
@@ -1150,7 +1150,7 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
                 int rfield;
                 opflags_t rflags;
                 struct operand *opy = &ins->oprs[op2];
-                struct operand *oplast;
+                struct operand *op_er_sae;
 
                 ea_data.rex = 0;           /* Ensure ea.REX is initially 0 */
 
@@ -1158,24 +1158,23 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
                     /* pick rfield from operand b (opx) */
                     rflags = regflag(opx);
                     rfield = nasm_regvals[opx->basereg];
-                    /* find the last SIMD operand where ER decorator resides */
-                    oplast = &ins->oprs[op1 > op2 ? op1 : op2];
-                    while (oplast && is_class(REG_CLASS_GPR, oplast->type))
-                        oplast--;
                 } else {
                     rflags = 0;
                     rfield = c & 7;
-                    oplast = opy;
                 }
 
-                if (oplast->decoflags & ER) {
+                /* EVEX.b1 : evex_brerop contains the operand position */
+                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;
                 } else {
                     /* set EVEX.L'L (vector length) */
                     ins->evex_p[2] |= ((ins->vex_wlp << (5 - 2)) & EVEX_P2LL);
-                    if ((oplast->decoflags & SAE) ||
+                    if ((op_er_sae && (op_er_sae->decoflags & SAE)) ||
                         (opy->decoflags & BRDCAST_MASK)) {
                         /* set EVEX.b */
                         ins->evex_p[2] |= EVEX_P2B;
@@ -1924,16 +1923,9 @@ static enum match_result find_match(const struct itemplate **tempp,
     enum match_result m, merr;
     opflags_t xsizeflags[MAX_OPERANDS];
     bool opsizemissing = false;
-    int8_t broadcast = -1;
+    int8_t broadcast = instruction->evex_brerop;
     int i;
 
-    /* find the position of broadcasting operand */
-    for (i = 0; i < instruction->operands; i++)
-        if (instruction->oprs[i].decoflags & BRDCAST_MASK) {
-            broadcast = i;
-            break;
-        }
-
     /* broadcasting uses a different data element size */
     for (i = 0; i < instruction->operands; i++)
         if (i == broadcast)
diff --git a/nasm.h b/nasm.h
index 72986ee..8d61748 100644 (file)
--- a/nasm.h
+++ b/nasm.h
@@ -690,6 +690,7 @@ typedef struct insn { /* an instruction itself */
                                             /* EVEX.P2: [z,L'L,b,V',aaa] */
     enum ttypes     evex_tuple;             /* Tuple type for compressed Disp8*N */
     int             evex_rm;                /* static rounding mode for AVX3 (EVEX) */
+    int8_t          evex_brerop;            /* BR/ER/SAE operand position */
 } insn;
 
 enum geninfo { GI_SWITCH };
index 585abe2..1b08657 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -262,6 +262,8 @@ restart_parse:
     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) {
@@ -1034,6 +1036,10 @@ is_expression:
                           "register size specification ignored");
             }
         }
+
+        /* remember the position of operand having broadcasting/ER mode */
+        if (result->oprs[operand].decoflags & (BRDCAST_MASK | ER | SAE))
+            result->evex_brerop = operand;
     }
 
     result->operands = operand; /* set operand count */