Skip to content

Commit

Permalink
[RISC-V] Fix receiving of 2nd register in struct (#86144)
Browse files Browse the repository at this point in the history
* [RISC-V] Fix receiving of 2nd register in struct

* jit-format patch apply
  • Loading branch information
t-mustafin committed May 30, 2023
1 parent 394d847 commit fcae73f
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 72 deletions.
56 changes: 9 additions & 47 deletions src/coreclr/jit/codegenriscv64.cpp
Expand Up @@ -7827,7 +7827,7 @@ void CodeGen::genFnPrologCalleeRegArgs()
{
assert(srcRegNum != varDsc->GetOtherArgReg());

regNumber tmp_reg = REG_NA;
regNumber tmpReg = REG_NA;

bool FPbased;
int baseOffset = compiler->lvaFrameAddress(varNum, &FPbased);
Expand All @@ -7839,13 +7839,13 @@ void CodeGen::genFnPrologCalleeRegArgs()
}
else
{
assert(tmp_reg == REG_NA);
assert(tmpReg == REG_NA);

tmp_reg = REG_RA;
GetEmitter()->emitIns_I_la(EA_PTRSIZE, tmp_reg, baseOffset);
// The last parameter `int offs` of the `emitIns_S_R` is negtive,
// it means the offset imm had been stored within the `REG_RA`.
GetEmitter()->emitIns_S_R_R(ins_Store(storeType, true), size, srcRegNum, tmp_reg, varNum, -8);
tmpReg = REG_RA;
// Prepare tmpReg to possible future use
GetEmitter()->emitIns_I_la(EA_PTRSIZE, tmpReg, baseOffset);
GetEmitter()->emitIns_R_R_R(INS_add, EA_PTRSIZE, tmpReg, tmpReg, FPbased ? REG_FPBASE : REG_SPBASE);
GetEmitter()->emitIns_S_R_R(ins_Store(storeType), size, srcRegNum, tmpReg, varNum, 0);
}

regArgMaskLive &= ~genRegMask(srcRegNum);
Expand Down Expand Up @@ -7882,27 +7882,7 @@ void CodeGen::genFnPrologCalleeRegArgs()
// if the struct passed by two register, then store the second register `varDsc->GetOtherArgReg()`.
if (srcRegNum == varDsc->GetOtherArgReg())
{
if (emitter::isValidSimm12(baseOffset))
{
GetEmitter()->emitIns_S_R(ins_Store(storeType), size, srcRegNum, varNum, slotSize);
}
else
{
if (tmp_reg == REG_NA)
{
GetEmitter()->emitIns_I_la(EA_PTRSIZE, REG_RA, baseOffset);
// The last parameter `int offs` of the `emitIns_S_R` is negtive,
// it means the offset imm had been stored within the `REG_RA`.
GetEmitter()->emitIns_S_R_R(ins_Store(storeType, true), size, srcRegNum, REG_RA, varNum,
-slotSize - 8);
}
else
{
GetEmitter()->emitIns_R_R_I(INS_addi, EA_PTRSIZE, REG_RA, REG_RA, slotSize);
GetEmitter()->emitIns_S_R_R(ins_Store(storeType, true), size, srcRegNum, REG_RA, varNum,
-slotSize - 8);
}
}
GetEmitter()->emitIns_S_R_R(ins_Store(storeType), size, srcRegNum, tmpReg, varNum, slotSize);
regArgMaskLive &= ~genRegMask(srcRegNum); // maybe do this later is better!
}
else if (varDsc->lvIsSplit)
Expand All @@ -7928,25 +7908,7 @@ void CodeGen::genFnPrologCalleeRegArgs()
GetEmitter()->emitIns_R_R_I(INS_ld, size, REG_SCRATCH, REG_SCRATCH, 0);
}

