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(qword[rax], T_FAR); // jmp m16:64(REX.W FF /5)
|
||||
```
|
||||
The same applies to `call`.
|
||||
|
||||
## Code size
|
||||
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 {
|
||||
Code()
|
||||
{
|
||||
#ifdef XBYAK32
|
||||
jmp(ptr[eax], T_FAR);
|
||||
void genJmp() { jmp(ptr[eax], T_FAR); }
|
||||
void genCall() { call(ptr[eax], T_FAR); }
|
||||
#else
|
||||
jmp(ptr[rax], T_FAR);
|
||||
void genJmp() { jmp(ptr[rax], T_FAR); }
|
||||
void genCall() { call(ptr[rax], T_FAR); }
|
||||
#endif
|
||||
}
|
||||
};
|
||||
CYBOZU_TEST_EXCEPTION(Code code, std::exception);
|
||||
} code;
|
||||
CYBOZU_TEST_EXCEPTION(code.genJmp(), 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", "dword[rax],T_FAR", "far dword [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
|
||||
put("jmp", "dword[eax],T_FAR", "far dword [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
|
||||
}
|
||||
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
|
||||
// immSize is the size for immediate value
|
||||
// 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
|
||||
void setDefaultJmpNEAR(bool isNear) { isDefaultJmpNEAR_ = isNear; }
|
||||
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(const Operand& op, LabelType type = T_AUTO) { opJmpOp(op, type, 4); }
|
||||
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); }
|
||||
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&
|
||||
void call(std::string label) { opJmp(label, T_NEAR, 0, 0xE8, 0); }
|
||||
void call(const char *label) { call(std::string(label)); }
|
||||
|
|
Loading…
Reference in a new issue