use 32bit extended encoding for mov(reg64, imm)

This commit is contained in:
MITSUNARI Shigeo 2010-06-01 16:28:14 +09:00
parent 2965c4c0ba
commit ba203dc894
15 changed files with 6359 additions and 461 deletions

View File

@ -1,5 +1,5 @@
C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak version 2.26 C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak version 2.27
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
◎概要 ◎概要
@ -199,6 +199,7 @@ sample/{echo,hello}.bfは http://www.kmonos.net/alang/etc/brainfuck.php から
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
◎履歴 ◎履歴
2010/06/01 ver 2.27 support encoding of mov(reg64, imm) like yasm(not nasm)
2010/05/24 ver 2.26 fix sub(rsp, 1000) 2010/05/24 ver 2.26 fix sub(rsp, 1000)
2010/04/26 ver 2.25 add jc/jnc(I forgot to implement them...) 2010/04/26 ver 2.25 add jc/jnc(I forgot to implement them...)
2010/04/16 ver 2.24 change the prototype of rewrite() method 2010/04/16 ver 2.24 change the prototype of rewrite() method

View File

@ -1,5 +1,5 @@
Xbyak 2.26 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++ Xbyak 2.27 ; JIT assembler for x86(IA32), x64(AMD64, x86-64) by C++
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
<Abstract> <Abstract>
@ -148,6 +148,7 @@ http://www.opensource.org/licenses/bsd-license.php
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
<History> <History>
2010/Jun/01 ver 2.27 support encoding of mov(reg64, imm) like yasm(not nasm)
2010/May/24 ver 2.26 fix sub(rsp, 1000) 2010/May/24 ver 2.26 fix sub(rsp, 1000)
2010/Apr/26 ver 2.25 add jc/jnc(I forgot to implement them...) 2010/Apr/26 ver 2.25 add jc/jnc(I forgot to implement them...)
2010/Apr/16 ver 2.24 change the prototype of rewrite() method 2010/Apr/16 ver 2.24 change the prototype of rewrite() method
@ -184,5 +185,5 @@ http://www.opensource.org/licenses/bsd-license.php
MITSUNARI Shigeo(herumi at nifty dot com) MITSUNARI Shigeo(herumi at nifty dot com)
--- ---
$Revision: 1.46 $ $Revision: 1.47 $
$Date: 2010/05/24 06:13:44 $ $Date: 2010/06/01 01:21:39 $

View File

@ -20,12 +20,17 @@ normalize_prefix: normalize_prefix.cpp
g++ $(CFLAGS) normalize_prefix.cpp -o $@ g++ $(CFLAGS) normalize_prefix.cpp -o $@
test_mmx: test_mmx.cpp test_mmx: test_mmx.cpp
g++ $(CFLAGS) test_mmx.cpp -o $@ -lpthread g++ $(CFLAGS) test_mmx.cpp -o $@ -lpthread
jmp: jmp.cpp
g++ $(CFLAGS) jmp.cpp -o $@
test: normalize_prefix test: normalize_prefix jmp
./test_nm.sh ./test_nm.sh
./test_nm.sh Y ./test_nm.sh Y
./test_nm.sh 64 ./test_nm.sh 64
./test_nm.sh Y64 ./test_nm.sh Y64
./test_address.sh
./test_address.sh 64
./jmp
clean: clean:
rm -rf *.o $(TARGET) rm -rf *.o $(TARGET)

View File

