diff options
author | MITSUNARI Shigeo <[email protected]> | 2015-04-22 14:31:36 +0900 |
---|---|---|
committer | MITSUNARI Shigeo <[email protected]> | 2015-04-22 16:53:52 +0900 |
commit | 2158b5387167b921106732d3be2f1c2e9bbd2727 (patch) | |
tree | fbb895609b8643fa2883bb41535465ef7b916314 | |
parent | 8a005aaffe462b08442e60baa4b5232af64b76cc (diff) | |
download | xbyak-2158b5387167b921106732d3be2f1c2e9bbd2727.tar.gz xbyak-2158b5387167b921106732d3be2f1c2e9bbd2727.zip |
now supporting label + offset(under construction)
-rw-r--r-- | readme.md | 3 | ||||
-rw-r--r-- | readme.txt | 3 | ||||
-rw-r--r-- | test/jmp.cpp | 32 | ||||
-rw-r--r-- | test/make_nm.cpp | 4 | ||||
-rw-r--r-- | xbyak/xbyak.h | 86 | ||||
-rw-r--r-- | xbyak/xbyak_mnemonic.h | 2 |
6 files changed, 101 insertions, 29 deletions
@@ -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 @@ -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); } |