mirror of
				https://git.wownero.com/wownero/RandomWOW.git
				synced 2024-08-15 00:23:14 +00:00 
			
		
		
		
	Fixed biased condition register selection
This commit is contained in:
		
							parent
							
								
									5543fb5f2f
								
							
						
					
					
						commit
						3cf6a30076
					
				
					 8 changed files with 107 additions and 116 deletions
				
			
		|  | @ -95,8 +95,8 @@ randomx_isn_23: | |||
| 	mulpd xmm6, xmm8 | ||||
| randomx_isn_24: | ||||
| 	; CBRANCH 149087159, COND 13 | ||||
| 	add r8, 149087159 | ||||
| 	test r8, 1040384 | ||||
| 	add r10, 149087159 | ||||
| 	test r10, 1040384 | ||||
| 	jz randomx_isn_21 | ||||
| randomx_isn_25: | ||||
| 	; FADD_R f3, a0 | ||||
|  | @ -197,8 +197,8 @@ randomx_isn_53: | |||
| 	subpd xmm2, xmm8 | ||||
| randomx_isn_54: | ||||
| 	; CBRANCH 1917049931, COND 12 | ||||
| 	add r8, 1917049931 | ||||
| 	test r8, 520192 | ||||
| 	add r11, 1917049931 | ||||
| 	test r11, 520192 | ||||
| 	jz randomx_isn_52 | ||||
| randomx_isn_55: | ||||
| 	; IXOR_R r2, r3 | ||||
|  | @ -329,8 +329,8 @@ randomx_isn_88: | |||
| 	imul r9, r11 | ||||
| randomx_isn_89: | ||||
| 	; CBRANCH -122257389, COND 13 | ||||
| 	add r8, -122249197 | ||||
| 	test r8, 1040384 | ||||
| 	add r13, -122249197 | ||||
| 	test r13, 1040384 | ||||
| 	jz randomx_isn_75 | ||||
| randomx_isn_90: | ||||
| 	; ISTORE L1[r5+228116180], r7 | ||||
|  |  | |||
|  | @ -45,7 +45,8 @@ namespace randomx { | |||
| 
 | ||||
| 	void AssemblyGeneratorX86::generateProgram(Program& prog) { | ||||
| 		for (unsigned i = 0; i < RegistersCount; ++i) { | ||||
| 			registerUsage[i] = -1; | ||||
| 			registerUsage[i].lastUsed = -1; | ||||
| 			registerUsage[i].count = 0; | ||||
| 		} | ||||
| 		asmCode.str(std::string()); //clear
 | ||||
| 		for (unsigned i = 0; i < prog.getSize(); ++i) { | ||||
|  | @ -215,18 +216,6 @@ namespace randomx { | |||
| 		asmCode << "}" << std::endl; | ||||
| 	} | ||||
| 
 | ||||
| 	int AssemblyGeneratorX86::getConditionRegister() { | ||||
| 		int min = INT_MAX; | ||||
| 		int minIndex; | ||||
| 		for (unsigned i = 0; i < 8; ++i) { | ||||
| 			if (registerUsage[i] < min) { | ||||
| 				min = registerUsage[i]; | ||||
| 				minIndex = i; | ||||
| 			} | ||||
| 		} | ||||
| 		return minIndex; | ||||
| 	} | ||||
| 
 | ||||
| 	void AssemblyGeneratorX86::traceint(Instruction& instr) { | ||||
| 		if (trace) { | ||||
| 			asmCode << "\tpush " << regR[instr.dst] << std::endl; | ||||
|  | @ -273,7 +262,7 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void AssemblyGeneratorX86::h_IADD_RS(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = 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 | ||||
|  | @ -282,7 +271,7 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void AssemblyGeneratorX86::h_IADD_M(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		if (instr.src != instr.dst) { | ||||
| 			genAddressReg(instr); | ||||
| 			asmCode << "\tadd " << regR[instr.dst] << ", qword ptr [" << regScratchpadAddr << "+rax]" << std::endl; | ||||
|  | @ -294,7 +283,7 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void AssemblyGeneratorX86::h_ISUB_R(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		if (instr.src != instr.dst) { | ||||
| 			asmCode << "\tsub " << regR[instr.dst] << ", " << regR[instr.src] << std::endl; | ||||
| 		} | ||||
|  | @ -305,7 +294,7 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void AssemblyGeneratorX86::h_ISUB_M(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		if (instr.src != instr.dst) { | ||||
| 			genAddressReg(instr); | ||||
| 			asmCode << "\tsub " << regR[instr.dst] << ", qword ptr [" << regScratchpadAddr << "+rax]" << std::endl; | ||||
|  | @ -317,7 +306,7 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void AssemblyGeneratorX86::h_IMUL_R(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		if (instr.src != instr.dst) { | ||||
| 			asmCode << "\timul " << regR[instr.dst] << ", " << regR[instr.src] << std::endl; | ||||
| 		} | ||||
|  | @ -328,7 +317,7 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void AssemblyGeneratorX86::h_IMUL_M(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		if (instr.src != instr.dst) { | ||||
| 			genAddressReg(instr); | ||||
| 			asmCode << "\timul " << regR[instr.dst] << ", qword ptr [" << regScratchpadAddr << "+rax]" << std::endl; | ||||
|  | @ -341,7 +330,7 @@ namespace randomx { | |||
| 
 | ||||
| 	//4 uOPs
 | ||||
| 	void AssemblyGeneratorX86::h_IMULH_R(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		asmCode << "\tmov rax, " << regR[instr.dst] << std::endl; | ||||
| 		asmCode << "\tmul " << regR[instr.src] << std::endl; | ||||
| 		asmCode << "\tmov " << regR[instr.dst] << ", rdx" << std::endl; | ||||
|  | @ -349,7 +338,7 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void AssemblyGeneratorX86::h_IMULH_M(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		if (instr.src != instr.dst) { | ||||
| 			genAddressReg(instr, "ecx"); | ||||
| 			asmCode << "\tmov rax, " << regR[instr.dst] << std::endl; | ||||
|  | @ -364,7 +353,7 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void AssemblyGeneratorX86::h_ISMULH_R(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		asmCode << "\tmov rax, " << regR[instr.dst] << std::endl; | ||||
| 		asmCode << "\timul " << regR[instr.src] << std::endl; | ||||
| 		asmCode << "\tmov " << regR[instr.dst] << ", rdx" << std::endl; | ||||
|  | @ -372,7 +361,7 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void AssemblyGeneratorX86::h_ISMULH_M(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		if (instr.src != instr.dst) { | ||||
| 			genAddressReg(instr, "ecx"); | ||||
| 			asmCode << "\tmov rax, " << regR[instr.dst] << std::endl; | ||||
|  | @ -387,13 +376,13 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void AssemblyGeneratorX86::h_INEG_R(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		asmCode << "\tneg " << regR[instr.dst] << std::endl; | ||||
| 		traceint(instr); | ||||
| 	} | ||||
| 
 | ||||
| 	void AssemblyGeneratorX86::h_IXOR_R(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		if (instr.src != instr.dst) { | ||||
| 			asmCode << "\txor " << regR[instr.dst] << ", " << regR[instr.src] << std::endl; | ||||
| 		} | ||||
|  | @ -404,7 +393,7 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void AssemblyGeneratorX86::h_IXOR_M(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		if (instr.src != instr.dst) { | ||||
| 			genAddressReg(instr); | ||||
| 			asmCode << "\txor " << regR[instr.dst] << ", qword ptr [" << regScratchpadAddr << "+rax]" << std::endl; | ||||
|  | @ -416,7 +405,7 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void AssemblyGeneratorX86::h_IROR_R(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		if (instr.src != instr.dst) { | ||||
| 			asmCode << "\tmov ecx, " << regR32[instr.src] << std::endl; | ||||
| 			asmCode << "\tror " << regR[instr.dst] << ", cl" << std::endl; | ||||
|  | @ -428,7 +417,7 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void AssemblyGeneratorX86::h_IROL_R(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		if (instr.src != instr.dst) { | ||||
| 			asmCode << "\tmov ecx, " << regR32[instr.src] << std::endl; | ||||
| 			asmCode << "\trol " << regR[instr.dst] << ", cl" << std::endl; | ||||
|  | @ -441,7 +430,7 @@ namespace randomx { | |||
| 
 | ||||
| 	void AssemblyGeneratorX86::h_IMUL_RCP(Instruction& instr, int i) { | ||||
| 		if (instr.getImm32() != 0) { | ||||
| 			registerUsage[instr.dst] = i; | ||||
| 			registerUsage[instr.dst].lastUsed = i; | ||||
| 			asmCode << "\tmov rax, " << randomx_reciprocal(instr.getImm32()) << std::endl; | ||||
| 			asmCode << "\timul " << regR[instr.dst] << ", rax" << std::endl; | ||||
| 			traceint(instr); | ||||
|  | @ -453,8 +442,8 @@ namespace randomx { | |||
| 
 | ||||
| 	void AssemblyGeneratorX86::h_ISWAP_R(Instruction& instr, int i) { | ||||
| 		if (instr.src != instr.dst) { | ||||
| 			registerUsage[instr.dst] = i; | ||||
| 			registerUsage[instr.src] = i; | ||||
| 			registerUsage[instr.dst].lastUsed = i; | ||||
| 			registerUsage[instr.src].lastUsed = i; | ||||
| 			asmCode << "\txchg " << regR[instr.dst] << ", " << regR[instr.src] << std::endl; | ||||
| 			traceint(instr); | ||||
| 		} | ||||
|  | @ -541,14 +530,16 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void AssemblyGeneratorX86::h_CBRANCH(Instruction& instr, int i) { | ||||
| 		int reg = getConditionRegister(); | ||||
| 		int target = registerUsage[reg] + 1; | ||||
| 		int reg = getConditionRegister(registerUsage); | ||||
| 		int target = registerUsage[reg].lastUsed + 1; | ||||
| 		registerUsage[reg].count++; | ||||
| 		int shift = instr.getModCond(); | ||||
| 		asmCode << "\tadd " << regR[reg] << ", " << (int32_t)(instr.getImm32() | (1 << shift)) << std::endl; | ||||
| 		asmCode << "\ttest " << regR[reg] << ", " << (ConditionMask << shift) << std::endl; | ||||
| 		asmCode << "\tjz randomx_isn_" << target << std::endl; | ||||
| 		for (unsigned j = 0; j < RegistersCount; ++j) { //mark all registers as used
 | ||||
| 			registerUsage[j] = i; | ||||
| 		//mark all registers as used
 | ||||
| 		for (unsigned j = 0; j < RegistersCount; ++j) { | ||||
| 			registerUsage[j].lastUsed = i; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -43,7 +43,6 @@ namespace randomx { | |||
| 		void genAddressReg(Instruction&, const char*); | ||||
| 		void genAddressRegDst(Instruction&, int); | ||||
| 		int32_t genAddressImm(Instruction&); | ||||
| 		int getConditionRegister(); | ||||
| 		void generateCode(Instruction&, int); | ||||
| 		void traceint(Instruction&); | ||||
| 		void traceflt(Instruction&); | ||||
|  | @ -82,6 +81,6 @@ namespace randomx { | |||
| 
 | ||||
| 		static InstructionGenerator engine[256]; | ||||
| 		std::stringstream asmCode; | ||||
| 		int registerUsage[RegistersCount]; | ||||
| 		RegisterUsage registerUsage[RegistersCount]; | ||||
| 	}; | ||||
| } | ||||
|  | @ -88,6 +88,11 @@ 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); | ||||
|  | @ -102,6 +107,21 @@ namespace randomx { | |||
| 	constexpr int RegisterNeedsDisplacement = 5; //x86 r13 register
 | ||||
| 	constexpr int RegisterNeedsSib = 4; //x86 r12 register
 | ||||
| 
 | ||||
| 	inline int getConditionRegister(RegisterUsage(®isterUsage)[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; | ||||
| 	} | ||||
| 
 | ||||
| 	struct MemoryRegisters { | ||||
| 		addr_t mx, ma; | ||||
| 		uint8_t* memory = nullptr; | ||||
|  |  | |||
|  | @ -299,7 +299,8 @@ namespace randomx { | |||
| 	void JitCompilerX86::generateProgramPrologue(Program& prog, ProgramConfiguration& pcfg) { | ||||
| 		instructionOffsets.clear(); | ||||
| 		for (unsigned i = 0; i < 8; ++i) { | ||||
| 			registerUsage[i] = -1; | ||||
| 			registerUsage[i].lastUsed = -1; | ||||
| 			registerUsage[i].count = 0; | ||||
| 		} | ||||
| 		codePos = prologueSize; | ||||
| 		memcpy(code + codePos - 48, &pcfg.eMask, sizeof(pcfg.eMask)); | ||||
|  | @ -468,7 +469,7 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void JitCompilerX86::h_IADD_RS(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		emit(REX_LEA); | ||||
| 		if (instr.dst == RegisterNeedsDisplacement) | ||||
| 			emitByte(0xac); | ||||
|  | @ -480,7 +481,7 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void JitCompilerX86::h_IADD_M(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		if (instr.src != instr.dst) { | ||||
| 			genAddressReg(instr); | ||||
| 			emit(REX_ADD_RM); | ||||
|  | @ -499,7 +500,7 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void JitCompilerX86::h_ISUB_R(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		if (instr.src != instr.dst) { | ||||
| 			emit(REX_SUB_RR); | ||||
| 			emitByte(0xc0 + 8 * instr.dst + instr.src); | ||||
|  | @ -512,7 +513,7 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void JitCompilerX86::h_ISUB_M(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		if (instr.src != instr.dst) { | ||||
| 			genAddressReg(instr); | ||||
| 			emit(REX_SUB_RM); | ||||
|  | @ -527,7 +528,7 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void JitCompilerX86::h_IMUL_R(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		if (instr.src != instr.dst) { | ||||
| 			emit(REX_IMUL_RR); | ||||
| 			emitByte(0xc0 + 8 * instr.dst + instr.src); | ||||
|  | @ -540,7 +541,7 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void JitCompilerX86::h_IMUL_M(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		if (instr.src != instr.dst) { | ||||
| 			genAddressReg(instr); | ||||
| 			emit(REX_IMUL_RM); | ||||
|  | @ -555,7 +556,7 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void JitCompilerX86::h_IMULH_R(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		emit(REX_MOV_RR64); | ||||
| 		emitByte(0xc0 + instr.dst); | ||||
| 		emit(REX_MUL_R); | ||||
|  | @ -565,7 +566,7 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void JitCompilerX86::h_IMULH_M(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		if (instr.src != instr.dst) { | ||||
| 			genAddressReg(instr, false); | ||||
| 			emit(REX_MOV_RR64); | ||||
|  | @ -584,7 +585,7 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void JitCompilerX86::h_ISMULH_R(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		emit(REX_MOV_RR64); | ||||
| 		emitByte(0xc0 + instr.dst); | ||||
| 		emit(REX_MUL_R); | ||||
|  | @ -594,7 +595,7 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void JitCompilerX86::h_ISMULH_M(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		if (instr.src != instr.dst) { | ||||
| 			genAddressReg(instr, false); | ||||
| 			emit(REX_MOV_RR64); | ||||
|  | @ -614,7 +615,7 @@ namespace randomx { | |||
| 
 | ||||
| 	void JitCompilerX86::h_IMUL_RCP(Instruction& instr, int i) { | ||||
| 		if (instr.getImm32() != 0) { | ||||
| 			registerUsage[instr.dst] = i; | ||||
| 			registerUsage[instr.dst].lastUsed = i; | ||||
| 			emit(MOV_RAX_I); | ||||
| 			emit64(randomx_reciprocal(instr.getImm32())); | ||||
| 			emit(REX_IMUL_RM); | ||||
|  | @ -623,13 +624,13 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void JitCompilerX86::h_INEG_R(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		emit(REX_NEG); | ||||
| 		emitByte(0xd8 + instr.dst); | ||||
| 	} | ||||
| 
 | ||||
| 	void JitCompilerX86::h_IXOR_R(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		if (instr.src != instr.dst) { | ||||
| 			emit(REX_XOR_RR); | ||||
| 			emitByte(0xc0 + 8 * instr.dst + instr.src); | ||||
|  | @ -642,7 +643,7 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void JitCompilerX86::h_IXOR_M(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		if (instr.src != instr.dst) { | ||||
| 			genAddressReg(instr); | ||||
| 			emit(REX_XOR_RM); | ||||
|  | @ -657,7 +658,7 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void JitCompilerX86::h_IROR_R(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		if (instr.src != instr.dst) { | ||||
| 			emit(REX_MOV_RR); | ||||
| 			emitByte(0xc8 + instr.src); | ||||
|  | @ -672,7 +673,7 @@ namespace randomx { | |||
| 	} | ||||
| 
 | ||||
| 	void JitCompilerX86::h_IROL_R(Instruction& instr, int i) { | ||||
| 		registerUsage[instr.dst] = i; | ||||
| 		registerUsage[instr.dst].lastUsed = i; | ||||
| 		if (instr.src != instr.dst) { | ||||
| 			emit(REX_MOV_RR); | ||||
| 			emitByte(0xc8 + instr.src); | ||||
|  | @ -688,8 +689,8 @@ namespace randomx { | |||
| 
 | ||||
| 	void JitCompilerX86::h_ISWAP_R(Instruction& instr, int i) { | ||||
| 		if (instr.src != instr.dst) { | ||||
| 			registerUsage[instr.dst] = i; | ||||
| 			registerUsage[instr.src] = i; | ||||
| 			registerUsage[instr.dst].lastUsed = i; | ||||
| 			registerUsage[instr.src].lastUsed = i; | ||||
| 			emit(REX_XCHG); | ||||
| 			emitByte(0xc0 + instr.src + 8 * instr.dst); | ||||
| 		} | ||||
|  | @ -770,21 +771,10 @@ namespace randomx { | |||
| 		emit(AND_OR_MOV_LDMXCSR); | ||||
| 	} | ||||
| 
 | ||||
| 	int JitCompilerX86::getConditionRegister() { | ||||
| 		int min = INT_MAX; | ||||
| 		int minIndex; | ||||
| 		for (unsigned i = 0; i < RegistersCount; ++i) { | ||||
| 			if (registerUsage[i] < min) { | ||||
| 				min = registerUsage[i]; | ||||
| 				minIndex = i; | ||||
| 			} | ||||
| 		} | ||||
| 		return minIndex; | ||||
| 	} | ||||
| 
 | ||||
| 	void JitCompilerX86::h_CBRANCH(Instruction& instr, int i) { | ||||
| 		int reg = getConditionRegister(); | ||||
| 		int target = registerUsage[reg] + 1; | ||||
| 		int reg = getConditionRegister(registerUsage); | ||||
| 		int target = registerUsage[reg].lastUsed + 1; | ||||
| 		registerUsage[reg].count++; | ||||
| 		int shift = instr.getModCond(); | ||||
| 		emit(REX_ADD_I); | ||||
| 		emitByte(0xc0 + reg); | ||||
|  | @ -794,8 +784,9 @@ namespace randomx { | |||
| 		emit32(ConditionMask << shift); | ||||
| 		emit(JZ); | ||||
| 		emit32(instructionOffsets[target] - (codePos + 4)); | ||||
| 		for (unsigned j = 0; j < RegistersCount; ++j) { //mark all registers as used
 | ||||
| 			registerUsage[j] = i; | ||||
| 		//mark all registers as used
 | ||||
| 		for (unsigned j = 0; j < RegistersCount; ++j) { | ||||
| 			registerUsage[j].lastUsed = i; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -58,13 +58,12 @@ namespace randomx { | |||
| 	private: | ||||
| 		static InstructionGeneratorX86 engine[256]; | ||||
| 		std::vector<int32_t> instructionOffsets; | ||||
| 		int registerUsage[8]; | ||||
| 		RegisterUsage registerUsage[RegistersCount]; | ||||
| 		uint8_t* code; | ||||
| 		int32_t codePos; | ||||
| 
 | ||||
| 		void generateProgramPrologue(Program&, ProgramConfiguration&); | ||||
| 		void generateProgramEpilogue(Program&); | ||||
| 		int getConditionRegister(); | ||||
| 		void genAddressReg(Instruction&, bool); | ||||
| 		void genAddressRegDst(Instruction&, bool); | ||||
| 		void genAddressImm(Instruction&); | ||||
|  |  | |||
|  | @ -229,7 +229,7 @@ int main(int argc, char** argv) { | |||
| 		std::cout << "Calculated result: "; | ||||
| 		result.print(std::cout); | ||||
| 		if (noncesCount == 1000 && seedValue == 0) | ||||
| 			std::cout << "Reference result:  804fed4a3dc4ed12917a210aad295925544e688e28549d7178eb27f412476a10" << std::endl; | ||||
| 			std::cout << "Reference result:  df0862de0bedf2da0432a5eeb097453f2b020d00eadc60c32ae27b8d9d10ee0c" << std::endl; | ||||
| 		if (!miningMode) { | ||||
| 			std::cout << "Performance: " << 1000 * elapsed / noncesCount << " ms per hash" << std::endl; | ||||
| 		} | ||||
|  |  | |||
|  | @ -265,18 +265,6 @@ namespace randomx { | |||
| 			_mm_store_pd(®.e[i].lo, e[i]); | ||||
| 	} | ||||
| 
 | ||||
| 	static int getConditionRegister(int(®isterUsage)[RegistersCount]) { | ||||
| 		int min = INT_MAX; | ||||
| 		int minIndex; | ||||
| 		for (unsigned i = 0; i < RegistersCount; ++i) { | ||||
| 			if (registerUsage[i] < min) { | ||||
| 				min = registerUsage[i]; | ||||
| 				minIndex = i; | ||||
| 			} | ||||
| 		} | ||||
| 		return minIndex; | ||||
| 	} | ||||
| 
 | ||||
| 	template<class Allocator, bool softAes> | ||||
| 	void InterpretedVm<Allocator, softAes>::datasetRead(uint32_t address, int_reg_t(&r)[RegistersCount]) { | ||||
| 		uint64_t* datasetLine = (uint64_t*)(mem.memory + address); | ||||
|  | @ -288,9 +276,10 @@ namespace randomx { | |||
| 
 | ||||
| 	template<class Allocator, bool softAes> | ||||
| 	void InterpretedVm<Allocator, softAes>::precompileProgram(int_reg_t(&r)[RegistersCount], __m128d (&f)[RegisterCountFlt], __m128d (&e)[RegisterCountFlt], __m128d (&a)[RegisterCountFlt]) { | ||||
| 		int registerUsage[RegistersCount]; | ||||
| 		RegisterUsage registerUsage[RegistersCount]; | ||||
| 		for (unsigned i = 0; i < RegistersCount; ++i) { | ||||
| 			registerUsage[i] = -1; | ||||
| 			registerUsage[i].lastUsed = -1; | ||||
| 			registerUsage[i].count = 0; | ||||
| 		} | ||||
| 		for (unsigned i = 0; i < RANDOMX_PROGRAM_SIZE; ++i) { | ||||
| 			auto& instr = program(i); | ||||
|  | @ -311,7 +300,7 @@ namespace randomx { | |||
| 						ibc.shift = instr.getModShift(); | ||||
| 						ibc.imm = signExtend2sCompl(instr.getImm32()); | ||||
| 					} | ||||
| 					registerUsage[dst] = i; | ||||
| 					registerUsage[dst].lastUsed = i; | ||||
| 				} break; | ||||
| 
 | ||||
| 				CASE_REP(IADD_M) { | ||||
|  | @ -328,7 +317,7 @@ namespace randomx { | |||
| 						ibc.isrc = &Zero; | ||||
| 						ibc.memMask = ScratchpadL3Mask; | ||||
| 					} | ||||
| 					registerUsage[dst] = i; | ||||
| 					registerUsage[dst].lastUsed = i; | ||||
| 				} break; | ||||
| 
 | ||||
| 				CASE_REP(ISUB_R) { | ||||
|  | @ -343,7 +332,7 @@ namespace randomx { | |||
| 						ibc.imm = signExtend2sCompl(instr.getImm32()); | ||||
| 						ibc.isrc = &ibc.imm; | ||||
| 					} | ||||
| 					registerUsage[dst] = i; | ||||
| 					registerUsage[dst].lastUsed = i; | ||||
| 				} break; | ||||
| 
 | ||||
| 				CASE_REP(ISUB_M) { | ||||
|  | @ -360,7 +349,7 @@ namespace randomx { | |||
| 						ibc.isrc = &Zero; | ||||
| 						ibc.memMask = ScratchpadL3Mask; | ||||
| 					} | ||||
| 					registerUsage[dst] = i; | ||||
| 					registerUsage[dst].lastUsed = i; | ||||
| 				} break; | ||||
| 
 | ||||
| 				CASE_REP(IMUL_R) { | ||||
|  | @ -375,7 +364,7 @@ namespace randomx { | |||
| 						ibc.imm = signExtend2sCompl(instr.getImm32()); | ||||
| 						ibc.isrc = &ibc.imm; | ||||
| 					} | ||||
| 					registerUsage[dst] = i; | ||||
| 					registerUsage[dst].lastUsed = i; | ||||
| 				} break; | ||||
| 
 | ||||
| 				CASE_REP(IMUL_M) { | ||||
|  | @ -392,7 +381,7 @@ namespace randomx { | |||
| 						ibc.isrc = &Zero; | ||||
| 						ibc.memMask = ScratchpadL3Mask; | ||||
| 					} | ||||
| 					registerUsage[dst] = i; | ||||
| 					registerUsage[dst].lastUsed = i; | ||||
| 				} break; | ||||
| 
 | ||||
| 				CASE_REP(IMULH_R) { | ||||
|  | @ -401,7 +390,7 @@ namespace randomx { | |||
| 					ibc.type = InstructionType::IMULH_R; | ||||
| 					ibc.idst = &r[dst]; | ||||
| 					ibc.isrc = &r[src]; | ||||
| 					registerUsage[dst] = i; | ||||
| 					registerUsage[dst].lastUsed = i; | ||||
| 				} break; | ||||
| 
 | ||||
| 				CASE_REP(IMULH_M) { | ||||
|  | @ -418,7 +407,7 @@ namespace randomx { | |||
| 						ibc.isrc = &Zero; | ||||
| 						ibc.memMask = ScratchpadL3Mask; | ||||
| 					} | ||||
| 					registerUsage[dst] = i; | ||||
| 					registerUsage[dst].lastUsed = i; | ||||
| 				} break; | ||||
| 
 | ||||
| 				CASE_REP(ISMULH_R) { | ||||
|  | @ -427,7 +416,7 @@ namespace randomx { | |||
| 					ibc.type = InstructionType::ISMULH_R; | ||||
| 					ibc.idst = &r[dst]; | ||||
| 					ibc.isrc = &r[src]; | ||||
| 					registerUsage[dst] = i; | ||||
| 					registerUsage[dst].lastUsed = i; | ||||
| 				} break; | ||||
| 
 | ||||
| 				CASE_REP(ISMULH_M) { | ||||
|  | @ -444,7 +433,7 @@ namespace randomx { | |||
| 						ibc.isrc = &Zero; | ||||
| 						ibc.memMask = ScratchpadL3Mask; | ||||
| 					} | ||||
| 					registerUsage[dst] = i; | ||||
| 					registerUsage[dst].lastUsed = i; | ||||
| 				} break; | ||||
| 
 | ||||
| 				CASE_REP(IMUL_RCP) { | ||||
|  | @ -455,7 +444,7 @@ namespace randomx { | |||
| 						ibc.idst = &r[dst]; | ||||
| 						ibc.imm = randomx_reciprocal(divisor); | ||||
| 						ibc.isrc = &ibc.imm; | ||||
| 						registerUsage[dst] = i; | ||||
| 						registerUsage[dst].lastUsed = i; | ||||
| 					} | ||||
| 					else { | ||||
| 						ibc.type = InstructionType::NOP; | ||||
|  | @ -466,7 +455,7 @@ namespace randomx { | |||
| 					auto dst = instr.dst % RegistersCount; | ||||
| 					ibc.type = InstructionType::INEG_R; | ||||
| 					ibc.idst = &r[dst]; | ||||
| 					registerUsage[dst] = i; | ||||
| 					registerUsage[dst].lastUsed = i; | ||||
| 				} break; | ||||
| 
 | ||||
| 				CASE_REP(IXOR_R) { | ||||
|  | @ -481,7 +470,7 @@ namespace randomx { | |||
| 						ibc.imm = signExtend2sCompl(instr.getImm32()); | ||||
| 						ibc.isrc = &ibc.imm; | ||||
| 					} | ||||
| 					registerUsage[dst] = i; | ||||
| 					registerUsage[dst].lastUsed = i; | ||||
| 				} break; | ||||
| 
 | ||||
| 				CASE_REP(IXOR_M) { | ||||
|  | @ -498,7 +487,7 @@ namespace randomx { | |||
| 						ibc.isrc = &Zero; | ||||
| 						ibc.memMask = ScratchpadL3Mask; | ||||
| 					} | ||||
| 					registerUsage[dst] = i; | ||||
| 					registerUsage[dst].lastUsed = i; | ||||
| 				} break; | ||||
| 
 | ||||
| 				CASE_REP(IROR_R) { | ||||
|  | @ -513,7 +502,7 @@ namespace randomx { | |||
| 						ibc.imm = instr.getImm32(); | ||||
| 						ibc.isrc = &ibc.imm; | ||||
| 					} | ||||
| 					registerUsage[dst] = i; | ||||
| 					registerUsage[dst].lastUsed = i; | ||||
| 				} break; | ||||
| 
 | ||||
| 				CASE_REP(IROL_R) { | ||||
|  | @ -528,7 +517,7 @@ namespace randomx { | |||
| 						ibc.imm = instr.getImm32(); | ||||
| 						ibc.isrc = &ibc.imm; | ||||
| 					} | ||||
| 					registerUsage[dst] = i; | ||||
| 					registerUsage[dst].lastUsed = i; | ||||
| 				} break; | ||||
| 
 | ||||
| 				CASE_REP(ISWAP_R) { | ||||
|  | @ -538,8 +527,8 @@ namespace randomx { | |||
| 						ibc.idst = &r[dst]; | ||||
| 						ibc.isrc = &r[src]; | ||||
| 						ibc.type = InstructionType::ISWAP_R; | ||||
| 						registerUsage[dst] = i; | ||||
| 						registerUsage[src] = i; | ||||
| 						registerUsage[dst].lastUsed = i; | ||||
| 						registerUsage[src].lastUsed = i; | ||||
| 					} | ||||
| 					else { | ||||
| 						ibc.type = InstructionType::NOP; | ||||
|  | @ -626,13 +615,15 @@ namespace randomx { | |||
| 					//jump condition
 | ||||
| 					int reg = getConditionRegister(registerUsage); | ||||
| 					ibc.isrc = &r[reg]; | ||||
| 					ibc.target = registerUsage[reg]; | ||||
| 					ibc.target = registerUsage[reg].lastUsed; | ||||
| 					registerUsage[reg].count++; | ||||
| 					int shift = instr.getModCond(); | ||||
| 					const uint64_t conditionMask = ConditionMask << instr.getModCond(); | ||||
| 					ibc.imm = signExtend2sCompl(instr.getImm32()) | (1ULL << shift); | ||||
| 					ibc.memMask = ConditionMask << shift; | ||||
| 					for (unsigned j = 0; j < RegistersCount; ++j) { //mark all registers as used
 | ||||
| 						registerUsage[j] = i; | ||||
| 					//mark all registers as used
 | ||||
| 					for (unsigned j = 0; j < RegistersCount; ++j) { | ||||
| 						registerUsage[j].lastUsed = i; | ||||
| 					} | ||||
| 				} break; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue