Use 'dst' as the CBRANCH condition register

See issue #43
pr-ds4
tevador 5 years ago
parent 1276d67d2f
commit 8a5ead5ce3

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

@ -598,51 +598,42 @@ There are 2 control instructions.
|frequency|instruction|dst|src|operation| |frequency|instruction|dst|src|operation|
|-|-|-|-|-| |-|-|-|-|-|
|1/256|CFROUND|`fprc`|R|`fprc = src >>> imm32` |1/256|CFROUND|-|R|`fprc = src >>> imm32`
|16/256|CBRANCH|-|-|(conditional jump) |16/256|CBRANCH|R|-|`dst = dst + cimm`, conditional jump
#### 5.4.1 CFROUND #### 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. 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 #### 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. 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:
* `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:
* It is the destination register of an integer instruction except IMUL_RCP and ISWAP_R. * 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 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. * 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. * 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: If register `dst` has not been modified yet, the jump target is the first instruction in the Program Buffer.
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.
The CBRANCH instruction performs the following steps: The CBRANCH instruction performs the following steps:
1. A constant `b` is calculated as `mod.cond + RANDOMX_JUMP_OFFSET`. 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. 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. `cimm` is added to the destination register.
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. 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: 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 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. 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) { void AssemblyGeneratorX86::generateProgram(Program& prog) {
for (unsigned i = 0; i < RegistersCount; ++i) { for (unsigned i = 0; i < RegistersCount; ++i) {
registerUsage[i].lastUsed = -1; registerUsage[i] = -1;
registerUsage[i].count = 0;
} }
asmCode.str(std::string()); //clear asmCode.str(std::string()); //clear
for (unsigned i = 0; i < prog.getSize(); ++i) { for (unsigned i = 0; i < prog.getSize(); ++i) {
@ -270,7 +269,7 @@ namespace randomx {
} }
void AssemblyGeneratorX86::h_IADD_RS(Instruction& instr, int i) { void AssemblyGeneratorX86::h_IADD_RS(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i; registerUsage[instr.dst] = i;
if(instr.dst == RegisterNeedsDisplacement) 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; 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 else
@ -279,7 +278,7 @@ namespace randomx {
} }
void AssemblyGeneratorX86::h_IADD_M(Instruction& instr, int i) { void AssemblyGeneratorX86::h_IADD_M(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i; registerUsage[instr.dst] = i;
if (instr.src != instr.dst) { if (instr.src != instr.dst) {
genAddressReg(instr); genAddressReg(instr);
asmCode << "\tadd " << regR[instr.dst] << ", qword ptr [" << regScratchpadAddr << "+rax]" << std::endl; 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) { void AssemblyGeneratorX86::h_ISUB_R(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i; registerUsage[instr.dst] = i;
if (instr.src != instr.dst) { if (instr.src != instr.dst) {
asmCode << "\tsub " << regR[instr.dst] << ", " << regR[instr.src] << std::endl; 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) { void AssemblyGeneratorX86::h_ISUB_M(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i; registerUsage[instr.dst] = i;
if (instr.src != instr.dst) { if (instr.src != instr.dst) {
genAddressReg(instr); genAddressReg(instr);
asmCode << "\tsub " << regR[instr.dst] << ", qword ptr [" << regScratchpadAddr << "+rax]" << std::endl; 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) { void AssemblyGeneratorX86::h_IMUL_R(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i; registerUsage[instr.dst] = i;
if (instr.src != instr.dst) { if (instr.src != instr.dst) {
asmCode << "\timul " << regR[instr.dst] << ", " << regR[instr.src] << std::endl; 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) { void AssemblyGeneratorX86::h_IMUL_M(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i; registerUsage[instr.dst] = i;
if (instr.src != instr.dst) { if (instr.src != instr.dst) {
genAddressReg(instr); genAddressReg(instr);
asmCode << "\timul " << regR[instr.dst] << ", qword ptr [" << regScratchpadAddr << "+rax]" << std::endl; 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) { 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 << "\tmov rax, " << regR[instr.dst] << std::endl;
asmCode << "\tmul " << regR[instr.src] << std::endl; asmCode << "\tmul " << regR[instr.src] << std::endl;
asmCode << "\tmov " << regR[instr.dst] << ", rdx" << 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) { void AssemblyGeneratorX86::h_IMULH_M(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i; registerUsage[instr.dst] = i;
if (instr.src != instr.dst) { if (instr.src != instr.dst) {
genAddressReg(instr, "ecx"); genAddressReg(instr, "ecx");
asmCode << "\tmov rax, " << regR[instr.dst] << std::endl; asmCode << "\tmov rax, " << regR[instr.dst] << std::endl;
@ -360,7 +359,7 @@ namespace randomx {
} }
void AssemblyGeneratorX86::h_ISMULH_R(Instruction& instr, int i) { 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 << "\tmov rax, " << regR[instr.dst] << std::endl;
asmCode << "\timul " << regR[instr.src] << std::endl; asmCode << "\timul " << regR[instr.src] << std::endl;
asmCode << "\tmov " << regR[instr.dst] << ", rdx" << 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) { void AssemblyGeneratorX86::h_ISMULH_M(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i; registerUsage[instr.dst] = i;
if (instr.src != instr.dst) { if (instr.src != instr.dst) {
genAddressReg(instr, "ecx"); genAddressReg(instr, "ecx");
asmCode << "\tmov rax, " << regR[instr.dst] << std::endl; asmCode << "\tmov rax, " << regR[instr.dst] << std::endl;
@ -383,13 +382,13 @@ namespace randomx {
} }
void AssemblyGeneratorX86::h_INEG_R(Instruction& instr, int i) { 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; asmCode << "\tneg " << regR[instr.dst] << std::endl;
traceint(instr); traceint(instr);
} }
void AssemblyGeneratorX86::h_IXOR_R(Instruction& instr, int i) { void AssemblyGeneratorX86::h_IXOR_R(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i; registerUsage[instr.dst] = i;
if (instr.src != instr.dst) { if (instr.src != instr.dst) {
asmCode << "\txor " << regR[instr.dst] << ", " << regR[instr.src] << std::endl; 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) { void AssemblyGeneratorX86::h_IXOR_M(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i; registerUsage[instr.dst] = i;
if (instr.src != instr.dst) { if (instr.src != instr.dst) {
genAddressReg(instr); genAddressReg(instr);
asmCode << "\txor " << regR[instr.dst] << ", qword ptr [" << regScratchpadAddr << "+rax]" << std::endl; 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) { void AssemblyGeneratorX86::h_IROR_R(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i; registerUsage[instr.dst] = i;
if (instr.src != instr.dst) { if (instr.src != instr.dst) {
asmCode << "\tmov ecx, " << regR32[instr.src] << std::endl; asmCode << "\tmov ecx, " << regR32[instr.src] << std::endl;
asmCode << "\tror " << regR[instr.dst] << ", cl" << 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) { void AssemblyGeneratorX86::h_IROL_R(Instruction& instr, int i) {
registerUsage[instr.dst].lastUsed = i; registerUsage[instr.dst] = i;
if (instr.src != instr.dst) { if (instr.src != instr.dst) {
asmCode << "\tmov ecx, " << regR32[instr.src] << std::endl; asmCode << "\tmov ecx, " << regR32[instr.src] << std::endl;
asmCode << "\trol " << regR[instr.dst] << ", cl" << 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) { void AssemblyGeneratorX86::h_IMUL_RCP(Instruction& instr, int i) {
uint64_t divisor = instr.getImm32(); uint64_t divisor = instr.getImm32();
if (!isPowerOf2(divisor)) { if (!isPowerOf2(divisor)) {
registerUsage[instr.dst].lastUsed = i; registerUsage[instr.dst] = i;
asmCode << "\tmov rax, " << randomx_reciprocal(divisor) << std::endl; asmCode << "\tmov rax, " << randomx_reciprocal(divisor) << std::endl;
asmCode << "\timul " << regR[instr.dst] << ", rax" << std::endl; asmCode << "\timul " << regR[instr.dst] << ", rax" << std::endl;
traceint(instr); traceint(instr);
@ -450,8 +449,8 @@ namespace randomx {
void AssemblyGeneratorX86::h_ISWAP_R(Instruction& instr, int i) { void AssemblyGeneratorX86::h_ISWAP_R(Instruction& instr, int i) {
if (instr.src != instr.dst) { if (instr.src != instr.dst) {
registerUsage[instr.dst].lastUsed = i; registerUsage[instr.dst] = i;
registerUsage[instr.src].lastUsed = i; registerUsage[instr.src] = i;
asmCode << "\txchg " << regR[instr.dst] << ", " << regR[instr.src] << std::endl; asmCode << "\txchg " << regR[instr.dst] << ", " << regR[instr.src] << std::endl;
traceint(instr); traceint(instr);
} }
@ -538,9 +537,8 @@ namespace randomx {
} }
void AssemblyGeneratorX86::h_CBRANCH(Instruction& instr, int i) { void AssemblyGeneratorX86::h_CBRANCH(Instruction& instr, int i) {
int reg = getConditionRegister(registerUsage); int reg = instr.dst;
int target = registerUsage[reg].lastUsed + 1; int target = registerUsage[reg] + 1;
registerUsage[reg].count++;
int shift = instr.getModCond() + ConditionOffset; int shift = instr.getModCond() + ConditionOffset;
int32_t imm = instr.getImm32() | (1L << shift); int32_t imm = instr.getImm32() | (1L << shift);
if (ConditionOffset > 0 || shift > 0) if (ConditionOffset > 0 || shift > 0)
@ -550,7 +548,7 @@ namespace randomx {
asmCode << "\tjz randomx_isn_" << target << std::endl; asmCode << "\tjz randomx_isn_" << target << std::endl;
//mark all registers as used //mark all registers as used
for (unsigned j = 0; j < RegistersCount; ++j) { for (unsigned j = 0; j < RegistersCount; ++j) {
registerUsage[j].lastUsed = i; registerUsage[j] = i;
} }
} }

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

@ -112,11 +112,6 @@ namespace randomx {
double hi; double hi;
}; };
struct RegisterUsage {
int32_t lastUsed;
int32_t count;
};
constexpr uint32_t ScratchpadL1 = RANDOMX_SCRATCHPAD_L1 / sizeof(int_reg_t); 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 ScratchpadL2 = RANDOMX_SCRATCHPAD_L2 / sizeof(int_reg_t);
constexpr uint32_t ScratchpadL3 = RANDOMX_SCRATCHPAD_L3 / 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 RegisterNeedsDisplacement = 5; //x86 r13 register
constexpr int RegisterNeedsSib = 4; //x86 r12 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) { inline bool isPowerOf2(uint64_t x) {
return (x & (x - 1)) == 0; return (x & (x - 1)) == 0;
} }

@ -288,7 +288,7 @@ namespace randomx {
} }
void Instruction::h_CBRANCH(std::ostream& os) const { 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 { void Instruction::h_ISTORE(std::ostream& os) const {

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

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

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

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

Loading…
Cancel
Save