diff options
author | Jin Kyu Song <jin.kyu.song@intel.com> | 2013-08-28 19:15:23 -0700 |
---|---|---|
committer | Cyrill Gorcunov <gorcunov@gmail.com> | 2013-08-29 10:03:02 +0400 |
commit | e3a06b9d0a12a7a9ac9143d631717223097849b7 (patch) | |
tree | 61bde6ad906fd7695f54fda49fc82add5650d5ff | |
parent | fe0ee08586f9cb31e8bc52200818a5bbb9d4c149 (diff) | |
download | nasm-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.c | 24 | ||||
-rw-r--r-- | nasm.h | 1 | ||||
-rw-r--r-- | parser.c | 6 |
3 files changed, 15 insertions, 16 deletions
@@ -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) @@ -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 }; @@ -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 */ |