Преглед изворни кода

Use 'dst' as the CBRANCH condition register
See issue #43

tevador пре 7 година
родитељ
комит
8a5ead5ce3

+ 58 - 58
doc/program.asm

@@ -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
-	add r10, -1886823353
-	test r10, 2139095040
+	; CBRANCH r7, -1891017657, COND 15
+	add r15, -1886823353
+	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
-	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:
 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
-	add r11, -1278791788
-	test r11, 1069547520
+	; CBRANCH r5, -1278791788, COND 14
+	add r13, -1278791788
+	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
-	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:
 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
-	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:
 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
-	add r12, -2143810860
-	test r12, 130560
+	; CBRANCH r6, -2143810604, COND 1
+	add r14, -2143810860
+	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
-	add r15, -67705940
-	test r15, 2088960
+	; CBRANCH r1, -67701844, COND 5
+	add r9, -67705940
+	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
-	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:
 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
-	add r9, -1784542676
-	test r9, 2139095040
+	; CBRANCH r4, -1780348372, COND 15
+	add r12, -1784542676
+	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
-	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:
 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
-	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:
 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
-	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:
 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
-	add r12, -1282234992
-	test r12, 261120
+	; CBRANCH r1, -1282235504, COND 2
+	add r9, -1282234992
+	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
-	add r10, -1555187574
-	test r10, 1069547520
+	; CBRANCH r0, -1557284726, COND 14
+	add r8, -1555187574
+	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
-	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:
 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
-	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

+ 10 - 19
doc/specs.md

@@ -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`
-|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
 #### 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.
-* `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 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:
-
-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:
 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. 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:
 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.
 
 

+ 22 - 24
src/assembly_generator_x86.cpp

@@ -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].count = 0;
+			registerUsage[i] = -1;
 		}
 		}
 		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.src].lastUsed = i;
+			registerUsage[instr.dst] = 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 target = registerUsage[reg].lastUsed + 1;
-		registerUsage[reg].count++;
+		int reg = instr.dst;
+		int target = registerUsage[reg] + 1;
 		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;
 		}
 		}
 	}
 	}
 
 

+ 1 - 1
src/assembly_generator_x86.hpp

@@ -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];
 	};
 	};
 }
 }

+ 0 - 20
src/common.hpp

@@ -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;
 	}
 	}

+ 1 - 1
src/instruction.cpp

@@ -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 {

+ 22 - 24
src/jit_compiler_x86.cpp

@@ -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].count = 0;
+			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));
@@ -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.src].lastUsed = i;
+			registerUsage[instr.dst] = 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 target = registerUsage[reg].lastUsed + 1;
-		registerUsage[reg].count++;
+		int reg = instr.dst;
+		int target = registerUsage[reg] + 1;
 		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;
 		}
 		}
 	}
 	}
 
 

+ 1 - 1
src/jit_compiler_x86.hpp

@@ -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;
 
 

+ 1 - 1
src/tests/benchmark.cpp

@@ -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;
 		}
 		}

+ 23 - 25
src/vm_interpreted.cpp

@@ -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].count = 0;
+			registerUsage[i] = -1;
 		}
 		}
 		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[src].lastUsed = i;
+						registerUsage[dst] = 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;
-					registerUsage[reg].count++;
+					ibc.target = registerUsage[reg];
 					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;