summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJin Kyu Song <jin.kyu.song@intel.com>2013-08-28 19:15:23 -0700
committerCyrill Gorcunov <gorcunov@gmail.com>2013-08-29 10:03:02 +0400
commite3a06b9d0a12a7a9ac9143d631717223097849b7 (patch)
tree61bde6ad906fd7695f54fda49fc82add5650d5ff
parentfe0ee08586f9cb31e8bc52200818a5bbb9d4c149 (diff)
downloadnasm-e3a06b9d0a12a7a9ac9143d631717223097849b7.tar.gz
nasm-e3a06b9d0a12a7a9ac9143d631717223097849b7.tar.bz2
nasm-e3a06b9d0a12a7a9ac9143d631717223097849b7.zip
AVX-512: Remember the position of operand with broadcast or embedded rounding
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>
-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 b0d4571..d847d37 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 72986ee..8d61748 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 585abe2..1b08657 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 */