riscv: Improve immediate generation.

Use compressed instructions more, better jumps when outside PC 32-bit
range.
This commit is contained in:
Unknown W. Brackets 2023-08-10 18:19:30 -07:00
parent 50ea506b6a
commit fc476020ba

View File

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