Xbyak ver 3.50

This commit is contained in:
MITSUNARI Shigeo 2012-03-20 00:07:29 +09:00
parent f4f84a65aa
commit 683f7448ae
9 changed files with 717 additions and 215 deletions

View file

@ -1,11 +1,16 @@
#include <stdio.h>
#include <string.h>
#include "xbyak/xbyak.h"
#include <string>
#include <xbyak/xbyak.h>
#define NUM_OF_ARRAY(x) (sizeof(x) / sizeof(x[0]))
#if !defined(_WIN64) && !defined(__x86_64__)
#define ONLY_32BIT
#endif
using namespace Xbyak;
struct TestJmp : public CodeGenerator {
struct TestJmp : public Xbyak::CodeGenerator {
void putNop(int n)
{
for (int i = 0; i < n; i++) {
@ -45,24 +50,19 @@ struct TestJmp : public CodeGenerator {
*/
TestJmp(int offset, bool isBack, bool isShort)
{
char buf[32];
static int count = 0;
if (isBack) {
sprintf(buf, "L(\"X%d\");\n", count);
L(buf);
L("@@");
putNop(offset);
jmp(buf);
jmp("@b");
} else {
sprintf(buf, "L(\"Y%d\");\n", count);
if (isShort) {
jmp(buf);
jmp("@f");
} else {
jmp(buf, T_NEAR);
jmp("@f", T_NEAR);
}
putNop(offset);
L(buf);
L("@@");
}
count++;
}
};
@ -72,34 +72,125 @@ void test1()
int offset;
bool isBack;
bool isShort;
const char *result;
uint8 result[6];
int size;
} tbl[] = {
{ 0, true, true, "EBFE" },
{ 1, true, true, "EBFD" },
{ 126, true, true, "EB80" },
{ 127, true, false, "E97CFFFFFF" },
{ 0, false, true, "EB00" },
{ 1, false, true, "EB01" },
{ 127, false, true, "EB7F" },
{ 128, false, false, "E980000000" },
{ 0, true, true, { 0xeb, 0xfe }, 2 },
{ 1, true, true, { 0xeb, 0xfd }, 2 },
{ 126, true, true, { 0xeb, 0x80 }, 2 },
{ 127, true, false, {0xe9, 0x7c, 0xff, 0xff, 0xff }, 5 },
{ 0, false, true, { 0xeb, 0x00 }, 2 },
{ 1, false, true, { 0xeb, 0x01 }, 2 },
{ 127, false, true, { 0xeb, 0x7f }, 2 },
{ 128, false, false, { 0xe9, 0x80, 0x00, 0x00, 0x00 }, 5 },
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
TestJmp jmp(p->offset, p->isBack, p->isShort);
const uint8 *q = (const uint8*)jmp.getCode();
char buf[32];
if (p->isBack) q += p->offset; /* skip nop */
for (size_t j = 0; j < jmp.getSize() - p->offset; j++) {
sprintf(&buf[j * 2], "%02X", q[j]);
for (int j = 0; j < p->size; 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 {
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 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) {
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()
{
try {
test1();
test2();
#ifdef ONLY_32BIT
test3();
#endif
test4();
test5();
} catch (Xbyak::Error err) {
printf("ERR:%s(%d)\n", Xbyak::ConvertErrorToString(err), err);
} catch (...) {