From a400b3e7f79dc66bbd96289d9849482530accc61 Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Thu, 18 May 2023 19:20:32 +0900 Subject: [PATCH 1/7] [RISC-V][JIT] Fix branch --- src/coreclr/jit/emitriscv64.cpp | 30 ++++++++++++++++++------------ src/coreclr/jit/emitriscv64.h | 12 ++++++++++++ src/coreclr/jit/targetriscv64.h | 8 ++++---- 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 37405347dd47e8..451d87f1becd5a 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -667,6 +667,7 @@ void emitter::emitIns_R_R_I( { assert(isGeneralRegister(reg1)); assert(isGeneralRegister(reg2)); + assert(isValidSimm13(imm)); code |= reg1 << 15; code |= reg2 << 20; code |= ((imm >> 11) & 0x1) << 7; @@ -1621,10 +1622,10 @@ void emitter::emitJumpDistBind() #endif // DEBUG // NOTE: - // bit0 of isLinkingEnd_LA: indicating whether updating the instrDescJmp's size with the type INS_OPTS_J; - // bit1 of isLinkingEnd_LA: indicating not needed updating the size while emitTotalCodeSize <= (0x7fff << 2) or had + // bit0 of isLinkingEnd: indicating whether updating the instrDescJmp's size with the type INS_OPTS_J; + // bit1 of isLinkingEnd: indicating not needed updating the size while emitTotalCodeSize <= 0xfff or had // updated; - unsigned int isLinkingEnd_LA = emitTotalCodeSize <= (0x7fff << 2) ? 2 : 0; + unsigned int isLinkingEnd = emitTotalCodeSize <= 0xfff ? 2 : 0; UNATIVE_OFFSET ssz = 0; // relative small jump's delay-slot. // small jump max. neg distance @@ -1836,7 +1837,7 @@ void emitter::emitJumpDistBind() assert(jmpDist >= 0); // Forward jump assert(!(jmpDist & 0x3)); - if (isLinkingEnd_LA & 0x2) + if (isLinkingEnd & 0x2) { jmp->idAddr()->iiaSetJmpOffset(jmpDist); } @@ -1879,7 +1880,7 @@ void emitter::emitJumpDistBind() adjIG += (UNATIVE_OFFSET)extra; emitTotalCodeSize += (UNATIVE_OFFSET)extra; jmpIG->igFlags |= IGF_UPD_ISZ; - isLinkingEnd_LA |= 0x1; + isLinkingEnd |= 0x1; } continue; } @@ -1923,7 +1924,7 @@ void emitter::emitJumpDistBind() assert(jmpDist >= 0); // Backward jump assert(!(jmpDist & 0x3)); - if (isLinkingEnd_LA & 0x2) + if (isLinkingEnd & 0x2) { jmp->idAddr()->iiaSetJmpOffset(-jmpDist); // Backward jump is negative! } @@ -1954,7 +1955,7 @@ void emitter::emitJumpDistBind() } else { - assert(ins == INS_jal || ins == INS_jalr); + assert(ins == INS_jal || ins == INS_jalr || ins == INS_j); assert((jmpDist + emitCounts_INS_OPTS_J * 4) < 0x8000000); continue; } @@ -1966,17 +1967,17 @@ void emitter::emitJumpDistBind() adjIG += (UNATIVE_OFFSET)extra; emitTotalCodeSize += (UNATIVE_OFFSET)extra; jmpIG->igFlags |= IGF_UPD_ISZ; - isLinkingEnd_LA |= 0x1; + isLinkingEnd |= 0x1; } continue; } } // end for each jump - if ((isLinkingEnd_LA & 0x3) < 0x2) + if ((isLinkingEnd & 0x3) < 0x2) { // indicating the instrDescJmp's size of the type INS_OPTS_J had updated // after the first round and should iterate again to update. - isLinkingEnd_LA = 0x2; + isLinkingEnd = 0x2; // Adjust offsets of any remaining blocks. for (; lstIG;) @@ -2460,7 +2461,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) } else { - assert((-0x100000 <= imm) && (imm < 0x100000)); + assert(isValidSimm21(imm)); assert((emitInsCode(INS_bne) & 0xefff) == emitInsCode(INS_beq)); code = emitInsCode(ins) ^ 0x1000; @@ -2482,7 +2483,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) } else if ((INS_blt <= ins) && (ins <= INS_bgeu)) { - assert((-0x100000 <= imm) && (imm < 0x100000)); + assert(isValidSimm21(imm)); assert((emitInsCode(INS_bge) & 0xefff) == emitInsCode(INS_blt)); assert((emitInsCode(INS_bgeu) & 0xefff) == emitInsCode(INS_bltu)); @@ -2542,6 +2543,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) code = emitInsCode(ins); if (ins == INS_jal) { + assert(isValidSimm21(imm)); code |= ((imm >> 12) & 0xff) << 12; code |= ((imm >> 11) & 0x1) << 20; code |= ((imm >> 1) & 0x3ff) << 21; @@ -2550,6 +2552,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) } else if (ins == INS_j) { + assert(isValidSimm21(imm)); code |= ((imm >> 12) & 0xff) << 12; code |= ((imm >> 11) & 0x1) << 20; code |= ((imm >> 1) & 0x3ff) << 21; @@ -2557,10 +2560,12 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) } else if (ins == INS_jalr) { + assert(isValidSimm12(imm)); code |= ((code_t)(imm & 0xfff) << 20); } else if (ins == INS_bnez || ins == INS_beqz) { + assert(isValidSimm13(imm)); code |= (code_t)id->idReg1() << 15; code |= ((imm >> 11) & 0x1) << 7; code |= ((imm >> 1) & 0xf) << 8; @@ -2569,6 +2574,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) } else if ((INS_beq <= ins) && (ins <= INS_bgeu)) { + assert(isValidSimm13(imm)); code |= ((code_t)id->idReg1()) << 15; code |= ((code_t)id->idReg2()) << 20; code |= ((imm >> 11) & 0x1) << 7; diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index c39d534af2334a..f9eb23be2f8de8 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -81,6 +81,12 @@ bool IsRedundantLdStr( /************************************************************************/ public: +// Returns true if 'value' is a legal signed immediate 13 bit encoding. +static bool isValidSimm13(ssize_t value) +{ + return -(((int)1) << 12) <= value && value < (((int)1) << 12); +}; + // Returns true if 'value' is a legal signed immediate 12 bit encoding. static bool isValidSimm12(ssize_t value) { @@ -105,6 +111,12 @@ static bool isValidSimm20(ssize_t value) return -(((int)1) << 19) <= value && value < (((int)1) << 19); }; +// Returns true if 'value' is a legal signed immediate 21 bit encoding. +static bool isValidSimm21(ssize_t value) +{ + return -(((int)1) << 20) <= value && value < (((int)1) << 20); +}; + // Returns true if 'value' is a legal signed immediate 32 bit encoding. static bool isValidSimm32(ssize_t value) { diff --git a/src/coreclr/jit/targetriscv64.h b/src/coreclr/jit/targetriscv64.h index dd8da7a81c7a23..db991607091f98 100644 --- a/src/coreclr/jit/targetriscv64.h +++ b/src/coreclr/jit/targetriscv64.h @@ -295,11 +295,11 @@ extern const regNumber fltArgRegs [MAX_FLOAT_REG_ARG]; extern const regMaskTP fltArgMasks[MAX_FLOAT_REG_ARG]; - #define B_DIST_SMALL_MAX_NEG (-131072) - #define B_DIST_SMALL_MAX_POS (+131071) + #define B_DIST_SMALL_MAX_NEG (-4096) + #define B_DIST_SMALL_MAX_POS (+4095) - #define OFFSET_DIST_SMALL_MAX_NEG (-2048) - #define OFFSET_DIST_SMALL_MAX_POS (+2047) + #define OFFSET_DIST_SMALL_MAX_NEG (-1048) + #define OFFSET_DIST_SMALL_MAX_POS (+1047) #define STACK_PROBE_BOUNDARY_THRESHOLD_BYTES 0 From 5a0c6e82422f9d4aa655b3bae2b507e74abf1154 Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Mon, 22 May 2023 16:17:55 +0900 Subject: [PATCH 2/7] [RISC-V][JIT] Updated emitJumpDistBind --- src/coreclr/jit/emitriscv64.cpp | 277 +++++++++++++++++++++----------- src/coreclr/jit/targetriscv64.h | 3 - 2 files changed, 183 insertions(+), 97 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 451d87f1becd5a..96e2982cd0117a 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -501,7 +501,7 @@ void emitter::emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t break; case INS_jal: assert(isGeneralRegisterOrR0(reg)); - assert(imm >= -1048576 && imm < 1048576); + assert(isValidSimm21(imm)); code |= reg << 7; code |= ((imm >> 12) & 0xff) << 12; @@ -1627,13 +1627,13 @@ void emitter::emitJumpDistBind() // updated; unsigned int isLinkingEnd = emitTotalCodeSize <= 0xfff ? 2 : 0; - UNATIVE_OFFSET ssz = 0; // relative small jump's delay-slot. + UNATIVE_OFFSET ssz = 0; // relative small jump's delay-slot. // small jump max. neg distance NATIVE_OFFSET nsd = B_DIST_SMALL_MAX_NEG; // small jump max. pos distance - NATIVE_OFFSET psd = - B_DIST_SMALL_MAX_POS - - emitCounts_INS_OPTS_J * (3 << 2); // the max placeholder sizeof(INS_OPTS_JALR) - sizeof(INS_OPTS_J). + NATIVE_OFFSET maxPlaceholderSize = + emitCounts_INS_OPTS_J * (6 << 2); // the max placeholder sizeof(INS_OPTS_JALR) - sizeof(INS_OPTS_J) + NATIVE_OFFSET psd = B_DIST_SMALL_MAX_POS - maxPlaceholderSize; /*****************************************************************************/ /* If the default small encoding is not enough, we start again here. */ @@ -1846,30 +1846,37 @@ void emitter::emitJumpDistBind() instruction ins = jmp->idIns(); assert((INS_jal <= ins) && (ins <= INS_bgeu)); - if (ins > INS_jalr) // jal < beqz < bnez < jalr < beq/bne/blt/bltu/bge/bgeu + if (ins > INS_jalr || + (ins < INS_jalr && ins > INS_j)) // jal < beqz < bnez < jalr < beq/bne/blt/bltu/bge/bgeu { - if ((jmpDist + emitCounts_INS_OPTS_J * 4) < 0x8000000) + if (isValidSimm13(jmpDist + maxPlaceholderSize)) + { + continue; + } + else if (isValidSimm21(jmpDist + maxPlaceholderSize)) { extra = 4; } else { - assert((jmpDist + emitCounts_INS_OPTS_J * 4) < 0x8000000); - extra = 8; + extra = 4 * 6; } } - else if (ins > INS_j && ins < INS_jalr) // jal < beqz < bnez < jalr < beq/bne/blt/bltu/bge/bgeu + else if (ins == INS_jal || ins == INS_j) { - if (jmpDist + emitCounts_INS_OPTS_J * 4 < 0x200000) + if (isValidSimm21(jmpDist + maxPlaceholderSize)) + { continue; - - extra = 4; - assert((jmpDist + emitCounts_INS_OPTS_J * 4) < 0x8000000); + } + else + { + extra = 4 * 5; + } } else { - assert(ins == INS_j || ins == INS_jal || ins == INS_jalr); - assert((jmpDist + emitCounts_INS_OPTS_J * 4) < 0x8000000); + assert(ins == INS_jalr); + assert((jmpDist + maxPlaceholderSize) < 0x800); continue; } @@ -1933,30 +1940,37 @@ void emitter::emitJumpDistBind() instruction ins = jmp->idIns(); assert((INS_jal <= ins) && (ins <= INS_bgeu)); - if (ins > INS_jalr) // jal < beqz < bnez < jalr < beq/bne/blt/bltu/bge/bgeu + if (ins > INS_jalr || + (ins < INS_jalr && ins > INS_j)) // jal < beqz < bnez < jalr < beq/bne/blt/bltu/bge/bgeu { - if ((jmpDist + emitCounts_INS_OPTS_J * 4) < 0x8000000) + if (isValidSimm13(jmpDist + maxPlaceholderSize)) + { + continue; + } + else if (isValidSimm21(jmpDist + maxPlaceholderSize)) { extra = 4; } else { - assert((jmpDist + emitCounts_INS_OPTS_J * 4) < 0x8000000); - extra = 8; + extra = 4 * 6; } } - else if (ins < INS_jalr && ins > INS_j) // jal < beqz < bnez < jalr < beq/bne/blt/bltu/bge/bgeu + else if (ins == INS_jal || ins == INS_j) { - if (jmpDist + emitCounts_INS_OPTS_J * 4 < 0x200000) + if (isValidSimm21(jmpDist + maxPlaceholderSize)) + { continue; - - extra = 4; - assert((jmpDist + emitCounts_INS_OPTS_J * 4) < 0x8000000); + } + else + { + extra = 4 * 5; + } } else { - assert(ins == INS_jal || ins == INS_jalr || ins == INS_j); - assert((jmpDist + emitCounts_INS_OPTS_J * 4) < 0x8000000); + assert(ins == INS_jalr); + assert((jmpDist + maxPlaceholderSize) < 0x800); continue; } @@ -2431,77 +2445,152 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) assert((imm & 0x3) == 0); ins = jmp->idIns(); - assert(jmp->idCodeSize() > 4); // The original INS_OPTS_JIRL: not used by now!!! + assert(jmp->idCodeSize() > 4); // The original INS_OPTS_JALR: not used by now!!! switch (jmp->idCodeSize()) { case 8: { - regNumber reg2 = id->idReg2(); + assert((INS_blt <= ins && ins <= INS_bgeu) || (INS_beq == ins) || (INS_bne == ins) || + (INS_bnez == ins) || (INS_beqz == ins)); + assert(isValidSimm21(imm)); + assert((emitInsCode(INS_bne) & 0xefff) == emitInsCode(INS_beq)); + assert((emitInsCode(INS_bge) & 0xefff) == emitInsCode(INS_blt)); + assert((emitInsCode(INS_bgeu) & 0xefff) == emitInsCode(INS_bltu)); + + regNumber reg2 = REG_R0; + if (INS_beqz != ins && INS_bnez != ins) + reg2 = id->idReg2(); + code = emitInsCode(ins) ^ 0x1000; + code |= (code_t)reg1 << 15; /* rj */ + code |= (code_t)reg2 << 20; /* rd */ + code |= 0x8 << 7; + *(code_t*)dstRW = code; + dstRW += 4; + + code = emitInsCode(INS_jal); + code |= ((imm >> 12) & 0xff) << 12; + code |= ((imm >> 11) & 0x1) << 20; + code |= ((imm >> 1) & 0x3ff) << 21; + code |= ((imm >> 20) & 0x1) << 31; + + *(code_t*)dstRW = code; + dstRW += 4; + break; + } + case 24: + { + assert(ins == INS_j || ins == INS_jal); + imm = imm - 2 * 4; + regNumber tmpReg1 = REG_RA; + ssize_t high = (imm >> 32) & 0xffffffff; + code = emitInsCode(INS_lui); + code |= (code_t)tmpReg1 << 7; + code |= ((code_t)((high + 0x800) >> 12) & 0xfffff) << 12; + + *(code_t*)dstRW = code; + dstRW += 4; + + code = emitInsCode(INS_addi); + code |= (code_t)tmpReg1 << 7; + code |= (code_t)tmpReg1 << 15; + code |= (code_t)(high & 0xfff) << 20; + *(code_t*)dstRW = code; + dstRW += 4; + + code = emitInsCode(INS_slli); + code |= (code_t)tmpReg1 << 7; + code |= (code_t)tmpReg1 << 15; + code |= (code_t)32 << 20; + *(code_t*)dstRW = code; + dstRW += 4; + + regNumber tmpReg2 = codeGen->rsGetRsvdReg(); + ssize_t low = imm & 0xffffffff; + code = emitInsCode(INS_auipc); + code |= (code_t)tmpReg2 << 7; + code |= ((code_t)((low + 0x800) >> 12) & 0xfffff) << 12; + + *(code_t*)dstRW = code; + dstRW += 4; + + code = emitInsCode(INS_add); + code |= (code_t)tmpReg2 << 7; + code |= (code_t)tmpReg1 << 15; + code |= (code_t)tmpReg2 << 20; + *(code_t*)dstRW = code; + dstRW += 4; + + code = emitInsCode(INS_jalr); + code |= (code_t)tmpReg2 << 15; + code |= (code_t)(low & 0xfff) << 20; + *(code_t*)dstRW = code; + dstRW += 4; + break; + } + case 28: + { + assert((INS_blt <= ins && ins <= INS_bgeu) || (INS_beq == ins) || (INS_bne == ins) || + (INS_bnez == ins) || (INS_beqz == ins)); + assert((emitInsCode(INS_bne) & 0xefff) == emitInsCode(INS_beq)); + assert((emitInsCode(INS_bge) & 0xefff) == emitInsCode(INS_blt)); + assert((emitInsCode(INS_bgeu) & 0xefff) == emitInsCode(INS_bltu)); + + regNumber reg2 = REG_R0; + if (INS_beqz != ins && INS_bnez != ins) + reg2 = id->idReg2(); + code = emitInsCode(ins) ^ 0x1000; + code |= (code_t)reg1 << 15; /* rj */ + code |= (code_t)reg2 << 20; /* rd */ + code |= 28 << 7; + *(code_t*)dstRW = code; + dstRW += 4; + + imm = imm - 2 * 4; + regNumber tmpReg1 = REG_RA; + ssize_t high = (imm >> 32) & 0xffffffff; + code = emitInsCode(INS_lui); + code |= (code_t)tmpReg1 << 7; + code |= ((code_t)((high + 0x800) >> 12) & 0xfffff) << 12; + + *(code_t*)dstRW = code; + dstRW += 4; + + code = emitInsCode(INS_addi); + code |= (code_t)tmpReg1 << 7; + code |= (code_t)tmpReg1 << 15; + code |= (code_t)(high & 0xfff) << 20; + *(code_t*)dstRW = code; + dstRW += 4; + + code = emitInsCode(INS_slli); + code |= (code_t)tmpReg1 << 7; + code |= (code_t)tmpReg1 << 15; + code |= (code_t)32 << 20; + *(code_t*)dstRW = code; + dstRW += 4; + + regNumber tmpReg2 = codeGen->rsGetRsvdReg(); + ssize_t low = imm & 0xffffffff; + code = emitInsCode(INS_auipc); + code |= (code_t)tmpReg2 << 7; + code |= ((code_t)((low + 0x800) >> 12) & 0xfffff) << 12; + + *(code_t*)dstRW = code; + dstRW += 4; + + code = emitInsCode(INS_add); + code |= (code_t)tmpReg2 << 7; + code |= (code_t)tmpReg1 << 15; + code |= (code_t)tmpReg2 << 20; + *(code_t*)dstRW = code; + dstRW += 4; + + code = emitInsCode(INS_jalr); + code |= (code_t)tmpReg2 << 15; + code |= (code_t)(low & 0xfff) << 20; + *(code_t*)dstRW = code; + dstRW += 4; - if ((INS_beq == ins) || (INS_bne == ins)) - { - if ((-0x1000 <= imm) && (imm < 0x1000)) - { - code = emitInsCode(INS_xor); - code |= (code_t)codeGen->rsGetRsvdReg() << 7; - code |= (code_t)reg1 << 15; - code |= (code_t)reg2 << 20; - - *(code_t*)dstRW = code; - dstRW += 4; - - code = emitInsCode(ins); - code |= (code_t)codeGen->rsGetRsvdReg() << 15; - code |= ((imm >> 11) & 0x1) << 7; - code |= ((imm >> 1) & 0xf) << 8; - code |= ((imm >> 5) & 0x3f) << 25; - code |= ((imm >> 12) & 0x1) << 31; - *(code_t*)dstRW = code; - dstRW += 4; - } - else - { - assert(isValidSimm21(imm)); - assert((emitInsCode(INS_bne) & 0xefff) == emitInsCode(INS_beq)); - - code = emitInsCode(ins) ^ 0x1000; - code |= (code_t)reg1 << 15; /* rj */ - code |= (code_t)reg2 << 20; /* rd */ - code |= 0x8 << 7; - *(code_t*)dstRW = code; - dstRW += 4; - - code = emitInsCode(INS_jal); - code |= ((imm >> 12) & 0xff) << 12; - code |= ((imm >> 11) & 0x1) << 20; - code |= ((imm >> 1) & 0x3ff) << 21; - code |= ((imm >> 20) & 0x1) << 31; - - *(code_t*)dstRW = code; - dstRW += 4; - } - } - else if ((INS_blt <= ins) && (ins <= INS_bgeu)) - { - assert(isValidSimm21(imm)); - assert((emitInsCode(INS_bge) & 0xefff) == emitInsCode(INS_blt)); - assert((emitInsCode(INS_bgeu) & 0xefff) == emitInsCode(INS_bltu)); - - code = emitInsCode(ins) ^ 0x1000; - code |= (code_t)reg1 << 15; /* rj */ - code |= (code_t)reg2 << 20; /* rd */ - code |= 0x8 << 7; - *(code_t*)dstRW = code; - dstRW += 4; - - code = emitInsCode(INS_jal); - code |= ((imm >> 12) & 0xff) << 12; - code |= ((imm >> 11) & 0x1) << 20; - code |= ((imm >> 1) & 0x3ff) << 21; - code |= ((imm >> 20) & 0x1) << 31; - *(code_t*)dstRW = code; - dstRW += 4; - } break; } @@ -2516,7 +2605,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) case INS_OPTS_J_cond: { ssize_t imm = (ssize_t)id->idAddr()->iiaGetJmpOffset(); // get jmp's offset relative delay-slot. - assert((OFFSET_DIST_SMALL_MAX_NEG << 2) <= imm && imm <= (OFFSET_DIST_SMALL_MAX_POS << 2)); + assert(isValidSimm13(imm)); assert(!(imm & 1)); ins = id->idIns(); diff --git a/src/coreclr/jit/targetriscv64.h b/src/coreclr/jit/targetriscv64.h index db991607091f98..884b5c1c555c80 100644 --- a/src/coreclr/jit/targetriscv64.h +++ b/src/coreclr/jit/targetriscv64.h @@ -298,9 +298,6 @@ #define B_DIST_SMALL_MAX_NEG (-4096) #define B_DIST_SMALL_MAX_POS (+4095) - #define OFFSET_DIST_SMALL_MAX_NEG (-1048) - #define OFFSET_DIST_SMALL_MAX_POS (+1047) - #define STACK_PROBE_BOUNDARY_THRESHOLD_BYTES 0 // clang-format on From 92067280adecde42f6132043d9039e07c6eae5d3 Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Mon, 22 May 2023 17:02:22 +0900 Subject: [PATCH 3/7] jit-format --- src/coreclr/jit/emitriscv64.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 96e2982cd0117a..b75fe9f37460e5 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -1627,7 +1627,7 @@ void emitter::emitJumpDistBind() // updated; unsigned int isLinkingEnd = emitTotalCodeSize <= 0xfff ? 2 : 0; - UNATIVE_OFFSET ssz = 0; // relative small jump's delay-slot. + UNATIVE_OFFSET ssz = 0; // relative small jump's delay-slot. // small jump max. neg distance NATIVE_OFFSET nsd = B_DIST_SMALL_MAX_NEG; // small jump max. pos distance From 10dead9432c13c481756f60ad2dd02a07326d889 Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Mon, 22 May 2023 17:35:39 +0900 Subject: [PATCH 4/7] Update JALR offset value --- src/coreclr/jit/emitriscv64.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index b75fe9f37460e5..afa26edbc72270 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2482,7 +2482,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) assert(ins == INS_j || ins == INS_jal); imm = imm - 2 * 4; regNumber tmpReg1 = REG_RA; - ssize_t high = (imm >> 32) & 0xffffffff; + ssize_t high = ((imm + 0x80000000) >> 32) & 0xffffffff; code = emitInsCode(INS_lui); code |= (code_t)tmpReg1 << 7; code |= ((code_t)((high + 0x800) >> 12) & 0xfffff) << 12; @@ -2547,7 +2547,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) imm = imm - 2 * 4; regNumber tmpReg1 = REG_RA; - ssize_t high = (imm >> 32) & 0xffffffff; + ssize_t high = ((imm + 0x80000000) >> 32) & 0xffffffff; code = emitInsCode(INS_lui); code |= (code_t)tmpReg1 << 7; code |= ((code_t)((high + 0x800) >> 12) & 0xfffff) << 12; From 404a6642e80d75390933642cad32f880cc53b62e Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Wed, 24 May 2023 10:46:26 +0900 Subject: [PATCH 5/7] Updated by reviews --- src/coreclr/jit/emitriscv64.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index afa26edbc72270..db5dcd3307e87b 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -668,6 +668,7 @@ void emitter::emitIns_R_R_I( assert(isGeneralRegister(reg1)); assert(isGeneralRegister(reg2)); assert(isValidSimm13(imm)); + assert(!(imm & 3)); code |= reg1 << 15; code |= reg2 << 20; code |= ((imm >> 11) & 0x1) << 7; @@ -1855,10 +1856,12 @@ void emitter::emitJumpDistBind() } else if (isValidSimm21(jmpDist + maxPlaceholderSize)) { + // convert to opposite branch and jal extra = 4; } else { + // convert to opposite branch and jalr extra = 4 * 6; } } @@ -1870,6 +1873,7 @@ void emitter::emitJumpDistBind() } else { + // convert to jalr extra = 4 * 5; } } @@ -1949,10 +1953,12 @@ void emitter::emitJumpDistBind() } else if (isValidSimm21(jmpDist + maxPlaceholderSize)) { + // convert to opposite branch and jal extra = 4; } else { + // convert to opposite branch and jalr extra = 4 * 6; } } @@ -1964,6 +1970,7 @@ void emitter::emitJumpDistBind() } else { + // convert to jalr extra = 4 * 5; } } From bec52131e630c5d156c61eda6740421118aa8f3b Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Thu, 25 May 2023 10:30:56 +0900 Subject: [PATCH 6/7] Updated by reviews and fix --- src/coreclr/jit/emitriscv64.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index db5dcd3307e87b..0f38428330c2c9 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -1023,7 +1023,7 @@ void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount) assert(dst != nullptr); // // INS_OPTS_J: placeholders. 1-ins: if the dst outof-range will be replaced by INS_OPTS_JALR. - // bceqz/bcnez/beq/bne/blt/bltu/bge/bgeu/beqz/bnez/b/bl dst + // jal/j/jalr/bnez/beqz/beq/bne/blt/bge/bltu/bgeu dst assert(dst->bbFlags & BBF_HAS_LABEL); @@ -2487,6 +2487,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) case 24: { assert(ins == INS_j || ins == INS_jal); + // Make target address with offset, then jump (JALR) with the target address imm = imm - 2 * 4; regNumber tmpReg1 = REG_RA; ssize_t high = ((imm + 0x80000000) >> 32) & 0xffffffff; @@ -2528,6 +2529,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) dstRW += 4; code = emitInsCode(INS_jalr); + code |= (code_t)id->idReg1() << 7; code |= (code_t)tmpReg2 << 15; code |= (code_t)(low & 0xfff) << 20; *(code_t*)dstRW = code; @@ -2552,6 +2554,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) *(code_t*)dstRW = code; dstRW += 4; + // Make target address with offset, then jump (JALR) with the target address imm = imm - 2 * 4; regNumber tmpReg1 = REG_RA; ssize_t high = ((imm + 0x80000000) >> 32) & 0xffffffff; @@ -2630,7 +2633,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) } break; case INS_OPTS_J: - // bceqz/bcnez/beq/bne/blt/bltu/bge/bgeu/beqz/bnez/b/bl dstRW-relative. + // jal/j/jalr/bnez/beqz/beq/bne/blt/bge/bltu/bgeu dstRW-relative. { ssize_t imm = (ssize_t)id->idAddr()->iiaGetJmpOffset(); // get jmp's offset relative delay-slot. assert((imm & 3) == 0); @@ -2658,6 +2661,8 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) { assert(isValidSimm12(imm)); code |= ((code_t)(imm & 0xfff) << 20); + code |= ((code_t)id->idReg1()) << 7; + code |= ((code_t)id->idReg2()) << 15; } else if (ins == INS_bnez || ins == INS_beqz) { @@ -2680,7 +2685,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) } else { - NYI_RISCV64("unimplemented on RISCV64 yet"); + unreached(); } *(code_t*)dstRW = code; From c49d87c83479705129faea106c56516f74f56cd4 Mon Sep 17 00:00:00 2001 From: Dong-Heon Jung Date: Fri, 26 May 2023 14:40:24 +0900 Subject: [PATCH 7/7] [RISC-V][JIT] Fixed the dest reg of jalr - Pass `./JIT/jit64/opt/cse/HugeField2/HugeField2.sh` test --- src/coreclr/jit/emitriscv64.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 0f38428330c2c9..0a1ef556b41cf8 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -2529,7 +2529,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) dstRW += 4; code = emitInsCode(INS_jalr); - code |= (code_t)id->idReg1() << 7; + code |= (code_t)REG_RA << 7; // use REG_RA for returning code |= (code_t)tmpReg2 << 15; code |= (code_t)(low & 0xfff) << 20; *(code_t*)dstRW = code; @@ -2596,6 +2596,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp) dstRW += 4; code = emitInsCode(INS_jalr); + code |= (code_t)REG_RA << 7; // use REG_RA for returning code |= (code_t)tmpReg2 << 15; code |= (code_t)(low & 0xfff) << 20; *(code_t*)dstRW = code;