summaryrefslogtreecommitdiff
path: root/parser.c
diff options
context:
space:
mode:
authorJin Kyu Song <jin.kyu.song@intel.com>2013-08-05 20:46:18 -0700
committerCyrill Gorcunov <gorcunov@gmail.com>2013-08-06 09:37:52 +0400
commit72018a2b4326d5a647b8879ba8124300b68ca212 (patch)
treed0c1a7aef244b6db36fd3d055bbfe0d0118ce2c3 /parser.c
parentb775985beefc968f9862d45764f7c7ad8e949299 (diff)
downloadnasm-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.c94
1 files changed, 92 insertions, 2 deletions
diff --git a/parser.c b/parser.c
index afc422a..f7139f3 100644
--- a/parser.c
+++ b/parser.c
@@ -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)