mirror of
https://github.com/herumi/xbyak
synced 2024-11-20 16:06:14 -07:00
support call(mem, T_FAR)
This commit is contained in:
parent
fb158f9014
commit
1abfc3465f
4 changed files with 28 additions and 19 deletions
|
@ -347,6 +347,7 @@ jmp(word[eax], T_FAR); // jmp m16:16(FF /5)
|
||||||
jmp(dword[rax], T_FAR); // jmp m16:32(FF /5)
|
jmp(dword[rax], T_FAR); // jmp m16:32(FF /5)
|
||||||
jmp(qword[rax], T_FAR); // jmp m16:64(REX.W FF /5)
|
jmp(qword[rax], T_FAR); // jmp m16:64(REX.W FF /5)
|
||||||
```
|
```
|
||||||
|
The same applies to `call`.
|
||||||
|
|
||||||
## Code size
|
## Code size
|
||||||
The default max code size is 4096 bytes.
|
The default max code size is 4096 bytes.
|
||||||
|
|
16
test/jmp.cpp
16
test/jmp.cpp
|
@ -1384,17 +1384,17 @@ CYBOZU_TEST_AUTO(setDefaultJmpNEAR)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CYBOZU_TEST_AUTO(farJmp)
|
CYBOZU_TEST_AUTO(ambiguousFarJmp)
|
||||||
{
|
{
|
||||||
struct Code : Xbyak::CodeGenerator {
|
struct Code : Xbyak::CodeGenerator {
|
||||||
Code()
|
|
||||||
{
|
|
||||||
#ifdef XBYAK32
|
#ifdef XBYAK32
|
||||||
jmp(ptr[eax], T_FAR);
|
void genJmp() { jmp(ptr[eax], T_FAR); }
|
||||||
|
void genCall() { call(ptr[eax], T_FAR); }
|
||||||
#else
|
#else
|
||||||
jmp(ptr[rax], T_FAR);
|
void genJmp() { jmp(ptr[rax], T_FAR); }
|
||||||
|
void genCall() { call(ptr[rax], T_FAR); }
|
||||||
#endif
|
#endif
|
||||||
}
|
} code;
|
||||||
};
|
CYBOZU_TEST_EXCEPTION(code.genJmp(), std::exception);
|
||||||
CYBOZU_TEST_EXCEPTION(Code code, std::exception);
|
CYBOZU_TEST_EXCEPTION(code.genCall(), std::exception);
|
||||||
}
|
}
|
||||||
|
|
|
@ -707,9 +707,16 @@ class Test {
|
||||||
put("jmp", "word[rax],T_FAR", "far word [rax]");
|
put("jmp", "word[rax],T_FAR", "far word [rax]");
|
||||||
put("jmp", "dword[rax],T_FAR", "far dword [rax]");
|
put("jmp", "dword[rax],T_FAR", "far dword [rax]");
|
||||||
put("jmp", "qword[rax],T_FAR", "far qword [rax]");
|
put("jmp", "qword[rax],T_FAR", "far qword [rax]");
|
||||||
|
|
||||||
|
put("call", "word[rax],T_FAR", "far word [rax]");
|
||||||
|
put("call", "dword[rax],T_FAR", "far dword [rax]");
|
||||||
|
put("call", "qword[rax],T_FAR", "far qword [rax]");
|
||||||
#else
|
#else
|
||||||
put("jmp", "dword[eax],T_FAR", "far dword [eax]");
|
put("jmp", "dword[eax],T_FAR", "far dword [eax]");
|
||||||
put("jmp", "word[eax],T_FAR", "far word [eax]");
|
put("jmp", "word[eax],T_FAR", "far word [eax]");
|
||||||
|
|
||||||
|
put("call", "dword[eax],T_FAR", "far dword [eax]");
|
||||||
|
put("call", "word[eax],T_FAR", "far word [eax]");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
void putMMX1() const
|
void putMMX1() const
|
||||||
|
|
|
@ -1922,6 +1922,16 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
void opJmpOp(const Operand& op, LabelType type, int ext)
|
||||||
|
{
|
||||||
|
const int bit = 16|i32e;
|
||||||
|
if (type == T_FAR) {
|
||||||
|
if (!op.isMEM(bit)) XBYAK_THROW(ERR_NOT_SUPPORTED)
|
||||||
|
opR_ModM(op, bit, ext + 1, 0xFF, NONE, NONE, false);
|
||||||
|
} else {
|
||||||
|
opR_ModM(op, bit, ext, 0xFF, NONE, NONE, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
// reg is reg field of ModRM
|
// reg is reg field of ModRM
|
||||||
// immSize is the size for immediate value
|
// immSize is the size for immediate value
|
||||||
// disp8N = 0(normal), disp8N = 1(force disp32), disp8N = {2, 4, 8} ; compressed displacement
|
// disp8N = 0(normal), disp8N = 1(force disp32), disp8N = {2, 4, 8} ; compressed displacement
|
||||||
|
@ -2477,22 +2487,13 @@ public:
|
||||||
|
|
||||||
// set default type of `jmp` of undefined label to T_NEAR
|
// set default type of `jmp` of undefined label to T_NEAR
|
||||||
void setDefaultJmpNEAR(bool isNear) { isDefaultJmpNEAR_ = isNear; }
|
void setDefaultJmpNEAR(bool isNear) { isDefaultJmpNEAR_ = isNear; }
|
||||||
void jmp(const Operand& op, LabelType type = T_AUTO)
|
void jmp(const Operand& op, LabelType type = T_AUTO) { opJmpOp(op, type, 4); }
|
||||||
{
|
|
||||||
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(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 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); }
|
void jmp(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0xEB, 0xE9, 0); }
|
||||||
void jmp(const void *addr, LabelType type = T_AUTO) { opJmpAbs(addr, type, 0xEB, 0xE9); }
|
void jmp(const void *addr, LabelType type = T_AUTO) { opJmpAbs(addr, type, 0xEB, 0xE9); }
|
||||||
|
|
||||||
void call(const Operand& op) { opR_ModM(op, 16 | i32e, 2, 0xFF, NONE, NONE, true); }
|
void call(const Operand& op, LabelType type = T_AUTO) { opJmpOp(op, type, 2); }
|
||||||
// call(string label), not const std::string&
|
// call(string label), not const std::string&
|
||||||
void call(std::string label) { opJmp(label, T_NEAR, 0, 0xE8, 0); }
|
void call(std::string label) { opJmp(label, T_NEAR, 0, 0xE8, 0); }
|
||||||
void call(const char *label) { call(std::string(label)); }
|
void call(const char *label) { call(std::string(label)); }
|
||||||
|
|
Loading…
Reference in a new issue