aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--readme.md20
-rw-r--r--test/jmp.cpp15
-rw-r--r--test/make_nm.cpp12
-rw-r--r--xbyak/xbyak.h14
4 files changed, 59 insertions, 2 deletions
diff --git a/readme.md b/readme.md
index 6c9dbc4..8a7f0a3 100644
--- a/readme.md
+++ b/readme.md
@@ -1,6 +1,6 @@
[![Build Status](https://github.com/herumi/xbyak/actions/workflows/main.yml/badge.svg)](https://github.com/herumi/xbyak/actions/workflows/main.yml)
-# Xbyak 6.00 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++
+# Xbyak 6.01 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++
## Abstract
@@ -19,6 +19,7 @@ Use `and_()`, `or_()`, ... instead of `and()`, `or()`.
If you want to use them, then specify `-fno-operator-names` option to gcc/clang.
### News
+- add `jmp(mem)`, `call(mem)` `retf` for far absolute indirect jump.
- vnni instructions such as vpdpbusd supports vex encoding.
- (break backward compatibility) `push(byte, imm)` (resp. `push(word, imm)`) forces to cast `imm` to 8(resp. 16) bit.
- (Windows) `#include <winsock2.h>` has been removed from xbyak.h, so add it explicitly if you need it.
@@ -330,6 +331,23 @@ int x;
mov(eax, ptr[rip + &x]); // throw exception if the difference between &x and current position is larger than 2GiB
```
+## Far jump
+
+Use `word|dword|qword` instead of `ptr` to specify the address size.
+
+### 32 bit mode
+```
+jmp(word[eax], T_FAR); // jmp m16:16(FF /5)
+jmp(dword[eax], T_FAR); // jmp m16:32(FF /5)
+```
+
+### 64 bit mode
+```
+jmp(word[eax], T_FAR); // jmp m16:16(FF /5)
+jmp(dword[rax], T_FAR); // jmp m16:32(FF /5)
+jmp(qword[rax], T_FAR); // jmp m16:64(REX.W FF /5)
+```
+
## Code size
The default max code size is 4096 bytes.
Specify the size in constructor of `CodeGenerator()` if necessary.
diff --git a/test/jmp.cpp b/test/jmp.cpp
index e9192b2..a9076c3 100644
--- a/test/jmp.cpp
+++ b/test/jmp.cpp
@@ -1383,3 +1383,18 @@ CYBOZU_TEST_AUTO(setDefaultJmpNEAR)
}
}
}
+
+CYBOZU_TEST_AUTO(farJmp)
+{
+ struct Code : Xbyak::CodeGenerator {
+ Code()
+ {
+#ifdef XBYAK32
+ jmp(ptr[eax], T_FAR);
+#else
+ jmp(ptr[rax], T_FAR);
+#endif
+ }
+ };
+ CYBOZU_TEST_EXCEPTION(Code code, std::exception);
+}
diff --git a/test/make_nm.cpp b/test/make_nm.cpp
index b797df5..f0503e6 100644
--- a/test/make_nm.cpp
+++ b/test/make_nm.cpp
@@ -701,6 +701,17 @@ class Test {
#endif
#endif
}
+ void putFarJmp() const
+ {
+#ifdef XBYAK64
+ put("jmp", "word[rax],T_FAR", "far word [rax]");
+ put("jmp", "dword[rax],T_FAR", "far dword [rax]");
+ put("jmp", "qword[rax],T_FAR", "far qword [rax]");
+#else
+ put("jmp", "dword[eax],T_FAR", "far dword [eax]");
+ put("jmp", "word[eax],T_FAR", "far word [eax]");
+#endif
+ }
void putMMX1() const
{
// emms etc
@@ -2530,6 +2541,7 @@ public:
#else // USE_AVX
putJmp();
+ putFarJmp();
#ifdef USE_YASM
diff --git a/xbyak/xbyak.h b/xbyak/xbyak.h
index 41b5cc0..03be278 100644
--- a/xbyak/xbyak.h
+++ b/xbyak/xbyak.h
@@ -1574,6 +1574,7 @@ public:
enum LabelType {
T_SHORT,
T_NEAR,
+ T_FAR, // far jump
T_AUTO // T_SHORT if possible
};
private:
@@ -1887,6 +1888,7 @@ private:
template<class T>
void opJmp(T& label, LabelType type, uint8_t shortCode, uint8_t longCode, uint8_t longPref)
{
+ if (type == T_FAR) XBYAK_THROW(ERR_NOT_SUPPORTED)
if (isAutoGrow() && size_ + 16 >= maxSize_) growMemory(); /* avoid splitting code of jmp */
size_t offset = 0;
if (labelMgr_.getOffset(&offset, label)) { /* label exists */
@@ -1907,6 +1909,7 @@ private:
}
void opJmpAbs(const void *addr, LabelType type, uint8_t shortCode, uint8_t longCode, uint8_t longPref = 0)
{
+ if (type == T_FAR) XBYAK_THROW(ERR_NOT_SUPPORTED)
if (isAutoGrow()) {
if (!isNEAR(type)) XBYAK_THROW(ERR_ONLY_T_NEAR_IS_SUPPORTED_IN_AUTO_GROW)
if (size_ + 16 >= maxSize_) growMemory();
@@ -2474,7 +2477,16 @@ public:
// set default type of `jmp` of undefined label to T_NEAR
void setDefaultJmpNEAR(bool isNear) { isDefaultJmpNEAR_ = isNear; }
- void jmp(const Operand& op) { opR_ModM(op, BIT, 4, 0xFF, NONE, NONE, true); }
+ void jmp(const Operand& op, LabelType type = T_AUTO)
+ {
+ if (type == T_FAR) {
+ const int bit = (BIT == 32) ? (16|32) : (16|32|64);
+ if (!op.isMEM(bit)) XBYAK_THROW(ERR_NOT_SUPPORTED)
+ opR_ModM(op, BIT, 5, 0xFF, NONE, NONE, false);
+ } else {
+ 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); }
void jmp(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0xEB, 0xE9, 0); }