Use 'dst' as the CBRANCH condition register

See issue #43
1.1.6-wow
tevador 5 years ago
parent 1276d67d2f
commit 8a5ead5ce3

@ -19,9 +19,9 @@ randomx_isn_4:
mov ecx, r13d
ror r11, cl
randomx_isn_5:
; CBRANCH -1891017657, COND 15
add r10, -1886823353
test r10, 2139095040
; CBRANCH r7, -1891017657, COND 15
add r15, -1886823353
test r15, 2139095040
jz randomx_isn_0
randomx_isn_6:
; ISUB_M r3, L1[r7-1023302103]
@ -41,10 +41,10 @@ randomx_isn_10:
; FADD_R f0, a3
addpd xmm0, xmm11
randomx_isn_11:
; CBRANCH -1981570318, COND 4
add r8, -1981566222
test r8, 1044480
jz randomx_isn_6
; CBRANCH r3, -1981570318, COND 4
add r11, -1981566222
test r11, 1044480
jz randomx_isn_10
randomx_isn_12:
; FSUB_R f0, a1
subpd xmm0, xmm9
@ -55,9 +55,9 @@ randomx_isn_14:
; FSQRT_R e2
sqrtpd xmm6, xmm6
randomx_isn_15:
; CBRANCH -1278791788, COND 14
add r11, -1278791788
test r11, 1069547520
; CBRANCH r5, -1278791788, COND 14
add r13, -1278791788
test r13, 1069547520
jz randomx_isn_12
randomx_isn_16:
; ISUB_R r3, -1310797453
@ -167,10 +167,10 @@ randomx_isn_42:
; ISUB_R r4, r3
sub r12, r11
randomx_isn_43:
; CBRANCH 335851892, COND 5
add r13, 335847796
test r13, 2088960
jz randomx_isn_16
; CBRANCH r6, 335851892, COND 5
add r14, 335847796
test r14, 2088960
jz randomx_isn_25
randomx_isn_44:
; IADD_RS r7, r5, SHFT 3
lea r15, [r15+r13*8]
@ -194,10 +194,10 @@ randomx_isn_48:
; IMUL_R r0, r5
imul r8, r13
randomx_isn_49:
; CBRANCH -272659465, COND 15
add r9, -272659465
test r9, 2139095040
jz randomx_isn_44
; CBRANCH r2, -272659465, COND 15
add r10, -272659465
test r10, 2139095040
jz randomx_isn_48
randomx_isn_50:
; ISTORE L1[r6+1414933948], r5
lea eax, [r14d+1414933948]
@ -212,9 +212,9 @@ randomx_isn_52:
; FSCAL_R f1
xorps xmm1, xmm15
randomx_isn_53:
; CBRANCH -2143810604, COND 1
add r12, -2143810860
test r12, 130560
; CBRANCH r6, -2143810604, COND 1
add r14, -2143810860
test r14, 130560
jz randomx_isn_50
randomx_isn_54:
; ISUB_M r3, L1[r1-649360673]
@ -241,7 +241,7 @@ randomx_isn_58:
; IADD_RS r4, r2, SHFT 1
lea r12, [r12+r10*2]
randomx_isn_59:
; CBRANCH -704407571, COND 10
; CBRANCH r6, -704407571, COND 10
add r14, -704276499
test r14, 66846720
jz randomx_isn_54
@ -263,9 +263,9 @@ randomx_isn_64:
and eax, 2097144
mov qword ptr [rsi+rax], r8
randomx_isn_65:
; CBRANCH -67701844, COND 5
add r15, -67705940
test r15, 2088960
; CBRANCH r1, -67701844, COND 5
add r9, -67705940
test r9, 2088960
jz randomx_isn_60
randomx_isn_66:
; IROR_R r3, r1
@ -345,10 +345,10 @@ randomx_isn_86:
mul r12
mov r11, rdx
randomx_isn_87:
; CBRANCH -1821955951, COND 5
add r8, -1821955951
test r8, 2088960
jz randomx_isn_66
; CBRANCH r3, -1821955951, COND 5
add r11, -1821955951
test r11, 2088960
jz randomx_isn_87
randomx_isn_88:
; FADD_R f2, a3
addpd xmm2, xmm11
@ -356,9 +356,9 @@ randomx_isn_89:
; IXOR_R r6, r3
xor r14, r11
randomx_isn_90:
; CBRANCH -1780348372, COND 15
add r9, -1784542676
test r9, 2139095040
; CBRANCH r4, -1780348372, COND 15
add r12, -1784542676
test r12, 2139095040
jz randomx_isn_88
randomx_isn_91:
; IROR_R r4, 55
@ -403,10 +403,10 @@ randomx_isn_102:
; IXOR_R r4, r7
xor r12, r15
randomx_isn_103:
; CBRANCH -607792642, COND 4
add r11, -607792642
test r11, 1044480
jz randomx_isn_91
; CBRANCH r7, -607792642, COND 4
add r15, -607792642
test r15, 1044480
jz randomx_isn_99
randomx_isn_104:
; FMUL_R e1, a1
mulpd xmm5, xmm9
@ -484,10 +484,10 @@ randomx_isn_123:
; FSQRT_R e2
sqrtpd xmm6, xmm6
randomx_isn_124:
; CBRANCH -1807592127, COND 12
add r15, -1806543551
test r15, 267386880
jz randomx_isn_104
; CBRANCH r1, -1807592127, COND 12
add r9, -1806543551
test r9, 267386880
jz randomx_isn_118
randomx_isn_125:
; IADD_RS r4, r4, SHFT 0
lea r12, [r12+r12*1]
@ -703,10 +703,10 @@ randomx_isn_180:
and eax, 16376
xor r15, qword ptr [rsi+rax]
randomx_isn_181:
; CBRANCH -759703940, COND 2
add r14, -759704452
test r14, 261120
jz randomx_isn_144
; CBRANCH r2, -759703940, COND 2
add r10, -759704452
test r10, 261120
jz randomx_isn_175
randomx_isn_182:
; FADD_R f1, a2
addpd xmm1, xmm10
@ -781,9 +781,9 @@ randomx_isn_202:
; FSUB_R f0, a0
subpd xmm0, xmm8
randomx_isn_203:
; CBRANCH -1282235504, COND 2
add r12, -1282234992
test r12, 261120
; CBRANCH r1, -1282235504, COND 2
add r9, -1282234992
test r9, 261120
jz randomx_isn_182
randomx_isn_204:
; IMUL_M r1, L3[176744]
@ -792,9 +792,9 @@ randomx_isn_205:
; FSWAP_R e1
shufpd xmm5, xmm5, 1
randomx_isn_206:
; CBRANCH -1557284726, COND 14
add r10, -1555187574
test r10, 1069547520
; CBRANCH r0, -1557284726, COND 14
add r8, -1555187574
test r8, 1069547520
jz randomx_isn_204
randomx_isn_207:
; IADD_M r3, L1[r0+72267507]
@ -945,10 +945,10 @@ randomx_isn_246:
mov rax, 9887096364157721599
imul r12, rax
randomx_isn_247:
; CBRANCH -722123512, COND 2
add r13, -722123512
test r13, 261120
jz randomx_isn_217
; CBRANCH r3, -722123512, COND 2
add r11, -722123512
test r11, 261120
jz randomx_isn_246
randomx_isn_248:
; ISMULH_R r7, r6
mov rax, r15
@ -977,7 +977,7 @@ randomx_isn_254:
; FMUL_R e3, a2
mulpd xmm7, xmm10
randomx_isn_255:
; CBRANCH -2007380935, COND 9
add r9, -2007315399
test r9, 33423360
jz randomx_isn_248
; CBRANCH r7, -2007380935, COND 9
add r15, -2007315399
test r15, 33423360
jz randomx_isn_249

@ -598,51 +598,42 @@ There are 2 control instructions.
|frequency|instruction|dst|src|operation|
|-|-|-|-|-|
|1/256|CFROUND|`fprc`|R|`fprc = src >>> imm32`
|16/256|CBRANCH|-|-|(conditional jump)
|1/256|CFROUND|-|R|`fprc = src >>> imm32`
|16/256|CBRANCH|R|-|`dst = dst + cimm`, conditional jump
#### 5.4.1 CFROUND
This instruction calculates a 2-bit value by rotating the source register right by `imm32` bits and taking the 2 least significant bits (the value of the source register is unaffected). The result is stored in the `fprc` register. This changes the rounding mode of all subsequent floating point instructions.
#### 5.4.2 CBRANCH
This instruction performs a conditional jump in the Program Buffer. It uses an implicit integer register operand `creg`. This register is determined based on preceding instructions. For this purpose, the VM assigns each integer register two tag values:
This instruction adds an immediate value `cimm` (constructed from `imm32`, see below) to the destination register and then performs a conditional jump in the Program Buffer based on the value of the destination register. The target of the jump is the instruction following the instruction when register `dst` was last modified.
* `lastUsed` - the index of the instruction when the register was last modified. The initial value at the start of each program iteration is `-1`, meaning the register is unmodified.
* `count` - the number of times the register has been selected as the operand of a CBRANCH instruction. The initial value at the start of each program iteration is `0`.
A register is considered as modified by an instruction in the following cases:
At the beginning of each program iteration, all registers are considered to be unmodified. A register is considered as modified by an instruction in the following cases:
* It is the destination register of an integer instruction except IMUL_RCP and ISWAP_R.
* It is the destination register of IMUL_RCP and `imm32` is not zero or a power of 2.
* It is the source or the destination register of ISWAP_R and the destination and source registers are distinct.
* The CBRANCH instruction is considered to modify all integer registers.
There are 3 rules for the selection of the `creg` register, evaluated in this order:
1. The register with the lowest value of `lastUsed` tag is selected.
1. In case multiple registers have the same value of the `lastUsed` tag, the register with the lowest value of the `count` tag is selected from them.
1. In case multiple registers have the same values of both `lastUsed` and `count` tags, the register with the lowest index is selected (`r0` before `r1` etc.) from them.
Whenever a register is selected as the operand of a CBRANCH instruction, its `count` tag is increased by 1.
If register `dst` has not been modified yet, the jump target is the first instruction in the Program Buffer.
The CBRANCH instruction performs the following steps:
1. A constant `b` is calculated as `mod.cond + RANDOMX_JUMP_OFFSET`.
1. A constant `cimm` is constructed as sign-extended `imm32` with bit `b` set to 1 and bit `b-1` set to 0 (if `b > 0`).
1. `cimm` is added to `creg`.
1. If bits `b` to `b + RANDOMX_JUMP_BITS - 1` of `creg` are zero, execution jumps to instruction `creg.lastUsed + 1` (the instruction following the instruction where `creg` was last modified).
1. `cimm` is added to the destination register.
1. If bits `b` to `b + RANDOMX_JUMP_BITS - 1` of the destination register are zero, the jump is executed (target is the instruction following the instruction where `dst` was last modified).
Bits in immediate and register values are numbered from 0 to 63 with 0 being the least significant bit. For example, for `b = 10` and `RANDOMX_JUMP_BITS = 8`, the bits are arranged like this:
```
cimm = SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSMMMMMMMMMMMMMMMMMMMMM10MMMMMMMMM
creg = ..............................................XXXXXXXX..........
dst = ..............................................XXXXXXXX..........
```
`S` is a copied sign bit from `imm32`. `M` denotes bits of `imm32`. The 9th bit is set to 0 and the 10th bit is set to 1. This value would be added to `creg`.
`S` is a copied sign bit from `imm32`. `M` denotes bits of `imm32`. The 9th bit is set to 0 and the 10th bit is set to 1. This value will be added to `dst`.
The second line uses `X` to mark bits of `creg` that would be checked by the condition. If all these bits are 0 after adding `cimm`, the jump is executed.
The second line uses `X` to mark bits of `dst` that will be checked by the condition. If all these bits are 0 after adding `cimm`, the jump is executed.
The construction of the CBRANCH instruction ensures that no inifinite loops are possible in the program.

