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 /stdscan.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 'stdscan.c')
-rw-r--r-- | stdscan.c | 94 |
1 files changed, 90 insertions, 4 deletions
@@ -53,6 +53,8 @@ static char *stdscan_bufptr = NULL; static char **stdscan_tempstorage = NULL; static int stdscan_tempsize = 0, stdscan_templen = 0; +static int brace = 0; /* nested brace counter */ +static bool brace_opened = false; /* if brace is just opened */ #define STDSCAN_TEMP_DELTA 256 void stdscan_set(char *str) @@ -105,6 +107,40 @@ static char *stdscan_copy(char *p, int len) return text; } +/* + * a token is enclosed with braces. proper token type will be assigned + * accordingly with the token flag. + * a closing brace is treated as an ending character of corresponding token. + */ +static int stdscan_handle_brace(struct tokenval *tv) +{ + if (!(tv->t_flag & TFLAG_BRC_ANY)) { + /* invalid token is put inside braces */ + nasm_error(ERR_NONFATAL, + "%s is not a valid decorator with braces", tv->t_charptr); + tv->t_type = TOKEN_INVALID; + } else if (tv->t_flag & TFLAG_BRC_OPT) { + if (is_reg_class(OPMASKREG, tv->t_integer)) { + /* within braces, opmask register is now used as a mask */ + tv->t_type = TOKEN_OPMASK; + } + } + + stdscan_bufptr = nasm_skip_spaces(stdscan_bufptr); + + if (stdscan_bufptr[0] == '}') { + stdscan_bufptr ++; /* skip the closing brace */ + brace --; + } else if (stdscan_bufptr[0] != ',') { + /* treat {foo,bar} as {foo}{bar} + * by regarding ',' as a mere separator between decorators + */ + nasm_error(ERR_NONFATAL, "closing brace expected"); + tv->t_type = TOKEN_INVALID; + } + return tv->t_type; +} + int stdscan(void *private_data, struct tokenval *tv) { char ourcopy[MAX_KEYWORD + 1], *r, *s; @@ -112,14 +148,22 @@ int stdscan(void *private_data, struct tokenval *tv) (void)private_data; /* Don't warn that this parameter is unused */ stdscan_bufptr = nasm_skip_spaces(stdscan_bufptr); - if (!*stdscan_bufptr) + if (!*stdscan_bufptr) { + /* nested brace shouldn't affect following lines */ + brace = 0; return tv->t_type = TOKEN_EOS; + } /* we have a token; either an id, a number or a char */ if (isidstart(*stdscan_bufptr) || - (*stdscan_bufptr == '$' && isidstart(stdscan_bufptr[1]))) { + (*stdscan_bufptr == '$' && isidstart(stdscan_bufptr[1])) || + (brace && isidchar(*stdscan_bufptr))) { /* because of {1to8} */ /* now we've got an identifier */ bool is_sym = false; + int token_type; + + /* opening brace is followed by any letter */ + brace_opened = false; if (*stdscan_bufptr == '$') { is_sym = true; @@ -128,7 +172,8 @@ int stdscan(void *private_data, struct tokenval *tv) r = stdscan_bufptr++; /* read the entire buffer to advance the buffer pointer but... */ - while (isidchar(*stdscan_bufptr)) + /* {rn-sae}, {rd-sae}, {ru-sae}, {rz-sae} contain '-' in tokens. */ + while (isidchar(*stdscan_bufptr) || (brace && *stdscan_bufptr == '-')) stdscan_bufptr++; /* ... copy only up to IDLEN_MAX-1 characters */ @@ -143,7 +188,19 @@ int stdscan(void *private_data, struct tokenval *tv) *r = '\0'; /* right, so we have an identifier sitting in temp storage. now, * is it actually a register or instruction name, or what? */ - return nasm_token_hash(ourcopy, tv); + token_type = nasm_token_hash(ourcopy, tv); + + if (likely(!brace)) { + if (likely(!(tv->t_flag & TFLAG_BRC))) { + /* most of the tokens fall into this case */ + return token_type; + } else { + return tv->t_type = TOKEN_ID; + } + } else { + /* handle tokens inside braces */ + return stdscan_handle_brace(tv); + } } else if (*stdscan_bufptr == '$' && !isnumchar(stdscan_bufptr[1])) { /* * It's a $ sign with no following hex number; this must @@ -267,6 +324,35 @@ int stdscan(void *private_data, struct tokenval *tv) } else if (stdscan_bufptr[0] == '|' && stdscan_bufptr[1] == '|') { stdscan_bufptr += 2; return tv->t_type = TOKEN_DBL_OR; + } else if (stdscan_bufptr[0] == '{') { + stdscan_bufptr ++; /* skip the opening brace */ + brace ++; /* in case of nested braces */ + brace_opened = true; /* brace is just opened */ + return stdscan(private_data, tv); + } else if (stdscan_bufptr[0] == ',' && brace) { + /* + * a comma inside braces should be treated just as a separator. + * this is almost same as an opening brace except increasing counter. + */ + stdscan_bufptr ++; + brace_opened = true; /* brace is just opened */ + return stdscan(private_data, tv); + } else if (stdscan_bufptr[0] == '}') { + stdscan_bufptr ++; /* skip the closing brace */ + if (brace) { + /* unhandled nested closing brace */ + brace --; + /* if brace is closed without any content in it */ + if (brace_opened) { + brace_opened = false; + nasm_error(ERR_NONFATAL, "nothing inside braces"); + } + return stdscan(private_data, tv); + } else { + /* redundant closing brace */ + return tv->t_type = TOKEN_INVALID; + } + return stdscan(private_data, tv); } else /* just an ordinary char */ return tv->t_type = (uint8_t)(*stdscan_bufptr++); } |