jmp test runs well

This commit is contained in:
MITSUNARI Shigeo 2013-03-27 14:28:22 +09:00
parent be26fde1fa
commit 3756d85207
2 changed files with 68 additions and 42 deletions

View File

@ -464,9 +464,8 @@ 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);
if (v == size_t(p) + expect) return true;
printf("err p=%p, offset=%lld, v=%llx(%llx), expect=%d\n", p, (long long)offset, (long long)v, (long long)(expect + size_t(p)), (int)expect);
return false;
}

View File

@ -197,7 +197,7 @@ namespace inner {
enum { debug = 1 };
static const size_t ALIGN_PAGE_SIZE = 4096;
inline bool IsInDisp8(uint64 x) { return 0xFFFFFF80 <= x || x <= 0x7F; }
inline bool IsInDisp8(uint32 x) { return 0xFFFFFF80 <= x || x <= 0x7F; }
inline bool IsInInt32(uint64 x) { return ~uint64(0x7fffffffu) <= x || x <= 0x7FFFFFFFU; }
inline uint32 VerifyInInt32(uint64 x)
@ -208,6 +208,12 @@ inline uint32 VerifyInInt32(uint64 x)
return static_cast<uint32>(x);
}
enum LabelMode {
Labs, // absolute
Lrelative, // relative(input addr is relative)
LaddTop // relative(addr + top)
};
} // inner
/*
@ -221,7 +227,6 @@ struct Allocator {
virtual bool useProtect() const { return true; }
};
class Operand {
private:
const uint8 idx_;
@ -480,10 +485,13 @@ class CodeArray {
struct AddrInfo {
size_t offset_;
size_t val_;
int size_;
bool isRelative_;
AddrInfo(size_t offset, size_t val, int size, bool isRelative)
: offset_(offset), val_(val), size_(size), isRelative_(isRelative) {}
int jmpSize;
inner::LabelMode mode;
AddrInfo(size_t offset, size_t val, int size, inner::LabelMode _mode)
: offset_(offset), val_(val), jmpSize(size), mode(_mode) {}
bool isAbs() const { return mode == inner::Labs; }
bool isRelative() const { return mode == inner::Lrelative; }
bool isAddTop() const { return mode == inner::LaddTop; }
};
typedef std::list<AddrInfo> AddrInfoList;
AddrInfoList addrInfoList_;
@ -515,9 +523,9 @@ protected:
void calcJmpAddress()
{
for (AddrInfoList::const_iterator i = addrInfoList_.begin(), ie = addrInfoList_.end(); i != ie; ++i) {
// uint32 disp = inner::GetOffsetDist(i->val_, i->isRelative_ ? 0 : size_t(top_));
uint32 disp = inner::VerifyInInt32(i->isRelative_ ? i->val_ : i->val_ - size_t(top_));
rewrite(i->offset_, disp, i->size_);
uint64 disp = i->isAddTop() ? i->val_ + size_t(top_) : i->isRelative() ? i->val_ : i->val_ - size_t(top_);
if (i->jmpSize == 4) disp = inner::VerifyInInt32(disp);
rewrite(i->offset_, disp, i->jmpSize);
}
if (alloc_->useProtect() && !protect(top_, size_, true)) throw ERR_CANT_PROTECT;
}
@ -627,9 +635,9 @@ public:
data[i] = static_cast<uint8>(disp >> (i * 8));
}
}
void save(size_t offset, size_t val, int size, bool isRelative)
void save(size_t offset, size_t val, int size, inner::LabelMode mode)
{
addrInfoList_.push_back(AddrInfo(offset, val, size, isRelative));
addrInfoList_.push_back(AddrInfo(offset, val, size, mode));
}
bool isAutoGrow() const { return type_ == AUTO_GROW; }
void updateRegField(uint8 regIdx) const
@ -767,13 +775,16 @@ 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)
inner::LabelMode mode;
JmpLabel(size_t _endOfJmp = 0, int _jmpSize = 0, inner::LabelMode _mode = inner::Lrelative)
: endOfJmp(_endOfJmp)
, jmpSize(_jmpSize)
, mode(_mode)
{
}
bool isAbs() const { return mode == inner::Labs; }
bool isRelative() const { return mode == inner::Lrelative; }
bool isAddTop() const { return mode == inner::LaddTop; }
};
class Label {
@ -786,14 +797,21 @@ class Label {
int stackPos_;
int usedCount_;
int localCount_; // for .***
public:
struct Addr {
Addr(size_t _offset = 0, const uint8 *_addr = 0) : offset(_offset), addr(_addr) {}
size_t offset;
const uint8 *addr;
};
private:
#ifdef XBYAK_USE_UNORDERED_MAP
typedef std::unordered_map<std::string, size_t> DefinedList;
typedef std::unordered_map<std::string, Addr> DefinedList;
typedef std::unordered_multimap<std::string, const JmpLabel> UndefinedList;
#elif defined(XBYAK_USE_TR1_UNORDERED_MAP)
typedef std::tr1::unordered_map<std::string, size_t> DefinedList;
typedef std::tr1::unordered_map<std::string, Addr> DefinedList;
typedef std::tr1::unordered_multimap<std::string, const JmpLabel> UndefinedList;
#else
typedef std::map<std::string, size_t> DefinedList;
typedef std::map<std::string, Addr> DefinedList;
typedef std::multimap<std::string, const JmpLabel> UndefinedList;
#endif
DefinedList definedList_;
@ -857,7 +875,7 @@ public:
}
label = newLabel.c_str();
// add label
DefinedList::value_type item(label, addrOffset);
DefinedList::value_type item(label, Label::Addr(addrOffset, addr));
std::pair<DefinedList::iterator, bool> ret = definedList_.insert(item);
if (!ret.second) throw ERR_LABEL_IS_REDEFINED;
// search undefined label
@ -867,12 +885,12 @@ public:
const JmpLabel *jmp = &itr->second;
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;
if (jmp->jmpSize == 1 && !inner::IsInDisp8((uint32)disp)) throw ERR_LABEL_IS_TOO_FAR;
size_t offset = jmp->endOfJmp - jmp->jmpSize;
if (base_->isAutoGrow()) {
base_->save(offset, disp, jmp->jmpSize, true);
base_->save(offset, jmp->isAddTop() ? addrOffset : jmp->isAbs() ? size_t(addr) : disp, jmp->jmpSize, jmp->mode);
} else {
base_->rewrite(offset, jmp->isAbs ? size_t(addr) : disp, jmp->jmpSize);
base_->rewrite(offset, jmp->isAbs() ? size_t(addr) : disp, jmp->jmpSize);
}
undefinedList_.erase(itr);
}
@ -882,12 +900,18 @@ public:
std::string newLabel = convertLabel(label);
DefinedList::const_iterator itr = definedList_.find(newLabel);
if (itr != definedList_.end()) {
*offset = itr->second;
*offset = itr->second.offset;
return true;
} else {
return false;
}
}
const Label::Addr *getAddr(const char *label) const
{
std::string newLabel = convertLabel(label);
DefinedList::const_iterator itr = definedList_.find(newLabel);
return (itr == definedList_.end()) ? 0 : &(itr->second);
}
void addUndefinedLabel(const char *label, const JmpLabel& jmp)
{
std::string newLabel = convertLabel(label);
@ -1031,9 +1055,9 @@ private:
void opJmp(const char *label, LabelType type, uint8 shortCode, uint8 longCode, uint8 longPref)
{
if (isAutoGrow() && size_ + 16 >= maxSize_) growMemory(); /* avoid splitting code of jmp */
size_t offset = 0;
if (label_.getOffset(&offset, label)) { /* label exists */
makeJmp(inner::VerifyInInt32(offset - getSize()), type, shortCode, longCode, longPref);
const Label::Addr *addr = label_.getAddr(label);
if (addr) { /* label exists */
makeJmp(inner::VerifyInInt32(addr->offset - getSize()), type, shortCode, longCode, longPref);
} else {
JmpLabel jmp;
if (type == T_NEAR) {
@ -1054,8 +1078,8 @@ private:
if (type != T_NEAR) throw ERR_ONLY_T_NEAR_IS_SUPPORTED_IN_AUTO_GROW;
if (size_ + 16 >= maxSize_) growMemory();
db(longCode);
save(size_, size_t(addr) - (getSize() + 4), 4, false);
dd(0);
save(size_ - 4, size_t(addr) - size_, 4, inner::Labs);
} else {
makeJmp(inner::VerifyInInt32(reinterpret_cast<const uint8*>(addr) - getCurr()), type, shortCode, longCode, 0);
}
@ -1425,26 +1449,29 @@ public:
#endif
const char *label)
{
if (label == 0) {
mov(reg, 0, true);
return;
}
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);
if (isAutoGrow() && size_ + 16 >= maxSize_) growMemory();
const Label::Addr *addr = label_.getAddr(label);
if (addr) {
if (isAutoGrow()) {
mov(reg, dummyAddr);
save(size_ - jmpSize, addr->offset, jmpSize, inner::LaddTop);
} else {
mov(reg, size_t(top_) + addr->offset, false);
}
return;
}
mov(reg, dummyAddr);
JmpLabel jmp;
jmp.jmpSize = jmpSize;
jmp.endOfJmp = getSize();
jmp.isAbs = true;
JmpLabel jmp(getSize(), jmpSize, isAutoGrow() ? inner::LaddTop : inner::Labs);
label_.addUndefinedLabel(label, jmp);
}
void cmpxchg8b(const Address& addr) { opModM(addr, Reg32(1), 0x0F, B11000111); }