@ -5,16 +5,21 @@
void genAddress(bool isJIT, const char regTbl[][5], size_t regTblNum) void genAddress(bool isJIT, const char regTbl[][5], size_t regTblNum)
{ {
int count = 0;
int funcNum = 1;
if (isJIT) {
puts("void gen0(){");
}
for (size_t i = 0; i < regTblNum + 1; i++) { for (size_t i = 0; i < regTblNum + 1; i++) {
const char *base = regTbl[i]; const char *base = regTbl[i];
for (size_t j = 0; j < regTblNum + 1; j++) { for (size_t j = 0; j < regTblNum + 1; j++) {
if (j == 4) continue; /* esp is not index register */ if (j == 4) continue; /* esp is not index register */
const char *index = regTbl[j]; const char *index = regTbl[j];
static const int scaleTbl[] = { 0, 1, 2, 4, 8 }; static const int scaleTbl[] = { 0, 1, 2, 4, 8 };
for (int k = 0; k < NUM_OF_ARRAY(scaleTbl); k++) { for (size_t k = 0; k < NUM_OF_ARRAY(scaleTbl); k++) {
int scale = scaleTbl[k]; int scale = scaleTbl[k];
static const int dispTbl[] = { 0, 1, 1000, -1, -1000 }; static const int dispTbl[] = { 0, 1, 1000, -1, -1000 };
for (int m = 0; m < NUM_OF_ARRAY(dispTbl); m++) { for (size_t m = 0; m < NUM_OF_ARRAY(dispTbl); m++) {
int disp = dispTbl[m]; int disp = dispTbl[m];
bool isFirst = true; bool isFirst = true;
if (isJIT) { if (isJIT) {
@ -47,10 +52,23 @@ void genAddress(bool isJIT, const char regTbl[][5], size_t regTblNum)
} else { } else {
printf("]\n"); printf("]\n");
} }
if (isJIT) {
count++;
if ((count % 100) == 0) {
printf("}\n void gen%d(){\n", funcNum++);
}
}
} }
} }
} }
} }
if (isJIT) {
printf("}\nvoid gen(){\n");
for (int i = 0; i < funcNum; i++) {
printf(" gen%d();\n", i);
}
printf("}\n");
}
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
@ -60,6 +78,7 @@ int main(int argc, char *argv[])
bool isJIT = (argc > 1); bool isJIT = (argc > 1);
fprintf(stderr, "phase:%c %s\n", phase ? '1' : '2', isJIT ? "jit" : "asm"); fprintf(stderr, "phase:%c %s\n", phase ? '1' : '2', isJIT ? "jit" : "asm");
if (phase) { if (phase) {
fprintf(stderr, "32bit reg\n");
static const char reg32Tbl[][5] = { static const char reg32Tbl[][5] = {
"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
#ifdef XBYAK64 #ifdef XBYAK64
@ -69,6 +88,7 @@ int main(int argc, char *argv[])
genAddress(isJIT, reg32Tbl, NUM_OF_ARRAY(reg32Tbl)); genAddress(isJIT, reg32Tbl, NUM_OF_ARRAY(reg32Tbl));
} else { } else {
#ifdef XBYAK64 #ifdef XBYAK64
fprintf(stderr, "64bit reg\n");
static const char reg64Tbl[][5] = { static const char reg64Tbl[][5] = {
"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
}; };

View File

@ -1,4 +1,5 @@
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include "xbyak/xbyak.h" #include "xbyak/xbyak.h"
#define NUM_OF_ARRAY(x) (sizeof(x) / sizeof(x[0])) #define NUM_OF_ARRAY(x) (sizeof(x) / sizeof(x[0]))
@ -82,13 +83,13 @@ int main()
{ 127, false, true, "EB7F" }, { 127, false, true, "EB7F" },
{ 128, false, false, "E980000000" }, { 128, false, false, "E980000000" },
}; };
for (int 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); TestJmp jmp(p->offset, p->isBack, p->isShort);
const uint8 *q = (const uint8*)jmp.getCode(); const uint8 *q = (const uint8*)jmp.getCode();
char buf[32]; char buf[32];
if (p->isBack) q += p->offset; /* skip nop */ if (p->isBack) q += p->offset; /* skip nop */
for (int j = 0; j < jmp.getSize() - p->offset; j++) { for (size_t j = 0; j < jmp.getSize() - p->offset; j++) {
sprintf(&buf[j * 2], "%02X", q[j]); sprintf(&buf[j * 2], "%02X", q[j]);
} }
if (strcmp(buf, p->result) != 0) { if (strcmp(buf, p->result) != 0) {

View File

@ -62,6 +62,7 @@ const uint64 NOPARA = 1ULL << (bitEnd - 1);
class Test { class Test {
const bool isXbyak_; const bool isXbyak_;
int funcNum_;
// check all op1, op2, op3 // check all op1, op2, op3
void put(const char *nm, uint64 op1 = NOPARA, uint64 op2 = NOPARA, uint64 op3 = NOPARA) const void put(const char *nm, uint64 op1 = NOPARA, uint64 op2 = NOPARA, uint64 op3 = NOPARA) const
{ {
@ -811,6 +812,31 @@ class Test {
put(p, REG8|REG8_3|MEM, REG8|REG8_3); put(p, REG8|REG8_3|MEM, REG8|REG8_3);
put(p, REG32e|REG16|REG8|REG8_3|EAX|AX|AL|MEM32|MEM16|MEM8, IMM); put(p, REG32e|REG16|REG8|REG8_3|EAX|AX|AL|MEM32|MEM16|MEM8, IMM);
} }
void putMov64() const
{
const struct {
const char *a;
const char *b;
} tbl[] = {
{ "0", "dword 0" },
{ "0x123", "dword 0x123" },
{ "0x12345678", "dword 0x12345678" },
{ "0x7fffffff", "dword 0x7fffffff" },
{ "0xffffffff", "0xffffffff" },
{ "0x80000000", "0x80000000" },
{ "2147483648U", "2147483648" },
{ "0x80000001", "0x80000001" },
{ "0xffffffffffffffff", "dword 0xffffffffffffffff" },
{ "-1", "dword -1" },
{ "0xffffffff80000000", "dword 0xffffffff80000000" },
{ "0xffffffff80000001", "dword 0xffffffff80000001" },
{ "0xffffffff12345678", "0xffffffff12345678" },
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
put("mov", REG64, tbl[i].a, tbl[i].b);
}
put("mov", REG32e|REG16|REG8|RAX|EAX|AX|AL, IMM);
}
void putEtc() const void putEtc() const
{ {
const char *p = "ret"; const char *p = "ret";
@ -821,7 +847,7 @@ class Test {
put(p, REG64|MEM|MEM_ONLY_DISP, REG64|RAX); put(p, REG64|MEM|MEM_ONLY_DISP, REG64|RAX);
put(p, AX|REG16|MEM|MEM_ONLY_DISP, REG16|AX); put(p, AX|REG16|MEM|MEM_ONLY_DISP, REG16|AX);
put(p, AL|REG8|REG8_3|MEM|MEM_ONLY_DISP, REG8|REG8_3|AL); put(p, AL|REG8|REG8_3|MEM|MEM_ONLY_DISP, REG8|REG8_3|AL);
put(p, REG32e|REG16|REG8|RAX|EAX|AX|AL, MEM|IMM|MEM_ONLY_DISP); put(p, REG32e|REG16|REG8|RAX|EAX|AX|AL, MEM|MEM_ONLY_DISP);
put(p, MEM32|MEM16|MEM8, IMM); put(p, MEM32|MEM16|MEM8, IMM);
put(p, REG64, "0x1234567890abcdefLL", "0x1234567890abcdef"); put(p, REG64, "0x1234567890abcdefLL", "0x1234567890abcdef");
#ifdef XBYAK64 #ifdef XBYAK64
@ -1117,32 +1143,72 @@ class Test {
public: public:
Test(bool isXbyak) Test(bool isXbyak)
: isXbyak_(isXbyak) : isXbyak_(isXbyak)
, funcNum_(1)
{ {
if (!isXbyak_) return;
printf("%s",
" void gen0()\n"
" {\n");
} }
void put() const /*
gcc and vc give up to compile this source,
so I split functions.
*/
void separateFunc()
{
if (!isXbyak_) return;
printf(
" }\n"
" void gen%d()\n"
" {\n", funcNum_++);
}
~Test()
{
if (!isXbyak_) return;
printf("%s",
" }\n"
" void gen()\n"
" {\n");
for (int i = 0; i < funcNum_; i++) {
printf(
" gen%d();\n", i);
}
printf(
" }\n");
}
void put()
{ {
#ifndef USE_YASM #ifndef USE_YASM
putSIMPLE(); putSIMPLE();
putReg1(); putReg1();
putRorM(); putRorM();
separateFunc();
putPushPop(); putPushPop();
putTest(); putTest();
separateFunc();
putEtc(); putEtc();
putShift(); putShift();
putShxd(); putShxd();
separateFunc();
putBs(); putBs();
putMMX1(); putMMX1();
putMMX2(); putMMX2();
separateFunc();
putMMX3(); putMMX3();
putMMX4(); putMMX4();
putMMX5(); putMMX5();
separateFunc();
putXMM1(); putXMM1();
putXMM2(); putXMM2();
putXMM3(); putXMM3();
putXMM4(); putXMM4();
separateFunc();
putCmov(); putCmov();
putFpuMem16_32(); putFpuMem16_32();
putFpuMem32_64(); putFpuMem32_64();
separateFunc();
putFpuMem16_32_64(); putFpuMem16_32_64();
put("clflush", MEM); // current nasm is ok put("clflush", MEM); // current nasm is ok
putFpu(); putFpu();
@ -1150,7 +1216,9 @@ public:
putFpuFpu(); putFpuFpu();
putSSSE3(); putSSSE3();
putSSE4_1(); putSSE4_1();
separateFunc();
putSSE4_2(); putSSE4_2();
putMov64();
#endif #endif
} }
}; };
@ -1160,4 +1228,3 @@ int main(int argc, char *[])
Test test(argc > 1); Test test(argc > 1);
test.put(); test.put();
} }

File diff suppressed because it is too large Load Diff

View File

@ -6,21 +6,9 @@ using namespace Xbyak;
class Sample : public CodeGenerator { class Sample : public CodeGenerator {
void operator=(const Sample&); void operator=(const Sample&);
public: public:
void gen()
{
try {
#include "nm.cpp" #include "nm.cpp"
} catch (Xbyak::Error err) {
printf("ERR:%s(%d)\n", ConvertErrorToString(err), err);
} catch (...) {
printf("unkwon error\n");
}
}
}; };
#define _STR(x) #x #define _STR(x) #x
#define TEST(syntax) err = true; try { syntax; err = false; } catch (Xbyak::Error) { } catch (...) { } if (!err) printf("should be err:%s;\n", _STR(syntax)) #define TEST(syntax) err = true; try { syntax; err = false; } catch (Xbyak::Error) { } catch (...) { } if (!err) printf("should be err:%s;\n", _STR(syntax))
@ -38,8 +26,14 @@ public:
}; };
int main() int main()
{ {
Sample s; try {
s.gen(); Sample s;
s.gen();
} catch (Xbyak::Error err) {
printf("ERR:%s(%d)\n", Xbyak::ConvertErrorToString(err), err);
} catch (...) {
printf("unknown error\n");
}
ErrorSample es; ErrorSample es;
es.gen(); es.gen();
} }

View File

@ -3,7 +3,7 @@ if /i "%1"=="64" (
set OPT2=-DXBYAK64 set OPT2=-DXBYAK64
set OPT3=win64 set OPT3=win64
) else ( ) else (
set OPT2= set OPT2=-DXBYAK32
set OPT3=win32 set OPT3=win32
) )
@ -20,12 +20,16 @@ if /i "%1"=="64" (
goto end goto end
:sub :sub
echo cl address.cpp %OPT% %OPT2%
cl address.cpp %OPT% %OPT2% cl address.cpp %OPT% %OPT2%
address %1% > a.asm address %1% > a.asm
echo nasm -f %OPT3% -l a.lst a.asm
nasm -f %OPT3% -l a.lst a.asm nasm -f %OPT3% -l a.lst a.asm
awk "{print $3}" < a.lst > ok.lst awk "{print $3}" < a.lst > ok.lst
echo address %1% jit > nm.cpp
address %1% jit > nm.cpp address %1% jit > nm.cpp
cl -I../ -DTEST_NM nm_frame.cpp %OPT% %OPT2% echo cl -I../ -DXBYAK_TEST nm_frame.cpp %OPT% %OPT2%
cl -I../ -DXBYAK_TEST nm_frame.cpp %OPT% %OPT2%
nm_frame > x.lst nm_frame > x.lst
diff x.lst ok.lst diff x.lst ok.lst
wc x.lst wc x.lst

View File

@ -1,5 +1,5 @@
pushd ..\gen pushd ..\gen
call update call update
popd popd
cl -I../ -DTEST_NM jmp.cpp %OPT% cl -I../ -DXBYAK_TEST jmp.cpp %OPT%
jmp jmp

View File

@ -18,8 +18,8 @@ if /i "%1"=="Y" (
set OPT3=win64 set OPT3=win64
set FILTER=normalize_prefix set FILTER=normalize_prefix
) else ( ) else (
set EXE=nasm.exe -DXBYAK32 set EXE=nasm.exe
set OPT2= set OPT2=-DXBYAK32
set OPT3=win32 set OPT3=win32
) )
pushd ..\gen pushd ..\gen
@ -36,7 +36,7 @@ if /i "%Y%"=="1" (
awk "{if (index($3, ""-"")) { conti=substr($3, 0, length($3) - 1) } else { conti = conti $3; print conti; conti = """" }} " < a.lst |%FILTER% > ok.lst awk "{if (index($3, ""-"")) { conti=substr($3, 0, length($3) - 1) } else { conti = conti $3; print conti; conti = """" }} " < a.lst |%FILTER% > ok.lst
) )
make_nm jit > nm.cpp make_nm jit > nm.cpp
cl -I../ -DTEST_NM nm_frame.cpp %OPT% %OPT2% cl -I../ -DXBYAK_TEST nm_frame.cpp %OPT% %OPT2%
nm_frame |%FILTER% > x.lst nm_frame |%FILTER% > x.lst
diff x.lst ok.lst diff x.lst ok.lst
wc x.lst wc x.lst

View File

@ -36,7 +36,7 @@ awk '{if (index($3, "-")) { conti=substr($3, 0, length($3) - 1) } else { conti =
echo "xbyak" echo "xbyak"
./make_nm jit > nm.cpp ./make_nm jit > nm.cpp
echo "compile nm_frame.cpp" echo "compile nm_frame.cpp"
g++ $CFLAGS -DTEST_NM nm_frame.cpp -o nm_frame g++ $CFLAGS -DXBYAK_TEST nm_frame.cpp -o nm_frame
./nm_frame | $FILTER > x.lst ./nm_frame | $FILTER > x.lst
diff ok.lst x.lst && echo "ok" diff ok.lst x.lst && echo "ok"
exit 0 exit 0

View File

@ -4,9 +4,9 @@
@file xbyak.h @file xbyak.h
@brief Xbyak ; JIT assembler for x86(IA32)/x64 by C++ @brief Xbyak ; JIT assembler for x86(IA32)/x64 by C++
@author herumi @author herumi
@version $Revision: 1.188 $ @version $Revision: 1.191 $
@url http://homepage1.nifty.com/herumi/soft/xbyak.html @url http://homepage1.nifty.com/herumi/soft/xbyak.html
@date $Date: 2010/05/24 06:13:44 $ @date $Date: 2010/06/01 05:26:11 $
@note modified new BSD license @note modified new BSD license
http://www.opensource.org/licenses/bsd-license.php http://www.opensource.org/licenses/bsd-license.php
*/ */
@ -55,7 +55,7 @@ namespace Xbyak {
enum { enum {
DEFAULT_MAX_CODE_SIZE = 2048, DEFAULT_MAX_CODE_SIZE = 2048,
VERSION = 0x2260, /* 0xABCD = A.BC(D) */ VERSION = 0x2270, /* 0xABCD = A.BC(D) */
}; };
#ifndef MIE_INTEGER_TYPE_DEFINED #ifndef MIE_INTEGER_TYPE_DEFINED
@ -144,7 +144,7 @@ namespace inner {
enum { debug = 1 }; enum { debug = 1 };
static inline uint32 GetPtrDist(const void *p1, const void *p2 = 0) static inline uint32 GetPtrDist(const void *p1, const void *p2)
{ {
uint64 diff = static_cast<const char *>(p1) - static_cast<const char *>(p2); uint64 diff = static_cast<const char *>(p1) - static_cast<const char *>(p2);
#ifdef XBYAK64 #ifdef XBYAK64
@ -154,6 +154,7 @@ static inline uint32 GetPtrDist(const void *p1, const void *p2 = 0)
} }
static inline bool IsInDisp8(uint32 x) { return 0xFFFFFF80 <= x || x <= 0x7F; } static inline bool IsInDisp8(uint32 x) { return 0xFFFFFF80 <= x || x <= 0x7F; }
static inline bool IsInInt32(uint64 x) { return 0xFFFFFFFF80000000ULL <= x || x <= 0x7FFFFFFFU; }
} }
@ -555,7 +556,11 @@ public:
explicit AddressFrame(uint32 bit) : bit_(bit) { } explicit AddressFrame(uint32 bit) : bit_(bit) { }
Address operator[](const void *disp) const Address operator[](const void *disp) const
{ {
Reg32e r(Reg(), Reg(), 0, inner::GetPtrDist(disp)); size_t adr = reinterpret_cast<size_t>(disp);
#ifdef XBYAK64
if (adr > 0xFFFFFFFFU) throw ERR_OFFSET_IS_TOO_BIG;
#endif
Reg32e r(Reg(), Reg(), 0, adr);
return operator[](r); return operator[](r);
} }
#ifdef XBYAK64 #ifdef XBYAK64
@ -1216,13 +1221,32 @@ protected:
opRM_RM(reg1, reg2, B10001000); opRM_RM(reg1, reg2, B10001000);
} }
} }
void mov(const Operand& op, uint64 imm) void mov(const Operand& op,
#ifdef XBYAK64
uint64
#else
uint32
#endif
imm)
{ {
verifyMemHasSize(op); verifyMemHasSize(op);
if (op.isREG()) { if (op.isREG()) {
int w = op.isBit(8) ? 0 : 1; rex(op);
rex(op); db(B10110000 | (w << 3) | (op.getIdx() & 7)); int code, size;
db(imm, op.getBit() / 8); #ifdef XBYAK64
if (op.isBit(64) && inner::IsInInt32(imm)) {
db(B11000111);
code = B11000000;
size = 4;
} else
#endif
{
code = B10110000 | ((op.isBit(8) ? 0 : 1) << 3);
size = op.getBit() / 8;
}
db(code | (op.getIdx() & 7));
db(imm, size);
} else if (op.isMEM()) { } else if (op.isMEM()) {
opModM(static_cast<const Address&>(op), Reg(0, Operand::REG, op.getBit()), B11000110); opModM(static_cast<const Address&>(op), Reg(0, Operand::REG, op.getBit()), B11000110);
int size = op.getBit() / 8; if (size > 4) size = 4; int size = op.getBit() / 8; if (size > 4) size = 4;
@ -1398,7 +1422,7 @@ public:
// if (hasUndefinedLabel()) throw ERR_LABEL_IS_NOT_FOUND; // if (hasUndefinedLabel()) throw ERR_LABEL_IS_NOT_FOUND;
return top_; return top_;
} }
#ifdef TEST_NM #ifdef XBYAK_TEST
void dump(bool doClear = true) void dump(bool doClear = true)
{ {
CodeArray::dump(); CodeArray::dump();

View File

@ -1,4 +1,4 @@
const char *getVersionString() const { return "2.26"; } const char *getVersionString() const { return "2.27"; }
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); }

View File

@ -95,25 +95,25 @@ public:
if (data[2] == get32bitAsBE(amd)) { if (data[2] == get32bitAsBE(amd)) {
type_ |= tAMD; type_ |= tAMD;
getCpuid(0x80000001, data); getCpuid(0x80000001, data);
if (data[3] & (1 << 31)) type_ |= t3DN; if (data[3] & (1U << 31)) type_ |= t3DN;
if (data[3] & (1 << 15)) type_ |= tCMOV; if (data[3] & (1U << 15)) type_ |= tCMOV;
if (data[3] & (1 << 30)) type_ |= tE3DN; if (data[3] & (1U << 30)) type_ |= tE3DN;
if (data[3] & (1 << 22)) type_ |= tMMX2; if (data[3] & (1U << 22)) type_ |= tMMX2;
} }
if (data[2] == get32bitAsBE(intel)) { if (data[2] == get32bitAsBE(intel)) {
type_ |= tINTEL; type_ |= tINTEL;
} }
getCpuid(1, data); getCpuid(1, data);
if (data[2] & (1 << 0)) type_ |= tSSE3; if (data[2] & (1U << 0)) type_ |= tSSE3;
if (data[2] & (1 << 9)) type_ |= tSSSE3; if (data[2] & (1U << 9)) type_ |= tSSSE3;
if (data[2] & (1 << 19)) type_ |= tSSE41; if (data[2] & (1U << 19)) type_ |= tSSE41;
if (data[2] & (1 << 20)) type_ |= tSSE42; if (data[2] & (1U << 20)) type_ |= tSSE42;
if (data[2] & (1 << 23)) type_ |= tPOPCNT; if (data[2] & (1U << 23)) type_ |= tPOPCNT;
if (data[3] & (1 << 15)) type_ |= tCMOV; if (data[3] & (1U << 15)) type_ |= tCMOV;
if (data[3] & (1 << 23)) type_ |= tMMX; if (data[3] & (1U << 23)) type_ |= tMMX;
if (data[3] & (1 << 25)) type_ |= tMMX2 | tSSE; if (data[3] & (1U << 25)) type_ |= tMMX2 | tSSE;
if (data[3] & (1 << 26)) type_ |= tSSE2; if (data[3] & (1U << 26)) type_ |= tSSE2;
} }
bool has(Type type) const bool has(Type type) const
{ {