enum match_result m, merr;
opflags_t xsizeflags[MAX_OPERANDS];
bool opsizemissing = false;
+ int8_t broadcast = -1;
int i;
+ /* find the position of broadcasting operand */
for (i = 0; i < instruction->operands; i++)
- xsizeflags[i] = instruction->oprs[i].type & SIZE_MASK;
+ if (instruction->oprs[i].decoflags & BRDCAST_MASK) {
+ broadcast = i;
+ break;
+ }
+
+ /* broadcasting uses a different data element size */
+ for (i = 0; i < instruction->operands; i++)
+ if (i == broadcast)
+ xsizeflags[i] = instruction->oprs[i].decoflags & BRSIZE_MASK;
+ else
+ xsizeflags[i] = instruction->oprs[i].type & SIZE_MASK;
merr = MERR_INVALOP;
* Missing operand size and a candidate for fuzzy matching...
*/
for (i = 0; i < temp->operands; i++)
- xsizeflags[i] |= temp->opd[i] & SIZE_MASK;
+ if (i == broadcast)
+ xsizeflags[i] |= temp->deco[i] & BRSIZE_MASK;
+ else
+ xsizeflags[i] |= temp->opd[i] & SIZE_MASK;
opsizemissing = true;
}
if (m > merr)
if ((xsizeflags[i] & (xsizeflags[i]-1)))
goto done; /* No luck */
- instruction->oprs[i].type |= xsizeflags[i]; /* Set the size */
+ if (i == broadcast)
+ instruction->oprs[i].decoflags |= xsizeflags[i];
+ else
+ instruction->oprs[i].type |= xsizeflags[i]; /* Set the size */
}
/* Try matching again... */
} else if ((itemp->opd[i] & SIZE_MASK) &&
(itemp->opd[i] & SIZE_MASK) != (type & SIZE_MASK)) {
if (type & SIZE_MASK) {
- return MERR_INVALOP;
+ /*
+ * 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)))) {
+ return MERR_INVALOP;
+ }
} else if (!is_class(REGISTER, type)) {
/*
* Note: we don't honor extrinsic operand sizes for registers,
* ..........................1..... broadcast
* .........................1...... static rounding
* ........................1....... SAE
+ * ......................11........ broadcast element size
*/
#define OP_GENVAL(val, bits, shift) (((val) & ((UINT64_C(1) << (bits)) - 1)) << (shift))
#define SAE_MASK OP_GENMASK(SAE_BITS, SAE_SHIFT)
#define GEN_SAE(bit) OP_GENBIT(bit, SAE_SHIFT)
+/*
+ * Broadcasting element size.
+ *
+ * Bits: 8 - 9
+ */
+#define BRSIZE_SHIFT (8)
+#define BRSIZE_BITS (2)
+#define BRSIZE_MASK OP_GENMASK(BRSIZE_BITS, BRSIZE_SHIFT)
+#define GEN_BRSIZE(bit) OP_GENBIT(bit, BRSIZE_SHIFT)
+
+#define BR_BITS32 GEN_BRSIZE(0)
+#define BR_BITS64 GEN_BRSIZE(1)
+
#define MASK OPMASK_MASK /* Opmask (k1 ~ 7) can be used */
#define Z Z_MASK
-#define B32 BRDCAST_MASK /* {1to16} : load+op instruction can broadcast when it is reg-reg operation */
-#define B64 BRDCAST_MASK /* {1to8} : There are two definitions just for conforming to SDM */
+#define B32 (BRDCAST_MASK|BR_BITS32) /* {1to16} : broadcast 32b * 16 to zmm(512b) */
+#define B64 (BRDCAST_MASK|BR_BITS64) /* {1to8} : broadcast 64b * 8 to zmm(512b) */
#define ER STATICRND_MASK /* ER(Embedded Rounding) == Static rounding mode */
#define SAE SAE_MASK /* SAE(Suppress All Exception) */
extern const char * const nasm_reg_names[];
/* regflags.c */
typedef uint64_t opflags_t;
-typedef uint8_t decoflags_t;
+typedef uint16_t decoflags_t;
extern const opflags_t nasm_reg_flags[];
/* regvals.c */
extern const int nasm_regvals[];