summaryrefslogtreecommitdiff
path: root/assemble.c
diff options
context:
space:
mode:
authorJin Kyu Song <jin.kyu.song@intel.com>2013-10-30 03:12:45 -0700
committerJin Kyu Song <jin.kyu.song@intel.com>2013-11-20 11:29:42 -0800
commit25c221258641aec4198e9e46127536676878a4bd (patch)
tree3b3435793bd08c7bcbde3dba5b8a6d581ad05863 /assemble.c
parent7903c07b7753fb02fc3b5ba6211dc566bc25aa7c (diff)
downloadnasm-25c221258641aec4198e9e46127536676878a4bd.tar.gz
nasm-25c221258641aec4198e9e46127536676878a4bd.tar.bz2
nasm-25c221258641aec4198e9e46127536676878a4bd.zip
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>
Diffstat (limited to 'assemble.c')
-rw-r--r--assemble.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/assemble.c b/assemble.c
index a619575..00acd20 100644
--- a/assemble.c
+++ b/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 &&