diff --git a/readme.md b/readme.md index b25e30b..8f34431 100644 --- a/readme.md +++ b/readme.md @@ -1,5 +1,5 @@ -Xbyak 4.21 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++ +Xbyak 4.30 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++ ============= Abstract @@ -237,6 +237,7 @@ http://opensource.org/licenses/BSD-3-Clause History ------------- +* 2013/Dec/03 ver 4.30 support Reg::cvt8(), cvt16(), cvt32(), cvt64() * 2013/Oct/16 ver 4.21 label support std::string * 2013/Jul/30 ver 4.20 [break backward compatibility] split Reg32e class into RegExp(base+index*scale+disp) and Reg32e(means Reg32 or Reg64) * 2013/Jul/04 ver 4.10 [break backward compatibility] change the type of Xbyak::Error from enum to a class diff --git a/readme.txt b/readme.txt index 93e9d84..f8fc328 100644 --- a/readme.txt +++ b/readme.txt @@ -1,5 +1,5 @@ - C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak 4.21 + C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak 4.30 ----------------------------------------------------------------------------- ◎概要 @@ -252,6 +252,7 @@ sample/{echo,hello}.bfは http://www.kmonos.net/alang/etc/brainfuck.php から ----------------------------------------------------------------------------- ◎履歴 +2013/12/03 ver 4.30 Reg::cvt8(), cvt16(), cvt32()のサポート 2013/10/16 ver 4.21 ラベルでstd::stringを受け付ける。 2013/07/30 ver 4.20 [break backward compatibility] 従来のReg32eクラスをアドレッシング用のRegExpとReg32, Reg64を表すReg32eに分離 2013/07/04 ver 4.10 [break backward compatibility] Xbyak::Errorの型をenumからclassに変更 diff --git a/test/cvt_test.cpp b/test/cvt_test.cpp new file mode 100644 index 0000000..cce7613 --- /dev/null +++ b/test/cvt_test.cpp @@ -0,0 +1,125 @@ +#include + +using namespace Xbyak; +using namespace Xbyak::util; + +#ifdef XBYAK64 +const struct Ptn { + const Reg8 *reg8; + Reg16 reg16; + Reg32 reg32; + Reg64 reg64; +} tbl[] = { + { &al, ax, eax, rax }, + { &bl, bx, ebx, rbx }, + { &cl, cx, ecx, rcx }, + { &dl, dx, edx, rdx }, + { &sil, si, esi, rsi }, + { &dil, di, edi, rdi }, + { &bpl, bp, ebp, rbp }, + { &spl, sp, esp, rsp }, + { &r8b, r8w, r8d, r8 }, + { &r9b, r9w, r9d, r9 }, + { &r10b, r10w, r10d, r10 }, + { &r11b, r11w, r11d, r11 }, + { &r12b, r12w, r12d, r12 }, + { &r13b, r13w, r13d, r13 }, + { &r14b, r14w, r14d, r14 }, + { &r15b, r15w, r15d, r15 }, +}; +#else +const struct Ptn { + const Reg8 *reg8; + Reg16 reg16; + Reg32 reg32; +} tbl[] = { + { &al, ax, eax }, + { &bl, bx, ebx }, + { &cl, cx, ecx }, + { &dl, dx, edx }, + { 0, si, esi }, + { 0, di, edi }, + { 0, bp, ebp }, + { 0, sp, esp }, +}; +#endif + +int errNum = 0; +int testNum = 0; + +template +void verify(const T& x, const T& y) +{ + if (x != y) { + printf("ERR %s %s\n", x.toString(), y.toString()); + errNum++; + } + testNum++; +} + +#define verifyExp(state) \ +{ \ + bool isOK = false; \ + try { \ + state; \ + } catch (const Xbyak::Error& e) { \ + if ((int)e == ERR_CANT_CONVERT) { \ + isOK = true; \ + } \ + } \ + if (!isOK) { \ + printf("ERR " #state "\n"); \ + errNum++; \ + } \ + testNum++; \ +} + +int main() + try +{ + for (size_t i = 0; i < sizeof(tbl) / sizeof(tbl[0]); i++) { + if (tbl[i].reg8) { + verify(tbl[i].reg8->cvt8(), *tbl[i].reg8); + verify(tbl[i].reg8->cvt16(), tbl[i].reg16); + verify(tbl[i].reg8->cvt32(), tbl[i].reg32); + verify(tbl[i].reg16.cvt8(), *tbl[i].reg8); + verify(tbl[i].reg32.cvt8(), *tbl[i].reg8); + } + verify(tbl[i].reg16.cvt16(), tbl[i].reg16); + verify(tbl[i].reg16.cvt32(), tbl[i].reg32); + verify(tbl[i].reg32.cvt16(), tbl[i].reg16); + verify(tbl[i].reg32.cvt32(), tbl[i].reg32); +#ifdef XBYAK64 + if (tbl[i].reg8) { + verify(tbl[i].reg64.cvt8(), *tbl[i].reg8); + verify(tbl[i].reg8->cvt64(), tbl[i].reg64); + } + verify(tbl[i].reg64.cvt16(), tbl[i].reg16); + verify(tbl[i].reg64.cvt32(), tbl[i].reg32); + verify(tbl[i].reg64.cvt64(), tbl[i].reg64); + verify(tbl[i].reg16.cvt64(), tbl[i].reg64); + verify(tbl[i].reg32.cvt64(), tbl[i].reg64); +#endif + } + { + const Reg8 errTbl[] = { + ah, bh, ch, dh + }; + for (size_t i = 0; i < sizeof(errTbl) / sizeof(errTbl[0]); i++) { + verifyExp(errTbl[i].cvt16()); + } + } +#ifdef XBYAK32 + { + const Reg16 errTbl[] = { + si, di, bp, sp + }; + for (size_t i = 0; i < sizeof(errTbl) / sizeof(errTbl[0]); i++) { + verifyExp(errTbl[i].cvt8()); + } + } +#endif + printf("test=%d(err=%d)\n", testNum, errNum); +} catch (std::exception& e) { + printf("ERR %s\n", e.what()); +} diff --git a/xbyak/xbyak.h b/xbyak/xbyak.h index 2f1bca2..ac670d0 100644 --- a/xbyak/xbyak.h +++ b/xbyak/xbyak.h @@ -72,7 +72,7 @@ namespace Xbyak { enum { DEFAULT_MAX_CODE_SIZE = 4096, - VERSION = 0x4210 /* 0xABCD = A.BC(D) */ + VERSION = 0x4300 /* 0xABCD = A.BC(D) */ }; #ifndef MIE_INTEGER_TYPE_DEFINED @@ -129,6 +129,7 @@ enum { ERR_BAD_PNUM, ERR_BAD_TNUM, ERR_BAD_VSIB_ADDRESSING, + ERR_CANT_CONVERT, ERR_INTERNAL }; @@ -174,6 +175,7 @@ public: "bad pNum", "bad tNum", "bad vsib addressing", + "can't convert", "internal error", }; assert((size_t)err_ < sizeof(errTbl) / sizeof(*errTbl)); @@ -337,6 +339,12 @@ public: bool operator!=(const Operand& rhs) const { return !operator==(rhs); } }; +struct Reg8; +struct Reg16; +struct Reg32; +#ifdef XBYAK64 +struct Reg64; +#endif class Reg : public Operand { bool hasRex() const { return isExt8bit() | isREG(64) | isExtIdx(); } public: @@ -348,6 +356,12 @@ public: { return (hasRex() || base.hasRex()) ? uint8(0x40 | ((isREG(64) | base.isREG(64)) ? 8 : 0) | (isExtIdx() ? 4 : 0)| (base.isExtIdx() ? 1 : 0)) : 0; } + Reg8 cvt8() const; + Reg16 cvt16() const; + Reg32 cvt32() const; +#ifdef XBYAK64 + Reg64 cvt64() const; +#endif }; struct Reg8 : public Reg { @@ -396,6 +410,39 @@ struct RegRip { }; #endif +inline Reg8 Reg::cvt8() const +{ + const int idx = getIdx(); + if (isBit(8)) return Reg8(idx, isExt8bit()); +#ifdef XBYAK32 + if (idx >= 4) throw Error(ERR_CANT_CONVERT); +#endif + return Reg8(idx, 4 <= idx && idx < 8); +} + +inline Reg16 Reg::cvt16() const +{ + const int idx = getIdx(); + if (isBit(8) && (4 <= idx && idx < 8) && !isExt8bit()) throw Error(ERR_CANT_CONVERT); + return Reg16(idx); +} + +inline Reg32 Reg::cvt32() const +{ + const int idx = getIdx(); + if (isBit(8) && (4 <= idx && idx < 8) && !isExt8bit()) throw Error(ERR_CANT_CONVERT); + return Reg32(idx); +} + +#ifdef XBYAK64 +inline Reg64 Reg::cvt64() const +{ + const int idx = getIdx(); + if (isBit(8) && (4 <= idx && idx < 8) && !isExt8bit()) throw Error(ERR_CANT_CONVERT); + return Reg64(idx); +} +#endif + class RegExp { public: struct SReg { diff --git a/xbyak/xbyak_mnemonic.h b/xbyak/xbyak_mnemonic.h index a8f2e95..928b7f8 100644 --- a/xbyak/xbyak_mnemonic.h +++ b/xbyak/xbyak_mnemonic.h @@ -1,4 +1,4 @@ -const char *getVersionString() const { return "4.21"; } +const char *getVersionString() const { return "4.30"; } 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 packuswb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x67); }