aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMITSUNARI Shigeo <[email protected]>2019-09-05 21:52:55 +0900
committerMITSUNARI Shigeo <[email protected]>2019-09-05 21:52:55 +0900
commit06235fa6510ca7b0be92ca8c02a1383f6b8afe4d (patch)
tree347782a2ddca34b6480e48a3ec6b90b0e75e7cad
parent7fc0c2bb74e80f0aa1b5b25040131bf991a346c7 (diff)
downloadxbyak-06235fa6510ca7b0be92ca8c02a1383f6b8afe4d.tar.gz
xbyak-06235fa6510ca7b0be92ca8c02a1383f6b8afe4d.zip
add loop/loope/loopne
-rw-r--r--gen/gen_code.cpp16
-rw-r--r--test/jmp.cpp35
-rw-r--r--xbyak/xbyak_mnemonic.h9
3 files changed, 60 insertions, 0 deletions
diff --git a/gen/gen_code.cpp b/gen/gen_code.cpp
index 5ca982e..dae0c5e 100644
--- a/gen/gen_code.cpp
+++ b/gen/gen_code.cpp
@@ -616,6 +616,22 @@ void put()
printf("void set%s(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | %d); }%s\n", p->name, p->ext, msg);
}
}
+ {
+ const struct Tbl {
+ const char *name;
+ uint8 code;
+ } tbl[] = {
+ { "loop", 0xE2 },
+ { "loope", 0xE1 },
+ { "loopne", 0xE0 },
+ };
+ for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
+ const Tbl *p = &tbl[i];
+ printf("void %s(std::string label) { opJmp(label, T_SHORT, 0x%02X, 0, 0); }\n", p->name, p->code);
+ printf("void %s(const Label& label) { opJmp(label, T_SHORT, 0x%02X, 0, 0); }\n", p->name, p->code);
+ printf("void %s(const char *label) { %s(std::string(label)); }\n", p->name, p->name);
+ }
+ }
////////////////////////////////////////////////////////////////
{
const GenericTbl tbl[] = {
diff --git a/test/jmp.cpp b/test/jmp.cpp
index 9fe8ff6..4921a5a 100644
--- a/test/jmp.cpp
+++ b/test/jmp.cpp
@@ -205,6 +205,41 @@ CYBOZU_TEST_AUTO(testJmpCx)
}
}
+CYBOZU_TEST_AUTO(loop)
+{
+ const uint8 ok[] = {
+ // lp:
+ 0x31, 0xC0, // xor eax, eax
+ 0xE2, 0xFC, // loop lp
+ 0xE0, 0xFA, // loopne lp
+ 0xE1, 0xF8, // loope lp
+ };
+ struct Code : CodeGenerator {
+ Code(bool useLabel)
+ {
+ if (useLabel) {
+ Xbyak::Label lp = L();
+ xor_(eax, eax);
+ loop(lp);
+ loopne(lp);
+ loope(lp);
+ } else {
+ L("@@");
+ xor_(eax, eax);
+ loop("@b");
+ loopne("@b");
+ loope("@b");
+ }
+ }
+ };
+ Code code1(false);
+ CYBOZU_TEST_EQUAL(code1.getSize(), sizeof(ok));
+ CYBOZU_TEST_EQUAL_ARRAY(code1.getCode(), ok, sizeof(ok));
+ Code code2(true);
+ CYBOZU_TEST_EQUAL(code2.getSize(), sizeof(ok));
+ CYBOZU_TEST_EQUAL_ARRAY(code2.getCode(), ok, sizeof(ok));
+}
+
#ifdef _MSC_VER
#pragma warning(disable : 4310)
#endif
diff --git a/xbyak/xbyak_mnemonic.h b/xbyak/xbyak_mnemonic.h
index 2f2d768..b2fb1d8 100644
--- a/xbyak/xbyak_mnemonic.h
+++ b/xbyak/xbyak_mnemonic.h
@@ -446,6 +446,15 @@ void lock() { db(0xF0); }
void lodsb() { db(0xAC); }
void lodsd() { db(0xAD); }
void lodsw() { db(0x66); db(0xAD); }
+void loop(const Label& label) { opJmp(label, T_SHORT, 0xE2, 0, 0); }
+void loop(const char *label) { loop(std::string(label)); }
+void loop(std::string label) { opJmp(label, T_SHORT, 0xE2, 0, 0); }
+void loope(const Label& label) { opJmp(label, T_SHORT, 0xE1, 0, 0); }
+void loope(const char *label) { loope(std::string(label)); }
+void loope(std::string label) { opJmp(label, T_SHORT, 0xE1, 0, 0); }
+void loopne(const Label& label) { opJmp(label, T_SHORT, 0xE0, 0, 0); }
+void loopne(const char *label) { loopne(std::string(label)); }
+void loopne(std::string label) { opJmp(label, T_SHORT, 0xE0, 0, 0); }
void lzcnt(const Reg&reg, const Operand& op) { opSp1(reg, op, 0xF3, 0x0F, 0xBD); }
void maskmovdqu(const Xmm& reg1, const Xmm& reg2) { db(0x66); opModR(reg1, reg2, 0x0F, 0xF7); }
void maskmovq(const Mmx& reg1, const Mmx& reg2) { if (!reg1.isMMX() || !reg2.isMMX()) throw Error(ERR_BAD_COMBINATION); opModR(reg1, reg2, 0x0F, 0xF7); }