diff options
author | Jin Kyu Song <jin.kyu.song@intel.com> | 2013-10-30 03:12:45 -0700 |
---|---|---|
committer | Jin Kyu Song <jin.kyu.song@intel.com> | 2013-11-20 11:29:42 -0800 |
commit | 25c221258641aec4198e9e46127536676878a4bd (patch) | |
tree | 3b3435793bd08c7bcbde3dba5b8a6d581ad05863 /assemble.c | |
parent | 7903c07b7753fb02fc3b5ba6211dc566bc25aa7c (diff) | |
download | nasm-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.c | 21 |
1 files changed, 20 insertions, 1 deletions
@@ -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 && |