MPX: Add MPX instructions

Added MPX instructions and corresponding parser and encoder.

ICC style mib - base + disp and index are separate - is supported.
E.g. bndstx [ebx+3], bnd2, edx -> ebx+3 : base+disp, edx : index

As a supplement to NASM style mib - split EA - parser,
omitted base+disp is now treated as 0 displacement.
E.g. bndstx [,edx], bnd2 -> bndstx [0,edx], bnd2

Signed-off-by: Jin Kyu Song <jin.kyu.song@intel.com>
This commit is contained in:
Jin Kyu Song 2013-10-15 19:10:13 -07:00
parent 0bc288f8b9
commit 164d60740f
7 changed files with 61 additions and 2 deletions

View file

@ -42,6 +42,7 @@
* \7 - add 4 to both the primary and the secondary operand number
* \10..\13 - a literal byte follows in the code stream, to be added
* to the register value of operand 0..3
* \14..\17 - the position of index register operand in MIB (BND insns)
* \20..\23 - a byte immediate operand, from operand 0..3
* \24..\27 - a zero-extended byte immediate operand, from operand 0..3
* \30..\33 - a word immediate operand, from operand 0..3
@ -852,6 +853,7 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
enum ea_type eat;
uint8_t hleok = 0;
bool lockcheck = true;
enum reg_enum mib_index = R_none; /* For a separate index MIB reg form */
ins->rex = 0; /* Ensure REX is reset */
eat = EA_SCALAR; /* Expect a scalar EA */
@ -885,6 +887,11 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
codes++, length++;
break;
case4(014):
/* this is an index reg of MIB operand */
mib_index = opx->basereg;
break;
case4(020):
case4(024):
length++;
@ -1184,6 +1191,17 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits,
}
}
/*
* if a separate form of MIB (ICC style) is used,
* the index reg info is merged into mem operand
*/
if (mib_index != R_none) {
opy->indexreg = mib_index;
opy->scale = 1;
opy->hintbase = mib_index;
opy->hinttype = EAH_NOTBASE;
}
if (process_ea(opy, &ea_data, bits,
rfield, rflags, ins) != eat) {
errfunc(ERR_NONFATAL, "invalid effective address");
@ -1336,6 +1354,9 @@ static void gencode(int32_t segment, int64_t offset, int bits,
offset += 1;
break;
case4(014):
break;
case4(020):
if (opx->offset < -256 || opx->offset > 255) {
errfunc(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
@ -2545,7 +2566,7 @@ static enum ea_type process_ea(operand *input, ea *output, int bits,
}
if (bt == it) /* convert EAX+2*EAX to 3*EAX */
bt = -1, bx = 0, s++;
if (bt == -1 && s == 1 && !(hb == it && ht == EAH_NOTBASE)) {
if (bt == -1 && s == 1 && !(hb == i && ht == EAH_NOTBASE)) {
/* make single reg base, unless hint */
bt = it, bx = ix, it = -1, ix = 0;
}

View file

@ -4095,6 +4095,27 @@ VSCATTERPF1QPD zmem64|mask [m:t1s: vsibz evex.512.66.0f38.w1 c7 /6 ] AVX51
VSCATTERPF1QPS zmem32|mask [m:t1s: vsibz evex.512.66.0f38.w0 c7 /6 ] AVX512PF,FUTURE
PREFETCHWT1 mem8 [m: 0f 0d /2 ] FUTURE
; MPX instructions
BNDMK bndreg,mem32 [rm: o32 f3 0f 1b /r ] MPX,SD,FUTURE
BNDMK bndreg,mem64 [rm: o64nw f3 0f 1b /r ] MPX,SQ,FUTURE
BNDCL bndreg,rm32 [rm: o32 f3 0f 1a /r ] MPX,SD,FUTURE
BNDCL bndreg,rm64 [rm: o64nw f3 0f 1a /r ] MPX,SQ,FUTURE
BNDCU bndreg,rm32 [rm: o32 f2 0f 1a /r ] MPX,SD,FUTURE
BNDCU bndreg,rm64 [rm: o64nw f2 0f 1a /r ] MPX,SQ,FUTURE
BNDCN bndreg,rm32 [rm: o32 f2 0f 1b /r ] MPX,SD,FUTURE
BNDCN bndreg,rm64 [rm: o64nw f2 0f 1b /r ] MPX,SQ,FUTURE
BNDMOV bndreg,bndrm64 [rm: 66 0f 1a /r ] MPX,SQ,FUTURE
BNDMOV bndreg,bndrm128 [rm: 66 0f 1a /r ] MPX,SO,FUTURE
BNDMOV bndrm64,bndreg [mr: 66 0f 1b /r ] MPX,SQ,FUTURE
BNDMOV bndrm128,bndreg [mr: 66 0f 1b /r ] MPX,SO,FUTURE
BNDLDX bndreg,mem128 [rm: 0f 1a /r ] MPX,MIB,FUTURE
BNDLDX bndreg,mem128,reg64 [rmx: 0f 1a /r ] MPX,MIB,FUTURE
BNDSTX mem64,bndreg [mr: 0f 1b /r ] MPX,MIB,SQ,FUTURE
BNDSTX mem64,reg32,bndreg [mxr: 0f 1b /r ] MPX,MIB,FUTURE
BNDSTX mem64,bndreg,reg32 [mrx: 0f 1b /r ] MPX,MIB,FUTURE
BNDSTX mem128,bndreg [mr: 0f 1b /r ] MPX,MIB,SO,FUTURE
BNDSTX mem128,reg64,bndreg [mxr: 0f 1b /r ] MPX,MIB,FUTURE
BNDSTX mem128,bndreg,reg64 [mrx: 0f 1b /r ] MPX,MIB,FUTURE
;# Systematic names for the hinting nop instructions
; These should be last in the file

View file

@ -132,6 +132,7 @@ extern const uint8_t nasm_bytecodes[];
#define IF_AVX512CD (0x1600000000UL|IF_AVX512) /* AVX-512 Conflict Detection insns */
#define IF_AVX512ER (0x1700000000UL|IF_AVX512) /* AVX-512 Exponential and Reciprocal */
#define IF_AVX512PF (0x1800000000UL|IF_AVX512) /* AVX-512 Prefetch instructions */
#define IF_MPX 0x1900000000UL /* MPX instructions */
#define IF_INSMASK 0xFF00000000UL /* the mask for instruction set types */
#define IF_PMASK 0xFF000000UL /* the mask for processor types */
#define IF_PLEVEL 0x0F000000UL /* the mask for processor instr. level */

View file

@ -704,6 +704,7 @@ sub tupletype($) {
# i = immediate
# s = register field of is4/imz2 field
# - = implicit (unencoded) operand
# x = indeX register of mib. 014..017 bytecodes are used.
#
# For an operand that should be filled into more than one field,
# enter it as e.g. "r+v".
@ -843,6 +844,8 @@ sub byte_code_compile($$) {
$opex = (($oppos{'m'} & 4) ? 06 : 0) |
(($oppos{'r'} & 4) ? 05 : 0);
push(@codes, $opex) if ($opex);
# if mib is composed with two separate operands - ICC style
push(@codes, 014 + ($oppos{'x'} & 3)) if (defined($oppos{'x'}));
push(@codes, 0100 + (($oppos{'m'} & 3) << 3) + ($oppos{'r'} & 3));
$prefix_ok = 0;
} elsif ($op =~ m:^/([0-7])$:) {

View file

@ -163,6 +163,7 @@
#define REG_CLASS_RM_YMM GEN_REG_CLASS(6)
#define REG_CLASS_RM_ZMM GEN_REG_CLASS(7)
#define REG_CLASS_OPMASK GEN_REG_CLASS(8)
#define REG_CLASS_BND GEN_REG_CLASS(9)
#define is_class(class, op) (!((opflags_t)(class) & ~(opflags_t)(op)))
#define is_reg_class(class, reg) is_class((class), nasm_reg_flags[(reg)])
@ -196,6 +197,8 @@
#define OPMASK0 (GEN_SUBCLASS(1) | REG_CLASS_OPMASK | REGMEM | REGISTER) /* Opmask register zero (k0) */
#define RM_K RM_OPMASK
#define KREG OPMASKREG
#define RM_BND ( REG_CLASS_BND | REGMEM) /* Bounds operand */
#define BNDREG ( REG_CLASS_BND | REGMEM | REGISTER) /* Bounds register */
#define REG_CDT ( REG_CLASS_CDT | BITS32 | REGISTER) /* CRn, DRn and TRn */
#define REG_CREG (GEN_SUBCLASS(1) | REG_CLASS_CDT | BITS32 | REGISTER) /* CRn */
#define REG_DREG (GEN_SUBCLASS(2) | REG_CLASS_CDT | BITS32 | REGISTER) /* DRn */
@ -243,7 +246,7 @@
#define ZMEM (GEN_SUBCLASS(5) | MEMORY) /* 512-bit vector SIB */
/* memory which matches any type of r/m operand */
#define MEMORY_ANY (MEMORY | RM_GPR | RM_MMX | RM_XMM | RM_YMM | RM_ZMM | RM_OPMASK)
#define MEMORY_ANY (MEMORY | RM_GPR | RM_MMX | RM_XMM | RM_YMM | RM_ZMM | RM_OPMASK | RM_BND)
/* special immediate values */
#define UNITY (GEN_SUBCLASS(0) | IMMEDIATE) /* operand equals 1 */

View file

@ -821,6 +821,13 @@ is_expression:
process_size_override(result, op);
i = stdscan(NULL, &tokval);
}
/* when a comma follows an opening bracket - [ , eax*4] */
if (i == ',') {
/* treat as if there is a zero displacement virtually */
tokval.t_type = TOKEN_NUM;
tokval.t_integer = 0;
stdscan_set(stdscan_get() - 1); /* rewind the comma */
}
} else { /* immediate operand, or register */
mref = false;
bracket = false; /* placate optimisers */

View file

@ -130,3 +130,6 @@ zmm1-31 ZMMREG zmmreg 1
# Opmask registers
k0 OPMASK0 opmaskreg 0
k1-7 OPMASKREG opmaskreg 1 TFLAG_BRC_OPT
# Bounds registers
bnd0-3 BNDREG bndreg 0