jcxz/jecxz support new Label
This commit is contained in:
parent
abae0742fb
commit
59f4d082fc
3 changed files with 327 additions and 285 deletions
|
@ -49,6 +49,7 @@ std::string type2String(int type)
|
||||||
void put_jREGz(const char *reg, bool prefix)
|
void put_jREGz(const char *reg, bool prefix)
|
||||||
{
|
{
|
||||||
printf("void j%sz(const std::string& label) { %sopJmp(label, T_SHORT, 0xe3, 0, 0); }\n", reg, prefix ? "db(0x67); " : "");
|
printf("void j%sz(const std::string& label) { %sopJmp(label, T_SHORT, 0xe3, 0, 0); }\n", reg, prefix ? "db(0x67); " : "");
|
||||||
|
printf("void j%sz(Label& label) { %sopJmp(label, T_SHORT, 0xe3, 0, 0); }\n", reg, prefix ? "db(0x67); " : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
void put()
|
void put()
|
||||||
|
|
205
test/jmp.cpp
205
test/jmp.cpp
|
@ -16,6 +16,10 @@ void putNop(Xbyak::CodeGenerator *gen, int n)
|
||||||
gen->nop();
|
gen->nop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test1()
|
||||||
|
{
|
||||||
|
puts("test1");
|
||||||
struct TestJmp : public Xbyak::CodeGenerator {
|
struct TestJmp : public Xbyak::CodeGenerator {
|
||||||
/*
|
/*
|
||||||
4 X0:
|
4 X0:
|
||||||
|
@ -48,8 +52,24 @@ struct TestJmp : public Xbyak::CodeGenerator {
|
||||||
31 00000198 <res 00000080> dummyY128 resb 128
|
31 00000198 <res 00000080> dummyY128 resb 128
|
||||||
32 Y128:
|
32 Y128:
|
||||||
*/
|
*/
|
||||||
TestJmp(int offset, bool isBack, bool isShort)
|
TestJmp(int offset, bool isBack, bool isShort, bool useNewLabel)
|
||||||
{
|
{
|
||||||
|
if (useNewLabel) {
|
||||||
|
Label label;
|
||||||
|
if (isBack) {
|
||||||
|
L(label);
|
||||||
|
putNop(this, offset);
|
||||||
|
jmp(label);
|
||||||
|
} else {
|
||||||
|
if (isShort) {
|
||||||
|
jmp(label);
|
||||||
|
} else {
|
||||||
|
jmp(label, T_NEAR);
|
||||||
|
}
|
||||||
|
putNop(this, offset);
|
||||||
|
L(label);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (isBack) {
|
if (isBack) {
|
||||||
L("@@");
|
L("@@");
|
||||||
putNop(this, offset);
|
putNop(this, offset);
|
||||||
|
@ -64,11 +84,8 @@ struct TestJmp : public Xbyak::CodeGenerator {
|
||||||
L("@@");
|
L("@@");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void test1()
|
|
||||||
{
|
|
||||||
puts("test1");
|
|
||||||
static const struct Tbl {
|
static const struct Tbl {
|
||||||
int offset;
|
int offset;
|
||||||
bool isBack;
|
bool isBack;
|
||||||
|
@ -87,17 +104,100 @@ void test1()
|
||||||
};
|
};
|
||||||
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);
|
for (int k = 0; k < 2; k++) {
|
||||||
|
TestJmp jmp(p->offset, p->isBack, p->isShort, k == 0);
|
||||||
const uint8 *q = (const uint8*)jmp.getCode();
|
const uint8 *q = (const uint8*)jmp.getCode();
|
||||||
if (p->isBack) q += p->offset; /* skip nop */
|
if (p->isBack) q += p->offset; /* skip nop */
|
||||||
for (int j = 0; j < p->size; j++) {
|
for (int j = 0; j < p->size; j++) {
|
||||||
if (q[j] != p->result[j]) {
|
if (q[j] != p->result[j]) {
|
||||||
printf("err (%d,%d) %02x assume=%02x\n", (int)i, j, q[j], p->result[j]);
|
printf("err (%d, %d, %d) %02x assume=%02x\n", (int)i, k, j, q[j], p->result[j]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void testJmpCx()
|
||||||
|
{
|
||||||
|
puts("testJmpCx");
|
||||||
|
struct TestJmpCx : public CodeGenerator {
|
||||||
|
explicit TestJmpCx(void *p, bool useNewLabel)
|
||||||
|
: Xbyak::CodeGenerator(16, p)
|
||||||
|
{
|
||||||
|
if (useNewLabel) {
|
||||||
|
Label lp;
|
||||||
|
L(lp);
|
||||||
|
#ifdef XBYAK64
|
||||||
|
puts("TestJmpCx 64bit");
|
||||||
|
/*
|
||||||
|
67 E3 FD ; jecxz lp
|
||||||
|
E3 FB ; jrcxz lp
|
||||||
|
*/
|
||||||
|
jecxz(lp);
|
||||||
|
jrcxz(lp);
|
||||||
|
#else
|
||||||
|
puts("TestJmpCx 32bit");
|
||||||
|
/*
|
||||||
|
E3FE ; jecxz lp
|
||||||
|
67E3FB ; jcxz lp
|
||||||
|
*/
|
||||||
|
jecxz(lp);
|
||||||
|
jcxz(lp);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
inLocalLabel();
|
||||||
|
L(".lp");
|
||||||
|
#ifdef XBYAK64
|
||||||
|
puts("TestJmpCx 64bit");
|
||||||
|
/*
|
||||||
|
67 E3 FD ; jecxz lp
|
||||||
|
E3 FB ; jrcxz lp
|
||||||
|
*/
|
||||||
|
jecxz(".lp");
|
||||||
|
jrcxz(".lp");
|
||||||
|
#else
|
||||||
|
puts("TestJmpCx 32bit");
|
||||||
|
/*
|
||||||
|
E3FE ; jecxz lp
|
||||||
|
67E3FB ; jcxz lp
|
||||||
|
*/
|
||||||
|
jecxz(".lp");
|
||||||
|
jcxz(".lp");
|
||||||
|
#endif
|
||||||
|
outLocalLabel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const struct {
|
||||||
|
const char *p;
|
||||||
|
size_t len;
|
||||||
|
} tbl = {
|
||||||
|
#ifdef XBYAK64
|
||||||
|
"\x67\xe3\xfd\xe3\xfb", 5
|
||||||
|
#else
|
||||||
|
"\xe3\xfe\x67\xe3\xfb", 5
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
for (int j = 0; j < 2; j++) {
|
||||||
|
char buf[16] = {};
|
||||||
|
TestJmpCx code(buf, j == 0);
|
||||||
|
if (memcmp(buf, tbl.p, tbl.len) == 0) {
|
||||||
|
} else {
|
||||||
|
printf("err %d\n", j);
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
printf("%02x ", (unsigned char)buf[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(disable : 4310)
|
||||||
|
#endif
|
||||||
|
void test2()
|
||||||
|
{
|
||||||
|
puts("test2");
|
||||||
struct TestJmp2 : public CodeGenerator {
|
struct TestJmp2 : public CodeGenerator {
|
||||||
/*
|
/*
|
||||||
1 00000000 90 nop
|
1 00000000 90 nop
|
||||||
|
@ -142,64 +242,6 @@ struct TestJmp2 : public CodeGenerator {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TestJmpCx : public CodeGenerator {
|
|
||||||
explicit TestJmpCx(void *p)
|
|
||||||
: Xbyak::CodeGenerator(16, p)
|
|
||||||
{
|
|
||||||
inLocalLabel();
|
|
||||||
L(".lp");
|
|
||||||
#ifdef XBYAK64
|
|
||||||
puts("TestJmpCx 64bit");
|
|
||||||
/*
|
|
||||||
67 E3 FD ; jecxz lp
|
|
||||||
E3 FB ; jrcxz lp
|
|
||||||
*/
|
|
||||||
jecxz(".lp");
|
|
||||||
jrcxz(".lp");
|
|
||||||
#else
|
|
||||||
puts("TestJmpCx 32bit");
|
|
||||||
/*
|
|
||||||
E3FE ; jecxz lp
|
|
||||||
67E3FB ; jcxz lp
|
|
||||||
*/
|
|
||||||
jecxz(".lp");
|
|
||||||
jcxz(".lp");
|
|
||||||
#endif
|
|
||||||
outLocalLabel();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void testJmpCx()
|
|
||||||
{
|
|
||||||
puts("testJmpCx");
|
|
||||||
const struct {
|
|
||||||
const char *p;
|
|
||||||
size_t len;
|
|
||||||
} tbl = {
|
|
||||||
#ifdef XBYAK64
|
|
||||||
"\x67\xe3\xfd\xe3\xfb", 5
|
|
||||||
#else
|
|
||||||
"\xe3\xfe\x67\xe3\xfb", 5
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
char buf[16] = {};
|
|
||||||
TestJmpCx code(buf);
|
|
||||||
if (memcmp(buf, tbl.p, tbl.len) == 0) {
|
|
||||||
} else {
|
|
||||||
puts("ng");
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
printf("%02x ", (unsigned char)buf[i]);
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#pragma warning(disable : 4310)
|
|
||||||
#endif
|
|
||||||
void test2()
|
|
||||||
{
|
|
||||||
puts("test2");
|
|
||||||
std::string ok;
|
std::string ok;
|
||||||
ok.resize(0x18C + 128, (char)0x90);
|
ok.resize(0x18C + 128, (char)0x90);
|
||||||
ok[0x080] = (char)0xeb;
|
ok[0x080] = (char)0xeb;
|
||||||
|
@ -241,6 +283,9 @@ void test2()
|
||||||
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; }
|
||||||
|
|
||||||
|
void test3()
|
||||||
|
{
|
||||||
|
puts("test3");
|
||||||
struct Grow : Xbyak::CodeGenerator {
|
struct Grow : Xbyak::CodeGenerator {
|
||||||
Grow(int dummySize)
|
Grow(int dummySize)
|
||||||
: Xbyak::CodeGenerator(128, Xbyak::AutoGrow)
|
: Xbyak::CodeGenerator(128, Xbyak::AutoGrow)
|
||||||
|
@ -258,10 +303,6 @@ struct Grow : Xbyak::CodeGenerator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void test3()
|
|
||||||
{
|
|
||||||
puts("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);
|
||||||
Grow g(dummySize);
|
Grow g(dummySize);
|
||||||
|
@ -327,6 +368,9 @@ void diff(const std::string& a, const std::string& b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test4()
|
||||||
|
{
|
||||||
|
puts("test4");
|
||||||
struct Test4 : Xbyak::CodeGenerator {
|
struct Test4 : Xbyak::CodeGenerator {
|
||||||
explicit Test4(int size, void *mode)
|
explicit Test4(int size, void *mode)
|
||||||
: CodeGenerator(size, mode)
|
: CodeGenerator(size, mode)
|
||||||
|
@ -342,9 +386,6 @@ struct Test4 : Xbyak::CodeGenerator {
|
||||||
ret();
|
ret();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
void test4()
|
|
||||||
{
|
|
||||||
puts("test4");
|
|
||||||
std::string fm, gm;
|
std::string fm, gm;
|
||||||
Test4 fc(1024, 0);
|
Test4 fc(1024, 0);
|
||||||
Test4 gc(5, Xbyak::AutoGrow);
|
Test4 gc(5, Xbyak::AutoGrow);
|
||||||
|
@ -356,6 +397,9 @@ void test4()
|
||||||
diff(gm, gm);
|
diff(gm, gm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test5()
|
||||||
|
{
|
||||||
|
puts("test5");
|
||||||
struct Test5 : Xbyak::CodeGenerator {
|
struct Test5 : Xbyak::CodeGenerator {
|
||||||
explicit Test5(int size, int count, void *mode)
|
explicit Test5(int size, int count, void *mode)
|
||||||
: CodeGenerator(size, mode, &myAlloc)
|
: CodeGenerator(size, mode, &myAlloc)
|
||||||
|
@ -387,10 +431,6 @@ struct Test5 : Xbyak::CodeGenerator {
|
||||||
outLocalLabel();
|
outLocalLabel();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void test5()
|
|
||||||
{
|
|
||||||
puts("test5");
|
|
||||||
std::string fm, gm;
|
std::string fm, gm;
|
||||||
const int count = 50;
|
const int count = 50;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -509,6 +549,9 @@ void testMovLabel(bool grow)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void testMovLabel2()
|
||||||
|
{
|
||||||
|
puts("tsetMovLabel2");
|
||||||
struct MovLabel2Code : Xbyak::CodeGenerator {
|
struct MovLabel2Code : Xbyak::CodeGenerator {
|
||||||
MovLabel2Code()
|
MovLabel2Code()
|
||||||
{
|
{
|
||||||
|
@ -538,15 +581,13 @@ struct MovLabel2Code : Xbyak::CodeGenerator {
|
||||||
ret();
|
ret();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void testMovLabel2()
|
|
||||||
{
|
|
||||||
puts("tsetMovLabel2");
|
|
||||||
MovLabel2Code code;
|
MovLabel2Code code;
|
||||||
int ret = code.getCode<int (*)()>()();
|
int ret = code.getCode<int (*)()>()();
|
||||||
if (ret != 7) printf("ERR=%d\n", ret);
|
if (ret != 7) printf("ERR=%d\n", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test6()
|
||||||
|
{
|
||||||
struct TestLocal : public Xbyak::CodeGenerator {
|
struct TestLocal : public Xbyak::CodeGenerator {
|
||||||
TestLocal(bool grow)
|
TestLocal(bool grow)
|
||||||
: Xbyak::CodeGenerator(grow ? 128 : 4096, grow ? Xbyak::AutoGrow : 0)
|
: Xbyak::CodeGenerator(grow ? 128 : 4096, grow ? Xbyak::AutoGrow : 0)
|
||||||
|
@ -612,8 +653,6 @@ struct TestLocal : public Xbyak::CodeGenerator {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void test6()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
const bool grow = i == 1;
|
const bool grow = i == 1;
|
||||||
printf("test6 grow=%d\n", i);
|
printf("test6 grow=%d\n", i);
|
||||||
|
@ -695,7 +734,6 @@ void testNewLabel()
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
try {
|
try {
|
||||||
#if 0
|
|
||||||
test1();
|
test1();
|
||||||
test2();
|
test2();
|
||||||
#ifdef ONLY_32BIT
|
#ifdef ONLY_32BIT
|
||||||
|
@ -708,7 +746,6 @@ try {
|
||||||
testMovLabel(false);
|
testMovLabel(false);
|
||||||
testMovLabel(true);
|
testMovLabel(true);
|
||||||
testMovLabel2();
|
testMovLabel2();
|
||||||
#endif
|
|
||||||
testNewLabel();
|
testNewLabel();
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
printf("ERR:%s\n", e.what());
|
printf("ERR:%s\n", e.what());
|
||||||
|
|
|
@ -304,10 +304,14 @@ void jg(Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F,
|
||||||
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 XBYAK32
|
#ifdef XBYAK32
|
||||||
void jcxz(const std::string& label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); }
|
void jcxz(const std::string& label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); }
|
||||||
|
void jcxz(Label& label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); }
|
||||||
void jecxz(const std::string& label) { opJmp(label, T_SHORT, 0xe3, 0, 0); }
|
void jecxz(const std::string& label) { opJmp(label, T_SHORT, 0xe3, 0, 0); }
|
||||||
|
void jecxz(Label& label) { opJmp(label, T_SHORT, 0xe3, 0, 0); }
|
||||||
#else
|
#else
|
||||||
void jecxz(const std::string& label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); }
|
void jecxz(const std::string& label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); }
|
||||||
|
void jecxz(Label& label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); }
|
||||||
void jrcxz(const std::string& label) { opJmp(label, T_SHORT, 0xe3, 0, 0); }
|
void jrcxz(const std::string& label) { opJmp(label, T_SHORT, 0xe3, 0, 0); }
|
||||||
|
void jrcxz(Label& label) { opJmp(label, T_SHORT, 0xe3, 0, 0); }
|
||||||
#endif
|
#endif
|
||||||
#ifdef XBYAK64
|
#ifdef XBYAK64
|
||||||
void cdqe() { db(0x48); db(0x98); }
|
void cdqe() { db(0x48); db(0x98); }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue