Include VS solution

And refactor code: tab, code style. and end of lines. Update the libcpuid lib.
This commit is contained in:
enWILLYado 2018-02-07 22:14:06 +01:00
parent 98c151b190
commit 86f0d9d944
106 changed files with 12665 additions and 6894 deletions

View file

@ -28,7 +28,7 @@
* This file contains a list of internal codes we use in detection. It is
* of no external use and isn't a complete list of AMD products.
*/
CODE2(OPTERON_800, 1000),
CODE2(OPTERON_800, 1000),
CODE(PHENOM),
CODE(PHENOM2),
CODE(FUSION_C),

View file

@ -48,11 +48,12 @@ int cpuid_exists_by_eflags(void)
" push %%ecx\n"
" popfl\n"
: "=m"(result)
: :"eax", "ecx", "memory");
: : "eax", "ecx", "memory");
return (result != 0);
# elif defined(COMPILER_MICROSOFT)
int result;
__asm {
__asm
{
pushfd
pop eax
mov ecx, eax
@ -80,7 +81,7 @@ int cpuid_exists_by_eflags(void)
* with MSVC/AMD64, the exec_cpuid() and cpu_rdtsc() functions
* are implemented in separate .asm files. Otherwise, use inline assembly
*/
void exec_cpuid(uint32_t *regs)
void exec_cpuid(uint32_t* regs)
{
#ifdef COMPILER_GCC
# ifdef PLATFORM_X64
@ -106,8 +107,8 @@ void exec_cpuid(uint32_t *regs)
" pop %%rcx\n"
" pop %%rbx\n"
:
:"m"(regs)
:"memory", "eax", "rdi"
: "m"(regs)
: "memory", "eax", "rdi"
);
# else
__asm __volatile(
@ -132,13 +133,14 @@ void exec_cpuid(uint32_t *regs)
" pop %%ecx\n"
" pop %%ebx\n"
:
:"m"(regs)
:"memory", "eax", "edi"
: "m"(regs)
: "memory", "eax", "edi"
);
# endif /* COMPILER_GCC */
#else
# ifdef COMPILER_MICROSOFT
__asm {
__asm
{
push ebx
push ecx
push edx
@ -174,15 +176,16 @@ void cpu_rdtsc(uint64_t* result)
{
uint32_t low_part, hi_part;
#ifdef COMPILER_GCC
__asm __volatile (
__asm __volatile(
" rdtsc\n"
" mov %%eax, %0\n"
" mov %%edx, %1\n"
:"=m"(low_part), "=m"(hi_part)::"memory", "eax", "edx"
: "=m"(low_part), "=m"(hi_part)::"memory", "eax", "edx"
);
#else
# ifdef COMPILER_MICROSOFT
__asm {
__asm
{
rdtsc
mov low_part, eax
mov hi_part, edx
@ -204,7 +207,7 @@ void busy_sse_loop(int cycles)
#else
# define XALIGN ".align 4\n"
#endif
__asm __volatile (
__asm __volatile(
" xorps %%xmm0, %%xmm0\n"
" xorps %%xmm1, %%xmm1\n"
" xorps %%xmm2, %%xmm2\n"
@ -512,7 +515,8 @@ void busy_sse_loop(int cycles)
);
#else
# ifdef COMPILER_MICROSOFT
__asm {
__asm
{
mov eax, cycles
xorps xmm0, xmm0
xorps xmm1, xmm1
@ -524,7 +528,7 @@ void busy_sse_loop(int cycles)
xorps xmm7, xmm7
//--
align 16
bsLoop:
bsLoop:
// 0:
addps xmm0, xmm1
addps xmm1, xmm2

View file

@ -47,7 +47,7 @@
#endif
int cpuid_exists_by_eflags(void);
void exec_cpuid(uint32_t *regs);
void exec_cpuid(uint32_t* regs);
void busy_sse_loop(int cycles);
#endif /* __ASM_BITS_H__ */

View file

@ -36,6 +36,10 @@
#include <string.h>
#include <stdlib.h>
#ifndef VERSION
#define VERSION "7.10"
#endif
/* Implementation: */
static int _libcpiud_errno = ERR_OK;
@ -46,6 +50,11 @@ int set_error(cpu_error_t err)
return (int) err;
}
static void raw_data_t_constructor(struct cpu_raw_data_t* raw)
{
memset(raw, 0, sizeof(struct cpu_raw_data_t));
}
static void cpu_id_t_constructor(struct cpu_id_t* id)
{
memset(id, 0, sizeof(struct cpu_id_t));
@ -55,6 +64,37 @@ static void cpu_id_t_constructor(struct cpu_id_t* id)
id->sse_size = -1;
}
static int parse_token(const char* expected_token, const char* token,
const char* value, uint32_t array[][4], int limit, int* recognized)
{
char format[32];
int veax, vebx, vecx, vedx;
int index;
if(*recognized)
{
return 1; /* already recognized */
}
if(strncmp(token, expected_token, strlen(expected_token)))
{
return 1; /* not what we search for */
}
sprintf(format, "%s[%%d]", expected_token);
*recognized = 1;
if(1 == sscanf(token, format, &index) && index >= 0 && index < limit)
{
if(4 == sscanf(value, "%x%x%x%x", &veax, &vebx, &vecx, &vedx))
{
array[index][0] = veax;
array[index][1] = vebx;
array[index][2] = vecx;
array[index][3] = vedx;
return 1;
}
}
return 0;
}
/* get_total_cpus() system specific code: uses OS routines to determine total number of CPUs */
#ifdef __APPLE__
#include <unistd.h>
@ -69,7 +109,10 @@ static int get_total_cpus(void)
host_flavor_t flavor = HOST_BASIC_INFO;
mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
kr = host_info(mach_host_self(), flavor, info, &count);
if (kr != KERN_SUCCESS) return 1;
if(kr != KERN_SUCCESS)
{
return 1;
}
return basic_info.avail_cpus;
}
#define GET_TOTAL_CPUS_DEFINED
@ -106,7 +149,10 @@ static int get_total_cpus(void)
int mib[2] = { CTL_HW, HW_NCPU };
int ncpus;
size_t len = sizeof(ncpus);
if (sysctl(mib, 2, &ncpus, &len, (void *) 0, 0) != 0) return 1;
if(sysctl(mib, 2, &ncpus, &len, (void*) 0, 0) != 0)
{
return 1;
}
return ncpus;
}
#define GET_TOTAL_CPUS_DEFINED
@ -116,7 +162,8 @@ static int get_total_cpus(void)
static int get_total_cpus(void)
{
static int warning_printed = 0;
if (!warning_printed) {
if(!warning_printed)
{
warning_printed = 1;
warnf("Your system is not supported by libcpuid -- don't know how to detect the\n");
warnf("total number of CPUs on your system. It will be reported as 1.\n");
@ -129,7 +176,8 @@ static int get_total_cpus(void)
static void load_features_common(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
{
const struct feature_map_t matchtable_edx1[] = {
const struct feature_map_t matchtable_edx1[] =
{
{ 0, CPU_FEATURE_FPU },
{ 1, CPU_FEATURE_VME },
{ 2, CPU_FEATURE_DE },
@ -154,7 +202,8 @@ static void load_features_common(struct cpu_raw_data_t* raw, struct cpu_id_t* da
{ 26, CPU_FEATURE_SSE2 },
{ 28, CPU_FEATURE_HT },
};
const struct feature_map_t matchtable_ecx1[] = {
const struct feature_map_t matchtable_ecx1[] =
{
{ 0, CPU_FEATURE_PNI },
{ 1, CPU_FEATURE_PCLMUL },
{ 3, CPU_FEATURE_MONITOR },
@ -172,39 +221,49 @@ static void load_features_common(struct cpu_raw_data_t* raw, struct cpu_id_t* da
{ 29, CPU_FEATURE_F16C },
{ 30, CPU_FEATURE_RDRAND },
};
const struct feature_map_t matchtable_ebx7[] = {
const struct feature_map_t matchtable_ebx7[] =
{
{ 3, CPU_FEATURE_BMI1 },
{ 5, CPU_FEATURE_AVX2 },
{ 8, CPU_FEATURE_BMI2 },
};
const struct feature_map_t matchtable_edx81[] = {
const struct feature_map_t matchtable_edx81[] =
{
{ 11, CPU_FEATURE_SYSCALL },
{ 27, CPU_FEATURE_RDTSCP },
{ 29, CPU_FEATURE_LM },
};
const struct feature_map_t matchtable_ecx81[] = {
const struct feature_map_t matchtable_ecx81[] =
{
{ 0, CPU_FEATURE_LAHF_LM },
};
const struct feature_map_t matchtable_edx87[] = {
const struct feature_map_t matchtable_edx87[] =
{
{ 8, CPU_FEATURE_CONSTANT_TSC },
};
if (raw->basic_cpuid[0][0] >= 1) {
if(raw->basic_cpuid[0][0] >= 1)
{
match_features(matchtable_edx1, COUNT_OF(matchtable_edx1), raw->basic_cpuid[1][3], data);
match_features(matchtable_ecx1, COUNT_OF(matchtable_ecx1), raw->basic_cpuid[1][2], data);
}
if (raw->basic_cpuid[0][0] >= 7) {
if(raw->basic_cpuid[0][0] >= 7)
{
match_features(matchtable_ebx7, COUNT_OF(matchtable_ebx7), raw->basic_cpuid[7][1], data);
}
if (raw->ext_cpuid[0][0] >= 0x80000001) {
if(raw->ext_cpuid[0][0] >= 0x80000001)
{
match_features(matchtable_edx81, COUNT_OF(matchtable_edx81), raw->ext_cpuid[1][3], data);
match_features(matchtable_ecx81, COUNT_OF(matchtable_ecx81), raw->ext_cpuid[1][2], data);
}
if (raw->ext_cpuid[0][0] >= 0x80000007) {
if(raw->ext_cpuid[0][0] >= 0x80000007)
{
match_features(matchtable_edx87, COUNT_OF(matchtable_edx87), raw->ext_cpuid[7][3], data);
}
if (data->flags[CPU_FEATURE_SSE]) {
if(data->flags[CPU_FEATURE_SSE])
{
/* apply guesswork to check if the SSE unit width is 128 bit */
switch (data->vendor) {
switch(data->vendor)
{
case VENDOR_AMD:
data->sse_size = (data->ext_family >= 16 && data->ext_family != 17) ? 128 : 64;
break;
@ -219,12 +278,17 @@ static void load_features_common(struct cpu_raw_data_t* raw, struct cpu_id_t* da
}
}
static cpu_vendor_t cpuid_vendor_identify(const uint32_t *raw_vendor, char *vendor_str)
static cpu_vendor_t cpuid_vendor_identify(const uint32_t* raw_vendor, char* vendor_str)
{
int i;
cpu_vendor_t vendor = VENDOR_UNKNOWN;
const struct { cpu_vendor_t vendor; char match[16]; }
matchtable[NUM_CPU_VENDORS] = {
const struct
{
cpu_vendor_t vendor;
char match[16];
}
matchtable[NUM_CPU_VENDORS] =
{
/* source: http://www.sandpile.org/ia32/cpuid.htm */
{ VENDOR_INTEL , "GenuineIntel" },
{ VENDOR_AMD , "AuthenticAMD" },
@ -244,8 +308,9 @@ static cpu_vendor_t cpuid_vendor_identify(const uint32_t *raw_vendor, char *vend
vendor_str[12] = 0;
/* Determine vendor: */
for (i = 0; i < NUM_CPU_VENDORS; i++)
if (!strcmp(vendor_str, matchtable[i].match)) {
for(i = 0; i < NUM_CPU_VENDORS; i++)
if(!strcmp(vendor_str, matchtable[i].match))
{
vendor = matchtable[i].vendor;
break;
}
@ -258,32 +323,43 @@ static int cpuid_basic_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* dat
char brandstr[64] = {0};
data->vendor = cpuid_vendor_identify(raw->basic_cpuid[0], data->vendor_str);
if (data->vendor == VENDOR_UNKNOWN)
if(data->vendor == VENDOR_UNKNOWN)
{
return set_error(ERR_CPU_UNKN);
}
basic = raw->basic_cpuid[0][0];
if (basic >= 1) {
if(basic >= 1)
{
data->family = (raw->basic_cpuid[1][0] >> 8) & 0xf;
data->model = (raw->basic_cpuid[1][0] >> 4) & 0xf;
data->stepping = raw->basic_cpuid[1][0] & 0xf;
xmodel = (raw->basic_cpuid[1][0] >> 16) & 0xf;
xfamily = (raw->basic_cpuid[1][0] >> 20) & 0xff;
if (data->vendor == VENDOR_AMD && data->family < 0xf)
if(data->vendor == VENDOR_AMD && data->family < 0xf)
{
data->ext_family = data->family;
}
else
{
data->ext_family = data->family + xfamily;
}
data->ext_model = data->model + (xmodel << 4);
}
ext = raw->ext_cpuid[0][0] - 0x8000000;
/* obtain the brand string, if present: */
if (ext >= 4) {
for (i = 0; i < 3; i++)
for (j = 0; j < 4; j++)
if(ext >= 4)
{
for(i = 0; i < 3; i++)
for(j = 0; j < 4; j++)
memcpy(brandstr + i * 16 + j * 4,
&raw->ext_cpuid[2 + i][j], 4);
brandstr[48] = 0;
i = 0;
while (brandstr[i] == ' ') i++;
while(brandstr[i] == ' ')
{
i++;
}
strncpy(data->brand_str, brandstr + i, sizeof(data->brand_str));
data->brand_str[48] = 0;
}
@ -292,6 +368,31 @@ static int cpuid_basic_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* dat
return set_error(ERR_OK);
}
static void make_list_from_string(const char* csv, struct cpu_list_t* list)
{
int i, n, l, last;
l = (int) strlen(csv);
n = 0;
for(i = 0; i < l; i++) if(csv[i] == ',')
{
n++;
}
n++;
list->num_entries = n;
list->names = (char**) malloc(sizeof(char*) * n);
last = -1;
n = 0;
for(i = 0; i <= l; i++) if(i == l || csv[i] == ',')
{
list->names[n] = (char*) malloc(i - last);
memcpy(list->names[n], &csv[last + 1], i - last - 1);
list->names[n][i - last - 1] = '\0';
n++;
last = i;
}
}
/* Interface: */
int cpuid_get_total_cpus(void)
@ -319,31 +420,41 @@ void cpu_exec_cpuid_ext(uint32_t* regs)
int cpuid_get_raw_data(struct cpu_raw_data_t* data)
{
unsigned i;
if (!cpuid_present())
if(!cpuid_present())
{
return set_error(ERR_NO_CPUID);
for (i = 0; i < 32; i++)
}
for(i = 0; i < 32; i++)
{
cpu_exec_cpuid(i, data->basic_cpuid[i]);
for (i = 0; i < 32; i++)
}
for(i = 0; i < 32; i++)
{
cpu_exec_cpuid(0x80000000 + i, data->ext_cpuid[i]);
for (i = 0; i < MAX_INTELFN4_LEVEL; i++) {
}
for(i = 0; i < MAX_INTELFN4_LEVEL; i++)
{
memset(data->intel_fn4[i], 0, sizeof(data->intel_fn4[i]));
data->intel_fn4[i][0] = 4;
data->intel_fn4[i][2] = i;
cpu_exec_cpuid_ext(data->intel_fn4[i]);
}
for (i = 0; i < MAX_INTELFN11_LEVEL; i++) {
for(i = 0; i < MAX_INTELFN11_LEVEL; i++)
{
memset(data->intel_fn11[i], 0, sizeof(data->intel_fn11[i]));
data->intel_fn11[i][0] = 11;
data->intel_fn11[i][2] = i;
cpu_exec_cpuid_ext(data->intel_fn11[i]);
}
for (i = 0; i < MAX_INTELFN12H_LEVEL; i++) {
for(i = 0; i < MAX_INTELFN12H_LEVEL; i++)
{
memset(data->intel_fn12h[i], 0, sizeof(data->intel_fn12h[i]));
data->intel_fn12h[i][0] = 0x12;
data->intel_fn12h[i][2] = i;
cpu_exec_cpuid_ext(data->intel_fn12h[i]);
}
for (i = 0; i < MAX_INTELFN14H_LEVEL; i++) {
for(i = 0; i < MAX_INTELFN14H_LEVEL; i++)
{
memset(data->intel_fn14h[i], 0, sizeof(data->intel_fn14h[i]));
data->intel_fn14h[i][0] = 0x14;
data->intel_fn14h[i][2] = i;
@ -352,19 +463,159 @@ int cpuid_get_raw_data(struct cpu_raw_data_t* data)
return set_error(ERR_OK);
}
int cpuid_serialize_raw_data(struct cpu_raw_data_t* data, const char* filename)
{
int i;
FILE* f;
if(!strcmp(filename, ""))
{
f = stdout;
}
else
{
f = fopen(filename, "wt");
}
if(!f)
{
return set_error(ERR_OPEN);
}
fprintf(f, "version=%s\n", VERSION);
for(i = 0; i < MAX_CPUID_LEVEL; i++)
fprintf(f, "basic_cpuid[%d]=%08x %08x %08x %08x\n", i,
data->basic_cpuid[i][0], data->basic_cpuid[i][1],
data->basic_cpuid[i][2], data->basic_cpuid[i][3]);
for(i = 0; i < MAX_EXT_CPUID_LEVEL; i++)
fprintf(f, "ext_cpuid[%d]=%08x %08x %08x %08x\n", i,
data->ext_cpuid[i][0], data->ext_cpuid[i][1],
data->ext_cpuid[i][2], data->ext_cpuid[i][3]);
for(i = 0; i < MAX_INTELFN4_LEVEL; i++)
fprintf(f, "intel_fn4[%d]=%08x %08x %08x %08x\n", i,
data->intel_fn4[i][0], data->intel_fn4[i][1],
data->intel_fn4[i][2], data->intel_fn4[i][3]);
for(i = 0; i < MAX_INTELFN11_LEVEL; i++)
fprintf(f, "intel_fn11[%d]=%08x %08x %08x %08x\n", i,
data->intel_fn11[i][0], data->intel_fn11[i][1],
data->intel_fn11[i][2], data->intel_fn11[i][3]);
for(i = 0; i < MAX_INTELFN12H_LEVEL; i++)
fprintf(f, "intel_fn12h[%d]=%08x %08x %08x %08x\n", i,
data->intel_fn12h[i][0], data->intel_fn12h[i][1],
data->intel_fn12h[i][2], data->intel_fn12h[i][3]);
for(i = 0; i < MAX_INTELFN14H_LEVEL; i++)
fprintf(f, "intel_fn14h[%d]=%08x %08x %08x %08x\n", i,
data->intel_fn14h[i][0], data->intel_fn14h[i][1],
data->intel_fn14h[i][2], data->intel_fn14h[i][3]);
if(strcmp(filename, ""))
{
fclose(f);
}
return set_error(ERR_OK);
}
int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename)
{
int i, len;
char line[100];
char token[100];
char* value;
int syntax;
int cur_line = 0;
int recognized;
FILE* f;
raw_data_t_constructor(data);
if(!strcmp(filename, ""))
{
f = stdin;
}
else
{
f = fopen(filename, "rt");
}
if(!f)
{
return set_error(ERR_OPEN);
}
while(fgets(line, sizeof(line), f))
{
++cur_line;
len = (int) strlen(line);
if(len < 2)
{
continue;
}
if(line[len - 1] == '\n')
{
line[--len] = '\0';
}
for(i = 0; i < len && line[i] != '='; i++)
if(i >= len && i < 1 && len - i - 1 <= 0)
{
fclose(f);
return set_error(ERR_BADFMT);
}
strncpy(token, line, i);
token[i] = '\0';
value = &line[i + 1];
/* try to recognize the line */
recognized = 0;
if(!strcmp(token, "version") || !strcmp(token, "build_date"))
{
recognized = 1;
}
syntax = 1;
syntax = syntax && parse_token("basic_cpuid", token, value, data->basic_cpuid, MAX_CPUID_LEVEL, &recognized);
syntax = syntax &&
parse_token("ext_cpuid", token, value, data->ext_cpuid, MAX_EXT_CPUID_LEVEL, &recognized);
syntax = syntax &&
parse_token("intel_fn4", token, value, data->intel_fn4, MAX_INTELFN4_LEVEL, &recognized);
syntax = syntax &&
parse_token("intel_fn11", token, value, data->intel_fn11, MAX_INTELFN11_LEVEL, &recognized);
syntax = syntax &&
parse_token("intel_fn12h", token, value, data->intel_fn12h, MAX_INTELFN12H_LEVEL, &recognized);
syntax = syntax &&
parse_token("intel_fn14h", token, value, data->intel_fn14h, MAX_INTELFN14H_LEVEL, &recognized);
if(!syntax)
{
warnf("Error: %s:%d: Syntax error\n", filename, cur_line);
fclose(f);
return set_error(ERR_BADFMT);
}
if(!recognized)
{
warnf("Warning: %s:%d not understood!\n", filename, cur_line);
}
}
if(strcmp(filename, ""))
{
fclose(f);
}
return set_error(ERR_OK);
}
int cpu_ident_internal(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal)
{
int r;
struct cpu_raw_data_t myraw;
if (!raw) {
if ((r = cpuid_get_raw_data(&myraw)) < 0)
if(!raw)
{
if((r = cpuid_get_raw_data(&myraw)) < 0)
{
return set_error(r);
}
raw = &myraw;
}
cpu_id_t_constructor(data);
if ((r = cpuid_basic_identify(raw, data)) < 0)
if((r = cpuid_basic_identify(raw, data)) < 0)
{
return set_error(r);
switch (data->vendor) {
}
switch(data->vendor)
{
case VENDOR_INTEL:
r = cpuid_identify_intel(raw, data, internal);
break;
@ -383,7 +634,264 @@ int cpu_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
return cpu_ident_internal(raw, data, &throwaway);
}
const char* cpu_feature_str(cpu_feature_t feature)
{
const struct
{
cpu_feature_t feature;
const char* name;
}
matchtable[] =
{
{ CPU_FEATURE_FPU, "fpu" },
{ CPU_FEATURE_VME, "vme" },
{ CPU_FEATURE_DE, "de" },
{ CPU_FEATURE_PSE, "pse" },
{ CPU_FEATURE_TSC, "tsc" },
{ CPU_FEATURE_MSR, "msr" },
{ CPU_FEATURE_PAE, "pae" },
{ CPU_FEATURE_MCE, "mce" },
{ CPU_FEATURE_CX8, "cx8" },
{ CPU_FEATURE_APIC, "apic" },
{ CPU_FEATURE_MTRR, "mtrr" },
{ CPU_FEATURE_SEP, "sep" },
{ CPU_FEATURE_PGE, "pge" },
{ CPU_FEATURE_MCA, "mca" },
{ CPU_FEATURE_CMOV, "cmov" },
{ CPU_FEATURE_PAT, "pat" },
{ CPU_FEATURE_PSE36, "pse36" },
{ CPU_FEATURE_PN, "pn" },
{ CPU_FEATURE_CLFLUSH, "clflush" },
{ CPU_FEATURE_DTS, "dts" },
{ CPU_FEATURE_ACPI, "acpi" },
{ CPU_FEATURE_MMX, "mmx" },
{ CPU_FEATURE_FXSR, "fxsr" },
{ CPU_FEATURE_SSE, "sse" },
{ CPU_FEATURE_SSE2, "sse2" },
{ CPU_FEATURE_SS, "ss" },
{ CPU_FEATURE_HT, "ht" },
{ CPU_FEATURE_TM, "tm" },
{ CPU_FEATURE_IA64, "ia64" },
{ CPU_FEATURE_PBE, "pbe" },
{ CPU_FEATURE_PNI, "pni" },
{ CPU_FEATURE_PCLMUL, "pclmul" },
{ CPU_FEATURE_DTS64, "dts64" },
{ CPU_FEATURE_MONITOR, "monitor" },
{ CPU_FEATURE_DS_CPL, "ds_cpl" },
{ CPU_FEATURE_VMX, "vmx" },
{ CPU_FEATURE_SMX, "smx" },
{ CPU_FEATURE_EST, "est" },
{ CPU_FEATURE_TM2, "tm2" },
{ CPU_FEATURE_SSSE3, "ssse3" },
{ CPU_FEATURE_CID, "cid" },
{ CPU_FEATURE_CX16, "cx16" },
{ CPU_FEATURE_XTPR, "xtpr" },
{ CPU_FEATURE_PDCM, "pdcm" },
{ CPU_FEATURE_DCA, "dca" },
{ CPU_FEATURE_SSE4_1, "sse4_1" },
{ CPU_FEATURE_SSE4_2, "sse4_2" },
{ CPU_FEATURE_SYSCALL, "syscall" },
{ CPU_FEATURE_XD, "xd" },
{ CPU_FEATURE_X2APIC, "x2apic"},
{ CPU_FEATURE_MOVBE, "movbe" },
{ CPU_FEATURE_POPCNT, "popcnt" },
{ CPU_FEATURE_AES, "aes" },
{ CPU_FEATURE_XSAVE, "xsave" },
{ CPU_FEATURE_OSXSAVE, "osxsave" },
{ CPU_FEATURE_AVX, "avx" },
{ CPU_FEATURE_MMXEXT, "mmxext" },
{ CPU_FEATURE_3DNOW, "3dnow" },
{ CPU_FEATURE_3DNOWEXT, "3dnowext" },
{ CPU_FEATURE_NX, "nx" },
{ CPU_FEATURE_FXSR_OPT, "fxsr_opt" },
{ CPU_FEATURE_RDTSCP, "rdtscp" },
{ CPU_FEATURE_LM, "lm" },
{ CPU_FEATURE_LAHF_LM, "lahf_lm" },
{ CPU_FEATURE_CMP_LEGACY, "cmp_legacy" },
{ CPU_FEATURE_SVM, "svm" },
{ CPU_FEATURE_SSE4A, "sse4a" },
{ CPU_FEATURE_MISALIGNSSE, "misalignsse" },
{ CPU_FEATURE_ABM, "abm" },
{ CPU_FEATURE_3DNOWPREFETCH, "3dnowprefetch" },
{ CPU_FEATURE_OSVW, "osvw" },
{ CPU_FEATURE_IBS, "ibs" },
{ CPU_FEATURE_SSE5, "sse5" },
{ CPU_FEATURE_SKINIT, "skinit" },
{ CPU_FEATURE_WDT, "wdt" },
{ CPU_FEATURE_TS, "ts" },
{ CPU_FEATURE_FID, "fid" },
{ CPU_FEATURE_VID, "vid" },
{ CPU_FEATURE_TTP, "ttp" },
{ CPU_FEATURE_TM_AMD, "tm_amd" },
{ CPU_FEATURE_STC, "stc" },
{ CPU_FEATURE_100MHZSTEPS, "100mhzsteps" },
{ CPU_FEATURE_HWPSTATE, "hwpstate" },
{ CPU_FEATURE_CONSTANT_TSC, "constant_tsc" },
{ CPU_FEATURE_XOP, "xop" },
{ CPU_FEATURE_FMA3, "fma3" },
{ CPU_FEATURE_FMA4, "fma4" },
{ CPU_FEATURE_TBM, "tbm" },
{ CPU_FEATURE_F16C, "f16c" },
{ CPU_FEATURE_RDRAND, "rdrand" },
{ CPU_FEATURE_CPB, "cpb" },
{ CPU_FEATURE_APERFMPERF, "aperfmperf" },
{ CPU_FEATURE_PFI, "pfi" },
{ CPU_FEATURE_PA, "pa" },
{ CPU_FEATURE_AVX2, "avx2" },
{ CPU_FEATURE_BMI1, "bmi1" },
{ CPU_FEATURE_BMI2, "bmi2" },
{ CPU_FEATURE_HLE, "hle" },
{ CPU_FEATURE_RTM, "rtm" },
{ CPU_FEATURE_AVX512F, "avx512f" },
{ CPU_FEATURE_AVX512DQ, "avx512dq" },
{ CPU_FEATURE_AVX512PF, "avx512pf" },
{ CPU_FEATURE_AVX512ER, "avx512er" },
{ CPU_FEATURE_AVX512CD, "avx512cd" },
{ CPU_FEATURE_SHA_NI, "sha_ni" },
{ CPU_FEATURE_AVX512BW, "avx512bw" },
{ CPU_FEATURE_AVX512VL, "avx512vl" },
{ CPU_FEATURE_SGX, "sgx" },
{ CPU_FEATURE_RDSEED, "rdseed" },
{ CPU_FEATURE_ADX, "adx" },
};
unsigned i, n = COUNT_OF(matchtable);
if(n != NUM_CPU_FEATURES)
{
warnf("Warning: incomplete library, feature matchtable size differs from the actual number of features.\n");
}
for(i = 0; i < n; i++)
if(matchtable[i].feature == feature)
{
return matchtable[i].name;
}
return "";
}
const char* cpuid_error(void)
{
const struct
{
cpu_error_t error;
const char* description;
}
matchtable[] =
{
{ ERR_OK , "No error"},
{ ERR_NO_CPUID , "CPUID instruction is not supported"},
{ ERR_NO_RDTSC , "RDTSC instruction is not supported"},
{ ERR_NO_MEM , "Memory allocation failed"},
{ ERR_OPEN , "File open operation failed"},
{ ERR_BADFMT , "Bad file format"},
{ ERR_NOT_IMP , "Not implemented"},
{ ERR_CPU_UNKN , "Unsupported processor"},
{ ERR_NO_RDMSR , "RDMSR instruction is not supported"},
{ ERR_NO_DRIVER, "RDMSR driver error (generic)"},
{ ERR_NO_PERMS , "No permissions to install RDMSR driver"},
{ ERR_EXTRACT , "Cannot extract RDMSR driver (read only media?)"},
{ ERR_HANDLE , "Bad handle"},
{ ERR_INVMSR , "Invalid MSR"},
{ ERR_INVCNB , "Invalid core number"},
{ ERR_HANDLE_R , "Error on handle read"},
{ ERR_INVRANGE , "Invalid given range"},
};
unsigned i;
for(i = 0; i < COUNT_OF(matchtable); i++)
if(_libcpiud_errno == matchtable[i].error)
{
return matchtable[i].description;
}
return "Unknown error";
}
const char* cpuid_lib_version(void)
{
return VERSION;
}
libcpuid_warn_fn_t cpuid_set_warn_function(libcpuid_warn_fn_t new_fn)
{
libcpuid_warn_fn_t ret = _warn_fun;
_warn_fun = new_fn;
return ret;
}
void cpuid_set_verbosiness_level(int level)
{
_current_verboselevel = level;
}
cpu_vendor_t cpuid_get_vendor(void)
{
static cpu_vendor_t vendor = VENDOR_UNKNOWN;
uint32_t raw_vendor[4];
char vendor_str[VENDOR_STR_MAX];
if(vendor == VENDOR_UNKNOWN)
{
if(!cpuid_present())
{
set_error(ERR_NO_CPUID);
}
else
{
cpu_exec_cpuid(0, raw_vendor);
vendor = cpuid_vendor_identify(raw_vendor, vendor_str);
}
}
return vendor;
}
void cpuid_get_cpu_list(cpu_vendor_t vendor, struct cpu_list_t* list)
{
switch(vendor)
{
case VENDOR_INTEL:
cpuid_get_list_intel(list);
break;
case VENDOR_AMD:
cpuid_get_list_amd(list);
break;
case VENDOR_CYRIX:
make_list_from_string("Cx486,Cx5x86,6x86,6x86MX,M II,MediaGX,MediaGXi,MediaGXm", list);
break;
case VENDOR_NEXGEN:
make_list_from_string("Nx586", list);
break;
case VENDOR_TRANSMETA:
make_list_from_string("Crusoe,Efficeon", list);
break;
case VENDOR_UMC:
make_list_from_string("UMC x86 CPU", list);
break;
case VENDOR_CENTAUR:
make_list_from_string("VIA C3,VIA C7,VIA Nano", list);
break;
case VENDOR_RISE:
make_list_from_string("Rise mP6", list);
break;
case VENDOR_SIS:
make_list_from_string("SiS mP6", list);
break;
case VENDOR_NSC:
make_list_from_string("Geode GXm,Geode GXLV,Geode GX1,Geode GX2", list);
break;
default:
warnf("Unknown vendor passed to cpuid_get_cpu_list()\n");
break;
}
}
void cpuid_free_cpu_list(struct cpu_list_t* list)
{
int i;
if(list->num_entries <= 0)
{
return;
}
for(i = 0; i < list->num_entries; i++)
{
free(list->names[i]);
}
free(list->names);
}

View file

@ -28,7 +28,7 @@
* This file contains a list of internal codes we use in detection. It is
* of no external use and isn't a complete list of intel products.
*/
CODE2(PENTIUM, 2000),
CODE2(PENTIUM, 2000),
CODE(IRWIN),
CODE(POTOMAC),

View file

@ -85,7 +85,11 @@
@{ */
/* Include some integer type specifications: */
#ifdef _WIN32
#include "libcpuid_types.h"
#else
# include <stdint.h>
#endif
/* Some limits and other constants */
#include "libcpuid_constants.h"
@ -97,7 +101,8 @@ extern "C" {
/**
* @brief CPU vendor, as guessed from the Vendor String.
*/
typedef enum {
typedef enum
{
VENDOR_INTEL = 0, /*!< Intel CPU */
VENDOR_AMD, /*!< AMD CPU */
VENDOR_CYRIX, /*!< Cyrix CPU */
@ -121,7 +126,8 @@ typedef enum {
* and feature recognition. Every processor should be identifiable using this
* data only.
*/
struct cpu_raw_data_t {
struct cpu_raw_data_t
{
/** contains results of CPUID for eax = 0, 1, ...*/
uint32_t basic_cpuid[MAX_CPUID_LEVEL][4];
@ -173,7 +179,8 @@ struct cpu_raw_data_t {
* }
* @endcode
*/
struct cpu_sgx_t {
struct cpu_sgx_t
{
/** Whether SGX is present (boolean) */
uint32_t present;
@ -217,7 +224,8 @@ struct cpu_sgx_t {
/**
* @brief This contains the recognized CPU features/info
*/
struct cpu_id_t {
struct cpu_id_t
{
/** contains the CPU vendor string, e.g. "GenuineIntel" */
char vendor_str[VENDOR_STR_MAX];
@ -375,7 +383,8 @@ struct cpu_id_t {
* }
* @endcode
*/
typedef enum {
typedef enum
{
CPU_FEATURE_FPU = 0, /*!< Floating point unit */
CPU_FEATURE_VME, /*!< Virtual mode extension */
CPU_FEATURE_DE, /*!< Debugging extension */
@ -495,7 +504,8 @@ typedef enum {
*
* Usage: similar to the flags usage
*/
typedef enum {
typedef enum
{
CPU_HINT_SSE_SIZE_AUTH = 0, /*!< SSE unit size is authoritative (not only a Family/Model guesswork, but based on an actual CPUID bit) */
/* termination */
NUM_CPU_HINTS,
@ -523,7 +533,8 @@ typedef enum {
* @endcode
*/
typedef enum {
typedef enum
{
INTEL_SGX1, /*!< SGX1 instructions support */
INTEL_SGX2, /*!< SGX2 instructions support */
@ -534,7 +545,8 @@ typedef enum {
/**
* @brief Describes common library error codes
*/
typedef enum {
typedef enum
{
ERR_OK = 0, /*!< "No error" */
ERR_NO_CPUID = -1, /*!< "CPUID instruction is not supported" */
ERR_NO_RDTSC = -2, /*!< "RDTSC instruction is not supported" */
@ -544,7 +556,7 @@ typedef enum {
ERR_NOT_IMP = -6, /*!< "Not implemented" */
ERR_CPU_UNKN = -7, /*!< "Unsupported processor" */
ERR_NO_RDMSR = -8, /*!< "RDMSR instruction is not supported" */
ERR_NO_DRIVER= -9, /*!< "RDMSR driver error (generic)" */
ERR_NO_DRIVER = -9, /*!< "RDMSR driver error (generic)" */
ERR_NO_PERMS = -10, /*!< "No permissions to install RDMSR driver" */
ERR_EXTRACT = -11, /*!< "Cannot extract RDMSR driver (read only media?)" */
ERR_HANDLE = -12, /*!< "Bad handle" */
@ -558,7 +570,8 @@ typedef enum {
* @brief Internal structure, used in cpu_tsc_mark, cpu_tsc_unmark and
* cpu_clock_by_mark
*/
struct cpu_mark_t {
struct cpu_mark_t
{
uint64_t tsc; /*!< Time-stamp from RDTSC */
uint64_t sys_clock; /*!< In microsecond resolution */
};
@ -610,6 +623,39 @@ void cpu_exec_cpuid_ext(uint32_t* regs);
*/
int cpuid_get_raw_data(struct cpu_raw_data_t* data);
/**
* @brief Writes the raw CPUID data to a text file
* @param data - a pointer to cpu_raw_data_t structure
* @param filename - the path of the file, where the serialized data should be
* written. If empty, stdout will be used.
* @note This is intended primarily for debugging. On some processor, which is
* not currently supported or not completely recognized by cpu_identify,
* one can still successfully get the raw data and write it to a file.
* libcpuid developers can later import this file and debug the detection
* code as if running on the actual hardware.
* The file is simple text format of "something=value" pairs. Version info
* is also written, but the format is not intended to be neither backward-
* nor forward compatible.
* @returns zero if successful, and some negative number on error.
* The error message can be obtained by calling \ref cpuid_error.
* @see cpu_error_t
*/
int cpuid_serialize_raw_data(struct cpu_raw_data_t* data, const char* filename);
/**
* @brief Reads raw CPUID data from file
* @param data - a pointer to cpu_raw_data_t structure. The deserialized data will
* be written here.
* @param filename - the path of the file, containing the serialized raw data.
* If empty, stdin will be used.
* @note This function may fail, if the file is created by different version of
* the library. Also, see the notes on cpuid_serialize_raw_data.
* @returns zero if successful, and some negative number on error.
* The error message can be obtained by calling \ref cpuid_error.
* @see cpu_error_t
*/
int cpuid_deserialize_raw_data(struct cpu_raw_data_t* data, const char* filename);
/**
* @brief Identifies the CPU
* @param raw - Input - a pointer to the raw CPUID data, which is obtained
@ -635,6 +681,222 @@ int cpuid_get_raw_data(struct cpu_raw_data_t* data);
*/
int cpu_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data);
/**
* @brief Returns the short textual representation of a CPU flag
* @param feature - the feature, whose textual representation is wanted.
* @returns a constant string like "fpu", "tsc", "sse2", etc.
* @note the names of the returned flags are compatible with those from
* /proc/cpuinfo in Linux, with the exception of `tm_amd'
*/
const char* cpu_feature_str(cpu_feature_t feature);
/**
* @brief Returns textual description of the last error
*
* libcpuid stores an `errno'-style error status, whose description
* can be obtained with this function.
* @note This function is not thread-safe
* @see cpu_error_t
*/
const char* cpuid_error(void);
/**
* @brief Executes RDTSC
*
* The RDTSC (ReaD Time Stamp Counter) instruction gives access to an
* internal 64-bit counter, which usually increments at each clock cycle.
* This can be used for various timing routines, and as a very precise
* clock source. It is set to zero on system startup. Beware that may not
* increment at the same frequency as the CPU. Consecutive calls of RDTSC
* are, however, guaranteed to return monotonically-increasing values.
*
* @param result - a pointer to a 64-bit unsigned integer, where the TSC value
* will be stored
*
* @note If 100% compatibility is a concern, you must first check if the
* RDTSC instruction is present (if it is not, your program will crash
* with "invalid opcode" exception). Only some very old processors (i486,
* early AMD K5 and some Cyrix CPUs) lack that instruction - they should
* have become exceedingly rare these days. To verify RDTSC presence,
* run cpu_identify() and check flags[CPU_FEATURE_TSC].
*
* @note The monotonically increasing nature of the TSC may be violated
* on SMP systems, if their TSC clocks run at different rate. If the OS
* doesn't account for that, the TSC drift may become arbitrary large.
*/
void cpu_rdtsc(uint64_t* result);
/**
* @brief Store TSC and timing info
*
* This function stores the current TSC value and current
* time info from a precise OS-specific clock source in the cpu_mark_t
* structure. The sys_clock field contains time with microsecond resolution.
* The values can later be used to measure time intervals, number of clocks,
* FPU frequency, etc.
* @see cpu_rdtsc
*
* @param mark [out] - a pointer to a cpu_mark_t structure
*/
void cpu_tsc_mark(struct cpu_mark_t* mark);
/**
* @brief Calculate TSC and timing difference
*
* @param mark - input/output: a pointer to a cpu_mark_t sturcture, which has
* already been initialized by cpu_tsc_mark. The difference in
* TSC and time will be written here.
*
* This function calculates the TSC and time difference, by obtaining the
* current TSC and timing values and subtracting the contents of the `mark'
* structure from them. Results are written in the same structure.
*
* Example:
* @code
* ...
* struct cpu_mark_t mark;
* cpu_tsc_mark(&mark);
* foo();
* cpu_tsc_unmark(&mark);
* printf("Foo finished. Executed in %llu cycles and %llu usecs\n",
* mark.tsc, mark.sys_clock);
* ...
* @endcode
*/
void cpu_tsc_unmark(struct cpu_mark_t* mark);
/**
* @brief Calculates the CPU clock
*
* @param mark - pointer to a cpu_mark_t structure, which has been initialized
* with cpu_tsc_mark and later `stopped' with cpu_tsc_unmark.
*
* @note For reliable results, the marked time interval should be at least about
* 10 ms.
*
* @returns the CPU clock frequency, in MHz. Due to measurement error, it will
* differ from the true value in a few least-significant bits. Accuracy depends
* on the timing interval - the more, the better. If the timing interval is
* insufficient, the result is -1. Also, see the comment on cpu_clock_measure
* for additional issues and pitfalls in using RDTSC for CPU frequency
* measurements.
*/
int cpu_clock_by_mark(struct cpu_mark_t* mark);
/**
* @brief Returns the CPU clock, as reported by the OS
*
* This function uses OS-specific functions to obtain the CPU clock. It may
* differ from the true clock for several reasons:<br><br>
*
* i) The CPU might be in some power saving state, while the OS reports its
* full-power frequency, or vice-versa.<br>
* ii) In some cases you can raise or lower the CPU frequency with overclocking
* utilities and the OS will not notice.
*
* @returns the CPU clock frequency in MHz. If the OS is not (yet) supported
* or lacks the necessary reporting machinery, the return value is -1
*/
int cpu_clock_by_os(void);
/**
* @brief Measure the CPU clock frequency
*
* @param millis - How much time to waste in the busy-wait cycle. In millisecs.
* Useful values 10 - 1000
* @param quad_check - Do a more thorough measurement if nonzero
* (see the explanation).
*
* The function performs a busy-wait cycle for the given time and calculates
* the CPU frequency by the difference of the TSC values. The accuracy of the
* calculation depends on the length of the busy-wait cycle: more is better,
* but 100ms should be enough for most purposes.
*
* While this will calculate the CPU frequency correctly in most cases, there are
* several reasons why it might be incorrect:<br>
*
* i) RDTSC doesn't guarantee it will run at the same clock as the CPU.
* Apparently there aren't CPUs at the moment, but still, there's no
* guarantee.<br>
* ii) The CPU might be in a low-frequency power saving mode, and the CPU
* might be switched to higher frequency at any time. If this happens
* during the measurement, the result can be anywhere between the
* low and high frequencies. Also, if you're interested in the
* high frequency value only, this function might return the low one
* instead.<br>
* iii) On SMP systems exhibiting TSC drift (see \ref cpu_rdtsc)
*
* the quad_check option will run four consecutive measurements and
* then return the average of the two most-consistent results. The total
* runtime of the function will still be `millis' - consider using
* a bit more time for the timing interval.
*
* Finally, for benchmarking / CPU intensive applications, the best strategy is
* to use the cpu_tsc_mark() / cpu_tsc_unmark() / cpu_clock_by_mark() method.
* Begin by mark()-ing about one second after application startup (allowing the
* power-saving manager to kick in and rise the frequency during that time),
* then unmark() just before application finishing. The result will most
* acurately represent at what frequency your app was running.
*
* @returns the CPU clock frequency in MHz (within some measurement error
* margin). If RDTSC is not supported, the result is -1.
*/
int cpu_clock_measure(int millis, int quad_check);
/**
* @brief Measure the CPU clock frequency using instruction-counting
*
* @param millis - how much time to allocate for each run, in milliseconds
* @param runs - how many runs to perform
*
* The function performs a busy-wait cycle using a known number of "heavy" (SSE)
* instructions. These instructions run at (more or less guaranteed) 1 IPC rate,
* so by running a busy loop for a fixed amount of time, and measuring the
* amount of instructions done, the CPU clock is accurately measured.
*
* Of course, this function is still affected by the power-saving schemes, so
* the warnings as of cpu_clock_measure() still apply. However, this function is
* immune to problems with detection, related to the Intel Nehalem's "Turbo"
* mode, where the internal clock is raised, but the RDTSC rate is unaffected.
*
* The function will run for about (millis * runs) milliseconds.
* You can make only a single busy-wait run (runs == 1); however, this can
* be affected by task scheduling (which will break the counting), so allowing
* more than one run is recommended. As run length is not imperative for
* accurate readings (e.g., 50ms is sufficient), you can afford a lot of short
* runs, e.g. 10 runs of 50ms or 20 runs of 25ms.
*
* Recommended values - millis = 50, runs = 4. For more robustness,
* increase the number of runs.
*
* NOTE: on Bulldozer and later CPUs, the busy-wait cycle runs at 1.4 IPC, thus
* the results are skewed. This is corrected internally by dividing the resulting
* value by 1.4.
* However, this only occurs if the thread is executed on a single CMT
* module - if there are other threads competing for resources, the results are
* unpredictable. Make sure you run cpu_clock_by_ic() on a CPU that is free from
* competing threads, or if there are such threads, they shouldn't exceed the
* number of modules. On a Bulldozer X8, that means 4 threads.
*
* @returns the CPU clock frequency in MHz (within some measurement error
* margin). If SSE is not supported, the result is -1. If the input parameters
* are incorrect, or some other internal fault is detected, the result is -2.
*/
int cpu_clock_by_ic(int millis, int runs);
/**
* @brief Get the CPU clock frequency (all-in-one method)
*
* This is an all-in-one method for getting the CPU clock frequency.
* It tries to use the OS for that. If the OS doesn't have this info, it
* uses cpu_clock_measure with 200ms time interval and quadruple checking.
*
* @returns the CPU clock frequency in MHz. If every possible method fails,
* the result is -1.
*/
int cpu_clock(void);
/**
* @brief The return value of cpuid_get_epc().
* @details
@ -642,7 +904,8 @@ int cpu_identify(struct cpu_raw_data_t* raw, struct cpu_id_t* data);
* A CPU may have one or more EPC areas, and information about each is
* fetched via \ref cpuid_get_epc.
*/
struct cpu_epc_t {
struct cpu_epc_t
{
uint64_t start_addr;
uint64_t length;
};
@ -667,6 +930,232 @@ struct cpu_epc_t cpuid_get_epc(int index, const struct cpu_raw_data_t* raw);
*/
const char* cpuid_lib_version(void);
typedef void (*libcpuid_warn_fn_t)(const char* msg);
/**
* @brief Sets the warning print function
*
* In some cases, the internal libcpuid machinery would like to emit useful
* debug warnings. By default, these warnings are written to stderr. However,
* you can set a custom function that will receive those warnings.
*
* @param warn_fun - the warning function you want to set. If NULL, warnings
* are disabled. The function takes const char* argument.
*
* @returns the current warning function. You can use the return value to
* keep the previous warning function and restore it at your discretion.
*/
libcpuid_warn_fn_t cpuid_set_warn_function(libcpuid_warn_fn_t warn_fun);
/**
* @brief Sets the verbosiness level
*
* When the verbosiness level is above zero, some functions might print
* diagnostic information about what are they doing. The higher the level is,
* the more detail is printed. Level zero is guaranteed to omit all such
* output. The output is written using the same machinery as the warnings,
* @see cpuid_set_warn_function()
*
* @param level the desired verbosiness level. Useful values 0..2 inclusive
*/
void cpuid_set_verbosiness_level(int level);
/**
* @brief Obtains the CPU vendor from CPUID from the current CPU
* @note The result is cached.
* @returns VENDOR_UNKNOWN if failed, otherwise the CPU vendor type.
* @see cpu_vendor_t
*/
cpu_vendor_t cpuid_get_vendor(void);
/**
* @brief a structure that holds a list of processor names
*/
struct cpu_list_t
{
/** Number of entries in the list */
int num_entries;
/** Pointers to names. There will be num_entries of them */
char** names;
};
/**
* @brief Gets a list of all known CPU names from a specific vendor.
*
* This function compiles a list of all known CPU (code)names
* (i.e. the possible values of cpu_id_t::cpu_codename) for the given vendor.
*
* There are about 100 entries for Intel and AMD, and a few for the other
* vendors. The list is written out in approximate chronological introduction
* order of the parts.
*
* @param vendor the vendor to be queried
* @param list [out] the resulting list will be written here.
* NOTE: As the memory is dynamically allocated, be sure to call
* cpuid_free_cpu_list() after you're done with the data
* @see cpu_list_t
*/
void cpuid_get_cpu_list(cpu_vendor_t vendor, struct cpu_list_t* list);
/**
* @brief Frees a CPU list
*
* This function deletes all the memory associated with a CPU list, as obtained
* by cpuid_get_cpu_list()
*
* @param list - the list to be free()'d.
*/
void cpuid_free_cpu_list(struct cpu_list_t* list);
struct msr_driver_t;
/**
* @brief Starts/opens a driver, needed to read MSRs (Model Specific Registers)
*
* On systems that support it, this function will create a temporary
* system driver, that has privileges to execute the RDMSR instruction.
* After the driver is created, you can read MSRs by calling \ref cpu_rdmsr
*
* @returns a handle to the driver on success, and NULL on error.
* The error message can be obtained by calling \ref cpuid_error.
* @see cpu_error_t
*/
struct msr_driver_t* cpu_msr_driver_open(void);
/**
* @brief Similar to \ref cpu_msr_driver_open, but accept one parameter
*
* This function works on certain operating systems (GNU/Linux, FreeBSD)
*
* @param core_num specify the core number for MSR.
* The first core number is 0.
* The last core number is \ref cpuid_get_total_cpus - 1.
*
* @returns a handle to the driver on success, and NULL on error.
* The error message can be obtained by calling \ref cpuid_error.
* @see cpu_error_t
*/
struct msr_driver_t* cpu_msr_driver_open_core(unsigned core_num);
/**
* @brief Reads a Model-Specific Register (MSR)
*
* If the CPU has MSRs (as indicated by the CPU_FEATURE_MSR flag), you can
* read a MSR with the given index by calling this function.
*
* There are several prerequisites you must do before reading MSRs:
* 1) You must ensure the CPU has RDMSR. Check the CPU_FEATURE_MSR flag
* in cpu_id_t::flags
* 2) You must ensure that the CPU implements the specific MSR you intend to
* read.
* 3) You must open a MSR-reader driver. RDMSR is a privileged instruction and
* needs ring-0 access in order to work. This temporary driver is created
* by calling \ref cpu_msr_driver_open
*
* @param handle - a handle to the MSR reader driver, as created by
* cpu_msr_driver_open
* @param msr_index - the numeric ID of the MSR you want to read
* @param result - a pointer to a 64-bit integer, where the MSR value is stored
*
* @returns zero if successful, and some negative number on error.
* The error message can be obtained by calling \ref cpuid_error.
* @see cpu_error_t
*/
int cpu_rdmsr(struct msr_driver_t* handle, uint32_t msr_index, uint64_t* result);
typedef enum
{
INFO_MPERF, /*!< Maximum performance frequency clock. This
is a counter, which increments as a
proportion of the actual processor speed. */
INFO_APERF, /*!< Actual performance frequency clock. This
accumulates the core clock counts when the
core is active. */
INFO_MIN_MULTIPLIER, /*!< Minimum CPU:FSB ratio for this CPU,
multiplied by 100. */
INFO_CUR_MULTIPLIER, /*!< Current CPU:FSB ratio, multiplied by 100.
e.g., a CPU:FSB value of 18.5 reads as
"1850". */
INFO_MAX_MULTIPLIER, /*!< Maximum CPU:FSB ratio for this CPU,
multiplied by 100. */
INFO_TEMPERATURE, /*!< The current core temperature in Celsius. */
INFO_THROTTLING, /*!< 1 if the current logical processor is
throttling. 0 if it is running normally. */
INFO_VOLTAGE, /*!< The current core voltage in Volt,
multiplied by 100. */
INFO_BCLK, /*!< See \ref INFO_BUS_CLOCK. */
INFO_BUS_CLOCK, /*!< The main bus clock in MHz,
e.g., FSB/QPI/DMI/HT base clock,
multiplied by 100. */
} cpu_msrinfo_request_t;
/**
* @brief Similar to \ref cpu_rdmsr, but extract a range of bits
*
* @param handle - a handle to the MSR reader driver, as created by
* cpu_msr_driver_open
* @param msr_index - the numeric ID of the MSR you want to read
* @param highbit - the high bit in range, must be inferior to 64
* @param lowbit - the low bit in range, must be equal or superior to 0
* @param result - a pointer to a 64-bit integer, where the MSR value is stored
*
* @returns zero if successful, and some negative number on error.
* The error message can be obtained by calling \ref cpuid_error.
* @see cpu_error_t
*/
int cpu_rdmsr_range(struct msr_driver_t* handle, uint32_t msr_index, uint8_t highbit,
uint8_t lowbit, uint64_t* result);
/**
* @brief Reads extended CPU information from Model-Specific Registers.
* @param handle - a handle to an open MSR driver, @see cpu_msr_driver_open
* @param which - which info field should be returned. A list of
* available information entities is listed in the
* cpu_msrinfo_request_t enum.
* @retval - if the requested information is available for the current
* processor model, the respective value is returned.
* if no information is available, or the CPU doesn't support
* the query, the special value CPU_INVALID_VALUE is returned
* @note This function is not MT-safe. If you intend to call it from multiple
* threads, guard it through a mutex or a similar primitive.
*/
int cpu_msrinfo(struct msr_driver_t* handle, cpu_msrinfo_request_t which);
#define CPU_INVALID_VALUE 0x3fffffff
/**
* @brief Writes the raw MSR data to a text file
* @param data - a pointer to msr_driver_t structure
* @param filename - the path of the file, where the serialized data should be
* written. If empty, stdout will be used.
* @note This is intended primarily for debugging. On some processor, which is
* not currently supported or not completely recognized by cpu_identify,
* one can still successfully get the raw data and write it to a file.
* libcpuid developers can later import this file and debug the detection
* code as if running on the actual hardware.
* The file is simple text format of "something=value" pairs. Version info
* is also written, but the format is not intended to be neither backward-
* nor forward compatible.
* @returns zero if successful, and some negative number on error.
* The error message can be obtained by calling \ref cpuid_error.
* @see cpu_error_t
*/
int msr_serialize_raw_data(struct msr_driver_t* handle, const char* filename);
/**
* @brief Closes an open MSR driver
*
* This function unloads the MSR driver opened by cpu_msr_driver_open and
* frees any resources associated with it.
*
* @param handle - a handle to the MSR reader driver, as created by
* cpu_msr_driver_open
*
* @returns zero if successful, and some negative number on error.
* The error message can be obtained by calling \ref cpuid_error.
* @see cpu_error_t
*/
int cpu_msr_driver_close(struct msr_driver_t* handle);
#ifdef __cplusplus
}; /* extern "C" */
#endif

View file

@ -30,27 +30,32 @@
* for the workings of the internal library infrastructure.
*/
enum _common_codes_t {
enum _common_codes_t
{
NA = 0,
NC, /* No code */
};
#define CODE(x) x
#define CODE2(x, y) x = y
enum _amd_code_t {
#include "amd_code_t.h"
enum _amd_code_t
{
#include "amd_code_t.h"
};
typedef enum _amd_code_t amd_code_t;
enum _intel_code_t {
#include "intel_code_t.h"
enum _intel_code_t
{
#include "intel_code_t.h"
};
typedef enum _intel_code_t intel_code_t;
#undef CODE
#undef CODE2
struct internal_id_info_t {
union {
struct internal_id_info_t
{
union
{
amd_code_t amd;
intel_code_t intel;
} code;
@ -60,41 +65,44 @@ struct internal_id_info_t {
#define LBIT(x) (((long long) 1) << x)
enum _common_bits_t {
_M_ = LBIT( 0 ),
MOBILE_ = LBIT( 1 ),
_MP_ = LBIT( 2 ),
enum _common_bits_t
{
_M_ = LBIT(0),
MOBILE_ = LBIT(1),
_MP_ = LBIT(2),
};
// additional detection bits for Intel CPUs:
enum _intel_bits_t {
PENTIUM_ = LBIT( 10 ),
CELERON_ = LBIT( 11 ),
CORE_ = LBIT( 12 ),
_I_ = LBIT( 13 ),
_3 = LBIT( 14 ),
_5 = LBIT( 15 ),
_7 = LBIT( 16 ),
XEON_ = LBIT( 17 ),
ATOM_ = LBIT( 18 ),
enum _intel_bits_t
{
PENTIUM_ = LBIT(10),
CELERON_ = LBIT(11),
CORE_ = LBIT(12),
_I_ = LBIT(13),
_3 = LBIT(14),
_5 = LBIT(15),
_7 = LBIT(16),
XEON_ = LBIT(17),
ATOM_ = LBIT(18),
};
typedef enum _intel_bits_t intel_bits_t;
enum _amd_bits_t {
ATHLON_ = LBIT( 10 ),
_XP_ = LBIT( 11 ),
DURON_ = LBIT( 12 ),
SEMPRON_ = LBIT( 13 ),
OPTERON_ = LBIT( 14 ),
TURION_ = LBIT( 15 ),
_LV_ = LBIT( 16 ),
_64_ = LBIT( 17 ),
_X2 = LBIT( 18 ),
_X3 = LBIT( 19 ),
_X4 = LBIT( 20 ),
_X6 = LBIT( 21 ),
_FX = LBIT( 22 ),
_APU_ = LBIT( 23 ),
enum _amd_bits_t
{
ATHLON_ = LBIT(10),
_XP_ = LBIT(11),
DURON_ = LBIT(12),
SEMPRON_ = LBIT(13),
OPTERON_ = LBIT(14),
TURION_ = LBIT(15),
_LV_ = LBIT(16),
_64_ = LBIT(17),
_X2 = LBIT(18),
_X3 = LBIT(19),
_X4 = LBIT(20),
_X6 = LBIT(21),
_FX = LBIT(22),
_APU_ = LBIT(23),
};
typedef enum _amd_bits_t amd_bits_t;

View file

@ -32,6 +32,36 @@
#ifndef __LIBCPUID_TYPES_H__
#define __LIBCPUID_TYPES_H__
#include <stdint.h>
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#if defined(HAVE_STDINT_H)
# include <stdint.h>
#else
/* we have to provide our own: */
# if !defined(HAVE_INT32_T) && !defined(__int32_t_defined)
typedef int int32_t;
# endif
# if !defined(HAVE_UINT32_T) && !defined(__uint32_t_defined)
typedef unsigned uint32_t;
# endif
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
#if (defined _MSC_VER) && (_MSC_VER <= 1300)
/* MSVC 6.0: no long longs ... */
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
#else
/* all other sane compilers: */
typedef signed long long int64_t;
typedef unsigned long long uint64_t;
#endif
#endif
#endif /* __LIBCPUID_TYPES_H__ */

View file

@ -32,27 +32,212 @@
#include "libcpuid.h"
#include "libcpuid_util.h"
int _current_verboselevel;
void match_features(const struct feature_map_t* matchtable, int count, uint32_t reg, struct cpu_id_t* data)
{
int i;
for (i = 0; i < count; i++)
if (reg & (1u << matchtable[i].bit))
for(i = 0; i < count; i++)
if(reg & (1u << matchtable[i].bit))
{
data->flags[matchtable[i].feature] = 1;
}
}
static void default_warn(const char* msg)
{
fprintf(stderr, "%s", msg);
}
libcpuid_warn_fn_t _warn_fun = default_warn;
#if defined(_MSC_VER)
# define vsnprintf _vsnprintf
#endif
void warnf(const char* format, ...)
{
char buff[1024];
va_list va;
if(!_warn_fun)
{
return;
}
va_start(va, format);
vsnprintf(buff, sizeof(buff), format, va);
va_end(va);
_warn_fun(buff);
}
void debugf(int verboselevel, const char* format, ...)
{
char buff[1024];
va_list va;
if(verboselevel > _current_verboselevel)
{
return;
}
va_start(va, format);
vsnprintf(buff, sizeof(buff), format, va);
va_end(va);
_warn_fun(buff);
}
static int popcount64(uint64_t mask)
{
int num_set_bits = 0;
while(mask)
{
mask &= mask - 1;
num_set_bits++;
}
return num_set_bits;
}
static int score(const struct match_entry_t* entry, const struct cpu_id_t* data,
int brand_code, uint64_t bits, int model_code)
{
int res = 0;
if(entry->family == data->family)
{
res += 2;
}
if(entry->model == data->model)
{
res += 2;
}
if(entry->stepping == data->stepping)
{
res += 2;
}
if(entry->ext_family == data->ext_family)
{
res += 2;
}
if(entry->ext_model == data->ext_model)
{
res += 2;
}
if(entry->ncores == data->num_cores)
{
res += 2;
}
if(entry->l2cache == data->l2_cache)
{
res += 1;
}
if(entry->l3cache == data->l3_cache)
{
res += 1;
}
if(entry->brand_code == brand_code)
{
res += 2;
}
if(entry->model_code == model_code)
{
res += 2;
}
res += popcount64(entry->model_bits & bits) * 2;
return res;
}
int match_cpu_codename(const struct match_entry_t* matchtable, int count,
struct cpu_id_t* data, int brand_code, uint64_t bits,
int model_code)
{
int bestscore = -1;
int bestindex = 0;
int i, t;
debugf(3, "Matching cpu f:%d, m:%d, s:%d, xf:%d, xm:%d, ncore:%d, l2:%d, bcode:%d, bits:%llu, code:%d\n",
data->family, data->model, data->stepping, data->ext_family,
data->ext_model, data->num_cores, data->l2_cache, brand_code, (unsigned long long) bits, model_code);
for(i = 0; i < count; i++)
{
t = score(&matchtable[i], data, brand_code, bits, model_code);
debugf(3, "Entry %d, `%s', score %d\n", i, matchtable[i].name, t);
if(t > bestscore)
{
debugf(2, "Entry `%s' selected - best score so far (%d)\n", matchtable[i].name, t);
bestscore = t;
bestindex = i;
}
}
strcpy(data->cpu_codename, matchtable[bestindex].name);
return bestscore;
}
void generic_get_cpu_list(const struct match_entry_t* matchtable, int count,
struct cpu_list_t* list)
{
int i, j, n, good;
n = 0;
list->names = (char**) malloc(sizeof(char*) * count);
for(i = 0; i < count; i++)
{
if(strstr(matchtable[i].name, "Unknown"))
{
continue;
}
good = 1;
for(j = n - 1; j >= 0; j--)
if(!strcmp(list->names[j], matchtable[i].name))
{
good = 0;
break;
}
if(!good)
{
continue;
}
#if defined(_MSC_VER)
list->names[n++] = _strdup(matchtable[i].name);
#else
list->names[n++] = strdup(matchtable[i].name);
#endif
}
list->num_entries = n;
}
static int xmatch_entry(char c, const char* p)
{
int i, j;
if (c == 0) return -1;
if (c == p[0]) return 1;
if (p[0] == '.') return 1;
if (p[0] == '#' && isdigit(c)) return 1;
if (p[0] == '[') {
if(c == 0)
{
return -1;
}
if(c == p[0])
{
return 1;
}
if(p[0] == '.')
{
return 1;
}
if(p[0] == '#' && isdigit(c))
{
return 1;
}
if(p[0] == '[')
{
j = 1;
while (p[j] && p[j] != ']') j++;
if (!p[j]) return -1;
for (i = 1; i < j; i++)
if (p[i] == c) return j + 1;
while(p[j] && p[j] != ']')
{
j++;
}
if(!p[j])
{
return -1;
}
for(i = 1; i < j; i++)
if(p[i] == c)
{
return j + 1;
}
}
return -1;
}
@ -62,15 +247,21 @@ int match_pattern(const char* s, const char* p)
int i, j, dj, k, n, m;
n = (int) strlen(s);
m = (int) strlen(p);
for (i = 0; i < n; i++) {
if (xmatch_entry(s[i], p) != -1) {
for(i = 0; i < n; i++)
{
if(xmatch_entry(s[i], p) != -1)
{
j = 0;
k = 0;
while (j < m && ((dj = xmatch_entry(s[i + k], p + j)) != -1)) {
while(j < m && ((dj = xmatch_entry(s[i + k], p + j)) != -1))
{
k++;
j += dj;
}
if (j == m) return i + 1;
if(j == m)
{
return i + 1;
}
}
}
return 0;
@ -80,9 +271,14 @@ struct cpu_id_t* get_cached_cpuid(void)
{
static int initialized = 0;
static struct cpu_id_t id;
if (initialized) return &id;
if (cpu_identify(NULL, &id))
if(initialized)
{
return &id;
}
if(cpu_identify(NULL, &id))
{
memset(&id, 0, sizeof(id));
}
initialized = 1;
return &id;
}
@ -91,3 +287,21 @@ int match_all(uint64_t bits, uint64_t mask)
{
return (bits & mask) == mask;
}
void debug_print_lbits(int debuglevel, uint64_t mask)
{
int i, first = 0;
for(i = 0; i < 64; i++) if(mask & (((uint64_t) 1) << i))
{
if(first)
{
first = 0;
}
else
{
debugf(2, " + ");
}
debugf(2, "LBIT(%d)", i);
}
debugf(2, "\n");
}

View file

@ -28,7 +28,8 @@
#define COUNT_OF(array) (sizeof(array) / sizeof(array[0]))
struct feature_map_t {
struct feature_map_t
{
unsigned bit;
cpu_feature_t feature;
};
@ -36,7 +37,8 @@ struct feature_map_t {
void match_features(const struct feature_map_t* matchtable, int count,
uint32_t reg, struct cpu_id_t* data);
struct match_entry_t {
struct match_entry_t
{
int family, model, stepping, ext_family, ext_model;
int ncores, l2cache, l3cache, brand_code;
uint64_t model_bits;
@ -48,6 +50,20 @@ struct match_entry_t {
int match_cpu_codename(const struct match_entry_t* matchtable, int count,
struct cpu_id_t* data, int brand_code, uint64_t bits,
int model_code);
void warnf(const char* format, ...)
#ifdef __GNUC__
__attribute__((format(printf, 1, 2)))
#endif
;
void debugf(int verboselevel, const char* format, ...)
#ifdef __GNUC__
__attribute__((format(printf, 2, 3)))
#endif
;
void generic_get_cpu_list(const struct match_entry_t* matchtable, int count,
struct cpu_list_t* list);
/*
* Seek for a pattern in `haystack'.
* Pattern may be an fixed string, or contain the special metacharacters
@ -70,9 +86,15 @@ struct cpu_id_t* get_cached_cpuid(void);
/* returns true if all bits of mask are present in `bits'. */
int match_all(uint64_t bits, uint64_t mask);
/* print what bits a mask consists of */
void debug_print_lbits(int debuglevel, uint64_t mask);
/*
* Sets the current errno
*/
int set_error(cpu_error_t err);
extern libcpuid_warn_fn_t _warn_fun;
extern int _current_verboselevel;
#endif /* __LIBCPUID_UTIL_H__ */

595
src/3rdparty/libcpuid/msrdriver.c vendored Normal file
View file

@ -0,0 +1,595 @@
/*
* Copyright 2009 Veselin Georgiev,
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @File msrdriver.c
* @Brief Contains the binary images of the x86 and x64 MSR drivers for Windows
* @Date 2009-09-29
*
* The driver is courtesy of Nick 'Bombera' Gabareff, and its source is actually
* available, see the contrib/ dir.
*
* However, for simplicity, here we just include the images of the compiled .SYS
* files.
* They are extracted to the filesystem on demand and loaded in the kernel
* by the cpu_msr_driver_open() function
*/
#ifdef _WIN32
#include "asm-bits.h"
//begin {
int cc_x86driver_code_size = 4608;
uint8_t cc_x86driver_code[4608] =
{
0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xb8, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,
0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d,
0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20,
0x44, 0x4f, 0x53, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x9f, 0x99, 0x48, 0xdf, 0xdb, 0xf8, 0x26, 0x8c, 0xdb, 0xf8, 0x26, 0x8c, 0xdb, 0xf8, 0x26, 0x8c,
0xdb, 0xf8, 0x27, 0x8c, 0xdd, 0xf8, 0x26, 0x8c, 0x21, 0xdb, 0x3f, 0x8c, 0xd8, 0xf8, 0x26, 0x8c, 0xfc, 0x3e,
0x57, 0x8c, 0xda, 0xf8, 0x26, 0x8c, 0xfc, 0x3e, 0x5a, 0x8c, 0xda, 0xf8, 0x26, 0x8c, 0xfc, 0x3e, 0x5e, 0x8c,
0xda, 0xf8, 0x26, 0x8c, 0x52, 0x69, 0x63, 0x68, 0xdb, 0xf8, 0x26, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x50, 0x45, 0x00, 0x00, 0x4c, 0x01, 0x07, 0x00, 0x12, 0x9b, 0x9b, 0x4a, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x02, 0x21, 0x0b, 0x01, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0a,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
0xa9, 0xd1, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xc0, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x70, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x74,
0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
0x00, 0x68, 0x2e, 0x72, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x40, 0x00, 0x00, 0x48, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xc8, 0x50, 0x41, 0x47, 0x45, 0x30, 0x44, 0x45, 0x46,
0x8c, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x60, 0x49, 0x4e, 0x49, 0x54,
0x00, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0a,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xe2,
0x2e, 0x72, 0x73, 0x72, 0x63, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x00, 0x00, 0x42, 0x2e, 0x72, 0x65, 0x6c, 0x6f, 0x63, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x70,
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0x4c,
0x24, 0x08, 0x83, 0x61, 0x18, 0x00, 0x83, 0x61, 0x1c, 0x00, 0x32, 0xd2, 0xff, 0x15, 0x08, 0x20, 0x01, 0x00,
0x33, 0xc0, 0xc2, 0x08, 0x00, 0x56, 0x8b, 0x74, 0x24, 0x0c, 0x8b, 0x46, 0x60, 0x81, 0x78, 0x0c, 0x0c, 0xe0,
0x22, 0x00, 0x57, 0x75, 0x3c, 0x83, 0x78, 0x04, 0x08, 0x72, 0x36, 0x83, 0x78, 0x08, 0x04, 0x75, 0x07, 0x8b,
0x46, 0x0c, 0x8b, 0x08, 0xeb, 0x05, 0xb9, 0x9c, 0x01, 0x00, 0x00, 0x8b, 0x7e, 0x0c, 0x0f, 0x32, 0x89, 0x07,
0x89, 0x57, 0x04, 0xc7, 0x46, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x33, 0xff, 0x32, 0xd2, 0x8b, 0xce, 0xff, 0x15,
0x08, 0x20, 0x01, 0x00, 0x8b, 0xc7, 0x5f, 0x5e, 0xc2, 0x08, 0x00, 0x83, 0x66, 0x1c, 0x00, 0xbf, 0x01, 0x00,
0x00, 0xc0, 0x89, 0x7e, 0x18, 0xeb, 0xe1, 0x55, 0x8b, 0xec, 0x51, 0x51, 0x8b, 0x45, 0x08, 0xff, 0x70, 0x04,
0xff, 0x15, 0x04, 0x20, 0x01, 0x00, 0x68, 0x3c, 0x20, 0x01, 0x00, 0x8d, 0x45, 0xf8, 0x50, 0xff, 0x15, 0x00,
0x20, 0x01, 0x00, 0x8d, 0x45, 0xf8, 0x50, 0xff, 0x15, 0x14, 0x20, 0x01, 0x00, 0xc9, 0xc2, 0x04, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x50, 0x00, 0x00, 0x74, 0x50, 0x00, 0x00, 0x86, 0x50, 0x00, 0x00,
0x9c, 0x50, 0x00, 0x00, 0xb4, 0x50, 0x00, 0x00, 0x44, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00,
0x44, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x5c, 0x00, 0x54, 0x00, 0x6d, 0x00,
0x70, 0x00, 0x52, 0x00, 0x64, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x44, 0x00, 0x6f, 0x00,
0x73, 0x00, 0x44, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, 0x5c, 0x00,
0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, 0x64, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x8b, 0xec, 0x83,
0xec, 0x14, 0x56, 0x8b, 0x35, 0x00, 0x20, 0x01, 0x00, 0x57, 0x68, 0x1c, 0x20, 0x01, 0x00, 0x8d, 0x45, 0xf4,
0x50, 0xff, 0xd6, 0x8b, 0x7d, 0x08, 0x8d, 0x45, 0xfc, 0x50, 0x6a, 0x00, 0x6a, 0x00, 0x6a, 0x22, 0x8d, 0x45,
0xf4, 0x50, 0x6a, 0x04, 0x57, 0xff, 0x15, 0x10, 0x20, 0x01, 0x00, 0x85, 0xc0, 0x75, 0x4f, 0x68, 0x3c, 0x20,
0x01, 0x00, 0x8d, 0x45, 0xec, 0x50, 0xff, 0xd6, 0x8d, 0x45, 0xf4, 0x50, 0x8d, 0x45, 0xec, 0x50, 0xff, 0x15,
0x0c, 0x20, 0x01, 0x00, 0x8b, 0xf0, 0x85, 0xf6, 0x74, 0x0d, 0xff, 0x75, 0xfc, 0xff, 0x15, 0x04, 0x20, 0x01,
0x00, 0x8b, 0xc6, 0xeb, 0x23, 0x8b, 0x45, 0xfc, 0xa3, 0x00, 0x30, 0x01, 0x00, 0xb8, 0x00, 0x10, 0x01, 0x00,
0x89, 0x47, 0x38, 0x89, 0x47, 0x40, 0xc7, 0x47, 0x34, 0x75, 0x10, 0x01, 0x00, 0xc7, 0x47, 0x70, 0x19, 0x10,
0x01, 0x00, 0x33, 0xc0, 0x5f, 0x5e, 0xc9, 0xc2, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x28, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x50,
0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x50, 0x00, 0x00, 0x74, 0x50, 0x00, 0x00, 0x86, 0x50,
0x00, 0x00, 0x9c, 0x50, 0x00, 0x00, 0xb4, 0x50, 0x00, 0x00, 0x44, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x4b, 0x01, 0x49, 0x6f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x63,
0x4c, 0x69, 0x6e, 0x6b, 0x00, 0x00, 0x0b, 0x04, 0x52, 0x74, 0x6c, 0x49, 0x6e, 0x69, 0x74, 0x55, 0x6e, 0x69,
0x63, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x49, 0x01, 0x49, 0x6f, 0x44, 0x65,
0x6c, 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0xda, 0x01, 0x49, 0x6f, 0x66, 0x43,
0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x00, 0x00, 0x41, 0x01,
0x49, 0x6f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x63, 0x4c, 0x69,
0x6e, 0x6b, 0x00, 0x00, 0x38, 0x01, 0x49, 0x6f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69,
0x63, 0x65, 0x00, 0x00, 0x6e, 0x74, 0x6f, 0x73, 0x6b, 0x72, 0x6e, 0x6c, 0x2e, 0x65, 0x78, 0x65, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
0x00, 0x00, 0x30, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x09, 0x04, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x5c, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x5c, 0x03, 0x34, 0x00, 0x00, 0x00, 0x56, 0x00, 0x53, 0x00, 0x5f, 0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x00,
0x53, 0x00, 0x49, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x5f, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x46, 0x00, 0x4f, 0x00,
0x00, 0x00, 0x00, 0x00, 0xbd, 0x04, 0xef, 0xfe, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xba, 0x02, 0x00, 0x00, 0x01, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00,
0x67, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x6f, 0x00,
0x00, 0x00, 0x96, 0x02, 0x00, 0x00, 0x01, 0x00, 0x30, 0x00, 0x34, 0x00, 0x30, 0x00, 0x39, 0x00, 0x30, 0x00,
0x34, 0x00, 0x62, 0x00, 0x30, 0x00, 0x00, 0x00, 0x58, 0x00, 0x20, 0x00, 0x01, 0x00, 0x43, 0x00, 0x6f, 0x00,
0x6d, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x53, 0x00,
0x52, 0x00, 0x20, 0x00, 0x72, 0x00, 0x65, 0x00, 0x61, 0x00, 0x64, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00,
0x33, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x69, 0x00, 0x74, 0x00, 0x20, 0x00, 0x6b, 0x00, 0x65, 0x00,
0x72, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x64, 0x00, 0x72, 0x00, 0x69, 0x00, 0x76, 0x00,
0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x42, 0x00, 0x11, 0x00, 0x01, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x6d, 0x00,
0x70, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x79, 0x00, 0x4e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00,
0x00, 0x00, 0x49, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x65, 0x00,
0x65, 0x00, 0x64, 0x00, 0x73, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x2e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x60, 0x00, 0x1c, 0x00, 0x01, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x44, 0x00,
0x65, 0x00, 0x73, 0x00, 0x63, 0x00, 0x72, 0x00, 0x69, 0x00, 0x70, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00,
0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, 0x64, 0x00, 0x72, 0x00,
0x20, 0x00, 0x33, 0x00, 0x32, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x69, 0x00, 0x74, 0x00, 0x20, 0x00, 0x4b, 0x00,
0x65, 0x00, 0x72, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x4d, 0x00, 0x6f, 0x00, 0x64, 0x00,
0x75, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x36, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x46, 0x00, 0x69, 0x00,
0x6c, 0x00, 0x65, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00,
0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x30, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x30, 0x00,
0x2c, 0x00, 0x20, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x07, 0x00, 0x01, 0x00, 0x49, 0x00,
0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x4e, 0x00, 0x61, 0x00,
0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, 0x64, 0x00, 0x72, 0x00,
0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x13, 0x00, 0x01, 0x00, 0x4c, 0x00, 0x65, 0x00, 0x67, 0x00, 0x61, 0x00,
0x6c, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00,
0x74, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x69, 0x00, 0x63, 0x00, 0x6b, 0x00, 0x20, 0x00, 0x47, 0x00, 0x61, 0x00,
0x62, 0x00, 0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x76, 0x00, 0x20, 0x00, 0x27, 0x00, 0x32, 0x00, 0x30, 0x00,
0x30, 0x00, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x72, 0x00,
0x69, 0x00, 0x67, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00,
0x65, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00,
0x52, 0x00, 0x64, 0x00, 0x72, 0x00, 0x2e, 0x00, 0x73, 0x00, 0x79, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00,
0x54, 0x00, 0x1a, 0x00, 0x01, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x75, 0x00, 0x63, 0x00,
0x74, 0x00, 0x4e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x6f, 0x00,
0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x32, 0x00, 0x20, 0x00, 0x54, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x70, 0x00,
0x65, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x75, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x52, 0x00,
0x65, 0x00, 0x61, 0x00, 0x64, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x0b, 0x00, 0x01, 0x00,
0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x75, 0x00, 0x63, 0x00, 0x74, 0x00, 0x56, 0x00, 0x65, 0x00,
0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x31, 0x00, 0x2c, 0x00, 0x20, 0x00,
0x30, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x30, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00,
0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x56, 0x00, 0x61, 0x00, 0x72, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00,
0x65, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x04, 0x00,
0x00, 0x00, 0x54, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x74, 0x00,
0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, 0xb0, 0x04, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
0x10, 0x30, 0x5c, 0x30, 0x82, 0x30, 0x87, 0x30, 0x91, 0x30, 0x9b, 0x30, 0x00, 0x40, 0x00, 0x00, 0x1c, 0x00,
0x00, 0x00, 0x09, 0x30, 0x0f, 0x30, 0x2f, 0x30, 0x38, 0x30, 0x4c, 0x30, 0x5b, 0x30, 0x67, 0x30, 0x6c, 0x30,
0x79, 0x30, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
int cc_x64driver_code_size = 5120;
uint8_t cc_x64driver_code[5120] =
{
0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xb8, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,
0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d,
0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20,
0x44, 0x4f, 0x53, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xb7, 0x04, 0xa8, 0xc2, 0xf3, 0x65, 0xc6, 0x91, 0xf3, 0x65, 0xc6, 0x91, 0xf3, 0x65, 0xc6, 0x91,
0xf3, 0x65, 0xc7, 0x91, 0xf4, 0x65, 0xc6, 0x91, 0x85, 0xf8, 0xbd, 0x91, 0xf0, 0x65, 0xc6, 0x91, 0x85, 0xf8,
0xab, 0x91, 0xf0, 0x65, 0xc6, 0x91, 0x30, 0x6a, 0x98, 0x91, 0xf2, 0x65, 0xc6, 0x91, 0x85, 0xf8, 0xbe, 0x91,
0xf2, 0x65, 0xc6, 0x91, 0x52, 0x69, 0x63, 0x68, 0xf3, 0x65, 0xc6, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x45, 0x00, 0x00, 0x64, 0x86, 0x07, 0x00,
0x41, 0xc8, 0x6d, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x22, 0x00, 0x0b, 0x02,
0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x60, 0x00, 0x00,
0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02,
0x00, 0x00, 0x05, 0x00, 0x02, 0x00, 0x05, 0x00, 0x02, 0x00, 0x05, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x79, 0x44, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x60, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
0x00, 0x70, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00,
0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x2e, 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x26, 0x01, 0x00, 0x00, 0x00, 0x10,
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x68, 0x2e, 0x72, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0xf0, 0x00,
0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x48, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x00,
0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xc8, 0x2e, 0x70,
0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
0x00, 0x48, 0x50, 0x41, 0x47, 0x45, 0x30, 0x44, 0x45, 0x46, 0x4e, 0x01, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00,
0x00, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x20, 0x00, 0x00, 0x60, 0x49, 0x4e, 0x49, 0x54, 0x00, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00,
0x00, 0x60, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xe2, 0x2e, 0x72, 0x73, 0x72, 0x63, 0x00, 0x00, 0x00,
0xc0, 0x03, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x83, 0xec, 0x28,
0x33, 0xc9, 0x48, 0x8b, 0xc2, 0x89, 0x4a, 0x30, 0x48, 0x89, 0x4a, 0x38, 0x33, 0xd2, 0x48, 0x8b, 0xc8, 0xff,
0x15, 0xfd, 0x0f, 0x00, 0x00, 0x33, 0xc0, 0x48, 0x83, 0xc4, 0x28, 0xc3, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x48, 0x83, 0xec, 0x28, 0x48, 0x8b, 0x82, 0xb8, 0x00, 0x00,
0x00, 0x4c, 0x8b, 0xca, 0x81, 0x78, 0x18, 0x0c, 0xe0, 0x22, 0x00, 0x75, 0x43, 0x83, 0x78, 0x08, 0x08, 0x72,
0x3d, 0x83, 0x78, 0x10, 0x04, 0x75, 0x08, 0x48, 0x8b, 0x42, 0x18, 0x8b, 0x08, 0xeb, 0x05, 0xb9, 0x9c, 0x01,
0x00, 0x00, 0x4c, 0x8b, 0x42, 0x18, 0x0f, 0x32, 0x48, 0xc1, 0xe2, 0x20, 0x49, 0x8b, 0xc9, 0x48, 0x0b, 0xc2,
0x33, 0xd2, 0x49, 0x89, 0x00, 0x49, 0xc7, 0x41, 0x38, 0x08, 0x00, 0x00, 0x00, 0xff, 0x15, 0x95, 0x0f, 0x00,
0x00, 0x33, 0xc0, 0x48, 0x83, 0xc4, 0x28, 0xc3, 0xc7, 0x42, 0x30, 0x01, 0x00, 0x00, 0xc0, 0x48, 0xc7, 0x42,
0x38, 0x00, 0x00, 0x00, 0x00, 0x49, 0x8b, 0xc9, 0x33, 0xd2, 0xff, 0x15, 0x74, 0x0f, 0x00, 0x00, 0xb8, 0x01,
0x00, 0x00, 0xc0, 0x48, 0x83, 0xc4, 0x28, 0xc3, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x48, 0x83, 0xec, 0x38, 0x48, 0x8b, 0x49, 0x08, 0xff, 0x15,
0x32, 0x0f, 0x00, 0x00, 0x48, 0x8d, 0x15, 0x1b, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x4c, 0x24, 0x20, 0xff, 0x15,
0x18, 0x0f, 0x00, 0x00, 0x48, 0x8d, 0x4c, 0x24, 0x20, 0xff, 0x15, 0x05, 0x0f, 0x00, 0x00, 0x48, 0x83, 0xc4,
0x38, 0xc3, 0x5c, 0x00, 0x44, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x44, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00,
0x63, 0x00, 0x65, 0x00, 0x73, 0x00, 0x5c, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, 0x64, 0x00,
0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x60, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x16, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x61, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x40, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x41, 0xc8, 0x6d, 0x49, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x49, 0x00, 0x00, 0x00,
0x5c, 0x20, 0x00, 0x00, 0x5c, 0x06, 0x00, 0x00, 0x52, 0x53, 0x44, 0x53, 0xd9, 0x5e, 0xab, 0x47, 0xc4, 0xf2,
0x4f, 0x40, 0xaa, 0xe9, 0x90, 0x47, 0x67, 0x30, 0xa5, 0xfa, 0x03, 0x00, 0x00, 0x00, 0x44, 0x3a, 0x5c, 0x74,
0x6d, 0x70, 0x5c, 0x4b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x5c, 0x6f, 0x62, 0x6a, 0x66, 0x72, 0x65, 0x5f, 0x77,
0x6e, 0x65, 0x74, 0x5f, 0x41, 0x4d, 0x44, 0x36, 0x34, 0x5c, 0x61, 0x6d, 0x64, 0x36, 0x34, 0x5c, 0x54, 0x6d,
0x70, 0x52, 0x64, 0x72, 0x2e, 0x70, 0x64, 0x62, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x04, 0x42,
0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x04, 0x42, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x04, 0x62, 0x00, 0x00,
0x21, 0x00, 0x00, 0x00, 0x10, 0x50, 0x00, 0x00, 0x74, 0x50, 0x00, 0x00, 0xe4, 0x20, 0x00, 0x00, 0x21, 0x08,
0x02, 0x00, 0x08, 0x74, 0x13, 0x00, 0x10, 0x50, 0x00, 0x00, 0x74, 0x50, 0x00, 0x00, 0xe4, 0x20, 0x00, 0x00,
0x01, 0x0c, 0x03, 0x00, 0x0c, 0x34, 0x12, 0x00, 0x04, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xcd, 0x5d, 0x20, 0xd2, 0x66, 0xd4, 0xff, 0xff, 0x32, 0xa2, 0xdf, 0x2d, 0x99, 0x2b, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x32, 0x10, 0x00, 0x00, 0xa8, 0x20, 0x00, 0x00, 0x40, 0x10,
0x00, 0x00, 0xbe, 0x10, 0x00, 0x00, 0xb0, 0x20, 0x00, 0x00, 0xd0, 0x10, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00,
0xb8, 0x20, 0x00, 0x00, 0x10, 0x50, 0x00, 0x00, 0x74, 0x50, 0x00, 0x00, 0xe4, 0x20, 0x00, 0x00, 0x74, 0x50,
0x00, 0x00, 0xe8, 0x50, 0x00, 0x00, 0xd0, 0x20, 0x00, 0x00, 0xe8, 0x50, 0x00, 0x00, 0xf5, 0x50, 0x00, 0x00,
0xc0, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x83, 0xec, 0x78, 0x48, 0x89, 0x9c, 0x24,
0x90, 0x00, 0x00, 0x00, 0x48, 0x8b, 0xd9, 0x48, 0x8d, 0x15, 0x0a, 0x01, 0x00, 0x00, 0x48, 0x8d, 0x4c, 0x24,
0x48, 0xff, 0x15, 0xd7, 0xcf, 0xff, 0xff, 0x41, 0xb9, 0x22, 0x00, 0x00, 0x00, 0x4c, 0x8d, 0x5c, 0x24, 0x40,
0x4c, 0x89, 0x5c, 0x24, 0x30, 0x4c, 0x8d, 0x44, 0x24, 0x48, 0x41, 0x8d, 0x51, 0xe6, 0x48, 0x8b, 0xcb, 0xc6,
0x44, 0x24, 0x28, 0x00, 0xc7, 0x44, 0x24, 0x20, 0x00, 0x00, 0x00, 0x00, 0xff, 0x15, 0xc0, 0xcf, 0xff, 0xff,
0x85, 0xc0, 0x0f, 0x85, 0x80, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x15, 0x91, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x4c,
0x24, 0x58, 0x48, 0x89, 0xbc, 0x24, 0x98, 0x00, 0x00, 0x00, 0xff, 0x15, 0x86, 0xcf, 0xff, 0xff, 0x48, 0x8d,
0x54, 0x24, 0x48, 0x48, 0x8d, 0x4c, 0x24, 0x58, 0xff, 0x15, 0x86, 0xcf, 0xff, 0xff, 0x85, 0xc0, 0x8b, 0xf8,
0x74, 0x0f, 0x48, 0x8b, 0x4c, 0x24, 0x40, 0xff, 0x15, 0x6d, 0xcf, 0xff, 0xff, 0x8b, 0xc7, 0xeb, 0x39, 0x48,
0x8b, 0x44, 0x24, 0x40, 0x48, 0x89, 0x05, 0x5d, 0xe0, 0xff, 0xff, 0x48, 0x8d, 0x05, 0x16, 0xc0, 0xff, 0xff,
0x48, 0x89, 0x43, 0x68, 0x48, 0x8d, 0x05, 0x4b, 0xbf, 0xff, 0xff, 0x48, 0x89, 0x43, 0x70, 0x48, 0x89, 0x83,
0x80, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x05, 0x69, 0xbf, 0xff, 0xff, 0x48, 0x89, 0x83, 0xe0, 0x00, 0x00, 0x00,
0x33, 0xc0, 0x48, 0x8b, 0xbc, 0x24, 0x98, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x9c, 0x24, 0x90, 0x00, 0x00, 0x00,
0x48, 0x83, 0xc4, 0x78, 0xc3, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x5c, 0x00,
0x44, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x44, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00,
0x73, 0x00, 0x5c, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, 0x64, 0x00, 0x72, 0x00, 0x00, 0x00,
0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x5c, 0x00, 0x44, 0x00, 0x65, 0x00, 0x76, 0x00,
0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x5c, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, 0x64, 0x00,
0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x48, 0x8b, 0x05, 0xf1, 0xd0, 0xff, 0xff, 0x49, 0xb9, 0x32, 0xa2, 0xdf, 0x2d, 0x99, 0x2b, 0x00, 0x00, 0x48,
0x85, 0xc0, 0x74, 0x05, 0x49, 0x3b, 0xc1, 0x75, 0x2f, 0x4c, 0x8d, 0x05, 0xd6, 0xd0, 0xff, 0xff, 0x48, 0xb8,
0x20, 0x03, 0x00, 0x00, 0x80, 0xf7, 0xff, 0xff, 0x48, 0x8b, 0x00, 0x49, 0x33, 0xc0, 0x49, 0xb8, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x49, 0x23, 0xc0, 0x49, 0x0f, 0x44, 0xc1, 0x48, 0x89, 0x05, 0xae, 0xd0,
0xff, 0xff, 0x48, 0xf7, 0xd0, 0x48, 0x89, 0x05, 0x9c, 0xd0, 0xff, 0xff, 0xe9, 0xa7, 0xef, 0xff, 0xff, 0xcc,
0xcc, 0xcc, 0x98, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x61, 0x00, 0x00,
0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xfe, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x61,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x60, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x01, 0x49, 0x6f, 0x66, 0x43,
0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x00, 0x00, 0x61, 0x01,
0x49, 0x6f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x63, 0x4c, 0x69,
0x6e, 0x6b, 0x00, 0x00, 0x3e, 0x04, 0x52, 0x74, 0x6c, 0x49, 0x6e, 0x69, 0x74, 0x55, 0x6e, 0x69, 0x63, 0x6f,
0x64, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x5f, 0x01, 0x49, 0x6f, 0x44, 0x65, 0x6c, 0x65,
0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x55, 0x01, 0x49, 0x6f, 0x43, 0x72, 0x65, 0x61,
0x74, 0x65, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, 0x63, 0x4c, 0x69, 0x6e, 0x6b, 0x00, 0x00, 0x4c, 0x01,
0x49, 0x6f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x6e, 0x74,
0x6f, 0x73, 0x6b, 0x72, 0x6e, 0x6c, 0x2e, 0x65, 0x78, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
0x30, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x09, 0x04, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x60, 0x70, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x03,
0x34, 0x00, 0x00, 0x00, 0x56, 0x00, 0x53, 0x00, 0x5f, 0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x00, 0x53, 0x00,
0x49, 0x00, 0x4f, 0x00, 0x4e, 0x00, 0x5f, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x46, 0x00, 0x4f, 0x00, 0x00, 0x00,
0x00, 0x00, 0xbd, 0x04, 0xef, 0xfe, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xbe, 0x02, 0x00, 0x00, 0x01, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00,
0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x00, 0x00,
0x9a, 0x02, 0x00, 0x00, 0x01, 0x00, 0x30, 0x00, 0x34, 0x00, 0x30, 0x00, 0x39, 0x00, 0x30, 0x00, 0x34, 0x00,
0x62, 0x00, 0x30, 0x00, 0x00, 0x00, 0x58, 0x00, 0x20, 0x00, 0x01, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x6d, 0x00,
0x6d, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x73, 0x00, 0x00, 0x00, 0x4d, 0x00, 0x53, 0x00, 0x52, 0x00,
0x20, 0x00, 0x72, 0x00, 0x65, 0x00, 0x61, 0x00, 0x64, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x36, 0x00,
0x34, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x69, 0x00, 0x74, 0x00, 0x20, 0x00, 0x6b, 0x00, 0x65, 0x00, 0x72, 0x00,
0x6e, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x64, 0x00, 0x72, 0x00, 0x69, 0x00, 0x76, 0x00, 0x65, 0x00,
0x72, 0x00, 0x00, 0x00, 0x42, 0x00, 0x11, 0x00, 0x01, 0x00, 0x43, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x70, 0x00,
0x61, 0x00, 0x6e, 0x00, 0x79, 0x00, 0x4e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00,
0x49, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x65, 0x00, 0x65, 0x00,
0x64, 0x00, 0x73, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00,
0x60, 0x00, 0x1c, 0x00, 0x01, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x44, 0x00, 0x65, 0x00,
0x73, 0x00, 0x63, 0x00, 0x72, 0x00, 0x69, 0x00, 0x70, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00,
0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, 0x64, 0x00, 0x72, 0x00, 0x20, 0x00,
0x36, 0x00, 0x34, 0x00, 0x2d, 0x00, 0x62, 0x00, 0x69, 0x00, 0x74, 0x00, 0x20, 0x00, 0x4b, 0x00, 0x65, 0x00,
0x72, 0x00, 0x6e, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x4d, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x75, 0x00,
0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x36, 0x00, 0x0b, 0x00, 0x01, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00,
0x65, 0x00, 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x31, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x30, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x30, 0x00, 0x2c, 0x00,
0x20, 0x00, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x07, 0x00, 0x01, 0x00, 0x49, 0x00, 0x6e, 0x00,
0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x4e, 0x00, 0x61, 0x00, 0x6d, 0x00,
0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00, 0x64, 0x00, 0x72, 0x00, 0x00, 0x00,
0x00, 0x00, 0x4a, 0x00, 0x13, 0x00, 0x01, 0x00, 0x4c, 0x00, 0x65, 0x00, 0x67, 0x00, 0x61, 0x00, 0x6c, 0x00,
0x43, 0x00, 0x6f, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x68, 0x00, 0x74, 0x00,
0x00, 0x00, 0x4e, 0x00, 0x69, 0x00, 0x63, 0x00, 0x6b, 0x00, 0x20, 0x00, 0x47, 0x00, 0x61, 0x00, 0x62, 0x00,
0x61, 0x00, 0x72, 0x00, 0x65, 0x00, 0x76, 0x00, 0x20, 0x00, 0x27, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00,
0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x0d, 0x00, 0x01, 0x00, 0x4f, 0x00, 0x72, 0x00, 0x69, 0x00,
0x67, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6c, 0x00, 0x65, 0x00,
0x6e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x54, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x52, 0x00,
0x64, 0x00, 0x72, 0x00, 0x36, 0x00, 0x34, 0x00, 0x2e, 0x00, 0x73, 0x00, 0x79, 0x00, 0x73, 0x00, 0x00, 0x00,
0x00, 0x00, 0x54, 0x00, 0x1a, 0x00, 0x01, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x75, 0x00,
0x63, 0x00, 0x74, 0x00, 0x4e, 0x00, 0x61, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00,
0x6f, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00, 0x32, 0x00, 0x20, 0x00, 0x54, 0x00, 0x65, 0x00, 0x6d, 0x00,
0x70, 0x00, 0x65, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x75, 0x00, 0x72, 0x00, 0x65, 0x00, 0x20, 0x00,
0x52, 0x00, 0x65, 0x00, 0x61, 0x00, 0x64, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x0b, 0x00,
0x01, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x64, 0x00, 0x75, 0x00, 0x63, 0x00, 0x74, 0x00, 0x56, 0x00,
0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x31, 0x00, 0x2c, 0x00,
0x20, 0x00, 0x30, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x30, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x31, 0x00, 0x00, 0x00,
0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x56, 0x00, 0x61, 0x00, 0x72, 0x00, 0x46, 0x00, 0x69, 0x00,
0x6c, 0x00, 0x65, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x66, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00,
0x04, 0x00, 0x00, 0x00, 0x54, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x6c, 0x00, 0x61, 0x00,
0x74, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, 0xb0, 0x04, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
//} end
#endif // _WIN32
int msrdriver_dummy; // a dummy to avoid a linker warning on OS X.

1291
src/3rdparty/libcpuid/rdmsr.c vendored Normal file

File diff suppressed because it is too large Load diff

409
src/3rdparty/libcpuid/rdtsc.c vendored Normal file
View file

@ -0,0 +1,409 @@
/*
* Copyright 2008 Veselin Georgiev,
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include "libcpuid.h"
#include "libcpuid_util.h"
#include "asm-bits.h"
#include "rdtsc.h"
#ifdef _WIN32
#include <windows.h>
void sys_precise_clock(uint64_t* result)
{
double c, f;
LARGE_INTEGER freq, counter;
QueryPerformanceCounter(&counter);
QueryPerformanceFrequency(&freq);
c = (double) counter.QuadPart;
f = (double) freq.QuadPart;
*result = (uint64_t)(c * 1000000.0 / f);
}
#else
/* assuming Linux, Mac OS or other POSIX */
#include <sys/time.h>
void sys_precise_clock(uint64_t* result)
{
struct timeval tv;
gettimeofday(&tv, NULL);
*result = (uint64_t) tv.tv_sec * (uint64_t) 1000000 +
(uint64_t) tv.tv_usec;
}
#endif /* _WIN32 */
/* out = a - b */
static void mark_t_subtract(struct cpu_mark_t* a, struct cpu_mark_t* b, struct cpu_mark_t* out)
{
out->tsc = a->tsc - b->tsc;
out->sys_clock = a->sys_clock - b->sys_clock;
}
void cpu_tsc_mark(struct cpu_mark_t* mark)
{
cpu_rdtsc(&mark->tsc);
sys_precise_clock(&mark->sys_clock);
}
void cpu_tsc_unmark(struct cpu_mark_t* mark)
{
struct cpu_mark_t temp;
cpu_tsc_mark(&temp);
mark_t_subtract(&temp, mark, mark);
}
int cpu_clock_by_mark(struct cpu_mark_t* mark)
{
uint64_t result;
/* Check if some subtraction resulted in a negative number: */
if((mark->tsc >> 63) != 0 || (mark->sys_clock >> 63) != 0)
{
return -1;
}
/* Divide-by-zero check: */
if(mark->sys_clock == 0)
{
return -1;
}
/* Check if the result fits in 32bits */
result = mark->tsc / mark->sys_clock;
if(result > (uint64_t) 0x7fffffff)
{
return -1;
}
return (int) result;
}
#ifdef _WIN32
int cpu_clock_by_os(void)
{
HKEY key;
DWORD result;
DWORD size = 4;
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), 0, KEY_READ,
&key) != ERROR_SUCCESS)
{
return -1;
}
if(RegQueryValueEx(key, TEXT("~MHz"), NULL, NULL, (LPBYTE) &result, (LPDWORD) &size) != ERROR_SUCCESS)
{
RegCloseKey(key);
return -1;
}
RegCloseKey(key);
return (int)result;
}
#else
#ifdef __APPLE__
#include <sys/types.h>
#include <sys/sysctl.h>
/* Assuming Mac OS X with hw.cpufrequency sysctl */
int cpu_clock_by_os(void)
{
long long result = -1;
size_t size = sizeof(result);
if(sysctlbyname("hw.cpufrequency", &result, &size, NULL, 0))
{
return -1;
}
return (int)(result / (long long) 1000000);
}
#else
/* Assuming Linux with /proc/cpuinfo */
int cpu_clock_by_os(void)
{
FILE* f;
char line[1024], *s;
int result;
f = fopen("/proc/cpuinfo", "rt");
if(!f)
{
return -1;
}
while(fgets(line, sizeof(line), f))
{
if(!strncmp(line, "cpu MHz", 7))
{
s = strchr(line, ':');
if(s && 1 == sscanf(s, ":%d.", &result))
{
fclose(f);
return result;
}
}
}
fclose(f);
return -1;
}
#endif /* __APPLE__ */
#endif /* _WIN32 */
/* Emulate doing useful CPU intensive work */
static int busy_loop(int amount)
{
int i, j, k, s = 0;
static volatile int data[42] = {32, 12, -1, 5, 23, 0 };
for(i = 0; i < amount; i++)
for(j = 0; j < 65536; j++)
for(k = 0; k < 42; k++)
{
s += data[k];
}
return s;
}
int busy_loop_delay(int milliseconds)
{
int cycles = 0, r = 0, first = 1;
uint64_t a, b, c;
sys_precise_clock(&a);
while(1)
{
sys_precise_clock(&c);
if((c - a) / 1000 > milliseconds)
{
return r;
}
r += busy_loop(cycles);
if(first)
{
first = 0;
}
else
{
if(c - b < 1000)
{
cycles *= 2;
}
if(c - b > 10000)
{
cycles /= 2;
}
}
b = c;
}
}
int cpu_clock_measure(int millis, int quad_check)
{
struct cpu_mark_t begin[4], end[4], temp, temp2;
int results[4], cycles, n, k, i, j, bi, bj, mdiff, diff, _zero = 0;
uint64_t tl;
if(millis < 1)
{
return -1;
}
tl = millis * (uint64_t) 1000;
if(quad_check)
{
tl /= 4;
}
n = quad_check ? 4 : 1;
cycles = 1;
for(k = 0; k < n; k++)
{
cpu_tsc_mark(&begin[k]);
end[k] = begin[k];
do
{
/* Run busy loop, and fool the compiler that we USE the garbishy
value it calculates */
_zero |= (1 & busy_loop(cycles));
cpu_tsc_mark(&temp);
mark_t_subtract(&temp, &end[k], &temp2);
/* If busy loop is too short, increase it */
if(temp2.sys_clock < tl / 8)
{
cycles *= 2;
}
end[k] = temp;
}
while(end[k].sys_clock - begin[k].sys_clock < tl);
mark_t_subtract(&end[k], &begin[k], &temp);
results[k] = cpu_clock_by_mark(&temp);
}
if(n == 1)
{
return results[0];
}
mdiff = 0x7fffffff;
bi = bj = -1;
for(i = 0; i < 4; i++)
{
for(j = i + 1; j < 4; j++)
{
diff = results[i] - results[j];
if(diff < 0)
{
diff = -diff;
}
if(diff < mdiff)
{
mdiff = diff;
bi = i;
bj = j;
}
}
}
if(results[bi] == -1)
{
return -1;
}
return (results[bi] + results[bj] + _zero) / 2;
}
static void adjust_march_ic_multiplier(const struct cpu_id_t* id, int* numerator, int* denom)
{
/*
* for cpu_clock_by_ic: we need to know how many clocks does a typical ADDPS instruction
* take, when issued in rapid succesion without dependencies. The whole idea of
* cpu_clock_by_ic was that this is easy to determine, at least it was back in 2010. Now
* it's getting progressively more hairy, but here are the current measurements:
*
* 1. For CPUs with 64-bit SSE units, ADDPS issue rate is 0.5 IPC (one insn in 2 clocks)
* 2. For CPUs with 128-bit SSE units, issue rate is exactly 1.0 IPC
* 3. For Bulldozer and later, it is 1.4 IPC (we multiply by 5/7)
* 4. For Skylake and later, it is 1.6 IPC (we multiply by 5/8)
*/
//
if(id->sse_size < 128)
{
debugf(1, "SSE execution path is 64-bit\n");
// on a CPU with half SSE unit length, SSE instructions execute at 0.5 IPC;
// the resulting value must be multiplied by 2:
*numerator = 2;
}
else
{
debugf(1, "SSE execution path is 128-bit\n");
}
//
// Bulldozer or later: assume 1.4 IPC
if(id->vendor == VENDOR_AMD && id->ext_family >= 21)
{
debugf(1, "cpu_clock_by_ic: Bulldozer (or later) detected, dividing result by 1.4\n");
*numerator = 5;
*denom = 7; // multiply by 5/7, to divide by 1.4
}
//
// Skylake or later: assume 1.6 IPC
if(id->vendor == VENDOR_INTEL && id->ext_model >= 94)
{
debugf(1, "cpu_clock_by_ic: Skylake (or later) detected, dividing result by 1.6\n");
*numerator = 5;
*denom = 8; // to divide by 1.6, multiply by 5/8
}
}
int cpu_clock_by_ic(int millis, int runs)
{
int max_value = 0, cur_value, i, ri, cycles_inner, cycles_outer, c;
struct cpu_id_t* id;
uint64_t t0, t1, tl, hz;
int multiplier_numerator = 1, multiplier_denom = 1;
if(millis <= 0 || runs <= 0)
{
return -2;
}
id = get_cached_cpuid();
// if there aren't SSE instructions - we can't run the test at all
if(!id || !id->flags[CPU_FEATURE_SSE])
{
return -1;
}
//
adjust_march_ic_multiplier(id, &multiplier_numerator, &multiplier_denom);
//
tl = millis * 125; // (*1000 / 8)
cycles_inner = 128;
cycles_outer = 1;
do
{
if(cycles_inner < 1000000000)
{
cycles_inner *= 2;
}
else
{
cycles_outer *= 2;
}
sys_precise_clock(&t0);
for(i = 0; i < cycles_outer; i++)
{
busy_sse_loop(cycles_inner);
}
sys_precise_clock(&t1);
}
while(t1 - t0 < tl);
debugf(2, "inner: %d, outer: %d\n", cycles_inner, cycles_outer);
for(ri = 0; ri < runs; ri++)
{
sys_precise_clock(&t0);
c = 0;
do
{
c++;
for(i = 0; i < cycles_outer; i++)
{
busy_sse_loop(cycles_inner);
}
sys_precise_clock(&t1);
}
while(t1 - t0 < tl * (uint64_t) 8);
// cpu_Hz = cycles_inner * cycles_outer * 256 / (t1 - t0) * 1000000
debugf(2, "c = %d, td = %d\n", c, (int)(t1 - t0));
hz = ((uint64_t) cycles_inner * (uint64_t) 256 + 12) *
(uint64_t) cycles_outer * (uint64_t) multiplier_numerator * (uint64_t) c * (uint64_t) 1000000
/ ((t1 - t0) * (uint64_t) multiplier_denom);
cur_value = (int)(hz / 1000000);
if(cur_value > max_value)
{
max_value = cur_value;
}
}
return max_value;
}
int cpu_clock(void)
{
int result;
result = cpu_clock_by_os();
if(result <= 0)
{
result = cpu_clock_measure(200, 1);
}
return result;
}

33
src/3rdparty/libcpuid/rdtsc.h vendored Normal file
View file

@ -0,0 +1,33 @@
/*
* Copyright 2010 Veselin Georgiev,
* anrieffNOSPAM @ mgail_DOT.com (convert to gmail)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __RDTSC_H__
#define __RDTSC_H__
void sys_precise_clock(uint64_t* result);
int busy_loop_delay(int milliseconds);
#endif /* __RDTSC_H__ */

View file

@ -32,35 +32,276 @@
#include "libcpuid_internal.h"
#include "recog_amd.h"
const struct amd_code_str { amd_code_t code; char *str; } amd_code_str[] = {
#define CODE(x) { x, #x }
#define CODE2(x, y) CODE(x)
#include "amd_code_t.h"
#undef CODE
const struct amd_code_str
{
amd_code_t code;
char* str;
} amd_code_str[] =
{
#define CODE(x) { x, #x }
#define CODE2(x, y) CODE(x)
#include "amd_code_t.h"
#undef CODE
};
struct amd_code_and_bits_t {
struct amd_code_and_bits_t
{
int code;
uint64_t bits;
};
enum _amd_model_codes_t {
enum _amd_model_codes_t
{
// Only for Ryzen CPUs:
_1400,
_1500,
_1600,
};
const struct match_entry_t cpudb_amd[] =
{
{ -1, -1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown AMD CPU" },
/* 486 and the likes */
{ 4, -1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown AMD 486" },
{ 4, 3, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "AMD 486DX2" },
{ 4, 7, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "AMD 486DX2WB" },
{ 4, 8, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "AMD 486DX4" },
{ 4, 9, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "AMD 486DX4WB" },
/* Pentia clones */
{ 5, -1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown AMD 586" },
{ 5, 0, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K5" },
{ 5, 1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K5" },
{ 5, 2, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K5" },
{ 5, 3, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K5" },
/* The K6 */
{ 5, 6, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K6" },
{ 5, 7, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K6" },
{ 5, 8, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K6-2" },
{ 5, 9, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K6-III" },
{ 5, 10, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown K6" },
{ 5, 11, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown K6" },
{ 5, 12, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown K6" },
{ 5, 13, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "K6-2+" },
/* Athlon et al. */
{ 6, 1, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Athlon (Slot-A)" },
{ 6, 2, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Athlon (Slot-A)" },
{ 6, 3, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Duron (Spitfire)" },
{ 6, 4, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Athlon (ThunderBird)" },
{ 6, 6, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown Athlon" },
{ 6, 6, -1, -1, -1, 1, -1, -1, NC, ATHLON_ , 0, "Athlon (Palomino)" },
{ 6, 6, -1, -1, -1, 1, -1, -1, NC, ATHLON_ | _MP_ , 0, "Athlon MP (Palomino)" },
{ 6, 6, -1, -1, -1, 1, -1, -1, NC, DURON_ , 0, "Duron (Palomino)" },
{ 6, 6, -1, -1, -1, 1, -1, -1, NC, ATHLON_ | _XP_ , 0, "Athlon XP" },
{ 6, 7, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Unknown Athlon XP" },
{ 6, 7, -1, -1, -1, 1, -1, -1, NC, DURON_ , 0, "Duron (Morgan)" },
{ 6, 8, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Athlon XP" },
{ 6, 8, -1, -1, -1, 1, -1, -1, NC, ATHLON_ , 0, "Athlon XP (Thoroughbred)" },
{ 6, 8, -1, -1, -1, 1, -1, -1, NC, ATHLON_ | _XP_ , 0, "Athlon XP (Thoroughbred)" },
{ 6, 8, -1, -1, -1, 1, -1, -1, NC, DURON_ , 0, "Duron (Applebred)" },
{ 6, 8, -1, -1, -1, 1, -1, -1, NC, SEMPRON_ , 0, "Sempron (Thoroughbred)" },
{ 6, 8, -1, -1, -1, 1, 128, -1, NC, SEMPRON_ , 0, "Sempron (Thoroughbred)" },
{ 6, 8, -1, -1, -1, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron (Thoroughbred)" },
{ 6, 8, -1, -1, -1, 1, -1, -1, NC, ATHLON_ | _MP_ , 0, "Athlon MP (Thoroughbred)" },
{ 6, 8, -1, -1, -1, 1, -1, -1, NC, ATHLON_ | _XP_ | _M_ , 0, "Mobile Athlon (T-Bred)" },
{ 6, 8, -1, -1, -1, 1, -1, -1, NC, ATHLON_ | _XP_ | _M_ | _LV_, 0, "Mobile Athlon (T-Bred)" },
{ 6, 10, -1, -1, -1, 1, -1, -1, NC, 0 , 0, "Athlon XP (Barton)" },
{ 6, 10, -1, -1, -1, 1, 512, -1, NC, ATHLON_ | _XP_ , 0, "Athlon XP (Barton)" },
{ 6, 10, -1, -1, -1, 1, 512, -1, NC, SEMPRON_ , 0, "Sempron (Barton)" },
{ 6, 10, -1, -1, -1, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron (Thorton)" },
{ 6, 10, -1, -1, -1, 1, 256, -1, NC, ATHLON_ | _XP_ , 0, "Athlon XP (Thorton)" },
{ 6, 10, -1, -1, -1, 1, -1, -1, NC, ATHLON_ | _MP_ , 0, "Athlon MP (Barton)" },
{ 6, 10, -1, -1, -1, 1, -1, -1, NC, ATHLON_ | _XP_ | _M_ , 0, "Mobile Athlon (Barton)" },
{ 6, 10, -1, -1, -1, 1, -1, -1, NC, ATHLON_ | _XP_ | _M_ | _LV_, 0, "Mobile Athlon (Barton)" },
/* K8 Architecture */
{ 15, -1, -1, 15, -1, 1, -1, -1, NC, 0 , 0, "Unknown K8" },
{ 15, -1, -1, 16, -1, 1, -1, -1, NC, 0 , 0, "Unknown K9" },
{ 15, -1, -1, 15, -1, 1, -1, -1, NC, 0 , 0, "Unknown A64" },
{ 15, -1, -1, 15, -1, 1, -1, -1, NC, OPTERON_ , 0, "Opteron" },
{ 15, -1, -1, 15, -1, 2, -1, -1, NC, OPTERON_ | _X2 , 0, "Opteron (Dual Core)" },
{ 15, 3, -1, 15, -1, 1, -1, -1, NC, OPTERON_ , 0, "Opteron" },
{ 15, 3, -1, 15, -1, 2, -1, -1, NC, OPTERON_ | _X2 , 0, "Opteron (Dual Core)" },
{ 15, -1, -1, 15, -1, 1, 512, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (512K)" },
{ 15, -1, -1, 15, -1, 1, 1024, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (1024K)" },
{ 15, -1, -1, 15, -1, 1, -1, -1, NC, ATHLON_ | _FX , 0, "Athlon FX" },
{ 15, -1, -1, 15, -1, 1, -1, -1, NC, ATHLON_ | _64_ | _FX , 0, "Athlon 64 FX" },
{ 15, 3, -1, 15, 35, 2, -1, -1, NC, ATHLON_ | _64_ | _FX , 0, "Athlon 64 FX X2 (Toledo)" },
{ 15, -1, -1, 15, -1, 2, 512, -1, NC, ATHLON_ | _64_ | _X2 , 0, "Athlon 64 X2 (512K)" },
{ 15, -1, -1, 15, -1, 2, 1024, -1, NC, ATHLON_ | _64_ | _X2 , 0, "Athlon 64 X2 (1024K)" },
{ 15, -1, -1, 15, -1, 1, 512, -1, NC, TURION_ | _64_ , 0, "Turion 64 (512K)" },
{ 15, -1, -1, 15, -1, 1, 1024, -1, NC, TURION_ | _64_ , 0, "Turion 64 (1024K)" },
{ 15, -1, -1, 15, -1, 2, 512, -1, NC, TURION_ | _X2 , 0, "Turion 64 X2 (512K)" },
{ 15, -1, -1, 15, -1, 2, 1024, -1, NC, TURION_ | _X2 , 0, "Turion 64 X2 (1024K)" },
{ 15, -1, -1, 15, -1, 1, 128, -1, NC, SEMPRON_ , 0, "A64 Sempron (128K)" },
{ 15, -1, -1, 15, -1, 1, 256, -1, NC, SEMPRON_ , 0, "A64 Sempron (256K)" },
{ 15, -1, -1, 15, -1, 1, 512, -1, NC, SEMPRON_ , 0, "A64 Sempron (512K)" },
{ 15, -1, -1, 15, 0x4f, 1, 512, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (Orleans/512K)" },
{ 15, -1, -1, 15, 0x5f, 1, 512, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (Orleans/512K)" },
{ 15, -1, -1, 15, 0x2f, 1, 512, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (Venice/512K)" },
{ 15, -1, -1, 15, 0x2c, 1, 512, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (Venice/512K)" },
{ 15, -1, -1, 15, 0x1f, 1, 512, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (Winchester/512K)" },
{ 15, -1, -1, 15, 0x0c, 1, 512, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (Newcastle/512K)" },
{ 15, -1, -1, 15, 0x27, 1, 512, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (San Diego/512K)" },
{ 15, -1, -1, 15, 0x37, 1, 512, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (San Diego/512K)" },
{ 15, -1, -1, 15, 0x04, 1, 512, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (ClawHammer/512K)" },
{ 15, -1, -1, 15, 0x5f, 1, 1024, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (Orleans/1024K)" },
{ 15, -1, -1, 15, 0x27, 1, 1024, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (San Diego/1024K)" },
{ 15, -1, -1, 15, 0x04, 1, 1024, -1, NC, ATHLON_ | _64_ , 0, "Athlon 64 (ClawHammer/1024K)" },
{ 15, -1, -1, 15, 0x4b, 2, 256, -1, NC, SEMPRON_ , 0, "Athlon 64 X2 (Windsor/256K)" },
{ 15, -1, -1, 15, 0x23, 2, 512, -1, NC, ATHLON_ | _64_ | _X2 , 0, "Athlon 64 X2 (Toledo/512K)" },
{ 15, -1, -1, 15, 0x4b, 2, 512, -1, NC, ATHLON_ | _64_ | _X2 , 0, "Athlon 64 X2 (Windsor/512K)" },
{ 15, -1, -1, 15, 0x43, 2, 512, -1, NC, ATHLON_ | _64_ | _X2 , 0, "Athlon 64 X2 (Windsor/512K)" },
{ 15, -1, -1, 15, 0x6b, 2, 512, -1, NC, ATHLON_ | _64_ | _X2 , 0, "Athlon 64 X2 (Brisbane/512K)" },
{ 15, -1, -1, 15, 0x2b, 2, 512, -1, NC, ATHLON_ | _64_ | _X2 , 0, "Athlon 64 X2 (Manchester/512K)"},
{ 15, -1, -1, 15, 0x23, 2, 1024, -1, NC, ATHLON_ | _64_ | _X2 , 0, "Athlon 64 X2 (Toledo/1024K)" },
{ 15, -1, -1, 15, 0x43, 2, 1024, -1, NC, ATHLON_ | _64_ | _X2 , 0, "Athlon 64 X2 (Windsor/1024K)" },
{ 15, -1, -1, 15, 0x08, 1, 128, -1, NC, MOBILE_ | SEMPRON_ , 0, "Mobile Sempron 64 (Dublin/128K)"},
{ 15, -1, -1, 15, 0x08, 1, 256, -1, NC, MOBILE_ | SEMPRON_ , 0, "Mobile Sempron 64 (Dublin/256K)"},
{ 15, -1, -1, 15, 0x0c, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron 64 (Paris)" },
{ 15, -1, -1, 15, 0x1c, 1, 128, -1, NC, SEMPRON_ , 0, "Sempron 64 (Palermo/128K)" },
{ 15, -1, -1, 15, 0x1c, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron 64 (Palermo/256K)" },
{ 15, -1, -1, 15, 0x1c, 1, 128, -1, NC, MOBILE_ | SEMPRON_ , 0, "Mobile Sempron 64 (Sonora/128K)"},
{ 15, -1, -1, 15, 0x1c, 1, 256, -1, NC, MOBILE_ | SEMPRON_ , 0, "Mobile Sempron 64 (Sonora/256K)"},
{ 15, -1, -1, 15, 0x2c, 1, 128, -1, NC, SEMPRON_ , 0, "Sempron 64 (Palermo/128K)" },
{ 15, -1, -1, 15, 0x2c, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron 64 (Palermo/256K)" },
{ 15, -1, -1, 15, 0x2c, 1, 128, -1, NC, MOBILE_ | SEMPRON_ , 0, "Mobile Sempron 64 (Albany/128K)"},
{ 15, -1, -1, 15, 0x2c, 1, 256, -1, NC, MOBILE_ | SEMPRON_ , 0, "Mobile Sempron 64 (Albany/256K)"},
{ 15, -1, -1, 15, 0x2f, 1, 128, -1, NC, SEMPRON_ , 0, "Sempron 64 (Palermo/128K)" },
{ 15, -1, -1, 15, 0x2f, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron 64 (Palermo/256K)" },
{ 15, -1, -1, 15, 0x4f, 1, 128, -1, NC, SEMPRON_ , 0, "Sempron 64 (Manila/128K)" },
{ 15, -1, -1, 15, 0x4f, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron 64 (Manila/256K)" },
{ 15, -1, -1, 15, 0x5f, 1, 128, -1, NC, SEMPRON_ , 0, "Sempron 64 (Manila/128K)" },
{ 15, -1, -1, 15, 0x5f, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron 64 (Manila/256K)" },
{ 15, -1, -1, 15, 0x6b, 2, 256, -1, NC, SEMPRON_ , 0, "Sempron 64 Dual (Sherman/256K)"},
{ 15, -1, -1, 15, 0x6b, 2, 512, -1, NC, SEMPRON_ , 0, "Sempron 64 Dual (Sherman/512K)"},
{ 15, -1, -1, 15, 0x7f, 1, 256, -1, NC, SEMPRON_ , 0, "Sempron 64 (Sparta/256K)" },
{ 15, -1, -1, 15, 0x7f, 1, 512, -1, NC, SEMPRON_ , 0, "Sempron 64 (Sparta/512K)" },
{ 15, -1, -1, 15, 0x4c, 1, 256, -1, NC, MOBILE_ | SEMPRON_ , 0, "Mobile Sempron 64 (Keene/256K)"},
{ 15, -1, -1, 15, 0x4c, 1, 512, -1, NC, MOBILE_ | SEMPRON_ , 0, "Mobile Sempron 64 (Keene/512K)"},
{ 15, -1, -1, 15, -1, 2, -1, -1, NC, SEMPRON_ , 0, "Sempron Dual Core" },
{ 15, -1, -1, 15, 0x24, 1, 512, -1, NC, TURION_ | _64_ , 0, "Turion 64 (Lancaster/512K)" },
{ 15, -1, -1, 15, 0x24, 1, 1024, -1, NC, TURION_ | _64_ , 0, "Turion 64 (Lancaster/1024K)" },
{ 15, -1, -1, 15, 0x48, 2, 256, -1, NC, TURION_ | _X2 , 0, "Turion X2 (Taylor)" },
{ 15, -1, -1, 15, 0x48, 2, 512, -1, NC, TURION_ | _X2 , 0, "Turion X2 (Trinidad)" },
{ 15, -1, -1, 15, 0x4c, 1, 512, -1, NC, TURION_ | _64_ , 0, "Turion 64 (Richmond)" },
{ 15, -1, -1, 15, 0x68, 2, 256, -1, NC, TURION_ | _X2 , 0, "Turion X2 (Tyler/256K)" },
{ 15, -1, -1, 15, 0x68, 2, 512, -1, NC, TURION_ | _X2 , 0, "Turion X2 (Tyler/512K)" },
{ 15, -1, -1, 17, 3, 2, 512, -1, NC, TURION_ | _X2 , 0, "Turion X2 (Griffin/512K)" },
{ 15, -1, -1, 17, 3, 2, 1024, -1, NC, TURION_ | _X2 , 0, "Turion X2 (Griffin/1024K)" },
/* K10 Architecture (2007) */
{ 15, -1, -1, 16, -1, 1, -1, -1, PHENOM, 0 , 0, "Unknown AMD Phenom" },
{ 15, 2, -1, 16, -1, 1, -1, -1, PHENOM, 0 , 0, "Phenom" },
{ 15, 2, -1, 16, -1, 3, -1, -1, PHENOM, 0 , 0, "Phenom X3 (Toliman)" },
{ 15, 2, -1, 16, -1, 4, -1, -1, PHENOM, 0 , 0, "Phenom X4 (Agena)" },
{ 15, 2, -1, 16, -1, 3, 512, -1, PHENOM, 0 , 0, "Phenom X3 (Toliman/256K)" },
{ 15, 2, -1, 16, -1, 3, 512, -1, PHENOM, 0 , 0, "Phenom X3 (Toliman/512K)" },
{ 15, 2, -1, 16, -1, 4, 128, -1, PHENOM, 0 , 0, "Phenom X4 (Agena/128K)" },
{ 15, 2, -1, 16, -1, 4, 256, -1, PHENOM, 0 , 0, "Phenom X4 (Agena/256K)" },
{ 15, 2, -1, 16, -1, 4, 512, -1, PHENOM, 0 , 0, "Phenom X4 (Agena/512K)" },
{ 15, 2, -1, 16, -1, 2, 512, -1, NC, ATHLON_ | _64_ | _X2 , 0, "Athlon X2 (Kuma)" },
/* Phenom II derivates: */
{ 15, 4, -1, 16, -1, 4, -1, -1, NC, 0 , 0, "Phenom (Deneb-based)" },
{ 15, 4, -1, 16, -1, 1, 1024, -1, NC, SEMPRON_ , 0, "Sempron (Sargas)" },
{ 15, 4, -1, 16, -1, 2, 512, -1, PHENOM2, 0 , 0, "Phenom II X2 (Callisto)" },
{ 15, 4, -1, 16, -1, 3, 512, -1, PHENOM2, 0 , 0, "Phenom II X3 (Heka)" },
{ 15, 4, -1, 16, -1, 4, 512, -1, PHENOM2, 0 , 0, "Phenom II X4" },
{ 15, 4, -1, 16, 4, 4, 512, -1, PHENOM2, 0 , 0, "Phenom II X4 (Deneb)" },
{ 15, 5, -1, 16, 5, 4, 512, -1, PHENOM2, 0 , 0, "Phenom II X4 (Deneb)" },
{ 15, 4, -1, 16, 10, 4, 512, -1, PHENOM2, 0 , 0, "Phenom II X4 (Zosma)" },
{ 15, 4, -1, 16, 10, 6, 512, -1, PHENOM2, 0 , 0, "Phenom II X6 (Thuban)" },
/* Athlon II derivates: */
{ 15, 6, -1, 16, 6, 2, 512, -1, NC, ATHLON_ | _X2 , 0, "Athlon II (Champlain)" },
{ 15, 6, -1, 16, 6, 2, 512, -1, NC, ATHLON_ | _64_ | _X2 , 0, "Athlon II X2 (Regor)" },
{ 15, 6, -1, 16, 6, 2, 1024, -1, NC, ATHLON_ | _64_ | _X2 , 0, "Athlon II X2 (Regor)" },
{ 15, 5, -1, 16, 5, 3, 512, -1, NC, ATHLON_ | _64_ | _X3 , 0, "Athlon II X3 (Rana)" },
{ 15, 5, -1, 16, 5, 4, 512, -1, NC, ATHLON_ | _64_ | _X4 , 0, "Athlon II X4 (Propus)" },
/* Llano APUs (2011): */
{ 15, 1, -1, 18, 1, 2, -1, -1, FUSION_EA, 0 , 0, "Llano X2" },
{ 15, 1, -1, 18, 1, 3, -1, -1, FUSION_EA, 0 , 0, "Llano X3" },
{ 15, 1, -1, 18, 1, 4, -1, -1, FUSION_EA, 0 , 0, "Llano X4" },
/* Family 14h: Bobcat Architecture (2011) */
{ 15, 2, -1, 20, -1, 1, -1, -1, FUSION_C, 0 , 0, "Brazos Ontario" },
{ 15, 2, -1, 20, -1, 2, -1, -1, FUSION_C, 0 , 0, "Brazos Ontario (Dual-core)" },
{ 15, 1, -1, 20, -1, 1, -1, -1, FUSION_E, 0 , 0, "Brazos Zacate" },
{ 15, 1, -1, 20, -1, 2, -1, -1, FUSION_E, 0 , 0, "Brazos Zacate (Dual-core)" },
{ 15, 2, -1, 20, -1, 2, -1, -1, FUSION_Z, 0 , 0, "Brazos Desna (Dual-core)" },
/* Family 15h: Bulldozer Architecture (2011) */
{ 15, -1, -1, 21, 0, 4, -1, -1, NC, 0 , 0, "Bulldozer X2" },
{ 15, -1, -1, 21, 1, 4, -1, -1, NC, 0 , 0, "Bulldozer X2" },
{ 15, -1, -1, 21, 1, 6, -1, -1, NC, 0 , 0, "Bulldozer X3" },
{ 15, -1, -1, 21, 1, 8, -1, -1, NC, 0 , 0, "Bulldozer X4" },
/* 2nd-gen, Piledriver core (2012): */
{ 15, -1, -1, 21, 2, 4, -1, -1, NC, 0 , 0, "Vishera X2" },
{ 15, -1, -1, 21, 2, 6, -1, -1, NC, 0 , 0, "Vishera X3" },
{ 15, -1, -1, 21, 2, 8, -1, -1, NC, 0 , 0, "Vishera X4" },
{ 15, 0, -1, 21, 16, 2, -1, -1, FUSION_A, 0 , 0, "Trinity X2" },
{ 15, 0, -1, 21, 16, 4, -1, -1, FUSION_A, 0 , 0, "Trinity X4" },
{ 15, 3, -1, 21, 19, 2, -1, -1, FUSION_A, 0 , 0, "Richland X2" },
{ 15, 3, -1, 21, 19, 4, -1, -1, FUSION_A, 0 , 0, "Richland X4" },
/* 3rd-gen, Steamroller core (2014): */
{ 15, 0, -1, 21, 48, 2, -1, -1, FUSION_A, 0 , 0, "Kaveri X2" },
{ 15, 0, -1, 21, 48, 4, -1, -1, FUSION_A, 0 , 0, "Kaveri X4" },
{ 15, 8, -1, 21, 56, 4, -1, -1, FUSION_A, 0 , 0, "Godavari X4" },
/* 4th-gen, Excavator core (2015): */
{ 15, 1, -1, 21, 96, 2, -1, -1, FUSION_A, 0 , 0, "Carrizo X2" },
{ 15, 1, -1, 21, 96, 4, -1, -1, FUSION_A, 0 , 0, "Carrizo X4" },
{ 15, 5, -1, 21, 101, 2, -1, -1, FUSION_A, 0 , 0, "Bristol Ridge X2" },
{ 15, 5, -1, 21, 101, 4, -1, -1, FUSION_A, 0 , 0, "Bristol Ridge X4" },
{ 15, 0, -1, 21, 112, 2, -1, -1, FUSION_A, 0 , 0, "Stoney Ridge X2" },
{ 15, 0, -1, 21, 112, 2, -1, -1, FUSION_E, 0 , 0, "Stoney Ridge X2" },
/* Family 16h: Jaguar Architecture (2013) */
{ 15, 0, -1, 22, 0, 2, -1, -1, FUSION_A, 0 , 0, "Kabini X2" },
{ 15, 0, -1, 22, 0, 4, -1, -1, FUSION_A, 0 , 0, "Kabini X4" },
/* 2nd-gen, Puma core (2013): */
{ 15, 0, -1, 22, 48, 2, -1, -1, FUSION_E, 0 , 0, "Mullins X2" },
{ 15, 0, -1, 22, 48, 4, -1, -1, FUSION_A, 0 , 0, "Mullins X4" },
/* Family 17h: Zen Architecture (2017) */
{ 15, -1, -1, 23, 1, 8, -1, -1, NC, 0 , 0, "Ryzen 7" },
{ 15, -1, -1, 23, 1, 6, -1, -1, NC, 0 , _1600, "Ryzen 5" },
{ 15, -1, -1, 23, 1, 4, -1, -1, NC, 0 , _1500, "Ryzen 5" },
{ 15, -1, -1, 23, 1, 4, -1, -1, NC, 0 , _1400, "Ryzen 5" },
{ 15, -1, -1, 23, 1, 4, -1, -1, NC, 0 , 0, "Ryzen 3" },
//{ 15, -1, -1, 23, 1, 4, -1, -1, NC, 0 , 0, "Raven Ridge" }, //TBA
/* Newer Opterons: */
{ 15, 9, -1, 22, 9, 8, -1, -1, NC, OPTERON_ , 0, "Magny-Cours Opteron" },
};
static void load_amd_features(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
{
const struct feature_map_t matchtable_edx81[] = {
const struct feature_map_t matchtable_edx81[] =
{
{ 20, CPU_FEATURE_NX },
{ 22, CPU_FEATURE_MMXEXT },
{ 25, CPU_FEATURE_FXSR_OPT },
{ 30, CPU_FEATURE_3DNOWEXT },
{ 31, CPU_FEATURE_3DNOW },
};
const struct feature_map_t matchtable_ecx81[] = {
const struct feature_map_t matchtable_ecx81[] =
{
{ 1, CPU_FEATURE_CMP_LEGACY },
{ 2, CPU_FEATURE_SVM },
{ 5, CPU_FEATURE_ABM },
@ -75,7 +316,8 @@ static void load_amd_features(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
{ 16, CPU_FEATURE_FMA4 },
{ 21, CPU_FEATURE_TBM },
};
const struct feature_map_t matchtable_edx87[] = {
const struct feature_map_t matchtable_edx87[] =
{
{ 0, CPU_FEATURE_TS },
{ 1, CPU_FEATURE_FID },
{ 2, CPU_FEATURE_VID },
@ -90,13 +332,17 @@ static void load_amd_features(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
{ 11, CPU_FEATURE_PFI },
{ 12, CPU_FEATURE_PA },
};
if (raw->ext_cpuid[0][0] >= 0x80000001) {
if(raw->ext_cpuid[0][0] >= 0x80000001)
{
match_features(matchtable_edx81, COUNT_OF(matchtable_edx81), raw->ext_cpuid[1][3], data);
match_features(matchtable_ecx81, COUNT_OF(matchtable_ecx81), raw->ext_cpuid[1][2], data);
}
if (raw->ext_cpuid[0][0] >= 0x80000007)
if(raw->ext_cpuid[0][0] >= 0x80000007)
{
match_features(matchtable_edx87, COUNT_OF(matchtable_edx87), raw->ext_cpuid[7][3], data);
if (raw->ext_cpuid[0][0] >= 0x8000001a) {
}
if(raw->ext_cpuid[0][0] >= 0x8000001a)
{
/* We have the extended info about SSE unit size */
data->detection_hints[CPU_HINT_SSE_SIZE_AUTH] = 1;
data->sse_size = (raw->ext_cpuid[0x1a][0] & 1) ? 128 : 64;
@ -106,30 +352,36 @@ static void load_amd_features(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
static void decode_amd_cache_info(struct cpu_raw_data_t* raw, struct cpu_id_t* data)
{
int l3_result;
const int assoc_table[16] = {
const int assoc_table[16] =
{
0, 1, 2, 0, 4, 0, 8, 0, 16, 0, 32, 48, 64, 96, 128, 255
};
unsigned n = raw->ext_cpuid[0][0];
if (n >= 0x80000005) {
if(n >= 0x80000005)
{
data->l1_data_cache = (raw->ext_cpuid[5][2] >> 24) & 0xff;
data->l1_assoc = (raw->ext_cpuid[5][2] >> 16) & 0xff;
data->l1_cacheline = (raw->ext_cpuid[5][2]) & 0xff;
data->l1_instruction_cache = (raw->ext_cpuid[5][3] >> 24) & 0xff;
}
if (n >= 0x80000006) {
if(n >= 0x80000006)
{
data->l2_cache = (raw->ext_cpuid[6][2] >> 16) & 0xffff;
data->l2_assoc = assoc_table[(raw->ext_cpuid[6][2] >> 12) & 0xf];
data->l2_cacheline = (raw->ext_cpuid[6][2]) & 0xff;
l3_result = (raw->ext_cpuid[6][3] >> 18);
if (l3_result > 0) {
if(l3_result > 0)
{
l3_result = 512 * l3_result; /* AMD spec says it's a range,
but we take the lower bound */
data->l3_cache = l3_result;
data->l3_assoc = assoc_table[(raw->ext_cpuid[6][3] >> 12) & 0xf];
data->l3_cacheline = (raw->ext_cpuid[6][3]) & 0xff;
} else {
}
else
{
data->l3_cache = 0;
}
}
@ -139,31 +391,248 @@ static void decode_amd_number_of_cores(struct cpu_raw_data_t* raw, struct cpu_id
{
int logical_cpus = -1, num_cores = -1;
if (raw->basic_cpuid[0][0] >= 1) {
if(raw->basic_cpuid[0][0] >= 1)
{
logical_cpus = (raw->basic_cpuid[1][1] >> 16) & 0xff;
if (raw->ext_cpuid[0][0] >= 8) {
if(raw->ext_cpuid[0][0] >= 8)
{
num_cores = 1 + (raw->ext_cpuid[8][2] & 0xff);
}
}
if (data->flags[CPU_FEATURE_HT]) {
if (num_cores > 1) {
if (data->ext_family >= 23)
if(data->flags[CPU_FEATURE_HT])
{
if(num_cores > 1)
{
if(data->ext_family >= 23)
{
num_cores /= 2; // e.g., Ryzen 7 reports 16 "real" cores, but they are really just 8.
}
data->num_cores = num_cores;
data->num_logical_cpus = logical_cpus;
} else {
}
else
{
data->num_cores = 1;
data->num_logical_cpus = (logical_cpus >= 2 ? logical_cpus : 2);
}
} else {
}
else
{
data->num_cores = data->num_logical_cpus = 1;
}
}
static int amd_has_turion_modelname(const char* bs)
{
/* We search for something like TL-60. Ahh, I miss regexes...*/
int i, l, k;
char code[3] = {0};
const char* codes[] = { "ML", "MT", "MK", "TK", "TL", "RM", "ZM", "" };
l = (int) strlen(bs);
for(i = 3; i < l - 2; i++)
{
if(bs[i] == '-' &&
isupper(bs[i - 1]) && isupper(bs[i - 2]) && !isupper(bs[i - 3]) &&
isdigit(bs[i + 1]) && isdigit(bs[i + 2]) && !isdigit(bs[i + 3]))
{
code[0] = bs[i - 2];
code[1] = bs[i - 1];
for(k = 0; codes[k][0]; k++)
if(!strcmp(codes[k], code))
{
return 1;
}
}
}
return 0;
}
static struct amd_code_and_bits_t decode_amd_codename_part1(const char* bs)
{
amd_code_t code = NC;
uint64_t bits = 0;
struct amd_code_and_bits_t result;
if(strstr(bs, "Dual Core") ||
strstr(bs, "Dual-Core") ||
strstr(bs, " X2 "))
{
bits |= _X2;
}
if(strstr(bs, " X4 "))
{
bits |= _X4;
}
if(strstr(bs, " X3 "))
{
bits |= _X3;
}
if(strstr(bs, "Opteron"))
{
bits |= OPTERON_;
}
if(strstr(bs, "Phenom"))
{
code = (strstr(bs, "II")) ? PHENOM2 : PHENOM;
}
if(amd_has_turion_modelname(bs))
{
bits |= TURION_;
}
if(strstr(bs, "Athlon(tm)"))
{
bits |= ATHLON_;
}
if(strstr(bs, "Sempron(tm)"))
{
bits |= SEMPRON_;
}
if(strstr(bs, "Duron"))
{
bits |= DURON_;
}
if(strstr(bs, " 64 "))
{
bits |= _64_;
}
if(strstr(bs, " FX"))
{
bits |= _FX;
}
if(strstr(bs, " MP"))
{
bits |= _MP_;
}
if(strstr(bs, "Athlon(tm) 64") || strstr(bs, "Athlon(tm) II X") || match_pattern(bs, "Athlon(tm) X#"))
{
bits |= ATHLON_ | _64_;
}
if(strstr(bs, "Turion"))
{
bits |= TURION_;
}
if(strstr(bs, "mobile") || strstr(bs, "Mobile"))
{
bits |= MOBILE_;
}
if(strstr(bs, "XP"))
{
bits |= _XP_;
}
if(strstr(bs, "XP-M"))
{
bits |= _M_;
}
if(strstr(bs, "(LV)"))
{
bits |= _LV_;
}
if(strstr(bs, " APU "))
{
bits |= _APU_;
}
if(match_pattern(bs, "C-##"))
{
code = FUSION_C;
}
if(match_pattern(bs, "E-###"))
{
code = FUSION_E;
}
if(match_pattern(bs, "Z-##"))
{
code = FUSION_Z;
}
if(match_pattern(bs, "[EA]#-####"))
{
code = FUSION_EA;
}
result.code = code;
result.bits = bits;
return result;
}
static int decode_amd_ryzen_model_code(const char* bs)
{
const struct
{
int model_code;
const char* match_str;
} patterns[] =
{
{ _1600, "1600" },
{ _1500, "1500" },
{ _1400, "1400" },
};
int i;
for(i = 0; i < COUNT_OF(patterns); i++)
if(strstr(bs, patterns[i].match_str))
{
return patterns[i].model_code;
}
//
return 0;
}
static void decode_amd_codename(struct cpu_raw_data_t* raw, struct cpu_id_t* data,
struct internal_id_info_t* internal)
{
struct amd_code_and_bits_t code_and_bits = decode_amd_codename_part1(data->brand_str);
int i = 0;
char* code_str = NULL;
int model_code;
for(i = 0; i < COUNT_OF(amd_code_str); i++)
{
if(code_and_bits.code == amd_code_str[i].code)
{
code_str = amd_code_str[i].str;
break;
}
}
if(/*code == ATHLON_64_X2*/ match_all(code_and_bits.bits, ATHLON_ | _64_ | _X2) && data->l2_cache < 512)
{
code_and_bits.bits &= ~(ATHLON_ | _64_);
code_and_bits.bits |= SEMPRON_;
}
if(code_str)
{
debugf(2, "Detected AMD brand code: %d (%s)\n", code_and_bits.code, code_str);
}
else
{
debugf(2, "Detected AMD brand code: %d\n", code_and_bits.code);
}
if(code_and_bits.bits)
{
debugf(2, "Detected AMD bits: ");
debug_print_lbits(2, code_and_bits.bits);
}
// is it Ryzen? if so, we need to detect discern between the four-core 1400/1500 (Ryzen 5) and the four-core Ryzen 3:
model_code = (data->ext_family == 23) ? decode_amd_ryzen_model_code(data->brand_str) : 0;
internal->code.amd = code_and_bits.code;
internal->bits = code_and_bits.bits;
internal->score = match_cpu_codename(cpudb_amd, COUNT_OF(cpudb_amd), data, code_and_bits.code,
code_and_bits.bits, model_code);
}
int cpuid_identify_amd(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal)
{
load_amd_features(raw, data);
decode_amd_cache_info(raw, data);
decode_amd_number_of_cores(raw, data);
decode_amd_codename(raw, data, internal);
return 0;
}
void cpuid_get_list_amd(struct cpu_list_t* list)
{
generic_get_cpu_list(cpudb_amd, COUNT_OF(cpudb_amd), list);
}

View file

@ -27,5 +27,6 @@
#define __RECOG_AMD_H__
int cpuid_identify_amd(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal);
void cpuid_get_list_amd(struct cpu_list_t* list);
#endif /* __RECOG_AMD_H__ */

File diff suppressed because it is too large Load diff

View file

@ -26,6 +26,8 @@
#ifndef __RECOG_INTEL_H__
#define __RECOG_INTEL_H__
int cpuid_identify_intel(struct cpu_raw_data_t* raw, struct cpu_id_t* data, struct internal_id_info_t* internal);
int cpuid_identify_intel(struct cpu_raw_data_t* raw, struct cpu_id_t* data,
struct internal_id_info_t* internal);
void cpuid_get_list_intel(struct cpu_list_t* list);
#endif /*__RECOG_INTEL_H__*/

View file

@ -52,6 +52,13 @@ RAPIDJSON_DIAG_OFF(terminate) // ignore throwing RAPIDJSON_ASSERT in RAPIDJSON_N
#include <utility> // std::move
#endif
#ifdef max
#undef max
#endif
#ifdef min
#undef min
#endif
RAPIDJSON_NAMESPACE_BEGIN
// Forward declaration.

View file

@ -54,7 +54,8 @@
// 7.8 Format conversion of integer types
typedef struct {
typedef struct
{
intmax_t quot;
intmax_t rem;
} imaxdiv_t;
@ -194,11 +195,11 @@ typedef struct {
#define SCNiMAX "I64i"
#ifdef _WIN64 // [
# define SCNdPTR "I64d"
# define SCNiPTR "I64i"
#define SCNdPTR "I64d"
#define SCNiPTR "I64i"
#else // _WIN64 ][
# define SCNdPTR "ld"
# define SCNiPTR "li"
#define SCNdPTR "ld"
#define SCNiPTR "li"
#endif // _WIN64 ]
// The fscanf macros for unsigned integers are:
@ -260,15 +261,15 @@ typedef struct {
#define SCNXMAX "I64X"
#ifdef _WIN64 // [
# define SCNoPTR "I64o"
# define SCNuPTR "I64u"
# define SCNxPTR "I64x"
# define SCNXPTR "I64X"
#define SCNoPTR "I64o"
#define SCNuPTR "I64u"
#define SCNxPTR "I64x"
#define SCNXPTR "I64X"
#else // _WIN64 ][
# define SCNoPTR "lo"
# define SCNuPTR "lu"
# define SCNxPTR "lx"
# define SCNXPTR "lX"
#define SCNoPTR "lo"
#define SCNuPTR "lu"
#define SCNxPTR "lx"
#define SCNXPTR "lX"
#endif // _WIN64 ]
#endif // __STDC_FORMAT_MACROS ]
@ -294,7 +295,8 @@ imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
result.quot = numer / denom;
result.rem = numer % denom;
if (numer < 0 && result.rem > 0) {
if(numer < 0 && result.rem > 0)
{
// did division wrong; must fix up
++result.quot;
result.rem -= denom;

View file

@ -1,7 +1,7 @@
// ISO C9x compliant stdint.h for Microsoft Visual Studio
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
//
// Copyright (c) 2006-2013 Alexander Chemeris
// Copyright (c) 2006-2008 Alexander Chemeris
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
@ -13,9 +13,8 @@
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the product nor the names of its contributors may
// be used to endorse or promote products derived from this software
// without specific prior written permission.
// 3. The name of the author may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
@ -30,10 +29,6 @@
//
///////////////////////////////////////////////////////////////////////////////
// The above software in this distribution may have been modified by
// THL A29 Limited ("Tencent Modifications").
// All Tencent Modifications are Copyright (C) 2015 THL A29 Limited.
#ifndef _MSC_VER // [
#error "Use this header only with Microsoft Visual C++ compilers!"
#endif // _MSC_VER ]
@ -45,68 +40,27 @@
#pragma once
#endif
// miloyip: Originally Visual Studio 2010 uses its own stdint.h. However it generates warning with INT64_C(), so change to use this file for vs2010.
#if _MSC_VER >= 1600 // [
#include <stdint.h>
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
#undef INT8_C
#undef INT16_C
#undef INT32_C
#undef INT64_C
#undef UINT8_C
#undef UINT16_C
#undef UINT32_C
#undef UINT64_C
// 7.18.4.1 Macros for minimum-width integer constants
#define INT8_C(val) val##i8
#define INT16_C(val) val##i16
#define INT32_C(val) val##i32
#define INT64_C(val) val##i64
#define UINT8_C(val) val##ui8
#define UINT16_C(val) val##ui16
#define UINT32_C(val) val##ui32
#define UINT64_C(val) val##ui64
// 7.18.4.2 Macros for greatest-width integer constants
// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
// Check out Issue 9 for the details.
#ifndef INTMAX_C // [
# define INTMAX_C INT64_C
#endif // INTMAX_C ]
#ifndef UINTMAX_C // [
# define UINTMAX_C UINT64_C
#endif // UINTMAX_C ]
#endif // __STDC_CONSTANT_MACROS ]
#else // ] _MSC_VER >= 1700 [
#include <limits.h>
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
// compiling for ARM we have to wrap <wchar.h> include with 'extern "C++" {}'
// or compiler would give many errors like this:
// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
// or compiler give many errors like this:
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
#if defined(__cplusplus) && !defined(_M_ARM)
#ifdef __cplusplus
extern "C" {
#endif
# include <wchar.h>
#if defined(__cplusplus) && !defined(_M_ARM)
#include <wchar.h>
#ifdef __cplusplus
}
#endif
// Define _W64 macros to mark types changing their size, like intptr_t.
#ifndef _W64
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
# define _W64 __w64
# else
# define _W64
# endif
#if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
#define _W64 __w64
#else
#define _W64
#endif
#endif
@ -118,19 +72,19 @@ extern "C" {
// realize that, e.g. char has the same size as __int8
// so we give up on __intX for them.
#if (_MSC_VER < 1300)
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
#else
typedef signed __int8 int8_t;
typedef signed __int16 int16_t;
typedef signed __int32 int32_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef signed __int8 int8_t;
typedef signed __int16 int16_t;
typedef signed __int32 int32_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
#endif
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
@ -158,11 +112,11 @@ typedef uint64_t uint_fast64_t;
// 7.18.1.4 Integer types capable of holding object pointers
#ifdef _WIN64 // [
typedef signed __int64 intptr_t;
typedef unsigned __int64 uintptr_t;
typedef signed __int64 intptr_t;
typedef unsigned __int64 uintptr_t;
#else // _WIN64 ][
typedef _W64 signed int intptr_t;
typedef _W64 unsigned int uintptr_t;
typedef _W64 signed int intptr_t;
typedef _W64 unsigned int uintptr_t;
#endif // _WIN64 ]
// 7.18.1.5 Greatest-width integer types
@ -218,13 +172,13 @@ typedef uint64_t uintmax_t;
// 7.18.2.4 Limits of integer types capable of holding object pointers
#ifdef _WIN64 // [
# define INTPTR_MIN INT64_MIN
# define INTPTR_MAX INT64_MAX
# define UINTPTR_MAX UINT64_MAX
#define INTPTR_MIN INT64_MIN
#define INTPTR_MAX INT64_MAX
#define UINTPTR_MAX UINT64_MAX
#else // _WIN64 ][
# define INTPTR_MIN INT32_MIN
# define INTPTR_MAX INT32_MAX
# define UINTPTR_MAX UINT32_MAX
#define INTPTR_MIN INT32_MIN
#define INTPTR_MAX INT32_MAX
#define UINTPTR_MAX UINT32_MAX
#endif // _WIN64 ]
// 7.18.2.5 Limits of greatest-width integer types
@ -235,30 +189,30 @@ typedef uint64_t uintmax_t;
// 7.18.3 Limits of other integer types
#ifdef _WIN64 // [
# define PTRDIFF_MIN _I64_MIN
# define PTRDIFF_MAX _I64_MAX
#define PTRDIFF_MIN _I64_MIN
#define PTRDIFF_MAX _I64_MAX
#else // _WIN64 ][
# define PTRDIFF_MIN _I32_MIN
# define PTRDIFF_MAX _I32_MAX
#define PTRDIFF_MIN _I32_MIN
#define PTRDIFF_MAX _I32_MAX
#endif // _WIN64 ]
#define SIG_ATOMIC_MIN INT_MIN
#define SIG_ATOMIC_MAX INT_MAX
#ifndef SIZE_MAX // [
# ifdef _WIN64 // [
# define SIZE_MAX _UI64_MAX
# else // _WIN64 ][
# define SIZE_MAX _UI32_MAX
# endif // _WIN64 ]
#ifdef _WIN64 // [
#define SIZE_MAX _UI64_MAX
#else // _WIN64 ][
#define SIZE_MAX _UI32_MAX
#endif // _WIN64 ]
#endif // SIZE_MAX ]
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
#ifndef WCHAR_MIN // [
# define WCHAR_MIN 0
#define WCHAR_MIN 0
#endif // WCHAR_MIN ]
#ifndef WCHAR_MAX // [
# define WCHAR_MAX _UI16_MAX
#define WCHAR_MAX _UI16_MAX
#endif // WCHAR_MAX ]
#define WINT_MIN 0
@ -284,17 +238,10 @@ typedef uint64_t uintmax_t;
#define UINT64_C(val) val##ui64
// 7.18.4.2 Macros for greatest-width integer constants
// These #ifndef's are needed to prevent collisions with <boost/cstdint.hpp>.
// Check out Issue 9 for the details.
#ifndef INTMAX_C // [
# define INTMAX_C INT64_C
#endif // INTMAX_C ]
#ifndef UINTMAX_C // [
# define UINTMAX_C UINT64_C
#endif // UINTMAX_C ]
#define INTMAX_C INT64_C
#define UINTMAX_C UINT64_C
#endif // __STDC_CONSTANT_MACROS ]
#endif // _MSC_VER >= 1600 ]
#endif // _MSC_STDINT_H_ ]

View file

@ -52,11 +52,11 @@
#endif
App *App::m_self = nullptr;
App* App::m_self = nullptr;
App::App(int argc, char **argv) :
App::App(int argc, char** argv) :
m_console(nullptr),
m_httpd(nullptr),
m_network(nullptr),
@ -66,23 +66,27 @@ App::App(int argc, char **argv) :
Cpu::init();
m_options = Options::parse(argc, argv);
if (!m_options) {
if(!m_options)
{
return;
}
Log::init();
if (!m_options->background()) {
if(!m_options->background())
{
Log::add(new ConsoleLog(m_options->colors()));
m_console = new Console(this);
}
if (m_options->logFile()) {
if(0 < m_options->logFile().size())
{
Log::add(new FileLog(m_options->logFile()));
}
# ifdef HAVE_SYSLOG_H
if (m_options->syslog()) {
if(m_options->syslog())
{
Log::add(new SysLog());
}
# endif
@ -112,7 +116,8 @@ App::~App()
int App::exec()
{
if (!m_options) {
if(!m_options)
{
return 0;
}
@ -122,8 +127,9 @@ int App::exec()
background();
if (!CryptoNight::init(m_options->algo(), m_options->algoVariant())) {
LOG_ERR("\"%s\" hash self-test failed.", m_options->algoName());
if(!CryptoNight::init(m_options->algo(), m_options->algoVariant()))
{
LOG_ERR("\"" << m_options->algoName() << "\" hash self-test failed.");
return 1;
}
@ -158,7 +164,8 @@ int App::exec()
void App::onConsoleCommand(char command)
{
switch (command) {
switch(command)
{
case 'h':
case 'H':
Workers::printHashrate(true);
@ -166,16 +173,18 @@ void App::onConsoleCommand(char command)
case 'p':
case 'P':
if (Workers::isEnabled()) {
LOG_INFO(m_options->colors() ? "\x1B[01;33mpaused\x1B[0m, press \x1B[01;35mr\x1B[0m to resume" : "paused, press 'r' to resume");
if(Workers::isEnabled())
{
LOG_INFO("paused, press 'r' to resume");
Workers::setEnabled(false);
}
break;
case 'r':
case 'R':
if (!Workers::isEnabled()) {
LOG_INFO(m_options->colors() ? "\x1B[01;32mresumed" : "resumed");
if(!Workers::isEnabled())
{
LOG_INFO("resumed");
Workers::setEnabled(true);
}
break;
@ -200,9 +209,9 @@ void App::close()
}
void App::onSignal(uv_signal_t *handle, int signum)
void App::onSignal(uv_signal_t* handle, int signum)
{
switch (signum)
switch(signum)
{
case SIGHUP:
LOG_WARN("SIGHUP received, exiting");

View file

@ -20,7 +20,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _WIN32
#include <stdlib.h>
#include <signal.h>
@ -36,31 +36,39 @@
void App::background()
{
if (m_options->affinity() != -1L) {
if(m_options->affinity() != -1L)
{
Cpu::setAffinity(-1, m_options->affinity());
}
if (!m_options->background()) {
if(!m_options->background())
{
return;
}
int i = fork();
if (i < 0) {
if(i < 0)
{
exit(1);
}
if (i > 0) {
if(i > 0)
{
exit(0);
}
i = setsid();
if (i < 0) {
LOG_ERR("setsid() failed (errno = %d)", errno);
if(i < 0)
{
LOG_ERR("setsid() failed (errno = " << errno << ")");
}
i = chdir("/");
if (i < 0) {
LOG_ERR("chdir() failed (errno = %d)", errno);
if(i < 0)
{
LOG_ERR("chdir() failed (errno = " << errno << ")");
}
}
#endif

View file

@ -20,7 +20,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _WIN32
#include <string.h>
@ -52,3 +52,5 @@ void Cpu::initCommon()
m_flags |= AES;
# endif
}
#endif

View file

@ -20,7 +20,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _WIN32
#include <pthread.h>
#include <sched.h>
@ -43,3 +43,5 @@ void Cpu::init()
void Cpu::setAffinity(int id, uint64_t mask)
{
}
#endif

View file

@ -20,7 +20,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _WIN32
#ifdef _MSC_VER
# include <intrin.h>
@ -52,11 +52,13 @@
#ifdef _MSC_VER
static inline void cpuid(int level, int output[4]) {
static inline void cpuid(int level, int output[4])
{
__cpuid(output, level);
}
#else
static inline void cpuid(int level, int output[4]) {
static inline void cpuid(int level, int output[4])
{
int a, b, c, d;
__cpuid_count(level, 0, a, b, c, d);
@ -68,12 +70,15 @@ static inline void cpuid(int level, int output[4]) {
#endif
static inline void cpu_brand_string(char* s) {
static inline void cpu_brand_string(char* s)
{
int cpu_info[4] = { 0 };
cpuid(VENDOR_ID, cpu_info);
if (cpu_info[EAX_Reg] >= 4) {
for (int i = 0; i < 4; i++) {
if(cpu_info[EAX_Reg] >= 4)
{
for(int i = 0; i < 4; i++)
{
cpuid(0x80000002 + i, cpu_info);
memcpy(s, cpu_info, sizeof(cpu_info));
s += 16;
@ -91,7 +96,8 @@ static inline bool has_aes_ni()
}
static inline bool has_bmi2() {
static inline bool has_bmi2()
{
int cpu_info[4] = { 0 };
cpuid(EXTENDED_FEATURES, cpu_info);
@ -123,11 +129,15 @@ void Cpu::initCommon()
m_flags |= X86_64;
# endif
if (has_aes_ni()) {
if(has_aes_ni())
{
m_flags |= AES;
}
if (has_bmi2()) {
if(has_bmi2())
{
m_flags |= BMI2;
}
}
#endif

View file

@ -20,7 +20,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _WIN32
#ifdef __FreeBSD__
# include <sys/types.h>
@ -56,6 +56,7 @@ void Cpu::init()
void Cpu::setAffinity(int id, uint64_t mask)
{
/*
cpu_set_t set;
CPU_ZERO(&set);
@ -66,14 +67,16 @@ void Cpu::setAffinity(int id, uint64_t mask)
}
if (id == -1) {
# ifndef __FreeBSD__
# ifndef __FreeBSD__
sched_setaffinity(0, sizeof(&set), &set);
# endif
# endif
} else {
# ifndef __ANDROID__
# ifndef __ANDROID__
pthread_setaffinity_np(pthread_self(), sizeof(&set), &set);
# else
# else
sched_setaffinity(gettid(), sizeof(&set), &set);
# endif
# endif
}
*/
}
#endif

View file

@ -20,7 +20,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _WIN32
#include <stdlib.h>
#include <sys/mman.h>
@ -38,6 +38,12 @@
#include "Mem.h"
#include "Options.h"
#ifndef MAP_HUGETLB
#define MAP_HUGETLB 0x40000 /* create a huge page mapping */
#endif
#ifndef MAP_POPULATE
#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
#endif
bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled)
{
@ -48,7 +54,8 @@ bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled)
const int ratio = (doubleHash && algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1;
const size_t size = MEMORY * (threads * ratio + 1);
if (!enabled) {
if(!enabled)
{
m_memory = static_cast<uint8_t*>(_mm_malloc(size, 16));
return true;
}
@ -56,24 +63,30 @@ bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled)
m_flags |= HugepagesAvailable;
# if defined(__APPLE__)
m_memory = static_cast<uint8_t*>(mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, VM_FLAGS_SUPERPAGE_SIZE_2MB, 0));
m_memory = static_cast<uint8_t*>(mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON,
VM_FLAGS_SUPERPAGE_SIZE_2MB, 0));
# elif defined(__FreeBSD__)
m_memory = static_cast<uint8_t*>(mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_ALIGNED_SUPER | MAP_PREFAULT_READ, -1, 0));
m_memory = static_cast<uint8_t*>(mmap(0, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_ALIGNED_SUPER | MAP_PREFAULT_READ, -1, 0));
# else
m_memory = static_cast<uint8_t*>(mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, 0, 0));
m_memory = static_cast<uint8_t*>(mmap(0, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_POPULATE, 0, 0));
# endif
if (m_memory == MAP_FAILED) {
if(m_memory == MAP_FAILED)
{
m_memory = static_cast<uint8_t*>(_mm_malloc(size, 16));
return true;
}
m_flags |= HugepagesEnabled;
if (madvise(m_memory, size, MADV_RANDOM | MADV_WILLNEED) != 0) {
if(madvise(m_memory, size, MADV_RANDOM | MADV_WILLNEED) != 0)
{
LOG_ERR("madvise failed");
}
if (mlock(m_memory, size) == 0) {
if(mlock(m_memory, size) == 0)
{
m_flags |= Lock;
}
@ -85,14 +98,19 @@ void Mem::release()
{
const int size = MEMORY * (m_threads + 1);
if (m_flags & HugepagesEnabled) {
if (m_flags & Lock) {
if(m_flags & HugepagesEnabled)
{
if(m_flags & Lock)
{
munlock(m_memory, size);
}
munmap(m_memory, size);
}
else {
else
{
_mm_free(m_memory);
}
}
#endif

View file

@ -57,10 +57,12 @@ Return value: TRUE indicates success, FALSE failure.
* AWE Example: https://msdn.microsoft.com/en-us/library/windows/desktop/aa366531(v=vs.85).aspx
* Creating a File Mapping Using Large Pages: https://msdn.microsoft.com/en-us/library/aa366543(VS.85).aspx
*/
static BOOL SetLockPagesPrivilege() {
static BOOL SetLockPagesPrivilege()
{
HANDLE token;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token) != TRUE) {
if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token) != TRUE)
{
return FALSE;
}
@ -68,12 +70,14 @@ static BOOL SetLockPagesPrivilege() {
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid)) != TRUE) {
if(LookupPrivilegeValue(NULL, SE_LOCK_MEMORY_NAME, &(tp.Privileges[0].Luid)) != TRUE)
{
return FALSE;
}
BOOL rc = AdjustTokenPrivileges(token, FALSE, (PTOKEN_PRIVILEGES) &tp, 0, NULL, NULL);
if (rc != TRUE || GetLastError() != ERROR_SUCCESS) {
if(rc != TRUE || GetLastError() != ERROR_SUCCESS)
{
return FALSE;
}
@ -83,10 +87,11 @@ static BOOL SetLockPagesPrivilege() {
}
static LSA_UNICODE_STRING StringToLsaUnicodeString(LPCTSTR string) {
static LSA_UNICODE_STRING StringToLsaUnicodeString(LPCTSTR string)
{
LSA_UNICODE_STRING lsaString;
DWORD dwLen = (DWORD) wcslen(string);
DWORD dwLen = (DWORD) wcslen((WCHAR*)string);
lsaString.Buffer = (LPWSTR) string;
lsaString.Length = (USHORT)((dwLen) * sizeof(WCHAR));
lsaString.MaximumLength = (USHORT)((dwLen + 1) * sizeof(WCHAR));
@ -94,15 +99,18 @@ static LSA_UNICODE_STRING StringToLsaUnicodeString(LPCTSTR string) {
}
static BOOL ObtainLockPagesPrivilege() {
static BOOL ObtainLockPagesPrivilege()
{
HANDLE token;
PTOKEN_USER user = NULL;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) == TRUE) {
if(OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token) == TRUE)
{
DWORD size = 0;
GetTokenInformation(token, TokenUser, NULL, 0, &size);
if (size) {
if(size)
{
user = (PTOKEN_USER) LocalAlloc(LPTR, size);
}
@ -110,7 +118,8 @@ static BOOL ObtainLockPagesPrivilege() {
CloseHandle(token);
}
if (!user) {
if(!user)
{
return FALSE;
}
@ -119,10 +128,12 @@ static BOOL ObtainLockPagesPrivilege() {
ZeroMemory(&attributes, sizeof(attributes));
BOOL result = FALSE;
if (LsaOpenPolicy(NULL, &attributes, POLICY_ALL_ACCESS, &handle) == 0) {
if(LsaOpenPolicy(NULL, &attributes, POLICY_ALL_ACCESS, &handle) == 0)
{
LSA_UNICODE_STRING str = StringToLsaUnicodeString(_T(SE_LOCK_MEMORY_NAME));
if (LsaAddAccountRights(handle, user->User.Sid, &str, 1) == 0) {
if(LsaAddAccountRights(handle, user->User.Sid, &str, 1) == 0)
{
LOG_NOTICE("Huge pages support was successfully enabled, but reboot required to use it");
result = TRUE;
}
@ -135,8 +146,10 @@ static BOOL ObtainLockPagesPrivilege() {
}
static BOOL TrySetLockPagesPrivilege() {
if (SetLockPagesPrivilege()) {
static BOOL TrySetLockPagesPrivilege()
{
if(SetLockPagesPrivilege())
{
return TRUE;
}
@ -153,20 +166,25 @@ bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled)
const int ratio = (doubleHash && algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1;
const size_t size = MEMORY * (threads * ratio + 1);
if (!enabled) {
if(!enabled)
{
m_memory = static_cast<uint8_t*>(_mm_malloc(size, 16));
return true;
}
if (TrySetLockPagesPrivilege()) {
if(TrySetLockPagesPrivilege())
{
m_flags |= HugepagesAvailable;
}
m_memory = static_cast<uint8_t*>(VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES, PAGE_READWRITE));
if (!m_memory) {
m_memory = static_cast<uint8_t*>(VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES,
PAGE_READWRITE));
if(!m_memory)
{
m_memory = static_cast<uint8_t*>(_mm_malloc(size, 16));
}
else {
else
{
m_flags |= HugepagesEnabled;
}
@ -176,10 +194,12 @@ bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled)
void Mem::release()
{
if (m_flags & HugepagesEnabled) {
if(m_flags & HugepagesEnabled)
{
VirtualFree(m_memory, 0, MEM_RELEASE);
}
else {
else
{
_mm_free(m_memory);
}
}

View file

@ -27,14 +27,14 @@
#ifdef _MSC_VER
# include "getopt/getopt.h"
#include "getopt/getopt.h"
#else
# include <getopt.h>
#include <getopt.h>
#endif
#ifndef XMRIG_NO_HTTPD
# include <microhttpd.h>
#include <microhttpd.h>
#endif
@ -54,7 +54,7 @@
#endif
Options *Options::m_self = nullptr;
Options* Options::m_self = nullptr;
static char const usage[] = "\
@ -80,10 +80,10 @@ Options:\n\
-c, --config=FILE load a JSON-format configuration file\n\
-l, --log-file=FILE log all output to a file\n"
# ifdef HAVE_SYSLOG_H
"\
"\
-S, --syslog use system log for output messages\n"
# endif
"\
"\
--max-cpu-usage=N maximum CPU usage for automatic threads mode (default 75)\n\
--safe safe adjust threads and av settings for current CPU\n\
--nicehash enable nicehash/xmrig-proxy support\n\
@ -99,7 +99,8 @@ Options:\n\
static char const short_options[] = "a:c:khBp:Px:r:R:s:t:T:o:u:O:v:Vl:S";
static struct option const options[] = {
static struct option const options[] =
{
{ "algo", 1, nullptr, 'a' },
{ "av", 1, nullptr, 'v' },
{ "background", 0, nullptr, 'B' },
@ -108,7 +109,7 @@ static struct option const options[] = {
{ "cpu-priority", 1, nullptr, 1021 },
{ "donate-level", 1, nullptr, 1003 },
{ "help", 0, nullptr, 'h' },
{ "keepalive", 0, nullptr ,'k' },
{ "keepalive", 0, nullptr , 'k' },
{ "log-file", 1, nullptr, 'l' },
{ "max-cpu-usage", 1, nullptr, 1004 },
{ "nicehash", 0, nullptr, 1006 },
@ -133,7 +134,8 @@ static struct option const options[] = {
};
static struct option const config_options[] = {
static struct option const config_options[] =
{
{ "algo", 1, nullptr, 'a' },
{ "av", 1, nullptr, 'v' },
{ "background", 0, nullptr, 'B' },
@ -155,18 +157,20 @@ static struct option const config_options[] = {
};
static struct option const pool_options[] = {
static struct option const pool_options[] =
{
{ "url", 1, nullptr, 'o' },
{ "pass", 1, nullptr, 'p' },
{ "user", 1, nullptr, 'u' },
{ "userpass", 1, nullptr, 'O' },
{ "keepalive", 0, nullptr ,'k' },
{ "keepalive", 0, nullptr , 'k' },
{ "nicehash", 0, nullptr, 1006 },
{ 0, 0, 0, 0 }
};
static struct option const api_options[] = {
static struct option const api_options[] =
{
{ "port", 1, nullptr, 4000 },
{ "access-token", 1, nullptr, 4001 },
{ "worker-id", 1, nullptr, 4002 },
@ -174,7 +178,8 @@ static struct option const api_options[] = {
};
static const char *algo_names[] = {
static const char* algo_names[] =
{
"cryptonight",
# ifndef XMRIG_NO_AEON
"cryptonight-lite"
@ -182,10 +187,11 @@ static const char *algo_names[] = {
};
Options *Options::parse(int argc, char **argv)
Options* Options::parse(int argc, char** argv)
{
Options *options = new Options(argc, argv);
if (options->isReady()) {
Options* options = new Options(argc, argv);
if(options->isReady())
{
m_self = options;
return m_self;
}
@ -195,13 +201,13 @@ Options *Options::parse(int argc, char **argv)
}
const char *Options::algoName() const
const char* Options::algoName() const
{
return algo_names[m_algo];
}
Options::Options(int argc, char **argv) :
Options::Options(int argc, char** argv) :
m_background(false),
m_colors(true),
m_doubleHash(false),
@ -209,10 +215,10 @@ Options::Options(int argc, char **argv) :
m_ready(false),
m_safe(false),
m_syslog(false),
m_apiToken(nullptr),
m_apiWorkerId(nullptr),
m_logFile(nullptr),
m_userAgent(nullptr),
m_apiToken(""),
m_apiWorkerId(""),
m_logFile(""),
m_userAgent(""),
m_algo(0),
m_algoVariant(0),
m_apiPort(0),
@ -225,52 +231,64 @@ Options::Options(int argc, char **argv) :
m_threads(0),
m_affinity(-1L)
{
m_pools.push_back(new Url());
m_pools.push_back(Url());
int key;
while (1) {
while(1)
{
key = getopt_long(argc, argv, short_options, options, NULL);
if (key < 0) {
if(key < 0)
{
break;
}
if (!parseArg(key, optarg)) {
if(!parseArg(key, optarg))
{
return;
}
}
if (optind < argc) {
if(optind < argc)
{
fprintf(stderr, "%s: unsupported non-option argument '%s'\n", argv[0], argv[optind]);
return;
}
if (!m_pools[0]->isValid()) {
if(!m_pools[0].isValid())
{
parseConfig(Platform::defaultConfigName());
}
if (!m_pools[0]->isValid()) {
if(!m_pools[0].isValid())
{
fprintf(stderr, "No pool URL supplied. Exiting.\n");
return;
}
m_algoVariant = getAlgoVariant();
if (m_algoVariant == AV2_AESNI_DOUBLE || m_algoVariant == AV4_SOFT_AES_DOUBLE) {
if(m_algoVariant == AV2_AESNI_DOUBLE || m_algoVariant == AV4_SOFT_AES_DOUBLE)
{
m_doubleHash = true;
}
if (!m_threads) {
if(!m_threads)
{
m_threads = Cpu::optimalThreadsCount(m_algo, m_doubleHash, m_maxCpuUsage);
}
else if (m_safe) {
else if(m_safe)
{
const int count = Cpu::optimalThreadsCount(m_algo, m_doubleHash, m_maxCpuUsage);
if (m_threads > count) {
if(m_threads > count)
{
m_threads = count;
}
}
for (Url *url : m_pools) {
url->applyExceptions();
for(size_t i = 0; i < m_pools.size(); ++i)
{
Url & url = m_pools[i];
url.applyExceptions();
}
m_ready = true;
@ -279,21 +297,23 @@ Options::Options(int argc, char **argv) :
Options::~Options()
{
m_pools.clear();
}
bool Options::getJSON(const char *fileName, rapidjson::Document &doc)
bool Options::getJSON(const std::string & fileName, rapidjson::Document & doc)
{
uv_fs_t req;
const int fd = uv_fs_open(uv_default_loop(), &req, fileName, O_RDONLY, 0644, nullptr);
if (fd < 0) {
fprintf(stderr, "unable to open %s: %s\n", fileName, uv_strerror(fd));
const int fd = uv_fs_open(uv_default_loop(), &req, fileName.c_str(), O_RDONLY, 0644, nullptr);
if(fd < 0)
{
fprintf(stderr, "unable to open %s: %s\n", fileName.c_str(), uv_strerror(fd));
return false;
}
uv_fs_req_cleanup(&req);
FILE *fp = fdopen(fd, "rb");
FILE* fp = fdopen(fd, "rb");
char buf[8192];
rapidjson::FileReadStream is(fp, buf, sizeof(buf));
@ -302,8 +322,10 @@ bool Options::getJSON(const char *fileName, rapidjson::Document &doc)
uv_fs_close(uv_default_loop(), &req, fd, nullptr);
uv_fs_req_cleanup(&req);
if (doc.HasParseError()) {
printf("%s:%d: %s\n", fileName, (int) doc.GetErrorOffset(), rapidjson::GetParseError_En(doc.GetParseError()));
if(doc.HasParseError())
{
printf("%s:%d: %s\n", fileName.c_str(), (int) doc.GetErrorOffset(),
rapidjson::GetParseError_En(doc.GetParseError()));
return false;
}
@ -311,62 +333,62 @@ bool Options::getJSON(const char *fileName, rapidjson::Document &doc)
}
bool Options::parseArg(int key, const char *arg)
bool Options::parseArg(int key, const std::string & arg)
{
switch (key) {
switch(key)
{
case 'a': /* --algo */
if (!setAlgo(arg)) {
if(!setAlgo(arg))
{
return false;
}
break;
case 'o': /* --url */
if (m_pools.size() > 1 || m_pools[0]->isValid()) {
Url *url = new Url(arg);
if (url->isValid()) {
if(m_pools.size() > 1 || m_pools[0].isValid())
{
Url url(arg);
if(url.isValid())
{
m_pools.push_back(url);
}
else {
delete url;
}
}
else {
m_pools[0]->parse(arg);
else
{
m_pools[0].parse(arg);
}
if (!m_pools.back()->isValid()) {
if(!m_pools.back().isValid())
{
return false;
}
break;
case 'O': /* --userpass */
if (!m_pools.back()->setUserpass(arg)) {
if(!m_pools.back().setUserpass(arg))
{
return false;
}
break;
case 'u': /* --user */
m_pools.back()->setUser(arg);
m_pools.back().setUser(arg);
break;
case 'p': /* --pass */
m_pools.back()->setPassword(arg);
m_pools.back().setPassword(arg);
break;
case 'l': /* --log-file */
free(m_logFile);
m_logFile = strdup(arg);
m_colors = false;
m_logFile = arg;
break;
case 4001: /* --access-token */
free(m_apiToken);
m_apiToken = strdup(arg);
m_apiToken = arg;
break;
case 4002: /* --worker-id */
free(m_apiWorkerId);
m_apiWorkerId = strdup(arg);
m_apiWorkerId = arg;
break;
case 'r': /* --retries */
@ -377,7 +399,7 @@ bool Options::parseArg(int key, const char *arg)
case 1007: /* --print-time */
case 1021: /* --cpu-priority */
case 4000: /* --api-port */
return parseArg(key, strtol(arg, nullptr, 10));
return parseArg(key, strtol(arg.c_str(), nullptr, 10));
case 'B': /* --background */
case 'k': /* --keepalive */
@ -391,12 +413,13 @@ bool Options::parseArg(int key, const char *arg)
return parseBoolean(key, false);
case 't': /* --threads */
if (strncmp(arg, "all", 3) == 0) {
if(arg == "all")
{
m_threads = Cpu::threads();
return true;
}
return parseArg(key, strtol(arg, nullptr, 10));
return parseArg(key, strtol(arg.c_str(), nullptr, 10));
case 'V': /* --version */
showVersion();
@ -410,14 +433,15 @@ bool Options::parseArg(int key, const char *arg)
parseConfig(arg);
break;
case 1020: { /* --cpu-affinity */
const char *p = strstr(arg, "0x");
return parseArg(key, p ? strtoull(p, nullptr, 16) : strtoull(arg, nullptr, 10));
case 1020: /* --cpu-affinity */
{
const size_t p = arg.find("0x");
return parseArg(key, p != std::string::npos ? strtoul(arg.substr(p).c_str(), nullptr, 16) :
strtoul(arg.c_str(), nullptr, 10));
}
case 1008: /* --user-agent */
free(m_userAgent);
m_userAgent = strdup(arg);
m_userAgent = arg;
break;
default:
@ -431,9 +455,11 @@ bool Options::parseArg(int key, const char *arg)
bool Options::parseArg(int key, uint64_t arg)
{
switch (key) {
switch(key)
{
case 'r': /* --retries */
if (arg < 1 || arg > 1000) {
if(arg < 1 || arg > 1000)
{
showUsage(1);
return false;
}
@ -442,7 +468,8 @@ bool Options::parseArg(int key, uint64_t arg)
break;
case 'R': /* --retry-pause */
if (arg < 1 || arg > 3600) {
if(arg < 1 || arg > 3600)
{
showUsage(1);
return false;
}
@ -451,7 +478,8 @@ bool Options::parseArg(int key, uint64_t arg)
break;
case 't': /* --threads */
if (arg < 1 || arg > 1024) {
if(arg < 1 || arg > 1024)
{
showUsage(1);
return false;
}
@ -460,7 +488,8 @@ bool Options::parseArg(int key, uint64_t arg)
break;
case 'v': /* --av */
if (arg > 1000) {
if(arg > 1000)
{
showUsage(1);
return false;
}
@ -469,7 +498,8 @@ bool Options::parseArg(int key, uint64_t arg)
break;
case 1003: /* --donate-level */
if (arg < 1 || arg > 99) {
if(arg < 0 || arg > 99)
{
return true;
}
@ -477,7 +507,8 @@ bool Options::parseArg(int key, uint64_t arg)
break;
case 1004: /* --max-cpu-usage */
if (arg < 1 || arg > 100) {
if(arg < 1 || arg > 100)
{
showUsage(1);
return false;
}
@ -486,7 +517,8 @@ bool Options::parseArg(int key, uint64_t arg)
break;
case 1007: /* --print-time */
if (arg > 1000) {
if(arg > 1000)
{
showUsage(1);
return false;
}
@ -495,19 +527,22 @@ bool Options::parseArg(int key, uint64_t arg)
break;
case 1020: /* --cpu-affinity */
if (arg) {
if(arg)
{
m_affinity = arg;
}
break;
case 1021: /* --cpu-priority */
if (arg <= 5) {
if(arg <= 5)
{
m_priority = (int) arg;
}
break;
case 4000: /* --api-port */
if (arg <= 65536) {
if(arg <= 65536)
{
m_apiPort = (int) arg;
}
break;
@ -522,9 +557,10 @@ bool Options::parseArg(int key, uint64_t arg)
bool Options::parseBoolean(int key, bool enable)
{
switch (key) {
switch(key)
{
case 'k': /* --keepalive */
m_pools.back()->setKeepAlive(enable);
m_pools.back().setKeepAlive(enable);
break;
case 'B': /* --background */
@ -546,7 +582,7 @@ bool Options::parseBoolean(int key, bool enable)
break;
case 1006: /* --nicehash */
m_pools.back()->setNicehash(enable);
m_pools.back().setNicehash(enable);
break;
case 1009: /* --no-huge-pages */
@ -565,66 +601,73 @@ bool Options::parseBoolean(int key, bool enable)
}
Url *Options::parseUrl(const char *arg) const
Url Options::parseUrl(const std::string & arg) const
{
auto url = new Url(arg);
if (!url->isValid()) {
delete url;
return nullptr;
}
return url;
return Url(arg);
}
void Options::parseConfig(const char *fileName)
void Options::parseConfig(const std::string & fileName)
{
rapidjson::Document doc;
if (!getJSON(fileName, doc)) {
if(!getJSON(fileName, doc))
{
return;
}
for (size_t i = 0; i < ARRAY_SIZE(config_options); i++) {
for(size_t i = 0; i < ARRAY_SIZE(config_options); i++)
{
parseJSON(&config_options[i], doc);
}
const rapidjson::Value &pools = doc["pools"];
if (pools.IsArray()) {
for (const rapidjson::Value &value : pools.GetArray()) {
if (!value.IsObject()) {
const rapidjson::Value & pools = doc["pools"];
if(pools.IsArray())
{
for(size_t i = 0; i < pools.GetArray().Size(); ++i)
{
const rapidjson::Value & value = pools.GetArray()[i];
if(!value.IsObject())
{
continue;
}
for (size_t i = 0; i < ARRAY_SIZE(pool_options); i++) {
for(size_t i = 0; i < ARRAY_SIZE(pool_options); i++)
{
parseJSON(&pool_options[i], value);
}
}
}
const rapidjson::Value &api = doc["api"];
if (api.IsObject()) {
for (size_t i = 0; i < ARRAY_SIZE(api_options); i++) {
const rapidjson::Value & api = doc["api"];
if(api.IsObject())
{
for(size_t i = 0; i < ARRAY_SIZE(api_options); i++)
{
parseJSON(&api_options[i], api);
}
}
}
void Options::parseJSON(const struct option *option, const rapidjson::Value &object)
void Options::parseJSON(const struct option* option, const rapidjson::Value & object)
{
if (!option->name || !object.HasMember(option->name)) {
if(!option->name || !object.HasMember(option->name))
{
return;
}
const rapidjson::Value &value = object[option->name];
const rapidjson::Value & value = object[option->name];
if (option->has_arg && value.IsString()) {
if(option->has_arg && value.IsString())
{
parseArg(option->val, value.GetString());
}
else if (option->has_arg && value.IsUint64()) {
else if(option->has_arg && value.IsUint64())
{
parseArg(option->val, value.GetUint64());
}
else if (!option->has_arg && value.IsBool()) {
else if(!option->has_arg && value.IsBool())
{
parseBoolean(option->val, value.IsTrue());
}
}
@ -632,10 +675,12 @@ void Options::parseJSON(const struct option *option, const rapidjson::Value &obj
void Options::showUsage(int status) const
{
if (status) {
if(status)
{
fprintf(stderr, "Try \"" APP_ID "\" --help' for more information.\n");
}
else {
else
{
printf(usage);
}
}
@ -677,22 +722,26 @@ void Options::showVersion()
}
bool Options::setAlgo(const char *algo)
bool Options::setAlgo(const std::string & algo)
{
for (size_t i = 0; i < ARRAY_SIZE(algo_names); i++) {
if (algo_names[i] && !strcmp(algo, algo_names[i])) {
for(size_t i = 0; i < ARRAY_SIZE(algo_names); i++)
{
if(algo_names[i] && algo == algo_names[i])
{
m_algo = (int) i;
break;
}
# ifndef XMRIG_NO_AEON
if (i == ARRAY_SIZE(algo_names) - 1 && !strcmp(algo, "cryptonight-light")) {
if(i == ARRAY_SIZE(algo_names) - 1 && algo == "cryptonight-light")
{
m_algo = ALGO_CRYPTONIGHT_LITE;
break;
}
# endif
if (i == ARRAY_SIZE(algo_names) - 1) {
if(i == ARRAY_SIZE(algo_names) - 1)
{
showUsage(1);
return false;
}
@ -705,16 +754,19 @@ bool Options::setAlgo(const char *algo)
int Options::getAlgoVariant() const
{
# ifndef XMRIG_NO_AEON
if (m_algo == ALGO_CRYPTONIGHT_LITE) {
if(m_algo == ALGO_CRYPTONIGHT_LITE)
{
return getAlgoVariantLite();
}
# endif
if (m_algoVariant <= AV0_AUTO || m_algoVariant >= AV_MAX) {
if(m_algoVariant <= AV0_AUTO || m_algoVariant >= AV_MAX)
{
return Cpu::hasAES() ? AV1_AESNI : AV3_SOFT_AES;
}
if (m_safe && !Cpu::hasAES() && m_algoVariant <= AV2_AESNI_DOUBLE) {
if(m_safe && !Cpu::hasAES() && m_algoVariant <= AV2_AESNI_DOUBLE)
{
return m_algoVariant + 2;
}
@ -725,11 +777,13 @@ int Options::getAlgoVariant() const
#ifndef XMRIG_NO_AEON
int Options::getAlgoVariantLite() const
{
if (m_algoVariant <= AV0_AUTO || m_algoVariant >= AV_MAX) {
if(m_algoVariant <= AV0_AUTO || m_algoVariant >= AV_MAX)
{
return Cpu::hasAES() ? AV2_AESNI_DOUBLE : AV4_SOFT_AES_DOUBLE;
}
if (m_safe && !Cpu::hasAES() && m_algoVariant <= AV2_AESNI_DOUBLE) {
if(m_safe && !Cpu::hasAES() && m_algoVariant <= AV2_AESNI_DOUBLE)
{
return m_algoVariant + 2;
}

View file

@ -27,7 +27,7 @@
#include <stdint.h>
#include <vector>
#include <string>
#include "rapidjson/fwd.h"
@ -39,12 +39,14 @@ struct option;
class Options
{
public:
enum Algo {
enum Algo
{
ALGO_CRYPTONIGHT, /* CryptoNight (Monero) */
ALGO_CRYPTONIGHT_LITE, /* CryptoNight-Lite (AEON) */
};
enum AlgoVariant {
enum AlgoVariant
{
AV0_AUTO,
AV1_AESNI,
AV2_AESNI_DOUBLE,
@ -53,54 +55,126 @@ public:
AV_MAX
};
static inline Options* i() { return m_self; }
static Options *parse(int argc, char **argv);
static inline Options* i()
{
return m_self;
}
static Options* parse(int argc, char** argv);
inline bool background() const { return m_background; }
inline bool colors() const { return m_colors; }
inline bool doubleHash() const { return m_doubleHash; }
inline bool hugePages() const { return m_hugePages; }
inline bool syslog() const { return m_syslog; }
inline const char *apiToken() const { return m_apiToken; }
inline const char *apiWorkerId() const { return m_apiWorkerId; }
inline const char *logFile() const { return m_logFile; }
inline const char *userAgent() const { return m_userAgent; }
inline const std::vector<Url*> &pools() const { return m_pools; }
inline int algo() const { return m_algo; }
inline int algoVariant() const { return m_algoVariant; }
inline int apiPort() const { return m_apiPort; }
inline int donateLevel() const { return m_donateLevel; }
inline int printTime() const { return m_printTime; }
inline int priority() const { return m_priority; }
inline int retries() const { return m_retries; }
inline int retryPause() const { return m_retryPause; }
inline int threads() const { return m_threads; }
inline int64_t affinity() const { return m_affinity; }
inline void setColors(bool colors) { m_colors = colors; }
inline bool background() const
{
return m_background;
}
inline bool colors() const
{
return m_colors;
}
inline bool doubleHash() const
{
return m_doubleHash;
}
inline bool hugePages() const
{
return m_hugePages;
}
inline bool syslog() const
{
return m_syslog;
}
inline const std::string apiToken() const
{
return m_apiToken;
}
inline const std::string & apiWorkerId() const
{
return m_apiWorkerId;
}
inline const std::string & logFile() const
{
return m_logFile;
}
inline const std::string & userAgent() const
{
return m_userAgent;
}
inline const std::vector<Url> & pools() const
{
return m_pools;
}
inline int algo() const
{
return m_algo;
}
inline int algoVariant() const
{
return m_algoVariant;
}
inline int apiPort() const
{
return m_apiPort;
}
inline int donateLevel() const
{
return m_donateLevel;
}
inline int printTime() const
{
return m_printTime;
}
inline int priority() const
{
return m_priority;
}
inline int retries() const
{
return m_retries;
}
inline int retryPause() const
{
return m_retryPause;
}
inline int threads() const
{
return m_threads;
}
inline int64_t affinity() const
{
return m_affinity;
}
inline void setColors(bool colors)
{
m_colors = colors;
}
inline static void release() { delete m_self; }
inline static void release()
{
delete m_self;
}
const char *algoName() const;
const char* algoName() const;
private:
Options(int argc, char **argv);
Options(int argc, char** argv);
~Options();
inline bool isReady() const { return m_ready; }
inline bool isReady() const
{
return m_ready;
}
static Options *m_self;
static Options* m_self;
bool getJSON(const char *fileName, rapidjson::Document &doc);
bool parseArg(int key, const char *arg);
bool getJSON(const std::string & fileName, rapidjson::Document & doc);
bool parseArg(int key, const std::string & arg);
bool parseArg(int key, uint64_t arg);
bool parseBoolean(int key, bool enable);
Url *parseUrl(const char *arg) const;
void parseConfig(const char *fileName);
void parseJSON(const struct option *option, const rapidjson::Value &object);
Url parseUrl(const std::string & arg) const;
void parseConfig(const std::string & fileName);
void parseJSON(const struct option* option, const rapidjson::Value & object);
void showUsage(int status) const;
void showVersion(void);
bool setAlgo(const char *algo);
bool setAlgo(const std::string & algo);
int getAlgoVariant() const;
# ifndef XMRIG_NO_AEON
@ -114,10 +188,10 @@ private:
bool m_ready;
bool m_safe;
bool m_syslog;
char *m_apiToken;
char *m_apiWorkerId;
char *m_logFile;
char *m_userAgent;
std::string m_apiToken;
std::string m_apiWorkerId;
std::string m_logFile;
std::string m_userAgent;
int m_algo;
int m_algoVariant;
int m_apiPort;
@ -129,7 +203,7 @@ private:
int m_retryPause;
int m_threads;
int64_t m_affinity;
std::vector<Url*> m_pools;
std::vector<Url> m_pools;
};
#endif /* __OPTIONS_H__ */

View file

@ -29,34 +29,40 @@
#include "Platform.h"
char *Platform::m_defaultConfigName = nullptr;
char *Platform::m_userAgent = nullptr;
std::string Platform::m_defaultConfigName = "";
std::string Platform::m_userAgent = "";
const char *Platform::defaultConfigName()
const std::string & Platform::defaultConfigName()
{
size_t size = 520;
enum
{
C_SIZE = 520,
};
if (m_defaultConfigName == nullptr) {
m_defaultConfigName = new char[size];
}
if (uv_exepath(m_defaultConfigName, &size) < 0) {
return nullptr;
}
if (size < 500) {
# ifdef WIN32
char *p = strrchr(m_defaultConfigName, '\\');
# else
char *p = strrchr(m_defaultConfigName, '/');
# endif
if (p) {
strcpy(p + 1, "config.json");
size_t size = C_SIZE ;
char defaultConfigName[C_SIZE];
if(uv_exepath(defaultConfigName, &size) < 0)
{
return m_defaultConfigName;
}
m_defaultConfigName = defaultConfigName;
if(size < 500)
{
#ifdef WIN32
size_t p = m_defaultConfigName.find_last_of('\\');
#else
size_t p = m_defaultConfigName.find_last_of('/');
#endif
if(p != std::string::npos)
{
m_defaultConfigName.resize(p + 1);
m_defaultConfigName.append("config.json");
}
}
return nullptr;
return m_defaultConfigName;
}

View file

@ -24,21 +24,25 @@
#ifndef __PLATFORM_H__
#define __PLATFORM_H__
#include <string>
class Platform
{
public:
static const char *defaultConfigName();
static void init(const char *userAgent);
static const std::string & defaultConfigName();
static void init(const std::string & userAgent);
static void release();
static void setProcessPriority(int priority);
static void setThreadPriority(int priority);
static inline const char *userAgent() { return m_userAgent; }
static inline const std::string & userAgent()
{
return m_userAgent;
}
private:
static char *m_defaultConfigName;
static char *m_userAgent;
static std::string m_defaultConfigName;
static std::string m_userAgent;
};

View file

@ -20,7 +20,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _WIN32
#include <stdio.h>
#include <stdlib.h>
@ -36,26 +36,29 @@
#endif
static inline char *createUserAgent()
static inline char* createUserAgent()
{
const size_t max = 160;
char *buf = new char[max];
char* buf = new char[max];
# ifdef XMRIG_NVIDIA_PROJECT
const int cudaVersion = cuda_get_runtime_version();
snprintf(buf, max, "%s/%s (Macintosh; Intel Mac OS X) libuv/%s CUDA/%d.%d clang/%d.%d.%d", APP_NAME, APP_VERSION, uv_version_string(), cudaVersion / 1000, cudaVersion % 100, __clang_major__, __clang_minor__, __clang_patchlevel__);
snprintf(buf, max, "%s/%s (Macintosh; Intel Mac OS X) libuv/%s CUDA/%d.%d clang/%d.%d.%d", APP_NAME,
APP_VERSION, uv_version_string(), cudaVersion / 1000, cudaVersion % 100, __clang_major__, __clang_minor__,
__clang_patchlevel__);
# else
snprintf(buf, max, "%s/%s (Macintosh; Intel Mac OS X) libuv/%s clang/%d.%d.%d", APP_NAME, APP_VERSION, uv_version_string(), __clang_major__, __clang_minor__, __clang_patchlevel__);
snprintf(buf, max, "%s/%s (Macintosh; Intel Mac OS X) libuv/%s clang/%d.%d.%d", APP_NAME, APP_VERSION,
uv_version_string(), __clang_major__, __clang_minor__, __clang_patchlevel__);
# endif
return buf;
}
void Platform::init(const char *userAgent)
void Platform::init(const std::string & userAgent)
{
m_userAgent = userAgent ? strdup(userAgent) : createUserAgent();
m_userAgent = (userAgent.size() != "") ? userAgent : createUserAgent();
}
@ -73,12 +76,13 @@ void Platform::setProcessPriority(int priority)
void Platform::setThreadPriority(int priority)
{
if (priority == -1) {
if(priority == -1)
{
return;
}
int prio = 19;
switch (priority)
switch(priority)
{
case 1:
prio = 5;
@ -107,3 +111,4 @@ void Platform::setThreadPriority(int priority)
setpriority(PRIO_PROCESS, 0, prio);
}
#endif

View file

@ -20,6 +20,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _WIN32
#include <sched.h>
#include <stdio.h>
@ -37,11 +38,11 @@
#endif
static inline char *createUserAgent()
static inline std::string createUserAgent()
{
const size_t max = 160;
char *buf = new char[max];
char* buf = new char[max];
int length = snprintf(buf, max, "%s/%s (Linux ", APP_NAME, APP_VERSION);
# if defined(__x86_64__)
@ -63,15 +64,15 @@ static inline char *createUserAgent()
}
void Platform::init(const char *userAgent)
void Platform::init(const std::string & userAgent)
{
m_userAgent = userAgent ? strdup(userAgent) : createUserAgent();
m_userAgent = (0 < userAgent.size()) ? userAgent : createUserAgent();
}
void Platform::release()
{
delete [] m_userAgent;
m_userAgent.clear();
}
@ -83,12 +84,13 @@ void Platform::setProcessPriority(int priority)
void Platform::setThreadPriority(int priority)
{
if (priority == -1) {
if(priority == -1)
{
return;
}
int prio = 19;
switch (priority)
switch(priority)
{
case 1:
prio = 5;
@ -117,13 +119,17 @@ void Platform::setThreadPriority(int priority)
setpriority(PRIO_PROCESS, 0, prio);
# ifdef SCHED_IDLE
if (priority == 0) {
if(priority == 0)
{
sched_param param;
param.sched_priority = 0;
if (sched_setscheduler(0, SCHED_IDLE, &param) != 0) {
if(sched_setscheduler(0, SCHED_IDLE, &param) != 0)
{
sched_setscheduler(0, SCHED_BATCH, &param);
}
}
# endif
}
#endif

View file

@ -26,25 +26,29 @@
#include <windows.h>
#include <uv.h>
#include "log/Log.h"
#include "Platform.h"
#include "version.h"
#ifdef XMRIG_NVIDIA_PROJECT
# include "nvidia/cryptonight.h"
#include "nvidia/cryptonight.h"
#endif
static inline OSVERSIONINFOEX winOsVersion()
{
typedef NTSTATUS (NTAPI *RtlGetVersionFunction)(LPOSVERSIONINFO);
typedef NTSTATUS(NTAPI * RtlGetVersionFunction)(LPOSVERSIONINFO);
OSVERSIONINFOEX result = { sizeof(OSVERSIONINFOEX), 0, 0, 0, 0, {'\0'}, 0, 0, 0, 0, 0};
HMODULE ntdll = GetModuleHandleW(L"ntdll.dll");
if (ntdll ) {
RtlGetVersionFunction pRtlGetVersion = reinterpret_cast<RtlGetVersionFunction>(GetProcAddress(ntdll, "RtlGetVersion"));
if(ntdll)
{
RtlGetVersionFunction pRtlGetVersion = reinterpret_cast<RtlGetVersionFunction>(GetProcAddress(ntdll,
"RtlGetVersion"));
if (pRtlGetVersion) {
if(pRtlGetVersion)
{
pRtlGetVersion((LPOSVERSIONINFO) &result);
}
}
@ -53,56 +57,57 @@ static inline OSVERSIONINFOEX winOsVersion()
}
static inline char *createUserAgent()
static inline std::string createUserAgent()
{
const auto osver = winOsVersion();
const size_t max = 160;
char *buf = new char[max];
int length = snprintf(buf, max, "%s/%s (Windows NT %lu.%lu", APP_NAME, APP_VERSION, osver.dwMajorVersion, osver.dwMinorVersion);
char buf[max];
int length = snprintf(buf, max, "%s/%s (Windows NT %lu.%lu", APP_NAME, APP_VERSION, osver.dwMajorVersion,
osver.dwMinorVersion);
# if defined(__x86_64__) || defined(_M_AMD64)
#if defined(__x86_64__) || defined(_M_AMD64)
length += snprintf(buf + length, max - length, "; Win64; x64) libuv/%s", uv_version_string());
# else
#else
length += snprintf(buf + length, max - length, ") libuv/%s", uv_version_string());
# endif
#endif
# ifdef XMRIG_NVIDIA_PROJECT
#ifdef XMRIG_NVIDIA_PROJECT
const int cudaVersion = cuda_get_runtime_version();
length += snprintf(buf + length, max - length, " CUDA/%d.%d", cudaVersion / 1000, cudaVersion % 100);
# endif
#endif
# ifdef __GNUC__
#ifdef __GNUC__
length += snprintf(buf + length, max - length, " gcc/%d.%d.%d", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
# elif _MSC_VER
#elif _MSC_VER
length += snprintf(buf + length, max - length, " msvc/%d", MSVC_VERSION);
# endif
#endif
return buf;
}
void Platform::init(const char *userAgent)
void Platform::init(const std::string & userAgent)
{
m_userAgent = userAgent ? strdup(userAgent) : createUserAgent();
m_userAgent = (0 < userAgent.size()) ? userAgent : createUserAgent();
}
void Platform::release()
{
delete [] m_defaultConfigName;
delete [] m_userAgent;
m_userAgent.clear();
}
void Platform::setProcessPriority(int priority)
{
if (priority == -1) {
if(priority == -1)
{
return;
}
DWORD prio = IDLE_PRIORITY_CLASS;
switch (priority)
switch(priority)
{
case 1:
prio = BELOW_NORMAL_PRIORITY_CLASS;
@ -134,12 +139,13 @@ void Platform::setProcessPriority(int priority)
void Platform::setThreadPriority(int priority)
{
if (priority == -1) {
if(priority == -1)
{
return;
}
int prio = THREAD_PRIORITY_IDLE;
switch (priority)
switch(priority)
{
case 1:
prio = THREAD_PRIORITY_BELOW_NORMAL;

View file

@ -51,39 +51,50 @@ static void print_versions()
# endif
Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mVERSIONS: \x1B[01;36mXMRig/%s\x1B[01;37m libuv/%s%s" : " * VERSIONS: XMRig/%s libuv/%s%s",
APP_VERSION, uv_version_string(), buf);
PRINT_MSG(" * VERSIONS: XMRig/" << APP_VERSION << " libuv/" << uv_version_string() << buf);
}
static void print_memory() {
if (Options::i()->colors()) {
static void print_memory()
{
if(Options::i()->colors())
{
/*
Log::i()->text("\x1B[01;32m * \x1B[01;37mHUGE PAGES: %s, %s",
Mem::isHugepagesAvailable() ? "\x1B[01;32mavailable" : "\x1B[01;31munavailable",
Mem::isHugepagesEnabled() ? "\x1B[01;32menabled" : "\x1B[01;31mdisabled");
*/
}
else {
Log::i()->text(" * HUGE PAGES: %s, %s", Mem::isHugepagesAvailable() ? "available" : "unavailable", Mem::isHugepagesEnabled() ? "enabled" : "disabled");
else
{
PRINT_MSG(" * HUGE PAGES: " << (Mem::isHugepagesAvailable() ? "available" : "unavailable") << ", " <<
(Mem::isHugepagesEnabled() ? "enabled" : "disabled"));
}
}
static void print_cpu()
{
if (Options::i()->colors()) {
if(Options::i()->colors())
{
/*
Log::i()->text("\x1B[01;32m * \x1B[01;37mCPU: %s (%d) %sx64 %sAES-NI",
Cpu::brand(),
Cpu::sockets(),
Cpu::isX64() ? "\x1B[01;32m" : "\x1B[01;31m-",
Cpu::hasAES() ? "\x1B[01;32m" : "\x1B[01;31m-");
# ifndef XMRIG_NO_LIBCPUID
Log::i()->text("\x1B[01;32m * \x1B[01;37mCPU L2/L3: %.1f MB/%.1f MB", Cpu::l2() / 1024.0, Cpu::l3() / 1024.0);
# endif
# ifndef XMRIG_NO_LIBCPUID
Log::i()->text("\x1B[01;32m * \x1B[01;37mCPU L2/L3: %.1f MB/%.1f MB", Cpu::l2() / 1024.0,
Cpu::l3() / 1024.0);
# endif
*/
}
else {
Log::i()->text(" * CPU: %s (%d) %sx64 %sAES-NI", Cpu::brand(), Cpu::sockets(), Cpu::isX64() ? "" : "-", Cpu::hasAES() ? "" : "-");
else
{
PRINT_MSG(" * CPU: " << Cpu::brand() << " (" << Cpu::sockets() << ") " << (Cpu::isX64() ? "" : "-") <<
" " << (Cpu::hasAES() ? "" : "-") << "AES-NI");
# ifndef XMRIG_NO_LIBCPUID
Log::i()->text(" * CPU L2/L3: %.1f MB/%.1f MB", Cpu::l2() / 1024.0, Cpu::l3() / 1024.0);
PRINT_MSG(" * CPU L2/L3: " << (Cpu::l2() / 1024.0) << " MB/" << Cpu::l3() / 1024.0 << " MB");
# endif
}
}
@ -92,37 +103,34 @@ static void print_cpu()
static void print_threads()
{
char buf[32];
if (Options::i()->affinity() != -1L) {
if(Options::i()->affinity() != -1L)
{
snprintf(buf, 32, ", affinity=0x%" PRIX64, Options::i()->affinity());
}
else {
else
{
buf[0] = '\0';
}
Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mTHREADS: \x1B[01;36m%d\x1B[01;37m, %s, av=%d, %sdonate=%d%%%s" : " * THREADS: %d, %s, av=%d, %sdonate=%d%%%s",
Options::i()->threads(),
Options::i()->algoName(),
Options::i()->algoVariant(),
Options::i()->colors() && Options::i()->donateLevel() == 0 ? "\x1B[01;31m" : "",
Options::i()->donateLevel(),
buf);
PRINT_MSG(" * THREADS: " << Options::i()->threads() << ", " << Options::i()->algoName() << ", av=" <<
Options::i()->algoVariant() << ", donate=" << Options::i()->donateLevel() << " " << buf);
}
static void print_pools()
{
const std::vector<Url*> &pools = Options::i()->pools();
const std::vector<Url> & pools = Options::i()->pools();
for (size_t i = 0; i < pools.size(); ++i) {
Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mPOOL #%d: \x1B[01;36m%s:%d" : " * POOL #%d: %s:%d",
i + 1,
pools[i]->host(),
pools[i]->port());
for(size_t i = 0; i < pools.size(); ++i)
{
PRINT_MSG(" * POOL #" << (i + 1) << ": " << pools[i].host() << ":" << pools[i].port());
}
# ifdef APP_DEBUG
for (size_t i = 0; i < pools.size(); ++i) {
Log::i()->text("%s:%d, user: %s, pass: %s, ka: %d, nicehash: %d", pools[i]->host(), pools[i]->port(), pools[i]->user(), pools[i]->password(), pools[i]->isKeepAlive(), pools[i]->isNicehash());
for(size_t i = 0; i < pools.size(); ++i)
{
PRINT_MSG(pools[i].host() << ":" << pools[i].port() << ", user: " << pools[i].user() << ", pass: " <<
pools[i].password() << ", ka: " << pools[i].isKeepAlive() << ", nicehash: " << pools[i].isNicehash());
}
# endif
}
@ -131,22 +139,37 @@ static void print_pools()
#ifndef XMRIG_NO_API
static void print_api()
{
if (Options::i()->apiPort() == 0) {
if(Options::i()->apiPort() == 0)
{
return;
}
Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mAPI PORT: \x1B[01;36m%d" : " * API PORT: %d", Options::i()->apiPort());
if(Options::i()->colors())
{
/*TODO LOG
Log::i()->text(Options::i()->colors() ? "\x1B[01;32m * \x1B[01;37mAPI PORT: \x1B[01;36m%d" :
" * API PORT: %d", Options::i()->apiPort());
*/
}
else
{
PRINT_MSG(" * API PORT: " << Options::i()->apiPort());
}
}
#endif
static void print_commands()
{
if (Options::i()->colors()) {
if(Options::i()->colors())
{
/*
Log::i()->text("\x1B[01;32m * \x1B[01;37mCOMMANDS: \x1B[01;35mh\x1B[01;37mashrate, \x1B[01;35mp\x1B[01;37mause, \x1B[01;35mr\x1B[01;37mesume");
*/
}
else {
Log::i()->text(" * COMMANDS: 'h' hashrate, 'p' pause, 'r' resume");
else
{
PRINT_MSG(" * COMMANDS: 'h' hashrate, 'p' pause, 'r' resume");
}
}

View file

@ -21,6 +21,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_NO_API
#include <string.h>
@ -28,7 +29,7 @@
#include "api/ApiState.h"
ApiState *Api::m_state = nullptr;
ApiState* Api::m_state = nullptr;
uv_mutex_t Api::m_mutex;
@ -47,23 +48,25 @@ void Api::release()
}
char *Api::get(const char *url, int *status)
std::string Api::get(const std::string & url, int* status)
{
if (!m_state) {
return nullptr;
if(!m_state)
{
return "";
}
uv_mutex_lock(&m_mutex);
char *buf = m_state->get(url, status);
std::string buf = m_state->get(url, status);
uv_mutex_unlock(&m_mutex);
return buf;
}
void Api::tick(const Hashrate *hashrate)
void Api::tick(const Hashrate* hashrate)
{
if (!m_state) {
if(!m_state)
{
return;
}
@ -73,9 +76,10 @@ void Api::tick(const Hashrate *hashrate)
}
void Api::tick(const NetworkState &network)
void Api::tick(const NetworkState & network)
{
if (!m_state) {
if(!m_state)
{
return;
}
@ -83,3 +87,5 @@ void Api::tick(const NetworkState &network)
m_state->tick(network);
uv_mutex_unlock(&m_mutex);
}
#endif

View file

@ -26,6 +26,7 @@
#include <uv.h>
#include <string>
class ApiState;
@ -39,12 +40,12 @@ public:
static bool start();
static void release();
static char *get(const char *url, int *status);
static void tick(const Hashrate *hashrate);
static void tick(const NetworkState &results);
static std::string get(const std::string & url, int* status);
static void tick(const Hashrate* hashrate);
static void tick(const NetworkState & results);
private:
static ApiState *m_state;
static ApiState* m_state;
static uv_mutex_t m_mutex;
};

View file

@ -31,7 +31,6 @@
# include "unistd.h"
#endif
#include "api/ApiState.h"
#include "Cpu.h"
#include "Mem.h"
@ -50,13 +49,14 @@ extern "C"
#include "crypto/c_keccak.h"
}
static inline double normalize(double d)
{
if (!isnormal(d)) {
#ifndef _WIN32
if(!isnormal(d))
{
return 0.0;
}
#endif
return floor(d * 100.0) / 100.0;
}
@ -69,10 +69,12 @@ ApiState::ApiState()
memset(m_totalHashrate, 0, sizeof(m_totalHashrate));
memset(m_workerId, 0, sizeof(m_workerId));
if (Options::i()->apiWorkerId()) {
strncpy(m_workerId, Options::i()->apiWorkerId(), sizeof(m_workerId) - 1);
if(0 < Options::i()->apiWorkerId().size())
{
strncpy(m_workerId, Options::i()->apiWorkerId().c_str(), sizeof(m_workerId) - 1);
}
else {
else
{
gethostname(m_workerId, sizeof(m_workerId) - 1);
}
@ -86,7 +88,7 @@ ApiState::~ApiState()
}
char *ApiState::get(const char *url, int *status) const
std::string ApiState::get(const std::string & url, int* status) const
{
rapidjson::Document doc;
doc.SetObject();
@ -101,9 +103,10 @@ char *ApiState::get(const char *url, int *status) const
}
void ApiState::tick(const Hashrate *hashrate)
void ApiState::tick(const Hashrate* hashrate)
{
for (int i = 0; i < m_threads; ++i) {
for(int i = 0; i < m_threads; ++i)
{
m_hashrate[i * 3] = hashrate->calc((size_t) i, Hashrate::ShortInterval);
m_hashrate[i * 3 + 1] = hashrate->calc((size_t) i, Hashrate::MediumInterval);
m_hashrate[i * 3 + 2] = hashrate->calc((size_t) i, Hashrate::LargeInterval);
@ -116,20 +119,20 @@ void ApiState::tick(const Hashrate *hashrate)
}
void ApiState::tick(const NetworkState &network)
void ApiState::tick(const NetworkState & network)
{
m_network = network;
}
char *ApiState::finalize(rapidjson::Document &doc) const
std::string ApiState::finalize(rapidjson::Document & doc) const
{
rapidjson::StringBuffer buffer(0, 4096);
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer);
writer.SetMaxDecimalPlaces(10);
doc.Accept(writer);
return strdup(buffer.GetString());
return buffer.GetString();
}
@ -137,25 +140,30 @@ void ApiState::genId()
{
memset(m_id, 0, sizeof(m_id));
uv_interface_address_t *interfaces;
uv_interface_address_t* interfaces;
int count = 0;
if (uv_interface_addresses(&interfaces, &count) < 0) {
if(uv_interface_addresses(&interfaces, &count) < 0)
{
return;
}
for (int i = 0; i < count; i++) {
if (!interfaces[i].is_internal && interfaces[i].address.address4.sin_family == AF_INET) {
for(int i = 0; i < count; i++)
{
if(!interfaces[i].is_internal && interfaces[i].address.address4.sin_family == AF_INET)
{
uint8_t hash[200];
const size_t addrSize = sizeof(interfaces[i].phys_addr);
const size_t inSize = strlen(APP_KIND) + addrSize;
uint8_t *input = new uint8_t[inSize]();
uint8_t* input = new uint8_t[inSize]();
memcpy(input, interfaces[i].phys_addr, addrSize);
memcpy(input + addrSize, APP_KIND, strlen(APP_KIND));
keccak(input, static_cast<int>(inSize), hash, sizeof(hash));
Job::toHex(hash, 8, m_id);
char* hashChar = (char*)hash;
Job::toHex(std::string(hashChar, 8), m_id);
delete [] input;
break;
@ -166,9 +174,9 @@ void ApiState::genId()
}
void ApiState::getConnection(rapidjson::Document &doc) const
void ApiState::getConnection(rapidjson::Document & doc) const
{
auto &allocator = doc.GetAllocator();
auto & allocator = doc.GetAllocator();
rapidjson::Value connection(rapidjson::kObjectType);
connection.AddMember("pool", rapidjson::StringRef(m_network.pool), allocator);
@ -181,19 +189,21 @@ void ApiState::getConnection(rapidjson::Document &doc) const
}
void ApiState::getHashrate(rapidjson::Document &doc) const
void ApiState::getHashrate(rapidjson::Document & doc) const
{
auto &allocator = doc.GetAllocator();
auto & allocator = doc.GetAllocator();
rapidjson::Value hashrate(rapidjson::kObjectType);
rapidjson::Value total(rapidjson::kArrayType);
rapidjson::Value threads(rapidjson::kArrayType);
for (int i = 0; i < 3; ++i) {
for(int i = 0; i < 3; ++i)
{
total.PushBack(normalize(m_totalHashrate[i]), allocator);
}
for (int i = 0; i < m_threads * 3; i += 3) {
for(int i = 0; i < m_threads * 3; i += 3)
{
rapidjson::Value thread(rapidjson::kArrayType);
thread.PushBack(normalize(m_hashrate[i]), allocator);
thread.PushBack(normalize(m_hashrate[i + 1]), allocator);
@ -209,16 +219,16 @@ void ApiState::getHashrate(rapidjson::Document &doc) const
}
void ApiState::getIdentify(rapidjson::Document &doc) const
void ApiState::getIdentify(rapidjson::Document & doc) const
{
doc.AddMember("id", rapidjson::StringRef(m_id), doc.GetAllocator());
doc.AddMember("worker_id", rapidjson::StringRef(m_workerId), doc.GetAllocator());
}
void ApiState::getMiner(rapidjson::Document &doc) const
void ApiState::getMiner(rapidjson::Document & doc) const
{
auto &allocator = doc.GetAllocator();
auto & allocator = doc.GetAllocator();
rapidjson::Value cpu(rapidjson::kObjectType);
cpu.AddMember("brand", rapidjson::StringRef(Cpu::brand()), allocator);
@ -228,7 +238,7 @@ void ApiState::getMiner(rapidjson::Document &doc) const
doc.AddMember("version", APP_VERSION, allocator);
doc.AddMember("kind", APP_KIND, allocator);
doc.AddMember("ua", rapidjson::StringRef(Platform::userAgent()), allocator);
doc.AddMember("ua", rapidjson::StringRef(Platform::userAgent().c_str()), allocator);
doc.AddMember("cpu", cpu, allocator);
doc.AddMember("algo", rapidjson::StringRef(Options::i()->algoName()), allocator);
doc.AddMember("hugepages", Mem::isHugepagesEnabled(), allocator);
@ -236,9 +246,9 @@ void ApiState::getMiner(rapidjson::Document &doc) const
}
void ApiState::getResults(rapidjson::Document &doc) const
void ApiState::getResults(rapidjson::Document & doc) const
{
auto &allocator = doc.GetAllocator();
auto & allocator = doc.GetAllocator();
rapidjson::Value results(rapidjson::kObjectType);
@ -249,7 +259,8 @@ void ApiState::getResults(rapidjson::Document &doc) const
results.AddMember("hashes_total", m_network.total, allocator);
rapidjson::Value best(rapidjson::kArrayType);
for (size_t i = 0; i < m_network.topDiff.size(); ++i) {
for(size_t i = 0; i < m_network.topDiff.size(); ++i)
{
best.PushBack(m_network.topDiff[i], allocator);
}

View file

@ -28,6 +28,7 @@
#include "api/NetworkState.h"
#include "rapidjson/fwd.h"
#include <string>
class Hashrate;
@ -38,22 +39,22 @@ public:
ApiState();
~ApiState();
char *get(const char *url, int *status) const;
void tick(const Hashrate *hashrate);
void tick(const NetworkState &results);
std::string get(const std::string & url, int* status) const;
void tick(const Hashrate* hashrate);
void tick(const NetworkState & results);
private:
char *finalize(rapidjson::Document &doc) const;
std::string finalize(rapidjson::Document & doc) const;
void genId();
void getConnection(rapidjson::Document &doc) const;
void getHashrate(rapidjson::Document &doc) const;
void getIdentify(rapidjson::Document &doc) const;
void getMiner(rapidjson::Document &doc) const;
void getResults(rapidjson::Document &doc) const;
void getConnection(rapidjson::Document & doc) const;
void getHashrate(rapidjson::Document & doc) const;
void getIdentify(rapidjson::Document & doc) const;
void getMiner(rapidjson::Document & doc) const;
void getResults(rapidjson::Document & doc) const;
char m_id[17];
char m_workerId[128];
double *m_hashrate;
double* m_hashrate;
double m_highestHashrate;
double m_totalHashrate[3];
int m_threads;

View file

@ -21,32 +21,32 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_NO_HTTPD
#include <microhttpd.h>
#include <string.h>
#include "api/Api.h"
#include "api/Httpd.h"
#include "log/Log.h"
Httpd::Httpd(int port, const char *accessToken) :
Httpd::Httpd(int port, const std::string & accessToken) :
m_accessToken(accessToken),
m_port(port),
m_daemon(nullptr)
{
}
bool Httpd::start()
{
if (!m_port) {
if(!m_port)
{
return false;
}
m_daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, m_port, nullptr, nullptr, &Httpd::handler, this, MHD_OPTION_END);
if (!m_daemon) {
m_daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, m_port, nullptr, nullptr, &Httpd::handler, this,
MHD_OPTION_END);
if(!m_daemon)
{
LOG_ERR("HTTP Daemon failed to start.");
return false;
}
@ -55,28 +55,32 @@ bool Httpd::start()
}
int Httpd::auth(const char *header)
int Httpd::auth(const std::string & header)
{
if (!m_accessToken) {
if(m_accessToken.empty())
{
return MHD_HTTP_OK;
}
if (m_accessToken && !header) {
if(0 < m_accessToken.size() && header.empty())
{
return MHD_HTTP_UNAUTHORIZED;
}
const size_t size = strlen(header);
if (size < 8 || strlen(m_accessToken) != size - 7 || memcmp("Bearer ", header, 7) != 0) {
const size_t size = header.size();
if(size < 8 || m_accessToken.size() != size - 7 || "Bearer " == header.substr(0, 7))
{
return MHD_HTTP_FORBIDDEN;
}
return strncmp(m_accessToken, header + 7, strlen(m_accessToken)) == 0 ? MHD_HTTP_OK : MHD_HTTP_FORBIDDEN;
return (m_accessToken == header.substr(7)) ? MHD_HTTP_OK : MHD_HTTP_FORBIDDEN;
}
int Httpd::done(MHD_Connection *connection, int status, MHD_Response *rsp)
int Httpd::done(MHD_Connection* connection, int status, MHD_Response* rsp)
{
if (!rsp) {
if(!rsp)
{
rsp = MHD_create_response_from_buffer(0, nullptr, MHD_RESPMEM_PERSISTENT);
}
@ -91,26 +95,42 @@ int Httpd::done(MHD_Connection *connection, int status, MHD_Response *rsp)
}
int Httpd::handler(void *cls, struct MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **con_cls)
int Httpd::handlerStd(void* cls, struct MHD_Connection* connection, const std::string & url,
const std::string & method, const std::string & version, const std::string & upload_data,
size_t* upload_data_size, void** con_cls)
{
if (strcmp(method, "OPTIONS") == 0) {
if(method == "OPTIONS")
{
return done(connection, MHD_HTTP_OK, nullptr);
}
if (strcmp(method, "GET") != 0) {
if(method != "GET")
{
return MHD_NO;
}
int status = static_cast<Httpd*>(cls)->auth(MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "Authorization"));
if (status != MHD_HTTP_OK) {
int status = static_cast<Httpd*>(cls)->auth(MHD_lookup_connection_value(connection, MHD_HEADER_KIND,
"Authorization"));
if(status != MHD_HTTP_OK)
{
return done(connection, status, nullptr);
}
char *buf = Api::get(url, &status);
if (buf == nullptr) {
std::string buf = Api::get(url, &status);
if(buf.empty())
{
return MHD_NO;
}
MHD_Response *rsp = MHD_create_response_from_buffer(strlen(buf), (void*) buf, MHD_RESPMEM_MUST_FREE);
MHD_Response* rsp = MHD_create_response_from_buffer(buf.size(), (void*) buf.c_str(), MHD_RESPMEM_MUST_FREE);
return done(connection, status, rsp);
}
int Httpd::handler(void* cls, MHD_Connection* connection, const char* url, const char* method,
const char* version, const char* upload_data, size_t* upload_data_size,
void** con_cls)
{
return handlerStd(cls, connection, url, method, version, upload_data, upload_data_size, con_cls);
}
#endif

View file

@ -24,30 +24,34 @@
#ifndef __HTTPD_H__
#define __HTTPD_H__
#include <uv.h>
struct MHD_Connection;
struct MHD_Daemon;
struct MHD_Response;
class Httpd
{
public:
Httpd(int port, const char *accessToken);
Httpd(int port, const std::string & accessToken);
bool start();
private:
int auth(const char *header);
int auth(const std::string & header);
static int done(MHD_Connection *connection, int status, MHD_Response *rsp);
static int handler(void *cls, MHD_Connection *connection, const char *url, const char *method, const char *version, const char *upload_data, size_t *upload_data_size, void **con_cls);
static int done(MHD_Connection* connection, int status, MHD_Response* rsp);
static int handlerStd(void* cls, MHD_Connection* connection, const std::string & url,
const std::string & method,
const std::string & version, const std::string & upload_data, size_t* upload_data_size,
void** con_cls);
const char *m_accessToken;
static int handler(void* cls, MHD_Connection* connection, const char* url, const char* method,
const char* version, const char* upload_data, size_t* upload_data_size,
void** con_cls);
const std::string & m_accessToken;
const int m_port;
MHD_Daemon *m_daemon;
MHD_Daemon* m_daemon;
};
#endif /* __HTTPD_H__ */

View file

@ -27,6 +27,8 @@
#include <string.h>
#include <uv.h>
#include "interfaces/interface.h"
#include "api/NetworkState.h"
#include "net/SubmitResult.h"
@ -52,7 +54,8 @@ int NetworkState::connectionTime() const
uint32_t NetworkState::avgTime() const
{
if (m_latency.empty()) {
if(m_latency.empty())
{
return 0;
}
@ -63,7 +66,8 @@ uint32_t NetworkState::avgTime() const
uint32_t NetworkState::latency() const
{
const size_t calls = m_latency.size();
if (calls == 0) {
if(calls == 0)
{
return 0;
}
@ -74,9 +78,10 @@ uint32_t NetworkState::latency() const
}
void NetworkState::add(const SubmitResult &result, const char *error)
void NetworkState::add(const SubmitResult & result, const std::string & error)
{
if (error) {
if(0 < error.size())
{
rejected++;
return;
}
@ -85,7 +90,8 @@ void NetworkState::add(const SubmitResult &result, const char *error)
total += result.diff;
const size_t ln = topDiff.size() - 1;
if (result.actualDiff > topDiff[ln]) {
if(result.actualDiff > topDiff[ln])
{
topDiff[ln] = result.actualDiff;
std::sort(topDiff.rbegin(), topDiff.rend());
}
@ -94,9 +100,9 @@ void NetworkState::add(const SubmitResult &result, const char *error)
}
void NetworkState::setPool(const char *host, int port, const char *ip)
void NetworkState::setPool(const std::string & host, int port, const std::string & ip)
{
snprintf(pool, sizeof(pool) - 1, "%s:%d", host, port);
snprintf(pool, sizeof(pool) - 1, "%s:%d", host.c_str(), port);
m_active = true;
m_connectionTime = uv_now(uv_default_loop());

View file

@ -40,12 +40,12 @@ public:
int connectionTime() const;
uint32_t avgTime() const;
uint32_t latency() const;
void add(const SubmitResult &result, const char *error);
void setPool(const char *host, int port, const char *ip);
void add(const SubmitResult & result, const std::string & error);
void setPool(const std::string & host, int port, const std::string & ip);
void stop();
char pool[256];
std::array<uint64_t, 10> topDiff { { } };
std::array<uint64_t, 10> topDiff;
uint32_t diff;
uint64_t accepted;
uint64_t failures;

View file

@ -36,58 +36,69 @@
#include "Options.h"
void (*cryptonight_hash_ctx)(const void *input, size_t size, void *output, cryptonight_ctx *ctx) = nullptr;
void (*cryptonight_hash_ctx)(const void* input, size_t size, void* output, cryptonight_ctx* ctx) = nullptr;
static void cryptonight_av1_aesni(const void *input, size_t size, void *output, struct cryptonight_ctx *ctx) {
static void cryptonight_av1_aesni(const void* input, size_t size, void* output, struct cryptonight_ctx* ctx)
{
# if !defined(XMRIG_ARMv7)
cryptonight_hash<0x80000, MEMORY, 0x1FFFF0, false>(input, size, output, ctx);
# endif
}
static void cryptonight_av2_aesni_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
static void cryptonight_av2_aesni_double(const void* input, size_t size, void* output, cryptonight_ctx* ctx)
{
# if !defined(XMRIG_ARMv7)
cryptonight_double_hash<0x80000, MEMORY, 0x1FFFF0, false>(input, size, output, ctx);
# endif
}
static void cryptonight_av3_softaes(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
static void cryptonight_av3_softaes(const void* input, size_t size, void* output, cryptonight_ctx* ctx)
{
cryptonight_hash<0x80000, MEMORY, 0x1FFFF0, true>(input, size, output, ctx);
}
static void cryptonight_av4_softaes_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
static void cryptonight_av4_softaes_double(const void* input, size_t size, void* output, cryptonight_ctx* ctx)
{
cryptonight_double_hash<0x80000, MEMORY, 0x1FFFF0, true>(input, size, output, ctx);
}
#ifndef XMRIG_NO_AEON
static void cryptonight_lite_av1_aesni(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
# if !defined(XMRIG_ARMv7)
static void cryptonight_lite_av1_aesni(const void* input, size_t size, void* output, cryptonight_ctx* ctx)
{
# if !defined(XMRIG_ARMv7)
cryptonight_hash<0x40000, MEMORY_LITE, 0xFFFF0, false>(input, size, output, ctx);
#endif
}
static void cryptonight_lite_av2_aesni_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
static void cryptonight_lite_av2_aesni_double(const void* input, size_t size, void* output,
cryptonight_ctx* ctx)
{
# if !defined(XMRIG_ARMv7)
cryptonight_double_hash<0x40000, MEMORY_LITE, 0xFFFF0, false>(input, size, output, ctx);
# endif
}
static void cryptonight_lite_av3_softaes(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
static void cryptonight_lite_av3_softaes(const void* input, size_t size, void* output, cryptonight_ctx* ctx)
{
cryptonight_hash<0x40000, MEMORY_LITE, 0xFFFF0, true>(input, size, output, ctx);
}
static void cryptonight_lite_av4_softaes_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) {
static void cryptonight_lite_av4_softaes_double(const void* input, size_t size, void* output,
cryptonight_ctx* ctx)
{
cryptonight_double_hash<0x40000, MEMORY_LITE, 0xFFFF0, true>(input, size, output, ctx);
}
void (*cryptonight_variations[8])(const void *input, size_t size, void *output, cryptonight_ctx *ctx) = {
void (*cryptonight_variations[8])(const void* input, size_t size, void* output, cryptonight_ctx* ctx) =
{
cryptonight_av1_aesni,
cryptonight_av2_aesni_double,
cryptonight_av3_softaes,
@ -96,18 +107,19 @@ void (*cryptonight_variations[8])(const void *input, size_t size, void *output,
cryptonight_lite_av2_aesni_double,
cryptonight_lite_av3_softaes,
cryptonight_lite_av4_softaes_double
};
};
#else
void (*cryptonight_variations[4])(const void *input, size_t size, void *output, cryptonight_ctx *ctx) = {
void (*cryptonight_variations[4])(const void* input, size_t size, void* output, cryptonight_ctx* ctx) =
{
cryptonight_av1_aesni,
cryptonight_av2_aesni_double,
cryptonight_av3_softaes,
cryptonight_av4_softaes_double
};
};
#endif
bool CryptoNight::hash(const Job &job, JobResult &result, cryptonight_ctx *ctx)
bool CryptoNight::hash(const Job & job, JobResult & result, cryptonight_ctx* ctx)
{
cryptonight_hash_ctx(job.blob(), job.size(), result.result, ctx);
@ -117,7 +129,8 @@ bool CryptoNight::hash(const Job &job, JobResult &result, cryptonight_ctx *ctx)
bool CryptoNight::init(int algo, int variant)
{
if (variant < 1 || variant > 4) {
if(variant < 1 || variant > 4)
{
return false;
}
@ -133,21 +146,23 @@ bool CryptoNight::init(int algo, int variant)
}
void CryptoNight::hash(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx)
void CryptoNight::hash(const uint8_t* input, size_t size, uint8_t* output, cryptonight_ctx* ctx)
{
cryptonight_hash_ctx(input, size, output, ctx);
}
bool CryptoNight::selfTest(int algo) {
if (cryptonight_hash_ctx == nullptr) {
bool CryptoNight::selfTest(int algo)
{
if(cryptonight_hash_ctx == nullptr)
{
return false;
}
char output[64];
struct cryptonight_ctx *ctx = (struct cryptonight_ctx*) _mm_malloc(sizeof(struct cryptonight_ctx), 16);
ctx->memory = (uint8_t *) _mm_malloc(MEMORY * 2, 16);
struct cryptonight_ctx* ctx = (struct cryptonight_ctx*) _mm_malloc(sizeof(struct cryptonight_ctx), 16);
ctx->memory = (uint8_t*) _mm_malloc(MEMORY * 2, 16);
cryptonight_hash_ctx(test_input, 76, output, ctx);
@ -155,7 +170,8 @@ bool CryptoNight::selfTest(int algo) {
_mm_free(ctx);
# ifndef XMRIG_NO_AEON
return memcmp(output, algo == Options::ALGO_CRYPTONIGHT_LITE ? test_output1 : test_output0, (Options::i()->doubleHash() ? 64 : 32)) == 0;
return memcmp(output, algo == Options::ALGO_CRYPTONIGHT_LITE ? test_output1 : test_output0,
(Options::i()->doubleHash() ? 64 : 32)) == 0;
# else
return memcmp(output, test_output0, (Options::i()->doubleHash() ? 64 : 32)) == 0;
# endif

View file

@ -36,7 +36,8 @@
#define MEMORY_LITE 1048576 /* 1 MiB */
struct cryptonight_ctx {
struct cryptonight_ctx
{
VAR_ALIGN(16, uint8_t state0[200]);
VAR_ALIGN(16, uint8_t state1[200]);
VAR_ALIGN(16, uint8_t* memory);
@ -50,9 +51,9 @@ class JobResult;
class CryptoNight
{
public:
static bool hash(const Job &job, JobResult &result, cryptonight_ctx *ctx);
static bool hash(const Job & job, JobResult & result, cryptonight_ctx* ctx);
static bool init(int algo, int variant);
static void hash(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx);
static void hash(const uint8_t* input, size_t size, uint8_t* output, cryptonight_ctx* ctx);
private:
static bool selfTest(int algo);

View file

@ -47,27 +47,31 @@ extern "C"
}
static inline void do_blake_hash(const void* input, size_t len, char* output) {
static inline void do_blake_hash(const void* input, size_t len, char* output)
{
blake256_hash(reinterpret_cast<uint8_t*>(output), static_cast<const uint8_t*>(input), len);
}
static inline void do_groestl_hash(const void* input, size_t len, char* output) {
static inline void do_groestl_hash(const void* input, size_t len, char* output)
{
groestl(static_cast<const uint8_t*>(input), len * 8, reinterpret_cast<uint8_t*>(output));
}
static inline void do_jh_hash(const void* input, size_t len, char* output) {
static inline void do_jh_hash(const void* input, size_t len, char* output)
{
jh_hash(32 * 8, static_cast<const uint8_t*>(input), 8 * len, reinterpret_cast<uint8_t*>(output));
}
static inline void do_skein_hash(const void* input, size_t len, char* output) {
static inline void do_skein_hash(const void* input, size_t len, char* output)
{
xmr_skein(static_cast<const uint8_t*>(input), reinterpret_cast<uint8_t*>(output));
}
void (* const extra_hashes[4])(const void *, size_t, char *) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash};
void (* const extra_hashes[4])(const void*, size_t, char*) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash};
static inline __attribute__((always_inline)) __m128i _mm_set_epi64x(const uint64_t a, const uint64_t b)
@ -94,7 +98,8 @@ static inline uint64_t __umul128(uint64_t a, uint64_t b, uint64_t* hi)
return (uint64_t) r;
}
#else
static inline uint64_t __umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
static inline uint64_t __umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t* product_hi)
{
// multiplier = ab = a * 2^32 + b
// multiplicand = cd = c * 2^32 + d
// ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
@ -139,14 +144,14 @@ static inline __m128i sl_xor(__m128i tmp1)
template<uint8_t rcon>
static inline void aes_genkey_sub(__m128i* xout0, __m128i* xout2)
{
// __m128i xout1 = _mm_aeskeygenassist_si128(*xout2, rcon);
// xout1 = _mm_shuffle_epi32(xout1, 0xFF); // see PSHUFD, set all elems to 4th elem
// *xout0 = sl_xor(*xout0);
// *xout0 = _mm_xor_si128(*xout0, xout1);
// xout1 = _mm_aeskeygenassist_si128(*xout0, 0x00);
// xout1 = _mm_shuffle_epi32(xout1, 0xAA); // see PSHUFD, set all elems to 3rd elem
// *xout2 = sl_xor(*xout2);
// *xout2 = _mm_xor_si128(*xout2, xout1);
// __m128i xout1 = _mm_aeskeygenassist_si128(*xout2, rcon);
// xout1 = _mm_shuffle_epi32(xout1, 0xFF); // see PSHUFD, set all elems to 4th elem
// *xout0 = sl_xor(*xout0);
// *xout0 = _mm_xor_si128(*xout0, xout1);
// xout1 = _mm_aeskeygenassist_si128(*xout0, 0x00);
// xout1 = _mm_shuffle_epi32(xout1, 0xAA); // see PSHUFD, set all elems to 3rd elem
// *xout2 = sl_xor(*xout2);
// *xout2 = _mm_xor_si128(*xout2, xout1);
}
@ -165,7 +170,8 @@ static inline void soft_aes_genkey_sub(__m128i* xout0, __m128i* xout2)
template<bool SOFT_AES>
static inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i* k2, __m128i* k3, __m128i* k4, __m128i* k5, __m128i* k6, __m128i* k7, __m128i* k8, __m128i* k9)
static inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i* k2, __m128i* k3,
__m128i* k4, __m128i* k5, __m128i* k6, __m128i* k7, __m128i* k8, __m128i* k9)
{
__m128i xout0 = _mm_load_si128(memory);
__m128i xout2 = _mm_load_si128(memory + 1);
@ -191,9 +197,11 @@ static inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, _
template<bool SOFT_AES>
static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7)
static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4,
__m128i* x5, __m128i* x6, __m128i* x7)
{
if (SOFT_AES) {
if(SOFT_AES)
{
*x0 = soft_aesenc(*x0, key);
*x1 = soft_aesenc(*x1, key);
*x2 = soft_aesenc(*x2, key);
@ -204,22 +212,23 @@ static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2,
*x7 = soft_aesenc(*x7, key);
}
# ifndef XMRIG_ARMv7
else {
*x0 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x0), key));
*x1 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x1), key));
*x2 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x2), key));
*x3 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x3), key));
*x4 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x4), key));
*x5 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x5), key));
*x6 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x6), key));
*x7 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t *) x7), key));
else
{
*x0 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t*) x0), key));
*x1 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t*) x1), key));
*x2 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t*) x2), key));
*x3 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t*) x3), key));
*x4 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t*) x4), key));
*x5 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t*) x5), key));
*x6 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t*) x6), key));
*x7 = vaesmcq_u8(vaeseq_u8(*((uint8x16_t*) x7), key));
}
# endif
}
template<size_t MEM, bool SOFT_AES>
static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
static inline void cn_explode_scratchpad(const __m128i* input, __m128i* output)
{
__m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7;
__m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
@ -235,8 +244,10 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
xin6 = _mm_load_si128(input + 10);
xin7 = _mm_load_si128(input + 11);
for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8) {
if (!SOFT_AES) {
for(size_t i = 0; i < MEM / sizeof(__m128i); i += 8)
{
if(!SOFT_AES)
{
aes_round<SOFT_AES>(_mm_setzero_si128(), &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
}
@ -250,7 +261,8 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
aes_round<SOFT_AES>(k7, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k8, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
if (!SOFT_AES) {
if(!SOFT_AES)
{
xin0 ^= k9;
xin1 ^= k9;
xin2 ^= k9;
@ -260,7 +272,8 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
xin6 ^= k9;
xin7 ^= k9;
}
else {
else
{
aes_round<SOFT_AES>(k9, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
}
@ -277,7 +290,7 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
template<size_t MEM, bool SOFT_AES>
static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
static inline void cn_implode_scratchpad(const __m128i* input, __m128i* output)
{
__m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7;
__m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
@ -293,7 +306,7 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
xout6 = _mm_load_si128(output + 10);
xout7 = _mm_load_si128(output + 11);
for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8)
for(size_t i = 0; i < MEM / sizeof(__m128i); i += 8)
{
xout0 = _mm_xor_si128(_mm_load_si128(input + i + 0), xout0);
xout1 = _mm_xor_si128(_mm_load_si128(input + i + 1), xout1);
@ -304,7 +317,8 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
xout6 = _mm_xor_si128(_mm_load_si128(input + i + 6), xout6);
xout7 = _mm_xor_si128(_mm_load_si128(input + i + 7), xout7);
if (!SOFT_AES) {
if(!SOFT_AES)
{
aes_round<SOFT_AES>(_mm_setzero_si128(), &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
}
@ -318,7 +332,8 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
aes_round<SOFT_AES>(k7, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
aes_round<SOFT_AES>(k8, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
if (!SOFT_AES) {
if(!SOFT_AES)
{
xout0 ^= k9;
xout1 ^= k9;
xout2 ^= k9;
@ -328,7 +343,8 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
xout6 ^= k9;
xout7 ^= k9;
}
else {
else
{
aes_round<SOFT_AES>(k9, &xout0, &xout1, &xout2, &xout3, &xout4, &xout5, &xout6, &xout7);
}
}
@ -345,7 +361,8 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
template<size_t ITERATIONS, size_t MEM, size_t MASK, bool SOFT_AES>
inline void cryptonight_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, cryptonight_ctx *__restrict__ ctx)
inline void cryptonight_hash(const void* __restrict__ input, size_t size, void* __restrict__ output,
cryptonight_ctx* __restrict__ ctx)
{
keccak(static_cast<const uint8_t*>(input), (int) size, ctx->state0, 200);
@ -360,19 +377,22 @@ inline void cryptonight_hash(const void *__restrict__ input, size_t size, void *
uint64_t idx0 = h0[0] ^ h0[4];
for (size_t i = 0; i < ITERATIONS; i++) {
__m128i cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
for(size_t i = 0; i < ITERATIONS; i++)
{
__m128i cx = _mm_load_si128((__m128i*) &l0[idx0 & MASK]);
if (SOFT_AES) {
if(SOFT_AES)
{
cx = soft_aesenc(cx, _mm_set_epi64x(ah0, al0));
}
else {
else
{
# ifndef XMRIG_ARMv7
cx = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah0, al0);
# endif
}
_mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx));
_mm_store_si128((__m128i*) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx));
idx0 = EXTRACT64(cx);
bx0 = cx;
@ -400,10 +420,11 @@ inline void cryptonight_hash(const void *__restrict__ input, size_t size, void *
template<size_t ITERATIONS, size_t MEM, size_t MASK, bool SOFT_AES>
inline void cryptonight_double_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx)
inline void cryptonight_double_hash(const void* __restrict__ input, size_t size, void* __restrict__ output,
struct cryptonight_ctx* __restrict__ ctx)
{
keccak((const uint8_t *) input, (int) size, ctx->state0, 200);
keccak((const uint8_t *) input + size, (int) size, ctx->state1, 200);
keccak((const uint8_t*) input, (int) size, ctx->state0, 200);
keccak((const uint8_t*) input + size, (int) size, ctx->state1, 200);
const uint8_t* l0 = ctx->memory;
const uint8_t* l1 = ctx->memory + MEM;
@ -424,23 +445,26 @@ inline void cryptonight_double_hash(const void *__restrict__ input, size_t size,
uint64_t idx0 = h0[0] ^ h0[4];
uint64_t idx1 = h1[0] ^ h1[4];
for (size_t i = 0; i < ITERATIONS; i++) {
__m128i cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
__m128i cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]);
for(size_t i = 0; i < ITERATIONS; i++)
{
__m128i cx0 = _mm_load_si128((__m128i*) &l0[idx0 & MASK]);
__m128i cx1 = _mm_load_si128((__m128i*) &l1[idx1 & MASK]);
if (SOFT_AES) {
if(SOFT_AES)
{
cx0 = soft_aesenc(cx0, _mm_set_epi64x(ah0, al0));
cx1 = soft_aesenc(cx1, _mm_set_epi64x(ah1, al1));
}
else {
else
{
# ifndef XMRIG_ARMv7
cx0 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx0, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah0, al0);
cx1 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx1, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah1, al1);
# endif
}
_mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0));
_mm_store_si128((__m128i *) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1));
_mm_store_si128((__m128i*) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0));
_mm_store_si128((__m128i*) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1));
idx0 = EXTRACT64(cx0);
idx1 = EXTRACT64(cx1);

View file

@ -25,7 +25,8 @@
#define __CRYPTONIGHT_TEST_H__
const static uint8_t test_input[152] = {
const static uint8_t test_input[152] =
{
0x01, 0x00, 0xFB, 0x8E, 0x8A, 0xC8, 0x05, 0x89, 0x93, 0x23, 0x37, 0x1B, 0xB7, 0x90, 0xDB, 0x19,
0x21, 0x8A, 0xFD, 0x8D, 0xB8, 0xE3, 0x75, 0x5D, 0x8B, 0x90, 0xF3, 0x9B, 0x3D, 0x55, 0x06, 0xA9,
0xAB, 0xCE, 0x4F, 0xA9, 0x12, 0x24, 0x45, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x81, 0x46, 0xD4, 0x9F,
@ -39,7 +40,8 @@ const static uint8_t test_input[152] = {
};
const static uint8_t test_output0[64] = {
const static uint8_t test_output0[64] =
{
0x1B, 0x60, 0x6A, 0x3F, 0x4A, 0x07, 0xD6, 0x48, 0x9A, 0x1B, 0xCD, 0x07, 0x69, 0x7B, 0xD1, 0x66,
0x96, 0xB6, 0x1C, 0x8A, 0xE9, 0x82, 0xF6, 0x1A, 0x90, 0x16, 0x0F, 0x4E, 0x52, 0x82, 0x8A, 0x7F,
0x1A, 0x3F, 0xFB, 0xEE, 0x90, 0x9B, 0x42, 0x0D, 0x91, 0xF7, 0xBE, 0x6E, 0x5F, 0xB5, 0x6D, 0xB7,
@ -48,7 +50,8 @@ const static uint8_t test_output0[64] = {
#ifndef XMRIG_NO_AEON
const static uint8_t test_output1[64] = {
const static uint8_t test_output1[64] =
{
0x28, 0xA2, 0x2B, 0xAD, 0x3F, 0x93, 0xD1, 0x40, 0x8F, 0xCA, 0x47, 0x2E, 0xB5, 0xAD, 0x1C, 0xBE,
0x75, 0xF2, 0x1D, 0x05, 0x3C, 0x8C, 0xE5, 0xB3, 0xAF, 0x10, 0x5A, 0x57, 0x71, 0x3E, 0x21, 0xDD,
0x36, 0x95, 0xB4, 0xB5, 0x3B, 0xB0, 0x03, 0x58, 0xB0, 0xAD, 0x38, 0xDC, 0x16, 0x0F, 0xEB, 0x9E,

View file

@ -47,27 +47,31 @@ extern "C"
}
static inline void do_blake_hash(const void* input, size_t len, char* output) {
static inline void do_blake_hash(const void* input, size_t len, char* output)
{
blake256_hash(reinterpret_cast<uint8_t*>(output), static_cast<const uint8_t*>(input), len);
}
static inline void do_groestl_hash(const void* input, size_t len, char* output) {
static inline void do_groestl_hash(const void* input, size_t len, char* output)
{
groestl(static_cast<const uint8_t*>(input), len * 8, reinterpret_cast<uint8_t*>(output));
}
static inline void do_jh_hash(const void* input, size_t len, char* output) {
static inline void do_jh_hash(const void* input, size_t len, char* output)
{
jh_hash(32 * 8, static_cast<const uint8_t*>(input), 8 * len, reinterpret_cast<uint8_t*>(output));
}
static inline void do_skein_hash(const void* input, size_t len, char* output) {
static inline void do_skein_hash(const void* input, size_t len, char* output)
{
xmr_skein(static_cast<const uint8_t*>(input), reinterpret_cast<uint8_t*>(output));
}
void (* const extra_hashes[4])(const void *, size_t, char *) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash};
void (* const extra_hashes[4])(const void*, size_t, char*) = {do_blake_hash, do_groestl_hash, do_jh_hash, do_skein_hash};
@ -82,7 +86,7 @@ static inline uint64_t __umul128(uint64_t a, uint64_t b, uint64_t* hi)
return (uint64_t) r;
}
# else
#define __umul128 _umul128
#define __umul128 _umul128
# endif
#elif defined(__i386__) || defined(_M_IX86)
# define HI32(X) \
@ -93,7 +97,8 @@ static inline uint64_t __umul128(uint64_t a, uint64_t b, uint64_t* hi)
((uint64_t)(uint32_t)_mm_cvtsi128_si32(X) | \
((uint64_t)(uint32_t)_mm_cvtsi128_si32(HI32(X)) << 32))
static inline uint64_t __umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t *product_hi) {
static inline uint64_t __umul128(uint64_t multiplier, uint64_t multiplicand, uint64_t* product_hi)
{
// multiplier = ab = a * 2^32 + b
// multiplicand = cd = c * 2^32 + d
// ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
@ -164,7 +169,8 @@ static inline void soft_aes_genkey_sub(__m128i* xout0, __m128i* xout2)
template<bool SOFT_AES>
static inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i* k2, __m128i* k3, __m128i* k4, __m128i* k5, __m128i* k6, __m128i* k7, __m128i* k8, __m128i* k9)
static inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, __m128i* k2, __m128i* k3,
__m128i* k4, __m128i* k5, __m128i* k6, __m128i* k7, __m128i* k8, __m128i* k9)
{
__m128i xout0 = _mm_load_si128(memory);
__m128i xout2 = _mm_load_si128(memory + 1);
@ -190,9 +196,11 @@ static inline void aes_genkey(const __m128i* memory, __m128i* k0, __m128i* k1, _
template<bool SOFT_AES>
static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4, __m128i* x5, __m128i* x6, __m128i* x7)
static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2, __m128i* x3, __m128i* x4,
__m128i* x5, __m128i* x6, __m128i* x7)
{
if (SOFT_AES) {
if(SOFT_AES)
{
*x0 = soft_aesenc(*x0, key);
*x1 = soft_aesenc(*x1, key);
*x2 = soft_aesenc(*x2, key);
@ -202,7 +210,8 @@ static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2,
*x6 = soft_aesenc(*x6, key);
*x7 = soft_aesenc(*x7, key);
}
else {
else
{
*x0 = _mm_aesenc_si128(*x0, key);
*x1 = _mm_aesenc_si128(*x1, key);
*x2 = _mm_aesenc_si128(*x2, key);
@ -216,7 +225,7 @@ static inline void aes_round(__m128i key, __m128i* x0, __m128i* x1, __m128i* x2,
template<size_t MEM, bool SOFT_AES>
static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
static inline void cn_explode_scratchpad(const __m128i* input, __m128i* output)
{
__m128i xin0, xin1, xin2, xin3, xin4, xin5, xin6, xin7;
__m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
@ -232,7 +241,8 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
xin6 = _mm_load_si128(input + 10);
xin7 = _mm_load_si128(input + 11);
for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8) {
for(size_t i = 0; i < MEM / sizeof(__m128i); i += 8)
{
aes_round<SOFT_AES>(k0, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k1, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
aes_round<SOFT_AES>(k2, &xin0, &xin1, &xin2, &xin3, &xin4, &xin5, &xin6, &xin7);
@ -257,7 +267,7 @@ static inline void cn_explode_scratchpad(const __m128i *input, __m128i *output)
template<size_t MEM, bool SOFT_AES>
static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
static inline void cn_implode_scratchpad(const __m128i* input, __m128i* output)
{
__m128i xout0, xout1, xout2, xout3, xout4, xout5, xout6, xout7;
__m128i k0, k1, k2, k3, k4, k5, k6, k7, k8, k9;
@ -273,7 +283,7 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
xout6 = _mm_load_si128(output + 10);
xout7 = _mm_load_si128(output + 11);
for (size_t i = 0; i < MEM / sizeof(__m128i); i += 8)
for(size_t i = 0; i < MEM / sizeof(__m128i); i += 8)
{
xout0 = _mm_xor_si128(_mm_load_si128(input + i + 0), xout0);
xout1 = _mm_xor_si128(_mm_load_si128(input + i + 1), xout1);
@ -308,7 +318,8 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output)
template<size_t ITERATIONS, size_t MEM, size_t MASK, bool SOFT_AES>
inline void cryptonight_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, cryptonight_ctx *__restrict__ ctx)
inline void cryptonight_hash(const void* __restrict__ input, size_t size, void* __restrict__ output,
cryptonight_ctx* __restrict__ ctx)
{
keccak(static_cast<const uint8_t*>(input), (int) size, ctx->state0, 200);
@ -323,18 +334,21 @@ inline void cryptonight_hash(const void *__restrict__ input, size_t size, void *
uint64_t idx0 = h0[0] ^ h0[4];
for (size_t i = 0; i < ITERATIONS; i++) {
for(size_t i = 0; i < ITERATIONS; i++)
{
__m128i cx;
cx = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
cx = _mm_load_si128((__m128i*) &l0[idx0 & MASK]);
if (SOFT_AES) {
if(SOFT_AES)
{
cx = soft_aesenc(cx, _mm_set_epi64x(ah0, al0));
}
else {
else
{
cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0));
}
_mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx));
_mm_store_si128((__m128i*) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx));
idx0 = EXTRACT64(cx);
bx0 = cx;
@ -362,10 +376,11 @@ inline void cryptonight_hash(const void *__restrict__ input, size_t size, void *
template<size_t ITERATIONS, size_t MEM, size_t MASK, bool SOFT_AES>
inline void cryptonight_double_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx)
inline void cryptonight_double_hash(const void* __restrict__ input, size_t size, void* __restrict__ output,
struct cryptonight_ctx* __restrict__ ctx)
{
keccak((const uint8_t *) input, (int) size, ctx->state0, 200);
keccak((const uint8_t *) input + size, (int) size, ctx->state1, 200);
keccak((const uint8_t*) input, (int) size, ctx->state0, 200);
keccak((const uint8_t*) input + size, (int) size, ctx->state1, 200);
const uint8_t* l0 = ctx->memory;
const uint8_t* l1 = ctx->memory + MEM;
@ -386,21 +401,24 @@ inline void cryptonight_double_hash(const void *__restrict__ input, size_t size,
uint64_t idx0 = h0[0] ^ h0[4];
uint64_t idx1 = h1[0] ^ h1[4];
for (size_t i = 0; i < ITERATIONS; i++) {
__m128i cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]);
__m128i cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]);
for(size_t i = 0; i < ITERATIONS; i++)
{
__m128i cx0 = _mm_load_si128((__m128i*) &l0[idx0 & MASK]);
__m128i cx1 = _mm_load_si128((__m128i*) &l1[idx1 & MASK]);
if (SOFT_AES) {
if(SOFT_AES)
{
cx0 = soft_aesenc(cx0, _mm_set_epi64x(ah0, al0));
cx1 = soft_aesenc(cx1, _mm_set_epi64x(ah1, al1));
}
else {
else
{
cx0 = _mm_aesenc_si128(cx0, _mm_set_epi64x(ah0, al0));
cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1));
}
_mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0));
_mm_store_si128((__m128i *) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1));
_mm_store_si128((__m128i*) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0));
_mm_store_si128((__m128i*) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1));
idx0 = EXTRACT64(cx0);
idx1 = EXTRACT64(cx1);

View file

@ -338,9 +338,9 @@ FORCE_INLINE __m128 _mm_set_ps(float w, float z, float y, float x)
}
// Sets the four single-precision, floating-point values to the four inputs in reverse order. https://msdn.microsoft.com/en-us/library/vstudio/d2172ct3(v=vs.100).aspx
FORCE_INLINE __m128 _mm_setr_ps(float w, float z , float y , float x )
FORCE_INLINE __m128 _mm_setr_ps(float w, float z , float y , float x)
{
float __attribute__ ((aligned (16))) data[4] = { w, z, y, x };
float __attribute__((aligned(16))) data[4] = { w, z, y, x };
return vreinterpretq_m128_f32(vld1q_f32(data));
}
@ -358,25 +358,25 @@ FORCE_INLINE __m128i _mm_set_epi32(int i3, int i2, int i1, int i0)
}
// Stores four single-precision, floating-point values. https://msdn.microsoft.com/en-us/library/vstudio/s3h4ay6y(v=vs.100).aspx
FORCE_INLINE void _mm_store_ps(float *p, __m128 a)
FORCE_INLINE void _mm_store_ps(float* p, __m128 a)
{
vst1q_f32(p, vreinterpretq_f32_m128(a));
}
// Stores four single-precision, floating-point values. https://msdn.microsoft.com/en-us/library/44e30x22(v=vs.100).aspx
FORCE_INLINE void _mm_storeu_ps(float *p, __m128 a)
FORCE_INLINE void _mm_storeu_ps(float* p, __m128 a)
{
vst1q_f32(p, vreinterpretq_f32_m128(a));
}
// Stores four 32-bit integer values as (as a __m128i value) at the address p. https://msdn.microsoft.com/en-us/library/vstudio/edk11s13(v=vs.100).aspx
FORCE_INLINE void _mm_store_si128(__m128i *p, __m128i a)
FORCE_INLINE void _mm_store_si128(__m128i* p, __m128i a)
{
vst1q_s32((int32_t*) p, vreinterpretq_s32_m128i(a));
}
// Stores the lower single - precision, floating - point value. https://msdn.microsoft.com/en-us/library/tzz10fbx(v=vs.100).aspx
FORCE_INLINE void _mm_store_ss(float *p, __m128 a)
FORCE_INLINE void _mm_store_ss(float* p, __m128 a)
{
vst1q_lane_f32(p, vreinterpretq_f32_m128(a), 0);
}
@ -390,26 +390,26 @@ FORCE_INLINE void _mm_storel_epi64(__m128i* a, __m128i b)
}
// Loads a single single-precision, floating-point value, copying it into all four words https://msdn.microsoft.com/en-us/library/vstudio/5cdkf716(v=vs.100).aspx
FORCE_INLINE __m128 _mm_load1_ps(const float * p)
FORCE_INLINE __m128 _mm_load1_ps(const float* p)
{
return vreinterpretq_m128_f32(vld1q_dup_f32(p));
}
// Loads four single-precision, floating-point values. https://msdn.microsoft.com/en-us/library/vstudio/zzd50xxt(v=vs.100).aspx
FORCE_INLINE __m128 _mm_load_ps(const float * p)
FORCE_INLINE __m128 _mm_load_ps(const float* p)
{
return vreinterpretq_m128_f32(vld1q_f32(p));
}
// Loads four single-precision, floating-point values. https://msdn.microsoft.com/en-us/library/x1b16s7z%28v=vs.90%29.aspx
FORCE_INLINE __m128 _mm_loadu_ps(const float * p)
FORCE_INLINE __m128 _mm_loadu_ps(const float* p)
{
// for neon, alignment doesn't matter, so _mm_load_ps and _mm_loadu_ps are equivalent for neon
return vreinterpretq_m128_f32(vld1q_f32(p));
}
// Loads an single - precision, floating - point value into the low word and clears the upper three words. https://msdn.microsoft.com/en-us/library/548bb9h4%28v=vs.90%29.aspx
FORCE_INLINE __m128 _mm_load_ss(const float * p)
FORCE_INLINE __m128 _mm_load_ss(const float* p)
{
return vreinterpretq_m128_f32(vsetq_lane_f32(*p, vdupq_n_f32(0), 0));
}
@ -422,55 +422,57 @@ FORCE_INLINE __m128 _mm_load_ss(const float * p)
// Compares for inequality. https://msdn.microsoft.com/en-us/library/sf44thbx(v=vs.100).aspx
FORCE_INLINE __m128 _mm_cmpneq_ps(__m128 a, __m128 b)
{
return vreinterpretq_m128_u32( vmvnq_u32( vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b)) ) );
return vreinterpretq_m128_u32(vmvnq_u32(vceqq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))));
}
// Computes the bitwise AND-NOT of the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/68h7wd02(v=vs.100).aspx
FORCE_INLINE __m128 _mm_andnot_ps(__m128 a, __m128 b)
{
return vreinterpretq_m128_s32( vbicq_s32(vreinterpretq_s32_m128(b), vreinterpretq_s32_m128(a)) ); // *NOTE* argument swap
return vreinterpretq_m128_s32(vbicq_s32(vreinterpretq_s32_m128(b),
vreinterpretq_s32_m128(a))); // *NOTE* argument swap
}
// Computes the bitwise AND of the 128-bit value in b and the bitwise NOT of the 128-bit value in a. https://msdn.microsoft.com/en-us/library/vstudio/1beaceh8(v=vs.100).aspx
FORCE_INLINE __m128i _mm_andnot_si128(__m128i a, __m128i b)
{
return vreinterpretq_m128i_s32( vbicq_s32(vreinterpretq_s32_m128i(b), vreinterpretq_s32_m128i(a)) ); // *NOTE* argument swap
return vreinterpretq_m128i_s32(vbicq_s32(vreinterpretq_s32_m128i(b),
vreinterpretq_s32_m128i(a))); // *NOTE* argument swap
}
// Computes the bitwise AND of the 128-bit value in a and the 128-bit value in b. https://msdn.microsoft.com/en-us/library/vstudio/6d1txsa8(v=vs.100).aspx
FORCE_INLINE __m128i _mm_and_si128(__m128i a, __m128i b)
{
return vreinterpretq_m128i_s32( vandq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)) );
return vreinterpretq_m128i_s32(vandq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
}
// Computes the bitwise AND of the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/73ck1xc5(v=vs.100).aspx
FORCE_INLINE __m128 _mm_and_ps(__m128 a, __m128 b)
{
return vreinterpretq_m128_s32( vandq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b)) );
return vreinterpretq_m128_s32(vandq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b)));
}
// Computes the bitwise OR of the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/7ctdsyy0(v=vs.100).aspx
FORCE_INLINE __m128 _mm_or_ps(__m128 a, __m128 b)
{
return vreinterpretq_m128_s32( vorrq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b)) );
return vreinterpretq_m128_s32(vorrq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b)));
}
// Computes bitwise EXOR (exclusive-or) of the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/ss6k3wk8(v=vs.100).aspx
FORCE_INLINE __m128 _mm_xor_ps(__m128 a, __m128 b)
{
return vreinterpretq_m128_s32( veorq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b)) );
return vreinterpretq_m128_s32(veorq_s32(vreinterpretq_s32_m128(a), vreinterpretq_s32_m128(b)));
}
// Computes the bitwise OR of the 128-bit value in a and the 128-bit value in b. https://msdn.microsoft.com/en-us/library/vstudio/ew8ty0db(v=vs.100).aspx
FORCE_INLINE __m128i _mm_or_si128(__m128i a, __m128i b)
{
return vreinterpretq_m128i_s32( vorrq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)) );
return vreinterpretq_m128i_s32(vorrq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
}
// Computes the bitwise XOR of the 128-bit value in a and the 128-bit value in b. https://msdn.microsoft.com/en-us/library/fzt08www(v=vs.100).aspx
FORCE_INLINE __m128i _mm_xor_si128(__m128i a, __m128i b)
{
return vreinterpretq_m128i_s32( veorq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)) );
return vreinterpretq_m128i_s32(veorq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
}
// NEON does not provide this method
@ -478,7 +480,7 @@ FORCE_INLINE __m128i _mm_xor_si128(__m128i a, __m128i b)
FORCE_INLINE int _mm_movemask_ps(__m128 a)
{
#if ENABLE_CPP_VERSION // I am not yet convinced that the NEON version is faster than the C version of this
uint32x4_t &ia = *(uint32x4_t *)&a;
uint32x4_t & ia = *(uint32x4_t*)&a;
return (ia[0] >> 31) | ((ia[1] >> 30) & 2) | ((ia[2] >> 29) & 4) | ((ia[3] >> 28) & 8);
#else
static const uint32x4_t movemask = { 1, 2, 4, 8 };
@ -622,7 +624,7 @@ FORCE_INLINE __m128 _mm_shuffle_ps_2032(__m128 a, __m128 b)
// The same is true on SSE as well.
// Selects four specific single-precision, floating-point values from a and b, based on the mask i. https://msdn.microsoft.com/en-us/library/vstudio/5f0858x0(v=vs.100).aspx
#if ENABLE_CPP_VERSION // I am not convinced that the NEON version is faster than the C version yet.
FORCE_INLINE __m128 _mm_shuffle_ps_default(__m128 a, __m128 b, __constrange(0,255) int imm)
FORCE_INLINE __m128 _mm_shuffle_ps_default(__m128 a, __m128 b, __constrange(0, 255) int imm)
{
__m128 ret;
ret[0] = a[imm & 0x3];
@ -633,19 +635,19 @@ FORCE_INLINE __m128 _mm_shuffle_ps_default(__m128 a, __m128 b, __constrange(0,25
}
#else
#define _mm_shuffle_ps_default(a, b, imm) \
({ \
({ \
float32x4_t ret; \
ret = vmovq_n_f32(vgetq_lane_f32(vreinterpretq_f32_m128(a), (imm) & 0x3)); \
ret = vsetq_lane_f32(vgetq_lane_f32(vreinterpretq_f32_m128(a), ((imm) >> 2) & 0x3), ret, 1); \
ret = vsetq_lane_f32(vgetq_lane_f32(vreinterpretq_f32_m128(b), ((imm) >> 4) & 0x3), ret, 2); \
ret = vsetq_lane_f32(vgetq_lane_f32(vreinterpretq_f32_m128(b), ((imm) >> 6) & 0x3), ret, 3); \
vreinterpretq_m128_f32(ret); \
})
})
#endif
//FORCE_INLINE __m128 _mm_shuffle_ps(__m128 a, __m128 b, __constrange(0,255) int imm)
#define _mm_shuffle_ps(a, b, imm) \
({ \
({ \
__m128 ret; \
switch (imm) \
{ \
@ -668,7 +670,7 @@ FORCE_INLINE __m128 _mm_shuffle_ps_default(__m128 a, __m128 b, __constrange(0,25
default: ret = _mm_shuffle_ps_default((a), (b), (imm)); break; \
} \
ret; \
})
})
// Takes the upper 64 bits of a and places it in the low end of the result
// Takes the lower 64 bits of a and places it into the high end of the result.
@ -748,7 +750,7 @@ FORCE_INLINE __m128i _mm_shuffle_epi_3332(__m128i a)
//FORCE_INLINE __m128i _mm_shuffle_epi32_default(__m128i a, __constrange(0,255) int imm)
#if ENABLE_CPP_VERSION
FORCE_INLINE __m128i _mm_shuffle_epi32_default(__m128i a, __constrange(0,255) int imm)
FORCE_INLINE __m128i _mm_shuffle_epi32_default(__m128i a, __constrange(0, 255) int imm)
{
__m128i ret;
ret[0] = a[imm & 0x3];
@ -759,33 +761,33 @@ FORCE_INLINE __m128i _mm_shuffle_epi32_default(__m128i a, __constrange(0,255) in
}
#else
#define _mm_shuffle_epi32_default(a, imm) \
({ \
({ \
int32x4_t ret; \
ret = vmovq_n_s32(vgetq_lane_s32(vreinterpretq_s32_m128i(a), (imm) & 0x3)); \
ret = vsetq_lane_s32(vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 2) & 0x3), ret, 1); \
ret = vsetq_lane_s32(vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 4) & 0x3), ret, 2); \
ret = vsetq_lane_s32(vgetq_lane_s32(vreinterpretq_s32_m128i(a), ((imm) >> 6) & 0x3), ret, 3); \
vreinterpretq_m128i_s32(ret); \
})
})
#endif
//FORCE_INLINE __m128i _mm_shuffle_epi32_splat(__m128i a, __constrange(0,255) int imm)
#if defined(__aarch64__)
#define _mm_shuffle_epi32_splat(a, imm) \
({ \
({ \
vreinterpretq_m128i_s32(vdupq_laneq_s32(vreinterpretq_s32_m128i(a), (imm))); \
})
})
#else
#define _mm_shuffle_epi32_splat(a, imm) \
({ \
({ \
vreinterpretq_m128i_s32(vdupq_n_s32(vgetq_lane_s32(vreinterpretq_s32_m128i(a), (imm)))); \
})
})
#endif
// Shuffles the 4 signed or unsigned 32-bit integers in a as specified by imm. https://msdn.microsoft.com/en-us/library/56f67xbk%28v=vs.90%29.aspx
//FORCE_INLINE __m128i _mm_shuffle_epi32(__m128i a, __constrange(0,255) int imm)
#define _mm_shuffle_epi32(a, imm) \
({ \
({ \
__m128i ret; \
switch (imm) \
{ \
@ -806,12 +808,12 @@ FORCE_INLINE __m128i _mm_shuffle_epi32_default(__m128i a, __constrange(0,255) in
default: ret = _mm_shuffle_epi32_default((a), (imm)); break; \
} \
ret; \
})
})
// Shuffles the upper 4 signed or unsigned 16 - bit integers in a as specified by imm. https://msdn.microsoft.com/en-us/library/13ywktbs(v=vs.100).aspx
//FORCE_INLINE __m128i _mm_shufflehi_epi16_function(__m128i a, __constrange(0,255) int imm)
#define _mm_shufflehi_epi16_function(a, imm) \
({ \
({ \
int16x8_t ret = vreinterpretq_s16_s32(a); \
int16x4_t highBits = vget_high_s16(ret); \
ret = vsetq_lane_s16(vget_lane_s16(highBits, (imm) & 0x3), ret, 4); \
@ -819,7 +821,7 @@ FORCE_INLINE __m128i _mm_shuffle_epi32_default(__m128i a, __constrange(0,255) in
ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 4) & 0x3), ret, 6); \
ret = vsetq_lane_s16(vget_lane_s16(highBits, ((imm) >> 6) & 0x3), ret, 7); \
vreinterpretq_s32_s16(ret); \
})
})
//FORCE_INLINE __m128i _mm_shufflehi_epi16(__m128i a, __constrange(0,255) int imm)
#define _mm_shufflehi_epi16(a, imm) \
@ -829,7 +831,7 @@ FORCE_INLINE __m128i _mm_shuffle_epi32_default(__m128i a, __constrange(0,255) in
// Shifts the 4 signed or unsigned 32-bit integers in a left by count bits while shifting in zeros. : https://msdn.microsoft.com/en-us/library/z2k3bbtb%28v=vs.90%29.aspx
//FORCE_INLINE __m128i _mm_slli_epi32(__m128i a, __constrange(0,255) int imm)
#define _mm_slli_epi32(a, imm) \
({ \
({ \
__m128i ret; \
if ((imm) <= 0) {\
ret = a; \
@ -841,12 +843,12 @@ FORCE_INLINE __m128i _mm_shuffle_epi32_default(__m128i a, __constrange(0,255) in
ret = vreinterpretq_m128i_s32(vshlq_n_s32(vreinterpretq_s32_m128i(a), (imm))); \
} \
ret; \
})
})
//Shifts the 4 signed or unsigned 32-bit integers in a right by count bits while shifting in zeros. https://msdn.microsoft.com/en-us/library/w486zcfa(v=vs.100).aspx
//FORCE_INLINE __m128i _mm_srli_epi32(__m128i a, __constrange(0,255) int imm)
#define _mm_srli_epi32(a, imm) \
({ \
({ \
__m128i ret; \
if ((imm) <= 0) { \
ret = a; \
@ -858,12 +860,12 @@ FORCE_INLINE __m128i _mm_shuffle_epi32_default(__m128i a, __constrange(0,255) in
ret = vreinterpretq_m128i_u32(vshrq_n_u32(vreinterpretq_u32_m128i(a), (imm))); \
} \
ret; \
})
})
// Shifts the 4 signed 32 - bit integers in a right by count bits while shifting in the sign bit. https://msdn.microsoft.com/en-us/library/z1939387(v=vs.100).aspx
//FORCE_INLINE __m128i _mm_srai_epi32(__m128i a, __constrange(0,255) int imm)
#define _mm_srai_epi32(a, imm) \
({ \
({ \
__m128i ret; \
if ((imm) <= 0) { \
ret = a; \
@ -876,12 +878,12 @@ FORCE_INLINE __m128i _mm_shuffle_epi32_default(__m128i a, __constrange(0,255) in
ret = vreinterpretq_m128i_s32(vshrq_n_s32(vreinterpretq_s32_m128i(a), (imm))); \
} \
ret; \
})
})
// Shifts the 128 - bit value in a right by imm bytes while shifting in zeros.imm must be an immediate. https://msdn.microsoft.com/en-us/library/305w28yz(v=vs.100).aspx
//FORCE_INLINE _mm_srli_si128(__m128i a, __constrange(0,255) int imm)
#define _mm_srli_si128(a, imm) \
({ \
({ \
__m128i ret; \
if ((imm) <= 0) { \
ret = a; \
@ -893,12 +895,12 @@ FORCE_INLINE __m128i _mm_shuffle_epi32_default(__m128i a, __constrange(0,255) in
ret = vreinterpretq_m128i_s8(vextq_s8(vreinterpretq_s8_m128i(a), vdupq_n_s8(0), (imm))); \
} \
ret; \
})
})
// Shifts the 128-bit value in a left by imm bytes while shifting in zeros. imm must be an immediate. https://msdn.microsoft.com/en-us/library/34d3k2kt(v=vs.100).aspx
//FORCE_INLINE __m128i _mm_slli_si128(__m128i a, __constrange(0,255) int imm)
#define _mm_slli_si128(a, imm) \
({ \
({ \
__m128i ret; \
if ((imm) <= 0) { \
ret = a; \
@ -910,7 +912,7 @@ FORCE_INLINE __m128i _mm_shuffle_epi32_default(__m128i a, __constrange(0,255) in
ret = vreinterpretq_m128i_s8(vextq_s8(vdupq_n_s8(0), vreinterpretq_s8_m128i(a), 16 - (imm))); \
} \
ret; \
})
})
// NEON does not provide a version of this function, here is an article about some ways to repro the results.
// http://stackoverflow.com/questions/11870910/sse-mm-movemask-epi8-equivalent-method-for-arm-neon
@ -1000,7 +1002,7 @@ FORCE_INLINE __m128i _mm_mullo_epi16(__m128i a, __m128i b)
// Multiplies the 4 signed or unsigned 32-bit integers from a by the 4 signed or unsigned 32-bit integers from b. https://msdn.microsoft.com/en-us/library/vstudio/bb531409(v=vs.100).aspx
FORCE_INLINE __m128i _mm_mullo_epi32(__m128i a, __m128i b)
{
return vreinterpretq_m128i_s32(vmulq_s32(vreinterpretq_s32_m128i(a),vreinterpretq_s32_m128i(b)));
return vreinterpretq_m128i_s32(vmulq_s32(vreinterpretq_s32_m128i(a), vreinterpretq_s32_m128i(b)));
}
// Multiplies the four single-precision, floating-point values of a and b. https://msdn.microsoft.com/en-us/library/vstudio/22kbk6t9(v=vs.100).aspx
@ -1030,7 +1032,7 @@ FORCE_INLINE __m128 recipq_newton(__m128 in, int n)
{
int i;
float32x4_t recip = vrecpeq_f32(vreinterpretq_f32_m128(in));
for (i = 0; i < n; ++i)
for(i = 0; i < n; ++i)
{
recip = vmulq_f32(recip, vrecpsq_f32(recip, vreinterpretq_f32_m128(in)));
}
@ -1130,7 +1132,7 @@ FORCE_INLINE __m128i _mm_mulhi_epi16(__m128i a, __m128i b)
// Computes pairwise add of each argument as single-precision, floating-point values a and b.
//https://msdn.microsoft.com/en-us/library/yd9wecaa.aspx
FORCE_INLINE __m128 _mm_hadd_ps(__m128 a, __m128 b )
FORCE_INLINE __m128 _mm_hadd_ps(__m128 a, __m128 b)
{
#if defined(__aarch64__)
return vreinterpretq_m128_f32(vpaddq_f32(vreinterpretq_f32_m128(a), vreinterpretq_f32_m128(b))); //AArch64
@ -1193,7 +1195,7 @@ FORCE_INLINE __m128i _mm_cmpgt_epi32(__m128i a, __m128i b)
// see also:
// http://stackoverflow.com/questions/8627331/what-does-ordered-unordered-comparison-mean
// http://stackoverflow.com/questions/29349621/neon-isnanval-intrinsics
FORCE_INLINE __m128 _mm_cmpord_ps(__m128 a, __m128 b )
FORCE_INLINE __m128 _mm_cmpord_ps(__m128 a, __m128 b)
{
// Note: NEON does not have ordered compare builtin
// Need to compare a eq a and b eq b to check for NaN
@ -1318,11 +1320,14 @@ FORCE_INLINE __m128i _mm_cvtps_epi32(__m128 a)
#else
uint32x4_t signmask = vdupq_n_u32(0x80000000);
float32x4_t half = vbslq_f32(signmask, vreinterpretq_f32_m128(a), vdupq_n_f32(0.5f)); /* +/- 0.5 */
int32x4_t r_normal = vcvtq_s32_f32(vaddq_f32(vreinterpretq_f32_m128(a), half)); /* round to integer: [a + 0.5]*/
int32x4_t r_normal = vcvtq_s32_f32(vaddq_f32(vreinterpretq_f32_m128(a),
half)); /* round to integer: [a + 0.5]*/
int32x4_t r_trunc = vcvtq_s32_f32(vreinterpretq_f32_m128(a)); /* truncate to integer: [a] */
int32x4_t plusone = vreinterpretq_s32_u32(vshrq_n_u32(vreinterpretq_u32_s32(vnegq_s32(r_trunc)), 31)); /* 1 or 0 */
int32x4_t plusone = vreinterpretq_s32_u32(vshrq_n_u32(vreinterpretq_u32_s32(vnegq_s32(r_trunc)),
31)); /* 1 or 0 */
int32x4_t r_even = vbicq_s32(vaddq_s32(r_trunc, plusone), vdupq_n_s32(1)); /* ([a] + {0,1}) & ~1 */
float32x4_t delta = vsubq_f32(vreinterpretq_f32_m128(a), vcvtq_f32_s32(r_trunc)); /* compute delta: delta = (a - [a]) */
float32x4_t delta = vsubq_f32(vreinterpretq_f32_m128(a),
vcvtq_f32_s32(r_trunc)); /* compute delta: delta = (a - [a]) */
uint32x4_t is_delta_half = vceqq_f32(delta, half); /* delta == +/- 0.5 */
return vreinterpretq_m128i_s32(vbslq_s32(is_delta_half, r_even, r_normal));
#endif
@ -1354,9 +1359,9 @@ FORCE_INLINE __m128 _mm_castsi128_ps(__m128i a)
}
// Loads 128-bit value. : https://msdn.microsoft.com/en-us/library/atzzad1h(v=vs.80).aspx
FORCE_INLINE __m128i _mm_load_si128(const __m128i *p)
FORCE_INLINE __m128i _mm_load_si128(const __m128i* p)
{
return vreinterpretq_m128i_s32(vld1q_s32((int32_t *)p));
return vreinterpretq_m128i_s32(vld1q_s32((int32_t*)p));
}
// ******************************************
@ -1366,19 +1371,22 @@ FORCE_INLINE __m128i _mm_load_si128(const __m128i *p)
// Packs the 16 signed 16-bit integers from a and b into 8-bit integers and saturates. https://msdn.microsoft.com/en-us/library/k4y4f7w5%28v=vs.90%29.aspx
FORCE_INLINE __m128i _mm_packs_epi16(__m128i a, __m128i b)
{
return vreinterpretq_m128i_s8(vcombine_s8(vqmovn_s16(vreinterpretq_s16_m128i(a)), vqmovn_s16(vreinterpretq_s16_m128i(b))));
return vreinterpretq_m128i_s8(vcombine_s8(vqmovn_s16(vreinterpretq_s16_m128i(a)),
vqmovn_s16(vreinterpretq_s16_m128i(b))));
}
// Packs the 16 signed 16 - bit integers from a and b into 8 - bit unsigned integers and saturates. https://msdn.microsoft.com/en-us/library/07ad1wx4(v=vs.100).aspx
FORCE_INLINE __m128i _mm_packus_epi16(const __m128i a, const __m128i b)
{
return vreinterpretq_m128i_u8(vcombine_u8(vqmovun_s16(vreinterpretq_s16_m128i(a)), vqmovun_s16(vreinterpretq_s16_m128i(b))));
return vreinterpretq_m128i_u8(vcombine_u8(vqmovun_s16(vreinterpretq_s16_m128i(a)),
vqmovun_s16(vreinterpretq_s16_m128i(b))));
}
// Packs the 8 signed 32-bit integers from a and b into signed 16-bit integers and saturates. https://msdn.microsoft.com/en-us/library/393t56f9%28v=vs.90%29.aspx
FORCE_INLINE __m128i _mm_packs_epi32(__m128i a, __m128i b)
{
return vreinterpretq_m128i_s16(vcombine_s16(vqmovn_s32(vreinterpretq_s32_m128i(a)), vqmovn_s32(vreinterpretq_s32_m128i(b))));
return vreinterpretq_m128i_s16(vcombine_s16(vqmovn_s32(vreinterpretq_s32_m128i(a)),
vqmovn_s32(vreinterpretq_s32_m128i(b))));
}
// Interleaves the lower 8 signed or unsigned 8-bit integers in a with the lower 8 signed or unsigned 8-bit integers in b. https://msdn.microsoft.com/en-us/library/xf7k860c%28v=vs.90%29.aspx
@ -1456,16 +1464,16 @@ FORCE_INLINE __m128i _mm_unpackhi_epi32(__m128i a, __m128i b)
// Extracts the selected signed or unsigned 16-bit integer from a and zero extends. https://msdn.microsoft.com/en-us/library/6dceta0c(v=vs.100).aspx
//FORCE_INLINE int _mm_extract_epi16(__m128i a, __constrange(0,8) int imm)
#define _mm_extract_epi16(a, imm) \
({ \
({ \
(vgetq_lane_s16(vreinterpretq_s16_m128i(a), (imm)) & 0x0000ffffUL); \
})
})
// Inserts the least significant 16 bits of b into the selected 16-bit integer of a. https://msdn.microsoft.com/en-us/library/kaze8hz1%28v=vs.100%29.aspx
//FORCE_INLINE __m128i _mm_insert_epi16(__m128i a, const int b, __constrange(0,8) int imm)
#define _mm_insert_epi16(a, b, imm) \
({ \
({ \
vreinterpretq_m128i_s16(vsetq_lane_s16((b), vreinterpretq_s16_m128i(a), (imm))); \
})
})
// ******************************************
// Streaming Extensions
@ -1478,13 +1486,13 @@ FORCE_INLINE void _mm_sfence(void)
}
// Stores the data in a to the address p without polluting the caches. If the cache line containing address p is already in the cache, the cache will be updated.Address p must be 16 - byte aligned. https://msdn.microsoft.com/en-us/library/ba08y07y%28v=vs.90%29.aspx
FORCE_INLINE void _mm_stream_si128(__m128i *p, __m128i a)
FORCE_INLINE void _mm_stream_si128(__m128i* p, __m128i a)
{
*p = a;
}
// Cache line containing p is flushed and invalidated from all caches in the coherency domain. : https://msdn.microsoft.com/en-us/library/ba08y07y(v=vs.100).aspx
FORCE_INLINE void _mm_clflush(void const*p)
FORCE_INLINE void _mm_clflush(void const* p)
{
// no corollary for Neon?
}

View file

@ -20,37 +20,41 @@
(p)[0] = (uint8_t)((v) >> 24); (p)[1] = (uint8_t)((v) >> 16); \
(p)[2] = (uint8_t)((v) >> 8); (p)[3] = (uint8_t)((v) );
const uint8_t sigma[][16] = {
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15},
{14,10, 4, 8, 9,15,13, 6, 1,12, 0, 2,11, 7, 5, 3},
{11, 8,12, 0, 5, 2,15,13,10,14, 3, 6, 7, 1, 9, 4},
{ 7, 9, 3, 1,13,12,11,14, 2, 6, 5,10, 4, 0,15, 8},
{ 9, 0, 5, 7, 2, 4,10,15,14, 1,11,12, 6, 8, 3,13},
{ 2,12, 6,10, 0,11, 8, 3, 4,13, 7, 5,15,14, 1, 9},
{12, 5, 1,15,14,13, 4,10, 0, 7, 6, 3, 9, 2, 8,11},
{13,11, 7,14,12, 1, 3, 9, 5, 0,15, 4, 8, 6, 2,10},
{ 6,15,14, 9,11, 3, 0, 8,12, 2,13, 7, 1, 4,10, 5},
{10, 2, 8, 4, 7, 6, 1, 5,15,11, 9,14, 3,12,13, 0},
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15},
{14,10, 4, 8, 9,15,13, 6, 1,12, 0, 2,11, 7, 5, 3},
{11, 8,12, 0, 5, 2,15,13,10,14, 3, 6, 7, 1, 9, 4},
{ 7, 9, 3, 1,13,12,11,14, 2, 6, 5,10, 4, 0,15, 8}
const uint8_t sigma[][16] =
{
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
{14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
{11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
{12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
{13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5},
{10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0},
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
{14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
{11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8}
};
const uint32_t cst[16] = {
const uint32_t cst[16] =
{
0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344,
0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89,
0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C,
0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917
};
static const uint8_t padding[] = {
0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
static const uint8_t padding[] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
void blake256_compress(state *S, const uint8_t *block) {
void blake256_compress(state* S, const uint8_t* block)
{
uint32_t v[16], m[16], i;
#define ROT(x,n) (((x)<<(32-n))|((x)>>(n)))
@ -64,8 +68,14 @@ void blake256_compress(state *S, const uint8_t *block) {
v[c] += v[d]; \
v[b] = ROT(v[b] ^ v[c], 7);
for (i = 0; i < 16; ++i) m[i] = U8TO32(block + i * 4);
for (i = 0; i < 8; ++i) v[i] = S->h[i];
for(i = 0; i < 16; ++i)
{
m[i] = U8TO32(block + i * 4);
}
for(i = 0; i < 8; ++i)
{
v[i] = S->h[i];
}
v[ 8] = S->s[0] ^ 0x243F6A88;
v[ 9] = S->s[1] ^ 0x85A308D3;
v[10] = S->s[2] ^ 0x13198A2E;
@ -75,14 +85,16 @@ void blake256_compress(state *S, const uint8_t *block) {
v[14] = 0x082EFA98;
v[15] = 0xEC4E6C89;
if (S->nullt == 0) {
if(S->nullt == 0)
{
v[12] ^= S->t[0];
v[13] ^= S->t[0];
v[14] ^= S->t[1];
v[15] ^= S->t[1];
}
for (i = 0; i < 14; ++i) {
for(i = 0; i < 14; ++i)
{
G(0, 4, 8, 12, 0);
G(1, 5, 9, 13, 2);
G(2, 6, 10, 14, 4);
@ -93,11 +105,18 @@ void blake256_compress(state *S, const uint8_t *block) {
G(1, 6, 11, 12, 10);
}
for (i = 0; i < 16; ++i) S->h[i % 8] ^= v[i];
for (i = 0; i < 8; ++i) S->h[i] ^= S->s[i % 4];
for(i = 0; i < 16; ++i)
{
S->h[i % 8] ^= v[i];
}
for(i = 0; i < 8; ++i)
{
S->h[i] ^= S->s[i % 4];
}
}
void blake256_init(state *S) {
void blake256_init(state* S)
{
S->h[0] = 0x6A09E667;
S->h[1] = 0xBB67AE85;
S->h[2] = 0x3C6EF372;
@ -110,7 +129,8 @@ void blake256_init(state *S) {
S->s[0] = S->s[1] = S->s[2] = S->s[3] = 0;
}
void blake224_init(state *S) {
void blake224_init(state* S)
{
S->h[0] = 0xC1059ED8;
S->h[1] = 0x367CD507;
S->h[2] = 0x3070DD17;
@ -124,57 +144,83 @@ void blake224_init(state *S) {
}
// datalen = number of bits
void blake256_update(state *S, const uint8_t *data, uint64_t datalen) {
void blake256_update(state* S, const uint8_t* data, uint64_t datalen)
{
int left = S->buflen >> 3;
int fill = 64 - left;
if (left && (((datalen >> 3) & 0x3F) >= (unsigned) fill)) {
memcpy((void *) (S->buf + left), (void *) data, fill);
if(left && (((datalen >> 3) & 0x3F) >= (unsigned) fill))
{
memcpy((void*)(S->buf + left), (void*) data, fill);
S->t[0] += 512;
if (S->t[0] == 0) S->t[1]++;
if(S->t[0] == 0)
{
S->t[1]++;
}
blake256_compress(S, S->buf);
data += fill;
datalen -= (fill << 3);
left = 0;
}
while (datalen >= 512) {
while(datalen >= 512)
{
S->t[0] += 512;
if (S->t[0] == 0) S->t[1]++;
if(S->t[0] == 0)
{
S->t[1]++;
}
blake256_compress(S, data);
data += 64;
datalen -= 512;
}
if (datalen > 0) {
memcpy((void *) (S->buf + left), (void *) data, datalen >> 3);
if(datalen > 0)
{
memcpy((void*)(S->buf + left), (void*) data, datalen >> 3);
S->buflen = (left << 3) + (int) datalen;
} else {
}
else
{
S->buflen = 0;
}
}
// datalen = number of bits
void blake224_update(state *S, const uint8_t *data, uint64_t datalen) {
void blake224_update(state* S, const uint8_t* data, uint64_t datalen)
{
blake256_update(S, data, datalen);
}
void blake256_final_h(state *S, uint8_t *digest, uint8_t pa, uint8_t pb) {
void blake256_final_h(state* S, uint8_t* digest, uint8_t pa, uint8_t pb)
{
uint8_t msglen[8];
uint32_t lo = S->t[0] + S->buflen, hi = S->t[1];
if (lo < (unsigned) S->buflen) hi++;
if(lo < (unsigned) S->buflen)
{
hi++;
}
U32TO8(msglen + 0, hi);
U32TO8(msglen + 4, lo);
if (S->buflen == 440) { /* one padding byte */
if(S->buflen == 440) /* one padding byte */
{
S->t[0] -= 8;
blake256_update(S, &pa, 8);
} else {
if (S->buflen < 440) { /* enough space to fill the block */
if (S->buflen == 0) S->nullt = 1;
}
else
{
if(S->buflen < 440) /* enough space to fill the block */
{
if(S->buflen == 0)
{
S->nullt = 1;
}
S->t[0] -= 440 - S->buflen;
blake256_update(S, padding, 440 - S->buflen);
} else { /* need 2 compressions */
}
else /* need 2 compressions */
{
S->t[0] -= 512 - S->buflen;
blake256_update(S, padding, 512 - S->buflen);
S->t[0] -= 440;
@ -197,16 +243,19 @@ void blake256_final_h(state *S, uint8_t *digest, uint8_t pa, uint8_t pb) {
U32TO8(digest + 28, S->h[7]);
}
void blake256_final(state *S, uint8_t *digest) {
void blake256_final(state* S, uint8_t* digest)
{
blake256_final_h(S, digest, 0x81, 0x01);
}
void blake224_final(state *S, uint8_t *digest) {
void blake224_final(state* S, uint8_t* digest)
{
blake256_final_h(S, digest, 0x80, 0x00);
}
// inlen = number of bytes
void blake256_hash(uint8_t *out, const uint8_t *in, uint64_t inlen) {
void blake256_hash(uint8_t* out, const uint8_t* in, uint64_t inlen)
{
state S;
blake256_init(&S);
blake256_update(&S, in, inlen * 8);
@ -214,7 +263,8 @@ void blake256_hash(uint8_t *out, const uint8_t *in, uint64_t inlen) {
}
// inlen = number of bytes
void blake224_hash(uint8_t *out, const uint8_t *in, uint64_t inlen) {
void blake224_hash(uint8_t* out, const uint8_t* in, uint64_t inlen)
{
state S;
blake224_init(&S);
blake224_update(&S, in, inlen * 8);
@ -222,13 +272,15 @@ void blake224_hash(uint8_t *out, const uint8_t *in, uint64_t inlen) {
}
// keylen = number of bytes
void hmac_blake256_init(hmac_state *S, const uint8_t *_key, uint64_t keylen) {
const uint8_t *key = _key;
void hmac_blake256_init(hmac_state* S, const uint8_t* _key, uint64_t keylen)
{
const uint8_t* key = _key;
uint8_t keyhash[32];
uint8_t pad[64];
uint64_t i;
if (keylen > 64) {
if(keylen > 64)
{
blake256_hash(keyhash, key, keylen);
key = keyhash;
keylen = 32;
@ -236,14 +288,16 @@ void hmac_blake256_init(hmac_state *S, const uint8_t *_key, uint64_t keylen) {
blake256_init(&S->inner);
memset(pad, 0x36, 64);
for (i = 0; i < keylen; ++i) {
for(i = 0; i < keylen; ++i)
{
pad[i] ^= key[i];
}
blake256_update(&S->inner, pad, 512);
blake256_init(&S->outer);
memset(pad, 0x5c, 64);
for (i = 0; i < keylen; ++i) {
for(i = 0; i < keylen; ++i)
{
pad[i] ^= key[i];
}
blake256_update(&S->outer, pad, 512);
@ -252,13 +306,15 @@ void hmac_blake256_init(hmac_state *S, const uint8_t *_key, uint64_t keylen) {
}
// keylen = number of bytes
void hmac_blake224_init(hmac_state *S, const uint8_t *_key, uint64_t keylen) {
const uint8_t *key = _key;
void hmac_blake224_init(hmac_state* S, const uint8_t* _key, uint64_t keylen)
{
const uint8_t* key = _key;
uint8_t keyhash[32];
uint8_t pad[64];
uint64_t i;
if (keylen > 64) {
if(keylen > 64)
{
blake256_hash(keyhash, key, keylen);
key = keyhash;
keylen = 28;
@ -266,14 +322,16 @@ void hmac_blake224_init(hmac_state *S, const uint8_t *_key, uint64_t keylen) {
blake224_init(&S->inner);
memset(pad, 0x36, 64);
for (i = 0; i < keylen; ++i) {
for(i = 0; i < keylen; ++i)
{
pad[i] ^= key[i];
}
blake224_update(&S->inner, pad, 512);
blake224_init(&S->outer);
memset(pad, 0x5c, 64);
for (i = 0; i < keylen; ++i) {
for(i = 0; i < keylen; ++i)
{
pad[i] ^= key[i];
}
blake224_update(&S->outer, pad, 512);
@ -282,18 +340,21 @@ void hmac_blake224_init(hmac_state *S, const uint8_t *_key, uint64_t keylen) {
}
// datalen = number of bits
void hmac_blake256_update(hmac_state *S, const uint8_t *data, uint64_t datalen) {
void hmac_blake256_update(hmac_state* S, const uint8_t* data, uint64_t datalen)
{
// update the inner state
blake256_update(&S->inner, data, datalen);
}
// datalen = number of bits
void hmac_blake224_update(hmac_state *S, const uint8_t *data, uint64_t datalen) {
void hmac_blake224_update(hmac_state* S, const uint8_t* data, uint64_t datalen)
{
// update the inner state
blake224_update(&S->inner, data, datalen);
}
void hmac_blake256_final(hmac_state *S, uint8_t *digest) {
void hmac_blake256_final(hmac_state* S, uint8_t* digest)
{
uint8_t ihash[32];
blake256_final(&S->inner, ihash);
blake256_update(&S->outer, ihash, 256);
@ -301,7 +362,8 @@ void hmac_blake256_final(hmac_state *S, uint8_t *digest) {
memset(ihash, 0, 32);
}
void hmac_blake224_final(hmac_state *S, uint8_t *digest) {
void hmac_blake224_final(hmac_state* S, uint8_t* digest)
{
uint8_t ihash[32];
blake224_final(&S->inner, ihash);
blake224_update(&S->outer, ihash, 224);
@ -310,7 +372,8 @@ void hmac_blake224_final(hmac_state *S, uint8_t *digest) {
}
// keylen = number of bytes; inlen = number of bytes
void hmac_blake256_hash(uint8_t *out, const uint8_t *key, uint64_t keylen, const uint8_t *in, uint64_t inlen) {
void hmac_blake256_hash(uint8_t* out, const uint8_t* key, uint64_t keylen, const uint8_t* in, uint64_t inlen)
{
hmac_state S;
hmac_blake256_init(&S, key, keylen);
hmac_blake256_update(&S, in, inlen * 8);
@ -318,7 +381,8 @@ void hmac_blake256_hash(uint8_t *out, const uint8_t *key, uint64_t keylen, const
}
// keylen = number of bytes; inlen = number of bytes
void hmac_blake224_hash(uint8_t *out, const uint8_t *key, uint64_t keylen, const uint8_t *in, uint64_t inlen) {
void hmac_blake224_hash(uint8_t* out, const uint8_t* key, uint64_t keylen, const uint8_t* in, uint64_t inlen)
{
hmac_state S;
hmac_blake224_init(&S, key, keylen);
hmac_blake224_update(&S, in, inlen * 8);

View file

@ -3,41 +3,43 @@
#include <stdint.h>
typedef struct {
typedef struct
{
uint32_t h[8], s[4], t[2];
int buflen, nullt;
uint8_t buf[64];
} state;
typedef struct {
typedef struct
{
state inner;
state outer;
} hmac_state;
void blake256_init(state *);
void blake224_init(state *);
void blake256_init(state*);
void blake224_init(state*);
void blake256_update(state *, const uint8_t *, uint64_t);
void blake224_update(state *, const uint8_t *, uint64_t);
void blake256_update(state*, const uint8_t*, uint64_t);
void blake224_update(state*, const uint8_t*, uint64_t);
void blake256_final(state *, uint8_t *);
void blake224_final(state *, uint8_t *);
void blake256_final(state*, uint8_t*);
void blake224_final(state*, uint8_t*);
void blake256_hash(uint8_t *, const uint8_t *, uint64_t);
void blake224_hash(uint8_t *, const uint8_t *, uint64_t);
void blake256_hash(uint8_t*, const uint8_t*, uint64_t);
void blake224_hash(uint8_t*, const uint8_t*, uint64_t);
/* HMAC functions: */
void hmac_blake256_init(hmac_state *, const uint8_t *, uint64_t);
void hmac_blake224_init(hmac_state *, const uint8_t *, uint64_t);
void hmac_blake256_init(hmac_state*, const uint8_t*, uint64_t);
void hmac_blake224_init(hmac_state*, const uint8_t*, uint64_t);
void hmac_blake256_update(hmac_state *, const uint8_t *, uint64_t);
void hmac_blake224_update(hmac_state *, const uint8_t *, uint64_t);
void hmac_blake256_update(hmac_state*, const uint8_t*, uint64_t);
void hmac_blake224_update(hmac_state*, const uint8_t*, uint64_t);
void hmac_blake256_final(hmac_state *, uint8_t *);
void hmac_blake224_final(hmac_state *, uint8_t *);
void hmac_blake256_final(hmac_state*, uint8_t*);
void hmac_blake224_final(hmac_state*, uint8_t*);
void hmac_blake256_hash(uint8_t *, const uint8_t *, uint64_t, const uint8_t *, uint64_t);
void hmac_blake224_hash(uint8_t *, const uint8_t *, uint64_t, const uint8_t *, uint64_t);
void hmac_blake256_hash(uint8_t*, const uint8_t*, uint64_t, const uint8_t*, uint64_t);
void hmac_blake224_hash(uint8_t*, const uint8_t*, uint64_t, const uint8_t*, uint64_t);
#endif /* _BLAKE256_H_ */

View file

@ -14,9 +14,9 @@
#define P_TYPE 0
#define Q_TYPE 1
const uint8_t shift_Values[2][8] = {{0,1,2,3,4,5,6,7},{1,3,5,7,0,2,4,6}};
const uint8_t shift_Values[2][8] = {{0, 1, 2, 3, 4, 5, 6, 7}, {1, 3, 5, 7, 0, 2, 4, 6}};
const uint8_t indices_cyclic[15] = {0,1,2,3,4,5,6,7,0,1,2,3,4,5,6};
const uint8_t indices_cyclic[15] = {0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6};
#define ROTATE_COLUMN_DOWN(v1, v2, amount_bytes, temp_var) {temp_var = (v1<<(8*amount_bytes))|(v2>>(8*(4-amount_bytes))); \
@ -64,68 +64,72 @@ const uint8_t indices_cyclic[15] = {0,1,2,3,4,5,6,7,0,1,2,3,4,5,6};
/* compute one round of P (short variants) */
static void RND512P(uint8_t *x, uint32_t *y, uint32_t r) {
static void RND512P(uint8_t* x, uint32_t* y, uint32_t r)
{
uint32_t temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp;
uint32_t* x32 = (uint32_t*)x;
x32[ 0] ^= 0x00000000^r;
x32[ 2] ^= 0x00000010^r;
x32[ 4] ^= 0x00000020^r;
x32[ 6] ^= 0x00000030^r;
x32[ 8] ^= 0x00000040^r;
x32[10] ^= 0x00000050^r;
x32[12] ^= 0x00000060^r;
x32[14] ^= 0x00000070^r;
COLUMN(x,y, 0, 0, 2, 4, 6, 9, 11, 13, 15, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x,y, 2, 2, 4, 6, 8, 11, 13, 15, 1, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x,y, 4, 4, 6, 8, 10, 13, 15, 1, 3, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x,y, 6, 6, 8, 10, 12, 15, 1, 3, 5, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x,y, 8, 8, 10, 12, 14, 1, 3, 5, 7, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x,y,10, 10, 12, 14, 0, 3, 5, 7, 9, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x,y,12, 12, 14, 0, 2, 5, 7, 9, 11, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x,y,14, 14, 0, 2, 4, 7, 9, 11, 13, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
x32[ 0] ^= 0x00000000 ^ r;
x32[ 2] ^= 0x00000010 ^ r;
x32[ 4] ^= 0x00000020 ^ r;
x32[ 6] ^= 0x00000030 ^ r;
x32[ 8] ^= 0x00000040 ^ r;
x32[10] ^= 0x00000050 ^ r;
x32[12] ^= 0x00000060 ^ r;
x32[14] ^= 0x00000070 ^ r;
COLUMN(x, y, 0, 0, 2, 4, 6, 9, 11, 13, 15, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x, y, 2, 2, 4, 6, 8, 11, 13, 15, 1, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x, y, 4, 4, 6, 8, 10, 13, 15, 1, 3, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x, y, 6, 6, 8, 10, 12, 15, 1, 3, 5, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x, y, 8, 8, 10, 12, 14, 1, 3, 5, 7, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x, y, 10, 10, 12, 14, 0, 3, 5, 7, 9, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x, y, 12, 12, 14, 0, 2, 5, 7, 9, 11, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x, y, 14, 14, 0, 2, 4, 7, 9, 11, 13, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
}
/* compute one round of Q (short variants) */
static void RND512Q(uint8_t *x, uint32_t *y, uint32_t r) {
static void RND512Q(uint8_t* x, uint32_t* y, uint32_t r)
{
uint32_t temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp;
uint32_t* x32 = (uint32_t*)x;
x32[ 0] = ~x32[ 0];
x32[ 1] ^= 0xffffffff^r;
x32[ 1] ^= 0xffffffff ^ r;
x32[ 2] = ~x32[ 2];
x32[ 3] ^= 0xefffffff^r;
x32[ 3] ^= 0xefffffff ^ r;
x32[ 4] = ~x32[ 4];
x32[ 5] ^= 0xdfffffff^r;
x32[ 5] ^= 0xdfffffff ^ r;
x32[ 6] = ~x32[ 6];
x32[ 7] ^= 0xcfffffff^r;
x32[ 7] ^= 0xcfffffff ^ r;
x32[ 8] = ~x32[ 8];
x32[ 9] ^= 0xbfffffff^r;
x32[ 9] ^= 0xbfffffff ^ r;
x32[10] = ~x32[10];
x32[11] ^= 0xafffffff^r;
x32[11] ^= 0xafffffff ^ r;
x32[12] = ~x32[12];
x32[13] ^= 0x9fffffff^r;
x32[13] ^= 0x9fffffff ^ r;
x32[14] = ~x32[14];
x32[15] ^= 0x8fffffff^r;
COLUMN(x,y, 0, 2, 6, 10, 14, 1, 5, 9, 13, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x,y, 2, 4, 8, 12, 0, 3, 7, 11, 15, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x,y, 4, 6, 10, 14, 2, 5, 9, 13, 1, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x,y, 6, 8, 12, 0, 4, 7, 11, 15, 3, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x,y, 8, 10, 14, 2, 6, 9, 13, 1, 5, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x,y,10, 12, 0, 4, 8, 11, 15, 3, 7, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x,y,12, 14, 2, 6, 10, 13, 1, 5, 9, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x,y,14, 0, 4, 8, 12, 15, 3, 7, 11, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
x32[15] ^= 0x8fffffff ^ r;
COLUMN(x, y, 0, 2, 6, 10, 14, 1, 5, 9, 13, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x, y, 2, 4, 8, 12, 0, 3, 7, 11, 15, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x, y, 4, 6, 10, 14, 2, 5, 9, 13, 1, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x, y, 6, 8, 12, 0, 4, 7, 11, 15, 3, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x, y, 8, 10, 14, 2, 6, 9, 13, 1, 5, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x, y, 10, 12, 0, 4, 8, 11, 15, 3, 7, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x, y, 12, 14, 2, 6, 10, 13, 1, 5, 9, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
COLUMN(x, y, 14, 0, 4, 8, 12, 15, 3, 7, 11, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
}
/* compute compression function (short variants) */
static void F512(uint32_t *h, const uint32_t *m) {
static void F512(uint32_t* h, const uint32_t* m)
{
int i;
uint32_t Ptmp[2*COLS512];
uint32_t Qtmp[2*COLS512];
uint32_t y[2*COLS512];
uint32_t z[2*COLS512];
uint32_t Ptmp[2 * COLS512];
uint32_t Qtmp[2 * COLS512];
uint32_t y[2 * COLS512];
uint32_t z[2 * COLS512];
for (i = 0; i < 2*COLS512; i++) {
for(i = 0; i < 2 * COLS512; i++)
{
z[i] = m[i];
Ptmp[i] = h[i]^m[i];
Ptmp[i] = h[i] ^ m[i];
}
/* compute Q(m) */
@ -153,38 +157,46 @@ static void F512(uint32_t *h, const uint32_t *m) {
RND512P((uint8_t*)y, Ptmp, 0x00000009);
/* compute P(h+m) + Q(m) + h */
for (i = 0; i < 2*COLS512; i++) {
h[i] ^= Ptmp[i]^Qtmp[i];
for(i = 0; i < 2 * COLS512; i++)
{
h[i] ^= Ptmp[i] ^ Qtmp[i];
}
}
/* digest up to msglen bytes of input (full blocks only) */
static void Transform(groestlHashState *ctx,
const uint8_t *input,
int msglen) {
static void Transform(groestlHashState* ctx,
const uint8_t* input,
int msglen)
{
/* digest message, one block at a time */
for (; msglen >= SIZE512;
msglen -= SIZE512, input += SIZE512) {
F512(ctx->chaining,(uint32_t*)input);
for(; msglen >= SIZE512;
msglen -= SIZE512, input += SIZE512)
{
F512(ctx->chaining, (uint32_t*)input);
/* increment block counter */
ctx->block_counter1++;
if (ctx->block_counter1 == 0) ctx->block_counter2++;
if(ctx->block_counter1 == 0)
{
ctx->block_counter2++;
}
}
}
/* given state h, do h <- P(h)+h */
static void OutputTransformation(groestlHashState *ctx) {
static void OutputTransformation(groestlHashState* ctx)
{
int j;
uint32_t temp[2*COLS512];
uint32_t y[2*COLS512];
uint32_t z[2*COLS512];
uint32_t temp[2 * COLS512];
uint32_t y[2 * COLS512];
uint32_t z[2 * COLS512];
for (j = 0; j < 2*COLS512; j++) {
for(j = 0; j < 2 * COLS512; j++)
{
temp[j] = ctx->chaining[j];
}
RND512P((uint8_t*)temp, y, 0x00000000);
@ -197,23 +209,25 @@ static void OutputTransformation(groestlHashState *ctx) {
RND512P((uint8_t*)y, z, 0x00000007);
RND512P((uint8_t*)z, y, 0x00000008);
RND512P((uint8_t*)y, temp, 0x00000009);
for (j = 0; j < 2*COLS512; j++) {
for(j = 0; j < 2 * COLS512; j++)
{
ctx->chaining[j] ^= temp[j];
}
}
/* initialise context */
static void Init(groestlHashState* ctx) {
static void Init(groestlHashState* ctx)
{
int i = 0;
/* allocate memory for state and data buffer */
for(;i<(SIZE512/sizeof(uint32_t));i++)
for(; i < (SIZE512 / sizeof(uint32_t)); i++)
{
ctx->chaining[i] = 0;
}
/* set initial value */
ctx->chaining[2*COLS512-1] = u32BIG((uint32_t)HASH_BIT_LEN);
ctx->chaining[2 * COLS512 - 1] = u32BIG((uint32_t)HASH_BIT_LEN);
/* set other variables */
ctx->buf_ptr = 0;
@ -225,20 +239,25 @@ static void Init(groestlHashState* ctx) {
/* update state with databitlen bits of input */
static void Update(groestlHashState* ctx,
const BitSequence* input,
DataLength databitlen) {
DataLength databitlen)
{
int index = 0;
int msglen = (int)(databitlen/8);
int rem = (int)(databitlen%8);
int msglen = (int)(databitlen / 8);
int rem = (int)(databitlen % 8);
/* if the buffer contains data that has not yet been digested, first
add data to buffer until full */
if (ctx->buf_ptr) {
while (ctx->buf_ptr < SIZE512 && index < msglen) {
if(ctx->buf_ptr)
{
while(ctx->buf_ptr < SIZE512 && index < msglen)
{
ctx->buffer[(int)ctx->buf_ptr++] = input[index++];
}
if (ctx->buf_ptr < SIZE512) {
if(ctx->buf_ptr < SIZE512)
{
/* buffer still not full, return */
if (rem) {
if(rem)
{
ctx->bits_in_last_byte = rem;
ctx->buffer[(int)ctx->buf_ptr++] = input[index];
}
@ -251,18 +270,20 @@ static void Update(groestlHashState* ctx,
}
/* digest bulk of message */
Transform(ctx, input+index, msglen-index);
index += ((msglen-index)/SIZE512)*SIZE512;
Transform(ctx, input + index, msglen - index);
index += ((msglen - index) / SIZE512) * SIZE512;
/* store remaining data in buffer */
while (index < msglen) {
while(index < msglen)
{
ctx->buffer[(int)ctx->buf_ptr++] = input[index++];
}
/* if non-integral number of bytes have been supplied, store
remaining bits in last byte, together with information about
number of bits */
if (rem) {
if(rem)
{
ctx->bits_in_last_byte = rem;
ctx->buffer[(int)ctx->buf_ptr++] = input[index];
}
@ -273,42 +294,55 @@ static void Update(groestlHashState* ctx,
/* finalise: process remaining data (including padding), perform
output transformation, and write hash result to 'output' */
static void Final(groestlHashState* ctx,
BitSequence* output) {
int i, j = 0, hashbytelen = HASH_BIT_LEN/8;
uint8_t *s = (BitSequence*)ctx->chaining;
BitSequence* output)
{
int i, j = 0, hashbytelen = HASH_BIT_LEN / 8;
uint8_t* s = (BitSequence*)ctx->chaining;
/* pad with '1'-bit and first few '0'-bits */
if (BILB) {
ctx->buffer[(int)ctx->buf_ptr-1] &= ((1<<BILB)-1)<<(8-BILB);
ctx->buffer[(int)ctx->buf_ptr-1] ^= 0x1<<(7-BILB);
if(BILB)
{
ctx->buffer[(int)ctx->buf_ptr - 1] &= ((1 << BILB) - 1) << (8 - BILB);
ctx->buffer[(int)ctx->buf_ptr - 1] ^= 0x1 << (7 - BILB);
BILB = 0;
}
else ctx->buffer[(int)ctx->buf_ptr++] = 0x80;
else
{
ctx->buffer[(int)ctx->buf_ptr++] = 0x80;
}
/* pad with '0'-bits */
if (ctx->buf_ptr > SIZE512-LENGTHFIELDLEN) {
if(ctx->buf_ptr > SIZE512 - LENGTHFIELDLEN)
{
/* padding requires two blocks */
while (ctx->buf_ptr < SIZE512) {
while(ctx->buf_ptr < SIZE512)
{
ctx->buffer[(int)ctx->buf_ptr++] = 0;
}
/* digest first padding block */
Transform(ctx, ctx->buffer, SIZE512);
ctx->buf_ptr = 0;
}
while (ctx->buf_ptr < SIZE512-LENGTHFIELDLEN) {
while(ctx->buf_ptr < SIZE512 - LENGTHFIELDLEN)
{
ctx->buffer[(int)ctx->buf_ptr++] = 0;
}
/* length padding */
ctx->block_counter1++;
if (ctx->block_counter1 == 0) ctx->block_counter2++;
if(ctx->block_counter1 == 0)
{
ctx->block_counter2++;
}
ctx->buf_ptr = SIZE512;
while (ctx->buf_ptr > SIZE512-(int)sizeof(uint32_t)) {
while(ctx->buf_ptr > SIZE512 - (int)sizeof(uint32_t))
{
ctx->buffer[(int)--ctx->buf_ptr] = (uint8_t)ctx->block_counter1;
ctx->block_counter1 >>= 8;
}
while (ctx->buf_ptr > SIZE512-LENGTHFIELDLEN) {
while(ctx->buf_ptr > SIZE512 - LENGTHFIELDLEN)
{
ctx->buffer[(int)--ctx->buf_ptr] = (uint8_t)ctx->block_counter2;
ctx->block_counter2 >>= 8;
}
@ -318,15 +352,18 @@ static void Final(groestlHashState* ctx,
OutputTransformation(ctx);
/* store hash result in output */
for (i = SIZE512-hashbytelen; i < SIZE512; i++,j++) {
for(i = SIZE512 - hashbytelen; i < SIZE512; i++, j++)
{
output[j] = s[i];
}
/* zeroise relevant variables and deallocate memory */
for (i = 0; i < COLS512; i++) {
for(i = 0; i < COLS512; i++)
{
ctx->chaining[i] = 0;
}
for (i = 0; i < SIZE512; i++) {
for(i = 0; i < SIZE512; i++)
{
ctx->buffer[i] = 0;
}
}
@ -334,7 +371,8 @@ static void Final(groestlHashState* ctx,
/* hash bit sequence */
void groestl(const BitSequence* data,
DataLength databitlen,
BitSequence* hashval) {
BitSequence* hashval)
{
groestlHashState context;

View file

@ -35,8 +35,9 @@ typedef crypto_uint64 uint64_t;
/* NIST API begin */
typedef struct {
uint32_t chaining[SIZE512/sizeof(uint32_t)]; /* actual state */
typedef struct
{
uint32_t chaining[SIZE512 / sizeof(uint32_t)]; /* actual state */
uint32_t block_counter1,
block_counter2; /* message block counter(s) */
BitSequence buffer[SIZE512]; /* data buffer */

View file

@ -23,81 +23,86 @@ typedef uint64_t uint64;
/*define data alignment for different C compilers*/
#if defined(__GNUC__)
#define DATA_ALIGN16(x) x __attribute__ ((aligned(16)))
#define DATA_ALIGN16(x) x __attribute__ ((aligned(16)))
#else
#define DATA_ALIGN16(x) __declspec(align(16)) x
#define DATA_ALIGN16(x) __declspec(align(16)) x
#endif
typedef struct {
typedef struct
{
int hashbitlen; /*the message digest size*/
unsigned long long databitlen; /*the message size in bits*/
unsigned long long datasize_in_buffer; /*the size of the message remained in buffer; assumed to be multiple of 8bits except for the last partial block at the end of the message*/
DATA_ALIGN16(uint64 x[8][2]); /*the 1024-bit state, ( x[i][0] || x[i][1] ) is the ith row of the state in the pseudocode*/
unsigned long long
datasize_in_buffer; /*the size of the message remained in buffer; assumed to be multiple of 8bits except for the last partial block at the end of the message*/
DATA_ALIGN16(uint64
x[8][2]); /*the 1024-bit state, ( x[i][0] || x[i][1] ) is the ith row of the state in the pseudocode*/
unsigned char buffer[64]; /*the 512-bit message block to be hashed;*/
} hashState;
/*The initial hash value H(0)*/
const unsigned char JH224_H0[128]={0x2d,0xfe,0xdd,0x62,0xf9,0x9a,0x98,0xac,0xae,0x7c,0xac,0xd6,0x19,0xd6,0x34,0xe7,0xa4,0x83,0x10,0x5,0xbc,0x30,0x12,0x16,0xb8,0x60,0x38,0xc6,0xc9,0x66,0x14,0x94,0x66,0xd9,0x89,0x9f,0x25,0x80,0x70,0x6f,0xce,0x9e,0xa3,0x1b,0x1d,0x9b,0x1a,0xdc,0x11,0xe8,0x32,0x5f,0x7b,0x36,0x6e,0x10,0xf9,0x94,0x85,0x7f,0x2,0xfa,0x6,0xc1,0x1b,0x4f,0x1b,0x5c,0xd8,0xc8,0x40,0xb3,0x97,0xf6,0xa1,0x7f,0x6e,0x73,0x80,0x99,0xdc,0xdf,0x93,0xa5,0xad,0xea,0xa3,0xd3,0xa4,0x31,0xe8,0xde,0xc9,0x53,0x9a,0x68,0x22,0xb4,0xa9,0x8a,0xec,0x86,0xa1,0xe4,0xd5,0x74,0xac,0x95,0x9c,0xe5,0x6c,0xf0,0x15,0x96,0xd,0xea,0xb5,0xab,0x2b,0xbf,0x96,0x11,0xdc,0xf0,0xdd,0x64,0xea,0x6e};
const unsigned char JH256_H0[128]={0xeb,0x98,0xa3,0x41,0x2c,0x20,0xd3,0xeb,0x92,0xcd,0xbe,0x7b,0x9c,0xb2,0x45,0xc1,0x1c,0x93,0x51,0x91,0x60,0xd4,0xc7,0xfa,0x26,0x0,0x82,0xd6,0x7e,0x50,0x8a,0x3,0xa4,0x23,0x9e,0x26,0x77,0x26,0xb9,0x45,0xe0,0xfb,0x1a,0x48,0xd4,0x1a,0x94,0x77,0xcd,0xb5,0xab,0x26,0x2,0x6b,0x17,0x7a,0x56,0xf0,0x24,0x42,0xf,0xff,0x2f,0xa8,0x71,0xa3,0x96,0x89,0x7f,0x2e,0x4d,0x75,0x1d,0x14,0x49,0x8,0xf7,0x7d,0xe2,0x62,0x27,0x76,0x95,0xf7,0x76,0x24,0x8f,0x94,0x87,0xd5,0xb6,0x57,0x47,0x80,0x29,0x6c,0x5c,0x5e,0x27,0x2d,0xac,0x8e,0xd,0x6c,0x51,0x84,0x50,0xc6,0x57,0x5,0x7a,0xf,0x7b,0xe4,0xd3,0x67,0x70,0x24,0x12,0xea,0x89,0xe3,0xab,0x13,0xd3,0x1c,0xd7,0x69};
const unsigned char JH384_H0[128]={0x48,0x1e,0x3b,0xc6,0xd8,0x13,0x39,0x8a,0x6d,0x3b,0x5e,0x89,0x4a,0xde,0x87,0x9b,0x63,0xfa,0xea,0x68,0xd4,0x80,0xad,0x2e,0x33,0x2c,0xcb,0x21,0x48,0xf,0x82,0x67,0x98,0xae,0xc8,0x4d,0x90,0x82,0xb9,0x28,0xd4,0x55,0xea,0x30,0x41,0x11,0x42,0x49,0x36,0xf5,0x55,0xb2,0x92,0x48,0x47,0xec,0xc7,0x25,0xa,0x93,0xba,0xf4,0x3c,0xe1,0x56,0x9b,0x7f,0x8a,0x27,0xdb,0x45,0x4c,0x9e,0xfc,0xbd,0x49,0x63,0x97,0xaf,0xe,0x58,0x9f,0xc2,0x7d,0x26,0xaa,0x80,0xcd,0x80,0xc0,0x8b,0x8c,0x9d,0xeb,0x2e,0xda,0x8a,0x79,0x81,0xe8,0xf8,0xd5,0x37,0x3a,0xf4,0x39,0x67,0xad,0xdd,0xd1,0x7a,0x71,0xa9,0xb4,0xd3,0xbd,0xa4,0x75,0xd3,0x94,0x97,0x6c,0x3f,0xba,0x98,0x42,0x73,0x7f};
const unsigned char JH512_H0[128]={0x6f,0xd1,0x4b,0x96,0x3e,0x0,0xaa,0x17,0x63,0x6a,0x2e,0x5,0x7a,0x15,0xd5,0x43,0x8a,0x22,0x5e,0x8d,0xc,0x97,0xef,0xb,0xe9,0x34,0x12,0x59,0xf2,0xb3,0xc3,0x61,0x89,0x1d,0xa0,0xc1,0x53,0x6f,0x80,0x1e,0x2a,0xa9,0x5,0x6b,0xea,0x2b,0x6d,0x80,0x58,0x8e,0xcc,0xdb,0x20,0x75,0xba,0xa6,0xa9,0xf,0x3a,0x76,0xba,0xf8,0x3b,0xf7,0x1,0x69,0xe6,0x5,0x41,0xe3,0x4a,0x69,0x46,0xb5,0x8a,0x8e,0x2e,0x6f,0xe6,0x5a,0x10,0x47,0xa7,0xd0,0xc1,0x84,0x3c,0x24,0x3b,0x6e,0x71,0xb1,0x2d,0x5a,0xc1,0x99,0xcf,0x57,0xf6,0xec,0x9d,0xb1,0xf8,0x56,0xa7,0x6,0x88,0x7c,0x57,0x16,0xb1,0x56,0xe3,0xc2,0xfc,0xdf,0xe6,0x85,0x17,0xfb,0x54,0x5a,0x46,0x78,0xcc,0x8c,0xdd,0x4b};
const unsigned char JH224_H0[128] = {0x2d, 0xfe, 0xdd, 0x62, 0xf9, 0x9a, 0x98, 0xac, 0xae, 0x7c, 0xac, 0xd6, 0x19, 0xd6, 0x34, 0xe7, 0xa4, 0x83, 0x10, 0x5, 0xbc, 0x30, 0x12, 0x16, 0xb8, 0x60, 0x38, 0xc6, 0xc9, 0x66, 0x14, 0x94, 0x66, 0xd9, 0x89, 0x9f, 0x25, 0x80, 0x70, 0x6f, 0xce, 0x9e, 0xa3, 0x1b, 0x1d, 0x9b, 0x1a, 0xdc, 0x11, 0xe8, 0x32, 0x5f, 0x7b, 0x36, 0x6e, 0x10, 0xf9, 0x94, 0x85, 0x7f, 0x2, 0xfa, 0x6, 0xc1, 0x1b, 0x4f, 0x1b, 0x5c, 0xd8, 0xc8, 0x40, 0xb3, 0x97, 0xf6, 0xa1, 0x7f, 0x6e, 0x73, 0x80, 0x99, 0xdc, 0xdf, 0x93, 0xa5, 0xad, 0xea, 0xa3, 0xd3, 0xa4, 0x31, 0xe8, 0xde, 0xc9, 0x53, 0x9a, 0x68, 0x22, 0xb4, 0xa9, 0x8a, 0xec, 0x86, 0xa1, 0xe4, 0xd5, 0x74, 0xac, 0x95, 0x9c, 0xe5, 0x6c, 0xf0, 0x15, 0x96, 0xd, 0xea, 0xb5, 0xab, 0x2b, 0xbf, 0x96, 0x11, 0xdc, 0xf0, 0xdd, 0x64, 0xea, 0x6e};
const unsigned char JH256_H0[128] = {0xeb, 0x98, 0xa3, 0x41, 0x2c, 0x20, 0xd3, 0xeb, 0x92, 0xcd, 0xbe, 0x7b, 0x9c, 0xb2, 0x45, 0xc1, 0x1c, 0x93, 0x51, 0x91, 0x60, 0xd4, 0xc7, 0xfa, 0x26, 0x0, 0x82, 0xd6, 0x7e, 0x50, 0x8a, 0x3, 0xa4, 0x23, 0x9e, 0x26, 0x77, 0x26, 0xb9, 0x45, 0xe0, 0xfb, 0x1a, 0x48, 0xd4, 0x1a, 0x94, 0x77, 0xcd, 0xb5, 0xab, 0x26, 0x2, 0x6b, 0x17, 0x7a, 0x56, 0xf0, 0x24, 0x42, 0xf, 0xff, 0x2f, 0xa8, 0x71, 0xa3, 0x96, 0x89, 0x7f, 0x2e, 0x4d, 0x75, 0x1d, 0x14, 0x49, 0x8, 0xf7, 0x7d, 0xe2, 0x62, 0x27, 0x76, 0x95, 0xf7, 0x76, 0x24, 0x8f, 0x94, 0x87, 0xd5, 0xb6, 0x57, 0x47, 0x80, 0x29, 0x6c, 0x5c, 0x5e, 0x27, 0x2d, 0xac, 0x8e, 0xd, 0x6c, 0x51, 0x84, 0x50, 0xc6, 0x57, 0x5, 0x7a, 0xf, 0x7b, 0xe4, 0xd3, 0x67, 0x70, 0x24, 0x12, 0xea, 0x89, 0xe3, 0xab, 0x13, 0xd3, 0x1c, 0xd7, 0x69};
const unsigned char JH384_H0[128] = {0x48, 0x1e, 0x3b, 0xc6, 0xd8, 0x13, 0x39, 0x8a, 0x6d, 0x3b, 0x5e, 0x89, 0x4a, 0xde, 0x87, 0x9b, 0x63, 0xfa, 0xea, 0x68, 0xd4, 0x80, 0xad, 0x2e, 0x33, 0x2c, 0xcb, 0x21, 0x48, 0xf, 0x82, 0x67, 0x98, 0xae, 0xc8, 0x4d, 0x90, 0x82, 0xb9, 0x28, 0xd4, 0x55, 0xea, 0x30, 0x41, 0x11, 0x42, 0x49, 0x36, 0xf5, 0x55, 0xb2, 0x92, 0x48, 0x47, 0xec, 0xc7, 0x25, 0xa, 0x93, 0xba, 0xf4, 0x3c, 0xe1, 0x56, 0x9b, 0x7f, 0x8a, 0x27, 0xdb, 0x45, 0x4c, 0x9e, 0xfc, 0xbd, 0x49, 0x63, 0x97, 0xaf, 0xe, 0x58, 0x9f, 0xc2, 0x7d, 0x26, 0xaa, 0x80, 0xcd, 0x80, 0xc0, 0x8b, 0x8c, 0x9d, 0xeb, 0x2e, 0xda, 0x8a, 0x79, 0x81, 0xe8, 0xf8, 0xd5, 0x37, 0x3a, 0xf4, 0x39, 0x67, 0xad, 0xdd, 0xd1, 0x7a, 0x71, 0xa9, 0xb4, 0xd3, 0xbd, 0xa4, 0x75, 0xd3, 0x94, 0x97, 0x6c, 0x3f, 0xba, 0x98, 0x42, 0x73, 0x7f};
const unsigned char JH512_H0[128] = {0x6f, 0xd1, 0x4b, 0x96, 0x3e, 0x0, 0xaa, 0x17, 0x63, 0x6a, 0x2e, 0x5, 0x7a, 0x15, 0xd5, 0x43, 0x8a, 0x22, 0x5e, 0x8d, 0xc, 0x97, 0xef, 0xb, 0xe9, 0x34, 0x12, 0x59, 0xf2, 0xb3, 0xc3, 0x61, 0x89, 0x1d, 0xa0, 0xc1, 0x53, 0x6f, 0x80, 0x1e, 0x2a, 0xa9, 0x5, 0x6b, 0xea, 0x2b, 0x6d, 0x80, 0x58, 0x8e, 0xcc, 0xdb, 0x20, 0x75, 0xba, 0xa6, 0xa9, 0xf, 0x3a, 0x76, 0xba, 0xf8, 0x3b, 0xf7, 0x1, 0x69, 0xe6, 0x5, 0x41, 0xe3, 0x4a, 0x69, 0x46, 0xb5, 0x8a, 0x8e, 0x2e, 0x6f, 0xe6, 0x5a, 0x10, 0x47, 0xa7, 0xd0, 0xc1, 0x84, 0x3c, 0x24, 0x3b, 0x6e, 0x71, 0xb1, 0x2d, 0x5a, 0xc1, 0x99, 0xcf, 0x57, 0xf6, 0xec, 0x9d, 0xb1, 0xf8, 0x56, 0xa7, 0x6, 0x88, 0x7c, 0x57, 0x16, 0xb1, 0x56, 0xe3, 0xc2, 0xfc, 0xdf, 0xe6, 0x85, 0x17, 0xfb, 0x54, 0x5a, 0x46, 0x78, 0xcc, 0x8c, 0xdd, 0x4b};
/*42 round constants, each round constant is 32-byte (256-bit)*/
const unsigned char E8_bitslice_roundconstant[42][32]={
{0x72,0xd5,0xde,0xa2,0xdf,0x15,0xf8,0x67,0x7b,0x84,0x15,0xa,0xb7,0x23,0x15,0x57,0x81,0xab,0xd6,0x90,0x4d,0x5a,0x87,0xf6,0x4e,0x9f,0x4f,0xc5,0xc3,0xd1,0x2b,0x40},
{0xea,0x98,0x3a,0xe0,0x5c,0x45,0xfa,0x9c,0x3,0xc5,0xd2,0x99,0x66,0xb2,0x99,0x9a,0x66,0x2,0x96,0xb4,0xf2,0xbb,0x53,0x8a,0xb5,0x56,0x14,0x1a,0x88,0xdb,0xa2,0x31},
{0x3,0xa3,0x5a,0x5c,0x9a,0x19,0xe,0xdb,0x40,0x3f,0xb2,0xa,0x87,0xc1,0x44,0x10,0x1c,0x5,0x19,0x80,0x84,0x9e,0x95,0x1d,0x6f,0x33,0xeb,0xad,0x5e,0xe7,0xcd,0xdc},
{0x10,0xba,0x13,0x92,0x2,0xbf,0x6b,0x41,0xdc,0x78,0x65,0x15,0xf7,0xbb,0x27,0xd0,0xa,0x2c,0x81,0x39,0x37,0xaa,0x78,0x50,0x3f,0x1a,0xbf,0xd2,0x41,0x0,0x91,0xd3},
{0x42,0x2d,0x5a,0xd,0xf6,0xcc,0x7e,0x90,0xdd,0x62,0x9f,0x9c,0x92,0xc0,0x97,0xce,0x18,0x5c,0xa7,0xb,0xc7,0x2b,0x44,0xac,0xd1,0xdf,0x65,0xd6,0x63,0xc6,0xfc,0x23},
{0x97,0x6e,0x6c,0x3,0x9e,0xe0,0xb8,0x1a,0x21,0x5,0x45,0x7e,0x44,0x6c,0xec,0xa8,0xee,0xf1,0x3,0xbb,0x5d,0x8e,0x61,0xfa,0xfd,0x96,0x97,0xb2,0x94,0x83,0x81,0x97},
{0x4a,0x8e,0x85,0x37,0xdb,0x3,0x30,0x2f,0x2a,0x67,0x8d,0x2d,0xfb,0x9f,0x6a,0x95,0x8a,0xfe,0x73,0x81,0xf8,0xb8,0x69,0x6c,0x8a,0xc7,0x72,0x46,0xc0,0x7f,0x42,0x14},
{0xc5,0xf4,0x15,0x8f,0xbd,0xc7,0x5e,0xc4,0x75,0x44,0x6f,0xa7,0x8f,0x11,0xbb,0x80,0x52,0xde,0x75,0xb7,0xae,0xe4,0x88,0xbc,0x82,0xb8,0x0,0x1e,0x98,0xa6,0xa3,0xf4},
{0x8e,0xf4,0x8f,0x33,0xa9,0xa3,0x63,0x15,0xaa,0x5f,0x56,0x24,0xd5,0xb7,0xf9,0x89,0xb6,0xf1,0xed,0x20,0x7c,0x5a,0xe0,0xfd,0x36,0xca,0xe9,0x5a,0x6,0x42,0x2c,0x36},
{0xce,0x29,0x35,0x43,0x4e,0xfe,0x98,0x3d,0x53,0x3a,0xf9,0x74,0x73,0x9a,0x4b,0xa7,0xd0,0xf5,0x1f,0x59,0x6f,0x4e,0x81,0x86,0xe,0x9d,0xad,0x81,0xaf,0xd8,0x5a,0x9f},
{0xa7,0x5,0x6,0x67,0xee,0x34,0x62,0x6a,0x8b,0xb,0x28,0xbe,0x6e,0xb9,0x17,0x27,0x47,0x74,0x7,0x26,0xc6,0x80,0x10,0x3f,0xe0,0xa0,0x7e,0x6f,0xc6,0x7e,0x48,0x7b},
{0xd,0x55,0xa,0xa5,0x4a,0xf8,0xa4,0xc0,0x91,0xe3,0xe7,0x9f,0x97,0x8e,0xf1,0x9e,0x86,0x76,0x72,0x81,0x50,0x60,0x8d,0xd4,0x7e,0x9e,0x5a,0x41,0xf3,0xe5,0xb0,0x62},
{0xfc,0x9f,0x1f,0xec,0x40,0x54,0x20,0x7a,0xe3,0xe4,0x1a,0x0,0xce,0xf4,0xc9,0x84,0x4f,0xd7,0x94,0xf5,0x9d,0xfa,0x95,0xd8,0x55,0x2e,0x7e,0x11,0x24,0xc3,0x54,0xa5},
{0x5b,0xdf,0x72,0x28,0xbd,0xfe,0x6e,0x28,0x78,0xf5,0x7f,0xe2,0xf,0xa5,0xc4,0xb2,0x5,0x89,0x7c,0xef,0xee,0x49,0xd3,0x2e,0x44,0x7e,0x93,0x85,0xeb,0x28,0x59,0x7f},
{0x70,0x5f,0x69,0x37,0xb3,0x24,0x31,0x4a,0x5e,0x86,0x28,0xf1,0x1d,0xd6,0xe4,0x65,0xc7,0x1b,0x77,0x4,0x51,0xb9,0x20,0xe7,0x74,0xfe,0x43,0xe8,0x23,0xd4,0x87,0x8a},
{0x7d,0x29,0xe8,0xa3,0x92,0x76,0x94,0xf2,0xdd,0xcb,0x7a,0x9,0x9b,0x30,0xd9,0xc1,0x1d,0x1b,0x30,0xfb,0x5b,0xdc,0x1b,0xe0,0xda,0x24,0x49,0x4f,0xf2,0x9c,0x82,0xbf},
{0xa4,0xe7,0xba,0x31,0xb4,0x70,0xbf,0xff,0xd,0x32,0x44,0x5,0xde,0xf8,0xbc,0x48,0x3b,0xae,0xfc,0x32,0x53,0xbb,0xd3,0x39,0x45,0x9f,0xc3,0xc1,0xe0,0x29,0x8b,0xa0},
{0xe5,0xc9,0x5,0xfd,0xf7,0xae,0x9,0xf,0x94,0x70,0x34,0x12,0x42,0x90,0xf1,0x34,0xa2,0x71,0xb7,0x1,0xe3,0x44,0xed,0x95,0xe9,0x3b,0x8e,0x36,0x4f,0x2f,0x98,0x4a},
{0x88,0x40,0x1d,0x63,0xa0,0x6c,0xf6,0x15,0x47,0xc1,0x44,0x4b,0x87,0x52,0xaf,0xff,0x7e,0xbb,0x4a,0xf1,0xe2,0xa,0xc6,0x30,0x46,0x70,0xb6,0xc5,0xcc,0x6e,0x8c,0xe6},
{0xa4,0xd5,0xa4,0x56,0xbd,0x4f,0xca,0x0,0xda,0x9d,0x84,0x4b,0xc8,0x3e,0x18,0xae,0x73,0x57,0xce,0x45,0x30,0x64,0xd1,0xad,0xe8,0xa6,0xce,0x68,0x14,0x5c,0x25,0x67},
{0xa3,0xda,0x8c,0xf2,0xcb,0xe,0xe1,0x16,0x33,0xe9,0x6,0x58,0x9a,0x94,0x99,0x9a,0x1f,0x60,0xb2,0x20,0xc2,0x6f,0x84,0x7b,0xd1,0xce,0xac,0x7f,0xa0,0xd1,0x85,0x18},
{0x32,0x59,0x5b,0xa1,0x8d,0xdd,0x19,0xd3,0x50,0x9a,0x1c,0xc0,0xaa,0xa5,0xb4,0x46,0x9f,0x3d,0x63,0x67,0xe4,0x4,0x6b,0xba,0xf6,0xca,0x19,0xab,0xb,0x56,0xee,0x7e},
{0x1f,0xb1,0x79,0xea,0xa9,0x28,0x21,0x74,0xe9,0xbd,0xf7,0x35,0x3b,0x36,0x51,0xee,0x1d,0x57,0xac,0x5a,0x75,0x50,0xd3,0x76,0x3a,0x46,0xc2,0xfe,0xa3,0x7d,0x70,0x1},
{0xf7,0x35,0xc1,0xaf,0x98,0xa4,0xd8,0x42,0x78,0xed,0xec,0x20,0x9e,0x6b,0x67,0x79,0x41,0x83,0x63,0x15,0xea,0x3a,0xdb,0xa8,0xfa,0xc3,0x3b,0x4d,0x32,0x83,0x2c,0x83},
{0xa7,0x40,0x3b,0x1f,0x1c,0x27,0x47,0xf3,0x59,0x40,0xf0,0x34,0xb7,0x2d,0x76,0x9a,0xe7,0x3e,0x4e,0x6c,0xd2,0x21,0x4f,0xfd,0xb8,0xfd,0x8d,0x39,0xdc,0x57,0x59,0xef},
{0x8d,0x9b,0xc,0x49,0x2b,0x49,0xeb,0xda,0x5b,0xa2,0xd7,0x49,0x68,0xf3,0x70,0xd,0x7d,0x3b,0xae,0xd0,0x7a,0x8d,0x55,0x84,0xf5,0xa5,0xe9,0xf0,0xe4,0xf8,0x8e,0x65},
{0xa0,0xb8,0xa2,0xf4,0x36,0x10,0x3b,0x53,0xc,0xa8,0x7,0x9e,0x75,0x3e,0xec,0x5a,0x91,0x68,0x94,0x92,0x56,0xe8,0x88,0x4f,0x5b,0xb0,0x5c,0x55,0xf8,0xba,0xbc,0x4c},
{0xe3,0xbb,0x3b,0x99,0xf3,0x87,0x94,0x7b,0x75,0xda,0xf4,0xd6,0x72,0x6b,0x1c,0x5d,0x64,0xae,0xac,0x28,0xdc,0x34,0xb3,0x6d,0x6c,0x34,0xa5,0x50,0xb8,0x28,0xdb,0x71},
{0xf8,0x61,0xe2,0xf2,0x10,0x8d,0x51,0x2a,0xe3,0xdb,0x64,0x33,0x59,0xdd,0x75,0xfc,0x1c,0xac,0xbc,0xf1,0x43,0xce,0x3f,0xa2,0x67,0xbb,0xd1,0x3c,0x2,0xe8,0x43,0xb0},
{0x33,0xa,0x5b,0xca,0x88,0x29,0xa1,0x75,0x7f,0x34,0x19,0x4d,0xb4,0x16,0x53,0x5c,0x92,0x3b,0x94,0xc3,0xe,0x79,0x4d,0x1e,0x79,0x74,0x75,0xd7,0xb6,0xee,0xaf,0x3f},
{0xea,0xa8,0xd4,0xf7,0xbe,0x1a,0x39,0x21,0x5c,0xf4,0x7e,0x9,0x4c,0x23,0x27,0x51,0x26,0xa3,0x24,0x53,0xba,0x32,0x3c,0xd2,0x44,0xa3,0x17,0x4a,0x6d,0xa6,0xd5,0xad},
{0xb5,0x1d,0x3e,0xa6,0xaf,0xf2,0xc9,0x8,0x83,0x59,0x3d,0x98,0x91,0x6b,0x3c,0x56,0x4c,0xf8,0x7c,0xa1,0x72,0x86,0x60,0x4d,0x46,0xe2,0x3e,0xcc,0x8,0x6e,0xc7,0xf6},
{0x2f,0x98,0x33,0xb3,0xb1,0xbc,0x76,0x5e,0x2b,0xd6,0x66,0xa5,0xef,0xc4,0xe6,0x2a,0x6,0xf4,0xb6,0xe8,0xbe,0xc1,0xd4,0x36,0x74,0xee,0x82,0x15,0xbc,0xef,0x21,0x63},
{0xfd,0xc1,0x4e,0xd,0xf4,0x53,0xc9,0x69,0xa7,0x7d,0x5a,0xc4,0x6,0x58,0x58,0x26,0x7e,0xc1,0x14,0x16,0x6,0xe0,0xfa,0x16,0x7e,0x90,0xaf,0x3d,0x28,0x63,0x9d,0x3f},
{0xd2,0xc9,0xf2,0xe3,0x0,0x9b,0xd2,0xc,0x5f,0xaa,0xce,0x30,0xb7,0xd4,0xc,0x30,0x74,0x2a,0x51,0x16,0xf2,0xe0,0x32,0x98,0xd,0xeb,0x30,0xd8,0xe3,0xce,0xf8,0x9a},
{0x4b,0xc5,0x9e,0x7b,0xb5,0xf1,0x79,0x92,0xff,0x51,0xe6,0x6e,0x4,0x86,0x68,0xd3,0x9b,0x23,0x4d,0x57,0xe6,0x96,0x67,0x31,0xcc,0xe6,0xa6,0xf3,0x17,0xa,0x75,0x5},
{0xb1,0x76,0x81,0xd9,0x13,0x32,0x6c,0xce,0x3c,0x17,0x52,0x84,0xf8,0x5,0xa2,0x62,0xf4,0x2b,0xcb,0xb3,0x78,0x47,0x15,0x47,0xff,0x46,0x54,0x82,0x23,0x93,0x6a,0x48},
{0x38,0xdf,0x58,0x7,0x4e,0x5e,0x65,0x65,0xf2,0xfc,0x7c,0x89,0xfc,0x86,0x50,0x8e,0x31,0x70,0x2e,0x44,0xd0,0xb,0xca,0x86,0xf0,0x40,0x9,0xa2,0x30,0x78,0x47,0x4e},
{0x65,0xa0,0xee,0x39,0xd1,0xf7,0x38,0x83,0xf7,0x5e,0xe9,0x37,0xe4,0x2c,0x3a,0xbd,0x21,0x97,0xb2,0x26,0x1,0x13,0xf8,0x6f,0xa3,0x44,0xed,0xd1,0xef,0x9f,0xde,0xe7},
{0x8b,0xa0,0xdf,0x15,0x76,0x25,0x92,0xd9,0x3c,0x85,0xf7,0xf6,0x12,0xdc,0x42,0xbe,0xd8,0xa7,0xec,0x7c,0xab,0x27,0xb0,0x7e,0x53,0x8d,0x7d,0xda,0xaa,0x3e,0xa8,0xde},
{0xaa,0x25,0xce,0x93,0xbd,0x2,0x69,0xd8,0x5a,0xf6,0x43,0xfd,0x1a,0x73,0x8,0xf9,0xc0,0x5f,0xef,0xda,0x17,0x4a,0x19,0xa5,0x97,0x4d,0x66,0x33,0x4c,0xfd,0x21,0x6a},
{0x35,0xb4,0x98,0x31,0xdb,0x41,0x15,0x70,0xea,0x1e,0xf,0xbb,0xed,0xcd,0x54,0x9b,0x9a,0xd0,0x63,0xa1,0x51,0x97,0x40,0x72,0xf6,0x75,0x9d,0xbf,0x91,0x47,0x6f,0xe2}};
const unsigned char E8_bitslice_roundconstant[42][32] =
{
{0x72, 0xd5, 0xde, 0xa2, 0xdf, 0x15, 0xf8, 0x67, 0x7b, 0x84, 0x15, 0xa, 0xb7, 0x23, 0x15, 0x57, 0x81, 0xab, 0xd6, 0x90, 0x4d, 0x5a, 0x87, 0xf6, 0x4e, 0x9f, 0x4f, 0xc5, 0xc3, 0xd1, 0x2b, 0x40},
{0xea, 0x98, 0x3a, 0xe0, 0x5c, 0x45, 0xfa, 0x9c, 0x3, 0xc5, 0xd2, 0x99, 0x66, 0xb2, 0x99, 0x9a, 0x66, 0x2, 0x96, 0xb4, 0xf2, 0xbb, 0x53, 0x8a, 0xb5, 0x56, 0x14, 0x1a, 0x88, 0xdb, 0xa2, 0x31},
{0x3, 0xa3, 0x5a, 0x5c, 0x9a, 0x19, 0xe, 0xdb, 0x40, 0x3f, 0xb2, 0xa, 0x87, 0xc1, 0x44, 0x10, 0x1c, 0x5, 0x19, 0x80, 0x84, 0x9e, 0x95, 0x1d, 0x6f, 0x33, 0xeb, 0xad, 0x5e, 0xe7, 0xcd, 0xdc},
{0x10, 0xba, 0x13, 0x92, 0x2, 0xbf, 0x6b, 0x41, 0xdc, 0x78, 0x65, 0x15, 0xf7, 0xbb, 0x27, 0xd0, 0xa, 0x2c, 0x81, 0x39, 0x37, 0xaa, 0x78, 0x50, 0x3f, 0x1a, 0xbf, 0xd2, 0x41, 0x0, 0x91, 0xd3},
{0x42, 0x2d, 0x5a, 0xd, 0xf6, 0xcc, 0x7e, 0x90, 0xdd, 0x62, 0x9f, 0x9c, 0x92, 0xc0, 0x97, 0xce, 0x18, 0x5c, 0xa7, 0xb, 0xc7, 0x2b, 0x44, 0xac, 0xd1, 0xdf, 0x65, 0xd6, 0x63, 0xc6, 0xfc, 0x23},
{0x97, 0x6e, 0x6c, 0x3, 0x9e, 0xe0, 0xb8, 0x1a, 0x21, 0x5, 0x45, 0x7e, 0x44, 0x6c, 0xec, 0xa8, 0xee, 0xf1, 0x3, 0xbb, 0x5d, 0x8e, 0x61, 0xfa, 0xfd, 0x96, 0x97, 0xb2, 0x94, 0x83, 0x81, 0x97},
{0x4a, 0x8e, 0x85, 0x37, 0xdb, 0x3, 0x30, 0x2f, 0x2a, 0x67, 0x8d, 0x2d, 0xfb, 0x9f, 0x6a, 0x95, 0x8a, 0xfe, 0x73, 0x81, 0xf8, 0xb8, 0x69, 0x6c, 0x8a, 0xc7, 0x72, 0x46, 0xc0, 0x7f, 0x42, 0x14},
{0xc5, 0xf4, 0x15, 0x8f, 0xbd, 0xc7, 0x5e, 0xc4, 0x75, 0x44, 0x6f, 0xa7, 0x8f, 0x11, 0xbb, 0x80, 0x52, 0xde, 0x75, 0xb7, 0xae, 0xe4, 0x88, 0xbc, 0x82, 0xb8, 0x0, 0x1e, 0x98, 0xa6, 0xa3, 0xf4},
{0x8e, 0xf4, 0x8f, 0x33, 0xa9, 0xa3, 0x63, 0x15, 0xaa, 0x5f, 0x56, 0x24, 0xd5, 0xb7, 0xf9, 0x89, 0xb6, 0xf1, 0xed, 0x20, 0x7c, 0x5a, 0xe0, 0xfd, 0x36, 0xca, 0xe9, 0x5a, 0x6, 0x42, 0x2c, 0x36},
{0xce, 0x29, 0x35, 0x43, 0x4e, 0xfe, 0x98, 0x3d, 0x53, 0x3a, 0xf9, 0x74, 0x73, 0x9a, 0x4b, 0xa7, 0xd0, 0xf5, 0x1f, 0x59, 0x6f, 0x4e, 0x81, 0x86, 0xe, 0x9d, 0xad, 0x81, 0xaf, 0xd8, 0x5a, 0x9f},
{0xa7, 0x5, 0x6, 0x67, 0xee, 0x34, 0x62, 0x6a, 0x8b, 0xb, 0x28, 0xbe, 0x6e, 0xb9, 0x17, 0x27, 0x47, 0x74, 0x7, 0x26, 0xc6, 0x80, 0x10, 0x3f, 0xe0, 0xa0, 0x7e, 0x6f, 0xc6, 0x7e, 0x48, 0x7b},
{0xd, 0x55, 0xa, 0xa5, 0x4a, 0xf8, 0xa4, 0xc0, 0x91, 0xe3, 0xe7, 0x9f, 0x97, 0x8e, 0xf1, 0x9e, 0x86, 0x76, 0x72, 0x81, 0x50, 0x60, 0x8d, 0xd4, 0x7e, 0x9e, 0x5a, 0x41, 0xf3, 0xe5, 0xb0, 0x62},
{0xfc, 0x9f, 0x1f, 0xec, 0x40, 0x54, 0x20, 0x7a, 0xe3, 0xe4, 0x1a, 0x0, 0xce, 0xf4, 0xc9, 0x84, 0x4f, 0xd7, 0x94, 0xf5, 0x9d, 0xfa, 0x95, 0xd8, 0x55, 0x2e, 0x7e, 0x11, 0x24, 0xc3, 0x54, 0xa5},
{0x5b, 0xdf, 0x72, 0x28, 0xbd, 0xfe, 0x6e, 0x28, 0x78, 0xf5, 0x7f, 0xe2, 0xf, 0xa5, 0xc4, 0xb2, 0x5, 0x89, 0x7c, 0xef, 0xee, 0x49, 0xd3, 0x2e, 0x44, 0x7e, 0x93, 0x85, 0xeb, 0x28, 0x59, 0x7f},
{0x70, 0x5f, 0x69, 0x37, 0xb3, 0x24, 0x31, 0x4a, 0x5e, 0x86, 0x28, 0xf1, 0x1d, 0xd6, 0xe4, 0x65, 0xc7, 0x1b, 0x77, 0x4, 0x51, 0xb9, 0x20, 0xe7, 0x74, 0xfe, 0x43, 0xe8, 0x23, 0xd4, 0x87, 0x8a},
{0x7d, 0x29, 0xe8, 0xa3, 0x92, 0x76, 0x94, 0xf2, 0xdd, 0xcb, 0x7a, 0x9, 0x9b, 0x30, 0xd9, 0xc1, 0x1d, 0x1b, 0x30, 0xfb, 0x5b, 0xdc, 0x1b, 0xe0, 0xda, 0x24, 0x49, 0x4f, 0xf2, 0x9c, 0x82, 0xbf},
{0xa4, 0xe7, 0xba, 0x31, 0xb4, 0x70, 0xbf, 0xff, 0xd, 0x32, 0x44, 0x5, 0xde, 0xf8, 0xbc, 0x48, 0x3b, 0xae, 0xfc, 0x32, 0x53, 0xbb, 0xd3, 0x39, 0x45, 0x9f, 0xc3, 0xc1, 0xe0, 0x29, 0x8b, 0xa0},
{0xe5, 0xc9, 0x5, 0xfd, 0xf7, 0xae, 0x9, 0xf, 0x94, 0x70, 0x34, 0x12, 0x42, 0x90, 0xf1, 0x34, 0xa2, 0x71, 0xb7, 0x1, 0xe3, 0x44, 0xed, 0x95, 0xe9, 0x3b, 0x8e, 0x36, 0x4f, 0x2f, 0x98, 0x4a},
{0x88, 0x40, 0x1d, 0x63, 0xa0, 0x6c, 0xf6, 0x15, 0x47, 0xc1, 0x44, 0x4b, 0x87, 0x52, 0xaf, 0xff, 0x7e, 0xbb, 0x4a, 0xf1, 0xe2, 0xa, 0xc6, 0x30, 0x46, 0x70, 0xb6, 0xc5, 0xcc, 0x6e, 0x8c, 0xe6},
{0xa4, 0xd5, 0xa4, 0x56, 0xbd, 0x4f, 0xca, 0x0, 0xda, 0x9d, 0x84, 0x4b, 0xc8, 0x3e, 0x18, 0xae, 0x73, 0x57, 0xce, 0x45, 0x30, 0x64, 0xd1, 0xad, 0xe8, 0xa6, 0xce, 0x68, 0x14, 0x5c, 0x25, 0x67},
{0xa3, 0xda, 0x8c, 0xf2, 0xcb, 0xe, 0xe1, 0x16, 0x33, 0xe9, 0x6, 0x58, 0x9a, 0x94, 0x99, 0x9a, 0x1f, 0x60, 0xb2, 0x20, 0xc2, 0x6f, 0x84, 0x7b, 0xd1, 0xce, 0xac, 0x7f, 0xa0, 0xd1, 0x85, 0x18},
{0x32, 0x59, 0x5b, 0xa1, 0x8d, 0xdd, 0x19, 0xd3, 0x50, 0x9a, 0x1c, 0xc0, 0xaa, 0xa5, 0xb4, 0x46, 0x9f, 0x3d, 0x63, 0x67, 0xe4, 0x4, 0x6b, 0xba, 0xf6, 0xca, 0x19, 0xab, 0xb, 0x56, 0xee, 0x7e},
{0x1f, 0xb1, 0x79, 0xea, 0xa9, 0x28, 0x21, 0x74, 0xe9, 0xbd, 0xf7, 0x35, 0x3b, 0x36, 0x51, 0xee, 0x1d, 0x57, 0xac, 0x5a, 0x75, 0x50, 0xd3, 0x76, 0x3a, 0x46, 0xc2, 0xfe, 0xa3, 0x7d, 0x70, 0x1},
{0xf7, 0x35, 0xc1, 0xaf, 0x98, 0xa4, 0xd8, 0x42, 0x78, 0xed, 0xec, 0x20, 0x9e, 0x6b, 0x67, 0x79, 0x41, 0x83, 0x63, 0x15, 0xea, 0x3a, 0xdb, 0xa8, 0xfa, 0xc3, 0x3b, 0x4d, 0x32, 0x83, 0x2c, 0x83},
{0xa7, 0x40, 0x3b, 0x1f, 0x1c, 0x27, 0x47, 0xf3, 0x59, 0x40, 0xf0, 0x34, 0xb7, 0x2d, 0x76, 0x9a, 0xe7, 0x3e, 0x4e, 0x6c, 0xd2, 0x21, 0x4f, 0xfd, 0xb8, 0xfd, 0x8d, 0x39, 0xdc, 0x57, 0x59, 0xef},
{0x8d, 0x9b, 0xc, 0x49, 0x2b, 0x49, 0xeb, 0xda, 0x5b, 0xa2, 0xd7, 0x49, 0x68, 0xf3, 0x70, 0xd, 0x7d, 0x3b, 0xae, 0xd0, 0x7a, 0x8d, 0x55, 0x84, 0xf5, 0xa5, 0xe9, 0xf0, 0xe4, 0xf8, 0x8e, 0x65},
{0xa0, 0xb8, 0xa2, 0xf4, 0x36, 0x10, 0x3b, 0x53, 0xc, 0xa8, 0x7, 0x9e, 0x75, 0x3e, 0xec, 0x5a, 0x91, 0x68, 0x94, 0x92, 0x56, 0xe8, 0x88, 0x4f, 0x5b, 0xb0, 0x5c, 0x55, 0xf8, 0xba, 0xbc, 0x4c},
{0xe3, 0xbb, 0x3b, 0x99, 0xf3, 0x87, 0x94, 0x7b, 0x75, 0xda, 0xf4, 0xd6, 0x72, 0x6b, 0x1c, 0x5d, 0x64, 0xae, 0xac, 0x28, 0xdc, 0x34, 0xb3, 0x6d, 0x6c, 0x34, 0xa5, 0x50, 0xb8, 0x28, 0xdb, 0x71},
{0xf8, 0x61, 0xe2, 0xf2, 0x10, 0x8d, 0x51, 0x2a, 0xe3, 0xdb, 0x64, 0x33, 0x59, 0xdd, 0x75, 0xfc, 0x1c, 0xac, 0xbc, 0xf1, 0x43, 0xce, 0x3f, 0xa2, 0x67, 0xbb, 0xd1, 0x3c, 0x2, 0xe8, 0x43, 0xb0},
{0x33, 0xa, 0x5b, 0xca, 0x88, 0x29, 0xa1, 0x75, 0x7f, 0x34, 0x19, 0x4d, 0xb4, 0x16, 0x53, 0x5c, 0x92, 0x3b, 0x94, 0xc3, 0xe, 0x79, 0x4d, 0x1e, 0x79, 0x74, 0x75, 0xd7, 0xb6, 0xee, 0xaf, 0x3f},
{0xea, 0xa8, 0xd4, 0xf7, 0xbe, 0x1a, 0x39, 0x21, 0x5c, 0xf4, 0x7e, 0x9, 0x4c, 0x23, 0x27, 0x51, 0x26, 0xa3, 0x24, 0x53, 0xba, 0x32, 0x3c, 0xd2, 0x44, 0xa3, 0x17, 0x4a, 0x6d, 0xa6, 0xd5, 0xad},
{0xb5, 0x1d, 0x3e, 0xa6, 0xaf, 0xf2, 0xc9, 0x8, 0x83, 0x59, 0x3d, 0x98, 0x91, 0x6b, 0x3c, 0x56, 0x4c, 0xf8, 0x7c, 0xa1, 0x72, 0x86, 0x60, 0x4d, 0x46, 0xe2, 0x3e, 0xcc, 0x8, 0x6e, 0xc7, 0xf6},
{0x2f, 0x98, 0x33, 0xb3, 0xb1, 0xbc, 0x76, 0x5e, 0x2b, 0xd6, 0x66, 0xa5, 0xef, 0xc4, 0xe6, 0x2a, 0x6, 0xf4, 0xb6, 0xe8, 0xbe, 0xc1, 0xd4, 0x36, 0x74, 0xee, 0x82, 0x15, 0xbc, 0xef, 0x21, 0x63},
{0xfd, 0xc1, 0x4e, 0xd, 0xf4, 0x53, 0xc9, 0x69, 0xa7, 0x7d, 0x5a, 0xc4, 0x6, 0x58, 0x58, 0x26, 0x7e, 0xc1, 0x14, 0x16, 0x6, 0xe0, 0xfa, 0x16, 0x7e, 0x90, 0xaf, 0x3d, 0x28, 0x63, 0x9d, 0x3f},
{0xd2, 0xc9, 0xf2, 0xe3, 0x0, 0x9b, 0xd2, 0xc, 0x5f, 0xaa, 0xce, 0x30, 0xb7, 0xd4, 0xc, 0x30, 0x74, 0x2a, 0x51, 0x16, 0xf2, 0xe0, 0x32, 0x98, 0xd, 0xeb, 0x30, 0xd8, 0xe3, 0xce, 0xf8, 0x9a},
{0x4b, 0xc5, 0x9e, 0x7b, 0xb5, 0xf1, 0x79, 0x92, 0xff, 0x51, 0xe6, 0x6e, 0x4, 0x86, 0x68, 0xd3, 0x9b, 0x23, 0x4d, 0x57, 0xe6, 0x96, 0x67, 0x31, 0xcc, 0xe6, 0xa6, 0xf3, 0x17, 0xa, 0x75, 0x5},
{0xb1, 0x76, 0x81, 0xd9, 0x13, 0x32, 0x6c, 0xce, 0x3c, 0x17, 0x52, 0x84, 0xf8, 0x5, 0xa2, 0x62, 0xf4, 0x2b, 0xcb, 0xb3, 0x78, 0x47, 0x15, 0x47, 0xff, 0x46, 0x54, 0x82, 0x23, 0x93, 0x6a, 0x48},
{0x38, 0xdf, 0x58, 0x7, 0x4e, 0x5e, 0x65, 0x65, 0xf2, 0xfc, 0x7c, 0x89, 0xfc, 0x86, 0x50, 0x8e, 0x31, 0x70, 0x2e, 0x44, 0xd0, 0xb, 0xca, 0x86, 0xf0, 0x40, 0x9, 0xa2, 0x30, 0x78, 0x47, 0x4e},
{0x65, 0xa0, 0xee, 0x39, 0xd1, 0xf7, 0x38, 0x83, 0xf7, 0x5e, 0xe9, 0x37, 0xe4, 0x2c, 0x3a, 0xbd, 0x21, 0x97, 0xb2, 0x26, 0x1, 0x13, 0xf8, 0x6f, 0xa3, 0x44, 0xed, 0xd1, 0xef, 0x9f, 0xde, 0xe7},
{0x8b, 0xa0, 0xdf, 0x15, 0x76, 0x25, 0x92, 0xd9, 0x3c, 0x85, 0xf7, 0xf6, 0x12, 0xdc, 0x42, 0xbe, 0xd8, 0xa7, 0xec, 0x7c, 0xab, 0x27, 0xb0, 0x7e, 0x53, 0x8d, 0x7d, 0xda, 0xaa, 0x3e, 0xa8, 0xde},
{0xaa, 0x25, 0xce, 0x93, 0xbd, 0x2, 0x69, 0xd8, 0x5a, 0xf6, 0x43, 0xfd, 0x1a, 0x73, 0x8, 0xf9, 0xc0, 0x5f, 0xef, 0xda, 0x17, 0x4a, 0x19, 0xa5, 0x97, 0x4d, 0x66, 0x33, 0x4c, 0xfd, 0x21, 0x6a},
{0x35, 0xb4, 0x98, 0x31, 0xdb, 0x41, 0x15, 0x70, 0xea, 0x1e, 0xf, 0xbb, 0xed, 0xcd, 0x54, 0x9b, 0x9a, 0xd0, 0x63, 0xa1, 0x51, 0x97, 0x40, 0x72, 0xf6, 0x75, 0x9d, 0xbf, 0x91, 0x47, 0x6f, 0xe2}
};
static void E8(hashState *state); /*The bijective function E8, in bitslice form*/
static void F8(hashState *state); /*The compression function F8 */
static void E8(hashState* state); /*The bijective function E8, in bitslice form*/
static void F8(hashState* state); /*The compression function F8 */
/*The API functions*/
static HashReturn Init(hashState *state, int hashbitlen);
static HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen);
static HashReturn Final(hashState *state, BitSequence *hashval);
HashReturn jh_hash(int hashbitlen, const BitSequence *data,DataLength databitlen, BitSequence *hashval);
static HashReturn Init(hashState* state, int hashbitlen);
static HashReturn Update(hashState* state, const BitSequence* data, DataLength databitlen);
static HashReturn Final(hashState* state, BitSequence* hashval);
HashReturn jh_hash(int hashbitlen, const BitSequence* data, DataLength databitlen, BitSequence* hashval);
/*swapping bit 2i with bit 2i+1 of 64-bit x*/
#define SWAP1(x) (x) = ((((x) & 0x5555555555555555ULL) << 1) | (((x) & 0xaaaaaaaaaaaaaaaaULL) >> 1));
@ -150,83 +155,139 @@ HashReturn jh_hash(int hashbitlen, const BitSequence *data,DataLength databitlen
m6 ^= temp1;
/*The bijective function E8, in bitslice form*/
static void E8(hashState *state)
static void E8(hashState* state)
{
uint64 i,roundnumber,temp0,temp1;
uint64 i, roundnumber, temp0, temp1;
for (roundnumber = 0; roundnumber < 42; roundnumber = roundnumber+7) {
for(roundnumber = 0; roundnumber < 42; roundnumber = roundnumber + 7)
{
/*round 7*roundnumber+0: Sbox, MDS and Swapping layers*/
for (i = 0; i < 2; i++) {
SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+0])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+0])[i+2] );
L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
SWAP1(state->x[1][i]); SWAP1(state->x[3][i]); SWAP1(state->x[5][i]); SWAP1(state->x[7][i]);
for(i = 0; i < 2; i++)
{
SS(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i],
state->x[5][i], state->x[7][i], ((uint64*)E8_bitslice_roundconstant[roundnumber + 0])[i],
((uint64*)E8_bitslice_roundconstant[roundnumber + 0])[i + 2]);
L(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i],
state->x[5][i], state->x[7][i]);
SWAP1(state->x[1][i]);
SWAP1(state->x[3][i]);
SWAP1(state->x[5][i]);
SWAP1(state->x[7][i]);
}
/*round 7*roundnumber+1: Sbox, MDS and Swapping layers*/
for (i = 0; i < 2; i++) {
SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+1])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+1])[i+2] );
L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
SWAP2(state->x[1][i]); SWAP2(state->x[3][i]); SWAP2(state->x[5][i]); SWAP2(state->x[7][i]);
for(i = 0; i < 2; i++)
{
SS(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i],
state->x[5][i], state->x[7][i], ((uint64*)E8_bitslice_roundconstant[roundnumber + 1])[i],
((uint64*)E8_bitslice_roundconstant[roundnumber + 1])[i + 2]);
L(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i],
state->x[5][i], state->x[7][i]);
SWAP2(state->x[1][i]);
SWAP2(state->x[3][i]);
SWAP2(state->x[5][i]);
SWAP2(state->x[7][i]);
}
/*round 7*roundnumber+2: Sbox, MDS and Swapping layers*/
for (i = 0; i < 2; i++) {
SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+2])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+2])[i+2] );
L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
SWAP4(state->x[1][i]); SWAP4(state->x[3][i]); SWAP4(state->x[5][i]); SWAP4(state->x[7][i]);
for(i = 0; i < 2; i++)
{
SS(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i],
state->x[5][i], state->x[7][i], ((uint64*)E8_bitslice_roundconstant[roundnumber + 2])[i],
((uint64*)E8_bitslice_roundconstant[roundnumber + 2])[i + 2]);
L(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i],
state->x[5][i], state->x[7][i]);
SWAP4(state->x[1][i]);
SWAP4(state->x[3][i]);
SWAP4(state->x[5][i]);
SWAP4(state->x[7][i]);
}
/*round 7*roundnumber+3: Sbox, MDS and Swapping layers*/
for (i = 0; i < 2; i++) {
SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+3])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+3])[i+2] );
L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
SWAP8(state->x[1][i]); SWAP8(state->x[3][i]); SWAP8(state->x[5][i]); SWAP8(state->x[7][i]);
for(i = 0; i < 2; i++)
{
SS(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i],
state->x[5][i], state->x[7][i], ((uint64*)E8_bitslice_roundconstant[roundnumber + 3])[i],
((uint64*)E8_bitslice_roundconstant[roundnumber + 3])[i + 2]);
L(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i],
state->x[5][i], state->x[7][i]);
SWAP8(state->x[1][i]);
SWAP8(state->x[3][i]);
SWAP8(state->x[5][i]);
SWAP8(state->x[7][i]);
}
/*round 7*roundnumber+4: Sbox, MDS and Swapping layers*/
for (i = 0; i < 2; i++) {
SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+4])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+4])[i+2] );
L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
SWAP16(state->x[1][i]); SWAP16(state->x[3][i]); SWAP16(state->x[5][i]); SWAP16(state->x[7][i]);
for(i = 0; i < 2; i++)
{
SS(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i],
state->x[5][i], state->x[7][i], ((uint64*)E8_bitslice_roundconstant[roundnumber + 4])[i],
((uint64*)E8_bitslice_roundconstant[roundnumber + 4])[i + 2]);
L(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i],
state->x[5][i], state->x[7][i]);
SWAP16(state->x[1][i]);
SWAP16(state->x[3][i]);
SWAP16(state->x[5][i]);
SWAP16(state->x[7][i]);
}
/*round 7*roundnumber+5: Sbox, MDS and Swapping layers*/
for (i = 0; i < 2; i++) {
SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+5])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+5])[i+2] );
L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
SWAP32(state->x[1][i]); SWAP32(state->x[3][i]); SWAP32(state->x[5][i]); SWAP32(state->x[7][i]);
for(i = 0; i < 2; i++)
{
SS(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i],
state->x[5][i], state->x[7][i], ((uint64*)E8_bitslice_roundconstant[roundnumber + 5])[i],
((uint64*)E8_bitslice_roundconstant[roundnumber + 5])[i + 2]);
L(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i],
state->x[5][i], state->x[7][i]);
SWAP32(state->x[1][i]);
SWAP32(state->x[3][i]);
SWAP32(state->x[5][i]);
SWAP32(state->x[7][i]);
}
/*round 7*roundnumber+6: Sbox and MDS layers*/
for (i = 0; i < 2; i++) {
SS(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i],((uint64*)E8_bitslice_roundconstant[roundnumber+6])[i],((uint64*)E8_bitslice_roundconstant[roundnumber+6])[i+2] );
L(state->x[0][i],state->x[2][i],state->x[4][i],state->x[6][i],state->x[1][i],state->x[3][i],state->x[5][i],state->x[7][i]);
for(i = 0; i < 2; i++)
{
SS(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i],
state->x[5][i], state->x[7][i], ((uint64*)E8_bitslice_roundconstant[roundnumber + 6])[i],
((uint64*)E8_bitslice_roundconstant[roundnumber + 6])[i + 2]);
L(state->x[0][i], state->x[2][i], state->x[4][i], state->x[6][i], state->x[1][i], state->x[3][i],
state->x[5][i], state->x[7][i]);
}
/*round 7*roundnumber+6: swapping layer*/
for (i = 1; i < 8; i = i+2) {
temp0 = state->x[i][0]; state->x[i][0] = state->x[i][1]; state->x[i][1] = temp0;
for(i = 1; i < 8; i = i + 2)
{
temp0 = state->x[i][0];
state->x[i][0] = state->x[i][1];
state->x[i][1] = temp0;
}
}
}
/*The compression function F8 */
static void F8(hashState *state)
static void F8(hashState* state)
{
uint64 i;
/*xor the 512-bit message with the fist half of the 1024-bit hash state*/
for (i = 0; i < 8; i++) state->x[i >> 1][i & 1] ^= ((uint64*)state->buffer)[i];
for(i = 0; i < 8; i++)
{
state->x[i >> 1][i & 1] ^= ((uint64*)state->buffer)[i];
}
/*the bijective function E8 */
E8(state);
/*xor the 512-bit message with the second half of the 1024-bit hash state*/
for (i = 0; i < 8; i++) state->x[(8+i) >> 1][(8+i) & 1] ^= ((uint64*)state->buffer)[i];
for(i = 0; i < 8; i++)
{
state->x[(8 + i) >> 1][(8 + i) & 1] ^= ((uint64*)state->buffer)[i];
}
}
/*before hashing a message, initialize the hash state as H0 */
static HashReturn Init(hashState *state, int hashbitlen)
static HashReturn Init(hashState* state, int hashbitlen)
{
state->databitlen = 0;
state->datasize_in_buffer = 0;
@ -235,12 +296,20 @@ static HashReturn Init(hashState *state, int hashbitlen)
state->hashbitlen = hashbitlen;
/*load the intital hash value into state*/
switch (hashbitlen)
switch(hashbitlen)
{
case 224: memcpy(state->x,JH224_H0,128); break;
case 256: memcpy(state->x,JH256_H0,128); break;
case 384: memcpy(state->x,JH384_H0,128); break;
case 512: memcpy(state->x,JH512_H0,128); break;
case 224:
memcpy(state->x, JH224_H0, 128);
break;
case 256:
memcpy(state->x, JH256_H0, 128);
break;
case 384:
memcpy(state->x, JH384_H0, 128);
break;
case 512:
memcpy(state->x, JH512_H0, 128);
break;
}
return(SUCCESS);
@ -248,7 +317,7 @@ static HashReturn Init(hashState *state, int hashbitlen)
/*hash each 512-bit message block, except the last partial block*/
static HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen)
static HashReturn Update(hashState* state, const BitSequence* data, DataLength databitlen)
{
DataLength index; /*the starting address of the data to be compressed*/
@ -259,36 +328,48 @@ static HashReturn Update(hashState *state, const BitSequence *data, DataLength d
/*we assume that the size of the data in the buffer is the multiple of 8 bits if it is not at the end of a message*/
/*There is data in the buffer, but the incoming data is insufficient for a full block*/
if ( (state->datasize_in_buffer > 0 ) && (( state->datasize_in_buffer + databitlen) < 512) ) {
if ( (databitlen & 7) == 0 ) {
memcpy(state->buffer + (state->datasize_in_buffer >> 3), data, 64-(state->datasize_in_buffer >> 3)) ;
if((state->datasize_in_buffer > 0) && ((state->datasize_in_buffer + databitlen) < 512))
{
if((databitlen & 7) == 0)
{
memcpy(state->buffer + (state->datasize_in_buffer >> 3), data, 64 - (state->datasize_in_buffer >> 3)) ;
}
else
{
memcpy(state->buffer + (state->datasize_in_buffer >> 3), data, 64 - (state->datasize_in_buffer >> 3) + 1) ;
}
else memcpy(state->buffer + (state->datasize_in_buffer >> 3), data, 64-(state->datasize_in_buffer >> 3)+1) ;
state->datasize_in_buffer += databitlen;
databitlen = 0;
}
/*There is data in the buffer, and the incoming data is sufficient for a full block*/
if ( (state->datasize_in_buffer > 0 ) && (( state->datasize_in_buffer + databitlen) >= 512) ) {
memcpy( state->buffer + (state->datasize_in_buffer >> 3), data, 64-(state->datasize_in_buffer >> 3) ) ;
index = 64-(state->datasize_in_buffer >> 3);
if((state->datasize_in_buffer > 0) && ((state->datasize_in_buffer + databitlen) >= 512))
{
memcpy(state->buffer + (state->datasize_in_buffer >> 3), data, 64 - (state->datasize_in_buffer >> 3)) ;
index = 64 - (state->datasize_in_buffer >> 3);
databitlen = databitlen - (512 - state->datasize_in_buffer);
F8(state);
state->datasize_in_buffer = 0;
}
/*hash the remaining full message blocks*/
for ( ; databitlen >= 512; index = index+64, databitlen = databitlen - 512) {
memcpy(state->buffer, data+index, 64);
for(; databitlen >= 512; index = index + 64, databitlen = databitlen - 512)
{
memcpy(state->buffer, data + index, 64);
F8(state);
}
/*store the partial block into buffer, assume that -- if part of the last byte is not part of the message, then that part consists of 0 bits*/
if ( databitlen > 0) {
if ((databitlen & 7) == 0)
memcpy(state->buffer, data+index, (databitlen & 0x1ff) >> 3);
if(databitlen > 0)
{
if((databitlen & 7) == 0)
{
memcpy(state->buffer, data + index, (databitlen & 0x1ff) >> 3);
}
else
memcpy(state->buffer, data+index, ((databitlen & 0x1ff) >> 3)+1);
{
memcpy(state->buffer, data + index, ((databitlen & 0x1ff) >> 3) + 1);
}
state->datasize_in_buffer = databitlen;
}
@ -296,11 +377,12 @@ static HashReturn Update(hashState *state, const BitSequence *data, DataLength d
}
/*pad the message, process the padded block(s), truncate the hash value H to obtain the message digest*/
static HashReturn Final(hashState *state, BitSequence *hashval)
static HashReturn Final(hashState* state, BitSequence* hashval)
{
unsigned int i;
if ( (state->databitlen & 0x1ff) == 0 ) {
if((state->databitlen & 0x1ff) == 0)
{
/*pad the message when databitlen is multiple of 512 bits, then process the padded block*/
memset(state->buffer, 0, 64);
state->buffer[0] = 0x80;
@ -314,15 +396,22 @@ static HashReturn Final(hashState *state, BitSequence *hashval)
state->buffer[56] = (state->databitlen >> 56) & 0xff;
F8(state);
}
else {
/*set the rest of the bytes in the buffer to 0*/
if ( (state->datasize_in_buffer & 7) == 0)
for (i = (state->databitlen & 0x1ff) >> 3; i < 64; i++) state->buffer[i] = 0;
else
for (i = ((state->databitlen & 0x1ff) >> 3)+1; i < 64; i++) state->buffer[i] = 0;
{
/*set the rest of the bytes in the buffer to 0*/
if((state->datasize_in_buffer & 7) == 0)
for(i = (state->databitlen & 0x1ff) >> 3; i < 64; i++)
{
state->buffer[i] = 0;
}
else
for(i = ((state->databitlen & 0x1ff) >> 3) + 1; i < 64; i++)
{
state->buffer[i] = 0;
}
/*pad and process the partial block when databitlen is not multiple of 512 bits, then hash the padded blocks*/
state->buffer[((state->databitlen & 0x1ff) >> 3)] |= 1 << (7- (state->databitlen & 7));
state->buffer[((state->databitlen & 0x1ff) >> 3)] |= 1 << (7 - (state->databitlen & 7));
F8(state);
memset(state->buffer, 0, 64);
@ -338,11 +427,20 @@ static HashReturn Final(hashState *state, BitSequence *hashval)
}
/*truncating the final hash value to generate the message digest*/
switch(state->hashbitlen) {
case 224: memcpy(hashval,(unsigned char*)state->x+64+36,28); break;
case 256: memcpy(hashval,(unsigned char*)state->x+64+32,32); break;
case 384: memcpy(hashval,(unsigned char*)state->x+64+16,48); break;
case 512: memcpy(hashval,(unsigned char*)state->x+64,64); break;
switch(state->hashbitlen)
{
case 224:
memcpy(hashval, (unsigned char*)state->x + 64 + 36, 28);
break;
case 256:
memcpy(hashval, (unsigned char*)state->x + 64 + 32, 32);
break;
case 384:
memcpy(hashval, (unsigned char*)state->x + 64 + 16, 48);
break;
case 512:
memcpy(hashval, (unsigned char*)state->x + 64, 64);
break;
}
return(SUCCESS);
@ -352,16 +450,19 @@ static HashReturn Final(hashState *state, BitSequence *hashval)
three inputs: message digest size in bits (hashbitlen); message (data); message length in bits (databitlen)
one output: message digest (hashval)
*/
HashReturn jh_hash(int hashbitlen, const BitSequence *data,DataLength databitlen, BitSequence *hashval)
HashReturn jh_hash(int hashbitlen, const BitSequence* data, DataLength databitlen, BitSequence* hashval)
{
hashState state;
if ( hashbitlen == 224 || hashbitlen == 256 || hashbitlen == 384 || hashbitlen == 512 ) {
if(hashbitlen == 224 || hashbitlen == 256 || hashbitlen == 384 || hashbitlen == 512)
{
Init(&state, hashbitlen);
Update(&state, data, databitlen);
Final(&state, hashval);
return SUCCESS;
}
else
{
return(BAD_HASHLEN);
}
}

View file

@ -16,4 +16,4 @@
#include "hash.h"
HashReturn jh_hash(int hashbitlen, const BitSequence *data, DataLength databitlen, BitSequence *hashval);
HashReturn jh_hash(int hashbitlen, const BitSequence* data, DataLength databitlen, BitSequence* hashval);

View file

@ -31,7 +31,8 @@ void keccakf(uint64_t st[25], int rounds)
int i, j, round;
uint64_t t, bc[5];
for (round = 0; round < rounds; ++round) {
for(round = 0; round < rounds; ++round)
{
// Theta
bc[0] = st[0] ^ st[5] ^ st[10] ^ st[15] ^ st[20];
@ -40,7 +41,8 @@ void keccakf(uint64_t st[25], int rounds)
bc[3] = st[3] ^ st[8] ^ st[13] ^ st[18] ^ st[23];
bc[4] = st[4] ^ st[9] ^ st[14] ^ st[19] ^ st[24];
for (i = 0; i < 5; ++i) {
for(i = 0; i < 5; ++i)
{
t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1);
st[i ] ^= t;
st[i + 5] ^= t;
@ -139,7 +141,7 @@ void keccakf(uint64_t st[25], int rounds)
// compute a keccak hash (md) of given byte length from "in"
typedef uint64_t state_t[25];
void keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen)
void keccak(const uint8_t* in, int inlen, uint8_t* md, int mdlen)
{
state_t st;
uint8_t temp[144];
@ -150,9 +152,12 @@ void keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen)
memset(st, 0, sizeof(st));
for ( ; inlen >= rsiz; inlen -= rsiz, in += rsiz) {
for (i = 0; i < rsizw; i++)
st[i] ^= ((uint64_t *) in)[i];
for(; inlen >= rsiz; inlen -= rsiz, in += rsiz)
{
for(i = 0; i < rsizw; i++)
{
st[i] ^= ((uint64_t*) in)[i];
}
keccakf(st, KECCAK_ROUNDS);
}
@ -162,15 +167,17 @@ void keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen)
memset(temp + inlen, 0, rsiz - inlen);
temp[rsiz - 1] |= 0x80;
for (i = 0; i < rsizw; i++)
st[i] ^= ((uint64_t *) temp)[i];
for(i = 0; i < rsizw; i++)
{
st[i] ^= ((uint64_t*) temp)[i];
}
keccakf(st, KECCAK_ROUNDS);
memcpy(md, st, mdlen);
}
void keccak1600(const uint8_t *in, int inlen, uint8_t *md)
void keccak1600(const uint8_t* in, int inlen, uint8_t* md)
{
keccak(in, inlen, md, sizeof(state_t));
}

View file

@ -16,11 +16,11 @@
#endif
// compute a keccak hash (md) of given byte length from "in"
int keccak(const uint8_t *in, int inlen, uint8_t *md, int mdlen);
int keccak(const uint8_t* in, int inlen, uint8_t* md, int mdlen);
// update the state
void keccakf(uint64_t st[25], int norounds);
void keccak1600(const uint8_t *in, int inlen, uint8_t *md);
void keccak1600(const uint8_t* in, int inlen, uint8_t* md);
#endif

View file

@ -47,9 +47,9 @@ typedef struct /* 512-bit Skein hash context stru
} Skein_512_Ctxt_t;
/* Skein APIs for (incremental) "straight hashing" */
static int Skein_512_Init (Skein_512_Ctxt_t *ctx, size_t hashBitLen);
static int Skein_512_Update(Skein_512_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt);
static int Skein_512_Final (Skein_512_Ctxt_t *ctx, u08b_t * hashVal);
static int Skein_512_Init(Skein_512_Ctxt_t* ctx, size_t hashBitLen);
static int Skein_512_Update(Skein_512_Ctxt_t* ctx, const u08b_t* msg, size_t msgByteCnt);
static int Skein_512_Final(Skein_512_Ctxt_t* ctx, u08b_t* hashVal);
#ifndef SKEIN_TREE_HASH
#define SKEIN_TREE_HASH (1)
@ -148,17 +148,17 @@ static int Skein_512_Final (Skein_512_Ctxt_t *ctx, u08b_t * hashVal);
/* set both tweak words at once */
#define Skein_Set_T0_T1(ctxPtr,T0,T1) \
{ \
{ \
Skein_Set_T0(ctxPtr,(T0)); \
Skein_Set_T1(ctxPtr,(T1)); \
}
}
#define Skein_Set_Type(ctxPtr,BLK_TYPE) \
Skein_Set_T1(ctxPtr,SKEIN_T1_BLK_TYPE_##BLK_TYPE)
/* set up for starting with a new type: h.T[0]=0; h.T[1] = NEW_TYPE; h.bCnt=0; */
#define Skein_Start_New_Type(ctxPtr,BLK_TYPE) \
{ Skein_Set_T0_T1(ctxPtr,0,SKEIN_T1_FLAG_FIRST | SKEIN_T1_BLK_TYPE_##BLK_TYPE); (ctxPtr)->h.bCnt=0; }
{ Skein_Set_T0_T1(ctxPtr,0,SKEIN_T1_FLAG_FIRST | SKEIN_T1_BLK_TYPE_##BLK_TYPE); (ctxPtr)->h.bCnt=0; }
#define Skein_Clear_First_Flag(hdr) { (hdr).T[1] &= ~SKEIN_T1_FLAG_FIRST; }
#define Skein_Set_Bit_Pad_Flag(hdr) { (hdr).T[1] |= SKEIN_T1_FLAG_BIT_PAD; }
@ -194,14 +194,14 @@ static int Skein_512_Final (Skein_512_Ctxt_t *ctx, u08b_t * hashVal);
enum
{
/* Skein_512 round rotation constants */
R_512_0_0=46, R_512_0_1=36, R_512_0_2=19, R_512_0_3=37,
R_512_1_0=33, R_512_1_1=27, R_512_1_2=14, R_512_1_3=42,
R_512_2_0=17, R_512_2_1=49, R_512_2_2=36, R_512_2_3=39,
R_512_3_0=44, R_512_3_1= 9, R_512_3_2=54, R_512_3_3=56,
R_512_4_0=39, R_512_4_1=30, R_512_4_2=34, R_512_4_3=24,
R_512_5_0=13, R_512_5_1=50, R_512_5_2=10, R_512_5_3=17,
R_512_6_0=25, R_512_6_1=29, R_512_6_2=39, R_512_6_3=43,
R_512_7_0= 8, R_512_7_1=35, R_512_7_2=56, R_512_7_3=22,
R_512_0_0 = 46, R_512_0_1 = 36, R_512_0_2 = 19, R_512_0_3 = 37,
R_512_1_0 = 33, R_512_1_1 = 27, R_512_1_2 = 14, R_512_1_3 = 42,
R_512_2_0 = 17, R_512_2_1 = 49, R_512_2_2 = 36, R_512_2_3 = 39,
R_512_3_0 = 44, R_512_3_1 = 9, R_512_3_2 = 54, R_512_3_3 = 56,
R_512_4_0 = 39, R_512_4_1 = 30, R_512_4_2 = 34, R_512_4_3 = 24,
R_512_5_0 = 13, R_512_5_1 = 50, R_512_5_2 = 10, R_512_5_3 = 17,
R_512_6_0 = 25, R_512_6_1 = 29, R_512_6_2 = 39, R_512_6_3 = 43,
R_512_7_0 = 8, R_512_7_1 = 35, R_512_7_2 = 56, R_512_7_3 = 22,
};
#ifndef SKEIN_ROUNDS
@ -229,16 +229,16 @@ enum
/* blkSize = 512 bits. hashSize = 256 bits */
const u64b_t SKEIN_512_IV_256[] =
{
MK_64(0xCCD044A1,0x2FDB3E13),
MK_64(0xE8359030,0x1A79A9EB),
MK_64(0x55AEA061,0x4F816E6F),
MK_64(0x2A2767A4,0xAE9B94DB),
MK_64(0xEC06025E,0x74DD7683),
MK_64(0xE7A436CD,0xC4746251),
MK_64(0xC36FBAF9,0x393AD185),
MK_64(0x3EEDBA18,0x33EDFC13)
};
{
MK_64(0xCCD044A1, 0x2FDB3E13),
MK_64(0xE8359030, 0x1A79A9EB),
MK_64(0x55AEA061, 0x4F816E6F),
MK_64(0x2A2767A4, 0xAE9B94DB),
MK_64(0xEC06025E, 0x74DD7683),
MK_64(0xE7A436CD, 0xC4746251),
MK_64(0xC36FBAF9, 0x393AD185),
MK_64(0x3EEDBA18, 0x33EDFC13)
};
#ifndef SKEIN_USE_ASM
#define SKEIN_USE_ASM (0) /* default is all C code (no ASM) */
@ -262,8 +262,10 @@ const u64b_t SKEIN_512_IV_256[] =
/***************************** Skein_512 ******************************/
#if !(SKEIN_USE_ASM & 512)
static void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,size_t blkCnt,size_t byteCntAdd)
{ /* do it in C */
static void Skein_512_Process_Block(Skein_512_Ctxt_t* ctx, const u08b_t* blkPtr, size_t blkCnt,
size_t byteCntAdd)
{
/* do it in C */
enum
{
WCNT = SKEIN_512_STATE_WORDS
@ -282,22 +284,29 @@ static void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,s
#error "Invalid SKEIN_UNROLL_512" /* sanity check on unroll count */
#endif
size_t r;
u64b_t kw[WCNT+4+RCNT*2]; /* key schedule words : chaining vars + tweak + "rotation"*/
u64b_t kw[WCNT + 4 + RCNT * 2]; /* key schedule words : chaining vars + tweak + "rotation"*/
#else
u64b_t kw[WCNT+4]; /* key schedule words : chaining vars + tweak */
u64b_t kw[WCNT + 4]; /* key schedule words : chaining vars + tweak */
#endif
u64b_t X0,X1,X2,X3,X4,X5,X6,X7; /* local copy of vars, for speed */
u64b_t X0, X1, X2, X3, X4, X5, X6, X7; /* local copy of vars, for speed */
u64b_t w [WCNT]; /* local copy of input block */
#ifdef SKEIN_DEBUG
const u64b_t *Xptr[8]; /* use for debugging (help compiler put Xn in registers) */
Xptr[0] = &X0; Xptr[1] = &X1; Xptr[2] = &X2; Xptr[3] = &X3;
Xptr[4] = &X4; Xptr[5] = &X5; Xptr[6] = &X6; Xptr[7] = &X7;
const u64b_t* Xptr[8]; /* use for debugging (help compiler put Xn in registers) */
Xptr[0] = &X0;
Xptr[1] = &X1;
Xptr[2] = &X2;
Xptr[3] = &X3;
Xptr[4] = &X4;
Xptr[5] = &X5;
Xptr[6] = &X6;
Xptr[7] = &X7;
#endif
Skein_assert(blkCnt != 0); /* never call with blkCnt == 0! */
ts[0] = ctx->h.T[0];
ts[1] = ctx->h.T[1];
do {
do
{
/* this implementation only supports 2**64 input bytes (no carry out here) */
ts[0] += byteCntAdd; /* update processed length */
@ -315,9 +324,9 @@ static void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,s
ts[2] = ts[0] ^ ts[1];
Skein_Get64_LSB_First(w,blkPtr,WCNT); /* get input block in little-endian format */
Skein_Get64_LSB_First(w, blkPtr, WCNT); /* get input block in little-endian format */
DebugSaveTweak(ctx);
Skein_Show_Block(BLK_BITS,&ctx->h,ctx->X,blkPtr,w,ks,ts);
Skein_Show_Block(BLK_BITS, &ctx->h, ctx->X, blkPtr, w, ks, ts);
X0 = w[0] + ks[0]; /* do the first full key injection */
X1 = w[1] + ks[1];
@ -330,7 +339,7 @@ static void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,s
blkPtr += SKEIN_512_BLOCK_BYTES;
Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INITIAL,Xptr);
Skein_Show_R_Ptr(BLK_BITS, &ctx->h, SKEIN_RND_KEY_INITIAL, Xptr);
/* run the rounds */
#define Round512(p0,p1,p2,p3,p4,p5,p6,p7,ROT,rNum) \
X##p0 += X##p1; X##p1 = RotL_64(X##p1,ROT##_0); X##p1 ^= X##p0; \
@ -371,7 +380,7 @@ static void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,s
ts[r + (R)+2] = ts[r+(R)-1]; \
Skein_Show_R_Ptr(BLK_BITS,&ctx->h,SKEIN_RND_KEY_INJECT,Xptr);
for (r=1;r < 2*RCNT;r+=2*SKEIN_UNROLL_512) /* loop thru it */
for(r = 1; r < 2 * RCNT; r += 2 * SKEIN_UNROLL_512) /* loop thru it */
#endif /* end of looped code definitions */
{
#define R512_8_rounds(R) /* do 8 full rounds */ \
@ -386,55 +395,55 @@ static void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,s
R512(6,1,0,7,2,5,4,3,R_512_7,8*(R)+ 8); \
I512(2*(R)+1); /* and key injection */
R512_8_rounds( 0);
R512_8_rounds(0);
#define R512_Unroll_R(NN) ((SKEIN_UNROLL_512 == 0 && SKEIN_512_ROUNDS_TOTAL/8 > (NN)) || (SKEIN_UNROLL_512 > (NN)))
#if R512_Unroll_R( 1)
R512_8_rounds( 1);
#endif
#if R512_Unroll_R( 2)
R512_8_rounds( 2);
#endif
#if R512_Unroll_R( 3)
R512_8_rounds( 3);
#endif
#if R512_Unroll_R( 4)
R512_8_rounds( 4);
#endif
#if R512_Unroll_R( 5)
R512_8_rounds( 5);
#endif
#if R512_Unroll_R( 6)
R512_8_rounds( 6);
#endif
#if R512_Unroll_R( 7)
R512_8_rounds( 7);
#endif
#if R512_Unroll_R( 8)
R512_8_rounds( 8);
#endif
#if R512_Unroll_R( 9)
R512_8_rounds( 9);
#endif
#if R512_Unroll_R(10)
#if R512_Unroll_R( 1)
R512_8_rounds(1);
#endif
#if R512_Unroll_R( 2)
R512_8_rounds(2);
#endif
#if R512_Unroll_R( 3)
R512_8_rounds(3);
#endif
#if R512_Unroll_R( 4)
R512_8_rounds(4);
#endif
#if R512_Unroll_R( 5)
R512_8_rounds(5);
#endif
#if R512_Unroll_R( 6)
R512_8_rounds(6);
#endif
#if R512_Unroll_R( 7)
R512_8_rounds(7);
#endif
#if R512_Unroll_R( 8)
R512_8_rounds(8);
#endif
#if R512_Unroll_R( 9)
R512_8_rounds(9);
#endif
#if R512_Unroll_R(10)
R512_8_rounds(10);
#endif
#if R512_Unroll_R(11)
#endif
#if R512_Unroll_R(11)
R512_8_rounds(11);
#endif
#if R512_Unroll_R(12)
#endif
#if R512_Unroll_R(12)
R512_8_rounds(12);
#endif
#if R512_Unroll_R(13)
#endif
#if R512_Unroll_R(13)
R512_8_rounds(13);
#endif
#if R512_Unroll_R(14)
#endif
#if R512_Unroll_R(14)
R512_8_rounds(14);
#endif
#if (SKEIN_UNROLL_512 > 14)
#endif
#if (SKEIN_UNROLL_512 > 14)
#error "need more unrolling in Skein_512_Process_Block"
#endif
#endif
}
/* do the final "feedforward" xor, update context chaining vars */
@ -446,14 +455,14 @@ static void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,s
ctx->X[5] = X5 ^ w[5];
ctx->X[6] = X6 ^ w[6];
ctx->X[7] = X7 ^ w[7];
Skein_Show_Round(BLK_BITS,&ctx->h,SKEIN_RND_FEED_FWD,ctx->X);
Skein_Show_Round(BLK_BITS, &ctx->h, SKEIN_RND_FEED_FWD, ctx->X);
ts[1] &= ~SKEIN_T1_FLAG_FIRST;
}
while (--blkCnt);
while(--blkCnt);
ctx->h.T[0] = ts[0];
ctx->h.T[1] = ts[1];
}
}
#endif
/*****************************************************************/
@ -462,76 +471,79 @@ static void Skein_512_Process_Block(Skein_512_Ctxt_t *ctx,const u08b_t *blkPtr,s
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/* init the context for a straight hashing operation */
static int Skein_512_Init(Skein_512_Ctxt_t *ctx, size_t hashBitLen)
{
static int Skein_512_Init(Skein_512_Ctxt_t* ctx, size_t hashBitLen)
{
union
{
u08b_t b[SKEIN_512_STATE_BYTES];
u64b_t w[SKEIN_512_STATE_WORDS];
} cfg; /* config block */
Skein_Assert(hashBitLen > 0,SKEIN_BAD_HASHLEN);
Skein_Assert(hashBitLen > 0, SKEIN_BAD_HASHLEN);
ctx->h.hashBitLen = hashBitLen; /* output hash bit count */
switch (hashBitLen)
{ /* use pre-computed values, where available */
switch(hashBitLen)
{
/* use pre-computed values, where available */
#ifndef SKEIN_NO_PRECOMP
case 256: memcpy(ctx->X,SKEIN_512_IV_256,sizeof(ctx->X)); break;
case 256:
memcpy(ctx->X, SKEIN_512_IV_256, sizeof(ctx->X));
break;
#endif
default:
/* here if there is no precomputed IV value available */
/* build/process the config block, type == CONFIG (could be precomputed) */
Skein_Start_New_Type(ctx,CFG_FINAL); /* set tweaks: T0=0; T1=CFG | FINAL */
Skein_Start_New_Type(ctx, CFG_FINAL); /* set tweaks: T0=0; T1=CFG | FINAL */
cfg.w[0] = Skein_Swap64(SKEIN_SCHEMA_VER); /* set the schema, version */
cfg.w[1] = Skein_Swap64(hashBitLen); /* hash result length in bits */
cfg.w[2] = Skein_Swap64(SKEIN_CFG_TREE_INFO_SEQUENTIAL);
memset(&cfg.w[3],0,sizeof(cfg) - 3*sizeof(cfg.w[0])); /* zero pad config block */
memset(&cfg.w[3], 0, sizeof(cfg) - 3 * sizeof(cfg.w[0])); /* zero pad config block */
/* compute the initial chaining values from config block */
memset(ctx->X,0,sizeof(ctx->X)); /* zero the chaining variables */
Skein_512_Process_Block(ctx,cfg.b,1,SKEIN_CFG_STR_LEN);
memset(ctx->X, 0, sizeof(ctx->X)); /* zero the chaining variables */
Skein_512_Process_Block(ctx, cfg.b, 1, SKEIN_CFG_STR_LEN);
break;
}
/* The chaining vars ctx->X are now initialized for the given hashBitLen. */
/* Set up to process the data message portion of the hash (default) */
Skein_Start_New_Type(ctx,MSG); /* T0=0, T1= MSG type */
Skein_Start_New_Type(ctx, MSG); /* T0=0, T1= MSG type */
return SKEIN_SUCCESS;
}
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/* process the input bytes */
static int Skein_512_Update(Skein_512_Ctxt_t *ctx, const u08b_t *msg, size_t msgByteCnt)
{
static int Skein_512_Update(Skein_512_Ctxt_t* ctx, const u08b_t* msg, size_t msgByteCnt)
{
size_t n;
Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL); /* catch uninitialized context */
/* process full blocks, if any */
if (msgByteCnt + ctx->h.bCnt > SKEIN_512_BLOCK_BYTES)
if(msgByteCnt + ctx->h.bCnt > SKEIN_512_BLOCK_BYTES)
{
if (ctx->h.bCnt) /* finish up any buffered message data */
if(ctx->h.bCnt) /* finish up any buffered message data */
{
n = SKEIN_512_BLOCK_BYTES - ctx->h.bCnt; /* # bytes free in buffer b[] */
if (n)
if(n)
{
Skein_assert(n < msgByteCnt); /* check on our logic here */
memcpy(&ctx->b[ctx->h.bCnt],msg,n);
memcpy(&ctx->b[ctx->h.bCnt], msg, n);
msgByteCnt -= n;
msg += n;
ctx->h.bCnt += n;
}
Skein_assert(ctx->h.bCnt == SKEIN_512_BLOCK_BYTES);
Skein_512_Process_Block(ctx,ctx->b,1,SKEIN_512_BLOCK_BYTES);
Skein_512_Process_Block(ctx, ctx->b, 1, SKEIN_512_BLOCK_BYTES);
ctx->h.bCnt = 0;
}
/* now process any remaining full blocks, directly from input message data */
if (msgByteCnt > SKEIN_512_BLOCK_BYTES)
if(msgByteCnt > SKEIN_512_BLOCK_BYTES)
{
n = (msgByteCnt-1) / SKEIN_512_BLOCK_BYTES; /* number of full blocks to process */
Skein_512_Process_Block(ctx,msg,n,SKEIN_512_BLOCK_BYTES);
n = (msgByteCnt - 1) / SKEIN_512_BLOCK_BYTES; /* number of full blocks to process */
Skein_512_Process_Block(ctx, msg, n, SKEIN_512_BLOCK_BYTES);
msgByteCnt -= n * SKEIN_512_BLOCK_BYTES;
msg += n * SKEIN_512_BLOCK_BYTES;
}
@ -539,57 +551,61 @@ static int Skein_512_Update(Skein_512_Ctxt_t *ctx, const u08b_t *msg, size_t msg
}
/* copy any remaining source message data bytes into b[] */
if (msgByteCnt)
if(msgByteCnt)
{
Skein_assert(msgByteCnt + ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES);
memcpy(&ctx->b[ctx->h.bCnt],msg,msgByteCnt);
memcpy(&ctx->b[ctx->h.bCnt], msg, msgByteCnt);
ctx->h.bCnt += msgByteCnt;
}
return SKEIN_SUCCESS;
}
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/* finalize the hash computation and output the result */
static int Skein_512_Final(Skein_512_Ctxt_t *ctx, u08b_t *hashVal)
{
size_t i,n,byteCnt;
static int Skein_512_Final(Skein_512_Ctxt_t* ctx, u08b_t* hashVal)
{
size_t i, n, byteCnt;
u64b_t X[SKEIN_512_STATE_WORDS];
Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES,SKEIN_FAIL); /* catch uninitialized context */
Skein_Assert(ctx->h.bCnt <= SKEIN_512_BLOCK_BYTES, SKEIN_FAIL); /* catch uninitialized context */
ctx->h.T[1] |= SKEIN_T1_FLAG_FINAL; /* tag as the final block */
if (ctx->h.bCnt < SKEIN_512_BLOCK_BYTES) /* zero pad b[] if necessary */
memset(&ctx->b[ctx->h.bCnt],0,SKEIN_512_BLOCK_BYTES - ctx->h.bCnt);
if(ctx->h.bCnt < SKEIN_512_BLOCK_BYTES) /* zero pad b[] if necessary */
{
memset(&ctx->b[ctx->h.bCnt], 0, SKEIN_512_BLOCK_BYTES - ctx->h.bCnt);
}
Skein_512_Process_Block(ctx,ctx->b,1,ctx->h.bCnt); /* process the final block */
Skein_512_Process_Block(ctx, ctx->b, 1, ctx->h.bCnt); /* process the final block */
/* now output the result */
byteCnt = (ctx->h.hashBitLen + 7) >> 3; /* total number of output bytes */
/* run Threefish in "counter mode" to generate output */
memset(ctx->b,0,sizeof(ctx->b)); /* zero out b[], so it can hold the counter */
memcpy(X,ctx->X,sizeof(X)); /* keep a local copy of counter mode "key" */
for (i=0;i*SKEIN_512_BLOCK_BYTES < byteCnt;i++)
memset(ctx->b, 0, sizeof(ctx->b)); /* zero out b[], so it can hold the counter */
memcpy(X, ctx->X, sizeof(X)); /* keep a local copy of counter mode "key" */
for(i = 0; i * SKEIN_512_BLOCK_BYTES < byteCnt; i++)
{
((u64b_t*)ctx->b)[0] = Skein_Swap64((u64b_t) i); /* build the counter block */
Skein_Start_New_Type(ctx, OUT_FINAL);
Skein_512_Process_Block(ctx, ctx->b, 1, sizeof(u64b_t)); /* run "counter mode" */
n = byteCnt - i * SKEIN_512_BLOCK_BYTES; /* number of output bytes left to go */
if(n >= SKEIN_512_BLOCK_BYTES)
{
((u64b_t *)ctx->b)[0]= Skein_Swap64((u64b_t) i); /* build the counter block */
Skein_Start_New_Type(ctx,OUT_FINAL);
Skein_512_Process_Block(ctx,ctx->b,1,sizeof(u64b_t)); /* run "counter mode" */
n = byteCnt - i*SKEIN_512_BLOCK_BYTES; /* number of output bytes left to go */
if (n >= SKEIN_512_BLOCK_BYTES)
n = SKEIN_512_BLOCK_BYTES;
Skein_Put64_LSB_First(hashVal+i*SKEIN_512_BLOCK_BYTES,ctx->X,n); /* "output" the ctr mode bytes */
Skein_Show_Final(512,&ctx->h,n,hashVal+i*SKEIN_512_BLOCK_BYTES);
memcpy(ctx->X,X,sizeof(X)); /* restore the counter mode key for next time */
}
Skein_Put64_LSB_First(hashVal + i * SKEIN_512_BLOCK_BYTES, ctx->X, n); /* "output" the ctr mode bytes */
Skein_Show_Final(512, &ctx->h, n, hashVal + i * SKEIN_512_BLOCK_BYTES);
memcpy(ctx->X, X, sizeof(X)); /* restore the counter mode key for next time */
}
return SKEIN_SUCCESS;
}
}
#if defined(SKEIN_CODE_SIZE) || defined(SKEIN_PERF)
static size_t Skein_512_API_CodeSize(void)
{
return ((u08b_t *) Skein_512_API_CodeSize) -
((u08b_t *) Skein_512_Init);
}
{
return ((u08b_t*) Skein_512_API_CodeSize) -
((u08b_t*) Skein_512_Init);
}
#endif
typedef struct
@ -604,40 +620,41 @@ typedef struct
hashState;
/* "incremental" hashing API */
static SkeinHashReturn Init (hashState *state, int hashbitlen);
static SkeinHashReturn Update(hashState *state, const SkeinBitSequence *data, SkeinDataLength databitlen);
static SkeinHashReturn Final (hashState *state, SkeinBitSequence *hashval);
static SkeinHashReturn Init(hashState* state, int hashbitlen);
static SkeinHashReturn Update(hashState* state, const SkeinBitSequence* data, SkeinDataLength databitlen);
static SkeinHashReturn Final(hashState* state, SkeinBitSequence* hashval);
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/* select the context size and init the context */
static SkeinHashReturn Init(hashState *state, int hashbitlen)
static SkeinHashReturn Init(hashState* state, int hashbitlen)
{
state->statebits = 64*SKEIN_512_STATE_WORDS;
return Skein_512_Init(&state->u.ctx_512,(size_t) hashbitlen);
state->statebits = 64 * SKEIN_512_STATE_WORDS;
return Skein_512_Init(&state->u.ctx_512, (size_t) hashbitlen);
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/* process data to be hashed */
static SkeinHashReturn Update(hashState *state, const SkeinBitSequence *data, SkeinDataLength databitlen)
static SkeinHashReturn Update(hashState* state, const SkeinBitSequence* data, SkeinDataLength databitlen)
{
/* only the final Update() call is allowed do partial bytes, else assert an error */
Skein_Assert((state->u.h.T[1] & SKEIN_T1_FLAG_BIT_PAD) == 0 || databitlen == 0, SKEIN_FAIL);
Skein_Assert(state->statebits % 256 == 0 && (state->statebits-256) < 1024,SKEIN_FAIL);
if ((databitlen & 7) == 0) /* partial bytes? */
Skein_Assert(state->statebits % 256 == 0 && (state->statebits - 256) < 1024, SKEIN_FAIL);
if((databitlen & 7) == 0) /* partial bytes? */
{
return Skein_512_Update(&state->u.ctx_512,data,databitlen >> 3);
return Skein_512_Update(&state->u.ctx_512, data, databitlen >> 3);
}
else
{ /* handle partial final byte */
{
/* handle partial final byte */
size_t bCnt = (databitlen >> 3) + 1; /* number of bytes to handle (nonzero here!) */
u08b_t b,mask;
u08b_t b, mask;
mask = (u08b_t) (1u << (7 - (databitlen & 7))); /* partial byte bit mask */
b = (u08b_t) ((data[bCnt-1] & (0-mask)) | mask); /* apply bit padding on final byte */
mask = (u08b_t)(1u << (7 - (databitlen & 7))); /* partial byte bit mask */
b = (u08b_t)((data[bCnt - 1] & (0 - mask)) | mask); /* apply bit padding on final byte */
Skein_512_Update(&state->u.ctx_512,data,bCnt-1); /* process all but the final byte */
Skein_512_Update(&state->u.ctx_512,&b , 1 ); /* process the (masked) partial byte */
Skein_512_Update(&state->u.ctx_512, data, bCnt - 1); /* process all but the final byte */
Skein_512_Update(&state->u.ctx_512, &b , 1); /* process the (masked) partial byte */
Skein_Set_Bit_Pad_Flag(state->u.h); /* set tweak flag for the final call */
return SKEIN_SUCCESS;
@ -646,54 +663,58 @@ static SkeinHashReturn Update(hashState *state, const SkeinBitSequence *data, Sk
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/* finalize hash computation and output the result (hashbitlen bits) */
static SkeinHashReturn Final(hashState *state, SkeinBitSequence *hashval)
static SkeinHashReturn Final(hashState* state, SkeinBitSequence* hashval)
{
Skein_Assert(state->statebits % 256 == 0 && (state->statebits-256) < 1024,FAIL);
return Skein_512_Final(&state->u.ctx_512,hashval);
Skein_Assert(state->statebits % 256 == 0 && (state->statebits - 256) < 1024, FAIL);
return Skein_512_Final(&state->u.ctx_512, hashval);
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
/* all-in-one hash function */
SkeinHashReturn skein_hash(int hashbitlen, const SkeinBitSequence *data, /* all-in-one call */
SkeinDataLength databitlen,SkeinBitSequence *hashval)
SkeinHashReturn skein_hash(int hashbitlen, const SkeinBitSequence* data, /* all-in-one call */
SkeinDataLength databitlen, SkeinBitSequence* hashval)
{
hashState state;
SkeinHashReturn r = Init(&state,hashbitlen);
if (r == SKEIN_SUCCESS)
{ /* these calls do not fail when called properly */
r = Update(&state,data,databitlen);
Final(&state,hashval);
SkeinHashReturn r = Init(&state, hashbitlen);
if(r == SKEIN_SUCCESS)
{
/* these calls do not fail when called properly */
r = Update(&state, data, databitlen);
Final(&state, hashval);
}
return r;
}
void xmr_skein(const SkeinBitSequence *data, SkeinBitSequence *hashval){
#define XMR_HASHBITLEN 256
#define XMR_DATABITLEN 1600
void xmr_skein(const SkeinBitSequence* data, SkeinBitSequence* hashval)
{
#define XMR_HASHBITLEN 256
#define XMR_DATABITLEN 1600
// Init
hashState state;
state.statebits = 64*SKEIN_512_STATE_WORDS;
state.statebits = 64 * SKEIN_512_STATE_WORDS;
// Skein_512_Init(&state.u.ctx_512, (size_t)XMR_HASHBITLEN);
state.u.ctx_512.h.hashBitLen = XMR_HASHBITLEN;
memcpy(state.u.ctx_512.X,SKEIN_512_IV_256,sizeof(state.u.ctx_512.X));
Skein_512_Ctxt_t* ctx = &(state.u.ctx_512);
Skein_Start_New_Type(ctx,MSG);
memcpy(state.u.ctx_512.X, SKEIN_512_IV_256, sizeof(state.u.ctx_512.X));
Skein_Start_New_Type(&state.u.ctx_512, MSG);
// Update
if ((XMR_DATABITLEN & 7) == 0){ /* partial bytes? */
Skein_512_Update(&state.u.ctx_512,data,XMR_DATABITLEN >> 3);
}else{ /* handle partial final byte */
size_t bCnt = (XMR_DATABITLEN >> 3) + 1; /* number of bytes to handle (nonzero here!) */
u08b_t b,mask;
if((XMR_DATABITLEN & 7) == 0) // partial bytes?
{
Skein_512_Update(&state.u.ctx_512, data, XMR_DATABITLEN >> 3);
}
else // handle partial final byte
{
size_t bCnt = (XMR_DATABITLEN >> 3) + 1; // number of bytes to handle (nonzero here!)
u08b_t b, mask;
mask = (u08b_t) (1u << (7 - (XMR_DATABITLEN & 7))); /* partial byte bit mask */
b = (u08b_t) ((data[bCnt-1] & (0-mask)) | mask); /* apply bit padding on final byte */
mask = (u08b_t)(1u << (7 - (XMR_DATABITLEN & 7))); // partial byte bit mask
b = (u08b_t)((data[bCnt - 1] & (0 - mask)) | mask); // apply bit padding on final byte
Skein_512_Update(&state.u.ctx_512,data,bCnt-1); /* process all but the final byte */
Skein_512_Update(&state.u.ctx_512,&b , 1 ); /* process the (masked) partial byte */
Skein_Set_Bit_Pad_Flag(state.u.h); /* set tweak flag for the final call */
Skein_512_Update(&state.u.ctx_512, data, bCnt - 1); // process all but the final byte
Skein_512_Update(&state.u.ctx_512, &b , 1); //process the (masked) partial byte
Skein_Set_Bit_Pad_Flag(state.u.h); // set tweak flag for the final call
}
// Finalize

View file

@ -41,9 +41,9 @@ typedef size_t SkeinDataLength; /* bit count type */
typedef u08b_t SkeinBitSequence; /* bit stream type */
/* "all-in-one" call */
SkeinHashReturn skein_hash(int hashbitlen, const SkeinBitSequence *data,
SkeinDataLength databitlen, SkeinBitSequence *hashval);
SkeinHashReturn skein_hash(int hashbitlen, const SkeinBitSequence* data,
SkeinDataLength databitlen, SkeinBitSequence* hashval);
void xmr_skein(const SkeinBitSequence *data, SkeinBitSequence *hashval);
void xmr_skein(const SkeinBitSequence* data, SkeinBitSequence* hashval);
#endif /* ifndef _SKEIN_H_ */

View file

@ -3,36 +3,37 @@
const uint32_t T[512] = {0xa5f432c6, 0xc6a597f4, 0x84976ff8, 0xf884eb97, 0x99b05eee, 0xee99c7b0, 0x8d8c7af6, 0xf68df78c, 0xd17e8ff, 0xff0de517, 0xbddc0ad6, 0xd6bdb7dc, 0xb1c816de, 0xdeb1a7c8, 0x54fc6d91, 0x915439fc
, 0x50f09060, 0x6050c0f0, 0x3050702, 0x2030405, 0xa9e02ece, 0xcea987e0, 0x7d87d156, 0x567dac87, 0x192bcce7, 0xe719d52b, 0x62a613b5, 0xb56271a6, 0xe6317c4d, 0x4de69a31, 0x9ab559ec, 0xec9ac3b5
, 0x45cf408f, 0x8f4505cf, 0x9dbca31f, 0x1f9d3ebc, 0x40c04989, 0x894009c0, 0x879268fa, 0xfa87ef92, 0x153fd0ef, 0xef15c53f, 0xeb2694b2, 0xb2eb7f26, 0xc940ce8e, 0x8ec90740, 0xb1de6fb, 0xfb0bed1d
, 0xec2f6e41, 0x41ec822f, 0x67a91ab3, 0xb3677da9, 0xfd1c435f, 0x5ffdbe1c, 0xea256045, 0x45ea8a25, 0xbfdaf923, 0x23bf46da, 0xf7025153, 0x53f7a602, 0x96a145e4, 0xe496d3a1, 0x5bed769b, 0x9b5b2ded
, 0xc25d2875, 0x75c2ea5d, 0x1c24c5e1, 0xe11cd924, 0xaee9d43d, 0x3dae7ae9, 0x6abef24c, 0x4c6a98be, 0x5aee826c, 0x6c5ad8ee, 0x41c3bd7e, 0x7e41fcc3, 0x206f3f5, 0xf502f106, 0x4fd15283, 0x834f1dd1
, 0x5ce48c68, 0x685cd0e4, 0xf4075651, 0x51f4a207, 0x345c8dd1, 0xd134b95c, 0x818e1f9, 0xf908e918, 0x93ae4ce2, 0xe293dfae, 0x73953eab, 0xab734d95, 0x53f59762, 0x6253c4f5, 0x3f416b2a, 0x2a3f5441
, 0xc141c08, 0x80c1014, 0x52f66395, 0x955231f6, 0x65afe946, 0x46658caf, 0x5ee27f9d, 0x9d5e21e2, 0x28784830, 0x30286078, 0xa1f8cf37, 0x37a16ef8, 0xf111b0a, 0xa0f1411, 0xb5c4eb2f, 0x2fb55ec4
, 0x91b150e, 0xe091c1b, 0x365a7e24, 0x2436485a, 0x9bb6ad1b, 0x1b9b36b6, 0x3d4798df, 0xdf3da547, 0x266aa7cd, 0xcd26816a, 0x69bbf54e, 0x4e699cbb, 0xcd4c337f, 0x7fcdfe4c, 0x9fba50ea, 0xea9fcfba
, 0x1b2d3f12, 0x121b242d, 0x9eb9a41d, 0x1d9e3ab9, 0x749cc458, 0x5874b09c, 0x2e724634, 0x342e6872, 0x2d774136, 0x362d6c77, 0xb2cd11dc, 0xdcb2a3cd, 0xee299db4, 0xb4ee7329, 0xfb164d5b, 0x5bfbb616
, 0xf601a5a4, 0xa4f65301, 0x4dd7a176, 0x764decd7, 0x61a314b7, 0xb76175a3, 0xce49347d, 0x7dcefa49, 0x7b8ddf52, 0x527ba48d, 0x3e429fdd, 0xdd3ea142, 0x7193cd5e, 0x5e71bc93, 0x97a2b113, 0x139726a2
, 0xf504a2a6, 0xa6f55704, 0x68b801b9, 0xb96869b8, 0x0, 0x0, 0x2c74b5c1, 0xc12c9974, 0x60a0e040, 0x406080a0, 0x1f21c2e3, 0xe31fdd21, 0xc8433a79, 0x79c8f243, 0xed2c9ab6, 0xb6ed772c
, 0xbed90dd4, 0xd4beb3d9, 0x46ca478d, 0x8d4601ca, 0xd9701767, 0x67d9ce70, 0x4bddaf72, 0x724be4dd, 0xde79ed94, 0x94de3379, 0xd467ff98, 0x98d42b67, 0xe82393b0, 0xb0e87b23, 0x4ade5b85, 0x854a11de
, 0x6bbd06bb, 0xbb6b6dbd, 0x2a7ebbc5, 0xc52a917e, 0xe5347b4f, 0x4fe59e34, 0x163ad7ed, 0xed16c13a, 0xc554d286, 0x86c51754, 0xd762f89a, 0x9ad72f62, 0x55ff9966, 0x6655ccff, 0x94a7b611, 0x119422a7
, 0xcf4ac08a, 0x8acf0f4a, 0x1030d9e9, 0xe910c930, 0x60a0e04, 0x406080a, 0x819866fe, 0xfe81e798, 0xf00baba0, 0xa0f05b0b, 0x44ccb478, 0x7844f0cc, 0xbad5f025, 0x25ba4ad5, 0xe33e754b, 0x4be3963e
, 0xf30eaca2, 0xa2f35f0e, 0xfe19445d, 0x5dfeba19, 0xc05bdb80, 0x80c01b5b, 0x8a858005, 0x58a0a85, 0xadecd33f, 0x3fad7eec, 0xbcdffe21, 0x21bc42df, 0x48d8a870, 0x7048e0d8, 0x40cfdf1, 0xf104f90c
, 0xdf7a1963, 0x63dfc67a, 0xc1582f77, 0x77c1ee58, 0x759f30af, 0xaf75459f, 0x63a5e742, 0x426384a5, 0x30507020, 0x20304050, 0x1a2ecbe5, 0xe51ad12e, 0xe12effd, 0xfd0ee112, 0x6db708bf, 0xbf6d65b7
, 0x4cd45581, 0x814c19d4, 0x143c2418, 0x1814303c, 0x355f7926, 0x26354c5f, 0x2f71b2c3, 0xc32f9d71, 0xe13886be, 0xbee16738, 0xa2fdc835, 0x35a26afd, 0xcc4fc788, 0x88cc0b4f, 0x394b652e, 0x2e395c4b
, 0x57f96a93, 0x93573df9, 0xf20d5855, 0x55f2aa0d, 0x829d61fc, 0xfc82e39d, 0x47c9b37a, 0x7a47f4c9, 0xacef27c8, 0xc8ac8bef, 0xe73288ba, 0xbae76f32, 0x2b7d4f32, 0x322b647d, 0x95a442e6, 0xe695d7a4
, 0xa0fb3bc0, 0xc0a09bfb, 0x98b3aa19, 0x199832b3, 0xd168f69e, 0x9ed12768, 0x7f8122a3, 0xa37f5d81, 0x66aaee44, 0x446688aa, 0x7e82d654, 0x547ea882, 0xabe6dd3b, 0x3bab76e6, 0x839e950b, 0xb83169e
, 0xca45c98c, 0x8cca0345, 0x297bbcc7, 0xc729957b, 0xd36e056b, 0x6bd3d66e, 0x3c446c28, 0x283c5044, 0x798b2ca7, 0xa779558b, 0xe23d81bc, 0xbce2633d, 0x1d273116, 0x161d2c27, 0x769a37ad, 0xad76419a
, 0x3b4d96db, 0xdb3bad4d, 0x56fa9e64, 0x6456c8fa, 0x4ed2a674, 0x744ee8d2, 0x1e223614, 0x141e2822, 0xdb76e492, 0x92db3f76, 0xa1e120c, 0xc0a181e, 0x6cb4fc48, 0x486c90b4, 0xe4378fb8, 0xb8e46b37
, 0x5de7789f, 0x9f5d25e7, 0x6eb20fbd, 0xbd6e61b2, 0xef2a6943, 0x43ef862a, 0xa6f135c4, 0xc4a693f1, 0xa8e3da39, 0x39a872e3, 0xa4f7c631, 0x31a462f7, 0x37598ad3, 0xd337bd59, 0x8b8674f2, 0xf28bff86
, 0x325683d5, 0xd532b156, 0x43c54e8b, 0x8b430dc5, 0x59eb856e, 0x6e59dceb, 0xb7c218da, 0xdab7afc2, 0x8c8f8e01, 0x18c028f, 0x64ac1db1, 0xb16479ac, 0xd26df19c, 0x9cd2236d, 0xe03b7249, 0x49e0923b
, 0xb4c71fd8, 0xd8b4abc7, 0xfa15b9ac, 0xacfa4315, 0x709faf3, 0xf307fd09, 0x256fa0cf, 0xcf25856f, 0xafea20ca, 0xcaaf8fea, 0x8e897df4, 0xf48ef389, 0xe9206747, 0x47e98e20, 0x18283810, 0x10182028
, 0xd5640b6f, 0x6fd5de64, 0x888373f0, 0xf088fb83, 0x6fb1fb4a, 0x4a6f94b1, 0x7296ca5c, 0x5c72b896, 0x246c5438, 0x3824706c, 0xf1085f57, 0x57f1ae08, 0xc7522173, 0x73c7e652, 0x51f36497, 0x975135f3
, 0x2365aecb, 0xcb238d65, 0x7c8425a1, 0xa17c5984, 0x9cbf57e8, 0xe89ccbbf, 0x21635d3e, 0x3e217c63, 0xdd7cea96, 0x96dd377c, 0xdc7f1e61, 0x61dcc27f, 0x86919c0d, 0xd861a91, 0x85949b0f, 0xf851e94
, 0x90ab4be0, 0xe090dbab, 0x42c6ba7c, 0x7c42f8c6, 0xc4572671, 0x71c4e257, 0xaae529cc, 0xccaa83e5, 0xd873e390, 0x90d83b73, 0x50f0906, 0x6050c0f, 0x103f4f7, 0xf701f503, 0x12362a1c, 0x1c123836
, 0xa3fe3cc2, 0xc2a39ffe, 0x5fe18b6a, 0x6a5fd4e1, 0xf910beae, 0xaef94710, 0xd06b0269, 0x69d0d26b, 0x91a8bf17, 0x17912ea8, 0x58e87199, 0x995829e8, 0x2769533a, 0x3a277469, 0xb9d0f727, 0x27b94ed0
, 0x384891d9, 0xd938a948, 0x1335deeb, 0xeb13cd35, 0xb3cee52b, 0x2bb356ce, 0x33557722, 0x22334455, 0xbbd604d2, 0xd2bbbfd6, 0x709039a9, 0xa9704990, 0x89808707, 0x7890e80, 0xa7f2c133, 0x33a766f2
, 0xb6c1ec2d, 0x2db65ac1, 0x22665a3c, 0x3c227866, 0x92adb815, 0x15922aad, 0x2060a9c9, 0xc9208960, 0x49db5c87, 0x874915db, 0xff1ab0aa, 0xaaff4f1a, 0x7888d850, 0x5078a088, 0x7a8e2ba5, 0xa57a518e
, 0x8f8a8903, 0x38f068a, 0xf8134a59, 0x59f8b213, 0x809b9209, 0x980129b, 0x1739231a, 0x1a173439, 0xda751065, 0x65daca75, 0x315384d7, 0xd731b553, 0xc651d584, 0x84c61351, 0xb8d303d0, 0xd0b8bbd3
, 0xc35edc82, 0x82c31f5e, 0xb0cbe229, 0x29b052cb, 0x7799c35a, 0x5a77b499, 0x11332d1e, 0x1e113c33, 0xcb463d7b, 0x7bcbf646, 0xfc1fb7a8, 0xa8fc4b1f, 0xd6610c6d, 0x6dd6da61, 0x3a4e622c, 0x2c3a584e};
, 0x50f09060, 0x6050c0f0, 0x3050702, 0x2030405, 0xa9e02ece, 0xcea987e0, 0x7d87d156, 0x567dac87, 0x192bcce7, 0xe719d52b, 0x62a613b5, 0xb56271a6, 0xe6317c4d, 0x4de69a31, 0x9ab559ec, 0xec9ac3b5
, 0x45cf408f, 0x8f4505cf, 0x9dbca31f, 0x1f9d3ebc, 0x40c04989, 0x894009c0, 0x879268fa, 0xfa87ef92, 0x153fd0ef, 0xef15c53f, 0xeb2694b2, 0xb2eb7f26, 0xc940ce8e, 0x8ec90740, 0xb1de6fb, 0xfb0bed1d
, 0xec2f6e41, 0x41ec822f, 0x67a91ab3, 0xb3677da9, 0xfd1c435f, 0x5ffdbe1c, 0xea256045, 0x45ea8a25, 0xbfdaf923, 0x23bf46da, 0xf7025153, 0x53f7a602, 0x96a145e4, 0xe496d3a1, 0x5bed769b, 0x9b5b2ded
, 0xc25d2875, 0x75c2ea5d, 0x1c24c5e1, 0xe11cd924, 0xaee9d43d, 0x3dae7ae9, 0x6abef24c, 0x4c6a98be, 0x5aee826c, 0x6c5ad8ee, 0x41c3bd7e, 0x7e41fcc3, 0x206f3f5, 0xf502f106, 0x4fd15283, 0x834f1dd1
, 0x5ce48c68, 0x685cd0e4, 0xf4075651, 0x51f4a207, 0x345c8dd1, 0xd134b95c, 0x818e1f9, 0xf908e918, 0x93ae4ce2, 0xe293dfae, 0x73953eab, 0xab734d95, 0x53f59762, 0x6253c4f5, 0x3f416b2a, 0x2a3f5441
, 0xc141c08, 0x80c1014, 0x52f66395, 0x955231f6, 0x65afe946, 0x46658caf, 0x5ee27f9d, 0x9d5e21e2, 0x28784830, 0x30286078, 0xa1f8cf37, 0x37a16ef8, 0xf111b0a, 0xa0f1411, 0xb5c4eb2f, 0x2fb55ec4
, 0x91b150e, 0xe091c1b, 0x365a7e24, 0x2436485a, 0x9bb6ad1b, 0x1b9b36b6, 0x3d4798df, 0xdf3da547, 0x266aa7cd, 0xcd26816a, 0x69bbf54e, 0x4e699cbb, 0xcd4c337f, 0x7fcdfe4c, 0x9fba50ea, 0xea9fcfba
, 0x1b2d3f12, 0x121b242d, 0x9eb9a41d, 0x1d9e3ab9, 0x749cc458, 0x5874b09c, 0x2e724634, 0x342e6872, 0x2d774136, 0x362d6c77, 0xb2cd11dc, 0xdcb2a3cd, 0xee299db4, 0xb4ee7329, 0xfb164d5b, 0x5bfbb616
, 0xf601a5a4, 0xa4f65301, 0x4dd7a176, 0x764decd7, 0x61a314b7, 0xb76175a3, 0xce49347d, 0x7dcefa49, 0x7b8ddf52, 0x527ba48d, 0x3e429fdd, 0xdd3ea142, 0x7193cd5e, 0x5e71bc93, 0x97a2b113, 0x139726a2
, 0xf504a2a6, 0xa6f55704, 0x68b801b9, 0xb96869b8, 0x0, 0x0, 0x2c74b5c1, 0xc12c9974, 0x60a0e040, 0x406080a0, 0x1f21c2e3, 0xe31fdd21, 0xc8433a79, 0x79c8f243, 0xed2c9ab6, 0xb6ed772c
, 0xbed90dd4, 0xd4beb3d9, 0x46ca478d, 0x8d4601ca, 0xd9701767, 0x67d9ce70, 0x4bddaf72, 0x724be4dd, 0xde79ed94, 0x94de3379, 0xd467ff98, 0x98d42b67, 0xe82393b0, 0xb0e87b23, 0x4ade5b85, 0x854a11de
, 0x6bbd06bb, 0xbb6b6dbd, 0x2a7ebbc5, 0xc52a917e, 0xe5347b4f, 0x4fe59e34, 0x163ad7ed, 0xed16c13a, 0xc554d286, 0x86c51754, 0xd762f89a, 0x9ad72f62, 0x55ff9966, 0x6655ccff, 0x94a7b611, 0x119422a7
, 0xcf4ac08a, 0x8acf0f4a, 0x1030d9e9, 0xe910c930, 0x60a0e04, 0x406080a, 0x819866fe, 0xfe81e798, 0xf00baba0, 0xa0f05b0b, 0x44ccb478, 0x7844f0cc, 0xbad5f025, 0x25ba4ad5, 0xe33e754b, 0x4be3963e
, 0xf30eaca2, 0xa2f35f0e, 0xfe19445d, 0x5dfeba19, 0xc05bdb80, 0x80c01b5b, 0x8a858005, 0x58a0a85, 0xadecd33f, 0x3fad7eec, 0xbcdffe21, 0x21bc42df, 0x48d8a870, 0x7048e0d8, 0x40cfdf1, 0xf104f90c
, 0xdf7a1963, 0x63dfc67a, 0xc1582f77, 0x77c1ee58, 0x759f30af, 0xaf75459f, 0x63a5e742, 0x426384a5, 0x30507020, 0x20304050, 0x1a2ecbe5, 0xe51ad12e, 0xe12effd, 0xfd0ee112, 0x6db708bf, 0xbf6d65b7
, 0x4cd45581, 0x814c19d4, 0x143c2418, 0x1814303c, 0x355f7926, 0x26354c5f, 0x2f71b2c3, 0xc32f9d71, 0xe13886be, 0xbee16738, 0xa2fdc835, 0x35a26afd, 0xcc4fc788, 0x88cc0b4f, 0x394b652e, 0x2e395c4b
, 0x57f96a93, 0x93573df9, 0xf20d5855, 0x55f2aa0d, 0x829d61fc, 0xfc82e39d, 0x47c9b37a, 0x7a47f4c9, 0xacef27c8, 0xc8ac8bef, 0xe73288ba, 0xbae76f32, 0x2b7d4f32, 0x322b647d, 0x95a442e6, 0xe695d7a4
, 0xa0fb3bc0, 0xc0a09bfb, 0x98b3aa19, 0x199832b3, 0xd168f69e, 0x9ed12768, 0x7f8122a3, 0xa37f5d81, 0x66aaee44, 0x446688aa, 0x7e82d654, 0x547ea882, 0xabe6dd3b, 0x3bab76e6, 0x839e950b, 0xb83169e
, 0xca45c98c, 0x8cca0345, 0x297bbcc7, 0xc729957b, 0xd36e056b, 0x6bd3d66e, 0x3c446c28, 0x283c5044, 0x798b2ca7, 0xa779558b, 0xe23d81bc, 0xbce2633d, 0x1d273116, 0x161d2c27, 0x769a37ad, 0xad76419a
, 0x3b4d96db, 0xdb3bad4d, 0x56fa9e64, 0x6456c8fa, 0x4ed2a674, 0x744ee8d2, 0x1e223614, 0x141e2822, 0xdb76e492, 0x92db3f76, 0xa1e120c, 0xc0a181e, 0x6cb4fc48, 0x486c90b4, 0xe4378fb8, 0xb8e46b37
, 0x5de7789f, 0x9f5d25e7, 0x6eb20fbd, 0xbd6e61b2, 0xef2a6943, 0x43ef862a, 0xa6f135c4, 0xc4a693f1, 0xa8e3da39, 0x39a872e3, 0xa4f7c631, 0x31a462f7, 0x37598ad3, 0xd337bd59, 0x8b8674f2, 0xf28bff86
, 0x325683d5, 0xd532b156, 0x43c54e8b, 0x8b430dc5, 0x59eb856e, 0x6e59dceb, 0xb7c218da, 0xdab7afc2, 0x8c8f8e01, 0x18c028f, 0x64ac1db1, 0xb16479ac, 0xd26df19c, 0x9cd2236d, 0xe03b7249, 0x49e0923b
, 0xb4c71fd8, 0xd8b4abc7, 0xfa15b9ac, 0xacfa4315, 0x709faf3, 0xf307fd09, 0x256fa0cf, 0xcf25856f, 0xafea20ca, 0xcaaf8fea, 0x8e897df4, 0xf48ef389, 0xe9206747, 0x47e98e20, 0x18283810, 0x10182028
, 0xd5640b6f, 0x6fd5de64, 0x888373f0, 0xf088fb83, 0x6fb1fb4a, 0x4a6f94b1, 0x7296ca5c, 0x5c72b896, 0x246c5438, 0x3824706c, 0xf1085f57, 0x57f1ae08, 0xc7522173, 0x73c7e652, 0x51f36497, 0x975135f3
, 0x2365aecb, 0xcb238d65, 0x7c8425a1, 0xa17c5984, 0x9cbf57e8, 0xe89ccbbf, 0x21635d3e, 0x3e217c63, 0xdd7cea96, 0x96dd377c, 0xdc7f1e61, 0x61dcc27f, 0x86919c0d, 0xd861a91, 0x85949b0f, 0xf851e94
, 0x90ab4be0, 0xe090dbab, 0x42c6ba7c, 0x7c42f8c6, 0xc4572671, 0x71c4e257, 0xaae529cc, 0xccaa83e5, 0xd873e390, 0x90d83b73, 0x50f0906, 0x6050c0f, 0x103f4f7, 0xf701f503, 0x12362a1c, 0x1c123836
, 0xa3fe3cc2, 0xc2a39ffe, 0x5fe18b6a, 0x6a5fd4e1, 0xf910beae, 0xaef94710, 0xd06b0269, 0x69d0d26b, 0x91a8bf17, 0x17912ea8, 0x58e87199, 0x995829e8, 0x2769533a, 0x3a277469, 0xb9d0f727, 0x27b94ed0
, 0x384891d9, 0xd938a948, 0x1335deeb, 0xeb13cd35, 0xb3cee52b, 0x2bb356ce, 0x33557722, 0x22334455, 0xbbd604d2, 0xd2bbbfd6, 0x709039a9, 0xa9704990, 0x89808707, 0x7890e80, 0xa7f2c133, 0x33a766f2
, 0xb6c1ec2d, 0x2db65ac1, 0x22665a3c, 0x3c227866, 0x92adb815, 0x15922aad, 0x2060a9c9, 0xc9208960, 0x49db5c87, 0x874915db, 0xff1ab0aa, 0xaaff4f1a, 0x7888d850, 0x5078a088, 0x7a8e2ba5, 0xa57a518e
, 0x8f8a8903, 0x38f068a, 0xf8134a59, 0x59f8b213, 0x809b9209, 0x980129b, 0x1739231a, 0x1a173439, 0xda751065, 0x65daca75, 0x315384d7, 0xd731b553, 0xc651d584, 0x84c61351, 0xb8d303d0, 0xd0b8bbd3
, 0xc35edc82, 0x82c31f5e, 0xb0cbe229, 0x29b052cb, 0x7799c35a, 0x5a77b499, 0x11332d1e, 0x1e113c33, 0xcb463d7b, 0x7bcbf646, 0xfc1fb7a8, 0xa8fc4b1f, 0xd6610c6d, 0x6dd6da61, 0x3a4e622c, 0x2c3a584e
};
#endif /* __tables_h */

View file

@ -111,10 +111,10 @@ typedef uint64_t u64b_t; /* 64-bit unsigned integer */
#if PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN
/* here for big-endian CPUs */
/* here for big-endian CPUs */
#define SKEIN_NEED_SWAP (1)
#elif PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN
/* here for x86 and x86-64 CPUs (and other detected little-endian CPUs) */
/* here for x86 and x86-64 CPUs (and other detected little-endian CPUs) */
#define SKEIN_NEED_SWAP (0)
#if PLATFORM_MUST_ALIGN == 0 /* ok to use "fast" versions? */
#define Skein_Put64_LSB_First(dst08,src64,bCnt) memcpy(dst08,src64,bCnt)
@ -149,38 +149,42 @@ typedef uint64_t u64b_t; /* 64-bit unsigned integer */
#ifndef Skein_Put64_LSB_First
void Skein_Put64_LSB_First(u08b_t *dst,const u64b_t *src,size_t bCnt)
void Skein_Put64_LSB_First(u08b_t* dst, const u64b_t* src, size_t bCnt)
#ifdef SKEIN_PORT_CODE /* instantiate the function code here? */
{ /* this version is fully portable (big-endian or little-endian), but slow */
{
/* this version is fully portable (big-endian or little-endian), but slow */
size_t n;
for (n=0;n<bCnt;n++)
dst[n] = (u08b_t) (src[n>>3] >> (8*(n&7)));
for(n = 0; n < bCnt; n++)
{
dst[n] = (u08b_t)(src[n >> 3] >> (8 * (n & 7)));
}
}
#else
; /* output only the function prototype */
; /* output only the function prototype */
#endif
#endif /* ifndef Skein_Put64_LSB_First */
#ifndef Skein_Get64_LSB_First
void Skein_Get64_LSB_First(u64b_t *dst,const u08b_t *src,size_t wCnt)
void Skein_Get64_LSB_First(u64b_t* dst, const u08b_t* src, size_t wCnt)
#ifdef SKEIN_PORT_CODE /* instantiate the function code here? */
{ /* this version is fully portable (big-endian or little-endian), but slow */
{
/* this version is fully portable (big-endian or little-endian), but slow */
size_t n;
for (n=0;n<8*wCnt;n+=8)
dst[n/8] = (((u64b_t) src[n ]) ) +
(((u64b_t) src[n+1]) << 8) +
(((u64b_t) src[n+2]) << 16) +
(((u64b_t) src[n+3]) << 24) +
(((u64b_t) src[n+4]) << 32) +
(((u64b_t) src[n+5]) << 40) +
(((u64b_t) src[n+6]) << 48) +
(((u64b_t) src[n+7]) << 56) ;
}
for(n = 0; n < 8 * wCnt; n += 8)
dst[n / 8] = (((u64b_t) src[n ])) +
(((u64b_t) src[n + 1]) << 8) +
(((u64b_t) src[n + 2]) << 16) +
(((u64b_t) src[n + 3]) << 24) +
(((u64b_t) src[n + 4]) << 32) +
(((u64b_t) src[n + 5]) << 40) +
(((u64b_t) src[n + 6]) << 48) +
(((u64b_t) src[n + 7]) << 56) ;
}
#else
; /* output only the function prototype */
; /* output only the function prototype */
#endif
#endif /* ifndef Skein_Get64_LSB_First */

View file

@ -86,8 +86,8 @@
#define saes_u2(p) saes_b2w( p, saes_f3(p), saes_f2(p), p)
#define saes_u3(p) saes_b2w( p, p, saes_f3(p), saes_f2(p))
alignas(16) const uint32_t saes_table[4][256] = { saes_data(saes_u0), saes_data(saes_u1), saes_data(saes_u2), saes_data(saes_u3) };
alignas(16) const uint8_t saes_sbox[256] = saes_data(saes_h0);
const uint32_t saes_table[4][256] = { saes_data(saes_u0), saes_data(saes_u1), saes_data(saes_u2), saes_data(saes_u3) };
const uint8_t saes_sbox[256] = saes_data(saes_h0);
static inline __m128i soft_aesenc(__m128i in, __m128i key)
{
@ -97,10 +97,14 @@ static inline __m128i soft_aesenc(__m128i in, __m128i key)
const uint32_t x3 = _mm_cvtsi128_si32(_mm_shuffle_epi32(in, 0xFF));
__m128i out = _mm_set_epi32(
(saes_table[0][x3 & 0xff] ^ saes_table[1][(x0 >> 8) & 0xff] ^ saes_table[2][(x1 >> 16) & 0xff] ^ saes_table[3][x2 >> 24]),
(saes_table[0][x2 & 0xff] ^ saes_table[1][(x3 >> 8) & 0xff] ^ saes_table[2][(x0 >> 16) & 0xff] ^ saes_table[3][x1 >> 24]),
(saes_table[0][x1 & 0xff] ^ saes_table[1][(x2 >> 8) & 0xff] ^ saes_table[2][(x3 >> 16) & 0xff] ^ saes_table[3][x0 >> 24]),
(saes_table[0][x0 & 0xff] ^ saes_table[1][(x1 >> 8) & 0xff] ^ saes_table[2][(x2 >> 16) & 0xff] ^ saes_table[3][x3 >> 24]));
(saes_table[0][x3 & 0xff] ^ saes_table[1][(x0 >> 8) & 0xff] ^ saes_table[2][(x1 >> 16) & 0xff] ^
saes_table[3][x2 >> 24]),
(saes_table[0][x2 & 0xff] ^ saes_table[1][(x3 >> 8) & 0xff] ^ saes_table[2][(x0 >> 16) & 0xff] ^
saes_table[3][x1 >> 24]),
(saes_table[0][x1 & 0xff] ^ saes_table[1][(x2 >> 8) & 0xff] ^ saes_table[2][(x3 >> 16) & 0xff] ^
saes_table[3][x0 >> 24]),
(saes_table[0][x0 & 0xff] ^ saes_table[1][(x1 >> 8) & 0xff] ^ saes_table[2][(x2 >> 16) & 0xff] ^
saes_table[3][x3 >> 24]));
return _mm_xor_si128(out, key);
}
@ -108,8 +112,8 @@ static inline __m128i soft_aesenc(__m128i in, __m128i key)
static inline uint32_t sub_word(uint32_t key)
{
return (saes_sbox[key >> 24 ] << 24) |
(saes_sbox[(key >> 16) & 0xff] << 16 ) |
(saes_sbox[(key >> 8) & 0xff] << 8 ) |
(saes_sbox[(key >> 16) & 0xff] << 16) |
(saes_sbox[(key >> 8) & 0xff] << 8) |
saes_sbox[key & 0xff];
}

View file

@ -37,7 +37,10 @@
* XMR: 48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD
* BTC: 1P7ujsXeX7GxQwHNnJsRMgAdNkFZmNVqJT
*/
constexpr const int kDonateLevel = 5;
enum
{
kDonateLevel = 5,
};
#endif /* __DONATE_H__ */

View file

@ -38,10 +38,10 @@ class IClientListener
public:
virtual ~IClientListener() {}
virtual void onClose(Client *client, int failures) = 0;
virtual void onJobReceived(Client *client, const Job &job) = 0;
virtual void onLoginSuccess(Client *client) = 0;
virtual void onResultAccepted(Client *client, const SubmitResult &result, const char *error) = 0;
virtual void onClose(Client* client, int failures) = 0;
virtual void onJobReceived(Client* client, const Job & job) = 0;
virtual void onLoginSuccess(Client* client) = 0;
virtual void onResultAccepted(Client* client, const SubmitResult & result, const std::string & error) = 0;
};

View file

@ -24,17 +24,25 @@
#ifndef __ILOGBACKEND_H__
#define __ILOGBACKEND_H__
#include <stdarg.h>
#include "interfaces/interface.h"
#include <string>
class ILogBackend
{
public:
enum Level
{
ERR,
WARNING,
NOTICE,
INFO,
DEBUG
};
virtual ~ILogBackend() {}
virtual void message(int level, const char* fmt, va_list args) = 0;
virtual void text(const char* fmt, va_list args) = 0;
virtual void message(Level level, const std::string & txt) = 0;
virtual void text(const std::string & txt) = 0;
};

View file

@ -24,10 +24,9 @@
#ifndef __ISTRATEGY_H__
#define __ISTRATEGY_H__
#include "interfaces/interface.h"
#include <stdint.h>
class JobResult;
@ -37,7 +36,7 @@ public:
virtual ~IStrategy() {}
virtual bool isActive() const = 0;
virtual int64_t submit(const JobResult &result) = 0;
virtual int64_t submit(const JobResult & result) = 0;
virtual void connect() = 0;
virtual void resume() = 0;
virtual void stop() = 0;

View file

@ -24,26 +24,23 @@
#ifndef __ISTRATEGYLISTENER_H__
#define __ISTRATEGYLISTENER_H__
#include <stdint.h>
#include <string>
class Client;
class IStrategy;
class Job;
class SubmitResult;
class IStrategyListener
{
public:
virtual ~IStrategyListener() {}
virtual void onActive(Client *client) = 0;
virtual void onJob(Client *client, const Job &job) = 0;
virtual void onPause(IStrategy *strategy) = 0;
virtual void onResultAccepted(Client *client, const SubmitResult &result, const char *error) = 0;
virtual void onActive(Client* client) = 0;
virtual void onJob(Client* client, const Job & job) = 0;
virtual void onPause(IStrategy* strategy) = 0;
virtual void onResultAccepted(Client* client, const SubmitResult & result, const std::string & error) = 0;
};
#endif // __ISTRATEGYLISTENER_H__

View file

@ -0,0 +1,62 @@
/* XMRig - enWILLYado
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __INTERFACE_H__
#define __INTERFACE_H__
#ifdef _WIN32
#if defined(_MSC_VER) && _MSC_VER < 1900
// C++-11
#define override
// VS
#include <vadefs.h>
#include <stdio.h>
#include <stdarg.h>
#define snprintf c99_snprintf
#define vsnprintf c99_vsnprintf
__inline int c99_vsnprintf(char* outBuf, size_t size, const char* format, va_list ap)
{
int count = -1;
if(size != 0)
{
count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
}
if(count == -1)
{
count = _vscprintf(format, ap);
}
return count;
}
__inline int c99_snprintf(char* outBuf, size_t size, const char* format, ...)
{
int count;
va_list ap;
va_start(ap, format);
count = c99_vsnprintf(outBuf, size, format, ap);
va_end(ap);
return count;
}
#endif
#endif
#endif // __INTERFACE_H__

View file

@ -21,134 +21,98 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef WIN32
# include <winsock2.h>
# include <windows.h>
#endif
#include <iostream>
#include "log/ConsoleLog.h"
#include "log/Log.h"
#include "Options.h"
ConsoleLog::ConsoleLog(bool colors) :
m_colors(colors),
m_stream(nullptr)
m_colors(colors)
{
if (uv_tty_init(uv_default_loop(), &m_tty, 1, 0) < 0) {
Options::i()->setColors(false);
m_colors = false;
}
void ConsoleLog::message(Level level, const std::string & text)
{
if(!isWritable())
{
return;
}
uv_tty_set_mode(&m_tty, UV_TTY_MODE_NORMAL);
m_uvBuf.base = m_buf;
m_stream = reinterpret_cast<uv_stream_t*>(&m_tty);
# ifdef WIN32
HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
if (handle != INVALID_HANDLE_VALUE) {
DWORD mode = 0;
if (GetConsoleMode(handle, &mode)) {
mode &= ~ENABLE_QUICK_EDIT_MODE;
SetConsoleMode(handle, mode | ENABLE_EXTENDED_FLAGS);
}
}
# endif
}
void ConsoleLog::message(int level, const char* fmt, va_list args)
{
//
//
time_t now = time(nullptr);
tm stime;
# ifdef _WIN32
#ifdef _WIN32
localtime_s(&stime, &now);
# else
#else
localtime_r(&now, &stime);
# endif
#endif
const char* color = nullptr;
if (m_colors) {
switch (level) {
case Log::ERR:
color = Log::kCL_RED;
break;
case Log::WARNING:
color = Log::kCL_YELLOW;
break;
case Log::NOTICE:
color = Log::kCL_WHITE;
break;
case Log::DEBUG:
color = Log::kCL_GRAY;
break;
default:
color = "";
break;
}
}
snprintf(m_fmt, sizeof(m_fmt) - 1, "[%d-%02d-%02d %02d:%02d:%02d]%s %s%s\n",
char buf[25];
int size = snprintf(buf, sizeof(buf), "[%d-%02d-%02d %02d:%02d:%02d] ",
stime.tm_year + 1900,
stime.tm_mon + 1,
stime.tm_mday,
stime.tm_hour,
stime.tm_min,
stime.tm_sec,
m_colors ? color : "",
fmt,
m_colors ? Log::kCL_N : ""
);
stime.tm_sec);
print(args);
}
//
//
std::string colorIni, colorEnd;
if(m_colors)
{
colorEnd = Log::CL_N();
switch(level)
{
case ILogBackend::ERR:
colorIni = Log::CL_RED();
break;
case ILogBackend::WARNING:
colorIni = Log::CL_YELLOW();
break;
void ConsoleLog::text(const char* fmt, va_list args)
{
snprintf(m_fmt, sizeof(m_fmt) - 1, "%s%s\n", fmt, m_colors ? Log::kCL_N : "");
case ILogBackend::NOTICE:
colorIni = Log::CL_WHITE();
break;
print(args);
}
case ILogBackend::DEBUG:
colorIni = Log::CL_GRAY();
break;
bool ConsoleLog::isWritable() const
{
if (!m_stream || uv_is_writable(m_stream) != 1) {
return false;
default:
break;
}
}
const uv_handle_type type = uv_guess_handle(1);
return type == UV_TTY || type == UV_NAMED_PIPE;
print(std::string(buf, size) + colorIni + text + colorEnd);
}
void ConsoleLog::print(va_list args)
void ConsoleLog::text(const std::string & txt)
{
m_uvBuf.len = vsnprintf(m_buf, sizeof(m_buf) - 1, m_fmt, args);
if (m_uvBuf.len <= 0) {
if(!isWritable())
{
return;
}
if (!isWritable()) {
fputs(m_buf, stdout);
fflush(stdout);
}
else {
uv_try_write(m_stream, &m_uvBuf, 1);
}
print(txt);
}
bool ConsoleLog::isWritable() const
{
return std::cout.good();
}
void ConsoleLog::print(const std::string & txt)
{
std::cout << txt << std::endl;
std::cout.flush();
}

View file

@ -36,19 +36,14 @@ class ConsoleLog : public ILogBackend
public:
ConsoleLog(bool colors);
void message(int level, const char *fmt, va_list args) override;
void text(const char *fmt, va_list args) override;
void message(Level level, const std::string & txt) override;
void text(const std::string & txt) override;
private:
bool isWritable() const;
void print(va_list args);
void print(const std::string & txt);
bool m_colors;
char m_buf[512];
char m_fmt[256];
uv_buf_t m_uvBuf;
uv_stream_t *m_stream;
uv_tty_t m_tty;
};
#endif /* __CONSOLELOG_H__ */

View file

@ -28,35 +28,37 @@
#include <string.h>
#include <time.h>
#include <fstream>
#include <iostream>
#include "log/Log.h"
#include "log/FileLog.h"
FileLog::FileLog(const char *fileName)
FileLog::FileLog(const std::string & fileName)
: m_file_name(fileName)
{
uv_fs_t req;
m_file = uv_fs_open(uv_default_loop(), &req, fileName, O_CREAT | O_APPEND | O_WRONLY, 0644, nullptr);
uv_fs_req_cleanup(&req);
}
void FileLog::message(int level, const char* fmt, va_list args)
void FileLog::message(Level level, const std::string & txt)
{
if (m_file < 0) {
if(!isWritable())
{
return;
}
//
//
time_t now = time(nullptr);
tm stime;
# ifdef _WIN32
#ifdef _WIN32
localtime_s(&stime, &now);
# else
#else
localtime_r(&now, &stime);
# endif
#endif
char *buf = new char[512];
int size = snprintf(buf, 23, "[%d-%02d-%02d %02d:%02d:%02d] ",
char buf[25];
int size = snprintf(buf, sizeof(buf), "[%d-%02d-%02d %02d:%02d:%02d] ",
stime.tm_year + 1900,
stime.tm_mon + 1,
stime.tm_mday,
@ -64,34 +66,30 @@ void FileLog::message(int level, const char* fmt, va_list args)
stime.tm_min,
stime.tm_sec);
size = vsnprintf(buf + size, 512 - size - 1, fmt, args) + size;
buf[size] = '\n';
write(buf, size + 1);
//
//
write(std::string(buf, size) + txt);
}
void FileLog::text(const char* fmt, va_list args)
void FileLog::text(const std::string & txt)
{
message(0, fmt, args);
if(!isWritable())
{
return;
}
write(txt);
}
void FileLog::onWrite(uv_fs_t *req)
bool FileLog::isWritable() const
{
delete [] static_cast<char *>(req->data);
uv_fs_req_cleanup(req);
delete req;
return (m_file_name != "") && std::ofstream(m_file_name, std::ios_base::app).good();
}
void FileLog::write(char *data, size_t size)
void FileLog::write(const std::string & txt)
{
uv_buf_t buf = uv_buf_init(data, (unsigned int) size);
uv_fs_t *req = new uv_fs_t;
req->data = buf.base;
std::ofstream outfile;
uv_fs_write(uv_default_loop(), req, m_file, &buf, 1, 0, FileLog::onWrite);
outfile.open(m_file_name, std::ios_base::app);
outfile << txt << std::endl;
}

View file

@ -24,27 +24,21 @@
#ifndef __FILELOG_H__
#define __FILELOG_H__
#include <uv.h>
#include "interfaces/ILogBackend.h"
class FileLog : public ILogBackend
{
public:
FileLog(const char *fileName);
FileLog(const std::string & fileName);
void message(int level, const char* fmt, va_list args) override;
void text(const char* fmt, va_list args) override;
void message(Level level, const std::string & txt) override;
void text(const std::string & txt) override;
private:
static void onWrite(uv_fs_t *req);
bool isWritable() const;
void write(const std::string & txt);
void write(char *data, size_t size);
int m_file;
const std::string m_file_name;
};
#endif /* __FILELOG_H__ */

View file

@ -28,47 +28,35 @@
#include <string.h>
#include <time.h>
#include "interfaces/ILogBackend.h"
#include "log/Log.h"
Log* Log::m_self = nullptr;
Log *Log::m_self = nullptr;
void Log::message(Log::Level level, const char* fmt, ...)
void Log::message(ILogBackend::Level level, const std::string & text)
{
va_list args;
va_list copy;
va_start(args, fmt);
for (ILogBackend *backend : m_backends) {
va_copy(copy, args);
backend->message(level, fmt, copy);
va_end(copy);
for(size_t i = 0; i < m_backends.size(); ++i)
{
auto backend = m_backends[i];
backend->message(level, text);
}
}
void Log::text(const char* fmt, ...)
void Log::text(const std::string & text)
{
va_list args;
va_list copy;
va_start(args, fmt);
for (ILogBackend *backend : m_backends) {
va_copy(copy, args);
backend->text(fmt, copy);
va_end(copy);
for(size_t i = 0; i < m_backends.size(); ++i)
{
auto backend = m_backends[i];
backend->text(text);
}
va_end(args);
}
Log::~Log()
{
for (auto backend : m_backends) {
for(size_t i = 0; i < m_backends.size(); ++i)
{
auto backend = m_backends[i];
delete backend;
}
}

View file

@ -24,70 +24,102 @@
#ifndef __LOG_H__
#define __LOG_H__
#include <uv.h>
#include <vector>
#include <sstream>
class ILogBackend;
#include "interfaces/ILogBackend.h"
class Log
{
public:
enum Level {
ERR,
WARNING,
NOTICE,
INFO,
DEBUG
};
constexpr static const char* kCL_N = "\x1B[0m";
constexpr static const char* kCL_RED = "\x1B[31m";
constexpr static const char* kCL_YELLOW = "\x1B[33m";
constexpr static const char* kCL_WHITE = "\x1B[01;37m";
static const std::string & CL_N()
{
static const std::string kCL_N = "\x1B[0m";
return kCL_N;
}
static const std::string & CL_RED()
{
static const std::string kCL_RED = "\x1B[31m";
return kCL_RED;
}
static const std::string & CL_YELLOW()
{
static const std::string kCL_YELLOW = "\x1B[33m";
return kCL_YELLOW;
}
static const std::string & CL_WHITE()
{
static const std::string kCL_WHITE = "\x1B[01;37m";
return kCL_WHITE;
}
static const std::string & CL_GRAY()
{
# ifdef WIN32
constexpr static const char* kCL_GRAY = "\x1B[01;30m";
# else
constexpr static const char* kCL_GRAY = "\x1B[90m";
# endif
#ifdef WIN32
static const std::string kCL_GRAY = "\x1B[01;30m";
#else
static const std::string kCL_GRAY = "\x1B[90m";
#endif
return kCL_GRAY;
}
static inline Log* i() { return m_self; }
static inline void add(ILogBackend *backend) { i()->m_backends.push_back(backend); }
static inline void init() { if (!m_self) { m_self = new Log();} }
static inline void release() { delete m_self; }
static inline Log* i()
{
return m_self;
}
static inline void add(ILogBackend* backend)
{
i()->m_backends.push_back(backend);
}
static inline void init()
{
if(!m_self)
{
m_self = new Log();
}
}
static inline void release()
{
delete m_self;
}
void message(Level level, const char* fmt, ...);
void text(const char* fmt, ...);
void message(ILogBackend::Level level, const std::string & text);
void text(const std::string & text);
static inline std::string TO_STRING(const std::basic_ostream<char> & i)
{
const std::stringstream & stream = static_cast<const std::stringstream &>(i);
return stream.str();
}
private:
inline Log() {}
~Log();
static Log *m_self;
static Log* m_self;
std::vector<ILogBackend*> m_backends;
};
#define LOG_ERR(x, ...) Log::i()->message(Log::ERR, x, ##__VA_ARGS__)
#define LOG_WARN(x, ...) Log::i()->message(Log::WARNING, x, ##__VA_ARGS__)
#define LOG_NOTICE(x, ...) Log::i()->message(Log::NOTICE, x, ##__VA_ARGS__)
#define LOG_INFO(x, ...) Log::i()->message(Log::INFO, x, ##__VA_ARGS__)
#define PRINT_MSG(x) Log::i()->text(Log::TO_STRING(std::stringstream() << x))
#define LOG_ERR(x) Log::i()->message(ILogBackend::ERR, Log::TO_STRING(std::stringstream() << x))
#define LOG_WARN(x) Log::i()->message(ILogBackend::WARNING, Log::TO_STRING(std::stringstream() << x))
#define LOG_NOTICE(x) Log::i()->message(ILogBackend::NOTICE, Log::TO_STRING(std::stringstream() << x))
#define LOG_INFO(x) Log::i()->message(ILogBackend::INFO, Log::TO_STRING(std::stringstream() << x))
#ifdef APP_DEBUG
# define LOG_DEBUG(x, ...) Log::i()->message(Log::DEBUG, x, ##__VA_ARGS__)
#define LOG_DEBUG(x) Log::i()->message(ILogBackend::DEBUG, Log::TO_STRING(std::stringstream() << x))
#else
# define LOG_DEBUG(x, ...)
#define LOG_DEBUG(x)
#endif
#if defined(APP_DEBUG) || defined(APP_DEVEL)
# define LOG_DEBUG_ERR(x, ...) Log::i()->message(Log::ERR, x, ##__VA_ARGS__)
# define LOG_DEBUG_WARN(x, ...) Log::i()->message(Log::WARNING, x, ##__VA_ARGS__)
#define LOG_DEBUG_ERR(x) Log::i()->message(ILogBackend::ERR, Log::TO_STRING(std::stringstream() << x))
#define LOG_DEBUG_WARN(x) Log::i()->message(ILogBackend::WARNING, Log::TO_STRING(std::stringstream() << x))
#else
# define LOG_DEBUG_ERR(x, ...)
# define LOG_DEBUG_WARN(x, ...)
#define LOG_DEBUG_ERR(x)
#define LOG_DEBUG_WARN(x)
#endif
#endif /* __LOG_H__ */

View file

@ -21,6 +21,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_SYSLOG_H
#include <syslog.h>
@ -34,14 +35,15 @@ SysLog::SysLog()
openlog(APP_ID, LOG_PID, LOG_USER);
}
void SysLog::message(int level, const char *fmt, va_list args)
void SysLog::text(const std::string & txt)
{
vsyslog(level, fmt, args);
message(INFO, txt);
}
void SysLog::text(const char *fmt, va_list args)
void SysLog::message(Level level, const std::string & txt)
{
message(LOG_INFO, fmt, args);
syslog(level == INFO ? LOG_INFO : LOG_NOTICE, "%s", txt);
}
#endif

View file

@ -33,8 +33,8 @@ class SysLog : public ILogBackend
public:
SysLog();
void message(int level, const char *fmt, va_list args) override;
void text(const char *fmt, va_list args) override;
void message(Level level, const std::string & txt) override;
void text(const std::string & txt) override;
};
#endif /* __SYSLOG_BACKEND_H__ */

View file

@ -4,7 +4,7 @@
* Copyright 2014 Lucas Jones <https://github.com/lucasjones>
* Copyright 2014-2016 Wolf9466 <https://github.com/OhGodAPet>
* Copyright 2016 Jay D Dee <jayddee246@gmail.com>
* Copyright 2016-2017 XMRig <support@xmrig.com>
* Copyright 2016-2018 XMRig <support@xmrig.com>
*
*
* This program is free software: you can redistribute it and/or modify
@ -37,25 +37,23 @@
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
#ifdef XMRIG_PROXY_PROJECT
# include "proxy/JobResult.h"
#include "proxy/JobResult.h"
#else
# include "net/JobResult.h"
#include "net/JobResult.h"
#endif
#ifdef _MSC_VER
# define strncasecmp(x,y,z) _strnicmp(x,y,z)
#define strncasecmp(x,y,z) _strnicmp(x,y,z)
#endif
int64_t Client::m_sequence = 1;
Client::Client(int id, const char *agent, IClientListener *listener) :
Client::Client(int id, const std::string & agent, IClientListener* listener) :
m_quiet(false),
m_keystream(),
m_encrypted(false),
m_agent(agent),
m_listener(listener),
@ -68,7 +66,6 @@ Client::Client(int id, const char *agent, IClientListener *listener) :
m_stream(nullptr),
m_socket(nullptr)
{
memset(m_ip, 0, sizeof(m_ip));
memset(&m_hints, 0, sizeof(m_hints));
memset(m_keystream, 0, sizeof(m_keystream));
@ -81,10 +78,10 @@ Client::Client(int id, const char *agent, IClientListener *listener) :
m_recvBuf.base = m_buf;
m_recvBuf.len = sizeof(m_buf);
# ifndef XMRIG_PROXY_PROJECT
#ifndef XMRIG_PROXY_PROJECT
m_keepAliveTimer.data = this;
uv_timer_init(uv_default_loop(), &m_keepAliveTimer);
# endif
#endif
}
@ -105,7 +102,7 @@ void Client::connect()
*
* @param url
*/
void Client::connect(const Url *url)
void Client::connect(const Url & url)
{
setUrl(url);
resolve(m_url.host());
@ -114,9 +111,9 @@ void Client::connect(const Url *url)
void Client::disconnect()
{
# ifndef XMRIG_PROXY_PROJECT
#ifndef XMRIG_PROXY_PROJECT
uv_timer_stop(&m_keepAliveTimer);
# endif
#endif
m_expire = 0;
m_failures = -1;
@ -125,15 +122,16 @@ void Client::disconnect()
}
void Client::setUrl(const Url *url)
void Client::setUrl(const Url & url)
{
if (!url || !url->isValid()) {
if(false == url.isValid())
{
return;
}
if (url->hasKeystream())
if(url.hasKeystream())
{
url->copyKeystream(m_keystream, sizeof(m_keystream));
url.copyKeystream(m_keystream, sizeof(m_keystream));
m_encrypted = true;
}
else
@ -147,61 +145,76 @@ void Client::setUrl(const Url *url)
void Client::tick(uint64_t now)
{
if (m_expire == 0 || now < m_expire) {
if(m_expire == 0 || now < m_expire)
{
return;
}
if (m_state == ConnectedState) {
LOG_DEBUG_ERR("[%s:%u] timeout", m_url.host(), m_url.port());
if(m_state == ConnectedState)
{
LOG_DEBUG_ERR("[" << m_url.host() << ":" << m_url.port() << "] timeout");
close();
}
if (m_state == ConnectingState) {
if(m_state == ConnectingState)
{
connect();
}
}
int64_t Client::submit(const JobResult &result)
int64_t Client::submit(const JobResult & result)
{
# ifdef XMRIG_PROXY_PROJECT
const char *nonce = result.nonce;
const char *data = result.result;
# else
char nonce[9];
char data[65];
#ifdef XMRIG_PROXY_PROJECT
const std::string nonce = result.nonce;
const std::string data = result.result;
#else
char nonce_buffer[9];
char data_buffer[65];
Job::toHex(reinterpret_cast<const unsigned char*>(&result.nonce), 4, nonce);
nonce[8] = '\0';
char* nonceChar = (char*)(&result.nonce);
Job::toHex(std::string(nonceChar, 4), nonce_buffer);
nonce_buffer[8] = '\0';
Job::toHex(result.result, 32, data);
data[64] = '\0';
# endif
char* resultChar = (char*)(&result.result);
Job::toHex(std::string(resultChar, 32), data_buffer);
data_buffer[64] = '\0';
const size_t size = snprintf(m_sendBuf, sizeof(m_sendBuf), "{\"id\":%" PRIu64 ",\"jsonrpc\":\"2.0\",\"method\":\"submit\",\"params\":{\"id\":\"%s\",\"job_id\":\"%s\",\"nonce\":\"%s\",\"result\":\"%s\"}}\n",
m_sequence, m_rpcId, result.jobId.data(), nonce, data);
const std::string nonce = nonce_buffer;
const std::string data = data_buffer;
#endif
const size_t size = snprintf(m_sendBuf, sizeof(m_sendBuf),
"{\"id\":%" PRIu64
",\"jsonrpc\":\"2.0\",\"method\":\"submit\",\"params\":{\"id\":\"%s\",\"job_id\":\"%s\",\"nonce\":\"%s\",\"result\":\"%s\"}}\n",
m_sequence, m_rpcId,
result.jobId.data().c_str(), nonce.c_str(), data.c_str());
m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff());
return send(size);
}
bool Client::isCriticalError(const char *message)
bool Client::isCriticalError(const std::string & message)
{
if (!message) {
if(message.empty())
{
return false;
}
if (strncasecmp(message, "Unauthenticated", 15) == 0) {
if(message == "Unauthenticated")
{
return true;
}
if (strncasecmp(message, "your IP is banned", 17) == 0) {
if(message == "your IP is banned")
{
return true;
}
if (strncasecmp(message, "IP Address currently banned", 27) == 0) {
if(message == "IP Address currently banned")
{
return true;
}
@ -209,32 +222,38 @@ bool Client::isCriticalError(const char *message)
}
bool Client::parseJob(const rapidjson::Value &params, int *code)
bool Client::parseJob(const rapidjson::Value & params, int* code)
{
if (!params.IsObject()) {
if(!params.IsObject())
{
*code = 2;
return false;
}
Job job(m_id, m_url.isNicehash());
if (!job.setId(params["job_id"].GetString())) {
if(!job.setId(params["job_id"].GetString()))
{
*code = 3;
return false;
}
if (!job.setBlob(params["blob"].GetString())) {
if(!job.setBlob(params["blob"].GetString()))
{
*code = 4;
return false;
}
if (!job.setTarget(params["target"].GetString())) {
if(!job.setTarget(params["target"].GetString()))
{
*code = 5;
return false;
}
if (m_job == job) {
if (!m_quiet) {
LOG_WARN("[%s:%u] duplicate job received, reconnect", m_url.host(), m_url.port());
if(m_job == job)
{
if(!m_quiet)
{
LOG_WARN("[" << m_url.host() << ":" << m_url.port() << "] duplicate job received, reconnect");
}
close();
@ -246,10 +265,11 @@ bool Client::parseJob(const rapidjson::Value &params, int *code)
}
bool Client::parseLogin(const rapidjson::Value &result, int *code)
bool Client::parseLogin(const rapidjson::Value & result, int* code)
{
const char *id = result["id"].GetString();
if (!id || strlen(id) >= sizeof(m_rpcId)) {
const char* id = result["id"].GetString();
if(!id || strlen(id) >= sizeof(m_rpcId))
{
*code = 1;
return false;
}
@ -261,21 +281,24 @@ bool Client::parseLogin(const rapidjson::Value &result, int *code)
}
int Client::resolve(const char *host)
int Client::resolve(const std::string & host)
{
setState(HostLookupState);
m_expire = 0;
m_recvBufPos = 0;
if (m_failures == -1) {
if(m_failures == -1)
{
m_failures = 0;
}
const int r = uv_getaddrinfo(uv_default_loop(), &m_resolver, Client::onResolved, host, NULL, &m_hints);
if (r) {
if (!m_quiet) {
LOG_ERR("[%s:%u] getaddrinfo error: \"%s\"", host, m_url.port(), uv_strerror(r));
const int r = uv_getaddrinfo(uv_default_loop(), &m_resolver, Client::onResolved, host.c_str(), NULL, &m_hints);
if(r)
{
if(!m_quiet)
{
LOG_ERR("[" << host << ":" << m_url.port() << "] getaddrinfo error: \"" << uv_strerror(r) << "\"");
}
return 1;
}
@ -286,31 +309,35 @@ int Client::resolve(const char *host)
int64_t Client::send(size_t size, const bool encrypted)
{
LOG_DEBUG("[%s:%u] send (%d bytes): \"%s\"", m_url.host(), m_url.port(), size, m_sendBuf);
if ((state() != ConnectedState && state() != ProxingState) || !uv_is_writable(m_stream)) {
LOG_DEBUG_ERR("[%s:%u] send failed, invalid state: %d", m_url.host(), m_url.port(), m_state);
LOG_DEBUG("[" << m_url.host() << ":" << m_url.port() << "] send(" << size << " bytes): \"" << m_sendBuf <<
"\"");
if((state() != ConnectedState && state() != ProxingState) || !uv_is_writable(m_stream))
{
LOG_DEBUG_ERR("[" << m_url.host() << ":" << m_url.port() << "] send failed, invalid state: " << m_state);
return -1;
}
if(encrypted && m_encrypted)
{
// Encrypt
for(size_t i = 0; i < std::min(size, sizeof(m_keystream)); ++i)
for(size_t i = 0; i < std::min(size, sizeof(SendBuf)); ++i)
{
m_sendBuf[i] ^= m_keystream[i];
}
char * send_encr_hex = static_cast<char*>(malloc(size * 2 + 1));
char* send_encr_hex = static_cast<char*>(malloc(size * 2 + 1));
memset(send_encr_hex, 0, size * 2 + 1);
Job::toHex((const unsigned char*)m_sendBuf, size, send_encr_hex);
Job::toHex(std::string(m_sendBuf, size), send_encr_hex);
send_encr_hex[size * 2] = '\0';
LOG_DEBUG("[%s:%u] send encr. (%d bytes): \"0x%s\"", m_url.host(), m_url.port(), size, send_encr_hex);
LOG_DEBUG("[" << m_url.host() << ":" << m_url.port() << "] send encr.(" << size << " bytes): \"0x" <<
send_encr_hex << "\"");
free(send_encr_hex);
}
uv_buf_t buf = uv_buf_init(m_sendBuf, (unsigned int) size);
if (uv_try_write(m_stream, &buf, 1) < 0) {
if(uv_try_write(m_stream, &buf, 1) < 0)
{
close();
return -1;
}
@ -322,26 +349,28 @@ int64_t Client::send(size_t size, const bool encrypted)
void Client::close()
{
if (m_state == UnconnectedState || m_state == ClosingState || !m_socket) {
if(m_state == UnconnectedState || m_state == ClosingState || !m_socket)
{
return;
}
setState(ClosingState);
if (uv_is_closing(reinterpret_cast<uv_handle_t*>(m_socket)) == 0) {
if(uv_is_closing(reinterpret_cast<uv_handle_t*>(m_socket)) == 0)
{
uv_close(reinterpret_cast<uv_handle_t*>(m_socket), Client::onClose);
}
}
void Client::connect(struct sockaddr *addr)
void Client::connect(struct sockaddr* addr)
{
setState(ConnectingState);
reinterpret_cast<struct sockaddr_in*>(addr)->sin_port = htons(m_url.port());
delete m_socket;
uv_connect_t *req = new uv_connect_t;
uv_connect_t* req = new uv_connect_t;
req->data = this;
m_socket = new uv_tcp_t;
@ -350,31 +379,32 @@ void Client::connect(struct sockaddr *addr)
uv_tcp_init(uv_default_loop(), m_socket);
uv_tcp_nodelay(m_socket, 1);
# ifndef WIN32
#ifndef WIN32
uv_tcp_keepalive(m_socket, 1, 60);
# endif
#endif
uv_tcp_connect(req, m_socket, reinterpret_cast<const sockaddr*>(addr), Client::onConnect);
}
void Client::prelogin()
{
if (m_url.proxyHost())
if(m_url.isProxyed())
{
setState (ProxingState);
const std::string buffer = std::string ("CONNECT ") + m_url.finalHost() + ":" + std::to_string(m_url.finalPort()) + " HTTP/1.1\n";
setState(ProxingState);
const std::string buffer = std::string("CONNECT ") + m_url.finalHost() + ":" +
std::to_string((unsigned long long)(m_url.finalPort())) + " HTTP/1.1\n";
const size_t size = buffer.size();
memcpy (m_sendBuf, buffer.c_str(), size);
memcpy(m_sendBuf, buffer.c_str(), size);
m_sendBuf[size] = '\n';
m_sendBuf[size + 1] = '\0';
LOG_DEBUG("Prelogin send (%d bytes): \"%s\"", size, m_sendBuf);
send (size + 1, false);
LOG_DEBUG("Prelogin send (" << size << " bytes): \"" << m_sendBuf << "\"");
send(size + 1, false);
}
else
{
setState (ConnectedState);
setState(ConnectedState);
login();
}
}
@ -386,16 +416,16 @@ void Client::login()
rapidjson::Document doc;
doc.SetObject();
auto &allocator = doc.GetAllocator();
auto & allocator = doc.GetAllocator();
doc.AddMember("id", 1, allocator);
doc.AddMember("jsonrpc", "2.0", allocator);
doc.AddMember("method", "login", allocator);
rapidjson::Value params(rapidjson::kObjectType);
params.AddMember("login", rapidjson::StringRef(m_url.user()), allocator);
params.AddMember("pass", rapidjson::StringRef(m_url.password()), allocator);
params.AddMember("agent", rapidjson::StringRef(m_agent), allocator);
params.AddMember("login", rapidjson::StringRef(m_url.user().c_str()), allocator);
params.AddMember("pass", rapidjson::StringRef(m_url.password().c_str()), allocator);
params.AddMember("agent", rapidjson::StringRef(m_agent.c_str()), allocator);
doc.AddMember("params", params, allocator);
@ -404,7 +434,8 @@ void Client::login()
doc.Accept(writer);
const size_t size = buffer.GetSize();
if (size > (sizeof(m_buf) - 2)) {
if(size > (sizeof(m_buf) - 2))
{
return;
}
@ -416,94 +447,117 @@ void Client::login()
}
void Client::parse(char *line, size_t len)
void Client::parse(char* line, size_t len)
{
startTimeout();
line[len - 1] = '\0';
LOG_DEBUG("[%s:%u] received (%d bytes): \"%s\"", m_url.host(), m_url.port(), len, line);
LOG_DEBUG("[" << m_url.host() << ":" << m_url.port() << "] received (" << len << " bytes): \"" << line <<
"\"");
rapidjson::Document doc;
if (doc.ParseInsitu(line).HasParseError()) {
if (!m_quiet) {
LOG_ERR("[%s:%u] JSON decode failed: \"%s\"", m_url.host(), m_url.port(), rapidjson::GetParseError_En(doc.GetParseError()));
if(doc.ParseInsitu(line).HasParseError())
{
if(!m_quiet)
{
LOG_ERR("[" << m_url.host() << ":" << m_url.port() << "] JSON decode failed: \"" <<
rapidjson::GetParseError_En(doc.GetParseError()) << "\"");
}
return;
}
if (!doc.IsObject()) {
if(!doc.IsObject())
{
return;
}
const rapidjson::Value &id = doc["id"];
if (id.IsInt64()) {
const rapidjson::Value & id = doc["id"];
if(id.IsInt64())
{
parseResponse(id.GetInt64(), doc["result"], doc["error"]);
}
else {
else
{
parseNotification(doc["method"].GetString(), doc["params"], doc["error"]);
}
}
void Client::parseNotification(const char *method, const rapidjson::Value &params, const rapidjson::Value &error)
void Client::parseNotification(const char* method, const rapidjson::Value & params,
const rapidjson::Value & error)
{
if (error.IsObject()) {
if (!m_quiet) {
LOG_ERR("[%s:%u] error: \"%s\", code: %d", m_url.host(), m_url.port(), error["message"].GetString(), error["code"].GetInt());
if(error.IsObject())
{
if(!m_quiet)
{
LOG_ERR("[" << m_url.host() << ":" << m_url.port() << "] error: \"" << error["message"].GetString() <<
"\", code: " << error["code"].GetInt());
}
return;
}
if (!method) {
if(!method)
{
return;
}
if (strcmp(method, "job") == 0) {
if(strcmp(method, "job") == 0)
{
int code = -1;
if (parseJob(params, &code)) {
if(parseJob(params, &code))
{
m_listener->onJobReceived(this, m_job);
}
return;
}
LOG_WARN("[%s:%u] unsupported method: \"%s\"", m_url.host(), m_url.port(), method);
LOG_WARN("[" << m_url.host() << ":" << m_url.port() << "] unsupported method: \"" << method << "\"");
}
void Client::parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error)
void Client::parseResponse(int64_t id, const rapidjson::Value & result, const rapidjson::Value & error)
{
if (error.IsObject()) {
const char *message = error["message"].GetString();
if(error.IsObject())
{
const char* message = error["message"].GetString();
auto it = m_results.find(id);
if (it != m_results.end()) {
if(it != m_results.end())
{
it->second.done();
m_listener->onResultAccepted(this, it->second, message);
m_results.erase(it);
}
else if (!m_quiet) {
LOG_ERR("[%s:%u] error: \"%s\", code: %d", m_url.host(), m_url.port(), message, error["code"].GetInt());
else if(!m_quiet)
{
LOG_ERR("[" << m_url.host() << ":" << m_url.port() << "] error: \"" << message << "\", code: " <<
error["code"].GetInt());
}
if (id == 1 || isCriticalError(message)) {
if(id == 1 || isCriticalError(message))
{
close();
}
return;
}
if (!result.IsObject()) {
if(!result.IsObject())
{
return;
}
if (id == 1) {
if(id == 1)
{
int code = -1;
if (!parseLogin(result, &code)) {
if (!m_quiet) {
LOG_ERR("[%s:%u] login error code: %d", m_url.host(), m_url.port(), code);
if(!parseLogin(result, &code))
{
if(!m_quiet)
{
LOG_ERR("[" << m_url.host() << ":" << m_url.port() << "] login error code: " << code);
}
return close();
@ -516,9 +570,10 @@ void Client::parseResponse(int64_t id, const rapidjson::Value &result, const rap
}
auto it = m_results.find(id);
if (it != m_results.end()) {
if(it != m_results.end())
{
it->second.done();
m_listener->onResultAccepted(this, it->second, nullptr);
m_listener->onResultAccepted(this, it->second, "");
m_results.erase(it);
}
}
@ -526,7 +581,9 @@ void Client::parseResponse(int64_t id, const rapidjson::Value &result, const rap
void Client::ping()
{
send(snprintf(m_sendBuf, sizeof(m_sendBuf), "{\"id\":%" PRId64 ",\"jsonrpc\":\"2.0\",\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"}}\n", m_sequence, m_rpcId));
send(snprintf(m_sendBuf, sizeof(m_sendBuf),
"{\"id\":%" PRId64 ",\"jsonrpc\":\"2.0\",\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"}}\n", m_sequence,
m_rpcId));
}
@ -534,13 +591,15 @@ void Client::reconnect()
{
setState(ConnectingState);
# ifndef XMRIG_PROXY_PROJECT
if (m_url.isKeepAlive()) {
#ifndef XMRIG_PROXY_PROJECT
if(m_url.isKeepAlive())
{
uv_timer_stop(&m_keepAliveTimer);
}
# endif
#endif
if (m_failures == -1) {
if(m_failures == -1)
{
return m_listener->onClose(this, -1);
}
@ -553,9 +612,10 @@ void Client::reconnect()
void Client::setState(SocketState state)
{
LOG_DEBUG("[%s:%u] state: %d", m_url.host(), m_url.port(), state);
LOG_DEBUG("[" << m_url.host() << ":" << m_url.port() << "] state: " << state);
if (m_state == state) {
if(m_state == state)
{
return;
}
@ -567,17 +627,22 @@ void Client::startTimeout()
{
m_expire = 0;
# ifndef XMRIG_PROXY_PROJECT
if (!m_url.isKeepAlive()) {
#ifndef XMRIG_PROXY_PROJECT
if(!m_url.isKeepAlive())
{
return;
}
uv_timer_start(&m_keepAliveTimer, [](uv_timer_t *handle) { getClient(handle->data)->ping(); }, kKeepAliveTimeout, 0);
# endif
uv_timer_start(&m_keepAliveTimer, &Client::onTimeout, kKeepAliveTimeout, 0);
#endif
}
void Client::onTimeout(uv_timer_t* handle)
{
getClient(handle->data)->ping();
}
void Client::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf)
void Client::onAllocBuffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf)
{
auto client = getClient(handle->data);
@ -586,7 +651,7 @@ void Client::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t
}
void Client::onClose(uv_handle_t *handle)
void Client::onClose(uv_handle_t* handle)
{
auto client = getClient(handle->data);
@ -600,12 +665,15 @@ void Client::onClose(uv_handle_t *handle)
}
void Client::onConnect(uv_connect_t *req, int status)
void Client::onConnect(uv_connect_t* req, int status)
{
auto client = getClient(req->data);
if (status < 0) {
if (!client->m_quiet) {
LOG_ERR("[%s:%u] connect error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror(status));
if(status < 0)
{
if(!client->m_quiet)
{
LOG_ERR("[" << client->m_url.host() << ":" << client->m_url.port() << "] connect error: \"" << uv_strerror(
status) << "\"");
}
delete req;
@ -623,31 +691,35 @@ void Client::onConnect(uv_connect_t *req, int status)
}
void Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
void Client::onRead(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf)
{
auto client = getClient(stream->data);
if (nread < 0) {
if (nread != UV_EOF && !client->m_quiet) {
LOG_ERR("[%s:%u] read error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror((int) nread));
if(nread < 0)
{
if(nread != UV_EOF && !client->m_quiet)
{
LOG_ERR("[" << client->m_url.host() << ":" << client->m_url.port() << "] read error: \"" << uv_strerror((
int) nread) << "\"");
}
return client->close();
}
if ((size_t) nread > (sizeof(m_buf) - 8 - client->m_recvBufPos)) {
if((size_t) nread > (sizeof(Buf) - 8 - client->m_recvBufPos))
{
return client->close();
}
if (client->state() == ProxingState)
if(client->state() == ProxingState)
{
const char* const content = buf->base;
LOG_DEBUG("[%s:%u] received from proxy (%d bytes): \"%s\"",
client->m_url.host(), client->m_url.port(),
nread, content);
LOG_DEBUG("[" << client->m_url.host() << ":" << client->m_url.port() << "] received from proxy (" << nread <<
" bytes): \"" << content << "\"");
if(content == strstr(content, "HTTP/1.1 200"))
{
LOG_INFO("[%s:%u] Proxy connected to %s:%u!", client->m_url.host(), client->m_url.port(), client->m_url.finalHost(), client->m_url.finalPort());
LOG_INFO("[" << client->m_url.host() << ":" << client->m_url.port() << "] Proxy connected to " <<
client->m_url.finalHost() << ":" << client->m_url.finalPort() << "!");
client->setState(ConnectedState);
client->login();
}
@ -662,10 +734,10 @@ void Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
if(client->m_encrypted)
{
char * read_encr_hex = static_cast<char*>(malloc(nread * 2 + 1));
char* read_encr_hex = static_cast<char*>(malloc(nread * 2 + 1));
memset(read_encr_hex, 0, nread * 2 + 1);
Job::toHex((const unsigned char*)start, nread, read_encr_hex);
LOG_DEBUG("[%s] read encr. (%d bytes): \"0x%s\"", client->m_ip, nread, read_encr_hex);
Job::toHex(std::string(start, nread), read_encr_hex);
LOG_DEBUG("[" << client->m_ip << "] read encr. (" << nread << " bytes): 0x\"" << read_encr_hex << "\"");
free(read_encr_hex);
// DeEncrypt
@ -675,7 +747,8 @@ void Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
}
}
while ((end = static_cast<char*>(memchr(start, '\n', remaining))) != nullptr) {
while((end = static_cast<char*>(memchr(start, '\n', remaining))) != nullptr)
{
end++;
size_t len = end - start;
client->parse(start, len);
@ -684,12 +757,14 @@ void Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
start = end;
}
if (remaining == 0) {
if(remaining == 0)
{
client->m_recvBufPos = 0;
return;
}
if (start == buf->base) {
if(start == buf->base)
{
return;
}
@ -698,33 +773,41 @@ void Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
}
void Client::onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res)
void Client::onResolved(uv_getaddrinfo_t* req, int status, struct addrinfo* res)
{
auto client = getClient(req->data);
if (status < 0) {
LOG_ERR("[%s:%u] DNS error: \"%s\"", client->m_url.host(), client->m_url.port(), uv_strerror(status));
if(status < 0)
{
LOG_ERR("[" << client->m_url.host() << ":" << client->m_url.port() << "] DNS error: \"" << uv_strerror(
status) << "\"");
return client->reconnect();
}
addrinfo *ptr = res;
addrinfo* ptr = res;
std::vector<addrinfo*> ipv4;
while (ptr != nullptr) {
if (ptr->ai_family == AF_INET) {
while(ptr != nullptr)
{
if(ptr->ai_family == AF_INET)
{
ipv4.push_back(ptr);
}
ptr = ptr->ai_next;
}
if (ipv4.empty()) {
LOG_ERR("[%s:%u] DNS error: \"No IPv4 records found\"", client->m_url.host(), client->m_url.port());
if(ipv4.empty())
{
LOG_ERR("[" << client->m_url.host() << ":" << client->m_url.port() <<
"] DNS error: \"No IPv4 records found\"");
return client->reconnect();
}
ptr = ipv4[rand() % ipv4.size()];
uv_ip4_name(reinterpret_cast<sockaddr_in*>(ptr->ai_addr), client->m_ip, 16);
char buf[16];
uv_ip4_name(reinterpret_cast<sockaddr_in*>(ptr->ai_addr), buf, sizeof(buf));
client->setIP(buf);
client->connect(ptr->ai_addr);
uv_freeaddrinfo(res);

View file

@ -42,7 +42,8 @@ class JobResult;
class Client
{
public:
enum SocketState {
enum SocketState
{
UnconnectedState,
HostLookupState,
ConnectingState,
@ -51,65 +52,106 @@ public:
ClosingState
};
constexpr static int kResponseTimeout = 20 * 1000;
constexpr static int kKeepAliveTimeout = 60 * 1000;
enum
{
kResponseTimeout = 20 * 1000,
kKeepAliveTimeout = 60 * 1000,
};
Client(int id, const char *agent, IClientListener *listener);
Client(int id, const std::string & agent, IClientListener* listener);
~Client();
int64_t submit(const JobResult &result);
int64_t submit(const JobResult & result);
void connect();
void connect(const Url *url);
void connect(const Url & url);
void disconnect();
void setUrl(const Url *url);
void setUrl(const Url & url);
void tick(uint64_t now);
inline bool isReady() const { return m_state == ConnectedState && m_failures == 0; }
inline const char *host() const { return m_url.host(); }
inline const char *ip() const { return m_ip; }
inline const Job &job() const { return m_job; }
inline int id() const { return m_id; }
inline SocketState state() const { return m_state; }
inline uint16_t port() const { return m_url.port(); }
inline void setQuiet(bool quiet) { m_quiet = quiet; }
inline void setRetryPause(int ms) { m_retryPause = ms; }
inline bool isReady() const
{
return m_state == ConnectedState && m_failures == 0;
}
inline const std::string & host() const
{
return m_url.host();
}
inline const std::string & ip() const
{
return m_ip;
}
inline void setIP(const std::string & iIp)
{
m_ip = iIp;
}
inline const Job & job() const
{
return m_job;
}
inline int id() const
{
return m_id;
}
inline SocketState state() const
{
return m_state;
}
inline uint16_t port() const
{
return m_url.port();
}
inline void setQuiet(bool quiet)
{
m_quiet = quiet;
}
inline void setRetryPause(int ms)
{
m_retryPause = ms;
}
private:
bool isCriticalError(const char *message);
bool parseJob(const rapidjson::Value &params, int *code);
bool parseLogin(const rapidjson::Value &result, int *code);
int resolve(const char *host);
bool isCriticalError(const std::string & message);
bool parseJob(const rapidjson::Value & params, int* code);
bool parseLogin(const rapidjson::Value & result, int* code);
int resolve(const std::string & host);
int64_t send(size_t size, const bool encrypted = true);
void close();
void connect(struct sockaddr *addr);
void connect(struct sockaddr* addr);
void prelogin();
void login();
void parse(char *line, size_t len);
void parseNotification(const char *method, const rapidjson::Value &params, const rapidjson::Value &error);
void parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error);
void parse(char* line, size_t len);
void parseNotification(const char* method, const rapidjson::Value & params, const rapidjson::Value & error);
void parseResponse(int64_t id, const rapidjson::Value & result, const rapidjson::Value & error);
void ping();
void reconnect();
void setState(SocketState state);
void startTimeout();
static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);
static void onClose(uv_handle_t *handle);
static void onConnect(uv_connect_t *req, int status);
static void onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf);
static void onResolved(uv_getaddrinfo_t *req, int status, struct addrinfo *res);
static void onAllocBuffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf);
static void onClose(uv_handle_t* handle);
static void onConnect(uv_connect_t* req, int status);
static void onTimeout(uv_timer_t* handle);
static void onRead(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf);
static void onResolved(uv_getaddrinfo_t* req, int status, struct addrinfo* res);
static inline Client *getClient(void *data) { return static_cast<Client*>(data); }
static inline Client* getClient(void* data)
{
return static_cast<Client*>(data);
}
typedef char Buf[2048];
typedef char SendBuf[768];
addrinfo m_hints;
bool m_quiet;
char m_buf[2048];
char m_ip[17];
char m_buf[sizeof(Buf)];
std::string m_ip;
char m_rpcId[64];
char m_sendBuf[768];
char m_keystream[sizeof(m_sendBuf)];
char m_sendBuf[sizeof(SendBuf)];
char m_keystream[sizeof(SendBuf)];
bool m_encrypted;
const char *m_agent;
IClientListener *m_listener;
const std::string & m_agent;
IClientListener* m_listener;
int m_id;
int m_retryPause;
int64_t m_failures;
@ -122,12 +164,12 @@ private:
Url m_url;
uv_buf_t m_recvBuf;
uv_getaddrinfo_t m_resolver;
uv_stream_t *m_stream;
uv_tcp_t *m_socket;
uv_stream_t* m_stream;
uv_tcp_t* m_socket;
# ifndef XMRIG_PROXY_PROJECT
#ifndef XMRIG_PROXY_PROJECT
uv_timer_t m_keepAliveTimer;
# endif
#endif
};

View file

@ -28,15 +28,18 @@
#include "net/Job.h"
static inline unsigned char hf_hex2bin(char c, bool &err)
static inline unsigned char hf_hex2bin(char c, bool & err)
{
if (c >= '0' && c <= '9') {
if(c >= '0' && c <= '9')
{
return c - '0';
}
else if (c >= 'a' && c <= 'f') {
else if(c >= 'a' && c <= 'f')
{
return c - 'a' + 0xA;
}
else if (c >= 'A' && c <= 'F') {
else if(c >= 'A' && c <= 'F')
{
return c - 'A' + 0xA;
}
@ -47,7 +50,8 @@ static inline unsigned char hf_hex2bin(char c, bool &err)
static inline char hf_bin2hex(unsigned char c)
{
if (c <= 0x9) {
if(c <= 0x9)
{
return '0' + c;
}
@ -59,6 +63,7 @@ Job::Job(int poolId, bool nicehash) :
m_nicehash(nicehash),
m_poolId(poolId),
m_threadId(-1),
m_id(),
m_size(0),
m_diff(0),
m_target(0)
@ -71,75 +76,86 @@ Job::~Job()
}
bool Job::setBlob(const char *blob)
bool Job::setBlob(const char* blob)
{
if (!blob) {
if(!blob)
{
return false;
}
m_size = strlen(blob);
if (m_size % 2 != 0) {
if(m_size % 2 != 0)
{
return false;
}
m_size /= 2;
if (m_size < 76 || m_size >= sizeof(m_blob)) {
if(m_size < 76 || m_size >= sizeof(m_blob))
{
return false;
}
if (!fromHex(blob, (int) m_size * 2, m_blob)) {
if(!fromHex(blob, (int) m_size * 2, m_blob))
{
return false;
}
if (*nonce() != 0 && !m_nicehash) {
if(*nonce() != 0 && !m_nicehash)
{
m_nicehash = true;
}
# ifdef XMRIG_PROXY_PROJECT
#ifdef XMRIG_PROXY_PROJECT
memset(m_rawBlob, 0, sizeof(m_rawBlob));
memcpy(m_rawBlob, blob, m_size * 2);
# endif
#endif
return true;
}
bool Job::setTarget(const char *target)
bool Job::setTarget(const char* target)
{
if (!target) {
if(!target)
{
return false;
}
const size_t len = strlen(target);
if (len <= 8) {
if(len <= 8)
{
uint32_t tmp = 0;
char str[8];
memcpy(str, target, len);
if (!fromHex(str, 8, reinterpret_cast<unsigned char*>(&tmp)) || tmp == 0) {
if(!fromHex(str, 8, reinterpret_cast<unsigned char*>(&tmp)) || tmp == 0)
{
return false;
}
m_target = 0xFFFFFFFFFFFFFFFFULL / (0xFFFFFFFFULL / static_cast<uint64_t>(tmp));
}
else if (len <= 16) {
else if(len <= 16)
{
m_target = 0;
char str[16];
memcpy(str, target, len);
if (!fromHex(str, 16, reinterpret_cast<unsigned char*>(&m_target)) || m_target == 0) {
if(!fromHex(str, 16, reinterpret_cast<unsigned char*>(&m_target)) || m_target == 0)
{
return false;
}
}
else {
else
{
return false;
}
# ifdef XMRIG_PROXY_PROJECT
#ifdef XMRIG_PROXY_PROJECT
memset(m_rawTarget, 0, sizeof(m_rawTarget));
memcpy(m_rawTarget, target, len);
# endif
#endif
m_diff = toDiff(m_target);
return true;
@ -149,10 +165,12 @@ bool Job::setTarget(const char *target)
bool Job::fromHex(const char* in, unsigned int len, unsigned char* out)
{
bool error = false;
for (unsigned int i = 0; i < len; i += 2) {
for(unsigned int i = 0; i < len; i += 2)
{
out[i / 2] = (hf_hex2bin(in[i], error) << 4) | hf_hex2bin(in[i + 1], error);
if (error) {
if(error)
{
return false;
}
}
@ -160,16 +178,17 @@ bool Job::fromHex(const char* in, unsigned int len, unsigned char* out)
}
void Job::toHex(const unsigned char* in, unsigned int len, char* out)
void Job::toHex(const std::string & in, char* out)
{
for (unsigned int i = 0; i < len; i++) {
for(size_t i = 0; i < in.size(); ++i)
{
out[i * 2] = hf_bin2hex((in[i] & 0xF0) >> 4);
out[i * 2 + 1] = hf_bin2hex(in[i] & 0x0F);
}
}
bool Job::operator==(const Job &other) const
bool Job::operator==(const Job & other) const
{
return m_id == other.m_id && memcmp(m_blob, other.m_blob, sizeof(m_blob)) == 0;
}

View file

@ -27,6 +27,7 @@
#include <stddef.h>
#include <stdint.h>
#include <string>
#include "align.h"
@ -39,38 +40,93 @@ public:
Job(int poolId = -2, bool nicehash = false);
~Job();
bool setBlob(const char *blob);
bool setTarget(const char *target);
bool setBlob(const char* blob);
bool setTarget(const char* target);
inline bool isNicehash() const { return m_nicehash; }
inline bool isValid() const { return m_size > 0 && m_diff > 0; }
inline bool setId(const char *id) { return m_id.setId(id); }
inline const JobId &id() const { return m_id; }
inline const uint32_t *nonce() const { return reinterpret_cast<const uint32_t*>(m_blob + 39); }
inline const uint8_t *blob() const { return m_blob; }
inline int poolId() const { return m_poolId; }
inline int threadId() const { return m_threadId; }
inline size_t size() const { return m_size; }
inline uint32_t *nonce() { return reinterpret_cast<uint32_t*>(m_blob + 39); }
inline uint32_t diff() const { return (uint32_t) m_diff; }
inline uint64_t target() const { return m_target; }
inline void setNicehash(bool nicehash) { m_nicehash = nicehash; }
inline void setThreadId(int threadId) { m_threadId = threadId; }
inline bool isNicehash() const
{
return m_nicehash;
}
inline bool isValid() const
{
return m_size > 0 && m_diff > 0;
}
inline bool setId(const std::string & id)
{
return m_id.setId(id);
}
inline const JobId & id() const
{
return m_id;
}
inline const uint32_t* nonce() const
{
return reinterpret_cast<const uint32_t*>(m_blob + 39);
}
inline const uint8_t* blob() const
{
return m_blob;
}
inline int poolId() const
{
return m_poolId;
}
inline int threadId() const
{
return m_threadId;
}
inline size_t size() const
{
return m_size;
}
inline uint32_t* nonce()
{
return reinterpret_cast<uint32_t*>(m_blob + 39);
}
inline uint32_t diff() const
{
return (uint32_t) m_diff;
}
inline uint64_t target() const
{
return m_target;
}
inline void setNicehash(bool nicehash)
{
m_nicehash = nicehash;
}
inline void setThreadId(int threadId)
{
m_threadId = threadId;
}
# ifdef XMRIG_PROXY_PROJECT
inline char *rawBlob() { return m_rawBlob; }
inline const char *rawTarget() const { return m_rawTarget; }
# endif
#ifdef XMRIG_PROXY_PROJECT
inline char* rawBlob()
{
return m_rawBlob;
}
inline const char* rawTarget() const
{
return m_rawTarget;
}
#endif
static bool fromHex(const char* in, unsigned int len, unsigned char* out);
static inline uint32_t *nonce(uint8_t *blob) { return reinterpret_cast<uint32_t*>(blob + 39); }
static inline uint64_t toDiff(uint64_t target) { return 0xFFFFFFFFFFFFFFFFULL / target; }
static void toHex(const unsigned char* in, unsigned int len, char* out);
static inline uint32_t* nonce(uint8_t* blob)
{
return reinterpret_cast<uint32_t*>(blob + 39);
}
static inline uint64_t toDiff(uint64_t target)
{
return 0xFFFFFFFFFFFFFFFFULL / target;
}
static void toHex(const std::string & in, char* out);
bool operator==(const Job &other) const;
bool operator==(const Job & other) const;
private:
VAR_ALIGN(16, uint8_t m_blob[84]); // Max blob size is 84 (75 fixed + 9 variable), aligned to 96. https://github.com/xmrig/xmrig/issues/1 Thanks fireice-uk.
VAR_ALIGN(16, uint8_t
m_blob[84]); // Max blob size is 84 (75 fixed + 9 variable), aligned to 96. https://github.com/xmrig/xmrig/issues/1 Thanks fireice-uk.
bool m_nicehash;
int m_poolId;
@ -80,10 +136,10 @@ private:
uint64_t m_diff;
uint64_t m_target;
# ifdef XMRIG_PROXY_PROJECT
#ifdef XMRIG_PROXY_PROJECT
VAR_ALIGN(16, char m_rawBlob[169]);
VAR_ALIGN(16, char m_rawTarget[17]);
# endif
#endif
};
#endif /* __JOB_H__ */

View file

@ -33,51 +33,48 @@ class JobId
public:
inline JobId()
{
memset(m_data, 0, sizeof(m_data));
}
inline JobId(const char *id, size_t sizeFix = 0)
inline JobId(const std::string & id, size_t sizeFix = 0)
{
setId(id, sizeFix);
}
inline bool operator==(const JobId &other) const
inline bool operator==(const JobId & other) const
{
return memcmp(m_data, other.m_data, sizeof(m_data)) == 0;
return m_data == other.m_data;
}
inline bool operator!=(const JobId &other) const
inline bool operator!=(const JobId & other) const
{
return memcmp(m_data, other.m_data, sizeof(m_data)) != 0;
return !operator!=(other);
}
inline bool setId(const char *id, size_t sizeFix = 0)
inline bool setId(const std::string & id, size_t sizeFix = 0)
{
m_data.clear();
if(id.empty())
{
memset(m_data, 0, sizeof(m_data));
if (!id) {
return false;
}
const size_t size = strlen(id);
if (size >= sizeof(m_data)) {
return false;
}
memcpy(m_data, id, size - sizeFix);
const size_t size = id.size();
m_data = id.substr(0, size - sizeFix);
return true;
}
inline const char *data() const { return m_data; }
inline bool isValid() const { return *m_data != '\0'; }
inline const std::string & data() const
{
return m_data;
}
inline bool isValid() const
{
return 0 < m_data.size() && m_data[0] != '\0';
}
private:
char m_data[64];
std::string m_data;
};
#endif /* __JOBID_H__ */

View file

@ -44,7 +44,7 @@
#include "workers/Workers.h"
Network::Network(const Options *options) :
Network::Network(const Options* options) :
m_options(options),
m_donate(nullptr)
{
@ -52,16 +52,19 @@ Network::Network(const Options *options) :
Workers::setListener(this);
const std::vector<Url*> &pools = options->pools();
const std::vector<Url> & pools = options->pools();
if (pools.size() > 1) {
if(pools.size() > 1)
{
m_strategy = new FailoverStrategy(pools, Platform::userAgent(), this);
}
else {
else
{
m_strategy = new SinglePoolStrategy(pools.front(), Platform::userAgent(), this);
}
if (m_options->donateLevel() > 0) {
if(m_options->donateLevel() > 0)
{
m_donate = new DonateStrategy(Platform::userAgent(), this);
}
@ -85,7 +88,8 @@ void Network::connect()
void Network::stop()
{
if (m_donate) {
if(m_donate)
{
m_donate->stop();
}
@ -93,22 +97,24 @@ void Network::stop()
}
void Network::onActive(Client *client)
void Network::onActive(Client* client)
{
if (client->id() == -1) {
if(client->id() == -1)
{
LOG_NOTICE("dev donate started");
return;
}
m_state.setPool(client->host(), client->port(), client->ip());
LOG_INFO(m_options->colors() ? "\x1B[01;37muse pool \x1B[01;36m%s:%d \x1B[01;30m%s" : "use pool %s:%d %s", client->host(), client->port(), client->ip());
LOG_INFO("use pool " << client->host() << ":" << client->port() << " " << client->ip());
}
void Network::onJob(Client *client, const Job &job)
void Network::onJob(Client* client, const Job & job)
{
if (m_donate && m_donate->isActive() && client->id() != -1) {
if(m_donate && m_donate->isActive() && client->id() != -1)
{
return;
}
@ -116,9 +122,10 @@ void Network::onJob(Client *client, const Job &job)
}
void Network::onJobResult(const JobResult &result)
void Network::onJobResult(const JobResult & result)
{
if (result.poolId == -1 && m_donate) {
if(result.poolId == -1 && m_donate)
{
m_donate->submit(result);
return;
}
@ -127,14 +134,16 @@ void Network::onJobResult(const JobResult &result)
}
void Network::onPause(IStrategy *strategy)
void Network::onPause(IStrategy* strategy)
{
if (m_donate && m_donate == strategy) {
if(m_donate && m_donate == strategy)
{
LOG_NOTICE("dev donate finished");
m_strategy->resume();
}
if (!m_strategy->isActive()) {
if(!m_strategy->isActive())
{
LOG_ERR("no active pools, stop mining");
m_state.stop();
return Workers::pause();
@ -142,30 +151,35 @@ void Network::onPause(IStrategy *strategy)
}
void Network::onResultAccepted(Client *client, const SubmitResult &result, const char *error)
void Network::onResultAccepted(Client* client, const SubmitResult & result, const std::string & error)
{
m_state.add(result, error);
if (error) {
LOG_INFO(m_options->colors() ? "\x1B[01;31mrejected\x1B[0m (%" PRId64 "/%" PRId64 ") diff \x1B[01;37m%u\x1B[0m \x1B[31m\"%s\"\x1B[0m \x1B[01;30m(%" PRIu64 " ms)"
: "rejected (%" PRId64 "/%" PRId64 ") diff %u \"%s\" (%" PRIu64 " ms)",
m_state.accepted, m_state.rejected, result.diff, error, result.elapsed);
if(0 < error.size())
{
LOG_INFO("rejected (" << m_state.accepted << "/" << m_state.rejected << ") diff " << result.diff << " \"" <<
error << "\" (" << result.elapsed << " ms)");
}
else {
LOG_INFO(m_options->colors() ? "\x1B[01;32maccepted\x1B[0m (%" PRId64 "/%" PRId64 ") diff \x1B[01;37m%u\x1B[0m \x1B[01;30m(%" PRIu64 " ms)"
: "accepted (%" PRId64 "/%" PRId64 ") diff %u (%" PRIu64 " ms)",
m_state.accepted, m_state.rejected, result.diff, result.elapsed);
else
{
LOG_INFO("accepted (" << m_state.accepted << "/" << m_state.rejected << ") diff " << result.diff << " (" <<
result.elapsed << " ms)");
}
}
void Network::setJob(Client *client, const Job &job)
void Network::setJob(Client* client, const Job & job)
{
if (m_options->colors()) {
LOG_INFO("\x1B[01;35mnew job\x1B[0m from \x1B[01;37m%s:%d\x1B[0m diff \x1B[01;37m%d", client->host(), client->port(), job.diff());
if(m_options->colors())
{
/*
LOG_INFO("\x1B[01;35mnew job\x1B[0m from \x1B[01;37m%s:%d\x1B[0m diff \x1B[01;37m%d", client->host(),
client->port(), job.diff());
*/
}
else {
LOG_INFO("new job from %s:%d diff %d", client->host(), client->port(), job.diff());
else
{
LOG_INFO("new job from " << client->host() << ":" << client->port() << " diff " << job.diff());
}
m_state.diff = job.diff();
@ -179,7 +193,8 @@ void Network::tick()
m_strategy->tick(now);
if (m_donate) {
if(m_donate)
{
m_donate->tick(now);
}
@ -189,7 +204,7 @@ void Network::tick()
}
void Network::onTick(uv_timer_t *handle)
void Network::onTick(uv_timer_t* handle)
{
static_cast<Network*>(handle->data)->tick();
}

View file

@ -42,30 +42,33 @@ class Url;
class Network : public IJobResultListener, public IStrategyListener
{
public:
Network(const Options *options);
Network(const Options* options);
~Network();
void connect();
void stop();
protected:
void onActive(Client *client) override;
void onJob(Client *client, const Job &job) override;
void onJobResult(const JobResult &result) override;
void onPause(IStrategy *strategy) override;
void onResultAccepted(Client *client, const SubmitResult &result, const char *error) override;
void onActive(Client* client) override;
void onJob(Client* client, const Job & job) override;
void onJobResult(const JobResult & result) override;
void onPause(IStrategy* strategy) override;
void onResultAccepted(Client* client, const SubmitResult & result, const std::string & error) override;
private:
constexpr static int kTickInterval = 1 * 1000;
enum
{
kTickInterval = 1 * 1000
};
void setJob(Client *client, const Job &job);
void setJob(Client* client, const Job & job);
void tick();
static void onTick(uv_timer_t *handle);
static void onTick(uv_timer_t* handle);
const Options *m_options;
IStrategy *m_donate;
IStrategy *m_strategy;
const Options* m_options;
IStrategy* m_donate;
IStrategy* m_strategy;
NetworkState m_state;
uv_timer_t m_timer;
};

View file

@ -21,34 +21,64 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <algorithm>
#include "net/Url.h"
#ifdef _MSC_VER
# define strncasecmp(x,y,z) _strnicmp(x,y,z)
#define strncasecmp(x,y,z) _strnicmp(x,y,z)
#endif
Url::Url() :
m_keepAlive(false),
Url::Url()
: m_keepAlive(false),
m_nicehash(false),
m_host(nullptr),
m_password(nullptr),
m_user(nullptr),
m_host(),
m_password(),
m_user(),
m_port(kDefaultPort),
m_proxy_host(nullptr),
m_proxy_host(),
m_proxy_port(kDefaultProxyPort),
m_keystream(nullptr)
m_keystream()
{
}
Url::Url(const std::string & url)
: m_keepAlive(false),
m_nicehash(false),
m_host(),
m_password(),
m_user(),
m_port(kDefaultPort),
m_proxy_host(),
m_proxy_port(kDefaultProxyPort),
m_keystream()
{
parse(url);
}
Url::Url(const std::string & host,
uint16_t port,
const std::string & user,
const std::string & password,
bool keepAlive,
bool nicehash)
: m_keepAlive(keepAlive),
m_nicehash(nicehash),
m_host(host),
m_password(password),
m_user(user),
m_port(port),
m_proxy_host(),
m_proxy_port(kDefaultProxyPort),
m_keystream()
{
}
Url::~Url()
{
}
/**
* @brief Parse url.
@ -56,132 +86,114 @@ Url::Url() :
* Valid urls:
* example.com
* example.com:3333
* example.com:3333#keystream
* example.com:3333@proxy
* example.com:3333@proxy:8080
* example.com:3333#keystream@proxy
* example.com:3333#keystream@proxy:8080
* stratum+tcp://example.com
* stratum+tcp://example.com:3333
* stratum+tcp://example.com:3333#keystream
* stratum+tcp://example.com:3333@proxy
* stratum+tcp://example.com:3333@proxy:8080
* stratum+tcp://example.com:3333#keystream@proxy
* stratum+tcp://example.com:3333#keystream@proxy:8080
*
* @param url
*/
Url::Url(const char *url) :
m_keepAlive(false),
m_nicehash(false),
m_host(nullptr),
m_password(nullptr),
m_user(nullptr),
m_port(kDefaultPort),
m_proxy_host(nullptr),
m_proxy_port(kDefaultProxyPort),
m_keystream(nullptr)
bool Url::parse(const std::string & url)
{
parse(url);
}
size_t base = 0;
Url::Url(const char *host, uint16_t port, const char *user, const char *password, bool keepAlive, bool nicehash) :
m_keepAlive(keepAlive),
m_nicehash(nicehash),
m_password(password ? strdup(password) : nullptr),
m_user(user ? strdup(user) : nullptr),
m_port(port),
m_proxy_host(nullptr),
m_proxy_port(kDefaultProxyPort),
m_keystream(nullptr)
{
m_host = strdup(host);
}
Url::~Url()
{
free(m_host);
free(m_password);
free(m_user);
free(m_proxy_host);
free(m_keystream);
}
bool Url::parse(const char *url)
{
const char *p = strstr(url, "://");
const char *base = url;
if (p) {
if (strncasecmp(url, "stratum+tcp://", 14)) {
return false;
}
base = url + 14;
}
if (!strlen(base) || *base == '/') {
return false;
}
const char *port = strchr(base, ':');
if (!port) {
m_host = strdup(base);
return false;
}
const size_t size = port++ - base + 1;
m_host = static_cast<char*>(malloc(size));
memcpy(m_host, base, size - 1);
m_host[size - 1] = '\0';
const char* proxy = strchr(port, '@');
const char* keystream = strchr(port, '#');
if(keystream)
const size_t p = url.find("://");
if(p != std::string::npos)
{
++keystream;
if(!proxy)
static const std::string STRATUM_PREFIX = "stratum+tcp://";
if(strncasecmp(url.c_str(), STRATUM_PREFIX.c_str(), STRATUM_PREFIX.size()))
{
m_keystream = strdup(keystream);
return false;
}
base = STRATUM_PREFIX.size();
}
const std::string path = url.substr(base);
if(path.empty() || path[0] == '/')
{
return false;
}
const size_t port = path.find_first_of(':');
size_t portini = port;
if(port != std::string::npos)
{
m_host = path.substr(0, port);
m_port = (uint16_t) strtol(path.substr(port + 1).c_str(), nullptr, 10);
}
else
{
const size_t keystreamsize = proxy - keystream;
m_keystream = static_cast<char*>(malloc (keystreamsize + 1));
m_keystream[keystreamsize] = '\0';
memcpy(m_keystream, keystream, keystreamsize);
portini = 0;
}
const size_t proxy = path.find_first_of('@', portini);
const size_t keystream = path.find_first_of('#', portini);
if(keystream != std::string::npos)
{
if(port == std::string::npos)
{
m_host = path.substr(0, keystream);
}
if(proxy != std::string::npos)
{
m_keystream = path.substr(keystream + 1, proxy - keystream - 1);
}
else
{
m_keystream = path.substr(keystream + 1);
}
}
m_port = (uint16_t) strtol(port, nullptr, 10);
if (!proxy) {
m_port = (uint16_t) strtol(port, nullptr, 10);
if(proxy == std::string::npos)
{
if(port == std::string::npos && keystream == std::string::npos)
{
m_host = path;
}
return true;
}
else
{
if(port == std::string::npos && keystream == std::string::npos)
{
m_host = path.substr(0, proxy);
}
}
++proxy;
const size_t proxyini = proxy + 1;
const char* proxyport = strchr(proxy, ':');
if (!port) {
m_proxy_host = strdup(proxy);
const size_t proxyport = path.find_first_of(':', proxyini);
if(proxyport == std::string::npos)
{
m_proxy_host = path.substr(proxyini);
return false;
}
const size_t proxysize = proxyport++ - proxy + 1;
m_proxy_host = static_cast<char*>(malloc (proxysize));
memcpy(m_proxy_host, proxy, proxysize - 1);
m_proxy_host[proxysize - 1] = '\0';
m_proxy_port = (uint16_t) strtol(proxyport, nullptr, 10);
m_proxy_host = path.substr(proxyini, proxyport - proxyini);
m_proxy_port = (uint16_t) strtol(path.substr(proxyport + 1).c_str(), nullptr, 10);
return true;
}
bool Url::setUserpass(const char *userpass)
bool Url::setUserpass(const std::string & userpass)
{
const char *p = strchr(userpass, ':');
if (!p) {
const size_t p = userpass.find_first_of(':');
if(p == std::string::npos)
{
return false;
}
free(m_user);
free(m_password);
m_user = static_cast<char*>(calloc(p - userpass + 1, 1));
strncpy(m_user, userpass, p - userpass);
m_password = strdup(p + 1);
m_user = userpass.substr(0, p);
m_password = userpass.substr(p + 1);
return true;
}
@ -189,82 +201,55 @@ bool Url::setUserpass(const char *userpass)
void Url::applyExceptions()
{
if (!isValid()) {
if(!isValid())
{
return;
}
if (strstr(m_host, ".nicehash.com")) {
if(m_host.find(".nicehash.com") != std::string::npos)
{
m_keepAlive = false;
m_nicehash = true;
}
if (strstr(m_host, ".minergate.com")) {
if(m_host.find(".minergate.com") != std::string::npos)
{
m_keepAlive = false;
}
}
void Url::setPassword(const char *password)
{
if (!password) {
return;
}
free(m_password);
m_password = strdup(password);
void Url::setPassword(const std::string & password)
{
m_password = password;
}
void Url::setUser(const char *user)
void Url::setUser(const std::string & user)
{
if (!user) {
return;
}
free(m_user);
m_user = strdup(user);
m_user = user;
}
void Url::copyKeystream(char *keystreamDest, const size_t keystreamLen) const
void Url::copyKeystream(char* keystreamDest, const size_t keystreamLen) const
{
if(hasKeystream())
{
memset(keystreamDest, 1, keystreamLen);
memcpy(keystreamDest, m_keystream, std::min(keystreamLen, strlen(m_keystream)));
memcpy(keystreamDest, m_keystream.c_str(), std::min(keystreamLen, m_keystream.size()));
}
}
Url &Url::operator=(const Url *other)
Url & Url::operator=(const Url* other)
{
m_keepAlive = other->m_keepAlive;
m_nicehash = other->m_nicehash;
m_port = other->m_port;
m_proxy_port = other->m_proxy_port;
m_host = other->m_host;
m_proxy_host = other->m_proxy_host;
m_password = other->m_password;
m_user = other->m_user;
m_keystream = other->m_keystream;
free(m_host);
m_host = strdup(other->m_host);
free (m_proxy_host);
if(other->m_proxy_host)
{
m_proxy_host = strdup (other->m_proxy_host);
}
else
{
m_proxy_host = nullptr;
}
setPassword(other->m_password);
setUser(other->m_user);
free (m_keystream);
if(other->m_keystream)
{
m_keystream = strdup (other->m_keystream);
}
else
{
m_keystream = nullptr;
}
return *this;
}

View file

@ -24,58 +24,117 @@
#ifndef __URL_H__
#define __URL_H__
#include <stdint.h>
#include <string>
class Url
{
public:
constexpr static const char *kDefaultPassword = "x";
constexpr static const char *kDefaultUser = "x";
constexpr static uint16_t kDefaultPort = 3333;
constexpr static uint16_t kDefaultProxyPort = 8080;
static const std::string & DefaultPassword()
{
static const std::string kDefaultPassword = "x";
return kDefaultPassword;
}
static const std::string & DefaultUser()
{
static const std::string kDefaultUser = "x";
return kDefaultUser;
}
enum
{
kDefaultPort = 3333,
kDefaultProxyPort = 8080,
};
Url();
Url(const char *url);
Url(const char *host, uint16_t port, const char *user = nullptr, const char *password = nullptr, bool keepAlive = false, bool nicehash = false );
Url(const std::string & url);
Url(const std::string & host, uint16_t port, const std::string & user = "",
const std::string & password = "",
bool keepAlive = false, bool nicehash = false);
~Url();
inline bool isKeepAlive() const { return m_keepAlive; }
inline bool isNicehash() const { return m_nicehash; }
inline bool isValid() const { return m_host && m_port > 0; }
inline bool hasKeystream() const { return m_keystream; }
inline const char *host() const { return isProxyed() ? proxyHost() : finalHost(); }
inline const char *password() const { return m_password ? m_password : kDefaultPassword; }
inline const char *user() const { return m_user ? m_user : kDefaultUser; }
inline uint16_t port() const { return isProxyed() ? proxyPort() : finalPort(); }
inline bool isProxyed() const { return proxyHost(); }
inline const char* finalHost() const { return m_host; }
inline uint16_t finalPort() const { return m_port; }
inline const char* proxyHost() const { return m_proxy_host; }
inline uint16_t proxyPort() const { return m_proxy_port; }
inline void setKeepAlive(bool keepAlive) { m_keepAlive = keepAlive; }
inline void setNicehash(bool nicehash) { m_nicehash = nicehash; }
inline bool isKeepAlive() const
{
return m_keepAlive;
}
inline bool isNicehash() const
{
return m_nicehash;
}
inline bool isValid() const
{
return m_host.size() > 0 && m_port > 0;
}
inline bool hasKeystream() const
{
return m_keystream.size() > 0;
}
inline const std::string & host() const
{
return isProxyed() ? proxyHost() : finalHost();
}
inline const std::string & password() const
{
return m_password.empty() ? DefaultPassword() : m_password;
}
inline const std::string & user() const
{
return m_user.empty() ? DefaultUser() : m_user;
}
inline uint16_t port() const
{
return isProxyed() ? proxyPort() : finalPort();
}
inline bool isProxyed() const
{
return proxyHost().size() > 0;
}
inline const std::string & finalHost() const
{
return m_host;
}
inline uint16_t finalPort() const
{
return m_port;
}
inline const std::string & proxyHost() const
{
return m_proxy_host;
}
inline uint16_t proxyPort() const
{
return m_proxy_port;
}
inline void setKeepAlive(bool keepAlive)
{
m_keepAlive = keepAlive;
}
inline void setNicehash(bool nicehash)
{
m_nicehash = nicehash;
}
bool parse(const char *url);
bool setUserpass(const char *userpass);
bool parse(const std::string & url);
bool setUserpass(const std::string & userpass);
void applyExceptions();
void setPassword(const char *password);
void setUser(const char *user);
void copyKeystream(char *keystreamDest, const size_t keystreamLen) const;
void setPassword(const std::string & password);
void setUser(const std::string & user);
void copyKeystream(char* keystreamDest, const size_t keystreamLen) const;
Url &operator=(const Url *other);
Url & operator=(const Url* other);
private:
bool m_keepAlive;
bool m_nicehash;
char *m_host;
char *m_password;
char *m_user;
std::string m_host;
std::string m_password;
std::string m_user;
uint16_t m_port;
char* m_proxy_host;
std::string m_proxy_host;
uint16_t m_proxy_port;
char* m_keystream;
std::string m_keystream;
};
#endif /* __URL_H__ */

View file

@ -24,7 +24,6 @@
#include "interfaces/IStrategyListener.h"
#include "net/Client.h"
#include "net/Job.h"
#include "net/strategies/DonateStrategy.h"
#include "Options.h"
@ -34,37 +33,58 @@ extern "C"
#include "crypto/c_keccak.h"
}
static inline int random(int min, int max)
{
return min + rand() / (RAND_MAX / (max - min + 1) + 1);
}
DonateStrategy::DonateStrategy(const char *agent, IStrategyListener *listener) :
DonateStrategy::DonateStrategy(const std::string & agent, IStrategyListener* listener) :
m_active(false),
m_donateTime(Options::i()->donateLevel() * 60 * 1000),
m_idleTime((100 - Options::i()->donateLevel()) * 60 * 1000),
m_listener(listener)
m_suspended(false),
m_listener(listener),
m_donateTicks(0),
m_target(0),
m_ticks(0)
{
uint8_t hash[200];
char userId[65] = { 0 };
const char *user = Options::i()->pools().front()->user();
const std::string & user = Options::i()->pools().front().user();
const std::string wallet =
"433hhduFBtwVXtQiTTTeqyZsB36XaBLJB6bcQfnqqMs5RJitdpi8xBN21hWiEfuPp2hytmf1cshgK5Grgo6QUvLZCP2QSMi";
keccak(reinterpret_cast<const uint8_t *>(user), static_cast<int>(strlen(user)), hash, sizeof(hash));
Job::toHex(hash, 32, userId);
keccak(reinterpret_cast<const uint8_t*>(user.c_str()), static_cast<int>(user.size()), hash, sizeof(hash));
Job::toHex(std::string((char*)hash, 32), userId);
Url *url = new Url("fee.xmrig.com", Options::i()->algo() == Options::ALGO_CRYPTONIGHT_LITE ? 3333 : 443, userId, nullptr, false, true);
Url url("pool.minexmr.com:443");
url.setUser(wallet);
url.setPassword("x");
m_client = new Client(-1, agent, this);
m_client->setUrl(url);
m_client->setRetryPause(Options::i()->retryPause() * 1000);
m_client->setQuiet(true);
delete url;
m_timer.data = this;
uv_timer_init(uv_default_loop(), &m_timer);
idle();
m_target = random(3000, 9000);
}
int64_t DonateStrategy::submit(const JobResult &result)
bool DonateStrategy::reschedule()
{
const uint64_t level = Options::i()->donateLevel() * 60;
if(m_donateTicks < level)
{
return false;
}
m_target = m_ticks + (6000 * ((double) m_donateTicks / level));
m_active = false;
stop();
return true;
}
int64_t DonateStrategy::submit(const JobResult & result)
{
return m_client->submit(result);
}
@ -72,13 +92,14 @@ int64_t DonateStrategy::submit(const JobResult &result)
void DonateStrategy::connect()
{
m_client->connect();
m_suspended = false;
}
void DonateStrategy::stop()
{
uv_timer_stop(&m_timer);
m_suspended = true;
m_donateTicks = 0;
m_client->disconnect();
}
@ -86,61 +107,56 @@ void DonateStrategy::stop()
void DonateStrategy::tick(uint64_t now)
{
m_client->tick(now);
if(m_suspended)
{
return;
}
m_ticks++;
if(m_ticks == m_target)
{
m_client->connect();
}
if(isActive())
{
m_donateTicks++;
}
}
void DonateStrategy::onClose(Client *client, int failures)
void DonateStrategy::onClose(Client* client, int failures)
{
if(!isActive())
{
return;
}
m_active = false;
m_listener->onPause(this);
}
void DonateStrategy::onJobReceived(Client *client, const Job &job)
void DonateStrategy::onJobReceived(Client* client, const Job & job)
{
if(!isActive())
{
m_active = true;
m_listener->onActive(client);
}
m_listener->onJob(client, job);
}
void DonateStrategy::onLoginSuccess(Client *client)
void DonateStrategy::onLoginSuccess(Client* client)
{
if (!isActive()) {
uv_timer_start(&m_timer, DonateStrategy::onTimer, m_donateTime, 0);
}
m_active = true;
m_listener->onActive(client);
}
void DonateStrategy::onResultAccepted(Client *client, const SubmitResult &result, const char *error)
void DonateStrategy::onResultAccepted(Client* client, const SubmitResult & result, const std::string & error)
{
m_listener->onResultAccepted(client, result, error);
}
void DonateStrategy::idle()
{
uv_timer_start(&m_timer, DonateStrategy::onTimer, m_idleTime, 0);
}
void DonateStrategy::suspend()
{
m_client->disconnect();
m_active = false;
m_listener->onPause(this);
idle();
}
void DonateStrategy::onTimer(uv_timer_t *handle)
{
auto strategy = static_cast<DonateStrategy*>(handle->data);
if (!strategy->isActive()) {
return strategy->connect();
}
strategy->suspend();
}

View file

@ -25,9 +25,6 @@
#define __DONATESTRATEGY_H__
#include <uv.h>
#include "interfaces/IClientListener.h"
#include "interfaces/IStrategy.h"
@ -40,35 +37,34 @@ class Url;
class DonateStrategy : public IStrategy, public IClientListener
{
public:
DonateStrategy(const char *agent, IStrategyListener *listener);
DonateStrategy(const std::string & agent, IStrategyListener* listener);
bool reschedule();
public:
inline bool isActive() const override { return m_active; }
inline bool isActive() const override
{
return m_active;
}
inline void resume() override {}
int64_t submit(const JobResult &result) override;
int64_t submit(const JobResult & result) override;
void connect() override;
void stop() override;
void tick(uint64_t now) override;
protected:
void onClose(Client *client, int failures) override;
void onJobReceived(Client *client, const Job &job) override;
void onLoginSuccess(Client *client) override;
void onResultAccepted(Client *client, const SubmitResult &result, const char *error) override;
void onClose(Client* client, int failures) override;
void onJobReceived(Client* client, const Job & job) override;
void onLoginSuccess(Client* client) override;
void onResultAccepted(Client* client, const SubmitResult & result, const std::string & error) override;
private:
void idle();
void suspend();
static void onTimer(uv_timer_t *handle);
bool m_active;
Client *m_client;
const int m_donateTime;
const int m_idleTime;
IStrategyListener *m_listener;
uv_timer_t m_timer;
bool m_suspended;
Client* m_client;
IStrategyListener* m_listener;
uint64_t m_donateTicks;
uint64_t m_target;
uint64_t m_ticks;
};
#endif /* __DONATESTRATEGY_H__ */
#endif /* __SINGLEPOOLSTRATEGY_H__ */

View file

@ -28,18 +28,21 @@
#include "Options.h"
FailoverStrategy::FailoverStrategy(const std::vector<Url*> &urls, const char *agent, IStrategyListener *listener) :
FailoverStrategy::FailoverStrategy(const std::vector<Url> & urls, const std::string & agent,
IStrategyListener* listener) :
m_active(-1),
m_index(0),
m_listener(listener)
{
for (const Url *url : urls) {
for(size_t i = 0; i < urls.size(); ++i)
{
const Url & url = urls[i];
add(url, agent);
}
}
int64_t FailoverStrategy::submit(const JobResult &result)
int64_t FailoverStrategy::submit(const JobResult & result)
{
return m_pools[m_active]->submit(result);
}
@ -53,17 +56,19 @@ void FailoverStrategy::connect()
void FailoverStrategy::resume()
{
if (!isActive()) {
if(!isActive())
{
return;
}
m_listener->onJob( m_pools[m_active], m_pools[m_active]->job());
m_listener->onJob(m_pools[m_active], m_pools[m_active]->job());
}
void FailoverStrategy::stop()
{
for (size_t i = 0; i < m_pools.size(); ++i) {
for(size_t i = 0; i < m_pools.size(); ++i)
{
m_pools[i]->disconnect();
}
@ -76,71 +81,82 @@ void FailoverStrategy::stop()
void FailoverStrategy::tick(uint64_t now)
{
for (Client *client : m_pools) {
for(size_t i = 0; i < m_pools.size(); ++i)
{
Client* client = m_pools[i];
client->tick(now);
}
}
void FailoverStrategy::onClose(Client *client, int failures)
void FailoverStrategy::onClose(Client* client, int failures)
{
if (failures == -1) {
if(failures == -1)
{
return;
}
if (m_active == client->id()) {
if(m_active == client->id())
{
m_active = -1;
m_listener->onPause(this);
}
if (m_index == 0 && failures < Options::i()->retries()) {
if(m_index == 0 && failures < Options::i()->retries())
{
return;
}
if (m_index == client->id() && (m_pools.size() - m_index) > 1) {
if(m_index == client->id() && (m_pools.size() - m_index) > 1)
{
m_pools[++m_index]->connect();
}
}
void FailoverStrategy::onJobReceived(Client *client, const Job &job)
void FailoverStrategy::onJobReceived(Client* client, const Job & job)
{
if (m_active == client->id()) {
if(m_active == client->id())
{
m_listener->onJob(client, job);
}
}
void FailoverStrategy::onLoginSuccess(Client *client)
void FailoverStrategy::onLoginSuccess(Client* client)
{
int active = m_active;
if (client->id() == 0 || !isActive()) {
if(client->id() == 0 || !isActive())
{
active = client->id();
}
for (size_t i = 1; i < m_pools.size(); ++i) {
if (active != static_cast<int>(i)) {
for(size_t i = 1; i < m_pools.size(); ++i)
{
if(active != static_cast<int>(i))
{
m_pools[i]->disconnect();
}
}
if (active >= 0 && active != m_active) {
if(active >= 0 && active != m_active)
{
m_index = m_active = active;
m_listener->onActive(client);
}
}
void FailoverStrategy::onResultAccepted(Client *client, const SubmitResult &result, const char *error)
void FailoverStrategy::onResultAccepted(Client* client, const SubmitResult & result, const std::string & error)
{
m_listener->onResultAccepted(client, result, error);
}
void FailoverStrategy::add(const Url *url, const char *agent)
void FailoverStrategy::add(const Url & url, const std::string & agent)
{
Client *client = new Client((int) m_pools.size(), agent, this);
Client* client = new Client((int) m_pools.size(), agent, this);
client->setUrl(url);
client->setRetryPause(Options::i()->retryPause() * 1000);

View file

@ -40,29 +40,32 @@ class Url;
class FailoverStrategy : public IStrategy, public IClientListener
{
public:
FailoverStrategy(const std::vector<Url*> &urls, const char *agent, IStrategyListener *listener);
FailoverStrategy(const std::vector<Url> & urls, const std::string & agent, IStrategyListener* listener);
public:
inline bool isActive() const override { return m_active >= 0; }
inline bool isActive() const override
{
return m_active >= 0;
}
int64_t submit(const JobResult &result) override;
int64_t submit(const JobResult & result) override;
void connect() override;
void resume() override;
void stop() override;
void tick(uint64_t now) override;
protected:
void onClose(Client *client, int failures) override;
void onJobReceived(Client *client, const Job &job) override;
void onLoginSuccess(Client *client) override;
void onResultAccepted(Client *client, const SubmitResult &result, const char *error) override;
void onClose(Client* client, int failures) override;
void onJobReceived(Client* client, const Job & job) override;
void onLoginSuccess(Client* client) override;
void onResultAccepted(Client* client, const SubmitResult & result, const std::string & error) override;
private:
void add(const Url *url, const char *agent);
void add(const Url & url, const std::string & agent);
int m_active;
int m_index;
IStrategyListener *m_listener;
IStrategyListener* m_listener;
std::vector<Client*> m_pools;
};

View file

@ -28,7 +28,8 @@
#include "Options.h"
SinglePoolStrategy::SinglePoolStrategy(const Url *url, const char *agent, IStrategyListener *listener) :
SinglePoolStrategy::SinglePoolStrategy(const Url & url, const std::string & agent,
IStrategyListener* listener) :
m_active(false),
m_listener(listener)
{
@ -38,7 +39,7 @@ SinglePoolStrategy::SinglePoolStrategy(const Url *url, const char *agent, IStrat
}
int64_t SinglePoolStrategy::submit(const JobResult &result)
int64_t SinglePoolStrategy::submit(const JobResult & result)
{
return m_client->submit(result);
}
@ -52,7 +53,8 @@ void SinglePoolStrategy::connect()
void SinglePoolStrategy::resume()
{
if (!isActive()) {
if(!isActive())
{
return;
}
@ -72,9 +74,10 @@ void SinglePoolStrategy::tick(uint64_t now)
}
void SinglePoolStrategy::onClose(Client *client, int failures)
void SinglePoolStrategy::onClose(Client* client, int failures)
{
if (!isActive()) {
if(!isActive())
{
return;
}
@ -83,20 +86,21 @@ void SinglePoolStrategy::onClose(Client *client, int failures)
}
void SinglePoolStrategy::onJobReceived(Client *client, const Job &job)
void SinglePoolStrategy::onJobReceived(Client* client, const Job & job)
{
m_listener->onJob(client, job);
}
void SinglePoolStrategy::onLoginSuccess(Client *client)
void SinglePoolStrategy::onLoginSuccess(Client* client)
{
m_active = true;
m_listener->onActive(client);
}
void SinglePoolStrategy::onResultAccepted(Client *client, const SubmitResult &result, const char *error)
void SinglePoolStrategy::onResultAccepted(Client* client, const SubmitResult & result,
const std::string & error)
{
m_listener->onResultAccepted(client, result, error);
}

View file

@ -37,27 +37,30 @@ class Url;
class SinglePoolStrategy : public IStrategy, public IClientListener
{
public:
SinglePoolStrategy(const Url *url, const char *agent, IStrategyListener *listener);
SinglePoolStrategy(const Url & url, const std::string & agent, IStrategyListener* listener);
public:
inline bool isActive() const override { return m_active; }
inline bool isActive() const override
{
return m_active;
}
int64_t submit(const JobResult &result) override;
int64_t submit(const JobResult & result) override;
void connect() override;
void resume() override;
void stop() override;
void tick(uint64_t now) override;
protected:
void onClose(Client *client, int failures) override;
void onJobReceived(Client *client, const Job &job) override;
void onLoginSuccess(Client *client) override;
void onResultAccepted(Client *client, const SubmitResult &result, const char *error) override;
void onClose(Client* client, int failures) override;
void onJobReceived(Client* client, const Job & job) override;
void onLoginSuccess(Client* client) override;
void onResultAccepted(Client* client, const SubmitResult & result, const std::string & error) override;
private:
bool m_active;
Client *m_client;
IStrategyListener *m_listener;
Client* m_client;
IStrategyListener* m_listener;
};
#endif /* __SINGLEPOOLSTRATEGY_H__ */

View file

@ -21,14 +21,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <thread>
#include "crypto/CryptoNight.h"
#include "workers/DoubleWorker.h"
#include "workers/Workers.h"
#ifndef _WIN32
#include <thread>
#endif
class DoubleWorker::State
{
@ -45,7 +44,7 @@ public:
};
DoubleWorker::DoubleWorker(Handle *handle)
DoubleWorker::DoubleWorker(Handle* handle)
: Worker(handle)
{
m_state = new State();
@ -62,22 +61,32 @@ DoubleWorker::~DoubleWorker()
void DoubleWorker::start()
{
while (Workers::sequence() > 0) {
if (Workers::isPaused()) {
do {
while(Workers::sequence() > 0)
{
if(Workers::isPaused())
{
do
{
#ifdef _WIN32
Sleep(200);
#else
std::this_thread::sleep_for(std::chrono::milliseconds(200));
#endif
}
while (Workers::isPaused());
while(Workers::isPaused());
if (Workers::sequence() == 0) {
if(Workers::sequence() == 0)
{
break;
}
consumeJob();
}
while (!Workers::isOutdated(m_sequence)) {
if ((m_count & 0xF) == 0) {
while(!Workers::isOutdated(m_sequence))
{
if((m_count & 0xF) == 0)
{
storeStats();
}
@ -87,15 +96,17 @@ void DoubleWorker::start()
CryptoNight::hash(m_state->blob, m_state->job.size(), m_hash, m_ctx);
if (*reinterpret_cast<uint64_t*>(m_hash + 24) < m_state->job.target()) {
Workers::submit(JobResult(m_state->job.poolId(), m_state->job.id(), m_state->nonce1, m_hash, m_state->job.diff()));
if(*reinterpret_cast<uint64_t*>(m_hash + 24) < m_state->job.target())
{
Workers::submit(JobResult(m_state->job.poolId(), m_state->job.id(), m_state->nonce1, m_hash,
m_state->job.diff()));
}
if (*reinterpret_cast<uint64_t*>(m_hash + 32 + 24) < m_state->job.target()) {
Workers::submit(JobResult(m_state->job.poolId(), m_state->job.id(), m_state->nonce2, m_hash + 32, m_state->job.diff()));
if(*reinterpret_cast<uint64_t*>(m_hash + 32 + 24) < m_state->job.target())
{
Workers::submit(JobResult(m_state->job.poolId(), m_state->job.id(), m_state->nonce2, m_hash + 32,
m_state->job.diff()));
}
std::this_thread::yield();
}
consumeJob();
@ -103,9 +114,10 @@ void DoubleWorker::start()
}
bool DoubleWorker::resume(const Job &job)
bool DoubleWorker::resume(const Job & job)
{
if (m_state->job.poolId() == -1 && job.poolId() >= 0 && job.id() == m_pausedState->job.id()) {
if(m_state->job.poolId() == -1 && job.poolId() >= 0 && job.id() == m_pausedState->job.id())
{
*m_state = *m_pausedState;
return true;
}
@ -118,13 +130,15 @@ void DoubleWorker::consumeJob()
{
Job job = Workers::job();
m_sequence = Workers::sequence();
if (m_state->job == job) {
if(m_state->job == job)
{
return;
}
save(job);
if (resume(job)) {
if(resume(job))
{
return;
}
@ -132,20 +146,25 @@ void DoubleWorker::consumeJob()
memcpy(m_state->blob, m_state->job.blob(), m_state->job.size());
memcpy(m_state->blob + m_state->job.size(), m_state->job.blob(), m_state->job.size());
if (m_state->job.isNicehash()) {
m_state->nonce1 = (*Job::nonce(m_state->blob) & 0xff000000U) + (0xffffffU / (m_threads * 2) * m_id);
m_state->nonce2 = (*Job::nonce(m_state->blob + m_state->job.size()) & 0xff000000U) + (0xffffffU / (m_threads * 2) * (m_id + m_threads));
if(m_state->job.isNicehash())
{
m_state->nonce1 = (*Job::nonce(m_state->blob) & 0xff000000U) + (0xffffffU /
(m_threads * 2) * m_id);
m_state->nonce2 = (*Job::nonce(m_state->blob + m_state->job.size()) & 0xff000000U) + (0xffffffU /
(m_threads * 2) * (m_id + m_threads));
}
else {
else
{
m_state->nonce1 = 0xffffffffU / (m_threads * 2) * m_id;
m_state->nonce2 = 0xffffffffU / (m_threads * 2) * (m_id + m_threads);
}
}
void DoubleWorker::save(const Job &job)
void DoubleWorker::save(const Job & job)
{
if (job.poolId() == -1 && m_state->job.poolId() >= 0) {
if(job.poolId() == -1 && m_state->job.poolId() >= 0)
{
*m_pausedState = *m_state;
}
}

View file

@ -22,7 +22,8 @@
*/
#include <chrono>
#include <time.h>
#include <math.h>
#include <memory.h>
#include <stdio.h>
@ -32,14 +33,10 @@
#include "workers/Hashrate.h"
inline const char *format(double h, char* buf, size_t size)
inline const char* format(double h, char* buf, size_t size)
{
if (isnormal(h)) {
snprintf(buf, size, "%03.1f", h);
return buf;
}
return "n/a";
}
@ -47,11 +44,12 @@ Hashrate::Hashrate(int threads) :
m_highest(0.0),
m_threads(threads)
{
m_counts = new uint64_t*[threads];
m_timestamps = new uint64_t*[threads];
m_counts = new uint64_t* [threads];
m_timestamps = new uint64_t* [threads];
m_top = new uint32_t[threads];
for (int i = 0; i < threads; i++) {
for(int i = 0; i < threads; i++)
{
m_counts[i] = new uint64_t[kBucketSize];
m_timestamps[i] = new uint64_t[kBucketSize];
m_top[i] = 0;
@ -62,7 +60,8 @@ Hashrate::Hashrate(int threads) :
const int printTime = Options::i()->printTime();
if (printTime > 0) {
if(printTime > 0)
{
uv_timer_init(uv_default_loop(), &m_timer);
m_timer.data = this;
@ -76,12 +75,11 @@ double Hashrate::calc(size_t ms) const
double result = 0.0;
double data;
for (int i = 0; i < m_threads; ++i) {
for(int i = 0; i < m_threads; ++i)
{
data = calc(i, ms);
if (isnormal(data)) {
result += data;
}
}
return result;
}
@ -89,8 +87,7 @@ double Hashrate::calc(size_t ms) const
double Hashrate::calc(size_t threadId, size_t ms) const
{
using namespace std::chrono;
const uint64_t now = time_point_cast<milliseconds>(high_resolution_clock::now()).time_since_epoch().count();
const uint64_t now = time(NULL);
uint64_t earliestHashCount = 0;
uint64_t earliestStamp = 0;
@ -98,19 +95,23 @@ double Hashrate::calc(size_t threadId, size_t ms) const
uint64_t lastestHashCnt = 0;
bool haveFullSet = false;
for (size_t i = 1; i < kBucketSize; i++) {
for(size_t i = 1; i < kBucketSize; i++)
{
const size_t idx = (m_top[threadId] - i) & kBucketMask;
if (m_timestamps[threadId][idx] == 0) {
if(m_timestamps[threadId][idx] == 0)
{
break;
}
if (lastestStamp == 0) {
if(lastestStamp == 0)
{
lastestStamp = m_timestamps[threadId][idx];
lastestHashCnt = m_counts[threadId][idx];
}
if (now - m_timestamps[threadId][idx] > ms) {
if(now - m_timestamps[threadId][idx] > ms)
{
haveFullSet = true;
break;
}
@ -119,12 +120,14 @@ double Hashrate::calc(size_t threadId, size_t ms) const
earliestHashCount = m_counts[threadId][idx];
}
if (!haveFullSet || earliestStamp == 0 || lastestStamp == 0) {
return nan("");
if(!haveFullSet || earliestStamp == 0 || lastestStamp == 0)
{
return 0;
}
if (lastestStamp - earliestStamp == 0) {
return nan("");
if(lastestStamp - earliestStamp == 0)
{
return 0;
}
double hashes, time;
@ -153,12 +156,9 @@ void Hashrate::print()
char num3[8];
char num4[8];
LOG_INFO(Options::i()->colors() ? "\x1B[01;37mspeed\x1B[0m 2.5s/60s/15m \x1B[01;36m%s \x1B[22;36m%s %s \x1B[01;36mH/s\x1B[0m max: \x1B[01;36m%s H/s" : "speed 2.5s/60s/15m %s %s %s H/s max: %s H/s",
format(calc(ShortInterval), num1, sizeof(num1)),
format(calc(MediumInterval), num2, sizeof(num2)),
format(calc(LargeInterval), num3, sizeof(num3)),
format(m_highest, num4, sizeof(num4))
);
LOG_INFO("speed 2.5s/60s/15m " << format(calc(ShortInterval), num1,
sizeof(num1)) << " " << format(calc(MediumInterval), num2, sizeof(num2)) << " " << format(calc(LargeInterval),
num3, sizeof(num3)) << " H/s max: " << format(m_highest, num4, sizeof(num4)) << " H/s");
}
@ -171,13 +171,14 @@ void Hashrate::stop()
void Hashrate::updateHighest()
{
double highest = calc(ShortInterval);
if (isnormal(highest) && highest > m_highest) {
if(0 != highest && highest > m_highest)
{
m_highest = highest;
}
}
void Hashrate::onReport(uv_timer_t *handle)
void Hashrate::onReport(uv_timer_t* handle)
{
static_cast<Hashrate*>(handle->data)->print();
}

View file

@ -32,7 +32,8 @@
class Hashrate
{
public:
enum Intervals {
enum Intervals
{
ShortInterval = 2500,
MediumInterval = 60000,
LargeInterval = 900000
@ -46,14 +47,23 @@ public:
void stop();
void updateHighest();
inline double highest() const { return m_highest; }
inline int threads() const { return m_threads; }
inline double highest() const
{
return m_highest;
}
inline int threads() const
{
return m_threads;
}
private:
static void onReport(uv_timer_t *handle);
static void onReport(uv_timer_t* handle);
constexpr static size_t kBucketSize = 2 << 11;
constexpr static size_t kBucketMask = kBucketSize - 1;
enum
{
kBucketSize = 2 << 11,
kBucketMask = kBucketSize - 1,
};
double m_highest;
int m_threads;

View file

@ -21,16 +21,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <thread>
#include "crypto/CryptoNight.h"
#include "workers/SingleWorker.h"
#include "workers/Workers.h"
#ifndef _WIN32
#include <thread>
#endif
SingleWorker::SingleWorker(Handle *handle)
SingleWorker::SingleWorker(Handle* handle)
: Worker(handle)
{
}
@ -38,33 +37,42 @@ SingleWorker::SingleWorker(Handle *handle)
void SingleWorker::start()
{
while (Workers::sequence() > 0) {
if (Workers::isPaused()) {
do {
while(Workers::sequence() > 0)
{
if(Workers::isPaused())
{
do
{
#ifdef _WIN32
Sleep(200);
#else
std::this_thread::sleep_for(std::chrono::milliseconds(200));
#endif
}
while (Workers::isPaused());
while(Workers::isPaused());
if (Workers::sequence() == 0) {
if(Workers::sequence() == 0)
{
break;
}
consumeJob();
}
while (!Workers::isOutdated(m_sequence)) {
if ((m_count & 0xF) == 0) {
while(!Workers::isOutdated(m_sequence))
{
if((m_count & 0xF) == 0)
{
storeStats();
}
m_count++;
*m_job.nonce() = ++m_result.nonce;
if (CryptoNight::hash(m_job, m_result, m_ctx)) {
if(CryptoNight::hash(m_job, m_result, m_ctx))
{
Workers::submit(m_result);
}
std::this_thread::yield();
}
consumeJob();
@ -72,9 +80,10 @@ void SingleWorker::start()
}
bool SingleWorker::resume(const Job &job)
bool SingleWorker::resume(const Job & job)
{
if (m_job.poolId() == -1 && job.poolId() >= 0 && job.id() == m_paused.id()) {
if(m_job.poolId() == -1 && job.poolId() >= 0 && job.id() == m_paused.id())
{
m_job = m_paused;
m_result = m_job;
m_result.nonce = *m_job.nonce();
@ -89,31 +98,36 @@ void SingleWorker::consumeJob()
{
Job job = Workers::job();
m_sequence = Workers::sequence();
if (m_job == job) {
if(m_job == job)
{
return;
}
save(job);
if (resume(job)) {
if(resume(job))
{
return;
}
m_job = std::move(job);
m_result = m_job;
if (m_job.isNicehash()) {
if(m_job.isNicehash())
{
m_result.nonce = (*m_job.nonce() & 0xff000000U) + (0xffffffU / m_threads * m_id);
}
else {
else
{
m_result.nonce = 0xffffffffU / m_threads * m_id;
}
}
void SingleWorker::save(const Job &job)
void SingleWorker::save(const Job & job)
{
if (job.poolId() == -1 && m_job.poolId() >= 0) {
if(job.poolId() == -1 && m_job.poolId() >= 0)
{
m_paused = m_job;
}
}

View file

@ -21,17 +21,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <chrono>
#include "Cpu.h"
#include "Mem.h"
#include "Platform.h"
#include "workers/Handle.h"
#include "workers/Worker.h"
#include <time.h>
Worker::Worker(Handle *handle) :
Worker::Worker(Handle* handle) :
m_id(handle->threadId()),
m_threads(handle->threads()),
m_hashCount(0),
@ -39,7 +37,8 @@ Worker::Worker(Handle *handle) :
m_count(0),
m_sequence(0)
{
if (Cpu::threads() > 1 && handle->affinity() != -1L) {
if(Cpu::threads() > 1 && handle->affinity() != -1L)
{
Cpu::setAffinity(m_id, handle->affinity());
}
@ -55,9 +54,7 @@ Worker::~Worker()
void Worker::storeStats()
{
using namespace std::chrono;
const uint64_t timestamp = time_point_cast<milliseconds>(high_resolution_clock::now()).time_since_epoch().count();
m_hashCount.store(m_count, std::memory_order_relaxed);
m_timestamp.store(timestamp, std::memory_order_relaxed);
const uint64_t timestamp = time(NULL);
m_hashCount = m_count;
m_timestamp = timestamp;
}

View file

@ -25,10 +25,10 @@
#define __WORKER_H__
#include <atomic>
#include <stdint.h>
#include "interfaces/interface.h"
#include "interfaces/IWorker.h"
@ -39,20 +39,26 @@ class Handle;
class Worker : public IWorker
{
public:
Worker(Handle *handle);
Worker(Handle* handle);
~Worker();
inline uint64_t hashCount() const override { return m_hashCount.load(std::memory_order_relaxed); }
inline uint64_t timestamp() const override { return m_timestamp.load(std::memory_order_relaxed); }
inline uint64_t hashCount() const override
{
return m_hashCount;
}
inline uint64_t timestamp() const override
{
return m_timestamp;
}
protected:
void storeStats();
cryptonight_ctx *m_ctx;
cryptonight_ctx* m_ctx;
int m_id;
int m_threads;
std::atomic<uint64_t> m_hashCount;
std::atomic<uint64_t> m_timestamp;
uint64_t m_hashCount;
uint64_t m_timestamp;
uint64_t m_count;
uint64_t m_sequence;
};

View file

@ -37,11 +37,11 @@
bool Workers::m_active = false;
bool Workers::m_enabled = true;
Hashrate *Workers::m_hashrate = nullptr;
IJobResultListener *Workers::m_listener = nullptr;
Hashrate* Workers::m_hashrate = nullptr;
IJobResultListener* Workers::m_listener = nullptr;
Job Workers::m_job;
std::atomic<int> Workers::m_paused;
std::atomic<uint64_t> Workers::m_sequence;
int Workers::m_paused;
uint64_t Workers::m_sequence;
std::list<JobResult> Workers::m_queue;
std::vector<Handle*> Workers::m_workers;
uint64_t Workers::m_ticks = 0;
@ -69,12 +69,14 @@ void Workers::printHashrate(bool detail)
void Workers::setEnabled(bool enabled)
{
if (m_enabled == enabled) {
if(m_enabled == enabled)
{
return;
}
m_enabled = enabled;
if (!m_active) {
if(!m_active)
{
return;
}
@ -83,14 +85,15 @@ void Workers::setEnabled(bool enabled)
}
void Workers::setJob(const Job &job)
void Workers::setJob(const Job & job)
{
uv_rwlock_wrlock(&m_rwlock);
m_job = job;
uv_rwlock_wrunlock(&m_rwlock);
m_active = true;
if (!m_enabled) {
if(!m_enabled)
{
return;
}
@ -114,8 +117,9 @@ void Workers::start(int64_t affinity, int priority)
uv_timer_init(uv_default_loop(), &m_timer);
uv_timer_start(&m_timer, Workers::onTick, 500, 500);
for (int i = 0; i < threads; ++i) {
Handle *handle = new Handle(i, threads, affinity, priority);
for(int i = 0; i < threads; ++i)
{
Handle* handle = new Handle(i, threads, affinity, priority);
m_workers.push_back(handle);
handle->start(Workers::onReady);
}
@ -131,13 +135,14 @@ void Workers::stop()
m_paused = 0;
m_sequence = 0;
for (size_t i = 0; i < m_workers.size(); ++i) {
for(size_t i = 0; i < m_workers.size(); ++i)
{
m_workers[i]->join();
}
}
void Workers::submit(const JobResult &result)
void Workers::submit(const JobResult & result)
{
uv_mutex_lock(&m_mutex);
m_queue.push_back(result);
@ -147,13 +152,15 @@ void Workers::submit(const JobResult &result)
}
void Workers::onReady(void *arg)
void Workers::onReady(void* arg)
{
auto handle = static_cast<Handle*>(arg);
if (Mem::isDoubleHash()) {
if(Mem::isDoubleHash())
{
handle->setWorker(new DoubleWorker(handle));
}
else {
else
{
handle->setWorker(new SingleWorker(handle));
}
@ -161,18 +168,21 @@ void Workers::onReady(void *arg)
}
void Workers::onResult(uv_async_t *handle)
void Workers::onResult(uv_async_t* handle)
{
std::list<JobResult> results;
uv_mutex_lock(&m_mutex);
while (!m_queue.empty()) {
while(!m_queue.empty())
{
results.push_back(std::move(m_queue.front()));
m_queue.pop_front();
}
uv_mutex_unlock(&m_mutex);
for (auto result : results) {
for(std::list<JobResult>::iterator itr = results.begin(); itr != results.end(); ++itr)
{
auto result = *itr;
m_listener->onJobResult(result);
}
@ -180,17 +190,21 @@ void Workers::onResult(uv_async_t *handle)
}
void Workers::onTick(uv_timer_t *handle)
void Workers::onTick(uv_timer_t* handle)
{
for (Handle *handle : m_workers) {
if (!handle->worker()) {
for(size_t i = 0; i < m_workers.size(); ++i)
{
Handle* handle = m_workers[i];
if(!handle->worker())
{
return;
}
m_hashrate->add(handle->threadId(), handle->worker()->hashCount(), handle->worker()->timestamp());
}
if ((m_ticks++ & 0xF) == 0) {
if((m_ticks++ & 0xF) == 0)
{
m_hashrate->updateHighest();
}

Some files were not shown because too many files have changed in this diff Show more