mirror of
https://github.com/wownero/RandomX.git
synced 2026-10-17 23:41:39 +02:00
Added branches - ASM and JIT only
This commit is contained in:
+134
-40
@@ -18,12 +18,15 @@ along with RandomX. If not, see<http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include <climits>
|
||||
#include <stdexcept>
|
||||
#include "JitCompilerX86.hpp"
|
||||
#include "Program.hpp"
|
||||
#include "reciprocal.h"
|
||||
#include "virtualMemory.hpp"
|
||||
|
||||
#define RANDOMX_JUMP
|
||||
|
||||
namespace RandomX {
|
||||
|
||||
#if !defined(_M_X64) && !defined(__x86_64__)
|
||||
@@ -168,6 +171,9 @@ namespace RandomX {
|
||||
static const uint8_t REX_ANDPS_XMM12[] = { 0x45, 0x0F, 0x54, 0xE5, 0x45, 0x0F, 0x56, 0xE6 };
|
||||
static const uint8_t REX_PADD[] = { 0x66, 0x44, 0x0f };
|
||||
static const uint8_t PADD_OPCODES[] = { 0xfc, 0xfd, 0xfe, 0xd4 };
|
||||
static const uint8_t REX_ADD_I[] = { 0x49, 0x83 };
|
||||
static const uint8_t REX_TEST[] = { 0x49, 0xF7 };
|
||||
static const uint8_t JZ[] = { 0x0f, 0x84 };
|
||||
|
||||
size_t JitCompilerX86::getCodeSize() {
|
||||
return codePos - prologueSize;
|
||||
@@ -180,6 +186,12 @@ namespace RandomX {
|
||||
}
|
||||
|
||||
void JitCompilerX86::generateProgram(Program& prog) {
|
||||
#ifdef RANDOMX_JUMP
|
||||
instructionOffsets.clear();
|
||||
for (unsigned i = 0; i < 8; ++i) {
|
||||
registerUsage[i] = -1;
|
||||
}
|
||||
#endif
|
||||
auto addressRegisters = prog.getEntropy(12);
|
||||
uint32_t readReg0 = 0 + (addressRegisters & 1);
|
||||
addressRegisters >>= 1;
|
||||
@@ -199,7 +211,7 @@ namespace RandomX {
|
||||
Instruction& instr = prog(i);
|
||||
instr.src %= RegistersCount;
|
||||
instr.dst %= RegistersCount;
|
||||
generateCode(instr);
|
||||
generateCode(instr, i);
|
||||
}
|
||||
emit(REX_MOV_RR);
|
||||
emitByte(0xc0 + readReg2);
|
||||
@@ -217,9 +229,12 @@ namespace RandomX {
|
||||
emitByte(0x90);
|
||||
}
|
||||
|
||||
void JitCompilerX86::generateCode(Instruction& instr) {
|
||||
void JitCompilerX86::generateCode(Instruction& instr, int i) {
|
||||
#ifdef RANDOMX_JUMP
|
||||
instructionOffsets.push_back(codePos);
|
||||
#endif
|
||||
auto generator = engine[instr.opcode];
|
||||
(this->*generator)(instr);
|
||||
(this->*generator)(instr, i);
|
||||
}
|
||||
|
||||
void JitCompilerX86::genAddressReg(Instruction& instr, bool rax = true) {
|
||||
@@ -245,7 +260,8 @@ namespace RandomX {
|
||||
emit32(instr.getImm32() & ScratchpadL3Mask);
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_IADD_R(Instruction& instr) {
|
||||
void JitCompilerX86::h_IADD_R(Instruction& instr, int i) {
|
||||
registerUsage[instr.dst] = i;
|
||||
if (instr.src != instr.dst) {
|
||||
emit(REX_ADD_RR);
|
||||
emitByte(0xc0 + 8 * instr.dst + instr.src);
|
||||
@@ -257,7 +273,8 @@ namespace RandomX {
|
||||
}
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_IADD_M(Instruction& instr) {
|
||||
void JitCompilerX86::h_IADD_M(Instruction& instr, int i) {
|
||||
registerUsage[instr.dst] = i;
|
||||
if (instr.src != instr.dst) {
|
||||
genAddressReg(instr);
|
||||
emit(REX_ADD_RM);
|
||||
@@ -275,14 +292,16 @@ namespace RandomX {
|
||||
emitByte((scale << 6) | (index << 3) | base);
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_IADD_RC(Instruction& instr) {
|
||||
void JitCompilerX86::h_IADD_RC(Instruction& instr, int i) {
|
||||
registerUsage[instr.dst] = i;
|
||||
emit(REX_LEA);
|
||||
emitByte(0x84 + 8 * instr.dst);
|
||||
genSIB(0, instr.src, instr.dst);
|
||||
emit32(instr.getImm32());
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_ISUB_R(Instruction& instr) {
|
||||
void JitCompilerX86::h_ISUB_R(Instruction& instr, int i) {
|
||||
registerUsage[instr.dst] = i;
|
||||
if (instr.src != instr.dst) {
|
||||
emit(REX_SUB_RR);
|
||||
emitByte(0xc0 + 8 * instr.dst + instr.src);
|
||||
@@ -294,7 +313,8 @@ namespace RandomX {
|
||||
}
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_ISUB_M(Instruction& instr) {
|
||||
void JitCompilerX86::h_ISUB_M(Instruction& instr, int i) {
|
||||
registerUsage[instr.dst] = i;
|
||||
if (instr.src != instr.dst) {
|
||||
genAddressReg(instr);
|
||||
emit(REX_SUB_RM);
|
||||
@@ -308,14 +328,16 @@ namespace RandomX {
|
||||
}
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_IMUL_9C(Instruction& instr) {
|
||||
void JitCompilerX86::h_IMUL_9C(Instruction& instr, int i) {
|
||||
registerUsage[instr.dst] = i;
|
||||
emit(REX_LEA);
|
||||
emitByte(0x84 + 8 * instr.dst);
|
||||
genSIB(3, instr.dst, instr.dst);
|
||||
emit32(instr.getImm32());
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_IMUL_R(Instruction& instr) {
|
||||
void JitCompilerX86::h_IMUL_R(Instruction& instr, int i) {
|
||||
registerUsage[instr.dst] = i;
|
||||
if (instr.src != instr.dst) {
|
||||
emit(REX_IMUL_RR);
|
||||
emitByte(0xc0 + 8 * instr.dst + instr.src);
|
||||
@@ -327,7 +349,8 @@ namespace RandomX {
|
||||
}
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_IMUL_M(Instruction& instr) {
|
||||
void JitCompilerX86::h_IMUL_M(Instruction& instr, int i) {
|
||||
registerUsage[instr.dst] = i;
|
||||
if (instr.src != instr.dst) {
|
||||
genAddressReg(instr);
|
||||
emit(REX_IMUL_RM);
|
||||
@@ -341,7 +364,8 @@ namespace RandomX {
|
||||
}
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_IMULH_R(Instruction& instr) {
|
||||
void JitCompilerX86::h_IMULH_R(Instruction& instr, int i) {
|
||||
registerUsage[instr.dst] = i;
|
||||
emit(REX_MOV_RR64);
|
||||
emitByte(0xc0 + instr.dst);
|
||||
emit(REX_MUL_R);
|
||||
@@ -350,7 +374,8 @@ namespace RandomX {
|
||||
emitByte(0xc2 + 8 * instr.dst);
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_IMULH_M(Instruction& instr) {
|
||||
void JitCompilerX86::h_IMULH_M(Instruction& instr, int i) {
|
||||
registerUsage[instr.dst] = i;
|
||||
if (instr.src != instr.dst) {
|
||||
genAddressReg(instr, false);
|
||||
emit(REX_MOV_RR64);
|
||||
@@ -368,7 +393,8 @@ namespace RandomX {
|
||||
emitByte(0xc2 + 8 * instr.dst);
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_ISMULH_R(Instruction& instr) {
|
||||
void JitCompilerX86::h_ISMULH_R(Instruction& instr, int i) {
|
||||
registerUsage[instr.dst] = i;
|
||||
emit(REX_MOV_RR64);
|
||||
emitByte(0xc0 + instr.dst);
|
||||
emit(REX_MUL_R);
|
||||
@@ -377,7 +403,8 @@ namespace RandomX {
|
||||
emitByte(0xc2 + 8 * instr.dst);
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_ISMULH_M(Instruction& instr) {
|
||||
void JitCompilerX86::h_ISMULH_M(Instruction& instr, int i) {
|
||||
registerUsage[instr.dst] = i;
|
||||
if (instr.src != instr.dst) {
|
||||
genAddressReg(instr, false);
|
||||
emit(REX_MOV_RR64);
|
||||
@@ -395,8 +422,9 @@ namespace RandomX {
|
||||
emitByte(0xc2 + 8 * instr.dst);
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_IMUL_RCP(Instruction& instr) {
|
||||
void JitCompilerX86::h_IMUL_RCP(Instruction& instr, int i) {
|
||||
if (instr.getImm32() != 0) {
|
||||
registerUsage[instr.dst] = i;
|
||||
emit(MOV_RAX_I);
|
||||
emit64(reciprocal(instr.getImm32()));
|
||||
emit(REX_IMUL_RM);
|
||||
@@ -404,16 +432,18 @@ namespace RandomX {
|
||||
}
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_ISDIV_C(Instruction& instr) {
|
||||
void JitCompilerX86::h_ISDIV_C(Instruction& instr, int i) {
|
||||
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_INEG_R(Instruction& instr) {
|
||||
void JitCompilerX86::h_INEG_R(Instruction& instr, int i) {
|
||||
registerUsage[instr.dst] = i;
|
||||
emit(REX_NEG);
|
||||
emitByte(0xd8 + instr.dst);
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_IXOR_R(Instruction& instr) {
|
||||
void JitCompilerX86::h_IXOR_R(Instruction& instr, int i) {
|
||||
registerUsage[instr.dst] = i;
|
||||
if (instr.src != instr.dst) {
|
||||
emit(REX_XOR_RR);
|
||||
emitByte(0xc0 + 8 * instr.dst + instr.src);
|
||||
@@ -425,7 +455,8 @@ namespace RandomX {
|
||||
}
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_IXOR_M(Instruction& instr) {
|
||||
void JitCompilerX86::h_IXOR_M(Instruction& instr, int i) {
|
||||
registerUsage[instr.dst] = i;
|
||||
if (instr.src != instr.dst) {
|
||||
genAddressReg(instr);
|
||||
emit(REX_XOR_RM);
|
||||
@@ -439,7 +470,8 @@ namespace RandomX {
|
||||
}
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_IROR_R(Instruction& instr) {
|
||||
void JitCompilerX86::h_IROR_R(Instruction& instr, int i) {
|
||||
registerUsage[instr.dst] = i;
|
||||
if (instr.src != instr.dst) {
|
||||
emit(REX_MOV_RR);
|
||||
emitByte(0xc8 + instr.src);
|
||||
@@ -453,7 +485,8 @@ namespace RandomX {
|
||||
}
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_IROL_R(Instruction& instr) {
|
||||
void JitCompilerX86::h_IROL_R(Instruction& instr, int i) {
|
||||
registerUsage[instr.dst] = i;
|
||||
if (instr.src != instr.dst) {
|
||||
emit(REX_MOV_RR);
|
||||
emitByte(0xc8 + instr.src);
|
||||
@@ -467,20 +500,22 @@ namespace RandomX {
|
||||
}
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_ISWAP_R(Instruction& instr) {
|
||||
void JitCompilerX86::h_ISWAP_R(Instruction& instr, int i) {
|
||||
if (instr.src != instr.dst) {
|
||||
registerUsage[instr.dst] = i;
|
||||
registerUsage[instr.src] = i;
|
||||
emit(REX_XCHG);
|
||||
emitByte(0xc0 + instr.src + 8 * instr.dst);
|
||||
}
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_FSWAP_R(Instruction& instr) {
|
||||
void JitCompilerX86::h_FSWAP_R(Instruction& instr, int i) {
|
||||
emit(SHUFPD);
|
||||
emitByte(0xc0 + 9 * instr.dst);
|
||||
emitByte(1);
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_FADD_R(Instruction& instr) {
|
||||
void JitCompilerX86::h_FADD_R(Instruction& instr, int i) {
|
||||
instr.dst %= 4;
|
||||
instr.src %= 4;
|
||||
emit(REX_ADDPD);
|
||||
@@ -490,7 +525,7 @@ namespace RandomX {
|
||||
//emitByte(0xf8 + instr.dst);
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_FADD_M(Instruction& instr) {
|
||||
void JitCompilerX86::h_FADD_M(Instruction& instr, int i) {
|
||||
instr.dst %= 4;
|
||||
genAddressReg(instr);
|
||||
emit(REX_CVTDQ2PD_XMM12);
|
||||
@@ -498,7 +533,7 @@ namespace RandomX {
|
||||
emitByte(0xc4 + 8 * instr.dst);
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_FSUB_R(Instruction& instr) {
|
||||
void JitCompilerX86::h_FSUB_R(Instruction& instr, int i) {
|
||||
instr.dst %= 4;
|
||||
instr.src %= 4;
|
||||
emit(REX_SUBPD);
|
||||
@@ -508,7 +543,7 @@ namespace RandomX {
|
||||
//emitByte(0xf8 + instr.dst);
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_FSUB_M(Instruction& instr) {
|
||||
void JitCompilerX86::h_FSUB_M(Instruction& instr, int i) {
|
||||
instr.dst %= 4;
|
||||
genAddressReg(instr);
|
||||
emit(REX_CVTDQ2PD_XMM12);
|
||||
@@ -516,20 +551,20 @@ namespace RandomX {
|
||||
emitByte(0xc4 + 8 * instr.dst);
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_FSCAL_R(Instruction& instr) {
|
||||
void JitCompilerX86::h_FSCAL_R(Instruction& instr, int i) {
|
||||
instr.dst %= 4;
|
||||
emit(REX_XORPS);
|
||||
emitByte(0xc7 + 8 * instr.dst);
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_FMUL_R(Instruction& instr) {
|
||||
void JitCompilerX86::h_FMUL_R(Instruction& instr, int i) {
|
||||
instr.dst %= 4;
|
||||
instr.src %= 4;
|
||||
emit(REX_MULPD);
|
||||
emitByte(0xe0 + instr.src + 8 * instr.dst);
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_FMUL_M(Instruction& instr) {
|
||||
void JitCompilerX86::h_FMUL_M(Instruction& instr, int i) {
|
||||
instr.dst %= 4;
|
||||
genAddressReg(instr);
|
||||
emit(REX_CVTDQ2PD_XMM12);
|
||||
@@ -540,7 +575,7 @@ namespace RandomX {
|
||||
emitByte(0xe5 + 8 * instr.dst);
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_FDIV_R(Instruction& instr) {
|
||||
void JitCompilerX86::h_FDIV_R(Instruction& instr, int i) {
|
||||
instr.dst %= 4;
|
||||
instr.src %= 4;
|
||||
emit(REX_DIVPD);
|
||||
@@ -549,7 +584,7 @@ namespace RandomX {
|
||||
emitByte(0xe5 + 8 * instr.dst);
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_FDIV_M(Instruction& instr) {
|
||||
void JitCompilerX86::h_FDIV_M(Instruction& instr, int i) {
|
||||
instr.dst %= 4;
|
||||
genAddressReg(instr);
|
||||
emit(REX_CVTDQ2PD_XMM12);
|
||||
@@ -558,13 +593,13 @@ namespace RandomX {
|
||||
emitByte(0xe4 + 8 * instr.dst);
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_FSQRT_R(Instruction& instr) {
|
||||
void JitCompilerX86::h_FSQRT_R(Instruction& instr, int i) {
|
||||
instr.dst %= 4;
|
||||
emit(SQRTPD);
|
||||
emitByte(0xe4 + 9 * instr.dst);
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_CFROUND(Instruction& instr) {
|
||||
void JitCompilerX86::h_CFROUND(Instruction& instr, int i) {
|
||||
emit(REX_MOV_RR64);
|
||||
emitByte(0xc0 + instr.src);
|
||||
int rotate = (13 - (instr.getImm32() & 63)) & 63;
|
||||
@@ -575,6 +610,28 @@ namespace RandomX {
|
||||
emit(AND_OR_MOV_LDMXCSR);
|
||||
}
|
||||
|
||||
static inline uint8_t jumpCondition(Instruction& instr, bool invert = false) {
|
||||
switch (((instr.mod >> 2) & 7) ^ invert)
|
||||
{
|
||||
case 0:
|
||||
return 0x76; //jbe
|
||||
case 1:
|
||||
return 0x77; //ja
|
||||
case 2:
|
||||
return 0x78; //js
|
||||
case 3:
|
||||
return 0x79; //jns
|
||||
case 4:
|
||||
return 0x70; //jo
|
||||
case 5:
|
||||
return 0x71; //jno
|
||||
case 6:
|
||||
return 0x7c; //jl
|
||||
case 7:
|
||||
return 0x7d; //jge
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint8_t condition(Instruction& instr) {
|
||||
switch ((instr.mod >> 2) & 7)
|
||||
{
|
||||
@@ -599,7 +656,41 @@ namespace RandomX {
|
||||
}
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_COND_R(Instruction& instr) {
|
||||
int JitCompilerX86::getConditionRegister() {
|
||||
int min = INT_MAX;
|
||||
int minIndex;
|
||||
for (unsigned i = 0; i < 8; ++i) {
|
||||
if (registerUsage[i] < min) {
|
||||
min = registerUsage[i];
|
||||
minIndex = i;
|
||||
}
|
||||
}
|
||||
return minIndex;
|
||||
}
|
||||
|
||||
void JitCompilerX86::handleCondition(Instruction& instr, int i) {
|
||||
const int shift = (instr.mod >> 5);
|
||||
const int conditionMask = ((1 << RANDOMX_CONDITION_BITS) - 1) << shift;
|
||||
int reg = getConditionRegister();
|
||||
int target = registerUsage[reg] + 1;
|
||||
registerUsage[reg] = i;
|
||||
emit(REX_ADD_I);
|
||||
emitByte(0xc0 + reg);
|
||||
emitByte(1 << shift);
|
||||
emit(REX_TEST);
|
||||
emitByte(0xc0 + reg);
|
||||
emit32(conditionMask);
|
||||
emit(JZ);
|
||||
emit32(instructionOffsets[target] - (codePos + 4));
|
||||
for (unsigned j = 0; j < 8; ++j) { //mark all registers as used
|
||||
registerUsage[j] = i;
|
||||
}
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_COND_R(Instruction& instr, int i) {
|
||||
#ifdef RANDOMX_JUMP
|
||||
handleCondition(instr, i);
|
||||
#endif
|
||||
emit(XOR_ECX_ECX);
|
||||
emit(REX_CMP_R32I);
|
||||
emitByte(0xf8 + instr.src);
|
||||
@@ -611,7 +702,10 @@ namespace RandomX {
|
||||
emitByte(0xc1 + 8 * instr.dst);
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_COND_M(Instruction& instr) {
|
||||
void JitCompilerX86::h_COND_M(Instruction& instr, int i) {
|
||||
#ifdef RANDOMX_JUMP
|
||||
handleCondition(instr, i);
|
||||
#endif
|
||||
emit(XOR_ECX_ECX);
|
||||
genAddressReg(instr);
|
||||
emit(REX_CMP_M32I);
|
||||
@@ -623,21 +717,21 @@ namespace RandomX {
|
||||
emitByte(0xc1 + 8 * instr.dst);
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_ISTORE(Instruction& instr) {
|
||||
void JitCompilerX86::h_ISTORE(Instruction& instr, int i) {
|
||||
genAddressRegDst(instr);
|
||||
emit(REX_MOV_MR);
|
||||
emitByte(0x04 + 8 * instr.src);
|
||||
emitByte(0x06);
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_FSTORE(Instruction& instr) {
|
||||
void JitCompilerX86::h_FSTORE(Instruction& instr, int i) {
|
||||
genAddressRegDst(instr, true);
|
||||
emit(MOVAPD);
|
||||
emitByte(0x04 + 8 * instr.src);
|
||||
emitByte(0x06);
|
||||
}
|
||||
|
||||
void JitCompilerX86::h_NOP(Instruction& instr) {
|
||||
void JitCompilerX86::h_NOP(Instruction& instr, int i) {
|
||||
emitByte(0x90);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user