Merge branch 'dev'
This commit is contained in:
commit
1a8abf054e
27 changed files with 563 additions and 346 deletions
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -1,3 +1,13 @@
|
||||||
|
# v3.1.1
|
||||||
|
- [#1133](https://github.com/xmrig/xmrig/issues/1133) Fixed syslog regression.
|
||||||
|
- [#1138](https://github.com/xmrig/xmrig/issues/1138) Fixed multiple network bugs.
|
||||||
|
- [#1141](https://github.com/xmrig/xmrig/issues/1141) Fixed log in background mode.
|
||||||
|
- [#1142](https://github.com/xmrig/xmrig/pull/1142) RandomX hashrate improved by 0.5-1.5% depending on variant and CPU.
|
||||||
|
- [#1146](https://github.com/xmrig/xmrig/pull/1146) Fixed race condition in RandomX thread init.
|
||||||
|
- [#1148](https://github.com/xmrig/xmrig/pull/1148) Fixed, on Linux linker marking entire executable as having an executable stack.
|
||||||
|
- Fixed, for Argon2 algorithms command line options like `--threads` was ignored.
|
||||||
|
- Fixed command line options for single pool, free order allowed again.
|
||||||
|
|
||||||
# v3.1.0
|
# v3.1.0
|
||||||
- [#1107](https://github.com/xmrig/xmrig/issues/1107#issuecomment-522235892) Added Argon2 algorithm family: `argon2/chukwa` and `argon2/wrkz`.
|
- [#1107](https://github.com/xmrig/xmrig/issues/1107#issuecomment-522235892) Added Argon2 algorithm family: `argon2/chukwa` and `argon2/wrkz`.
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,8 @@ void xmrig::CpuWorker<N>::allocateRandomX_VM()
|
||||||
if (Nonce::sequence(Nonce::CPU) == 0) {
|
if (Nonce::sequence(Nonce::CPU) == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dataset = Rx::dataset(m_job.currentJob(), m_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_vm) {
|
if (!m_vm) {
|
||||||
|
|
|
@ -91,6 +91,10 @@ public:
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
|
if (Log::background && m_backends.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
timestamp(level, size, offset);
|
timestamp(level, size, offset);
|
||||||
color(level, size);
|
color(level, size);
|
||||||
|
|
||||||
|
@ -111,7 +115,7 @@ public:
|
||||||
if (!m_backends.empty()) {
|
if (!m_backends.empty()) {
|
||||||
for (ILogBackend *backend : m_backends) {
|
for (ILogBackend *backend : m_backends) {
|
||||||
backend->print(level, m_buf, offset, size, true);
|
backend->print(level, m_buf, offset, size, true);
|
||||||
backend->print(level, txt.c_str(), offset, txt.size(), false);
|
backend->print(level, txt.c_str(), offset ? (offset - 11) : 0, txt.size(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -190,8 +194,9 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
bool Log::colors = true;
|
bool Log::background = false;
|
||||||
LogPrivate *Log::d = new LogPrivate();
|
bool Log::colors = true;
|
||||||
|
LogPrivate *Log::d = new LogPrivate();
|
||||||
|
|
||||||
|
|
||||||
} /* namespace xmrig */
|
} /* namespace xmrig */
|
||||||
|
|
|
@ -54,6 +54,7 @@ public:
|
||||||
static void print(const char *fmt, ...);
|
static void print(const char *fmt, ...);
|
||||||
static void print(Level level, const char *fmt, ...);
|
static void print(Level level, const char *fmt, ...);
|
||||||
|
|
||||||
|
static bool background;
|
||||||
static bool colors;
|
static bool colors;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -37,7 +37,7 @@ class SysLog : public ILogBackend
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SysLog();
|
SysLog();
|
||||||
~SysLog();
|
~SysLog() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void print(int level, const char *line, size_t offset, size_t size, bool colors) override;
|
void print(int level, const char *line, size_t offset, size_t size, bool colors) override;
|
||||||
|
|
|
@ -184,7 +184,10 @@ int xmrig::Base::init()
|
||||||
Platform::setProcessPriority(config()->cpu().priority());
|
Platform::setProcessPriority(config()->cpu().priority());
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
if (!config()->isBackground()) {
|
if (config()->isBackground()) {
|
||||||
|
Log::background = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
Log::add(new ConsoleLog());
|
Log::add(new ConsoleLog());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,11 +33,12 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include "base/kernel/config/BaseTransform.h"
|
|
||||||
#include "base/kernel/Process.h"
|
|
||||||
#include "base/io/log/Log.h"
|
|
||||||
#include "base/kernel/interfaces/IConfig.h"
|
|
||||||
#include "base/io/json/JsonChain.h"
|
#include "base/io/json/JsonChain.h"
|
||||||
|
#include "base/io/log/Log.h"
|
||||||
|
#include "base/kernel/config/BaseTransform.h"
|
||||||
|
#include "base/kernel/interfaces/IConfig.h"
|
||||||
|
#include "base/kernel/Process.h"
|
||||||
|
#include "base/net/stratum/Pool.h"
|
||||||
#include "core/config/Config_platform.h"
|
#include "core/config/Config_platform.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -138,7 +139,19 @@ void xmrig::BaseTransform::transform(rapidjson::Document &doc, int key, const ch
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IConfig::UrlKey: /* --url */
|
case IConfig::UrlKey: /* --url */
|
||||||
return add(doc, kPools, "url", arg, true);
|
{
|
||||||
|
if (!doc.HasMember(kPools)) {
|
||||||
|
doc.AddMember(rapidjson::StringRef(kPools), rapidjson::kArrayType, doc.GetAllocator());
|
||||||
|
}
|
||||||
|
|
||||||
|
rapidjson::Value &array = doc[kPools];
|
||||||
|
if (array.Size() == 0 || Pool(array[array.Size() - 1]).isValid()) {
|
||||||
|
array.PushBack(rapidjson::kObjectType, doc.GetAllocator());
|
||||||
|
}
|
||||||
|
|
||||||
|
set(doc, array[array.Size() - 1], "url", arg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case IConfig::UserKey: /* --user */
|
case IConfig::UserKey: /* --user */
|
||||||
return add(doc, kPools, "user", arg);
|
return add(doc, kPools, "user", arg);
|
||||||
|
|
|
@ -42,7 +42,8 @@ xmrig::BaseClient::BaseClient(int id, IClientListener *listener) :
|
||||||
m_retries(5),
|
m_retries(5),
|
||||||
m_failures(0),
|
m_failures(0),
|
||||||
m_state(UnconnectedState),
|
m_state(UnconnectedState),
|
||||||
m_retryPause(5000)
|
m_retryPause(5000),
|
||||||
|
m_enabled(true)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,8 @@ protected:
|
||||||
HostLookupState,
|
HostLookupState,
|
||||||
ConnectingState,
|
ConnectingState,
|
||||||
ConnectedState,
|
ConnectedState,
|
||||||
ClosingState
|
ClosingState,
|
||||||
|
ReconnectingState
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool isQuiet() const { return m_quiet || m_failures >= m_retries; }
|
inline bool isQuiet() const { return m_quiet || m_failures >= m_retries; }
|
||||||
|
|
|
@ -70,21 +70,15 @@ static const char *states[] = {
|
||||||
"host-lookup",
|
"host-lookup",
|
||||||
"connecting",
|
"connecting",
|
||||||
"connected",
|
"connected",
|
||||||
"closing"
|
"closing",
|
||||||
|
"reconnecting"
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
xmrig::Client::Client(int id, const char *agent, IClientListener *listener) :
|
xmrig::Client::Client(int id, const char *agent, IClientListener *listener) :
|
||||||
BaseClient(id, listener),
|
BaseClient(id, listener),
|
||||||
m_agent(agent),
|
m_agent(agent)
|
||||||
m_tls(nullptr),
|
|
||||||
m_expire(0),
|
|
||||||
m_jobs(0),
|
|
||||||
m_keepAlive(0),
|
|
||||||
m_key(0),
|
|
||||||
m_stream(nullptr),
|
|
||||||
m_socket(nullptr)
|
|
||||||
{
|
{
|
||||||
m_key = m_storage.add(this);
|
m_key = m_storage.add(this);
|
||||||
m_dns = new Dns(this);
|
m_dns = new Dns(this);
|
||||||
|
@ -234,10 +228,16 @@ void xmrig::Client::tick(uint64_t now)
|
||||||
else if (m_keepAlive && now > m_keepAlive) {
|
else if (m_keepAlive && now > m_keepAlive) {
|
||||||
ping();
|
ping();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_expire && now > m_expire && m_state == ConnectingState) {
|
if (m_state == ReconnectingState && m_expire && now > m_expire) {
|
||||||
connect();
|
return connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_state == ConnectingState && m_expire && now > m_expire) {
|
||||||
|
return reconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -447,7 +447,6 @@ int xmrig::Client::resolve(const String &host)
|
||||||
{
|
{
|
||||||
setState(HostLookupState);
|
setState(HostLookupState);
|
||||||
|
|
||||||
m_expire = 0;
|
|
||||||
m_recvBuf.reset();
|
m_recvBuf.reset();
|
||||||
|
|
||||||
if (m_failures == -1) {
|
if (m_failures == -1) {
|
||||||
|
@ -754,6 +753,8 @@ void xmrig::Client::parseResponse(int64_t id, const rapidjson::Value &result, co
|
||||||
void xmrig::Client::ping()
|
void xmrig::Client::ping()
|
||||||
{
|
{
|
||||||
send(snprintf(m_sendBuf, sizeof(m_sendBuf), "{\"id\":%" PRId64 ",\"jsonrpc\":\"2.0\",\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"}}\n", m_sequence, m_rpcId.data()));
|
send(snprintf(m_sendBuf, sizeof(m_sendBuf), "{\"id\":%" PRId64 ",\"jsonrpc\":\"2.0\",\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"}}\n", m_sequence, m_rpcId.data()));
|
||||||
|
|
||||||
|
m_keepAlive = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -810,12 +811,10 @@ void xmrig::Client::reconnect()
|
||||||
return m_listener->onClose(this, -1);
|
return m_listener->onClose(this, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
setState(ConnectingState);
|
setState(ReconnectingState);
|
||||||
|
|
||||||
m_failures++;
|
m_failures++;
|
||||||
m_listener->onClose(this, static_cast<int>(m_failures));
|
m_listener->onClose(this, static_cast<int>(m_failures));
|
||||||
|
|
||||||
m_expire = Chrono::steadyMSecs() + m_retryPause;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -827,6 +826,23 @@ void xmrig::Client::setState(SocketState state)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case HostLookupState:
|
||||||
|
m_expire = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ConnectingState:
|
||||||
|
m_expire = Chrono::steadyMSecs() + kConnectTimeout;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ReconnectingState:
|
||||||
|
m_expire = Chrono::steadyMSecs() + m_retryPause;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
m_state = state;
|
m_state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,12 +56,13 @@ class JobResult;
|
||||||
class Client : public BaseClient, public IDnsListener, public ILineListener
|
class Client : public BaseClient, public IDnsListener, public ILineListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
constexpr static int kResponseTimeout = 20 * 1000;
|
constexpr static uint64_t kConnectTimeout = 20 * 1000;
|
||||||
|
constexpr static uint64_t kResponseTimeout = 20 * 1000;
|
||||||
|
|
||||||
# ifdef XMRIG_FEATURE_TLS
|
# ifdef XMRIG_FEATURE_TLS
|
||||||
constexpr static int kInputBufferSize = 1024 * 16;
|
constexpr static size_t kInputBufferSize = 1024 * 16;
|
||||||
# else
|
# else
|
||||||
constexpr static int kInputBufferSize = 1024 * 2;
|
constexpr static size_t kInputBufferSize = 1024 * 2;
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
Client(int id, const char *agent, IClientListener *listener);
|
Client(int id, const char *agent, IClientListener *listener);
|
||||||
|
@ -122,19 +123,19 @@ private:
|
||||||
|
|
||||||
static inline Client *getClient(void *data) { return m_storage.get(data); }
|
static inline Client *getClient(void *data) { return m_storage.get(data); }
|
||||||
|
|
||||||
char m_sendBuf[2048];
|
char m_sendBuf[2048] = { 0 };
|
||||||
const char *m_agent;
|
const char *m_agent;
|
||||||
Dns *m_dns;
|
Dns *m_dns;
|
||||||
RecvBuf<kInputBufferSize> m_recvBuf;
|
RecvBuf<kInputBufferSize> m_recvBuf;
|
||||||
std::bitset<EXT_MAX> m_extensions;
|
std::bitset<EXT_MAX> m_extensions;
|
||||||
String m_rpcId;
|
String m_rpcId;
|
||||||
Tls *m_tls;
|
Tls *m_tls = nullptr;
|
||||||
uint64_t m_expire;
|
uint64_t m_expire = 0;
|
||||||
uint64_t m_jobs;
|
uint64_t m_jobs = 0;
|
||||||
uint64_t m_keepAlive;
|
uint64_t m_keepAlive = 0;
|
||||||
uintptr_t m_key;
|
uintptr_t m_key = 0;
|
||||||
uv_stream_t *m_stream;
|
uv_stream_t *m_stream = nullptr;
|
||||||
uv_tcp_t *m_socket;
|
uv_tcp_t *m_socket = nullptr;
|
||||||
|
|
||||||
static Storage<Client> m_storage;
|
static Storage<Client> m_storage;
|
||||||
};
|
};
|
||||||
|
|
|
@ -200,6 +200,9 @@ bool xmrig::Pool::isEqual(const Pool &other) const
|
||||||
bool xmrig::Pool::parse(const char *url)
|
bool xmrig::Pool::parse(const char *url)
|
||||||
{
|
{
|
||||||
assert(url != nullptr);
|
assert(url != nullptr);
|
||||||
|
if (url == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const char *p = strstr(url, "://");
|
const char *p = strstr(url, "://");
|
||||||
const char *base = url;
|
const char *base = url;
|
||||||
|
|
|
@ -96,6 +96,8 @@ void xmrig::ConfigTransform::finalize(rapidjson::Document &doc)
|
||||||
BaseTransform::finalize(doc);
|
BaseTransform::finalize(doc);
|
||||||
|
|
||||||
if (m_threads) {
|
if (m_threads) {
|
||||||
|
doc.AddMember("version", 1, allocator);
|
||||||
|
|
||||||
if (!doc.HasMember(kCpu)) {
|
if (!doc.HasMember(kCpu)) {
|
||||||
doc.AddMember(StringRef(kCpu), Value(kObjectType), allocator);
|
doc.AddMember(StringRef(kCpu), Value(kObjectType), allocator);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1593,3 +1593,7 @@ FN_PREFIX(CryptonightR_instruction_mov254):
|
||||||
FN_PREFIX(CryptonightR_instruction_mov255):
|
FN_PREFIX(CryptonightR_instruction_mov255):
|
||||||
|
|
||||||
FN_PREFIX(CryptonightR_instruction_mov256):
|
FN_PREFIX(CryptonightR_instruction_mov256):
|
||||||
|
|
||||||
|
#if defined(__linux__) && defined(__ELF__)
|
||||||
|
.section .note.GNU-stack,"",%progbits
|
||||||
|
#endif
|
||||||
|
|
|
@ -71,3 +71,7 @@ FN_PREFIX(cnv2_rwz_double_mainloop_asm):
|
||||||
add rsp, 48
|
add rsp, 48
|
||||||
ret 0
|
ret 0
|
||||||
mov eax, 3735929054
|
mov eax, 3735929054
|
||||||
|
|
||||||
|
#if defined(__linux__) && defined(__ELF__)
|
||||||
|
.section .note.GNU-stack,"",%progbits
|
||||||
|
#endif
|
||||||
|
|
|
@ -263,19 +263,6 @@ int rxa2_validate_inputs(const argon2_context *context) {
|
||||||
return ARGON2_INCORRECT_PARAMETER;
|
return ARGON2_INCORRECT_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NULL == context->out) {
|
|
||||||
return ARGON2_OUTPUT_PTR_NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Validate output length */
|
|
||||||
if (ARGON2_MIN_OUTLEN > context->outlen) {
|
|
||||||
return ARGON2_OUTPUT_TOO_SHORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ARGON2_MAX_OUTLEN < context->outlen) {
|
|
||||||
return ARGON2_OUTPUT_TOO_LONG;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Validate password (required param) */
|
/* Validate password (required param) */
|
||||||
if (NULL == context->pwd) {
|
if (NULL == context->pwd) {
|
||||||
if (0 != context->pwdlen) {
|
if (0 != context->pwdlen) {
|
||||||
|
|
|
@ -46,7 +46,7 @@ namespace randomx {
|
||||||
return data[dataIndex++];
|
return data[dataIndex++];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Blake2Generator::getInt32() {
|
uint32_t Blake2Generator::getUInt32() {
|
||||||
checkData(4);
|
checkData(4);
|
||||||
auto ret = load32(&data[dataIndex]);
|
auto ret = load32(&data[dataIndex]);
|
||||||
dataIndex += 4;
|
dataIndex += 4;
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace randomx {
|
||||||
public:
|
public:
|
||||||
Blake2Generator(const void* seed, size_t seedSize, int nonce = 0);
|
Blake2Generator(const void* seed, size_t seedSize, int nonce = 0);
|
||||||
uint8_t getByte();
|
uint8_t getByte();
|
||||||
uint32_t getInt32();
|
uint32_t getUInt32();
|
||||||
private:
|
private:
|
||||||
void checkData(const size_t);
|
void checkData(const size_t);
|
||||||
|
|
||||||
|
|
|
@ -244,7 +244,7 @@ namespace randomx {
|
||||||
|
|
||||||
if (opcode < RandomX_CurrentConfig.CEIL_IMUL_RCP) {
|
if (opcode < RandomX_CurrentConfig.CEIL_IMUL_RCP) {
|
||||||
uint64_t divisor = instr.getImm32();
|
uint64_t divisor = instr.getImm32();
|
||||||
if (!isPowerOf2(divisor)) {
|
if (!isZeroOrPowerOf2(divisor)) {
|
||||||
auto dst = instr.dst % RegistersCount;
|
auto dst = instr.dst % RegistersCount;
|
||||||
ibc.type = InstructionType::IMUL_R;
|
ibc.type = InstructionType::IMUL_R;
|
||||||
ibc.idst = &nreg->r[dst];
|
ibc.idst = &nreg->r[dst];
|
||||||
|
|
|
@ -137,7 +137,7 @@ namespace randomx {
|
||||||
constexpr int RegisterNeedsDisplacement = 5; //x86 r13 register
|
constexpr int RegisterNeedsDisplacement = 5; //x86 r13 register
|
||||||
constexpr int RegisterNeedsSib = 4; //x86 r12 register
|
constexpr int RegisterNeedsSib = 4; //x86 r12 register
|
||||||
|
|
||||||
inline bool isPowerOf2(uint64_t x) {
|
inline bool isZeroOrPowerOf2(uint64_t x) {
|
||||||
return (x & (x - 1)) == 0;
|
return (x & (x - 1)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,13 +77,13 @@ namespace randomx {
|
||||||
void setImm32(uint32_t val) {
|
void setImm32(uint32_t val) {
|
||||||
return store32(&imm32, val);
|
return store32(&imm32, val);
|
||||||
}
|
}
|
||||||
int getModMem() const {
|
uint32_t getModMem() const {
|
||||||
return mod % 4; //bits 0-1
|
return mod & 3; //bits 0-1
|
||||||
}
|
}
|
||||||
int getModShift() const {
|
uint32_t getModShift() const {
|
||||||
return (mod >> 2) % 4; //bits 2-3
|
return (mod >> 2) & 3; //bits 2-3
|
||||||
}
|
}
|
||||||
int getModCond() const {
|
uint32_t getModCond() const {
|
||||||
return mod >> 4; //bits 4-7
|
return mod >> 4; //bits 4-7
|
||||||
}
|
}
|
||||||
void setMod(uint8_t val) {
|
void setMod(uint8_t val) {
|
||||||
|
|
|
@ -181,7 +181,7 @@ namespace randomx {
|
||||||
static const uint8_t REX_TEST[] = { 0x49, 0xF7 };
|
static const uint8_t REX_TEST[] = { 0x49, 0xF7 };
|
||||||
static const uint8_t JZ[] = { 0x0f, 0x84 };
|
static const uint8_t JZ[] = { 0x0f, 0x84 };
|
||||||
static const uint8_t RET = 0xc3;
|
static const uint8_t RET = 0xc3;
|
||||||
static const uint8_t LEA_32[] = { 0x67, 0x41, 0x8d };
|
static const uint8_t LEA_32[] = { 0x41, 0x8d };
|
||||||
static const uint8_t MOVNTI[] = { 0x4c, 0x0f, 0xc3 };
|
static const uint8_t MOVNTI[] = { 0x4c, 0x0f, 0xc3 };
|
||||||
static const uint8_t ADD_EBX_I[] = { 0x81, 0xc3 };
|
static const uint8_t ADD_EBX_I[] = { 0x81, 0xc3 };
|
||||||
|
|
||||||
|
@ -197,7 +197,7 @@ namespace randomx {
|
||||||
// static const uint8_t* NOPX[] = { NOP1, NOP2, NOP3, NOP4, NOP5, NOP6, NOP7, NOP8 };
|
// static const uint8_t* NOPX[] = { NOP1, NOP2, NOP3, NOP4, NOP5, NOP6, NOP7, NOP8 };
|
||||||
|
|
||||||
size_t JitCompilerX86::getCodeSize() {
|
size_t JitCompilerX86::getCodeSize() {
|
||||||
return codePos - prologueSize;
|
return codePos < prologueSize ? 0 : codePos - prologueSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
JitCompilerX86::JitCompilerX86() {
|
JitCompilerX86::JitCompilerX86() {
|
||||||
|
@ -219,12 +219,12 @@ namespace randomx {
|
||||||
|
|
||||||
void JitCompilerX86::generateProgramLight(Program& prog, ProgramConfiguration& pcfg, uint32_t datasetOffset) {
|
void JitCompilerX86::generateProgramLight(Program& prog, ProgramConfiguration& pcfg, uint32_t datasetOffset) {
|
||||||
generateProgramPrologue(prog, pcfg);
|
generateProgramPrologue(prog, pcfg);
|
||||||
emit(RandomX_CurrentConfig.codeReadDatasetLightSshInitTweaked, readDatasetLightInitSize);
|
emit(RandomX_CurrentConfig.codeReadDatasetLightSshInitTweaked, readDatasetLightInitSize, code, codePos);
|
||||||
emit(ADD_EBX_I);
|
emit(ADD_EBX_I, code, codePos);
|
||||||
emit32(datasetOffset / CacheLineSize);
|
emit32(datasetOffset / CacheLineSize, code, codePos);
|
||||||
emitByte(CALL);
|
emitByte(CALL, code, codePos);
|
||||||
emit32(superScalarHashOffset - (codePos + 4));
|
emit32(superScalarHashOffset - (codePos + 4), code, codePos);
|
||||||
emit(codeReadDatasetLightSshFin, readDatasetLightFinSize);
|
emit(codeReadDatasetLightSshFin, readDatasetLightFinSize, code, codePos);
|
||||||
generateProgramEpilogue(prog);
|
generateProgramEpilogue(prog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,23 +238,23 @@ namespace randomx {
|
||||||
Instruction& instr = prog(i);
|
Instruction& instr = prog(i);
|
||||||
generateSuperscalarCode(instr, reciprocalCache);
|
generateSuperscalarCode(instr, reciprocalCache);
|
||||||
}
|
}
|
||||||
emit(codeShhLoad, codeSshLoadSize);
|
emit(codeShhLoad, codeSshLoadSize, code, codePos);
|
||||||
if (j < RandomX_CurrentConfig.CacheAccesses - 1) {
|
if (j < RandomX_CurrentConfig.CacheAccesses - 1) {
|
||||||
emit(REX_MOV_RR64);
|
emit(REX_MOV_RR64, code, codePos);
|
||||||
emitByte(0xd8 + prog.getAddressRegister());
|
emitByte(0xd8 + prog.getAddressRegister(), code, codePos);
|
||||||
emit(RandomX_CurrentConfig.codeShhPrefetchTweaked, codeSshPrefetchSize);
|
emit(RandomX_CurrentConfig.codeShhPrefetchTweaked, codeSshPrefetchSize, code, codePos);
|
||||||
#ifdef RANDOMX_ALIGN
|
#ifdef RANDOMX_ALIGN
|
||||||
int align = (codePos % 16);
|
int align = (codePos % 16);
|
||||||
while (align != 0) {
|
while (align != 0) {
|
||||||
int nopSize = 16 - align;
|
int nopSize = 16 - align;
|
||||||
if (nopSize > 8) nopSize = 8;
|
if (nopSize > 8) nopSize = 8;
|
||||||
emit(NOPX[nopSize - 1], nopSize);
|
emit(NOPX[nopSize - 1], nopSize, code, codePos);
|
||||||
align = (codePos % 16);
|
align = (codePos % 16);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
emitByte(RET);
|
emitByte(RET, code, codePos);
|
||||||
}
|
}
|
||||||
|
|
||||||
template
|
template
|
||||||
|
@ -265,508 +265,664 @@ namespace randomx {
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::generateProgramPrologue(Program& prog, ProgramConfiguration& pcfg) {
|
void JitCompilerX86::generateProgramPrologue(Program& prog, ProgramConfiguration& pcfg) {
|
||||||
instructionOffsets.clear();
|
memset(registerUsage, -1, sizeof(registerUsage));
|
||||||
for (unsigned i = 0; i < 8; ++i) {
|
|
||||||
registerUsage[i] = -1;
|
|
||||||
}
|
|
||||||
codePos = prologueSize;
|
codePos = prologueSize;
|
||||||
memcpy(code + codePos - 48, &pcfg.eMask, sizeof(pcfg.eMask));
|
memcpy(code + codePos - 48, &pcfg.eMask, sizeof(pcfg.eMask));
|
||||||
emit(REX_XOR_RAX_R64);
|
emit(REX_XOR_RAX_R64, code, codePos);
|
||||||
emitByte(0xc0 + pcfg.readReg0);
|
emitByte(0xc0 + pcfg.readReg0, code, codePos);
|
||||||
emit(REX_XOR_RAX_R64);
|
emit(REX_XOR_RAX_R64, code, codePos);
|
||||||
emitByte(0xc0 + pcfg.readReg1);
|
emitByte(0xc0 + pcfg.readReg1, code, codePos);
|
||||||
memcpy(code + codePos, RandomX_CurrentConfig.codeLoopLoadTweaked, loopLoadSize);
|
memcpy(code + codePos, RandomX_CurrentConfig.codeLoopLoadTweaked, loopLoadSize);
|
||||||
codePos += loopLoadSize;
|
codePos += loopLoadSize;
|
||||||
for (unsigned i = 0; i < prog.getSize(); ++i) {
|
for (unsigned i = 0; i < prog.getSize(); ++i) {
|
||||||
Instruction& instr = prog(i);
|
Instruction& instr = prog(i);
|
||||||
instr.src %= RegistersCount;
|
instr.src %= RegistersCount;
|
||||||
instr.dst %= RegistersCount;
|
instr.dst %= RegistersCount;
|
||||||
generateCode(instr, i);
|
instructionOffsets[i] = codePos;
|
||||||
|
(this->*(engine[instr.opcode]))(instr, i);
|
||||||
}
|
}
|
||||||
emit(REX_MOV_RR);
|
emit(REX_MOV_RR, code, codePos);
|
||||||
emitByte(0xc0 + pcfg.readReg2);
|
emitByte(0xc0 + pcfg.readReg2, code, codePos);
|
||||||
emit(REX_XOR_EAX);
|
emit(REX_XOR_EAX, code, codePos);
|
||||||
emitByte(0xc0 + pcfg.readReg3);
|
emitByte(0xc0 + pcfg.readReg3, code, codePos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::generateProgramEpilogue(Program& prog) {
|
void JitCompilerX86::generateProgramEpilogue(Program& prog) {
|
||||||
memcpy(code + codePos, codeLoopStore, loopStoreSize);
|
memcpy(code + codePos, codeLoopStore, loopStoreSize);
|
||||||
codePos += loopStoreSize;
|
codePos += loopStoreSize;
|
||||||
emit(SUB_EBX);
|
emit(SUB_EBX, code, codePos);
|
||||||
emit(JNZ);
|
emit(JNZ, code, codePos);
|
||||||
emit32(prologueSize - codePos - 4);
|
emit32(prologueSize - codePos - 4, code, codePos);
|
||||||
emitByte(JMP);
|
emitByte(JMP, code, codePos);
|
||||||
emit32(epilogueOffset - codePos - 4);
|
emit32(epilogueOffset - codePos - 4, code, codePos);
|
||||||
}
|
|
||||||
|
|
||||||
void JitCompilerX86::generateCode(Instruction& instr, int i) {
|
|
||||||
instructionOffsets.push_back(codePos);
|
|
||||||
auto generator = engine[instr.opcode];
|
|
||||||
(this->*generator)(instr, i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::generateSuperscalarCode(Instruction& instr, std::vector<uint64_t> &reciprocalCache) {
|
void JitCompilerX86::generateSuperscalarCode(Instruction& instr, std::vector<uint64_t> &reciprocalCache) {
|
||||||
switch ((SuperscalarInstructionType)instr.opcode)
|
switch ((SuperscalarInstructionType)instr.opcode)
|
||||||
{
|
{
|
||||||
case randomx::SuperscalarInstructionType::ISUB_R:
|
case randomx::SuperscalarInstructionType::ISUB_R:
|
||||||
emit(REX_SUB_RR);
|
emit(REX_SUB_RR, code, codePos);
|
||||||
emitByte(0xc0 + 8 * instr.dst + instr.src);
|
emitByte(0xc0 + 8 * instr.dst + instr.src, code, codePos);
|
||||||
break;
|
break;
|
||||||
case randomx::SuperscalarInstructionType::IXOR_R:
|
case randomx::SuperscalarInstructionType::IXOR_R:
|
||||||
emit(REX_XOR_RR);
|
emit(REX_XOR_RR, code, codePos);
|
||||||
emitByte(0xc0 + 8 * instr.dst + instr.src);
|
emitByte(0xc0 + 8 * instr.dst + instr.src, code, codePos);
|
||||||
break;
|
break;
|
||||||
case randomx::SuperscalarInstructionType::IADD_RS:
|
case randomx::SuperscalarInstructionType::IADD_RS:
|
||||||
emit(REX_LEA);
|
emit(REX_LEA, code, codePos);
|
||||||
emitByte(0x04 + 8 * instr.dst);
|
emitByte(0x04 + 8 * instr.dst, code, codePos);
|
||||||
genSIB(instr.getModShift(), instr.src, instr.dst);
|
genSIB(instr.getModShift(), instr.src, instr.dst, code, codePos);
|
||||||
break;
|
break;
|
||||||
case randomx::SuperscalarInstructionType::IMUL_R:
|
case randomx::SuperscalarInstructionType::IMUL_R:
|
||||||
emit(REX_IMUL_RR);
|
emit(REX_IMUL_RR, code, codePos);
|
||||||
emitByte(0xc0 + 8 * instr.dst + instr.src);
|
emitByte(0xc0 + 8 * instr.dst + instr.src, code, codePos);
|
||||||
break;
|
break;
|
||||||
case randomx::SuperscalarInstructionType::IROR_C:
|
case randomx::SuperscalarInstructionType::IROR_C:
|
||||||
emit(REX_ROT_I8);
|
emit(REX_ROT_I8, code, codePos);
|
||||||
emitByte(0xc8 + instr.dst);
|
emitByte(0xc8 + instr.dst, code, codePos);
|
||||||
emitByte(instr.getImm32() & 63);
|
emitByte(instr.getImm32() & 63, code, codePos);
|
||||||
break;
|
break;
|
||||||
case randomx::SuperscalarInstructionType::IADD_C7:
|
case randomx::SuperscalarInstructionType::IADD_C7:
|
||||||
emit(REX_81);
|
emit(REX_81, code, codePos);
|
||||||
emitByte(0xc0 + instr.dst);
|
emitByte(0xc0 + instr.dst, code, codePos);
|
||||||
emit32(instr.getImm32());
|
emit32(instr.getImm32(), code, codePos);
|
||||||
break;
|
break;
|
||||||
case randomx::SuperscalarInstructionType::IXOR_C7:
|
case randomx::SuperscalarInstructionType::IXOR_C7:
|
||||||
emit(REX_XOR_RI);
|
emit(REX_XOR_RI, code, codePos);
|
||||||
emitByte(0xf0 + instr.dst);
|
emitByte(0xf0 + instr.dst, code, codePos);
|
||||||
emit32(instr.getImm32());
|
emit32(instr.getImm32(), code, codePos);
|
||||||
break;
|
break;
|
||||||
case randomx::SuperscalarInstructionType::IADD_C8:
|
case randomx::SuperscalarInstructionType::IADD_C8:
|
||||||
emit(REX_81);
|
emit(REX_81, code, codePos);
|
||||||
emitByte(0xc0 + instr.dst);
|
emitByte(0xc0 + instr.dst, code, codePos);
|
||||||
emit32(instr.getImm32());
|
emit32(instr.getImm32(), code, codePos);
|
||||||
#ifdef RANDOMX_ALIGN
|
#ifdef RANDOMX_ALIGN
|
||||||
emit(NOP1);
|
emit(NOP1, code, codePos);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case randomx::SuperscalarInstructionType::IXOR_C8:
|
case randomx::SuperscalarInstructionType::IXOR_C8:
|
||||||
emit(REX_XOR_RI);
|
emit(REX_XOR_RI, code, codePos);
|
||||||
emitByte(0xf0 + instr.dst);
|
emitByte(0xf0 + instr.dst, code, codePos);
|
||||||
emit32(instr.getImm32());
|
emit32(instr.getImm32(), code, codePos);
|
||||||
#ifdef RANDOMX_ALIGN
|
#ifdef RANDOMX_ALIGN
|
||||||
emit(NOP1);
|
emit(NOP1, code, codePos);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case randomx::SuperscalarInstructionType::IADD_C9:
|
case randomx::SuperscalarInstructionType::IADD_C9:
|
||||||
emit(REX_81);
|
emit(REX_81, code, codePos);
|
||||||
emitByte(0xc0 + instr.dst);
|
emitByte(0xc0 + instr.dst, code, codePos);
|
||||||
emit32(instr.getImm32());
|
emit32(instr.getImm32(), code, codePos);
|
||||||
#ifdef RANDOMX_ALIGN
|
#ifdef RANDOMX_ALIGN
|
||||||
emit(NOP2);
|
emit(NOP2, code, codePos);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case randomx::SuperscalarInstructionType::IXOR_C9:
|
case randomx::SuperscalarInstructionType::IXOR_C9:
|
||||||
emit(REX_XOR_RI);
|
emit(REX_XOR_RI, code, codePos);
|
||||||
emitByte(0xf0 + instr.dst);
|
emitByte(0xf0 + instr.dst, code, codePos);
|
||||||
emit32(instr.getImm32());
|
emit32(instr.getImm32(), code, codePos);
|
||||||
#ifdef RANDOMX_ALIGN
|
#ifdef RANDOMX_ALIGN
|
||||||
emit(NOP2);
|
emit(NOP2, code, codePos);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case randomx::SuperscalarInstructionType::IMULH_R:
|
case randomx::SuperscalarInstructionType::IMULH_R:
|
||||||
emit(REX_MOV_RR64);
|
emit(REX_MOV_RR64, code, codePos);
|
||||||
emitByte(0xc0 + instr.dst);
|
emitByte(0xc0 + instr.dst, code, codePos);
|
||||||
emit(REX_MUL_R);
|
emit(REX_MUL_R, code, codePos);
|
||||||
emitByte(0xe0 + instr.src);
|
emitByte(0xe0 + instr.src, code, codePos);
|
||||||
emit(REX_MOV_R64R);
|
emit(REX_MOV_R64R, code, codePos);
|
||||||
emitByte(0xc2 + 8 * instr.dst);
|
emitByte(0xc2 + 8 * instr.dst, code, codePos);
|
||||||
break;
|
break;
|
||||||
case randomx::SuperscalarInstructionType::ISMULH_R:
|
case randomx::SuperscalarInstructionType::ISMULH_R:
|
||||||
emit(REX_MOV_RR64);
|
emit(REX_MOV_RR64, code, codePos);
|
||||||
emitByte(0xc0 + instr.dst);
|
emitByte(0xc0 + instr.dst, code, codePos);
|
||||||
emit(REX_MUL_R);
|
emit(REX_MUL_R, code, codePos);
|
||||||
emitByte(0xe8 + instr.src);
|
emitByte(0xe8 + instr.src, code, codePos);
|
||||||
emit(REX_MOV_R64R);
|
emit(REX_MOV_R64R, code, codePos);
|
||||||
emitByte(0xc2 + 8 * instr.dst);
|
emitByte(0xc2 + 8 * instr.dst, code, codePos);
|
||||||
break;
|
break;
|
||||||
case randomx::SuperscalarInstructionType::IMUL_RCP:
|
case randomx::SuperscalarInstructionType::IMUL_RCP:
|
||||||
emit(MOV_RAX_I);
|
emit(MOV_RAX_I, code, codePos);
|
||||||
emit64(reciprocalCache[instr.getImm32()]);
|
emit64(reciprocalCache[instr.getImm32()], code, codePos);
|
||||||
emit(REX_IMUL_RM);
|
emit(REX_IMUL_RM, code, codePos);
|
||||||
emitByte(0xc0 + 8 * instr.dst);
|
emitByte(0xc0 + 8 * instr.dst, code, codePos);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
UNREACHABLE;
|
UNREACHABLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::genAddressReg(Instruction& instr, bool rax = true) {
|
void JitCompilerX86::genAddressReg(Instruction& instr, uint8_t* code, int& codePos, bool rax) {
|
||||||
emit(LEA_32);
|
emit(LEA_32, code, codePos);
|
||||||
emitByte(0x80 + instr.src + (rax ? 0 : 8));
|
emitByte(0x80 + instr.src + (rax ? 0 : 8), code, codePos);
|
||||||
if (instr.src == RegisterNeedsSib) {
|
if (instr.src == RegisterNeedsSib) {
|
||||||
emitByte(0x24);
|
emitByte(0x24, code, codePos);
|
||||||
}
|
}
|
||||||
emit32(instr.getImm32());
|
emit32(instr.getImm32(), code, codePos);
|
||||||
if (rax)
|
if (rax)
|
||||||
emitByte(AND_EAX_I);
|
emitByte(AND_EAX_I, code, codePos);
|
||||||
else
|
else
|
||||||
emit(AND_ECX_I);
|
emit(AND_ECX_I, code, codePos);
|
||||||
emit32(instr.getModMem() ? ScratchpadL1Mask : ScratchpadL2Mask);
|
emit32(instr.getModMem() ? ScratchpadL1Mask : ScratchpadL2Mask, code, codePos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::genAddressRegDst(Instruction& instr) {
|
void JitCompilerX86::genAddressRegDst(Instruction& instr, uint8_t* code, int& codePos) {
|
||||||
emit(LEA_32);
|
emit(LEA_32, code, codePos);
|
||||||
emitByte(0x80 + instr.dst);
|
emitByte(0x80 + instr.dst, code, codePos);
|
||||||
if (instr.dst == RegisterNeedsSib) {
|
if (instr.dst == RegisterNeedsSib) {
|
||||||
emitByte(0x24);
|
emitByte(0x24, code, codePos);
|
||||||
}
|
}
|
||||||
emit32(instr.getImm32());
|
emit32(instr.getImm32(), code, codePos);
|
||||||
emitByte(AND_EAX_I);
|
emitByte(AND_EAX_I, code, codePos);
|
||||||
if (instr.getModCond() < StoreL3Condition) {
|
if (instr.getModCond() < StoreL3Condition) {
|
||||||
emit32(instr.getModMem() ? ScratchpadL1Mask : ScratchpadL2Mask);
|
emit32(instr.getModMem() ? ScratchpadL1Mask : ScratchpadL2Mask, code, codePos);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
emit32(ScratchpadL3Mask);
|
emit32(ScratchpadL3Mask, code, codePos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::genAddressImm(Instruction& instr) {
|
void JitCompilerX86::genAddressImm(Instruction& instr, uint8_t* code, int& codePos) {
|
||||||
emit32(instr.getImm32() & ScratchpadL3Mask);
|
emit32(instr.getImm32() & ScratchpadL3Mask, code, codePos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const uint32_t template_IADD_RS[8] = {
|
||||||
|
0x048d4f,
|
||||||
|
0x0c8d4f,
|
||||||
|
0x148d4f,
|
||||||
|
0x1c8d4f,
|
||||||
|
0x248d4f,
|
||||||
|
0xac8d4f,
|
||||||
|
0x348d4f,
|
||||||
|
0x3c8d4f,
|
||||||
|
};
|
||||||
|
|
||||||
void JitCompilerX86::h_IADD_RS(Instruction& instr, int i) {
|
void JitCompilerX86::h_IADD_RS(Instruction& instr, int i) {
|
||||||
|
int pos = codePos;
|
||||||
|
uint8_t* const p = code + pos;
|
||||||
|
|
||||||
registerUsage[instr.dst] = i;
|
registerUsage[instr.dst] = i;
|
||||||
emit(REX_LEA);
|
|
||||||
if (instr.dst == RegisterNeedsDisplacement)
|
const uint32_t sib = (instr.getModShift() << 6) | (instr.src << 3) | instr.dst;
|
||||||
emitByte(0xac);
|
*(uint32_t*)(p) = template_IADD_RS[instr.dst] | (sib << 24);
|
||||||
else
|
*(uint32_t*)(p + 4) = instr.getImm32();
|
||||||
emitByte(0x04 + 8 * instr.dst);
|
|
||||||
genSIB(instr.getModShift(), instr.src, instr.dst);
|
codePos = pos + ((instr.dst == RegisterNeedsDisplacement) ? 8 : 4);
|
||||||
if (instr.dst == RegisterNeedsDisplacement)
|
|
||||||
emit32(instr.getImm32());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const uint32_t template_IADD_M[8] = {
|
||||||
|
0x0604034c,
|
||||||
|
0x060c034c,
|
||||||
|
0x0614034c,
|
||||||
|
0x061c034c,
|
||||||
|
0x0624034c,
|
||||||
|
0x062c034c,
|
||||||
|
0x0634034c,
|
||||||
|
0x063c034c,
|
||||||
|
};
|
||||||
|
|
||||||
void JitCompilerX86::h_IADD_M(Instruction& instr, int i) {
|
void JitCompilerX86::h_IADD_M(Instruction& instr, int i) {
|
||||||
|
uint8_t* const p = code;
|
||||||
|
int pos = codePos;
|
||||||
|
|
||||||
registerUsage[instr.dst] = i;
|
registerUsage[instr.dst] = i;
|
||||||
if (instr.src != instr.dst) {
|
if (instr.src != instr.dst) {
|
||||||
genAddressReg(instr);
|
genAddressReg(instr, p, pos);
|
||||||
emit(REX_ADD_RM);
|
emit32(template_IADD_M[instr.dst], p, pos);
|
||||||
emitByte(0x04 + 8 * instr.dst);
|
|
||||||
emitByte(0x06);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
emit(REX_ADD_RM);
|
emit(REX_ADD_RM, p, pos);
|
||||||
emitByte(0x86 + 8 * instr.dst);
|
emitByte(0x86 + 8 * instr.dst, p, pos);
|
||||||
genAddressImm(instr);
|
genAddressImm(instr, p, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::genSIB(int scale, int index, int base) {
|
void JitCompilerX86::genSIB(int scale, int index, int base, uint8_t* code, int& codePos) {
|
||||||
emitByte((scale << 6) | (index << 3) | base);
|
emitByte((scale << 6) | (index << 3) | base, code, codePos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_ISUB_R(Instruction& instr, int i) {
|
void JitCompilerX86::h_ISUB_R(Instruction& instr, int i) {
|
||||||
|
uint8_t* const p = code;
|
||||||
|
int pos = codePos;
|
||||||
|
|
||||||
registerUsage[instr.dst] = i;
|
registerUsage[instr.dst] = i;
|
||||||
if (instr.src != instr.dst) {
|
if (instr.src != instr.dst) {
|
||||||
emit(REX_SUB_RR);
|
emit(REX_SUB_RR, p, pos);
|
||||||
emitByte(0xc0 + 8 * instr.dst + instr.src);
|
emitByte(0xc0 + 8 * instr.dst + instr.src, p, pos);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
emit(REX_81);
|
emit(REX_81, p, pos);
|
||||||
emitByte(0xe8 + instr.dst);
|
emitByte(0xe8 + instr.dst, p, pos);
|
||||||
emit32(instr.getImm32());
|
emit32(instr.getImm32(), p, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_ISUB_M(Instruction& instr, int i) {
|
void JitCompilerX86::h_ISUB_M(Instruction& instr, int i) {
|
||||||
|
uint8_t* const p = code;
|
||||||
|
int pos = codePos;
|
||||||
|
|
||||||
registerUsage[instr.dst] = i;
|
registerUsage[instr.dst] = i;
|
||||||
if (instr.src != instr.dst) {
|
if (instr.src != instr.dst) {
|
||||||
genAddressReg(instr);
|
genAddressReg(instr, p, pos);
|
||||||
emit(REX_SUB_RM);
|
emit(REX_SUB_RM, p, pos);
|
||||||
emitByte(0x04 + 8 * instr.dst);
|
emitByte(0x04 + 8 * instr.dst, p, pos);
|
||||||
emitByte(0x06);
|
emitByte(0x06, p, pos);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
emit(REX_SUB_RM);
|
emit(REX_SUB_RM, p, pos);
|
||||||
emitByte(0x86 + 8 * instr.dst);
|
emitByte(0x86 + 8 * instr.dst, p, pos);
|
||||||
genAddressImm(instr);
|
genAddressImm(instr, p, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_IMUL_R(Instruction& instr, int i) {
|
void JitCompilerX86::h_IMUL_R(Instruction& instr, int i) {
|
||||||
|
uint8_t* const p = code;
|
||||||
|
int pos = codePos;
|
||||||
|
|
||||||
registerUsage[instr.dst] = i;
|
registerUsage[instr.dst] = i;
|
||||||
if (instr.src != instr.dst) {
|
if (instr.src != instr.dst) {
|
||||||
emit(REX_IMUL_RR);
|
emit(REX_IMUL_RR, p, pos);
|
||||||
emitByte(0xc0 + 8 * instr.dst + instr.src);
|
emitByte(0xc0 + 8 * instr.dst + instr.src, p, pos);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
emit(REX_IMUL_RRI);
|
emit(REX_IMUL_RRI, p, pos);
|
||||||
emitByte(0xc0 + 9 * instr.dst);
|
emitByte(0xc0 + 9 * instr.dst, p, pos);
|
||||||
emit32(instr.getImm32());
|
emit32(instr.getImm32(), p, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_IMUL_M(Instruction& instr, int i) {
|
void JitCompilerX86::h_IMUL_M(Instruction& instr, int i) {
|
||||||
|
uint8_t* const p = code;
|
||||||
|
int pos = codePos;
|
||||||
|
|
||||||
registerUsage[instr.dst] = i;
|
registerUsage[instr.dst] = i;
|
||||||
if (instr.src != instr.dst) {
|
if (instr.src != instr.dst) {
|
||||||
genAddressReg(instr);
|
genAddressReg(instr, p, pos);
|
||||||
emit(REX_IMUL_RM);
|
emit(REX_IMUL_RM, p, pos);
|
||||||
emitByte(0x04 + 8 * instr.dst);
|
emitByte(0x04 + 8 * instr.dst, p, pos);
|
||||||
emitByte(0x06);
|
emitByte(0x06, p, pos);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
emit(REX_IMUL_RM);
|
emit(REX_IMUL_RM, p, pos);
|
||||||
emitByte(0x86 + 8 * instr.dst);
|
emitByte(0x86 + 8 * instr.dst, p, pos);
|
||||||
genAddressImm(instr);
|
genAddressImm(instr, p, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_IMULH_R(Instruction& instr, int i) {
|
void JitCompilerX86::h_IMULH_R(Instruction& instr, int i) {
|
||||||
|
uint8_t* const p = code;
|
||||||
|
int pos = codePos;
|
||||||
|
|
||||||
registerUsage[instr.dst] = i;
|
registerUsage[instr.dst] = i;
|
||||||
emit(REX_MOV_RR64);
|
emit(REX_MOV_RR64, p, pos);
|
||||||
emitByte(0xc0 + instr.dst);
|
emitByte(0xc0 + instr.dst, p, pos);
|
||||||
emit(REX_MUL_R);
|
emit(REX_MUL_R, p, pos);
|
||||||
emitByte(0xe0 + instr.src);
|
emitByte(0xe0 + instr.src, p, pos);
|
||||||
emit(REX_MOV_R64R);
|
emit(REX_MOV_R64R, p, pos);
|
||||||
emitByte(0xc2 + 8 * instr.dst);
|
emitByte(0xc2 + 8 * instr.dst, p, pos);
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_IMULH_M(Instruction& instr, int i) {
|
void JitCompilerX86::h_IMULH_M(Instruction& instr, int i) {
|
||||||
|
uint8_t* const p = code;
|
||||||
|
int pos = codePos;
|
||||||
|
|
||||||
registerUsage[instr.dst] = i;
|
registerUsage[instr.dst] = i;
|
||||||
if (instr.src != instr.dst) {
|
if (instr.src != instr.dst) {
|
||||||
genAddressReg(instr, false);
|
genAddressReg(instr, p, pos, false);
|
||||||
emit(REX_MOV_RR64);
|
emit(REX_MOV_RR64, p, pos);
|
||||||
emitByte(0xc0 + instr.dst);
|
emitByte(0xc0 + instr.dst, p, pos);
|
||||||
emit(REX_MUL_MEM);
|
emit(REX_MUL_MEM, p, pos);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
emit(REX_MOV_RR64);
|
emit(REX_MOV_RR64, p, pos);
|
||||||
emitByte(0xc0 + instr.dst);
|
emitByte(0xc0 + instr.dst, p, pos);
|
||||||
emit(REX_MUL_M);
|
emit(REX_MUL_M, p, pos);
|
||||||
emitByte(0xa6);
|
emitByte(0xa6, p, pos);
|
||||||
genAddressImm(instr);
|
genAddressImm(instr, p, pos);
|
||||||
}
|
}
|
||||||
emit(REX_MOV_R64R);
|
emit(REX_MOV_R64R, p, pos);
|
||||||
emitByte(0xc2 + 8 * instr.dst);
|
emitByte(0xc2 + 8 * instr.dst, p, pos);
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_ISMULH_R(Instruction& instr, int i) {
|
void JitCompilerX86::h_ISMULH_R(Instruction& instr, int i) {
|
||||||
|
uint8_t* const p = code;
|
||||||
|
int pos = codePos;
|
||||||
|
|
||||||
registerUsage[instr.dst] = i;
|
registerUsage[instr.dst] = i;
|
||||||
emit(REX_MOV_RR64);
|
emit(REX_MOV_RR64, p, pos);
|
||||||
emitByte(0xc0 + instr.dst);
|
emitByte(0xc0 + instr.dst, p, pos);
|
||||||
emit(REX_MUL_R);
|
emit(REX_MUL_R, p, pos);
|
||||||
emitByte(0xe8 + instr.src);
|
emitByte(0xe8 + instr.src, p, pos);
|
||||||
emit(REX_MOV_R64R);
|
emit(REX_MOV_R64R, p, pos);
|
||||||
emitByte(0xc2 + 8 * instr.dst);
|
emitByte(0xc2 + 8 * instr.dst, p, pos);
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_ISMULH_M(Instruction& instr, int i) {
|
void JitCompilerX86::h_ISMULH_M(Instruction& instr, int i) {
|
||||||
|
uint8_t* const p = code;
|
||||||
|
int pos = codePos;
|
||||||
|
|
||||||
registerUsage[instr.dst] = i;
|
registerUsage[instr.dst] = i;
|
||||||
if (instr.src != instr.dst) {
|
if (instr.src != instr.dst) {
|
||||||
genAddressReg(instr, false);
|
genAddressReg(instr, p, pos, false);
|
||||||
emit(REX_MOV_RR64);
|
emit(REX_MOV_RR64, p, pos);
|
||||||
emitByte(0xc0 + instr.dst);
|
emitByte(0xc0 + instr.dst, p, pos);
|
||||||
emit(REX_IMUL_MEM);
|
emit(REX_IMUL_MEM, p, pos);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
emit(REX_MOV_RR64);
|
emit(REX_MOV_RR64, p, pos);
|
||||||
emitByte(0xc0 + instr.dst);
|
emitByte(0xc0 + instr.dst, p, pos);
|
||||||
emit(REX_MUL_M);
|
emit(REX_MUL_M, p, pos);
|
||||||
emitByte(0xae);
|
emitByte(0xae, p, pos);
|
||||||
genAddressImm(instr);
|
genAddressImm(instr, p, pos);
|
||||||
}
|
}
|
||||||
emit(REX_MOV_R64R);
|
emit(REX_MOV_R64R, p, pos);
|
||||||
emitByte(0xc2 + 8 * instr.dst);
|
emitByte(0xc2 + 8 * instr.dst, p, pos);
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_IMUL_RCP(Instruction& instr, int i) {
|
void JitCompilerX86::h_IMUL_RCP(Instruction& instr, int i) {
|
||||||
|
uint8_t* const p = code;
|
||||||
|
int pos = codePos;
|
||||||
|
|
||||||
uint64_t divisor = instr.getImm32();
|
uint64_t divisor = instr.getImm32();
|
||||||
if (!isPowerOf2(divisor)) {
|
if (!isZeroOrPowerOf2(divisor)) {
|
||||||
registerUsage[instr.dst] = i;
|
registerUsage[instr.dst] = i;
|
||||||
emit(MOV_RAX_I);
|
emit(MOV_RAX_I, p, pos);
|
||||||
emit64(randomx_reciprocal_fast(divisor));
|
emit64(randomx_reciprocal_fast(divisor), p, pos);
|
||||||
emit(REX_IMUL_RM);
|
emit(REX_IMUL_RM, p, pos);
|
||||||
emitByte(0xc0 + 8 * instr.dst);
|
emitByte(0xc0 + 8 * instr.dst, p, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_INEG_R(Instruction& instr, int i) {
|
void JitCompilerX86::h_INEG_R(Instruction& instr, int i) {
|
||||||
|
uint8_t* const p = code;
|
||||||
|
int pos = codePos;
|
||||||
|
|
||||||
registerUsage[instr.dst] = i;
|
registerUsage[instr.dst] = i;
|
||||||
emit(REX_NEG);
|
emit(REX_NEG, p, pos);
|
||||||
emitByte(0xd8 + instr.dst);
|
emitByte(0xd8 + instr.dst, p, pos);
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_IXOR_R(Instruction& instr, int i) {
|
void JitCompilerX86::h_IXOR_R(Instruction& instr, int i) {
|
||||||
|
uint8_t* const p = code;
|
||||||
|
int pos = codePos;
|
||||||
|
|
||||||
registerUsage[instr.dst] = i;
|
registerUsage[instr.dst] = i;
|
||||||
if (instr.src != instr.dst) {
|
if (instr.src != instr.dst) {
|
||||||
emit(REX_XOR_RR);
|
emit(REX_XOR_RR, p, pos);
|
||||||
emitByte(0xc0 + 8 * instr.dst + instr.src);
|
emitByte(0xc0 + 8 * instr.dst + instr.src, p, pos);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
emit(REX_XOR_RI);
|
emit(REX_XOR_RI, p, pos);
|
||||||
emitByte(0xf0 + instr.dst);
|
emitByte(0xf0 + instr.dst, p, pos);
|
||||||
emit32(instr.getImm32());
|
emit32(instr.getImm32(), p, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_IXOR_M(Instruction& instr, int i) {
|
void JitCompilerX86::h_IXOR_M(Instruction& instr, int i) {
|
||||||
|
uint8_t* const p = code;
|
||||||
|
int pos = codePos;
|
||||||
|
|
||||||
registerUsage[instr.dst] = i;
|
registerUsage[instr.dst] = i;
|
||||||
if (instr.src != instr.dst) {
|
if (instr.src != instr.dst) {
|
||||||
genAddressReg(instr);
|
genAddressReg(instr, p, pos);
|
||||||
emit(REX_XOR_RM);
|
emit(REX_XOR_RM, p, pos);
|
||||||
emitByte(0x04 + 8 * instr.dst);
|
emitByte(0x04 + 8 * instr.dst, p, pos);
|
||||||
emitByte(0x06);
|
emitByte(0x06, p, pos);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
emit(REX_XOR_RM);
|
emit(REX_XOR_RM, p, pos);
|
||||||
emitByte(0x86 + 8 * instr.dst);
|
emitByte(0x86 + 8 * instr.dst, p, pos);
|
||||||
genAddressImm(instr);
|
genAddressImm(instr, p, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_IROR_R(Instruction& instr, int i) {
|
void JitCompilerX86::h_IROR_R(Instruction& instr, int i) {
|
||||||
|
uint8_t* const p = code;
|
||||||
|
int pos = codePos;
|
||||||
|
|
||||||
registerUsage[instr.dst] = i;
|
registerUsage[instr.dst] = i;
|
||||||
if (instr.src != instr.dst) {
|
if (instr.src != instr.dst) {
|
||||||
emit(REX_MOV_RR);
|
emit(REX_MOV_RR, p, pos);
|
||||||
emitByte(0xc8 + instr.src);
|
emitByte(0xc8 + instr.src, p, pos);
|
||||||
emit(REX_ROT_CL);
|
emit(REX_ROT_CL, p, pos);
|
||||||
emitByte(0xc8 + instr.dst);
|
emitByte(0xc8 + instr.dst, p, pos);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
emit(REX_ROT_I8);
|
emit(REX_ROT_I8, p, pos);
|
||||||
emitByte(0xc8 + instr.dst);
|
emitByte(0xc8 + instr.dst, p, pos);
|
||||||
emitByte(instr.getImm32() & 63);
|
emitByte(instr.getImm32() & 63, p, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_IROL_R(Instruction& instr, int i) {
|
void JitCompilerX86::h_IROL_R(Instruction& instr, int i) {
|
||||||
|
uint8_t* const p = code;
|
||||||
|
int pos = codePos;
|
||||||
|
|
||||||
registerUsage[instr.dst] = i;
|
registerUsage[instr.dst] = i;
|
||||||
if (instr.src != instr.dst) {
|
if (instr.src != instr.dst) {
|
||||||
emit(REX_MOV_RR);
|
emit(REX_MOV_RR, p, pos);
|
||||||
emitByte(0xc8 + instr.src);
|
emitByte(0xc8 + instr.src, p, pos);
|
||||||
emit(REX_ROT_CL);
|
emit(REX_ROT_CL, p, pos);
|
||||||
emitByte(0xc0 + instr.dst);
|
emitByte(0xc0 + instr.dst, p, pos);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
emit(REX_ROT_I8);
|
emit(REX_ROT_I8, p, pos);
|
||||||
emitByte(0xc0 + instr.dst);
|
emitByte(0xc0 + instr.dst, p, pos);
|
||||||
emitByte(instr.getImm32() & 63);
|
emitByte(instr.getImm32() & 63, p, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_ISWAP_R(Instruction& instr, int i) {
|
void JitCompilerX86::h_ISWAP_R(Instruction& instr, int i) {
|
||||||
|
uint8_t* const p = code;
|
||||||
|
int pos = codePos;
|
||||||
|
|
||||||
if (instr.src != instr.dst) {
|
if (instr.src != instr.dst) {
|
||||||
registerUsage[instr.dst] = i;
|
registerUsage[instr.dst] = i;
|
||||||
registerUsage[instr.src] = i;
|
registerUsage[instr.src] = i;
|
||||||
emit(REX_XCHG);
|
emit(REX_XCHG, p, pos);
|
||||||
emitByte(0xc0 + instr.src + 8 * instr.dst);
|
emitByte(0xc0 + instr.src + 8 * instr.dst, p, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_FSWAP_R(Instruction& instr, int i) {
|
void JitCompilerX86::h_FSWAP_R(Instruction& instr, int i) {
|
||||||
emit(SHUFPD);
|
uint8_t* const p = code;
|
||||||
emitByte(0xc0 + 9 * instr.dst);
|
int pos = codePos;
|
||||||
emitByte(1);
|
|
||||||
|
emit(SHUFPD, p, pos);
|
||||||
|
emitByte(0xc0 + 9 * instr.dst, p, pos);
|
||||||
|
emitByte(1, p, pos);
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_FADD_R(Instruction& instr, int i) {
|
void JitCompilerX86::h_FADD_R(Instruction& instr, int i) {
|
||||||
|
uint8_t* const p = code;
|
||||||
|
int pos = codePos;
|
||||||
|
|
||||||
instr.dst %= RegisterCountFlt;
|
instr.dst %= RegisterCountFlt;
|
||||||
instr.src %= RegisterCountFlt;
|
instr.src %= RegisterCountFlt;
|
||||||
emit(REX_ADDPD);
|
emit(REX_ADDPD, p, pos);
|
||||||
emitByte(0xc0 + instr.src + 8 * instr.dst);
|
emitByte(0xc0 + instr.src + 8 * instr.dst, p, pos);
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_FADD_M(Instruction& instr, int i) {
|
void JitCompilerX86::h_FADD_M(Instruction& instr, int i) {
|
||||||
|
uint8_t* const p = code;
|
||||||
|
int pos = codePos;
|
||||||
|
|
||||||
instr.dst %= RegisterCountFlt;
|
instr.dst %= RegisterCountFlt;
|
||||||
genAddressReg(instr);
|
genAddressReg(instr, p, pos);
|
||||||
emit(REX_CVTDQ2PD_XMM12);
|
emit(REX_CVTDQ2PD_XMM12, p, pos);
|
||||||
emit(REX_ADDPD);
|
emit(REX_ADDPD, p, pos);
|
||||||
emitByte(0xc4 + 8 * instr.dst);
|
emitByte(0xc4 + 8 * instr.dst, p, pos);
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_FSUB_R(Instruction& instr, int i) {
|
void JitCompilerX86::h_FSUB_R(Instruction& instr, int i) {
|
||||||
|
uint8_t* const p = code;
|
||||||
|
int pos = codePos;
|
||||||
|
|
||||||
instr.dst %= RegisterCountFlt;
|
instr.dst %= RegisterCountFlt;
|
||||||
instr.src %= RegisterCountFlt;
|
instr.src %= RegisterCountFlt;
|
||||||
emit(REX_SUBPD);
|
emit(REX_SUBPD, p, pos);
|
||||||
emitByte(0xc0 + instr.src + 8 * instr.dst);
|
emitByte(0xc0 + instr.src + 8 * instr.dst, p, pos);
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_FSUB_M(Instruction& instr, int i) {
|
void JitCompilerX86::h_FSUB_M(Instruction& instr, int i) {
|
||||||
|
uint8_t* const p = code;
|
||||||
|
int pos = codePos;
|
||||||
|
|
||||||
instr.dst %= RegisterCountFlt;
|
instr.dst %= RegisterCountFlt;
|
||||||
genAddressReg(instr);
|
genAddressReg(instr, p, pos);
|
||||||
emit(REX_CVTDQ2PD_XMM12);
|
emit(REX_CVTDQ2PD_XMM12, p, pos);
|
||||||
emit(REX_SUBPD);
|
emit(REX_SUBPD, p, pos);
|
||||||
emitByte(0xc4 + 8 * instr.dst);
|
emitByte(0xc4 + 8 * instr.dst, p, pos);
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_FSCAL_R(Instruction& instr, int i) {
|
void JitCompilerX86::h_FSCAL_R(Instruction& instr, int i) {
|
||||||
|
uint8_t* const p = code;
|
||||||
|
int pos = codePos;
|
||||||
|
|
||||||
instr.dst %= RegisterCountFlt;
|
instr.dst %= RegisterCountFlt;
|
||||||
emit(REX_XORPS);
|
emit(REX_XORPS, p, pos);
|
||||||
emitByte(0xc7 + 8 * instr.dst);
|
emitByte(0xc7 + 8 * instr.dst, p, pos);
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_FMUL_R(Instruction& instr, int i) {
|
void JitCompilerX86::h_FMUL_R(Instruction& instr, int i) {
|
||||||
|
uint8_t* const p = code;
|
||||||
|
int pos = codePos;
|
||||||
|
|
||||||
instr.dst %= RegisterCountFlt;
|
instr.dst %= RegisterCountFlt;
|
||||||
instr.src %= RegisterCountFlt;
|
instr.src %= RegisterCountFlt;
|
||||||
emit(REX_MULPD);
|
emit(REX_MULPD, p, pos);
|
||||||
emitByte(0xe0 + instr.src + 8 * instr.dst);
|
emitByte(0xe0 + instr.src + 8 * instr.dst, p, pos);
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_FDIV_M(Instruction& instr, int i) {
|
void JitCompilerX86::h_FDIV_M(Instruction& instr, int i) {
|
||||||
|
uint8_t* const p = code;
|
||||||
|
int pos = codePos;
|
||||||
|
|
||||||
instr.dst %= RegisterCountFlt;
|
instr.dst %= RegisterCountFlt;
|
||||||
genAddressReg(instr);
|
genAddressReg(instr, p, pos);
|
||||||
emit(REX_CVTDQ2PD_XMM12);
|
emit(REX_CVTDQ2PD_XMM12, p, pos);
|
||||||
emit(REX_ANDPS_XMM12);
|
emit(REX_ANDPS_XMM12, p, pos);
|
||||||
emit(REX_DIVPD);
|
emit(REX_DIVPD, p, pos);
|
||||||
emitByte(0xe4 + 8 * instr.dst);
|
emitByte(0xe4 + 8 * instr.dst, p, pos);
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_FSQRT_R(Instruction& instr, int i) {
|
void JitCompilerX86::h_FSQRT_R(Instruction& instr, int i) {
|
||||||
|
uint8_t* const p = code;
|
||||||
|
int pos = codePos;
|
||||||
|
|
||||||
instr.dst %= RegisterCountFlt;
|
instr.dst %= RegisterCountFlt;
|
||||||
emit(SQRTPD);
|
emit(SQRTPD, p, pos);
|
||||||
emitByte(0xe4 + 9 * instr.dst);
|
emitByte(0xe4 + 9 * instr.dst, p, pos);
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_CFROUND(Instruction& instr, int i) {
|
void JitCompilerX86::h_CFROUND(Instruction& instr, int i) {
|
||||||
emit(REX_MOV_RR64);
|
uint8_t* const p = code;
|
||||||
emitByte(0xc0 + instr.src);
|
int pos = codePos;
|
||||||
|
|
||||||
|
emit(REX_MOV_RR64, p, pos);
|
||||||
|
emitByte(0xc0 + instr.src, p, pos);
|
||||||
int rotate = (13 - (instr.getImm32() & 63)) & 63;
|
int rotate = (13 - (instr.getImm32() & 63)) & 63;
|
||||||
if (rotate != 0) {
|
if (rotate != 0) {
|
||||||
emit(ROL_RAX);
|
emit(ROL_RAX, p, pos);
|
||||||
emitByte(rotate);
|
emitByte(rotate, p, pos);
|
||||||
}
|
}
|
||||||
emit(AND_OR_MOV_LDMXCSR);
|
emit(AND_OR_MOV_LDMXCSR, p, pos);
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_CBRANCH(Instruction& instr, int i) {
|
void JitCompilerX86::h_CBRANCH(Instruction& instr, int i) {
|
||||||
|
uint8_t* const p = code;
|
||||||
|
int pos = codePos;
|
||||||
|
|
||||||
int reg = instr.dst;
|
int reg = instr.dst;
|
||||||
int target = registerUsage[reg] + 1;
|
int target = registerUsage[reg] + 1;
|
||||||
emit(REX_ADD_I);
|
emit(REX_ADD_I, p, pos);
|
||||||
emitByte(0xc0 + reg);
|
emitByte(0xc0 + reg, p, pos);
|
||||||
int shift = instr.getModCond() + RandomX_CurrentConfig.JumpOffset;
|
int shift = instr.getModCond() + RandomX_CurrentConfig.JumpOffset;
|
||||||
uint32_t imm = instr.getImm32() | (1UL << shift);
|
uint32_t imm = instr.getImm32() | (1UL << shift);
|
||||||
if (RandomX_CurrentConfig.JumpOffset > 0 || shift > 0)
|
if (RandomX_CurrentConfig.JumpOffset > 0 || shift > 0)
|
||||||
imm &= ~(1UL << (shift - 1));
|
imm &= ~(1UL << (shift - 1));
|
||||||
emit32(imm);
|
emit32(imm, p, pos);
|
||||||
emit(REX_TEST);
|
emit(REX_TEST, p, pos);
|
||||||
emitByte(0xc0 + reg);
|
emitByte(0xc0 + reg, p, pos);
|
||||||
emit32(RandomX_CurrentConfig.ConditionMask_Calculated << shift);
|
emit32(RandomX_CurrentConfig.ConditionMask_Calculated << shift, p, pos);
|
||||||
emit(JZ);
|
emit(JZ, p, pos);
|
||||||
emit32(instructionOffsets[target] - (codePos + 4));
|
emit32(instructionOffsets[target] - (pos + 4), p, pos);
|
||||||
//mark all registers as used
|
//mark all registers as used
|
||||||
for (unsigned j = 0; j < RegistersCount; ++j) {
|
uint64_t* r = (uint64_t*) registerUsage;
|
||||||
registerUsage[j] = i;
|
uint64_t k = i;
|
||||||
|
k |= k << 32;
|
||||||
|
for (unsigned j = 0; j < RegistersCount / 2; ++j) {
|
||||||
|
r[j] = k;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_ISTORE(Instruction& instr, int i) {
|
void JitCompilerX86::h_ISTORE(Instruction& instr, int i) {
|
||||||
genAddressRegDst(instr);
|
uint8_t* const p = code;
|
||||||
emit(REX_MOV_MR);
|
int pos = codePos;
|
||||||
emitByte(0x04 + 8 * instr.src);
|
|
||||||
emitByte(0x06);
|
genAddressRegDst(instr, p, pos);
|
||||||
|
emit(REX_MOV_MR, p, pos);
|
||||||
|
emitByte(0x04 + 8 * instr.src, p, pos);
|
||||||
|
emitByte(0x06, p, pos);
|
||||||
|
|
||||||
|
codePos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitCompilerX86::h_NOP(Instruction& instr, int i) {
|
void JitCompilerX86::h_NOP(Instruction& instr, int i) {
|
||||||
emit(NOP1);
|
emit(NOP1, code, codePos);
|
||||||
}
|
}
|
||||||
|
|
||||||
InstructionGeneratorX86 JitCompilerX86::engine[256] = {};
|
InstructionGeneratorX86 JitCompilerX86::engine[256] = {};
|
||||||
|
|
|
@ -66,42 +66,41 @@ namespace randomx {
|
||||||
size_t getCodeSize();
|
size_t getCodeSize();
|
||||||
|
|
||||||
static InstructionGeneratorX86 engine[256];
|
static InstructionGeneratorX86 engine[256];
|
||||||
std::vector<int32_t> instructionOffsets;
|
int32_t instructionOffsets[512];
|
||||||
int registerUsage[RegistersCount];
|
int registerUsage[RegistersCount];
|
||||||
uint8_t* code;
|
uint8_t* code;
|
||||||
int32_t codePos;
|
int32_t codePos;
|
||||||
|
|
||||||
void generateProgramPrologue(Program&, ProgramConfiguration&);
|
void generateProgramPrologue(Program&, ProgramConfiguration&);
|
||||||
void generateProgramEpilogue(Program&);
|
void generateProgramEpilogue(Program&);
|
||||||
void genAddressReg(Instruction&, bool);
|
static void genAddressReg(Instruction&, uint8_t* code, int& codePos, bool rax = true);
|
||||||
void genAddressRegDst(Instruction&);
|
static void genAddressRegDst(Instruction&, uint8_t* code, int& codePos);
|
||||||
void genAddressImm(Instruction&);
|
static void genAddressImm(Instruction&, uint8_t* code, int& codePos);
|
||||||
void genSIB(int scale, int index, int base);
|
static void genSIB(int scale, int index, int base, uint8_t* code, int& codePos);
|
||||||
|
|
||||||
void generateCode(Instruction&, int);
|
|
||||||
void generateSuperscalarCode(Instruction &, std::vector<uint64_t> &);
|
void generateSuperscalarCode(Instruction &, std::vector<uint64_t> &);
|
||||||
|
|
||||||
void emitByte(uint8_t val) {
|
static void emitByte(uint8_t val, uint8_t* code, int& codePos) {
|
||||||
code[codePos] = val;
|
code[codePos] = val;
|
||||||
codePos++;
|
++codePos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit32(uint32_t val) {
|
static void emit32(uint32_t val, uint8_t* code, int& codePos) {
|
||||||
memcpy(code + codePos, &val, sizeof val);
|
memcpy(code + codePos, &val, sizeof val);
|
||||||
codePos += sizeof val;
|
codePos += sizeof val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit64(uint64_t val) {
|
static void emit64(uint64_t val, uint8_t* code, int& codePos) {
|
||||||
memcpy(code + codePos, &val, sizeof val);
|
memcpy(code + codePos, &val, sizeof val);
|
||||||
codePos += sizeof val;
|
codePos += sizeof val;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<size_t N>
|
template<size_t N>
|
||||||
void emit(const uint8_t (&src)[N]) {
|
static void emit(const uint8_t (&src)[N], uint8_t* code, int& codePos) {
|
||||||
emit(src, N);
|
emit(src, N, code, codePos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit(const uint8_t* src, size_t count) {
|
static void emit(const uint8_t* src, size_t count, uint8_t* code, int& codePos) {
|
||||||
memcpy(code + codePos, src, count);
|
memcpy(code + codePos, src, count);
|
||||||
codePos += count;
|
codePos += count;
|
||||||
}
|
}
|
||||||
|
|
|
@ -206,3 +206,7 @@ DECL(randomx_reciprocal_fast):
|
||||||
mov rcx, rdi
|
mov rcx, rdi
|
||||||
#endif
|
#endif
|
||||||
#include "asm/randomx_reciprocal.inc"
|
#include "asm/randomx_reciprocal.inc"
|
||||||
|
|
||||||
|
#if defined(__linux__) && defined(__ELF__)
|
||||||
|
.section .note.GNU-stack,"",%progbits
|
||||||
|
#endif
|
||||||
|
|
|
@ -44,12 +44,14 @@ RandomX_ConfigurationWownero::RandomX_ConfigurationWownero()
|
||||||
ScratchpadL2_Size = 131072;
|
ScratchpadL2_Size = 131072;
|
||||||
ScratchpadL3_Size = 1048576;
|
ScratchpadL3_Size = 1048576;
|
||||||
|
|
||||||
|
RANDOMX_FREQ_IADD_RS = 25;
|
||||||
RANDOMX_FREQ_IROR_R = 10;
|
RANDOMX_FREQ_IROR_R = 10;
|
||||||
RANDOMX_FREQ_IROL_R = 0;
|
RANDOMX_FREQ_IROL_R = 0;
|
||||||
RANDOMX_FREQ_FSWAP_R = 8;
|
RANDOMX_FREQ_FSWAP_R = 8;
|
||||||
RANDOMX_FREQ_FADD_R = 20;
|
RANDOMX_FREQ_FADD_R = 20;
|
||||||
RANDOMX_FREQ_FSUB_R = 20;
|
RANDOMX_FREQ_FSUB_R = 20;
|
||||||
RANDOMX_FREQ_FMUL_R = 20;
|
RANDOMX_FREQ_FMUL_R = 20;
|
||||||
|
RANDOMX_FREQ_CBRANCH = 16;
|
||||||
|
|
||||||
fillAes4Rx4_Key[0] = rx_set_int_vec_i128(0xcf359e95, 0x141f82b7, 0x7ffbe4a6, 0xf890465d);
|
fillAes4Rx4_Key[0] = rx_set_int_vec_i128(0xcf359e95, 0x141f82b7, 0x7ffbe4a6, 0xf890465d);
|
||||||
fillAes4Rx4_Key[1] = rx_set_int_vec_i128(0x6741ffdc, 0xbd5c5ac3, 0xfee8278a, 0x6a55c450);
|
fillAes4Rx4_Key[1] = rx_set_int_vec_i128(0x6741ffdc, 0xbd5c5ac3, 0xfee8278a, 0x6a55c450);
|
||||||
|
@ -68,6 +70,9 @@ RandomX_ConfigurationLoki::RandomX_ConfigurationLoki()
|
||||||
ArgonSalt = "RandomXL\x12";
|
ArgonSalt = "RandomXL\x12";
|
||||||
ProgramSize = 320;
|
ProgramSize = 320;
|
||||||
ProgramCount = 7;
|
ProgramCount = 7;
|
||||||
|
|
||||||
|
RANDOMX_FREQ_IADD_RS = 25;
|
||||||
|
RANDOMX_FREQ_CBRANCH = 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
RandomX_ConfigurationBase::RandomX_ConfigurationBase()
|
RandomX_ConfigurationBase::RandomX_ConfigurationBase()
|
||||||
|
@ -87,7 +92,7 @@ RandomX_ConfigurationBase::RandomX_ConfigurationBase()
|
||||||
, ProgramCount(8)
|
, ProgramCount(8)
|
||||||
, JumpBits(8)
|
, JumpBits(8)
|
||||||
, JumpOffset(8)
|
, JumpOffset(8)
|
||||||
, RANDOMX_FREQ_IADD_RS(25)
|
, RANDOMX_FREQ_IADD_RS(16)
|
||||||
, RANDOMX_FREQ_IADD_M(7)
|
, RANDOMX_FREQ_IADD_M(7)
|
||||||
, RANDOMX_FREQ_ISUB_R(16)
|
, RANDOMX_FREQ_ISUB_R(16)
|
||||||
, RANDOMX_FREQ_ISUB_M(7)
|
, RANDOMX_FREQ_ISUB_M(7)
|
||||||
|
@ -113,7 +118,7 @@ RandomX_ConfigurationBase::RandomX_ConfigurationBase()
|
||||||
, RANDOMX_FREQ_FMUL_R(32)
|
, RANDOMX_FREQ_FMUL_R(32)
|
||||||
, RANDOMX_FREQ_FDIV_M(4)
|
, RANDOMX_FREQ_FDIV_M(4)
|
||||||
, RANDOMX_FREQ_FSQRT_R(6)
|
, RANDOMX_FREQ_FSQRT_R(6)
|
||||||
, RANDOMX_FREQ_CBRANCH(16)
|
, RANDOMX_FREQ_CBRANCH(25)
|
||||||
, RANDOMX_FREQ_CFROUND(1)
|
, RANDOMX_FREQ_CFROUND(1)
|
||||||
, RANDOMX_FREQ_ISTORE(16)
|
, RANDOMX_FREQ_ISTORE(16)
|
||||||
, RANDOMX_FREQ_NOP(0)
|
, RANDOMX_FREQ_NOP(0)
|
||||||
|
|
|
@ -329,7 +329,7 @@ namespace randomx {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (availableRegisters.size() > 1) {
|
if (availableRegisters.size() > 1) {
|
||||||
index = gen.getInt32() % availableRegisters.size();
|
index = gen.getUInt32() % availableRegisters.size();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
index = 0;
|
index = 0;
|
||||||
|
@ -442,7 +442,7 @@ namespace randomx {
|
||||||
case SuperscalarInstructionType::IADD_C8:
|
case SuperscalarInstructionType::IADD_C8:
|
||||||
case SuperscalarInstructionType::IADD_C9: {
|
case SuperscalarInstructionType::IADD_C9: {
|
||||||
mod_ = 0;
|
mod_ = 0;
|
||||||
imm32_ = gen.getInt32();
|
imm32_ = gen.getUInt32();
|
||||||
opGroup_ = SuperscalarInstructionType::IADD_C7;
|
opGroup_ = SuperscalarInstructionType::IADD_C7;
|
||||||
opGroupPar_ = -1;
|
opGroupPar_ = -1;
|
||||||
} break;
|
} break;
|
||||||
|
@ -451,7 +451,7 @@ namespace randomx {
|
||||||
case SuperscalarInstructionType::IXOR_C8:
|
case SuperscalarInstructionType::IXOR_C8:
|
||||||
case SuperscalarInstructionType::IXOR_C9: {
|
case SuperscalarInstructionType::IXOR_C9: {
|
||||||
mod_ = 0;
|
mod_ = 0;
|
||||||
imm32_ = gen.getInt32();
|
imm32_ = gen.getUInt32();
|
||||||
opGroup_ = SuperscalarInstructionType::IXOR_C7;
|
opGroup_ = SuperscalarInstructionType::IXOR_C7;
|
||||||
opGroupPar_ = -1;
|
opGroupPar_ = -1;
|
||||||
} break;
|
} break;
|
||||||
|
@ -461,7 +461,7 @@ namespace randomx {
|
||||||
mod_ = 0;
|
mod_ = 0;
|
||||||
imm32_ = 0;
|
imm32_ = 0;
|
||||||
opGroup_ = SuperscalarInstructionType::IMULH_R;
|
opGroup_ = SuperscalarInstructionType::IMULH_R;
|
||||||
opGroupPar_ = gen.getInt32();
|
opGroupPar_ = gen.getUInt32();
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case SuperscalarInstructionType::ISMULH_R: {
|
case SuperscalarInstructionType::ISMULH_R: {
|
||||||
|
@ -469,14 +469,14 @@ namespace randomx {
|
||||||
mod_ = 0;
|
mod_ = 0;
|
||||||
imm32_ = 0;
|
imm32_ = 0;
|
||||||
opGroup_ = SuperscalarInstructionType::ISMULH_R;
|
opGroup_ = SuperscalarInstructionType::ISMULH_R;
|
||||||
opGroupPar_ = gen.getInt32();
|
opGroupPar_ = gen.getUInt32();
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case SuperscalarInstructionType::IMUL_RCP: {
|
case SuperscalarInstructionType::IMUL_RCP: {
|
||||||
mod_ = 0;
|
mod_ = 0;
|
||||||
do {
|
do {
|
||||||
imm32_ = gen.getInt32();
|
imm32_ = gen.getUInt32();
|
||||||
} while ((imm32_ & (imm32_ - 1)) == 0);
|
} while (isZeroOrPowerOf2(imm32_));
|
||||||
opGroup_ = SuperscalarInstructionType::IMUL_RCP;
|
opGroup_ = SuperscalarInstructionType::IMUL_RCP;
|
||||||
opGroupPar_ = -1;
|
opGroupPar_ = -1;
|
||||||
} break;
|
} break;
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#define APP_ID "xmrig"
|
#define APP_ID "xmrig"
|
||||||
#define APP_NAME "XMRig"
|
#define APP_NAME "XMRig"
|
||||||
#define APP_DESC "XMRig CPU miner"
|
#define APP_DESC "XMRig CPU miner"
|
||||||
#define APP_VERSION "3.1.0"
|
#define APP_VERSION "3.1.1-dev"
|
||||||
#define APP_DOMAIN "xmrig.com"
|
#define APP_DOMAIN "xmrig.com"
|
||||||
#define APP_SITE "www.xmrig.com"
|
#define APP_SITE "www.xmrig.com"
|
||||||
#define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com"
|
#define APP_COPYRIGHT "Copyright (C) 2016-2019 xmrig.com"
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
|
|
||||||
#define APP_VER_MAJOR 3
|
#define APP_VER_MAJOR 3
|
||||||
#define APP_VER_MINOR 1
|
#define APP_VER_MINOR 1
|
||||||
#define APP_VER_PATCH 0
|
#define APP_VER_PATCH 1
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
# if (_MSC_VER >= 1920)
|
# if (_MSC_VER >= 1920)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue