Compare commits

...

10 Commits

Author SHA1 Message Date
T0b1
9263c3d6b2 wasm support 2023-04-28 20:41:17 +02:00
Alexis Engelke
e2480e9f85 instrs: Fix VMOVD_G2X with W1 in 32-bit mode 2023-04-24 22:21:00 +02:00
Alexis Engelke
6abc971576 decode: Move instr-width to legacy path
Very few instructions set use instrwidth, so move this check as well to
the legacy path. The only affected common instructions are RET and
LEAVE.
2023-04-24 08:55:56 +02:00
Alexis Engelke
48f886e130 decode: Group all VSIB handling in single branch
Most instructions don't use VSIB encoding, so move all VSIB-related
handling to a single block behind a single branch.
2023-04-23 11:55:45 +02:00
Alexis Engelke
1290e9f094 decode: Group all EVEX-handling for ModRM operands
Most instructions aren't EVEX-encoded, so hide all uncommon paths behind
a single branch.
2023-04-23 11:29:34 +02:00
Alexis Engelke
bbc1b0b648 decode: Use macros for all desc accesses [NFC] 2023-04-23 08:57:08 +02:00
Alexis Engelke
8dad665751 encode: Fix unhelpful warning [NFC] 2023-04-23 08:57:08 +02:00
Alexis Engelke
247acd6221 decode: Unify VEX opcode escape extraction 2023-04-23 08:57:08 +02:00
Alexis Engelke
239be46d4a format: Fix out-of-bounds reads for strings 2023-04-23 08:57:08 +02:00
Alexis Engelke
0297f66de6 decode-test: Add VPEXTRB sil case 2023-04-23 08:57:08 +02:00
8 changed files with 101 additions and 81 deletions

View File

@@ -1449,6 +1449,9 @@ main(int argc, char** argv)
TEST("\xc5\xf9\x6e\xc8", "vmovd xmm1, eax"); TEST("\xc5\xf9\x6e\xc8", "vmovd xmm1, eax");
TEST64("\xc4\xe1\xf9\x6e\xc8", "vmovq xmm1, rax"); TEST64("\xc4\xe1\xf9\x6e\xc8", "vmovq xmm1, rax");
TEST32("\xc4\xe1\xf9\x6e\xc8", "vmovd xmm1, eax"); TEST32("\xc4\xe1\xf9\x6e\xc8", "vmovd xmm1, eax");
TEST("\xc5\xf9\x7e\xc8", "vmovd eax, xmm1");
TEST64("\xc4\xe1\xf9\x7e\xc8", "vmovq rax, xmm1");
TEST32("\xc4\xe1\xf9\x7e\xc8", "vmovd eax, xmm1");
TEST("\xc5\xf2\x10\xc2", "vmovss xmm0, xmm1, xmm2"); TEST("\xc5\xf2\x10\xc2", "vmovss xmm0, xmm1, xmm2");
TEST("\xc5\xf6\x10\xc2", "vmovss xmm0, xmm1, xmm2"); // VEX.L=1 TEST("\xc5\xf6\x10\xc2", "vmovss xmm0, xmm1, xmm2"); // VEX.L=1
TEST("\xc5\xfa\x10\x04\x25\x34\x12\x00\x00", "vmovss xmm0, dword ptr [0x1234]"); TEST("\xc5\xfa\x10\x04\x25\x34\x12\x00\x00", "vmovss xmm0, dword ptr [0x1234]");
@@ -1547,6 +1550,7 @@ main(int argc, char** argv)
TEST("\xc4\xe3\x71\x20\xc0\x00", "vpinsrb xmm0, xmm1, al, 0x0"); TEST("\xc4\xe3\x71\x20\xc0\x00", "vpinsrb xmm0, xmm1, al, 0x0");
TEST("\xc4\xe3\xf1\x20\xc0\x00", "vpinsrb xmm0, xmm1, al, 0x0"); TEST("\xc4\xe3\xf1\x20\xc0\x00", "vpinsrb xmm0, xmm1, al, 0x0");
TEST("\xc4\xe3\x71\x20\xc6\x00", "vpinsrb xmm0, xmm1, sil, 0x0");
TEST("\xc4\xe1\x71\xc4\xc0\x00", "vpinsrw xmm0, xmm1, ax, 0x0"); TEST("\xc4\xe1\x71\xc4\xc0\x00", "vpinsrw xmm0, xmm1, ax, 0x0");
TEST("\xc4\xe1\xf1\xc4\xc0\x00", "vpinsrw xmm0, xmm1, ax, 0x0"); TEST("\xc4\xe1\xf1\xc4\xc0\x00", "vpinsrw xmm0, xmm1, ax, 0x0");
TEST("\xc4\xe3\x71\x22\xc0\x00", "vpinsrd xmm0, xmm1, eax, 0x0"); TEST("\xc4\xe3\x71\x22\xc0\x00", "vpinsrd xmm0, xmm1, eax, 0x0");

