diff options
-rw-r--r-- | readme.md | 20 | ||||
-rw-r--r-- | test/jmp.cpp | 15 | ||||
-rw-r--r-- | test/make_nm.cpp | 12 | ||||
-rw-r--r-- | xbyak/xbyak.h | 14 |
4 files changed, 59 insertions, 2 deletions
@@ -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); } |