mirror of
https://github.com/herumi/xbyak
synced 2024-11-20 16:06:14 -07:00
Xbyak ver 3.50
This commit is contained in:
parent
f4f84a65aa
commit
683f7448ae
9 changed files with 717 additions and 215 deletions
|
@ -421,7 +421,7 @@ void put()
|
||||||
for (int i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
for (int i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
||||||
const Tbl *p = &tbl[i];
|
const Tbl *p = &tbl[i];
|
||||||
printf("void cmov%s(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | %d); }\n", p->name, p->ext);
|
printf("void cmov%s(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | %d); }\n", p->name, p->ext);
|
||||||
printf("void j%s(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x%02X, 0x%02X, 0x%02X); }\n", p->name, p->ext | B01110000, p->ext | B10000000, 0x0F);
|
printf("void j%s(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x%02X, 0x%02X, 0x%02X); }\n", p->name, p->ext | B01110000, p->ext | B10000000, 0x0F);
|
||||||
printf("void set%s(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | %d); }\n", p->name, p->ext);
|
printf("void set%s(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | %d); }\n", p->name, p->ext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
27
readme.md
27
readme.md
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
Xbyak 3.05 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++
|
Xbyak 3.50 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++
|
||||||
=============
|
=============
|
||||||
|
|
||||||
Abstract
|
Abstract
|
||||||
|
@ -46,6 +46,26 @@ Linux:
|
||||||
|
|
||||||
These files are copied into /usr/local/include/xbyak
|
These files are copied into /usr/local/include/xbyak
|
||||||
|
|
||||||
|
New Feature
|
||||||
|
-------------
|
||||||
|
|
||||||
|
AutoGrow mode is a mode that Xbyak grows memory automatically if necessary.
|
||||||
|
Call ready() before calling getCode() to calc address of jmp.
|
||||||
|
|
||||||
|
struct Code : Xbyak::CodeGenerator {
|
||||||
|
Code()
|
||||||
|
: Xbyak::CodeGenerator(<default memory size>, Xbyak::AutoGrow)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Code c;
|
||||||
|
c.ready(); // Don't forget to call this function
|
||||||
|
|
||||||
|
>Don't use the address returned by getCurr() before calling ready().
|
||||||
|
>It may be invalid address.
|
||||||
|
>RESTRICTION : rip addressing is not supported in AutoGrow
|
||||||
|
|
||||||
Syntax
|
Syntax
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
@ -202,6 +222,7 @@ http://opensource.org/licenses/BSD-3-Clause
|
||||||
History
|
History
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
* 2012/Mar/19 ver 3.50 support AutoGrow mode
|
||||||
* 2011/Nov/09 ver 3.05 fix bit property of rip addresing / support movsxd
|
* 2011/Nov/09 ver 3.05 fix bit property of rip addresing / support movsxd
|
||||||
* 2011/Aug/15 ver 3.04 fix dealing with imm8 such as add(dword [ebp-8], 0xda); (thanks to lolcat)
|
* 2011/Aug/15 ver 3.04 fix dealing with imm8 such as add(dword [ebp-8], 0xda); (thanks to lolcat)
|
||||||
* 2011/Jun/16 ver 3.03 fix __GNUC_PREREQ macro for Mac gcc(thanks to t_teruya)
|
* 2011/Jun/16 ver 3.03 fix __GNUC_PREREQ macro for Mac gcc(thanks to t_teruya)
|
||||||
|
@ -252,5 +273,5 @@ Author
|
||||||
MITSUNARI Shigeo(herumi at nifty dot com)
|
MITSUNARI Shigeo(herumi at nifty dot com)
|
||||||
|
|
||||||
---
|
---
|
||||||
$Revision: 1.16 $
|
$Revision: 1.17 $
|
||||||
$Date: 2011/12/22 01:43:13 $
|
$Date: 2012/03/19 14:28:46 $
|
||||||
|
|
31
readme.txt
31
readme.txt
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak version 3.05
|
C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak version 3.50
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
◎概要
|
◎概要
|
||||||
|
@ -34,6 +34,34 @@ xbyak_mnemonic.h
|
||||||
これらを同一のパスに入れてインクルードパスに追加してください.
|
これらを同一のパスに入れてインクルードパスに追加してください.
|
||||||
|
|
||||||
Linuxではmake installで/usr/local/include/xbyakにコピーされます.
|
Linuxではmake installで/usr/local/include/xbyakにコピーされます.
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
◎新機能
|
||||||
|
|
||||||
|
AutoGrowモード追加
|
||||||
|
これはメモリ伸長を動的に行うモードです.
|
||||||
|
今まではXbyak::CodeGenerator()に渡したメモリサイズを超えると例外が発生して
|
||||||
|
いましたが,このモードでは内部でメモリを再確保して伸長します.
|
||||||
|
ただし,getCode()を呼び出す前にジャンプ命令のアドレス解決をするためにready()
|
||||||
|
関数を呼ぶ必要があります.
|
||||||
|
|
||||||
|
次のように使います.
|
||||||
|
|
||||||
|
struct Code : Xbyak::CodeGenerator {
|
||||||
|
Code()
|
||||||
|
: Xbyak::CodeGenerator(<default memory size>, Xbyak::AutoGrow)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Code c;
|
||||||
|
c.ready(); // この呼び出しを忘れてはいけない
|
||||||
|
|
||||||
|
注意1. ready()を呼んで確定するまではgetCurr()で得たポインタは無効化されている
|
||||||
|
可能性があります.getSize()でoffsetを保持しておきready()のあとにgetCode()を
|
||||||
|
呼び出してからgetCode() + offsetで新しいポインタを取得してください.
|
||||||
|
|
||||||
|
注意2. AutoGrowモードでは64bitモードの相対アドレッシング[rip]は非サポートです.
|
||||||
|
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
◎文法
|
◎文法
|
||||||
|
|
||||||
|
@ -214,6 +242,7 @@ sample/{echo,hello}.bfは http://www.kmonos.net/alang/etc/brainfuck.php から
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
◎履歴
|
◎履歴
|
||||||
|
|
||||||
|
2012/03/19 ver 3.50 AutoGrowモードサポート
|
||||||
2011/11/09 ver 3.05 rip相対の64bitサイズ以外の扱いのバグ修正 / movsxdサポート
|
2011/11/09 ver 3.05 rip相対の64bitサイズ以外の扱いのバグ修正 / movsxdサポート
|
||||||
2011/08/15 ver 3.04 add(dword [ebp-8], 0xda);などにおけるimm8の扱いのバグ修正(thanks to lolcat)
|
2011/08/15 ver 3.04 add(dword [ebp-8], 0xda);などにおけるimm8の扱いのバグ修正(thanks to lolcat)
|
||||||
2011/06/16 ver 3.03 Macのgcc上での__GNUC_PREREQがミスってたのを修正(thanks to t_teruya)
|
2011/06/16 ver 3.03 Macのgcc上での__GNUC_PREREQがミスってたのを修正(thanks to t_teruya)
|
||||||
|
|
|
@ -2,11 +2,8 @@ TARGET = make_nm normalize_prefix
|
||||||
XBYAK_INC=../xbyak/xbyak.h
|
XBYAK_INC=../xbyak/xbyak.h
|
||||||
|
|
||||||
ifeq ($(MODE_BIT),64)
|
ifeq ($(MODE_BIT),64)
|
||||||
XBYAK_OPT=-m64
|
RARGET += jmp64
|
||||||
XBYAK_COPT=-DXBYAK64
|
|
||||||
else
|
else
|
||||||
XBYAK_OPT=-m32
|
|
||||||
XBYAK_COPT=-DXBYAK32
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
@ -16,12 +13,16 @@ CFLAGS_WARN=-Wall -Wextra -Wformat=2 -Wcast-qual -Wcast-align -Wwrite-strings -W
|
||||||
CFLAGS=-O2 -fomit-frame-pointer -Wall -fno-operator-names -I../ $(XBYAK_OPT) $(XBYAK_COPT) $(CFLAGS_WARN)
|
CFLAGS=-O2 -fomit-frame-pointer -Wall -fno-operator-names -I../ $(XBYAK_OPT) $(XBYAK_COPT) $(CFLAGS_WARN)
|
||||||
make_nm:
|
make_nm:
|
||||||
$(CXX) $(CFLAGS) make_nm.cpp -o $@
|
$(CXX) $(CFLAGS) make_nm.cpp -o $@
|
||||||
normalize_prefix: normalize_prefix.cpp
|
normalize_prefix: normalize_prefix.cpp ../xbyak/xbyak.h
|
||||||
$(CXX) $(CFLAGS) normalize_prefix.cpp -o $@
|
$(CXX) $(CFLAGS) normalize_prefix.cpp -o $@
|
||||||
test_mmx: test_mmx.cpp
|
test_mmx: test_mmx.cpp ../xbyak/xbyak.h
|
||||||
$(CXX) $(CFLAGS) test_mmx.cpp -o $@ -lpthread
|
$(CXX) $(CFLAGS) test_mmx.cpp -o $@ -lpthread
|
||||||
jmp: jmp.cpp
|
jmp: jmp.cpp ../xbyak/xbyak.h
|
||||||
|
$(CXX) $(CFLAGS) jmp.cpp -o $@ -m32
|
||||||
|
jmp64: jmp.cpp ../xbyak/xbyak.h
|
||||||
$(CXX) $(CFLAGS) jmp.cpp -o $@
|
$(CXX) $(CFLAGS) jmp.cpp -o $@
|
||||||
|
grow: grow.cpp ../xbyak/xbyak.h
|
||||||
|
$(CXX) $(CFLAGS) grow.cpp -o $@
|
||||||
|
|
||||||
test: normalize_prefix jmp
|
test: normalize_prefix jmp
|
||||||
./test_nm.sh
|
./test_nm.sh
|
||||||
|
|
293
test/jmp.cpp
293
test/jmp.cpp
|
@ -1,11 +1,16 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "xbyak/xbyak.h"
|
#include <string>
|
||||||
|
#include <xbyak/xbyak.h>
|
||||||
#define NUM_OF_ARRAY(x) (sizeof(x) / sizeof(x[0]))
|
#define NUM_OF_ARRAY(x) (sizeof(x) / sizeof(x[0]))
|
||||||
|
|
||||||
|
#if !defined(_WIN64) && !defined(__x86_64__)
|
||||||
|
#define ONLY_32BIT
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace Xbyak;
|
using namespace Xbyak;
|
||||||
|
|
||||||
struct TestJmp : public CodeGenerator {
|
struct TestJmp : public Xbyak::CodeGenerator {
|
||||||
void putNop(int n)
|
void putNop(int n)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
|
@ -45,24 +50,19 @@ struct TestJmp : public CodeGenerator {
|
||||||
*/
|
*/
|
||||||
TestJmp(int offset, bool isBack, bool isShort)
|
TestJmp(int offset, bool isBack, bool isShort)
|
||||||
{
|
{
|
||||||
char buf[32];
|
|
||||||
static int count = 0;
|
|
||||||
if (isBack) {
|
if (isBack) {
|
||||||
sprintf(buf, "L(\"X%d\");\n", count);
|
L("@@");
|
||||||
L(buf);
|
|
||||||
putNop(offset);
|
putNop(offset);
|
||||||
jmp(buf);
|
jmp("@b");
|
||||||
} else {
|
} else {
|
||||||
sprintf(buf, "L(\"Y%d\");\n", count);
|
|
||||||
if (isShort) {
|
if (isShort) {
|
||||||
jmp(buf);
|
jmp("@f");
|
||||||
} else {
|
} else {
|
||||||
jmp(buf, T_NEAR);
|
jmp("@f", T_NEAR);
|
||||||
}
|
}
|
||||||
putNop(offset);
|
putNop(offset);
|
||||||
L(buf);
|
L("@@");
|
||||||
}
|
}
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -72,34 +72,125 @@ void test1()
|
||||||
int offset;
|
int offset;
|
||||||
bool isBack;
|
bool isBack;
|
||||||
bool isShort;
|
bool isShort;
|
||||||
const char *result;
|
uint8 result[6];
|
||||||
|
int size;
|
||||||
} tbl[] = {
|
} tbl[] = {
|
||||||
{ 0, true, true, "EBFE" },
|
{ 0, true, true, { 0xeb, 0xfe }, 2 },
|
||||||
{ 1, true, true, "EBFD" },
|
{ 1, true, true, { 0xeb, 0xfd }, 2 },
|
||||||
{ 126, true, true, "EB80" },
|
{ 126, true, true, { 0xeb, 0x80 }, 2 },
|
||||||
{ 127, true, false, "E97CFFFFFF" },
|
{ 127, true, false, {0xe9, 0x7c, 0xff, 0xff, 0xff }, 5 },
|
||||||
{ 0, false, true, "EB00" },
|
{ 0, false, true, { 0xeb, 0x00 }, 2 },
|
||||||
{ 1, false, true, "EB01" },
|
{ 1, false, true, { 0xeb, 0x01 }, 2 },
|
||||||
{ 127, false, true, "EB7F" },
|
{ 127, false, true, { 0xeb, 0x7f }, 2 },
|
||||||
{ 128, false, false, "E980000000" },
|
{ 128, false, false, { 0xe9, 0x80, 0x00, 0x00, 0x00 }, 5 },
|
||||||
};
|
};
|
||||||
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
|
||||||
const Tbl *p = &tbl[i];
|
const Tbl *p = &tbl[i];
|
||||||
TestJmp jmp(p->offset, p->isBack, p->isShort);
|
TestJmp jmp(p->offset, p->isBack, p->isShort);
|
||||||
const uint8 *q = (const uint8*)jmp.getCode();
|
const uint8 *q = (const uint8*)jmp.getCode();
|
||||||
char buf[32];
|
|
||||||
if (p->isBack) q += p->offset; /* skip nop */
|
if (p->isBack) q += p->offset; /* skip nop */
|
||||||
for (size_t j = 0; j < jmp.getSize() - p->offset; j++) {
|
for (int j = 0; j < p->size; j++) {
|
||||||
sprintf(&buf[j * 2], "%02X", q[j]);
|
if (q[j] != p->result[j]) {
|
||||||
|
printf("err (%d,%d) %02x assume=%02x\n", (int)i, j, q[j], p->result[j]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (strcmp(buf, p->result) != 0) {
|
}
|
||||||
printf("error %d assume:%s, err=%s\n", i, p->result, buf);
|
puts("ok");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestJmp2 : public CodeGenerator {
|
||||||
|
void putNop(int n)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
nop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
1 00000000 90 nop
|
||||||
|
2 00000001 90 nop
|
||||||
|
3 f1:
|
||||||
|
4 00000002 <res 0000007E> dummyX1 resb 126
|
||||||
|
6 00000080 EB80 jmp f1
|
||||||
|
7
|
||||||
|
8 f2:
|
||||||
|
9 00000082 <res 0000007F> dummyX2 resb 127
|
||||||
|
11 00000101 E97CFFFFFF jmp f2
|
||||||
|
12
|
||||||
|
13
|
||||||
|
14 00000106 EB7F jmp f3
|
||||||
|
15 00000108 <res 0000007F> dummyX3 resb 127
|
||||||
|
17 f3:
|
||||||
|
18
|
||||||
|
19 00000187 E980000000 jmp f4
|
||||||
|
20 0000018C <res 00000080> dummyX4 resb 128
|
||||||
|
22 f4:
|
||||||
|
*/
|
||||||
|
explicit TestJmp2(void *p)
|
||||||
|
: Xbyak::CodeGenerator(8192, p)
|
||||||
|
{
|
||||||
|
inLocalLabel();
|
||||||
|
nop();
|
||||||
|
nop();
|
||||||
|
L(".f1");
|
||||||
|
putNop(126);
|
||||||
|
jmp(".f1");
|
||||||
|
L(".f2");
|
||||||
|
putNop(127);
|
||||||
|
jmp(".f2", T_NEAR);
|
||||||
|
|
||||||
|
jmp(".f3");
|
||||||
|
putNop(127);
|
||||||
|
L(".f3");
|
||||||
|
jmp(".f4", T_NEAR);
|
||||||
|
putNop(128);
|
||||||
|
L(".f4");
|
||||||
|
outLocalLabel();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void test2()
|
||||||
|
{
|
||||||
|
puts("test2");
|
||||||
|
std::string ok;
|
||||||
|
ok.resize(0x18C + 128, (char)0x90);
|
||||||
|
ok[0x080] = (char)0xeb;
|
||||||
|
ok[0x081] = (char)0x80;
|
||||||
|
|
||||||
|
ok[0x101] = (char)0xe9;
|
||||||
|
ok[0x102] = (char)0x7c;
|
||||||
|
ok[0x103] = (char)0xff;
|
||||||
|
ok[0x104] = (char)0xff;
|
||||||
|
ok[0x105] = (char)0xff;
|
||||||
|
|
||||||
|
ok[0x106] = (char)0xeb;
|
||||||
|
ok[0x107] = (char)0x7f;
|
||||||
|
|
||||||
|
ok[0x187] = (char)0xe9;
|
||||||
|
ok[0x188] = (char)0x80;
|
||||||
|
ok[0x189] = (char)0x00;
|
||||||
|
ok[0x18a] = (char)0x00;
|
||||||
|
ok[0x18b] = (char)0x00;
|
||||||
|
for (int j = 0; j < 2; j++) {
|
||||||
|
TestJmp2 c(j == 0 ? 0 : Xbyak::AutoGrow);
|
||||||
|
c.ready();
|
||||||
|
std::string m((const char*)c.getCode(), c.getSize());
|
||||||
|
if (m.size() != ok.size()) {
|
||||||
|
printf("test2 err %d %d\n", (int)m.size(), (int)ok.size());
|
||||||
} else {
|
} else {
|
||||||
printf("ok %d\n", i);
|
if (m != ok) {
|
||||||
|
for (size_t i = 0; i < m.size(); i++) {
|
||||||
|
if (m[i] != ok[i]) {
|
||||||
|
printf("diff 0x%03x %02x %02x\n", (int)i, (unsigned char)m[i], (unsigned char)ok[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
puts("ok");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ONLY_32BIT
|
||||||
int add5(int x) { return x + 5; }
|
int add5(int x) { return x + 5; }
|
||||||
int add2(int x) { return x + 2; }
|
int add2(int x) { return x + 2; }
|
||||||
|
|
||||||
|
@ -121,7 +212,7 @@ struct Grow : Xbyak::CodeGenerator {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void test2()
|
void test3()
|
||||||
{
|
{
|
||||||
for (int dummySize = 0; dummySize < 40000; dummySize += 10000) {
|
for (int dummySize = 0; dummySize < 40000; dummySize += 10000) {
|
||||||
printf("dummySize=%d\n", dummySize);
|
printf("dummySize=%d\n", dummySize);
|
||||||
|
@ -137,12 +228,158 @@ void test2()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Xbyak::uint8 bufL[4096 * 32];
|
||||||
|
Xbyak::uint8 bufS[4096 * 2];
|
||||||
|
|
||||||
|
struct MyAllocator : Xbyak::Allocator {
|
||||||
|
Xbyak::uint8 *alloc(size_t size)
|
||||||
|
{
|
||||||
|
if (size < sizeof(bufS)) {
|
||||||
|
printf("use bufS(%d)\n", (int)size);
|
||||||
|
return bufS;
|
||||||
|
}
|
||||||
|
if (size < sizeof(bufL)) {
|
||||||
|
printf("use bufL(%d)\n", (int)size);
|
||||||
|
return bufL;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "no memory %d\n", (int)size);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
void free(Xbyak::uint8 *)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
} myAlloc;
|
||||||
|
|
||||||
|
void dump(const std::string& m)
|
||||||
|
{
|
||||||
|
printf("size=%d\n ", (int)m.size());
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
printf("%02x ", i);
|
||||||
|
}
|
||||||
|
printf("\n ");
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
printf("---");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
for (size_t i = 0; i < m.size(); i++) {
|
||||||
|
if ((i % 16) == 0) printf("%04x ", (int)(i / 16));
|
||||||
|
printf("%02x ", (unsigned char)m[i]);
|
||||||
|
if ((i % 16) == 15) putchar('\n');
|
||||||
|
}
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
void diff(const std::string& a, const std::string& b)
|
||||||
|
{
|
||||||
|
puts("diff");
|
||||||
|
if (a.size() != b.size()) printf("size diff %d %d\n", (int)a.size(), (int)b.size());
|
||||||
|
for (size_t i = 0; i < a.size(); i++) {
|
||||||
|
if (a[i] != b[i]) {
|
||||||
|
printf("diff %d(%04x) %02x %02x\n", (int)i, (int)i, (unsigned char)a[i], (unsigned char)b[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
puts("end");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Test4 : Xbyak::CodeGenerator {
|
||||||
|
explicit Test4(int size, void *mode)
|
||||||
|
: CodeGenerator(size, mode)
|
||||||
|
{
|
||||||
|
using namespace Xbyak;
|
||||||
|
inLocalLabel();
|
||||||
|
outLocalLabel();
|
||||||
|
jmp(".x");
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
nop();
|
||||||
|
}
|
||||||
|
L(".x");
|
||||||
|
ret();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
void test4()
|
||||||
|
{
|
||||||
|
std::string fm, gm;
|
||||||
|
Test4 fc(1024, 0);
|
||||||
|
Test4 gc(5, Xbyak::AutoGrow);
|
||||||
|
gc.ready();
|
||||||
|
fm.assign((const char*)fc.getCode(), fc.getSize());
|
||||||
|
gm.assign((const char*)gc.getCode(), gc.getSize());
|
||||||
|
// dump(fm);
|
||||||
|
// dump(gm);
|
||||||
|
diff(gm, gm);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Test5 : Xbyak::CodeGenerator {
|
||||||
|
explicit Test5(int size, int count, void *mode)
|
||||||
|
: CodeGenerator(size, mode, &myAlloc)
|
||||||
|
{
|
||||||
|
using namespace Xbyak;
|
||||||
|
inLocalLabel();
|
||||||
|
mov(ecx, count);
|
||||||
|
xor(eax, eax);
|
||||||
|
L(".lp");
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
L(Label::toStr(i).c_str());
|
||||||
|
add(eax, 1);
|
||||||
|
int to = 0;
|
||||||
|
if (i < count / 2) {
|
||||||
|
to = count - 1 - i;
|
||||||
|
} else {
|
||||||
|
to = count - i;
|
||||||
|
}
|
||||||
|
if (i == count / 2) {
|
||||||
|
jmp(".exit", T_NEAR);
|
||||||
|
} else {
|
||||||
|
jmp(Label::toStr(to).c_str(), T_NEAR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
L(".exit");
|
||||||
|
sub(ecx, 1);
|
||||||
|
jnz(".lp", T_NEAR);
|
||||||
|
ret();
|
||||||
|
outLocalLabel();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void test5()
|
||||||
|
{
|
||||||
|
std::string fm, gm;
|
||||||
|
const int count = 50;
|
||||||
|
int ret;
|
||||||
|
Test5 fc(1024 * 64, count, 0);
|
||||||
|
ret = ((int (*)())fc.getCode())();
|
||||||
|
if (ret != count * count) {
|
||||||
|
printf("err ret=%d, %d\n", ret, count * count);
|
||||||
|
} else {
|
||||||
|
puts("ok");
|
||||||
|
}
|
||||||
|
fm.assign((const char*)fc.getCode(), fc.getSize());
|
||||||
|
Test5 gc(10, count, Xbyak::AutoGrow);
|
||||||
|
gc.ready();
|
||||||
|
#if 0
|
||||||
|
ret = ((int (*)())gc.getCode())();
|
||||||
|
if (ret != count * count) {
|
||||||
|
printf("err ret=%d, %d\n", ret, count * count);
|
||||||
|
} else {
|
||||||
|
puts("ok");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
gm.assign((const char*)gc.getCode(), gc.getSize());
|
||||||
|
diff(fm, gm);
|
||||||
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
test1();
|
test1();
|
||||||
test2();
|
test2();
|
||||||
|
#ifdef ONLY_32BIT
|
||||||
|
test3();
|
||||||
|
#endif
|
||||||
|
test4();
|
||||||
|
test5();
|
||||||
} catch (Xbyak::Error err) {
|
} catch (Xbyak::Error err) {
|
||||||
printf("ERR:%s(%d)\n", Xbyak::ConvertErrorToString(err), err);
|
printf("ERR:%s(%d)\n", Xbyak::ConvertErrorToString(err), err);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
|
|
20
test/jmp.sln
Normal file
20
test/jmp.sln
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
þ½Ž¿
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||||
|
# Visual C++ Express 2008
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jmp", "jmp.vcproj", "{AC0B3317-E988-44F8-954A-BCBE4B3BB2BF}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Win32 = Debug|Win32
|
||||||
|
Release|Win32 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{AC0B3317-E988-44F8-954A-BCBE4B3BB2BF}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||||
|
{AC0B3317-E988-44F8-954A-BCBE4B3BB2BF}.Debug|Win32.Build.0 = Debug|Win32
|
||||||
|
{AC0B3317-E988-44F8-954A-BCBE4B3BB2BF}.Release|Win32.ActiveCfg = Release|Win32
|
||||||
|
{AC0B3317-E988-44F8-954A-BCBE4B3BB2BF}.Release|Win32.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
195
test/jmp.vcproj
Normal file
195
test/jmp.vcproj
Normal file
|
@ -0,0 +1,195 @@
|
||||||
|
<?xml version="1.0" encoding="shift_jis"?>
|
||||||
|
<VisualStudioProject
|
||||||
|
ProjectType="Visual C++"
|
||||||
|
Version="9.00"
|
||||||
|
Name="jmp"
|
||||||
|
ProjectGUID="{AC0B3317-E988-44F8-954A-BCBE4B3BB2BF}"
|
||||||
|
RootNamespace="jmp"
|
||||||
|
Keyword="Win32Proj"
|
||||||
|
TargetFrameworkVersion="196613"
|
||||||
|
>
|
||||||
|
<Platforms>
|
||||||
|
<Platform
|
||||||
|
Name="Win32"
|
||||||
|
/>
|
||||||
|
</Platforms>
|
||||||
|
<ToolFiles>
|
||||||
|
</ToolFiles>
|
||||||
|
<Configurations>
|
||||||
|
<Configuration
|
||||||
|
Name="Debug|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="1"
|
||||||
|
CharacterSet="1"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="0"
|
||||||
|
AdditionalIncludeDirectories="$(SolutionDir)/../"
|
||||||
|
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
|
||||||
|
MinimalRebuild="true"
|
||||||
|
BasicRuntimeChecks="3"
|
||||||
|
RuntimeLibrary="3"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="3"
|
||||||
|
DebugInformationFormat="4"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
LinkIncremental="2"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
SubSystem="1"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration
|
||||||
|
Name="Release|Win32"
|
||||||
|
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||||
|
IntermediateDirectory="$(ConfigurationName)"
|
||||||
|
ConfigurationType="1"
|
||||||
|
CharacterSet="1"
|
||||||
|
WholeProgramOptimization="1"
|
||||||
|
>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreBuildEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCustomBuildTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXMLDataGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCWebServiceProxyGeneratorTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCMIDLTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCCLCompilerTool"
|
||||||
|
Optimization="2"
|
||||||
|
EnableIntrinsicFunctions="true"
|
||||||
|
AdditionalIncludeDirectories="$(SolutionDir)/../"
|
||||||
|
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
|
||||||
|
RuntimeLibrary="2"
|
||||||
|
EnableFunctionLevelLinking="true"
|
||||||
|
UsePrecompiledHeader="0"
|
||||||
|
WarningLevel="3"
|
||||||
|
DebugInformationFormat="3"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManagedResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCResourceCompilerTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPreLinkEventTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCLinkerTool"
|
||||||
|
LinkIncremental="1"
|
||||||
|
GenerateDebugInformation="true"
|
||||||
|
SubSystem="1"
|
||||||
|
OptimizeReferences="2"
|
||||||
|
EnableCOMDATFolding="2"
|
||||||
|
TargetMachine="1"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCALinkTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCManifestTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCXDCMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCBscMakeTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCFxCopTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCAppVerifierTool"
|
||||||
|
/>
|
||||||
|
<Tool
|
||||||
|
Name="VCPostBuildEventTool"
|
||||||
|
/>
|
||||||
|
</Configuration>
|
||||||
|
</Configurations>
|
||||||
|
<References>
|
||||||
|
</References>
|
||||||
|
<Files>
|
||||||
|
<Filter
|
||||||
|
Name="ソース ファイル"
|
||||||
|
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||||
|
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||||
|
>
|
||||||
|
<File
|
||||||
|
RelativePath=".\jmp.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="ヘッダー ファイル"
|
||||||
|
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||||
|
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||||
|
>
|
||||||
|
</Filter>
|
||||||
|
<Filter
|
||||||
|
Name="リソース ファイル"
|
||||||
|
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||||
|
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||||
|
>
|
||||||
|
</Filter>
|
||||||
|
</Files>
|
||||||
|
<Globals>
|
||||||
|
</Globals>
|
||||||
|
</VisualStudioProject>
|
287
xbyak/xbyak.h
287
xbyak/xbyak.h
|
@ -5,9 +5,7 @@
|
||||||
@file xbyak.h
|
@file xbyak.h
|
||||||
@brief Xbyak ; JIT assembler for x86(IA32)/x64 by C++
|
@brief Xbyak ; JIT assembler for x86(IA32)/x64 by C++
|
||||||
@author herumi
|
@author herumi
|
||||||
@version $Revision: 1.268 $
|
@url http://homepage1.nifty.com/herumi/soft/xbyak_e.html
|
||||||
@url http://homepage1.nifty.com/herumi/soft/xbyak.html
|
|
||||||
@date $Date: 2012/03/16 14:43:46 $
|
|
||||||
@note modified new BSD license
|
@note modified new BSD license
|
||||||
http://opensource.org/licenses/BSD-3-Clause
|
http://opensource.org/licenses/BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -55,7 +53,7 @@ namespace Xbyak {
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
DEFAULT_MAX_CODE_SIZE = 4096,
|
DEFAULT_MAX_CODE_SIZE = 4096,
|
||||||
VERSION = 0x3060, /* 0xABCD = A.BC(D) */
|
VERSION = 0x3500, /* 0xABCD = A.BC(D) */
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef MIE_INTEGER_TYPE_DEFINED
|
#ifndef MIE_INTEGER_TYPE_DEFINED
|
||||||
|
@ -112,7 +110,7 @@ enum Error {
|
||||||
ERR_INTERNAL
|
ERR_INTERNAL
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline const char *ConvertErrorToString(Error err)
|
inline const char *ConvertErrorToString(Error err)
|
||||||
{
|
{
|
||||||
static const char errTbl[][40] = {
|
static const char errTbl[][40] = {
|
||||||
"none",
|
"none",
|
||||||
|
@ -159,7 +157,8 @@ namespace inner {
|
||||||
|
|
||||||
enum { debug = 1 };
|
enum { debug = 1 };
|
||||||
|
|
||||||
static inline uint32 GetPtrDist(const void *p1, const void *p2)
|
#if 0
|
||||||
|
inline uint32 GetPtrDist(const void *p1, const void *p2)
|
||||||
{
|
{
|
||||||
uint64 diff = static_cast<const char *>(p1) - static_cast<const char *>(p2);
|
uint64 diff = static_cast<const char *>(p1) - static_cast<const char *>(p2);
|
||||||
#ifdef XBYAK64
|
#ifdef XBYAK64
|
||||||
|
@ -168,8 +167,26 @@ static inline uint32 GetPtrDist(const void *p1, const void *p2)
|
||||||
return static_cast<uint32>(diff);
|
return static_cast<uint32>(diff);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool IsInDisp8(uint32 x) { return 0xFFFFFF80 <= x || x <= 0x7F; }
|
inline uint32 GetOffsetDist(size_t p1, size_t p2)
|
||||||
static inline bool IsInInt32(uint64 x) { return 0xFFFFFFFF80000000ULL <= x || x <= 0x7FFFFFFFU; }
|
{
|
||||||
|
uint64 diff = p1 - p2;
|
||||||
|
#ifdef XBYAK64
|
||||||
|
if (0x7FFFFFFFULL < diff && diff < 0xFFFFFFFF80000000ULL) throw ERR_OFFSET_IS_TOO_BIG;
|
||||||
|
#endif
|
||||||
|
return static_cast<uint32>(diff);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline bool IsInDisp8(uint32 x) { return 0xFFFFFF80 <= x || x <= 0x7F; }
|
||||||
|
inline bool IsInInt32(uint64 x) { return 0xFFFFFFFF80000000ULL <= x || x <= 0x7FFFFFFFU; }
|
||||||
|
|
||||||
|
inline uint32 VerifyInInt32(uint64 x)
|
||||||
|
{
|
||||||
|
#ifdef XBYAK64
|
||||||
|
if (!IsInInt32(x)) throw ERR_OFFSET_IS_TOO_BIG;
|
||||||
|
#endif
|
||||||
|
return static_cast<uint32>(x);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,27 +431,13 @@ class CodeArray {
|
||||||
ALIGN_PAGE_SIZE = 4096,
|
ALIGN_PAGE_SIZE = 4096,
|
||||||
MAX_FIXED_BUF_SIZE = 8
|
MAX_FIXED_BUF_SIZE = 8
|
||||||
};
|
};
|
||||||
void operator=(const CodeArray&);
|
|
||||||
void resize(size_t newSize)
|
|
||||||
{
|
|
||||||
uint8 *newAllocPtr = reinterpret_cast<uint8*>(alloc_->alloc(newSize + ALIGN_PAGE_SIZE));
|
|
||||||
if (newAllocPtr == 0) throw ERR_CANT_ALLOC;
|
|
||||||
uint8 *newTop = getAlignedAddress(newAllocPtr, ALIGN_PAGE_SIZE);
|
|
||||||
for (size_t i = 0; i < size_; i++) newTop[i] = top_[i];
|
|
||||||
alloc_->free(allocPtr_);
|
|
||||||
allocPtr_ = newAllocPtr;
|
|
||||||
top_ = newTop;
|
|
||||||
maxSize_ = newSize;
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
enum Type {
|
enum Type {
|
||||||
FIXED_BUF, // use buf_(non alignment, non protect)
|
FIXED_BUF, // use buf_(non alignment, non protect)
|
||||||
USER_BUF, // use userPtr(non alignment, non protect)
|
USER_BUF, // use userPtr(non alignment, non protect)
|
||||||
ALLOC_BUF, // use new(alignment, protect)
|
ALLOC_BUF, // use new(alignment, protect)
|
||||||
AUTO_GROW // automatically move and grow memory if necessary
|
AUTO_GROW // automatically move and grow memory if necessary
|
||||||
};
|
};
|
||||||
bool isAutoGrow() const { return type_ == AUTO_GROW; }
|
void operator=(const CodeArray&);
|
||||||
private:
|
|
||||||
bool isAllocType() const { return type_ == ALLOC_BUF || type_ == AUTO_GROW; }
|
bool isAllocType() const { return type_ == ALLOC_BUF || type_ == AUTO_GROW; }
|
||||||
Type getType(size_t maxSize, void *userPtr) const
|
Type getType(size_t maxSize, void *userPtr) const
|
||||||
{
|
{
|
||||||
|
@ -442,6 +445,16 @@ private:
|
||||||
if (maxSize <= MAX_FIXED_BUF_SIZE) return FIXED_BUF;
|
if (maxSize <= MAX_FIXED_BUF_SIZE) return FIXED_BUF;
|
||||||
return ALLOC_BUF;
|
return ALLOC_BUF;
|
||||||
}
|
}
|
||||||
|
struct AddrInfo {
|
||||||
|
size_t offset_;
|
||||||
|
size_t val_;
|
||||||
|
int size_;
|
||||||
|
bool isRelative_;
|
||||||
|
AddrInfo(size_t offset, size_t val, int size, bool isRelative)
|
||||||
|
: offset_(offset), val_(val), size_(size), isRelative_(isRelative) {}
|
||||||
|
};
|
||||||
|
typedef std::list<AddrInfo> AddrInfoList;
|
||||||
|
AddrInfoList addrInfoList_;
|
||||||
const Type type_;
|
const Type type_;
|
||||||
Allocator defaultAllocator_;
|
Allocator defaultAllocator_;
|
||||||
Allocator *alloc_;
|
Allocator *alloc_;
|
||||||
|
@ -451,6 +464,34 @@ protected:
|
||||||
size_t maxSize_;
|
size_t maxSize_;
|
||||||
uint8 *top_;
|
uint8 *top_;
|
||||||
size_t size_;
|
size_t size_;
|
||||||
|
|
||||||
|
/*
|
||||||
|
allocate new memory and copy old data to the new area
|
||||||
|
*/
|
||||||
|
void growMemory()
|
||||||
|
{
|
||||||
|
const size_t newSize = maxSize_ + ALIGN_PAGE_SIZE;
|
||||||
|
uint8 *newAllocPtr = reinterpret_cast<uint8*>(alloc_->alloc(newSize + ALIGN_PAGE_SIZE));
|
||||||
|
if (newAllocPtr == 0) throw ERR_CANT_ALLOC;
|
||||||
|
uint8 *newTop = getAlignedAddress(newAllocPtr, ALIGN_PAGE_SIZE);
|
||||||
|
for (size_t i = 0; i < size_; i++) newTop[i] = top_[i];
|
||||||
|
alloc_->free(allocPtr_);
|
||||||
|
allocPtr_ = newAllocPtr;
|
||||||
|
top_ = newTop;
|
||||||
|
maxSize_ = newSize;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
calc jmp address for AutoGrow mode
|
||||||
|
*/
|
||||||
|
void calcJmpAddress()
|
||||||
|
{
|
||||||
|
for (AddrInfoList::const_iterator i = addrInfoList_.begin(), ie = addrInfoList_.end(); i != ie; ++i) {
|
||||||
|
// uint32 disp = inner::GetOffsetDist(i->val_, i->isRelative_ ? 0 : size_t(top_));
|
||||||
|
uint32 disp = inner::VerifyInInt32(i->isRelative_ ? i->val_ : i->val_ - size_t(top_));
|
||||||
|
rewrite(i->offset_, disp, i->size_);
|
||||||
|
}
|
||||||
|
if (!protect(top_, size_, true)) throw ERR_CANT_PROTECT;
|
||||||
|
}
|
||||||
public:
|
public:
|
||||||
CodeArray(size_t maxSize = MAX_FIXED_BUF_SIZE, void *userPtr = 0, Allocator *allocator = 0)
|
CodeArray(size_t maxSize = MAX_FIXED_BUF_SIZE, void *userPtr = 0, Allocator *allocator = 0)
|
||||||
: type_(getType(maxSize, userPtr))
|
: type_(getType(maxSize, userPtr))
|
||||||
|
@ -461,7 +502,7 @@ public:
|
||||||
, size_(0)
|
, size_(0)
|
||||||
{
|
{
|
||||||
if (maxSize_ > 0 && top_ == 0) throw ERR_CANT_ALLOC;
|
if (maxSize_ > 0 && top_ == 0) throw ERR_CANT_ALLOC;
|
||||||
if (type_ == ALLOC_BUF && !protect(top_, maxSize, ReadWriteExecMode)) {
|
if (type_ == ALLOC_BUF && !protect(top_, maxSize, true)) {
|
||||||
alloc_->free(allocPtr_);
|
alloc_->free(allocPtr_);
|
||||||
throw ERR_CANT_PROTECT;
|
throw ERR_CANT_PROTECT;
|
||||||
}
|
}
|
||||||
|
@ -469,7 +510,7 @@ public:
|
||||||
virtual ~CodeArray()
|
virtual ~CodeArray()
|
||||||
{
|
{
|
||||||
if (isAllocType()) {
|
if (isAllocType()) {
|
||||||
protect(top_, maxSize_, ReadWriteMode);
|
protect(top_, maxSize_, false);
|
||||||
alloc_->free(allocPtr_);
|
alloc_->free(allocPtr_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -488,7 +529,7 @@ public:
|
||||||
{
|
{
|
||||||
if (size_ >= maxSize_) {
|
if (size_ >= maxSize_) {
|
||||||
if (type_ == AUTO_GROW) {
|
if (type_ == AUTO_GROW) {
|
||||||
resize(maxSize_ + ALIGN_PAGE_SIZE);
|
growMemory();
|
||||||
} else {
|
} else {
|
||||||
throw ERR_CODE_IS_TOO_BIG;
|
throw ERR_CODE_IS_TOO_BIG;
|
||||||
}
|
}
|
||||||
|
@ -532,17 +573,24 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@param data [in] address of jmp data
|
@param offset [in] offset from top
|
||||||
@param disp [in] offset from the next of jmp
|
@param disp [in] offset from the next of jmp
|
||||||
@param size [in] write size(1, 2, 4, 8)
|
@param size [in] write size(1, 2, 4, 8)
|
||||||
*/
|
*/
|
||||||
void rewrite(uint8 *data, uint64 disp, size_t size)
|
void rewrite(size_t offset, uint64 disp, size_t size)
|
||||||
{
|
{
|
||||||
|
assert(offset < maxSize_);
|
||||||
if (size != 1 && size != 2 && size != 4 && size != 8) throw ERR_BAD_PARAMETER;
|
if (size != 1 && size != 2 && size != 4 && size != 8) throw ERR_BAD_PARAMETER;
|
||||||
|
uint8 *const data = top_ + offset;
|
||||||
for (size_t i = 0; i < size; i++) {
|
for (size_t i = 0; i < size; i++) {
|
||||||
data[i] = static_cast<uint8>(disp >> (i * 8));
|
data[i] = static_cast<uint8>(disp >> (i * 8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void save(size_t offset, size_t val, int size, bool isRelative)
|
||||||
|
{
|
||||||
|
addrInfoList_.push_back(AddrInfo(offset, val, size, isRelative));
|
||||||
|
}
|
||||||
|
bool isAutoGrow() const { return type_ == AUTO_GROW; }
|
||||||
void updateRegField(uint8 regIdx) const
|
void updateRegField(uint8 regIdx) const
|
||||||
{
|
{
|
||||||
*top_ = (*top_ & B11000111) | ((regIdx << 3) & B00111000);
|
*top_ = (*top_ & B11000111) | ((regIdx << 3) & B00111000);
|
||||||
|
@ -551,48 +599,19 @@ public:
|
||||||
change exec permission of memory
|
change exec permission of memory
|
||||||
@param addr [in] buffer address
|
@param addr [in] buffer address
|
||||||
@param size [in] buffer size
|
@param size [in] buffer size
|
||||||
@param protectMode [in] 0:(write) 1:(write+exec) 2:(exec)
|
@param canExec [in] true(enable to exec), false(disable to exec)
|
||||||
@return true(success), false(failure)
|
@return true(success), false(failure)
|
||||||
*/
|
*/
|
||||||
static const int ReadWriteMode = 0;
|
static inline bool protect(const void *addr, size_t size, bool canExec)
|
||||||
static const int ReadWriteExecMode = 1;
|
|
||||||
static const int ReadExecMode = 2;
|
|
||||||
static inline bool protect(const void *addr, size_t size, int protectMode)
|
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
DWORD oldProtect, mode;
|
DWORD oldProtect;
|
||||||
switch (protectMode) {
|
return VirtualProtect(const_cast<void*>(addr), size, canExec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE, &oldProtect) != 0;
|
||||||
case ReadWriteMode:
|
|
||||||
mode = PAGE_READWRITE;
|
|
||||||
break;
|
|
||||||
case ReadWriteExecMode:
|
|
||||||
mode = PAGE_EXECUTE_READWRITE;
|
|
||||||
break;
|
|
||||||
case ReadExecMode:
|
|
||||||
mode = PAGE_EXECUTE_READ;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw ERR_BAD_PROTECT_MODE;
|
|
||||||
}
|
|
||||||
return VirtualProtect(const_cast<void*>(addr), size, mode, &oldProtect) != 0;
|
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
size_t pageSize = sysconf(_SC_PAGESIZE);
|
size_t pageSize = sysconf(_SC_PAGESIZE);
|
||||||
size_t iaddr = reinterpret_cast<size_t>(addr);
|
size_t iaddr = reinterpret_cast<size_t>(addr);
|
||||||
size_t roundAddr = iaddr & ~(pageSize - static_cast<size_t>(1));
|
size_t roundAddr = iaddr & ~(pageSize - static_cast<size_t>(1));
|
||||||
int mode;
|
int mode = PROT_READ | PROT_WRITE | (canExec ? PROT_EXEC : 0);
|
||||||
switch (protectMode) {
|
|
||||||
case ReadWriteMode:
|
|
||||||
mode = PROT_READ | PROT_WRITE;
|
|
||||||
break;
|
|
||||||
case ReadWriteExecMode:
|
|
||||||
mode = PROT_READ | PROT_WRITE | PROT_EXEC;
|
|
||||||
break;
|
|
||||||
case ReadExecMode:
|
|
||||||
mode = PROT_READ | PROT_EXEC;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw ERR_BAD_PROTECT_MODE;
|
|
||||||
}
|
|
||||||
return mprotect(reinterpret_cast<void*>(roundAddr), size + (iaddr - roundAddr), mode) == 0;
|
return mprotect(reinterpret_cast<void*>(roundAddr), size + (iaddr - roundAddr), mode) == 0;
|
||||||
#else
|
#else
|
||||||
return true;
|
return true;
|
||||||
|
@ -705,7 +724,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
struct JmpLabel {
|
struct JmpLabel {
|
||||||
uint8 *endOfJmp; /* end address of jmp */
|
size_t endOfJmp; /* offset from top to the end address of jmp */
|
||||||
bool isShort;
|
bool isShort;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -719,7 +738,7 @@ class Label {
|
||||||
int stackPos_;
|
int stackPos_;
|
||||||
int usedCount_;
|
int usedCount_;
|
||||||
int localCount_; // for .***
|
int localCount_; // for .***
|
||||||
typedef std::map<const std::string, const uint8*> DefinedList;
|
typedef std::map<const std::string, size_t> DefinedList;
|
||||||
typedef std::multimap<const std::string, const JmpLabel> UndefinedList;
|
typedef std::multimap<const std::string, const JmpLabel> UndefinedList;
|
||||||
DefinedList definedList_;
|
DefinedList definedList_;
|
||||||
UndefinedList undefinedList_;
|
UndefinedList undefinedList_;
|
||||||
|
@ -762,7 +781,7 @@ public:
|
||||||
localCount_ = stack_[--stackPos_ - 1];
|
localCount_ = stack_[--stackPos_ - 1];
|
||||||
}
|
}
|
||||||
void set(CodeArray *base) { base_ = base; }
|
void set(CodeArray *base) { base_ = base; }
|
||||||
void define(const char *label, const uint8 *address)
|
void define(const char *label, size_t addr)
|
||||||
{
|
{
|
||||||
std::string newLabel(label);
|
std::string newLabel(label);
|
||||||
if (newLabel == "@@") {
|
if (newLabel == "@@") {
|
||||||
|
@ -772,7 +791,7 @@ public:
|
||||||
}
|
}
|
||||||
label = newLabel.c_str();
|
label = newLabel.c_str();
|
||||||
// add label
|
// add label
|
||||||
DefinedList::value_type item(label, address);
|
DefinedList::value_type item(label, addr);
|
||||||
std::pair<DefinedList::iterator, bool> ret = definedList_.insert(item);
|
std::pair<DefinedList::iterator, bool> ret = definedList_.insert(item);
|
||||||
if (!ret.second) throw ERR_LABEL_IS_REDEFINED;
|
if (!ret.second) throw ERR_LABEL_IS_REDEFINED;
|
||||||
// search undefined label
|
// search undefined label
|
||||||
|
@ -780,22 +799,27 @@ public:
|
||||||
UndefinedList::iterator itr = undefinedList_.find(label);
|
UndefinedList::iterator itr = undefinedList_.find(label);
|
||||||
if (itr == undefinedList_.end()) break;
|
if (itr == undefinedList_.end()) break;
|
||||||
const JmpLabel *jmp = &itr->second;
|
const JmpLabel *jmp = &itr->second;
|
||||||
uint32 disp = inner::GetPtrDist(address, jmp->endOfJmp);
|
uint32 disp = inner::VerifyInInt32(addr - jmp->endOfJmp);
|
||||||
if (jmp->isShort && !inner::IsInDisp8(disp)) throw ERR_LABEL_IS_TOO_FAR;
|
if (jmp->isShort && !inner::IsInDisp8(disp)) throw ERR_LABEL_IS_TOO_FAR;
|
||||||
size_t jmpSize = jmp->isShort ? 1 : 4;
|
int jmpSize = jmp->isShort ? 1 : 4;
|
||||||
uint8 *data = jmp->endOfJmp - jmpSize;
|
size_t offset = jmp->endOfJmp - jmpSize;
|
||||||
base_->rewrite(data, disp, jmpSize);
|
if (base_->isAutoGrow()) {
|
||||||
|
base_->save(offset, disp, jmpSize, true);
|
||||||
|
} else {
|
||||||
|
base_->rewrite(offset, disp, jmpSize);
|
||||||
|
}
|
||||||
undefinedList_.erase(itr);
|
undefinedList_.erase(itr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const uint8 *getAddress(const char *label) const
|
bool getOffset(size_t *offset, const char *label) const
|
||||||
{
|
{
|
||||||
std::string newLabel = convertLabel(label);
|
std::string newLabel = convertLabel(label);
|
||||||
DefinedList::const_iterator itr = definedList_.find(newLabel);
|
DefinedList::const_iterator itr = definedList_.find(newLabel);
|
||||||
if (itr != definedList_.end()) {
|
if (itr != definedList_.end()) {
|
||||||
return itr->second;
|
*offset = itr->second;
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void addUndefinedLabel(const char *label, const JmpLabel& jmp)
|
void addUndefinedLabel(const char *label, const JmpLabel& jmp)
|
||||||
|
@ -816,11 +840,7 @@ public:
|
||||||
{
|
{
|
||||||
char buf[16];
|
char buf[16];
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#if _MSC_VER < 1400
|
_snprintf_s
|
||||||
_snprintf
|
|
||||||
#else
|
|
||||||
_snprintf_s
|
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
snprintf
|
snprintf
|
||||||
#endif
|
#endif
|
||||||
|
@ -929,64 +949,51 @@ private:
|
||||||
addr.updateRegField(static_cast<uint8>(reg.getIdx()));
|
addr.updateRegField(static_cast<uint8>(reg.getIdx()));
|
||||||
db(addr.getCode(), static_cast<int>(addr.getSize()));
|
db(addr.getCode(), static_cast<int>(addr.getSize()));
|
||||||
}
|
}
|
||||||
void opJmpL(const char *label, LabelType type, uint8 shortCode, uint8 longCode, uint8 longPref)
|
void makeJmp(uint32 disp, LabelType type, uint8 shortCode, uint8 longCode, uint8 longPref)
|
||||||
{
|
{
|
||||||
const uint8 *address = label_.getAddress(label);
|
const int shortJmpSize = 2;
|
||||||
if (address) { /* label exists */
|
|
||||||
opJmp(address, type, shortCode, longCode, longPref, true);
|
|
||||||
} else {
|
|
||||||
const int shortHeaderSize = 1;
|
|
||||||
const int shortJmpSize = shortHeaderSize + 1; /* +1 means 8-bit displacement */
|
|
||||||
const int longHeaderSize = longPref ? 2 : 1;
|
|
||||||
const int longJmpSize = longHeaderSize + 4; /* +4 means 32-bit displacement */
|
|
||||||
uint8 *top = const_cast<uint8*>(getCurr());
|
|
||||||
bool isShort = (type != T_NEAR);
|
|
||||||
JmpLabel jmp;
|
|
||||||
jmp.endOfJmp = top + (isShort ? shortJmpSize : longJmpSize);
|
|
||||||
jmp.isShort = isShort;
|
|
||||||
if (isShort) {
|
|
||||||
db(shortCode);
|
|
||||||
db(0);
|
|
||||||
} else {
|
|
||||||
if (longPref) db(longPref);
|
|
||||||
db(longCode);
|
|
||||||
dd(0);
|
|
||||||
}
|
|
||||||
label_.addUndefinedLabel(label, jmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
struct AddrInfo {
|
|
||||||
size_t offset_;
|
|
||||||
const uint8 *addr_;
|
|
||||||
AddrInfo(size_t offset, const uint8 *addr) : offset_(offset), addr_(addr) {}
|
|
||||||
};
|
|
||||||
typedef std::list<AddrInfo> AddrInfoList;
|
|
||||||
AddrInfoList addrInfoList_;
|
|
||||||
void opJmp(const void *addr, LabelType type, uint8 shortCode, uint8 longCode, uint8 longPref, bool isLabel = false)
|
|
||||||
{
|
|
||||||
bool isAuto = !isLabel && isAutoGrow();
|
|
||||||
if (isAuto && type != T_NEAR) throw ERR_ONLY_T_NEAR_IS_SUPPORTED_IN_AUTO_GROW;
|
|
||||||
const int shortHeaderSize = 1;
|
|
||||||
const int shortJmpSize = shortHeaderSize + 1; /* +1 means 8-bit displacement */
|
|
||||||
const int longHeaderSize = longPref ? 2 : 1;
|
const int longHeaderSize = longPref ? 2 : 1;
|
||||||
const int longJmpSize = longHeaderSize + 4; /* +4 means 32-bit displacement */
|
const int longJmpSize = longHeaderSize + 4;
|
||||||
|
|
||||||
uint32 disp = inner::GetPtrDist(addr, getCurr());
|
|
||||||
if (type != T_NEAR && inner::IsInDisp8(disp - shortJmpSize)) {
|
if (type != T_NEAR && inner::IsInDisp8(disp - shortJmpSize)) {
|
||||||
db(shortCode);
|
db(shortCode); db(disp - shortJmpSize);
|
||||||
db(disp - shortJmpSize);
|
|
||||||
} else {
|
} else {
|
||||||
if (type == T_SHORT) throw ERR_LABEL_IS_TOO_FAR;
|
if (type == T_SHORT) throw ERR_LABEL_IS_TOO_FAR;
|
||||||
if (longPref) db(longPref);
|
if (longPref) db(longPref);
|
||||||
db(longCode);
|
db(longCode); dd(disp - longJmpSize);
|
||||||
if (isAuto) {
|
|
||||||
addrInfoList_.push_back(AddrInfo(size_, reinterpret_cast<const uint8*>(addr) - longJmpSize + 1));
|
|
||||||
dd(0);
|
|
||||||
} else {
|
|
||||||
dd(disp - longJmpSize);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void opJmp(const char *label, LabelType type, uint8 shortCode, uint8 longCode, uint8 longPref)
|
||||||
|
{
|
||||||
|
if (isAutoGrow() && size_ + 16 >= maxSize_) growMemory(); /* avoid splitting code of jmp */
|
||||||
|
size_t offset = 0;
|
||||||
|
if (label_.getOffset(&offset, label)) { /* label exists */
|
||||||
|
makeJmp(inner::VerifyInInt32(offset - getSize()), type, shortCode, longCode, longPref);
|
||||||
|
} else {
|
||||||
|
JmpLabel jmp;
|
||||||
|
jmp.isShort = (type != T_NEAR);
|
||||||
|
if (jmp.isShort) {
|
||||||
|
db(shortCode); db(0);
|
||||||
|
} else {
|
||||||
|
if (longPref) db(longPref);
|
||||||
|
db(longCode); dd(0);
|
||||||
|
}
|
||||||
|
jmp.endOfJmp = getSize();
|
||||||
|
label_.addUndefinedLabel(label, jmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void opJmpAbs(const void *addr, LabelType type, uint8 shortCode, uint8 longCode)
|
||||||
|
{
|
||||||
|
if (isAutoGrow()) {
|
||||||
|
if (type != T_NEAR) throw ERR_ONLY_T_NEAR_IS_SUPPORTED_IN_AUTO_GROW;
|
||||||
|
if (size_ + 16 >= maxSize_) growMemory();
|
||||||
|
db(longCode);
|
||||||
|
save(size_, size_t(addr) - (getSize() + 4), 4, false);
|
||||||
|
dd(0);
|
||||||
|
} else {
|
||||||
|
makeJmp(inner::VerifyInInt32(reinterpret_cast<const uint8*>(addr) - getCurr()), type, shortCode, longCode, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
/* preCode is for SSSE3/SSE4 */
|
/* preCode is for SSSE3/SSE4 */
|
||||||
void opGen(const Operand& reg, const Operand& op, int code, int pref, bool isValid(const Operand&, const Operand&), int imm8 = NONE, int preCode = NONE)
|
void opGen(const Operand& reg, const Operand& op, int code, int pref, bool isValid(const Operand&, const Operand&), int imm8 = NONE, int preCode = NONE)
|
||||||
{
|
{
|
||||||
|
@ -1186,17 +1193,17 @@ public:
|
||||||
|
|
||||||
void L(const char *label)
|
void L(const char *label)
|
||||||
{
|
{
|
||||||
label_.define(label, getCurr());
|
label_.define(label, getSize());
|
||||||
}
|
}
|
||||||
void inLocalLabel() { label_.enterLocal(); }
|
void inLocalLabel() { label_.enterLocal(); }
|
||||||
void outLocalLabel() { label_.leaveLocal(); }
|
void outLocalLabel() { label_.leaveLocal(); }
|
||||||
void jmp(const char *label, LabelType type = T_AUTO)
|
void jmp(const char *label, LabelType type = T_AUTO)
|
||||||
{
|
{
|
||||||
opJmpL(label, type, B11101011, B11101001, 0);
|
opJmp(label, type, B11101011, B11101001, 0);
|
||||||
}
|
}
|
||||||
void jmp(const void *addr, LabelType type = T_AUTO)
|
void jmp(const void *addr, LabelType type = T_AUTO)
|
||||||
{
|
{
|
||||||
opJmp(addr, type, B11101011, B11101001, 0);
|
opJmpAbs(addr, type, B11101011, B11101001);
|
||||||
}
|
}
|
||||||
void jmp(const Operand& op)
|
void jmp(const Operand& op)
|
||||||
{
|
{
|
||||||
|
@ -1371,11 +1378,11 @@ public:
|
||||||
}
|
}
|
||||||
void call(const char *label)
|
void call(const char *label)
|
||||||
{
|
{
|
||||||
opJmpL(label, T_NEAR, 0, B11101000, 0);
|
opJmp(label, T_NEAR, 0, B11101000, 0);
|
||||||
}
|
}
|
||||||
void call(const void *addr)
|
void call(const void *addr)
|
||||||
{
|
{
|
||||||
opJmp(addr, T_NEAR, 0, B11101000, 0);
|
opJmpAbs(addr, T_NEAR, 0, B11101000);
|
||||||
}
|
}
|
||||||
// special case
|
// special case
|
||||||
void movd(const Address& addr, const Mmx& mmx)
|
void movd(const Address& addr, const Mmx& mmx)
|
||||||
|
@ -1545,8 +1552,8 @@ public:
|
||||||
}
|
}
|
||||||
enum { NONE = 256 };
|
enum { NONE = 256 };
|
||||||
public:
|
public:
|
||||||
CodeGenerator(size_t maxSize = DEFAULT_MAX_CODE_SIZE, void *userPtr = 0)
|
CodeGenerator(size_t maxSize = DEFAULT_MAX_CODE_SIZE, void *userPtr = 0, Allocator *allocator = 0)
|
||||||
: CodeArray(maxSize, userPtr)
|
: CodeArray(maxSize, userPtr, allocator)
|
||||||
, mm0(0), mm1(1), mm2(2), mm3(3), mm4(4), mm5(5), mm6(6), mm7(7)
|
, mm0(0), mm1(1), mm2(2), mm3(3), mm4(4), mm5(5), mm6(6), mm7(7)
|
||||||
, xmm0(0), xmm1(1), xmm2(2), xmm3(3), xmm4(4), xmm5(5), xmm6(6), xmm7(7)
|
, xmm0(0), xmm1(1), xmm2(2), xmm3(3), xmm4(4), xmm5(5), xmm6(6), xmm7(7)
|
||||||
, ymm0(0), ymm1(1), ymm2(2), ymm3(3), ymm4(4), ymm5(5), ymm6(6), ymm7(7)
|
, ymm0(0), ymm1(1), ymm2(2), ymm3(3), ymm4(4), ymm5(5), ymm6(6), ymm7(7)
|
||||||
|
@ -1573,21 +1580,13 @@ public:
|
||||||
label_.set(this);
|
label_.set(this);
|
||||||
}
|
}
|
||||||
bool hasUndefinedLabel() const { return label_.hasUndefinedLabel(); }
|
bool hasUndefinedLabel() const { return label_.hasUndefinedLabel(); }
|
||||||
const uint8 *getCode() const
|
|
||||||
{
|
|
||||||
assert(!hasUndefinedLabel());
|
|
||||||
return top_;
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
call ready() to complete generating code on AutoGrow
|
call ready() to complete generating code on AutoGrow
|
||||||
*/
|
*/
|
||||||
void ready()
|
void ready()
|
||||||
{
|
{
|
||||||
if (hasUndefinedLabel()) throw ERR_LABEL_IS_NOT_FOUND;
|
if (hasUndefinedLabel()) throw ERR_LABEL_IS_NOT_FOUND;
|
||||||
for (AddrInfoList::const_iterator i = addrInfoList_.begin(), ie = addrInfoList_.end(); i != ie; ++i) {
|
calcJmpAddress();
|
||||||
rewrite(top_ + i->offset_, (uint32)(i->addr_ - (top_ + i->offset_)), 4);
|
|
||||||
}
|
|
||||||
if (!protect(top_, size_, ReadWriteExecMode)) throw ERR_CANT_PROTECT;
|
|
||||||
}
|
}
|
||||||
#ifdef XBYAK_TEST
|
#ifdef XBYAK_TEST
|
||||||
void dump(bool doClear = true)
|
void dump(bool doClear = true)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const char *getVersionString() const { return "3.06"; }
|
const char *getVersionString() const { return "3.50"; }
|
||||||
void packssdw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x6B); }
|
void packssdw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x6B); }
|
||||||
void packsswb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x63); }
|
void packsswb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x63); }
|
||||||
void packuswb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x67); }
|
void packuswb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x67); }
|
||||||
|
@ -183,94 +183,94 @@ void movlps(const Operand& op1, const Operand& op2) { opMovXMM(op1, op2, 0x12, 0
|
||||||
void movhpd(const Operand& op1, const Operand& op2) { opMovXMM(op1, op2, 0x16, 0x66); }
|
void movhpd(const Operand& op1, const Operand& op2) { opMovXMM(op1, op2, 0x16, 0x66); }
|
||||||
void movlpd(const Operand& op1, const Operand& op2) { opMovXMM(op1, op2, 0x12, 0x66); }
|
void movlpd(const Operand& op1, const Operand& op2) { opMovXMM(op1, op2, 0x12, 0x66); }
|
||||||
void cmovo(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 0); }
|
void cmovo(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 0); }
|
||||||
void jo(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x70, 0x80, 0x0F); }
|
void jo(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x70, 0x80, 0x0F); }
|
||||||
void seto(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 0); }
|
void seto(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 0); }
|
||||||
void cmovno(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 1); }
|
void cmovno(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 1); }
|
||||||
void jno(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x71, 0x81, 0x0F); }
|
void jno(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x71, 0x81, 0x0F); }
|
||||||
void setno(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 1); }
|
void setno(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 1); }
|
||||||
void cmovb(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 2); }
|
void cmovb(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 2); }
|
||||||
void jb(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x72, 0x82, 0x0F); }
|
void jb(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }
|
||||||
void setb(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 2); }
|
void setb(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 2); }
|
||||||
void cmovc(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 2); }
|
void cmovc(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 2); }
|
||||||
void jc(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x72, 0x82, 0x0F); }
|
void jc(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }
|
||||||
void setc(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 2); }
|
void setc(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 2); }
|
||||||
void cmovnae(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 2); }
|
void cmovnae(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 2); }
|
||||||
void jnae(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x72, 0x82, 0x0F); }
|
void jnae(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }
|
||||||
void setnae(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 2); }
|
void setnae(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 2); }
|
||||||
void cmovnb(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 3); }
|
void cmovnb(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 3); }
|
||||||
void jnb(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x73, 0x83, 0x0F); }
|
void jnb(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }
|
||||||
void setnb(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 3); }
|
void setnb(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 3); }
|
||||||
void cmovae(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 3); }
|
void cmovae(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 3); }
|
||||||
void jae(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x73, 0x83, 0x0F); }
|
void jae(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }
|
||||||
void setae(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 3); }
|
void setae(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 3); }
|
||||||
void cmovnc(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 3); }
|
void cmovnc(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 3); }
|
||||||
void jnc(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x73, 0x83, 0x0F); }
|
void jnc(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }
|
||||||
void setnc(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 3); }
|
void setnc(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 3); }
|
||||||
void cmove(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 4); }
|
void cmove(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 4); }
|
||||||
void je(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x74, 0x84, 0x0F); }
|
void je(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x74, 0x84, 0x0F); }
|
||||||
void sete(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 4); }
|
void sete(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 4); }
|
||||||
void cmovz(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 4); }
|
void cmovz(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 4); }
|
||||||
void jz(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x74, 0x84, 0x0F); }
|
void jz(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x74, 0x84, 0x0F); }
|
||||||
void setz(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 4); }
|
void setz(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 4); }
|
||||||
void cmovne(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 5); }
|
void cmovne(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 5); }
|
||||||
void jne(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x75, 0x85, 0x0F); }
|
void jne(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x75, 0x85, 0x0F); }
|
||||||
void setne(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 5); }
|
void setne(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 5); }
|
||||||
void cmovnz(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 5); }
|
void cmovnz(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 5); }
|
||||||
void jnz(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x75, 0x85, 0x0F); }
|
void jnz(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x75, 0x85, 0x0F); }
|
||||||
void setnz(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 5); }
|
void setnz(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 5); }
|
||||||
void cmovbe(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 6); }
|
void cmovbe(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 6); }
|
||||||
void jbe(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x76, 0x86, 0x0F); }
|
void jbe(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x76, 0x86, 0x0F); }
|
||||||
void setbe(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 6); }
|
void setbe(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 6); }
|
||||||
void cmovna(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 6); }
|
void cmovna(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 6); }
|
||||||
void jna(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x76, 0x86, 0x0F); }
|
void jna(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x76, 0x86, 0x0F); }
|
||||||
void setna(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 6); }
|
void setna(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 6); }
|
||||||
void cmovnbe(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 7); }
|
void cmovnbe(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 7); }
|
||||||
void jnbe(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x77, 0x87, 0x0F); }
|
void jnbe(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x77, 0x87, 0x0F); }
|
||||||
void setnbe(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 7); }
|
void setnbe(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 7); }
|
||||||
void cmova(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 7); }
|
void cmova(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 7); }
|
||||||
void ja(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x77, 0x87, 0x0F); }
|
void ja(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x77, 0x87, 0x0F); }
|
||||||
void seta(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 7); }
|
void seta(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 7); }
|
||||||
void cmovs(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 8); }
|
void cmovs(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 8); }
|
||||||
void js(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x78, 0x88, 0x0F); }
|
void js(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x78, 0x88, 0x0F); }
|
||||||
void sets(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 8); }
|
void sets(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 8); }
|
||||||
void cmovns(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 9); }
|
void cmovns(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 9); }
|
||||||
void jns(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x79, 0x89, 0x0F); }
|
void jns(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x79, 0x89, 0x0F); }
|
||||||
void setns(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 9); }
|
void setns(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 9); }
|
||||||
void cmovp(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 10); }
|
void cmovp(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 10); }
|
||||||
void jp(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x7A, 0x8A, 0x0F); }
|
void jp(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x7A, 0x8A, 0x0F); }
|
||||||
void setp(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 10); }
|
void setp(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 10); }
|
||||||
void cmovpe(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 10); }
|
void cmovpe(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 10); }
|
||||||
void jpe(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x7A, 0x8A, 0x0F); }
|
void jpe(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x7A, 0x8A, 0x0F); }
|
||||||
void setpe(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 10); }
|
void setpe(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 10); }
|
||||||
void cmovnp(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 11); }
|
void cmovnp(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 11); }
|
||||||
void jnp(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x7B, 0x8B, 0x0F); }
|
void jnp(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x7B, 0x8B, 0x0F); }
|
||||||
void setnp(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 11); }
|
void setnp(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 11); }
|
||||||
void cmovpo(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 11); }
|
void cmovpo(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 11); }
|
||||||
void jpo(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x7B, 0x8B, 0x0F); }
|
void jpo(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x7B, 0x8B, 0x0F); }
|
||||||
void setpo(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 11); }
|
void setpo(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 11); }
|
||||||
void cmovl(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 12); }
|
void cmovl(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 12); }
|
||||||
void jl(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x7C, 0x8C, 0x0F); }
|
void jl(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x7C, 0x8C, 0x0F); }
|
||||||
void setl(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 12); }
|
void setl(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 12); }
|
||||||
void cmovnge(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 12); }
|
void cmovnge(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 12); }
|
||||||
void jnge(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x7C, 0x8C, 0x0F); }
|
void jnge(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x7C, 0x8C, 0x0F); }
|
||||||
void setnge(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 12); }
|
void setnge(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 12); }
|
||||||
void cmovnl(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 13); }
|
void cmovnl(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 13); }
|
||||||
void jnl(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x7D, 0x8D, 0x0F); }
|
void jnl(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x7D, 0x8D, 0x0F); }
|
||||||
void setnl(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 13); }
|
void setnl(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 13); }
|
||||||
void cmovge(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 13); }
|
void cmovge(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 13); }
|
||||||
void jge(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x7D, 0x8D, 0x0F); }
|
void jge(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x7D, 0x8D, 0x0F); }
|
||||||
void setge(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 13); }
|
void setge(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 13); }
|
||||||
void cmovle(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 14); }
|
void cmovle(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 14); }
|
||||||
void jle(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x7E, 0x8E, 0x0F); }
|
void jle(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x7E, 0x8E, 0x0F); }
|
||||||
void setle(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 14); }
|
void setle(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 14); }
|
||||||
void cmovng(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 14); }
|
void cmovng(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 14); }
|
||||||
void jng(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x7E, 0x8E, 0x0F); }
|
void jng(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x7E, 0x8E, 0x0F); }
|
||||||
void setng(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 14); }
|
void setng(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 14); }
|
||||||
void cmovnle(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 15); }
|
void cmovnle(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 15); }
|
||||||
void jnle(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x7F, 0x8F, 0x0F); }
|
void jnle(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F, 0x0F); }
|
||||||
void setnle(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 15); }
|
void setnle(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 15); }
|
||||||
void cmovg(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 15); }
|
void cmovg(const Reg32e& reg, const Operand& op) { opModRM(reg, op, op.isREG(i32e), op.isMEM(), 0x0F, B01000000 | 15); }
|
||||||
void jg(const char *label, LabelType type = T_AUTO) { opJmpL(label, type, 0x7F, 0x8F, 0x0F); }
|
void jg(const char *label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F, 0x0F); }
|
||||||
void setg(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 15); }
|
void setg(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, B10010000 | 15); }
|
||||||
#ifdef XBYAK64
|
#ifdef XBYAK64
|
||||||
void cdqe() { db(0x48); db(0x98); }
|
void cdqe() { db(0x48); db(0x98); }
|
||||||
|
|
Loading…
Reference in a new issue