@ -53,8 +53,7 @@ namespace randomx {
void AssemblyGeneratorX86::generateProgram(Program& prog) {
for (unsigned i = 0; i < RegistersCount; ++i) {
registerUsage[i].lastUsed = -1;
registerUsage[i].count = 0;
registerUsage[i] = -1;
}
asmCode.str(std::string()); //clear
for (unsigned i = 0; i < prog.getSize(); ++i) {
@ -270,7 +269,7 @@ namespace randomx {
}
void AssemblyGeneratorX86::h_IADD_RS(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
if(instr.dst == RegisterNeedsDisplacement)
asmCode << "\tlea " << regR[instr.dst] << ", [" << regR[instr.dst] << "+" << regR[instr.src] << "*" << (1 << (instr.getModShift())) << std::showpos << (int32_t)instr.getImm32() << std::noshowpos << "]" << std::endl;
else
@ -279,7 +278,7 @@ namespace randomx {
}
void AssemblyGeneratorX86::h_IADD_M(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
if (instr.src != instr.dst) {
genAddressReg(instr);
asmCode << "\tadd " << regR[instr.dst] << ", qword ptr [" << regScratchpadAddr << "+rax]" << std::endl;
@ -291,7 +290,7 @@ namespace randomx {
}
void AssemblyGeneratorX86::h_ISUB_R(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
if (instr.src != instr.dst) {
asmCode << "\tsub " << regR[instr.dst] << ", " << regR[instr.src] << std::endl;
}
@ -302,7 +301,7 @@ namespace randomx {
}
void AssemblyGeneratorX86::h_ISUB_M(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
if (instr.src != instr.dst) {
genAddressReg(instr);
asmCode << "\tsub " << regR[instr.dst] << ", qword ptr [" << regScratchpadAddr << "+rax]" << std::endl;
@ -314,7 +313,7 @@ namespace randomx {
}
void AssemblyGeneratorX86::h_IMUL_R(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
if (instr.src != instr.dst) {
asmCode << "\timul " << regR[instr.dst] << ", " << regR[instr.src] << std::endl;
}
@ -325,7 +324,7 @@ namespace randomx {
}
void AssemblyGeneratorX86::h_IMUL_M(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
if (instr.src != instr.dst) {
genAddressReg(instr);
asmCode << "\timul " << regR[instr.dst] << ", qword ptr [" << regScratchpadAddr << "+rax]" << std::endl;
@ -337,7 +336,7 @@ namespace randomx {
}
void AssemblyGeneratorX86::h_IMULH_R(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
asmCode << "\tmov rax, " << regR[instr.dst] << std::endl;
asmCode << "\tmul " << regR[instr.src] << std::endl;
asmCode << "\tmov " << regR[instr.dst] << ", rdx" << std::endl;
@ -345,7 +344,7 @@ namespace randomx {
}
void AssemblyGeneratorX86::h_IMULH_M(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
if (instr.src != instr.dst) {
genAddressReg(instr, "ecx");
asmCode << "\tmov rax, " << regR[instr.dst] << std::endl;
@ -360,7 +359,7 @@ namespace randomx {
}
void AssemblyGeneratorX86::h_ISMULH_R(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
asmCode << "\tmov rax, " << regR[instr.dst] << std::endl;
asmCode << "\timul " << regR[instr.src] << std::endl;
asmCode << "\tmov " << regR[instr.dst] << ", rdx" << std::endl;
@ -368,7 +367,7 @@ namespace randomx {
}
void AssemblyGeneratorX86::h_ISMULH_M(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
if (instr.src != instr.dst) {
genAddressReg(instr, "ecx");
asmCode << "\tmov rax, " << regR[instr.dst] << std::endl;
@ -383,13 +382,13 @@ namespace randomx {
}
void AssemblyGeneratorX86::h_INEG_R(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
asmCode << "\tneg " << regR[instr.dst] << std::endl;
traceint(instr);
}
void AssemblyGeneratorX86::h_IXOR_R(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
if (instr.src != instr.dst) {
asmCode << "\txor " << regR[instr.dst] << ", " << regR[instr.src] << std::endl;
}
@ -400,7 +399,7 @@ namespace randomx {
}
void AssemblyGeneratorX86::h_IXOR_M(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
if (instr.src != instr.dst) {
genAddressReg(instr);
asmCode << "\txor " << regR[instr.dst] << ", qword ptr [" << regScratchpadAddr << "+rax]" << std::endl;
@ -412,7 +411,7 @@ namespace randomx {
}
void AssemblyGeneratorX86::h_IROR_R(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
if (instr.src != instr.dst) {
asmCode << "\tmov ecx, " << regR32[instr.src] << std::endl;
asmCode << "\tror " << regR[instr.dst] << ", cl" << std::endl;
@ -424,7 +423,7 @@ namespace randomx {
}
void AssemblyGeneratorX86::h_IROL_R(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
if (instr.src != instr.dst) {
asmCode << "\tmov ecx, " << regR32[instr.src] << std::endl;
asmCode << "\trol " << regR[instr.dst] << ", cl" << std::endl;
@ -438,7 +437,7 @@ namespace randomx {
void AssemblyGeneratorX86::h_IMUL_RCP(Instruction& instr, int i) {
uint64_t divisor = instr.getImm32();
if (!isPowerOf2(divisor)) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
asmCode << "\tmov rax, " << randomx_reciprocal(divisor) << std::endl;
asmCode << "\timul " << regR[instr.dst] << ", rax" << std::endl;
traceint(instr);
@ -450,8 +449,8 @@ namespace randomx {
void AssemblyGeneratorX86::h_ISWAP_R(Instruction& instr, int i) {
if (instr.src != instr.dst) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.src].lastUsed = i;
registerUsage[instr.dst] = i;
registerUsage[instr.src] = i;
asmCode << "\txchg " << regR[instr.dst] << ", " << regR[instr.src] << std::endl;
traceint(instr);
}
@ -538,9 +537,8 @@ namespace randomx {
}
void AssemblyGeneratorX86::h_CBRANCH(Instruction& instr, int i) {
int reg = getConditionRegister(registerUsage);
int target = registerUsage[reg].lastUsed + 1;
registerUsage[reg].count++;
int reg = instr.dst;
int target = registerUsage[reg] + 1;
int shift = instr.getModCond() + ConditionOffset;
int32_t imm = instr.getImm32() | (1L << shift);
if (ConditionOffset > 0 || shift > 0)
@ -550,7 +548,7 @@ namespace randomx {
asmCode << "\tjz randomx_isn_" << target << std::endl;
//mark all registers as used
for (unsigned j = 0; j < RegistersCount; ++j) {
registerUsage[j].lastUsed = i;
registerUsage[j] = i;
}
}

@ -89,6 +89,6 @@ namespace randomx {
static InstructionGenerator engine[256];
std::stringstream asmCode;
RegisterUsage registerUsage[RegistersCount];
int registerUsage[RegistersCount];
};
}

@ -112,11 +112,6 @@ namespace randomx {
double hi;
};
struct RegisterUsage {
int32_t lastUsed;
int32_t count;
};
constexpr uint32_t ScratchpadL1 = RANDOMX_SCRATCHPAD_L1 / sizeof(int_reg_t);
constexpr uint32_t ScratchpadL2 = RANDOMX_SCRATCHPAD_L2 / sizeof(int_reg_t);
constexpr uint32_t ScratchpadL3 = RANDOMX_SCRATCHPAD_L3 / sizeof(int_reg_t);
@ -131,21 +126,6 @@ namespace randomx {
constexpr int RegisterNeedsDisplacement = 5; //x86 r13 register
constexpr int RegisterNeedsSib = 4; //x86 r12 register
inline int getConditionRegister(RegisterUsage(&registerUsage)[RegistersCount]) {
int min = INT_MAX;
int minCount = 0;
int minIndex;
//prefer registers that have been used as a condition register fewer times
for (unsigned i = 0; i < RegistersCount; ++i) {
if (registerUsage[i].lastUsed < min || (registerUsage[i].lastUsed == min && registerUsage[i].count < minCount)) {
min = registerUsage[i].lastUsed;
minCount = registerUsage[i].count;
minIndex = i;
}
}
return minIndex;
}
inline bool isPowerOf2(uint64_t x) {
return (x & (x - 1)) == 0;
}

@ -288,7 +288,7 @@ namespace randomx {
}
void Instruction::h_CBRANCH(std::ostream& os) const {
os << (int32_t)getImm32() << ", COND " << (int)(getModCond()) << std::endl;
os << "r" << (int)dst << ", " << (int32_t)getImm32() << ", COND " << (int)(getModCond()) << std::endl;
}
void Instruction::h_ISTORE(std::ostream& os) const {

@ -267,8 +267,7 @@ namespace randomx {
void JitCompilerX86::generateProgramPrologue(Program& prog, ProgramConfiguration& pcfg) {
instructionOffsets.clear();
for (unsigned i = 0; i < 8; ++i) {
registerUsage[i].lastUsed = -1;
registerUsage[i].count = 0;
registerUsage[i] = -1;
}
codePos = prologueSize;
memcpy(code + codePos - 48, &pcfg.eMask, sizeof(pcfg.eMask));
@ -435,7 +434,7 @@ namespace randomx {
}
void JitCompilerX86::h_IADD_RS(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
emit(REX_LEA);
if (instr.dst == RegisterNeedsDisplacement)
emitByte(0xac);
@ -447,7 +446,7 @@ namespace randomx {
}
void JitCompilerX86::h_IADD_M(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
if (instr.src != instr.dst) {
genAddressReg(instr);
emit(REX_ADD_RM);
@ -466,7 +465,7 @@ namespace randomx {
}
void JitCompilerX86::h_ISUB_R(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
if (instr.src != instr.dst) {
emit(REX_SUB_RR);
emitByte(0xc0 + 8 * instr.dst + instr.src);
@ -479,7 +478,7 @@ namespace randomx {
}
void JitCompilerX86::h_ISUB_M(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
if (instr.src != instr.dst) {
genAddressReg(instr);
emit(REX_SUB_RM);
@ -494,7 +493,7 @@ namespace randomx {
}
void JitCompilerX86::h_IMUL_R(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
if (instr.src != instr.dst) {
emit(REX_IMUL_RR);
emitByte(0xc0 + 8 * instr.dst + instr.src);
@ -507,7 +506,7 @@ namespace randomx {
}
void JitCompilerX86::h_IMUL_M(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
if (instr.src != instr.dst) {
genAddressReg(instr);
emit(REX_IMUL_RM);
@ -522,7 +521,7 @@ namespace randomx {
}
void JitCompilerX86::h_IMULH_R(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
emit(REX_MOV_RR64);
emitByte(0xc0 + instr.dst);
emit(REX_MUL_R);
@ -532,7 +531,7 @@ namespace randomx {
}
void JitCompilerX86::h_IMULH_M(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
if (instr.src != instr.dst) {
genAddressReg(instr, false);
emit(REX_MOV_RR64);
@ -551,7 +550,7 @@ namespace randomx {
}
void JitCompilerX86::h_ISMULH_R(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
emit(REX_MOV_RR64);
emitByte(0xc0 + instr.dst);
emit(REX_MUL_R);
@ -561,7 +560,7 @@ namespace randomx {
}
void JitCompilerX86::h_ISMULH_M(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
if (instr.src != instr.dst) {
genAddressReg(instr, false);
emit(REX_MOV_RR64);
@ -582,7 +581,7 @@ namespace randomx {
void JitCompilerX86::h_IMUL_RCP(Instruction& instr, int i) {
uint64_t divisor = instr.getImm32();
if (!isPowerOf2(divisor)) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
emit(MOV_RAX_I);
emit64(randomx_reciprocal_fast(divisor));
emit(REX_IMUL_RM);
@ -591,13 +590,13 @@ namespace randomx {
}
void JitCompilerX86::h_INEG_R(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
emit(REX_NEG);
emitByte(0xd8 + instr.dst);
}
void JitCompilerX86::h_IXOR_R(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
if (instr.src != instr.dst) {
emit(REX_XOR_RR);
emitByte(0xc0 + 8 * instr.dst + instr.src);
@ -610,7 +609,7 @@ namespace randomx {
}
void JitCompilerX86::h_IXOR_M(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
if (instr.src != instr.dst) {
genAddressReg(instr);
emit(REX_XOR_RM);
@ -625,7 +624,7 @@ namespace randomx {
}
void JitCompilerX86::h_IROR_R(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
if (instr.src != instr.dst) {
emit(REX_MOV_RR);
emitByte(0xc8 + instr.src);
@ -640,7 +639,7 @@ namespace randomx {
}
void JitCompilerX86::h_IROL_R(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.dst] = i;
if (instr.src != instr.dst) {
emit(REX_MOV_RR);
emitByte(0xc8 + instr.src);
@ -656,8 +655,8 @@ namespace randomx {
void JitCompilerX86::h_ISWAP_R(Instruction& instr, int i) {
if (instr.src != instr.dst) {
registerUsage[instr.dst].lastUsed = i;
registerUsage[instr.src].lastUsed = i;
registerUsage[instr.dst] = i;
registerUsage[instr.src] = i;
emit(REX_XCHG);
emitByte(0xc0 + instr.src + 8 * instr.dst);
}
@ -739,9 +738,8 @@ namespace randomx {
}
void JitCompilerX86::h_CBRANCH(Instruction& instr, int i) {
int reg = getConditionRegister(registerUsage);
int target = registerUsage[reg].lastUsed + 1;
registerUsage[reg].count++;
int reg = instr.dst;
int target = registerUsage[reg] + 1;
emit(REX_ADD_I);
emitByte(0xc0 + reg);
int shift = instr.getModCond() + ConditionOffset;
@ -756,7 +754,7 @@ namespace randomx {
emit32(instructionOffsets[target] - (codePos + 4));
//mark all registers as used
for (unsigned j = 0; j < RegistersCount; ++j) {
registerUsage[j].lastUsed = i;
registerUsage[j] = i;
}
}

@ -67,7 +67,7 @@ namespace randomx {
private:
static InstructionGeneratorX86 engine[256];
std::vector<int32_t> instructionOffsets;
RegisterUsage registerUsage[RegistersCount];
int registerUsage[RegistersCount];
uint8_t* code;
int32_t codePos;

@ -241,7 +241,7 @@ int main(int argc, char** argv) {
std::cout << "Calculated result: ";
result.print(std::cout);
if (noncesCount == 1000 && seedValue == 0)
std::cout << "Reference result: d908c4ce0329e2e104c08c3a76b427dd9dad3622a04b06af965cd00cd62b2d2e" << std::endl;
std::cout << "Reference result: 0063222e8c4c687cc7c91ea86f3747d8dbd53af6bdf937167736b9284e4d7dac" << std::endl;
if (!miningMode) {
std::cout << "Performance: " << 1000 * elapsed / noncesCount << " ms per hash" << std::endl;
}

@ -283,10 +283,9 @@ namespace randomx {
template<class Allocator, bool softAes>
void InterpretedVm<Allocator, softAes>::precompileProgram(int_reg_t(&r)[RegistersCount], rx_vec_f128(&f)[RegisterCountFlt], rx_vec_f128(&e)[RegisterCountFlt], rx_vec_f128(&a)[RegisterCountFlt]) {
RegisterUsage registerUsage[RegistersCount];
int registerUsage[RegistersCount];
for (unsigned i = 0; i < RegistersCount; ++i) {
registerUsage[i].lastUsed = -1;
registerUsage[i].count = 0;
registerUsage[i] = -1;
}
for (unsigned i = 0; i < RANDOMX_PROGRAM_SIZE; ++i) {
auto& instr = program(i);
@ -307,7 +306,7 @@ namespace randomx {
ibc.shift = instr.getModShift();
ibc.imm = signExtend2sCompl(instr.getImm32());
}
registerUsage[dst].lastUsed = i;
registerUsage[dst] = i;
} break;
CASE_REP(IADD_M) {
@ -324,7 +323,7 @@ namespace randomx {
ibc.isrc = &Zero;
ibc.memMask = ScratchpadL3Mask;
}
registerUsage[dst].lastUsed = i;
registerUsage[dst] = i;
} break;
CASE_REP(ISUB_R) {
@ -339,7 +338,7 @@ namespace randomx {
ibc.imm = signExtend2sCompl(instr.getImm32());
ibc.isrc = &ibc.imm;
}
registerUsage[dst].lastUsed = i;
registerUsage[dst] = i;
} break;
CASE_REP(ISUB_M) {
@ -356,7 +355,7 @@ namespace randomx {
ibc.isrc = &Zero;
ibc.memMask = ScratchpadL3Mask;
}
registerUsage[dst].lastUsed = i;
registerUsage[dst] = i;
} break;
CASE_REP(IMUL_R) {
@ -371,7 +370,7 @@ namespace randomx {
ibc.imm = signExtend2sCompl(instr.getImm32());
ibc.isrc = &ibc.imm;
}
registerUsage[dst].lastUsed = i;
registerUsage[dst] = i;
} break;
CASE_REP(IMUL_M) {
@ -388,7 +387,7 @@ namespace randomx {
ibc.isrc = &Zero;
ibc.memMask = ScratchpadL3Mask;
}
registerUsage[dst].lastUsed = i;
registerUsage[dst] = i;
} break;
CASE_REP(IMULH_R) {
@ -397,7 +396,7 @@ namespace randomx {
ibc.type = InstructionType::IMULH_R;
ibc.idst = &r[dst];
ibc.isrc = &r[src];
registerUsage[dst].lastUsed = i;
registerUsage[dst] = i;
} break;
CASE_REP(IMULH_M) {
@ -414,7 +413,7 @@ namespace randomx {
ibc.isrc = &Zero;
ibc.memMask = ScratchpadL3Mask;
}
registerUsage[dst].lastUsed = i;
registerUsage[dst] = i;
} break;
CASE_REP(ISMULH_R) {
@ -423,7 +422,7 @@ namespace randomx {
ibc.type = InstructionType::ISMULH_R;
ibc.idst = &r[dst];
ibc.isrc = &r[src];
registerUsage[dst].lastUsed = i;
registerUsage[dst] = i;
} break;
CASE_REP(ISMULH_M) {
@ -440,7 +439,7 @@ namespace randomx {
ibc.isrc = &Zero;
ibc.memMask = ScratchpadL3Mask;
}
registerUsage[dst].lastUsed = i;
registerUsage[dst] = i;
} break;
CASE_REP(IMUL_RCP) {
@ -451,7 +450,7 @@ namespace randomx {
ibc.idst = &r[dst];
ibc.imm = randomx_reciprocal(divisor);
ibc.isrc = &ibc.imm;
registerUsage[dst].lastUsed = i;
registerUsage[dst] = i;
}
else {
ibc.type = InstructionType::NOP;
@ -462,7 +461,7 @@ namespace randomx {
auto dst = instr.dst % RegistersCount;
ibc.type = InstructionType::INEG_R;
ibc.idst = &r[dst];
registerUsage[dst].lastUsed = i;
registerUsage[dst] = i;
} break;
CASE_REP(IXOR_R) {
@ -477,7 +476,7 @@ namespace randomx {
ibc.imm = signExtend2sCompl(instr.getImm32());
ibc.isrc = &ibc.imm;
}
registerUsage[dst].lastUsed = i;
registerUsage[dst] = i;
} break;
CASE_REP(IXOR_M) {
@ -494,7 +493,7 @@ namespace randomx {
ibc.isrc = &Zero;
ibc.memMask = ScratchpadL3Mask;
}
registerUsage[dst].lastUsed = i;
registerUsage[dst] = i;
} break;
CASE_REP(IROR_R) {
@ -509,7 +508,7 @@ namespace randomx {
ibc.imm = instr.getImm32();
ibc.isrc = &ibc.imm;
}
registerUsage[dst].lastUsed = i;
registerUsage[dst] = i;
} break;
CASE_REP(IROL_R) {
@ -524,7 +523,7 @@ namespace randomx {
ibc.imm = instr.getImm32();
ibc.isrc = &ibc.imm;
}
registerUsage[dst].lastUsed = i;
registerUsage[dst] = i;
} break;
CASE_REP(ISWAP_R) {
@ -534,8 +533,8 @@ namespace randomx {
ibc.idst = &r[dst];
ibc.isrc = &r[src];
ibc.type = InstructionType::ISWAP_R;
registerUsage[dst].lastUsed = i;
registerUsage[src].lastUsed = i;
registerUsage[dst] = i;
registerUsage[src] = i;
}
else {
ibc.type = InstructionType::NOP;
@ -620,10 +619,9 @@ namespace randomx {
CASE_REP(CBRANCH) {
ibc.type = InstructionType::CBRANCH;
//jump condition
int reg = getConditionRegister(registerUsage);
int reg = instr.dst % RegistersCount;
ibc.isrc = &r[reg];
ibc.target = registerUsage[reg].lastUsed;
registerUsage[reg].count++;
ibc.target = registerUsage[reg];
int shift = instr.getModCond() + ConditionOffset;
const uint64_t conditionMask = ConditionMask << shift;
ibc.imm = signExtend2sCompl(instr.getImm32()) | (1ULL << shift);
@ -632,7 +630,7 @@ namespace randomx {
ibc.memMask = ConditionMask << shift;
//mark all registers as used
for (unsigned j = 0; j < RegistersCount; ++j) {
registerUsage[j].lastUsed = i;
registerUsage[j] = i;
}
} break;

Loading…
Cancel
Save