mirror of
https://github.com/netwide-assembler/nasm.git
synced 2024-11-21 03:14:19 +08:00
match: Check the number of elements in broadcasting operands
The broadcasting decorator {1to##} must describe exactly how many times the memory element is repeated in order to clearly match the correct instruction format. For example, vaddpd zmm30,zmm29,QWORD [rdx+0x3f8]{1to8} ; good vaddpd zmm30,zmm29,QWORD [rdx+0x3f8]{1to16} ; fail qword * 16 = 1024b vaddps zmm30,zmm29,DWORD [rcx]{1to16} ; good vaddps zmm30,zmm29,DWORD [rcx]{1to8} ; fail dword * 8 = 256b Signed-off-by: Jin Kyu Song <jin.kyu.song@intel.com>
This commit is contained in:
parent
7903c07b77
commit
25c2212586
21
assemble.c
21
assemble.c
@ -189,6 +189,7 @@ enum match_result {
|
||||
MERR_INVALOP,
|
||||
MERR_OPSIZEMISSING,
|
||||
MERR_OPSIZEMISMATCH,
|
||||
MERR_BRNUMMISMATCH,
|
||||
MERR_BADCPU,
|
||||
MERR_BADMODE,
|
||||
MERR_BADHLE,
|
||||
@ -671,6 +672,10 @@ int64_t assemble(int32_t segment, int64_t offset, int bits, iflags_t cp,
|
||||
case MERR_OPSIZEMISMATCH:
|
||||
error(ERR_NONFATAL, "mismatch in operand sizes");
|
||||
break;
|
||||
case MERR_BRNUMMISMATCH:
|
||||
error(ERR_NONFATAL,
|
||||
"mismatch in the number of broadcasting elements");
|
||||
break;
|
||||
case MERR_BADCPU:
|
||||
error(ERR_NONFATAL, "no instruction for this cpu level");
|
||||
break;
|
||||
@ -2163,6 +2168,7 @@ static enum match_result matches(const struct itemplate *itemp,
|
||||
opflags_t type = instruction->oprs[i].type;
|
||||
decoflags_t deco = instruction->oprs[i].decoflags;
|
||||
bool is_broadcast = deco & BRDCAST_MASK;
|
||||
uint8_t brcast_num = 0;
|
||||
opflags_t template_opsize, insn_opsize;
|
||||
|
||||
if (!(type & SIZE_MASK))
|
||||
@ -2180,13 +2186,16 @@ static enum match_result matches(const struct itemplate *itemp,
|
||||
|
||||
if (deco_brsize) {
|
||||
template_opsize = (deco_brsize == BR_BITS32 ? BITS32 : BITS64);
|
||||
/* calculate the proper number : {1to<brcast_num>} */
|
||||
brcast_num = (itemp->opd[i] & SIZE_MASK) / BITS128 *
|
||||
BITS64 / template_opsize * 2;
|
||||
} else {
|
||||
template_opsize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((itemp->opd[i] & ~type & ~SIZE_MASK) ||
|
||||
(itemp->deco[i] & deco) != deco) {
|
||||
(deco & ~itemp->deco[i] & ~BRNUM_MASK)) {
|
||||
return MERR_INVALOP;
|
||||
} else if (template_opsize) {
|
||||
if (template_opsize != insn_opsize) {
|
||||
@ -2200,6 +2209,16 @@ static enum match_result matches(const struct itemplate *itemp,
|
||||
*/
|
||||
opsizemissing = true;
|
||||
}
|
||||
} else if (is_broadcast &&
|
||||
(brcast_num !=
|
||||
(8U << ((deco & BRNUM_MASK) >> BRNUM_SHIFT)))) {
|
||||
/*
|
||||
* broadcasting opsize matches but the number of repeated memory
|
||||
* element does not match.
|
||||
* if 64b double precision float is broadcasted to zmm (512b),
|
||||
* broadcasting decorator must be {1to8}.
|
||||
*/
|
||||
return MERR_BRNUMMISMATCH;
|
||||
}
|
||||
} else if (is_register(instruction->oprs[i].basereg) &&
|
||||
nasm_regvals[instruction->oprs[i].basereg] >= 16 &&
|
||||
|
14
nasm.h
14
nasm.h
@ -1048,6 +1048,7 @@ enum decorator_tokens {
|
||||
* .........................1...... static rounding
|
||||
* ........................1....... SAE
|
||||
* ......................11........ broadcast element size
|
||||
* ....................11.......... number of broadcast elements
|
||||
*/
|
||||
#define OP_GENVAL(val, bits, shift) (((val) & ((UINT64_C(1) << (bits)) - 1)) << (shift))
|
||||
|
||||
@ -1119,6 +1120,19 @@ enum decorator_tokens {
|
||||
#define BR_BITS32 GEN_BRSIZE(0)
|
||||
#define BR_BITS64 GEN_BRSIZE(1)
|
||||
|
||||
/*
|
||||
* Number of broadcasting elements
|
||||
*
|
||||
* Bits: 10 - 11
|
||||
*/
|
||||
#define BRNUM_SHIFT (10)
|
||||
#define BRNUM_BITS (2)
|
||||
#define BRNUM_MASK OP_GENMASK(BRNUM_BITS, BRNUM_SHIFT)
|
||||
#define VAL_BRNUM(val) OP_GENVAL(val, BRNUM_BITS, BRNUM_SHIFT)
|
||||
|
||||
#define BR_1TO8 VAL_BRNUM(0)
|
||||
#define BR_1TO16 VAL_BRNUM(1)
|
||||
|
||||
#define MASK OPMASK_MASK /* Opmask (k1 ~ 7) can be used */
|
||||
#define Z Z_MASK
|
||||
#define B32 (BRDCAST_MASK|BR_BITS32) /* {1to16} : broadcast 32b * 16 to zmm(512b) */
|
||||
|
3
parser.c
3
parser.c
@ -947,7 +947,8 @@ is_expression:
|
||||
* is expected for memory reference operands
|
||||
*/
|
||||
if (tokval.t_flag & TFLAG_BRDCAST) {
|
||||
brace_flags |= GEN_BRDCAST(0);
|
||||
brace_flags |= GEN_BRDCAST(0) |
|
||||
VAL_BRNUM(tokval.t_integer - BRC_1TO8);
|
||||
i = stdscan(NULL, &tokval);
|
||||
} else if (i == TOKEN_OPMASK) {
|
||||
brace_flags |= VAL_OPMASK(nasm_regvals[tokval.t_integer]);
|
||||
|
Loading…
Reference in New Issue
Block a user