View File

@@ -91,6 +91,10 @@ struct InstrDesc
#define DESC_LOCK(desc) (((desc)->operand_indices >> 11) & 1) #define DESC_LOCK(desc) (((desc)->operand_indices >> 11) & 1)
#define DESC_VSIB(desc) (((desc)->operand_indices >> 15) & 1) #define DESC_VSIB(desc) (((desc)->operand_indices >> 15) & 1)
#define DESC_OPSIZE(desc) (((desc)->reg_types >> 11) & 7) #define DESC_OPSIZE(desc) (((desc)->reg_types >> 11) & 7)
#define DESC_MODRM_SIZE(desc) (((desc)->operand_sizes >> 0) & 3)
#define DESC_MODREG_SIZE(desc) (((desc)->operand_sizes >> 2) & 3)
#define DESC_VEXREG_SIZE(desc) (((desc)->operand_sizes >> 4) & 3)
#define DESC_IMM_SIZE(desc) (((desc)->operand_sizes >> 6) & 3)
#define DESC_LEGACY(desc) (((desc)->operand_sizes >> 8) & 1) #define DESC_LEGACY(desc) (((desc)->operand_sizes >> 8) & 1)
#define DESC_SIZE_FIX1(desc) (((desc)->operand_sizes >> 10) & 7) #define DESC_SIZE_FIX1(desc) (((desc)->operand_sizes >> 10) & 7)
#define DESC_SIZE_FIX2(desc) (((desc)->operand_sizes >> 13) & 3) #define DESC_SIZE_FIX2(desc) (((desc)->operand_sizes >> 13) & 3)
@@ -245,18 +249,17 @@ fd_decode(const uint8_t* buffer, size_t len_sz, int mode_int, uintptr_t address,
{ {
if (byte & 0x08) // Bit 3 of opcode_escape must be clear. if (byte & 0x08) // Bit 3 of opcode_escape must be clear.
return FD_ERR_UD; return FD_ERR_UD;
opcode_escape = (byte & 0x07);
_Static_assert(PREFIX_REXRR == 0x10, "wrong REXRR value"); _Static_assert(PREFIX_REXRR == 0x10, "wrong REXRR value");
if (mode == DECODE_64) if (mode == DECODE_64)
prefix_rex |= (byte & PREFIX_REXRR) ^ PREFIX_REXRR; prefix_rex |= (byte & PREFIX_REXRR) ^ PREFIX_REXRR;
} }
else // 3-byte VEX else // 3-byte VEX
{ {
if (byte & 0x1c) // Bits 4:2 of opcode_escape must be clear. if (byte & 0x18) // Bits 4:3 of opcode_escape must be clear.
return FD_ERR_UD; return FD_ERR_UD;
opcode_escape = (byte & 0x03); // 4 is table index with VEX
} }
opcode_escape = (byte & 0x07);
if (UNLIKELY(opcode_escape == 0)) { if (UNLIKELY(opcode_escape == 0)) {
int prefix_len = vex_prefix == 0x62 ? 4 : 3; int prefix_len = vex_prefix == 0x62 ? 4 : 3;
// Pretend to decode the prefix plus one opcode byte. // Pretend to decode the prefix plus one opcode byte.
@@ -451,14 +454,14 @@ direct:
else if (UNLIKELY(prefix_rex & PREFIX_REXRR)) else if (UNLIKELY(prefix_rex & PREFIX_REXRR))
return FD_ERR_UD; return FD_ERR_UD;
op_modreg->type = FD_OT_REG; op_modreg->type = FD_OT_REG;
op_modreg->size = operand_sizes[(desc->operand_sizes >> 2) & 3]; op_modreg->size = operand_sizes[DESC_MODREG_SIZE(desc)];
op_modreg->reg = reg_idx; op_modreg->reg = reg_idx;
} }
if (DESC_HAS_MODRM(desc)) if (DESC_HAS_MODRM(desc))
{ {
FdOp* op_modrm = &instr->operands[DESC_MODRM_IDX(desc)]; FdOp* op_modrm = &instr->operands[DESC_MODRM_IDX(desc)];
op_modrm->size = operand_sizes[(desc->operand_sizes >> 0) & 3]; op_modrm->size = operand_sizes[DESC_MODRM_SIZE(desc)];
unsigned rm = op_byte & 0x07; unsigned rm = op_byte & 0x07;
if (op_byte >= 0xc0) if (op_byte >= 0xc0)
@@ -475,14 +478,14 @@ direct:
} }
else else
{ {
bool vsib = UNLIKELY(DESC_VSIB(desc)); unsigned dispscale = 0;
if (UNLIKELY(prefix_evex)) {
// EVEX.z for memory destination operand is UD. // EVEX.z for memory destination operand is UD.
if (UNLIKELY(prefix_evex & 0x80) && DESC_MODRM_IDX(desc) == 0) if (UNLIKELY(prefix_evex & 0x80) && DESC_MODRM_IDX(desc) == 0)
return FD_ERR_UD; return FD_ERR_UD;
// EVEX.b for memory-operand without broadcast support is UD. // EVEX.b for memory-operand without broadcast support is UD.
unsigned dispscale = 0;
if (UNLIKELY(prefix_evex & 0x10)) { if (UNLIKELY(prefix_evex & 0x10)) {
if (UNLIKELY(!DESC_EVEX_BCST(desc))) if (UNLIKELY(!DESC_EVEX_BCST(desc)))
return FD_ERR_UD; return FD_ERR_UD;
@@ -493,15 +496,17 @@ direct:
instr->segment |= dispscale << 6; // Store broadcast size instr->segment |= dispscale << 6; // Store broadcast size
op_modrm->type = FD_OT_MEMBCST; op_modrm->type = FD_OT_MEMBCST;
} else { } else {
if (UNLIKELY(prefix_evex))
dispscale = op_modrm->size - 1; dispscale = op_modrm->size - 1;
op_modrm->type = FD_OT_MEM; op_modrm->type = FD_OT_MEM;
} }
} else {
op_modrm->type = FD_OT_MEM;
}
// 16-bit address size implies different ModRM encoding // 16-bit address size implies different ModRM encoding
if (UNLIKELY(addr_size == 1)) { if (UNLIKELY(addr_size == 1)) {
ASSUME(mode == DECODE_32); ASSUME(mode == DECODE_32);
if (vsib) // 16-bit address size + VSIB is UD if (UNLIKELY(DESC_VSIB(desc))) // 16-bit addr size + VSIB is UD
return FD_ERR_UD; return FD_ERR_UD;
if (rm < 6) if (rm < 6)
op_modrm->misc = rm & 1 ? FD_REG_DI : FD_REG_SI; op_modrm->misc = rm & 1 ? FD_REG_DI : FD_REG_SI;
@@ -532,8 +537,7 @@ direct:
// SIB byte // SIB byte
uint8_t base = rm; uint8_t base = rm;
if (rm == 4) if (rm == 4) {
{
if (UNLIKELY(off >= len)) if (UNLIKELY(off >= len))
return FD_ERR_PARTIAL; return FD_ERR_PARTIAL;
uint8_t sib = buffer[off++]; uint8_t sib = buffer[off++];
@@ -541,22 +545,25 @@ direct:
unsigned idx = (sib & 0x38) >> 3; unsigned idx = (sib & 0x38) >> 3;
idx += prefix_rex & PREFIX_REXX ? 8 : 0; idx += prefix_rex & PREFIX_REXX ? 8 : 0;
base = sib & 0x07; base = sib & 0x07;
if (!vsib && idx == 4) if (idx == 4)
idx = FD_REG_NONE; idx = FD_REG_NONE;
if (vsib && prefix_evex) {
// EVEX.V':EVEX.X:SIB.idx
idx |= prefix_evex & 0x8 ? 0 : 0x10;
}
op_modrm->misc = scale | idx; op_modrm->misc = scale | idx;
} } else {
else
{
// VSIB must have a memory operand with SIB byte.
if (vsib)
return FD_ERR_UD;
op_modrm->misc = FD_REG_NONE; op_modrm->misc = FD_REG_NONE;
} }
if (UNLIKELY(DESC_VSIB(desc))) {
// VSIB must have a memory operand with SIB byte.
if (rm != 4)
return FD_ERR_UD;
_Static_assert(FD_REG_NONE == 0x3f, "unexpected FD_REG_NONE");
// idx 4 is valid for VSIB
if ((op_modrm->misc & 0x3f) == FD_REG_NONE)
op_modrm->misc &= 0xc4;
if (prefix_evex) // EVEX.V':EVEX.X:SIB.idx
op_modrm->misc |= prefix_evex & 0x8 ? 0 : 0x10;
}
// RIP-relative addressing only if SIB-byte is absent // RIP-relative addressing only if SIB-byte is absent
if (op_byte < 0x40 && rm == 5 && mode == DECODE_64) if (op_byte < 0x40 && rm == 5 && mode == DECODE_64)
op_modrm->reg = FD_REG_IP; op_modrm->reg = FD_REG_IP;
@@ -592,7 +599,7 @@ direct:
} else { } else {
operand->type = FD_OT_REG; operand->type = FD_OT_REG;
// Without VEX prefix, this encodes an implicit register // Without VEX prefix, this encodes an implicit register
operand->size = operand_sizes[(desc->operand_sizes >> 4) & 3]; operand->size = operand_sizes[DESC_VEXREG_SIZE(desc)];
if (mode == DECODE_32) if (mode == DECODE_32)
vex_operand &= 0x7; vex_operand &= 0x7;
// Note: 32-bit will never UD here. EVEX.V' is caught above already. // Note: 32-bit will never UD here. EVEX.V' is caught above already.
@@ -628,7 +635,7 @@ direct:
// 2 = memory, address-sized, used for mov with moffs operand // 2 = memory, address-sized, used for mov with moffs operand
FdOp* operand = &instr->operands[DESC_IMM_IDX(desc)]; FdOp* operand = &instr->operands[DESC_IMM_IDX(desc)];
operand->type = FD_OT_MEM; operand->type = FD_OT_MEM;
operand->size = operand_sizes[(desc->operand_sizes >> 6) & 3]; operand->size = operand_sizes[DESC_IMM_SIZE(desc)];
operand->reg = FD_REG_NONE; operand->reg = FD_REG_NONE;
operand->misc = FD_REG_NONE; operand->misc = FD_REG_NONE;
@@ -675,9 +682,9 @@ direct:
if (UNLIKELY(off + 1 > len)) if (UNLIKELY(off + 1 > len))
return FD_ERR_PARTIAL; return FD_ERR_PARTIAL;
instr->imm = (int8_t) LOAD_LE_1(&buffer[off++]); instr->imm = (int8_t) LOAD_LE_1(&buffer[off++]);
operand->size = desc->operand_sizes & 0x40 ? 1 : op_size; operand->size = DESC_IMM_SIZE(desc) & 1 ? 1 : op_size;
} else { } else {
operand->size = operand_sizes[(desc->operand_sizes >> 6) & 3]; operand->size = operand_sizes[DESC_IMM_SIZE(desc)];
uint8_t imm_size; uint8_t imm_size;
if (UNLIKELY(instr->type == FDI_RET || instr->type == FDI_RETF || if (UNLIKELY(instr->type == FDI_RET || instr->type == FDI_RETF ||
@@ -760,9 +767,9 @@ skip_modrm:
return FD_ERR_UD; return FD_ERR_UD;
} }
instr->operandsz = 0;
} else {
instr->operandsz = UNLIKELY(DESC_INSTR_WIDTH(desc)) ? op_size - 1 : 0; instr->operandsz = UNLIKELY(DESC_INSTR_WIDTH(desc)) ? op_size - 1 : 0;
} else {
instr->operandsz = 0;
} }
instr->size = off; instr->size = off;

View File

@@ -274,36 +274,36 @@ struct EncodingInfo {
const struct EncodingInfo encoding_infos[ENC_MAX] = { const struct EncodingInfo encoding_infos[ENC_MAX] = {
[ENC_INVALID] = { 0 }, [ENC_INVALID] = { 0 },
[ENC_NP] = { 0 }, [ENC_NP] = { 0 },
[ENC_M] = { .modrm = 0^3 }, [ENC_M] = { .modrm = 0x0^3 },
[ENC_M1] = { .modrm = 0^3, .immctl = 1, .immidx = 1 }, [ENC_M1] = { .modrm = 0x0^3, .immctl = 1, .immidx = 1 },
[ENC_MI] = { .modrm = 0^3, .immctl = 4, .immidx = 1 }, [ENC_MI] = { .modrm = 0x0^3, .immctl = 4, .immidx = 1 },
[ENC_MC] = { .modrm = 0^3, .zregidx = 1^3, .zregval = 1 }, [ENC_MC] = { .modrm = 0x0^3, .zregidx = 0x1^3, .zregval = 1 },
[ENC_MR] = { .modrm = 0^3, .modreg = 1^3 }, [ENC_MR] = { .modrm = 0x0^3, .modreg = 0x1^3 },
[ENC_RM] = { .modrm = 1^3, .modreg = 0^3 }, [ENC_RM] = { .modrm = 0x1^3, .modreg = 0x0^3 },
[ENC_RMA] = { .modrm = 1^3, .modreg = 0^3, .zregidx = 2^3, .zregval = 0 }, [ENC_RMA] = { .modrm = 0x1^3, .modreg = 0x0^3, .zregidx = 0x2^3, .zregval = 0 },
[ENC_MRI] = { .modrm = 0^3, .modreg = 1^3, .immctl = 4, .immidx = 2 }, [ENC_MRI] = { .modrm = 0x0^3, .modreg = 0x1^3, .immctl = 4, .immidx = 2 },
[ENC_RMI] = { .modrm = 1^3, .modreg = 0^3, .immctl = 4, .immidx = 2 }, [ENC_RMI] = { .modrm = 0x1^3, .modreg = 0x0^3, .immctl = 4, .immidx = 2 },
[ENC_MRC] = { .modrm = 0^3, .modreg = 1^3, .zregidx = 2^3, .zregval = 1 }, [ENC_MRC] = { .modrm = 0x0^3, .modreg = 0x1^3, .zregidx = 0x2^3, .zregval = 1 },
[ENC_AM] = { .modrm = 1^3, .zregidx = 0^3, .zregval = 0 }, [ENC_AM] = { .modrm = 0x1^3, .zregidx = 0x0^3, .zregval = 0 },
[ENC_MA] = { .modrm = 0^3, .zregidx = 1^3, .zregval = 0 }, [ENC_MA] = { .modrm = 0x0^3, .zregidx = 0x1^3, .zregval = 0 },
[ENC_I] = { .immctl = 4, .immidx = 0 }, [ENC_I] = { .immctl = 4, .immidx = 0 },
[ENC_IA] = { .zregidx = 0^3, .zregval = 0, .immctl = 4, .immidx = 1 }, [ENC_IA] = { .zregidx = 0x0^3, .zregval = 0, .immctl = 4, .immidx = 1 },
[ENC_O] = { .modreg = 0^3 }, [ENC_O] = { .modreg = 0x0^3 },
[ENC_OI] = { .modreg = 0^3, .immctl = 4, .immidx = 1 }, [ENC_OI] = { .modreg = 0x0^3, .immctl = 4, .immidx = 1 },
[ENC_OA] = { .modreg = 0^3, .zregidx = 1^3, .zregval = 0 }, [ENC_OA] = { .modreg = 0x0^3, .zregidx = 0x1^3, .zregval = 0 },
[ENC_S] = { 0 }, [ENC_S] = { 0 },
[ENC_A] = { .zregidx = 0^3, .zregval = 0 }, [ENC_A] = { .zregidx = 0x0^3, .zregval = 0 },
[ENC_D] = { .immctl = 6, .immidx = 0 }, [ENC_D] = { .immctl = 6, .immidx = 0 },
[ENC_FD] = { .zregidx = 0^3, .zregval = 0, .immctl = 2, .immidx = 1 }, [ENC_FD] = { .zregidx = 0x0^3, .zregval = 0, .immctl = 2, .immidx = 1 },
[ENC_TD] = { .zregidx = 1^3, .zregval = 0, .immctl = 2, .immidx = 0 }, [ENC_TD] = { .zregidx = 0x1^3, .zregval = 0, .immctl = 2, .immidx = 0 },
[ENC_RVM] = { .modrm = 2^3, .modreg = 0^3, .vexreg = 1^3 }, [ENC_RVM] = { .modrm = 0x2^3, .modreg = 0x0^3, .vexreg = 0x1^3 },
[ENC_RVMI] = { .modrm = 2^3, .modreg = 0^3, .vexreg = 1^3, .immctl = 4, .immidx = 3 }, [ENC_RVMI] = { .modrm = 0x2^3, .modreg = 0x0^3, .vexreg = 0x1^3, .immctl = 4, .immidx = 3 },
[ENC_RVMR] = { .modrm = 2^3, .modreg = 0^3, .vexreg = 1^3, .immctl = 3, .immidx = 3 }, [ENC_RVMR] = { .modrm = 0x2^3, .modreg = 0x0^3, .vexreg = 0x1^3, .immctl = 3, .immidx = 3 },
[ENC_RMV] = { .modrm = 1^3, .modreg = 0^3, .vexreg = 2^3 }, [ENC_RMV] = { .modrm = 0x1^3, .modreg = 0x0^3, .vexreg = 0x2^3 },
[ENC_VM] = { .modrm = 1^3, .vexreg = 0^3 }, [ENC_VM] = { .modrm = 0x1^3, .vexreg = 0x0^3 },
[ENC_VMI] = { .modrm = 1^3, .vexreg = 0^3, .immctl = 4, .immidx = 2 }, [ENC_VMI] = { .modrm = 0x1^3, .vexreg = 0x0^3, .immctl = 4, .immidx = 2 },
[ENC_MVR] = { .modrm = 0^3, .modreg = 2^3, .vexreg = 1^3 }, [ENC_MVR] = { .modrm = 0x0^3, .modreg = 0x2^3, .vexreg = 0x1^3 },
[ENC_MRV] = { .modrm = 0^3, .modreg = 1^3, .vexreg = 2^3 }, [ENC_MRV] = { .modrm = 0x0^3, .modreg = 0x1^3, .vexreg = 0x2^3 },
}; };
static const uint64_t alt_tab[] = { static const uint64_t alt_tab[] = {

View File

@@ -26,7 +26,7 @@ struct FdStr {
unsigned sz; unsigned sz;
}; };
#define fd_stre(s) ((struct FdStr) { (s "\0\0\0\0\0\0\0\0\0\0"), sizeof (s)-1 }) #define fd_stre(s) ((struct FdStr) { (s "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"), sizeof (s)-1 })
static char* static char*
fd_strpcat(char* restrict dst, struct FdStr src) { fd_strpcat(char* restrict dst, struct FdStr src) {

View File

@@ -1026,7 +1026,7 @@ VEX.F2.0f7c RVM Vx Hx Wx - VHADDPS F=AVX
VEX.66.0f7d RVM Vx Hx Wx - VHSUBPD F=AVX VEX.66.0f7d RVM Vx Hx Wx - VHSUBPD F=AVX
VEX.F2.0f7d RVM Vx Hx Wx - VHSUBPS F=AVX VEX.F2.0f7d RVM Vx Hx Wx - VHSUBPS F=AVX
VEX.66.W0.L0.0f7e MR Ey Vy - - VMOVD_X2G F=AVX ENC_NOSZ VEX.66.W0.L0.0f7e MR Ey Vy - - VMOVD_X2G F=AVX ENC_NOSZ
VEX.66.W1.L0.0f7e MR Ey Vy - - VMOVQ_X2G I64 F=AVX ENC_NOSZ VEX.66.W1.L0.0f7e MR Ey Vy - - VMOVD_X2G I64 F=AVX ENC_NOSZ
VEX.66.W1.L0.0f7e MR Ey Vy - - VMOVQ_X2G O64 F=AVX ENC_NOSZ VEX.66.W1.L0.0f7e MR Ey Vy - - VMOVQ_X2G O64 F=AVX ENC_NOSZ
VEX.F3.L0.0f7e RM Vq Wq - - VMOVQ F=AVX ENC_NOSZ VEX.F3.L0.0f7e RM Vq Wq - - VMOVQ F=AVX ENC_NOSZ
VEX.66.0f7f MR Wx Vx - - VMOVDQA F=AVX VEX.66.0f7f MR Wx Vx - - VMOVDQA F=AVX

View File

@@ -11,6 +11,12 @@ if not py_version.version_compare('>=3.6')
endif endif
cc = meson.get_compiler('c') cc = meson.get_compiler('c')
if get_option('wasm_build')
add_project_arguments('--target=wasm32', language: 'c')
add_project_arguments(['-nostdlib', '-fvisibility=default'], language: 'c')
endif
if cc.has_argument('-fstrict-aliasing') if cc.has_argument('-fstrict-aliasing')
add_project_arguments('-fstrict-aliasing', language: 'c') add_project_arguments('-fstrict-aliasing', language: 'c')
endif endif
@@ -99,11 +105,13 @@ fadec = declare_dependency(link_with: libfadec,
sources: tables) sources: tables)
install_headers(headers) install_headers(headers)
foreach component : components if get_option('wasm_build') == false
foreach component : components
test(component, executable('@0@-test'.format(component), test(component, executable('@0@-test'.format(component),
'@0@-test.c'.format(component), '@0@-test.c'.format(component),
dependencies: fadec)) dependencies: fadec))
endforeach endforeach
endif
if meson.version().version_compare('>=0.54.0') if meson.version().version_compare('>=0.54.0')
meson.override_dependency('fadec', fadec) meson.override_dependency('fadec', fadec)

View File

@@ -4,3 +4,4 @@ option('with_decode', type: 'boolean', value: true)
option('with_encode', type: 'boolean', value: true) option('with_encode', type: 'boolean', value: true)
# encode2 is off-by-default to reduce size and compile-time # encode2 is off-by-default to reduce size and compile-time
option('with_encode2', type: 'boolean', value: false) option('with_encode2', type: 'boolean', value: false)
option('wasm_build', type: 'boolean', value: false)

View File

@@ -276,17 +276,17 @@ class InstrDesc(NamedTuple):
else: # either empty or GP operand size else: # either empty or GP operand size
dynsizes = [OpKind.SZ_OP] dynsizes = [OpKind.SZ_OP]
if "SZ8" in self.flags: if "SZ8" in self.flags:
extraflags["opsize"] = 1
dynsizes = [] dynsizes = []
if "D64" in self.flags: extraflags["opsize"] = 2 if "D64" in self.flags: extraflags["opsize"] = 2
if "F64" in self.flags: extraflags["opsize"] = 3 if "F64" in self.flags: extraflags["opsize"] = 3
extraflags["instr_width"] = "INSTR_WIDTH" in self.flags
extraflags["lock"] = "LOCK" in self.flags extraflags["lock"] = "LOCK" in self.flags
if "SZ8" in self.flags or mnem in ("MOVSX", "MOVZX", "XCHG_NOP", "3DNOW"): if (self.flags & {"SZ8", "INSTR_WIDTH"} or
if "SZ8" not in self.flags and "INSTR_WIDTH" in self.flags: mnem in ("MOVSX", "MOVZX", "XCHG_NOP", "3DNOW")):
raise Exception("legacy instr with +w without SZ8")
extraflags["legacy"] = 1 extraflags["legacy"] = 1
# INSTR_WIDTH defaults to zero, so only enable when SZ8 is unset
if "INSTR_WIDTH" in self.flags and "SZ8" not in self.flags:
extraflags["instr_width"] = 1
imm_byte = self.imm_size(4) == 1 imm_byte = self.imm_size(4) == 1
extraflags["imm_control"] = flags.imm_control | imm_byte extraflags["imm_control"] = flags.imm_control | imm_byte