From 7903c07b7753fb02fc3b5ba6211dc566bc25aa7c Mon Sep 17 00:00:00 2001 From: Jin Kyu Song Date: Wed, 30 Oct 2013 03:00:12 -0700 Subject: [PATCH] match: Improve broadcast opsize matching Broadcasting operand size is different from the original operand size because 32b or 64b element is repeated to form a vector. So when matching a broadcasting operand, opsize should be treated differently. The broadcasting element size is specified in the decorator information. Signed-off-by: Jin Kyu Song --- assemble.c | 55 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/assemble.c b/assemble.c index 100d131..a619575 100644 --- a/assemble.c +++ b/assemble.c @@ -2020,10 +2020,13 @@ static enum match_result find_match(const struct itemplate **tempp, if ((xsizeflags[i] & (xsizeflags[i]-1))) goto done; /* No luck */ - if (i == broadcast) + if (i == broadcast) { instruction->oprs[i].decoflags |= xsizeflags[i]; - else + instruction->oprs[i].type |= (xsizeflags[i] == BR_BITS32 ? + BITS32 : BITS64); + } else { instruction->oprs[i].type |= xsizeflags[i]; /* Set the size */ + } } /* Try matching again... */ @@ -2159,32 +2162,44 @@ static enum match_result matches(const struct itemplate *itemp, for (i = 0; i < itemp->operands; i++) { opflags_t type = instruction->oprs[i].type; decoflags_t deco = instruction->oprs[i].decoflags; + bool is_broadcast = deco & BRDCAST_MASK; + opflags_t template_opsize, insn_opsize; + if (!(type & SIZE_MASK)) type |= size[i]; + insn_opsize = type & SIZE_MASK; + if (!is_broadcast) { + template_opsize = itemp->opd[i] & SIZE_MASK; + } else { + decoflags_t deco_brsize = itemp->deco[i] & BRSIZE_MASK; + /* + * when broadcasting, the element size depends on + * the instruction type. decorator flag should match. + */ + + if (deco_brsize) { + template_opsize = (deco_brsize == BR_BITS32 ? BITS32 : BITS64); + } else { + template_opsize = 0; + } + } + if ((itemp->opd[i] & ~type & ~SIZE_MASK) || (itemp->deco[i] & deco) != deco) { return MERR_INVALOP; - } else if ((itemp->opd[i] & SIZE_MASK) && - (itemp->opd[i] & SIZE_MASK) != (type & SIZE_MASK)) { - if (type & SIZE_MASK) { - /* - * when broadcasting, the element size depends on - * the instruction type. decorator flag should match. - */ -#define MATCH_BRSZ(bits) (((type & SIZE_MASK) == BITS##bits) && \ - ((itemp->deco[i] & BRSIZE_MASK) == BR_BITS##bits)) - if (!((deco & BRDCAST_MASK) && - (MATCH_BRSZ(32) || MATCH_BRSZ(64)))) { + } else if (template_opsize) { + if (template_opsize != insn_opsize) { + if (insn_opsize) { return MERR_INVALOP; + } else if (!is_class(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; } - } else if (!is_class(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; } } else if (is_register(instruction->oprs[i].basereg) && nasm_regvals[instruction->oprs[i].basereg] >= 16 && -- 2.7.4