mirror of
https://github.com/herumi/xbyak
synced 2024-11-20 16:06:14 -07:00
use 32bit extended encoding for mov(reg64, imm)
This commit is contained in:
parent
2965c4c0ba
commit
ba203dc894
15 changed files with 6359 additions and 461 deletions
|
@ -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/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
|
||||
|
|
|
@ -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>
|
||||
|
@ -148,6 +148,7 @@ http://www.opensource.org/licenses/bsd-license.php
|
|||
-----------------------------------------------------------------------------
|
||||
<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/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
|
||||
|
@ -184,5 +185,5 @@ http://www.opensource.org/licenses/bsd-license.php
|
|||
MITSUNARI Shigeo(herumi at nifty dot com)
|
||||
|
||||
---
|
||||
$Revision: 1.46 $
|
||||
$Date: 2010/05/24 06:13:44 $
|
||||
$Revision: 1.47 $
|
||||
$Date: 2010/06/01 01:21:39 $
|
||||
|
|
|
@ -20,12 +20,17 @@ normalize_prefix: normalize_prefix.cpp
|
|||
g++ $(CFLAGS) normalize_prefix.cpp -o $@
|
||||
test_mmx: test_mmx.cpp
|
||||
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 Y
|
||||
./test_nm.sh 64
|
||||
./test_nm.sh Y64
|
||||
./test_address.sh
|
||||
./test_address.sh 64
|
||||
./jmp
|
||||
|
||||
clean:
|
||||
rm -rf *.o $(TARGET)
|
||||
|
|
|
@ -5,16 +5,21 @@
|
|||
|
||||
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++) {
|
||||
const char *base = regTbl[i];
|
||||
for (size_t j = 0; j < regTblNum + 1; j++) {
|
||||
if (j == 4) continue; /* esp is not index register */
|
||||
const char *index = regTbl[j];
|
||||
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];
|
||||
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];
|
||||
bool isFirst = true;
|
||||
if (isJIT) {
|
||||
|
@ -47,10 +52,23 @@ void genAddress(bool isJIT, const char regTbl[][5], size_t regTblNum)
|
|||
} else {
|
||||
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[])
|
||||
|
@ -60,6 +78,7 @@ int main(int argc, char *argv[])
|
|||
bool isJIT = (argc > 1);
|
||||
fprintf(stderr, "phase:%c %s\n", phase ? '1' : '2', isJIT ? "jit" : "asm");
|
||||
if (phase) {
|
||||
fprintf(stderr, "32bit reg\n");
|
||||
static const char reg32Tbl[][5] = {
|
||||
"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi",
|
||||
#ifdef XBYAK64
|
||||
|
@ -69,6 +88,7 @@ int main(int argc, char *argv[])
|
|||
genAddress(isJIT, reg32Tbl, NUM_OF_ARRAY(reg32Tbl));
|
||||
} else {
|
||||
#ifdef XBYAK64
|
||||
fprintf(stderr, "64bit reg\n");
|
||||
static const char reg64Tbl[][5] = {
|
||||
"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
|
||||
};
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "xbyak/xbyak.h"
|
||||
#define NUM_OF_ARRAY(x) (sizeof(x) / sizeof(x[0]))
|
||||
|
||||
|
@ -82,13 +83,13 @@ int main()
|
|||
{ 127, false, true, "EB7F" },
|
||||
{ 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];
|
||||
TestJmp jmp(p->offset, p->isBack, p->isShort);
|
||||
const uint8 *q = (const uint8*)jmp.getCode();
|
||||
char buf[32];
|
||||
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]);
|
||||
}
|
||||
if (strcmp(buf, p->result) != 0) {
|
||||
|
|
|
@ -62,6 +62,7 @@ const uint64 NOPARA = 1ULL << (bitEnd - 1);
|
|||
|
||||
class Test {
|
||||
const bool isXbyak_;
|
||||
int funcNum_;
|
||||
// check all op1, op2, op3
|
||||
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, 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
|
||||
{
|
||||
const char *p = "ret";
|
||||
|
@ -821,7 +847,7 @@ class Test {
|
|||
put(p, REG64|MEM|MEM_ONLY_DISP, REG64|RAX);
|
||||
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, 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, REG64, "0x1234567890abcdefLL", "0x1234567890abcdef");
|
||||
#ifdef XBYAK64
|
||||
|
@ -1117,32 +1143,72 @@ class Test {
|
|||
public:
|
||||
Test(bool 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
|
||||
putSIMPLE();
|
||||
putReg1();
|
||||
putRorM();
|
||||
separateFunc();
|
||||
putPushPop();
|
||||
putTest();
|
||||
separateFunc();
|
||||
putEtc();
|
||||
putShift();
|
||||
putShxd();
|
||||
|
||||
separateFunc();
|
||||
|
||||
putBs();
|
||||
putMMX1();
|
||||
putMMX2();
|
||||
separateFunc();
|
||||
putMMX3();
|
||||
putMMX4();
|
||||
putMMX5();
|
||||
separateFunc();
|
||||
putXMM1();
|
||||
putXMM2();
|
||||
putXMM3();
|
||||
putXMM4();
|
||||
separateFunc();
|
||||
putCmov();
|
||||
putFpuMem16_32();
|
||||
putFpuMem32_64();
|
||||
separateFunc();
|
||||
putFpuMem16_32_64();
|
||||
put("clflush", MEM); // current nasm is ok
|
||||
putFpu();
|
||||
|
@ -1150,7 +1216,9 @@ public:
|
|||
putFpuFpu();
|
||||
putSSSE3();
|
||||
putSSE4_1();
|
||||
separateFunc();
|
||||
putSSE4_2();
|
||||
putMov64();
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
@ -1160,4 +1228,3 @@ int main(int argc, char *[])
|
|||
Test test(argc > 1);
|
||||
test.put();
|
||||
}
|
||||
|
||||
|
|
6589
test/nm.cpp
6589
test/nm.cpp
File diff suppressed because it is too large
Load diff
|
@ -6,21 +6,9 @@ using namespace Xbyak;
|
|||
class Sample : public CodeGenerator {
|
||||
void operator=(const Sample&);
|
||||
public:
|
||||
void gen()
|
||||
{
|
||||
try {
|
||||
|
||||
#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 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()
|
||||
{
|
||||
Sample s;
|
||||
s.gen();
|
||||
try {
|
||||
Sample s;
|
||||
s.gen();
|
||||
} catch (Xbyak::Error err) {
|
||||
printf("ERR:%s(%d)\n", Xbyak::ConvertErrorToString(err), err);
|
||||
} catch (...) {
|
||||
printf("unknown error\n");
|
||||
}
|
||||
ErrorSample es;
|
||||
es.gen();
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ if /i "%1"=="64" (
|
|||
set OPT2=-DXBYAK64
|
||||
set OPT3=win64
|
||||
) else (
|
||||
set OPT2=
|
||||
set OPT2=-DXBYAK32
|
||||
set OPT3=win32
|
||||
)
|
||||
|
||||
|
@ -20,12 +20,16 @@ if /i "%1"=="64" (
|
|||
goto end
|
||||
|
||||
:sub
|
||||
echo cl address.cpp %OPT% %OPT2%
|
||||
cl address.cpp %OPT% %OPT2%
|
||||
address %1% > a.asm
|
||||
echo nasm -f %OPT3% -l a.lst a.asm
|
||||
nasm -f %OPT3% -l a.lst a.asm
|
||||
awk "{print $3}" < a.lst > ok.lst
|
||||
echo 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
|
||||
diff x.lst ok.lst
|
||||
wc x.lst
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
pushd ..\gen
|
||||
call update
|
||||
popd
|
||||
cl -I../ -DTEST_NM jmp.cpp %OPT%
|
||||
cl -I../ -DXBYAK_TEST jmp.cpp %OPT%
|
||||
jmp
|
||||
|
|
|
@ -18,8 +18,8 @@ if /i "%1"=="Y" (
|
|||
set OPT3=win64
|
||||
set FILTER=normalize_prefix
|
||||
) else (
|
||||
set EXE=nasm.exe -DXBYAK32
|
||||
set OPT2=
|
||||
set EXE=nasm.exe
|
||||
set OPT2=-DXBYAK32
|
||||
set OPT3=win32
|
||||
)
|
||||
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
|
||||
)
|
||||
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
|
||||
diff x.lst ok.lst
|
||||
wc x.lst
|
||||
|
|
|
@ -36,7 +36,7 @@ awk '{if (index($3, "-")) { conti=substr($3, 0, length($3) - 1) } else { conti =
|
|||
echo "xbyak"
|
||||
./make_nm jit > nm.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
|
||||
diff ok.lst x.lst && echo "ok"
|
||||
exit 0
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
@file xbyak.h
|
||||
@brief Xbyak ; JIT assembler for x86(IA32)/x64 by C++
|
||||
@author herumi
|
||||
@version $Revision: 1.188 $
|
||||
@version $Revision: 1.191 $
|
||||
@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
|
||||
http://www.opensource.org/licenses/bsd-license.php
|
||||
*/
|
||||
|
@ -55,7 +55,7 @@ namespace Xbyak {
|
|||
|
||||
enum {
|
||||
DEFAULT_MAX_CODE_SIZE = 2048,
|
||||
VERSION = 0x2260, /* 0xABCD = A.BC(D) */
|
||||
VERSION = 0x2270, /* 0xABCD = A.BC(D) */
|
||||
};
|
||||
|
||||
#ifndef MIE_INTEGER_TYPE_DEFINED
|
||||
|
@ -144,7 +144,7 @@ namespace inner {
|
|||
|
||||
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);
|
||||
#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 IsInInt32(uint64 x) { return 0xFFFFFFFF80000000ULL <= x || x <= 0x7FFFFFFFU; }
|
||||
|
||||
}
|
||||
|
||||
|
@ -555,7 +556,11 @@ public:
|
|||
explicit AddressFrame(uint32 bit) : bit_(bit) { }
|
||||
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);
|
||||
}
|
||||
#ifdef XBYAK64
|
||||
|
@ -1216,13 +1221,32 @@ protected:
|
|||
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);
|
||||
if (op.isREG()) {
|
||||
int w = op.isBit(8) ? 0 : 1;
|
||||
rex(op); db(B10110000 | (w << 3) | (op.getIdx() & 7));
|
||||
db(imm, op.getBit() / 8);
|
||||
rex(op);
|
||||
int code, size;
|
||||
#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()) {
|
||||
opModM(static_cast<const Address&>(op), Reg(0, Operand::REG, op.getBit()), B11000110);
|
||||
int size = op.getBit() / 8; if (size > 4) size = 4;
|
||||
|
@ -1398,7 +1422,7 @@ public:
|
|||
// if (hasUndefinedLabel()) throw ERR_LABEL_IS_NOT_FOUND;
|
||||
return top_;
|
||||
}
|
||||
#ifdef TEST_NM
|
||||
#ifdef XBYAK_TEST
|
||||
void dump(bool doClear = true)
|
||||
{
|
||||
CodeArray::dump();
|
||||
|
|
|
@ -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 packsswb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x63); }
|
||||
void packuswb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x67); }
|
||||
|
|
|
@ -95,25 +95,25 @@ public:
|
|||
if (data[2] == get32bitAsBE(amd)) {
|
||||
type_ |= tAMD;
|
||||
getCpuid(0x80000001, data);
|
||||
if (data[3] & (1 << 31)) type_ |= t3DN;
|
||||
if (data[3] & (1 << 15)) type_ |= tCMOV;
|
||||
if (data[3] & (1 << 30)) type_ |= tE3DN;
|
||||
if (data[3] & (1 << 22)) type_ |= tMMX2;
|
||||
if (data[3] & (1U << 31)) type_ |= t3DN;
|
||||
if (data[3] & (1U << 15)) type_ |= tCMOV;
|
||||
if (data[3] & (1U << 30)) type_ |= tE3DN;
|
||||
if (data[3] & (1U << 22)) type_ |= tMMX2;
|
||||
}
|
||||
if (data[2] == get32bitAsBE(intel)) {
|
||||
type_ |= tINTEL;
|
||||
}
|
||||
getCpuid(1, data);
|
||||
if (data[2] & (1 << 0)) type_ |= tSSE3;
|
||||
if (data[2] & (1 << 9)) type_ |= tSSSE3;
|
||||
if (data[2] & (1 << 19)) type_ |= tSSE41;
|
||||
if (data[2] & (1 << 20)) type_ |= tSSE42;
|
||||
if (data[2] & (1 << 23)) type_ |= tPOPCNT;
|
||||
if (data[2] & (1U << 0)) type_ |= tSSE3;
|
||||
if (data[2] & (1U << 9)) type_ |= tSSSE3;
|
||||
if (data[2] & (1U << 19)) type_ |= tSSE41;
|
||||
if (data[2] & (1U << 20)) type_ |= tSSE42;
|
||||
if (data[2] & (1U << 23)) type_ |= tPOPCNT;
|
||||
|
||||
if (data[3] & (1 << 15)) type_ |= tCMOV;
|
||||
if (data[3] & (1 << 23)) type_ |= tMMX;
|
||||
if (data[3] & (1 << 25)) type_ |= tMMX2 | tSSE;
|
||||
if (data[3] & (1 << 26)) type_ |= tSSE2;
|
||||
if (data[3] & (1U << 15)) type_ |= tCMOV;
|
||||
if (data[3] & (1U << 23)) type_ |= tMMX;
|
||||
if (data[3] & (1U << 25)) type_ |= tMMX2 | tSSE;
|
||||
if (data[3] & (1U << 26)) type_ |= tSSE2;
|
||||
}
|
||||
bool has(Type type) const
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue