summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--assemble.c24
-rw-r--r--nasm.h1
-rw-r--r--parser.c6
3 files changed, 15 insertions, 16 deletions
diff --git a/assemble.c b/assemble.c
index b0d45714..d847d378 100644
--- a/assemble.c
+++ b/assemble.c
@@ -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 72986eec..8d617489 100644
--- 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 };
diff --git a/parser.c b/parser.c
index 585abe20..1b086577 100644
--- 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 */