summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJin Kyu Song <jin.kyu.song@intel.com>2013-10-15 19:10:13 -0700
committerJin Kyu Song <jin.kyu.song@intel.com>2013-11-20 11:29:41 -0800
commit164d60740f0aa2759ae78874bd5c8692d8d59e60 (patch)
tree237161a1e4ac230347feefa20a9ed1fc0b80a27a
parent0bc288f8b9ec5fb30fb816008e81282081d85e82 (diff)
downloadnasm-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.c23
-rw-r--r--insns.dat21
-rw-r--r--insns.h1
-rwxr-xr-xinsns.pl3
-rw-r--r--opflags.h5
-rw-r--r--parser.c7
-rw-r--r--regs.dat3
7 files changed, 61 insertions, 2 deletions
diff --git a/assemble.c b/assemble.c
index 57ef0cd..d913495 100644
--- a/assemble.c
+++ b/assemble.c
@@ -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;
}
diff --git a/insns.dat b/insns.dat
index 52aeff5..b1a1aac 100644
--- a/insns.dat
+++ b/insns.dat
@@ -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
diff --git a/insns.h b/insns.h
index 61b04cc..6e94f3d 100644
--- a/insns.h
+++ b/insns.h
@@ -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 */
diff --git a/insns.pl b/insns.pl
index 8d1f0ee..8bd76ab 100755
--- a/insns.pl
+++ b/insns.pl
@@ -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])$:) {
diff --git a/opflags.h b/opflags.h
index 014abe8..16c65cb 100644
--- a/opflags.h
+++ b/opflags.h
@@ -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 */
diff --git a/parser.c b/parser.c
index bb56924..0068ca3 100644
--- a/parser.c
+++ b/parser.c
@@ -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 */
diff --git a/regs.dat b/regs.dat
index 7861119..46d5409 100644
--- a/regs.dat
+++ b/regs.dat
@@ -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