aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMITSUNARI Shigeo <[email protected]>2017-08-22 15:53:34 +0900
committerMITSUNARI Shigeo <[email protected]>2017-08-22 15:53:46 +0900
commite4fc9d8a9291f69ed4b49ab51297c5b06d0deecb (patch)
treee1141425dbd12b866eb2d889e2e6e83962e7c1e8
parentd0b2fb623e2f9744a6f19fec7a2f51a8e908ea65 (diff)
downloadxbyak-e4fc9d8a9291f69ed4b49ab51297c5b06d0deecb.tar.gz
xbyak-e4fc9d8a9291f69ed4b49ab51297c5b06d0deecb.zip
fix mpx encodingv5.53
-rw-r--r--gen/gen_code.cpp4
-rw-r--r--readme.md3
-rw-r--r--readme.txt3
-rw-r--r--test/make_nm.cpp16
-rw-r--r--test/nm_frame.cpp1
-rw-r--r--test/test_address.bat2
-rw-r--r--xbyak/xbyak.h123
-rw-r--r--xbyak/xbyak_mnemonic.h6
8 files changed, 108 insertions, 50 deletions
diff --git a/gen/gen_code.cpp b/gen/gen_code.cpp
index 734fd83..413e632 100644
--- a/gen/gen_code.cpp
+++ b/gen/gen_code.cpp
@@ -942,11 +942,11 @@ void put()
puts("void bndcl(const BoundsReg& bnd, const Operand& op) { db(0xF3); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1A, NONE, !op.isMEM()); }");
puts("void bndcu(const BoundsReg& bnd, const Operand& op) { db(0xF2); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1A, NONE, !op.isMEM()); }");
puts("void bndcn(const BoundsReg& bnd, const Operand& op) { db(0xF2); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1B, NONE, !op.isMEM()); }");
- puts("void bndldx(const BoundsReg& bnd, const Address& addr) { opModM(addr, bnd, 0x0F, 0x1A); }");
+ puts("void bndldx(const BoundsReg& bnd, const Address& addr) { opMIB(addr, bnd, 0x0F, 0x1A); }");
puts("void bndmk(const BoundsReg& bnd, const Address& addr) { db(0xF3); opModM(addr, bnd, 0x0F, 0x1B); }");
puts("void bndmov(const BoundsReg& bnd, const Operand& op) { db(0x66); opModRM(bnd, op, op.isBNDREG(), op.isMEM(), 0x0F, 0x1A); }");
puts("void bndmov(const Address& addr, const BoundsReg& bnd) { db(0x66); opModM(addr, bnd, 0x0F, 0x1B); }");
- puts("void bndstx(const Address& addr, const BoundsReg& bnd) { opModM(addr, bnd, 0x0F, 0x1B); }");
+ puts("void bndstx(const Address& addr, const BoundsReg& bnd) { opMIB(addr, bnd, 0x0F, 0x1B); }");
}
// misc
{
diff --git a/readme.md b/readme.md
index 4f5adf0..b00ad5b 100644
--- a/readme.md
+++ b/readme.md
@@ -1,5 +1,5 @@
-Xbyak 5.52 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++
+Xbyak 5.53 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++
=============
Abstract
@@ -333,6 +333,7 @@ The header files under xbyak/ are independent of cybozulib.
History
-------------
+* 2017/Aug/22 ver 5.53 fix mpx encoding, add bnd() prefix
* 2017/Aug/18 ver 5.52 fix align (thanks to MerryMage)
* 2017/Aug/17 ver 5.51 add multi-byte nop and align() uses it(thanks to inolen)
* 2017/Aug/08 ver 5.50 add mpx(thanks to magurosan)
diff --git a/readme.txt b/readme.txt
index 2bc20f8..21de3b1 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,5 +1,5 @@
- C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak 5.52
+ C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak 5.53
-----------------------------------------------------------------------------
◎概要
@@ -343,6 +343,7 @@ cybozulibは単体テストでのみ利用されていて、xbyak/ディレク�
-----------------------------------------------------------------------------
◎履歴
+2017/08/22 ver 5.53 mpxエンコーディングバグ修正, bnd()プレフィクス追加
2017/08/18 ver 5.52 align修正(thanks to MerryMage)
2017/08/17 ver 5.51 multi-byte nop追加 align()はそれを使用する(thanks to inolen)
2017/08/08 ver 5.50 mpx追加(thanks to magurosan)
diff --git a/test/make_nm.cpp b/test/make_nm.cpp
index 6eff1e5..72c8247 100644
--- a/test/make_nm.cpp
+++ b/test/make_nm.cpp
@@ -1363,6 +1363,22 @@ class Test {
put("bndmk", BNDREG, MEM);
put("bndmov", BNDREG, BNDREG|MEM);
put("bndstx", MEM, BNDREG);
+ put("bndstx", "ptr [eax]", "[eax]", BNDREG);
+ put("bndstx", "ptr [eax+5]", "[eax+5]", BNDREG);
+ put("bndstx", "ptr [eax+500]", "[eax+500]", BNDREG);
+ put("bndstx", "ptr [eax+ecx]", "[eax+ecx]", BNDREG);
+ put("bndstx", "ptr [ecx+eax]", "[ecx+eax]", BNDREG);
+ put("bndstx", "ptr [eax+esp]", "[eax+esp]", BNDREG);
+ put("bndstx", "ptr [esp+eax]", "[esp+eax]", BNDREG);
+ put("bndstx", "ptr [eax+ecx*2]", "[eax+ecx*2]", BNDREG);
+ put("bndstx", "ptr [ecx+ecx]", "[ecx+ecx]", BNDREG);
+ put("bndstx", "ptr [ecx*2]", "[ecx*2]", BNDREG);
+ put("bndstx", "ptr [eax+ecx*2+500]", "[eax+ecx*2+500]", BNDREG);
+#ifdef XBYAK64
+ put("bndstx", "ptr [rax+rcx*2]", "[rax+rcx*2]", BNDREG);
+ put("bndstx", "ptr [r9*2]", "[r9*2]", BNDREG);
+ put("bndstx", "ptr [r9*2+r15]", "[r9*2+r15]", BNDREG);
+#endif
}
void putFpuMem16_32() const
{
diff --git a/test/nm_frame.cpp b/test/nm_frame.cpp
index 95240c7..697c2c4 100644
--- a/test/nm_frame.cpp
+++ b/test/nm_frame.cpp
@@ -6,6 +6,7 @@ using namespace Xbyak;
#ifdef _MSC_VER
#pragma warning(disable : 4245)
+ #pragma warning(disable : 4312)
#endif
class Sample : public CodeGenerator {
void operator=(const Sample&);
diff --git a/test/test_address.bat b/test/test_address.bat
index 030c04d..f96542f 100644
--- a/test/test_address.bat
+++ b/test/test_address.bat
@@ -1,5 +1,5 @@
@echo off
-set FILTER=cat
+set FILTER=grep -v warning
if /i "%1"=="64" (
set OPT2=-DXBYAK64
set OPT3=win64
diff --git a/xbyak/xbyak.h b/xbyak/xbyak.h
index 3c91ec9..047e6b6 100644
--- a/xbyak/xbyak.h
+++ b/xbyak/xbyak.h
@@ -105,7 +105,7 @@ namespace Xbyak {
enum {
DEFAULT_MAX_CODE_SIZE = 4096,
- VERSION = 0x5520 /* 0xABCD = A.BC(D) */
+ VERSION = 0x5530 /* 0xABCD = A.BC(D) */
};
#ifndef MIE_INTEGER_TYPE_DEFINED
@@ -177,6 +177,7 @@ enum {
ERR_INVALID_OPMASK_WITH_MEMORY,
ERR_INVALID_ZERO,
ERR_INVALID_RIP_IN_AUTO_GROW,
+ ERR_INVALID_MIB_ADDRESS,
ERR_INTERNAL
};
@@ -237,6 +238,7 @@ public:
"invalid opmask with memory",
"invalid zero",
"invalid rip in AutoGrow",
+ "invalid mib address",
"internal error",
};
assert((size_t)err_ < sizeof(errTbl) / sizeof(*errTbl));
@@ -345,6 +347,9 @@ public:
};
#endif
+class Address;
+class Reg;
+
class Operand {
static const uint8 EXT8BIT = 0x20;
unsigned int idx_:6; // 0..31 + EXT8BIT = 1 if spl/bpl/sil/dil
@@ -497,6 +502,8 @@ public:
bool isEqualIfNotInherited(const Operand& rhs) const { return idx_ == rhs.idx_ && kind_ == rhs.kind_ && bit_ == rhs.bit_ && zero_ == rhs.zero_ && mask_ == rhs.mask_ && rounding_ == rhs.rounding_; }
bool operator==(const Operand& rhs) const;
bool operator!=(const Operand& rhs) const { return !operator==(rhs); }
+ const Address& getAddress() const;
+ const Reg& getReg() const;
};
class Label;
@@ -530,6 +537,12 @@ public:
#endif
};
+inline const Reg& Operand::getReg() const
+{
+ assert(!isMEM());
+ return static_cast<const Reg&>(*this);
+}
+
struct Reg8 : public Reg {
explicit Reg8(int idx = 0, bool ext8bit = false) : Reg(idx, Operand::REG, 8, ext8bit) { }
};
@@ -689,13 +702,15 @@ public:
}
}
bool isVsib(int bit = 128 | 256 | 512) const { return index_.isBit(bit); }
- void optimize()
+ RegExp optimize() const
{
+ RegExp exp = *this;
// [reg * 2] => [reg + reg]
- if (index_.isBit(i32e) && !base_.getBit() && index_.getBit() && scale_ == 2) {
- base_ = index_;
- scale_ = 1;
+ if (index_.isBit(i32e) && !base_.getBit() && scale_ == 2) {
+ exp.base_ = index_;
+ exp.scale_ = 1;
}
+ return exp;
}
bool operator==(const RegExp& rhs) const
{
@@ -715,6 +730,11 @@ public:
}
friend RegExp operator+(const RegExp& a, const RegExp& b);
friend RegExp operator-(const RegExp& e, size_t disp);
+ uint8 getRex() const
+ {
+ uint8 rex = index_.getRexX() | base_.getRexB();
+ return rex ? uint8(rex | 0x40) : 0;
+ }
private:
/*
[base_ + index_ * scale_ + disp_]
@@ -975,7 +995,6 @@ public:
: Operand(0, MEM, sizeBit), e_(e), label_(0), mode_(M_ModRM), permitVsib_(false), broadcast_(broadcast)
{
e_.verify();
- e_.optimize();
}
#ifdef XBYAK64
explicit Address(size_t disp)
@@ -984,7 +1003,10 @@ public:
: Operand(0, MEM, sizeBit), e_(addr.disp_), label_(addr.label_), mode_(addr.isAddr_ ? M_ripAddr : M_rip), permitVsib_(false), broadcast_(broadcast) { }
#endif
void permitVsib() const { permitVsib_ = true; }
- const RegExp& getRegExp() const { return e_; }
+ RegExp getRegExp(bool optimize = true) const
+ {
+ return optimize ? e_.optimize() : e_;
+ }
Mode getMode() const { return mode_; }
bool is32bit() const { verify(); return e_.getBase().getBit() == 32 || e_.getIndex().getBit() == 32; }
bool isOnlyDisp() const { verify(); return !e_.getBase().getBit() && !e_.getIndex().getBit(); } // for mov eax
@@ -993,9 +1015,7 @@ public:
{
verify();
if (mode_ != M_ModRM) return 0;
- uint8 rex = e_.getIndex().getRexX() | e_.getBase().getRexB();
- if (rex) rex |= 0x40;
- return rex;
+ return getRegExp().getRex();
}
bool is64bitDisp() const { verify(); return mode_ == M_64bitDisp; } // for moffset
bool isBroadcast() const { return broadcast_; }
@@ -1014,9 +1034,15 @@ private:
void verify() const { if (e_.isVsib() && !permitVsib_) throw Error(ERR_BAD_VSIB_ADDRESSING); }
};
+inline const Address& Operand::getAddress() const
+{
+ assert(isMEM());
+ return static_cast<const Address&>(*this);
+}
+
inline bool Operand::operator==(const Operand& rhs) const
{
- if (isMEM() && rhs.isMEM()) return static_cast<const Address&>(*this) == static_cast<const Address&>(rhs);
+ if (isMEM() && rhs.isMEM()) return this->getAddress() == rhs.getAddress();
return isEqualIfNotInherited(rhs);
}
@@ -1363,12 +1389,12 @@ private:
if (p1->isMEM()) std::swap(p1, p2);
if (p1->isMEM()) throw Error(ERR_BAD_COMBINATION);
if (p2->isMEM()) {
- const Address& addr = static_cast<const Address&>(*p2);
+ const Address& addr = p2->getAddress();
if (BIT == 64 && addr.is32bit()) db(0x67);
- rex = addr.getRex() | static_cast<const Reg&>(*p1).getRex();
+ rex = addr.getRex() | p1->getReg().getRex();
} else {
// ModRM(reg, base);
- rex = static_cast<const Reg&>(op2).getRex(static_cast<const Reg&>(op1));
+ rex = op2.getReg().getRex(op1.getReg());
}
// except movsx(16bit, 32/64bit)
if ((op1.isBit(16) && !op2.isBit(i32e)) || (op2.isBit(16) && !op1.isBit(i32e))) db(0x66);
@@ -1581,6 +1607,17 @@ private:
db(code0 | (reg.isBit(8) ? 0 : 1)); if (code1 != NONE) db(code1); if (code2 != NONE) db(code2);
opAddr(addr, reg.getIdx(), immSize);
}
+ void opMIB(const Address& addr, const Reg& reg, int code0, int code1)
+ {
+ if (addr.is64bitDisp()) throw Error(ERR_CANT_USE_64BIT_DISP);
+ if (addr.getMode() != Address::M_ModRM) throw Error(ERR_INVALID_MIB_ADDRESS);
+ if (BIT == 64 && addr.is32bit()) db(0x67);
+ const RegExp& regExp = addr.getRegExp(false);
+ uint8 rex = regExp.getRex();
+ if (rex) db(rex);
+ db(code0); db(code1);
+ setSIB(regExp, reg.getIdx());
+ }
void makeJmp(uint32 disp, LabelType type, uint8 shortCode, uint8 longCode, uint8 longPref)
{
const int shortJmpSize = 2;
@@ -1656,9 +1693,9 @@ private:
if (isValid && !isValid(reg, op)) throw Error(ERR_BAD_COMBINATION);
if (pref != NONE) db(pref);
if (op.isMEM()) {
- opModM(static_cast<const Address&>(op), static_cast<const Reg&>(reg), 0x0F, preCode, code, (imm8 != NONE) ? 1 : 0);
+ opModM(op.getAddress(), reg.getReg(), 0x0F, preCode, code, (imm8 != NONE) ? 1 : 0);
} else {
- opModR(static_cast<const Reg&>(reg), static_cast<const Reg&>(op), 0x0F, preCode, code);
+ opModR(reg.getReg(), op.getReg(), 0x0F, preCode, code);
}
if (imm8 != NONE) db(imm8);
}
@@ -1676,9 +1713,9 @@ private:
{
if (pref != NONE) db(pref);
if (op1.isXMM() && op2.isMEM()) {
- opModM(static_cast<const Address&>(op2), static_cast<const Reg&>(op1), 0x0F, code);
+ opModM(op2.getAddress(), op1.getReg(), 0x0F, code);
} else if (op1.isMEM() && op2.isXMM()) {
- opModM(static_cast<const Address&>(op1), static_cast<const Reg&>(op2), 0x0F, code | 1);
+ opModM(op1.getAddress(), op2.getReg(), 0x0F, code | 1);
} else {
throw Error(ERR_BAD_COMBINATION);
}
@@ -1687,7 +1724,7 @@ private:
{
if (hasMMX2 && op.isREG(i32e)) { /* pextrw is special */
if (mmx.isXMM()) db(0x66);
- opModR(static_cast<const Reg&>(op), mmx, 0x0F, 0xC5); db(imm);
+ opModR(op.getReg(), mmx, 0x0F, 0xC5); db(imm);
} else {
opGen(mmx, op, code, 0x66, isXMM_REG32orMEM, imm, 0x3A);
}
@@ -1697,9 +1734,9 @@ private:
int opBit = op.getBit();
if (disableRex && opBit == 64) opBit = 32;
if (op.isREG(bit)) {
- opModR(Reg(ext, Operand::REG, opBit), static_cast<const Reg&>(op).changeBit(opBit), code0, code1, code2);
+ opModR(Reg(ext, Operand::REG, opBit), op.getReg().changeBit(opBit), code0, code1, code2);
} else if (op.isMEM()) {
- opModM(static_cast<const Address&>(op), Reg(ext, Operand::REG, opBit), code0, code1, code2, immSize);
+ opModM(op.getAddress(), Reg(ext, Operand::REG, opBit), code0, code1, code2, immSize);
} else {
throw Error(ERR_BAD_COMBINATION);
}
@@ -1718,9 +1755,9 @@ private:
void opModRM(const Operand& op1, const Operand& op2, bool condR, bool condM, int code0, int code1 = NONE, int code2 = NONE, int immSize = 0)
{
if (condR) {
- opModR(static_cast<const Reg&>(op1), static_cast<const Reg&>(op2), code0, code1, code2);
+ opModR(op1.getReg(), op2.getReg(), code0, code1, code2);
} else if (condM) {
- opModM(static_cast<const Address&>(op2), static_cast<const Reg&>(op1), code0, code1, code2, immSize);
+ opModM(op2.getAddress(), op1.getReg(), code0, code1, code2, immSize);
} else {
throw Error(ERR_BAD_COMBINATION);
}
@@ -1735,7 +1772,7 @@ private:
void opRM_RM(const Operand& op1, const Operand& op2, int code)
{
if (op1.isREG() && op2.isMEM()) {
- opModM(static_cast<const Address&>(op2), static_cast<const Reg&>(op1), code | 2);
+ opModM(op2.getAddress(), op1.getReg(), code | 2);
} else {
opModRM(op2, op1, op1.isREG() && op1.getKind() == op2.getKind(), op1.isMEM() && op2.isREG(), code);
}
@@ -1768,19 +1805,19 @@ private:
#endif
code = 0xFE;
if (op.isREG()) {
- opModR(Reg(ext, Operand::REG, op.getBit()), static_cast<const Reg&>(op), code);
+ opModR(Reg(ext, Operand::REG, op.getBit()), op.getReg(), code);
} else {
- opModM(static_cast<const Address&>(op), Reg(ext, Operand::REG, op.getBit()), code);
+ opModM(op.getAddress(), Reg(ext, Operand::REG, op.getBit()), code);
}
}
void opPushPop(const Operand& op, int code, int ext, int alt)
{
if (op.isREG()) {
if (op.isBit(16)) db(0x66);
- if (static_cast<const Reg&>(op).getIdx() >= 8) db(0x41);
+ if (op.getReg().getIdx() >= 8) db(0x41);
db(alt | (op.getIdx() & 7));
} else if (op.isMEM()) {
- opModM(static_cast<const Address&>(op), Reg(ext, Operand::REG, op.getBit()), code);
+ opModM(op.getAddress(), Reg(ext, Operand::REG, op.getBit()), code);
} else {
throw Error(ERR_BAD_COMBINATION);
}
@@ -1869,11 +1906,12 @@ private:
void opVex(const Reg& r, const Operand *p1, const Operand& op2, int type, int code, int imm8 = NONE)
{
if (op2.isMEM()) {
- const Address& addr = static_cast<const Address&>(op2);
- const Reg& base = addr.getRegExp().getBase();
+ const Address& addr = op2.getAddress();
+ const RegExp& regExp = addr.getRegExp();
+ const Reg& base = regExp.getBase();
if (BIT == 64 && addr.is32bit()) db(0x67);
int disp8N = 0;
- bool x = addr.getRegExp().getIndex().isExtIdx();
+ bool x = regExp.getIndex().isExtIdx();
if ((type & T_MUST_EVEX) || r.hasEvex() || (p1 && p1->hasEvex()) || addr.isBroadcast() || addr.getOpmaskIdx()) {
int aaa = addr.getOpmaskIdx();
if (aaa && !(type & T_M_K)) throw Error(ERR_INVALID_OPMASK_WITH_MEMORY);
@@ -1882,14 +1920,14 @@ private:
if (!(type & (T_B32 | T_B64))) throw Error(ERR_INVALID_BROADCAST);
b = true;
}
- int VL = addr.getRegExp().isVsib() ? addr.getRegExp().getIndex().getBit() : 0;
+ int VL = regExp.isVsib() ? regExp.getIndex().getBit() : 0;
disp8N = evex(r, base, p1, type, code, x, b, aaa, VL);
} else {
vex(r, base, p1, type, code, x);
}
opAddr(addr, r.getIdx(), (imm8 != NONE) ? 1 : 0, disp8N);
} else {
- const Reg& base = static_cast<const Reg&>(op2);
+ const Reg& base = op2.getReg();
if ((type & T_MUST_EVEX) || r.hasEvex() || (p1 && p1->hasEvex()) || base.hasEvex()) {
evex(r, base, p1, type, code);
} else {
@@ -1971,11 +2009,12 @@ private:
}
void opGather(const Xmm& x1, const Address& addr, const Xmm& x2, int type, uint8 code, int mode)
{
- if (!addr.getRegExp().isVsib(128 | 256)) throw Error(ERR_BAD_VSIB_ADDRESSING);
+ const RegExp& regExp = addr.getRegExp();
+ if (!regExp.isVsib(128 | 256)) throw Error(ERR_BAD_VSIB_ADDRESSING);
const int y_vx_y = 0;
const int y_vy_y = 1;
// const int x_vy_x = 2;
- const bool isAddrYMM = addr.getRegExp().getIndex().getBit() == 256;
+ const bool isAddrYMM = regExp.getIndex().getBit() == 256;
if (!x1.isXMM() || isAddrYMM || !x2.isXMM()) {
bool isOK = false;
if (mode == y_vx_y) {
@@ -2174,13 +2213,13 @@ public:
const Address *addr = 0;
uint8 code = 0;
if (reg1.isREG() && reg1.getIdx() == 0 && reg2.isMEM()) { // mov eax|ax|al, [disp]
- reg = &static_cast<const Reg&>(reg1);
- addr= &static_cast<const Address&>(reg2);
+ reg = &reg1.getReg();
+ addr= &reg2.getAddress();
code = 0xA0;
} else
if (reg1.isMEM() && reg2.isREG() && reg2.getIdx() == 0) { // mov [disp], eax|ax|al
- reg = &static_cast<const Reg&>(reg2);
- addr= &static_cast<const Address&>(reg1);
+ reg = &reg2.getReg();
+ addr= &reg1.getAddress();
code = 0xA2;
}
#ifdef XBYAK64
@@ -2207,7 +2246,7 @@ public:
void mov(const Operand& op, size_t imm)
{
if (op.isREG()) {
- const int size = mov_imm(static_cast<const Reg&>(op), imm);
+ const int size = mov_imm(op.getReg(), imm);
db(imm, size);
} else if (op.isMEM()) {
verifyMemHasSize(op);
@@ -2219,7 +2258,7 @@ public:
if (!inner::IsInInt32(imm)) throw Error(ERR_IMM_IS_TOO_BIG);
immSize = 4;
}
- opModM(static_cast<const Address&>(op), Reg(0, Operand::REG, op.getBit()), 0xC6, NONE, NONE, immSize);
+ opModM(op.getAddress(), Reg(0, Operand::REG, op.getBit()), 0xC6, NONE, NONE, immSize);
db(static_cast<uint32>(imm), immSize);
} else {
throw Error(ERR_BAD_COMBINATION);
@@ -2303,7 +2342,7 @@ public:
}
void mov(const Segment& seg, const Operand& op)
{
- opModRM(Reg8(seg.getIdx()), op.isREG(16|i32e) ? static_cast<const Operand&>(static_cast<const Reg&>(op).cvt32()) : op, op.isREG(16|i32e), op.isMEM(), 0x8E);
+ opModRM(Reg8(seg.getIdx()), op.isREG(16|i32e) ? static_cast<const Operand&>(op.getReg().cvt32()) : op, op.isREG(16|i32e), op.isMEM(), 0x8E);
}
#endif
diff --git a/xbyak/xbyak_mnemonic.h b/xbyak/xbyak_mnemonic.h
index 74e9759..ea306d2 100644
--- a/xbyak/xbyak_mnemonic.h
+++ b/xbyak/xbyak_mnemonic.h
@@ -1,4 +1,4 @@
-const char *getVersionString() const { return "5.52"; }
+const char *getVersionString() const { return "5.53"; }
void adc(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x10, 2); }
void adc(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x10); }
void adcx(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0x66, isREG32_REG32orMEM, NONE, 0x38); }
@@ -36,11 +36,11 @@ void bnd() { db(0xF2); }
void bndcl(const BoundsReg& bnd, const Operand& op) { db(0xF3); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1A, NONE, !op.isMEM()); }
void bndcn(const BoundsReg& bnd, const Operand& op) { db(0xF2); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1B, NONE, !op.isMEM()); }
void bndcu(const BoundsReg& bnd, const Operand& op) { db(0xF2); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1A, NONE, !op.isMEM()); }
-void bndldx(const BoundsReg& bnd, const Address& addr) { opModM(addr, bnd, 0x0F, 0x1A); }
+void bndldx(const BoundsReg& bnd, const Address& addr) { opMIB(addr, bnd, 0x0F, 0x1A); }
void bndmk(const BoundsReg& bnd, const Address& addr) { db(0xF3); opModM(addr, bnd, 0x0F, 0x1B); }
void bndmov(const Address& addr, const BoundsReg& bnd) { db(0x66); opModM(addr, bnd, 0x0F, 0x1B); }
void bndmov(const BoundsReg& bnd, const Operand& op) { db(0x66); opModRM(bnd, op, op.isBNDREG(), op.isMEM(), 0x0F, 0x1A); }
-void bndstx(const Address& addr, const BoundsReg& bnd) { opModM(addr, bnd, 0x0F, 0x1B); }
+void bndstx(const Address& addr, const BoundsReg& bnd) { opMIB(addr, bnd, 0x0F, 0x1B); }
void bsf(const Reg&reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0xBC); }
void bsr(const Reg&reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0xBD); }
void bswap(const Reg32e& reg) { opModR(Reg32(1), reg, 0x0F); }