diff --git a/Makefile.am b/Makefile.am index 2c149d0..b3ad6d6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -13,7 +13,8 @@ bin_PROGRAMS = minerd EXTRA_DIST = sha256_generic.c -minerd_SOURCES = cpu-miner.c sha256_4way.c util.c miner.h compat.h +minerd_SOURCES = cpu-miner.c sha256_4way.c sha256_via.c \ + util.c miner.h compat.h minerd_LDFLAGS = $(PTHREAD_FLAGS) minerd_LDADD = @LIBCURL@ @JANSSON_LIBS@ @PTHREAD_LIBS@ diff --git a/cpu-miner.c b/cpu-miner.c index f7dc37b..237f980 100644 --- a/cpu-miner.c +++ b/cpu-miner.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #ifndef WIN32 @@ -29,8 +30,6 @@ #define DEF_RPC_URL "http://127.0.0.1:8332/" #define DEF_RPC_USERPASS "rpcuser:rpcpass" -#include "sha256_generic.c" - enum { STAT_SLEEP_INTERVAL = 100, STAT_CTR_INTERVAL = 10000000, @@ -39,9 +38,10 @@ enum { enum sha256_algos { ALGO_C, /* plain C */ ALGO_4WAY, /* parallel SSE2 */ + ALGO_VIA, /* VIA padlock */ }; -static bool opt_debug; +bool opt_debug = false; bool opt_protocol = false; static bool program_running = true; static const bool opt_time = true; @@ -65,6 +65,9 @@ static struct option_help options_help[] = { "\tc\t\tLinux kernel sha256, implemented in C (default)" #ifdef WANT_SSE2_4WAY "\n\t4way\t\ttcatm's 4-way SSE2 implementation (EXPERIMENTAL)" +#endif +#ifdef WANT_VIA_PADLOCK + "\n\tvia\t\tVIA padlock implementation (EXPERIMENTAL)" #endif }, @@ -106,6 +109,8 @@ struct work { unsigned char hash[32]; }; +#include "sha256_generic.c" + static bool jobj_binary(const json_t *obj, const char *key, void *buf, size_t buflen) { @@ -222,7 +227,7 @@ static void runhash(void *state, void *input, const void *init) sha256_transform(state, input); } -static const uint32_t init_state[8] = { +const uint32_t sha256_init_state[8] = { 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 }; @@ -242,7 +247,7 @@ static bool scanhash(unsigned char *midstate, unsigned char *data, *nonce = n; runhash(hash1, data, midstate); - runhash(hash, hash1, init_state); + runhash(hash, hash1, sha256_init_state); stat_ctr++; @@ -317,6 +322,14 @@ static void *miner_thread(void *thr_id_int) } break; #endif + +#ifdef WANT_VIA_PADLOCK + case ALGO_VIA: + rc = scanhash_via(work.midstate, work.data + 64, + work.hash1, work.hash, + &hashes_done); + break; +#endif } hashmeter(thr_id, &tv_start, hashes_done); @@ -355,6 +368,10 @@ static void parse_arg (int key, char *arg) #ifdef WANT_SSE2_4WAY else if (!strcmp(arg, "4way")) opt_algo = ALGO_4WAY; +#endif +#ifdef WANT_VIA_PADLOCK + else if (!strcmp(arg, "via")) + opt_algo = ALGO_VIA; #endif else show_usage(); diff --git a/miner.h b/miner.h index ff5bddc..bf86f56 100644 --- a/miner.h +++ b/miner.h @@ -2,17 +2,24 @@ #define __MINER_H__ #include +#include #include #ifdef __SSE2__ #define WANT_SSE2_4WAY 1 #endif +#if defined(__i386__) || defined(__x86_64__) +#define WANT_VIA_PADLOCK 1 +#endif + #ifndef ARRAY_SIZE #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #endif +extern bool opt_debug; extern bool opt_protocol; +extern const uint32_t sha256_init_state[]; extern json_t *json_rpc_call(const char *url, const char *userpass, const char *rpc_req); extern char *bin2hex(unsigned char *p, size_t len); @@ -22,6 +29,9 @@ extern unsigned int ScanHash_4WaySSE2(unsigned char *pmidstate, unsigned char *pdata, unsigned char *phash1, unsigned char *phash, unsigned long *nHashesDone); +extern bool scanhash_via(unsigned char *midstate, const unsigned char *data_in, + unsigned char *hash1, unsigned char *hash, + unsigned long *hashes_done); extern int timeval_subtract (struct timeval *result, struct timeval *x, struct timeval *y); diff --git a/sha256_via.c b/sha256_via.c new file mode 100644 index 0000000..c03495b --- /dev/null +++ b/sha256_via.c @@ -0,0 +1,92 @@ + +#include +#include +#include +#include +#include +#include "miner.h" + +#ifdef WANT_VIA_PADLOCK + +#define ___constant_swab32(x) ((uint32_t)( \ + (((uint32_t)(x) & (uint32_t)0x000000ffUL) << 24) | \ + (((uint32_t)(x) & (uint32_t)0x0000ff00UL) << 8) | \ + (((uint32_t)(x) & (uint32_t)0x00ff0000UL) >> 8) | \ + (((uint32_t)(x) & (uint32_t)0xff000000UL) >> 24))) + +static inline uint32_t swab32(uint32_t v) +{ + return ___constant_swab32(v); +} + +static void via_sha256(void *hash, void *buf, unsigned len) +{ + unsigned stat = 0; + asm volatile(".byte 0xf3, 0x0f, 0xa6, 0xd0" + :"+S"(buf), "+a"(stat) + :"c"(len), "D" (hash) + :"memory"); +} + +bool scanhash_via(unsigned char *midstate, const unsigned char *data_in, + unsigned char *hash1, unsigned char *hash, + unsigned long *hashes_done) +{ + unsigned char data[128] __attribute__((aligned(128))); + unsigned char tmp_hash1[32] __attribute__((aligned(32))); + uint32_t *hash32 = (uint32_t *) hash; + uint32_t *nonce = (uint32_t *)(data + 12); + uint32_t n = 0; + unsigned long stat_ctr = 0; + int i; + + /* bitcoin gives us big endian input, but via wants LE, + * so we reverse the swapping bitcoin has already done (extra work) + */ + for (i = 0; i < 128/4; i++) { + uint32_t *data32 = (uint32_t *) data; + data32[i] = swab32(((uint32_t *)data_in)[i]); + } + + while (1) { + n++; + *nonce = n; + + /* first SHA256 transform */ + memcpy(tmp_hash1, sha256_init_state, 32); + via_sha256(tmp_hash1, data, 80); /* or maybe 128? */ + + for (i = 0; i < 32/4; i++) + ((uint32_t *)tmp_hash1)[i] = + swab32(((uint32_t *)tmp_hash1)[i]); + + /* second SHA256 transform */ + memcpy(hash, sha256_init_state, 32); + via_sha256(hash, tmp_hash1, 32); + + stat_ctr++; + + if (hash32[7] == 0) { + char *hexstr; + + hexstr = bin2hex(hash, 32); + fprintf(stderr, + "DBG: found zeroes in hash:\n%s\n", + hexstr); + free(hexstr); + + *hashes_done = stat_ctr; + return true; + } + + if ((n & 0xffffff) == 0) { + if (opt_debug) + fprintf(stderr, "DBG: end of nonce range\n"); + *hashes_done = stat_ctr; + return false; + } + } +} + +#endif /* WANT_VIA_PADLOCK */ +