diff options
author | H. Peter Anvin <hpa@zytor.com> | 2009-10-05 14:08:05 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-10-05 14:08:05 -0700 |
commit | ff5d6569297d9cd9e96555a5f667ecf0ea3c55ef (patch) | |
tree | 6e39b34d73a9e9f7e2e1a25c3e807982b1f58aa9 /assemble.c | |
parent | 8186a0061adcaa13dda72e898e54c963959778ce (diff) | |
download | nasm-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.c | 25 |
1 files changed, 20 insertions, 5 deletions
@@ -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; + } } } |