summaryrefslogtreecommitdiff
path: root/assemble.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2009-10-05 14:08:05 -0700
committerH. Peter Anvin <hpa@zytor.com>2009-10-05 14:08:05 -0700
commitff5d6569297d9cd9e96555a5f667ecf0ea3c55ef (patch)
tree6e39b34d73a9e9f7e2e1a25c3e807982b1f58aa9 /assemble.c
parent8186a0061adcaa13dda72e898e54c963959778ce (diff)
downloadnasm-ff5d6569297d9cd9e96555a5f667ecf0ea3c55ef.tar.gz
assemble: treat register operands without size as wildcards
Register with no size are a bit special: we don't honor extrinsic register sizes in the first place ("oword xmm1" gives a warning, even), and they should match any xmmrm size. As such, explicitly handle sizeless register operands as a hard match, instead of relying on the fuzzy-matching mechanism to handle them. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'assemble.c')
-rw-r--r--assemble.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/assemble.c b/assemble.c
index d0c44cd9..4f9638b1 100644
--- a/assemble.c
+++ b/assemble.c
@@ -2005,9 +2005,10 @@ static enum match_result find_match(const struct itemplate **tempp,
/*
* Missing operand size and a candidate for fuzzy matching...
*/
- for (i = 0; i < temp->operands; i++)
- xsizeflags[i] |= temp->opd[i] & SIZE_MASK;
-
+ for (i = 0; i < temp->operands; i++) {
+ if ((temp->opd[i] & SAME_AS) == 0)
+ xsizeflags[i] |= temp->opd[i] & SIZE_MASK;
+ }
opsizemissing = true;
}
if (m > merr)
@@ -2021,6 +2022,14 @@ static enum match_result find_match(const struct itemplate **tempp,
goto done;
for (i = 0; i < instruction->operands; i++) {
+ /*
+ * We ignore extrinsic operand sizes on registers, so we should
+ * never try to fuzzy-match on them. This also resolves the case
+ * when we have e.g. "xmmrm128" in two different positions.
+ */
+ if ((REGISTER & ~instruction->oprs[i].type) == 0)
+ continue;
+
/* This tests if xsizeflags[i] has more than one bit set */
if ((xsizeflags[i] & (xsizeflags[i]-1)))
goto done; /* No luck */
@@ -2144,10 +2153,16 @@ static enum match_result matches(const struct itemplate *itemp,
} else if (itemp->opd[i] & ~type ||
((itemp->opd[i] & SIZE_MASK) &&
((itemp->opd[i] ^ type) & SIZE_MASK))) {
- if ((itemp->opd[i] & ~type & ~SIZE_MASK) || (type & SIZE_MASK))
+ if ((itemp->opd[i] & ~type & ~SIZE_MASK) || (type & SIZE_MASK)) {
return MERR_INVALOP;
- else
+ } else if (!(REGISTER & ~type)) {
+ /*
+ * Note: we don't honor extrinsic operand sizes for registers,
+ * so "missing operand size" for a register should be
+ * considered a wildcard match rather than an error.
+ */
opsizemissing = true;
+ }
}
}