diff options
author | Jin Kyu Song <jin.kyu.song@intel.com> | 2013-10-15 19:10:13 -0700 |
---|---|---|
committer | Jin Kyu Song <jin.kyu.song@intel.com> | 2013-11-20 11:29:41 -0800 |
commit | 164d60740f0aa2759ae78874bd5c8692d8d59e60 (patch) | |
tree | 237161a1e4ac230347feefa20a9ed1fc0b80a27a | |
parent | 0bc288f8b9ec5fb30fb816008e81282081d85e82 (diff) | |
download | nasm-164d60740f0aa2759ae78874bd5c8692d8d59e60.tar.gz nasm-164d60740f0aa2759ae78874bd5c8692d8d59e60.tar.bz2 nasm-164d60740f0aa2759ae78874bd5c8692d8d59e60.zip |
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>
-rw-r--r-- | assemble.c | 23 | ||||
-rw-r--r-- | insns.dat | 21 | ||||
-rw-r--r-- | insns.h | 1 | ||||
-rwxr-xr-x | insns.pl | 3 | ||||
-rw-r--r-- | opflags.h | 5 | ||||
-rw-r--r-- | parser.c | 7 | ||||
-rw-r--r-- | regs.dat | 3 |
7 files changed, 61 insertions, 2 deletions
@@ -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; } @@ -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 @@ -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 */ @@ -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])$:) { @@ -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 */ @@ -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 */ @@ -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 |