fadec: Store broadcast size in segment
This is a preparation for AVX512-FP16, where the broadcast size is not just 32/64 bit depending solely on EVEX.W, but can also be 16 bit (with EVEX.W=0). The broadcast size therefore needs two bits, but the evex field only had one free bit left. Store broadcast size with the segment for now. (This is not a good fit and is likely to change at some point.)
This commit is contained in:
5
decode.c
5
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;
|
||||
|
||||
9
fadec.h
9
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)
|
||||
|
||||
10
format.c
10
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) {
|
||||
|
||||
Reference in New Issue
Block a user