mirror of
https://github.com/herumi/xbyak
synced 2024-11-21 16:09:11 -07:00
add setDefaultJmpNEAR
This commit is contained in:
parent
da7f731707
commit
4da8fd4e6d
5 changed files with 114 additions and 6 deletions
29
readme.md
29
readme.md
|
@ -1,5 +1,5 @@
|
|||
|
||||
# Xbyak 5.86 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++
|
||||
# Xbyak 5.87 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++
|
||||
|
||||
## Abstract
|
||||
|
||||
|
@ -216,6 +216,32 @@ void func1()
|
|||
}
|
||||
```
|
||||
|
||||
### short and long jump
|
||||
Xbyak deals with jump mnemonics of an undefined label as short jump if no type is specified.
|
||||
So if the size between jmp and label is larger than 127 byte, then xbyak will cause an error.
|
||||
|
||||
```
|
||||
jmp("short-jmp"); // short jmp
|
||||
// small code
|
||||
L("short-jmp");
|
||||
|
||||
jmp("long-jmp");
|
||||
// long code
|
||||
L("long-jmp"); // throw exception
|
||||
```
|
||||
Then specify T_NEAR for jmp.
|
||||
```
|
||||
jmp("long-jmp", T_NEAR); // long jmp
|
||||
// long code
|
||||
L("long-jmp");
|
||||
```
|
||||
Or call `setDefaultJmpNEAR(true);` once, then the default type is set to T_NEAR.
|
||||
```
|
||||
jmp("long-jmp"); // long jmp
|
||||
// long code
|
||||
L("long-jmp");
|
||||
```
|
||||
|
||||
### Label class
|
||||
|
||||
`L()` and `jxx()` support Label class.
|
||||
|
@ -396,6 +422,7 @@ modified new BSD License
|
|||
http://opensource.org/licenses/BSD-3-Clause
|
||||
|
||||
## History
|
||||
* 2019/Dec/19 ver 5.87 add setDefaultJmpNEAR(), which deals with `jmp` of an undefined label as T_NEAR if no type is specified.
|
||||
* 2019/Dec/13 ver 5.86 [changed] revert to the behavior before v5.84 if -fno-operator-names is defined (and() is available)
|
||||
* 2019/Dec/07 ver 5.85 append MAP_JIT flag to mmap for macOS mojave or later
|
||||
* 2019/Nov/29 ver 5.84 [changed] XBYAK_NO_OP_NAMES is defined unless XBYAK_USE_OP_NAMES is defined
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak 5.86
|
||||
C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak 5.87
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
◎概要
|
||||
|
@ -371,6 +371,7 @@ sample/{echo,hello}.bfは http://www.kmonos.net/alang/etc/brainfuck.php から
|
|||
-----------------------------------------------------------------------------
|
||||
◎履歴
|
||||
|
||||
2019/12/19 ver 5.87 未定義ラベルへのjmp命令のデフォルト挙動をT_NEARにするsetDefaultJmpNEAR()を追加
|
||||
2019/12/13 ver 5.86 [変更] -fno-operator-namesが指定されたときは5.84以前の挙動に戻す
|
||||
2019/12/07 ver 5.85 mmapにMAP_JITフラグを追加(macOS mojave以上)
|
||||
2019/11/29 ver 5.84 [変更] XBYAK_USE_OP_NAMESが定義されていない限りXBYAK_NO_OP_NAMESが定義されるように変更
|
||||
|
|
73
test/jmp.cpp
73
test/jmp.cpp
|
@ -1305,3 +1305,76 @@ CYBOZU_TEST_AUTO(release_label_after_code)
|
|||
printf("id=%d %d %d %d %d\n", L1.getId(), L2.getId(), L3.getId(), L4.getId(), L5.getId());
|
||||
}
|
||||
}
|
||||
|
||||
struct JmpTypeCode : Xbyak::CodeGenerator {
|
||||
void nops()
|
||||
{
|
||||
for (int i = 0; i < 130; i++) {
|
||||
nop();
|
||||
}
|
||||
}
|
||||
// return jmp code size
|
||||
size_t gen(bool pre, bool large, Xbyak::CodeGenerator::LabelType type)
|
||||
{
|
||||
Label label;
|
||||
if (pre) {
|
||||
L(label);
|
||||
if (large) nops();
|
||||
size_t pos = getSize();
|
||||
jmp(label, type);
|
||||
return getSize() - pos;
|
||||
} else {
|
||||
size_t pos = getSize();
|
||||
jmp(label, type);
|
||||
size_t size = getSize() - pos;
|
||||
if (large) nops();
|
||||
L(label);
|
||||
return size;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CYBOZU_TEST_AUTO(setDefaultJmpNEAR)
|
||||
{
|
||||
const Xbyak::CodeGenerator::LabelType T_SHORT = Xbyak::CodeGenerator::T_SHORT;
|
||||
const Xbyak::CodeGenerator::LabelType T_NEAR = Xbyak::CodeGenerator::T_NEAR;
|
||||
const Xbyak::CodeGenerator::LabelType T_AUTO = Xbyak::CodeGenerator::T_AUTO;
|
||||
const struct {
|
||||
bool pre;
|
||||
bool large;
|
||||
Xbyak::CodeGenerator::LabelType type;
|
||||
size_t expect1; // 0 means exception
|
||||
size_t expect2;
|
||||
} tbl[] = {
|
||||
{ false, false, T_SHORT, 2, 2 },
|
||||
{ false, false, T_NEAR, 5, 5 },
|
||||
{ false, true, T_SHORT, 0, 0 },
|
||||
{ false, true, T_NEAR, 5, 5 },
|
||||
|
||||
{ true, false, T_SHORT, 2, 2 },
|
||||
{ true, false, T_NEAR, 5, 5 },
|
||||
{ true, true, T_SHORT, 0, 0 },
|
||||
{ true, true, T_NEAR, 5, 5 },
|
||||
|
||||
{ false, false, T_AUTO, 2, 5 },
|
||||
{ false, true, T_AUTO, 0, 5 },
|
||||
{ true, false, T_AUTO, 2, 2 },
|
||||
{ true, true, T_AUTO, 5, 5 },
|
||||
};
|
||||
JmpTypeCode code1, code2;
|
||||
code2.setDefaultJmpNEAR(true);
|
||||
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
|
||||
if (tbl[i].expect1) {
|
||||
size_t size = code1.gen(tbl[i].pre, tbl[i].large, tbl[i].type);
|
||||
CYBOZU_TEST_EQUAL(size, tbl[i].expect1);
|
||||
} else {
|
||||
CYBOZU_TEST_EXCEPTION(code1.gen(tbl[i].pre, tbl[i].large, tbl[i].type), std::exception);
|
||||
}
|
||||
if (tbl[i].expect2) {
|
||||
size_t size = code2.gen(tbl[i].pre, tbl[i].large, tbl[i].type);
|
||||
CYBOZU_TEST_EQUAL(size, tbl[i].expect2);
|
||||
} else {
|
||||
CYBOZU_TEST_EXCEPTION(code2.gen(tbl[i].pre, tbl[i].large, tbl[i].type), std::exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,7 +115,7 @@ namespace Xbyak {
|
|||
|
||||
enum {
|
||||
DEFAULT_MAX_CODE_SIZE = 4096,
|
||||
VERSION = 0x5860 /* 0xABCD = A.BC(D) */
|
||||
VERSION = 0x5870 /* 0xABCD = A.BC(D) */
|
||||
};
|
||||
|
||||
#ifndef MIE_INTEGER_TYPE_DEFINED
|
||||
|
@ -1775,6 +1775,7 @@ private:
|
|||
db(longCode); dd(disp - longJmpSize);
|
||||
}
|
||||
}
|
||||
bool isNEAR(LabelType type) const { return type == T_NEAR || (type == T_AUTO && isDefaultJmpNEAR_); }
|
||||
template<class T>
|
||||
void opJmp(T& label, LabelType type, uint8 shortCode, uint8 longCode, uint8 longPref)
|
||||
{
|
||||
|
@ -1784,7 +1785,7 @@ private:
|
|||
makeJmp(inner::VerifyInInt32(offset - size_), type, shortCode, longCode, longPref);
|
||||
} else {
|
||||
int jmpSize = 0;
|
||||
if (type == T_NEAR) {
|
||||
if (isNEAR(type)) {
|
||||
jmpSize = 4;
|
||||
if (longPref) db(longPref);
|
||||
db(longCode); dd(0);
|
||||
|
@ -1799,7 +1800,7 @@ private:
|
|||
void opJmpAbs(const void *addr, LabelType type, uint8 shortCode, uint8 longCode, uint8 longPref = 0)
|
||||
{
|
||||
if (isAutoGrow()) {
|
||||
if (type != T_NEAR) throw Error(ERR_ONLY_T_NEAR_IS_SUPPORTED_IN_AUTO_GROW);
|
||||
if (!isNEAR(type)) throw Error(ERR_ONLY_T_NEAR_IS_SUPPORTED_IN_AUTO_GROW);
|
||||
if (size_ + 16 >= maxSize_) growMemory();
|
||||
if (longPref) db(longPref);
|
||||
db(longCode);
|
||||
|
@ -2293,6 +2294,9 @@ public:
|
|||
#ifndef XBYAK_DISABLE_SEGMENT
|
||||
const Segment es, cs, ss, ds, fs, gs;
|
||||
#endif
|
||||
private:
|
||||
bool isDefaultJmpNEAR_;
|
||||
public:
|
||||
void L(const std::string& label) { labelMgr_.defineSlabel(label); }
|
||||
void L(Label& label) { labelMgr_.defineClabel(label); }
|
||||
Label L() { Label label; L(label); return label; }
|
||||
|
@ -2312,6 +2316,8 @@ public:
|
|||
void putL(std::string label) { putL_inner(label); }
|
||||
void putL(const Label& label) { putL_inner(label); }
|
||||
|
||||
// set default type of `jmp` of undefined label to T_NEAR
|
||||
void setDefaultJmpNEAR(bool near) { isDefaultJmpNEAR_ = near; }
|
||||
void jmp(const Operand& op) { opR_ModM(op, BIT, 4, 0xFF, NONE, NONE, true); }
|
||||
void jmp(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0xEB, 0xE9, 0); }
|
||||
void jmp(const char *label, LabelType type = T_AUTO) { jmp(std::string(label), type); }
|
||||
|
@ -2570,6 +2576,7 @@ public:
|
|||
#ifndef XBYAK_DISABLE_SEGMENT
|
||||
, es(Segment::es), cs(Segment::cs), ss(Segment::ss), ds(Segment::ds), fs(Segment::fs), gs(Segment::gs)
|
||||
#endif
|
||||
, isDefaultJmpNEAR_(false)
|
||||
{
|
||||
labelMgr_.set(this);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const char *getVersionString() const { return "5.86"; }
|
||||
const char *getVersionString() const { return "5.87"; }
|
||||
void adc(const Operand& op, uint32 imm) { opRM_I(op, imm, 0x10, 2); }
|
||||
void adc(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x10); }
|
||||
void adcx(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0x66, isREG32_REG32orMEM, NONE, 0x38); }
|
||||
|
|
Loading…
Reference in a new issue