diff options
author | MITSUNARI Shigeo <[email protected]> | 2013-03-25 12:08:13 +0900 |
---|---|---|
committer | MITSUNARI Shigeo <[email protected]> | 2013-03-25 12:08:13 +0900 |
commit | be26fde1fad7d163bb49c3cd5a88d8b58791e732 (patch) | |
tree | e77336f13def519cde68edeeb4dc899ca4020808 | |
parent | f7872aef2114b8f167eeee3b713c19a6bec61923 (diff) | |
download | xbyak-be26fde1fad7d163bb49c3cd5a88d8b58791e732.tar.gz xbyak-be26fde1fad7d163bb49c3cd5a88d8b58791e732.zip |
support label for mov without AutoGrow
-rw-r--r-- | test/Makefile | 4 | ||||
-rw-r--r-- | test/jmp.cpp | 115 | ||||
-rw-r--r-- | xbyak/xbyak.h | 59 |
3 files changed, 165 insertions, 13 deletions
diff --git a/test/Makefile b/test/Makefile index f101dda..2d5a5bf 100644 --- a/test/Makefile +++ b/test/Makefile @@ -23,8 +23,8 @@ test_mmx: test_mmx.cpp ../xbyak/xbyak.h $(CXX) $(CFLAGS) test_mmx.cpp -o $@ -lpthread jmp: jmp.cpp ../xbyak/xbyak.h $(CXX) $(CFLAGS) jmp.cpp -o $@ -m32 -jmp64: jmp.cpp ../xbyak/xbyak.h -m64 - $(CXX) $(CFLAGS) jmp.cpp -o $@ +jmp64: jmp.cpp ../xbyak/xbyak.h + $(CXX) $(CFLAGS) jmp.cpp -o $@ -m64 address: address.cpp ../xbyak/xbyak.h $(CXX) $(CFLAGS) address.cpp -o $@ -m32 address64: address.cpp ../xbyak/xbyak.h diff --git a/test/jmp.cpp b/test/jmp.cpp index 5776d6f..148fa7a 100644 --- a/test/jmp.cpp +++ b/test/jmp.cpp @@ -200,6 +200,9 @@ void testJmpCx() } } +#ifdef _MSC_VER + #pragma warning(disable : 4310) +#endif void test2() { puts("test2"); @@ -422,6 +425,114 @@ void test5() diff(fm, gm); } +struct MovLabelCode : Xbyak::CodeGenerator { + MovLabelCode(bool grow) + : Xbyak::CodeGenerator(grow ? 128 : 4096, grow ? Xbyak::AutoGrow : 0) + { +#ifdef XBYAK64 + const Reg64& a = rax; +#else + const Reg32& a = eax; +#endif + inLocalLabel(); + nop(); // 0x90 + L(".lp1"); + nop(); + mov(a, ".lp1"); // 0xb8 + <4byte> / 0x48bb + <8byte> + nop(); + mov(a, ".lp2"); // 0xb8 + // force realloc if AutoGrow + for (int i = 0; i < 256; i++) { + nop(); + } + nop(); + L(".lp2"); + outLocalLabel(); + } +}; + +size_t getValue(const uint8* p) +{ + size_t v = 0; + for (size_t i = 0; i < sizeof(size_t); i++) { + v |= p[i] << (i * 8); + } + return v; +} + +bool checkAddr(const uint8 *p, size_t offset, size_t expect) +{ + size_t v = getValue(p + offset); + printf("v=%p\n", (void*)v); + v -= size_t(p); + if (v == expect) return true; + printf("err p=%p, offset=%lld, v=%d, expect=%d\n", p, (long long)offset, (int)v, (int)expect); + return false; +} + +void testMovLabel(bool grow) +{ + bool isOK = true; + MovLabelCode code(grow); + code.ready(); + const uint8* const p = code.getCode(); +printf("QQQ p=%p\n", p); + const struct { + int pos; + uint8 ok; + } tbl[] = { +#ifdef XBYAK32 + { 0x00, 0x90 }, + // lp1:0x001 + { 0x001, 0x90 }, + { 0x002, 0xb8 }, + // 0x003 + { 0x007, 0x90 }, + { 0x008, 0xb8 }, + // 0x009 + { 0x10d, 0x90 }, + // lp2:0x10e +#else + { 0x000, 0x90 }, + // lp1:0x001 + { 0x001, 0x90 }, + { 0x002, 0x48 }, + { 0x003, 0xb8 }, + // 0x004 + { 0x00c, 0x90 }, + { 0x00d, 0x48 }, + { 0x00e, 0xb8 }, + // 0x00f + { 0x117, 0x90 }, + // lp2:0x118 +#endif + }; + puts("---"); + for (int i = 0; i < 32; i++) { + printf("%02x ", p[i]); + if (i == 15) printf("\n"); + } + puts("---"); + + for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) { + int pos = tbl[i].pos; + uint8 x = p[pos]; + uint8 ok = tbl[i].ok; + if (x != ok) { + printf("err pos=%d, x=%02x, ok=%02x\n", pos, x, ok); + isOK = false; + } + } +#ifdef XBYAK32 + isOK &= checkAddr(p, 0x03, 0x001); + isOK &= checkAddr(p, 0x09, 0x10e); +#else + isOK &= checkAddr(p, 0x04, 0x001); + isOK &= checkAddr(p, 0x0f, 0x118); +#endif + if (isOK) puts("ok"); +} + int main() { try { @@ -433,6 +544,10 @@ int main() test4(); test5(); testJmpCx(); + puts("test MovLabelCode"); + testMovLabel(false); + puts("test MovLabelCode:grow"); + testMovLabel(true); } catch (Xbyak::Error err) { printf("ERR:%s(%d)\n", Xbyak::ConvertErrorToString(err), err); } catch (...) { diff --git a/xbyak/xbyak.h b/xbyak/xbyak.h index bf9acde..0a0e54f 100644 --- a/xbyak/xbyak.h +++ b/xbyak/xbyak.h @@ -197,7 +197,7 @@ namespace inner { enum { debug = 1 }; static const size_t ALIGN_PAGE_SIZE = 4096; -inline bool IsInDisp8(uint32 x) { return 0xFFFFFF80 <= x || x <= 0x7F; } +inline bool IsInDisp8(uint64 x) { return 0xFFFFFF80 <= x || x <= 0x7F; } inline bool IsInInt32(uint64 x) { return ~uint64(0x7fffffffu) <= x || x <= 0x7FFFFFFFU; } inline uint32 VerifyInInt32(uint64 x) @@ -501,7 +501,6 @@ protected: */ void growMemory() { -// const size_t newSize = maxSize_ + inner::ALIGN_PAGE_SIZE; const size_t newSize = maxSize_ * 2; uint8 *newTop = alloc_->alloc(newSize); if (newTop == 0) throw ERR_CANT_ALLOC; @@ -768,6 +767,13 @@ public: struct JmpLabel { size_t endOfJmp; /* offset from top to the end address of jmp */ int jmpSize; + bool isAbs; + JmpLabel() + : endOfJmp(0) + , jmpSize(0) + , isAbs(false) + { + } }; class Label { @@ -841,7 +847,7 @@ public: localCount_ = stack_[--stackPos_ - 1]; } void set(CodeArray *base) { base_ = base; } - void define(const char *label, size_t addr) + void define(const char *label, size_t addrOffset, const uint8_t *addr) { std::string newLabel(label); if (newLabel == "@@") { @@ -851,7 +857,7 @@ public: } label = newLabel.c_str(); // add label - DefinedList::value_type item(label, addr); + DefinedList::value_type item(label, addrOffset); std::pair<DefinedList::iterator, bool> ret = definedList_.insert(item); if (!ret.second) throw ERR_LABEL_IS_REDEFINED; // search undefined label @@ -859,13 +865,14 @@ public: UndefinedList::iterator itr = undefinedList_.find(label); if (itr == undefinedList_.end()) break; const JmpLabel *jmp = &itr->second; - uint32 disp = inner::VerifyInInt32(addr - jmp->endOfJmp); + size_t disp = addrOffset - jmp->endOfJmp; + if (jmp->jmpSize <= 4) disp = inner::VerifyInInt32(disp); if (jmp->jmpSize == 1 && !inner::IsInDisp8(disp)) throw ERR_LABEL_IS_TOO_FAR; size_t offset = jmp->endOfJmp - jmp->jmpSize; if (base_->isAutoGrow()) { base_->save(offset, disp, jmp->jmpSize, true); } else { - base_->rewrite(offset, disp, jmp->jmpSize); + base_->rewrite(offset, jmp->isAbs ? size_t(addr) : disp, jmp->jmpSize); } undefinedList_.erase(itr); } @@ -1252,7 +1259,7 @@ public: #endif void L(const char *label) { - label_.define(label, getSize()); + label_.define(label, getSize(), getCurr()); } void inLocalLabel() { label_.enterLocal(); } void outLocalLabel() { label_.leaveLocal(); } @@ -1378,18 +1385,18 @@ public: } void mov(const Operand& op, #ifdef XBYAK64 - uint64 + uint64 imm, bool opti = true #else - uint32 + uint32 imm, bool = true #endif - imm) + ) { verifyMemHasSize(op); if (op.isREG()) { rex(op); int code, size; #ifdef XBYAK64 - if (op.isBit(64) && inner::IsInInt32(imm)) { + if (opti && op.isBit(64) && inner::IsInInt32(imm)) { db(B11000111); code = B11000000; size = 4; @@ -1410,6 +1417,36 @@ public: throw ERR_BAD_COMBINATION; } } + void mov( +#ifdef XBYAK64 + const Reg64& reg, +#else + const Reg32& reg, +#endif + const char *label) + { + const int jmpSize = (int)sizeof(size_t); +#ifdef XBYAK64 + const size_t dummyAddr = size_t(0x1122334455667788ull); +#else + const size_t dummyAddr = 0x12345678; +#endif + if (isAutoGrow()) { + if (size_ + 16 >= maxSize_) growMemory(); + return; + } + size_t offset = 0; + if (label_.getOffset(&offset, label)) { + mov(reg, size_t(top_) + offset, false); + return; + } + mov(reg, dummyAddr); + JmpLabel jmp; + jmp.jmpSize = jmpSize; + jmp.endOfJmp = getSize(); + jmp.isAbs = true; + label_.addUndefinedLabel(label, jmp); + } void cmpxchg8b(const Address& addr) { opModM(addr, Reg32(1), 0x0F, B11000111); } #ifdef XBYAK64 void cmpxchg16b(const Address& addr) { opModM(addr, Reg64(1), 0x0F, B11000111); } |