From fc476020ba862a162843e3b57c69cc8c18b0aa8b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 10 Aug 2023 18:19:30 -0700 Subject: [PATCH] riscv: Improve immediate generation. Use compressed instructions more, better jumps when outside PC 32-bit range. --- Common/RiscVEmitter.cpp | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/Common/RiscVEmitter.cpp b/Common/RiscVEmitter.cpp index 71484f4656..6f11dbe2cc 100644 --- a/Common/RiscVEmitter.cpp +++ b/Common/RiscVEmitter.cpp @@ -1182,14 +1182,19 @@ bool RiscVEmitter::CJInRange(const void *src, const void *dst) const { void RiscVEmitter::QuickJAL(RiscVReg scratchreg, RiscVReg rd, const u8 *dst) { if (!JInRange(GetCodePointer(), dst)) { + int32_t lower = 0; static_assert(sizeof(intptr_t) <= sizeof(int64_t)); + // If it's near PC, we're better off shooting for AUIPC. Should take 8 bytes. int64_t pcdelta = (int64_t)dst - (int64_t)GetCodePointer(); - int32_t lower = (int32_t)SignReduce64(pcdelta, 12); - uintptr_t upper = ((pcdelta - lower) >> 12) << 12; - if (scratchreg != rd) - LI(scratchreg, (uintptr_t)GetCodePointer() + upper, rd); - else + if (pcdelta < 0x100000000LL && pcdelta >= -0x100000000LL) { + lower = (int32_t)SignReduce64(pcdelta, 12); + uintptr_t upper = ((pcdelta - lower) >> 12) << 12; LI(scratchreg, (uintptr_t)GetCodePointer() + upper); + } else { + lower = (int32_t)SignReduce64((int64_t)dst, 12); + // Abuse rd as a temporary if we need to. + LI(scratchreg, dst - lower, rd == scratchreg ? R_ZERO : rd); + } JALR(rd, scratchreg, lower); } else { JAL(rd, dst); @@ -1258,8 +1263,12 @@ void RiscVEmitter::SetRegToImmediate(RiscVReg rd, uint64_t value, RiscVReg temp) // If this is just a 32-bit unsigned value, use a wall to mask. if ((svalue >> 32) == 0) { LI(rd, (int32_t)(svalue & 0xFFFFFFFF)); - SLLI(rd, rd, BitsSupported() - 32); - SRLI(rd, rd, BitsSupported() - 32); + if (SupportsBitmanip('a')) { + ZEXT_W(rd, rd); + } else { + SLLI(rd, rd, BitsSupported() - 32); + SRLI(rd, rd, BitsSupported() - 32); + } return; } @@ -1277,7 +1286,7 @@ void RiscVEmitter::SetRegToImmediate(RiscVReg rd, uint64_t value, RiscVReg temp) return; } - // Okay, let's just start with the upper 32 bits and add the rest via ORI. + // Okay, let's just start with the upper 32 bits and add the rest via ADDI. int64_t upper = svalue >> 32; LI(rd, upper); @@ -1293,7 +1302,7 @@ void RiscVEmitter::SetRegToImmediate(RiscVReg rd, uint64_t value, RiscVReg temp) int32_t chunk = (remaining >> sourceShift) & 0x07FF; SLLI(rd, rd, targetShift - shifted); - ORI(rd, rd, chunk); + ADDI(rd, rd, chunk); // Okay, increase shift and clear the bits we've deposited. shifted = targetShift;