summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2013-09-26 17:28:39 -0700
committerJin Kyu Song <jin.kyu.song@intel.com>2013-11-20 11:29:41 -0800
commit9f4706ff457ebd20f8f06e57140203aa58238196 (patch)
tree8978d0ce032505596bfc3b9b9ba54241c23631e8
parentdf0d1ba107079779e646a933fe8a29574d53f2d0 (diff)
downloadnasm-9f4706ff457ebd20f8f06e57140203aa58238196.tar.gz
parse: factor out mref parsing
Factor out the parsing of an mref from parse_line(). In order to support the [base,index] syntax we need to be able to parse an mref in two steps. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com> Signed-off-by: Jin Kyu Song <jin.kyu.song@intel.com>
-rw-r--r--parser.c257
1 files changed, 132 insertions, 125 deletions
diff --git a/parser.c b/parser.c
index ba994b41..ed568f20 100644
--- a/parser.c
+++ b/parser.c
@@ -242,6 +242,137 @@ static bool parse_braces(decoflags_t *decoflags)
return recover;
}
+static int parse_mref(operand *op, const expr *e,
+ const struct eval_hints *hints, decoflags_t brace_flags)
+{
+ int b, i, s; /* basereg, indexreg, scale */
+ int64_t o; /* offset */
+
+ b = i = -1, o = s = 0;
+ op->hintbase = hints->base;
+ op->hinttype = hints->type;
+
+ if (e->type && e->type <= EXPR_REG_END) { /* this bit's a register */
+ bool is_gpr = is_class(REG_GPR,nasm_reg_flags[e->type]);
+
+ if (is_gpr && e->value == 1)
+ b = e->type; /* It can be basereg */
+ else /* No, it has to be indexreg */
+ i = e->type, s = e->value;
+ e++;
+ }
+ if (e->type && e->type <= EXPR_REG_END) { /* it's a 2nd register */
+ bool is_gpr = is_class(REG_GPR,nasm_reg_flags[e->type]);
+
+ if (b != -1) /* If the first was the base, ... */
+ i = e->type, s = e->value; /* second has to be indexreg */
+
+ else if (!is_gpr || e->value != 1) {
+ /* If both want to be index */
+ nasm_error(ERR_NONFATAL,
+ "invalid effective address: two index registers");
+ return -1;
+ } else
+ b = e->type;
+ e++;
+ }
+ if (e->type != 0) { /* is there an offset? */
+ if (e->type <= EXPR_REG_END) { /* in fact, is there an error? */
+ nasm_error(ERR_NONFATAL,
+ "beroset-p-603-invalid effective address");
+ return -1;
+ } else {
+ if (e->type == EXPR_UNKNOWN) {
+ op->opflags |= OPFLAG_UNKNOWN;
+ o = 0; /* doesn't matter what */
+ op->wrt = NO_SEG; /* nor this */
+ op->segment = NO_SEG; /* or this */
+ while (e->type)
+ e++; /* go to the end of the line */
+ } else {
+ if (e->type == EXPR_SIMPLE) {
+ o = e->value;
+ e++;
+ }
+ if (e->type == EXPR_WRT) {
+ op->wrt = e->value;
+ e++;
+ } else
+ op->wrt = NO_SEG;
+ /*
+ * Look for a segment base type.
+ */
+ if (e->type && e->type < EXPR_SEGBASE) {
+ nasm_error(ERR_NONFATAL,
+ "beroset-p-630-invalid effective address");
+ return -1;
+ }
+ while (e->type && e->value == 0)
+ e++;
+ if (e->type && e->value != 1) {
+ nasm_error(ERR_NONFATAL,
+ "beroset-p-637-invalid effective address");
+ return -1;
+ }
+ if (e->type) {
+ op->segment =
+ e->type - EXPR_SEGBASE;
+ e++;
+ } else
+ op->segment = NO_SEG;
+ while (e->type && e->value == 0)
+ e++;
+ if (e->type) {
+ nasm_error(ERR_NONFATAL,
+ "beroset-p-650-invalid effective address");
+ return -1;
+ }
+ }
+ }
+ } else {
+ o = 0;
+ op->wrt = NO_SEG;
+ op->segment = NO_SEG;
+ }
+
+ if (e->type != 0) { /* there'd better be nothing left! */
+ nasm_error(ERR_NONFATAL,
+ "beroset-p-663-invalid effective address");
+ return -1;
+ }
+
+ /* It is memory, but it can match any r/m operand */
+ op->type |= MEMORY_ANY;
+
+ if (b == -1 && (i == -1 || s == 0)) {
+ int is_rel = globalbits == 64 &&
+ !(op->eaflags & EAF_ABS) &&
+ ((globalrel &&
+ !(op->eaflags & EAF_FSGS)) ||
+ (op->eaflags & EAF_REL));
+
+ op->type |= is_rel ? IP_REL : MEM_OFFS;
+ }
+
+ if (i != -1) {
+ opflags_t iclass = nasm_reg_flags[i];
+
+ if (is_class(XMMREG,iclass))
+ op->type |= XMEM;
+ else if (is_class(YMMREG,iclass))
+ op->type |= YMEM;
+ else if (is_class(ZMMREG,iclass))
+ op->type |= ZMEM;
+ }
+
+ op->basereg = b;
+ op->indexreg = i;
+ op->scale = s;
+ op->offset = o;
+ op->decoflags |= brace_flags;
+ return 0;
+}
+
insn *parse_line(int pass, char *buffer, insn *result, ldfunc ldef)
{
bool insn_is_label = false;
@@ -794,132 +925,8 @@ is_expression:
*/
if (mref) { /* it's a memory reference */
- expr *e = value;
- int b, i, s; /* basereg, indexreg, scale */
- int64_t o; /* offset */
-
- b = i = -1, o = s = 0;
- op->hintbase = hints.base;
- op->hinttype = hints.type;
-
- if (e->type && e->type <= EXPR_REG_END) { /* this bit's a register */
- bool is_gpr = is_class(REG_GPR,nasm_reg_flags[e->type]);
-
- if (is_gpr && e->value == 1)
- b = e->type; /* It can be basereg */
- else /* No, it has to be indexreg */
- i = e->type, s = e->value;
- e++;
- }
- if (e->type && e->type <= EXPR_REG_END) { /* it's a 2nd register */
- bool is_gpr = is_class(REG_GPR,nasm_reg_flags[e->type]);
-
- if (b != -1) /* If the first was the base, ... */
- i = e->type, s = e->value; /* second has to be indexreg */
-
- else if (!is_gpr || e->value != 1) {
- /* If both want to be index */
- nasm_error(ERR_NONFATAL,
- "invalid effective address: two index registers");
- goto fail;
- } else
- b = e->type;
- e++;
- }
- if (e->type != 0) { /* is there an offset? */
- if (e->type <= EXPR_REG_END) { /* in fact, is there an error? */
- nasm_error(ERR_NONFATAL,
- "beroset-p-603-invalid effective address");
- goto fail;
- } else {
- if (e->type == EXPR_UNKNOWN) {
- op->opflags |= OPFLAG_UNKNOWN;
- o = 0; /* doesn't matter what */
- op->wrt = NO_SEG; /* nor this */
- op->segment = NO_SEG; /* or this */
- while (e->type)
- e++; /* go to the end of the line */
- } else {
- if (e->type == EXPR_SIMPLE) {
- o = e->value;
- e++;
- }
- if (e->type == EXPR_WRT) {
- op->wrt = e->value;
- e++;
- } else
- op->wrt = NO_SEG;
- /*
- * Look for a segment base type.
- */
- if (e->type && e->type < EXPR_SEGBASE) {
- nasm_error(ERR_NONFATAL,
- "beroset-p-630-invalid effective address");
- goto fail;
- }
- while (e->type && e->value == 0)
- e++;
- if (e->type && e->value != 1) {
- nasm_error(ERR_NONFATAL,
- "beroset-p-637-invalid effective address");
- goto fail;
- }
- if (e->type) {
- op->segment =
- e->type - EXPR_SEGBASE;
- e++;
- } else
- op->segment = NO_SEG;
- while (e->type && e->value == 0)
- e++;
- if (e->type) {
- nasm_error(ERR_NONFATAL,
- "beroset-p-650-invalid effective address");
- goto fail;
- }
- }
- }
- } else {
- o = 0;
- op->wrt = NO_SEG;
- op->segment = NO_SEG;
- }
-
- if (e->type != 0) { /* there'd better be nothing left! */
- nasm_error(ERR_NONFATAL,
- "beroset-p-663-invalid effective address");
+ if (parse_mref(op, value, &hints, brace_flags))
goto fail;
- }
-
- /* It is memory, but it can match any r/m operand */
- op->type |= MEMORY_ANY;
-
- if (b == -1 && (i == -1 || s == 0)) {
- int is_rel = globalbits == 64 &&
- !(op->eaflags & EAF_ABS) &&
- ((globalrel &&
- !(op->eaflags & EAF_FSGS)) ||
- (op->eaflags & EAF_REL));
-
- op->type |= is_rel ? IP_REL : MEM_OFFS;
- }
-
- if (i != -1) {
- opflags_t iclass = nasm_reg_flags[i];
-
- if (is_class(XMMREG,iclass))
- op->type |= XMEM;
- else if (is_class(YMMREG,iclass))
- op->type |= YMEM;
- else if (is_class(ZMMREG,iclass))
- op->type |= ZMEM;
- }
-
- op->basereg = b;
- op->indexreg = i;
- op->scale = s;
- op->offset = o;
- op->decoflags |= brace_flags;
} else { /* it's not a memory reference */
if (is_just_unknown(value)) { /* it's immediate but unknown */
op->type |= IMMEDIATE;