aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMITSUNARI Shigeo <[email protected]>2013-03-25 12:08:13 +0900
committerMITSUNARI Shigeo <[email protected]>2013-03-25 12:08:13 +0900
commitbe26fde1fad7d163bb49c3cd5a88d8b58791e732 (patch)
treee77336f13def519cde68edeeb4dc899ca4020808
parentf7872aef2114b8f167eeee3b713c19a6bec61923 (diff)
downloadxbyak-be26fde1fad7d163bb49c3cd5a88d8b58791e732.tar.gz
xbyak-be26fde1fad7d163bb49c3cd5a88d8b58791e732.zip
support label for mov without AutoGrow
-rw-r--r--test/Makefile4
-rw-r--r--test/jmp.cpp115
-rw-r--r--xbyak/xbyak.h59
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); }