aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMITSUNARI Shigeo <[email protected]>2015-04-22 14:31:36 +0900
committerMITSUNARI Shigeo <[email protected]>2015-04-22 16:53:52 +0900
commit2158b5387167b921106732d3be2f1c2e9bbd2727 (patch)
treefbb895609b8643fa2883bb41535465ef7b916314
parent8a005aaffe462b08442e60baa4b5232af64b76cc (diff)
downloadxbyak-2158b5387167b921106732d3be2f1c2e9bbd2727.tar.gz
xbyak-2158b5387167b921106732d3be2f1c2e9bbd2727.zip
now supporting label + offset(under construction)
-rw-r--r--readme.md3
-rw-r--r--readme.txt3
-rw-r--r--test/jmp.cpp32
-rw-r--r--test/make_nm.cpp4
-rw-r--r--xbyak/xbyak.h86
-rw-r--r--xbyak/xbyak_mnemonic.h2
6 files changed, 101 insertions, 29 deletions
diff --git a/readme.md b/readme.md
index a526c89..852afd0 100644
--- a/readme.md
+++ b/readme.md
@@ -1,5 +1,5 @@
-Xbyak 4.71 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++
+Xbyak 4.80 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++
=============
Abstract
@@ -277,6 +277,7 @@ The header files under xbyak/ are independent of cybozulib.
History
-------------
+* 2015/Apr/22 ver 4.80 rip supports label(thanks to whyisthisfieldhere)
* 2015/Jar/28 ver 4.71 support adcx, adox, cmpxchg, rdseed, stac
* 2014/Oct/14 ver 4.70 support MmapAllocator
* 2014/Jun/13 ver 4.62 disable warning of VC2014
diff --git a/readme.txt b/readme.txt
index c594c02..59ad553 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,5 +1,5 @@
- C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak 4.71
+ C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak 4.80
-----------------------------------------------------------------------------
◎概要
@@ -296,6 +296,7 @@ cybozulibは単体テストでのみ利用されていて、xbyak/ディレク�
-----------------------------------------------------------------------------
◎履歴
+2015/04/22 ver 4.80 rip相対でLabelのサポート(thanks to whyisthisfieldhere)
2015/01/28 ver 4.71 adcx, adox, cmpxchg, rdseed, stacのサポート
2014/10/14 ver 4.70 MmapAllocatorのサポート
2014/06/13 ver 4.62 VC2014で警告抑制
diff --git a/test/jmp.cpp b/test/jmp.cpp
index 7285838..5d5a158 100644
--- a/test/jmp.cpp
+++ b/test/jmp.cpp
@@ -935,3 +935,35 @@ CYBOZU_TEST_AUTO(doubleDefine)
}
} code;
}
+
+#ifndef ONLY_32BIT
+CYBOZU_TEST_AUTO(rip)
+{
+ int a[] = { 1, 10 };
+ int b[] = { 100, 1000 };
+ struct Code : Xbyak::CodeGenerator {
+ Code(const int *a, const int *b)
+ {
+ Label label1, label2;
+ jmp("@f");
+ L(label1);
+ db(a[0], 4);
+ db(a[1], 4);
+ L("@@");
+ mov(eax, ptr [rip + label1]); // a[0]
+ add(eax, ptr [rip + label1+4]); // a[1]
+ add(eax, ptr [rip + label2-8+2+6]); // b[0]
+ add(eax, ptr [rip + 16+label2-12]); // b[1]
+ ret();
+ L(label2);
+ db(b[0], 4);
+ db(b[1], 4);
+
+ // error
+ CYBOZU_TEST_EXCEPTION(rip + label1 + label2, Xbyak::Error);
+ }
+ } code(a, b);
+ int ret = code.getCode<int (*)()>()();
+ CYBOZU_TEST_EQUAL(ret, a[0] + a[1] + b[0] + b[1]);
+}
+#endif
diff --git a/test/make_nm.cpp b/test/make_nm.cpp
index ad32cae..b90d130 100644
--- a/test/make_nm.cpp
+++ b/test/make_nm.cpp
@@ -187,7 +187,7 @@ class Test {
if (ccc & 1) {
return isXbyak_ ? "ptr[rdx+r15+0x12]" : "[rdx+r15+0x12]";
} else {
- return isXbyak_ ? "ptr[rip - 0x13456]" : "[rip - 0x13456]";
+ return isXbyak_ ? "ptr[rip - 0x13456+1-3]" : "[rip - 0x13456+1-3]";
}
}
case MEM8:
@@ -457,6 +457,8 @@ class Test {
#ifdef USE_YASM
put("jmp", "ptr[rip + 0x12345678]", "[rip+0x12345678]");
put("call", "ptr[rip + 0x12345678]", "[rip+0x12345678]");
+ put("call", "ptr[rip -23]", "[rip-23]");
+ put("call", "ptr[rip -23+56]", "[rip-23+56]");
#endif
#endif
}
diff --git a/xbyak/xbyak.h b/xbyak/xbyak.h
index 7958863..33a2781 100644
--- a/xbyak/xbyak.h
+++ b/xbyak/xbyak.h
@@ -96,7 +96,7 @@ namespace Xbyak {
enum {
DEFAULT_MAX_CODE_SIZE = 4096,
- VERSION = 0x4710 /* 0xABCD = A.BC(D) */
+ VERSION = 0x4800 /* 0xABCD = A.BC(D) */
};
#ifndef MIE_INTEGER_TYPE_DEFINED
@@ -411,6 +411,8 @@ public:
bool operator!=(const Operand& rhs) const { return !operator==(rhs); }
};
+class Label;
+
struct Reg8;
struct Reg16;
struct Reg32;
@@ -471,13 +473,18 @@ struct Reg64 : public Reg32e {
explicit Reg64(int idx = 0) : Reg32e(idx, 64) {}
};
struct RegRip {
- uint32 disp_;
- explicit RegRip(unsigned int disp = 0) : disp_(disp) {}
- friend const RegRip operator+(const RegRip& r, unsigned int disp) {
- return RegRip(r.disp_ + disp);
+ sint64 disp_;
+ Label* label_;
+ explicit RegRip(sint64 disp = 0, Label* label = 0) : disp_(disp), label_(label) {}
+ friend const RegRip operator+(const RegRip& r, sint64 disp) {
+ return RegRip(r.disp_ + disp, r.label_);
+ }
+ friend const RegRip operator-(const RegRip& r, sint64 disp) {
+ return RegRip(r.disp_ - disp, r.label_);
}
- friend const RegRip operator-(const RegRip& r, unsigned int disp) {
- return RegRip(r.disp_ - disp);
+ friend const RegRip operator+(const RegRip& r, Label& label) {
+ if (r.label_) throw Error(ERR_BAD_ADDRESSING);
+ return RegRip(r.disp_, &label);
}
};
#endif
@@ -814,6 +821,7 @@ class Address : public Operand {
uint8 size_;
uint8 rex_;
uint64 disp_;
+ const Label* label_;
bool isOnlyDisp_;
bool is64bitDisp_;
bool is32bit_;
@@ -826,6 +834,7 @@ public:
, size_(0)
, rex_(0)
, disp_(disp)
+ , label_(0)
, isOnlyDisp_(isOnlyDisp)
, is64bitDisp_(is64bitDisp)
, is32bit_(is32bit)
@@ -833,6 +842,19 @@ public:
, isYMM_(isYMM)
{
}
+ Address(uint32 sizeBit, const Label *label, uint64 disp)
+ : Operand(0, MEM, sizeBit)
+ , size_(0)
+ , rex_(0)
+ , disp_(disp)
+ , label_(label)
+ , isOnlyDisp_(false)
+ , is64bitDisp_(false)
+ , is32bit_(false)
+ , isVsib_(false)
+ , isYMM_(false)
+ {
+ }
void db(int code)
{
if (size_ >= sizeof(top_)) throw Error(ERR_CODE_IS_TOO_BIG);
@@ -854,6 +876,7 @@ public:
uint8 getRex() const { verify(); return rex_; }
bool is64bitDisp() const { verify(); return is64bitDisp_; } // for moffset
void setRex(uint8 rex) { rex_ = rex; }
+ const Label* getLabel() const { return label_; }
};
class AddressFrame {
@@ -924,9 +947,10 @@ public:
}
Address operator[](const RegRip& addr) const
{
+ if (addr.label_) return Address(bit_, addr.label_, addr.disp_);
Address frame(bit_, true, addr.disp_, false);
- frame.db(B00000101);
- frame.dd(addr.disp_);
+ frame.db(0x05);
+ frame.dd(inner::VerifyInInt32(addr.disp_));
return frame;
}
#endif
@@ -940,6 +964,11 @@ struct JmpLabel {
size_t endOfJmp; /* offset from top to the end address of jmp */
int jmpSize;
inner::LabelMode mode;
+ uint64 disp; // disp for [rip + disp]
+ explicit JmpLabel(size_t endOfJmp = 0, int jmpSize = 0, inner::LabelMode mode = inner::LasIs, uint64 disp = 0)
+ : endOfJmp(endOfJmp), jmpSize(jmpSize), mode(mode), disp(disp)
+ {
+ }
};
class LabelManager;
@@ -1022,7 +1051,7 @@ class LabelManager {
} else if (jmp->mode == inner::Labs) {
disp = size_t(base_->getCurr());
} else {
- disp = addrOffset - jmp->endOfJmp;
+ disp = addrOffset - jmp->endOfJmp + jmp->disp;
#ifdef XBYAK64
if (jmp->jmpSize <= 4 && !inner::IsInInt32(disp)) throw Error(ERR_OFFSET_IS_TOO_BIG);
#endif
@@ -1288,7 +1317,7 @@ private:
rex(addr, reg);
db(code0 | (reg.isBit(8) ? 0 : 1)); if (code1 != NONE) db(code1); if (code2 != NONE) db(code2);
addr.updateRegField(static_cast<uint8>(reg.getIdx()));
- db(addr.getCode(), static_cast<int>(addr.getSize()));
+ opAddr(addr);
}
void makeJmp(uint32 disp, LabelType type, uint8 shortCode, uint8 longCode, uint8 longPref)
{
@@ -1311,17 +1340,16 @@ private:
if (labelMgr_.getOffset(&offset, label)) { /* label exists */
makeJmp(inner::VerifyInInt32(offset - size_), type, shortCode, longCode, longPref);
} else {
- JmpLabel jmp;
+ int jmpSize = 0;
if (type == T_NEAR) {
- jmp.jmpSize = 4;
+ jmpSize = 4;
if (longPref) db(longPref);
db(longCode); dd(0);
} else {
- jmp.jmpSize = 1;
+ jmpSize = 1;
db(shortCode); db(0);
}
- jmp.mode = inner::LasIs;
- jmp.endOfJmp = size_;
+ JmpLabel jmp(size_, jmpSize, inner::LasIs);
labelMgr_.addUndefinedLabel(label, jmp);
}
}
@@ -1338,6 +1366,15 @@ private:
}
}
+ void opAddr(const Address &addr)
+ {
+ if (addr.getLabel()) { // [rip + Label]
+ db(0x05);
+ putL_inner(*addr.getLabel(), true, addr.getDisp());
+ } else {
+ db(addr.getCode(), static_cast<int>(addr.getSize()));
+ }
+ }
/* preCode is for SSSE3/SSE4 */
void opGen(const Operand& reg, const Operand& op, int code, int pref, bool isValid(const Operand&, const Operand&), int imm8 = NONE, int preCode = NONE)
{
@@ -1497,7 +1534,7 @@ private:
rex(addr, st0);
db(code);
addr.updateRegField(ext);
- db(addr.getCode(), static_cast<int>(addr.getSize()));
+ opAddr(addr);
}
// use code1 if reg1 == st0
// use code2 if reg1 != st0 && reg2 == st0
@@ -1532,7 +1569,7 @@ private:
if (p2->isMEM()) {
const Address& addr = static_cast<const Address&>(*p2);
addr.updateRegField(static_cast<uint8>(r.getIdx()));
- db(addr.getCode(), static_cast<int>(addr.getSize()));
+ opAddr(addr);
} else {
db(getModRM(3, r.getIdx(), p2->getIdx()));
}
@@ -1792,13 +1829,15 @@ private:
return bit / 8;
}
template<class T>
- void putL_inner(T& label)
+ void putL_inner(T& label, bool relative = false, uint64 disp = 0)
{
- const int jmpSize = (int)sizeof(size_t);
+ const int jmpSize = relative ? 4 : (int)sizeof(size_t);
if (isAutoGrow() && size_ + 16 >= maxSize_) growMemory();
size_t offset = 0;
if (labelMgr_.getOffset(&offset, label)) {
- if (isAutoGrow()) {
+ if (relative) {
+ db(inner::VerifyInInt32(offset + disp - size_ - jmpSize), jmpSize);
+ } else if (isAutoGrow()) {
db(uint64(0), jmpSize);
save(size_ - jmpSize, offset, jmpSize, inner::LaddTop);
} else {
@@ -1807,10 +1846,7 @@ private:
return;
}
db(uint64(0), jmpSize);
- JmpLabel jmp;
- jmp.endOfJmp = size_;
- jmp.jmpSize = jmpSize;
- jmp.mode = isAutoGrow() ? inner::LaddTop : inner::Labs;
+ JmpLabel jmp(size_, jmpSize, (relative ? inner::LasIs : isAutoGrow() ? inner::LaddTop : inner::Labs), disp);
labelMgr_.addUndefinedLabel(label, jmp);
}
public:
diff --git a/xbyak/xbyak_mnemonic.h b/xbyak/xbyak_mnemonic.h
index d460e4c..5e0beae 100644
--- a/xbyak/xbyak_mnemonic.h
+++ b/xbyak/xbyak_mnemonic.h
@@ -1,4 +1,4 @@
-const char *getVersionString() const { return "4.71"; }
+const char *getVersionString() const { return "4.80"; }
void packssdw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x6B); }
void packsswb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x63); }
void packuswb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x67); }