diff options
author | Jin Kyu Song <jin.kyu.song@intel.com> | 2013-08-05 20:46:18 -0700 |
---|---|---|
committer | Cyrill Gorcunov <gorcunov@gmail.com> | 2013-08-06 09:37:52 +0400 |
commit | 72018a2b4326d5a647b8879ba8124300b68ca212 (patch) | |
tree | d0c1a7aef244b6db36fd3d055bbfe0d0118ce2c3 /parser.c | |
parent | b775985beefc968f9862d45764f7c7ad8e949299 (diff) | |
download | nasm-72018a2b4326d5a647b8879ba8124300b68ca212.tar.gz nasm-72018a2b4326d5a647b8879ba8124300b68ca212.tar.bz2 nasm-72018a2b4326d5a647b8879ba8124300b68ca212.zip |
AVX-512: Add support for parsing braces
AVX-512 introduced new syntax using braces for decorators.
Opmask, broadcat, rounding control use this new syntax.
http://software.intel.com/sites/default/files/319433-015.pdf
Signed-off-by: Jin Kyu Song <jin.kyu.song@intel.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Diffstat (limited to 'parser.c')
-rw-r--r-- | parser.c | 94 |
1 files changed, 92 insertions, 2 deletions
@@ -193,6 +193,51 @@ static void process_size_override(insn *result, int operand) } } +/* + * when two or more decorators follow a register operand, + * consecutive decorators are parsed here. + * the order of decorators does not matter. + * 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%lu 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; + } + } 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; +} + insn *parse_line(int pass, char *buffer, insn *result, ldfunc ldef) { bool insn_is_label = false; @@ -557,10 +602,12 @@ is_expression: int mref; /* is this going to be a memory ref? */ int bracket; /* is it a [] mref, or a & 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; + result->oprs[operand].decoflags = 0; i = stdscan(NULL, &tokval); if (i == TOKEN_EOS) @@ -702,17 +749,37 @@ is_expression: recover = true; } else { /* we got the required ] */ i = stdscan(NULL, &tokval); + if (i == TOKEN_DECORATOR) { + /* + * according to AVX512 spec, only broacast decorator is + * expected for memory reference operands + */ + if (tokval.t_flag & TFLAG_BRDCAST) { + brace_flags |= GEN_BRDCAST(0); + i = stdscan(NULL, &tokval); + } else { + nasm_error(ERR_NONFATAL, "broadcast 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; + } else if (i == TOKEN_DECORATOR || i == TOKEN_OPMASK) { + /* parse opmask (and zeroing) after an operand */ + recover = parse_braces(&brace_flags); } } if (recover) { @@ -856,6 +923,7 @@ is_expression: result->oprs[operand].indexreg = i; result->oprs[operand].scale = s; result->oprs[operand].offset = o; + result->oprs[operand].decoflags |= brace_flags; } else { /* it's not a memory reference */ if (is_just_unknown(value)) { /* it's immediate but unknown */ result->oprs[operand].type |= IMMEDIATE; @@ -891,6 +959,27 @@ is_expression: result->oprs[operand].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. + */ + operand --; + switch (value->value) { + case BRC_RN: + case BRC_RU: + case BRC_RD: + case BRC_RZ: + case BRC_SAE: + result->oprs[operand].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 */ opflags_t rs; @@ -923,6 +1012,7 @@ is_expression: result->oprs[operand].type &= TO; result->oprs[operand].type |= REGISTER; result->oprs[operand].type |= nasm_reg_flags[value->type]; + result->oprs[operand].decoflags |= brace_flags; result->oprs[operand].basereg = value->type; if (rs && (result->oprs[operand].type & SIZE_MASK) != rs) |