diff --git a/decode.c b/decode.c index fe84e8a..3696a5c 100644 --- a/decode.c +++ b/decode.c @@ -366,9 +366,7 @@ prefix_end: } else { if (UNLIKELY(vexl == 3)) // EVEX.L'L == 11b is UD return FD_ERR_UD; - // Update V' to REX.W, s.t. broadcast size is exposed - unsigned rexw = prefix_rex & PREFIX_REXW ? 0x08 : 0x00; - instr->evex = (prefix_evex & 0x87) | rexw; + instr->evex = prefix_evex & 0x87; // clear RC, clear B } } else { instr->evex = 0; @@ -498,6 +496,7 @@ prefix_end: if (UNLIKELY(!DESC_EVEX_BCST(desc))) return FD_ERR_UD; scale = prefix_rex & PREFIX_REXW ? 3 : 2; + instr->segment |= scale << 6; // Store broadcast size op_modrm->type = FD_OT_MEMBCST; } else { op_modrm->type = FD_OT_MEM; diff --git a/fadec.h b/fadec.h index afaaa80..9ffc9b7 100644 --- a/fadec.h +++ b/fadec.h @@ -192,7 +192,7 @@ const char* fdi_name(FdInstrType ty); /** Gets the size of the instruction in bytes. **/ #define FD_SIZE(instr) ((instr)->size) /** Gets the specified segment override, or FD_REG_NONE for default segment. **/ -#define FD_SEGMENT(instr) ((FdReg) (instr)->segment) +#define FD_SEGMENT(instr) ((FdReg) (instr)->segment & 0x3f) /** Gets the address size attribute of the instruction in bytes. **/ #define FD_ADDRSIZE(instr) (1 << (instr)->addrsz) /** Get the logarithmic address size; FD_ADDRSIZE == 1 << FD_ADDRSIZELG **/ @@ -262,9 +262,12 @@ const char* fdi_name(FdInstrType ty); /** Gets the sign-extended displacement of a memory operand. * Only valid if FD_OP_TYPE == FD_OT_MEM/MEMBCST **/ #define FD_OP_DISP(instr,idx) ((int64_t) (instr)->disp) -/** Get whether the memory broadcast is 64-bit (otherwise: 32-bit). +/** Get memory broadcast size in bytes. * Only valid if FD_OP_TYPE == FD_OT_MEMBCST **/ -#define FD_OP_BCST64(instr,idx) (!!((instr)->evex & 0x08)) +#define FD_OP_BCSTSZ(instr,idx) (1 << FD_OP_BCSTSZLG(instr,idx)) +/** Get logarithmic memory broadcast size (1 = 2-byte; 2=4-byte; 3=8-byte). + * Only valid if FD_OP_TYPE == FD_OT_MEMBCST **/ +#define FD_OP_BCSTSZLG(instr,idx) ((instr)->segment >> 6) /** Gets the (sign-extended) encoded constant for an immediate operand. * Only valid if FD_OP_TYPE == FD_OT_IMM or FD_OP_TYPE == FD_OT_OFF **/ #define FD_OP_IMM(instr,idx) ((instr)->imm) diff --git a/format.c b/format.c index 38f61a0..774e83d 100644 --- a/format.c +++ b/format.c @@ -410,7 +410,7 @@ fd_format_impl(char buf[DECLARE_RESTRICTED_ARRAY_SIZE(128)], const FdInstr* inst } if (op_type == FD_OT_MEMBCST) - size = FD_OP_BCST64(instr, i) ? 3 : 2; + size = FD_OP_BCSTSZLG(instr, i); const char* ptrsizes = "\00 " @@ -461,10 +461,10 @@ fd_format_impl(char buf[DECLARE_RESTRICTED_ARRAY_SIZE(128)], const FdInstr* inst *buf++ = ']'; if (UNLIKELY(op_type == FD_OT_MEMBCST)) { - // {1toX}, X = FD_OP_SIZE(instr, i) / size (=> 2/4/8/16) - unsigned bcstszidx = FD_OP_SIZE(instr, i) >> (FD_OP_BCST64(instr, i) + 1); - const char* bcstsizes = "\6{1to2} \6{1to4} \6{1to8} \0 \7{1to16} "; - const char* bcstsize = bcstsizes + bcstszidx; + // {1toX}, X = FD_OP_SIZE(instr, i) / BCSTSZ (=> 2/4/8/16/32) + unsigned bcstszidx = FD_OP_SIZELG(instr, i) - FD_OP_BCSTSZLG(instr, i) - 1; + const char* bcstsizes = "\6{1to2} \6{1to4} \6{1to8} \7{1to16}\7{1to32} "; + const char* bcstsize = bcstsizes + bcstszidx * 8; buf = fd_strpcat(buf, (struct FdStr) { bcstsize+1, *bcstsize }); } } else if (op_type == FD_OT_IMM || op_type == FD_OT_OFF) {