add cvt{8,16,32,64} for Reg
This commit is contained in:
parent
b1aa238e9c
commit
702d6e6683
5 changed files with 178 additions and 4 deletions
|
@ -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
|
Abstract
|
||||||
|
@ -237,6 +237,7 @@ http://opensource.org/licenses/BSD-3-Clause
|
||||||
|
|
||||||
History
|
History
|
||||||
-------------
|
-------------
|
||||||
|
* 2013/Dec/03 ver 4.30 support Reg::cvt8(), cvt16(), cvt32(), cvt64()
|
||||||
* 2013/Oct/16 ver 4.21 label support std::string
|
* 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/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
|
* 2013/Jul/04 ver 4.10 [break backward compatibility] change the type of Xbyak::Error from enum to a class
|
||||||
|
|
|
@ -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/10/16 ver 4.21 ラベルでstd::stringを受け付ける。
|
||||||
2013/07/30 ver 4.20 [break backward compatibility] 従来のReg32eクラスをアドレッシング用のRegExpとReg32, Reg64を表すReg32eに分離
|
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に変更
|
2013/07/04 ver 4.10 [break backward compatibility] Xbyak::Errorの型をenumからclassに変更
|
||||||
|
|
125
test/cvt_test.cpp
Normal file
125
test/cvt_test.cpp
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
#include <xbyak/xbyak.h>
|
||||||
|
|
||||||
|
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<class T>
|
||||||
|
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());
|
||||||
|
}
|
|
@ -72,7 +72,7 @@ namespace Xbyak {
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
DEFAULT_MAX_CODE_SIZE = 4096,
|
DEFAULT_MAX_CODE_SIZE = 4096,
|
||||||
VERSION = 0x4210 /* 0xABCD = A.BC(D) */
|
VERSION = 0x4300 /* 0xABCD = A.BC(D) */
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef MIE_INTEGER_TYPE_DEFINED
|
#ifndef MIE_INTEGER_TYPE_DEFINED
|
||||||
|
@ -129,6 +129,7 @@ enum {
|
||||||
ERR_BAD_PNUM,
|
ERR_BAD_PNUM,
|
||||||
ERR_BAD_TNUM,
|
ERR_BAD_TNUM,
|
||||||
ERR_BAD_VSIB_ADDRESSING,
|
ERR_BAD_VSIB_ADDRESSING,
|
||||||
|
ERR_CANT_CONVERT,
|
||||||
ERR_INTERNAL
|
ERR_INTERNAL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -174,6 +175,7 @@ public:
|
||||||
"bad pNum",
|
"bad pNum",
|
||||||
"bad tNum",
|
"bad tNum",
|
||||||
"bad vsib addressing",
|
"bad vsib addressing",
|
||||||
|
"can't convert",
|
||||||
"internal error",
|
"internal error",
|
||||||
};
|
};
|
||||||
assert((size_t)err_ < sizeof(errTbl) / sizeof(*errTbl));
|
assert((size_t)err_ < sizeof(errTbl) / sizeof(*errTbl));
|
||||||
|
@ -337,6 +339,12 @@ public:
|
||||||
bool operator!=(const Operand& rhs) const { return !operator==(rhs); }
|
bool operator!=(const Operand& rhs) const { return !operator==(rhs); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Reg8;
|
||||||
|
struct Reg16;
|
||||||
|
struct Reg32;
|
||||||
|
#ifdef XBYAK64
|
||||||
|
struct Reg64;
|
||||||
|
#endif
|
||||||
class Reg : public Operand {
|
class Reg : public Operand {
|
||||||
bool hasRex() const { return isExt8bit() | isREG(64) | isExtIdx(); }
|
bool hasRex() const { return isExt8bit() | isREG(64) | isExtIdx(); }
|
||||||
public:
|
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;
|
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 {
|
struct Reg8 : public Reg {
|
||||||
|
@ -396,6 +410,39 @@ struct RegRip {
|
||||||
};
|
};
|
||||||
#endif
|
#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 {
|
class RegExp {
|
||||||
public:
|
public:
|
||||||
struct SReg {
|
struct SReg {
|
||||||
|
|
|
@ -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 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); }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue