mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-02-17 17:19:35 +08:00
apx: smarter determination of REX2 prefix eligibility
REX2 encoding is mostly default, so flag the instruction patters which do *not* support REX2 instead. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
This commit is contained in:
parent
fd08822070
commit
dda9152b35
@ -112,7 +112,10 @@ static void add_asp(insn *, int);
|
||||
static int process_ea(operand *, ea *, int, int, opflags_t,
|
||||
insn *, enum ea_type, const char **);
|
||||
|
||||
/* Return any of REX_[BXR]1 corresponding to non-GPR registers */
|
||||
/*
|
||||
* Return any of REX_[BXR]1 corresponding to non-GPR registers by
|
||||
* masking them with the REX_[BXR]V flags.
|
||||
*/
|
||||
static inline uint32_t rex_highvec(uint32_t rexflags)
|
||||
{
|
||||
return rexflags & (rexflags >> 4) & REX_BXR1;
|
||||
@ -1793,7 +1796,7 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
|
||||
} else {
|
||||
/* VEX */
|
||||
if (ins->vexreg > 15 || (ins->rex & REX_BXR1)) {
|
||||
nasm_nonfatal("invalid high-16 register in non-AVX-512");
|
||||
nasm_nonfatal("invalid high-16 register in VEX encoded instruction");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1811,28 +1814,28 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
|
||||
}
|
||||
} else if (ins->rex & (REX_BXR1 | REX_2)) {
|
||||
/* REX2 prefix needed */
|
||||
if (!itemp_has(temp, IF_REX2) || rex_highvec(ins->rex)) {
|
||||
nasm_nonfatal("this use of registers 16-31 not supported for this instruction");
|
||||
return -1;
|
||||
}
|
||||
if (ins->rex & REX_H) {
|
||||
nasm_nonfatal("cannot use high byte register in rex2 instruction");
|
||||
return -1;
|
||||
}
|
||||
if (bits != 64) {
|
||||
nasm_nonfatal("invalid operands in non-64-bit mode");
|
||||
nasm_nonfatal("invalid operands in %d-bit mode", bits);
|
||||
return -1;
|
||||
}
|
||||
if (!iflag_test(&cpu, IF_APX)) {
|
||||
nasm_nonfatal("invalid operands in non-APX mode");
|
||||
return -1;
|
||||
}
|
||||
if (itemp_has(temp, IF_NOAPX) || rex_highvec(ins->rex)) {
|
||||
nasm_nonfatal("this use of registers 16-31 not supported for this instruction");
|
||||
return -1;
|
||||
}
|
||||
if (ins->rex & REX_H) {
|
||||
nasm_nonfatal("cannot use high byte register in this instruction");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ins->rex |= REX_2 | REX_P;
|
||||
length += 2;
|
||||
} else if (ins->rex & REX_MASK) {
|
||||
if (ins->rex & REX_H) {
|
||||
nasm_nonfatal("cannot use high byte register in rex instruction");
|
||||
nasm_nonfatal("cannot use high byte register in this instruction");
|
||||
return -1;
|
||||
} else if (bits == 64) {
|
||||
ins->rex &= ~REX_L;
|
||||
@ -1845,7 +1848,7 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
|
||||
lockcheck = false; /* Already errored, no need for warning */
|
||||
ins->rex &= ~REX_P;
|
||||
} else {
|
||||
nasm_nonfatal("invalid operands in non-64-bit mode");
|
||||
nasm_nonfatal("invalid operands in %d-bit mode", bits);
|
||||
return -1;
|
||||
}
|
||||
length++;
|
||||
@ -2522,23 +2525,26 @@ static uint32_t rexflags(int val, opflags_t flags, uint32_t mask)
|
||||
{
|
||||
uint32_t rex = 0;
|
||||
|
||||
if (val >= 0) {
|
||||
if (val & 8)
|
||||
rex |= REX_B|REX_X|REX_R;
|
||||
if (val & 16)
|
||||
rex |= REX_B1|REX_X1|REX_R1;
|
||||
if (val < 0 || !is_class(REGISTER, flags)) {
|
||||
/* Not a register */
|
||||
return 0;
|
||||
}
|
||||
if (flags & BITS64)
|
||||
rex |= REX_W;
|
||||
|
||||
if (!is_class(REG_GPR, flags)) {
|
||||
if (!is_class(REG_CDT, flags))
|
||||
rex |= REX_BV|REX_XV|REX_RV;
|
||||
if (val & 8)
|
||||
rex |= REX_B|REX_X|REX_R;
|
||||
if (val & 16)
|
||||
rex |= REX_B1|REX_X1|REX_R1;
|
||||
|
||||
if (flags & REG_CLASS_VECTOR) {
|
||||
rex |= REX_BV|REX_XV|REX_RV;
|
||||
} else if (is_class(REG8, flags)) {
|
||||
if (is_class(REG_HIGH, flags)) /* AH, CH, DH, BH */
|
||||
if (is_class(REG_HIGH, flags)) {
|
||||
/* AH, CH, DH, BH: REX/REX2/VEX/EVEX forbidden */
|
||||
rex |= REX_H;
|
||||
else if (val >= 4) /* SPL, BPL, SIL, DIL */
|
||||
} else if (val >= 4) {
|
||||
/* SPL, BPL, SIL, DIL, or extended: prefix required */
|
||||
rex |= REX_P;
|
||||
}
|
||||
}
|
||||
|
||||
return rex & mask;
|
||||
@ -2711,12 +2717,16 @@ static enum match_result matches(const struct itemplate *itemp,
|
||||
return MERR_ENCMISMATCH;
|
||||
break;
|
||||
case P_REX:
|
||||
if (itemp_has(itemp, IF_VEX) || itemp_has(itemp, IF_EVEX) ||
|
||||
bits != 64)
|
||||
if (bits != 64 ||
|
||||
itemp_has(itemp, IF_VEX) ||
|
||||
itemp_has(itemp, IF_EVEX) ||
|
||||
itemp_has(itemp, IF_REX2))
|
||||
return MERR_ENCMISMATCH;
|
||||
break;
|
||||
case P_REX2:
|
||||
if (!itemp_has(itemp, IF_REX2) || bits != 64)
|
||||
if (bits != 64 ||
|
||||
itemp_has(itemp, IF_NOAPX) ||
|
||||
itemp_has(itemp, IF_EVEX))
|
||||
return MERR_ENCMISMATCH;
|
||||
break;
|
||||
default:
|
||||
@ -2729,6 +2739,9 @@ static enum match_result matches(const struct itemplate *itemp,
|
||||
} else if (itemp_has(itemp, IF_LATEVEX)) {
|
||||
if (!iflag_test(&cpu, IF_LATEVEX) && iflag_test(&cpu, IF_EVEX))
|
||||
return MERR_ENCMISMATCH;
|
||||
} else if (itemp_has(itemp, IF_REX2)) {
|
||||
if (bits != 64 || !iflag_test(&cpu, IF_APX))
|
||||
return MERR_ENCMISMATCH;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -180,18 +180,24 @@
|
||||
#define REG_CLASS_BND GEN_REG_CLASS(9)
|
||||
#define REG_CLASS_RM_TMM GEN_REG_CLASS(10)
|
||||
|
||||
/* Verify value to be a valid register */
|
||||
static inline bool is_register(opflags_t reg)
|
||||
{
|
||||
return reg >= EXPR_REG_START && reg < REG_ENUM_LIMIT;
|
||||
}
|
||||
/* Register classes treated as vectors for EVEX/REX2 encoding purposes */
|
||||
#define REG_CLASS_VECTOR (REG_CLASS_RM_XMM|REG_CLASS_RM_YMM|\
|
||||
REG_CLASS_RM_ZMM|REG_CLASS_RM_TMM)
|
||||
|
||||
/* Helper function to test for a value matching a class */
|
||||
static inline bool is_class(opflags_t class, opflags_t op)
|
||||
{
|
||||
return !(class & ~op);
|
||||
}
|
||||
|
||||
static inline bool is_reg_class(opflags_t class, opflags_t reg)
|
||||
/* Verify a token value is a valid register */
|
||||
static inline bool is_register(int reg)
|
||||
{
|
||||
return reg >= EXPR_REG_START && reg < REG_ENUM_LIMIT;
|
||||
}
|
||||
|
||||
/* Helper function to test if a token is a register matching a class */
|
||||
static inline bool is_reg_class(opflags_t class, int reg)
|
||||
{
|
||||
if (!is_register(reg))
|
||||
return false;
|
||||
|
42
test/apx.asm
42
test/apx.asm
@ -31,3 +31,45 @@
|
||||
add [rdx],cl
|
||||
add {evex} [rdx],cl
|
||||
add {nf} [rdx],cl
|
||||
|
||||
add al,[rdx],r25b
|
||||
add {nf} al,[rdx],r25b
|
||||
add [rdx],r25b
|
||||
add {evex} [rdx],r25b
|
||||
add {nf} [rdx],r25b
|
||||
|
||||
add al,[r27],cl
|
||||
add {nf} al,[r27],cl
|
||||
add [r27],cl
|
||||
add {evex} [r27],cl
|
||||
add {nf} [r27],cl
|
||||
|
||||
add al,[r27],r25b
|
||||
add {nf} al,[r27],r25b
|
||||
add [r27],r25b
|
||||
add {evex} [r27],r25b
|
||||
add {nf} [r27],r25b
|
||||
|
||||
add eax,[rdx],ecx
|
||||
add {nf} eax,[rdx],ecx
|
||||
add [rdx],ecx
|
||||
add {evex} [rdx],ecx
|
||||
add {nf} [rdx],ecx
|
||||
|
||||
add eax,[rdx],r25d
|
||||
add {nf} eax,[rdx],r25d
|
||||
add [rdx],r25d
|
||||
add {evex} [rdx],r25d
|
||||
add {nf} [rdx],r25d
|
||||
|
||||
add eax,[r27],ecx
|
||||
add {nf} eax,[r27],ecx
|
||||
add [r27],ecx
|
||||
add {evex} [r27],ecx
|
||||
add {nf} [r27],ecx
|
||||
|
||||
add eax,[r27],r25d
|
||||
add {nf} eax,[r27],r25d
|
||||
add [r27],r25d
|
||||
add {evex} [r27],r25d
|
||||
add {nf} [r27],r25d
|
||||
|
@ -31,6 +31,22 @@ if_("LATEVEX", "Only if EVEX instructions are disabled");
|
||||
#
|
||||
if_align('FEATURE');
|
||||
|
||||
#
|
||||
# Encoding flags
|
||||
#
|
||||
if_("VEX", "VEX or XOP encoded instruction");
|
||||
if_("EVEX", "EVEX encoded instruction");
|
||||
if_("NOAPX", "Instruction does not support APX registers");
|
||||
if_("REX2", "REX2 encoding required");
|
||||
if_("NF", "Instruction supports the {nf} prefix");
|
||||
if_("LIG", "Ignore VEX/EVEX L field");
|
||||
if_("WIG", "Ignore VEX/EVEX W field");
|
||||
if_("WW", "VEX/EVEX W is REX.W");
|
||||
if_("SIB", "SIB encoding required");
|
||||
|
||||
#
|
||||
# Feature filtering flags
|
||||
#
|
||||
if_("PRIV", "Privileged instruction");
|
||||
if_("SMM", "Only valid in SMM");
|
||||
if_("PROT", "Protected mode only");
|
||||
@ -40,7 +56,6 @@ if_("NOLONG", "Not available in long mode");
|
||||
if_("LONG", "Long mode");
|
||||
if_("NOHLE", "HLE prefixes forbidden");
|
||||
if_("MIB", "split base/index EA");
|
||||
if_("SIB", "SIB encoding required");
|
||||
if_("BND", "BND (0xF2) prefix available");
|
||||
if_("UNDOC", "Undocumented");
|
||||
if_("HLE", "HLE prefixed");
|
||||
@ -123,18 +138,6 @@ if_("OBSOLETE", "Instruction removed from architecture");
|
||||
if_("NEVER", "Instruction never implemented");
|
||||
if_("NOP", "Instruction is always a (nonintentional) NOP");
|
||||
|
||||
#
|
||||
# Encoding flags
|
||||
#
|
||||
if_("VEX", "VEX or XOP encoded instruction");
|
||||
if_("EVEX", "EVEX encoded instruction");
|
||||
if_("REXX", "Instruction supports REX2 encoding");
|
||||
if_("REX2", "Instruction requires REX2 encoding");
|
||||
if_("NF", "Instruction supports the {nf} prefix");
|
||||
if_("LIG", "Ignore VEX/EVEX L field");
|
||||
if_("WIG", "Ignore VEX/EVEX W field");
|
||||
if_("WW", "VEX/EVEX W is REX.W");
|
||||
|
||||
#
|
||||
# special immediates types like {dfv=}
|
||||
#
|
||||
|
@ -194,8 +194,8 @@ AND mem,imm32 [mi: hle o32 81 /4 id] 386,SM,LOCK
|
||||
AND rm8,imm [mi: hle 82 /4 ib] 8086,SM,LOCK,ND,NOLONG
|
||||
ARPL mem,reg16 [mr: 63 /r] 286,PROT,SM,NOLONG
|
||||
ARPL reg16,reg16 [mr: 63 /r] 286,PROT,NOLONG
|
||||
BB0_RESET void [ 0f 3a] PENT,CYRIX,ND,OBSOLETE
|
||||
BB1_RESET void [ 0f 3b] PENT,CYRIX,ND,OBSOLETE
|
||||
BB0_RESET void [ 0f 3a] PENT,CYRIX,NOLONG,OBSOLETE,ND
|
||||
BB1_RESET void [ 0f 3b] PENT,CYRIX,NOLONG,OBSOLETE,ND
|
||||
BOUND reg16,mem [rm: o16 62 /r] 186,NOLONG
|
||||
BOUND reg32,mem [rm: o32 62 /r] 386,NOLONG
|
||||
BSF reg16,mem [rm: o16 nof3 0f bc /r] 386,SM
|
||||
@ -326,10 +326,10 @@ CMP mem,imm16 [mi: o16 81 /7 iw] 8086,SM
|
||||
CMP mem,sbytedword32 [mi: o32 83 /7 ib,s] 386,SM,ND
|
||||
CMP mem,imm32 [mi: o32 81 /7 id] 386,SM
|
||||
CMP rm8,imm [mi: 82 /7 ib] 8086,SM,ND,NOLONG
|
||||
CMPSB void [ repe a6] 8086
|
||||
CMPSD void [ repe o32 a7] 386
|
||||
CMPSQ void [ repe o64 a7] X86_64,LONG
|
||||
CMPSW void [ repe o16 a7] 8086
|
||||
CMPSB void [ repe a6] 8086,NOAPX
|
||||
CMPSD void [ repe o32 a7] 386,NOAPX
|
||||
CMPSQ void [ repe o64 a7] X86_64,LONG,NOAPX
|
||||
CMPSW void [ repe o16 a7] 8086,NOAPX
|
||||
CMPXCHG mem,reg8 [mr: hle 0f b0 /r] PENT,SM,LOCK
|
||||
CMPXCHG reg8,reg8 [mr: 0f b0 /r] PENT
|
||||
CMPXCHG mem,reg16 [mr: hle o16 0f b1 /r] PENT,SM,LOCK
|
||||
@ -347,8 +347,8 @@ CMPXCHG486 reg32,reg32 [mr: o32 0f a7 /r] 486,UNDOC,ND,OBSOLETE
|
||||
CMPXCHG8B mem64 [m: hle norexw 0f c7 /1] PENT,LOCK
|
||||
CMPXCHG16B mem128 [m: o64 0f c7 /1] X86_64,LONG,LOCK
|
||||
CPUID void [ 0f a2] PENT
|
||||
CPU_READ void [ 0f 3d] PENT,CYRIX
|
||||
CPU_WRITE void [ 0f 3c] PENT,CYRIX
|
||||
CPU_READ void [ 0f 3d] PENT,CYRIX,NOAPX
|
||||
CPU_WRITE void [ 0f 3c] PENT,CYRIX,NOAPX
|
||||
CQO void [ o64 99] X86_64,LONG
|
||||
CWD void [ o16 99] 8086
|
||||
CWDE void [ o32 98] 386
|
||||
@ -364,7 +364,7 @@ DIV rm8 [m: f6 /6] 8086
|
||||
DIV rm16 [m: o16 f7 /6] 8086
|
||||
DIV rm32 [m: o32 f7 /6] 386
|
||||
DIV rm64 [m: o64 f7 /6] X86_64,LONG
|
||||
DMINT void [ 0f 39] P6,CYRIX
|
||||
DMINT void [ 0f 39] P6,CYRIX,NOAPX
|
||||
EMMS void [ 0f 77] PENT,MMX
|
||||
ENTER imm,imm [ij: c8 iw ib,u] 186
|
||||
EQU imm ignore 8086
|
||||
@ -1121,10 +1121,10 @@ RCR rm32,imm8 [mi: o32 c1 /3 ib,u] 386
|
||||
RCR rm64,unity [m-: o64 d1 /3] X86_64,LONG
|
||||
RCR rm64,reg_cl [m-: o64 d3 /3] X86_64,LONG
|
||||
RCR rm64,imm8 [mi: o64 c1 /3 ib,u] X86_64,LONG
|
||||
RDSHR rm32 [m: o32 0f 36 /0] P6,CYRIX,SMM
|
||||
RDMSR void [ 0f 32] PENT,PRIV
|
||||
RDPMC void [ 0f 33] P6
|
||||
RDTSC void [ 0f 31] PENT
|
||||
RDSHR rm32 [m: o32 0f 36 /0] P6,CYRIX,SMM,NOAPX
|
||||
RDMSR void [ 0f 32] PENT,PRIV,NOAPX
|
||||
RDPMC void [ 0f 33] P6,NOAPX
|
||||
RDTSC void [ 0f 31] PENT,NOAPX
|
||||
RDTSCP void [ 0f 01 f9] X86_64
|
||||
RET void [ c3] 8086,BND
|
||||
RET imm [i: c2 iw] 8086,SW,BND
|
||||
@ -1372,8 +1372,8 @@ SVLDT mem80 [m: 0f 7a /0] 486,CYRIX,SMM,ND
|
||||
SVTS mem80 [m: 0f 7c /0] 486,CYRIX,SMM
|
||||
SWAPGS void [ 0f 01 f8] X86_64,LONG
|
||||
SYSCALL void [ 0f 05] P6,AMD
|
||||
SYSENTER void [ 0f 34] P6
|
||||
SYSEXIT void [ 0f 35] P6,PRIV
|
||||
SYSENTER void [ 0f 34] P6,NOAPX
|
||||
SYSEXIT void [ 0f 35] P6,PRIV,NOAPX
|
||||
SYSRET void [ 0f 07] P6,PRIV,AMD
|
||||
TEST mem,reg8 [mr: 84 /r] 8086,SM
|
||||
TEST reg8,reg8 [mr: 84 /r] 8086
|
||||
@ -1432,8 +1432,8 @@ VERW mem16 [m: 0f 00 /5] 286,PROT
|
||||
VERW reg16 [m: 0f 00 /5] 286,PROT
|
||||
FWAIT void [ wait] 8086
|
||||
WBINVD void [ 0f 09] 486,PRIV
|
||||
WRSHR rm32 [m: o32 0f 37 /0] P6,CYRIX,SMM
|
||||
WRMSR void [ 0f 30] PENT,PRIV
|
||||
WRSHR rm32 [m: o32 0f 37 /0] P6,CYRIX,SMM,NOAPX
|
||||
WRMSR void [ 0f 30] PENT,PRIV,NOAPX
|
||||
XADD mem,reg8 [mr: hle 0f c0 /r] 486,SM,LOCK
|
||||
XADD reg8,reg8 [mr: 0f c0 /r] 486
|
||||
XADD mem,reg16 [mr: hle o16 0f c1 /r] 486,SM,LOCK
|
||||
@ -1514,13 +1514,13 @@ CMOVcc reg32,mem [rm: o32 0f 40+c /r] P6,SM
|
||||
CMOVcc reg32,reg32 [rm: o32 0f 40+c /r] P6
|
||||
CMOVcc reg64,mem [rm: o64 0f 40+c /r] X86_64,LONG,SM
|
||||
CMOVcc reg64,reg64 [rm: o64 0f 40+c /r] X86_64,LONG
|
||||
Jcc imm|near [i: odf 0f 80+c rel] 386,BND
|
||||
Jcc imm|near [i: odf 0f 80+c rel] 386,BND,NOAPX
|
||||
Jcc imm16|near [i: o16 0f 80+c rel] 386,NOLONG,BND
|
||||
Jcc imm32|near [i: o32 0f 80+c rel] 386,NOLONG,BND
|
||||
Jcc imm64|near [i: o64nw 0f 80+c rel] X86_64,LONG,BND
|
||||
Jcc imm64|near [i: o64nw 0f 80+c rel] X86_64,LONG,BND,NOAPX
|
||||
Jcc imm|short [i: 70+c rel8] 8086,ND,BND
|
||||
Jcc imm [i: jcc8 70+c rel8] 8086,ND,BND
|
||||
Jcc imm [i: 0f 80+c rel] 386,ND,BND
|
||||
Jcc imm [i: 0f 80+c rel] 386,ND,BND,NOAPX
|
||||
Jcc imm [i: 71+c jlen e9 rel] 8086,ND,BND
|
||||
Jcc imm [i: 70+c rel8] 8086,BND
|
||||
|
||||
@ -1616,18 +1616,18 @@ FXSAVE64 mem [m: o64 np 0f ae /0] X86_64,LONG,SSE,FPU
|
||||
; of CPU feature bits.
|
||||
XGETBV void [ 0f 01 d0] NEHALEM
|
||||
XSETBV void [ 0f 01 d1] NEHALEM,PRIV
|
||||
XSAVE mem [m: np 0f ae /4] NEHALEM
|
||||
XSAVE64 mem [m: o64 np 0f ae /4] LONG,NEHALEM
|
||||
XSAVEC mem [m: np 0f c7 /4] FUTURE
|
||||
XSAVEC64 mem [m: o64 np 0f c7 /4] LONG,FUTURE
|
||||
XSAVEOPT mem [m: np 0f ae /6] FUTURE
|
||||
XSAVEOPT64 mem [m: o64 np 0f ae /6] LONG,FUTURE
|
||||
XSAVES mem [m: np 0f c7 /5] FUTURE
|
||||
XSAVES64 mem [m: o64 np 0f c7 /5] LONG,FUTURE
|
||||
XRSTOR mem [m: np 0f ae /5] NEHALEM
|
||||
XRSTOR64 mem [m: o64 np 0f ae /5] LONG,NEHALEM
|
||||
XRSTORS mem [m: np 0f c7 /3] FUTURE
|
||||
XRSTORS64 mem [m: o64 np 0f c7 /3] LONG,FUTURE
|
||||
XSAVE mem [m: np 0f ae /4] NEHALEM,NOAPX
|
||||
XSAVE64 mem [m: o64 np 0f ae /4] LONG,NEHALEM,NOAPX
|
||||
XSAVEC mem [m: np 0f c7 /4] FUTURE,NOAPX
|
||||
XSAVEC64 mem [m: o64 np 0f c7 /4] LONG,FUTURE,NOAPX
|
||||
XSAVEOPT mem [m: np 0f ae /6] FUTURE,NOAPX
|
||||
XSAVEOPT64 mem [m: o64 np 0f ae /6] LONG,FUTURE,NOAPX
|
||||
XSAVES mem [m: np 0f c7 /5] FUTURE,NOAPX
|
||||
XSAVES64 mem [m: o64 np 0f c7 /5] LONG,FUTURE,NOAPX
|
||||
XRSTOR mem [m: np 0f ae /5] NEHALEM,NOAPX
|
||||
XRSTOR64 mem [m: o64 np 0f ae /5] LONG,NEHALEM,NOAPX
|
||||
XRSTORS mem [m: np 0f c7 /3] FUTURE,NOAPX
|
||||
XRSTORS64 mem [m: o64 np 0f c7 /3] LONG,FUTURE,NOAPX
|
||||
|
||||
; These instructions are not SSE-specific; they are
|
||||
;# Generic memory operations
|
||||
@ -2028,7 +2028,7 @@ POPCNT reg32,rm32 [rm: o32 f3i 0f b8 /r] NEHALEM,SD
|
||||
POPCNT reg64,rm64 [rm: o64 f3i 0f b8 /r] NEHALEM,SQ,LONG
|
||||
|
||||
;# Intel SMX
|
||||
GETSEC void [ 0f 37] KATMAI
|
||||
GETSEC void [ 0f 37] KATMAI,NOAPX
|
||||
|
||||
;# Geode (Cyrix) 3DNow! additions
|
||||
PFRCPV mmxreg,mmxrm [rm: o64nw 0f 0f /r 86] PENT,3DNOW,SQ,CYRIX
|
||||
@ -6436,6 +6436,9 @@ PUSHP reg64 [r: o64nw rex.w rex2 50+r ] APX
|
||||
POPP reg64 [r: o64nw rex.w rex2 58+r ] APX
|
||||
|
||||
ADD reg8?,rm8,reg8 [vmr: evex.ndx.l0.np.m4.wig 00 /r ] APX,NF
|
||||
ADD reg16?,rm16,reg16 [vmr: evex.ndx.l0.66.m4.w0 01 /r ] APX,NF
|
||||
ADD reg32?,rm32,reg32 [vmr: evex.ndx.l0.np.m4.w0 01 /r ] APX,NF
|
||||
ADD reg64?,rm64,reg64 [vmr: evex.ndx.l0.np.m4.w1 01 /r ] APX,NF
|
||||
|
||||
JMP imm|abs [i: a64 np rex2 a1 iq ] APX
|
||||
JMP imm64|abs [i: a64 np rex2 a1 iq ] APX,SQ
|
||||
|
66
x86/insns.pl
66
x86/insns.pl
@ -591,10 +591,9 @@ sub format_insn($$$$$) {
|
||||
$flagsindex = insns_flag_index(keys %flags);
|
||||
die "$fname:$line: error in flags $flags\n" unless (defined($flagsindex));
|
||||
|
||||
# Flags that imply long mode only
|
||||
if ($flags{'APX'}) {
|
||||
$flags->{'LONG'}++;
|
||||
}
|
||||
# Flags implying each other
|
||||
$flags->{'LONG'}++ if ($flags{'APX'});
|
||||
$flags->{'NOAPX'}++ if ($flags{'NOLONG'});
|
||||
|
||||
# format the operands
|
||||
$operands =~ s/[\*\?]//g;
|
||||
@ -604,6 +603,7 @@ sub format_insn($$$$$) {
|
||||
@decos = ();
|
||||
if ($operands ne 'void') {
|
||||
foreach $op (split(/,/, $operands)) {
|
||||
my $iszero = 0;
|
||||
my $opsz = 0;
|
||||
@opx = ();
|
||||
@opevex = ();
|
||||
@ -613,15 +613,21 @@ sub format_insn($$$$$) {
|
||||
push(@opevex, $1);
|
||||
}
|
||||
|
||||
if ($opp =~ s/(?<!\d)(8|16|32|64|80|128|256|512)$//) {
|
||||
push(@oppx, "bits$1");
|
||||
if ($opp =~ s/([^0-9]0?)(8|16|32|64|80|128|256|512|1024|1k)$/$1/) {
|
||||
push(@oppx, "bits$2");
|
||||
$opsz = $1 + 0;
|
||||
}
|
||||
if ($opp =~ s/0$//) {
|
||||
push(@oppx, 'rm_zero');
|
||||
$iszero = 1;
|
||||
if ($opp !~ /reg/) {
|
||||
$opp .= 'reg';
|
||||
}
|
||||
}
|
||||
$opp =~ s/^mem$/memory/;
|
||||
$opp =~ s/^memory_offs$/mem_offs/;
|
||||
if ($opp =~ /^(spec|imm)4$/) {
|
||||
if ($opp =~ s/^(spec|imm)4$/$1/) {
|
||||
push(@oppx, 'fourbits');
|
||||
$opp = $1;
|
||||
}
|
||||
$opp =~ s/^spec$/immediate/; # Immediate or special immediate
|
||||
$opp =~ s/^imm$/imm_normal/; # Normal immediates only
|
||||
@ -629,20 +635,15 @@ sub format_insn($$$$$) {
|
||||
push(@oppx, 'imm_normal');
|
||||
}
|
||||
$opp =~ s/^([a-z]+)rm$/rm_$1/;
|
||||
$opp =~ s/^rm$/rm_gpr/;
|
||||
$opp =~ s/^reg$/reg_gpr/;
|
||||
# only for evex and rex2 insns, high-16 GPR or creg regs are allowed
|
||||
unless ($flags{'EVEX'} || $flags{'REX2'}) {
|
||||
if ($opp =~ /^(rm_gpr|reg_gpr|reg_[cd]reg)$/) {
|
||||
push(@oppx, 'rn_l16'); # Register number must be < 16
|
||||
}
|
||||
}
|
||||
# only for evex, high vector registers are allowed
|
||||
unless ($flags{'EVEX'}) {
|
||||
if ($opp =~ /^[xyz]mm(reg|rm)$/) {
|
||||
push(@oppx, 'rn_l16'); # Register number must be < 16
|
||||
}
|
||||
}
|
||||
$opp =~ s/^(rm|reg)$/$1_gpr/;
|
||||
$opp =~ s/^rm_k$/rm_opmask/;
|
||||
$opp =~ s/^kreg$/opmaskreg/;
|
||||
my $isreg = ($opp =~ /(\brm_|\breg_|reg\b)/);
|
||||
my $isvec = ($opp =~ /\b[xyzt]mm/);
|
||||
if ($isreg && !(($flags{'EVEX'} && $isvec) || !$flags{'NOAPX'})) {
|
||||
# Register numbers >= 16 disallowed
|
||||
push(@oppx, 'rn_l16');
|
||||
}
|
||||
push(@opx, $opp, @oppx) if $opp;
|
||||
}
|
||||
$op = join('|', @opx);
|
||||
@ -693,7 +694,7 @@ sub format_insn($$$$$) {
|
||||
foreach my $sf (keys(%sflags)) {
|
||||
next if (!$flags{$sf});
|
||||
for (my $i = $s; $i <= $e; $i++) {
|
||||
if ($opsize[$i] && $ops[$i] !~ /\breg_(gpr|[cdts]reg)\b/) {
|
||||
if ($opsize[$i] && $ops[$i] !~ /(\breg_|reg\b)/) {
|
||||
die "$fname:$line: inconsistent $sf flag for argument $i ($ops[$i])\n"
|
||||
if ($opsize[$i] != $sflags{$sf});
|
||||
}
|
||||
@ -1210,6 +1211,7 @@ sub byte_code_compile($$$) {
|
||||
($c << 6)+$m, ($w << 7)+($l << 2)+$p);
|
||||
|
||||
$flags->{'VEX'}++;
|
||||
$flags->{'NOAPX'}++; # VEX doesn't support registers 16+
|
||||
$prefix_ok = 0;
|
||||
} elsif ($op =~ /^(evex)(|\..*)$/) {
|
||||
my $c = $vexmap{$1};
|
||||
@ -1319,10 +1321,9 @@ sub byte_code_compile($$$) {
|
||||
|
||||
$flags->{'EVEX'}++;
|
||||
$prefix_ok = 0;
|
||||
} elsif ($op =~ /^(rex2(\??))(\..*)?$/) {
|
||||
} elsif ($op =~ /^(rex2)(\..*)?$/) {
|
||||
my $name = $1;
|
||||
my $optional = $2 eq '?';
|
||||
my @subops = split(/\./, $3);
|
||||
my @subops = split(/\./, $2);
|
||||
my $c = 0350;
|
||||
my $m = undef;
|
||||
foreach $oq (@subops) {
|
||||
@ -1339,12 +1340,10 @@ sub byte_code_compile($$$) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!$optional) {
|
||||
push(@codes, $c);
|
||||
$flags->{'APX'}++;
|
||||
$flags->{'LONG'}++;
|
||||
}
|
||||
push(@codes, $c);
|
||||
$flags->{'APX'}++;
|
||||
$flags->{'REX2'}++;
|
||||
$flags->{'LONG'}++;
|
||||
$prefix_ok = 0;
|
||||
} elsif (defined $imm_codes{$op}) {
|
||||
if ($op eq 'seg') {
|
||||
@ -1399,5 +1398,10 @@ sub byte_code_compile($$$) {
|
||||
}
|
||||
}
|
||||
|
||||
# Legacy maps 2+ do not support REX2 encodings
|
||||
if ($opmap > 1 && !$flags{'EVEX'}) {
|
||||
$flags->{'NOAPX'}++;
|
||||
}
|
||||
|
||||
return @codes;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user