if (emitter::isValidSimm12(baseOffset))
{
GetEmitter()->emitIns_S_R(INS_sd, size, REG_SCRATCH, varNum, TARGET_POINTER_SIZE);
}
else
{
if (tmp_reg == REG_NA)
{
GetEmitter()->emitIns_I_la(EA_PTRSIZE, REG_RA, baseOffset);
// The last parameter `int offs` of the `emitIns_S_R` is negtive,
// it means the offset imm had been stored within the `REG_RA`.
GetEmitter()->emitIns_S_R_R(INS_sd, size, REG_SCRATCH, REG_RA, varNum, -8);
}
else
{
GetEmitter()->emitIns_R_R_I(INS_addi, EA_PTRSIZE, REG_RA, REG_RA, TARGET_POINTER_SIZE);
GetEmitter()->emitIns_S_R_R(INS_sd, size, REG_SCRATCH, REG_RA, varNum, -slotSize - 8);
}
}
GetEmitter()->emitIns_S_R_R(ins_Store(storeType), size, REG_SCRATCH, tmpReg, varNum, slotSize);
}
}

Expand Down
46 changes: 21 additions & 25 deletions src/coreclr/jit/emitriscv64.cpp
Expand Up @@ -235,7 +235,7 @@ void emitter::emitIns(instruction ins)
}

/*****************************************************************************
* emitter::emitIns_S_R(), emitIns_S_R_R() and emitter::emitIns_R_S():
* emitter::emitIns_S_R(), emitter::emitIns_S_R_R() and emitter::emitIns_R_S():
*
* Add an Load/Store instruction(s): base+offset and base-addr-computing if needed.
* For referencing a stack-based local variable and a register
Expand All @@ -251,6 +251,7 @@ void emitter::emitIns_S_R_R(instruction ins, emitAttr attr, regNumber reg1, regN
ssize_t imm;

assert(tmpReg != codeGen->rsGetRsvdReg());
assert(reg1 != codeGen->rsGetRsvdReg());

emitAttr size = EA_SIZE(attr);

Expand All @@ -259,10 +260,10 @@ void emitter::emitIns_S_R_R(instruction ins, emitAttr attr, regNumber reg1, regN
{
case INS_sd:
case INS_sw:
case INS_fsw:
case INS_fsd:
case INS_sb:
case INS_sh:
case INS_sb:
case INS_fsd:
case INS_fsw:
break;

default:
Expand All @@ -277,41 +278,36 @@ void emitter::emitIns_S_R_R(instruction ins, emitAttr attr, regNumber reg1, regN
bool FPbased;

base = emitComp->lvaFrameAddress(varx, &FPbased);
imm = offs < 0 ? -offs - 8 : base + offs;

regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
regNumber reg2 = offs < 0 ? tmpReg : reg3;
assert(reg2 != REG_NA && reg2 != codeGen->rsGetRsvdReg());
assert(reg1 != codeGen->rsGetRsvdReg());

// regNumber reg2 = reg3;
offs = offs < 0 ? -offs - 8 : offs;
regNumber regBase = FPbased ? REG_FPBASE : REG_SPBASE;
regNumber reg2;

if ((-2048 <= imm) && (imm < 2048))
if (tmpReg == REG_NA)
{
// regs[1] = reg2;
reg2 = regBase;
imm = base + offs;
}
else
{
// ssize_t imm3 = imm & 0x800;
// ssize_t imm2 = imm + imm3;
reg2 = tmpReg;
imm = offs;
}

assert(reg2 != REG_NA && reg2 != codeGen->rsGetRsvdReg());

if (!isValidSimm12(imm))
{
// If immediate does not fit to store immediate 12 bits, construct necessary value in rsRsvdReg()
// and keep tmpReg hint value unchanged.
assert(isValidSimm20((imm + 0x800) >> 12));
emitIns_R_I(INS_lui, EA_PTRSIZE, codeGen->rsGetRsvdReg(), (imm + 0x800) >> 12);

emitIns_R_I(INS_lui, EA_PTRSIZE, codeGen->rsGetRsvdReg(), (imm + 0x800) >> 12);
emitIns_R_R_R(INS_add, EA_PTRSIZE, codeGen->rsGetRsvdReg(), codeGen->rsGetRsvdReg(), reg2);
// imm2 = imm2 & 0x7ff;
// imm = imm3 ? imm2 - imm3 : imm2;

imm = imm & 0xfff;
reg2 = codeGen->rsGetRsvdReg();
}

if (tmpReg != REG_NA)
{
emitIns_R_R_R(INS_add, attr, reg2, reg2, reg3);
imm = 0;
}

instrDesc* id = emitNewInstr(attr);

id->idReg1(reg1);
Expand Down

0 comments on commit fcae73f

Please sign in to comment.