From d247c04c3ad33a861ef22077cf1401cd30729d5e Mon Sep 17 00:00:00 2001 From: Demetrios Chiuratto Agourakis Date: Wed, 23 Sep 2026 21:31:30 +0000 Subject: [PATCH] assemble: fix broadcast ratio calculation for sub-64-bit vector operands Fixes #263. get_broadcast_num() previously computed: brcast_num = ((opsize / (BITS64 >> SIZE_SHIFT)) * (BITS64 / brsize)) >> (opsize > (BITS64 >> SIZE_SHIFT)); When the memory operand size is smaller than BITS64 (such as xmmrm32 in VCVTPH2PD or VCVTPH2QQ with xmm destination, where opsize is BITS32 = 4 and BITS64 >> SIZE_SHIFT is 8), integer division opsize / 8 truncated to 0, causing NASM to report: error: mismatch in the number of broadcasting elements when assembling instructions with {1to2} broadcast like: vcvtph2pd xmm0, [rcx]{1to2} Replace the broken division formula with an exact bit-size lookup table indexed by ilog2_32(opsize), correctly supporting broadcast ratios for all operand sizes from BITS32 to BITS512. --- asm/assemble.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/asm/assemble.c b/asm/assemble.c index 023aa3bf0..0d4f09675 100644 --- a/asm/assemble.c +++ b/asm/assemble.c @@ -9,6 +9,7 @@ */ #include "compiler.h" +#include "ilog2.h" #include "nasm.h" @@ -2977,20 +2978,18 @@ static enum match_result find_match(insn *instruction) static uint8_t get_broadcast_num(opflags_t opflags, opflags_t brsize) { + static const uint16_t size_bits[8] = { 8, 16, 32, 64, 80, 128, 256, 512 }; unsigned int opsize = (opflags & SIZE_MASK) >> SIZE_SHIFT; - uint8_t brcast_num; + unsigned int brsize_idx; if (brsize > BITS64) nasm_fatal("size of broadcasting element is greater than 64 bits"); - /* - * The shift term is to take care of the extra BITS80 inserted - * between BITS64 and BITS128. - */ - brcast_num = ((opsize / (BITS64 >> SIZE_SHIFT)) * (BITS64 / brsize)) - >> (opsize > (BITS64 >> SIZE_SHIFT)); + brsize_idx = (brsize & SIZE_MASK) >> SIZE_SHIFT; + if (!opsize || !brsize_idx) + return 0; - return brcast_num; + return size_bits[ilog2_32(opsize)] / size_bits[ilog2_32(brsize_idx)]; } static enum match_result matches(const struct itemplate * const itemp,