15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* CpuArch.h -- CPU specific code 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)2010-10-26: Igor Pavlov : Public domain */ 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef __CPU_ARCH_H 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define __CPU_ARCH_H 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "Types.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EXTERN_C_BEGIN 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MY_CPU_LE means that CPU is LITTLE ENDIAN. 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)If MY_CPU_LE is not defined, we don't know about that property of platform (it can be LITTLE ENDIAN). 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of platform. 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)*/ 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MY_CPU_AMD64 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(MY_CPU_AMD64) || defined(_M_IA64) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MY_CPU_64BIT 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(_M_IX86) || defined(__i386__) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MY_CPU_X86 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MY_CPU_X86_OR_AMD64 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(MY_CPU_X86) || defined(_M_ARM) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MY_CPU_32BIT 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(_WIN32) && defined(_M_ARM) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MY_CPU_ARM_LE 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(_WIN32) && defined(_M_IA64) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MY_CPU_IA64_LE 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(MY_CPU_X86_OR_AMD64) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MY_CPU_LE_UNALIGN 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE) || defined(MY_CPU_IA64_LE) || defined(__ARMEL__) || defined(__MIPSEL__) || defined(__LITTLE_ENDIAN__) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MY_CPU_LE 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__BIG_ENDIAN__) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MY_CPU_BE 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(MY_CPU_LE) && defined(MY_CPU_BE) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Stop_Compiling_Bad_Endian 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef MY_CPU_LE_UNALIGN 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GetUi16(p) (*(const UInt16 *)(p)) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GetUi32(p) (*(const UInt32 *)(p)) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GetUi64(p) (*(const UInt64 *)(p)) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SetUi16(p, d) *(UInt16 *)(p) = (d); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SetUi32(p, d) *(UInt32 *)(p) = (d); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SetUi64(p, d) *(UInt64 *)(p) = (d); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8)) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GetUi32(p) ( \ 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((const Byte *)(p))[0] | \ 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((UInt32)((const Byte *)(p))[1] << 8) | \ 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((UInt32)((const Byte *)(p))[2] << 16) | \ 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((UInt32)((const Byte *)(p))[3] << 24)) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SetUi16(p, d) { UInt32 _x_ = (d); \ 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((Byte *)(p))[0] = (Byte)_x_; \ 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((Byte *)(p))[1] = (Byte)(_x_ >> 8); } 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SetUi32(p, d) { UInt32 _x_ = (d); \ 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((Byte *)(p))[0] = (Byte)_x_; \ 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \ 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \ 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((Byte *)(p))[3] = (Byte)(_x_ >> 24); } 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SetUi64(p, d) { UInt64 _x64_ = (d); \ 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetUi32(p, (UInt32)_x64_); \ 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma intrinsic(_byteswap_ulong) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma intrinsic(_byteswap_uint64) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p)) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GetBe32(p) ( \ 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((UInt32)((const Byte *)(p))[0] << 24) | \ 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((UInt32)((const Byte *)(p))[1] << 16) | \ 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((UInt32)((const Byte *)(p))[2] << 8) | \ 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((const Byte *)(p))[3] ) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1]) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef MY_CPU_X86_OR_AMD64 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UInt32 maxFunc; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UInt32 vendor[3]; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UInt32 ver; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UInt32 b; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UInt32 c; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UInt32 d; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} Cx86cpuid; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CPU_FIRM_INTEL, 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CPU_FIRM_AMD, 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CPU_FIRM_VIA 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Bool x86cpuid_CheckAndRead(Cx86cpuid *p); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int x86cpuid_GetFirm(const Cx86cpuid *p); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define x86cpuid_GetFamily(p) (((p)->ver >> 8) & 0xFF00F) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define x86cpuid_GetModel(p) (((p)->ver >> 4) & 0xF00F) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define x86cpuid_GetStepping(p) ((p)->ver & 0xF) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Bool CPU_Is_InOrder(); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Bool CPU_Is_Aes_Supported(); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EXTERN_C_END 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 157